@palantir/pack.schema 0.3.0 → 0.4.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/.turbo/turbo-lint.log +3 -3
- package/.turbo/turbo-transpileBrowser.log +1 -1
- package/.turbo/turbo-transpileCjs.log +1 -1
- package/.turbo/turbo-transpileEsm.log +1 -1
- package/.turbo/turbo-transpileTypes.log +1 -1
- package/.turbo/turbo-typecheck.log +1 -1
- package/CHANGELOG.md +15 -0
- package/build/browser/index.js +55 -5
- package/build/browser/index.js.map +1 -1
- package/build/cjs/index.cjs +57 -4
- package/build/cjs/index.cjs.map +1 -1
- package/build/cjs/index.d.cts +39 -5
- package/build/esm/index.js +55 -5
- package/build/esm/index.js.map +1 -1
- package/build/types/__tests__/defineSchemaUpdate.test.d.ts +1 -0
- package/build/types/__tests__/defineSchemaUpdate.test.d.ts.map +1 -0
- package/build/types/defineMigration.d.ts +9 -7
- package/build/types/defineMigration.d.ts.map +1 -1
- package/build/types/defineSchemaUpdate.d.ts +38 -0
- package/build/types/defineSchemaUpdate.d.ts.map +1 -0
- package/build/types/defs.d.ts +1 -0
- package/build/types/defs.d.ts.map +1 -1
- package/build/types/index.d.ts +1 -0
- package/build/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/defineSchemaUpdate.test.ts +365 -0
- package/src/defineMigration.ts +13 -29
- package/src/defineSchemaUpdate.ts +114 -0
- package/src/defs.ts +1 -0
- package/src/index.ts +1 -0
package/build/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/defs.ts","../../src/primitives.ts","../../src/utils.ts","../../src/defineUnion.ts","../../src/defineMigration.ts","../../src/defineRecord.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const ModelDefType = {\n RECORD: \"record\",\n UNION: \"union\"\n};","/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const TypeKind = {\n ARRAY: \"array\",\n BOOLEAN: \"boolean\",\n DOC_REF: \"docRef\",\n DOUBLE: \"double\",\n MEDIA_REF: \"mediaRef\",\n OBJECT_REF: \"objectRef\",\n OPTIONAL: \"optional\",\n REF: \"ref\",\n STRING: \"string\",\n UNKNOWN: \"unknown\",\n USER_REF: \"userRef\"\n};\n\n// Forward declaration to avoid circular reference\n\n// A reference to a record or a union type\n\nexport const String = {\n type: TypeKind.STRING\n};\nexport const Double = {\n type: TypeKind.DOUBLE\n};\nexport const Boolean = {\n type: TypeKind.BOOLEAN\n};\nexport const Unknown = {\n type: TypeKind.UNKNOWN\n};\nexport const Array = item => ({\n type: TypeKind.ARRAY,\n items: item\n});\nexport const Optional = item => ({\n type: TypeKind.OPTIONAL,\n item\n});","/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ModelDefType } from \"./defs.js\";\nimport { TypeKind } from \"./primitives.js\";\n\n/**\n * Helper function to safely transform a record definition to a reference.\n * This function helps TypeScript track type transformations better.\n */\nexport function modelToRef(model) {\n return createRef(model.name, model.type);\n}\n\n/**\n * Helper function to create a reference with proper typing.\n * This avoids type assertions in multiple places.\n */\nexport function createRef(name, refType) {\n return {\n type: TypeKind.REF,\n name,\n refType\n };\n}\n\n/**\n * Type guard to check if a value is a RecordDef\n */\nexport function isRecordDef(value) {\n return value != null && typeof value === \"object\" && \"type\" in value && value.type === ModelDefType.RECORD && \"fields\" in value;\n}\n\n/**\n * Type guard to check if a value is a UnionDef\n */\nexport function isUnionDef(value) {\n return value != null && typeof value === \"object\" && \"type\" in value && value.type === ModelDefType.UNION && \"variants\" in value;\n}","/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ModelDefType } from \"./defs.js\";\nimport { TypeKind } from \"./primitives.js\";\nimport { modelToRef } from \"./utils.js\";\nexport function defineUnion(name, {\n discriminant = \"type\",\n docs,\n variants\n}) {\n const entries = Object.entries(variants).map(([key, value]) => [key, resolveUnionVariantArg(value)]);\n const resolvedVariants = Object.fromEntries(entries);\n return {\n type: ModelDefType.UNION,\n discriminant,\n name,\n docs,\n variants: resolvedVariants\n };\n}\nexport function resolveUnionVariantArg(arg) {\n const resolved = typeof arg === \"function\" ? arg() : arg;\n return resolved.type === TypeKind.REF ? resolved : modelToRef(resolved);\n}","/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { resolveUnionVariantArg } from \"./defineUnion.js\";\nimport { ModelDefType } from \"./defs.js\";\nimport { isRecordDef, isUnionDef } from \"./utils.js\";\nclass UnionBuilderImpl {\n name;\n docs;\n variants;\n constructor({\n name,\n docs,\n variants\n }) {\n this.name = name;\n this.docs = docs;\n this.variants = {\n ...variants\n };\n }\n addVariant(variantName, modelDefOrRef) {\n const ref = resolveUnionVariantArg(modelDefOrRef);\n const newVariants = {\n ...this.variants,\n [variantName]: ref\n };\n return new UnionBuilderImpl({\n type: ModelDefType.UNION,\n name: this.name,\n variants: newVariants,\n discriminant: \"type\"\n });\n }\n build() {\n return {\n type: ModelDefType.UNION,\n variants: this.variants,\n discriminant: \"type\",\n name: this.name\n };\n }\n}\nclass RecordBuilderImpl {\n name;\n fields;\n constructor(initialRecordDef) {\n this.name = initialRecordDef.name;\n this.fields = {\n ...initialRecordDef.fields\n };\n }\n\n // TODO: resolve field value from arg instead\n addField(name, value) {\n return new RecordBuilderImpl({\n type: ModelDefType.RECORD,\n name: this.name,\n fields: {\n ...this.fields,\n [name]: value\n },\n docs: \"\"\n });\n }\n build() {\n return {\n type: ModelDefType.RECORD,\n name: this.name,\n fields: this.fields,\n docs: \"\"\n };\n }\n}\nexport function defineMigration(previous, migration) {\n /**\n * Create a map of builders for the schema.\n *\n * Note about type assertions:\n * We use a type assertion here (SchemaBuilder<T>) because TypeScript cannot\n * track the relationship between the keys in the original schema and the\n * corresponding builder types. This is a fundamental limitation of TypeScript's\n * type system when dealing with dynamically constructed objects.\n *\n * The assertion is safe because:\n * 1. We're only adding keys that exist in the original schema\n * 2. For each key, we're creating a builder of the correct type\n * 3. The resulting object exactly matches the SchemaBuilder<T> type\n */\n const builders = {};\n for (const key in previous) {\n const v = previous[key];\n\n // Use our type guards for safer type narrowing\n if (isRecordDef(v)) {\n // This assertion is necessary because TypeScript can't track the field types\n // through the dynamic property access and object construction\n const recordBuilder = new RecordBuilderImpl(v);\n builders[key] = recordBuilder;\n } else if (isUnionDef(v)) {\n // Similar assertion needed for union builders\n const unionBuilder = new UnionBuilderImpl(v);\n builders[key] = unionBuilder;\n }\n }\n return {\n ...previous,\n ...migration(builders)\n };\n}","/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ModelDefType } from \"./defs.js\";\nimport { isRecordDef, isUnionDef, modelToRef } from \"./utils.js\";\n/**\n * Helper function to resolve a field value, handling functions and transforming\n * types as needed.\n */\nfunction resolveFieldArg(value) {\n // Handle function values\n const resolved = typeof value === \"function\" ? value() : value;\n if (isRecordDef(resolved) || isUnionDef(resolved)) {\n return modelToRef(resolved);\n }\n\n // For primitive types and other Types\n return resolved;\n}\nexport function defineRecord(name, record) {\n const entries = Object.entries(record.fields).map(([key, value]) => [key, resolveFieldArg(value)]);\n const fields = Object.fromEntries(entries);\n return {\n type: ModelDefType.RECORD,\n name: name,\n docs: record.docs,\n fields\n };\n}"]}
|
|
1
|
+
{"version":3,"sources":["../../src/defs.ts","../../src/primitives.ts","../../src/utils.ts","../../src/defineUnion.ts","../../src/defineMigration.ts","../../src/defineRecord.ts","../../src/defineSchemaUpdate.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const ModelDefType = {\n RECORD: \"record\",\n UNION: \"union\"\n};","/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const TypeKind = {\n ARRAY: \"array\",\n BOOLEAN: \"boolean\",\n DOC_REF: \"docRef\",\n DOUBLE: \"double\",\n MEDIA_REF: \"mediaRef\",\n OBJECT_REF: \"objectRef\",\n OPTIONAL: \"optional\",\n REF: \"ref\",\n STRING: \"string\",\n UNKNOWN: \"unknown\",\n USER_REF: \"userRef\"\n};\n\n// Forward declaration to avoid circular reference\n\n// A reference to a record or a union type\n\nexport const String = {\n type: TypeKind.STRING\n};\nexport const Double = {\n type: TypeKind.DOUBLE\n};\nexport const Boolean = {\n type: TypeKind.BOOLEAN\n};\nexport const Unknown = {\n type: TypeKind.UNKNOWN\n};\nexport const Array = item => ({\n type: TypeKind.ARRAY,\n items: item\n});\nexport const Optional = item => ({\n type: TypeKind.OPTIONAL,\n item\n});","/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ModelDefType } from \"./defs.js\";\nimport { TypeKind } from \"./primitives.js\";\n\n/**\n * Helper function to safely transform a record definition to a reference.\n * This function helps TypeScript track type transformations better.\n */\nexport function modelToRef(model) {\n return createRef(model.name, model.type);\n}\n\n/**\n * Helper function to create a reference with proper typing.\n * This avoids type assertions in multiple places.\n */\nexport function createRef(name, refType) {\n return {\n type: TypeKind.REF,\n name,\n refType\n };\n}\n\n/**\n * Type guard to check if a value is a RecordDef\n */\nexport function isRecordDef(value) {\n return value != null && typeof value === \"object\" && \"type\" in value && value.type === ModelDefType.RECORD && \"fields\" in value;\n}\n\n/**\n * Type guard to check if a value is a UnionDef\n */\nexport function isUnionDef(value) {\n return value != null && typeof value === \"object\" && \"type\" in value && value.type === ModelDefType.UNION && \"variants\" in value;\n}","/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ModelDefType } from \"./defs.js\";\nimport { TypeKind } from \"./primitives.js\";\nimport { modelToRef } from \"./utils.js\";\nexport function defineUnion(name, {\n discriminant = \"type\",\n docs,\n variants\n}) {\n const entries = Object.entries(variants).map(([key, value]) => [key, resolveUnionVariantArg(value)]);\n const resolvedVariants = Object.fromEntries(entries);\n return {\n type: ModelDefType.UNION,\n discriminant,\n name,\n docs,\n variants: resolvedVariants\n };\n}\nexport function resolveUnionVariantArg(arg) {\n const resolved = typeof arg === \"function\" ? arg() : arg;\n return resolved.type === TypeKind.REF ? resolved : modelToRef(resolved);\n}","/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { resolveUnionVariantArg } from \"./defineUnion.js\";\nimport { ModelDefType } from \"./defs.js\";\nimport { isRecordDef, isUnionDef } from \"./utils.js\";\n\n/** Soon to be deprecated - Use `ModelDefs` instead. */\n\n/** Soon to be deprecated - use `ModelDefs` instead. */\n\nclass UnionBuilderImpl {\n name;\n docs;\n variants;\n constructor({\n name,\n docs,\n variants\n }) {\n this.name = name;\n this.docs = docs;\n this.variants = {\n ...variants\n };\n }\n addVariant(variantName, modelDefOrRef) {\n const ref = resolveUnionVariantArg(modelDefOrRef);\n const newVariants = {\n ...this.variants,\n [variantName]: ref\n };\n return new UnionBuilderImpl({\n type: ModelDefType.UNION,\n name: this.name,\n variants: newVariants,\n discriminant: \"type\"\n });\n }\n build() {\n return {\n type: ModelDefType.UNION,\n variants: this.variants,\n discriminant: \"type\",\n name: this.name\n };\n }\n}\nclass RecordBuilderImpl {\n name;\n fields;\n constructor(initialRecordDef) {\n this.name = initialRecordDef.name;\n this.fields = {\n ...initialRecordDef.fields\n };\n }\n\n // TODO: resolve field value from arg instead\n addField(name, value) {\n return new RecordBuilderImpl({\n type: ModelDefType.RECORD,\n name: this.name,\n fields: {\n ...this.fields,\n [name]: value\n },\n docs: \"\"\n });\n }\n build() {\n return {\n type: ModelDefType.RECORD,\n name: this.name,\n fields: this.fields,\n docs: \"\"\n };\n }\n}\nexport function defineMigration(models, migration) {\n const builders = {};\n for (const key in models) {\n const v = models[key];\n if (isRecordDef(v)) {\n const recordBuilder = new RecordBuilderImpl(v);\n builders[key] = recordBuilder;\n } else if (isUnionDef(v)) {\n const unionBuilder = new UnionBuilderImpl(v);\n builders[key] = unionBuilder;\n }\n }\n return {\n ...models,\n ...migration(builders)\n };\n}","/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ModelDefType } from \"./defs.js\";\nimport { isRecordDef, isUnionDef, modelToRef } from \"./utils.js\";\n/**\n * Helper function to resolve a field value, handling functions and transforming\n * types as needed.\n */\nfunction resolveFieldArg(value) {\n // Handle function values\n const resolved = typeof value === \"function\" ? value() : value;\n if (isRecordDef(resolved) || isUnionDef(resolved)) {\n return modelToRef(resolved);\n }\n\n // For primitive types and other Types\n return resolved;\n}\nexport function defineRecord(name, record) {\n const entries = Object.entries(record.fields).map(([key, value]) => [key, resolveFieldArg(value)]);\n const fields = Object.fromEntries(entries);\n return {\n type: ModelDefType.RECORD,\n name: name,\n docs: record.docs,\n fields\n };\n}","/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { defineMigration } from \"./defineMigration.js\";\nexport function defineSchema(models) {\n return {\n type: \"initial\",\n version: 1,\n models\n };\n}\nexport function defineSchemaUpdate(name, migration) {\n return {\n name,\n migration\n };\n}\nclass SchemaVersionBuilderImpl {\n models;\n version;\n previous;\n _migrations;\n constructor(models, version, previous, migrations) {\n this.models = models;\n this.version = version;\n this.previous = previous;\n this._migrations = migrations;\n }\n addSchemaUpdate(update) {\n const merged = defineMigration(this.models, update.migration);\n return new SchemaVersionBuilderImpl(merged, this.version, this.previous, this._migrations);\n }\n withMigrations(migrations) {\n return new SchemaVersionBuilderImpl(this.models, this.version, this.previous, migrations);\n }\n build() {\n return {\n type: \"versioned\",\n models: {\n ...this.models\n },\n version: this.version,\n previous: this.previous,\n ...(this._migrations != null ? {\n migrations: this._migrations\n } : {})\n };\n }\n}\nexport function nextSchema(previous) {\n return new SchemaVersionBuilderImpl(previous.models, previous.version + 1, previous);\n}"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"mappings":"","names":[],"sources":["../../../src/__tests__/defineSchemaUpdate.test.ts"],"version":3,"file":"defineSchemaUpdate.test.d.ts"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { UnionVariantArg } from "./defineUnion.js";
|
|
2
|
-
import type { RecordDef, UnionDef, UnionVariants } from "./defs.js";
|
|
2
|
+
import type { ModelDefs, RecordDef, UnionDef, UnionVariants } from "./defs.js";
|
|
3
3
|
import type { Ref, Type } from "./primitives.js";
|
|
4
|
-
|
|
5
|
-
export type
|
|
6
|
-
|
|
4
|
+
/** Soon to be deprecated - Use `ModelDefs` instead. */
|
|
5
|
+
export type ReturnedSchema = ModelDefs;
|
|
6
|
+
/** Soon to be deprecated - use `ModelDefs` instead. */
|
|
7
|
+
export type Schema<T extends ModelDefs> = T;
|
|
8
|
+
export type SchemaBuilder<T extends ModelDefs> = { [k in keyof T] : T[k] extends UnionDef<infer R> ? UnionBuilder<R> : T[k] extends RecordDef<infer R> ? RecordBuilder<R> : never };
|
|
7
9
|
export interface RecordBuilder<T extends Record<string, Type>> {
|
|
8
10
|
addField<
|
|
9
11
|
const K extends string,
|
|
@@ -16,6 +18,6 @@ export interface UnionBuilder<S extends UnionVariants> {
|
|
|
16
18
|
build(): UnionDef<S>;
|
|
17
19
|
}
|
|
18
20
|
export declare function defineMigration<
|
|
19
|
-
const T extends
|
|
20
|
-
const S extends
|
|
21
|
-
>(
|
|
21
|
+
const T extends ModelDefs,
|
|
22
|
+
const S extends ModelDefs
|
|
23
|
+
>(models: T, migration: (schema: SchemaBuilder<T>) => S): T & S;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AAgBA,cAAc,uBAAuB;AAErC,cAAc,WAAyB,UAAU,qBAAqB;
|
|
1
|
+
{"mappings":"AAgBA,cAAc,uBAAuB;AAErC,cAAc,WAAW,WAAyB,UAAU,qBAAqB;AAEjF,cAAc,KAAK,YAAY;;AAI/B,YAAY,iBAAiB;;AAG7B,YAAY,OAAO,UAAU,aAAa;AAE1C,YAAY,cAAc,UAAU,gBACjC,WAAW,KAAI,EAAE,WAAW,eAAe,KAAK,aAAa,KAC1D,EAAE,WAAW,gBAAgB,KAAK,cAAc;AAItD,iBAAiB,cAAc,UAAU,eAAe,OAAO;CAE7D;QAAe;EAAkB,UAAU;GACzC,MAAM,GACN,MAAM,IACL,cAAc,OAAO,KAAK,KAAI;CACjC,SAAS,UAAU;;AAGrB,iBAAiB,aAAa,UAAU,eAAe;CAErD,iBAAiB,kBACf,MAAM,GACN,eAAe,kBACd,aAAa,OAAO,KAAK,KAAI;CAChC,SAAS,SAAS;;AAmEpB,OAAO,iBAAS;OACR,UAAU;OACV,UAAU;EAEhB,QAAQ,GACR,YAAY,QAAQ,cAAc,OAAO,IACxC,IAAI","names":[],"sources":["../../src/defineMigration.ts"],"version":3,"file":"defineMigration.d.ts"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { SchemaBuilder } from "./defineMigration.js";
|
|
2
|
+
import type { ModelDefs } from "./defs.js";
|
|
3
|
+
export interface InitialSchema<T extends ModelDefs = ModelDefs> {
|
|
4
|
+
readonly type: "initial";
|
|
5
|
+
readonly version: 1;
|
|
6
|
+
readonly models: T;
|
|
7
|
+
}
|
|
8
|
+
export interface FieldMigration {
|
|
9
|
+
readonly derivedFrom: readonly string[];
|
|
10
|
+
readonly forward: (oldFields: Record<string, unknown>) => unknown;
|
|
11
|
+
}
|
|
12
|
+
export type VersionMigrations = Record<string, Record<string, FieldMigration>>;
|
|
13
|
+
export interface VersionedSchema<T extends ModelDefs = ModelDefs> {
|
|
14
|
+
readonly type: "versioned";
|
|
15
|
+
readonly models: T;
|
|
16
|
+
readonly version: number;
|
|
17
|
+
readonly previous: SchemaDefinition;
|
|
18
|
+
readonly migrations?: VersionMigrations;
|
|
19
|
+
}
|
|
20
|
+
export type SchemaDefinition<T extends ModelDefs = ModelDefs> = InitialSchema<T> | VersionedSchema<T>;
|
|
21
|
+
export declare function defineSchema<T extends ModelDefs>(models: T): InitialSchema<T>;
|
|
22
|
+
export interface SchemaUpdate<
|
|
23
|
+
T extends ModelDefs,
|
|
24
|
+
S extends ModelDefs
|
|
25
|
+
> {
|
|
26
|
+
readonly name: string;
|
|
27
|
+
readonly migration: (schema: SchemaBuilder<T>) => S;
|
|
28
|
+
}
|
|
29
|
+
export declare function defineSchemaUpdate<
|
|
30
|
+
T extends ModelDefs,
|
|
31
|
+
S extends ModelDefs
|
|
32
|
+
>(name: string, migration: (schema: SchemaBuilder<T>) => S): SchemaUpdate<T, S>;
|
|
33
|
+
export interface SchemaVersionBuilder<T extends ModelDefs> {
|
|
34
|
+
addSchemaUpdate<S extends ModelDefs>(update: SchemaUpdate<T, S>): SchemaVersionBuilder<T & S>;
|
|
35
|
+
withMigrations(migrations: VersionMigrations): SchemaVersionBuilder<T>;
|
|
36
|
+
build(): VersionedSchema<T>;
|
|
37
|
+
}
|
|
38
|
+
export declare function nextSchema<T extends ModelDefs>(previous: SchemaDefinition<T>): SchemaVersionBuilder<T>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"mappings":"AAgBA,cAAc,qBAAqB;AAEnC,cAAc,iBAAiB;AAE/B,iBAAiB,cAAc,UAAU,YAAY,WAAW;UACrD,MAAM;UACN,SAAS;UACT,QAAQ;;AAGnB,iBAAiB,eAAe;UACrB;UACA,UAAU,WAAW;;AAGhC,YAAY,oBAAoB,eAAe,eAAe;AAE9D,iBAAiB,gBAAgB,UAAU,YAAY,WAAW;UACvD,MAAM;UACN,QAAQ;UACR;UACA,UAAU;UACV,aAAa;;AAGxB,YAAY,iBAAiB,UAAU,YAAY,aAC/C,cAAc,KACd,gBAAgB;AAEpB,OAAO,iBAAS,aAAa,UAAU,WAAW,QAAQ,IAAI,cAAc;AAI5E,iBAAiB;CAAa,UAAU;CAAW,UAAU;EAAW;UAC7D;UACA,YAAY,QAAQ,cAAc,OAAO;;AAGpD,OAAO,iBAAS;CAAmB,UAAU;CAAW,UAAU;EAChE,cACA,YAAY,QAAQ,cAAc,OAAO,IACxC,aAAa,GAAG;AAInB,iBAAiB,qBAAqB,UAAU,WAAW;CACzD,gBAAgB,UAAU,WACxB,QAAQ,aAAa,GAAG,KACvB,qBAAqB,IAAI;CAC5B,eAAe,YAAY,oBAAoB,qBAAqB;CACpE,SAAS,gBAAgB;;AA2C3B,OAAO,iBAAS,WAAW,UAAU,WACnC,UAAU,iBAAiB,KAC1B,qBAAqB","names":[],"sources":["../../src/defineSchemaUpdate.ts"],"version":3,"file":"defineSchemaUpdate.d.ts"}
|
package/build/types/defs.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AAgBA,cAAc,KAAK,YAAY;AAE/B,OAAO,cAAM;UACX,QAAQ;UACR,OAAO;;AAGT,YAAY,sBAAsB,0BAA0B;UAElD,aAAa;UACZ,MAAM;UACN;UACA;;AAGX,YAAY,eAAe,eAAe;AAC1C,YAAY,gBAAgB,eAAe;AAE3C,iBAAiB,SAAS,kBAAkB,gBAAgB,uBAAuB,aAAa;UACrF,aAAa,aAAa;UAC1B,UAAU;UACV;;AAGX,iBAAiB,UAAU,gBAAgB,eAAe,sBAAsB,aAAa;UAClF,aAAa,aAAa;UAC1B,QAAQ;;AAGnB,YAAY,WAAW,YAAY","names":[],"sources":["../../src/defs.ts"],"version":3,"file":"defs.d.ts"}
|
|
1
|
+
{"mappings":"AAgBA,cAAc,KAAK,YAAY;AAE/B,OAAO,cAAM;UACX,QAAQ;UACR,OAAO;;AAGT,YAAY,sBAAsB,0BAA0B;UAElD,aAAa;UACZ,MAAM;UACN;UACA;;AAGX,YAAY,eAAe,eAAe;AAC1C,YAAY,gBAAgB,eAAe;AAE3C,iBAAiB,SAAS,kBAAkB,gBAAgB,uBAAuB,aAAa;UACrF,aAAa,aAAa;UAC1B,UAAU;UACV;;AAGX,iBAAiB,UAAU,gBAAgB,eAAe,sBAAsB,aAAa;UAClF,aAAa,aAAa;UAC1B,QAAQ;;AAGnB,YAAY,WAAW,YAAY;AACnC,YAAY,YAAY,eAAe","names":[],"sources":["../../src/defs.ts"],"version":3,"file":"defs.d.ts"}
|
package/build/types/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AAgBA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc","names":[],"sources":["../../src/index.ts"],"version":3,"file":"index.d.ts"}
|
|
1
|
+
{"mappings":"AAgBA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc","names":[],"sources":["../../src/index.ts"],"version":3,"file":"index.d.ts"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026 Palantir Technologies, Inc. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { describe, expect, it } from "vitest";
|
|
18
|
+
import type { SchemaBuilder } from "../defineMigration.js";
|
|
19
|
+
import { defineRecord } from "../defineRecord.js";
|
|
20
|
+
import { defineSchema, defineSchemaUpdate, nextSchema } from "../defineSchemaUpdate.js";
|
|
21
|
+
import { defineUnion } from "../defineUnion.js";
|
|
22
|
+
import * as P from "../primitives.js";
|
|
23
|
+
import { assertExactKeys, assertHasKeys, assertTypeEquals } from "./testTypeUtils.js";
|
|
24
|
+
|
|
25
|
+
describe("defineSchemaUpdate", () => {
|
|
26
|
+
it("should create a schema update and apply it via nextSchema", () => {
|
|
27
|
+
const schemaV1 = defineSchema({
|
|
28
|
+
Person: defineRecord("Person", {
|
|
29
|
+
docs: "A person",
|
|
30
|
+
fields: {
|
|
31
|
+
name: P.String,
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const addAge = defineSchemaUpdate(
|
|
37
|
+
"addAge",
|
|
38
|
+
(schema: SchemaBuilder<typeof schemaV1.models>) => ({
|
|
39
|
+
PersonV2: schema.Person.addField("age", P.Double).build(),
|
|
40
|
+
}),
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const schemaV2 = nextSchema(schemaV1).addSchemaUpdate(addAge).build();
|
|
44
|
+
|
|
45
|
+
expect(schemaV2.models.Person).toBe(schemaV1.models.Person);
|
|
46
|
+
expect(schemaV2.models.PersonV2.fields.name).toEqual({ type: "string" });
|
|
47
|
+
expect(schemaV2.models.PersonV2.fields.age).toEqual({ type: "double" });
|
|
48
|
+
expect(schemaV2.version).toBe(2);
|
|
49
|
+
|
|
50
|
+
assertHasKeys<typeof schemaV2.models, "Person" | "PersonV2">();
|
|
51
|
+
assertExactKeys<typeof schemaV2.models.PersonV2.fields, "name" | "age">();
|
|
52
|
+
assertTypeEquals<typeof schemaV2.models.PersonV2.fields.name, P.String>();
|
|
53
|
+
assertTypeEquals<typeof schemaV2.models.PersonV2.fields.age, P.Double>();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("should compose multiple schema updates in one version", () => {
|
|
57
|
+
const schemaV1 = defineSchema({
|
|
58
|
+
ShapeBox: defineRecord("ShapeBox", {
|
|
59
|
+
docs: "A box shape",
|
|
60
|
+
fields: {
|
|
61
|
+
left: P.Double,
|
|
62
|
+
right: P.Double,
|
|
63
|
+
color: P.Optional(P.String),
|
|
64
|
+
},
|
|
65
|
+
}),
|
|
66
|
+
ShapeCircle: defineRecord("ShapeCircle", {
|
|
67
|
+
docs: "A circle shape",
|
|
68
|
+
fields: {
|
|
69
|
+
cx: P.Double,
|
|
70
|
+
radius: P.Double,
|
|
71
|
+
color: P.Optional(P.String),
|
|
72
|
+
},
|
|
73
|
+
}),
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const addFillColor = defineSchemaUpdate(
|
|
77
|
+
"addFillColor",
|
|
78
|
+
(schema: SchemaBuilder<typeof schemaV1.models>) => ({
|
|
79
|
+
ShapeBox: schema.ShapeBox
|
|
80
|
+
.addField("fillColor", P.Optional(P.String))
|
|
81
|
+
.build(),
|
|
82
|
+
ShapeCircle: schema.ShapeCircle
|
|
83
|
+
.addField("fillColor", P.Optional(P.String))
|
|
84
|
+
.build(),
|
|
85
|
+
}),
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const addOpacity = defineSchemaUpdate(
|
|
89
|
+
"addOpacity",
|
|
90
|
+
(schema: SchemaBuilder<typeof schemaV1.models>) => ({
|
|
91
|
+
ShapeBox: schema.ShapeBox
|
|
92
|
+
.addField("opacity", P.Optional(P.Double))
|
|
93
|
+
.build(),
|
|
94
|
+
ShapeCircle: schema.ShapeCircle
|
|
95
|
+
.addField("opacity", P.Optional(P.Double))
|
|
96
|
+
.build(),
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const schemaV2 = nextSchema(schemaV1)
|
|
101
|
+
.addSchemaUpdate(addFillColor)
|
|
102
|
+
.addSchemaUpdate(addOpacity)
|
|
103
|
+
.build();
|
|
104
|
+
|
|
105
|
+
expect(schemaV2.models.ShapeBox.fields.fillColor).toEqual({
|
|
106
|
+
type: "optional",
|
|
107
|
+
item: { type: "string" },
|
|
108
|
+
});
|
|
109
|
+
expect(schemaV2.models.ShapeBox.fields.opacity).toEqual({
|
|
110
|
+
type: "optional",
|
|
111
|
+
item: { type: "double" },
|
|
112
|
+
});
|
|
113
|
+
expect(schemaV2.models.ShapeBox.fields.left).toEqual({ type: "double" });
|
|
114
|
+
expect(schemaV2.models.ShapeCircle.fields.fillColor).toEqual({
|
|
115
|
+
type: "optional",
|
|
116
|
+
item: { type: "string" },
|
|
117
|
+
});
|
|
118
|
+
expect(schemaV2.models.ShapeCircle.fields.opacity).toEqual({
|
|
119
|
+
type: "optional",
|
|
120
|
+
item: { type: "double" },
|
|
121
|
+
});
|
|
122
|
+
expect(schemaV2.version).toBe(2);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("should track version advancement across multiple nextSchema calls", () => {
|
|
126
|
+
const schemaV1 = defineSchema({
|
|
127
|
+
Item: defineRecord("Item", {
|
|
128
|
+
docs: "An item",
|
|
129
|
+
fields: {
|
|
130
|
+
name: P.String,
|
|
131
|
+
},
|
|
132
|
+
}),
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const addDescription = defineSchemaUpdate(
|
|
136
|
+
"addDescription",
|
|
137
|
+
(schema: SchemaBuilder<typeof schemaV1.models>) => ({
|
|
138
|
+
Item: schema.Item.addField("description", P.Optional(P.String)).build(),
|
|
139
|
+
}),
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
const schemaV2 = nextSchema(schemaV1).addSchemaUpdate(addDescription).build();
|
|
143
|
+
|
|
144
|
+
expect(schemaV2.version).toBe(2);
|
|
145
|
+
|
|
146
|
+
const addTags = defineSchemaUpdate(
|
|
147
|
+
"addTags",
|
|
148
|
+
(schema: SchemaBuilder<typeof schemaV2.models>) => ({
|
|
149
|
+
Item: schema.Item.addField("tags", P.Optional(P.String)).build(),
|
|
150
|
+
}),
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
const schemaV3 = nextSchema(schemaV2).addSchemaUpdate(addTags).build();
|
|
154
|
+
|
|
155
|
+
expect(schemaV3.version).toBe(3);
|
|
156
|
+
expect(schemaV3.models.Item.fields.name).toEqual({ type: "string" });
|
|
157
|
+
expect(schemaV3.models.Item.fields.description).toEqual({
|
|
158
|
+
type: "optional",
|
|
159
|
+
item: { type: "string" },
|
|
160
|
+
});
|
|
161
|
+
expect(schemaV3.models.Item.fields.tags).toEqual({
|
|
162
|
+
type: "optional",
|
|
163
|
+
item: { type: "string" },
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it("should build a walkable version chain via .previous", () => {
|
|
168
|
+
const schemaV1 = defineSchema({
|
|
169
|
+
Node: defineRecord("Node", {
|
|
170
|
+
docs: "A node",
|
|
171
|
+
fields: {
|
|
172
|
+
label: P.String,
|
|
173
|
+
},
|
|
174
|
+
}),
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const addWeight = defineSchemaUpdate(
|
|
178
|
+
"addWeight",
|
|
179
|
+
(schema: SchemaBuilder<typeof schemaV1.models>) => ({
|
|
180
|
+
Node: schema.Node.addField("weight", P.Double).build(),
|
|
181
|
+
}),
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
const schemaV2 = nextSchema(schemaV1).addSchemaUpdate(addWeight).build();
|
|
185
|
+
|
|
186
|
+
// v2 points back to the v1 InitialSchema
|
|
187
|
+
expect(schemaV2.previous).toBe(schemaV1);
|
|
188
|
+
expect(schemaV2.previous.type).toBe("initial");
|
|
189
|
+
expect(schemaV2.version).toBe(2);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("should build a multi-step version chain", () => {
|
|
193
|
+
const schemaV1 = defineSchema({
|
|
194
|
+
Item: defineRecord("Item", {
|
|
195
|
+
docs: "An item",
|
|
196
|
+
fields: { name: P.String },
|
|
197
|
+
}),
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
const schemaV2 = nextSchema(schemaV1)
|
|
201
|
+
.addSchemaUpdate(
|
|
202
|
+
defineSchemaUpdate(
|
|
203
|
+
"addPrice",
|
|
204
|
+
schema => ({
|
|
205
|
+
Item: schema.Item.addField("price", P.Double).build(),
|
|
206
|
+
}),
|
|
207
|
+
),
|
|
208
|
+
)
|
|
209
|
+
.build();
|
|
210
|
+
|
|
211
|
+
const schemaV3 = nextSchema(schemaV2)
|
|
212
|
+
.addSchemaUpdate(
|
|
213
|
+
defineSchemaUpdate(
|
|
214
|
+
"addTags",
|
|
215
|
+
schema => ({
|
|
216
|
+
Item: schema.Item.addField("tags", P.Optional(P.String)).build(),
|
|
217
|
+
}),
|
|
218
|
+
),
|
|
219
|
+
)
|
|
220
|
+
.build();
|
|
221
|
+
|
|
222
|
+
// Walk the chain: v3 (versioned) -> v2 (versioned) -> v1 (initial)
|
|
223
|
+
expect(schemaV3.version).toBe(3);
|
|
224
|
+
expect(schemaV3.previous).toBe(schemaV2);
|
|
225
|
+
expect(schemaV3.previous.type).toBe("versioned");
|
|
226
|
+
if (schemaV3.previous.type === "versioned") {
|
|
227
|
+
expect(schemaV3.previous.previous).toBe(schemaV1);
|
|
228
|
+
expect(schemaV3.previous.previous.type).toBe("initial");
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it("should discriminate via type field on built schemas", () => {
|
|
233
|
+
const schemaV1 = defineSchema({
|
|
234
|
+
Item: defineRecord("Item", {
|
|
235
|
+
docs: "An item",
|
|
236
|
+
fields: { name: P.String },
|
|
237
|
+
}),
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
const schemaV2 = nextSchema(schemaV1)
|
|
241
|
+
.addSchemaUpdate(
|
|
242
|
+
defineSchemaUpdate(
|
|
243
|
+
"addPrice",
|
|
244
|
+
schema => ({
|
|
245
|
+
Item: schema.Item.addField("price", P.Double).build(),
|
|
246
|
+
}),
|
|
247
|
+
),
|
|
248
|
+
)
|
|
249
|
+
.build();
|
|
250
|
+
|
|
251
|
+
expect(schemaV2.type).toBe("versioned");
|
|
252
|
+
expect(schemaV2.previous.type).toBe("initial");
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it("should work with union schema updates", () => {
|
|
256
|
+
const CircleRecord = defineRecord("Circle", {
|
|
257
|
+
docs: "A circle",
|
|
258
|
+
fields: { radius: P.Double },
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
const RectangleRecord = defineRecord("Rectangle", {
|
|
262
|
+
docs: "A rectangle",
|
|
263
|
+
fields: { width: P.Double, height: P.Double },
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
const TriangleRecord = defineRecord("Triangle", {
|
|
267
|
+
docs: "A triangle",
|
|
268
|
+
fields: { base: P.Double, height: P.Double },
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
const schemaV1 = defineSchema({
|
|
272
|
+
Shape: defineUnion("Shape", {
|
|
273
|
+
docs: "A shape",
|
|
274
|
+
variants: {
|
|
275
|
+
circle: CircleRecord,
|
|
276
|
+
rectangle: RectangleRecord,
|
|
277
|
+
},
|
|
278
|
+
}),
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
const addTriangle = defineSchemaUpdate(
|
|
282
|
+
"addTriangle",
|
|
283
|
+
(schema: SchemaBuilder<typeof schemaV1.models>) => ({
|
|
284
|
+
Shape: schema.Shape.addVariant("triangle", TriangleRecord).build(),
|
|
285
|
+
}),
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
const schemaV2 = nextSchema(schemaV1).addSchemaUpdate(addTriangle).build();
|
|
289
|
+
|
|
290
|
+
expect(schemaV2.models.Shape.variants.circle).toEqual({
|
|
291
|
+
type: "ref",
|
|
292
|
+
name: "Circle",
|
|
293
|
+
refType: "record",
|
|
294
|
+
});
|
|
295
|
+
expect(schemaV2.models.Shape.variants.triangle).toEqual({
|
|
296
|
+
type: "ref",
|
|
297
|
+
name: "Triangle",
|
|
298
|
+
refType: "record",
|
|
299
|
+
});
|
|
300
|
+
expect(schemaV2.version).toBe(2);
|
|
301
|
+
|
|
302
|
+
assertExactKeys<
|
|
303
|
+
typeof schemaV2.models.Shape.variants,
|
|
304
|
+
"circle" | "rectangle" | "triangle"
|
|
305
|
+
>();
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it("should handle mixed record and union updates in one version", () => {
|
|
309
|
+
const PersonRecord = defineRecord("Person", {
|
|
310
|
+
docs: "A person",
|
|
311
|
+
fields: { name: P.String },
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
const OrganizationRecord = defineRecord("Organization", {
|
|
315
|
+
docs: "An organization",
|
|
316
|
+
fields: { orgName: P.String },
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
const schemaV1 = defineSchema({
|
|
320
|
+
Person: PersonRecord,
|
|
321
|
+
Entity: defineUnion("Entity", {
|
|
322
|
+
docs: "An entity",
|
|
323
|
+
variants: {
|
|
324
|
+
person: PersonRecord,
|
|
325
|
+
},
|
|
326
|
+
}),
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
const addAge = defineSchemaUpdate(
|
|
330
|
+
"addAge",
|
|
331
|
+
(schema: SchemaBuilder<typeof schemaV1.models>) => ({
|
|
332
|
+
PersonV2: schema.Person.addField("age", P.Double).build(),
|
|
333
|
+
}),
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
const addOrgVariant = defineSchemaUpdate(
|
|
337
|
+
"addOrgVariant",
|
|
338
|
+
(schema: SchemaBuilder<typeof schemaV1.models>) => ({
|
|
339
|
+
Entity: schema.Entity.addVariant("organization", OrganizationRecord).build(),
|
|
340
|
+
}),
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
const schemaV2 = nextSchema(schemaV1)
|
|
344
|
+
.addSchemaUpdate(addAge)
|
|
345
|
+
.addSchemaUpdate(addOrgVariant)
|
|
346
|
+
.build();
|
|
347
|
+
|
|
348
|
+
expect(schemaV2.models.PersonV2.fields.name).toEqual({ type: "string" });
|
|
349
|
+
expect(schemaV2.models.PersonV2.fields.age).toEqual({ type: "double" });
|
|
350
|
+
expect(schemaV2.models.Entity.variants.person).toEqual({
|
|
351
|
+
type: "ref",
|
|
352
|
+
name: "Person",
|
|
353
|
+
refType: "record",
|
|
354
|
+
});
|
|
355
|
+
expect(schemaV2.models.Entity.variants.organization).toEqual({
|
|
356
|
+
type: "ref",
|
|
357
|
+
name: "Organization",
|
|
358
|
+
refType: "record",
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
assertHasKeys<typeof schemaV2.models, "Person" | "PersonV2" | "Entity">();
|
|
362
|
+
assertExactKeys<typeof schemaV2.models.PersonV2.fields, "name" | "age">();
|
|
363
|
+
assertExactKeys<typeof schemaV2.models.Entity.variants, "person" | "organization">();
|
|
364
|
+
});
|
|
365
|
+
});
|
package/src/defineMigration.ts
CHANGED
|
@@ -16,16 +16,18 @@
|
|
|
16
16
|
|
|
17
17
|
import type { UnionVariantArg } from "./defineUnion.js";
|
|
18
18
|
import { resolveUnionVariantArg } from "./defineUnion.js";
|
|
19
|
-
import type { RecordDef, RecordFields, UnionDef, UnionVariants } from "./defs.js";
|
|
19
|
+
import type { ModelDefs, RecordDef, RecordFields, UnionDef, UnionVariants } from "./defs.js";
|
|
20
20
|
import { ModelDefType } from "./defs.js";
|
|
21
21
|
import type { Ref, Type } from "./primitives.js";
|
|
22
22
|
import { isRecordDef, isUnionDef } from "./utils.js";
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
/** Soon to be deprecated - Use `ModelDefs` instead. */
|
|
25
|
+
export type ReturnedSchema = ModelDefs;
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
/** Soon to be deprecated - use `ModelDefs` instead. */
|
|
28
|
+
export type Schema<T extends ModelDefs> = T;
|
|
27
29
|
|
|
28
|
-
export type SchemaBuilder<T extends
|
|
30
|
+
export type SchemaBuilder<T extends ModelDefs> = {
|
|
29
31
|
[k in keyof T]: T[k] extends UnionDef<infer R> ? UnionBuilder<R>
|
|
30
32
|
: T[k] extends RecordDef<infer R> ? RecordBuilder<R>
|
|
31
33
|
: never;
|
|
@@ -114,46 +116,28 @@ class RecordBuilderImpl<T extends RecordFields> implements RecordBuilder<T> {
|
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
export function defineMigration<
|
|
117
|
-
const T extends
|
|
118
|
-
const S extends
|
|
119
|
+
const T extends ModelDefs,
|
|
120
|
+
const S extends ModelDefs,
|
|
119
121
|
>(
|
|
120
|
-
|
|
122
|
+
models: T,
|
|
121
123
|
migration: (schema: SchemaBuilder<T>) => S,
|
|
122
|
-
):
|
|
123
|
-
/**
|
|
124
|
-
* Create a map of builders for the schema.
|
|
125
|
-
*
|
|
126
|
-
* Note about type assertions:
|
|
127
|
-
* We use a type assertion here (SchemaBuilder<T>) because TypeScript cannot
|
|
128
|
-
* track the relationship between the keys in the original schema and the
|
|
129
|
-
* corresponding builder types. This is a fundamental limitation of TypeScript's
|
|
130
|
-
* type system when dealing with dynamically constructed objects.
|
|
131
|
-
*
|
|
132
|
-
* The assertion is safe because:
|
|
133
|
-
* 1. We're only adding keys that exist in the original schema
|
|
134
|
-
* 2. For each key, we're creating a builder of the correct type
|
|
135
|
-
* 3. The resulting object exactly matches the SchemaBuilder<T> type
|
|
136
|
-
*/
|
|
124
|
+
): T & S {
|
|
137
125
|
const builders = {} as SchemaBuilder<T>;
|
|
138
126
|
|
|
139
|
-
for (const key in
|
|
140
|
-
const v =
|
|
127
|
+
for (const key in models) {
|
|
128
|
+
const v = models[key];
|
|
141
129
|
|
|
142
|
-
// Use our type guards for safer type narrowing
|
|
143
130
|
if (isRecordDef(v)) {
|
|
144
|
-
// This assertion is necessary because TypeScript can't track the field types
|
|
145
|
-
// through the dynamic property access and object construction
|
|
146
131
|
const recordBuilder = new RecordBuilderImpl(v);
|
|
147
132
|
builders[key] = recordBuilder as unknown as SchemaBuilder<T>[typeof key];
|
|
148
133
|
} else if (isUnionDef(v)) {
|
|
149
|
-
// Similar assertion needed for union builders
|
|
150
134
|
const unionBuilder = new UnionBuilderImpl(v);
|
|
151
135
|
builders[key] = unionBuilder as unknown as SchemaBuilder<T>[typeof key];
|
|
152
136
|
}
|
|
153
137
|
}
|
|
154
138
|
|
|
155
139
|
return {
|
|
156
|
-
...
|
|
140
|
+
...models,
|
|
157
141
|
...migration(builders),
|
|
158
142
|
};
|
|
159
143
|
}
|