@dudousxd/nestjs-codegen 0.25.1 → 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.js CHANGED
@@ -518,22 +518,22 @@ import { isAbsolute as isAbsolute2, join as join5, relative as relative4 } from
518
518
 
519
519
  // src/extension/registry.ts
520
520
  import { relative as relative3, resolve as resolve4 } from "path";
521
- import { Project as Project4 } from "ts-morph";
521
+ import { Project as Project5 } from "ts-morph";
522
522
 
523
523
  // src/discovery/contracts-fast.ts
524
524
  import { existsSync } from "fs";
525
525
  import { dirname as dirname2, join as join4, resolve as resolve3 } from "path";
526
526
  import fg2 from "fast-glob";
527
527
  import {
528
- Node as Node9,
529
- Project as Project3,
530
- ts
528
+ Node as Node11,
529
+ Project as Project4,
530
+ ts as ts3
531
531
  } from "ts-morph";
532
532
 
533
533
  // src/discovery/dto-type-resolver.ts
534
534
  import {
535
- Node as Node7,
536
- SyntaxKind as SyntaxKind3
535
+ Node as Node10,
536
+ SyntaxKind as SyntaxKind4
537
537
  } from "ts-morph";
538
538
 
539
539
  // src/discovery/dto-to-ir.ts
@@ -2071,6 +2071,674 @@ function extractFilterableEntityFields(filterClass, project, entityOverride, pre
2071
2071
  return fields;
2072
2072
  }
2073
2073
 
