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.
- package/README.md +253 -71
- package/dist/cli/generators/app/index.js.map +1 -1
- package/dist/cli/generators/controller/template.d.ts +1 -1
- package/dist/cli/generators/controller/template.js +15 -8
- package/dist/cli/generators/controller/template.js.map +1 -1
- package/dist/cli/generators/dto/index.js +5 -3
- package/dist/cli/generators/dto/index.js.map +1 -1
- package/dist/cli/generators/module/index.js +3 -3
- package/dist/cli/generators/service/template.d.ts +1 -1
- package/dist/cli/generators/service/template.js +17 -17
- package/dist/cli/index.js +1 -0
- 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 +47 -26
- package/dist/lib/core/client/index.js.map +1 -1
- package/dist/lib/core/{compiler → client}/types.d.ts +29 -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 +168 -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 +170 -34
- package/dist/lib/core/compiler/pre-routes.js +45 -25
- package/dist/lib/core/compiler/pre-routes.js.map +1 -1
- package/dist/lib/core/decorators/context.js +23 -15
- package/dist/lib/core/decorators/context.js.map +1 -1
- package/dist/lib/core/decorators/statusCode.js +3 -1
- package/dist/lib/core/decorators/statusCode.js.map +1 -1
- 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.js +2 -2
- package/dist/lib/core/server/index.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 +32 -27
- package/package.json +6 -3
- package/dist/cli/app.d.ts +0 -1
- package/dist/cli/app.js +0 -32
- package/dist/cli/app.js.map +0 -1
- package/dist/cli/client.d.ts +0 -1
- package/dist/cli/client.js +0 -30
- package/dist/cli/client.js.map +0 -1
- package/dist/cli/controller.d.ts +0 -1
- package/dist/cli/controller.js +0 -169
- package/dist/cli/controller.js.map +0 -1
- package/dist/cli/middleware.d.ts +0 -1
- package/dist/cli/middleware.js +0 -16
- package/dist/cli/middleware.js.map +0 -1
- package/dist/client.d.ts +0 -1
- package/dist/client.js +0 -17
- package/dist/client.js.map +0 -1
- package/dist/common/middlewares/log.middleware.d.ts +0 -2
- package/dist/common/middlewares/log.middleware.js +0 -12
- package/dist/common/middlewares/log.middleware.js.map +0 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.js +0 -32
- package/dist/index.js.map +0 -1
- package/dist/lib/core/compiler/types.js.map +0 -1
- package/dist/modules/cats/cat.controller.d.ts +0 -58
- package/dist/modules/cats/cat.controller.js +0 -90
- package/dist/modules/cats/cat.controller.js.map +0 -1
- package/dist/modules/cats/cat.dto.d.ts +0 -8
- package/dist/modules/cats/cat.dto.js +0 -44
- package/dist/modules/cats/cat.dto.js.map +0 -1
- package/dist/modules/cats/cat.service.d.ts +0 -23
- package/dist/modules/cats/cat.service.js +0 -56
- package/dist/modules/cats/cat.service.js.map +0 -1
- package/dist/tests/e2e..test.d.ts +0 -1
- package/dist/tests/e2e..test.js +0 -16
- package/dist/tests/e2e..test.js.map +0 -1
- /package/dist/lib/core/{compiler → client}/types.js +0 -0
|
@@ -1,15 +1,4 @@
|
|
|
1
|
-
import type { AnyRoutes, RoutesWithMethod,
|
|
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
|
-
*
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
|
28
|
+
const getFetch = async () => {
|
|
29
29
|
if (fetchFn)
|
|
30
30
|
return fetchFn;
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
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,
|
|
132
|
+
async get(path, ...args) {
|
|
133
|
+
const input = args[0];
|
|
125
134
|
return this.request("GET", path, input);
|
|
126
135
|
}
|
|
127
|
-
async post(path,
|
|
136
|
+
async post(path, ...args) {
|
|
137
|
+
const input = args[0];
|
|
128
138
|
return this.request("POST", path, input);
|
|
129
139
|
}
|
|
130
|
-
async put(path,
|
|
140
|
+
async put(path, ...args) {
|
|
141
|
+
const input = args[0];
|
|
131
142
|
return this.request("PUT", path, input);
|
|
132
143
|
}
|
|
133
|
-
async patch(path,
|
|
144
|
+
async patch(path, ...args) {
|
|
145
|
+
const input = args[0];
|
|
134
146
|
return this.request("PATCH", path, input);
|
|
135
147
|
}
|
|
136
|
-
async delete(path,
|
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/core/client/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AASA,IAAI,OAAO,GAAwB,IAAI,CAAC;AAExC,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;IAC1B,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAE5B,0CAA0C;IAC1C,IAAI,OAAO,UAAU,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;QAC3C,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5C,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,uBAAuB;IACvB,MAAM,GAAG,GAAG,wDAAa,YAAY,GAAC,CAAC;IACvC,OAAO,GAAG,GAAG,CAAC,OAAkC,CAAC;IAEjD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,KAAc,EAAW,EAAE;IAC7C,OAAO,CACL,KAAK,IAAI,IAAI;QACb,OAAO,KAAK,KAAK,QAAQ;QACzB,OAAQ,KAAa,CAAC,MAAM,KAAK,UAAU;QAC3C,OAAQ,KAAa,CAAC,UAAU,KAAK,UAAU,CAChD,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,SAAS;IAGL,OAAO,CAAS;IAExB,YAAY,OAAe;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAEO,KAAK,CAAC,OAAO,CAInB,MAAe,EACf,IAAW,EACX,KAIC;QAWC,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,GAAI,IAAe,CAAA;QAGzC,IAAI,KAAK,EAAE,MAAM,EAAE,CAAC;YAClB,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBAC/B,GAAG,GAAG,GAAG,CAAC,OAAO,CACf,IAAI,GAAG,EAAE,EACT,kBAAkB,CAAE,KAAK,CAAC,MAAc,CAAC,GAAG,CAAC,CAAC,CAC/C,CAAA;YACH,CAAC;QACH,CAAC;QAED,IAAI,KAAK,EAAE,KAAK,EAAE,CAAC;YACjB,MAAM,WAAW,GAAG,IAAI,eAAe,CACrC,KAAK,CAAC,KAAY,CACnB,CAAC,QAAQ,EAAE,CAAA;YAEZ,IAAI,WAAW,EAAE,CAAC;gBAChB,GAAG,IAAI,IAAI,WAAW,EAAE,CAAA;YAC1B,CAAC;QACH,CAAC;QAEH,OAAO,GAAG,MAAM,QAAQ,EAAE,CAAC;QAE3B,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACvE,CAAC;QAED,IAAI,IAAI,GAAQ,KAAK,EAAE,IAAI;YACzB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;YAC5B,CAAC,CAAC,SAAS,CAAA;QAEb,IAAI,OAAO,GAAQ;YACjB,cAAc,EACZ,kBAAkB;SACrB,CAAA;QAED,MAAM,YAAY,GAAG,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAE7C,IAAG,YAAY,EAAE,CAAC;YAChB,IAAI,GAAG,KAAK,EAAE,IAAI,CAAC;YACnB,OAAO,GAAG,SAAS,CAAC;QACtB,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;YAC7B,MAAM,EAAE,MAAgB;YACxB,OAAO;YACP,IAAI;SACL,CAAC,CAAC;QAEH,MAAM,WAAW,GACf,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAElC,MAAM,MAAM,GACV,WAAW,EAAE,QAAQ,CACnB,kBAAkB,CACnB,CAAC;QAEJ,MAAM,IAAI,GAAG,MAAM;YACjB,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE;YAClB,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAErB,OAAO;YACL,EAAE,EAAQ,GAAG,CAAC,EAAE;YAChB,OAAO,EAAG,GAAG,CAAC,OAAO;YACrB,MAAM,EAAI,GAAG,CAAC,MAAa;YAC3B,IAAI,EAAM,IAAI;SACf,CAAA;IACH,CAAC;IAEM,KAAK,CAAC,GAAG,CAMd,IAAW,EACX,GAAG,IAA0D;QAE7D,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC,OAAO,CACjB,KAAK,EACL,IAAI,EACJ,KAAK,CACN,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,IAAI,CAMf,IAAW,EACX,GAAG,IAA2D;QAE9D,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEtB,OAAO,IAAI,CAAC,OAAO,CACjB,MAAM,EACN,IAAI,EACJ,KAAK,CACN,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,GAAG,CAMd,IAAW,EACX,GAAG,IAA0D;QAE7D,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEtB,OAAO,IAAI,CAAC,OAAO,CACjB,KAAK,EACL,IAAI,EACJ,KAAK,CACN,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,KAAK,CAMhB,IAAW,EACX,GAAG,IAA4D;QAE/D,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEtB,OAAO,IAAI,CAAC,OAAO,CACjB,OAAO,EACP,IAAI,EACJ,KAAK,CACN,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,MAAM,CAMjB,IAAW,EACX,GAAG,IAA6D;QAEhE,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEtB,OAAO,IAAI,CAAC,OAAO,CACjB,QAAQ,EACR,IAAI,EACJ,KAAK,CACN,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,MAAM,CAIjB,IAAW,EACX,OAGC;QAED,MAAM,EAAE,MAAM,GAAG,MAAiB,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;QAEzD,OAAO,IAAI,CAAC,OAAO,CACjB,MAAM,EACN,IAAI;QACJ,YAAY;QACZ;YACE,IAAI,EAAG,QAAQ;SAChB,CACF,CAAC;IACJ,CAAC;CAEF;AAEQ,8BAAS;AAClB,kBAAe,SAAS,CAAC"}
|
|
@@ -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
|
-
|
|
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,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
|
-
|
|
189
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
317
|
-
if (
|
|
318
|
-
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 === 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: ${
|
|
340
|
-
query: ${
|
|
341
|
-
body: ${
|
|
342
|
-
files: ${
|
|
343
|
-
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.
|
|
502
|
+
target: typescript_1.default.ScriptTarget.ESNext
|
|
377
503
|
},
|
|
378
504
|
});
|
|
379
|
-
|
|
380
|
-
|
|
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
|