tspace-spear 1.2.8 → 1.2.9

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 (74) hide show
  1. package/README.md +253 -71
  2. package/dist/cli/generators/app/index.js.map +1 -1
  3. package/dist/cli/generators/controller/template.d.ts +1 -1
  4. package/dist/cli/generators/controller/template.js +15 -8
  5. package/dist/cli/generators/controller/template.js.map +1 -1
  6. package/dist/cli/generators/dto/index.js +5 -3
  7. package/dist/cli/generators/dto/index.js.map +1 -1
  8. package/dist/cli/generators/module/index.js +3 -3
  9. package/dist/cli/generators/service/template.d.ts +1 -1
  10. package/dist/cli/generators/service/template.js +17 -17
  11. package/dist/cli/index.js +1 -0
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/lib/core/client/index.d.ts +13 -43
  14. package/dist/lib/core/client/index.js +47 -26
  15. package/dist/lib/core/client/index.js.map +1 -1
  16. package/dist/lib/core/{compiler → client}/types.d.ts +29 -0
  17. package/dist/lib/core/client/types.js.map +1 -0
  18. package/dist/lib/core/compiler/generator.d.ts +4 -6
  19. package/dist/lib/core/compiler/generator.js +168 -39
  20. package/dist/lib/core/compiler/generator.js.map +1 -1
  21. package/dist/lib/core/compiler/index.d.ts +2 -2
  22. package/dist/lib/core/compiler/index.js +2 -2
  23. package/dist/lib/core/compiler/index.js.map +1 -1
  24. package/dist/lib/core/compiler/pre-routes.d.ts +170 -34
  25. package/dist/lib/core/compiler/pre-routes.js +45 -25
  26. package/dist/lib/core/compiler/pre-routes.js.map +1 -1
  27. package/dist/lib/core/decorators/context.js +23 -15
  28. package/dist/lib/core/decorators/context.js.map +1 -1
  29. package/dist/lib/core/decorators/statusCode.js +3 -1
  30. package/dist/lib/core/decorators/statusCode.js.map +1 -1
  31. package/dist/lib/core/server/fast-router.d.ts +2 -2
  32. package/dist/lib/core/server/fast-router.js +17 -3
  33. package/dist/lib/core/server/fast-router.js.map +1 -1
  34. package/dist/lib/core/server/index.js +2 -2
  35. package/dist/lib/core/server/index.js.map +1 -1
  36. package/dist/lib/core/server/response.js +21 -1
  37. package/dist/lib/core/server/response.js.map +1 -1
  38. package/dist/lib/core/types/index.d.ts +32 -27
  39. package/package.json +6 -3
  40. package/dist/cli/app.d.ts +0 -1
  41. package/dist/cli/app.js +0 -32
  42. package/dist/cli/app.js.map +0 -1
  43. package/dist/cli/client.d.ts +0 -1
  44. package/dist/cli/client.js +0 -30
  45. package/dist/cli/client.js.map +0 -1
  46. package/dist/cli/controller.d.ts +0 -1
  47. package/dist/cli/controller.js +0 -169
  48. package/dist/cli/controller.js.map +0 -1
  49. package/dist/cli/middleware.d.ts +0 -1
  50. package/dist/cli/middleware.js +0 -16
  51. package/dist/cli/middleware.js.map +0 -1
  52. package/dist/client.d.ts +0 -1
  53. package/dist/client.js +0 -17
  54. package/dist/client.js.map +0 -1
  55. package/dist/common/middlewares/log.middleware.d.ts +0 -2
  56. package/dist/common/middlewares/log.middleware.js +0 -12
  57. package/dist/common/middlewares/log.middleware.js.map +0 -1
  58. package/dist/index.d.ts +0 -4
  59. package/dist/index.js +0 -32
  60. package/dist/index.js.map +0 -1
  61. package/dist/lib/core/compiler/types.js.map +0 -1
  62. package/dist/modules/cats/cat.controller.d.ts +0 -58
  63. package/dist/modules/cats/cat.controller.js +0 -90
  64. package/dist/modules/cats/cat.controller.js.map +0 -1
  65. package/dist/modules/cats/cat.dto.d.ts +0 -8
  66. package/dist/modules/cats/cat.dto.js +0 -44
  67. package/dist/modules/cats/cat.dto.js.map +0 -1
  68. package/dist/modules/cats/cat.service.d.ts +0 -23
  69. package/dist/modules/cats/cat.service.js +0 -56
  70. package/dist/modules/cats/cat.service.js.map +0 -1
  71. package/dist/tests/e2e..test.d.ts +0 -1
  72. package/dist/tests/e2e..test.js +0 -16
  73. package/dist/tests/e2e..test.js.map +0 -1
  74. /package/dist/lib/core/{compiler → client}/types.js +0 -0