2074
+ // src/discovery/pipe-schema.ts
2075
+ import { Node as Node9 } from "ts-morph";
2076
+
2077
+ // src/discovery/schema-type-inference.ts
2078
+ import {
2079
+ ts as ts2
2080
+ } from "ts-morph";
2081
+
2082
+ // src/discovery/schema-type-program.ts
2083
+ import { Node as Node7, Project as Project3, ts } from "ts-morph";
2084
+ var PARAM_DECORATORS = /* @__PURE__ */ new Set(["Body", "Query", "Param"]);
2085
+ var SchemaTypeProgram = class {
2086
+ constructor(discovery) {
2087
+ this.discovery = discovery;
2088
+ const base = discovery.getCompilerOptions();
2089
+ this.options = {
2090
+ ...base,
2091
+ // A tsconfig-less consumer gets ES5 by default, whose lib has no `Map`/`Set`/
2092
+ // `Promise` for the schema libraries' declarations to lean on.
2093
+ target: base.target ?? ts.ScriptTarget.ES2022,
2094
+ // With neither set, resolve the way a bundler does: package `exports`
2095
+ // (`zod/v4`) and extensionless or `.js` relative imports all resolve.
2096
+ ...base.module === void 0 && base.moduleResolution === void 0 ? { module: ts.ModuleKind.ESNext, moduleResolution: ts.ModuleResolutionKind.Bundler } : {},
2097
+ // Without it `.nullable()` and `.optional()` would erase to the bare type.
2098
+ strictNullChecks: true,
2099
+ // No ambient `@types/*` (a tsconfig's `types: ['node']`): a schema does not
2100
+ // need them, and they are a hundred-odd files of program to build.
2101
+ types: [],
2102
+ noEmit: true
2103
+ };
2104
+ this.project = new Project3({
2105
+ skipAddingFilesFromTsConfig: true,
2106
+ compilerOptions: this.options
2107
+ });
2108
+ for (const sf of discovery.getSourceFiles()) this.request(sf.getFilePath(), { schema: true });
2109
+ this.flush();
2110
+ }
2111
+ project;
2112
+ options;
2113
+ /** Parses a file that is not in discovery's Project, without adding it there. */
2114
+ scratch = new Project3({
2115
+ skipAddingFilesFromTsConfig: true,
2116
+ skipLoadingLibFiles: true,
2117
+ skipFileDependencyResolution: true
2118
+ });
2119
+ needs = /* @__PURE__ */ new Map();
2120
+ /** Pruned text per file, as last written into {@link project}. */
2121
+ written = /* @__PURE__ */ new Map();
2122
+ /**
2123
+ * The typed copy of a discovery file, with its schema positions kept. Adding one
2124
+ * that was not there yet (a contract file discovery reached lazily) rebuilds the
2125
+ * program once.
2126
+ */
2127
+ sourceFileFor(sf) {
2128
+ this.request(sf.getFilePath(), { schema: true });
2129
+ this.flush();
2130
+ return this.project.getSourceFile(sf.getFilePath());
2131
+ }
2132
+ // -------------------------------------------------------------------------
2133
+ queue = [];
2134
+ request(path, want) {
2135
+ let needs = this.needs.get(path);
2136
+ const isNew = !needs;
2137
+ needs ??= { schema: false, all: false, names: /* @__PURE__ */ new Set() };
2138
+ let grew = isNew;
2139
+ if (want.schema && !needs.schema) {
2140
+ needs.schema = true;
2141
+ grew = true;
2142
+ }
2143
+ if (want.all && !needs.all) {
2144
+ needs.all = true;
2145
+ grew = true;
2146
+ }
2147
+ for (const name of want.names ?? []) {
2148
+ if (!needs.names.has(name)) {
2149
+ needs.names.add(name);
2150
+ grew = true;
2151
+ }
2152
+ }
2153
+ this.needs.set(path, needs);
2154
+ if (grew) this.queue.push(path);
2155
+ }
2156
+ /** Run the worklist to a fixpoint, then write every changed file into the program. */
2157
+ flush() {
2158
+ const changed = /* @__PURE__ */ new Map();
2159
+ while (this.queue.length > 0) {
2160
+ const path = this.queue.pop();
2161
+ const original = this.original(path);
2162
+ if (!original) continue;
2163
+ const needs = this.needs.get(path);
2164
+ const text = this.prune(original, needs);
2165
+ if (this.written.get(path) !== text) changed.set(path, text);
2166
+ }
2167
+ for (const [path, text] of changed) {
2168
+ this.project.createSourceFile(path, text, { overwrite: true });
2169
+ this.written.set(path, text);
2170
+ }
2171
+ }
2172
+ /** The file as discovery sees it (its in-memory text), else as it is on disk. */
2173
+ original(path) {
2174
+ return this.discovery.getSourceFile(path) ?? this.scratch.getSourceFile(path) ?? this.scratch.addSourceFileAtPathIfExists(path);
2175
+ }
2176
+ /**
2177
+ * `sf`'s text with every import/re-export nothing in `needs` references blanked,
2178
+ * requesting from each kept one's target the names it brings in.
2179
+ */
2180
+ prune(sf, needs) {
2181
+ const locals = topLevelDeclarations(sf);
2182
+ const roots = [];
2183
+ if (needs.all) roots.push(...sf.getStatements());
2184
+ if (needs.schema) roots.push(...schemaPositions(sf));
2185
+ const reexported = /* @__PURE__ */ new Map();
2186
+ for (const exp of sf.getExportDeclarations()) {
2187
+ const spec = exp.getModuleSpecifierValue();
2188
+ if (spec === void 0) {
2189
+ for (const named of exp.getNamedExports()) {
2190
+ const exposed = (named.getAliasNode() ?? named.getNameNode()).getText();
2191
+ if (needs.all || needs.names.has(exposed)) roots.push(named.getNameNode());
2192
+ }
2193
+ continue;
2194
+ }
2195
+ if (exp.isNamespaceExport() || exp.getNamedExports().length === 0) continue;
2196
+ for (const named of exp.getNamedExports()) {
2197
+ const exposed = (named.getAliasNode() ?? named.getNameNode()).getText();
2198
+ const list = reexported.get(exposed) ?? [];
2199
+ list.push({ from: spec, name: named.getNameNode().getText() });
2200
+ reexported.set(exposed, list);
2201
+ }
2202
+ }
2203
+ const unresolvedNames = [];
2204
+ for (const name of needs.names) {
2205
+ const decls = name === "default" ? defaultExport(sf) : locals.get(name) ?? [];
2206
+ if (decls.length > 0) roots.push(...decls);
2207
+ else if (!reexported.has(name)) unresolvedNames.push(name);
2208
+ }
2209
+ const referenced = /* @__PURE__ */ new Set();
2210
+ const queue = [...roots];
2211
+ const seen = new Set(queue);
2212
+ while (queue.length > 0) {
2213
+ const node = queue.pop();
2214
+ const ids = Node7.isIdentifier(node) ? [node] : node.getDescendantsOfKind(ts.SyntaxKind.Identifier);
2215
+ for (const id of ids) {
2216
+ const name = id.getText();
2217
+ if (referenced.has(name)) continue;
2218
+ referenced.add(name);
2219
+ for (const local of locals.get(name) ?? []) {
2220
+ if (seen.has(local)) continue;
2221
+ seen.add(local);
2222
+ queue.push(local);
2223
+ }
2224
+ }
2225
+ }
2226
+ const chars = sf.getFullText().split("");
2227
+ const blank = (node) => {
2228
+ for (let i = node.getStart(); i < node.getEnd(); i++) {
2229
+ if (chars[i] !== "\n" && chars[i] !== "\r") chars[i] = " ";
2230
+ }
2231
+ };
2232
+ for (const decl of sf.getImportDeclarations()) {
2233
+ const target = this.resolve(decl.getModuleSpecifierValue(), sf);
2234
+ const namespace = decl.getNamespaceImport()?.getText();
2235
+ const def = decl.getDefaultImport()?.getText();
2236
+ const named = decl.getNamedImports().map((n) => ({
2237
+ local: (n.getAliasNode() ?? n.getNameNode()).getText(),
2238
+ imported: n.getName()
2239
+ })).filter((n) => referenced.has(n.local));
2240
+ const wantsNamespace = namespace !== void 0 && referenced.has(namespace);
2241
+ const wantsDefault = def !== void 0 && referenced.has(def);
2242
+ if (!wantsNamespace && !wantsDefault && named.length === 0) {
2243
+ blank(decl);
2244
+ continue;
2245
+ }
2246
+ if (target) {
2247
+ this.request(target, {
2248
+ all: wantsNamespace,
2249
+ names: [...wantsDefault ? ["default"] : [], ...named.map((n) => n.imported)]
2250
+ });
2251
+ }
2252
+ }
2253
+ for (const exp of sf.getExportDeclarations()) {
2254
+ const spec = exp.getModuleSpecifierValue();
2255
+ if (spec === void 0) continue;
2256
+ const target = this.resolve(spec, sf);
2257
+ if (exp.isNamespaceExport() || exp.getNamedExports().length === 0) {
2258
+ if (!needs.all && unresolvedNames.length === 0) {
2259
+ blank(exp);
2260
+ } else if (target) {
2261
+ this.request(target, { all: needs.all, names: unresolvedNames });
2262
+ }
2263
+ continue;
2264
+ }
2265
+ const wanted = exp.getNamedExports().filter(
2266
+ (n) => needs.all || needs.names.has((n.getAliasNode() ?? n.getNameNode()).getText())
2267
+ ).map((n) => n.getNameNode().getText());
2268
+ if (wanted.length === 0) blank(exp);
2269
+ else if (target) this.request(target, { names: wanted });
2270
+ }
2271
+ return chars.join("");
2272
+ }
2273
+ /**
2274
+ * The project source file a module specifier resolves to, or undefined for a
2275
+ * package (read unpruned by the program itself) or an unresolvable one.
2276
+ */
2277
+ resolve(specifier, from) {
2278
+ const resolved = ts.resolveModuleName(
2279
+ specifier,
2280
+ from.getFilePath(),
2281
+ this.options,
2282
+ ts.sys
2283
+ ).resolvedModule;
2284
+ if (!resolved || resolved.isExternalLibraryImport) return void 0;
2285
+ const file = resolved.resolvedFileName;
2286
+ if (file.endsWith(".d.ts") || !/\.(m|c)?tsx?$/.test(file)) return void 0;
2287
+ return file;
2288
+ }
2289
+ };
2290
+ function schemaPositions(sf) {
2291
+ const roots = [];
2292
+ sf.forEachDescendant((node) => {
2293
+ if (Node7.isDecorator(node)) {
2294
+ const name = node.getName();
2295
+ if (name === "ApplyContract") {
2296
+ roots.push(...node.getArguments());
2297
+ } else if (PARAM_DECORATORS.has(name)) {
2298
+ for (const arg of node.getArguments()) {
2299
+ if (Node7.isNewExpression(arg) || Node7.isCallExpression(arg)) {
2300
+ roots.push(...arg.getArguments());
2301
+ }
2302
+ }
2303
+ }
2304
+ } else if (Node7.isCallExpression(node)) {
2305
+ const callee = node.getExpression();
2306
+ const name = Node7.isIdentifier(callee) ? callee.getText() : Node7.isPropertyAccessExpression(callee) ? callee.getName() : void 0;
2307
+ if (name === "defineContract") roots.push(...node.getArguments());
2308
+ }
2309
+ });
2310
+ return roots;
2311
+ }
2312
+ function topLevelDeclarations(sf) {
2313
+ const byName = /* @__PURE__ */ new Map();
2314
+ const add = (name, node) => {
2315
+ if (!name) return;
2316
+ const list = byName.get(name);
2317
+ if (list) list.push(node);
2318
+ else byName.set(name, [node]);
2319
+ };
2320
+ for (const decl of sf.getVariableDeclarations()) add(decl.getName(), decl);
2321
+ for (const decl of sf.getFunctions()) add(decl.getName(), decl);
2322
+ for (const decl of sf.getClasses()) add(decl.getName(), decl);
2323
+ for (const decl of sf.getEnums()) add(decl.getName(), decl);
2324
+ for (const decl of sf.getInterfaces()) add(decl.getName(), decl);
2325
+ for (const decl of sf.getTypeAliases()) add(decl.getName(), decl);
2326
+ for (const decl of sf.getModules()) add(decl.getName(), decl);
2327
+ return byName;
2328
+ }
2329
+ function defaultExport(sf) {
2330
+ const nodes = [];
2331
+ for (const assignment of sf.getExportAssignments()) nodes.push(assignment);
2332
+ for (const fn of sf.getFunctions()) if (fn.isDefaultExport()) nodes.push(fn);
2333
+ for (const cls of sf.getClasses()) if (cls.isDefaultExport()) nodes.push(cls);
2334
+ return nodes;
2335
+ }
2336
+
2337
+ // src/discovery/schema-type-inference.ts
2338
+ var programs = /* @__PURE__ */ new WeakMap();
2339
+ function programFor(discovery) {
2340
+ let program = programs.get(discovery);
2341
+ if (!program) {
2342
+ program = new SchemaTypeProgram(discovery);
2343
+ programs.set(discovery, program);
2344
+ }
2345
+ return program;
2346
+ }
2347
+ function clearSchemaTypeProject(discovery) {
2348
+ programs.delete(discovery);
2349
+ }
2350
+ function counterpart(typedSf, node) {
2351
+ const start = node.getStart();
2352
+ const end = node.getEnd();
2353
+ const kind = node.getKind();
2354
+ let candidate = typedSf.getDescendantAtPos(start);
2355
+ while (candidate) {
2356
+ if (candidate.getStart() === start && candidate.getEnd() === end && candidate.getKind() === kind) {
2357
+ return candidate;
2358
+ }
2359
+ if (candidate.getStart() < start || candidate.getEnd() > end) return void 0;
2360
+ candidate = candidate.getParent();
2361
+ }
2362
+ return void 0;
2363
+ }
2364
+ function propType(type, name, at) {
2365
+ return type.getProperty(name)?.getTypeAtLocation(at);
2366
+ }
2367
+ function isAnyOrUnknown(type) {
2368
+ return type.isAny() || type.isUnknown();
2369
+ }
2370
+ function inferSchema(expr, discovery) {
2371
+ try {
2372
+ const typedSf = programFor(discovery).sourceFileFor(expr.getSourceFile());
2373
+ const at = typedSf && counterpart(typedSf, expr);
2374
+ if (!at) return { kind: "unresolved" };
2375
+ const schemaType = at.getType();
2376
+ if (isAnyOrUnknown(schemaType)) return { kind: "unresolved" };
2377
+ const standard = propType(schemaType, "~standard", at);
2378
+ const stdTypes = standard ? propType(standard, "types", at)?.getNonNullableType() : void 0;
2379
+ const stdInput = stdTypes ? propType(stdTypes, "input", at) : void 0;
2380
+ const stdOutput = stdTypes ? propType(stdTypes, "output", at) : void 0;
2381
+ if (stdInput && stdOutput) {
2382
+ return { kind: "schema", types: { input: stdInput, output: stdOutput, at } };
2383
+ }
2384
+ const zodInput = propType(schemaType, "_input", at);
2385
+ const zodOutput = propType(schemaType, "_output", at);
2386
+ if (zodInput && zodOutput) {
2387
+ return { kind: "schema", types: { input: zodInput, output: zodOutput, at } };
2388
+ }
2389
+ return { kind: "not-schema" };
2390
+ } catch (err) {
2391
+ dbg("schema inference failed:", err);
2392
+ return { kind: "unresolved" };
2393
+ }
2394
+ }
2395
+ var GLOBAL_NAMED_TYPES = /* @__PURE__ */ new Set([
2396
+ "Date",
2397
+ "File",
2398
+ "Blob",
2399
+ "FormData",
2400
+ "URL",
2401
+ "RegExp",
2402
+ "Map",
2403
+ "Set",
2404
+ "ArrayBuffer",
2405
+ "Uint8Array"
2406
+ ]);
2407
+ var MAX_DEPTH = 12;
2408
+ function objectKey(name) {
2409
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
2410
+ }
2411
+ function isOptionalSymbol(sym) {
2412
+ return (sym.getFlags() & ts2.SymbolFlags.Optional) !== 0;
2413
+ }
2414
+ function isSymbolKeyed(sym) {
2415
+ return sym.getName().startsWith("__@");
2416
+ }
2417
+ function orderedProperties(type) {
2418
+ const position = (sym) => {
2419
+ const decl = sym.getDeclarations()[0];
2420
+ return decl ? [decl.getSourceFile().getFilePath(), decl.getStart()] : void 0;
2421
+ };
2422
+ return type.getProperties().map((sym, index) => ({ sym, index, at: position(sym) })).sort((a, b) => {
2423
+ if (a.at && b.at) {
2424
+ if (a.at[0] !== b.at[0]) return a.at[0] < b.at[0] ? -1 : 1;
2425
+ if (a.at[1] !== b.at[1]) return a.at[1] - b.at[1];
2426
+ } else if (a.at || b.at) {
2427
+ return a.at ? -1 : 1;
2428
+ }
2429
+ return a.index - b.index;
2430
+ }).map((entry) => entry.sym);
2431
+ }
2432
+ function isFromDeclarationFile(sym) {
2433
+ const decl = sym?.getDeclarations()[0];
2434
+ return !!decl && decl.getSourceFile().isDeclarationFile();
2435
+ }
2436
+ function render(type, state, paired) {
2437
+ if (state.depth > MAX_DEPTH) return "unknown";
2438
+ if (isAnyOrUnknown(type)) {
2439
+ return paired && !isAnyOrUnknown(paired) ? render(paired, state) : "unknown";
2440
+ }
2441
+ if (type.isNever()) return "never";
2442
+ if (type.isString() || type.isTemplateLiteral()) return "string";
2443
+ if (type.isNumber()) return "number";
2444
+ if (type.isBoolean()) return "boolean";
2445
+ if (type.isBigInt()) return "bigint";
2446
+ if (type.isNull()) return "null";
2447
+ if (type.isUndefined() || type.isVoid()) return "undefined";
2448
+ if (type.isBooleanLiteral()) return type.getText();
2449
+ if (type.isStringLiteral() || type.isNumberLiteral() || type.isEnumLiteral()) {
2450
+ const value = type.getLiteralValue();
2451
+ return typeof value === "string" ? JSON.stringify(value) : String(value);
2452
+ }
2453
+ if (type.isBigIntLiteral()) return type.getText();
2454
+ if (type.isTypeParameter()) return "unknown";
2455
+ if (type.isUnion()) return renderUnion(type, state, paired);
2456
+ if (type.isIntersection()) return renderIntersection(type, state);
2457
+ const next = { ...state, depth: state.depth + 1 };
2458
+ if (type.isArray() || type.isReadonlyArray()) {
2459
+ const element = type.getArrayElementType() ?? type.getTypeArguments()[0];
2460
+ const pairedElement = paired?.getArrayElementType() ?? paired?.getTypeArguments()[0];
2461
+ return element ? `Array<${render(element, next, pairedElement)}>` : "Array<unknown>";
2462
+ }
2463
+ if (type.isTuple()) {
2464
+ const elements = type.getTupleElements();
2465
+ const pairedElements = paired?.isTuple() ? paired.getTupleElements() : [];
2466
+ return `[${elements.map((e, i) => render(e, next, pairedElements[i])).join(", ")}]`;
2467
+ }
2468
+ if (type.isObject()) return renderObject(type, next, paired);
2469
+ return "unknown";
2470
+ }
2471
+ function renderUnion(type, state, paired) {
2472
+ const members = type.getUnionTypes();
2473
+ const hasTrue = members.some((m) => m.isBooleanLiteral() && m.getText() === "true");
2474
+ const hasFalse = members.some((m) => m.isBooleanLiteral() && m.getText() === "false");
2475
+ const pairedNonNull = paired?.getNonNullableType();
2476
+ const arms = [];
2477
+ let sawBoolean = false;
2478
+ let hasNull = false;
2479
+ let hasUndefined = false;
2480
+ for (const member of members) {
2481
+ if (member.isNull()) {
2482
+ hasNull = true;
2483
+ continue;
2484
+ }
2485
+ if (member.isUndefined()) {
2486
+ hasUndefined = true;
2487
+ continue;
2488
+ }
2489
+ if (member.isBooleanLiteral() && hasTrue && hasFalse) {
2490
+ if (!sawBoolean) arms.push("boolean");
2491
+ sawBoolean = true;
2492
+ continue;
2493
+ }
2494
+ arms.push(render(member, state, members.length === 1 ? paired : pairedNonNull));
2495
+ }
2496
+ if (hasNull) arms.push("null");
2497
+ if (hasUndefined) arms.push("undefined");
2498
+ const unique = [...new Set(arms)];
2499
+ if (unique.includes("unknown")) return "unknown";
2500
+ return unique.join(" | ");
2501
+ }
2502
+ function renderIntersection(type, state) {
2503
+ const members = type.getIntersectionTypes();
2504
+ const primitive = members.find((m) => !m.isObject());
2505
+ if (primitive) return render(primitive, state);
2506
+ return renderObject(type, { ...state, depth: state.depth + 1 }, void 0);
2507
+ }
2508
+ function renderObject(type, state, paired) {
2509
+ const symbol = type.getSymbol() ?? type.getAliasSymbol();
2510
+ const name = symbol?.getName();
2511
+ if (name && GLOBAL_NAMED_TYPES.has(name) && isFromDeclarationFile(symbol)) {
2512
+ const args = type.getTypeArguments();
2513
+ return args.length ? `${name}<${args.map((a) => render(a, state)).join(", ")}>` : name;
2514
+ }
2515
+ if (type.getCallSignatures().length > 0 || type.getConstructSignatures().length > 0) {
2516
+ return "unknown";
2517
+ }
2518
+ if (type.isClassOrInterface() && isFromDeclarationFile(symbol)) return "unknown";
2519
+ if (state.stack.has(type.compilerType)) return "unknown";
2520
+ const stack = new Set(state.stack).add(type.compilerType);
2521
+ const inner = { ...state, stack };
2522
+ const fields = [];
2523
+ for (const prop of orderedProperties(type)) {
2524
+ if (isSymbolKeyed(prop)) continue;
2525
+ const propName = prop.getName();
2526
+ const propT = prop.getTypeAtLocation(state.at);
2527
+ if (propT.getCallSignatures().length > 0 && !propT.isUnion()) continue;
2528
+ const pairedProp = paired?.getProperty(propName)?.getTypeAtLocation(state.at);
2529
+ const optional = isOptionalSymbol(prop) ? "?" : "";
2530
+ fields.push(`${objectKey(propName)}${optional}: ${render(propT, inner, pairedProp)}`);
2531
+ }
2532
+ const stringIndex = type.getStringIndexType();
2533
+ if (stringIndex) {
2534
+ const pairedIndex = paired?.getStringIndexType();
2535
+ const value = render(stringIndex, inner, pairedIndex);
2536
+ if (fields.length === 0) return `Record<string, ${value}>`;
2537
+ fields.push(`[key: string]: ${value}`);
2538
+ }
2539
+ return fields.length ? `{ ${fields.join("; ")} }` : "{}";
2540
+ }
2541
+ function stateAt(at) {
2542
+ return { at, stack: /* @__PURE__ */ new Set(), depth: 0 };
2543
+ }
2544
+ function requestTypeOf(types) {
2545
+ return render(types.input, stateAt(types.at), types.output);
2546
+ }
2547
+ function responseTypeOf(types) {
2548
+ return render(types.output, stateAt(types.at));
2549
+ }
2550
+ function requestFieldsOf(types) {
2551
+ const { input, output, at } = types;
2552
+ const objectInput = input.getNonNullableType();
2553
+ if (!objectInput.isObject() || objectInput.isArray() || objectInput.isTuple()) return null;
2554
+ const state = stateAt(at);
2555
+ return orderedProperties(objectInput).filter((prop) => !isSymbolKeyed(prop)).map((prop) => ({
2556
+ name: prop.getName(),
2557
+ type: render(
2558
+ prop.getTypeAtLocation(at),
2559
+ state,
2560
+ output.getProperty(prop.getName())?.getTypeAtLocation(at)
2561
+ ),
2562
+ optional: isOptionalSymbol(prop)
2563
+ }));
2564
+ }
2565
+ function acceptsUndefined(types) {
2566
+ const { input, output } = types;
2567
+ const accepted = isAnyOrUnknown(input) ? output : input;
2568
+ if (isAnyOrUnknown(accepted) || accepted.isUndefined()) return true;
2569
+ return accepted.isUnion() && accepted.getUnionTypes().some((t) => t.isUndefined());
2570
+ }
2571
+
2572
+ // src/discovery/zod-ast-to-ts.ts
2573
+ import { Node as Node8, SyntaxKind as SyntaxKind3 } from "ts-morph";
2574
+ function zodAstToTs(node) {
2575
+ if (!Node8.isCallExpression(node)) return "unknown";
2576
+ const expr = node.getExpression();
2577
+ if (Node8.isPropertyAccessExpression(expr)) {
2578
+ const methodName = expr.getName();
2579
+ const receiver = expr.getExpression();
2580
+ if (methodName === "optional") {
2581
+ return `${zodAstToTs(receiver)} | undefined`;
2582
+ }
2583
+ if (methodName === "nullable") {
2584
+ return `${zodAstToTs(receiver)} | null`;
2585
+ }
2586
+ const args = node.getArguments();
2587
+ switch (methodName) {
2588
+ case "string":
2589
+ return "string";
2590
+ case "number":
2591
+ return "number";
2592
+ case "boolean":
2593
+ return "boolean";
2594
+ case "unknown":
2595
+ return "unknown";
2596
+ case "any":
2597
+ return "unknown";
2598
+ case "literal": {
2599
+ const lit = args[0];
2600
+ if (!lit) return "unknown";
2601
+ if (Node8.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());
2602
+ if (Node8.isNumericLiteral(lit)) return lit.getLiteralValue().toString();
2603
+ if (lit.getKind() === SyntaxKind3.TrueKeyword) return "true";
2604
+ if (lit.getKind() === SyntaxKind3.FalseKeyword) return "false";
2605
+ return "unknown";
2606
+ }
2607
+ case "enum": {
2608
+ const arrArg = args[0];
2609
+ if (!arrArg || !Node8.isArrayLiteralExpression(arrArg)) return "unknown";
2610
+ const members = arrArg.getElements().map(
2611
+ (el) => Node8.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : "unknown"
2612
+ );
2613
+ return members.join(" | ");
2614
+ }
2615
+ case "array": {
2616
+ const inner = args[0];
2617
+ if (!inner) return "unknown";
2618
+ return `Array<${zodAstToTs(inner)}>`;
2619
+ }
2620
+ case "object": {
2621
+ const objArg = args[0];
2622
+ if (!objArg || !Node8.isObjectLiteralExpression(objArg)) return "unknown";
2623
+ const lines = [];
2624
+ for (const prop of objArg.getProperties()) {
2625
+ if (!Node8.isPropertyAssignment(prop)) continue;
2626
+ const key = prop.getName();
2627
+ const valNode = prop.getInitializer();
2628
+ if (!valNode) continue;
2629
+ const tsType = zodAstToTs(valNode);
2630
+ const isOpt = isOptionalChain(valNode);
2631
+ lines.push(`${key}${isOpt ? "?" : ""}: ${tsType}`);
2632
+ }
2633
+ return `{ ${lines.join("; ")} }`;
2634
+ }
2635
+ case "union": {
2636
+ const arrArg = args[0];
2637
+ if (!arrArg || !Node8.isArrayLiteralExpression(arrArg)) return "unknown";
2638
+ return arrArg.getElements().map(zodAstToTs).join(" | ");
2639
+ }
2640
+ case "record": {
2641
+ const valArg = args.length === 1 ? args[0] : args[1];
2642
+ if (!valArg) return "unknown";
2643
+ return `Record<string, ${zodAstToTs(valArg)}>`;
2644
+ }
2645
+ case "tuple": {
2646
+ const arrArg = args[0];
2647
+ if (!arrArg || !Node8.isArrayLiteralExpression(arrArg)) return "unknown";
2648
+ return `[${arrArg.getElements().map(zodAstToTs).join(", ")}]`;
2649
+ }
2650
+ default:
2651
+ return "unknown";
2652
+ }
2653
+ }
2654
+ return "unknown";
2655
+ }
2656
+ function isOptionalChain(node) {
2657
+ if (!Node8.isCallExpression(node)) return false;
2658
+ const expr = node.getExpression();
2659
+ return Node8.isPropertyAccessExpression(expr) && expr.getName() === "optional";
2660
+ }
2661
+ function memberType(val, position, project) {
2662
+ if (project) {
2663
+ const inferred = inferSchema(val, project);
2664
+ if (inferred.kind === "schema") {
2665
+ return position === "request" ? requestTypeOf(inferred.types) : responseTypeOf(inferred.types);
2666
+ }
2667
+ }
2668
+ return zodAstToTs(val);
2669
+ }
2670
+ function parseDefineContractCall(callExpr, project) {
2671
+ if (!Node8.isCallExpression(callExpr)) return null;
2672
+ const callee = callExpr.getExpression();
2673
+ const calleeName = Node8.isIdentifier(callee) ? callee.getText() : Node8.isPropertyAccessExpression(callee) ? callee.getName() : "";
2674
+ if (calleeName !== "defineContract") return null;
2675
+ const args = callExpr.getArguments();
2676
+ const optsArg = args[0];
2677
+ if (!optsArg || !Node8.isObjectLiteralExpression(optsArg)) return null;
2678
+ let query = null;
2679
+ let body = null;
2680
+ let response = "unknown";
2681
+ let error = null;
2682
+ let bodyZodText = null;
2683
+ let queryZodText = null;
2684
+ for (const prop of optsArg.getProperties()) {
2685
+ if (!Node8.isPropertyAssignment(prop)) continue;
2686
+ const propName = prop.getName();
2687
+ const val = prop.getInitializer();
2688
+ if (!val) continue;
2689
+ if (propName === "query") {
2690
+ query = memberType(val, "request", project);
2691
+ queryZodText = val.getText();
2692
+ } else if (propName === "body") {
2693
+ body = memberType(val, "request", project);
2694
+ bodyZodText = val.getText();
2695
+ } else if (propName === "response") {
2696
+ response = memberType(val, "response", project);
2697
+ } else if (propName === "error") {
2698
+ error = memberType(val, "response", project);
2699
+ }
2700
+ }
2701
+ return { query, body, response, error, bodyZodText, queryZodText };
2702
+ }
2703
+
2704
+ // src/discovery/pipe-schema.ts
2705
+ function pipeSchemaOf(decorator, project) {
2706
+ for (const pipe of decorator.getArguments()) {
2707
+ if (!Node9.isNewExpression(pipe) && !Node9.isCallExpression(pipe)) continue;
2708
+ for (const arg of pipe.getArguments()) {
2709
+ if (!couldBeSchema(arg)) continue;
2710
+ const inferred = inferSchema(arg, project);
2711
+ if (inferred.kind === "schema") {
2712
+ return {
2713
+ type: requestTypeOf(inferred.types),
2714
+ optional: acceptsUndefined(inferred.types),
2715
+ fields: requestFieldsOf(inferred.types)
2716
+ };
2717
+ }
2718
+ if (inferred.kind === "unresolved") {
2719
+ const fallback = syntacticZodType(arg, project);
2720
+ if (fallback) {
2721
+ return { type: fallback, optional: fallback.endsWith("| undefined"), fields: null };
2722
+ }
2723
+ }
2724
+ }
2725
+ }
2726
+ return null;
2727
+ }
2728
+ function couldBeSchema(arg) {
2729
+ return Node9.isIdentifier(arg) || Node9.isPropertyAccessExpression(arg) || Node9.isCallExpression(arg) || Node9.isAsExpression(arg) || Node9.isSatisfiesExpression(arg) || Node9.isParenthesizedExpression(arg);
2730
+ }
2731
+ function syntacticZodType(arg, project) {
2732
+ let expr = arg;
2733
+ if (Node9.isIdentifier(arg)) {
2734
+ const resolved = resolveImportedVariable(arg.getText(), arg.getSourceFile(), project);
2735
+ expr = resolved?.decl.getInitializer();
2736
+ }
2737
+ if (!expr || !Node9.isCallExpression(expr)) return null;
2738
+ const type = zodAstToTs(expr);
2739
+ return type === "unknown" ? null : type;
2740
+ }
2741
+
2074
2742
  // src/discovery/dto-type-resolver.ts
