@fluidframework/runtime-utils 2.0.0-dev-rc.3.0.0.254866 → 2.0.0-dev-rc.5.0.0.263932

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.
Files changed (53) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/api-report/runtime-utils.api.md +44 -1
  3. package/dist/dataStoreHelpers.d.ts +1 -1
  4. package/dist/dataStoreHelpers.js +1 -1
  5. package/dist/dataStoreHelpers.js.map +1 -1
  6. package/dist/deltaManager.d.ts +19 -0
  7. package/dist/deltaManager.d.ts.map +1 -0
  8. package/dist/deltaManager.js +25 -0
  9. package/dist/deltaManager.js.map +1 -0
  10. package/dist/handles.d.ts +35 -0
  11. package/dist/handles.d.ts.map +1 -1
  12. package/dist/handles.js +79 -1
  13. package/dist/handles.js.map +1 -1
  14. package/dist/index.d.ts +3 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +10 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/{alpha.d.ts → legacy.d.ts} +8 -2
  19. package/dist/public.d.ts +3 -0
  20. package/dist/snapshotUtils.d.ts +14 -0
  21. package/dist/snapshotUtils.d.ts.map +1 -0
  22. package/dist/snapshotUtils.js +37 -0
  23. package/dist/snapshotUtils.js.map +1 -0
  24. package/{dist/beta.d.ts → internal.d.ts} +2 -0
  25. package/{lib/beta.d.ts → legacy.d.ts} +2 -0
  26. package/lib/dataStoreHelpers.d.ts +1 -1
  27. package/lib/dataStoreHelpers.js +1 -1
  28. package/lib/dataStoreHelpers.js.map +1 -1
  29. package/lib/deltaManager.d.ts +19 -0
  30. package/lib/deltaManager.d.ts.map +1 -0
  31. package/lib/deltaManager.js +20 -0
  32. package/lib/deltaManager.js.map +1 -0
  33. package/lib/handles.d.ts +35 -0
  34. package/lib/handles.d.ts.map +1 -1
  35. package/lib/handles.js +74 -0
  36. package/lib/handles.js.map +1 -1
  37. package/lib/index.d.ts +3 -1
  38. package/lib/index.d.ts.map +1 -1
  39. package/lib/index.js +3 -1
  40. package/lib/index.js.map +1 -1
  41. package/lib/{alpha.d.ts → legacy.d.ts} +8 -2
  42. package/lib/public.d.ts +3 -0
  43. package/lib/snapshotUtils.d.ts +14 -0
  44. package/lib/snapshotUtils.d.ts.map +1 -0
  45. package/lib/snapshotUtils.js +33 -0
  46. package/lib/snapshotUtils.js.map +1 -0
  47. package/lib/tsdoc-metadata.json +1 -1
  48. package/package.json +26 -31
  49. package/src/dataStoreHelpers.ts +1 -1
  50. package/src/deltaManager.ts +32 -0
  51. package/src/handles.ts +92 -0
  52. package/src/index.ts +10 -1
  53. package/src/snapshotUtils.ts +38 -0
package/src/handles.ts CHANGED
@@ -3,6 +3,12 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
+ import type {
7
+ IFluidHandleErased,
8
+ IFluidHandleInternal,
9
+ } from "@fluidframework/core-interfaces/internal";
10
+ import { IFluidHandle, fluidHandleSymbol } from "@fluidframework/core-interfaces";
11
+
6
12
  /**
7
13
  * JSON serialized form of an IFluidHandle
8
14
  * @internal
@@ -21,3 +27,89 @@ export interface ISerializedHandle {
21
27
  */
22
28
  export const isSerializedHandle = (value: any): value is ISerializedHandle =>
23
29
  value?.type === "__fluid_handle__";