@@ -1,15 +1,4 @@
1
- import type { AnyRoutes, RoutesWithMethod, RequestBody, RequestQuery, RequestParams, RequestFiles, ResponseType } from "../compiler/types";
2
- type RequestInput<TRoutes extends AnyRoutes, TPath extends keyof TRoutes, TMethod extends keyof TRoutes[TPath]> = RequestParams<TRoutes, TPath, TMethod> extends never ? {
3
- params?: never;
4
- query?: RequestQuery<TRoutes, TPath, TMethod>;
5
- body?: RequestBody<TRoutes, TPath, TMethod>;
6
- files?: RequestFiles<TRoutes, TPath, TMethod>;
7
- } : {
8
- params: RequestParams<TRoutes, TPath, TMethod>;
9
- query?: RequestQuery<TRoutes, TPath, TMethod>;
10
- body?: RequestBody<TRoutes, TPath, TMethod>;
11
- files?: RequestFiles<TRoutes, TPath, TMethod>;
12
- };
1
+ import type { AnyRoutes, RoutesWithMethod, ResponseType, RequestInput, OptionalIfEmpty, ApiResponse } from "./types";
13
2
  /**
14
3
  * Type-safe HTTP client built on top of the native Fetch API.
15
4
  *
@@ -41,42 +30,23 @@ type RequestInput<TRoutes extends AnyRoutes, TPath extends keyof TRoutes, TMetho
41
30
  * })
42
31
  *
43
32
  * // fully typed response
44
- * console.log(res.cats)
33
+ * if(res.ok)
34
+ * console.log(res.cats)
45
35
  * ```
46
36
  */
