Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Throw errors with proper http code #89

Merged
merged 2 commits into from
Sep 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/build/src/containers/container.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Container as InversifyContainer } from 'inversify';
import { Container as CoreContainer } from '@vulcan-sql/core';
import { Container as CoreContainer, InternalError } from '@vulcan-sql/core';
import { IBuildOptions } from '@vulcan-sql/build/models';
import {
documentGeneratorModule,
Expand All @@ -15,7 +15,7 @@ export class Container {
public get<T>(type: symbol) {
const instance = this.inversifyContainer?.get<T>(type);
if (!instance)
throw new Error(`Cannot resolve ${type.toString()} in container`);
throw new InternalError(`Cannot resolve ${type.toString()} in container`);
return instance;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
VulcanExtensionId,
VulcanInternalExtension,
DocumentSpec,
ConfigurationError,
} from '@vulcan-sql/core';
import { isEmpty } from 'lodash';

Expand Down Expand Up @@ -104,7 +105,9 @@ export class OAS3SpecGenerator extends SpecGenerator<oas3.OpenAPIObject> {
case FieldInType.QUERY:
return 'query';
default:
throw new Error(`FieldInType ${fieldInType} is not supported`);
throw new ConfigurationError(
`FieldInType ${fieldInType} is not supported`
);
}
}

Expand Down Expand Up @@ -145,7 +148,9 @@ export class OAS3SpecGenerator extends SpecGenerator<oas3.OpenAPIObject> {
case FieldDataType.STRING:
return 'string';
default:
throw new Error(`FieldDataType ${fieldDataType} is not supported`);
throw new ConfigurationError(
`FieldDataType ${fieldDataType} is not supported`
);
}
}

Expand Down
11 changes: 8 additions & 3 deletions packages/build/src/lib/schema-parser/middleware/checkProfile.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { RawAPISchema, SchemaParserMiddleware } from './middleware';
import { APISchema, DataSource, TYPES as CORE_TYPES } from '@vulcan-sql/core';
import {
APISchema,
ConfigurationError,
DataSource,
TYPES as CORE_TYPES,
} from '@vulcan-sql/core';
import { inject, interfaces } from 'inversify';

