@palantir/pack.schema 0.27.0 → 0.29.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.
@@ -13,31 +13,38 @@ export declare const TypeKind: {
13
13
  readonly USER_REF: "userRef";
14
14
  };
15
15
  export type TypeKind = typeof TypeKind[keyof typeof TypeKind];
16
+ /** A UTF-8 string field. */
16
17
  export type String = {
17
18
  readonly type: typeof TypeKind.STRING;
18
19
  };
20
+ /** A double-precision floating point number field. */
19
21
  export type Double = {
20
22
  readonly type: typeof TypeKind.DOUBLE;
21
23
  };
24
+ /** A boolean field. */
22
25
  export type Boolean = {
23
26
  readonly type: typeof TypeKind.BOOLEAN;
24
27
  };
25
28
  interface TypeBase {
26
29
  readonly type: TypeKind;
27
30
  }
31
+ /** A list of `T`. Nested arrays are not supported — wrap the inner array in a record. */
28
32
  export type Array<T extends TypeBase = TypeBase> = {
29
33
  readonly type: typeof TypeKind.ARRAY;
30
34
  readonly items: T;
31
35
  };
36
+ /** A reference to another record or union in the same schema. */
32
37
  export type Ref = {
33
38
  readonly type: typeof TypeKind.REF;
34
39
  readonly refType: "record" | "union";
35
40
  readonly name: string;
36
41
  };
42
+ /** A `T` that may be absent. Nested optionals are not supported. */
37
43
  export type Optional<T extends TypeBase = TypeBase> = {
38
44
  readonly type: typeof TypeKind.OPTIONAL;
39
45
  readonly item: T;
40
46
  };
47
+ /** An opaque, arbitrary JSON value. */
41
48
  export type Unknown = {
42
49
  readonly type: typeof TypeKind.UNKNOWN;
43
50
  };
