@weclapp/sdk 2.0.0-dev.52 → 2.0.0-dev.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +1263 -1367
  2. package/package.json +7 -9
package/dist/cli.js CHANGED
@@ -1,1494 +1,1390 @@
1
- import { fileURLToPath } from 'url';
2
- import { resolve, dirname } from 'path';
3
- import { rollup } from 'rollup';
4
- import terser from '@rollup/plugin-terser';
5
- import ts from '@rollup/plugin-typescript';
6
- import indentString from 'indent-string';
7
- import { snakeCase, pascalCase, camelCase } from 'change-case';
8
- import chalk from 'chalk';
9
- import { OpenAPIV3 } from 'openapi-types';
10
- import { createHash } from 'crypto';
11
- import { stat, readFile, rm, cp, writeFile, mkdir } from 'fs/promises';
12
- import { config } from 'dotenv';
13
- import yargs from 'yargs';
14
- import { hideBin } from 'yargs/helpers';
15
- import pkg from '../package.json' with { type: 'json' };
16
- import prettyMs from 'pretty-ms';
17
-
1
+ import { fileURLToPath } from "url";
2
+ import { dirname, resolve } from "path";
3
+ import { rolldown } from "rolldown";
4
+ import indentString from "indent-string";
5
+ import { camelCase, pascalCase, snakeCase } from "change-case";
6
+ import chalk from "chalk";
7
+ import { OpenAPIV3 } from "openapi-types";
8
+ import { createHash } from "crypto";
9
+ import { cp, mkdir, readFile, rm, stat, writeFile } from "fs/promises";
10
+ import { config } from "dotenv";
11
+ import yargs from "yargs";
12
+ import { hideBin } from "yargs/helpers";
13
+ import pkg from "../package.json" with { type: "json" };
14
+ import prettyMs from "pretty-ms";
15
+ //#region src/utils/currentDirname.ts
18
16
  const currentDirname = () => {
19
- // Go one level up as the CLI is inside a folder
20
- return fileURLToPath(new URL('..', import.meta.url));
21
- };
22
-
23
- var Target;
24
- (function (Target) {
25
- Target["BROWSER_PROMISES"] = "browser";
26
- Target["BROWSER_RX"] = "browser.rx";
27
- Target["NODE_PROMISES"] = "node";
28
- Target["NODE_RX"] = "node.rx";
29
- })(Target || (Target = {}));
17
+ return fileURLToPath(new URL("..", import.meta.url));
18
+ };
19
+ //#endregion
20
+ //#region src/target.ts
21
+ let Target = /* @__PURE__ */ function(Target) {
22
+ Target["BROWSER_PROMISES"] = "browser";
23
+ Target["BROWSER_RX"] = "browser.rx";
24
+ Target["NODE_PROMISES"] = "node";
25
+ Target["NODE_RX"] = "node.rx";
26
+ return Target;
27
+ }({});
30
28
  const isNodeTarget = (target) => {
31
- return target === Target.NODE_PROMISES || target === Target.NODE_RX;
29
+ return target === Target.NODE_PROMISES || target === Target.NODE_RX;
32
30
  };
33
31
  const isRXTarget = (target) => {
34
- return target === Target.BROWSER_RX || target === Target.NODE_RX;
32
+ return target === Target.BROWSER_RX || target === Target.NODE_RX;
35
33
  };
36
34
  const resolveResponseType = (target) => {
37
- return isRXTarget(target) ? 'Observable' : 'Promise';
35
+ return isRXTarget(target) ? "Observable" : "Promise";
38
36
  };
39
37
  const resolveBinaryType = (target) => {
40
- return isNodeTarget(target) ? 'Buffer' : 'Blob';
38
+ return isNodeTarget(target) ? "Buffer" : "Blob";
41
39
  };
42
-
43
- const tsconfig = resolve(currentDirname(), './tsconfig.sdk.json');
44
- const resolveGlobals = (...globals) => Object.fromEntries(globals.map((v) => [v, '*']));
40
+ //#endregion
41
+ //#region src/bundle.ts
42
+ const tsconfig = resolve(currentDirname(), "./tsconfig.sdk.json");
43
+ const resolveGlobals = (...globals) => Object.fromEntries(globals.map((v) => [v, "*"]));
45
44
  const generateOutput = (config) => ({
46
- sourcemap: false,
47
- banner: `/* weclapp sdk */`,
48
- ...config
45
+ sourcemap: false,
46
+ banner: `/* weclapp sdk */`,
47
+ ...config
49
48
  });
50
49
  const bundle = async (workingDirectory, target) => {
51
- const dist = (...paths) => resolve(workingDirectory, 'dist', ...paths);
52
- const src = (...paths) => resolve(workingDirectory, 'src', ...paths);
53
- const generateNodeOutput = () => [
54
- generateOutput({
55
- file: dist('index.cjs'),
56
- format: 'cjs',
57
- globals: resolveGlobals('node-fetch', 'url')
58
- }),
59
- generateOutput({
60
- file: dist('index.js'),
61
- format: 'es',
62
- globals: resolveGlobals('node-fetch', 'url')
63
- })
64
- ];
65
- const bundles = {
66
- [Target.BROWSER_PROMISES]: () => ({
67
- input: src('index.ts'),
68
- plugins: [ts({ tsconfig, declarationDir: dist(), filterRoot: src() }), terser()],
69
- output: [
70
- generateOutput({
71
- file: dist('index.js'),
72
- format: 'es'
73
- })
74
- ]
75
- }),
76
- [Target.BROWSER_RX]: () => ({
77
- input: src('index.ts'),
78
- plugins: [ts({ tsconfig, declarationDir: dist(), filterRoot: src() }), terser()],
79
- external: ['rxjs'],
80
- output: [
81
- generateOutput({
82
- file: dist('index.js'),
83
- format: 'es',
84
- globals: resolveGlobals('rxjs')
85
- })
86
- ]
87
- }),
88
- [Target.NODE_PROMISES]: () => ({
89
- input: src('index.ts'),
90
- plugins: [ts({ tsconfig, declarationDir: dist(), filterRoot: src() }), terser()],
91
- external: ['node-fetch', 'url'],
92
- output: generateNodeOutput()
93
- }),
94
- [Target.NODE_RX]: () => ({
95
- input: src('index.ts'),
96
- plugins: [ts({ tsconfig, declarationDir: dist(), filterRoot: src() }), terser()],
97
- external: ['node-fetch', 'url', 'rxjs'],
98
- output: generateNodeOutput()
99
- })
100
- };
101
- const config = bundles[target]();
102
- const bundle = await rollup(config);
103
- if (Array.isArray(config.output)) {
104
- await Promise.all(config.output.map(bundle.write));
105
- }
106
- else if (config.output) {
107
- await bundle.write(config.output);
108
- }
109
- await bundle.close();
110
- };
111
-
50
+ const dist = (...paths) => resolve(workingDirectory, "dist", ...paths);
51
+ const src = (...paths) => resolve(workingDirectory, "src", ...paths);
52
+ const generateNodeOutput = () => [generateOutput({
53
+ file: dist("index.cjs"),
54
+ format: "cjs",
55
+ globals: resolveGlobals("node-fetch", "url")
56
+ }), generateOutput({
57
+ file: dist("index.js"),
58
+ format: "es",
59
+ globals: resolveGlobals("node-fetch", "url")
60
+ })];
61
+ const config = {
62
+ [Target.BROWSER_PROMISES]: () => ({
63
+ input: src("index.ts"),
64
+ resolve: { tsconfigFilename: tsconfig },
65
+ output: [generateOutput({
66
+ file: dist("index.js"),
67
+ format: "es",
68
+ minify: true
69
+ })]
70
+ }),
71
+ [Target.BROWSER_RX]: () => ({
72
+ input: src("index.ts"),
73
+ resolve: { tsconfigFilename: tsconfig },
74
+ external: ["rxjs"],
75
+ output: [generateOutput({
76
+ file: dist("index.js"),
77
+ format: "es",
78
+ minify: true,
79
+ globals: resolveGlobals("rxjs")
80
+ })]
81
+ }),
82
+ [Target.NODE_PROMISES]: () => ({
83
+ input: src("index.ts"),
84
+ resolve: { tsconfigFilename: tsconfig },
85
+ external: ["node-fetch", "url"],
86
+ output: generateNodeOutput().map((o) => ({
87
+ ...o,
88
+ minify: true
89
+ }))
90
+ }),
91
+ [Target.NODE_RX]: () => ({
92
+ input: src("index.ts"),
93
+ resolve: { tsconfigFilename: tsconfig },
94
+ external: [
95
+ "node-fetch",
96
+ "url",
97
+ "rxjs"
98
+ ],
99
+ output: generateNodeOutput().map((o) => ({
100
+ ...o,
101
+ minify: true
102
+ }))
103
+ })
104
+ }[target]();
105
+ const result = await rolldown(config);
106
+ if (Array.isArray(config.output)) await Promise.all(config.output.map((o) => result.write(o)));
107
+ else if (config.output) await result.write(config.output);
108
+ await result.close();
109
+ };
110
+ //#endregion
111
+ //#region src/ts/generateString.ts
112
112
  const generateString = (str) => `'${str}'`;
113
113
  const generateStrings = (str) => str.map(generateString);
114
-
114
+ //#endregion
115
+ //#region src/ts/generateImport.ts
115
116
  const generateImport = (opt) => {
116
- const imports = [opt.default, opt.imports?.length ? `{${opt.imports.join(', ')}}` : ''];
117
- return `import ${imports.filter(Boolean).join(', ')} from ${generateString(opt.src)};`;
117
+ return `import ${[opt.default, opt.imports?.length ? `{${opt.imports.join(", ")}}` : ""].filter(Boolean).join(", ")} from ${generateString(opt.src)};`;
118
118
  };
119
-
119
+ //#endregion
120
+ //#region src/utils/indent.ts
120
121
  /**
121
- * Indents each line of the given string
122
- * @param s String to indent
123
- * @param level Indentation level
124
- */
122
+ * Indents each line of the given string
123
+ * @param s String to indent
124
+ * @param level Indentation level
125
+ */
125
126
  const indent = (s, level = 1) => {
126
- return indentString(s, 4 * level);
127
+ return indentString(s, 4 * level);
127
128
  };
128
-
129
- const generateStatements = (...statements) => statements
130
- .map((v) => v.trim())
131
- .filter((v) => v.length)
132
- .join('\n\n');
129
+ //#endregion
130
+ //#region src/ts/generateStatements.ts
131
+ const generateStatements = (...statements) => statements.map((v) => v.trim()).filter((v) => v.length).join("\n\n");
133
132
  const generateBlockStatements = (...statements) => `{\n${indent(generateStatements(...statements))}\n}`;
