@fluidframework/tree 2.2.0 → 2.3.0-288113
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/api-report/tree.alpha.api.md +39 -3
- package/api-report/tree.beta.api.md +8 -3
- package/api-report/tree.public.api.md +8 -3
- package/dist/beta.d.ts +1 -0
- package/dist/core/tree/anchorSet.d.ts +4 -6
- package/dist/core/tree/anchorSet.d.ts.map +1 -1
- package/dist/core/tree/anchorSet.js +11 -1
- package/dist/core/tree/anchorSet.js.map +1 -1
- package/dist/events/events.d.ts +7 -1
- package/dist/events/events.d.ts.map +1 -1
- package/dist/events/events.js +5 -2
- package/dist/events/events.js.map +1 -1
- package/dist/feature-libraries/flex-map-tree/mapTreeNode.d.ts +0 -2
- package/dist/feature-libraries/flex-map-tree/mapTreeNode.d.ts.map +1 -1
- package/dist/feature-libraries/flex-map-tree/mapTreeNode.js +0 -12
- package/dist/feature-libraries/flex-map-tree/mapTreeNode.js.map +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts +4 -95
- package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.js +1 -30
- package/dist/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
- package/dist/feature-libraries/flex-tree/index.d.ts +2 -2
- package/dist/feature-libraries/flex-tree/index.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/index.js +1 -3
- package/dist/feature-libraries/flex-tree/index.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.d.ts +0 -1
- package/dist/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.js +0 -3
- package/dist/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyNode.d.ts +3 -10
- package/dist/feature-libraries/flex-tree/lazyNode.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyNode.js +2 -87
- package/dist/feature-libraries/flex-tree/lazyNode.js.map +1 -1
- package/dist/feature-libraries/index.d.ts +1 -1
- package/dist/feature-libraries/index.d.ts.map +1 -1
- package/dist/feature-libraries/index.js +2 -4
- package/dist/feature-libraries/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -31
- package/dist/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/public.d.ts +1 -0
- package/dist/simple-tree/api/treeNodeApi.d.ts +1 -1
- package/dist/simple-tree/api/treeNodeApi.d.ts.map +1 -1
- package/dist/simple-tree/api/treeNodeApi.js +30 -2
- package/dist/simple-tree/api/treeNodeApi.js.map +1 -1
- package/dist/simple-tree/arrayNode.d.ts.map +1 -1
- package/dist/simple-tree/arrayNode.js +5 -19
- package/dist/simple-tree/arrayNode.js.map +1 -1
- package/dist/simple-tree/core/index.d.ts +1 -1
- package/dist/simple-tree/core/index.d.ts.map +1 -1
- package/dist/simple-tree/core/index.js.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.d.ts +18 -5
- package/dist/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.js +57 -21
- package/dist/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/dist/simple-tree/core/types.d.ts +28 -10
- package/dist/simple-tree/core/types.d.ts.map +1 -1
- package/dist/simple-tree/core/types.js.map +1 -1
- package/dist/simple-tree/index.d.ts +1 -1
- package/dist/simple-tree/index.d.ts.map +1 -1
- package/dist/simple-tree/index.js.map +1 -1
- package/lib/beta.d.ts +1 -0
- package/lib/core/tree/anchorSet.d.ts +4 -6
- package/lib/core/tree/anchorSet.d.ts.map +1 -1
- package/lib/core/tree/anchorSet.js +11 -1
- package/lib/core/tree/anchorSet.js.map +1 -1
- package/lib/events/events.d.ts +7 -1
- package/lib/events/events.d.ts.map +1 -1
- package/lib/events/events.js +5 -2
- package/lib/events/events.js.map +1 -1
- package/lib/feature-libraries/flex-map-tree/mapTreeNode.d.ts +0 -2
- package/lib/feature-libraries/flex-map-tree/mapTreeNode.d.ts.map +1 -1
- package/lib/feature-libraries/flex-map-tree/mapTreeNode.js +0 -12
- package/lib/feature-libraries/flex-map-tree/mapTreeNode.js.map +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts +4 -95
- package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.js +0 -29
- package/lib/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
- package/lib/feature-libraries/flex-tree/index.d.ts +2 -2
- package/lib/feature-libraries/flex-tree/index.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/index.js +1 -1
- package/lib/feature-libraries/flex-tree/index.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.d.ts +0 -1
- package/lib/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.js +0 -3
- package/lib/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyNode.d.ts +3 -10
- package/lib/feature-libraries/flex-tree/lazyNode.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyNode.js +3 -86
- package/lib/feature-libraries/flex-tree/lazyNode.js.map +1 -1
- package/lib/feature-libraries/index.d.ts +1 -1
- package/lib/feature-libraries/index.d.ts.map +1 -1
- package/lib/feature-libraries/index.js +1 -1
- package/lib/feature-libraries/index.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -0
- package/lib/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/public.d.ts +1 -0
- package/lib/simple-tree/api/treeNodeApi.d.ts +1 -1
- package/lib/simple-tree/api/treeNodeApi.d.ts.map +1 -1
- package/lib/simple-tree/api/treeNodeApi.js +30 -2
- package/lib/simple-tree/api/treeNodeApi.js.map +1 -1
- package/lib/simple-tree/arrayNode.d.ts.map +1 -1
- package/lib/simple-tree/arrayNode.js +5 -19
- package/lib/simple-tree/arrayNode.js.map +1 -1
- package/lib/simple-tree/core/index.d.ts +1 -1
- package/lib/simple-tree/core/index.d.ts.map +1 -1
- package/lib/simple-tree/core/index.js.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.d.ts +18 -5
- package/lib/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.js +58 -22
- package/lib/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/lib/simple-tree/core/types.d.ts +28 -10
- package/lib/simple-tree/core/types.d.ts.map +1 -1
- package/lib/simple-tree/core/types.js.map +1 -1
- package/lib/simple-tree/index.d.ts +1 -1
- package/lib/simple-tree/index.d.ts.map +1 -1
- package/lib/simple-tree/index.js.map +1 -1
- package/package.json +22 -32
- package/src/core/tree/anchorSet.ts +20 -9
- package/src/events/events.ts +10 -2
- package/src/feature-libraries/flex-map-tree/mapTreeNode.ts +0 -21
- package/src/feature-libraries/flex-tree/flexTreeTypes.ts +3 -170
- package/src/feature-libraries/flex-tree/index.ts +1 -17
- package/src/feature-libraries/flex-tree/lazyField.ts +0 -6
- package/src/feature-libraries/flex-tree/lazyNode.ts +3 -154
- package/src/feature-libraries/index.ts +0 -14
- package/src/index.ts +8 -0
- package/src/packageVersion.ts +1 -1
- package/src/simple-tree/api/treeNodeApi.ts +37 -5
- package/src/simple-tree/arrayNode.ts +3 -12
- package/src/simple-tree/core/index.ts +1 -0
- package/src/simple-tree/core/treeNodeKernel.ts +88 -29
- package/src/simple-tree/core/types.ts +35 -9
- package/src/simple-tree/index.ts +1 -0
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
type TreeValue,
|
|
12
12
|
anchorSlot,
|
|
13
13
|
} from "../../core/index.js";
|
|
14
|
-
import type { Assume
|
|
14
|
+
import type { Assume } from "../../util/index.js";
|
|
15
15
|
import type {
|
|
16
16
|
FieldKinds,
|
|
17
17
|
SequenceFieldEditBuilder,
|
|
@@ -26,7 +26,6 @@ import type {
|
|
|
26
26
|
FlexList,
|
|
27
27
|
FlexListToUnion,
|
|
28
28
|
FlexMapNodeSchema,
|
|
29
|
-
FlexObjectNodeFields,
|
|
30
29
|
FlexObjectNodeSchema,
|
|
31
30
|
FlexTreeNodeSchema,
|
|
32
31
|
LazyItem,
|
|
@@ -309,33 +308,6 @@ export interface FlexTreeMapNode<in out TSchema extends FlexMapNodeSchema>
|
|
|
309
308
|
*/
|
|
310
309
|
entries(): IterableIterator<[FieldKey, FlexTreeUnboxField<TSchema["info"], "notEmpty">]>;
|
|
311
310
|
|
|
312
|
-
/**
|
|
313
|
-
* Executes a provided function once per each key/value pair in the map.
|
|
314
|
-
* @param callbackFn - The function to run for each map entry
|
|
315
|
-
* @param thisArg - If present, `callbackFn` will be bound to `thisArg`
|
|
316
|
-
*
|
|
317
|
-
* @privateRemarks
|
|
318
|
-
* TODO: This should run over fields in insertion order if we want to match the javascript foreach spec.
|
|
319
|
-
*/
|
|
320
|
-
forEach(
|
|
321
|
-
callbackFn: (
|
|
322
|
-
value: FlexTreeUnboxField<TSchema["info"], "notEmpty">,
|
|
323
|
-
key: FieldKey,
|
|
324
|
-
map: FlexTreeMapNode<TSchema>,
|
|
325
|
-
) => void,
|
|
326
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
327
|
-
thisArg?: any,
|
|
328
|
-
): void;
|
|
329
|
-
|
|
330
|
-
/**
|
|
331
|
-
* Iterate through all fields in the map.
|
|
332
|
-
*
|
|
333
|
-
* @remarks
|
|
334
|
-
* No mutations to the current view of the shared tree are permitted during iteration.
|
|
335
|
-
* To iterate over the unboxed values of the map, use `Symbol.Iterator()`.
|
|
336
|
-
*/
|
|
337
|
-
boxedIterator(): IterableIterator<FlexTreeTypedField<TSchema["info"]>>;
|
|
338
|
-
|
|
339
311
|
[Symbol.iterator](): IterableIterator<
|
|
340
312
|
[FieldKey, FlexTreeUnboxField<TSchema["info"], "notEmpty">]
|
|
341
313
|
>;
|
|
@@ -348,7 +320,6 @@ export interface FlexTreeMapNode<in out TSchema extends FlexMapNodeSchema>
|
|
|
348
320
|
*
|
|
349
321
|
* @remarks
|
|
350
322
|
* ObjectNodes require complex typing, and have been split into two parts for implementation purposes.
|
|
351
|
-
* See {@link FlexTreeObjectNodeTyped} for the schema aware extensions to this that provide access to the fields.
|
|
352
323
|
*
|
|
353
324
|
* These "Objects" resemble "Structs" from a wide variety of programming languages
|
|
354
325
|
* (Including Algol 68, C, Go, Rust, C# etc.).
|
|
@@ -380,138 +351,6 @@ export interface FlexTreeLeafNode<in out TSchema extends LeafNodeSchema> extends
|
|
|
380
351
|
readonly value: TreeValue<TSchema["info"]>;
|
|
381
352
|
}
|
|
382
353
|
|
|
383
|
-
/**
|
|
384
|
-
* An {@link FlexTreeObjectNode} with schema aware accessors for its fields.
|
|
385
|
-
*
|
|
386
|
-
* @privateRemarks
|
|
387
|
-
*
|
|
388
|
-
* The corresponding implementation logic for this lives in `LazyTree.ts` under `buildStructClass`.
|
|
389
|
-
* If you change the signature here, you will need to update that logic to match.
|
|
390
|
-
*/
|
|
391
|
-
export type FlexTreeObjectNodeTyped<TSchema extends FlexObjectNodeSchema> =
|
|
392
|
-
FlexObjectNodeSchema extends TSchema
|
|
393
|
-
? FlexTreeObjectNode
|
|
394
|
-
: FlexTreeObjectNode & FlexTreeObjectNodeFields<TSchema["info"]>;
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* Properties to access an object node's fields. See {@link FlexTreeObjectNodeTyped}.
|
|
398
|
-
*
|
|
399
|
-
* @privateRemarks
|
|
400
|
-
* TODO: Support custom field keys.
|
|
401
|
-
*/
|
|
402
|
-
export type FlexTreeObjectNodeFields<TFields extends FlexObjectNodeFields> =
|
|
403
|
-
FlexTreeObjectNodeFieldsInner<
|
|
404
|
-
FlattenKeys<
|
|
405
|
-
{
|
|
406
|
-
// When the key does not need to be escaped, map it from the input TFields in a way that doesn't break navigate to declaration
|
|
407
|
-
[key in keyof TFields as key extends PropertyNameFromFieldKey<key & string>
|
|
408
|
-
? key
|
|
409
|
-
: never]: TFields[key];
|
|
410
|
-
} & {
|
|
411
|
-
[key in keyof TFields as key extends PropertyNameFromFieldKey<key & string>
|
|
412
|
-
? never
|
|
413
|
-
: PropertyNameFromFieldKey<key & string>]: TFields[key];
|
|
414
|
-
}
|
|
415
|
-
>
|
|
416
|
-
>;
|
|
417
|
-
|
|
418
|
-
/**
|
|
419
|
-
* Properties to access an object node's fields. See {@link FlexTreeObjectNodeTyped}.
|
|
420
|
-
*
|
|
421
|
-
* @privateRemarks
|
|
422
|
-
* TODO: Do we keep assignment operator + "setFoo" methods, or just use methods?
|
|
423
|
-
* Inconsistency in the API experience could confusing for consumers.
|
|
424
|
-
*/
|
|
425
|
-
export type FlexTreeObjectNodeFieldsInner<TFields extends FlexObjectNodeFields> = FlattenKeys<
|
|
426
|
-
{
|
|
427
|
-
// boxed fields (TODO: maybe remove these when same as non-boxed version?)
|
|
428
|
-
readonly [key in keyof TFields as `boxed${Capitalize<key & string>}`]: FlexTreeTypedField<
|
|
429
|
-
TFields[key]
|
|
430
|
-
>;
|
|
431
|
-
} & {
|
|
432
|
-
// Add getter only (make property readonly) when the field is **not** of a kind that has a logical set operation.
|
|
433
|
-
// If we could map to getters and setters separately, we would preferably do that, but we can't.
|
|
434
|
-
// See https://github.com/microsoft/TypeScript/issues/43826 for more details on this limitation.
|
|
435
|
-
readonly [key in keyof TFields as TFields[key]["kind"] extends AssignableFieldKinds
|
|
436
|
-
? never
|
|
437
|
-
: key]: FlexTreeUnboxField<TFields[key]>;
|
|
438
|
-
} & {
|
|
439
|
-
// Add setter (make property writable) when the field is of a kind that has a logical set operation.
|
|
440
|
-
// If we could map to getters and setters separately, we would preferably do that, but we can't.
|
|
441
|
-
// See https://github.com/microsoft/TypeScript/issues/43826 for more details on this limitation.
|
|
442
|
-
-readonly [key in keyof TFields as TFields[key]["kind"] extends AssignableFieldKinds
|
|
443
|
-
? key
|
|
444
|
-
: never]: FlexTreeUnboxField<TFields[key]>;
|
|
445
|
-
} & {
|
|
446
|
-
// Setter method (when the field is of a kind that has a logical set operation).
|
|
447
|
-
readonly [key in keyof TFields as TFields[key]["kind"] extends AssignableFieldKinds
|
|
448
|
-
? `set${Capitalize<key & string>}`
|
|
449
|
-
: never]: (content: FlexibleNodeContent) => void;
|
|
450
|
-
}
|
|
451
|
-
>;
|
|
452
|
-
|
|
453
|
-
/**
|
|
454
|
-
* Reserved object node field property names to avoid collisions with the rest of the object node API.
|
|
455
|
-
*/
|
|
456
|
-
export const reservedObjectNodeFieldPropertyNames = [
|
|
457
|
-
"anchorNode",
|
|
458
|
-
"constructor",
|
|
459
|
-
"context",
|
|
460
|
-
"is",
|
|
461
|
-
"parentField",
|
|
462
|
-
"schema",
|
|
463
|
-
"tryGetField",
|
|
464
|
-
"type",
|
|
465
|
-
"value",
|
|
466
|
-
"boxedIterator",
|
|
467
|
-
"iterator",
|
|
468
|
-
"getBoxed",
|
|
469
|
-
] as const;
|
|
470
|
-
|
|
471
|
-
/**
|
|
472
|
-
* Reserved object node field property names prefixes.
|
|
473
|
-
* These are reserved to avoid collisions with properties derived from field other field names.
|
|
474
|
-
*
|
|
475
|
-
* Field names starting with these must be followed by a lowercase letter, or be escaped.
|
|
476
|
-
*/
|
|
477
|
-
export const reservedObjectNodeFieldPropertyNamePrefixes = [
|
|
478
|
-
"set",
|
|
479
|
-
"boxed",
|
|
480
|
-
"field",
|
|
481
|
-
"Field",
|
|
482
|
-
] as const;
|
|
483
|
-
|
|
484
|
-
/**
|
|
485
|
-
* {@link reservedObjectNodeFieldPropertyNamePrefixes} as a type union.
|
|
486
|
-
*/
|
|
487
|
-
export type ReservedObjectNodeFieldPropertyNames =
|
|
488
|
-
(typeof reservedObjectNodeFieldPropertyNames)[number];
|
|
489
|
-
|
|
490
|
-
/**
|
|
491
|
-
* {@link reservedObjectNodeFieldPropertyNamePrefixes} as a type union.
|
|
492
|
-
*/
|
|
493
|
-
export type ReservedObjectNodeFieldPropertyNamePrefixes =
|
|
494
|
-
(typeof reservedObjectNodeFieldPropertyNamePrefixes)[number];
|
|
495
|
-
|
|
496
|
-
/**
|
|
497
|
-
* Convert an object node's field key into an escaped string usable as a property name.
|
|
498
|
-
*
|
|
499
|
-
* @privateRemarks
|
|
500
|
-
* TODO:
|
|
501
|
-
* Collisions are still possible.
|
|
502
|
-
* For example fields named "foo" and "Foo" would both produce a setter "setFoo".
|
|
503
|
-
* Consider naming schemes to avoid this, ensure that there is a good workaround for these cases.
|
|
504
|
-
* Another approach would be to support custom field names (separate from keys),
|
|
505
|
-
* and do the escaping (if needed) when creating the flex tree schema (both when manually creating them and when doing so automatically):
|
|
506
|
-
* this would enable better intellisense for escaped fields, as well as allow the feature of custom field property names.
|
|
507
|
-
*/
|
|
508
|
-
export type PropertyNameFromFieldKey<T extends string> =
|
|
509
|
-
T extends ReservedObjectNodeFieldPropertyNames
|
|
510
|
-
? `field${Capitalize<T>}`
|
|
511
|
-
: T extends `${ReservedObjectNodeFieldPropertyNamePrefixes}${Capitalize<string>}`
|
|
512
|
-
? `field${Capitalize<T>}`
|
|
513
|
-
: T;
|
|
514
|
-
|
|
515
354
|
/**
|
|
516
355
|
* Field kinds that allow value assignment.
|
|
517
356
|
*/
|
|
@@ -588,12 +427,6 @@ export interface FlexTreeSequenceField<in out TTypes extends FlexAllowedTypes>
|
|
|
588
427
|
*/
|
|
589
428
|
map<U>(callbackfn: (value: FlexTreeUnboxNodeUnion<TTypes>, index: number) => U): U[];
|
|
590
429
|
|
|
591
|
-
/**
|
|
592
|
-
* Calls the provided callback function on each child of this sequence, and returns an array that contains the results.
|
|
593
|
-
* @param callbackfn - A function that accepts the child and its index.
|
|
594
|
-
*/
|
|
595
|
-
mapBoxed<U>(callbackfn: (value: FlexTreeTypedNodeUnion<TTypes>, index: number) => U): U[];
|
|
596
|
-
|
|
597
430
|
readonly length: number;
|
|
598
431
|
|
|
599
432
|
/**
|
|
@@ -687,7 +520,7 @@ export type FlexTreeTypedNode<TSchema extends FlexTreeNodeSchema> =
|
|
|
687
520
|
: TSchema extends FlexMapNodeSchema
|
|
688
521
|
? FlexTreeMapNode<TSchema>
|
|
689
522
|
: TSchema extends FlexObjectNodeSchema
|
|
690
|
-
?
|
|
523
|
+
? FlexTreeObjectNode
|
|
691
524
|
: FlexTreeNode;
|
|
692
525
|
|
|
693
526
|
// #endregion
|
|
@@ -764,7 +597,7 @@ export type FlexTreeUnboxNode<TSchema extends FlexTreeNodeSchema> =
|
|
|
764
597
|
: TSchema extends FlexMapNodeSchema
|
|
765
598
|
? FlexTreeMapNode<TSchema>
|
|
766
599
|
: TSchema extends FlexObjectNodeSchema
|
|
767
|
-
?
|
|
600
|
+
? FlexTreeObjectNode
|
|
768
601
|
: FlexTreeUnknownUnboxed;
|
|
769
602
|
|
|
770
603
|
/**
|
|
@@ -16,7 +16,6 @@ export {
|
|
|
16
16
|
type FlexTreeRequiredField,
|
|
17
17
|
type FlexTreeSequenceField,
|
|
18
18
|
type FlexTreeObjectNode,
|
|
19
|
-
type FlexTreeObjectNodeTyped,
|
|
20
19
|
type AssignableFieldKinds,
|
|
21
20
|
type FlexTreeTypedNode,
|
|
22
21
|
type FlexTreeTypedNodeUnion,
|
|
@@ -27,12 +26,6 @@ export {
|
|
|
27
26
|
flexTreeMarker,
|
|
28
27
|
FlexTreeEntityKind,
|
|
29
28
|
isFlexTreeNode,
|
|
30
|
-
type PropertyNameFromFieldKey,
|
|
31
|
-
type ReservedObjectNodeFieldPropertyNames,
|
|
32
|
-
type ReservedObjectNodeFieldPropertyNamePrefixes,
|
|
33
|
-
reservedObjectNodeFieldPropertyNames,
|
|
34
|
-
reservedObjectNodeFieldPropertyNamePrefixes,
|
|
35
|
-
type FlexTreeObjectNodeFieldsInner,
|
|
36
29
|
flexTreeSlot,
|
|
37
30
|
} from "./flexTreeTypes.js";
|
|
38
31
|
|
|
@@ -48,16 +41,7 @@ export { getTreeContext, type FlexTreeContext, Context, ContextSlot } from "./co
|
|
|
48
41
|
|
|
49
42
|
export { type FlexTreeNodeEvents } from "./treeEvents.js";
|
|
50
43
|
|
|
51
|
-
|
|
52
|
-
export type {
|
|
53
|
-
FlexTreeTypedFieldInner,
|
|
54
|
-
FlexTreeUnboxFieldInner,
|
|
55
|
-
FlexTreeObjectNodeFields,
|
|
56
|
-
FlexTreeUnboxNode,
|
|
57
|
-
FlexTreeUnboxNodeUnion,
|
|
58
|
-
IsArrayOfOne,
|
|
59
|
-
FlexibleNodeSubSequence,
|
|
60
|
-
} from "./flexTreeTypes.js";
|
|
44
|
+
export type { FlexTreeUnboxNodeUnion } from "./flexTreeTypes.js";
|
|
61
45
|
|
|
62
46
|
export {
|
|
63
47
|
assertFlexTreeEntityNotFreed,
|
|
@@ -225,12 +225,6 @@ export abstract class LazyField<
|
|
|
225
225
|
return Array.from(this, callbackfn);
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
-
public mapBoxed<U>(
|
|
229
|
-
callbackfn: (value: FlexTreeTypedNodeUnion<TTypes>, index: number) => U,
|
|
230
|
-
): U[] {
|
|
231
|
-
return Array.from(this.boxedIterator(), callbackfn);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
228
|
public boxedIterator(): IterableIterator<FlexTreeTypedNodeUnion<TTypes>> {
|
|
235
229
|
return iterateCursorField(
|
|
236
230
|
this[cursorSymbol],
|
|
@@ -19,14 +19,12 @@ import {
|
|
|
19
19
|
mapCursorFields,
|
|
20
20
|
rootFieldKey,
|
|
21
21
|
} from "../../core/index.js";
|
|
22
|
-
import { brand,
|
|
22
|
+
import { brand, disposeSymbol, fail } from "../../util/index.js";
|
|
23
23
|
import { FieldKinds } from "../default-schema/index.js";
|
|
24
24
|
import {
|
|
25
25
|
Any,
|
|
26
|
-
type FlexAllowedTypes,
|
|
27
26
|
FlexFieldSchema,
|
|
28
27
|
type FlexMapNodeSchema,
|
|
29
|
-
type FlexObjectNodeSchema,
|
|
30
28
|
type FlexTreeNodeSchema,
|
|
31
29
|
type LeafNodeSchema,
|
|
32
30
|
schemaIsLeaf,
|
|
@@ -41,18 +39,11 @@ import {
|
|
|
41
39
|
type FlexTreeLeafNode,
|
|
42
40
|
type FlexTreeMapNode,
|
|
43
41
|
type FlexTreeNode,
|
|
44
|
-
type FlexTreeObjectNodeTyped,
|
|
45
|
-
type FlexTreeOptionalField,
|
|
46
|
-
type FlexTreeRequiredField,
|
|
47
42
|
type FlexTreeTypedField,
|
|
48
43
|
type FlexTreeTypedNode,
|
|
49
44
|
type FlexTreeUnboxField,
|
|
50
|
-
type FlexibleNodeContent,
|
|
51
|
-
type PropertyNameFromFieldKey,
|
|
52
45
|
flexTreeMarker,
|
|
53
46
|
flexTreeSlot,
|
|
54
|
-
reservedObjectNodeFieldPropertyNamePrefixes,
|
|
55
|
-
reservedObjectNodeFieldPropertyNames,
|
|
56
47
|
} from "./flexTreeTypes.js";
|
|
57
48
|
import {
|
|
58
49
|
LazyEntity,
|
|
@@ -103,7 +94,7 @@ function buildSubclass(
|
|
|
103
94
|
return new LazyLeaf(context, schema, cursor, anchorNode, anchor);
|
|
104
95
|
}
|
|
105
96
|
if (schemaIsObjectNode(schema)) {
|
|
106
|
-
return
|
|
97
|
+
return new LazyTreeNode(context, schema, cursor, anchorNode, anchor);
|
|
107
98
|
}
|
|
108
99
|
// TODO: there should be a common fallback that works for cases without a specialized implementation.
|
|
109
100
|
fail("unrecognized node kind");
|
|
@@ -112,7 +103,7 @@ function buildSubclass(
|
|
|
112
103
|
/**
|
|
113
104
|
* Lazy implementation of {@link FlexTreeNode}.
|
|
114
105
|
*/
|
|
115
|
-
export
|
|
106
|
+
export class LazyTreeNode<TSchema extends FlexTreeNodeSchema = FlexTreeNodeSchema>
|
|
116
107
|
extends LazyEntity<TSchema, Anchor>
|
|
117
108
|
implements FlexTreeNode
|
|
118
109
|
{
|
|
@@ -307,10 +298,6 @@ export class LazyMap<TSchema extends FlexMapNodeSchema>
|
|
|
307
298
|
return super.getBoxed(brand(key)) as FlexTreeTypedField<TSchema["info"]>;
|
|
308
299
|
}
|
|
309
300
|
|
|
310
|
-
public override boxedIterator(): IterableIterator<FlexTreeTypedField<TSchema["info"]>> {
|
|
311
|
-
return super.boxedIterator() as IterableIterator<FlexTreeTypedField<TSchema["info"]>>;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
301
|
public [Symbol.iterator](): IterableIterator<
|
|
315
302
|
[FieldKey, FlexTreeUnboxField<TSchema["info"], "notEmpty">]
|
|
316
303
|
> {
|
|
@@ -337,54 +324,6 @@ export class LazyLeaf<TSchema extends LeafNodeSchema>
|
|
|
337
324
|
}
|
|
338
325
|
}
|
|
339
326
|
|
|
340
|
-
/**
|
|
341
|
-
* {@link reservedObjectNodeFieldPropertyNames} but as a set.
|
|
342
|
-
*/
|
|
343
|
-
export const reservedObjectNodeFieldPropertyNameSet: ReadonlySet<string> = new Set(
|
|
344
|
-
reservedObjectNodeFieldPropertyNames,
|
|
345
|
-
);
|
|
346
|
-
|
|
347
|
-
export function propertyNameFromFieldKey<T extends string>(
|
|
348
|
-
key: T,
|
|
349
|
-
): PropertyNameFromFieldKey<T> {
|
|
350
|
-
if (reservedObjectNodeFieldPropertyNameSet.has(key)) {
|
|
351
|
-
return `field${capitalize(key)}` as PropertyNameFromFieldKey<T>;
|
|
352
|
-
}
|
|
353
|
-
for (const prefix of reservedObjectNodeFieldPropertyNamePrefixes) {
|
|
354
|
-
if (key.startsWith(prefix)) {
|
|
355
|
-
const afterPrefix = key.slice(prefix.length);
|
|
356
|
-
if (afterPrefix === capitalize(afterPrefix)) {
|
|
357
|
-
return `field${capitalize(key)}` as PropertyNameFromFieldKey<T>;
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
return key as PropertyNameFromFieldKey<T>;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
export function buildLazyObjectNode<TSchema extends FlexObjectNodeSchema>(
|
|
365
|
-
context: Context,
|
|
366
|
-
schema: TSchema,
|
|
367
|
-
cursor: ITreeSubscriptionCursor,
|
|
368
|
-
anchorNode: AnchorNode,
|
|
369
|
-
anchor: Anchor,
|
|
370
|
-
): LazyTreeNode<TSchema> & FlexTreeObjectNodeTyped<TSchema> {
|
|
371
|
-
const objectNodeClass = getOrCreate(cachedStructClasses, schema, () =>
|
|
372
|
-
buildStructClass(schema),
|
|
373
|
-
);
|
|
374
|
-
return new objectNodeClass(context, cursor, anchorNode, anchor) as LazyTreeNode<TSchema> &
|
|
375
|
-
FlexTreeObjectNodeTyped<TSchema>;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
const cachedStructClasses = new WeakMap<
|
|
379
|
-
FlexObjectNodeSchema,
|
|
380
|
-
new (
|
|
381
|
-
context: Context,
|
|
382
|
-
cursor: ITreeSubscriptionCursor,
|
|
383
|
-
anchorNode: AnchorNode,
|
|
384
|
-
anchor: Anchor,
|
|
385
|
-
) => LazyTreeNode<FlexObjectNodeSchema>
|
|
386
|
-
>();
|
|
387
|
-
|
|
388
327
|
function getBoxedField(
|
|
389
328
|
objectNode: LazyTreeNode,
|
|
390
329
|
key: FieldKey,
|
|
@@ -394,93 +333,3 @@ function getBoxedField(
|
|
|
394
333
|
return makeField(objectNode.context, fieldSchema, cursor);
|
|
395
334
|
});
|
|
396
335
|
}
|
|
397
|
-
|
|
398
|
-
function buildStructClass<TSchema extends FlexObjectNodeSchema>(
|
|
399
|
-
schema: TSchema,
|
|
400
|
-
): new (
|
|
401
|
-
context: Context,
|
|
402
|
-
cursor: ITreeSubscriptionCursor,
|
|
403
|
-
anchorNode: AnchorNode,
|
|
404
|
-
anchor: Anchor,
|
|
405
|
-
) => LazyTreeNode<TSchema> {
|
|
406
|
-
const propertyDescriptorMap: PropertyDescriptorMap = {};
|
|
407
|
-
|
|
408
|
-
for (const [key, fieldSchema] of schema.objectNodeFields) {
|
|
409
|
-
const escapedKey = propertyNameFromFieldKey(key);
|
|
410
|
-
let setter: ((newContent: FlexibleNodeContent) => void) | undefined;
|
|
411
|
-
switch (fieldSchema.kind) {
|
|
412
|
-
case FieldKinds.optional: {
|
|
413
|
-
setter = function (
|
|
414
|
-
this: CustomStruct,
|
|
415
|
-
newContent: FlexibleNodeContent | undefined,
|
|
416
|
-
): void {
|
|
417
|
-
const field = getBoxedField(
|
|
418
|
-
this,
|
|
419
|
-
key,
|
|
420
|
-
fieldSchema,
|
|
421
|
-
) as FlexTreeOptionalField<FlexAllowedTypes>;
|
|
422
|
-
field.editor.set(newContent, field.length === 0);
|
|
423
|
-
};
|
|
424
|
-
break;
|
|
425
|
-
}
|
|
426
|
-
case FieldKinds.required: {
|
|
427
|
-
setter = function (this: CustomStruct, newContent: FlexibleNodeContent): void {
|
|
428
|
-
const field = getBoxedField(
|
|
429
|
-
this,
|
|
430
|
-
key,
|
|
431
|
-
fieldSchema,
|
|
432
|
-
) as FlexTreeRequiredField<FlexAllowedTypes>;
|
|
433
|
-
field.editor.set(newContent);
|
|
434
|
-
};
|
|
435
|
-
break;
|
|
436
|
-
}
|
|
437
|
-
default:
|
|
438
|
-
setter = undefined;
|
|
439
|
-
break;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// Create getter and setter (when appropriate) for property
|
|
443
|
-
propertyDescriptorMap[escapedKey] = {
|
|
444
|
-
enumerable: true,
|
|
445
|
-
get(this: CustomStruct): unknown {
|
|
446
|
-
return inCursorField(this[cursorSymbol], key, (cursor) =>
|
|
447
|
-
unboxedField(this.context, fieldSchema, cursor),
|
|
448
|
-
);
|
|
449
|
-
},
|
|
450
|
-
set: setter,
|
|
451
|
-
};
|
|
452
|
-
|
|
453
|
-
// Create set method for property (when appropriate)
|
|
454
|
-
if (setter !== undefined) {
|
|
455
|
-
propertyDescriptorMap[`set${capitalize(escapedKey)}`] = {
|
|
456
|
-
enumerable: false,
|
|
457
|
-
get(this: CustomStruct) {
|
|
458
|
-
return setter;
|
|
459
|
-
},
|
|
460
|
-
};
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
propertyDescriptorMap[`boxed${capitalize(escapedKey)}`] = {
|
|
464
|
-
enumerable: false,
|
|
465
|
-
get(this: CustomStruct) {
|
|
466
|
-
return getBoxedField(this, key, fieldSchema);
|
|
467
|
-
},
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// This must implement `StructTyped<TSchema>`, but TypeScript can't constrain it to do so.
|
|
472
|
-
class CustomStruct extends LazyTreeNode<TSchema> {
|
|
473
|
-
public constructor(
|
|
474
|
-
context: Context,
|
|
475
|
-
cursor: ITreeSubscriptionCursor,
|
|
476
|
-
anchorNode: AnchorNode,
|
|
477
|
-
anchor: Anchor,
|
|
478
|
-
) {
|
|
479
|
-
super(context, schema, cursor, anchorNode, anchor);
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
Object.defineProperties(CustomStruct.prototype, propertyDescriptorMap);
|
|
484
|
-
|
|
485
|
-
return CustomStruct;
|
|
486
|
-
}
|
|
@@ -224,7 +224,6 @@ export {
|
|
|
224
224
|
type FlexTreeSequenceField,
|
|
225
225
|
Skip,
|
|
226
226
|
type FlexTreeObjectNode,
|
|
227
|
-
type FlexTreeObjectNodeTyped,
|
|
228
227
|
type FlexTreeContext,
|
|
229
228
|
type FlexTreeTypedField,
|
|
230
229
|
type FlexTreeTypedNode,
|
|
@@ -241,22 +240,9 @@ export {
|
|
|
241
240
|
isFlexTreeNode,
|
|
242
241
|
ContextSlot,
|
|
243
242
|
// Internal
|
|
244
|
-
type FlexTreeTypedFieldInner,
|
|
245
|
-
type FlexTreeUnboxFieldInner,
|
|
246
|
-
type FlexTreeObjectNodeFields,
|
|
247
243
|
type FlexTreeUnboxField,
|
|
248
|
-
type FlexTreeUnboxNode,
|
|
249
|
-
type FlexTreeUnboxNodeUnion,
|
|
250
|
-
type IsArrayOfOne,
|
|
251
|
-
type FlexibleNodeSubSequence,
|
|
252
244
|
flexTreeMarker,
|
|
253
245
|
FlexTreeEntityKind,
|
|
254
|
-
type PropertyNameFromFieldKey,
|
|
255
|
-
type ReservedObjectNodeFieldPropertyNames,
|
|
256
|
-
type ReservedObjectNodeFieldPropertyNamePrefixes,
|
|
257
|
-
reservedObjectNodeFieldPropertyNames,
|
|
258
|
-
reservedObjectNodeFieldPropertyNamePrefixes,
|
|
259
|
-
type FlexTreeObjectNodeFieldsInner,
|
|
260
246
|
assertFlexTreeEntityNotFreed,
|
|
261
247
|
flexTreeSlot,
|
|
262
248
|
getSchemaAndPolicy,
|
package/src/index.ts
CHANGED
|
@@ -36,6 +36,13 @@ export {
|
|
|
36
36
|
type IsListener,
|
|
37
37
|
type Listenable,
|
|
38
38
|
type Off,
|
|
39
|
+
// Alpha APIs for using event library to implement events externally.
|
|
40
|
+
// If stabilizing these APIs, they should probably move out of the tree package first.
|
|
41
|
+
createEmitter,
|
|
42
|
+
EventEmitter,
|
|
43
|
+
type IEmitter,
|
|
44
|
+
type HasListeners,
|
|
45
|
+
type NoListenersCallback,
|
|
39
46
|
} from "./events/index.js";
|
|
40
47
|
|
|
41
48
|
export {
|
|
@@ -93,6 +100,7 @@ export {
|
|
|
93
100
|
type FieldProps,
|
|
94
101
|
type InternalTreeNode,
|
|
95
102
|
type WithType,
|
|
103
|
+
type NodeChangedData,
|
|
96
104
|
// Types not really intended for public use, but used in links.
|
|
97
105
|
// Can not be moved to internalTypes since doing so causes app code to throw errors like:
|
|
98
106
|
// Error: src/simple-tree/objectNode.ts:72:1 - (ae-unresolved-link) The @link reference could not be resolved: The package "@fluidframework/tree" does not have an export "TreeNodeApi"
|
package/src/packageVersion.ts
CHANGED
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
type TreeChangeEvents,
|
|
45
45
|
tryGetTreeNodeSchema,
|
|
46
46
|
} from "../core/index.js";
|
|
47
|
+
import { isObjectNodeSchema } from "../objectNodeTypes.js";
|
|
47
48
|
|
|
48
49
|
/**
|
|
49
50
|
* Provides various functions for analyzing {@link TreeNode}s.
|
|
@@ -98,10 +99,10 @@ export interface TreeNodeApi {
|
|
|
98
99
|
* @returns A callback function which will deregister the event.
|
|
99
100
|
* This callback should be called only once.
|
|
100
101
|
*/
|
|
101
|
-
on<K extends keyof TreeChangeEvents>(
|
|
102
|
-
node:
|
|
102
|
+
on<K extends keyof TreeChangeEvents<TNode>, TNode extends TreeNode>(
|
|
103
|
+
node: TNode,
|
|
103
104
|
eventName: K,
|
|
104
|
-
listener: TreeChangeEvents[K],
|
|
105
|
+
listener: TreeChangeEvents<TNode>[K],
|
|
105
106
|
): () => void;
|
|
106
107
|
|
|
107
108
|
/**
|
|
@@ -167,7 +168,38 @@ export const treeNodeApi: TreeNodeApi = {
|
|
|
167
168
|
eventName: K,
|
|
168
169
|
listener: TreeChangeEvents[K],
|
|
169
170
|
): Off {
|
|
170
|
-
|
|
171
|
+
const kernel = getKernel(node);
|
|
172
|
+
switch (eventName) {
|
|
173
|
+
case "nodeChanged": {
|
|
174
|
+
const nodeSchema = kernel.schema;
|
|
175
|
+
if (isObjectNodeSchema(nodeSchema)) {
|
|
176
|
+
return kernel.on("childrenChangedAfterBatch", ({ changedFields }) => {
|
|
177
|
+
const changedProperties = new Set(
|
|
178
|
+
Array.from(
|
|
179
|
+
changedFields,
|
|
180
|
+
(field) =>
|
|
181
|
+
nodeSchema.storedKeyToPropertyKey.get(field) ??
|
|
182
|
+
fail(`Could not find stored key '${field}' in schema.`),
|
|
183
|
+
),
|
|
184
|
+
);
|
|
185
|
+
listener({ changedProperties });
|
|
186
|
+
});
|
|
187
|
+
} else if (nodeSchema.kind === NodeKind.Array) {
|
|
188
|
+
return kernel.on("childrenChangedAfterBatch", () => {
|
|
189
|
+
listener({ changedProperties: undefined });
|
|
190
|
+
});
|
|
191
|
+
} else {
|
|
192
|
+
return kernel.on("childrenChangedAfterBatch", ({ changedFields }) => {
|
|
193
|
+
listener({ changedProperties: changedFields });
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
case "treeChanged": {
|
|
198
|
+
return kernel.on("subtreeChangedAfterBatch", () => listener({}));
|
|
199
|
+
}
|
|
200
|
+
default:
|
|
201
|
+
throw new UsageError(`No event named ${JSON.stringify(eventName)}.`);
|
|
202
|
+
}
|
|
171
203
|
},
|
|
172
204
|
status(node: TreeNode): TreeStatus {
|
|
173
205
|
return getKernel(node).getStatus();
|
|
@@ -245,7 +277,7 @@ export function tryGetSchema(value: unknown): undefined | TreeNodeSchema {
|
|
|
245
277
|
return booleanSchema;
|
|
246
278
|
case "object": {
|
|
247
279
|
if (isTreeNode(value)) {
|
|
248
|
-
// This case could be optimized, for example by placing the simple schema in a symbol on tree nodes.
|
|
280
|
+
// TODO: This case could be optimized, for example by placing the simple schema in a symbol on tree nodes.
|
|
249
281
|
return tryGetTreeNodeSchema(value);
|
|
250
282
|
}
|
|
251
283
|
if (value === null) {
|
|
@@ -670,19 +670,10 @@ abstract class CustomArrayNodeBase<const T extends ImplicitAllowedTypes>
|
|
|
670
670
|
|
|
671
671
|
protected abstract get simpleSchema(): T;
|
|
672
672
|
|
|
673
|
-
/**
|
|
674
|
-
* Generation number which is incremented any time we have an edit on the node.
|
|
675
|
-
* Used during iteration to make sure there has been no edits that were concurrently made.
|
|
676
|
-
*/
|
|
677
|
-
#generationNumber: number = 0;
|
|
678
|
-
|
|
679
673
|
public constructor(
|
|
680
674
|
input: Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>> | InternalTreeNode,
|
|
681
675
|
) {
|
|
682
676
|
super(input);
|
|
683
|
-
getKernel(this).on("nodeChanged", () => {
|
|
684
|
-
this.#generationNumber += 1;
|
|
685
|
-
});
|
|
686
677
|
}
|
|
687
678
|
|
|
688
679
|
#mapTreesFromFieldData(value: Insertable<T>): ExclusiveMapTree[] {
|
|
@@ -884,17 +875,17 @@ abstract class CustomArrayNodeBase<const T extends ImplicitAllowedTypes>
|
|
|
884
875
|
}
|
|
885
876
|
|
|
886
877
|
public values(): IterableIterator<TreeNodeFromImplicitAllowedTypes<T>> {
|
|
887
|
-
return this.generateValues(this
|
|
878
|
+
return this.generateValues(getKernel(this).generationNumber);
|
|
888
879
|
}
|
|
889
880
|
private *generateValues(
|
|
890
881
|
initialLastUpdatedStamp: number,
|
|
891
882
|
): Generator<TreeNodeFromImplicitAllowedTypes<T>> {
|
|
892
|
-
if (initialLastUpdatedStamp !== this
|
|
883
|
+
if (initialLastUpdatedStamp !== getKernel(this).generationNumber) {
|
|
893
884
|
throw new UsageError(`Concurrent editing and iteration is not allowed.`);
|
|
894
885
|
}
|
|
895
886
|
for (let i = 0; i < this.length; i++) {
|
|
896
887
|
yield this.at(i) ?? fail("Index is out of bounds");
|
|
897
|
-
if (initialLastUpdatedStamp !== this
|
|
888
|
+
if (initialLastUpdatedStamp !== getKernel(this).generationNumber) {
|
|
898
889
|
throw new UsageError(`Concurrent editing and iteration is not allowed.`);
|
|
899
890
|
}
|
|
900
891
|
}
|