export class CheckProfile extends SchemaParserMiddleware {
Expand All @@ -21,15 +26,15 @@ export class CheckProfile extends SchemaParserMiddleware {
await next();
const transformedSchemas = schemas as APISchema;
if (!transformedSchemas.profiles)
throw new Error(
throw new ConfigurationError(
`The profile of schema ${transformedSchemas.urlPath} is not defined`
);

for (const profile of transformedSchemas.profiles) {
try {
this.dataSourceFactory(profile);
} catch (e: any) {
throw new Error(
throw new ConfigurationError(
`The profile ${profile} of schema ${transformedSchemas.urlPath} is invalid: ${e?.message}`
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { RawAPISchema, SchemaParserMiddleware } from './middleware';
import { chain } from 'lodash';
import {
APISchema,
ConfigurationError,
IValidatorLoader,
TYPES as CORE_TYPES,
} from '@vulcan-sql/core';
Expand All @@ -26,7 +27,7 @@ export class CheckValidator extends SchemaParserMiddleware {

for (const validatorRequest of validators) {
if (!validatorRequest.name) {
throw new Error('Validator name is required');
throw new ConfigurationError('Validator name is required');
}

const validator = this.validatorLoader.getValidator(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { inject } from 'inversify';
import { RawAPISchema, SchemaParserMiddleware } from './middleware';
import {
APISchema,
ConfigurationError,
FieldDataType,
ResponseProperty,
TemplateEngine,
Expand All @@ -27,7 +28,7 @@ export class ResponseSampler extends SchemaParserMiddleware {
const schema = rawSchema as APISchema;
if (!schema.sample) return;
if (!schema.sample.profile) {
throw new Error(
throw new ConfigurationError(
`Schema ${schema.urlPath} misses the required property: sample.profile`
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
VulcanExtensionId,
VulcanInternalExtension,
TYPES as CORE_TYPES,
ConfigurationError,
} from '@vulcan-sql/core';
import { inject } from 'inversify';
import { TYPES } from '@vulcan-sql/build/containers';
Expand All @@ -36,7 +37,9 @@ export class FileSchemaReader extends SchemaReader {

public async *readSchema(): AsyncGenerator<SchemaData> {
if (!this.options?.folderPath)
throw new Error(`Config schema-parser.folderPath must be defined`);
throw new ConfigurationError(
`Config schema-parser.folderPath must be defined`
);
const files = await this.getSchemaFilePaths();

for (const file of files) {
Expand Down
8 changes: 6 additions & 2 deletions packages/build/src/lib/schema-parser/schemaParser.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { APISchema, AllTemplateMetadata } from '@vulcan-sql/core';
import {
APISchema,
AllTemplateMetadata,
InternalError,
} from '@vulcan-sql/core';
import {
SchemaData,
SchemaFormat,
Expand Down Expand Up @@ -61,7 +65,7 @@ export class SchemaParser {
...(yaml.load(schemaData.content) as object),
} as RawAPISchema;
default:
throw new Error(`Unsupported schema type: ${schemaData.type}`);
throw new InternalError(`Unsupported schema type: ${schemaData.type}`);
}
}
}
5 changes: 4 additions & 1 deletion packages/build/src/options/schemaParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
SchemaReaderType,
} from '@vulcan-sql/build/models';
import { IsOptional, IsString, validateSync } from 'class-validator';
import { ConfigurationError } from '@vulcan-sql/core';

@injectable()
export class SchemaParserOptions implements ISchemaParserOptions {
Expand All @@ -23,7 +24,9 @@ export class SchemaParserOptions implements ISchemaParserOptions {
Object.assign(this, options);
const errors = validateSync(this);
if (errors.length > 0) {
throw new Error('Invalid schema parser options: ' + errors.join(', '));
throw new ConfigurationError(
'Invalid schema parser options: ' + errors.join(', ')
);
}
}
}
2 changes: 1 addition & 1 deletion packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { program } from './cli';
} catch (e: any) {
// Ignore error with exit code = 0, e.g. commander.helpDisplayed error
if (e?.exitCode === 0) return;
logger.prettyError(e, true, false, false);
logger.prettyError(e, true, false, true);
process.exit(e?.exitCode ?? 1);
}
})();
4 changes: 3 additions & 1 deletion packages/core/src/containers/modules/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { Profile } from '../../models/profile';
import 'reflect-metadata';
import { ClassType } from '../../lib/utils/module';
import { ConfigurationError } from '@vulcan-sql/core/utils';

export const executorModule = (profiles: Map<string, Profile>) =>
new AsyncContainerModule(async (bind) => {
Expand All @@ -23,7 +24,8 @@ export const executorModule = (profiles: Map<string, Profile>) =>
TYPES.Factory_DataSource
).toFactory((context) => (profileName: string) => {
const profile = profiles.get(profileName);
if (!profile) throw new Error(`Profile ${profileName} not found`);
if (!profile)
throw new ConfigurationError(`Profile ${profileName} not found`);
return context.container.getNamed(
TYPES.Extension_DataSource,
profile.type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { PersistentStore } from '@vulcan-sql/core/models';
import { Serializer } from '@vulcan-sql/core/models';
import { inject, injectable } from 'inversify';
import { TYPES } from '@vulcan-sql/core/types';
import { InternalError } from '../utils';

@injectable()
export class VulcanArtifactBuilder implements ArtifactBuilder {
Expand Down Expand Up @@ -32,7 +33,7 @@ export class VulcanArtifactBuilder implements ArtifactBuilder {

public getArtifact<T = any>(key: string): T {
const target = this.artifact[key];
if (!target) throw new Error(`Artifact ${key} not found`);
if (!target) throw new InternalError(`Artifact ${key} not found`);
return target as T;
}

Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/lib/data-query/builder/dataQueryBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
JoinOnClause,
JoinOnClauseOperation,
} from './joinOnClause';
import { TemplateError } from '../../utils/errors';

export enum SelectCommandType {
SELECT = 'SELECT',
Expand Down Expand Up @@ -612,7 +613,7 @@ export class DataQueryBuilder implements IDataQueryBuilder {
value: string | number | boolean | IDataQueryBuilder
) {
if (!isOfComparisonOperator(operator))
throw new Error(`'There is no ${operator} operator.`);
throw new TemplateError(`'There is no ${operator} operator.`);

this.recordWhere({
command: null,
Expand Down Expand Up @@ -860,7 +861,7 @@ export class DataQueryBuilder implements IDataQueryBuilder {
) {
const normalized = typeof column === 'string' ? { name: column } : column;
if (!isOfComparisonOperator(operator))
throw new Error(`'There is no ${operator} operator.`);
throw new TemplateError(`'There is no ${operator} operator.`);

this.recordHaving({
command: null,
Expand Down
7 changes: 5 additions & 2 deletions packages/core/src/lib/data-query/builder/joinOnClause.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TemplateError } from '../../utils/errors';
import {
ComparisonPredicate,
ComparisonOperator,
Expand Down Expand Up @@ -68,7 +69,7 @@ export class JoinOnClause implements IJoinOnClause {

public on(leftColumn: string, operator: string, rightColumn: string) {
if (!isOfComparisonOperator(operator))
throw new Error(`'There is no ${operator} operator.`);
throw new TemplateError(`'There is no ${operator} operator.`);

this.recordOn({
command: null,
Expand All @@ -79,7 +80,9 @@ export class JoinOnClause implements IJoinOnClause {

public onBetween(column: string, min: number, max: number) {
if (min > max)
throw new Error(`min value ${min} not smaller than max value ${max}.`);
throw new TemplateError(
`min value ${min} not smaller than max value ${max}.`
);

this.recordOn({
command: ComparisonPredicate.BETWEEN,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import * as path from 'path';
import * as fs from 'fs';
import * as jsYAML from 'js-yaml';
import { ConfigurationError } from '@vulcan-sql/core/utils';

export interface LocalFileProfileReaderOptions {
path: string;
Expand All @@ -18,7 +19,9 @@ export interface LocalFileProfileReaderOptions {
export class LocalFileProfileReader extends ProfileReader {
public async read(options: LocalFileProfileReaderOptions) {
if (!options.path)
throw new Error('LocalFile profile reader needs options.path property');
throw new ConfigurationError(
'LocalFile profile reader needs options.path property'
);

const profilePath = path.resolve(process.cwd(), options.path);
if (!fs.existsSync(profilePath)) return [];
Expand All @@ -30,7 +33,7 @@ export class LocalFileProfileReader extends ProfileReader {
// validate profiles
for (const profile of profiles) {
if (!profile.name || !profile.type)
throw new Error(
throw new ConfigurationError(
`Invalid profile in ${profilePath}. Profile name and type are required.`
);
}
Expand Down
12 changes: 6 additions & 6 deletions packages/core/src/lib/extension-loader/extensionLoader.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ExtensionBase, ICoreOptions } from '@vulcan-sql/core/models';
import { interfaces } from 'inversify';
import { ClassType, defaultImport } from '../utils';
import { ClassType, defaultImport, InternalError } from '../utils';
import {
EXTENSION_ENFORCED_ID_METADATA_KEY,
EXTENSION_IDENTIFIER_METADATA_KEY,
Expand Down Expand Up @@ -30,7 +30,7 @@ export class ExtensionLoader {
/** Load external extensions (should be called by core package) */
public async loadExternalExtensionModules() {
if (this.bound)
throw new Error(
throw new InternalError(
`We must load all extensions before call bindExtension function`
);

Expand Down Expand Up @@ -61,7 +61,7 @@ export class ExtensionLoader {

public loadInternalExtensionModule(moduleEntry: ExtensionModuleEntry) {
if (this.bound)
throw new Error(
throw new InternalError(
`We must load all extensions before call bindExtension function`
);

Expand All @@ -70,7 +70,7 @@ export class ExtensionLoader {
for (const extension of extensions) {
const name = Reflect.getMetadata(EXTENSION_NAME_METADATA_KEY, extension);
if (name === undefined)
throw new Error(
throw new InternalError(
`Internal extension must have @VulcanInternalExtension decorator`
);
this.loadExtension(name, extension);
Expand Down Expand Up @@ -113,7 +113,7 @@ export class ExtensionLoader {
extension
);
if (enforcedId && !extensionId)
throw new Error(
throw new InternalError(
`Extension ${extension.name} needed an extension id but was not found, please use the decorator @VulcanExtensionId to set the id.`
);

Expand All @@ -128,7 +128,7 @@ export class ExtensionLoader {
extension
);
if (!extensionType)
throw new Error(
throw new InternalError(
`Extension must have @VulcanExtension decorator, have you use extend the correct super class?`
);
if (!this.extensionRegistry.has(extensionType))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as nunjucks from 'nunjucks';
import { chain } from 'lodash';
import { METADATA_NAME } from './constants';
import { TagBuilder, VulcanInternalExtension } from '@vulcan-sql/core/models';
import { TemplateError } from '../../../utils/errors';

interface ErrorCode {
code: string;
Expand Down Expand Up @@ -39,7 +40,9 @@ export class ErrorTagBuilder extends TagBuilder {

const errorCodeNode = node.args.children[0];
if (!(errorCodeNode instanceof nunjucks.nodes.Literal))
throw new Error(`Expected literal, got ${errorCodeNode.typename}`);
throw new TemplateError(
`Expected literal, got ${errorCodeNode.typename}`
);

this.errorCodes.push({
code: errorCodeNode.value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
TagRunnerOptions,
VulcanInternalExtension,
} from '@vulcan-sql/core/models';
import { UserError } from '../../../utils/errors';

@VulcanInternalExtension()
export class ErrorTagRunner extends TagRunner {
Expand All @@ -12,6 +13,8 @@ export class ErrorTagRunner extends TagRunner {
const message = args[0];
const lineno = args[1];
const colno = args[2];
throw new Error(`${message} at ${lineno}:${colno}`);
throw new UserError(String(message), {
description: `Error throw from template at ${lineno}:${colno}.`,
});
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { RequestParameter } from '@vulcan-sql/core/models';
import { InternalError } from '../../../utils/errors';

type PrepareParameterFuncWithoutProfile = {
(param: Omit<RequestParameter, 'profileName'>): Promise<string>;
Expand All @@ -20,7 +21,7 @@ export class Parameterizer {

public async generateIdentifier(value: any): Promise<string> {
if (this.sealed)
throw new Error(
throw new InternalError(
`This parameterizer has been sealed, we might use the parameterizer from a wrong request scope.`
);
if (this.valueToIdMapping.has(value))
Expand Down
Loading