134
-
135
- var globalConfig = "export type RequestPayloadMethod =\n | 'GET'\n | 'HEAD'\n | 'POST'\n | 'PUT'\n | 'DELETE'\n | 'CONNECT'\n | 'OPTIONS'\n | 'TRACE'\n | 'PATCH';\n\nexport interface RequestPayload {\n method?: RequestPayloadMethod;\n query?: Record<string, any>;\n body?: any;\n unwrap?: boolean;\n forceBlob?: boolean;\n}\n\nexport interface ServiceConfig {\n // Your API-Key, this is optional in the sense of if you omit this, and you're in a browser, the\n // cookie-authentication (include-credentials) will be used.\n key?: string;\n\n // Your domain, if omitted location.host will be used (browser env).\n host?: string;\n\n // If you want to use https, defaults to location.protocol (browser env).\n secure?: boolean;\n\n // If you want that some and count requests are bundled into multi requests.\n multiRequest?: boolean;\n\n // If you want that the ignoreMissingProperties parameter to be set to true for every post request.\n ignoreMissingProperties?: boolean;\n\n // Optional request/response interceptors.\n interceptors?: {\n // Takes the generated request, you can either return a new request,\n // a response (which will be taken as \"the\" response) or nothing.\n // The payload contains the raw input generated by the SDK.\n request?: (\n request: Request,\n payload: RequestPayload\n ) => Request | Response | void | Promise<Request | Response | void>;\n\n // Takes the response. This can either be the one from the server or an\n // artificially-crafted one by the request interceptor.\n response?: (response: Response) => Response | void | Promise<Response | void>;\n };\n\n // Whether POST should be used instead of GET for some() and count() operations\n usePost?: boolean;\n}\n\nexport interface RequestOptions {\n signal?: AbortSignal;\n}\n\ntype ServiceConfigWithoutMultiRequest = Omit<ServiceConfig, 'multiRequest'>;\n\nlet globalConfig: ServiceConfig | undefined;\nexport const getGlobalConfig = (): ServiceConfig | undefined => globalConfig;\nexport const setGlobalConfig = (cfg?: ServiceConfig) => (globalConfig = cfg);\n\nexport const getHost = (cfg: ServiceConfig) => {\n let host = cfg.host?.replace(/^https?:\\/\\//, '');\n if (!host && typeof location !== 'undefined') {\n host = location.host;\n }\n\n if (!host) {\n throw new Error('Please specify a host');\n }\n\n return host;\n};\n\nexport const getProtocol = (cfg: ServiceConfig) => {\n const protocol =\n cfg.secure !== undefined\n ? cfg.secure\n ? 'https:'\n : 'http:'\n : typeof location !== 'undefined'\n ? location.protocol\n : undefined;\n\n if (!protocol) {\n throw new Error('Please specify a protocol (secure)');\n }\n\n return protocol;\n};\n";
136
-
137
- var multiRequest = "type RequestTask = {\n uri: string;\n resolve: (result: unknown) => void;\n reject: (error: unknown) => void;\n};\n\ntype BatchRequestTask = RequestTask & {\n settled: boolean;\n};\n\ntype MultiRequestResponse = {\n status: number;\n body: object;\n};\n\nlet microtaskQueued: boolean = false;\nconst tasksSet: Set<RequestTask> = new Set<RequestTask>();\n\nconst SQUARE_BRACKET_OPEN = '['.charCodeAt(0);\nconst COMMA = ','.charCodeAt(0);\nconst DECODER = new TextDecoder();\n\nconst readNextResponse = (bytes: Uint8Array<ArrayBuffer>) => {\n let headerStart: number | undefined = undefined;\n let commasSeen = 0;\n\n for (let i = 0; i < bytes.length; i++) {\n const byte = bytes[i];\n if (headerStart === undefined) {\n if (byte === SQUARE_BRACKET_OPEN || byte === COMMA) {\n headerStart = i + 1;\n }\n } else {\n if (byte === COMMA) {\n commasSeen++;\n }\n if (commasSeen === 2) {\n const headerArrayString = `[${DECODER.decode(bytes.subarray(headerStart, i))}]`;\n const [index, jsonLength] = JSON.parse(headerArrayString);\n if (!(typeof index === 'number') || !(typeof jsonLength === 'number')) {\n throw new Error(`unexpected header: ${headerArrayString}`);\n }\n\n const endIndex = i + 1 + jsonLength;\n if (endIndex > bytes.length) {\n // not all bytes available yet\n return undefined;\n }\n const jsonString = DECODER.decode(bytes.subarray(i + 1, endIndex));\n const data = JSON.parse(jsonString) as MultiRequestResponse;\n return {\n index,\n data,\n remainingBytes: bytes.subarray(endIndex)\n };\n }\n }\n }\n return undefined;\n};\n\nconst fetchMultiRequest = async (requests: string[]) => {\n const cfg = getGlobalConfig();\n\n if (!cfg) {\n throw new Error(`ServiceConfig missing.`);\n }\n\n const host = getHost(cfg);\n const protocol = getProtocol(cfg);\n\n return await fetch(`${protocol}//${host}/webapp/api/v2/batch/query`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(cfg.key && { AuthenticationToken: cfg.key })\n },\n body: JSON.stringify({ requests })\n });\n};\n\nconst rejectTasks = (tasks: BatchRequestTask[], error: unknown) => {\n for (const task of tasks) {\n if (!task.settled) {\n task.reject(error);\n }\n }\n};\n\nconst processStream = (\n { value: chunk, done }: ReadableStreamReadResult<Uint8Array>,\n remainingBytes: Uint8Array,\n reader: ReadableStreamDefaultReader<Uint8Array>,\n tasks: BatchRequestTask[]\n) => {\n if (done) {\n return;\n }\n if (chunk) {\n let bytes = new Uint8Array(remainingBytes.length + chunk.length);\n bytes.set(remainingBytes);\n bytes.set(chunk, remainingBytes.length);\n\n while (bytes.length) {\n const result = readNextResponse(bytes);\n if (!result) {\n break;\n }\n const task = tasks[result.index];\n if (result.data.status >= 100 && result.data.status < 400) {\n task.resolve({\n ...result.data.body\n });\n } else {\n task.reject({\n ...result.data.body\n });\n }\n task.settled = true;\n bytes = result.remainingBytes;\n }\n reader\n .read()\n .then((readResult) => processStream(readResult, bytes, reader, tasks))\n .catch((error) => rejectTasks(tasks, error));\n }\n};\n\nconst batch = async (tasks: BatchRequestTask[]) => {\n try {\n const requests = tasks.map(({ uri }) => uri);\n const resp = await fetchMultiRequest(requests);\n const reader = resp.body?.getReader();\n\n if (!reader) {\n throw new Error('Stream reader is undefined');\n }\n reader\n .read()\n .then((readResult) => processStream(readResult, new Uint8Array(0), reader, tasks))\n .catch((error) => rejectTasks(tasks, error));\n } catch (e) {\n rejectTasks(tasks, e);\n throw e;\n }\n};\n\nconst addTask = (task: RequestTask) => {\n tasksSet.add(task);\n\n if (!microtaskQueued) {\n queueMicrotask(() => {\n microtaskQueued = false;\n if (tasksSet.size > 0) {\n const batchTasks = Array.from(tasksSet).map((task) => ({ ...task, settled: false }));\n void batch(batchTasks);\n tasksSet.clear();\n }\n });\n microtaskQueued = true;\n }\n};\n\nconst addRequest = (uri: string) => new Promise((resolve, reject) => addTask({ uri, resolve, reject }));\n";
138
-
139
- var queriesWithFilter = "export type EqualityOperator = 'EQ' | 'NE';\n\nexport type ComparisonOperator =\n | 'LT'\n | 'GT'\n | 'LE'\n | 'GE'\n | 'LIKE'\n | 'ILIKE'\n | 'NOT_LIKE'\n | 'NOT_ILIKE'\n | 'IEQ'\n | 'NOT_IEQ';\n\nexport type ArrayOperator = 'IN' | 'NOT_IN';\n\nexport type Operator = EqualityOperator | ComparisonOperator | ArrayOperator;\n\nexport type MapOperators<T> = { [K in EqualityOperator]?: T | null } & { [K in ComparisonOperator]?: T } & {\n [K in ArrayOperator]?: T[];\n};\n\nexport type QueryFilter<T> = {\n [P in keyof T]?: T[P] extends Array<infer U> | undefined\n ? U extends Record<any, any>\n ? QueryFilter<U>\n : MapOperators<U>\n : T[P] extends Record<any, any> | undefined\n ? QueryFilter<T[P]>\n : MapOperators<T[P]>;\n};\n\nexport type CountQuery<F> = {\n filter?: QueryFilter<F>;\n or?: (QueryFilter<F> & CustomAttributeFilter)[];\n};\n\nexport type SomeQuery<E, F, I, P> = {\n serializeNulls?: boolean;\n include?: QuerySelect<I>;\n properties?: P;\n filter?: QueryFilter<F> & CustomAttributeFilter;\n select?: QuerySelect<E>;\n or?: (QueryFilter<F> & CustomAttributeFilter)[];\n sort?: Sort<E>[];\n pagination?: Pagination;\n};\n\nconst equality: string[] = ['EQ', 'NE', 'IEQ', 'NOT_IEQ'];\n\nconst simple: string[] = [...equality, 'LT', 'GT', 'LE', 'GE', 'LIKE', 'NOT_LIKE', 'ILIKE', 'NOT_ILIKE'];\n\nconst array: string[] = ['IN', 'NOT_IN'];\n\nconst filterMap: Record<Operator, string> = {\n EQ: 'eq',\n NE: 'ne',\n LT: 'lt',\n GT: 'gt',\n LE: 'le',\n GE: 'ge',\n LIKE: 'like',\n NOT_LIKE: 'notlike',\n ILIKE: 'ilike',\n NOT_ILIKE: 'notilike',\n IN: 'in',\n NOT_IN: 'notin',\n IEQ: 'ieq',\n NOT_IEQ: 'notieq'\n};\n\nconst flattenCustomAttributes = (obj: CustomAttributeFilter = {}): [string, string][] => {\n const entries: [string, string][] = [];\n\n for (const [id, filter] of Object.entries(obj)) {\n const key = `customAttribute${id}`;\n\n if (typeof filter === 'object') {\n for (const [prop, value] of Object.entries(filter)) {\n entries.push([`${key}.${prop}-eq`, String(value)]);\n }\n } else if (filter !== undefined) {\n entries.push([`${key}-eq`, String(filter)]);\n }\n }\n\n return entries;\n};\n\nconst flatten = (obj: QueryFilter<any> = {}): [string, string][] => {\n const entries: [string, string][] = [];\n\n for (const [prop, propValue] of Object.entries(obj)) {\n for (const [filter, value] of Object.entries(propValue as object)) {\n if (value === undefined) continue;\n\n if (simple.includes(filter) || array.includes(filter)) {\n if (value === null && equality.includes(filter)) {\n entries.push([`${prop}-${filter === 'EQ' ? 'null' : 'notnull'}`, '']);\n } else {\n entries.push([`${prop}-${filterMap[filter as Operator]}`, value]);\n }\n } else {\n entries.push(\n ...(flatten(propValue as QueryFilter<any>).map((v) => [`${prop}.${v[0]}`, v[1]]) as [string, string][])\n );\n break;\n }\n }\n }\n\n return entries;\n};\n\nconst flattenFilter = (obj: QueryFilter<any> = {}): Record<string, string> => {\n const filter: [string, any][] = [],\n customAttributes: [string, any][] = [];\n\n Object.entries(obj).forEach((value) => {\n (value[0].match(/^\\d+$/) ? customAttributes : filter).push(value);\n });\n\n return Object.fromEntries([\n ...flatten(Object.fromEntries(filter)),\n ...flattenCustomAttributes(Object.fromEntries(customAttributes) as CustomAttributeFilter)\n ]);\n};\n\nconst flattenOrFilter = (obj: QueryFilter<any>[] = []): Record<string, string> => {\n const entries: [string, any][] = [];\n\n for (let i = 0; i < obj.length; i++) {\n entries.push(...(flatten(obj[i]).map((v) => [`or${i || ''}-${v[0]}`, v[1]]) as [string, string][]));\n }\n\n return Object.fromEntries(entries);\n};\n\nconst _count = (\n cfg: ServiceConfig | undefined,\n endpoint: string,\n query?: CountQuery<any> & { params?: Record<any, any> },\n requestOptions?: RequestOptions\n) =>\n{\n const usePost = cfg?.usePost ?? globalConfig?.usePost\n const payload = {\n ...flattenFilter(query?.filter),\n ...flattenOrFilter(query?.or),\n ...query?.params\n }\n\n return wrapResponse(() =>\n raw(cfg, endpoint, {\n method: usePost ? 'POST' : 'GET',\n unwrap: true,\n ...(usePost ? { body: payload } : { query: payload })\n }, requestOptions)\n )\n };\n\nconst _some = (\n cfg: ServiceConfig | undefined,\n endpoint: string,\n query?: SomeQuery<any, any, any, any> & { params?: Record<any, any> },\n requestOptions?: RequestOptions\n) =>\n{\n const usePost = cfg?.usePost ?? globalConfig?.usePost\n const payload = {\n serializeNulls: query?.serializeNulls,\n additionalProperties: query?.properties?.join(','),\n properties: query?.select ? flattenSelect(query.select).join(',') : undefined,\n includeReferencedEntities: query?.include ? Object.keys(query.include).join(',') : undefined,\n ...flattenOrFilter(query?.or),\n ...flattenFilter(query?.filter),\n ...flattenSort(query?.sort),\n ...query?.params,\n ...query?.pagination\n }\n\n return wrapResponse(() =>\n raw(cfg, usePost ? `${endpoint}/query` : endpoint, {\n method: usePost ? 'POST' : 'GET',\n ...(usePost ? { body: payload } : { query: payload })\n }, requestOptions).then((data) => ({\n entities: data.result,\n references: data.referencedEntities ?? {},\n properties: data.additionalProperties ?? {}\n }))\n )\n };\n";
140
-
141
- var queriesWithQueryLanguage = "export type ComparisonOperator =\n | 'EQ'\n | 'NE'\n | 'LT'\n | 'GT'\n | 'LE'\n | 'GE'\n | 'LIKE';\n\nexport type LengthOperator = 'LENGTH';\n\nexport type ArrayOperator = 'IN';\n\nexport type NullOperator = 'NULL';\n\nexport type Operator = ComparisonOperator | ArrayOperator | NullOperator;\n\nexport type ModifierFunction = 'LOWER' | 'TRIM';\n\n// use globalThis to use typescript's 'Pick', since the SDK contains an interface which is also called 'Pick'\nexport type RequireAtLeastOne<T> = {\n [K in keyof T]-?: Required<globalThis.Pick<T, K>> & Partial<Omit<T, K>>;\n}[keyof T];\n\nexport type LengthExpr = {\n [K in LengthOperator]: {\n [K in Exclude<ComparisonOperator, 'LIKE'>]?: number\n }\n};\n\nexport type LengthExprWithModifier =\n LengthExpr &\n { [K in ComparisonOperator]?: never } &\n { [K in ArrayOperator]?: never } &\n { [K in NullOperator]?: never } &\n { [K in ModifierFunction]?: boolean };\n\nexport type FilterExpr<T> =\n { [K in ComparisonOperator]?: T } &\n { [K in ArrayOperator]?: T[] } &\n { [K in keyof LengthExpr]?: never };\n\nexport type FilterExprWithoutNull<T> =\n RequireAtLeastOne<FilterExpr<T>> &\n { [K in NullOperator]?: never } &\n { [K in ModifierFunction]?: boolean };\n\nexport type FilterExprWithNull<T> =\n FilterExpr<T> &\n { [K in NullOperator]?: boolean} &\n { [K in ModifierFunction]?: never };\n\nexport type MapOperators<T> = LengthExprWithModifier | FilterExprWithoutNull<T> | FilterExprWithNull<T>;\n\nexport type SingleFilterExpr<T> = {\n [P in keyof T]?: T[P] extends Array<infer U> | undefined\n ? U extends Record<any, any>\n ? SingleFilterExpr<U> | { NOT?: SingleFilterExpr<U> }\n : MapOperators<U>\n : T[P] extends Record<any, any> | undefined\n ? SingleFilterExpr<T[P]> | { NOT?: SingleFilterExpr<T[P]> }\n : MapOperators<T[P]>;\n};\n\nexport type QueryFilter<T> = SingleFilterExpr<T> & {\n OR?: QueryFilter<T>[];\n AND?: QueryFilter<T>[];\n NOT?: QueryFilter<T>;\n};\n\nexport type CountQuery<F> = {\n where?: QueryFilter<F>;\n};\n\nexport type SomeQuery<E, F, I, P> = {\n serializeNulls?: boolean;\n include?: QuerySelect<I>;\n properties?: P;\n where?: QueryFilter<F>;\n select?: QuerySelect<E>;\n sort?: Sort<E>[];\n pagination?: Pagination;\n};\n\nconst comparisonOperatorList: ComparisonOperator[] = [\n 'EQ',\n 'NE',\n 'LT',\n 'GT',\n 'LE',\n 'GE',\n 'LIKE'\n];\n\nconst comparisonOperatorMap: Record<Operator, string> = {\n EQ: '=',\n NE: '!=',\n LT: '<',\n GT: '>',\n LE: '<=',\n GE: '>=',\n LIKE: '~',\n IN: 'in',\n NULL: 'null'\n};\n\nconst modifierFunctionList: ModifierFunction[] = ['LOWER', 'TRIM'];\n\nconst flattenWhere = (\n obj: QueryFilter<any> = {},\n nestedPaths: string[]\n): string[] => {\n const entries: string[] = [];\n for (const [prop, propValue] of Object.entries(obj)) {\n const setModifiers = findAllModifierFunctions(propValue ?? {}, modifierFunctionList).filter(\n (modifier) => modifier[1]\n );\n if (prop === 'OR') {\n const flattedOr: string[][] = [];\n for (let i = 0; i < (obj.OR?.length ?? 0); i++) {\n flattedOr.push(flattenWhere(obj.OR?.[i], nestedPaths));\n }\n entries.push(\n `(${flattedOr\n .map((x) => {\n const joined = x.join(' and ');\n\n if (x.length > 1) {\n return `(${joined})`;\n } else {\n return joined;\n }\n })\n .join(' or ')})`\n );\n } else if (prop === 'AND') {\n const flattedAnd: string[][] = [];\n for (let i = 0; i < (obj.AND?.length ?? 0); i++) {\n flattedAnd.push(flattenWhere(obj.AND?.[i], nestedPaths));\n }\n entries.push(\n `(${flattedAnd\n .map((x) => {\n const joined = x.join(' and ');\n\n if (x.length > 1) {\n return `(${joined})`;\n } else {\n return joined;\n }\n })\n .join(' and ')})`\n );\n } else if (prop === 'NOT') {\n const flattedNot = flattenWhere(obj.NOT, nestedPaths);\n entries.push(\n `not ${flattedNot.length > 1 ? '(' : ''}${flattedNot.join(' and ')}${flattedNot.length > 1 ? ')' : ''}`\n );\n } else if (propValue) {\n for (const [operator, value] of Object.entries(propValue)) {\n if (value === undefined) continue;\n if (comparisonOperatorList.includes(operator as ComparisonOperator)) {\n entries.push(\n `${setModifiers.reduce(\n (acc, [first]) => `${first.toLowerCase()}(${acc})`,\n nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')\n )} ${comparisonOperatorMap[operator as Operator]} ${\n typeof value === 'string' ? JSON.stringify(value) : value\n }`\n );\n } else if ((operator as Operator) === 'NULL') {\n entries.push(\n `${!value ? 'not ' : ''}${nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')} ${comparisonOperatorMap[operator as Operator]}`\n );\n } else if ((operator as Operator) === 'IN') {\n if(value.length === 0) {\n entries.push('1 = 0')\n } else {\n entries.push(\n `${setModifiers.reduce(\n (acc, [first]) => `${first.toLowerCase()}(${acc})`,\n nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')\n )} ${comparisonOperatorMap[operator as Operator]} [${value.map((v: string | number) =>\n typeof v === 'string' ? JSON.stringify(v) : v\n )}]`\n );\n }\n } else if ((operator as LengthOperator) === 'LENGTH') {\n const lengthProp = `length(${setModifiers.reduce(\n (acc, [first]) => `${first.toLowerCase()}(${acc})`,\n nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')\n )})`;\n entries.push(...flattenWhere({ [lengthProp]: value } as QueryFilter<any>, []));\n } else if (\n !modifierFunctionList.includes(operator as ModifierFunction)\n && typeof value === 'object'\n ) {\n entries.push(\n ...flattenWhere(propValue as QueryFilter<any>, [\n ...nestedPaths,\n prop\n ])\n );\n break;\n }\n }\n }\n }\n return entries;\n};\n\nconst assembleFilterParam = (\n obj: QueryFilter<any> = {}\n): Record<string, string> => {\n const flattedFilter = flattenWhere(obj, []);\n return flattedFilter.length ? { filter: flattedFilter.join(' and ') } : {};\n};\n\nconst findAllModifierFunctions = (\n obj: Record<string, any>,\n types: ModifierFunction[]\n) => {\n const result: [string, any][] = [];\n for (const key in obj) {\n if (types.includes(key as ModifierFunction)) {\n result[types.indexOf(key as ModifierFunction)] = [key, obj[key]];\n }\n }\n return result.filter((modifierTuple) => modifierTuple);\n};\n\nconst _count = (\n cfg: ServiceConfig | undefined,\n endpoint: string,\n query?: CountQuery<any> & { params?: Record<any, any> },\n requestOptions?: RequestOptions\n) =>\n {\n const usePost = cfg?.usePost ?? globalConfig?.usePost\n const payload = {\n ...assembleFilterParam(query?.where),\n ...query?.params\n }\n\n return wrapResponse(() =>\n raw(cfg, endpoint, {\n unwrap: true,\n method: usePost ? 'POST' : 'GET',\n ...(usePost ? { body: payload } : { query: payload })\n }, requestOptions)\n )\n };\n\nconst _some = (\n cfg: ServiceConfig | undefined,\n endpoint: string,\n query?: SomeQuery<any, any, any, any> & { params?: Record<any, any> },\n requestOptions?: RequestOptions\n) =>\n {\n const usePost = cfg?.usePost ?? globalConfig?.usePost\n const payload = {\n serializeNulls: query?.serializeNulls,\n additionalProperties: query?.properties?.join(','),\n properties: query?.select\n ? flattenSelect(query.select).join(',')\n : undefined,\n includeReferencedEntities: query?.include\n ? Object.keys(query.include).join(',')\n : undefined,\n ...assembleFilterParam(query?.where),\n ...flattenSort(query?.sort),\n ...query?.params,\n ...query?.pagination\n }\n\n return wrapResponse(() =>\n raw(cfg, usePost ? `${endpoint}/query` : endpoint, {\n method: usePost ? 'POST' : 'GET',\n ...(usePost ? { body: payload } : { query: payload })\n }, requestOptions).then((data) => ({\n entities: data.result,\n references: data.referencedEntities ?? {},\n properties: data.additionalProperties ?? {}\n }))\n )\n };\n";
142
-
143
- var root = "export const raw = async (\n cfg: ServiceConfig | undefined,\n endpoint: string,\n payload: RequestPayload = {},\n requestOptions?: RequestOptions\n): Promise<any> => {\n if (!cfg && !globalConfig) {\n throw new Error(`ServiceConfig missing.`);\n }\n\n const localCfg = {\n ...globalConfig,\n ...cfg,\n interceptors: { ...globalConfig?.interceptors, ...cfg?.interceptors }\n };\n\n const isBinaryData = payload.body instanceof resolveBinaryObject();\n const params = new URLSearchParams(Object.entries(payload.query ?? {}).filter((v) => v[1] !== undefined)\n .map(([key, value]) => [key, typeof value === 'string' ? value : JSON.stringify(value)])\n );\n\n const protocol = getProtocol(localCfg);\n\n const interceptRequest = localCfg.interceptors?.request ?? ((v) => v);\n const interceptResponse = localCfg.interceptors?.response ?? ((v) => v);\n\n const host = getHost(localCfg);\n\n let data;\n if (!cfg && localCfg.multiRequest) {\n let ep = endpoint;\n if (endpoint.startsWith('/')) {\n ep = endpoint.replace('/', '');\n }\n data = await addRequest(`${ep}?${params}`);\n } else {\n const request = new Request(`${protocol}//${host}/webapp/api/v${apiVersion}${endpoint}?${params}`, {\n ...(payload.body && {\n body: isBinaryData\n ? payload.body\n : JSON.stringify(payload.body, (_key, value) => (value === undefined ? null : value))\n }),\n ...(!localCfg.key && { credentials: 'same-origin' }),\n method: payload.method ?? 'get',\n headers: {\n Accept: 'application/json',\n ...(localCfg.key && { AuthenticationToken: localCfg.key }),\n ...(!isBinaryData && { 'Content-Type': 'application/json' })\n }\n });\n let res = (await interceptRequest(request, payload)) ?? request;\n if (!(res instanceof Response)) {\n res = requestOptions?.signal ? await fetch(res, { signal: requestOptions.signal } ) : await fetch(res);\n }\n res = (await interceptResponse(res)) ?? res;\n\n if (res.ok) {\n data =\n payload.forceBlob || !res.headers?.get('content-type')?.includes('application/json')\n ? await res.blob()\n : await res.json();\n } else {\n data = res.headers?.get('content-type')?.includes('application/json')\n ? await res.json()\n : res;\n }\n\n // Check if response was successful\n if (!res.ok) {\n return Promise.reject(data);\n }\n }\n\n return payload.unwrap ? data.result : data;\n};\n\nconst _remove = (\n cfg: ServiceConfigWithoutMultiRequest | undefined,\n endpoint: string,\n { dryRun = false }: RemoveQuery = {},\n requestOptions?: RequestOptions\n) =>\n wrapResponse(() =>\n raw({ ...cfg, multiRequest: false }, endpoint, {\n method: 'DELETE',\n query: { dryRun }\n }, requestOptions).then(() => undefined)\n );\n\nconst _create = (cfg: ServiceConfigWithoutMultiRequest | undefined, endpoint: string, data: any, requestOptions?: RequestOptions) =>\n wrapResponse(() =>\n raw({ ...cfg, multiRequest: false }, endpoint, {\n method: 'POST',\n body: data\n }, requestOptions)\n );\n\nconst _update = (\n cfg: ServiceConfigWithoutMultiRequest | undefined,\n endpoint: string,\n data: any,\n { ignoreMissingProperties, dryRun = false }: UpdateQuery = {},\n requestOptions?: RequestOptions\n) =>\n wrapResponse(() =>\n raw({ ...cfg, multiRequest: false }, endpoint, {\n method: 'PUT',\n body: data,\n query: {\n ignoreMissingProperties:\n ignoreMissingProperties ?? cfg?.ignoreMissingProperties ?? globalConfig?.ignoreMissingProperties,\n dryRun\n }\n }, requestOptions)\n );\n\nconst _generic = (\n cfg: ServiceConfigWithoutMultiRequest | undefined,\n method: RequestPayloadMethod,\n endpoint: string,\n payload?: GenericQuery<any, any>,\n forceBlob?: boolean,\n requestOptions?: RequestOptions\n) =>\n{\n const usePost = cfg?.usePost ?? globalConfig?.usePost\n return wrapResponse(() =>\n raw({ ...cfg, multiRequest: false }, endpoint, {\n method: usePost ? 'POST' : method,\n forceBlob,\n ...(usePost && method === 'GET' ?\n { body: { ...payload?.params } }\n :\n { body: payload?.body, query: payload?.params } )\n }, requestOptions))\n};\n";
144
-
145
- var unique = "const _unique = (cfg: ServiceConfigWithoutMultiRequest | undefined, endpoint: string, query?: UniqueQuery, requestOptions?: RequestOptions) =>\n wrapResponse(() => raw({ ...cfg, multiRequest: false }, endpoint, { query }, requestOptions));\n";
146
-
147
- var types = "export type DeepPartial<T> = T extends object\n ? {\n [P in keyof T]?: DeepPartial<T[P]>;\n }\n : T;\n\nexport type Sort<T> = {\n [K in keyof T]?: {\n [V in keyof T]?: V extends K\n ? T[V] extends Array<infer U> | undefined\n ? U extends object\n ? Sort<U>\n : never\n : T[V] extends object | undefined\n ? Sort<T[V]>\n : 'asc' | 'desc'\n : never;\n };\n}[keyof T];\n\nexport type CustomAttributeFilter = {\n [K in number]:| string | number | boolean | { id: string } | { entityName: string; entityId: string };\n};\n\nexport type QuerySelect<T> = {\n [P in keyof T]?: T[P] extends Array<infer U> | undefined\n ? QuerySelect<U> | boolean\n : T[P] extends Record<any, any> | undefined\n ? QuerySelect<T[P]> | boolean\n : boolean;\n};\n\nexport type Select<T, Q extends QuerySelect<T> | undefined> =\n Q extends QuerySelect<T>\n ? {\n // Filter out excluded properties beforehand\n [P in keyof T as Q[P] extends boolean ? P : Q[P] extends object ? P : never]: // Property\n Q[P] extends true\n ? T[P]\n : // Array\n T[P] extends Array<infer U>\n ? Select<U, Q[P] & QuerySelect<any>>[]\n : // Object\n T[P] extends Record<any, any>\n ? Select<T[P], Q[P] & QuerySelect<any>>\n : never;\n }\n : undefined;\n\nexport type MapKeys<T, S extends Record<keyof T, string>> = {\n [K in keyof T as S[K]]: T[K];\n};\n\nexport type ValueOf<T> = T[keyof T];\n\nexport type Pagination = {\n page: number;\n pageSize: number;\n};\n\nexport type UniqueQuery = {\n serializeNulls?: boolean;\n};\n\nexport type SomeQueryReturn<E, R, P> = {\n entities: E[];\n references?: R;\n properties?: P[];\n};\n\nexport type GenericQuery<P, B> = {\n params?: P;\n body?: B;\n};\n\nexport type UpdateQuery = {\n ignoreMissingProperties?: boolean;\n dryRun?: boolean;\n};\n\nexport type RemoveQuery = {\n dryRun?: boolean;\n};\n\nexport type WEntityPropertyMeta =\n | {\n type: 'string';\n format?: 'decimal' | 'html' | 'email' | 'password';\n maxLength?: number;\n pattern?: string;\n entity?: WEntity;\n service?: WService;\n }\n | {\n type: 'integer';\n format: 'int32' | 'int64' | 'duration' | 'date' | 'timestamp';\n }\n | { type: 'array'; format: 'reference'; entity: WEntity; service?: WService }\n | { type: 'array'; format: 'reference'; enum: WEnum }\n | { type: 'array'; format: 'string' }\n | { type: 'number'; format: 'double' }\n | { type: 'reference'; entity: WEntity }\n | { type: 'reference'; enum: WEnum }\n | { type: 'boolean' }\n | { type: 'object' };\n";
148
-
149
- var utils = "const flattenSelect = (obj: Select<any, any> = {}): string[] => {\n const entries: string[] = [];\n\n for (const [prop, value] of Object.entries(obj)) {\n if (typeof value === 'object' && value) {\n entries.push(...flattenSelect(value).map((v) => `${prop}.${v}`));\n } else if (value) {\n entries.push(prop);\n }\n }\n\n return entries;\n};\n\nexport const flattenSort = (obj: Sort<any>[] = []): { sort?: string } => {\n const flatten = (obj: Sort<any>, base = ''): string | undefined => {\n const [key, value] = Object.entries(obj ?? {})[0] ?? [];\n\n if (key && value) {\n const path = base + key;\n\n if (typeof value === 'object') {\n return flatten(value, path ? `${path}.` : '');\n } else if (['asc', 'desc'].includes(value)) {\n return `${value === 'desc' ? '-' : ''}${path}`;\n }\n }\n\n return undefined;\n };\n\n const sorts = obj.map((v) => flatten(v)).filter(Boolean);\n return sorts.length ? { sort: sorts.join(',') } : {};\n};\n";
150
-
133
+ //#endregion
134
+ //#region src/generator/01-base/static/globalConfig.ts.txt
135
+ var globalConfig_ts_default = "export default \"export type RequestPayloadMethod =\\n | 'GET'\\n | 'HEAD'\\n | 'POST'\\n | 'PUT'\\n | 'DELETE'\\n | 'CONNECT'\\n | 'OPTIONS'\\n | 'TRACE'\\n | 'PATCH';\\n\\nexport interface RequestPayload {\\n method?: RequestPayloadMethod;\\n query?: Record<string, any>;\\n body?: any;\\n unwrap?: boolean;\\n forceBlob?: boolean;\\n}\\n\\nexport interface ServiceConfig {\\n // Your API-Key, this is optional in the sense of if you omit this, and you're in a browser, the\\n // cookie-authentication (include-credentials) will be used.\\n key?: string;\\n\\n // Your domain, if omitted location.host will be used (browser env).\\n host?: string;\\n\\n // If you want to use https, defaults to location.protocol (browser env).\\n secure?: boolean;\\n\\n // If you want that some and count requests are bundled into multi requests.\\n multiRequest?: boolean;\\n\\n // If you want that the ignoreMissingProperties parameter to be set to true for every post request.\\n ignoreMissingProperties?: boolean;\\n\\n // Optional request/response interceptors.\\n interceptors?: {\\n // Takes the generated request, you can either return a new request,\\n // a response (which will be taken as \\\"the\\\" response) or nothing.\\n // The payload contains the raw input generated by the SDK.\\n request?: (\\n request: Request,\\n payload: RequestPayload\\n ) => Request | Response | void | Promise<Request | Response | void>;\\n\\n // Takes the response. This can either be the one from the server or an\\n // artificially-crafted one by the request interceptor.\\n response?: (response: Response) => Response | void | Promise<Response | void>;\\n };\\n\\n // Whether POST should be used instead of GET for some() and count() operations\\n usePost?: boolean;\\n}\\n\\nexport interface RequestOptions {\\n signal?: AbortSignal;\\n}\\n\\ntype ServiceConfigWithoutMultiRequest = Omit<ServiceConfig, 'multiRequest'>;\\n\\nlet globalConfig: ServiceConfig | undefined;\\nexport const getGlobalConfig = (): ServiceConfig | undefined => globalConfig;\\nexport const setGlobalConfig = (cfg?: ServiceConfig) => (globalConfig = cfg);\\n\\nexport const getHost = (cfg: ServiceConfig) => {\\n let host = cfg.host?.replace(/^https?:\\\\/\\\\//, '');\\n if (!host && typeof location !== 'undefined') {\\n host = location.host;\\n }\\n\\n if (!host) {\\n throw new Error('Please specify a host');\\n }\\n\\n return host;\\n};\\n\\nexport const getProtocol = (cfg: ServiceConfig) => {\\n const protocol =\\n cfg.secure !== undefined\\n ? cfg.secure\\n ? 'https:'\\n : 'http:'\\n : typeof location !== 'undefined'\\n ? location.protocol\\n : undefined;\\n\\n if (!protocol) {\\n throw new Error('Please specify a protocol (secure)');\\n }\\n\\n return protocol;\\n};\\n\";";
136
+ //#endregion
137
+ //#region src/generator/01-base/static/multiRequest.ts.txt
138
+ var multiRequest_ts_default = "export default \"type RequestTask = {\\n uri: string;\\n resolve: (result: unknown) => void;\\n reject: (error: unknown) => void;\\n};\\n\\ntype BatchRequestTask = RequestTask & {\\n settled: boolean;\\n};\\n\\ntype MultiRequestResponse = {\\n status: number;\\n body: object;\\n};\\n\\nlet microtaskQueued: boolean = false;\\nconst tasksSet: Set<RequestTask> = new Set<RequestTask>();\\n\\nconst SQUARE_BRACKET_OPEN = '['.charCodeAt(0);\\nconst COMMA = ','.charCodeAt(0);\\nconst DECODER = new TextDecoder();\\n\\nconst readNextResponse = (bytes: Uint8Array<ArrayBuffer>) => {\\n let headerStart: number | undefined = undefined;\\n let commasSeen = 0;\\n\\n for (let i = 0; i < bytes.length; i++) {\\n const byte = bytes[i];\\n if (headerStart === undefined) {\\n if (byte === SQUARE_BRACKET_OPEN || byte === COMMA) {\\n headerStart = i + 1;\\n }\\n } else {\\n if (byte === COMMA) {\\n commasSeen++;\\n }\\n if (commasSeen === 2) {\\n const headerArrayString = `[${DECODER.decode(bytes.subarray(headerStart, i))}]`;\\n const [index, jsonLength] = JSON.parse(headerArrayString);\\n if (!(typeof index === 'number') || !(typeof jsonLength === 'number')) {\\n throw new Error(`unexpected header: ${headerArrayString}`);\\n }\\n\\n const endIndex = i + 1 + jsonLength;\\n if (endIndex > bytes.length) {\\n // not all bytes available yet\\n return undefined;\\n }\\n const jsonString = DECODER.decode(bytes.subarray(i + 1, endIndex));\\n const data = JSON.parse(jsonString) as MultiRequestResponse;\\n return {\\n index,\\n data,\\n remainingBytes: bytes.subarray(endIndex)\\n };\\n }\\n }\\n }\\n return undefined;\\n};\\n\\nconst fetchMultiRequest = async (requests: string[]) => {\\n const cfg = getGlobalConfig();\\n\\n if (!cfg) {\\n throw new Error(`ServiceConfig missing.`);\\n }\\n\\n const host = getHost(cfg);\\n const protocol = getProtocol(cfg);\\n\\n return await fetch(`${protocol}//${host}/webapp/api/v2/batch/query`, {\\n method: 'POST',\\n headers: {\\n 'Content-Type': 'application/json',\\n ...(cfg.key && { AuthenticationToken: cfg.key })\\n },\\n body: JSON.stringify({ requests })\\n });\\n};\\n\\nconst rejectTasks = (tasks: BatchRequestTask[], error: unknown) => {\\n for (const task of tasks) {\\n if (!task.settled) {\\n task.reject(error);\\n }\\n }\\n};\\n\\nconst processStream = (\\n { value: chunk, done }: ReadableStreamReadResult<Uint8Array>,\\n remainingBytes: Uint8Array,\\n reader: ReadableStreamDefaultReader<Uint8Array>,\\n tasks: BatchRequestTask[]\\n) => {\\n if (done) {\\n return;\\n }\\n if (chunk) {\\n let bytes = new Uint8Array(remainingBytes.length + chunk.length);\\n bytes.set(remainingBytes);\\n bytes.set(chunk, remainingBytes.length);\\n\\n while (bytes.length) {\\n const result = readNextResponse(bytes);\\n if (!result) {\\n break;\\n }\\n const task = tasks[result.index];\\n if (result.data.status >= 100 && result.data.status < 400) {\\n task.resolve({\\n ...result.data.body\\n });\\n } else {\\n task.reject({\\n ...result.data.body\\n });\\n }\\n task.settled = true;\\n bytes = result.remainingBytes;\\n }\\n reader\\n .read()\\n .then((readResult) => processStream(readResult, bytes, reader, tasks))\\n .catch((error) => rejectTasks(tasks, error));\\n }\\n};\\n\\nconst batch = async (tasks: BatchRequestTask[]) => {\\n try {\\n const requests = tasks.map(({ uri }) => uri);\\n const resp = await fetchMultiRequest(requests);\\n const reader = resp.body?.getReader();\\n\\n if (!reader) {\\n throw new Error('Stream reader is undefined');\\n }\\n reader\\n .read()\\n .then((readResult) => processStream(readResult, new Uint8Array(0), reader, tasks))\\n .catch((error) => rejectTasks(tasks, error));\\n } catch (e) {\\n rejectTasks(tasks, e);\\n throw e;\\n }\\n};\\n\\nconst addTask = (task: RequestTask) => {\\n tasksSet.add(task);\\n\\n if (!microtaskQueued) {\\n queueMicrotask(() => {\\n microtaskQueued = false;\\n if (tasksSet.size > 0) {\\n const batchTasks = Array.from(tasksSet).map((task) => ({ ...task, settled: false }));\\n void batch(batchTasks);\\n tasksSet.clear();\\n }\\n });\\n microtaskQueued = true;\\n }\\n};\\n\\nconst addRequest = (uri: string) => new Promise((resolve, reject) => addTask({ uri, resolve, reject }));\\n\";";
139
+ //#endregion
140
+ //#region src/generator/01-base/static/queriesWithFilter.ts.txt
141
+ var queriesWithFilter_ts_default = "export default \"export type EqualityOperator = 'EQ' | 'NE';\\n\\nexport type ComparisonOperator =\\n | 'LT'\\n | 'GT'\\n | 'LE'\\n | 'GE'\\n | 'LIKE'\\n | 'ILIKE'\\n | 'NOT_LIKE'\\n | 'NOT_ILIKE'\\n | 'IEQ'\\n | 'NOT_IEQ';\\n\\nexport type ArrayOperator = 'IN' | 'NOT_IN';\\n\\nexport type Operator = EqualityOperator | ComparisonOperator | ArrayOperator;\\n\\nexport type MapOperators<T> = { [K in EqualityOperator]?: T | null } & { [K in ComparisonOperator]?: T } & {\\n [K in ArrayOperator]?: T[];\\n};\\n\\nexport type QueryFilter<T> = {\\n [P in keyof T]?: T[P] extends Array<infer U> | undefined\\n ? U extends Record<any, any>\\n ? QueryFilter<U>\\n : MapOperators<U>\\n : T[P] extends Record<any, any> | undefined\\n ? QueryFilter<T[P]>\\n : MapOperators<T[P]>;\\n};\\n\\nexport type CountQuery<F> = {\\n filter?: QueryFilter<F>;\\n or?: (QueryFilter<F> & CustomAttributeFilter)[];\\n};\\n\\nexport type SomeQuery<E, F, I, P> = {\\n serializeNulls?: boolean;\\n include?: QuerySelect<I>;\\n properties?: P;\\n filter?: QueryFilter<F> & CustomAttributeFilter;\\n select?: QuerySelect<E>;\\n or?: (QueryFilter<F> & CustomAttributeFilter)[];\\n sort?: Sort<E>[];\\n pagination?: Pagination;\\n};\\n\\nconst equality: string[] = ['EQ', 'NE', 'IEQ', 'NOT_IEQ'];\\n\\nconst simple: string[] = [...equality, 'LT', 'GT', 'LE', 'GE', 'LIKE', 'NOT_LIKE', 'ILIKE', 'NOT_ILIKE'];\\n\\nconst array: string[] = ['IN', 'NOT_IN'];\\n\\nconst filterMap: Record<Operator, string> = {\\n EQ: 'eq',\\n NE: 'ne',\\n LT: 'lt',\\n GT: 'gt',\\n LE: 'le',\\n GE: 'ge',\\n LIKE: 'like',\\n NOT_LIKE: 'notlike',\\n ILIKE: 'ilike',\\n NOT_ILIKE: 'notilike',\\n IN: 'in',\\n NOT_IN: 'notin',\\n IEQ: 'ieq',\\n NOT_IEQ: 'notieq'\\n};\\n\\nconst flattenCustomAttributes = (obj: CustomAttributeFilter = {}): [string, string][] => {\\n const entries: [string, string][] = [];\\n\\n for (const [id, filter] of Object.entries(obj)) {\\n const key = `customAttribute${id}`;\\n\\n if (typeof filter === 'object') {\\n for (const [prop, value] of Object.entries(filter)) {\\n entries.push([`${key}.${prop}-eq`, String(value)]);\\n }\\n } else if (filter !== undefined) {\\n entries.push([`${key}-eq`, String(filter)]);\\n }\\n }\\n\\n return entries;\\n};\\n\\nconst flatten = (obj: QueryFilter<any> = {}): [string, string][] => {\\n const entries: [string, string][] = [];\\n\\n for (const [prop, propValue] of Object.entries(obj)) {\\n for (const [filter, value] of Object.entries(propValue as object)) {\\n if (value === undefined) continue;\\n\\n if (simple.includes(filter) || array.includes(filter)) {\\n if (value === null && equality.includes(filter)) {\\n entries.push([`${prop}-${filter === 'EQ' ? 'null' : 'notnull'}`, '']);\\n } else {\\n entries.push([`${prop}-${filterMap[filter as Operator]}`, value]);\\n }\\n } else {\\n entries.push(\\n ...(flatten(propValue as QueryFilter<any>).map((v) => [`${prop}.${v[0]}`, v[1]]) as [string, string][])\\n );\\n break;\\n }\\n }\\n }\\n\\n return entries;\\n};\\n\\nconst flattenFilter = (obj: QueryFilter<any> = {}): Record<string, string> => {\\n const filter: [string, any][] = [],\\n customAttributes: [string, any][] = [];\\n\\n Object.entries(obj).forEach((value) => {\\n (value[0].match(/^\\\\d+$/) ? customAttributes : filter).push(value);\\n });\\n\\n return Object.fromEntries([\\n ...flatten(Object.fromEntries(filter)),\\n ...flattenCustomAttributes(Object.fromEntries(customAttributes) as CustomAttributeFilter)\\n ]);\\n};\\n\\nconst flattenOrFilter = (obj: QueryFilter<any>[] = []): Record<string, string> => {\\n const entries: [string, any][] = [];\\n\\n for (let i = 0; i < obj.length; i++) {\\n entries.push(...(flatten(obj[i]).map((v) => [`or${i || ''}-${v[0]}`, v[1]]) as [string, string][]));\\n }\\n\\n return Object.fromEntries(entries);\\n};\\n\\nconst _count = (\\n cfg: ServiceConfig | undefined,\\n endpoint: string,\\n query?: CountQuery<any> & { params?: Record<any, any> },\\n requestOptions?: RequestOptions\\n) =>\\n{\\n const usePost = cfg?.usePost ?? globalConfig?.usePost\\n const payload = {\\n ...flattenFilter(query?.filter),\\n ...flattenOrFilter(query?.or),\\n ...query?.params\\n }\\n\\n return wrapResponse(() =>\\n raw(cfg, endpoint, {\\n method: usePost ? 'POST' : 'GET',\\n unwrap: true,\\n ...(usePost ? { body: payload } : { query: payload })\\n }, requestOptions)\\n )\\n };\\n\\nconst _some = (\\n cfg: ServiceConfig | undefined,\\n endpoint: string,\\n query?: SomeQuery<any, any, any, any> & { params?: Record<any, any> },\\n requestOptions?: RequestOptions\\n) =>\\n{\\n const usePost = cfg?.usePost ?? globalConfig?.usePost\\n const payload = {\\n serializeNulls: query?.serializeNulls,\\n additionalProperties: query?.properties?.join(','),\\n properties: query?.select ? flattenSelect(query.select).join(',') : undefined,\\n includeReferencedEntities: query?.include ? Object.keys(query.include).join(',') : undefined,\\n ...flattenOrFilter(query?.or),\\n ...flattenFilter(query?.filter),\\n ...flattenSort(query?.sort),\\n ...query?.params,\\n ...query?.pagination\\n }\\n\\n return wrapResponse(() =>\\n raw(cfg, usePost ? `${endpoint}/query` : endpoint, {\\n method: usePost ? 'POST' : 'GET',\\n ...(usePost ? { body: payload } : { query: payload })\\n }, requestOptions).then((data) => ({\\n entities: data.result,\\n references: data.referencedEntities ?? {},\\n properties: data.additionalProperties ?? {}\\n }))\\n )\\n };\\n\";";
142
+ //#endregion
143
+ //#region src/generator/01-base/static/queriesWithQueryLanguage.ts.txt
144
+ var queriesWithQueryLanguage_ts_default = "export default \"export type ComparisonOperator =\\n | 'EQ'\\n | 'NE'\\n | 'LT'\\n | 'GT'\\n | 'LE'\\n | 'GE'\\n | 'LIKE';\\n\\nexport type LengthOperator = 'LENGTH';\\n\\nexport type ArrayOperator = 'IN';\\n\\nexport type NullOperator = 'NULL';\\n\\nexport type Operator = ComparisonOperator | ArrayOperator | NullOperator;\\n\\nexport type ModifierFunction = 'LOWER' | 'TRIM';\\n\\n// use globalThis to use typescript's 'Pick', since the SDK contains an interface which is also called 'Pick'\\nexport type RequireAtLeastOne<T> = {\\n [K in keyof T]-?: Required<globalThis.Pick<T, K>> & Partial<Omit<T, K>>;\\n}[keyof T];\\n\\nexport type LengthExpr = {\\n [K in LengthOperator]: {\\n [K in Exclude<ComparisonOperator, 'LIKE'>]?: number\\n }\\n};\\n\\nexport type LengthExprWithModifier =\\n LengthExpr &\\n { [K in ComparisonOperator]?: never } &\\n { [K in ArrayOperator]?: never } &\\n { [K in NullOperator]?: never } &\\n { [K in ModifierFunction]?: boolean };\\n\\nexport type FilterExpr<T> =\\n { [K in ComparisonOperator]?: T } &\\n { [K in ArrayOperator]?: T[] } &\\n { [K in keyof LengthExpr]?: never };\\n\\nexport type FilterExprWithoutNull<T> =\\n RequireAtLeastOne<FilterExpr<T>> &\\n { [K in NullOperator]?: never } &\\n { [K in ModifierFunction]?: boolean };\\n\\nexport type FilterExprWithNull<T> =\\n FilterExpr<T> &\\n { [K in NullOperator]?: boolean} &\\n { [K in ModifierFunction]?: never };\\n\\nexport type MapOperators<T> = LengthExprWithModifier | FilterExprWithoutNull<T> | FilterExprWithNull<T>;\\n\\nexport type SingleFilterExpr<T> = {\\n [P in keyof T]?: T[P] extends Array<infer U> | undefined\\n ? U extends Record<any, any>\\n ? SingleFilterExpr<U> | { NOT?: SingleFilterExpr<U> }\\n : MapOperators<U>\\n : T[P] extends Record<any, any> | undefined\\n ? SingleFilterExpr<T[P]> | { NOT?: SingleFilterExpr<T[P]> }\\n : MapOperators<T[P]>;\\n};\\n\\nexport type QueryFilter<T> = SingleFilterExpr<T> & {\\n OR?: QueryFilter<T>[];\\n AND?: QueryFilter<T>[];\\n NOT?: QueryFilter<T>;\\n};\\n\\nexport type CountQuery<F> = {\\n where?: QueryFilter<F>;\\n};\\n\\nexport type SomeQuery<E, F, I, P> = {\\n serializeNulls?: boolean;\\n include?: QuerySelect<I>;\\n properties?: P;\\n where?: QueryFilter<F>;\\n select?: QuerySelect<E>;\\n sort?: Sort<E>[];\\n pagination?: Pagination;\\n};\\n\\nconst comparisonOperatorList: ComparisonOperator[] = [\\n 'EQ',\\n 'NE',\\n 'LT',\\n 'GT',\\n 'LE',\\n 'GE',\\n 'LIKE'\\n];\\n\\nconst comparisonOperatorMap: Record<Operator, string> = {\\n EQ: '=',\\n NE: '!=',\\n LT: '<',\\n GT: '>',\\n LE: '<=',\\n GE: '>=',\\n LIKE: '~',\\n IN: 'in',\\n NULL: 'null'\\n};\\n\\nconst modifierFunctionList: ModifierFunction[] = ['LOWER', 'TRIM'];\\n\\nconst flattenWhere = (\\n obj: QueryFilter<any> = {},\\n nestedPaths: string[]\\n): string[] => {\\n const entries: string[] = [];\\n for (const [prop, propValue] of Object.entries(obj)) {\\n const setModifiers = findAllModifierFunctions(propValue ?? {}, modifierFunctionList).filter(\\n (modifier) => modifier[1]\\n );\\n if (prop === 'OR') {\\n const flattedOr: string[][] = [];\\n for (let i = 0; i < (obj.OR?.length ?? 0); i++) {\\n flattedOr.push(flattenWhere(obj.OR?.[i], nestedPaths));\\n }\\n entries.push(\\n `(${flattedOr\\n .map((x) => {\\n const joined = x.join(' and ');\\n\\n if (x.length > 1) {\\n return `(${joined})`;\\n } else {\\n return joined;\\n }\\n })\\n .join(' or ')})`\\n );\\n } else if (prop === 'AND') {\\n const flattedAnd: string[][] = [];\\n for (let i = 0; i < (obj.AND?.length ?? 0); i++) {\\n flattedAnd.push(flattenWhere(obj.AND?.[i], nestedPaths));\\n }\\n entries.push(\\n `(${flattedAnd\\n .map((x) => {\\n const joined = x.join(' and ');\\n\\n if (x.length > 1) {\\n return `(${joined})`;\\n } else {\\n return joined;\\n }\\n })\\n .join(' and ')})`\\n );\\n } else if (prop === 'NOT') {\\n const flattedNot = flattenWhere(obj.NOT, nestedPaths);\\n entries.push(\\n `not ${flattedNot.length > 1 ? '(' : ''}${flattedNot.join(' and ')}${flattedNot.length > 1 ? ')' : ''}`\\n );\\n } else if (propValue) {\\n for (const [operator, value] of Object.entries(propValue)) {\\n if (value === undefined) continue;\\n if (comparisonOperatorList.includes(operator as ComparisonOperator)) {\\n entries.push(\\n `${setModifiers.reduce(\\n (acc, [first]) => `${first.toLowerCase()}(${acc})`,\\n nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')\\n )} ${comparisonOperatorMap[operator as Operator]} ${\\n typeof value === 'string' ? JSON.stringify(value) : value\\n }`\\n );\\n } else if ((operator as Operator) === 'NULL') {\\n entries.push(\\n `${!value ? 'not ' : ''}${nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')} ${comparisonOperatorMap[operator as Operator]}`\\n );\\n } else if ((operator as Operator) === 'IN') {\\n if(value.length === 0) {\\n entries.push('1 = 0')\\n } else {\\n entries.push(\\n `${setModifiers.reduce(\\n (acc, [first]) => `${first.toLowerCase()}(${acc})`,\\n nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')\\n )} ${comparisonOperatorMap[operator as Operator]} [${value.map((v: string | number) =>\\n typeof v === 'string' ? JSON.stringify(v) : v\\n )}]`\\n );\\n }\\n } else if ((operator as LengthOperator) === 'LENGTH') {\\n const lengthProp = `length(${setModifiers.reduce(\\n (acc, [first]) => `${first.toLowerCase()}(${acc})`,\\n nestedPaths.some((path) => path === prop) ? nestedPaths.join('.') : [...nestedPaths, prop].join('.')\\n )})`;\\n entries.push(...flattenWhere({ [lengthProp]: value } as QueryFilter<any>, []));\\n } else if (\\n !modifierFunctionList.includes(operator as ModifierFunction)\\n && typeof value === 'object'\\n ) {\\n entries.push(\\n ...flattenWhere(propValue as QueryFilter<any>, [\\n ...nestedPaths,\\n prop\\n ])\\n );\\n break;\\n }\\n }\\n }\\n }\\n return entries;\\n};\\n\\nconst assembleFilterParam = (\\n obj: QueryFilter<any> = {}\\n): Record<string, string> => {\\n const flattedFilter = flattenWhere(obj, []);\\n return flattedFilter.length ? { filter: flattedFilter.join(' and ') } : {};\\n};\\n\\nconst findAllModifierFunctions = (\\n obj: Record<string, any>,\\n types: ModifierFunction[]\\n) => {\\n const result: [string, any][] = [];\\n for (const key in obj) {\\n if (types.includes(key as ModifierFunction)) {\\n result[types.indexOf(key as ModifierFunction)] = [key, obj[key]];\\n }\\n }\\n return result.filter((modifierTuple) => modifierTuple);\\n};\\n\\nconst _count = (\\n cfg: ServiceConfig | undefined,\\n endpoint: string,\\n query?: CountQuery<any> & { params?: Record<any, any> },\\n requestOptions?: RequestOptions\\n) =>\\n {\\n const usePost = cfg?.usePost ?? globalConfig?.usePost\\n const payload = {\\n ...assembleFilterParam(query?.where),\\n ...query?.params\\n }\\n\\n return wrapResponse(() =>\\n raw(cfg, endpoint, {\\n unwrap: true,\\n method: usePost ? 'POST' : 'GET',\\n ...(usePost ? { body: payload } : { query: payload })\\n }, requestOptions)\\n )\\n };\\n\\nconst _some = (\\n cfg: ServiceConfig | undefined,\\n endpoint: string,\\n query?: SomeQuery<any, any, any, any> & { params?: Record<any, any> },\\n requestOptions?: RequestOptions\\n) =>\\n {\\n const usePost = cfg?.usePost ?? globalConfig?.usePost\\n const payload = {\\n serializeNulls: query?.serializeNulls,\\n additionalProperties: query?.properties?.join(','),\\n properties: query?.select\\n ? flattenSelect(query.select).join(',')\\n : undefined,\\n includeReferencedEntities: query?.include\\n ? Object.keys(query.include).join(',')\\n : undefined,\\n ...assembleFilterParam(query?.where),\\n ...flattenSort(query?.sort),\\n ...query?.params,\\n ...query?.pagination\\n }\\n\\n return wrapResponse(() =>\\n raw(cfg, usePost ? `${endpoint}/query` : endpoint, {\\n method: usePost ? 'POST' : 'GET',\\n ...(usePost ? { body: payload } : { query: payload })\\n }, requestOptions).then((data) => ({\\n entities: data.result,\\n references: data.referencedEntities ?? {},\\n properties: data.additionalProperties ?? {}\\n }))\\n )\\n };\\n\";";
145
+ //#endregion
146
+ //#region src/generator/01-base/static/root.ts.txt
147
+ var root_ts_default = "export default \"export const raw = async (\\n cfg: ServiceConfig | undefined,\\n endpoint: string,\\n payload: RequestPayload = {},\\n requestOptions?: RequestOptions\\n): Promise<any> => {\\n if (!cfg && !globalConfig) {\\n throw new Error(`ServiceConfig missing.`);\\n }\\n\\n const localCfg = {\\n ...globalConfig,\\n ...cfg,\\n interceptors: { ...globalConfig?.interceptors, ...cfg?.interceptors }\\n };\\n\\n const isBinaryData = payload.body instanceof resolveBinaryObject();\\n const params = new URLSearchParams(Object.entries(payload.query ?? {}).filter((v) => v[1] !== undefined)\\n .map(([key, value]) => [key, typeof value === 'string' ? value : JSON.stringify(value)])\\n );\\n\\n const protocol = getProtocol(localCfg);\\n\\n const interceptRequest = localCfg.interceptors?.request ?? ((v) => v);\\n const interceptResponse = localCfg.interceptors?.response ?? ((v) => v);\\n\\n const host = getHost(localCfg);\\n\\n let data;\\n if (!cfg && localCfg.multiRequest) {\\n let ep = endpoint;\\n if (endpoint.startsWith('/')) {\\n ep = endpoint.replace('/', '');\\n }\\n data = await addRequest(`${ep}?${params}`);\\n } else {\\n const request = new Request(`${protocol}//${host}/webapp/api/v${apiVersion}${endpoint}?${params}`, {\\n ...(payload.body && {\\n body: isBinaryData\\n ? payload.body\\n : JSON.stringify(payload.body, (_key, value) => (value === undefined ? null : value))\\n }),\\n ...(!localCfg.key && { credentials: 'same-origin' }),\\n method: payload.method ?? 'get',\\n headers: {\\n Accept: 'application/json',\\n ...(localCfg.key && { AuthenticationToken: localCfg.key }),\\n ...(!isBinaryData && { 'Content-Type': 'application/json' })\\n }\\n });\\n let res = (await interceptRequest(request, payload)) ?? request;\\n if (!(res instanceof Response)) {\\n res = requestOptions?.signal ? await fetch(res, { signal: requestOptions.signal } ) : await fetch(res);\\n }\\n res = (await interceptResponse(res)) ?? res;\\n\\n if (res.ok) {\\n data =\\n payload.forceBlob || !res.headers?.get('content-type')?.includes('application/json')\\n ? await res.blob()\\n : await res.json();\\n } else {\\n data = res.headers?.get('content-type')?.includes('application/json')\\n ? await res.json()\\n : res;\\n }\\n\\n // Check if response was successful\\n if (!res.ok) {\\n return Promise.reject(data);\\n }\\n }\\n\\n return payload.unwrap ? data.result : data;\\n};\\n\\nconst _remove = (\\n cfg: ServiceConfigWithoutMultiRequest | undefined,\\n endpoint: string,\\n { dryRun = false }: RemoveQuery = {},\\n requestOptions?: RequestOptions\\n) =>\\n wrapResponse(() =>\\n raw({ ...cfg, multiRequest: false }, endpoint, {\\n method: 'DELETE',\\n query: { dryRun }\\n }, requestOptions).then(() => undefined)\\n );\\n\\nconst _create = (cfg: ServiceConfigWithoutMultiRequest | undefined, endpoint: string, data: any, requestOptions?: RequestOptions) =>\\n wrapResponse(() =>\\n raw({ ...cfg, multiRequest: false }, endpoint, {\\n method: 'POST',\\n body: data\\n }, requestOptions)\\n );\\n\\nconst _update = (\\n cfg: ServiceConfigWithoutMultiRequest | undefined,\\n endpoint: string,\\n data: any,\\n { ignoreMissingProperties, dryRun = false }: UpdateQuery = {},\\n requestOptions?: RequestOptions\\n) =>\\n wrapResponse(() =>\\n raw({ ...cfg, multiRequest: false }, endpoint, {\\n method: 'PUT',\\n body: data,\\n query: {\\n ignoreMissingProperties:\\n ignoreMissingProperties ?? cfg?.ignoreMissingProperties ?? globalConfig?.ignoreMissingProperties,\\n dryRun\\n }\\n }, requestOptions)\\n );\\n\\nconst _generic = (\\n cfg: ServiceConfigWithoutMultiRequest | undefined,\\n method: RequestPayloadMethod,\\n endpoint: string,\\n payload?: GenericQuery<any, any>,\\n forceBlob?: boolean,\\n requestOptions?: RequestOptions\\n) =>\\n{\\n const usePost = cfg?.usePost ?? globalConfig?.usePost\\n return wrapResponse(() =>\\n raw({ ...cfg, multiRequest: false }, endpoint, {\\n method: usePost ? 'POST' : method,\\n forceBlob,\\n ...(usePost && method === 'GET' ?\\n { body: { ...payload?.params } }\\n :\\n { body: payload?.body, query: payload?.params } )\\n }, requestOptions))\\n};\\n\";";
148
+ //#endregion
149
+ //#region src/generator/01-base/static/unique.ts.txt
150
+ var unique_ts_default = "export default \"const _unique = (cfg: ServiceConfigWithoutMultiRequest | undefined, endpoint: string, query?: UniqueQuery, requestOptions?: RequestOptions) =>\\n wrapResponse(() => raw({ ...cfg, multiRequest: false }, endpoint, { query }, requestOptions));\\n\";";
151
+ //#endregion
152
+ //#region src/generator/01-base/static/types.ts.txt
153
+ var types_ts_default = "export default \"export type DeepPartial<T> = T extends object\\n ? {\\n [P in keyof T]?: DeepPartial<T[P]>;\\n }\\n : T;\\n\\nexport type Sort<T> = {\\n [K in keyof T]?: {\\n [V in keyof T]?: V extends K\\n ? T[V] extends Array<infer U> | undefined\\n ? U extends object\\n ? Sort<U>\\n : never\\n : T[V] extends object | undefined\\n ? Sort<T[V]>\\n : 'asc' | 'desc'\\n : never;\\n };\\n}[keyof T];\\n\\nexport type CustomAttributeFilter = {\\n [K in number]:| string | number | boolean | { id: string } | { entityName: string; entityId: string };\\n};\\n\\nexport type QuerySelect<T> = {\\n [P in keyof T]?: T[P] extends Array<infer U> | undefined\\n ? QuerySelect<U> | boolean\\n : T[P] extends Record<any, any> | undefined\\n ? QuerySelect<T[P]> | boolean\\n : boolean;\\n};\\n\\nexport type Select<T, Q extends QuerySelect<T> | undefined> =\\n Q extends QuerySelect<T>\\n ? {\\n // Filter out excluded properties beforehand\\n [P in keyof T as Q[P] extends boolean ? P : Q[P] extends object ? P : never]: // Property\\n Q[P] extends true\\n ? T[P]\\n : // Array\\n T[P] extends Array<infer U>\\n ? Select<U, Q[P] & QuerySelect<any>>[]\\n : // Object\\n T[P] extends Record<any, any>\\n ? Select<T[P], Q[P] & QuerySelect<any>>\\n : never;\\n }\\n : undefined;\\n\\nexport type MapKeys<T, S extends Record<keyof T, string>> = {\\n [K in keyof T as S[K]]: T[K];\\n};\\n\\nexport type ValueOf<T> = T[keyof T];\\n\\nexport type Pagination = {\\n page: number;\\n pageSize: number;\\n};\\n\\nexport type UniqueQuery = {\\n serializeNulls?: boolean;\\n};\\n\\nexport type SomeQueryReturn<E, R, P> = {\\n entities: E[];\\n references?: R;\\n properties?: P[];\\n};\\n\\nexport type GenericQuery<P, B> = {\\n params?: P;\\n body?: B;\\n};\\n\\nexport type UpdateQuery = {\\n ignoreMissingProperties?: boolean;\\n dryRun?: boolean;\\n};\\n\\nexport type RemoveQuery = {\\n dryRun?: boolean;\\n};\\n\\nexport type WEntityPropertyMeta =\\n | {\\n type: 'string';\\n format?: 'decimal' | 'html' | 'email' | 'password';\\n maxLength?: number;\\n pattern?: string;\\n entity?: WEntity;\\n service?: WService;\\n }\\n | {\\n type: 'integer';\\n format: 'int32' | 'int64' | 'duration' | 'date' | 'timestamp';\\n }\\n | { type: 'array'; format: 'reference'; entity: WEntity; service?: WService }\\n | { type: 'array'; format: 'reference'; enum: WEnum }\\n | { type: 'array'; format: 'string' }\\n | { type: 'number'; format: 'double' }\\n | { type: 'reference'; entity: WEntity }\\n | { type: 'reference'; enum: WEnum }\\n | { type: 'boolean' }\\n | { type: 'object' };\\n\";";
154
+ //#endregion
155
+ //#region src/generator/01-base/static/utils.ts.txt
156
+ var utils_ts_default = "export default \"const flattenSelect = (obj: Select<any, any> = {}): string[] => {\\n const entries: string[] = [];\\n\\n for (const [prop, value] of Object.entries(obj)) {\\n if (typeof value === 'object' && value) {\\n entries.push(...flattenSelect(value).map((v) => `${prop}.${v}`));\\n } else if (value) {\\n entries.push(prop);\\n }\\n }\\n\\n return entries;\\n};\\n\\nexport const flattenSort = (obj: Sort<any>[] = []): { sort?: string } => {\\n const flatten = (obj: Sort<any>, base = ''): string | undefined => {\\n const [key, value] = Object.entries(obj ?? {})[0] ?? [];\\n\\n if (key && value) {\\n const path = base + key;\\n\\n if (typeof value === 'object') {\\n return flatten(value, path ? `${path}.` : '');\\n } else if (['asc', 'desc'].includes(value)) {\\n return `${value === 'desc' ? '-' : ''}${path}`;\\n }\\n }\\n\\n return undefined;\\n };\\n\\n const sorts = obj.map((v) => flatten(v)).filter(Boolean);\\n return sorts.length ? { sort: sorts.join(',') } : {};\\n};\\n\";";
157
+ //#endregion
158
+ //#region src/generator/01-base/index.ts
151
159
  const resolveImports = (target) => {
152
- const imports = [];
153
- if (isRXTarget(target)) {
154
- imports.push(generateImport({ src: 'rxjs', imports: ['defer', 'Observable'] }));
155
- }
156
- return imports.join('\n');
157
- };
158
- const resolveMappings = (target) => `const wrapResponse = ${isRXTarget(target) ? 'defer' : '(v: (...args: any[]) => any) => v()'};`;
160
+ const imports = [];
161
+ if (isRXTarget(target)) imports.push(generateImport({
162
+ src: "rxjs",
163
+ imports: ["defer", "Observable"]
164
+ }));
165
+ return imports.join("\n");
166
+ };
167
+ const resolveMappings = (target) => `const wrapResponse = ${isRXTarget(target) ? "defer" : "(v: (...args: any[]) => any) => v()"};`;
159
168
  const resolveBinaryClass = (target) => `const resolveBinaryObject = () => ${resolveBinaryType(target)};`;
