@fluidframework/container-loader 2.0.0-internal.7.3.0 → 2.0.0-internal.8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/api-extractor-lint.json +13 -0
  3. package/api-extractor.json +3 -3
  4. package/api-report/container-loader.api.md +17 -27
  5. package/dist/connectionState.cjs +3 -0
  6. package/dist/connectionState.cjs.map +1 -1
  7. package/dist/connectionState.d.ts +3 -0
  8. package/dist/connectionState.d.ts.map +1 -1
  9. package/dist/connectionStateHandler.cjs +3 -3
  10. package/dist/connectionStateHandler.cjs.map +1 -1
  11. package/dist/connectionStateHandler.d.ts +10 -0
  12. package/dist/connectionStateHandler.d.ts.map +1 -1
  13. package/dist/container-loader-alpha.d.ts +227 -0
  14. package/dist/container-loader-beta.d.ts +87 -0
  15. package/dist/container-loader-public.d.ts +87 -0
  16. package/dist/container-loader-untrimmed.d.ts +331 -0
  17. package/dist/container.cjs +11 -22
  18. package/dist/container.cjs.map +1 -1
  19. package/dist/container.d.ts +6 -16
  20. package/dist/container.d.ts.map +1 -1
  21. package/dist/containerStorageAdapter.cjs +4 -2
  22. package/dist/containerStorageAdapter.cjs.map +1 -1
  23. package/dist/containerStorageAdapter.d.ts.map +1 -1
  24. package/dist/deltaManager.cjs +18 -1
  25. package/dist/deltaManager.cjs.map +1 -1
  26. package/dist/deltaManager.d.ts.map +1 -1
  27. package/dist/index.cjs +1 -2
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.ts +1 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/loader.cjs +2 -65
  32. package/dist/loader.cjs.map +1 -1
  33. package/dist/loader.d.ts +11 -25
  34. package/dist/loader.d.ts.map +1 -1
  35. package/dist/location-redirection-utilities/resolveWithLocationRedirection.cjs +2 -0
  36. package/dist/location-redirection-utilities/resolveWithLocationRedirection.cjs.map +1 -1
  37. package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts +2 -0
  38. package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -1
  39. package/dist/packageVersion.cjs +1 -1
  40. package/dist/packageVersion.cjs.map +1 -1
  41. package/dist/packageVersion.d.ts +1 -1
  42. package/dist/protocol.cjs.map +1 -1
  43. package/dist/protocol.d.ts +4 -0
  44. package/dist/protocol.d.ts.map +1 -1
  45. package/dist/utils.cjs +1 -0
  46. package/dist/utils.cjs.map +1 -1
  47. package/dist/utils.d.ts +2 -0
  48. package/dist/utils.d.ts.map +1 -1
  49. package/lib/audience.d.ts +0 -4
  50. package/lib/audience.d.ts.map +1 -1
  51. package/lib/catchUpMonitor.d.ts.map +1 -1
  52. package/lib/connectionManager.d.ts +1 -1
  53. package/lib/connectionManager.d.ts.map +1 -1
  54. package/lib/connectionState.d.ts +3 -0
  55. package/lib/connectionState.d.ts.map +1 -1
  56. package/lib/connectionState.mjs +3 -0
  57. package/lib/connectionState.mjs.map +1 -1
  58. package/lib/connectionStateHandler.d.ts +13 -3
  59. package/lib/connectionStateHandler.d.ts.map +1 -1
  60. package/lib/connectionStateHandler.mjs +3 -3
  61. package/lib/connectionStateHandler.mjs.map +1 -1
  62. package/lib/container-loader-alpha.d.ts +227 -0
  63. package/lib/container-loader-beta.d.ts +87 -0
  64. package/lib/container-loader-public.d.ts +87 -0
  65. package/lib/container-loader-untrimmed.d.ts +331 -0
  66. package/lib/container.d.ts +10 -20
  67. package/lib/container.d.ts.map +1 -1
  68. package/lib/container.mjs +11 -22
  69. package/lib/container.mjs.map +1 -1
  70. package/lib/containerContext.d.ts.map +1 -1
  71. package/lib/containerStorageAdapter.d.ts +1 -1
  72. package/lib/containerStorageAdapter.d.ts.map +1 -1
  73. package/lib/containerStorageAdapter.mjs +4 -2
  74. package/lib/containerStorageAdapter.mjs.map +1 -1
  75. package/lib/contracts.d.ts.map +1 -1
  76. package/lib/debugLogger.d.ts.map +1 -1
  77. package/lib/deltaManager.d.ts +1 -1
  78. package/lib/deltaManager.d.ts.map +1 -1
  79. package/lib/deltaManager.mjs +18 -1
  80. package/lib/deltaManager.mjs.map +1 -1
  81. package/lib/deltaQueue.d.ts.map +1 -1
  82. package/lib/disposal.d.ts.map +1 -1
  83. package/lib/error.d.ts.map +1 -1
  84. package/lib/index.d.ts +6 -6
  85. package/lib/index.d.ts.map +1 -1
  86. package/lib/index.mjs +1 -1
  87. package/lib/index.mjs.map +1 -1
  88. package/lib/loader.d.ts +13 -27
  89. package/lib/loader.d.ts.map +1 -1
  90. package/lib/loader.mjs +1 -63
  91. package/lib/loader.mjs.map +1 -1
  92. package/lib/location-redirection-utilities/index.d.ts +1 -1
  93. package/lib/location-redirection-utilities/index.d.ts.map +1 -1
  94. package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts +2 -0
  95. package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -1
  96. package/lib/location-redirection-utilities/resolveWithLocationRedirection.mjs +2 -0
  97. package/lib/location-redirection-utilities/resolveWithLocationRedirection.mjs.map +1 -1
  98. package/lib/noopHeuristic.d.ts.map +1 -1
  99. package/lib/packageVersion.d.ts +1 -1
  100. package/lib/packageVersion.mjs +1 -1
  101. package/lib/packageVersion.mjs.map +1 -1
  102. package/lib/protocol.d.ts +4 -0
  103. package/lib/protocol.d.ts.map +1 -1
  104. package/lib/protocol.mjs.map +1 -1
  105. package/lib/protocolTreeDocumentStorageService.d.ts.map +1 -1
  106. package/lib/quorum.d.ts +0 -4
  107. package/lib/quorum.d.ts.map +1 -1
  108. package/lib/retriableDocumentStorageService.d.ts.map +1 -1
  109. package/lib/utils.d.ts +2 -0
  110. package/lib/utils.d.ts.map +1 -1
  111. package/lib/utils.mjs +1 -0
  112. package/lib/utils.mjs.map +1 -1
  113. package/package.json +46 -16
  114. package/src/connectionState.ts +3 -0
  115. package/src/connectionStateHandler.ts +16 -3
  116. package/src/container.ts +26 -39
  117. package/src/containerStorageAdapter.ts +4 -2
  118. package/src/deltaManager.ts +25 -1
  119. package/src/index.ts +0 -1
  120. package/src/loader.ts +10 -84
  121. package/src/location-redirection-utilities/resolveWithLocationRedirection.ts +2 -0
  122. package/src/packageVersion.ts +1 -1
  123. package/src/protocol.ts +4 -0
  124. package/src/utils.ts +2 -0
