@dudousxd/nestjs-codegen 0.25.2 → 0.26.0

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/dist/cli/main.cjs CHANGED
@@ -552,16 +552,16 @@ var import_node_path7 = require("path");
552
552
 
553
553
  // src/extension/registry.ts
554
554
  var import_node_path6 = require("path");
555
- var import_ts_morph10 = require("ts-morph");
555
+ var import_ts_morph13 = require("ts-morph");
556
556
 
557
557
  // src/discovery/contracts-fast.ts
558
558
  var import_node_fs = require("fs");
559
559
  var import_node_path5 = require("path");
560
560
  var import_fast_glob2 = __toESM(require("fast-glob"), 1);
561
- var import_ts_morph9 = require("ts-morph");
561
+ var import_ts_morph12 = require("ts-morph");
562
562
 
563
563
  // src/discovery/dto-type-resolver.ts
564
- var import_ts_morph7 = require("ts-morph");
564
+ var import_ts_morph11 = require("ts-morph");
565
565
 
566
566
  // src/discovery/dto-to-ir.ts
567
567
  var import_ts_morph3 = require("ts-morph");
@@ -2089,6 +2089,672 @@ function extractFilterableEntityFields(filterClass, project, entityOverride, pre
2089
2089
  return fields;
2090
2090
  }
2091
2091
 
