@osdk/seed-helpers 0.2.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/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # @osdk/seed-helpers
2
+
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - d6f67f6: add seed data compiler. New `@osdk/seed-helpers` package exports `createSeed` and `SeedBuilder` for declaring typed seed objects and links. New `@osdk/seed-compiler` package compiles all top-level `.mts` files in a directory into a merged seed JSON (sorted by filename for deterministic output) for foundry-cli's local ontology server to load into SQLite on startup. Schema-aware validation (primary-key uniqueness, string format checks for `timestamp`/`date`/`datetime`/`long`/`decimal`) reads from `ontology-metadata.json` produced by the SDK generator, so the same compiler works against both ontology-as-code projects and imported ontologies.
8
+
9
+ ### Patch Changes
10
+
11
+ - @osdk/api@2.18.0
@@ -0,0 +1,196 @@
1
+ /*
2
+ * Copyright 2025 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
+ /** Internal representation of a resolved link before validation. */
18
+
19
+ /** Checks whether a value is a {@link SeedRef} returned by `SeedBuilder.add()`. */
20
+ function isSeedRef(value) {
21
+ return typeof value === "object" && value != null && "__objectTypeApiName" in value && "__primaryKey" in value;
22
+ }
23
+
24
+ /**
25
+ * Resolves a link from two {@link SeedRef} instances.
26
+ * Extracts the object type and primary key from each ref.
27
+ */
28
+ function resolveFromRefs(src, srcLinkName, dst) {
29
+ return {
30
+ sourceObjectType: src.__objectTypeApiName,
31
+ sourceKey: String(src.__primaryKey),
32
+ linkType: srcLinkName,
33
+ targetObjectType: dst.__objectTypeApiName,
34
+ targetKey: String(dst.__primaryKey)
35
+ };
36
+ }
37
+
38
+ /**
39
+ * Resolves a link from two {@link ObjectTypeDefinition} instances and explicit primary keys.
40
+ * Reads the `apiName` from each type definition.
41
+ */
42
+ function resolveFromTypes(srcType, srcPk, srcLinkName, dstType, dstPk) {
43
+ return {
44
+ sourceObjectType: srcType.apiName,
45
+ sourceKey: String(srcPk),
46
+ linkType: srcLinkName,
47
+ targetObjectType: dstType.apiName,
48
+ targetKey: String(dstPk)
49
+ };
50
+ }
51
+
52
+ /**
53
+ * A lightweight, type-safe builder for constructing seed data.
54
+ *
55
+ * TypeScript catches everything expressible at the call site: property
56
+ * names and value types, required primary keys, link names valid on the
57
+ * source type, and link target types matching what the link points to.
58
+ */
59
+ export class SeedBuilder {
60
+ #objects = new Map();
61
+ #refs = new Set();
62
+ #links = [];
63
+
64
+ /**
65
+ * Register a seed object and return a typed reference for use in {@link link}.
66
+ *
67
+ * Property names and value types are validated at compile time against the
68
+ * generated SDK type. Non-nullable properties (including the primary key)
69
+ * are required.
70
+ *
71
+ * @param type - The generated SDK object type definition (e.g., `Product`).
72
+ * @param props - Property values for the object. Must match the SDK type's property schema.
73
+ * @returns A frozen {@link SeedRef} carrying the object type and primary key.
74
+ * @throws if the primary key is null, undefined, or already registered for this type.
75
+ * @throws if the object type definition is missing `apiName` or `primaryKeyApiName`.
76
+ */
77
+ add(type, props) {
78
+ // Runtime guards for callers who bypass the type system with `as any`.
79
+ // Properly-typed ObjectTypeDefinition values can't reach these.
80
+ const apiName = type.apiName;
81
+ const pkApiName = type.primaryKeyApiName;
82
+ if (!apiName) {
83
+ throw new Error("Object type is missing apiName");
84
+ }
85
+ if (!pkApiName) {
86
+ throw new Error(`[${apiName}] Object type is missing primaryKeyApiName`);
87
+ }
88
+ const record = props;
89
+ const pkValue = record[pkApiName];
90
+ if (pkValue == null) {
91
+ throw new Error(`[${apiName}] Primary key '${pkApiName}' is null or undefined`);
92
+ }
93
+ const pk = String(pkValue);
94
+ let typeMap = this.#objects.get(apiName);
95
+ if (!typeMap) {
96
+ typeMap = new Map();
97
+ this.#objects.set(apiName, typeMap);
98
+ }
99
+ if (typeMap.has(pk)) {
100
+ throw new Error(`[${apiName}] Duplicate primary key '${pk}'`);
101
+ }
102
+ typeMap.set(pk, {
103
+ ...record
104
+ });
105
+ this.#refs.add(`${apiName}:${pk}`);
106
+ return Object.freeze({
107
+ __objectTypeApiName: apiName,
108
+ __primaryKey: pkValue
109
+ });
110
+ }
111
+
112
+ /**
113
+ * Register a link between two seed objects.
114
+ *
115
+ * Supports two calling conventions that produce identical output:
116
+ * by-reference (passing `SeedRef`s returned from {@link add}) or by-type
117
+ * and primary-key. See the `@osdk/seed-compiler` README for usage examples.
118
+ *
119
+ * @param name - A descriptive label for this link (included in seed output and error messages).
120
+ * @throws if either source or target object was not registered via {@link add}.
121
+ */
122
+
123
+ link(name, srcOrType, linkNameOrPk, dstOrLinkName, typeOrLinkName, dstPk) {
124
+ const resolved = isSeedRef(srcOrType) ? resolveFromRefs(srcOrType, linkNameOrPk, dstOrLinkName) : resolveFromTypes(srcOrType, linkNameOrPk, dstOrLinkName, typeOrLinkName, dstPk);
125
+ this.#assertRegistered(resolved.sourceObjectType, resolved.sourceKey, "Source", name);
126
+ this.#assertRegistered(resolved.targetObjectType, resolved.targetKey, "Target", name);
127
+ this.#links.push({
128
+ name,
129
+ ...resolved
130
+ });
131
+ }
132
+
133
+ /**
134
+ * Asserts that an object with the given type and key was registered via {@link add}.
135
+ * @throws with a descriptive message including the link name for context.
136
+ */
137
+ #assertRegistered(objectType, key, role, linkName) {
138
+ const ref = `${objectType}:${key}`;
139
+ if (!this.#refs.has(ref)) {
140
+ throw new Error(`${role} '${ref}' not registered (link '${linkName}')`);
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Build the final {@link SeedOutput} from all registered objects and links.
146
+ *
147
+ * The returned arrays are fresh copies, so a subsequent `add()` or `link()`
148
+ * call does not retroactively grow or shrink an array that was already
149
+ * returned. The property records inside the arrays, however, are shared
150
+ * references with the builder's internal storage — mutating
151
+ * `output.objects.Employee[0].name = "x"` *will* propagate into the
152
+ * builder and into anything else holding a previous output. Treat the
153
+ * output as read-only, or deep-clone it before mutating.
154
+ *
155
+ * Inputs to {@link add} are still safe to mutate after calling: `add` stores
156
+ * a shallow copy of the props record on registration.
157
+ */
158
+ build() {
159
+ const objects = {};
160
+ for (const [apiName, typeMap] of this.#objects) {
161
+ objects[apiName] = [...typeMap.values()];
162
+ }
163
+ return {
164
+ objects,
165
+ links: [...this.#links]
166
+ };
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Create seed data using a builder function.
172
+ *
173
+ * The builder is created, passed to `fn`, and the resulting {@link SeedOutput}
174
+ * is returned as the module's default export for consumption by the seed compiler.
175
+ *
176
+ * @param fn - A function that registers objects and links on the provided {@link SeedBuilder}.
177
+ * @returns The built {@link SeedOutput} containing all registered objects and links.
178
+ *
179
+ * @example
180
+ * ```ts
181
+ * import { Product, Seller } from "@ontology/sdk";
182
+ * import { createSeed } from "@osdk/seed-helpers";
183
+ *
184
+ * export default createSeed((seed) => {
185
+ * const prod = seed.add(Product, { pk: "prod-001", title: "Widget", price: 100 });
186
+ * const alice = seed.add(Seller, { pk: "seller-001", name: "Alice" });
187
+ * seed.link("widget-seller", prod, "sellers", alice, "products");
188
+ * });
189
+ * ```
190
+ */
191
+ export function createSeed(fn) {
192
+ const builder = new SeedBuilder();
193
+ fn(builder);
194
+ return builder.build();
195
+ }
196
+ //# sourceMappingURL=SeedBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SeedBuilder.js","names":["isSeedRef","value","resolveFromRefs","src","srcLinkName","dst","sourceObjectType","__objectTypeApiName","sourceKey","String","__primaryKey","linkType","targetObjectType","targetKey","resolveFromTypes","srcType","srcPk","dstType","dstPk","apiName","SeedBuilder","objects","Map","refs","Set","links","add","type","props","pkApiName","primaryKeyApiName","Error","record","pkValue","pk","typeMap","get","set","has","Object","freeze","link","name","srcOrType","linkNameOrPk","dstOrLinkName","typeOrLinkName","resolved","assertRegistered","push","#assertRegistered","objectType","key","role","linkName","ref","build","values","createSeed","fn","builder"],"sources":["SeedBuilder.ts"],"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\nimport type { LinkedType, LinkNames, ObjectTypeDefinition } from \"@osdk/api\";\nimport type { SeedLinkEntry, SeedOutput, SeedProps, SeedRef } from \"./types.js\";\n\n/** Internal representation of a resolved link before validation. */\ninterface ResolvedLink {\n sourceObjectType: string;\n sourceKey: string;\n linkType: string;\n targetObjectType: string;\n targetKey: string;\n}\n\n/** Checks whether a value is a {@link SeedRef} returned by `SeedBuilder.add()`. */\nfunction isSeedRef(value: unknown): value is SeedRef {\n return typeof value === \"object\"\n && value != null\n && \"__objectTypeApiName\" in value\n && \"__primaryKey\" in value;\n}\n\n/**\n * Resolves a link from two {@link SeedRef} instances.\n * Extracts the object type and primary key from each ref.\n */\nfunction resolveFromRefs(\n src: SeedRef,\n srcLinkName: string,\n dst: SeedRef,\n): ResolvedLink {\n return {\n sourceObjectType: src.__objectTypeApiName,\n sourceKey: String(src.__primaryKey),\n linkType: srcLinkName,\n targetObjectType: dst.__objectTypeApiName,\n targetKey: String(dst.__primaryKey),\n };\n}\n\n/**\n * Resolves a link from two {@link ObjectTypeDefinition} instances and explicit primary keys.\n * Reads the `apiName` from each type definition.\n */\nfunction resolveFromTypes(\n srcType: ObjectTypeDefinition,\n srcPk: string | number,\n srcLinkName: string,\n dstType: ObjectTypeDefinition,\n dstPk: string | number,\n): ResolvedLink {\n return {\n sourceObjectType: srcType.apiName,\n sourceKey: String(srcPk),\n linkType: srcLinkName,\n targetObjectType: dstType.apiName,\n targetKey: String(dstPk),\n };\n}\n\n/**\n * A lightweight, type-safe builder for constructing seed data.\n *\n * TypeScript catches everything expressible at the call site: property\n * names and value types, required primary keys, link names valid on the\n * source type, and link target types matching what the link points to.\n */\nexport class SeedBuilder {\n readonly #objects = new Map<string, Map<string, Record<string, unknown>>>();\n readonly #refs = new Set<string>();\n readonly #links: SeedLinkEntry[] = [];\n\n /**\n * Register a seed object and return a typed reference for use in {@link link}.\n *\n * Property names and value types are validated at compile time against the\n * generated SDK type. Non-nullable properties (including the primary key)\n * are required.\n *\n * @param type - The generated SDK object type definition (e.g., `Product`).\n * @param props - Property values for the object. Must match the SDK type's property schema.\n * @returns A frozen {@link SeedRef} carrying the object type and primary key.\n * @throws if the primary key is null, undefined, or already registered for this type.\n * @throws if the object type definition is missing `apiName` or `primaryKeyApiName`.\n */\n add<Q extends ObjectTypeDefinition>(\n type: Q,\n props: SeedProps<Q>,\n ): SeedRef<Q> {\n // Runtime guards for callers who bypass the type system with `as any`.\n // Properly-typed ObjectTypeDefinition values can't reach these.\n const apiName = type.apiName;\n const pkApiName = type.primaryKeyApiName;\n\n if (!apiName) {\n throw new Error(\"Object type is missing apiName\");\n }\n if (!pkApiName) {\n throw new Error(`[${apiName}] Object type is missing primaryKeyApiName`);\n }\n\n const record = props as Record<string, unknown>;\n const pkValue = record[pkApiName];\n\n if (pkValue == null) {\n throw new Error(\n `[${apiName}] Primary key '${pkApiName}' is null or undefined`,\n );\n }\n\n const pk = String(pkValue);\n\n let typeMap = this.#objects.get(apiName);\n if (!typeMap) {\n typeMap = new Map();\n this.#objects.set(apiName, typeMap);\n }\n\n if (typeMap.has(pk)) {\n throw new Error(`[${apiName}] Duplicate primary key '${pk}'`);\n }\n\n typeMap.set(pk, { ...record });\n this.#refs.add(`${apiName}:${pk}`);\n\n return Object.freeze({\n __objectTypeApiName: apiName,\n __primaryKey: pkValue as string | number,\n }) as SeedRef<Q>;\n }\n\n /**\n * Register a link between two seed objects.\n *\n * Supports two calling conventions that produce identical output:\n * by-reference (passing `SeedRef`s returned from {@link add}) or by-type\n * and primary-key. See the `@osdk/seed-compiler` README for usage examples.\n *\n * @param name - A descriptive label for this link (included in seed output and error messages).\n * @throws if either source or target object was not registered via {@link add}.\n */\n link<\n S extends ObjectTypeDefinition,\n SL extends LinkNames<S>,\n D extends LinkedType<S, SL>,\n DL extends LinkNames<D>,\n >(\n name: string,\n src: SeedRef<S>,\n srcLinkName: SL,\n dst: SeedRef<D>,\n dstLinkName: DL,\n ): void;\n link<\n S extends ObjectTypeDefinition,\n SL extends LinkNames<S>,\n D extends LinkedType<S, SL>,\n DL extends LinkNames<D>,\n >(\n name: string,\n srcType: S,\n srcPk: string | number,\n srcLinkName: SL,\n dstType: D,\n dstPk: string | number,\n dstLinkName: DL,\n ): void;\n link(\n name: string,\n srcOrType: SeedRef | ObjectTypeDefinition,\n linkNameOrPk: string | number,\n dstOrLinkName: SeedRef | ObjectTypeDefinition | string,\n typeOrLinkName?: ObjectTypeDefinition | string,\n dstPk?: string | number,\n _dstLinkName?: string,\n ): void {\n const resolved = isSeedRef(srcOrType)\n ? resolveFromRefs(\n srcOrType,\n linkNameOrPk as string,\n dstOrLinkName as SeedRef,\n )\n : resolveFromTypes(\n srcOrType,\n linkNameOrPk,\n dstOrLinkName as string,\n typeOrLinkName as ObjectTypeDefinition,\n dstPk!,\n );\n\n this.#assertRegistered(\n resolved.sourceObjectType,\n resolved.sourceKey,\n \"Source\",\n name,\n );\n this.#assertRegistered(\n resolved.targetObjectType,\n resolved.targetKey,\n \"Target\",\n name,\n );\n\n this.#links.push({ name, ...resolved });\n }\n\n /**\n * Asserts that an object with the given type and key was registered via {@link add}.\n * @throws with a descriptive message including the link name for context.\n */\n #assertRegistered(\n objectType: string,\n key: string,\n role: \"Source\" | \"Target\",\n linkName: string,\n ): void {\n const ref = `${objectType}:${key}`;\n if (!this.#refs.has(ref)) {\n throw new Error(\n `${role} '${ref}' not registered (link '${linkName}')`,\n );\n }\n }\n\n /**\n * Build the final {@link SeedOutput} from all registered objects and links.\n *\n * The returned arrays are fresh copies, so a subsequent `add()` or `link()`\n * call does not retroactively grow or shrink an array that was already\n * returned. The property records inside the arrays, however, are shared\n * references with the builder's internal storage — mutating\n * `output.objects.Employee[0].name = \"x\"` *will* propagate into the\n * builder and into anything else holding a previous output. Treat the\n * output as read-only, or deep-clone it before mutating.\n *\n * Inputs to {@link add} are still safe to mutate after calling: `add` stores\n * a shallow copy of the props record on registration.\n */\n build(): SeedOutput {\n const objects: Record<string, Array<Record<string, unknown>>> = {};\n for (const [apiName, typeMap] of this.#objects) {\n objects[apiName] = [...typeMap.values()];\n }\n return { objects, links: [...this.#links] };\n }\n}\n\n/**\n * Create seed data using a builder function.\n *\n * The builder is created, passed to `fn`, and the resulting {@link SeedOutput}\n * is returned as the module's default export for consumption by the seed compiler.\n *\n * @param fn - A function that registers objects and links on the provided {@link SeedBuilder}.\n * @returns The built {@link SeedOutput} containing all registered objects and links.\n *\n * @example\n * ```ts\n * import { Product, Seller } from \"@ontology/sdk\";\n * import { createSeed } from \"@osdk/seed-helpers\";\n *\n * export default createSeed((seed) => {\n * const prod = seed.add(Product, { pk: \"prod-001\", title: \"Widget\", price: 100 });\n * const alice = seed.add(Seller, { pk: \"seller-001\", name: \"Alice\" });\n * seed.link(\"widget-seller\", prod, \"sellers\", alice, \"products\");\n * });\n * ```\n */\nexport function createSeed(fn: (seed: SeedBuilder) => void): SeedOutput {\n const builder = new SeedBuilder();\n fn(builder);\n return builder.build();\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,18 @@
1
+ /*
2
+ * Copyright 2025 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
+ export { createSeed, SeedBuilder } from "./SeedBuilder.js";
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["createSeed","SeedBuilder"],"sources":["index.ts"],"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 { createSeed, SeedBuilder } from \"./SeedBuilder.js\";\nexport type { SeedLinkEntry, SeedOutput, SeedProps, SeedRef } from \"./types.js\";\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,UAAU,EAAEC,WAAW,QAAQ,kBAAkB","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","names":[],"sources":["types.ts"],"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\nimport type { CompileTimeMetadata, ObjectTypeDefinition } from \"@osdk/api\";\n\n/**\n * Makes nullable properties optional while keeping non-nullable ones required.\n * `{ id: string; title: string | undefined }` becomes `{ id: string; title?: string }`.\n * This ensures required fields like primary keys must always be provided.\n */\ntype PartialForOptionalProperties<T> =\n & {\n [K in keyof T as undefined extends T[K] ? K : never]?: NonNullable<T[K]>;\n }\n & {\n [K in keyof T as undefined extends T[K] ? never : K]-?: T[K];\n };\n\n/**\n * Derives the property types for seed data from the generated SDK type.\n * Uses CompileTimeMetadata<T>[\"props\"] which resolves to the Props interface\n * on generated types (e.g., Employee.Props). Non-nullable properties like the\n * primary key are required; nullable properties are optional.\n */\nexport type SeedProps<T extends ObjectTypeDefinition> =\n PartialForOptionalProperties<\n CompileTimeMetadata<T>[\"props\"]\n >;\n\n/**\n * Unique symbol used to brand {@link SeedRef} instances. A branded type prevents\n * manually constructed objects from satisfying the interface — only `SeedBuilder.add()`\n * can produce a valid `SeedRef`. This ensures `link()` generics always have the\n * correct object type for compile-time link name and target type validation.\n */\ndeclare const SEED_REF_BRAND: unique symbol;\n\n/**\n * A typed reference returned by SeedBuilder.add(). The branded symbol field\n * carries the object type as a generic, enabling compile-time link validation.\n *\n * Cannot be constructed manually — the unique symbol key is not exported and\n * only `SeedBuilder.add()` can produce a valid `SeedRef` via an `as` cast.\n */\nexport interface SeedRef<\n Q extends ObjectTypeDefinition = ObjectTypeDefinition,\n> {\n readonly __objectTypeApiName: string;\n readonly __primaryKey: string | number;\n /** @internal Brand field — never set at runtime. Enforces nominal typing. */\n readonly [SEED_REF_BRAND]: Q;\n}\n\n/** A link entry in the seed output. */\nexport interface SeedLinkEntry {\n name: string;\n linkType: string;\n sourceObjectType: string;\n sourceKey: string;\n targetObjectType: string;\n targetKey: string;\n}\n\n/** The final serializable seed data output. */\nexport interface SeedOutput {\n objects: Record<string, Array<Record<string, unknown>>>;\n links: SeedLinkEntry[];\n}\n"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,137 @@
1
+ 'use strict';
2
+
3
+ // src/SeedBuilder.ts
4
+ function isSeedRef(value) {
5
+ return typeof value === "object" && value != null && "__objectTypeApiName" in value && "__primaryKey" in value;
6
+ }
7
+ function resolveFromRefs(src, srcLinkName, dst) {
8
+ return {
9
+ sourceObjectType: src.__objectTypeApiName,
10
+ sourceKey: String(src.__primaryKey),
11
+ linkType: srcLinkName,
12
+ targetObjectType: dst.__objectTypeApiName,
13
+ targetKey: String(dst.__primaryKey)
14
+ };
15
+ }
16
+ function resolveFromTypes(srcType, srcPk, srcLinkName, dstType, dstPk) {
17
+ return {
18
+ sourceObjectType: srcType.apiName,
19
+ sourceKey: String(srcPk),
20
+ linkType: srcLinkName,
21
+ targetObjectType: dstType.apiName,
22
+ targetKey: String(dstPk)
23
+ };
24
+ }
25
+ var SeedBuilder = class {
26
+ #objects = /* @__PURE__ */ new Map();
27
+ #refs = /* @__PURE__ */ new Set();
28
+ #links = [];
29
+ /**
30
+ * Register a seed object and return a typed reference for use in {@link link}.
31
+ *
32
+ * Property names and value types are validated at compile time against the
33
+ * generated SDK type. Non-nullable properties (including the primary key)
34
+ * are required.
35
+ *
36
+ * @param type - The generated SDK object type definition (e.g., `Product`).
37
+ * @param props - Property values for the object. Must match the SDK type's property schema.
38
+ * @returns A frozen {@link SeedRef} carrying the object type and primary key.
39
+ * @throws if the primary key is null, undefined, or already registered for this type.
40
+ * @throws if the object type definition is missing `apiName` or `primaryKeyApiName`.
41
+ */
42
+ add(type, props) {
43
+ const apiName = type.apiName;
44
+ const pkApiName = type.primaryKeyApiName;
45
+ if (!apiName) {
46
+ throw new Error("Object type is missing apiName");
47
+ }
48
+ if (!pkApiName) {
49
+ throw new Error(`[${apiName}] Object type is missing primaryKeyApiName`);
50
+ }
51
+ const record = props;
52
+ const pkValue = record[pkApiName];
53
+ if (pkValue == null) {
54
+ throw new Error(`[${apiName}] Primary key '${pkApiName}' is null or undefined`);
55
+ }
56
+ const pk = String(pkValue);
57
+ let typeMap = this.#objects.get(apiName);
58
+ if (!typeMap) {
59
+ typeMap = /* @__PURE__ */ new Map();
60
+ this.#objects.set(apiName, typeMap);
61
+ }
62
+ if (typeMap.has(pk)) {
63
+ throw new Error(`[${apiName}] Duplicate primary key '${pk}'`);
64
+ }
65
+ typeMap.set(pk, {
66
+ ...record
67
+ });
68
+ this.#refs.add(`${apiName}:${pk}`);
69
+ return Object.freeze({
70
+ __objectTypeApiName: apiName,
71
+ __primaryKey: pkValue
72
+ });
73
+ }
74
+ /**
75
+ * Register a link between two seed objects.
76
+ *
77
+ * Supports two calling conventions that produce identical output:
78
+ * by-reference (passing `SeedRef`s returned from {@link add}) or by-type
79
+ * and primary-key. See the `@osdk/seed-compiler` README for usage examples.
80
+ *
81
+ * @param name - A descriptive label for this link (included in seed output and error messages).
82
+ * @throws if either source or target object was not registered via {@link add}.
83
+ */
84
+ link(name, srcOrType, linkNameOrPk, dstOrLinkName, typeOrLinkName, dstPk, _dstLinkName) {
85
+ const resolved = isSeedRef(srcOrType) ? resolveFromRefs(srcOrType, linkNameOrPk, dstOrLinkName) : resolveFromTypes(srcOrType, linkNameOrPk, dstOrLinkName, typeOrLinkName, dstPk);
86
+ this.#assertRegistered(resolved.sourceObjectType, resolved.sourceKey, "Source", name);
87
+ this.#assertRegistered(resolved.targetObjectType, resolved.targetKey, "Target", name);
88
+ this.#links.push({
89
+ name,
90
+ ...resolved
91
+ });
92
+ }
93
+ /**
94
+ * Asserts that an object with the given type and key was registered via {@link add}.
95
+ * @throws with a descriptive message including the link name for context.
96
+ */
97
+ #assertRegistered(objectType, key, role, linkName) {
98
+ const ref = `${objectType}:${key}`;
99
+ if (!this.#refs.has(ref)) {
100
+ throw new Error(`${role} '${ref}' not registered (link '${linkName}')`);
101
+ }
102
+ }
103
+ /**
104
+ * Build the final {@link SeedOutput} from all registered objects and links.
105
+ *
106
+ * The returned arrays are fresh copies, so a subsequent `add()` or `link()`
107
+ * call does not retroactively grow or shrink an array that was already
108
+ * returned. The property records inside the arrays, however, are shared
109
+ * references with the builder's internal storage — mutating
110
+ * `output.objects.Employee[0].name = "x"` *will* propagate into the
111
+ * builder and into anything else holding a previous output. Treat the
112
+ * output as read-only, or deep-clone it before mutating.
113
+ *
114
+ * Inputs to {@link add} are still safe to mutate after calling: `add` stores
115
+ * a shallow copy of the props record on registration.
116
+ */
117
+ build() {
118
+ const objects = {};
119
+ for (const [apiName, typeMap] of this.#objects) {
120
+ objects[apiName] = [...typeMap.values()];
121
+ }
122
+ return {
123
+ objects,
124
+ links: [...this.#links]
125
+ };
126
+ }
127
+ };
128
+ function createSeed(fn) {
129
+ const builder = new SeedBuilder();
130
+ fn(builder);
131
+ return builder.build();
132
+ }
133
+
134
+ exports.SeedBuilder = SeedBuilder;
135
+ exports.createSeed = createSeed;
136
+ //# sourceMappingURL=index.cjs.map
137
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/SeedBuilder.ts"],"names":[],"mappings":"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","file":"index.cjs","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\n/** Internal representation of a resolved link before validation. */\n\n/** Checks whether a value is a {@link SeedRef} returned by `SeedBuilder.add()`. */\nfunction isSeedRef(value) {\n return typeof value === \"object\" && value != null && \"__objectTypeApiName\" in value && \"__primaryKey\" in value;\n}\n\n/**\n * Resolves a link from two {@link SeedRef} instances.\n * Extracts the object type and primary key from each ref.\n */\nfunction resolveFromRefs(src, srcLinkName, dst) {\n return {\n sourceObjectType: src.__objectTypeApiName,\n sourceKey: String(src.__primaryKey),\n linkType: srcLinkName,\n targetObjectType: dst.__objectTypeApiName,\n targetKey: String(dst.__primaryKey)\n };\n}\n\n/**\n * Resolves a link from two {@link ObjectTypeDefinition} instances and explicit primary keys.\n * Reads the `apiName` from each type definition.\n */\nfunction resolveFromTypes(srcType, srcPk, srcLinkName, dstType, dstPk) {\n return {\n sourceObjectType: srcType.apiName,\n sourceKey: String(srcPk),\n linkType: srcLinkName,\n targetObjectType: dstType.apiName,\n targetKey: String(dstPk)\n };\n}\n\n/**\n * A lightweight, type-safe builder for constructing seed data.\n *\n * TypeScript catches everything expressible at the call site: property\n * names and value types, required primary keys, link names valid on the\n * source type, and link target types matching what the link points to.\n */\nexport class SeedBuilder {\n #objects = new Map();\n #refs = new Set();\n #links = [];\n\n /**\n * Register a seed object and return a typed reference for use in {@link link}.\n *\n * Property names and value types are validated at compile time against the\n * generated SDK type. Non-nullable properties (including the primary key)\n * are required.\n *\n * @param type - The generated SDK object type definition (e.g., `Product`).\n * @param props - Property values for the object. Must match the SDK type's property schema.\n * @returns A frozen {@link SeedRef} carrying the object type and primary key.\n * @throws if the primary key is null, undefined, or already registered for this type.\n * @throws if the object type definition is missing `apiName` or `primaryKeyApiName`.\n */\n add(type, props) {\n // Runtime guards for callers who bypass the type system with `as any`.\n // Properly-typed ObjectTypeDefinition values can't reach these.\n const apiName = type.apiName;\n const pkApiName = type.primaryKeyApiName;\n if (!apiName) {\n throw new Error(\"Object type is missing apiName\");\n }\n if (!pkApiName) {\n throw new Error(`[${apiName}] Object type is missing primaryKeyApiName`);\n }\n const record = props;\n const pkValue = record[pkApiName];\n if (pkValue == null) {\n throw new Error(`[${apiName}] Primary key '${pkApiName}' is null or undefined`);\n }\n const pk = String(pkValue);\n let typeMap = this.#objects.get(apiName);\n if (!typeMap) {\n typeMap = new Map();\n this.#objects.set(apiName, typeMap);\n }\n if (typeMap.has(pk)) {\n throw new Error(`[${apiName}] Duplicate primary key '${pk}'`);\n }\n typeMap.set(pk, {\n ...record\n });\n this.#refs.add(`${apiName}:${pk}`);\n return Object.freeze({\n __objectTypeApiName: apiName,\n __primaryKey: pkValue\n });\n }\n\n /**\n * Register a link between two seed objects.\n *\n * Supports two calling conventions that produce identical output:\n * by-reference (passing `SeedRef`s returned from {@link add}) or by-type\n * and primary-key. See the `@osdk/seed-compiler` README for usage examples.\n *\n * @param name - A descriptive label for this link (included in seed output and error messages).\n * @throws if either source or target object was not registered via {@link add}.\n */\n\n link(name, srcOrType, linkNameOrPk, dstOrLinkName, typeOrLinkName, dstPk, _dstLinkName) {\n const resolved = isSeedRef(srcOrType) ? resolveFromRefs(srcOrType, linkNameOrPk, dstOrLinkName) : resolveFromTypes(srcOrType, linkNameOrPk, dstOrLinkName, typeOrLinkName, dstPk);\n this.#assertRegistered(resolved.sourceObjectType, resolved.sourceKey, \"Source\", name);\n this.#assertRegistered(resolved.targetObjectType, resolved.targetKey, \"Target\", name);\n this.#links.push({\n name,\n ...resolved\n });\n }\n\n /**\n * Asserts that an object with the given type and key was registered via {@link add}.\n * @throws with a descriptive message including the link name for context.\n */\n #assertRegistered(objectType, key, role, linkName) {\n const ref = `${objectType}:${key}`;\n if (!this.#refs.has(ref)) {\n throw new Error(`${role} '${ref}' not registered (link '${linkName}')`);\n }\n }\n\n /**\n * Build the final {@link SeedOutput} from all registered objects and links.\n *\n * The returned arrays are fresh copies, so a subsequent `add()` or `link()`\n * call does not retroactively grow or shrink an array that was already\n * returned. The property records inside the arrays, however, are shared\n * references with the builder's internal storage — mutating\n * `output.objects.Employee[0].name = \"x\"` *will* propagate into the\n * builder and into anything else holding a previous output. Treat the\n * output as read-only, or deep-clone it before mutating.\n *\n * Inputs to {@link add} are still safe to mutate after calling: `add` stores\n * a shallow copy of the props record on registration.\n */\n build() {\n const objects = {};\n for (const [apiName, typeMap] of this.#objects) {\n objects[apiName] = [...typeMap.values()];\n }\n return {\n objects,\n links: [...this.#links]\n };\n }\n}\n\n/**\n * Create seed data using a builder function.\n *\n * The builder is created, passed to `fn`, and the resulting {@link SeedOutput}\n * is returned as the module's default export for consumption by the seed compiler.\n *\n * @param fn - A function that registers objects and links on the provided {@link SeedBuilder}.\n * @returns The built {@link SeedOutput} containing all registered objects and links.\n *\n * @example\n * ```ts\n * import { Product, Seller } from \"@ontology/sdk\";\n * import { createSeed } from \"@osdk/seed-helpers\";\n *\n * export default createSeed((seed) => {\n * const prod = seed.add(Product, { pk: \"prod-001\", title: \"Widget\", price: 100 });\n * const alice = seed.add(Seller, { pk: \"seller-001\", name: \"Alice\" });\n * seed.link(\"widget-seller\", prod, \"sellers\", alice, \"products\");\n * });\n * ```\n */\nexport function createSeed(fn) {\n const builder = new SeedBuilder();\n fn(builder);\n return builder.build();\n}"]}
@@ -0,0 +1,120 @@
1
+ import { ObjectTypeDefinition, CompileTimeMetadata, LinkNames, LinkedType } from '@osdk/api';
2
+
3
+ /**
4
+ * Makes nullable properties optional while keeping non-nullable ones required.
5
+ * `{ id: string; title: string | undefined }` becomes `{ id: string; title?: string }`.
6
+ * This ensures required fields like primary keys must always be provided.
7
+ */
8
+ type PartialForOptionalProperties<T> = {
9
+ [K in keyof T as undefined extends T[K] ? K : never]?: NonNullable<T[K]>;
10
+ } & {
11
+ [K in keyof T as undefined extends T[K] ? never : K]-?: T[K];
12
+ };
13
+ /**
14
+ * Derives the property types for seed data from the generated SDK type.
15
+ * Uses CompileTimeMetadata<T>["props"] which resolves to the Props interface
16
+ * on generated types (e.g., Employee.Props). Non-nullable properties like the
17
+ * primary key are required; nullable properties are optional.
18
+ */
19
+ type SeedProps<T extends ObjectTypeDefinition> = PartialForOptionalProperties<CompileTimeMetadata<T>["props"]>;
20
+ /**
21
+ * A typed reference returned by SeedBuilder.add(). The branded symbol field
22
+ * carries the object type as a generic, enabling compile-time link validation.
23
+ *
24
+ * Cannot be constructed manually — the unique symbol key is not exported and
25
+ * only `SeedBuilder.add()` can produce a valid `SeedRef` via an `as` cast.
26
+ */
27
+ interface SeedRef<Q extends ObjectTypeDefinition = ObjectTypeDefinition> {
28
+ readonly __objectTypeApiName: string;
29
+ readonly __primaryKey: string | number;
30
+ }
31
+ /** A link entry in the seed output. */
32
+ interface SeedLinkEntry {
33
+ name: string;
34
+ linkType: string;
35
+ sourceObjectType: string;
36
+ sourceKey: string;
37
+ targetObjectType: string;
38
+ targetKey: string;
39
+ }
40
+ /** The final serializable seed data output. */
41
+ interface SeedOutput {
42
+ objects: Record<string, Array<Record<string, unknown>>>;
43
+ links: SeedLinkEntry[];
44
+ }
45
+
46
+ /**
47
+ * A lightweight, type-safe builder for constructing seed data.
48
+ *
49
+ * TypeScript catches everything expressible at the call site: property
50
+ * names and value types, required primary keys, link names valid on the
51
+ * source type, and link target types matching what the link points to.
52
+ */
53
+ declare class SeedBuilder {
54
+ #private;
55
+ /**
56
+ * Register a seed object and return a typed reference for use in {@link link}.
57
+ *
58
+ * Property names and value types are validated at compile time against the
59
+ * generated SDK type. Non-nullable properties (including the primary key)
60
+ * are required.
61
+ *
62
+ * @param type - The generated SDK object type definition (e.g., `Product`).
63
+ * @param props - Property values for the object. Must match the SDK type's property schema.
64
+ * @returns A frozen {@link SeedRef} carrying the object type and primary key.
65
+ * @throws if the primary key is null, undefined, or already registered for this type.
66
+ * @throws if the object type definition is missing `apiName` or `primaryKeyApiName`.
67
+ */
68
+ add<Q extends ObjectTypeDefinition>(type: Q, props: SeedProps<Q>): SeedRef<Q>;
69
+ /**
70
+ * Register a link between two seed objects.
71
+ *
72
+ * Supports two calling conventions that produce identical output:
73
+ * by-reference (passing `SeedRef`s returned from {@link add}) or by-type
74
+ * and primary-key. See the `@osdk/seed-compiler` README for usage examples.
75
+ *
76
+ * @param name - A descriptive label for this link (included in seed output and error messages).
77
+ * @throws if either source or target object was not registered via {@link add}.
78
+ */
79
+ link<S extends ObjectTypeDefinition, SL extends LinkNames<S>, D extends LinkedType<S, SL>, DL extends LinkNames<D>>(name: string, src: SeedRef<S>, srcLinkName: SL, dst: SeedRef<D>, dstLinkName: DL): void;
80
+ link<S extends ObjectTypeDefinition, SL extends LinkNames<S>, D extends LinkedType<S, SL>, DL extends LinkNames<D>>(name: string, srcType: S, srcPk: string | number, srcLinkName: SL, dstType: D, dstPk: string | number, dstLinkName: DL): void;
81
+ /**
82
+ * Build the final {@link SeedOutput} from all registered objects and links.
83
+ *
84
+ * The returned arrays are fresh copies, so a subsequent `add()` or `link()`
85
+ * call does not retroactively grow or shrink an array that was already
86
+ * returned. The property records inside the arrays, however, are shared
87
+ * references with the builder's internal storage — mutating
88
+ * `output.objects.Employee[0].name = "x"` *will* propagate into the
89
+ * builder and into anything else holding a previous output. Treat the
90
+ * output as read-only, or deep-clone it before mutating.
91
+ *
92
+ * Inputs to {@link add} are still safe to mutate after calling: `add` stores
93
+ * a shallow copy of the props record on registration.
94
+ */
95
+ build(): SeedOutput;
96
+ }
97
+ /**
98
+ * Create seed data using a builder function.
99
+ *
100
+ * The builder is created, passed to `fn`, and the resulting {@link SeedOutput}
101
+ * is returned as the module's default export for consumption by the seed compiler.
102
+ *
103
+ * @param fn - A function that registers objects and links on the provided {@link SeedBuilder}.
104
+ * @returns The built {@link SeedOutput} containing all registered objects and links.
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * import { Product, Seller } from "@ontology/sdk";
109
+ * import { createSeed } from "@osdk/seed-helpers";
110
+ *
111
+ * export default createSeed((seed) => {
112
+ * const prod = seed.add(Product, { pk: "prod-001", title: "Widget", price: 100 });
113
+ * const alice = seed.add(Seller, { pk: "seller-001", name: "Alice" });
114
+ * seed.link("widget-seller", prod, "sellers", alice, "products");
115
+ * });
116
+ * ```
117
+ */
118
+ declare function createSeed(fn: (seed: SeedBuilder) => void): SeedOutput;
119
+
120
+ export { SeedBuilder, type SeedLinkEntry, type SeedOutput, type SeedProps, type SeedRef, createSeed };
@@ -0,0 +1,196 @@
1
+ /*
2
+ * Copyright 2025 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
+ /** Internal representation of a resolved link before validation. */
18
+
19
+ /** Checks whether a value is a {@link SeedRef} returned by `SeedBuilder.add()`. */
20
+ function isSeedRef(value) {
21
+ return typeof value === "object" && value != null && "__objectTypeApiName" in value && "__primaryKey" in value;
22
+ }
23
+
24
+ /**
25
+ * Resolves a link from two {@link SeedRef} instances.
26
+ * Extracts the object type and primary key from each ref.
27
+ */
28
+ function resolveFromRefs(src, srcLinkName, dst) {
29
+ return {
30
+ sourceObjectType: src.__objectTypeApiName,
31
+ sourceKey: String(src.__primaryKey),
32
+ linkType: srcLinkName,
33
+ targetObjectType: dst.__objectTypeApiName,
34
+ targetKey: String(dst.__primaryKey)
35
+ };
36
+ }
37
+
38
+ /**
39
+ * Resolves a link from two {@link ObjectTypeDefinition} instances and explicit primary keys.
40
+ * Reads the `apiName` from each type definition.
41
+ */
42
+ function resolveFromTypes(srcType, srcPk, srcLinkName, dstType, dstPk) {
43
+ return {
44
+ sourceObjectType: srcType.apiName,
45
+ sourceKey: String(srcPk),
46
+ linkType: srcLinkName,
47
+ targetObjectType: dstType.apiName,
48
+ targetKey: String(dstPk)
49
+ };
50
+ }
51
+
52
+ /**
53
+ * A lightweight, type-safe builder for constructing seed data.
54
+ *
55
+ * TypeScript catches everything expressible at the call site: property
56
+ * names and value types, required primary keys, link names valid on the
57
+ * source type, and link target types matching what the link points to.
58
+ */
59
+ export class SeedBuilder {
60
+ #objects = new Map();
61
+ #refs = new Set();
62
+ #links = [];
63
+
64
+ /**
65
+ * Register a seed object and return a typed reference for use in {@link link}.
66
+ *
67
+ * Property names and value types are validated at compile time against the
68
+ * generated SDK type. Non-nullable properties (including the primary key)
69
+ * are required.
70
+ *
71
+ * @param type - The generated SDK object type definition (e.g., `Product`).
72
+ * @param props - Property values for the object. Must match the SDK type's property schema.
73
+ * @returns A frozen {@link SeedRef} carrying the object type and primary key.
74
+ * @throws if the primary key is null, undefined, or already registered for this type.
75
+ * @throws if the object type definition is missing `apiName` or `primaryKeyApiName`.
76
+ */
77
+ add(type, props) {
78
+ // Runtime guards for callers who bypass the type system with `as any`.
79
+ // Properly-typed ObjectTypeDefinition values can't reach these.
80
+ const apiName = type.apiName;
81
+ const pkApiName = type.primaryKeyApiName;
82
+ if (!apiName) {
83
+ throw new Error("Object type is missing apiName");
84
+ }
85
+ if (!pkApiName) {
86
+ throw new Error(`[${apiName}] Object type is missing primaryKeyApiName`);
87
+ }
88
+ const record = props;
89
+ const pkValue = record[pkApiName];
90
+ if (pkValue == null) {
91
+ throw new Error(`[${apiName}] Primary key '${pkApiName}' is null or undefined`);
92
+ }
93
+ const pk = String(pkValue);
94
+ let typeMap = this.#objects.get(apiName);
95
+ if (!typeMap) {
96
+ typeMap = new Map();
97
+ this.#objects.set(apiName, typeMap);
98
+ }
99
+ if (typeMap.has(pk)) {
100
+ throw new Error(`[${apiName}] Duplicate primary key '${pk}'`);
101
+ }
102
+ typeMap.set(pk, {
103
+ ...record
104
+ });
105
+ this.#refs.add(`${apiName}:${pk}`);
106
+ return Object.freeze({
107
+ __objectTypeApiName: apiName,
108
+ __primaryKey: pkValue
109
+ });
110
+ }
111
+
112
+ /**
113
+ * Register a link between two seed objects.
114
+ *
115
+ * Supports two calling conventions that produce identical output:
116
+ * by-reference (passing `SeedRef`s returned from {@link add}) or by-type
117
+ * and primary-key. See the `@osdk/seed-compiler` README for usage examples.
118
+ *
119
+ * @param name - A descriptive label for this link (included in seed output and error messages).
120
+ * @throws if either source or target object was not registered via {@link add}.
121
+ */
122
+
123
+ link(name, srcOrType, linkNameOrPk, dstOrLinkName, typeOrLinkName, dstPk) {
124
+ const resolved = isSeedRef(srcOrType) ? resolveFromRefs(srcOrType, linkNameOrPk, dstOrLinkName) : resolveFromTypes(srcOrType, linkNameOrPk, dstOrLinkName, typeOrLinkName, dstPk);
125
+ this.#assertRegistered(resolved.sourceObjectType, resolved.sourceKey, "Source", name);
126
+ this.#assertRegistered(resolved.targetObjectType, resolved.targetKey, "Target", name);
127
+ this.#links.push({
128
+ name,
129
+ ...resolved
130
+ });
131
+ }
132
+
133
+ /**
134
+ * Asserts that an object with the given type and key was registered via {@link add}.
135
+ * @throws with a descriptive message including the link name for context.
136
+ */
137
+ #assertRegistered(objectType, key, role, linkName) {
138
+ const ref = `${objectType}:${key}`;
139
+ if (!this.#refs.has(ref)) {
140
+ throw new Error(`${role} '${ref}' not registered (link '${linkName}')`);
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Build the final {@link SeedOutput} from all registered objects and links.
146
+ *
147
+ * The returned arrays are fresh copies, so a subsequent `add()` or `link()`
148
+ * call does not retroactively grow or shrink an array that was already
149
+ * returned. The property records inside the arrays, however, are shared
150
+ * references with the builder's internal storage — mutating
151
+ * `output.objects.Employee[0].name = "x"` *will* propagate into the
152
+ * builder and into anything else holding a previous output. Treat the
153
+ * output as read-only, or deep-clone it before mutating.
154
+ *
155
+ * Inputs to {@link add} are still safe to mutate after calling: `add` stores
156
+ * a shallow copy of the props record on registration.
157
+ */
158
+ build() {
159
+ const objects = {};
160
+ for (const [apiName, typeMap] of this.#objects) {
161
+ objects[apiName] = [...typeMap.values()];
162
+ }
163
+ return {
164
+ objects,
165
+ links: [...this.#links]
166
+ };
167
+ }
168
+ }
169
+
170
+ /**
171
+ * Create seed data using a builder function.
172
+ *
173
+ * The builder is created, passed to `fn`, and the resulting {@link SeedOutput}
174
+ * is returned as the module's default export for consumption by the seed compiler.
175
+ *
176
+ * @param fn - A function that registers objects and links on the provided {@link SeedBuilder}.
177
+ * @returns The built {@link SeedOutput} containing all registered objects and links.
178
+ *
179
+ * @example
180
+ * ```ts
181
+ * import { Product, Seller } from "@ontology/sdk";
182
+ * import { createSeed } from "@osdk/seed-helpers";
183
+ *
184
+ * export default createSeed((seed) => {
185
+ * const prod = seed.add(Product, { pk: "prod-001", title: "Widget", price: 100 });
186
+ * const alice = seed.add(Seller, { pk: "seller-001", name: "Alice" });
187
+ * seed.link("widget-seller", prod, "sellers", alice, "products");
188
+ * });
189
+ * ```
190
+ */
191
+ export function createSeed(fn) {
192
+ const builder = new SeedBuilder();
193
+ fn(builder);
194
+ return builder.build();
195
+ }
196
+ //# sourceMappingURL=SeedBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SeedBuilder.js","names":["isSeedRef","value","resolveFromRefs","src","srcLinkName","dst","sourceObjectType","__objectTypeApiName","sourceKey","String","__primaryKey","linkType","targetObjectType","targetKey","resolveFromTypes","srcType","srcPk","dstType","dstPk","apiName","SeedBuilder","objects","Map","refs","Set","links","add","type","props","pkApiName","primaryKeyApiName","Error","record","pkValue","pk","typeMap","get","set","has","Object","freeze","link","name","srcOrType","linkNameOrPk","dstOrLinkName","typeOrLinkName","resolved","assertRegistered","push","#assertRegistered","objectType","key","role","linkName","ref","build","values","createSeed","fn","builder"],"sources":["SeedBuilder.ts"],"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\nimport type { LinkedType, LinkNames, ObjectTypeDefinition } from \"@osdk/api\";\nimport type { SeedLinkEntry, SeedOutput, SeedProps, SeedRef } from \"./types.js\";\n\n/** Internal representation of a resolved link before validation. */\ninterface ResolvedLink {\n sourceObjectType: string;\n sourceKey: string;\n linkType: string;\n targetObjectType: string;\n targetKey: string;\n}\n\n/** Checks whether a value is a {@link SeedRef} returned by `SeedBuilder.add()`. */\nfunction isSeedRef(value: unknown): value is SeedRef {\n return typeof value === \"object\"\n && value != null\n && \"__objectTypeApiName\" in value\n && \"__primaryKey\" in value;\n}\n\n/**\n * Resolves a link from two {@link SeedRef} instances.\n * Extracts the object type and primary key from each ref.\n */\nfunction resolveFromRefs(\n src: SeedRef,\n srcLinkName: string,\n dst: SeedRef,\n): ResolvedLink {\n return {\n sourceObjectType: src.__objectTypeApiName,\n sourceKey: String(src.__primaryKey),\n linkType: srcLinkName,\n targetObjectType: dst.__objectTypeApiName,\n targetKey: String(dst.__primaryKey),\n };\n}\n\n/**\n * Resolves a link from two {@link ObjectTypeDefinition} instances and explicit primary keys.\n * Reads the `apiName` from each type definition.\n */\nfunction resolveFromTypes(\n srcType: ObjectTypeDefinition,\n srcPk: string | number,\n srcLinkName: string,\n dstType: ObjectTypeDefinition,\n dstPk: string | number,\n): ResolvedLink {\n return {\n sourceObjectType: srcType.apiName,\n sourceKey: String(srcPk),\n linkType: srcLinkName,\n targetObjectType: dstType.apiName,\n targetKey: String(dstPk),\n };\n}\n\n/**\n * A lightweight, type-safe builder for constructing seed data.\n *\n * TypeScript catches everything expressible at the call site: property\n * names and value types, required primary keys, link names valid on the\n * source type, and link target types matching what the link points to.\n */\nexport class SeedBuilder {\n readonly #objects = new Map<string, Map<string, Record<string, unknown>>>();\n readonly #refs = new Set<string>();\n readonly #links: SeedLinkEntry[] = [];\n\n /**\n * Register a seed object and return a typed reference for use in {@link link}.\n *\n * Property names and value types are validated at compile time against the\n * generated SDK type. Non-nullable properties (including the primary key)\n * are required.\n *\n * @param type - The generated SDK object type definition (e.g., `Product`).\n * @param props - Property values for the object. Must match the SDK type's property schema.\n * @returns A frozen {@link SeedRef} carrying the object type and primary key.\n * @throws if the primary key is null, undefined, or already registered for this type.\n * @throws if the object type definition is missing `apiName` or `primaryKeyApiName`.\n */\n add<Q extends ObjectTypeDefinition>(\n type: Q,\n props: SeedProps<Q>,\n ): SeedRef<Q> {\n // Runtime guards for callers who bypass the type system with `as any`.\n // Properly-typed ObjectTypeDefinition values can't reach these.\n const apiName = type.apiName;\n const pkApiName = type.primaryKeyApiName;\n\n if (!apiName) {\n throw new Error(\"Object type is missing apiName\");\n }\n if (!pkApiName) {\n throw new Error(`[${apiName}] Object type is missing primaryKeyApiName`);\n }\n\n const record = props as Record<string, unknown>;\n const pkValue = record[pkApiName];\n\n if (pkValue == null) {\n throw new Error(\n `[${apiName}] Primary key '${pkApiName}' is null or undefined`,\n );\n }\n\n const pk = String(pkValue);\n\n let typeMap = this.#objects.get(apiName);\n if (!typeMap) {\n typeMap = new Map();\n this.#objects.set(apiName, typeMap);\n }\n\n if (typeMap.has(pk)) {\n throw new Error(`[${apiName}] Duplicate primary key '${pk}'`);\n }\n\n typeMap.set(pk, { ...record });\n this.#refs.add(`${apiName}:${pk}`);\n\n return Object.freeze({\n __objectTypeApiName: apiName,\n __primaryKey: pkValue as string | number,\n }) as SeedRef<Q>;\n }\n\n /**\n * Register a link between two seed objects.\n *\n * Supports two calling conventions that produce identical output:\n * by-reference (passing `SeedRef`s returned from {@link add}) or by-type\n * and primary-key. See the `@osdk/seed-compiler` README for usage examples.\n *\n * @param name - A descriptive label for this link (included in seed output and error messages).\n * @throws if either source or target object was not registered via {@link add}.\n */\n link<\n S extends ObjectTypeDefinition,\n SL extends LinkNames<S>,\n D extends LinkedType<S, SL>,\n DL extends LinkNames<D>,\n >(\n name: string,\n src: SeedRef<S>,\n srcLinkName: SL,\n dst: SeedRef<D>,\n dstLinkName: DL,\n ): void;\n link<\n S extends ObjectTypeDefinition,\n SL extends LinkNames<S>,\n D extends LinkedType<S, SL>,\n DL extends LinkNames<D>,\n >(\n name: string,\n srcType: S,\n srcPk: string | number,\n srcLinkName: SL,\n dstType: D,\n dstPk: string | number,\n dstLinkName: DL,\n ): void;\n link(\n name: string,\n srcOrType: SeedRef | ObjectTypeDefinition,\n linkNameOrPk: string | number,\n dstOrLinkName: SeedRef | ObjectTypeDefinition | string,\n typeOrLinkName?: ObjectTypeDefinition | string,\n dstPk?: string | number,\n _dstLinkName?: string,\n ): void {\n const resolved = isSeedRef(srcOrType)\n ? resolveFromRefs(\n srcOrType,\n linkNameOrPk as string,\n dstOrLinkName as SeedRef,\n )\n : resolveFromTypes(\n srcOrType,\n linkNameOrPk,\n dstOrLinkName as string,\n typeOrLinkName as ObjectTypeDefinition,\n dstPk!,\n );\n\n this.#assertRegistered(\n resolved.sourceObjectType,\n resolved.sourceKey,\n \"Source\",\n name,\n );\n this.#assertRegistered(\n resolved.targetObjectType,\n resolved.targetKey,\n \"Target\",\n name,\n );\n\n this.#links.push({ name, ...resolved });\n }\n\n /**\n * Asserts that an object with the given type and key was registered via {@link add}.\n * @throws with a descriptive message including the link name for context.\n */\n #assertRegistered(\n objectType: string,\n key: string,\n role: \"Source\" | \"Target\",\n linkName: string,\n ): void {\n const ref = `${objectType}:${key}`;\n if (!this.#refs.has(ref)) {\n throw new Error(\n `${role} '${ref}' not registered (link '${linkName}')`,\n );\n }\n }\n\n /**\n * Build the final {@link SeedOutput} from all registered objects and links.\n *\n * The returned arrays are fresh copies, so a subsequent `add()` or `link()`\n * call does not retroactively grow or shrink an array that was already\n * returned. The property records inside the arrays, however, are shared\n * references with the builder's internal storage — mutating\n * `output.objects.Employee[0].name = \"x\"` *will* propagate into the\n * builder and into anything else holding a previous output. Treat the\n * output as read-only, or deep-clone it before mutating.\n *\n * Inputs to {@link add} are still safe to mutate after calling: `add` stores\n * a shallow copy of the props record on registration.\n */\n build(): SeedOutput {\n const objects: Record<string, Array<Record<string, unknown>>> = {};\n for (const [apiName, typeMap] of this.#objects) {\n objects[apiName] = [...typeMap.values()];\n }\n return { objects, links: [...this.#links] };\n }\n}\n\n/**\n * Create seed data using a builder function.\n *\n * The builder is created, passed to `fn`, and the resulting {@link SeedOutput}\n * is returned as the module's default export for consumption by the seed compiler.\n *\n * @param fn - A function that registers objects and links on the provided {@link SeedBuilder}.\n * @returns The built {@link SeedOutput} containing all registered objects and links.\n *\n * @example\n * ```ts\n * import { Product, Seller } from \"@ontology/sdk\";\n * import { createSeed } from \"@osdk/seed-helpers\";\n *\n * export default createSeed((seed) => {\n * const prod = seed.add(Product, { pk: \"prod-001\", title: \"Widget\", price: 100 });\n * const alice = seed.add(Seller, { pk: \"seller-001\", name: \"Alice\" });\n * seed.link(\"widget-seller\", prod, \"sellers\", alice, \"products\");\n * });\n * ```\n */\nexport function createSeed(fn: (seed: SeedBuilder) => void): SeedOutput {\n const builder = new SeedBuilder();\n fn(builder);\n return builder.build();\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,18 @@
1
+ /*
2
+ * Copyright 2025 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
+ export { createSeed, SeedBuilder } from "./SeedBuilder.js";
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["createSeed","SeedBuilder"],"sources":["index.ts"],"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 { createSeed, SeedBuilder } from \"./SeedBuilder.js\";\nexport type { SeedLinkEntry, SeedOutput, SeedProps, SeedRef } from \"./types.js\";\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,UAAU,EAAEC,WAAW,QAAQ,kBAAkB","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","names":[],"sources":["types.ts"],"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\nimport type { CompileTimeMetadata, ObjectTypeDefinition } from \"@osdk/api\";\n\n/**\n * Makes nullable properties optional while keeping non-nullable ones required.\n * `{ id: string; title: string | undefined }` becomes `{ id: string; title?: string }`.\n * This ensures required fields like primary keys must always be provided.\n */\ntype PartialForOptionalProperties<T> =\n & {\n [K in keyof T as undefined extends T[K] ? K : never]?: NonNullable<T[K]>;\n }\n & {\n [K in keyof T as undefined extends T[K] ? never : K]-?: T[K];\n };\n\n/**\n * Derives the property types for seed data from the generated SDK type.\n * Uses CompileTimeMetadata<T>[\"props\"] which resolves to the Props interface\n * on generated types (e.g., Employee.Props). Non-nullable properties like the\n * primary key are required; nullable properties are optional.\n */\nexport type SeedProps<T extends ObjectTypeDefinition> =\n PartialForOptionalProperties<\n CompileTimeMetadata<T>[\"props\"]\n >;\n\n/**\n * Unique symbol used to brand {@link SeedRef} instances. A branded type prevents\n * manually constructed objects from satisfying the interface — only `SeedBuilder.add()`\n * can produce a valid `SeedRef`. This ensures `link()` generics always have the\n * correct object type for compile-time link name and target type validation.\n */\ndeclare const SEED_REF_BRAND: unique symbol;\n\n/**\n * A typed reference returned by SeedBuilder.add(). The branded symbol field\n * carries the object type as a generic, enabling compile-time link validation.\n *\n * Cannot be constructed manually — the unique symbol key is not exported and\n * only `SeedBuilder.add()` can produce a valid `SeedRef` via an `as` cast.\n */\nexport interface SeedRef<\n Q extends ObjectTypeDefinition = ObjectTypeDefinition,\n> {\n readonly __objectTypeApiName: string;\n readonly __primaryKey: string | number;\n /** @internal Brand field — never set at runtime. Enforces nominal typing. */\n readonly [SEED_REF_BRAND]: Q;\n}\n\n/** A link entry in the seed output. */\nexport interface SeedLinkEntry {\n name: string;\n linkType: string;\n sourceObjectType: string;\n sourceKey: string;\n targetObjectType: string;\n targetKey: string;\n}\n\n/** The final serializable seed data output. */\nexport interface SeedOutput {\n objects: Record<string, Array<Record<string, unknown>>>;\n links: SeedLinkEntry[];\n}\n"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,85 @@
1
+ import type { LinkedType, LinkNames, ObjectTypeDefinition } from "@osdk/api";
2
+ import type { SeedOutput, SeedProps, SeedRef } from "./types.js";
3
+ /**
4
+ * A lightweight, type-safe builder for constructing seed data.
5
+ *
6
+ * TypeScript catches everything expressible at the call site: property
7
+ * names and value types, required primary keys, link names valid on the
8
+ * source type, and link target types matching what the link points to.
9
+ */
10
+ export declare class SeedBuilder {
11
+ #private;
12
+ /**
13
+ * Register a seed object and return a typed reference for use in {@link link}.
14
+ *
15
+ * Property names and value types are validated at compile time against the
16
+ * generated SDK type. Non-nullable properties (including the primary key)
17
+ * are required.
18
+ *
19
+ * @param type - The generated SDK object type definition (e.g., `Product`).
20
+ * @param props - Property values for the object. Must match the SDK type's property schema.
21
+ * @returns A frozen {@link SeedRef} carrying the object type and primary key.
22
+ * @throws if the primary key is null, undefined, or already registered for this type.
23
+ * @throws if the object type definition is missing `apiName` or `primaryKeyApiName`.
24
+ */
25
+ add<Q extends ObjectTypeDefinition>(type: Q, props: SeedProps<Q>): SeedRef<Q>;
26
+ /**
27
+ * Register a link between two seed objects.
28
+ *
29
+ * Supports two calling conventions that produce identical output:
30
+ * by-reference (passing `SeedRef`s returned from {@link add}) or by-type
31
+ * and primary-key. See the `@osdk/seed-compiler` README for usage examples.
32
+ *
33
+ * @param name - A descriptive label for this link (included in seed output and error messages).
34
+ * @throws if either source or target object was not registered via {@link add}.
35
+ */
36
+ link<
37
+ S extends ObjectTypeDefinition,
38
+ SL extends LinkNames<S>,
39
+ D extends LinkedType<S, SL>,
40
+ DL extends LinkNames<D>
41
+ >(name: string, src: SeedRef<S>, srcLinkName: SL, dst: SeedRef<D>, dstLinkName: DL): void;
42
+ link<
43
+ S extends ObjectTypeDefinition,
44
+ SL extends LinkNames<S>,
45
+ D extends LinkedType<S, SL>,
46
+ DL extends LinkNames<D>
47
+ >(name: string, srcType: S, srcPk: string | number, srcLinkName: SL, dstType: D, dstPk: string | number, dstLinkName: DL): void;
48
+ /**
49
+ * Build the final {@link SeedOutput} from all registered objects and links.
50
+ *
51
+ * The returned arrays are fresh copies, so a subsequent `add()` or `link()`
52
+ * call does not retroactively grow or shrink an array that was already
53
+ * returned. The property records inside the arrays, however, are shared
54
+ * references with the builder's internal storage — mutating
55
+ * `output.objects.Employee[0].name = "x"` *will* propagate into the
56
+ * builder and into anything else holding a previous output. Treat the
57
+ * output as read-only, or deep-clone it before mutating.
58
+ *
59
+ * Inputs to {@link add} are still safe to mutate after calling: `add` stores
60
+ * a shallow copy of the props record on registration.
61
+ */
62
+ build(): SeedOutput;
63
+ }
64
+ /**
65
+ * Create seed data using a builder function.
66
+ *
67
+ * The builder is created, passed to `fn`, and the resulting {@link SeedOutput}
68
+ * is returned as the module's default export for consumption by the seed compiler.
69
+ *
70
+ * @param fn - A function that registers objects and links on the provided {@link SeedBuilder}.
71
+ * @returns The built {@link SeedOutput} containing all registered objects and links.
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * import { Product, Seller } from "@ontology/sdk";
76
+ * import { createSeed } from "@osdk/seed-helpers";
77
+ *
78
+ * export default createSeed((seed) => {
79
+ * const prod = seed.add(Product, { pk: "prod-001", title: "Widget", price: 100 });
80
+ * const alice = seed.add(Seller, { pk: "seller-001", name: "Alice" });
81
+ * seed.link("widget-seller", prod, "sellers", alice, "products");
82
+ * });
83
+ * ```
84
+ */
85
+ export declare function createSeed(fn: (seed: SeedBuilder) => void): SeedOutput;
@@ -0,0 +1 @@
1
+ {"mappings":"AAgBA,cAAc,YAAY,WAAW,4BAA4B,WAAY;AAC7E,cAA6B,YAAY,WAAW,eAAe,YAAa;;;;;;;;AAgEhF,OAAO,cAAM,YAAY;;;;;;;;;;;;;;;CAkBvB,IAAI,UAAU,sBACZA,MAAM,GACNC,OAAO,UAAU,KAChB,QAAQ;;;;;;;;;;;CAqDX;EACE,UAAU;EACV,WAAW,UAAU;EACrB,UAAU,WAAW,GAAG;EACxB,WAAW,UAAU;GAErBC,cACAC,KAAK,QAAQ,IACbC,aAAa,IACbC,KAAK,QAAQ,IACbC,aAAa;CAEf;EACE,UAAU;EACV,WAAW,UAAU;EACrB,UAAU,WAAW,GAAG;EACxB,WAAW,UAAU;GAErBJ,cACAK,SAAS,GACTC,wBACAJ,aAAa,IACbK,SAAS,GACTC,wBACAJ,aAAa;;;;;;;;;;;;;;;CAyEf,SAAS;AAOV;;;;;;;;;;;;;;;;;;;;;;AAuBD,OAAO,iBAAS,WAAWK,KAAKC,MAAM,uBAAuB","names":["type: Q","props: SeedProps<Q>","name: string","src: SeedRef<S>","srcLinkName: SL","dst: SeedRef<D>","dstLinkName: DL","srcType: S","srcPk: string | number","dstType: D","dstPk: string | number","fn: (seed: SeedBuilder) => void","seed: SeedBuilder"],"sources":["../../src/SeedBuilder.ts"],"version":3,"file":"SeedBuilder.d.ts"}
@@ -0,0 +1,2 @@
1
+ export { createSeed, SeedBuilder } from "./SeedBuilder.js";
2
+ export type { SeedLinkEntry, SeedOutput, SeedProps, SeedRef } from "./types.js";
@@ -0,0 +1 @@
1
+ {"mappings":"AAgBA,SAAS,YAAY,mBAAmB;AACxC,cAAc,eAAe,YAAY,WAAW,eAAe","names":[],"sources":["../../src/index.ts"],"version":3,"file":"index.d.ts"}
@@ -0,0 +1,40 @@
1
+ import type { CompileTimeMetadata, ObjectTypeDefinition } from "@osdk/api";
2
+ /**
3
+ * Makes nullable properties optional while keeping non-nullable ones required.
4
+ * `{ id: string; title: string | undefined }` becomes `{ id: string; title?: string }`.
5
+ * This ensures required fields like primary keys must always be provided.
6
+ */
7
+ type PartialForOptionalProperties<T> = { [K in keyof T as undefined extends T[K] ? K : never]? : NonNullable<T[K]> } & { [K in keyof T as undefined extends T[K] ? never : K]-? : T[K] };
8
+ /**
9
+ * Derives the property types for seed data from the generated SDK type.
10
+ * Uses CompileTimeMetadata<T>["props"] which resolves to the Props interface
11
+ * on generated types (e.g., Employee.Props). Non-nullable properties like the
12
+ * primary key are required; nullable properties are optional.
13
+ */
14
+ export type SeedProps<T extends ObjectTypeDefinition> = PartialForOptionalProperties<CompileTimeMetadata<T>["props"]>;
15
+ /**
16
+ * A typed reference returned by SeedBuilder.add(). The branded symbol field
17
+ * carries the object type as a generic, enabling compile-time link validation.
18
+ *
19
+ * Cannot be constructed manually — the unique symbol key is not exported and
20
+ * only `SeedBuilder.add()` can produce a valid `SeedRef` via an `as` cast.
21
+ */
22
+ export interface SeedRef<Q extends ObjectTypeDefinition = ObjectTypeDefinition> {
23
+ readonly __objectTypeApiName: string;
24
+ readonly __primaryKey: string | number;
25
+ }
26
+ /** A link entry in the seed output. */
27
+ export interface SeedLinkEntry {
28
+ name: string;
29
+ linkType: string;
30
+ sourceObjectType: string;
31
+ sourceKey: string;
32
+ targetObjectType: string;
33
+ targetKey: string;
34
+ }
35
+ /** The final serializable seed data output. */
36
+ export interface SeedOutput {
37
+ objects: Record<string, Array<Record<string, unknown>>>;
38
+ links: SeedLinkEntry[];
39
+ }
40
+ export {};
@@ -0,0 +1 @@
1
+ {"mappings":"AAgBA,cAAc,qBAAqB,4BAA4B,WAAY;;;;;;KAOtE,6BAA6B,QAE7B,WAAW,uBAAuB,EAAE,KAAK,cAAa,YAAY,EAAE,WAGpE,WAAW,uBAAuB,EAAE,aAAa,OAAM,EAAE;;;;;;;AAS9D,YAAY,UAAU,UAAU,wBAC9B,6BACE,oBAAoB,GAAG;;;;;;;;AAkB3B,iBAAiB,QACf,UAAU,uBAAuB,sBACjC;UACS;UACA;AAGV;;AAGD,iBAAiB,cAAc;CAC7B;CACA;CACA;CACA;CACA;CACA;AACD;;AAGD,iBAAiB,WAAW;CAC1B,SAAS,eAAe,MAAM;CAC9B,OAAO;AACR","names":[],"sources":["../../src/types.ts"],"version":3,"file":"types.d.ts"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@osdk/seed-helpers",
3
+ "version": "0.2.0",
4
+ "license": "Apache-2.0",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/palantir/osdk-ts.git"
8
+ },
9
+ "exports": {
10
+ ".": {
11
+ "browser": "./build/browser/index.js",
12
+ "import": {
13
+ "types": "./build/types/index.d.ts",
14
+ "default": "./build/esm/index.js"
15
+ },
16
+ "require": "./build/cjs/index.cjs",
17
+ "default": "./build/browser/index.js"
18
+ },
19
+ "./*": {
20
+ "browser": "./build/browser/public/*.js",
21
+ "import": {
22
+ "types": "./build/types/public/*.d.ts",
23
+ "default": "./build/esm/public/*.js"
24
+ },
25
+ "require": "./build/cjs/public/*.cjs",
26
+ "default": "./build/browser/public/*.js"
27
+ }
28
+ },
29
+ "dependencies": {
30
+ "@osdk/api": "~2.18.0"
31
+ },
32
+ "devDependencies": {
33
+ "typescript": "~5.5.4",
34
+ "vitest": "^3.2.4",
35
+ "@osdk/monorepo.api-extractor": "~0.7.0",
36
+ "@osdk/monorepo.tsconfig": "~0.7.0"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "files": [
42
+ "build/cjs",
43
+ "build/esm",
44
+ "build/browser",
45
+ "build/types",
46
+ "CHANGELOG.md",
47
+ "package.json",
48
+ "templates",
49
+ "*.d.ts"
50
+ ],
51
+ "main": "./build/cjs/index.cjs",
52
+ "module": "./build/esm/index.js",
53
+ "types": "./build/cjs/index.d.cts",
54
+ "type": "module",
55
+ "scripts": {
56
+ "check-attw": "attw --pack .",
57
+ "check-spelling": "cspell --quiet .",
58
+ "clean": "rm -rf lib dist types build tsconfig.tsbuildinfo",
59
+ "fix-lint": "eslint . --fix && dprint fmt",
60
+ "lint": "eslint . && dprint check",
61
+ "test": "vitest run",
62
+ "transpileBrowser": "monorepo.tool.transpile -f esm -m normal -t browser",
63
+ "transpileCjs": "monorepo.tool.transpile -f cjs -m bundle -t node",
64
+ "transpileEsm": "monorepo.tool.transpile -f esm -m normal -t node",
65
+ "transpileTypes": "monorepo.tool.transpile -f esm -m types -t node",
66
+ "typecheck": "tsc --noEmit --emitDeclarationOnly false"
67
+ }
68
+ }