History

Build the Ajv instance on first use and mark codemode-core side-effect free

Rhys Sullivan committed 2 months ago

Commit 3bba5fe1 parent dc1b5aa2 files · +28 −8Browse files

Unified · Split

2 files
  1. packages/kernel/core/package.json +1 −0
  2. packages/kernel/core/src/json-schema.ts +27 −8
packages/kernel/core/package.json+1−0
@@ -15,6 +15,7 @@ · 14 unmodified lines
15 "dist"15 "dist"
16 ],16 ],
17 "type": "module",17 "type": "module",
18 "sideEffects": false,
18 "exports": {19 "exports": {
19 ".": "./src/index.ts"20 ".": "./src/index.ts"
20 },21 },
packages/kernel/core/src/json-schema.ts+27−8
@@ -5,14 +5,33 @@ import addFormats from "ajv-formats"; · 4 unmodified lines
5import type { StandardSchema } from "./types";5import type { StandardSchema } from "./types";
6import { unknownInputSchema } from "./types";6import { unknownInputSchema } from "./types";
7 7
8const ajv = new Ajv2020({8// Built on first use, not at import. Two reasons, and the second is the one
9 allErrors: true,9// that matters beyond this file:
10 strict: false,10//
11 validateSchema: false,11// 1. Constructing an Ajv instance and registering every format is real work,
12 allowUnionTypes: true,12// and it ran on each cold isolate that so much as imported this package —
13});13// including the many that never validate a schema.
14// 2. `new Ajv2020(...)` + `addFormats(...)` at module scope are import-time
15// side effects, so a bundler must keep this module (and therefore ajv)
16// whenever anything touches the package barrel. `packages/core/execution`
17// imports exactly one runtime value from it — `CodeExecutionError` — and
18// the rest as erased types, yet still dragged ajv AND sucrase into the
19// server graph. With no module-scope effects left here, `sideEffects:
20// false` in package.json is honest and the unused modules tree-shake out.
21let ajvInstance: Ajv2020 | undefined;
14 22
15addFormats(ajv);23const getAjv = (): Ajv2020 => {
24 if (ajvInstance === undefined) {
25 ajvInstance = new Ajv2020({
26 allErrors: true,
27 strict: false,
28 validateSchema: false,
29 allowUnionTypes: true,
30 });
31 addFormats(ajvInstance);
32 }
33 return ajvInstance;
34};
16 35
17const decodePointerSegment = (segment: string): PropertyKey => {36const decodePointerSegment = (segment: string): PropertyKey => {
18 const decoded = segment.replaceAll("~1", "/").replaceAll("~0", "~");37 const decoded = segment.replaceAll("~1", "/").replaceAll("~0", "~");
@@ -47,7 +66,7 @@ export const standardSchemaFromJsonSchema = ( · 28 unmodified lines
47): StandardSchema => {66): StandardSchema => {
48 // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: AJV compile throws for invalid schemas and this adapter preserves fallback behavior67 // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: AJV compile throws for invalid schemas and this adapter preserves fallback behavior
49 try {68 try {
50 const validate = ajv.compile(schema as Record<string, unknown>);69 const validate = getAjv().compile(schema as Record<string, unknown>);
51 70
52 return {71 return {
53 "~standard": {72 "~standard": {