160
169
  const generateBase = (apiVersion, { target, useQueryLanguage, generateUnique }) => {
161
- return generateStatements(resolveImports(target), `const apiVersion = ${apiVersion}`, resolveMappings(target), resolveBinaryClass(target), globalConfig, types, utils, root, useQueryLanguage ? queriesWithQueryLanguage : queriesWithFilter, generateUnique ? unique : '', multiRequest);
170
+ return generateStatements(resolveImports(target), `const apiVersion = ${apiVersion}`, resolveMappings(target), resolveBinaryClass(target), globalConfig_ts_default, types_ts_default, utils_ts_default, root_ts_default, useQueryLanguage ? queriesWithQueryLanguage_ts_default : queriesWithFilter_ts_default, generateUnique ? unique_ts_default : "", multiRequest_ts_default);
162
171
  };
163
-
172
+ //#endregion
173
+ //#region src/ts/generateEnum.ts
164
174
  const transformKey = (s) => snakeCase(s).toUpperCase();
165
175
  const generateEnum = (name, values) => {
166
- const props = indent(values.map((v) => `${transformKey(v)} = ${generateString(v)}`).join(',\n'));
167
- return `export enum ${name} {\n${props}\n}`;
176
+ return `export enum ${name} {\n${indent(values.map((v) => `${transformKey(v)} = ${generateString(v)}`).join(",\n"))}\n}`;
168
177
  };
