@fluidframework/runtime-utils 2.0.0-rc.3.0.3 → 2.0.0-rc.4.0.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 +30 -0
- package/api-report/runtime-utils.api.md +43 -0
- package/dist/deltaManager.d.ts +19 -0
- package/dist/deltaManager.d.ts.map +1 -0
- package/dist/deltaManager.js +25 -0
- package/dist/deltaManager.js.map +1 -0
- package/dist/handles.d.ts +35 -0
- package/dist/handles.d.ts.map +1 -1
- package/dist/handles.js +79 -1
- package/dist/handles.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +6 -2
- package/dist/snapshotUtils.d.ts +14 -0
- package/dist/snapshotUtils.d.ts.map +1 -0
- package/dist/snapshotUtils.js +37 -0
- package/dist/snapshotUtils.js.map +1 -0
- package/lib/deltaManager.d.ts +19 -0
- package/lib/deltaManager.d.ts.map +1 -0
- package/lib/deltaManager.js +20 -0
- package/lib/deltaManager.js.map +1 -0
- package/lib/handles.d.ts +35 -0
- package/lib/handles.d.ts.map +1 -1
- package/lib/handles.js +74 -0
- package/lib/handles.js.map +1 -1
- package/lib/index.d.ts +3 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -1
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +6 -2
- package/lib/snapshotUtils.d.ts +14 -0
- package/lib/snapshotUtils.d.ts.map +1 -0
- package/lib/snapshotUtils.js +33 -0
- package/lib/snapshotUtils.js.map +1 -0
- package/lib/tsdoc-metadata.json +1 -1
- package/package.json +17 -22
- package/src/deltaManager.ts +32 -0
- package/src/handles.ts +92 -0
- package/src/index.ts +10 -1
- package/src/snapshotUtils.ts +38 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @fluidframework/runtime-utils
|
|
2
2
|
|
|
3
|
+
## 2.0.0-rc.4.0.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Deprecated members of IFluidHandle are split off into new IFluidHandleInternal interface [96872186d0](https://github.com/microsoft/FluidFramework/commit/96872186d0d0f245c1fece7d19b3743e501679b6)
|
|
8
|
+
|
|
9
|
+
Split IFluidHandle into two interfaces, `IFluidHandle` and `IFluidHandleInternal`.
|
|
10
|
+
Code depending on the previously deprecated members of IFluidHandle can access them by using `toFluidHandleInternal` from `@fluidframework/runtime-utils/legacy`.
|
|
11
|
+
|
|
12
|
+
External implementation of the `IFluidHandle` interface are not supported: this change makes the typing better convey this using the `ErasedType` pattern.
|
|
13
|
+
Any existing and previously working, and now broken, external implementations of `IFluidHandle` should still work at runtime, but will need some unsafe type casts to compile.
|
|
14
|
+
Such handle implementation may break in the future and thus should be replaced with use of handles produced by the Fluid Framework client packages.
|
|
15
|
+
|
|
16
|
+
- Type Erase IFluidDataStoreRuntime.deltaManager [96872186d0](https://github.com/microsoft/FluidFramework/commit/96872186d0d0f245c1fece7d19b3743e501679b6)
|
|
17
|
+
|
|
18
|
+
Make IFluidDataStoreRuntime.deltaManager have an opaque type.
|
|
19
|
+
Marks the following types which were reachable from it as alpha:
|
|
20
|
+
|
|
21
|
+
- IConnectionDetails
|
|
22
|
+
- IDeltaSender
|
|
23
|
+
- IDeltaManagerEvents
|
|
24
|
+
- IDeltaManager
|
|
25
|
+
- IDeltaQueueEvents
|
|
26
|
+
- IDeltaQueue
|
|
27
|
+
- ReadOnlyInfo
|
|
28
|
+
|
|
29
|
+
As a temporary workaround, users needing access to the full delta manager API can use the `@alpha` `toDeltaManagerInternal` API to retrieve its members, but should migrate away from requiring access to those APIs.
|
|
30
|
+
|
|
31
|
+
Implementing a custom `IFluidDataStoreRuntime` is not supported: this is now indicated by it being marked with `@sealed`.
|
|
32
|
+
|
|
3
33
|
## 2.0.0-rc.3.0.0
|
|
4
34
|
|
|
5
35
|
### Major Changes
|
|
@@ -4,12 +4,19 @@
|
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
6
|
|
|
7
|
+
import { fluidHandleSymbol } from '@fluidframework/core-interfaces';
|
|
7
8
|
import { IChannelStorageService } from '@fluidframework/datastore-definitions';
|
|
8
9
|
import { IContainerContext } from '@fluidframework/container-definitions/internal';
|
|
9
10
|
import { IContainerRuntime } from '@fluidframework/container-runtime-definitions/internal';
|
|
11
|
+
import type { IDeltaManager } from '@fluidframework/container-definitions/internal';
|
|
12
|
+
import type { IDeltaManagerErased } from '@fluidframework/datastore-definitions';
|
|
13
|
+
import type { IDocumentMessage } from '@fluidframework/protocol-definitions';
|
|
10
14
|
import { IFluidDataStoreFactory } from '@fluidframework/runtime-definitions/internal';
|
|
11
15
|
import { IFluidDataStoreRegistry } from '@fluidframework/runtime-definitions/internal';
|
|
16
|
+
import { IFluidHandle } from '@fluidframework/core-interfaces';
|
|
12
17
|
import { IFluidHandleContext } from '@fluidframework/core-interfaces';
|
|
18
|
+
import type { IFluidHandleErased } from '@fluidframework/core-interfaces/internal';
|
|
19
|
+
import type { IFluidHandleInternal } from '@fluidframework/core-interfaces/internal';
|
|
13
20
|
import { IGarbageCollectionData } from '@fluidframework/runtime-definitions';
|
|
14
21
|
import { IProvideFluidDataStoreRegistry } from '@fluidframework/runtime-definitions/internal';
|
|
15
22
|
import { IRequest } from '@fluidframework/core-interfaces';
|
|
@@ -17,6 +24,7 @@ import { IRequestHeader } from '@fluidframework/core-interfaces';
|
|
|
17
24
|
import { IResponse } from '@fluidframework/core-interfaces';
|
|
18
25
|
import { IRuntime } from '@fluidframework/container-definitions/internal';
|
|
19
26
|
import { IRuntimeFactory } from '@fluidframework/container-definitions/internal';
|
|
27
|
+
import type { ISequencedDocumentMessage } from '@fluidframework/protocol-definitions';
|
|
20
28
|
import { ISnapshotTree } from '@fluidframework/protocol-definitions';
|
|
21
29
|
import { ISnapshotTreeWithBlobContents } from '@fluidframework/container-definitions/internal';
|
|
22
30
|
import { ISummarizeResult } from '@fluidframework/runtime-definitions/internal';
|
|
@@ -71,6 +79,23 @@ export function exceptionToResponse(err: any): IResponse;
|
|
|
71
79
|
// @internal (undocumented)
|
|
72
80
|
export type Factory = IFluidDataStoreFactory & Partial<IProvideFluidDataStoreRegistry>;
|
|
73
81
|
|
|
82
|
+
// @alpha
|
|
83
|
+
export abstract class FluidHandleBase<T> implements IFluidHandleInternal<T> {
|
|
84
|
+
// (undocumented)
|
|
85
|
+
get [fluidHandleSymbol](): IFluidHandleErased<T>;
|
|
86
|
+
// (undocumented)
|
|
87
|
+
abstract absolutePath: string;
|
|
88
|
+
// (undocumented)
|
|
89
|
+
abstract attachGraph(): void;
|
|
90
|
+
// (undocumented)
|
|
91
|
+
abstract bind(handle: IFluidHandleInternal): void;
|
|
92
|
+
// (undocumented)
|
|
93
|
+
abstract get(): Promise<T>;
|
|
94
|
+
get IFluidHandle(): IFluidHandleInternal;
|
|
95
|
+
// (undocumented)
|
|
96
|
+
abstract readonly isAttached: boolean;
|
|
97
|
+
}
|
|
98
|
+
|
|
74
99
|
// @internal
|
|
75
100
|
export class GCDataBuilder implements IGarbageCollectionData {
|
|
76
101
|
// (undocumented)
|
|
@@ -108,9 +133,15 @@ export interface ISerializedHandle {
|
|
|
108
133
|
url: string;
|
|
109
134
|
}
|
|
110
135
|
|
|
136
|
+
// @internal
|
|
137
|
+
export function isFluidHandle(value: unknown): value is IFluidHandle;
|
|
138
|
+
|
|
111
139
|
// @internal
|
|
112
140
|
export const isSerializedHandle: (value: any) => value is ISerializedHandle;
|
|
113
141
|
|
|
142
|
+
// @internal
|
|
143
|
+
export function isSnapshotFetchRequiredForLoadingGroupId(snapshotTree: ISnapshotTree, blobContents: Map<string, ArrayBuffer>): boolean;
|
|
144
|
+
|
|
114
145
|
// @internal (undocumented)
|
|
115
146
|
export function listBlobsAtTreePath(inputTree: ITree | undefined, path: string): Promise<string[]>;
|
|
116
147
|
|
|
@@ -200,6 +231,18 @@ export class TelemetryContext implements ITelemetryContext {
|
|
|
200
231
|
setMultiple(prefix: string, property: string, values: Record<string, TelemetryBaseEventPropertyType>): void;
|
|
201
232
|
}
|
|
202
233
|
|
|
234
|
+
// @internal
|
|
235
|
+
export function toDeltaManagerErased(deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>): IDeltaManagerErased;
|
|
236
|
+
|
|
237
|
+
// @alpha
|
|
238
|
+
export function toDeltaManagerInternal(deltaManager: IDeltaManagerErased): IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;
|
|
239
|
+
|
|
240
|
+
// @alpha
|
|
241
|
+
export function toFluidHandleErased<T>(handle: IFluidHandleInternal<T>): IFluidHandleErased<T>;
|
|
242
|
+
|
|
243
|
+
// @alpha
|
|
244
|
+
export function toFluidHandleInternal<T>(handle: IFluidHandle<T>): IFluidHandleInternal<T>;
|
|
245
|
+
|
|
203
246
|
// @internal
|
|
204
247
|
export function unpackChildNodesUsedRoutes(usedRoutes: readonly string[]): Map<string, string[]>;
|
|
205
248
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import type { IDeltaManager } from "@fluidframework/container-definitions/internal";
|
|
6
|
+
import type { IDeltaManagerErased } from "@fluidframework/datastore-definitions";
|
|
7
|
+
import type { IDocumentMessage, ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
8
|
+
/**
|
|
9
|
+
* Casts the public API for delta manager into the internal one,
|
|
10
|
+
* exposing access to APIs needed by the implementation of Fluid Framework but not its users.
|
|
11
|
+
* @alpha
|
|
12
|
+
*/
|
|
13
|
+
export declare function toDeltaManagerInternal(deltaManager: IDeltaManagerErased): IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;
|
|
14
|
+
/**
|
|
15
|
+
* Casts the the internal API for delta manager into the public type erased API for returning from public APIs that should not have access to any of its members.
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export declare function toDeltaManagerErased(deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>): IDeltaManagerErased;
|
|
19
|
+
//# sourceMappingURL=deltaManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deltaManager.d.ts","sourceRoot":"","sources":["../src/deltaManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAC;AACpF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,KAAK,EACX,gBAAgB,EAChB,yBAAyB,EACzB,MAAM,sCAAsC,CAAC;AAE9C;;;;GAIG;AACH,wBAAgB,sBAAsB,CACrC,YAAY,EAAE,mBAAmB,GAC/B,aAAa,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,CAE5D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CACnC,YAAY,EAAE,aAAa,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,GACtE,mBAAmB,CAErB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.toDeltaManagerErased = exports.toDeltaManagerInternal = void 0;
|
|
8
|
+
/**
|
|
9
|
+
* Casts the public API for delta manager into the internal one,
|
|
10
|
+
* exposing access to APIs needed by the implementation of Fluid Framework but not its users.
|
|
11
|
+
* @alpha
|
|
12
|
+
*/
|
|
13
|
+
function toDeltaManagerInternal(deltaManager) {
|
|
14
|
+
return deltaManager;
|
|
15
|
+
}
|
|
16
|
+
exports.toDeltaManagerInternal = toDeltaManagerInternal;
|
|
17
|
+
/**
|
|
18
|
+
* Casts the the internal API for delta manager into the public type erased API for returning from public APIs that should not have access to any of its members.
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
function toDeltaManagerErased(deltaManager) {
|
|
22
|
+
return deltaManager;
|
|
23
|
+
}
|
|
24
|
+
exports.toDeltaManagerErased = toDeltaManagerErased;
|
|
25
|
+
//# sourceMappingURL=deltaManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deltaManager.js","sourceRoot":"","sources":["../src/deltaManager.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AASH;;;;GAIG;AACH,SAAgB,sBAAsB,CACrC,YAAiC;IAEjC,OAAO,YAAqF,CAAC;AAC9F,CAAC;AAJD,wDAIC;AAED;;;GAGG;AACH,SAAgB,oBAAoB,CACnC,YAAwE;IAExE,OAAO,YAA8C,CAAC;AACvD,CAAC;AAJD,oDAIC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IDeltaManager } from \"@fluidframework/container-definitions/internal\";\nimport type { IDeltaManagerErased } from \"@fluidframework/datastore-definitions\";\nimport type {\n\tIDocumentMessage,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\n\n/**\n * Casts the public API for delta manager into the internal one,\n * exposing access to APIs needed by the implementation of Fluid Framework but not its users.\n * @alpha\n */\nexport function toDeltaManagerInternal(\n\tdeltaManager: IDeltaManagerErased,\n): IDeltaManager<ISequencedDocumentMessage, IDocumentMessage> {\n\treturn deltaManager as unknown as IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;\n}\n\n/**\n * Casts the the internal API for delta manager into the public type erased API for returning from public APIs that should not have access to any of its members.\n * @internal\n */\nexport function toDeltaManagerErased(\n\tdeltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,\n): IDeltaManagerErased {\n\treturn deltaManager as unknown as IDeltaManagerErased;\n}\n"]}
|
package/dist/handles.d.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
+
import type { IFluidHandleErased, IFluidHandleInternal } from "@fluidframework/core-interfaces/internal";
|
|
6
|
+
import { IFluidHandle, fluidHandleSymbol } from "@fluidframework/core-interfaces";
|
|
5
7
|
/**
|
|
6
8
|
* JSON serialized form of an IFluidHandle
|
|
7
9
|
* @internal
|
|
@@ -15,4 +17,37 @@ export interface ISerializedHandle {
|
|
|
15
17
|
* @internal
|
|
16
18
|
*/
|
|
17
19
|
export declare const isSerializedHandle: (value: any) => value is ISerializedHandle;
|
|
20
|
+
/**
|
|
21
|
+
* Check if a value is an IFluidHandle.
|
|
22
|
+
* @remarks
|
|
23
|
+
* Objects which have a field named `IFluidHandle` can in some cases produce a false positive.
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
export declare function isFluidHandle(value: unknown): value is IFluidHandle;
|
|
27
|
+
/**
|
|
28
|
+
* Downcast an IFluidHandle to an IFluidHandleInternal.
|
|
29
|
+
* @alpha
|
|
30
|
+
*/
|
|
31
|
+
export declare function toFluidHandleInternal<T>(handle: IFluidHandle<T>): IFluidHandleInternal<T>;
|
|
32
|
+
/**
|
|
33
|
+
* Type erase IFluidHandleInternal for use with {@link @fluidframework/core-interfaces#fluidHandleSymbol}.
|
|
34
|
+
* @alpha
|
|
35
|
+
*/
|
|
36
|
+
export declare function toFluidHandleErased<T>(handle: IFluidHandleInternal<T>): IFluidHandleErased<T>;
|
|
37
|
+
/**
|
|
38
|
+
* Base class which can be uses to assist implementing IFluidHandleInternal.
|
|
39
|
+
* @alpha
|
|
40
|
+
*/
|
|
41
|
+
export declare abstract class FluidHandleBase<T> implements IFluidHandleInternal<T> {
|
|
42
|
+
abstract absolutePath: string;
|
|
43
|
+
abstract attachGraph(): void;
|
|
44
|
+
abstract bind(handle: IFluidHandleInternal): void;
|
|
45
|
+
abstract readonly isAttached: boolean;
|
|
46
|
+
abstract get(): Promise<T>;
|
|
47
|
+
/**
|
|
48
|
+
* {@inheritDoc @fluidframework/core-interfaces#IProvideFluidHandle.IFluidHandle}
|
|
49
|
+
*/
|
|
50
|
+
get IFluidHandle(): IFluidHandleInternal;
|
|
51
|
+
get [fluidHandleSymbol](): IFluidHandleErased<T>;
|
|
52
|
+
}
|
|
18
53
|
//# sourceMappingURL=handles.d.ts.map
|
package/dist/handles.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handles.d.ts","sourceRoot":"","sources":["../src/handles.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAEjC,IAAI,EAAE,kBAAkB,CAAC;IAGzB,GAAG,EAAE,MAAM,CAAC;CACZ;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,UAAW,GAAG,+BACV,CAAC"}
|
|
1
|
+
{"version":3,"file":"handles.d.ts","sourceRoot":"","sources":["../src/handles.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,kBAAkB,EAClB,oBAAoB,EACpB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAElF;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAEjC,IAAI,EAAE,kBAAkB,CAAC;IAGzB,GAAG,EAAE,MAAM,CAAC;CACZ;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,UAAW,GAAG,+BACV,CAAC;AAcpC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAkBnE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAWzF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAE7F;AAED;;;GAGG;AACH,8BAAsB,eAAe,CAAC,CAAC,CAAE,YAAW,oBAAoB,CAAC,CAAC,CAAC;IAC1E,SAAgB,YAAY,EAAE,MAAM,CAAC;aACrB,WAAW,IAAI,IAAI;aACnB,IAAI,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI;IACxD,kBAAyB,UAAU,EAAE,OAAO,CAAC;aAC7B,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC;IAEjC;;OAEG;IACH,IAAW,YAAY,IAAI,oBAAoB,CAE9C;IAED,IAAW,CAAC,iBAAiB,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,CAEtD;CACD"}
|
package/dist/handles.js
CHANGED
|
@@ -4,11 +4,89 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.isSerializedHandle = void 0;
|
|
7
|
+
exports.FluidHandleBase = exports.toFluidHandleErased = exports.toFluidHandleInternal = exports.isFluidHandle = exports.isSerializedHandle = void 0;
|
|
8
|
+
const core_interfaces_1 = require("@fluidframework/core-interfaces");
|
|
8
9
|
/**
|
|
9
10
|
* Is the input object a @see ISerializedHandle?
|
|
10
11
|
* @internal
|
|
11
12
|
*/
|
|
12
13
|
const isSerializedHandle = (value) => value?.type === "__fluid_handle__";
|
|
13
14
|
exports.isSerializedHandle = isSerializedHandle;
|
|
15
|
+
/**
|
|
16
|
+
* Setting to opt into compatibility with handles from before {@link fluidHandleSymbol} existed (Fluid Framework client 2.0.0-rc.3.0.0 and earlier).
|
|
17
|
+
*
|
|
18
|
+
* Some code which uses this library might dynamically load multiple versions of it,
|
|
19
|
+
* as well as old or duplicated versions of packages which produce or implement handles.
|
|
20
|
+
* 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.
|
|
21
|
+
*
|
|
22
|
+
* 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.
|
|
23
|
+
* At some point this might be removed or turned into an actual configuration option, but for now its really just documentation.
|
|
24
|
+
*/
|
|
25
|
+
const enableBackwardsCompatibility = true;
|
|
26
|
+
/**
|
|
27
|
+
* Check if a value is an IFluidHandle.
|
|
28
|
+
* @remarks
|
|
29
|
+
* Objects which have a field named `IFluidHandle` can in some cases produce a false positive.
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
function isFluidHandle(value) {
|
|
33
|
+
// `in` gives a type error on non-objects and null, so filter them out
|
|
34
|
+
if (typeof value !== "object" || value === null) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
if (core_interfaces_1.fluidHandleSymbol in value) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
// If enableBackwardsCompatibility, run check for FluidHandles predating use of fluidHandleSymbol.
|
|
41
|
+
if (enableBackwardsCompatibility && core_interfaces_1.IFluidHandle in value) {
|
|
42
|
+
// Since this check can have false positives, make it a bit more robust by checking value[IFluidHandle][IFluidHandle]
|
|
43
|
+
const inner = value[core_interfaces_1.IFluidHandle];
|
|
44
|
+
if (typeof inner !== "object" || inner === null) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return core_interfaces_1.IFluidHandle in inner;
|
|
48
|
+
}
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
exports.isFluidHandle = isFluidHandle;
|
|
52
|
+
/**
|
|
53
|
+
* Downcast an IFluidHandle to an IFluidHandleInternal.
|
|
54
|
+
* @alpha
|
|
55
|
+
*/
|
|
56
|
+
function toFluidHandleInternal(handle) {
|
|
57
|
+
if (!(core_interfaces_1.fluidHandleSymbol in handle) || !(core_interfaces_1.fluidHandleSymbol in handle[core_interfaces_1.fluidHandleSymbol])) {
|
|
58
|
+
if (enableBackwardsCompatibility && core_interfaces_1.IFluidHandle in handle) {
|
|
59
|
+
return handle[core_interfaces_1.IFluidHandle];
|
|
60
|
+
}
|
|
61
|
+
throw new TypeError("Invalid IFluidHandle");
|
|
62
|
+
}
|
|
63
|
+
// This casts the IFluidHandleErased from the symbol instead of `handle` to ensure that if someone
|
|
64
|
+
// implements their own IFluidHandle in terms of an existing handle, it won't break anything.
|
|
65
|
+
return handle[core_interfaces_1.fluidHandleSymbol];
|
|
66
|
+
}
|
|
67
|
+
exports.toFluidHandleInternal = toFluidHandleInternal;
|
|
68
|
+
/**
|
|
69
|
+
* Type erase IFluidHandleInternal for use with {@link @fluidframework/core-interfaces#fluidHandleSymbol}.
|
|
70
|
+
* @alpha
|
|
71
|
+
*/
|
|
72
|
+
function toFluidHandleErased(handle) {
|
|
73
|
+
return handle;
|
|
74
|
+
}
|
|
75
|
+
exports.toFluidHandleErased = toFluidHandleErased;
|
|
76
|
+
/**
|
|
77
|
+
* Base class which can be uses to assist implementing IFluidHandleInternal.
|
|
78
|
+
* @alpha
|
|
79
|
+
*/
|
|
80
|
+
class FluidHandleBase {
|
|
81
|
+
/**
|
|
82
|
+
* {@inheritDoc @fluidframework/core-interfaces#IProvideFluidHandle.IFluidHandle}
|
|
83
|
+
*/
|
|
84
|
+
get IFluidHandle() {
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
87
|
+
get [core_interfaces_1.fluidHandleSymbol]() {
|
|
88
|
+
return toFluidHandleErased(this);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
exports.FluidHandleBase = FluidHandleBase;
|
|
14
92
|
//# sourceMappingURL=handles.js.map
|
package/dist/handles.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handles.js","sourceRoot":"","sources":["../src/handles.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;
|
|
1
|
+
{"version":3,"file":"handles.js","sourceRoot":"","sources":["../src/handles.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAMH,qEAAkF;AAclF;;;GAGG;AACI,MAAM,kBAAkB,GAAG,CAAC,KAAU,EAA8B,EAAE,CAC5E,KAAK,EAAE,IAAI,KAAK,kBAAkB,CAAC;AADvB,QAAA,kBAAkB,sBACK;AAEpC;;;;;;;;;GASG;AACH,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAE1C;;;;;GAKG;AACH,SAAgB,aAAa,CAAC,KAAc;IAC3C,sEAAsE;IACtE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE;QAChD,OAAO,KAAK,CAAC;KACb;IACD,IAAI,mCAAiB,IAAI,KAAK,EAAE;QAC/B,OAAO,IAAI,CAAC;KACZ;IACD,kGAAkG;IAClG,IAAI,4BAA4B,IAAI,8BAAY,IAAI,KAAK,EAAE;QAC1D,qHAAqH;QACrH,MAAM,KAAK,GAAG,KAAK,CAAC,8BAAY,CAAiB,CAAC;QAClD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE;YAChD,OAAO,KAAK,CAAC;SACb;QACD,OAAO,8BAAY,IAAI,KAAK,CAAC;KAC7B;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAlBD,sCAkBC;AAED;;;GAGG;AACH,SAAgB,qBAAqB,CAAI,MAAuB;IAC/D,IAAI,CAAC,CAAC,mCAAiB,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,mCAAiB,IAAI,MAAM,CAAC,mCAAiB,CAAC,CAAC,EAAE;QACxF,IAAI,4BAA4B,IAAI,8BAAY,IAAI,MAAM,EAAE;YAC3D,OAAO,MAAM,CAAC,8BAAY,CAA4B,CAAC;SACvD;QACD,MAAM,IAAI,SAAS,CAAC,sBAAsB,CAAC,CAAC;KAC5C;IAED,kGAAkG;IAClG,6FAA6F;IAC7F,OAAO,MAAM,CAAC,mCAAiB,CAAuC,CAAC;AACxE,CAAC;AAXD,sDAWC;AAED;;;GAGG;AACH,SAAgB,mBAAmB,CAAI,MAA+B;IACrE,OAAO,MAA0C,CAAC;AACnD,CAAC;AAFD,kDAEC;AAED;;;GAGG;AACH,MAAsB,eAAe;IAOpC;;OAEG;IACH,IAAW,YAAY;QACtB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,IAAW,CAAC,mCAAiB,CAAC;QAC7B,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;CACD;AAjBD,0CAiBC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tIFluidHandleErased,\n\tIFluidHandleInternal,\n} from \"@fluidframework/core-interfaces/internal\";\nimport { IFluidHandle, fluidHandleSymbol } from \"@fluidframework/core-interfaces\";\n\n/**\n * JSON serialized form of an IFluidHandle\n * @internal\n */\nexport interface ISerializedHandle {\n\t// Marker to indicate to JSON.parse that the object is a Fluid handle\n\ttype: \"__fluid_handle__\";\n\n\t// URL to the object. Relative URLs are relative to the handle context passed to the stringify.\n\turl: string;\n}\n\n/**\n * Is the input object a @see ISerializedHandle?\n * @internal\n */\nexport const isSerializedHandle = (value: any): value is ISerializedHandle =>\n\tvalue?.type === \"__fluid_handle__\";\n\n/**\n * Setting to opt into compatibility with handles from before {@link fluidHandleSymbol} existed (Fluid Framework client 2.0.0-rc.3.0.0 and earlier).\n *\n * Some code which uses this library might dynamically load multiple versions of it,\n * as well as old or duplicated versions of packages which produce or implement handles.\n * 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.\n *\n * 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.\n * At some point this might be removed or turned into an actual configuration option, but for now its really just documentation.\n */\nconst enableBackwardsCompatibility = true;\n\n/**\n * Check if a value is an IFluidHandle.\n * @remarks\n * Objects which have a field named `IFluidHandle` can in some cases produce a false positive.\n * @internal\n */\nexport function isFluidHandle(value: unknown): value is IFluidHandle {\n\t// `in` gives a type error on non-objects and null, so filter them out\n\tif (typeof value !== \"object\" || value === null) {\n\t\treturn false;\n\t}\n\tif (fluidHandleSymbol in value) {\n\t\treturn true;\n\t}\n\t// If enableBackwardsCompatibility, run check for FluidHandles predating use of fluidHandleSymbol.\n\tif (enableBackwardsCompatibility && IFluidHandle in value) {\n\t\t// Since this check can have false positives, make it a bit more robust by checking value[IFluidHandle][IFluidHandle]\n\t\tconst inner = value[IFluidHandle] as IFluidHandle;\n\t\tif (typeof inner !== \"object\" || inner === null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn IFluidHandle in inner;\n\t}\n\treturn false;\n}\n\n/**\n * Downcast an IFluidHandle to an IFluidHandleInternal.\n * @alpha\n */\nexport function toFluidHandleInternal<T>(handle: IFluidHandle<T>): IFluidHandleInternal<T> {\n\tif (!(fluidHandleSymbol in handle) || !(fluidHandleSymbol in handle[fluidHandleSymbol])) {\n\t\tif (enableBackwardsCompatibility && IFluidHandle in handle) {\n\t\t\treturn handle[IFluidHandle] as IFluidHandleInternal<T>;\n\t\t}\n\t\tthrow new TypeError(\"Invalid IFluidHandle\");\n\t}\n\n\t// This casts the IFluidHandleErased from the symbol instead of `handle` to ensure that if someone\n\t// implements their own IFluidHandle in terms of an existing handle, it won't break anything.\n\treturn handle[fluidHandleSymbol] as unknown as IFluidHandleInternal<T>;\n}\n\n/**\n * Type erase IFluidHandleInternal for use with {@link @fluidframework/core-interfaces#fluidHandleSymbol}.\n * @alpha\n */\nexport function toFluidHandleErased<T>(handle: IFluidHandleInternal<T>): IFluidHandleErased<T> {\n\treturn handle as unknown as IFluidHandleErased<T>;\n}\n\n/**\n * Base class which can be uses to assist implementing IFluidHandleInternal.\n * @alpha\n */\nexport abstract class FluidHandleBase<T> implements IFluidHandleInternal<T> {\n\tpublic abstract absolutePath: string;\n\tpublic abstract attachGraph(): void;\n\tpublic abstract bind(handle: IFluidHandleInternal): void;\n\tpublic abstract readonly isAttached: boolean;\n\tpublic abstract get(): Promise<T>;\n\n\t/**\n\t * {@inheritDoc @fluidframework/core-interfaces#IProvideFluidHandle.IFluidHandle}\n\t */\n\tpublic get IFluidHandle(): IFluidHandleInternal {\n\t\treturn this;\n\t}\n\n\tpublic get [fluidHandleSymbol](): IFluidHandleErased<T> {\n\t\treturn toFluidHandleErased(this);\n\t}\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { generateHandleContextPath } from "./dataStoreHandleContextUtils.js";
|
|
6
6
|
export { create404Response, createDataStoreFactory, createResponseError, exceptionToResponse, Factory, responseToException, } from "./dataStoreHelpers.js";
|
|
7
|
-
export { ISerializedHandle, isSerializedHandle } from "./handles.js";
|
|
7
|
+
export { ISerializedHandle, isSerializedHandle, isFluidHandle, toFluidHandleErased, toFluidHandleInternal, FluidHandleBase, } from "./handles.js";
|
|
8
8
|
export { ObjectStoragePartition } from "./objectstoragepartition.js";
|
|
9
9
|
export { getNormalizedObjectStoragePathParts, listBlobsAtTreePath } from "./objectstorageutils.js";
|
|
10
10
|
export { RequestParser } from "./requestParser.js";
|
|
@@ -12,4 +12,6 @@ export { RuntimeFactoryHelper } from "./runtimeFactoryHelper.js";
|
|
|
12
12
|
export { addBlobToSummary, addSummarizeResultToSummary, calculateStats, convertSnapshotTreeToSummaryTree, convertSummaryTreeToITree, convertToSummaryTree, convertToSummaryTreeWithStats, GCDataBuilder, getBlobSize, mergeStats, processAttachMessageGCData, SummaryTreeBuilder, TelemetryContext, utf8ByteLength, } from "./summaryUtils.js";
|
|
13
13
|
export { unpackChildNodesUsedRoutes } from "./unpackUsedRoutes.js";
|
|
14
14
|
export { ReadAndParseBlob, seqFromTree, encodeCompactIdToString } from "./utils.js";
|
|
15
|
+
export { isSnapshotFetchRequiredForLoadingGroupId } from "./snapshotUtils.js";
|
|
16
|
+
export { toDeltaManagerErased, toDeltaManagerInternal } from "./deltaManager.js";
|
|
15
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EACN,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,OAAO,EACP,mBAAmB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EACN,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,OAAO,EACP,mBAAmB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,mCAAmC,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnG,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EACN,gBAAgB,EAChB,2BAA2B,EAC3B,cAAc,EACd,gCAAgC,EAChC,yBAAyB,EACzB,oBAAoB,EACpB,6BAA6B,EAC7B,aAAa,EACb,WAAW,EACX,UAAU,EACV,0BAA0B,EAC1B,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,EAAE,wCAAwC,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.encodeCompactIdToString = exports.seqFromTree = exports.unpackChildNodesUsedRoutes = exports.utf8ByteLength = exports.TelemetryContext = exports.SummaryTreeBuilder = exports.processAttachMessageGCData = exports.mergeStats = exports.getBlobSize = exports.GCDataBuilder = exports.convertToSummaryTreeWithStats = exports.convertToSummaryTree = exports.convertSummaryTreeToITree = exports.convertSnapshotTreeToSummaryTree = exports.calculateStats = exports.addSummarizeResultToSummary = exports.addBlobToSummary = exports.RuntimeFactoryHelper = exports.RequestParser = exports.listBlobsAtTreePath = exports.getNormalizedObjectStoragePathParts = exports.ObjectStoragePartition = exports.isSerializedHandle = exports.responseToException = exports.exceptionToResponse = exports.createResponseError = exports.createDataStoreFactory = exports.create404Response = exports.generateHandleContextPath = void 0;
|
|
7
|
+
exports.toDeltaManagerInternal = exports.toDeltaManagerErased = exports.isSnapshotFetchRequiredForLoadingGroupId = exports.encodeCompactIdToString = exports.seqFromTree = exports.unpackChildNodesUsedRoutes = exports.utf8ByteLength = exports.TelemetryContext = exports.SummaryTreeBuilder = exports.processAttachMessageGCData = exports.mergeStats = exports.getBlobSize = exports.GCDataBuilder = exports.convertToSummaryTreeWithStats = exports.convertToSummaryTree = exports.convertSummaryTreeToITree = exports.convertSnapshotTreeToSummaryTree = exports.calculateStats = exports.addSummarizeResultToSummary = exports.addBlobToSummary = exports.RuntimeFactoryHelper = exports.RequestParser = exports.listBlobsAtTreePath = exports.getNormalizedObjectStoragePathParts = exports.ObjectStoragePartition = exports.FluidHandleBase = exports.toFluidHandleInternal = exports.toFluidHandleErased = exports.isFluidHandle = exports.isSerializedHandle = exports.responseToException = exports.exceptionToResponse = exports.createResponseError = exports.createDataStoreFactory = exports.create404Response = exports.generateHandleContextPath = void 0;
|
|
8
8
|
var dataStoreHandleContextUtils_js_1 = require("./dataStoreHandleContextUtils.js");
|
|
9
9
|
Object.defineProperty(exports, "generateHandleContextPath", { enumerable: true, get: function () { return dataStoreHandleContextUtils_js_1.generateHandleContextPath; } });
|
|
10
10
|
var dataStoreHelpers_js_1 = require("./dataStoreHelpers.js");
|
|
@@ -15,6 +15,10 @@ Object.defineProperty(exports, "exceptionToResponse", { enumerable: true, get: f
|
|
|
15
15
|
Object.defineProperty(exports, "responseToException", { enumerable: true, get: function () { return dataStoreHelpers_js_1.responseToException; } });
|
|
16
16
|
var handles_js_1 = require("./handles.js");
|
|
17
17
|
Object.defineProperty(exports, "isSerializedHandle", { enumerable: true, get: function () { return handles_js_1.isSerializedHandle; } });
|
|
18
|
+
Object.defineProperty(exports, "isFluidHandle", { enumerable: true, get: function () { return handles_js_1.isFluidHandle; } });
|
|
19
|
+
Object.defineProperty(exports, "toFluidHandleErased", { enumerable: true, get: function () { return handles_js_1.toFluidHandleErased; } });
|
|
20
|
+
Object.defineProperty(exports, "toFluidHandleInternal", { enumerable: true, get: function () { return handles_js_1.toFluidHandleInternal; } });
|
|
21
|
+
Object.defineProperty(exports, "FluidHandleBase", { enumerable: true, get: function () { return handles_js_1.FluidHandleBase; } });
|
|
18
22
|
var objectstoragepartition_js_1 = require("./objectstoragepartition.js");
|
|
19
23
|
Object.defineProperty(exports, "ObjectStoragePartition", { enumerable: true, get: function () { return objectstoragepartition_js_1.ObjectStoragePartition; } });
|
|
20
24
|
var objectstorageutils_js_1 = require("./objectstorageutils.js");
|
|
@@ -44,4 +48,9 @@ Object.defineProperty(exports, "unpackChildNodesUsedRoutes", { enumerable: true,
|
|
|
44
48
|
var utils_js_1 = require("./utils.js");
|
|
45
49
|
Object.defineProperty(exports, "seqFromTree", { enumerable: true, get: function () { return utils_js_1.seqFromTree; } });
|
|
46
50
|
Object.defineProperty(exports, "encodeCompactIdToString", { enumerable: true, get: function () { return utils_js_1.encodeCompactIdToString; } });
|
|
51
|
+
var snapshotUtils_js_1 = require("./snapshotUtils.js");
|
|
52
|
+
Object.defineProperty(exports, "isSnapshotFetchRequiredForLoadingGroupId", { enumerable: true, get: function () { return snapshotUtils_js_1.isSnapshotFetchRequiredForLoadingGroupId; } });
|
|
53
|
+
var deltaManager_js_1 = require("./deltaManager.js");
|
|
54
|
+
Object.defineProperty(exports, "toDeltaManagerErased", { enumerable: true, get: function () { return deltaManager_js_1.toDeltaManagerErased; } });
|
|
55
|
+
Object.defineProperty(exports, "toDeltaManagerInternal", { enumerable: true, get: function () { return deltaManager_js_1.toDeltaManagerInternal; } });
|
|
47
56
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,mFAA6E;AAApE,2IAAA,yBAAyB,OAAA;AAClC,6DAO+B;AAN9B,wHAAA,iBAAiB,OAAA;AACjB,6HAAA,sBAAsB,OAAA;AACtB,0HAAA,mBAAmB,OAAA;AACnB,0HAAA,mBAAmB,OAAA;AAEnB,0HAAA,mBAAmB,OAAA;AAEpB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,mFAA6E;AAApE,2IAAA,yBAAyB,OAAA;AAClC,6DAO+B;AAN9B,wHAAA,iBAAiB,OAAA;AACjB,6HAAA,sBAAsB,OAAA;AACtB,0HAAA,mBAAmB,OAAA;AACnB,0HAAA,mBAAmB,OAAA;AAEnB,0HAAA,mBAAmB,OAAA;AAEpB,2CAOsB;AALrB,gHAAA,kBAAkB,OAAA;AAClB,2GAAA,aAAa,OAAA;AACb,iHAAA,mBAAmB,OAAA;AACnB,mHAAA,qBAAqB,OAAA;AACrB,6GAAA,eAAe,OAAA;AAEhB,yEAAqE;AAA5D,mIAAA,sBAAsB,OAAA;AAC/B,iEAAmG;AAA1F,4IAAA,mCAAmC,OAAA;AAAE,4HAAA,mBAAmB,OAAA;AACjE,uDAAmD;AAA1C,iHAAA,aAAa,OAAA;AACtB,qEAAiE;AAAxD,+HAAA,oBAAoB,OAAA;AAC7B,qDAe2B;AAd1B,mHAAA,gBAAgB,OAAA;AAChB,8HAAA,2BAA2B,OAAA;AAC3B,iHAAA,cAAc,OAAA;AACd,mIAAA,gCAAgC,OAAA;AAChC,4HAAA,yBAAyB,OAAA;AACzB,uHAAA,oBAAoB,OAAA;AACpB,gIAAA,6BAA6B,OAAA;AAC7B,gHAAA,aAAa,OAAA;AACb,8GAAA,WAAW,OAAA;AACX,6GAAA,UAAU,OAAA;AACV,6HAAA,0BAA0B,OAAA;AAC1B,qHAAA,kBAAkB,OAAA;AAClB,mHAAA,gBAAgB,OAAA;AAChB,iHAAA,cAAc,OAAA;AAEf,6DAAmE;AAA1D,iIAAA,0BAA0B,OAAA;AACnC,uCAAoF;AAAzD,uGAAA,WAAW,OAAA;AAAE,mHAAA,uBAAuB,OAAA;AAC/D,uDAA8E;AAArE,4IAAA,wCAAwC,OAAA;AACjD,qDAAiF;AAAxE,uHAAA,oBAAoB,OAAA;AAAE,yHAAA,sBAAsB,OAAA","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport { generateHandleContextPath } from \"./dataStoreHandleContextUtils.js\";\nexport {\n\tcreate404Response,\n\tcreateDataStoreFactory,\n\tcreateResponseError,\n\texceptionToResponse,\n\tFactory,\n\tresponseToException,\n} from \"./dataStoreHelpers.js\";\nexport {\n\tISerializedHandle,\n\tisSerializedHandle,\n\tisFluidHandle,\n\ttoFluidHandleErased,\n\ttoFluidHandleInternal,\n\tFluidHandleBase,\n} from \"./handles.js\";\nexport { ObjectStoragePartition } from \"./objectstoragepartition.js\";\nexport { getNormalizedObjectStoragePathParts, listBlobsAtTreePath } from \"./objectstorageutils.js\";\nexport { RequestParser } from \"./requestParser.js\";\nexport { RuntimeFactoryHelper } from \"./runtimeFactoryHelper.js\";\nexport {\n\taddBlobToSummary,\n\taddSummarizeResultToSummary,\n\tcalculateStats,\n\tconvertSnapshotTreeToSummaryTree,\n\tconvertSummaryTreeToITree,\n\tconvertToSummaryTree,\n\tconvertToSummaryTreeWithStats,\n\tGCDataBuilder,\n\tgetBlobSize,\n\tmergeStats,\n\tprocessAttachMessageGCData,\n\tSummaryTreeBuilder,\n\tTelemetryContext,\n\tutf8ByteLength,\n} from \"./summaryUtils.js\";\nexport { unpackChildNodesUsedRoutes } from \"./unpackUsedRoutes.js\";\nexport { ReadAndParseBlob, seqFromTree, encodeCompactIdToString } from \"./utils.js\";\nexport { isSnapshotFetchRequiredForLoadingGroupId } from \"./snapshotUtils.js\";\nexport { toDeltaManagerErased, toDeltaManagerInternal } from \"./deltaManager.js\";\n"]}
|
package/dist/legacy.d.ts
CHANGED
|
@@ -9,10 +9,14 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
export {
|
|
12
|
-
// alpha APIs
|
|
12
|
+
// @alpha APIs
|
|
13
|
+
FluidHandleBase,
|
|
13
14
|
RequestParser,
|
|
14
15
|
RuntimeFactoryHelper,
|
|
15
16
|
SummaryTreeBuilder,
|
|
16
17
|
convertToSummaryTreeWithStats,
|
|
17
|
-
create404Response
|
|
18
|
+
create404Response,
|
|
19
|
+
toDeltaManagerInternal,
|
|
20
|
+
toFluidHandleErased,
|
|
21
|
+
toFluidHandleInternal
|
|
18
22
|
} from "./index.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import type { ISnapshotTree } from "@fluidframework/protocol-definitions";
|
|
6
|
+
/**
|
|
7
|
+
* Utility function to check if any blobs under a snapshot tree is missing and if so, then return
|
|
8
|
+
* true if that is the case.
|
|
9
|
+
* @internal
|
|
10
|
+
* @param snapshotTree - snapshotTree to be evaluated for missing blobs.
|
|
11
|
+
* @param blobContents - blobContents of the snapshot.
|
|
12
|
+
*/
|
|
13
|
+
export declare function isSnapshotFetchRequiredForLoadingGroupId(snapshotTree: ISnapshotTree, blobContents: Map<string, ArrayBuffer>): boolean;
|
|
14
|
+
//# sourceMappingURL=snapshotUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshotUtils.d.ts","sourceRoot":"","sources":["../src/snapshotUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAE1E;;;;;;GAMG;AACH,wBAAgB,wCAAwC,CACvD,YAAY,EAAE,aAAa,EAC3B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GACpC,OAAO,CAoBT"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.isSnapshotFetchRequiredForLoadingGroupId = void 0;
|
|
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
|
+
function isSnapshotFetchRequiredForLoadingGroupId(snapshotTree, blobContents) {
|
|
16
|
+
for (const [_, id] of Object.entries(snapshotTree.blobs)) {
|
|
17
|
+
if (!blobContents.has(id)) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
for (const [_, childTree] of Object.entries(snapshotTree.trees)) {
|
|
22
|
+
// Only evaluate childTree if it does not have a loading groupId because if the childTree has a loading
|
|
23
|
+
// groupId then it will be evaluated whether we want to fetch blobs for that childTree or not when
|
|
24
|
+
// that particular childTree is getting realized. Now we just want to check for blobs which belongs to
|
|
25
|
+
// tree with current loading groupId. Note: Child with no loading groupId, will fall under parent with
|
|
26
|
+
// a loading groupId as it does not have its own loading groupId.
|
|
27
|
+
if (childTree.groupId === undefined) {
|
|
28
|
+
const value = isSnapshotFetchRequiredForLoadingGroupId(childTree, blobContents);
|
|
29
|
+
if (value) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
exports.isSnapshotFetchRequiredForLoadingGroupId = isSnapshotFetchRequiredForLoadingGroupId;
|
|
37
|
+
//# sourceMappingURL=snapshotUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshotUtils.js","sourceRoot":"","sources":["../src/snapshotUtils.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIH;;;;;;GAMG;AACH,SAAgB,wCAAwC,CACvD,YAA2B,EAC3B,YAAsC;IAEtC,KAAK,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE;QACzD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAC1B,OAAO,IAAI,CAAC;SACZ;KACD;IACD,KAAK,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE;QAChE,uGAAuG;QACvG,kGAAkG;QAClG,sGAAsG;QACtG,sGAAsG;QACtG,iEAAiE;QACjE,IAAI,SAAS,CAAC,OAAO,KAAK,SAAS,EAAE;YACpC,MAAM,KAAK,GAAG,wCAAwC,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;YAChF,IAAI,KAAK,EAAE;gBACV,OAAO,IAAI,CAAC;aACZ;SACD;KACD;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAvBD,4FAuBC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\n\n/**\n * Utility function to check if any blobs under a snapshot tree is missing and if so, then return\n * true if that is the case.\n * @internal\n * @param snapshotTree - snapshotTree to be evaluated for missing blobs.\n * @param blobContents - blobContents of the snapshot.\n */\nexport function isSnapshotFetchRequiredForLoadingGroupId(\n\tsnapshotTree: ISnapshotTree,\n\tblobContents: Map<string, ArrayBuffer>,\n): boolean {\n\tfor (const [_, id] of Object.entries(snapshotTree.blobs)) {\n\t\tif (!blobContents.has(id)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\tfor (const [_, childTree] of Object.entries(snapshotTree.trees)) {\n\t\t// Only evaluate childTree if it does not have a loading groupId because if the childTree has a loading\n\t\t// groupId then it will be evaluated whether we want to fetch blobs for that childTree or not when\n\t\t// that particular childTree is getting realized. Now we just want to check for blobs which belongs to\n\t\t// tree with current loading groupId. Note: Child with no loading groupId, will fall under parent with\n\t\t// a loading groupId as it does not have its own loading groupId.\n\t\tif (childTree.groupId === undefined) {\n\t\t\tconst value = isSnapshotFetchRequiredForLoadingGroupId(childTree, blobContents);\n\t\t\tif (value) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import type { IDeltaManager } from "@fluidframework/container-definitions/internal";
|
|
6
|
+
import type { IDeltaManagerErased } from "@fluidframework/datastore-definitions";
|
|
7
|
+
import type { IDocumentMessage, ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
|
8
|
+
/**
|
|
9
|
+
* Casts the public API for delta manager into the internal one,
|
|
10
|
+
* exposing access to APIs needed by the implementation of Fluid Framework but not its users.
|
|
11
|
+
* @alpha
|
|
12
|
+
*/
|
|
13
|
+
export declare function toDeltaManagerInternal(deltaManager: IDeltaManagerErased): IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;
|
|
14
|
+
/**
|
|
15
|
+
* Casts the the internal API for delta manager into the public type erased API for returning from public APIs that should not have access to any of its members.
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export declare function toDeltaManagerErased(deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>): IDeltaManagerErased;
|
|
19
|
+
//# sourceMappingURL=deltaManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deltaManager.d.ts","sourceRoot":"","sources":["../src/deltaManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAC;AACpF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AACjF,OAAO,KAAK,EACX,gBAAgB,EAChB,yBAAyB,EACzB,MAAM,sCAAsC,CAAC;AAE9C;;;;GAIG;AACH,wBAAgB,sBAAsB,CACrC,YAAY,EAAE,mBAAmB,GAC/B,aAAa,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,CAE5D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CACnC,YAAY,EAAE,aAAa,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,GACtE,mBAAmB,CAErB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Casts the public API for delta manager into the internal one,
|
|
7
|
+
* exposing access to APIs needed by the implementation of Fluid Framework but not its users.
|
|
8
|
+
* @alpha
|
|
9
|
+
*/
|
|
10
|
+
export function toDeltaManagerInternal(deltaManager) {
|
|
11
|
+
return deltaManager;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Casts the the internal API for delta manager into the public type erased API for returning from public APIs that should not have access to any of its members.
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export function toDeltaManagerErased(deltaManager) {
|
|
18
|
+
return deltaManager;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=deltaManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deltaManager.js","sourceRoot":"","sources":["../src/deltaManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACrC,YAAiC;IAEjC,OAAO,YAAqF,CAAC;AAC9F,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CACnC,YAAwE;IAExE,OAAO,YAA8C,CAAC;AACvD,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IDeltaManager } from \"@fluidframework/container-definitions/internal\";\nimport type { IDeltaManagerErased } from \"@fluidframework/datastore-definitions\";\nimport type {\n\tIDocumentMessage,\n\tISequencedDocumentMessage,\n} from \"@fluidframework/protocol-definitions\";\n\n/**\n * Casts the public API for delta manager into the internal one,\n * exposing access to APIs needed by the implementation of Fluid Framework but not its users.\n * @alpha\n */\nexport function toDeltaManagerInternal(\n\tdeltaManager: IDeltaManagerErased,\n): IDeltaManager<ISequencedDocumentMessage, IDocumentMessage> {\n\treturn deltaManager as unknown as IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;\n}\n\n/**\n * Casts the the internal API for delta manager into the public type erased API for returning from public APIs that should not have access to any of its members.\n * @internal\n */\nexport function toDeltaManagerErased(\n\tdeltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,\n): IDeltaManagerErased {\n\treturn deltaManager as unknown as IDeltaManagerErased;\n}\n"]}
|
package/lib/handles.d.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
+
import type { IFluidHandleErased, IFluidHandleInternal } from "@fluidframework/core-interfaces/internal";
|
|
6
|
+
import { IFluidHandle, fluidHandleSymbol } from "@fluidframework/core-interfaces";
|
|
5
7
|
/**
|
|
6
8
|
* JSON serialized form of an IFluidHandle
|
|
7
9
|
* @internal
|
|
@@ -15,4 +17,37 @@ export interface ISerializedHandle {
|
|
|
15
17
|
* @internal
|
|
16
18
|
*/
|
|
17
19
|
export declare const isSerializedHandle: (value: any) => value is ISerializedHandle;
|
|
20
|
+
/**
|
|
21
|
+
* Check if a value is an IFluidHandle.
|
|
22
|
+
* @remarks
|
|
23
|
+
* Objects which have a field named `IFluidHandle` can in some cases produce a false positive.
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
26
|
+
export declare function isFluidHandle(value: unknown): value is IFluidHandle;
|
|
27
|
+
/**
|
|
28
|
+
* Downcast an IFluidHandle to an IFluidHandleInternal.
|
|
29
|
+
* @alpha
|
|
30
|
+
*/
|
|
31
|
+
export declare function toFluidHandleInternal<T>(handle: IFluidHandle<T>): IFluidHandleInternal<T>;
|
|
32
|
+
/**
|
|
33
|
+
* Type erase IFluidHandleInternal for use with {@link @fluidframework/core-interfaces#fluidHandleSymbol}.
|
|
34
|
+
* @alpha
|
|
35
|
+
*/
|
|
36
|
+
export declare function toFluidHandleErased<T>(handle: IFluidHandleInternal<T>): IFluidHandleErased<T>;
|
|
37
|
+
/**
|
|
38
|
+
* Base class which can be uses to assist implementing IFluidHandleInternal.
|
|
39
|
+
* @alpha
|
|
40
|
+
*/
|
|
41
|
+
export declare abstract class FluidHandleBase<T> implements IFluidHandleInternal<T> {
|
|
42
|
+
abstract absolutePath: string;
|
|
43
|
+
abstract attachGraph(): void;
|
|
44
|
+
abstract bind(handle: IFluidHandleInternal): void;
|
|
45
|
+
abstract readonly isAttached: boolean;
|
|
46
|
+
abstract get(): Promise<T>;
|
|
47
|
+
/**
|
|
48
|
+
* {@inheritDoc @fluidframework/core-interfaces#IProvideFluidHandle.IFluidHandle}
|
|
49
|
+
*/
|
|
50
|
+
get IFluidHandle(): IFluidHandleInternal;
|
|
51
|
+
get [fluidHandleSymbol](): IFluidHandleErased<T>;
|
|
52
|
+
}
|
|
18
53
|
//# sourceMappingURL=handles.d.ts.map
|
package/lib/handles.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handles.d.ts","sourceRoot":"","sources":["../src/handles.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAEjC,IAAI,EAAE,kBAAkB,CAAC;IAGzB,GAAG,EAAE,MAAM,CAAC;CACZ;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,UAAW,GAAG,+BACV,CAAC"}
|
|
1
|
+
{"version":3,"file":"handles.d.ts","sourceRoot":"","sources":["../src/handles.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,kBAAkB,EAClB,oBAAoB,EACpB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAElF;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAEjC,IAAI,EAAE,kBAAkB,CAAC;IAGzB,GAAG,EAAE,MAAM,CAAC;CACZ;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,UAAW,GAAG,+BACV,CAAC;AAcpC;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAkBnE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAWzF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAE7F;AAED;;;GAGG;AACH,8BAAsB,eAAe,CAAC,CAAC,CAAE,YAAW,oBAAoB,CAAC,CAAC,CAAC;IAC1E,SAAgB,YAAY,EAAE,MAAM,CAAC;aACrB,WAAW,IAAI,IAAI;aACnB,IAAI,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI;IACxD,kBAAyB,UAAU,EAAE,OAAO,CAAC;aAC7B,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC;IAEjC;;OAEG;IACH,IAAW,YAAY,IAAI,oBAAoB,CAE9C;IAED,IAAW,CAAC,iBAAiB,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,CAEtD;CACD"}
|
package/lib/handles.js
CHANGED
|
@@ -2,9 +2,83 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
+
import { IFluidHandle, fluidHandleSymbol } from "@fluidframework/core-interfaces";
|
|
5
6
|
/**
|
|
6
7
|
* Is the input object a @see ISerializedHandle?
|
|
7
8
|
* @internal
|
|
8
9
|
*/
|
|
9
10
|
export const isSerializedHandle = (value) => value?.type === "__fluid_handle__";
|
|
11
|
+
/**
|
|
12
|
+
* Setting to opt into compatibility with handles from before {@link fluidHandleSymbol} existed (Fluid Framework client 2.0.0-rc.3.0.0 and earlier).
|
|
13
|
+
*
|
|
14
|
+
* Some code which uses this library might dynamically load multiple versions of it,
|
|
15
|
+
* as well as old or duplicated versions of packages which produce or implement handles.
|
|
16
|
+
* 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.
|
|
17
|
+
*
|
|
18
|
+
* 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.
|
|
19
|
+
* At some point this might be removed or turned into an actual configuration option, but for now its really just documentation.
|
|
20
|
+
*/
|
|
21
|
+
const enableBackwardsCompatibility = true;
|
|
22
|
+
/**
|
|
23
|
+
* Check if a value is an IFluidHandle.
|
|
24
|
+
* @remarks
|
|
25
|
+
* Objects which have a field named `IFluidHandle` can in some cases produce a false positive.
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
export function isFluidHandle(value) {
|
|
29
|
+
// `in` gives a type error on non-objects and null, so filter them out
|
|
30
|
+
if (typeof value !== "object" || value === null) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
if (fluidHandleSymbol in value) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
// If enableBackwardsCompatibility, run check for FluidHandles predating use of fluidHandleSymbol.
|
|
37
|
+
if (enableBackwardsCompatibility && IFluidHandle in value) {
|
|
38
|
+
// Since this check can have false positives, make it a bit more robust by checking value[IFluidHandle][IFluidHandle]
|
|
39
|
+
const inner = value[IFluidHandle];
|
|
40
|
+
if (typeof inner !== "object" || inner === null) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return IFluidHandle in inner;
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Downcast an IFluidHandle to an IFluidHandleInternal.
|
|
49
|
+
* @alpha
|
|
50
|
+
*/
|
|
51
|
+
export function toFluidHandleInternal(handle) {
|
|
52
|
+
if (!(fluidHandleSymbol in handle) || !(fluidHandleSymbol in handle[fluidHandleSymbol])) {
|
|
53
|
+
if (enableBackwardsCompatibility && IFluidHandle in handle) {
|
|
54
|
+
return handle[IFluidHandle];
|
|
55
|
+
}
|
|
56
|
+
throw new TypeError("Invalid IFluidHandle");
|
|
57
|
+
}
|
|
58
|
+
// This casts the IFluidHandleErased from the symbol instead of `handle` to ensure that if someone
|
|
59
|
+
// implements their own IFluidHandle in terms of an existing handle, it won't break anything.
|
|
60
|
+
return handle[fluidHandleSymbol];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Type erase IFluidHandleInternal for use with {@link @fluidframework/core-interfaces#fluidHandleSymbol}.
|
|
64
|
+
* @alpha
|
|
65
|
+
*/
|
|
66
|
+
export function toFluidHandleErased(handle) {
|
|
67
|
+
return handle;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Base class which can be uses to assist implementing IFluidHandleInternal.
|
|
71
|
+
* @alpha
|
|
72
|
+
*/
|
|
73
|
+
export class FluidHandleBase {
|
|
74
|
+
/**
|
|
75
|
+
* {@inheritDoc @fluidframework/core-interfaces#IProvideFluidHandle.IFluidHandle}
|
|
76
|
+
*/
|
|
77
|
+
get IFluidHandle() {
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
get [fluidHandleSymbol]() {
|
|
81
|
+
return toFluidHandleErased(this);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
10
84
|
//# sourceMappingURL=handles.js.map
|
package/lib/handles.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handles.js","sourceRoot":"","sources":["../src/handles.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"handles.js","sourceRoot":"","sources":["../src/handles.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAclF;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAU,EAA8B,EAAE,CAC5E,KAAK,EAAE,IAAI,KAAK,kBAAkB,CAAC;AAEpC;;;;;;;;;GASG;AACH,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAE1C;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IAC3C,sEAAsE;IACtE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE;QAChD,OAAO,KAAK,CAAC;KACb;IACD,IAAI,iBAAiB,IAAI,KAAK,EAAE;QAC/B,OAAO,IAAI,CAAC;KACZ;IACD,kGAAkG;IAClG,IAAI,4BAA4B,IAAI,YAAY,IAAI,KAAK,EAAE;QAC1D,qHAAqH;QACrH,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,CAAiB,CAAC;QAClD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE;YAChD,OAAO,KAAK,CAAC;SACb;QACD,OAAO,YAAY,IAAI,KAAK,CAAC;KAC7B;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAI,MAAuB;IAC/D,IAAI,CAAC,CAAC,iBAAiB,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,iBAAiB,IAAI,MAAM,CAAC,iBAAiB,CAAC,CAAC,EAAE;QACxF,IAAI,4BAA4B,IAAI,YAAY,IAAI,MAAM,EAAE;YAC3D,OAAO,MAAM,CAAC,YAAY,CAA4B,CAAC;SACvD;QACD,MAAM,IAAI,SAAS,CAAC,sBAAsB,CAAC,CAAC;KAC5C;IAED,kGAAkG;IAClG,6FAA6F;IAC7F,OAAO,MAAM,CAAC,iBAAiB,CAAuC,CAAC;AACxE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAI,MAA+B;IACrE,OAAO,MAA0C,CAAC;AACnD,CAAC;AAED;;;GAGG;AACH,MAAM,OAAgB,eAAe;IAOpC;;OAEG;IACH,IAAW,YAAY;QACtB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,IAAW,CAAC,iBAAiB,CAAC;QAC7B,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tIFluidHandleErased,\n\tIFluidHandleInternal,\n} from \"@fluidframework/core-interfaces/internal\";\nimport { IFluidHandle, fluidHandleSymbol } from \"@fluidframework/core-interfaces\";\n\n/**\n * JSON serialized form of an IFluidHandle\n * @internal\n */\nexport interface ISerializedHandle {\n\t// Marker to indicate to JSON.parse that the object is a Fluid handle\n\ttype: \"__fluid_handle__\";\n\n\t// URL to the object. Relative URLs are relative to the handle context passed to the stringify.\n\turl: string;\n}\n\n/**\n * Is the input object a @see ISerializedHandle?\n * @internal\n */\nexport const isSerializedHandle = (value: any): value is ISerializedHandle =>\n\tvalue?.type === \"__fluid_handle__\";\n\n/**\n * Setting to opt into compatibility with handles from before {@link fluidHandleSymbol} existed (Fluid Framework client 2.0.0-rc.3.0.0 and earlier).\n *\n * Some code which uses this library might dynamically load multiple versions of it,\n * as well as old or duplicated versions of packages which produce or implement handles.\n * 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.\n *\n * 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.\n * At some point this might be removed or turned into an actual configuration option, but for now its really just documentation.\n */\nconst enableBackwardsCompatibility = true;\n\n/**\n * Check if a value is an IFluidHandle.\n * @remarks\n * Objects which have a field named `IFluidHandle` can in some cases produce a false positive.\n * @internal\n */\nexport function isFluidHandle(value: unknown): value is IFluidHandle {\n\t// `in` gives a type error on non-objects and null, so filter them out\n\tif (typeof value !== \"object\" || value === null) {\n\t\treturn false;\n\t}\n\tif (fluidHandleSymbol in value) {\n\t\treturn true;\n\t}\n\t// If enableBackwardsCompatibility, run check for FluidHandles predating use of fluidHandleSymbol.\n\tif (enableBackwardsCompatibility && IFluidHandle in value) {\n\t\t// Since this check can have false positives, make it a bit more robust by checking value[IFluidHandle][IFluidHandle]\n\t\tconst inner = value[IFluidHandle] as IFluidHandle;\n\t\tif (typeof inner !== \"object\" || inner === null) {\n\t\t\treturn false;\n\t\t}\n\t\treturn IFluidHandle in inner;\n\t}\n\treturn false;\n}\n\n/**\n * Downcast an IFluidHandle to an IFluidHandleInternal.\n * @alpha\n */\nexport function toFluidHandleInternal<T>(handle: IFluidHandle<T>): IFluidHandleInternal<T> {\n\tif (!(fluidHandleSymbol in handle) || !(fluidHandleSymbol in handle[fluidHandleSymbol])) {\n\t\tif (enableBackwardsCompatibility && IFluidHandle in handle) {\n\t\t\treturn handle[IFluidHandle] as IFluidHandleInternal<T>;\n\t\t}\n\t\tthrow new TypeError(\"Invalid IFluidHandle\");\n\t}\n\n\t// This casts the IFluidHandleErased from the symbol instead of `handle` to ensure that if someone\n\t// implements their own IFluidHandle in terms of an existing handle, it won't break anything.\n\treturn handle[fluidHandleSymbol] as unknown as IFluidHandleInternal<T>;\n}\n\n/**\n * Type erase IFluidHandleInternal for use with {@link @fluidframework/core-interfaces#fluidHandleSymbol}.\n * @alpha\n */\nexport function toFluidHandleErased<T>(handle: IFluidHandleInternal<T>): IFluidHandleErased<T> {\n\treturn handle as unknown as IFluidHandleErased<T>;\n}\n\n/**\n * Base class which can be uses to assist implementing IFluidHandleInternal.\n * @alpha\n */\nexport abstract class FluidHandleBase<T> implements IFluidHandleInternal<T> {\n\tpublic abstract absolutePath: string;\n\tpublic abstract attachGraph(): void;\n\tpublic abstract bind(handle: IFluidHandleInternal): void;\n\tpublic abstract readonly isAttached: boolean;\n\tpublic abstract get(): Promise<T>;\n\n\t/**\n\t * {@inheritDoc @fluidframework/core-interfaces#IProvideFluidHandle.IFluidHandle}\n\t */\n\tpublic get IFluidHandle(): IFluidHandleInternal {\n\t\treturn this;\n\t}\n\n\tpublic get [fluidHandleSymbol](): IFluidHandleErased<T> {\n\t\treturn toFluidHandleErased(this);\n\t}\n}\n"]}
|
package/lib/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { generateHandleContextPath } from "./dataStoreHandleContextUtils.js";
|
|
6
6
|
export { create404Response, createDataStoreFactory, createResponseError, exceptionToResponse, Factory, responseToException, } from "./dataStoreHelpers.js";
|
|
7
|
-
export { ISerializedHandle, isSerializedHandle } from "./handles.js";
|
|
7
|
+
export { ISerializedHandle, isSerializedHandle, isFluidHandle, toFluidHandleErased, toFluidHandleInternal, FluidHandleBase, } from "./handles.js";
|
|
8
8
|
export { ObjectStoragePartition } from "./objectstoragepartition.js";
|
|
9
9
|
export { getNormalizedObjectStoragePathParts, listBlobsAtTreePath } from "./objectstorageutils.js";
|
|
10
10
|
export { RequestParser } from "./requestParser.js";
|
|
@@ -12,4 +12,6 @@ export { RuntimeFactoryHelper } from "./runtimeFactoryHelper.js";
|
|
|
12
12
|
export { addBlobToSummary, addSummarizeResultToSummary, calculateStats, convertSnapshotTreeToSummaryTree, convertSummaryTreeToITree, convertToSummaryTree, convertToSummaryTreeWithStats, GCDataBuilder, getBlobSize, mergeStats, processAttachMessageGCData, SummaryTreeBuilder, TelemetryContext, utf8ByteLength, } from "./summaryUtils.js";
|
|
13
13
|
export { unpackChildNodesUsedRoutes } from "./unpackUsedRoutes.js";
|
|
14
14
|
export { ReadAndParseBlob, seqFromTree, encodeCompactIdToString } from "./utils.js";
|
|
15
|
+
export { isSnapshotFetchRequiredForLoadingGroupId } from "./snapshotUtils.js";
|
|
16
|
+
export { toDeltaManagerErased, toDeltaManagerInternal } from "./deltaManager.js";
|
|
15
17
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EACN,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,OAAO,EACP,mBAAmB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EACN,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,OAAO,EACP,mBAAmB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,mCAAmC,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnG,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EACN,gBAAgB,EAChB,2BAA2B,EAC3B,cAAc,EACd,gCAAgC,EAChC,yBAAyB,EACzB,oBAAoB,EACpB,6BAA6B,EAC7B,aAAa,EACb,WAAW,EACX,UAAU,EACV,0BAA0B,EAC1B,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,EAAE,wCAAwC,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { generateHandleContextPath } from "./dataStoreHandleContextUtils.js";
|
|
6
6
|
export { create404Response, createDataStoreFactory, createResponseError, exceptionToResponse, responseToException, } from "./dataStoreHelpers.js";
|
|
7
|
-
export { isSerializedHandle } from "./handles.js";
|
|
7
|
+
export { isSerializedHandle, isFluidHandle, toFluidHandleErased, toFluidHandleInternal, FluidHandleBase, } from "./handles.js";
|
|
8
8
|
export { ObjectStoragePartition } from "./objectstoragepartition.js";
|
|
9
9
|
export { getNormalizedObjectStoragePathParts, listBlobsAtTreePath } from "./objectstorageutils.js";
|
|
10
10
|
export { RequestParser } from "./requestParser.js";
|
|
@@ -12,4 +12,6 @@ export { RuntimeFactoryHelper } from "./runtimeFactoryHelper.js";
|
|
|
12
12
|
export { addBlobToSummary, addSummarizeResultToSummary, calculateStats, convertSnapshotTreeToSummaryTree, convertSummaryTreeToITree, convertToSummaryTree, convertToSummaryTreeWithStats, GCDataBuilder, getBlobSize, mergeStats, processAttachMessageGCData, SummaryTreeBuilder, TelemetryContext, utf8ByteLength, } from "./summaryUtils.js";
|
|
13
13
|
export { unpackChildNodesUsedRoutes } from "./unpackUsedRoutes.js";
|
|
14
14
|
export { seqFromTree, encodeCompactIdToString } from "./utils.js";
|
|
15
|
+
export { isSnapshotFetchRequiredForLoadingGroupId } from "./snapshotUtils.js";
|
|
16
|
+
export { toDeltaManagerErased, toDeltaManagerInternal } from "./deltaManager.js";
|
|
15
17
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EACN,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EAEnB,mBAAmB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EACN,iBAAiB,EACjB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EAEnB,mBAAmB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEN,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,qBAAqB,EACrB,eAAe,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,mCAAmC,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnG,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EACN,gBAAgB,EAChB,2BAA2B,EAC3B,cAAc,EACd,gCAAgC,EAChC,yBAAyB,EACzB,oBAAoB,EACpB,6BAA6B,EAC7B,aAAa,EACb,WAAW,EACX,UAAU,EACV,0BAA0B,EAC1B,kBAAkB,EAClB,gBAAgB,EAChB,cAAc,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAoB,WAAW,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,EAAE,wCAAwC,EAAE,MAAM,oBAAoB,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport { generateHandleContextPath } from \"./dataStoreHandleContextUtils.js\";\nexport {\n\tcreate404Response,\n\tcreateDataStoreFactory,\n\tcreateResponseError,\n\texceptionToResponse,\n\tFactory,\n\tresponseToException,\n} from \"./dataStoreHelpers.js\";\nexport {\n\tISerializedHandle,\n\tisSerializedHandle,\n\tisFluidHandle,\n\ttoFluidHandleErased,\n\ttoFluidHandleInternal,\n\tFluidHandleBase,\n} from \"./handles.js\";\nexport { ObjectStoragePartition } from \"./objectstoragepartition.js\";\nexport { getNormalizedObjectStoragePathParts, listBlobsAtTreePath } from \"./objectstorageutils.js\";\nexport { RequestParser } from \"./requestParser.js\";\nexport { RuntimeFactoryHelper } from \"./runtimeFactoryHelper.js\";\nexport {\n\taddBlobToSummary,\n\taddSummarizeResultToSummary,\n\tcalculateStats,\n\tconvertSnapshotTreeToSummaryTree,\n\tconvertSummaryTreeToITree,\n\tconvertToSummaryTree,\n\tconvertToSummaryTreeWithStats,\n\tGCDataBuilder,\n\tgetBlobSize,\n\tmergeStats,\n\tprocessAttachMessageGCData,\n\tSummaryTreeBuilder,\n\tTelemetryContext,\n\tutf8ByteLength,\n} from \"./summaryUtils.js\";\nexport { unpackChildNodesUsedRoutes } from \"./unpackUsedRoutes.js\";\nexport { ReadAndParseBlob, seqFromTree, encodeCompactIdToString } from \"./utils.js\";\nexport { isSnapshotFetchRequiredForLoadingGroupId } from \"./snapshotUtils.js\";\nexport { toDeltaManagerErased, toDeltaManagerInternal } from \"./deltaManager.js\";\n"]}
|
package/lib/legacy.d.ts
CHANGED
|
@@ -9,10 +9,14 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
export {
|
|
12
|
-
// alpha APIs
|
|
12
|
+
// @alpha APIs
|
|
13
|
+
FluidHandleBase,
|
|
13
14
|
RequestParser,
|
|
14
15
|
RuntimeFactoryHelper,
|
|
15
16
|
SummaryTreeBuilder,
|
|
16
17
|
convertToSummaryTreeWithStats,
|
|
17
|
-
create404Response
|
|
18
|
+
create404Response,
|
|
19
|
+
toDeltaManagerInternal,
|
|
20
|
+
toFluidHandleErased,
|
|
21
|
+
toFluidHandleInternal
|
|
18
22
|
} from "./index.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
import type { ISnapshotTree } from "@fluidframework/protocol-definitions";
|
|
6
|
+
/**
|
|
7
|
+
* Utility function to check if any blobs under a snapshot tree is missing and if so, then return
|
|
8
|
+
* true if that is the case.
|
|
9
|
+
* @internal
|
|
10
|
+
* @param snapshotTree - snapshotTree to be evaluated for missing blobs.
|
|
11
|
+
* @param blobContents - blobContents of the snapshot.
|
|
12
|
+
*/
|
|
13
|
+
export declare function isSnapshotFetchRequiredForLoadingGroupId(snapshotTree: ISnapshotTree, blobContents: Map<string, ArrayBuffer>): boolean;
|
|
14
|
+
//# sourceMappingURL=snapshotUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshotUtils.d.ts","sourceRoot":"","sources":["../src/snapshotUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAE1E;;;;;;GAMG;AACH,wBAAgB,wCAAwC,CACvD,YAAY,EAAE,aAAa,EAC3B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GACpC,OAAO,CAoBT"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Utility function to check if any blobs under a snapshot tree is missing and if so, then return
|
|
7
|
+
* true if that is the case.
|
|
8
|
+
* @internal
|
|
9
|
+
* @param snapshotTree - snapshotTree to be evaluated for missing blobs.
|
|
10
|
+
* @param blobContents - blobContents of the snapshot.
|
|
11
|
+
*/
|
|
12
|
+
export function isSnapshotFetchRequiredForLoadingGroupId(snapshotTree, blobContents) {
|
|
13
|
+
for (const [_, id] of Object.entries(snapshotTree.blobs)) {
|
|
14
|
+
if (!blobContents.has(id)) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
for (const [_, childTree] of Object.entries(snapshotTree.trees)) {
|
|
19
|
+
// Only evaluate childTree if it does not have a loading groupId because if the childTree has a loading
|
|
20
|
+
// groupId then it will be evaluated whether we want to fetch blobs for that childTree or not when
|
|
21
|
+
// that particular childTree is getting realized. Now we just want to check for blobs which belongs to
|
|
22
|
+
// tree with current loading groupId. Note: Child with no loading groupId, will fall under parent with
|
|
23
|
+
// a loading groupId as it does not have its own loading groupId.
|
|
24
|
+
if (childTree.groupId === undefined) {
|
|
25
|
+
const value = isSnapshotFetchRequiredForLoadingGroupId(childTree, blobContents);
|
|
26
|
+
if (value) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=snapshotUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshotUtils.js","sourceRoot":"","sources":["../src/snapshotUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;;;GAMG;AACH,MAAM,UAAU,wCAAwC,CACvD,YAA2B,EAC3B,YAAsC;IAEtC,KAAK,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE;QACzD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAC1B,OAAO,IAAI,CAAC;SACZ;KACD;IACD,KAAK,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE;QAChE,uGAAuG;QACvG,kGAAkG;QAClG,sGAAsG;QACtG,sGAAsG;QACtG,iEAAiE;QACjE,IAAI,SAAS,CAAC,OAAO,KAAK,SAAS,EAAE;YACpC,MAAM,KAAK,GAAG,wCAAwC,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;YAChF,IAAI,KAAK,EAAE;gBACV,OAAO,IAAI,CAAC;aACZ;SACD;KACD;IACD,OAAO,KAAK,CAAC;AACd,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ISnapshotTree } from \"@fluidframework/protocol-definitions\";\n\n/**\n * Utility function to check if any blobs under a snapshot tree is missing and if so, then return\n * true if that is the case.\n * @internal\n * @param snapshotTree - snapshotTree to be evaluated for missing blobs.\n * @param blobContents - blobContents of the snapshot.\n */\nexport function isSnapshotFetchRequiredForLoadingGroupId(\n\tsnapshotTree: ISnapshotTree,\n\tblobContents: Map<string, ArrayBuffer>,\n): boolean {\n\tfor (const [_, id] of Object.entries(snapshotTree.blobs)) {\n\t\tif (!blobContents.has(id)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\tfor (const [_, childTree] of Object.entries(snapshotTree.trees)) {\n\t\t// Only evaluate childTree if it does not have a loading groupId because if the childTree has a loading\n\t\t// groupId then it will be evaluated whether we want to fetch blobs for that childTree or not when\n\t\t// that particular childTree is getting realized. Now we just want to check for blobs which belongs to\n\t\t// tree with current loading groupId. Note: Child with no loading groupId, will fall under parent with\n\t\t// a loading groupId as it does not have its own loading groupId.\n\t\tif (childTree.groupId === undefined) {\n\t\t\tconst value = isSnapshotFetchRequiredForLoadingGroupId(childTree, blobContents);\n\t\t\tif (value) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n"]}
|
package/lib/tsdoc-metadata.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/runtime-utils",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
3
|
+
"version": "2.0.0-rc.4.0.0",
|
|
4
4
|
"description": "Collection of utility functions for Fluid Runtime",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -67,27 +67,27 @@
|
|
|
67
67
|
"temp-directory": "nyc/.nyc_output"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@fluid-internal/client-utils": ">=2.0.0-rc.
|
|
71
|
-
"@fluidframework/container-definitions": ">=2.0.0-rc.
|
|
72
|
-
"@fluidframework/container-runtime-definitions": ">=2.0.0-rc.
|
|
73
|
-
"@fluidframework/core-interfaces": ">=2.0.0-rc.
|
|
74
|
-
"@fluidframework/core-utils": ">=2.0.0-rc.
|
|
75
|
-
"@fluidframework/datastore-definitions": ">=2.0.0-rc.
|
|
76
|
-
"@fluidframework/driver-utils": ">=2.0.0-rc.
|
|
70
|
+
"@fluid-internal/client-utils": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
71
|
+
"@fluidframework/container-definitions": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
72
|
+
"@fluidframework/container-runtime-definitions": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
73
|
+
"@fluidframework/core-interfaces": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
74
|
+
"@fluidframework/core-utils": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
75
|
+
"@fluidframework/datastore-definitions": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
76
|
+
"@fluidframework/driver-utils": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
77
77
|
"@fluidframework/protocol-definitions": "^3.2.0",
|
|
78
|
-
"@fluidframework/runtime-definitions": ">=2.0.0-rc.
|
|
79
|
-
"@fluidframework/telemetry-utils": ">=2.0.0-rc.
|
|
78
|
+
"@fluidframework/runtime-definitions": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
79
|
+
"@fluidframework/telemetry-utils": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
82
|
"@arethetypeswrong/cli": "^0.15.2",
|
|
83
83
|
"@biomejs/biome": "^1.6.2",
|
|
84
|
-
"@fluid-internal/mocha-test-setup": ">=2.0.0-rc.
|
|
85
|
-
"@fluid-tools/build-cli": "^0.
|
|
84
|
+
"@fluid-internal/mocha-test-setup": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
85
|
+
"@fluid-tools/build-cli": "^0.38.0",
|
|
86
86
|
"@fluidframework/build-common": "^2.0.3",
|
|
87
|
-
"@fluidframework/build-tools": "^0.
|
|
87
|
+
"@fluidframework/build-tools": "^0.38.0",
|
|
88
88
|
"@fluidframework/eslint-config-fluid": "^5.1.0",
|
|
89
|
-
"@fluidframework/runtime-utils-previous": "npm:@fluidframework/runtime-utils@2.0.0-
|
|
90
|
-
"@microsoft/api-extractor": "^7.
|
|
89
|
+
"@fluidframework/runtime-utils-previous": "npm:@fluidframework/runtime-utils@2.0.0-rc.3.0.0",
|
|
90
|
+
"@microsoft/api-extractor": "^7.43.1",
|
|
91
91
|
"@types/mocha": "^9.1.1",
|
|
92
92
|
"@types/node": "^18.19.0",
|
|
93
93
|
"@types/sinon": "^17.0.3",
|
|
@@ -106,12 +106,7 @@
|
|
|
106
106
|
"typescript": "~5.1.6"
|
|
107
107
|
},
|
|
108
108
|
"typeValidation": {
|
|
109
|
-
"broken": {
|
|
110
|
-
"RemovedFunctionDeclaration_addTreeToSummary": {
|
|
111
|
-
"forwardCompat": false,
|
|
112
|
-
"backCompat": false
|
|
113
|
-
}
|
|
114
|
-
}
|
|
109
|
+
"broken": {}
|
|
115
110
|
},
|
|
116
111
|
"scripts": {
|
|
117
112
|
"api": "fluid-build . --task api",
|
|
@@ -143,7 +138,7 @@
|
|
|
143
138
|
"test:mocha:esm": "mocha --recursive \"lib/test/**/*.spec.*js\" --exit",
|
|
144
139
|
"test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
|
|
145
140
|
"tsc": "fluid-tsc commonjs --project ./tsconfig.cjs.json && copyfiles -f ../../../common/build/build-common/src/cjs/package.json ./dist",
|
|
146
|
-
"typetests:gen": "
|
|
141
|
+
"typetests:gen": "flub generate typetests --dir . -v --publicFallback",
|
|
147
142
|
"typetests:prepare": "flub typetests --dir . --reset --previous --normalize"
|
|
148
143
|
}
|
|
149
144
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { IDeltaManager } from "@fluidframework/container-definitions/internal";
|
|
7
|
+
import type { IDeltaManagerErased } from "@fluidframework/datastore-definitions";
|
|
8
|
+
import type {
|
|
9
|
+
IDocumentMessage,
|
|
10
|
+
ISequencedDocumentMessage,
|
|
11
|
+
} from "@fluidframework/protocol-definitions";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Casts the public API for delta manager into the internal one,
|
|
15
|
+
* exposing access to APIs needed by the implementation of Fluid Framework but not its users.
|
|
16
|
+
* @alpha
|
|
17
|
+
*/
|
|
18
|
+
export function toDeltaManagerInternal(
|
|
19
|
+
deltaManager: IDeltaManagerErased,
|
|
20
|
+
): IDeltaManager<ISequencedDocumentMessage, IDocumentMessage> {
|
|
21
|
+
return deltaManager as unknown as IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Casts the the internal API for delta manager into the public type erased API for returning from public APIs that should not have access to any of its members.
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
export function toDeltaManagerErased(
|
|
29
|
+
deltaManager: IDeltaManager<ISequencedDocumentMessage, IDocumentMessage>,
|
|
30
|
+
): IDeltaManagerErased {
|
|
31
|
+
return deltaManager as unknown as IDeltaManagerErased;
|
|
32
|
+
}
|
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 {
|
|
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
|
+
}
|