@dudousxd/nestjs-codegen 0.14.0 → 0.14.2

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.
@@ -605,7 +605,7 @@ function requestShape(route) {
605
605
  const cs = route.contract?.contractSource;
606
606
  const isGet = route.method.toUpperCase() === "GET";
607
607
  const isQuery = isGet || !!cs?.filterFields?.length || !!cs?.asQuery;
608
- const hasBody = !!cs?.bodyRef || cs?.body != null && cs.body !== "never";
608
+ const hasBody = !!cs?.bodyRef || cs?.body != null && cs.body !== "never" || !!cs?.multipart;
609
609
  const hasQuery = isGet || !!cs?.queryRef || cs?.query != null && cs.query !== "never";
610
610
  return { isGet, isQuery, hasBody, hasQuery };
611
611
  }
@@ -2135,8 +2135,9 @@ function debugWarn(message) {
2135
2135
  }
2136
2136
 
2137
2137
  // src/generate.ts
2138
- function driftGuardMessage(outDir, previousEntryPoint, currentEntryPoint) {
2139
- return `[nestjs-codegen] Config drift detected in "${outDir}": the last generate ran from the "${previousEntryPoint}" entry point, this run is from the "${currentEntryPoint}" entry point, and their resolved configs differ (e.g. \`serialization: "json"\` vs \`"superjson"\`). Both entry points must read the SAME config \u2014 export a shared config object (e.g. codegen.config.ts) and import it from BOTH nestjs-codegen.config.ts (CLI) and NestjsCodegenModule.forRoot() (Nest module), or set \`driftGuard: false\` on either config to opt out of this check.`;
2138
+ function driftGuardMessage(outDir, previousEntryPoint, currentEntryPoint, differingKeys) {
2139
+ const differ = differingKeys.length > 0 ? `their resolved configs differ at: ${differingKeys.map((key) => `\`${key}\``).join(", ")}` : "their resolved configs differ (re-run after this generate records per-key hashes to see which keys)";
2140
+ return `[nestjs-codegen] Config drift detected in "${outDir}": the last generate ran from the "${previousEntryPoint}" entry point, this run is from the "${currentEntryPoint}" entry point, and ${differ}. Both entry points must read the SAME config \u2014 export a shared config object (e.g. codegen.config.ts) and import it from BOTH nestjs-codegen.config.ts (CLI) and NestjsCodegenModule.forRoot() (Nest module), or set \`driftGuard: false\` on either config to opt out of this check.`;
2140
2141
  }
2141
2142
  async function generate(config, inputRoutes = [], entryPoint = "cli") {
2142
2143
  setCodegenDebug(config.debug);
@@ -2147,9 +2148,17 @@ async function generate(config, inputRoutes = [], entryPoint = "cli") {
2147
2148
  return;
2148
2149
  }
2149
2150
  const configHash = computeConfigHash(config);
2151
+ const configKeyHashes = computeConfigKeyHashes(config);
2150
2152
  if (config.driftGuard && manifest?.entryPoint && manifest.entryPoint !== entryPoint && manifest.configHash && manifest.configHash !== configHash) {
2151
2153
  throw new DriftGuardError(
2152
- driftGuardMessage(config.codegen.outDir, manifest.entryPoint, entryPoint)
2154
+ driftGuardMessage(
2155
+ config.codegen.outDir,
2156
+ manifest.entryPoint,
2157
+ entryPoint,
2158
+ // A pre-key-hash manifest can't tell us WHICH keys differ — pass none
2159
+ // rather than diffing against {} (which would name every key).
2160
+ manifest.configKeyHashes ? diffConfigKeyHashes(manifest.configKeyHashes, configKeyHashes) : []
2161
+ )
2153
2162
  );
2154
2163
  }
2155
2164
  const extensions = config.extensions ?? [];
@@ -2219,6 +2228,7 @@ async function generate(config, inputRoutes = [], entryPoint = "cli") {
2219
2228
  hash: inputsHash,
2220
2229
  entryPoint,
2221
2230
  configHash,
2231
+ configKeyHashes,
2222
2232
  files: outputFiles
2223
2233
  });
2224
2234
  }
@@ -4633,7 +4643,7 @@ async function watch(config, onChange, options = {}) {
4633
4643
  }
4634
4644
 
4635
4645
  // src/index.ts
4636
- var VERSION = "0.14.0";
4646
+ var VERSION = "0.14.2";
4637
4647
 
4638
4648
  // src/generate-manifest.ts
4639
4649
  var MANIFEST_FILE = ".codegen-manifest.json";
@@ -4654,19 +4664,41 @@ function isManifestShape(value) {
4654
4664
  if (typeof candidate.hash !== "string") return false;
4655
4665
  if (candidate.entryPoint !== void 0 && !isEntryPoint(candidate.entryPoint)) return false;
4656
4666
  if (candidate.configHash !== void 0 && typeof candidate.configHash !== "string") return false;
4667
+ if (candidate.configKeyHashes !== void 0 && !isStringRecord(candidate.configKeyHashes)) {
4668
+ return false;
4669
+ }
4657
4670
  if (!Array.isArray(candidate.files)) return false;
4658
4671
  return candidate.files.every((entry) => typeof entry === "string");
4659
4672
  }
4673
+ function isStringRecord(value) {
4674
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
4675
+ return Object.values(value).every((entry) => typeof entry === "string");
4676
+ }
4660
4677
  function serializeConfig(config) {
4678
+ return serializeConfigValue(config, `unserializable:${config.codegen.outDir}`);
4679
+ }
4680
+ function serializeConfigValue(value, unserializableMarker) {
4661
4681
  try {
4662
- return JSON.stringify(config, (_key, value) => {
4663
- if (typeof value === "function") return `[fn:${value.name}]${value.toString()}`;
4664
- return value;
4682
+ return JSON.stringify(value, (_key, entry) => {
4683
+ if (typeof entry === "function") return `[fn:${entry.name}]`;
4684
+ return entry;
4665
4685
  });
4666
4686
  } catch {
4667
- return `unserializable:${config.codegen.outDir}:${config.contracts.glob}`;
4687
+ return unserializableMarker;
4668
4688
  }
4669
4689
  }
4690
+ function computeConfigKeyHashes(config) {
4691
+ const hashes = {};
4692
+ for (const [key, value] of Object.entries(config)) {
4693
+ if (value === void 0) continue;
4694
+ hashes[key] = (0, import_node_crypto.createHash)("sha256").update(serializeConfigValue(value, `unserializable:${key}`)).digest("hex");
4695
+ }
4696
+ return hashes;
4697
+ }
4698
+ function diffConfigKeyHashes(previous, current) {
4699
+ const keys = /* @__PURE__ */ new Set([...Object.keys(previous), ...Object.keys(current)]);
4700
+ return [...keys].filter((key) => previous[key] !== current[key]).sort();
4701
+ }
4670
4702
  async function discoverInputFiles(config) {
4671
4703
  const globs = [config.contracts.glob, config.forms.watch];
4672
4704
  if (config.pages) globs.push(config.pages.glob);
@@ -4701,6 +4733,7 @@ async function readManifest(outDir) {
4701
4733
  hash: parsed.hash,
4702
4734
  ...parsed.entryPoint ? { entryPoint: parsed.entryPoint } : {},
4703
4735
  ...parsed.configHash ? { configHash: parsed.configHash } : {},
4736
+ ...parsed.configKeyHashes ? { configKeyHashes: parsed.configKeyHashes } : {},
4704
4737
  files: parsed.files
4705
4738
  };
4706
4739
  } catch {