@dudousxd/nestjs-codegen 0.14.2 → 0.15.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
@@ -741,6 +741,9 @@ function buildErrorType(c) {
741
741
  }
742
742
  return c.contractSource.error ?? "unknown";
743
743
  }
744
+ function filterFieldLiterals(fields) {
745
+ return fields?.length ? fields.map((f) => JSON.stringify(f)) : [];
746
+ }
744
747
  function emitRouterTypeBlock(tree, indent, outDir, serialization) {
745
748
  const pad = " ".repeat(indent);
746
749
  const lines = [];
@@ -767,7 +770,8 @@ function emitRouterTypeBlock(tree, indent, outDir, serialization) {
767
770
  const params = buildParamsType(c.params);
768
771
  const safeMethod = JSON.stringify(method);
769
772
  const safeUrl = JSON.stringify(c.path);
770
- const filterFields = c.contractSource.filterFields?.length ? c.contractSource.filterFields.map((f) => JSON.stringify(f)).join(" | ") : "never";
773
+ const filterLiterals = filterFieldLiterals(c.contractSource.filterFields);
774
+ const filterFields = filterLiterals.length ? filterLiterals.join(" | ") : "never";
771
775
  const stream = c.contractSource.stream ? "true" : "false";
772
776
  const binary = c.contractSource.binaryResponse ? "true" : "false";
773
777
  lines.push(
@@ -807,6 +811,7 @@ function buildRequestModel(c) {
807
811
  const TA = buildRouterTypeAccess(c.name);
808
812
  const withParams = hasPathParams(c.params);
809
813
  const { isGet, isQuery, hasBody, hasQuery } = requestShape(c.route);
814
+ const filterLiterals = filterFieldLiterals(c.contractSource.filterFields);
810
815
  const fields = [];
811
816
  if (withParams) fields.push(`params: ${TA}['params']`);
812
817
  if (hasQuery) fields.push(`query?: ${TA}['query']`);
@@ -836,7 +841,12 @@ function buildRequestModel(c) {
836
841
  // (`[name]` rather than `[name, undefined]`) so the bare `.queryKey()` is a
837
842
  // clean prefix that partial-matches every parametrized variant — making it
838
843
  // directly usable for `invalidateQueries`.
839
- queryKeyExpr: `(input === undefined ? [${flat}] as const : [${flat}, input] as const)`
844
+ queryKeyExpr: `(input === undefined ? [${flat}] as const : [${flat}, input] as const)`,
845
+ // Runtime counterpart to the type-level `filterFields` union: the same
846
+ // discovered field list, emitted as a literal `[...] as const` so apps can
847
+ // validate a dynamic/user-supplied field string with `isFilterField(...)`
848
+ // instead of casting. Omitted for routes with no filter.
849
+ ...filterLiterals.length ? { filterFieldsExpr: `[${filterLiterals.join(", ")}] as const` } : {}
840
850
  };
841
851
  }
842
852
  function renderFetcherRequest(req, binaryResponse) {
@@ -871,9 +881,24 @@ function emitReqHelper() {
871
881
  ""
872
882
  ];
873
883
  }
884
+ function emitFilterFieldGuard() {
885
+ return [
886
+ "/** Runtime guard: narrows `value` to one of the leaf's `filterFields` (a `readonly K[] as const`), so a dynamic field string can be passed to `.where()` without a cast. */",
887
+ "export function isFilterField<const K extends string>(",
888
+ " fields: readonly K[],",
889
+ " value: string,",
890
+ "): value is K {",
891
+ " return (fields as readonly string[]).includes(value);",
892
+ "}",
893
+ ""
894
+ ];
895
+ }
874
896
  function renderLeaf(pad, objKey, req, requestExpr, members, streamExpr) {
875
897
  const lines = [`${pad}${objKey}: (input?: ${req.inputType}) => ({`];
876
898
  lines.push(`${pad} ...__req<${req.responseType}>(() => ${requestExpr}),`);
899
+ if (req.filterFieldsExpr) {
900
+ lines.push(`${pad} filterFields: ${req.filterFieldsExpr},`);
901
+ }
877
902
  if (streamExpr) {
878
903
  lines.push(`${pad} stream: () => ${streamExpr},`);
879
904
  }
@@ -1145,6 +1170,9 @@ function buildApiFile(routes, outDir, opts = {}) {
1145
1170
  lines.push("};");
1146
1171
  lines.push("");
1147
1172
  lines.push(...emitReqHelper());
1173
+ if (contracted.some((r) => r.contract?.contractSource.filterFields?.length)) {
1174
+ lines.push(...emitFilterFieldGuard());
1175
+ }
1148
1176
  lines.push("export function createApi(fetcher: Fetcher) {");
1149
1177
  lines.push(" return {");
1150
1178
  lines.push(
@@ -4815,7 +4843,7 @@ async function watch(config, onChange, options = {}) {
4815
4843
  }
4816
4844
 
4817
4845
  // src/index.ts
4818
- var VERSION = "0.14.2";
4846
+ var VERSION = "0.15.0";
4819
4847
 
4820
4848
  // src/cli/codegen.ts
4821
4849
  async function runCodegen(opts = {}) {