@fluidframework/odsp-driver 2.114.0 → 2.115.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/api-extractor/api-extractor-lint-legacyAlpha.cjs.json +5 -0
  3. package/api-extractor/api-extractor-lint-legacyAlpha.esm.json +5 -0
  4. package/api-extractor/api-extractor.legacy.json +5 -1
  5. package/api-report/odsp-driver.legacy.alpha.api.md +232 -0
  6. package/dist/getUrlAndHeadersWithAuth.d.ts +4 -0
  7. package/dist/getUrlAndHeadersWithAuth.d.ts.map +1 -1
  8. package/dist/getUrlAndHeadersWithAuth.js +4 -0
  9. package/dist/getUrlAndHeadersWithAuth.js.map +1 -1
  10. package/dist/index.d.ts +3 -2
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +7 -3
  13. package/dist/index.js.map +1 -1
  14. package/dist/legacy.d.ts +1 -1
  15. package/dist/legacyAlpha.d.ts +49 -0
  16. package/dist/odspVersionManager/odspFileVersionFetcher.d.ts +40 -1
  17. package/dist/odspVersionManager/odspFileVersionFetcher.d.ts.map +1 -1
  18. package/dist/odspVersionManager/odspFileVersionFetcher.js +52 -14
  19. package/dist/odspVersionManager/odspFileVersionFetcher.js.map +1 -1
  20. package/dist/odspVersionManager/odspVersionManager.d.ts +23 -45
  21. package/dist/odspVersionManager/odspVersionManager.d.ts.map +1 -1
  22. package/dist/odspVersionManager/odspVersionManager.js +68 -33
  23. package/dist/odspVersionManager/odspVersionManager.js.map +1 -1
  24. package/dist/packageVersion.d.ts +1 -1
  25. package/dist/packageVersion.js +1 -1
  26. package/dist/packageVersion.js.map +1 -1
  27. package/dist/pointInTimeDriver/odspPointInTimeDocumentService.d.ts +5 -0
  28. package/dist/pointInTimeDriver/odspPointInTimeDocumentService.d.ts.map +1 -1
  29. package/dist/pointInTimeDriver/odspPointInTimeDocumentService.js +6 -3
  30. package/dist/pointInTimeDriver/odspPointInTimeDocumentService.js.map +1 -1
  31. package/dist/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.d.ts +25 -33
  32. package/dist/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.d.ts.map +1 -1
  33. package/dist/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.js +62 -38
  34. package/dist/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.js.map +1 -1
  35. package/dist/public.d.ts +1 -1
  36. package/internal.d.ts +1 -1
  37. package/legacy/alpha.d.ts +11 -0
  38. package/legacy.d.ts +1 -1
  39. package/lib/getUrlAndHeadersWithAuth.d.ts +4 -0
  40. package/lib/getUrlAndHeadersWithAuth.d.ts.map +1 -1
  41. package/lib/getUrlAndHeadersWithAuth.js +4 -0
  42. package/lib/getUrlAndHeadersWithAuth.js.map +1 -1
  43. package/lib/index.d.ts +3 -2
  44. package/lib/index.d.ts.map +1 -1
  45. package/lib/index.js +5 -3
  46. package/lib/index.js.map +1 -1
  47. package/lib/legacy.d.ts +1 -1
  48. package/lib/legacyAlpha.d.ts +49 -0
  49. package/lib/odspVersionManager/odspFileVersionFetcher.d.ts +40 -1
  50. package/lib/odspVersionManager/odspFileVersionFetcher.d.ts.map +1 -1
  51. package/lib/odspVersionManager/odspFileVersionFetcher.js +53 -15
  52. package/lib/odspVersionManager/odspFileVersionFetcher.js.map +1 -1
  53. package/lib/odspVersionManager/odspVersionManager.d.ts +23 -45
  54. package/lib/odspVersionManager/odspVersionManager.d.ts.map +1 -1
  55. package/lib/odspVersionManager/odspVersionManager.js +68 -33
  56. package/lib/odspVersionManager/odspVersionManager.js.map +1 -1
  57. package/lib/packageVersion.d.ts +1 -1
  58. package/lib/packageVersion.js +1 -1
  59. package/lib/packageVersion.js.map +1 -1
  60. package/lib/pointInTimeDriver/odspPointInTimeDocumentService.d.ts +5 -0
  61. package/lib/pointInTimeDriver/odspPointInTimeDocumentService.d.ts.map +1 -1
  62. package/lib/pointInTimeDriver/odspPointInTimeDocumentService.js +6 -3
  63. package/lib/pointInTimeDriver/odspPointInTimeDocumentService.js.map +1 -1
  64. package/lib/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.d.ts +25 -33
  65. package/lib/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.d.ts.map +1 -1
  66. package/lib/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.js +62 -38
  67. package/lib/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.js.map +1 -1
  68. package/lib/public.d.ts +1 -1
  69. package/package.json +26 -14
  70. package/src/getUrlAndHeadersWithAuth.ts +4 -0
  71. package/src/index.ts +8 -3
  72. package/src/odspVersionManager/DEV.md +376 -54
  73. package/src/odspVersionManager/odspFileVersionFetcher.ts +111 -16
  74. package/src/odspVersionManager/odspVersionManager.ts +106 -68
  75. package/src/packageVersion.ts +1 -1
  76. package/src/pointInTimeDriver/odspPointInTimeDocumentService.ts +8 -4
  77. package/src/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.ts +123 -48
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { UsageError, createChildLogger } from "@fluidframework/telemetry-utils/internal";
5
+ import { UsageError, createChildLogger, } from "@fluidframework/telemetry-utils/internal";
6
6
  import { createOdspCacheAndTracker } from "../epochTracker.js";
