@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testObjectProvider.js","sourceRoot":"","sources":["../src/testObjectProvider.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IContainer, IHostLoader, IFluidCodeDetails } from \"@fluidframework/container-definitions\";\nimport { ITelemetryGenericEvent, ITelemetryBaseLogger, ITelemetryBaseEvent } from \"@fluidframework/common-definitions\";\nimport {\n ILoaderProps,\n Loader,\n waitContainerToCatchUp as waitContainerToCatchUp_original,\n} from \"@fluidframework/container-loader\";\nimport { IContainerRuntimeOptions } from \"@fluidframework/container-runtime\";\nimport { IRequestHeader } from \"@fluidframework/core-interfaces\";\nimport { IDocumentServiceFactory, IResolvedUrl, IUrlResolver } from \"@fluidframework/driver-definitions\";\nimport { ensureFluidResolvedUrl } from \"@fluidframework/driver-utils\";\nimport { ITestDriver, TestDriverTypes } from \"@fluidframework/test-driver-definitions\";\nimport { v4 as uuid } from \"uuid\";\nimport { ChildLogger, MultiSinkLogger, TelemetryLogger } from \"@fluidframework/telemetry-utils\";\nimport { LoaderContainerTracker } from \"./loaderContainerTracker\";\nimport { fluidEntryPoint, LocalCodeLoader } from \"./localCodeLoader\";\nimport { createAndAttachContainer } from \"./localLoader\";\nimport { ChannelFactoryRegistry } from \"./testFluidObject\";\n\nconst defaultCodeDetails: IFluidCodeDetails = {\n package: \"defaultTestPackage\",\n config: {},\n};\n\nexport interface IOpProcessingController {\n processIncoming(...containers: IContainer[]): Promise<void>;\n processOutgoing(...containers: IContainer[]): Promise<void>;\n pauseProcessing(...containers: IContainer[]): Promise<void>;\n resumeProcessing(...containers: IContainer[]): void;\n}\n\nexport interface ITestObjectProvider {\n createFluidEntryPoint: (testContainerConfig?: ITestContainerConfig) => fluidEntryPoint;\n createLoader(\n packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,\n loaderProps?: Partial<ILoaderProps>,\n ): IHostLoader;\n createContainer(entryPoint: fluidEntryPoint, loaderProps?: Partial<ILoaderProps>): Promise<IContainer>;\n loadContainer(\n entryPoint: fluidEntryPoint,\n loaderProps?: Partial<ILoaderProps>,\n requestHeader?: IRequestHeader,\n ): Promise<IContainer>;\n\n /**\n * Used to create a test Container. The Loader/ContainerRuntime/DataRuntime might be different versioned.\n * In generateLocalCompatTest(), this Container and its runtime will be arbitrarily-versioned.\n */\n makeTestLoader(testContainerConfig?: ITestContainerConfig): IHostLoader;\n makeTestContainer(testContainerConfig?: ITestContainerConfig): Promise<IContainer>;\n loadTestContainer(testContainerConfig?: ITestContainerConfig, requestHeader?: IRequestHeader): Promise<IContainer>;\n /**\n *\n * @param url - Resolved container URL\n */\n updateDocumentId(url: IResolvedUrl | undefined): void;\n\n logger: ITelemetryBaseLogger;\n documentServiceFactory: IDocumentServiceFactory;\n urlResolver: IUrlResolver;\n defaultCodeDetails: IFluidCodeDetails;\n opProcessingController: IOpProcessingController;\n\n ensureSynchronized(): Promise<void>;\n reset(): void;\n\n documentId: string;\n driver: ITestDriver;\n}\n\nexport enum DataObjectFactoryType {\n Primed, // default\n Test,\n}\n\nexport interface ITestContainerConfig {\n /** TestFluidDataObject instead of PrimedDataStore */\n fluidDataObjectType?: DataObjectFactoryType;\n\n /** An array of channel name and DDS factory pair to create on container creation time */\n registry?: ChannelFactoryRegistry;\n\n /** Container runtime options for the container instance */\n runtimeOptions?: IContainerRuntimeOptions;\n\n /** Loader options for the loader used to create containers */\n loaderProps?: Partial<ILoaderProps>;\n}\n\nexport const createDocumentId = (): string => uuid();\n\ninterface IDocumentIdStrategy {\n get(): string;\n update(resolvedUrl?: IResolvedUrl): void;\n reset(): void;\n}\n\n/**\n * Document ID is treated differently by test drivers. The key difference is in generating\n * a new container ID and accessing the container in multi-instance test cases.\n */\nfunction getDocumentIdStrategy(type?: TestDriverTypes): IDocumentIdStrategy {\n let documentId = createDocumentId();\n switch (type) {\n case \"odsp\":\n return {\n get: () => documentId,\n update: () => { }, // do not update the document ID in odsp test cases\n reset: () => { documentId = createDocumentId(); },\n };\n default:\n return {\n get: () => documentId,\n update: (resolvedUrl?: IResolvedUrl) => {\n // Extract the document ID from the resolved container's URL and reset the ID property\n ensureFluidResolvedUrl(resolvedUrl);\n documentId = resolvedUrl.id ?? documentId;\n },\n reset: () => { documentId = createDocumentId(); },\n };\n }\n}\n\n/**\n * This class tracks events. It allows specifying expected events, which will be looked for in order.\n * It also tracks all unexpected errors.\n * At any point you call reportAndClearTrackedEvents which will provide all unexpected errors, and\n * any expected events that have not occurred.\n */\nexport class EventAndErrorTrackingLogger extends TelemetryLogger {\n constructor(private readonly baseLogger: ITelemetryBaseLogger) {\n super();\n }\n\n private readonly expectedEvents: ({ index: number; event: ITelemetryGenericEvent | undefined; } | undefined)[] = [];\n private readonly unexpectedErrors: ITelemetryBaseEvent[] = [];\n\n public registerExpectedEvent(... orderedExpectedEvents: ITelemetryGenericEvent[]) {\n if (this.expectedEvents.length !== 0) {\n // we don't have to error here. just no reason not to. given the events must be\n // ordered it could be tricky to figure out problems around multiple registrations.\n throw new Error(\n \"Expected events already registered.\\n\"\n + \"Call reportAndClearTrackedEvents to clear them before registering more\");\n }\n this.expectedEvents.push(... orderedExpectedEvents.map((event, index) => ({ index, event })));\n }\n\n send(event: ITelemetryBaseEvent): void {\n const ee = this.expectedEvents[0]?.event;\n if (ee?.eventName === event.eventName) {\n let matches = true;\n for (const key of Object.keys(ee)) {\n if (ee[key] !== event[key]) {\n matches = false;\n break;\n }\n }\n if (matches) {\n // we found an expected event\n // so remove it from the list of expected events\n // and if it is an error, change it to generic\n // this helps keep our telemetry clear of\n // expected errors.\n this.expectedEvents.shift();\n if (event.category === \"error\") {\n event.category = \"generic\";\n }\n }\n }\n if (event.category === \"error\") {\n this.unexpectedErrors.push(event);\n }\n\n this.baseLogger.send(event);\n }\n\n public reportAndClearTrackedEvents() {\n const expectedNotFound = this.expectedEvents.splice(0, this.expectedEvents.length);\n const unexpectedErrors = this.unexpectedErrors.splice(0, this.unexpectedErrors.length);\n return {\n expectedNotFound,\n unexpectedErrors,\n };\n }\n}\n\n/**\n * Shared base class for test object provider. Contain code for loader and container creation and loading\n */\nexport class TestObjectProvider implements ITestObjectProvider {\n private _loaderContainerTracker = new LoaderContainerTracker();\n private _documentServiceFactory: IDocumentServiceFactory | undefined;\n private _urlResolver: IUrlResolver | undefined;\n private _logger: EventAndErrorTrackingLogger | undefined;\n private readonly _documentIdStrategy: IDocumentIdStrategy;\n // Since documentId doesn't change we can only create/make one container. Call the load functions instead.\n private _documentCreated = false;\n\n /**\n * Manage objects for loading and creating container, including the driver, loader, and OpProcessingController\n * @param createFluidEntryPoint - callback to create a fluidEntryPoint, with an optional set of channel name\n * and factory for TestFluidObject\n */\n constructor(\n public readonly LoaderConstructor: typeof Loader,\n public readonly driver: ITestDriver,\n public readonly createFluidEntryPoint: (testContainerConfig?: ITestContainerConfig) => fluidEntryPoint,\n ) {\n this._documentIdStrategy = getDocumentIdStrategy(driver.type);\n }\n\n get logger(): EventAndErrorTrackingLogger {\n if (this._logger === undefined) {\n this._logger = new EventAndErrorTrackingLogger(\n ChildLogger.create(getTestLogger?.(), undefined,\n {\n all: {\n driverType: this.driver.type,\n driverEndpointName: this.driver.endpointName,\n driverTenantName: this.driver.tenantName,\n driverUserIndex: this.driver.userIndex,\n },\n }));\n }\n return this._logger;\n }\n\n get documentServiceFactory() {\n if (!this._documentServiceFactory) {\n this._documentServiceFactory = this.driver.createDocumentServiceFactory();\n }\n return this._documentServiceFactory;\n }\n\n get urlResolver() {\n if (!this._urlResolver) {\n this._urlResolver = this.driver.createUrlResolver();\n }\n return this._urlResolver;\n }\n\n get documentId() {\n return this._documentIdStrategy.get();\n }\n\n get defaultCodeDetails() {\n return defaultCodeDetails;\n }\n\n get opProcessingController(): IOpProcessingController {\n return this._loaderContainerTracker;\n }\n\n /**\n * Create a loader. Containers created/loaded through this loader will be added to the OpProcessingController.\n *\n * Only the version of the loader will vary based on compat config. The version of\n * containerRuntime/dataRuntime used in fluidEntryPoint will be used as is from what is passed in.\n *\n * @param packageEntries - list of code details and fluidEntryPoint pairs.\n */\n public createLoader(\n packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,\n loaderProps?: Partial<ILoaderProps>,\n ) {\n const multiSinkLogger = new MultiSinkLogger();\n multiSinkLogger.addLogger(this.logger);\n if (loaderProps?.logger !== undefined) {\n multiSinkLogger.addLogger(loaderProps.logger);\n }\n\n const loader = new this.LoaderConstructor({\n ... loaderProps,\n logger: multiSinkLogger,\n codeLoader: loaderProps?.codeLoader ?? new LocalCodeLoader(packageEntries),\n urlResolver: loaderProps?.urlResolver ?? this.urlResolver,\n documentServiceFactory: loaderProps?.documentServiceFactory ?? this.documentServiceFactory,\n });\n this._loaderContainerTracker.add(loader);\n return loader;\n }\n\n /**\n * Create a container using a default document id and code details.\n * Container created is automatically added to the OpProcessingController to manage op flow\n *\n * Only the version of the loader will vary based on compat config. The version of\n * containerRuntime/dataRuntime used in fluidEntryPoint will be used as is from what is passed in.\n *\n * @param packageEntries - list of code details and fluidEntryPoint pairs.\n */\n public async createContainer(entryPoint: fluidEntryPoint, loaderProps?: Partial<ILoaderProps>) {\n if (this._documentCreated) {\n throw new Error(\n \"Only one container/document can be created. To load the container/document use loadContainer\");\n }\n const loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);\n const container = await createAndAttachContainer(\n defaultCodeDetails,\n loader,\n this.driver.createCreateNewRequest(this.documentId),\n );\n this._documentCreated = true;\n // r11s driver will generate a new ID for the new container.\n // update the document ID with the actual ID of the attached container.\n this._documentIdStrategy.update(container.resolvedUrl);\n return container;\n }\n\n public async loadContainer(\n entryPoint: fluidEntryPoint,\n loaderProps?: Partial<ILoaderProps>,\n requestHeader?: IRequestHeader): Promise<IContainer> {\n const loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);\n return loader.resolve({ url: await this.driver.createContainerUrl(this.documentId), headers: requestHeader });\n }\n\n /**\n * Make a test loader. Containers created/loaded through this loader will be added to the OpProcessingController.\n * The version of the loader/containerRuntime/dataRuntime may vary based on compat config of the current run\n * @param testContainerConfig - optional configuring the test Container\n */\n public makeTestLoader(testContainerConfig?: ITestContainerConfig) {\n return this.createLoader(\n [[defaultCodeDetails, this.createFluidEntryPoint(testContainerConfig)]],\n testContainerConfig?.loaderProps,\n );\n }\n\n /**\n * Make a container using a default document id and code details\n * Container loaded is automatically added to the OpProcessingController to manage op flow\n * @param testContainerConfig - optional configuring the test Container\n */\n public async makeTestContainer(testContainerConfig?: ITestContainerConfig): Promise<IContainer> {\n if (this._documentCreated) {\n throw new Error(\n \"Only one container/document can be created. To load the container/document use loadTestContainer\");\n }\n const loader = this.makeTestLoader(testContainerConfig);\n const container =\n await createAndAttachContainer(\n defaultCodeDetails,\n loader,\n this.driver.createCreateNewRequest(this.documentId));\n this._documentCreated = true;\n // r11s driver will generate a new ID for the new container.\n // update the document ID with the actual ID of the attached container.\n this._documentIdStrategy.update(container.resolvedUrl);\n return container;\n }\n\n /**\n * Load a container using a default document id and code details.\n * IContainer loaded is automatically added to the OpProcessingController to manage op flow\n * @param testContainerConfig - optional configuring the test Container\n * @param requestHeader - optional headers to be supplied to the loader\n */\n public async loadTestContainer(\n testContainerConfig?: ITestContainerConfig,\n requestHeader?: IRequestHeader,\n ): Promise<IContainer> {\n const loader = this.makeTestLoader(testContainerConfig);\n const container = await loader.resolve({\n url: await this.driver.createContainerUrl(this.documentId),\n headers: requestHeader,\n });\n await this.waitContainerToCatchUp(container);\n\n return container;\n }\n\n public reset() {\n this._loaderContainerTracker.reset();\n this._documentServiceFactory = undefined;\n this._urlResolver = undefined;\n this._documentIdStrategy.reset();\n const logError = getUnexpectedLogErrorException(this._logger);\n if (logError) {\n throw logError;\n }\n this._logger = undefined;\n this._documentCreated = false;\n }\n\n public async ensureSynchronized() {\n return this._loaderContainerTracker.ensureSynchronized();\n }\n\n public async waitContainerToCatchUp(container: IContainer) {\n // The original waitContainerToCatchUp() from container loader uses either Container.resume()\n // or Container.connect() as part of its implementation. However, resume() was deprecated\n // and eventually replaced with connect(). To avoid issues during LTS compatibility testing\n // with older container versions issues, we use resume() when connect() is unavailable.\n if ((container as any).connect === undefined) {\n (container as any).connect = (container as any).resume;\n }\n\n return waitContainerToCatchUp_original(container);\n }\n\n updateDocumentId(resolvedUrl: IResolvedUrl | undefined) {\n this._documentIdStrategy.update(resolvedUrl);\n }\n\n public resetLoaderContainerTracker(syncSummarizerClients: boolean = false) {\n this._loaderContainerTracker.reset();\n this._loaderContainerTracker = new LoaderContainerTracker(syncSummarizerClients);\n }\n}\n\nexport function getUnexpectedLogErrorException(logger: EventAndErrorTrackingLogger | undefined, prefix?: string) {\n if (logger === undefined) {\n return;\n }\n const results = logger.reportAndClearTrackedEvents();\n if (results.unexpectedErrors.length > 0) {\n return new Error(\n `${prefix ?? \"\"}Unexpected Errors in Logs:\\n${JSON.stringify(results.unexpectedErrors, undefined, 2)}`);\n }\n if (results.expectedNotFound.length > 0) {\n return new Error(\n `${prefix ?? \"\"}Expected Events not found:\\n${JSON.stringify(results.expectedNotFound, undefined, 2)}`);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"testObjectProvider.js","sourceRoot":"","sources":["../src/testObjectProvider.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAQH,uEAI0C;AAc1C,+BAAkC;AAClC,qEAA2F;AAC3F,qEAAkE;AAClE,uDAAqE;AACrE,+CAAyD;AAGzD,MAAM,kBAAkB,GAAsB;IAC7C,OAAO,EAAE,oBAAoB;IAC7B,MAAM,EAAE,EAAE;CACV,CAAC;AAgJF;;GAEG;AACH,IAAY,qBAGX;AAHD,WAAY,qBAAqB;IAChC,qEAAM,CAAA;IACN,iEAAI,CAAA;AACL,CAAC,EAHW,qBAAqB,qCAArB,qBAAqB,QAGhC;AAsBD;;GAEG;AACI,MAAM,gBAAgB,GAAG,GAAW,EAAE,CAAC,IAAA,SAAI,GAAE,CAAC;AAAxC,QAAA,gBAAgB,oBAAwB;AAsBrD;;;GAGG;AACH,SAAS,qBAAqB,CAAC,IAAsB;IACpD,IAAI,UAAU,GAAG,IAAA,wBAAgB,GAAE,CAAC;IACpC,QAAQ,IAAI,EAAE;QACb,KAAK,MAAM;YACV,OAAO;gBACN,GAAG,EAAE,GAAG,EAAE,CAAC,UAAU;gBACrB,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC;gBAChB,KAAK,EAAE,GAAG,EAAE;oBACX,UAAU,GAAG,IAAA,wBAAgB,GAAE,CAAC;gBACjC,CAAC;aACD,CAAC;QACH;YACC,OAAO;gBACN,GAAG,EAAE,GAAG,EAAE,CAAC,UAAU;gBACrB,MAAM,EAAE,CAAC,WAA0B,EAAE,EAAE;oBACtC,sFAAsF;oBACtF,UAAU,GAAG,WAAW,EAAE,EAAE,IAAI,UAAU,CAAC;gBAC5C,CAAC;gBACD,KAAK,EAAE,GAAG,EAAE;oBACX,UAAU,GAAG,IAAA,wBAAgB,GAAE,CAAC;gBACjC,CAAC;aACD,CAAC;KACH;AACF,CAAC;AAED;;;;;;GAMG;AACH,MAAa,2BAA2B;IAevC,YAA6B,UAAgC;QAAhC,eAAU,GAAV,UAAU,CAAsB;QAd7D;;;WAGG;QACc,kBAAa,GAA8C;YAC3E,sGAAsG;YACtG;gBACC,SAAS,EAAE,4DAA4D;gBACvE,SAAS,EAAE,IAAI;aACf;YACD,mJAAmJ;YACnJ,EAAE,SAAS,EAAE,wCAAwC,EAAE;SACvD,CAAC;QAIe,mBAAc,GAGzB,EAAE,CAAC;QACQ,qBAAgB,GAA0B,EAAE,CAAC;IANE,CAAC;IAQ1D,qBAAqB,CAAC,GAAG,qBAA+C;QAC9E,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE;YACrC,+EAA+E;YAC/E,mFAAmF;YACnF,MAAM,IAAI,KAAK,CACd,uCAAuC;gBACtC,wEAAwE,CACzE,CAAC;SACF;QACD,IAAI,CAAC,cAAc,CAAC,IAAI,CACvB,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAClE,CAAC;IACH,CAAC;IAED,IAAI,CAAC,KAA0B;QAC9B,MAAM,EAAE,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;QACzC,IAAI,EAAE,EAAE,SAAS,KAAK,KAAK,CAAC,SAAS,EAAE;YACtC,IAAI,OAAO,GAAG,IAAI,CAAC;YACnB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;gBAClC,IAAI,EAAE,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,EAAE;oBAC3B,OAAO,GAAG,KAAK,CAAC;oBAChB,MAAM;iBACN;aACD;YACD,IAAI,OAAO,EAAE;gBACZ,6BAA6B;gBAC7B,gDAAgD;gBAChD,8CAA8C;gBAC9C,yCAAyC;gBACzC,mBAAmB;gBACnB,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;gBAC5B,IAAI,KAAK,CAAC,QAAQ,KAAK,OAAO,EAAE;oBAC/B,KAAK,CAAC,QAAQ,GAAG,SAAS,CAAC;iBAC3B;aACD;SACD;QACD,IAAI,KAAK,CAAC,QAAQ,KAAK,OAAO,EAAE;YAC/B,iFAAiF;YACjF,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAC3C,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,CAChD,CAAC;YAEF,IAAI,YAAY,KAAK,SAAS,EAAE;gBAC/B,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aAClC;iBAAM,IAAI,YAAY,CAAC,SAAS,EAAE;gBAClC,KAAK,CAAC,QAAQ,GAAG,SAAS,CAAC;aAC3B;SACD;QAED,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAEM,2BAA2B;QACjC,MAAM,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QACnF,MAAM,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACvF,OAAO;YACN,gBAAgB;YAChB,gBAAgB;SAChB,CAAC;IACH,CAAC;CACD;AAnFD,kEAmFC;AAED;;;GAGG;AACH,MAAa,kBAAkB;IAa9B;;;;OAIG;IACH,YACkB,iBAAgC;IACjD;;OAEG;IACa,MAAmB;IACnC;;OAEG;IACa,qBAEI;QAVH,sBAAiB,GAAjB,iBAAiB,CAAe;QAIjC,WAAM,GAAN,MAAM,CAAa;QAInB,0BAAqB,GAArB,qBAAqB,CAEjB;QA5BrB;;WAEG;QACa,SAAI,GAAG,oBAAoB,CAAC;QACpC,4BAAuB,GAAG,IAAI,+CAAsB,EAAE,CAAC;QAK/D,0GAA0G;QAClG,qBAAgB,GAAG,KAAK,CAAC;QAoBhC,IAAI,CAAC,mBAAmB,GAAG,qBAAqB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC;IAED;;OAEG;IACH,IAAW,MAAM;QAChB,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE;YAC/B,IAAI,CAAC,OAAO,GAAG,IAAI,2BAA2B,CAC7C,IAAA,mCAAiB,EAAC;gBACjB,MAAM,EAAE,aAAa,EAAE,EAAE;gBACzB,UAAU,EAAE;oBACX,GAAG,EAAE;wBACJ,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI;wBAC5B,kBAAkB,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY;wBAC5C,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU;wBACxC,eAAe,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;qBACtC;iBACD;aACD,CAAC,CACF,CAAC;SACF;QACD,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,IAAY,MAAM,CAAC,MAAmC;QACrD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,IAAW,sBAAsB;QAChC,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE;YAClC,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC,MAAM,CAAC,4BAA4B,EAAE,CAAC;SAC1E;QACD,OAAO,IAAI,CAAC,uBAAuB,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,IAAW,WAAW;QACrB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;YACvB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;SACpD;QACD,OAAO,IAAI,CAAC,YAAY,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,IAAW,UAAU;QACpB,OAAO,IAAI,CAAC,mBAAmB,CAAC,GAAG,EAAE,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,IAAW,kBAAkB;QAC5B,OAAO,kBAAkB,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,IAAW,sBAAsB;QAChC,OAAO,IAAI,CAAC,uBAAuB,CAAC;IACrC,CAAC;IAED;;OAEG;IACI,YAAY,CAClB,cAA8D,EAC9D,WAAmC;QAEnC,MAAM,MAAM,GAAG,IAAA,uCAAqB,EAAC;YACpC,OAAO,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC;SAC3C,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,iBAAiB,CAAC;YACzC,GAAG,WAAW;YACd,MAAM;YACN,UAAU,EAAE,WAAW,EAAE,UAAU,IAAI,IAAI,iCAAe,CAAC,cAAc,CAAC;YAC1E,WAAW,EAAE,WAAW,EAAE,WAAW,IAAI,IAAI,CAAC,WAAW;YACzD,sBAAsB,EACrB,WAAW,EAAE,sBAAsB,IAAI,IAAI,CAAC,sBAAsB;SACnE,CAAC,CAAC;QACH,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,eAAe,CAAC,UAA2B,EAAE,WAAmC;QAC5F,IAAI,IAAI,CAAC,gBAAgB,EAAE;YAC1B,MAAM,IAAI,KAAK,CACd,8FAA8F,CAC9F,CAAC;SACF;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QAClF,MAAM,SAAS,GAAG,MAAM,IAAA,sCAAwB,EAC/C,kBAAkB,EAClB,MAAM,EACN,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,IAAI,CAAC,UAAU,CAAC,CACnD,CAAC;QACF,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,4DAA4D;QAC5D,uEAAuE;QACvE,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QACvD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,aAAa,CACzB,UAA2B,EAC3B,WAAmC,EACnC,aAA8B;QAE9B,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QAClF,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACrD,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,MAAe,EAAE,OAAwB;QACvE,OAAO,MAAM,CAAC,OAAO,CAAC;YACrB,GAAG,EAAE,MAAM,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC;YAC1D,OAAO;SACP,CAAC,CAAC;IACJ,CAAC;IAED;;OAEG;IACI,cAAc,CAAC,mBAA0C;QAC/D,OAAO,IAAI,CAAC,YAAY,CACvB,CAAC,CAAC,kBAAkB,EAAE,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,CAAC,CAAC,EACvE,mBAAmB,EAAE,WAAW,CAChC,CAAC;IACH,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,iBAAiB,CAC7B,mBAA0C;QAE1C,IAAI,IAAI,CAAC,gBAAgB,EAAE;YAC1B,MAAM,IAAI,KAAK,CACd,kGAAkG,CAClG,CAAC;SACF;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,MAAM,IAAA,sCAAwB,EAC/C,kBAAkB,EAClB,MAAM,EACN,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,IAAI,CAAC,UAAU,CAAC,CACnD,CAAC;QACF,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,4DAA4D;QAC5D,uEAAuE;QACvE,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QACvD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,iBAAiB,CAC7B,mBAA0C,EAC1C,aAA8B;QAE9B,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC;QAExD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QACrE,MAAM,IAAI,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;QAE7C,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;OAEG;IACI,KAAK;QACX,IAAI,CAAC,uBAAuB,CAAC,KAAK,EAAE,CAAC;QACrC,IAAI,CAAC,uBAAuB,GAAG,SAAS,CAAC;QACzC,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;QAC9B,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,8BAA8B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9D,IAAI,QAAQ,EAAE;YACb,MAAM,QAAQ,CAAC;SACf;QACD,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QACzB,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;IAC/B,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,kBAAkB;QAC9B,OAAO,IAAI,CAAC,uBAAuB,CAAC,kBAAkB,EAAE,CAAC;IAC1D,CAAC;IAEO,KAAK,CAAC,sBAAsB,CAAC,SAAqB;QACzD,6FAA6F;QAC7F,yFAAyF;QACzF,2FAA2F;QAC3F,uFAAuF;QACvF,IAAK,SAAiB,CAAC,OAAO,KAAK,SAAS,EAAE;YAC5C,SAAiB,CAAC,OAAO,GAAI,SAAiB,CAAC,MAAM,CAAC;SACvD;QAED,OAAO,IAAA,yCAA+B,EAAC,SAAS,CAAC,CAAC;IACnD,CAAC;IAED;;OAEG;IACI,gBAAgB,CAAC,WAAqC;QAC5D,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACI,2BAA2B,CAAC,wBAAiC,KAAK;QACxE,IAAI,CAAC,uBAAuB,CAAC,KAAK,EAAE,CAAC;QACrC,IAAI,CAAC,uBAAuB,GAAG,IAAI,+CAAsB,CAAC,qBAAqB,CAAC,CAAC;IAClF,CAAC;CACD;AAvQD,gDAuQC;AAED;;;;GAIG;AACH,MAAa,mCAAmC;IAuB/C,YACkB,4BAA2C,EAC3C,2BAA0C,EAC1C,iBAA8B,EAC9B,gBAA6B,EAC7B,gCAEG,EACH,+BAEG;QATH,iCAA4B,GAA5B,4BAA4B,CAAe;QAC3C,gCAA2B,GAA3B,2BAA2B,CAAe;QAC1C,sBAAiB,GAAjB,iBAAiB,CAAa;QAC9B,qBAAgB,GAAhB,gBAAgB,CAAa;QAC7B,qCAAgC,GAAhC,gCAAgC,CAE7B;QACH,oCAA+B,GAA/B,+BAA+B,CAE5B;QAhCrB;;WAEG;QACa,SAAI,GAAG,qCAAqC,CAAC;QACrD,4BAAuB,GAAG,IAAI,+CAAsB,EAAE,CAAC;QAK/D,0GAA0G;QAClG,qBAAgB,GAAG,KAAK,CAAC;QAEjC;;;;;;WAMG;QAEK,eAAU,GAAW,CAAC,CAAC;QAc9B,IAAI,CAAC,mBAAmB,GAAG,qBAAqB,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC1E,CAAC;IAED;;OAEG;IACH,IAAW,MAAM;QAChB,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE;YAC/B,IAAI,CAAC,OAAO,GAAG,IAAI,2BAA2B,CAC7C,IAAA,mCAAiB,EAAC;gBACjB,MAAM,EAAE,aAAa,EAAE,EAAE;aACzB,CAAC,CACF,CAAC;SACF;QACD,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,IAAW,sBAAsB;QAChC,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE;YAClC,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC,iBAAiB,CAAC,4BAA4B,EAAE,CAAC;SACrF;QACD,OAAO,IAAI,CAAC,uBAAuB,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,IAAW,WAAW;QACrB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;YACvB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,CAAC;SAC/D;QACD,OAAO,IAAI,CAAC,YAAY,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,IAAW,UAAU;QACpB,OAAO,IAAI,CAAC,mBAAmB,CAAC,GAAG,EAAE,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,IAAW,kBAAkB;QAC5B,OAAO,kBAAkB,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,IAAW,sBAAsB;QAChC,OAAO,IAAI,CAAC,uBAAuB,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,IAAW,MAAM;QAChB,OAAO,IAAI,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC;IACvF,CAAC;IAED;;OAEG;IACH,IAAW,qBAAqB;QAG/B,OAAO,IAAI,CAAC,sBAAsB,EAAE;YACnC,CAAC,CAAC,IAAI,CAAC,gCAAgC;YACvC,CAAC,CAAC,IAAI,CAAC,+BAA+B,CAAC;IACzC,CAAC;IAEO,uBAAuB,CAC9B,cAA8D,EAC9D,WAAmC;QAEnC,MAAM,MAAM,GAAG,IAAA,uCAAqB,EAAC;YACpC,OAAO,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC;SAC3C,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,4BAA4B,CAAC;YACpD,GAAG,WAAW;YACd,MAAM;YACN,UAAU,EAAE,WAAW,EAAE,UAAU,IAAI,IAAI,iCAAe,CAAC,cAAc,CAAC;YAC1E,WAAW,EAAE,WAAW,EAAE,WAAW,IAAI,IAAI,CAAC,WAAW;YACzD,sBAAsB,EACrB,WAAW,EAAE,sBAAsB,IAAI,IAAI,CAAC,sBAAsB;SACnE,CAAC,CAAC;QAEH,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC;IACf,CAAC;IAEO,sBAAsB,CAC7B,cAA8D,EAC9D,WAAmC;QAEnC,MAAM,MAAM,GAAG,IAAA,uCAAqB,EAAC;YACpC,OAAO,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC;SAC3C,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,2BAA2B,CAAC;YACnD,GAAG,WAAW;YACd,MAAM;YACN,UAAU,EAAE,WAAW,EAAE,UAAU,IAAI,IAAI,iCAAe,CAAC,cAAc,CAAC;YAC1E,WAAW,EAAE,WAAW,EAAE,WAAW,IAAI,IAAI,CAAC,WAAW;YACzD,sBAAsB,EACrB,WAAW,EAAE,sBAAsB,IAAI,IAAI,CAAC,sBAAsB;SACnE,CAAC,CAAC;QAEH,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;OAEG;IACI,YAAY,CAClB,cAA8D,EAC9D,WAAmC;QAEnC,OAAO,IAAI,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,IAAI,CAAC;YACxD,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,cAAc,EAAE,WAAW,CAAC;YAC3D,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;IAC7D,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,eAAe,CAAC,UAA2B,EAAE,WAAmC;QAC5F,IAAI,IAAI,CAAC,gBAAgB,EAAE;YAC1B,MAAM,IAAI,KAAK,CACd,8FAA8F,CAC9F,CAAC;SACF;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QAClF,MAAM,SAAS,GAAG,MAAM,IAAA,sCAAwB,EAC/C,kBAAkB,EAClB,MAAM,EACN,IAAI,CAAC,iBAAiB,CAAC,sBAAsB,CAAC,IAAI,CAAC,UAAU,CAAC,CAC9D,CAAC;QACF,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,4DAA4D;QAC5D,uEAAuE;QACvE,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QACvD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,aAAa,CACzB,UAA2B,EAC3B,WAAmC,EACnC,aAA8B;QAE9B,MAAM,MAAM,GAAG,IAAI,CAAC,sBAAsB,EAAE;YAC3C,CAAC,CAAC,IAAI,CAAC,iBAAiB;YACxB,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QAClF,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;IAC7D,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAC7B,MAAe,EACf,OAAwB,EACxB,MAAoB;QAEpB,OAAO,MAAM,CAAC,OAAO,CAAC;YACrB,oEAAoE;YACpE,GAAG,EAAE,MAAM,MAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC;YACtD,OAAO;SACP,CAAC,CAAC;IACJ,CAAC;IAED;;OAEG;IACI,cAAc,CAAC,mBAA0C;QAC/D,OAAO,IAAI,CAAC,YAAY,CACvB,CAAC,CAAC,kBAAkB,EAAE,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,CAAC,CAAC,EACvE,mBAAmB,EAAE,WAAW,CAChC,CAAC;IACH,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,iBAAiB,CAC7B,mBAA0C;QAE1C,IAAI,IAAI,CAAC,gBAAgB,EAAE;YAC1B,MAAM,IAAI,KAAK,CACd,kGAAkG,CAClG,CAAC;SACF;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAC/B,CAAC,CAAC,kBAAkB,EAAE,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,CAAC,CAAC,EACvE,mBAAmB,EAAE,WAAW,CAChC,CAAC;QACF,MAAM,SAAS,GAAG,MAAM,IAAA,sCAAwB,EAC/C,kBAAkB,EAClB,MAAM,EACN,IAAI,CAAC,iBAAiB,CAAC,sBAAsB,CAAC,IAAI,CAAC,UAAU,CAAC,CAC9D,CAAC;QACF,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,4DAA4D;QAC5D,uEAAuE;QACvE,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QACvD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,iBAAiB,CAC7B,mBAA0C,EAC1C,aAA8B;QAE9B,2FAA2F;QAC3F,MAAM,MAAM,GAAG,IAAI,CAAC,sBAAsB,EAAE;YAC3C,CAAC,CAAC,IAAI,CAAC,iBAAiB;YACxB,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;QAC7E,MAAM,IAAI,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;QAE7C,OAAO,SAAS,CAAC;IAClB,CAAC;IAED;;OAEG;IACI,KAAK;QACX,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,uBAAuB,CAAC,KAAK,EAAE,CAAC;QACrC,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;QACzB,IAAI,CAAC,uBAAuB,GAAG,SAAS,CAAC;QACzC,IAAI,CAAC,YAAY,GAAG,SAAS,CAAC;QAC9B,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,8BAA8B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9D,IAAI,QAAQ,EAAE;YACb,MAAM,QAAQ,CAAC;SACf;QACD,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;IAC/B,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,kBAAkB;QAC9B,OAAO,IAAI,CAAC,uBAAuB,CAAC,kBAAkB,EAAE,CAAC;IAC1D,CAAC;IAEO,KAAK,CAAC,sBAAsB,CAAC,SAAqB;QACzD,6FAA6F;QAC7F,yFAAyF;QACzF,2FAA2F;QAC3F,uFAAuF;QACvF,IAAK,SAAiB,CAAC,OAAO,KAAK,SAAS,EAAE;YAC5C,SAAiB,CAAC,OAAO,GAAI,SAAiB,CAAC,MAAM,CAAC;SACvD;QAED,OAAO,IAAA,yCAA+B,EAAC,SAAS,CAAC,CAAC;IACnD,CAAC;IAED;;OAEG;IACI,gBAAgB,CAAC,WAAqC;QAC5D,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACI,2BAA2B,CAAC,wBAAiC,KAAK;QACxE,IAAI,CAAC,uBAAuB,CAAC,KAAK,EAAE,CAAC;QACrC,IAAI,CAAC,uBAAuB,GAAG,IAAI,+CAAsB,CAAC,qBAAqB,CAAC,CAAC;IAClF,CAAC;IAEO,sBAAsB,CAAC,YAAqB,KAAK;QACxD,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,GAAG,CAAC,KAAK,CAAC,CAAC;QAC/C,IAAI,SAAS,EAAE;YACd,IAAI,CAAC,UAAU,EAAE,CAAC;SAClB;QACD,OAAO,YAAY,CAAC;IACrB,CAAC;CACD;AAvUD,kFAuUC;AAED;;GAEG;AACH,SAAgB,8BAA8B,CAC7C,MAA+C,EAC/C,MAAe;IAEf,IAAI,MAAM,KAAK,SAAS,EAAE;QACzB,OAAO;KACP;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,2BAA2B,EAAE,CAAC;IACrD,IAAI,OAAO,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE;QACxC,OAAO,IAAI,KAAK,CACf,GAAG,MAAM,IAAI,EAAE,+BAA+B,IAAI,CAAC,SAAS,CAC3D,OAAO,CAAC,gBAAgB,EACxB,SAAS,EACT,CAAC,CACD,EAAE,CACH,CAAC;KACF;IACD,IAAI,OAAO,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE;QACxC,OAAO,IAAI,KAAK,CACf,GAAG,MAAM,IAAI,EAAE,+BAA+B,IAAI,CAAC,SAAS,CAC3D,OAAO,CAAC,gBAAgB,EACxB,SAAS,EACT,CAAC,CACD,EAAE,CACH,CAAC;KACF;AACF,CAAC;AA1BD,wEA0BC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tIContainer,\n\tIHostLoader,\n\tIFluidCodeDetails,\n\tILoader,\n} from \"@fluidframework/container-definitions\";\nimport {\n\tILoaderProps,\n\tLoader,\n\twaitContainerToCatchUp as waitContainerToCatchUp_original,\n} from \"@fluidframework/container-loader\";\nimport { IContainerRuntimeOptions } from \"@fluidframework/container-runtime\";\nimport {\n\tITelemetryGenericEvent,\n\tITelemetryBaseLogger,\n\tITelemetryBaseEvent,\n\tIRequestHeader,\n} from \"@fluidframework/core-interfaces\";\nimport {\n\tIDocumentServiceFactory,\n\tIResolvedUrl,\n\tIUrlResolver,\n} from \"@fluidframework/driver-definitions\";\nimport { ITestDriver, TestDriverTypes } from \"@fluidframework/test-driver-definitions\";\nimport { v4 as uuid } from \"uuid\";\nimport { createChildLogger, createMultiSinkLogger } from \"@fluidframework/telemetry-utils\";\nimport { LoaderContainerTracker } from \"./loaderContainerTracker\";\nimport { fluidEntryPoint, LocalCodeLoader } from \"./localCodeLoader\";\nimport { createAndAttachContainer } from \"./localLoader\";\nimport { ChannelFactoryRegistry } from \"./testFluidObject\";\n\nconst defaultCodeDetails: IFluidCodeDetails = {\n\tpackage: \"defaultTestPackage\",\n\tconfig: {},\n};\n\n/**\n * @alpha\n */\nexport interface IOpProcessingController {\n\tprocessIncoming(...containers: IContainer[]): Promise<void>;\n\tprocessOutgoing(...containers: IContainer[]): Promise<void>;\n\tpauseProcessing(...containers: IContainer[]): Promise<void>;\n\tresumeProcessing(...containers: IContainer[]): void;\n}\n\n/**\n * @internal\n */\nexport interface ITestObjectProvider {\n\t/**\n\t * Indicates which type of test object provider is being used.\n\t */\n\ttype: \"TestObjectProvider\" | \"TestObjectProviderWithVersionedLoad\";\n\n\t/**\n\t * The document id to retrieve or create containers\n\t */\n\tdocumentId: string;\n\n\t/**\n\t * Creates the document service after extracting different endpoints URLs from a resolved URL.\n\t */\n\tdocumentServiceFactory: IDocumentServiceFactory;\n\n\t/**\n\t * Test driver used to create the IDocumentServiceFactory. Varies depending on the test type.\n\t */\n\tdriver: ITestDriver;\n\n\t/**\n\t * Logger used to track expected and unexpected events.\n\t */\n\tlogger: EventAndErrorTrackingLogger | undefined;\n\n\t/**\n\t * Used to create a url for the created container with any data store path given in the relative url.\n\t */\n\turlResolver: IUrlResolver;\n\n\t/**\n\t * Default IFluidCodeDetails used to create containers.\n\t */\n\tdefaultCodeDetails: IFluidCodeDetails;\n\n\t/**\n\t * Contains functions to pause/resume op processing.\n\t */\n\topProcessingController: IOpProcessingController;\n\n\t/**\n\t * Represents the entry point for a Fluid container.\n\t */\n\tcreateFluidEntryPoint: (testContainerConfig?: ITestContainerConfig) => fluidEntryPoint;\n\n\t/**\n\t * Create a loader. Containers created/loaded through this loader will be added to the OpProcessingController.\n\t *\n\t * Only the version of the loader will vary based on compat config. The version of\n\t * containerRuntime/dataRuntime used in fluidEntryPoint will be used as is from what is passed in.\n\t *\n\t * @param packageEntries - list of code details and fluidEntryPoint pairs.\n\t */\n\tcreateLoader(\n\t\tpackageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,\n\t\tloaderProps?: Partial<ILoaderProps>,\n\t): IHostLoader;\n\n\t/**\n\t * Create a container using a default document id and code details.\n\t * Container created is automatically added to the OpProcessingController to manage op flow\n\t *\n\t * Only the version of the loader will vary based on compat config. The version of\n\t * containerRuntime/dataRuntime used in fluidEntryPoint will be used as is from what is passed in.\n\t *\n\t * @param packageEntries - list of code details and fluidEntryPoint pairs.\n\t */\n\n\tcreateContainer(\n\t\tentryPoint: fluidEntryPoint,\n\t\tloaderProps?: Partial<ILoaderProps>,\n\t): Promise<IContainer>;\n\n\t/**\n\t * Loads a container using the default document id\n\t */\n\tloadContainer(\n\t\tentryPoint: fluidEntryPoint,\n\t\tloaderProps?: Partial<ILoaderProps>,\n\t\trequestHeader?: IRequestHeader,\n\t): Promise<IContainer>;\n\n\t/**\n\t * Make a test loader. Containers created/loaded through this loader will be added to the OpProcessingController.\n\t * The version of the loader/containerRuntime/dataRuntime may vary based on compat config of the current run\n\t * @param testContainerConfig - optional configuring the test Container\n\t */\n\tmakeTestLoader(testContainerConfig?: ITestContainerConfig): IHostLoader;\n\n\t/**\n\t * Make a container using a default document id and code details\n\t * Container loaded is automatically added to the OpProcessingController to manage op flow\n\t * @param testContainerConfig - optional configuring the test Container\n\t */\n\tmakeTestContainer(testContainerConfig?: ITestContainerConfig): Promise<IContainer>;\n\n\t/**\n\t * Load a container using a default document id and code details.\n\t * IContainer loaded is automatically added to the OpProcessingController to manage op flow\n\t * @param testContainerConfig - optional configuring the test Container\n\t * @param requestHeader - optional headers to be supplied to the loader\n\t */\n\tloadTestContainer(\n\t\ttestContainerConfig?: ITestContainerConfig,\n\t\trequestHeader?: IRequestHeader,\n\t): Promise<IContainer>;\n\n\t/**\n\t * Update the document ID from the resolved container's URL and reset the ID property\n\t */\n\tupdateDocumentId(url: IResolvedUrl | undefined): void;\n\n\t/**\n\t * Make sure all the tracked containers are synchronized.\n\t */\n\tensureSynchronized(timeoutDuration?: number): Promise<void>;\n\n\t/**\n\t * Reset the tracker, closing all containers and stop tracking them.\n\t */\n\tresetLoaderContainerTracker(syncSummarizerClients?: boolean);\n\n\t/**\n\t * Resets and closes all tracked containers and class states.\n\t */\n\treset(): void;\n}\n\n/**\n * @internal\n */\nexport enum DataObjectFactoryType {\n\tPrimed, // default\n\tTest,\n}\n\n/**\n * @internal\n */\nexport interface ITestContainerConfig {\n\t/** TestFluidDataObject instead of PrimedDataStore */\n\tfluidDataObjectType?: DataObjectFactoryType;\n\n\t/** An array of channel name and DDS factory pair to create on container creation time */\n\tregistry?: ChannelFactoryRegistry;\n\n\t/** Container runtime options for the container instance */\n\truntimeOptions?: IContainerRuntimeOptions;\n\n\t/** Whether this runtime should be instantiated using a mixed-in attributor class */\n\tenableAttribution?: boolean;\n\n\t/** Loader options for the loader used to create containers */\n\tloaderProps?: Partial<ILoaderProps>;\n}\n\n/**\n * @internal\n */\nexport const createDocumentId = (): string => uuid();\n\n/**\n * Used to retrieve, update, and reset document id based on the type of driver being used.\n *\n * @internal\n */\nexport interface IDocumentIdStrategy {\n\t/**\n\t * Get document id\n\t */\n\tget(): string;\n\t/**\n\t * Update the document ID from the resolved container's URL and reset the ID property\n\t */\n\tupdate(resolvedUrl?: IResolvedUrl): void;\n\t/**\n\t * Reset document id to a new document id\n\t */\n\treset(): void;\n}\n\n/**\n * Document ID is treated differently by test drivers. The key difference is in generating\n * a new container ID and accessing the container in multi-instance test cases.\n */\nfunction getDocumentIdStrategy(type?: TestDriverTypes): IDocumentIdStrategy {\n\tlet documentId = createDocumentId();\n\tswitch (type) {\n\t\tcase \"odsp\":\n\t\t\treturn {\n\t\t\t\tget: () => documentId,\n\t\t\t\tupdate: () => {}, // do not update the document ID in odsp test cases\n\t\t\t\treset: () => {\n\t\t\t\t\tdocumentId = createDocumentId();\n\t\t\t\t},\n\t\t\t};\n\t\tdefault:\n\t\t\treturn {\n\t\t\t\tget: () => documentId,\n\t\t\t\tupdate: (resolvedUrl?: IResolvedUrl) => {\n\t\t\t\t\t// Extract the document ID from the resolved container's URL and reset the ID property\n\t\t\t\t\tdocumentId = resolvedUrl?.id ?? documentId;\n\t\t\t\t},\n\t\t\t\treset: () => {\n\t\t\t\t\tdocumentId = createDocumentId();\n\t\t\t\t},\n\t\t\t};\n\t}\n}\n\n/**\n * This class tracks events. It allows specifying expected events, which will be looked for in order.\n * It also tracks all unexpected errors.\n * At any point you call reportAndClearTrackedEvents which will provide all unexpected errors, and\n * any expected events that have not occurred.\n * @internal\n */\nexport class EventAndErrorTrackingLogger implements ITelemetryBaseLogger {\n\t/**\n\t * Even if these error events are logged, tests should still be allowed to pass\n\t * Additionally, if downgrade is true, then log as generic (e.g. to avoid polluting the e2e test logs)\n\t */\n\tprivate readonly allowedErrors: { eventName: string; downgrade?: true }[] = [\n\t\t// This log was removed in current version as unnecessary, but it's still present in previous versions\n\t\t{\n\t\t\teventName: \"fluid:telemetry:Container:NoRealStorageInDetachedContainer\",\n\t\t\tdowngrade: true,\n\t\t},\n\t\t// This log's category changes depending on the op latency. test results shouldn't be affected but if we see lots we'd like an alert from the logs.\n\t\t{ eventName: \"fluid:telemetry:OpPerf:OpRoundtripTime\" },\n\t];\n\n\tconstructor(private readonly baseLogger: ITelemetryBaseLogger) {}\n\n\tprivate readonly expectedEvents: (\n\t\t| { index: number; event: ITelemetryGenericEvent | undefined }\n\t\t| undefined\n\t)[] = [];\n\tprivate readonly unexpectedErrors: ITelemetryBaseEvent[] = [];\n\n\tpublic registerExpectedEvent(...orderedExpectedEvents: ITelemetryGenericEvent[]) {\n\t\tif (this.expectedEvents.length !== 0) {\n\t\t\t// we don't have to error here. just no reason not to. given the events must be\n\t\t\t// ordered it could be tricky to figure out problems around multiple registrations.\n\t\t\tthrow new Error(\n\t\t\t\t\"Expected events already registered.\\n\" +\n\t\t\t\t\t\"Call reportAndClearTrackedEvents to clear them before registering more\",\n\t\t\t);\n\t\t}\n\t\tthis.expectedEvents.push(\n\t\t\t...orderedExpectedEvents.map((event, index) => ({ index, event })),\n\t\t);\n\t}\n\n\tsend(event: ITelemetryBaseEvent): void {\n\t\tconst ee = this.expectedEvents[0]?.event;\n\t\tif (ee?.eventName === event.eventName) {\n\t\t\tlet matches = true;\n\t\t\tfor (const key of Object.keys(ee)) {\n\t\t\t\tif (ee[key] !== event[key]) {\n\t\t\t\t\tmatches = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (matches) {\n\t\t\t\t// we found an expected event\n\t\t\t\t// so remove it from the list of expected events\n\t\t\t\t// and if it is an error, change it to generic\n\t\t\t\t// this helps keep our telemetry clear of\n\t\t\t\t// expected errors.\n\t\t\t\tthis.expectedEvents.shift();\n\t\t\t\tif (event.category === \"error\") {\n\t\t\t\t\tevent.category = \"generic\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (event.category === \"error\") {\n\t\t\t// Check to see if this error is allowed and if its category should be downgraded\n\t\t\tconst allowedError = this.allowedErrors.find(\n\t\t\t\t({ eventName }) => eventName === event.eventName,\n\t\t\t);\n\n\t\t\tif (allowedError === undefined) {\n\t\t\t\tthis.unexpectedErrors.push(event);\n\t\t\t} else if (allowedError.downgrade) {\n\t\t\t\tevent.category = \"generic\";\n\t\t\t}\n\t\t}\n\n\t\tthis.baseLogger.send(event);\n\t}\n\n\tpublic reportAndClearTrackedEvents() {\n\t\tconst expectedNotFound = this.expectedEvents.splice(0, this.expectedEvents.length);\n\t\tconst unexpectedErrors = this.unexpectedErrors.splice(0, this.unexpectedErrors.length);\n\t\treturn {\n\t\t\texpectedNotFound,\n\t\t\tunexpectedErrors,\n\t\t};\n\t}\n}\n\n/**\n * Shared base class for test object provider. Contain code for loader and container creation and loading\n * @internal\n */\nexport class TestObjectProvider implements ITestObjectProvider {\n\t/**\n\t * {@inheritDoc ITestObjectProvider.\"type\"}\n\t */\n\tpublic readonly type = \"TestObjectProvider\";\n\tprivate _loaderContainerTracker = new LoaderContainerTracker();\n\tprivate _documentServiceFactory: IDocumentServiceFactory | undefined;\n\tprivate _urlResolver: IUrlResolver | undefined;\n\tprivate _logger: EventAndErrorTrackingLogger | undefined;\n\tprivate readonly _documentIdStrategy: IDocumentIdStrategy;\n\t// Since documentId doesn't change we can only create/make one container. Call the load functions instead.\n\tprivate _documentCreated = false;\n\n\t/**\n\t * Manage objects for loading and creating container, including the driver, loader, and OpProcessingController\n\t * @param createFluidEntryPoint - callback to create a fluidEntryPoint, with an optional set of channel name\n\t * and factory for TestFluidObject\n\t */\n\tconstructor(\n\t\tprivate readonly LoaderConstructor: typeof Loader,\n\t\t/**\n\t\t * {@inheritDoc ITestObjectProvider.driver}\n\t\t */\n\t\tpublic readonly driver: ITestDriver,\n\t\t/**\n\t\t * {@inheritDoc ITestObjectProvider.createFluidEntryPoint}\n\t\t */\n\t\tpublic readonly createFluidEntryPoint: (\n\t\t\ttestContainerConfig?: ITestContainerConfig,\n\t\t) => fluidEntryPoint,\n\t) {\n\t\tthis._documentIdStrategy = getDocumentIdStrategy(driver.type);\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.logger}\n\t */\n\tpublic get logger(): EventAndErrorTrackingLogger {\n\t\tif (this._logger === undefined) {\n\t\t\tthis._logger = new EventAndErrorTrackingLogger(\n\t\t\t\tcreateChildLogger({\n\t\t\t\t\tlogger: getTestLogger?.(),\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tall: {\n\t\t\t\t\t\t\tdriverType: this.driver.type,\n\t\t\t\t\t\t\tdriverEndpointName: this.driver.endpointName,\n\t\t\t\t\t\t\tdriverTenantName: this.driver.tenantName,\n\t\t\t\t\t\t\tdriverUserIndex: this.driver.userIndex,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn this._logger;\n\t}\n\n\tprivate set logger(logger: EventAndErrorTrackingLogger) {\n\t\tthis._logger = logger;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.documentServiceFactory}\n\t */\n\tpublic get documentServiceFactory() {\n\t\tif (!this._documentServiceFactory) {\n\t\t\tthis._documentServiceFactory = this.driver.createDocumentServiceFactory();\n\t\t}\n\t\treturn this._documentServiceFactory;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.urlResolver}\n\t */\n\tpublic get urlResolver() {\n\t\tif (!this._urlResolver) {\n\t\t\tthis._urlResolver = this.driver.createUrlResolver();\n\t\t}\n\t\treturn this._urlResolver;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.documentId}\n\t */\n\tpublic get documentId() {\n\t\treturn this._documentIdStrategy.get();\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.defaultCodeDetails}\n\t */\n\tpublic get defaultCodeDetails() {\n\t\treturn defaultCodeDetails;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.opProcessingController}\n\t */\n\tpublic get opProcessingController(): IOpProcessingController {\n\t\treturn this._loaderContainerTracker;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.createLoader}\n\t */\n\tpublic createLoader(\n\t\tpackageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,\n\t\tloaderProps?: Partial<ILoaderProps>,\n\t) {\n\t\tconst logger = createMultiSinkLogger({\n\t\t\tloggers: [this.logger, loaderProps?.logger],\n\t\t});\n\n\t\tconst loader = new this.LoaderConstructor({\n\t\t\t...loaderProps,\n\t\t\tlogger,\n\t\t\tcodeLoader: loaderProps?.codeLoader ?? new LocalCodeLoader(packageEntries),\n\t\t\turlResolver: loaderProps?.urlResolver ?? this.urlResolver,\n\t\t\tdocumentServiceFactory:\n\t\t\t\tloaderProps?.documentServiceFactory ?? this.documentServiceFactory,\n\t\t});\n\t\tthis._loaderContainerTracker.add(loader);\n\t\treturn loader;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.createContainer}\n\t */\n\tpublic async createContainer(entryPoint: fluidEntryPoint, loaderProps?: Partial<ILoaderProps>) {\n\t\tif (this._documentCreated) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Only one container/document can be created. To load the container/document use loadContainer\",\n\t\t\t);\n\t\t}\n\t\tconst loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);\n\t\tconst container = await createAndAttachContainer(\n\t\t\tdefaultCodeDetails,\n\t\t\tloader,\n\t\t\tthis.driver.createCreateNewRequest(this.documentId),\n\t\t);\n\t\tthis._documentCreated = true;\n\t\t// r11s driver will generate a new ID for the new container.\n\t\t// update the document ID with the actual ID of the attached container.\n\t\tthis._documentIdStrategy.update(container.resolvedUrl);\n\t\treturn container;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.loadContainer}\n\t */\n\tpublic async loadContainer(\n\t\tentryPoint: fluidEntryPoint,\n\t\tloaderProps?: Partial<ILoaderProps>,\n\t\trequestHeader?: IRequestHeader,\n\t): Promise<IContainer> {\n\t\tconst loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);\n\t\treturn this.resolveContainer(loader, requestHeader);\n\t}\n\n\tprivate async resolveContainer(loader: ILoader, headers?: IRequestHeader) {\n\t\treturn loader.resolve({\n\t\t\turl: await this.driver.createContainerUrl(this.documentId),\n\t\t\theaders,\n\t\t});\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.makeTestLoader}\n\t */\n\tpublic makeTestLoader(testContainerConfig?: ITestContainerConfig) {\n\t\treturn this.createLoader(\n\t\t\t[[defaultCodeDetails, this.createFluidEntryPoint(testContainerConfig)]],\n\t\t\ttestContainerConfig?.loaderProps,\n\t\t);\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.makeTestContainer}\n\t */\n\tpublic async makeTestContainer(\n\t\ttestContainerConfig?: ITestContainerConfig,\n\t): Promise<IContainer> {\n\t\tif (this._documentCreated) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Only one container/document can be created. To load the container/document use loadTestContainer\",\n\t\t\t);\n\t\t}\n\t\tconst loader = this.makeTestLoader(testContainerConfig);\n\t\tconst container = await createAndAttachContainer(\n\t\t\tdefaultCodeDetails,\n\t\t\tloader,\n\t\t\tthis.driver.createCreateNewRequest(this.documentId),\n\t\t);\n\t\tthis._documentCreated = true;\n\t\t// r11s driver will generate a new ID for the new container.\n\t\t// update the document ID with the actual ID of the attached container.\n\t\tthis._documentIdStrategy.update(container.resolvedUrl);\n\t\treturn container;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.loadTestContainer}\n\t */\n\tpublic async loadTestContainer(\n\t\ttestContainerConfig?: ITestContainerConfig,\n\t\trequestHeader?: IRequestHeader,\n\t): Promise<IContainer> {\n\t\tconst loader = this.makeTestLoader(testContainerConfig);\n\n\t\tconst container = await this.resolveContainer(loader, requestHeader);\n\t\tawait this.waitContainerToCatchUp(container);\n\n\t\treturn container;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.reset}\n\t */\n\tpublic reset() {\n\t\tthis._loaderContainerTracker.reset();\n\t\tthis._documentServiceFactory = undefined;\n\t\tthis._urlResolver = undefined;\n\t\tthis._documentIdStrategy.reset();\n\t\tconst logError = getUnexpectedLogErrorException(this._logger);\n\t\tif (logError) {\n\t\t\tthrow logError;\n\t\t}\n\t\tthis._logger = undefined;\n\t\tthis._documentCreated = false;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.ensureSynchronized}\n\t */\n\tpublic async ensureSynchronized(): Promise<void> {\n\t\treturn this._loaderContainerTracker.ensureSynchronized();\n\t}\n\n\tprivate async waitContainerToCatchUp(container: IContainer) {\n\t\t// The original waitContainerToCatchUp() from container loader uses either Container.resume()\n\t\t// or Container.connect() as part of its implementation. However, resume() was deprecated\n\t\t// and eventually replaced with connect(). To avoid issues during LTS compatibility testing\n\t\t// with older container versions issues, we use resume() when connect() is unavailable.\n\t\tif ((container as any).connect === undefined) {\n\t\t\t(container as any).connect = (container as any).resume;\n\t\t}\n\n\t\treturn waitContainerToCatchUp_original(container);\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.updateDocumentId}\n\t */\n\tpublic updateDocumentId(resolvedUrl: IResolvedUrl | undefined) {\n\t\tthis._documentIdStrategy.update(resolvedUrl);\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.resetLoaderContainerTracker}\n\t */\n\tpublic resetLoaderContainerTracker(syncSummarizerClients: boolean = false) {\n\t\tthis._loaderContainerTracker.reset();\n\t\tthis._loaderContainerTracker = new LoaderContainerTracker(syncSummarizerClients);\n\t}\n}\n\n/**\n * Implements {@link ITestObjectProvider}, but uses different versions to create and load containers.\n *\n * @internal\n */\nexport class TestObjectProviderWithVersionedLoad implements ITestObjectProvider {\n\t/**\n\t * {@inheritDoc ITestObjectProvider.\"type\"}\n\t */\n\tpublic readonly type = \"TestObjectProviderWithVersionedLoad\";\n\tprivate _loaderContainerTracker = new LoaderContainerTracker();\n\tprivate _logger: EventAndErrorTrackingLogger | undefined;\n\tprivate readonly _documentIdStrategy: IDocumentIdStrategy;\n\tprivate _documentServiceFactory: IDocumentServiceFactory | undefined;\n\tprivate _urlResolver: IUrlResolver | undefined;\n\t// Since documentId doesn't change we can only create/make one container. Call the load functions instead.\n\tprivate _documentCreated = false;\n\n\t/**\n\t * `_loadCount` is used to alternate which version we load the next container with.\n\t * loadCount is even then we will load with the \"create\" version, and if odd we load with the \"load\" version.\n\t * After each test we will reset loadCount to 0 to ensure we always create the first container with the create version.\n\t *\n\t * Note: This will only affect tests that load a container more than two times.\n\t */\n\n\tprivate _loadCount: number = 0;\n\n\tconstructor(\n\t\tprivate readonly LoaderConstructorForCreating: typeof Loader,\n\t\tprivate readonly LoaderConstructorForLoading: typeof Loader,\n\t\tprivate readonly driverForCreating: ITestDriver,\n\t\tprivate readonly driverForLoading: ITestDriver,\n\t\tprivate readonly createFluidEntryPointForCreating: (\n\t\t\ttestContainerConfig?: ITestContainerConfig,\n\t\t) => fluidEntryPoint,\n\t\tprivate readonly createFluidEntryPointForLoading: (\n\t\t\ttestContainerConfig?: ITestContainerConfig,\n\t\t) => fluidEntryPoint,\n\t) {\n\t\tthis._documentIdStrategy = getDocumentIdStrategy(driverForCreating.type);\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.logger}\n\t */\n\tpublic get logger(): EventAndErrorTrackingLogger {\n\t\tif (this._logger === undefined) {\n\t\t\tthis._logger = new EventAndErrorTrackingLogger(\n\t\t\t\tcreateChildLogger({\n\t\t\t\t\tlogger: getTestLogger?.(),\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn this._logger;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.documentServiceFactory}\n\t */\n\tpublic get documentServiceFactory() {\n\t\tif (!this._documentServiceFactory) {\n\t\t\tthis._documentServiceFactory = this.driverForCreating.createDocumentServiceFactory();\n\t\t}\n\t\treturn this._documentServiceFactory;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.urlResolver}\n\t */\n\tpublic get urlResolver() {\n\t\tif (!this._urlResolver) {\n\t\t\tthis._urlResolver = this.driverForCreating.createUrlResolver();\n\t\t}\n\t\treturn this._urlResolver;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.documentId}\n\t */\n\tpublic get documentId() {\n\t\treturn this._documentIdStrategy.get();\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.defaultCodeDetails}\n\t */\n\tpublic get defaultCodeDetails() {\n\t\treturn defaultCodeDetails;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.opProcessingController}\n\t */\n\tpublic get opProcessingController(): IOpProcessingController {\n\t\treturn this._loaderContainerTracker;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.driver}\n\t */\n\tpublic get driver(): ITestDriver {\n\t\treturn this.nextLoaderShouldCreate() ? this.driverForCreating : this.driverForLoading;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.createFluidEntryPoint}\n\t */\n\tpublic get createFluidEntryPoint(): (\n\t\ttestContainerConfig?: ITestContainerConfig,\n\t) => fluidEntryPoint {\n\t\treturn this.nextLoaderShouldCreate()\n\t\t\t? this.createFluidEntryPointForCreating\n\t\t\t: this.createFluidEntryPointForLoading;\n\t}\n\n\tprivate createLoaderForCreating(\n\t\tpackageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,\n\t\tloaderProps?: Partial<ILoaderProps>,\n\t) {\n\t\tconst logger = createMultiSinkLogger({\n\t\t\tloggers: [this.logger, loaderProps?.logger],\n\t\t});\n\n\t\tconst loader = new this.LoaderConstructorForCreating({\n\t\t\t...loaderProps,\n\t\t\tlogger,\n\t\t\tcodeLoader: loaderProps?.codeLoader ?? new LocalCodeLoader(packageEntries),\n\t\t\turlResolver: loaderProps?.urlResolver ?? this.urlResolver,\n\t\t\tdocumentServiceFactory:\n\t\t\t\tloaderProps?.documentServiceFactory ?? this.documentServiceFactory,\n\t\t});\n\n\t\tthis._loaderContainerTracker.add(loader);\n\t\treturn loader;\n\t}\n\n\tprivate createLoaderForLoading(\n\t\tpackageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,\n\t\tloaderProps?: Partial<ILoaderProps>,\n\t) {\n\t\tconst logger = createMultiSinkLogger({\n\t\t\tloggers: [this.logger, loaderProps?.logger],\n\t\t});\n\n\t\tconst loader = new this.LoaderConstructorForLoading({\n\t\t\t...loaderProps,\n\t\t\tlogger,\n\t\t\tcodeLoader: loaderProps?.codeLoader ?? new LocalCodeLoader(packageEntries),\n\t\t\turlResolver: loaderProps?.urlResolver ?? this.urlResolver,\n\t\t\tdocumentServiceFactory:\n\t\t\t\tloaderProps?.documentServiceFactory ?? this.documentServiceFactory,\n\t\t});\n\n\t\tthis._loaderContainerTracker.add(loader);\n\t\treturn loader;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.createLoader}\n\t */\n\tpublic createLoader(\n\t\tpackageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,\n\t\tloaderProps?: Partial<ILoaderProps>,\n\t) {\n\t\treturn this.nextLoaderShouldCreate(/** increment */ true)\n\t\t\t? this.createLoaderForCreating(packageEntries, loaderProps)\n\t\t\t: this.createLoaderForLoading(packageEntries, loaderProps);\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.createContainer}\n\t */\n\tpublic async createContainer(entryPoint: fluidEntryPoint, loaderProps?: Partial<ILoaderProps>) {\n\t\tif (this._documentCreated) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Only one container/document can be created. To load the container/document use loadContainer\",\n\t\t\t);\n\t\t}\n\t\tconst loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);\n\t\tconst container = await createAndAttachContainer(\n\t\t\tdefaultCodeDetails,\n\t\t\tloader,\n\t\t\tthis.driverForCreating.createCreateNewRequest(this.documentId),\n\t\t);\n\t\tthis._documentCreated = true;\n\t\t// r11s driver will generate a new ID for the new container.\n\t\t// update the document ID with the actual ID of the attached container.\n\t\tthis._documentIdStrategy.update(container.resolvedUrl);\n\t\treturn container;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.loadContainer}\n\t */\n\tpublic async loadContainer(\n\t\tentryPoint: fluidEntryPoint,\n\t\tloaderProps?: Partial<ILoaderProps>,\n\t\trequestHeader?: IRequestHeader,\n\t): Promise<IContainer> {\n\t\tconst driver = this.nextLoaderShouldCreate()\n\t\t\t? this.driverForCreating\n\t\t\t: this.driverForLoading;\n\t\tconst loader = this.createLoader([[defaultCodeDetails, entryPoint]], loaderProps);\n\t\treturn this.resolveContainer(loader, requestHeader, driver);\n\t}\n\n\tprivate async resolveContainer(\n\t\tloader: ILoader,\n\t\theaders?: IRequestHeader,\n\t\tdriver?: ITestDriver,\n\t) {\n\t\treturn loader.resolve({\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\turl: await driver!.createContainerUrl(this.documentId),\n\t\t\theaders,\n\t\t});\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.makeTestLoader}\n\t */\n\tpublic makeTestLoader(testContainerConfig?: ITestContainerConfig) {\n\t\treturn this.createLoader(\n\t\t\t[[defaultCodeDetails, this.createFluidEntryPoint(testContainerConfig)]],\n\t\t\ttestContainerConfig?.loaderProps,\n\t\t);\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.makeTestContainer}\n\t */\n\tpublic async makeTestContainer(\n\t\ttestContainerConfig?: ITestContainerConfig,\n\t): Promise<IContainer> {\n\t\tif (this._documentCreated) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Only one container/document can be created. To load the container/document use loadTestContainer\",\n\t\t\t);\n\t\t}\n\t\tconst loader = this.createLoader(\n\t\t\t[[defaultCodeDetails, this.createFluidEntryPoint(testContainerConfig)]],\n\t\t\ttestContainerConfig?.loaderProps,\n\t\t);\n\t\tconst container = await createAndAttachContainer(\n\t\t\tdefaultCodeDetails,\n\t\t\tloader,\n\t\t\tthis.driverForCreating.createCreateNewRequest(this.documentId),\n\t\t);\n\t\tthis._documentCreated = true;\n\t\t// r11s driver will generate a new ID for the new container.\n\t\t// update the document ID with the actual ID of the attached container.\n\t\tthis._documentIdStrategy.update(container.resolvedUrl);\n\t\treturn container;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.loadTestContainer}\n\t */\n\tpublic async loadTestContainer(\n\t\ttestContainerConfig?: ITestContainerConfig,\n\t\trequestHeader?: IRequestHeader,\n\t): Promise<IContainer> {\n\t\t// Keep track of which Loader we are about to use so we can pass the correct driver through\n\t\tconst driver = this.nextLoaderShouldCreate()\n\t\t\t? this.driverForCreating\n\t\t\t: this.driverForLoading;\n\t\tconst loader = this.makeTestLoader(testContainerConfig);\n\t\tconst container = await this.resolveContainer(loader, requestHeader, driver);\n\t\tawait this.waitContainerToCatchUp(container);\n\n\t\treturn container;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.reset}\n\t */\n\tpublic reset() {\n\t\tthis._loadCount = 0;\n\t\tthis._loaderContainerTracker.reset();\n\t\tthis._logger = undefined;\n\t\tthis._documentServiceFactory = undefined;\n\t\tthis._urlResolver = undefined;\n\t\tthis._documentIdStrategy.reset();\n\t\tconst logError = getUnexpectedLogErrorException(this._logger);\n\t\tif (logError) {\n\t\t\tthrow logError;\n\t\t}\n\t\tthis._documentCreated = false;\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.ensureSynchronized}\n\t */\n\tpublic async ensureSynchronized(): Promise<void> {\n\t\treturn this._loaderContainerTracker.ensureSynchronized();\n\t}\n\n\tprivate async waitContainerToCatchUp(container: IContainer) {\n\t\t// The original waitContainerToCatchUp() from container loader uses either Container.resume()\n\t\t// or Container.connect() as part of its implementation. However, resume() was deprecated\n\t\t// and eventually replaced with connect(). To avoid issues during LTS compatibility testing\n\t\t// with older container versions issues, we use resume() when connect() is unavailable.\n\t\tif ((container as any).connect === undefined) {\n\t\t\t(container as any).connect = (container as any).resume;\n\t\t}\n\n\t\treturn waitContainerToCatchUp_original(container);\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.updateDocumentId}\n\t */\n\tpublic updateDocumentId(resolvedUrl: IResolvedUrl | undefined) {\n\t\tthis._documentIdStrategy.update(resolvedUrl);\n\t}\n\n\t/**\n\t * {@inheritDoc ITestObjectProvider.resetLoaderContainerTracker}\n\t */\n\tpublic resetLoaderContainerTracker(syncSummarizerClients: boolean = false) {\n\t\tthis._loaderContainerTracker.reset();\n\t\tthis._loaderContainerTracker = new LoaderContainerTracker(syncSummarizerClients);\n\t}\n\n\tprivate nextLoaderShouldCreate(increment: boolean = false): boolean {\n\t\tconst shouldCreate = this._loadCount % 2 === 0;\n\t\tif (increment) {\n\t\t\tthis._loadCount++;\n\t\t}\n\t\treturn shouldCreate;\n\t}\n}\n\n/**\n * @internal\n */\nexport function getUnexpectedLogErrorException(\n\tlogger: EventAndErrorTrackingLogger | undefined,\n\tprefix?: string,\n) {\n\tif (logger === undefined) {\n\t\treturn;\n\t}\n\tconst results = logger.reportAndClearTrackedEvents();\n\tif (results.unexpectedErrors.length > 0) {\n\t\treturn new Error(\n\t\t\t`${prefix ?? \"\"}Unexpected Errors in Logs:\\n${JSON.stringify(\n\t\t\t\tresults.unexpectedErrors,\n\t\t\t\tundefined,\n\t\t\t\t2,\n\t\t\t)}`,\n\t\t);\n\t}\n\tif (results.expectedNotFound.length > 0) {\n\t\treturn new Error(\n\t\t\t`${prefix ?? \"\"}Expected Events not found:\\n${JSON.stringify(\n\t\t\t\tresults.expectedNotFound,\n\t\t\t\tundefined,\n\t\t\t\t2,\n\t\t\t)}`,\n\t\t);\n\t}\n}\n"]}
|
package/dist/timeoutUtils.d.ts
CHANGED
|
@@ -2,17 +2,59 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
+
/**
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
5
8
|
export declare const defaultTimeoutDurationMs = 250;
|
|
9
|
+
/**
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
6
12
|
export interface TimeoutWithError {
|
|
13
|
+
/**
|
|
14
|
+
* Timeout duration in milliseconds, if it is great than 0 and not Infinity
|
|
15
|
+
* If it is undefined, then it will use test timeout if we are in side the test function
|
|
16
|
+
* Otherwise, there is no timeout
|
|
17
|
+
*/
|
|
7
18
|
durationMs?: number;
|
|
8
19
|
reject?: true;
|
|
9
20
|
errorMsg?: string;
|
|
10
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
11
25
|
export interface TimeoutWithValue<T = void> {
|
|
26
|
+
/**
|
|
27
|
+
* Timeout duration in milliseconds, if it is great than 0 and not Infinity
|
|
28
|
+
* If it is undefined, then it will use test timeout if we are in side the test function
|
|
29
|
+
* Otherwise, there is no timeout
|
|
30
|
+
*/
|
|
12
31
|
durationMs?: number;
|
|
13
32
|
reject: false;
|
|
14
33
|
value: T;
|
|
15
34
|
}
|
|
35
|
+
export type PromiseExecutor<T = void> = (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void;
|
|
36
|
+
/**
|
|
37
|
+
* Wraps the given promise around with promise that will complete after a specific timeout if the original promise does
|
|
38
|
+
* not resolve by then. By default, it uses the mocha test timeout and complete the promise just before that so that
|
|
39
|
+
* tests don't time out because of unpredictable awaits.
|
|
40
|
+
* The timeout can be overridden via timeoutOptions but it's recommended to use the default value.
|
|
41
|
+
* @param promise - The promise to be awaited.
|
|
42
|
+
* @param timeoutOptions - Options that can be used to override the timeout and / or define the behavior
|
|
43
|
+
* when the promise is not fulfilled. For example, instead of rejecting the promise, resolve with a
|
|
44
|
+
* specific value.
|
|
45
|
+
* @returns A new promise that will complete when the given promise resolves or the timeout expires.
|
|
46
|
+
* @internal
|
|
47
|
+
*/
|
|
16
48
|
export declare function timeoutAwait<T = void>(promise: PromiseLike<T>, timeoutOptions?: TimeoutWithError | TimeoutWithValue<T>): Promise<T>;
|
|
49
|
+
/**
|
|
50
|
+
* Creates a promise from the given executor that will complete after a specific timeout. By default, it uses the mocha
|
|
51
|
+
* test timeout and complete the promise just before that so that tests don't time out because of unpredictable awaits.
|
|
52
|
+
* The timeout can be overridden via timeoutOptions but it's recommended to use the default value.
|
|
53
|
+
* @param executor - The executor for the promise.
|
|
54
|
+
* @param timeoutOptions - Options that can be used to override the timeout and / or define the behavior when
|
|
55
|
+
* the promise is not fulfilled. For example, instead of rejecting the promise, resolve with a specific value.
|
|
56
|
+
* @returns A new promise that will complete when the given executor resolves or the timeout expires.
|
|
57
|
+
* @internal
|
|
58
|
+
*/
|
|
17
59
|
export declare function timeoutPromise<T = void>(executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void, timeoutOptions?: TimeoutWithError | TimeoutWithValue<T>): Promise<T>;
|
|
18
60
|
//# sourceMappingURL=timeoutUtils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeoutUtils.d.ts","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"timeoutUtils.d.ts","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;GAEG;AACH,eAAO,MAAM,wBAAwB,MAAM,CAAC;AA8F5C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AACD;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,IAAI;IACzC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;CACT;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,GAAG,IAAI,IAAI,CACvC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,EAC5C,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,KAC1B,IAAI,CAAC;AAEV;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAAC,CAAC,GAAG,IAAI,EAC1C,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,GACzD,OAAO,CAAC,CAAC,CAAC,CAEZ;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAAC,CAAC,GAAG,IAAI,EAC5C,QAAQ,EAAE,CACT,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,EAC5C,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,KAC1B,IAAI,EACT,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,GACzD,OAAO,CAAC,CAAC,CAAC,CA6BZ"}
|
package/dist/timeoutUtils.js
CHANGED
|
@@ -5,24 +5,158 @@
|
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.timeoutPromise = exports.timeoutAwait = exports.defaultTimeoutDurationMs = void 0;
|
|
8
|
+
const core_utils_1 = require("@fluidframework/core-utils");
|
|
9
|
+
// @deprecated this value is no longer used
|
|
10
|
+
/**
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
8
13
|
exports.defaultTimeoutDurationMs = 250;
|
|
14
|
+
const timeBuffer = 15; // leave 15 ms leeway for finish processing
|
|
15
|
+
// TestTimeout class that manages tracking of test timeout. It creates a timer when timeout is in effect,
|
|
16
|
+
// and provides a promise that will be rejected some time (as defined by `timeBuffer`) before the test timeout happens.
|
|
17
|
+
// This will ensure that async awaits in tests do not end up timing out the tests but resolve / reject
|
|
18
|
+
// before that happens.
|
|
19
|
+
// Once rejected, a new TestTimeout object will be create for the timeout.
|
|
20
|
+
class TestTimeout {
|
|
21
|
+
static reset(runnable) {
|
|
22
|
+
TestTimeout.clear();
|
|
23
|
+
TestTimeout.instance.resetTimer(runnable);
|
|
24
|
+
}
|
|
25
|
+
static clear() {
|
|
26
|
+
if (TestTimeout.instance.rejected) {
|
|
27
|
+
TestTimeout.instance = new TestTimeout();
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
TestTimeout.instance.clearTimer();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
static getInstance() {
|
|
34
|
+
return TestTimeout.instance;
|
|
35
|
+
}
|
|
36
|
+
async getPromise() {
|
|
37
|
+
return this.deferred.promise;
|
|
38
|
+
}
|
|
39
|
+
getTimeout() {
|
|
40
|
+
return this.timeout;
|
|
41
|
+
}
|
|
42
|
+
constructor() {
|
|
43
|
+
this.timeout = 0;
|
|
44
|
+
this.rejected = false;
|
|
45
|
+
this.deferred = new core_utils_1.Deferred();
|
|
46
|
+
// Ignore rejection for timeout promise if no one is waiting for it.
|
|
47
|
+
this.deferred.promise.catch(() => { });
|
|
48
|
+
}
|
|
49
|
+
resetTimer(runnable) {
|
|
50
|
+
(0, core_utils_1.assert)(!this.timer, "clearTimer should have been called before reset");
|
|
51
|
+
(0, core_utils_1.assert)(!this.deferred.isCompleted, "can't reset a completed TestTimeout");
|
|
52
|
+
// Check the test timeout setting
|
|
53
|
+
const timeout = runnable.timeout();
|
|
54
|
+
if (!(Number.isFinite(timeout) && timeout > 0)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
// subtract a buffer
|
|
58
|
+
this.timeout = Math.max(timeout - timeBuffer, 1);
|
|
59
|
+
// Set up timer to reject near the test timeout.
|
|
60
|
+
this.timer = setTimeout(() => {
|
|
61
|
+
this.deferred.reject(this);
|
|
62
|
+
this.rejected = true;
|
|
63
|
+
}, this.timeout);
|
|
64
|
+
}
|
|
65
|
+
clearTimer() {
|
|
66
|
+
if (this.timer) {
|
|
67
|
+
clearTimeout(this.timer);
|
|
68
|
+
this.timer = undefined;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
TestTimeout.instance = new TestTimeout();
|
|
73
|
+
// only register if we are running with mocha-test-setup loaded
|
|
74
|
+
if (globalThis.getMochaModule !== undefined) {
|
|
75
|
+
// patching resetTimeout and clearTimeout on the runnable object
|
|
76
|
+
// so we can track when test timeout are enforced
|
|
77
|
+
const mochaModule = globalThis.getMochaModule();
|
|
78
|
+
const runnablePrototype = mochaModule.Runnable.prototype;
|
|
79
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
80
|
+
const oldResetTimeoutFunc = runnablePrototype.resetTimeout;
|
|
81
|
+
runnablePrototype.resetTimeout = function () {
|
|
82
|
+
oldResetTimeoutFunc.call(this);
|
|
83
|
+
TestTimeout.reset(this);
|
|
84
|
+
};
|
|
85
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
86
|
+
const oldClearTimeoutFunc = runnablePrototype.clearTimeout;
|
|
87
|
+
runnablePrototype.clearTimeout = function () {
|
|
88
|
+
TestTimeout.clear();
|
|
89
|
+
oldClearTimeoutFunc.call(this);
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Wraps the given promise around with promise that will complete after a specific timeout if the original promise does
|
|
94
|
+
* not resolve by then. By default, it uses the mocha test timeout and complete the promise just before that so that
|
|
95
|
+
* tests don't time out because of unpredictable awaits.
|
|
96
|
+
* The timeout can be overridden via timeoutOptions but it's recommended to use the default value.
|
|
97
|
+
* @param promise - The promise to be awaited.
|
|
98
|
+
* @param timeoutOptions - Options that can be used to override the timeout and / or define the behavior
|
|
99
|
+
* when the promise is not fulfilled. For example, instead of rejecting the promise, resolve with a
|
|
100
|
+
* specific value.
|
|
101
|
+
* @returns A new promise that will complete when the given promise resolves or the timeout expires.
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
9
104
|
async function timeoutAwait(promise, timeoutOptions = {}) {
|
|
10
105
|
return Promise.race([promise, timeoutPromise(() => { }, timeoutOptions)]);
|
|
11
106
|
}
|
|
12
107
|
exports.timeoutAwait = timeoutAwait;
|
|
108
|
+
/**
|
|
109
|
+
* Creates a promise from the given executor that will complete after a specific timeout. By default, it uses the mocha
|
|
110
|
+
* test timeout and complete the promise just before that so that tests don't time out because of unpredictable awaits.
|
|
111
|
+
* The timeout can be overridden via timeoutOptions but it's recommended to use the default value.
|
|
112
|
+
* @param executor - The executor for the promise.
|
|
113
|
+
* @param timeoutOptions - Options that can be used to override the timeout and / or define the behavior when
|
|
114
|
+
* the promise is not fulfilled. For example, instead of rejecting the promise, resolve with a specific value.
|
|
115
|
+
* @returns A new promise that will complete when the given executor resolves or the timeout expires.
|
|
116
|
+
* @internal
|
|
117
|
+
*/
|
|
13
118
|
async function timeoutPromise(executor, timeoutOptions = {}) {
|
|
14
|
-
|
|
15
|
-
const timeout = timeoutOptions.durationMs !== undefined
|
|
16
|
-
&& Number.isFinite(timeoutOptions.durationMs)
|
|
17
|
-
&& timeoutOptions.durationMs > 0
|
|
18
|
-
? timeoutOptions.durationMs : exports.defaultTimeoutDurationMs;
|
|
19
|
-
// create the timeout error outside the async task, so it's callstack includes
|
|
119
|
+
// create the timeout error outside the async task, so its callstack includes
|
|
20
120
|
// the original call site, this makes it easier to debug
|
|
21
121
|
const err = timeoutOptions.reject === false
|
|
22
122
|
? undefined
|
|
23
|
-
: new Error(
|
|
123
|
+
: new Error(timeoutOptions.errorMsg ?? "Timed out");
|
|
124
|
+
const executorPromise = getTimeoutPromise(executor, timeoutOptions, err);
|
|
125
|
+
const currentTestTimeout = TestTimeout.getInstance();
|
|
126
|
+
if (currentTestTimeout === undefined) {
|
|
127
|
+
return executorPromise;
|
|
128
|
+
}
|
|
129
|
+
return Promise.race([executorPromise, currentTestTimeout.getPromise()]).catch((e) => {
|
|
130
|
+
if (e === currentTestTimeout) {
|
|
131
|
+
if (timeoutOptions.reject !== false) {
|
|
132
|
+
// If the rejection is because of the timeout then
|
|
133
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
134
|
+
const errorObject = err;
|
|
135
|
+
errorObject.message = `${timeoutOptions.errorMsg ?? "Test timed out"} (${currentTestTimeout.getTimeout()}ms)`;
|
|
136
|
+
throw errorObject;
|
|
137
|
+
}
|
|
138
|
+
return timeoutOptions.value;
|
|
139
|
+
}
|
|
140
|
+
throw e;
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
exports.timeoutPromise = timeoutPromise;
|
|
144
|
+
// Create a promise based on the timeout options
|
|
145
|
+
async function getTimeoutPromise(executor, timeoutOptions, err) {
|
|
146
|
+
const timeout = timeoutOptions.durationMs ?? 0;
|
|
147
|
+
if (timeout <= 0 || !Number.isFinite(timeout)) {
|
|
148
|
+
return new Promise(executor);
|
|
149
|
+
}
|
|
24
150
|
return new Promise((resolve, reject) => {
|
|
25
|
-
const
|
|
151
|
+
const timeoutRejections = () => {
|
|
152
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
153
|
+
const errorObject = err;
|
|
154
|
+
errorObject.message = `${errorObject.message} (${timeout}ms)`;
|
|
155
|
+
reject(err);
|
|
156
|
+
};
|
|
157
|
+
const timer = setTimeout(() => timeoutOptions.reject === false
|
|
158
|
+
? resolve(timeoutOptions.value)
|
|
159
|
+
: timeoutRejections(), timeout);
|
|
26
160
|
executor((value) => {
|
|
27
161
|
clearTimeout(timer);
|
|
28
162
|
resolve(value);
|
|
@@ -32,5 +166,4 @@ async function timeoutPromise(executor, timeoutOptions = {}) {
|
|
|
32
166
|
});
|
|
33
167
|
});
|
|
34
168
|
}
|
|
35
|
-
exports.timeoutPromise = timeoutPromise;
|
|
36
169
|
//# sourceMappingURL=timeoutUtils.js.map
|
package/dist/timeoutUtils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeoutUtils.js","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEU,QAAA,wBAAwB,GAAG,GAAG,CAAC;AAarC,KAAK,UAAU,YAAY,CAC9B,OAAuB,EACvB,iBAAyD,EAAE;IAE3D,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,cAAc,CAAI,GAAG,EAAE,GAAG,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;AACjF,CAAC;AALD,oCAKC;AAEM,KAAK,UAAU,cAAc,CAChC,QAAgG,EAChG,iBAAyD,EAAE;;IAE3D,MAAM,OAAO,GACT,cAAc,CAAC,UAAU,KAAK,SAAS;WACpC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAC;WAC1C,cAAc,CAAC,UAAU,GAAG,CAAC;QAC5B,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,gCAAwB,CAAC;IAC/D,8EAA8E;IAC9E,wDAAwD;IACxD,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,KAAK,KAAK;QACvC,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,MAAA,cAAc,CAAC,QAAQ,mCAAI,WAAW,IAAI,OAAO,KAAK,CAAC,CAAC;IAC3E,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACtC,MAAM,KAAK,GAAG,UAAU,CACpB,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EACnF,OAAO,CAAC,CAAC;QAEb,QAAQ,CACJ,CAAC,KAAK,EAAE,EAAE;YACN,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC,EACD,CAAC,MAAM,EAAE,EAAE;YACP,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACP,CAAC;AA7BD,wCA6BC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const defaultTimeoutDurationMs = 250;\n\nexport interface TimeoutWithError {\n durationMs?: number;\n reject?: true;\n errorMsg?: string;\n}\nexport interface TimeoutWithValue<T = void> {\n durationMs?: number;\n reject: false;\n value: T;\n}\n\nexport async function timeoutAwait<T = void>(\n promise: PromiseLike<T>,\n timeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},\n) {\n return Promise.race([promise, timeoutPromise<T>(() => { }, timeoutOptions)]);\n}\n\nexport async function timeoutPromise<T = void>(\n executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void,\n timeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},\n): Promise<T> {\n const timeout =\n timeoutOptions.durationMs !== undefined\n && Number.isFinite(timeoutOptions.durationMs)\n && timeoutOptions.durationMs > 0\n ? timeoutOptions.durationMs : defaultTimeoutDurationMs;\n // create the timeout error outside the async task, so it's callstack includes\n // the original call site, this makes it easier to debug\n const err = timeoutOptions.reject === false\n ? undefined\n : new Error(`${timeoutOptions.errorMsg ?? \"Timed out\"}(${timeout}ms)`);\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(\n () => timeoutOptions.reject === false ? resolve(timeoutOptions.value) : reject(err),\n timeout);\n\n executor(\n (value) => {\n clearTimeout(timer);\n resolve(value);\n },\n (reason) => {\n clearTimeout(timer);\n reject(reason);\n });\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"timeoutUtils.js","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert, Deferred } from \"@fluidframework/core-utils\";\n\n// @deprecated this value is no longer used\n/**\n * @internal\n */\nexport const defaultTimeoutDurationMs = 250;\n\nconst timeBuffer = 15; // leave 15 ms leeway for finish processing\n\n// TestTimeout class that manages tracking of test timeout. It creates a timer when timeout is in effect,\n// and provides a promise that will be rejected some time (as defined by `timeBuffer`) before the test timeout happens.\n// This will ensure that async awaits in tests do not end up timing out the tests but resolve / reject\n// before that happens.\n// Once rejected, a new TestTimeout object will be create for the timeout.\nclass TestTimeout {\n\tprivate timeout: number = 0;\n\tprivate timer: NodeJS.Timeout | undefined;\n\tprivate readonly deferred: Deferred<void>;\n\tprivate rejected = false;\n\n\tprivate static instance: TestTimeout = new TestTimeout();\n\tpublic static reset(runnable: Mocha.Runnable) {\n\t\tTestTimeout.clear();\n\t\tTestTimeout.instance.resetTimer(runnable);\n\t}\n\n\tpublic static clear() {\n\t\tif (TestTimeout.instance.rejected) {\n\t\t\tTestTimeout.instance = new TestTimeout();\n\t\t} else {\n\t\t\tTestTimeout.instance.clearTimer();\n\t\t}\n\t}\n\n\tpublic static getInstance() {\n\t\treturn TestTimeout.instance;\n\t}\n\n\tpublic async getPromise() {\n\t\treturn this.deferred.promise;\n\t}\n\n\tpublic getTimeout() {\n\t\treturn this.timeout;\n\t}\n\n\tprivate constructor() {\n\t\tthis.deferred = new Deferred();\n\t\t// Ignore rejection for timeout promise if no one is waiting for it.\n\t\tthis.deferred.promise.catch(() => {});\n\t}\n\n\tprivate resetTimer(runnable: Mocha.Runnable) {\n\t\tassert(!this.timer, \"clearTimer should have been called before reset\");\n\t\tassert(!this.deferred.isCompleted, \"can't reset a completed TestTimeout\");\n\n\t\t// Check the test timeout setting\n\t\tconst timeout = runnable.timeout();\n\t\tif (!(Number.isFinite(timeout) && timeout > 0)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// subtract a buffer\n\t\tthis.timeout = Math.max(timeout - timeBuffer, 1);\n\n\t\t// Set up timer to reject near the test timeout.\n\t\tthis.timer = setTimeout(() => {\n\t\t\tthis.deferred.reject(this);\n\t\t\tthis.rejected = true;\n\t\t}, this.timeout);\n\t}\n\tprivate clearTimer() {\n\t\tif (this.timer) {\n\t\t\tclearTimeout(this.timer);\n\t\t\tthis.timer = undefined;\n\t\t}\n\t}\n}\n\n// only register if we are running with mocha-test-setup loaded\nif (globalThis.getMochaModule !== undefined) {\n\t// patching resetTimeout and clearTimeout on the runnable object\n\t// so we can track when test timeout are enforced\n\tconst mochaModule = globalThis.getMochaModule() as typeof Mocha;\n\tconst runnablePrototype = mochaModule.Runnable.prototype;\n\t// eslint-disable-next-line @typescript-eslint/unbound-method\n\tconst oldResetTimeoutFunc = runnablePrototype.resetTimeout;\n\trunnablePrototype.resetTimeout = function (this: Mocha.Runnable) {\n\t\toldResetTimeoutFunc.call(this);\n\t\tTestTimeout.reset(this);\n\t};\n\t// eslint-disable-next-line @typescript-eslint/unbound-method\n\tconst oldClearTimeoutFunc = runnablePrototype.clearTimeout;\n\trunnablePrototype.clearTimeout = function (this: Mocha.Runnable) {\n\t\tTestTimeout.clear();\n\t\toldClearTimeoutFunc.call(this);\n\t};\n}\n\n/**\n * @internal\n */\nexport interface TimeoutWithError {\n\t/**\n\t * Timeout duration in milliseconds, if it is great than 0 and not Infinity\n\t * If it is undefined, then it will use test timeout if we are in side the test function\n\t * Otherwise, there is no timeout\n\t */\n\tdurationMs?: number;\n\treject?: true;\n\terrorMsg?: string;\n}\n/**\n * @internal\n */\nexport interface TimeoutWithValue<T = void> {\n\t/**\n\t * Timeout duration in milliseconds, if it is great than 0 and not Infinity\n\t * If it is undefined, then it will use test timeout if we are in side the test function\n\t * Otherwise, there is no timeout\n\t */\n\tdurationMs?: number;\n\treject: false;\n\tvalue: T;\n}\n\nexport type PromiseExecutor<T = void> = (\n\tresolve: (value: T | PromiseLike<T>) => void,\n\treject: (reason?: any) => void,\n) => void;\n\n/**\n * Wraps the given promise around with promise that will complete after a specific timeout if the original promise does\n * not resolve by then. By default, it uses the mocha test timeout and complete the promise just before that so that\n * tests don't time out because of unpredictable awaits.\n * The timeout can be overridden via timeoutOptions but it's recommended to use the default value.\n * @param promise - The promise to be awaited.\n * @param timeoutOptions - Options that can be used to override the timeout and / or define the behavior\n * when the promise is not fulfilled. For example, instead of rejecting the promise, resolve with a\n * specific value.\n * @returns A new promise that will complete when the given promise resolves or the timeout expires.\n * @internal\n */\nexport async function timeoutAwait<T = void>(\n\tpromise: PromiseLike<T>,\n\ttimeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},\n): Promise<T> {\n\treturn Promise.race([promise, timeoutPromise<T>(() => {}, timeoutOptions)]);\n}\n\n/**\n * Creates a promise from the given executor that will complete after a specific timeout. By default, it uses the mocha\n * test timeout and complete the promise just before that so that tests don't time out because of unpredictable awaits.\n * The timeout can be overridden via timeoutOptions but it's recommended to use the default value.\n * @param executor - The executor for the promise.\n * @param timeoutOptions - Options that can be used to override the timeout and / or define the behavior when\n * the promise is not fulfilled. For example, instead of rejecting the promise, resolve with a specific value.\n * @returns A new promise that will complete when the given executor resolves or the timeout expires.\n * @internal\n */\nexport async function timeoutPromise<T = void>(\n\texecutor: (\n\t\tresolve: (value: T | PromiseLike<T>) => void,\n\t\treject: (reason?: any) => void,\n\t) => void,\n\ttimeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},\n): Promise<T> {\n\t// create the timeout error outside the async task, so its callstack includes\n\t// the original call site, this makes it easier to debug\n\tconst err =\n\t\ttimeoutOptions.reject === false\n\t\t\t? undefined\n\t\t\t: new Error(timeoutOptions.errorMsg ?? \"Timed out\");\n\tconst executorPromise = getTimeoutPromise(executor, timeoutOptions, err);\n\n\tconst currentTestTimeout = TestTimeout.getInstance();\n\tif (currentTestTimeout === undefined) {\n\t\treturn executorPromise;\n\t}\n\n\treturn Promise.race([executorPromise, currentTestTimeout.getPromise()]).catch((e) => {\n\t\tif (e === currentTestTimeout) {\n\t\t\tif (timeoutOptions.reject !== false) {\n\t\t\t\t// If the rejection is because of the timeout then\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tconst errorObject = err!;\n\t\t\t\terrorObject.message = `${\n\t\t\t\t\ttimeoutOptions.errorMsg ?? \"Test timed out\"\n\t\t\t\t} (${currentTestTimeout.getTimeout()}ms)`;\n\t\t\t\tthrow errorObject;\n\t\t\t}\n\t\t\treturn timeoutOptions.value;\n\t\t}\n\t\tthrow e;\n\t}) as Promise<T>;\n}\n\n// Create a promise based on the timeout options\nasync function getTimeoutPromise<T = void>(\n\texecutor: (\n\t\tresolve: (value: T | PromiseLike<T>) => void,\n\t\treject: (reason?: any) => void,\n\t) => void,\n\ttimeoutOptions: TimeoutWithError | TimeoutWithValue<T>,\n\terr: Error | undefined,\n) {\n\tconst timeout = timeoutOptions.durationMs ?? 0;\n\tif (timeout <= 0 || !Number.isFinite(timeout)) {\n\t\treturn new Promise(executor);\n\t}\n\n\treturn new Promise<T>((resolve, reject) => {\n\t\tconst timeoutRejections = () => {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tconst errorObject = err!;\n\t\t\terrorObject.message = `${errorObject.message} (${timeout}ms)`;\n\t\t\treject(err);\n\t\t};\n\t\tconst timer = setTimeout(\n\t\t\t() =>\n\t\t\t\ttimeoutOptions.reject === false\n\t\t\t\t\t? resolve(timeoutOptions.value)\n\t\t\t\t\t: timeoutRejections(),\n\t\t\ttimeout,\n\t\t);\n\n\t\texecutor(\n\t\t\t(value) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tresolve(value);\n\t\t\t},\n\t\t\t(reason) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\treject(reason);\n\t\t\t},\n\t\t);\n\t});\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// This file is read by tools that parse documentation comments conforming to the TSDoc standard.
|
|
2
|
+
// It should be published with your NPM package. It should not be tracked by Git.
|
|
3
|
+
{
|
|
4
|
+
"tsdocVersion": "0.12",
|
|
5
|
+
"toolPackages": [
|
|
6
|
+
{
|
|
7
|
+
"packageName": "@microsoft/api-extractor",
|
|
8
|
+
"packageVersion": "7.38.3"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|