package/lib/utils.mjs CHANGED
@@ -17,6 +17,7 @@ import { DriverErrorTypes } from "@fluidframework/driver-definitions";
17
17
  * with urls of type: protocol://<string>/.../..?<querystring>
18
18
  * @param url - This is the IResolvedUrl.url part of the resolved url.
19
19
  * @returns The IParsedUrl representing the input URL, or undefined if the format was not supported
20
+ * @internal
20
21
  */
21
22
  export function tryParseCompatibleResolvedUrl(url) {
22
23
  const parsed = parse(url, true);
package/lib/utils.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","sourceRoot":"","sources":["../src/utils.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 { parse } from \"url\";\nimport { v4 as uuid } from \"uuid\";\nimport { stringToBuffer, Uint8ArrayToArrayBuffer } from \"@fluid-internal/client-utils\";\nimport { assert, unreachableCase } from \"@fluidframework/core-utils\";\nimport { ISummaryTree, ISnapshotTree, SummaryType } from \"@fluidframework/protocol-definitions\";\nimport { LoggingError } from \"@fluidframework/telemetry-utils\";\nimport {\n\tCombinedAppAndProtocolSummary,\n\tDeltaStreamConnectionForbiddenError,\n\tisCombinedAppAndProtocolSummary,\n} from \"@fluidframework/driver-utils\";\nimport { DriverErrorTypes } from \"@fluidframework/driver-definitions\";\n\n// This is used when we rehydrate a container from the snapshot. Here we put the blob contents\n// in separate property: blobContents.\nexport interface ISnapshotTreeWithBlobContents extends ISnapshotTree {\n\tblobsContents: { [path: string]: ArrayBufferLike };\n\ttrees: { [path: string]: ISnapshotTreeWithBlobContents };\n}\n\n/**\n * Interface to represent the parsed parts of IResolvedUrl.url to help\n * in getting info about different parts of the url.\n * May not be compatible or relevant for any Url Resolver\n */\nexport interface IParsedUrl {\n\t/**\n\t * It is combination of tenantid/docId part of the url.\n\t */\n\tid: string;\n\t/**\n\t * It is the deep link path in the url.\n\t */\n\tpath: string;\n\t/**\n\t * Query string part of the url.\n\t */\n\tquery: string;\n\t/**\n\t * Null means do not use snapshots, undefined means load latest snapshot\n\t * otherwise it's version ID passed to IDocumentStorageService.getVersions() to figure out what snapshot to use.\n\t * If needed, can add undefined which is treated by Container.load() as load latest snapshot.\n\t */\n\tversion: string | null | undefined;\n}\n\n/**\n * Utility api to parse the IResolvedUrl.url into specific parts like querystring, path to get\n * deep link info etc.\n * Warning - This function may not be compatible with any Url Resolver's resolved url. It works\n * with urls of type: protocol://<string>/.../..?<querystring>\n * @param url - This is the IResolvedUrl.url part of the resolved url.\n * @returns The IParsedUrl representing the input URL, or undefined if the format was not supported\n */\nexport function tryParseCompatibleResolvedUrl(url: string): IParsedUrl | undefined {\n\tconst parsed = parse(url, true);\n\tif (typeof parsed.pathname !== \"string\") {\n\t\tthrow new LoggingError(\"Failed to parse pathname\");\n\t}\n\tconst query = parsed.search ?? \"\";\n\tconst regex = /^\\/([^/]*\\/[^/]*)(\\/?.*)$/;\n\tconst match = regex.exec(parsed.pathname);\n\treturn match?.length === 3\n\t\t? { id: match[1], path: match[2], query, version: parsed.query.version as string }\n\t\t: undefined;\n}\n\n/**\n * Combine the app summary and protocol summary in 1 tree.\n * @param appSummary - Summary of the app.\n * @param protocolSummary - Summary of the protocol.\n * @internal\n */\nexport function combineAppAndProtocolSummary(\n\tappSummary: ISummaryTree,\n\tprotocolSummary: ISummaryTree,\n): CombinedAppAndProtocolSummary {\n\tassert(\n\t\t!isCombinedAppAndProtocolSummary(appSummary),\n\t\t0x5a8 /* app summary is already a combined tree! */,\n\t);\n\tassert(\n\t\t!isCombinedAppAndProtocolSummary(protocolSummary),\n\t\t0x5a9 /* protocol summary is already a combined tree! */,\n\t);\n\tconst createNewSummary: CombinedAppAndProtocolSummary = {\n\t\ttype: SummaryType.Tree,\n\t\ttree: {\n\t\t\t\".protocol\": protocolSummary,\n\t\t\t\".app\": appSummary,\n\t\t},\n\t};\n\treturn createNewSummary;\n}\n\n/**\n * Converts summary tree (for upload) to snapshot tree (for download).\n * Summary tree blobs contain contents, but snapshot tree blobs normally\n * contain IDs pointing to storage. This will create 2 blob entries in the\n * snapshot tree for each blob in the summary tree. One will be the regular\n * path pointing to a uniquely generated ID. Then there will be another\n * entry with the path as that uniquely generated ID, and value as the\n * blob contents as a base-64 string.\n * @param summary - summary to convert\n */\nfunction convertSummaryToSnapshotWithEmbeddedBlobContents(\n\tsummary: ISummaryTree,\n): ISnapshotTreeWithBlobContents {\n\tconst treeNode: ISnapshotTreeWithBlobContents = {\n\t\tblobs: {},\n\t\tblobsContents: {},\n\t\ttrees: {},\n\t\tid: uuid(),\n\t\tunreferenced: summary.unreferenced,\n\t};\n\tconst keys = Object.keys(summary.tree);\n\tfor (const key of keys) {\n\t\tconst summaryObject = summary.tree[key];\n\n\t\tswitch (summaryObject.type) {\n\t\t\tcase SummaryType.Tree: {\n\t\t\t\ttreeNode.trees[key] =\n\t\t\t\t\tconvertSummaryToSnapshotWithEmbeddedBlobContents(summaryObject);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SummaryType.Attachment:\n\t\t\t\ttreeNode.blobs[key] = summaryObject.id;\n\t\t\t\tbreak;\n\t\t\tcase SummaryType.Blob: {\n\t\t\t\tconst blobId = uuid();\n\t\t\t\ttreeNode.blobs[key] = blobId;\n\t\t\t\tconst contentBuffer =\n\t\t\t\t\ttypeof summaryObject.content === \"string\"\n\t\t\t\t\t\t? stringToBuffer(summaryObject.content, \"utf8\")\n\t\t\t\t\t\t: Uint8ArrayToArrayBuffer(summaryObject.content);\n\t\t\t\ttreeNode.blobsContents[blobId] = contentBuffer;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SummaryType.Handle:\n\t\t\t\tthrow new LoggingError(\n\t\t\t\t\t\"No handles should be there in summary in detached container!!\",\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tdefault: {\n\t\t\t\tunreachableCase(summaryObject, `Unknown tree type ${(summaryObject as any).type}`);\n\t\t\t}\n\t\t}\n\t}\n\treturn treeNode;\n}\n\n/**\n * Combine and convert protocol and app summary tree to format which is readable by container while rehydrating.\n * @param protocolSummaryTree - Protocol Summary Tree\n * @param appSummaryTree - App Summary Tree\n */\nexport function convertProtocolAndAppSummaryToSnapshotTree(\n\tprotocolSummaryTree: ISummaryTree,\n\tappSummaryTree: ISummaryTree,\n): ISnapshotTreeWithBlobContents {\n\t// Shallow copy is fine, since we are doing a deep clone below.\n\tconst combinedSummary: ISummaryTree = {\n\t\ttype: SummaryType.Tree,\n\t\ttree: { ...appSummaryTree.tree },\n\t};\n\n\tcombinedSummary.tree[\".protocol\"] = protocolSummaryTree;\n\tconst snapshotTreeWithBlobContents =\n\t\tconvertSummaryToSnapshotWithEmbeddedBlobContents(combinedSummary);\n\treturn snapshotTreeWithBlobContents;\n}\n\n// This function converts the snapshot taken in detached container(by serialize api) to snapshotTree with which\n// a detached container can be rehydrated.\nexport const getSnapshotTreeFromSerializedContainer = (\n\tdetachedContainerSnapshot: ISummaryTree,\n): ISnapshotTreeWithBlobContents => {\n\tassert(\n\t\tisCombinedAppAndProtocolSummary(detachedContainerSnapshot),\n\t\t0x1e0 /* \"Protocol and App summary trees should be present\" */,\n\t);\n\tconst protocolSummaryTree = detachedContainerSnapshot.tree[\".protocol\"];\n\tconst appSummaryTree = detachedContainerSnapshot.tree[\".app\"];\n\tconst snapshotTreeWithBlobContents = convertProtocolAndAppSummaryToSnapshotTree(\n\t\tprotocolSummaryTree,\n\t\tappSummaryTree,\n\t);\n\treturn snapshotTreeWithBlobContents;\n};\n\nexport function getProtocolSnapshotTree(snapshot: ISnapshotTree): ISnapshotTree {\n\treturn \".protocol\" in snapshot.trees ? snapshot.trees[\".protocol\"] : snapshot;\n}\n\nexport function isDeltaStreamConnectionForbiddenError(\n\terror: any,\n): error is DeltaStreamConnectionForbiddenError {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\terror?.errorType === DriverErrorTypes.deltaStreamConnectionForbidden\n\t);\n}\n"]}
1
+ {"version":3,"file":"utils.mjs","sourceRoot":"","sources":["../src/utils.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 { parse } from \"url\";\nimport { v4 as uuid } from \"uuid\";\nimport { stringToBuffer, Uint8ArrayToArrayBuffer } from \"@fluid-internal/client-utils\";\nimport { assert, unreachableCase } from \"@fluidframework/core-utils\";\nimport { ISummaryTree, ISnapshotTree, SummaryType } from \"@fluidframework/protocol-definitions\";\nimport { LoggingError } from \"@fluidframework/telemetry-utils\";\nimport {\n\tCombinedAppAndProtocolSummary,\n\tDeltaStreamConnectionForbiddenError,\n\tisCombinedAppAndProtocolSummary,\n} from \"@fluidframework/driver-utils\";\nimport { DriverErrorTypes } from \"@fluidframework/driver-definitions\";\n\n// This is used when we rehydrate a container from the snapshot. Here we put the blob contents\n// in separate property: blobContents.\nexport interface ISnapshotTreeWithBlobContents extends ISnapshotTree {\n\tblobsContents: { [path: string]: ArrayBufferLike };\n\ttrees: { [path: string]: ISnapshotTreeWithBlobContents };\n}\n\n/**\n * Interface to represent the parsed parts of IResolvedUrl.url to help\n * in getting info about different parts of the url.\n * May not be compatible or relevant for any Url Resolver\n * @internal\n */\nexport interface IParsedUrl {\n\t/**\n\t * It is combination of tenantid/docId part of the url.\n\t */\n\tid: string;\n\t/**\n\t * It is the deep link path in the url.\n\t */\n\tpath: string;\n\t/**\n\t * Query string part of the url.\n\t */\n\tquery: string;\n\t/**\n\t * Null means do not use snapshots, undefined means load latest snapshot\n\t * otherwise it's version ID passed to IDocumentStorageService.getVersions() to figure out what snapshot to use.\n\t * If needed, can add undefined which is treated by Container.load() as load latest snapshot.\n\t */\n\tversion: string | null | undefined;\n}\n\n/**\n * Utility api to parse the IResolvedUrl.url into specific parts like querystring, path to get\n * deep link info etc.\n * Warning - This function may not be compatible with any Url Resolver's resolved url. It works\n * with urls of type: protocol://<string>/.../..?<querystring>\n * @param url - This is the IResolvedUrl.url part of the resolved url.\n * @returns The IParsedUrl representing the input URL, or undefined if the format was not supported\n * @internal\n */\nexport function tryParseCompatibleResolvedUrl(url: string): IParsedUrl | undefined {\n\tconst parsed = parse(url, true);\n\tif (typeof parsed.pathname !== \"string\") {\n\t\tthrow new LoggingError(\"Failed to parse pathname\");\n\t}\n\tconst query = parsed.search ?? \"\";\n\tconst regex = /^\\/([^/]*\\/[^/]*)(\\/?.*)$/;\n\tconst match = regex.exec(parsed.pathname);\n\treturn match?.length === 3\n\t\t? { id: match[1], path: match[2], query, version: parsed.query.version as string }\n\t\t: undefined;\n}\n\n/**\n * Combine the app summary and protocol summary in 1 tree.\n * @param appSummary - Summary of the app.\n * @param protocolSummary - Summary of the protocol.\n * @internal\n */\nexport function combineAppAndProtocolSummary(\n\tappSummary: ISummaryTree,\n\tprotocolSummary: ISummaryTree,\n): CombinedAppAndProtocolSummary {\n\tassert(\n\t\t!isCombinedAppAndProtocolSummary(appSummary),\n\t\t0x5a8 /* app summary is already a combined tree! */,\n\t);\n\tassert(\n\t\t!isCombinedAppAndProtocolSummary(protocolSummary),\n\t\t0x5a9 /* protocol summary is already a combined tree! */,\n\t);\n\tconst createNewSummary: CombinedAppAndProtocolSummary = {\n\t\ttype: SummaryType.Tree,\n\t\ttree: {\n\t\t\t\".protocol\": protocolSummary,\n\t\t\t\".app\": appSummary,\n\t\t},\n\t};\n\treturn createNewSummary;\n}\n\n/**\n * Converts summary tree (for upload) to snapshot tree (for download).\n * Summary tree blobs contain contents, but snapshot tree blobs normally\n * contain IDs pointing to storage. This will create 2 blob entries in the\n * snapshot tree for each blob in the summary tree. One will be the regular\n * path pointing to a uniquely generated ID. Then there will be another\n * entry with the path as that uniquely generated ID, and value as the\n * blob contents as a base-64 string.\n * @param summary - summary to convert\n */\nfunction convertSummaryToSnapshotWithEmbeddedBlobContents(\n\tsummary: ISummaryTree,\n): ISnapshotTreeWithBlobContents {\n\tconst treeNode: ISnapshotTreeWithBlobContents = {\n\t\tblobs: {},\n\t\tblobsContents: {},\n\t\ttrees: {},\n\t\tid: uuid(),\n\t\tunreferenced: summary.unreferenced,\n\t};\n\tconst keys = Object.keys(summary.tree);\n\tfor (const key of keys) {\n\t\tconst summaryObject = summary.tree[key];\n\n\t\tswitch (summaryObject.type) {\n\t\t\tcase SummaryType.Tree: {\n\t\t\t\ttreeNode.trees[key] =\n\t\t\t\t\tconvertSummaryToSnapshotWithEmbeddedBlobContents(summaryObject);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SummaryType.Attachment:\n\t\t\t\ttreeNode.blobs[key] = summaryObject.id;\n\t\t\t\tbreak;\n\t\t\tcase SummaryType.Blob: {\n\t\t\t\tconst blobId = uuid();\n\t\t\t\ttreeNode.blobs[key] = blobId;\n\t\t\t\tconst contentBuffer =\n\t\t\t\t\ttypeof summaryObject.content === \"string\"\n\t\t\t\t\t\t? stringToBuffer(summaryObject.content, \"utf8\")\n\t\t\t\t\t\t: Uint8ArrayToArrayBuffer(summaryObject.content);\n\t\t\t\ttreeNode.blobsContents[blobId] = contentBuffer;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SummaryType.Handle:\n\t\t\t\tthrow new LoggingError(\n\t\t\t\t\t\"No handles should be there in summary in detached container!!\",\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tdefault: {\n\t\t\t\tunreachableCase(summaryObject, `Unknown tree type ${(summaryObject as any).type}`);\n\t\t\t}\n\t\t}\n\t}\n\treturn treeNode;\n}\n\n/**\n * Combine and convert protocol and app summary tree to format which is readable by container while rehydrating.\n * @param protocolSummaryTree - Protocol Summary Tree\n * @param appSummaryTree - App Summary Tree\n */\nexport function convertProtocolAndAppSummaryToSnapshotTree(\n\tprotocolSummaryTree: ISummaryTree,\n\tappSummaryTree: ISummaryTree,\n): ISnapshotTreeWithBlobContents {\n\t// Shallow copy is fine, since we are doing a deep clone below.\n\tconst combinedSummary: ISummaryTree = {\n\t\ttype: SummaryType.Tree,\n\t\ttree: { ...appSummaryTree.tree },\n\t};\n\n\tcombinedSummary.tree[\".protocol\"] = protocolSummaryTree;\n\tconst snapshotTreeWithBlobContents =\n\t\tconvertSummaryToSnapshotWithEmbeddedBlobContents(combinedSummary);\n\treturn snapshotTreeWithBlobContents;\n}\n\n// This function converts the snapshot taken in detached container(by serialize api) to snapshotTree with which\n// a detached container can be rehydrated.\nexport const getSnapshotTreeFromSerializedContainer = (\n\tdetachedContainerSnapshot: ISummaryTree,\n): ISnapshotTreeWithBlobContents => {\n\tassert(\n\t\tisCombinedAppAndProtocolSummary(detachedContainerSnapshot),\n\t\t0x1e0 /* \"Protocol and App summary trees should be present\" */,\n\t);\n\tconst protocolSummaryTree = detachedContainerSnapshot.tree[\".protocol\"];\n\tconst appSummaryTree = detachedContainerSnapshot.tree[\".app\"];\n\tconst snapshotTreeWithBlobContents = convertProtocolAndAppSummaryToSnapshotTree(\n\t\tprotocolSummaryTree,\n\t\tappSummaryTree,\n\t);\n\treturn snapshotTreeWithBlobContents;\n};\n\nexport function getProtocolSnapshotTree(snapshot: ISnapshotTree): ISnapshotTree {\n\treturn \".protocol\" in snapshot.trees ? snapshot.trees[\".protocol\"] : snapshot;\n}\n\nexport function isDeltaStreamConnectionForbiddenError(\n\terror: any,\n): error is DeltaStreamConnectionForbiddenError {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\terror?.errorType === DriverErrorTypes.deltaStreamConnectionForbidden\n\t);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/container-loader",
3
- "version": "2.0.0-internal.7.3.0",
3
+ "version": "2.0.0-internal.8.0.0",
4
4
  "description": "Fluid container loader",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -35,15 +35,15 @@
35
35
  "temp-directory": "nyc/.nyc_output"
36
36
  },
37
37
  "dependencies": {
38
- "@fluid-internal/client-utils": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
39
- "@fluidframework/container-definitions": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
40
- "@fluidframework/core-interfaces": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
41
- "@fluidframework/core-utils": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
42
- "@fluidframework/driver-definitions": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
43
- "@fluidframework/driver-utils": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
38
+ "@fluid-internal/client-utils": ">=2.0.0-internal.8.0.0 <2.0.0-internal.8.1.0",
39
+ "@fluidframework/container-definitions": ">=2.0.0-internal.8.0.0 <2.0.0-internal.8.1.0",
40
+ "@fluidframework/core-interfaces": ">=2.0.0-internal.8.0.0 <2.0.0-internal.8.1.0",
41
+ "@fluidframework/core-utils": ">=2.0.0-internal.8.0.0 <2.0.0-internal.8.1.0",
42
+ "@fluidframework/driver-definitions": ">=2.0.0-internal.8.0.0 <2.0.0-internal.8.1.0",
43
+ "@fluidframework/driver-utils": ">=2.0.0-internal.8.0.0 <2.0.0-internal.8.1.0",
44
44
  "@fluidframework/protocol-base": "^2.0.1",
45
45
  "@fluidframework/protocol-definitions": "^3.0.0",
46
- "@fluidframework/telemetry-utils": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
46
+ "@fluidframework/telemetry-utils": ">=2.0.0-internal.8.0.0 <2.0.0-internal.8.1.0",
47
47
  "debug": "^4.3.4",
48
48
  "double-ended-queue": "^2.1.0-0",
49
49
  "events": "^3.1.0",
@@ -51,21 +51,23 @@
51
51
  "uuid": "^9.0.0"
52
52
  },
53
53
  "devDependencies": {
54
- "@fluid-private/test-loader-utils": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
54
+ "@arethetypeswrong/cli": "^0.13.3",
55
+ "@fluid-private/test-loader-utils": ">=2.0.0-internal.8.0.0 <2.0.0-internal.8.1.0",
55
56
  "@fluid-tools/build-cli": "^0.28.0",
56
57
  "@fluidframework/build-common": "^2.0.3",
57
58
  "@fluidframework/build-tools": "^0.28.0",
58
59
  "@fluidframework/container-loader-previous": "npm:@fluidframework/container-loader@2.0.0-internal.7.2.0",
59
60
  "@fluidframework/eslint-config-fluid": "^3.1.0",
60
- "@fluidframework/mocha-test-setup": ">=2.0.0-internal.7.3.0 <2.0.0-internal.7.4.0",
61
+ "@fluidframework/mocha-test-setup": ">=2.0.0-internal.8.0.0 <2.0.0-internal.8.1.0",
61
62
  "@microsoft/api-extractor": "^7.38.3",
62
63
  "@types/debug": "^4.1.5",
63
64
  "@types/double-ended-queue": "^2.1.0",
64
65
  "@types/events": "^3.0.0",
65
66
  "@types/mocha": "^9.1.1",
66
- "@types/node": "^16.18.38",
67
+ "@types/node": "^18.19.0",
67
68
  "@types/sinon": "^7.0.13",
68
69
  "c8": "^7.7.1",
70
+ "copyfiles": "^2.4.1",
69
71
  "cross-env": "^7.0.3",
70
72
  "eslint": "~8.50.0",
71
73
  "mocha": "^10.2.0",
@@ -78,26 +80,54 @@
78
80
  "tsc-multi": "^1.1.0",
79
81
  "typescript": "~5.1.6"
80
82
  },
83
+ "fluidBuild": {
84
+ "tasks": {
85
+ "build:docs": {
86
+ "dependsOn": [
87
+ "...",
88
+ "api-extractor:commonjs",
89
+ "api-extractor:esnext"
90
+ ],
91
+ "script": false
92
+ }
93
+ }
94
+ },
81
95
  "typeValidation": {
82
- "broken": {}
96
+ "broken": {
97
+ "RemovedFunctionDeclaration_requestResolvedObjectFromContainer": {
98
+ "forwardCompat": false,
99
+ "backCompat": false
100
+ },
101
+ "InterfaceDeclaration_IContainerExperimental": {
102
+ "backCompat": false
103
+ },
104
+ "ClassDeclaration_Loader": {
105
+ "backCompat": false
106
+ }
107
+ }
83
108
  },
84
109
  "scripts": {
110
+ "api": "fluid-build . --task api",
111
+ "api-extractor:commonjs": "api-extractor run --local",
112
+ "api-extractor:esnext": "copyfiles -u 1 \"dist/**/*-@(alpha|beta|public|untrimmed).d.ts\" lib",
85
113
  "build": "fluid-build . --task build",
86
114
  "build:commonjs": "fluid-build . --task commonjs",
87
115
  "build:compile": "fluid-build . --task compile",
88
- "build:docs": "api-extractor run --local",
116
+ "build:docs": "fluid-build . --task api",
89
117
  "build:esnext": "tsc-multi --config ../../../common/build/build-common/tsc-multi.esm.json",
90
118
  "build:genver": "gen-version",
91
119
  "build:test": "tsc-multi --config tsc-multi.test.json",
120
+ "check:are-the-types-wrong": "attw --pack",
121
+ "check:release-tags": "api-extractor run --local --config ./api-extractor-lint.json",
92
122
  "ci:build:docs": "api-extractor run",
93
123
  "clean": "rimraf --glob dist lib \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
94
124
  "eslint": "eslint --format stylish src",
95
125
  "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
96
126
  "format": "npm run prettier:fix",
97
- "lint": "npm run prettier && npm run eslint",
127
+ "lint": "npm run prettier && npm run check:release-tags && npm run eslint",
98
128
  "lint:fix": "npm run prettier:fix && npm run eslint:fix",
99
- "prettier": "prettier --check . --ignore-path ../../../.prettierignore",
100
- "prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
129
+ "prettier": "prettier --check . --cache --ignore-path ../../../.prettierignore",
130
+ "prettier:fix": "prettier --write . --cache --ignore-path ../../../.prettierignore",
101
131
  "test": "npm run test:mocha",
102
132
  "test:coverage": "c8 npm test",
103
133
  "test:mocha": "mocha --ignore \"dist/test/types/*\" --recursive dist/test -r node_modules/@fluidframework/mocha-test-setup",
@@ -3,6 +3,9 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
+ /**
7
+ * @internal
8
+ */
6
9
  export enum ConnectionState {
7
10
  /**
8
11
  * The container is not connected to the ordering service
@@ -312,12 +312,25 @@ class ConnectionStateCatchup extends ConnectionStateHandlerPassThrough {
312
312
  class ConnectionStateHandler implements IConnectionStateHandler {
313
313
  private _connectionState = ConnectionState.Disconnected;
314
314
  private _pendingClientId: string | undefined;
315
+
316
+ /**
317
+ * Tracks that we observe the "leave" op within the timeout for our previous clientId (see comment on ConnectionStateHandler class)
318
+ * ! This ensures we do not switch to a new clientId until we process all potential messages from old clientId
319
+ * ! i.e. We will always see the "leave" op for a client after we have seen all the ops it has sent
320
+ * ! This check helps prevent the same op from being resubmitted by the PendingStateManager upon reconnecting
321
+ */
315
322
  private readonly prevClientLeftTimer: Timer;
323
+
324
+ /**
325
+ * Tracks that we observe our own "join" op within the timeout after receiving a "connected" event from the DeltaManager
326
+ */
316
327
  private readonly joinOpTimer: Timer;
328
+
317
329
  private protocol?: IProtocolHandler;
318
330
  private connection?: IConnectionDetailsInternal;
319
331
  private _clientId?: string;
320
332
 
333
+ /** Track how long we waited to see "leave" op for previous clientId */
321
334
  private waitEvent: PerformanceEvent | undefined;
322
335
 
323
336
  public get connectionState(): ConnectionState {
@@ -453,9 +466,9 @@ class ConnectionStateHandler implements IConnectionStateHandler {
453
466
  0x2e2 /* "Must only wait for leave message when clientId in quorum" */,
454
467
  );
455
468
 
456
- // Move to connected state only if we are in Connecting state, we have seen our join op
457
- // and there is no timer running which means we are not waiting for previous client to leave
458
- // or timeout has occurred while doing so.
469
+ // Move to connected state only if:
470
+ // 1. We have seen our own "join" op (i.e. for this.pendingClientId)
471
+ // 2. There is no "leave" timer running, meaning this is our first connection or the previous client has left (via this.prevClientLeftTimer)
459
472
  if (
460
473
  this.pendingClientId !== this.clientId &&
461
474
  this.hasMember(this.pendingClientId) &&
package/src/container.ts CHANGED
@@ -11,9 +11,6 @@ import {
11
11
  ITelemetryProperties,
12
12
  TelemetryEventCategory,
13
13
  IRequest,
14
- IResponse,
15
- // eslint-disable-next-line import/no-deprecated
16
- IFluidRouter,
17
14
  FluidObject,
18
15
  LogLevel,
19
16
  } from "@fluidframework/core-interfaces";
@@ -237,6 +234,7 @@ export interface IContainerCreateProps {
237
234
  * but it maybe still behind.
238
235
  *
239
236
  * @throws an error beginning with `"Container closed"` if the container is closed before it catches up.
237
+ * @internal
240
238
  */
241
239
  export async function waitContainerToCatchUp(container: IContainer) {
242
240
  // Make sure we stop waiting if container is closed.
@@ -497,6 +495,7 @@ export class Container
497
495
  private readonly subLogger: ITelemetryLoggerExt;
498
496
  private readonly detachedBlobStorage: IDetachedBlobStorage | undefined;
499
497
  private readonly protocolHandlerBuilder: ProtocolHandlerBuilder;
498
+ private readonly client: IClient;
500
499
 
501
500
  private readonly mc: MonitoringContext;
502
501
 
@@ -599,14 +598,6 @@ export class Container
599
598
  return this._deltaManager.connectionManager.connectionMode;
600
599
  }
601
600
 
602
- /**
603
- * @deprecated Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
604
- */
605
- // eslint-disable-next-line import/no-deprecated
606
- public get IFluidRouter(): IFluidRouter {
607
- return this;
608
- }
609
-
610
601
  public get resolvedUrl(): IResolvedUrl | undefined {
611
602
  /**
612
603
  * All attached containers will have a document service,
@@ -716,14 +707,14 @@ export class Container
716
707
  /**
717
708
  * {@inheritDoc @fluidframework/container-definitions#IContainer.entryPoint}
718
709
  */
719
- public async getEntryPoint(): Promise<FluidObject | undefined> {
710
+ public async getEntryPoint(): Promise<FluidObject> {
720
711
  if (this._disposed) {
721
712
  throw new UsageError("The context is already disposed");
722
713
  }
723
714
  if (this._runtime !== undefined) {
724
715
  return this._runtime.getEntryPoint?.();
725
716
  }
726
- return new Promise<FluidObject | undefined>((resolve, reject) => {
717
+ return new Promise<FluidObject>((resolve, reject) => {
727
718
  const runtimeInstantiatedHandler = () => {
728
719
  assert(
729
720
  this._runtime !== undefined,
@@ -814,6 +805,14 @@ export class Container
814
805
  });
815
806
  };
816
807
 
808
+ this._containerId = uuid();
809
+
810
+ this.client = Container.setupClient(
811
+ this._containerId,
812
+ this.options,
813
+ this.clientDetailsOverride,
814
+ );
815
+
817
816
  // Create logger for data stores to use
818
817
  const type = this.client.details.type;
819
818
  const interactive = this.client.details.capabilities.interactive;
@@ -821,7 +820,6 @@ export class Container
821
820
  type !== undefined && type !== "" ? `/${type}` : ""
822
821
  }`;
823
822
 
824
- this._containerId = uuid();
825
823
  // Need to use the property getter for docId because for detached flow we don't have the docId initially.
826
824
  // We assign the id later so property getter is used.
827
825
  this.subLogger = createChildLogger({
@@ -1116,7 +1114,6 @@ export class Container
1116
1114
  // runtime matches pending ops to successful ones by clientId and client seq num, so we need to close the
1117
1115
  // container at the same time we get pending state, otherwise this container could reconnect and resubmit with
1118
1116
  // a new clientId and a future container using stale pending state without the new clientId would resubmit them
1119
- this.disconnectInternal({ text: "closeAndGetPendingLocalState" }); // TODO https://dev.azure.com/fluidframework/internal/_workitems/edit/5127
1120
1117
  const pendingState = await this.getPendingLocalStateCore({
1121
1118
  notifyImminentClosure: true,
1122
1119
  stopBlobAttachingSignal,
@@ -1347,18 +1344,6 @@ export class Container
1347
1344
  );
1348
1345
  }
1349
1346
 
1350
- /**
1351
- * @deprecated Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
1352
- */
1353
- public async request(path: IRequest): Promise<IResponse> {
1354
- return PerformanceEvent.timedExecAsync(
1355
- this.mc.logger,
1356
- { eventName: "Request" },
1357
- async () => this.runtime.request(path),
1358
- { end: true, cancel: "error" },
1359
- );
1360
- }
1361
-
1362
1347
  private setAutoReconnectInternal(mode: ReconnectMode, reason: IConnectionStateChangeReason) {
1363
1348
  const currentMode = this._deltaManager.connectionManager.reconnectMode;
1364
1349
 
@@ -1996,10 +1981,15 @@ export class Container
1996
1981
  return pkg as IFluidCodeDetails;
1997
1982
  }
1998
1983
 
1999
- private get client(): IClient {
1984
+ private static setupClient(
1985
+ containerId: string,
1986
+ options?: ILoaderOptions,
1987
+ clientDetailsOverride?: IClientDetails,
1988
+ ): IClient {
1989
+ const loaderOptionsClient = structuredClone(options?.client);
2000
1990
  const client: IClient =
2001
- this.options?.client !== undefined
2002
- ? (this.options.client as IClient)
1991
+ loaderOptionsClient !== undefined
1992
+ ? (loaderOptionsClient as IClient)
2003
1993
  : {
2004
1994
  details: {
2005
1995
  capabilities: { interactive: true },
@@ -2010,21 +2000,22 @@ export class Container
2010
2000
  user: { id: "" },
2011
2001
  };
2012
2002
 
2013
- if (this.clientDetailsOverride !== undefined) {
2003
+ if (clientDetailsOverride !== undefined) {
2014
2004
  client.details = {
2015
2005
  ...client.details,
2016
- ...this.clientDetailsOverride,
2006
+ ...clientDetailsOverride,
2017
2007
  capabilities: {
2018
2008
  ...client.details.capabilities,
2019
- ...this.clientDetailsOverride.capabilities,
2009
+ ...clientDetailsOverride?.capabilities,
2020
2010
  },
2021
2011
  };
2022
2012
  }
2023
2013
  client.details.environment = [
2024
2014
  client.details.environment,
2025
2015
  ` loaderVersion:${pkgVersion}`,
2026
- ` containerId:${this._containerId}`,
2016
+ ` containerId:${containerId}`,
2027
2017
  ].join(";");
2018
+
2028
2019
  return client;
2029
2020
  }
2030
2021
 
@@ -2530,7 +2521,7 @@ export class Container
2530
2521
 
2531
2522
  /**
2532
2523
  * IContainer interface that includes experimental features still under development.
2533
- * @alpha
2524
+ * @internal
2534
2525
  */
2535
2526
  export interface IContainerExperimental extends IContainer {
2536
2527
  /**
@@ -2538,16 +2529,12 @@ export interface IContainerExperimental extends IContainer {
2538
2529
  * submission and potential document corruption. The blob returned MUST be deleted if and when this
2539
2530
  * container emits a "connected" event.
2540
2531
  * @returns serialized blob that can be passed to Loader.resolve()
2541
- * @alpha misuse of this API can result in duplicate op submission and potential document corruption
2542
- * {@link https://github.com/microsoft/FluidFramework/blob/main/packages/loader/container-loader/closeAndGetPendingLocalState.md}
2543
2532
  */
2544
2533
  getPendingLocalState?(): Promise<string>;
2545
2534
 
2546
2535
  /**
2547
2536
  * Closes the container and returns serialized local state intended to be
2548
2537
  * given to a newly loaded container.
2549
- * @alpha
2550
- * {@link https://github.com/microsoft/FluidFramework/blob/main/packages/loader/container-loader/closeAndGetPendingLocalState.md}
2551
2538
  */
2552
2539
  closeAndGetPendingLocalState?(stopBlobAttachingSignal?: AbortSignal): Promise<string>;
2553
2540
  }
@@ -106,8 +106,10 @@ export class ContainerStorageAdapter implements IDocumentStorageService, IDispos
106
106
  }
107
107
 
108
108
  private getBlobContents(snapshotTree: ISnapshotTreeWithBlobContents) {
109
- for (const [id, value] of Object.entries(snapshotTree.blobsContents ?? {})) {
110
- this.blobContents[id] = value;
109
+ if (snapshotTree.blobsContents !== undefined) {
110
+ for (const [id, value] of Object.entries(snapshotTree.blobsContents ?? {})) {
111
+ this.blobContents[id] = value;
112
+ }
111
113
  }
112
114
  for (const [_, tree] of Object.entries(snapshotTree.trees)) {
113
115
  this.getBlobContents(tree);
@@ -9,6 +9,7 @@ import {
9
9
  IEventProvider,
10
10
  ITelemetryProperties,
11
11
  ITelemetryErrorEvent,
12
+ type ITelemetryBaseEvent,
12
13
  } from "@fluidframework/core-interfaces";
13
14
  import {
14
15
  ICriticalContainerError,
@@ -22,12 +23,12 @@ import {
22
23
  DataProcessingError,
23
24
  extractSafePropertiesFromMessage,
24
25
  normalizeError,
25
- logIfFalse,
26
26
  safeRaiseEvent,
27
27
  isFluidError,
28
28
  ITelemetryLoggerExt,
29
29
  DataCorruptionError,
30
30
  UsageError,
31
+ type ITelemetryGenericEventExt,
31
32
  } from "@fluidframework/telemetry-utils";
32
33
  import {
33
34
  IDocumentDeltaStorageService,
@@ -114,6 +115,29 @@ function isClientMessage(message: ISequencedDocumentMessage | IDocumentMessage):
114
115
  }
115
116
  }
116
117
 
118
+ /**
119
+ * Like assert, but logs only if the condition is false, rather than throwing
120
+ * @param condition - The condition to attest too
121
+ * @param logger - The logger to log with
122
+ * @param event - The string or event to log
123
+ * @returns The outcome of the condition
124
+ */
125
+ function logIfFalse(
126
+ condition: boolean,
127
+ logger: ITelemetryLoggerExt,
128
+ event: string | ITelemetryGenericEventExt,
129
+ ): condition is true {
130
+ if (condition) {
131
+ return true;
132
+ }
133
+ const newEvent: ITelemetryBaseEvent =
134
+ typeof event === "string"
135
+ ? { eventName: event, category: "error" }
136
+ : { category: "error", ...event };
137
+ logger.send(newEvent);
138
+ return false;
139
+ }
140
+
117
141
  /**
118
142
  * Manages the flow of both inbound and outbound messages. This class ensures that shared objects receive delta
119
143
  * messages in order regardless of possible network conditions or timings causing out of order delivery.
package/src/index.ts CHANGED
@@ -13,7 +13,6 @@ export {
13
13
  ILoaderProps,
14
14
  ILoaderServices,
15
15
  Loader,
16
- requestResolvedObjectFromContainer,
17
16
  } from "./loader";
18
17
  export {
19
18
  isLocationRedirectionError,
package/src/loader.ts CHANGED
@@ -6,7 +6,6 @@
6
6
  import { v4 as uuid } from "uuid";
7
7
  import {
8
8
  ITelemetryLoggerExt,
9
- IConfigProviderBase,
10
9
  mixinMonitoringContext,
11
10
  MonitoringContext,
12
11
  PerformanceEvent,
@@ -17,11 +16,8 @@ import {
17
16
  import {
18
17
  ITelemetryBaseLogger,
19
18
  FluidObject,
20
- // eslint-disable-next-line import/no-deprecated
21
- IFluidRouter,
22
19
  IRequest,
23
- IRequestHeader,
24
- IResponse,
20
+ IConfigProviderBase,
25
21
  } from "@fluidframework/core-interfaces";
26
22
  import {
27
23
  IContainer,
@@ -62,14 +58,6 @@ export class RelativeLoader implements ILoader {
62
58
  private readonly loader: ILoader | undefined,
63
59
  ) {}
64
60
 
65
- /**
66
- * @deprecated Will be removed in future major release. Migrate all usage of IFluidRouter to the Container's IFluidRouter/request.
67
- */
68
- // eslint-disable-next-line import/no-deprecated
69
- public get IFluidRouter(): IFluidRouter {
70
- return this;
71
- }
72
-
73
61
  public async resolve(request: IRequest): Promise<IContainer> {
74
62
  if (request.url.startsWith("/")) {
75
63
  ensureResolvedUrlDefined(this.container.resolvedUrl);
@@ -92,27 +80,11 @@ export class RelativeLoader implements ILoader {
92
80
  }
93
81
  return this.loader.resolve(request);
94
82
  }
95
-
96
- /**
97
- * @deprecated Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
98
- */
99
- public async request(request: IRequest): Promise<IResponse> {
100
- if (request.url.startsWith("/")) {
101
- const container = await this.resolve(request);
102
- return container.request(request);
103
- }
104
-
105
- if (this.loader === undefined) {
106
- return {
107
- status: 404,
108
- value: "Cannot request external containers",
109
- mimeType: "plain/text",
110
- };
111
- }
112
- return this.loader.request(request);
113
- }
114
83
  }
115
84
 
85
+ /**
86
+ * @alpha
87
+ */
116
88
  export interface ILoaderOptions extends ILoaderOptions1 {
117
89
  summarizeProtocolTree?: boolean;
118
90
  }
@@ -122,6 +94,7 @@ export interface ILoaderOptions extends ILoaderOptions1 {
122
94
  * {@link @fluidframework/container-definitions#IFluidModuleWithDetails}
123
95
  * to have all the code loading modules in one package. #8193
124
96
  * Encapsulates a module entry point with corresponding code details.
97
+ * @alpha
125
98
  */
126
99
  export interface IFluidModuleWithDetails {
127
100
  /** Fluid code module that implements the runtime factory needed to instantiate the container runtime. */
@@ -139,6 +112,7 @@ export interface IFluidModuleWithDetails {
139
112
  * to have code loading modules in one package. #8193
140
113
  * Fluid code loader resolves a code module matching the document schema, i.e. code details, such as
141
114
  * a package name and package version range.
115
+ * @alpha
142
116
  */
143
117
  export interface ICodeDetailsLoader extends Partial<IProvideFluidCodeDetailsComparer> {
144
118
  /**
@@ -152,6 +126,7 @@ export interface ICodeDetailsLoader extends Partial<IProvideFluidCodeDetailsComp
152
126
 
153
127
  /**
154
128
  * Services and properties necessary for creating a loader
129
+ * @alpha
155
130
  */
156
131
  export interface ILoaderProps {
157
132
  /**
@@ -208,6 +183,7 @@ export interface ILoaderProps {
208
183
 
209
184
  /**
210
185
  * Services and properties used by and exposed by the loader
186
+ * @alpha
211
187
  */
212
188
  export interface ILoaderServices {
213
189
  /**
@@ -260,6 +236,7 @@ export interface ILoaderServices {
260
236
  /**
261
237
  * Subset of IDocumentStorageService which only supports createBlob() and readBlob(). This is used to support
262
238
  * blobs in detached containers.
239
+ * @alpha
263
240
  */
264
241
  export type IDetachedBlobStorage = Pick<IDocumentStorageService, "createBlob" | "readBlob"> & {
265
242
  size: number;
@@ -269,35 +246,9 @@ export type IDetachedBlobStorage = Pick<IDocumentStorageService, "createBlob" |
269
246
  getBlobIds(): string[];
270
247
  };
271
248
 
272
- /**
273
- * With an already-resolved container, we can request a component directly, without loading the container again
274
- * @param container - a resolved container
275
- * @returns component on the container
276
- * @deprecated Will be removed in future major release. Migrate all usage of IFluidRouter to the "entryPoint" pattern. Refer to Removing-IFluidRouter.md
277
- */
278
- export async function requestResolvedObjectFromContainer(
279
- container: IContainer,
280
- headers?: IRequestHeader,
281
- ): Promise<IResponse> {
282
- ensureResolvedUrlDefined(container.resolvedUrl);
283
- const parsedUrl = tryParseCompatibleResolvedUrl(container.resolvedUrl.url);
284
-
285
- if (parsedUrl === undefined) {
286
- throw new Error(`Invalid URL ${container.resolvedUrl.url}`);
287
- }
288
-
289
- // eslint-disable-next-line import/no-deprecated
290
- const entryPoint: FluidObject<IFluidRouter> | undefined = await container.getEntryPoint?.();
291
- const router = entryPoint?.IFluidRouter ?? container.IFluidRouter;
292
-
293
- return router.request({
294
- url: `${parsedUrl.path}${parsedUrl.query}`,
295
- headers,
296
- });
297
- }
298
-
299
249
  /**
300
250
  * Manages Fluid resource loading
251
+ * @alpha
301
252
  */
302
253
  export class Loader implements IHostLoader {
303
254
  public readonly services: ILoaderServices;
@@ -346,14 +297,6 @@ export class Loader implements IHostLoader {
346
297
  });
347
298
  }
348
299
 
349
- /**
350
- * @deprecated Will be removed in future major release. Migrate all usage of IFluidRouter to the Container's IFluidRouter/request.
351
- */
352
- // eslint-disable-next-line import/no-deprecated
353
- public get IFluidRouter(): IFluidRouter {
354
- return this;
355
- }
356
-
357
300
  public async createDetachedContainer(
358
301
  codeDetails: IFluidCodeDetails,
359
302
  createDetachedProps?: {
@@ -397,23 +340,6 @@ export class Loader implements IHostLoader {
397
340
  });
398
341
  }
399
342
 
400
- /**
401
- * @deprecated Will be removed in future major release. Migrate all usage of IFluidRouter to the Container's IFluidRouter/request.
402
- */
403
- public async request(request: IRequest): Promise<IResponse> {
404
- return PerformanceEvent.timedExecAsync(
405
- this.mc.logger,
406
- { eventName: "Request" },
407
- async () => {
408
- const resolved = await this.resolveCore(request);
409
- return resolved.container.request({
410
- ...request,
411
- url: `${resolved.parsed.path}${resolved.parsed.query}`,
412
- });
413
- },
414
- );
415
- }
416
-
417
343
  private async resolveCore(
418
344
  request: IRequest,
419
345
  pendingLocalState?: IPendingContainerState,