@fluidframework/test-utils 1.4.0-115997 → 2.0.0-dev-rc.1.0.0.224419
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/.eslintrc.js +8 -7
- package/.mocharc.js +12 -0
- package/CHANGELOG.md +177 -0
- package/README.md +44 -14
- package/api-extractor-lint.json +4 -0
- package/api-extractor.json +2 -2
- package/api-report/test-utils.api.md +395 -0
- package/dist/DriverWrappers.d.ts +32 -0
- package/dist/DriverWrappers.d.ts.map +1 -0
- package/dist/DriverWrappers.js +57 -0
- package/dist/DriverWrappers.js.map +1 -0
- package/dist/TestConfigs.d.ts +10 -0
- package/dist/TestConfigs.d.ts.map +1 -0
- package/dist/TestConfigs.js +17 -0
- package/dist/TestConfigs.js.map +1 -0
- package/dist/TestSummaryUtils.d.ts +61 -0
- package/dist/TestSummaryUtils.d.ts.map +1 -0
- package/dist/TestSummaryUtils.js +135 -0
- package/dist/TestSummaryUtils.js.map +1 -0
- package/dist/containerUtils.d.ts +46 -0
- package/dist/containerUtils.d.ts.map +1 -0
- package/dist/containerUtils.js +85 -0
- package/dist/containerUtils.js.map +1 -0
- package/dist/index.d.ts +14 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +43 -19
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +6 -0
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/loaderContainerTracker.d.ts +39 -15
- package/dist/loaderContainerTracker.d.ts.map +1 -1
- package/dist/loaderContainerTracker.js +214 -86
- package/dist/loaderContainerTracker.js.map +1 -1
- package/dist/localCodeLoader.d.ts +9 -2
- package/dist/localCodeLoader.d.ts.map +1 -1
- package/dist/localCodeLoader.js +18 -17
- package/dist/localCodeLoader.js.map +1 -1
- package/dist/localLoader.d.ts +3 -2
- package/dist/localLoader.d.ts.map +1 -1
- package/dist/localLoader.js +2 -0
- package/dist/localLoader.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/retry.d.ts +1 -0
- package/dist/retry.d.ts.map +1 -1
- package/dist/retry.js +3 -2
- package/dist/retry.js.map +1 -1
- package/dist/test-utils-alpha.d.ts +305 -0
- package/dist/test-utils-beta.d.ts +202 -0
- package/dist/test-utils-public.d.ts +202 -0
- package/dist/test-utils-untrimmed.d.ts +1001 -0
- package/dist/testContainerRuntimeFactory.d.ts +4 -2
- package/dist/testContainerRuntimeFactory.d.ts.map +1 -1
- package/dist/testContainerRuntimeFactory.js +67 -12
- package/dist/testContainerRuntimeFactory.js.map +1 -1
- package/dist/testContainerRuntimeFactoryWithDefaultDataStore.d.ts +23 -0
- package/dist/testContainerRuntimeFactoryWithDefaultDataStore.d.ts.map +1 -0
- package/dist/testContainerRuntimeFactoryWithDefaultDataStore.js +32 -0
- package/dist/testContainerRuntimeFactoryWithDefaultDataStore.js.map +1 -0
- package/dist/testFluidObject.d.ts +30 -12
- package/dist/testFluidObject.d.ts.map +1 -1
- package/dist/testFluidObject.js +74 -43
- package/dist/testFluidObject.js.map +1 -1
- package/dist/testObjectProvider.d.ts +298 -41
- package/dist/testObjectProvider.d.ts.map +1 -1
- package/dist/testObjectProvider.js +377 -61
- package/dist/testObjectProvider.js.map +1 -1
- package/dist/timeoutUtils.d.ts +42 -0
- package/dist/timeoutUtils.d.ts.map +1 -1
- package/dist/timeoutUtils.js +142 -9
- package/dist/timeoutUtils.js.map +1 -1
- package/dist/tsdoc-metadata.json +11 -0
- package/lib/test-utils-alpha.d.ts +305 -0
- package/lib/test-utils-beta.d.ts +202 -0
- package/lib/test-utils-public.d.ts +202 -0
- package/lib/test-utils-untrimmed.d.ts +1001 -0
- package/package.json +106 -72
- package/prettier.config.cjs +8 -0
- package/src/DriverWrappers.ts +83 -0
- package/src/TestConfigs.ts +17 -0
- package/src/TestSummaryUtils.ts +210 -0
- package/src/containerUtils.ts +90 -0
- package/src/index.ts +47 -9
- package/src/interfaces.ts +16 -7
- package/src/loaderContainerTracker.ts +754 -534
- package/src/localCodeLoader.ts +87 -86
- package/src/localLoader.ts +27 -26
- package/src/packageVersion.ts +1 -1
- package/src/retry.ts +33 -26
- package/src/testContainerRuntimeFactory.ts +152 -59
- package/src/testContainerRuntimeFactoryWithDefaultDataStore.ts +61 -0
- package/src/testFluidObject.ts +190 -147
- package/src/testObjectProvider.ts +931 -372
- package/src/timeoutUtils.ts +226 -37
- package/tsconfig.json +9 -12
package/src/localCodeLoader.ts
CHANGED
|
@@ -6,110 +6,111 @@
|
|
|
6
6
|
import assert from "assert";
|
|
7
7
|
import { ContainerRuntimeFactoryWithDefaultDataStore } from "@fluidframework/aqueduct";
|
|
8
8
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
IProvideRuntimeFactory,
|
|
10
|
+
IFluidModule,
|
|
11
|
+
IProvideFluidCodeDetailsComparer,
|
|
12
|
+
IFluidCodeDetails,
|
|
13
|
+
ICodeDetailsLoader,
|
|
14
|
+
IFluidModuleWithDetails,
|
|
15
15
|
} from "@fluidframework/container-definitions";
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
import {
|
|
17
|
+
IProvideFluidDataStoreFactory,
|
|
18
|
+
IProvideFluidDataStoreRegistry,
|
|
19
|
+
} from "@fluidframework/runtime-definitions";
|
|
19
20
|
import { createDataStoreFactory } from "@fluidframework/runtime-utils";
|
|
20
21
|
import { IContainerRuntimeOptions } from "@fluidframework/container-runtime";
|
|
21
22
|
|
|
23
|
+
/**
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
22
26
|
export type SupportedExportInterfaces = Partial<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
IProvideRuntimeFactory &
|
|
28
|
+
IProvideFluidDataStoreFactory &
|
|
29
|
+
IProvideFluidDataStoreRegistry &
|
|
30
|
+
IProvideFluidCodeDetailsComparer
|
|
31
|
+
>;
|
|
27
32
|
|
|
28
33
|
// Represents the entry point for a Fluid container.
|
|
34
|
+
/**
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
29
37
|
export type fluidEntryPoint = SupportedExportInterfaces | IFluidModule;
|
|
30
38
|
|
|
31
39
|
/**
|
|
32
40
|
* A simple code loader that caches a mapping of package name to a Fluid entry point.
|
|
33
41
|
* On load, it retrieves the entry point matching the package name in the given code details.
|
|
42
|
+
* @internal
|
|
34
43
|
*/
|
|
35
44
|
export class LocalCodeLoader implements ICodeDetailsLoader {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
constructor(
|
|
39
|
-
packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,
|
|
40
|
-
runtimeOptions?: IContainerRuntimeOptions,
|
|
41
|
-
) {
|
|
42
|
-
for (const entry of packageEntries) {
|
|
43
|
-
// Store the entry point against a unique id in the fluidPackageCache.
|
|
44
|
-
// For code details containing a package name, use the package name as the id.
|
|
45
|
-
// For code details containing a Fluid package, create a unique id from the package name and version.
|
|
46
|
-
let pkgId: string;
|
|
47
|
-
|
|
48
|
-
const source = entry[0];
|
|
49
|
-
if (typeof source.package === "string") {
|
|
50
|
-
pkgId = source.package;
|
|
51
|
-
} else {
|
|
52
|
-
pkgId = `${source.package.name}@${source.package.version}`;
|
|
53
|
-
}
|
|
54
|
-
let fluidModule = entry[1] as IFluidModule;
|
|
55
|
-
if (fluidModule?.fluidExport === undefined) {
|
|
56
|
-
const maybeExport = fluidModule as SupportedExportInterfaces;
|
|
45
|
+
private readonly fluidPackageCache = new Map<string, IFluidModuleWithDetails>();
|
|
57
46
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
runtimeOptions,
|
|
75
|
-
),
|
|
76
|
-
},
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
}
|
|
47
|
+
constructor(
|
|
48
|
+
packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,
|
|
49
|
+
runtimeOptions?: IContainerRuntimeOptions,
|
|
50
|
+
) {
|
|
51
|
+
for (const entry of packageEntries) {
|
|
52
|
+
// Store the entry point against a unique id in the fluidPackageCache.
|
|
53
|
+
// For code details containing a package name, use the package name as the id.
|
|
54
|
+
// For code details containing a Fluid package, create a unique id from the package name and version.
|
|
55
|
+
const source = entry[0];
|
|
56
|
+
const pkgId =
|
|
57
|
+
typeof source.package === "string"
|
|
58
|
+
? source.package
|
|
59
|
+
: `${source.package.name}@${source.package.version}`;
|
|
60
|
+
let fluidModule = entry[1] as IFluidModule;
|
|
61
|
+
if (fluidModule?.fluidExport === undefined) {
|
|
62
|
+
const maybeExport = fluidModule as SupportedExportInterfaces;
|
|
80
63
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
64
|
+
if (maybeExport.IRuntimeFactory !== undefined) {
|
|
65
|
+
fluidModule = { fluidExport: maybeExport };
|
|
66
|
+
} else {
|
|
67
|
+
assert(maybeExport.IFluidDataStoreFactory !== undefined);
|
|
68
|
+
const defaultFactory = createDataStoreFactory(
|
|
69
|
+
"default",
|
|
70
|
+
maybeExport.IFluidDataStoreFactory,
|
|
71
|
+
);
|
|
72
|
+
fluidModule = {
|
|
73
|
+
fluidExport: {
|
|
74
|
+
...maybeExport,
|
|
75
|
+
IRuntimeFactory: new ContainerRuntimeFactoryWithDefaultDataStore({
|
|
76
|
+
defaultFactory,
|
|
77
|
+
registryEntries: [
|
|
78
|
+
[defaultFactory.type, Promise.resolve(defaultFactory)],
|
|
79
|
+
],
|
|
80
|
+
runtimeOptions,
|
|
81
|
+
}),
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
85
86
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
const runtimeFactory = {
|
|
88
|
+
module: fluidModule,
|
|
89
|
+
details: source,
|
|
90
|
+
};
|
|
89
91
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
* @param source - Details of where to find chaincode
|
|
94
|
-
*/
|
|
95
|
-
public async load(
|
|
96
|
-
source: IFluidCodeDetails,
|
|
97
|
-
): Promise<IFluidModuleWithDetails> {
|
|
98
|
-
// Get the entry point for from the fluidPackageCache for the given code details.
|
|
99
|
-
// For code details containing a package name, use the package name as the id.
|
|
100
|
-
// For code details containing a Fluid package, create a unique id from the package name and version.
|
|
101
|
-
let pkdId: string;
|
|
92
|
+
this.fluidPackageCache.set(pkgId, runtimeFactory);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
102
95
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
96
|
+
/**
|
|
97
|
+
* It finds the entry point for the package name in the given source and return it
|
|
98
|
+
* as a Fluid module.
|
|
99
|
+
* @param source - Details of where to find chaincode
|
|
100
|
+
*/
|
|
101
|
+
public async load(source: IFluidCodeDetails): Promise<IFluidModuleWithDetails> {
|
|
102
|
+
// Get the entry point for from the fluidPackageCache for the given code details.
|
|
103
|
+
// For code details containing a package name, use the package name as the id.
|
|
104
|
+
// For code details containing a Fluid package, create a unique id from the package name and version.
|
|
105
|
+
const pkdId =
|
|
106
|
+
typeof source.package === "string"
|
|
107
|
+
? source.package
|
|
108
|
+
: `${source.package.name}@${source.package.version}`;
|
|
108
109
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
110
|
+
const entryPoint = this.fluidPackageCache.get(pkdId);
|
|
111
|
+
if (entryPoint === undefined) {
|
|
112
|
+
throw new Error(`Cannot find package ${pkdId}`);
|
|
113
|
+
}
|
|
114
|
+
return entryPoint;
|
|
115
|
+
}
|
|
115
116
|
}
|
package/src/localLoader.ts
CHANGED
|
@@ -4,16 +4,15 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
ICodeDetailsLoader,
|
|
8
|
+
IContainer,
|
|
9
|
+
IHostLoader,
|
|
10
|
+
ILoaderOptions,
|
|
11
|
+
IFluidCodeDetails,
|
|
12
12
|
} from "@fluidframework/container-definitions";
|
|
13
13
|
import { Loader } from "@fluidframework/container-loader";
|
|
14
|
-
import { IRequest } from "@fluidframework/core-interfaces";
|
|
14
|
+
import { ITelemetryBaseLogger, IRequest } from "@fluidframework/core-interfaces";
|
|
15
15
|
import { IDocumentServiceFactory, IUrlResolver } from "@fluidframework/driver-definitions";
|
|
16
|
-
import { ITelemetryBaseLogger } from "@fluidframework/common-definitions";
|
|
17
16
|
import { fluidEntryPoint, LocalCodeLoader } from "./localCodeLoader";
|
|
18
17
|
|
|
19
18
|
/**
|
|
@@ -22,23 +21,24 @@ import { fluidEntryPoint, LocalCodeLoader } from "./localCodeLoader";
|
|
|
22
21
|
* @param documentServiceFactory - the driver factory to use
|
|
23
22
|
* @param urlResolver - the url resolver to use
|
|
24
23
|
* @param options - loader options
|
|
24
|
+
* @internal
|
|
25
25
|
*/
|
|
26
26
|
export function createLoader(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,
|
|
28
|
+
documentServiceFactory: IDocumentServiceFactory,
|
|
29
|
+
urlResolver: IUrlResolver,
|
|
30
|
+
logger?: ITelemetryBaseLogger,
|
|
31
|
+
options?: ILoaderOptions,
|
|
32
32
|
): IHostLoader {
|
|
33
|
-
|
|
33
|
+
const codeLoader: ICodeDetailsLoader = new LocalCodeLoader(packageEntries);
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
return new Loader({
|
|
36
|
+
urlResolver,
|
|
37
|
+
documentServiceFactory,
|
|
38
|
+
codeLoader,
|
|
39
|
+
logger,
|
|
40
|
+
options,
|
|
41
|
+
});
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
/**
|
|
@@ -46,15 +46,16 @@ export function createLoader(
|
|
|
46
46
|
* @param source - The code details used to create the Container.
|
|
47
47
|
* @param loader - The loader to use to initialize the container.
|
|
48
48
|
* @param attachRequest - The request to create new from.
|
|
49
|
+
* @alpha
|
|
49
50
|
*/
|
|
50
51
|
|
|
51
52
|
export async function createAndAttachContainer(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
source: IFluidCodeDetails,
|
|
54
|
+
loader: IHostLoader,
|
|
55
|
+
attachRequest: IRequest,
|
|
55
56
|
): Promise<IContainer> {
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
const container = await loader.createDetachedContainer(source);
|
|
58
|
+
await container.attach(attachRequest);
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
return container;
|
|
60
61
|
}
|
package/src/packageVersion.ts
CHANGED
package/src/retry.ts
CHANGED
|
@@ -3,24 +3,24 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { delay } from "@fluidframework/
|
|
6
|
+
import { delay } from "@fluidframework/core-utils";
|
|
7
7
|
|
|
8
8
|
const retry = async <T>(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
callback: () => Promise<T>,
|
|
10
|
+
defaultValue: T,
|
|
11
|
+
maxTries: number,
|
|
12
|
+
backOffMs: number,
|
|
13
13
|
): Promise<T> => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
for (let currentTry = 1; currentTry <= maxTries; currentTry++) {
|
|
15
|
+
try {
|
|
16
|
+
const result = await callback();
|
|
17
|
+
return result;
|
|
18
|
+
} catch (error) {
|
|
19
|
+
await delay(currentTry * backOffMs);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
return Promise.resolve(defaultValue);
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
/**
|
|
@@ -33,18 +33,25 @@ const retry = async <T>(
|
|
|
33
33
|
* @param maxTries - maximum number of attempts
|
|
34
34
|
* @param backOffMs - back off between attempts in milliseconds
|
|
35
35
|
* @returns the actual value from the callback when successful or the default value otherwise
|
|
36
|
+
* @internal
|
|
36
37
|
*/
|
|
37
38
|
export const retryWithEventualValue = async <T>(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
): Promise<T> =>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
callback: () => Promise<T>,
|
|
40
|
+
check: (value: T) => boolean,
|
|
41
|
+
defaultValue: T,
|
|
42
|
+
maxTries = 20,
|
|
43
|
+
backOffMs = 50,
|
|
44
|
+
): Promise<T> =>
|
|
45
|
+
retry(
|
|
46
|
+
async () => {
|
|
47
|
+
const value = await callback();
|
|
48
|
+
if (check(value)) {
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
48
51
|
|
|
49
|
-
|
|
50
|
-
},
|
|
52
|
+
throw Error("Not ready");
|
|
53
|
+
},
|
|
54
|
+
defaultValue,
|
|
55
|
+
maxTries,
|
|
56
|
+
backOffMs,
|
|
57
|
+
);
|
|
@@ -3,80 +3,173 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { defaultRouteRequestHandler } from "@fluidframework/aqueduct";
|
|
7
6
|
import { IContainerContext, IRuntime } from "@fluidframework/container-definitions";
|
|
8
7
|
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
ContainerRuntime,
|
|
9
|
+
IContainerRuntimeOptions,
|
|
10
|
+
DefaultSummaryConfiguration,
|
|
12
11
|
} from "@fluidframework/container-runtime";
|
|
13
12
|
import { IContainerRuntime } from "@fluidframework/container-runtime-definitions";
|
|
14
13
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
FluidObject,
|
|
15
|
+
IFluidHandleContext,
|
|
16
|
+
IRequest,
|
|
17
|
+
IResponse,
|
|
18
|
+
} from "@fluidframework/core-interfaces";
|
|
19
|
+
// eslint-disable-next-line import/no-deprecated
|
|
20
|
+
import { buildRuntimeRequestHandler, RuntimeRequestHandler } from "@fluidframework/request-handler";
|
|
21
|
+
import {
|
|
22
|
+
IFluidDataStoreFactory,
|
|
23
|
+
NamedFluidDataStoreRegistryEntries,
|
|
24
|
+
} from "@fluidframework/runtime-definitions";
|
|
25
|
+
import { RequestParser, RuntimeFactoryHelper } from "@fluidframework/runtime-utils";
|
|
26
|
+
|
|
27
|
+
interface backCompat_IFluidRouter {
|
|
28
|
+
IFluidRouter?: backCompat_IFluidRouter;
|
|
29
|
+
request(request: IRequest): Promise<IResponse>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const backCompat_DefaultRouteRequestHandler = (defaultRootId: string) => {
|
|
33
|
+
return async (request: IRequest, runtime: IContainerRuntime) => {
|
|
34
|
+
const parser = RequestParser.create(request);
|
|
35
|
+
if (parser.pathParts.length === 0) {
|
|
36
|
+
return (
|
|
37
|
+
runtime as any as Required<FluidObject<IFluidHandleContext>>
|
|
38
|
+
).IFluidHandleContext.resolveHandle({
|
|
39
|
+
url: `/${defaultRootId}${parser.query}`,
|
|
40
|
+
headers: request.headers,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return undefined; // continue search
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
interface backCompat_ContainerRuntime {
|
|
48
|
+
load(
|
|
49
|
+
context: IContainerContext,
|
|
50
|
+
registryEntries: NamedFluidDataStoreRegistryEntries,
|
|
51
|
+
requestHandler?: (request: IRequest, runtime: IContainerRuntime) => Promise<IResponse>,
|
|
52
|
+
runtimeOptions?: IContainerRuntimeOptions,
|
|
53
|
+
containerScope?: FluidObject,
|
|
54
|
+
existing?: boolean,
|
|
55
|
+
containerRuntimeCtor?: typeof ContainerRuntime,
|
|
56
|
+
): Promise<ContainerRuntime>;
|
|
57
|
+
}
|
|
19
58
|
|
|
20
59
|
/**
|
|
21
60
|
* Create a container runtime factory class that allows you to set runtime options
|
|
61
|
+
* @internal
|
|
22
62
|
*/
|
|
23
|
-
export const createTestContainerRuntimeFactory = (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const rootContext = runtime.createDetachedRootDataStore([this.type], "default");
|
|
45
|
-
const rootRuntime = await this.dataStoreFactory.instantiateDataStore(rootContext, /* existing */ false);
|
|
46
|
-
await rootContext.attachRuntime(this.dataStoreFactory, rootRuntime);
|
|
47
|
-
}
|
|
63
|
+
export const createTestContainerRuntimeFactory = (
|
|
64
|
+
containerRuntimeCtor: typeof ContainerRuntime,
|
|
65
|
+
) => {
|
|
66
|
+
return class extends RuntimeFactoryHelper {
|
|
67
|
+
constructor(
|
|
68
|
+
public type: string,
|
|
69
|
+
public dataStoreFactory: IFluidDataStoreFactory,
|
|
70
|
+
public runtimeOptions: IContainerRuntimeOptions = {
|
|
71
|
+
summaryOptions: {
|
|
72
|
+
summaryConfigOverrides: {
|
|
73
|
+
...DefaultSummaryConfiguration,
|
|
74
|
+
...{
|
|
75
|
+
initialSummarizerDelayMs: 0,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
public requestHandlers: RuntimeRequestHandler[] = [],
|
|
81
|
+
) {
|
|
82
|
+
super();
|
|
83
|
+
}
|
|
48
84
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
85
|
+
public async instantiateFirstTime(runtime: ContainerRuntime): Promise<void> {
|
|
86
|
+
const rootContext = runtime.createDetachedRootDataStore([this.type], "default");
|
|
87
|
+
const rootRuntime = await this.dataStoreFactory.instantiateDataStore(
|
|
88
|
+
rootContext,
|
|
89
|
+
/* existing */ false,
|
|
90
|
+
);
|
|
91
|
+
await rootContext.attachRuntime(this.dataStoreFactory, rootRuntime);
|
|
92
|
+
}
|
|
54
93
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
undefined, // containerScope
|
|
71
|
-
existing,
|
|
72
|
-
);
|
|
94
|
+
public async instantiateFromExisting(runtime: ContainerRuntime): Promise<void> {
|
|
95
|
+
// Validate we can load root data stores.
|
|
96
|
+
// We should be able to load any data store that was created in initializeFirstTime!
|
|
97
|
+
// Note: We use the deprecated `getRootDataStore` from v1.X here to allow for cross-major version compat
|
|
98
|
+
// testing. Can be removed when we no longer support v1.X.
|
|
99
|
+
await (runtime.getAliasedDataStoreEntryPoint?.("default") ??
|
|
100
|
+
(
|
|
101
|
+
runtime as any as {
|
|
102
|
+
getRootDataStore(
|
|
103
|
+
id: string,
|
|
104
|
+
wait?: boolean,
|
|
105
|
+
): Promise<backCompat_IFluidRouter>;
|
|
106
|
+
}
|
|
107
|
+
).getRootDataStore("default"));
|
|
108
|
+
}
|
|
73
109
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
110
|
+
async preInitialize(
|
|
111
|
+
context: IContainerContext,
|
|
112
|
+
existing: boolean,
|
|
113
|
+
): Promise<IRuntime & IContainerRuntime> {
|
|
114
|
+
if (containerRuntimeCtor.loadRuntime === undefined) {
|
|
115
|
+
// Note: We use the deprecated `load` from v1.X here to allow for cross-major version compat testing.
|
|
116
|
+
// Can be removed when we no longer support v1.X.
|
|
117
|
+
return (containerRuntimeCtor as any as backCompat_ContainerRuntime).load(
|
|
118
|
+
context,
|
|
119
|
+
[
|
|
120
|
+
["default", Promise.resolve(this.dataStoreFactory)],
|
|
121
|
+
[this.type, Promise.resolve(this.dataStoreFactory)],
|
|
122
|
+
],
|
|
123
|
+
buildRuntimeRequestHandler(
|
|
124
|
+
backCompat_DefaultRouteRequestHandler("default"),
|
|
125
|
+
...this.requestHandlers,
|
|
126
|
+
),
|
|
127
|
+
this.runtimeOptions,
|
|
128
|
+
context.scope,
|
|
129
|
+
existing,
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
const provideEntryPoint = async (runtime: IContainerRuntime) => {
|
|
133
|
+
const entryPoint = await runtime.getAliasedDataStoreEntryPoint("default");
|
|
134
|
+
if (entryPoint === undefined) {
|
|
135
|
+
throw new Error("default dataStore must exist");
|
|
136
|
+
}
|
|
137
|
+
return entryPoint.get();
|
|
138
|
+
};
|
|
139
|
+
const getDefaultObject = async (request: IRequest, runtime: IContainerRuntime) => {
|
|
140
|
+
const parser = RequestParser.create(request);
|
|
141
|
+
if (parser.pathParts.length === 0) {
|
|
142
|
+
// This cast is safe as ContainerRuntime.loadRuntime is called below
|
|
143
|
+
return (runtime as ContainerRuntime).resolveHandle({
|
|
144
|
+
url: `/default${parser.query}`,
|
|
145
|
+
headers: request.headers,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
return undefined; // continue search
|
|
149
|
+
};
|
|
150
|
+
return containerRuntimeCtor.loadRuntime({
|
|
151
|
+
context,
|
|
152
|
+
registryEntries: [
|
|
153
|
+
["default", Promise.resolve(this.dataStoreFactory)],
|
|
154
|
+
[this.type, Promise.resolve(this.dataStoreFactory)],
|
|
155
|
+
],
|
|
156
|
+
requestHandler: buildRuntimeRequestHandler(
|
|
157
|
+
getDefaultObject,
|
|
158
|
+
...this.requestHandlers,
|
|
159
|
+
),
|
|
160
|
+
provideEntryPoint,
|
|
161
|
+
// ! This prop is needed for back-compat. Can be removed in 2.0.0-internal.8.0.0
|
|
162
|
+
initializeEntryPoint: provideEntryPoint,
|
|
163
|
+
runtimeOptions: this.runtimeOptions,
|
|
164
|
+
containerScope: context.scope,
|
|
165
|
+
existing,
|
|
166
|
+
} as any);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
77
169
|
};
|
|
78
170
|
|
|
79
171
|
/**
|
|
80
172
|
* A container runtime factory that allows you to set runtime options
|
|
173
|
+
* @internal
|
|
81
174
|
*/
|
|
82
175
|
export const TestContainerRuntimeFactory = createTestContainerRuntimeFactory(ContainerRuntime);
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ContainerRuntimeFactoryWithDefaultDataStore } from "@fluidframework/aqueduct";
|
|
7
|
+
import { IContainerRuntimeOptions } from "@fluidframework/container-runtime";
|
|
8
|
+
import { IContainerRuntime } from "@fluidframework/container-runtime-definitions";
|
|
9
|
+
import { FluidObject } from "@fluidframework/core-interfaces";
|
|
10
|
+
import { RuntimeRequestHandler } from "@fluidframework/request-handler";
|
|
11
|
+
import {
|
|
12
|
+
IFluidDataStoreFactory,
|
|
13
|
+
NamedFluidDataStoreRegistryEntries,
|
|
14
|
+
} from "@fluidframework/runtime-definitions";
|
|
15
|
+
|
|
16
|
+
const getDefaultFluidObject = async (runtime: IContainerRuntime) => {
|
|
17
|
+
const entryPoint = await runtime.getAliasedDataStoreEntryPoint("default");
|
|
18
|
+
if (entryPoint === undefined) {
|
|
19
|
+
throw new Error("default dataStore must exist");
|
|
20
|
+
}
|
|
21
|
+
return entryPoint.get();
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* ! Note: This function is purely needed for back-compat as the constructor argument structure was changed
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
export const createContainerRuntimeFactoryWithDefaultDataStore = (
|
|
29
|
+
Base: typeof ContainerRuntimeFactoryWithDefaultDataStore = ContainerRuntimeFactoryWithDefaultDataStore,
|
|
30
|
+
ctorArgs: {
|
|
31
|
+
defaultFactory: IFluidDataStoreFactory;
|
|
32
|
+
registryEntries: NamedFluidDataStoreRegistryEntries;
|
|
33
|
+
dependencyContainer?: any;
|
|
34
|
+
requestHandlers?: RuntimeRequestHandler[];
|
|
35
|
+
runtimeOptions?: IContainerRuntimeOptions;
|
|
36
|
+
provideEntryPoint?: (runtime: IContainerRuntime) => Promise<FluidObject>;
|
|
37
|
+
},
|
|
38
|
+
): ContainerRuntimeFactoryWithDefaultDataStore => {
|
|
39
|
+
try {
|
|
40
|
+
return new Base(ctorArgs);
|
|
41
|
+
} catch (err) {
|
|
42
|
+
// IMPORTANT: The constructor argument structure changed, so this is needed for dynamically using older ContainerRuntimeFactoryWithDefaultDataStore's
|
|
43
|
+
const {
|
|
44
|
+
defaultFactory,
|
|
45
|
+
registryEntries,
|
|
46
|
+
dependencyContainer,
|
|
47
|
+
requestHandlers,
|
|
48
|
+
runtimeOptions,
|
|
49
|
+
provideEntryPoint,
|
|
50
|
+
} = ctorArgs;
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
52
|
+
return new (Base as any)(
|
|
53
|
+
defaultFactory,
|
|
54
|
+
registryEntries,
|
|
55
|
+
dependencyContainer,
|
|
56
|
+
requestHandlers,
|
|
57
|
+
runtimeOptions,
|
|
58
|
+
provideEntryPoint ?? getDefaultFluidObject,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
};
|