169
-
170
- // We can't use the pascalCase utility as it converts "cDBReminderType" to "CDbReminderType" which is incorrect.
178
+ //#endregion
179
+ //#region src/utils/case.ts
171
180
  const loosePascalCase = (str) => str[0].toUpperCase() + str.slice(1);
172
-
181
+ //#endregion
182
+ //#region src/utils/openapi/guards.ts
173
183
  const isObject = (v) => {
174
- return v !== null && typeof v === 'object' && !Array.isArray(v);
184
+ return v !== null && typeof v === "object" && !Array.isArray(v);
175
185
  };
176
186
  const isParameterObject = (v) => {
177
- return isObject(v) && typeof v.name === 'string' && typeof v.in === 'string';
187
+ return isObject(v) && typeof v.name === "string" && typeof v.in === "string";
178
188
  };
179
189
  const isReferenceObject = (v) => {
180
- return isObject(v) && typeof v.$ref === 'string';
190
+ return isObject(v) && typeof v.$ref === "string";
181
191
  };
182
192
  const isObjectSchemaObject = (v) => {
183
- return isObject(v) && v.type === 'object' && isObject(v.properties);
193
+ return isObject(v) && v.type === "object" && isObject(v.properties);
184
194
  };
185
195
  const isEnumSchemaObject = (v) => {
186
- return isObject(v) && v.type === 'string' && Array.isArray(v.enum);
196
+ return isObject(v) && v.type === "string" && Array.isArray(v.enum);
187
197
  };
188
198
  const isArraySchemaObject = (v) => {
189
- return isObject(v) && v.type === 'array' && typeof v.items === 'object';
199
+ return isObject(v) && v.type === "array" && typeof v.items === "object";
190
200
  };
191
201
  const isResponseObject = (v) => {
192
- return isObject(v) && typeof v.description === 'string';
202
+ return isObject(v) && typeof v.description === "string";
193
203
  };
194
-
204
+ //#endregion
205
+ //#region src/generator/02-enums/index.ts
195
206
  const generateEnums = (context) => {
196
- const enums = new Map();
197
- for (const [schemaName, schema] of context.schemas) {
198
- if (isEnumSchemaObject(schema)) {
199
- const enumName = loosePascalCase(schemaName);
200
- if (!enums.has(enumName)) {
201
- enums.set(enumName, {
202
- name: enumName,
203
- properties: schema.enum,
204
- source: generateEnum(enumName, schema.enum)
205
- });
206
- }
207
- }
208
- }
209
- return enums;
210
- };
211
-
212
- const concat = (strings, separator = ', ', maxLength = 80) => {
213
- const joined = strings.join(separator);
214
- if (joined.length > maxLength) {
215
- const length = strings.length - 1;
216
- return `\n${indent(strings.map((value, index) => (index === length ? value : `${(value + separator).trim()}\n`)).join(''))}\n`;
217
- }
218
- else {
219
- return joined;
220
- }
221
- };
222
-
207
+ const enums = /* @__PURE__ */ new Map();
208
+ for (const [schemaName, schema] of context.schemas) if (isEnumSchemaObject(schema)) {
209
+ const enumName = loosePascalCase(schemaName);
210
+ if (!enums.has(enumName)) enums.set(enumName, {
211
+ name: enumName,
212
+ properties: schema.enum,
213
+ source: generateEnum(enumName, schema.enum)
214
+ });
215
+ }
216
+ return enums;
217
+ };
218
+ //#endregion
219
+ //#region src/utils/concat.ts
220
+ const concat = (strings, separator = ", ", maxLength = 80) => {
221
+ const joined = strings.join(separator);
222
+ if (joined.length > maxLength) {
223
+ const length = strings.length - 1;
224
+ return `\n${indent(strings.map((value, index) => index === length ? value : `${(value + separator).trim()}\n`).join(""))}\n`;
225
+ } else return joined;
226
+ };
227
+ //#endregion
228
+ //#region src/utils/openapi/convertParametersToSchemaObject.ts
223
229
  const convertParametersToSchemaObject = (parameters) => {
224
- const properties = [];
225
- const required = [];
226
- for (const param of parameters) {
227
- if (param.in === 'query' && param.schema) {
228
- properties.push([param.name, param.schema]);
229
- if (param.required)
230
- required.push(param.name);
231
- }
232
- }
233
- return {
234
- type: 'object',
235
- properties: Object.fromEntries(properties),
236
- required
237
- };
238
- };
239
-
230
+ const properties = [];
231
+ const required = [];
232
+ for (const param of parameters) if (param.in === "query" && param.schema) {
233
+ properties.push([param.name, param.schema]);
234
+ if (param.required) required.push(param.name);
235
+ }
236
+ return {
237
+ type: "object",
238
+ properties: Object.fromEntries(properties),
239
+ required
240
+ };
241
+ };
242
+ //#endregion
243
+ //#region src/utils/openapi/convertToTypeScriptType.ts
240
244
  const createReferenceType = (value) => ({
241
- type: 'reference',
242
- toString: () => loosePascalCase(value)
245
+ type: "reference",
246
+ toString: () => loosePascalCase(value)
243
247
  });
244
248
  const createRawType = (value) => ({
245
- type: 'raw',
246
- toString: () => value
249
+ type: "raw",
250
+ toString: () => value
247
251
  });
248
252
  const createArrayType = (value) => ({
249
- type: 'array',
250
- toString: () => `(${value.toString()})[]`
253
+ type: "array",
254
+ toString: () => `(${value.toString()})[]`
251
255
  });
252
256
  const createTupleType = (value) => ({
253
- type: 'tuple',
254
- toString: () => concat([...new Set(value.map((v) => (typeof v === 'string' ? `'${v}'` : v.toString())))], ' | ')
257
+ type: "tuple",
258
+ toString: () => concat([...new Set(value.map((v) => typeof v === "string" ? `'${v}'` : v.toString()))], " | ")
255
259
  });
256
260
  const createObjectType = (value, required = []) => ({
257
- type: 'object',
258
- isFullyOptional: () => {
259
- return (!required.length &&
260
- Object.values(value)
261
- .filter((v) => v?.type === 'object')
262
- .every((v) => v.isFullyOptional()));
263
- },
264
- toString: (propertyPropagationOption = 'ignore') => {
265
- const properties = Object.entries(value)
266
- .filter((v) => v[1])
267
- .map((v) => {
268
- const name = v[0];
269
- const value = v[1];
270
- const isRequired = required.includes(name) ||
271
- propertyPropagationOption === 'force' ||
272
- (value.type === 'object' && !value.isFullyOptional() && propertyPropagationOption === 'propagate');
273
- return `${name + (isRequired ? '' : '?')}: ${value.toString()};`;
274
- });
275
- return properties.length ? `{\n${indent(properties.join('\n'))}\n}` : '{}';
276
- }
261
+ type: "object",
262
+ isFullyOptional: () => {
263
+ return !required.length && Object.values(value).filter((v) => v?.type === "object").every((v) => v.isFullyOptional());
264
+ },
265
+ toString: (propertyPropagationOption = "ignore") => {
266
+ const properties = Object.entries(value).filter((v) => v[1]).map((v) => {
267
+ const name = v[0];
268
+ const value = v[1];
269
+ return `${name + (required.includes(name) || propertyPropagationOption === "force" || value.type === "object" && !value.isFullyOptional() && propertyPropagationOption === "propagate" ? "" : "?")}: ${value.toString()};`;
270
+ });
271
+ return properties.length ? `{\n${indent(properties.join("\n"))}\n}` : "{}";
272
+ }
277
273
  });
278
274
  const getRefName = (obj) => {
279
- return obj.$ref.replace(/.*\//, '');
275
+ return obj.$ref.replace(/.*\//, "");
280
276
  };
281
277
  const convertToTypeScriptType = (schema) => {
282
- if (Array.isArray(schema)) {
283
- return convertToTypeScriptType(convertParametersToSchemaObject(schema));
284
- }
285
- else if (isReferenceObject(schema)) {
286
- return createReferenceType(getRefName(schema));
287
- }
288
- else {
289
- switch (schema.type) {
290
- case 'integer':
291
- case 'number':
292
- return createRawType('number');
293
- case 'string':
294
- if (schema.enum) {
295
- return createTupleType(schema.enum);
296
- }
297
- else {
298
- return schema.format === 'binary' ? createRawType('binary') : createRawType('string');
299
- }
300
- case 'boolean':
301
- return createRawType('boolean');
302
- case 'object': {
303
- const { properties = {}, required = [] } = schema;
304
- return createObjectType(Object.fromEntries(Object.entries(properties).map(([prop, propSchema]) => [prop, convertToTypeScriptType(propSchema)])), required);
305
- }
306
- case 'array':
307
- return createArrayType(convertToTypeScriptType(schema.items));
308
- default:
309
- return createRawType('unknown');
310
- }
311
- }
312
- };
313
-
278
+ if (Array.isArray(schema)) return convertToTypeScriptType(convertParametersToSchemaObject(schema));
279
+ else if (isReferenceObject(schema)) return createReferenceType(getRefName(schema));
280
+ else switch (schema.type) {
281
+ case "integer":
282
+ case "number": return createRawType("number");
283
+ case "string": if (schema.enum) return createTupleType(schema.enum);
284
+ else return schema.format === "binary" ? createRawType("binary") : createRawType("string");
285
+ case "boolean": return createRawType("boolean");
286
+ case "object": {
287
+ const { properties = {}, required = [] } = schema;
288
+ return createObjectType(Object.fromEntries(Object.entries(properties).map(([prop, propSchema]) => [prop, convertToTypeScriptType(propSchema)])), required);
289
+ }
290
+ case "array": return createArrayType(convertToTypeScriptType(schema.items));
291
+ default: return createRawType("unknown");
292
+ }
293
+ };
294
+ //#endregion
295
+ //#region src/generator/03-entities/utils/extractPropertyMetaData.ts
314
296
  const setReferenceMeta = (prop, metaData, context) => {
315
- const referenceName = getRefName(prop);
316
- const referenceSchema = context.schemas.get(referenceName);
317
- if (isEnumSchemaObject(referenceSchema)) {
318
- metaData.enum = loosePascalCase(referenceName);
319
- }
320
- else {
321
- metaData.entity = referenceName;
322
- }
297
+ const referenceName = getRefName(prop);
298
+ if (isEnumSchemaObject(context.schemas.get(referenceName))) metaData.enum = loosePascalCase(referenceName);
299
+ else metaData.entity = referenceName;
323
300
  };
324
301
  const extractPropertyMetaData = (prop, context) => {
325
- const metaData = {};
326
- const weclappExtension = prop['x-weclapp'];
327
- if (weclappExtension) {
328
- metaData.service = weclappExtension.service;
329
- metaData.entity = weclappExtension.entity;
330
- }
331
- if (isReferenceObject(prop)) {
332
- metaData.type = 'reference';
333
- setReferenceMeta(prop, metaData, context);
334
- }
335
- else {
336
- metaData.type = prop.type;
337
- metaData.format = prop.format;
338
- metaData.maxLength = prop.maxLength;
339
- metaData.pattern = prop.pattern;
340
- if (isArraySchemaObject(prop)) {
341
- if (isReferenceObject(prop.items)) {
342
- metaData.format = 'reference';
343
- setReferenceMeta(prop.items, metaData, context);
344
- }
345
- else {
346
- metaData.format = 'string';
347
- }
348
- }
349
- }
350
- return metaData;
351
- };
352
-
302
+ const metaData = {};
303
+ const weclappExtension = prop["x-weclapp"];
304
+ if (weclappExtension) {
305
+ metaData.service = weclappExtension.service;
306
+ metaData.entity = weclappExtension.entity;
307
+ }
308
+ if (isReferenceObject(prop)) {
309
+ metaData.type = "reference";
310
+ setReferenceMeta(prop, metaData, context);
311
+ } else {
312
+ metaData.type = prop.type;
313
+ metaData.format = prop.format;
314
+ metaData.maxLength = prop.maxLength;
315
+ metaData.pattern = prop.pattern;
316
+ if (isArraySchemaObject(prop)) if (isReferenceObject(prop.items)) {
317
+ metaData.format = "reference";
318
+ setReferenceMeta(prop.items, metaData, context);
319
+ } else metaData.format = "string";
320
+ }
321
+ return metaData;
322
+ };
323
+ //#endregion
324
+ //#region src/ts/generateComment.ts
353
325
  const generateInlineComment = (comment) => `/** ${comment} */`;
354
- const generateBlockComment = (comment, body) => `/**\n${comment.trim().replace(/^ */gm, ' * ')}\n */${body ? `\n${body}` : ''}`;
355
-
326
+ const generateBlockComment = (comment, body) => `/**\n${comment.trim().replace(/^ */gm, " * ")}\n */${body ? `\n${body}` : ""}`;
327
+ //#endregion
328
+ //#region src/ts/generateType.ts
356
329
  const generateType = (name, value) => {
357
- return `export type ${name} = ${value.trim()};`;
330
+ return `export type ${name} = ${value.trim()};`;
358
331
  };
359
-
360
- const arrayify = (v) => (Array.isArray(v) ? v : [v]);
361
-
332
+ //#endregion
333
+ //#region src/utils/arrayify.ts
334
+ const arrayify = (v) => Array.isArray(v) ? v : [v];
335
+ //#endregion
336
+ //#region src/ts/generateInterface.ts
362
337
  const generateInterfaceProperties = (entries) => {
363
- const properties = entries
364
- .filter((v) => v.type !== undefined)
365
- .filter((value, index, array) => array.findIndex((v) => v.name === value.name) === index)
366
- .map(({ name, type, required, readonly, comment }) => {
367
- const cmd = comment ? `${generateInlineComment(comment)}\n` : '';
368
- const req = required ? '' : '?';
369
- const rol = readonly ? 'readonly ' : '';
370
- return `${cmd + rol + name + req}: ${type};`;
371
- })
372
- .join('\n');
373
- return properties.length ? `{\n${indent(properties)}\n}` : `{}`;
338
+ const properties = entries.filter((v) => v.type !== void 0).filter((value, index, array) => array.findIndex((v) => v.name === value.name) === index).map(({ name, type, required, readonly, comment }) => {
339
+ const cmd = comment ? `${generateInlineComment(comment)}\n` : "";
340
+ const req = required ? "" : "?";
341
+ return `${cmd + (readonly ? "readonly " : "") + name + req}: ${type};`;
342
+ }).join("\n");
343
+ return properties.length ? `{\n${indent(properties)}\n}` : `{}`;
374
344
  };
375
345
  const generateInterfaceFromObject = (name, obj, propertyPropagationOption) => `export interface ${name} ${obj.toString(propertyPropagationOption)}`;
376
346
  const generateInterface = (name, entries, extend) => {
377
- const signature = `${name} ${extend ? `extends ${arrayify(extend).join(', ')}` : ''}`.trim();
378
- const body = generateInterfaceProperties(entries);
379
- return `export interface ${signature} ${body}`;
347
+ return `export interface ${`${name} ${extend ? `extends ${arrayify(extend).join(", ")}` : ""}`.trim()} ${generateInterfaceProperties(entries)}`;
380
348
  };
