@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.
@@ -187,10 +187,10 @@ var import_fast_glob3 = __toESM(require("fast-glob"), 1);
187
187
  var import_node_fs = require("fs");
188
188
  var import_node_path3 = require("path");
189
189
  var import_fast_glob = __toESM(require("fast-glob"), 1);
190
- var import_ts_morph8 = require("ts-morph");
190
+ var import_ts_morph11 = require("ts-morph");
191
191
 
192
192
  // src/discovery/dto-type-resolver.ts
193
- var import_ts_morph6 = require("ts-morph");
193
+ var import_ts_morph10 = require("ts-morph");
194
194
 
195
195
  // src/discovery/dto-to-ir.ts
196
196
  var import_ts_morph2 = require("ts-morph");
@@ -1718,6 +1718,672 @@ function extractFilterableEntityFields(filterClass, project, entityOverride, pre
1718
1718
  return fields;
1719
1719
  }
1720
1720
 
1721
+ // src/discovery/pipe-schema.ts
1722
+ var import_ts_morph9 = require("ts-morph");
1723
+
1724
+ // src/discovery/schema-type-inference.ts
1725
+ var import_ts_morph7 = require("ts-morph");
1726
+
1727
+ // src/discovery/schema-type-program.ts
1728
+ var import_ts_morph6 = require("ts-morph");
1729
+ var PARAM_DECORATORS = /* @__PURE__ */ new Set(["Body", "Query", "Param"]);
1730
+ var SchemaTypeProgram = class {
1731
+ constructor(discovery) {
1732
+ this.discovery = discovery;
1733
+ const base = discovery.getCompilerOptions();
1734
+ this.options = {
1735
+ ...base,
1736
+ // A tsconfig-less consumer gets ES5 by default, whose lib has no `Map`/`Set`/
1737
+ // `Promise` for the schema libraries' declarations to lean on.
1738
+ target: base.target ?? import_ts_morph6.ts.ScriptTarget.ES2022,
1739
+ // With neither set, resolve the way a bundler does: package `exports`
1740
+ // (`zod/v4`) and extensionless or `.js` relative imports all resolve.
1741
+ ...base.module === void 0 && base.moduleResolution === void 0 ? { module: import_ts_morph6.ts.ModuleKind.ESNext, moduleResolution: import_ts_morph6.ts.ModuleResolutionKind.Bundler } : {},
1742
+ // Without it `.nullable()` and `.optional()` would erase to the bare type.
1743
+ strictNullChecks: true,
1744
+ // No ambient `@types/*` (a tsconfig's `types: ['node']`): a schema does not
1745
+ // need them, and they are a hundred-odd files of program to build.
1746
+ types: [],
1747
+ noEmit: true
1748
+ };
1749
+ this.project = new import_ts_morph6.Project({
1750
+ skipAddingFilesFromTsConfig: true,
1751
+ compilerOptions: this.options
1752
+ });
1753
+ for (const sf of discovery.getSourceFiles()) this.request(sf.getFilePath(), { schema: true });
1754
+ this.flush();
1755
+ }
1756
+ project;
1757
+ options;
1758
+ /** Parses a file that is not in discovery's Project, without adding it there. */
1759
+ scratch = new import_ts_morph6.Project({
1760
+ skipAddingFilesFromTsConfig: true,
1761
+ skipLoadingLibFiles: true,
1762
+ skipFileDependencyResolution: true
1763
+ });
1764
+ needs = /* @__PURE__ */ new Map();
1765
+ /** Pruned text per file, as last written into {@link project}. */
1766
+ written = /* @__PURE__ */ new Map();
1767
+ /**
1768
+ * The typed copy of a discovery file, with its schema positions kept. Adding one
1769
+ * that was not there yet (a contract file discovery reached lazily) rebuilds the
1770
+ * program once.
1771
+ */
1772
+ sourceFileFor(sf) {
1773
+ this.request(sf.getFilePath(), { schema: true });
1774
+ this.flush();
1775
+ return this.project.getSourceFile(sf.getFilePath());
1776
+ }
1777
+ // -------------------------------------------------------------------------
1778
+ queue = [];
1779
+ request(path, want) {
1780
+ let needs = this.needs.get(path);
1781
+ const isNew = !needs;
1782
+ needs ??= { schema: false, all: false, names: /* @__PURE__ */ new Set() };
1783
+ let grew = isNew;
1784
+ if (want.schema && !needs.schema) {
1785
+ needs.schema = true;
1786
+ grew = true;
1787
+ }
1788
+ if (want.all && !needs.all) {
1789
+ needs.all = true;
1790
+ grew = true;
1791
+ }
1792
+ for (const name of want.names ?? []) {
1793
+ if (!needs.names.has(name)) {
1794
+ needs.names.add(name);
1795
+ grew = true;
1796
+ }
1797
+ }
1798
+ this.needs.set(path, needs);
1799
+ if (grew) this.queue.push(path);
1800
+ }
1801
+ /** Run the worklist to a fixpoint, then write every changed file into the program. */
1802
+ flush() {
1803
+ const changed = /* @__PURE__ */ new Map();
1804
+ while (this.queue.length > 0) {
1805
+ const path = this.queue.pop();
1806
+ const original = this.original(path);
1807
+ if (!original) continue;
1808
+ const needs = this.needs.get(path);
1809
+ const text = this.prune(original, needs);
1810
+ if (this.written.get(path) !== text) changed.set(path, text);
1811
+ }
1812
+ for (const [path, text] of changed) {
1813
+ this.project.createSourceFile(path, text, { overwrite: true });
1814
+ this.written.set(path, text);
1815
+ }
1816
+ }
1817
+ /** The file as discovery sees it (its in-memory text), else as it is on disk. */
1818
+ original(path) {
1819
+ return this.discovery.getSourceFile(path) ?? this.scratch.getSourceFile(path) ?? this.scratch.addSourceFileAtPathIfExists(path);
1820
+ }
1821
+ /**
1822
+ * `sf`'s text with every import/re-export nothing in `needs` references blanked,
1823
+ * requesting from each kept one's target the names it brings in.
1824
+ */
1825
+ prune(sf, needs) {
1826
+ const locals = topLevelDeclarations(sf);
1827
+ const roots = [];
1828
+ if (needs.all) roots.push(...sf.getStatements());
1829
+ if (needs.schema) roots.push(...schemaPositions(sf));
1830
+ const reexported = /* @__PURE__ */ new Map();
1831
+ for (const exp of sf.getExportDeclarations()) {
1832
+ const spec = exp.getModuleSpecifierValue();
1833
+ if (spec === void 0) {
1834
+ for (const named of exp.getNamedExports()) {
1835
+ const exposed = (named.getAliasNode() ?? named.getNameNode()).getText();
1836
+ if (needs.all || needs.names.has(exposed)) roots.push(named.getNameNode());
1837
+ }
1838
+ continue;
1839
+ }
1840
+ if (exp.isNamespaceExport() || exp.getNamedExports().length === 0) continue;
1841
+ for (const named of exp.getNamedExports()) {
1842
+ const exposed = (named.getAliasNode() ?? named.getNameNode()).getText();
1843
+ const list = reexported.get(exposed) ?? [];
1844
+ list.push({ from: spec, name: named.getNameNode().getText() });
1845
+ reexported.set(exposed, list);
1846
+ }
1847
+ }
1848
+ const unresolvedNames = [];
1849
+ for (const name of needs.names) {
1850
+ const decls = name === "default" ? defaultExport(sf) : locals.get(name) ?? [];
1851
+ if (decls.length > 0) roots.push(...decls);
1852
+ else if (!reexported.has(name)) unresolvedNames.push(name);
1853
+ }
1854
+ const referenced = /* @__PURE__ */ new Set();
1855
+ const queue = [...roots];
1856
+ const seen = new Set(queue);
1857
+ while (queue.length > 0) {
1858
+ const node = queue.pop();
1859
+ const ids = import_ts_morph6.Node.isIdentifier(node) ? [node] : node.getDescendantsOfKind(import_ts_morph6.ts.SyntaxKind.Identifier);
1860
+ for (const id of ids) {
1861
+ const name = id.getText();
1862
+ if (referenced.has(name)) continue;
1863
+ referenced.add(name);
1864
+ for (const local of locals.get(name) ?? []) {
1865
+ if (seen.has(local)) continue;
1866
+ seen.add(local);
1867
+ queue.push(local);
1868
+ }
1869
+ }
1870
+ }
1871
+ const chars = sf.getFullText().split("");
1872
+ const blank = (node) => {
1873
+ for (let i = node.getStart(); i < node.getEnd(); i++) {
1874
+ if (chars[i] !== "\n" && chars[i] !== "\r") chars[i] = " ";
1875
+ }
1876
+ };
1877
+ for (const decl of sf.getImportDeclarations()) {
1878
+ const target = this.resolve(decl.getModuleSpecifierValue(), sf);
1879
+ const namespace = decl.getNamespaceImport()?.getText();
1880
+ const def = decl.getDefaultImport()?.getText();
1881
+ const named = decl.getNamedImports().map((n) => ({
1882
+ local: (n.getAliasNode() ?? n.getNameNode()).getText(),
1883
+ imported: n.getName()
1884
+ })).filter((n) => referenced.has(n.local));
1885
+ const wantsNamespace = namespace !== void 0 && referenced.has(namespace);
1886
+ const wantsDefault = def !== void 0 && referenced.has(def);
1887
+ if (!wantsNamespace && !wantsDefault && named.length === 0) {
1888
+ blank(decl);
1889
+ continue;
1890
+ }
1891
+ if (target) {
1892
+ this.request(target, {
1893
+ all: wantsNamespace,
1894
+ names: [...wantsDefault ? ["default"] : [], ...named.map((n) => n.imported)]
1895
+ });
1896
+ }
1897
+ }
1898
+ for (const exp of sf.getExportDeclarations()) {
1899
+ const spec = exp.getModuleSpecifierValue();
1900
+ if (spec === void 0) continue;
1901
+ const target = this.resolve(spec, sf);
1902
+ if (exp.isNamespaceExport() || exp.getNamedExports().length === 0) {
1903
+ if (!needs.all && unresolvedNames.length === 0) {
1904
+ blank(exp);
1905
+ } else if (target) {
1906
+ this.request(target, { all: needs.all, names: unresolvedNames });
1907
+ }
1908
+ continue;
1909
+ }
1910
+ const wanted = exp.getNamedExports().filter(
1911
+ (n) => needs.all || needs.names.has((n.getAliasNode() ?? n.getNameNode()).getText())
1912
+ ).map((n) => n.getNameNode().getText());
1913
+ if (wanted.length === 0) blank(exp);
1914
+ else if (target) this.request(target, { names: wanted });
1915
+ }
1916
+ return chars.join("");
1917
+ }
1918
+ /**
1919
+ * The project source file a module specifier resolves to, or undefined for a
1920
+ * package (read unpruned by the program itself) or an unresolvable one.
1921
+ */
1922
+ resolve(specifier, from) {
1923
+ const resolved = import_ts_morph6.ts.resolveModuleName(
1924
+ specifier,
1925
+ from.getFilePath(),
1926
+ this.options,
1927
+ import_ts_morph6.ts.sys
1928
+ ).resolvedModule;
1929
+ if (!resolved || resolved.isExternalLibraryImport) return void 0;
1930
+ const file = resolved.resolvedFileName;
1931
+ if (file.endsWith(".d.ts") || !/\.(m|c)?tsx?$/.test(file)) return void 0;
1932
+ return file;
1933
+ }
1934
+ };
1935
+ function schemaPositions(sf) {
1936
+ const roots = [];
1937
+ sf.forEachDescendant((node) => {
1938
+ if (import_ts_morph6.Node.isDecorator(node)) {
1939
+ const name = node.getName();
1940
+ if (name === "ApplyContract") {
1941
+ roots.push(...node.getArguments());
1942
+ } else if (PARAM_DECORATORS.has(name)) {
1943
+ for (const arg of node.getArguments()) {
1944
+ if (import_ts_morph6.Node.isNewExpression(arg) || import_ts_morph6.Node.isCallExpression(arg)) {
1945
+ roots.push(...arg.getArguments());
1946
+ }
1947
+ }
1948
+ }
1949
+ } else if (import_ts_morph6.Node.isCallExpression(node)) {
1950
+ const callee = node.getExpression();
1951
+ const name = import_ts_morph6.Node.isIdentifier(callee) ? callee.getText() : import_ts_morph6.Node.isPropertyAccessExpression(callee) ? callee.getName() : void 0;
1952
+ if (name === "defineContract") roots.push(...node.getArguments());
1953
+ }
1954
+ });
1955
+ return roots;
1956
+ }
1957
+ function topLevelDeclarations(sf) {
1958
+ const byName = /* @__PURE__ */ new Map();
1959
+ const add = (name, node) => {
1960
+ if (!name) return;
1961
+ const list = byName.get(name);
1962
+ if (list) list.push(node);
1963
+ else byName.set(name, [node]);
1964
+ };
1965
+ for (const decl of sf.getVariableDeclarations()) add(decl.getName(), decl);
1966
+ for (const decl of sf.getFunctions()) add(decl.getName(), decl);
1967
+ for (const decl of sf.getClasses()) add(decl.getName(), decl);
1968
+ for (const decl of sf.getEnums()) add(decl.getName(), decl);
1969
+ for (const decl of sf.getInterfaces()) add(decl.getName(), decl);
1970
+ for (const decl of sf.getTypeAliases()) add(decl.getName(), decl);
1971
+ for (const decl of sf.getModules()) add(decl.getName(), decl);
1972
+ return byName;
1973
+ }
1974
+ function defaultExport(sf) {
1975
+ const nodes = [];
1976
+ for (const assignment of sf.getExportAssignments()) nodes.push(assignment);
1977
+ for (const fn of sf.getFunctions()) if (fn.isDefaultExport()) nodes.push(fn);
1978
+ for (const cls of sf.getClasses()) if (cls.isDefaultExport()) nodes.push(cls);
1979
+ return nodes;
1980
+ }
1981
+
1982
+ // src/discovery/schema-type-inference.ts
1983
+ var programs = /* @__PURE__ */ new WeakMap();
1984
+ function programFor(discovery) {
1985
+ let program = programs.get(discovery);
1986
+ if (!program) {
1987
+ program = new SchemaTypeProgram(discovery);
1988
+ programs.set(discovery, program);
1989
+ }
1990
+ return program;
1991
+ }
1992
+ function clearSchemaTypeProject(discovery) {
1993
+ programs.delete(discovery);
1994
+ }
1995
+ function counterpart(typedSf, node) {
1996
+ const start = node.getStart();
1997
+ const end = node.getEnd();
1998
+ const kind = node.getKind();
1999
+ let candidate = typedSf.getDescendantAtPos(start);
2000
+ while (candidate) {
2001
+ if (candidate.getStart() === start && candidate.getEnd() === end && candidate.getKind() === kind) {
2002
+ return candidate;
2003
+ }
2004
+ if (candidate.getStart() < start || candidate.getEnd() > end) return void 0;
2005
+ candidate = candidate.getParent();
2006
+ }
2007
+ return void 0;
2008
+ }
2009
+ function propType(type, name, at) {
2010
+ return type.getProperty(name)?.getTypeAtLocation(at);
2011
+ }
2012
+ function isAnyOrUnknown(type) {
2013
+ return type.isAny() || type.isUnknown();
2014
+ }
2015
+ function inferSchema(expr, discovery) {
2016
+ try {
2017
+ const typedSf = programFor(discovery).sourceFileFor(expr.getSourceFile());
2018
+ const at = typedSf && counterpart(typedSf, expr);
2019
+ if (!at) return { kind: "unresolved" };
2020
+ const schemaType = at.getType();
2021
+ if (isAnyOrUnknown(schemaType)) return { kind: "unresolved" };
2022
+ const standard = propType(schemaType, "~standard", at);
2023
+ const stdTypes = standard ? propType(standard, "types", at)?.getNonNullableType() : void 0;
2024
+ const stdInput = stdTypes ? propType(stdTypes, "input", at) : void 0;
2025
+ const stdOutput = stdTypes ? propType(stdTypes, "output", at) : void 0;
2026
+ if (stdInput && stdOutput) {
2027
+ return { kind: "schema", types: { input: stdInput, output: stdOutput, at } };
2028
+ }
2029
+ const zodInput = propType(schemaType, "_input", at);
2030
+ const zodOutput = propType(schemaType, "_output", at);
2031
+ if (zodInput && zodOutput) {
2032
+ return { kind: "schema", types: { input: zodInput, output: zodOutput, at } };
2033
+ }
2034
+ return { kind: "not-schema" };
2035
+ } catch (err) {
2036
+ dbg("schema inference failed:", err);
2037
+ return { kind: "unresolved" };
2038
+ }
2039
+ }
2040
+ var GLOBAL_NAMED_TYPES = /* @__PURE__ */ new Set([
2041
+ "Date",
2042
+ "File",
2043
+ "Blob",
2044
+ "FormData",
2045
+ "URL",
2046
+ "RegExp",
2047
+ "Map",
2048
+ "Set",
2049
+ "ArrayBuffer",
2050
+ "Uint8Array"
2051
+ ]);
2052
+ var MAX_DEPTH = 12;
2053
+ function objectKey(name) {
2054
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name) ? name : JSON.stringify(name);
2055
+ }
2056
+ function isOptionalSymbol(sym) {
2057
+ return (sym.getFlags() & import_ts_morph7.ts.SymbolFlags.Optional) !== 0;
2058
+ }
2059
+ function isSymbolKeyed(sym) {
2060
+ return sym.getName().startsWith("__@");
2061
+ }
2062
+ function orderedProperties(type) {
2063
+ const position = (sym) => {
2064
+ const decl = sym.getDeclarations()[0];
2065
+ return decl ? [decl.getSourceFile().getFilePath(), decl.getStart()] : void 0;
2066
+ };
2067
+ return type.getProperties().map((sym, index) => ({ sym, index, at: position(sym) })).sort((a, b) => {
2068
+ if (a.at && b.at) {
2069
+ if (a.at[0] !== b.at[0]) return a.at[0] < b.at[0] ? -1 : 1;
2070
+ if (a.at[1] !== b.at[1]) return a.at[1] - b.at[1];
2071
+ } else if (a.at || b.at) {
2072
+ return a.at ? -1 : 1;
2073
+ }
2074
+ return a.index - b.index;
2075
+ }).map((entry) => entry.sym);
2076
+ }
2077
+ function isFromDeclarationFile(sym) {
2078
+ const decl = sym?.getDeclarations()[0];
2079
+ return !!decl && decl.getSourceFile().isDeclarationFile();
2080
+ }
2081
+ function render(type, state, paired) {
2082
+ if (state.depth > MAX_DEPTH) return "unknown";
2083
+ if (isAnyOrUnknown(type)) {
2084
+ return paired && !isAnyOrUnknown(paired) ? render(paired, state) : "unknown";
2085
+ }
2086
+ if (type.isNever()) return "never";
2087
+ if (type.isString() || type.isTemplateLiteral()) return "string";
2088
+ if (type.isNumber()) return "number";
2089
+ if (type.isBoolean()) return "boolean";
2090
+ if (type.isBigInt()) return "bigint";
2091
+ if (type.isNull()) return "null";
2092
+ if (type.isUndefined() || type.isVoid()) return "undefined";
2093
+ if (type.isBooleanLiteral()) return type.getText();
2094
+ if (type.isStringLiteral() || type.isNumberLiteral() || type.isEnumLiteral()) {
2095
+ const value = type.getLiteralValue();
2096
+ return typeof value === "string" ? JSON.stringify(value) : String(value);
2097
+ }
2098
+ if (type.isBigIntLiteral()) return type.getText();
2099
+ if (type.isTypeParameter()) return "unknown";
2100
+ if (type.isUnion()) return renderUnion(type, state, paired);
2101
+ if (type.isIntersection()) return renderIntersection(type, state);
2102
+ const next = { ...state, depth: state.depth + 1 };
2103
+ if (type.isArray() || type.isReadonlyArray()) {
2104
+ const element = type.getArrayElementType() ?? type.getTypeArguments()[0];
2105
+ const pairedElement = paired?.getArrayElementType() ?? paired?.getTypeArguments()[0];
2106
+ return element ? `Array<${render(element, next, pairedElement)}>` : "Array<unknown>";
2107
+ }
2108
+ if (type.isTuple()) {
2109
+ const elements = type.getTupleElements();
2110
+ const pairedElements = paired?.isTuple() ? paired.getTupleElements() : [];
2111
+ return `[${elements.map((e, i) => render(e, next, pairedElements[i])).join(", ")}]`;
2112
+ }
2113
+ if (type.isObject()) return renderObject(type, next, paired);
2114
+ return "unknown";
2115
+ }
2116
+ function renderUnion(type, state, paired) {
2117
+ const members = type.getUnionTypes();
2118
+ const hasTrue = members.some((m) => m.isBooleanLiteral() && m.getText() === "true");
2119
+ const hasFalse = members.some((m) => m.isBooleanLiteral() && m.getText() === "false");
2120
+ const pairedNonNull = paired?.getNonNullableType();
2121
+ const arms = [];
2122
+ let sawBoolean = false;
2123
+ let hasNull = false;
2124
+ let hasUndefined = false;
2125
+ for (const member of members) {
2126
+ if (member.isNull()) {
2127
+ hasNull = true;
2128
+ continue;
2129
+ }
2130
+ if (member.isUndefined()) {
2131
+ hasUndefined = true;
2132
+ continue;
2133
+ }
2134
+ if (member.isBooleanLiteral() && hasTrue && hasFalse) {
2135
+ if (!sawBoolean) arms.push("boolean");
2136
+ sawBoolean = true;
2137
+ continue;
2138
+ }
2139
+ arms.push(render(member, state, members.length === 1 ? paired : pairedNonNull));
2140
+ }
2141
+ if (hasNull) arms.push("null");
2142
+ if (hasUndefined) arms.push("undefined");
2143
+ const unique = [...new Set(arms)];
2144
+ if (unique.includes("unknown")) return "unknown";
2145
+ return unique.join(" | ");
2146
+ }
2147
+ function renderIntersection(type, state) {
2148
+ const members = type.getIntersectionTypes();
2149
+ const primitive = members.find((m) => !m.isObject());
2150
+ if (primitive) return render(primitive, state);
2151
+ return renderObject(type, { ...state, depth: state.depth + 1 }, void 0);
2152
+ }
2153
+ function renderObject(type, state, paired) {
2154
+ const symbol = type.getSymbol() ?? type.getAliasSymbol();
2155
+ const name = symbol?.getName();
2156
+ if (name && GLOBAL_NAMED_TYPES.has(name) && isFromDeclarationFile(symbol)) {
2157
+ const args = type.getTypeArguments();
2158
+ return args.length ? `${name}<${args.map((a) => render(a, state)).join(", ")}>` : name;
2159
+ }
2160
+ if (type.getCallSignatures().length > 0 || type.getConstructSignatures().length > 0) {
2161
+ return "unknown";
2162
+ }
2163
+ if (type.isClassOrInterface() && isFromDeclarationFile(symbol)) return "unknown";
2164
+ if (state.stack.has(type.compilerType)) return "unknown";
2165
+ const stack = new Set(state.stack).add(type.compilerType);
2166
+ const inner = { ...state, stack };
2167
+ const fields = [];
2168
+ for (const prop of orderedProperties(type)) {
2169
+ if (isSymbolKeyed(prop)) continue;
2170
+ const propName = prop.getName();
2171
+ const propT = prop.getTypeAtLocation(state.at);
2172
+ if (propT.getCallSignatures().length > 0 && !propT.isUnion()) continue;
2173
+ const pairedProp = paired?.getProperty(propName)?.getTypeAtLocation(state.at);
2174
+ const optional = isOptionalSymbol(prop) ? "?" : "";
2175
+ fields.push(`${objectKey(propName)}${optional}: ${render(propT, inner, pairedProp)}`);
2176
+ }
2177
+ const stringIndex = type.getStringIndexType();
2178
+ if (stringIndex) {
2179
+ const pairedIndex = paired?.getStringIndexType();
2180
+ const value = render(stringIndex, inner, pairedIndex);
2181
+ if (fields.length === 0) return `Record<string, ${value}>`;
2182
+ fields.push(`[key: string]: ${value}`);
2183
+ }
2184
+ return fields.length ? `{ ${fields.join("; ")} }` : "{}";
2185
+ }
2186
+ function stateAt(at) {
2187
+ return { at, stack: /* @__PURE__ */ new Set(), depth: 0 };
2188
+ }
2189
+ function requestTypeOf(types) {
2190
+ return render(types.input, stateAt(types.at), types.output);
2191
+ }
2192
+ function responseTypeOf(types) {
2193
+ return render(types.output, stateAt(types.at));
2194
+ }
2195
+ function requestFieldsOf(types) {
2196
+ const { input, output, at } = types;
2197
+ const objectInput = input.getNonNullableType();
2198
+ if (!objectInput.isObject() || objectInput.isArray() || objectInput.isTuple()) return null;
2199
+ const state = stateAt(at);
2200
+ return orderedProperties(objectInput).filter((prop) => !isSymbolKeyed(prop)).map((prop) => ({
2201
+ name: prop.getName(),
2202
+ type: render(
2203
+ prop.getTypeAtLocation(at),
2204
+ state,
2205
+ output.getProperty(prop.getName())?.getTypeAtLocation(at)
2206
+ ),
2207
+ optional: isOptionalSymbol(prop)
2208
+ }));
2209
+ }
2210
+ function acceptsUndefined(types) {
2211
+ const { input, output } = types;
2212
+ const accepted = isAnyOrUnknown(input) ? output : input;
2213
+ if (isAnyOrUnknown(accepted) || accepted.isUndefined()) return true;
2214
+ return accepted.isUnion() && accepted.getUnionTypes().some((t) => t.isUndefined());
2215
+ }
2216
+
2217
+ // src/discovery/zod-ast-to-ts.ts
2218
+ var import_ts_morph8 = require("ts-morph");
2219
+ function zodAstToTs(node) {
2220
+ if (!import_ts_morph8.Node.isCallExpression(node)) return "unknown";
2221
+ const expr = node.getExpression();
2222
+ if (import_ts_morph8.Node.isPropertyAccessExpression(expr)) {
2223
+ const methodName = expr.getName();
2224
+ const receiver = expr.getExpression();
2225
+ if (methodName === "optional") {
2226
+ return `${zodAstToTs(receiver)} | undefined`;
2227
+ }
2228
+ if (methodName === "nullable") {
2229
+ return `${zodAstToTs(receiver)} | null`;
2230
+ }
2231
+ const args = node.getArguments();
2232
+ switch (methodName) {
2233
+ case "string":
2234
+ return "string";
2235
+ case "number":
2236
+ return "number";
2237
+ case "boolean":
2238
+ return "boolean";
2239
+ case "unknown":
2240
+ return "unknown";
2241
+ case "any":
2242
+ return "unknown";
2243
+ case "literal": {
2244
+ const lit = args[0];
2245
+ if (!lit) return "unknown";
2246
+ if (import_ts_morph8.Node.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());
2247
+ if (import_ts_morph8.Node.isNumericLiteral(lit)) return lit.getLiteralValue().toString();
2248
+ if (lit.getKind() === import_ts_morph8.SyntaxKind.TrueKeyword) return "true";
2249
+ if (lit.getKind() === import_ts_morph8.SyntaxKind.FalseKeyword) return "false";
2250
+ return "unknown";
2251
+ }
2252
+ case "enum": {
2253
+ const arrArg = args[0];
2254
+ if (!arrArg || !import_ts_morph8.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2255
+ const members = arrArg.getElements().map(
2256
+ (el) => import_ts_morph8.Node.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : "unknown"
2257
+ );
2258
+ return members.join(" | ");
2259
+ }
2260
+ case "array": {
2261
+ const inner = args[0];
2262
+ if (!inner) return "unknown";
2263
+ return `Array<${zodAstToTs(inner)}>`;
2264
+ }
2265
+ case "object": {
2266
+ const objArg = args[0];
2267
+ if (!objArg || !import_ts_morph8.Node.isObjectLiteralExpression(objArg)) return "unknown";
2268
+ const lines = [];
2269
+ for (const prop of objArg.getProperties()) {
2270
+ if (!import_ts_morph8.Node.isPropertyAssignment(prop)) continue;
2271
+ const key = prop.getName();
2272
+ const valNode = prop.getInitializer();
2273
+ if (!valNode) continue;
2274
+ const tsType = zodAstToTs(valNode);
2275
+ const isOpt = isOptionalChain(valNode);
2276
+ lines.push(`${key}${isOpt ? "?" : ""}: ${tsType}`);
2277
+ }
2278
+ return `{ ${lines.join("; ")} }`;
2279
+ }
2280
+ case "union": {
2281
+ const arrArg = args[0];
2282
+ if (!arrArg || !import_ts_morph8.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2283
+ return arrArg.getElements().map(zodAstToTs).join(" | ");
2284
+ }
2285
+ case "record": {
2286
+ const valArg = args.length === 1 ? args[0] : args[1];
2287
+ if (!valArg) return "unknown";
2288
+ return `Record<string, ${zodAstToTs(valArg)}>`;
2289
+ }
2290
+ case "tuple": {
2291
+ const arrArg = args[0];
2292
+ if (!arrArg || !import_ts_morph8.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2293
+ return `[${arrArg.getElements().map(zodAstToTs).join(", ")}]`;
2294
+ }
2295
+ default:
2296
+ return "unknown";
2297
+ }
2298
+ }
2299
+ return "unknown";
2300
+ }
2301
+ function isOptionalChain(node) {
2302
+ if (!import_ts_morph8.Node.isCallExpression(node)) return false;
2303
+ const expr = node.getExpression();
2304
+ return import_ts_morph8.Node.isPropertyAccessExpression(expr) && expr.getName() === "optional";
2305
+ }
2306
+ function memberType(val, position, project) {
2307
+ if (project) {
2308
+ const inferred = inferSchema(val, project);
2309
+ if (inferred.kind === "schema") {
2310
+ return position === "request" ? requestTypeOf(inferred.types) : responseTypeOf(inferred.types);
2311
+ }
2312
+ }
2313
+ return zodAstToTs(val);
2314
+ }
2315
+ function parseDefineContractCall(callExpr, project) {
2316
+ if (!import_ts_morph8.Node.isCallExpression(callExpr)) return null;
2317
+ const callee = callExpr.getExpression();
2318
+ const calleeName = import_ts_morph8.Node.isIdentifier(callee) ? callee.getText() : import_ts_morph8.Node.isPropertyAccessExpression(callee) ? callee.getName() : "";
2319
+ if (calleeName !== "defineContract") return null;
2320
+ const args = callExpr.getArguments();
2321
+ const optsArg = args[0];
2322
+ if (!optsArg || !import_ts_morph8.Node.isObjectLiteralExpression(optsArg)) return null;
2323
+ let query = null;
2324
+ let body = null;
2325
+ let response = "unknown";
2326
+ let error = null;
2327
+ let bodyZodText = null;
2328
+ let queryZodText = null;
2329
+ for (const prop of optsArg.getProperties()) {
2330
+ if (!import_ts_morph8.Node.isPropertyAssignment(prop)) continue;
2331
+ const propName = prop.getName();
2332
+ const val = prop.getInitializer();
2333
+ if (!val) continue;
2334
+ if (propName === "query") {
2335
+ query = memberType(val, "request", project);
2336
+ queryZodText = val.getText();
2337
+ } else if (propName === "body") {
2338
+ body = memberType(val, "request", project);
2339
+ bodyZodText = val.getText();
2340
+ } else if (propName === "response") {
2341
+ response = memberType(val, "response", project);
2342
+ } else if (propName === "error") {
2343
+ error = memberType(val, "response", project);
2344
+ }
2345
+ }
2346
+ return { query, body, response, error, bodyZodText, queryZodText };
2347
+ }
2348
+
2349
+ // src/discovery/pipe-schema.ts
2350
+ function pipeSchemaOf(decorator, project) {
2351
+ for (const pipe of decorator.getArguments()) {
2352
+ if (!import_ts_morph9.Node.isNewExpression(pipe) && !import_ts_morph9.Node.isCallExpression(pipe)) continue;
2353
+ for (const arg of pipe.getArguments()) {
2354
+ if (!couldBeSchema(arg)) continue;
2355
+ const inferred = inferSchema(arg, project);
2356
+ if (inferred.kind === "schema") {
2357
+ return {
2358
+ type: requestTypeOf(inferred.types),
2359
+ optional: acceptsUndefined(inferred.types),
2360
+ fields: requestFieldsOf(inferred.types)
2361
+ };
2362
+ }
2363
+ if (inferred.kind === "unresolved") {
2364
+ const fallback = syntacticZodType(arg, project);
2365
+ if (fallback) {
2366
+ return { type: fallback, optional: fallback.endsWith("| undefined"), fields: null };
2367
+ }
2368
+ }
2369
+ }
2370
+ }
2371
+ return null;
2372
+ }
2373
+ function couldBeSchema(arg) {
2374
+ return import_ts_morph9.Node.isIdentifier(arg) || import_ts_morph9.Node.isPropertyAccessExpression(arg) || import_ts_morph9.Node.isCallExpression(arg) || import_ts_morph9.Node.isAsExpression(arg) || import_ts_morph9.Node.isSatisfiesExpression(arg) || import_ts_morph9.Node.isParenthesizedExpression(arg);
2375
+ }
2376
+ function syntacticZodType(arg, project) {
2377
+ let expr = arg;
2378
+ if (import_ts_morph9.Node.isIdentifier(arg)) {
2379
+ const resolved = resolveImportedVariable(arg.getText(), arg.getSourceFile(), project);
2380
+ expr = resolved?.decl.getInitializer();
2381
+ }
2382
+ if (!expr || !import_ts_morph9.Node.isCallExpression(expr)) return null;
2383
+ const type = zodAstToTs(expr);
2384
+ return type === "unknown" ? null : type;
2385
+ }
2386
+
1721
2387
  // src/discovery/dto-type-resolver.ts
1722
2388
  var WRAPPER_TYPES = {
1723
2389
  // MikroORM Ref/Reference/LoadedReference/IdentifiedReference are server-side
@@ -1749,22 +2415,22 @@ var PASSTHROUGH_UTILITY = /* @__PURE__ */ new Set([
1749
2415
  ]);
1750
2416
  function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /* @__PURE__ */ new Map()) {
1751
2417
  if (depth <= 0) return "unknown";
1752
- if (import_ts_morph6.Node.isArrayTypeNode(typeNode)) {
2418
+ if (import_ts_morph10.Node.isArrayTypeNode(typeNode)) {
1753
2419
  const elementType = typeNode.getElementTypeNode();
1754
2420
  return `Array<${resolveTypeNodeToString(elementType, sourceFile, project, depth, subst)}>`;
1755
2421
  }
1756
- if (import_ts_morph6.Node.isUnionTypeNode(typeNode)) {
2422
+ if (import_ts_morph10.Node.isUnionTypeNode(typeNode)) {
1757
2423
  return typeNode.getTypeNodes().map((t) => resolveTypeNodeToString(t, sourceFile, project, depth, subst)).join(" | ");
1758
2424
  }
1759
- if (import_ts_morph6.Node.isIntersectionTypeNode(typeNode)) {
2425
+ if (import_ts_morph10.Node.isIntersectionTypeNode(typeNode)) {
1760
2426
  return typeNode.getTypeNodes().map((t) => resolveTypeNodeToString(t, sourceFile, project, depth, subst)).join(" & ");
1761
2427
  }
1762
- if (import_ts_morph6.Node.isParenthesizedTypeNode(typeNode)) {
2428
+ if (import_ts_morph10.Node.isParenthesizedTypeNode(typeNode)) {
1763
2429
  return `(${resolveTypeNodeToString(typeNode.getTypeNode(), sourceFile, project, depth, subst)})`;
1764
2430
  }
1765
- if (import_ts_morph6.Node.isTypeReference(typeNode)) {
2431
+ if (import_ts_morph10.Node.isTypeReference(typeNode)) {
1766
2432
  const typeName = typeNode.getTypeName();
1767
- const name = import_ts_morph6.Node.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();
2433
+ const name = import_ts_morph10.Node.isIdentifier(typeName) ? typeName.getText() : typeNode.getText();
1768
2434
  const bound = subst.get(name);
1769
2435
  if (bound !== void 0) return bound;
1770
2436
  if (name === "string" || name === "number" || name === "boolean") return name;
@@ -1787,13 +2453,13 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /
1787
2453
  dbg("unresolvable type:", name, "in", sourceFile.getFilePath());
1788
2454
  return "unknown";
1789
2455
  }
1790
- if (import_ts_morph6.Node.isTypeLiteral(typeNode)) {
2456
+ if (import_ts_morph10.Node.isTypeLiteral(typeNode)) {
1791
2457
  const members = [];
1792
2458
  for (const member of typeNode.getMembers()) {
1793
- if (import_ts_morph6.Node.isPropertySignature(member)) {
2459
+ if (import_ts_morph10.Node.isPropertySignature(member)) {
1794
2460
  const memberTypeNode = member.getTypeNode();
1795
- const memberType = memberTypeNode ? resolveTypeNodeToString(memberTypeNode, sourceFile, project, depth, subst) : "unknown";
1796
- members.push(`${member.getName()}${member.hasQuestionToken() ? "?" : ""}: ${memberType}`);
2461
+ const memberType2 = memberTypeNode ? resolveTypeNodeToString(memberTypeNode, sourceFile, project, depth, subst) : "unknown";
2462
+ members.push(`${member.getName()}${member.hasQuestionToken() ? "?" : ""}: ${memberType2}`);
1797
2463
  } else {
1798
2464
  members.push(member.getText());
1799
2465
  }
@@ -1801,11 +2467,11 @@ function resolveTypeNodeToString(typeNode, sourceFile, project, depth, subst = /
1801
2467
  return members.length > 0 ? `{ ${members.join("; ")} }` : "{}";
1802
2468
  }
1803
2469
  const kind = typeNode.getKind();
1804
- if (kind === import_ts_morph6.SyntaxKind.StringKeyword) return "string";
1805
- if (kind === import_ts_morph6.SyntaxKind.NumberKeyword) return "number";
1806
- if (kind === import_ts_morph6.SyntaxKind.BooleanKeyword) return "boolean";
1807
- if (kind === import_ts_morph6.SyntaxKind.UnknownKeyword) return "unknown";
1808
- if (kind === import_ts_morph6.SyntaxKind.AnyKeyword) return "unknown";
2470
+ if (kind === import_ts_morph10.SyntaxKind.StringKeyword) return "string";
2471
+ if (kind === import_ts_morph10.SyntaxKind.NumberKeyword) return "number";
2472
+ if (kind === import_ts_morph10.SyntaxKind.BooleanKeyword) return "boolean";
2473
+ if (kind === import_ts_morph10.SyntaxKind.UnknownKeyword) return "unknown";
2474
+ if (kind === import_ts_morph10.SyntaxKind.AnyKeyword) return "unknown";
1809
2475
  return typeNode.getText();
1810
2476
  }
1811
2477
  function unwrapFirstTypeArg(typeNode, sourceFile, project, depth, mode, subst = /* @__PURE__ */ new Map()) {
@@ -1853,20 +2519,24 @@ function resolvePropertied(decl, sourceFile, project, depth, subst = /* @__PURE_
1853
2519
  const propName = prop.getName();
1854
2520
  const isOptional = prop.hasQuestionToken();
1855
2521
  const propTypeNode = prop.getTypeNode();
1856
- let propType = "unknown";
2522
+ let propType2 = "unknown";
1857
2523
  if (propTypeNode) {
1858
- propType = resolveTypeNodeToString(propTypeNode, sourceFile, project, depth, subst);
2524
+ propType2 = resolveTypeNodeToString(propTypeNode, sourceFile, project, depth, subst);
1859
2525
  }
1860
- lines.push(`${propName}${isOptional ? "?" : ""}: ${propType}`);
2526
+ lines.push(`${propName}${isOptional ? "?" : ""}: ${propType2}`);
1861
2527
  }
1862
2528
  return `{ ${lines.join("; ")} }`;
1863
2529
  }
2530
+ function namedField(decorator) {
2531
+ const first = decorator.getArguments()[0];
2532
+ return first && import_ts_morph10.Node.isStringLiteral(first) ? first.getLiteralValue() : null;
2533
+ }
1864
2534
  function extractBodyType(method, sourceFile, project) {
1865
2535
  for (const param of method.getParameters()) {
1866
2536
  const bodyDecorator = param.getDecorators().find((d) => d.getName() === "Body");
1867
- if (!bodyDecorator) continue;
1868
- const bodyArgs = bodyDecorator.getArguments();
1869
- if (bodyArgs.length > 0) continue;
2537
+ if (!bodyDecorator || namedField(bodyDecorator) !== null) continue;
2538
+ const piped = pipeSchemaOf(bodyDecorator, project);
2539
+ if (piped) return piped.type;
1870
2540
  const typeNode = param.getTypeNode();
1871
2541
  if (typeNode) {
1872
2542
  return resolveTypeNodeToString(typeNode, sourceFile, project, 3);
@@ -1874,11 +2544,16 @@ function extractBodyType(method, sourceFile, project) {
1874
2544
  }
1875
2545
  return null;
1876
2546
  }
2547
+ function hasPipeSchema(param, decoratorName, project) {
2548
+ const decorator = param.getDecorators().find((d) => d.getName() === decoratorName);
2549
+ return !!decorator && pipeSchemaOf(decorator, project) !== null;
2550
+ }
1877
2551
  function extractQueryType(method, sourceFile, project) {
1878
2552
  for (const param of method.getParameters()) {
1879
2553
  const queryDecorator = param.getDecorators().find((d) => d.getName() === "Query");
1880
- if (!queryDecorator) continue;
1881
- if (queryDecorator.getArguments().length > 0) continue;
2554
+ if (!queryDecorator || namedField(queryDecorator) !== null) continue;
2555
+ const piped = pipeSchemaOf(queryDecorator, project);
2556
+ if (piped) return piped.type;
1882
2557
  const typeNode = param.getTypeNode();
1883
2558
  if (typeNode) {
1884
2559
  return resolveTypeNodeToString(typeNode, sourceFile, project, 3);
@@ -1888,10 +2563,13 @@ function extractQueryType(method, sourceFile, project) {
1888
2563
  for (const param of method.getParameters()) {
1889
2564
  const queryDecorator = param.getDecorators().find((d) => d.getName() === "Query");
1890
2565
  if (!queryDecorator) continue;
1891
- const queryArgs = queryDecorator.getArguments();
1892
- const nameArg = queryArgs[0];
1893
- if (!nameArg || !import_ts_morph6.Node.isStringLiteral(nameArg)) continue;
1894
- const queryName = nameArg.getLiteralValue();
2566
+ const queryName = namedField(queryDecorator);
2567
+ if (queryName === null) continue;
2568
+ const piped = pipeSchemaOf(queryDecorator, project);
2569
+ if (piped) {
2570
+ entries.push(`${queryName}${piped.optional ? "?" : ""}: ${piped.type}`);
2571
+ continue;
2572
+ }
1895
2573
  const typeNode = param.getTypeNode();
1896
2574
  const queryType = typeNode ? resolveTypeNodeToString(typeNode, sourceFile, project, 3) : "string";
1897
2575
  entries.push(`${queryName}${isParamOptional(param) ? "?" : ""}: ${queryType}`);
@@ -1901,8 +2579,8 @@ function extractQueryType(method, sourceFile, project) {
1901
2579
  function isParamOptional(param) {
1902
2580
  if (param.hasQuestionToken() || param.hasInitializer()) return true;
1903
2581
  const typeNode = param.getTypeNode();
1904
- if (typeNode && import_ts_morph6.Node.isUnionTypeNode(typeNode)) {
1905
- return typeNode.getTypeNodes().some((t) => t.getKind() === import_ts_morph6.SyntaxKind.UndefinedKeyword);
2582
+ if (typeNode && import_ts_morph10.Node.isUnionTypeNode(typeNode)) {
2583
+ return typeNode.getTypeNodes().some((t) => t.getKind() === import_ts_morph10.SyntaxKind.UndefinedKeyword);
1906
2584
  }
1907
2585
  return false;
1908
2586
  }
@@ -1914,7 +2592,7 @@ function extractParamsType(method, sourceFile, project) {
1914
2592
  const paramArgs = paramDecorator.getArguments();
1915
2593
  if (paramArgs.length === 0) continue;
1916
2594
  const nameArg = paramArgs[0];
1917
- if (!import_ts_morph6.Node.isStringLiteral(nameArg)) continue;
2595
+ if (!import_ts_morph10.Node.isStringLiteral(nameArg)) continue;
1918
2596
  const paramName = nameArg.getLiteralValue();
1919
2597
  const typeNode = param.getTypeNode();
1920
2598
  const paramType = typeNode ? resolveTypeNodeToString(typeNode, sourceFile, project, 3) : "string";
@@ -1922,6 +2600,22 @@ function extractParamsType(method, sourceFile, project) {
1922
2600
  }
1923
2601
  return entries.length > 0 ? `{ ${entries.join("; ")} }` : null;
1924
2602
  }
2603
+ function extractPipedParamTypes(method, project) {
2604
+ const types = {};
2605
+ for (const param of method.getParameters()) {
2606
+ const paramDecorator = param.getDecorators().find((d) => d.getName() === "Param");
2607
+ if (!paramDecorator) continue;
2608
+ const piped = pipeSchemaOf(paramDecorator, project);
2609
+ if (!piped) continue;
2610
+ const name = namedField(paramDecorator);
2611
+ if (name !== null) {
2612
+ types[name] = piped.type;
2613
+ } else {
2614
+ for (const field of piped.fields ?? []) types[field.name] = field.type;
2615
+ }
2616
+ }
2617
+ return Object.keys(types).length > 0 ? types : null;
2618
+ }
1925
2619
  function extractUploadedFiles(method) {
1926
2620
  const FILE = "File | Blob";
1927
2621
  const entries = [];
@@ -1935,28 +2629,28 @@ function extractUploadedFiles(method) {
1935
2629
  for (const decorator of method.getDecorators()) {
1936
2630
  if (decorator.getName() !== "UseInterceptors") continue;
1937
2631
  for (const arg of decorator.getArguments()) {
1938
- if (!import_ts_morph6.Node.isCallExpression(arg)) continue;
2632
+ if (!import_ts_morph10.Node.isCallExpression(arg)) continue;
1939
2633
  const interceptor = arg.getExpression().getText();
1940
2634
  const callArgs = arg.getArguments();
1941
2635
  const firstArg2 = callArgs[0];
1942
2636
  if (interceptor === "FileInterceptor") {
1943
- if (firstArg2 && import_ts_morph6.Node.isStringLiteral(firstArg2)) {
2637
+ if (firstArg2 && import_ts_morph10.Node.isStringLiteral(firstArg2)) {
1944
2638
  entries.push(`${firstArg2.getLiteralValue()}: ${FILE}`);
1945
2639
  multipart = true;
1946
2640
  }
1947
2641
  } else if (interceptor === "FilesInterceptor") {
1948
- if (firstArg2 && import_ts_morph6.Node.isStringLiteral(firstArg2)) {
2642
+ if (firstArg2 && import_ts_morph10.Node.isStringLiteral(firstArg2)) {
1949
2643
  entries.push(`${firstArg2.getLiteralValue()}: Array<${FILE}>`);
1950
2644
  multipart = true;
1951
2645
  }
1952
2646
  } else if (interceptor === "FileFieldsInterceptor") {
1953
- if (firstArg2 && import_ts_morph6.Node.isArrayLiteralExpression(firstArg2)) {
2647
+ if (firstArg2 && import_ts_morph10.Node.isArrayLiteralExpression(firstArg2)) {
1954
2648
  for (const el of firstArg2.getElements()) {
1955
- if (!import_ts_morph6.Node.isObjectLiteralExpression(el)) continue;
2649
+ if (!import_ts_morph10.Node.isObjectLiteralExpression(el)) continue;
1956
2650
  const nameProp = el.getProperty("name");
1957
- if (nameProp && import_ts_morph6.Node.isPropertyAssignment(nameProp)) {
2651
+ if (nameProp && import_ts_morph10.Node.isPropertyAssignment(nameProp)) {
1958
2652
  const init = nameProp.getInitializer();
1959
- if (init && import_ts_morph6.Node.isStringLiteral(init)) {
2653
+ if (init && import_ts_morph10.Node.isStringLiteral(init)) {
1960
2654
  entries.push(`${init.getLiteralValue()}: Array<${FILE}>`);
1961
2655
  }
1962
2656
  }
@@ -1976,13 +2670,13 @@ function extractResponseType(method, sourceFile, project) {
1976
2670
  if (apiResponseDecorator) {
1977
2671
  const args = apiResponseDecorator.getArguments();
1978
2672
  const optsArg = args[0];
1979
- if (optsArg && import_ts_morph6.Node.isObjectLiteralExpression(optsArg)) {
2673
+ if (optsArg && import_ts_morph10.Node.isObjectLiteralExpression(optsArg)) {
1980
2674
  for (const prop of optsArg.getProperties()) {
1981
- if (!import_ts_morph6.Node.isPropertyAssignment(prop)) continue;
2675
+ if (!import_ts_morph10.Node.isPropertyAssignment(prop)) continue;
1982
2676
  if (prop.getName() !== "type") continue;
1983
2677
  const val = prop.getInitializer();
1984
2678
  if (!val) continue;
1985
- if (import_ts_morph6.Node.isArrayLiteralExpression(val)) {
2679
+ if (import_ts_morph10.Node.isArrayLiteralExpression(val)) {
1986
2680
  const elements = val.getElements();
1987
2681
  const firstEl = elements[0];
1988
2682
  if (elements.length > 0 && firstEl !== void 0) {
@@ -2003,24 +2697,24 @@ function extractResponseType(method, sourceFile, project) {
2003
2697
  }
2004
2698
  function apiResponseStatus(decorator) {
2005
2699
  const optsArg = decorator.getArguments()[0];
2006
- if (!optsArg || !import_ts_morph6.Node.isObjectLiteralExpression(optsArg)) return null;
2700
+ if (!optsArg || !import_ts_morph10.Node.isObjectLiteralExpression(optsArg)) return null;
2007
2701
  for (const prop of optsArg.getProperties()) {
2008
- if (!import_ts_morph6.Node.isPropertyAssignment(prop)) continue;
2702
+ if (!import_ts_morph10.Node.isPropertyAssignment(prop)) continue;
2009
2703
  if (prop.getName() !== "status") continue;
2010
2704
  const val = prop.getInitializer();
2011
- if (val && import_ts_morph6.Node.isNumericLiteral(val)) return Number(val.getLiteralValue());
2705
+ if (val && import_ts_morph10.Node.isNumericLiteral(val)) return Number(val.getLiteralValue());
2012
2706
  }
2013
2707
  return null;
2014
2708
  }
2015
2709
  function apiResponseTypeNode(decorator) {
2016
2710
  const optsArg = decorator.getArguments()[0];
2017
- if (!optsArg || !import_ts_morph6.Node.isObjectLiteralExpression(optsArg)) return null;
2711
+ if (!optsArg || !import_ts_morph10.Node.isObjectLiteralExpression(optsArg)) return null;
2018
2712
  for (const prop of optsArg.getProperties()) {
2019
- if (!import_ts_morph6.Node.isPropertyAssignment(prop)) continue;
2713
+ if (!import_ts_morph10.Node.isPropertyAssignment(prop)) continue;
2020
2714
  if (prop.getName() !== "type") continue;
2021
2715
  const val = prop.getInitializer();
2022
2716
  if (!val) return null;
2023
- if (import_ts_morph6.Node.isArrayLiteralExpression(val)) {
2717
+ if (import_ts_morph10.Node.isArrayLiteralExpression(val)) {
2024
2718
  const first = val.getElements()[0];
2025
2719
  return first ? { node: first, isArray: true } : null;
2026
2720
  }
@@ -2038,7 +2732,7 @@ function extractErrorType(method, sourceFile, project) {
2038
2732
  const inner = resolveIdentifierToClassType(typeInfo.node, sourceFile, project, 3);
2039
2733
  const type = typeInfo.isArray ? `Array<${inner}>` : inner;
2040
2734
  let ref = null;
2041
- if (import_ts_morph6.Node.isIdentifier(typeInfo.node)) {
2735
+ if (import_ts_morph10.Node.isIdentifier(typeInfo.node)) {
2042
2736
  const name = typeInfo.node.getText();
2043
2737
  const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
2044
2738
  if (localDecl?.isExported()) {
@@ -2055,7 +2749,7 @@ function extractErrorType(method, sourceFile, project) {
2055
2749
  return null;
2056
2750
  }
2057
2751
  function resolveIdentifierToClassType(node, sourceFile, project, depth) {
2058
- if (!import_ts_morph6.Node.isIdentifier(node)) return "unknown";
2752
+ if (!import_ts_morph10.Node.isIdentifier(node)) return "unknown";
2059
2753
  const name = node.getText();
2060
2754
  const resolved = findType(name, sourceFile, project);
2061
2755
  if (resolved) {
@@ -2075,9 +2769,9 @@ var STREAM_ENVELOPES = /* @__PURE__ */ new Set(["MessageEvent", "MessageEventLik
2075
2769
  var BINARY_RESPONSE_TYPES = /* @__PURE__ */ new Set(["StreamableFile", "Buffer"]);
2076
2770
  function detectBinaryResponse(method) {
2077
2771
  const node = unwrapNamedContainer(method.getReturnTypeNode(), /* @__PURE__ */ new Set(["Promise"]));
2078
- if (!node || !import_ts_morph6.Node.isTypeReference(node)) return false;
2772
+ if (!node || !import_ts_morph10.Node.isTypeReference(node)) return false;
2079
2773
  const typeName = node.getTypeName();
2080
- const name = import_ts_morph6.Node.isIdentifier(typeName) ? typeName.getText() : "";
2774
+ const name = import_ts_morph10.Node.isIdentifier(typeName) ? typeName.getText() : "";
2081
2775
  return BINARY_RESPONSE_TYPES.has(name);
2082
2776
  }
2083
2777
  function detectStreamElement(method) {
@@ -2092,9 +2786,9 @@ function detectStreamElement(method) {
2092
2786
  return null;
2093
2787
  }
2094
2788
  function streamContainerElement(node) {
2095
- if (!node || !import_ts_morph6.Node.isTypeReference(node)) return null;
2789
+ if (!node || !import_ts_morph10.Node.isTypeReference(node)) return null;
2096
2790
  const typeName = node.getTypeName();
2097
- const name = import_ts_morph6.Node.isIdentifier(typeName) ? typeName.getText() : "";
2791
+ const name = import_ts_morph10.Node.isIdentifier(typeName) ? typeName.getText() : "";
2098
2792
  if (STREAM_CONTAINERS.has(name) || STREAM_CONTAINERS_GENERATOR.has(name)) {
2099
2793
  return node.getTypeArguments()[0] ?? null;
2100
2794
  }
@@ -2104,9 +2798,9 @@ function hasAsQueryDecorator(method) {
2104
2798
  return method.getDecorators().some((d) => d.getName() === "AsQuery");
2105
2799
  }
2106
2800
  function unwrapNamedContainer(node, names) {
2107
- if (!node || !import_ts_morph6.Node.isTypeReference(node)) return node;
2801
+ if (!node || !import_ts_morph10.Node.isTypeReference(node)) return node;
2108
2802
  const typeName = node.getTypeName();
2109
- const name = import_ts_morph6.Node.isIdentifier(typeName) ? typeName.getText() : "";
2803
+ const name = import_ts_morph10.Node.isIdentifier(typeName) ? typeName.getText() : "";
2110
2804
  if (names.has(name)) {
2111
2805
  return node.getTypeArguments()[0] ?? node;
2112
2806
  }
@@ -2127,19 +2821,20 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2127
2821
  body = body ?? bodyType;
2128
2822
  }
2129
2823
  const paramsType = extractParamsType(method, sourceFile, project);
2824
+ const paramTypes = extractPipedParamTypes(method, project);
2130
2825
  const response = isStream ? resolveTypeNodeToString(streamElement, sourceFile, project, 3) : extractResponseType(method, sourceFile, project);
2131
2826
  const errorInfo = extractErrorType(method, sourceFile, project);
2132
- if (body === null && query === null && paramsType === null && response === "unknown" && errorInfo === null && filterInfo === null && !isStream && !uploads.multipart && !binaryResponse && !asQuery) {
2827
+ if (body === null && query === null && paramsType === null && paramTypes === null && response === "unknown" && errorInfo === null && filterInfo === null && !isStream && !uploads.multipart && !binaryResponse && !asQuery) {
2133
2828
  return null;
2134
2829
  }
2135
2830
  let bodyRef = null;
2136
2831
  let queryRef = null;
2137
2832
  let responseRef = null;
2138
2833
  for (const param of method.getParameters()) {
2139
- if (param.getDecorators().some((d) => d.getName() === "Body") && param.getTypeNode()) {
2834
+ if (param.getDecorators().some((d) => d.getName() === "Body") && param.getTypeNode() && !hasPipeSchema(param, "Body", project)) {
2140
2835
  bodyRef = resolveBodyQueryResponseRef(param.getTypeNode(), sourceFile, project);
2141
2836
  }
2142
- if (param.getDecorators().some((d) => d.getName() === "Query") && param.getTypeNode()) {
2837
+ if (param.getDecorators().some((d) => d.getName() === "Query") && param.getTypeNode() && !hasPipeSchema(param, "Query", project)) {
2143
2838
  queryRef = resolveBodyQueryResponseRef(param.getTypeNode(), sourceFile, project);
2144
2839
  }
2145
2840
  }
@@ -2152,11 +2847,11 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2152
2847
  if (apiResp) {
2153
2848
  const args = apiResp.getArguments();
2154
2849
  const optsArg = args[0];
2155
- if (optsArg && import_ts_morph6.Node.isObjectLiteralExpression(optsArg)) {
2850
+ if (optsArg && import_ts_morph10.Node.isObjectLiteralExpression(optsArg)) {
2156
2851
  for (const prop of optsArg.getProperties()) {
2157
- if (import_ts_morph6.Node.isPropertyAssignment(prop) && prop.getName() === "type") {
2852
+ if (import_ts_morph10.Node.isPropertyAssignment(prop) && prop.getName() === "type") {
2158
2853
  const val = prop.getInitializer();
2159
- if (val && import_ts_morph6.Node.isIdentifier(val)) {
2854
+ if (val && import_ts_morph10.Node.isIdentifier(val)) {
2160
2855
  const name = val.getText();
2161
2856
  const localDecl = sourceFile.getInterface(name) || sourceFile.getClass(name) || sourceFile.getTypeAlias(name);
2162
2857
  if (localDecl?.isExported()) {
@@ -2192,6 +2887,7 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2192
2887
  response,
2193
2888
  error: errorInfo?.type ?? null,
2194
2889
  params: paramsType,
2890
+ paramTypes,
2195
2891
  queryRef,
2196
2892
  bodyRef,
2197
2893
  responseRef,
@@ -2212,6 +2908,7 @@ function extractDtoContract(method, sourceFile, project, mixin, controllerClass)
2212
2908
  function resolveParamClass(method, decoratorName, sourceFile, project) {
2213
2909
  for (const param of method.getParameters()) {
2214
2910
  if (!param.getDecorators().some((d) => d.getName() === decoratorName)) continue;
2911
+ if (hasPipeSchema(param, decoratorName, project)) continue;
2215
2912
  const typeNode = param.getTypeNode();
2216
2913
  if (!typeNode) continue;
2217
2914
  const text = typeNode.getText().replace(/\[\]$/, "");
@@ -2224,129 +2921,6 @@ function resolveParamClass(method, decoratorName, sourceFile, project) {
2224
2921
  return null;
2225
2922
  }
2226
2923
 
2227
- // src/discovery/zod-ast-to-ts.ts
2228
- var import_ts_morph7 = require("ts-morph");
2229
- function zodAstToTs(node) {
2230
- if (!import_ts_morph7.Node.isCallExpression(node)) return "unknown";
2231
- const expr = node.getExpression();
2232
- if (import_ts_morph7.Node.isPropertyAccessExpression(expr)) {
2233
- const methodName = expr.getName();
2234
- const receiver = expr.getExpression();
2235
- if (methodName === "optional") {
2236
- return `${zodAstToTs(receiver)} | undefined`;
2237
- }
2238
- if (methodName === "nullable") {
2239
- return `${zodAstToTs(receiver)} | null`;
2240
- }
2241
- const args = node.getArguments();
2242
- switch (methodName) {
2243
- case "string":
2244
- return "string";
2245
- case "number":
2246
- return "number";
2247
- case "boolean":
2248
- return "boolean";
2249
- case "unknown":
2250
- return "unknown";
2251
- case "any":
2252
- return "unknown";
2253
- case "literal": {
2254
- const lit = args[0];
2255
- if (!lit) return "unknown";
2256
- if (import_ts_morph7.Node.isStringLiteral(lit)) return JSON.stringify(lit.getLiteralValue());
2257
- if (import_ts_morph7.Node.isNumericLiteral(lit)) return lit.getLiteralValue().toString();
2258
- if (lit.getKind() === import_ts_morph7.SyntaxKind.TrueKeyword) return "true";
2259
- if (lit.getKind() === import_ts_morph7.SyntaxKind.FalseKeyword) return "false";
2260
- return "unknown";
2261
- }
2262
- case "enum": {
2263
- const arrArg = args[0];
2264
- if (!arrArg || !import_ts_morph7.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2265
- const members = arrArg.getElements().map(
2266
- (el) => import_ts_morph7.Node.isStringLiteral(el) ? JSON.stringify(el.getLiteralValue()) : "unknown"
2267
- );
2268
- return members.join(" | ");
2269
- }
2270
- case "array": {
2271
- const inner = args[0];
2272
- if (!inner) return "unknown";
2273
- return `Array<${zodAstToTs(inner)}>`;
2274
- }
2275
- case "object": {
2276
- const objArg = args[0];
2277
- if (!objArg || !import_ts_morph7.Node.isObjectLiteralExpression(objArg)) return "unknown";
2278
- const lines = [];
2279
- for (const prop of objArg.getProperties()) {
2280
- if (!import_ts_morph7.Node.isPropertyAssignment(prop)) continue;
2281
- const key = prop.getName();
2282
- const valNode = prop.getInitializer();
2283
- if (!valNode) continue;
2284
- const tsType = zodAstToTs(valNode);
2285
- const isOpt = isOptionalChain(valNode);
2286
- lines.push(`${key}${isOpt ? "?" : ""}: ${tsType}`);
2287
- }
2288
- return `{ ${lines.join("; ")} }`;
2289
- }
2290
- case "union": {
2291
- const arrArg = args[0];
2292
- if (!arrArg || !import_ts_morph7.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2293
- return arrArg.getElements().map(zodAstToTs).join(" | ");
2294
- }
2295
- case "record": {
2296
- const valArg = args.length === 1 ? args[0] : args[1];
2297
- if (!valArg) return "unknown";
2298
- return `Record<string, ${zodAstToTs(valArg)}>`;
2299
- }
2300
- case "tuple": {
2301
- const arrArg = args[0];
2302
- if (!arrArg || !import_ts_morph7.Node.isArrayLiteralExpression(arrArg)) return "unknown";
2303
- return `[${arrArg.getElements().map(zodAstToTs).join(", ")}]`;
2304
- }
2305
- default:
2306
- return "unknown";
2307
- }
2308
- }
2309
- return "unknown";
2310
- }
2311
- function isOptionalChain(node) {
2312
- if (!import_ts_morph7.Node.isCallExpression(node)) return false;
2313
- const expr = node.getExpression();
2314
- return import_ts_morph7.Node.isPropertyAccessExpression(expr) && expr.getName() === "optional";
2315
- }
2316
- function parseDefineContractCall(callExpr) {
2317
- if (!import_ts_morph7.Node.isCallExpression(callExpr)) return null;
2318
- const callee = callExpr.getExpression();
2319
- const calleeName = import_ts_morph7.Node.isIdentifier(callee) ? callee.getText() : import_ts_morph7.Node.isPropertyAccessExpression(callee) ? callee.getName() : "";
2320
- if (calleeName !== "defineContract") return null;
2321
- const args = callExpr.getArguments();
2322
- const optsArg = args[0];
2323
- if (!optsArg || !import_ts_morph7.Node.isObjectLiteralExpression(optsArg)) return null;
2324
- let query = null;
2325
- let body = null;
2326
- let response = "unknown";
2327
- let error = null;
2328
- let bodyZodText = null;
2329
- let queryZodText = null;
2330
- for (const prop of optsArg.getProperties()) {
2331
- if (!import_ts_morph7.Node.isPropertyAssignment(prop)) continue;
2332
- const propName = prop.getName();
2333
- const val = prop.getInitializer();
2334
- if (!val) continue;
2335
- if (propName === "query") {
2336
- query = zodAstToTs(val);
2337
- queryZodText = val.getText();
2338
- } else if (propName === "body") {
2339
- body = zodAstToTs(val);
2340
- bodyZodText = val.getText();
2341
- } else if (propName === "response") {
2342
- response = zodAstToTs(val);
2343
- } else if (propName === "error") {
2344
- error = zodAstToTs(val);
2345
- }
2346
- }
2347
- return { query, body, response, error, bodyZodText, queryZodText };
2348
- }
2349
-
2350
2924
  // src/discovery/contracts-fast.ts
2351
2925
  function resolveTsconfigPath(cwd, tsconfig) {
2352
2926
  return tsconfig ? (0, import_node_path3.resolve)(tsconfig) : (0, import_node_path3.join)(cwd, "tsconfig.json");
@@ -2358,25 +2932,25 @@ var NO_TSCONFIG_OPTIONS = {
2358
2932
  };
2359
2933
  function loadDiscoveryTsconfig(tsconfigPath) {
2360
2934
  if (!(0, import_node_fs.existsSync)(tsconfigPath)) return { options: null, files: [] };
2361
- const read = import_ts_morph8.ts.readConfigFile(tsconfigPath, (path) => import_ts_morph8.ts.sys.readFile(path));
2935
+ const read = import_ts_morph11.ts.readConfigFile(tsconfigPath, (path) => import_ts_morph11.ts.sys.readFile(path));
2362
2936
  if (read.error) {
2363
2937
  return {
2364
2938
  options: null,
2365
2939
  files: [tsconfigPath],
2366
- error: import_ts_morph8.ts.flattenDiagnosticMessageText(read.error.messageText, " ")
2940
+ error: import_ts_morph11.ts.flattenDiagnosticMessageText(read.error.messageText, " ")
2367
2941
  };
2368
2942
  }
2369
2943
  const host = {
2370
- useCaseSensitiveFileNames: import_ts_morph8.ts.sys.useCaseSensitiveFileNames,
2944
+ useCaseSensitiveFileNames: import_ts_morph11.ts.sys.useCaseSensitiveFileNames,
2371
2945
  // The one line that keeps a tsconfig from being a filesystem walk.
2372
2946
  readDirectory: () => [],
2373
- fileExists: (path) => import_ts_morph8.ts.sys.fileExists(path),
2947
+ fileExists: (path) => import_ts_morph11.ts.sys.fileExists(path),
2374
2948
  // `extends` is resolved through the host, so a consumer whose `paths` live
2375
2949
  // in a base tsconfig keeps working.
2376
- readFile: (path) => import_ts_morph8.ts.sys.readFile(path)
2950
+ readFile: (path) => import_ts_morph11.ts.sys.readFile(path)
2377
2951
  };
2378
- const sourceFile = import_ts_morph8.ts.readJsonConfigFile(tsconfigPath, (path) => import_ts_morph8.ts.sys.readFile(path));
2379
- const parsed = import_ts_morph8.ts.parseJsonSourceFileConfigFileContent(
2952
+ const sourceFile = import_ts_morph11.ts.readJsonConfigFile(tsconfigPath, (path) => import_ts_morph11.ts.sys.readFile(path));
2953
+ const parsed = import_ts_morph11.ts.parseJsonSourceFileConfigFileContent(
2380
2954
  sourceFile,
2381
2955
  host,
2382
2956
  (0, import_node_path3.dirname)(tsconfigPath),
@@ -2399,7 +2973,7 @@ function createDiscoveryProject(tsconfigPath, tsconfig = loadDiscoveryTsconfig(t
2399
2973
  `[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.`
2400
2974
  );
2401
2975
  }
2402
- return new import_ts_morph8.Project({
2976
+ return new import_ts_morph11.Project({
2403
2977
  compilerOptions: tsconfig.options ?? { ...NO_TSCONFIG_OPTIONS },
2404
2978
  skipAddingFilesFromTsConfig: true,
2405
2979
  skipLoadingLibFiles: true,
@@ -2504,15 +3078,16 @@ var PersistentDiscovery = class _PersistentDiscovery {
2504
3078
  clearTypeResolutionCaches(this.project);
2505
3079
  clearEnumCache(this.project);
2506
3080
  clearMixinTypeProject();
3081
+ clearSchemaTypeProject(this.project);
2507
3082
  return extractRoutesFrom(this.project, this.controllerPaths);
2508
3083
  }
2509
3084
  };
2510
3085
  function decoratorStringArg(decoratorExpr) {
2511
3086
  if (!decoratorExpr) return void 0;
2512
- if (import_ts_morph8.Node.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();
2513
- if (import_ts_morph8.Node.isArrayLiteralExpression(decoratorExpr)) {
3087
+ if (import_ts_morph11.Node.isStringLiteral(decoratorExpr)) return decoratorExpr.getLiteralValue();
3088
+ if (import_ts_morph11.Node.isArrayLiteralExpression(decoratorExpr)) {
2514
3089
  const first = decoratorExpr.getElements()[0];
2515
- if (first && import_ts_morph8.Node.isStringLiteral(first)) return first.getLiteralValue();
3090
+ if (first && import_ts_morph11.Node.isStringLiteral(first)) return first.getLiteralValue();
2516
3091
  }
2517
3092
  return void 0;
2518
3093
  }
@@ -2633,9 +3208,9 @@ function extractContractRoute(args) {
2633
3208
  let contractDef = null;
2634
3209
  let bodyZodRef = null;
2635
3210
  let queryZodRef = null;
2636
- if (import_ts_morph8.Node.isCallExpression(firstDecoratorArg)) {
2637
- contractDef = parseDefineContractCall(firstDecoratorArg);
2638
- } else if (import_ts_morph8.Node.isIdentifier(firstDecoratorArg)) {
3211
+ if (import_ts_morph11.Node.isCallExpression(firstDecoratorArg)) {
3212
+ contractDef = parseDefineContractCall(firstDecoratorArg, project);
3213
+ } else if (import_ts_morph11.Node.isIdentifier(firstDecoratorArg)) {
2639
3214
  const identName = firstDecoratorArg.getText();
2640
3215
  const resolvedVar = resolveImportedVariable(identName, sourceFile, project);
2641
3216
  if (!resolvedVar) {
@@ -2647,7 +3222,7 @@ function extractContractRoute(args) {
2647
3222
  const { decl: varDecl, file: declFile } = resolvedVar;
2648
3223
  const initializer = varDecl.getInitializer();
2649
3224
  if (!initializer) return null;
2650
- contractDef = parseDefineContractCall(initializer);
3225
+ contractDef = parseDefineContractCall(initializer, project);
2651
3226
  if (contractDef && varDecl.isExported()) {
2652
3227
  const filePath = declFile.getFilePath();
2653
3228
  if (contractDef.body !== null) {
@@ -2718,6 +3293,7 @@ function extractDtoRoute(args) {
2718
3293
  body: dtoContract?.body ?? null,
2719
3294
  response: mixinResponse ?? dtoContract?.response ?? "unknown",
2720
3295
  error: dtoContract?.error ?? null,
3296
+ paramTypes: dtoContract?.paramTypes ?? null,
2721
3297
  queryRef: dtoContract?.queryRef ?? null,
2722
3298
  bodyRef: dtoContract?.bodyRef ?? null,
2723
3299
  responseRef: dtoContract?.responseRef ?? null,
@@ -2847,7 +3423,7 @@ function extractPropsSource(source, exportName) {
2847
3423
 
2848
3424
  // src/discovery/shared-props.ts
2849
3425
  var import_node_path5 = require("path");
2850
- var import_ts_morph9 = require("ts-morph");
3426
+ var import_ts_morph12 = require("ts-morph");
2851
3427
  function discoverSharedProps(project, moduleEntry) {
2852
3428
  try {
2853
3429
  let sourceFile = project.getSourceFile(moduleEntry);
@@ -2873,14 +3449,14 @@ function discoverSharedPropsFromConfig(config) {
2873
3449
  const tsconfigPath = config.app.tsconfig ?? (0, import_node_path5.join)(config.codegen.cwd, "tsconfig.json");
2874
3450
  let project;
2875
3451
  try {
2876
- project = new import_ts_morph9.Project({
3452
+ project = new import_ts_morph12.Project({
2877
3453
  tsConfigFilePath: tsconfigPath,
2878
3454
  skipAddingFilesFromTsConfig: true,
2879
3455
  skipLoadingLibFiles: true,
2880
3456
  skipFileDependencyResolution: true
2881
3457
  });
2882
3458
  } catch {
2883
- project = new import_ts_morph9.Project({
3459
+ project = new import_ts_morph12.Project({
2884
3460
  skipAddingFilesFromTsConfig: true,
2885
3461
  skipLoadingLibFiles: true,
2886
3462
  skipFileDependencyResolution: true,
@@ -2893,13 +3469,13 @@ function discoverSharedPropsFromConfig(config) {
2893
3469
  }
2894
3470
  }
2895
3471
  function findForRootCall(sourceFile) {
2896
- const callExpressions = sourceFile.getDescendantsOfKind(import_ts_morph9.SyntaxKind.CallExpression);
3472
+ const callExpressions = sourceFile.getDescendantsOfKind(import_ts_morph12.SyntaxKind.CallExpression);
2897
3473
  for (const call of callExpressions) {
2898
3474
  const expr = call.getExpression();
2899
- if (!import_ts_morph9.Node.isPropertyAccessExpression(expr)) continue;
3475
+ if (!import_ts_morph12.Node.isPropertyAccessExpression(expr)) continue;
2900
3476
  const methodName = expr.getName();
2901
3477
  const objectExpr = expr.getExpression();
2902
- if (methodName === "forRoot" && import_ts_morph9.Node.isIdentifier(objectExpr)) {
3478
+ if (methodName === "forRoot" && import_ts_morph12.Node.isIdentifier(objectExpr)) {
2903
3479
  const name = objectExpr.getText();
2904
3480
  if (name === "InertiaModule") {
2905
3481
  return call;
@@ -2909,19 +3485,19 @@ function findForRootCall(sourceFile) {
2909
3485
  return null;
2910
3486
  }
2911
3487
  function findShareInitializer(forRootCall) {
2912
- if (!import_ts_morph9.Node.isCallExpression(forRootCall)) return null;
3488
+ if (!import_ts_morph12.Node.isCallExpression(forRootCall)) return null;
2913
3489
  const args = forRootCall.getArguments();
2914
3490
  const firstArg2 = args[0];
2915
- if (!firstArg2 || !import_ts_morph9.Node.isObjectLiteralExpression(firstArg2)) return null;
3491
+ if (!firstArg2 || !import_ts_morph12.Node.isObjectLiteralExpression(firstArg2)) return null;
2916
3492
  for (const prop of firstArg2.getProperties()) {
2917
- if (import_ts_morph9.Node.isPropertyAssignment(prop) && prop.getName() === "share") {
3493
+ if (import_ts_morph12.Node.isPropertyAssignment(prop) && prop.getName() === "share") {
2918
3494
  return prop.getInitializer() ?? null;
2919
3495
  }
2920
3496
  }
2921
3497
  return null;
2922
3498
  }
2923
3499
  function extractShareType(node, sourceFile, project) {
2924
- if (import_ts_morph9.Node.isIdentifier(node)) {
3500
+ if (import_ts_morph12.Node.isIdentifier(node)) {
2925
3501
  const ref = resolveIdentifierToImportRef(node, sourceFile, project);
2926
3502
  if (ref) {
2927
3503
  return {
@@ -2931,22 +3507,22 @@ function extractShareType(node, sourceFile, project) {
2931
3507
  };
2932
3508
  }
2933
3509
  }
2934
- if (import_ts_morph9.Node.isArrowFunction(node)) {
3510
+ if (import_ts_morph12.Node.isArrowFunction(node)) {
2935
3511
  const result = extractFromFunctionLike(node, sourceFile);
2936
3512
  return result ? { ...result, isImportRef: false } : null;
2937
3513
  }
2938
- if (import_ts_morph9.Node.isFunctionExpression(node)) {
3514
+ if (import_ts_morph12.Node.isFunctionExpression(node)) {
2939
3515
  const result = extractFromFunctionLike(node, sourceFile);
2940
3516
  return result ? { ...result, isImportRef: false } : null;
2941
3517
  }
2942
- if (import_ts_morph9.Node.isObjectLiteralExpression(node)) {
3518
+ if (import_ts_morph12.Node.isObjectLiteralExpression(node)) {
2943
3519
  const result = extractFromObjectLiteral(node);
2944
3520
  return result ? { ...result, isImportRef: false } : null;
2945
3521
  }
2946
3522
  return null;
2947
3523
  }
2948
3524
  function resolveIdentifierToImportRef(id, sourceFile, project) {
2949
- if (!import_ts_morph9.Node.isIdentifier(id)) return null;
3525
+ if (!import_ts_morph12.Node.isIdentifier(id)) return null;
2950
3526
  const name = id.getText();
2951
3527
  const localFunc = sourceFile.getFunction(name);
2952
3528
  if (localFunc?.isExported()) {
@@ -2980,37 +3556,37 @@ function resolveIdentifierToImportRef(id, sourceFile, project) {
2980
3556
  return null;
2981
3557
  }
2982
3558
  function extractFromFunctionLike(node, _sourceFile) {
2983
- const returnTypeNode = import_ts_morph9.Node.isArrowFunction(node) || import_ts_morph9.Node.isFunctionExpression(node) ? node.getReturnTypeNode() : null;
3559
+ const returnTypeNode = import_ts_morph12.Node.isArrowFunction(node) || import_ts_morph12.Node.isFunctionExpression(node) ? node.getReturnTypeNode() : null;
2984
3560
  if (returnTypeNode) {
2985
3561
  return extractFromReturnTypeAnnotation(returnTypeNode);
2986
3562
  }
2987
- if (import_ts_morph9.Node.isArrowFunction(node)) {
3563
+ if (import_ts_morph12.Node.isArrowFunction(node)) {
2988
3564
  const body = node.getBody();
2989
- if (import_ts_morph9.Node.isParenthesizedExpression(body)) {
3565
+ if (import_ts_morph12.Node.isParenthesizedExpression(body)) {
2990
3566
  const inner = body.getExpression();
2991
- if (import_ts_morph9.Node.isObjectLiteralExpression(inner)) {
3567
+ if (import_ts_morph12.Node.isObjectLiteralExpression(inner)) {
2992
3568
  return extractFromObjectLiteral(inner);
2993
3569
  }
2994
3570
  }
2995
- if (import_ts_morph9.Node.isObjectLiteralExpression(body)) {
3571
+ if (import_ts_morph12.Node.isObjectLiteralExpression(body)) {
2996
3572
  return extractFromObjectLiteral(body);
2997
3573
  }
2998
- if (import_ts_morph9.Node.isBlock(body)) {
3574
+ if (import_ts_morph12.Node.isBlock(body)) {
2999
3575
  return extractFromBlockReturn(body);
3000
3576
  }
3001
3577
  }
3002
- if (import_ts_morph9.Node.isFunctionExpression(node)) {
3578
+ if (import_ts_morph12.Node.isFunctionExpression(node)) {
3003
3579
  const body = node.getBody();
3004
- if (import_ts_morph9.Node.isBlock(body)) {
3580
+ if (import_ts_morph12.Node.isBlock(body)) {
3005
3581
  return extractFromBlockReturn(body);
3006
3582
  }
3007
3583
  }
3008
3584
  return null;
3009
3585
  }
3010
3586
  function extractFromReturnTypeAnnotation(typeNode) {
3011
- if (import_ts_morph9.Node.isTypeReference(typeNode)) {
3587
+ if (import_ts_morph12.Node.isTypeReference(typeNode)) {
3012
3588
  const typeName = typeNode.getTypeName();
3013
- if (import_ts_morph9.Node.isIdentifier(typeName) && typeName.getText() === "Promise") {
3589
+ if (import_ts_morph12.Node.isIdentifier(typeName) && typeName.getText() === "Promise") {
3014
3590
  const typeArgs = typeNode.getTypeArguments();
3015
3591
  const firstArg2 = typeArgs[0];
3016
3592
  if (firstArg2) {
@@ -3019,10 +3595,10 @@ function extractFromReturnTypeAnnotation(typeNode) {
3019
3595
  return null;
3020
3596
  }
3021
3597
  }
3022
- if (import_ts_morph9.Node.isTypeLiteral(typeNode)) {
3598
+ if (import_ts_morph12.Node.isTypeLiteral(typeNode)) {
3023
3599
  const properties = [];
3024
3600
  for (const member of typeNode.getMembers()) {
3025
- if (import_ts_morph9.Node.isPropertySignature(member)) {
3601
+ if (import_ts_morph12.Node.isPropertySignature(member)) {
3026
3602
  const name = member.getName();
3027
3603
  const memberTypeNode = member.getTypeNode();
3028
3604
  const type = memberTypeNode ? memberTypeNode.getText() : "unknown";
@@ -3036,19 +3612,19 @@ function extractFromReturnTypeAnnotation(typeNode) {
3036
3612
  return null;
3037
3613
  }
3038
3614
  function extractFromBlockReturn(block) {
3039
- if (!import_ts_morph9.Node.isBlock(block)) return null;
3615
+ if (!import_ts_morph12.Node.isBlock(block)) return null;
3040
3616
  const statements = block.getStatements();
3041
3617
  for (let i = statements.length - 1; i >= 0; i--) {
3042
3618
  const stmt = statements[i];
3043
- if (!import_ts_morph9.Node.isReturnStatement(stmt)) continue;
3619
+ if (!import_ts_morph12.Node.isReturnStatement(stmt)) continue;
3044
3620
  const expr = stmt.getExpression();
3045
3621
  if (!expr) continue;
3046
- if (import_ts_morph9.Node.isObjectLiteralExpression(expr)) {
3622
+ if (import_ts_morph12.Node.isObjectLiteralExpression(expr)) {
3047
3623
  return extractFromObjectLiteral(expr);
3048
3624
  }
3049
- if (import_ts_morph9.Node.isParenthesizedExpression(expr)) {
3625
+ if (import_ts_morph12.Node.isParenthesizedExpression(expr)) {
3050
3626
  const inner = expr.getExpression();
3051
- if (import_ts_morph9.Node.isObjectLiteralExpression(inner)) {
3627
+ if (import_ts_morph12.Node.isObjectLiteralExpression(inner)) {
3052
3628
  return extractFromObjectLiteral(inner);
3053
3629
  }
3054
3630
  }
@@ -3057,10 +3633,10 @@ function extractFromBlockReturn(block) {
3057
3633
  return null;
3058
3634
  }
3059
3635
  function extractFromObjectLiteral(objLiteral) {
3060
- if (!import_ts_morph9.Node.isObjectLiteralExpression(objLiteral)) return null;
3636
+ if (!import_ts_morph12.Node.isObjectLiteralExpression(objLiteral)) return null;
3061
3637
  const properties = [];
3062
3638
  for (const prop of objLiteral.getProperties()) {
3063
- if (!import_ts_morph9.Node.isPropertyAssignment(prop)) continue;
3639
+ if (!import_ts_morph12.Node.isPropertyAssignment(prop)) continue;
3064
3640
  const name = prop.getName();
3065
3641
  const initializer = prop.getInitializer();
3066
3642
  if (!initializer) continue;
@@ -3072,21 +3648,21 @@ function extractFromObjectLiteral(objLiteral) {
3072
3648
  return { typeString, properties, isImportRef: false };
3073
3649
  }
3074
3650
  function inferExpressionType(node) {
3075
- if (import_ts_morph9.Node.isStringLiteral(node)) return "string";
3076
- if (import_ts_morph9.Node.isTemplateExpression(node) || import_ts_morph9.Node.isNoSubstitutionTemplateLiteral(node))
3651
+ if (import_ts_morph12.Node.isStringLiteral(node)) return "string";
3652
+ if (import_ts_morph12.Node.isTemplateExpression(node) || import_ts_morph12.Node.isNoSubstitutionTemplateLiteral(node))
3077
3653
  return "string";
3078
- if (import_ts_morph9.Node.isNumericLiteral(node)) return "number";
3079
- if (node.getKind() === import_ts_morph9.SyntaxKind.TrueKeyword || node.getKind() === import_ts_morph9.SyntaxKind.FalseKeyword) {
3654
+ if (import_ts_morph12.Node.isNumericLiteral(node)) return "number";
3655
+ if (node.getKind() === import_ts_morph12.SyntaxKind.TrueKeyword || node.getKind() === import_ts_morph12.SyntaxKind.FalseKeyword) {
3080
3656
  return "boolean";
3081
3657
  }
3082
- if (node.getKind() === import_ts_morph9.SyntaxKind.NullKeyword) return "null";
3083
- if (import_ts_morph9.Node.isIdentifier(node) && node.getText() === "undefined") return "undefined";
3084
- if (import_ts_morph9.Node.isObjectLiteralExpression(node)) {
3658
+ if (node.getKind() === import_ts_morph12.SyntaxKind.NullKeyword) return "null";
3659
+ if (import_ts_morph12.Node.isIdentifier(node) && node.getText() === "undefined") return "undefined";
3660
+ if (import_ts_morph12.Node.isObjectLiteralExpression(node)) {
3085
3661
  const props = node.getProperties();
3086
3662
  if (props.length === 0) return "Record<string, unknown>";
3087
3663
  const entries = [];
3088
3664
  for (const prop of props) {
3089
- if (!import_ts_morph9.Node.isPropertyAssignment(prop)) continue;
3665
+ if (!import_ts_morph12.Node.isPropertyAssignment(prop)) continue;
3090
3666
  const key = prop.getName();
3091
3667
  const init = prop.getInitializer();
3092
3668
  if (!init) continue;
@@ -3095,23 +3671,23 @@ function inferExpressionType(node) {
3095
3671
  if (entries.length === 0) return "Record<string, unknown>";
3096
3672
  return `{ ${entries.join("; ")} }`;
3097
3673
  }
3098
- if (import_ts_morph9.Node.isArrayLiteralExpression(node)) {
3674
+ if (import_ts_morph12.Node.isArrayLiteralExpression(node)) {
3099
3675
  const elements = node.getElements();
3100
3676
  if (elements.length === 0) return "Array<unknown>";
3101
3677
  const first = elements[0];
3102
3678
  if (first) return `Array<${inferExpressionType(first)}>`;
3103
3679
  return "Array<unknown>";
3104
3680
  }
3105
- if (import_ts_morph9.Node.isConditionalExpression(node)) {
3681
+ if (import_ts_morph12.Node.isConditionalExpression(node)) {
3106
3682
  const whenTrue = inferExpressionType(node.getWhenTrue());
3107
3683
  const whenFalse = inferExpressionType(node.getWhenFalse());
3108
3684
  if (whenTrue === whenFalse) return whenTrue;
3109
3685
  return `${whenTrue} | ${whenFalse}`;
3110
3686
  }
3111
- if (import_ts_morph9.Node.isParenthesizedExpression(node)) {
3687
+ if (import_ts_morph12.Node.isParenthesizedExpression(node)) {
3112
3688
  return inferExpressionType(node.getExpression());
3113
3689
  }
3114
- if (import_ts_morph9.Node.isAsExpression(node)) {
3690
+ if (import_ts_morph12.Node.isAsExpression(node)) {
3115
3691
  const typeNode = node.getTypeNode();
3116
3692
  if (typeNode) return typeNode.getText();
3117
3693
  }
@@ -3124,7 +3700,7 @@ var import_node_path7 = require("path");
3124
3700
 
3125
3701
  // src/extension/registry.ts
3126
3702
  var import_node_path6 = require("path");
3127
- var import_ts_morph10 = require("ts-morph");
3703
+ var import_ts_morph13 = require("ts-morph");
3128
3704
  function resolveApiSlots(extensions) {
3129
3705
  let layer;
3130
3706
  let layerOwner;
@@ -3175,7 +3751,7 @@ function createExtensionContext(config, getRoutes, trackedInputs) {
3175
3751
  },
3176
3752
  project() {
3177
3753
  if (!project) {
3178
- project = new import_ts_morph10.Project({
3754
+ project = new import_ts_morph13.Project({
3179
3755
  skipAddingFilesFromTsConfig: true,
3180
3756
  skipLoadingLibFiles: true,
3181
3757
  skipFileDependencyResolution: true,
@@ -3293,10 +3869,11 @@ function insertIntoTree(tree, segments, leaf, fullName) {
3293
3869
  insertIntoTree(branch.children, rest, leaf, fullName);
3294
3870
  }
3295
3871
  }
3296
- function buildParamsType(params) {
3872
+ function buildParamsType(params, paramTypes) {
3297
3873
  const pathParams = params.filter((p) => p.source === "path");
3298
3874
  if (pathParams.length === 0) return "never";
3299
- return `{ ${pathParams.map((p) => `${p.name}: string`).join("; ")} }`;
3875
+ const typeOf = (name) => paramTypes && Object.hasOwn(paramTypes, name) && paramTypes[name] || "string";
3876
+ return `{ ${pathParams.map((p) => `${p.name}: ${typeOf(p.name)}`).join("; ")} }`;
3300
3877
  }
3301
3878
  function hasPathParams(params) {
3302
3879
  return params.some((p) => p.source === "path");
@@ -3390,7 +3967,7 @@ function emitRouterTypeBlock(tree, indent, outDir, serialization) {
3390
3967
  }
3391
3968
  const response = buildResponseType(c, outDir, serialization);
3392
3969
  const error = buildErrorType(c);
3393
- const params = buildParamsType(c.params);
3970
+ const params = buildParamsType(c.params, c.contractSource.paramTypes);
3394
3971
  const safeMethod = JSON.stringify(method);
3395
3972
  const safeUrl = JSON.stringify(c.path);
3396
3973
  const filterLiterals = filterFieldLiterals(c.contractSource.filterFields);
@@ -3659,6 +4236,9 @@ var EMPTY_PATH_NAMESPACE = [
3659
4236
  "}",
3660
4237
  ""
3661
4238
  ];
4239
+ function isClientCallable(route) {
4240
+ return route.method.toUpperCase() !== "ALL";
4241
+ }
3662
4242
  function buildApiFile(routes, outDir, opts = {}) {
3663
4243
  const fetcherImportPath = opts.fetcherImportPath;
3664
4244
  const serialization = opts.serialization ?? "json";
@@ -3666,7 +4246,7 @@ function buildApiFile(routes, outDir, opts = {}) {
3666
4246
  const { layer } = resolveApiSlots(extensions);
3667
4247
  const memberExts = extensions.filter((e) => e.apiMembers);
3668
4248
  const headerExts = extensions.filter((e) => e.apiHeader);
3669
- const contracted = routes.filter((r) => r.contract);
4249
+ const contracted = routes.filter((r) => r.contract && isClientCallable(r));
3670
4250
  const ctx = opts.ctx ?? {
3671
4251
  cwd: outDir ?? "",
3672
4252
  outDir: outDir ?? "",
@@ -4584,6 +5164,7 @@ function buildOpenApiSpec(routes, opts = {}) {
4584
5164
  const paths = {};
4585
5165
  for (const route of routes) {
4586
5166
  if (!route.contract) continue;
5167
+ if (route.method.toUpperCase() === "ALL") continue;
4587
5168
  const oaPath = toOpenApiPath(route.path);
4588
5169
  const method = route.method.toLowerCase();
4589
5170
  let pathItem = paths[oaPath];
@@ -5085,7 +5666,7 @@ async function watch(config, onChange, options = {}) {
5085
5666
  }
5086
5667
 
5087
5668
  // src/index.ts
5088
- var VERSION = "0.25.1";
5669
+ var VERSION = "0.26.0";
5089
5670
 
5090
5671
  // src/generate-manifest.ts
5091
5672
  var MANIFEST_FILE = ".codegen-manifest.json";