@amritk/generate-parsers 0.11.0 → 0.11.1

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.
@@ -796,6 +796,40 @@ const generateObjectParser = (schema, typeName, useRefImports, suffix, logWarnin
796
796
  lines.push(objectLines.join('\n'));
797
797
  lines.push(` } as unknown as ${typeName};`);
798
798
  };
799
+ // The deep-guard fast path. `{ ...input }` is the only correct shape when the
800
+ // guard let undeclared keys through (no known-keys term) — they must survive.
801
+ // But when `stripKeys` is set the guard *also* proved `_hasOnlyKnownKeys`, so
802
+ // the input's keys are exactly the declared properties: an explicit literal of
803
+ // those keys is then equivalent to the spread, and faster — a fixed-shape
804
+ // literal beats a generic spread, yields a stable hidden class, and produces
805
+ // the same declared key order as the slow path (the spread used input order).
806
+ // The literal shares each value by reference, exactly like the spread did, so
807
+ // it never re-parses an already-validated nested object. allOf merges in
808
+ // properties this `propInfo` list doesn't carry, so it keeps the spread.
809
+ const emitDeepGuardReturn = (lines) => {
810
+ const canLiteral = stripKeys && !(isSchemaObject(schema) && hasAllOf(schema));
811
+ if (!canLiteral) {
812
+ lines.push(` if (${deepGuard}) return { ...input } as ${typeName};`);
813
+ return;
814
+ }
815
+ const fields = [];
816
+ for (const { key, varName, isRequired, propSchema } of propInfo) {
817
+ if (!isSchemaObject(propSchema)) {
818
+ if (isRequired)
819
+ fields.push(` ${safeKey(key)}: undefined,`);
820
+ continue;
821
+ }
822
+ const accessor = shouldCacheVariable(propSchema, canFastPath, useRefImports)
823
+ ? varName
824
+ : safeAccessor('input', key);
825
+ fields.push(isRequired
826
+ ? ` ${safeKey(key)}: ${accessor},`
827
+ : ` ...(${accessor} !== undefined && { ${safeKey(key)}: ${accessor} }),`);
828
+ }
829
+ lines.push(` if (${deepGuard}) return {`);
830
+ lines.push(fields.join('\n'));
831
+ lines.push(` } as ${typeName};`);
832
+ };
799
833
  const lines = [];
800
834
  lines.push(`${exportPrefix}const ${functionName} = (input: unknown): ${typeName} => {`);
801
835
  if (strict) {
@@ -819,7 +853,7 @@ const generateObjectParser = (schema, typeName, useRefImports, suffix, logWarnin
819
853
  }
820
854
  else {
821
855
  if (deepGuard) {
822
- lines.push(` if (${deepGuard}) return { ...input } as ${typeName};`);
856
+ emitDeepGuardReturn(lines);
823
857
  }
824
858
  for (const assertionLine of assertionLines) {
825
859
  lines.push(assertionLine);
@@ -837,7 +871,7 @@ const generateObjectParser = (schema, typeName, useRefImports, suffix, logWarnin
837
871
  lines.push(...varDeclLines);
838
872
  lines.push(...warnLines);
839
873
  if (deepGuard) {
840
- lines.push(` if (${deepGuard}) return { ...input } as ${typeName};`);
874
+ emitDeepGuardReturn(lines);
841
875
  }
842
876
  emitReturn(lines, buildObjectLines(false));
843
877
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amritk/generate-parsers",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "Generate TypeScript parsers and type definitions from JSON Schemas.",
5
5
  "module": "./dist/index.js",
6
6
  "type": "module",