381
349
  const generateInterfaceType = (name, entries, extend) => {
382
- const body = generateInterfaceProperties(entries);
383
- const bases = extend ? arrayify(extend).join(' & ') : undefined;
384
- let typeDefinition = '';
385
- if (bases) {
386
- typeDefinition = bases;
387
- }
388
- else {
389
- typeDefinition = body;
390
- }
391
- if (bases && body !== '{}') {
392
- typeDefinition += ` & ${body}`;
393
- }
394
- return generateType(name, typeDefinition);
395
- };
396
-
350
+ const body = generateInterfaceProperties(entries);
351
+ const bases = extend ? arrayify(extend).join(" & ") : void 0;
352
+ let typeDefinition = "";
353
+ if (bases) typeDefinition = bases;
354
+ else typeDefinition = body;
355
+ if (bases && body !== "{}") typeDefinition += ` & ${body}`;
356
+ return generateType(name, typeDefinition);
357
+ };
358
+ //#endregion
359
+ //#region src/utils/pluralize.ts
397
360
  /**
398
- * Pluralizes a word, most of the time correct.
399
- * @param s String to pluralize.
400
- */
361
+ * Pluralizes a word, most of the time correct.
362
+ * @param s String to pluralize.
363
+ */
401
364
  const pluralize = (s) => {
402
- return s.endsWith('s') ? s : s.endsWith('y') ? `${s.slice(0, -1)}ies` : `${s}s`;
403
- };
404
-
405
- const logger = new (class {
406
- active = true;
407
- warnings = 0;
408
- errors = 0;
409
- write(str = '') {
410
- process.stdout.write(str);
411
- }
412
- blankLn(str = '') {
413
- this.blank(`${str}\n`);
414
- }
415
- warnLn(str) {
416
- this.warn(`${str}\n`);
417
- }
418
- errorLn(str) {
419
- this.error(`${str}\n`);
420
- }
421
- successLn(str) {
422
- this.success(`${str}\n`);
423
- }
424
- infoLn(str) {
425
- this.info(`${str}\n`);
426
- }
427
- debugLn(str) {
428
- this.debug(`${str}\n`);
429
- }
430
- blank(str) {
431
- this.write(str);
432
- }
433
- warn(str) {
434
- this.write(`${chalk.yellowBright('[!]')} ${str}`);
435
- this.warnings++;
436
- }
437
- error(str) {
438
- this.write(`${chalk.redBright('[X]')} ${str}`);
439
- this.errors++;
440
- }
441
- success(str) {
442
- this.write(`${chalk.greenBright('[✓]')} ${str}`);
443
- }
444
- info(str) {
445
- this.write(`${chalk.blueBright('[i]')} ${str}`);
446
- }
447
- debug(str) {
448
- this.write(`[-] ${str}`);
449
- }
450
- printSummary() {
451
- const format = (v, name, fail, ok) => {
452
- const color = v ? fail : ok;
453
- return v === 0
454
- ? `${color('zero')} ${pluralize(name)}`
455
- : v === 1
456
- ? `${color('one')} ${name}`
457
- : `${color(v)} ${pluralize(name)}`;
458
- };
459
- const warnings = format(this.warnings, 'warning', chalk.yellowBright, chalk.greenBright);
460
- const errors = format(this.errors, 'error', chalk.redBright, chalk.greenBright);
461
- const info = `Finished with ${warnings} and ${errors}.`;
462
- this[this.errors ? 'errorLn' : this.warnings ? 'warnLn' : 'successLn'](info);
463
- }
464
- })();
465
-
466
- const FILTER_PROPS_SUFFIX = 'Filter_Props';
365
+ return s.endsWith("s") ? s : s.endsWith("y") ? `${s.slice(0, -1)}ies` : `${s}s`;
366
+ };
367
+ //#endregion
368
+ //#region src/utils/logger.ts
369
+ const logger = new class {
370
+ active = true;
371
+ warnings = 0;
372
+ errors = 0;
373
+ write(str = "") {
374
+ process.stdout.write(str);
375
+ }
376
+ blankLn(str = "") {
377
+ this.blank(`${str}\n`);
378
+ }
379
+ warnLn(str) {
380
+ this.warn(`${str}\n`);
381
+ }
382
+ errorLn(str) {
383
+ this.error(`${str}\n`);
384
+ }
385
+ successLn(str) {
386
+ this.success(`${str}\n`);
387
+ }
388
+ infoLn(str) {
389
+ this.info(`${str}\n`);
390
+ }
391
+ debugLn(str) {
392
+ this.debug(`${str}\n`);
393
+ }
394
+ blank(str) {
395
+ this.write(str);
396
+ }
397
+ warn(str) {
398
+ this.write(`${chalk.yellowBright("[!]")} ${str}`);
399
+ this.warnings++;
400
+ }
401
+ error(str) {
402
+ this.write(`${chalk.redBright("[X]")} ${str}`);
403
+ this.errors++;
404
+ }
405
+ success(str) {
406
+ this.write(`${chalk.greenBright("[✓]")} ${str}`);
407
+ }
408
+ info(str) {
409
+ this.write(`${chalk.blueBright("[i]")} ${str}`);
410
+ }
411
+ debug(str) {
412
+ this.write(`[-] ${str}`);
413
+ }
414
+ printSummary() {
415
+ const format = (v, name, fail, ok) => {
416
+ const color = v ? fail : ok;
417
+ return v === 0 ? `${color("zero")} ${pluralize(name)}` : v === 1 ? `${color("one")} ${name}` : `${color(v)} ${pluralize(name)}`;
418
+ };
419
+ const info = `Finished with ${format(this.warnings, "warning", chalk.yellowBright, chalk.greenBright)} and ${format(this.errors, "error", chalk.redBright, chalk.greenBright)}.`;
420
+ this[this.errors ? "errorLn" : this.warnings ? "warnLn" : "successLn"](info);
421
+ }
422
+ }();
423
+ //#endregion
424
+ //#region src/generator/03-entities/index.ts
425
+ const FILTER_PROPS_SUFFIX = "Filter_Props";
467
426
  const generateEntities = (context) => {
468
- const entities = new Map();
469
- for (const [schemaName, schema] of context.schemas) {
470
- // Enums are generated separately
471
- if (isEnumSchemaObject(schema)) {
472
- continue;
473
- }
474
- const entityName = schemaName;
475
- const entityInterfaceName = loosePascalCase(entityName);
476
- const entityInterfaceProperties = [];
477
- const properties = new Map();
478
- let parentEntityName = undefined;
479
- let parentEntityInterfaceName = undefined;
480
- const entityFilterInterfaceName = `${entityInterfaceName}_${FILTER_PROPS_SUFFIX}`;
481
- const entityFilterInterfaceProperties = [];
482
- let parentEntityFilterInterfaceName = undefined;
483
- const processProperties = (props = {}) => {
484
- for (const [propertyName, propertySchema] of Object.entries(props)) {
485
- const weclappExtension = propertySchema['x-weclapp'];
486
- properties.set(propertyName, extractPropertyMetaData(propertySchema, context));
487
- const type = convertToTypeScriptType(propertySchema).toString();
488
- // cast to SchemaObject to access deprecated and readOnly properties (ReferenceObject can also include these props in OpenAPI 3.1)
489
- const castedSchema = propertySchema;
490
- const comment = castedSchema.deprecated
491
- ? '@deprecated will be removed.'
492
- : castedSchema.format
493
- ? `format: ${castedSchema.format}`
494
- : undefined;
495
- if (weclappExtension?.filterable !== false) {
496
- entityFilterInterfaceProperties.push({ name: propertyName, type, comment });
497
- }
498
- entityInterfaceProperties.push({
499
- name: propertyName,
500
- type,
501
- required: weclappExtension?.required,
502
- readonly: castedSchema.readOnly,
503
- comment
504
- });
505
- }
506
- };
507
- const processExtraFilterProperties = (props = {}) => {
508
- for (const [propertyName, propertySchema] of Object.entries(props)) {
509
- if (isReferenceObject(propertySchema))
510
- continue;
511
- const type = convertToTypeScriptType(propertySchema).toString();
512
- const comment = propertySchema.deprecated
513
- ? '@deprecated will be removed.'
514
- : propertySchema.format
515
- ? `format: ${propertySchema.format}`
516
- : undefined;
517
- entityFilterInterfaceProperties.push({ name: propertyName, type, comment });
518
- }
519
- };
520
- const processFilterPaths = (filterPaths = {}) => {
521
- for (const [filterProp, entityName] of Object.entries(filterPaths)) {
522
- if (!filterProp.includes('.') && context.schemas.get(entityName)) {
523
- entityFilterInterfaceProperties.push({
524
- name: filterProp,
525
- type: `${loosePascalCase(entityName)}_${FILTER_PROPS_SUFFIX}`
526
- });
527
- }
528
- }
529
- };
530
- if (schema.allOf?.length) {
531
- if (schema.allOf.length > 2) {
532
- logger.errorLn(`Failed to process schema for ${schemaName}: invalid allOf length`);
533
- continue;
534
- }
535
- for (const item of schema.allOf) {
536
- if (isReferenceObject(item)) {
537
- parentEntityName = getRefName(item);
538
- parentEntityInterfaceName = createReferenceType(parentEntityName).toString();
539
- parentEntityFilterInterfaceName = `${parentEntityInterfaceName}_${FILTER_PROPS_SUFFIX}`;
540
- }
541
- else if (item.type === 'object') {
542
- processProperties(item.properties);
543
- processExtraFilterProperties(item['x-weclapp-filterProperties']);
544
- processFilterPaths(item['x-weclapp-filterPaths']);
545
- }
546
- else {
547
- logger.errorLn(`Failed to process schema for ${schemaName}: invalid schema type in allOf`);
548
- }
549
- }
550
- }
551
- else {
552
- processProperties(schema.properties);
553
- }
554
- entities.set(entityName, {
555
- name: entityName,
556
- interfaceName: entityInterfaceName,
557
- properties,
558
- source: generateStatements(generateInterface(entityInterfaceName, entityInterfaceProperties, parentEntityInterfaceName)),
559
- filterInterfaceName: entityFilterInterfaceName,
560
- filterSource: generateStatements(generateInterface(entityFilterInterfaceName, entityFilterInterfaceProperties, parentEntityFilterInterfaceName)),
561
- parentName: parentEntityName,
562
- parentInterfaceName: parentEntityInterfaceName
563
- });
564
- }
565
- return entities;
566
- };
567
-
427
+ const entities = /* @__PURE__ */ new Map();
428
+ for (const [schemaName, schema] of context.schemas) {
429
+ if (isEnumSchemaObject(schema)) continue;
430
+ const entityName = schemaName;
431
+ const entityInterfaceName = loosePascalCase(entityName);
432
+ const entityInterfaceProperties = [];
433
+ const properties = /* @__PURE__ */ new Map();
434
+ let parentEntityName = void 0;
435
+ let parentEntityInterfaceName = void 0;
436
+ const entityFilterInterfaceName = `${entityInterfaceName}_${FILTER_PROPS_SUFFIX}`;
437
+ const entityFilterInterfaceProperties = [];
438
+ let parentEntityFilterInterfaceName = void 0;
439
+ const processProperties = (props = {}) => {
440
+ for (const [propertyName, propertySchema] of Object.entries(props)) {
441
+ const weclappExtension = propertySchema["x-weclapp"];
442
+ properties.set(propertyName, extractPropertyMetaData(propertySchema, context));
443
+ const type = convertToTypeScriptType(propertySchema).toString();
444
+ const castedSchema = propertySchema;
445
+ const comment = castedSchema.deprecated ? "@deprecated will be removed." : castedSchema.format ? `format: ${castedSchema.format}` : void 0;
446
+ if (weclappExtension?.filterable !== false) entityFilterInterfaceProperties.push({
447
+ name: propertyName,
448
+ type,
449
+ comment
450
+ });
451
+ entityInterfaceProperties.push({
452
+ name: propertyName,
453
+ type,
454
+ required: weclappExtension?.required,
455
+ readonly: castedSchema.readOnly,
456
+ comment
457
+ });
458
+ }
459
+ };
460
+ const processExtraFilterProperties = (props = {}) => {
461
+ for (const [propertyName, propertySchema] of Object.entries(props)) {
462
+ if (isReferenceObject(propertySchema)) continue;
463
+ const type = convertToTypeScriptType(propertySchema).toString();
464
+ const comment = propertySchema.deprecated ? "@deprecated will be removed." : propertySchema.format ? `format: ${propertySchema.format}` : void 0;
465
+ entityFilterInterfaceProperties.push({
466
+ name: propertyName,
467
+ type,
468
+ comment
469
+ });
470
+ }
471
+ };
472
+ const processFilterPaths = (filterPaths = {}) => {
473
+ for (const [filterProp, entityName] of Object.entries(filterPaths)) if (!filterProp.includes(".") && context.schemas.get(entityName)) entityFilterInterfaceProperties.push({
474
+ name: filterProp,
475
+ type: `${loosePascalCase(entityName)}_${FILTER_PROPS_SUFFIX}`
476
+ });
477
+ };
478
+ if (schema.allOf?.length) {
479
+ if (schema.allOf.length > 2) {
480
+ logger.errorLn(`Failed to process schema for ${schemaName}: invalid allOf length`);
481
+ continue;
482
+ }
483
+ for (const item of schema.allOf) if (isReferenceObject(item)) {
484
+ parentEntityName = getRefName(item);
485
+ parentEntityInterfaceName = createReferenceType(parentEntityName).toString();
486
+ parentEntityFilterInterfaceName = `${parentEntityInterfaceName}_${FILTER_PROPS_SUFFIX}`;
487
+ } else if (item.type === "object") {
488
+ processProperties(item.properties);
489
+ processExtraFilterProperties(item["x-weclapp-filterProperties"]);
490
+ processFilterPaths(item["x-weclapp-filterPaths"]);
491
+ } else logger.errorLn(`Failed to process schema for ${schemaName}: invalid schema type in allOf`);
492
+ } else processProperties(schema.properties);
493
+ entities.set(entityName, {
494
+ name: entityName,
495
+ interfaceName: entityInterfaceName,
496
+ properties,
497
+ source: generateStatements(generateInterface(entityInterfaceName, entityInterfaceProperties, parentEntityInterfaceName)),
498
+ filterInterfaceName: entityFilterInterfaceName,
499
+ filterSource: generateStatements(generateInterface(entityFilterInterfaceName, entityFilterInterfaceProperties, parentEntityFilterInterfaceName)),
500
+ parentName: parentEntityName,
501
+ parentInterfaceName: parentEntityInterfaceName
502
+ });
503
+ }
504
+ return entities;
505
+ };
506
+ //#endregion
507
+ //#region src/utils/weclapp/parseEndpointPath.ts
568
508
  /**
569
- * ROOT => /article
570
- * COUNT => /article/count
571
- * ENTITY => /article/{id}
572
- * SPECIAL_ROOT => /article/generateImage
573
- * SPECIAL_ENTITY => /article/id/{id}/generateImag
574
- */
575
- var WeclappEndpointType;
576
- (function (WeclappEndpointType) {
577
- WeclappEndpointType["ROOT"] = "ROOT";
578
- WeclappEndpointType["COUNT"] = "COUNT";
579
- WeclappEndpointType["ENTITY"] = "ENTITY";
580
- WeclappEndpointType["GENERIC_ROOT"] = "GENERIC_ROOT";
581
- WeclappEndpointType["GENERIC_ENTITY"] = "GENERIC_ENTITY";
582
- })(WeclappEndpointType || (WeclappEndpointType = {}));
509
+ * ROOT => /article
510
+ * COUNT => /article/count
511
+ * ENTITY => /article/{id}
512
+ * SPECIAL_ROOT => /article/generateImage
513
+ * SPECIAL_ENTITY => /article/id/{id}/generateImag
514
+ */
515
+ let WeclappEndpointType = /* @__PURE__ */ function(WeclappEndpointType) {
516
+ WeclappEndpointType["ROOT"] = "ROOT";
517
+ WeclappEndpointType["COUNT"] = "COUNT";
518
+ WeclappEndpointType["ENTITY"] = "ENTITY";
519
+ WeclappEndpointType["GENERIC_ROOT"] = "GENERIC_ROOT";
520
+ WeclappEndpointType["GENERIC_ENTITY"] = "GENERIC_ENTITY";
521
+ return WeclappEndpointType;
522
+ }({});
583
523
  const parseEndpointPath = (path) => {
584
- const [, service, ...rest] = path.split('/');
585
- if (!service) {
586
- return undefined;
587
- }
588
- if (!rest.length) {
589
- return { path, service, type: WeclappEndpointType.ROOT };
590
- }
591
- else if (rest[0] === 'count') {
592
- return { path, service, type: WeclappEndpointType.COUNT };
593
- }
594
- else if (rest[0] === 'id') {
595
- return rest.length === 2
596
- ? { path, service, type: WeclappEndpointType.ENTITY }
597
- : {
598
- path,
599
- service,
600
- method: rest[2],
601
- type: WeclappEndpointType.GENERIC_ENTITY
602
- };
603
- }
604
- else if (rest.length === 1) {
605
- return {
606
- path,
607
- service,
608
- method: rest[1],
609
- type: WeclappEndpointType.GENERIC_ROOT
610
- };
611
- }
612
- return undefined;
524
+ const [, service, ...rest] = path.split("/");
525
+ if (!service) return;
526
+ if (!rest.length) return {
527
+ path,
528
+ service,
529
+ type: WeclappEndpointType.ROOT
530
+ };
531
+ else if (rest[0] === "count") return {
532
+ path,
533
+ service,
534
+ type: WeclappEndpointType.COUNT
535
+ };
536
+ else if (rest[0] === "id") return rest.length === 2 ? {
537
+ path,
538
+ service,
539
+ type: WeclappEndpointType.ENTITY
540
+ } : {
541
+ path,
542
+ service,
543
+ method: rest[2],
544
+ type: WeclappEndpointType.GENERIC_ENTITY
545
+ };
546
+ else if (rest.length === 1) return {
547
+ path,
548
+ service,
549
+ method: rest[1],
550
+ type: WeclappEndpointType.GENERIC_ROOT
551
+ };
613
552
  };
614
553
  const isMultiPartUploadPath = (path) => {
615
- const [, entity, ...rest] = path.split('/');
616
- return entity && rest.length === 2 && rest[1] === 'multipartUpload';
554
+ const [, entity, ...rest] = path.split("/");
555
+ return entity && rest.length === 2 && rest[1] === "multipartUpload";
617
556
  };
618
557
  const parseEndpointsPaths = (paths) => {
619
- const endpoints = new Map();
620
- for (const [rawPath, path] of Object.entries(paths)) {
621
- const endpoint = parseEndpointPath(rawPath);
622
- if (!endpoint || !path) {
623
- // Todo: Should be removed if sdk supports multi part upload.
624
- if (isMultiPartUploadPath(rawPath)) {
625
- continue;
626
- }
627
- logger.errorLn(`Failed to parse ${rawPath}`);
628
- continue;
629
- }
630
- if (endpoints.has(endpoint.service)) {
631
- endpoints.get(endpoint.service)?.push({ endpoint, path });
632
- }
633
- else {
634
- endpoints.set(endpoint.service, [{ endpoint, path }]);
635
- }
636
- }
637
- return endpoints;
638
- };
639
-
558
+ const endpoints = /* @__PURE__ */ new Map();
559
+ for (const [rawPath, path] of Object.entries(paths)) {
560
+ const endpoint = parseEndpointPath(rawPath);
561
+ if (!endpoint || !path) {
562
+ if (isMultiPartUploadPath(rawPath)) continue;
563
+ logger.errorLn(`Failed to parse ${rawPath}`);
564
+ continue;
565
+ }
566
+ if (endpoints.has(endpoint.service)) endpoints.get(endpoint.service)?.push({
567
+ endpoint,
568
+ path
569
+ });
570
+ else endpoints.set(endpoint.service, [{
571
+ endpoint,
572
+ path
573
+ }]);
574
+ }
575
+ return endpoints;
576
+ };
577
+ //#endregion
578
+ //#region src/ts/generateArrowFunction.ts
640
579
  const generateArrowFunction = ({ name, signature, returns, params }) => {
641
- return `const ${name}: ${signature} = (${params?.join(', ') ?? ''}) =>\n${indent(returns)};`;
580
+ return `const ${name}: ${signature} = (${params?.join(", ") ?? ""}) =>\n${indent(returns)};`;
642
581
  };
643
-
644
- const generateArrowFunctionType = ({ type, returns = 'void', generics, params }) => {
645
- const genericsString = generics?.length ? `<\n${indent(generics.join(',\n'))}\n>` : '';
646
- const paramsString = params?.length ? `(${params.join(', ')})` : `()`;
647
- return generateType(type, `${genericsString + paramsString} =>\n${indent(returns)}`);
582
+ //#endregion
583
+ //#region src/ts/generateArrowFunctionType.ts
584
+ const generateArrowFunctionType = ({ type, returns = "void", generics, params }) => {
585
+ return generateType(type, `${(generics?.length ? `<\n${indent(generics.join(",\n"))}\n>` : "") + (params?.length ? `(${params.join(", ")})` : `()`)} =>\n${indent(returns)}`);
648
586
  };
649
-
587
+ //#endregion
588
+ //#region src/generator/04-services/utils/resolveParameters.ts
650
589
  const resolveParameters = (resolvableParameters = [], parameters) => {
651
- if (!resolvableParameters)
652
- return [];
653
- return resolvableParameters.flatMap((param) => {
654
- if (isReferenceObject(param)) {
655
- const resolved = parameters.get(getRefName(param));
656
- return resolved ? [resolved] : [];
657
- }
658
- return [param];
659
- });
660
- };
661
-
590
+ if (!resolvableParameters) return [];
591
+ return resolvableParameters.flatMap((param) => {
592
+ if (isReferenceObject(param)) {
593
+ const resolved = parameters.get(getRefName(param));
594
+ return resolved ? [resolved] : [];
595
+ }
596
+ return [param];
597
+ });
598
+ };
599
+ //#endregion
600
+ //#region src/generator/04-services/endpoints/count.ts
662
601
  const generateCountEndpoint = ({ endpoint, operationObject, entities, context, options }) => {
663
- const functionName = 'count';
664
- const functionTypeName = `${pascalCase(endpoint.service)}Service_${pascalCase(functionName)}`;
665
- const relatedEntityName = context.aliases.get(endpoint.service);
666
- const relatedEntity = !!relatedEntityName && entities.get(relatedEntityName);
667
- if (!relatedEntity) {
668
- throw Error(`Related entity schema for service ${endpoint.service} not found`);
669
- }
670
- const parametersTypeName = `${functionTypeName}_Parameters`;
671
- const parametersType = createObjectType({
672
- params: convertToTypeScriptType(resolveParameters(operationObject.parameters, context.parameters))
673
- });
674
- const parametersTypeSource = generateInterfaceFromObject(parametersTypeName, parametersType, 'propagate');
675
- const filterTypeName = `${functionTypeName}_Filter`;
676
- const filterTypeSource = generateInterfaceType(filterTypeName, [], [`${relatedEntity.filterInterfaceName}`]);
677
- const functionTypeSource = generateArrowFunctionType({
678
- type: functionTypeName,
679
- params: [
680
- `query${parametersType.isFullyOptional() ? '?' : ''}: CountQuery<${filterTypeName}>${operationObject.parameters?.length ? ' & ' + parametersTypeName : ''}`,
681
- 'requestOptions?: RequestOptions'
682
- ],
683
- returns: `${resolveResponseType(options.target)}<number>`
684
- });
685
- const functionSource = generateArrowFunction({
686
- name: functionName,
687
- signature: functionTypeName,
688
- returns: `_${functionName}(cfg, ${generateString(endpoint.path)}, query, requestOptions)`,
689
- params: ['query', 'requestOptions?: RequestOptions']
690
- });
691
- return {
692
- name: functionName,
693
- type: { name: functionTypeName, source: functionTypeSource },
694
- func: { name: functionName, source: functionSource },
695
- interfaces: [
696
- ...(operationObject.parameters?.length ? [{ name: parametersTypeName, source: parametersTypeSource }] : []),
697
- { name: filterTypeName, source: filterTypeSource }
698
- ]
699
- };
700
- };
701
-
702
- const generateContentType = (body, fallback = 'unknown') => {
703
- if (!body?.content)
704
- return createRawType(fallback);
705
- const types = [];
706
- for (const { schema } of Object.values(body.content)) {
707
- if (schema) {
708
- types.push(convertToTypeScriptType(schema));
709
- }
710
- }
711
- return (types.length > 1 ? createTupleType(types) : types[0]) ?? createRawType(fallback);
712
- };
713
-
602
+ const functionName = "count";
603
+ const functionTypeName = `${pascalCase(endpoint.service)}Service_${pascalCase(functionName)}`;
604
+ const relatedEntityName = context.aliases.get(endpoint.service);
605
+ const relatedEntity = !!relatedEntityName && entities.get(relatedEntityName);
606
+ if (!relatedEntity) throw Error(`Related entity schema for service ${endpoint.service} not found`);
607
+ const parametersTypeName = `${functionTypeName}_Parameters`;
608
+ const parametersType = createObjectType({ params: convertToTypeScriptType(resolveParameters(operationObject.parameters, context.parameters)) });
609
+ const parametersTypeSource = generateInterfaceFromObject(parametersTypeName, parametersType, "propagate");
610
+ const filterTypeName = `${functionTypeName}_Filter`;
611
+ const filterTypeSource = generateInterfaceType(filterTypeName, [], [`${relatedEntity.filterInterfaceName}`]);
612
+ const functionTypeSource = generateArrowFunctionType({
613
+ type: functionTypeName,
614
+ params: [`query${parametersType.isFullyOptional() ? "?" : ""}: CountQuery<${filterTypeName}>${operationObject.parameters?.length ? " & " + parametersTypeName : ""}`, "requestOptions?: RequestOptions"],
615
+ returns: `${resolveResponseType(options.target)}<number>`
616
+ });
617
+ const functionSource = generateArrowFunction({
618
+ name: functionName,
619
+ signature: functionTypeName,
620
+ returns: `_${functionName}(cfg, ${generateString(endpoint.path)}, query, requestOptions)`,
621
+ params: ["query", "requestOptions?: RequestOptions"]
622
+ });
623
+ return {
624
+ name: functionName,
625
+ type: {
626
+ name: functionTypeName,
627
+ source: functionTypeSource
628
+ },
629
+ func: {
630
+ name: functionName,
631
+ source: functionSource
632
+ },
633
+ interfaces: [...operationObject.parameters?.length ? [{
634
+ name: parametersTypeName,
635
+ source: parametersTypeSource
636
+ }] : [], {
637
+ name: filterTypeName,
638
+ source: filterTypeSource
639
+ }]
640
+ };
641
+ };
642
+ //#endregion
643
+ //#region src/generator/04-services/utils/generateContentType.ts
644
+ const generateContentType = (body, fallback = "unknown") => {
645
+ if (!body?.content) return createRawType(fallback);
646
+ const types = [];
647
+ for (const { schema } of Object.values(body.content)) if (schema) types.push(convertToTypeScriptType(schema));
648
+ return (types.length > 1 ? createTupleType(types) : types[0]) ?? createRawType(fallback);
649
+ };
650
+ //#endregion
651
+ //#region src/generator/04-services/utils/generateRequestBodyType.ts
714
652
  const generateRequestBodyType = ({ requestBody }, requestBodies) => {
715
- const requestBodyObject = requestBody && isReferenceObject(requestBody) ? requestBodies.get(getRefName(requestBody)) : requestBody;
716
- return generateContentType(requestBodyObject);
653
+ return generateContentType(requestBody && isReferenceObject(requestBody) ? requestBodies.get(getRefName(requestBody)) : requestBody);
717
654
  };
718
-
719
- const resolveResponsesObject = (responses) => Object.entries(responses).find(([statusCode]) => statusCode.startsWith('2'))?.[1];
720
-
655
+ //#endregion
656
+ //#region src/generator/04-services/utils/resolveResponsesObject.ts
657
+ const resolveResponsesObject = (responses) => Object.entries(responses).find(([statusCode]) => statusCode.startsWith("2"))?.[1];
658
+ //#endregion
659
+ //#region src/generator/04-services/utils/generateResponseType.ts
721
660
  const generateResponseType = (operationObject, responses) => {
722
- const response = resolveResponsesObject(operationObject.responses);
723
- const responseObject = response && isReferenceObject(response) ? responses.get(getRefName(response)) : response;
724
- return generateContentType(responseObject, 'void');
661
+ const response = resolveResponsesObject(operationObject.responses);
662
+ return generateContentType(response && isReferenceObject(response) ? responses.get(getRefName(response)) : response, "void");
725
663
  };