@@ -56,12 +63,20 @@ export type ResourceRef = {
56
63
  export type UserRef = {
57
64
  readonly type: typeof TypeKind.USER_REF;
58
65
  };
66
+ /** Any valid field type: a primitive, a composite (`Array`/`Optional`), or a `Ref`. */
59
67
  export type Type = Array | Boolean | DocRef | Double | MediaRef | ObjectRef | ResourceRef | Optional | Ref | String | Unknown | UserRef;
68
+ /** A UTF-8 string field. */
60
69
  export declare const String: String;
70
+ /** A double-precision floating point number field. */
61
71
  export declare const Double: Double;
72
+ /** A boolean field. */
62
73
  export declare const Boolean: Boolean;
74
+ /** An opaque, arbitrary JSON value. */
63
75
  export declare const Unknown: Unknown;
76
+ /** A reference to a Foundry resource. */
64
77
  export declare const ResourceRef: ResourceRef;
78
+ /** Build an array field whose elements are `item`. */
65
79
  export declare const Array: <T extends TypeBase>(item: T) => Array<T>;
80
+ /** Build an optional field wrapping `item`, marking it as possibly absent. */
66
81
  export declare const Optional: <T extends TypeBase>(item: T) => Optional<T>;
67
82
  export {};
@@ -1 +1 @@
1
- {"mappings":"AAgBA,OAAO,cAAM;UACX,OAAO;UACP,SAAS;UACT,SAAS;UACT,QAAQ;UACR,WAAW;UACX,YAAY;UACZ,UAAU;UACV,KAAK;UACL,cAAc;UACd,QAAQ;UACR,SAAS;UACT,UAAU;;AAGZ,YAAY,kBAAkB,sBAAsB;AAEpD,YAAY,SAAS;UACV,aAAa,SAAS;;AAGjC,YAAY,SAAS;UACV,aAAa,SAAS;;AAGjC,YAAY,UAAU;UACX,aAAa,SAAS;;UAIvB,SAAS;UACR,MAAM;;AAGjB,YAAY,MAAM,UAAU,WAAW,YAAY;UACxC,aAAa,SAAS;UACtB,OAAO;;AAIlB,YAAY,MAAM;UACP,aAAa,SAAS;UACtB,SAAS,WAAW;UACpB;;AAGX,YAAY,SAAS,UAAU,WAAW,YAAY;UAC3C,aAAa,SAAS;UACtB,MAAM;;AAGjB,YAAY,UAAU;UACX,aAAa,SAAS;;AAGjC,YAAY,SAAS;UACV,aAAa,SAAS;;AAGjC,YAAY,WAAW;UACZ,aAAa,SAAS;;AAGjC,YAAY,YAAY;UACb,aAAa,SAAS;;AAGjC,YAAY,cAAc;UACf,aAAa,SAAS;;AAGjC,YAAY,UAAU;UACX,aAAa,SAAS;;AAGjC,YAAY,OACR,QACA,UACA,SACA,SACA,WACA,YACA,cACA,WACA,MACA,SACA,UACA;AAEJ,OAAO,cAAMA,QAAQ;AACrB,OAAO,cAAMC,QAAQ;AACrB,OAAO,cAAMC,SAAS;AACtB,OAAO,cAAMC,SAAS;AACtB,OAAO,cAAMC,aAAa;AAK1B,OAAO,cAAM,QAAS,UAAU,UAAU,MAAM,MAAI,MAAM;AAS1D,OAAO,cAAM,WAAY,UAAU,UAAU,MAAM,MAAI,SAAS","names":["String: String","Double: Double","Boolean: Boolean","Unknown: Unknown","ResourceRef: ResourceRef"],"sources":["../../src/primitives.ts"],"version":3,"file":"primitives.d.ts"}
1
+ {"mappings":"AAgBA,OAAO,cAAM;UACX,OAAO;UACP,SAAS;UACT,SAAS;UACT,QAAQ;UACR,WAAW;UACX,YAAY;UACZ,UAAU;UACV,KAAK;UACL,cAAc;UACd,QAAQ;UACR,SAAS;UACT,UAAU;;AAGZ,YAAY,kBAAkB,sBAAsB;;AAGpD,YAAY,SAAS;UACV,aAAa,SAAS;;;AAIjC,YAAY,SAAS;UACV,aAAa,SAAS;;;AAIjC,YAAY,UAAU;UACX,aAAa,SAAS;;UAIvB,SAAS;UACR,MAAM;;;AAIjB,YAAY,MAAM,UAAU,WAAW,YAAY;UACxC,aAAa,SAAS;UACtB,OAAO;;;AAIlB,YAAY,MAAM;UACP,aAAa,SAAS;UACtB,SAAS,WAAW;UACpB;;;AAIX,YAAY,SAAS,UAAU,WAAW,YAAY;UAC3C,aAAa,SAAS;UACtB,MAAM;;;AAIjB,YAAY,UAAU;UACX,aAAa,SAAS;;AAGjC,YAAY,SAAS;UACV,aAAa,SAAS;;AAGjC,YAAY,WAAW;UACZ,aAAa,SAAS;;AAGjC,YAAY,YAAY;UACb,aAAa,SAAS;;AAGjC,YAAY,cAAc;UACf,aAAa,SAAS;;AAGjC,YAAY,UAAU;UACX,aAAa,SAAS;;;AAIjC,YAAY,OACR,QACA,UACA,SACA,SACA,WACA,YACA,cACA,WACA,MACA,SACA,UACA;;AAGJ,OAAO,cAAMA,QAAQ;;AAErB,OAAO,cAAMC,QAAQ;;AAErB,OAAO,cAAMC,SAAS;;AAEtB,OAAO,cAAMC,SAAS;;AAEtB,OAAO,cAAMC,aAAa;;AAM1B,OAAO,cAAM,QAAS,UAAU,UAAU,MAAM,MAAI,MAAM;;AAU1D,OAAO,cAAM,WAAY,UAAU,UAAU,MAAM,MAAI,SAAS","names":["String: String","Double: Double","Boolean: Boolean","Unknown: Unknown","ResourceRef: ResourceRef"],"sources":["../../src/primitives.ts"],"version":3,"file":"primitives.d.ts"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@palantir/pack.schema",
3
- "version": "0.27.0",
3
+ "version": "0.29.0",
4
4
  "description": "API package for PACK schema functionality",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -27,6 +27,11 @@ export type ReturnedSchema = ModelDefs;
27
27
  /** Soon to be deprecated - use `ModelDefs` instead. */
28
28
  export type Schema<T extends ModelDefs> = T;
29
29
 
30
+ /**
31
+ * The set of builders handed to a {@link SchemaUpdate} callback — one
32
+ * {@link RecordBuilder} or {@link UnionBuilder} per existing model, keyed by
33
+ * model name. Mutate the ones you're changing and return the results.
34
+ */
30
35
  export type SchemaBuilder<T extends ModelDefs> = {
31
36
  [k in keyof T]: T[k] extends UnionDef<infer R> ? UnionBuilder<R>
32
37
  : T[k] extends RecordDef<infer R> ? RecordBuilder<R>
@@ -43,31 +48,47 @@ export type SchemaBuilder<T extends ModelDefs> = {
43
48
  * parameter.
44
49
  */
45
50
  export interface UpgradeFieldOptions<TOld extends Record<string, unknown>> {
51
+ /**
52
+ * The existing fields this new field is derived from. The runtime read lens
53
+ * uses this to know when to back-fill the field for records written by an
54
+ * older version; the app supplies the actual upgrade function at boot.
55
+ */
46
56
  readonly derivedFrom: ReadonlyArray<keyof TOld & string>;
47
57
  }
48
58
 
59
+ /** Options passed as the third argument to {@link RecordBuilder.addField}. */
49
60
  export type FieldOptions = UpgradeFieldOptions<Record<string, unknown>>;
50
61
 
62
+ /** Evolves a record within a {@link SchemaUpdate}. Obtain one from the {@link SchemaBuilder} and finish with `build()`. */
51
63
  export interface RecordBuilder<T extends Record<string, Type>> {
52
64
  // TODO: builders should support arg types and resolveModels to refs
65
+ /**
66
+ * Add a field. Pass `{ derivedFrom }` so the SDK can back-fill it when
67
+ * reading records written before this field existed.
68
+ */
53
69
  addField<const K extends string, V extends Type>(
54
70
  name: K,
55
71
  type: V,
56
72
  options?: FieldOptions,
57
73
  ): RecordBuilder<T & { [k in K]: V }>;
74
+ /** Mark a field deprecated, with an optional message pointing at its replacement. */
58
75
  deprecateField<K extends keyof T & string>(
59
76
  name: K,
60
77
  message?: string,
61
78
  ): RecordBuilder<T>;
79
+ /** Produce the updated {@link RecordDef}. */
62
80
  build(): RecordDef<T>;
63
81
  }
64
82
 
83
+ /** Evolves a union within a {@link SchemaUpdate}. Obtain one from the {@link SchemaBuilder} and finish with `build()`. */
65
84
  export interface UnionBuilder<S extends UnionVariants> {
66
85
  // TODO: builders should support arg types and resolveModels to refs
86
+ /** Add a variant, referencing a record (or a `Ref` to one). */
67
87
  addVariant<const K extends string>(
68
88
  name: K,
69
89
  modelDefOrRef: UnionVariantArg,
70
90
  ): UnionBuilder<S & { [k in K]: Ref }>;
91
+ /** Produce the updated {@link UnionDef}. */
71
92
  build(): UnionDef<S>;
72
93
  }
73
94
 
@@ -312,6 +333,14 @@ export function applyMigration<
312
333
  };
313
334
  }
314
335
 
336
+ /**
337
+ * Lower-level alternative to the {@link nextSchema}/{@link defineSchemaUpdate}
338
+ * chain: apply a migration callback and return only the merged models, dropping
339
+ * the per-field upgrade and deprecation metadata.
340
+ *
341
+ * @deprecated Use the {@link nextSchema}/{@link defineSchemaUpdate} chain to
342
+ * build versioned schemas. This function will be removed in a future version.
343
+ */
315
344
  export function defineMigration<
316
345
  const T extends ModelDefs,
317
346
  const S extends ModelDefs,
@@ -64,6 +64,22 @@ function resolveFieldArg<T extends FieldArg>(value: T): ResolvedFieldArg<T> {
64
64
  return resolved as ResolvedFieldArg<T>;
65
65
  }
66
66
 
67
+ /**
68
+ * Define a **record**: a named set of typed fields, the basic building block of
69
+ * a schema.
70
+ *
71
+ * Each field's type is a primitive ({@link String}, {@link Double}, …), a
72
+ * composite ({@link Optional}, {@link Array}), or a reference to another record
73
+ * or union — passed directly, or as `() => Model` for forward references.
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * const ShapeBox = defineRecord("ShapeBox", {
78
+ * docs: "A box.",
79
+ * fields: { top: Double, left: Double, color: Optional(String) },
80
+ * });
81
+ * ```
82
+ */
67
83
  export function defineRecord<const T extends FieldArgs>(
68
84
  name: string,
69
85
  record: RecordArgs<T>,
@@ -19,6 +19,7 @@ import { applyMigration } from "./defineMigration.js";
19
19
  import type { ModelDefs } from "./defs.js";
20
20
  import { isRecordDef } from "./utils.js";
21
21
 
22
+ /** Version 1 of a schema, produced by {@link defineSchema}. */
22
23
  export interface InitialSchema<T extends ModelDefs = ModelDefs> {
23
24
  readonly type: "initial";
24
25
  readonly version: 1;
@@ -37,6 +38,7 @@ export interface FieldDeprecationInfo {
37
38
  }
38
39
  export type VersionDeprecations = Record<string, Record<string, FieldDeprecationInfo>>;
39
40
 
41
+ /** Version 2 or later of a schema, produced by {@link nextSchema}. Links back to the `previous` version. */
40
42
  export interface VersionedSchema<T extends ModelDefs = ModelDefs> {
41
43
  readonly type: "versioned";
42
44
  readonly models: T;
@@ -46,19 +48,48 @@ export interface VersionedSchema<T extends ModelDefs = ModelDefs> {
46
48
  readonly deprecations?: VersionDeprecations;
47
49
  }
48
50
 
51
+ /** Any version of a schema: the {@link InitialSchema} (v1) or a {@link VersionedSchema} (v2+). */
49
52
  export type SchemaDefinition<T extends ModelDefs = ModelDefs> =
50
53
  | InitialSchema<T>
51
54
  | VersionedSchema<T>;
52
55
 
56
+ /**
57
+ * Define version 1 of a schema from its initial set of models (records and
58
+ * unions). Later versions extend it via {@link nextSchema} and
59
+ * {@link defineSchemaUpdate}.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * const schemaV1 = defineSchema({ ShapeBox, NodeShape });
64
+ * ```
65
+ */
53
66
  export function defineSchema<T extends ModelDefs>(models: T): InitialSchema<T> {
54
67
  return { type: "initial", version: 1, models };
55
68
  }
56
69
 
70
+ /** A named schema change created by {@link defineSchemaUpdate} and applied with {@link SchemaVersionBuilder.addSchemaUpdate}. */
57
71
  export interface SchemaUpdate<T extends ModelDefs, S extends ModelDefs> {
58
72
  readonly name: string;
59
73
  readonly migration: (schema: SchemaBuilder<T>) => S;
60
74
  }
61
75
 
76
+ /**
77
+ * Define a named, reusable schema change. The callback receives a
78
+ * {@link SchemaBuilder} — one builder per existing model — and returns the
79
+ * records and unions it changed or added.
80
+ *
81
+ * @param name - A stable identifier for this change, used to track the migration.
82
+ * @example
83
+ * ```ts
84
+ * const splitColor = defineSchemaUpdate("splitColor", schema => {
85
+ * const ShapeBox = schema.ShapeBox
86
+ * .addField("fillColor", Optional(String), { derivedFrom: ["color"] })
87
+ * .deprecateField("color", "Use fillColor instead.")
88
+ * .build();
89
+ * return { ShapeBox };
90
+ * });
91
+ * ```
92
+ */
62
93
  export function defineSchemaUpdate<T extends ModelDefs, S extends ModelDefs>(
63
94
  name: string,
64
95
  migration: (schema: SchemaBuilder<T>) => S,
@@ -66,11 +97,15 @@ export function defineSchemaUpdate<T extends ModelDefs, S extends ModelDefs>(
66
97
  return { name, migration };
67
98
  }
68
99
 
100
+ /** Accumulates {@link SchemaUpdate}s onto the previous version. Create one with {@link nextSchema} and finish with `build()`. */
69
101
  export interface SchemaVersionBuilder<T extends ModelDefs> {
102
+ /** Apply a named change from {@link defineSchemaUpdate} to this version. */
70
103
  addSchemaUpdate<S extends ModelDefs>(
71
104
  update: SchemaUpdate<T, S>,
72
105
  ): SchemaVersionBuilder<T & S>;
106
+ /** Attach explicit field migrations, supplementing the `derivedFrom` sugar on `addField`. */
73
107
  withMigrations(migrations: VersionMigrations): SchemaVersionBuilder<T>;
108
+ /** Produce the finished {@link VersionedSchema}. */
74
109
  build(): VersionedSchema<T>;
75
110
  }
76
111
 
@@ -215,6 +250,15 @@ class SchemaVersionBuilderImpl<T extends ModelDefs> implements SchemaVersionBuil
215
250
  }
216
251
  }
217
252
 
253
+ /**
254
+ * Start building the next version of a schema. Chain {@link SchemaVersionBuilder.addSchemaUpdate}
255
+ * calls and finish with `build()`; the new version is the previous one's plus one.
256
+ *
257
+ * @example
258
+ * ```ts
259
+ * const schemaV2 = nextSchema(schemaV1).addSchemaUpdate(splitColor).build();
260
+ * ```
261
+ */
218
262
  export function nextSchema<T extends ModelDefs>(
219
263
  previous: SchemaDefinition<T>,
220
264
  ): SchemaVersionBuilder<T> {
@@ -39,6 +39,20 @@ export type UnionArgs<T extends UnionVariantArgs> = {
39
39
  readonly variants: T;
40
40
  };
41
41
 
42
+ /**
43
+ * Define a **union**: a discriminated choice between several record variants. A
44
+ * value of the union is exactly one of its variants, tagged by the
45
+ * `discriminant` field (default `"type"`).
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * const NodeShape = defineUnion("NodeShape", {
50
+ * discriminant: "shapeType",
51
+ * docs: "The shape of a node.",
52
+ * variants: { box: ShapeBox, circle: ShapeCircle },
53
+ * });
54
+ * ```
55
+ */
42
56
  export function defineUnion<const TVariants extends UnionVariantArgs>(
43
57
  name: string,
44
58
  {
package/src/primitives.ts CHANGED
@@ -31,14 +31,17 @@ export const TypeKind = {
31
31
 
32
32
  export type TypeKind = typeof TypeKind[keyof typeof TypeKind];
33
33
 
34
+ /** A UTF-8 string field. */
34
35
  export type String = {
35
36
  readonly type: typeof TypeKind.STRING;
36
37
  };
37
38
 
39
+ /** A double-precision floating point number field. */
38
40
  export type Double = {
39
41
  readonly type: typeof TypeKind.DOUBLE;
40
42
  };
41
43
 
44
+ /** A boolean field. */
42
45
  export type Boolean = {
43
46
  readonly type: typeof TypeKind.BOOLEAN;
44
47
  };
@@ -48,23 +51,26 @@ interface TypeBase {
48
51
  readonly type: TypeKind;
49
52
  }
50
53
 
54
+ /** A list of `T`. Nested arrays are not supported — wrap the inner array in a record. */
51
55
  export type Array<T extends TypeBase = TypeBase> = {
52
56
  readonly type: typeof TypeKind.ARRAY;
53
57
  readonly items: T;
54
58
  };
55
59
 
56
- // A reference to a record or a union type
60
+ /** A reference to another record or union in the same schema. */
57
61
  export type Ref = {
58
62
  readonly type: typeof TypeKind.REF;
59
63
  readonly refType: "record" | "union"; // TODO: do we care?
60
64
  readonly name: string;
61
65
  };
62
66
 
67
+ /** A `T` that may be absent. Nested optionals are not supported. */
63
68
  export type Optional<T extends TypeBase = TypeBase> = {
64
69
  readonly type: typeof TypeKind.OPTIONAL;
65
70
  readonly item: T;
66
71
  };
67
72
 
73
+ /** An opaque, arbitrary JSON value. */
68
74
  export type Unknown = {
69
75
  readonly type: typeof TypeKind.UNKNOWN;
70
76
  };
@@ -89,6 +95,7 @@ export type UserRef = {
89
95
  readonly type: typeof TypeKind.USER_REF;
90
96
  };
91
97
 
98
+ /** Any valid field type: a primitive, a composite (`Array`/`Optional`), or a `Ref`. */
92
99
  export type Type =
93
100
  | Array
94
101
  | Boolean
@@ -103,15 +110,21 @@ export type Type =
103
110
  | Unknown
104
111
  | UserRef;
105
112
 
113
+ /** A UTF-8 string field. */
106
114
  export const String: String = { type: TypeKind.STRING };
115
+ /** A double-precision floating point number field. */
107
116
  export const Double: Double = { type: TypeKind.DOUBLE };
117
+ /** A boolean field. */
108
118
  export const Boolean: Boolean = { type: TypeKind.BOOLEAN };
119
+ /** An opaque, arbitrary JSON value. */
109
120
  export const Unknown: Unknown = { type: TypeKind.UNKNOWN };
121
+ /** A reference to a Foundry resource. */
110
122
  export const ResourceRef: ResourceRef = { type: TypeKind.RESOURCE_REF };
111
123
  function unwrapOneOptional(t: TypeBase): TypeBase {
112
124
  return t.type === TypeKind.OPTIONAL && "item" in t ? (t as { item: TypeBase }).item : t;
113
125
  }
114
126
 
127
+ /** Build an array field whose elements are `item`. */
115
128
  export const Array = <T extends TypeBase>(item: T): Array<T> => {
116
129
  if (unwrapOneOptional(item).type === TypeKind.ARRAY) {
117
130
  throw new Error(
@@ -121,6 +134,7 @@ export const Array = <T extends TypeBase>(item: T): Array<T> => {
121
134
  }
122
135
  return { type: TypeKind.ARRAY, items: item };
123
136
  };
137
+ /** Build an optional field wrapping `item`, marking it as possibly absent. */
124
138
  export const Optional = <T extends TypeBase>(item: T): Optional<T> => {
125
139
  if (item.type === TypeKind.OPTIONAL) {
126
140
  throw new Error("Nested optionals (Optional(Optional(...))) are not supported.");