47
37
  declare class ApiClient<TRoutes extends AnyRoutes> {
48
38
  private baseURL;
49
39
  constructor(baseURL: string);
50
- protected request<TPath extends keyof TRoutes, TMethod extends keyof TRoutes[TPath]>(method: TMethod, path: TPath, input?: RequestInput<TRoutes, TPath, TMethod>): Promise<{
51
- ok: boolean;
52
- status: number;
53
- data: ResponseType<TRoutes, TPath, TMethod>;
54
- }>;
55
- get<TPath extends RoutesWithMethod<TRoutes, "GET">>(path: TPath, input?: RequestInput<TRoutes, TPath, "GET">): Promise<{
56
- ok: boolean;
57
- status: number;
58
- data: ResponseType<TRoutes, TPath, "GET">;
59
- }>;
60
- post<TPath extends RoutesWithMethod<TRoutes, "POST">>(path: TPath, input: RequestInput<TRoutes, TPath, "POST">): Promise<{
61
- ok: boolean;
62
- status: number;
63
- data: ResponseType<TRoutes, TPath, "POST">;
64
- }>;
65
- put<TPath extends RoutesWithMethod<TRoutes, "PUT">>(path: TPath, input: RequestInput<TRoutes, TPath, "PUT">): Promise<{
66
- ok: boolean;
67
- status: number;
68
- data: ResponseType<TRoutes, TPath, "PUT">;
69
- }>;
70
- patch<TPath extends RoutesWithMethod<TRoutes, "PATCH">>(path: TPath, input: RequestInput<TRoutes, TPath, "PATCH">): Promise<{
71
- ok: boolean;
72
- status: number;
73
- data: ResponseType<TRoutes, TPath, "PATCH">;
74
- }>;
75
- delete<TPath extends RoutesWithMethod<TRoutes, "DELETE">>(path: TPath, input?: RequestInput<TRoutes, TPath, "DELETE">): Promise<{
76
- ok: boolean;
77
- status: number;
78
- data: ResponseType<TRoutes, TPath, "DELETE">;
79
- }>;
40
+ private request;
41
+ get<TPath extends RoutesWithMethod<TRoutes, "GET">>(path: TPath, ...args: OptionalIfEmpty<RequestInput<TRoutes, TPath, "GET">>): Promise<ApiResponse<ResponseType<TRoutes, TPath, "GET">>>;
42
+ post<TPath extends RoutesWithMethod<TRoutes, "POST">>(path: TPath, ...args: OptionalIfEmpty<RequestInput<TRoutes, TPath, "POST">>): Promise<ApiResponse<ResponseType<TRoutes, TPath, "POST">>>;
43
+ put<TPath extends RoutesWithMethod<TRoutes, "PUT">>(path: TPath, ...args: OptionalIfEmpty<RequestInput<TRoutes, TPath, "PUT">>): Promise<ApiResponse<ResponseType<TRoutes, TPath, "PUT">>>;
44
+ patch<TPath extends RoutesWithMethod<TRoutes, "PATCH">>(path: TPath, ...args: OptionalIfEmpty<RequestInput<TRoutes, TPath, "PATCH">>): Promise<ApiResponse<ResponseType<TRoutes, TPath, "PATCH">>>;
45
+ delete<TPath extends RoutesWithMethod<TRoutes, "DELETE">>(path: TPath, ...args: OptionalIfEmpty<RequestInput<TRoutes, TPath, "DELETE">>): Promise<ApiResponse<ResponseType<TRoutes, TPath, "DELETE">>>;
46
+ upload<TMethod extends "POST" | "PUT" | "PATCH" = "POST", TPath extends RoutesWithMethod<TRoutes, TMethod> = RoutesWithMethod<TRoutes, TMethod>>(path: TPath, options: {
47
+ method?: TMethod;
48
+ formdata: FormData;
49
+ }): Promise<ApiResponse<ResponseType<TRoutes, TPath, TMethod>>>;
80
50
  }
81
51
  export { ApiClient };
82
52
  export default ApiClient;