726
-
664
+ //#endregion
665
+ //#region src/generator/04-services/endpoints/create.ts
727
666
  const generateCreateEndpoint = ({ endpoint, operationObject, context, options }) => {
728
- const functionName = 'create';
729
- const functionTypeName = `${pascalCase(endpoint.service)}Service_${pascalCase(functionName)}`;
730
- const functionTypeSource = generateArrowFunctionType({
731
- type: functionTypeName,
732
- params: [
733
- `data: DeepPartial<${generateRequestBodyType(operationObject, context.requestBodies).toString()}>`,
734
- 'requestOptions?: RequestOptions'
735
- ],
736
- returns: `${resolveResponseType(options.target)}<${generateResponseType(operationObject, context.responses).toString()}>`
737
- });
738
- const functionSource = generateArrowFunction({
739
- name: functionName,
740
- signature: functionTypeName,
741
- returns: `_${functionName}(cfg, ${generateString(endpoint.path)}, data, requestOptions)`,
742
- params: ['data', 'requestOptions?: RequestOptions']
743
- });
744
- return {
745
- name: functionName,
746
- type: { name: functionTypeName, source: functionTypeSource },
747
- func: { name: functionName, source: functionSource }
748
- };
749
- };
750
-
751
- const generateGenericFunctionName = (path, suffix = '', prefix = '') => {
752
- return camelCase(`${prefix}_` + path.replace(/.*\//, '').replace(/\W+/, '_').replace(/[_]+/, '_') + `_${suffix}`);
753
- };
754
-
667
+ const functionName = "create";
668
+ const functionTypeName = `${pascalCase(endpoint.service)}Service_${pascalCase(functionName)}`;
669
+ const functionTypeSource = generateArrowFunctionType({
670
+ type: functionTypeName,
671
+ params: [`data: DeepPartial<${generateRequestBodyType(operationObject, context.requestBodies).toString()}>`, "requestOptions?: RequestOptions"],
672
+ returns: `${resolveResponseType(options.target)}<${generateResponseType(operationObject, context.responses).toString()}>`
673
+ });
674
+ const functionSource = generateArrowFunction({
675
+ name: functionName,
676
+ signature: functionTypeName,
677
+ returns: `_${functionName}(cfg, ${generateString(endpoint.path)}, data, requestOptions)`,
678
+ params: ["data", "requestOptions?: RequestOptions"]
679
+ });
680
+ return {
681
+ name: functionName,
682
+ type: {
683
+ name: functionTypeName,
684
+ source: functionTypeSource
685
+ },
686
+ func: {
687
+ name: functionName,
688
+ source: functionSource
689
+ }
690
+ };
691
+ };
692
+ //#endregion
693
+ //#region src/generator/04-services/utils/generateGenericFunctionName.ts
694
+ const generateGenericFunctionName = (path, suffix = "", prefix = "") => {
695
+ return camelCase(`${prefix}_` + path.replace(/.*\//, "").replace(/\W+/, "_").replace(/[_]+/, "_") + `_${suffix}`);
696
+ };
697
+ //#endregion
698
+ //#region src/generator/04-services/utils/insertPathPlaceholder.ts
755
699
  const insertPathPlaceholder = (path, record) => {
756
- return path.replace(/{(\w+)}/g, (_, name) => record[name]);
700
+ return path.replace(/{(\w+)}/g, (_, name) => record[name]);
757
701
  };
758
-
702
+ //#endregion
703
+ //#region src/generator/04-services/endpoints/generic.ts
759
704
  const wrapBody = (type, target) => {
760
- return type.toString() === 'binary' ? createRawType(isNodeTarget(target) ? 'BodyInit' : 'Blob') : type; // node-fetch returns a Blob as well
705
+ return type.toString() === "binary" ? createRawType(isNodeTarget(target) ? "BodyInit" : "Blob") : type;
761
706
  };
762
707
  const generateGenericEndpoint = (suffix) => ({ method, endpoint, operationObject, context, options }) => {
763
- const functionName = generateGenericFunctionName(endpoint.path, suffix, method);
764
- const functionTypeName = `${pascalCase(endpoint.service)}Service_${pascalCase(functionName)}`;
765
- const entityQuery = `${functionTypeName}_Query`;
766
- const hasId = endpoint.path.includes('{id}');
767
- const params = createObjectType({
768
- params: operationObject.parameters &&
769
- convertToTypeScriptType(resolveParameters(operationObject.parameters, context.parameters)),
770
- body: method === 'get'
771
- ? undefined
772
- : wrapBody(generateRequestBodyType(operationObject, context.requestBodies), options.target)
773
- });
774
- const responseBody = generateResponseType(operationObject, context.responses);
775
- const functionTypeSource = generateArrowFunctionType({
776
- type: functionTypeName,
777
- params: [
778
- ...(hasId ? ['id: string'] : []),
779
- `query${params.isFullyOptional() ? '?' : ''}: ${entityQuery}`,
780
- 'requestOptions?: RequestOptions'
781
- ],
782
- returns: `${resolveResponseType(options.target)}<${wrapBody(responseBody, options.target).toString('force')}>`
783
- });
784
- const functionSource = generateArrowFunction({
785
- name: functionName,
786
- signature: functionTypeName,
787
- params: hasId ? ['id', 'query', 'requestOptions?: RequestOptions'] : ['query', 'requestOptions?: RequestOptions'],
788
- returns: `_generic(cfg, ${generateString(method.toUpperCase())}, \`${insertPathPlaceholder(endpoint.path, { id: '${id}' })}\`, query, ${String(responseBody.toString() === 'binary')}, requestOptions)`
789
- });
790
- return {
791
- name: functionName,
792
- type: { name: functionTypeName, source: functionTypeSource },
793
- func: { name: functionName, source: functionSource },
794
- interfaces: [
795
- {
796
- name: entityQuery,
797
- source: generateInterfaceFromObject(entityQuery, params, 'propagate')
798
- }
799
- ]
800
- };
801
- };
802
-
708
+ const functionName = generateGenericFunctionName(endpoint.path, suffix, method);
709
+ const functionTypeName = `${pascalCase(endpoint.service)}Service_${pascalCase(functionName)}`;
710
+ const entityQuery = `${functionTypeName}_Query`;
711
+ const hasId = endpoint.path.includes("{id}");
712
+ const params = createObjectType({
713
+ params: operationObject.parameters && convertToTypeScriptType(resolveParameters(operationObject.parameters, context.parameters)),
714
+ body: method === "get" ? void 0 : wrapBody(generateRequestBodyType(operationObject, context.requestBodies), options.target)
715
+ });
716
+ const responseBody = generateResponseType(operationObject, context.responses);
717
+ const functionTypeSource = generateArrowFunctionType({
718
+ type: functionTypeName,
719
+ params: [
720
+ ...hasId ? ["id: string"] : [],
721
+ `query${params.isFullyOptional() ? "?" : ""}: ${entityQuery}`,
722
+ "requestOptions?: RequestOptions"
723
+ ],
724
+ returns: `${resolveResponseType(options.target)}<${wrapBody(responseBody, options.target).toString("force")}>`
725
+ });
726
+ const functionSource = generateArrowFunction({
727
+ name: functionName,
728
+ signature: functionTypeName,
729
+ params: hasId ? [
730
+ "id",
731
+ "query",
732
+ "requestOptions?: RequestOptions"
733
+ ] : ["query", "requestOptions?: RequestOptions"],
734
+ returns: `_generic(cfg, ${generateString(method.toUpperCase())}, \`${insertPathPlaceholder(endpoint.path, { id: "${id}" })}\`, query, ${String(responseBody.toString() === "binary")}, requestOptions)`
735
+ });
736
+ return {
737
+ name: functionName,
738
+ type: {
739
+ name: functionTypeName,
740
+ source: functionTypeSource
741
+ },
742
+ func: {
743
+ name: functionName,
744
+ source: functionSource
745
+ },
746
+ interfaces: [{
747
+ name: entityQuery,
748
+ source: generateInterfaceFromObject(entityQuery, params, "propagate")
749
+ }]
750
+ };
751
+ };
752
+ //#endregion
753
+ //#region src/generator/04-services/endpoints/remove.ts
803
754
  const generateRemoveEndpoint = ({ endpoint, options }) => {
804
- const functionName = 'remove';
805
- const functionTypeName = `${pascalCase(endpoint.service)}Service_${pascalCase(functionName)}`;
806
- const functionTypeSource = generateArrowFunctionType({
807
- type: functionTypeName,
808
- params: ['id: string', 'options?: RemoveQuery', 'requestOptions?: RequestOptions'],
809
- returns: `${resolveResponseType(options.target)}<void>`
810
- });
811
- const functionSource = generateArrowFunction({
812
- name: functionName,
813
- signature: functionTypeName,
814
- returns: `_${functionName}(cfg, \`${insertPathPlaceholder(endpoint.path, { id: '${id}' })}\`, options, requestOptions)`,
815
- params: ['id', 'options?: RemoveQuery', 'requestOptions?: RequestOptions']
816
- });
817
- return {
818
- name: functionName,
819
- type: { name: functionTypeName, source: functionTypeSource },
820
- func: { name: functionName, source: functionSource }
821
- };
822
- };
823
-
755
+ const functionName = "remove";
756
+ const functionTypeName = `${pascalCase(endpoint.service)}Service_${pascalCase(functionName)}`;
757
+ const functionTypeSource = generateArrowFunctionType({
758
+ type: functionTypeName,
759
+ params: [
760
+ "id: string",
761
+ "options?: RemoveQuery",
762
+ "requestOptions?: RequestOptions"
763
+ ],
764
+ returns: `${resolveResponseType(options.target)}<void>`
765
+ });
766
+ const functionSource = generateArrowFunction({
767
+ name: functionName,
768
+ signature: functionTypeName,
769
+ returns: `_${functionName}(cfg, \`${insertPathPlaceholder(endpoint.path, { id: "${id}" })}\`, options, requestOptions)`,
770
+ params: [
771
+ "id",
772
+ "options?: RemoveQuery",
773
+ "requestOptions?: RequestOptions"
774
+ ]
775
+ });
776
+ return {
777
+ name: functionName,
778
+ type: {
779
+ name: functionTypeName,
780
+ source: functionTypeSource
781
+ },
782
+ func: {
783
+ name: functionName,
784
+ source: functionSource
785
+ }
786
+ };
787
+ };
788
+ //#endregion
789
+ //#region src/generator/04-services/endpoints/some.ts
824
790
  const excludedParameters = [
825
- 'page',
826
- 'pageSize',
827
- 'sort',
828
- 'serializeNulls',
829
- 'properties',
830
- 'includeReferencedEntities',
831
- 'additionalProperties'
791
+ "page",
792
+ "pageSize",
793
+ "sort",
794
+ "serializeNulls",
795
+ "properties",
796
+ "includeReferencedEntities",
797
+ "additionalProperties"
832
798
  ];
833
799
  const resolveAdditionalPropertiesSchema = ({ responses }) => {
834
- const body = resolveResponsesObject(responses);
835
- if (isResponseObject(body)) {
836
- const schema = body?.content?.['application/json']?.schema;
837
- if (isObjectSchemaObject(schema)) {
838
- const obj = schema?.properties?.additionalProperties;
839
- if (isObjectSchemaObject(obj)) {
840
- return obj;
841
- }
842
- }
843
- }
844
- return undefined;
800
+ const body = resolveResponsesObject(responses);
801
+ if (isResponseObject(body)) {
802
+ const schema = body?.content?.["application/json"]?.schema;
803
+ if (isObjectSchemaObject(schema)) {
804
+ const obj = schema?.properties?.additionalProperties;
805
+ if (isObjectSchemaObject(obj)) return obj;
806
+ }
807
+ }
845
808
  };
846
809
  const resolveReferences = (entity, entities) => {
847
- const references = [];
848
- const generatedEntity = entities.get(entity);
849
- if (generatedEntity) {
850
- for (const [property, propertyMetaData] of generatedEntity.properties) {
851
- if (propertyMetaData.service) {
852
- references.push({
853
- name: property,
854
- type: generateString(propertyMetaData.service),
855
- required: true
856
- });
857
- }
858
- }
859
- if (generatedEntity.parentName) {
860
- references.push(...resolveReferences(generatedEntity.parentName, entities));
861
- }
862
- }
863
- return references;
810
+ const references = [];
811
+ const generatedEntity = entities.get(entity);
812
+ if (generatedEntity) {
813
+ for (const [property, propertyMetaData] of generatedEntity.properties) if (propertyMetaData.service) references.push({
814
+ name: property,
815
+ type: generateString(propertyMetaData.service),
816
+ required: true
817
+ });
818
+ if (generatedEntity.parentName) references.push(...resolveReferences(generatedEntity.parentName, entities));
819
+ }
820
+ return references;
864
821
  };
865
822
  const resolveReferencedEntities = (entity, entities) => {
866
- const referencedEntities = [];
867
- const generatedEntity = entities.get(entity);
868
- if (generatedEntity) {
869
- for (const [, propertyMetaData] of generatedEntity.properties) {
870
- if (propertyMetaData.service && propertyMetaData.entity) {
871
- const referencedEntity = entities.get(propertyMetaData.entity);
872
- if (referencedEntity)
873
- referencedEntities.push({
874
- name: propertyMetaData.service,
875
- type: `${referencedEntity.interfaceName}[]`,
876
- required: true
877
- });
878
- }
879
- }
880
- if (generatedEntity.parentName) {
881
- referencedEntities.push(...resolveReferencedEntities(generatedEntity.parentName, entities));
882
- }
883
- }
884
- return referencedEntities;
823
+ const referencedEntities = [];
824
+ const generatedEntity = entities.get(entity);
825
+ if (generatedEntity) {
826
+ for (const [, propertyMetaData] of generatedEntity.properties) if (propertyMetaData.service && propertyMetaData.entity) {
827
+ const referencedEntity = entities.get(propertyMetaData.entity);
828
+ if (referencedEntity) referencedEntities.push({
829
+ name: propertyMetaData.service,
830
+ type: `${referencedEntity.interfaceName}[]`,
831
+ required: true
832
+ });
833
+ }
834
+ if (generatedEntity.parentName) referencedEntities.push(...resolveReferencedEntities(generatedEntity.parentName, entities));
835
+ }
836
+ return referencedEntities;
885
837
  };
886
838
  const generateSomeEndpoint = ({ endpoint, operationObject, entities, context, options }) => {
887
- const functionName = 'some';
888
- const functionTypeName = `${pascalCase(endpoint.service)}Service_${pascalCase(functionName)}`;
889
- const relatedEntityName = context.aliases.get(endpoint.service);
890
- const relatedEntity = !!relatedEntityName && entities.get(relatedEntityName);
891
- if (!relatedEntity) {
892
- throw Error(`Related entity schema for service ${endpoint.service} not found`);
893
- }
894
- const parametersTypeName = `${functionTypeName}_Parameters`;
895
- const parameters = operationObject.parameters?.filter((v) => isParameterObject(v) ? !excludedParameters.includes(v.name) : false);
896
- const parametersType = createObjectType({
897
- params: parameters && convertToTypeScriptType(resolveParameters(parameters, context.parameters))
898
- });
899
- const parametersTypeSource = generateInterfaceFromObject(parametersTypeName, parametersType, 'propagate');
900
- const filterTypeName = `${functionTypeName}_Filter`;
901
- const filterTypeSource = generateInterfaceType(filterTypeName, [], [`${relatedEntity.filterInterfaceName}`]);
902
- const referencesTypeName = `${functionTypeName}_References`;
903
- const referencesTypeSource = generateInterfaceType(referencesTypeName, resolveReferences(endpoint.service, entities));
904
- const additionalPropertyTypeName = `${functionTypeName}_AdditionalProperty`;
905
- const additionalPropertyTypeSource = generateType(additionalPropertyTypeName, 'string');
906
- const queryTypeName = `${functionTypeName}_Query`;
907
- const queryTypeSource = generateType(queryTypeName, `SomeQuery<${relatedEntity.interfaceName}, ${filterTypeName}, ${referencesTypeName}, ${additionalPropertyTypeName}> & ${parametersTypeName}`);
908
- const referencedEntitiesTypeName = `${functionTypeName}_ReferencedEntities`;
909
- const referencedEntitiesTypeSource = generateInterfaceType(referencedEntitiesTypeName, resolveReferencedEntities(endpoint.service, entities));
910
- const additionalPropertiesTypeName = `${functionTypeName}_AdditionalProperties`;
911
- const additionalPropertiesSchema = resolveAdditionalPropertiesSchema(operationObject);
912
- const additionalPropertiesTypeSource = generateType(additionalPropertiesTypeName, additionalPropertiesSchema ? convertToTypeScriptType(additionalPropertiesSchema).toString() : '{}');
913
- const functionTypeSource = generateArrowFunctionType({
914
- type: functionTypeName,
915
- params: [`query${parametersType.isFullyOptional() ? '?' : ''}: ${queryTypeName}, requestOptions?: RequestOptions`],
916
- returns: `${resolveResponseType(options.target)}<SomeQueryReturn<${relatedEntity.interfaceName}, ${referencedEntitiesTypeName}, ${additionalPropertiesTypeName}>>`
917
- });
918
- const functionSource = generateArrowFunction({
919
- name: functionName,
920
- signature: functionTypeName,
921
- returns: `_${functionName}(cfg, ${generateString(endpoint.path)}, query, requestOptions)`,
922
- params: ['query', 'requestOptions?: RequestOptions']
923
- });
924
- return {
925
- name: functionName,
926
- type: { name: functionTypeName, source: functionTypeSource },
927
- func: { name: functionName, source: functionSource },
928
- interfaces: [
929
- { name: parametersTypeName, source: parametersTypeSource },
930
- { name: filterTypeName, source: filterTypeSource },
931
- { name: referencesTypeName, source: referencesTypeSource },
932
- { name: additionalPropertyTypeName, source: additionalPropertyTypeSource },
933
- { name: queryTypeName, source: queryTypeSource },
934
- { name: referencedEntitiesTypeName, source: referencedEntitiesTypeSource },
935
- { name: additionalPropertiesTypeName, source: additionalPropertiesTypeSource }
936
- ]
937
- };
938
- };
939
-
839
+ const functionName = "some";
840
+ const functionTypeName = `${pascalCase(endpoint.service)}Service_${pascalCase(functionName)}`;
841
+ const relatedEntityName = context.aliases.get(endpoint.service);
842
+ const relatedEntity = !!relatedEntityName && entities.get(relatedEntityName);
843
+ if (!relatedEntity) throw Error(`Related entity schema for service ${endpoint.service} not found`);
844
+ const parametersTypeName = `${functionTypeName}_Parameters`;
845
+ const parameters = operationObject.parameters?.filter((v) => isParameterObject(v) ? !excludedParameters.includes(v.name) : false);
846
+ const parametersType = createObjectType({ params: parameters && convertToTypeScriptType(resolveParameters(parameters, context.parameters)) });
847
+ const parametersTypeSource = generateInterfaceFromObject(parametersTypeName, parametersType, "propagate");
848
+ const filterTypeName = `${functionTypeName}_Filter`;
849
+ const filterTypeSource = generateInterfaceType(filterTypeName, [], [`${relatedEntity.filterInterfaceName}`]);
850
+ const referencesTypeName = `${functionTypeName}_References`;
851
+ const referencesTypeSource = generateInterfaceType(referencesTypeName, resolveReferences(endpoint.service, entities));
852
+ const additionalPropertyTypeName = `${functionTypeName}_AdditionalProperty`;
853
+ const additionalPropertyTypeSource = generateType(additionalPropertyTypeName, "string");
854
+ const queryTypeName = `${functionTypeName}_Query`;
855
+ const queryTypeSource = generateType(queryTypeName, `SomeQuery<${relatedEntity.interfaceName}, ${filterTypeName}, ${referencesTypeName}, ${additionalPropertyTypeName}> & ${parametersTypeName}`);
856
+ const referencedEntitiesTypeName = `${functionTypeName}_ReferencedEntities`;
857
+ const referencedEntitiesTypeSource = generateInterfaceType(referencedEntitiesTypeName, resolveReferencedEntities(endpoint.service, entities));
858
+ const additionalPropertiesTypeName = `${functionTypeName}_AdditionalProperties`;
859
+ const additionalPropertiesSchema = resolveAdditionalPropertiesSchema(operationObject);
860
+ const additionalPropertiesTypeSource = generateType(additionalPropertiesTypeName, additionalPropertiesSchema ? convertToTypeScriptType(additionalPropertiesSchema).toString() : "{}");
861
+ const functionTypeSource = generateArrowFunctionType({
862
+ type: functionTypeName,
863
+ params: [`query${parametersType.isFullyOptional() ? "?" : ""}: ${queryTypeName}, requestOptions?: RequestOptions`],
864
+ returns: `${resolveResponseType(options.target)}<SomeQueryReturn<${relatedEntity.interfaceName}, ${referencedEntitiesTypeName}, ${additionalPropertiesTypeName}>>`
865
+ });
866
+ const functionSource = generateArrowFunction({
867
+ name: functionName,
868
+ signature: functionTypeName,
869
+ returns: `_${functionName}(cfg, ${generateString(endpoint.path)}, query, requestOptions)`,
870
+ params: ["query", "requestOptions?: RequestOptions"]
871
+ });
872
+ return {
873
+ name: functionName,
874
+ type: {
875
+ name: functionTypeName,
876
+ source: functionTypeSource
877
+ },
878
+ func: {
879
+ name: functionName,
880
+ source: functionSource
881
+ },
882
+ interfaces: [
883
+ {
884
+ name: parametersTypeName,
885
+ source: parametersTypeSource
886
+ },
887
+ {
888
+ name: filterTypeName,
889
+ source: filterTypeSource
890
+ },
891
+ {
892
+ name: referencesTypeName,
893
+ source: referencesTypeSource
894
+ },
895
+ {
896
+ name: additionalPropertyTypeName,
897
+ source: additionalPropertyTypeSource
898
+ },
899
+ {
900
+ name: queryTypeName,
901
+ source: queryTypeSource
902
+ },
903
+ {
904
+ name: referencedEntitiesTypeName,
905
+ source: referencedEntitiesTypeSource
906
+ },
907
+ {
908
+ name: additionalPropertiesTypeName,
909
+ source: additionalPropertiesTypeSource
910
+ }
911
+ ]
912
+ };
913
+ };
914
+ //#endregion
915
+ //#region src/generator/04-services/endpoints/unique.ts
940
916
  const generateUniqueEndpoint = ({ operationObject, endpoint, context, options }) => {
941
- const functionName = 'unique';
942
- const functionTypeName = `${pascalCase(endpoint.service)}Service_${pascalCase(functionName)}`;
943
- const functionTypeSource = generateArrowFunctionType({
944
- type: functionTypeName,
945
- params: ['id: string', 'query?: Q', 'requestOptions?: RequestOptions'],
946
- generics: ['Q extends UniqueQuery'],
947
- returns: `${resolveResponseType(options.target)}<${generateResponseType(operationObject, context.responses).toString()}>`
948
- });
949
- const functionSource = generateArrowFunction({
950
- name: functionName,
951
- signature: functionTypeName,
952
- params: ['id', 'query', 'requestOptions?: RequestOptions'],
953
- returns: `_${functionName}(cfg, \`${insertPathPlaceholder(endpoint.path, { id: '${id}' })}\`, query, requestOptions)`
954
- });
955
- return {
956
- name: functionName,
957
- type: { name: functionTypeName, source: functionTypeSource },
958
- func: { name: functionName, source: functionSource }
959
- };
960
- };
961
-
917
+ const functionName = "unique";
918
+ const functionTypeName = `${pascalCase(endpoint.service)}Service_${pascalCase(functionName)}`;
919
+ const functionTypeSource = generateArrowFunctionType({
920
+ type: functionTypeName,
921
+ params: [
922
+ "id: string",
923
+ "query?: Q",
924
+ "requestOptions?: RequestOptions"
925
+ ],
926
+ generics: ["Q extends UniqueQuery"],
927
+ returns: `${resolveResponseType(options.target)}<${generateResponseType(operationObject, context.responses).toString()}>`
928
+ });
929
+ const functionSource = generateArrowFunction({
930
+ name: functionName,
931
+ signature: functionTypeName,
932
+ params: [
933
+ "id",
934
+ "query",
935
+ "requestOptions?: RequestOptions"
936
+ ],
937
+ returns: `_${functionName}(cfg, \`${insertPathPlaceholder(endpoint.path, { id: "${id}" })}\`, query, requestOptions)`
938
+ });
939
+ return {
940
+ name: functionName,
941
+ type: {
942
+ name: functionTypeName,
943
+ source: functionTypeSource
944
+ },
945
+ func: {
946
+ name: functionName,
947
+ source: functionSource
948
+ }
949
+ };
950
+ };
951
+ //#endregion
952
+ //#region src/generator/04-services/endpoints/update.ts
962
953
  const generateUpdateEndpoint = ({ endpoint, operationObject, context, options }) => {
963
- const functionName = 'update';
964
- const functionTypeName = `${pascalCase(endpoint.service)}Service_${pascalCase(functionName)}`;
965
- const functionTypeSource = generateArrowFunctionType({
966
- type: functionTypeName,
967
- params: [
968
- 'id: string',
969
- `data: DeepPartial<${generateRequestBodyType(operationObject, context.requestBodies).toString()}>`,
970
- 'options?: UpdateQuery',
971
- 'requestOptions?: RequestOptions'
972
- ],
973
- returns: `${resolveResponseType(options.target)}<${generateResponseType(operationObject, context.responses).toString()}>`
974
- });
975
- const functionSource = generateArrowFunction({
976
- name: functionName,
977
- signature: functionTypeName,
978
- returns: `_${functionName}(cfg, \`${insertPathPlaceholder(endpoint.path, { id: '${id}' })}\`, data, options, requestOptions)`,
979
- params: ['id', 'data', 'options', 'requestOptions?: RequestOptions']
980
- });
981
- return {
982
- name: functionName,
983
- type: { name: functionTypeName, source: functionTypeSource },
984
- func: { name: functionName, source: functionSource }
985
- };
986
- };
987
-
954
+ const functionName = "update";
955
+ const functionTypeName = `${pascalCase(endpoint.service)}Service_${pascalCase(functionName)}`;
956
+ const functionTypeSource = generateArrowFunctionType({
957
+ type: functionTypeName,
958
+ params: [
959
+ "id: string",
960
+ `data: DeepPartial<${generateRequestBodyType(operationObject, context.requestBodies).toString()}>`,
961
+ "options?: UpdateQuery",
962
+ "requestOptions?: RequestOptions"
963
+ ],
964
+ returns: `${resolveResponseType(options.target)}<${generateResponseType(operationObject, context.responses).toString()}>`
965
+ });
966
+ const functionSource = generateArrowFunction({
967
+ name: functionName,
968
+ signature: functionTypeName,
969
+ returns: `_${functionName}(cfg, \`${insertPathPlaceholder(endpoint.path, { id: "${id}" })}\`, data, options, requestOptions)`,
970
+ params: [
971
+ "id",
972
+ "data",
973
+ "options",
974
+ "requestOptions?: RequestOptions"
975
+ ]
976
+ });
977
+ return {
978
+ name: functionName,
979
+ type: {
980
+ name: functionTypeName,
981
+ source: functionTypeSource
982
+ },
983
+ func: {
984
+ name: functionName,
985
+ source: functionSource
986
+ }
987
+ };
988
+ };
989
+ //#endregion
990
+ //#region src/generator/04-services/index.ts
988
991
  const generators = {
989
- /* /article */
990
- [WeclappEndpointType.ROOT]: {
991
- [OpenAPIV3.HttpMethods.GET]: generateSomeEndpoint,
992
- [OpenAPIV3.HttpMethods.POST]: generateCreateEndpoint
993
- },
994
- /* /article/count */
995
- [WeclappEndpointType.COUNT]: {
996
- [OpenAPIV3.HttpMethods.GET]: generateCountEndpoint
997
- },
998
- /* /article/:id */
999
- [WeclappEndpointType.ENTITY]: {
1000
- [OpenAPIV3.HttpMethods.GET]: generateUniqueEndpoint,
1001
- [OpenAPIV3.HttpMethods.PUT]: generateUpdateEndpoint,
1002
- [OpenAPIV3.HttpMethods.DELETE]: generateRemoveEndpoint
1003
- },
1004
- /* /article/:id/method */
1005
- [WeclappEndpointType.GENERIC_ENTITY]: {
1006
- [OpenAPIV3.HttpMethods.GET]: generateGenericEndpoint('ById'),
1007
- [OpenAPIV3.HttpMethods.POST]: generateGenericEndpoint('ById')
1008
- },
1009
- /* /article/method */
1010
- [WeclappEndpointType.GENERIC_ROOT]: {
1011
- [OpenAPIV3.HttpMethods.GET]: generateGenericEndpoint(),
1012
- [OpenAPIV3.HttpMethods.POST]: generateGenericEndpoint()
1013
- }
992
+ [WeclappEndpointType.ROOT]: {
993
+ [OpenAPIV3.HttpMethods.GET]: generateSomeEndpoint,
994
+ [OpenAPIV3.HttpMethods.POST]: generateCreateEndpoint
995
+ },
996
+ [WeclappEndpointType.COUNT]: { [OpenAPIV3.HttpMethods.GET]: generateCountEndpoint },
997
+ [WeclappEndpointType.ENTITY]: {
998
+ [OpenAPIV3.HttpMethods.GET]: generateUniqueEndpoint,
999
+ [OpenAPIV3.HttpMethods.PUT]: generateUpdateEndpoint,
1000
+ [OpenAPIV3.HttpMethods.DELETE]: generateRemoveEndpoint
1001
+ },
1002
+ [WeclappEndpointType.GENERIC_ENTITY]: {
1003
+ [OpenAPIV3.HttpMethods.GET]: generateGenericEndpoint("ById"),
1004
+ [OpenAPIV3.HttpMethods.POST]: generateGenericEndpoint("ById")
1005
+ },
1006
+ [WeclappEndpointType.GENERIC_ROOT]: {
1007
+ [OpenAPIV3.HttpMethods.GET]: generateGenericEndpoint(),
1008
+ [OpenAPIV3.HttpMethods.POST]: generateGenericEndpoint()
1009
+ }
1014
1010
  };
