node-server-engine 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.commitlintrc.js +10 -10
- package/.nycrc +1 -3
- package/.releaserc.js +2 -1
- package/README.md +206 -146
- package/dist/const/metrics.js.map +1 -1
- package/dist/db/models/index.js.map +1 -1
- package/dist/entities/AWSS3/AWSS3.js +12 -12
- package/dist/entities/AWSS3/AWSS3.js.map +1 -1
- package/dist/entities/ElasticSearch/ElasticSearch.js.map +1 -1
- package/dist/entities/Endpoint/Endpoint.types.js.map +1 -1
- package/dist/entities/GoogleCloudStorage/GoogleCloudStorage.js +11 -11
- package/dist/entities/GoogleCloudStorage/GoogleCloudStorage.js.map +1 -1
- package/dist/entities/KeySet/KeySet.js.map +1 -1
- package/dist/entities/PubSub/PubSub.js.map +1 -1
- package/dist/entities/PushNotification/PushNotification.js.map +1 -1
- package/dist/entities/Redis/Redis.js +3 -3
- package/dist/entities/Redis/Redis.js.map +1 -1
- package/dist/entities/SecretManager/SecretManager.js +3 -3
- package/dist/entities/SecretManager/SecretManager.js.map +1 -1
- package/dist/entities/Sequelize/Sequelize.config.js +11 -7
- package/dist/entities/Sequelize/Sequelize.config.js.map +1 -1
- package/dist/entities/Sequelize/Sequelize.js.map +1 -1
- package/dist/entities/Server/Server.js.map +1 -1
- package/dist/entities/Server/Server.types.js.map +1 -1
- package/dist/entities/SocketClient/SocketClient.d.ts +12 -0
- package/dist/entities/SocketClient/SocketClient.js +34 -3
- package/dist/entities/SocketClient/SocketClient.js.map +1 -1
- package/dist/entities/SocketClient/SocketClient.types.d.ts +6 -0
- package/dist/entities/SocketClient/SocketClient.types.js.map +1 -1
- package/dist/entities/index.js.map +1 -1
- package/dist/middleware/checkPermission/checkPermission.js.map +1 -1
- package/dist/middleware/checkPermission/index.js.map +1 -1
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/multiPartFileUploader/multiPartFileUploader.js.map +1 -1
- package/dist/middleware/requestMetrics/requestMetrics.js.map +1 -1
- package/dist/middleware/swaggerDocs/swaggerDocs.js.map +1 -1
- package/dist/middleware/verificationToken/verificationToken.js.map +1 -1
- package/dist/utils/createSortedObject/createSortedObject.js.map +1 -1
- package/dist/utils/dbMigration/dbMigration.js.map +1 -1
- package/dist/utils/dbMigration/migrateMetadataTable/migrateMetadataTable.js.map +1 -1
- package/dist/utils/jwt/jwt.js.map +1 -1
- package/dist/utils/jwt/jwt.types.js.map +1 -1
- package/dist/utils/report/output.js.map +1 -1
- package/dist/utils/report/report.js.map +1 -1
- package/dist/utils/semverCompare/semverCompare.js.map +1 -1
- package/dist/utils/verificationToken/verificationToken.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.js","names":["_output","require","_const","_EngineError","_WebError","reportInfo","data","output","severity","LogSeverity","INFO","message","reportError","error","request","logEntry","Error","stack_trace","stack","ERROR","CRITICAL","EngineError","errorType","constructor","name","WebError","statusCode","undefined","errorCode","context","user","id","hosts","join","httpRequest","url","originalUrl","method","referrer","header","userAgent","remoteIp","ip","responseStatusCode","NAMESPACE_SELECTORS","exports","initNamespaceSelector","process","env","DEBUG","split","map","namespace","RegExp","replace","resetNamespaceSelector","debugNamespace","reportDebug","isEngineReport","startsWith","match","some","selector","test","spaces","prefix","length","setNameSpace","globalNamespace","clearNamespace"],"sources":["../../../src/utils/report/report.ts"],"sourcesContent":["import { Request } from 'express';\nimport { output } from './output';\nimport { LogEntry, FullLogEntry } from './output.types';\nimport { DebugLogEntry, InfoLogEntry } from './report.types';\nimport { LogSeverity } from 'const';\nimport { EngineError } from 'entities/EngineError';\nimport { WebError } from 'entities/WebError';\nimport {} from 'middleware/authHmac/authHmac.types';\nimport {} from 'middleware/authJwt/authJwt.types';\nimport {} from 'middleware/authTls/authTls.types';\n\n/** Default generic logger */\nexport function reportInfo(data: InfoLogEntry | string): FullLogEntry {\n return output({\n severity: LogSeverity.INFO,\n ...(typeof data === 'string' ? { message: data } : data)\n });\n}\n\n/** Error specific logger */\nexport function reportError(\n error: unknown | Error | EngineError | WebError,\n request?: Request\n): FullLogEntry {\n let logEntry: LogEntry =\n error instanceof Error\n ? {\n message: error.message,\n stack_trace: error.stack,\n severity: LogSeverity.ERROR\n }\n : {\n message: 'An unknown error occurred',\n data: error,\n severity: LogSeverity.CRITICAL\n };\n\n if (error instanceof EngineError) {\n logEntry = {\n ...logEntry,\n severity: error.severity,\n errorType: error.constructor.name,\n data: error.data,\n '@type':\n !(error instanceof WebError) || error.statusCode >= 500\n ? 'type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent'\n : undefined\n };\n }\n\n if (error instanceof WebError) {\n logEntry = {\n ...logEntry,\n errorCode: error.errorCode,\n statusCode: error.statusCode\n };\n }\n\n if (request) {\n logEntry = {\n ...logEntry,\n context: {\n user
|
|
1
|
+
{"version":3,"file":"report.js","names":["_output","require","_const","_EngineError","_WebError","reportInfo","data","output","severity","LogSeverity","INFO","message","reportError","error","request","logEntry","Error","stack_trace","stack","ERROR","CRITICAL","EngineError","errorType","constructor","name","WebError","statusCode","undefined","errorCode","context","user","id","hosts","join","httpRequest","url","originalUrl","method","referrer","header","userAgent","remoteIp","ip","responseStatusCode","NAMESPACE_SELECTORS","exports","initNamespaceSelector","process","env","DEBUG","split","map","namespace","RegExp","replace","resetNamespaceSelector","debugNamespace","reportDebug","isEngineReport","startsWith","match","some","selector","test","spaces","prefix","length","setNameSpace","globalNamespace","clearNamespace"],"sources":["../../../src/utils/report/report.ts"],"sourcesContent":["import { Request } from 'express';\nimport { output } from './output';\nimport { LogEntry, FullLogEntry } from './output.types';\nimport { DebugLogEntry, InfoLogEntry } from './report.types';\nimport { LogSeverity } from 'const';\nimport { EngineError } from 'entities/EngineError';\nimport { WebError } from 'entities/WebError';\nimport {} from 'middleware/authHmac/authHmac.types';\nimport {} from 'middleware/authJwt/authJwt.types';\nimport {} from 'middleware/authTls/authTls.types';\n\n/** Default generic logger */\nexport function reportInfo(data: InfoLogEntry | string): FullLogEntry {\n return output({\n severity: LogSeverity.INFO,\n ...(typeof data === 'string' ? { message: data } : data)\n });\n}\n\n/** Error specific logger */\nexport function reportError(\n error: unknown | Error | EngineError | WebError,\n request?: Request\n): FullLogEntry {\n let logEntry: LogEntry =\n error instanceof Error\n ? {\n message: error.message,\n stack_trace: error.stack,\n severity: LogSeverity.ERROR\n }\n : {\n message: 'An unknown error occurred',\n data: error,\n severity: LogSeverity.CRITICAL\n };\n\n if (error instanceof EngineError) {\n logEntry = {\n ...logEntry,\n severity: error.severity,\n errorType: error.constructor.name,\n data: error.data,\n '@type':\n !(error instanceof WebError) || error.statusCode >= 500\n ? 'type.googleapis.com/google.devtools.clouderrorreporting.v1beta1.ReportedErrorEvent'\n : undefined\n };\n }\n\n if (error instanceof WebError) {\n logEntry = {\n ...logEntry,\n errorCode: error.errorCode,\n statusCode: error.statusCode\n };\n }\n\n if (request) {\n logEntry = {\n ...logEntry,\n context: {\n user: request.user?.id ?? request.hosts?.join(','),\n httpRequest: {\n url: request.originalUrl,\n method: request.method,\n referrer: request.header('Referer'),\n userAgent: request.header('User-Agent'),\n remoteIp: request.ip,\n responseStatusCode:\n error instanceof WebError ? error.statusCode : undefined\n }\n }\n };\n }\n\n return output(logEntry);\n}\n\nexport let NAMESPACE_SELECTORS: Array<RegExp> | undefined;\n\n/**\n * Generate the namespace selectors based on the DEBUG environment variable\n */\nfunction initNamespaceSelector(): void {\n if (process.env.DEBUG) {\n NAMESPACE_SELECTORS = process.env.DEBUG.split(',').map(\n (namespace) => new RegExp(`^${namespace.replace(/\\*/g, '.*?')}$`)\n );\n }\n}\n\n/**\n * Reset the namespace selectors\n */\nexport function resetNamespaceSelector(): void {\n NAMESPACE_SELECTORS = undefined;\n}\n\nlet debugNamespace: string | undefined;\n\n/**\n * Log a message for debugging purposes, based on a namespace specified in an environment variable\n * @param data - Debug log entry data\n * @returns The full log entry if namespace matches, undefined otherwise\n */\nexport function reportDebug(data: DebugLogEntry): FullLogEntry | undefined {\n if (!NAMESPACE_SELECTORS) {\n initNamespaceSelector();\n }\n\n let { namespace } = data;\n const isEngineReport = namespace?.startsWith('engine') ?? false;\n\n if (debugNamespace && !isEngineReport && namespace) {\n namespace = `${debugNamespace}:${namespace}`;\n }\n\n const match =\n namespace &&\n NAMESPACE_SELECTORS &&\n NAMESPACE_SELECTORS.some((selector) => selector.test(namespace));\n\n if (!match) return undefined;\n\n // Generate a prefix with the rightmost part of the namespace\n const spaces = namespace.split(':');\n const prefix = spaces[spaces.length - 1];\n\n return output({\n severity: LogSeverity.DEBUG,\n ...data,\n message: `[${prefix}] ${data.message}`\n });\n}\n\n/**\n * Specify a global debugging namespace\n * @param globalNamespace - The namespace to set globally\n */\nreportDebug.setNameSpace = function (globalNamespace: string): void {\n debugNamespace = globalNamespace;\n};\n\n/**\n * Remove any defined global namespace\n */\nreportDebug.clearNamespace = function (): void {\n debugNamespace = undefined;\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"semverCompare.js","names":["_validator","_interopRequireDefault","require","_EngineError","SEMVER_REGEX","semverCompare","v1","v2","match1","match2","map","v","match","EngineError","message","data","major1","minor1","patch1","preType1","preVersion1","major2","minor2","patch2","preType2","preVersion2","group","item","validator","isInt","parseInt"],"sources":["../../../src/utils/semverCompare/semverCompare.ts"],"sourcesContent":["import validator from 'validator';\nimport { EngineError } from 'entities/EngineError';\n\n// Regex to validate our SemVer style and capture the different parts\nconst SEMVER_REGEX =\n /^v?(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-(?:(alpha|beta|rc)(?:\\.(0|[1-9]\\d*))))?$/;\n\n/**\n * Comparison function for our SemVer strings, includes support for pre-releases\n * @param v1 - First version string to compare\n * @param v2 - Second version string to compare\n * @returns -1 if v1 < v2, 0 if v1 = v2, +1 if v1 > v2\n */\nexport function semverCompare(v1: string, v2: string): 1 | -1 | 0 {\n const [match1, match2] = [v1, v2].map((v) => v.match(SEMVER_REGEX));\n
|
|
1
|
+
{"version":3,"file":"semverCompare.js","names":["_validator","_interopRequireDefault","require","_EngineError","SEMVER_REGEX","semverCompare","v1","v2","match1","match2","map","v","match","EngineError","message","data","major1","minor1","patch1","preType1","preVersion1","major2","minor2","patch2","preType2","preVersion2","group","item","validator","isInt","parseInt"],"sources":["../../../src/utils/semverCompare/semverCompare.ts"],"sourcesContent":["import validator from 'validator';\nimport { EngineError } from 'entities/EngineError';\n\n// Regex to validate our SemVer style and capture the different parts\nconst SEMVER_REGEX =\n /^v?(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-(?:(alpha|beta|rc)(?:\\.(0|[1-9]\\d*))))?$/;\n\n/**\n * Comparison function for our SemVer strings, includes support for pre-releases\n * @param v1 - First version string to compare\n * @param v2 - Second version string to compare\n * @returns -1 if v1 < v2, 0 if v1 = v2, +1 if v1 > v2\n */\nexport function semverCompare(v1: string, v2: string): 1 | -1 | 0 {\n const [match1, match2] = [v1, v2].map((v) => v.match(SEMVER_REGEX));\n\n if (!match1 || !match2) {\n throw new EngineError({\n message: 'Provided invalid SemVer string, cannot compare',\n data: { v1, v2 }\n });\n }\n\n const [\n [, major1, minor1, patch1, preType1, preVersion1],\n [, major2, minor2, patch2, preType2, preVersion2]\n ] = [match1, match2].map((group) =>\n // Parse numeric values\n group.map((item) =>\n item && validator.isInt(item) ? parseInt(item, 10) : item\n )\n );\n\n // Compare majors first\n if (major1 < major2) return -1;\n if (major1 > major2) return 1;\n\n // Compare minors second\n if (minor1 < minor2) return -1;\n if (minor1 > minor2) return 1;\n\n // Compare patch third\n if (patch1 < patch2) return -1;\n if (patch1 > patch2) return 1;\n\n // Compare pre-release type\n // Release > pre-release\n if (!preType1 && !preType2) return 0;\n if (preType1 && !preType2) return -1;\n if (!preType1 && preType2) return 1;\n\n // RC > Beta > Alpha\n if (preType1 !== 'rc' && preType2 === 'rc') return -1;\n if (preType1 === 'rc' && preType2 !== 'rc') return 1;\n if (preType1 !== 'beta' && preType2 === 'beta') return -1;\n if (preType1 === 'beta' && preType2 !== 'beta') return 1;\n\n // Finally compare the pre-release versions\n if (preVersion1 < preVersion2) return -1;\n if (preVersion1 > preVersion2) return 1;\n\n return 0;\n}\n"],"mappings":";;;;;;;AAAA,IAAAA,UAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AAEA;AACA,MAAME,YAAY,GAChB,yFAAyF;;AAE3F;AACA;AACA;AACA;AACA;AACA;AACO,SAASC,aAAaA,CAACC,EAAU,EAAEC,EAAU,EAAc;EAChE,MAAM,CAACC,MAAM,EAAEC,MAAM,CAAC,GAAG,CAACH,EAAE,EAAEC,EAAE,CAAC,CAACG,GAAG,CAAEC,CAAC,IAAKA,CAAC,CAACC,KAAK,CAACR,YAAY,CAAC,CAAC;EAEnE,IAAI,CAACI,MAAM,IAAI,CAACC,MAAM,EAAE;IACtB,MAAM,IAAII,wBAAW,CAAC;MACpBC,OAAO,EAAE,gDAAgD;MACzDC,IAAI,EAAE;QAAET,EAAE;QAAEC;MAAG;IACjB,CAAC,CAAC;EACJ;EAEA,MAAM,CACJ,GAAGS,MAAM,EAAEC,MAAM,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,WAAW,CAAC,EACjD,GAAGC,MAAM,EAAEC,MAAM,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,WAAW,CAAC,CAClD,GAAG,CAACjB,MAAM,EAAEC,MAAM,CAAC,CAACC,GAAG,CAAEgB,KAAK;EAC7B;EACAA,KAAK,CAAChB,GAAG,CAAEiB,IAAI,IACbA,IAAI,IAAIC,kBAAS,CAACC,KAAK,CAACF,IAAI,CAAC,GAAGG,QAAQ,CAACH,IAAI,EAAE,EAAE,CAAC,GAAGA,IACvD,CACF,CAAC;;EAED;EACA,IAAIX,MAAM,GAAGK,MAAM,EAAE,OAAO,CAAC,CAAC;EAC9B,IAAIL,MAAM,GAAGK,MAAM,EAAE,OAAO,CAAC;;EAE7B;EACA,IAAIJ,MAAM,GAAGK,MAAM,EAAE,OAAO,CAAC,CAAC;EAC9B,IAAIL,MAAM,GAAGK,MAAM,EAAE,OAAO,CAAC;;EAE7B;EACA,IAAIJ,MAAM,GAAGK,MAAM,EAAE,OAAO,CAAC,CAAC;EAC9B,IAAIL,MAAM,GAAGK,MAAM,EAAE,OAAO,CAAC;;EAE7B;EACA;EACA,IAAI,CAACJ,QAAQ,IAAI,CAACK,QAAQ,EAAE,OAAO,CAAC;EACpC,IAAIL,QAAQ,IAAI,CAACK,QAAQ,EAAE,OAAO,CAAC,CAAC;EACpC,IAAI,CAACL,QAAQ,IAAIK,QAAQ,EAAE,OAAO,CAAC;;EAEnC;EACA,IAAIL,QAAQ,KAAK,IAAI,IAAIK,QAAQ,KAAK,IAAI,EAAE,OAAO,CAAC,CAAC;EACrD,IAAIL,QAAQ,KAAK,IAAI,IAAIK,QAAQ,KAAK,IAAI,EAAE,OAAO,CAAC;EACpD,IAAIL,QAAQ,KAAK,MAAM,IAAIK,QAAQ,KAAK,MAAM,EAAE,OAAO,CAAC,CAAC;EACzD,IAAIL,QAAQ,KAAK,MAAM,IAAIK,QAAQ,KAAK,MAAM,EAAE,OAAO,CAAC;;EAExD;EACA,IAAIJ,WAAW,GAAGK,WAAW,EAAE,OAAO,CAAC,CAAC;EACxC,IAAIL,WAAW,GAAGK,WAAW,EAAE,OAAO,CAAC;EAEvC,OAAO,CAAC;AACV","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verificationToken.js","names":["_crypto","require","_jsonwebtoken","_EngineError","_WebError","_checkEnvironment","_envAssert","DEFAULT_OTP_LENGTH","DEFAULT_EXPIRES_IN_SECONDS","DEFAULT_ISSUER","normalizeAction","action","EngineError","message","data","trim","toUpperCase","resolveOtpLength","length","undefined","Number","isInteger","resolveExpiresInSeconds","expiresInSeconds","getTokenSecret","secret","process","env","VERIFICATION_TOKEN_SECRET","assertEnvironment","envAssert","isString","getOtpSecret","VERIFICATION_TOKEN_OTP_SECRET","hashOtp","otp","createHmac","update","digest","safeEqual","a","b","bufferA","Buffer","from","bufferB","timingSafeEqual","generateOtp","index","randomInt","toString","buildIssuer","issuer","VERIFICATION_TOKEN_ISSUER","buildSignOptions","options","signOptions","algorithm","expiresIn","audience","VERIFICATION_TOKEN_AUDIENCE","normalizeAudience","Array","isArray","slice","buildVerifyOptions","verifyOptions","algorithms","normalizedAudience","createVerificationToken","otpLength","tokenSecret","otpSecret","payload","act","jti","randomUUID","sub","subject","token","sign","expiresAt","Date","now","verificationToken","exports","verifyVerificationToken","bypassSubject","VERIFICATION_BYPASS_SUBJECT","bypassOtp","VERIFICATION_BYPASS_OTP","iat","Math","floor","exp","iss","verify","error","WebError","errorCode","statusCode","Error","expected","actual","expectedHash"],"sources":["../../../src/utils/verificationToken/verificationToken.ts"],"sourcesContent":["import { randomInt, randomUUID, createHmac, timingSafeEqual } from 'crypto';\nimport { sign, verify, SignOptions, VerifyOptions } from 'jsonwebtoken';\nimport { EngineError } from 'entities/EngineError';\nimport { WebError } from 'entities/WebError';\nimport { assertEnvironment } from 'utils/checkEnvironment';\nimport { envAssert } from 'utils/envAssert';\nimport {\n VerificationTokenPayload,\n VerificationTokenOptions,\n VerificationTokenResult,\n VerifyVerificationTokenOptions\n} from './verificationToken.types';\n\nconst DEFAULT_OTP_LENGTH = 6;\nconst DEFAULT_EXPIRES_IN_SECONDS = 5 * 60;\nconst DEFAULT_ISSUER = 'node-server-engine';\n\nfunction normalizeAction(action: string): string {\n if (!action || typeof action !== 'string') {\n throw new EngineError({\n message: 'Verification token action must be a non-empty string',\n data: { action }\n });\n }\n return action.trim().toUpperCase();\n}\n\nfunction resolveOtpLength(length?: number): number {\n if (length === undefined) return DEFAULT_OTP_LENGTH;\n if (!Number.isInteger(length) || length < 4 || length > 10) {\n throw new EngineError({\n message: 'OTP length must be an integer between 4 and 10',\n data: { length }\n });\n }\n return length;\n}\n\nfunction resolveExpiresInSeconds(expiresInSeconds?: number): number {\n if (expiresInSeconds === undefined) return DEFAULT_EXPIRES_IN_SECONDS;\n if (!Number.isInteger(expiresInSeconds) || expiresInSeconds < 30) {\n throw new EngineError({\n message: 'Verification token expiration must be at least 30 seconds',\n data: { expiresInSeconds }\n });\n }\n return expiresInSeconds;\n}\n\nfunction getTokenSecret(): string {\n const secret = process.env.VERIFICATION_TOKEN_SECRET;\n if (!secret) {\n assertEnvironment({ VERIFICATION_TOKEN_SECRET: envAssert.isString() });\n }\n return secret as string;\n}\n\nfunction getOtpSecret(): string {\n return process.env.VERIFICATION_TOKEN_OTP_SECRET ?? getTokenSecret();\n}\n\nfunction hashOtp(otp: string, secret: string): string {\n return createHmac('sha256', secret).update(otp).digest('hex');\n}\n\n/** Constant time string comparison */\nfunction safeEqual(a: string, b: string): boolean {\n const bufferA = Buffer.from(a);\n const bufferB = Buffer.from(b);\n return bufferA.length === bufferB.length && timingSafeEqual(bufferA, bufferB);\n}\n\nfunction generateOtp(length: number): string {\n let otp = '';\n for (let index = 0; index < length; index += 1) {\n otp += randomInt(0, 10).toString();\n }\n return otp;\n}\n\nfunction buildIssuer(issuer?: string): string {\n return issuer ?? process.env.VERIFICATION_TOKEN_ISSUER ?? DEFAULT_ISSUER;\n}\n\nfunction buildSignOptions(options: VerificationTokenOptions): SignOptions {\n const signOptions: SignOptions = {\n algorithm: 'HS256',\n expiresIn: resolveExpiresInSeconds(options.expiresInSeconds),\n issuer: buildIssuer(options.issuer)\n };\n if (options.audience) {\n signOptions.audience = options.audience;\n } else if (process.env.VERIFICATION_TOKEN_AUDIENCE) {\n signOptions.audience = process.env.VERIFICATION_TOKEN_AUDIENCE;\n }\n return signOptions;\n}\n\nfunction normalizeAudience(\n audience?: string | string[]\n): VerifyOptions['audience'] | undefined {\n if (!audience) return undefined;\n if (Array.isArray(audience)) {\n if (audience.length === 0) return undefined;\n return [audience[0], ...audience.slice(1)];\n }\n return audience;\n}\n\nfunction buildVerifyOptions(options: VerifyVerificationTokenOptions): VerifyOptions {\n const verifyOptions: VerifyOptions = {\n algorithms: ['HS256'],\n issuer: buildIssuer(options.issuer)\n };\n const normalizedAudience = normalizeAudience(\n options.audience ?? process.env.VERIFICATION_TOKEN_AUDIENCE\n );\n if (normalizedAudience) verifyOptions.audience = normalizedAudience;\n return verifyOptions;\n}\n\nexport function createVerificationToken(\n options: VerificationTokenOptions\n): VerificationTokenResult {\n const action = normalizeAction(options.action);\n const otpLength = resolveOtpLength(options.otpLength);\n const tokenSecret = getTokenSecret();\n const otpSecret = getOtpSecret();\n const otp = generateOtp(otpLength);\n const signOptions = buildSignOptions(options);\n const payload: VerificationTokenPayload = {\n act: action,\n otp: hashOtp(otp, otpSecret),\n jti: randomUUID(),\n sub: options.subject\n };\n\n const token = sign(payload, tokenSecret, signOptions);\n const expiresInSeconds = signOptions.expiresIn as number;\n\n return {\n token,\n otp,\n expiresAt: Date.now() + expiresInSeconds * 1000,\n action\n };\n}\n\nexport const verificationToken = createVerificationToken;\n\nexport function verifyVerificationToken(\n token: string,\n options: VerifyVerificationTokenOptions = {}\n): VerificationTokenPayload {\n // Optional verification bypass for a single review account (e.g. app store review)\n // It is disabled unless both VERIFICATION_BYPASS_SUBJECT and VERIFICATION_BYPASS_OTP are explicitly set\n const bypassSubject = process.env.VERIFICATION_BYPASS_SUBJECT;\n const bypassOtp = process.env.VERIFICATION_BYPASS_OTP;\n if (\n bypassSubject &&\n bypassOtp &&\n options.subject === bypassSubject &&\n options.otp !== undefined &&\n safeEqual(options.otp, bypassOtp)\n ) {\n return {\n act: options.action ? normalizeAction(options.action) : 'TEST_VERIFICATION',\n otp: hashOtp(bypassOtp, getOtpSecret()),\n jti: 'test-verification-jti',\n sub: bypassSubject,\n iat: Math.floor(Date.now() / 1000),\n exp: Math.floor(Date.now() / 1000) + DEFAULT_EXPIRES_IN_SECONDS,\n iss: buildIssuer(options.issuer)\n } as VerificationTokenPayload;\n }\n\n const tokenSecret = getTokenSecret();\n let payload: VerificationTokenPayload;\n\n try {\n payload = verify(token, tokenSecret, buildVerifyOptions(options)) as VerificationTokenPayload;\n } catch (error: unknown) {\n throw new WebError({\n errorCode: 'unauthorized',\n statusCode: 401,\n message: 'Invalid verification token supplied',\n error: error instanceof Error ? error : undefined\n });\n }\n\n if (!payload?.act || !payload?.otp || !payload?.jti) {\n throw new WebError({\n errorCode: 'unauthorized',\n statusCode: 401,\n message: 'Malformed verification token payload'\n });\n }\n\n if (options.action) {\n const action = normalizeAction(options.action);\n if (payload.act !== action) {\n throw new WebError({\n errorCode: 'verification_failed',\n statusCode: 403,\n message: 'Verification action mismatch',\n data: { expected: action, actual: payload.act }\n });\n }\n }\n\n if (options.subject && payload.sub !== options.subject) {\n throw new WebError({\n errorCode: 'verification_failed',\n statusCode: 403,\n message: 'Verification subject mismatch',\n data: { expected: options.subject, actual: payload.sub }\n });\n }\n\n if (options.otp) {\n const otpSecret = getOtpSecret();\n const expectedHash = hashOtp(options.otp, otpSecret);\n if (!safeEqual(payload.otp, expectedHash)) {\n throw new WebError({\n errorCode: 'verification_failed',\n statusCode: 403,\n message: 'Verification OTP mismatch'\n });\n }\n }\n\n return payload;\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"verificationToken.js","names":["_crypto","require","_jsonwebtoken","_EngineError","_WebError","_checkEnvironment","_envAssert","DEFAULT_OTP_LENGTH","DEFAULT_EXPIRES_IN_SECONDS","DEFAULT_ISSUER","normalizeAction","action","EngineError","message","data","trim","toUpperCase","resolveOtpLength","length","undefined","Number","isInteger","resolveExpiresInSeconds","expiresInSeconds","getTokenSecret","secret","process","env","VERIFICATION_TOKEN_SECRET","assertEnvironment","envAssert","isString","getOtpSecret","VERIFICATION_TOKEN_OTP_SECRET","hashOtp","otp","createHmac","update","digest","safeEqual","a","b","bufferA","Buffer","from","bufferB","timingSafeEqual","generateOtp","index","randomInt","toString","buildIssuer","issuer","VERIFICATION_TOKEN_ISSUER","buildSignOptions","options","signOptions","algorithm","expiresIn","audience","VERIFICATION_TOKEN_AUDIENCE","normalizeAudience","Array","isArray","slice","buildVerifyOptions","verifyOptions","algorithms","normalizedAudience","createVerificationToken","otpLength","tokenSecret","otpSecret","payload","act","jti","randomUUID","sub","subject","token","sign","expiresAt","Date","now","verificationToken","exports","verifyVerificationToken","bypassSubject","VERIFICATION_BYPASS_SUBJECT","bypassOtp","VERIFICATION_BYPASS_OTP","iat","Math","floor","exp","iss","verify","error","WebError","errorCode","statusCode","Error","expected","actual","expectedHash"],"sources":["../../../src/utils/verificationToken/verificationToken.ts"],"sourcesContent":["import { randomInt, randomUUID, createHmac, timingSafeEqual } from 'crypto';\nimport { sign, verify, SignOptions, VerifyOptions } from 'jsonwebtoken';\nimport { EngineError } from 'entities/EngineError';\nimport { WebError } from 'entities/WebError';\nimport { assertEnvironment } from 'utils/checkEnvironment';\nimport { envAssert } from 'utils/envAssert';\nimport {\n VerificationTokenPayload,\n VerificationTokenOptions,\n VerificationTokenResult,\n VerifyVerificationTokenOptions\n} from './verificationToken.types';\n\nconst DEFAULT_OTP_LENGTH = 6;\nconst DEFAULT_EXPIRES_IN_SECONDS = 5 * 60;\nconst DEFAULT_ISSUER = 'node-server-engine';\n\nfunction normalizeAction(action: string): string {\n if (!action || typeof action !== 'string') {\n throw new EngineError({\n message: 'Verification token action must be a non-empty string',\n data: { action }\n });\n }\n return action.trim().toUpperCase();\n}\n\nfunction resolveOtpLength(length?: number): number {\n if (length === undefined) return DEFAULT_OTP_LENGTH;\n if (!Number.isInteger(length) || length < 4 || length > 10) {\n throw new EngineError({\n message: 'OTP length must be an integer between 4 and 10',\n data: { length }\n });\n }\n return length;\n}\n\nfunction resolveExpiresInSeconds(expiresInSeconds?: number): number {\n if (expiresInSeconds === undefined) return DEFAULT_EXPIRES_IN_SECONDS;\n if (!Number.isInteger(expiresInSeconds) || expiresInSeconds < 30) {\n throw new EngineError({\n message: 'Verification token expiration must be at least 30 seconds',\n data: { expiresInSeconds }\n });\n }\n return expiresInSeconds;\n}\n\nfunction getTokenSecret(): string {\n const secret = process.env.VERIFICATION_TOKEN_SECRET;\n if (!secret) {\n assertEnvironment({ VERIFICATION_TOKEN_SECRET: envAssert.isString() });\n }\n return secret as string;\n}\n\nfunction getOtpSecret(): string {\n return process.env.VERIFICATION_TOKEN_OTP_SECRET ?? getTokenSecret();\n}\n\nfunction hashOtp(otp: string, secret: string): string {\n return createHmac('sha256', secret).update(otp).digest('hex');\n}\n\n/** Constant time string comparison */\nfunction safeEqual(a: string, b: string): boolean {\n const bufferA = Buffer.from(a);\n const bufferB = Buffer.from(b);\n return bufferA.length === bufferB.length && timingSafeEqual(bufferA, bufferB);\n}\n\nfunction generateOtp(length: number): string {\n let otp = '';\n for (let index = 0; index < length; index += 1) {\n otp += randomInt(0, 10).toString();\n }\n return otp;\n}\n\nfunction buildIssuer(issuer?: string): string {\n return issuer ?? process.env.VERIFICATION_TOKEN_ISSUER ?? DEFAULT_ISSUER;\n}\n\nfunction buildSignOptions(options: VerificationTokenOptions): SignOptions {\n const signOptions: SignOptions = {\n algorithm: 'HS256',\n expiresIn: resolveExpiresInSeconds(options.expiresInSeconds),\n issuer: buildIssuer(options.issuer)\n };\n if (options.audience) {\n signOptions.audience = options.audience;\n } else if (process.env.VERIFICATION_TOKEN_AUDIENCE) {\n signOptions.audience = process.env.VERIFICATION_TOKEN_AUDIENCE;\n }\n return signOptions;\n}\n\nfunction normalizeAudience(\n audience?: string | string[]\n): VerifyOptions['audience'] | undefined {\n if (!audience) return undefined;\n if (Array.isArray(audience)) {\n if (audience.length === 0) return undefined;\n return [audience[0], ...audience.slice(1)];\n }\n return audience;\n}\n\nfunction buildVerifyOptions(\n options: VerifyVerificationTokenOptions\n): VerifyOptions {\n const verifyOptions: VerifyOptions = {\n algorithms: ['HS256'],\n issuer: buildIssuer(options.issuer)\n };\n const normalizedAudience = normalizeAudience(\n options.audience ?? process.env.VERIFICATION_TOKEN_AUDIENCE\n );\n if (normalizedAudience) verifyOptions.audience = normalizedAudience;\n return verifyOptions;\n}\n\nexport function createVerificationToken(\n options: VerificationTokenOptions\n): VerificationTokenResult {\n const action = normalizeAction(options.action);\n const otpLength = resolveOtpLength(options.otpLength);\n const tokenSecret = getTokenSecret();\n const otpSecret = getOtpSecret();\n const otp = generateOtp(otpLength);\n const signOptions = buildSignOptions(options);\n const payload: VerificationTokenPayload = {\n act: action,\n otp: hashOtp(otp, otpSecret),\n jti: randomUUID(),\n sub: options.subject\n };\n\n const token = sign(payload, tokenSecret, signOptions);\n const expiresInSeconds = signOptions.expiresIn as number;\n\n return {\n token,\n otp,\n expiresAt: Date.now() + expiresInSeconds * 1000,\n action\n };\n}\n\nexport const verificationToken = createVerificationToken;\n\nexport function verifyVerificationToken(\n token: string,\n options: VerifyVerificationTokenOptions = {}\n): VerificationTokenPayload {\n // Optional verification bypass for a single review account (e.g. app store review)\n // It is disabled unless both VERIFICATION_BYPASS_SUBJECT and VERIFICATION_BYPASS_OTP are explicitly set\n const bypassSubject = process.env.VERIFICATION_BYPASS_SUBJECT;\n const bypassOtp = process.env.VERIFICATION_BYPASS_OTP;\n if (\n bypassSubject &&\n bypassOtp &&\n options.subject === bypassSubject &&\n options.otp !== undefined &&\n safeEqual(options.otp, bypassOtp)\n ) {\n return {\n act: options.action\n ? normalizeAction(options.action)\n : 'TEST_VERIFICATION',\n otp: hashOtp(bypassOtp, getOtpSecret()),\n jti: 'test-verification-jti',\n sub: bypassSubject,\n iat: Math.floor(Date.now() / 1000),\n exp: Math.floor(Date.now() / 1000) + DEFAULT_EXPIRES_IN_SECONDS,\n iss: buildIssuer(options.issuer)\n } as VerificationTokenPayload;\n }\n\n const tokenSecret = getTokenSecret();\n let payload: VerificationTokenPayload;\n\n try {\n payload = verify(\n token,\n tokenSecret,\n buildVerifyOptions(options)\n ) as VerificationTokenPayload;\n } catch (error: unknown) {\n throw new WebError({\n errorCode: 'unauthorized',\n statusCode: 401,\n message: 'Invalid verification token supplied',\n error: error instanceof Error ? error : undefined\n });\n }\n\n if (!payload?.act || !payload?.otp || !payload?.jti) {\n throw new WebError({\n errorCode: 'unauthorized',\n statusCode: 401,\n message: 'Malformed verification token payload'\n });\n }\n\n if (options.action) {\n const action = normalizeAction(options.action);\n if (payload.act !== action) {\n throw new WebError({\n errorCode: 'verification_failed',\n statusCode: 403,\n message: 'Verification action mismatch',\n data: { expected: action, actual: payload.act }\n });\n }\n }\n\n if (options.subject && payload.sub !== options.subject) {\n throw new WebError({\n errorCode: 'verification_failed',\n statusCode: 403,\n message: 'Verification subject mismatch',\n data: { expected: options.subject, actual: payload.sub }\n });\n }\n\n if (options.otp) {\n const otpSecret = getOtpSecret();\n const expectedHash = hashOtp(options.otp, otpSecret);\n if (!safeEqual(payload.otp, expectedHash)) {\n throw new WebError({\n errorCode: 'verification_failed',\n statusCode: 403,\n message: 'Verification OTP mismatch'\n });\n }\n }\n\n return payload;\n}\n"],"mappings":";;;;;;;;AAAA,IAAAA,OAAA,GAAAC,OAAA;AACA,IAAAC,aAAA,GAAAD,OAAA;AACA,IAAAE,YAAA,GAAAF,OAAA;AACA,IAAAG,SAAA,GAAAH,OAAA;AACA,IAAAI,iBAAA,GAAAJ,OAAA;AACA,IAAAK,UAAA,GAAAL,OAAA;AAQA,MAAMM,kBAAkB,GAAG,CAAC;AAC5B,MAAMC,0BAA0B,GAAG,CAAC,GAAG,EAAE;AACzC,MAAMC,cAAc,GAAG,oBAAoB;AAE3C,SAASC,eAAeA,CAACC,MAAc,EAAU;EAC/C,IAAI,CAACA,MAAM,IAAI,OAAOA,MAAM,KAAK,QAAQ,EAAE;IACzC,MAAM,IAAIC,wBAAW,CAAC;MACpBC,OAAO,EAAE,sDAAsD;MAC/DC,IAAI,EAAE;QAAEH;MAAO;IACjB,CAAC,CAAC;EACJ;EACA,OAAOA,MAAM,CAACI,IAAI,CAAC,CAAC,CAACC,WAAW,CAAC,CAAC;AACpC;AAEA,SAASC,gBAAgBA,CAACC,MAAe,EAAU;EACjD,IAAIA,MAAM,KAAKC,SAAS,EAAE,OAAOZ,kBAAkB;EACnD,IAAI,CAACa,MAAM,CAACC,SAAS,CAACH,MAAM,CAAC,IAAIA,MAAM,GAAG,CAAC,IAAIA,MAAM,GAAG,EAAE,EAAE;IAC1D,MAAM,IAAIN,wBAAW,CAAC;MACpBC,OAAO,EAAE,gDAAgD;MACzDC,IAAI,EAAE;QAAEI;MAAO;IACjB,CAAC,CAAC;EACJ;EACA,OAAOA,MAAM;AACf;AAEA,SAASI,uBAAuBA,CAACC,gBAAyB,EAAU;EAClE,IAAIA,gBAAgB,KAAKJ,SAAS,EAAE,OAAOX,0BAA0B;EACrE,IAAI,CAACY,MAAM,CAACC,SAAS,CAACE,gBAAgB,CAAC,IAAIA,gBAAgB,GAAG,EAAE,EAAE;IAChE,MAAM,IAAIX,wBAAW,CAAC;MACpBC,OAAO,EAAE,2DAA2D;MACpEC,IAAI,EAAE;QAAES;MAAiB;IAC3B,CAAC,CAAC;EACJ;EACA,OAAOA,gBAAgB;AACzB;AAEA,SAASC,cAAcA,CAAA,EAAW;EAChC,MAAMC,MAAM,GAAGC,OAAO,CAACC,GAAG,CAACC,yBAAyB;EACpD,IAAI,CAACH,MAAM,EAAE;IACX,IAAAI,mCAAiB,EAAC;MAAED,yBAAyB,EAAEE,oBAAS,CAACC,QAAQ,CAAC;IAAE,CAAC,CAAC;EACxE;EACA,OAAON,MAAM;AACf;AAEA,SAASO,YAAYA,CAAA,EAAW;EAC9B,OAAON,OAAO,CAACC,GAAG,CAACM,6BAA6B,IAAIT,cAAc,CAAC,CAAC;AACtE;AAEA,SAASU,OAAOA,CAACC,GAAW,EAAEV,MAAc,EAAU;EACpD,OAAO,IAAAW,kBAAU,EAAC,QAAQ,EAAEX,MAAM,CAAC,CAACY,MAAM,CAACF,GAAG,CAAC,CAACG,MAAM,CAAC,KAAK,CAAC;AAC/D;;AAEA;AACA,SAASC,SAASA,CAACC,CAAS,EAAEC,CAAS,EAAW;EAChD,MAAMC,OAAO,GAAGC,MAAM,CAACC,IAAI,CAACJ,CAAC,CAAC;EAC9B,MAAMK,OAAO,GAAGF,MAAM,CAACC,IAAI,CAACH,CAAC,CAAC;EAC9B,OAAOC,OAAO,CAACxB,MAAM,KAAK2B,OAAO,CAAC3B,MAAM,IAAI,IAAA4B,uBAAe,EAACJ,OAAO,EAAEG,OAAO,CAAC;AAC/E;AAEA,SAASE,WAAWA,CAAC7B,MAAc,EAAU;EAC3C,IAAIiB,GAAG,GAAG,EAAE;EACZ,KAAK,IAAIa,KAAK,GAAG,CAAC,EAAEA,KAAK,GAAG9B,MAAM,EAAE8B,KAAK,IAAI,CAAC,EAAE;IAC9Cb,GAAG,IAAI,IAAAc,iBAAS,EAAC,CAAC,EAAE,EAAE,CAAC,CAACC,QAAQ,CAAC,CAAC;EACpC;EACA,OAAOf,GAAG;AACZ;AAEA,SAASgB,WAAWA,CAACC,MAAe,EAAU;EAC5C,OAAOA,MAAM,IAAI1B,OAAO,CAACC,GAAG,CAAC0B,yBAAyB,IAAI5C,cAAc;AAC1E;AAEA,SAAS6C,gBAAgBA,CAACC,OAAiC,EAAe;EACxE,MAAMC,WAAwB,GAAG;IAC/BC,SAAS,EAAE,OAAO;IAClBC,SAAS,EAAEpC,uBAAuB,CAACiC,OAAO,CAAChC,gBAAgB,CAAC;IAC5D6B,MAAM,EAAED,WAAW,CAACI,OAAO,CAACH,MAAM;EACpC,CAAC;EACD,IAAIG,OAAO,CAACI,QAAQ,EAAE;IACpBH,WAAW,CAACG,QAAQ,GAAGJ,OAAO,CAACI,QAAQ;EACzC,CAAC,MAAM,IAAIjC,OAAO,CAACC,GAAG,CAACiC,2BAA2B,EAAE;IAClDJ,WAAW,CAACG,QAAQ,GAAGjC,OAAO,CAACC,GAAG,CAACiC,2BAA2B;EAChE;EACA,OAAOJ,WAAW;AACpB;AAEA,SAASK,iBAAiBA,CACxBF,QAA4B,EACW;EACvC,IAAI,CAACA,QAAQ,EAAE,OAAOxC,SAAS;EAC/B,IAAI2C,KAAK,CAACC,OAAO,CAACJ,QAAQ,CAAC,EAAE;IAC3B,IAAIA,QAAQ,CAACzC,MAAM,KAAK,CAAC,EAAE,OAAOC,SAAS;IAC3C,OAAO,CAACwC,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAGA,QAAQ,CAACK,KAAK,CAAC,CAAC,CAAC,CAAC;EAC5C;EACA,OAAOL,QAAQ;AACjB;AAEA,SAASM,kBAAkBA,CACzBV,OAAuC,EACxB;EACf,MAAMW,aAA4B,GAAG;IACnCC,UAAU,EAAE,CAAC,OAAO,CAAC;IACrBf,MAAM,EAAED,WAAW,CAACI,OAAO,CAACH,MAAM;EACpC,CAAC;EACD,MAAMgB,kBAAkB,GAAGP,iBAAiB,CAC1CN,OAAO,CAACI,QAAQ,IAAIjC,OAAO,CAACC,GAAG,CAACiC,2BAClC,CAAC;EACD,IAAIQ,kBAAkB,EAAEF,aAAa,CAACP,QAAQ,GAAGS,kBAAkB;EACnE,OAAOF,aAAa;AACtB;AAEO,SAASG,uBAAuBA,CACrCd,OAAiC,EACR;EACzB,MAAM5C,MAAM,GAAGD,eAAe,CAAC6C,OAAO,CAAC5C,MAAM,CAAC;EAC9C,MAAM2D,SAAS,GAAGrD,gBAAgB,CAACsC,OAAO,CAACe,SAAS,CAAC;EACrD,MAAMC,WAAW,GAAG/C,cAAc,CAAC,CAAC;EACpC,MAAMgD,SAAS,GAAGxC,YAAY,CAAC,CAAC;EAChC,MAAMG,GAAG,GAAGY,WAAW,CAACuB,SAAS,CAAC;EAClC,MAAMd,WAAW,GAAGF,gBAAgB,CAACC,OAAO,CAAC;EAC7C,MAAMkB,OAAiC,GAAG;IACxCC,GAAG,EAAE/D,MAAM;IACXwB,GAAG,EAAED,OAAO,CAACC,GAAG,EAAEqC,SAAS,CAAC;IAC5BG,GAAG,EAAE,IAAAC,kBAAU,EAAC,CAAC;IACjBC,GAAG,EAAEtB,OAAO,CAACuB;EACf,CAAC;EAED,MAAMC,KAAK,GAAG,IAAAC,kBAAI,EAACP,OAAO,EAAEF,WAAW,EAAEf,WAAW,CAAC;EACrD,MAAMjC,gBAAgB,GAAGiC,WAAW,CAACE,SAAmB;EAExD,OAAO;IACLqB,KAAK;IACL5C,GAAG;IACH8C,SAAS,EAAEC,IAAI,CAACC,GAAG,CAAC,CAAC,GAAG5D,gBAAgB,GAAG,IAAI;IAC/CZ;EACF,CAAC;AACH;AAEO,MAAMyE,iBAAiB,GAAAC,OAAA,CAAAD,iBAAA,GAAGf,uBAAuB;AAEjD,SAASiB,uBAAuBA,CACrCP,KAAa,EACbxB,OAAuC,GAAG,CAAC,CAAC,EAClB;EAC1B;EACA;EACA,MAAMgC,aAAa,GAAG7D,OAAO,CAACC,GAAG,CAAC6D,2BAA2B;EAC7D,MAAMC,SAAS,GAAG/D,OAAO,CAACC,GAAG,CAAC+D,uBAAuB;EACrD,IACEH,aAAa,IACbE,SAAS,IACTlC,OAAO,CAACuB,OAAO,KAAKS,aAAa,IACjChC,OAAO,CAACpB,GAAG,KAAKhB,SAAS,IACzBoB,SAAS,CAACgB,OAAO,CAACpB,GAAG,EAAEsD,SAAS,CAAC,EACjC;IACA,OAAO;MACLf,GAAG,EAAEnB,OAAO,CAAC5C,MAAM,GACfD,eAAe,CAAC6C,OAAO,CAAC5C,MAAM,CAAC,GAC/B,mBAAmB;MACvBwB,GAAG,EAAED,OAAO,CAACuD,SAAS,EAAEzD,YAAY,CAAC,CAAC,CAAC;MACvC2C,GAAG,EAAE,uBAAuB;MAC5BE,GAAG,EAAEU,aAAa;MAClBI,GAAG,EAAEC,IAAI,CAACC,KAAK,CAACX,IAAI,CAACC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC;MAClCW,GAAG,EAAEF,IAAI,CAACC,KAAK,CAACX,IAAI,CAACC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG3E,0BAA0B;MAC/DuF,GAAG,EAAE5C,WAAW,CAACI,OAAO,CAACH,MAAM;IACjC,CAAC;EACH;EAEA,MAAMmB,WAAW,GAAG/C,cAAc,CAAC,CAAC;EACpC,IAAIiD,OAAiC;EAErC,IAAI;IACFA,OAAO,GAAG,IAAAuB,oBAAM,EACdjB,KAAK,EACLR,WAAW,EACXN,kBAAkB,CAACV,OAAO,CAC5B,CAA6B;EAC/B,CAAC,CAAC,OAAO0C,KAAc,EAAE;IACvB,MAAM,IAAIC,kBAAQ,CAAC;MACjBC,SAAS,EAAE,cAAc;MACzBC,UAAU,EAAE,GAAG;MACfvF,OAAO,EAAE,qCAAqC;MAC9CoF,KAAK,EAAEA,KAAK,YAAYI,KAAK,GAAGJ,KAAK,GAAG9E;IAC1C,CAAC,CAAC;EACJ;EAEA,IAAI,CAACsD,OAAO,EAAEC,GAAG,IAAI,CAACD,OAAO,EAAEtC,GAAG,IAAI,CAACsC,OAAO,EAAEE,GAAG,EAAE;IACnD,MAAM,IAAIuB,kBAAQ,CAAC;MACjBC,SAAS,EAAE,cAAc;MACzBC,UAAU,EAAE,GAAG;MACfvF,OAAO,EAAE;IACX,CAAC,CAAC;EACJ;EAEA,IAAI0C,OAAO,CAAC5C,MAAM,EAAE;IAClB,MAAMA,MAAM,GAAGD,eAAe,CAAC6C,OAAO,CAAC5C,MAAM,CAAC;IAC9C,IAAI8D,OAAO,CAACC,GAAG,KAAK/D,MAAM,EAAE;MAC1B,MAAM,IAAIuF,kBAAQ,CAAC;QACjBC,SAAS,EAAE,qBAAqB;QAChCC,UAAU,EAAE,GAAG;QACfvF,OAAO,EAAE,8BAA8B;QACvCC,IAAI,EAAE;UAAEwF,QAAQ,EAAE3F,MAAM;UAAE4F,MAAM,EAAE9B,OAAO,CAACC;QAAI;MAChD,CAAC,CAAC;IACJ;EACF;EAEA,IAAInB,OAAO,CAACuB,OAAO,IAAIL,OAAO,CAACI,GAAG,KAAKtB,OAAO,CAACuB,OAAO,EAAE;IACtD,MAAM,IAAIoB,kBAAQ,CAAC;MACjBC,SAAS,EAAE,qBAAqB;MAChCC,UAAU,EAAE,GAAG;MACfvF,OAAO,EAAE,+BAA+B;MACxCC,IAAI,EAAE;QAAEwF,QAAQ,EAAE/C,OAAO,CAACuB,OAAO;QAAEyB,MAAM,EAAE9B,OAAO,CAACI;MAAI;IACzD,CAAC,CAAC;EACJ;EAEA,IAAItB,OAAO,CAACpB,GAAG,EAAE;IACf,MAAMqC,SAAS,GAAGxC,YAAY,CAAC,CAAC;IAChC,MAAMwE,YAAY,GAAGtE,OAAO,CAACqB,OAAO,CAACpB,GAAG,EAAEqC,SAAS,CAAC;IACpD,IAAI,CAACjC,SAAS,CAACkC,OAAO,CAACtC,GAAG,EAAEqE,YAAY,CAAC,EAAE;MACzC,MAAM,IAAIN,kBAAQ,CAAC;QACjBC,SAAS,EAAE,qBAAqB;QAChCC,UAAU,EAAE,GAAG;QACfvF,OAAO,EAAE;MACX,CAAC,CAAC;IACJ;EACF;EAEA,OAAO4D,OAAO;AAChB","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-server-engine",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Framework used to develop backend services. This package ships with a lot of features to standardize the creation of services, letting you focus on the business logic.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|