2092
+ // src/discovery/pipe-schema.ts
2093
+ var import_ts_morph10 = require("ts-morph");
2094
+
2095
+ // src/discovery/schema-type-inference.ts
2096
+ var import_ts_morph8 = require("ts-morph");
2097
+
2098
+ // src/discovery/schema-type-program.ts
2099
+ var import_ts_morph7 = require("ts-morph");
2100
+ var PARAM_DECORATORS = /* @__PURE__ */ new Set(["Body", "Query", "Param"]);
2101
+ var SchemaTypeProgram = class {
2102
+ constructor(discovery) {
2103
+ this.discovery = discovery;
2104
+ const base = discovery.getCompilerOptions();
2105
+ this.options = {
2106
+ ...base,
2107
+ // A tsconfig-less consumer gets ES5 by default, whose lib has no `Map`/`Set`/
2108
+ // `Promise` for the schema libraries' declarations to lean on.
2109
+ target: base.target ?? import_ts_morph7.ts.ScriptTarget.ES2022,
2110
+ // With neither set, resolve the way a bundler does: package `exports`
2111
+ // (`zod/v4`) and extensionless or `.js` relative imports all resolve.
2112
+ ...base.module === void 0 && base.moduleResolution === void 0 ? { module: import_ts_morph7.ts.ModuleKind.ESNext, moduleResolution: import_ts_morph7.ts.ModuleResolutionKind.Bundler } : {},
2113
+ // Without it `.nullable()` and `.optional()` would erase to the bare type.
2114
+ strictNullChecks: true,
2115
+ // No ambient `@types/*` (a tsconfig's `types: ['node']`): a schema does not
2116
+ // need them, and they are a hundred-odd files of program to build.
2117
+ types: [],
2118
+ noEmit: true
2119
+ };
2120
+ this.project = new import_ts_morph7.Project({
2121
+ skipAddingFilesFromTsConfig: true,
2122
+ compilerOptions: this.options
2123
+ });
2124
+ for (const sf of discovery.getSourceFiles()) this.request(sf.getFilePath(), { schema: true });
2125
+ this.flush();
2126
+ }
2127
+ project;
2128
+ options;
2129
+ /** Parses a file that is not in discovery's Project, without adding it there. */
2130
+ scratch = new import_ts_morph7.Project({
2131
+ skipAddingFilesFromTsConfig: true,
2132
+ skipLoadingLibFiles: true,
2133
+ skipFileDependencyResolution: true
2134
+ });
2135
+ needs = /* @__PURE__ */ new Map();
2136
+ /** Pruned text per file, as last written into {@link project}. */
2137
+ written = /* @__PURE__ */ new Map();
2138
+ /**
2139
+ * The typed copy of a discovery file, with its schema positions kept. Adding one
2140
+ * that was not there yet (a contract file discovery reached lazily) rebuilds the
2141
+ * program once.
2142
+ */
2143
+ sourceFileFor(sf) {
2144
+ this.request(sf.getFilePath(), { schema: true });
2145
+ this.flush();
2146
+ return this.project.getSourceFile(sf.getFilePath());
2147
+ }
2148
+ // -------------------------------------------------------------------------
2149
+ queue = [];
2150
+ request(path, want) {
2151
+ let needs = this.needs.get(path);
2152
+ const isNew = !needs;
2153
+ needs ??= { schema: false, all: false, names: /* @__PURE__ */ new Set() };
2154
+ let grew = isNew;
2155
+ if (want.schema && !needs.schema) {
2156
+ needs.schema = true;
2157
+ grew = true;
2158
+ }
2159
+ if (want.all && !needs.all) {
2160
+ needs.all = true;
2161
+ grew = true;
2162
+ }
2163
+ for (const name of want.names ?? []) {
2164
+ if (!needs.names.has(name)) {
2165
+ needs.names.add(name);
2166
+ grew = true;
2167
+ }
2168
+ }
2169
+ this.needs.set(path, needs);
2170
+ if (grew) this.queue.push(path);
2171
+ }
2172
+ /** Run the worklist to a fixpoint, then write every changed file into the program. */
2173
+ flush() {
2174
+ const changed = /* @__PURE__ */ new Map();
2175
+ while (this.queue.length > 0) {
2176
+ const path = this.queue.pop();
2177
+ const original = this.original(path);
2178
+ if (!original) continue;
2179
+ const needs = this.needs.get(path);
2180
+ const text = this.prune(original, needs);
2181
+ if (this.written.get(path) !== text) changed.set(path, text);
2182
+ }
2183
+ for (const [path, text] of changed) {
2184
+ this.project.createSourceFile(path, text, { overwrite: true });
2185
+ this.written.set(path, text);
2186
+ }
2187
+ }
2188
+ /** The file as discovery sees it (its in-memory text), else as it is on disk. */
2189
+ original(path) {
2190
+ return this.discovery.getSourceFile(path) ?? this.scratch.getSourceFile(path) ?? this.scratch.addSourceFileAtPathIfExists(path);
2191
+ }
2192
+ /**
2193
+ * `sf`'s text with every import/re-export nothing in `needs` references blanked,
2194
+ * requesting from each kept one's target the names it brings in.
2195
+ */
2196
+ prune(sf, needs) {
2197
+ const locals = topLevelDeclarations(sf);
2198
+ const roots = [];
2199
+ if (needs.all) roots.push(...sf.getStatements());
2200
+ if (needs.schema) roots.push(...schemaPositions(sf));
2201
+ const reexported = /* @__PURE__ */ new Map();
2202
+ for (const exp of sf.getExportDeclarations()) {
2203
+ const spec = exp.getModuleSpecifierValue();
2204
+ if (spec === void 0) {
2205
+ for (const named of exp.getNamedExports()) {
2206
+ const exposed = (named.getAliasNode() ?? named.getNameNode()).getText();
2207
+ if (needs.all || needs.names.has(exposed)) roots.push(named.getNameNode());
2208
+ }
2209
+ continue;
2210
+ }
2211
+ if (exp.isNamespaceExport() || exp.getNamedExports().length === 0) continue;
2212
+ for (const named of exp.getNamedExports()) {
2213
+ const exposed = (named.getAliasNode() ?? named.getNameNode()).getText();
2214
+ const list = reexported.get(exposed) ?? [];
2215
+ list.push({ from: spec, name: named.getNameNode().getText() });
2216
+ reexported.set(exposed, list);
2217
+ }
2218
+ }
2219
+ const unresolvedNames = [];
2220
+ for (const name of needs.names) {
2221
+ const decls = name === "default" ? defaultExport(sf) : locals.get(name) ?? [];
2222
+ if (decls.length > 0) roots.push(...decls);
2223
+ else if (!reexported.has(name)) unresolvedNames.push(name);
2224
+ }
2225
+ const referenced = /* @__PURE__ */ new Set();
2226
+ const queue = [...roots];
2227
+ const seen = new Set(queue);
2228
+ while (queue.length > 0) {
2229
+ const node = queue.pop();
2230
+ const ids = import_ts_morph7.Node.isIdentifier(node) ? [node] : node.getDescendantsOfKind(import_ts_morph7.ts.SyntaxKind.Identifier);
2231
+ for (const id of ids) {
2232
+ const name = id.getText();
2233
+ if (referenced.has(name)) continue;
2234
+ referenced.add(name);
2235
+ for (const local of locals.get(name) ?? []) {
2236
+ if (seen.has(local)) continue;
2237
+ seen.add(local);
2238
+ queue.push(local);
2239
+ }
2240
+ }
2241
+ }
2242
+ const chars = sf.getFullText().split("");
2243
+ const blank = (node) => {
2244
+ for (let i = node.getStart(); i < node.getEnd(); i++) {
2245
+ if (chars[i] !== "\n" && chars[i] !== "\r") chars[i] = " ";
2246
+ }
2247
+ };
2248
+ for (const decl of sf.getImportDeclarations()) {
2249
+ const target = this.resolve(decl.getModuleSpecifierValue(), sf);
2250
+ const namespace = decl.getNamespaceImport()?.getText();
2251
+ const def = decl.getDefaultImport()?.getText();
2252
+ const named = decl.getNamedImports().map((n) => ({
2253
+ local: (n.getAliasNode() ?? n.getNameNode()).getText(),
2254
+ imported: n.getName()
2255
+ })).filter((n) => referenced.has(n.local));
2256
+ const wantsNamespace = namespace !== void 0 && referenced.has(namespace);
2257
+ const wantsDefault = def !== void 0 && referenced.has(def);
2258
+ if (!wantsNamespace && !wantsDefault && named.length === 0) {
2259
+ blank(decl);
2260
+ continue;
2261
+ }
2262
+ if (target) {
2263
+ this.request(target, {
2264
+ all: wantsNamespace,
2265
+ names: [...wantsDefault ? ["default"] : [], ...named.map((n) => n.imported)]
2266
+ });
2267
+ }
2268
+ }
2269
+ for (const exp of sf.getExportDeclarations()) {
2270
+ const spec = exp.getModuleSpecifierValue();
2271
+ if (spec === void 0) continue;
2272
+ const target = this.resolve(spec, sf);
2273
+ if (exp.isNamespaceExport() || exp.getNamedExports().length === 0) {
2274
+ if (!needs.all && unresolvedNames.length === 0) {
2275
+ blank(exp);
2276
+ } else if (target) {
2277
+ this.request(target, { all: needs.all, names: unresolvedNames });
2278
+ }
2279
+ continue;
2280
+ }
2281
+ const wanted = exp.getNamedExports().filter(
2282
+ (n) => needs.all || needs.names.has((n.getAliasNode() ?? n.getNameNode()).getText())
2283
+ ).map((n) => n.getNameNode().getText());
2284
+ if (wanted.length === 0) blank(exp);
2285
+ else if (target) this.request(target, { names: wanted });
2286
+ }
2287
+ return chars.join("");
2288
+ }
2289
+ /**
2290
+ * The project source file a module specifier resolves to, or undefined for a
2291
+ * package (read unpruned by the program itself) or an unresolvable one.
2292
+ */
2293
+ resolve(specifier, from) {
2294
+ const resolved = import_ts_morph7.ts.resolveModuleName(
2295
+ specifier,
2296
+ from.getFilePath(),
2297
+ this.options,
2298
+ import_ts_morph7.ts.sys
2299
+ ).resolvedModule;
2300
+ if (!resolved || resolved.isExternalLibraryImport) return void 0;
2301
+ const file = resolved.resolvedFileName;
2302
+ if (file.endsWith(".d.ts") || !/\.(m|c)?tsx?$/.test(file)) return void 0;
2303
+ return file;
2304
+ }
2305
+ };
2306
+ function schemaPositions(sf) {
2307
+ const roots = [];
2308
+ sf.forEachDescendant((node) => {
2309
+ if (import_ts_morph7.Node.isDecorator(node)) {
2310
+ const name = node.getName();
2311
+ if (name === "ApplyContract") {
2312
+ roots.push(...node.getArguments());
2313
+ } else if (PARAM_DECORATORS.has(name)) {
2314
+ for (const arg of node.getArguments()) {
2315
+ if (import_ts_morph7.Node.isNewExpression(arg) || import_ts_morph7.Node.isCallExpression(arg)) {
2316
+ roots.push(...arg.getArguments());
2317
+ }
2318
+ }
2319
+ }
2320
+ } else if (import_ts_morph7.Node.isCallExpression(node)) {
2321
+ const callee = node.getExpression();
2322
+ const name = import_ts_morph7.Node.isIdentifier(callee) ? callee.getText() : import_ts_morph7.Node.isPropertyAccessExpression(callee) ? callee.getName() : void 0;
2323
+ if (name === "defineContract") roots.push(...node.getArguments());
2324
+ }
2325
+ });
2326
+ return roots;
2327
+ }
2328
+ function topLevelDeclarations(sf) {
2329
+ const byName = /* @__PURE__ */ new Map();
2330
+ const add = (name, node) => {
2331
+ if (!name) return;
2332
+ const list = byName.get(name);
2333
+ if (list) list.push(node);
2334
+ else byName.set(name, [node]);
2335
+ };
2336
+ for (const decl of sf.getVariableDeclarations()) add(decl.getName(), decl);
2337
+ for (const decl of sf.getFunctions()) add(decl.getName(), decl);
2338
+ for (const decl of sf.getClasses()) add(decl.getName(), decl);
2339
+ for (const decl of sf.getEnums()) add(decl.getName(), decl);
2340
+ for (const decl of sf.getInterfaces()) add(decl.getName(), decl);
2341
+ for (const decl of sf.getTypeAliases()) add(decl.getName(), decl);
2342
+ for (const decl of sf.getModules()) add(decl.getName(), decl);
2343
+ return byName;
2344
+ }
2345
+ function defaultExport(sf) {
2346
+ const nodes = [];
2347
+ for (const assignment of sf.getExportAssignments()) nodes.push(assignment);
2348
+ for (const fn of sf.getFunctions()) if (fn.isDefaultExport()) nodes.push(fn);
2349
+ for (const cls of sf.getClasses()) if (cls.isDefaultExport()) nodes.push(cls);
2350
+ return nodes;
2351
+ }
2352
+
2353
+ // src/discovery/schema-type-inference.ts
2354
+ var programs = /* @__PURE__ */ new WeakMap();
2355
+ function programFor(discovery) {
2356
+ let program = programs.get(discovery);
2357
+ if (!program) {
2358
+ program = new SchemaTypeProgram(discovery);
2359
+ programs.set(discovery, program);
2360
+ }
2361
+ return program;
2362
+ }
2363
+ function clearSchemaTypeProject(discovery) {
2364
+ programs.delete(discovery);
2365
+ }
2366
+ function counterpart(typedSf, node) {
2367
+ const start = node.getStart();
2368
+ const end = node.getEnd();
2369
+ const kind = node.getKind();
2370
+ let candidate = typedSf.getDescendantAtPos(start);
2371
+ while (candidate) {
2372
+ if (candidate.getStart() === start && candidate.getEnd() === end && candidate.getKind() === kind) {
2373
+ return candidate;
2374
+ }
2375
+ if (candidate.getStart() < start || candidate.getEnd() > end) return void 0;
2376
+ candidate = candidate.getParent();
2377
+ }
2378
+ return void 0;
2379
+ }
2380
+ function propType(type, name, at) {
2381
+ return type.getProperty(name)?.getTypeAtLocation(at);
2382
+ }
2383
+ function isAnyOrUnknown(type) {
2384
+ return type.isAny() || type.isUnknown();
2385
+ }
2386
+ function inferSchema(expr, discovery) {
2387
+ try {
2388
+ const typedSf = programFor(discovery).sourceFileFor(expr.getSourceFile());
2389
+ const at = typedSf && counterpart(typedSf, expr);
2390
+ if (!at) return { kind: "unresolved" };
2391
+ const schemaType = at.getType();
2392
+ if (isAnyOrUnknown(schemaType)) return { kind: "unresolved" };
2393
+ const standard = propType(schemaType, "~standard", at);
2394
+ const stdTypes = standard ? propType(standard, "types", at)?.getNonNullableType() : void 0;
2395
+ const stdInput = stdTypes ? propType(stdTypes, "input", at) : void 0;
2396
+ const stdOutput = stdTypes ? propType(stdTypes, "output", at) : void 0;
2397
+ if (stdInput && stdOutput) {
2398
+ return { kind: "schema", types: { input: stdInput, output: stdOutput, at } };
2399
+ }
2400
+ const zodInput = propType(schemaType, "_input", at);
2401
+ const zodOutput = propType(schemaType, "_output", at);
2402
+ if (zodInput && zodOutput) {
2403
+ return { kind: "schema", types: { input: zodInput, output: zodOutput, at } };
2404
+ }
2405
+ return { kind: "not-schema" };
2406
+ } catch (err) {
2407
+ dbg("schema inference failed:", err);
2408
+ return { kind: "unresolved" };
2409
+ }
2410
+ }
2411
+ var GLOBAL_NAMED_TYPES = /* @__PURE__ */ new Set([
2412
+ "Date",
2413
+ "File",
2414
+ "Blob",
2415
+ "FormData",
2416
+ "URL",
2417
+ "RegExp",
2418
+ "Map",
2419
+ "Set",
2420
+ "ArrayBuffer",
2421
+ "Uint8Array"
2422
+ ]);
2423
+ var MAX_DEPTH = 12;
2424
+ function objectKey(name) {
2425
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
2426
+ }
2427
+ function isOptionalSymbol(sym) {
2428
+ return (sym.getFlags() & import_ts_morph8.ts.SymbolFlags.Optional) !== 0;
2429
+ }
2430
+ function isSymbolKeyed(sym) {
2431
+ return sym.getName().startsWith("__@");
2432
+ }
2433
+ function orderedProperties(type) {
2434
+ const position = (sym) => {
2435
+ const decl = sym.getDeclarations()[0];
2436
+ return decl ? [decl.getSourceFile().getFilePath(), decl.getStart()] : void 0;
2437
+ };
2438
+ return type.getProperties().map((sym, index) => ({ sym, index, at: position(sym) })).sort((a, b) => {
2439
+ if (a.at && b.at) {
2440
+ if (a.at[0] !== b.at[0]) return a.at[0] < b.at[0] ? -1 : 1;
2441
+ if (a.at[1] !== b.at[1]) return a.at[1] - b.at[1];
2442
+ } else if (a.at || b.at) {
2443
+ return a.at ? -1 : 1;
2444
+ }
2445
+ return a.index - b.index;
2446
+ }).map((entry) => entry.sym);
2447
+ }
2448
+ function isFromDeclarationFile(sym) {
2449
+ const decl = sym?.getDeclarations()[0];
2450
+ return !!decl && decl.getSourceFile().isDeclarationFile();
2451
+ }
2452
+ function render(type, state, paired) {
2453
+ if (state.depth > MAX_DEPTH) return "unknown";
2454
+ if (isAnyOrUnknown(type)) {
2455
+ return paired && !isAnyOrUnknown(paired) ? render(paired, state) : "unknown";
2456
+ }
2457
+ if (type.isNever()) return "never";
2458
+ if (type.isString() || type.isTemplateLiteral()) return "string";
2459
+ if (type.isNumber()) return "number";
2460
+ if (type.isBoolean()) return "boolean";
2461
+ if (type.isBigInt()) return "bigint";
2462
+ if (type.isNull()) return "null";
2463
+ if (type.isUndefined() || type.isVoid()) return "undefined";
2464
+ if (type.isBooleanLiteral()) return type.getText();
2465
+ if (type.isStringLiteral() || type.isNumberLiteral() || type.isEnumLiteral()) {
2466
+ const value = type.getLiteralValue();
2467
+ return typeof value === "string" ? JSON.stringify(value) : String(value);
2468
+ }
2469
+ if (type.isBigIntLiteral()) return type.getText();
2470
+ if (type.isTypeParameter()) return "unknown";
2471
+ if (type.isUnion()) return renderUnion(type, state, paired);
2472
+ if (type.isIntersection()) return renderIntersection(type, state);
2473
+ const next = { ...state, depth: state.depth + 1 };
2474
+ if (type.isArray() || type.isReadonlyArray()) {
2475
+ const element = type.getArrayElementType() ?? type.getTypeArguments()[0];
2476
+ const pairedElement = paired?.getArrayElementType() ?? paired?.getTypeArguments()[0];
2477
+ return element ? `Array<${render(element, next, pairedElement)}>` : "Array<unknown>";
2478
+ }
2479
+ if (type.isTuple()) {
2480
+ const elements = type.getTupleElements();
2481
+ const pairedElements = paired?.isTuple() ? paired.getTupleElements() : [];
2482
+ return `[${elements.map((e, i) => render(e, next, pairedElements[i])).join(", ")}]`;
2483
+ }
2484
+ if (type.isObject()) return renderObject(type, next, paired);
2485
+ return "unknown";
2486
+ }
2487
+ function renderUnion(type, state, paired) {
2488
+ const members = type.getUnionTypes();
2489
+ const hasTrue = members.some((m) => m.isBooleanLiteral() && m.getText() === "true");
2490
+ const hasFalse = members.some((m) => m.isBooleanLiteral() && m.getText() === "false");
2491
+ const pairedNonNull = paired?.getNonNullableType();
2492
+ const arms = [];
2493
+ let sawBoolean = false;
2494
+ let hasNull = false;
2495
+ let hasUndefined = false;
2496
+ for (const member of members) {
2497
+ if (member.isNull()) {
2498
+ hasNull = true;
2499
+ continue;
2500
+ }
2501
+ if (member.isUndefined()) {
2502
+ hasUndefined = true;
2503
+ continue;
2504
+ }
2505
+ if (member.isBooleanLiteral() && hasTrue && hasFalse) {
2506
+ if (!sawBoolean) arms.push("boolean");
2507
+ sawBoolean = true;
2508
+ continue;
2509
+ }
2510
+ arms.push(render(member, state, members.length === 1 ? paired : pairedNonNull));
2511
+ }
2512
+ if (hasNull) arms.push("null");
2513
+ if (hasUndefined) arms.push("undefined");
2514
+ const unique = [...new Set(arms)];
2515
+ if (unique.includes("unknown")) return "unknown";
2516
+ return unique.join(" | ");
2517
+ }
2518
+ function renderIntersection(type, state) {
2519
+ const members = type.getIntersectionTypes();
2520
+ const primitive = members.find((m) => !m.isObject());
2521
+ if (primitive) return render(primitive, state);
2522
+ return renderObject(type, { ...state, depth: state.depth + 1 }, void 0);
2523
+ }
2524
+ function renderObject(type, state, paired) {
2525
+ const symbol = type.getSymbol() ?? type.getAliasSymbol();
2526
+ const name = symbol?.getName();
2527
+ if (name && GLOBAL_NAMED_TYPES.has(name) && isFromDeclarationFile(symbol)) {
2528
+ const args = type.getTypeArguments();
2529
+ return args.length ? `${name}<${args.map((a) => render(a, state)).join(", ")}>` : name;
2530
+ }
2531
+ if (type.getCallSignatures().length > 0 || type.getConstructSignatures().length > 0) {
2532
+ return "unknown";
2533
+ }
2534
+ if (type.isClassOrInterface() && isFromDeclarationFile(symbol)) return "unknown";
2535
+ if (state.stack.has(type.compilerType)) return "unknown";
2536
+ const stack = new Set(state.stack).add(type.compilerType);
2537
+ const inner = { ...state, stack };
2538
+ const fields = [];
2539
+ for (const prop of orderedProperties(type)) {
2540
+ if (isSymbolKeyed(prop)) continue;
2541
+ const propName = prop.getName();
2542
+ const propT = prop.getTypeAtLocation(state.at);
2543
+ if (propT.getCallSignatures().length > 0 && !propT.isUnion()) continue;
2544
+ const pairedProp = paired?.getProperty(propName)?.getTypeAtLocation(state.at);
2545
+ const optional = isOptionalSymbol(prop) ? "?" : "";
2546
+ fields.push(`${objectKey(propName)}${optional}: ${render(propT, inner, pairedProp)}`);
2547
+ }
2548
+ const stringIndex = type.getStringIndexType();
2549
+ if (stringIndex) {
2550
+ const pairedIndex = paired?.getStringIndexType();
2551
+ const value = render(stringIndex, inner, pairedIndex);
2552
+ if (fields.length === 0) return `Record<string, ${value}>`;
2553
+ fields.push(`[key: string]: ${value}`);
2554
+ }
2555
+ return fields.length ? `{ ${fields.join("; ")} }` : "{}";
2556
+ }
2557
+ function stateAt(at) {
2558
+ return { at, stack: /* @__PURE__ */ new Set(), depth: 0 };
2559
+ }
2560
+ function requestTypeOf(types) {
2561
+ return render(types.input, stateAt(types.at), types.output);
2562
+ }
2563
+ function responseTypeOf(types) {
2564
+ return render(types.output, stateAt(types.at));
2565
+ }
2566
+ function requestFieldsOf(types) {
2567
+ const { input, output, at } = types;
2568
+ const objectInput = input.getNonNullableType();
2569
+ if (!objectInput.isObject() || objectInput.isArray() || objectInput.isTuple()) return null;
2570
+ const state = stateAt(at);
2571
+ return orderedProperties(objectInput).filter((prop) => !isSymbolKeyed(prop)).map((prop) => ({
2572
+ name: prop.getName(),
2573
+ type: render(
2574
+ prop.getTypeAtLocation(at),
2575
+ state,
2576
+ output.getProperty(prop.getName())?.getTypeAtLocation(at)
2577
+ ),
2578
+ optional: isOptionalSymbol(prop)
2579
+ }));
2580
+ }
2581
+ function acceptsUndefined(types) {
2582
+ const { input, output } = types;
2583
+ const accepted = isAnyOrUnknown(input) ? output : input;
2584
+ if (isAnyOrUnknown(accepted) || accepted.isUndefined()) return true;
2585
+ return accepted.isUnion() && accepted.getUnionTypes().some((t) => t.isUndefined());
2586
+ }
2587
+
2588
+ // src/discovery/zod-ast-to-ts.ts
2589
+ var import_ts_morph9 = require("ts-morph");
2590
+ function zodAstToTs(node) {
2591
+ if (!import_ts_morph9.Node.isCallExpression(node)) return "unknown";
2592
+ const expr = node.getExpression();
2593
+ if (import_ts_morph9.Node.isPropertyAccessExpression(expr)) {
2594
+ const methodName = expr.getName();
2595
+ const receiver = expr.getExpression();
2596
+ if (methodName === "optional") {
2597
+ return `${zodAstToTs(receiver)} | undefined`;
2598
+ }
2599
+ if (methodName === "nullable") {
2600
+ return `${zodAstToTs(receiver)} | null`;
2601
+ }
2602
+ const args = node.getArguments();
2603
+ switch (methodName) {
2604
+ case "string":
2605
+ return "string";
2606
+ case "number":
2607
+ return "number";
2608
+ case "boolean":
2609
+ return "boolean";
2610
+ case "unknown":
2611
+ return "unknown";
2612
+ case "any":
2613
+ return "unknown";
2614
+ case "literal": {
2615
+ const lit = args[0];
2616
+ if (!lit) return "unknown";
2617
+ if (import_ts_morph9.Node.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());
2618
+ if (import_ts_morph9.Node.isNumericLiteral(lit)) return lit.getLiteralValue().toString();
2619
+ if (lit.getKind() === import_ts_morph9.SyntaxKind.TrueKeyword) return "true";
2620
+ if (lit.getKind() === import_ts_morph9.SyntaxKind.FalseKeyword) return "false";
2621
+ return "unknown";
2622
+ }
2623
+ case "enum": {
2624
+ const arrArg = args[0];
2625
+ if (!arrArg || !import_ts_morph9.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2626
+ const members = arrArg.getElements().map(
2627
+ (el) => import_ts_morph9.Node.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : "unknown"
2628
+ );
2629
+ return members.join(" | ");
2630
+ }
2631
+ case "array": {
2632
+ const inner = args[0];
2633
+ if (!inner) return "unknown";
2634
+ return `Array<${zodAstToTs(inner)}>`;
2635
+ }
2636
+ case "object": {
2637
+ const objArg = args[0];
2638
+ if (!objArg || !import_ts_morph9.Node.isObjectLiteralExpression(objArg)) return "unknown";
2639
+ const lines = [];
2640
+ for (const prop of objArg.getProperties()) {
2641
+ if (!import_ts_morph9.Node.isPropertyAssignment(prop)) continue;
2642
+ const key = prop.getName();
2643
+ const valNode = prop.getInitializer();
2644
+ if (!valNode) continue;
2645
+ const tsType = zodAstToTs(valNode);
2646
+ const isOpt = isOptionalChain(valNode);
2647
+ lines.push(`${key}${isOpt ? "?" : ""}: ${tsType}`);
2648
+ }
2649
+ return `{ ${lines.join("; ")} }`;
2650
+ }
2651
+ case "union": {
2652
+ const arrArg = args[0];
2653
+ if (!arrArg || !import_ts_morph9.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2654
+ return arrArg.getElements().map(zodAstToTs).join(" | ");
2655
+ }
2656
+ case "record": {
2657
+ const valArg = args.length === 1 ? args[0] : args[1];
2658
+ if (!valArg) return "unknown";
2659
+ return `Record<string, ${zodAstToTs(valArg)}>`;
2660
+ }
2661
+ case "tuple": {
2662
+ const arrArg = args[0];
2663
+ if (!arrArg || !import_ts_morph9.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2664
+ return `[${arrArg.getElements().map(zodAstToTs).join(", ")}]`;
2665
+ }
2666
+ default:
2667
+ return "unknown";
2668
+ }
2669
+ }
2670
+ return "unknown";
2671
+ }
2672
+ function isOptionalChain(node) {
2673
+ if (!import_ts_morph9.Node.isCallExpression(node)) return false;
2674
+ const expr = node.getExpression();
2675
+ return import_ts_morph9.Node.isPropertyAccessExpression(expr) && expr.getName() === "optional";
2676
+ }
2677
+ function memberType(val, position, project) {
2678
+ if (project) {
2679
+ const inferred = inferSchema(val, project);
2680
+ if (inferred.kind === "schema") {
2681
+ return position === "request" ? requestTypeOf(inferred.types) : responseTypeOf(inferred.types);
2682
+ }
2683
+ }
2684
+ return zodAstToTs(val);
2685
+ }
2686
+ function parseDefineContractCall(callExpr, project) {
2687
+ if (!import_ts_morph9.Node.isCallExpression(callExpr)) return null;
2688
+ const callee = callExpr.getExpression();
2689
+ const calleeName = import_ts_morph9.Node.isIdentifier(callee) ? callee.getText() : import_ts_morph9.Node.isPropertyAccessExpression(callee) ? callee.getName() : "";
2690
+ if (calleeName !== "defineContract") return null;
2691
+ const args = callExpr.getArguments();
2692
+ const optsArg = args[0];
2693
+ if (!optsArg || !import_ts_morph9.Node.isObjectLiteralExpression(optsArg)) return null;
2694
+ let query = null;
2695
+ let body = null;
2696
+ let response = "unknown";
2697
+ let error = null;
2698
+ let bodyZodText = null;
2699
+ let queryZodText = null;
2700
+ for (const prop of optsArg.getProperties()) {
2701
+ if (!import_ts_morph9.Node.isPropertyAssignment(prop)) continue;
2702
+ const propName = prop.getName();
2703
+ const val = prop.getInitializer();
2704
+ if (!val) continue;
2705
+ if (propName === "query") {
2706
+ query = memberType(val, "request", project);
2707
+ queryZodText = val.getText();
2708
+ } else if (propName === "body") {
2709
+ body = memberType(val, "request", project);
2710
+ bodyZodText = val.getText();
2711
+ } else if (propName === "response") {
2712
+ response = memberType(val, "response", project);
2713
+ } else if (propName === "error") {
2714
+ error = memberType(val, "response", project);
2715
+ }
2716
+ }
2717
+ return { query, body, response, error, bodyZodText, queryZodText };
2718
+ }
2719
+
2720
+ // src/discovery/pipe-schema.ts
2721
+ function pipeSchemaOf(decorator, project) {
2722
+ for (const pipe of decorator.getArguments()) {
2723
+ if (!import_ts_morph10.Node.isNewExpression(pipe) && !import_ts_morph10.Node.isCallExpression(pipe)) continue;
2724
+ for (const arg of pipe.getArguments()) {
2725
+ if (!couldBeSchema(arg)) continue;
2726
+ const inferred = inferSchema(arg, project);
2727
+ if (inferred.kind === "schema") {
2728
+ return {
2729
+ type: requestTypeOf(inferred.types),
2730
+ optional: acceptsUndefined(inferred.types),
2731
+ fields: requestFieldsOf(inferred.types)
2732
+ };
2733
+ }
2734
+ if (inferred.kind === "unresolved") {
2735
+ const fallback = syntacticZodType(arg, project);
2736
+ if (fallback) {
2737
+ return { type: fallback, optional: fallback.endsWith("| undefined"), fields: null };
2738
+ }
2739
+ }
2740
+ }
2741
+ }
2742
+ return null;
2743
+ }
2744
+ function couldBeSchema(arg) {
2745
+ return import_ts_morph10.Node.isIdentifier(arg) || import_ts_morph10.Node.isPropertyAccessExpression(arg) || import_ts_morph10.Node.isCallExpression(arg) || import_ts_morph10.Node.isAsExpression(arg) || import_ts_morph10.Node.isSatisfiesExpression(arg) || import_ts_morph10.Node.isParenthesizedExpression(arg);
2746
+ }
2747
+ function syntacticZodType(arg, project) {
2748
+ let expr = arg;
2749
+ if (import_ts_morph10.Node.isIdentifier(arg)) {
2750
+ const resolved = resolveImportedVariable(arg.getText(), arg.getSourceFile(), project);
2751
+ expr = resolved?.decl.getInitializer();
2752
+ }
2753
+ if (!expr || !import_ts_morph10.Node.isCallExpression(expr)) return null;
2754
+ const type = zodAstToTs(expr);
2755
+ return type === "unknown" ? null : type;
2756
+ }
2757
+
2092
2758
  // src/discovery/dto-type-resolver.ts
2093
2759
  var WRAPPER_TYPES = {
2094
2760
  // MikroORM Ref/Reference/LoadedReference/IdentifiedReference are server-side
@@ -2120,22 +2786,22 @@ var PASSTHROUGH_UTILITY = /* @__PURE__ */ new Set([
2120
2786
  ]);
2121
2787
  function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /* @__PURE__ */ new Map()) {
2122
2788
  if (depth <= 0) return "unknown";
2123
- if (import_ts_morph7.Node.isArrayTypeNode(typeNode)) {
2789
+ if (import_ts_morph11.Node.isArrayTypeNode(typeNode)) {
2124
2790
  const elementType = typeNode.getElementTypeNode();
2125
2791
  return `Array<${resolveTypeNodeToString(elementType, sourceFile, project, depth, subst)}>`;
2126
2792
  }
2127
- if (import_ts_morph7.Node.isUnionTypeNode(typeNode)) {
2793
+ if (import_ts_morph11.Node.isUnionTypeNode(typeNode)) {
2128
2794
  return typeNode.getTypeNodes().map((t) => resolveTypeNodeToString(t, sourceFile, project, depth, subst)).join(" | ");
2129
2795
  }
2130
- if (import_ts_morph7.Node.isIntersectionTypeNode(typeNode)) {
2796
+ if (import_ts_morph11.Node.isIntersectionTypeNode(typeNode)) {
2131
2797
  return typeNode.getTypeNodes().map((t) => resolveTypeNodeToString(t, sourceFile, project, depth, subst)).join(" & ");
2132
2798
  }
2133
- if (import_ts_morph7.Node.isParenthesizedTypeNode(typeNode)) {
2799
+ if (import_ts_morph11.Node.isParenthesizedTypeNode(typeNode)) {
2134
2800
  return `(${resolveTypeNodeToString(typeNode.getTypeNode(), sourceFile, project, depth, subst)})`;
2135
2801
  }
2136
- if (import_ts_morph7.Node.isTypeReference(typeNode)) {
2802
+ if (import_ts_morph11.Node.isTypeReference(typeNode)) {
2137
2803
  const typeName = typeNode.getTypeName();
2138
- const name = import_ts_morph7.Node.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();
2804
+ const name = import_ts_morph11.Node.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();
2139
2805
  const bound = subst.get(name);
2140
2806
  if (bound !== void 0) return bound;
2141
2807
  if (name === "string" || name === "number" || name === "boolean") return name;
@@ -2158,13 +2824,13 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /
2158
2824
  dbg("unresolvable type:", name, "in", sourceFile.getFilePath());
2159
2825
  return "unknown";
2160
2826
  }
2161
- if (import_ts_morph7.Node.isTypeLiteral(typeNode)) {
2827
+ if (import_ts_morph11.Node.isTypeLiteral(typeNode)) {
2162
2828
  const members = [];
2163
2829
  for (const member of typeNode.getMembers()) {
2164
- if (import_ts_morph7.Node.isPropertySignature(member)) {
2830
+ if (import_ts_morph11.Node.isPropertySignature(member)) {
2165
2831
  const memberTypeNode = member.getTypeNode();
2166
- const memberType = memberTypeNode ? resolveTypeNodeToString(memberTypeNode, sourceFile, project, depth, subst) : "unknown";
2167
- members.push(`${member.getName()}${member.hasQuestionToken() ? "?" : ""}: ${memberType}`);
2832
+ const memberType2 = memberTypeNode ? resolveTypeNodeToString(memberTypeNode, sourceFile, project, depth, subst) : "unknown";
2833
+ members.push(`${member.getName()}${member.hasQuestionToken() ? "?" : ""}: ${memberType2}`);
2168
2834
  } else {
2169
2835
  members.push(member.getText());
2170
2836
  }
@@ -2172,11 +2838,11 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /
2172
2838
  return members.length > 0 ? `{ ${members.join("; ")} }` : "{}";
2173
2839
  }
2174
2840
  const kind = typeNode.getKind();
2175
- if (kind === import_ts_morph7.SyntaxKind.StringKeyword) return "string";
2176
- if (kind === import_ts_morph7.SyntaxKind.NumberKeyword) return "number";
2177
- if (kind === import_ts_morph7.SyntaxKind.BooleanKeyword) return "boolean";
2178
- if (kind === import_ts_morph7.SyntaxKind.UnknownKeyword) return "unknown";
2179
- if (kind === import_ts_morph7.SyntaxKind.AnyKeyword) return "unknown";
2841
+ if (kind === import_ts_morph11.SyntaxKind.StringKeyword) return "string";
2842
+ if (kind === import_ts_morph11.SyntaxKind.NumberKeyword) return "number";
2843
+ if (kind === import_ts_morph11.SyntaxKind.BooleanKeyword) return "boolean";
2844
+ if (kind === import_ts_morph11.SyntaxKind.UnknownKeyword) return "unknown";
2845
+ if (kind === import_ts_morph11.SyntaxKind.AnyKeyword) return "unknown";
2180
2846
  return typeNode.getText();
2181
2847
  }
2182
2848
  function unwrapFirstTypeArg(typeNode, sourceFile, project, depth, mode, subst = /* @__PURE__ */ new Map()) {
@@ -2224,20 +2890,24 @@ function resolvePropertied(decl, sourceFile, project, depth, subst = /* @__PURE_
2224
2890
  const propName = prop.getName();
2225
2891
  const isOptional = prop.hasQuestionToken();
2226
2892
  const propTypeNode = prop.getTypeNode();
2227
- let propType = "unknown";
2893
+ let propType2 = "unknown";
2228
2894
  if (propTypeNode) {
2229
- propType = resolveTypeNodeToString(propTypeNode, sourceFile, project, depth, subst);
2895
+ propType2 = resolveTypeNodeToString(propTypeNode, sourceFile, project, depth, subst);
2230
2896
  }
2231
- lines.push(`${propName}${isOptional ? "?" : ""}: ${propType}`);
2897
+ lines.push(`${propName}${isOptional ? "?" : ""}: ${propType2}`);
2232
2898
  }
2233
2899
  return `{ ${lines.join("; ")} }`;
2234
2900
  }
2901
+ function namedField(decorator) {
2902
+ const first = decorator.getArguments()[0];
2903
+ return first && import_ts_morph11.Node.isStringLiteral(first) ? first.getLiteralValue() : null;
2904
+ }
2235
2905
  function extractBodyType(method, sourceFile, project) {
2236
2906
  for (const param of method.getParameters()) {
2237
2907
  const bodyDecorator = param.getDecorators().find((d) => d.getName() === "Body");
2238
- if (!bodyDecorator) continue;
2239
- const bodyArgs = bodyDecorator.getArguments();
2240
- if (bodyArgs.length > 0) continue;
2908
+ if (!bodyDecorator || namedField(bodyDecorator) !== null) continue;
2909
+ const piped = pipeSchemaOf(bodyDecorator, project);
2910
+ if (piped) return piped.type;
2241
2911
  const typeNode = param.getTypeNode();
2242
2912
  if (typeNode) {
2243
2913
  return resolveTypeNodeToString(typeNode, sourceFile, project, 3);
@@ -2245,11 +2915,16 @@ function extractBodyType(method, sourceFile, project) {
2245
2915
  }
2246
2916
  return null;
2247
2917
  }
2918
+ function hasPipeSchema(param, decoratorName, project) {
2919
+ const decorator = param.getDecorators().find((d) => d.getName() === decoratorName);
2920
+ return !!decorator && pipeSchemaOf(decorator, project) !== null;
2921
+ }
2248
2922
  function extractQueryType(method, sourceFile, project) {
2249
2923
  for (const param of method.getParameters()) {
2250
2924
  const queryDecorator = param.getDecorators().find((d) => d.getName() === "Query");
2251
- if (!queryDecorator) continue;
2252
- if (queryDecorator.getArguments().length > 0) continue;
2925
+ if (!queryDecorator || namedField(queryDecorator) !== null) continue;
2926
+ const piped = pipeSchemaOf(queryDecorator, project);
2927
+ if (piped) return piped.type;
2253
2928
  const typeNode = param.getTypeNode();
2254
2929
  if (typeNode) {
2255
2930
  return resolveTypeNodeToString(typeNode, sourceFile, project, 3);
@@ -2259,10 +2934,13 @@ function extractQueryType(method, sourceFile, project) {
2259
2934
  for (const param of method.getParameters()) {
2260
2935
  const queryDecorator = param.getDecorators().find((d) => d.getName() === "Query");
2261
2936
  if (!queryDecorator) continue;
2262
- const queryArgs = queryDecorator.getArguments();
2263
- const nameArg = queryArgs[0];
2264
- if (!nameArg || !import_ts_morph7.Node.isStringLiteral(nameArg)) continue;
2265
- const queryName = nameArg.getLiteralValue();
2937
+ const queryName = namedField(queryDecorator);
2938
+ if (queryName === null) continue;
2939
+ const piped = pipeSchemaOf(queryDecorator, project);
2940
+ if (piped) {
2941
+ entries.push(`${queryName}${piped.optional ? "?" : ""}: ${piped.type}`);
2942
+ continue;
2943
+ }
2266
2944
  const typeNode = param.getTypeNode();
2267
2945
  const queryType = typeNode ? resolveTypeNodeToString(typeNode, sourceFile, project, 3) : "string";
2268
2946
  entries.push(`${queryName}${isParamOptional(param) ? "?" : ""}: ${queryType}`);
@@ -2272,8 +2950,8 @@ function extractQueryType(method, sourceFile, project) {
2272
2950
  function isParamOptional(param) {
2273
2951
  if (param.hasQuestionToken() || param.hasInitializer()) return true;
2274
2952
  const typeNode = param.getTypeNode();
2275
- if (typeNode && import_ts_morph7.Node.isUnionTypeNode(typeNode)) {
2276
- return typeNode.getTypeNodes().some((t) => t.getKind() === import_ts_morph7.SyntaxKind.UndefinedKeyword);
2953
+ if (typeNode && import_ts_morph11.Node.isUnionTypeNode(typeNode)) {
2954
+ return typeNode.getTypeNodes().some((t) => t.getKind() === import_ts_morph11.SyntaxKind.UndefinedKeyword);
2277
2955
  }
2278
2956
  return false;
2279
2957
  }
@@ -2285,7 +2963,7 @@ function extractParamsType(method, sourceFile, project) {
2285
2963
  const paramArgs = paramDecorator.getArguments();
2286
2964
  if (paramArgs.length === 0) continue;
2287
2965
  const nameArg = paramArgs[0];
2288
- if (!import_ts_morph7.Node.isStringLiteral(nameArg)) continue;
2966
+ if (!import_ts_morph11.Node.isStringLiteral(nameArg)) continue;
2289
2967
  const paramName = nameArg.getLiteralValue();
2290
2968
  const typeNode = param.getTypeNode();
2291
2969
  const paramType = typeNode ? resolveTypeNodeToString(typeNode, sourceFile, project, 3) : "string";
@@ -2293,6 +2971,22 @@ function extractParamsType(method, sourceFile, project) {
2293
2971
  }
2294
2972
  return entries.length > 0 ? `{ ${entries.join("; ")} }` : null;
2295
2973
  }
2974
+ function extractPipedParamTypes(method, project) {
2975
+ const types = {};
2976
+ for (const param of method.getParameters()) {
2977
+ const paramDecorator = param.getDecorators().find((d) => d.getName() === "Param");
2978
+ if (!paramDecorator) continue;
2979
+ const piped = pipeSchemaOf(paramDecorator, project);
2980
+ if (!piped) continue;
2981
+ const name = namedField(paramDecorator);
2982
+ if (name !== null) {
2983
+ types[name] = piped.type;
2984
+ } else {
2985
+ for (const field of piped.fields ?? []) types[field.name] = field.type;
2986
+ }
2987
+ }
2988
+ return Object.keys(types).length > 0 ? types : null;
2989
+ }
2296
2990
  function extractUploadedFiles(method) {
2297
2991
  const FILE = "File | Blob";
2298
2992
  const entries = [];
@@ -2306,28 +3000,28 @@ function extractUploadedFiles(method) {
2306
3000
  for (const decorator of method.getDecorators()) {
2307
3001
  if (decorator.getName() !== "UseInterceptors") continue;
2308
3002
  for (const arg of decorator.getArguments()) {
2309
- if (!import_ts_morph7.Node.isCallExpression(arg)) continue;
3003
+ if (!import_ts_morph11.Node.isCallExpression(arg)) continue;
2310
3004
  const interceptor = arg.getExpression().getText();
2311
3005
  const callArgs = arg.getArguments();
2312
3006
  const firstArg2 = callArgs[0];
2313
3007
  if (interceptor === "FileInterceptor") {
2314
- if (firstArg2 && import_ts_morph7.Node.isStringLiteral(firstArg2)) {
3008
+ if (firstArg2 && import_ts_morph11.Node.isStringLiteral(firstArg2)) {
2315
3009
  entries.push(`${firstArg2.getLiteralValue()}: ${FILE}`);
2316
3010
  multipart = true;
2317
3011
  }
2318
3012
  } else if (interceptor === "FilesInterceptor") {
2319
- if (firstArg2 && import_ts_morph7.Node.isStringLiteral(firstArg2)) {
3013
+ if (firstArg2 && import_ts_morph11.Node.isStringLiteral(firstArg2)) {
2320
3014
  entries.push(`${firstArg2.getLiteralValue()}: Array<${FILE}>`);
2321
3015
  multipart = true;
2322
3016
  }
2323
3017
  } else if (interceptor === "FileFieldsInterceptor") {
2324
- if (firstArg2 && import_ts_morph7.Node.isArrayLiteralExpression(firstArg2)) {
3018
+ if (firstArg2 && import_ts_morph11.Node.isArrayLiteralExpression(firstArg2)) {
2325
3019
  for (const el of firstArg2.getElements()) {
2326
- if (!import_ts_morph7.Node.isObjectLiteralExpression(el)) continue;
3020
+ if (!import_ts_morph11.Node.isObjectLiteralExpression(el)) continue;
2327
3021
  const nameProp = el.getProperty("name");
2328
- if (nameProp && import_ts_morph7.Node.isPropertyAssignment(nameProp)) {
3022
+ if (nameProp && import_ts_morph11.Node.isPropertyAssignment(nameProp)) {
2329
3023
  const init = nameProp.getInitializer();
2330
- if (init && import_ts_morph7.Node.isStringLiteral(init)) {
3024
+ if (init && import_ts_morph11.Node.isStringLiteral(init)) {
2331
3025
  entries.push(`${init.getLiteralValue()}: Array<${FILE}>`);
2332
3026
  }
2333
3027
  }
@@ -2347,13 +3041,13 @@ function extractResponseType(method, sourceFile, project) {
2347
3041
  if (apiResponseDecorator) {
2348
3042
  const args = apiResponseDecorator.getArguments();
2349
3043
  const optsArg = args[0];
2350
- if (optsArg && import_ts_morph7.Node.isObjectLiteralExpression(optsArg)) {
3044
+ if (optsArg && import_ts_morph11.Node.isObjectLiteralExpression(optsArg)) {
2351
3045
  for (const prop of optsArg.getProperties()) {
2352
- if (!import_ts_morph7.Node.isPropertyAssignment(prop)) continue;
3046
+ if (!import_ts_morph11.Node.isPropertyAssignment(prop)) continue;
2353
3047
  if (prop.getName() !== "type") continue;
2354
3048
  const val = prop.getInitializer();
2355
3049
  if (!val) continue;
2356
- if (import_ts_morph7.Node.isArrayLiteralExpression(val)) {
3050
+ if (import_ts_morph11.Node.isArrayLiteralExpression(val)) {
2357
3051
  const elements = val.getElements();
2358
3052
  const firstEl = elements[0];
2359
3053
  if (elements.length > 0 && firstEl !== void 0) {
@@ -2374,24 +3068,24 @@ function extractResponseType(method, sourceFile, project) {
2374
3068
  }
2375
3069
  function apiResponseStatus(decorator) {
2376
3070
  const optsArg = decorator.getArguments()[0];
2377
- if (!optsArg || !import_ts_morph7.Node.isObjectLiteralExpression(optsArg)) return null;
3071
+ if (!optsArg || !import_ts_morph11.Node.isObjectLiteralExpression(optsArg)) return null;
2378
3072
  for (const prop of optsArg.getProperties()) {
2379
- if (!import_ts_morph7.Node.isPropertyAssignment(prop)) continue;
3073
+ if (!import_ts_morph11.Node.isPropertyAssignment(prop)) continue;
2380
3074
  if (prop.getName() !== "status") continue;
2381
3075
  const val = prop.getInitializer();
2382
- if (val && import_ts_morph7.Node.isNumericLiteral(val)) return Number(val.getLiteralValue());
3076
+ if (val && import_ts_morph11.Node.isNumericLiteral(val)) return Number(val.getLiteralValue());
2383
3077
  }
2384
3078
  return null;
2385
3079
  }
2386
3080
  function apiResponseTypeNode(decorator) {
2387
3081
  const optsArg = decorator.getArguments()[0];
2388
- if (!optsArg || !import_ts_morph7.Node.isObjectLiteralExpression(optsArg)) return null;
3082
+ if (!optsArg || !import_ts_morph11.Node.isObjectLiteralExpression(optsArg)) return null;
2389
3083
  for (const prop of optsArg.getProperties()) {
2390
- if (!import_ts_morph7.Node.isPropertyAssignment(prop)) continue;
3084
+ if (!import_ts_morph11.Node.isPropertyAssignment(prop)) continue;
2391
3085
  if (prop.getName() !== "type") continue;
2392
3086
  const val = prop.getInitializer();
2393
3087
  if (!val) return null;
2394
- if (import_ts_morph7.Node.isArrayLiteralExpression(val)) {
3088
+ if (import_ts_morph11.Node.isArrayLiteralExpression(val)) {
2395
3089
  const first = val.getElements()[0];
2396
3090
  return first ? { node: first, isArray: true } : null;
2397
3091
  }
@@ -2409,7 +3103,7 @@ function extractErrorType(method, sourceFile, project) {
2409
3103
  const inner = resolveIdentifierToClassType(typeInfo.node, sourceFile, project, 3);
2410
3104
  const type = typeInfo.isArray ? `Array<${inner}>` : inner;
2411
3105
  let ref = null;
2412
- if (import_ts_morph7.Node.isIdentifier(typeInfo.node)) {
3106
+ if (import_ts_morph11.Node.isIdentifier(typeInfo.node)) {
2413
3107
  const name = typeInfo.node.getText();
2414
3108
  const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
2415
3109
  if (localDecl?.isExported()) {
@@ -2426,7 +3120,7 @@ function extractErrorType(method, sourceFile, project) {
2426
3120
  return null;
2427
3121
  }
2428
3122
  function resolveIdentifierToClassType(node, sourceFile, project, depth) {
2429
- if (!import_ts_morph7.Node.isIdentifier(node)) return "unknown";
3123
+ if (!import_ts_morph11.Node.isIdentifier(node)) return "unknown";
2430
3124
  const name = node.getText();
2431
3125
  const resolved = findType(name, sourceFile, project);
2432
3126
  if (resolved) {
@@ -2446,9 +3140,9 @@ var STREAM_ENVELOPES = /* @__PURE__ */ new Set(["MessageEvent", "MessageEventLik
2446
3140
  var BINARY_RESPONSE_TYPES = /* @__PURE__ */ new Set(["StreamableFile", "Buffer"]);
2447
3141
  function detectBinaryResponse(method) {
2448
3142
  const node = unwrapNamedContainer(method.getReturnTypeNode(), /* @__PURE__ */ new Set(["Promise"]));
2449
- if (!node || !import_ts_morph7.Node.isTypeReference(node)) return false;
3143
+ if (!node || !import_ts_morph11.Node.isTypeReference(node)) return false;
2450
3144
  const typeName = node.getTypeName();
2451
- const name = import_ts_morph7.Node.isIdentifier(typeName) ? typeName.getText() : "";
3145
+ const name = import_ts_morph11.Node.isIdentifier(typeName) ? typeName.getText() : "";
2452
3146
  return BINARY_RESPONSE_TYPES.has(name);
2453
3147
  }
2454
3148
  function detectStreamElement(method) {
@@ -2463,9 +3157,9 @@ function detectStreamElement(method) {
2463
3157
  return null;
2464
3158
  }
2465
3159
  function streamContainerElement(node) {
2466
- if (!node || !import_ts_morph7.Node.isTypeReference(node)) return null;
3160
+ if (!node || !import_ts_morph11.Node.isTypeReference(node)) return null;
2467
3161
  const typeName = node.getTypeName();
2468
- const name = import_ts_morph7.Node.isIdentifier(typeName) ? typeName.getText() : "";
3162
+ const name = import_ts_morph11.Node.isIdentifier(typeName) ? typeName.getText() : "";
2469
3163
  if (STREAM_CONTAINERS.has(name) || STREAM_CONTAINERS_GENERATOR.has(name)) {
2470
3164
  return node.getTypeArguments()[0] ?? null;
2471
3165
  }
@@ -2475,9 +3169,9 @@ function hasAsQueryDecorator(method) {
2475
3169
  return method.getDecorators().some((d) => d.getName() === "AsQuery");
2476
3170
  }
2477
3171
  function unwrapNamedContainer(node, names) {
2478
- if (!node || !import_ts_morph7.Node.isTypeReference(node)) return node;
3172
+ if (!node || !import_ts_morph11.Node.isTypeReference(node)) return node;
2479
3173
  const typeName = node.getTypeName();
2480
- const name = import_ts_morph7.Node.isIdentifier(typeName) ? typeName.getText() : "";
3174
+ const name = import_ts_morph11.Node.isIdentifier(typeName) ? typeName.getText() : "";
2481
3175
  if (names.has(name)) {
2482
3176
  return node.getTypeArguments()[0] ?? node;
2483
3177
  }
@@ -2498,19 +3192,20 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2498
3192
  body = body ?? bodyType;
2499
3193
  }
2500
3194
  const paramsType = extractParamsType(method, sourceFile, project);
3195
+ const paramTypes = extractPipedParamTypes(method, project);
2501
3196
  const response = isStream ? resolveTypeNodeToString(streamElement, sourceFile, project, 3) : extractResponseType(method, sourceFile, project);
2502
3197
  const errorInfo = extractErrorType(method, sourceFile, project);
2503
- if (body === null && query === null && paramsType === null && response === "unknown" && errorInfo === null && filterInfo === null && !isStream && !uploads.multipart && !binaryResponse && !asQuery) {
3198
+ if (body === null && query === null && paramsType === null && paramTypes === null && response === "unknown" && errorInfo === null && filterInfo === null && !isStream && !uploads.multipart && !binaryResponse && !asQuery) {
2504
3199
  return null;
2505
3200
  }
2506
3201
  let bodyRef = null;
2507
3202
  let queryRef = null;
2508
3203
  let responseRef = null;
2509
3204
  for (const param of method.getParameters()) {
2510
- if (param.getDecorators().some((d) => d.getName() === "Body") && param.getTypeNode()) {
3205
+ if (param.getDecorators().some((d) => d.getName() === "Body") && param.getTypeNode() && !hasPipeSchema(param, "Body", project)) {
2511
3206
  bodyRef = resolveBodyQueryResponseRef(param.getTypeNode(), sourceFile, project);
2512
3207
  }
2513
- if (param.getDecorators().some((d) => d.getName() === "Query") && param.getTypeNode()) {
3208
+ if (param.getDecorators().some((d) => d.getName() === "Query") && param.getTypeNode() && !hasPipeSchema(param, "Query", project)) {
2514
3209
  queryRef = resolveBodyQueryResponseRef(param.getTypeNode(), sourceFile, project);
2515
3210
  }
2516
3211
  }
@@ -2523,11 +3218,11 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2523
3218
  if (apiResp) {
2524
3219
  const args = apiResp.getArguments();
2525
3220
  const optsArg = args[0];
2526
- if (optsArg && import_ts_morph7.Node.isObjectLiteralExpression(optsArg)) {
3221
+ if (optsArg && import_ts_morph11.Node.isObjectLiteralExpression(optsArg)) {
2527
3222
  for (const prop of optsArg.getProperties()) {
2528
- if (import_ts_morph7.Node.isPropertyAssignment(prop) && prop.getName() === "type") {
3223
+ if (import_ts_morph11.Node.isPropertyAssignment(prop) && prop.getName() === "type") {
2529
3224
  const val = prop.getInitializer();
2530
- if (val && import_ts_morph7.Node.isIdentifier(val)) {
3225
+ if (val && import_ts_morph11.Node.isIdentifier(val)) {
2531
3226
  const name = val.getText();
2532
3227
  const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
2533
3228
  if (localDecl?.isExported()) {
@@ -2563,6 +3258,7 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2563
3258
  response,
2564
3259
  error: errorInfo?.type ?? null,
2565
3260
  params: paramsType,
3261
+ paramTypes,
2566
3262
  queryRef,
2567
3263
  bodyRef,
2568
3264
  responseRef,
@@ -2583,6 +3279,7 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2583
3279
  function resolveParamClass(method, decoratorName, sourceFile, project) {
2584
3280
  for (const param of method.getParameters()) {
2585
3281
  if (!param.getDecorators().some((d) => d.getName() === decoratorName)) continue;
3282
+ if (hasPipeSchema(param, decoratorName, project)) continue;
2586
3283
  const typeNode = param.getTypeNode();
2587
3284
  if (!typeNode) continue;
2588
3285
  const text = typeNode.getText().replace(/\[\]$/, "");
@@ -2595,129 +3292,6 @@ function resolveParamClass(method, decoratorName, sourceFile, project) {
2595
3292
  return null;
2596
3293
  }
2597
3294
 
2598
- // src/discovery/zod-ast-to-ts.ts
2599
- var import_ts_morph8 = require("ts-morph");
2600
- function zodAstToTs(node) {
2601
- if (!import_ts_morph8.Node.isCallExpression(node)) return "unknown";
2602
- const expr = node.getExpression();
2603
- if (import_ts_morph8.Node.isPropertyAccessExpression(expr)) {
2604
- const methodName = expr.getName();
2605
- const receiver = expr.getExpression();
2606
- if (methodName === "optional") {
2607
- return `${zodAstToTs(receiver)} | undefined`;
2608
- }
2609
- if (methodName === "nullable") {
2610
- return `${zodAstToTs(receiver)} | null`;
2611
- }
2612
- const args = node.getArguments();
2613
- switch (methodName) {
2614
- case "string":
2615
- return "string";
2616
- case "number":
2617
- return "number";
2618
- case "boolean":
2619
- return "boolean";
2620
- case "unknown":
2621
- return "unknown";
2622
- case "any":
2623
- return "unknown";
2624
- case "literal": {
2625
- const lit = args[0];
2626
- if (!lit) return "unknown";
2627
- if (import_ts_morph8.Node.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());
2628
- if (import_ts_morph8.Node.isNumericLiteral(lit)) return lit.getLiteralValue().toString();
2629
- if (lit.getKind() === import_ts_morph8.SyntaxKind.TrueKeyword) return "true";
2630
- if (lit.getKind() === import_ts_morph8.SyntaxKind.FalseKeyword) return "false";
2631
- return "unknown";
2632
- }
2633
- case "enum": {
2634
- const arrArg = args[0];
2635
- if (!arrArg || !import_ts_morph8.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2636
- const members = arrArg.getElements().map(
2637
- (el) => import_ts_morph8.Node.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : "unknown"
2638
- );
2639
- return members.join(" | ");
2640
- }
2641
- case "array": {
2642
- const inner = args[0];
2643
- if (!inner) return "unknown";
2644
- return `Array<${zodAstToTs(inner)}>`;
2645
- }
2646
- case "object": {
2647
- const objArg = args[0];
2648
- if (!objArg || !import_ts_morph8.Node.isObjectLiteralExpression(objArg)) return "unknown";
2649
- const lines = [];
2650
- for (const prop of objArg.getProperties()) {
2651
- if (!import_ts_morph8.Node.isPropertyAssignment(prop)) continue;
2652
- const key = prop.getName();
2653
- const valNode = prop.getInitializer();
2654
- if (!valNode) continue;
2655
- const tsType = zodAstToTs(valNode);
2656
- const isOpt = isOptionalChain(valNode);
2657
- lines.push(`${key}${isOpt ? "?" : ""}: ${tsType}`);
2658
- }
2659
- return `{ ${lines.join("; ")} }`;
2660
- }
2661
- case "union": {
2662
- const arrArg = args[0];
2663
- if (!arrArg || !import_ts_morph8.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2664
- return arrArg.getElements().map(zodAstToTs).join(" | ");
2665
- }
2666
- case "record": {
2667
- const valArg = args.length === 1 ? args[0] : args[1];
2668
- if (!valArg) return "unknown";
2669
- return `Record<string, ${zodAstToTs(valArg)}>`;
2670
- }
2671
- case "tuple": {
2672
- const arrArg = args[0];
2673
- if (!arrArg || !import_ts_morph8.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2674
- return `[${arrArg.getElements().map(zodAstToTs).join(", ")}]`;
2675
- }
2676
- default:
2677
- return "unknown";
2678
- }
2679
- }
2680
- return "unknown";
2681
- }
2682
- function isOptionalChain(node) {
2683
- if (!import_ts_morph8.Node.isCallExpression(node)) return false;
2684
- const expr = node.getExpression();
2685
- return import_ts_morph8.Node.isPropertyAccessExpression(expr) && expr.getName() === "optional";
2686
- }
2687
- function parseDefineContractCall(callExpr) {
2688
- if (!import_ts_morph8.Node.isCallExpression(callExpr)) return null;
2689
- const callee = callExpr.getExpression();
2690
- const calleeName = import_ts_morph8.Node.isIdentifier(callee) ? callee.getText() : import_ts_morph8.Node.isPropertyAccessExpression(callee) ? callee.getName() : "";
2691
- if (calleeName !== "defineContract") return null;
2692
- const args = callExpr.getArguments();
2693
- const optsArg = args[0];
2694
- if (!optsArg || !import_ts_morph8.Node.isObjectLiteralExpression(optsArg)) return null;
2695
- let query = null;
2696
- let body = null;
2697
- let response = "unknown";
2698
- let error = null;
2699
- let bodyZodText = null;
2700
- let queryZodText = null;
2701
- for (const prop of optsArg.getProperties()) {
2702
- if (!import_ts_morph8.Node.isPropertyAssignment(prop)) continue;
2703
- const propName = prop.getName();
2704
- const val = prop.getInitializer();
2705
- if (!val) continue;
2706
- if (propName === "query") {
2707
- query = zodAstToTs(val);
2708
- queryZodText = val.getText();
2709
- } else if (propName === "body") {
2710
- body = zodAstToTs(val);
2711
- bodyZodText = val.getText();
2712
- } else if (propName === "response") {
2713
- response = zodAstToTs(val);
2714
- } else if (propName === "error") {
2715
- error = zodAstToTs(val);
2716
- }
2717
- }
2718
- return { query, body, response, error, bodyZodText, queryZodText };
2719
- }
2720
-
2721
3295
  // src/discovery/contracts-fast.ts
2722
3296
  async function discoverContractsFast(opts) {
2723
3297
  const { cwd, glob, tsconfig } = opts;
@@ -2730,7 +3304,9 @@ async function discoverContractsFast(opts) {
2730
3304
  }
2731
3305
  bindDiscoveryContext(project, cwd, tsconfigPath, loaded);
2732
3306
  clearMixinTypeProject();
2733
- return extractAllRoutes(project);
3307
+ const routes = extractAllRoutes(project);
3308
+ clearSchemaTypeProject(project);
3309
+ return routes;
2734
3310
  }
2735
3311
  function resolveTsconfigPath(cwd, tsconfig) {
2736
3312
  return tsconfig ? (0, import_node_path5.resolve)(tsconfig) : (0, import_node_path5.join)(cwd, "tsconfig.json");
@@ -2742,25 +3318,25 @@ var NO_TSCONFIG_OPTIONS = {
2742
3318
  };
2743
3319
  function loadDiscoveryTsconfig(tsconfigPath) {
2744
3320
  if (!(0, import_node_fs.existsSync)(tsconfigPath)) return { options: null, files: [] };
2745
- const read = import_ts_morph9.ts.readConfigFile(tsconfigPath, (path) => import_ts_morph9.ts.sys.readFile(path));
3321
+ const read = import_ts_morph12.ts.readConfigFile(tsconfigPath, (path) => import_ts_morph12.ts.sys.readFile(path));
2746
3322
  if (read.error) {
2747
3323
  return {
2748
3324
  options: null,
2749
3325
  files: [tsconfigPath],
2750
- error: import_ts_morph9.ts.flattenDiagnosticMessageText(read.error.messageText, " ")
3326
+ error: import_ts_morph12.ts.flattenDiagnosticMessageText(read.error.messageText, " ")
2751
3327
  };
2752
3328
  }
2753
3329
  const host = {
2754
- useCaseSensitiveFileNames: import_ts_morph9.ts.sys.useCaseSensitiveFileNames,
3330
+ useCaseSensitiveFileNames: import_ts_morph12.ts.sys.useCaseSensitiveFileNames,
2755
3331
  // The one line that keeps a tsconfig from being a filesystem walk.
2756
3332
  readDirectory: () => [],
2757
- fileExists: (path) => import_ts_morph9.ts.sys.fileExists(path),
3333
+ fileExists: (path) => import_ts_morph12.ts.sys.fileExists(path),
2758
3334
  // `extends` is resolved through the host, so a consumer whose `paths` live
2759
3335
  // in a base tsconfig keeps working.
2760
- readFile: (path) => import_ts_morph9.ts.sys.readFile(path)
3336
+ readFile: (path) => import_ts_morph12.ts.sys.readFile(path)
2761
3337
  };
2762
- const sourceFile = import_ts_morph9.ts.readJsonConfigFile(tsconfigPath, (path) => import_ts_morph9.ts.sys.readFile(path));
2763
- const parsed = import_ts_morph9.ts.parseJsonSourceFileConfigFileContent(
3338
+ const sourceFile = import_ts_morph12.ts.readJsonConfigFile(tsconfigPath, (path) => import_ts_morph12.ts.sys.readFile(path));
3339
+ const parsed = import_ts_morph12.ts.parseJsonSourceFileConfigFileContent(
2764
3340
  sourceFile,
2765
3341
  host,
2766
3342
  (0, import_node_path5.dirname)(tsconfigPath),
@@ -2783,7 +3359,7 @@ function createDiscoveryProject(tsconfigPath, tsconfig = loadDiscoveryTsconfig(t
2783
3359
  `[nestjs-codegen/fast] Could not load ${tsconfigPath}: ${tsconfig.error} \u2014 continuing WITHOUT its compiler options, so path alias imports (e.g. '@/...') will not resolve and controllers extending an alias-imported factory will contribute NO routes to the generated client.`
2784
3360
  );
2785
3361
  }
2786
- return new import_ts_morph9.Project({
3362
+ return new import_ts_morph12.Project({
2787
3363
  compilerOptions: tsconfig.options ?? { ...NO_TSCONFIG_OPTIONS },
2788
3364
  skipAddingFilesFromTsConfig: true,
2789
3365
  skipLoadingLibFiles: true,
@@ -2895,15 +3471,16 @@ var PersistentDiscovery = class _PersistentDiscovery {
2895
3471
  clearTypeResolutionCaches(this.project);
2896
3472
  clearEnumCache(this.project);
2897
3473
  clearMixinTypeProject();
3474
+ clearSchemaTypeProject(this.project);
2898
3475
  return extractRoutesFrom(this.project, this.controllerPaths);
2899
3476
  }
2900
3477
  };
2901
3478
  function decoratorStringArg(decoratorExpr) {
2902
3479
  if (!decoratorExpr) return void 0;
2903
- if (import_ts_morph9.Node.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();
2904
- if (import_ts_morph9.Node.isArrayLiteralExpression(decoratorExpr)) {
3480
+ if (import_ts_morph12.Node.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();
3481
+ if (import_ts_morph12.Node.isArrayLiteralExpression(decoratorExpr)) {
2905
3482
  const first = decoratorExpr.getElements()[0];
2906
- if (first && import_ts_morph9.Node.isStringLiteral(first)) return first.getLiteralValue();
3483
+ if (first && import_ts_morph12.Node.isStringLiteral(first)) return first.getLiteralValue();
2907
3484
  }
2908
3485
  return void 0;
2909
3486
  }
@@ -3024,9 +3601,9 @@ function extractContractRoute(args) {
3024
3601
  let contractDef = null;
3025
3602
  let bodyZodRef = null;
3026
3603
  let queryZodRef = null;
3027
- if (import_ts_morph9.Node.isCallExpression(firstDecoratorArg)) {
3028
- contractDef = parseDefineContractCall(firstDecoratorArg);
3029
- } else if (import_ts_morph9.Node.isIdentifier(firstDecoratorArg)) {
3604
+ if (import_ts_morph12.Node.isCallExpression(firstDecoratorArg)) {
3605
+ contractDef = parseDefineContractCall(firstDecoratorArg, project);
3606
+ } else if (import_ts_morph12.Node.isIdentifier(firstDecoratorArg)) {
3030
3607
  const identName = firstDecoratorArg.getText();
3031
3608
  const resolvedVar = resolveImportedVariable(identName, sourceFile, project);
3032
3609
  if (!resolvedVar) {
@@ -3038,7 +3615,7 @@ function extractContractRoute(args) {
3038
3615
  const { decl: varDecl, file: declFile } = resolvedVar;
3039
3616
  const initializer = varDecl.getInitializer();
3040
3617
  if (!initializer) return null;
3041
- contractDef = parseDefineContractCall(initializer);
3618
+ contractDef = parseDefineContractCall(initializer, project);
3042
3619
  if (contractDef && varDecl.isExported()) {
3043
3620
  const filePath = declFile.getFilePath();
3044
3621
  if (contractDef.body !== null) {
@@ -3109,6 +3686,7 @@ function extractDtoRoute(args) {
3109
3686
  body: dtoContract?.body ?? null,
3110
3687
  response: mixinResponse ?? dtoContract?.response ?? "unknown",
3111
3688
  error: dtoContract?.error ?? null,
3689
+ paramTypes: dtoContract?.paramTypes ?? null,
3112
3690
  queryRef: dtoContract?.queryRef ?? null,
3113
3691
  bodyRef: dtoContract?.bodyRef ?? null,
3114
3692
  responseRef: dtoContract?.responseRef ?? null,
@@ -3231,7 +3809,7 @@ function createExtensionContext(config, getRoutes, trackedInputs) {
3231
3809
  },
3232
3810
  project() {
3233
3811
  if (!project) {
3234
- project = new import_ts_morph10.Project({
3812
+ project = new import_ts_morph13.Project({
3235
3813
  skipAddingFilesFromTsConfig: true,
3236
3814
  skipLoadingLibFiles: true,
3237
3815
  skipFileDependencyResolution: true,
@@ -3349,10 +3927,11 @@ function insertIntoTree(tree, segments, leaf, fullName) {
3349
3927
  insertIntoTree(branch.children, rest, leaf, fullName);
3350
3928
  }
3351
3929
  }
3352
- function buildParamsType(params) {
3930
+ function buildParamsType(params, paramTypes) {
3353
3931
  const pathParams = params.filter((p) => p.source === "path");
3354
3932
  if (pathParams.length === 0) return "never";
3355
- return `{ ${pathParams.map((p) => `${p.name}: string`).join("; ")} }`;
3933
+ const typeOf = (name) => paramTypes && Object.hasOwn(paramTypes, name) && paramTypes[name] || "string";
3934
+ return `{ ${pathParams.map((p) => `${p.name}: ${typeOf(p.name)}`).join("; ")} }`;
3356
3935
  }
3357
3936
  function hasPathParams(params) {
3358
3937
  return params.some((p) => p.source === "path");
@@ -3446,7 +4025,7 @@ function emitRouterTypeBlock(tree, indent, outDir, serialization) {
3446
4025
  }
3447
4026
  const response = buildResponseType(c, outDir, serialization);
3448
4027
  const error = buildErrorType(c);
3449
- const params = buildParamsType(c.params);
4028
+ const params = buildParamsType(c.params, c.contractSource.paramTypes);
3450
4029
  const safeMethod = JSON.stringify(method);
3451
4030
  const safeUrl = JSON.stringify(c.path);
3452
4031
  const filterLiterals = filterFieldLiterals(c.contractSource.filterFields);
@@ -3715,6 +4294,9 @@ var EMPTY_PATH_NAMESPACE = [
3715
4294
  "}",
3716
4295
  ""
3717
4296
  ];
4297
+ function isClientCallable(route) {
4298
+ return route.method.toUpperCase() !== "ALL";
4299
+ }
3718
4300
  function buildApiFile(routes, outDir, opts = {}) {
3719
4301
  const fetcherImportPath = opts.fetcherImportPath;
3720
4302
  const serialization = opts.serialization ?? "json";
@@ -3722,7 +4304,7 @@ function buildApiFile(routes, outDir, opts = {}) {
3722
4304
  const { layer } = resolveApiSlots(extensions);
3723
4305
  const memberExts = extensions.filter((e) => e.apiMembers);
3724
4306
  const headerExts = extensions.filter((e) => e.apiHeader);
3725
- const contracted = routes.filter((r) => r.contract);
4307
+ const contracted = routes.filter((r) => r.contract && isClientCallable(r));
3726
4308
  const ctx = opts.ctx ?? {
3727
4309
  cwd: outDir ?? "",
3728
4310
  outDir: outDir ?? "",
@@ -4640,6 +5222,7 @@ function buildOpenApiSpec(routes, opts = {}) {
4640
5222
  const paths = {};
4641
5223
  for (const route of routes) {
4642
5224
  if (!route.contract) continue;
5225
+ if (route.method.toUpperCase() === "ALL") continue;
4643
5226
  const oaPath = toOpenApiPath(route.path);
4644
5227
  const method = route.method.toLowerCase();
4645
5228
  let pathItem = paths[oaPath];
@@ -5299,7 +5882,7 @@ async function watch(config, onChange, options = {}) {
5299
5882
  }
5300
5883
 
5301
5884
  // src/index.ts
5302
- var VERSION = "0.25.2";
5885
+ var VERSION = "0.26.0";
5303
5886
 
5304
5887
  // src/cli/codegen.ts
5305
5888
  async function runCodegen(opts = {}) {