equipped 5.2.0 → 5.2.2

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/server/impls/base.cjs +12 -11
  3. package/dist/cjs/server/impls/base.cjs.map +1 -1
  4. package/dist/cjs/server/impls/base.min.cjs +1 -1
  5. package/dist/cjs/server/impls/base.min.cjs.map +1 -1
  6. package/dist/cjs/server/pipes.cjs +1 -1
  7. package/dist/cjs/server/pipes.cjs.map +1 -1
  8. package/dist/cjs/server/pipes.min.cjs +1 -1
  9. package/dist/cjs/server/pipes.min.cjs.map +1 -1
  10. package/dist/cjs/utilities/authProviders.cjs +2 -2
  11. package/dist/cjs/utilities/authProviders.cjs.map +1 -1
  12. package/dist/cjs/utilities/authProviders.min.cjs +1 -1
  13. package/dist/cjs/utilities/authProviders.min.cjs.map +1 -1
  14. package/dist/esm/server/impls/base.min.mjs +1 -1
  15. package/dist/esm/server/impls/base.min.mjs.map +1 -1
  16. package/dist/esm/server/impls/base.mjs +3 -2
  17. package/dist/esm/server/impls/base.mjs.map +1 -1
  18. package/dist/esm/server/pipes.min.mjs +1 -1
  19. package/dist/esm/server/pipes.min.mjs.map +1 -1
  20. package/dist/esm/server/pipes.mjs +1 -1
  21. package/dist/esm/server/pipes.mjs.map +1 -1
  22. package/dist/esm/utilities/authProviders.min.mjs +1 -1
  23. package/dist/esm/utilities/authProviders.min.mjs.map +1 -1
  24. package/dist/esm/utilities/authProviders.mjs +2 -2
  25. package/dist/esm/utilities/authProviders.mjs.map +1 -1
  26. package/dist/types/errors/index.d.ts +3 -3
  27. package/dist/types/{fastify-B6FUtYe9.d.ts → fastify-bLbDRjkI.d.ts} +4 -6
  28. package/dist/types/index.d.ts +4 -2
  29. package/dist/types/instance/index.d.ts +6 -4
  30. package/dist/types/{requestError-7N-ngghg.d.ts → requestError-JVHgFJzE.d.ts} +4 -4
  31. package/dist/types/server/impls/base.js +3 -2
  32. package/dist/types/server/index.d.ts +5 -3
  33. package/dist/types/server/pipes.js +1 -1
  34. package/dist/types/utilities/authProviders.js +2 -2
  35. package/dist/types/{validationError-BB4cfdZa.d.ts → validationError-CPQdQ7rX.d.ts} +1 -1
  36. package/dist/types/validations/index.d.ts +2 -2
  37. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [5.2.2](https://github.com/kevinand11/equipped/compare/v5.2.1...v5.2.2) (2026-02-08)
6
+
7
+
8
+ ### Features
9
+
10
+ * support allow all domains for cors ([bf12ed4](https://github.com/kevinand11/equipped/commit/bf12ed451970c5946f819c9ea2ae43471b640c85))
11
+
12
+ ### [5.2.1](https://github.com/kevinand11/equipped/compare/v5.2.0...v5.2.1) (2026-02-03)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * only log error if it is not an equipped error ([ab8f517](https://github.com/kevinand11/equipped/commit/ab8f517b0ea4412453a89df759943e9d2c9df736))
18
+
5
19
  ## [5.2.0](https://github.com/kevinand11/equipped/compare/v5.1.11...v5.2.0) (2026-02-03)
6
20
 
7
21
 
@@ -1,4 +1,5 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }require('cors');
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }require('@fastify/cors');
2
+ require('cors');
2
3
  var _socketio = require('socket.io');
3
4
  var _supertest = require('supertest'); var _supertest2 = _interopRequireDefault(_supertest);
4
5
  var _valleyed = require('valleyed');
@@ -36,9 +37,9 @@ class Server {
36
37
 
37
38
  get cors() {
38
39
  return {
39
- origin: _optionalChain([this, 'access', _2 => _2.config, 'access', _3 => _3.cors, 'optionalAccess', _4 => _4.origin]),
40
- methods: (_nullishCoalesce(_optionalChain([this, 'access', _5 => _5.config, 'access', _6 => _6.cors, 'optionalAccess', _7 => _7.methods]), () => ( Object.values(_typescjs.Methods)))).filter((m) => m !== _typescjs.Methods.options).map((m) => m.toUpperCase()),
41
- credentials: _optionalChain([this, 'access', _8 => _8.config, 'access', _9 => _9.cors, 'optionalAccess', _10 => _10.credentials])
40
+ origin: _optionalChain([this, 'access', _2 => _2.config, 'access', _3 => _3.cors, 'optionalAccess', _4 => _4.origin]) ? (_, cb) => cb(null, true) : _optionalChain([this, 'access', _5 => _5.config, 'access', _6 => _6.cors, 'optionalAccess', _7 => _7.origin]),
41
+ methods: (_nullishCoalesce(_optionalChain([this, 'access', _8 => _8.config, 'access', _9 => _9.cors, 'optionalAccess', _10 => _10.methods]), () => ( Object.values(_typescjs.Methods)))).filter((m) => m !== _typescjs.Methods.options).map((m) => m.toUpperCase()),
42
+ credentials: _optionalChain([this, 'access', _11 => _11.config, 'access', _12 => _12.cors, 'optionalAccess', _13 => _13.credentials])
42
43
  };
43
44
  }
44
45
  addRouter(...routers) {
@@ -51,8 +52,8 @@ class Server {
51
52
  const key = `(${method.toUpperCase()}) ${this.#openapi.cleanPath(path)}`;
52
53
  if (this.#routesByKey.get(key))
53
54
  throw new (0, _indexcjs.EquippedError)(`Route key ${key} already registered. All route keys must be unique`, { route, key });
54
- middlewares.forEach((m) => _optionalChain([m, 'access', _11 => _11.onSetup, 'optionalCall', _12 => _12(route)]));
55
- _optionalChain([onError, 'optionalAccess', _13 => _13.onSetup, 'optionalCall', _14 => _14(route)]);
55
+ middlewares.forEach((m) => _optionalChain([m, 'access', _14 => _14.onSetup, 'optionalCall', _15 => _15(route)]));
56
+ _optionalChain([onError, 'optionalAccess', _16 => _16.onSetup, 'optionalCall', _17 => _17(route)]);
56
57
  const { validateRequest, validateResponse, jsonSchema } = this.#resolveSchema(method, schema);
57
58
  this.#routesByKey.set(key, true);
58
59
  await this.#openapi.register(route, jsonSchema);
@@ -64,7 +65,7 @@ class Server {
64
65
  const response = rawRes instanceof _requestscjs.Response ? rawRes : new (0, _requestscjs.Response)({ body: rawRes, status: _typescjs.StatusCodes.Ok, headers: {}, piped: false });
65
66
  return await this.implementations.handleResponse(res, await validateResponse(response));
66
67
  } catch (error) {
67
- if (_optionalChain([onError, 'optionalAccess', _15 => _15.cb])) {
68
+ if (_optionalChain([onError, 'optionalAccess', _18 => _18.cb])) {
68
69
  const rawResponse = await onError.cb(request, this.config, error);
69
70
  const response = rawResponse instanceof _requestscjs.Response ? rawResponse : new (0, _requestscjs.Response)({ body: rawResponse, status: _typescjs.StatusCodes.BadRequest, headers: {} });
70
71
  return await this.implementations.handleResponse(res, await validateResponse(response));
@@ -76,8 +77,8 @@ class Server {
76
77
  });
77
78
  }
78
79
  #resolveSchema(method, schema) {
79
- const defaultStatusCode = _nullishCoalesce(_optionalChain([schema, 'optionalAccess', _16 => _16.defaultStatusCode]), () => ( _typescjs.StatusCodes.Ok));
80
- const defaultContentType = _nullishCoalesce(_optionalChain([schema, 'optionalAccess', _17 => _17.defaultContentType]), () => ( "application/json"));
80
+ const defaultStatusCode = _nullishCoalesce(_optionalChain([schema, 'optionalAccess', _19 => _19.defaultStatusCode]), () => ( _typescjs.StatusCodes.Ok));
81
+ const defaultContentType = _nullishCoalesce(_optionalChain([schema, 'optionalAccess', _20 => _20.defaultContentType]), () => ( "application/json"));
81
82
  let status = defaultStatusCode;
82
83
  let contentType = defaultContentType;
83
84
  const jsonSchema = { response: {}, request: {} };
@@ -103,7 +104,7 @@ class Server {
103
104
  if (def.type === "response") {
104
105
  const pipeRecords = errorsSchemas.concat({ status: defaultStatusCode, contentType, pipe });
105
106
  responsePipeDefs[def.key] = _valleyed.v.any().pipe((input) => {
106
- const p = _optionalChain([pipeRecords, 'access', _18 => _18.find, 'call', _19 => _19((r) => r.status === status), 'optionalAccess', _20 => _20.pipe]);
107
+ const p = _optionalChain([pipeRecords, 'access', _21 => _21.find, 'call', _22 => _22((r) => r.status === status), 'optionalAccess', _23 => _23.pipe]);
107
108
  if (!p) throw _valleyed.PipeError.root(`schema not defined for status code: ${status}`, input);
108
109
  return _valleyed.v.assert(p, input);
109
110
  });
@@ -183,7 +184,7 @@ class Server {
183
184
  throw new (0, _indexcjs.NotFoundError)(`Route ${request.path} not found`);
184
185
  });
185
186
  this.implementations.registerErrorHandler(async (error, _, res) => {
186
- _indexcjs3.Instance.get().log.error({ error }, "Uncaught error in route handler");
187
+ if (!(error instanceof _indexcjs.EquippedError)) _indexcjs3.Instance.get().log.error({ error }, "Uncaught error in route handler");
187
188
  const response = error instanceof _indexcjs.RequestError ? new (0, _requestscjs.Response)({
188
189
  body: error.serializedErrors,
189
190
  status: error.statusCode
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/server/impls/base.ts","/home/runner/work/equipped/equipped/dist/cjs/server/impls/base.cjs"],"names":[],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/server/impls/base.cjs","sourcesContent":["import type http from 'node:http'\n\nimport { type CorsOptions } from 'cors'\nimport { Server as SocketServer } from 'socket.io'\nimport supertest from 'supertest'\nimport { type Pipe, PipeError, v } from 'valleyed'\n\nimport { EquippedError, NotFoundError, RequestError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { pipeErrorToValidationError } from '../../validations'\nimport { requestLocalStorage, responseLocalStorage } from '../../validations/valleyed'\nimport { OpenApi, type OpenApiSchemaDef } from '../openapi'\nimport type { ServerConfig } from '../pipes'\nimport { type Request, Response } from '../requests'\nimport { Router } from '../routes'\nimport { SocketEmitter } from '../sockets'\nimport { Methods, type MethodsEnum, type Route, type RouteDef, StatusCodes } from '../types'\n\ntype RequestValidator = (req: Request<any>) => Promise<Request<any>>\ntype ResponseValidator = (res: Response<any>) => Promise<Response<any>>\n\nconst errorsSchemas = Object.entries(StatusCodes)\n\t.filter(([, value]) => value > 399)\n\t.map(([key, value]) => ({\n\t\tstatus: value,\n\t\tcontentType: 'application/json',\n\t\tpipe: v.meta(v.array(v.object({ message: v.string(), field: v.optional(v.string()) })), {\n\t\t\t$refId: `Errors.${key}Response`,\n\t\t\tdescription: `${key} Response`,\n\t\t}) as Pipe<any, any>,\n\t}))\n\nexport abstract class Server<Req = any, Res = any> {\n\t#queue: (() => void | Promise<void>)[] = []\n\t#routesByKey = new Map<string, boolean>()\n\t#openapi: OpenApi\n\tsocket: SocketEmitter\n\tprotected server: http.Server\n\tprotected get cors() {\n\t\treturn {\n\t\t\torigin: this.config.cors?.origin,\n\t\t\tmethods: (this.config.cors?.methods ?? Object.values(Methods)).filter((m) => m !== Methods.options).map((m) => m.toUpperCase()),\n\t\t\tcredentials: this.config.cors?.credentials,\n\t\t} satisfies CorsOptions\n\t}\n\n\tconstructor(\n\t\tserver: http.Server,\n\t\tprivate config: ServerConfig,\n\t\tprivate implementations: {\n\t\t\tparseRequest: (req: Req) => Promise<Request<any>>\n\t\t\thandleResponse: (res: Res, response: Response<any>) => Promise<void>\n\t\t\tregisterRoute: (method: MethodsEnum, path: string, cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterErrorHandler: (cb: (error: Error, req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterNotFoundHandler: (cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tstart: (port: number) => Promise<boolean>\n\t\t},\n\t) {\n\t\tthis.server = server\n\t\tthis.#openapi = new OpenApi(config)\n\t\tconst socketInstance = new SocketServer(server, { cors: this.cors })\n\t\tthis.socket = new SocketEmitter(socketInstance, config)\n\t\tthis.addRouter(this.#openapi.router())\n\t}\n\n\taddRouter(...routers: Router<any>[]) {\n\t\trouters.map((router) => router.routes).forEach((routes) => this.addRoute(...routes))\n\t}\n\n\taddRoute<T extends RouteDef>(...routes: Route<T>[]) {\n\t\troutes.forEach((route) => {\n\t\t\tthis.#queue.push(async () => {\n\t\t\t\tconst { method, path, schema = {}, onError, middlewares = [] } = route\n\n\t\t\t\tconst key = `(${method.toUpperCase()}) ${this.#openapi.cleanPath(path)}`\n\t\t\t\tif (this.#routesByKey.get(key))\n\t\t\t\t\tthrow new EquippedError(`Route key ${key} already registered. All route keys must be unique`, { route, key })\n\n\t\t\t\tmiddlewares.forEach((m) => m.onSetup?.(route as any))\n\t\t\t\tonError?.onSetup?.(route as any)\n\n\t\t\t\tconst { validateRequest, validateResponse, jsonSchema } = this.#resolveSchema(method, schema)\n\n\t\t\t\tthis.#routesByKey.set(key, true)\n\t\t\t\tawait this.#openapi.register(route, jsonSchema)\n\t\t\t\tthis.implementations.registerRoute(method, this.#openapi.cleanPath(path), async (req: Req, res: Res) => {\n\t\t\t\t\tconst request = await validateRequest(await this.implementations.parseRequest(req))\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor (const middleware of middlewares) await middleware.cb(request, this.config)\n\t\t\t\t\t\tconst rawRes = await route.handler(request, this.config)\n\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\trawRes instanceof Response\n\t\t\t\t\t\t\t\t? rawRes\n\t\t\t\t\t\t\t\t: new Response({ body: rawRes, status: StatusCodes.Ok, headers: {}, piped: false })\n\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (onError?.cb) {\n\t\t\t\t\t\t\tconst rawResponse = await onError.cb(request, this.config, error as Error)\n\t\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\t\trawResponse instanceof Response\n\t\t\t\t\t\t\t\t\t? rawResponse\n\t\t\t\t\t\t\t\t\t: new Response({ body: rawResponse, status: StatusCodes.BadRequest, headers: {} })\n\t\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t}\n\n\t#resolveSchema(method: MethodsEnum, schema: RouteDef) {\n\t\tconst defaultStatusCode = schema?.defaultStatusCode ?? StatusCodes.Ok\n\t\tconst defaultContentType = schema?.defaultContentType ?? 'application/json'\n\t\tlet status = defaultStatusCode\n\t\tlet contentType = defaultContentType\n\t\tconst jsonSchema: OpenApiSchemaDef = { response: {}, request: {} }\n\t\tconst requestPipeDefs: Pick<RouteDef, 'body' | 'headers' | 'query' | 'params' | 'cookies'> = {}\n\t\tconst responsePipeDefs: Pick<RouteDef, 'response' | 'responseHeaders' | 'responseCookies'> = {}\n\n\t\tconst defs: {\n\t\t\tkey: Exclude<keyof RouteDef, `default${string}` | 'context'>\n\t\t\ttype: keyof OpenApiSchemaDef\n\t\t\tskip?: boolean\n\t\t}[] = [\n\t\t\t{ key: 'params', type: 'request' },\n\t\t\t{ key: 'headers', type: 'request' },\n\t\t\t{ key: 'cookies', type: 'request' },\n\t\t\t{ key: 'query', type: 'request' },\n\t\t\t{ key: 'body', type: 'request', skip: !(<MethodsEnum[]>[Methods.post, Methods.put, Methods.patch]).includes(method) },\n\t\t\t{ key: 'response', type: 'response' },\n\t\t\t{ key: 'responseHeaders', type: 'response' },\n\t\t\t{ key: 'responseCookies', type: 'response' },\n\t\t]\n\t\tdefs.forEach((def) => {\n\t\t\tconst pipe = schema[def.key] ?? v.any()\n\t\t\tif (def.skip) return\n\n\t\t\tif (def.type === 'request') {\n\t\t\t\trequestPipeDefs[def.key] = pipe\n\t\t\t\tjsonSchema.request[def.key as keyof typeof jsonSchema.request] = v.schema(pipe)\n\t\t\t}\n\t\t\tif (def.type === 'response') {\n\t\t\t\tconst pipeRecords = errorsSchemas.concat({ status: defaultStatusCode, contentType, pipe })\n\t\t\t\tresponsePipeDefs[def.key] = v.any().pipe((input) => {\n\t\t\t\t\tconst p = pipeRecords.find((r) => r.status === status)?.pipe\n\t\t\t\t\tif (!p) throw PipeError.root(`schema not defined for status code: ${status}`, input)\n\t\t\t\t\treturn v.assert(p, input)\n\t\t\t\t})\n\t\t\t\tjsonSchema.response[def.key as keyof typeof jsonSchema.response] = pipeRecords.map((record) => ({\n\t\t\t\t\tstatus: record.status,\n\t\t\t\t\tcontentType: record.contentType,\n\t\t\t\t\tschema: v.schema(record.pipe),\n\t\t\t\t}))\n\t\t\t}\n\t\t})\n\t\tconst requestPipe = v.object(requestPipeDefs)\n\t\tv.compile(requestPipe, { allErrors: true })\n\t\tconst responsePipe = v.object(responsePipeDefs)\n\t\tv.compile(responsePipe, { allErrors: true })\n\t\tconst validateRequest: RequestValidator = async (request) => {\n\t\t\tif (!Object.keys(requestPipeDefs)) return request\n\t\t\tconst validity = requestLocalStorage.run(request, () =>\n\t\t\t\tv.validate(requestPipe, {\n\t\t\t\t\tparams: request.params,\n\t\t\t\t\theaders: request.headers,\n\t\t\t\t\tquery: request.query,\n\t\t\t\t\tbody: request.body,\n\t\t\t\t\tcookies: request.cookies,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\trequest.params = validity.value.params!\n\t\t\trequest.headers = validity.value.headers!\n\t\t\trequest.query = validity.value.query!\n\t\t\trequest.body = validity.value.body!\n\t\t\trequest.cookies = validity.value.cookies!\n\t\t\treturn request\n\t\t}\n\t\tconst validateResponse: ResponseValidator = async (response) => {\n\t\t\tif (!Object.keys(responsePipeDefs)) return response\n\t\t\tstatus = response.status\n\t\t\tcontentType = response.contentType\n\n\t\t\tconst validity = responseLocalStorage.run(response, () =>\n\t\t\t\tv.validate(responsePipe, {\n\t\t\t\t\tresponseHeaders: response.headers,\n\t\t\t\t\tresponseCookies: Object.fromEntries(Object.entries(response.cookies).map(([key, val]) => [key, val.value] as const)),\n\t\t\t\t\tresponse: response.body,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\tresponse.body = validity.value.response!\n\t\t\tresponse.headers = validity.value.responseHeaders!\n\t\t\tresponse.cookieValues = validity.value.responseCookies!\n\t\t\treturn response\n\t\t}\n\t\treturn {\n\t\t\tjsonSchema,\n\t\t\tvalidateRequest,\n\t\t\tvalidateResponse,\n\t\t}\n\t}\n\n\ttest() {\n\t\treturn supertest(this.server)\n\t}\n\n\tasync start() {\n\t\tconst port = this.config.port\n\t\tconst instance = Instance.get()\n\t\tconst { app } = instance.settings\n\t\tif (this.config.healthPath)\n\t\t\tthis.addRoute({\n\t\t\t\tmethod: Methods.get,\n\t\t\t\tpath: this.config.healthPath,\n\t\t\t\thandler: async (req) =>\n\t\t\t\t\treq.res({\n\t\t\t\t\t\tbody: `${instance.id}(${app.name}) service running`,\n\t\t\t\t\t\tcontentType: 'text/plain',\n\t\t\t\t\t}),\n\t\t\t})\n\n\t\tthis.implementations.registerNotFoundHandler(async (req) => {\n\t\t\tconst request = await this.implementations.parseRequest(req)\n\t\t\tthrow new NotFoundError(`Route ${request.path} not found`)\n\t\t})\n\t\tthis.implementations.registerErrorHandler(async (error, _, res) => {\n\t\t\tInstance.get().log.error({ error }, 'Uncaught error in route handler')\n\t\t\tconst response =\n\t\t\t\terror instanceof RequestError\n\t\t\t\t\t? new Response({\n\t\t\t\t\t\t\tbody: error.serializedErrors,\n\t\t\t\t\t\t\tstatus: error.statusCode,\n\t\t\t\t\t\t})\n\t\t\t\t\t: new Response({\n\t\t\t\t\t\t\tbody: [{ message: 'Something went wrong', data: error.message }],\n\t\t\t\t\t\t\tstatus: StatusCodes.BadRequest,\n\t\t\t\t\t\t})\n\t\t\treturn await this.implementations.handleResponse(res, response)\n\t\t})\n\n\t\tawait Promise.all(this.#queue.map((cb) => cb()))\n\t\tconst started = await this.implementations.start(port)\n\t\tif (started) Instance.get().log.info(`${instance.id}(${app.name}) service listening on port ${port}`)\n\t\treturn started\n\t}\n}\n",null]}
1
+ {"version":3,"sources":["../../../../src/server/impls/base.ts","/home/runner/work/equipped/equipped/dist/cjs/server/impls/base.cjs"],"names":[],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/server/impls/base.cjs","sourcesContent":["import type http from 'node:http'\n\nimport { type FastifyCorsOptions } from '@fastify/cors'\nimport { type CorsOptions } from 'cors'\nimport { Server as SocketServer } from 'socket.io'\nimport supertest from 'supertest'\nimport { type Pipe, PipeError, v } from 'valleyed'\n\nimport { EquippedError, NotFoundError, RequestError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { pipeErrorToValidationError } from '../../validations'\nimport { requestLocalStorage, responseLocalStorage } from '../../validations/valleyed'\nimport { OpenApi, type OpenApiSchemaDef } from '../openapi'\nimport type { ServerConfig } from '../pipes'\nimport { type Request, Response } from '../requests'\nimport { Router } from '../routes'\nimport { SocketEmitter } from '../sockets'\nimport { Methods, type MethodsEnum, type Route, type RouteDef, StatusCodes } from '../types'\n\ntype RequestValidator = (req: Request<any>) => Promise<Request<any>>\ntype ResponseValidator = (res: Response<any>) => Promise<Response<any>>\n\nconst errorsSchemas = Object.entries(StatusCodes)\n\t.filter(([, value]) => value > 399)\n\t.map(([key, value]) => ({\n\t\tstatus: value,\n\t\tcontentType: 'application/json',\n\t\tpipe: v.meta(v.array(v.object({ message: v.string(), field: v.optional(v.string()) })), {\n\t\t\t$refId: `Errors.${key}Response`,\n\t\t\tdescription: `${key} Response`,\n\t\t}) as Pipe<any, any>,\n\t}))\n\nexport abstract class Server<Req = any, Res = any> {\n\t#queue: (() => void | Promise<void>)[] = []\n\t#routesByKey = new Map<string, boolean>()\n\t#openapi: OpenApi\n\tsocket: SocketEmitter\n\tprotected server: http.Server\n\tprotected get cors(): CorsOptions & FastifyCorsOptions {\n\t\treturn {\n\t\t\torigin: this.config.cors?.origin ? (_, cb) => cb(null, true) : this.config.cors?.origin,\n\t\t\tmethods: (this.config.cors?.methods ?? Object.values(Methods)).filter((m) => m !== Methods.options).map((m) => m.toUpperCase()),\n\t\t\tcredentials: this.config.cors?.credentials,\n\t\t}\n\t}\n\n\tconstructor(\n\t\tserver: http.Server,\n\t\tprivate config: ServerConfig,\n\t\tprivate implementations: {\n\t\t\tparseRequest: (req: Req) => Promise<Request<any>>\n\t\t\thandleResponse: (res: Res, response: Response<any>) => Promise<void>\n\t\t\tregisterRoute: (method: MethodsEnum, path: string, cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterErrorHandler: (cb: (error: Error, req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterNotFoundHandler: (cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tstart: (port: number) => Promise<boolean>\n\t\t},\n\t) {\n\t\tthis.server = server\n\t\tthis.#openapi = new OpenApi(config)\n\t\tconst socketInstance = new SocketServer(server, { cors: this.cors })\n\t\tthis.socket = new SocketEmitter(socketInstance, config)\n\t\tthis.addRouter(this.#openapi.router())\n\t}\n\n\taddRouter(...routers: Router<any>[]) {\n\t\trouters.map((router) => router.routes).forEach((routes) => this.addRoute(...routes))\n\t}\n\n\taddRoute<T extends RouteDef>(...routes: Route<T>[]) {\n\t\troutes.forEach((route) => {\n\t\t\tthis.#queue.push(async () => {\n\t\t\t\tconst { method, path, schema = {}, onError, middlewares = [] } = route\n\n\t\t\t\tconst key = `(${method.toUpperCase()}) ${this.#openapi.cleanPath(path)}`\n\t\t\t\tif (this.#routesByKey.get(key))\n\t\t\t\t\tthrow new EquippedError(`Route key ${key} already registered. All route keys must be unique`, { route, key })\n\n\t\t\t\tmiddlewares.forEach((m) => m.onSetup?.(route as any))\n\t\t\t\tonError?.onSetup?.(route as any)\n\n\t\t\t\tconst { validateRequest, validateResponse, jsonSchema } = this.#resolveSchema(method, schema)\n\n\t\t\t\tthis.#routesByKey.set(key, true)\n\t\t\t\tawait this.#openapi.register(route, jsonSchema)\n\t\t\t\tthis.implementations.registerRoute(method, this.#openapi.cleanPath(path), async (req: Req, res: Res) => {\n\t\t\t\t\tconst request = await validateRequest(await this.implementations.parseRequest(req))\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor (const middleware of middlewares) await middleware.cb(request, this.config)\n\t\t\t\t\t\tconst rawRes = await route.handler(request, this.config)\n\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\trawRes instanceof Response\n\t\t\t\t\t\t\t\t? rawRes\n\t\t\t\t\t\t\t\t: new Response({ body: rawRes, status: StatusCodes.Ok, headers: {}, piped: false })\n\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (onError?.cb) {\n\t\t\t\t\t\t\tconst rawResponse = await onError.cb(request, this.config, error as Error)\n\t\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\t\trawResponse instanceof Response\n\t\t\t\t\t\t\t\t\t? rawResponse\n\t\t\t\t\t\t\t\t\t: new Response({ body: rawResponse, status: StatusCodes.BadRequest, headers: {} })\n\t\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t}\n\n\t#resolveSchema(method: MethodsEnum, schema: RouteDef) {\n\t\tconst defaultStatusCode = schema?.defaultStatusCode ?? StatusCodes.Ok\n\t\tconst defaultContentType = schema?.defaultContentType ?? 'application/json'\n\t\tlet status = defaultStatusCode\n\t\tlet contentType = defaultContentType\n\t\tconst jsonSchema: OpenApiSchemaDef = { response: {}, request: {} }\n\t\tconst requestPipeDefs: Pick<RouteDef, 'body' | 'headers' | 'query' | 'params' | 'cookies'> = {}\n\t\tconst responsePipeDefs: Pick<RouteDef, 'response' | 'responseHeaders' | 'responseCookies'> = {}\n\n\t\tconst defs: {\n\t\t\tkey: Exclude<keyof RouteDef, `default${string}` | 'context'>\n\t\t\ttype: keyof OpenApiSchemaDef\n\t\t\tskip?: boolean\n\t\t}[] = [\n\t\t\t{ key: 'params', type: 'request' },\n\t\t\t{ key: 'headers', type: 'request' },\n\t\t\t{ key: 'cookies', type: 'request' },\n\t\t\t{ key: 'query', type: 'request' },\n\t\t\t{ key: 'body', type: 'request', skip: !(<MethodsEnum[]>[Methods.post, Methods.put, Methods.patch]).includes(method) },\n\t\t\t{ key: 'response', type: 'response' },\n\t\t\t{ key: 'responseHeaders', type: 'response' },\n\t\t\t{ key: 'responseCookies', type: 'response' },\n\t\t]\n\t\tdefs.forEach((def) => {\n\t\t\tconst pipe = schema[def.key] ?? v.any()\n\t\t\tif (def.skip) return\n\n\t\t\tif (def.type === 'request') {\n\t\t\t\trequestPipeDefs[def.key] = pipe\n\t\t\t\tjsonSchema.request[def.key as keyof typeof jsonSchema.request] = v.schema(pipe)\n\t\t\t}\n\t\t\tif (def.type === 'response') {\n\t\t\t\tconst pipeRecords = errorsSchemas.concat({ status: defaultStatusCode, contentType, pipe })\n\t\t\t\tresponsePipeDefs[def.key] = v.any().pipe((input) => {\n\t\t\t\t\tconst p = pipeRecords.find((r) => r.status === status)?.pipe\n\t\t\t\t\tif (!p) throw PipeError.root(`schema not defined for status code: ${status}`, input)\n\t\t\t\t\treturn v.assert(p, input)\n\t\t\t\t})\n\t\t\t\tjsonSchema.response[def.key as keyof typeof jsonSchema.response] = pipeRecords.map((record) => ({\n\t\t\t\t\tstatus: record.status,\n\t\t\t\t\tcontentType: record.contentType,\n\t\t\t\t\tschema: v.schema(record.pipe),\n\t\t\t\t}))\n\t\t\t}\n\t\t})\n\t\tconst requestPipe = v.object(requestPipeDefs)\n\t\tv.compile(requestPipe, { allErrors: true })\n\t\tconst responsePipe = v.object(responsePipeDefs)\n\t\tv.compile(responsePipe, { allErrors: true })\n\t\tconst validateRequest: RequestValidator = async (request) => {\n\t\t\tif (!Object.keys(requestPipeDefs)) return request\n\t\t\tconst validity = requestLocalStorage.run(request, () =>\n\t\t\t\tv.validate(requestPipe, {\n\t\t\t\t\tparams: request.params,\n\t\t\t\t\theaders: request.headers,\n\t\t\t\t\tquery: request.query,\n\t\t\t\t\tbody: request.body,\n\t\t\t\t\tcookies: request.cookies,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\trequest.params = validity.value.params!\n\t\t\trequest.headers = validity.value.headers!\n\t\t\trequest.query = validity.value.query!\n\t\t\trequest.body = validity.value.body!\n\t\t\trequest.cookies = validity.value.cookies!\n\t\t\treturn request\n\t\t}\n\t\tconst validateResponse: ResponseValidator = async (response) => {\n\t\t\tif (!Object.keys(responsePipeDefs)) return response\n\t\t\tstatus = response.status\n\t\t\tcontentType = response.contentType\n\n\t\t\tconst validity = responseLocalStorage.run(response, () =>\n\t\t\t\tv.validate(responsePipe, {\n\t\t\t\t\tresponseHeaders: response.headers,\n\t\t\t\t\tresponseCookies: Object.fromEntries(Object.entries(response.cookies).map(([key, val]) => [key, val.value] as const)),\n\t\t\t\t\tresponse: response.body,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\tresponse.body = validity.value.response!\n\t\t\tresponse.headers = validity.value.responseHeaders!\n\t\t\tresponse.cookieValues = validity.value.responseCookies!\n\t\t\treturn response\n\t\t}\n\t\treturn {\n\t\t\tjsonSchema,\n\t\t\tvalidateRequest,\n\t\t\tvalidateResponse,\n\t\t}\n\t}\n\n\ttest() {\n\t\treturn supertest(this.server)\n\t}\n\n\tasync start() {\n\t\tconst port = this.config.port\n\t\tconst instance = Instance.get()\n\t\tconst { app } = instance.settings\n\t\tif (this.config.healthPath)\n\t\t\tthis.addRoute({\n\t\t\t\tmethod: Methods.get,\n\t\t\t\tpath: this.config.healthPath,\n\t\t\t\thandler: async (req) =>\n\t\t\t\t\treq.res({\n\t\t\t\t\t\tbody: `${instance.id}(${app.name}) service running`,\n\t\t\t\t\t\tcontentType: 'text/plain',\n\t\t\t\t\t}),\n\t\t\t})\n\n\t\tthis.implementations.registerNotFoundHandler(async (req) => {\n\t\t\tconst request = await this.implementations.parseRequest(req)\n\t\t\tthrow new NotFoundError(`Route ${request.path} not found`)\n\t\t})\n\t\tthis.implementations.registerErrorHandler(async (error, _, res) => {\n\t\t\tif (!(error instanceof EquippedError)) Instance.get().log.error({ error }, 'Uncaught error in route handler')\n\t\t\tconst response =\n\t\t\t\terror instanceof RequestError\n\t\t\t\t\t? new Response({\n\t\t\t\t\t\t\tbody: error.serializedErrors,\n\t\t\t\t\t\t\tstatus: error.statusCode,\n\t\t\t\t\t\t})\n\t\t\t\t\t: new Response({\n\t\t\t\t\t\t\tbody: [{ message: 'Something went wrong', data: error.message }],\n\t\t\t\t\t\t\tstatus: StatusCodes.BadRequest,\n\t\t\t\t\t\t})\n\t\t\treturn await this.implementations.handleResponse(res, response)\n\t\t})\n\n\t\tawait Promise.all(this.#queue.map((cb) => cb()))\n\t\tconst started = await this.implementations.start(port)\n\t\tif (started) Instance.get().log.info(`${instance.id}(${app.name}) service listening on port ${port}`)\n\t\treturn started\n\t}\n}\n",null]}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }require('cors');var _socketio = require('socket.io');var _supertest = require('supertest'); var _supertest2 = _interopRequireDefault(_supertest);var _valleyed = require('valleyed');var _indexmincjs = require('../../errors/index.min.cjs');var _indexmincjs3 = require('../../instance/index.min.cjs');var _indexmincjs5 = require('../../validations/index.min.cjs');var _valleyedmincjs = require('../../validations/valleyed.min.cjs');var _openapimincjs = require('../openapi.min.cjs');var _requestsmincjs = require('../requests.min.cjs');require('../routes');var _socketsmincjs = require('../sockets.min.cjs');var _typesmincjs = require('../types.min.cjs');const x=Object.entries(_typesmincjs.StatusCodes).filter(([,f])=>f>399).map(([f,o])=>({status:o,contentType:"application/json",pipe:_valleyed.v.meta(_valleyed.v.array(_valleyed.v.object({message:_valleyed.v.string(),field:_valleyed.v.optional(_valleyed.v.string())})),{$refId:`Errors.${f}Response`,description:`${f} Response`})}));class Y{constructor(o,s,n){this.config=s;this.implementations=n;this.server=o,this.#e=new (0, _openapimincjs.OpenApi)(s);const p=new (0, _socketio.Server)(o,{cors:this.cors});this.socket=new (0, _socketsmincjs.SocketEmitter)(p,s),this.addRouter(this.#e.router())}#t=[];#s=new Map;#e;get cors(){return{origin:_optionalChain([this, 'access', _ => _.config, 'access', _2 => _2.cors, 'optionalAccess', _3 => _3.origin]),methods:(_nullishCoalesce(_optionalChain([this, 'access', _4 => _4.config, 'access', _5 => _5.cors, 'optionalAccess', _6 => _6.methods]), () => (Object.values(_typesmincjs.Methods)))).filter(o=>o!==_typesmincjs.Methods.options).map(o=>o.toUpperCase()),credentials:_optionalChain([this, 'access', _7 => _7.config, 'access', _8 => _8.cors, 'optionalAccess', _9 => _9.credentials])}}addRouter(...o){o.map(s=>s.routes).forEach(s=>this.addRoute(...s))}addRoute(...o){o.forEach(s=>{this.#t.push(async()=>{const{method:n,path:p,schema:r={},onError:c,middlewares:d=[]}=s,i=`(${n.toUpperCase()}) ${this.#e.cleanPath(p)}`;if(this.#s.get(i))throw new (0, _indexmincjs.EquippedError)(`Route key ${i} already registered. All route keys must be unique`,{route:s,key:i});d.forEach(h=>_optionalChain([h, 'access', _10 => _10.onSetup, 'optionalCall', _11 => _11(s)])),_optionalChain([c, 'optionalAccess', _12 => _12.onSetup, 'optionalCall', _13 => _13(s)]);const{validateRequest:R,validateResponse:q,jsonSchema:v}=this.#o(n,r);this.#s.set(i,!0),await this.#e.register(s,v),this.implementations.registerRoute(n,this.#e.cleanPath(p),async(h,w)=>{const g=await R(await this.implementations.parseRequest(h));try{for(const u of d)await u.cb(g,this.config);const e=await s.handler(g,this.config),t=e instanceof _requestsmincjs.Response?e:new (0, _requestsmincjs.Response)({body:e,status:_typesmincjs.StatusCodes.Ok,headers:{},piped:!1});return await this.implementations.handleResponse(w,await q(t))}catch(e){if(_optionalChain([c, 'optionalAccess', _14 => _14.cb])){const t=await c.cb(g,this.config,e),u=t instanceof _requestsmincjs.Response?t:new (0, _requestsmincjs.Response)({body:t,status:_typesmincjs.StatusCodes.BadRequest,headers:{}});return await this.implementations.handleResponse(w,await q(u))}throw e}})})})}#o(o,s){const n=_nullishCoalesce(_optionalChain([s, 'optionalAccess', _15 => _15.defaultStatusCode]), () => (_typesmincjs.StatusCodes.Ok)),p=_nullishCoalesce(_optionalChain([s, 'optionalAccess', _16 => _16.defaultContentType]), () => ("application/json"));let r=n,c=p;const d={response:{},request:{}},i={},R={};[{key:"params",type:"request"},{key:"headers",type:"request"},{key:"cookies",type:"request"},{key:"query",type:"request"},{key:"body",type:"request",skip:![_typesmincjs.Methods.post,_typesmincjs.Methods.put,_typesmincjs.Methods.patch].includes(o)},{key:"response",type:"response"},{key:"responseHeaders",type:"response"},{key:"responseCookies",type:"response"}].forEach(e=>{const t=_nullishCoalesce(s[e.key], () => (_valleyed.v.any()));if(!e.skip&&(e.type==="request"&&(i[e.key]=t,d.request[e.key]=_valleyed.v.schema(t)),e.type==="response")){const u=x.concat({status:n,contentType:c,pipe:t});R[e.key]=_valleyed.v.any().pipe(m=>{const E=_optionalChain([u, 'access', _17 => _17.find, 'call', _18 => _18(P=>P.status===r), 'optionalAccess', _19 => _19.pipe]);if(!E)throw _valleyed.PipeError.root(`schema not defined for status code: ${r}`,m);return _valleyed.v.assert(E,m)}),d.response[e.key]=u.map(m=>({status:m.status,contentType:m.contentType,schema:_valleyed.v.schema(m.pipe)}))}});const v=_valleyed.v.object(i);_valleyed.v.compile(v,{allErrors:!0});const h=_valleyed.v.object(R);return _valleyed.v.compile(h,{allErrors:!0}),{jsonSchema:d,validateRequest:async e=>{if(!Object.keys(i))return e;const t=_valleyedmincjs.requestLocalStorage.run(e,()=>_valleyed.v.validate(v,{params:e.params,headers:e.headers,query:e.query,body:e.body,cookies:e.cookies}));if(!t.valid)throw _indexmincjs5.pipeErrorToValidationError.call(void 0, t.error);return e.params=t.value.params,e.headers=t.value.headers,e.query=t.value.query,e.body=t.value.body,e.cookies=t.value.cookies,e},validateResponse:async e=>{if(!Object.keys(R))return e;r=e.status,c=e.contentType;const t=_valleyedmincjs.responseLocalStorage.run(e,()=>_valleyed.v.validate(h,{responseHeaders:e.headers,responseCookies:Object.fromEntries(Object.entries(e.cookies).map(([u,m])=>[u,m.value])),response:e.body}));if(!t.valid)throw _indexmincjs5.pipeErrorToValidationError.call(void 0, t.error);return e.body=t.value.response,e.headers=t.value.responseHeaders,e.cookieValues=t.value.responseCookies,e}}}test(){return _supertest2.default.call(void 0, this.server)}async start(){const o=this.config.port,s=_indexmincjs3.Instance.get(),{app:n}=s.settings;this.config.healthPath&&this.addRoute({method:_typesmincjs.Methods.get,path:this.config.healthPath,handler:async r=>r.res({body:`${s.id}(${n.name}) service running`,contentType:"text/plain"})}),this.implementations.registerNotFoundHandler(async r=>{const c=await this.implementations.parseRequest(r);throw new (0, _indexmincjs.NotFoundError)(`Route ${c.path} not found`)}),this.implementations.registerErrorHandler(async(r,c,d)=>{_indexmincjs3.Instance.get().log.error({error:r},"Uncaught error in route handler");const i=r instanceof _indexmincjs.RequestError?new (0, _requestsmincjs.Response)({body:r.serializedErrors,status:r.statusCode}):new (0, _requestsmincjs.Response)({body:[{message:"Something went wrong",data:r.message}],status:_typesmincjs.StatusCodes.BadRequest});return await this.implementations.handleResponse(d,i)}),await Promise.all(this.#t.map(r=>r()));const p=await this.implementations.start(o);return p&&_indexmincjs3.Instance.get().log.info(`${s.id}(${n.name}) service listening on port ${o}`),p}}exports.Server = Y;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }require('@fastify/cors');require('cors');var _socketio = require('socket.io');var _supertest = require('supertest'); var _supertest2 = _interopRequireDefault(_supertest);var _valleyed = require('valleyed');var _indexmincjs = require('../../errors/index.min.cjs');var _indexmincjs3 = require('../../instance/index.min.cjs');var _indexmincjs5 = require('../../validations/index.min.cjs');var _valleyedmincjs = require('../../validations/valleyed.min.cjs');var _openapimincjs = require('../openapi.min.cjs');var _requestsmincjs = require('../requests.min.cjs');require('../routes');var _socketsmincjs = require('../sockets.min.cjs');var _typesmincjs = require('../types.min.cjs');const x=Object.entries(_typesmincjs.StatusCodes).filter(([,f])=>f>399).map(([f,o])=>({status:o,contentType:"application/json",pipe:_valleyed.v.meta(_valleyed.v.array(_valleyed.v.object({message:_valleyed.v.string(),field:_valleyed.v.optional(_valleyed.v.string())})),{$refId:`Errors.${f}Response`,description:`${f} Response`})}));class Z{constructor(o,t,n){this.config=t;this.implementations=n;this.server=o,this.#e=new (0, _openapimincjs.OpenApi)(t);const p=new (0, _socketio.Server)(o,{cors:this.cors});this.socket=new (0, _socketsmincjs.SocketEmitter)(p,t),this.addRouter(this.#e.router())}#t=[];#s=new Map;#e;get cors(){return{origin:_optionalChain([this, 'access', _ => _.config, 'access', _2 => _2.cors, 'optionalAccess', _3 => _3.origin])?(o,t)=>t(null,!0):_optionalChain([this, 'access', _4 => _4.config, 'access', _5 => _5.cors, 'optionalAccess', _6 => _6.origin]),methods:(_nullishCoalesce(_optionalChain([this, 'access', _7 => _7.config, 'access', _8 => _8.cors, 'optionalAccess', _9 => _9.methods]), () => (Object.values(_typesmincjs.Methods)))).filter(o=>o!==_typesmincjs.Methods.options).map(o=>o.toUpperCase()),credentials:_optionalChain([this, 'access', _10 => _10.config, 'access', _11 => _11.cors, 'optionalAccess', _12 => _12.credentials])}}addRouter(...o){o.map(t=>t.routes).forEach(t=>this.addRoute(...t))}addRoute(...o){o.forEach(t=>{this.#t.push(async()=>{const{method:n,path:p,schema:r={},onError:c,middlewares:d=[]}=t,i=`(${n.toUpperCase()}) ${this.#e.cleanPath(p)}`;if(this.#s.get(i))throw new (0, _indexmincjs.EquippedError)(`Route key ${i} already registered. All route keys must be unique`,{route:t,key:i});d.forEach(h=>_optionalChain([h, 'access', _13 => _13.onSetup, 'optionalCall', _14 => _14(t)])),_optionalChain([c, 'optionalAccess', _15 => _15.onSetup, 'optionalCall', _16 => _16(t)]);const{validateRequest:R,validateResponse:q,jsonSchema:g}=this.#o(n,r);this.#s.set(i,!0),await this.#e.register(t,g),this.implementations.registerRoute(n,this.#e.cleanPath(p),async(h,w)=>{const v=await R(await this.implementations.parseRequest(h));try{for(const u of d)await u.cb(v,this.config);const e=await t.handler(v,this.config),s=e instanceof _requestsmincjs.Response?e:new (0, _requestsmincjs.Response)({body:e,status:_typesmincjs.StatusCodes.Ok,headers:{},piped:!1});return await this.implementations.handleResponse(w,await q(s))}catch(e){if(_optionalChain([c, 'optionalAccess', _17 => _17.cb])){const s=await c.cb(v,this.config,e),u=s instanceof _requestsmincjs.Response?s:new (0, _requestsmincjs.Response)({body:s,status:_typesmincjs.StatusCodes.BadRequest,headers:{}});return await this.implementations.handleResponse(w,await q(u))}throw e}})})})}#o(o,t){const n=_nullishCoalesce(_optionalChain([t, 'optionalAccess', _18 => _18.defaultStatusCode]), () => (_typesmincjs.StatusCodes.Ok)),p=_nullishCoalesce(_optionalChain([t, 'optionalAccess', _19 => _19.defaultContentType]), () => ("application/json"));let r=n,c=p;const d={response:{},request:{}},i={},R={};[{key:"params",type:"request"},{key:"headers",type:"request"},{key:"cookies",type:"request"},{key:"query",type:"request"},{key:"body",type:"request",skip:![_typesmincjs.Methods.post,_typesmincjs.Methods.put,_typesmincjs.Methods.patch].includes(o)},{key:"response",type:"response"},{key:"responseHeaders",type:"response"},{key:"responseCookies",type:"response"}].forEach(e=>{const s=_nullishCoalesce(t[e.key], () => (_valleyed.v.any()));if(!e.skip&&(e.type==="request"&&(i[e.key]=s,d.request[e.key]=_valleyed.v.schema(s)),e.type==="response")){const u=x.concat({status:n,contentType:c,pipe:s});R[e.key]=_valleyed.v.any().pipe(m=>{const E=_optionalChain([u, 'access', _20 => _20.find, 'call', _21 => _21(C=>C.status===r), 'optionalAccess', _22 => _22.pipe]);if(!E)throw _valleyed.PipeError.root(`schema not defined for status code: ${r}`,m);return _valleyed.v.assert(E,m)}),d.response[e.key]=u.map(m=>({status:m.status,contentType:m.contentType,schema:_valleyed.v.schema(m.pipe)}))}});const g=_valleyed.v.object(i);_valleyed.v.compile(g,{allErrors:!0});const h=_valleyed.v.object(R);return _valleyed.v.compile(h,{allErrors:!0}),{jsonSchema:d,validateRequest:async e=>{if(!Object.keys(i))return e;const s=_valleyedmincjs.requestLocalStorage.run(e,()=>_valleyed.v.validate(g,{params:e.params,headers:e.headers,query:e.query,body:e.body,cookies:e.cookies}));if(!s.valid)throw _indexmincjs5.pipeErrorToValidationError.call(void 0, s.error);return e.params=s.value.params,e.headers=s.value.headers,e.query=s.value.query,e.body=s.value.body,e.cookies=s.value.cookies,e},validateResponse:async e=>{if(!Object.keys(R))return e;r=e.status,c=e.contentType;const s=_valleyedmincjs.responseLocalStorage.run(e,()=>_valleyed.v.validate(h,{responseHeaders:e.headers,responseCookies:Object.fromEntries(Object.entries(e.cookies).map(([u,m])=>[u,m.value])),response:e.body}));if(!s.valid)throw _indexmincjs5.pipeErrorToValidationError.call(void 0, s.error);return e.body=s.value.response,e.headers=s.value.responseHeaders,e.cookieValues=s.value.responseCookies,e}}}test(){return _supertest2.default.call(void 0, this.server)}async start(){const o=this.config.port,t=_indexmincjs3.Instance.get(),{app:n}=t.settings;this.config.healthPath&&this.addRoute({method:_typesmincjs.Methods.get,path:this.config.healthPath,handler:async r=>r.res({body:`${t.id}(${n.name}) service running`,contentType:"text/plain"})}),this.implementations.registerNotFoundHandler(async r=>{const c=await this.implementations.parseRequest(r);throw new (0, _indexmincjs.NotFoundError)(`Route ${c.path} not found`)}),this.implementations.registerErrorHandler(async(r,c,d)=>{r instanceof _indexmincjs.EquippedError||_indexmincjs3.Instance.get().log.error({error:r},"Uncaught error in route handler");const i=r instanceof _indexmincjs.RequestError?new (0, _requestsmincjs.Response)({body:r.serializedErrors,status:r.statusCode}):new (0, _requestsmincjs.Response)({body:[{message:"Something went wrong",data:r.message}],status:_typesmincjs.StatusCodes.BadRequest});return await this.implementations.handleResponse(d,i)}),await Promise.all(this.#t.map(r=>r()));const p=await this.implementations.start(o);return p&&_indexmincjs3.Instance.get().log.info(`${t.id}(${n.name}) service listening on port ${o}`),p}}exports.Server = Z;
2
2
  //# sourceMappingURL=base.min.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/server/impls/base.ts"],"names":["v","server","config","implementations"],"mappings":"AAEA,iyBAAiC,qCACM,4FACjB,oCACkB,yDAG/B,4DACA,+DACqB,oEAGP,mDAEvB,qDACS,qBAAsD,mDAM7D,+CAGa,MAAA,CAAA,CAAA,MACb,CAAA,OAAQ,CAAA,wBAAA,CAAKA,CAAAA,MAAE,CAAMA,CAAAA,CAAE,CAAA,CAAA,CAAA,CAAA,EAAA,CAAO,CAAE,GAAA,CAAA,CAAA,GAASA,CAAAA,CAAE,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAO,CAAG,CAAA,MAAOA,CAAE,CAAA,CAAA,WAAW,CAAA,kBAChE,CAAA,IAAA,CAAA,WAAA,CAAA,IAAa,CAAA,WAAA,CAAA,KAAA,CAAA,WACrB,CAAA,MAAA,CAAA,CAAA,OAAmB,CAAA,WAAA,CAAA,MAAA,CAAA,CACpB,CAAC,KAGI,CAAA,WAAA,CAAA,QAcN,CAAA,WAAA,CAAA,MACCC,CAAAA,CACQC,CAAAA,CACAC,CAAAA,CAQP,CATO,CAAA,MAAA,CAAA,CAAA,OACA,EAAA,CAAA,CAAA,QAAA,CAAA,CAAA,WASR,CAAK,CAAA,EAAA","file":"/home/runner/work/equipped/equipped/dist/cjs/server/impls/base.min.cjs","sourcesContent":["import type http from 'node:http'\n\nimport { type CorsOptions } from 'cors'\nimport { Server as SocketServer } from 'socket.io'\nimport supertest from 'supertest'\nimport { type Pipe, PipeError, v } from 'valleyed'\n\nimport { EquippedError, NotFoundError, RequestError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { pipeErrorToValidationError } from '../../validations'\nimport { requestLocalStorage, responseLocalStorage } from '../../validations/valleyed'\nimport { OpenApi, type OpenApiSchemaDef } from '../openapi'\nimport type { ServerConfig } from '../pipes'\nimport { type Request, Response } from '../requests'\nimport { Router } from '../routes'\nimport { SocketEmitter } from '../sockets'\nimport { Methods, type MethodsEnum, type Route, type RouteDef, StatusCodes } from '../types'\n\ntype RequestValidator = (req: Request<any>) => Promise<Request<any>>\ntype ResponseValidator = (res: Response<any>) => Promise<Response<any>>\n\nconst errorsSchemas = Object.entries(StatusCodes)\n\t.filter(([, value]) => value > 399)\n\t.map(([key, value]) => ({\n\t\tstatus: value,\n\t\tcontentType: 'application/json',\n\t\tpipe: v.meta(v.array(v.object({ message: v.string(), field: v.optional(v.string()) })), {\n\t\t\t$refId: `Errors.${key}Response`,\n\t\t\tdescription: `${key} Response`,\n\t\t}) as Pipe<any, any>,\n\t}))\n\nexport abstract class Server<Req = any, Res = any> {\n\t#queue: (() => void | Promise<void>)[] = []\n\t#routesByKey = new Map<string, boolean>()\n\t#openapi: OpenApi\n\tsocket: SocketEmitter\n\tprotected server: http.Server\n\tprotected get cors() {\n\t\treturn {\n\t\t\torigin: this.config.cors?.origin,\n\t\t\tmethods: (this.config.cors?.methods ?? Object.values(Methods)).filter((m) => m !== Methods.options).map((m) => m.toUpperCase()),\n\t\t\tcredentials: this.config.cors?.credentials,\n\t\t} satisfies CorsOptions\n\t}\n\n\tconstructor(\n\t\tserver: http.Server,\n\t\tprivate config: ServerConfig,\n\t\tprivate implementations: {\n\t\t\tparseRequest: (req: Req) => Promise<Request<any>>\n\t\t\thandleResponse: (res: Res, response: Response<any>) => Promise<void>\n\t\t\tregisterRoute: (method: MethodsEnum, path: string, cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterErrorHandler: (cb: (error: Error, req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterNotFoundHandler: (cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tstart: (port: number) => Promise<boolean>\n\t\t},\n\t) {\n\t\tthis.server = server\n\t\tthis.#openapi = new OpenApi(config)\n\t\tconst socketInstance = new SocketServer(server, { cors: this.cors })\n\t\tthis.socket = new SocketEmitter(socketInstance, config)\n\t\tthis.addRouter(this.#openapi.router())\n\t}\n\n\taddRouter(...routers: Router<any>[]) {\n\t\trouters.map((router) => router.routes).forEach((routes) => this.addRoute(...routes))\n\t}\n\n\taddRoute<T extends RouteDef>(...routes: Route<T>[]) {\n\t\troutes.forEach((route) => {\n\t\t\tthis.#queue.push(async () => {\n\t\t\t\tconst { method, path, schema = {}, onError, middlewares = [] } = route\n\n\t\t\t\tconst key = `(${method.toUpperCase()}) ${this.#openapi.cleanPath(path)}`\n\t\t\t\tif (this.#routesByKey.get(key))\n\t\t\t\t\tthrow new EquippedError(`Route key ${key} already registered. All route keys must be unique`, { route, key })\n\n\t\t\t\tmiddlewares.forEach((m) => m.onSetup?.(route as any))\n\t\t\t\tonError?.onSetup?.(route as any)\n\n\t\t\t\tconst { validateRequest, validateResponse, jsonSchema } = this.#resolveSchema(method, schema)\n\n\t\t\t\tthis.#routesByKey.set(key, true)\n\t\t\t\tawait this.#openapi.register(route, jsonSchema)\n\t\t\t\tthis.implementations.registerRoute(method, this.#openapi.cleanPath(path), async (req: Req, res: Res) => {\n\t\t\t\t\tconst request = await validateRequest(await this.implementations.parseRequest(req))\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor (const middleware of middlewares) await middleware.cb(request, this.config)\n\t\t\t\t\t\tconst rawRes = await route.handler(request, this.config)\n\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\trawRes instanceof Response\n\t\t\t\t\t\t\t\t? rawRes\n\t\t\t\t\t\t\t\t: new Response({ body: rawRes, status: StatusCodes.Ok, headers: {}, piped: false })\n\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (onError?.cb) {\n\t\t\t\t\t\t\tconst rawResponse = await onError.cb(request, this.config, error as Error)\n\t\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\t\trawResponse instanceof Response\n\t\t\t\t\t\t\t\t\t? rawResponse\n\t\t\t\t\t\t\t\t\t: new Response({ body: rawResponse, status: StatusCodes.BadRequest, headers: {} })\n\t\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t}\n\n\t#resolveSchema(method: MethodsEnum, schema: RouteDef) {\n\t\tconst defaultStatusCode = schema?.defaultStatusCode ?? StatusCodes.Ok\n\t\tconst defaultContentType = schema?.defaultContentType ?? 'application/json'\n\t\tlet status = defaultStatusCode\n\t\tlet contentType = defaultContentType\n\t\tconst jsonSchema: OpenApiSchemaDef = { response: {}, request: {} }\n\t\tconst requestPipeDefs: Pick<RouteDef, 'body' | 'headers' | 'query' | 'params' | 'cookies'> = {}\n\t\tconst responsePipeDefs: Pick<RouteDef, 'response' | 'responseHeaders' | 'responseCookies'> = {}\n\n\t\tconst defs: {\n\t\t\tkey: Exclude<keyof RouteDef, `default${string}` | 'context'>\n\t\t\ttype: keyof OpenApiSchemaDef\n\t\t\tskip?: boolean\n\t\t}[] = [\n\t\t\t{ key: 'params', type: 'request' },\n\t\t\t{ key: 'headers', type: 'request' },\n\t\t\t{ key: 'cookies', type: 'request' },\n\t\t\t{ key: 'query', type: 'request' },\n\t\t\t{ key: 'body', type: 'request', skip: !(<MethodsEnum[]>[Methods.post, Methods.put, Methods.patch]).includes(method) },\n\t\t\t{ key: 'response', type: 'response' },\n\t\t\t{ key: 'responseHeaders', type: 'response' },\n\t\t\t{ key: 'responseCookies', type: 'response' },\n\t\t]\n\t\tdefs.forEach((def) => {\n\t\t\tconst pipe = schema[def.key] ?? v.any()\n\t\t\tif (def.skip) return\n\n\t\t\tif (def.type === 'request') {\n\t\t\t\trequestPipeDefs[def.key] = pipe\n\t\t\t\tjsonSchema.request[def.key as keyof typeof jsonSchema.request] = v.schema(pipe)\n\t\t\t}\n\t\t\tif (def.type === 'response') {\n\t\t\t\tconst pipeRecords = errorsSchemas.concat({ status: defaultStatusCode, contentType, pipe })\n\t\t\t\tresponsePipeDefs[def.key] = v.any().pipe((input) => {\n\t\t\t\t\tconst p = pipeRecords.find((r) => r.status === status)?.pipe\n\t\t\t\t\tif (!p) throw PipeError.root(`schema not defined for status code: ${status}`, input)\n\t\t\t\t\treturn v.assert(p, input)\n\t\t\t\t})\n\t\t\t\tjsonSchema.response[def.key as keyof typeof jsonSchema.response] = pipeRecords.map((record) => ({\n\t\t\t\t\tstatus: record.status,\n\t\t\t\t\tcontentType: record.contentType,\n\t\t\t\t\tschema: v.schema(record.pipe),\n\t\t\t\t}))\n\t\t\t}\n\t\t})\n\t\tconst requestPipe = v.object(requestPipeDefs)\n\t\tv.compile(requestPipe, { allErrors: true })\n\t\tconst responsePipe = v.object(responsePipeDefs)\n\t\tv.compile(responsePipe, { allErrors: true })\n\t\tconst validateRequest: RequestValidator = async (request) => {\n\t\t\tif (!Object.keys(requestPipeDefs)) return request\n\t\t\tconst validity = requestLocalStorage.run(request, () =>\n\t\t\t\tv.validate(requestPipe, {\n\t\t\t\t\tparams: request.params,\n\t\t\t\t\theaders: request.headers,\n\t\t\t\t\tquery: request.query,\n\t\t\t\t\tbody: request.body,\n\t\t\t\t\tcookies: request.cookies,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\trequest.params = validity.value.params!\n\t\t\trequest.headers = validity.value.headers!\n\t\t\trequest.query = validity.value.query!\n\t\t\trequest.body = validity.value.body!\n\t\t\trequest.cookies = validity.value.cookies!\n\t\t\treturn request\n\t\t}\n\t\tconst validateResponse: ResponseValidator = async (response) => {\n\t\t\tif (!Object.keys(responsePipeDefs)) return response\n\t\t\tstatus = response.status\n\t\t\tcontentType = response.contentType\n\n\t\t\tconst validity = responseLocalStorage.run(response, () =>\n\t\t\t\tv.validate(responsePipe, {\n\t\t\t\t\tresponseHeaders: response.headers,\n\t\t\t\t\tresponseCookies: Object.fromEntries(Object.entries(response.cookies).map(([key, val]) => [key, val.value] as const)),\n\t\t\t\t\tresponse: response.body,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\tresponse.body = validity.value.response!\n\t\t\tresponse.headers = validity.value.responseHeaders!\n\t\t\tresponse.cookieValues = validity.value.responseCookies!\n\t\t\treturn response\n\t\t}\n\t\treturn {\n\t\t\tjsonSchema,\n\t\t\tvalidateRequest,\n\t\t\tvalidateResponse,\n\t\t}\n\t}\n\n\ttest() {\n\t\treturn supertest(this.server)\n\t}\n\n\tasync start() {\n\t\tconst port = this.config.port\n\t\tconst instance = Instance.get()\n\t\tconst { app } = instance.settings\n\t\tif (this.config.healthPath)\n\t\t\tthis.addRoute({\n\t\t\t\tmethod: Methods.get,\n\t\t\t\tpath: this.config.healthPath,\n\t\t\t\thandler: async (req) =>\n\t\t\t\t\treq.res({\n\t\t\t\t\t\tbody: `${instance.id}(${app.name}) service running`,\n\t\t\t\t\t\tcontentType: 'text/plain',\n\t\t\t\t\t}),\n\t\t\t})\n\n\t\tthis.implementations.registerNotFoundHandler(async (req) => {\n\t\t\tconst request = await this.implementations.parseRequest(req)\n\t\t\tthrow new NotFoundError(`Route ${request.path} not found`)\n\t\t})\n\t\tthis.implementations.registerErrorHandler(async (error, _, res) => {\n\t\t\tInstance.get().log.error({ error }, 'Uncaught error in route handler')\n\t\t\tconst response =\n\t\t\t\terror instanceof RequestError\n\t\t\t\t\t? new Response({\n\t\t\t\t\t\t\tbody: error.serializedErrors,\n\t\t\t\t\t\t\tstatus: error.statusCode,\n\t\t\t\t\t\t})\n\t\t\t\t\t: new Response({\n\t\t\t\t\t\t\tbody: [{ message: 'Something went wrong', data: error.message }],\n\t\t\t\t\t\t\tstatus: StatusCodes.BadRequest,\n\t\t\t\t\t\t})\n\t\t\treturn await this.implementations.handleResponse(res, response)\n\t\t})\n\n\t\tawait Promise.all(this.#queue.map((cb) => cb()))\n\t\tconst started = await this.implementations.start(port)\n\t\tif (started) Instance.get().log.info(`${instance.id}(${app.name}) service listening on port ${port}`)\n\t\treturn started\n\t}\n}\n"]}
1
+ {"version":3,"sources":["../../../../src/server/impls/base.ts"],"names":["v","server","config","implementations"],"mappings":"AAEA,0yBAAwC,gBACP,qCACM,4FACjB,oCACkB,yDAG/B,4DACA,+DACqB,oEAGP,mDAEvB,qDACS,qBAAsD,mDAM7D,+CAGa,MAAA,CAAA,CAAA,MACb,CAAA,OAAQ,CAAA,wBAAA,CAAKA,CAAAA,MAAE,CAAMA,CAAAA,CAAE,CAAA,CAAA,CAAA,CAAA,EAAA,CAAO,CAAE,GAAA,CAAA,CAAA,GAASA,CAAAA,CAAE,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAO,CAAG,CAAA,MAAOA,CAAE,CAAA,CAAA,WAAW,CAAA,kBAChE,CAAA,IAAA,CAAA,WAAA,CAAA,IAAa,CAAA,WAAA,CAAA,KAAA,CAAA,WACrB,CAAA,MAAA,CAAA,CAAA,OAAmB,CAAA,WAAA,CAAA,MAAA,CAAA,CACpB,CAAC,KAGI,CAAA,WAAA,CAAA,QAcN,CAAA,WAAA,CAAA,MACCC,CAAAA,CACQC,CAAAA,CACAC,CAAAA,CAQP,CATO,CAAA,MAAA,CAAA,CAAA,OACA,EAAA,CAAA,CAAA,QAAA,CAAA,CAAA,WASR,CAAK,CAAA,EAAA","file":"/home/runner/work/equipped/equipped/dist/cjs/server/impls/base.min.cjs","sourcesContent":["import type http from 'node:http'\n\nimport { type FastifyCorsOptions } from '@fastify/cors'\nimport { type CorsOptions } from 'cors'\nimport { Server as SocketServer } from 'socket.io'\nimport supertest from 'supertest'\nimport { type Pipe, PipeError, v } from 'valleyed'\n\nimport { EquippedError, NotFoundError, RequestError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { pipeErrorToValidationError } from '../../validations'\nimport { requestLocalStorage, responseLocalStorage } from '../../validations/valleyed'\nimport { OpenApi, type OpenApiSchemaDef } from '../openapi'\nimport type { ServerConfig } from '../pipes'\nimport { type Request, Response } from '../requests'\nimport { Router } from '../routes'\nimport { SocketEmitter } from '../sockets'\nimport { Methods, type MethodsEnum, type Route, type RouteDef, StatusCodes } from '../types'\n\ntype RequestValidator = (req: Request<any>) => Promise<Request<any>>\ntype ResponseValidator = (res: Response<any>) => Promise<Response<any>>\n\nconst errorsSchemas = Object.entries(StatusCodes)\n\t.filter(([, value]) => value > 399)\n\t.map(([key, value]) => ({\n\t\tstatus: value,\n\t\tcontentType: 'application/json',\n\t\tpipe: v.meta(v.array(v.object({ message: v.string(), field: v.optional(v.string()) })), {\n\t\t\t$refId: `Errors.${key}Response`,\n\t\t\tdescription: `${key} Response`,\n\t\t}) as Pipe<any, any>,\n\t}))\n\nexport abstract class Server<Req = any, Res = any> {\n\t#queue: (() => void | Promise<void>)[] = []\n\t#routesByKey = new Map<string, boolean>()\n\t#openapi: OpenApi\n\tsocket: SocketEmitter\n\tprotected server: http.Server\n\tprotected get cors(): CorsOptions & FastifyCorsOptions {\n\t\treturn {\n\t\t\torigin: this.config.cors?.origin ? (_, cb) => cb(null, true) : this.config.cors?.origin,\n\t\t\tmethods: (this.config.cors?.methods ?? Object.values(Methods)).filter((m) => m !== Methods.options).map((m) => m.toUpperCase()),\n\t\t\tcredentials: this.config.cors?.credentials,\n\t\t}\n\t}\n\n\tconstructor(\n\t\tserver: http.Server,\n\t\tprivate config: ServerConfig,\n\t\tprivate implementations: {\n\t\t\tparseRequest: (req: Req) => Promise<Request<any>>\n\t\t\thandleResponse: (res: Res, response: Response<any>) => Promise<void>\n\t\t\tregisterRoute: (method: MethodsEnum, path: string, cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterErrorHandler: (cb: (error: Error, req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterNotFoundHandler: (cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tstart: (port: number) => Promise<boolean>\n\t\t},\n\t) {\n\t\tthis.server = server\n\t\tthis.#openapi = new OpenApi(config)\n\t\tconst socketInstance = new SocketServer(server, { cors: this.cors })\n\t\tthis.socket = new SocketEmitter(socketInstance, config)\n\t\tthis.addRouter(this.#openapi.router())\n\t}\n\n\taddRouter(...routers: Router<any>[]) {\n\t\trouters.map((router) => router.routes).forEach((routes) => this.addRoute(...routes))\n\t}\n\n\taddRoute<T extends RouteDef>(...routes: Route<T>[]) {\n\t\troutes.forEach((route) => {\n\t\t\tthis.#queue.push(async () => {\n\t\t\t\tconst { method, path, schema = {}, onError, middlewares = [] } = route\n\n\t\t\t\tconst key = `(${method.toUpperCase()}) ${this.#openapi.cleanPath(path)}`\n\t\t\t\tif (this.#routesByKey.get(key))\n\t\t\t\t\tthrow new EquippedError(`Route key ${key} already registered. All route keys must be unique`, { route, key })\n\n\t\t\t\tmiddlewares.forEach((m) => m.onSetup?.(route as any))\n\t\t\t\tonError?.onSetup?.(route as any)\n\n\t\t\t\tconst { validateRequest, validateResponse, jsonSchema } = this.#resolveSchema(method, schema)\n\n\t\t\t\tthis.#routesByKey.set(key, true)\n\t\t\t\tawait this.#openapi.register(route, jsonSchema)\n\t\t\t\tthis.implementations.registerRoute(method, this.#openapi.cleanPath(path), async (req: Req, res: Res) => {\n\t\t\t\t\tconst request = await validateRequest(await this.implementations.parseRequest(req))\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor (const middleware of middlewares) await middleware.cb(request, this.config)\n\t\t\t\t\t\tconst rawRes = await route.handler(request, this.config)\n\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\trawRes instanceof Response\n\t\t\t\t\t\t\t\t? rawRes\n\t\t\t\t\t\t\t\t: new Response({ body: rawRes, status: StatusCodes.Ok, headers: {}, piped: false })\n\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (onError?.cb) {\n\t\t\t\t\t\t\tconst rawResponse = await onError.cb(request, this.config, error as Error)\n\t\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\t\trawResponse instanceof Response\n\t\t\t\t\t\t\t\t\t? rawResponse\n\t\t\t\t\t\t\t\t\t: new Response({ body: rawResponse, status: StatusCodes.BadRequest, headers: {} })\n\t\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t}\n\n\t#resolveSchema(method: MethodsEnum, schema: RouteDef) {\n\t\tconst defaultStatusCode = schema?.defaultStatusCode ?? StatusCodes.Ok\n\t\tconst defaultContentType = schema?.defaultContentType ?? 'application/json'\n\t\tlet status = defaultStatusCode\n\t\tlet contentType = defaultContentType\n\t\tconst jsonSchema: OpenApiSchemaDef = { response: {}, request: {} }\n\t\tconst requestPipeDefs: Pick<RouteDef, 'body' | 'headers' | 'query' | 'params' | 'cookies'> = {}\n\t\tconst responsePipeDefs: Pick<RouteDef, 'response' | 'responseHeaders' | 'responseCookies'> = {}\n\n\t\tconst defs: {\n\t\t\tkey: Exclude<keyof RouteDef, `default${string}` | 'context'>\n\t\t\ttype: keyof OpenApiSchemaDef\n\t\t\tskip?: boolean\n\t\t}[] = [\n\t\t\t{ key: 'params', type: 'request' },\n\t\t\t{ key: 'headers', type: 'request' },\n\t\t\t{ key: 'cookies', type: 'request' },\n\t\t\t{ key: 'query', type: 'request' },\n\t\t\t{ key: 'body', type: 'request', skip: !(<MethodsEnum[]>[Methods.post, Methods.put, Methods.patch]).includes(method) },\n\t\t\t{ key: 'response', type: 'response' },\n\t\t\t{ key: 'responseHeaders', type: 'response' },\n\t\t\t{ key: 'responseCookies', type: 'response' },\n\t\t]\n\t\tdefs.forEach((def) => {\n\t\t\tconst pipe = schema[def.key] ?? v.any()\n\t\t\tif (def.skip) return\n\n\t\t\tif (def.type === 'request') {\n\t\t\t\trequestPipeDefs[def.key] = pipe\n\t\t\t\tjsonSchema.request[def.key as keyof typeof jsonSchema.request] = v.schema(pipe)\n\t\t\t}\n\t\t\tif (def.type === 'response') {\n\t\t\t\tconst pipeRecords = errorsSchemas.concat({ status: defaultStatusCode, contentType, pipe })\n\t\t\t\tresponsePipeDefs[def.key] = v.any().pipe((input) => {\n\t\t\t\t\tconst p = pipeRecords.find((r) => r.status === status)?.pipe\n\t\t\t\t\tif (!p) throw PipeError.root(`schema not defined for status code: ${status}`, input)\n\t\t\t\t\treturn v.assert(p, input)\n\t\t\t\t})\n\t\t\t\tjsonSchema.response[def.key as keyof typeof jsonSchema.response] = pipeRecords.map((record) => ({\n\t\t\t\t\tstatus: record.status,\n\t\t\t\t\tcontentType: record.contentType,\n\t\t\t\t\tschema: v.schema(record.pipe),\n\t\t\t\t}))\n\t\t\t}\n\t\t})\n\t\tconst requestPipe = v.object(requestPipeDefs)\n\t\tv.compile(requestPipe, { allErrors: true })\n\t\tconst responsePipe = v.object(responsePipeDefs)\n\t\tv.compile(responsePipe, { allErrors: true })\n\t\tconst validateRequest: RequestValidator = async (request) => {\n\t\t\tif (!Object.keys(requestPipeDefs)) return request\n\t\t\tconst validity = requestLocalStorage.run(request, () =>\n\t\t\t\tv.validate(requestPipe, {\n\t\t\t\t\tparams: request.params,\n\t\t\t\t\theaders: request.headers,\n\t\t\t\t\tquery: request.query,\n\t\t\t\t\tbody: request.body,\n\t\t\t\t\tcookies: request.cookies,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\trequest.params = validity.value.params!\n\t\t\trequest.headers = validity.value.headers!\n\t\t\trequest.query = validity.value.query!\n\t\t\trequest.body = validity.value.body!\n\t\t\trequest.cookies = validity.value.cookies!\n\t\t\treturn request\n\t\t}\n\t\tconst validateResponse: ResponseValidator = async (response) => {\n\t\t\tif (!Object.keys(responsePipeDefs)) return response\n\t\t\tstatus = response.status\n\t\t\tcontentType = response.contentType\n\n\t\t\tconst validity = responseLocalStorage.run(response, () =>\n\t\t\t\tv.validate(responsePipe, {\n\t\t\t\t\tresponseHeaders: response.headers,\n\t\t\t\t\tresponseCookies: Object.fromEntries(Object.entries(response.cookies).map(([key, val]) => [key, val.value] as const)),\n\t\t\t\t\tresponse: response.body,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\tresponse.body = validity.value.response!\n\t\t\tresponse.headers = validity.value.responseHeaders!\n\t\t\tresponse.cookieValues = validity.value.responseCookies!\n\t\t\treturn response\n\t\t}\n\t\treturn {\n\t\t\tjsonSchema,\n\t\t\tvalidateRequest,\n\t\t\tvalidateResponse,\n\t\t}\n\t}\n\n\ttest() {\n\t\treturn supertest(this.server)\n\t}\n\n\tasync start() {\n\t\tconst port = this.config.port\n\t\tconst instance = Instance.get()\n\t\tconst { app } = instance.settings\n\t\tif (this.config.healthPath)\n\t\t\tthis.addRoute({\n\t\t\t\tmethod: Methods.get,\n\t\t\t\tpath: this.config.healthPath,\n\t\t\t\thandler: async (req) =>\n\t\t\t\t\treq.res({\n\t\t\t\t\t\tbody: `${instance.id}(${app.name}) service running`,\n\t\t\t\t\t\tcontentType: 'text/plain',\n\t\t\t\t\t}),\n\t\t\t})\n\n\t\tthis.implementations.registerNotFoundHandler(async (req) => {\n\t\t\tconst request = await this.implementations.parseRequest(req)\n\t\t\tthrow new NotFoundError(`Route ${request.path} not found`)\n\t\t})\n\t\tthis.implementations.registerErrorHandler(async (error, _, res) => {\n\t\t\tif (!(error instanceof EquippedError)) Instance.get().log.error({ error }, 'Uncaught error in route handler')\n\t\t\tconst response =\n\t\t\t\terror instanceof RequestError\n\t\t\t\t\t? new Response({\n\t\t\t\t\t\t\tbody: error.serializedErrors,\n\t\t\t\t\t\t\tstatus: error.statusCode,\n\t\t\t\t\t\t})\n\t\t\t\t\t: new Response({\n\t\t\t\t\t\t\tbody: [{ message: 'Something went wrong', data: error.message }],\n\t\t\t\t\t\t\tstatus: StatusCodes.BadRequest,\n\t\t\t\t\t\t})\n\t\t\treturn await this.implementations.handleResponse(res, response)\n\t\t})\n\n\t\tawait Promise.all(this.#queue.map((cb) => cb()))\n\t\tconst started = await this.implementations.start(port)\n\t\tif (started) Instance.get().log.info(`${instance.id}(${app.name}) service listening on port ${port}`)\n\t\treturn started\n\t}\n}\n"]}
@@ -6,7 +6,7 @@ const serverBasePipe = () => _valleyed.v.object({
6
6
  port: _valleyed.v.number(),
7
7
  cors: _valleyed.v.optional(
8
8
  _valleyed.v.object({
9
- origin: _valleyed.v.optional(_valleyed.v.array(_valleyed.v.string())),
9
+ origin: _valleyed.v.optional(_valleyed.v.or([_valleyed.v.array(_valleyed.v.string()), _valleyed.v.is(true)])),
10
10
  methods: _valleyed.v.optional(_valleyed.v.array(_valleyed.v.in(Object.values(_typescjs.Methods)))),
11
11
  credentials: _valleyed.v.optional(_valleyed.v.boolean())
12
12
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/pipes.ts","/home/runner/work/equipped/equipped/dist/cjs/server/pipes.cjs"],"names":[],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/server/pipes.cjs","sourcesContent":["import { type PipeOutput, v } from 'valleyed'\n\nimport { EventBus } from '../events'\nimport type { AuthUser } from '../types'\nimport { BaseRequestAuthMethod } from './requests-auth-methods'\nimport { Methods } from './types'\n\nconst serverBasePipe = () =>\n\tv.object({\n\t\tport: v.number(),\n\t\tcors: v.optional(\n\t\t\tv.object({\n\t\t\t\torigin: v.optional(v.array(v.string())),\n\t\t\t\tmethods: v.optional(v.array(v.in(Object.values(Methods)))),\n\t\t\t\tcredentials: v.optional(v.boolean()),\n\t\t\t}),\n\t\t),\n\t\teventBus: v.optional(v.instanceOf(EventBus)),\n\t\tpublicPath: v.optional(v.string()),\n\t\thealthPath: v.optional(v.string()),\n\t\topenapi: v.defaults(\n\t\t\tv.object({\n\t\t\t\tdocsVersion: v.defaults(v.string(), '1.0.0'),\n\t\t\t\tdocsBaseUrl: v.defaults(v.array(v.string()), ['/']),\n\t\t\t\tdocsPath: v.defaults(v.string(), '/__docs'),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\trequests: v.defaults(\n\t\t\tv.object({\n\t\t\t\tlog: v.defaults(v.boolean(), true),\n\t\t\t\trateLimit: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 60 * 60 * 1000),\n\t\t\t\t\t\tlimit: v.defaults(v.number(), 5000),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t\tslowdown: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 10 * 60 * 1000),\n\t\t\t\t\t\tdelayAfter: v.defaults(v.number(), 2000),\n\t\t\t\t\t\tdelayInMs: v.defaults(v.number(), 500),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\tsocketsAuthMethods: v.defaults(v.array(v.instanceOf(BaseRequestAuthMethod<AuthUser>)), []),\n\t})\n\nexport const serverConfigPipe = () =>\n\tv.discriminate((d: any) => d.type, {\n\t\tfastify: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('fastify' as const),\n\t\t\t}),\n\t\t),\n\t\texpress: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('express' as const),\n\t\t\t}),\n\t\t),\n\t})\n\nexport type ServerConfig = PipeOutput<ReturnType<typeof serverConfigPipe>>\n",null]}
1
+ {"version":3,"sources":["../../../src/server/pipes.ts","/home/runner/work/equipped/equipped/dist/cjs/server/pipes.cjs"],"names":[],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/server/pipes.cjs","sourcesContent":["import { type PipeOutput, v } from 'valleyed'\n\nimport { EventBus } from '../events'\nimport type { AuthUser } from '../types'\nimport { BaseRequestAuthMethod } from './requests-auth-methods'\nimport { Methods } from './types'\n\nconst serverBasePipe = () =>\n\tv.object({\n\t\tport: v.number(),\n\t\tcors: v.optional(\n\t\t\tv.object({\n\t\t\t\torigin: v.optional(v.or([v.array(v.string()), v.is(true)])),\n\t\t\t\tmethods: v.optional(v.array(v.in(Object.values(Methods)))),\n\t\t\t\tcredentials: v.optional(v.boolean()),\n\t\t\t}),\n\t\t),\n\t\teventBus: v.optional(v.instanceOf(EventBus)),\n\t\tpublicPath: v.optional(v.string()),\n\t\thealthPath: v.optional(v.string()),\n\t\topenapi: v.defaults(\n\t\t\tv.object({\n\t\t\t\tdocsVersion: v.defaults(v.string(), '1.0.0'),\n\t\t\t\tdocsBaseUrl: v.defaults(v.array(v.string()), ['/']),\n\t\t\t\tdocsPath: v.defaults(v.string(), '/__docs'),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\trequests: v.defaults(\n\t\t\tv.object({\n\t\t\t\tlog: v.defaults(v.boolean(), true),\n\t\t\t\trateLimit: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 60 * 60 * 1000),\n\t\t\t\t\t\tlimit: v.defaults(v.number(), 5000),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t\tslowdown: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 10 * 60 * 1000),\n\t\t\t\t\t\tdelayAfter: v.defaults(v.number(), 2000),\n\t\t\t\t\t\tdelayInMs: v.defaults(v.number(), 500),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\tsocketsAuthMethods: v.defaults(v.array(v.instanceOf(BaseRequestAuthMethod<AuthUser>)), []),\n\t})\n\nexport const serverConfigPipe = () =>\n\tv.discriminate((d: any) => d.type, {\n\t\tfastify: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('fastify' as const),\n\t\t\t}),\n\t\t),\n\t\texpress: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('express' as const),\n\t\t\t}),\n\t\t),\n\t})\n\nexport type ServerConfig = PipeOutput<ReturnType<typeof serverConfigPipe>>\n",null]}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _valleyed = require('valleyed');var _indexmincjs = require('../events/index.min.cjs');var _indexmincjs3 = require('./requests-auth-methods/index.min.cjs');var _typesmincjs = require('./types.min.cjs');const t=()=>_valleyed.v.object({port:_valleyed.v.number(),cors:_valleyed.v.optional(_valleyed.v.object({origin:_valleyed.v.optional(_valleyed.v.array(_valleyed.v.string())),methods:_valleyed.v.optional(_valleyed.v.array(_valleyed.v.in(Object.values(_typesmincjs.Methods)))),credentials:_valleyed.v.optional(_valleyed.v.boolean())})),eventBus:_valleyed.v.optional(_valleyed.v.instanceOf(_indexmincjs.EventBus)),publicPath:_valleyed.v.optional(_valleyed.v.string()),healthPath:_valleyed.v.optional(_valleyed.v.string()),openapi:_valleyed.v.defaults(_valleyed.v.object({docsVersion:_valleyed.v.defaults(_valleyed.v.string(),"1.0.0"),docsBaseUrl:_valleyed.v.defaults(_valleyed.v.array(_valleyed.v.string()),["/"]),docsPath:_valleyed.v.defaults(_valleyed.v.string(),"/__docs")}),{}),requests:_valleyed.v.defaults(_valleyed.v.object({log:_valleyed.v.defaults(_valleyed.v.boolean(),!0),rateLimit:_valleyed.v.defaults(_valleyed.v.object({enabled:_valleyed.v.defaults(_valleyed.v.boolean(),!1),periodInMs:_valleyed.v.defaults(_valleyed.v.number(),3600*1e3),limit:_valleyed.v.defaults(_valleyed.v.number(),5e3)}),{}),slowdown:_valleyed.v.defaults(_valleyed.v.object({enabled:_valleyed.v.defaults(_valleyed.v.boolean(),!1),periodInMs:_valleyed.v.defaults(_valleyed.v.number(),600*1e3),delayAfter:_valleyed.v.defaults(_valleyed.v.number(),2e3),delayInMs:_valleyed.v.defaults(_valleyed.v.number(),500)}),{})}),{}),socketsAuthMethods:_valleyed.v.defaults(_valleyed.v.array(_valleyed.v.instanceOf(_indexmincjs3.BaseRequestAuthMethod)),[])}),u= exports.serverConfigPipe =()=>_valleyed.v.discriminate(s=>s.type,{fastify:_valleyed.v.merge(t(),_valleyed.v.object({type:_valleyed.v.is("fastify")})),express:_valleyed.v.merge(t(),_valleyed.v.object({type:_valleyed.v.is("express")}))});exports.serverConfigPipe = u;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _valleyed = require('valleyed');var _indexmincjs = require('../events/index.min.cjs');var _indexmincjs3 = require('./requests-auth-methods/index.min.cjs');var _typesmincjs = require('./types.min.cjs');const t=()=>_valleyed.v.object({port:_valleyed.v.number(),cors:_valleyed.v.optional(_valleyed.v.object({origin:_valleyed.v.optional(_valleyed.v.or([_valleyed.v.array(_valleyed.v.string()),_valleyed.v.is(!0)])),methods:_valleyed.v.optional(_valleyed.v.array(_valleyed.v.in(Object.values(_typesmincjs.Methods)))),credentials:_valleyed.v.optional(_valleyed.v.boolean())})),eventBus:_valleyed.v.optional(_valleyed.v.instanceOf(_indexmincjs.EventBus)),publicPath:_valleyed.v.optional(_valleyed.v.string()),healthPath:_valleyed.v.optional(_valleyed.v.string()),openapi:_valleyed.v.defaults(_valleyed.v.object({docsVersion:_valleyed.v.defaults(_valleyed.v.string(),"1.0.0"),docsBaseUrl:_valleyed.v.defaults(_valleyed.v.array(_valleyed.v.string()),["/"]),docsPath:_valleyed.v.defaults(_valleyed.v.string(),"/__docs")}),{}),requests:_valleyed.v.defaults(_valleyed.v.object({log:_valleyed.v.defaults(_valleyed.v.boolean(),!0),rateLimit:_valleyed.v.defaults(_valleyed.v.object({enabled:_valleyed.v.defaults(_valleyed.v.boolean(),!1),periodInMs:_valleyed.v.defaults(_valleyed.v.number(),3600*1e3),limit:_valleyed.v.defaults(_valleyed.v.number(),5e3)}),{}),slowdown:_valleyed.v.defaults(_valleyed.v.object({enabled:_valleyed.v.defaults(_valleyed.v.boolean(),!1),periodInMs:_valleyed.v.defaults(_valleyed.v.number(),600*1e3),delayAfter:_valleyed.v.defaults(_valleyed.v.number(),2e3),delayInMs:_valleyed.v.defaults(_valleyed.v.number(),500)}),{})}),{}),socketsAuthMethods:_valleyed.v.defaults(_valleyed.v.array(_valleyed.v.instanceOf(_indexmincjs3.BaseRequestAuthMethod)),[])}),p= exports.serverConfigPipe =()=>_valleyed.v.discriminate(s=>s.type,{fastify:_valleyed.v.merge(t(),_valleyed.v.object({type:_valleyed.v.is("fastify")})),express:_valleyed.v.merge(t(),_valleyed.v.object({type:_valleyed.v.is("express")}))});exports.serverConfigPipe = p;
2
2
  //# sourceMappingURL=pipes.min.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/pipes.ts"],"names":["v","Methods","EventBus"],"mappings":"AAAA,6GAAmC,sDAI1B,qEACe,8CAKtB,MAAQ,CAAA,CAAA,CAAA,CAAA,EAAA,WAAA,CAAA,MACL,CAAA,CAAA,IACD,CAAA,WAAA,CAAA,MAAU,CAAA,CAAA,CAAA,IAAA,CAASA,WAAAA,CAAE,QAAQ,CAAA,WAAA,CAAA,MAAS,CAAA,CACtC,MAAA,CAAA,WAASA,CAAAA,QAAE,CAAA,WAASA,CAAAA,KAAE,CAAA,WAAMA,CAAAA,MAAK,CAAA,CAAA,CAAA,CAAA,CAAO,OAAOC,CAAO,WAAC,CAAC,QACxD,CAAA,WAAA,CAAA,KAAaD,CAAE,WAAA,CAAA,EAAA,CAAA,MAAW,CAAA,MAAA,CAAQ,oBAAC,CACpC,CAAC,CACF,CAAA,CACA,WAAY,CAAA,WAAA,CAAA,QAAW,CAAA,WAAA,CAAA,OAAA,CAAWE,CAAQ,CAAC,CAAA,CAC3C,CAAA,CAAA,QAAA,CAAYF,WAAAA,CAAE,QAAA,CAASA,WAAAA,CAAE,UACzB,CAAA,qBAAA,CAAA,CAAA,CAAA,UAAc,CAAA,WAAA,CAAA,QAAW,CAAA,WAAA,CAAA,MACzB,CAAA,CAAA,CAAA,CAAA,UAAW,CAAA,WAAA,CAAA,QACR,CAAA,WAAO,CACR,MAAA,CAAA,CAAA,CAAA,CAAA,OAAe,CAAA,WAAA,CAAA,QAAW,CAAA,WAAA,CAAA,MAAU,CAAA,CAAA,WACpC,CAAA,WAAA,CAAA,QAAe,CAAA,WAAA,CAAA,MAAW,CAAA,CAAA,CAAA,OAAQ,CAAA,CAAA,WAClC,CAAA,WAAA,CAAA,QAAY,CAAA,WAAA,CAAA,KAAA,CAASA,WAAAA,CAAE,MAAA,CAAO,CAAA,CAAG,CAAA,CAAA,GAAA,CAAA,CAAA,CAAA,QAGnC,CACA,WAAA,CAAA,QAAUA,CAAE,WAAA,CAAA,MAAA,CACXA,CAAAA,CAAE,SACD,CAAA,CAAA,CAAKA,CAAAA,CAAE,CAAA,CAAA,CAAA,QAAW,CAAA,WAAA,CAAA,QAAW,CAAI,WAAA,CACjC,MAAA,CAAA,CAAA,GAAWA,CAAE,WAAA,CAAA,QACZA,CAAE,WAAA,CAAA,OACD,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAASA,SAAE,CAAA,WAASA,CAAAA,QAAE,CAAQ,WAAA,CAAG,MACjC,CAAA,CAAA,OAAYA,CAAAA,WAAE,CAAA,QAASA,CAAAA,WAAE,CAAA,OAAO,CAAG,CAAA,CAAA,CAAA,CAAA,CAAU,CAAA,UACtCA,CAAAA,WAAE,CAAA,QAASA,CAAAA,WAAE,CAAA,MAAO,CAAA,CAAG,CAAA,IAC9B,CAAA,GAEF,CAAA,CACA,KAAA,CAAA,WAAA,CAAA,QAAY,CAAA,WAAA,CAAA,MACT,CAAA,CAAA,CAAA,GACD,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAASA,CAAAA,QAAE,CAAA,WAASA,CAAAA,QAAE,CAAQ,WAAA,CAAG,MACjC,CAAA,CAAA,OAAYA,CAAAA,WAAE,CAAA,QAASA,CAAAA,WAAE,CAAA,OAAO,CAAG,CAAA,CAAA,CAAA,CAAU,CAAA,CAAA,UAC7C,CAAA,WAAA,CAAA,QAAc,CAAA,WAAA,CAAA,MAAW,CAAA,CAAA,CAAA,GAAU,CAAA,GAAI,CACvC,CAAA,UAAWA,CAAE,WAAA,CAAA,QAASA,CAAE,WAAA,CAAA,MAAO,CAAG,CAAA,CAAA,GAClC,CAAA,CACD,SAIH,CACA,WAAA,CAAA,QAAA,CAAA,WAAA,CAAA,MAAoBA,CAAAA,CAAE,CAAA,GAAA,CAAA,CAAA,CAAA,CAAA,CAASA,CAAAA,CAAE,CAAA,CAAA,CAAA,CAAA,CAAA,CAAMA,CAAAA,kBAAkD,CAC1F,WAAC,CAAA,QAGDA,CAAE,WAAA,CAAA,KAAA,CAAA,WAAA,CAAA,UAA2B,CAAA,mCAAA,CAAM,CAClC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAASA,4BAAAA,CAAE,CAAA,EAAA,WAAA,CAAA,YAER,CAAA,CAAO,EACR,CAAA,CAAA,IAAQ,CAAA,CAAA,OAAG,CAAA,WAAA,CAAkB,KAG/B,CAAA,CAAA,CAAA,CAAA,CAAA,WAAA,CAAA,MAAW,CAAA,CAAA,IACK,CACfA,WAAAA,CAAE,EAAA,CAAA,SACD,CAAMA,CAAAA,CAAE,CAAA,CAAA,OAAG,CAAA,WAAA,CAAkB,KAG/B,CAAA,CAAA,CAAA,CAAA,CAAA,WAAA,CAAA,MAAA,CAAA,CAAA,IAAA,CAAA,WAAA,CAAA,EAAA,CAAA,SAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,6BAAA","file":"/home/runner/work/equipped/equipped/dist/cjs/server/pipes.min.cjs","sourcesContent":["import { type PipeOutput, v } from 'valleyed'\n\nimport { EventBus } from '../events'\nimport type { AuthUser } from '../types'\nimport { BaseRequestAuthMethod } from './requests-auth-methods'\nimport { Methods } from './types'\n\nconst serverBasePipe = () =>\n\tv.object({\n\t\tport: v.number(),\n\t\tcors: v.optional(\n\t\t\tv.object({\n\t\t\t\torigin: v.optional(v.array(v.string())),\n\t\t\t\tmethods: v.optional(v.array(v.in(Object.values(Methods)))),\n\t\t\t\tcredentials: v.optional(v.boolean()),\n\t\t\t}),\n\t\t),\n\t\teventBus: v.optional(v.instanceOf(EventBus)),\n\t\tpublicPath: v.optional(v.string()),\n\t\thealthPath: v.optional(v.string()),\n\t\topenapi: v.defaults(\n\t\t\tv.object({\n\t\t\t\tdocsVersion: v.defaults(v.string(), '1.0.0'),\n\t\t\t\tdocsBaseUrl: v.defaults(v.array(v.string()), ['/']),\n\t\t\t\tdocsPath: v.defaults(v.string(), '/__docs'),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\trequests: v.defaults(\n\t\t\tv.object({\n\t\t\t\tlog: v.defaults(v.boolean(), true),\n\t\t\t\trateLimit: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 60 * 60 * 1000),\n\t\t\t\t\t\tlimit: v.defaults(v.number(), 5000),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t\tslowdown: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 10 * 60 * 1000),\n\t\t\t\t\t\tdelayAfter: v.defaults(v.number(), 2000),\n\t\t\t\t\t\tdelayInMs: v.defaults(v.number(), 500),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\tsocketsAuthMethods: v.defaults(v.array(v.instanceOf(BaseRequestAuthMethod<AuthUser>)), []),\n\t})\n\nexport const serverConfigPipe = () =>\n\tv.discriminate((d: any) => d.type, {\n\t\tfastify: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('fastify' as const),\n\t\t\t}),\n\t\t),\n\t\texpress: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('express' as const),\n\t\t\t}),\n\t\t),\n\t})\n\nexport type ServerConfig = PipeOutput<ReturnType<typeof serverConfigPipe>>\n"]}
1
+ {"version":3,"sources":["../../../src/server/pipes.ts"],"names":["v","Methods","EventBus"],"mappings":"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","file":"/home/runner/work/equipped/equipped/dist/cjs/server/pipes.min.cjs","sourcesContent":["import { type PipeOutput, v } from 'valleyed'\n\nimport { EventBus } from '../events'\nimport type { AuthUser } from '../types'\nimport { BaseRequestAuthMethod } from './requests-auth-methods'\nimport { Methods } from './types'\n\nconst serverBasePipe = () =>\n\tv.object({\n\t\tport: v.number(),\n\t\tcors: v.optional(\n\t\t\tv.object({\n\t\t\t\torigin: v.optional(v.or([v.array(v.string()), v.is(true)])),\n\t\t\t\tmethods: v.optional(v.array(v.in(Object.values(Methods)))),\n\t\t\t\tcredentials: v.optional(v.boolean()),\n\t\t\t}),\n\t\t),\n\t\teventBus: v.optional(v.instanceOf(EventBus)),\n\t\tpublicPath: v.optional(v.string()),\n\t\thealthPath: v.optional(v.string()),\n\t\topenapi: v.defaults(\n\t\t\tv.object({\n\t\t\t\tdocsVersion: v.defaults(v.string(), '1.0.0'),\n\t\t\t\tdocsBaseUrl: v.defaults(v.array(v.string()), ['/']),\n\t\t\t\tdocsPath: v.defaults(v.string(), '/__docs'),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\trequests: v.defaults(\n\t\t\tv.object({\n\t\t\t\tlog: v.defaults(v.boolean(), true),\n\t\t\t\trateLimit: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 60 * 60 * 1000),\n\t\t\t\t\t\tlimit: v.defaults(v.number(), 5000),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t\tslowdown: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 10 * 60 * 1000),\n\t\t\t\t\t\tdelayAfter: v.defaults(v.number(), 2000),\n\t\t\t\t\t\tdelayInMs: v.defaults(v.number(), 500),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\tsocketsAuthMethods: v.defaults(v.array(v.instanceOf(BaseRequestAuthMethod<AuthUser>)), []),\n\t})\n\nexport const serverConfigPipe = () =>\n\tv.discriminate((d: any) => d.type, {\n\t\tfastify: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('fastify' as const),\n\t\t\t}),\n\t\t),\n\t\texpress: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('express' as const),\n\t\t\t}),\n\t\t),\n\t})\n\nexport type ServerConfig = PipeOutput<ReturnType<typeof serverConfigPipe>>\n"]}
@@ -15,7 +15,7 @@ const signinWithApple = async (idToken) => {
15
15
  try {
16
16
  const APPLE_BASE = "https://appleid.apple.com";
17
17
  const json = _jsonwebtoken2.default.decode(idToken, { complete: true });
18
- if (!_optionalChain([json, 'optionalAccess', _ => _.header])) throw new Error("");
18
+ if (!_optionalChain([json, 'optionalAccess', _ => _.header])) throw new (0, _indexcjs.EquippedError)("Missing JWT header", { idToken, json });
19
19
  const { kid, alg } = json.header;
20
20
  const publicKey = await _jwksrsa2.default.call(void 0, { jwksUri: `${APPLE_BASE}/auth/keys`, cache: true }).getSigningKey(kid).then((key) => key.getPublicKey()).catch(() => null);
21
21
  if (!publicKey) throw new (0, _indexcjs.EquippedError)("no publicKey", { idToken, publicKey, json });
@@ -41,7 +41,7 @@ const signinWithFacebook = async (accessToken, fields = []) => {
41
41
  throw new (0, _indexcjs.EquippedError)("Failed to sign in with facebook", { accessToken, fields }, err);
42
42
  });
43
43
  const isValidData = fields.every((key) => key in data);
44
- if (!isValidData) throw new Error("Incomplete scope for access token");
44
+ if (!isValidData) throw new (0, _indexcjs.EquippedError)("Incomplete scope for access token", { accessToken, fields, data });
45
45
  data.email_verified = "true";
46
46
  return data;
47
47
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utilities/authProviders.ts","/home/runner/work/equipped/equipped/dist/cjs/utilities/authProviders.cjs"],"names":[],"mappings":"AAAA,yvBAAkB;AAClB,wGAAgB;AAChB,qFAAuB;AAEvB,+CAA8B;AAEvB,MAAM,iBAAA,EAAmB,MAAA,CAAO,OAAA,EAAA,GAAoB;AAC1D,EAAA,MAAM,QAAA,EAAU,CAAA,iDAAA,EAAoD,OAAO,CAAA,CAAA;AAClB,EAAA;AACiB,IAAA;AACzE,EAAA;AACsB,EAAA;AACD,EAAA;AACf,EAAA;AAQR;AAE0D;AACrD,EAAA;AACgB,IAAA;AACgC,IAAA;AACd,IAAA;AACX,IAAA;AAC+C,IAAA;AAIN,IAAA;AACK,IAAA;AACT,IAAA;AACU,IAAA;AACf,IAAA;AAEnD,IAAA;AAMM,EAAA;AAC2D,IAAA;AACzE,EAAA;AACD;AAE0F;AAC7B,EAAA;AAElD,EAAA;AACA,IAAA;AACH,IAAA;AACG,IAAA;AACgB,MAAA;AACT,MAAA;AACf,IAAA;AAEe,EAAA;AAC2D,IAAA;AAC1E,EAAA;AACmD,EAAA;AACgB,EAAA;AAC/C,EAAA;AACf,EAAA;AASR;AC7B8E;AACA;AACA;AACA;AACA","file":"/home/runner/work/equipped/equipped/dist/cjs/utilities/authProviders.cjs","sourcesContent":["import axios from 'axios'\nimport jwt from 'jsonwebtoken'\nimport jwksClient from 'jwks-rsa'\n\nimport { EquippedError } from '../errors'\n\nexport const signinWithGoogle = async (idToken: string) => {\n\tconst authUrl = `https://oauth2.googleapis.com/tokeninfo?id_token=${idToken}`\n\tconst { data } = await axios.get(authUrl).catch((err) => {\n\t\tthrow new EquippedError('Failed to sign in with google', { idToken }, err)\n\t})\n\tdata.first_name = data.given_name\n\tdata.last_name = data.family_name\n\treturn data as {\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tfirst_name: string\n\t\tlast_name: string\n\t\tpicture: string\n\t\tsub: string\n\t} & Record<string, any>\n}\n\nexport const signinWithApple = async (idToken: string) => {\n\ttry {\n\t\tconst APPLE_BASE = 'https://appleid.apple.com'\n\t\tconst json = jwt.decode(idToken, { complete: true })\n\t\tif (!json?.header) throw new Error('')\n\t\tconst { kid, alg } = json.header\n\t\tconst publicKey = await jwksClient({ jwksUri: `${APPLE_BASE}/auth/keys`, cache: true })\n\t\t\t.getSigningKey(kid)\n\t\t\t.then((key) => key.getPublicKey())\n\t\t\t.catch(() => null)\n\t\tif (!publicKey) throw new EquippedError('no publicKey', { idToken, publicKey, json })\n\t\tconst data = jwt.verify(idToken, publicKey, { algorithms: [alg as any] }) as Record<string, any>\n\t\tif (!data) throw new EquippedError('no data', { idToken, data })\n\t\tif (data.iss !== APPLE_BASE) throw new EquippedError('iss doesnt match', { idToken, data })\n\t\tif (data.exp * 1000 < Date.now()) throw new EquippedError('expired idToken', { idToken, data })\n\t\t// TODO: Find out how to get profile data from api\n\t\treturn data as {\n\t\t\temail?: string\n\t\t\tsub: string\n\t\t\temail_verified?: 'true' | 'false'\n\t\t\tis_private_email?: 'true' | 'false'\n\t\t} & Record<string, any>\n\t} catch (err) {\n\t\tthrow new EquippedError('Failed to sign in with apple', { idToken }, err)\n\t}\n}\n\nexport const signinWithFacebook = async (accessToken: string, fields = [] as string[]) => {\n\tfields = [...new Set([...fields, 'name', 'picture', 'email'])]\n\tconst { data } = await axios\n\t\t.request({\n\t\t\tmethod: 'get',\n\t\t\turl: 'https://graph.facebook.com/v15.0/me',\n\t\t\tparams: {\n\t\t\t\tfields: fields.join(','),\n\t\t\t\taccess_token: accessToken,\n\t\t\t},\n\t\t})\n\t\t.catch((err) => {\n\t\t\tthrow new EquippedError('Failed to sign in with facebook', { accessToken, fields }, err)\n\t\t})\n\tconst isValidData = fields.every((key) => key in data)\n\tif (!isValidData) throw new Error('Incomplete scope for access token')\n\tdata.email_verified = 'true'\n\treturn data as {\n\t\tid: string\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tname: string\n\t\tpicture: {\n\t\t\tdata: { height: number; is_silhouette: boolean; url: string; width: number }\n\t\t}\n\t} & Record<string, any>\n}\n",null]}
1
+ {"version":3,"sources":["../../../src/utilities/authProviders.ts","/home/runner/work/equipped/equipped/dist/cjs/utilities/authProviders.cjs"],"names":[],"mappings":"AAAA,yvBAAkB;AAClB,wGAAgB;AAChB,qFAAuB;AAEvB,+CAA8B;AAEvB,MAAM,iBAAA,EAAmB,MAAA,CAAO,OAAA,EAAA,GAAoB;AAC1D,EAAA,MAAM,QAAA,EAAU,CAAA,iDAAA,EAAoD,OAAO,CAAA,CAAA;AAClB,EAAA;AACiB,IAAA;AACzE,EAAA;AACsB,EAAA;AACD,EAAA;AACf,EAAA;AAQR;AAE0D;AACrD,EAAA;AACgB,IAAA;AACgC,IAAA;AACgB,IAAA;AACzC,IAAA;AAC+C,IAAA;AAIN,IAAA;AACK,IAAA;AACT,IAAA;AACU,IAAA;AACf,IAAA;AAEnD,IAAA;AAMM,EAAA;AAC2D,IAAA;AACzE,EAAA;AACD;AAE0F;AAC7B,EAAA;AAElD,EAAA;AACA,IAAA;AACH,IAAA;AACG,IAAA;AACgB,MAAA;AACT,MAAA;AACf,IAAA;AAEe,EAAA;AAC2D,IAAA;AAC1E,EAAA;AACmD,EAAA;AACX,EAAA;AACpB,EAAA;AACf,EAAA;AASR;AC7B8E;AACA;AACA;AACA;AACA","file":"/home/runner/work/equipped/equipped/dist/cjs/utilities/authProviders.cjs","sourcesContent":["import axios from 'axios'\nimport jwt from 'jsonwebtoken'\nimport jwksClient from 'jwks-rsa'\n\nimport { EquippedError } from '../errors'\n\nexport const signinWithGoogle = async (idToken: string) => {\n\tconst authUrl = `https://oauth2.googleapis.com/tokeninfo?id_token=${idToken}`\n\tconst { data } = await axios.get(authUrl).catch((err) => {\n\t\tthrow new EquippedError('Failed to sign in with google', { idToken }, err)\n\t})\n\tdata.first_name = data.given_name\n\tdata.last_name = data.family_name\n\treturn data as {\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tfirst_name: string\n\t\tlast_name: string\n\t\tpicture: string\n\t\tsub: string\n\t} & Record<string, any>\n}\n\nexport const signinWithApple = async (idToken: string) => {\n\ttry {\n\t\tconst APPLE_BASE = 'https://appleid.apple.com'\n\t\tconst json = jwt.decode(idToken, { complete: true })\n\t\tif (!json?.header) throw new EquippedError('Missing JWT header', { idToken, json })\n\t\tconst { kid, alg } = json.header\n\t\tconst publicKey = await jwksClient({ jwksUri: `${APPLE_BASE}/auth/keys`, cache: true })\n\t\t\t.getSigningKey(kid)\n\t\t\t.then((key) => key.getPublicKey())\n\t\t\t.catch(() => null)\n\t\tif (!publicKey) throw new EquippedError('no publicKey', { idToken, publicKey, json })\n\t\tconst data = jwt.verify(idToken, publicKey, { algorithms: [alg as any] }) as Record<string, any>\n\t\tif (!data) throw new EquippedError('no data', { idToken, data })\n\t\tif (data.iss !== APPLE_BASE) throw new EquippedError('iss doesnt match', { idToken, data })\n\t\tif (data.exp * 1000 < Date.now()) throw new EquippedError('expired idToken', { idToken, data })\n\t\t// TODO: Find out how to get profile data from api\n\t\treturn data as {\n\t\t\temail?: string\n\t\t\tsub: string\n\t\t\temail_verified?: 'true' | 'false'\n\t\t\tis_private_email?: 'true' | 'false'\n\t\t} & Record<string, any>\n\t} catch (err) {\n\t\tthrow new EquippedError('Failed to sign in with apple', { idToken }, err)\n\t}\n}\n\nexport const signinWithFacebook = async (accessToken: string, fields = [] as string[]) => {\n\tfields = [...new Set([...fields, 'name', 'picture', 'email'])]\n\tconst { data } = await axios\n\t\t.request({\n\t\t\tmethod: 'get',\n\t\t\turl: 'https://graph.facebook.com/v15.0/me',\n\t\t\tparams: {\n\t\t\t\tfields: fields.join(','),\n\t\t\t\taccess_token: accessToken,\n\t\t\t},\n\t\t})\n\t\t.catch((err) => {\n\t\t\tthrow new EquippedError('Failed to sign in with facebook', { accessToken, fields }, err)\n\t\t})\n\tconst isValidData = fields.every((key) => key in data)\n\tif (!isValidData) throw new EquippedError('Incomplete scope for access token', { accessToken, fields, data })\n\tdata.email_verified = 'true'\n\treturn data as {\n\t\tid: string\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tname: string\n\t\tpicture: {\n\t\t\tdata: { height: number; is_silhouette: boolean; url: string; width: number }\n\t\t}\n\t} & Record<string, any>\n}\n",null]}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _axios = require('axios'); var _axios2 = _interopRequireDefault(_axios);var _jsonwebtoken = require('jsonwebtoken'); var _jsonwebtoken2 = _interopRequireDefault(_jsonwebtoken);var _jwksrsa = require('jwks-rsa'); var _jwksrsa2 = _interopRequireDefault(_jwksrsa);var _indexmincjs = require('../errors/index.min.cjs');const f=async t=>{const i=`https://oauth2.googleapis.com/tokeninfo?id_token=${t}`,{data:e}=await _axios2.default.get(i).catch(s=>{throw new (0, _indexmincjs.EquippedError)("Failed to sign in with google",{idToken:t},s)});return e.first_name=e.given_name,e.last_name=e.family_name,e},d= exports.signinWithApple =async t=>{try{const i="https://appleid.apple.com",e=_jsonwebtoken2.default.decode(t,{complete:!0});if(!_optionalChain([e, 'optionalAccess', _ => _.header]))throw new Error("");const{kid:s,alg:n}=e.header,o=await _jwksrsa2.default.call(void 0, {jwksUri:`${i}/auth/keys`,cache:!0}).getSigningKey(s).then(l=>l.getPublicKey()).catch(()=>null);if(!o)throw new (0, _indexmincjs.EquippedError)("no publicKey",{idToken:t,publicKey:o,json:e});const r=_jsonwebtoken2.default.verify(t,o,{algorithms:[n]});if(!r)throw new (0, _indexmincjs.EquippedError)("no data",{idToken:t,data:r});if(r.iss!==i)throw new (0, _indexmincjs.EquippedError)("iss doesnt match",{idToken:t,data:r});if(r.exp*1e3<Date.now())throw new (0, _indexmincjs.EquippedError)("expired idToken",{idToken:t,data:r});return r}catch(i){throw new (0, _indexmincjs.EquippedError)("Failed to sign in with apple",{idToken:t},i)}},y= exports.signinWithFacebook =async(t,i=[])=>{i=[...new Set([...i,"name","picture","email"])];const{data:e}=await _axios2.default.request({method:"get",url:"https://graph.facebook.com/v15.0/me",params:{fields:i.join(","),access_token:t}}).catch(n=>{throw new (0, _indexmincjs.EquippedError)("Failed to sign in with facebook",{accessToken:t,fields:i},n)});if(!i.every(n=>n in e))throw new Error("Incomplete scope for access token");return e.email_verified="true",e};exports.signinWithApple = d; exports.signinWithFacebook = y; exports.signinWithGoogle = f;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _axios = require('axios'); var _axios2 = _interopRequireDefault(_axios);var _jsonwebtoken = require('jsonwebtoken'); var _jsonwebtoken2 = _interopRequireDefault(_jsonwebtoken);var _jwksrsa = require('jwks-rsa'); var _jwksrsa2 = _interopRequireDefault(_jwksrsa);var _indexmincjs = require('../errors/index.min.cjs');const f=async t=>{const i=`https://oauth2.googleapis.com/tokeninfo?id_token=${t}`,{data:e}=await _axios2.default.get(i).catch(s=>{throw new (0, _indexmincjs.EquippedError)("Failed to sign in with google",{idToken:t},s)});return e.first_name=e.given_name,e.last_name=e.family_name,e},d= exports.signinWithApple =async t=>{try{const i="https://appleid.apple.com",e=_jsonwebtoken2.default.decode(t,{complete:!0});if(!_optionalChain([e, 'optionalAccess', _ => _.header]))throw new (0, _indexmincjs.EquippedError)("Missing JWT header",{idToken:t,json:e});const{kid:s,alg:n}=e.header,o=await _jwksrsa2.default.call(void 0, {jwksUri:`${i}/auth/keys`,cache:!0}).getSigningKey(s).then(l=>l.getPublicKey()).catch(()=>null);if(!o)throw new (0, _indexmincjs.EquippedError)("no publicKey",{idToken:t,publicKey:o,json:e});const r=_jsonwebtoken2.default.verify(t,o,{algorithms:[n]});if(!r)throw new (0, _indexmincjs.EquippedError)("no data",{idToken:t,data:r});if(r.iss!==i)throw new (0, _indexmincjs.EquippedError)("iss doesnt match",{idToken:t,data:r});if(r.exp*1e3<Date.now())throw new (0, _indexmincjs.EquippedError)("expired idToken",{idToken:t,data:r});return r}catch(i){throw new (0, _indexmincjs.EquippedError)("Failed to sign in with apple",{idToken:t},i)}},y= exports.signinWithFacebook =async(t,i=[])=>{i=[...new Set([...i,"name","picture","email"])];const{data:e}=await _axios2.default.request({method:"get",url:"https://graph.facebook.com/v15.0/me",params:{fields:i.join(","),access_token:t}}).catch(n=>{throw new (0, _indexmincjs.EquippedError)("Failed to sign in with facebook",{accessToken:t,fields:i},n)});if(!i.every(n=>n in e))throw new (0, _indexmincjs.EquippedError)("Incomplete scope for access token",{accessToken:t,fields:i,data:e});return e.email_verified="true",e};exports.signinWithApple = d; exports.signinWithFacebook = y; exports.signinWithGoogle = f;
2
2
  //# sourceMappingURL=authProviders.min.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utilities/authProviders.ts"],"names":["idToken"],"mappings":"AAAA,yvBAAkB,wGACF,qFACO,sDAIgBA,MACtC,CAAA,CAAA,MAAgB,CAAA,EAAA,CAAA,MAAA,CAAA,CAAA,CAAA,iDACC,EAAA,CAAA,CAAA,CAAA","file":"/home/runner/work/equipped/equipped/dist/cjs/utilities/authProviders.min.cjs","sourcesContent":["import axios from 'axios'\nimport jwt from 'jsonwebtoken'\nimport jwksClient from 'jwks-rsa'\n\nimport { EquippedError } from '../errors'\n\nexport const signinWithGoogle = async (idToken: string) => {\n\tconst authUrl = `https://oauth2.googleapis.com/tokeninfo?id_token=${idToken}`\n\tconst { data } = await axios.get(authUrl).catch((err) => {\n\t\tthrow new EquippedError('Failed to sign in with google', { idToken }, err)\n\t})\n\tdata.first_name = data.given_name\n\tdata.last_name = data.family_name\n\treturn data as {\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tfirst_name: string\n\t\tlast_name: string\n\t\tpicture: string\n\t\tsub: string\n\t} & Record<string, any>\n}\n\nexport const signinWithApple = async (idToken: string) => {\n\ttry {\n\t\tconst APPLE_BASE = 'https://appleid.apple.com'\n\t\tconst json = jwt.decode(idToken, { complete: true })\n\t\tif (!json?.header) throw new Error('')\n\t\tconst { kid, alg } = json.header\n\t\tconst publicKey = await jwksClient({ jwksUri: `${APPLE_BASE}/auth/keys`, cache: true })\n\t\t\t.getSigningKey(kid)\n\t\t\t.then((key) => key.getPublicKey())\n\t\t\t.catch(() => null)\n\t\tif (!publicKey) throw new EquippedError('no publicKey', { idToken, publicKey, json })\n\t\tconst data = jwt.verify(idToken, publicKey, { algorithms: [alg as any] }) as Record<string, any>\n\t\tif (!data) throw new EquippedError('no data', { idToken, data })\n\t\tif (data.iss !== APPLE_BASE) throw new EquippedError('iss doesnt match', { idToken, data })\n\t\tif (data.exp * 1000 < Date.now()) throw new EquippedError('expired idToken', { idToken, data })\n\t\t// TODO: Find out how to get profile data from api\n\t\treturn data as {\n\t\t\temail?: string\n\t\t\tsub: string\n\t\t\temail_verified?: 'true' | 'false'\n\t\t\tis_private_email?: 'true' | 'false'\n\t\t} & Record<string, any>\n\t} catch (err) {\n\t\tthrow new EquippedError('Failed to sign in with apple', { idToken }, err)\n\t}\n}\n\nexport const signinWithFacebook = async (accessToken: string, fields = [] as string[]) => {\n\tfields = [...new Set([...fields, 'name', 'picture', 'email'])]\n\tconst { data } = await axios\n\t\t.request({\n\t\t\tmethod: 'get',\n\t\t\turl: 'https://graph.facebook.com/v15.0/me',\n\t\t\tparams: {\n\t\t\t\tfields: fields.join(','),\n\t\t\t\taccess_token: accessToken,\n\t\t\t},\n\t\t})\n\t\t.catch((err) => {\n\t\t\tthrow new EquippedError('Failed to sign in with facebook', { accessToken, fields }, err)\n\t\t})\n\tconst isValidData = fields.every((key) => key in data)\n\tif (!isValidData) throw new Error('Incomplete scope for access token')\n\tdata.email_verified = 'true'\n\treturn data as {\n\t\tid: string\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tname: string\n\t\tpicture: {\n\t\t\tdata: { height: number; is_silhouette: boolean; url: string; width: number }\n\t\t}\n\t} & Record<string, any>\n}\n"]}
1
+ {"version":3,"sources":["../../../src/utilities/authProviders.ts"],"names":["idToken"],"mappings":"AAAA,yvBAAkB,wGACF,qFACO,sDAIgBA,MACtC,CAAA,CAAA,MAAgB,CAAA,EAAA,CAAA,MAAA,CAAA,CAAA,CAAA,iDACC,EAAA,CAAA,CAAA,CAAA","file":"/home/runner/work/equipped/equipped/dist/cjs/utilities/authProviders.min.cjs","sourcesContent":["import axios from 'axios'\nimport jwt from 'jsonwebtoken'\nimport jwksClient from 'jwks-rsa'\n\nimport { EquippedError } from '../errors'\n\nexport const signinWithGoogle = async (idToken: string) => {\n\tconst authUrl = `https://oauth2.googleapis.com/tokeninfo?id_token=${idToken}`\n\tconst { data } = await axios.get(authUrl).catch((err) => {\n\t\tthrow new EquippedError('Failed to sign in with google', { idToken }, err)\n\t})\n\tdata.first_name = data.given_name\n\tdata.last_name = data.family_name\n\treturn data as {\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tfirst_name: string\n\t\tlast_name: string\n\t\tpicture: string\n\t\tsub: string\n\t} & Record<string, any>\n}\n\nexport const signinWithApple = async (idToken: string) => {\n\ttry {\n\t\tconst APPLE_BASE = 'https://appleid.apple.com'\n\t\tconst json = jwt.decode(idToken, { complete: true })\n\t\tif (!json?.header) throw new EquippedError('Missing JWT header', { idToken, json })\n\t\tconst { kid, alg } = json.header\n\t\tconst publicKey = await jwksClient({ jwksUri: `${APPLE_BASE}/auth/keys`, cache: true })\n\t\t\t.getSigningKey(kid)\n\t\t\t.then((key) => key.getPublicKey())\n\t\t\t.catch(() => null)\n\t\tif (!publicKey) throw new EquippedError('no publicKey', { idToken, publicKey, json })\n\t\tconst data = jwt.verify(idToken, publicKey, { algorithms: [alg as any] }) as Record<string, any>\n\t\tif (!data) throw new EquippedError('no data', { idToken, data })\n\t\tif (data.iss !== APPLE_BASE) throw new EquippedError('iss doesnt match', { idToken, data })\n\t\tif (data.exp * 1000 < Date.now()) throw new EquippedError('expired idToken', { idToken, data })\n\t\t// TODO: Find out how to get profile data from api\n\t\treturn data as {\n\t\t\temail?: string\n\t\t\tsub: string\n\t\t\temail_verified?: 'true' | 'false'\n\t\t\tis_private_email?: 'true' | 'false'\n\t\t} & Record<string, any>\n\t} catch (err) {\n\t\tthrow new EquippedError('Failed to sign in with apple', { idToken }, err)\n\t}\n}\n\nexport const signinWithFacebook = async (accessToken: string, fields = [] as string[]) => {\n\tfields = [...new Set([...fields, 'name', 'picture', 'email'])]\n\tconst { data } = await axios\n\t\t.request({\n\t\t\tmethod: 'get',\n\t\t\turl: 'https://graph.facebook.com/v15.0/me',\n\t\t\tparams: {\n\t\t\t\tfields: fields.join(','),\n\t\t\t\taccess_token: accessToken,\n\t\t\t},\n\t\t})\n\t\t.catch((err) => {\n\t\t\tthrow new EquippedError('Failed to sign in with facebook', { accessToken, fields }, err)\n\t\t})\n\tconst isValidData = fields.every((key) => key in data)\n\tif (!isValidData) throw new EquippedError('Incomplete scope for access token', { accessToken, fields, data })\n\tdata.email_verified = 'true'\n\treturn data as {\n\t\tid: string\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tname: string\n\t\tpicture: {\n\t\t\tdata: { height: number; is_silhouette: boolean; url: string; width: number }\n\t\t}\n\t} & Record<string, any>\n}\n"]}
@@ -1,2 +1,2 @@
1
- import"cors";import{Server as C}from"socket.io";import j from"supertest";import{PipeError as O,v as a}from"valleyed";import{EquippedError as $,NotFoundError as D,RequestError as T}from "../../errors/index.min.mjs";import{Instance as b}from "../../instance/index.min.mjs";import{pipeErrorToValidationError as S}from "../../validations/index.min.mjs";import{requestLocalStorage as H,responseLocalStorage as A}from "../../validations/valleyed.min.mjs";import{OpenApi as M}from "../openapi.min.mjs";import{Response as y}from "../requests.min.mjs";import"../routes";import{SocketEmitter as V}from "../sockets.min.mjs";import{Methods as l,StatusCodes as k}from "../types.min.mjs";const x=Object.entries(k).filter(([,f])=>f>399).map(([f,o])=>({status:o,contentType:"application/json",pipe:a.meta(a.array(a.object({message:a.string(),field:a.optional(a.string())})),{$refId:`Errors.${f}Response`,description:`${f} Response`})}));class Y{constructor(o,s,n){this.config=s;this.implementations=n;this.server=o,this.#e=new M(s);const p=new C(o,{cors:this.cors});this.socket=new V(p,s),this.addRouter(this.#e.router())}#t=[];#s=new Map;#e;socket;server;get cors(){return{origin:this.config.cors?.origin,methods:(this.config.cors?.methods??Object.values(l)).filter(o=>o!==l.options).map(o=>o.toUpperCase()),credentials:this.config.cors?.credentials}}addRouter(...o){o.map(s=>s.routes).forEach(s=>this.addRoute(...s))}addRoute(...o){o.forEach(s=>{this.#t.push(async()=>{const{method:n,path:p,schema:r={},onError:c,middlewares:d=[]}=s,i=`(${n.toUpperCase()}) ${this.#e.cleanPath(p)}`;if(this.#s.get(i))throw new $(`Route key ${i} already registered. All route keys must be unique`,{route:s,key:i});d.forEach(h=>h.onSetup?.(s)),c?.onSetup?.(s);const{validateRequest:R,validateResponse:q,jsonSchema:v}=this.#o(n,r);this.#s.set(i,!0),await this.#e.register(s,v),this.implementations.registerRoute(n,this.#e.cleanPath(p),async(h,w)=>{const g=await R(await this.implementations.parseRequest(h));try{for(const u of d)await u.cb(g,this.config);const e=await s.handler(g,this.config),t=e instanceof y?e:new y({body:e,status:k.Ok,headers:{},piped:!1});return await this.implementations.handleResponse(w,await q(t))}catch(e){if(c?.cb){const t=await c.cb(g,this.config,e),u=t instanceof y?t:new y({body:t,status:k.BadRequest,headers:{}});return await this.implementations.handleResponse(w,await q(u))}throw e}})})})}#o(o,s){const n=s?.defaultStatusCode??k.Ok,p=s?.defaultContentType??"application/json";let r=n,c=p;const d={response:{},request:{}},i={},R={};[{key:"params",type:"request"},{key:"headers",type:"request"},{key:"cookies",type:"request"},{key:"query",type:"request"},{key:"body",type:"request",skip:![l.post,l.put,l.patch].includes(o)},{key:"response",type:"response"},{key:"responseHeaders",type:"response"},{key:"responseCookies",type:"response"}].forEach(e=>{const t=s[e.key]??a.any();if(!e.skip&&(e.type==="request"&&(i[e.key]=t,d.request[e.key]=a.schema(t)),e.type==="response")){const u=x.concat({status:n,contentType:c,pipe:t});R[e.key]=a.any().pipe(m=>{const E=u.find(P=>P.status===r)?.pipe;if(!E)throw O.root(`schema not defined for status code: ${r}`,m);return a.assert(E,m)}),d.response[e.key]=u.map(m=>({status:m.status,contentType:m.contentType,schema:a.schema(m.pipe)}))}});const v=a.object(i);a.compile(v,{allErrors:!0});const h=a.object(R);return a.compile(h,{allErrors:!0}),{jsonSchema:d,validateRequest:async e=>{if(!Object.keys(i))return e;const t=H.run(e,()=>a.validate(v,{params:e.params,headers:e.headers,query:e.query,body:e.body,cookies:e.cookies}));if(!t.valid)throw S(t.error);return e.params=t.value.params,e.headers=t.value.headers,e.query=t.value.query,e.body=t.value.body,e.cookies=t.value.cookies,e},validateResponse:async e=>{if(!Object.keys(R))return e;r=e.status,c=e.contentType;const t=A.run(e,()=>a.validate(h,{responseHeaders:e.headers,responseCookies:Object.fromEntries(Object.entries(e.cookies).map(([u,m])=>[u,m.value])),response:e.body}));if(!t.valid)throw S(t.error);return e.body=t.value.response,e.headers=t.value.responseHeaders,e.cookieValues=t.value.responseCookies,e}}}test(){return j(this.server)}async start(){const o=this.config.port,s=b.get(),{app:n}=s.settings;this.config.healthPath&&this.addRoute({method:l.get,path:this.config.healthPath,handler:async r=>r.res({body:`${s.id}(${n.name}) service running`,contentType:"text/plain"})}),this.implementations.registerNotFoundHandler(async r=>{const c=await this.implementations.parseRequest(r);throw new D(`Route ${c.path} not found`)}),this.implementations.registerErrorHandler(async(r,c,d)=>{b.get().log.error({error:r},"Uncaught error in route handler");const i=r instanceof T?new y({body:r.serializedErrors,status:r.statusCode}):new y({body:[{message:"Something went wrong",data:r.message}],status:k.BadRequest});return await this.implementations.handleResponse(d,i)}),await Promise.all(this.#t.map(r=>r()));const p=await this.implementations.start(o);return p&&b.get().log.info(`${s.id}(${n.name}) service listening on port ${o}`),p}}export{Y as Server};
1
+ import"@fastify/cors";import"cors";import{Server as O}from"socket.io";import j from"supertest";import{PipeError as $,v as a}from"valleyed";import{EquippedError as S,NotFoundError as D,RequestError as T}from "../../errors/index.min.mjs";import{Instance as b}from "../../instance/index.min.mjs";import{pipeErrorToValidationError as P}from "../../validations/index.min.mjs";import{requestLocalStorage as H,responseLocalStorage as A}from "../../validations/valleyed.min.mjs";import{OpenApi as M}from "../openapi.min.mjs";import{Response as y}from "../requests.min.mjs";import"../routes";import{SocketEmitter as V}from "../sockets.min.mjs";import{Methods as l,StatusCodes as k}from "../types.min.mjs";const x=Object.entries(k).filter(([,f])=>f>399).map(([f,o])=>({status:o,contentType:"application/json",pipe:a.meta(a.array(a.object({message:a.string(),field:a.optional(a.string())})),{$refId:`Errors.${f}Response`,description:`${f} Response`})}));class Z{constructor(o,t,n){this.config=t;this.implementations=n;this.server=o,this.#e=new M(t);const p=new O(o,{cors:this.cors});this.socket=new V(p,t),this.addRouter(this.#e.router())}#t=[];#s=new Map;#e;socket;server;get cors(){return{origin:this.config.cors?.origin?(o,t)=>t(null,!0):this.config.cors?.origin,methods:(this.config.cors?.methods??Object.values(l)).filter(o=>o!==l.options).map(o=>o.toUpperCase()),credentials:this.config.cors?.credentials}}addRouter(...o){o.map(t=>t.routes).forEach(t=>this.addRoute(...t))}addRoute(...o){o.forEach(t=>{this.#t.push(async()=>{const{method:n,path:p,schema:r={},onError:c,middlewares:d=[]}=t,i=`(${n.toUpperCase()}) ${this.#e.cleanPath(p)}`;if(this.#s.get(i))throw new S(`Route key ${i} already registered. All route keys must be unique`,{route:t,key:i});d.forEach(h=>h.onSetup?.(t)),c?.onSetup?.(t);const{validateRequest:R,validateResponse:q,jsonSchema:g}=this.#o(n,r);this.#s.set(i,!0),await this.#e.register(t,g),this.implementations.registerRoute(n,this.#e.cleanPath(p),async(h,w)=>{const v=await R(await this.implementations.parseRequest(h));try{for(const u of d)await u.cb(v,this.config);const e=await t.handler(v,this.config),s=e instanceof y?e:new y({body:e,status:k.Ok,headers:{},piped:!1});return await this.implementations.handleResponse(w,await q(s))}catch(e){if(c?.cb){const s=await c.cb(v,this.config,e),u=s instanceof y?s:new y({body:s,status:k.BadRequest,headers:{}});return await this.implementations.handleResponse(w,await q(u))}throw e}})})})}#o(o,t){const n=t?.defaultStatusCode??k.Ok,p=t?.defaultContentType??"application/json";let r=n,c=p;const d={response:{},request:{}},i={},R={};[{key:"params",type:"request"},{key:"headers",type:"request"},{key:"cookies",type:"request"},{key:"query",type:"request"},{key:"body",type:"request",skip:![l.post,l.put,l.patch].includes(o)},{key:"response",type:"response"},{key:"responseHeaders",type:"response"},{key:"responseCookies",type:"response"}].forEach(e=>{const s=t[e.key]??a.any();if(!e.skip&&(e.type==="request"&&(i[e.key]=s,d.request[e.key]=a.schema(s)),e.type==="response")){const u=x.concat({status:n,contentType:c,pipe:s});R[e.key]=a.any().pipe(m=>{const E=u.find(C=>C.status===r)?.pipe;if(!E)throw $.root(`schema not defined for status code: ${r}`,m);return a.assert(E,m)}),d.response[e.key]=u.map(m=>({status:m.status,contentType:m.contentType,schema:a.schema(m.pipe)}))}});const g=a.object(i);a.compile(g,{allErrors:!0});const h=a.object(R);return a.compile(h,{allErrors:!0}),{jsonSchema:d,validateRequest:async e=>{if(!Object.keys(i))return e;const s=H.run(e,()=>a.validate(g,{params:e.params,headers:e.headers,query:e.query,body:e.body,cookies:e.cookies}));if(!s.valid)throw P(s.error);return e.params=s.value.params,e.headers=s.value.headers,e.query=s.value.query,e.body=s.value.body,e.cookies=s.value.cookies,e},validateResponse:async e=>{if(!Object.keys(R))return e;r=e.status,c=e.contentType;const s=A.run(e,()=>a.validate(h,{responseHeaders:e.headers,responseCookies:Object.fromEntries(Object.entries(e.cookies).map(([u,m])=>[u,m.value])),response:e.body}));if(!s.valid)throw P(s.error);return e.body=s.value.response,e.headers=s.value.responseHeaders,e.cookieValues=s.value.responseCookies,e}}}test(){return j(this.server)}async start(){const o=this.config.port,t=b.get(),{app:n}=t.settings;this.config.healthPath&&this.addRoute({method:l.get,path:this.config.healthPath,handler:async r=>r.res({body:`${t.id}(${n.name}) service running`,contentType:"text/plain"})}),this.implementations.registerNotFoundHandler(async r=>{const c=await this.implementations.parseRequest(r);throw new D(`Route ${c.path} not found`)}),this.implementations.registerErrorHandler(async(r,c,d)=>{r instanceof S||b.get().log.error({error:r},"Uncaught error in route handler");const i=r instanceof T?new y({body:r.serializedErrors,status:r.statusCode}):new y({body:[{message:"Something went wrong",data:r.message}],status:k.BadRequest});return await this.implementations.handleResponse(d,i)}),await Promise.all(this.#t.map(r=>r()));const p=await this.implementations.start(o);return p&&b.get().log.info(`${t.id}(${n.name}) service listening on port ${o}`),p}}export{Z as Server};
2
2
  //# sourceMappingURL=base.min.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/server/impls/base.ts"],"sourcesContent":["import type http from 'node:http'\n\nimport { type CorsOptions } from 'cors'\nimport { Server as SocketServer } from 'socket.io'\nimport supertest from 'supertest'\nimport { type Pipe, PipeError, v } from 'valleyed'\n\nimport { EquippedError, NotFoundError, RequestError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { pipeErrorToValidationError } from '../../validations'\nimport { requestLocalStorage, responseLocalStorage } from '../../validations/valleyed'\nimport { OpenApi, type OpenApiSchemaDef } from '../openapi'\nimport type { ServerConfig } from '../pipes'\nimport { type Request, Response } from '../requests'\nimport { Router } from '../routes'\nimport { SocketEmitter } from '../sockets'\nimport { Methods, type MethodsEnum, type Route, type RouteDef, StatusCodes } from '../types'\n\ntype RequestValidator = (req: Request<any>) => Promise<Request<any>>\ntype ResponseValidator = (res: Response<any>) => Promise<Response<any>>\n\nconst errorsSchemas = Object.entries(StatusCodes)\n\t.filter(([, value]) => value > 399)\n\t.map(([key, value]) => ({\n\t\tstatus: value,\n\t\tcontentType: 'application/json',\n\t\tpipe: v.meta(v.array(v.object({ message: v.string(), field: v.optional(v.string()) })), {\n\t\t\t$refId: `Errors.${key}Response`,\n\t\t\tdescription: `${key} Response`,\n\t\t}) as Pipe<any, any>,\n\t}))\n\nexport abstract class Server<Req = any, Res = any> {\n\t#queue: (() => void | Promise<void>)[] = []\n\t#routesByKey = new Map<string, boolean>()\n\t#openapi: OpenApi\n\tsocket: SocketEmitter\n\tprotected server: http.Server\n\tprotected get cors() {\n\t\treturn {\n\t\t\torigin: this.config.cors?.origin,\n\t\t\tmethods: (this.config.cors?.methods ?? Object.values(Methods)).filter((m) => m !== Methods.options).map((m) => m.toUpperCase()),\n\t\t\tcredentials: this.config.cors?.credentials,\n\t\t} satisfies CorsOptions\n\t}\n\n\tconstructor(\n\t\tserver: http.Server,\n\t\tprivate config: ServerConfig,\n\t\tprivate implementations: {\n\t\t\tparseRequest: (req: Req) => Promise<Request<any>>\n\t\t\thandleResponse: (res: Res, response: Response<any>) => Promise<void>\n\t\t\tregisterRoute: (method: MethodsEnum, path: string, cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterErrorHandler: (cb: (error: Error, req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterNotFoundHandler: (cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tstart: (port: number) => Promise<boolean>\n\t\t},\n\t) {\n\t\tthis.server = server\n\t\tthis.#openapi = new OpenApi(config)\n\t\tconst socketInstance = new SocketServer(server, { cors: this.cors })\n\t\tthis.socket = new SocketEmitter(socketInstance, config)\n\t\tthis.addRouter(this.#openapi.router())\n\t}\n\n\taddRouter(...routers: Router<any>[]) {\n\t\trouters.map((router) => router.routes).forEach((routes) => this.addRoute(...routes))\n\t}\n\n\taddRoute<T extends RouteDef>(...routes: Route<T>[]) {\n\t\troutes.forEach((route) => {\n\t\t\tthis.#queue.push(async () => {\n\t\t\t\tconst { method, path, schema = {}, onError, middlewares = [] } = route\n\n\t\t\t\tconst key = `(${method.toUpperCase()}) ${this.#openapi.cleanPath(path)}`\n\t\t\t\tif (this.#routesByKey.get(key))\n\t\t\t\t\tthrow new EquippedError(`Route key ${key} already registered. All route keys must be unique`, { route, key })\n\n\t\t\t\tmiddlewares.forEach((m) => m.onSetup?.(route as any))\n\t\t\t\tonError?.onSetup?.(route as any)\n\n\t\t\t\tconst { validateRequest, validateResponse, jsonSchema } = this.#resolveSchema(method, schema)\n\n\t\t\t\tthis.#routesByKey.set(key, true)\n\t\t\t\tawait this.#openapi.register(route, jsonSchema)\n\t\t\t\tthis.implementations.registerRoute(method, this.#openapi.cleanPath(path), async (req: Req, res: Res) => {\n\t\t\t\t\tconst request = await validateRequest(await this.implementations.parseRequest(req))\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor (const middleware of middlewares) await middleware.cb(request, this.config)\n\t\t\t\t\t\tconst rawRes = await route.handler(request, this.config)\n\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\trawRes instanceof Response\n\t\t\t\t\t\t\t\t? rawRes\n\t\t\t\t\t\t\t\t: new Response({ body: rawRes, status: StatusCodes.Ok, headers: {}, piped: false })\n\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (onError?.cb) {\n\t\t\t\t\t\t\tconst rawResponse = await onError.cb(request, this.config, error as Error)\n\t\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\t\trawResponse instanceof Response\n\t\t\t\t\t\t\t\t\t? rawResponse\n\t\t\t\t\t\t\t\t\t: new Response({ body: rawResponse, status: StatusCodes.BadRequest, headers: {} })\n\t\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t}\n\n\t#resolveSchema(method: MethodsEnum, schema: RouteDef) {\n\t\tconst defaultStatusCode = schema?.defaultStatusCode ?? StatusCodes.Ok\n\t\tconst defaultContentType = schema?.defaultContentType ?? 'application/json'\n\t\tlet status = defaultStatusCode\n\t\tlet contentType = defaultContentType\n\t\tconst jsonSchema: OpenApiSchemaDef = { response: {}, request: {} }\n\t\tconst requestPipeDefs: Pick<RouteDef, 'body' | 'headers' | 'query' | 'params' | 'cookies'> = {}\n\t\tconst responsePipeDefs: Pick<RouteDef, 'response' | 'responseHeaders' | 'responseCookies'> = {}\n\n\t\tconst defs: {\n\t\t\tkey: Exclude<keyof RouteDef, `default${string}` | 'context'>\n\t\t\ttype: keyof OpenApiSchemaDef\n\t\t\tskip?: boolean\n\t\t}[] = [\n\t\t\t{ key: 'params', type: 'request' },\n\t\t\t{ key: 'headers', type: 'request' },\n\t\t\t{ key: 'cookies', type: 'request' },\n\t\t\t{ key: 'query', type: 'request' },\n\t\t\t{ key: 'body', type: 'request', skip: !(<MethodsEnum[]>[Methods.post, Methods.put, Methods.patch]).includes(method) },\n\t\t\t{ key: 'response', type: 'response' },\n\t\t\t{ key: 'responseHeaders', type: 'response' },\n\t\t\t{ key: 'responseCookies', type: 'response' },\n\t\t]\n\t\tdefs.forEach((def) => {\n\t\t\tconst pipe = schema[def.key] ?? v.any()\n\t\t\tif (def.skip) return\n\n\t\t\tif (def.type === 'request') {\n\t\t\t\trequestPipeDefs[def.key] = pipe\n\t\t\t\tjsonSchema.request[def.key as keyof typeof jsonSchema.request] = v.schema(pipe)\n\t\t\t}\n\t\t\tif (def.type === 'response') {\n\t\t\t\tconst pipeRecords = errorsSchemas.concat({ status: defaultStatusCode, contentType, pipe })\n\t\t\t\tresponsePipeDefs[def.key] = v.any().pipe((input) => {\n\t\t\t\t\tconst p = pipeRecords.find((r) => r.status === status)?.pipe\n\t\t\t\t\tif (!p) throw PipeError.root(`schema not defined for status code: ${status}`, input)\n\t\t\t\t\treturn v.assert(p, input)\n\t\t\t\t})\n\t\t\t\tjsonSchema.response[def.key as keyof typeof jsonSchema.response] = pipeRecords.map((record) => ({\n\t\t\t\t\tstatus: record.status,\n\t\t\t\t\tcontentType: record.contentType,\n\t\t\t\t\tschema: v.schema(record.pipe),\n\t\t\t\t}))\n\t\t\t}\n\t\t})\n\t\tconst requestPipe = v.object(requestPipeDefs)\n\t\tv.compile(requestPipe, { allErrors: true })\n\t\tconst responsePipe = v.object(responsePipeDefs)\n\t\tv.compile(responsePipe, { allErrors: true })\n\t\tconst validateRequest: RequestValidator = async (request) => {\n\t\t\tif (!Object.keys(requestPipeDefs)) return request\n\t\t\tconst validity = requestLocalStorage.run(request, () =>\n\t\t\t\tv.validate(requestPipe, {\n\t\t\t\t\tparams: request.params,\n\t\t\t\t\theaders: request.headers,\n\t\t\t\t\tquery: request.query,\n\t\t\t\t\tbody: request.body,\n\t\t\t\t\tcookies: request.cookies,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\trequest.params = validity.value.params!\n\t\t\trequest.headers = validity.value.headers!\n\t\t\trequest.query = validity.value.query!\n\t\t\trequest.body = validity.value.body!\n\t\t\trequest.cookies = validity.value.cookies!\n\t\t\treturn request\n\t\t}\n\t\tconst validateResponse: ResponseValidator = async (response) => {\n\t\t\tif (!Object.keys(responsePipeDefs)) return response\n\t\t\tstatus = response.status\n\t\t\tcontentType = response.contentType\n\n\t\t\tconst validity = responseLocalStorage.run(response, () =>\n\t\t\t\tv.validate(responsePipe, {\n\t\t\t\t\tresponseHeaders: response.headers,\n\t\t\t\t\tresponseCookies: Object.fromEntries(Object.entries(response.cookies).map(([key, val]) => [key, val.value] as const)),\n\t\t\t\t\tresponse: response.body,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\tresponse.body = validity.value.response!\n\t\t\tresponse.headers = validity.value.responseHeaders!\n\t\t\tresponse.cookieValues = validity.value.responseCookies!\n\t\t\treturn response\n\t\t}\n\t\treturn {\n\t\t\tjsonSchema,\n\t\t\tvalidateRequest,\n\t\t\tvalidateResponse,\n\t\t}\n\t}\n\n\ttest() {\n\t\treturn supertest(this.server)\n\t}\n\n\tasync start() {\n\t\tconst port = this.config.port\n\t\tconst instance = Instance.get()\n\t\tconst { app } = instance.settings\n\t\tif (this.config.healthPath)\n\t\t\tthis.addRoute({\n\t\t\t\tmethod: Methods.get,\n\t\t\t\tpath: this.config.healthPath,\n\t\t\t\thandler: async (req) =>\n\t\t\t\t\treq.res({\n\t\t\t\t\t\tbody: `${instance.id}(${app.name}) service running`,\n\t\t\t\t\t\tcontentType: 'text/plain',\n\t\t\t\t\t}),\n\t\t\t})\n\n\t\tthis.implementations.registerNotFoundHandler(async (req) => {\n\t\t\tconst request = await this.implementations.parseRequest(req)\n\t\t\tthrow new NotFoundError(`Route ${request.path} not found`)\n\t\t})\n\t\tthis.implementations.registerErrorHandler(async (error, _, res) => {\n\t\t\tInstance.get().log.error({ error }, 'Uncaught error in route handler')\n\t\t\tconst response =\n\t\t\t\terror instanceof RequestError\n\t\t\t\t\t? new Response({\n\t\t\t\t\t\t\tbody: error.serializedErrors,\n\t\t\t\t\t\t\tstatus: error.statusCode,\n\t\t\t\t\t\t})\n\t\t\t\t\t: new Response({\n\t\t\t\t\t\t\tbody: [{ message: 'Something went wrong', data: error.message }],\n\t\t\t\t\t\t\tstatus: StatusCodes.BadRequest,\n\t\t\t\t\t\t})\n\t\t\treturn await this.implementations.handleResponse(res, response)\n\t\t})\n\n\t\tawait Promise.all(this.#queue.map((cb) => cb()))\n\t\tconst started = await this.implementations.start(port)\n\t\tif (started) Instance.get().log.info(`${instance.id}(${app.name}) service listening on port ${port}`)\n\t\treturn started\n\t}\n}\n"],"mappings":"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","names":["SocketServer","supertest","PipeError","v","EquippedError","NotFoundError","RequestError","Instance","pipeErrorToValidationError","requestLocalStorage","responseLocalStorage","OpenApi","Response","SocketEmitter","Methods","StatusCodes","errorsSchemas","value","key","Server","server","config","implementations","#openapi","socketInstance","#queue","#routesByKey","m","routers","router","routes","route","method","path","schema","onError","middlewares","validateRequest","validateResponse","jsonSchema","#resolveSchema","req","res","request","middleware","rawRes","response","error","rawResponse","defaultStatusCode","defaultContentType","status","contentType","requestPipeDefs","responsePipeDefs","def","pipe","pipeRecords","input","p","r","record","requestPipe","responsePipe","validity","val","port","instance","app","_","cb","started"]}
1
+ {"version":3,"sources":["../../../../src/server/impls/base.ts"],"sourcesContent":["import type http from 'node:http'\n\nimport { type FastifyCorsOptions } from '@fastify/cors'\nimport { type CorsOptions } from 'cors'\nimport { Server as SocketServer } from 'socket.io'\nimport supertest from 'supertest'\nimport { type Pipe, PipeError, v } from 'valleyed'\n\nimport { EquippedError, NotFoundError, RequestError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { pipeErrorToValidationError } from '../../validations'\nimport { requestLocalStorage, responseLocalStorage } from '../../validations/valleyed'\nimport { OpenApi, type OpenApiSchemaDef } from '../openapi'\nimport type { ServerConfig } from '../pipes'\nimport { type Request, Response } from '../requests'\nimport { Router } from '../routes'\nimport { SocketEmitter } from '../sockets'\nimport { Methods, type MethodsEnum, type Route, type RouteDef, StatusCodes } from '../types'\n\ntype RequestValidator = (req: Request<any>) => Promise<Request<any>>\ntype ResponseValidator = (res: Response<any>) => Promise<Response<any>>\n\nconst errorsSchemas = Object.entries(StatusCodes)\n\t.filter(([, value]) => value > 399)\n\t.map(([key, value]) => ({\n\t\tstatus: value,\n\t\tcontentType: 'application/json',\n\t\tpipe: v.meta(v.array(v.object({ message: v.string(), field: v.optional(v.string()) })), {\n\t\t\t$refId: `Errors.${key}Response`,\n\t\t\tdescription: `${key} Response`,\n\t\t}) as Pipe<any, any>,\n\t}))\n\nexport abstract class Server<Req = any, Res = any> {\n\t#queue: (() => void | Promise<void>)[] = []\n\t#routesByKey = new Map<string, boolean>()\n\t#openapi: OpenApi\n\tsocket: SocketEmitter\n\tprotected server: http.Server\n\tprotected get cors(): CorsOptions & FastifyCorsOptions {\n\t\treturn {\n\t\t\torigin: this.config.cors?.origin ? (_, cb) => cb(null, true) : this.config.cors?.origin,\n\t\t\tmethods: (this.config.cors?.methods ?? Object.values(Methods)).filter((m) => m !== Methods.options).map((m) => m.toUpperCase()),\n\t\t\tcredentials: this.config.cors?.credentials,\n\t\t}\n\t}\n\n\tconstructor(\n\t\tserver: http.Server,\n\t\tprivate config: ServerConfig,\n\t\tprivate implementations: {\n\t\t\tparseRequest: (req: Req) => Promise<Request<any>>\n\t\t\thandleResponse: (res: Res, response: Response<any>) => Promise<void>\n\t\t\tregisterRoute: (method: MethodsEnum, path: string, cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterErrorHandler: (cb: (error: Error, req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterNotFoundHandler: (cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tstart: (port: number) => Promise<boolean>\n\t\t},\n\t) {\n\t\tthis.server = server\n\t\tthis.#openapi = new OpenApi(config)\n\t\tconst socketInstance = new SocketServer(server, { cors: this.cors })\n\t\tthis.socket = new SocketEmitter(socketInstance, config)\n\t\tthis.addRouter(this.#openapi.router())\n\t}\n\n\taddRouter(...routers: Router<any>[]) {\n\t\trouters.map((router) => router.routes).forEach((routes) => this.addRoute(...routes))\n\t}\n\n\taddRoute<T extends RouteDef>(...routes: Route<T>[]) {\n\t\troutes.forEach((route) => {\n\t\t\tthis.#queue.push(async () => {\n\t\t\t\tconst { method, path, schema = {}, onError, middlewares = [] } = route\n\n\t\t\t\tconst key = `(${method.toUpperCase()}) ${this.#openapi.cleanPath(path)}`\n\t\t\t\tif (this.#routesByKey.get(key))\n\t\t\t\t\tthrow new EquippedError(`Route key ${key} already registered. All route keys must be unique`, { route, key })\n\n\t\t\t\tmiddlewares.forEach((m) => m.onSetup?.(route as any))\n\t\t\t\tonError?.onSetup?.(route as any)\n\n\t\t\t\tconst { validateRequest, validateResponse, jsonSchema } = this.#resolveSchema(method, schema)\n\n\t\t\t\tthis.#routesByKey.set(key, true)\n\t\t\t\tawait this.#openapi.register(route, jsonSchema)\n\t\t\t\tthis.implementations.registerRoute(method, this.#openapi.cleanPath(path), async (req: Req, res: Res) => {\n\t\t\t\t\tconst request = await validateRequest(await this.implementations.parseRequest(req))\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor (const middleware of middlewares) await middleware.cb(request, this.config)\n\t\t\t\t\t\tconst rawRes = await route.handler(request, this.config)\n\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\trawRes instanceof Response\n\t\t\t\t\t\t\t\t? rawRes\n\t\t\t\t\t\t\t\t: new Response({ body: rawRes, status: StatusCodes.Ok, headers: {}, piped: false })\n\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (onError?.cb) {\n\t\t\t\t\t\t\tconst rawResponse = await onError.cb(request, this.config, error as Error)\n\t\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\t\trawResponse instanceof Response\n\t\t\t\t\t\t\t\t\t? rawResponse\n\t\t\t\t\t\t\t\t\t: new Response({ body: rawResponse, status: StatusCodes.BadRequest, headers: {} })\n\t\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t}\n\n\t#resolveSchema(method: MethodsEnum, schema: RouteDef) {\n\t\tconst defaultStatusCode = schema?.defaultStatusCode ?? StatusCodes.Ok\n\t\tconst defaultContentType = schema?.defaultContentType ?? 'application/json'\n\t\tlet status = defaultStatusCode\n\t\tlet contentType = defaultContentType\n\t\tconst jsonSchema: OpenApiSchemaDef = { response: {}, request: {} }\n\t\tconst requestPipeDefs: Pick<RouteDef, 'body' | 'headers' | 'query' | 'params' | 'cookies'> = {}\n\t\tconst responsePipeDefs: Pick<RouteDef, 'response' | 'responseHeaders' | 'responseCookies'> = {}\n\n\t\tconst defs: {\n\t\t\tkey: Exclude<keyof RouteDef, `default${string}` | 'context'>\n\t\t\ttype: keyof OpenApiSchemaDef\n\t\t\tskip?: boolean\n\t\t}[] = [\n\t\t\t{ key: 'params', type: 'request' },\n\t\t\t{ key: 'headers', type: 'request' },\n\t\t\t{ key: 'cookies', type: 'request' },\n\t\t\t{ key: 'query', type: 'request' },\n\t\t\t{ key: 'body', type: 'request', skip: !(<MethodsEnum[]>[Methods.post, Methods.put, Methods.patch]).includes(method) },\n\t\t\t{ key: 'response', type: 'response' },\n\t\t\t{ key: 'responseHeaders', type: 'response' },\n\t\t\t{ key: 'responseCookies', type: 'response' },\n\t\t]\n\t\tdefs.forEach((def) => {\n\t\t\tconst pipe = schema[def.key] ?? v.any()\n\t\t\tif (def.skip) return\n\n\t\t\tif (def.type === 'request') {\n\t\t\t\trequestPipeDefs[def.key] = pipe\n\t\t\t\tjsonSchema.request[def.key as keyof typeof jsonSchema.request] = v.schema(pipe)\n\t\t\t}\n\t\t\tif (def.type === 'response') {\n\t\t\t\tconst pipeRecords = errorsSchemas.concat({ status: defaultStatusCode, contentType, pipe })\n\t\t\t\tresponsePipeDefs[def.key] = v.any().pipe((input) => {\n\t\t\t\t\tconst p = pipeRecords.find((r) => r.status === status)?.pipe\n\t\t\t\t\tif (!p) throw PipeError.root(`schema not defined for status code: ${status}`, input)\n\t\t\t\t\treturn v.assert(p, input)\n\t\t\t\t})\n\t\t\t\tjsonSchema.response[def.key as keyof typeof jsonSchema.response] = pipeRecords.map((record) => ({\n\t\t\t\t\tstatus: record.status,\n\t\t\t\t\tcontentType: record.contentType,\n\t\t\t\t\tschema: v.schema(record.pipe),\n\t\t\t\t}))\n\t\t\t}\n\t\t})\n\t\tconst requestPipe = v.object(requestPipeDefs)\n\t\tv.compile(requestPipe, { allErrors: true })\n\t\tconst responsePipe = v.object(responsePipeDefs)\n\t\tv.compile(responsePipe, { allErrors: true })\n\t\tconst validateRequest: RequestValidator = async (request) => {\n\t\t\tif (!Object.keys(requestPipeDefs)) return request\n\t\t\tconst validity = requestLocalStorage.run(request, () =>\n\t\t\t\tv.validate(requestPipe, {\n\t\t\t\t\tparams: request.params,\n\t\t\t\t\theaders: request.headers,\n\t\t\t\t\tquery: request.query,\n\t\t\t\t\tbody: request.body,\n\t\t\t\t\tcookies: request.cookies,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\trequest.params = validity.value.params!\n\t\t\trequest.headers = validity.value.headers!\n\t\t\trequest.query = validity.value.query!\n\t\t\trequest.body = validity.value.body!\n\t\t\trequest.cookies = validity.value.cookies!\n\t\t\treturn request\n\t\t}\n\t\tconst validateResponse: ResponseValidator = async (response) => {\n\t\t\tif (!Object.keys(responsePipeDefs)) return response\n\t\t\tstatus = response.status\n\t\t\tcontentType = response.contentType\n\n\t\t\tconst validity = responseLocalStorage.run(response, () =>\n\t\t\t\tv.validate(responsePipe, {\n\t\t\t\t\tresponseHeaders: response.headers,\n\t\t\t\t\tresponseCookies: Object.fromEntries(Object.entries(response.cookies).map(([key, val]) => [key, val.value] as const)),\n\t\t\t\t\tresponse: response.body,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\tresponse.body = validity.value.response!\n\t\t\tresponse.headers = validity.value.responseHeaders!\n\t\t\tresponse.cookieValues = validity.value.responseCookies!\n\t\t\treturn response\n\t\t}\n\t\treturn {\n\t\t\tjsonSchema,\n\t\t\tvalidateRequest,\n\t\t\tvalidateResponse,\n\t\t}\n\t}\n\n\ttest() {\n\t\treturn supertest(this.server)\n\t}\n\n\tasync start() {\n\t\tconst port = this.config.port\n\t\tconst instance = Instance.get()\n\t\tconst { app } = instance.settings\n\t\tif (this.config.healthPath)\n\t\t\tthis.addRoute({\n\t\t\t\tmethod: Methods.get,\n\t\t\t\tpath: this.config.healthPath,\n\t\t\t\thandler: async (req) =>\n\t\t\t\t\treq.res({\n\t\t\t\t\t\tbody: `${instance.id}(${app.name}) service running`,\n\t\t\t\t\t\tcontentType: 'text/plain',\n\t\t\t\t\t}),\n\t\t\t})\n\n\t\tthis.implementations.registerNotFoundHandler(async (req) => {\n\t\t\tconst request = await this.implementations.parseRequest(req)\n\t\t\tthrow new NotFoundError(`Route ${request.path} not found`)\n\t\t})\n\t\tthis.implementations.registerErrorHandler(async (error, _, res) => {\n\t\t\tif (!(error instanceof EquippedError)) Instance.get().log.error({ error }, 'Uncaught error in route handler')\n\t\t\tconst response =\n\t\t\t\terror instanceof RequestError\n\t\t\t\t\t? new Response({\n\t\t\t\t\t\t\tbody: error.serializedErrors,\n\t\t\t\t\t\t\tstatus: error.statusCode,\n\t\t\t\t\t\t})\n\t\t\t\t\t: new Response({\n\t\t\t\t\t\t\tbody: [{ message: 'Something went wrong', data: error.message }],\n\t\t\t\t\t\t\tstatus: StatusCodes.BadRequest,\n\t\t\t\t\t\t})\n\t\t\treturn await this.implementations.handleResponse(res, response)\n\t\t})\n\n\t\tawait Promise.all(this.#queue.map((cb) => cb()))\n\t\tconst started = await this.implementations.start(port)\n\t\tif (started) Instance.get().log.info(`${instance.id}(${app.name}) service listening on port ${port}`)\n\t\treturn started\n\t}\n}\n"],"mappings":"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","names":["SocketServer","supertest","PipeError","v","EquippedError","NotFoundError","RequestError","Instance","pipeErrorToValidationError","requestLocalStorage","responseLocalStorage","OpenApi","Response","SocketEmitter","Methods","StatusCodes","errorsSchemas","value","key","Server","server","config","implementations","#openapi","socketInstance","#queue","#routesByKey","_","cb","m","routers","router","routes","route","method","path","schema","onError","middlewares","validateRequest","validateResponse","jsonSchema","#resolveSchema","req","res","request","middleware","rawRes","response","error","rawResponse","defaultStatusCode","defaultContentType","status","contentType","requestPipeDefs","responsePipeDefs","def","pipe","pipeRecords","input","p","r","record","requestPipe","responsePipe","validity","val","port","instance","app","started"]}
@@ -1,3 +1,4 @@
1
+ import {} from "@fastify/cors";
1
2
  import {} from "cors";
2
3
  import { Server as SocketServer } from "socket.io";
3
4
  import supertest from "supertest";
@@ -36,7 +37,7 @@ class Server {
36
37
  server;
37
38
  get cors() {
38
39
  return {
39
- origin: this.config.cors?.origin,
40
+ origin: this.config.cors?.origin ? (_, cb) => cb(null, true) : this.config.cors?.origin,
40
41
  methods: (this.config.cors?.methods ?? Object.values(Methods)).filter((m) => m !== Methods.options).map((m) => m.toUpperCase()),
41
42
  credentials: this.config.cors?.credentials
42
43
  };
@@ -183,7 +184,7 @@ class Server {
183
184
  throw new NotFoundError(`Route ${request.path} not found`);
184
185
  });
185
186
  this.implementations.registerErrorHandler(async (error, _, res) => {
186
- Instance.get().log.error({ error }, "Uncaught error in route handler");
187
+ if (!(error instanceof EquippedError)) Instance.get().log.error({ error }, "Uncaught error in route handler");
187
188
  const response = error instanceof RequestError ? new Response({
188
189
  body: error.serializedErrors,
189
190
  status: error.statusCode
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/server/impls/base.ts"],"sourcesContent":["import type http from 'node:http'\n\nimport { type CorsOptions } from 'cors'\nimport { Server as SocketServer } from 'socket.io'\nimport supertest from 'supertest'\nimport { type Pipe, PipeError, v } from 'valleyed'\n\nimport { EquippedError, NotFoundError, RequestError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { pipeErrorToValidationError } from '../../validations'\nimport { requestLocalStorage, responseLocalStorage } from '../../validations/valleyed'\nimport { OpenApi, type OpenApiSchemaDef } from '../openapi'\nimport type { ServerConfig } from '../pipes'\nimport { type Request, Response } from '../requests'\nimport { Router } from '../routes'\nimport { SocketEmitter } from '../sockets'\nimport { Methods, type MethodsEnum, type Route, type RouteDef, StatusCodes } from '../types'\n\ntype RequestValidator = (req: Request<any>) => Promise<Request<any>>\ntype ResponseValidator = (res: Response<any>) => Promise<Response<any>>\n\nconst errorsSchemas = Object.entries(StatusCodes)\n\t.filter(([, value]) => value > 399)\n\t.map(([key, value]) => ({\n\t\tstatus: value,\n\t\tcontentType: 'application/json',\n\t\tpipe: v.meta(v.array(v.object({ message: v.string(), field: v.optional(v.string()) })), {\n\t\t\t$refId: `Errors.${key}Response`,\n\t\t\tdescription: `${key} Response`,\n\t\t}) as Pipe<any, any>,\n\t}))\n\nexport abstract class Server<Req = any, Res = any> {\n\t#queue: (() => void | Promise<void>)[] = []\n\t#routesByKey = new Map<string, boolean>()\n\t#openapi: OpenApi\n\tsocket: SocketEmitter\n\tprotected server: http.Server\n\tprotected get cors() {\n\t\treturn {\n\t\t\torigin: this.config.cors?.origin,\n\t\t\tmethods: (this.config.cors?.methods ?? Object.values(Methods)).filter((m) => m !== Methods.options).map((m) => m.toUpperCase()),\n\t\t\tcredentials: this.config.cors?.credentials,\n\t\t} satisfies CorsOptions\n\t}\n\n\tconstructor(\n\t\tserver: http.Server,\n\t\tprivate config: ServerConfig,\n\t\tprivate implementations: {\n\t\t\tparseRequest: (req: Req) => Promise<Request<any>>\n\t\t\thandleResponse: (res: Res, response: Response<any>) => Promise<void>\n\t\t\tregisterRoute: (method: MethodsEnum, path: string, cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterErrorHandler: (cb: (error: Error, req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterNotFoundHandler: (cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tstart: (port: number) => Promise<boolean>\n\t\t},\n\t) {\n\t\tthis.server = server\n\t\tthis.#openapi = new OpenApi(config)\n\t\tconst socketInstance = new SocketServer(server, { cors: this.cors })\n\t\tthis.socket = new SocketEmitter(socketInstance, config)\n\t\tthis.addRouter(this.#openapi.router())\n\t}\n\n\taddRouter(...routers: Router<any>[]) {\n\t\trouters.map((router) => router.routes).forEach((routes) => this.addRoute(...routes))\n\t}\n\n\taddRoute<T extends RouteDef>(...routes: Route<T>[]) {\n\t\troutes.forEach((route) => {\n\t\t\tthis.#queue.push(async () => {\n\t\t\t\tconst { method, path, schema = {}, onError, middlewares = [] } = route\n\n\t\t\t\tconst key = `(${method.toUpperCase()}) ${this.#openapi.cleanPath(path)}`\n\t\t\t\tif (this.#routesByKey.get(key))\n\t\t\t\t\tthrow new EquippedError(`Route key ${key} already registered. All route keys must be unique`, { route, key })\n\n\t\t\t\tmiddlewares.forEach((m) => m.onSetup?.(route as any))\n\t\t\t\tonError?.onSetup?.(route as any)\n\n\t\t\t\tconst { validateRequest, validateResponse, jsonSchema } = this.#resolveSchema(method, schema)\n\n\t\t\t\tthis.#routesByKey.set(key, true)\n\t\t\t\tawait this.#openapi.register(route, jsonSchema)\n\t\t\t\tthis.implementations.registerRoute(method, this.#openapi.cleanPath(path), async (req: Req, res: Res) => {\n\t\t\t\t\tconst request = await validateRequest(await this.implementations.parseRequest(req))\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor (const middleware of middlewares) await middleware.cb(request, this.config)\n\t\t\t\t\t\tconst rawRes = await route.handler(request, this.config)\n\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\trawRes instanceof Response\n\t\t\t\t\t\t\t\t? rawRes\n\t\t\t\t\t\t\t\t: new Response({ body: rawRes, status: StatusCodes.Ok, headers: {}, piped: false })\n\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (onError?.cb) {\n\t\t\t\t\t\t\tconst rawResponse = await onError.cb(request, this.config, error as Error)\n\t\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\t\trawResponse instanceof Response\n\t\t\t\t\t\t\t\t\t? rawResponse\n\t\t\t\t\t\t\t\t\t: new Response({ body: rawResponse, status: StatusCodes.BadRequest, headers: {} })\n\t\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t}\n\n\t#resolveSchema(method: MethodsEnum, schema: RouteDef) {\n\t\tconst defaultStatusCode = schema?.defaultStatusCode ?? StatusCodes.Ok\n\t\tconst defaultContentType = schema?.defaultContentType ?? 'application/json'\n\t\tlet status = defaultStatusCode\n\t\tlet contentType = defaultContentType\n\t\tconst jsonSchema: OpenApiSchemaDef = { response: {}, request: {} }\n\t\tconst requestPipeDefs: Pick<RouteDef, 'body' | 'headers' | 'query' | 'params' | 'cookies'> = {}\n\t\tconst responsePipeDefs: Pick<RouteDef, 'response' | 'responseHeaders' | 'responseCookies'> = {}\n\n\t\tconst defs: {\n\t\t\tkey: Exclude<keyof RouteDef, `default${string}` | 'context'>\n\t\t\ttype: keyof OpenApiSchemaDef\n\t\t\tskip?: boolean\n\t\t}[] = [\n\t\t\t{ key: 'params', type: 'request' },\n\t\t\t{ key: 'headers', type: 'request' },\n\t\t\t{ key: 'cookies', type: 'request' },\n\t\t\t{ key: 'query', type: 'request' },\n\t\t\t{ key: 'body', type: 'request', skip: !(<MethodsEnum[]>[Methods.post, Methods.put, Methods.patch]).includes(method) },\n\t\t\t{ key: 'response', type: 'response' },\n\t\t\t{ key: 'responseHeaders', type: 'response' },\n\t\t\t{ key: 'responseCookies', type: 'response' },\n\t\t]\n\t\tdefs.forEach((def) => {\n\t\t\tconst pipe = schema[def.key] ?? v.any()\n\t\t\tif (def.skip) return\n\n\t\t\tif (def.type === 'request') {\n\t\t\t\trequestPipeDefs[def.key] = pipe\n\t\t\t\tjsonSchema.request[def.key as keyof typeof jsonSchema.request] = v.schema(pipe)\n\t\t\t}\n\t\t\tif (def.type === 'response') {\n\t\t\t\tconst pipeRecords = errorsSchemas.concat({ status: defaultStatusCode, contentType, pipe })\n\t\t\t\tresponsePipeDefs[def.key] = v.any().pipe((input) => {\n\t\t\t\t\tconst p = pipeRecords.find((r) => r.status === status)?.pipe\n\t\t\t\t\tif (!p) throw PipeError.root(`schema not defined for status code: ${status}`, input)\n\t\t\t\t\treturn v.assert(p, input)\n\t\t\t\t})\n\t\t\t\tjsonSchema.response[def.key as keyof typeof jsonSchema.response] = pipeRecords.map((record) => ({\n\t\t\t\t\tstatus: record.status,\n\t\t\t\t\tcontentType: record.contentType,\n\t\t\t\t\tschema: v.schema(record.pipe),\n\t\t\t\t}))\n\t\t\t}\n\t\t})\n\t\tconst requestPipe = v.object(requestPipeDefs)\n\t\tv.compile(requestPipe, { allErrors: true })\n\t\tconst responsePipe = v.object(responsePipeDefs)\n\t\tv.compile(responsePipe, { allErrors: true })\n\t\tconst validateRequest: RequestValidator = async (request) => {\n\t\t\tif (!Object.keys(requestPipeDefs)) return request\n\t\t\tconst validity = requestLocalStorage.run(request, () =>\n\t\t\t\tv.validate(requestPipe, {\n\t\t\t\t\tparams: request.params,\n\t\t\t\t\theaders: request.headers,\n\t\t\t\t\tquery: request.query,\n\t\t\t\t\tbody: request.body,\n\t\t\t\t\tcookies: request.cookies,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\trequest.params = validity.value.params!\n\t\t\trequest.headers = validity.value.headers!\n\t\t\trequest.query = validity.value.query!\n\t\t\trequest.body = validity.value.body!\n\t\t\trequest.cookies = validity.value.cookies!\n\t\t\treturn request\n\t\t}\n\t\tconst validateResponse: ResponseValidator = async (response) => {\n\t\t\tif (!Object.keys(responsePipeDefs)) return response\n\t\t\tstatus = response.status\n\t\t\tcontentType = response.contentType\n\n\t\t\tconst validity = responseLocalStorage.run(response, () =>\n\t\t\t\tv.validate(responsePipe, {\n\t\t\t\t\tresponseHeaders: response.headers,\n\t\t\t\t\tresponseCookies: Object.fromEntries(Object.entries(response.cookies).map(([key, val]) => [key, val.value] as const)),\n\t\t\t\t\tresponse: response.body,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\tresponse.body = validity.value.response!\n\t\t\tresponse.headers = validity.value.responseHeaders!\n\t\t\tresponse.cookieValues = validity.value.responseCookies!\n\t\t\treturn response\n\t\t}\n\t\treturn {\n\t\t\tjsonSchema,\n\t\t\tvalidateRequest,\n\t\t\tvalidateResponse,\n\t\t}\n\t}\n\n\ttest() {\n\t\treturn supertest(this.server)\n\t}\n\n\tasync start() {\n\t\tconst port = this.config.port\n\t\tconst instance = Instance.get()\n\t\tconst { app } = instance.settings\n\t\tif (this.config.healthPath)\n\t\t\tthis.addRoute({\n\t\t\t\tmethod: Methods.get,\n\t\t\t\tpath: this.config.healthPath,\n\t\t\t\thandler: async (req) =>\n\t\t\t\t\treq.res({\n\t\t\t\t\t\tbody: `${instance.id}(${app.name}) service running`,\n\t\t\t\t\t\tcontentType: 'text/plain',\n\t\t\t\t\t}),\n\t\t\t})\n\n\t\tthis.implementations.registerNotFoundHandler(async (req) => {\n\t\t\tconst request = await this.implementations.parseRequest(req)\n\t\t\tthrow new NotFoundError(`Route ${request.path} not found`)\n\t\t})\n\t\tthis.implementations.registerErrorHandler(async (error, _, res) => {\n\t\t\tInstance.get().log.error({ error }, 'Uncaught error in route handler')\n\t\t\tconst response =\n\t\t\t\terror instanceof RequestError\n\t\t\t\t\t? new Response({\n\t\t\t\t\t\t\tbody: error.serializedErrors,\n\t\t\t\t\t\t\tstatus: error.statusCode,\n\t\t\t\t\t\t})\n\t\t\t\t\t: new Response({\n\t\t\t\t\t\t\tbody: [{ message: 'Something went wrong', data: error.message }],\n\t\t\t\t\t\t\tstatus: StatusCodes.BadRequest,\n\t\t\t\t\t\t})\n\t\t\treturn await this.implementations.handleResponse(res, response)\n\t\t})\n\n\t\tawait Promise.all(this.#queue.map((cb) => cb()))\n\t\tconst started = await this.implementations.start(port)\n\t\tif (started) Instance.get().log.info(`${instance.id}(${app.name}) service listening on port ${port}`)\n\t\treturn started\n\t}\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/server/impls/base.ts"],"sourcesContent":["import type http from 'node:http'\n\nimport { type FastifyCorsOptions } from '@fastify/cors'\nimport { type CorsOptions } from 'cors'\nimport { Server as SocketServer } from 'socket.io'\nimport supertest from 'supertest'\nimport { type Pipe, PipeError, v } from 'valleyed'\n\nimport { EquippedError, NotFoundError, RequestError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { pipeErrorToValidationError } from '../../validations'\nimport { requestLocalStorage, responseLocalStorage } from '../../validations/valleyed'\nimport { OpenApi, type OpenApiSchemaDef } from '../openapi'\nimport type { ServerConfig } from '../pipes'\nimport { type Request, Response } from '../requests'\nimport { Router } from '../routes'\nimport { SocketEmitter } from '../sockets'\nimport { Methods, type MethodsEnum, type Route, type RouteDef, StatusCodes } from '../types'\n\ntype RequestValidator = (req: Request<any>) => Promise<Request<any>>\ntype ResponseValidator = (res: Response<any>) => Promise<Response<any>>\n\nconst errorsSchemas = Object.entries(StatusCodes)\n\t.filter(([, value]) => value > 399)\n\t.map(([key, value]) => ({\n\t\tstatus: value,\n\t\tcontentType: 'application/json',\n\t\tpipe: v.meta(v.array(v.object({ message: v.string(), field: v.optional(v.string()) })), {\n\t\t\t$refId: `Errors.${key}Response`,\n\t\t\tdescription: `${key} Response`,\n\t\t}) as Pipe<any, any>,\n\t}))\n\nexport abstract class Server<Req = any, Res = any> {\n\t#queue: (() => void | Promise<void>)[] = []\n\t#routesByKey = new Map<string, boolean>()\n\t#openapi: OpenApi\n\tsocket: SocketEmitter\n\tprotected server: http.Server\n\tprotected get cors(): CorsOptions & FastifyCorsOptions {\n\t\treturn {\n\t\t\torigin: this.config.cors?.origin ? (_, cb) => cb(null, true) : this.config.cors?.origin,\n\t\t\tmethods: (this.config.cors?.methods ?? Object.values(Methods)).filter((m) => m !== Methods.options).map((m) => m.toUpperCase()),\n\t\t\tcredentials: this.config.cors?.credentials,\n\t\t}\n\t}\n\n\tconstructor(\n\t\tserver: http.Server,\n\t\tprivate config: ServerConfig,\n\t\tprivate implementations: {\n\t\t\tparseRequest: (req: Req) => Promise<Request<any>>\n\t\t\thandleResponse: (res: Res, response: Response<any>) => Promise<void>\n\t\t\tregisterRoute: (method: MethodsEnum, path: string, cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterErrorHandler: (cb: (error: Error, req: Req, res: Res) => Promise<void>) => void\n\t\t\tregisterNotFoundHandler: (cb: (req: Req, res: Res) => Promise<void>) => void\n\t\t\tstart: (port: number) => Promise<boolean>\n\t\t},\n\t) {\n\t\tthis.server = server\n\t\tthis.#openapi = new OpenApi(config)\n\t\tconst socketInstance = new SocketServer(server, { cors: this.cors })\n\t\tthis.socket = new SocketEmitter(socketInstance, config)\n\t\tthis.addRouter(this.#openapi.router())\n\t}\n\n\taddRouter(...routers: Router<any>[]) {\n\t\trouters.map((router) => router.routes).forEach((routes) => this.addRoute(...routes))\n\t}\n\n\taddRoute<T extends RouteDef>(...routes: Route<T>[]) {\n\t\troutes.forEach((route) => {\n\t\t\tthis.#queue.push(async () => {\n\t\t\t\tconst { method, path, schema = {}, onError, middlewares = [] } = route\n\n\t\t\t\tconst key = `(${method.toUpperCase()}) ${this.#openapi.cleanPath(path)}`\n\t\t\t\tif (this.#routesByKey.get(key))\n\t\t\t\t\tthrow new EquippedError(`Route key ${key} already registered. All route keys must be unique`, { route, key })\n\n\t\t\t\tmiddlewares.forEach((m) => m.onSetup?.(route as any))\n\t\t\t\tonError?.onSetup?.(route as any)\n\n\t\t\t\tconst { validateRequest, validateResponse, jsonSchema } = this.#resolveSchema(method, schema)\n\n\t\t\t\tthis.#routesByKey.set(key, true)\n\t\t\t\tawait this.#openapi.register(route, jsonSchema)\n\t\t\t\tthis.implementations.registerRoute(method, this.#openapi.cleanPath(path), async (req: Req, res: Res) => {\n\t\t\t\t\tconst request = await validateRequest(await this.implementations.parseRequest(req))\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor (const middleware of middlewares) await middleware.cb(request, this.config)\n\t\t\t\t\t\tconst rawRes = await route.handler(request, this.config)\n\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\trawRes instanceof Response\n\t\t\t\t\t\t\t\t? rawRes\n\t\t\t\t\t\t\t\t: new Response({ body: rawRes, status: StatusCodes.Ok, headers: {}, piped: false })\n\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (onError?.cb) {\n\t\t\t\t\t\t\tconst rawResponse = await onError.cb(request, this.config, error as Error)\n\t\t\t\t\t\t\tconst response =\n\t\t\t\t\t\t\t\trawResponse instanceof Response\n\t\t\t\t\t\t\t\t\t? rawResponse\n\t\t\t\t\t\t\t\t\t: new Response({ body: rawResponse, status: StatusCodes.BadRequest, headers: {} })\n\t\t\t\t\t\t\treturn await this.implementations.handleResponse(res, await validateResponse(response))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t})\n\t}\n\n\t#resolveSchema(method: MethodsEnum, schema: RouteDef) {\n\t\tconst defaultStatusCode = schema?.defaultStatusCode ?? StatusCodes.Ok\n\t\tconst defaultContentType = schema?.defaultContentType ?? 'application/json'\n\t\tlet status = defaultStatusCode\n\t\tlet contentType = defaultContentType\n\t\tconst jsonSchema: OpenApiSchemaDef = { response: {}, request: {} }\n\t\tconst requestPipeDefs: Pick<RouteDef, 'body' | 'headers' | 'query' | 'params' | 'cookies'> = {}\n\t\tconst responsePipeDefs: Pick<RouteDef, 'response' | 'responseHeaders' | 'responseCookies'> = {}\n\n\t\tconst defs: {\n\t\t\tkey: Exclude<keyof RouteDef, `default${string}` | 'context'>\n\t\t\ttype: keyof OpenApiSchemaDef\n\t\t\tskip?: boolean\n\t\t}[] = [\n\t\t\t{ key: 'params', type: 'request' },\n\t\t\t{ key: 'headers', type: 'request' },\n\t\t\t{ key: 'cookies', type: 'request' },\n\t\t\t{ key: 'query', type: 'request' },\n\t\t\t{ key: 'body', type: 'request', skip: !(<MethodsEnum[]>[Methods.post, Methods.put, Methods.patch]).includes(method) },\n\t\t\t{ key: 'response', type: 'response' },\n\t\t\t{ key: 'responseHeaders', type: 'response' },\n\t\t\t{ key: 'responseCookies', type: 'response' },\n\t\t]\n\t\tdefs.forEach((def) => {\n\t\t\tconst pipe = schema[def.key] ?? v.any()\n\t\t\tif (def.skip) return\n\n\t\t\tif (def.type === 'request') {\n\t\t\t\trequestPipeDefs[def.key] = pipe\n\t\t\t\tjsonSchema.request[def.key as keyof typeof jsonSchema.request] = v.schema(pipe)\n\t\t\t}\n\t\t\tif (def.type === 'response') {\n\t\t\t\tconst pipeRecords = errorsSchemas.concat({ status: defaultStatusCode, contentType, pipe })\n\t\t\t\tresponsePipeDefs[def.key] = v.any().pipe((input) => {\n\t\t\t\t\tconst p = pipeRecords.find((r) => r.status === status)?.pipe\n\t\t\t\t\tif (!p) throw PipeError.root(`schema not defined for status code: ${status}`, input)\n\t\t\t\t\treturn v.assert(p, input)\n\t\t\t\t})\n\t\t\t\tjsonSchema.response[def.key as keyof typeof jsonSchema.response] = pipeRecords.map((record) => ({\n\t\t\t\t\tstatus: record.status,\n\t\t\t\t\tcontentType: record.contentType,\n\t\t\t\t\tschema: v.schema(record.pipe),\n\t\t\t\t}))\n\t\t\t}\n\t\t})\n\t\tconst requestPipe = v.object(requestPipeDefs)\n\t\tv.compile(requestPipe, { allErrors: true })\n\t\tconst responsePipe = v.object(responsePipeDefs)\n\t\tv.compile(responsePipe, { allErrors: true })\n\t\tconst validateRequest: RequestValidator = async (request) => {\n\t\t\tif (!Object.keys(requestPipeDefs)) return request\n\t\t\tconst validity = requestLocalStorage.run(request, () =>\n\t\t\t\tv.validate(requestPipe, {\n\t\t\t\t\tparams: request.params,\n\t\t\t\t\theaders: request.headers,\n\t\t\t\t\tquery: request.query,\n\t\t\t\t\tbody: request.body,\n\t\t\t\t\tcookies: request.cookies,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\trequest.params = validity.value.params!\n\t\t\trequest.headers = validity.value.headers!\n\t\t\trequest.query = validity.value.query!\n\t\t\trequest.body = validity.value.body!\n\t\t\trequest.cookies = validity.value.cookies!\n\t\t\treturn request\n\t\t}\n\t\tconst validateResponse: ResponseValidator = async (response) => {\n\t\t\tif (!Object.keys(responsePipeDefs)) return response\n\t\t\tstatus = response.status\n\t\t\tcontentType = response.contentType\n\n\t\t\tconst validity = responseLocalStorage.run(response, () =>\n\t\t\t\tv.validate(responsePipe, {\n\t\t\t\t\tresponseHeaders: response.headers,\n\t\t\t\t\tresponseCookies: Object.fromEntries(Object.entries(response.cookies).map(([key, val]) => [key, val.value] as const)),\n\t\t\t\t\tresponse: response.body,\n\t\t\t\t}),\n\t\t\t)\n\n\t\t\tif (!validity.valid) throw pipeErrorToValidationError(validity.error)\n\t\t\tresponse.body = validity.value.response!\n\t\t\tresponse.headers = validity.value.responseHeaders!\n\t\t\tresponse.cookieValues = validity.value.responseCookies!\n\t\t\treturn response\n\t\t}\n\t\treturn {\n\t\t\tjsonSchema,\n\t\t\tvalidateRequest,\n\t\t\tvalidateResponse,\n\t\t}\n\t}\n\n\ttest() {\n\t\treturn supertest(this.server)\n\t}\n\n\tasync start() {\n\t\tconst port = this.config.port\n\t\tconst instance = Instance.get()\n\t\tconst { app } = instance.settings\n\t\tif (this.config.healthPath)\n\t\t\tthis.addRoute({\n\t\t\t\tmethod: Methods.get,\n\t\t\t\tpath: this.config.healthPath,\n\t\t\t\thandler: async (req) =>\n\t\t\t\t\treq.res({\n\t\t\t\t\t\tbody: `${instance.id}(${app.name}) service running`,\n\t\t\t\t\t\tcontentType: 'text/plain',\n\t\t\t\t\t}),\n\t\t\t})\n\n\t\tthis.implementations.registerNotFoundHandler(async (req) => {\n\t\t\tconst request = await this.implementations.parseRequest(req)\n\t\t\tthrow new NotFoundError(`Route ${request.path} not found`)\n\t\t})\n\t\tthis.implementations.registerErrorHandler(async (error, _, res) => {\n\t\t\tif (!(error instanceof EquippedError)) Instance.get().log.error({ error }, 'Uncaught error in route handler')\n\t\t\tconst response =\n\t\t\t\terror instanceof RequestError\n\t\t\t\t\t? new Response({\n\t\t\t\t\t\t\tbody: error.serializedErrors,\n\t\t\t\t\t\t\tstatus: error.statusCode,\n\t\t\t\t\t\t})\n\t\t\t\t\t: new Response({\n\t\t\t\t\t\t\tbody: [{ message: 'Something went wrong', data: error.message }],\n\t\t\t\t\t\t\tstatus: StatusCodes.BadRequest,\n\t\t\t\t\t\t})\n\t\t\treturn await this.implementations.handleResponse(res, response)\n\t\t})\n\n\t\tawait Promise.all(this.#queue.map((cb) => cb()))\n\t\tconst started = await this.implementations.start(port)\n\t\tif (started) Instance.get().log.info(`${instance.id}(${app.name}) service listening on port ${port}`)\n\t\treturn started\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -1,2 +1,2 @@
1
- import{v as e}from"valleyed";import{EventBus as o}from "../events/index.min.mjs";import{BaseRequestAuthMethod as a}from "./requests-auth-methods/index.min.mjs";import{Methods as r}from "./types.min.mjs";const t=()=>e.object({port:e.number(),cors:e.optional(e.object({origin:e.optional(e.array(e.string())),methods:e.optional(e.array(e.in(Object.values(r)))),credentials:e.optional(e.boolean())})),eventBus:e.optional(e.instanceOf(o)),publicPath:e.optional(e.string()),healthPath:e.optional(e.string()),openapi:e.defaults(e.object({docsVersion:e.defaults(e.string(),"1.0.0"),docsBaseUrl:e.defaults(e.array(e.string()),["/"]),docsPath:e.defaults(e.string(),"/__docs")}),{}),requests:e.defaults(e.object({log:e.defaults(e.boolean(),!0),rateLimit:e.defaults(e.object({enabled:e.defaults(e.boolean(),!1),periodInMs:e.defaults(e.number(),3600*1e3),limit:e.defaults(e.number(),5e3)}),{}),slowdown:e.defaults(e.object({enabled:e.defaults(e.boolean(),!1),periodInMs:e.defaults(e.number(),600*1e3),delayAfter:e.defaults(e.number(),2e3),delayInMs:e.defaults(e.number(),500)}),{})}),{}),socketsAuthMethods:e.defaults(e.array(e.instanceOf(a)),[])}),u=()=>e.discriminate(s=>s.type,{fastify:e.merge(t(),e.object({type:e.is("fastify")})),express:e.merge(t(),e.object({type:e.is("express")}))});export{u as serverConfigPipe};
1
+ import{v as e}from"valleyed";import{EventBus as o}from "../events/index.min.mjs";import{BaseRequestAuthMethod as r}from "./requests-auth-methods/index.min.mjs";import{Methods as a}from "./types.min.mjs";const t=()=>e.object({port:e.number(),cors:e.optional(e.object({origin:e.optional(e.or([e.array(e.string()),e.is(!0)])),methods:e.optional(e.array(e.in(Object.values(a)))),credentials:e.optional(e.boolean())})),eventBus:e.optional(e.instanceOf(o)),publicPath:e.optional(e.string()),healthPath:e.optional(e.string()),openapi:e.defaults(e.object({docsVersion:e.defaults(e.string(),"1.0.0"),docsBaseUrl:e.defaults(e.array(e.string()),["/"]),docsPath:e.defaults(e.string(),"/__docs")}),{}),requests:e.defaults(e.object({log:e.defaults(e.boolean(),!0),rateLimit:e.defaults(e.object({enabled:e.defaults(e.boolean(),!1),periodInMs:e.defaults(e.number(),3600*1e3),limit:e.defaults(e.number(),5e3)}),{}),slowdown:e.defaults(e.object({enabled:e.defaults(e.boolean(),!1),periodInMs:e.defaults(e.number(),600*1e3),delayAfter:e.defaults(e.number(),2e3),delayInMs:e.defaults(e.number(),500)}),{})}),{}),socketsAuthMethods:e.defaults(e.array(e.instanceOf(r)),[])}),p=()=>e.discriminate(s=>s.type,{fastify:e.merge(t(),e.object({type:e.is("fastify")})),express:e.merge(t(),e.object({type:e.is("express")}))});export{p as serverConfigPipe};
2
2
  //# sourceMappingURL=pipes.min.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/pipes.ts"],"sourcesContent":["import { type PipeOutput, v } from 'valleyed'\n\nimport { EventBus } from '../events'\nimport type { AuthUser } from '../types'\nimport { BaseRequestAuthMethod } from './requests-auth-methods'\nimport { Methods } from './types'\n\nconst serverBasePipe = () =>\n\tv.object({\n\t\tport: v.number(),\n\t\tcors: v.optional(\n\t\t\tv.object({\n\t\t\t\torigin: v.optional(v.array(v.string())),\n\t\t\t\tmethods: v.optional(v.array(v.in(Object.values(Methods)))),\n\t\t\t\tcredentials: v.optional(v.boolean()),\n\t\t\t}),\n\t\t),\n\t\teventBus: v.optional(v.instanceOf(EventBus)),\n\t\tpublicPath: v.optional(v.string()),\n\t\thealthPath: v.optional(v.string()),\n\t\topenapi: v.defaults(\n\t\t\tv.object({\n\t\t\t\tdocsVersion: v.defaults(v.string(), '1.0.0'),\n\t\t\t\tdocsBaseUrl: v.defaults(v.array(v.string()), ['/']),\n\t\t\t\tdocsPath: v.defaults(v.string(), '/__docs'),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\trequests: v.defaults(\n\t\t\tv.object({\n\t\t\t\tlog: v.defaults(v.boolean(), true),\n\t\t\t\trateLimit: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 60 * 60 * 1000),\n\t\t\t\t\t\tlimit: v.defaults(v.number(), 5000),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t\tslowdown: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 10 * 60 * 1000),\n\t\t\t\t\t\tdelayAfter: v.defaults(v.number(), 2000),\n\t\t\t\t\t\tdelayInMs: v.defaults(v.number(), 500),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\tsocketsAuthMethods: v.defaults(v.array(v.instanceOf(BaseRequestAuthMethod<AuthUser>)), []),\n\t})\n\nexport const serverConfigPipe = () =>\n\tv.discriminate((d: any) => d.type, {\n\t\tfastify: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('fastify' as const),\n\t\t\t}),\n\t\t),\n\t\texpress: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('express' as const),\n\t\t\t}),\n\t\t),\n\t})\n\nexport type ServerConfig = PipeOutput<ReturnType<typeof serverConfigPipe>>\n"],"mappings":"AAAA,OAA0B,KAAAA,MAAS,WAEnC,OAAS,YAAAC,MAAgB,YAEzB,OAAS,yBAAAC,MAA6B,0BACtC,OAAS,WAAAC,MAAe,UAExB,MAAMC,EAAiB,IACtBJ,EAAE,OAAO,CACR,KAAMA,EAAE,OAAO,EACf,KAAMA,EAAE,SACPA,EAAE,OAAO,CACR,OAAQA,EAAE,SAASA,EAAE,MAAMA,EAAE,OAAO,CAAC,CAAC,EACtC,QAASA,EAAE,SAASA,EAAE,MAAMA,EAAE,GAAG,OAAO,OAAOG,CAAO,CAAC,CAAC,CAAC,EACzD,YAAaH,EAAE,SAASA,EAAE,QAAQ,CAAC,CACpC,CAAC,CACF,EACA,SAAUA,EAAE,SAASA,EAAE,WAAWC,CAAQ,CAAC,EAC3C,WAAYD,EAAE,SAASA,EAAE,OAAO,CAAC,EACjC,WAAYA,EAAE,SAASA,EAAE,OAAO,CAAC,EACjC,QAASA,EAAE,SACVA,EAAE,OAAO,CACR,YAAaA,EAAE,SAASA,EAAE,OAAO,EAAG,OAAO,EAC3C,YAAaA,EAAE,SAASA,EAAE,MAAMA,EAAE,OAAO,CAAC,EAAG,CAAC,GAAG,CAAC,EAClD,SAAUA,EAAE,SAASA,EAAE,OAAO,EAAG,SAAS,CAC3C,CAAC,EACD,CAAC,CACF,EACA,SAAUA,EAAE,SACXA,EAAE,OAAO,CACR,IAAKA,EAAE,SAASA,EAAE,QAAQ,EAAG,EAAI,EACjC,UAAWA,EAAE,SACZA,EAAE,OAAO,CACR,QAASA,EAAE,SAASA,EAAE,QAAQ,EAAG,EAAK,EACtC,WAAYA,EAAE,SAASA,EAAE,OAAO,EAAG,KAAU,GAAI,EACjD,MAAOA,EAAE,SAASA,EAAE,OAAO,EAAG,GAAI,CACnC,CAAC,EACD,CAAC,CACF,EACA,SAAUA,EAAE,SACXA,EAAE,OAAO,CACR,QAASA,EAAE,SAASA,EAAE,QAAQ,EAAG,EAAK,EACtC,WAAYA,EAAE,SAASA,EAAE,OAAO,EAAG,IAAU,GAAI,EACjD,WAAYA,EAAE,SAASA,EAAE,OAAO,EAAG,GAAI,EACvC,UAAWA,EAAE,SAASA,EAAE,OAAO,EAAG,GAAG,CACtC,CAAC,EACD,CAAC,CACF,CACD,CAAC,EACD,CAAC,CACF,EACA,mBAAoBA,EAAE,SAASA,EAAE,MAAMA,EAAE,WAAWE,CAA+B,CAAC,EAAG,CAAC,CAAC,CAC1F,CAAC,EAEWG,EAAmB,IAC/BL,EAAE,aAAcM,GAAWA,EAAE,KAAM,CAClC,QAASN,EAAE,MACVI,EAAe,EACfJ,EAAE,OAAO,CACR,KAAMA,EAAE,GAAG,SAAkB,CAC9B,CAAC,CACF,EACA,QAASA,EAAE,MACVI,EAAe,EACfJ,EAAE,OAAO,CACR,KAAMA,EAAE,GAAG,SAAkB,CAC9B,CAAC,CACF,CACD,CAAC","names":["v","EventBus","BaseRequestAuthMethod","Methods","serverBasePipe","serverConfigPipe","d"]}
1
+ {"version":3,"sources":["../../../src/server/pipes.ts"],"sourcesContent":["import { type PipeOutput, v } from 'valleyed'\n\nimport { EventBus } from '../events'\nimport type { AuthUser } from '../types'\nimport { BaseRequestAuthMethod } from './requests-auth-methods'\nimport { Methods } from './types'\n\nconst serverBasePipe = () =>\n\tv.object({\n\t\tport: v.number(),\n\t\tcors: v.optional(\n\t\t\tv.object({\n\t\t\t\torigin: v.optional(v.or([v.array(v.string()), v.is(true)])),\n\t\t\t\tmethods: v.optional(v.array(v.in(Object.values(Methods)))),\n\t\t\t\tcredentials: v.optional(v.boolean()),\n\t\t\t}),\n\t\t),\n\t\teventBus: v.optional(v.instanceOf(EventBus)),\n\t\tpublicPath: v.optional(v.string()),\n\t\thealthPath: v.optional(v.string()),\n\t\topenapi: v.defaults(\n\t\t\tv.object({\n\t\t\t\tdocsVersion: v.defaults(v.string(), '1.0.0'),\n\t\t\t\tdocsBaseUrl: v.defaults(v.array(v.string()), ['/']),\n\t\t\t\tdocsPath: v.defaults(v.string(), '/__docs'),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\trequests: v.defaults(\n\t\t\tv.object({\n\t\t\t\tlog: v.defaults(v.boolean(), true),\n\t\t\t\trateLimit: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 60 * 60 * 1000),\n\t\t\t\t\t\tlimit: v.defaults(v.number(), 5000),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t\tslowdown: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 10 * 60 * 1000),\n\t\t\t\t\t\tdelayAfter: v.defaults(v.number(), 2000),\n\t\t\t\t\t\tdelayInMs: v.defaults(v.number(), 500),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\tsocketsAuthMethods: v.defaults(v.array(v.instanceOf(BaseRequestAuthMethod<AuthUser>)), []),\n\t})\n\nexport const serverConfigPipe = () =>\n\tv.discriminate((d: any) => d.type, {\n\t\tfastify: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('fastify' as const),\n\t\t\t}),\n\t\t),\n\t\texpress: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('express' as const),\n\t\t\t}),\n\t\t),\n\t})\n\nexport type ServerConfig = PipeOutput<ReturnType<typeof serverConfigPipe>>\n"],"mappings":"AAAA,OAA0B,KAAAA,MAAS,WAEnC,OAAS,YAAAC,MAAgB,YAEzB,OAAS,yBAAAC,MAA6B,0BACtC,OAAS,WAAAC,MAAe,UAExB,MAAMC,EAAiB,IACtBJ,EAAE,OAAO,CACR,KAAMA,EAAE,OAAO,EACf,KAAMA,EAAE,SACPA,EAAE,OAAO,CACR,OAAQA,EAAE,SAASA,EAAE,GAAG,CAACA,EAAE,MAAMA,EAAE,OAAO,CAAC,EAAGA,EAAE,GAAG,EAAI,CAAC,CAAC,CAAC,EAC1D,QAASA,EAAE,SAASA,EAAE,MAAMA,EAAE,GAAG,OAAO,OAAOG,CAAO,CAAC,CAAC,CAAC,EACzD,YAAaH,EAAE,SAASA,EAAE,QAAQ,CAAC,CACpC,CAAC,CACF,EACA,SAAUA,EAAE,SAASA,EAAE,WAAWC,CAAQ,CAAC,EAC3C,WAAYD,EAAE,SAASA,EAAE,OAAO,CAAC,EACjC,WAAYA,EAAE,SAASA,EAAE,OAAO,CAAC,EACjC,QAASA,EAAE,SACVA,EAAE,OAAO,CACR,YAAaA,EAAE,SAASA,EAAE,OAAO,EAAG,OAAO,EAC3C,YAAaA,EAAE,SAASA,EAAE,MAAMA,EAAE,OAAO,CAAC,EAAG,CAAC,GAAG,CAAC,EAClD,SAAUA,EAAE,SAASA,EAAE,OAAO,EAAG,SAAS,CAC3C,CAAC,EACD,CAAC,CACF,EACA,SAAUA,EAAE,SACXA,EAAE,OAAO,CACR,IAAKA,EAAE,SAASA,EAAE,QAAQ,EAAG,EAAI,EACjC,UAAWA,EAAE,SACZA,EAAE,OAAO,CACR,QAASA,EAAE,SAASA,EAAE,QAAQ,EAAG,EAAK,EACtC,WAAYA,EAAE,SAASA,EAAE,OAAO,EAAG,KAAU,GAAI,EACjD,MAAOA,EAAE,SAASA,EAAE,OAAO,EAAG,GAAI,CACnC,CAAC,EACD,CAAC,CACF,EACA,SAAUA,EAAE,SACXA,EAAE,OAAO,CACR,QAASA,EAAE,SAASA,EAAE,QAAQ,EAAG,EAAK,EACtC,WAAYA,EAAE,SAASA,EAAE,OAAO,EAAG,IAAU,GAAI,EACjD,WAAYA,EAAE,SAASA,EAAE,OAAO,EAAG,GAAI,EACvC,UAAWA,EAAE,SAASA,EAAE,OAAO,EAAG,GAAG,CACtC,CAAC,EACD,CAAC,CACF,CACD,CAAC,EACD,CAAC,CACF,EACA,mBAAoBA,EAAE,SAASA,EAAE,MAAMA,EAAE,WAAWE,CAA+B,CAAC,EAAG,CAAC,CAAC,CAC1F,CAAC,EAEWG,EAAmB,IAC/BL,EAAE,aAAcM,GAAWA,EAAE,KAAM,CAClC,QAASN,EAAE,MACVI,EAAe,EACfJ,EAAE,OAAO,CACR,KAAMA,EAAE,GAAG,SAAkB,CAC9B,CAAC,CACF,EACA,QAASA,EAAE,MACVI,EAAe,EACfJ,EAAE,OAAO,CACR,KAAMA,EAAE,GAAG,SAAkB,CAC9B,CAAC,CACF,CACD,CAAC","names":["v","EventBus","BaseRequestAuthMethod","Methods","serverBasePipe","serverConfigPipe","d"]}
@@ -6,7 +6,7 @@ const serverBasePipe = () => v.object({
6
6
  port: v.number(),
7
7
  cors: v.optional(
8
8
  v.object({
9
- origin: v.optional(v.array(v.string())),
9
+ origin: v.optional(v.or([v.array(v.string()), v.is(true)])),
10
10
  methods: v.optional(v.array(v.in(Object.values(Methods)))),
11
11
  credentials: v.optional(v.boolean())
12
12
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/pipes.ts"],"sourcesContent":["import { type PipeOutput, v } from 'valleyed'\n\nimport { EventBus } from '../events'\nimport type { AuthUser } from '../types'\nimport { BaseRequestAuthMethod } from './requests-auth-methods'\nimport { Methods } from './types'\n\nconst serverBasePipe = () =>\n\tv.object({\n\t\tport: v.number(),\n\t\tcors: v.optional(\n\t\t\tv.object({\n\t\t\t\torigin: v.optional(v.array(v.string())),\n\t\t\t\tmethods: v.optional(v.array(v.in(Object.values(Methods)))),\n\t\t\t\tcredentials: v.optional(v.boolean()),\n\t\t\t}),\n\t\t),\n\t\teventBus: v.optional(v.instanceOf(EventBus)),\n\t\tpublicPath: v.optional(v.string()),\n\t\thealthPath: v.optional(v.string()),\n\t\topenapi: v.defaults(\n\t\t\tv.object({\n\t\t\t\tdocsVersion: v.defaults(v.string(), '1.0.0'),\n\t\t\t\tdocsBaseUrl: v.defaults(v.array(v.string()), ['/']),\n\t\t\t\tdocsPath: v.defaults(v.string(), '/__docs'),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\trequests: v.defaults(\n\t\t\tv.object({\n\t\t\t\tlog: v.defaults(v.boolean(), true),\n\t\t\t\trateLimit: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 60 * 60 * 1000),\n\t\t\t\t\t\tlimit: v.defaults(v.number(), 5000),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t\tslowdown: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 10 * 60 * 1000),\n\t\t\t\t\t\tdelayAfter: v.defaults(v.number(), 2000),\n\t\t\t\t\t\tdelayInMs: v.defaults(v.number(), 500),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\tsocketsAuthMethods: v.defaults(v.array(v.instanceOf(BaseRequestAuthMethod<AuthUser>)), []),\n\t})\n\nexport const serverConfigPipe = () =>\n\tv.discriminate((d: any) => d.type, {\n\t\tfastify: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('fastify' as const),\n\t\t\t}),\n\t\t),\n\t\texpress: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('express' as const),\n\t\t\t}),\n\t\t),\n\t})\n\nexport type ServerConfig = PipeOutput<ReturnType<typeof serverConfigPipe>>\n"],"mappings":"AAAA,SAA0B,SAAS;AAEnC,SAAS,gBAAgB;AAEzB,SAAS,6BAA6B;AACtC,SAAS,eAAe;AAExB,MAAM,iBAAiB,MACtB,EAAE,OAAO;AAAA,EACR,MAAM,EAAE,OAAO;AAAA,EACf,MAAM,EAAE;AAAA,IACP,EAAE,OAAO;AAAA,MACR,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAAA,MACtC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,OAAO,OAAO,CAAC,CAAC,CAAC;AAAA,MACzD,aAAa,EAAE,SAAS,EAAE,QAAQ,CAAC;AAAA,IACpC,CAAC;AAAA,EACF;AAAA,EACA,UAAU,EAAE,SAAS,EAAE,WAAW,QAAQ,CAAC;AAAA,EAC3C,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC;AAAA,EACjC,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC;AAAA,EACjC,SAAS,EAAE;AAAA,IACV,EAAE,OAAO;AAAA,MACR,aAAa,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO;AAAA,MAC3C,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;AAAA,MAClD,UAAU,EAAE,SAAS,EAAE,OAAO,GAAG,SAAS;AAAA,IAC3C,CAAC;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EACA,UAAU,EAAE;AAAA,IACX,EAAE,OAAO;AAAA,MACR,KAAK,EAAE,SAAS,EAAE,QAAQ,GAAG,IAAI;AAAA,MACjC,WAAW,EAAE;AAAA,QACZ,EAAE,OAAO;AAAA,UACR,SAAS,EAAE,SAAS,EAAE,QAAQ,GAAG,KAAK;AAAA,UACtC,YAAY,EAAE,SAAS,EAAE,OAAO,GAAG,KAAK,KAAK,GAAI;AAAA,UACjD,OAAO,EAAE,SAAS,EAAE,OAAO,GAAG,GAAI;AAAA,QACnC,CAAC;AAAA,QACD,CAAC;AAAA,MACF;AAAA,MACA,UAAU,EAAE;AAAA,QACX,EAAE,OAAO;AAAA,UACR,SAAS,EAAE,SAAS,EAAE,QAAQ,GAAG,KAAK;AAAA,UACtC,YAAY,EAAE,SAAS,EAAE,OAAO,GAAG,KAAK,KAAK,GAAI;AAAA,UACjD,YAAY,EAAE,SAAS,EAAE,OAAO,GAAG,GAAI;AAAA,UACvC,WAAW,EAAE,SAAS,EAAE,OAAO,GAAG,GAAG;AAAA,QACtC,CAAC;AAAA,QACD,CAAC;AAAA,MACF;AAAA,IACD,CAAC;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EACA,oBAAoB,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,qBAA+B,CAAC,GAAG,CAAC,CAAC;AAC1F,CAAC;AAEK,MAAM,mBAAmB,MAC/B,EAAE,aAAa,CAAC,MAAW,EAAE,MAAM;AAAA,EAClC,SAAS,EAAE;AAAA,IACV,eAAe;AAAA,IACf,EAAE,OAAO;AAAA,MACR,MAAM,EAAE,GAAG,SAAkB;AAAA,IAC9B,CAAC;AAAA,EACF;AAAA,EACA,SAAS,EAAE;AAAA,IACV,eAAe;AAAA,IACf,EAAE,OAAO;AAAA,MACR,MAAM,EAAE,GAAG,SAAkB;AAAA,IAC9B,CAAC;AAAA,EACF;AACD,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../src/server/pipes.ts"],"sourcesContent":["import { type PipeOutput, v } from 'valleyed'\n\nimport { EventBus } from '../events'\nimport type { AuthUser } from '../types'\nimport { BaseRequestAuthMethod } from './requests-auth-methods'\nimport { Methods } from './types'\n\nconst serverBasePipe = () =>\n\tv.object({\n\t\tport: v.number(),\n\t\tcors: v.optional(\n\t\t\tv.object({\n\t\t\t\torigin: v.optional(v.or([v.array(v.string()), v.is(true)])),\n\t\t\t\tmethods: v.optional(v.array(v.in(Object.values(Methods)))),\n\t\t\t\tcredentials: v.optional(v.boolean()),\n\t\t\t}),\n\t\t),\n\t\teventBus: v.optional(v.instanceOf(EventBus)),\n\t\tpublicPath: v.optional(v.string()),\n\t\thealthPath: v.optional(v.string()),\n\t\topenapi: v.defaults(\n\t\t\tv.object({\n\t\t\t\tdocsVersion: v.defaults(v.string(), '1.0.0'),\n\t\t\t\tdocsBaseUrl: v.defaults(v.array(v.string()), ['/']),\n\t\t\t\tdocsPath: v.defaults(v.string(), '/__docs'),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\trequests: v.defaults(\n\t\t\tv.object({\n\t\t\t\tlog: v.defaults(v.boolean(), true),\n\t\t\t\trateLimit: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 60 * 60 * 1000),\n\t\t\t\t\t\tlimit: v.defaults(v.number(), 5000),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t\tslowdown: v.defaults(\n\t\t\t\t\tv.object({\n\t\t\t\t\t\tenabled: v.defaults(v.boolean(), false),\n\t\t\t\t\t\tperiodInMs: v.defaults(v.number(), 10 * 60 * 1000),\n\t\t\t\t\t\tdelayAfter: v.defaults(v.number(), 2000),\n\t\t\t\t\t\tdelayInMs: v.defaults(v.number(), 500),\n\t\t\t\t\t}),\n\t\t\t\t\t{},\n\t\t\t\t),\n\t\t\t}),\n\t\t\t{},\n\t\t),\n\t\tsocketsAuthMethods: v.defaults(v.array(v.instanceOf(BaseRequestAuthMethod<AuthUser>)), []),\n\t})\n\nexport const serverConfigPipe = () =>\n\tv.discriminate((d: any) => d.type, {\n\t\tfastify: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('fastify' as const),\n\t\t\t}),\n\t\t),\n\t\texpress: v.merge(\n\t\t\tserverBasePipe(),\n\t\t\tv.object({\n\t\t\t\ttype: v.is('express' as const),\n\t\t\t}),\n\t\t),\n\t})\n\nexport type ServerConfig = PipeOutput<ReturnType<typeof serverConfigPipe>>\n"],"mappings":"AAAA,SAA0B,SAAS;AAEnC,SAAS,gBAAgB;AAEzB,SAAS,6BAA6B;AACtC,SAAS,eAAe;AAExB,MAAM,iBAAiB,MACtB,EAAE,OAAO;AAAA,EACR,MAAM,EAAE,OAAO;AAAA,EACf,MAAM,EAAE;AAAA,IACP,EAAE,OAAO;AAAA,MACR,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;AAAA,MAC1D,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,OAAO,OAAO,CAAC,CAAC,CAAC;AAAA,MACzD,aAAa,EAAE,SAAS,EAAE,QAAQ,CAAC;AAAA,IACpC,CAAC;AAAA,EACF;AAAA,EACA,UAAU,EAAE,SAAS,EAAE,WAAW,QAAQ,CAAC;AAAA,EAC3C,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC;AAAA,EACjC,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC;AAAA,EACjC,SAAS,EAAE;AAAA,IACV,EAAE,OAAO;AAAA,MACR,aAAa,EAAE,SAAS,EAAE,OAAO,GAAG,OAAO;AAAA,MAC3C,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;AAAA,MAClD,UAAU,EAAE,SAAS,EAAE,OAAO,GAAG,SAAS;AAAA,IAC3C,CAAC;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EACA,UAAU,EAAE;AAAA,IACX,EAAE,OAAO;AAAA,MACR,KAAK,EAAE,SAAS,EAAE,QAAQ,GAAG,IAAI;AAAA,MACjC,WAAW,EAAE;AAAA,QACZ,EAAE,OAAO;AAAA,UACR,SAAS,EAAE,SAAS,EAAE,QAAQ,GAAG,KAAK;AAAA,UACtC,YAAY,EAAE,SAAS,EAAE,OAAO,GAAG,KAAK,KAAK,GAAI;AAAA,UACjD,OAAO,EAAE,SAAS,EAAE,OAAO,GAAG,GAAI;AAAA,QACnC,CAAC;AAAA,QACD,CAAC;AAAA,MACF;AAAA,MACA,UAAU,EAAE;AAAA,QACX,EAAE,OAAO;AAAA,UACR,SAAS,EAAE,SAAS,EAAE,QAAQ,GAAG,KAAK;AAAA,UACtC,YAAY,EAAE,SAAS,EAAE,OAAO,GAAG,KAAK,KAAK,GAAI;AAAA,UACjD,YAAY,EAAE,SAAS,EAAE,OAAO,GAAG,GAAI;AAAA,UACvC,WAAW,EAAE,SAAS,EAAE,OAAO,GAAG,GAAG;AAAA,QACtC,CAAC;AAAA,QACD,CAAC;AAAA,MACF;AAAA,IACD,CAAC;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EACA,oBAAoB,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,qBAA+B,CAAC,GAAG,CAAC,CAAC;AAC1F,CAAC;AAEK,MAAM,mBAAmB,MAC/B,EAAE,aAAa,CAAC,MAAW,EAAE,MAAM;AAAA,EAClC,SAAS,EAAE;AAAA,IACV,eAAe;AAAA,IACf,EAAE,OAAO;AAAA,MACR,MAAM,EAAE,GAAG,SAAkB;AAAA,IAC9B,CAAC;AAAA,EACF;AAAA,EACA,SAAS,EAAE;AAAA,IACV,eAAe;AAAA,IACf,EAAE,OAAO;AAAA,MACR,MAAM,EAAE,GAAG,SAAkB;AAAA,IAC9B,CAAC;AAAA,EACF;AACD,CAAC;","names":[]}
@@ -1,2 +1,2 @@
1
- import c from"axios";import g from"jsonwebtoken";import m from"jwks-rsa";import{EquippedError as a}from "../errors/index.min.mjs";const f=async t=>{const i=`https://oauth2.googleapis.com/tokeninfo?id_token=${t}`,{data:e}=await c.get(i).catch(s=>{throw new a("Failed to sign in with google",{idToken:t},s)});return e.first_name=e.given_name,e.last_name=e.family_name,e},d=async t=>{try{const i="https://appleid.apple.com",e=g.decode(t,{complete:!0});if(!e?.header)throw new Error("");const{kid:s,alg:n}=e.header,o=await m({jwksUri:`${i}/auth/keys`,cache:!0}).getSigningKey(s).then(l=>l.getPublicKey()).catch(()=>null);if(!o)throw new a("no publicKey",{idToken:t,publicKey:o,json:e});const r=g.verify(t,o,{algorithms:[n]});if(!r)throw new a("no data",{idToken:t,data:r});if(r.iss!==i)throw new a("iss doesnt match",{idToken:t,data:r});if(r.exp*1e3<Date.now())throw new a("expired idToken",{idToken:t,data:r});return r}catch(i){throw new a("Failed to sign in with apple",{idToken:t},i)}},y=async(t,i=[])=>{i=[...new Set([...i,"name","picture","email"])];const{data:e}=await c.request({method:"get",url:"https://graph.facebook.com/v15.0/me",params:{fields:i.join(","),access_token:t}}).catch(n=>{throw new a("Failed to sign in with facebook",{accessToken:t,fields:i},n)});if(!i.every(n=>n in e))throw new Error("Incomplete scope for access token");return e.email_verified="true",e};export{d as signinWithApple,y as signinWithFacebook,f as signinWithGoogle};
1
+ import c from"axios";import g from"jsonwebtoken";import h from"jwks-rsa";import{EquippedError as a}from "../errors/index.min.mjs";const f=async t=>{const i=`https://oauth2.googleapis.com/tokeninfo?id_token=${t}`,{data:e}=await c.get(i).catch(s=>{throw new a("Failed to sign in with google",{idToken:t},s)});return e.first_name=e.given_name,e.last_name=e.family_name,e},d=async t=>{try{const i="https://appleid.apple.com",e=g.decode(t,{complete:!0});if(!e?.header)throw new a("Missing JWT header",{idToken:t,json:e});const{kid:s,alg:n}=e.header,o=await h({jwksUri:`${i}/auth/keys`,cache:!0}).getSigningKey(s).then(l=>l.getPublicKey()).catch(()=>null);if(!o)throw new a("no publicKey",{idToken:t,publicKey:o,json:e});const r=g.verify(t,o,{algorithms:[n]});if(!r)throw new a("no data",{idToken:t,data:r});if(r.iss!==i)throw new a("iss doesnt match",{idToken:t,data:r});if(r.exp*1e3<Date.now())throw new a("expired idToken",{idToken:t,data:r});return r}catch(i){throw new a("Failed to sign in with apple",{idToken:t},i)}},y=async(t,i=[])=>{i=[...new Set([...i,"name","picture","email"])];const{data:e}=await c.request({method:"get",url:"https://graph.facebook.com/v15.0/me",params:{fields:i.join(","),access_token:t}}).catch(n=>{throw new a("Failed to sign in with facebook",{accessToken:t,fields:i},n)});if(!i.every(n=>n in e))throw new a("Incomplete scope for access token",{accessToken:t,fields:i,data:e});return e.email_verified="true",e};export{d as signinWithApple,y as signinWithFacebook,f as signinWithGoogle};
2
2
  //# sourceMappingURL=authProviders.min.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utilities/authProviders.ts"],"sourcesContent":["import axios from 'axios'\nimport jwt from 'jsonwebtoken'\nimport jwksClient from 'jwks-rsa'\n\nimport { EquippedError } from '../errors'\n\nexport const signinWithGoogle = async (idToken: string) => {\n\tconst authUrl = `https://oauth2.googleapis.com/tokeninfo?id_token=${idToken}`\n\tconst { data } = await axios.get(authUrl).catch((err) => {\n\t\tthrow new EquippedError('Failed to sign in with google', { idToken }, err)\n\t})\n\tdata.first_name = data.given_name\n\tdata.last_name = data.family_name\n\treturn data as {\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tfirst_name: string\n\t\tlast_name: string\n\t\tpicture: string\n\t\tsub: string\n\t} & Record<string, any>\n}\n\nexport const signinWithApple = async (idToken: string) => {\n\ttry {\n\t\tconst APPLE_BASE = 'https://appleid.apple.com'\n\t\tconst json = jwt.decode(idToken, { complete: true })\n\t\tif (!json?.header) throw new Error('')\n\t\tconst { kid, alg } = json.header\n\t\tconst publicKey = await jwksClient({ jwksUri: `${APPLE_BASE}/auth/keys`, cache: true })\n\t\t\t.getSigningKey(kid)\n\t\t\t.then((key) => key.getPublicKey())\n\t\t\t.catch(() => null)\n\t\tif (!publicKey) throw new EquippedError('no publicKey', { idToken, publicKey, json })\n\t\tconst data = jwt.verify(idToken, publicKey, { algorithms: [alg as any] }) as Record<string, any>\n\t\tif (!data) throw new EquippedError('no data', { idToken, data })\n\t\tif (data.iss !== APPLE_BASE) throw new EquippedError('iss doesnt match', { idToken, data })\n\t\tif (data.exp * 1000 < Date.now()) throw new EquippedError('expired idToken', { idToken, data })\n\t\t// TODO: Find out how to get profile data from api\n\t\treturn data as {\n\t\t\temail?: string\n\t\t\tsub: string\n\t\t\temail_verified?: 'true' | 'false'\n\t\t\tis_private_email?: 'true' | 'false'\n\t\t} & Record<string, any>\n\t} catch (err) {\n\t\tthrow new EquippedError('Failed to sign in with apple', { idToken }, err)\n\t}\n}\n\nexport const signinWithFacebook = async (accessToken: string, fields = [] as string[]) => {\n\tfields = [...new Set([...fields, 'name', 'picture', 'email'])]\n\tconst { data } = await axios\n\t\t.request({\n\t\t\tmethod: 'get',\n\t\t\turl: 'https://graph.facebook.com/v15.0/me',\n\t\t\tparams: {\n\t\t\t\tfields: fields.join(','),\n\t\t\t\taccess_token: accessToken,\n\t\t\t},\n\t\t})\n\t\t.catch((err) => {\n\t\t\tthrow new EquippedError('Failed to sign in with facebook', { accessToken, fields }, err)\n\t\t})\n\tconst isValidData = fields.every((key) => key in data)\n\tif (!isValidData) throw new Error('Incomplete scope for access token')\n\tdata.email_verified = 'true'\n\treturn data as {\n\t\tid: string\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tname: string\n\t\tpicture: {\n\t\t\tdata: { height: number; is_silhouette: boolean; url: string; width: number }\n\t\t}\n\t} & Record<string, any>\n}\n"],"mappings":"AAAA,OAAOA,MAAW,QAClB,OAAOC,MAAS,eAChB,OAAOC,MAAgB,WAEvB,OAAS,iBAAAC,MAAqB,YAEvB,MAAMC,EAAmB,MAAOC,GAAoB,CAC1D,MAAMC,EAAU,oDAAoDD,CAAO,GACrE,CAAE,KAAAE,CAAK,EAAI,MAAMP,EAAM,IAAIM,CAAO,EAAE,MAAOE,GAAQ,CACxD,MAAM,IAAIL,EAAc,gCAAiC,CAAE,QAAAE,CAAQ,EAAGG,CAAG,CAC1E,CAAC,EACD,OAAAD,EAAK,WAAaA,EAAK,WACvBA,EAAK,UAAYA,EAAK,YACfA,CAQR,EAEaE,EAAkB,MAAOJ,GAAoB,CACzD,GAAI,CACH,MAAMK,EAAa,4BACbC,EAAOV,EAAI,OAAOI,EAAS,CAAE,SAAU,EAAK,CAAC,EACnD,GAAI,CAACM,GAAM,OAAQ,MAAM,IAAI,MAAM,EAAE,EACrC,KAAM,CAAE,IAAAC,EAAK,IAAAC,CAAI,EAAIF,EAAK,OACpBG,EAAY,MAAMZ,EAAW,CAAE,QAAS,GAAGQ,CAAU,aAAc,MAAO,EAAK,CAAC,EACpF,cAAcE,CAAG,EACjB,KAAMG,GAAQA,EAAI,aAAa,CAAC,EAChC,MAAM,IAAM,IAAI,EAClB,GAAI,CAACD,EAAW,MAAM,IAAIX,EAAc,eAAgB,CAAE,QAAAE,EAAS,UAAAS,EAAW,KAAAH,CAAK,CAAC,EACpF,MAAMJ,EAAON,EAAI,OAAOI,EAASS,EAAW,CAAE,WAAY,CAACD,CAAU,CAAE,CAAC,EACxE,GAAI,CAACN,EAAM,MAAM,IAAIJ,EAAc,UAAW,CAAE,QAAAE,EAAS,KAAAE,CAAK,CAAC,EAC/D,GAAIA,EAAK,MAAQG,EAAY,MAAM,IAAIP,EAAc,mBAAoB,CAAE,QAAAE,EAAS,KAAAE,CAAK,CAAC,EAC1F,GAAIA,EAAK,IAAM,IAAO,KAAK,IAAI,EAAG,MAAM,IAAIJ,EAAc,kBAAmB,CAAE,QAAAE,EAAS,KAAAE,CAAK,CAAC,EAE9F,OAAOA,CAMR,OAASC,EAAK,CACb,MAAM,IAAIL,EAAc,+BAAgC,CAAE,QAAAE,CAAQ,EAAGG,CAAG,CACzE,CACD,EAEaQ,EAAqB,MAAOC,EAAqBC,EAAS,CAAC,IAAkB,CACzFA,EAAS,CAAC,GAAG,IAAI,IAAI,CAAC,GAAGA,EAAQ,OAAQ,UAAW,OAAO,CAAC,CAAC,EAC7D,KAAM,CAAE,KAAAX,CAAK,EAAI,MAAMP,EACrB,QAAQ,CACR,OAAQ,MACR,IAAK,sCACL,OAAQ,CACP,OAAQkB,EAAO,KAAK,GAAG,EACvB,aAAcD,CACf,CACD,CAAC,EACA,MAAOT,GAAQ,CACf,MAAM,IAAIL,EAAc,kCAAmC,CAAE,YAAAc,EAAa,OAAAC,CAAO,EAAGV,CAAG,CACxF,CAAC,EAEF,GAAI,CADgBU,EAAO,MAAOH,GAAQA,KAAOR,CAAI,EACnC,MAAM,IAAI,MAAM,mCAAmC,EACrE,OAAAA,EAAK,eAAiB,OACfA,CASR","names":["axios","jwt","jwksClient","EquippedError","signinWithGoogle","idToken","authUrl","data","err","signinWithApple","APPLE_BASE","json","kid","alg","publicKey","key","signinWithFacebook","accessToken","fields"]}
1
+ {"version":3,"sources":["../../../src/utilities/authProviders.ts"],"sourcesContent":["import axios from 'axios'\nimport jwt from 'jsonwebtoken'\nimport jwksClient from 'jwks-rsa'\n\nimport { EquippedError } from '../errors'\n\nexport const signinWithGoogle = async (idToken: string) => {\n\tconst authUrl = `https://oauth2.googleapis.com/tokeninfo?id_token=${idToken}`\n\tconst { data } = await axios.get(authUrl).catch((err) => {\n\t\tthrow new EquippedError('Failed to sign in with google', { idToken }, err)\n\t})\n\tdata.first_name = data.given_name\n\tdata.last_name = data.family_name\n\treturn data as {\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tfirst_name: string\n\t\tlast_name: string\n\t\tpicture: string\n\t\tsub: string\n\t} & Record<string, any>\n}\n\nexport const signinWithApple = async (idToken: string) => {\n\ttry {\n\t\tconst APPLE_BASE = 'https://appleid.apple.com'\n\t\tconst json = jwt.decode(idToken, { complete: true })\n\t\tif (!json?.header) throw new EquippedError('Missing JWT header', { idToken, json })\n\t\tconst { kid, alg } = json.header\n\t\tconst publicKey = await jwksClient({ jwksUri: `${APPLE_BASE}/auth/keys`, cache: true })\n\t\t\t.getSigningKey(kid)\n\t\t\t.then((key) => key.getPublicKey())\n\t\t\t.catch(() => null)\n\t\tif (!publicKey) throw new EquippedError('no publicKey', { idToken, publicKey, json })\n\t\tconst data = jwt.verify(idToken, publicKey, { algorithms: [alg as any] }) as Record<string, any>\n\t\tif (!data) throw new EquippedError('no data', { idToken, data })\n\t\tif (data.iss !== APPLE_BASE) throw new EquippedError('iss doesnt match', { idToken, data })\n\t\tif (data.exp * 1000 < Date.now()) throw new EquippedError('expired idToken', { idToken, data })\n\t\t// TODO: Find out how to get profile data from api\n\t\treturn data as {\n\t\t\temail?: string\n\t\t\tsub: string\n\t\t\temail_verified?: 'true' | 'false'\n\t\t\tis_private_email?: 'true' | 'false'\n\t\t} & Record<string, any>\n\t} catch (err) {\n\t\tthrow new EquippedError('Failed to sign in with apple', { idToken }, err)\n\t}\n}\n\nexport const signinWithFacebook = async (accessToken: string, fields = [] as string[]) => {\n\tfields = [...new Set([...fields, 'name', 'picture', 'email'])]\n\tconst { data } = await axios\n\t\t.request({\n\t\t\tmethod: 'get',\n\t\t\turl: 'https://graph.facebook.com/v15.0/me',\n\t\t\tparams: {\n\t\t\t\tfields: fields.join(','),\n\t\t\t\taccess_token: accessToken,\n\t\t\t},\n\t\t})\n\t\t.catch((err) => {\n\t\t\tthrow new EquippedError('Failed to sign in with facebook', { accessToken, fields }, err)\n\t\t})\n\tconst isValidData = fields.every((key) => key in data)\n\tif (!isValidData) throw new EquippedError('Incomplete scope for access token', { accessToken, fields, data })\n\tdata.email_verified = 'true'\n\treturn data as {\n\t\tid: string\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tname: string\n\t\tpicture: {\n\t\t\tdata: { height: number; is_silhouette: boolean; url: string; width: number }\n\t\t}\n\t} & Record<string, any>\n}\n"],"mappings":"AAAA,OAAOA,MAAW,QAClB,OAAOC,MAAS,eAChB,OAAOC,MAAgB,WAEvB,OAAS,iBAAAC,MAAqB,YAEvB,MAAMC,EAAmB,MAAOC,GAAoB,CAC1D,MAAMC,EAAU,oDAAoDD,CAAO,GACrE,CAAE,KAAAE,CAAK,EAAI,MAAMP,EAAM,IAAIM,CAAO,EAAE,MAAOE,GAAQ,CACxD,MAAM,IAAIL,EAAc,gCAAiC,CAAE,QAAAE,CAAQ,EAAGG,CAAG,CAC1E,CAAC,EACD,OAAAD,EAAK,WAAaA,EAAK,WACvBA,EAAK,UAAYA,EAAK,YACfA,CAQR,EAEaE,EAAkB,MAAOJ,GAAoB,CACzD,GAAI,CACH,MAAMK,EAAa,4BACbC,EAAOV,EAAI,OAAOI,EAAS,CAAE,SAAU,EAAK,CAAC,EACnD,GAAI,CAACM,GAAM,OAAQ,MAAM,IAAIR,EAAc,qBAAsB,CAAE,QAAAE,EAAS,KAAAM,CAAK,CAAC,EAClF,KAAM,CAAE,IAAAC,EAAK,IAAAC,CAAI,EAAIF,EAAK,OACpBG,EAAY,MAAMZ,EAAW,CAAE,QAAS,GAAGQ,CAAU,aAAc,MAAO,EAAK,CAAC,EACpF,cAAcE,CAAG,EACjB,KAAMG,GAAQA,EAAI,aAAa,CAAC,EAChC,MAAM,IAAM,IAAI,EAClB,GAAI,CAACD,EAAW,MAAM,IAAIX,EAAc,eAAgB,CAAE,QAAAE,EAAS,UAAAS,EAAW,KAAAH,CAAK,CAAC,EACpF,MAAMJ,EAAON,EAAI,OAAOI,EAASS,EAAW,CAAE,WAAY,CAACD,CAAU,CAAE,CAAC,EACxE,GAAI,CAACN,EAAM,MAAM,IAAIJ,EAAc,UAAW,CAAE,QAAAE,EAAS,KAAAE,CAAK,CAAC,EAC/D,GAAIA,EAAK,MAAQG,EAAY,MAAM,IAAIP,EAAc,mBAAoB,CAAE,QAAAE,EAAS,KAAAE,CAAK,CAAC,EAC1F,GAAIA,EAAK,IAAM,IAAO,KAAK,IAAI,EAAG,MAAM,IAAIJ,EAAc,kBAAmB,CAAE,QAAAE,EAAS,KAAAE,CAAK,CAAC,EAE9F,OAAOA,CAMR,OAASC,EAAK,CACb,MAAM,IAAIL,EAAc,+BAAgC,CAAE,QAAAE,CAAQ,EAAGG,CAAG,CACzE,CACD,EAEaQ,EAAqB,MAAOC,EAAqBC,EAAS,CAAC,IAAkB,CACzFA,EAAS,CAAC,GAAG,IAAI,IAAI,CAAC,GAAGA,EAAQ,OAAQ,UAAW,OAAO,CAAC,CAAC,EAC7D,KAAM,CAAE,KAAAX,CAAK,EAAI,MAAMP,EACrB,QAAQ,CACR,OAAQ,MACR,IAAK,sCACL,OAAQ,CACP,OAAQkB,EAAO,KAAK,GAAG,EACvB,aAAcD,CACf,CACD,CAAC,EACA,MAAOT,GAAQ,CACf,MAAM,IAAIL,EAAc,kCAAmC,CAAE,YAAAc,EAAa,OAAAC,CAAO,EAAGV,CAAG,CACxF,CAAC,EAEF,GAAI,CADgBU,EAAO,MAAOH,GAAQA,KAAOR,CAAI,EACnC,MAAM,IAAIJ,EAAc,oCAAqC,CAAE,YAAAc,EAAa,OAAAC,EAAQ,KAAAX,CAAK,CAAC,EAC5G,OAAAA,EAAK,eAAiB,OACfA,CASR","names":["axios","jwt","jwksClient","EquippedError","signinWithGoogle","idToken","authUrl","data","err","signinWithApple","APPLE_BASE","json","kid","alg","publicKey","key","signinWithFacebook","accessToken","fields"]}
@@ -15,7 +15,7 @@ const signinWithApple = async (idToken) => {
15
15
  try {
16
16
  const APPLE_BASE = "https://appleid.apple.com";
17
17
  const json = jwt.decode(idToken, { complete: true });
18
- if (!json?.header) throw new Error("");
18
+ if (!json?.header) throw new EquippedError("Missing JWT header", { idToken, json });
19
19
  const { kid, alg } = json.header;
20
20
  const publicKey = await jwksClient({ jwksUri: `${APPLE_BASE}/auth/keys`, cache: true }).getSigningKey(kid).then((key) => key.getPublicKey()).catch(() => null);
21
21
  if (!publicKey) throw new EquippedError("no publicKey", { idToken, publicKey, json });
@@ -41,7 +41,7 @@ const signinWithFacebook = async (accessToken, fields = []) => {
41
41
  throw new EquippedError("Failed to sign in with facebook", { accessToken, fields }, err);
42
42
  });
43
43
  const isValidData = fields.every((key) => key in data);
44
- if (!isValidData) throw new Error("Incomplete scope for access token");
44
+ if (!isValidData) throw new EquippedError("Incomplete scope for access token", { accessToken, fields, data });
45
45
  data.email_verified = "true";
46
46
  return data;
47
47
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utilities/authProviders.ts"],"sourcesContent":["import axios from 'axios'\nimport jwt from 'jsonwebtoken'\nimport jwksClient from 'jwks-rsa'\n\nimport { EquippedError } from '../errors'\n\nexport const signinWithGoogle = async (idToken: string) => {\n\tconst authUrl = `https://oauth2.googleapis.com/tokeninfo?id_token=${idToken}`\n\tconst { data } = await axios.get(authUrl).catch((err) => {\n\t\tthrow new EquippedError('Failed to sign in with google', { idToken }, err)\n\t})\n\tdata.first_name = data.given_name\n\tdata.last_name = data.family_name\n\treturn data as {\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tfirst_name: string\n\t\tlast_name: string\n\t\tpicture: string\n\t\tsub: string\n\t} & Record<string, any>\n}\n\nexport const signinWithApple = async (idToken: string) => {\n\ttry {\n\t\tconst APPLE_BASE = 'https://appleid.apple.com'\n\t\tconst json = jwt.decode(idToken, { complete: true })\n\t\tif (!json?.header) throw new Error('')\n\t\tconst { kid, alg } = json.header\n\t\tconst publicKey = await jwksClient({ jwksUri: `${APPLE_BASE}/auth/keys`, cache: true })\n\t\t\t.getSigningKey(kid)\n\t\t\t.then((key) => key.getPublicKey())\n\t\t\t.catch(() => null)\n\t\tif (!publicKey) throw new EquippedError('no publicKey', { idToken, publicKey, json })\n\t\tconst data = jwt.verify(idToken, publicKey, { algorithms: [alg as any] }) as Record<string, any>\n\t\tif (!data) throw new EquippedError('no data', { idToken, data })\n\t\tif (data.iss !== APPLE_BASE) throw new EquippedError('iss doesnt match', { idToken, data })\n\t\tif (data.exp * 1000 < Date.now()) throw new EquippedError('expired idToken', { idToken, data })\n\t\t// TODO: Find out how to get profile data from api\n\t\treturn data as {\n\t\t\temail?: string\n\t\t\tsub: string\n\t\t\temail_verified?: 'true' | 'false'\n\t\t\tis_private_email?: 'true' | 'false'\n\t\t} & Record<string, any>\n\t} catch (err) {\n\t\tthrow new EquippedError('Failed to sign in with apple', { idToken }, err)\n\t}\n}\n\nexport const signinWithFacebook = async (accessToken: string, fields = [] as string[]) => {\n\tfields = [...new Set([...fields, 'name', 'picture', 'email'])]\n\tconst { data } = await axios\n\t\t.request({\n\t\t\tmethod: 'get',\n\t\t\turl: 'https://graph.facebook.com/v15.0/me',\n\t\t\tparams: {\n\t\t\t\tfields: fields.join(','),\n\t\t\t\taccess_token: accessToken,\n\t\t\t},\n\t\t})\n\t\t.catch((err) => {\n\t\t\tthrow new EquippedError('Failed to sign in with facebook', { accessToken, fields }, err)\n\t\t})\n\tconst isValidData = fields.every((key) => key in data)\n\tif (!isValidData) throw new Error('Incomplete scope for access token')\n\tdata.email_verified = 'true'\n\treturn data as {\n\t\tid: string\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tname: string\n\t\tpicture: {\n\t\t\tdata: { height: number; is_silhouette: boolean; url: string; width: number }\n\t\t}\n\t} & Record<string, any>\n}\n"],"mappings":"AAAA,OAAO,WAAW;AAClB,OAAO,SAAS;AAChB,OAAO,gBAAgB;AAEvB,SAAS,qBAAqB;AAEvB,MAAM,mBAAmB,OAAO,YAAoB;AAC1D,QAAM,UAAU,oDAAoD,OAAO;AAC3E,QAAM,EAAE,KAAK,IAAI,MAAM,MAAM,IAAI,OAAO,EAAE,MAAM,CAAC,QAAQ;AACxD,UAAM,IAAI,cAAc,iCAAiC,EAAE,QAAQ,GAAG,GAAG;AAAA,EAC1E,CAAC;AACD,OAAK,aAAa,KAAK;AACvB,OAAK,YAAY,KAAK;AACtB,SAAO;AAQR;AAEO,MAAM,kBAAkB,OAAO,YAAoB;AACzD,MAAI;AACH,UAAM,aAAa;AACnB,UAAM,OAAO,IAAI,OAAO,SAAS,EAAE,UAAU,KAAK,CAAC;AACnD,QAAI,CAAC,MAAM,OAAQ,OAAM,IAAI,MAAM,EAAE;AACrC,UAAM,EAAE,KAAK,IAAI,IAAI,KAAK;AAC1B,UAAM,YAAY,MAAM,WAAW,EAAE,SAAS,GAAG,UAAU,cAAc,OAAO,KAAK,CAAC,EACpF,cAAc,GAAG,EACjB,KAAK,CAAC,QAAQ,IAAI,aAAa,CAAC,EAChC,MAAM,MAAM,IAAI;AAClB,QAAI,CAAC,UAAW,OAAM,IAAI,cAAc,gBAAgB,EAAE,SAAS,WAAW,KAAK,CAAC;AACpF,UAAM,OAAO,IAAI,OAAO,SAAS,WAAW,EAAE,YAAY,CAAC,GAAU,EAAE,CAAC;AACxE,QAAI,CAAC,KAAM,OAAM,IAAI,cAAc,WAAW,EAAE,SAAS,KAAK,CAAC;AAC/D,QAAI,KAAK,QAAQ,WAAY,OAAM,IAAI,cAAc,oBAAoB,EAAE,SAAS,KAAK,CAAC;AAC1F,QAAI,KAAK,MAAM,MAAO,KAAK,IAAI,EAAG,OAAM,IAAI,cAAc,mBAAmB,EAAE,SAAS,KAAK,CAAC;AAE9F,WAAO;AAAA,EAMR,SAAS,KAAK;AACb,UAAM,IAAI,cAAc,gCAAgC,EAAE,QAAQ,GAAG,GAAG;AAAA,EACzE;AACD;AAEO,MAAM,qBAAqB,OAAO,aAAqB,SAAS,CAAC,MAAkB;AACzF,WAAS,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,QAAQ,QAAQ,WAAW,OAAO,CAAC,CAAC;AAC7D,QAAM,EAAE,KAAK,IAAI,MAAM,MACrB,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,QAAQ;AAAA,MACP,QAAQ,OAAO,KAAK,GAAG;AAAA,MACvB,cAAc;AAAA,IACf;AAAA,EACD,CAAC,EACA,MAAM,CAAC,QAAQ;AACf,UAAM,IAAI,cAAc,mCAAmC,EAAE,aAAa,OAAO,GAAG,GAAG;AAAA,EACxF,CAAC;AACF,QAAM,cAAc,OAAO,MAAM,CAAC,QAAQ,OAAO,IAAI;AACrD,MAAI,CAAC,YAAa,OAAM,IAAI,MAAM,mCAAmC;AACrE,OAAK,iBAAiB;AACtB,SAAO;AASR;","names":[]}
1
+ {"version":3,"sources":["../../../src/utilities/authProviders.ts"],"sourcesContent":["import axios from 'axios'\nimport jwt from 'jsonwebtoken'\nimport jwksClient from 'jwks-rsa'\n\nimport { EquippedError } from '../errors'\n\nexport const signinWithGoogle = async (idToken: string) => {\n\tconst authUrl = `https://oauth2.googleapis.com/tokeninfo?id_token=${idToken}`\n\tconst { data } = await axios.get(authUrl).catch((err) => {\n\t\tthrow new EquippedError('Failed to sign in with google', { idToken }, err)\n\t})\n\tdata.first_name = data.given_name\n\tdata.last_name = data.family_name\n\treturn data as {\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tfirst_name: string\n\t\tlast_name: string\n\t\tpicture: string\n\t\tsub: string\n\t} & Record<string, any>\n}\n\nexport const signinWithApple = async (idToken: string) => {\n\ttry {\n\t\tconst APPLE_BASE = 'https://appleid.apple.com'\n\t\tconst json = jwt.decode(idToken, { complete: true })\n\t\tif (!json?.header) throw new EquippedError('Missing JWT header', { idToken, json })\n\t\tconst { kid, alg } = json.header\n\t\tconst publicKey = await jwksClient({ jwksUri: `${APPLE_BASE}/auth/keys`, cache: true })\n\t\t\t.getSigningKey(kid)\n\t\t\t.then((key) => key.getPublicKey())\n\t\t\t.catch(() => null)\n\t\tif (!publicKey) throw new EquippedError('no publicKey', { idToken, publicKey, json })\n\t\tconst data = jwt.verify(idToken, publicKey, { algorithms: [alg as any] }) as Record<string, any>\n\t\tif (!data) throw new EquippedError('no data', { idToken, data })\n\t\tif (data.iss !== APPLE_BASE) throw new EquippedError('iss doesnt match', { idToken, data })\n\t\tif (data.exp * 1000 < Date.now()) throw new EquippedError('expired idToken', { idToken, data })\n\t\t// TODO: Find out how to get profile data from api\n\t\treturn data as {\n\t\t\temail?: string\n\t\t\tsub: string\n\t\t\temail_verified?: 'true' | 'false'\n\t\t\tis_private_email?: 'true' | 'false'\n\t\t} & Record<string, any>\n\t} catch (err) {\n\t\tthrow new EquippedError('Failed to sign in with apple', { idToken }, err)\n\t}\n}\n\nexport const signinWithFacebook = async (accessToken: string, fields = [] as string[]) => {\n\tfields = [...new Set([...fields, 'name', 'picture', 'email'])]\n\tconst { data } = await axios\n\t\t.request({\n\t\t\tmethod: 'get',\n\t\t\turl: 'https://graph.facebook.com/v15.0/me',\n\t\t\tparams: {\n\t\t\t\tfields: fields.join(','),\n\t\t\t\taccess_token: accessToken,\n\t\t\t},\n\t\t})\n\t\t.catch((err) => {\n\t\t\tthrow new EquippedError('Failed to sign in with facebook', { accessToken, fields }, err)\n\t\t})\n\tconst isValidData = fields.every((key) => key in data)\n\tif (!isValidData) throw new EquippedError('Incomplete scope for access token', { accessToken, fields, data })\n\tdata.email_verified = 'true'\n\treturn data as {\n\t\tid: string\n\t\temail: string\n\t\temail_verified: 'true' | 'false'\n\t\tname: string\n\t\tpicture: {\n\t\t\tdata: { height: number; is_silhouette: boolean; url: string; width: number }\n\t\t}\n\t} & Record<string, any>\n}\n"],"mappings":"AAAA,OAAO,WAAW;AAClB,OAAO,SAAS;AAChB,OAAO,gBAAgB;AAEvB,SAAS,qBAAqB;AAEvB,MAAM,mBAAmB,OAAO,YAAoB;AAC1D,QAAM,UAAU,oDAAoD,OAAO;AAC3E,QAAM,EAAE,KAAK,IAAI,MAAM,MAAM,IAAI,OAAO,EAAE,MAAM,CAAC,QAAQ;AACxD,UAAM,IAAI,cAAc,iCAAiC,EAAE,QAAQ,GAAG,GAAG;AAAA,EAC1E,CAAC;AACD,OAAK,aAAa,KAAK;AACvB,OAAK,YAAY,KAAK;AACtB,SAAO;AAQR;AAEO,MAAM,kBAAkB,OAAO,YAAoB;AACzD,MAAI;AACH,UAAM,aAAa;AACnB,UAAM,OAAO,IAAI,OAAO,SAAS,EAAE,UAAU,KAAK,CAAC;AACnD,QAAI,CAAC,MAAM,OAAQ,OAAM,IAAI,cAAc,sBAAsB,EAAE,SAAS,KAAK,CAAC;AAClF,UAAM,EAAE,KAAK,IAAI,IAAI,KAAK;AAC1B,UAAM,YAAY,MAAM,WAAW,EAAE,SAAS,GAAG,UAAU,cAAc,OAAO,KAAK,CAAC,EACpF,cAAc,GAAG,EACjB,KAAK,CAAC,QAAQ,IAAI,aAAa,CAAC,EAChC,MAAM,MAAM,IAAI;AAClB,QAAI,CAAC,UAAW,OAAM,IAAI,cAAc,gBAAgB,EAAE,SAAS,WAAW,KAAK,CAAC;AACpF,UAAM,OAAO,IAAI,OAAO,SAAS,WAAW,EAAE,YAAY,CAAC,GAAU,EAAE,CAAC;AACxE,QAAI,CAAC,KAAM,OAAM,IAAI,cAAc,WAAW,EAAE,SAAS,KAAK,CAAC;AAC/D,QAAI,KAAK,QAAQ,WAAY,OAAM,IAAI,cAAc,oBAAoB,EAAE,SAAS,KAAK,CAAC;AAC1F,QAAI,KAAK,MAAM,MAAO,KAAK,IAAI,EAAG,OAAM,IAAI,cAAc,mBAAmB,EAAE,SAAS,KAAK,CAAC;AAE9F,WAAO;AAAA,EAMR,SAAS,KAAK;AACb,UAAM,IAAI,cAAc,gCAAgC,EAAE,QAAQ,GAAG,GAAG;AAAA,EACzE;AACD;AAEO,MAAM,qBAAqB,OAAO,aAAqB,SAAS,CAAC,MAAkB;AACzF,WAAS,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,QAAQ,QAAQ,WAAW,OAAO,CAAC,CAAC;AAC7D,QAAM,EAAE,KAAK,IAAI,MAAM,MACrB,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,QAAQ;AAAA,MACP,QAAQ,OAAO,KAAK,GAAG;AAAA,MACvB,cAAc;AAAA,IACf;AAAA,EACD,CAAC,EACA,MAAM,CAAC,QAAQ;AACf,UAAM,IAAI,cAAc,mCAAmC,EAAE,aAAa,OAAO,GAAG,GAAG;AAAA,EACxF,CAAC;AACF,QAAM,cAAc,OAAO,MAAM,CAAC,QAAQ,OAAO,IAAI;AACrD,MAAI,CAAC,YAAa,OAAM,IAAI,cAAc,qCAAqC,EAAE,aAAa,QAAQ,KAAK,CAAC;AAC5G,OAAK,iBAAiB;AACtB,SAAO;AASR;","names":[]}
@@ -1,6 +1,6 @@
1
- import { R as RequestError } from '../requestError-7N-ngghg.js';
2
- export { E as EquippedError } from '../requestError-7N-ngghg.js';
3
- export { V as ValidationError } from '../validationError-BB4cfdZa.js';
1
+ import { R as RequestError } from '../requestError-JVHgFJzE.js';
2
+ export { E as EquippedError } from '../requestError-JVHgFJzE.js';
3
+ export { V as ValidationError } from '../validationError-CPQdQ7rX.js';
4
4
  import 'valleyed';
5
5
  import '../types/index.js';
6
6
  import '../overrides-6Hxg764S.js';
@@ -1,8 +1,10 @@
1
1
  import express from 'express';
2
- import { d as RouteDef, k as RouterConfig, j as RouteConfig, m as RouteDefHandler, l as MergeRouteDefs, e as Route, S as ServerConfig, a as Request, b as Response, g as MethodsEnum } from './requestError-7N-ngghg.js';
2
+ import { d as RouteDef, k as RouterConfig, j as RouteConfig, m as RouteDefHandler, l as MergeRouteDefs, e as Route, S as ServerConfig, a as Request, b as Response, g as MethodsEnum } from './requestError-JVHgFJzE.js';
3
3
  import { FastifyRequest, FastifyReply } from 'fastify';
4
4
  import * as supertest_lib_agent from 'supertest/lib/agent';
5
5
  import http from 'node:http';
6
+ import { FastifyCorsOptions } from '@fastify/cors';
7
+ import { CorsOptions } from 'cors';
6
8
  import supertest from 'supertest';
7
9
  import { Server as Server$1 } from 'socket.io';
8
10
  import { E as Entity } from './core-BWUHISEy.js';
@@ -51,11 +53,7 @@ declare abstract class Server<Req = any, Res = any> {
51
53
  private implementations;
52
54
  socket: SocketEmitter;
53
55
  protected server: http.Server;
54
- protected get cors(): {
55
- origin: string[] | undefined;
56
- methods: string[];
57
- credentials: boolean | undefined;
58
- };
56
+ protected get cors(): CorsOptions & FastifyCorsOptions;
59
57
  constructor(server: http.Server, config: ServerConfig, implementations: {
60
58
  parseRequest: (req: Req) => Promise<Request<any>>;
61
59
  handleResponse: (res: Res, response: Response<any>) => Promise<void>;
@@ -1,7 +1,7 @@
1
1
  export { Instance } from './instance/index.js';
2
2
  import 'pino';
3
3
  import 'valleyed';
4
- import './requestError-7N-ngghg.js';
4
+ import './requestError-JVHgFJzE.js';
5
5
  import './types/index.js';
6
6
  import './overrides-6Hxg764S.js';
7
7
  import './base-CfeyC14V.js';
@@ -10,11 +10,13 @@ import 'node:stream';
10
10
  import '@fastify/cookie';
11
11
  import './kafka-DCpqW_YM.js';
12
12
  import './events/index.js';
13
- import './fastify-B6FUtYe9.js';
13
+ import './fastify-bLbDRjkI.js';
14
14
  import 'express';
15
15
  import 'fastify';
16
16
  import 'supertest/lib/agent';
17
17
  import 'node:http';
18
+ import '@fastify/cors';
19
+ import 'cors';
18
20
  import 'supertest';
19
21
  import 'socket.io';
20
22
  import './core-BWUHISEy.js';
@@ -1,12 +1,12 @@
1
1
  import { Logger } from 'pino';
2
2
  import * as valleyed from 'valleyed';
3
3
  import { PipeOutput, ConditionalObjectKeys, PipeInput, Pipe } from 'valleyed';
4
- import { B as BaseRequestAuthMethod, E as EquippedError } from '../requestError-7N-ngghg.js';
4
+ import { B as BaseRequestAuthMethod, E as EquippedError } from '../requestError-JVHgFJzE.js';
5
5
  import { E as EventBus } from '../base-CfeyC14V.js';
6
6
  import { K as KafkaEventBus } from '../kafka-DCpqW_YM.js';
7
7
  import { RabbitMQEventBus } from '../events/index.js';
8
8
  import { A as AuthUser } from '../overrides-6Hxg764S.js';
9
- import { E as ExpressServer, F as FastifyServer } from '../fastify-B6FUtYe9.js';
9
+ import { E as ExpressServer, F as FastifyServer } from '../fastify-bLbDRjkI.js';
10
10
  import { InMemoryCache, RedisCache } from '../cache/index.js';
11
11
  import { M as MongoDb } from '../db-vKGTnGlO.js';
12
12
  import { RedisJob } from '../jobs/index.js';
@@ -18,6 +18,8 @@ import 'express';
18
18
  import 'fastify';
19
19
  import 'supertest/lib/agent';
20
20
  import 'node:http';
21
+ import '@fastify/cors';
22
+ import 'cors';
21
23
  import 'supertest';
22
24
  import 'socket.io';
23
25
  import '../core-BWUHISEy.js';
@@ -129,7 +131,7 @@ type ServerTypes = {
129
131
  declare const serverTypePipe: () => valleyed.Pipe<({
130
132
  port: number;
131
133
  cors: {
132
- origin: string[] | undefined;
134
+ origin: boolean | string[] | undefined;
133
135
  methods: ("get" | "delete" | "head" | "options" | "post" | "put" | "patch")[] | undefined;
134
136
  credentials: boolean | undefined;
135
137
  } | undefined;
@@ -161,7 +163,7 @@ declare const serverTypePipe: () => valleyed.Pipe<({
161
163
  }) | ({
162
164
  port: number;
163
165
  cors: {
164
- origin: string[] | undefined;
166
+ origin: boolean | string[] | undefined;
165
167
  methods: ("get" | "delete" | "head" | "options" | "post" | "put" | "patch")[] | undefined;
166
168
  credentials: boolean | undefined;
167
169
  } | undefined;
@@ -27,7 +27,7 @@ declare abstract class BaseRequestAuthMethod<T extends {
27
27
  declare const serverConfigPipe: () => valleyed.Pipe<({
28
28
  port: number;
29
29
  cors: {
30
- origin: string[] | undefined;
30
+ origin: boolean | string[] | undefined;
31
31
  methods: ("get" | "delete" | "head" | "options" | "post" | "put" | "patch")[] | undefined;
32
32
  credentials: boolean | undefined;
33
33
  } | undefined;
@@ -59,7 +59,7 @@ declare const serverConfigPipe: () => valleyed.Pipe<({
59
59
  }) | ({
60
60
  port: number;
61
61
  cors: {
62
- origin: string[] | undefined;
62
+ origin: boolean | string[] | undefined;
63
63
  methods: ("get" | "delete" | "head" | "options" | "post" | "put" | "patch")[] | undefined;
64
64
  credentials: boolean | undefined;
65
65
  } | undefined;
@@ -91,7 +91,7 @@ declare const serverConfigPipe: () => valleyed.Pipe<({
91
91
  }), ({
92
92
  port: number;
93
93
  cors: {
94
- origin: string[] | undefined;
94
+ origin: boolean | string[] | undefined;
95
95
  methods: ("get" | "delete" | "head" | "options" | "post" | "put" | "patch")[] | undefined;
96
96
  credentials: boolean | undefined;
97
97
  } | undefined;
@@ -123,7 +123,7 @@ declare const serverConfigPipe: () => valleyed.Pipe<({
123
123
  }) | ({
124
124
  port: number;
125
125
  cors: {
126
- origin: string[] | undefined;
126
+ origin: boolean | string[] | undefined;
127
127
  methods: ("get" | "delete" | "head" | "options" | "post" | "put" | "patch")[] | undefined;
128
128
  credentials: boolean | undefined;
129
129
  } | undefined;
@@ -1,3 +1,4 @@
1
+ import {} from "@fastify/cors";
1
2
  import {} from "cors";
2
3
  import { Server as SocketServer } from "socket.io";
3
4
  import supertest from "supertest";
@@ -36,7 +37,7 @@ class Server {
36
37
  server;
37
38
  get cors() {
38
39
  return {
39
- origin: this.config.cors?.origin,
40
+ origin: this.config.cors?.origin ? (_, cb) => cb(null, true) : this.config.cors?.origin,
40
41
  methods: (this.config.cors?.methods ?? Object.values(Methods)).filter((m) => m !== Methods.options).map((m) => m.toUpperCase()),
41
42
  credentials: this.config.cors?.credentials
42
43
  };
@@ -183,7 +184,7 @@ class Server {
183
184
  throw new NotFoundError(`Route ${request.path} not found`);
184
185
  });
185
186
  this.implementations.registerErrorHandler(async (error, _, res) => {
186
- Instance.get().log.error({ error }, "Uncaught error in route handler");
187
+ if (!(error instanceof EquippedError)) Instance.get().log.error({ error }, "Uncaught error in route handler");
187
188
  const response = error instanceof RequestError ? new Response({
188
189
  body: error.serializedErrors,
189
190
  status: error.statusCode
@@ -1,12 +1,14 @@
1
- export { E as ExpressServer, F as FastifyServer, O as OnJoinFn, R as Router, S as Server, a as SocketCallbacks, b as SocketEmitter } from '../fastify-B6FUtYe9.js';
2
- import { B as BaseRequestAuthMethod, a as Request, c as RouteDefToReqRes, d as RouteDef, S as ServerConfig, e as Route } from '../requestError-7N-ngghg.js';
3
- export { C as CookieVal, i as DefaultCookies, D as DefaultHeaders, I as IncomingFile, l as MergeRouteDefs, M as Methods, g as MethodsEnum, b as Response, j as RouteConfig, m as RouteDefHandler, k as RouterConfig, f as StatusCodes, h as StatusCodesEnum, o as makeErrorMiddleware, n as makeMiddleware, s as serverConfigPipe } from '../requestError-7N-ngghg.js';
1
+ export { E as ExpressServer, F as FastifyServer, O as OnJoinFn, R as Router, S as Server, a as SocketCallbacks, b as SocketEmitter } from '../fastify-bLbDRjkI.js';
2
+ import { B as BaseRequestAuthMethod, a as Request, c as RouteDefToReqRes, d as RouteDef, S as ServerConfig, e as Route } from '../requestError-JVHgFJzE.js';
3
+ export { C as CookieVal, i as DefaultCookies, D as DefaultHeaders, I as IncomingFile, l as MergeRouteDefs, M as Methods, g as MethodsEnum, b as Response, j as RouteConfig, m as RouteDefHandler, k as RouterConfig, f as StatusCodes, h as StatusCodesEnum, o as makeErrorMiddleware, n as makeMiddleware, s as serverConfigPipe } from '../requestError-JVHgFJzE.js';
4
4
  import { A as AuthUser } from '../overrides-6Hxg764S.js';
5
5
  import { IncomingHttpHeaders } from 'node:http2';
6
6
  import 'express';
7
7
  import 'fastify';
8
8
  import 'supertest/lib/agent';
9
9
  import 'node:http';
10
+ import '@fastify/cors';
11
+ import 'cors';
10
12
  import 'supertest';
11
13
  import 'socket.io';
12
14
  import '../core-BWUHISEy.js';
@@ -6,7 +6,7 @@ const serverBasePipe = () => v.object({
6
6
  port: v.number(),
7
7
  cors: v.optional(
8
8
  v.object({
9
- origin: v.optional(v.array(v.string())),
9
+ origin: v.optional(v.or([v.array(v.string()), v.is(true)])),
10
10
  methods: v.optional(v.array(v.in(Object.values(Methods)))),
11
11
  credentials: v.optional(v.boolean())
12
12
  })
@@ -15,7 +15,7 @@ const signinWithApple = async (idToken) => {
15
15
  try {
16
16
  const APPLE_BASE = "https://appleid.apple.com";
17
17
  const json = jwt.decode(idToken, { complete: true });
18
- if (!json?.header) throw new Error("");
18
+ if (!json?.header) throw new EquippedError("Missing JWT header", { idToken, json });
19
19
  const { kid, alg } = json.header;
20
20
  const publicKey = await jwksClient({ jwksUri: `${APPLE_BASE}/auth/keys`, cache: true }).getSigningKey(kid).then((key) => key.getPublicKey()).catch(() => null);
21
21
  if (!publicKey) throw new EquippedError("no publicKey", { idToken, publicKey, json });
@@ -41,7 +41,7 @@ const signinWithFacebook = async (accessToken, fields = []) => {
41
41
  throw new EquippedError("Failed to sign in with facebook", { accessToken, fields }, err);
42
42
  });
43
43
  const isValidData = fields.every((key) => key in data);
44
- if (!isValidData) throw new Error("Incomplete scope for access token");
44
+ if (!isValidData) throw new EquippedError("Incomplete scope for access token", { accessToken, fields, data });
45
45
  data.email_verified = "true";
46
46
  return data;
47
47
  };
@@ -1,4 +1,4 @@
1
- import { R as RequestError } from './requestError-7N-ngghg.js';
1
+ import { R as RequestError } from './requestError-JVHgFJzE.js';
2
2
 
3
3
  type ValidError = {
4
4
  messages: string[];
@@ -1,8 +1,8 @@
1
1
  import { Pipe, PipeInput, PipeOutput, PipeError } from 'valleyed';
2
2
  export * from 'valleyed';
3
3
  import { AsyncLocalStorage } from 'node:async_hooks';
4
- import { I as IncomingFile, a as Request, b as Response, c as RouteDefToReqRes, d as RouteDef } from '../requestError-7N-ngghg.js';
5
- import { V as ValidationError } from '../validationError-BB4cfdZa.js';
4
+ import { I as IncomingFile, a as Request, b as Response, c as RouteDefToReqRes, d as RouteDef } from '../requestError-JVHgFJzE.js';
5
+ import { V as ValidationError } from '../validationError-CPQdQ7rX.js';
6
6
  import '../types/index.js';
7
7
  import '../overrides-6Hxg764S.js';
8
8
  import '../base-CfeyC14V.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "equipped",
3
- "version": "5.2.0",
3
+ "version": "5.2.2",
4
4
  "private": false,
5
5
  "description": "",
6
6
  "type": "module",