2075
2743
  var WRAPPER_TYPES = {
2076
2744
  // MikroORM Ref/Reference/LoadedReference/IdentifiedReference are server-side
@@ -2102,22 +2770,22 @@ var PASSTHROUGH_UTILITY = /* @__PURE__ */ new Set([
2102
2770
  ]);
2103
2771
  function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /* @__PURE__ */ new Map()) {
2104
2772
  if (depth <= 0) return "unknown";
2105
- if (Node7.isArrayTypeNode(typeNode)) {
2773
+ if (Node10.isArrayTypeNode(typeNode)) {
2106
2774
  const elementType = typeNode.getElementTypeNode();
2107
2775
  return `Array<${resolveTypeNodeToString(elementType, sourceFile, project, depth, subst)}>`;
2108
2776
  }
2109
- if (Node7.isUnionTypeNode(typeNode)) {
2777
+ if (Node10.isUnionTypeNode(typeNode)) {
2110
2778
  return typeNode.getTypeNodes().map((t) => resolveTypeNodeToString(t, sourceFile, project, depth, subst)).join(" | ");
2111
2779
  }
2112
- if (Node7.isIntersectionTypeNode(typeNode)) {
2780
+ if (Node10.isIntersectionTypeNode(typeNode)) {
2113
2781
  return typeNode.getTypeNodes().map((t) => resolveTypeNodeToString(t, sourceFile, project, depth, subst)).join(" & ");
2114
2782
  }
2115
- if (Node7.isParenthesizedTypeNode(typeNode)) {
2783
+ if (Node10.isParenthesizedTypeNode(typeNode)) {
2116
2784
  return `(${resolveTypeNodeToString(typeNode.getTypeNode(), sourceFile, project, depth, subst)})`;
2117
2785
  }
2118
- if (Node7.isTypeReference(typeNode)) {
2786
+ if (Node10.isTypeReference(typeNode)) {
2119
2787
  const typeName = typeNode.getTypeName();
2120
- const name = Node7.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();
2788
+ const name = Node10.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();
2121
2789
  const bound = subst.get(name);
2122
2790
  if (bound !== void 0) return bound;
2123
2791
  if (name === "string" || name === "number" || name === "boolean") return name;
@@ -2140,13 +2808,13 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /
2140
2808
  dbg("unresolvable type:", name, "in", sourceFile.getFilePath());
2141
2809
  return "unknown";
2142
2810
  }
2143
- if (Node7.isTypeLiteral(typeNode)) {
2811
+ if (Node10.isTypeLiteral(typeNode)) {
2144
2812
  const members = [];
2145
2813
  for (const member of typeNode.getMembers()) {
2146
- if (Node7.isPropertySignature(member)) {
2814
+ if (Node10.isPropertySignature(member)) {
2147
2815
  const memberTypeNode = member.getTypeNode();
2148
- const memberType = memberTypeNode ? resolveTypeNodeToString(memberTypeNode, sourceFile, project, depth, subst) : "unknown";
2149
- members.push(`${member.getName()}${member.hasQuestionToken() ? "?" : ""}: ${memberType}`);
2816
+ const memberType2 = memberTypeNode ? resolveTypeNodeToString(memberTypeNode, sourceFile, project, depth, subst) : "unknown";
2817
+ members.push(`${member.getName()}${member.hasQuestionToken() ? "?" : ""}: ${memberType2}`);
2150
2818
  } else {
2151
2819
  members.push(member.getText());
2152
2820
  }
@@ -2154,11 +2822,11 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /
2154
2822
  return members.length > 0 ? `{ ${members.join("; ")} }` : "{}";
2155
2823
  }
2156
2824
  const kind = typeNode.getKind();
2157
- if (kind === SyntaxKind3.StringKeyword) return "string";
2158
- if (kind === SyntaxKind3.NumberKeyword) return "number";
2159
- if (kind === SyntaxKind3.BooleanKeyword) return "boolean";
2160
- if (kind === SyntaxKind3.UnknownKeyword) return "unknown";
2161
- if (kind === SyntaxKind3.AnyKeyword) return "unknown";
2825
+ if (kind === SyntaxKind4.StringKeyword) return "string";
2826
+ if (kind === SyntaxKind4.NumberKeyword) return "number";
2827
+ if (kind === SyntaxKind4.BooleanKeyword) return "boolean";
2828
+ if (kind === SyntaxKind4.UnknownKeyword) return "unknown";
2829
+ if (kind === SyntaxKind4.AnyKeyword) return "unknown";
2162
2830
  return typeNode.getText();
2163
2831
  }
2164
2832
  function unwrapFirstTypeArg(typeNode, sourceFile, project, depth, mode, subst = /* @__PURE__ */ new Map()) {
@@ -2206,20 +2874,24 @@ function resolvePropertied(decl, sourceFile, project, depth, subst = /* @__PURE_
2206
2874
  const propName = prop.getName();
2207
2875
  const isOptional = prop.hasQuestionToken();
2208
2876
  const propTypeNode = prop.getTypeNode();
2209
- let propType = "unknown";
2877
+ let propType2 = "unknown";
2210
2878
  if (propTypeNode) {
2211
- propType = resolveTypeNodeToString(propTypeNode, sourceFile, project, depth, subst);
2879
+ propType2 = resolveTypeNodeToString(propTypeNode, sourceFile, project, depth, subst);
2212
2880
  }
2213
- lines.push(`${propName}${isOptional ? "?" : ""}: ${propType}`);
2881
+ lines.push(`${propName}${isOptional ? "?" : ""}: ${propType2}`);
2214
2882
  }
2215
2883
  return `{ ${lines.join("; ")} }`;
2216
2884
  }
2885
+ function namedField(decorator) {
2886
+ const first = decorator.getArguments()[0];
2887
+ return first && Node10.isStringLiteral(first) ? first.getLiteralValue() : null;
2888
+ }
2217
2889
  function extractBodyType(method, sourceFile, project) {
2218
2890
  for (const param of method.getParameters()) {
2219
2891
  const bodyDecorator = param.getDecorators().find((d) => d.getName() === "Body");
2220
- if (!bodyDecorator) continue;
2221
- const bodyArgs = bodyDecorator.getArguments();
2222
- if (bodyArgs.length > 0) continue;
2892
+ if (!bodyDecorator || namedField(bodyDecorator) !== null) continue;
2893
+ const piped = pipeSchemaOf(bodyDecorator, project);
2894
+ if (piped) return piped.type;
2223
2895
  const typeNode = param.getTypeNode();
2224
2896
  if (typeNode) {
2225
2897
  return resolveTypeNodeToString(typeNode, sourceFile, project, 3);
@@ -2227,11 +2899,16 @@ function extractBodyType(method, sourceFile, project) {
2227
2899
  }
2228
2900
  return null;
2229
2901
  }
2902
+ function hasPipeSchema(param, decoratorName, project) {
2903
+ const decorator = param.getDecorators().find((d) => d.getName() === decoratorName);
2904
+ return !!decorator && pipeSchemaOf(decorator, project) !== null;
2905
+ }
2230
2906
  function extractQueryType(method, sourceFile, project) {
2231
2907
  for (const param of method.getParameters()) {
2232
2908
  const queryDecorator = param.getDecorators().find((d) => d.getName() === "Query");
2233
- if (!queryDecorator) continue;
2234
- if (queryDecorator.getArguments().length > 0) continue;
2909
+ if (!queryDecorator || namedField(queryDecorator) !== null) continue;
2910
+ const piped = pipeSchemaOf(queryDecorator, project);
2911
+ if (piped) return piped.type;
2235
2912
  const typeNode = param.getTypeNode();
2236
2913
  if (typeNode) {
2237
2914
  return resolveTypeNodeToString(typeNode, sourceFile, project, 3);
@@ -2241,10 +2918,13 @@ function extractQueryType(method, sourceFile, project) {
2241
2918
  for (const param of method.getParameters()) {
2242
2919
  const queryDecorator = param.getDecorators().find((d) => d.getName() === "Query");
2243
2920
  if (!queryDecorator) continue;
2244
- const queryArgs = queryDecorator.getArguments();
2245
- const nameArg = queryArgs[0];
2246
- if (!nameArg || !Node7.isStringLiteral(nameArg)) continue;
2247
- const queryName = nameArg.getLiteralValue();
2921
+ const queryName = namedField(queryDecorator);
2922
+ if (queryName === null) continue;
2923
+ const piped = pipeSchemaOf(queryDecorator, project);
2924
+ if (piped) {
2925
+ entries.push(`${queryName}${piped.optional ? "?" : ""}: ${piped.type}`);
2926
+ continue;
2927
+ }
2248
2928
  const typeNode = param.getTypeNode();
2249
2929
  const queryType = typeNode ? resolveTypeNodeToString(typeNode, sourceFile, project, 3) : "string";
2250
2930
  entries.push(`${queryName}${isParamOptional(param) ? "?" : ""}: ${queryType}`);
@@ -2254,8 +2934,8 @@ function extractQueryType(method, sourceFile, project) {
2254
2934
  function isParamOptional(param) {
2255
2935
  if (param.hasQuestionToken() || param.hasInitializer()) return true;
2256
2936
  const typeNode = param.getTypeNode();
2257
- if (typeNode && Node7.isUnionTypeNode(typeNode)) {
2258
- return typeNode.getTypeNodes().some((t) => t.getKind() === SyntaxKind3.UndefinedKeyword);
2937
+ if (typeNode && Node10.isUnionTypeNode(typeNode)) {
2938
+ return typeNode.getTypeNodes().some((t) => t.getKind() === SyntaxKind4.UndefinedKeyword);
2259
2939
  }
2260
2940
  return false;
2261
2941
  }
@@ -2267,7 +2947,7 @@ function extractParamsType(method, sourceFile, project) {
2267
2947
  const paramArgs = paramDecorator.getArguments();
2268
2948
  if (paramArgs.length === 0) continue;
2269
2949
  const nameArg = paramArgs[0];
2270
- if (!Node7.isStringLiteral(nameArg)) continue;
2950
+ if (!Node10.isStringLiteral(nameArg)) continue;
2271
2951
  const paramName = nameArg.getLiteralValue();
2272
2952
  const typeNode = param.getTypeNode();
2273
2953
  const paramType = typeNode ? resolveTypeNodeToString(typeNode, sourceFile, project, 3) : "string";
@@ -2275,6 +2955,22 @@ function extractParamsType(method, sourceFile, project) {
2275
2955
  }
2276
2956
  return entries.length > 0 ? `{ ${entries.join("; ")} }` : null;
2277
2957
  }
2958
+ function extractPipedParamTypes(method, project) {
2959
+ const types = {};
2960
+ for (const param of method.getParameters()) {
2961
+ const paramDecorator = param.getDecorators().find((d) => d.getName() === "Param");
2962
+ if (!paramDecorator) continue;
2963
+ const piped = pipeSchemaOf(paramDecorator, project);
2964
+ if (!piped) continue;
2965
+ const name = namedField(paramDecorator);
2966
+ if (name !== null) {
2967
+ types[name] = piped.type;
2968
+ } else {
2969
+ for (const field of piped.fields ?? []) types[field.name] = field.type;
2970
+ }
2971
+ }
2972
+ return Object.keys(types).length > 0 ? types : null;
2973
+ }
2278
2974
  function extractUploadedFiles(method) {
2279
2975
  const FILE = "File | Blob";
2280
2976
  const entries = [];
@@ -2288,28 +2984,28 @@ function extractUploadedFiles(method) {
2288
2984
  for (const decorator of method.getDecorators()) {
2289
2985
  if (decorator.getName() !== "UseInterceptors") continue;
2290
2986
  for (const arg of decorator.getArguments()) {
2291
- if (!Node7.isCallExpression(arg)) continue;
2987
+ if (!Node10.isCallExpression(arg)) continue;
2292
2988
  const interceptor = arg.getExpression().getText();
2293
2989
  const callArgs = arg.getArguments();
2294
2990
  const firstArg2 = callArgs[0];
2295
2991
  if (interceptor === "FileInterceptor") {
2296
- if (firstArg2 && Node7.isStringLiteral(firstArg2)) {
2992
+ if (firstArg2 && Node10.isStringLiteral(firstArg2)) {
2297
2993
  entries.push(`${firstArg2.getLiteralValue()}: ${FILE}`);
2298
2994
  multipart = true;
2299
2995
  }
2300
2996
  } else if (interceptor === "FilesInterceptor") {
2301
- if (firstArg2 && Node7.isStringLiteral(firstArg2)) {
2997
+ if (firstArg2 && Node10.isStringLiteral(firstArg2)) {
2302
2998
  entries.push(`${firstArg2.getLiteralValue()}: Array<${FILE}>`);
2303
2999
  multipart = true;
2304
3000
  }
2305
3001
  } else if (interceptor === "FileFieldsInterceptor") {
2306
- if (firstArg2 && Node7.isArrayLiteralExpression(firstArg2)) {
3002
+ if (firstArg2 && Node10.isArrayLiteralExpression(firstArg2)) {
2307
3003
  for (const el of firstArg2.getElements()) {
2308
- if (!Node7.isObjectLiteralExpression(el)) continue;
3004
+ if (!Node10.isObjectLiteralExpression(el)) continue;
2309
3005
  const nameProp = el.getProperty("name");
2310
- if (nameProp && Node7.isPropertyAssignment(nameProp)) {
3006
+ if (nameProp && Node10.isPropertyAssignment(nameProp)) {
2311
3007
  const init = nameProp.getInitializer();
2312
- if (init && Node7.isStringLiteral(init)) {
3008
+ if (init && Node10.isStringLiteral(init)) {
2313
3009
  entries.push(`${init.getLiteralValue()}: Array<${FILE}>`);
2314
3010
  }
2315
3011
  }
@@ -2329,13 +3025,13 @@ function extractResponseType(method, sourceFile, project) {
2329
3025
  if (apiResponseDecorator) {
2330
3026
  const args = apiResponseDecorator.getArguments();
2331
3027
  const optsArg = args[0];
2332
- if (optsArg && Node7.isObjectLiteralExpression(optsArg)) {
3028
+ if (optsArg && Node10.isObjectLiteralExpression(optsArg)) {
2333
3029
  for (const prop of optsArg.getProperties()) {
2334
- if (!Node7.isPropertyAssignment(prop)) continue;
3030
+ if (!Node10.isPropertyAssignment(prop)) continue;
2335
3031
  if (prop.getName() !== "type") continue;
2336
3032
  const val = prop.getInitializer();
2337
3033
  if (!val) continue;
2338
- if (Node7.isArrayLiteralExpression(val)) {
3034
+ if (Node10.isArrayLiteralExpression(val)) {
2339
3035
  const elements = val.getElements();
2340
3036
  const firstEl = elements[0];
2341
3037
  if (elements.length > 0 && firstEl !== void 0) {
@@ -2356,24 +3052,24 @@ function extractResponseType(method, sourceFile, project) {
2356
3052
  }
2357
3053
  function apiResponseStatus(decorator) {
2358
3054
  const optsArg = decorator.getArguments()[0];
2359
- if (!optsArg || !Node7.isObjectLiteralExpression(optsArg)) return null;
3055
+ if (!optsArg || !Node10.isObjectLiteralExpression(optsArg)) return null;
2360
3056
  for (const prop of optsArg.getProperties()) {
2361
- if (!Node7.isPropertyAssignment(prop)) continue;
3057
+ if (!Node10.isPropertyAssignment(prop)) continue;
2362
3058
  if (prop.getName() !== "status") continue;
2363
3059
  const val = prop.getInitializer();
2364
- if (val && Node7.isNumericLiteral(val)) return Number(val.getLiteralValue());
3060
+ if (val && Node10.isNumericLiteral(val)) return Number(val.getLiteralValue());
2365
3061
  }
2366
3062
  return null;
2367
3063
  }
2368
3064
  function apiResponseTypeNode(decorator) {
2369
3065
  const optsArg = decorator.getArguments()[0];
2370
- if (!optsArg || !Node7.isObjectLiteralExpression(optsArg)) return null;
3066
+ if (!optsArg || !Node10.isObjectLiteralExpression(optsArg)) return null;
2371
3067
  for (const prop of optsArg.getProperties()) {
2372
- if (!Node7.isPropertyAssignment(prop)) continue;
3068
+ if (!Node10.isPropertyAssignment(prop)) continue;
2373
3069
  if (prop.getName() !== "type") continue;
2374
3070
  const val = prop.getInitializer();
2375
3071
  if (!val) return null;
2376
- if (Node7.isArrayLiteralExpression(val)) {
3072
+ if (Node10.isArrayLiteralExpression(val)) {
2377
3073
  const first = val.getElements()[0];
2378
3074
  return first ? { node: first, isArray: true } : null;
2379
3075
  }
@@ -2391,7 +3087,7 @@ function extractErrorType(method, sourceFile, project) {
2391
3087
  const inner = resolveIdentifierToClassType(typeInfo.node, sourceFile, project, 3);
2392
3088
  const type = typeInfo.isArray ? `Array<${inner}>` : inner;
2393
3089
  let ref = null;
2394
- if (Node7.isIdentifier(typeInfo.node)) {
3090
+ if (Node10.isIdentifier(typeInfo.node)) {
2395
3091
  const name = typeInfo.node.getText();
2396
3092
  const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
2397
3093
  if (localDecl?.isExported()) {
@@ -2408,7 +3104,7 @@ function extractErrorType(method, sourceFile, project) {
2408
3104
  return null;
2409
3105
  }
2410
3106
  function resolveIdentifierToClassType(node, sourceFile, project, depth) {
2411
- if (!Node7.isIdentifier(node)) return "unknown";
3107
+ if (!Node10.isIdentifier(node)) return "unknown";
2412
3108
  const name = node.getText();
2413
3109
  const resolved = findType(name, sourceFile, project);
2414
3110
  if (resolved) {
@@ -2428,9 +3124,9 @@ var STREAM_ENVELOPES = /* @__PURE__ */ new Set(["MessageEvent", "MessageEventLik
2428
3124
  var BINARY_RESPONSE_TYPES = /* @__PURE__ */ new Set(["StreamableFile", "Buffer"]);
2429
3125
  function detectBinaryResponse(method) {
2430
3126
  const node = unwrapNamedContainer(method.getReturnTypeNode(), /* @__PURE__ */ new Set(["Promise"]));
2431
- if (!node || !Node7.isTypeReference(node)) return false;
3127
+ if (!node || !Node10.isTypeReference(node)) return false;
2432
3128
  const typeName = node.getTypeName();
2433
- const name = Node7.isIdentifier(typeName) ? typeName.getText() : "";
3129
+ const name = Node10.isIdentifier(typeName) ? typeName.getText() : "";
2434
3130
  return BINARY_RESPONSE_TYPES.has(name);
2435
3131
  }
2436
3132
  function detectStreamElement(method) {
@@ -2445,9 +3141,9 @@ function detectStreamElement(method) {
2445
3141
  return null;
2446
3142
  }
2447
3143
  function streamContainerElement(node) {
2448
- if (!node || !Node7.isTypeReference(node)) return null;
3144
+ if (!node || !Node10.isTypeReference(node)) return null;
2449
3145
  const typeName = node.getTypeName();
2450
- const name = Node7.isIdentifier(typeName) ? typeName.getText() : "";
3146
+ const name = Node10.isIdentifier(typeName) ? typeName.getText() : "";
2451
3147
  if (STREAM_CONTAINERS.has(name) || STREAM_CONTAINERS_GENERATOR.has(name)) {
2452
3148
  return node.getTypeArguments()[0] ?? null;
2453
3149
  }
@@ -2457,9 +3153,9 @@ function hasAsQueryDecorator(method) {
2457
3153
  return method.getDecorators().some((d) => d.getName() === "AsQuery");
2458
3154
  }
2459
3155
  function unwrapNamedContainer(node, names) {
2460
- if (!node || !Node7.isTypeReference(node)) return node;
3156
+ if (!node || !Node10.isTypeReference(node)) return node;
2461
3157
  const typeName = node.getTypeName();
2462
- const name = Node7.isIdentifier(typeName) ? typeName.getText() : "";
3158
+ const name = Node10.isIdentifier(typeName) ? typeName.getText() : "";
2463
3159
  if (names.has(name)) {
2464
3160
  return node.getTypeArguments()[0] ?? node;
2465
3161
  }
@@ -2480,19 +3176,20 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2480
3176
  body = body ?? bodyType;
2481
3177
  }
2482
3178
  const paramsType = extractParamsType(method, sourceFile, project);
3179
+ const paramTypes = extractPipedParamTypes(method, project);
2483
3180
  const response = isStream ? resolveTypeNodeToString(streamElement, sourceFile, project, 3) : extractResponseType(method, sourceFile, project);
2484
3181
  const errorInfo = extractErrorType(method, sourceFile, project);
2485
- if (body === null && query === null && paramsType === null && response === "unknown" && errorInfo === null && filterInfo === null && !isStream && !uploads.multipart && !binaryResponse && !asQuery) {
3182
+ if (body === null && query === null && paramsType === null && paramTypes === null && response === "unknown" && errorInfo === null && filterInfo === null && !isStream && !uploads.multipart && !binaryResponse && !asQuery) {
2486
3183
  return null;
2487
3184
  }
2488
3185
  let bodyRef = null;
2489
3186
  let queryRef = null;
2490
3187
  let responseRef = null;
2491
3188
  for (const param of method.getParameters()) {
2492
- if (param.getDecorators().some((d) => d.getName() === "Body") && param.getTypeNode()) {
3189
+ if (param.getDecorators().some((d) => d.getName() === "Body") && param.getTypeNode() && !hasPipeSchema(param, "Body", project)) {
2493
3190
  bodyRef = resolveBodyQueryResponseRef(param.getTypeNode(), sourceFile, project);
2494
3191
  }
2495
- if (param.getDecorators().some((d) => d.getName() === "Query") && param.getTypeNode()) {
3192
+ if (param.getDecorators().some((d) => d.getName() === "Query") && param.getTypeNode() && !hasPipeSchema(param, "Query", project)) {
2496
3193
  queryRef = resolveBodyQueryResponseRef(param.getTypeNode(), sourceFile, project);
2497
3194
  }
2498
3195
  }
@@ -2505,11 +3202,11 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2505
3202
  if (apiResp) {
2506
3203
  const args = apiResp.getArguments();
2507
3204
  const optsArg = args[0];
2508
- if (optsArg && Node7.isObjectLiteralExpression(optsArg)) {
3205
+ if (optsArg && Node10.isObjectLiteralExpression(optsArg)) {
2509
3206
  for (const prop of optsArg.getProperties()) {
2510
- if (Node7.isPropertyAssignment(prop) && prop.getName() === "type") {
3207
+ if (Node10.isPropertyAssignment(prop) && prop.getName() === "type") {
2511
3208
  const val = prop.getInitializer();
2512
- if (val && Node7.isIdentifier(val)) {
3209
+ if (val && Node10.isIdentifier(val)) {
2513
3210
  const name = val.getText();
2514
3211
  const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
2515
3212
  if (localDecl?.isExported()) {
@@ -2545,6 +3242,7 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2545
3242
  response,
2546
3243
  error: errorInfo?.type ?? null,
2547
3244
  params: paramsType,
3245
+ paramTypes,
2548
3246
  queryRef,
2549
3247
  bodyRef,
2550
3248
  responseRef,
@@ -2565,6 +3263,7 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2565
3263
  function resolveParamClass(method, decoratorName, sourceFile, project) {
2566
3264
  for (const param of method.getParameters()) {
2567
3265
  if (!param.getDecorators().some((d) => d.getName() === decoratorName)) continue;
3266
+ if (hasPipeSchema(param, decoratorName, project)) continue;
2568
3267
  const typeNode = param.getTypeNode();
2569
3268
  if (!typeNode) continue;
2570
3269
  const text = typeNode.getText().replace(/\[\]$/, "");
@@ -2577,129 +3276,6 @@ function resolveParamClass(method, decoratorName, sourceFile, project) {
2577
3276
  return null;
2578
3277
  }
2579
3278
 
2580
- // src/discovery/zod-ast-to-ts.ts
2581
- import { Node as Node8, SyntaxKind as SyntaxKind4 } from "ts-morph";
2582
- function zodAstToTs(node) {
2583
- if (!Node8.isCallExpression(node)) return "unknown";
2584
- const expr = node.getExpression();
2585
- if (Node8.isPropertyAccessExpression(expr)) {
2586
- const methodName = expr.getName();
2587
- const receiver = expr.getExpression();
2588
- if (methodName === "optional") {
2589
- return `${zodAstToTs(receiver)} | undefined`;
2590
- }
2591
- if (methodName === "nullable") {
2592
- return `${zodAstToTs(receiver)} | null`;
2593
- }
2594
- const args = node.getArguments();
2595
- switch (methodName) {
2596
- case "string":
2597
- return "string";
2598
- case "number":
2599
- return "number";
2600
- case "boolean":
2601
- return "boolean";
2602
- case "unknown":
2603
- return "unknown";
2604
- case "any":
2605
- return "unknown";
2606
- case "literal": {
2607
- const lit = args[0];
2608
- if (!lit) return "unknown";
2609
- if (Node8.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());
2610
- if (Node8.isNumericLiteral(lit)) return lit.getLiteralValue().toString();
2611
- if (lit.getKind() === SyntaxKind4.TrueKeyword) return "true";
2612
- if (lit.getKind() === SyntaxKind4.FalseKeyword) return "false";
2613
- return "unknown";
2614
- }
2615
- case "enum": {
2616
- const arrArg = args[0];
2617
- if (!arrArg || !Node8.isArrayLiteralExpression(arrArg)) return "unknown";
2618
- const members = arrArg.getElements().map(
2619
- (el) => Node8.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : "unknown"
2620
- );
2621
- return members.join(" | ");
2622
- }
2623
- case "array": {
2624
- const inner = args[0];
2625
- if (!inner) return "unknown";
2626
- return `Array<${zodAstToTs(inner)}>`;
2627
- }
2628
- case "object": {
2629
- const objArg = args[0];
2630
- if (!objArg || !Node8.isObjectLiteralExpression(objArg)) return "unknown";
2631
- const lines = [];
2632
- for (const prop of objArg.getProperties()) {
2633
- if (!Node8.isPropertyAssignment(prop)) continue;
2634
- const key = prop.getName();
2635
- const valNode = prop.getInitializer();
2636
- if (!valNode) continue;
2637
- const tsType = zodAstToTs(valNode);
2638
- const isOpt = isOptionalChain(valNode);
2639
- lines.push(`${key}${isOpt ? "?" : ""}: ${tsType}`);
2640
- }
2641
- return `{ ${lines.join("; ")} }`;
2642
- }
2643
- case "union": {
2644
- const arrArg = args[0];
2645
- if (!arrArg || !Node8.isArrayLiteralExpression(arrArg)) return "unknown";
2646
- return arrArg.getElements().map(zodAstToTs).join(" | ");
2647
- }
2648
- case "record": {
2649
- const valArg = args.length === 1 ? args[0] : args[1];
2650
- if (!valArg) return "unknown";
2651
- return `Record<string, ${zodAstToTs(valArg)}>`;
2652
- }
2653
- case "tuple": {
2654
- const arrArg = args[0];
2655
- if (!arrArg || !Node8.isArrayLiteralExpression(arrArg)) return "unknown";
2656
- return `[${arrArg.getElements().map(zodAstToTs).join(", ")}]`;
2657
- }
2658
- default:
2659
- return "unknown";
2660
- }
2661
- }
2662
- return "unknown";
2663
- }
2664
- function isOptionalChain(node) {
2665
- if (!Node8.isCallExpression(node)) return false;
2666
- const expr = node.getExpression();
2667
- return Node8.isPropertyAccessExpression(expr) && expr.getName() === "optional";
2668
- }
2669
- function parseDefineContractCall(callExpr) {
2670
- if (!Node8.isCallExpression(callExpr)) return null;
2671
- const callee = callExpr.getExpression();
2672
- const calleeName = Node8.isIdentifier(callee) ? callee.getText() : Node8.isPropertyAccessExpression(callee) ? callee.getName() : "";
2673
- if (calleeName !== "defineContract") return null;
2674
- const args = callExpr.getArguments();
2675
- const optsArg = args[0];
2676
- if (!optsArg || !Node8.isObjectLiteralExpression(optsArg)) return null;
2677
- let query = null;
2678
- let body = null;
2679
- let response = "unknown";
2680
- let error = null;
2681
- let bodyZodText = null;
2682
- let queryZodText = null;
2683
- for (const prop of optsArg.getProperties()) {
2684
- if (!Node8.isPropertyAssignment(prop)) continue;
2685
- const propName = prop.getName();
2686
- const val = prop.getInitializer();
2687
- if (!val) continue;
2688
- if (propName === "query") {
2689
- query = zodAstToTs(val);
2690
- queryZodText = val.getText();
2691
- } else if (propName === "body") {
2692
- body = zodAstToTs(val);
2693
- bodyZodText = val.getText();
2694
- } else if (propName === "response") {
2695
- response = zodAstToTs(val);
2696
- } else if (propName === "error") {
2697
- error = zodAstToTs(val);
2698
- }
2699
- }
2700
- return { query, body, response, error, bodyZodText, queryZodText };
2701
- }
2702
-
2703
3279
  // src/discovery/contracts-fast.ts
2704
3280
  async function discoverContractsFast(opts) {
2705
3281
  const { cwd, glob, tsconfig } = opts;
@@ -2712,7 +3288,9 @@ async function discoverContractsFast(opts) {
2712
3288
  }
2713
3289
  bindDiscoveryContext(project, cwd, tsconfigPath, loaded);
2714
3290
  clearMixinTypeProject();
2715
- return extractAllRoutes(project);
3291
+ const routes = extractAllRoutes(project);
3292
+ clearSchemaTypeProject(project);
3293
+ return routes;
2716
3294
  }
2717
3295
  function resolveTsconfigPath(cwd, tsconfig) {
2718
3296
  return tsconfig ? resolve3(tsconfig) : join4(cwd, "tsconfig.json");
@@ -2724,25 +3302,25 @@ var NO_TSCONFIG_OPTIONS = {
2724
3302
  };
2725
3303
  function loadDiscoveryTsconfig(tsconfigPath) {
2726
3304
  if (!existsSync(tsconfigPath)) return { options: null, files: [] };
2727
- const read = ts.readConfigFile(tsconfigPath, (path) => ts.sys.readFile(path));
3305
+ const read = ts3.readConfigFile(tsconfigPath, (path) => ts3.sys.readFile(path));
2728
3306
  if (read.error) {
2729
3307
  return {
2730
3308
  options: null,
2731
3309
  files: [tsconfigPath],
2732
- error: ts.flattenDiagnosticMessageText(read.error.messageText, " ")
3310
+ error: ts3.flattenDiagnosticMessageText(read.error.messageText, " ")
2733
3311
  };
2734
3312
  }
2735
3313
  const host = {
2736
- useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
3314
+ useCaseSensitiveFileNames: ts3.sys.useCaseSensitiveFileNames,
2737
3315
  // The one line that keeps a tsconfig from being a filesystem walk.
2738
3316
  readDirectory: () => [],
2739
- fileExists: (path) => ts.sys.fileExists(path),
3317
+ fileExists: (path) => ts3.sys.fileExists(path),
2740
3318
  // `extends` is resolved through the host, so a consumer whose `paths` live
2741
3319
  // in a base tsconfig keeps working.
2742
- readFile: (path) => ts.sys.readFile(path)
3320
+ readFile: (path) => ts3.sys.readFile(path)
2743
3321
  };
2744
- const sourceFile = ts.readJsonConfigFile(tsconfigPath, (path) => ts.sys.readFile(path));
2745
- const parsed = ts.parseJsonSourceFileConfigFileContent(
3322
+ const sourceFile = ts3.readJsonConfigFile(tsconfigPath, (path) => ts3.sys.readFile(path));
3323
+ const parsed = ts3.parseJsonSourceFileConfigFileContent(
2746
3324
  sourceFile,
2747
3325
  host,
2748
3326
  dirname2(tsconfigPath),
@@ -2765,7 +3343,7 @@ function createDiscoveryProject(tsconfigPath, tsconfig = loadDiscoveryTsconfig(t
2765
3343
  `[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.`
2766
3344
  );
2767
3345
  }
2768
- return new Project3({
3346
+ return new Project4({
2769
3347
  compilerOptions: tsconfig.options ?? { ...NO_TSCONFIG_OPTIONS },
2770
3348
  skipAddingFilesFromTsConfig: true,
2771
3349
  skipLoadingLibFiles: true,
@@ -2877,15 +3455,16 @@ var PersistentDiscovery = class _PersistentDiscovery {
2877
3455
  clearTypeResolutionCaches(this.project);
2878
3456
  clearEnumCache(this.project);
2879
3457
  clearMixinTypeProject();
3458
+ clearSchemaTypeProject(this.project);
2880
3459
  return extractRoutesFrom(this.project, this.controllerPaths);
2881
3460
  }
2882
3461
  };
2883
3462
  function decoratorStringArg(decoratorExpr) {
2884
3463
  if (!decoratorExpr) return void 0;
2885
- if (Node9.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();
2886
- if (Node9.isArrayLiteralExpression(decoratorExpr)) {
3464
+ if (Node11.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();
3465
+ if (Node11.isArrayLiteralExpression(decoratorExpr)) {
2887
3466
  const first = decoratorExpr.getElements()[0];
2888
- if (first && Node9.isStringLiteral(first)) return first.getLiteralValue();
3467
+ if (first && Node11.isStringLiteral(first)) return first.getLiteralValue();
2889
3468
  }
2890
3469
  return void 0;
2891
3470
  }
@@ -3006,9 +3585,9 @@ function extractContractRoute(args) {
3006
3585
  let contractDef = null;
3007
3586
  let bodyZodRef = null;
3008
3587
  let queryZodRef = null;
3009
- if (Node9.isCallExpression(firstDecoratorArg)) {
3010
- contractDef = parseDefineContractCall(firstDecoratorArg);
3011
- } else if (Node9.isIdentifier(firstDecoratorArg)) {
3588
+ if (Node11.isCallExpression(firstDecoratorArg)) {
3589
+ contractDef = parseDefineContractCall(firstDecoratorArg, project);
3590
+ } else if (Node11.isIdentifier(firstDecoratorArg)) {
3012
3591
  const identName = firstDecoratorArg.getText();
3013
3592
  const resolvedVar = resolveImportedVariable(identName, sourceFile, project);
3014
3593
  if (!resolvedVar) {
@@ -3020,7 +3599,7 @@ function extractContractRoute(args) {
3020
3599
  const { decl: varDecl, file: declFile } = resolvedVar;
3021
3600
  const initializer = varDecl.getInitializer();
3022
3601
  if (!initializer) return null;
3023
- contractDef = parseDefineContractCall(initializer);
3602
+ contractDef = parseDefineContractCall(initializer, project);
3024
3603
  if (contractDef && varDecl.isExported()) {
3025
3604
  const filePath = declFile.getFilePath();
3026
3605
  if (contractDef.body !== null) {
@@ -3091,6 +3670,7 @@ function extractDtoRoute(args) {
3091
3670
  body: dtoContract?.body ?? null,
3092
3671
  response: mixinResponse ?? dtoContract?.response ?? "unknown",
3093
3672
  error: dtoContract?.error ?? null,
3673
+ paramTypes: dtoContract?.paramTypes ?? null,
3094
3674
  queryRef: dtoContract?.queryRef ?? null,
3095
3675
  bodyRef: dtoContract?.bodyRef ?? null,
3096
3676
  responseRef: dtoContract?.responseRef ?? null,
@@ -3213,7 +3793,7 @@ function createExtensionContext(config, getRoutes, trackedInputs) {
3213
3793
  },
3214
3794
  project() {
3215
3795
  if (!project) {
3216
- project = new Project4({
3796
+ project = new Project5({
3217
3797
  skipAddingFilesFromTsConfig: true,
3218
3798
  skipLoadingLibFiles: true,
3219
3799
  skipFileDependencyResolution: true,
@@ -3331,10 +3911,11 @@ function insertIntoTree(tree, segments, leaf, fullName) {
3331
3911
  insertIntoTree(branch.children, rest, leaf, fullName);
3332
3912
  }
3333
3913
  }
3334
- function buildParamsType(params) {
3914
+ function buildParamsType(params, paramTypes) {
3335
3915
  const pathParams = params.filter((p) => p.source === "path");
3336
3916
  if (pathParams.length === 0) return "never";
3337
- return `{ ${pathParams.map((p) => `${p.name}: string`).join("; ")} }`;
3917
+ const typeOf = (name) => paramTypes && Object.hasOwn(paramTypes, name) && paramTypes[name] || "string";
3918
+ return `{ ${pathParams.map((p) => `${p.name}: ${typeOf(p.name)}`).join("; ")} }`;
3338
3919
  }
3339
3920
  function hasPathParams(params) {
3340
3921
  return params.some((p) => p.source === "path");
@@ -3428,7 +4009,7 @@ function emitRouterTypeBlock(tree, indent, outDir, serialization) {
3428
4009
  }
3429
4010
  const response = buildResponseType(c, outDir, serialization);
3430
4011
  const error = buildErrorType(c);
3431
- const params = buildParamsType(c.params);
4012
+ const params = buildParamsType(c.params, c.contractSource.paramTypes);
3432
4013
  const safeMethod = JSON.stringify(method);
3433
4014
  const safeUrl = JSON.stringify(c.path);
3434
4015
  const filterLiterals = filterFieldLiterals(c.contractSource.filterFields);
@@ -3697,6 +4278,9 @@ var EMPTY_PATH_NAMESPACE = [
3697
4278
  "}",
3698
4279
  ""
3699
4280
  ];
4281
+ function isClientCallable(route) {
4282
+ return route.method.toUpperCase() !== "ALL";
4283
+ }
3700
4284
  function buildApiFile(routes, outDir, opts = {}) {
3701
4285
  const fetcherImportPath = opts.fetcherImportPath;
3702
4286
  const serialization = opts.serialization ?? "json";
@@ -3704,7 +4288,7 @@ function buildApiFile(routes, outDir, opts = {}) {
3704
4288
  const { layer } = resolveApiSlots(extensions);
3705
4289
  const memberExts = extensions.filter((e) => e.apiMembers);
3706
4290
  const headerExts = extensions.filter((e) => e.apiHeader);
3707
- const contracted = routes.filter((r) => r.contract);
4291
+ const contracted = routes.filter((r) => r.contract && isClientCallable(r));
3708
4292
  const ctx = opts.ctx ?? {
3709
4293
  cwd: outDir ?? "",
3710
4294
  outDir: outDir ?? "",
@@ -4622,6 +5206,7 @@ function buildOpenApiSpec(routes, opts = {}) {
4622
5206
  const paths = {};
4623
5207
  for (const route of routes) {
4624
5208
  if (!route.contract) continue;
5209
+ if (route.method.toUpperCase() === "ALL") continue;
4625
5210
  const oaPath = toOpenApiPath(route.path);
4626
5211
  const method = route.method.toLowerCase();
4627
5212
  let pathItem = paths[oaPath];
@@ -5281,7 +5866,7 @@ async function watch(config, onChange, options = {}) {
5281
5866
  }
5282
5867
 
5283
5868
  // src/index.ts
5284
- var VERSION = "0.25.1";
5869
+ var VERSION = "0.26.0";
5285
5870
 
5286
5871
  // src/cli/codegen.ts
5287
5872
  async function runCodegen(opts = {}) {