@@ -25,17 +25,25 @@ var __importStar = (this && this.__importStar) || function (mod) {
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.ApiClient = void 0;
27
27
  let fetchFn = null;
28
- async function getFetch() {
28
+ const getFetch = async () => {
29
29
  if (fetchFn)
30
30
  return fetchFn;
31
- if (globalThis.fetch) {
32
- fetchFn = globalThis.fetch;
31
+ // Browser OR modern Node v18+ (preferred)
32
+ if (typeof globalThis.fetch === "function") {
33
+ fetchFn = globalThis.fetch.bind(globalThis);
33
34
  return fetchFn;
34
35
  }
36
+ // Legacy Node fallback
35
37
  const mod = await Promise.resolve().then(() => __importStar(require("node-fetch")));
36
38
  fetchFn = mod.default;
37
39
  return fetchFn;
38
- }
40
+ };
41
+ const isFormData = (value) => {
42
+ return (value != null &&
43
+ typeof value === "object" &&
44
+ typeof value.append === "function" &&
45
+ typeof value.getHeaders === "function");
46
+ };
39
47
  /**
40
48
  * Type-safe HTTP client built on top of the native Fetch API.
41
49
  *
@@ -67,7 +75,8 @@ async function getFetch() {
67
75
  * })
68
76
  *
69
77
  * // fully typed response
70
- * console.log(res.cats)
78
+ * if(res.ok)
79
+ * console.log(res.cats)
71
80
  * ```
72
81
  */
73
82
  class ApiClient {
@@ -92,50 +101,62 @@ class ApiClient {
92
101
  if (!fetchFn) {
93
102
  throw new Error("Fetch is not available. Use Node 18+ or polyfill.");
94
103
  }
104
+ let body = input?.body
105
+ ? JSON.stringify(input.body)
106
+ : undefined;
107
+ let headers = {
108
+ "Content-Type": "application/json",
109
+ };
110
+ const isFileUpload = isFormData(input?.body);
111
+ if (isFileUpload) {
112
+ body = input?.body;
113
+ headers = undefined;
114
+ }
95
115
  const res = await fetchFn(url, {
96
116
  method: method,
97
- headers: {
98
- "Content-Type": "application/json",
99
- },
100
- body: input?.body
101
- ? JSON.stringify(input.body)
102
- : undefined,
117
+ headers,
118
+ body
103
119
  });
104
120
  const contentType = res.headers.get("content-type");
105
121
  const isJson = contentType?.includes("application/json");
106
122
  const data = isJson
107
123
  ? await res.json()
108
124
  : await res.text();
109
- // if (!res.ok) {
110
- // throw new Error(
111
- // data?.message ||
112
- // data?.error ||
113
- // (typeof data === "string"
114
- // ? data
115
- // : `HTTP ${res.status}`),
116
- // );
117
- // }
118
125
  return {
119
126
  ok: res.ok,
127
+ headers: res.headers,
120
128
  status: res.status,
121
- data,
129
+ data: data,
122
130
  };
123
131
  }
124
- async get(path, input) {
132
+ async get(path, ...args) {
133
+ const input = args[0];
125
134
  return this.request("GET", path, input);
126
135
  }
127
- async post(path, input) {
136
+ async post(path, ...args) {
137
+ const input = args[0];
128
138
  return this.request("POST", path, input);
129
139
  }
130
- async put(path, input) {
140
+ async put(path, ...args) {
141
+ const input = args[0];
131
142
  return this.request("PUT", path, input);
132
143
  }
133
- async patch(path, input) {
144
+ async patch(path, ...args) {
145
+ const input = args[0];
134
146
  return this.request("PATCH", path, input);
135
147
  }
136
- async delete(path, input) {
148
+ async delete(path, ...args) {
149
+ const input = args[0];
137
150
  return this.request("DELETE", path, input);
138
151
  }
152
+ async upload(path, options) {
153
+ const { method = "POST", formdata } = options;
154
+ return this.request(method, path,
155
+ //@ts-ignore
156
+ {
157
+ body: formdata
158
+ });
159
+ }
139
160
  }
140
161
  exports.ApiClient = ApiClient;
141
162
  exports.default = ApiClient;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/core/client/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/core/client/index.ts"],"names":[],"mappings":"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"}
@@ -12,3 +12,32 @@ export type RequestFiles<TRoutes extends AnyRoutes, TPath extends keyof TRoutes,
12
12
  export type ResponseType<TRoutes extends AnyRoutes, TPath extends keyof TRoutes, TMethod extends keyof TRoutes[TPath]> = TRoutes[TPath][TMethod] extends {
13
13
  response: infer R;
14
14
  } ? Awaited<R> : never;
15
+ export type Prettify<T> = {
16
+ [K in keyof T]: T[K];
17
+ } & {};
18
+ export type ExactProperty<Key extends string, T> = [
19
+ T
20
+ ] extends [never] ? {
21
+ [K in Key]?: never;
22
+ } : undefined extends T ? {
23
+ [K in Key]?: T;
24
+ } : {} extends T ? {
25
+ [K in Key]?: T;
26
+ } : {
27
+ [K in Key]: T;
28
+ };
29
+ export type OptionalIfEmpty<T> = {} extends T ? [input?: T] : [input: T];
30
+ export type RequestInput<TRoutes extends AnyRoutes, TPath extends keyof TRoutes, TMethod extends keyof TRoutes[TPath]> = Prettify<ExactProperty<"params", RequestParams<TRoutes, TPath, TMethod>> & ExactProperty<"query", RequestQuery<TRoutes, TPath, TMethod>> & ExactProperty<"body", RequestBody<TRoutes, TPath, TMethod>> & ExactProperty<"files", RequestFiles<TRoutes, TPath, TMethod>>>;
31
+ export type SuccessStatus = 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 226;
32
+ export type ErrorStatus = 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511;
33
+ export type ApiResponse<T, E = any> = {
34
+ ok: true;
35
+ status: SuccessStatus;
36
+ headers: Headers;
37
+ data: T;
38
+ } | {
39
+ ok: false;
40
+ status: ErrorStatus;
41
+ headers: Headers;
42
+ data: E;
43
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/lib/core/client/types.ts"],"names":[],"mappings":""}
@@ -1,18 +1,16 @@
1
1
  type Route = {
2
2
  method: string;
3
3
  path: string;
4
- response: string;
5
4
  body: string;
6
5
  params: string;
7
6
  query: string;
8
7
  files: string;
8
+ response: string;
9
9
  };
10
10
  type Options = {
11
- controllers: {
12
- folder: string;
13
- name: RegExp;
14
- };
11
+ folder: string;
12
+ name: RegExp;
15
13
  output?: string;
16
14
  };
17
- export declare function generateRoutes(options: Options): Promise<Route[] | undefined>;
15
+ export declare const generateRoutes: (globalPrefix: string, options: Options) => Promise<Route[] | undefined>;
18
16
  export {};
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.generateRoutes = generateRoutes;
6
+ exports.generateRoutes = void 0;
7
7
  const ts_morph_1 = require("ts-morph");
8
8
  const typescript_1 = __importDefault(require("typescript"));
9
9
  const fs_1 = __importDefault(require("fs"));
@@ -17,15 +17,30 @@ const HTTP_METHODS = {
17
17
  Options: "OPTIONS",
18
18
  Head: "HEAD",
19
19
  };
20
- function normalizePath(p) {
20
+ const normalizeType = (t) => {
21
+ return t
22
+ .split("|")
23
+ .map(v => v.trim())
24
+ .filter(v => v !== "null" &&
25
+ v !== "undefined")[0] || "string";
26
+ };
27
+ const maybeObject = (v) => {
28
+ const s = v.trim();
29
+ return s.startsWith("{") && s.endsWith("}");
30
+ };
31
+ const maybeArrayObject = (v) => {
32
+ const s = v.trim();
33
+ return s.endsWith("}[]");
34
+ };
35
+ const normalizePath = (p) => {
21
36
  return ("/" +
22
37
  p
23
38
  .replace(/['"`]/g, "")
24
39
  .replace(/\/+/g, "/")
25
40
  .replace(/\/$/, "")
26
41
  .replace(/^\//, ""));
27
- }
28
- function splitTopLevel(input) {
42
+ };
43
+ const splitTopLevel = (input) => {
29
44
  const parts = [];
30
45
  let current = "";
31
46
  let depth = 0;
@@ -45,11 +60,11 @@ function splitTopLevel(input) {
45
60
  parts.push(current.trim());
46
61
  }
47
62
  return parts;
48
- }
49
- function parseType(type) {
63
+ };
64
+ const parseType = (type) => {
50
65
  type = type.trim();
51
66
  if (type === "never") {
52
- return null;
67
+ return undefined;
53
68
  }
54
69
  if (type.startsWith("Record<")) {
55
70
  return {};
@@ -121,6 +136,8 @@ function parseType(type) {
121
136
  return "boolean";
122
137
  if (type === "date")
123
138
  return "date";
139
+ if (type === "Date")
140
+ return "Date";
124
141
  if (type === "string | undefined")
125
142
  return "string";
126
143
  if (type === "number | undefined")
@@ -129,6 +146,8 @@ function parseType(type) {
129
146
  return "boolean";
130
147
  if (type === "date | undefined")
131
148
  return "date";
149
+ if (type === "Date | undefined")
150
+ return "Date";
132
151
  if (type.includes("| undefined")) {
133
152
  return type;
134
153
  }
@@ -139,11 +158,9 @@ function parseType(type) {
139
158
  return type.replace(/"/g, "");
140
159
  }
141
160
  // fallback
142
- return {
143
- $ref: type
144
- };
145
- }
146
- function resolveType(type) {
161
+ return "string";
162
+ };
163
+ const resolveType = (type) => {
147
164
  if (type.getSymbol()?.getName() === "Promise") {
148
165
  type = type.getTypeArguments()[0];
149
166
  }
@@ -161,8 +178,28 @@ function resolveType(type) {
161
178
  return "any";
162
179
  if (type.isUnknown())
163
180
  return "unknown";
164
- if (type.isStringLiteral())
181
+ if (type.isStringLiteral() ||
182
+ type.isBooleanLiteral() ||
183
+ type.isNumberLiteral())
165
184
  return type.getText();
185
+ if (type.getText() === 'Date' &&
186
+ type.getSymbol()?.getName() === 'Date') {
187
+ return "Date";
188
+ }
189
+ if (type.getText().includes("ServerResponse") &&
190
+ type.getText().includes("THttpResponder")) {
191
+ const filtered = type
192
+ .getIntersectionTypes()
193
+ .filter((t) => {
194
+ const text = t.getText();
195
+ return (!text.includes("ServerResponse") &&
196
+ !text.includes("THttpResponder"));
197
+ });
198
+ const t = filtered[0];
199
+ if (t == null)
200
+ return 'never';
201
+ return resolveType(t);
202
+ }
166
203
  if (type.isUnion()) {
167
204
  const text = type.getText();
168
205
  if (text.includes('| null') || text.includes('| undefined')) {
@@ -185,8 +222,8 @@ function resolveType(type) {
185
222
  const el = type.getArrayElementTypeOrThrow();
186
223
  return `${resolveType(el)}[]`;
187
224
  }
188
- const props = type.getProperties();
189
- if (props.length) {
225
+ if (type.getProperties().length) {
226
+ const props = type.getProperties();
190
227
  const obj = [];
191
228
  for (const prop of props) {
192
229
  const decl = prop.getDeclarations()[0];
@@ -214,8 +251,8 @@ function resolveType(type) {
214
251
  return `{ ${obj.join("; ")} }`;
215
252
  }
216
253
  return type.getText();
217
- }
218
- function extractPropertyType(type, key, node) {
254
+ };
255
+ const extractPropertyType = (type, key, node) => {
219
256
  const prop = type.getProperty(key);
220
257
  if (!prop)
221
258
  return "never";
@@ -226,12 +263,12 @@ function extractPropertyType(type, key, node) {
226
263
  if (!text || text.includes("undefined"))
227
264
  return "never";
228
265
  return resolveType(t) ?? "never";
229
- }
230
- async function generateRoutes(options) {
266
+ };
267
+ const generateRoutes = async (globalPrefix, options) => {
231
268
  const project = new ts_morph_1.Project({
232
269
  tsConfigFilePath: path_1.default.resolve(process.cwd(), "tsconfig.json"),
233
270
  });
234
- project.addSourceFilesAtPaths(path_1.default.join(options.controllers.folder, "**/*"));
271
+ project.addSourceFilesAtPaths(path_1.default.join(options.folder, "**/*"));
235
272
  const files = project.getSourceFiles();
236
273
  if (!files.length) {
237
274
  console.log("No controller files found");
@@ -240,7 +277,7 @@ async function generateRoutes(options) {
240
277
  const routes = [];
241
278
  for (const file of files) {
242
279
  const filename = file.getBaseName();
243
- if (!options.controllers.name.test(filename))
280
+ if (!options.name.test(filename))
244
281
  continue;
245
282
  for (const cls of file.getClasses()) {
246
283
  const controller = cls.getDecorator("Controller");
@@ -267,10 +304,12 @@ async function generateRoutes(options) {
267
304
  const firstParam = method.getParameters()[0];
268
305
  if (firstParam) {
269
306
  const type = firstParam.getType();
270
- body = extractPropertyType(type, "body", firstParam);
271
307
  params = extractPropertyType(type, "params", firstParam);
272
308
  query = extractPropertyType(type, "query", firstParam);
309
+ body = extractPropertyType(type, "body", firstParam);
273
310
  files = extractPropertyType(type, "files", firstParam);
311
+ if (body === 'Record<string, any>')
312
+ body = "never";
274
313
  }
275
314
  routes.push({
276
315
  method: http,
@@ -279,7 +318,7 @@ async function generateRoutes(options) {
279
318
  body,
280
319
  params,
281
320
  query,
282
- files,
321
+ files
283
322
  });
284
323
  }
285
324
  }
@@ -313,9 +352,93 @@ async function generateRoutes(options) {
313
352
  }`;
314
353
  })
315
354
  .join("\n");
316
- const formatValue = (v) => {
317
- if (typeof v === "string")
318
- return `"${v.replace(/"/g, '')}"`;
355
+ const formatExampleValue = (v) => {
356
+ if (v === null) {
357
+ return "null";
358
+ }
359
+ if (v === undefined) {
360
+ return "undefined";
361
+ }
362
+ if (typeof v === "string") {
363
+ const t = normalizeType(v.trim());
364
+ if (maybeObject(t)) {
365
+ const inner = t.trim().slice(1, -1);
366
+ const result = Object.fromEntries(splitTopLevel(inner)
367
+ .map(s => s.trim())
368
+ .filter(Boolean)
369
+ .map(pair => {
370
+ const idx = pair.indexOf(":");
371
+ const key = pair.slice(0, idx).trim();
372
+ const type = pair.slice(idx + 1).trim();
373
+ return [key.replace(/\?/g, ''), type];
374
+ }));
375
+ return formatExampleValue(result);
376
+ }
377
+ if (maybeArrayObject(t)) {
378
+ const s = v.trim();
379
+ const output = s.replace(/(\w+):\s*(\{[^}]+\})\[\]/, '$1: [$2]').match(/\{(.*)\}/)?.[1];
380
+ if (!output)
381
+ return `[]`;
382
+ const result = Object.fromEntries(splitTopLevel(output)
383
+ .map(s => s.trim())
384
+ .filter(Boolean)
385
+ .map(pair => {
386
+ const idx = pair.indexOf(":");
387
+ const key = pair.slice(0, idx).trim();
388
+ const type = pair.slice(idx + 1).trim();
389
+ return [key, type];
390
+ }));
391
+ return formatExampleValue(result);
392
+ }
393
+ switch (t) {
394
+ case "string":
395
+ return `"example"`;
396
+ case "string[]":
397
+ return `["example1", "example2", "example3"]`;
398
+ case "number":
399
+ return "123";
400
+ case "number[]":
401
+ return "[1 ,2, 3]";
402
+ case "boolean":
403
+ return "true";
404
+ case "boolean[]":
405
+ return "[true, false, true]";
406
+ case "null":
407
+ return "null";
408
+ case "null[]":
409
+ return "[null, null, null]";
410
+ case "undefined":
411
+ return "undefined";
412
+ case "undefined[]":
413
+ return "[undefined, undefined, undefined]";
414
+ case "date":
415
+ case "Date":
416
+ return `"2000-01-01T00:00:00.000Z"`;
417
+ case "date[]":
418
+ case "Date[]":
419
+ return `["2000-01-01T00:00:00.000Z","2000-01-02T00:00:00.000Z","2000-01-03T00:00:00.000Z"]`;
420
+ default:
421
+ return `"${t.replace(/"/g, "")}"`;
422
+ }
423
+ }
424
+ if (Array.isArray(v)) {
425
+ if (v.length === 0) {
426
+ return "[]";
427
+ }
428
+ return `[${formatExampleValue(v[0])}]`;
429
+ }
430
+ if (typeof v === "object") {
431
+ const entries = Object.entries(v).map(([key, value]) => {
432
+ if (key.includes("uuid")) {
433
+ return `${key}: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"`;
434
+ }
435
+ if (key === "id" || key.endsWith("id")) {
436
+ return `${key}: 123`;
437
+ }
438
+ return `${key}: ${formatExampleValue(value)}`;
439
+ });
440
+ return `{ ${entries.map(v => `${v}`).join(", ")} }`;
441
+ }
319
442
  return JSON.stringify(v);
320
443
  };
321
444
  const groupedValues = routes.reduce((acc, route) => {
@@ -336,11 +459,11 @@ async function generateRoutes(options) {
336
459
  const methodBlock = Object.entries(methods)
337
460
  .map(([method, c]) => `
338
461
  ${method}: {
339
- params: ${formatValue(c.params)},
340
- query: ${formatValue(c.query)},
341
- body: ${formatValue(c.body)},
342
- files: ${formatValue(c.files)},
343
- response: ${formatValue(c.response)}
462
+ params: ${formatExampleValue(c.params)},
463
+ query: ${formatExampleValue(c.query)},
464
+ body: ${formatExampleValue(c.body)},
465
+ files: ${formatExampleValue(c.files)},
466
+ response: ${formatExampleValue(c.response)}
344
467
  }`).join(",\n");
345
468
  return `
346
469
  "${path}": {
@@ -352,16 +475,20 @@ async function generateRoutes(options) {
352
475
  // @ts-nocheck
353
476
  // AUTO GENERATED FILE
354
477
  // DO NOT EDIT
478
+ // **Response values shown here are examples only.
479
+ ${globalPrefix ?
480
+ `// **The App is using the configuration:
481
+ // globalPrefix: '${globalPrefix}'` : ''}
355
482
 
356
483
  export const appRoutes = {
357
484
  ${routerMapValues}
358
- }
485
+ };
359
486
 
360
487
  export interface AppRoutes {
361
488
  ${routeMapTypes}
362
- }
489
+ };
363
490
 
364
- export type AppRoute = keyof AppRoutes
491
+ export type AppRoute = keyof AppRoutes;
365
492
  `;
366
493
  const outPath = options.output
367
494
  ? `${__dirname}/${options.output}/pre-routes.ts`
@@ -369,15 +496,17 @@ export type AppRoute = keyof AppRoutes
369
496
  await fs_1.default.promises.mkdir(path_1.default.dirname(outPath), {
370
497
  recursive: true,
371
498
  });
372
- await fs_1.default.promises.writeFile(outPath, output);
373
499
  const compiled = typescript_1.default.transpileModule(output, {
374
500
  compilerOptions: {
375
501
  module: typescript_1.default.ModuleKind.CommonJS,
376
- target: typescript_1.default.ScriptTarget.ES2020,
502
+ target: typescript_1.default.ScriptTarget.ESNext
377
503
  },
378
504
  });
379
- const jsPath = outPath.replace(/\.ts$/, ".js");
380
- await fs_1.default.promises.writeFile(jsPath, compiled.outputText, "utf8");
505
+ await Promise.all([
506
+ fs_1.default.promises.writeFile(outPath, output),
507
+ fs_1.default.promises.writeFile(outPath.replace(/\.ts$/, ".js"), compiled.outputText)
508
+ ]);
381
509
  return routes;
382
- }
510
+ };
511
+ exports.generateRoutes = generateRoutes;
383
512
  //# sourceMappingURL=generator.js.map