@fluidframework/tree-agent 2.80.0 → 2.81.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 +95 -0
- package/api-report/tree-agent.alpha.api.md +195 -20
- package/dist/alpha.d.ts +31 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/methodBinding.d.ts +54 -10
- package/dist/methodBinding.d.ts.map +1 -1
- package/dist/methodBinding.js.map +1 -1
- package/dist/propertyBinding.d.ts +52 -2
- package/dist/propertyBinding.d.ts.map +1 -1
- package/dist/propertyBinding.js +28 -3
- package/dist/propertyBinding.js.map +1 -1
- package/dist/renderSchemaTypeScript.d.ts.map +1 -1
- package/dist/renderSchemaTypeScript.js +23 -8
- package/dist/renderSchemaTypeScript.js.map +1 -1
- package/dist/renderTypeFactoryTypeScript.d.ts +13 -0
- package/dist/renderTypeFactoryTypeScript.d.ts.map +1 -0
- package/dist/renderTypeFactoryTypeScript.js +290 -0
- package/dist/renderTypeFactoryTypeScript.js.map +1 -0
- package/dist/subtree.d.ts.map +1 -1
- package/dist/subtree.js +4 -4
- package/dist/subtree.js.map +1 -1
- package/dist/treeAgentTypes.d.ts +430 -0
- package/dist/treeAgentTypes.d.ts.map +1 -0
- package/dist/treeAgentTypes.js +227 -0
- package/dist/treeAgentTypes.js.map +1 -0
- package/dist/utils.d.ts +0 -4
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +2 -9
- package/dist/utils.js.map +1 -1
- package/eslint.config.mts +4 -4
- package/lib/alpha.d.ts +31 -1
- package/lib/index.d.ts +3 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/methodBinding.d.ts +54 -10
- package/lib/methodBinding.d.ts.map +1 -1
- package/lib/methodBinding.js.map +1 -1
- package/lib/propertyBinding.d.ts +52 -2
- package/lib/propertyBinding.d.ts.map +1 -1
- package/lib/propertyBinding.js +28 -3
- package/lib/propertyBinding.js.map +1 -1
- package/lib/renderSchemaTypeScript.d.ts.map +1 -1
- package/lib/renderSchemaTypeScript.js +23 -8
- package/lib/renderSchemaTypeScript.js.map +1 -1
- package/lib/renderTypeFactoryTypeScript.d.ts +13 -0
- package/lib/renderTypeFactoryTypeScript.d.ts.map +1 -0
- package/lib/renderTypeFactoryTypeScript.js +285 -0
- package/lib/renderTypeFactoryTypeScript.js.map +1 -0
- package/lib/subtree.d.ts.map +1 -1
- package/lib/subtree.js +4 -4
- package/lib/subtree.js.map +1 -1
- package/lib/treeAgentTypes.d.ts +430 -0
- package/lib/treeAgentTypes.d.ts.map +1 -0
- package/lib/treeAgentTypes.js +223 -0
- package/lib/treeAgentTypes.js.map +1 -0
- package/lib/utils.d.ts +0 -4
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +2 -8
- package/lib/utils.js.map +1 -1
- package/package.json +12 -12
- package/src/index.ts +36 -0
- package/src/methodBinding.ts +93 -15
- package/src/propertyBinding.ts +66 -9
- package/src/renderSchemaTypeScript.ts +31 -9
- package/src/renderTypeFactoryTypeScript.ts +339 -0
- package/src/subtree.ts +5 -4
- package/src/treeAgentTypes.ts +611 -0
- package/src/utils.ts +2 -9
- package/.eslintrc.cjs +0 -48
package/src/propertyBinding.ts
CHANGED
|
@@ -9,6 +9,8 @@ import type { ZodType, ZodTypeAny, ZodTypeDef, infer as ZodInfer } from "zod";
|
|
|
9
9
|
|
|
10
10
|
import type { BindableSchema, Ctor } from "./methodBinding.js";
|
|
11
11
|
import { instanceOf } from "./renderZodTypeScript.js";
|
|
12
|
+
import type { TypeFactoryType } from "./treeAgentTypes.js";
|
|
13
|
+
import { isTypeFactoryType } from "./treeAgentTypes.js";
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* A symbol used to expose properties to the LLM.
|
|
@@ -73,9 +75,21 @@ export type TypeMatchOrError<Expected, Received> = [Received] extends [Expected]
|
|
|
73
75
|
*/
|
|
74
76
|
export class PropertyDef {
|
|
75
77
|
public constructor(
|
|
78
|
+
/**
|
|
79
|
+
* The name of the property.
|
|
80
|
+
*/
|
|
76
81
|
public readonly name: string,
|
|
82
|
+
/**
|
|
83
|
+
* Optional description of the property.
|
|
84
|
+
*/
|
|
77
85
|
public readonly description: string | undefined,
|
|
78
|
-
|
|
86
|
+
/**
|
|
87
|
+
* The schema defining the property's type (either Zod or TypeFactory).
|
|
88
|
+
*/
|
|
89
|
+
public readonly schema: ZodTypeAny | TypeFactoryType,
|
|
90
|
+
/**
|
|
91
|
+
* Whether the property is readonly.
|
|
92
|
+
*/
|
|
79
93
|
public readonly readOnly: boolean,
|
|
80
94
|
) {}
|
|
81
95
|
}
|
|
@@ -85,6 +99,9 @@ export class PropertyDef {
|
|
|
85
99
|
* @alpha
|
|
86
100
|
*/
|
|
87
101
|
export interface ExposedProperties {
|
|
102
|
+
/**
|
|
103
|
+
* Expose a property with Zod type checking.
|
|
104
|
+
*/
|
|
88
105
|
exposeProperty<
|
|
89
106
|
S extends BindableSchema & Ctor,
|
|
90
107
|
K extends string & ExposableKeys<InstanceType<S>>,
|
|
@@ -96,6 +113,29 @@ export interface ExposedProperties {
|
|
|
96
113
|
TypeMatchOrError<InstanceType<S>[K], ZodInfer<TZ>>,
|
|
97
114
|
): void;
|
|
98
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Expose a property with type factory type and metadata.
|
|
118
|
+
*/
|
|
119
|
+
exposeProperty<
|
|
120
|
+
S extends BindableSchema & Ctor,
|
|
121
|
+
K extends string & ExposableKeys<InstanceType<S>>,
|
|
122
|
+
>(
|
|
123
|
+
schema: S,
|
|
124
|
+
name: K,
|
|
125
|
+
def: { schema: TypeFactoryType; description?: string; readOnly?: boolean },
|
|
126
|
+
): void;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Expose a property with type factory type (simple form).
|
|
130
|
+
*/
|
|
131
|
+
exposeProperty<
|
|
132
|
+
S extends BindableSchema & Ctor,
|
|
133
|
+
K extends string & ExposableKeys<InstanceType<S>>,
|
|
134
|
+
>(schema: S, name: K, tfType: TypeFactoryType): void;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Create a Zod type that references a SharedTree schema class.
|
|
138
|
+
*/
|
|
99
139
|
instanceOf<T extends TreeNodeSchemaClass>(
|
|
100
140
|
schema: T,
|
|
101
141
|
): ZodType<InstanceType<T>, ZodTypeDef, InstanceType<T>>;
|
|
@@ -116,6 +156,9 @@ export interface ExposedProperties {
|
|
|
116
156
|
* @alpha
|
|
117
157
|
*/
|
|
118
158
|
export interface IExposedProperties {
|
|
159
|
+
/**
|
|
160
|
+
* Static method that exposes properties of this schema class to an agent.
|
|
161
|
+
*/
|
|
119
162
|
[exposePropertiesSymbol]?(properties: ExposedProperties): void;
|
|
120
163
|
}
|
|
121
164
|
|
|
@@ -132,18 +175,32 @@ class ExposedPropertiesI implements ExposedProperties {
|
|
|
132
175
|
>(
|
|
133
176
|
schema: S,
|
|
134
177
|
name: K,
|
|
135
|
-
|
|
136
|
-
|
|
178
|
+
defOrType:
|
|
179
|
+
| ({ schema: TZ; description?: string } & ReadOnlyRequirement<InstanceType<S>, K> &
|
|
180
|
+
TypeMatchOrError<InstanceType<S>[K], ZodInfer<TZ>>)
|
|
181
|
+
| TypeFactoryType,
|
|
137
182
|
): void {
|
|
138
183
|
if (schema !== this.schemaClass) {
|
|
139
184
|
throw new Error('Must expose properties on the "this" schema class');
|
|
140
185
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
186
|
+
|
|
187
|
+
// Handle TypeFactoryType (simple case - type passed directly)
|
|
188
|
+
if (isTypeFactoryType(defOrType)) {
|
|
189
|
+
this.properties[name] = new PropertyDef(name, undefined, defOrType, false);
|
|
190
|
+
} else {
|
|
191
|
+
// Handle object with schema property (works for both Zod and TypeFactory)
|
|
192
|
+
const def = defOrType as {
|
|
193
|
+
schema: TZ | TypeFactoryType;
|
|
194
|
+
description?: string;
|
|
195
|
+
readOnly?: boolean;
|
|
196
|
+
};
|
|
197
|
+
this.properties[name] = new PropertyDef(
|
|
198
|
+
name,
|
|
199
|
+
def.description,
|
|
200
|
+
def.schema,
|
|
201
|
+
def.readOnly === true,
|
|
202
|
+
);
|
|
203
|
+
}
|
|
147
204
|
}
|
|
148
205
|
|
|
149
206
|
public instanceOf<T extends TreeNodeSchemaClass>(
|
|
@@ -18,7 +18,13 @@ import { z } from "zod";
|
|
|
18
18
|
import type { BindableSchema, FunctionWrapper } from "./methodBinding.js";
|
|
19
19
|
import { getExposedMethods } from "./methodBinding.js";
|
|
20
20
|
import { getExposedProperties, type PropertyDef } from "./propertyBinding.js";
|
|
21
|
+
import {
|
|
22
|
+
instanceOfsTypeFactory,
|
|
23
|
+
renderTypeFactoryTypeScript,
|
|
24
|
+
} from "./renderTypeFactoryTypeScript.js";
|
|
21
25
|
import { instanceOfs, renderZodTypeScript } from "./renderZodTypeScript.js";
|
|
26
|
+
import type { TypeFactoryOptional, TypeFactoryType } from "./treeAgentTypes.js";
|
|
27
|
+
import { isTypeFactoryType } from "./treeAgentTypes.js";
|
|
22
28
|
import { getFriendlyName, isNamedSchema, llmDefault, unqualifySchema } from "./utils.js";
|
|
23
29
|
|
|
24
30
|
interface BoundMembers {
|
|
@@ -284,7 +290,9 @@ export function renderSchemaTypeScript(
|
|
|
284
290
|
lines.push(`// ${note}`);
|
|
285
291
|
}
|
|
286
292
|
}
|
|
287
|
-
|
|
293
|
+
const methodString = formatMethod(name, method);
|
|
294
|
+
const methodLines = methodString.split("\n");
|
|
295
|
+
lines.push(...methodLines);
|
|
288
296
|
}
|
|
289
297
|
if (lines.length > 0) {
|
|
290
298
|
hasHelperMethods = true;
|
|
@@ -434,7 +442,11 @@ function renderPropertyLines(properties: Record<string, PropertyDef>): string[]
|
|
|
434
442
|
}
|
|
435
443
|
}
|
|
436
444
|
const modifier = property.readOnly ? "readonly " : "";
|
|
437
|
-
|
|
445
|
+
const typeString = renderType(property.schema, 0);
|
|
446
|
+
const propertyLine = `${modifier}${name}: ${typeString};`;
|
|
447
|
+
// Split multi-line type strings and add to lines array
|
|
448
|
+
const propertyLines = propertyLine.split("\n");
|
|
449
|
+
lines.push(...propertyLines);
|
|
438
450
|
}
|
|
439
451
|
return lines;
|
|
440
452
|
}
|
|
@@ -443,13 +455,13 @@ function formatMethod(name: string, method: FunctionWrapper): string {
|
|
|
443
455
|
const args: string[] = [];
|
|
444
456
|
for (const [argName, argType] of method.args) {
|
|
445
457
|
const { innerType, optional } = unwrapOptional(argType);
|
|
446
|
-
const renderedType =
|
|
458
|
+
const renderedType = renderType(innerType, 0);
|
|
447
459
|
args.push(`${argName}${optional ? "?" : ""}: ${renderedType}`);
|
|
448
460
|
}
|
|
449
461
|
if (method.rest !== null) {
|
|
450
|
-
args.push(`...rest: ${
|
|
462
|
+
args.push(`...rest: ${renderType(method.rest, 0)}[]`);
|
|
451
463
|
}
|
|
452
|
-
return `${name}(${args.join(", ")}): ${
|
|
464
|
+
return `${name}(${args.join(", ")}): ${renderType(method.returns, 0)};`;
|
|
453
465
|
}
|
|
454
466
|
|
|
455
467
|
function renderLeaf(leafKind: ValueSchema): string {
|
|
@@ -482,7 +494,15 @@ function formatExpression(
|
|
|
482
494
|
/**
|
|
483
495
|
* Detects optional zod wrappers so argument lists can keep TypeScript optional markers in sync.
|
|
484
496
|
*/
|
|
485
|
-
function unwrapOptional(type: z.ZodTypeAny
|
|
497
|
+
function unwrapOptional(type: z.ZodTypeAny | TypeFactoryType): {
|
|
498
|
+
innerType: z.ZodTypeAny | TypeFactoryType;
|
|
499
|
+
optional: boolean;
|
|
500
|
+
} {
|
|
501
|
+
// Handle type factory optional type
|
|
502
|
+
if (isTypeFactoryType(type) && type._kind === "optional") {
|
|
503
|
+
return { innerType: (type as TypeFactoryOptional).innerType, optional: true };
|
|
504
|
+
}
|
|
505
|
+
// Handle Zod optional type
|
|
486
506
|
if (type instanceof z.ZodOptional) {
|
|
487
507
|
const inner = type.unwrap() as z.ZodTypeAny;
|
|
488
508
|
return { innerType: inner, optional: true };
|
|
@@ -516,8 +536,10 @@ function ensureNoMemberConflicts(
|
|
|
516
536
|
}
|
|
517
537
|
|
|
518
538
|
/**
|
|
519
|
-
*
|
|
539
|
+
* Dispatches to the correct renderer based on whether the type is Zod or type factory.
|
|
520
540
|
*/
|
|
521
|
-
function
|
|
522
|
-
return
|
|
541
|
+
function renderType(type: z.ZodTypeAny | TypeFactoryType, indentLevel: number = 0): string {
|
|
542
|
+
return isTypeFactoryType(type)
|
|
543
|
+
? renderTypeFactoryTypeScript(type, getFriendlyName, instanceOfsTypeFactory, indentLevel)
|
|
544
|
+
: renderZodTypeScript(type, getFriendlyName, instanceOfs);
|
|
523
545
|
}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
7
|
+
import type { ObjectNodeSchema, TreeNodeSchema } from "@fluidframework/tree/alpha";
|
|
8
|
+
|
|
9
|
+
import type {
|
|
10
|
+
TypeFactoryType,
|
|
11
|
+
TypeFactoryArray,
|
|
12
|
+
TypeFactoryPromise,
|
|
13
|
+
TypeFactoryObject,
|
|
14
|
+
TypeFactoryTuple,
|
|
15
|
+
TypeFactoryRecord,
|
|
16
|
+
TypeFactoryMap,
|
|
17
|
+
TypeFactoryLiteral,
|
|
18
|
+
TypeFactoryOptional,
|
|
19
|
+
TypeFactoryReadonly,
|
|
20
|
+
TypeFactoryUnion,
|
|
21
|
+
TypeFactoryIntersection,
|
|
22
|
+
TypeFactoryFunction,
|
|
23
|
+
} from "./treeAgentTypes.js";
|
|
24
|
+
|
|
25
|
+
export { instanceOfsTypeFactory } from "./treeAgentTypes.js";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Converts type factory type definitions into TypeScript declaration text.
|
|
29
|
+
* @alpha
|
|
30
|
+
*/
|
|
31
|
+
export function renderTypeFactoryTypeScript(
|
|
32
|
+
typeFactoryType: TypeFactoryType,
|
|
33
|
+
getFriendlyName: (schema: TreeNodeSchema) => string,
|
|
34
|
+
instanceOfLookup: WeakMap<TypeFactoryType, ObjectNodeSchema>,
|
|
35
|
+
initialIndent: number = 0,
|
|
36
|
+
): string {
|
|
37
|
+
let result = "";
|
|
38
|
+
let startOfLine = false;
|
|
39
|
+
let indent = initialIndent;
|
|
40
|
+
|
|
41
|
+
appendType(typeFactoryType, TypePrecedence.Union);
|
|
42
|
+
return result;
|
|
43
|
+
|
|
44
|
+
function appendType(type: TypeFactoryType, minPrecedence = TypePrecedence.Object): void {
|
|
45
|
+
const shouldParenthesize = getTypePrecedence(type) < minPrecedence;
|
|
46
|
+
if (shouldParenthesize) {
|
|
47
|
+
append("(");
|
|
48
|
+
}
|
|
49
|
+
appendTypeDefinition(type);
|
|
50
|
+
if (shouldParenthesize) {
|
|
51
|
+
append(")");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function append(s: string): void {
|
|
56
|
+
if (startOfLine) {
|
|
57
|
+
result += " ".repeat(indent);
|
|
58
|
+
startOfLine = false;
|
|
59
|
+
}
|
|
60
|
+
result += s;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function appendNewLine(): void {
|
|
64
|
+
append("\n");
|
|
65
|
+
startOfLine = true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function appendTypeDefinition(type: TypeFactoryType): void {
|
|
69
|
+
switch (type._kind) {
|
|
70
|
+
case "string": {
|
|
71
|
+
append("string");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
case "number": {
|
|
75
|
+
append("number");
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
case "boolean": {
|
|
79
|
+
append("boolean");
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
case "date": {
|
|
83
|
+
append("Date");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
case "void": {
|
|
87
|
+
append("void");
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
case "undefined": {
|
|
91
|
+
append("undefined");
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
case "null": {
|
|
95
|
+
append("null");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
case "unknown": {
|
|
99
|
+
append("unknown");
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
case "array": {
|
|
103
|
+
appendArrayType(type as TypeFactoryArray);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
case "promise": {
|
|
107
|
+
appendPromiseType(type as TypeFactoryPromise);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
case "object": {
|
|
111
|
+
appendObjectType(type as TypeFactoryObject);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
case "union": {
|
|
115
|
+
appendUnionTypes((type as TypeFactoryUnion).options, TypePrecedence.Union);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
case "intersection": {
|
|
119
|
+
appendIntersectionTypes(
|
|
120
|
+
(type as TypeFactoryIntersection).types,
|
|
121
|
+
TypePrecedence.Intersection,
|
|
122
|
+
);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
case "tuple": {
|
|
126
|
+
appendTupleType(type as TypeFactoryTuple);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
case "record": {
|
|
130
|
+
appendRecordType(type as TypeFactoryRecord);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
case "map": {
|
|
134
|
+
appendMapType(type as TypeFactoryMap);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
case "literal": {
|
|
138
|
+
appendLiteral((type as TypeFactoryLiteral).value);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
case "optional": {
|
|
142
|
+
appendUnionTypes(
|
|
143
|
+
[(type as TypeFactoryOptional).innerType, { _kind: "undefined" }],
|
|
144
|
+
TypePrecedence.Union,
|
|
145
|
+
);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
case "readonly": {
|
|
149
|
+
appendReadonlyType(type as TypeFactoryReadonly);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
case "function": {
|
|
153
|
+
appendFunctionType(type as TypeFactoryFunction);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
case "instanceof": {
|
|
157
|
+
const schema = instanceOfLookup.get(type);
|
|
158
|
+
if (schema === undefined) {
|
|
159
|
+
throw new UsageError(
|
|
160
|
+
"instanceof type not found in lookup - this typically indicates the type was not created via typeFactory.instanceOf",
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
append(getFriendlyName(schema));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
default: {
|
|
167
|
+
throw new UsageError(
|
|
168
|
+
`Unsupported type when formatting helper types: ${String(type._kind ?? "unknown")}. Expected one of: string, number, boolean, void, undefined, null, unknown, array, object, union, tuple, record, map, literal, optional, readonly, instanceof.`,
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function appendArrayType(arrayType: TypeFactoryArray): void {
|
|
175
|
+
appendType(arrayType.element, TypePrecedence.Object);
|
|
176
|
+
append("[]");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function appendPromiseType(promiseType: TypeFactoryPromise): void {
|
|
180
|
+
append("Promise<");
|
|
181
|
+
appendType(promiseType.innerType, TypePrecedence.Union);
|
|
182
|
+
append(">");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function appendObjectType(objectType: TypeFactoryObject): void {
|
|
186
|
+
append("{");
|
|
187
|
+
appendNewLine();
|
|
188
|
+
indent++;
|
|
189
|
+
for (const [name, propertyType] of Object.entries(objectType.shape)) {
|
|
190
|
+
append(name);
|
|
191
|
+
if (propertyType._kind === "optional") {
|
|
192
|
+
append("?");
|
|
193
|
+
append(": ");
|
|
194
|
+
appendType((propertyType as TypeFactoryOptional).innerType);
|
|
195
|
+
} else {
|
|
196
|
+
append(": ");
|
|
197
|
+
appendType(propertyType);
|
|
198
|
+
}
|
|
199
|
+
append(";");
|
|
200
|
+
appendNewLine();
|
|
201
|
+
}
|
|
202
|
+
indent--;
|
|
203
|
+
append("}");
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function appendUnionTypes(
|
|
207
|
+
types: readonly TypeFactoryType[],
|
|
208
|
+
minPrecedence: TypePrecedence,
|
|
209
|
+
): void {
|
|
210
|
+
let first = true;
|
|
211
|
+
for (const innerType of types) {
|
|
212
|
+
if (!first) {
|
|
213
|
+
append(" | ");
|
|
214
|
+
}
|
|
215
|
+
appendType(innerType, minPrecedence);
|
|
216
|
+
first = false;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function appendIntersectionTypes(
|
|
221
|
+
types: readonly TypeFactoryType[],
|
|
222
|
+
minPrecedence: TypePrecedence,
|
|
223
|
+
): void {
|
|
224
|
+
let first = true;
|
|
225
|
+
for (const innerType of types) {
|
|
226
|
+
if (!first) {
|
|
227
|
+
append(" & ");
|
|
228
|
+
}
|
|
229
|
+
appendType(innerType, minPrecedence);
|
|
230
|
+
first = false;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function appendTupleType(tupleType: TypeFactoryTuple): void {
|
|
235
|
+
append("[");
|
|
236
|
+
let first = true;
|
|
237
|
+
for (const innerType of tupleType.items) {
|
|
238
|
+
if (!first) {
|
|
239
|
+
append(", ");
|
|
240
|
+
}
|
|
241
|
+
if (innerType._kind === "optional") {
|
|
242
|
+
appendType((innerType as TypeFactoryOptional).innerType, TypePrecedence.Object);
|
|
243
|
+
append("?");
|
|
244
|
+
} else {
|
|
245
|
+
appendType(innerType);
|
|
246
|
+
}
|
|
247
|
+
first = false;
|
|
248
|
+
}
|
|
249
|
+
if (tupleType.rest !== undefined) {
|
|
250
|
+
if (!first) {
|
|
251
|
+
append(", ");
|
|
252
|
+
}
|
|
253
|
+
append("...");
|
|
254
|
+
appendType(tupleType.rest, TypePrecedence.Object);
|
|
255
|
+
append("[]");
|
|
256
|
+
}
|
|
257
|
+
append("]");
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function appendRecordType(recordType: TypeFactoryRecord): void {
|
|
261
|
+
append("Record<");
|
|
262
|
+
appendType(recordType.keyType, TypePrecedence.Union);
|
|
263
|
+
append(", ");
|
|
264
|
+
appendType(recordType.valueType, TypePrecedence.Union);
|
|
265
|
+
append(">");
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function appendMapType(mapType: TypeFactoryMap): void {
|
|
269
|
+
append("Map<");
|
|
270
|
+
appendType(mapType.keyType, TypePrecedence.Union);
|
|
271
|
+
append(", ");
|
|
272
|
+
appendType(mapType.valueType, TypePrecedence.Union);
|
|
273
|
+
append(">");
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function appendLiteral(value: string | number | boolean): void {
|
|
277
|
+
append(JSON.stringify(value));
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function appendReadonlyType(readonlyType: TypeFactoryReadonly): void {
|
|
281
|
+
append("Readonly<");
|
|
282
|
+
appendType(readonlyType.innerType);
|
|
283
|
+
append(">");
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function appendFunctionType(functionType: TypeFactoryFunction): void {
|
|
287
|
+
append("(");
|
|
288
|
+
let first = true;
|
|
289
|
+
for (const param of functionType.parameters) {
|
|
290
|
+
if (!first) {
|
|
291
|
+
append(", ");
|
|
292
|
+
}
|
|
293
|
+
const [name, type] = param;
|
|
294
|
+
append(name);
|
|
295
|
+
if (type._kind === "optional") {
|
|
296
|
+
append("?");
|
|
297
|
+
append(": ");
|
|
298
|
+
appendType((type as TypeFactoryOptional).innerType, TypePrecedence.Union);
|
|
299
|
+
} else {
|
|
300
|
+
append(": ");
|
|
301
|
+
appendType(type, TypePrecedence.Union);
|
|
302
|
+
}
|
|
303
|
+
first = false;
|
|
304
|
+
}
|
|
305
|
+
if (functionType.restParameter !== undefined) {
|
|
306
|
+
if (!first) {
|
|
307
|
+
append(", ");
|
|
308
|
+
}
|
|
309
|
+
const [name, type] = functionType.restParameter;
|
|
310
|
+
append("...");
|
|
311
|
+
append(name);
|
|
312
|
+
append(": ");
|
|
313
|
+
appendType(type, TypePrecedence.Object);
|
|
314
|
+
append("[]");
|
|
315
|
+
}
|
|
316
|
+
append(") => ");
|
|
317
|
+
appendType(functionType.returnType, TypePrecedence.Union);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const enum TypePrecedence {
|
|
322
|
+
Union = 0,
|
|
323
|
+
Intersection = 1,
|
|
324
|
+
Object = 2,
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function getTypePrecedence(type: TypeFactoryType): TypePrecedence {
|
|
328
|
+
switch (type._kind) {
|
|
329
|
+
case "union": {
|
|
330
|
+
return TypePrecedence.Union;
|
|
331
|
+
}
|
|
332
|
+
case "intersection": {
|
|
333
|
+
return TypePrecedence.Intersection;
|
|
334
|
+
}
|
|
335
|
+
default: {
|
|
336
|
+
return TypePrecedence.Object;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
package/src/subtree.ts
CHANGED
|
@@ -34,7 +34,7 @@ export class Subtree<TRoot extends ImplicitFieldSchema> {
|
|
|
34
34
|
|
|
35
35
|
public get branch(): TreeBranchAlpha {
|
|
36
36
|
return this.viewOrTree instanceof TreeNode
|
|
37
|
-
? (TreeAlpha.branch(this.viewOrTree) ?? fail(
|
|
37
|
+
? (TreeAlpha.branch(this.viewOrTree) ?? fail(0xcb3 /* Node cannot be raw. */))
|
|
38
38
|
: this.viewOrTree;
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -89,7 +89,7 @@ export class Subtree<TRoot extends ImplicitFieldSchema> {
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
default: {
|
|
92
|
-
fail(
|
|
92
|
+
fail(0xcb4 /* Unexpected node kind */);
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
}
|
|
@@ -108,10 +108,11 @@ export class Subtree<TRoot extends ImplicitFieldSchema> {
|
|
|
108
108
|
|
|
109
109
|
public fork(): Subtree<TRoot> {
|
|
110
110
|
if (this.viewOrTree instanceof TreeNode) {
|
|
111
|
-
const branch =
|
|
111
|
+
const branch =
|
|
112
|
+
TreeAlpha.branch(this.viewOrTree) ?? fail(0xcb5 /* Node cannot be raw. */);
|
|
112
113
|
const node =
|
|
113
114
|
getNodeOnBranch(this.viewOrTree, branch.fork()) ??
|
|
114
|
-
fail(
|
|
115
|
+
fail(0xcb6 /* Expected node to be on new fork. */);
|
|
115
116
|
|
|
116
117
|
return new Subtree<TRoot>(node);
|
|
117
118
|
} else {
|