@dudousxd/nestjs-codegen 0.3.0 → 0.4.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/CHANGELOG.md +33 -0
- package/dist/cli/main.cjs +79 -20
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +79 -20
- package/dist/cli/main.js.map +1 -1
- package/dist/extension/index.d.cts +1 -1
- package/dist/extension/index.d.ts +1 -1
- package/dist/{index-oH5t7x4G.d.cts → index-DA4uySjo.d.cts} +29 -1
- package/dist/{index-oH5t7x4G.d.ts → index-DA4uySjo.d.ts} +29 -1
- package/dist/index.cjs +130 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -4
- package/dist/index.d.ts +29 -4
- package/dist/index.js +129 -20
- package/dist/index.js.map +1 -1
- package/dist/nest/index.cjs +78 -19
- package/dist/nest/index.cjs.map +1 -1
- package/dist/nest/index.d.cts +1 -1
- package/dist/nest/index.d.ts +1 -1
- package/dist/nest/index.js +78 -19
- package/dist/nest/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { l as ApiClientLayer, m as ApiHeaderContribution, n as ApiModuleDeps, C as CodegenExtension, o as EmittedFile, E as ExtensionContext, L as LeafModel, p as RequestModel, q as RequestShape, s as defineExtension, t as requestShape } from '../index-
|
|
1
|
+
export { l as ApiClientLayer, m as ApiHeaderContribution, n as ApiModuleDeps, C as CodegenExtension, o as EmittedFile, E as ExtensionContext, L as LeafModel, p as RequestModel, q as RequestShape, s as defineExtension, t as requestShape } from '../index-DA4uySjo.cjs';
|
|
2
2
|
import 'ts-morph';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { l as ApiClientLayer, m as ApiHeaderContribution, n as ApiModuleDeps, C as CodegenExtension, o as EmittedFile, E as ExtensionContext, L as LeafModel, p as RequestModel, q as RequestShape, s as defineExtension, t as requestShape } from '../index-
|
|
1
|
+
export { l as ApiClientLayer, m as ApiHeaderContribution, n as ApiModuleDeps, C as CodegenExtension, o as EmittedFile, E as ExtensionContext, L as LeafModel, p as RequestModel, q as RequestShape, s as defineExtension, t as requestShape } from '../index-DA4uySjo.js';
|
|
2
2
|
import 'ts-morph';
|
|
@@ -111,6 +111,14 @@ interface SchemaModule {
|
|
|
111
111
|
root: SchemaNode;
|
|
112
112
|
named: Map<string, SchemaNode>;
|
|
113
113
|
warnings: string[];
|
|
114
|
+
/**
|
|
115
|
+
* Names (keys of {@link named}) that are genuinely self/mutually recursive,
|
|
116
|
+
* i.e. reachable from themselves through a `lazyRef` back-edge. Adapters use
|
|
117
|
+
* this to break the TypeScript inference cycle (annotated const + hoisted
|
|
118
|
+
* structural type for zod/valibot; `this`/degrade for arktype). Absent or
|
|
119
|
+
* empty means no recursion.
|
|
120
|
+
*/
|
|
121
|
+
recursive?: Set<string>;
|
|
114
122
|
}
|
|
115
123
|
|
|
116
124
|
/** Signals to an adapter what it must import to render the current output. */
|
|
@@ -121,12 +129,32 @@ interface AdapterUsage {
|
|
|
121
129
|
interface RenderContext {
|
|
122
130
|
/** Hoisted named schemas being emitted alongside the root. */
|
|
123
131
|
named: Map<string, SchemaNode>;
|
|
132
|
+
/**
|
|
133
|
+
* Name of the hoisted schema currently being rendered, when rendering a named
|
|
134
|
+
* schema's own body. Lets an adapter express a self-reference specially (e.g.
|
|
135
|
+
* arktype's `this` keyword). Absent when rendering the root.
|
|
136
|
+
*/
|
|
137
|
+
selfName?: string;
|
|
124
138
|
}
|
|
125
139
|
interface RenderedModule {
|
|
126
140
|
/** Root schema source text, e.g. `"z.object({ email: z.string().email() })"`. */
|
|
127
141
|
schemaText: string;
|
|
128
142
|
/** name → schema source text, hoisted above the parent. */
|
|
129
143
|
namedNestedSchemas: Map<string, string>;
|
|
144
|
+
/**
|
|
145
|
+
* name → hoisted TS `type` alias *body* for a recursive schema (e.g.
|
|
146
|
+
* `"{ field?: string; and?: Array<ColumnFilter> }"`), emitted as
|
|
147
|
+
* `type <TypeName> = <body>;` above the const. The alias name is derived from
|
|
148
|
+
* the schema name. Absent for adapters/schemas that don't need it (arktype,
|
|
149
|
+
* non-recursive schemas).
|
|
150
|
+
*/
|
|
151
|
+
namedTypeAliases?: Map<string, string>;
|
|
152
|
+
/**
|
|
153
|
+
* name → const type annotation for a recursive schema (e.g.
|
|
154
|
+
* `"z.ZodType<ColumnFilter>"`), emitted as `const <name>: <annotation> = ...`
|
|
155
|
+
* to break the implicit-any self-reference cycle.
|
|
156
|
+
*/
|
|
157
|
+
namedAnnotations?: Map<string, string>;
|
|
130
158
|
warnings: string[];
|
|
131
159
|
}
|
|
132
160
|
/**
|
|
@@ -521,4 +549,4 @@ declare function requestShape(route: RouteDescriptor): RequestShape;
|
|
|
521
549
|
/** Identity helper for authoring extensions with full type inference. */
|
|
522
550
|
declare function defineExtension(ext: CodegenExtension): CodegenExtension;
|
|
523
551
|
|
|
524
|
-
export { type AdapterUsage as A, type CodegenExtension as C, type ExtensionContext as E, type LeafModel as L, type NumberCheck as N, type ResolvedConfig as R, type
|
|
552
|
+
export { type AdapterUsage as A, type CodegenExtension as C, type ExtensionContext as E, type LeafModel as L, type NumberCheck as N, type ResolvedConfig as R, type SchemaNode as S, type TypeRef as T, type UserConfig as U, type ValidationAdapter as V, type RouteDescriptor as a, type SchemaModule as b, type ResolvedFormsConfig as c, type ContractDescriptor as d, type ContractSource as e, type ControllerRef as f, type RenderContext as g, type RenderedModule as h, type ScopeConfig as i, type StringCheck as j, type ValidationOption as k, type ApiClientLayer as l, type ApiHeaderContribution as m, type ApiModuleDeps as n, type EmittedFile as o, type RequestModel as p, type RequestShape as q, resolveAdapter as r, defineExtension as s, requestShape as t };
|
|
@@ -111,6 +111,14 @@ interface SchemaModule {
|
|
|
111
111
|
root: SchemaNode;
|
|
112
112
|
named: Map<string, SchemaNode>;
|
|
113
113
|
warnings: string[];
|
|
114
|
+
/**
|
|
115
|
+
* Names (keys of {@link named}) that are genuinely self/mutually recursive,
|
|
116
|
+
* i.e. reachable from themselves through a `lazyRef` back-edge. Adapters use
|
|
117
|
+
* this to break the TypeScript inference cycle (annotated const + hoisted
|
|
118
|
+
* structural type for zod/valibot; `this`/degrade for arktype). Absent or
|
|
119
|
+
* empty means no recursion.
|
|
120
|
+
*/
|
|
121
|
+
recursive?: Set<string>;
|
|
114
122
|
}
|
|
115
123
|
|
|
116
124
|
/** Signals to an adapter what it must import to render the current output. */
|
|
@@ -121,12 +129,32 @@ interface AdapterUsage {
|
|
|
121
129
|
interface RenderContext {
|
|
122
130
|
/** Hoisted named schemas being emitted alongside the root. */
|
|
123
131
|
named: Map<string, SchemaNode>;
|
|
132
|
+
/**
|
|
133
|
+
* Name of the hoisted schema currently being rendered, when rendering a named
|
|
134
|
+
* schema's own body. Lets an adapter express a self-reference specially (e.g.
|
|
135
|
+
* arktype's `this` keyword). Absent when rendering the root.
|
|
136
|
+
*/
|
|
137
|
+
selfName?: string;
|
|
124
138
|
}
|
|
125
139
|
interface RenderedModule {
|
|
126
140
|
/** Root schema source text, e.g. `"z.object({ email: z.string().email() })"`. */
|
|
127
141
|
schemaText: string;
|
|
128
142
|
/** name → schema source text, hoisted above the parent. */
|
|
129
143
|
namedNestedSchemas: Map<string, string>;
|
|
144
|
+
/**
|
|
145
|
+
* name → hoisted TS `type` alias *body* for a recursive schema (e.g.
|
|
146
|
+
* `"{ field?: string; and?: Array<ColumnFilter> }"`), emitted as
|
|
147
|
+
* `type <TypeName> = <body>;` above the const. The alias name is derived from
|
|
148
|
+
* the schema name. Absent for adapters/schemas that don't need it (arktype,
|
|
149
|
+
* non-recursive schemas).
|
|
150
|
+
*/
|
|
151
|
+
namedTypeAliases?: Map<string, string>;
|
|
152
|
+
/**
|
|
153
|
+
* name → const type annotation for a recursive schema (e.g.
|
|
154
|
+
* `"z.ZodType<ColumnFilter>"`), emitted as `const <name>: <annotation> = ...`
|
|
155
|
+
* to break the implicit-any self-reference cycle.
|
|
156
|
+
*/
|
|
157
|
+
namedAnnotations?: Map<string, string>;
|
|
130
158
|
warnings: string[];
|
|
131
159
|
}
|
|
132
160
|
/**
|
|
@@ -521,4 +549,4 @@ declare function requestShape(route: RouteDescriptor): RequestShape;
|
|
|
521
549
|
/** Identity helper for authoring extensions with full type inference. */
|
|
522
550
|
declare function defineExtension(ext: CodegenExtension): CodegenExtension;
|
|
523
551
|
|
|
524
|
-
export { type AdapterUsage as A, type CodegenExtension as C, type ExtensionContext as E, type LeafModel as L, type NumberCheck as N, type ResolvedConfig as R, type
|
|
552
|
+
export { type AdapterUsage as A, type CodegenExtension as C, type ExtensionContext as E, type LeafModel as L, type NumberCheck as N, type ResolvedConfig as R, type SchemaNode as S, type TypeRef as T, type UserConfig as U, type ValidationAdapter as V, type RouteDescriptor as a, type SchemaModule as b, type ResolvedFormsConfig as c, type ContractDescriptor as d, type ContractSource as e, type ControllerRef as f, type RenderContext as g, type RenderedModule as h, type ScopeConfig as i, type StringCheck as j, type ValidationOption as k, type ApiClientLayer as l, type ApiHeaderContribution as m, type ApiModuleDeps as n, type EmittedFile as o, type RequestModel as p, type RequestShape as q, resolveAdapter as r, defineExtension as s, requestShape as t };
|
package/dist/index.cjs
CHANGED
|
@@ -42,6 +42,7 @@ __export(src_exports, {
|
|
|
42
42
|
extractSchemaFromDto: () => extractSchemaFromDto,
|
|
43
43
|
generate: () => generate,
|
|
44
44
|
loadConfig: () => loadConfig,
|
|
45
|
+
renderTsType: () => renderTsType,
|
|
45
46
|
resolveAdapter: () => resolveAdapter,
|
|
46
47
|
resolveConfig: () => resolveConfig,
|
|
47
48
|
watch: () => watch
|
|
@@ -1306,6 +1307,8 @@ function buildFormsFileWithAdapter(routes, outDir, adapter, config) {
|
|
|
1306
1307
|
}
|
|
1307
1308
|
const { globalSchemas, renamesByEntry } = planNestedSchemas(entries);
|
|
1308
1309
|
const irNamed = /* @__PURE__ */ new Map();
|
|
1310
|
+
const irTypeAliases = /* @__PURE__ */ new Map();
|
|
1311
|
+
const irAnnotations = /* @__PURE__ */ new Map();
|
|
1309
1312
|
const decls = [];
|
|
1310
1313
|
const mapEntries = [];
|
|
1311
1314
|
let used = false;
|
|
@@ -1313,6 +1316,8 @@ function buildFormsFileWithAdapter(routes, outDir, adapter, config) {
|
|
|
1313
1316
|
if (src.schema) {
|
|
1314
1317
|
const r = adapter.renderModule(src.schema);
|
|
1315
1318
|
for (const [n, t] of r.namedNestedSchemas) irNamed.set(n, t);
|
|
1319
|
+
if (r.namedTypeAliases) for (const [n, t] of r.namedTypeAliases) irTypeAliases.set(n, t);
|
|
1320
|
+
if (r.namedAnnotations) for (const [n, a] of r.namedAnnotations) irAnnotations.set(n, a);
|
|
1316
1321
|
return { text: r.schemaText };
|
|
1317
1322
|
}
|
|
1318
1323
|
if (src.zodText) {
|
|
@@ -1386,7 +1391,13 @@ function buildFormsFileWithAdapter(routes, outDir, adapter, config) {
|
|
|
1386
1391
|
for (const [n, t] of irNamed) if (!allNested.has(n)) allNested.set(n, t);
|
|
1387
1392
|
if (allNested.size > 0) {
|
|
1388
1393
|
lines.push("// Hoisted nested schemas (shared across endpoints).");
|
|
1389
|
-
for (const [n,
|
|
1394
|
+
for (const [n, alias] of irTypeAliases) {
|
|
1395
|
+
if (allNested.has(n)) lines.push(`${alias};`);
|
|
1396
|
+
}
|
|
1397
|
+
for (const [n, t] of allNested) {
|
|
1398
|
+
const annotation = irAnnotations.get(n);
|
|
1399
|
+
lines.push(`const ${n}${annotation ? `: ${annotation}` : ""} = ${t};`);
|
|
1400
|
+
}
|
|
1390
1401
|
lines.push("");
|
|
1391
1402
|
}
|
|
1392
1403
|
lines.push(...decls);
|
|
@@ -1811,10 +1822,19 @@ function followModuleForType(name, moduleSpecifier, fromFile, project, seen) {
|
|
|
1811
1822
|
}
|
|
1812
1823
|
return null;
|
|
1813
1824
|
}
|
|
1825
|
+
var _findTypeCache = /* @__PURE__ */ new WeakMap();
|
|
1814
1826
|
function findType(name, sourceFile, project) {
|
|
1827
|
+
let byKey = _findTypeCache.get(project);
|
|
1828
|
+
if (byKey === void 0) {
|
|
1829
|
+
byKey = /* @__PURE__ */ new Map();
|
|
1830
|
+
_findTypeCache.set(project, byKey);
|
|
1831
|
+
}
|
|
1832
|
+
const key = `${sourceFile.getFilePath()}\0${name}`;
|
|
1833
|
+
if (byKey.has(key)) return byKey.get(key) ?? null;
|
|
1815
1834
|
const local = findTypeInFile(name, sourceFile);
|
|
1816
|
-
|
|
1817
|
-
|
|
1835
|
+
const result = local ?? resolveImportedType(name, sourceFile, project);
|
|
1836
|
+
byKey.set(key, result);
|
|
1837
|
+
return result;
|
|
1818
1838
|
}
|
|
1819
1839
|
var _NON_REF_NAMES = /* @__PURE__ */ new Set(["string", "number", "boolean", "void", "unknown", "any", "Date"]);
|
|
1820
1840
|
function _localDeclForKinds(name, file, kinds) {
|
|
@@ -1851,6 +1871,26 @@ function resolveTypeRef(nodeOrName, sourceFile, project, opts) {
|
|
|
1851
1871
|
if (_NON_REF_NAMES.has(refName)) return null;
|
|
1852
1872
|
name = refName;
|
|
1853
1873
|
}
|
|
1874
|
+
return _resolveNamedRef(name, sourceFile, project, opts);
|
|
1875
|
+
}
|
|
1876
|
+
var _resolveNamedRefCache = /* @__PURE__ */ new WeakMap();
|
|
1877
|
+
function _resolveNamedRef(name, sourceFile, project, opts) {
|
|
1878
|
+
let byKey = _resolveNamedRefCache.get(project);
|
|
1879
|
+
if (byKey === void 0) {
|
|
1880
|
+
byKey = /* @__PURE__ */ new Map();
|
|
1881
|
+
_resolveNamedRefCache.set(project, byKey);
|
|
1882
|
+
}
|
|
1883
|
+
const kindsKey = [...opts.kinds].sort().join(",");
|
|
1884
|
+
const key = `${sourceFile.getFilePath()}\0${name}\0${kindsKey}\0${opts.allowBareSpecifier ? 1 : 0}`;
|
|
1885
|
+
if (byKey.has(key)) {
|
|
1886
|
+
const cached = byKey.get(key) ?? null;
|
|
1887
|
+
return cached ? { ...cached } : null;
|
|
1888
|
+
}
|
|
1889
|
+
const computed = _computeNamedRef(name, sourceFile, project, opts);
|
|
1890
|
+
byKey.set(key, computed);
|
|
1891
|
+
return computed ? { ...computed } : null;
|
|
1892
|
+
}
|
|
1893
|
+
function _computeNamedRef(name, sourceFile, project, opts) {
|
|
1854
1894
|
if (_localDeclForKinds(name, sourceFile, opts.kinds)) {
|
|
1855
1895
|
return { name, filePath: sourceFile.getFilePath() };
|
|
1856
1896
|
}
|
|
@@ -1928,10 +1968,7 @@ function extractSchemaFromDto(classDecl, sourceFile, project) {
|
|
|
1928
1968
|
depth: 0
|
|
1929
1969
|
};
|
|
1930
1970
|
const root = buildObject(classDecl, sourceFile, ctx);
|
|
1931
|
-
|
|
1932
|
-
ctx.named.set(schemaName, { kind: "unknown", note: "recursive type \u2014 not expanded" });
|
|
1933
|
-
}
|
|
1934
|
-
return { root, named: ctx.named, warnings: ctx.warnings };
|
|
1971
|
+
return { root, named: ctx.named, warnings: ctx.warnings, recursive: ctx.recursiveSchemas };
|
|
1935
1972
|
}
|
|
1936
1973
|
function buildObject(classDecl, classFile, ctx) {
|
|
1937
1974
|
const props = classDecl.getProperties();
|
|
@@ -1951,7 +1988,7 @@ function buildProperty(prop, classFile, ctx) {
|
|
|
1951
1988
|
const dec = (n) => decorators.get(n);
|
|
1952
1989
|
const typeNode = prop.getTypeNode();
|
|
1953
1990
|
const typeText = typeNode?.getText() ?? "unknown";
|
|
1954
|
-
const isArrayType = !!typeNode &&
|
|
1991
|
+
const isArrayType = !!typeNode && import_ts_morph4.Node.isArrayTypeNode(typeNode);
|
|
1955
1992
|
const typeRefName = resolveTypeFactoryName(dec("Type"));
|
|
1956
1993
|
if (has("ValidateNested") || typeRefName) {
|
|
1957
1994
|
const childName = typeRefName ?? singularClassName(typeText);
|
|
@@ -2082,18 +2119,27 @@ function baseFromType(typeText, isArrayType) {
|
|
|
2082
2119
|
}
|
|
2083
2120
|
}
|
|
2084
2121
|
function buildNestedReference(className, fromFile, ctx) {
|
|
2085
|
-
if (ctx.visiting.has(className)
|
|
2122
|
+
if (ctx.visiting.has(className)) {
|
|
2086
2123
|
const reserved = ctx.emittedClasses.get(className) ?? aliasFor(className, ctx);
|
|
2087
2124
|
ctx.emittedClasses.set(className, reserved);
|
|
2088
2125
|
ctx.recursiveSchemas.add(reserved);
|
|
2089
2126
|
if (!ctx.warnedDecorators.has(`recursive:${reserved}`)) {
|
|
2090
2127
|
ctx.warnedDecorators.add(`recursive:${reserved}`);
|
|
2091
|
-
const msg = `${className} is a recursive type
|
|
2128
|
+
const msg = `${className} is a recursive type; the generated schema validates it via a lazy self-reference.`;
|
|
2092
2129
|
ctx.warnings.push(msg);
|
|
2093
2130
|
console.warn(`[nestjs-codegen] ${msg}`);
|
|
2094
2131
|
}
|
|
2095
2132
|
return { kind: "lazyRef", name: reserved };
|
|
2096
2133
|
}
|
|
2134
|
+
if (ctx.depth >= 8) {
|
|
2135
|
+
if (!ctx.warnedDecorators.has(`deep:${className}`)) {
|
|
2136
|
+
ctx.warnedDecorators.add(`deep:${className}`);
|
|
2137
|
+
const msg = `${className} nesting is too deep to expand; the generated schema uses unknown for it.`;
|
|
2138
|
+
ctx.warnings.push(msg);
|
|
2139
|
+
console.warn(`[nestjs-codegen] ${msg}`);
|
|
2140
|
+
}
|
|
2141
|
+
return { kind: "unknown", note: "nesting too deep \u2014 not expanded" };
|
|
2142
|
+
}
|
|
2097
2143
|
const existing = ctx.emittedClasses.get(className);
|
|
2098
2144
|
if (existing) return { kind: "ref", name: existing };
|
|
2099
2145
|
const schemaName = aliasFor(className, ctx);
|
|
@@ -2219,17 +2265,31 @@ var import_ts_morph6 = require("ts-morph");
|
|
|
2219
2265
|
var import_ts_morph5 = require("ts-morph");
|
|
2220
2266
|
|
|
2221
2267
|
// src/discovery/enum-resolution.ts
|
|
2268
|
+
var _enumCache = /* @__PURE__ */ new WeakMap();
|
|
2222
2269
|
function resolveEnumValues(name, sourceFile, project) {
|
|
2270
|
+
let byKey = _enumCache.get(project);
|
|
2271
|
+
if (byKey === void 0) {
|
|
2272
|
+
byKey = /* @__PURE__ */ new Map();
|
|
2273
|
+
_enumCache.set(project, byKey);
|
|
2274
|
+
}
|
|
2275
|
+
const key = `${sourceFile.getFilePath()}\0${name}`;
|
|
2276
|
+
if (byKey.has(key)) {
|
|
2277
|
+
const cached = byKey.get(key) ?? null;
|
|
2278
|
+
return cached ? { values: [...cached.values], numeric: cached.numeric } : null;
|
|
2279
|
+
}
|
|
2223
2280
|
const resolved = findType(name, sourceFile, project);
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
const
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2281
|
+
let result = null;
|
|
2282
|
+
if (resolved && resolved.kind === "enum") {
|
|
2283
|
+
let numeric = true;
|
|
2284
|
+
const values = resolved.members.map((m) => {
|
|
2285
|
+
const parsed = JSON.parse(m);
|
|
2286
|
+
if (typeof parsed === "string") numeric = false;
|
|
2287
|
+
return String(parsed);
|
|
2288
|
+
});
|
|
2289
|
+
if (values.length > 0) result = { values, numeric };
|
|
2290
|
+
}
|
|
2291
|
+
byKey.set(key, result);
|
|
2292
|
+
return result ? { values: [...result.values], numeric: result.numeric } : null;
|
|
2233
2293
|
}
|
|
2234
2294
|
|
|
2235
2295
|
// src/discovery/filter-field-types.ts
|
|
@@ -3498,8 +3558,57 @@ async function watch(config, onChange) {
|
|
|
3498
3558
|
};
|
|
3499
3559
|
}
|
|
3500
3560
|
|
|
3561
|
+
// src/ir/render-ts-type.ts
|
|
3562
|
+
function tsKey(name) {
|
|
3563
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
|
|
3564
|
+
}
|
|
3565
|
+
function renderTsType(node, ctx) {
|
|
3566
|
+
switch (node.kind) {
|
|
3567
|
+
case "string":
|
|
3568
|
+
return "string";
|
|
3569
|
+
case "number":
|
|
3570
|
+
return "number";
|
|
3571
|
+
case "boolean":
|
|
3572
|
+
return "boolean";
|
|
3573
|
+
case "date":
|
|
3574
|
+
return "Date";
|
|
3575
|
+
case "unknown":
|
|
3576
|
+
return "unknown";
|
|
3577
|
+
case "instanceof":
|
|
3578
|
+
return node.ctor;
|
|
3579
|
+
case "enum":
|
|
3580
|
+
return node.literals.join(" | ");
|
|
3581
|
+
case "literal":
|
|
3582
|
+
return node.raw;
|
|
3583
|
+
case "union":
|
|
3584
|
+
return node.options.map((o) => renderTsType(o, ctx)).join(" | ");
|
|
3585
|
+
case "array":
|
|
3586
|
+
return `Array<${renderTsType(node.element, ctx)}>`;
|
|
3587
|
+
case "optional":
|
|
3588
|
+
return `${renderTsType(node.inner, ctx)} | undefined`;
|
|
3589
|
+
case "annotated":
|
|
3590
|
+
return renderTsType(node.inner, ctx);
|
|
3591
|
+
case "object": {
|
|
3592
|
+
if (node.fields.length === 0) return node.passthrough ? "Record<string, unknown>" : "{}";
|
|
3593
|
+
const inner = node.fields.map((f) => {
|
|
3594
|
+
if (f.value.kind === "optional") {
|
|
3595
|
+
return `${tsKey(f.key)}?: ${renderTsType(f.value.inner, ctx)}`;
|
|
3596
|
+
}
|
|
3597
|
+
return `${tsKey(f.key)}: ${renderTsType(f.value, ctx)}`;
|
|
3598
|
+
}).join("; ");
|
|
3599
|
+
return `{ ${inner} }`;
|
|
3600
|
+
}
|
|
3601
|
+
case "ref":
|
|
3602
|
+
case "lazyRef": {
|
|
3603
|
+
if (ctx.recursive.has(node.name)) return ctx.typeNameFor(node.name);
|
|
3604
|
+
const target = ctx.named.get(node.name);
|
|
3605
|
+
return target ? renderTsType(target, ctx) : "unknown";
|
|
3606
|
+
}
|
|
3607
|
+
}
|
|
3608
|
+
}
|
|
3609
|
+
|
|
3501
3610
|
// src/index.ts
|
|
3502
|
-
var VERSION = "0.
|
|
3611
|
+
var VERSION = "0.4.1";
|
|
3503
3612
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3504
3613
|
0 && (module.exports = {
|
|
3505
3614
|
CodegenError,
|
|
@@ -3514,6 +3623,7 @@ var VERSION = "0.3.0";
|
|
|
3514
3623
|
extractSchemaFromDto,
|
|
3515
3624
|
generate,
|
|
3516
3625
|
loadConfig,
|
|
3626
|
+
renderTsType,
|
|
3517
3627
|
resolveAdapter,
|
|
3518
3628
|
resolveConfig,
|
|
3519
3629
|
watch
|