7
7
  import { NonPersistentCache } from "../odspCache.js";
8
8
  import { OdspDocumentServiceFactoryCore } from "../odspDocumentServiceFactoryCore.js";
@@ -10,20 +10,15 @@ import { OdspDriverUrlResolver } from "../odspDriverUrlResolver.js";
10
10
  import { createOdspLogger, getOdspResolvedUrl, toInstrumentedOdspStorageTokenFetcher, } from "../odspUtils.js";
11
11
  import { createOdspVersionManager, } from "../odspVersionManager/index.js";
12
12
  import { OdspPointInTimeDocumentService } from "./odspPointInTimeDocumentService.js";
13
- /**
14
- * ODSP document service factory that additionally supports point-in-time (sequence-number-based)
15
- * loading.
16
- *
17
- * @remarks
18
- * This extends {@link OdspDocumentServiceFactoryCore} with the ability to materialize a read-only
19
- * document service at a requested Fluid sequence number. The loader detects this capability via the
20
- * presence of {@link OdspPointInTimeDocumentServiceFactory.createPointInTimeDocumentService}, so
21
- * hosts that want to load a container to a target sequence number must construct this factory
22
- * (rather than the legacy `OdspDocumentServiceFactory`) and pass it to the loader.
23
- *
24
- * @internal
25
- */
26
- export class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFactoryCore {
13
+ class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFactoryCore {
14
+ /**
15
+ * Creates a point-in-time-capable ODSP document service factory.
16
+ *
17
+ * @param getStorageToken - Fetches storage access tokens.
18
+ * @param getWebsocketToken - Fetches websocket access tokens, or `undefined` when unavailable.
19
+ * @param persistedCache - Optional persisted ODSP cache.
20
+ * @param hostPolicy - Optional host storage policy.
21
+ */
27
22
  constructor(getStorageToken, getWebsocketToken, persistedCache, hostPolicy) {
28
23
  super(getStorageToken, getWebsocketToken, persistedCache, hostPolicy);
29
24
  this.getStorageTokenForVersions = getStorageToken;
@@ -32,9 +27,33 @@ export class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFa
32
27
  * Creates a document service that reads its snapshot from the closest file version at or before
33
28
  * the target and its deltas from the live document, materializing a requested sequence number
34
29
  * through replay.
30
+ *
31
+ * @param resolvedUrl - The resolved ODSP document URL.
32
+ * @param targetSequenceNumber - The sequence number at which to materialize the document.
33
+ * @param logger - Optional telemetry logger.
34
+ * @param clientIsSummarizer - Whether the requesting client is a summarizer.
35
+ * @returns A read-only document service materialized at the requested sequence number.
35
36
  */
36
37
  async createPointInTimeDocumentService(resolvedUrl, targetSequenceNumber, logger, clientIsSummarizer) {
37
- const versionManager = await this.createVersionManager(resolvedUrl, logger, clientIsSummarizer);
38
+ const odspLogger = createOdspLogger(logger);
39
+ const extLogger = createChildLogger({ logger: odspLogger });
40
+ const odspResolvedUrl = getOdspResolvedUrl(resolvedUrl);
41
+ // Build ONE cache-and-tracker and thread its EpochTracker through every read this method
42
+ // makes: the version-history reads that pick the base, the recoverable base snapshot, and the
43
+ // live op stream. This shared tracker IS the lineage guard.
44
+ //
45
+ // ODSP stamps each response with the file's epoch; an EpochTracker instance pins itself to the
46
+ // first epoch it sees and throws on any later divergence (see setEpoch / checkForEpochError in
47
+ // epochTracker.ts).
48
+ //
49
+ // A fresh NonPersistentCache keeps this read-only historical load isolated from the factory's
50
+ // shared cache, so a base file version's snapshot can never leak into a normal live load.
51
+ const cacheAndTracker = createOdspCacheAndTracker(this.persistedCache, new NonPersistentCache(), {
52
+ resolvedUrl: odspResolvedUrl,
53
+ docId: odspResolvedUrl.hashedDocumentId,
54
+ fileVersion: odspResolvedUrl.fileVersion,
55
+ }, extLogger, clientIsSummarizer);
56
+ const versionManager = this.createVersionManager(odspResolvedUrl, extLogger, cacheAndTracker.epochTracker);
38
57
  const baseResult = await versionManager.findBaseForSeq(targetSequenceNumber);
39
58
  if (baseResult.kind === "noBaseVersion") {
40
59
  const oldestResolvedSequenceDetail = baseResult.oldestResolvedSeq === undefined
@@ -43,8 +62,10 @@ export class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFa
43
62
  throw new UsageError(`No ODSP file version is available at or before sequence number ${targetSequenceNumber}.${oldestResolvedSequenceDetail}`);
44
63
  }
45
64
  const recoverableResolvedUrl = await this.resolveFileVersion(resolvedUrl, baseResult.base.versionId);
46
- const recoverableDocumentService = await this.createDocumentService(recoverableResolvedUrl, logger, clientIsSummarizer);
47
- const liveDocumentService = await this.createDocumentService(resolvedUrl, logger, clientIsSummarizer);
65
+ // Both services are created via createDocumentServiceCore with the shared cacheAndTracker, so
66
+ // their reads validate against the same epoch - see the lineage-guard note above.
67
+ const recoverableDocumentService = await this.createDocumentServiceCore(recoverableResolvedUrl, odspLogger, cacheAndTracker, clientIsSummarizer);
68
+ const liveDocumentService = await this.createDocumentServiceCore(resolvedUrl, odspLogger, cacheAndTracker, clientIsSummarizer);
48
69
  return new OdspPointInTimeDocumentService(recoverableResolvedUrl, recoverableDocumentService, liveDocumentService, targetSequenceNumber);
49
70
  }
50
71
  /**
@@ -52,35 +73,24 @@ export class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFa
52
73
  * versions and resolves the closest version at or before a target sequence number.
53
74
  *
54
75
  * @remarks
55
- * This wires up the plumbing the version manager needs to talk to ODSP: it resolves the URL to
56
- * its ODSP parts (site/drive/item), creates a scoped child logger, an epoch tracker (from a fresh
57
- * NonPersistentCache, since only the tracker is needed for consistency checks), and an
58
- * instrumented storage-token/auth-header fetcher. The resulting manager is used by
59
- * {@link OdspPointInTimeDocumentServiceFactory.createPointInTimeDocumentService} to pick the base
60
- * snapshot for point-in-time loading.
76
+ * The caller passes in the shared {@link EpochTracker} so the version-history reads validate
77
+ * against the same epoch as the recoverable and live document services - this is the lineage
78
+ * guard used by `createPointInTimeDocumentService`.
79
+ * The manager itself only needs the URL parts and an instrumented storage-token/auth-header
80
+ * fetcher wired to that tracker.
61
81
  */
62
- async createVersionManager(resolvedUrl, logger, clientIsSummarizer) {
63
- const odspLogger = createOdspLogger(logger);
64
- const extLogger = createChildLogger({ logger: odspLogger });
65
- const odspResolvedUrl = getOdspResolvedUrl(resolvedUrl);
82
+ createVersionManager(odspResolvedUrl, logger, epochTracker) {
66
83
  const urlParts = {
67
84
  siteUrl: odspResolvedUrl.siteUrl,
68
85
  driveId: odspResolvedUrl.driveId,
69
86
  itemId: odspResolvedUrl.itemId,
70
87
  };
71
- // Only the epochTracker from the returned cacheAndTracker is used below, so a fresh
72
- // NonPersistentCache is sufficient here.
73
- const cacheAndTracker = createOdspCacheAndTracker(this.persistedCache, new NonPersistentCache(), {
74
- resolvedUrl: odspResolvedUrl,
75
- docId: odspResolvedUrl.hashedDocumentId,
76
- fileVersion: odspResolvedUrl.fileVersion,
77
- }, extLogger, clientIsSummarizer);
78
- const getAuthHeader = toInstrumentedOdspStorageTokenFetcher(extLogger, urlParts, this.getStorageTokenForVersions);
88
+ const getAuthHeader = toInstrumentedOdspStorageTokenFetcher(logger, urlParts, this.getStorageTokenForVersions);
79
89
  return createOdspVersionManager({
80
90
  urlParts,
81
91
  getAuthHeader,
82
- epochTracker: cacheAndTracker.epochTracker,
83
- logger: extLogger,
92
+ epochTracker,
93
+ logger,
84
94
  });
85
95
  }
86
96
  async resolveFileVersion(resolvedUrl, fileVersion) {
@@ -101,4 +111,18 @@ export class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFa
101
111
  });
102
112
  }
103
113
  }
114
+ /**
115
+ * Creates an ODSP document service factory that supports point-in-time loading.
116
+ *
117
+ * @param getStorageToken - Fetches storage access tokens.
118
+ * @param getWebsocketToken - Fetches websocket access tokens, or `undefined` when unavailable.
119
+ * @param persistedCache - Optional persisted ODSP cache.
120
+ * @param hostPolicy - Optional host storage policy.
121
+ * @returns An ODSP document service factory with point-in-time loading capability.
122
+ *
123
+ * @legacy @alpha
124
+ */
125
+ export function getOdspPointInTimeDocumentServiceFactory(getStorageToken, getWebsocketToken, persistedCache, hostPolicy) {
126
+ return new OdspPointInTimeDocumentServiceFactory(getStorageToken, getWebsocketToken, persistedCache, hostPolicy);
127
+ }
104
128
  //# sourceMappingURL=odspPointInTimeDocumentServiceFactory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"odspPointInTimeDocumentServiceFactory.js","sourceRoot":"","sources":["../../src/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.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 type { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport type {\n\tIDocumentService,\n\tIPersistedCache,\n\tIResolvedUrl,\n} from \"@fluidframework/driver-definitions/internal\";\nimport type {\n\tHostStoragePolicy,\n\tIOdspUrlParts,\n\tOdspResourceTokenFetchOptions,\n\tTokenFetcher,\n} from \"@fluidframework/odsp-driver-definitions/internal\";\nimport { UsageError, createChildLogger } from \"@fluidframework/telemetry-utils/internal\";\n\nimport { createOdspCacheAndTracker } from \"../epochTracker.js\";\nimport { NonPersistentCache } from \"../odspCache.js\";\nimport { OdspDocumentServiceFactoryCore } from \"../odspDocumentServiceFactoryCore.js\";\nimport { OdspDriverUrlResolver } from \"../odspDriverUrlResolver.js\";\nimport {\n\tcreateOdspLogger,\n\tgetOdspResolvedUrl,\n\ttoInstrumentedOdspStorageTokenFetcher,\n} from \"../odspUtils.js\";\nimport {\n\tcreateOdspVersionManager,\n\ttype IOdspVersionManager,\n} from \"../odspVersionManager/index.js\";\n\nimport { OdspPointInTimeDocumentService } from \"./odspPointInTimeDocumentService.js\";\n\n/**\n * ODSP document service factory that additionally supports point-in-time (sequence-number-based)\n * loading.\n *\n * @remarks\n * This extends {@link OdspDocumentServiceFactoryCore} with the ability to materialize a read-only\n * document service at a requested Fluid sequence number. The loader detects this capability via the\n * presence of {@link OdspPointInTimeDocumentServiceFactory.createPointInTimeDocumentService}, so\n * hosts that want to load a container to a target sequence number must construct this factory\n * (rather than the legacy `OdspDocumentServiceFactory`) and pass it to the loader.\n *\n * @internal\n */\nexport class OdspPointInTimeDocumentServiceFactory extends OdspDocumentServiceFactoryCore {\n\t/**\n\t * The storage token fetcher, captured here because the base class keeps it private.\n\t */\n\tprivate readonly getStorageTokenForVersions: TokenFetcher<OdspResourceTokenFetchOptions>;\n\n\tconstructor(\n\t\tgetStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n\t\tgetWebsocketToken: TokenFetcher<OdspResourceTokenFetchOptions> | undefined,\n\t\tpersistedCache?: IPersistedCache,\n\t\thostPolicy?: HostStoragePolicy,\n\t) {\n\t\tsuper(getStorageToken, getWebsocketToken, persistedCache, hostPolicy);\n\t\tthis.getStorageTokenForVersions = getStorageToken;\n\t}\n\n\t/**\n\t * Creates a document service that reads its snapshot from the closest file version at or before\n\t * the target and its deltas from the live document, materializing a requested sequence number\n\t * through replay.\n\t */\n\tpublic async createPointInTimeDocumentService(\n\t\tresolvedUrl: IResolvedUrl,\n\t\ttargetSequenceNumber: number,\n\t\tlogger?: ITelemetryBaseLogger,\n\t\tclientIsSummarizer?: boolean,\n\t): Promise<IDocumentService> {\n\t\tconst versionManager = await this.createVersionManager(\n\t\t\tresolvedUrl,\n\t\t\tlogger,\n\t\t\tclientIsSummarizer,\n\t\t);\n\t\tconst baseResult = await versionManager.findBaseForSeq(targetSequenceNumber);\n\t\tif (baseResult.kind === \"noBaseVersion\") {\n\t\t\tconst oldestResolvedSequenceDetail =\n\t\t\t\tbaseResult.oldestResolvedSeq === undefined\n\t\t\t\t\t? \"\"\n\t\t\t\t\t: ` The oldest resolved file version is at sequence number ${baseResult.oldestResolvedSeq}.`;\n\t\t\tthrow new UsageError(\n\t\t\t\t`No ODSP file version is available at or before sequence number ${targetSequenceNumber}.${oldestResolvedSequenceDetail}`,\n\t\t\t);\n\t\t}\n\n\t\tconst recoverableResolvedUrl = await this.resolveFileVersion(\n\t\t\tresolvedUrl,\n\t\t\tbaseResult.base.versionId,\n\t\t);\n\t\tconst recoverableDocumentService = await this.createDocumentService(\n\t\t\trecoverableResolvedUrl,\n\t\t\tlogger,\n\t\t\tclientIsSummarizer,\n\t\t);\n\t\tconst liveDocumentService = await this.createDocumentService(\n\t\t\tresolvedUrl,\n\t\t\tlogger,\n\t\t\tclientIsSummarizer,\n\t\t);\n\t\treturn new OdspPointInTimeDocumentService(\n\t\t\trecoverableResolvedUrl,\n\t\t\trecoverableDocumentService,\n\t\t\tliveDocumentService,\n\t\t\ttargetSequenceNumber,\n\t\t);\n\t}\n\n\t/**\n\t * Builds an IOdspVersionManager for the given file, which enumerates the file's stored\n\t * versions and resolves the closest version at or before a target sequence number.\n\t *\n\t * @remarks\n\t * This wires up the plumbing the version manager needs to talk to ODSP: it resolves the URL to\n\t * its ODSP parts (site/drive/item), creates a scoped child logger, an epoch tracker (from a fresh\n\t * NonPersistentCache, since only the tracker is needed for consistency checks), and an\n\t * instrumented storage-token/auth-header fetcher. The resulting manager is used by\n\t * {@link OdspPointInTimeDocumentServiceFactory.createPointInTimeDocumentService} to pick the base\n\t * snapshot for point-in-time loading.\n\t */\n\tprivate async createVersionManager(\n\t\tresolvedUrl: IResolvedUrl,\n\t\tlogger?: ITelemetryBaseLogger,\n\t\tclientIsSummarizer?: boolean,\n\t): Promise<IOdspVersionManager> {\n\t\tconst odspLogger = createOdspLogger(logger);\n\t\tconst extLogger = createChildLogger({ logger: odspLogger });\n\t\tconst odspResolvedUrl = getOdspResolvedUrl(resolvedUrl);\n\t\tconst urlParts: IOdspUrlParts = {\n\t\t\tsiteUrl: odspResolvedUrl.siteUrl,\n\t\t\tdriveId: odspResolvedUrl.driveId,\n\t\t\titemId: odspResolvedUrl.itemId,\n\t\t};\n\t\t// Only the epochTracker from the returned cacheAndTracker is used below, so a fresh\n\t\t// NonPersistentCache is sufficient here.\n\t\tconst cacheAndTracker = createOdspCacheAndTracker(\n\t\t\tthis.persistedCache,\n\t\t\tnew NonPersistentCache(),\n\t\t\t{\n\t\t\t\tresolvedUrl: odspResolvedUrl,\n\t\t\t\tdocId: odspResolvedUrl.hashedDocumentId,\n\t\t\t\tfileVersion: odspResolvedUrl.fileVersion,\n\t\t\t},\n\t\t\textLogger,\n\t\t\tclientIsSummarizer,\n\t\t);\n\t\tconst getAuthHeader = toInstrumentedOdspStorageTokenFetcher(\n\t\t\textLogger,\n\t\t\turlParts,\n\t\t\tthis.getStorageTokenForVersions,\n\t\t);\n\t\treturn createOdspVersionManager({\n\t\t\turlParts,\n\t\t\tgetAuthHeader,\n\t\t\tepochTracker: cacheAndTracker.epochTracker,\n\t\t\tlogger: extLogger,\n\t\t});\n\t}\n\n\tprivate async resolveFileVersion(\n\t\tresolvedUrl: IResolvedUrl,\n\t\tfileVersion: string,\n\t): Promise<IResolvedUrl> {\n\t\tconst odspResolvedUrl = getOdspResolvedUrl(resolvedUrl);\n\t\tconst query = new URLSearchParams({\n\t\t\tdriveId: odspResolvedUrl.driveId,\n\t\t\titemId: odspResolvedUrl.itemId,\n\t\t\tfileVersion,\n\t\t});\n\t\tif (odspResolvedUrl.dataStorePath !== undefined) {\n\t\t\tquery.set(\"path\", odspResolvedUrl.dataStorePath);\n\t\t}\n\t\tif (odspResolvedUrl.codeHint?.containerPackageName !== undefined) {\n\t\t\tquery.set(\"containerPackageName\", odspResolvedUrl.codeHint.containerPackageName);\n\t\t}\n\t\treturn new OdspDriverUrlResolver().resolve({\n\t\t\turl: `${odspResolvedUrl.siteUrl}?${query.toString()}`,\n\t\t});\n\t}\n}\n"]}
1
+ {"version":3,"file":"odspPointInTimeDocumentServiceFactory.js","sourceRoot":"","sources":["../../src/pointInTimeDriver/odspPointInTimeDocumentServiceFactory.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 type { ITelemetryBaseLogger } from \"@fluidframework/core-interfaces\";\nimport type {\n\tIDocumentService,\n\tIDocumentServiceFactory,\n\tIPersistedCache,\n\tIResolvedUrl,\n} from \"@fluidframework/driver-definitions/internal\";\nimport type {\n\tHostStoragePolicy,\n\tIOdspResolvedUrl,\n\tIOdspUrlParts,\n\tOdspResourceTokenFetchOptions,\n\tTokenFetcher,\n} from \"@fluidframework/odsp-driver-definitions/internal\";\nimport {\n\tUsageError,\n\tcreateChildLogger,\n\ttype TelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n\nimport { createOdspCacheAndTracker, type EpochTracker } from \"../epochTracker.js\";\nimport { NonPersistentCache } from \"../odspCache.js\";\nimport { OdspDocumentServiceFactoryCore } from \"../odspDocumentServiceFactoryCore.js\";\nimport { OdspDriverUrlResolver } from \"../odspDriverUrlResolver.js\";\nimport {\n\tcreateOdspLogger,\n\tgetOdspResolvedUrl,\n\ttoInstrumentedOdspStorageTokenFetcher,\n} from \"../odspUtils.js\";\nimport {\n\tcreateOdspVersionManager,\n\ttype IOdspVersionManager,\n} from \"../odspVersionManager/index.js\";\n\nimport { OdspPointInTimeDocumentService } from \"./odspPointInTimeDocumentService.js\";\n\n/**\n * An ODSP document service factory that supports point-in-time (sequence-number-based) loading.\n *\n * @remarks\n * The loader detects this capability structurally, so hosts can pass this factory directly to\n * `loadContainerToSequenceNumber`.\n *\n * @legacy @alpha\n */\nexport interface IPointInTimeDocumentServiceFactory extends IDocumentServiceFactory {\n\t/**\n\t * Creates a document service that materializes the document at the requested sequence number.\n\t *\n\t * @param resolvedUrl - The resolved ODSP document URL.\n\t * @param targetSequenceNumber - The sequence number at which to materialize the document.\n\t * @param logger - Optional telemetry logger.\n\t * @param clientIsSummarizer - Whether the requesting client is a summarizer.\n\t * @returns A read-only document service materialized at the requested sequence number.\n\t */\n\tcreatePointInTimeDocumentService(\n\t\tresolvedUrl: IResolvedUrl,\n\t\ttargetSequenceNumber: number,\n\t\tlogger?: ITelemetryBaseLogger,\n\t\tclientIsSummarizer?: boolean,\n\t): Promise<IDocumentService>;\n}\n\nclass OdspPointInTimeDocumentServiceFactory\n\textends OdspDocumentServiceFactoryCore\n\timplements IPointInTimeDocumentServiceFactory\n{\n\t/**\n\t * The storage token fetcher, captured here because the base class keeps it private.\n\t */\n\tprivate readonly getStorageTokenForVersions: TokenFetcher<OdspResourceTokenFetchOptions>;\n\n\t/**\n\t * Creates a point-in-time-capable ODSP document service factory.\n\t *\n\t * @param getStorageToken - Fetches storage access tokens.\n\t * @param getWebsocketToken - Fetches websocket access tokens, or `undefined` when unavailable.\n\t * @param persistedCache - Optional persisted ODSP cache.\n\t * @param hostPolicy - Optional host storage policy.\n\t */\n\tconstructor(\n\t\tgetStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n\t\tgetWebsocketToken: TokenFetcher<OdspResourceTokenFetchOptions> | undefined,\n\t\tpersistedCache?: IPersistedCache,\n\t\thostPolicy?: HostStoragePolicy,\n\t) {\n\t\tsuper(getStorageToken, getWebsocketToken, persistedCache, hostPolicy);\n\t\tthis.getStorageTokenForVersions = getStorageToken;\n\t}\n\n\t/**\n\t * Creates a document service that reads its snapshot from the closest file version at or before\n\t * the target and its deltas from the live document, materializing a requested sequence number\n\t * through replay.\n\t *\n\t * @param resolvedUrl - The resolved ODSP document URL.\n\t * @param targetSequenceNumber - The sequence number at which to materialize the document.\n\t * @param logger - Optional telemetry logger.\n\t * @param clientIsSummarizer - Whether the requesting client is a summarizer.\n\t * @returns A read-only document service materialized at the requested sequence number.\n\t */\n\tpublic async createPointInTimeDocumentService(\n\t\tresolvedUrl: IResolvedUrl,\n\t\ttargetSequenceNumber: number,\n\t\tlogger?: ITelemetryBaseLogger,\n\t\tclientIsSummarizer?: boolean,\n\t): Promise<IDocumentService> {\n\t\tconst odspLogger = createOdspLogger(logger);\n\t\tconst extLogger = createChildLogger({ logger: odspLogger });\n\t\tconst odspResolvedUrl = getOdspResolvedUrl(resolvedUrl);\n\n\t\t// Build ONE cache-and-tracker and thread its EpochTracker through every read this method\n\t\t// makes: the version-history reads that pick the base, the recoverable base snapshot, and the\n\t\t// live op stream. This shared tracker IS the lineage guard.\n\t\t//\n\t\t// ODSP stamps each response with the file's epoch; an EpochTracker instance pins itself to the\n\t\t// first epoch it sees and throws on any later divergence (see setEpoch / checkForEpochError in\n\t\t// epochTracker.ts).\n\t\t//\n\t\t// A fresh NonPersistentCache keeps this read-only historical load isolated from the factory's\n\t\t// shared cache, so a base file version's snapshot can never leak into a normal live load.\n\t\tconst cacheAndTracker = createOdspCacheAndTracker(\n\t\t\tthis.persistedCache,\n\t\t\tnew NonPersistentCache(),\n\t\t\t{\n\t\t\t\tresolvedUrl: odspResolvedUrl,\n\t\t\t\tdocId: odspResolvedUrl.hashedDocumentId,\n\t\t\t\tfileVersion: odspResolvedUrl.fileVersion,\n\t\t\t},\n\t\t\textLogger,\n\t\t\tclientIsSummarizer,\n\t\t);\n\n\t\tconst versionManager = this.createVersionManager(\n\t\t\todspResolvedUrl,\n\t\t\textLogger,\n\t\t\tcacheAndTracker.epochTracker,\n\t\t);\n\t\tconst baseResult = await versionManager.findBaseForSeq(targetSequenceNumber);\n\t\tif (baseResult.kind === \"noBaseVersion\") {\n\t\t\tconst oldestResolvedSequenceDetail =\n\t\t\t\tbaseResult.oldestResolvedSeq === undefined\n\t\t\t\t\t? \"\"\n\t\t\t\t\t: ` The oldest resolved file version is at sequence number ${baseResult.oldestResolvedSeq}.`;\n\t\t\tthrow new UsageError(\n\t\t\t\t`No ODSP file version is available at or before sequence number ${targetSequenceNumber}.${oldestResolvedSequenceDetail}`,\n\t\t\t);\n\t\t}\n\n\t\tconst recoverableResolvedUrl = await this.resolveFileVersion(\n\t\t\tresolvedUrl,\n\t\t\tbaseResult.base.versionId,\n\t\t);\n\t\t// Both services are created via createDocumentServiceCore with the shared cacheAndTracker, so\n\t\t// their reads validate against the same epoch - see the lineage-guard note above.\n\t\tconst recoverableDocumentService = await this.createDocumentServiceCore(\n\t\t\trecoverableResolvedUrl,\n\t\t\todspLogger,\n\t\t\tcacheAndTracker,\n\t\t\tclientIsSummarizer,\n\t\t);\n\t\tconst liveDocumentService = await this.createDocumentServiceCore(\n\t\t\tresolvedUrl,\n\t\t\todspLogger,\n\t\t\tcacheAndTracker,\n\t\t\tclientIsSummarizer,\n\t\t);\n\t\treturn new OdspPointInTimeDocumentService(\n\t\t\trecoverableResolvedUrl,\n\t\t\trecoverableDocumentService,\n\t\t\tliveDocumentService,\n\t\t\ttargetSequenceNumber,\n\t\t);\n\t}\n\n\t/**\n\t * Builds an IOdspVersionManager for the given file, which enumerates the file's stored\n\t * versions and resolves the closest version at or before a target sequence number.\n\t *\n\t * @remarks\n\t * The caller passes in the shared {@link EpochTracker} so the version-history reads validate\n\t * against the same epoch as the recoverable and live document services - this is the lineage\n\t * guard used by `createPointInTimeDocumentService`.\n\t * The manager itself only needs the URL parts and an instrumented storage-token/auth-header\n\t * fetcher wired to that tracker.\n\t */\n\tprivate createVersionManager(\n\t\todspResolvedUrl: IOdspResolvedUrl,\n\t\tlogger: TelemetryLoggerExt,\n\t\tepochTracker: EpochTracker,\n\t): IOdspVersionManager {\n\t\tconst urlParts: IOdspUrlParts = {\n\t\t\tsiteUrl: odspResolvedUrl.siteUrl,\n\t\t\tdriveId: odspResolvedUrl.driveId,\n\t\t\titemId: odspResolvedUrl.itemId,\n\t\t};\n\t\tconst getAuthHeader = toInstrumentedOdspStorageTokenFetcher(\n\t\t\tlogger,\n\t\t\turlParts,\n\t\t\tthis.getStorageTokenForVersions,\n\t\t);\n\t\treturn createOdspVersionManager({\n\t\t\turlParts,\n\t\t\tgetAuthHeader,\n\t\t\tepochTracker,\n\t\t\tlogger,\n\t\t});\n\t}\n\n\tprivate async resolveFileVersion(\n\t\tresolvedUrl: IResolvedUrl,\n\t\tfileVersion: string,\n\t): Promise<IResolvedUrl> {\n\t\tconst odspResolvedUrl = getOdspResolvedUrl(resolvedUrl);\n\t\tconst query = new URLSearchParams({\n\t\t\tdriveId: odspResolvedUrl.driveId,\n\t\t\titemId: odspResolvedUrl.itemId,\n\t\t\tfileVersion,\n\t\t});\n\t\tif (odspResolvedUrl.dataStorePath !== undefined) {\n\t\t\tquery.set(\"path\", odspResolvedUrl.dataStorePath);\n\t\t}\n\t\tif (odspResolvedUrl.codeHint?.containerPackageName !== undefined) {\n\t\t\tquery.set(\"containerPackageName\", odspResolvedUrl.codeHint.containerPackageName);\n\t\t}\n\t\treturn new OdspDriverUrlResolver().resolve({\n\t\t\turl: `${odspResolvedUrl.siteUrl}?${query.toString()}`,\n\t\t});\n\t}\n}\n\n/**\n * Creates an ODSP document service factory that supports point-in-time loading.\n *\n * @param getStorageToken - Fetches storage access tokens.\n * @param getWebsocketToken - Fetches websocket access tokens, or `undefined` when unavailable.\n * @param persistedCache - Optional persisted ODSP cache.\n * @param hostPolicy - Optional host storage policy.\n * @returns An ODSP document service factory with point-in-time loading capability.\n *\n * @legacy @alpha\n */\nexport function getOdspPointInTimeDocumentServiceFactory(\n\tgetStorageToken: TokenFetcher<OdspResourceTokenFetchOptions>,\n\tgetWebsocketToken: TokenFetcher<OdspResourceTokenFetchOptions> | undefined,\n\tpersistedCache?: IPersistedCache,\n\thostPolicy?: HostStoragePolicy,\n): IPointInTimeDocumentServiceFactory {\n\treturn new OdspPointInTimeDocumentServiceFactory(\n\t\tgetStorageToken,\n\t\tgetWebsocketToken,\n\t\tpersistedCache,\n\t\thostPolicy,\n\t);\n}\n"]}
package/lib/public.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  /*
7
7
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
8
- * Generated by "flub generate entrypoints --outFileLegacyBeta legacy --outDir ./lib --node10TypeCompat" in @fluid-tools/build-cli.
8
+ * Generated by "flub generate entrypoints --outFileLegacyBeta legacy --outFileLegacyAlpha legacyAlpha --outDir ./lib --node10TypeCompat" in @fluid-tools/build-cli.
9
9
  */
10
10
 
11
11
  export {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/odsp-driver",
3
- "version": "2.114.0",
3
+ "version": "2.115.0",
4
4
  "description": "Socket storage implementation for SPO and ODC",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -33,6 +33,16 @@
33
33
  "default": "./dist/index.js"
34
34
  }
35
35
  },
