@fluidframework/test-utils 0.54.1 → 0.55.1

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 CHANGED
@@ -5,6 +5,6 @@
5
5
 
6
6
  module.exports = {
7
7
  "extends": [
8
- "@fluidframework/eslint-config-fluid/eslint7"
8
+ "@fluidframework/eslint-config-fluid"
9
9
  ]
10
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"loaderContainerTracker.d.ts","sourceRoot":"","sources":["../src/loaderContainerTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,UAAU,EAAe,WAAW,EAAE,MAAM,uCAAuC,CAAC;AAI7F,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAqB/D,qBAAa,sBAAuB,YAAW,uBAAuB;IAClE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0C;IACrE,OAAO,CAAC,kBAAkB,CAAa;IAEvC;;;OAGG;IACI,GAAG,CAAC,UAAU,SAAS,WAAW,EAAE,MAAM,EAAE,UAAU;IAkB7D;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAoBpB;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAsC1B,OAAO,CAAC,iBAAiB;IAQzB;;OAEG;IACI,KAAK;IAUZ;;;;;;;;;;OAUG;IACU,kBAAkB,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAmD3D;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAyBzB;;;;;OAKG;IACH,OAAO,CAAC,4BAA4B;IA0CpC;;;;;;;OAOG;YACW,qBAAqB;IA6BnC;;;OAGG;YACW,oBAAoB;IAclC;;OAEG;IACI,gBAAgB,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAgBnD;;;OAGG;IACU,eAAe,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAexD;;;;OAIG;IACU,eAAe,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAIxD;;;;OAIG;IACU,eAAe,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAIxD;;OAEG;YACW,YAAY;IAqC1B;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAyBzB;;OAEG;IACH,OAAO,CAAC,UAAU;IA+DlB;;;;OAIG;IACH,OAAO,CAAC,aAAa;CAIxB"}
1
+ {"version":3,"file":"loaderContainerTracker.d.ts","sourceRoot":"","sources":["../src/loaderContainerTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,UAAU,EAAe,WAAW,EAAE,MAAM,uCAAuC,CAAC;AAI7F,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAqB/D,qBAAa,sBAAuB,YAAW,uBAAuB;IAClE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0C;IACrE,OAAO,CAAC,kBAAkB,CAAa;IAEvC;;;OAGG;IACI,GAAG,CAAC,UAAU,SAAS,WAAW,EAAE,MAAM,EAAE,UAAU;IAe7D;;;;OAIG;IACH,OAAO,CAAC,YAAY;IAoBpB;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAsC1B,OAAO,CAAC,iBAAiB;IAQzB;;OAEG;IACI,KAAK;IAUZ;;;;;;;;;;OAUG;IACU,kBAAkB,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAmD3D;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAyBzB;;;;;OAKG;IACH,OAAO,CAAC,4BAA4B;IA0CpC;;;;;;;OAOG;YACW,qBAAqB;IA6BnC;;;OAGG;YACW,oBAAoB;IAclC;;OAEG;IACI,gBAAgB,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAgBnD;;;OAGG;IACU,eAAe,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAexD;;;;OAIG;IACU,eAAe,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAIxD;;;;OAIG;IACU,eAAe,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE;IAIxD;;OAEG;YACW,YAAY;IAqC1B;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAyBzB;;OAEG;IACH,OAAO,CAAC,UAAU;IA+DlB;;;;OAIG;IACH,OAAO,CAAC,aAAa;CAIxB"}
@@ -29,11 +29,8 @@ class LoaderContainerTracker {
29
29
  return container;
30
30
  };
31
31
  };
32
- // eslint-disable-next-line @typescript-eslint/unbound-method
33
32
  loader.resolve = patch(loader.resolve);
34
- // eslint-disable-next-line @typescript-eslint/unbound-method
35
33
  loader.createDetachedContainer = patch(loader.createDetachedContainer);
36
- // eslint-disable-next-line @typescript-eslint/unbound-method
37
34
  loader.rehydrateDetachedContainerFromSnapshot = patch(loader.rehydrateDetachedContainerFromSnapshot);
38
35
  }
39
36
  /**
@@ -169,10 +166,10 @@ class LoaderContainerTracker {
169
166
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
170
167
  debugWait(`Waiting container to be saved ${dirtyContainers.map((c) => this.containers.get(c).index)}`);
171
168
  waitingSequenceNumberSynchronized = false;
172
- await Promise.all(dirtyContainers.map(async (c) => new Promise((res) => c.once("saved", res))));
169
+ await Promise.all(dirtyContainers.map(async (c) => new Promise((resolve) => c.once("saved", resolve))));
173
170
  }
174
171
  // yield a turn to allow side effect of the ops we just processed execute before we check again
175
- await new Promise((res) => { setTimeout(res, 0); });
172
+ await new Promise((resolve) => { setTimeout(resolve, 0); });
176
173
  }
177
174
  // Pause all container that was resumed
178
175
  // don't call pause if resumed is empty and pause everything, which is not what we want
@@ -265,7 +262,7 @@ class LoaderContainerTracker {
265
262
  async waitForPendingClients(pendingClients) {
266
263
  const unconnectedClients = Array.from(this.containers.keys()).filter((c) => !c.closed && !c.connected);
267
264
  return Promise.all(pendingClients.map(async ([container, pendingClientId]) => {
268
- return new Promise((res) => {
265
+ return new Promise((resolve) => {
269
266
  const cleanup = () => {
270
267
  unconnectedClients.forEach((c) => c.off("connected", handler));
271
268
  container.getQuorum().off("removeMember", handler);
@@ -274,7 +271,7 @@ class LoaderContainerTracker {
274
271
  pendingClientId.delete(clientId);
275
272
  if (pendingClientId.size === 0) {
276
273
  cleanup();
277
- res();
274
+ resolve();
278
275
  }
279
276
  };
280
277
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -284,7 +281,7 @@ class LoaderContainerTracker {
284
281
  container.getQuorum().on("removeMember", handler);
285
282
  container.on("closed", () => {
286
283
  cleanup();
287
- res();
284
+ resolve();
288
285
  });
289
286
  });
290
287
  }));
@@ -294,12 +291,12 @@ class LoaderContainerTracker {
294
291
  * @param containersToApply - the set of containers to wait for any inbound ops for
295
292
  */
