@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/index.cjs CHANGED
@@ -584,16 +584,16 @@ var import_node_path7 = require("path");
584
584
 
585
585
  // src/extension/registry.ts
586
586
  var import_node_path6 = require("path");
587
- var import_ts_morph10 = require("ts-morph");
587
+ var import_ts_morph13 = require("ts-morph");
588
588
 
589
589
  // src/discovery/contracts-fast.ts
590
590
  var import_node_fs = require("fs");
591
591
  var import_node_path5 = require("path");
592
592
  var import_fast_glob2 = __toESM(require("fast-glob"), 1);
593
- var import_ts_morph9 = require("ts-morph");
593
+ var import_ts_morph12 = require("ts-morph");
594
594
 
595
595
  // src/discovery/dto-type-resolver.ts
596
- var import_ts_morph7 = require("ts-morph");
596
+ var import_ts_morph11 = require("ts-morph");
597
597
 
598
598
  // src/discovery/dto-to-ir.ts
599
599
  var import_ts_morph3 = require("ts-morph");
@@ -2121,6 +2121,672 @@ function extractFilterableEntityFields(filterClass, project, entityOverride, pre
2121
2121
  return fields;
2122
2122
  }
2123
2123
 
2124
+ // src/discovery/pipe-schema.ts
2125
+ var import_ts_morph10 = require("ts-morph");
2126
+
2127
+ // src/discovery/schema-type-inference.ts
2128
+ var import_ts_morph8 = require("ts-morph");
2129
+
2130
+ // src/discovery/schema-type-program.ts
2131
+ var import_ts_morph7 = require("ts-morph");
2132
+ var PARAM_DECORATORS = /* @__PURE__ */ new Set(["Body", "Query", "Param"]);
2133
+ var SchemaTypeProgram = class {
2134
+ constructor(discovery) {
2135
+ this.discovery = discovery;
2136
+ const base = discovery.getCompilerOptions();
2137
+ this.options = {
2138
+ ...base,
2139
+ // A tsconfig-less consumer gets ES5 by default, whose lib has no `Map`/`Set`/
2140
+ // `Promise` for the schema libraries' declarations to lean on.
2141
+ target: base.target ?? import_ts_morph7.ts.ScriptTarget.ES2022,
2142
+ // With neither set, resolve the way a bundler does: package `exports`
2143
+ // (`zod/v4`) and extensionless or `.js` relative imports all resolve.
2144
+ ...base.module === void 0 && base.moduleResolution === void 0 ? { module: import_ts_morph7.ts.ModuleKind.ESNext, moduleResolution: import_ts_morph7.ts.ModuleResolutionKind.Bundler } : {},
2145
+ // Without it `.nullable()` and `.optional()` would erase to the bare type.
2146
+ strictNullChecks: true,
2147
+ // No ambient `@types/*` (a tsconfig's `types: ['node']`): a schema does not
2148
+ // need them, and they are a hundred-odd files of program to build.
2149
+ types: [],
2150
+ noEmit: true
2151
+ };
2152
+ this.project = new import_ts_morph7.Project({
2153
+ skipAddingFilesFromTsConfig: true,
2154
+ compilerOptions: this.options
2155
+ });
2156
+ for (const sf of discovery.getSourceFiles()) this.request(sf.getFilePath(), { schema: true });
2157
+ this.flush();
2158
+ }
2159
+ project;
2160
+ options;
2161
+ /** Parses a file that is not in discovery's Project, without adding it there. */
2162
+ scratch = new import_ts_morph7.Project({
2163
+ skipAddingFilesFromTsConfig: true,
2164
+ skipLoadingLibFiles: true,
2165
+ skipFileDependencyResolution: true
2166
+ });
2167
+ needs = /* @__PURE__ */ new Map();
2168
+ /** Pruned text per file, as last written into {@link project}. */
2169
+ written = /* @__PURE__ */ new Map();
2170
+ /**
2171
+ * The typed copy of a discovery file, with its schema positions kept. Adding one
2172
+ * that was not there yet (a contract file discovery reached lazily) rebuilds the
2173
+ * program once.
2174
+ */
2175
+ sourceFileFor(sf) {
2176
+ this.request(sf.getFilePath(), { schema: true });
2177
+ this.flush();
2178
+ return this.project.getSourceFile(sf.getFilePath());
2179
+ }
2180
+ // -------------------------------------------------------------------------
2181
+ queue = [];
2182
+ request(path, want) {
2183
+ let needs = this.needs.get(path);
2184
+ const isNew = !needs;
2185
+ needs ??= { schema: false, all: false, names: /* @__PURE__ */ new Set() };
2186
+ let grew = isNew;
2187
+ if (want.schema && !needs.schema) {
2188
+ needs.schema = true;
2189
+ grew = true;
2190
+ }
2191
+ if (want.all && !needs.all) {
2192
+ needs.all = true;
2193
+ grew = true;
2194
+ }
2195
+ for (const name of want.names ?? []) {
2196
+ if (!needs.names.has(name)) {
2197
+ needs.names.add(name);
2198
+ grew = true;
2199
+ }
2200
+ }
2201
+ this.needs.set(path, needs);
2202
+ if (grew) this.queue.push(path);
2203
+ }
2204
+ /** Run the worklist to a fixpoint, then write every changed file into the program. */
2205
+ flush() {
2206
+ const changed = /* @__PURE__ */ new Map();
2207
+ while (this.queue.length > 0) {
2208
+ const path = this.queue.pop();
2209
+ const original = this.original(path);
2210
+ if (!original) continue;
2211
+ const needs = this.needs.get(path);
2212
+ const text = this.prune(original, needs);
2213
+ if (this.written.get(path) !== text) changed.set(path, text);
2214
+ }
2215
+ for (const [path, text] of changed) {
2216
+ this.project.createSourceFile(path, text, { overwrite: true });
2217
+ this.written.set(path, text);
2218
+ }
2219
+ }
2220
+ /** The file as discovery sees it (its in-memory text), else as it is on disk. */
2221
+ original(path) {
2222
+ return this.discovery.getSourceFile(path) ?? this.scratch.getSourceFile(path) ?? this.scratch.addSourceFileAtPathIfExists(path);
2223
+ }
2224
+ /**
2225
+ * `sf`'s text with every import/re-export nothing in `needs` references blanked,
2226
+ * requesting from each kept one's target the names it brings in.
2227
+ */
2228
+ prune(sf, needs) {
2229
+ const locals = topLevelDeclarations(sf);
2230
+ const roots = [];
2231
+ if (needs.all) roots.push(...sf.getStatements());
2232
+ if (needs.schema) roots.push(...schemaPositions(sf));
2233
+ const reexported = /* @__PURE__ */ new Map();
2234
+ for (const exp of sf.getExportDeclarations()) {
2235
+ const spec = exp.getModuleSpecifierValue();
2236
+ if (spec === void 0) {
2237
+ for (const named of exp.getNamedExports()) {
2238
+ const exposed = (named.getAliasNode() ?? named.getNameNode()).getText();
2239
+ if (needs.all || needs.names.has(exposed)) roots.push(named.getNameNode());
2240
+ }
2241
+ continue;
2242
+ }
2243
+ if (exp.isNamespaceExport() || exp.getNamedExports().length === 0) continue;
2244
+ for (const named of exp.getNamedExports()) {
2245
+ const exposed = (named.getAliasNode() ?? named.getNameNode()).getText();
2246
+ const list = reexported.get(exposed) ?? [];
2247
+ list.push({ from: spec, name: named.getNameNode().getText() });
2248
+ reexported.set(exposed, list);
2249
+ }
2250
+ }
2251
+ const unresolvedNames = [];
2252
+ for (const name of needs.names) {
2253
+ const decls = name === "default" ? defaultExport(sf) : locals.get(name) ?? [];
2254
+ if (decls.length > 0) roots.push(...decls);
2255
+ else if (!reexported.has(name)) unresolvedNames.push(name);
2256
+ }
2257
+ const referenced = /* @__PURE__ */ new Set();
2258
+ const queue = [...roots];
2259
+ const seen = new Set(queue);
2260
+ while (queue.length > 0) {
2261
+ const node = queue.pop();
2262
+ const ids = import_ts_morph7.Node.isIdentifier(node) ? [node] : node.getDescendantsOfKind(import_ts_morph7.ts.SyntaxKind.Identifier);
2263
+ for (const id of ids) {
2264
+ const name = id.getText();
2265
+ if (referenced.has(name)) continue;
2266
+ referenced.add(name);
2267
+ for (const local of locals.get(name) ?? []) {
2268
+ if (seen.has(local)) continue;
2269
+ seen.add(local);
2270
+ queue.push(local);
2271
+ }
2272
+ }
2273
+ }
2274
+ const chars = sf.getFullText().split("");
2275
+ const blank = (node) => {
2276
+ for (let i = node.getStart(); i < node.getEnd(); i++) {
2277
+ if (chars[i] !== "\n" && chars[i] !== "\r") chars[i] = " ";
2278
+ }
2279
+ };
2280
+ for (const decl of sf.getImportDeclarations()) {
2281
+ const target = this.resolve(decl.getModuleSpecifierValue(), sf);
2282
+ const namespace = decl.getNamespaceImport()?.getText();
2283
+ const def = decl.getDefaultImport()?.getText();
2284
+ const named = decl.getNamedImports().map((n) => ({
2285
+ local: (n.getAliasNode() ?? n.getNameNode()).getText(),
2286
+ imported: n.getName()
2287
+ })).filter((n) => referenced.has(n.local));
2288
+ const wantsNamespace = namespace !== void 0 && referenced.has(namespace);
2289
+ const wantsDefault = def !== void 0 && referenced.has(def);
2290
+ if (!wantsNamespace && !wantsDefault && named.length === 0) {
2291
+ blank(decl);
2292
+ continue;
2293
+ }
2294
+ if (target) {
2295
+ this.request(target, {
2296
+ all: wantsNamespace,
2297
+ names: [...wantsDefault ? ["default"] : [], ...named.map((n) => n.imported)]
2298
+ });
2299
+ }
2300
+ }
2301
+ for (const exp of sf.getExportDeclarations()) {
2302
+ const spec = exp.getModuleSpecifierValue();
2303
+ if (spec === void 0) continue;
2304
+ const target = this.resolve(spec, sf);
2305
+ if (exp.isNamespaceExport() || exp.getNamedExports().length === 0) {
2306
+ if (!needs.all && unresolvedNames.length === 0) {
2307
+ blank(exp);
2308
+ } else if (target) {
2309
+ this.request(target, { all: needs.all, names: unresolvedNames });
2310
+ }
2311
+ continue;
2312
+ }
2313
+ const wanted = exp.getNamedExports().filter(
2314
+ (n) => needs.all || needs.names.has((n.getAliasNode() ?? n.getNameNode()).getText())
2315
+ ).map((n) => n.getNameNode().getText());
2316
+ if (wanted.length === 0) blank(exp);
2317
+ else if (target) this.request(target, { names: wanted });
2318
+ }
2319
+ return chars.join("");
2320
+ }
2321
+ /**
2322
+ * The project source file a module specifier resolves to, or undefined for a
2323
+ * package (read unpruned by the program itself) or an unresolvable one.
2324
+ */
2325
+ resolve(specifier, from) {
2326
+ const resolved = import_ts_morph7.ts.resolveModuleName(
2327
+ specifier,
2328
+ from.getFilePath(),
2329
+ this.options,
2330
+ import_ts_morph7.ts.sys
2331
+ ).resolvedModule;
2332
+ if (!resolved || resolved.isExternalLibraryImport) return void 0;
2333
+ const file = resolved.resolvedFileName;
2334
+ if (file.endsWith(".d.ts") || !/\.(m|c)?tsx?$/.test(file)) return void 0;
2335
+ return file;
2336
+ }
2337
+ };
2338
+ function schemaPositions(sf) {
2339
+ const roots = [];
2340
+ sf.forEachDescendant((node) => {
2341
+ if (import_ts_morph7.Node.isDecorator(node)) {
2342
+ const name = node.getName();
2343
+ if (name === "ApplyContract") {
2344
+ roots.push(...node.getArguments());
2345
+ } else if (PARAM_DECORATORS.has(name)) {
2346
+ for (const arg of node.getArguments()) {
2347
+ if (import_ts_morph7.Node.isNewExpression(arg) || import_ts_morph7.Node.isCallExpression(arg)) {
2348
+ roots.push(...arg.getArguments());
2349
+ }
2350
+ }
2351
+ }
2352
+ } else if (import_ts_morph7.Node.isCallExpression(node)) {
2353
+ const callee = node.getExpression();
2354
+ const name = import_ts_morph7.Node.isIdentifier(callee) ? callee.getText() : import_ts_morph7.Node.isPropertyAccessExpression(callee) ? callee.getName() : void 0;
2355
+ if (name === "defineContract") roots.push(...node.getArguments());
2356
+ }
2357
+ });
2358
+ return roots;
2359
+ }
2360
+ function topLevelDeclarations(sf) {
2361
+ const byName = /* @__PURE__ */ new Map();
2362
+ const add = (name, node) => {
2363
+ if (!name) return;
2364
+ const list = byName.get(name);
2365
+ if (list) list.push(node);
2366
+ else byName.set(name, [node]);
2367
+ };
2368
+ for (const decl of sf.getVariableDeclarations()) add(decl.getName(), decl);
2369
+ for (const decl of sf.getFunctions()) add(decl.getName(), decl);
2370
+ for (const decl of sf.getClasses()) add(decl.getName(), decl);
2371
+ for (const decl of sf.getEnums()) add(decl.getName(), decl);
2372
+ for (const decl of sf.getInterfaces()) add(decl.getName(), decl);
2373
+ for (const decl of sf.getTypeAliases()) add(decl.getName(), decl);
2374
+ for (const decl of sf.getModules()) add(decl.getName(), decl);
2375
+ return byName;
2376
+ }
2377
+ function defaultExport(sf) {
2378
+ const nodes = [];
2379
+ for (const assignment of sf.getExportAssignments()) nodes.push(assignment);
2380
+ for (const fn of sf.getFunctions()) if (fn.isDefaultExport()) nodes.push(fn);
2381
+ for (const cls of sf.getClasses()) if (cls.isDefaultExport()) nodes.push(cls);
2382
+ return nodes;
2383
+ }
2384
+
2385
+ // src/discovery/schema-type-inference.ts
2386
+ var programs = /* @__PURE__ */ new WeakMap();
2387
+ function programFor(discovery) {
2388
+ let program = programs.get(discovery);
2389
+ if (!program) {
2390
+ program = new SchemaTypeProgram(discovery);
2391
+ programs.set(discovery, program);
2392
+ }
2393
+ return program;
2394
+ }
2395
+ function clearSchemaTypeProject(discovery) {
2396
+ programs.delete(discovery);
2397
+ }
2398
+ function counterpart(typedSf, node) {
2399
+ const start = node.getStart();
2400
+ const end = node.getEnd();
2401
+ const kind = node.getKind();
2402
+ let candidate = typedSf.getDescendantAtPos(start);
2403
+ while (candidate) {
2404
+ if (candidate.getStart() === start && candidate.getEnd() === end && candidate.getKind() === kind) {
2405
+ return candidate;
2406
+ }
2407
+ if (candidate.getStart() < start || candidate.getEnd() > end) return void 0;
2408
+ candidate = candidate.getParent();
2409
+ }
2410
+ return void 0;
2411
+ }
2412
+ function propType(type, name, at) {
2413
+ return type.getProperty(name)?.getTypeAtLocation(at);
2414
+ }
2415
+ function isAnyOrUnknown(type) {
2416
+ return type.isAny() || type.isUnknown();
2417
+ }
2418
+ function inferSchema(expr, discovery) {
2419
+ try {
2420
+ const typedSf = programFor(discovery).sourceFileFor(expr.getSourceFile());
2421
+ const at = typedSf && counterpart(typedSf, expr);
2422
+ if (!at) return { kind: "unresolved" };
2423
+ const schemaType = at.getType();
2424
+ if (isAnyOrUnknown(schemaType)) return { kind: "unresolved" };
2425
+ const standard = propType(schemaType, "~standard", at);
2426
+ const stdTypes = standard ? propType(standard, "types", at)?.getNonNullableType() : void 0;
2427
+ const stdInput = stdTypes ? propType(stdTypes, "input", at) : void 0;
2428
+ const stdOutput = stdTypes ? propType(stdTypes, "output", at) : void 0;
2429
+ if (stdInput && stdOutput) {
2430
+ return { kind: "schema", types: { input: stdInput, output: stdOutput, at } };
2431
+ }
2432
+ const zodInput = propType(schemaType, "_input", at);
2433
+ const zodOutput = propType(schemaType, "_output", at);
2434
+ if (zodInput && zodOutput) {
2435
+ return { kind: "schema", types: { input: zodInput, output: zodOutput, at } };
2436
+ }
2437
+ return { kind: "not-schema" };
2438
+ } catch (err) {
2439
+ dbg("schema inference failed:", err);
2440
+ return { kind: "unresolved" };
2441
+ }
2442
+ }
2443
+ var GLOBAL_NAMED_TYPES = /* @__PURE__ */ new Set([
2444
+ "Date",
2445
+ "File",
2446
+ "Blob",
2447
+ "FormData",
2448
+ "URL",
2449
+ "RegExp",
2450
+ "Map",
2451
+ "Set",
2452
+ "ArrayBuffer",
2453
+ "Uint8Array"
2454
+ ]);
2455
+ var MAX_DEPTH = 12;
2456
+ function objectKey(name) {
2457
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
2458
+ }
2459
+ function isOptionalSymbol(sym) {
2460
+ return (sym.getFlags() & import_ts_morph8.ts.SymbolFlags.Optional) !== 0;
2461
+ }
2462
+ function isSymbolKeyed(sym) {
2463
+ return sym.getName().startsWith("__@");
2464
+ }
2465
+ function orderedProperties(type) {
2466
+ const position = (sym) => {
2467
+ const decl = sym.getDeclarations()[0];
2468
+ return decl ? [decl.getSourceFile().getFilePath(), decl.getStart()] : void 0;
2469
+ };
2470
+ return type.getProperties().map((sym, index) => ({ sym, index, at: position(sym) })).sort((a, b) => {
2471
+ if (a.at && b.at) {
2472
+ if (a.at[0] !== b.at[0]) return a.at[0] < b.at[0] ? -1 : 1;
2473
+ if (a.at[1] !== b.at[1]) return a.at[1] - b.at[1];
2474
+ } else if (a.at || b.at) {
2475
+ return a.at ? -1 : 1;
2476
+ }
2477
+ return a.index - b.index;
2478
+ }).map((entry) => entry.sym);
2479
+ }
2480
+ function isFromDeclarationFile(sym) {
2481
+ const decl = sym?.getDeclarations()[0];
2482
+ return !!decl && decl.getSourceFile().isDeclarationFile();
2483
+ }
2484
+ function render(type, state, paired) {
2485
+ if (state.depth > MAX_DEPTH) return "unknown";
2486
+ if (isAnyOrUnknown(type)) {
2487
+ return paired && !isAnyOrUnknown(paired) ? render(paired, state) : "unknown";
2488
+ }
2489
+ if (type.isNever()) return "never";
2490
+ if (type.isString() || type.isTemplateLiteral()) return "string";
2491
+ if (type.isNumber()) return "number";
2492
+ if (type.isBoolean()) return "boolean";
2493
+ if (type.isBigInt()) return "bigint";
2494
+ if (type.isNull()) return "null";
2495
+ if (type.isUndefined() || type.isVoid()) return "undefined";
2496
+ if (type.isBooleanLiteral()) return type.getText();
2497
+ if (type.isStringLiteral() || type.isNumberLiteral() || type.isEnumLiteral()) {
2498
+ const value = type.getLiteralValue();
2499
+ return typeof value === "string" ? JSON.stringify(value) : String(value);
2500
+ }
2501
+ if (type.isBigIntLiteral()) return type.getText();
2502
+ if (type.isTypeParameter()) return "unknown";
2503
+ if (type.isUnion()) return renderUnion(type, state, paired);
2504
+ if (type.isIntersection()) return renderIntersection(type, state);
2505
+ const next = { ...state, depth: state.depth + 1 };
2506
+ if (type.isArray() || type.isReadonlyArray()) {
2507
+ const element = type.getArrayElementType() ?? type.getTypeArguments()[0];
2508
+ const pairedElement = paired?.getArrayElementType() ?? paired?.getTypeArguments()[0];
2509
+ return element ? `Array<${render(element, next, pairedElement)}>` : "Array<unknown>";
2510
+ }
2511
+ if (type.isTuple()) {
2512
+ const elements = type.getTupleElements();
2513
+ const pairedElements = paired?.isTuple() ? paired.getTupleElements() : [];
2514
+ return `[${elements.map((e, i) => render(e, next, pairedElements[i])).join(", ")}]`;
2515
+ }
2516
+ if (type.isObject()) return renderObject(type, next, paired);
2517
+ return "unknown";
2518
+ }
2519
+ function renderUnion(type, state, paired) {
2520
+ const members = type.getUnionTypes();
2521
+ const hasTrue = members.some((m) => m.isBooleanLiteral() && m.getText() === "true");
2522
+ const hasFalse = members.some((m) => m.isBooleanLiteral() && m.getText() === "false");
2523
+ const pairedNonNull = paired?.getNonNullableType();
2524
+ const arms = [];
2525
+ let sawBoolean = false;
2526
+ let hasNull = false;
2527
+ let hasUndefined = false;
2528
+ for (const member of members) {
2529
+ if (member.isNull()) {
2530
+ hasNull = true;
2531
+ continue;
2532
+ }
2533
+ if (member.isUndefined()) {
2534
+ hasUndefined = true;
2535
+ continue;
2536
+ }
2537
+ if (member.isBooleanLiteral() && hasTrue && hasFalse) {
2538
+ if (!sawBoolean) arms.push("boolean");
2539
+ sawBoolean = true;
2540
+ continue;
2541
+ }
2542
+ arms.push(render(member, state, members.length === 1 ? paired : pairedNonNull));
2543
+ }
2544
+ if (hasNull) arms.push("null");
2545
+ if (hasUndefined) arms.push("undefined");
2546
+ const unique = [...new Set(arms)];
2547
+ if (unique.includes("unknown")) return "unknown";
2548
+ return unique.join(" | ");
2549
+ }
2550
+ function renderIntersection(type, state) {
2551
+ const members = type.getIntersectionTypes();
2552
+ const primitive = members.find((m) => !m.isObject());
2553
+ if (primitive) return render(primitive, state);
2554
+ return renderObject(type, { ...state, depth: state.depth + 1 }, void 0);
2555
+ }
2556
+ function renderObject(type, state, paired) {
2557
+ const symbol = type.getSymbol() ?? type.getAliasSymbol();
2558
+ const name = symbol?.getName();
2559
+ if (name && GLOBAL_NAMED_TYPES.has(name) && isFromDeclarationFile(symbol)) {
2560
+ const args = type.getTypeArguments();
2561
+ return args.length ? `${name}<${args.map((a) => render(a, state)).join(", ")}>` : name;
2562
+ }
2563
+ if (type.getCallSignatures().length > 0 || type.getConstructSignatures().length > 0) {
2564
+ return "unknown";
2565
+ }
2566
+ if (type.isClassOrInterface() && isFromDeclarationFile(symbol)) return "unknown";
2567
+ if (state.stack.has(type.compilerType)) return "unknown";
2568
+ const stack = new Set(state.stack).add(type.compilerType);
2569
+ const inner = { ...state, stack };
2570
+ const fields = [];
2571
+ for (const prop of orderedProperties(type)) {
2572
+ if (isSymbolKeyed(prop)) continue;
2573
+ const propName = prop.getName();
2574
+ const propT = prop.getTypeAtLocation(state.at);
2575
+ if (propT.getCallSignatures().length > 0 && !propT.isUnion()) continue;
2576
+ const pairedProp = paired?.getProperty(propName)?.getTypeAtLocation(state.at);
2577
+ const optional = isOptionalSymbol(prop) ? "?" : "";
2578
+ fields.push(`${objectKey(propName)}${optional}: ${render(propT, inner, pairedProp)}`);
2579
+ }
2580
+ const stringIndex = type.getStringIndexType();
2581
+ if (stringIndex) {
2582
+ const pairedIndex = paired?.getStringIndexType();
2583
+ const value = render(stringIndex, inner, pairedIndex);
2584
+ if (fields.length === 0) return `Record<string, ${value}>`;
2585
+ fields.push(`[key: string]: ${value}`);
2586
+ }
2587
+ return fields.length ? `{ ${fields.join("; ")} }` : "{}";
2588
+ }
2589
+ function stateAt(at) {
2590
+ return { at, stack: /* @__PURE__ */ new Set(), depth: 0 };
2591
+ }
2592
+ function requestTypeOf(types) {
2593
+ return render(types.input, stateAt(types.at), types.output);
2594
+ }
2595
+ function responseTypeOf(types) {
2596
+ return render(types.output, stateAt(types.at));
2597
+ }
2598
+ function requestFieldsOf(types) {
2599
+ const { input, output, at } = types;
2600
+ const objectInput = input.getNonNullableType();
2601
+ if (!objectInput.isObject() || objectInput.isArray() || objectInput.isTuple()) return null;
2602
+ const state = stateAt(at);
2603
+ return orderedProperties(objectInput).filter((prop) => !isSymbolKeyed(prop)).map((prop) => ({
2604
+ name: prop.getName(),
2605
+ type: render(
2606
+ prop.getTypeAtLocation(at),
2607
+ state,
2608
+ output.getProperty(prop.getName())?.getTypeAtLocation(at)
2609
+ ),
2610
+ optional: isOptionalSymbol(prop)
2611
+ }));
2612
+ }
2613
+ function acceptsUndefined(types) {
2614
+ const { input, output } = types;
2615
+ const accepted = isAnyOrUnknown(input) ? output : input;
2616
+ if (isAnyOrUnknown(accepted) || accepted.isUndefined()) return true;
2617
+ return accepted.isUnion() && accepted.getUnionTypes().some((t) => t.isUndefined());
2618
+ }
2619
+
2620
+ // src/discovery/zod-ast-to-ts.ts
2621
+ var import_ts_morph9 = require("ts-morph");
2622
+ function zodAstToTs(node) {
2623
+ if (!import_ts_morph9.Node.isCallExpression(node)) return "unknown";
2624
+ const expr = node.getExpression();
2625
+ if (import_ts_morph9.Node.isPropertyAccessExpression(expr)) {
2626
+ const methodName = expr.getName();
2627
+ const receiver = expr.getExpression();
2628
+ if (methodName === "optional") {
2629
+ return `${zodAstToTs(receiver)} | undefined`;
2630
+ }
2631
+ if (methodName === "nullable") {
2632
+ return `${zodAstToTs(receiver)} | null`;
2633
+ }
2634
+ const args = node.getArguments();
2635
+ switch (methodName) {
2636
+ case "string":
2637
+ return "string";
2638
+ case "number":
2639
+ return "number";
2640
+ case "boolean":
2641
+ return "boolean";
2642
+ case "unknown":
2643
+ return "unknown";
2644
+ case "any":
2645
+ return "unknown";
2646
+ case "literal": {
2647
+ const lit = args[0];
2648
+ if (!lit) return "unknown";
2649
+ if (import_ts_morph9.Node.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());
2650
+ if (import_ts_morph9.Node.isNumericLiteral(lit)) return lit.getLiteralValue().toString();
2651
+ if (lit.getKind() === import_ts_morph9.SyntaxKind.TrueKeyword) return "true";
2652
+ if (lit.getKind() === import_ts_morph9.SyntaxKind.FalseKeyword) return "false";
2653
+ return "unknown";
2654
+ }
2655
+ case "enum": {
2656
+ const arrArg = args[0];
2657
+ if (!arrArg || !import_ts_morph9.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2658
+ const members = arrArg.getElements().map(
2659
+ (el) => import_ts_morph9.Node.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : "unknown"
2660
+ );
2661
+ return members.join(" | ");
2662
+ }
2663
+ case "array": {
2664
+ const inner = args[0];
2665
+ if (!inner) return "unknown";
2666
+ return `Array<${zodAstToTs(inner)}>`;
2667
+ }
2668
+ case "object": {
2669
+ const objArg = args[0];
2670
+ if (!objArg || !import_ts_morph9.Node.isObjectLiteralExpression(objArg)) return "unknown";
2671
+ const lines = [];
2672
+ for (const prop of objArg.getProperties()) {
2673
+ if (!import_ts_morph9.Node.isPropertyAssignment(prop)) continue;
2674
+ const key = prop.getName();
2675
+ const valNode = prop.getInitializer();
2676
+ if (!valNode) continue;
2677
+ const tsType = zodAstToTs(valNode);
2678
+ const isOpt = isOptionalChain(valNode);
2679
+ lines.push(`${key}${isOpt ? "?" : ""}: ${tsType}`);
2680
+ }
2681
+ return `{ ${lines.join("; ")} }`;
2682
+ }
2683
+ case "union": {
2684
+ const arrArg = args[0];
2685
+ if (!arrArg || !import_ts_morph9.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2686
+ return arrArg.getElements().map(zodAstToTs).join(" | ");
2687
+ }
2688
+ case "record": {
2689
+ const valArg = args.length === 1 ? args[0] : args[1];
2690
+ if (!valArg) return "unknown";
2691
+ return `Record<string, ${zodAstToTs(valArg)}>`;
2692
+ }
2693
+ case "tuple": {
2694
+ const arrArg = args[0];
2695
+ if (!arrArg || !import_ts_morph9.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2696
+ return `[${arrArg.getElements().map(zodAstToTs).join(", ")}]`;
2697
+ }
2698
+ default:
2699
+ return "unknown";
2700
+ }
2701
+ }
2702
+ return "unknown";
2703
+ }
2704
+ function isOptionalChain(node) {
2705
+ if (!import_ts_morph9.Node.isCallExpression(node)) return false;
2706
+ const expr = node.getExpression();
2707
+ return import_ts_morph9.Node.isPropertyAccessExpression(expr) && expr.getName() === "optional";
2708
+ }
2709
+ function memberType(val, position, project) {
2710
+ if (project) {
2711
+ const inferred = inferSchema(val, project);
2712
+ if (inferred.kind === "schema") {
2713
+ return position === "request" ? requestTypeOf(inferred.types) : responseTypeOf(inferred.types);
2714
+ }
2715
+ }
2716
+ return zodAstToTs(val);
2717
+ }
2718
+ function parseDefineContractCall(callExpr, project) {
2719
+ if (!import_ts_morph9.Node.isCallExpression(callExpr)) return null;
2720
+ const callee = callExpr.getExpression();
2721
+ const calleeName = import_ts_morph9.Node.isIdentifier(callee) ? callee.getText() : import_ts_morph9.Node.isPropertyAccessExpression(callee) ? callee.getName() : "";
2722
+ if (calleeName !== "defineContract") return null;
2723
+ const args = callExpr.getArguments();
2724
+ const optsArg = args[0];
2725
+ if (!optsArg || !import_ts_morph9.Node.isObjectLiteralExpression(optsArg)) return null;
2726
+ let query = null;
2727
+ let body = null;
2728
+ let response = "unknown";
2729
+ let error = null;
2730
+ let bodyZodText = null;
2731
+ let queryZodText = null;
2732
+ for (const prop of optsArg.getProperties()) {
2733
+ if (!import_ts_morph9.Node.isPropertyAssignment(prop)) continue;
2734
+ const propName = prop.getName();
2735
+ const val = prop.getInitializer();
2736
+ if (!val) continue;
2737
+ if (propName === "query") {
2738
+ query = memberType(val, "request", project);
2739
+ queryZodText = val.getText();
2740
+ } else if (propName === "body") {
2741
+ body = memberType(val, "request", project);
2742
+ bodyZodText = val.getText();
2743
+ } else if (propName === "response") {
2744
+ response = memberType(val, "response", project);
2745
+ } else if (propName === "error") {
2746
+ error = memberType(val, "response", project);
2747
+ }
2748
+ }
2749
+ return { query, body, response, error, bodyZodText, queryZodText };
2750
+ }
2751
+
2752
+ // src/discovery/pipe-schema.ts
2753
+ function pipeSchemaOf(decorator, project) {
2754
+ for (const pipe of decorator.getArguments()) {
2755
+ if (!import_ts_morph10.Node.isNewExpression(pipe) && !import_ts_morph10.Node.isCallExpression(pipe)) continue;
2756
+ for (const arg of pipe.getArguments()) {
2757
+ if (!couldBeSchema(arg)) continue;
2758
+ const inferred = inferSchema(arg, project);
2759
+ if (inferred.kind === "schema") {
2760
+ return {
2761
+ type: requestTypeOf(inferred.types),
2762
+ optional: acceptsUndefined(inferred.types),
2763
+ fields: requestFieldsOf(inferred.types)
2764
+ };
2765
+ }
2766
+ if (inferred.kind === "unresolved") {
2767
+ const fallback = syntacticZodType(arg, project);
2768
+ if (fallback) {
2769
+ return { type: fallback, optional: fallback.endsWith("| undefined"), fields: null };
2770
+ }
2771
+ }
2772
+ }
2773
+ }
2774
+ return null;
2775
+ }
2776
+ function couldBeSchema(arg) {
2777
+ 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);
2778
+ }
2779
+ function syntacticZodType(arg, project) {
2780
+ let expr = arg;
2781
+ if (import_ts_morph10.Node.isIdentifier(arg)) {
2782
+ const resolved = resolveImportedVariable(arg.getText(), arg.getSourceFile(), project);
2783
+ expr = resolved?.decl.getInitializer();
2784
+ }
2785
+ if (!expr || !import_ts_morph10.Node.isCallExpression(expr)) return null;
2786
+ const type = zodAstToTs(expr);
2787
+ return type === "unknown" ? null : type;
2788
+ }
2789
+
2124
2790
  // src/discovery/dto-type-resolver.ts
2125
2791
  var WRAPPER_TYPES = {
2126
2792
  // MikroORM Ref/Reference/LoadedReference/IdentifiedReference are server-side
@@ -2152,22 +2818,22 @@ var PASSTHROUGH_UTILITY = /* @__PURE__ */ new Set([
2152
2818
  ]);
2153
2819
  function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /* @__PURE__ */ new Map()) {
2154
2820
  if (depth <= 0) return "unknown";
2155
- if (import_ts_morph7.Node.isArrayTypeNode(typeNode)) {
2821
+ if (import_ts_morph11.Node.isArrayTypeNode(typeNode)) {
2156
2822
  const elementType = typeNode.getElementTypeNode();
2157
2823
  return `Array<${resolveTypeNodeToString(elementType, sourceFile, project, depth, subst)}>`;
2158
2824
  }
2159
- if (import_ts_morph7.Node.isUnionTypeNode(typeNode)) {
2825
+ if (import_ts_morph11.Node.isUnionTypeNode(typeNode)) {
2160
2826
  return typeNode.getTypeNodes().map((t) => resolveTypeNodeToString(t, sourceFile, project, depth, subst)).join(" | ");
2161
2827
  }
2162
- if (import_ts_morph7.Node.isIntersectionTypeNode(typeNode)) {
2828
+ if (import_ts_morph11.Node.isIntersectionTypeNode(typeNode)) {
2163
2829
  return typeNode.getTypeNodes().map((t) => resolveTypeNodeToString(t, sourceFile, project, depth, subst)).join(" & ");
2164
2830
  }
2165
- if (import_ts_morph7.Node.isParenthesizedTypeNode(typeNode)) {
2831
+ if (import_ts_morph11.Node.isParenthesizedTypeNode(typeNode)) {
2166
2832
  return `(${resolveTypeNodeToString(typeNode.getTypeNode(), sourceFile, project, depth, subst)})`;
2167
2833
  }
2168
- if (import_ts_morph7.Node.isTypeReference(typeNode)) {
2834
+ if (import_ts_morph11.Node.isTypeReference(typeNode)) {
2169
2835
  const typeName = typeNode.getTypeName();
2170
- const name = import_ts_morph7.Node.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();
2836
+ const name = import_ts_morph11.Node.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();
2171
2837
  const bound = subst.get(name);
2172
2838
  if (bound !== void 0) return bound;
2173
2839
  if (name === "string" || name === "number" || name === "boolean") return name;
@@ -2190,13 +2856,13 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /
2190
2856
  dbg("unresolvable type:", name, "in", sourceFile.getFilePath());
2191
2857
  return "unknown";
2192
2858
  }
2193
- if (import_ts_morph7.Node.isTypeLiteral(typeNode)) {
2859
+ if (import_ts_morph11.Node.isTypeLiteral(typeNode)) {
2194
2860
  const members = [];
2195
2861
  for (const member of typeNode.getMembers()) {
2196
- if (import_ts_morph7.Node.isPropertySignature(member)) {
2862
+ if (import_ts_morph11.Node.isPropertySignature(member)) {
2197
2863
  const memberTypeNode = member.getTypeNode();
2198
- const memberType = memberTypeNode ? resolveTypeNodeToString(memberTypeNode, sourceFile, project, depth, subst) : "unknown";
2199
- members.push(`${member.getName()}${member.hasQuestionToken() ? "?" : ""}: ${memberType}`);
2864
+ const memberType2 = memberTypeNode ? resolveTypeNodeToString(memberTypeNode, sourceFile, project, depth, subst) : "unknown";
2865
+ members.push(`${member.getName()}${member.hasQuestionToken() ? "?" : ""}: ${memberType2}`);
2200
2866
  } else {
2201
2867
  members.push(member.getText());
2202
2868
  }
@@ -2204,11 +2870,11 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /
2204
2870
  return members.length > 0 ? `{ ${members.join("; ")} }` : "{}";
2205
2871
  }
2206
2872
  const kind = typeNode.getKind();
2207
- if (kind === import_ts_morph7.SyntaxKind.StringKeyword) return "string";
2208
- if (kind === import_ts_morph7.SyntaxKind.NumberKeyword) return "number";
2209
- if (kind === import_ts_morph7.SyntaxKind.BooleanKeyword) return "boolean";
2210
- if (kind === import_ts_morph7.SyntaxKind.UnknownKeyword) return "unknown";
2211
- if (kind === import_ts_morph7.SyntaxKind.AnyKeyword) return "unknown";
2873
+ if (kind === import_ts_morph11.SyntaxKind.StringKeyword) return "string";
2874
+ if (kind === import_ts_morph11.SyntaxKind.NumberKeyword) return "number";
2875
+ if (kind === import_ts_morph11.SyntaxKind.BooleanKeyword) return "boolean";
2876
+ if (kind === import_ts_morph11.SyntaxKind.UnknownKeyword) return "unknown";
2877
+ if (kind === import_ts_morph11.SyntaxKind.AnyKeyword) return "unknown";
2212
2878
  return typeNode.getText();
2213
2879
  }
2214
2880
  function unwrapFirstTypeArg(typeNode, sourceFile, project, depth, mode, subst = /* @__PURE__ */ new Map()) {
@@ -2256,20 +2922,24 @@ function resolvePropertied(decl, sourceFile, project, depth, subst = /* @__PURE_
2256
2922
  const propName = prop.getName();
2257
2923
  const isOptional = prop.hasQuestionToken();
2258
2924
  const propTypeNode = prop.getTypeNode();
2259
- let propType = "unknown";
2925
+ let propType2 = "unknown";
2260
2926
  if (propTypeNode) {
2261
- propType = resolveTypeNodeToString(propTypeNode, sourceFile, project, depth, subst);
2927
+ propType2 = resolveTypeNodeToString(propTypeNode, sourceFile, project, depth, subst);
2262
2928
  }
2263
- lines.push(`${propName}${isOptional ? "?" : ""}: ${propType}`);
2929
+ lines.push(`${propName}${isOptional ? "?" : ""}: ${propType2}`);
2264
2930
  }
2265
2931
  return `{ ${lines.join("; ")} }`;
2266
2932
  }
2933
+ function namedField(decorator) {
2934
+ const first = decorator.getArguments()[0];
2935
+ return first && import_ts_morph11.Node.isStringLiteral(first) ? first.getLiteralValue() : null;
2936
+ }
2267
2937
  function extractBodyType(method, sourceFile, project) {
2268
2938
  for (const param of method.getParameters()) {
2269
2939
  const bodyDecorator = param.getDecorators().find((d) => d.getName() === "Body");
2270
- if (!bodyDecorator) continue;
2271
- const bodyArgs = bodyDecorator.getArguments();
2272
- if (bodyArgs.length > 0) continue;
2940
+ if (!bodyDecorator || namedField(bodyDecorator) !== null) continue;
2941
+ const piped = pipeSchemaOf(bodyDecorator, project);
2942
+ if (piped) return piped.type;
2273
2943
  const typeNode = param.getTypeNode();
2274
2944
  if (typeNode) {
2275
2945
  return resolveTypeNodeToString(typeNode, sourceFile, project, 3);
@@ -2277,11 +2947,16 @@ function extractBodyType(method, sourceFile, project) {
2277
2947
  }
2278
2948
  return null;
2279
2949
  }
2950
+ function hasPipeSchema(param, decoratorName, project) {
2951
+ const decorator = param.getDecorators().find((d) => d.getName() === decoratorName);
2952
+ return !!decorator && pipeSchemaOf(decorator, project) !== null;
2953
+ }
2280
2954
  function extractQueryType(method, sourceFile, project) {
2281
2955
  for (const param of method.getParameters()) {
2282
2956
  const queryDecorator = param.getDecorators().find((d) => d.getName() === "Query");
2283
- if (!queryDecorator) continue;
2284
- if (queryDecorator.getArguments().length > 0) continue;
2957
+ if (!queryDecorator || namedField(queryDecorator) !== null) continue;
2958
+ const piped = pipeSchemaOf(queryDecorator, project);
2959
+ if (piped) return piped.type;
2285
2960
  const typeNode = param.getTypeNode();
2286
2961
  if (typeNode) {
2287
2962
  return resolveTypeNodeToString(typeNode, sourceFile, project, 3);
@@ -2291,10 +2966,13 @@ function extractQueryType(method, sourceFile, project) {
2291
2966
  for (const param of method.getParameters()) {
2292
2967
  const queryDecorator = param.getDecorators().find((d) => d.getName() === "Query");
2293
2968
  if (!queryDecorator) continue;
2294
- const queryArgs = queryDecorator.getArguments();
2295
- const nameArg = queryArgs[0];
2296
- if (!nameArg || !import_ts_morph7.Node.isStringLiteral(nameArg)) continue;
2297
- const queryName = nameArg.getLiteralValue();
2969
+ const queryName = namedField(queryDecorator);
2970
+ if (queryName === null) continue;
2971
+ const piped = pipeSchemaOf(queryDecorator, project);
2972
+ if (piped) {
2973
+ entries.push(`${queryName}${piped.optional ? "?" : ""}: ${piped.type}`);
2974
+ continue;
2975
+ }
2298
2976
  const typeNode = param.getTypeNode();
2299
2977
  const queryType = typeNode ? resolveTypeNodeToString(typeNode, sourceFile, project, 3) : "string";
2300
2978
  entries.push(`${queryName}${isParamOptional(param) ? "?" : ""}: ${queryType}`);
@@ -2304,8 +2982,8 @@ function extractQueryType(method, sourceFile, project) {
2304
2982
  function isParamOptional(param) {
2305
2983
  if (param.hasQuestionToken() || param.hasInitializer()) return true;
2306
2984
  const typeNode = param.getTypeNode();
2307
- if (typeNode && import_ts_morph7.Node.isUnionTypeNode(typeNode)) {
2308
- return typeNode.getTypeNodes().some((t) => t.getKind() === import_ts_morph7.SyntaxKind.UndefinedKeyword);
2985
+ if (typeNode && import_ts_morph11.Node.isUnionTypeNode(typeNode)) {
2986
+ return typeNode.getTypeNodes().some((t) => t.getKind() === import_ts_morph11.SyntaxKind.UndefinedKeyword);
2309
2987
  }
2310
2988
  return false;
2311
2989
  }
@@ -2317,7 +2995,7 @@ function extractParamsType(method, sourceFile, project) {
2317
2995
  const paramArgs = paramDecorator.getArguments();
2318
2996
  if (paramArgs.length === 0) continue;
2319
2997
  const nameArg = paramArgs[0];
2320
- if (!import_ts_morph7.Node.isStringLiteral(nameArg)) continue;
2998
+ if (!import_ts_morph11.Node.isStringLiteral(nameArg)) continue;
2321
2999
  const paramName = nameArg.getLiteralValue();
2322
3000
  const typeNode = param.getTypeNode();
2323
3001
  const paramType = typeNode ? resolveTypeNodeToString(typeNode, sourceFile, project, 3) : "string";
@@ -2325,6 +3003,22 @@ function extractParamsType(method, sourceFile, project) {
2325
3003
  }
2326
3004
  return entries.length > 0 ? `{ ${entries.join("; ")} }` : null;
2327
3005
  }
3006
+ function extractPipedParamTypes(method, project) {
3007
+ const types = {};
3008
+ for (const param of method.getParameters()) {
3009
+ const paramDecorator = param.getDecorators().find((d) => d.getName() === "Param");
3010
+ if (!paramDecorator) continue;
3011
+ const piped = pipeSchemaOf(paramDecorator, project);
3012
+ if (!piped) continue;
3013
+ const name = namedField(paramDecorator);
3014
+ if (name !== null) {
3015
+ types[name] = piped.type;
3016
+ } else {
3017
+ for (const field of piped.fields ?? []) types[field.name] = field.type;
3018
+ }
3019
+ }
3020
+ return Object.keys(types).length > 0 ? types : null;
3021
+ }
2328
3022
  function extractUploadedFiles(method) {
2329
3023
  const FILE = "File | Blob";
2330
3024
  const entries = [];
@@ -2338,28 +3032,28 @@ function extractUploadedFiles(method) {
2338
3032
  for (const decorator of method.getDecorators()) {
2339
3033
  if (decorator.getName() !== "UseInterceptors") continue;
2340
3034
  for (const arg of decorator.getArguments()) {
2341
- if (!import_ts_morph7.Node.isCallExpression(arg)) continue;
3035
+ if (!import_ts_morph11.Node.isCallExpression(arg)) continue;
2342
3036
  const interceptor = arg.getExpression().getText();
2343
3037
  const callArgs = arg.getArguments();
2344
3038
  const firstArg2 = callArgs[0];
2345
3039
  if (interceptor === "FileInterceptor") {
2346
- if (firstArg2 && import_ts_morph7.Node.isStringLiteral(firstArg2)) {
3040
+ if (firstArg2 && import_ts_morph11.Node.isStringLiteral(firstArg2)) {
2347
3041
  entries.push(`${firstArg2.getLiteralValue()}: ${FILE}`);
2348
3042
  multipart = true;
2349
3043
  }
2350
3044
  } else if (interceptor === "FilesInterceptor") {
2351
- if (firstArg2 && import_ts_morph7.Node.isStringLiteral(firstArg2)) {
3045
+ if (firstArg2 && import_ts_morph11.Node.isStringLiteral(firstArg2)) {
2352
3046
  entries.push(`${firstArg2.getLiteralValue()}: Array<${FILE}>`);
2353
3047
  multipart = true;
2354
3048
  }
2355
3049
  } else if (interceptor === "FileFieldsInterceptor") {
2356
- if (firstArg2 && import_ts_morph7.Node.isArrayLiteralExpression(firstArg2)) {
3050
+ if (firstArg2 && import_ts_morph11.Node.isArrayLiteralExpression(firstArg2)) {
2357
3051
  for (const el of firstArg2.getElements()) {
2358
- if (!import_ts_morph7.Node.isObjectLiteralExpression(el)) continue;
3052
+ if (!import_ts_morph11.Node.isObjectLiteralExpression(el)) continue;
2359
3053
  const nameProp = el.getProperty("name");
2360
- if (nameProp && import_ts_morph7.Node.isPropertyAssignment(nameProp)) {
3054
+ if (nameProp && import_ts_morph11.Node.isPropertyAssignment(nameProp)) {
2361
3055
  const init = nameProp.getInitializer();
2362
- if (init && import_ts_morph7.Node.isStringLiteral(init)) {
3056
+ if (init && import_ts_morph11.Node.isStringLiteral(init)) {
2363
3057
  entries.push(`${init.getLiteralValue()}: Array<${FILE}>`);
2364
3058
  }
2365
3059
  }
@@ -2379,13 +3073,13 @@ function extractResponseType(method, sourceFile, project) {
2379
3073
  if (apiResponseDecorator) {
2380
3074
  const args = apiResponseDecorator.getArguments();
2381
3075
  const optsArg = args[0];
2382
- if (optsArg && import_ts_morph7.Node.isObjectLiteralExpression(optsArg)) {
3076
+ if (optsArg && import_ts_morph11.Node.isObjectLiteralExpression(optsArg)) {
2383
3077
  for (const prop of optsArg.getProperties()) {
2384
- if (!import_ts_morph7.Node.isPropertyAssignment(prop)) continue;
3078
+ if (!import_ts_morph11.Node.isPropertyAssignment(prop)) continue;
2385
3079
  if (prop.getName() !== "type") continue;
2386
3080
  const val = prop.getInitializer();
2387
3081
  if (!val) continue;
2388
- if (import_ts_morph7.Node.isArrayLiteralExpression(val)) {
3082
+ if (import_ts_morph11.Node.isArrayLiteralExpression(val)) {
2389
3083
  const elements = val.getElements();
2390
3084
  const firstEl = elements[0];
2391
3085
  if (elements.length > 0 && firstEl !== void 0) {
@@ -2406,24 +3100,24 @@ function extractResponseType(method, sourceFile, project) {
2406
3100
  }
2407
3101
  function apiResponseStatus(decorator) {
2408
3102
  const optsArg = decorator.getArguments()[0];
2409
- if (!optsArg || !import_ts_morph7.Node.isObjectLiteralExpression(optsArg)) return null;
3103
+ if (!optsArg || !import_ts_morph11.Node.isObjectLiteralExpression(optsArg)) return null;
2410
3104
  for (const prop of optsArg.getProperties()) {
2411
- if (!import_ts_morph7.Node.isPropertyAssignment(prop)) continue;
3105
+ if (!import_ts_morph11.Node.isPropertyAssignment(prop)) continue;
2412
3106
  if (prop.getName() !== "status") continue;
2413
3107
  const val = prop.getInitializer();
2414
- if (val && import_ts_morph7.Node.isNumericLiteral(val)) return Number(val.getLiteralValue());
3108
+ if (val && import_ts_morph11.Node.isNumericLiteral(val)) return Number(val.getLiteralValue());
2415
3109
  }
2416
3110
  return null;
2417
3111
  }
2418
3112
  function apiResponseTypeNode(decorator) {
2419
3113
  const optsArg = decorator.getArguments()[0];
2420
- if (!optsArg || !import_ts_morph7.Node.isObjectLiteralExpression(optsArg)) return null;
3114
+ if (!optsArg || !import_ts_morph11.Node.isObjectLiteralExpression(optsArg)) return null;
2421
3115
  for (const prop of optsArg.getProperties()) {
2422
- if (!import_ts_morph7.Node.isPropertyAssignment(prop)) continue;
3116
+ if (!import_ts_morph11.Node.isPropertyAssignment(prop)) continue;
2423
3117
  if (prop.getName() !== "type") continue;
2424
3118
  const val = prop.getInitializer();
2425
3119
  if (!val) return null;
2426
- if (import_ts_morph7.Node.isArrayLiteralExpression(val)) {
3120
+ if (import_ts_morph11.Node.isArrayLiteralExpression(val)) {
2427
3121
  const first = val.getElements()[0];
2428
3122
  return first ? { node: first, isArray: true } : null;
2429
3123
  }
@@ -2441,7 +3135,7 @@ function extractErrorType(method, sourceFile, project) {
2441
3135
  const inner = resolveIdentifierToClassType(typeInfo.node, sourceFile, project, 3);
2442
3136
  const type = typeInfo.isArray ? `Array<${inner}>` : inner;
2443
3137
  let ref = null;
2444
- if (import_ts_morph7.Node.isIdentifier(typeInfo.node)) {
3138
+ if (import_ts_morph11.Node.isIdentifier(typeInfo.node)) {
2445
3139
  const name = typeInfo.node.getText();
2446
3140
  const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
2447
3141
  if (localDecl?.isExported()) {
@@ -2458,7 +3152,7 @@ function extractErrorType(method, sourceFile, project) {
2458
3152
  return null;
2459
3153
  }
2460
3154
  function resolveIdentifierToClassType(node, sourceFile, project, depth) {
2461
- if (!import_ts_morph7.Node.isIdentifier(node)) return "unknown";
3155
+ if (!import_ts_morph11.Node.isIdentifier(node)) return "unknown";
2462
3156
  const name = node.getText();
2463
3157
  const resolved = findType(name, sourceFile, project);
2464
3158
  if (resolved) {
@@ -2478,9 +3172,9 @@ var STREAM_ENVELOPES = /* @__PURE__ */ new Set(["MessageEvent", "MessageEventLik
2478
3172
  var BINARY_RESPONSE_TYPES = /* @__PURE__ */ new Set(["StreamableFile", "Buffer"]);
2479
3173
  function detectBinaryResponse(method) {
2480
3174
  const node = unwrapNamedContainer(method.getReturnTypeNode(), /* @__PURE__ */ new Set(["Promise"]));
2481
- if (!node || !import_ts_morph7.Node.isTypeReference(node)) return false;
3175
+ if (!node || !import_ts_morph11.Node.isTypeReference(node)) return false;
2482
3176
  const typeName = node.getTypeName();
2483
- const name = import_ts_morph7.Node.isIdentifier(typeName) ? typeName.getText() : "";
3177
+ const name = import_ts_morph11.Node.isIdentifier(typeName) ? typeName.getText() : "";
2484
3178
  return BINARY_RESPONSE_TYPES.has(name);
2485
3179
  }
2486
3180
  function detectStreamElement(method) {
@@ -2495,9 +3189,9 @@ function detectStreamElement(method) {
2495
3189
  return null;
2496
3190
  }
2497
3191
  function streamContainerElement(node) {
2498
- if (!node || !import_ts_morph7.Node.isTypeReference(node)) return null;
3192
+ if (!node || !import_ts_morph11.Node.isTypeReference(node)) return null;
2499
3193
  const typeName = node.getTypeName();
2500
- const name = import_ts_morph7.Node.isIdentifier(typeName) ? typeName.getText() : "";
3194
+ const name = import_ts_morph11.Node.isIdentifier(typeName) ? typeName.getText() : "";
2501
3195
  if (STREAM_CONTAINERS.has(name) || STREAM_CONTAINERS_GENERATOR.has(name)) {
2502
3196
  return node.getTypeArguments()[0] ?? null;
2503
3197
  }
@@ -2507,9 +3201,9 @@ function hasAsQueryDecorator(method) {
2507
3201
  return method.getDecorators().some((d) => d.getName() === "AsQuery");
2508
3202
  }
2509
3203
  function unwrapNamedContainer(node, names) {
2510
- if (!node || !import_ts_morph7.Node.isTypeReference(node)) return node;
3204
+ if (!node || !import_ts_morph11.Node.isTypeReference(node)) return node;
2511
3205
  const typeName = node.getTypeName();
2512
- const name = import_ts_morph7.Node.isIdentifier(typeName) ? typeName.getText() : "";
3206
+ const name = import_ts_morph11.Node.isIdentifier(typeName) ? typeName.getText() : "";
2513
3207
  if (names.has(name)) {
2514
3208
  return node.getTypeArguments()[0] ?? node;
2515
3209
  }
@@ -2530,19 +3224,20 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2530
3224
  body = body ?? bodyType;
2531
3225
  }
2532
3226
  const paramsType = extractParamsType(method, sourceFile, project);
3227
+ const paramTypes = extractPipedParamTypes(method, project);
2533
3228
  const response = isStream ? resolveTypeNodeToString(streamElement, sourceFile, project, 3) : extractResponseType(method, sourceFile, project);
2534
3229
  const errorInfo = extractErrorType(method, sourceFile, project);
2535
- if (body === null && query === null && paramsType === null && response === "unknown" && errorInfo === null && filterInfo === null && !isStream && !uploads.multipart && !binaryResponse && !asQuery) {
3230
+ if (body === null && query === null && paramsType === null && paramTypes === null && response === "unknown" && errorInfo === null && filterInfo === null && !isStream && !uploads.multipart && !binaryResponse && !asQuery) {
2536
3231
  return null;
2537
3232
  }
2538
3233
  let bodyRef = null;
2539
3234
  let queryRef = null;
2540
3235
  let responseRef = null;
2541
3236
  for (const param of method.getParameters()) {
2542
- if (param.getDecorators().some((d) => d.getName() === "Body") && param.getTypeNode()) {
3237
+ if (param.getDecorators().some((d) => d.getName() === "Body") && param.getTypeNode() && !hasPipeSchema(param, "Body", project)) {
2543
3238
  bodyRef = resolveBodyQueryResponseRef(param.getTypeNode(), sourceFile, project);
2544
3239
  }
2545
- if (param.getDecorators().some((d) => d.getName() === "Query") && param.getTypeNode()) {
3240
+ if (param.getDecorators().some((d) => d.getName() === "Query") && param.getTypeNode() && !hasPipeSchema(param, "Query", project)) {
2546
3241
  queryRef = resolveBodyQueryResponseRef(param.getTypeNode(), sourceFile, project);
2547
3242
  }
2548
3243
  }
@@ -2555,11 +3250,11 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2555
3250
  if (apiResp) {
2556
3251
  const args = apiResp.getArguments();
2557
3252
  const optsArg = args[0];
2558
- if (optsArg && import_ts_morph7.Node.isObjectLiteralExpression(optsArg)) {
3253
+ if (optsArg && import_ts_morph11.Node.isObjectLiteralExpression(optsArg)) {
2559
3254
  for (const prop of optsArg.getProperties()) {
2560
- if (import_ts_morph7.Node.isPropertyAssignment(prop) && prop.getName() === "type") {
3255
+ if (import_ts_morph11.Node.isPropertyAssignment(prop) && prop.getName() === "type") {
2561
3256
  const val = prop.getInitializer();
2562
- if (val && import_ts_morph7.Node.isIdentifier(val)) {
3257
+ if (val && import_ts_morph11.Node.isIdentifier(val)) {
2563
3258
  const name = val.getText();
2564
3259
  const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
2565
3260
  if (localDecl?.isExported()) {
@@ -2595,6 +3290,7 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2595
3290
  response,
2596
3291
  error: errorInfo?.type ?? null,
2597
3292
  params: paramsType,
3293
+ paramTypes,
2598
3294
  queryRef,
2599
3295
  bodyRef,
2600
3296
  responseRef,
@@ -2615,6 +3311,7 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2615
3311
  function resolveParamClass(method, decoratorName, sourceFile, project) {
2616
3312
  for (const param of method.getParameters()) {
2617
3313
  if (!param.getDecorators().some((d) => d.getName() === decoratorName)) continue;
3314
+ if (hasPipeSchema(param, decoratorName, project)) continue;
2618
3315
  const typeNode = param.getTypeNode();
2619
3316
  if (!typeNode) continue;
2620
3317
  const text = typeNode.getText().replace(/\[\]$/, "");
@@ -2627,129 +3324,6 @@ function resolveParamClass(method, decoratorName, sourceFile, project) {
2627
3324
  return null;
2628
3325
  }
2629
3326
 
2630
- // src/discovery/zod-ast-to-ts.ts
2631
- var import_ts_morph8 = require("ts-morph");
2632
- function zodAstToTs(node) {
2633
- if (!import_ts_morph8.Node.isCallExpression(node)) return "unknown";
2634
- const expr = node.getExpression();
2635
- if (import_ts_morph8.Node.isPropertyAccessExpression(expr)) {
2636
- const methodName = expr.getName();
2637
- const receiver = expr.getExpression();
2638
- if (methodName === "optional") {
2639
- return `${zodAstToTs(receiver)} | undefined`;
2640
- }
2641
- if (methodName === "nullable") {
2642
- return `${zodAstToTs(receiver)} | null`;
2643
- }
2644
- const args = node.getArguments();
2645
- switch (methodName) {
2646
- case "string":
2647
- return "string";
2648
- case "number":
2649
- return "number";
2650
- case "boolean":
2651
- return "boolean";
2652
- case "unknown":
2653
- return "unknown";
2654
- case "any":
2655
- return "unknown";
2656
- case "literal": {
2657
- const lit = args[0];
2658
- if (!lit) return "unknown";
2659
- if (import_ts_morph8.Node.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());
2660
- if (import_ts_morph8.Node.isNumericLiteral(lit)) return lit.getLiteralValue().toString();
2661
- if (lit.getKind() === import_ts_morph8.SyntaxKind.TrueKeyword) return "true";
2662
- if (lit.getKind() === import_ts_morph8.SyntaxKind.FalseKeyword) return "false";
2663
- return "unknown";
2664
- }
2665
- case "enum": {
2666
- const arrArg = args[0];
2667
- if (!arrArg || !import_ts_morph8.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2668
- const members = arrArg.getElements().map(
2669
- (el) => import_ts_morph8.Node.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : "unknown"
2670
- );
2671
- return members.join(" | ");
2672
- }
2673
- case "array": {
2674
- const inner = args[0];
2675
- if (!inner) return "unknown";
2676
- return `Array<${zodAstToTs(inner)}>`;
2677
- }
2678
- case "object": {
2679
- const objArg = args[0];
2680
- if (!objArg || !import_ts_morph8.Node.isObjectLiteralExpression(objArg)) return "unknown";
2681
- const lines = [];
2682
- for (const prop of objArg.getProperties()) {
2683
- if (!import_ts_morph8.Node.isPropertyAssignment(prop)) continue;
2684
- const key = prop.getName();
2685
- const valNode = prop.getInitializer();
2686
- if (!valNode) continue;
2687
- const tsType = zodAstToTs(valNode);
2688
- const isOpt = isOptionalChain(valNode);
2689
- lines.push(`${key}${isOpt ? "?" : ""}: ${tsType}`);
2690
- }
2691
- return `{ ${lines.join("; ")} }`;
2692
- }
2693
- case "union": {
2694
- const arrArg = args[0];
2695
- if (!arrArg || !import_ts_morph8.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2696
- return arrArg.getElements().map(zodAstToTs).join(" | ");
2697
- }
2698
- case "record": {
2699
- const valArg = args.length === 1 ? args[0] : args[1];
2700
- if (!valArg) return "unknown";
2701
- return `Record<string, ${zodAstToTs(valArg)}>`;
2702
- }
2703
- case "tuple": {
2704
- const arrArg = args[0];
2705
- if (!arrArg || !import_ts_morph8.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2706
- return `[${arrArg.getElements().map(zodAstToTs).join(", ")}]`;
2707
- }
2708
- default:
2709
- return "unknown";
2710
- }
2711
- }
2712
- return "unknown";
2713
- }
2714
- function isOptionalChain(node) {
2715
- if (!import_ts_morph8.Node.isCallExpression(node)) return false;
2716
- const expr = node.getExpression();
2717
- return import_ts_morph8.Node.isPropertyAccessExpression(expr) && expr.getName() === "optional";
2718
- }
2719
- function parseDefineContractCall(callExpr) {
2720
- if (!import_ts_morph8.Node.isCallExpression(callExpr)) return null;
2721
- const callee = callExpr.getExpression();
2722
- const calleeName = import_ts_morph8.Node.isIdentifier(callee) ? callee.getText() : import_ts_morph8.Node.isPropertyAccessExpression(callee) ? callee.getName() : "";
2723
- if (calleeName !== "defineContract") return null;
2724
- const args = callExpr.getArguments();
2725
- const optsArg = args[0];
2726
- if (!optsArg || !import_ts_morph8.Node.isObjectLiteralExpression(optsArg)) return null;
2727
- let query = null;
2728
- let body = null;
2729
- let response = "unknown";
2730
- let error = null;
2731
- let bodyZodText = null;
2732
- let queryZodText = null;
2733
- for (const prop of optsArg.getProperties()) {
2734
- if (!import_ts_morph8.Node.isPropertyAssignment(prop)) continue;
2735
- const propName = prop.getName();
2736
- const val = prop.getInitializer();
2737
- if (!val) continue;
2738
- if (propName === "query") {
2739
- query = zodAstToTs(val);
2740
- queryZodText = val.getText();
2741
- } else if (propName === "body") {
2742
- body = zodAstToTs(val);
2743
- bodyZodText = val.getText();
2744
- } else if (propName === "response") {
2745
- response = zodAstToTs(val);
2746
- } else if (propName === "error") {
2747
- error = zodAstToTs(val);
2748
- }
2749
- }
2750
- return { query, body, response, error, bodyZodText, queryZodText };
2751
- }
2752
-
2753
3327
  // src/discovery/contracts-fast.ts
2754
3328
  async function discoverContractsFast(opts) {
2755
3329
  const { cwd, glob, tsconfig } = opts;
@@ -2762,7 +3336,9 @@ async function discoverContractsFast(opts) {
2762
3336
  }
2763
3337
  bindDiscoveryContext(project, cwd, tsconfigPath, loaded);
2764
3338
  clearMixinTypeProject();
2765
- return extractAllRoutes(project);
3339
+ const routes = extractAllRoutes(project);
3340
+ clearSchemaTypeProject(project);
3341
+ return routes;
2766
3342
  }
2767
3343
  function resolveTsconfigPath(cwd, tsconfig) {
2768
3344
  return tsconfig ? (0, import_node_path5.resolve)(tsconfig) : (0, import_node_path5.join)(cwd, "tsconfig.json");
@@ -2774,25 +3350,25 @@ var NO_TSCONFIG_OPTIONS = {
2774
3350
  };
2775
3351
  function loadDiscoveryTsconfig(tsconfigPath) {
2776
3352
  if (!(0, import_node_fs.existsSync)(tsconfigPath)) return { options: null, files: [] };
2777
- const read = import_ts_morph9.ts.readConfigFile(tsconfigPath, (path) => import_ts_morph9.ts.sys.readFile(path));
3353
+ const read = import_ts_morph12.ts.readConfigFile(tsconfigPath, (path) => import_ts_morph12.ts.sys.readFile(path));
2778
3354
  if (read.error) {
2779
3355
  return {
2780
3356
  options: null,
2781
3357
  files: [tsconfigPath],
2782
- error: import_ts_morph9.ts.flattenDiagnosticMessageText(read.error.messageText, " ")
3358
+ error: import_ts_morph12.ts.flattenDiagnosticMessageText(read.error.messageText, " ")
2783
3359
  };
2784
3360
  }
2785
3361
  const host = {
2786
- useCaseSensitiveFileNames: import_ts_morph9.ts.sys.useCaseSensitiveFileNames,
3362
+ useCaseSensitiveFileNames: import_ts_morph12.ts.sys.useCaseSensitiveFileNames,
2787
3363
  // The one line that keeps a tsconfig from being a filesystem walk.
2788
3364
  readDirectory: () => [],
2789
- fileExists: (path) => import_ts_morph9.ts.sys.fileExists(path),
3365
+ fileExists: (path) => import_ts_morph12.ts.sys.fileExists(path),
2790
3366
  // `extends` is resolved through the host, so a consumer whose `paths` live
2791
3367
  // in a base tsconfig keeps working.
2792
- readFile: (path) => import_ts_morph9.ts.sys.readFile(path)
3368
+ readFile: (path) => import_ts_morph12.ts.sys.readFile(path)
2793
3369
  };
2794
- const sourceFile = import_ts_morph9.ts.readJsonConfigFile(tsconfigPath, (path) => import_ts_morph9.ts.sys.readFile(path));
2795
- const parsed = import_ts_morph9.ts.parseJsonSourceFileConfigFileContent(
3370
+ const sourceFile = import_ts_morph12.ts.readJsonConfigFile(tsconfigPath, (path) => import_ts_morph12.ts.sys.readFile(path));
3371
+ const parsed = import_ts_morph12.ts.parseJsonSourceFileConfigFileContent(
2796
3372
  sourceFile,
2797
3373
  host,
2798
3374
  (0, import_node_path5.dirname)(tsconfigPath),
@@ -2815,7 +3391,7 @@ function createDiscoveryProject(tsconfigPath, tsconfig = loadDiscoveryTsconfig(t
2815
3391
  `[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.`
2816
3392
  );
2817
3393
  }
2818
- return new import_ts_morph9.Project({
3394
+ return new import_ts_morph12.Project({
2819
3395
  compilerOptions: tsconfig.options ?? { ...NO_TSCONFIG_OPTIONS },
2820
3396
  skipAddingFilesFromTsConfig: true,
2821
3397
  skipLoadingLibFiles: true,
@@ -2927,15 +3503,16 @@ var PersistentDiscovery = class _PersistentDiscovery {
2927
3503
  clearTypeResolutionCaches(this.project);
2928
3504
  clearEnumCache(this.project);
2929
3505
  clearMixinTypeProject();
3506
+ clearSchemaTypeProject(this.project);
2930
3507
  return extractRoutesFrom(this.project, this.controllerPaths);
2931
3508
  }
2932
3509
  };
2933
3510
  function decoratorStringArg(decoratorExpr) {
2934
3511
  if (!decoratorExpr) return void 0;
2935
- if (import_ts_morph9.Node.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();
2936
- if (import_ts_morph9.Node.isArrayLiteralExpression(decoratorExpr)) {
3512
+ if (import_ts_morph12.Node.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();
3513
+ if (import_ts_morph12.Node.isArrayLiteralExpression(decoratorExpr)) {
2937
3514
  const first = decoratorExpr.getElements()[0];
2938
- if (first && import_ts_morph9.Node.isStringLiteral(first)) return first.getLiteralValue();
3515
+ if (first && import_ts_morph12.Node.isStringLiteral(first)) return first.getLiteralValue();
2939
3516
  }
2940
3517
  return void 0;
2941
3518
  }
@@ -3056,9 +3633,9 @@ function extractContractRoute(args) {
3056
3633
  let contractDef = null;
3057
3634
  let bodyZodRef = null;
3058
3635
  let queryZodRef = null;
3059
- if (import_ts_morph9.Node.isCallExpression(firstDecoratorArg)) {
3060
- contractDef = parseDefineContractCall(firstDecoratorArg);
3061
- } else if (import_ts_morph9.Node.isIdentifier(firstDecoratorArg)) {
3636
+ if (import_ts_morph12.Node.isCallExpression(firstDecoratorArg)) {
3637
+ contractDef = parseDefineContractCall(firstDecoratorArg, project);
3638
+ } else if (import_ts_morph12.Node.isIdentifier(firstDecoratorArg)) {
3062
3639
  const identName = firstDecoratorArg.getText();
3063
3640
  const resolvedVar = resolveImportedVariable(identName, sourceFile, project);
3064
3641
  if (!resolvedVar) {
@@ -3070,7 +3647,7 @@ function extractContractRoute(args) {
3070
3647
  const { decl: varDecl, file: declFile } = resolvedVar;
3071
3648
  const initializer = varDecl.getInitializer();
3072
3649
  if (!initializer) return null;
3073
- contractDef = parseDefineContractCall(initializer);
3650
+ contractDef = parseDefineContractCall(initializer, project);
3074
3651
  if (contractDef && varDecl.isExported()) {
3075
3652
  const filePath = declFile.getFilePath();
3076
3653
  if (contractDef.body !== null) {
@@ -3141,6 +3718,7 @@ function extractDtoRoute(args) {
3141
3718
  body: dtoContract?.body ?? null,
3142
3719
  response: mixinResponse ?? dtoContract?.response ?? "unknown",
3143
3720
  error: dtoContract?.error ?? null,
3721
+ paramTypes: dtoContract?.paramTypes ?? null,
3144
3722
  queryRef: dtoContract?.queryRef ?? null,
3145
3723
  bodyRef: dtoContract?.bodyRef ?? null,
3146
3724
  responseRef: dtoContract?.responseRef ?? null,
@@ -3263,7 +3841,7 @@ function createExtensionContext(config, getRoutes, trackedInputs) {
3263
3841
  },
3264
3842
  project() {
3265
3843
  if (!project) {
3266
- project = new import_ts_morph10.Project({
3844
+ project = new import_ts_morph13.Project({
3267
3845
  skipAddingFilesFromTsConfig: true,
3268
3846
  skipLoadingLibFiles: true,
3269
3847
  skipFileDependencyResolution: true,
@@ -3381,10 +3959,11 @@ function insertIntoTree(tree, segments, leaf, fullName) {
3381
3959
  insertIntoTree(branch.children, rest, leaf, fullName);
3382
3960
  }
3383
3961
  }
3384
- function buildParamsType(params) {
3962
+ function buildParamsType(params, paramTypes) {
3385
3963
  const pathParams = params.filter((p) => p.source === "path");
3386
3964
  if (pathParams.length === 0) return "never";
3387
- return `{ ${pathParams.map((p) => `${p.name}: string`).join("; ")} }`;
3965
+ const typeOf = (name) => paramTypes && Object.hasOwn(paramTypes, name) && paramTypes[name] || "string";
3966
+ return `{ ${pathParams.map((p) => `${p.name}: ${typeOf(p.name)}`).join("; ")} }`;
3388
3967
  }
3389
3968
  function hasPathParams(params) {
3390
3969
  return params.some((p) => p.source === "path");
@@ -3478,7 +4057,7 @@ function emitRouterTypeBlock(tree, indent, outDir, serialization) {
3478
4057
  }
3479
4058
  const response = buildResponseType(c, outDir, serialization);
3480
4059
  const error = buildErrorType(c);
3481
- const params = buildParamsType(c.params);
4060
+ const params = buildParamsType(c.params, c.contractSource.paramTypes);
3482
4061
  const safeMethod = JSON.stringify(method);
3483
4062
  const safeUrl = JSON.stringify(c.path);
3484
4063
  const filterLiterals = filterFieldLiterals(c.contractSource.filterFields);
@@ -3747,6 +4326,9 @@ var EMPTY_PATH_NAMESPACE = [
3747
4326
  "}",
3748
4327
  ""
3749
4328
  ];
4329
+ function isClientCallable(route) {
4330
+ return route.method.toUpperCase() !== "ALL";
4331
+ }
3750
4332
  function buildApiFile(routes, outDir, opts = {}) {
3751
4333
  const fetcherImportPath = opts.fetcherImportPath;
3752
4334
  const serialization = opts.serialization ?? "json";
@@ -3754,7 +4336,7 @@ function buildApiFile(routes, outDir, opts = {}) {
3754
4336
  const { layer } = resolveApiSlots(extensions);
3755
4337
  const memberExts = extensions.filter((e) => e.apiMembers);
3756
4338
  const headerExts = extensions.filter((e) => e.apiHeader);
3757
- const contracted = routes.filter((r) => r.contract);
4339
+ const contracted = routes.filter((r) => r.contract && isClientCallable(r));
3758
4340
  const ctx = opts.ctx ?? {
3759
4341
  cwd: outDir ?? "",
3760
4342
  outDir: outDir ?? "",
@@ -4675,6 +5257,7 @@ function buildOpenApiSpec(routes, opts = {}) {
4675
5257
  const paths = {};
4676
5258
  for (const route of routes) {
4677
5259
  if (!route.contract) continue;
5260
+ if (route.method.toUpperCase() === "ALL") continue;
4678
5261
  const oaPath = toOpenApiPath(route.path);
4679
5262
  const method = route.method.toLowerCase();
4680
5263
  let pathItem = paths[oaPath];
@@ -5390,7 +5973,7 @@ function toObjectKey2(name) {
5390
5973
  return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
5391
5974
  }
5392
5975
  function createChainModuleRenderer(opts) {
5393
- const { render, recursiveAnnotation } = opts;
5976
+ const { render: render2, recursiveAnnotation } = opts;
5394
5977
  return (mod) => {
5395
5978
  const ctx = { named: mod.named };
5396
5979
  const recursive = mod.recursive ?? /* @__PURE__ */ new Set();
@@ -5399,7 +5982,7 @@ function createChainModuleRenderer(opts) {
5399
5982
  const namedTypeAliases = /* @__PURE__ */ new Map();
5400
5983
  const namedAnnotations = /* @__PURE__ */ new Map();
5401
5984
  for (const [name, node] of mod.named) {
5402
- namedNestedSchemas.set(name, render(node, ctx));
5985
+ namedNestedSchemas.set(name, render2(node, ctx));
5403
5986
  if (recursive.has(name)) {
5404
5987
  const typeName = typeNameFor(name);
5405
5988
  namedTypeAliases.set(name, `type ${typeName} = ${renderTsType(node, tctx)}`);
@@ -5407,7 +5990,7 @@ function createChainModuleRenderer(opts) {
5407
5990
  }
5408
5991
  }
5409
5992
  return {
5410
- schemaText: render(mod.root, ctx),
5993
+ schemaText: render2(mod.root, ctx),
5411
5994
  namedNestedSchemas,
5412
5995
  namedTypeAliases,
5413
5996
  namedAnnotations,
@@ -5417,7 +6000,7 @@ function createChainModuleRenderer(opts) {
5417
6000
  }
5418
6001
 
5419
6002
  // src/index.ts
5420
- var VERSION = "0.25.2";
6003
+ var VERSION = "0.26.0";
5421
6004
  // Annotate the CommonJS export names for ESM import in node:
5422
6005
  0 && (module.exports = {
5423
6006
  CodegenError,