equipped 5.0.13 → 5.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/cjs/cache/base.cjs.map +1 -1
- package/dist/cjs/cache/base.min.cjs.map +1 -1
- package/dist/cjs/cache/types/in-memory.cjs +3 -3
- package/dist/cjs/cache/types/in-memory.cjs.map +1 -1
- package/dist/cjs/cache/types/in-memory.min.cjs +1 -1
- package/dist/cjs/cache/types/in-memory.min.cjs.map +1 -1
- package/dist/cjs/cache/types/redis.cjs +1 -1
- package/dist/cjs/cache/types/redis.cjs.map +1 -1
- package/dist/cjs/cache/types/redis.min.cjs +1 -1
- package/dist/cjs/cache/types/redis.min.cjs.map +1 -1
- package/dist/cjs/dbs/mongo/api.cjs +4 -6
- package/dist/cjs/dbs/mongo/api.cjs.map +1 -1
- package/dist/cjs/dbs/mongo/api.min.cjs +1 -1
- package/dist/cjs/dbs/mongo/api.min.cjs.map +1 -1
- package/dist/cjs/dbs/mongo/index.cjs +8 -8
- package/dist/cjs/dbs/mongo/index.cjs.map +1 -1
- package/dist/cjs/dbs/mongo/index.min.cjs +1 -1
- package/dist/cjs/dbs/mongo/index.min.cjs.map +1 -1
- package/dist/cjs/server/openapi.cjs +1 -1
- package/dist/cjs/server/openapi.cjs.map +1 -1
- package/dist/cjs/server/openapi.min.cjs +1 -1
- package/dist/cjs/server/openapi.min.cjs.map +1 -1
- package/dist/esm/cache/base.min.mjs.map +1 -1
- package/dist/esm/cache/base.mjs.map +1 -1
- package/dist/esm/cache/types/in-memory.min.mjs +1 -1
- package/dist/esm/cache/types/in-memory.min.mjs.map +1 -1
- package/dist/esm/cache/types/in-memory.mjs +3 -3
- package/dist/esm/cache/types/in-memory.mjs.map +1 -1
- package/dist/esm/cache/types/redis.min.mjs +1 -1
- package/dist/esm/cache/types/redis.min.mjs.map +1 -1
- package/dist/esm/cache/types/redis.mjs +1 -1
- package/dist/esm/cache/types/redis.mjs.map +1 -1
- package/dist/esm/dbs/mongo/api.min.mjs +1 -1
- package/dist/esm/dbs/mongo/api.min.mjs.map +1 -1
- package/dist/esm/dbs/mongo/api.mjs +4 -6
- package/dist/esm/dbs/mongo/api.mjs.map +1 -1
- package/dist/esm/dbs/mongo/index.min.mjs +1 -1
- package/dist/esm/dbs/mongo/index.min.mjs.map +1 -1
- package/dist/esm/dbs/mongo/index.mjs +8 -8
- package/dist/esm/dbs/mongo/index.mjs.map +1 -1
- package/dist/esm/server/openapi.min.mjs +1 -1
- package/dist/esm/server/openapi.min.mjs.map +1 -1
- package/dist/esm/server/openapi.mjs +1 -1
- package/dist/esm/server/openapi.mjs.map +1 -1
- package/dist/types/{base-k4t2NepI.d.ts → base-8yVXb67P.d.ts} +2 -2
- package/dist/types/cache/index.d.ts +5 -5
- package/dist/types/cache/types/in-memory.js +3 -3
- package/dist/types/cache/types/redis.js +1 -1
- package/dist/types/dbs/index.d.ts +2 -2
- package/dist/types/dbs/mongo/api.js +4 -6
- package/dist/types/dbs/mongo/index.js +8 -8
- package/dist/types/{index-BtF0VClz.d.ts → index-BS53hVyq.d.ts} +2 -2
- package/dist/types/{index-CegB2bgP.d.ts → index-CfuXekZB.d.ts} +2 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/instance/index.d.ts +3 -3
- package/dist/types/server/index.d.ts +4 -4
- package/dist/types/server/openapi.js +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/openapi.ts","/home/runner/work/equipped/equipped/dist/cjs/server/openapi.cjs"],"names":["schema"],"mappings":"AAAA,4wBAAwB;AAExB,oCAAuC;AAGvC,yCAAuB;AAmBhB,MAAM,QAAQ;AAAA,EAKpB,WAAA,CAAoB,MAAA,EAAsB;AAAtB,IAAA,IAAA,CAAA,OAAA,EAAA,MAAA;AACnB,IAAA,IAAA,CAAK,CAAA,eAAA,EAAkB;AAAA,MACtB,OAAA,EAAS,OAAA;AAAA,MACT,IAAA,EAAM;AAAA,QACL,KAAA,EAAO,CAAA,EAAA;AACP,QAAA;AACD,MAAA;AACS,MAAA;AACD,MAAA;AACR,MAAA;AACC,QAAA;AACA,QAAA;AACC,UAAA;AACC,YAAA;AACA,YAAA;AACI,YAAA;AACL,UAAA;AACA,UAAA;AACC,YAAA;AACA,YAAA;AACI,YAAA;AACL,UAAA;AACA,UAAA;AACC,YAAA;AACA,YAAA;AACI,YAAA;AACL,UAAA;AACD,QAAA;AACD,MAAA;AACO,MAAA;AACP,MAAA;AACD,IAAA;AACD,EAAA;AApCA,EAAA;AACA,EAAA;AACA,EAAA;AAoCU,EAAA;AACL,IAAA;AACC,IAAA;AACD,IAAA;AACG,IAAA;AACR,EAAA;AAEM,EAAA;AACK,IAAA;AAEE,IAAA;AAEN,IAAA;AACA,IAAA;AACK,IAAA;AACV,MAAA;AACS,MAAA;AACT,MAAA;AACM,MAAA;AACI,MAAA;AACV,IAAA;AACF,EAAA;AAEM,EAAA;AACG,IAAA;AACG,MAAA;AACV,MAAA;AACC,QAAA;AACM,QAAA;AACF,QAAA;AACL,MAAA;AACD,IAAA;AAEQ,IAAA;AACG,MAAA;AACV,MAAA;AACC,QAAA;AACA,QAAA;AACM,QAAA;AACF,QAAA;AACL,MAAA;AACD,IAAA;AAEQ,IAAA;AACG,MAAA;AACT,QAAA;AACA,QAAA;AACC,UAAA;AACD,QAAA;AACD,MAAA;AAEK,IAAA;AAEA,IAAA;AACA,MAAA;AACC,MAAA;AACN,MAAA;AACMA,QAAAA;AACL,QAAA;AACC,UAAA;AACC,YAAA;AACI,YAAA;AACJ,YAAA;AACA,YAAA;AACA,UAAA;AACH,MAAA;AACD,IAAA;AAEM,IAAA;AACK,MAAA;AACA,MAAA;AACA,MAAA;AACV,IAAA;AACG,IAAA;AAEE,IAAA;AACI,IAAA;AACA,IAAA;AACC,IAAA;AACZ,EAAA;AAES,EAAA;AACF,IAAA;AACA,IAAA;AACK,IAAA;AACA,IAAA;AACJ,IAAA;AACR,EAAA;AAEA,EAAA;AACS,IAAA;AACG,IAAA;AACH,IAAA;AACT,EAAA;AAEyB,EAAA;AACnB,IAAA;AACM,IAAA;AACF,MAAA;AACF,MAAA;AACG,MAAA;AACH,QAAA;AACE,QAAA;AACD,MAAA;AACR,IAAA;AAEU,IAAA;AACH,IAAA;AACR,EAAA;AAEU,EAAA;AACG,IAAA;AACN,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AAKI,IAAA;AACJ,MAAA;AACA,MAAA;AAEC,MAAA;AACA,MAAA;AACI,MAAA;AACH,QAAA;AACD,QAAA;AACA,QAAA;AACN,MAAA;AACK,MAAA;AACN,IAAA;AAEO,IAAA;AACR,EAAA;AAEM,EAAA;AACC,IAAA;AACC,IAAA;AAAA;AAAA;AAAA;AAII,WAAA;AAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yCAAA;AAUiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASlD,EAAA;AACD;AC3CgB;AACA;AACA","file":"/home/runner/work/equipped/equipped/dist/cjs/server/openapi.cjs","sourcesContent":["import { convert } from '@openapi-contrib/json-schema-to-openapi-schema'\nimport { OpenAPIV3_1 } from 'openapi-types'\nimport { capitalize, JsonSchema } from 'valleyed'\n\nimport { ServerConfig } from './pipes'\nimport { Router } from './routes'\nimport { Route } from './types'\n\ndeclare module 'openapi-types' {\n\tnamespace OpenAPIV3 {\n\t\tinterface Document {\n\t\t\t'x-tagGroups': { name: string; tags: string[] }[]\n\t\t}\n\t\tinterface TagObject {\n\t\t\t'x-displayName': string\n\t\t}\n\t}\n}\n\nexport type OpenApiSchemaDef = {\n\trequest: Partial<Record<'body' | 'query' | 'params' | 'headers' | 'response', JsonSchema>>\n\tresponse: Partial<Record<'response' | 'responseHeaders', { status: number; schema: JsonSchema; contentType: string }[]>>\n}\n\nexport class OpenApi {\n\t#registeredTags: Record<string, boolean> = {}\n\t#registeredTagGroups: Record<string, { name: string; tags: string[] }> = {}\n\t#baseOpenapiDoc: OpenAPIV3_1.Document\n\n\tconstructor(private config: ServerConfig) {\n\t\tthis.#baseOpenapiDoc = {\n\t\t\topenapi: '3.0.0',\n\t\t\tinfo: {\n\t\t\t\ttitle: `${config.app.name} ${config.app.id}`,\n\t\t\t\tversion: config.config.openapi.docsVersion ?? '',\n\t\t\t},\n\t\t\tservers: config.config.openapi.docsBaseUrl?.map((url) => ({ url })),\n\t\t\tpaths: {},\n\t\t\tcomponents: {\n\t\t\t\tschemas: {},\n\t\t\t\tsecuritySchemes: {\n\t\t\t\t\tAuthorization: {\n\t\t\t\t\t\ttype: 'apiKey',\n\t\t\t\t\t\tname: 'authorization',\n\t\t\t\t\t\tin: 'header',\n\t\t\t\t\t},\n\t\t\t\t\tRefreshToken: {\n\t\t\t\t\t\ttype: 'apiKey',\n\t\t\t\t\t\tname: 'x-refresh-token',\n\t\t\t\t\t\tin: 'header',\n\t\t\t\t\t},\n\t\t\t\t\tApiKey: {\n\t\t\t\t\t\ttype: 'apiKey',\n\t\t\t\t\t\tname: 'x-api-key',\n\t\t\t\t\t\tin: 'header',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\ttags: [],\n\t\t\t'x-tagGroups': [],\n\t\t}\n\t}\n\n\tcleanPath(path: string) {\n\t\tlet cleaned = path.replace(/(\\/\\s*)+/g, '/')\n\t\tif (!cleaned.startsWith('/')) cleaned = `/${cleaned}`\n\t\tif (cleaned !== '/' && cleaned.endsWith('/')) cleaned = cleaned.slice(0, -1)\n\t\treturn cleaned\n\t}\n\n\tasync register(route: Route<any>, def: OpenApiSchemaDef) {\n\t\tif (route.hide) return\n\n\t\tconst tag = this.#buildTag(route.groups ?? [])\n\n\t\tconst cleanPath = this.cleanPath(route.path)\n\t\tconst operationId = `(${route.method.toUpperCase()}) ${cleanPath}`\n\t\tawait this.#addRouteToOpenApiDoc(cleanPath, route.method.toLowerCase(), def, {\n\t\t\toperationId,\n\t\t\tsummary: route.title ?? cleanPath,\n\t\t\tdescription: route.descriptions?.join('\\n\\n'),\n\t\t\ttags: tag ? [tag] : undefined,\n\t\t\tsecurity: route.security,\n\t\t})\n\t}\n\n\tasync #addRouteToOpenApiDoc(path: string, method: string, def: OpenApiSchemaDef, methodObj: OpenAPIV3_1.OperationObject) {\n\t\tif (def.response.response?.length) {\n\t\t\tmethodObj.responses ??= {}\n\t\t\tfor (const resp of def.response.response) {\n\t\t\t\tmethodObj.responses[resp.status] ??= { description: '', content: {} }\n\t\t\t\tconst res = methodObj.responses[resp.status] as OpenAPIV3_1.ResponseObject\n\t\t\t\tres.content![resp.contentType] = { schema: await convert(this.#visit(resp.schema)) }\n\t\t\t}\n\t\t}\n\n\t\tif (def.response.responseHeaders?.length) {\n\t\t\tmethodObj.responses ??= {}\n\t\t\tfor (const resp of def.response.responseHeaders) {\n\t\t\t\tmethodObj.responses[resp.status] ??= { description: '', content: {} }\n\t\t\t\tmethodObj.responses[resp.status] as OpenAPIV3_1.ResponseObject\n\t\t\t\tconst res = methodObj.responses[resp.status] as OpenAPIV3_1.ResponseObject\n\t\t\t\tres.headers = { schema: (await convert(this.#visit(resp.schema))) as any }\n\t\t\t}\n\t\t}\n\n\t\tif (def.request.body)\n\t\t\tmethodObj.requestBody = {\n\t\t\t\trequired: true,\n\t\t\t\tcontent: {\n\t\t\t\t\t'application/json': { schema: await convert(this.#visit(def.request.body)) },\n\t\t\t\t},\n\t\t\t}\n\n\t\tconst parameters: OpenAPIV3_1.ParameterObject[] = []\n\n\t\tconst addParams = async (location: 'query' | 'path' | 'header', schema: JsonSchema | undefined) => {\n\t\t\tif (!schema) return\n\t\t\tconst flat = this.#flattenForParameters(schema)\n\t\t\tfor (const schema of flat) {\n\t\t\t\tif (!schema.properties) continue\n\t\t\t\tfor (const [name, value] of Object.entries(schema.properties))\n\t\t\t\t\tparameters.push({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tin: location,\n\t\t\t\t\t\tschema: await convert(this.#visit(value)),\n\t\t\t\t\t\trequired: (schema.required || []).includes(name),\n\t\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tawait Promise.all([\n\t\t\taddParams('query', def.request.query),\n\t\t\taddParams('path', def.request.params),\n\t\t\taddParams('header', def.request.headers),\n\t\t])\n\t\tif (parameters.length) methodObj.parameters = parameters\n\n\t\tconst base = this.#baseOpenapiDoc\n\t\tif (!base.paths) base.paths = {}\n\t\tif (!base.paths[path]) base.paths[path] = {}\n\t\tbase.paths[path]![method] = methodObj\n\t}\n\n\trouter() {\n\t\tconst jsonPath = '/openapi.json'\n\t\tconst router = new Router({ path: this.config.config.openapi.docsPath ?? '/', hide: true })\n\t\trouter.get('/')((req) => req.res({ body: this.#html(`.${jsonPath}`), contentType: 'text/html' }))\n\t\trouter.get(jsonPath)((req) => req.res({ body: this.#baseOpenapiDoc }))\n\t\treturn router\n\t}\n\n\t#flattenForParameters(node: JsonSchema): JsonSchema[] {\n\t\tconst { allOf, oneOf, anyOf, ...schema } = node\n\t\tif (allOf) return allOf.flatMap((n) => this.#flattenForParameters(n))\n\t\treturn [schema]\n\t}\n\n\t#visit(node: JsonSchema) {\n\t\tif (!node || typeof node !== 'object') return node\n\t\tif (typeof node.$refId === 'string') {\n\t\t\tconst { $refId: id, ...rest } = node\n\t\t\tconst res = this.#visit(rest)\n\t\t\tif (this.#baseOpenapiDoc.components?.schemas) {\n\t\t\t\tthis.#baseOpenapiDoc.components.schemas[id] = res\n\t\t\t\treturn { $ref: `#/components/schemas/${id}` }\n\t\t\t} else return res\n\t\t}\n\n\t\tif (Array.isArray(node)) return node.map((n) => this.#visit(n)) as any\n\t\treturn Object.fromEntries(Object.entries(node).map(([key, value]) => [key, this.#visit(value as any)]))\n\t}\n\n\t#buildTag(groups: NonNullable<Route<any>['groups']>) {\n\t\tif (!groups.length) return undefined\n\t\tconst parsed = groups.map((g) => (typeof g === 'string' ? { name: g } : g))\n\t\tconst name = parsed.map((g) => g.name).join(' > ')\n\t\tconst displayName = parsed.at(-1)?.name ?? ''\n\t\tconst description = parsed\n\t\t\t.map((g) => g.description?.trim() ?? '')\n\t\t\t.filter(Boolean)\n\t\t\t.join('\\n\\n\\n\\n')\n\n\t\tif (!this.#registeredTags[name]) {\n\t\t\tthis.#registeredTags[name] = true\n\t\t\tthis.#baseOpenapiDoc.tags!.push({ name, 'x-displayName': displayName, description })\n\n\t\t\tconst tagGroups = parsed.slice(0, -1)\n\t\t\tconst groupName = tagGroups.map((g) => g.name).join(' > ') || 'default'\n\t\t\tif (!this.#registeredTagGroups[groupName]) {\n\t\t\t\tconst group = { name: groupName, tags: [] }\n\t\t\t\tthis.#baseOpenapiDoc['x-tagGroups'].push(group)\n\t\t\t\tthis.#registeredTagGroups[groupName] = group\n\t\t\t}\n\t\t\tthis.#registeredTagGroups[groupName].tags = [...new Set([...this.#registeredTagGroups[groupName].tags, name])]\n\t\t}\n\n\t\treturn name\n\t}\n\n\t#html(jsonPath: string) {\n\t\tconst title = capitalize(`${this.config.app.name} ${this.config.app.id}`)\n\t\treturn `\n<!doctype html>\n<html>\n <head>\n <title>${title}</title>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n\t<style>\n .darklight-reference {\n display: none;\n }\n </style>\n </head>\n <body>\n <script id=\"api-reference\" data-url=\"${jsonPath}\"></script>\n <script>\n const configuration = { theme: 'purple' };\n document.getElementById('api-reference').dataset.configuration = JSON.stringify(configuration);\n </script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference@1.28.33\"></script>\n </body>\n</html>\n`\n\t}\n}\n",null]}
|
|
1
|
+
{"version":3,"sources":["../../../src/server/openapi.ts","/home/runner/work/equipped/equipped/dist/cjs/server/openapi.cjs"],"names":["schema"],"mappings":"AAAA,4wBAAwB;AAExB,oCAAuC;AAGvC,yCAAuB;AAmBhB,MAAM,QAAQ;AAAA,EAKpB,WAAA,CAAoB,MAAA,EAAsB;AAAtB,IAAA,IAAA,CAAA,OAAA,EAAA,MAAA;AACnB,IAAA,IAAA,CAAK,CAAA,eAAA,EAAkB;AAAA,MACtB,OAAA,EAAS,OAAA;AAAA,MACT,IAAA,EAAM;AAAA,QACL,KAAA,EAAO,CAAA,EAAA;AACP,QAAA;AACD,MAAA;AACS,MAAA;AACD,MAAA;AACR,MAAA;AACC,QAAA;AACA,QAAA;AACC,UAAA;AACC,YAAA;AACA,YAAA;AACI,YAAA;AACL,UAAA;AACA,UAAA;AACC,YAAA;AACA,YAAA;AACI,YAAA;AACL,UAAA;AACA,UAAA;AACC,YAAA;AACA,YAAA;AACI,YAAA;AACL,UAAA;AACD,QAAA;AACD,MAAA;AACO,MAAA;AACP,MAAA;AACD,IAAA;AACD,EAAA;AApCA,EAAA;AACA,EAAA;AACA,EAAA;AAoCU,EAAA;AACL,IAAA;AACC,IAAA;AACD,IAAA;AACG,IAAA;AACR,EAAA;AAEM,EAAA;AACK,IAAA;AAEE,IAAA;AAEN,IAAA;AACA,IAAA;AACK,IAAA;AACV,MAAA;AACS,MAAA;AACT,MAAA;AACM,MAAA;AACI,MAAA;AACV,IAAA;AACF,EAAA;AAEM,EAAA;AACG,IAAA;AACG,MAAA;AACV,MAAA;AACC,QAAA;AACM,QAAA;AACF,QAAA;AACL,MAAA;AACD,IAAA;AAEQ,IAAA;AACG,MAAA;AACV,MAAA;AACC,QAAA;AACA,QAAA;AACM,QAAA;AACF,QAAA;AACL,MAAA;AACD,IAAA;AAEQ,IAAA;AACG,MAAA;AACT,QAAA;AACA,QAAA;AACC,UAAA;AACD,QAAA;AACD,MAAA;AAEK,IAAA;AAEA,IAAA;AACA,MAAA;AACC,MAAA;AACN,MAAA;AACMA,QAAAA;AACL,QAAA;AACC,UAAA;AACC,YAAA;AACI,YAAA;AACJ,YAAA;AACA,YAAA;AACA,UAAA;AACH,MAAA;AACD,IAAA;AAEM,IAAA;AACK,MAAA;AACA,MAAA;AACA,MAAA;AACV,IAAA;AACG,IAAA;AAEE,IAAA;AACI,IAAA;AACA,IAAA;AACC,IAAA;AACZ,EAAA;AAES,EAAA;AACF,IAAA;AACA,IAAA;AACK,IAAA;AACA,IAAA;AACJ,IAAA;AACR,EAAA;AAEA,EAAA;AACS,IAAA;AACG,IAAA;AACH,IAAA;AACT,EAAA;AAEyB,EAAA;AACnB,IAAA;AACM,IAAA;AACF,MAAA;AACF,MAAA;AACG,MAAA;AACH,QAAA;AACE,QAAA;AACD,MAAA;AACR,IAAA;AAEU,IAAA;AACH,IAAA;AACR,EAAA;AAEU,EAAA;AACG,IAAA;AACN,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AAKI,IAAA;AACJ,MAAA;AACA,MAAA;AAEC,MAAA;AACA,MAAA;AACI,MAAA;AACH,QAAA;AACD,QAAA;AACA,QAAA;AACN,MAAA;AACK,MAAA;AACN,IAAA;AAEO,IAAA;AACR,EAAA;AAEM,EAAA;AACC,IAAA;AACC,IAAA;AAAA;AAAA;AAAA;AAII,WAAA;AAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yCAAA;AAUiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASlD,EAAA;AACD;AC3CgB;AACA;AACA","file":"/home/runner/work/equipped/equipped/dist/cjs/server/openapi.cjs","sourcesContent":["import { convert } from '@openapi-contrib/json-schema-to-openapi-schema'\nimport { OpenAPIV3_1 } from 'openapi-types'\nimport { capitalize, JsonSchema } from 'valleyed'\n\nimport { ServerConfig } from './pipes'\nimport { Router } from './routes'\nimport { Route } from './types'\n\ndeclare module 'openapi-types' {\n\tnamespace OpenAPIV3 {\n\t\tinterface Document {\n\t\t\t'x-tagGroups': { name: string; tags: string[] }[]\n\t\t}\n\t\tinterface TagObject {\n\t\t\t'x-displayName': string\n\t\t}\n\t}\n}\n\nexport type OpenApiSchemaDef = {\n\trequest: Partial<Record<'body' | 'query' | 'params' | 'headers' | 'response', JsonSchema>>\n\tresponse: Partial<Record<'response' | 'responseHeaders', { status: number; schema: JsonSchema; contentType: string }[]>>\n}\n\nexport class OpenApi {\n\t#registeredTags: Record<string, boolean> = {}\n\t#registeredTagGroups: Record<string, { name: string; tags: string[] }> = {}\n\t#baseOpenapiDoc: OpenAPIV3_1.Document\n\n\tconstructor(private config: ServerConfig) {\n\t\tthis.#baseOpenapiDoc = {\n\t\t\topenapi: '3.0.0',\n\t\t\tinfo: {\n\t\t\t\ttitle: `${config.app.name} ${config.app.id}`,\n\t\t\t\tversion: config.config.openapi.docsVersion ?? '',\n\t\t\t},\n\t\t\tservers: config.config.openapi.docsBaseUrl?.map((url) => ({ url })),\n\t\t\tpaths: {},\n\t\t\tcomponents: {\n\t\t\t\tschemas: {},\n\t\t\t\tsecuritySchemes: {\n\t\t\t\t\tAuthorization: {\n\t\t\t\t\t\ttype: 'apiKey',\n\t\t\t\t\t\tname: 'authorization',\n\t\t\t\t\t\tin: 'header',\n\t\t\t\t\t},\n\t\t\t\t\tRefreshToken: {\n\t\t\t\t\t\ttype: 'apiKey',\n\t\t\t\t\t\tname: 'x-refresh-token',\n\t\t\t\t\t\tin: 'header',\n\t\t\t\t\t},\n\t\t\t\t\tApiKey: {\n\t\t\t\t\t\ttype: 'apiKey',\n\t\t\t\t\t\tname: 'x-api-key',\n\t\t\t\t\t\tin: 'header',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\ttags: [],\n\t\t\t'x-tagGroups': [],\n\t\t}\n\t}\n\n\tcleanPath(path: string) {\n\t\tlet cleaned = path.replace(/(\\/\\s*)+/g, '/')\n\t\tif (!cleaned.startsWith('/')) cleaned = `/${cleaned}`\n\t\tif (cleaned !== '/' && cleaned.endsWith('/')) cleaned = cleaned.slice(0, -1)\n\t\treturn cleaned\n\t}\n\n\tasync register(route: Route<any>, def: OpenApiSchemaDef) {\n\t\tif (route.hide) return\n\n\t\tconst tag = this.#buildTag(route.groups ?? [])\n\n\t\tconst cleanPath = this.cleanPath(route.path)\n\t\tconst operationId = `(${route.method.toUpperCase()}) ${cleanPath}`\n\t\tawait this.#addRouteToOpenApiDoc(cleanPath, route.method.toLowerCase(), def, {\n\t\t\toperationId,\n\t\t\tsummary: route.title ?? cleanPath,\n\t\t\tdescription: route.descriptions?.join('\\n\\n'),\n\t\t\ttags: tag ? [tag] : undefined,\n\t\t\tsecurity: route.security,\n\t\t})\n\t}\n\n\tasync #addRouteToOpenApiDoc(path: string, method: string, def: OpenApiSchemaDef, methodObj: OpenAPIV3_1.OperationObject) {\n\t\tif (def.response.response?.length) {\n\t\t\tmethodObj.responses ??= {}\n\t\t\tfor (const resp of def.response.response) {\n\t\t\t\tmethodObj.responses[resp.status] ??= { description: '', content: {} }\n\t\t\t\tconst res = methodObj.responses[resp.status] as OpenAPIV3_1.ResponseObject\n\t\t\t\tres.content![resp.contentType] = { schema: await convert(this.#visit(resp.schema)) }\n\t\t\t}\n\t\t}\n\n\t\tif (def.response.responseHeaders?.length) {\n\t\t\tmethodObj.responses ??= {}\n\t\t\tfor (const resp of def.response.responseHeaders) {\n\t\t\t\tmethodObj.responses[resp.status] ??= { description: '', content: {} }\n\t\t\t\tmethodObj.responses[resp.status] as OpenAPIV3_1.ResponseObject\n\t\t\t\tconst res = methodObj.responses[resp.status] as OpenAPIV3_1.ResponseObject\n\t\t\t\tres.headers = { schema: (await convert(this.#visit(resp.schema))) as any }\n\t\t\t}\n\t\t}\n\n\t\tif (def.request.body)\n\t\t\tmethodObj.requestBody = {\n\t\t\t\trequired: true,\n\t\t\t\tcontent: {\n\t\t\t\t\t'application/json': { schema: await convert(this.#visit(def.request.body)) },\n\t\t\t\t},\n\t\t\t}\n\n\t\tconst parameters: OpenAPIV3_1.ParameterObject[] = []\n\n\t\tconst addParams = async (location: 'query' | 'path' | 'header', schema: JsonSchema | undefined) => {\n\t\t\tif (!schema) return\n\t\t\tconst flat = this.#flattenForParameters(schema)\n\t\t\tfor (const schema of flat) {\n\t\t\t\tif (!schema.properties) continue\n\t\t\t\tfor (const [name, value] of Object.entries(schema.properties))\n\t\t\t\t\tparameters.push({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tin: location,\n\t\t\t\t\t\tschema: await convert(this.#visit(value)),\n\t\t\t\t\t\trequired: (schema.required || []).includes(name),\n\t\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tawait Promise.all([\n\t\t\taddParams('query', def.request.query),\n\t\t\taddParams('path', def.request.params),\n\t\t\taddParams('header', def.request.headers),\n\t\t])\n\t\tif (parameters.length) methodObj.parameters = parameters\n\n\t\tconst base = this.#baseOpenapiDoc\n\t\tif (!base.paths) base.paths = {}\n\t\tif (!base.paths[path]) base.paths[path] = {}\n\t\tbase.paths[path]![method] = methodObj\n\t}\n\n\trouter() {\n\t\tconst jsonPath = '/openapi.json'\n\t\tconst router = new Router({ path: this.config.config.openapi.docsPath ?? '/', hide: true })\n\t\trouter.get('/index.html')((req) => req.res({ body: this.#html(`.${jsonPath}`), contentType: 'text/html' }))\n\t\trouter.get(jsonPath)((req) => req.res({ body: this.#baseOpenapiDoc }))\n\t\treturn router\n\t}\n\n\t#flattenForParameters(node: JsonSchema): JsonSchema[] {\n\t\tconst { allOf, oneOf, anyOf, ...schema } = node\n\t\tif (allOf) return allOf.flatMap((n) => this.#flattenForParameters(n))\n\t\treturn [schema]\n\t}\n\n\t#visit(node: JsonSchema) {\n\t\tif (!node || typeof node !== 'object') return node\n\t\tif (typeof node.$refId === 'string') {\n\t\t\tconst { $refId: id, ...rest } = node\n\t\t\tconst res = this.#visit(rest)\n\t\t\tif (this.#baseOpenapiDoc.components?.schemas) {\n\t\t\t\tthis.#baseOpenapiDoc.components.schemas[id] = res\n\t\t\t\treturn { $ref: `#/components/schemas/${id}` }\n\t\t\t} else return res\n\t\t}\n\n\t\tif (Array.isArray(node)) return node.map((n) => this.#visit(n)) as any\n\t\treturn Object.fromEntries(Object.entries(node).map(([key, value]) => [key, this.#visit(value as any)]))\n\t}\n\n\t#buildTag(groups: NonNullable<Route<any>['groups']>) {\n\t\tif (!groups.length) return undefined\n\t\tconst parsed = groups.map((g) => (typeof g === 'string' ? { name: g } : g))\n\t\tconst name = parsed.map((g) => g.name).join(' > ')\n\t\tconst displayName = parsed.at(-1)?.name ?? ''\n\t\tconst description = parsed\n\t\t\t.map((g) => g.description?.trim() ?? '')\n\t\t\t.filter(Boolean)\n\t\t\t.join('\\n\\n\\n\\n')\n\n\t\tif (!this.#registeredTags[name]) {\n\t\t\tthis.#registeredTags[name] = true\n\t\t\tthis.#baseOpenapiDoc.tags!.push({ name, 'x-displayName': displayName, description })\n\n\t\t\tconst tagGroups = parsed.slice(0, -1)\n\t\t\tconst groupName = tagGroups.map((g) => g.name).join(' > ') || 'default'\n\t\t\tif (!this.#registeredTagGroups[groupName]) {\n\t\t\t\tconst group = { name: groupName, tags: [] }\n\t\t\t\tthis.#baseOpenapiDoc['x-tagGroups'].push(group)\n\t\t\t\tthis.#registeredTagGroups[groupName] = group\n\t\t\t}\n\t\t\tthis.#registeredTagGroups[groupName].tags = [...new Set([...this.#registeredTagGroups[groupName].tags, name])]\n\t\t}\n\n\t\treturn name\n\t}\n\n\t#html(jsonPath: string) {\n\t\tconst title = capitalize(`${this.config.app.name} ${this.config.app.id}`)\n\t\treturn `\n<!doctype html>\n<html>\n <head>\n <title>${title}</title>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n\t<style>\n .darklight-reference {\n display: none;\n }\n </style>\n </head>\n <body>\n <script id=\"api-reference\" data-url=\"${jsonPath}\"></script>\n <script>\n const configuration = { theme: 'purple' };\n document.getElementById('api-reference').dataset.configuration = JSON.stringify(configuration);\n </script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference@1.28.33\"></script>\n </body>\n</html>\n`\n\t}\n}\n",null]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); 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; }var _jsonschematoopenapischema = require('@openapi-contrib/json-schema-to-openapi-schema');var _valleyed = require('valleyed');var _routesmincjs = require('./routes.min.cjs');class I{constructor(e){this.config=e;this.#e={openapi:"3.0.0",info:{title:`${e.app.name} ${e.app.id}`,version:_nullishCoalesce(e.config.openapi.docsVersion, () => (""))},servers:_optionalChain([e, 'access', _ => _.config, 'access', _2 => _2.openapi, 'access', _3 => _3.docsBaseUrl, 'optionalAccess', _4 => _4.map, 'call', _5 => _5(s=>({url:s}))]),paths:{},components:{schemas:{},securitySchemes:{Authorization:{type:"apiKey",name:"authorization",in:"header"},RefreshToken:{type:"apiKey",name:"x-refresh-token",in:"header"},ApiKey:{type:"apiKey",name:"x-api-key",in:"header"}}},tags:[],"x-tagGroups":[]}}#n={};#t={};#e;cleanPath(e){let s=e.replace(/(\/\s*)+/g,"/");return s.startsWith("/")||(s=`/${s}`),s!=="/"&&s.endsWith("/")&&(s=s.slice(0,-1)),s}async register(e,s){if(e.hide)return;const t=this.#i(_nullishCoalesce(e.groups, () => ([]))),n=this.cleanPath(e.path),o=`(${e.method.toUpperCase()}) ${n}`;await this.#a(n,e.method.toLowerCase(),s,{operationId:o,summary:_nullishCoalesce(e.title, () => (n)),description:_optionalChain([e, 'access', _6 => _6.descriptions, 'optionalAccess', _7 => _7.join, 'call', _8 => _8(`
|
|
2
2
|
|
|
3
|
-
`)]),tags:t?[t]:void 0,security:e.security})}async#a(e,s,t,n){if(_optionalChain([t, 'access', _9 => _9.response, 'access', _10 => _10.response, 'optionalAccess', _11 => _11.length])){n.responses??={};for(const r of t.response.response){n.responses[r.status]??={description:"",content:{}};const p=n.responses[r.status];p.content[r.contentType]={schema:await _jsonschematoopenapischema.convert.call(void 0, this.#s(r.schema))}}}if(_optionalChain([t, 'access', _12 => _12.response, 'access', _13 => _13.responseHeaders, 'optionalAccess', _14 => _14.length])){n.responses??={};for(const r of t.response.responseHeaders){n.responses[r.status]??={description:"",content:{}},n.responses[r.status];const p=n.responses[r.status];p.headers={schema:await _jsonschematoopenapischema.convert.call(void 0, this.#s(r.schema))}}}t.request.body&&(n.requestBody={required:!0,content:{"application/json":{schema:await _jsonschematoopenapischema.convert.call(void 0, this.#s(t.request.body))}}});const o=[],a=async(r,p)=>{if(!p)return;const u=this.#r(p);for(const h of u)if(h.properties)for(const[m,f]of Object.entries(h.properties))o.push({name:m,in:r,schema:await _jsonschematoopenapischema.convert.call(void 0, this.#s(f)),required:(h.required||[]).includes(m)})};await Promise.all([a("query",t.request.query),a("path",t.request.params),a("header",t.request.headers)]),o.length&&(n.parameters=o);const i=this.#e;i.paths||(i.paths={}),i.paths[e]||(i.paths[e]={}),i.paths[e][s]=n}router(){const e="/openapi.json",s=new (0, _routesmincjs.Router)({path:_nullishCoalesce(this.config.config.openapi.docsPath, () => ("/")),hide:!0});return s.get("/")(t=>t.res({body:this.#o(`.${e}`),contentType:"text/html"})),s.get(e)(t=>t.res({body:this.#e})),s}#r(e){const{allOf:s,oneOf:t,anyOf:n,...o}=e;return s?s.flatMap(a=>this.#r(a)):[o]}#s(e){if(!e||typeof e!="object")return e;if(typeof e.$refId=="string"){const{$refId:s,...t}=e,n=this.#s(t);return _optionalChain([this, 'access', _15 => _15.#e, 'access', _16 => _16.components, 'optionalAccess', _17 => _17.schemas])?(this.#e.components.schemas[s]=n,{$ref:`#/components/schemas/${s}`}):n}return Array.isArray(e)?e.map(s=>this.#s(s)):Object.fromEntries(Object.entries(e).map(([s,t])=>[s,this.#s(t)]))}#i(e){if(!e.length)return;const s=e.map(a=>typeof a=="string"?{name:a}:a),t=s.map(a=>a.name).join(" > "),n=_nullishCoalesce(_optionalChain([s, 'access', _18 => _18.at, 'call', _19 => _19(-1), 'optionalAccess', _20 => _20.name]), () => ("")),o=s.map(a=>_nullishCoalesce(_optionalChain([a, 'access', _21 => _21.description, 'optionalAccess', _22 => _22.trim, 'call', _23 => _23()]), () => (""))).filter(Boolean).join(`
|
|
3
|
+
`)]),tags:t?[t]:void 0,security:e.security})}async#a(e,s,t,n){if(_optionalChain([t, 'access', _9 => _9.response, 'access', _10 => _10.response, 'optionalAccess', _11 => _11.length])){n.responses??={};for(const r of t.response.response){n.responses[r.status]??={description:"",content:{}};const p=n.responses[r.status];p.content[r.contentType]={schema:await _jsonschematoopenapischema.convert.call(void 0, this.#s(r.schema))}}}if(_optionalChain([t, 'access', _12 => _12.response, 'access', _13 => _13.responseHeaders, 'optionalAccess', _14 => _14.length])){n.responses??={};for(const r of t.response.responseHeaders){n.responses[r.status]??={description:"",content:{}},n.responses[r.status];const p=n.responses[r.status];p.headers={schema:await _jsonschematoopenapischema.convert.call(void 0, this.#s(r.schema))}}}t.request.body&&(n.requestBody={required:!0,content:{"application/json":{schema:await _jsonschematoopenapischema.convert.call(void 0, this.#s(t.request.body))}}});const o=[],a=async(r,p)=>{if(!p)return;const u=this.#r(p);for(const h of u)if(h.properties)for(const[m,f]of Object.entries(h.properties))o.push({name:m,in:r,schema:await _jsonschematoopenapischema.convert.call(void 0, this.#s(f)),required:(h.required||[]).includes(m)})};await Promise.all([a("query",t.request.query),a("path",t.request.params),a("header",t.request.headers)]),o.length&&(n.parameters=o);const i=this.#e;i.paths||(i.paths={}),i.paths[e]||(i.paths[e]={}),i.paths[e][s]=n}router(){const e="/openapi.json",s=new (0, _routesmincjs.Router)({path:_nullishCoalesce(this.config.config.openapi.docsPath, () => ("/")),hide:!0});return s.get("/index.html")(t=>t.res({body:this.#o(`.${e}`),contentType:"text/html"})),s.get(e)(t=>t.res({body:this.#e})),s}#r(e){const{allOf:s,oneOf:t,anyOf:n,...o}=e;return s?s.flatMap(a=>this.#r(a)):[o]}#s(e){if(!e||typeof e!="object")return e;if(typeof e.$refId=="string"){const{$refId:s,...t}=e,n=this.#s(t);return _optionalChain([this, 'access', _15 => _15.#e, 'access', _16 => _16.components, 'optionalAccess', _17 => _17.schemas])?(this.#e.components.schemas[s]=n,{$ref:`#/components/schemas/${s}`}):n}return Array.isArray(e)?e.map(s=>this.#s(s)):Object.fromEntries(Object.entries(e).map(([s,t])=>[s,this.#s(t)]))}#i(e){if(!e.length)return;const s=e.map(a=>typeof a=="string"?{name:a}:a),t=s.map(a=>a.name).join(" > "),n=_nullishCoalesce(_optionalChain([s, 'access', _18 => _18.at, 'call', _19 => _19(-1), 'optionalAccess', _20 => _20.name]), () => ("")),o=s.map(a=>_nullishCoalesce(_optionalChain([a, 'access', _21 => _21.description, 'optionalAccess', _22 => _22.trim, 'call', _23 => _23()]), () => (""))).filter(Boolean).join(`
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/openapi.ts"],"names":["config","#baseOpenapiDoc"],"mappings":"AAAA,4wBAAwB,oCAEe,gDA2BtC,MAAA,CAAA,CAAA,WAAoB,CAAA,CAAA,CAAA,CAAA,IAAAA,CACnB,MAAKC,CAAAA,CAAkB,CACtB,IAAA,CAAA,CAAA,CAAA,CAAS,CAAA,OACT,CAAA,OACC,CAAA,IAAO,CAAA,CAAGD,KAAO,CAAI,CAAA,EAAA;AA+CgB;AAYjC;AAyFC;AAAA;AAAA;AAWL;AAUK;AAAA;AAAA;AAIS,WAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUiC,yCAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUnD","file":"/home/runner/work/equipped/equipped/dist/cjs/server/openapi.min.cjs","sourcesContent":["import { convert } from '@openapi-contrib/json-schema-to-openapi-schema'\nimport { OpenAPIV3_1 } from 'openapi-types'\nimport { capitalize, JsonSchema } from 'valleyed'\n\nimport { ServerConfig } from './pipes'\nimport { Router } from './routes'\nimport { Route } from './types'\n\ndeclare module 'openapi-types' {\n\tnamespace OpenAPIV3 {\n\t\tinterface Document {\n\t\t\t'x-tagGroups': { name: string; tags: string[] }[]\n\t\t}\n\t\tinterface TagObject {\n\t\t\t'x-displayName': string\n\t\t}\n\t}\n}\n\nexport type OpenApiSchemaDef = {\n\trequest: Partial<Record<'body' | 'query' | 'params' | 'headers' | 'response', JsonSchema>>\n\tresponse: Partial<Record<'response' | 'responseHeaders', { status: number; schema: JsonSchema; contentType: string }[]>>\n}\n\nexport class OpenApi {\n\t#registeredTags: Record<string, boolean> = {}\n\t#registeredTagGroups: Record<string, { name: string; tags: string[] }> = {}\n\t#baseOpenapiDoc: OpenAPIV3_1.Document\n\n\tconstructor(private config: ServerConfig) {\n\t\tthis.#baseOpenapiDoc = {\n\t\t\topenapi: '3.0.0',\n\t\t\tinfo: {\n\t\t\t\ttitle: `${config.app.name} ${config.app.id}`,\n\t\t\t\tversion: config.config.openapi.docsVersion ?? '',\n\t\t\t},\n\t\t\tservers: config.config.openapi.docsBaseUrl?.map((url) => ({ url })),\n\t\t\tpaths: {},\n\t\t\tcomponents: {\n\t\t\t\tschemas: {},\n\t\t\t\tsecuritySchemes: {\n\t\t\t\t\tAuthorization: {\n\t\t\t\t\t\ttype: 'apiKey',\n\t\t\t\t\t\tname: 'authorization',\n\t\t\t\t\t\tin: 'header',\n\t\t\t\t\t},\n\t\t\t\t\tRefreshToken: {\n\t\t\t\t\t\ttype: 'apiKey',\n\t\t\t\t\t\tname: 'x-refresh-token',\n\t\t\t\t\t\tin: 'header',\n\t\t\t\t\t},\n\t\t\t\t\tApiKey: {\n\t\t\t\t\t\ttype: 'apiKey',\n\t\t\t\t\t\tname: 'x-api-key',\n\t\t\t\t\t\tin: 'header',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\ttags: [],\n\t\t\t'x-tagGroups': [],\n\t\t}\n\t}\n\n\tcleanPath(path: string) {\n\t\tlet cleaned = path.replace(/(\\/\\s*)+/g, '/')\n\t\tif (!cleaned.startsWith('/')) cleaned = `/${cleaned}`\n\t\tif (cleaned !== '/' && cleaned.endsWith('/')) cleaned = cleaned.slice(0, -1)\n\t\treturn cleaned\n\t}\n\n\tasync register(route: Route<any>, def: OpenApiSchemaDef) {\n\t\tif (route.hide) return\n\n\t\tconst tag = this.#buildTag(route.groups ?? [])\n\n\t\tconst cleanPath = this.cleanPath(route.path)\n\t\tconst operationId = `(${route.method.toUpperCase()}) ${cleanPath}`\n\t\tawait this.#addRouteToOpenApiDoc(cleanPath, route.method.toLowerCase(), def, {\n\t\t\toperationId,\n\t\t\tsummary: route.title ?? cleanPath,\n\t\t\tdescription: route.descriptions?.join('\\n\\n'),\n\t\t\ttags: tag ? [tag] : undefined,\n\t\t\tsecurity: route.security,\n\t\t})\n\t}\n\n\tasync #addRouteToOpenApiDoc(path: string, method: string, def: OpenApiSchemaDef, methodObj: OpenAPIV3_1.OperationObject) {\n\t\tif (def.response.response?.length) {\n\t\t\tmethodObj.responses ??= {}\n\t\t\tfor (const resp of def.response.response) {\n\t\t\t\tmethodObj.responses[resp.status] ??= { description: '', content: {} }\n\t\t\t\tconst res = methodObj.responses[resp.status] as OpenAPIV3_1.ResponseObject\n\t\t\t\tres.content![resp.contentType] = { schema: await convert(this.#visit(resp.schema)) }\n\t\t\t}\n\t\t}\n\n\t\tif (def.response.responseHeaders?.length) {\n\t\t\tmethodObj.responses ??= {}\n\t\t\tfor (const resp of def.response.responseHeaders) {\n\t\t\t\tmethodObj.responses[resp.status] ??= { description: '', content: {} }\n\t\t\t\tmethodObj.responses[resp.status] as OpenAPIV3_1.ResponseObject\n\t\t\t\tconst res = methodObj.responses[resp.status] as OpenAPIV3_1.ResponseObject\n\t\t\t\tres.headers = { schema: (await convert(this.#visit(resp.schema))) as any }\n\t\t\t}\n\t\t}\n\n\t\tif (def.request.body)\n\t\t\tmethodObj.requestBody = {\n\t\t\t\trequired: true,\n\t\t\t\tcontent: {\n\t\t\t\t\t'application/json': { schema: await convert(this.#visit(def.request.body)) },\n\t\t\t\t},\n\t\t\t}\n\n\t\tconst parameters: OpenAPIV3_1.ParameterObject[] = []\n\n\t\tconst addParams = async (location: 'query' | 'path' | 'header', schema: JsonSchema | undefined) => {\n\t\t\tif (!schema) return\n\t\t\tconst flat = this.#flattenForParameters(schema)\n\t\t\tfor (const schema of flat) {\n\t\t\t\tif (!schema.properties) continue\n\t\t\t\tfor (const [name, value] of Object.entries(schema.properties))\n\t\t\t\t\tparameters.push({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tin: location,\n\t\t\t\t\t\tschema: await convert(this.#visit(value)),\n\t\t\t\t\t\trequired: (schema.required || []).includes(name),\n\t\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tawait Promise.all([\n\t\t\taddParams('query', def.request.query),\n\t\t\taddParams('path', def.request.params),\n\t\t\taddParams('header', def.request.headers),\n\t\t])\n\t\tif (parameters.length) methodObj.parameters = parameters\n\n\t\tconst base = this.#baseOpenapiDoc\n\t\tif (!base.paths) base.paths = {}\n\t\tif (!base.paths[path]) base.paths[path] = {}\n\t\tbase.paths[path]![method] = methodObj\n\t}\n\n\trouter() {\n\t\tconst jsonPath = '/openapi.json'\n\t\tconst router = new Router({ path: this.config.config.openapi.docsPath ?? '/', hide: true })\n\t\trouter.get('/')((req) => req.res({ body: this.#html(`.${jsonPath}`), contentType: 'text/html' }))\n\t\trouter.get(jsonPath)((req) => req.res({ body: this.#baseOpenapiDoc }))\n\t\treturn router\n\t}\n\n\t#flattenForParameters(node: JsonSchema): JsonSchema[] {\n\t\tconst { allOf, oneOf, anyOf, ...schema } = node\n\t\tif (allOf) return allOf.flatMap((n) => this.#flattenForParameters(n))\n\t\treturn [schema]\n\t}\n\n\t#visit(node: JsonSchema) {\n\t\tif (!node || typeof node !== 'object') return node\n\t\tif (typeof node.$refId === 'string') {\n\t\t\tconst { $refId: id, ...rest } = node\n\t\t\tconst res = this.#visit(rest)\n\t\t\tif (this.#baseOpenapiDoc.components?.schemas) {\n\t\t\t\tthis.#baseOpenapiDoc.components.schemas[id] = res\n\t\t\t\treturn { $ref: `#/components/schemas/${id}` }\n\t\t\t} else return res\n\t\t}\n\n\t\tif (Array.isArray(node)) return node.map((n) => this.#visit(n)) as any\n\t\treturn Object.fromEntries(Object.entries(node).map(([key, value]) => [key, this.#visit(value as any)]))\n\t}\n\n\t#buildTag(groups: NonNullable<Route<any>['groups']>) {\n\t\tif (!groups.length) return undefined\n\t\tconst parsed = groups.map((g) => (typeof g === 'string' ? { name: g } : g))\n\t\tconst name = parsed.map((g) => g.name).join(' > ')\n\t\tconst displayName = parsed.at(-1)?.name ?? ''\n\t\tconst description = parsed\n\t\t\t.map((g) => g.description?.trim() ?? '')\n\t\t\t.filter(Boolean)\n\t\t\t.join('\\n\\n\\n\\n')\n\n\t\tif (!this.#registeredTags[name]) {\n\t\t\tthis.#registeredTags[name] = true\n\t\t\tthis.#baseOpenapiDoc.tags!.push({ name, 'x-displayName': displayName, description })\n\n\t\t\tconst tagGroups = parsed.slice(0, -1)\n\t\t\tconst groupName = tagGroups.map((g) => g.name).join(' > ') || 'default'\n\t\t\tif (!this.#registeredTagGroups[groupName]) {\n\t\t\t\tconst group = { name: groupName, tags: [] }\n\t\t\t\tthis.#baseOpenapiDoc['x-tagGroups'].push(group)\n\t\t\t\tthis.#registeredTagGroups[groupName] = group\n\t\t\t}\n\t\t\tthis.#registeredTagGroups[groupName].tags = [...new Set([...this.#registeredTagGroups[groupName].tags, name])]\n\t\t}\n\n\t\treturn name\n\t}\n\n\t#html(jsonPath: string) {\n\t\tconst title = capitalize(`${this.config.app.name} ${this.config.app.id}`)\n\t\treturn `\n<!doctype html>\n<html>\n <head>\n <title>${title}</title>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n\t<style>\n .darklight-reference {\n display: none;\n }\n </style>\n </head>\n <body>\n <script id=\"api-reference\" data-url=\"${jsonPath}\"></script>\n <script>\n const configuration = { theme: 'purple' };\n document.getElementById('api-reference').dataset.configuration = JSON.stringify(configuration);\n </script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference@1.28.33\"></script>\n </body>\n</html>\n`\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/server/openapi.ts"],"names":["config","#baseOpenapiDoc"],"mappings":"AAAA,4wBAAwB,oCAEe,gDA2BtC,MAAA,CAAA,CAAA,WAAoB,CAAA,CAAA,CAAA,CAAA,IAAAA,CACnB,MAAKC,CAAAA,CAAkB,CACtB,IAAA,CAAA,CAAA,CAAA,CAAS,CAAA,OACT,CAAA,OACC,CAAA,IAAO,CAAA,CAAGD,KAAO,CAAI,CAAA,EAAA;AA+CgB;AAYjC;AAyFC;AAAA;AAAA;AAWL;AAUK;AAAA;AAAA;AAIS,WAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUiC,yCAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUnD","file":"/home/runner/work/equipped/equipped/dist/cjs/server/openapi.min.cjs","sourcesContent":["import { convert } from '@openapi-contrib/json-schema-to-openapi-schema'\nimport { OpenAPIV3_1 } from 'openapi-types'\nimport { capitalize, JsonSchema } from 'valleyed'\n\nimport { ServerConfig } from './pipes'\nimport { Router } from './routes'\nimport { Route } from './types'\n\ndeclare module 'openapi-types' {\n\tnamespace OpenAPIV3 {\n\t\tinterface Document {\n\t\t\t'x-tagGroups': { name: string; tags: string[] }[]\n\t\t}\n\t\tinterface TagObject {\n\t\t\t'x-displayName': string\n\t\t}\n\t}\n}\n\nexport type OpenApiSchemaDef = {\n\trequest: Partial<Record<'body' | 'query' | 'params' | 'headers' | 'response', JsonSchema>>\n\tresponse: Partial<Record<'response' | 'responseHeaders', { status: number; schema: JsonSchema; contentType: string }[]>>\n}\n\nexport class OpenApi {\n\t#registeredTags: Record<string, boolean> = {}\n\t#registeredTagGroups: Record<string, { name: string; tags: string[] }> = {}\n\t#baseOpenapiDoc: OpenAPIV3_1.Document\n\n\tconstructor(private config: ServerConfig) {\n\t\tthis.#baseOpenapiDoc = {\n\t\t\topenapi: '3.0.0',\n\t\t\tinfo: {\n\t\t\t\ttitle: `${config.app.name} ${config.app.id}`,\n\t\t\t\tversion: config.config.openapi.docsVersion ?? '',\n\t\t\t},\n\t\t\tservers: config.config.openapi.docsBaseUrl?.map((url) => ({ url })),\n\t\t\tpaths: {},\n\t\t\tcomponents: {\n\t\t\t\tschemas: {},\n\t\t\t\tsecuritySchemes: {\n\t\t\t\t\tAuthorization: {\n\t\t\t\t\t\ttype: 'apiKey',\n\t\t\t\t\t\tname: 'authorization',\n\t\t\t\t\t\tin: 'header',\n\t\t\t\t\t},\n\t\t\t\t\tRefreshToken: {\n\t\t\t\t\t\ttype: 'apiKey',\n\t\t\t\t\t\tname: 'x-refresh-token',\n\t\t\t\t\t\tin: 'header',\n\t\t\t\t\t},\n\t\t\t\t\tApiKey: {\n\t\t\t\t\t\ttype: 'apiKey',\n\t\t\t\t\t\tname: 'x-api-key',\n\t\t\t\t\t\tin: 'header',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\ttags: [],\n\t\t\t'x-tagGroups': [],\n\t\t}\n\t}\n\n\tcleanPath(path: string) {\n\t\tlet cleaned = path.replace(/(\\/\\s*)+/g, '/')\n\t\tif (!cleaned.startsWith('/')) cleaned = `/${cleaned}`\n\t\tif (cleaned !== '/' && cleaned.endsWith('/')) cleaned = cleaned.slice(0, -1)\n\t\treturn cleaned\n\t}\n\n\tasync register(route: Route<any>, def: OpenApiSchemaDef) {\n\t\tif (route.hide) return\n\n\t\tconst tag = this.#buildTag(route.groups ?? [])\n\n\t\tconst cleanPath = this.cleanPath(route.path)\n\t\tconst operationId = `(${route.method.toUpperCase()}) ${cleanPath}`\n\t\tawait this.#addRouteToOpenApiDoc(cleanPath, route.method.toLowerCase(), def, {\n\t\t\toperationId,\n\t\t\tsummary: route.title ?? cleanPath,\n\t\t\tdescription: route.descriptions?.join('\\n\\n'),\n\t\t\ttags: tag ? [tag] : undefined,\n\t\t\tsecurity: route.security,\n\t\t})\n\t}\n\n\tasync #addRouteToOpenApiDoc(path: string, method: string, def: OpenApiSchemaDef, methodObj: OpenAPIV3_1.OperationObject) {\n\t\tif (def.response.response?.length) {\n\t\t\tmethodObj.responses ??= {}\n\t\t\tfor (const resp of def.response.response) {\n\t\t\t\tmethodObj.responses[resp.status] ??= { description: '', content: {} }\n\t\t\t\tconst res = methodObj.responses[resp.status] as OpenAPIV3_1.ResponseObject\n\t\t\t\tres.content![resp.contentType] = { schema: await convert(this.#visit(resp.schema)) }\n\t\t\t}\n\t\t}\n\n\t\tif (def.response.responseHeaders?.length) {\n\t\t\tmethodObj.responses ??= {}\n\t\t\tfor (const resp of def.response.responseHeaders) {\n\t\t\t\tmethodObj.responses[resp.status] ??= { description: '', content: {} }\n\t\t\t\tmethodObj.responses[resp.status] as OpenAPIV3_1.ResponseObject\n\t\t\t\tconst res = methodObj.responses[resp.status] as OpenAPIV3_1.ResponseObject\n\t\t\t\tres.headers = { schema: (await convert(this.#visit(resp.schema))) as any }\n\t\t\t}\n\t\t}\n\n\t\tif (def.request.body)\n\t\t\tmethodObj.requestBody = {\n\t\t\t\trequired: true,\n\t\t\t\tcontent: {\n\t\t\t\t\t'application/json': { schema: await convert(this.#visit(def.request.body)) },\n\t\t\t\t},\n\t\t\t}\n\n\t\tconst parameters: OpenAPIV3_1.ParameterObject[] = []\n\n\t\tconst addParams = async (location: 'query' | 'path' | 'header', schema: JsonSchema | undefined) => {\n\t\t\tif (!schema) return\n\t\t\tconst flat = this.#flattenForParameters(schema)\n\t\t\tfor (const schema of flat) {\n\t\t\t\tif (!schema.properties) continue\n\t\t\t\tfor (const [name, value] of Object.entries(schema.properties))\n\t\t\t\t\tparameters.push({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tin: location,\n\t\t\t\t\t\tschema: await convert(this.#visit(value)),\n\t\t\t\t\t\trequired: (schema.required || []).includes(name),\n\t\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tawait Promise.all([\n\t\t\taddParams('query', def.request.query),\n\t\t\taddParams('path', def.request.params),\n\t\t\taddParams('header', def.request.headers),\n\t\t])\n\t\tif (parameters.length) methodObj.parameters = parameters\n\n\t\tconst base = this.#baseOpenapiDoc\n\t\tif (!base.paths) base.paths = {}\n\t\tif (!base.paths[path]) base.paths[path] = {}\n\t\tbase.paths[path]![method] = methodObj\n\t}\n\n\trouter() {\n\t\tconst jsonPath = '/openapi.json'\n\t\tconst router = new Router({ path: this.config.config.openapi.docsPath ?? '/', hide: true })\n\t\trouter.get('/index.html')((req) => req.res({ body: this.#html(`.${jsonPath}`), contentType: 'text/html' }))\n\t\trouter.get(jsonPath)((req) => req.res({ body: this.#baseOpenapiDoc }))\n\t\treturn router\n\t}\n\n\t#flattenForParameters(node: JsonSchema): JsonSchema[] {\n\t\tconst { allOf, oneOf, anyOf, ...schema } = node\n\t\tif (allOf) return allOf.flatMap((n) => this.#flattenForParameters(n))\n\t\treturn [schema]\n\t}\n\n\t#visit(node: JsonSchema) {\n\t\tif (!node || typeof node !== 'object') return node\n\t\tif (typeof node.$refId === 'string') {\n\t\t\tconst { $refId: id, ...rest } = node\n\t\t\tconst res = this.#visit(rest)\n\t\t\tif (this.#baseOpenapiDoc.components?.schemas) {\n\t\t\t\tthis.#baseOpenapiDoc.components.schemas[id] = res\n\t\t\t\treturn { $ref: `#/components/schemas/${id}` }\n\t\t\t} else return res\n\t\t}\n\n\t\tif (Array.isArray(node)) return node.map((n) => this.#visit(n)) as any\n\t\treturn Object.fromEntries(Object.entries(node).map(([key, value]) => [key, this.#visit(value as any)]))\n\t}\n\n\t#buildTag(groups: NonNullable<Route<any>['groups']>) {\n\t\tif (!groups.length) return undefined\n\t\tconst parsed = groups.map((g) => (typeof g === 'string' ? { name: g } : g))\n\t\tconst name = parsed.map((g) => g.name).join(' > ')\n\t\tconst displayName = parsed.at(-1)?.name ?? ''\n\t\tconst description = parsed\n\t\t\t.map((g) => g.description?.trim() ?? '')\n\t\t\t.filter(Boolean)\n\t\t\t.join('\\n\\n\\n\\n')\n\n\t\tif (!this.#registeredTags[name]) {\n\t\t\tthis.#registeredTags[name] = true\n\t\t\tthis.#baseOpenapiDoc.tags!.push({ name, 'x-displayName': displayName, description })\n\n\t\t\tconst tagGroups = parsed.slice(0, -1)\n\t\t\tconst groupName = tagGroups.map((g) => g.name).join(' > ') || 'default'\n\t\t\tif (!this.#registeredTagGroups[groupName]) {\n\t\t\t\tconst group = { name: groupName, tags: [] }\n\t\t\t\tthis.#baseOpenapiDoc['x-tagGroups'].push(group)\n\t\t\t\tthis.#registeredTagGroups[groupName] = group\n\t\t\t}\n\t\t\tthis.#registeredTagGroups[groupName].tags = [...new Set([...this.#registeredTagGroups[groupName].tags, name])]\n\t\t}\n\n\t\treturn name\n\t}\n\n\t#html(jsonPath: string) {\n\t\tconst title = capitalize(`${this.config.app.name} ${this.config.app.id}`)\n\t\treturn `\n<!doctype html>\n<html>\n <head>\n <title>${title}</title>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n\t<style>\n .darklight-reference {\n display: none;\n }\n </style>\n </head>\n <body>\n <script id=\"api-reference\" data-url=\"${jsonPath}\"></script>\n <script>\n const configuration = { theme: 'purple' };\n document.getElementById('api-reference').dataset.configuration = JSON.stringify(configuration);\n </script>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference@1.28.33\"></script>\n </body>\n</html>\n`\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/cache/base.ts"],"sourcesContent":["export abstract class Cache {\n\tabstract set(key: string, data: string, ttlInSecs
|
|
1
|
+
{"version":3,"sources":["../../../src/cache/base.ts"],"sourcesContent":["export abstract class Cache {\n\tabstract set(key: string, data: string, ttlInSecs?: number): Promise<void>\n\n\tabstract get(key: string): Promise<string | null>\n\n\tabstract delete(key: string): Promise<void>\n\n\tabstract getOrSet<T>(key: string, fn: () => Promise<T>, ttlInSecs?: number): Promise<T>\n}\n"],"mappings":"AAAO,MAAeA,CAAM,CAQ5B","names":["Cache"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/cache/base.ts"],"sourcesContent":["export abstract class Cache {\n\tabstract set(key: string, data: string, ttlInSecs
|
|
1
|
+
{"version":3,"sources":["../../../src/cache/base.ts"],"sourcesContent":["export abstract class Cache {\n\tabstract set(key: string, data: string, ttlInSecs?: number): Promise<void>\n\n\tabstract get(key: string): Promise<string | null>\n\n\tabstract delete(key: string): Promise<void>\n\n\tabstract getOrSet<T>(key: string, fn: () => Promise<T>, ttlInSecs?: number): Promise<T>\n}\n"],"mappings":"AAAO,MAAe,MAAM;AAQ5B;","names":[]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Instance as s}from "../../instance/index.min.mjs";import{Cache as
|
|
1
|
+
import{Instance as s}from "../../instance/index.min.mjs";import{Cache as i}from "../base.min.mjs";class p extends i{cache=new Map;constructor(){super();let e;s.on("start",async()=>{e=setInterval(()=>{const t=Date.now();for(const[r,n]of this.cache.entries())n.expiredAt&&n.expiredAt<=t&&this.cache.delete(r)},5e3)},1),s.on("close",async()=>clearInterval(e),1)}getScopedKey(e){return s.get().getScopedName(e,":")}async delete(e){this.cache.delete(this.getScopedKey(e))}async get(e){const t=this.cache.get(this.getScopedKey(e));return t&&(t.expiredAt===void 0||t.expiredAt>Date.now())?t.data:null}async set(e,t,r){this.cache.set(this.getScopedKey(e),{data:t,expiredAt:r?Date.now()+r*1e3:void 0})}async getOrSet(e,t,r){const n=await this.get(e);if(n)return JSON.parse(n);const a=await t();return await this.set(e,JSON.stringify(a),r),a}}export{p as InMemoryCache};
|
|
2
2
|
//# sourceMappingURL=in-memory.min.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/cache/types/in-memory.ts"],"sourcesContent":["import { Instance } from '../../instance'\nimport { Cache } from '../base'\n\ntype CacheEntry = {\n\tdata: string\n\texpiredAt
|
|
1
|
+
{"version":3,"sources":["../../../../src/cache/types/in-memory.ts"],"sourcesContent":["import { Instance } from '../../instance'\nimport { Cache } from '../base'\n\ntype CacheEntry = {\n\tdata: string\n\texpiredAt?: number\n}\n\nexport class InMemoryCache extends Cache {\n\tprivate readonly cache = new Map<string, CacheEntry>()\n\n\tconstructor() {\n\t\tsuper()\n\t\tlet interval: ReturnType<typeof setInterval> | undefined\n\t\tInstance.on(\n\t\t\t'start',\n\t\t\tasync () => {\n\t\t\t\tinterval = setInterval(() => {\n\t\t\t\t\tconst now = Date.now()\n\t\t\t\t\tfor (const [key, record] of this.cache.entries()) {\n\t\t\t\t\t\tif (record.expiredAt && record.expiredAt <= now) this.cache.delete(key)\n\t\t\t\t\t}\n\t\t\t\t}, 5000)\n\t\t\t},\n\t\t\t1,\n\t\t)\n\t\tInstance.on('close', async () => clearInterval(interval), 1)\n\t}\n\n\tprivate getScopedKey(key: string): string {\n\t\treturn Instance.get().getScopedName(key, ':')\n\t}\n\n\tasync delete(key: string) {\n\t\tthis.cache.delete(this.getScopedKey(key))\n\t}\n\n\tasync get(key: string) {\n\t\tconst record = this.cache.get(this.getScopedKey(key))\n\t\tif (record && (record.expiredAt === undefined || record.expiredAt > Date.now())) return record.data\n\t\treturn null\n\t}\n\n\tasync set(key: string, data: string, ttlInSecs?: number) {\n\t\tthis.cache.set(this.getScopedKey(key), { data, expiredAt: ttlInSecs ? Date.now() + ttlInSecs * 1000 : undefined })\n\t}\n\n\tasync getOrSet<T>(key: string, fn: () => Promise<T>, ttlInSecs?: number): Promise<T> {\n\t\tconst cached = await this.get(key)\n\t\tif (cached) return JSON.parse(cached) as T\n\n\t\tconst result = await fn()\n\t\tawait this.set(key, JSON.stringify(result), ttlInSecs)\n\t\treturn result\n\t}\n}\n"],"mappings":"AAAA,OAAS,YAAAA,MAAgB,iBACzB,OAAS,SAAAC,MAAa,UAOf,MAAMC,UAAsBD,CAAM,CACvB,MAAQ,IAAI,IAE7B,aAAc,CACb,MAAM,EACN,IAAIE,EACJH,EAAS,GACR,QACA,SAAY,CACXG,EAAW,YAAY,IAAM,CAC5B,MAAMC,EAAM,KAAK,IAAI,EACrB,SAAW,CAACC,EAAKC,CAAM,IAAK,KAAK,MAAM,QAAQ,EAC1CA,EAAO,WAAaA,EAAO,WAAaF,GAAK,KAAK,MAAM,OAAOC,CAAG,CAExE,EAAG,GAAI,CACR,EACA,CACD,EACAL,EAAS,GAAG,QAAS,SAAY,cAAcG,CAAQ,EAAG,CAAC,CAC5D,CAEQ,aAAaE,EAAqB,CACzC,OAAOL,EAAS,IAAI,EAAE,cAAcK,EAAK,GAAG,CAC7C,CAEA,MAAM,OAAOA,EAAa,CACzB,KAAK,MAAM,OAAO,KAAK,aAAaA,CAAG,CAAC,CACzC,CAEA,MAAM,IAAIA,EAAa,CACtB,MAAMC,EAAS,KAAK,MAAM,IAAI,KAAK,aAAaD,CAAG,CAAC,EACpD,OAAIC,IAAWA,EAAO,YAAc,QAAaA,EAAO,UAAY,KAAK,IAAI,GAAWA,EAAO,KACxF,IACR,CAEA,MAAM,IAAID,EAAaE,EAAcC,EAAoB,CACxD,KAAK,MAAM,IAAI,KAAK,aAAaH,CAAG,EAAG,CAAE,KAAAE,EAAM,UAAWC,EAAY,KAAK,IAAI,EAAIA,EAAY,IAAO,MAAU,CAAC,CAClH,CAEA,MAAM,SAAYH,EAAaI,EAAsBD,EAAgC,CACpF,MAAME,EAAS,MAAM,KAAK,IAAIL,CAAG,EACjC,GAAIK,EAAQ,OAAO,KAAK,MAAMA,CAAM,EAEpC,MAAMC,EAAS,MAAMF,EAAG,EACxB,aAAM,KAAK,IAAIJ,EAAK,KAAK,UAAUM,CAAM,EAAGH,CAAS,EAC9CG,CACR,CACD","names":["Instance","Cache","InMemoryCache","interval","now","key","record","data","ttlInSecs","fn","cached","result"]}
|
|
@@ -11,7 +11,7 @@ class InMemoryCache extends Cache {
|
|
|
11
11
|
interval = setInterval(() => {
|
|
12
12
|
const now = Date.now();
|
|
13
13
|
for (const [key, record] of this.cache.entries()) {
|
|
14
|
-
if (record.expiredAt <= now) this.cache.delete(key);
|
|
14
|
+
if (record.expiredAt && record.expiredAt <= now) this.cache.delete(key);
|
|
15
15
|
}
|
|
16
16
|
}, 5e3);
|
|
17
17
|
},
|
|
@@ -27,11 +27,11 @@ class InMemoryCache extends Cache {
|
|
|
27
27
|
}
|
|
28
28
|
async get(key) {
|
|
29
29
|
const record = this.cache.get(this.getScopedKey(key));
|
|
30
|
-
if (record && record.expiredAt > Date.now()) return record.data;
|
|
30
|
+
if (record && (record.expiredAt === void 0 || record.expiredAt > Date.now())) return record.data;
|
|
31
31
|
return null;
|
|
32
32
|
}
|
|
33
33
|
async set(key, data, ttlInSecs) {
|
|
34
|
-
this.cache.set(this.getScopedKey(key), { data, expiredAt: Date.now() + ttlInSecs * 1e3 });
|
|
34
|
+
this.cache.set(this.getScopedKey(key), { data, expiredAt: ttlInSecs ? Date.now() + ttlInSecs * 1e3 : void 0 });
|
|
35
35
|
}
|
|
36
36
|
async getOrSet(key, fn, ttlInSecs) {
|
|
37
37
|
const cached = await this.get(key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/cache/types/in-memory.ts"],"sourcesContent":["import { Instance } from '../../instance'\nimport { Cache } from '../base'\n\ntype CacheEntry = {\n\tdata: string\n\texpiredAt
|
|
1
|
+
{"version":3,"sources":["../../../../src/cache/types/in-memory.ts"],"sourcesContent":["import { Instance } from '../../instance'\nimport { Cache } from '../base'\n\ntype CacheEntry = {\n\tdata: string\n\texpiredAt?: number\n}\n\nexport class InMemoryCache extends Cache {\n\tprivate readonly cache = new Map<string, CacheEntry>()\n\n\tconstructor() {\n\t\tsuper()\n\t\tlet interval: ReturnType<typeof setInterval> | undefined\n\t\tInstance.on(\n\t\t\t'start',\n\t\t\tasync () => {\n\t\t\t\tinterval = setInterval(() => {\n\t\t\t\t\tconst now = Date.now()\n\t\t\t\t\tfor (const [key, record] of this.cache.entries()) {\n\t\t\t\t\t\tif (record.expiredAt && record.expiredAt <= now) this.cache.delete(key)\n\t\t\t\t\t}\n\t\t\t\t}, 5000)\n\t\t\t},\n\t\t\t1,\n\t\t)\n\t\tInstance.on('close', async () => clearInterval(interval), 1)\n\t}\n\n\tprivate getScopedKey(key: string): string {\n\t\treturn Instance.get().getScopedName(key, ':')\n\t}\n\n\tasync delete(key: string) {\n\t\tthis.cache.delete(this.getScopedKey(key))\n\t}\n\n\tasync get(key: string) {\n\t\tconst record = this.cache.get(this.getScopedKey(key))\n\t\tif (record && (record.expiredAt === undefined || record.expiredAt > Date.now())) return record.data\n\t\treturn null\n\t}\n\n\tasync set(key: string, data: string, ttlInSecs?: number) {\n\t\tthis.cache.set(this.getScopedKey(key), { data, expiredAt: ttlInSecs ? Date.now() + ttlInSecs * 1000 : undefined })\n\t}\n\n\tasync getOrSet<T>(key: string, fn: () => Promise<T>, ttlInSecs?: number): Promise<T> {\n\t\tconst cached = await this.get(key)\n\t\tif (cached) return JSON.parse(cached) as T\n\n\t\tconst result = await fn()\n\t\tawait this.set(key, JSON.stringify(result), ttlInSecs)\n\t\treturn result\n\t}\n}\n"],"mappings":"AAAA,SAAS,gBAAgB;AACzB,SAAS,aAAa;AAOf,MAAM,sBAAsB,MAAM;AAAA,EACvB,QAAQ,oBAAI,IAAwB;AAAA,EAErD,cAAc;AACb,UAAM;AACN,QAAI;AACJ,aAAS;AAAA,MACR;AAAA,MACA,YAAY;AACX,mBAAW,YAAY,MAAM;AAC5B,gBAAM,MAAM,KAAK,IAAI;AACrB,qBAAW,CAAC,KAAK,MAAM,KAAK,KAAK,MAAM,QAAQ,GAAG;AACjD,gBAAI,OAAO,aAAa,OAAO,aAAa,IAAK,MAAK,MAAM,OAAO,GAAG;AAAA,UACvE;AAAA,QACD,GAAG,GAAI;AAAA,MACR;AAAA,MACA;AAAA,IACD;AACA,aAAS,GAAG,SAAS,YAAY,cAAc,QAAQ,GAAG,CAAC;AAAA,EAC5D;AAAA,EAEQ,aAAa,KAAqB;AACzC,WAAO,SAAS,IAAI,EAAE,cAAc,KAAK,GAAG;AAAA,EAC7C;AAAA,EAEA,MAAM,OAAO,KAAa;AACzB,SAAK,MAAM,OAAO,KAAK,aAAa,GAAG,CAAC;AAAA,EACzC;AAAA,EAEA,MAAM,IAAI,KAAa;AACtB,UAAM,SAAS,KAAK,MAAM,IAAI,KAAK,aAAa,GAAG,CAAC;AACpD,QAAI,WAAW,OAAO,cAAc,UAAa,OAAO,YAAY,KAAK,IAAI,GAAI,QAAO,OAAO;AAC/F,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,IAAI,KAAa,MAAc,WAAoB;AACxD,SAAK,MAAM,IAAI,KAAK,aAAa,GAAG,GAAG,EAAE,MAAM,WAAW,YAAY,KAAK,IAAI,IAAI,YAAY,MAAO,OAAU,CAAC;AAAA,EAClH;AAAA,EAEA,MAAM,SAAY,KAAa,IAAsB,WAAgC;AACpF,UAAM,SAAS,MAAM,KAAK,IAAI,GAAG;AACjC,QAAI,OAAQ,QAAO,KAAK,MAAM,MAAM;AAEpC,UAAM,SAAS,MAAM,GAAG;AACxB,UAAM,KAAK,IAAI,KAAK,KAAK,UAAU,MAAM,GAAG,SAAS;AACrD,WAAO;AAAA,EACR;AACD;","names":[]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Cluster as n,Redis as c}from"ioredis";import{EquippedError as a}from "../../errors/index.min.mjs";import{Instance as i}from "../../instance/index.min.mjs";import{Cache as p}from "../base.min.mjs";class f extends p{client;constructor(e,t){super();const s={...e.host?{host:e.host}:{},...e.port?{port:e.port}:{}},r={...t,...e.password?{password:e.password}:{},...e.username?{username:e.username}:{},...e.tls?{tls:{}}:{},lazyConnect:!0};this.client=e.cluster?new n([s],{...t,redisOptions:r,lazyConnect:!0}):new c({...r,...s}),this.client.on("error",async o=>{i.crash(new a("Redis failed with error",{},o))}),t||i.on("start",async()=>this.client.connect(),1),i.on("close",async()=>this.client.quit(),1)}getScopedKey(e){return i.get().getScopedName(e,":")}async delete(e){await this.client.del(this.getScopedKey(e))}async get(e){return await this.client.get(this.getScopedKey(e))}async set(e,t,s){s
|
|
1
|
+
import{Cluster as n,Redis as c}from"ioredis";import{EquippedError as a}from "../../errors/index.min.mjs";import{Instance as i}from "../../instance/index.min.mjs";import{Cache as p}from "../base.min.mjs";class f extends p{client;constructor(e,t){super();const s={...e.host?{host:e.host}:{},...e.port?{port:e.port}:{}},r={...t,...e.password?{password:e.password}:{},...e.username?{username:e.username}:{},...e.tls?{tls:{}}:{},lazyConnect:!0};this.client=e.cluster?new n([s],{...t,redisOptions:r,lazyConnect:!0}):new c({...r,...s}),this.client.on("error",async o=>{i.crash(new a("Redis failed with error",{},o))}),t||i.on("start",async()=>this.client.connect(),1),i.on("close",async()=>this.client.quit(),1)}getScopedKey(e){return i.get().getScopedName(e,":")}async delete(e){await this.client.del(this.getScopedKey(e))}async get(e){return await this.client.get(this.getScopedKey(e))}async set(e,t,s){s?await this.client.setex(this.getScopedKey(e),s,t):this.client.set(this.getScopedKey(e),t)}async getOrSet(e,t,s){const r=await this.get(this.getScopedKey(e));if(r)return JSON.parse(r);const o=await t();await this.set(this.getScopedKey(e),JSON.stringify(o),s)}}export{f as RedisCache};
|
|
2
2
|
//# sourceMappingURL=redis.min.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/cache/types/redis.ts"],"sourcesContent":["import { Cluster, Redis, RedisOptions } from 'ioredis'\n\nimport { EquippedError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { Cache } from '../base'\nimport { RedisConfig } from '../pipes'\n\nexport class RedisCache extends Cache {\n\tclient: Redis | Cluster\n\n\tconstructor(settings: RedisConfig, extraConfig?: Partial<RedisOptions>) {\n\t\tsuper()\n\t\tconst node = {\n\t\t\t...(settings.host ? { host: settings.host } : {}),\n\t\t\t...(settings.port ? { port: settings.port } : {}),\n\t\t}\n\t\tconst common = {\n\t\t\t...extraConfig,\n\t\t\t...(settings.password ? { password: settings.password } : {}),\n\t\t\t...(settings.username ? { username: settings.username } : {}),\n\t\t\t...(settings.tls ? { tls: {} } : {}),\n\t\t\tlazyConnect: true,\n\t\t}\n\t\tthis.client = settings.cluster\n\t\t\t? new Cluster([node], {\n\t\t\t\t\t...extraConfig,\n\t\t\t\t\tredisOptions: common,\n\t\t\t\t\tlazyConnect: true,\n\t\t\t\t})\n\t\t\t: new Redis({ ...common, ...node })\n\t\tthis.client.on('error', async (error) => {\n\t\t\tInstance.crash(new EquippedError(`Redis failed with error`, {}, error))\n\t\t})\n\t\tif (!extraConfig) Instance.on('start', async () => this.client.connect(), 1)\n\t\tInstance.on('close', async () => this.client.quit(), 1)\n\t}\n\n\tprivate getScopedKey(key: string): string {\n\t\treturn Instance.get().getScopedName(key, ':')\n\t}\n\n\tasync delete(key: string) {\n\t\tawait this.client.del(this.getScopedKey(key))\n\t}\n\n\tasync get(key: string) {\n\t\treturn await this.client.get(this.getScopedKey(key))\n\t}\n\n\tasync set(key: string, data: string, ttlInSecs
|
|
1
|
+
{"version":3,"sources":["../../../../src/cache/types/redis.ts"],"sourcesContent":["import { Cluster, Redis, RedisOptions } from 'ioredis'\n\nimport { EquippedError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { Cache } from '../base'\nimport { RedisConfig } from '../pipes'\n\nexport class RedisCache extends Cache {\n\tclient: Redis | Cluster\n\n\tconstructor(settings: RedisConfig, extraConfig?: Partial<RedisOptions>) {\n\t\tsuper()\n\t\tconst node = {\n\t\t\t...(settings.host ? { host: settings.host } : {}),\n\t\t\t...(settings.port ? { port: settings.port } : {}),\n\t\t}\n\t\tconst common = {\n\t\t\t...extraConfig,\n\t\t\t...(settings.password ? { password: settings.password } : {}),\n\t\t\t...(settings.username ? { username: settings.username } : {}),\n\t\t\t...(settings.tls ? { tls: {} } : {}),\n\t\t\tlazyConnect: true,\n\t\t}\n\t\tthis.client = settings.cluster\n\t\t\t? new Cluster([node], {\n\t\t\t\t\t...extraConfig,\n\t\t\t\t\tredisOptions: common,\n\t\t\t\t\tlazyConnect: true,\n\t\t\t\t})\n\t\t\t: new Redis({ ...common, ...node })\n\t\tthis.client.on('error', async (error) => {\n\t\t\tInstance.crash(new EquippedError(`Redis failed with error`, {}, error))\n\t\t})\n\t\tif (!extraConfig) Instance.on('start', async () => this.client.connect(), 1)\n\t\tInstance.on('close', async () => this.client.quit(), 1)\n\t}\n\n\tprivate getScopedKey(key: string): string {\n\t\treturn Instance.get().getScopedName(key, ':')\n\t}\n\n\tasync delete(key: string) {\n\t\tawait this.client.del(this.getScopedKey(key))\n\t}\n\n\tasync get(key: string) {\n\t\treturn await this.client.get(this.getScopedKey(key))\n\t}\n\n\tasync set(key: string, data: string, ttlInSecs?: number) {\n\t\tif (ttlInSecs) await this.client.setex(this.getScopedKey(key), ttlInSecs, data)\n\t\telse this.client.set(this.getScopedKey(key), data)\n\t}\n\n\tasync getOrSet<T>(key: string, fn: () => Promise<T>, ttlInSecs?: number) {\n\t\tconst cached = await this.get(this.getScopedKey(key))\n\t\tif (cached) return JSON.parse(cached)\n\n\t\tconst result = await fn()\n\t\tawait this.set(this.getScopedKey(key), JSON.stringify(result), ttlInSecs)\n\t}\n}\n"],"mappings":"AAAA,OAAS,WAAAA,EAAS,SAAAC,MAA2B,UAE7C,OAAS,iBAAAC,MAAqB,eAC9B,OAAS,YAAAC,MAAgB,iBACzB,OAAS,SAAAC,MAAa,UAGf,MAAMC,UAAmBD,CAAM,CACrC,OAEA,YAAYE,EAAuBC,EAAqC,CACvE,MAAM,EACN,MAAMC,EAAO,CACZ,GAAIF,EAAS,KAAO,CAAE,KAAMA,EAAS,IAAK,EAAI,CAAC,EAC/C,GAAIA,EAAS,KAAO,CAAE,KAAMA,EAAS,IAAK,EAAI,CAAC,CAChD,EACMG,EAAS,CACd,GAAGF,EACH,GAAID,EAAS,SAAW,CAAE,SAAUA,EAAS,QAAS,EAAI,CAAC,EAC3D,GAAIA,EAAS,SAAW,CAAE,SAAUA,EAAS,QAAS,EAAI,CAAC,EAC3D,GAAIA,EAAS,IAAM,CAAE,IAAK,CAAC,CAAE,EAAI,CAAC,EAClC,YAAa,EACd,EACA,KAAK,OAASA,EAAS,QACpB,IAAIN,EAAQ,CAACQ,CAAI,EAAG,CACpB,GAAGD,EACH,aAAcE,EACd,YAAa,EACd,CAAC,EACA,IAAIR,EAAM,CAAE,GAAGQ,EAAQ,GAAGD,CAAK,CAAC,EACnC,KAAK,OAAO,GAAG,QAAS,MAAOE,GAAU,CACxCP,EAAS,MAAM,IAAID,EAAc,0BAA2B,CAAC,EAAGQ,CAAK,CAAC,CACvE,CAAC,EACIH,GAAaJ,EAAS,GAAG,QAAS,SAAY,KAAK,OAAO,QAAQ,EAAG,CAAC,EAC3EA,EAAS,GAAG,QAAS,SAAY,KAAK,OAAO,KAAK,EAAG,CAAC,CACvD,CAEQ,aAAaQ,EAAqB,CACzC,OAAOR,EAAS,IAAI,EAAE,cAAcQ,EAAK,GAAG,CAC7C,CAEA,MAAM,OAAOA,EAAa,CACzB,MAAM,KAAK,OAAO,IAAI,KAAK,aAAaA,CAAG,CAAC,CAC7C,CAEA,MAAM,IAAIA,EAAa,CACtB,OAAO,MAAM,KAAK,OAAO,IAAI,KAAK,aAAaA,CAAG,CAAC,CACpD,CAEA,MAAM,IAAIA,EAAaC,EAAcC,EAAoB,CACpDA,EAAW,MAAM,KAAK,OAAO,MAAM,KAAK,aAAaF,CAAG,EAAGE,EAAWD,CAAI,EACzE,KAAK,OAAO,IAAI,KAAK,aAAaD,CAAG,EAAGC,CAAI,CAClD,CAEA,MAAM,SAAYD,EAAaG,EAAsBD,EAAoB,CACxE,MAAME,EAAS,MAAM,KAAK,IAAI,KAAK,aAAaJ,CAAG,CAAC,EACpD,GAAII,EAAQ,OAAO,KAAK,MAAMA,CAAM,EAEpC,MAAMC,EAAS,MAAMF,EAAG,EACxB,MAAM,KAAK,IAAI,KAAK,aAAaH,CAAG,EAAG,KAAK,UAAUK,CAAM,EAAGH,CAAS,CACzE,CACD","names":["Cluster","Redis","EquippedError","Instance","Cache","RedisCache","settings","extraConfig","node","common","error","key","data","ttlInSecs","fn","cached","result"]}
|
|
@@ -38,7 +38,7 @@ class RedisCache extends Cache {
|
|
|
38
38
|
return await this.client.get(this.getScopedKey(key));
|
|
39
39
|
}
|
|
40
40
|
async set(key, data, ttlInSecs) {
|
|
41
|
-
if (ttlInSecs
|
|
41
|
+
if (ttlInSecs) await this.client.setex(this.getScopedKey(key), ttlInSecs, data);
|
|
42
42
|
else this.client.set(this.getScopedKey(key), data);
|
|
43
43
|
}
|
|
44
44
|
async getOrSet(key, fn, ttlInSecs) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/cache/types/redis.ts"],"sourcesContent":["import { Cluster, Redis, RedisOptions } from 'ioredis'\n\nimport { EquippedError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { Cache } from '../base'\nimport { RedisConfig } from '../pipes'\n\nexport class RedisCache extends Cache {\n\tclient: Redis | Cluster\n\n\tconstructor(settings: RedisConfig, extraConfig?: Partial<RedisOptions>) {\n\t\tsuper()\n\t\tconst node = {\n\t\t\t...(settings.host ? { host: settings.host } : {}),\n\t\t\t...(settings.port ? { port: settings.port } : {}),\n\t\t}\n\t\tconst common = {\n\t\t\t...extraConfig,\n\t\t\t...(settings.password ? { password: settings.password } : {}),\n\t\t\t...(settings.username ? { username: settings.username } : {}),\n\t\t\t...(settings.tls ? { tls: {} } : {}),\n\t\t\tlazyConnect: true,\n\t\t}\n\t\tthis.client = settings.cluster\n\t\t\t? new Cluster([node], {\n\t\t\t\t\t...extraConfig,\n\t\t\t\t\tredisOptions: common,\n\t\t\t\t\tlazyConnect: true,\n\t\t\t\t})\n\t\t\t: new Redis({ ...common, ...node })\n\t\tthis.client.on('error', async (error) => {\n\t\t\tInstance.crash(new EquippedError(`Redis failed with error`, {}, error))\n\t\t})\n\t\tif (!extraConfig) Instance.on('start', async () => this.client.connect(), 1)\n\t\tInstance.on('close', async () => this.client.quit(), 1)\n\t}\n\n\tprivate getScopedKey(key: string): string {\n\t\treturn Instance.get().getScopedName(key, ':')\n\t}\n\n\tasync delete(key: string) {\n\t\tawait this.client.del(this.getScopedKey(key))\n\t}\n\n\tasync get(key: string) {\n\t\treturn await this.client.get(this.getScopedKey(key))\n\t}\n\n\tasync set(key: string, data: string, ttlInSecs
|
|
1
|
+
{"version":3,"sources":["../../../../src/cache/types/redis.ts"],"sourcesContent":["import { Cluster, Redis, RedisOptions } from 'ioredis'\n\nimport { EquippedError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { Cache } from '../base'\nimport { RedisConfig } from '../pipes'\n\nexport class RedisCache extends Cache {\n\tclient: Redis | Cluster\n\n\tconstructor(settings: RedisConfig, extraConfig?: Partial<RedisOptions>) {\n\t\tsuper()\n\t\tconst node = {\n\t\t\t...(settings.host ? { host: settings.host } : {}),\n\t\t\t...(settings.port ? { port: settings.port } : {}),\n\t\t}\n\t\tconst common = {\n\t\t\t...extraConfig,\n\t\t\t...(settings.password ? { password: settings.password } : {}),\n\t\t\t...(settings.username ? { username: settings.username } : {}),\n\t\t\t...(settings.tls ? { tls: {} } : {}),\n\t\t\tlazyConnect: true,\n\t\t}\n\t\tthis.client = settings.cluster\n\t\t\t? new Cluster([node], {\n\t\t\t\t\t...extraConfig,\n\t\t\t\t\tredisOptions: common,\n\t\t\t\t\tlazyConnect: true,\n\t\t\t\t})\n\t\t\t: new Redis({ ...common, ...node })\n\t\tthis.client.on('error', async (error) => {\n\t\t\tInstance.crash(new EquippedError(`Redis failed with error`, {}, error))\n\t\t})\n\t\tif (!extraConfig) Instance.on('start', async () => this.client.connect(), 1)\n\t\tInstance.on('close', async () => this.client.quit(), 1)\n\t}\n\n\tprivate getScopedKey(key: string): string {\n\t\treturn Instance.get().getScopedName(key, ':')\n\t}\n\n\tasync delete(key: string) {\n\t\tawait this.client.del(this.getScopedKey(key))\n\t}\n\n\tasync get(key: string) {\n\t\treturn await this.client.get(this.getScopedKey(key))\n\t}\n\n\tasync set(key: string, data: string, ttlInSecs?: number) {\n\t\tif (ttlInSecs) await this.client.setex(this.getScopedKey(key), ttlInSecs, data)\n\t\telse this.client.set(this.getScopedKey(key), data)\n\t}\n\n\tasync getOrSet<T>(key: string, fn: () => Promise<T>, ttlInSecs?: number) {\n\t\tconst cached = await this.get(this.getScopedKey(key))\n\t\tif (cached) return JSON.parse(cached)\n\n\t\tconst result = await fn()\n\t\tawait this.set(this.getScopedKey(key), JSON.stringify(result), ttlInSecs)\n\t}\n}\n"],"mappings":"AAAA,SAAS,SAAS,aAA2B;AAE7C,SAAS,qBAAqB;AAC9B,SAAS,gBAAgB;AACzB,SAAS,aAAa;AAGf,MAAM,mBAAmB,MAAM;AAAA,EACrC;AAAA,EAEA,YAAY,UAAuB,aAAqC;AACvE,UAAM;AACN,UAAM,OAAO;AAAA,MACZ,GAAI,SAAS,OAAO,EAAE,MAAM,SAAS,KAAK,IAAI,CAAC;AAAA,MAC/C,GAAI,SAAS,OAAO,EAAE,MAAM,SAAS,KAAK,IAAI,CAAC;AAAA,IAChD;AACA,UAAM,SAAS;AAAA,MACd,GAAG;AAAA,MACH,GAAI,SAAS,WAAW,EAAE,UAAU,SAAS,SAAS,IAAI,CAAC;AAAA,MAC3D,GAAI,SAAS,WAAW,EAAE,UAAU,SAAS,SAAS,IAAI,CAAC;AAAA,MAC3D,GAAI,SAAS,MAAM,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC;AAAA,MAClC,aAAa;AAAA,IACd;AACA,SAAK,SAAS,SAAS,UACpB,IAAI,QAAQ,CAAC,IAAI,GAAG;AAAA,MACpB,GAAG;AAAA,MACH,cAAc;AAAA,MACd,aAAa;AAAA,IACd,CAAC,IACA,IAAI,MAAM,EAAE,GAAG,QAAQ,GAAG,KAAK,CAAC;AACnC,SAAK,OAAO,GAAG,SAAS,OAAO,UAAU;AACxC,eAAS,MAAM,IAAI,cAAc,2BAA2B,CAAC,GAAG,KAAK,CAAC;AAAA,IACvE,CAAC;AACD,QAAI,CAAC,YAAa,UAAS,GAAG,SAAS,YAAY,KAAK,OAAO,QAAQ,GAAG,CAAC;AAC3E,aAAS,GAAG,SAAS,YAAY,KAAK,OAAO,KAAK,GAAG,CAAC;AAAA,EACvD;AAAA,EAEQ,aAAa,KAAqB;AACzC,WAAO,SAAS,IAAI,EAAE,cAAc,KAAK,GAAG;AAAA,EAC7C;AAAA,EAEA,MAAM,OAAO,KAAa;AACzB,UAAM,KAAK,OAAO,IAAI,KAAK,aAAa,GAAG,CAAC;AAAA,EAC7C;AAAA,EAEA,MAAM,IAAI,KAAa;AACtB,WAAO,MAAM,KAAK,OAAO,IAAI,KAAK,aAAa,GAAG,CAAC;AAAA,EACpD;AAAA,EAEA,MAAM,IAAI,KAAa,MAAc,WAAoB;AACxD,QAAI,UAAW,OAAM,KAAK,OAAO,MAAM,KAAK,aAAa,GAAG,GAAG,WAAW,IAAI;AAAA,QACzE,MAAK,OAAO,IAAI,KAAK,aAAa,GAAG,GAAG,IAAI;AAAA,EAClD;AAAA,EAEA,MAAM,SAAY,KAAa,IAAsB,WAAoB;AACxE,UAAM,SAAS,MAAM,KAAK,IAAI,KAAK,aAAa,GAAG,CAAC;AACpD,QAAI,OAAQ,QAAO,KAAK,MAAM,MAAM;AAEpC,UAAM,SAAS,MAAM,GAAG;AACxB,UAAM,KAAK,IAAI,KAAK,aAAa,GAAG,GAAG,KAAK,UAAU,MAAM,GAAG,SAAS;AAAA,EACzE;AACD;","names":[]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ObjectId as m}from"mongodb";import{parseMongodbQueryParams as f}from "./query.min.mjs";import{EquippedError as p}from "../../errors/index.min.mjs";const c="_id";function W(y,d){async function u(t){const n=(Array.isArray(t)?t:[t]).map(r=>y.mapper(r));return Array.isArray(t)?n:n[0]}function l(t,e,n,r){const s={[c]:e,...y.options?.skipAudit?{}:{createdAt:n.getTime(),...r?{}:{updatedAt:n.getTime()}}};return{...t,...s}}function o(t,e){return{...t,$set:{...t.$set,...Object.keys(t).length>0&&!y.options?.skipAudit?{updatedAt:e.getTime()}:{}}}}const i={config:y,extras:{collection:d},query:async t=>{const e=await f(d,t);return{...e,results:await u(e.results)}},findMany:async(t,e={})=>{const r=(Array.isArray(e.sort)?e.sort:e.sort?[e.sort]:[]).map(a=>[a.field,a.desc?"desc":"asc"]),s=await d.find(t,{session:e.session,limit:e.limit,sort:r}).toArray();return u(s)},findOne:async(t,e={})=>(await i.findMany(t,{...e,limit:1})).at(0)??null,findById:async(t,e={})=>await i.findOne({[c]:t},e),insertMany:async(t,e={})=>{const n=e.getTime?.()??new Date,r=t.map((a,w)=>l(a,e.makeId?.(w)??new m().toString(),n));return await d.insertMany(r,{session:e.session}),(await Promise.all(r.map(async a=>await i.findById(a[c],e)))).filter(a=>!!a)},insertOne:async(t,e={})=>(await i.insertMany([t],e))[0],updateMany:async(t,e,n={})=>{const r=n.getTime?.()??new Date;return await d.updateMany(t,o(e,r),{session:n.session}),i.findMany(t,n)},updateOne:async(t,e,n={})=>{const r=n.getTime?.()??new Date,s=await d.findOneAndUpdate(t,o(e,r),{returnDocument:"after",session:n.session});return s?u(s):null},updateById:async(t,e,n={})=>await i.updateOne({[c]:t},e,n),upsertOne:async(t,e,n={})=>{const r=n.getTime?.()??new Date,s=await d.findOneAndUpdate(t,{...o("update"in e?e.update:{},r),$setOnInsert:l(e.insert,n.makeId?.()??new m().toString(),r,!0)},{returnDocument:"after",session:n.session,upsert:!0});return u(s)},deleteMany:async(t,e={})=>{const n=await i.findMany(t,e);return await d.deleteMany(t,{session:e.session}),n},deleteOne:async(t,e)=>{const n=await d.findOneAndDelete(t,{session:e?.session});return n?u(n):null},deleteById:async(t,e)=>await i.deleteOne({[c]:t},e),bulkWrite:async(t,e={})=>{const n=d.initializeUnorderedBulkOp({session:e.session}),r=e.getTime?.()??new Date;t.forEach((s,a)=>{switch(s.op){case"insert":n.insert(l(s.value,s.makeId?.(a)??new m().toString(),r));break;case"delete":n.find(s.filter).delete();break;case"update":n.find(s.filter).update(o(s.value,r));break;case"upsert":n.find(s.filter).upsert().update({...o("update"in s?s.update:{},r),$setOnInsert:l(s.insert,s.makeId?.(a)??new m().toString(),r,!0)});break;default:throw new p("Unknown bulkWrite operation",{operation:s})}}),await n.execute({session:e.session})}};return i}export{W as getTable};
|
|
1
|
+
import{ObjectId as m}from"mongodb";import{parseMongodbQueryParams as f}from "./query.min.mjs";import{EquippedError as p}from "../../errors/index.min.mjs";const c="_id";function W(y,d){async function u(t){const n=(Array.isArray(t)?t:[t]).map(r=>y.mapper(r));return Array.isArray(t)?n:n[0]}function l(t,e,n,r){const s={[c]:e,...y.options?.skipAudit?{}:{createdAt:n.getTime(),...r?{}:{updatedAt:n.getTime()}}};return{...t,...s}}function o(t,e,n=!1){return{...t,$set:{...t.$set,...n||Object.keys(t).length>0&&!y.options?.skipAudit?{updatedAt:e.getTime()}:{}}}}const i={config:y,extras:{collection:d},query:async t=>{const e=await f(d,t);return{...e,results:await u(e.results)}},findMany:async(t,e={})=>{const r=(Array.isArray(e.sort)?e.sort:e.sort?[e.sort]:[]).map(a=>[a.field,a.desc?"desc":"asc"]),s=await d.find(t,{session:e.session,limit:e.limit,sort:r}).toArray();return u(s)},findOne:async(t,e={})=>(await i.findMany(t,{...e,limit:1})).at(0)??null,findById:async(t,e={})=>await i.findOne({[c]:t},e),insertMany:async(t,e={})=>{const n=e.getTime?.()??new Date,r=t.map((a,w)=>l(a,e.makeId?.(w)??new m().toString(),n));return await d.insertMany(r,{session:e.session}),(await Promise.all(r.map(async a=>await i.findById(a[c],e)))).filter(a=>!!a)},insertOne:async(t,e={})=>(await i.insertMany([t],e))[0],updateMany:async(t,e,n={})=>{const r=n.getTime?.()??new Date;return await d.updateMany(t,o(e,r),{session:n.session}),i.findMany(t,n)},updateOne:async(t,e,n={})=>{const r=n.getTime?.()??new Date,s=await d.findOneAndUpdate(t,o(e,r),{returnDocument:"after",session:n.session});return s?u(s):null},updateById:async(t,e,n={})=>await i.updateOne({[c]:t},e,n),upsertOne:async(t,e,n={})=>{const r=n.getTime?.()??new Date,s=await d.findOneAndUpdate(t,{...o("update"in e?e.update:{},r,!0),$setOnInsert:l(e.insert,n.makeId?.()??new m().toString(),r,!0)},{returnDocument:"after",session:n.session,upsert:!0});return u(s)},deleteMany:async(t,e={})=>{const n=await i.findMany(t,e);return await d.deleteMany(t,{session:e.session}),n},deleteOne:async(t,e)=>{const n=await d.findOneAndDelete(t,{session:e?.session});return n?u(n):null},deleteById:async(t,e)=>await i.deleteOne({[c]:t},e),bulkWrite:async(t,e={})=>{const n=d.initializeUnorderedBulkOp({session:e.session}),r=e.getTime?.()??new Date;t.forEach((s,a)=>{switch(s.op){case"insert":n.insert(l(s.value,s.makeId?.(a)??new m().toString(),r));break;case"delete":n.find(s.filter).delete();break;case"update":n.find(s.filter).update(o(s.value,r));break;case"upsert":n.find(s.filter).upsert().update({...o("update"in s?s.update:{},r,!0),$setOnInsert:l(s.insert,s.makeId?.(a)??new m().toString(),r,!0)});break;default:throw new p("Unknown bulkWrite operation",{operation:s})}}),await n.execute({session:e.session})}};return i}export{W as getTable};
|
|
2
2
|
//# sourceMappingURL=api.min.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/dbs/mongo/api.ts"],"sourcesContent":["import { Collection, ObjectId, OptionalUnlessRequiredId, SortDirection, WithId } from 'mongodb'\n\nimport { QueryParams } from '../pipes'\nimport { parseMongodbQueryParams } from './query'\nimport { EquippedError } from '../../errors'\nimport * as core from '../base/core'\n\nconst idKey = '_id'\ntype IdType = { _id: string }\n\nexport function getTable<Model extends core.Model<IdType>, Entity extends core.Entity>(\n\tconfig: core.Config<Model, Entity>,\n\tcollection: Collection<Model>,\n) {\n\ttype WI = Model | WithId<Model>\n\tasync function transform(doc: WI): Promise<Entity>\n\t// eslint-disable-next-line no-redeclare\n\tasync function transform(doc: WI[]): Promise<Entity[]>\n\t// eslint-disable-next-line no-redeclare\n\tasync function transform(doc: WI | WI[]) {\n\t\tconst docs = Array.isArray(doc) ? doc : [doc]\n\t\tconst mapped = docs.map((d) => config.mapper(d as Model))\n\t\treturn Array.isArray(doc) ? mapped : mapped[0]\n\t}\n\n\tfunction prepInsertValue(value: core.CreateInput<Model>, id: string, now: Date, skipUpdate?: boolean) {\n\t\tconst base: core.Model<IdType> = {\n\t\t\t[idKey]: id,\n\t\t\t...(config.options?.skipAudit\n\t\t\t\t? {}\n\t\t\t\t: {\n\t\t\t\t\t\tcreatedAt: now.getTime(),\n\t\t\t\t\t\t...(skipUpdate ? {} : { updatedAt: now.getTime() }),\n\t\t\t\t\t}),\n\t\t}\n\t\treturn {\n\t\t\t...value,\n\t\t\t...base,\n\t\t} as unknown as OptionalUnlessRequiredId<Model>\n\t}\n\n\tfunction prepUpdateValue(value: core.UpdateInput<Model>, now: Date) {\n\t\treturn {\n\t\t\t...value,\n\t\t\t$set: {\n\t\t\t\t...value.$set,\n\t\t\t\t...(Object.keys(value).length > 0 && !config.options?.skipAudit\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tupdatedAt: now.getTime(),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t}\n\t}\n\n\tconst table: core.Table<IdType, Model, Entity, { collection: Collection<Model> }> = {\n\t\tconfig,\n\t\textras: { collection },\n\n\t\tquery: async (params: QueryParams) => {\n\t\t\tconst results = await parseMongodbQueryParams(collection, params)\n\t\t\treturn {\n\t\t\t\t...results,\n\t\t\t\tresults: (await transform(results.results as any)) as any,\n\t\t\t}\n\t\t},\n\n\t\tfindMany: async (filter, options = {}) => {\n\t\t\tconst sortArray = Array.isArray(options.sort) ? options.sort : options.sort ? [options.sort] : []\n\t\t\tconst sort = sortArray.map((p) => [p.field, p.desc ? 'desc' : 'asc'] as [string, SortDirection])\n\t\t\tconst docs = await collection\n\t\t\t\t.find(filter, {\n\t\t\t\t\tsession: options.session,\n\t\t\t\t\tlimit: options.limit,\n\t\t\t\t\tsort,\n\t\t\t\t})\n\t\t\t\t.toArray()\n\t\t\treturn transform(docs)\n\t\t},\n\n\t\tfindOne: async (filter, options = {}) => {\n\t\t\tconst result = await table.findMany(filter, { ...options, limit: 1 })\n\t\t\treturn result.at(0) ?? null\n\t\t},\n\n\t\tfindById: async (id, options = {}) => {\n\t\t\tconst result = await table.findOne({ [idKey]: id } as core.Filter<Model>, options)\n\t\t\treturn result\n\t\t},\n\n\t\tinsertMany: async (values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\tconst payload = values.map((value, i) => prepInsertValue(value, options.makeId?.(i) ?? new ObjectId().toString(), now))\n\t\t\tawait collection.insertMany(payload, { session: options.session })\n\n\t\t\tconst insertedData = await Promise.all(payload.map(async (data) => await table.findById(data[idKey] as any, options)))\n\t\t\treturn insertedData.filter((value) => !!value)\n\t\t},\n\n\t\tinsertOne: async (values, options = {}) => {\n\t\t\tconst result = await table.insertMany([values], options)\n\t\t\treturn result[0]\n\t\t},\n\n\t\tupdateMany: async (filter, values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\tawait collection.updateMany(filter, prepUpdateValue(values, now), { session: options.session })\n\t\t\treturn table.findMany(filter, options)\n\t\t},\n\n\t\tupdateOne: async (filter, values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\tconst doc = await collection.findOneAndUpdate(filter, prepUpdateValue(values, now), {\n\t\t\t\treturnDocument: 'after',\n\t\t\t\tsession: options.session,\n\t\t\t})\n\t\t\treturn doc ? transform(doc) : null\n\t\t},\n\n\t\tupdateById: async (id, values, options = {}) => {\n\t\t\tconst result = await table.updateOne({ [idKey]: id } as core.Filter<Model>, values, options)\n\t\t\treturn result\n\t\t},\n\n\t\tupsertOne: async (filter, values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\n\t\t\tconst doc = await collection.findOneAndUpdate(\n\t\t\t\tfilter,\n\t\t\t\t{\n\t\t\t\t\t...prepUpdateValue('update' in values ? values.update : {}, now),\n\t\t\t\t\t// @ts-expect-error fighting ts\n\t\t\t\t\t$setOnInsert: prepInsertValue(values.insert, options.makeId?.() ?? new ObjectId().toString(), now, true),\n\t\t\t\t},\n\t\t\t\t{ returnDocument: 'after', session: options.session, upsert: true },\n\t\t\t)\n\n\t\t\treturn transform(doc)\n\t\t},\n\n\t\tdeleteMany: async (filter, options = {}) => {\n\t\t\tconst docs = await table.findMany(filter, options)\n\t\t\tawait collection.deleteMany(filter, { session: options.session })\n\t\t\treturn docs\n\t\t},\n\n\t\tdeleteOne: async (filter, options) => {\n\t\t\tconst doc = await collection.findOneAndDelete(filter, { session: options?.session })\n\t\t\treturn doc ? transform(doc) : null\n\t\t},\n\n\t\tdeleteById: async (id, options) => {\n\t\t\tconst result = await table.deleteOne({ [idKey]: id } as core.Filter<Model>, options)\n\t\t\treturn result\n\t\t},\n\n\t\tbulkWrite: async (operations, options = {}) => {\n\t\t\tconst bulk = collection.initializeUnorderedBulkOp({ session: options.session })\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\toperations.forEach((operation, i) => {\n\t\t\t\tswitch (operation.op) {\n\t\t\t\t\tcase 'insert':\n\t\t\t\t\t\tbulk.insert(prepInsertValue(operation.value, operation.makeId?.(i) ?? new ObjectId().toString(), now))\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'delete':\n\t\t\t\t\t\tbulk.find(operation.filter).delete()\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'update':\n\t\t\t\t\t\tbulk.find(operation.filter).update(prepUpdateValue(operation.value, now))\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'upsert':\n\t\t\t\t\t\tbulk.find(operation.filter)\n\t\t\t\t\t\t\t.upsert()\n\t\t\t\t\t\t\t.update({\n\t\t\t\t\t\t\t\t...prepUpdateValue('update' in operation ? operation.update : {}, now),\n\t\t\t\t\t\t\t\t$setOnInsert: prepInsertValue(\n\t\t\t\t\t\t\t\t\toperation.insert as any,\n\t\t\t\t\t\t\t\t\toperation.makeId?.(i) ?? new ObjectId().toString(),\n\t\t\t\t\t\t\t\t\tnow,\n\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\tbreak\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new EquippedError(`Unknown bulkWrite operation`, { operation })\n\t\t\t\t}\n\t\t\t})\n\t\t\tawait bulk.execute({ session: options.session })\n\t\t},\n\t}\n\n\treturn table\n}\n"],"mappings":"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","names":["ObjectId","parseMongodbQueryParams","EquippedError","idKey","getTable","config","collection","transform","doc","mapped","d","prepInsertValue","value","id","now","skipUpdate","base","prepUpdateValue","table","params","results","filter","options","sort","p","docs","values","payload","i","data","operations","bulk","operation"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/dbs/mongo/api.ts"],"sourcesContent":["import { Collection, ObjectId, OptionalUnlessRequiredId, SortDirection, WithId } from 'mongodb'\n\nimport { QueryParams } from '../pipes'\nimport { parseMongodbQueryParams } from './query'\nimport { EquippedError } from '../../errors'\nimport * as core from '../base/core'\n\nconst idKey = '_id'\ntype IdType = { _id: string }\n\nexport function getTable<Model extends core.Model<IdType>, Entity extends core.Entity>(\n\tconfig: core.Config<Model, Entity>,\n\tcollection: Collection<Model>,\n) {\n\ttype WI = Model | WithId<Model>\n\tasync function transform(doc: WI): Promise<Entity>\n\t// eslint-disable-next-line no-redeclare\n\tasync function transform(doc: WI[]): Promise<Entity[]>\n\t// eslint-disable-next-line no-redeclare\n\tasync function transform(doc: WI | WI[]) {\n\t\tconst docs = Array.isArray(doc) ? doc : [doc]\n\t\tconst mapped = docs.map((d) => config.mapper(d as Model))\n\t\treturn Array.isArray(doc) ? mapped : mapped[0]\n\t}\n\n\tfunction prepInsertValue(value: core.CreateInput<Model>, id: string, now: Date, skipUpdate?: boolean) {\n\t\tconst base: core.Model<IdType> = {\n\t\t\t[idKey]: id,\n\t\t\t...(config.options?.skipAudit\n\t\t\t\t? {}\n\t\t\t\t: {\n\t\t\t\t\t\tcreatedAt: now.getTime(),\n\t\t\t\t\t\t...(skipUpdate ? {} : { updatedAt: now.getTime() }),\n\t\t\t\t\t}),\n\t\t}\n\t\treturn {\n\t\t\t...value,\n\t\t\t...base,\n\t\t} as unknown as OptionalUnlessRequiredId<Model>\n\t}\n\n\tfunction prepUpdateValue(value: core.UpdateInput<Model>, now: Date, upsert = false) {\n\t\treturn {\n\t\t\t...value,\n\t\t\t$set: {\n\t\t\t\t...value.$set,\n\t\t\t\t...(upsert || (Object.keys(value).length > 0 && !config.options?.skipAudit) ? { updatedAt: now.getTime() } : {}),\n\t\t\t},\n\t\t}\n\t}\n\n\tconst table: core.Table<IdType, Model, Entity, { collection: Collection<Model> }> = {\n\t\tconfig,\n\t\textras: { collection },\n\n\t\tquery: async (params: QueryParams) => {\n\t\t\tconst results = await parseMongodbQueryParams(collection, params)\n\t\t\treturn {\n\t\t\t\t...results,\n\t\t\t\tresults: (await transform(results.results as any)) as any,\n\t\t\t}\n\t\t},\n\n\t\tfindMany: async (filter, options = {}) => {\n\t\t\tconst sortArray = Array.isArray(options.sort) ? options.sort : options.sort ? [options.sort] : []\n\t\t\tconst sort = sortArray.map((p) => [p.field, p.desc ? 'desc' : 'asc'] as [string, SortDirection])\n\t\t\tconst docs = await collection\n\t\t\t\t.find(filter, {\n\t\t\t\t\tsession: options.session,\n\t\t\t\t\tlimit: options.limit,\n\t\t\t\t\tsort,\n\t\t\t\t})\n\t\t\t\t.toArray()\n\t\t\treturn transform(docs)\n\t\t},\n\n\t\tfindOne: async (filter, options = {}) => {\n\t\t\tconst result = await table.findMany(filter, { ...options, limit: 1 })\n\t\t\treturn result.at(0) ?? null\n\t\t},\n\n\t\tfindById: async (id, options = {}) => {\n\t\t\tconst result = await table.findOne({ [idKey]: id } as core.Filter<Model>, options)\n\t\t\treturn result\n\t\t},\n\n\t\tinsertMany: async (values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\tconst payload = values.map((value, i) => prepInsertValue(value, options.makeId?.(i) ?? new ObjectId().toString(), now))\n\t\t\tawait collection.insertMany(payload, { session: options.session })\n\n\t\t\tconst insertedData = await Promise.all(payload.map(async (data) => await table.findById(data[idKey] as any, options)))\n\t\t\treturn insertedData.filter((value) => !!value)\n\t\t},\n\n\t\tinsertOne: async (values, options = {}) => {\n\t\t\tconst result = await table.insertMany([values], options)\n\t\t\treturn result[0]\n\t\t},\n\n\t\tupdateMany: async (filter, values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\tawait collection.updateMany(filter, prepUpdateValue(values, now), { session: options.session })\n\t\t\treturn table.findMany(filter, options)\n\t\t},\n\n\t\tupdateOne: async (filter, values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\tconst doc = await collection.findOneAndUpdate(filter, prepUpdateValue(values, now), {\n\t\t\t\treturnDocument: 'after',\n\t\t\t\tsession: options.session,\n\t\t\t})\n\t\t\treturn doc ? transform(doc) : null\n\t\t},\n\n\t\tupdateById: async (id, values, options = {}) => {\n\t\t\tconst result = await table.updateOne({ [idKey]: id } as core.Filter<Model>, values, options)\n\t\t\treturn result\n\t\t},\n\n\t\tupsertOne: async (filter, values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\n\t\t\tconst doc = await collection.findOneAndUpdate(\n\t\t\t\tfilter,\n\t\t\t\t{\n\t\t\t\t\t...prepUpdateValue('update' in values ? values.update : {}, now, true),\n\t\t\t\t\t// @ts-expect-error fighting ts\n\t\t\t\t\t$setOnInsert: prepInsertValue(values.insert, options.makeId?.() ?? new ObjectId().toString(), now, true),\n\t\t\t\t},\n\t\t\t\t{ returnDocument: 'after', session: options.session, upsert: true },\n\t\t\t)\n\n\t\t\treturn transform(doc)\n\t\t},\n\n\t\tdeleteMany: async (filter, options = {}) => {\n\t\t\tconst docs = await table.findMany(filter, options)\n\t\t\tawait collection.deleteMany(filter, { session: options.session })\n\t\t\treturn docs\n\t\t},\n\n\t\tdeleteOne: async (filter, options) => {\n\t\t\tconst doc = await collection.findOneAndDelete(filter, { session: options?.session })\n\t\t\treturn doc ? transform(doc) : null\n\t\t},\n\n\t\tdeleteById: async (id, options) => {\n\t\t\tconst result = await table.deleteOne({ [idKey]: id } as core.Filter<Model>, options)\n\t\t\treturn result\n\t\t},\n\n\t\tbulkWrite: async (operations, options = {}) => {\n\t\t\tconst bulk = collection.initializeUnorderedBulkOp({ session: options.session })\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\toperations.forEach((operation, i) => {\n\t\t\t\tswitch (operation.op) {\n\t\t\t\t\tcase 'insert':\n\t\t\t\t\t\tbulk.insert(prepInsertValue(operation.value, operation.makeId?.(i) ?? new ObjectId().toString(), now))\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'delete':\n\t\t\t\t\t\tbulk.find(operation.filter).delete()\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'update':\n\t\t\t\t\t\tbulk.find(operation.filter).update(prepUpdateValue(operation.value, now))\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'upsert':\n\t\t\t\t\t\tbulk.find(operation.filter)\n\t\t\t\t\t\t\t.upsert()\n\t\t\t\t\t\t\t.update({\n\t\t\t\t\t\t\t\t...prepUpdateValue('update' in operation ? operation.update : {}, now, true),\n\t\t\t\t\t\t\t\t$setOnInsert: prepInsertValue(\n\t\t\t\t\t\t\t\t\toperation.insert as any,\n\t\t\t\t\t\t\t\t\toperation.makeId?.(i) ?? new ObjectId().toString(),\n\t\t\t\t\t\t\t\t\tnow,\n\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\tbreak\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new EquippedError(`Unknown bulkWrite operation`, { operation })\n\t\t\t\t}\n\t\t\t})\n\t\t\tawait bulk.execute({ session: options.session })\n\t\t},\n\t}\n\n\treturn table\n}\n"],"mappings":"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","names":["ObjectId","parseMongodbQueryParams","EquippedError","idKey","getTable","config","collection","transform","doc","mapped","d","prepInsertValue","value","id","now","skipUpdate","base","prepUpdateValue","upsert","table","params","results","filter","options","sort","p","docs","values","payload","i","data","operations","bulk","operation"]}
|
|
@@ -21,14 +21,12 @@ function getTable(config, collection) {
|
|
|
21
21
|
...base
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
-
function prepUpdateValue(value, now) {
|
|
24
|
+
function prepUpdateValue(value, now, upsert = false) {
|
|
25
25
|
return {
|
|
26
26
|
...value,
|
|
27
27
|
$set: {
|
|
28
28
|
...value.$set,
|
|
29
|
-
...Object.keys(value).length > 0 && !config.options?.skipAudit ? {
|
|
30
|
-
updatedAt: now.getTime()
|
|
31
|
-
} : {}
|
|
29
|
+
...upsert || Object.keys(value).length > 0 && !config.options?.skipAudit ? { updatedAt: now.getTime() } : {}
|
|
32
30
|
}
|
|
33
31
|
};
|
|
34
32
|
}
|
|
@@ -93,7 +91,7 @@ function getTable(config, collection) {
|
|
|
93
91
|
const doc = await collection.findOneAndUpdate(
|
|
94
92
|
filter,
|
|
95
93
|
{
|
|
96
|
-
...prepUpdateValue("update" in values ? values.update : {}, now),
|
|
94
|
+
...prepUpdateValue("update" in values ? values.update : {}, now, true),
|
|
97
95
|
// @ts-expect-error fighting ts
|
|
98
96
|
$setOnInsert: prepInsertValue(values.insert, options.makeId?.() ?? new ObjectId().toString(), now, true)
|
|
99
97
|
},
|
|
@@ -130,7 +128,7 @@ function getTable(config, collection) {
|
|
|
130
128
|
break;
|
|
131
129
|
case "upsert":
|
|
132
130
|
bulk.find(operation.filter).upsert().update({
|
|
133
|
-
...prepUpdateValue("update" in operation ? operation.update : {}, now),
|
|
131
|
+
...prepUpdateValue("update" in operation ? operation.update : {}, now, true),
|
|
134
132
|
$setOnInsert: prepInsertValue(
|
|
135
133
|
operation.insert,
|
|
136
134
|
operation.makeId?.(i) ?? new ObjectId().toString(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/dbs/mongo/api.ts"],"sourcesContent":["import { Collection, ObjectId, OptionalUnlessRequiredId, SortDirection, WithId } from 'mongodb'\n\nimport { QueryParams } from '../pipes'\nimport { parseMongodbQueryParams } from './query'\nimport { EquippedError } from '../../errors'\nimport * as core from '../base/core'\n\nconst idKey = '_id'\ntype IdType = { _id: string }\n\nexport function getTable<Model extends core.Model<IdType>, Entity extends core.Entity>(\n\tconfig: core.Config<Model, Entity>,\n\tcollection: Collection<Model>,\n) {\n\ttype WI = Model | WithId<Model>\n\tasync function transform(doc: WI): Promise<Entity>\n\t// eslint-disable-next-line no-redeclare\n\tasync function transform(doc: WI[]): Promise<Entity[]>\n\t// eslint-disable-next-line no-redeclare\n\tasync function transform(doc: WI | WI[]) {\n\t\tconst docs = Array.isArray(doc) ? doc : [doc]\n\t\tconst mapped = docs.map((d) => config.mapper(d as Model))\n\t\treturn Array.isArray(doc) ? mapped : mapped[0]\n\t}\n\n\tfunction prepInsertValue(value: core.CreateInput<Model>, id: string, now: Date, skipUpdate?: boolean) {\n\t\tconst base: core.Model<IdType> = {\n\t\t\t[idKey]: id,\n\t\t\t...(config.options?.skipAudit\n\t\t\t\t? {}\n\t\t\t\t: {\n\t\t\t\t\t\tcreatedAt: now.getTime(),\n\t\t\t\t\t\t...(skipUpdate ? {} : { updatedAt: now.getTime() }),\n\t\t\t\t\t}),\n\t\t}\n\t\treturn {\n\t\t\t...value,\n\t\t\t...base,\n\t\t} as unknown as OptionalUnlessRequiredId<Model>\n\t}\n\n\tfunction prepUpdateValue(value: core.UpdateInput<Model>, now: Date) {\n\t\treturn {\n\t\t\t...value,\n\t\t\t$set: {\n\t\t\t\t...value.$set,\n\t\t\t\t...(Object.keys(value).length > 0 && !config.options?.skipAudit\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tupdatedAt: now.getTime(),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t}\n\t}\n\n\tconst table: core.Table<IdType, Model, Entity, { collection: Collection<Model> }> = {\n\t\tconfig,\n\t\textras: { collection },\n\n\t\tquery: async (params: QueryParams) => {\n\t\t\tconst results = await parseMongodbQueryParams(collection, params)\n\t\t\treturn {\n\t\t\t\t...results,\n\t\t\t\tresults: (await transform(results.results as any)) as any,\n\t\t\t}\n\t\t},\n\n\t\tfindMany: async (filter, options = {}) => {\n\t\t\tconst sortArray = Array.isArray(options.sort) ? options.sort : options.sort ? [options.sort] : []\n\t\t\tconst sort = sortArray.map((p) => [p.field, p.desc ? 'desc' : 'asc'] as [string, SortDirection])\n\t\t\tconst docs = await collection\n\t\t\t\t.find(filter, {\n\t\t\t\t\tsession: options.session,\n\t\t\t\t\tlimit: options.limit,\n\t\t\t\t\tsort,\n\t\t\t\t})\n\t\t\t\t.toArray()\n\t\t\treturn transform(docs)\n\t\t},\n\n\t\tfindOne: async (filter, options = {}) => {\n\t\t\tconst result = await table.findMany(filter, { ...options, limit: 1 })\n\t\t\treturn result.at(0) ?? null\n\t\t},\n\n\t\tfindById: async (id, options = {}) => {\n\t\t\tconst result = await table.findOne({ [idKey]: id } as core.Filter<Model>, options)\n\t\t\treturn result\n\t\t},\n\n\t\tinsertMany: async (values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\tconst payload = values.map((value, i) => prepInsertValue(value, options.makeId?.(i) ?? new ObjectId().toString(), now))\n\t\t\tawait collection.insertMany(payload, { session: options.session })\n\n\t\t\tconst insertedData = await Promise.all(payload.map(async (data) => await table.findById(data[idKey] as any, options)))\n\t\t\treturn insertedData.filter((value) => !!value)\n\t\t},\n\n\t\tinsertOne: async (values, options = {}) => {\n\t\t\tconst result = await table.insertMany([values], options)\n\t\t\treturn result[0]\n\t\t},\n\n\t\tupdateMany: async (filter, values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\tawait collection.updateMany(filter, prepUpdateValue(values, now), { session: options.session })\n\t\t\treturn table.findMany(filter, options)\n\t\t},\n\n\t\tupdateOne: async (filter, values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\tconst doc = await collection.findOneAndUpdate(filter, prepUpdateValue(values, now), {\n\t\t\t\treturnDocument: 'after',\n\t\t\t\tsession: options.session,\n\t\t\t})\n\t\t\treturn doc ? transform(doc) : null\n\t\t},\n\n\t\tupdateById: async (id, values, options = {}) => {\n\t\t\tconst result = await table.updateOne({ [idKey]: id } as core.Filter<Model>, values, options)\n\t\t\treturn result\n\t\t},\n\n\t\tupsertOne: async (filter, values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\n\t\t\tconst doc = await collection.findOneAndUpdate(\n\t\t\t\tfilter,\n\t\t\t\t{\n\t\t\t\t\t...prepUpdateValue('update' in values ? values.update : {}, now),\n\t\t\t\t\t// @ts-expect-error fighting ts\n\t\t\t\t\t$setOnInsert: prepInsertValue(values.insert, options.makeId?.() ?? new ObjectId().toString(), now, true),\n\t\t\t\t},\n\t\t\t\t{ returnDocument: 'after', session: options.session, upsert: true },\n\t\t\t)\n\n\t\t\treturn transform(doc)\n\t\t},\n\n\t\tdeleteMany: async (filter, options = {}) => {\n\t\t\tconst docs = await table.findMany(filter, options)\n\t\t\tawait collection.deleteMany(filter, { session: options.session })\n\t\t\treturn docs\n\t\t},\n\n\t\tdeleteOne: async (filter, options) => {\n\t\t\tconst doc = await collection.findOneAndDelete(filter, { session: options?.session })\n\t\t\treturn doc ? transform(doc) : null\n\t\t},\n\n\t\tdeleteById: async (id, options) => {\n\t\t\tconst result = await table.deleteOne({ [idKey]: id } as core.Filter<Model>, options)\n\t\t\treturn result\n\t\t},\n\n\t\tbulkWrite: async (operations, options = {}) => {\n\t\t\tconst bulk = collection.initializeUnorderedBulkOp({ session: options.session })\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\toperations.forEach((operation, i) => {\n\t\t\t\tswitch (operation.op) {\n\t\t\t\t\tcase 'insert':\n\t\t\t\t\t\tbulk.insert(prepInsertValue(operation.value, operation.makeId?.(i) ?? new ObjectId().toString(), now))\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'delete':\n\t\t\t\t\t\tbulk.find(operation.filter).delete()\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'update':\n\t\t\t\t\t\tbulk.find(operation.filter).update(prepUpdateValue(operation.value, now))\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'upsert':\n\t\t\t\t\t\tbulk.find(operation.filter)\n\t\t\t\t\t\t\t.upsert()\n\t\t\t\t\t\t\t.update({\n\t\t\t\t\t\t\t\t...prepUpdateValue('update' in operation ? operation.update : {}, now),\n\t\t\t\t\t\t\t\t$setOnInsert: prepInsertValue(\n\t\t\t\t\t\t\t\t\toperation.insert as any,\n\t\t\t\t\t\t\t\t\toperation.makeId?.(i) ?? new ObjectId().toString(),\n\t\t\t\t\t\t\t\t\tnow,\n\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\tbreak\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new EquippedError(`Unknown bulkWrite operation`, { operation })\n\t\t\t\t}\n\t\t\t})\n\t\t\tawait bulk.execute({ session: options.session })\n\t\t},\n\t}\n\n\treturn table\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/dbs/mongo/api.ts"],"sourcesContent":["import { Collection, ObjectId, OptionalUnlessRequiredId, SortDirection, WithId } from 'mongodb'\n\nimport { QueryParams } from '../pipes'\nimport { parseMongodbQueryParams } from './query'\nimport { EquippedError } from '../../errors'\nimport * as core from '../base/core'\n\nconst idKey = '_id'\ntype IdType = { _id: string }\n\nexport function getTable<Model extends core.Model<IdType>, Entity extends core.Entity>(\n\tconfig: core.Config<Model, Entity>,\n\tcollection: Collection<Model>,\n) {\n\ttype WI = Model | WithId<Model>\n\tasync function transform(doc: WI): Promise<Entity>\n\t// eslint-disable-next-line no-redeclare\n\tasync function transform(doc: WI[]): Promise<Entity[]>\n\t// eslint-disable-next-line no-redeclare\n\tasync function transform(doc: WI | WI[]) {\n\t\tconst docs = Array.isArray(doc) ? doc : [doc]\n\t\tconst mapped = docs.map((d) => config.mapper(d as Model))\n\t\treturn Array.isArray(doc) ? mapped : mapped[0]\n\t}\n\n\tfunction prepInsertValue(value: core.CreateInput<Model>, id: string, now: Date, skipUpdate?: boolean) {\n\t\tconst base: core.Model<IdType> = {\n\t\t\t[idKey]: id,\n\t\t\t...(config.options?.skipAudit\n\t\t\t\t? {}\n\t\t\t\t: {\n\t\t\t\t\t\tcreatedAt: now.getTime(),\n\t\t\t\t\t\t...(skipUpdate ? {} : { updatedAt: now.getTime() }),\n\t\t\t\t\t}),\n\t\t}\n\t\treturn {\n\t\t\t...value,\n\t\t\t...base,\n\t\t} as unknown as OptionalUnlessRequiredId<Model>\n\t}\n\n\tfunction prepUpdateValue(value: core.UpdateInput<Model>, now: Date, upsert = false) {\n\t\treturn {\n\t\t\t...value,\n\t\t\t$set: {\n\t\t\t\t...value.$set,\n\t\t\t\t...(upsert || (Object.keys(value).length > 0 && !config.options?.skipAudit) ? { updatedAt: now.getTime() } : {}),\n\t\t\t},\n\t\t}\n\t}\n\n\tconst table: core.Table<IdType, Model, Entity, { collection: Collection<Model> }> = {\n\t\tconfig,\n\t\textras: { collection },\n\n\t\tquery: async (params: QueryParams) => {\n\t\t\tconst results = await parseMongodbQueryParams(collection, params)\n\t\t\treturn {\n\t\t\t\t...results,\n\t\t\t\tresults: (await transform(results.results as any)) as any,\n\t\t\t}\n\t\t},\n\n\t\tfindMany: async (filter, options = {}) => {\n\t\t\tconst sortArray = Array.isArray(options.sort) ? options.sort : options.sort ? [options.sort] : []\n\t\t\tconst sort = sortArray.map((p) => [p.field, p.desc ? 'desc' : 'asc'] as [string, SortDirection])\n\t\t\tconst docs = await collection\n\t\t\t\t.find(filter, {\n\t\t\t\t\tsession: options.session,\n\t\t\t\t\tlimit: options.limit,\n\t\t\t\t\tsort,\n\t\t\t\t})\n\t\t\t\t.toArray()\n\t\t\treturn transform(docs)\n\t\t},\n\n\t\tfindOne: async (filter, options = {}) => {\n\t\t\tconst result = await table.findMany(filter, { ...options, limit: 1 })\n\t\t\treturn result.at(0) ?? null\n\t\t},\n\n\t\tfindById: async (id, options = {}) => {\n\t\t\tconst result = await table.findOne({ [idKey]: id } as core.Filter<Model>, options)\n\t\t\treturn result\n\t\t},\n\n\t\tinsertMany: async (values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\tconst payload = values.map((value, i) => prepInsertValue(value, options.makeId?.(i) ?? new ObjectId().toString(), now))\n\t\t\tawait collection.insertMany(payload, { session: options.session })\n\n\t\t\tconst insertedData = await Promise.all(payload.map(async (data) => await table.findById(data[idKey] as any, options)))\n\t\t\treturn insertedData.filter((value) => !!value)\n\t\t},\n\n\t\tinsertOne: async (values, options = {}) => {\n\t\t\tconst result = await table.insertMany([values], options)\n\t\t\treturn result[0]\n\t\t},\n\n\t\tupdateMany: async (filter, values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\tawait collection.updateMany(filter, prepUpdateValue(values, now), { session: options.session })\n\t\t\treturn table.findMany(filter, options)\n\t\t},\n\n\t\tupdateOne: async (filter, values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\tconst doc = await collection.findOneAndUpdate(filter, prepUpdateValue(values, now), {\n\t\t\t\treturnDocument: 'after',\n\t\t\t\tsession: options.session,\n\t\t\t})\n\t\t\treturn doc ? transform(doc) : null\n\t\t},\n\n\t\tupdateById: async (id, values, options = {}) => {\n\t\t\tconst result = await table.updateOne({ [idKey]: id } as core.Filter<Model>, values, options)\n\t\t\treturn result\n\t\t},\n\n\t\tupsertOne: async (filter, values, options = {}) => {\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\n\t\t\tconst doc = await collection.findOneAndUpdate(\n\t\t\t\tfilter,\n\t\t\t\t{\n\t\t\t\t\t...prepUpdateValue('update' in values ? values.update : {}, now, true),\n\t\t\t\t\t// @ts-expect-error fighting ts\n\t\t\t\t\t$setOnInsert: prepInsertValue(values.insert, options.makeId?.() ?? new ObjectId().toString(), now, true),\n\t\t\t\t},\n\t\t\t\t{ returnDocument: 'after', session: options.session, upsert: true },\n\t\t\t)\n\n\t\t\treturn transform(doc)\n\t\t},\n\n\t\tdeleteMany: async (filter, options = {}) => {\n\t\t\tconst docs = await table.findMany(filter, options)\n\t\t\tawait collection.deleteMany(filter, { session: options.session })\n\t\t\treturn docs\n\t\t},\n\n\t\tdeleteOne: async (filter, options) => {\n\t\t\tconst doc = await collection.findOneAndDelete(filter, { session: options?.session })\n\t\t\treturn doc ? transform(doc) : null\n\t\t},\n\n\t\tdeleteById: async (id, options) => {\n\t\t\tconst result = await table.deleteOne({ [idKey]: id } as core.Filter<Model>, options)\n\t\t\treturn result\n\t\t},\n\n\t\tbulkWrite: async (operations, options = {}) => {\n\t\t\tconst bulk = collection.initializeUnorderedBulkOp({ session: options.session })\n\t\t\tconst now = options.getTime?.() ?? new Date()\n\t\t\toperations.forEach((operation, i) => {\n\t\t\t\tswitch (operation.op) {\n\t\t\t\t\tcase 'insert':\n\t\t\t\t\t\tbulk.insert(prepInsertValue(operation.value, operation.makeId?.(i) ?? new ObjectId().toString(), now))\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'delete':\n\t\t\t\t\t\tbulk.find(operation.filter).delete()\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'update':\n\t\t\t\t\t\tbulk.find(operation.filter).update(prepUpdateValue(operation.value, now))\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'upsert':\n\t\t\t\t\t\tbulk.find(operation.filter)\n\t\t\t\t\t\t\t.upsert()\n\t\t\t\t\t\t\t.update({\n\t\t\t\t\t\t\t\t...prepUpdateValue('update' in operation ? operation.update : {}, now, true),\n\t\t\t\t\t\t\t\t$setOnInsert: prepInsertValue(\n\t\t\t\t\t\t\t\t\toperation.insert as any,\n\t\t\t\t\t\t\t\t\toperation.makeId?.(i) ?? new ObjectId().toString(),\n\t\t\t\t\t\t\t\t\tnow,\n\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\tbreak\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new EquippedError(`Unknown bulkWrite operation`, { operation })\n\t\t\t\t}\n\t\t\t})\n\t\t\tawait bulk.execute({ session: options.session })\n\t\t},\n\t}\n\n\treturn table\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{MongoClient as g,ObjectId as b}from"mongodb";import{getTable as h}from "./api.min.mjs";import{MongoDbChange as p}from "./changes.min.mjs";import{EquippedError as f}from "../../errors/index.min.mjs";import{Instance as
|
|
1
|
+
import{MongoClient as g,ObjectId as b}from"mongodb";import{getTable as h}from "./api.min.mjs";import{MongoDbChange as p}from "./changes.min.mjs";import{EquippedError as f}from "../../errors/index.min.mjs";import{Instance as l}from "../../instance/index.min.mjs";import{Db as C}from "../base/_instance.min.mjs";class q extends C{constructor(e,n){super(n);this.mongoConfig=e;this.client=new g(e.uri),l.on("start",async()=>{await this.client.connect();const a=this.#e.reduce((t,o)=>(t[o.db]||(t[o.db]=[]),t[o.db].push(o.col),t),{}),i={changeStreamPreAndPostImages:{enabled:!0}};await Promise.all(Object.entries(a).map(async([t,o])=>{const s=this.client.db(t),d=await s.listCollections().toArray();return o.map(async r=>{const c=d.find(m=>m.name===r);c?c.options?.changeStreamPreAndPostImages?.enabled!==i.changeStreamPreAndPostImages.enabled&&await s.command({collMod:r,...i}):await s.createCollection(r,i)})}))},3),l.on("close",async()=>this.client.close(),1)}client;#e=[];async session(e){return this.client.withSession(e)}id(){return new b}use(e){e.change&&(this.config.changes||l.crash(new f("Db changes are not enabled in the configuration.",{config:e})),new p(this.mongoConfig,this.config.changes,this.client,this.getScopedDb(e.db),e.col,e.change,e.mapper)),this.#e.push({db:this.getScopedDb(e.db),col:e.col});const n=this.client.db(this.getScopedDb(e.db)).collection(e.col);return h(e,n)}}export{q as MongoDb};
|
|
2
2
|
//# sourceMappingURL=index.min.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/dbs/mongo/index.ts"],"sourcesContent":["import { ClientSession, CollectionInfo, MongoClient, ObjectId } from 'mongodb'\n\nimport { getTable } from './api'\nimport { MongoDbConfig } from '../pipes'\nimport { MongoDbChange } from './changes'\nimport { EquippedError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { Db } from '../base/_instance'\nimport * as core from '../base/core'\nimport { DbConfig } from '../base/types'\n\nexport class MongoDb extends Db<{ _id: string }> {\n\
|
|
1
|
+
{"version":3,"sources":["../../../../src/dbs/mongo/index.ts"],"sourcesContent":["import { ClientSession, CollectionInfo, MongoClient, ObjectId } from 'mongodb'\n\nimport { getTable } from './api'\nimport { MongoDbConfig } from '../pipes'\nimport { MongoDbChange } from './changes'\nimport { EquippedError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { Db } from '../base/_instance'\nimport * as core from '../base/core'\nimport { DbConfig } from '../base/types'\n\nexport class MongoDb extends Db<{ _id: string }> {\n\tclient: MongoClient\n\t#cols: { db: string; col: string }[] = []\n\n\tconstructor(\n\t\tprivate mongoConfig: MongoDbConfig,\n\t\tdbConfig: DbConfig,\n\t) {\n\t\tsuper(dbConfig)\n\t\tthis.client = new MongoClient(mongoConfig.uri)\n\t\tInstance.on(\n\t\t\t'start',\n\t\t\tasync () => {\n\t\t\t\tawait this.client.connect()\n\n\t\t\t\tconst grouped = this.#cols.reduce<Record<string, string[]>>((acc, cur) => {\n\t\t\t\t\tif (!acc[cur.db]) acc[cur.db] = []\n\t\t\t\t\tacc[cur.db].push(cur.col)\n\t\t\t\t\treturn acc\n\t\t\t\t}, {})\n\n\t\t\t\tconst options = {\n\t\t\t\t\tchangeStreamPreAndPostImages: { enabled: true },\n\t\t\t\t}\n\t\t\t\tawait Promise.all(\n\t\t\t\t\tObject.entries(grouped).map(async ([dbName, colNames]) => {\n\t\t\t\t\t\tconst db = this.client.db(dbName)\n\t\t\t\t\t\tconst collections = await db.listCollections<CollectionInfo>().toArray()\n\t\t\t\t\t\treturn colNames.map(async (colName) => {\n\t\t\t\t\t\t\tconst existing = collections.find((collection) => collection.name === colName)\n\t\t\t\t\t\t\tif (existing) {\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\texisting.options?.changeStreamPreAndPostImages?.enabled !== options.changeStreamPreAndPostImages.enabled\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\tawait db.command({ collMod: colName, ...options })\n\t\t\t\t\t\t\t} else await db.createCollection(colName, options)\n\t\t\t\t\t\t})\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t},\n\t\t\t3,\n\t\t)\n\t\tInstance.on('close', async () => this.client.close(), 1)\n\t}\n\n\tasync session<T>(callback: (session: ClientSession) => Promise<T>) {\n\t\treturn this.client.withSession(callback)\n\t}\n\n\tid() {\n\t\treturn new ObjectId()\n\t}\n\n\tuse<Model extends core.Model<{ _id: string }>, Entity extends core.Entity>(config: core.Config<Model, Entity>) {\n\t\tif (config.change) {\n\t\t\tif (!this.config.changes) Instance.crash(new EquippedError('Db changes are not enabled in the configuration.', { config }))\n\t\t\tnew MongoDbChange<Model, Entity>(\n\t\t\t\tthis.mongoConfig,\n\t\t\t\tthis.config.changes,\n\t\t\t\tthis.client,\n\t\t\t\tthis.getScopedDb(config.db),\n\t\t\t\tconfig.col,\n\t\t\t\tconfig.change,\n\t\t\t\tconfig.mapper,\n\t\t\t)\n\t\t}\n\t\tthis.#cols.push({ db: this.getScopedDb(config.db), col: config.col })\n\t\tconst collection = this.client.db(this.getScopedDb(config.db)).collection<Model>(config.col)\n\t\treturn getTable(config, collection)\n\t}\n}\n"],"mappings":"AAAA,OAAwC,eAAAA,EAAa,YAAAC,MAAgB,UAErE,OAAS,YAAAC,MAAgB,QAEzB,OAAS,iBAAAC,MAAqB,YAC9B,OAAS,iBAAAC,MAAqB,eAC9B,OAAS,YAAAC,MAAgB,iBACzB,OAAS,MAAAC,MAAU,oBAIZ,MAAMC,UAAgBD,CAAoB,CAIhD,YACSE,EACRC,EACC,CACD,MAAMA,CAAQ,EAHN,iBAAAD,EAIR,KAAK,OAAS,IAAIR,EAAYQ,EAAY,GAAG,EAC7CH,EAAS,GACR,QACA,SAAY,CACX,MAAM,KAAK,OAAO,QAAQ,EAE1B,MAAMK,EAAU,KAAKC,GAAM,OAAiC,CAACC,EAAKC,KAC5DD,EAAIC,EAAI,EAAE,IAAGD,EAAIC,EAAI,EAAE,EAAI,CAAC,GACjCD,EAAIC,EAAI,EAAE,EAAE,KAAKA,EAAI,GAAG,EACjBD,GACL,CAAC,CAAC,EAECE,EAAU,CACf,6BAA8B,CAAE,QAAS,EAAK,CAC/C,EACA,MAAM,QAAQ,IACb,OAAO,QAAQJ,CAAO,EAAE,IAAI,MAAO,CAACK,EAAQC,CAAQ,IAAM,CACzD,MAAMC,EAAK,KAAK,OAAO,GAAGF,CAAM,EAC1BG,EAAc,MAAMD,EAAG,gBAAgC,EAAE,QAAQ,EACvE,OAAOD,EAAS,IAAI,MAAOG,GAAY,CACtC,MAAMC,EAAWF,EAAY,KAAMG,GAAeA,EAAW,OAASF,CAAO,EACzEC,EAEFA,EAAS,SAAS,8BAA8B,UAAYN,EAAQ,6BAA6B,SAEjG,MAAMG,EAAG,QAAQ,CAAE,QAASE,EAAS,GAAGL,CAAQ,CAAC,EAC5C,MAAMG,EAAG,iBAAiBE,EAASL,CAAO,CAClD,CAAC,CACF,CAAC,CACF,CACD,EACA,CACD,EACAT,EAAS,GAAG,QAAS,SAAY,KAAK,OAAO,MAAM,EAAG,CAAC,CACxD,CA1CA,OACAM,GAAuC,CAAC,EA2CxC,MAAM,QAAWW,EAAkD,CAClE,OAAO,KAAK,OAAO,YAAYA,CAAQ,CACxC,CAEA,IAAK,CACJ,OAAO,IAAIrB,CACZ,CAEA,IAA2EsB,EAAoC,CAC1GA,EAAO,SACL,KAAK,OAAO,SAASlB,EAAS,MAAM,IAAID,EAAc,mDAAoD,CAAE,OAAAmB,CAAO,CAAC,CAAC,EAC1H,IAAIpB,EACH,KAAK,YACL,KAAK,OAAO,QACZ,KAAK,OACL,KAAK,YAAYoB,EAAO,EAAE,EAC1BA,EAAO,IACPA,EAAO,OACPA,EAAO,MACR,GAED,KAAKZ,GAAM,KAAK,CAAE,GAAI,KAAK,YAAYY,EAAO,EAAE,EAAG,IAAKA,EAAO,GAAI,CAAC,EACpE,MAAMF,EAAa,KAAK,OAAO,GAAG,KAAK,YAAYE,EAAO,EAAE,CAAC,EAAE,WAAkBA,EAAO,GAAG,EAC3F,OAAOrB,EAASqB,EAAQF,CAAU,CACnC,CACD","names":["MongoClient","ObjectId","getTable","MongoDbChange","EquippedError","Instance","Db","MongoDb","mongoConfig","dbConfig","grouped","#cols","acc","cur","options","dbName","colNames","db","collections","colName","existing","collection","callback","config"]}
|
|
@@ -8,11 +8,11 @@ class MongoDb extends Db {
|
|
|
8
8
|
constructor(mongoConfig, dbConfig) {
|
|
9
9
|
super(dbConfig);
|
|
10
10
|
this.mongoConfig = mongoConfig;
|
|
11
|
-
this
|
|
11
|
+
this.client = new MongoClient(mongoConfig.uri);
|
|
12
12
|
Instance.on(
|
|
13
13
|
"start",
|
|
14
14
|
async () => {
|
|
15
|
-
await this
|
|
15
|
+
await this.client.connect();
|
|
16
16
|
const grouped = this.#cols.reduce((acc, cur) => {
|
|
17
17
|
if (!acc[cur.db]) acc[cur.db] = [];
|
|
18
18
|
acc[cur.db].push(cur.col);
|
|
@@ -23,7 +23,7 @@ class MongoDb extends Db {
|
|
|
23
23
|
};
|
|
24
24
|
await Promise.all(
|
|
25
25
|
Object.entries(grouped).map(async ([dbName, colNames]) => {
|
|
26
|
-
const db = this
|
|
26
|
+
const db = this.client.db(dbName);
|
|
27
27
|
const collections = await db.listCollections().toArray();
|
|
28
28
|
return colNames.map(async (colName) => {
|
|
29
29
|
const existing = collections.find((collection) => collection.name === colName);
|
|
@@ -37,12 +37,12 @@ class MongoDb extends Db {
|
|
|
37
37
|
},
|
|
38
38
|
3
|
|
39
39
|
);
|
|
40
|
-
Instance.on("close", async () => this
|
|
40
|
+
Instance.on("close", async () => this.client.close(), 1);
|
|
41
41
|
}
|
|
42
|
-
|
|
42
|
+
client;
|
|
43
43
|
#cols = [];
|
|
44
44
|
async session(callback) {
|
|
45
|
-
return this
|
|
45
|
+
return this.client.withSession(callback);
|
|
46
46
|
}
|
|
47
47
|
id() {
|
|
48
48
|
return new ObjectId();
|
|
@@ -53,7 +53,7 @@ class MongoDb extends Db {
|
|
|
53
53
|
new MongoDbChange(
|
|
54
54
|
this.mongoConfig,
|
|
55
55
|
this.config.changes,
|
|
56
|
-
this
|
|
56
|
+
this.client,
|
|
57
57
|
this.getScopedDb(config.db),
|
|
58
58
|
config.col,
|
|
59
59
|
config.change,
|
|
@@ -61,7 +61,7 @@ class MongoDb extends Db {
|
|
|
61
61
|
);
|
|
62
62
|
}
|
|
63
63
|
this.#cols.push({ db: this.getScopedDb(config.db), col: config.col });
|
|
64
|
-
const collection = this
|
|
64
|
+
const collection = this.client.db(this.getScopedDb(config.db)).collection(config.col);
|
|
65
65
|
return getTable(config, collection);
|
|
66
66
|
}
|
|
67
67
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/dbs/mongo/index.ts"],"sourcesContent":["import { ClientSession, CollectionInfo, MongoClient, ObjectId } from 'mongodb'\n\nimport { getTable } from './api'\nimport { MongoDbConfig } from '../pipes'\nimport { MongoDbChange } from './changes'\nimport { EquippedError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { Db } from '../base/_instance'\nimport * as core from '../base/core'\nimport { DbConfig } from '../base/types'\n\nexport class MongoDb extends Db<{ _id: string }> {\n\
|
|
1
|
+
{"version":3,"sources":["../../../../src/dbs/mongo/index.ts"],"sourcesContent":["import { ClientSession, CollectionInfo, MongoClient, ObjectId } from 'mongodb'\n\nimport { getTable } from './api'\nimport { MongoDbConfig } from '../pipes'\nimport { MongoDbChange } from './changes'\nimport { EquippedError } from '../../errors'\nimport { Instance } from '../../instance'\nimport { Db } from '../base/_instance'\nimport * as core from '../base/core'\nimport { DbConfig } from '../base/types'\n\nexport class MongoDb extends Db<{ _id: string }> {\n\tclient: MongoClient\n\t#cols: { db: string; col: string }[] = []\n\n\tconstructor(\n\t\tprivate mongoConfig: MongoDbConfig,\n\t\tdbConfig: DbConfig,\n\t) {\n\t\tsuper(dbConfig)\n\t\tthis.client = new MongoClient(mongoConfig.uri)\n\t\tInstance.on(\n\t\t\t'start',\n\t\t\tasync () => {\n\t\t\t\tawait this.client.connect()\n\n\t\t\t\tconst grouped = this.#cols.reduce<Record<string, string[]>>((acc, cur) => {\n\t\t\t\t\tif (!acc[cur.db]) acc[cur.db] = []\n\t\t\t\t\tacc[cur.db].push(cur.col)\n\t\t\t\t\treturn acc\n\t\t\t\t}, {})\n\n\t\t\t\tconst options = {\n\t\t\t\t\tchangeStreamPreAndPostImages: { enabled: true },\n\t\t\t\t}\n\t\t\t\tawait Promise.all(\n\t\t\t\t\tObject.entries(grouped).map(async ([dbName, colNames]) => {\n\t\t\t\t\t\tconst db = this.client.db(dbName)\n\t\t\t\t\t\tconst collections = await db.listCollections<CollectionInfo>().toArray()\n\t\t\t\t\t\treturn colNames.map(async (colName) => {\n\t\t\t\t\t\t\tconst existing = collections.find((collection) => collection.name === colName)\n\t\t\t\t\t\t\tif (existing) {\n\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\texisting.options?.changeStreamPreAndPostImages?.enabled !== options.changeStreamPreAndPostImages.enabled\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\tawait db.command({ collMod: colName, ...options })\n\t\t\t\t\t\t\t} else await db.createCollection(colName, options)\n\t\t\t\t\t\t})\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t},\n\t\t\t3,\n\t\t)\n\t\tInstance.on('close', async () => this.client.close(), 1)\n\t}\n\n\tasync session<T>(callback: (session: ClientSession) => Promise<T>) {\n\t\treturn this.client.withSession(callback)\n\t}\n\n\tid() {\n\t\treturn new ObjectId()\n\t}\n\n\tuse<Model extends core.Model<{ _id: string }>, Entity extends core.Entity>(config: core.Config<Model, Entity>) {\n\t\tif (config.change) {\n\t\t\tif (!this.config.changes) Instance.crash(new EquippedError('Db changes are not enabled in the configuration.', { config }))\n\t\t\tnew MongoDbChange<Model, Entity>(\n\t\t\t\tthis.mongoConfig,\n\t\t\t\tthis.config.changes,\n\t\t\t\tthis.client,\n\t\t\t\tthis.getScopedDb(config.db),\n\t\t\t\tconfig.col,\n\t\t\t\tconfig.change,\n\t\t\t\tconfig.mapper,\n\t\t\t)\n\t\t}\n\t\tthis.#cols.push({ db: this.getScopedDb(config.db), col: config.col })\n\t\tconst collection = this.client.db(this.getScopedDb(config.db)).collection<Model>(config.col)\n\t\treturn getTable(config, collection)\n\t}\n}\n"],"mappings":"AAAA,SAAwC,aAAa,gBAAgB;AAErE,SAAS,gBAAgB;AAEzB,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,gBAAgB;AACzB,SAAS,UAAU;AAIZ,MAAM,gBAAgB,GAAoB;AAAA,EAIhD,YACS,aACR,UACC;AACD,UAAM,QAAQ;AAHN;AAIR,SAAK,SAAS,IAAI,YAAY,YAAY,GAAG;AAC7C,aAAS;AAAA,MACR;AAAA,MACA,YAAY;AACX,cAAM,KAAK,OAAO,QAAQ;AAE1B,cAAM,UAAU,KAAK,MAAM,OAAiC,CAAC,KAAK,QAAQ;AACzE,cAAI,CAAC,IAAI,IAAI,EAAE,EAAG,KAAI,IAAI,EAAE,IAAI,CAAC;AACjC,cAAI,IAAI,EAAE,EAAE,KAAK,IAAI,GAAG;AACxB,iBAAO;AAAA,QACR,GAAG,CAAC,CAAC;AAEL,cAAM,UAAU;AAAA,UACf,8BAA8B,EAAE,SAAS,KAAK;AAAA,QAC/C;AACA,cAAM,QAAQ;AAAA,UACb,OAAO,QAAQ,OAAO,EAAE,IAAI,OAAO,CAAC,QAAQ,QAAQ,MAAM;AACzD,kBAAM,KAAK,KAAK,OAAO,GAAG,MAAM;AAChC,kBAAM,cAAc,MAAM,GAAG,gBAAgC,EAAE,QAAQ;AACvE,mBAAO,SAAS,IAAI,OAAO,YAAY;AACtC,oBAAM,WAAW,YAAY,KAAK,CAAC,eAAe,WAAW,SAAS,OAAO;AAC7E,kBAAI,UAAU;AACb,oBACC,SAAS,SAAS,8BAA8B,YAAY,QAAQ,6BAA6B;AAEjG,wBAAM,GAAG,QAAQ,EAAE,SAAS,SAAS,GAAG,QAAQ,CAAC;AAAA,cACnD,MAAO,OAAM,GAAG,iBAAiB,SAAS,OAAO;AAAA,YAClD,CAAC;AAAA,UACF,CAAC;AAAA,QACF;AAAA,MACD;AAAA,MACA;AAAA,IACD;AACA,aAAS,GAAG,SAAS,YAAY,KAAK,OAAO,MAAM,GAAG,CAAC;AAAA,EACxD;AAAA,EA1CA;AAAA,EACA,QAAuC,CAAC;AAAA,EA2CxC,MAAM,QAAW,UAAkD;AAClE,WAAO,KAAK,OAAO,YAAY,QAAQ;AAAA,EACxC;AAAA,EAEA,KAAK;AACJ,WAAO,IAAI,SAAS;AAAA,EACrB;AAAA,EAEA,IAA2E,QAAoC;AAC9G,QAAI,OAAO,QAAQ;AAClB,UAAI,CAAC,KAAK,OAAO,QAAS,UAAS,MAAM,IAAI,cAAc,oDAAoD,EAAE,OAAO,CAAC,CAAC;AAC1H,UAAI;AAAA,QACH,KAAK;AAAA,QACL,KAAK,OAAO;AAAA,QACZ,KAAK;AAAA,QACL,KAAK,YAAY,OAAO,EAAE;AAAA,QAC1B,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,MACR;AAAA,IACD;AACA,SAAK,MAAM,KAAK,EAAE,IAAI,KAAK,YAAY,OAAO,EAAE,GAAG,KAAK,OAAO,IAAI,CAAC;AACpE,UAAM,aAAa,KAAK,OAAO,GAAG,KAAK,YAAY,OAAO,EAAE,CAAC,EAAE,WAAkB,OAAO,GAAG;AAC3F,WAAO,SAAS,QAAQ,UAAU;AAAA,EACnC;AACD;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import{convert as c}from"@openapi-contrib/json-schema-to-openapi-schema";import{capitalize as l}from"valleyed";import{Router as d}from "./routes.min.mjs";class I{constructor(e){this.config=e;this.#e={openapi:"3.0.0",info:{title:`${e.app.name} ${e.app.id}`,version:e.config.openapi.docsVersion??""},servers:e.config.openapi.docsBaseUrl?.map(s=>({url:s})),paths:{},components:{schemas:{},securitySchemes:{Authorization:{type:"apiKey",name:"authorization",in:"header"},RefreshToken:{type:"apiKey",name:"x-refresh-token",in:"header"},ApiKey:{type:"apiKey",name:"x-api-key",in:"header"}}},tags:[],"x-tagGroups":[]}}#n={};#t={};#e;cleanPath(e){let s=e.replace(/(\/\s*)+/g,"/");return s.startsWith("/")||(s=`/${s}`),s!=="/"&&s.endsWith("/")&&(s=s.slice(0,-1)),s}async register(e,s){if(e.hide)return;const t=this.#i(e.groups??[]),n=this.cleanPath(e.path),o=`(${e.method.toUpperCase()}) ${n}`;await this.#a(n,e.method.toLowerCase(),s,{operationId:o,summary:e.title??n,description:e.descriptions?.join(`
|
|
2
2
|
|
|
3
|
-
`),tags:t?[t]:void 0,security:e.security})}async#a(e,s,t,n){if(t.response.response?.length){n.responses??={};for(const r of t.response.response){n.responses[r.status]??={description:"",content:{}};const p=n.responses[r.status];p.content[r.contentType]={schema:await c(this.#s(r.schema))}}}if(t.response.responseHeaders?.length){n.responses??={};for(const r of t.response.responseHeaders){n.responses[r.status]??={description:"",content:{}},n.responses[r.status];const p=n.responses[r.status];p.headers={schema:await c(this.#s(r.schema))}}}t.request.body&&(n.requestBody={required:!0,content:{"application/json":{schema:await c(this.#s(t.request.body))}}});const o=[],a=async(r,p)=>{if(!p)return;const u=this.#r(p);for(const h of u)if(h.properties)for(const[m,f]of Object.entries(h.properties))o.push({name:m,in:r,schema:await c(this.#s(f)),required:(h.required||[]).includes(m)})};await Promise.all([a("query",t.request.query),a("path",t.request.params),a("header",t.request.headers)]),o.length&&(n.parameters=o);const i=this.#e;i.paths||(i.paths={}),i.paths[e]||(i.paths[e]={}),i.paths[e][s]=n}router(){const e="/openapi.json",s=new d({path:this.config.config.openapi.docsPath??"/",hide:!0});return s.get("/")(t=>t.res({body:this.#o(`.${e}`),contentType:"text/html"})),s.get(e)(t=>t.res({body:this.#e})),s}#r(e){const{allOf:s,oneOf:t,anyOf:n,...o}=e;return s?s.flatMap(a=>this.#r(a)):[o]}#s(e){if(!e||typeof e!="object")return e;if(typeof e.$refId=="string"){const{$refId:s,...t}=e,n=this.#s(t);return this.#e.components?.schemas?(this.#e.components.schemas[s]=n,{$ref:`#/components/schemas/${s}`}):n}return Array.isArray(e)?e.map(s=>this.#s(s)):Object.fromEntries(Object.entries(e).map(([s,t])=>[s,this.#s(t)]))}#i(e){if(!e.length)return;const s=e.map(a=>typeof a=="string"?{name:a}:a),t=s.map(a=>a.name).join(" > "),n=s.at(-1)?.name??"",o=s.map(a=>a.description?.trim()??"").filter(Boolean).join(`
|
|
3
|
+
`),tags:t?[t]:void 0,security:e.security})}async#a(e,s,t,n){if(t.response.response?.length){n.responses??={};for(const r of t.response.response){n.responses[r.status]??={description:"",content:{}};const p=n.responses[r.status];p.content[r.contentType]={schema:await c(this.#s(r.schema))}}}if(t.response.responseHeaders?.length){n.responses??={};for(const r of t.response.responseHeaders){n.responses[r.status]??={description:"",content:{}},n.responses[r.status];const p=n.responses[r.status];p.headers={schema:await c(this.#s(r.schema))}}}t.request.body&&(n.requestBody={required:!0,content:{"application/json":{schema:await c(this.#s(t.request.body))}}});const o=[],a=async(r,p)=>{if(!p)return;const u=this.#r(p);for(const h of u)if(h.properties)for(const[m,f]of Object.entries(h.properties))o.push({name:m,in:r,schema:await c(this.#s(f)),required:(h.required||[]).includes(m)})};await Promise.all([a("query",t.request.query),a("path",t.request.params),a("header",t.request.headers)]),o.length&&(n.parameters=o);const i=this.#e;i.paths||(i.paths={}),i.paths[e]||(i.paths[e]={}),i.paths[e][s]=n}router(){const e="/openapi.json",s=new d({path:this.config.config.openapi.docsPath??"/",hide:!0});return s.get("/index.html")(t=>t.res({body:this.#o(`.${e}`),contentType:"text/html"})),s.get(e)(t=>t.res({body:this.#e})),s}#r(e){const{allOf:s,oneOf:t,anyOf:n,...o}=e;return s?s.flatMap(a=>this.#r(a)):[o]}#s(e){if(!e||typeof e!="object")return e;if(typeof e.$refId=="string"){const{$refId:s,...t}=e,n=this.#s(t);return this.#e.components?.schemas?(this.#e.components.schemas[s]=n,{$ref:`#/components/schemas/${s}`}):n}return Array.isArray(e)?e.map(s=>this.#s(s)):Object.fromEntries(Object.entries(e).map(([s,t])=>[s,this.#s(t)]))}#i(e){if(!e.length)return;const s=e.map(a=>typeof a=="string"?{name:a}:a),t=s.map(a=>a.name).join(" > "),n=s.at(-1)?.name??"",o=s.map(a=>a.description?.trim()??"").filter(Boolean).join(`
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|