1015
1011
  const generateServices = (entities, context, options) => {
1016
- const services = new Map();
1017
- for (const [serviceName, serviceEndpoints] of context.endpoints) {
1018
- const serviceFnName = camelCase(`${serviceName}Service`);
1019
- const serviceTypeName = pascalCase(`${serviceName}Service`);
1020
- const functions = [];
1021
- for (const { path, endpoint } of serviceEndpoints) {
1022
- for (const method of [
1023
- OpenAPIV3.HttpMethods.GET,
1024
- OpenAPIV3.HttpMethods.POST,
1025
- OpenAPIV3.HttpMethods.PUT,
1026
- OpenAPIV3.HttpMethods.DELETE
1027
- ]) {
1028
- if ((method === OpenAPIV3.HttpMethods.GET &&
1029
- endpoint.type === WeclappEndpointType.ENTITY &&
1030
- !options.generateUnique) ||
1031
- (method === OpenAPIV3.HttpMethods.POST &&
1032
- (endpoint.type === WeclappEndpointType.COUNT || endpoint.path.endsWith('query')))) {
1033
- // Skip unique endpoints if generateUnique option is not set or if POST is used for filter queries
1034
- continue;
1035
- }
1036
- const operationObject = path[method];
1037
- const generatorFn = generators[endpoint.type][method];
1038
- if (operationObject && generatorFn) {
1039
- if (!operationObject.deprecated || options.deprecated) {
1040
- functions.push({
1041
- ...generatorFn({
1042
- method,
1043
- endpoint,
1044
- operationObject,
1045
- entities,
1046
- context,
1047
- options
1048
- }),
1049
- path: operationObject
1050
- });
1051
- }
1052
- }
1053
- }
1054
- }
1055
- if (!functions.length) {
1056
- continue;
1057
- }
1058
- const serviceTypes = generateStatements(...functions.flatMap((v) => generateBlockComment(`${serviceTypeName} - ${pascalCase(v.name)}`, generateStatements(...[...(v.interfaces?.map((v) => v.source) ?? []), v.type.source]))), generateBlockComment(`${serviceTypeName}`, generateInterface(serviceTypeName, [
1059
- ...functions.map((v) => ({
1060
- required: true,
1061
- comment: v.path.deprecated ? '@deprecated' : undefined,
1062
- name: v.func.name,
1063
- type: v.type.name
1064
- }))
1065
- ])));
1066
- const serviceFn = `export const ${serviceFnName} = (cfg?: ServiceConfig): ${serviceTypeName} => ${generateBlockStatements(...functions.map((v) => v.func.source), `return {${concat(functions.map((v) => v.func.name))}};`)};`;
1067
- const relatedEntityName = context.aliases.get(serviceName);
1068
- const relatedEntity = relatedEntityName ? entities.get(relatedEntityName) : undefined;
1069
- services.set(serviceName, {
1070
- name: serviceName,
1071
- serviceFnName,
1072
- functions,
1073
- source: generateStatements(serviceTypes, serviceFn),
1074
- deprecated: functions.every((v) => v.path.deprecated),
1075
- relatedEntity
1076
- });
1077
- }
1078
- return services;
1079
- };
1080
-
1012
+ const services = /* @__PURE__ */ new Map();
1013
+ for (const [serviceName, serviceEndpoints] of context.endpoints) {
1014
+ const serviceFnName = camelCase(`${serviceName}Service`);
1015
+ const serviceTypeName = pascalCase(`${serviceName}Service`);
1016
+ const functions = [];
1017
+ for (const { path, endpoint } of serviceEndpoints) for (const method of [
1018
+ OpenAPIV3.HttpMethods.GET,
1019
+ OpenAPIV3.HttpMethods.POST,
1020
+ OpenAPIV3.HttpMethods.PUT,
1021
+ OpenAPIV3.HttpMethods.DELETE
1022
+ ]) {
1023
+ if (method === OpenAPIV3.HttpMethods.GET && endpoint.type === WeclappEndpointType.ENTITY && !options.generateUnique || method === OpenAPIV3.HttpMethods.POST && (endpoint.type === WeclappEndpointType.COUNT || endpoint.path.endsWith("query"))) continue;
1024
+ const operationObject = path[method];
1025
+ const generatorFn = generators[endpoint.type][method];
1026
+ if (operationObject && generatorFn) {
1027
+ if (!operationObject.deprecated || options.deprecated) functions.push({
1028
+ ...generatorFn({
1029
+ method,
1030
+ endpoint,
1031
+ operationObject,
1032
+ entities,
1033
+ context,
1034
+ options
1035
+ }),
1036
+ path: operationObject
1037
+ });
1038
+ }
1039
+ }
1040
+ if (!functions.length) continue;
1041
+ const serviceTypes = generateStatements(...functions.flatMap((v) => generateBlockComment(`${serviceTypeName} - ${pascalCase(v.name)}`, generateStatements(...[...v.interfaces?.map((v) => v.source) ?? [], v.type.source]))), generateBlockComment(`${serviceTypeName}`, generateInterface(serviceTypeName, [...functions.map((v) => ({
1042
+ required: true,
1043
+ comment: v.path.deprecated ? "@deprecated" : void 0,
1044
+ name: v.func.name,
1045
+ type: v.type.name
1046
+ }))])));
1047
+ const serviceFn = `export const ${serviceFnName} = (cfg?: ServiceConfig): ${serviceTypeName} => ${generateBlockStatements(...functions.map((v) => v.func.source), `return {${concat(functions.map((v) => v.func.name))}};`)};`;
1048
+ const relatedEntityName = context.aliases.get(serviceName);
1049
+ const relatedEntity = relatedEntityName ? entities.get(relatedEntityName) : void 0;
1050
+ services.set(serviceName, {
1051
+ name: serviceName,
1052
+ serviceFnName,
1053
+ functions,
1054
+ source: generateStatements(serviceTypes, serviceFn),
1055
+ deprecated: functions.every((v) => v.path.deprecated),
1056
+ relatedEntity
1057
+ });
1058
+ }
1059
+ return services;
1060
+ };
1061
+ //#endregion
1062
+ //#region src/generator/05-maps/utils/generateCustomValueServices.ts
1081
1063
  const generateCustomValueServices = (services) => {
1082
- const customValueEntities = [];
1083
- for (const service of services) {
1084
- const relatedEntity = service.relatedEntity;
1085
- if (relatedEntity?.name === 'customValue') {
1086
- customValueEntities.push(service.name);
1087
- }
1088
- }
1089
- return generateStatements(generateType('WCustomValueService', concat(generateStrings(customValueEntities), ' | ')), `export const wCustomValueServiceNames: WCustomValueService[] = [${concat(generateStrings(customValueEntities))}];`, `export const isWCustomValueService = (service: string | undefined): service is WCustomValueService =>\n${indent('wCustomValueServiceNames.includes(service as WCustomValueService);')}`);
1090
- };
1091
-
1064
+ const customValueEntities = [];
1065
+ for (const service of services) if (service.relatedEntity?.name === "customValue") customValueEntities.push(service.name);
1066
+ return generateStatements(generateType("WCustomValueService", concat(generateStrings(customValueEntities), " | ")), `export const wCustomValueServiceNames: WCustomValueService[] = [${concat(generateStrings(customValueEntities))}];`, `export const isWCustomValueService = (service: string | undefined): service is WCustomValueService =>\n${indent("wCustomValueServiceNames.includes(service as WCustomValueService);")}`);
1067
+ };
1068
+ //#endregion
1069
+ //#region src/ts/generateObject.ts
1092
1070
  const generateObject = (properties) => {
1093
- const body = [];
1094
- for (const { key, value, comment } of properties) {
1095
- if (value === undefined) {
1096
- continue;
1097
- }
1098
- if (Array.isArray(value)) {
1099
- const str = generateObject(value);
1100
- if (str.length > 2) {
1101
- body.push(`${comment ? generateInlineComment(comment) + '\n' : ''}${key}: ${str}`);
1102
- }
1103
- }
1104
- else {
1105
- body.push(`${comment ? generateInlineComment(comment) + '\n' : ''}${key}: ${String(value)}`);
1106
- }
1107
- }
1108
- return body.length ? `{\n${indent(body.join(',\n'))}\n}` : `{}`;
1109
- };
1110
-
1071
+ const body = [];
1072
+ for (const { key, value, comment } of properties) {
1073
+ if (value === void 0) continue;
1074
+ if (Array.isArray(value)) {
1075
+ const str = generateObject(value);
1076
+ if (str.length > 2) body.push(`${comment ? generateInlineComment(comment) + "\n" : ""}${key}: ${str}`);
1077
+ } else body.push(`${comment ? generateInlineComment(comment) + "\n" : ""}${key}: ${String(value)}`);
1078
+ }
1079
+ return body.length ? `{\n${indent(body.join(",\n"))}\n}` : `{}`;
1080
+ };
1081
+ //#endregion
1082
+ //#region src/generator/05-maps/utils/generateEntityProperties.ts
1111
1083
  const resolveInheritedEntities = (root, entities) => {
1112
- const parent = root.parentName ? entities.get(root.parentName) : undefined;
1113
- return parent ? [parent, ...resolveInheritedEntities(parent, entities)] : [];
1114
- };
1115
- const generatePropertyDescriptors = (entity, entities, services, options) => [...resolveInheritedEntities(entity, entities).flatMap((v) => [...v.properties]), ...entity.properties]
1116
- .filter(([, meta]) => {
1117
- // If we generate deprecated things we can skip the filtering
1118
- if (options.deprecated) {
1119
- return true;
1120
- }
1121
- // Check if corresponding service is deprecated and can be removed
1122
- const service = services.find((v) => v.name === meta.service);
1123
- return !meta.service || (service && !service.deprecated);
1124
- })
1125
- .map(([property, meta]) => ({
1126
- key: property,
1127
- value: Object.entries(meta).map(([key, value]) => ({
1128
- key,
1129
- value: value !== undefined ? (typeof value === 'number' ? value : generateString(value)) : undefined
1130
- }))
1084
+ const parent = root.parentName ? entities.get(root.parentName) : void 0;
1085
+ return parent ? [parent, ...resolveInheritedEntities(parent, entities)] : [];
1086
+ };
1087
+ const generatePropertyDescriptors = (entity, entities, services, options) => [...resolveInheritedEntities(entity, entities).flatMap((v) => [...v.properties]), ...entity.properties].filter(([, meta]) => {
1088
+ if (options.deprecated) return true;
1089
+ const service = services.find((v) => v.name === meta.service);
1090
+ return !meta.service || service && !service.deprecated;
1091
+ }).map(([property, meta]) => ({
1092
+ key: property,
1093
+ value: Object.entries(meta).map(([key, value]) => ({
1094
+ key,
1095
+ value: value !== void 0 ? typeof value === "number" ? value : generateString(value) : void 0
1096
+ }))
1131
1097
  }));
1132
1098
  const generateEntityProperties = (entities, services, options) => {
1133
- const typeName = 'WEntityProperties';
1134
- const propertyMap = [
1135
- ...entities.entries(),
1136
- ...services
1137
- .filter(({ relatedEntity }) => !!relatedEntity)
1138
- .filter(({ name }) => !entities.get(name))
1139
- .map(({ name, relatedEntity }) => {
1140
- return [name, relatedEntity];
1141
- })
1142
- ].map(([entityName, entity]) => ({
1143
- key: entityName,
1144
- value: generatePropertyDescriptors(entity, entities, services, options)
1145
- }));
1146
- return generateStatements(`export type ${typeName} = Partial<Record<WEntity, Partial<Record<string, WEntityPropertyMeta>>>>;`, `export const wEntityProperties: ${typeName} = ${generateObject(propertyMap)};`);
1147
- };
1148
-
1099
+ const typeName = "WEntityProperties";
1100
+ const propertyMap = [...entities.entries(), ...services.filter(({ relatedEntity }) => !!relatedEntity).filter(({ name }) => !entities.get(name)).map(({ name, relatedEntity }) => {
1101
+ return [name, relatedEntity];
1102
+ })].map(([entityName, entity]) => ({
1103
+ key: entityName,
1104
+ value: generatePropertyDescriptors(entity, entities, services, options)
1105
+ }));
1106
+ return generateStatements(`export type ${typeName} = Partial<Record<WEntity, Partial<Record<string, WEntityPropertyMeta>>>>;`, `export const wEntityProperties: ${typeName} = ${generateObject(propertyMap)};`);
1107
+ };
1108
+ //#endregion
1109
+ //#region src/ts/generateArray.ts
1149
1110
  const generateArray = (values) => {
1150
- return `[${concat(values.map((v) => generateString(String(v))))}]`;
1111
+ return `[${concat(values.map((v) => generateString(String(v))))}]`;
1151
1112
  };
1152
-
1153
- // Only functions matching this regex are included in the generation.
1113
+ //#endregion
1114
+ //#region src/generator/05-maps/utils/generateGroupedServices.ts
1154
1115
  const FILTER_REGEX = /^(some|count|create|remove|unique|update)$/;
1155
1116
  /**
1156
- * Generates for each function a map with the entity-name as key and service type as value.
1157
- * E.g. WServicesWith[Function] where [Function] may be something like "some" or "create".
1158
- *
1159
- * This function also generates an exported array with the names of each service for each name.
1160
- */
1117
+ * Generates for each function a map with the entity-name as key and service type as value.
1118
+ * E.g. WServicesWith[Function] where [Function] may be something like "some" or "create".
1119
+ *
1120
+ * This function also generates an exported array with the names of each service for each name.
1121
+ */
1161
1122
  const generateGroupedServices = (services) => {
1162
- const entityDescriptors = new Map();
1163
- for (const service of services) {
1164
- for (const fn of service.functions) {
1165
- if (!FILTER_REGEX.test(fn.name)) {
1166
- continue;
1167
- }
1168
- entityDescriptors.set(fn.name, [
1169
- ...(entityDescriptors.get(fn.name) ?? []),
1170
- {
1171
- name: service.name,
1172
- required: true,
1173
- type: `${pascalCase(service.name)}Service_${pascalCase(fn.name)}`
1174
- }
1175
- ]);
1176
- }
1177
- }
1178
- const descriptors = [...entityDescriptors.entries()];
1179
- const typeGuards = [];
1180
- for (const [name] of descriptors) {
1181
- const constant = camelCase(`wServiceWith_${name}_Names`);
1182
- const service = pascalCase(`WServiceWith_${name}`);
1183
- const guard = `(service: string | undefined): service is ${service} =>\n${indent(`${constant}.includes(service as ${service});`)}`;
1184
- typeGuards.push(`export const is${service} = ${guard}`);
1185
- }
1186
- return generateStatements(...descriptors.map(([name, props]) => generateInterface(pascalCase(`WServicesWith_${name}`), props)), ...descriptors.map(([name]) => generateType(pascalCase(`WServiceWith_${name}`), `keyof ${pascalCase(`WServicesWith_${name}`)}`)), ...descriptors.map(([name, props]) => {
1187
- const constant = camelCase(`wServiceWith_${name}_Names`);
1188
- const type = pascalCase(`WServiceWith_${name}`);
1189
- const value = generateArray(props.map((v) => v.name));
1190
- return `export const ${constant}: ${type}[] = ${value};`;
1191
- }), ...typeGuards);
1192
- };
1193
-
1123
+ const entityDescriptors = /* @__PURE__ */ new Map();
1124
+ for (const service of services) for (const fn of service.functions) {
1125
+ if (!FILTER_REGEX.test(fn.name)) continue;
1126
+ entityDescriptors.set(fn.name, [...entityDescriptors.get(fn.name) ?? [], {
1127
+ name: service.name,
1128
+ required: true,
1129
+ type: `${pascalCase(service.name)}Service_${pascalCase(fn.name)}`
1130
+ }]);
1131
+ }
1132
+ const descriptors = [...entityDescriptors.entries()];
1133
+ const typeGuards = [];
1134
+ for (const [name] of descriptors) {
1135
+ const constant = camelCase(`wServiceWith_${name}_Names`);
1136
+ const service = pascalCase(`WServiceWith_${name}`);
1137
+ const guard = `(service: string | undefined): service is ${service} =>\n${indent(`${constant}.includes(service as ${service});`)}`;
1138
+ typeGuards.push(`export const is${service} = ${guard}`);
1139
+ }
1140
+ return generateStatements(...descriptors.map(([name, props]) => generateInterface(pascalCase(`WServicesWith_${name}`), props)), ...descriptors.map(([name]) => generateType(pascalCase(`WServiceWith_${name}`), `keyof ${pascalCase(`WServicesWith_${name}`)}`)), ...descriptors.map(([name, props]) => {
1141
+ return `export const ${camelCase(`wServiceWith_${name}_Names`)}: ${pascalCase(`WServiceWith_${name}`)}[] = ${generateArray(props.map((v) => v.name))};`;
1142
+ }), ...typeGuards);
1143
+ };
1144
+ //#endregion
1145
+ //#region src/generator/05-maps/index.ts
1194
1146
  const generateMaps = (enums, entities, services, context, options) => {
1195
- const enumInstances = `export const wEnums = ${generateObject([...enums.keys()].map((v) => ({ key: v, value: v })))};`;
1196
- const entityNames = `export const wEntityNames: WEntity[] = ${generateArray([...entities.keys()])};`;
1197
- const generatedServices = [...services.values()];
1198
- const serviceInstances = `export const wServices = ${generateObject(generatedServices.map((v) => ({
1199
- key: v.name,
1200
- value: `${v.serviceFnName}()`,
1201
- comment: v.deprecated ? '@deprecated' : undefined
1202
- })))};`;
1203
- const serviceFactories = `export const wServiceFactories = ${generateObject(generatedServices.map((v) => ({
1204
- key: v.name,
1205
- value: v.serviceFnName,
1206
- comment: v.deprecated ? '@deprecated' : undefined
1207
- })))};`;
1208
- return generateStatements(
1209
- /* Enums */
1210
- generateInterface('WEnums', [...enums.keys()].map((name) => ({ name, type: name, required: true }))), generateType('WEnum', 'keyof WEnums'), enumInstances,
1211
- /* Entities */
1212
- generateInterface('WEntities', [
1213
- ...[...entities.entries()].map(([name, entity]) => ({
1214
- name,
1215
- type: entity.interfaceName,
1216
- required: true
1217
- })),
1218
- ...generatedServices
1219
- .filter(({ relatedEntity }) => !!relatedEntity)
1220
- .filter(({ name }) => !entities.get(name))
1221
- .map(({ name, relatedEntity }) => ({
1222
- name,
1223
- type: relatedEntity.interfaceName,
1224
- required: true
1225
- }))
1226
- ].sort((a, b) => (a.name > b.name ? 1 : -1))), generateType('WEntity', 'keyof WEntities'), entityNames,
1227
- /* Services */
1228
- serviceInstances, generateType('WServices', 'typeof wServices'), generateType('WService', 'keyof WServices'), serviceFactories, generateType('WServiceFactories', 'typeof wServiceFactories'),
1229
- /* Service Utils */
1230
- generateGroupedServices(generatedServices), generateCustomValueServices(generatedServices),
1231
- /* Entity Properties (Runtime Meta Infos) */
1232
- generateEntityProperties(entities, generatedServices, options));
1233
- };
1234
-
1147
+ const enumInstances = `export const wEnums = ${generateObject([...enums.keys()].map((v) => ({
1148
+ key: v,
1149
+ value: v
1150
+ })))};`;
1151
+ const entityNames = `export const wEntityNames: WEntity[] = ${generateArray([...entities.keys()])};`;
1152
+ const generatedServices = [...services.values()];
1153
+ const serviceInstances = `export const wServices = ${generateObject(generatedServices.map((v) => ({
1154
+ key: v.name,
1155
+ value: `${v.serviceFnName}()`,
1156
+ comment: v.deprecated ? "@deprecated" : void 0
1157
+ })))};`;
1158
+ const serviceFactories = `export const wServiceFactories = ${generateObject(generatedServices.map((v) => ({
1159
+ key: v.name,
1160
+ value: v.serviceFnName,
1161
+ comment: v.deprecated ? "@deprecated" : void 0
1162
+ })))};`;
1163
+ return generateStatements(generateInterface("WEnums", [...enums.keys()].map((name) => ({
1164
+ name,
1165
+ type: name,
1166
+ required: true
1167
+ }))), generateType("WEnum", "keyof WEnums"), enumInstances, generateInterface("WEntities", [...[...entities.entries()].map(([name, entity]) => ({
1168
+ name,
1169
+ type: entity.interfaceName,
1170
+ required: true
1171
+ })), ...generatedServices.filter(({ relatedEntity }) => !!relatedEntity).filter(({ name }) => !entities.get(name)).map(({ name, relatedEntity }) => ({
1172
+ name,
1173
+ type: relatedEntity.interfaceName,
1174
+ required: true
1175
+ }))].sort((a, b) => a.name > b.name ? 1 : -1)), generateType("WEntity", "keyof WEntities"), entityNames, serviceInstances, generateType("WServices", "typeof wServices"), generateType("WService", "keyof WServices"), serviceFactories, generateType("WServiceFactories", "typeof wServiceFactories"), generateGroupedServices(generatedServices), generateCustomValueServices(generatedServices), generateEntityProperties(entities, generatedServices, options));
1176
+ };
1177
+ //#endregion
1178
+ //#region src/utils/weclapp/extractRelatedEntityName.ts
1235
1179
  function extractRelatedEntityName(serviceEndpoints, responses) {
1236
- const rootEndpoint = serviceEndpoints.find((v) => v.endpoint.type === WeclappEndpointType.ROOT);
1237
- if (!rootEndpoint)
1238
- return;
1239
- const response = rootEndpoint?.path.get?.responses['200'];
1240
- if (!response)
1241
- return;
1242
- let responseObject;
1243
- if (isReferenceObject(response)) {
1244
- const refName = getRefName(response);
1245
- responseObject = responses.get(refName);
1246
- }
1247
- else {
1248
- responseObject = response;
1249
- }
1250
- const responseSchema = responseObject?.content?.['application/json'].schema;
1251
- if (responseSchema) {
1252
- if (isReferenceObject(responseSchema)) {
1253
- return;
1254
- }
1255
- const resultSchema = responseSchema.properties?.result;
1256
- if (!resultSchema) {
1257
- return;
1258
- }
1259
- if (isReferenceObject(resultSchema)) {
1260
- return getRefName(resultSchema);
1261
- }
1262
- else if (isArraySchemaObject(resultSchema)) {
1263
- const resultItemSchema = resultSchema.items;
1264
- if (isReferenceObject(resultItemSchema)) {
1265
- return getRefName(resultItemSchema);
1266
- }
1267
- }
1268
- }
1180
+ const rootEndpoint = serviceEndpoints.find((v) => v.endpoint.type === WeclappEndpointType.ROOT);
1181
+ if (!rootEndpoint) return;
1182
+ const response = rootEndpoint?.path.get?.responses["200"];
1183
+ if (!response) return;
1184
+ let responseObject;
1185
+ if (isReferenceObject(response)) {
1186
+ const refName = getRefName(response);
1187
+ responseObject = responses.get(refName);
1188
+ } else responseObject = response;
1189
+ const responseSchema = responseObject?.content?.["application/json"].schema;
1190
+ if (responseSchema) {
1191
+ if (isReferenceObject(responseSchema)) return;
1192
+ const resultSchema = responseSchema.properties?.result;
1193
+ if (!resultSchema) return;
1194
+ if (isReferenceObject(resultSchema)) return getRefName(resultSchema);
1195
+ else if (isArraySchemaObject(resultSchema)) {
1196
+ const resultItemSchema = resultSchema.items;
1197
+ if (isReferenceObject(resultItemSchema)) return getRefName(resultItemSchema);
1198
+ }
1199
+ }
1269
1200
  }