296
293
  async waitForAnyInboundOps(containersToApply) {
297
- return new Promise((res) => {
294
+ return new Promise((resolve) => {
298
295
  const handler = () => {
299
296
  containersToApply.map((c) => {
300
297
  c.deltaManager.inbound.off("push", handler);
301
298
  });
302
- res();
299
+ resolve();
303
300
  };
304
301
  containersToApply.map((c) => {
305
302
  c.deltaManager.inbound.on("push", handler);
@@ -377,7 +374,7 @@ class LoaderContainerTracker {
377
374
  }
378
375
  while (resumed.some((queue) => !queue.idle)) {
379
376
  debugWait("Wait until queue is idle");
380
- await new Promise((res) => { setTimeout(res, 0); });
377
+ await new Promise((resolve) => { setTimeout(resolve, 0); });
381
378
  }
382
379
  // Make sure all the op that we sent out are acked first
383
380
  // This is no op if we are processing incoming
@@ -1 +1 @@
1
- {"version":3,"file":"loaderContainerTracker.js","sourceRoot":"","sources":["../src/loaderContainerTracker.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 } from \"@fluidframework/common-utils\";\nimport { IContainer, IDeltaQueue, IHostLoader } from \"@fluidframework/container-definitions\";\nimport { Container } from \"@fluidframework/container-loader\";\nimport { IDocumentMessage, ISequencedDocumentMessage, MessageType } from \"@fluidframework/protocol-definitions\";\nimport { debug } from \"./debug\";\nimport { IOpProcessingController } from \"./testObjectProvider\";\n\nconst debugOp = debug.extend(\"ops\");\nconst debugWait = debug.extend(\"wait\");\n\ninterface ContainerRecord {\n // A short number for debug output\n index: number;\n\n // LoaderContainerTracker paused state\n paused: boolean;\n\n // Tracking trailing no-op that may or may be acked by the server so we can discount them\n // See issue #5629\n startTrailingNoOps: number;\n trailingNoOps: number;\n\n // Track last proposal to ensure no unresolved proposal\n lastProposal: number;\n}\n\nexport class LoaderContainerTracker implements IOpProcessingController {\n private readonly containers = new Map<IContainer, ContainerRecord>();\n private lastProposalSeqNum: number = 0;\n\n /**\n * Add a loader to start to track any container created from them\n * @param loader - loader to start tracking any container created.\n */\n public add<LoaderType extends IHostLoader>(loader: LoaderType) {\n // TODO: Expose Loader API to able to intercept container creation (See issue #5114)\n const patch = <T, C extends IContainer>(fn: (...args) => Promise<C>) => {\n const boundFn = fn.bind(loader);\n return async (...args: T[]) => {\n const container = await boundFn(...args);\n this.addContainer(container);\n return container;\n };\n };\n // eslint-disable-next-line @typescript-eslint/unbound-method\n loader.resolve = patch(loader.resolve);\n // eslint-disable-next-line @typescript-eslint/unbound-method\n loader.createDetachedContainer = patch(loader.createDetachedContainer);\n // eslint-disable-next-line @typescript-eslint/unbound-method\n loader.rehydrateDetachedContainerFromSnapshot = patch(loader.rehydrateDetachedContainerFromSnapshot);\n }\n\n /**\n * Utility function to add container to be tracked.\n *\n * @param container - container to add\n */\n private addContainer(container: IContainer) {\n // ignore summarizer\n if (!container.deltaManager.clientDetails.capabilities.interactive) { return; }\n\n // don't add container that is already tracked\n if (this.containers.has(container)) { return; }\n\n const record = {\n index: this.containers.size,\n paused: false,\n startTrailingNoOps: 0,\n trailingNoOps: 0,\n lastProposal: 0,\n };\n this.containers.set(container, record);\n this.trackTrailingNoOps(container, record);\n this.trackLastProposal(container);\n this.setupTrace(container, record.index);\n }\n\n /**\n * Keep track of the trailing NoOp that was sent so we can discount them in the clientSequenceNumber tracking.\n * The server might coalesce them with other ops, or a single NoOp, or delay it if it don't think it is necessary.\n *\n * @param container - the container to track\n * @param record - the record to update the trailing op information\n */\n private trackTrailingNoOps(container: IContainer, record: ContainerRecord) {\n container.deltaManager.outbound.on(\"op\", (messages) => {\n for (const msg of messages) {\n if (msg.type === MessageType.NoOp) {\n // Track the NoOp that was sent.\n if (record.trailingNoOps === 0) {\n // record the starting sequence number of the trailing no ops if we haven't been tracking yet.\n record.startTrailingNoOps = msg.clientSequenceNumber;\n }\n record.trailingNoOps++;\n } else {\n // Other ops has been sent. We would like to see those ack'ed, so no more need to track NoOps\n record.trailingNoOps = 0;\n }\n }\n });\n\n container.deltaManager.inbound.on(\"push\", (message) => {\n // Received the no op back, update the record if we are tracking\n if (message.type === MessageType.NoOp\n && message.clientId === (container as Container).clientId\n && record.trailingNoOps !== 0\n && record.startTrailingNoOps <= message.clientSequenceNumber\n ) {\n // NoOp might have coalesced and skipped ahead some sequence number\n // update the record and skip ahead as well\n const oldStartTrailingNoOps = record.startTrailingNoOps;\n record.startTrailingNoOps = message.clientSequenceNumber + 1;\n record.trailingNoOps -= (record.startTrailingNoOps - oldStartTrailingNoOps);\n }\n });\n\n container.on(\"disconnected\", () => {\n // reset on disconnect.\n record.trailingNoOps = 0;\n });\n }\n\n private trackLastProposal(container: IContainer) {\n container.getQuorum().on(\"addProposal\", (proposal) => {\n if (proposal.sequenceNumber > this.lastProposalSeqNum) {\n this.lastProposalSeqNum = proposal.sequenceNumber;\n }\n });\n }\n\n /**\n * Reset the tracker, closing all containers and stop tracking them.\n */\n public reset() {\n this.lastProposalSeqNum = 0;\n for (const container of this.containers.keys()) {\n container.close();\n }\n this.containers.clear();\n\n // REVIEW: do we need to unpatch the loaders?\n }\n\n /**\n * Make sure all the tracked containers are synchronized.\n * - No isDirty (non-readonly) containers\n * - No extra clientId in quorum of any container that is not tracked and still opened.\n * - i.e. no pending Join/Leave message.\n * - No unresolved proposal (minSeqNum \\>= lastProposalSeqNum)\n * - lastSequenceNumber of all container is the same\n * - clientSequenceNumberObserved is the same as clientSequenceNumber sent\n * - this overlaps with !isDirty, but include task scheduler ops.\n * - Trailing NoOp is tracked and don't count as pending ops.\n */\n public async ensureSynchronized(...containers: IContainer[]) {\n const resumed = this.resumeProcessing(...containers);\n\n let waitingSequenceNumberSynchronized = false;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const containersToApply = this.getContainers(containers);\n if (containersToApply.length === 0) { break; }\n\n // Ignore readonly dirty containers, because it can't sent up and nothing can be done about it being dirty\n const dirtyContainers =\n containersToApply.filter((c) => c.deltaManager.readOnlyInfo.readonly !== true && c.isDirty);\n if (dirtyContainers.length === 0) {\n // Wait for all the leave messages\n const pendingClients = this.getPendingClients(containersToApply);\n if (pendingClients.length === 0) {\n if (this.isSequenceNumberSynchronized(containersToApply)) {\n // done, we are in sync\n break;\n }\n if (!waitingSequenceNumberSynchronized) {\n // Only write it out once\n waitingSequenceNumberSynchronized = true;\n debugWait(\"Waiting for sequence number synchronized\");\n await this.waitForAnyInboundOps(containersToApply);\n }\n } else {\n waitingSequenceNumberSynchronized = false;\n await this.waitForPendingClients(pendingClients);\n }\n } else {\n // Wait for all the containers to be saved\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n debugWait(`Waiting container to be saved ${dirtyContainers.map((c) => this.containers.get(c)!.index)}`);\n waitingSequenceNumberSynchronized = false;\n await Promise.all(dirtyContainers.map(async (c) => new Promise((res) => c.once(\"saved\", res))));\n }\n\n // yield a turn to allow side effect of the ops we just processed execute before we check again\n await new Promise<void>((res) => { setTimeout(res, 0); });\n }\n\n // Pause all container that was resumed\n // don't call pause if resumed is empty and pause everything, which is not what we want\n if (resumed.length !== 0) {\n await this.pauseProcessing(...resumed);\n }\n\n debugWait(\"Synchronized\");\n }\n\n /**\n * Utility to calculate the set of clientId per container in quorum that is NOT associated with\n * any container we tracked, indicating there is a pending join or leave op that we need to wait.\n *\n * @param containersToApply - the set of containers to check\n */\n private getPendingClients(containersToApply: IContainer[]) {\n // All the clientId we track should be a superset of the quorum, otherwise, we are missing\n // leave messages\n const openedDocuments = Array.from(this.containers.keys()).filter((c) => !c.closed);\n const openedClientId = openedDocuments.map((container) => (container as Container).clientId);\n\n const pendingClients: [IContainer, Set<string>][] = [];\n containersToApply.forEach((container) => {\n const pendingClientId = new Set<string>();\n const quorum = container.getQuorum();\n quorum.getMembers().forEach((client, clientId) => {\n // ignore summarizer\n if (!client.client.details.capabilities.interactive) { return; }\n if (!openedClientId.includes(clientId)) {\n pendingClientId.add(clientId);\n }\n });\n\n if (pendingClientId.size !== 0) {\n pendingClients.push([container, pendingClientId]);\n }\n });\n return pendingClients;\n }\n\n /**\n * Utility to check synchronization based on sequence number\n * See ensureSynchronized for more detail\n *\n * @param containersToApply - the set of containers to check\n */\n private isSequenceNumberSynchronized(containersToApply: IContainer[]) {\n // clientSequenceNumber check detects ops in flight, both on the wire and in the outbound queue\n // We need both client sequence number and isDirty check because:\n // - Currently isDirty flag ignores ops for task scheduler, so we need the client sequence number check\n // - But isDirty flags include ops during forceReadonly and disconnected, because we don't submit\n // the ops in the first place, clientSequenceNumber is not assigned\n\n const isClientSequenceNumberSynchronized = containersToApply.every((container) => {\n if (container.deltaManager.readOnlyInfo.readonly === true) {\n // Ignore readonly container. the clientSeqNum and clientSeqNumObserved might be out of sync\n // because we transition to readonly when outbound is not empty or the in transit op got lost\n return true;\n }\n // Note that in read only mode, the op won't be submitted\n let deltaManager = (container.deltaManager as any);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const { trailingNoOps } = this.containers.get(container)!;\n // Back-compat: clientSequenceNumber & clientSequenceNumberObserved moved to ConnectionManager in 0.53\n if (!(\"clientSequenceNumber\" in deltaManager)) {\n deltaManager = deltaManager.connectionManager;\n }\n assert(\"clientSequenceNumber\" in deltaManager, \"no clientSequenceNumber\");\n assert(\"clientSequenceNumberObserved\" in deltaManager, \"no clientSequenceNumber\");\n return deltaManager.clientSequenceNumber ===\n (deltaManager.clientSequenceNumberObserved as number) + trailingNoOps;\n });\n\n if (!isClientSequenceNumberSynchronized) {\n return false;\n }\n\n const minSeqNum = containersToApply[0].deltaManager.minimumSequenceNumber;\n if (minSeqNum < this.lastProposalSeqNum) {\n // There is an unresolved proposal\n return false;\n }\n\n // Check to see if all the container has process the same number of ops.\n const seqNum = containersToApply[0].deltaManager.lastSequenceNumber;\n return containersToApply.every((c) => c.deltaManager.lastSequenceNumber === seqNum);\n }\n\n /**\n * Utility to wait for any clientId in quorum that is NOT associated with any container we\n * tracked, indicating there is a pending join or leave op that we need to wait.\n *\n * Note that this function doesn't account for container that got added after we started waiting\n *\n * @param containersToApply - the set of containers to wait for any inbound ops for\n */\n private async waitForPendingClients(pendingClients: [IContainer, Set<string>][]) {\n const unconnectedClients =\n Array.from(this.containers.keys()).filter((c) => !c.closed && !(c as Container).connected);\n return Promise.all(pendingClients.map(async ([container, pendingClientId]) => {\n return new Promise<void>((res) => {\n const cleanup = () => {\n unconnectedClients.forEach((c) => c.off(\"connected\", handler));\n container.getQuorum().off(\"removeMember\", handler);\n };\n const handler = (clientId: string) => {\n pendingClientId.delete(clientId);\n if (pendingClientId.size === 0) {\n cleanup();\n res();\n }\n };\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const index = this.containers.get(container)!.index;\n debugWait(`${index}: Waiting for pending clients ${Array.from(pendingClientId.keys())}`);\n unconnectedClients.forEach((c) => c.on(\"connected\", handler));\n container.getQuorum().on(\"removeMember\", handler);\n container.on(\"closed\", () => {\n cleanup();\n res();\n });\n });\n }));\n }\n\n /**\n * Utility to wait for any inbound ops from a set of containers\n * @param containersToApply - the set of containers to wait for any inbound ops for\n */\n private async waitForAnyInboundOps(containersToApply: IContainer[]) {\n return new Promise<void>((res) => {\n const handler = () => {\n containersToApply.map((c) => {\n c.deltaManager.inbound.off(\"push\", handler);\n });\n res();\n };\n containersToApply.map((c) => {\n c.deltaManager.inbound.on(\"push\", handler);\n });\n });\n }\n\n /**\n * Resume all queue activities on all paused tracked containers and return them\n */\n public resumeProcessing(...containers: IContainer[]) {\n const resumed: IContainer[] = [];\n const containersToApply = this.getContainers(containers);\n for (const container of containersToApply) {\n const record = this.containers.get(container);\n if (record !== undefined && record.paused) {\n debugWait(`${record.index}: container resumed`);\n container.deltaManager.inbound.resume();\n container.deltaManager.outbound.resume();\n resumed.push(container);\n record.paused = false;\n }\n }\n return resumed;\n }\n\n /**\n * Pause all queue activities on the containers given, or all tracked containers\n * Any containers given that is not tracked will be ignored.\n */\n public async pauseProcessing(...containers: IContainer[]) {\n const pauseP: Promise<void>[] = [];\n const containersToApply = this.getContainers(containers);\n for (const container of containersToApply) {\n const record = this.containers.get(container);\n if (record !== undefined && !record.paused) {\n debugWait(`${record.index}: container paused`);\n pauseP.push(container.deltaManager.inbound.pause());\n pauseP.push(container.deltaManager.outbound.pause());\n record.paused = true;\n }\n }\n await Promise.all(pauseP);\n }\n\n /**\n * Pause all queue activities on all tracked containers, and resume only\n * inbound to process ops until it is idle. All queues are left in the paused state\n * after the function\n */\n public async processIncoming(...containers: IContainer[]) {\n return this.processQueue(containers, (container) => container.deltaManager.inbound);\n }\n\n /**\n * Pause all queue activities on all tracked containers, and resume only\n * outbound to process ops until it is idle. All queues are left in the paused state\n * after the function\n */\n public async processOutgoing(...containers: IContainer[]) {\n return this.processQueue(containers, (container) => container.deltaManager.outbound);\n }\n\n /**\n * Implementation of processIncoming and processOutgoing\n */\n private async processQueue<U>(containers: IContainer[], getQueue: (container: IContainer) => IDeltaQueue<U>) {\n await this.pauseProcessing(...containers);\n const resumed: IDeltaQueue<U>[] = [];\n\n const containersToApply = this.getContainers(containers);\n const inflightTracker = new Map<IContainer, number>();\n const cleanup: (() => void)[] = [];\n for (const container of containersToApply) {\n const queue = getQueue(container);\n\n // track the outgoing ops (if any) to make sure they make the round trip to at least to the same client\n // to make sure they are sequenced.\n cleanup.push(this.setupInOutTracker(container, inflightTracker));\n queue.resume();\n resumed.push(queue);\n }\n\n while (resumed.some((queue) => !queue.idle)) {\n debugWait(\"Wait until queue is idle\");\n await new Promise<void>((res) => { setTimeout(res, 0); });\n }\n\n // Make sure all the op that we sent out are acked first\n // This is no op if we are processing incoming\n if (inflightTracker.size) {\n debugWait(\"Wait for inflight ops\");\n do {\n await this.waitForAnyInboundOps(containersToApply);\n } while (inflightTracker.size);\n }\n\n // remove the handlers\n cleanup.forEach((clean) => clean());\n\n await Promise.all(resumed.map(async (queue) => queue.pause()));\n }\n\n /**\n * Utility to set up listener to track the outbound ops until it round trip back\n * Returns a function to remove the handler after it is done.\n *\n * @param container - the container to setup\n * @param inflightTracker - a map to track the clientSequenceNumber per container it expect to get ops back\n */\n private setupInOutTracker(container: IContainer, inflightTracker: Map<IContainer, number>) {\n const outHandler = (messages: IDocumentMessage[]) => {\n for (const message of messages) {\n if (message.type !== MessageType.NoOp) {\n inflightTracker.set(container, message.clientSequenceNumber);\n }\n }\n };\n const inHandler = (message: ISequencedDocumentMessage) => {\n if (message.type !== MessageType.NoOp\n && message.clientId === (container as Container).clientId\n && inflightTracker.get(container) === message.clientSequenceNumber) {\n inflightTracker.delete(container);\n }\n };\n\n container.deltaManager.outbound.on(\"op\", outHandler);\n container.deltaManager.inbound.on(\"push\", inHandler);\n\n return () => {\n container.deltaManager.outbound.off(\"op\", outHandler);\n container.deltaManager.inbound.off(\"push\", inHandler);\n };\n }\n\n /**\n * Setup debug traces for connection and ops\n */\n private setupTrace(container: IContainer, index: number) {\n if (debugOp.enabled) {\n const getContentsString = (type: string, msgContents: any) => {\n try {\n if (type !== MessageType.Operation) {\n if (typeof msgContents === \"string\") { return msgContents; }\n return JSON.stringify(msgContents);\n }\n let address = \"\";\n\n // contents comes in the wire as JSON string (\"push\" event)\n // But already parsed when apply (\"op\" event)\n let contents = typeof msgContents === \"string\" ?\n JSON.parse(msgContents) : msgContents;\n // eslint-disable-next-line no-null/no-null\n while (contents !== undefined && contents !== null) {\n if (contents.contents?.address !== undefined) {\n address += `/${contents.contents.address}`;\n contents = contents.contents.contents;\n } else if (contents.content?.address !== undefined) {\n address += `/${contents.content.address}`;\n contents = contents.content.contents;\n } else {\n break;\n }\n }\n if (address) {\n return `${address} ${JSON.stringify(contents)}`;\n }\n return JSON.stringify(contents);\n } catch (e) {\n return `${e.message}: ${e.stack}`;\n }\n };\n debugOp(`${index}: ADD: clientId: ${(container as Container).clientId}`);\n container.deltaManager.outbound.on(\"op\", (messages) => {\n for (const msg of messages) {\n debugOp(`${index}: OUT: `\n + `cli: ${msg.clientSequenceNumber.toString().padStart(3)} `\n + `rsq: ${msg.referenceSequenceNumber.toString().padStart(3)} `\n + `${msg.type} ${getContentsString(msg.type, msg.contents)}`);\n }\n });\n const getInboundHandler = (type: string) => {\n return (msg: ISequencedDocumentMessage) => {\n const clientSeq = msg.clientId === (container as Container).clientId ?\n `cli: ${msg.clientSequenceNumber.toString().padStart(3)}` : \" \";\n debugOp(`${index}: ${type}: seq: ${msg.sequenceNumber.toString().padStart(3)} `\n + `${clientSeq} min: ${msg.minimumSequenceNumber.toString().padStart(3)} `\n + `${msg.type} ${getContentsString(msg.type, msg.contents)}`);\n };\n };\n container.deltaManager.inbound.on(\"push\", getInboundHandler(\"IN \"));\n container.deltaManager.inbound.on(\"op\", getInboundHandler(\"OP \"));\n container.deltaManager.on(\"connect\", (details) => {\n debugOp(`${index}: CON: clientId: ${details.clientId}`);\n });\n container.deltaManager.on(\"disconnect\", (reason) => {\n debugOp(`${index}: DIS: ${reason}`);\n });\n }\n }\n\n /**\n * Filter out the opened containers based on param.\n * @param containers - The container to filter to. If the array is empty, it means don't filter and return\n * all open containers.\n */\n private getContainers(containers: IContainer[]) {\n const containersToApply = containers.length === 0 ? Array.from(this.containers.keys()) : containers;\n return containersToApply.filter((container) => !container.closed);\n }\n}\n"]}
1
+ {"version":3,"file":"loaderContainerTracker.js","sourceRoot":"","sources":["../src/loaderContainerTracker.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 } from \"@fluidframework/common-utils\";\nimport { IContainer, IDeltaQueue, IHostLoader } from \"@fluidframework/container-definitions\";\nimport { Container } from \"@fluidframework/container-loader\";\nimport { IDocumentMessage, ISequencedDocumentMessage, MessageType } from \"@fluidframework/protocol-definitions\";\nimport { debug } from \"./debug\";\nimport { IOpProcessingController } from \"./testObjectProvider\";\n\nconst debugOp = debug.extend(\"ops\");\nconst debugWait = debug.extend(\"wait\");\n\ninterface ContainerRecord {\n // A short number for debug output\n index: number;\n\n // LoaderContainerTracker paused state\n paused: boolean;\n\n // Tracking trailing no-op that may or may be acked by the server so we can discount them\n // See issue #5629\n startTrailingNoOps: number;\n trailingNoOps: number;\n\n // Track last proposal to ensure no unresolved proposal\n lastProposal: number;\n}\n\nexport class LoaderContainerTracker implements IOpProcessingController {\n private readonly containers = new Map<IContainer, ContainerRecord>();\n private lastProposalSeqNum: number = 0;\n\n /**\n * Add a loader to start to track any container created from them\n * @param loader - loader to start tracking any container created.\n */\n public add<LoaderType extends IHostLoader>(loader: LoaderType) {\n // TODO: Expose Loader API to able to intercept container creation (See issue #5114)\n const patch = <T, C extends IContainer>(fn: (...args) => Promise<C>) => {\n const boundFn = fn.bind(loader);\n return async (...args: T[]) => {\n const container = await boundFn(...args);\n this.addContainer(container);\n return container;\n };\n };\n loader.resolve = patch(loader.resolve);\n loader.createDetachedContainer = patch(loader.createDetachedContainer);\n loader.rehydrateDetachedContainerFromSnapshot = patch(loader.rehydrateDetachedContainerFromSnapshot);\n }\n\n /**\n * Utility function to add container to be tracked.\n *\n * @param container - container to add\n */\n private addContainer(container: IContainer) {\n // ignore summarizer\n if (!container.deltaManager.clientDetails.capabilities.interactive) { return; }\n\n // don't add container that is already tracked\n if (this.containers.has(container)) { return; }\n\n const record = {\n index: this.containers.size,\n paused: false,\n startTrailingNoOps: 0,\n trailingNoOps: 0,\n lastProposal: 0,\n };\n this.containers.set(container, record);\n this.trackTrailingNoOps(container, record);\n this.trackLastProposal(container);\n this.setupTrace(container, record.index);\n }\n\n /**\n * Keep track of the trailing NoOp that was sent so we can discount them in the clientSequenceNumber tracking.\n * The server might coalesce them with other ops, or a single NoOp, or delay it if it don't think it is necessary.\n *\n * @param container - the container to track\n * @param record - the record to update the trailing op information\n */\n private trackTrailingNoOps(container: IContainer, record: ContainerRecord) {\n container.deltaManager.outbound.on(\"op\", (messages) => {\n for (const msg of messages) {\n if (msg.type === MessageType.NoOp) {\n // Track the NoOp that was sent.\n if (record.trailingNoOps === 0) {\n // record the starting sequence number of the trailing no ops if we haven't been tracking yet.\n record.startTrailingNoOps = msg.clientSequenceNumber;\n }\n record.trailingNoOps++;\n } else {\n // Other ops has been sent. We would like to see those ack'ed, so no more need to track NoOps\n record.trailingNoOps = 0;\n }\n }\n });\n\n container.deltaManager.inbound.on(\"push\", (message) => {\n // Received the no op back, update the record if we are tracking\n if (message.type === MessageType.NoOp\n && message.clientId === (container as Container).clientId\n && record.trailingNoOps !== 0\n && record.startTrailingNoOps <= message.clientSequenceNumber\n ) {\n // NoOp might have coalesced and skipped ahead some sequence number\n // update the record and skip ahead as well\n const oldStartTrailingNoOps = record.startTrailingNoOps;\n record.startTrailingNoOps = message.clientSequenceNumber + 1;\n record.trailingNoOps -= (record.startTrailingNoOps - oldStartTrailingNoOps);\n }\n });\n\n container.on(\"disconnected\", () => {\n // reset on disconnect.\n record.trailingNoOps = 0;\n });\n }\n\n private trackLastProposal(container: IContainer) {\n container.getQuorum().on(\"addProposal\", (proposal) => {\n if (proposal.sequenceNumber > this.lastProposalSeqNum) {\n this.lastProposalSeqNum = proposal.sequenceNumber;\n }\n });\n }\n\n /**\n * Reset the tracker, closing all containers and stop tracking them.\n */\n public reset() {\n this.lastProposalSeqNum = 0;\n for (const container of this.containers.keys()) {\n container.close();\n }\n this.containers.clear();\n\n // REVIEW: do we need to unpatch the loaders?\n }\n\n /**\n * Make sure all the tracked containers are synchronized.\n * - No isDirty (non-readonly) containers\n * - No extra clientId in quorum of any container that is not tracked and still opened.\n * - i.e. no pending Join/Leave message.\n * - No unresolved proposal (minSeqNum \\>= lastProposalSeqNum)\n * - lastSequenceNumber of all container is the same\n * - clientSequenceNumberObserved is the same as clientSequenceNumber sent\n * - this overlaps with !isDirty, but include task scheduler ops.\n * - Trailing NoOp is tracked and don't count as pending ops.\n */\n public async ensureSynchronized(...containers: IContainer[]) {\n const resumed = this.resumeProcessing(...containers);\n\n let waitingSequenceNumberSynchronized = false;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const containersToApply = this.getContainers(containers);\n if (containersToApply.length === 0) { break; }\n\n // Ignore readonly dirty containers, because it can't sent up and nothing can be done about it being dirty\n const dirtyContainers =\n containersToApply.filter((c) => c.deltaManager.readOnlyInfo.readonly !== true && c.isDirty);\n if (dirtyContainers.length === 0) {\n // Wait for all the leave messages\n const pendingClients = this.getPendingClients(containersToApply);\n if (pendingClients.length === 0) {\n if (this.isSequenceNumberSynchronized(containersToApply)) {\n // done, we are in sync\n break;\n }\n if (!waitingSequenceNumberSynchronized) {\n // Only write it out once\n waitingSequenceNumberSynchronized = true;\n debugWait(\"Waiting for sequence number synchronized\");\n await this.waitForAnyInboundOps(containersToApply);\n }\n } else {\n waitingSequenceNumberSynchronized = false;\n await this.waitForPendingClients(pendingClients);\n }\n } else {\n // Wait for all the containers to be saved\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n debugWait(`Waiting container to be saved ${dirtyContainers.map((c) => this.containers.get(c)!.index)}`);\n waitingSequenceNumberSynchronized = false;\n await Promise.all(dirtyContainers.map(async (c) => new Promise((resolve) => c.once(\"saved\", resolve))));\n }\n\n // yield a turn to allow side effect of the ops we just processed execute before we check again\n await new Promise<void>((resolve) => { setTimeout(resolve, 0); });\n }\n\n // Pause all container that was resumed\n // don't call pause if resumed is empty and pause everything, which is not what we want\n if (resumed.length !== 0) {\n await this.pauseProcessing(...resumed);\n }\n\n debugWait(\"Synchronized\");\n }\n\n /**\n * Utility to calculate the set of clientId per container in quorum that is NOT associated with\n * any container we tracked, indicating there is a pending join or leave op that we need to wait.\n *\n * @param containersToApply - the set of containers to check\n */\n private getPendingClients(containersToApply: IContainer[]) {\n // All the clientId we track should be a superset of the quorum, otherwise, we are missing\n // leave messages\n const openedDocuments = Array.from(this.containers.keys()).filter((c) => !c.closed);\n const openedClientId = openedDocuments.map((container) => (container as Container).clientId);\n\n const pendingClients: [IContainer, Set<string>][] = [];\n containersToApply.forEach((container) => {\n const pendingClientId = new Set<string>();\n const quorum = container.getQuorum();\n quorum.getMembers().forEach((client, clientId) => {\n // ignore summarizer\n if (!client.client.details.capabilities.interactive) { return; }\n if (!openedClientId.includes(clientId)) {\n pendingClientId.add(clientId);\n }\n });\n\n if (pendingClientId.size !== 0) {\n pendingClients.push([container, pendingClientId]);\n }\n });\n return pendingClients;\n }\n\n /**\n * Utility to check synchronization based on sequence number\n * See ensureSynchronized for more detail\n *\n * @param containersToApply - the set of containers to check\n */\n private isSequenceNumberSynchronized(containersToApply: IContainer[]) {\n // clientSequenceNumber check detects ops in flight, both on the wire and in the outbound queue\n // We need both client sequence number and isDirty check because:\n // - Currently isDirty flag ignores ops for task scheduler, so we need the client sequence number check\n // - But isDirty flags include ops during forceReadonly and disconnected, because we don't submit\n // the ops in the first place, clientSequenceNumber is not assigned\n\n const isClientSequenceNumberSynchronized = containersToApply.every((container) => {\n if (container.deltaManager.readOnlyInfo.readonly === true) {\n // Ignore readonly container. the clientSeqNum and clientSeqNumObserved might be out of sync\n // because we transition to readonly when outbound is not empty or the in transit op got lost\n return true;\n }\n // Note that in read only mode, the op won't be submitted\n let deltaManager = (container.deltaManager as any);\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const { trailingNoOps } = this.containers.get(container)!;\n // Back-compat: clientSequenceNumber & clientSequenceNumberObserved moved to ConnectionManager in 0.53\n if (!(\"clientSequenceNumber\" in deltaManager)) {\n deltaManager = deltaManager.connectionManager;\n }\n assert(\"clientSequenceNumber\" in deltaManager, \"no clientSequenceNumber\");\n assert(\"clientSequenceNumberObserved\" in deltaManager, \"no clientSequenceNumber\");\n return deltaManager.clientSequenceNumber ===\n (deltaManager.clientSequenceNumberObserved as number) + trailingNoOps;\n });\n\n if (!isClientSequenceNumberSynchronized) {\n return false;\n }\n\n const minSeqNum = containersToApply[0].deltaManager.minimumSequenceNumber;\n if (minSeqNum < this.lastProposalSeqNum) {\n // There is an unresolved proposal\n return false;\n }\n\n // Check to see if all the container has process the same number of ops.\n const seqNum = containersToApply[0].deltaManager.lastSequenceNumber;\n return containersToApply.every((c) => c.deltaManager.lastSequenceNumber === seqNum);\n }\n\n /**\n * Utility to wait for any clientId in quorum that is NOT associated with any container we\n * tracked, indicating there is a pending join or leave op that we need to wait.\n *\n * Note that this function doesn't account for container that got added after we started waiting\n *\n * @param containersToApply - the set of containers to wait for any inbound ops for\n */\n private async waitForPendingClients(pendingClients: [IContainer, Set<string>][]) {\n const unconnectedClients =\n Array.from(this.containers.keys()).filter((c) => !c.closed && !(c as Container).connected);\n return Promise.all(pendingClients.map(async ([container, pendingClientId]) => {\n return new Promise<void>((resolve) => {\n const cleanup = () => {\n unconnectedClients.forEach((c) => c.off(\"connected\", handler));\n container.getQuorum().off(\"removeMember\", handler);\n };\n const handler = (clientId: string) => {\n pendingClientId.delete(clientId);\n if (pendingClientId.size === 0) {\n cleanup();\n resolve();\n }\n };\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const index = this.containers.get(container)!.index;\n debugWait(`${index}: Waiting for pending clients ${Array.from(pendingClientId.keys())}`);\n unconnectedClients.forEach((c) => c.on(\"connected\", handler));\n container.getQuorum().on(\"removeMember\", handler);\n container.on(\"closed\", () => {\n cleanup();\n resolve();\n });\n });\n }));\n }\n\n /**\n * Utility to wait for any inbound ops from a set of containers\n * @param containersToApply - the set of containers to wait for any inbound ops for\n */\n private async waitForAnyInboundOps(containersToApply: IContainer[]) {\n return new Promise<void>((resolve) => {\n const handler = () => {\n containersToApply.map((c) => {\n c.deltaManager.inbound.off(\"push\", handler);\n });\n resolve();\n };\n containersToApply.map((c) => {\n c.deltaManager.inbound.on(\"push\", handler);\n });\n });\n }\n\n /**\n * Resume all queue activities on all paused tracked containers and return them\n */\n public resumeProcessing(...containers: IContainer[]) {\n const resumed: IContainer[] = [];\n const containersToApply = this.getContainers(containers);\n for (const container of containersToApply) {\n const record = this.containers.get(container);\n if (record !== undefined && record.paused) {\n debugWait(`${record.index}: container resumed`);\n container.deltaManager.inbound.resume();\n container.deltaManager.outbound.resume();\n resumed.push(container);\n record.paused = false;\n }\n }\n return resumed;\n }\n\n /**\n * Pause all queue activities on the containers given, or all tracked containers\n * Any containers given that is not tracked will be ignored.\n */\n public async pauseProcessing(...containers: IContainer[]) {\n const pauseP: Promise<void>[] = [];\n const containersToApply = this.getContainers(containers);\n for (const container of containersToApply) {\n const record = this.containers.get(container);\n if (record !== undefined && !record.paused) {\n debugWait(`${record.index}: container paused`);\n pauseP.push(container.deltaManager.inbound.pause());\n pauseP.push(container.deltaManager.outbound.pause());\n record.paused = true;\n }\n }\n await Promise.all(pauseP);\n }\n\n /**\n * Pause all queue activities on all tracked containers, and resume only\n * inbound to process ops until it is idle. All queues are left in the paused state\n * after the function\n */\n public async processIncoming(...containers: IContainer[]) {\n return this.processQueue(containers, (container) => container.deltaManager.inbound);\n }\n\n /**\n * Pause all queue activities on all tracked containers, and resume only\n * outbound to process ops until it is idle. All queues are left in the paused state\n * after the function\n */\n public async processOutgoing(...containers: IContainer[]) {\n return this.processQueue(containers, (container) => container.deltaManager.outbound);\n }\n\n /**\n * Implementation of processIncoming and processOutgoing\n */\n private async processQueue<U>(containers: IContainer[], getQueue: (container: IContainer) => IDeltaQueue<U>) {\n await this.pauseProcessing(...containers);\n const resumed: IDeltaQueue<U>[] = [];\n\n const containersToApply = this.getContainers(containers);\n const inflightTracker = new Map<IContainer, number>();\n const cleanup: (() => void)[] = [];\n for (const container of containersToApply) {\n const queue = getQueue(container);\n\n // track the outgoing ops (if any) to make sure they make the round trip to at least to the same client\n // to make sure they are sequenced.\n cleanup.push(this.setupInOutTracker(container, inflightTracker));\n queue.resume();\n resumed.push(queue);\n }\n\n while (resumed.some((queue) => !queue.idle)) {\n debugWait(\"Wait until queue is idle\");\n await new Promise<void>((resolve) => { setTimeout(resolve, 0); });\n }\n\n // Make sure all the op that we sent out are acked first\n // This is no op if we are processing incoming\n if (inflightTracker.size) {\n debugWait(\"Wait for inflight ops\");\n do {\n await this.waitForAnyInboundOps(containersToApply);\n } while (inflightTracker.size);\n }\n\n // remove the handlers\n cleanup.forEach((clean) => clean());\n\n await Promise.all(resumed.map(async (queue) => queue.pause()));\n }\n\n /**\n * Utility to set up listener to track the outbound ops until it round trip back\n * Returns a function to remove the handler after it is done.\n *\n * @param container - the container to setup\n * @param inflightTracker - a map to track the clientSequenceNumber per container it expect to get ops back\n */\n private setupInOutTracker(container: IContainer, inflightTracker: Map<IContainer, number>) {\n const outHandler = (messages: IDocumentMessage[]) => {\n for (const message of messages) {\n if (message.type !== MessageType.NoOp) {\n inflightTracker.set(container, message.clientSequenceNumber);\n }\n }\n };\n const inHandler = (message: ISequencedDocumentMessage) => {\n if (message.type !== MessageType.NoOp\n && message.clientId === (container as Container).clientId\n && inflightTracker.get(container) === message.clientSequenceNumber) {\n inflightTracker.delete(container);\n }\n };\n\n container.deltaManager.outbound.on(\"op\", outHandler);\n container.deltaManager.inbound.on(\"push\", inHandler);\n\n return () => {\n container.deltaManager.outbound.off(\"op\", outHandler);\n container.deltaManager.inbound.off(\"push\", inHandler);\n };\n }\n\n /**\n * Setup debug traces for connection and ops\n */\n private setupTrace(container: IContainer, index: number) {\n if (debugOp.enabled) {\n const getContentsString = (type: string, msgContents: any) => {\n try {\n if (type !== MessageType.Operation) {\n if (typeof msgContents === \"string\") { return msgContents; }\n return JSON.stringify(msgContents);\n }\n let address = \"\";\n\n // contents comes in the wire as JSON string (\"push\" event)\n // But already parsed when apply (\"op\" event)\n let contents = typeof msgContents === \"string\" ?\n JSON.parse(msgContents) : msgContents;\n // eslint-disable-next-line no-null/no-null\n while (contents !== undefined && contents !== null) {\n if (contents.contents?.address !== undefined) {\n address += `/${contents.contents.address}`;\n contents = contents.contents.contents;\n } else if (contents.content?.address !== undefined) {\n address += `/${contents.content.address}`;\n contents = contents.content.contents;\n } else {\n break;\n }\n }\n if (address) {\n return `${address} ${JSON.stringify(contents)}`;\n }\n return JSON.stringify(contents);\n } catch (e) {\n return `${e.message}: ${e.stack}`;\n }\n };\n debugOp(`${index}: ADD: clientId: ${(container as Container).clientId}`);\n container.deltaManager.outbound.on(\"op\", (messages) => {\n for (const msg of messages) {\n debugOp(`${index}: OUT: `\n + `cli: ${msg.clientSequenceNumber.toString().padStart(3)} `\n + `rsq: ${msg.referenceSequenceNumber.toString().padStart(3)} `\n + `${msg.type} ${getContentsString(msg.type, msg.contents)}`);\n }\n });\n const getInboundHandler = (type: string) => {\n return (msg: ISequencedDocumentMessage) => {\n const clientSeq = msg.clientId === (container as Container).clientId ?\n `cli: ${msg.clientSequenceNumber.toString().padStart(3)}` : \" \";\n debugOp(`${index}: ${type}: seq: ${msg.sequenceNumber.toString().padStart(3)} `\n + `${clientSeq} min: ${msg.minimumSequenceNumber.toString().padStart(3)} `\n + `${msg.type} ${getContentsString(msg.type, msg.contents)}`);\n };\n };\n container.deltaManager.inbound.on(\"push\", getInboundHandler(\"IN \"));\n container.deltaManager.inbound.on(\"op\", getInboundHandler(\"OP \"));\n container.deltaManager.on(\"connect\", (details) => {\n debugOp(`${index}: CON: clientId: ${details.clientId}`);\n });\n container.deltaManager.on(\"disconnect\", (reason) => {\n debugOp(`${index}: DIS: ${reason}`);\n });\n }\n }\n\n /**\n * Filter out the opened containers based on param.\n * @param containers - The container to filter to. If the array is empty, it means don't filter and return\n * all open containers.\n */\n private getContainers(containers: IContainer[]) {\n const containersToApply = containers.length === 0 ? Array.from(this.containers.keys()) : containers;\n return containersToApply.filter((container) => !container.closed);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"localCodeLoader.d.ts","sourceRoot":"","sources":["../src/localCodeLoader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EACH,WAAW,EACX,sBAAsB,EACtB,YAAY,EACf,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,gCAAgC,EAAE,MAAM,iCAAiC,CAAC;AACtG,OAAO,EAAE,6BAA6B,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AAEpH,OAAO,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAE7E,oBAAY,yBAAyB,GAAG,OAAO,CAC3C,sBAAsB,GACtB,6BAA6B,GAC7B,8BAA8B,GAC9B,gCAAgC,CAAC,CAAC;AAGtC,oBAAY,eAAe,GAAG,yBAAyB,GAAG,YAAY,CAAC;AAEvE;;;GAGG;AACH,qBAAa,eAAgB,YAAW,WAAW;IAC/C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmC;gBAGjE,cAAc,EAAE,QAAQ,CAAC,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC,EAC9D,cAAc,CAAC,EAAE,wBAAwB;IA2C7C;;;;OAIG;IACU,IAAI,CACb,MAAM,EAAE,iBAAiB,GAC1B,OAAO,CAAC,YAAY,CAAC;CAkB3B"}
1
+ {"version":3,"file":"localCodeLoader.d.ts","sourceRoot":"","sources":["../src/localCodeLoader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EACH,WAAW,EACX,sBAAsB,EACtB,YAAY,EACf,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,gCAAgC,EAAY,MAAM,iCAAiC,CAAC;AAChH,OAAO,EAAyB,6BAA6B,EACzD,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AAEhF,OAAO,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAE7E,oBAAY,yBAAyB,GAAG,OAAO,CAC3C,sBAAsB,GACtB,6BAA6B,GAC7B,8BAA8B,GAC9B,gCAAgC,CAAC,CAAC;AAGtC,oBAAY,eAAe,GAAG,yBAAyB,GAAG,YAAY,CAAC;AAEvE;;;GAGG;AACH,qBAAa,eAAgB,YAAW,WAAW;IAC/C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmC;gBAGjE,cAAc,EAAE,QAAQ,CAAC,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC,EAC9D,cAAc,CAAC,EAAE,wBAAwB;IA6C7C;;;;OAIG;IACU,IAAI,CACb,MAAM,EAAE,iBAAiB,GAC1B,OAAO,CAAC,YAAY,CAAC;CAkB3B"}
@@ -39,8 +39,9 @@ class LocalCodeLoader {
39
39
  else {
40
40
  assert_1.default(maybeExport.IFluidDataStoreFactory !== undefined);
41
41
  const defaultFactory = runtime_utils_1.createDataStoreFactory("default", maybeExport.IFluidDataStoreFactory);
42
+ const innerRequestHandler = async (request, runtime) => runtime.IFluidHandleContext.resolveHandle(request);
42
43
  fluidModule = {
43
- fluidExport: Object.assign(Object.assign({}, maybeExport), { IRuntimeFactory: new aqueduct_1.ContainerRuntimeFactoryWithDefaultDataStore(defaultFactory, [[defaultFactory.type, Promise.resolve(defaultFactory)]], undefined, undefined, runtimeOptions) }),
44
+ fluidExport: Object.assign(Object.assign({}, maybeExport), { IRuntimeFactory: new aqueduct_1.ContainerRuntimeFactoryWithDefaultDataStore(defaultFactory, [[defaultFactory.type, Promise.resolve(defaultFactory)]], undefined, [innerRequestHandler], runtimeOptions) }),
44
45
  };
45
46
  }
46
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"localCodeLoader.js","sourceRoot":"","sources":["../src/localCodeLoader.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAEH,oDAA4B;AAC5B,uDAAuF;AAQvF,iEAAuE;AAYvE;;;GAGG;AACH,MAAa,eAAe;IAGxB,YACI,cAA8D,EAC9D,cAAyC;QAJ5B,sBAAiB,GAAG,IAAI,GAAG,EAAwB,CAAC;QAMjE,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE;YAChC,sEAAsE;YACtE,8EAA8E;YAC9E,qGAAqG;YACrG,IAAI,KAAa,CAAC;YAElB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE;gBACpC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC;aAC1B;iBAAM;gBACH,KAAK,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;aAC9D;YACD,IAAI,WAAW,GAAG,KAAK,CAAC,CAAC,CAAiB,CAAC;YAC3C,IAAI,CAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,WAAW,MAAK,SAAS,EAAE;gBACxC,MAAM,WAAW,GAAG,WAAwC,CAAC;gBAE7D,IAAI,WAAW,CAAC,eAAe,KAAK,SAAS,EAAE;oBAC3C,WAAW,GAAG,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;iBAC9C;qBAAM;oBACH,gBAAM,CAAC,WAAW,CAAC,sBAAsB,KAAK,SAAS,CAAC,CAAC;oBACzD,MAAM,cAAc,GAAG,sCAAsB,CAAC,SAAS,EAAE,WAAW,CAAC,sBAAsB,CAAC,CAAC;oBAC7F,WAAW,GAAG;wBACV,WAAW,kCACH,WAAW,KACf,eAAe,EACX,IAAI,sDAA2C,CAC3C,cAAc,EACd,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,EACxD,SAAS,EACT,SAAS,EACT,cAAc,CACjB,GACR;qBACJ,CAAC;iBACL;aACJ;YAED,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;SAClD;IACL,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,IAAI,CACb,MAAyB;QAEzB,iFAAiF;QACjF,8EAA8E;QAC9E,qGAAqG;QACrG,IAAI,KAAa,CAAC;QAElB,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE;YACpC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC;SAC1B;aAAM;YACH,KAAK,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;SAC9D;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrD,IAAI,UAAU,KAAK,SAAS,EAAE;YAC1B,MAAM,IAAI,KAAK,CAAC,uBAAuB,KAAK,EAAE,CAAC,CAAC;SACnD;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;CACJ;AAzED,0CAyEC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport assert from \"assert\";\nimport { ContainerRuntimeFactoryWithDefaultDataStore } from \"@fluidframework/aqueduct\";\nimport {\n ICodeLoader,\n IProvideRuntimeFactory,\n IFluidModule,\n} from \"@fluidframework/container-definitions\";\nimport { IFluidCodeDetails, IProvideFluidCodeDetailsComparer } from \"@fluidframework/core-interfaces\";\nimport { IProvideFluidDataStoreFactory, IProvideFluidDataStoreRegistry } from \"@fluidframework/runtime-definitions\";\nimport { createDataStoreFactory } from \"@fluidframework/runtime-utils\";\nimport { IContainerRuntimeOptions } from \"@fluidframework/container-runtime\";\n\nexport type SupportedExportInterfaces = Partial<\n IProvideRuntimeFactory &\n IProvideFluidDataStoreFactory &\n IProvideFluidDataStoreRegistry &\n IProvideFluidCodeDetailsComparer>;\n\n// Represents the entry point for a Fluid container.\nexport type fluidEntryPoint = SupportedExportInterfaces | IFluidModule;\n\n/**\n * A simple code loader that caches a mapping of package name to a Fluid entry point.\n * On load, it retrieves the entry point matching the package name in the given code details.\n */\nexport class LocalCodeLoader implements ICodeLoader {\n private readonly fluidPackageCache = new Map<string, IFluidModule>();\n\n constructor(\n packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,\n runtimeOptions?: IContainerRuntimeOptions,\n ) {\n for (const entry of packageEntries) {\n // Store the entry point against a unique id in the fluidPackageCache.\n // For code details containing a package name, use the package name as the id.\n // For code details containing a Fluid package, create a unique id from the package name and version.\n let pkgId: string;\n\n const source = entry[0];\n if (typeof source.package === \"string\") {\n pkgId = source.package;\n } else {\n pkgId = `${source.package.name}@${source.package.version}`;\n }\n let fluidModule = entry[1] as IFluidModule;\n if (fluidModule?.fluidExport === undefined) {\n const maybeExport = fluidModule as SupportedExportInterfaces;\n\n if (maybeExport.IRuntimeFactory !== undefined) {\n fluidModule = { fluidExport: maybeExport };\n } else {\n assert(maybeExport.IFluidDataStoreFactory !== undefined);\n const defaultFactory = createDataStoreFactory(\"default\", maybeExport.IFluidDataStoreFactory);\n fluidModule = {\n fluidExport: {\n ... maybeExport,\n IRuntimeFactory:\n new ContainerRuntimeFactoryWithDefaultDataStore(\n defaultFactory,\n [[defaultFactory.type, Promise.resolve(defaultFactory)]],\n undefined,\n undefined,\n runtimeOptions,\n ),\n },\n };\n }\n }\n\n this.fluidPackageCache.set(pkgId, fluidModule);\n }\n }\n\n /**\n * It finds the entry point for the package name in the given source and return it\n * as a Fluid module.\n * @param source - Details of where to find chaincode\n */\n public async load(\n source: IFluidCodeDetails,\n ): Promise<IFluidModule> {\n // Get the entry point for from the fluidPackageCache for the given code details.\n // For code details containing a package name, use the package name as the id.\n // For code details containing a Fluid package, create a unique id from the package name and version.\n let pkdId: string;\n\n if (typeof source.package === \"string\") {\n pkdId = source.package;\n } else {\n pkdId = `${source.package.name}@${source.package.version}`;\n }\n\n const entryPoint = this.fluidPackageCache.get(pkdId);\n if (entryPoint === undefined) {\n throw new Error(`Cannot find package ${pkdId}`);\n }\n return entryPoint;\n }\n}\n"]}
1
+ {"version":3,"file":"localCodeLoader.js","sourceRoot":"","sources":["../src/localCodeLoader.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAEH,oDAA4B;AAC5B,uDAAuF;AASvF,iEAAuE;AAYvE;;;GAGG;AACH,MAAa,eAAe;IAGxB,YACI,cAA8D,EAC9D,cAAyC;QAJ5B,sBAAiB,GAAG,IAAI,GAAG,EAAwB,CAAC;QAMjE,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE;YAChC,sEAAsE;YACtE,8EAA8E;YAC9E,qGAAqG;YACrG,IAAI,KAAa,CAAC;YAElB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE;gBACpC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC;aAC1B;iBAAM;gBACH,KAAK,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;aAC9D;YACD,IAAI,WAAW,GAAG,KAAK,CAAC,CAAC,CAAiB,CAAC;YAC3C,IAAI,CAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,WAAW,MAAK,SAAS,EAAE;gBACxC,MAAM,WAAW,GAAG,WAAwC,CAAC;gBAE7D,IAAI,WAAW,CAAC,eAAe,KAAK,SAAS,EAAE;oBAC3C,WAAW,GAAG,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;iBAC9C;qBAAM;oBACH,gBAAM,CAAC,WAAW,CAAC,sBAAsB,KAAK,SAAS,CAAC,CAAC;oBACzD,MAAM,cAAc,GAAG,sCAAsB,CAAC,SAAS,EAAE,WAAW,CAAC,sBAAsB,CAAC,CAAC;oBAC7F,MAAM,mBAAmB,GAAG,KAAK,EAAE,OAAiB,EAAE,OAA8B,EAAE,EAAE,CACpF,OAAO,CAAC,mBAAmB,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;oBACvD,WAAW,GAAG;wBACV,WAAW,kCACH,WAAW,KACf,eAAe,EACX,IAAI,sDAA2C,CAC3C,cAAc,EACd,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,EACxD,SAAS,EACT,CAAC,mBAAmB,CAAC,EACrB,cAAc,CACjB,GACR;qBACJ,CAAC;iBACL;aACJ;YAED,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;SAClD;IACL,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,IAAI,CACb,MAAyB;QAEzB,iFAAiF;QACjF,8EAA8E;QAC9E,qGAAqG;QACrG,IAAI,KAAa,CAAC;QAElB,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE;YACpC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC;SAC1B;aAAM;YACH,KAAK,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;SAC9D;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrD,IAAI,UAAU,KAAK,SAAS,EAAE;YAC1B,MAAM,IAAI,KAAK,CAAC,uBAAuB,KAAK,EAAE,CAAC,CAAC;SACnD;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;CACJ;AA3ED,0CA2EC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport assert from \"assert\";\nimport { ContainerRuntimeFactoryWithDefaultDataStore } from \"@fluidframework/aqueduct\";\nimport {\n ICodeLoader,\n IProvideRuntimeFactory,\n IFluidModule,\n} from \"@fluidframework/container-definitions\";\nimport { IFluidCodeDetails, IProvideFluidCodeDetailsComparer, IRequest } from \"@fluidframework/core-interfaces\";\nimport { IContainerRuntimeBase, IProvideFluidDataStoreFactory,\n IProvideFluidDataStoreRegistry } from \"@fluidframework/runtime-definitions\";\nimport { createDataStoreFactory } from \"@fluidframework/runtime-utils\";\nimport { IContainerRuntimeOptions } from \"@fluidframework/container-runtime\";\n\nexport type SupportedExportInterfaces = Partial<\n IProvideRuntimeFactory &\n IProvideFluidDataStoreFactory &\n IProvideFluidDataStoreRegistry &\n IProvideFluidCodeDetailsComparer>;\n\n// Represents the entry point for a Fluid container.\nexport type fluidEntryPoint = SupportedExportInterfaces | IFluidModule;\n\n/**\n * A simple code loader that caches a mapping of package name to a Fluid entry point.\n * On load, it retrieves the entry point matching the package name in the given code details.\n */\nexport class LocalCodeLoader implements ICodeLoader {\n private readonly fluidPackageCache = new Map<string, IFluidModule>();\n\n constructor(\n packageEntries: Iterable<[IFluidCodeDetails, fluidEntryPoint]>,\n runtimeOptions?: IContainerRuntimeOptions,\n ) {\n for (const entry of packageEntries) {\n // Store the entry point against a unique id in the fluidPackageCache.\n // For code details containing a package name, use the package name as the id.\n // For code details containing a Fluid package, create a unique id from the package name and version.\n let pkgId: string;\n\n const source = entry[0];\n if (typeof source.package === \"string\") {\n pkgId = source.package;\n } else {\n pkgId = `${source.package.name}@${source.package.version}`;\n }\n let fluidModule = entry[1] as IFluidModule;\n if (fluidModule?.fluidExport === undefined) {\n const maybeExport = fluidModule as SupportedExportInterfaces;\n\n if (maybeExport.IRuntimeFactory !== undefined) {\n fluidModule = { fluidExport: maybeExport };\n } else {\n assert(maybeExport.IFluidDataStoreFactory !== undefined);\n const defaultFactory = createDataStoreFactory(\"default\", maybeExport.IFluidDataStoreFactory);\n const innerRequestHandler = async (request: IRequest, runtime: IContainerRuntimeBase) =>\n runtime.IFluidHandleContext.resolveHandle(request);\n fluidModule = {\n fluidExport: {\n ... maybeExport,\n IRuntimeFactory:\n new ContainerRuntimeFactoryWithDefaultDataStore(\n defaultFactory,\n [[defaultFactory.type, Promise.resolve(defaultFactory)]],\n undefined,\n [innerRequestHandler],\n runtimeOptions,\n ),\n },\n };\n }\n }\n\n this.fluidPackageCache.set(pkgId, fluidModule);\n }\n }\n\n /**\n * It finds the entry point for the package name in the given source and return it\n * as a Fluid module.\n * @param source - Details of where to find chaincode\n */\n public async load(\n source: IFluidCodeDetails,\n ): Promise<IFluidModule> {\n // Get the entry point for from the fluidPackageCache for the given code details.\n // For code details containing a package name, use the package name as the id.\n // For code details containing a Fluid package, create a unique id from the package name and version.\n let pkdId: string;\n\n if (typeof source.package === \"string\") {\n pkdId = source.package;\n } else {\n pkdId = `${source.package.name}@${source.package.version}`;\n }\n\n const entryPoint = this.fluidPackageCache.get(pkdId);\n if (entryPoint === undefined) {\n throw new Error(`Cannot find package ${pkdId}`);\n }\n return entryPoint;\n }\n}\n"]}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export declare const pkgName = "@fluidframework/test-utils";
8
- export declare const pkgVersion = "0.54.1";
8
+ export declare const pkgVersion = "0.55.1";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -8,5 +8,5 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.pkgVersion = exports.pkgName = void 0;
10
10
  exports.pkgName = "@fluidframework/test-utils";
11
- exports.pkgVersion = "0.54.1";
11
+ exports.pkgVersion = "0.55.1";
12
12
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,4BAA4B,CAAC;AACvC,QAAA,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/test-utils\";\nexport const pkgVersion = \"0.54.1\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,4BAA4B,CAAC;AACvC,QAAA,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/test-utils\";\nexport const pkgVersion = \"0.55.1\";\n"]}
@@ -5,15 +5,17 @@
5
5
  import { IContainerContext, IRuntime } from "@fluidframework/container-definitions";
6
6
  import { ContainerRuntime, IContainerRuntimeOptions } from "@fluidframework/container-runtime";
7
7
  import { IContainerRuntime } from "@fluidframework/container-runtime-definitions";
8
+ import { RuntimeRequestHandler } from "@fluidframework/request-handler";
8
9
  import { IFluidDataStoreFactory } from "@fluidframework/runtime-definitions";
9
10
  /**
10
11
  * Create a container runtime factory class that allows you to set runtime options
11
12
  */
12
13
  export declare const createTestContainerRuntimeFactory: (containerRuntimeCtor: typeof ContainerRuntime) => {
13
- new (type: string, dataStoreFactory: IFluidDataStoreFactory, runtimeOptions?: IContainerRuntimeOptions): {
14
+ new (type: string, dataStoreFactory: IFluidDataStoreFactory, runtimeOptions?: IContainerRuntimeOptions, requestHandlers?: RuntimeRequestHandler[]): {
14
15
  type: string;
15
16
  dataStoreFactory: IFluidDataStoreFactory;
16
17
  runtimeOptions: IContainerRuntimeOptions;
18
+ requestHandlers: RuntimeRequestHandler[];
17
19
  instantiateFirstTime(runtime: ContainerRuntime): Promise<void>;
18
20
  instantiateFromExisting(runtime: ContainerRuntime): Promise<void>;
19
21
  preInitialize(context: IContainerContext, existing: boolean): Promise<IRuntime & IContainerRuntime>;
@@ -26,10 +28,11 @@ export declare const createTestContainerRuntimeFactory: (containerRuntimeCtor: t
26
28
  * A container runtime factory that allows you to set runtime options
27
29
  */
28
30
  export declare const TestContainerRuntimeFactory: {
29
- new (type: string, dataStoreFactory: IFluidDataStoreFactory, runtimeOptions?: IContainerRuntimeOptions): {
31
+ new (type: string, dataStoreFactory: IFluidDataStoreFactory, runtimeOptions?: IContainerRuntimeOptions, requestHandlers?: RuntimeRequestHandler[]): {
30
32
  type: string;
31
33
  dataStoreFactory: IFluidDataStoreFactory;
32
34
  runtimeOptions: IContainerRuntimeOptions;
35
+ requestHandlers: RuntimeRequestHandler[];
33
36
  instantiateFirstTime(runtime: ContainerRuntime): Promise<void>;
34
37
  instantiateFromExisting(runtime: ContainerRuntime): Promise<void>;
35
38
  preInitialize(context: IContainerContext, existing: boolean): Promise<IRuntime & IContainerRuntime>;
@@ -1 +1 @@
1
- {"version":3,"file":"testContainerRuntimeFactory.d.ts","sourceRoot":"","sources":["../src/testContainerRuntimeFactory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAC/F,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAElF,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAG7E;;GAEG;AACH,eAAO,MAAM,iCAAiC,yBAA0B,uBAAuB;eAGtE,MAAM,oBACM,sBAAsB,mBACxB,wBAAwB;cAFlC,MAAM;0BACM,sBAAsB;wBACxB,wBAAwB;sCAOR,gBAAgB,GAAG,QAAQ,IAAI,CAAC;yCAS7B,gBAAgB,GAAG,QAAQ,IAAI,CAAC;+BAQjE,iBAAiB,YAChB,OAAO,GAClB,QAAQ,QAAQ,GAAG,iBAAiB,CAAC;;;;;CAqB/C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,2BAA2B;eAtDf,MAAM,oBACM,sBAAsB,mBACxB,wBAAwB;cAFlC,MAAM;0BACM,sBAAsB;wBACxB,wBAAwB;sCAOR,gBAAgB,GAAG,QAAQ,IAAI,CAAC;yCAS7B,gBAAgB,GAAG,QAAQ,IAAI,CAAC;+BAQjE,iBAAiB,YAChB,OAAO,GAClB,QAAQ,QAAQ,GAAG,iBAAiB,CAAC;;;;;CA0B8C,CAAC"}
1
+ {"version":3,"file":"testContainerRuntimeFactory.d.ts","sourceRoot":"","sources":["../src/testContainerRuntimeFactory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAC/F,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAClF,OAAO,EAEH,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAG7E;;GAEG;AACH,eAAO,MAAM,iCAAiC,yBAA0B,uBAAuB;eAGtE,MAAM,oBACM,sBAAsB,mBACxB,wBAAwB,oBAGvB,qBAAqB,EAAE;cALlC,MAAM;0BACM,sBAAsB;wBACxB,wBAAwB;yBAGvB,qBAAqB,EAAE;sCAKR,gBAAgB,GAAG,QAAQ,IAAI,CAAC;yCAS7B,gBAAgB,GAAG,QAAQ,IAAI,CAAC;+BAQjE,iBAAiB,YAChB,OAAO,GAClB,QAAQ,QAAQ,GAAG,iBAAiB,CAAC;;;;;CAmB/C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,2BAA2B;eArDf,MAAM,oBACM,sBAAsB,mBACxB,wBAAwB,oBAGvB,qBAAqB,EAAE;cALlC,MAAM;0BACM,sBAAsB;wBACxB,wBAAwB;yBAGvB,qBAAqB,EAAE;sCAKR,gBAAgB,GAAG,QAAQ,IAAI,CAAC;yCAS7B,gBAAgB,GAAG,QAAQ,IAAI,CAAC;+BAQjE,iBAAiB,YAChB,OAAO,GAClB,QAAQ,QAAQ,GAAG,iBAAiB,CAAC;;;;;CAwB8C,CAAC"}
@@ -16,11 +16,12 @@ const createTestContainerRuntimeFactory = (containerRuntimeCtor) => {
16
16
  return class extends runtime_utils_1.RuntimeFactoryHelper {
17
17
  constructor(type, dataStoreFactory, runtimeOptions = {
18
18
  summaryOptions: { initialSummarizerDelayMs: 0 },
19
- }) {
19
+ }, requestHandlers = []) {
20
20
  super();
21
21
  this.type = type;
22
22
  this.dataStoreFactory = dataStoreFactory;
23
23
  this.runtimeOptions = runtimeOptions;
24
+ this.requestHandlers = requestHandlers;
24
25
  }
25
26
  async instantiateFirstTime(runtime) {
26
27
  await runtime.createRootDataStore(this.type, "default");
@@ -36,12 +37,10 @@ const createTestContainerRuntimeFactory = (containerRuntimeCtor) => {
36
37
  await runtime.getRootDataStore("default2");
37
38
  }
38
39
  async preInitialize(context, existing) {
39
- const builder = new request_handler_1.RuntimeRequestHandlerBuilder();
40
- builder.pushHandler(aqueduct_1.defaultRouteRequestHandler("default"), request_handler_1.innerRequestHandler);
41
40
  const runtime = await containerRuntimeCtor.load(context, [
42
41
  ["default", Promise.resolve(this.dataStoreFactory)],
43
42
  [this.type, Promise.resolve(this.dataStoreFactory)],
44
- ], async (req, rt) => builder.handleRequest(req, rt), this.runtimeOptions, undefined, // containerScope
43
+ ], request_handler_1.buildRuntimeRequestHandler(aqueduct_1.defaultRouteRequestHandler("default"), ...this.requestHandlers), this.runtimeOptions, undefined, // containerScope
45
44
  existing);
46
45
  return runtime;
47
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"testContainerRuntimeFactory.js","sourceRoot":"","sources":["../src/testContainerRuntimeFactory.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,uDAAsE;AAEtE,yEAA+F;AAE/F,qEAAoG;AAEpG,iEAAqE;AAErE;;GAEG;AACI,MAAM,iCAAiC,GAAG,CAAC,oBAA6C,EAAE,EAAE;IAC/F,OAAO,KAAM,SAAQ,oCAAoB;QACrC,YACW,IAAY,EACZ,gBAAwC,EACxC,iBAA2C;YAC9C,cAAc,EAAE,EAAE,wBAAwB,EAAE,CAAC,EAAE;SAClD;YAED,KAAK,EAAE,CAAC;YAND,SAAI,GAAJ,IAAI,CAAQ;YACZ,qBAAgB,GAAhB,gBAAgB,CAAwB;YACxC,mBAAc,GAAd,cAAc,CAEpB;QAGL,CAAC;QAEM,KAAK,CAAC,oBAAoB,CAAC,OAAyB;YACvD,MAAM,OAAO,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAExD,yBAAyB;YACzB,MAAM,YAAY,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC;YAClF,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,YAAY,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;YAC1G,MAAM,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC;QAC1E,CAAC;QAEM,KAAK,CAAC,uBAAuB,CAAC,OAAyB;YAC1D,yCAAyC;YACzC,oFAAoF;YACpF,MAAM,OAAO,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;YAC1C,MAAM,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;QAC/C,CAAC;QAED,KAAK,CAAC,aAAa,CACf,OAA0B,EAC1B,QAAiB;YAEjB,MAAM,OAAO,GAAG,IAAI,8CAA4B,EAAE,CAAC;YACnD,OAAO,CAAC,WAAW,CACf,qCAA0B,CAAC,SAAS,CAAC,EACrC,qCAAmB,CAAC,CAAC;YAEzB,MAAM,OAAO,GAAqB,MAAM,oBAAoB,CAAC,IAAI,CAC7D,OAAO,EACP;gBACI,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBACnD,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;aACtD,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,EAAE,EAAE,CAAC,EACjD,IAAI,CAAC,cAAc,EACnB,SAAS,EAAE,iBAAiB;YAC5B,QAAQ,CACX,CAAC;YAEF,OAAO,OAAO,CAAC;QACnB,CAAC;KACJ,CAAC;AACN,CAAC,CAAC;AApDW,QAAA,iCAAiC,qCAoD5C;AAEF;;GAEG;AACU,QAAA,2BAA2B,GAAG,yCAAiC,CAAC,oCAAgB,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { defaultRouteRequestHandler } from \"@fluidframework/aqueduct\";\nimport { IContainerContext, IRuntime } from \"@fluidframework/container-definitions\";\nimport { ContainerRuntime, IContainerRuntimeOptions } from \"@fluidframework/container-runtime\";\nimport { IContainerRuntime } from \"@fluidframework/container-runtime-definitions\";\nimport { innerRequestHandler, RuntimeRequestHandlerBuilder } from \"@fluidframework/request-handler\";\nimport { IFluidDataStoreFactory } from \"@fluidframework/runtime-definitions\";\nimport { RuntimeFactoryHelper } from \"@fluidframework/runtime-utils\";\n\n/**\n * Create a container runtime factory class that allows you to set runtime options\n */\nexport const createTestContainerRuntimeFactory = (containerRuntimeCtor: typeof ContainerRuntime) => {\n return class extends RuntimeFactoryHelper {\n constructor(\n public type: string,\n public dataStoreFactory: IFluidDataStoreFactory,\n public runtimeOptions: IContainerRuntimeOptions = {\n summaryOptions: { initialSummarizerDelayMs: 0 },\n },\n ) {\n super();\n }\n\n public async instantiateFirstTime(runtime: ContainerRuntime): Promise<void> {\n await runtime.createRootDataStore(this.type, \"default\");\n\n // Test detached creation\n const root2Context = runtime.createDetachedRootDataStore([this.type], \"default2\");\n const root2Runtime = await this.dataStoreFactory.instantiateDataStore(root2Context, /* existing */ false);\n await root2Context.attachRuntime(this.dataStoreFactory, root2Runtime);\n }\n\n public async instantiateFromExisting(runtime: ContainerRuntime): Promise<void> {\n // Validate we can load root data stores.\n // We should be able to load any data store that was created in initializeFirstTime!\n await runtime.getRootDataStore(\"default\");\n await runtime.getRootDataStore(\"default2\");\n }\n\n async preInitialize(\n context: IContainerContext,\n existing: boolean,\n ): Promise<IRuntime & IContainerRuntime> {\n const builder = new RuntimeRequestHandlerBuilder();\n builder.pushHandler(\n defaultRouteRequestHandler(\"default\"),\n innerRequestHandler);\n\n const runtime: ContainerRuntime = await containerRuntimeCtor.load(\n context,\n [\n [\"default\", Promise.resolve(this.dataStoreFactory)],\n [this.type, Promise.resolve(this.dataStoreFactory)],\n ],\n async (req, rt) => builder.handleRequest(req, rt),\n this.runtimeOptions,\n undefined, // containerScope\n existing,\n );\n\n return runtime;\n }\n };\n};\n\n/**\n * A container runtime factory that allows you to set runtime options\n */\nexport const TestContainerRuntimeFactory = createTestContainerRuntimeFactory(ContainerRuntime);\n"]}
1
+ {"version":3,"file":"testContainerRuntimeFactory.js","sourceRoot":"","sources":["../src/testContainerRuntimeFactory.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,uDAAsE;AAEtE,yEAA+F;AAE/F,qEAEmE;AAEnE,iEAAqE;AAErE;;GAEG;AACI,MAAM,iCAAiC,GAAG,CAAC,oBAA6C,EAAE,EAAE;IAC/F,OAAO,KAAM,SAAQ,oCAAoB;QACrC,YACW,IAAY,EACZ,gBAAwC,EACxC,iBAA2C;YAC9C,cAAc,EAAE,EAAE,wBAAwB,EAAE,CAAC,EAAE;SAClD,EACM,kBAA2C,EAAE;YAEpD,KAAK,EAAE,CAAC;YAPD,SAAI,GAAJ,IAAI,CAAQ;YACZ,qBAAgB,GAAhB,gBAAgB,CAAwB;YACxC,mBAAc,GAAd,cAAc,CAEpB;YACM,oBAAe,GAAf,eAAe,CAA8B;QAGxD,CAAC;QAEM,KAAK,CAAC,oBAAoB,CAAC,OAAyB;YACvD,MAAM,OAAO,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAExD,yBAAyB;YACzB,MAAM,YAAY,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC;YAClF,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,YAAY,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;YAC1G,MAAM,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC;QAC1E,CAAC;QAEM,KAAK,CAAC,uBAAuB,CAAC,OAAyB;YAC1D,yCAAyC;YACzC,oFAAoF;YACpF,MAAM,OAAO,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;YAC1C,MAAM,OAAO,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;QAC/C,CAAC;QAED,KAAK,CAAC,aAAa,CACf,OAA0B,EAC1B,QAAiB;YAEjB,MAAM,OAAO,GAAqB,MAAM,oBAAoB,CAAC,IAAI,CAC7D,OAAO,EACP;gBACI,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBACnD,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;aACtD,EACD,4CAA0B,CACtB,qCAA0B,CAAC,SAAS,CAAC,EACrC,GAAG,IAAI,CAAC,eAAe,CAC1B,EACD,IAAI,CAAC,cAAc,EACnB,SAAS,EAAE,iBAAiB;YAC5B,QAAQ,CACX,CAAC;YAEF,OAAO,OAAO,CAAC;QACnB,CAAC;KACJ,CAAC;AACN,CAAC,CAAC;AAnDW,QAAA,iCAAiC,qCAmD5C;AAEF;;GAEG;AACU,QAAA,2BAA2B,GAAG,yCAAiC,CAAC,oCAAgB,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { defaultRouteRequestHandler } from \"@fluidframework/aqueduct\";\nimport { IContainerContext, IRuntime } from \"@fluidframework/container-definitions\";\nimport { ContainerRuntime, IContainerRuntimeOptions } from \"@fluidframework/container-runtime\";\nimport { IContainerRuntime } from \"@fluidframework/container-runtime-definitions\";\nimport {\n buildRuntimeRequestHandler,\n RuntimeRequestHandler } from \"@fluidframework/request-handler\";\nimport { IFluidDataStoreFactory } from \"@fluidframework/runtime-definitions\";\nimport { RuntimeFactoryHelper } from \"@fluidframework/runtime-utils\";\n\n/**\n * Create a container runtime factory class that allows you to set runtime options\n */\nexport const createTestContainerRuntimeFactory = (containerRuntimeCtor: typeof ContainerRuntime) => {\n return class extends RuntimeFactoryHelper {\n constructor(\n public type: string,\n public dataStoreFactory: IFluidDataStoreFactory,\n public runtimeOptions: IContainerRuntimeOptions = {\n summaryOptions: { initialSummarizerDelayMs: 0 },\n },\n public requestHandlers: RuntimeRequestHandler[] = [],\n ) {\n super();\n }\n\n public async instantiateFirstTime(runtime: ContainerRuntime): Promise<void> {\n await runtime.createRootDataStore(this.type, \"default\");\n\n // Test detached creation\n const root2Context = runtime.createDetachedRootDataStore([this.type], \"default2\");\n const root2Runtime = await this.dataStoreFactory.instantiateDataStore(root2Context, /* existing */ false);\n await root2Context.attachRuntime(this.dataStoreFactory, root2Runtime);\n }\n\n public async instantiateFromExisting(runtime: ContainerRuntime): Promise<void> {\n // Validate we can load root data stores.\n // We should be able to load any data store that was created in initializeFirstTime!\n await runtime.getRootDataStore(\"default\");\n await runtime.getRootDataStore(\"default2\");\n }\n\n async preInitialize(\n context: IContainerContext,\n existing: boolean,\n ): Promise<IRuntime & IContainerRuntime> {\n const runtime: ContainerRuntime = await containerRuntimeCtor.load(\n context,\n [\n [\"default\", Promise.resolve(this.dataStoreFactory)],\n [this.type, Promise.resolve(this.dataStoreFactory)],\n ],\n buildRuntimeRequestHandler(\n defaultRouteRequestHandler(\"default\"),\n ...this.requestHandlers,\n ),\n this.runtimeOptions,\n undefined, // containerScope\n existing,\n );\n\n return runtime;\n }\n };\n};\n\n/**\n * A container runtime factory that allows you to set runtime options\n */\nexport const TestContainerRuntimeFactory = createTestContainerRuntimeFactory(ContainerRuntime);\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"timeoutUtils.d.ts","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACpB;AACD,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,IAAI;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;CACX;AAGF,wBAAsB,YAAY,CAAC,CAAC,GAAG,IAAI,EACvC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,cAG9D;AAEA,wBAAsB,cAAc,CAAC,CAAC,GAAG,IAAI,EAC1C,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,KAAK,IAAI,EAChG,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,GAC5D,OAAO,CAAC,CAAC,CAAC,CAqBZ"}
1
+ {"version":3,"file":"timeoutUtils.d.ts","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C,MAAM,WAAW,gBAAgB;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,IAAI,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,IAAI;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,KAAK,CAAC;IACd,KAAK,EAAE,CAAC,CAAC;CACZ;AAED,wBAAsB,YAAY,CAAC,CAAC,GAAG,IAAI,EACvC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,cAG9D;AAED,wBAAsB,cAAc,CAAC,CAAC,GAAG,IAAI,EACzC,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,IAAI,KAAK,IAAI,EAChG,cAAc,GAAE,gBAAgB,GAAG,gBAAgB,CAAC,CAAC,CAAM,GAC5D,OAAO,CAAC,CAAC,CAAC,CAqBZ"}
@@ -6,7 +6,6 @@
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.timeoutPromise = exports.timeoutAwait = exports.defaultTimeoutDurationMs = void 0;
8
8
  exports.defaultTimeoutDurationMs = 250;
9
- // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
10
9
  async function timeoutAwait(promise, timeoutOptions = {}) {
11
10
  return Promise.race([promise, timeoutPromise(() => { }, timeoutOptions)]);
12
11
  }
@@ -18,15 +17,15 @@ async function timeoutPromise(executor, timeoutOptions = {}) {
18
17
  const err = timeoutOptions.reject === false
19
18
  ? undefined
20
19
  : new Error((_a = timeoutOptions.errorMsg) !== null && _a !== void 0 ? _a : "Timeout");
21
- return new Promise((res, rej) => {
20
+ return new Promise((resolve, reject) => {
22
21
  var _a;
23
- const timeout = setTimeout(() => timeoutOptions.reject === false ? res(timeoutOptions.value) : rej(err), (_a = timeoutOptions.durationMs) !== null && _a !== void 0 ? _a : exports.defaultTimeoutDurationMs);
22
+ const timeout = setTimeout(() => timeoutOptions.reject === false ? resolve(timeoutOptions.value) : reject(err), (_a = timeoutOptions.durationMs) !== null && _a !== void 0 ? _a : exports.defaultTimeoutDurationMs);
24
23
  executor((value) => {
25
24
  clearTimeout(timeout);
26
- res(value);
25
+ resolve(value);
27
26
  }, (reason) => {
28
27
  clearTimeout(timeout);
29
- rej(reason);
28
+ reject(reason);
30
29
  });
31
30
  });
32
31
  }
@@ -1 +1 @@
1
- {"version":3,"file":"timeoutUtils.js","sourceRoot":"","sources":["../src/timeoutUtils.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEU,QAAA,wBAAwB,GAAG,GAAG,CAAC;AAa5C,+DAA+D;AACxD,KAAK,UAAU,YAAY,CAC9B,OAAuB,EACvB,iBAAyD,EAAE;IAE3D,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,cAAc,CAAI,GAAE,EAAE,GAAC,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC;AALD,oCAKC;AAEO,KAAK,UAAU,cAAc,CACjC,QAAgG,EAChG,iBAAyD,EAAE;;IAE3D,8EAA8E;IAC9E,wDAAwD;IACxD,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,KAAK,KAAK;QACvC,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,KAAK,OAAC,cAAc,CAAC,QAAQ,mCAAI,SAAS,CAAC,CAAC;IACtD,OAAO,IAAI,OAAO,CAAI,CAAC,GAAG,EAAC,GAAG,EAAC,EAAE;;QAC7B,MAAM,OAAO,GAAG,UAAU,CACtB,GAAE,EAAE,CAAA,cAAc,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,QAC1E,cAAc,CAAC,UAAU,mCAAI,gCAAwB,CAAC,CAAC;QAE3D,QAAQ,CACJ,CAAC,KAAK,EAAE,EAAE;YACN,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,GAAG,CAAC,KAAK,CAAC,CAAC;QACf,CAAC,EACD,CAAC,MAAM,EAAE,EAAE;YACP,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,GAAG,CAAC,MAAM,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACP,CAAC;AAxBA,wCAwBA","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport const defaultTimeoutDurationMs = 250;\n\n export interface TimeoutWithError{\n durationMs?: number;\n reject?: true;\n errorMsg?: string;\n }\n export interface TimeoutWithValue<T = void>{\n durationMs?: number;\n reject: false;\n value: T;\n }\n\n// eslint-disable-next-line prefer-arrow/prefer-arrow-functions\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\n export 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 // 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 ?? \"Timeout\");\n return new Promise<T>((res,rej)=>{\n const timeout = setTimeout(\n ()=>timeoutOptions.reject === false ? res(timeoutOptions.value) : rej(err),\n timeoutOptions.durationMs ?? defaultTimeoutDurationMs);\n\n executor(\n (value) => {\n clearTimeout(timeout);\n res(value);\n },\n (reason) => {\n clearTimeout(timeout);\n rej(reason);\n });\n });\n}\n"]}
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,8EAA8E;IAC9E,wDAAwD;IACxD,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,KAAK,KAAK;QACvC,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,KAAK,OAAC,cAAc,CAAC,QAAQ,mCAAI,SAAS,CAAC,CAAC;IACtD,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;;QACtC,MAAM,OAAO,GAAG,UAAU,CACtB,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,QACnF,cAAc,CAAC,UAAU,mCAAI,gCAAwB,CAAC,CAAC;QAE3D,QAAQ,CACJ,CAAC,KAAK,EAAE,EAAE;YACN,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC,EACD,CAAC,MAAM,EAAE,EAAE;YACP,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,MAAM,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACP,CAAC;AAxBD,wCAwBC","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 // 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 ?? \"Timeout\");\n return new Promise<T>((resolve, reject) => {\n const timeout = setTimeout(\n () => timeoutOptions.reject === false ? resolve(timeoutOptions.value) : reject(err),\n timeoutOptions.durationMs ?? defaultTimeoutDurationMs);\n\n executor(\n (value) => {\n clearTimeout(timeout);\n resolve(value);\n },\n (reason) => {\n clearTimeout(timeout);\n reject(reason);\n });\n });\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/test-utils",
3
- "version": "0.54.1",
3
+ "version": "0.55.1",
4
4
  "description": "Utilities for Fluid tests",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": "https://github.com/microsoft/FluidFramework",
@@ -21,7 +21,7 @@
21
21
  "ci:build:docs": "api-extractor run --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/* ../../../_api-extractor-temp/",
22
22
  "clean": "rimraf dist lib *.tsbuildinfo *.build.log",
23
23
  "eslint": "eslint --format stylish src",
24
- "eslint:fix": "eslint --format stylish src --fix",
24
+ "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
25
25
  "lint": "npm run eslint",
26
26
  "lint:fix": "npm run eslint:fix",
27
27
  "tsc": "tsc",
@@ -49,51 +49,52 @@
49
49
  "temp-directory": "nyc/.nyc_output"
50
50
  },
51
51
  "dependencies": {
52
- "@fluidframework/aqueduct": "^0.54.1",
52
+ "@fluidframework/aqueduct": "^0.55.1",
53
53
  "@fluidframework/common-definitions": "^0.20.1",
54
54
  "@fluidframework/common-utils": "^0.32.1",
55
55
  "@fluidframework/container-definitions": "^0.44.0",
56
- "@fluidframework/container-loader": "^0.54.1",
57
- "@fluidframework/container-runtime": "^0.54.1",
58
- "@fluidframework/container-runtime-definitions": "^0.54.1",
56
+ "@fluidframework/container-loader": "^0.55.1",
57
+ "@fluidframework/container-runtime": "^0.55.1",
58
+ "@fluidframework/container-runtime-definitions": "^0.55.1",
59
59
  "@fluidframework/core-interfaces": "^0.41.0",
60
- "@fluidframework/datastore": "^0.54.1",
61
- "@fluidframework/datastore-definitions": "^0.54.1",
60
+ "@fluidframework/datastore": "^0.55.1",
61
+ "@fluidframework/datastore-definitions": "^0.55.1",
62
62
  "@fluidframework/driver-definitions": "^0.43.0",
63
- "@fluidframework/driver-utils": "^0.54.1",
64
- "@fluidframework/local-driver": "^0.54.1",
65
- "@fluidframework/map": "^0.54.1",
63
+ "@fluidframework/driver-utils": "^0.55.1",
64
+ "@fluidframework/local-driver": "^0.55.1",
65
+ "@fluidframework/map": "^0.55.1",
66
66
  "@fluidframework/protocol-definitions": "^0.1026.0",
67
- "@fluidframework/request-handler": "^0.54.1",
68
- "@fluidframework/routerlicious-driver": "^0.54.1",
69
- "@fluidframework/runtime-definitions": "^0.54.1",
70
- "@fluidframework/runtime-utils": "^0.54.1",
71
- "@fluidframework/telemetry-utils": "^0.54.1",
72
- "@fluidframework/test-driver-definitions": "^0.54.1",
73
- "@fluidframework/test-runtime-utils": "^0.54.1",
67
+ "@fluidframework/request-handler": "^0.55.1",
68
+ "@fluidframework/routerlicious-driver": "^0.55.1",
69
+ "@fluidframework/runtime-definitions": "^0.55.1",
70
+ "@fluidframework/runtime-utils": "^0.55.1",
71
+ "@fluidframework/telemetry-utils": "^0.55.1",
72
+ "@fluidframework/test-driver-definitions": "^0.55.1",
73
+ "@fluidframework/test-runtime-utils": "^0.55.1",
74
74
  "debug": "^4.1.1",
75
75
  "uuid": "^8.3.1"
76
76
  },
77
77
  "devDependencies": {
78
78
  "@fluidframework/build-common": "^0.23.0",
79
- "@fluidframework/eslint-config-fluid": "^0.24.0",
79
+ "@fluidframework/eslint-config-fluid": "^0.25.0",
80
80
  "@microsoft/api-extractor": "^7.16.1",
81
+ "@rushstack/eslint-config": "^2.5.1",
81
82
  "@types/diff": "^3.5.1",
82
83
  "@types/mocha": "^8.2.2",
83
84
  "@types/node": "^14.18.0",
84
85
  "@types/random-js": "^1.0.31",
85
- "@typescript-eslint/eslint-plugin": "~4.14.0",
86
- "@typescript-eslint/parser": "~4.14.0",
86
+ "@typescript-eslint/eslint-plugin": "~5.9.0",
87
+ "@typescript-eslint/parser": "~5.9.0",
87
88
  "concurrently": "^6.2.0",
88
89
  "copyfiles": "^2.1.0",
89
90
  "diff": "^3.5.0",
90
- "eslint": "~7.18.0",
91
+ "eslint": "~8.6.0",
92
+ "eslint-plugin-editorconfig": "~3.2.0",
91
93
  "eslint-plugin-eslint-comments": "~3.2.0",
92
- "eslint-plugin-import": "~2.22.1",
94
+ "eslint-plugin-import": "~2.25.4",
93
95
  "eslint-plugin-no-null": "~1.0.2",
94
- "eslint-plugin-prefer-arrow": "~1.2.2",
95
- "eslint-plugin-react": "~7.22.0",
96
- "eslint-plugin-unicorn": "~26.0.1",
96
+ "eslint-plugin-react": "~7.28.0",
97
+ "eslint-plugin-unicorn": "~40.0.0",
97
98
  "mocha": "^8.4.0",
98
99
  "nyc": "^15.0.0",
99
100
  "random-js": "^1.0.8",
@@ -47,11 +47,8 @@ export class LoaderContainerTracker implements IOpProcessingController {
47
47
  return container;
48
48
  };
49
49
  };
50
- // eslint-disable-next-line @typescript-eslint/unbound-method
51
50
  loader.resolve = patch(loader.resolve);
52
- // eslint-disable-next-line @typescript-eslint/unbound-method
53
51
  loader.createDetachedContainer = patch(loader.createDetachedContainer);
54
- // eslint-disable-next-line @typescript-eslint/unbound-method
55
52
  loader.rehydrateDetachedContainerFromSnapshot = patch(loader.rehydrateDetachedContainerFromSnapshot);
56
53
  }
57
54
 
@@ -192,11 +189,11 @@ export class LoaderContainerTracker implements IOpProcessingController {
192
189
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
193
190
  debugWait(`Waiting container to be saved ${dirtyContainers.map((c) => this.containers.get(c)!.index)}`);
194
191
  waitingSequenceNumberSynchronized = false;
195
- await Promise.all(dirtyContainers.map(async (c) => new Promise((res) => c.once("saved", res))));
192
+ await Promise.all(dirtyContainers.map(async (c) => new Promise((resolve) => c.once("saved", resolve))));
196
193
  }
197
194
 
198
195
  // yield a turn to allow side effect of the ops we just processed execute before we check again
199
- await new Promise<void>((res) => { setTimeout(res, 0); });
196
+ await new Promise<void>((resolve) => { setTimeout(resolve, 0); });
200
197
  }
201
198
 
202
199
  // Pause all container that was resumed
@@ -299,7 +296,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
299
296
  const unconnectedClients =
300
297
  Array.from(this.containers.keys()).filter((c) => !c.closed && !(c as Container).connected);
301
298
  return Promise.all(pendingClients.map(async ([container, pendingClientId]) => {
302
- return new Promise<void>((res) => {
299
+ return new Promise<void>((resolve) => {
303
300
  const cleanup = () => {
304
301
  unconnectedClients.forEach((c) => c.off("connected", handler));
305
302
  container.getQuorum().off("removeMember", handler);
@@ -308,7 +305,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
308
305
  pendingClientId.delete(clientId);
309
306
  if (pendingClientId.size === 0) {
310
307
  cleanup();
311
- res();
308
+ resolve();
312
309
  }
313
310
  };
314
311
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -318,7 +315,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
318
315
  container.getQuorum().on("removeMember", handler);
319
316
  container.on("closed", () => {
320
317
  cleanup();
321
- res();
318
+ resolve();
322
319
  });
323
320
  });
324
321
  }));
@@ -329,12 +326,12 @@ export class LoaderContainerTracker implements IOpProcessingController {
329
326
  * @param containersToApply - the set of containers to wait for any inbound ops for
330
327
  */
331
328
  private async waitForAnyInboundOps(containersToApply: IContainer[]) {
332
- return new Promise<void>((res) => {
329
+ return new Promise<void>((resolve) => {
333
330
  const handler = () => {
334
331
  containersToApply.map((c) => {
335
332
  c.deltaManager.inbound.off("push", handler);
336
333
  });
337
- res();
334
+ resolve();
338
335
  };
339
336
  containersToApply.map((c) => {
340
337
  c.deltaManager.inbound.on("push", handler);
@@ -420,7 +417,7 @@ export class LoaderContainerTracker implements IOpProcessingController {
420
417
 
421
418
  while (resumed.some((queue) => !queue.idle)) {
422
419
  debugWait("Wait until queue is idle");
423
- await new Promise<void>((res) => { setTimeout(res, 0); });
420
+ await new Promise<void>((resolve) => { setTimeout(resolve, 0); });
424
421
  }
425
422
 
426
423
  // Make sure all the op that we sent out are acked first
@@ -10,8 +10,9 @@ import {
10
10
  IProvideRuntimeFactory,
11
11
  IFluidModule,
12
12
  } from "@fluidframework/container-definitions";
13
- import { IFluidCodeDetails, IProvideFluidCodeDetailsComparer } from "@fluidframework/core-interfaces";
14
- import { IProvideFluidDataStoreFactory, IProvideFluidDataStoreRegistry } from "@fluidframework/runtime-definitions";
13
+ import { IFluidCodeDetails, IProvideFluidCodeDetailsComparer, IRequest } from "@fluidframework/core-interfaces";
14
+ import { IContainerRuntimeBase, IProvideFluidDataStoreFactory,
15
+ IProvideFluidDataStoreRegistry } from "@fluidframework/runtime-definitions";
15
16
  import { createDataStoreFactory } from "@fluidframework/runtime-utils";
16
17
  import { IContainerRuntimeOptions } from "@fluidframework/container-runtime";
17
18
 
@@ -56,6 +57,8 @@ export class LocalCodeLoader implements ICodeLoader {
56
57
  } else {
57
58
  assert(maybeExport.IFluidDataStoreFactory !== undefined);
58
59
  const defaultFactory = createDataStoreFactory("default", maybeExport.IFluidDataStoreFactory);
60
+ const innerRequestHandler = async (request: IRequest, runtime: IContainerRuntimeBase) =>
61
+ runtime.IFluidHandleContext.resolveHandle(request);
59
62
  fluidModule = {
60
63
  fluidExport: {
61
64
  ... maybeExport,
@@ -64,7 +67,7 @@ export class LocalCodeLoader implements ICodeLoader {
64
67
  defaultFactory,
65
68
  [[defaultFactory.type, Promise.resolve(defaultFactory)]],
66
69
  undefined,
67
- undefined,
70
+ [innerRequestHandler],
68
71
  runtimeOptions,
69
72
  ),
70
73
  },
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/test-utils";
9
- export const pkgVersion = "0.54.1";
9
+ export const pkgVersion = "0.55.1";
@@ -7,7 +7,9 @@ import { defaultRouteRequestHandler } from "@fluidframework/aqueduct";
7
7
  import { IContainerContext, IRuntime } from "@fluidframework/container-definitions";
8
8
  import { ContainerRuntime, IContainerRuntimeOptions } from "@fluidframework/container-runtime";
9
9
  import { IContainerRuntime } from "@fluidframework/container-runtime-definitions";
10
- import { innerRequestHandler, RuntimeRequestHandlerBuilder } from "@fluidframework/request-handler";
10
+ import {
11
+ buildRuntimeRequestHandler,
12
+ RuntimeRequestHandler } from "@fluidframework/request-handler";
11
13
  import { IFluidDataStoreFactory } from "@fluidframework/runtime-definitions";
12
14
  import { RuntimeFactoryHelper } from "@fluidframework/runtime-utils";
13
15
 
@@ -22,6 +24,7 @@ export const createTestContainerRuntimeFactory = (containerRuntimeCtor: typeof C
22
24
  public runtimeOptions: IContainerRuntimeOptions = {
23
25
  summaryOptions: { initialSummarizerDelayMs: 0 },
24
26
  },
27
+ public requestHandlers: RuntimeRequestHandler[] = [],
25
28
  ) {
26
29
  super();
27
30
  }
@@ -46,18 +49,16 @@ export const createTestContainerRuntimeFactory = (containerRuntimeCtor: typeof C
46
49
  context: IContainerContext,
47
50
  existing: boolean,
48
51
  ): Promise<IRuntime & IContainerRuntime> {
49
- const builder = new RuntimeRequestHandlerBuilder();
50
- builder.pushHandler(
51
- defaultRouteRequestHandler("default"),
52
- innerRequestHandler);
53
-
54
52
  const runtime: ContainerRuntime = await containerRuntimeCtor.load(
55
53
  context,
56
54
  [
57
55
  ["default", Promise.resolve(this.dataStoreFactory)],
58
56
  [this.type, Promise.resolve(this.dataStoreFactory)],
59
57
  ],
60
- async (req, rt) => builder.handleRequest(req, rt),
58
+ buildRuntimeRequestHandler(
59
+ defaultRouteRequestHandler("default"),
60
+ ...this.requestHandlers,
61
+ ),
61
62
  this.runtimeOptions,
62
63
  undefined, // containerScope
63
64
  existing,
@@ -5,26 +5,25 @@
5
5
 
6
6
  export const defaultTimeoutDurationMs = 250;
7
7
 
8
- export interface TimeoutWithError{
8
+ export interface TimeoutWithError {
9
9
  durationMs?: number;
10
10
  reject?: true;
11
11
  errorMsg?: string;
12
- }
13
- export interface TimeoutWithValue<T = void>{
12
+ }
13
+ export interface TimeoutWithValue<T = void> {
14
14
  durationMs?: number;
15
15
  reject: false;
16
16
  value: T;
17
- }
17
+ }
18
18
 
19
- // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
20
19
  export async function timeoutAwait<T = void>(
21
20
  promise: PromiseLike<T>,
22
21
  timeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},
23
22
  ) {
24
- return Promise.race([promise, timeoutPromise<T>(()=>{}, timeoutOptions)]);
23
+ return Promise.race([promise, timeoutPromise<T>(() => { }, timeoutOptions)]);
25
24
  }
26
25
 
27
- export async function timeoutPromise<T = void>(
26
+ export async function timeoutPromise<T = void>(
28
27
  executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void,
29
28
  timeoutOptions: TimeoutWithError | TimeoutWithValue<T> = {},
30
29
  ): Promise<T> {
@@ -33,19 +32,19 @@ export async function timeoutAwait<T = void>(
33
32
  const err = timeoutOptions.reject === false
34
33
  ? undefined
35
34
  : new Error(timeoutOptions.errorMsg ?? "Timeout");
36
- return new Promise<T>((res,rej)=>{
35
+ return new Promise<T>((resolve, reject) => {
37
36
  const timeout = setTimeout(
38
- ()=>timeoutOptions.reject === false ? res(timeoutOptions.value) : rej(err),
37
+ () => timeoutOptions.reject === false ? resolve(timeoutOptions.value) : reject(err),
39
38
  timeoutOptions.durationMs ?? defaultTimeoutDurationMs);
40
39
 
41
40
  executor(
42
41
  (value) => {
43
42
  clearTimeout(timeout);
44
- res(value);
43
+ resolve(value);
45
44
  },
46
45
  (reason) => {
47
46
  clearTimeout(timeout);
48
- rej(reason);
47
+ reject(reason);
49
48
  });
50
49
  });
51
50
  }