tspace-spear 1.2.7 → 1.2.9-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +347 -155
- package/dist/cli/generators/app/index.d.ts +1 -0
- package/dist/cli/generators/app/index.js +124 -0
- package/dist/cli/generators/app/index.js.map +1 -0
- package/dist/cli/generators/app/template.d.ts +1 -0
- package/dist/cli/generators/app/template.js +42 -0
- package/dist/cli/generators/app/template.js.map +1 -0
- package/dist/cli/generators/client/template.d.ts +1 -0
- package/dist/cli/generators/client/template.js +30 -0
- package/dist/cli/generators/client/template.js.map +1 -0
- package/dist/cli/generators/controller/index.d.ts +1 -0
- package/dist/cli/generators/controller/index.js +78 -0
- package/dist/cli/generators/controller/index.js.map +1 -0
- package/dist/cli/generators/controller/template.d.ts +1 -0
- package/dist/cli/generators/controller/template.js +108 -0
- package/dist/cli/generators/controller/template.js.map +1 -0
- package/dist/cli/generators/dto/index.d.ts +1 -0
- package/dist/cli/generators/dto/index.js +57 -0
- package/dist/cli/generators/dto/index.js.map +1 -0
- package/dist/cli/generators/dto/template.d.ts +1 -0
- package/dist/cli/generators/dto/template.js +32 -0
- package/dist/cli/generators/dto/template.js.map +1 -0
- package/dist/cli/generators/middleware/index.d.ts +1 -0
- package/dist/cli/generators/middleware/index.js +38 -0
- package/dist/cli/generators/middleware/index.js.map +1 -0
- package/dist/cli/generators/middleware/template.d.ts +1 -0
- package/dist/cli/generators/middleware/template.js +16 -0
- package/dist/cli/generators/middleware/template.js.map +1 -0
- package/dist/cli/generators/module/index.d.ts +1 -0
- package/dist/cli/generators/module/index.js +173 -0
- package/dist/cli/generators/module/index.js.map +1 -0
- package/dist/cli/generators/service/index.d.ts +1 -0
- package/dist/cli/generators/service/index.js +53 -0
- package/dist/cli/generators/service/index.js.map +1 -0
- package/dist/cli/generators/service/template.d.ts +1 -0
- package/dist/cli/generators/service/template.js +74 -0
- package/dist/cli/generators/service/template.js.map +1 -0
- package/dist/cli/generators/shared/index.d.ts +3 -0
- package/dist/cli/generators/shared/index.js +22 -0
- package/dist/cli/generators/shared/index.js.map +1 -0
- package/dist/cli/index.js +55 -96
- package/dist/cli/index.js.map +1 -1
- package/dist/lib/core/client/index.d.ts +13 -43
- package/dist/lib/core/client/index.js +70 -33
- package/dist/lib/core/client/index.js.map +1 -1
- package/dist/lib/core/client/types.d.ts +43 -0
- package/dist/lib/core/client/types.js +3 -0
- package/dist/lib/core/client/types.js.map +1 -0
- package/dist/lib/core/compiler/generator.d.ts +4 -6
- package/dist/lib/core/compiler/generator.js +190 -39
- package/dist/lib/core/compiler/generator.js.map +1 -1
- package/dist/lib/core/compiler/index.d.ts +2 -2
- package/dist/lib/core/compiler/index.js +2 -2
- package/dist/lib/core/compiler/index.js.map +1 -1
- package/dist/lib/core/compiler/pre-routes.d.ts +12 -130
- package/dist/lib/core/compiler/pre-routes.js +13 -35
- package/dist/lib/core/compiler/pre-routes.js.map +1 -1
- package/dist/lib/core/compiler/types.d.ts +25 -0
- package/dist/lib/core/decorators/context.d.ts +78 -8
- package/dist/lib/core/decorators/context.js +84 -9
- package/dist/lib/core/decorators/context.js.map +1 -1
- package/dist/lib/core/decorators/controller.js +2 -1
- package/dist/lib/core/decorators/controller.js.map +1 -1
- package/dist/lib/core/decorators/index.d.ts +1 -0
- package/dist/lib/core/decorators/index.js +1 -0
- package/dist/lib/core/decorators/index.js.map +1 -1
- package/dist/lib/core/decorators/methods.js +4 -3
- package/dist/lib/core/decorators/methods.js.map +1 -1
- package/dist/lib/core/decorators/middleware.d.ts +40 -2
- package/dist/lib/core/decorators/middleware.js +54 -9
- package/dist/lib/core/decorators/middleware.js.map +1 -1
- package/dist/lib/core/decorators/service.d.ts +28 -0
- package/dist/lib/core/decorators/service.js +36 -0
- package/dist/lib/core/decorators/service.js.map +1 -0
- package/dist/lib/core/decorators/statusCode.js +3 -1
- package/dist/lib/core/decorators/statusCode.js.map +1 -1
- package/dist/lib/core/decorators/swagger.js +4 -3
- package/dist/lib/core/decorators/swagger.js.map +1 -1
- package/dist/lib/core/exception/index.d.ts +68 -0
- package/dist/lib/core/exception/index.js +123 -0
- package/dist/lib/core/exception/index.js.map +1 -0
- package/dist/lib/core/metadata/index.d.ts +6 -0
- package/dist/lib/core/metadata/index.js +13 -0
- package/dist/lib/core/metadata/index.js.map +1 -0
- package/dist/lib/core/package/index.d.ts +11 -0
- package/dist/lib/core/package/index.js +42 -0
- package/dist/lib/core/package/index.js.map +1 -0
- package/dist/lib/core/server/fast-router.d.ts +2 -2
- package/dist/lib/core/server/fast-router.js +17 -3
- package/dist/lib/core/server/fast-router.js.map +1 -1
- package/dist/lib/core/server/index.d.ts +32 -5
- package/dist/lib/core/server/index.js +188 -45
- package/dist/lib/core/server/index.js.map +1 -1
- package/dist/lib/core/server/parser-factory.js +59 -10
- package/dist/lib/core/server/parser-factory.js.map +1 -1
- package/dist/lib/core/server/response.js +21 -1
- package/dist/lib/core/server/response.js.map +1 -1
- package/dist/lib/core/types/index.d.ts +42 -29
- package/package.json +15 -6
|
@@ -15,27 +15,51 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
25
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
36
|
exports.ApiClient = void 0;
|
|
27
37
|
let fetchFn = null;
|
|
28
|
-
async
|
|
38
|
+
const getFetch = async () => {
|
|
29
39
|
if (fetchFn)
|
|
30
40
|
return fetchFn;
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
// Browser OR modern Node v18+ (preferred)
|
|
42
|
+
if (typeof globalThis.fetch === "function") {
|
|
43
|
+
fetchFn = globalThis.fetch.bind(globalThis);
|
|
33
44
|
return fetchFn;
|
|
34
45
|
}
|
|
46
|
+
// Legacy Node fallback
|
|
35
47
|
const mod = await Promise.resolve().then(() => __importStar(require("node-fetch")));
|
|
36
48
|
fetchFn = mod.default;
|
|
37
49
|
return fetchFn;
|
|
38
|
-
}
|
|
50
|
+
};
|
|
51
|
+
const isFormData = (value) => {
|
|
52
|
+
// In Node.js 18+ it is compatible with the browser implementation.
|
|
53
|
+
if (typeof globalThis.FormData !== "undefined") {
|
|
54
|
+
return value instanceof globalThis.FormData;
|
|
55
|
+
}
|
|
56
|
+
// In Node.js below 18-, FormData is not the same as in the browser
|
|
57
|
+
// using from pkg form-data
|
|
58
|
+
return (value != null &&
|
|
59
|
+
typeof value === "object" &&
|
|
60
|
+
typeof value.append === "function" &&
|
|
61
|
+
typeof value.getHeaders === "function");
|
|
62
|
+
};
|
|
39
63
|
/**
|
|
40
64
|
* Type-safe HTTP client built on top of the native Fetch API.
|
|
41
65
|
*
|
|
@@ -67,7 +91,8 @@ async function getFetch() {
|
|
|
67
91
|
* })
|
|
68
92
|
*
|
|
69
93
|
* // fully typed response
|
|
70
|
-
*
|
|
94
|
+
* if(res.ok)
|
|
95
|
+
* console.log(res.cats)
|
|
71
96
|
* ```
|
|
72
97
|
*/
|
|
73
98
|
class ApiClient {
|
|
@@ -92,50 +117,62 @@ class ApiClient {
|
|
|
92
117
|
if (!fetchFn) {
|
|
93
118
|
throw new Error("Fetch is not available. Use Node 18+ or polyfill.");
|
|
94
119
|
}
|
|
120
|
+
let body = input?.body
|
|
121
|
+
? JSON.stringify(input.body)
|
|
122
|
+
: undefined;
|
|
123
|
+
let headers = {
|
|
124
|
+
"Content-Type": "application/json",
|
|
125
|
+
};
|
|
126
|
+
const isFileUpload = isFormData(input?.body);
|
|
127
|
+
if (isFileUpload) {
|
|
128
|
+
body = input?.body;
|
|
129
|
+
headers = undefined;
|
|
130
|
+
}
|
|
95
131
|
const res = await fetchFn(url, {
|
|
96
132
|
method: method,
|
|
97
|
-
headers
|
|
98
|
-
|
|
99
|
-
},
|
|
100
|
-
body: input?.body
|
|
101
|
-
? JSON.stringify(input.body)
|
|
102
|
-
: undefined,
|
|
133
|
+
headers,
|
|
134
|
+
body
|
|
103
135
|
});
|
|
104
136
|
const contentType = res.headers.get("content-type");
|
|
105
137
|
const isJson = contentType?.includes("application/json");
|
|
106
138
|
const data = isJson
|
|
107
139
|
? await res.json()
|
|
108
140
|
: 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
141
|
return {
|
|
119
142
|
ok: res.ok,
|
|
143
|
+
headers: res.headers,
|
|
120
144
|
status: res.status,
|
|
121
|
-
data,
|
|
145
|
+
data: data,
|
|
122
146
|
};
|
|
123
147
|
}
|
|
124
|
-
async get(path,
|
|
148
|
+
async get(path, ...args) {
|
|
149
|
+
const input = args[0];
|
|
125
150
|
return this.request("GET", path, input);
|
|
126
151
|
}
|
|
127
|
-
async post(path,
|
|
152
|
+
async post(path, ...args) {
|
|
153
|
+
const input = args[0];
|
|
128
154
|
return this.request("POST", path, input);
|
|
129
155
|
}
|
|
130
|
-
async put(path,
|
|
156
|
+
async put(path, ...args) {
|
|
157
|
+
const input = args[0];
|
|
131
158
|
return this.request("PUT", path, input);
|
|
132
159
|
}
|
|
133
|
-
async patch(path,
|
|
160
|
+
async patch(path, ...args) {
|
|
161
|
+
const input = args[0];
|
|
134
162
|
return this.request("PATCH", path, input);
|
|
135
163
|
}
|
|
136
|
-
async delete(path,
|
|
164
|
+
async delete(path, ...args) {
|
|
165
|
+
const input = args[0];
|
|
137
166
|
return this.request("DELETE", path, input);
|
|
138
167
|
}
|
|
168
|
+
async upload(path, options) {
|
|
169
|
+
const { method = "POST", formdata } = options;
|
|
170
|
+
return this.request(method, path,
|
|
171
|
+
//@ts-ignore
|
|
172
|
+
{
|
|
173
|
+
body: formdata
|
|
174
|
+
});
|
|
175
|
+
}
|
|
139
176
|
}
|
|
140
177
|
exports.ApiClient = ApiClient;
|
|
141
178
|
exports.default = ApiClient;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/core/client/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/core/client/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type AnyRoutes = {
|
|
2
|
+
[key: string]: any;
|
|
3
|
+
};
|
|
4
|
+
export type RoutesWithMethod<TRoutes extends AnyRoutes, TMethod extends string> = {
|
|
5
|
+
[K in keyof TRoutes]: TMethod extends keyof TRoutes[K] ? K : never;
|
|
6
|
+
}[keyof TRoutes];
|
|
7
|
+
export type ExtractFrom<TRoutes extends AnyRoutes, TPath extends keyof TRoutes, TMethod extends keyof TRoutes[TPath], Key extends string> = TRoutes[TPath][TMethod] extends Record<Key, infer R> ? R : never;
|
|
8
|
+
export type RequestBody<TRoutes extends AnyRoutes, TPath extends keyof TRoutes, TMethod extends keyof TRoutes[TPath]> = ExtractFrom<TRoutes, TPath, TMethod, "body">;
|
|
9
|
+
export type RequestQuery<TRoutes extends AnyRoutes, TPath extends keyof TRoutes, TMethod extends keyof TRoutes[TPath]> = ExtractFrom<TRoutes, TPath, TMethod, "query">;
|
|
10
|
+
export type RequestParams<TRoutes extends AnyRoutes, TPath extends keyof TRoutes, TMethod extends keyof TRoutes[TPath]> = ExtractFrom<TRoutes, TPath, TMethod, "params">;
|
|
11
|
+
export type RequestFiles<TRoutes extends AnyRoutes, TPath extends keyof TRoutes, TMethod extends keyof TRoutes[TPath]> = ExtractFrom<TRoutes, TPath, TMethod, "files">;
|
|
12
|
+
export type ResponseType<TRoutes extends AnyRoutes, TPath extends keyof TRoutes, TMethod extends keyof TRoutes[TPath]> = TRoutes[TPath][TMethod] extends {
|
|
13
|
+
response: infer R;
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
name: RegExp;
|
|
14
|
-
};
|
|
11
|
+
folder: string;
|
|
12
|
+
name: RegExp;
|
|
15
13
|
output?: string;
|
|
16
14
|
};
|
|
17
|
-
export declare
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
63
|
+
};
|
|
64
|
+
const parseType = (type) => {
|
|
50
65
|
type = type.trim();
|
|
51
66
|
if (type === "never") {
|
|
52
|
-
return
|
|
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
|
-
|
|
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,14 +178,52 @@ function resolveType(type) {
|
|
|
161
178
|
return "any";
|
|
162
179
|
if (type.isUnknown())
|
|
163
180
|
return "unknown";
|
|
164
|
-
if (type.
|
|
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
|
+
}
|
|
203
|
+
if (type.isUnion()) {
|
|
204
|
+
const text = type.getText();
|
|
205
|
+
if (text.includes('| null') || text.includes('| undefined')) {
|
|
206
|
+
const types = type.getUnionTypes();
|
|
207
|
+
if (types.length > 1) {
|
|
208
|
+
const nonSpecial = types.filter(t => !t.isNull() && !t.isUndefined());
|
|
209
|
+
const hasNull = types.some(t => t.isNull());
|
|
210
|
+
const hasUndefined = types.some(t => t.isUndefined());
|
|
211
|
+
const sorted = [
|
|
212
|
+
...nonSpecial,
|
|
213
|
+
...(hasNull ? [types.find(t => t.isNull())] : []),
|
|
214
|
+
...(hasUndefined ? [types.find(t => t.isUndefined())] : []),
|
|
215
|
+
];
|
|
216
|
+
return sorted.map(t => resolveType(t)).join(" | ");
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return text;
|
|
220
|
+
}
|
|
166
221
|
if (type.isArray()) {
|
|
167
222
|
const el = type.getArrayElementTypeOrThrow();
|
|
168
223
|
return `${resolveType(el)}[]`;
|
|
169
224
|
}
|
|
170
|
-
|
|
171
|
-
|
|
225
|
+
if (type.getProperties().length) {
|
|
226
|
+
const props = type.getProperties();
|
|
172
227
|
const obj = [];
|
|
173
228
|
for (const prop of props) {
|
|
174
229
|
const decl = prop.getDeclarations()[0];
|
|
@@ -196,8 +251,8 @@ function resolveType(type) {
|
|
|
196
251
|
return `{ ${obj.join("; ")} }`;
|
|
197
252
|
}
|
|
198
253
|
return type.getText();
|
|
199
|
-
}
|
|
200
|
-
|
|
254
|
+
};
|
|
255
|
+
const extractPropertyType = (type, key, node) => {
|
|
201
256
|
const prop = type.getProperty(key);
|
|
202
257
|
if (!prop)
|
|
203
258
|
return "never";
|
|
@@ -208,12 +263,12 @@ function extractPropertyType(type, key, node) {
|
|
|
208
263
|
if (!text || text.includes("undefined"))
|
|
209
264
|
return "never";
|
|
210
265
|
return resolveType(t) ?? "never";
|
|
211
|
-
}
|
|
212
|
-
async
|
|
266
|
+
};
|
|
267
|
+
const generateRoutes = async (globalPrefix, options) => {
|
|
213
268
|
const project = new ts_morph_1.Project({
|
|
214
269
|
tsConfigFilePath: path_1.default.resolve(process.cwd(), "tsconfig.json"),
|
|
215
270
|
});
|
|
216
|
-
project.addSourceFilesAtPaths(path_1.default.join(options.
|
|
271
|
+
project.addSourceFilesAtPaths(path_1.default.join(options.folder, "**/*"));
|
|
217
272
|
const files = project.getSourceFiles();
|
|
218
273
|
if (!files.length) {
|
|
219
274
|
console.log("No controller files found");
|
|
@@ -222,7 +277,7 @@ async function generateRoutes(options) {
|
|
|
222
277
|
const routes = [];
|
|
223
278
|
for (const file of files) {
|
|
224
279
|
const filename = file.getBaseName();
|
|
225
|
-
if (!options.
|
|
280
|
+
if (!options.name.test(filename))
|
|
226
281
|
continue;
|
|
227
282
|
for (const cls of file.getClasses()) {
|
|
228
283
|
const controller = cls.getDecorator("Controller");
|
|
@@ -249,10 +304,12 @@ async function generateRoutes(options) {
|
|
|
249
304
|
const firstParam = method.getParameters()[0];
|
|
250
305
|
if (firstParam) {
|
|
251
306
|
const type = firstParam.getType();
|
|
252
|
-
body = extractPropertyType(type, "body", firstParam);
|
|
253
307
|
params = extractPropertyType(type, "params", firstParam);
|
|
254
308
|
query = extractPropertyType(type, "query", firstParam);
|
|
309
|
+
body = extractPropertyType(type, "body", firstParam);
|
|
255
310
|
files = extractPropertyType(type, "files", firstParam);
|
|
311
|
+
if (body === 'Record<string, any>')
|
|
312
|
+
body = "never";
|
|
256
313
|
}
|
|
257
314
|
routes.push({
|
|
258
315
|
method: http,
|
|
@@ -261,7 +318,7 @@ async function generateRoutes(options) {
|
|
|
261
318
|
body,
|
|
262
319
|
params,
|
|
263
320
|
query,
|
|
264
|
-
files
|
|
321
|
+
files
|
|
265
322
|
});
|
|
266
323
|
}
|
|
267
324
|
}
|
|
@@ -295,9 +352,97 @@ async function generateRoutes(options) {
|
|
|
295
352
|
}`;
|
|
296
353
|
})
|
|
297
354
|
.join("\n");
|
|
298
|
-
const
|
|
299
|
-
if (
|
|
300
|
-
return
|
|
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) {
|
|
426
|
+
return "[]";
|
|
427
|
+
}
|
|
428
|
+
return `[
|
|
429
|
+
${formatExampleValue(v[0])},
|
|
430
|
+
${formatExampleValue(v[0])},
|
|
431
|
+
${formatExampleValue(v[0])}
|
|
432
|
+
]`;
|
|
433
|
+
}
|
|
434
|
+
if (typeof v === "object") {
|
|
435
|
+
const entries = Object.entries(v).map(([key, value]) => {
|
|
436
|
+
if (key.includes("uuid")) {
|
|
437
|
+
return `${key}: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"`;
|
|
438
|
+
}
|
|
439
|
+
if (key === "id" || key.endsWith("id")) {
|
|
440
|
+
return `${key}: 123`;
|
|
441
|
+
}
|
|
442
|
+
return `${key}: ${formatExampleValue(value)}`;
|
|
443
|
+
});
|
|
444
|
+
return `{ ${entries.map(v => `${v}`).join(", ")} }`;
|
|
445
|
+
}
|
|
301
446
|
return JSON.stringify(v);
|
|
302
447
|
};
|
|
303
448
|
const groupedValues = routes.reduce((acc, route) => {
|
|
@@ -318,11 +463,11 @@ async function generateRoutes(options) {
|
|
|
318
463
|
const methodBlock = Object.entries(methods)
|
|
319
464
|
.map(([method, c]) => `
|
|
320
465
|
${method}: {
|
|
321
|
-
params: ${
|
|
322
|
-
query: ${
|
|
323
|
-
body: ${
|
|
324
|
-
files: ${
|
|
325
|
-
response: ${
|
|
466
|
+
params: ${formatExampleValue(c.params)},
|
|
467
|
+
query: ${formatExampleValue(c.query)},
|
|
468
|
+
body: ${formatExampleValue(c.body)},
|
|
469
|
+
files: ${formatExampleValue(c.files)},
|
|
470
|
+
response: ${formatExampleValue(c.response)}
|
|
326
471
|
}`).join(",\n");
|
|
327
472
|
return `
|
|
328
473
|
"${path}": {
|
|
@@ -334,16 +479,20 @@ async function generateRoutes(options) {
|
|
|
334
479
|
// @ts-nocheck
|
|
335
480
|
// AUTO GENERATED FILE
|
|
336
481
|
// DO NOT EDIT
|
|
482
|
+
// **Response values shown here are examples only.
|
|
483
|
+
${globalPrefix ?
|
|
484
|
+
`// **The App is using the configuration:
|
|
485
|
+
// globalPrefix: '${globalPrefix}'` : ''}
|
|
337
486
|
|
|
338
487
|
export const appRoutes = {
|
|
339
488
|
${routerMapValues}
|
|
340
|
-
}
|
|
489
|
+
};
|
|
341
490
|
|
|
342
491
|
export interface AppRoutes {
|
|
343
492
|
${routeMapTypes}
|
|
344
|
-
}
|
|
493
|
+
};
|
|
345
494
|
|
|
346
|
-
export type AppRoute = keyof AppRoutes
|
|
495
|
+
export type AppRoute = keyof AppRoutes;
|
|
347
496
|
`;
|
|
348
497
|
const outPath = options.output
|
|
349
498
|
? `${__dirname}/${options.output}/pre-routes.ts`
|
|
@@ -351,15 +500,17 @@ export type AppRoute = keyof AppRoutes
|
|
|
351
500
|
await fs_1.default.promises.mkdir(path_1.default.dirname(outPath), {
|
|
352
501
|
recursive: true,
|
|
353
502
|
});
|
|
354
|
-
await fs_1.default.promises.writeFile(outPath, output);
|
|
355
503
|
const compiled = typescript_1.default.transpileModule(output, {
|
|
356
504
|
compilerOptions: {
|
|
357
505
|
module: typescript_1.default.ModuleKind.CommonJS,
|
|
358
|
-
target: typescript_1.default.ScriptTarget.
|
|
506
|
+
target: typescript_1.default.ScriptTarget.ESNext
|
|
359
507
|
},
|
|
360
508
|
});
|
|
361
|
-
|
|
362
|
-
|
|
509
|
+
await Promise.all([
|
|
510
|
+
fs_1.default.promises.writeFile(outPath, output),
|
|
511
|
+
fs_1.default.promises.writeFile(outPath.replace(/\.ts$/, ".js"), compiled.outputText)
|
|
512
|
+
]);
|
|
363
513
|
return routes;
|
|
364
|
-
}
|
|
514
|
+
};
|
|
515
|
+
exports.generateRoutes = generateRoutes;
|
|
365
516
|
//# sourceMappingURL=generator.js.map
|