1270
-
1201
+ //#endregion
1202
+ //#region src/utils/weclapp/extractContext.ts
1271
1203
  const extractServiceAliases = (endpoints, responses) => {
1272
- const aliases = new Map();
1273
- for (const [serviceName, serviceEndpoints] of endpoints) {
1274
- const relatedEntityName = extractRelatedEntityName(serviceEndpoints, responses);
1275
- if (relatedEntityName)
1276
- aliases.set(serviceName, relatedEntityName);
1277
- }
1278
- return aliases;
1204
+ const aliases = /* @__PURE__ */ new Map();
1205
+ for (const [serviceName, serviceEndpoints] of endpoints) {
1206
+ const relatedEntityName = extractRelatedEntityName(serviceEndpoints, responses);
1207
+ if (relatedEntityName) aliases.set(serviceName, relatedEntityName);
1208
+ }
1209
+ return aliases;
1279
1210
  };
1280
1211
  const extractContext = (doc) => {
1281
- const endpoints = parseEndpointsPaths(doc.paths);
1282
- const schemas = new Map();
1283
- for (const [name, schema] of Object.entries(doc.components?.schemas ?? {})) {
1284
- if (!isReferenceObject(schema)) {
1285
- schemas.set(name, schema);
1286
- }
1287
- }
1288
- const responses = new Map();
1289
- for (const [name, response] of Object.entries(doc.components?.responses ?? {})) {
1290
- if (!isReferenceObject(response)) {
1291
- responses.set(name, response);
1292
- }
1293
- }
1294
- const parameters = new Map();
1295
- for (const [name, parameter] of Object.entries(doc.components?.parameters ?? {})) {
1296
- if (!isReferenceObject(parameter)) {
1297
- parameters.set(name, parameter);
1298
- }
1299
- }
1300
- const requestBodies = new Map();
1301
- for (const [name, requestBody] of Object.entries(doc.components?.requestBodies ?? {})) {
1302
- if (!isReferenceObject(requestBody)) {
1303
- requestBodies.set(name, requestBody);
1304
- }
1305
- }
1306
- const aliases = extractServiceAliases(endpoints, responses);
1307
- return { endpoints, schemas, responses, parameters, requestBodies, aliases };
1308
- };
1309
-
1212
+ const endpoints = parseEndpointsPaths(doc.paths);
1213
+ const schemas = /* @__PURE__ */ new Map();
1214
+ for (const [name, schema] of Object.entries(doc.components?.schemas ?? {})) if (!isReferenceObject(schema)) schemas.set(name, schema);
1215
+ const responses = /* @__PURE__ */ new Map();
1216
+ for (const [name, response] of Object.entries(doc.components?.responses ?? {})) if (!isReferenceObject(response)) responses.set(name, response);
1217
+ const parameters = /* @__PURE__ */ new Map();
1218
+ for (const [name, parameter] of Object.entries(doc.components?.parameters ?? {})) if (!isReferenceObject(parameter)) parameters.set(name, parameter);
1219
+ const requestBodies = /* @__PURE__ */ new Map();
1220
+ for (const [name, requestBody] of Object.entries(doc.components?.requestBodies ?? {})) if (!isReferenceObject(requestBody)) requestBodies.set(name, requestBody);
1221
+ return {
1222
+ endpoints,
1223
+ schemas,
1224
+ responses,
1225
+ parameters,
1226
+ requestBodies,
1227
+ aliases: extractServiceAliases(endpoints, responses)
1228
+ };
1229
+ };
1230
+ //#endregion
1231
+ //#region src/generator/generate.ts
1310
1232
  const generate = (doc, options) => {
1311
- const context = extractContext(doc);
1312
- const base = generateBase(doc.info.version, options);
1313
- const enums = generateEnums(context);
1314
- const entities = generateEntities(context);
1315
- const services = generateServices(entities, context, options);
1316
- const maps = generateMaps(enums, entities, services, context, options);
1317
- return generateStatements(generateBlockComment('BASE', base), generateBlockComment('ENUMS', generateStatements(...[...enums.values()].map((v) => v.source))), generateBlockComment('ENTITIES', generateStatements(...[...entities.values()].map((v) => v.source))), generateBlockComment('FILTERS', generateStatements(...[...entities.values()].map((v) => v.filterSource))), generateBlockComment('SERVICES', generateStatements(...[...services.values()].map((v) => v.source))), generateBlockComment('MAPS', maps));
1318
- };
1319
-
1320
- const hash = (content, algorithm = 'sha256') => {
1321
- const hash = createHash(algorithm);
1322
- if (Array.isArray(content)) {
1323
- content.map(hash.update.bind(hash));
1324
- }
1325
- else {
1326
- hash.update(content);
1327
- }
1328
- return hash.digest('hex');
1329
- };
1330
-
1331
- /* eslint-disable @typescript-eslint/no-unsafe-assignment */
1233
+ const context = extractContext(doc);
1234
+ const base = generateBase(doc.info.version, options);
1235
+ const enums = generateEnums(context);
1236
+ const entities = generateEntities(context);
1237
+ const services = generateServices(entities, context, options);
1238
+ const maps = generateMaps(enums, entities, services, context, options);
1239
+ return generateStatements(generateBlockComment("BASE", base), generateBlockComment("ENUMS", generateStatements(...[...enums.values()].map((v) => v.source))), generateBlockComment("ENTITIES", generateStatements(...[...entities.values()].map((v) => v.source))), generateBlockComment("FILTERS", generateStatements(...[...entities.values()].map((v) => v.filterSource))), generateBlockComment("SERVICES", generateStatements(...[...services.values()].map((v) => v.source))), generateBlockComment("MAPS", maps));
1240
+ };
1241
+ //#endregion
1242
+ //#region src/utils/hash.ts
1243
+ const hash = (content, algorithm = "sha256") => {
1244
+ const hash = createHash(algorithm);
1245
+ if (Array.isArray(content)) content.map(hash.update.bind(hash));
1246
+ else hash.update(content);
1247
+ return hash.digest("hex");
1248
+ };
1249
+ //#endregion
1250
+ //#region src/cli.ts
1332
1251
  const cli = async () => {
1333
- const version = pkg.version;
1334
- const { argv } = yargs(hideBin(process.argv))
1335
- .scriptName('build-weclapp-sdk')
1336
- .usage('Usage: $0 <source> [flags]')
1337
- .version(version)
1338
- .example('$0 openapi.json', 'Generate the SDK based on a local openapi file')
1339
- .example('$0 openapi.json', 'Generate the SDK based on a local openapi file')
1340
- .example('$0 xxx.weclapp.com --key ...', 'Generate the SDK based on the openapi file from the given weclapp instance')
1341
- .help('h')
1342
- .alias('v', 'version')
1343
- .alias('h', 'help')
1344
- .option('k', {
1345
- alias: 'key',
1346
- describe: 'API Key (only needed when not using a local file)',
1347
- type: 'string'
1348
- })
1349
- .option('c', {
1350
- alias: 'cache',
1351
- describe: 'If the generated SDK should cached',
1352
- type: 'boolean'
1353
- })
1354
- .option('q', {
1355
- alias: 'query',
1356
- describe: 'Extra query params when fetching the openapi.json from a server',
1357
- type: 'string'
1358
- })
1359
- .option('generate-unique', {
1360
- describe: 'Generate .unique functions',
1361
- type: 'boolean'
1362
- })
1363
- .option('d', {
1364
- alias: 'deprecated',
1365
- describe: 'Include deprecated functions and services',
1366
- type: 'boolean'
1367
- })
1368
- .option('e', {
1369
- alias: 'from-env',
1370
- describe: 'Use env variables WECLAPP_BACKEND_URL and WECLAPP_API_KEY as credentials',
1371
- type: 'boolean'
1372
- })
1373
- .option('t', {
1374
- alias: 'target',
1375
- describe: 'Specify the target platform',
1376
- type: 'string',
1377
- choices: ['browser', 'browser.rx', 'node', 'node.rx']
1378
- })
1379
- .option('use-query-language', {
1380
- describe: 'Generate the new where property for some and count queries',
1381
- type: 'boolean'
1382
- })
1383
- .option('apiVersion', {
1384
- describe: 'Specify the api version (only needed when not using a local file)',
1385
- type: 'string'
1386
- })
1387
- .epilog(`Copyright ${new Date().getFullYear()} weclapp GmbH`);
1388
- if (argv.fromEnv) {
1389
- config();
1390
- }
1391
- const { WECLAPP_API_KEY, WECLAPP_BACKEND_URL } = process.env;
1392
- const { query, cache = false, deprecated = false, key = WECLAPP_API_KEY, apiVersion, _: [src = WECLAPP_BACKEND_URL] } = argv;
1393
- const options = {
1394
- deprecated,
1395
- generateUnique: argv.generateUnique ?? false,
1396
- target: argv.target ?? Target.BROWSER_PROMISES,
1397
- useQueryLanguage: argv.useQueryLanguage ?? false
1398
- };
1399
- if (!src || typeof src === 'number') {
1400
- return Promise.reject(new Error('Expected string as command'));
1401
- }
1402
- if (!Object.values(Target).includes(options.target)) {
1403
- logger.errorLn(`Unknown target: ${options.target}. Possible values are ${Object.values(Target).join(', ')}`);
1404
- return Promise.reject(new Error());
1405
- }
1406
- if (await stat(src).catch(() => false)) {
1407
- logger.infoLn(`Source is a file`);
1408
- const content = JSON.parse(await readFile(src, 'utf-8'));
1409
- return { cache, content, options };
1410
- }
1411
- logger.infoLn(`Source is a URL`);
1412
- if (!key) {
1413
- return Promise.reject(new Error('API key is missing'));
1414
- }
1415
- if (!apiVersion) {
1416
- return Promise.reject(new Error('API version is missing'));
1417
- }
1418
- const url = new URL(src.startsWith('http') ? src : `https://${src}`);
1419
- url.pathname = `/webapp/api/${apiVersion}/meta/openapi.json`;
1420
- if (query?.length) {
1421
- for (const param of query.split(',')) {
1422
- const [name, value] = param.split('=');
1423
- url.searchParams.set(name, value);
1424
- }
1425
- }
1426
- const content = await fetch(url.toString(), {
1427
- headers: { Accept: 'application/json', AuthenticationToken: key }
1428
- }).then((res) => (res.ok ? res.json() : undefined));
1429
- if (!content) {
1430
- logger.errorLn(`Couldn't fetch file ${url.toString()} `);
1431
- return Promise.reject(new Error());
1432
- }
1433
- else {
1434
- logger.infoLn(`Use remote file: ${url.toString()}`);
1435
- }
1436
- return { cache, content, options };
1437
- };
1438
-
1439
- const workingDir = resolve(currentDirname(), './sdk');
1440
- const cacheDir = resolve(currentDirname(), './.cache');
1441
- void (async () => {
1442
- const start = process.hrtime.bigint();
1443
- const { content: doc, cache: useCache, options } = await cli();
1444
- const workingDirPath = async (...paths) => {
1445
- const fullPath = resolve(workingDir, ...paths);
1446
- await mkdir(dirname(fullPath), { recursive: true });
1447
- return fullPath;
1448
- };
1449
- // Resolve cache dir and key
1450
- const cacheKey = hash([pkg.version, JSON.stringify(doc), JSON.stringify(options)]).slice(-8);
1451
- const cachedSdkDir = resolve(cacheDir, cacheKey);
1452
- // Remove old SDK
1453
- await rm(workingDir, { recursive: true, force: true });
1454
- if (useCache) {
1455
- logger.infoLn(`Cache ID: ${cacheKey}`);
1456
- }
1457
- if (useCache && (await stat(cachedSdkDir).catch(() => false))) {
1458
- // Copy cached SDK to working dir
1459
- logger.successLn(`Cache match! (${cachedSdkDir})`);
1460
- await cp(cachedSdkDir, workingDir, { recursive: true });
1461
- }
1462
- else {
1463
- // Write openapi.json file
1464
- await writeFile(await workingDirPath('openapi.json'), JSON.stringify(doc, null, 2));
1465
- logger.infoLn(`Generate sdk (target: ${options.target})`);
1466
- // Generate and write SDK (index.ts)
1467
- const sdk = generate(doc, options);
1468
- await writeFile(await workingDirPath('src', 'index.ts'), sdk.trim() + '\n');
1469
- // Bundle and write SDK
1470
- logger.infoLn('Bundle... (this may take some time)');
1471
- await bundle(workingDir, options.target);
1472
- // Remove index.ts (only bundle is required)
1473
- await rm(await workingDirPath('src'), { recursive: true, force: true });
1474
- if (useCache) {
1475
- // Copy SDK to cache
1476
- logger.successLn(`Caching SDK: (${cachedSdkDir})`);
1477
- await mkdir(cachedSdkDir, { recursive: true });
1478
- await cp(workingDir, cachedSdkDir, { recursive: true });
1479
- }
1480
- }
1481
- // Print job summary
1482
- const duration = (process.hrtime.bigint() - start) / 1000000n;
1483
- logger.successLn(`SDK built in ${prettyMs(Number(duration))}`);
1484
- logger.printSummary();
1485
- })()
1486
- .catch((error) => {
1487
- logger.errorLn(`Fatal error:`);
1488
- /* eslint-disable no-console */
1489
- console.error(error);
1490
- })
1491
- .finally(() => {
1492
- if (logger.errors)
1493
- process.exit(1);
1252
+ const version = pkg.version;
1253
+ const { argv } = yargs(hideBin(process.argv)).scriptName("build-weclapp-sdk").usage("Usage: $0 <source> [flags]").version(version).example("$0 openapi.json", "Generate the SDK based on a local openapi file").example("$0 openapi.json", "Generate the SDK based on a local openapi file").example("$0 xxx.weclapp.com --key ...", "Generate the SDK based on the openapi file from the given weclapp instance").help("h").alias("v", "version").alias("h", "help").option("k", {
1254
+ alias: "key",
1255
+ describe: "API Key (only needed when not using a local file)",
1256
+ type: "string"
1257
+ }).option("c", {
1258
+ alias: "cache",
1259
+ describe: "If the generated SDK should cached",
1260
+ type: "boolean"
1261
+ }).option("q", {
1262
+ alias: "query",
1263
+ describe: "Extra query params when fetching the openapi.json from a server",
1264
+ type: "string"
1265
+ }).option("generate-unique", {
1266
+ describe: "Generate .unique functions",
1267
+ type: "boolean"
1268
+ }).option("d", {
1269
+ alias: "deprecated",
1270
+ describe: "Include deprecated functions and services",
1271
+ type: "boolean"
1272
+ }).option("e", {
1273
+ alias: "from-env",
1274
+ describe: "Use env variables WECLAPP_BACKEND_URL and WECLAPP_API_KEY as credentials",
1275
+ type: "boolean"
1276
+ }).option("t", {
1277
+ alias: "target",
1278
+ describe: "Specify the target platform",
1279
+ type: "string",
1280
+ choices: [
1281
+ "browser",
1282
+ "browser.rx",
1283
+ "node",
1284
+ "node.rx"
1285
+ ]
1286
+ }).option("use-query-language", {
1287
+ describe: "Generate the new where property for some and count queries",
1288
+ type: "boolean"
1289
+ }).option("apiVersion", {
1290
+ describe: "Specify the api version (only needed when not using a local file)",
1291
+ type: "string"
1292
+ }).epilog(`Copyright ${(/* @__PURE__ */ new Date()).getFullYear()} weclapp GmbH`);
1293
+ if (argv.fromEnv) config();
1294
+ const { WECLAPP_API_KEY, WECLAPP_BACKEND_URL } = process.env;
1295
+ const { query, cache = false, deprecated = false, key = WECLAPP_API_KEY, apiVersion, _: [src = WECLAPP_BACKEND_URL] } = argv;
1296
+ const options = {
1297
+ deprecated,
1298
+ generateUnique: argv.generateUnique ?? false,
1299
+ target: argv.target ?? Target.BROWSER_PROMISES,
1300
+ useQueryLanguage: argv.useQueryLanguage ?? false
1301
+ };
1302
+ if (!src || typeof src === "number") return Promise.reject(/* @__PURE__ */ new Error("Expected string as command"));
1303
+ if (!Object.values(Target).includes(options.target)) {
1304
+ logger.errorLn(`Unknown target: ${options.target}. Possible values are ${Object.values(Target).join(", ")}`);
1305
+ return Promise.reject(/* @__PURE__ */ new Error());
1306
+ }
1307
+ if (await stat(src).catch(() => false)) {
1308
+ logger.infoLn(`Source is a file`);
1309
+ return {
1310
+ cache,
1311
+ content: JSON.parse(await readFile(src, "utf-8")),
1312
+ options
1313
+ };
1314
+ }
1315
+ logger.infoLn(`Source is a URL`);
1316
+ if (!key) return Promise.reject(/* @__PURE__ */ new Error("API key is missing"));
1317
+ if (!apiVersion) return Promise.reject(/* @__PURE__ */ new Error("API version is missing"));
1318
+ const url = new URL(src.startsWith("http") ? src : `https://${src}`);
1319
+ url.pathname = `/webapp/api/${apiVersion}/meta/openapi.json`;
1320
+ if (query?.length) for (const param of query.split(",")) {
1321
+ const [name, value] = param.split("=");
1322
+ url.searchParams.set(name, value);
1323
+ }
1324
+ const content = await fetch(url.toString(), { headers: {
1325
+ Accept: "application/json",
1326
+ AuthenticationToken: key
1327
+ } }).then((res) => res.ok ? res.json() : void 0);
1328
+ if (!content) {
1329
+ logger.errorLn(`Couldn't fetch file ${url.toString()} `);
1330
+ return Promise.reject(/* @__PURE__ */ new Error());
1331
+ } else logger.infoLn(`Use remote file: ${url.toString()}`);
1332
+ return {
1333
+ cache,
1334
+ content,
1335
+ options
1336
+ };
1337
+ };
1338
+ //#endregion
1339
+ //#region src/index.ts
1340
+ const workingDir = resolve(currentDirname(), "./sdk");
1341
+ const cacheDir = resolve(currentDirname(), "./.cache");
1342
+ (async () => {
1343
+ const start = process.hrtime.bigint();
1344
+ const { content: doc, cache: useCache, options } = await cli();
1345
+ const workingDirPath = async (...paths) => {
1346
+ const fullPath = resolve(workingDir, ...paths);
1347
+ await mkdir(dirname(fullPath), { recursive: true });
1348
+ return fullPath;
1349
+ };
1350
+ const cacheKey = hash([
1351
+ pkg.version,
1352
+ JSON.stringify(doc),
1353
+ JSON.stringify(options)
1354
+ ]).slice(-8);
1355
+ const cachedSdkDir = resolve(cacheDir, cacheKey);
1356
+ await rm(workingDir, {
1357
+ recursive: true,
1358
+ force: true
1359
+ });
1360
+ if (useCache) logger.infoLn(`Cache ID: ${cacheKey}`);
1361
+ if (useCache && await stat(cachedSdkDir).catch(() => false)) {
1362
+ logger.successLn(`Cache match! (${cachedSdkDir})`);
1363
+ await cp(cachedSdkDir, workingDir, { recursive: true });
1364
+ } else {
1365
+ await writeFile(await workingDirPath("openapi.json"), JSON.stringify(doc, null, 2));
1366
+ logger.infoLn(`Generate sdk (target: ${options.target})`);
1367
+ const sdk = generate(doc, options);
1368
+ await writeFile(await workingDirPath("src", "index.ts"), sdk.trim() + "\n");
1369
+ logger.infoLn("Bundle... (this may take some time)");
1370
+ await bundle(workingDir, options.target);
1371
+ await rm(await workingDirPath("src"), {
1372
+ recursive: true,
1373
+ force: true
1374
+ });
1375
+ if (useCache) {
1376
+ logger.successLn(`Caching SDK: (${cachedSdkDir})`);
1377
+ await mkdir(cachedSdkDir, { recursive: true });
1378
+ await cp(workingDir, cachedSdkDir, { recursive: true });
1379
+ }
1380
+ }
1381
+ const duration = (process.hrtime.bigint() - start) / 1000000n;
1382
+ logger.successLn(`SDK built in ${prettyMs(Number(duration))}`);
1383
+ logger.printSummary();
1384
+ })().catch((error) => {
1385
+ logger.errorLn(`Fatal error:`);
1386
+ console.error(error);
1387
+ }).finally(() => {
1388
+ if (logger.errors) process.exit(1);
1494
1389
  });
1390
+ //#endregion