30
+
31
+ /**
32
+ * Setting to opt into compatibility with handles from before {@link fluidHandleSymbol} existed (Fluid Framework client 2.0.0-rc.3.0.0 and earlier).
33
+ *
34
+ * Some code which uses this library might dynamically load multiple versions of it,
35
+ * as well as old or duplicated versions of packages which produce or implement handles.
36
+ * To correctly interoperate with this old packages and object produced by them, the old in-memory format for handles, without the symbol, are explicitly supported.
37
+ *
38
+ * This setting mostly exists as a way to easily find any code that only exists to provide this compatibility and clarify how to remove that compatibility.
39
+ * At some point this might be removed or turned into an actual configuration option, but for now its really just documentation.
40
+ */
41
+ const enableBackwardsCompatibility = true;
42
+
43
+ /**
44
+ * Check if a value is an IFluidHandle.
45
+ * @remarks
46
+ * Objects which have a field named `IFluidHandle` can in some cases produce a false positive.
47
+ * @internal
48
+ */
49
+ export function isFluidHandle(value: unknown): value is IFluidHandle {
50
+ // `in` gives a type error on non-objects and null, so filter them out
51
+ if (typeof value !== "object" || value === null) {
52
+ return false;
53
+ }
54
+ if (fluidHandleSymbol in value) {
55
+ return true;
56
+ }
57
+ // If enableBackwardsCompatibility, run check for FluidHandles predating use of fluidHandleSymbol.
58
+ if (enableBackwardsCompatibility && IFluidHandle in value) {
59
+ // Since this check can have false positives, make it a bit more robust by checking value[IFluidHandle][IFluidHandle]
60
+ const inner = value[IFluidHandle] as IFluidHandle;
61
+ if (typeof inner !== "object" || inner === null) {
62
+ return false;
63
+ }
64
+ return IFluidHandle in inner;
65
+ }
66
+ return false;
67
+ }
68
+
69
+ /**
70
+ * Downcast an IFluidHandle to an IFluidHandleInternal.
71
+ * @alpha
72
+ */
73
+ export function toFluidHandleInternal<T>(handle: IFluidHandle<T>): IFluidHandleInternal<T> {
74
+ if (!(fluidHandleSymbol in handle) || !(fluidHandleSymbol in handle[fluidHandleSymbol])) {
75
+ if (enableBackwardsCompatibility && IFluidHandle in handle) {
76
+ return handle[IFluidHandle] as IFluidHandleInternal<T>;
77
+ }
78
+ throw new TypeError("Invalid IFluidHandle");
79
+ }
80
+
81
+ // This casts the IFluidHandleErased from the symbol instead of `handle` to ensure that if someone
82
+ // implements their own IFluidHandle in terms of an existing handle, it won't break anything.
83
+ return handle[fluidHandleSymbol] as unknown as IFluidHandleInternal<T>;
84
+ }
85
+
86
+ /**
87
+ * Type erase IFluidHandleInternal for use with {@link @fluidframework/core-interfaces#fluidHandleSymbol}.
88
+ * @alpha
89
+ */
90
+ export function toFluidHandleErased<T>(handle: IFluidHandleInternal<T>): IFluidHandleErased<T> {
91
+ return handle as unknown as IFluidHandleErased<T>;
92
+ }
93
+
94
+ /**
95
+ * Base class which can be uses to assist implementing IFluidHandleInternal.
96
+ * @alpha
97
+ */
98
+ export abstract class FluidHandleBase<T> implements IFluidHandleInternal<T> {
99
+ public abstract absolutePath: string;
100
+ public abstract attachGraph(): void;
101
+ public abstract bind(handle: IFluidHandleInternal): void;
102
+ public abstract readonly isAttached: boolean;
103
+ public abstract get(): Promise<T>;
104
+
105
+ /**
106
+ * {@inheritDoc @fluidframework/core-interfaces#IProvideFluidHandle.IFluidHandle}
107
+ */
108
+ public get IFluidHandle(): IFluidHandleInternal {
109
+ return this;
110
+ }
111
+
112
+ public get [fluidHandleSymbol](): IFluidHandleErased<T> {
113
+ return toFluidHandleErased(this);
114
+ }
115
+ }
package/src/index.ts CHANGED
@@ -12,7 +12,14 @@ export {
12
12
  Factory,
13
13
  responseToException,
14
14
  } from "./dataStoreHelpers.js";
15
- export { ISerializedHandle, isSerializedHandle } from "./handles.js";
15
+ export {
16
+ ISerializedHandle,
17
+ isSerializedHandle,
18
+ isFluidHandle,
19
+ toFluidHandleErased,
20
+ toFluidHandleInternal,
21
+ FluidHandleBase,
22
+ } from "./handles.js";
16
23
  export { ObjectStoragePartition } from "./objectstoragepartition.js";
17
24
  export { getNormalizedObjectStoragePathParts, listBlobsAtTreePath } from "./objectstorageutils.js";
18
25
  export { RequestParser } from "./requestParser.js";
@@ -35,3 +42,5 @@ export {
35
42
  } from "./summaryUtils.js";
36
43
  export { unpackChildNodesUsedRoutes } from "./unpackUsedRoutes.js";
37
44
  export { ReadAndParseBlob, seqFromTree, encodeCompactIdToString } from "./utils.js";
45
+ export { isSnapshotFetchRequiredForLoadingGroupId } from "./snapshotUtils.js";
46
+ export { toDeltaManagerErased, toDeltaManagerInternal } from "./deltaManager.js";
@@ -0,0 +1,38 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import type { ISnapshotTree } from "@fluidframework/protocol-definitions";
7
+
8
+ /**
9
+ * Utility function to check if any blobs under a snapshot tree is missing and if so, then return
10
+ * true if that is the case.
11
+ * @internal
12
+ * @param snapshotTree - snapshotTree to be evaluated for missing blobs.
13
+ * @param blobContents - blobContents of the snapshot.
14
+ */
15
+ export function isSnapshotFetchRequiredForLoadingGroupId(
16
+ snapshotTree: ISnapshotTree,
17
+ blobContents: Map<string, ArrayBuffer>,
18
+ ): boolean {
19
+ for (const [_, id] of Object.entries(snapshotTree.blobs)) {
20
+ if (!blobContents.has(id)) {
21
+ return true;
22
+ }
23
+ }
24
+ for (const [_, childTree] of Object.entries(snapshotTree.trees)) {
25
+ // Only evaluate childTree if it does not have a loading groupId because if the childTree has a loading
26
+ // groupId then it will be evaluated whether we want to fetch blobs for that childTree or not when
27
+ // that particular childTree is getting realized. Now we just want to check for blobs which belongs to
28
+ // tree with current loading groupId. Note: Child with no loading groupId, will fall under parent with
29
+ // a loading groupId as it does not have its own loading groupId.
30
+ if (childTree.groupId === undefined) {
31
+ const value = isSnapshotFetchRequiredForLoadingGroupId(childTree, blobContents);
32
+ if (value) {
33
+ return true;
34
+ }
35
+ }
36
+ }
37
+ return false;
38
+ }