@palantir/pack.schema 0.0.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-lint.log +4 -0
- package/.turbo/turbo-transpileBrowser.log +5 -0
- package/.turbo/turbo-transpileCjs.log +5 -0
- package/.turbo/turbo-transpileEsm.log +5 -0
- package/.turbo/turbo-transpileTypes.log +5 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/LICENSE.txt +13 -0
- package/README.md +87 -0
- package/build/browser/index.js +176 -0
- package/build/browser/index.js.map +1 -0
- package/build/cjs/index.cjs +192 -0
- package/build/cjs/index.cjs.map +1 -0
- package/build/cjs/index.d.cts +131 -0
- package/build/esm/index.js +176 -0
- package/build/esm/index.js.map +1 -0
- package/build/types/__tests__/defineMigration.test.d.ts +1 -0
- package/build/types/__tests__/defineMigration.test.d.ts.map +1 -0
- package/build/types/__tests__/defineRecord.test.d.ts +1 -0
- package/build/types/__tests__/defineRecord.test.d.ts.map +1 -0
- package/build/types/__tests__/defineUnion.test.d.ts +1 -0
- package/build/types/__tests__/defineUnion.test.d.ts.map +1 -0
- package/build/types/__tests__/integration.test.d.ts +1 -0
- package/build/types/__tests__/integration.test.d.ts.map +1 -0
- package/build/types/__tests__/primitives.test.d.ts +1 -0
- package/build/types/__tests__/primitives.test.d.ts.map +1 -0
- package/build/types/__tests__/testTypeUtils.d.ts +74 -0
- package/build/types/__tests__/testTypeUtils.d.ts.map +1 -0
- package/build/types/defineMigration.d.ts +21 -0
- package/build/types/defineMigration.d.ts.map +1 -0
- package/build/types/defineRecord.d.ts +14 -0
- package/build/types/defineRecord.d.ts.map +1 -0
- package/build/types/defineUnion.d.ts +12 -0
- package/build/types/defineUnion.d.ts.map +1 -0
- package/build/types/defs.d.ts +24 -0
- package/build/types/defs.d.ts.map +1 -0
- package/build/types/index.d.ts +6 -0
- package/build/types/index.d.ts.map +1 -0
- package/build/types/primitives.d.ts +41 -0
- package/build/types/primitives.d.ts.map +1 -0
- package/build/types/utils.d.ts +20 -0
- package/build/types/utils.d.ts.map +1 -0
- package/package.json +55 -0
- package/src/__tests__/defineMigration.test.ts +265 -0
- package/src/__tests__/defineRecord.test.ts +167 -0
- package/src/__tests__/defineUnion.test.ts +231 -0
- package/src/__tests__/integration.test.ts +126 -0
- package/src/__tests__/primitives.test.ts +153 -0
- package/src/__tests__/testTypeUtils.ts +92 -0
- package/src/defineMigration.ts +159 -0
- package/src/defineRecord.ts +83 -0
- package/src/defineUnion.ts +58 -0
- package/src/defs.ts +46 -0
- package/src/index.ts +22 -0
- package/src/primitives.ts +80 -0
- package/src/utils.ts +62 -0
- package/tsconfig.json +21 -0
- package/vitest.config.mjs +26 -0
|
@@ -0,0 +1,159 @@
|
|
|
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
|
+
import type { UnionVariantArg } from "./defineUnion.js";
|
|
18
|
+
import { resolveUnionVariantArg } from "./defineUnion.js";
|
|
19
|
+
import type { RecordDef, RecordFields, UnionDef, UnionVariants } from "./defs.js";
|
|
20
|
+
import { ModelDefType } from "./defs.js";
|
|
21
|
+
import type { Ref, Type } from "./primitives.js";
|
|
22
|
+
import { isRecordDef, isUnionDef } from "./utils.js";
|
|
23
|
+
|
|
24
|
+
export type ReturnedSchema = Record<string, RecordDef | UnionDef>;
|
|
25
|
+
|
|
26
|
+
export type Schema<T extends ReturnedSchema> = T;
|
|
27
|
+
|
|
28
|
+
export type SchemaBuilder<T extends ReturnedSchema> = {
|
|
29
|
+
[k in keyof T]: T[k] extends UnionDef<infer R> ? UnionBuilder<R>
|
|
30
|
+
: T[k] extends RecordDef<infer R> ? RecordBuilder<R>
|
|
31
|
+
: never;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export interface RecordBuilder<T extends Record<string, Type>> {
|
|
35
|
+
// TODO: builders should support arg types and resolveModels to refs
|
|
36
|
+
addField<const K extends string, V extends Type>(
|
|
37
|
+
name: K,
|
|
38
|
+
type: V,
|
|
39
|
+
): RecordBuilder<T & { [k in K]: V }>;
|
|
40
|
+
build(): RecordDef<T>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface UnionBuilder<S extends UnionVariants> {
|
|
44
|
+
// TODO: builders should support arg types and resolveModels to refs
|
|
45
|
+
addVariant<const K extends string>(
|
|
46
|
+
name: K,
|
|
47
|
+
modelDefOrRef: UnionVariantArg,
|
|
48
|
+
): UnionBuilder<S & { [k in K]: Ref }>;
|
|
49
|
+
build(): UnionDef<S>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
class UnionBuilderImpl<S extends UnionVariants> implements UnionBuilder<S> {
|
|
53
|
+
private readonly name: string;
|
|
54
|
+
private readonly docs: string | undefined;
|
|
55
|
+
private readonly variants: S;
|
|
56
|
+
constructor({ name, docs, variants }: UnionDef<S>) {
|
|
57
|
+
this.name = name;
|
|
58
|
+
this.docs = docs;
|
|
59
|
+
this.variants = { ...variants };
|
|
60
|
+
}
|
|
61
|
+
addVariant<const K extends string>(
|
|
62
|
+
variantName: K,
|
|
63
|
+
modelDefOrRef: UnionVariantArg,
|
|
64
|
+
): UnionBuilder<S & Record<K, Ref>> {
|
|
65
|
+
const ref: Ref = resolveUnionVariantArg(modelDefOrRef);
|
|
66
|
+
const newVariants = { ...this.variants, [variantName]: ref };
|
|
67
|
+
|
|
68
|
+
return new UnionBuilderImpl({
|
|
69
|
+
type: ModelDefType.UNION,
|
|
70
|
+
name: this.name,
|
|
71
|
+
variants: newVariants,
|
|
72
|
+
discriminant: "type",
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
build(): UnionDef<S> {
|
|
76
|
+
return {
|
|
77
|
+
type: ModelDefType.UNION,
|
|
78
|
+
variants: this.variants,
|
|
79
|
+
discriminant: "type",
|
|
80
|
+
name: this.name,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
class RecordBuilderImpl<T extends RecordFields> implements RecordBuilder<T> {
|
|
86
|
+
private readonly name: string;
|
|
87
|
+
private readonly fields: T;
|
|
88
|
+
|
|
89
|
+
constructor(initialRecordDef: RecordDef<T>) {
|
|
90
|
+
this.name = initialRecordDef.name;
|
|
91
|
+
this.fields = { ...initialRecordDef.fields };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// TODO: resolve field value from arg instead
|
|
95
|
+
addField<const K extends string, const V extends Type>(
|
|
96
|
+
name: K,
|
|
97
|
+
value: V,
|
|
98
|
+
): RecordBuilder<T & Record<K, V>> {
|
|
99
|
+
return new RecordBuilderImpl({
|
|
100
|
+
type: ModelDefType.RECORD,
|
|
101
|
+
name: this.name,
|
|
102
|
+
fields: { ...this.fields, [name]: value },
|
|
103
|
+
docs: "",
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
build(): RecordDef<T> {
|
|
107
|
+
return {
|
|
108
|
+
type: ModelDefType.RECORD,
|
|
109
|
+
name: this.name,
|
|
110
|
+
fields: this.fields,
|
|
111
|
+
docs: "",
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function defineMigration<
|
|
117
|
+
const T extends ReturnedSchema,
|
|
118
|
+
const S extends ReturnedSchema,
|
|
119
|
+
>(
|
|
120
|
+
previous: Schema<T>,
|
|
121
|
+
migration: (schema: SchemaBuilder<T>) => S,
|
|
122
|
+
): Schema<T & S> {
|
|
123
|
+
/**
|
|
124
|
+
* Create a map of builders for the schema.
|
|
125
|
+
*
|
|
126
|
+
* Note about type assertions:
|
|
127
|
+
* We use a type assertion here (SchemaBuilder<T>) because TypeScript cannot
|
|
128
|
+
* track the relationship between the keys in the original schema and the
|
|
129
|
+
* corresponding builder types. This is a fundamental limitation of TypeScript's
|
|
130
|
+
* type system when dealing with dynamically constructed objects.
|
|
131
|
+
*
|
|
132
|
+
* The assertion is safe because:
|
|
133
|
+
* 1. We're only adding keys that exist in the original schema
|
|
134
|
+
* 2. For each key, we're creating a builder of the correct type
|
|
135
|
+
* 3. The resulting object exactly matches the SchemaBuilder<T> type
|
|
136
|
+
*/
|
|
137
|
+
const builders = {} as SchemaBuilder<T>;
|
|
138
|
+
|
|
139
|
+
for (const key in previous) {
|
|
140
|
+
const v = previous[key];
|
|
141
|
+
|
|
142
|
+
// Use our type guards for safer type narrowing
|
|
143
|
+
if (isRecordDef(v)) {
|
|
144
|
+
// This assertion is necessary because TypeScript can't track the field types
|
|
145
|
+
// through the dynamic property access and object construction
|
|
146
|
+
const recordBuilder = new RecordBuilderImpl(v);
|
|
147
|
+
builders[key] = recordBuilder as unknown as SchemaBuilder<T>[typeof key];
|
|
148
|
+
} else if (isUnionDef(v)) {
|
|
149
|
+
// Similar assertion needed for union builders
|
|
150
|
+
const unionBuilder = new UnionBuilderImpl(v);
|
|
151
|
+
builders[key] = unionBuilder as unknown as SchemaBuilder<T>[typeof key];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
...previous,
|
|
157
|
+
...migration(builders),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
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
|
+
import type { RecordDef, UnionDef } from "./defs.js";
|
|
18
|
+
import { ModelDefType } from "./defs.js";
|
|
19
|
+
import type { Ref, Type } from "./primitives.js";
|
|
20
|
+
import { isRecordDef, isUnionDef, modelToRef } from "./utils.js";
|
|
21
|
+
|
|
22
|
+
export type FieldArgExplicit =
|
|
23
|
+
| Type
|
|
24
|
+
| RecordDef
|
|
25
|
+
| UnionDef;
|
|
26
|
+
|
|
27
|
+
export type FieldArg =
|
|
28
|
+
| FieldArgExplicit
|
|
29
|
+
| (() => FieldArgExplicit);
|
|
30
|
+
|
|
31
|
+
export type FieldArgExplicitOf<T extends FieldArg> = T extends () => infer R ? R
|
|
32
|
+
: T;
|
|
33
|
+
|
|
34
|
+
export type FieldArgs = Record<string, FieldArg>;
|
|
35
|
+
|
|
36
|
+
export type ResolvedFieldArgExplicit<T extends FieldArgExplicit> = T extends RecordDef | UnionDef
|
|
37
|
+
? Ref
|
|
38
|
+
: T;
|
|
39
|
+
|
|
40
|
+
export type ResolvedFieldArg<T extends FieldArg> = ResolvedFieldArgExplicit<FieldArgExplicitOf<T>>;
|
|
41
|
+
|
|
42
|
+
export type ResolvedFields<T extends FieldArgs> = {
|
|
43
|
+
readonly [K in keyof T]: ResolvedFieldArg<T[K]>;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type RecordArgs<T extends FieldArgs> = {
|
|
47
|
+
readonly docs: string;
|
|
48
|
+
readonly fields: T;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Helper function to resolve a field value, handling functions and transforming
|
|
53
|
+
* types as needed.
|
|
54
|
+
*/
|
|
55
|
+
function resolveFieldArg<T extends FieldArg>(value: T): ResolvedFieldArg<T> {
|
|
56
|
+
// Handle function values
|
|
57
|
+
const resolved = typeof value === "function" ? value() : value;
|
|
58
|
+
|
|
59
|
+
if (isRecordDef(resolved) || isUnionDef(resolved)) {
|
|
60
|
+
return modelToRef(resolved) as ResolvedFieldArg<T>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// For primitive types and other Types
|
|
64
|
+
return resolved as ResolvedFieldArg<T>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function defineRecord<const T extends FieldArgs>(
|
|
68
|
+
name: string,
|
|
69
|
+
record: RecordArgs<T>,
|
|
70
|
+
): RecordDef<ResolvedFields<T>> {
|
|
71
|
+
const entries = Object.entries(record.fields).map(
|
|
72
|
+
([key, value]) => [key, resolveFieldArg(value)] as const,
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const fields = Object.fromEntries(entries) as ResolvedFields<T>;
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
type: ModelDefType.RECORD,
|
|
79
|
+
name: name,
|
|
80
|
+
docs: record.docs,
|
|
81
|
+
fields,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
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
|
+
import type { ModelDef, UnionDef } from "./defs.js";
|
|
18
|
+
import { ModelDefType } from "./defs.js";
|
|
19
|
+
import type { Ref } from "./primitives.js";
|
|
20
|
+
import { TypeKind } from "./primitives.js";
|
|
21
|
+
import { modelToRef } from "./utils.js";
|
|
22
|
+
|
|
23
|
+
export type UnionVariantArgExplicit = Ref | ModelDef;
|
|
24
|
+
export type UnionVariantArg = UnionVariantArgExplicit | (() => UnionVariantArgExplicit);
|
|
25
|
+
export type UnionVariantArgs = Record<string, UnionVariantArg>;
|
|
26
|
+
|
|
27
|
+
export type ResolvedUnionVariants<T extends UnionVariantArgs> = {
|
|
28
|
+
readonly [K in keyof T]: Ref;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type UnionArgs<T extends UnionVariantArgs> = {
|
|
32
|
+
readonly docs: string;
|
|
33
|
+
readonly variants: T;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export function defineUnion<const TVariants extends UnionVariantArgs>(
|
|
37
|
+
name: string,
|
|
38
|
+
union: UnionArgs<TVariants>,
|
|
39
|
+
): UnionDef<ResolvedUnionVariants<TVariants>> {
|
|
40
|
+
const entries = Object.entries(union.variants).map(
|
|
41
|
+
([key, value]) => [key, resolveUnionVariantArg(value)] as const,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const variants = Object.fromEntries(entries) as ResolvedUnionVariants<TVariants>;
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
type: ModelDefType.UNION,
|
|
48
|
+
discriminant: "type",
|
|
49
|
+
name: name,
|
|
50
|
+
docs: union.docs,
|
|
51
|
+
variants,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function resolveUnionVariantArg(arg: UnionVariantArg): Ref {
|
|
56
|
+
const resolved = typeof arg === "function" ? arg() : arg;
|
|
57
|
+
return resolved.type === TypeKind.REF ? resolved : modelToRef(resolved);
|
|
58
|
+
}
|
package/src/defs.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
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
|
+
import type { Ref, Type } from "./primitives.js";
|
|
18
|
+
|
|
19
|
+
export const ModelDefType = {
|
|
20
|
+
RECORD: "record",
|
|
21
|
+
UNION: "union",
|
|
22
|
+
} as const;
|
|
23
|
+
|
|
24
|
+
export type ModelDefType = typeof ModelDefType[keyof typeof ModelDefType];
|
|
25
|
+
|
|
26
|
+
interface ModelDefBase {
|
|
27
|
+
readonly type: ModelDefType;
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly docs?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type RecordFields = Record<string, Type>;
|
|
33
|
+
export type UnionVariants = Record<string, Ref>;
|
|
34
|
+
|
|
35
|
+
export interface UnionDef<TVariants extends UnionVariants = UnionVariants> extends ModelDefBase {
|
|
36
|
+
readonly type: typeof ModelDefType.UNION;
|
|
37
|
+
readonly variants: TVariants;
|
|
38
|
+
readonly discriminant: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface RecordDef<TFields extends RecordFields = RecordFields> extends ModelDefBase {
|
|
42
|
+
readonly type: typeof ModelDefType.RECORD;
|
|
43
|
+
readonly fields: TFields;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type ModelDef = RecordDef | UnionDef;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
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 * from "./defineMigration.js";
|
|
18
|
+
export * from "./defineRecord.js";
|
|
19
|
+
export * from "./defineUnion.js";
|
|
20
|
+
export * from "./defs.js";
|
|
21
|
+
export * from "./primitives.js";
|
|
22
|
+
export * from "./utils.js";
|
|
@@ -0,0 +1,80 @@
|
|
|
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 const TypeKind = {
|
|
18
|
+
ARRAY: "array",
|
|
19
|
+
DOUBLE: "double",
|
|
20
|
+
OPTIONAL: "optional",
|
|
21
|
+
REF: "ref",
|
|
22
|
+
STRING: "string",
|
|
23
|
+
UNKNOWN: "unknown",
|
|
24
|
+
} as const;
|
|
25
|
+
|
|
26
|
+
export type TypeKind = typeof TypeKind[keyof typeof TypeKind];
|
|
27
|
+
|
|
28
|
+
export type String = {
|
|
29
|
+
readonly type: typeof TypeKind.STRING;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type Double = {
|
|
33
|
+
readonly type: typeof TypeKind.DOUBLE;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Forward declaration to avoid circular reference
|
|
37
|
+
interface TypeBase {
|
|
38
|
+
readonly type: TypeKind;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type Array<T extends TypeBase = TypeBase> = {
|
|
42
|
+
readonly type: typeof TypeKind.ARRAY;
|
|
43
|
+
readonly items: T;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// A reference to a record or a union type
|
|
47
|
+
export type Ref = {
|
|
48
|
+
readonly type: typeof TypeKind.REF;
|
|
49
|
+
readonly refType: "record" | "union"; // TODO: do we care?
|
|
50
|
+
readonly name: string;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type Optional<T extends TypeBase = TypeBase> = {
|
|
54
|
+
readonly type: typeof TypeKind.OPTIONAL;
|
|
55
|
+
readonly item: T;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export type Unknown = {
|
|
59
|
+
readonly type: typeof TypeKind.UNKNOWN;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export type Type =
|
|
63
|
+
| String
|
|
64
|
+
| Double
|
|
65
|
+
| Array
|
|
66
|
+
| Ref
|
|
67
|
+
| Optional
|
|
68
|
+
| Unknown;
|
|
69
|
+
|
|
70
|
+
export const String: String = { type: TypeKind.STRING };
|
|
71
|
+
export const Double: Double = { type: TypeKind.DOUBLE };
|
|
72
|
+
export const Unknown: Unknown = { type: TypeKind.UNKNOWN };
|
|
73
|
+
export const Array = <T extends TypeBase>(item: T): Array<T> => ({
|
|
74
|
+
type: TypeKind.ARRAY,
|
|
75
|
+
items: item,
|
|
76
|
+
});
|
|
77
|
+
export const Optional = <T extends TypeBase>(item: T): Optional<T> => ({
|
|
78
|
+
type: TypeKind.OPTIONAL,
|
|
79
|
+
item,
|
|
80
|
+
});
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
import type { ModelDef, RecordDef, UnionDef } from "./defs.js";
|
|
18
|
+
import { ModelDefType } from "./defs.js";
|
|
19
|
+
import type { Ref } from "./primitives.js";
|
|
20
|
+
import { TypeKind } from "./primitives.js";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Helper function to safely transform a record definition to a reference.
|
|
24
|
+
* This function helps TypeScript track type transformations better.
|
|
25
|
+
*/
|
|
26
|
+
export function modelToRef(model: ModelDef): Ref {
|
|
27
|
+
return createRef(model.name, model.type);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Helper function to create a reference with proper typing.
|
|
32
|
+
* This avoids type assertions in multiple places.
|
|
33
|
+
*/
|
|
34
|
+
export function createRef(name: string, refType: "record" | "union"): Ref {
|
|
35
|
+
return {
|
|
36
|
+
type: TypeKind.REF,
|
|
37
|
+
name,
|
|
38
|
+
refType,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Type guard to check if a value is a RecordDef
|
|
44
|
+
*/
|
|
45
|
+
export function isRecordDef(value: unknown): value is RecordDef {
|
|
46
|
+
return value != null
|
|
47
|
+
&& typeof value === "object"
|
|
48
|
+
&& "type" in value
|
|
49
|
+
&& value.type === ModelDefType.RECORD
|
|
50
|
+
&& "fields" in value;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Type guard to check if a value is a UnionDef
|
|
55
|
+
*/
|
|
56
|
+
export function isUnionDef(value: unknown): value is UnionDef {
|
|
57
|
+
return value != null
|
|
58
|
+
&& typeof value === "object"
|
|
59
|
+
&& "type" in value
|
|
60
|
+
&& value.type === ModelDefType.UNION
|
|
61
|
+
&& "variants" in value;
|
|
62
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "@palantir/pack.monorepo.tsconfig/base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "./build/esm",
|
|
5
|
+
"rootDir": "./src",
|
|
6
|
+
"declarationDir": "./build/types",
|
|
7
|
+
"tsBuildInfoFile": "./build/tsconfig.tsbuildinfo"
|
|
8
|
+
},
|
|
9
|
+
"include": [
|
|
10
|
+
"src/**/*"
|
|
11
|
+
],
|
|
12
|
+
"exclude": [
|
|
13
|
+
"build",
|
|
14
|
+
"dist",
|
|
15
|
+
"node_modules",
|
|
16
|
+
"test-output",
|
|
17
|
+
"**/__tests__/**/__snapshots__",
|
|
18
|
+
"**/__tests__/**/fixtures"
|
|
19
|
+
],
|
|
20
|
+
"references": []
|
|
21
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { coverageConfigDefaults, defaultExclude, defineProject } from "vitest/config";
|
|
2
|
+
|
|
3
|
+
export default defineProject({
|
|
4
|
+
test: {
|
|
5
|
+
exclude: [...defaultExclude, "**/build/**", "**/test-output/**"],
|
|
6
|
+
coverage: {
|
|
7
|
+
provider: "v8",
|
|
8
|
+
all: true,
|
|
9
|
+
enabled: true,
|
|
10
|
+
pool: "forks",
|
|
11
|
+
include: ["src/**/*.{ts,tsx}"],
|
|
12
|
+
exclude: [
|
|
13
|
+
...coverageConfigDefaults.exclude,
|
|
14
|
+
"**/*.test.{ts,tsx}",
|
|
15
|
+
"**/__tests__",
|
|
16
|
+
"build",
|
|
17
|
+
"coverage",
|
|
18
|
+
"dist",
|
|
19
|
+
"node_modules",
|
|
20
|
+
"src/index.ts",
|
|
21
|
+
"test-output",
|
|
22
|
+
"vitest.config.*",
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
});
|