36
+ "./legacy/alpha": {
37
+ "import": {
38
+ "types": "./lib/legacyAlpha.d.ts",
39
+ "default": "./lib/index.js"
40
+ },
41
+ "require": {
42
+ "types": "./dist/legacyAlpha.d.ts",
43
+ "default": "./dist/index.js"
44
+ }
45
+ },
36
46
  "./internal": {
37
47
  "import": {
38
48
  "types": "./lib/index.d.ts",
@@ -69,22 +79,22 @@
69
79
  "temp-directory": "nyc/.nyc_output"
70
80
  },
71
81
  "dependencies": {
72
- "@fluid-internal/client-utils": "~2.114.0",
73
- "@fluidframework/core-interfaces": "~2.114.0",
74
- "@fluidframework/core-utils": "~2.114.0",
75
- "@fluidframework/driver-base": "~2.114.0",
76
- "@fluidframework/driver-definitions": "~2.114.0",
77
- "@fluidframework/driver-utils": "~2.114.0",
78
- "@fluidframework/odsp-doclib-utils": "~2.114.0",
79
- "@fluidframework/odsp-driver-definitions": "~2.114.0",
80
- "@fluidframework/telemetry-utils": "~2.114.0",
82
+ "@fluid-internal/client-utils": "~2.115.0",
83
+ "@fluidframework/core-interfaces": "~2.115.0",
84
+ "@fluidframework/core-utils": "~2.115.0",
85
+ "@fluidframework/driver-base": "~2.115.0",
86
+ "@fluidframework/driver-definitions": "~2.115.0",
87
+ "@fluidframework/driver-utils": "~2.115.0",
88
+ "@fluidframework/odsp-doclib-utils": "~2.115.0",
89
+ "@fluidframework/odsp-driver-definitions": "~2.115.0",
90
+ "@fluidframework/telemetry-utils": "~2.115.0",
81
91
  "socket.io-client": "^4.8.3",
82
92
  "uuid": "^11.1.0"
83
93
  },
84
94
  "devDependencies": {
85
95
  "@arethetypeswrong/cli": "^0.18.2",
86
96
  "@biomejs/biome": "~2.4.5",
87
- "@fluid-internal/mocha-test-setup": "~2.114.0",
97
+ "@fluid-internal/mocha-test-setup": "~2.115.0",
88
98
  "@fluid-tools/build-cli": "^0.65.0",
89
99
  "@fluidframework/build-common": "^2.0.3",
90
100
  "@fluidframework/build-tools": "^0.65.0",
@@ -119,8 +129,8 @@
119
129
  "build:compile": "fluid-build . --task compile",
120
130
  "build:docs": "api-extractor run --local",
121
131
  "build:entrypoints": "fluid-build . --task build:entrypoints",
122
- "build:entrypoints:cjs": "flub generate entrypoints --resolutionConditions require --outFileLegacyBeta legacy --outDir ./dist",
123
- "build:entrypoints:esm": "flub generate entrypoints --outFileLegacyBeta legacy --outDir ./lib --node10TypeCompat",
132
+ "build:entrypoints:cjs": "flub generate entrypoints --resolutionConditions require --outFileLegacyBeta legacy --outFileLegacyAlpha legacyAlpha --outDir ./dist",
133
+ "build:entrypoints:esm": "flub generate entrypoints --outFileLegacyBeta legacy --outFileLegacyAlpha legacyAlpha --outDir ./lib --node10TypeCompat",
124
134
  "build:esnext": "tsc --project ./tsconfig.json",
125
135
  "build:genver": "gen-version",
126
136
  "build:test": "concurrently npm:build:test:esm npm:build:test:cjs",
@@ -131,15 +141,17 @@
131
141
  "check:exports": "concurrently \"npm:check:exports:*\"",
132
142
  "check:exports:bundle-release-tags": "api-extractor run --config api-extractor/api-extractor-lint-bundle.json",
133
143
  "check:exports:cjs:legacy": "api-extractor run --config api-extractor/api-extractor-lint-legacy.cjs.json",
144
+ "check:exports:cjs:legacyAlpha": "api-extractor run --config api-extractor/api-extractor-lint-legacyAlpha.cjs.json",
134
145
  "check:exports:cjs:public": "api-extractor run --config api-extractor/api-extractor-lint-public.cjs.json",
135
146
  "check:exports:esm:legacy": "api-extractor run --config api-extractor/api-extractor-lint-legacy.esm.json",
147
+ "check:exports:esm:legacyAlpha": "api-extractor run --config api-extractor/api-extractor-lint-legacyAlpha.esm.json",
136
148
  "check:exports:esm:public": "api-extractor run --config api-extractor/api-extractor-lint-public.esm.json",
137
149
  "check:format": "npm run check:biome",
138
150
  "ci:build:api-reports": "concurrently \"npm:ci:build:api-reports:*\"",
139
151
  "ci:build:api-reports:current": "api-extractor run --config api-extractor/api-extractor.current.json",
140
152
  "ci:build:api-reports:legacy": "api-extractor run --config api-extractor/api-extractor.legacy.json",
141
153
  "ci:build:docs": "api-extractor run",
142
- "clean": "rimraf --glob dist lib {alpha,beta,internal,legacy}.d.ts \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
154
+ "clean": "rimraf --glob dist lib {alpha,beta,internal,legacy}.d.ts legacyAlpha.d.ts \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
143
155
  "eslint": "eslint --quiet --format stylish src",
144
156
  "eslint:fix": "eslint --quiet --format stylish src --fix --fix-type problem,suggestion,layout",
145
157
  "format": "npm run format:biome",
@@ -5,6 +5,10 @@
5
5
 
6
6
  import { assert } from "@fluidframework/core-utils/internal";
7
7
 
8
+ /**
9
+ * Builds the request headers carrying the given Authorization header value.
10
+ * @internal
11
+ */
8
12
  export function getHeadersWithAuth(
9
13
  // eslint-disable-next-line @rushstack/no-new-null
10
14
  authHeader: string | null,
package/src/index.ts CHANGED
@@ -18,7 +18,8 @@ export {
18
18
  export { checkUrl } from "./checkUrl.js";
19
19
  export { createOdspUrl } from "./createOdspUrl.js";
20
20
  export { getHashedDocumentId, type ISnapshotContents } from "./odspPublicUtils.js";
21
- export { getOdspUrlParts, isOdcUrl, isSpoUrl } from "./odspUrlHelper.js";
21
+ export { getApiRoot, getOdspUrlParts, isOdcUrl, isSpoUrl } from "./odspUrlHelper.js";
22
+ export { getHeadersWithAuth } from "./getUrlAndHeadersWithAuth.js";
22
23
 
23
24
  // prefetch latest snapshot before container load
24
25
  export { prefetchLatestSnapshot } from "./prefetchLatestSnapshot.js";
@@ -29,8 +30,12 @@ export {
29
30
  OdspDocumentServiceFactory,
30
31
  } from "./odspDocumentServiceFactory.js";
31
32
  export { OdspDocumentServiceFactoryCore } from "./odspDocumentServiceFactoryCore.js";
32
- // eslint-disable-next-line import-x/no-internal-modules
33
- export { OdspPointInTimeDocumentServiceFactory } from "./pointInTimeDriver/odspPointInTimeDocumentServiceFactory.js";
33
+ /* eslint-disable import-x/no-internal-modules */
34
+ export {
35
+ getOdspPointInTimeDocumentServiceFactory,
36
+ type IPointInTimeDocumentServiceFactory,
37
+ } from "./pointInTimeDriver/odspPointInTimeDocumentServiceFactory.js";
38
+ /* eslint-enable import-x/no-internal-modules */
34
39
 
35
40
  // File creation
36
41
  export { createOdspCreateContainerRequest } from "./createOdspCreateContainerRequest.js";