@fluidframework/odsp-client 2.0.0-dev-rc.5.0.0.270401

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 (65) hide show
  1. package/.eslintrc.cjs +23 -0
  2. package/.mocharc.cjs +12 -0
  3. package/CHANGELOG.md +81 -0
  4. package/LICENSE +21 -0
  5. package/README.md +109 -0
  6. package/api-extractor-lint.json +4 -0
  7. package/api-extractor.json +4 -0
  8. package/api-report/odsp-client.alpha.api.md +68 -0
  9. package/api-report/odsp-client.beta.api.md +68 -0
  10. package/api-report/odsp-client.public.api.md +17 -0
  11. package/beta.d.ts +11 -0
  12. package/dist/beta.d.ts +21 -0
  13. package/dist/index.d.ts +18 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +10 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/interfaces.d.ts +102 -0
  18. package/dist/interfaces.d.ts.map +1 -0
  19. package/dist/interfaces.js +7 -0
  20. package/dist/interfaces.js.map +1 -0
  21. package/dist/odspAudience.d.ts +8 -0
  22. package/dist/odspAudience.d.ts.map +1 -0
  23. package/dist/odspAudience.js +20 -0
  24. package/dist/odspAudience.js.map +1 -0
  25. package/dist/odspClient.d.ts +31 -0
  26. package/dist/odspClient.d.ts.map +1 -0
  27. package/dist/odspClient.js +165 -0
  28. package/dist/odspClient.js.map +1 -0
  29. package/dist/package.json +3 -0
  30. package/dist/token.d.ts +35 -0
  31. package/dist/token.d.ts.map +1 -0
  32. package/dist/token.js +7 -0
  33. package/dist/token.js.map +1 -0
  34. package/internal.d.ts +11 -0
  35. package/lib/beta.d.ts +21 -0
  36. package/lib/index.d.ts +18 -0
  37. package/lib/index.d.ts.map +1 -0
  38. package/lib/index.js +6 -0
  39. package/lib/index.js.map +1 -0
  40. package/lib/interfaces.d.ts +102 -0
  41. package/lib/interfaces.d.ts.map +1 -0
  42. package/lib/interfaces.js +6 -0
  43. package/lib/interfaces.js.map +1 -0
  44. package/lib/odspAudience.d.ts +8 -0
  45. package/lib/odspAudience.d.ts.map +1 -0
  46. package/lib/odspAudience.js +16 -0
  47. package/lib/odspAudience.js.map +1 -0
  48. package/lib/odspClient.d.ts +31 -0
  49. package/lib/odspClient.d.ts.map +1 -0
  50. package/lib/odspClient.js +161 -0
  51. package/lib/odspClient.js.map +1 -0
  52. package/lib/token.d.ts +35 -0
  53. package/lib/token.d.ts.map +1 -0
  54. package/lib/token.js +6 -0
  55. package/lib/token.js.map +1 -0
  56. package/lib/tsdoc-metadata.json +11 -0
  57. package/package.json +138 -0
  58. package/prettier.config.cjs +8 -0
  59. package/src/index.ts +25 -0
  60. package/src/interfaces.ts +114 -0
  61. package/src/odspAudience.ts +44 -0
  62. package/src/odspClient.ts +265 -0
  63. package/src/token.ts +37 -0
  64. package/tsconfig.cjs.json +7 -0
  65. package/tsconfig.json +11 -0
@@ -0,0 +1,161 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { AttachState } from "@fluidframework/container-definitions";
6
+ import { Loader } from "@fluidframework/container-loader/internal";
7
+ import { assert } from "@fluidframework/core-utils/internal";
8
+ import { createDOProviderContainerRuntimeFactory, createFluidContainer, createServiceAudience, } from "@fluidframework/fluid-static/internal";
9
+ import { OdspDocumentServiceFactory, OdspDriverUrlResolver, createOdspCreateContainerRequest, createOdspUrl, isOdspResolvedUrl, } from "@fluidframework/odsp-driver/internal";
10
+ import { wrapConfigProviderWithDefaults } from "@fluidframework/telemetry-utils/internal";
11
+ import { v4 as uuid } from "uuid";
12
+ import { createOdspAudienceMember } from "./odspAudience.js";
13
+ async function getStorageToken(options, tokenProvider) {
14
+ const tokenResponse = await tokenProvider.fetchStorageToken(options.siteUrl, options.refresh);
15
+ return tokenResponse;
16
+ }
17
+ async function getWebsocketToken(options, tokenProvider) {
18
+ const tokenResponse = await tokenProvider.fetchWebsocketToken(options.siteUrl, options.refresh);
19
+ return tokenResponse;
20
+ }
21
+ /**
22
+ * Default feature gates.
23
+ * These values will only be used if the feature gate is not already set by the supplied config provider.
24
+ */
25
+ const odspClientFeatureGates = {
26
+ // None yet
27
+ };
28
+ /**
29
+ * Feature gates required to support runtime compatibility when V1 and V2 clients are collaborating
30
+ */
31
+ const odspClientV1CompatFeatureGates = {
32
+ // Disable Garbage Collection
33
+ "Fluid.GarbageCollection.RunSweep": false, // To prevent the GC op
34
+ "Fluid.GarbageCollection.DisableAutoRecovery": true, // To prevent the GC op
35
+ "Fluid.GarbageCollection.ThrowOnTombstoneLoadOverride": false, // For a consistent story of "GC is disabled"
36
+ };
37
+ /**
38
+ * Wrap the config provider to fall back on the appropriate defaults for ODSP Client.
39
+ * @param baseConfigProvider - The base config provider to wrap
40
+ * @returns A new config provider with the appropriate defaults applied underneath the given provider
41
+ */
42
+ function wrapConfigProvider(baseConfigProvider) {
43
+ const defaults = {
44
+ ...odspClientFeatureGates,
45
+ ...odspClientV1CompatFeatureGates,
46
+ };
47
+ return wrapConfigProviderWithDefaults(baseConfigProvider, defaults);
48
+ }
49
+ /**
50
+ * OdspClient provides the ability to have a Fluid object backed by the ODSP service within the context of Microsoft 365 (M365) tenants.
51
+ * @sealed
52
+ * @beta
53
+ */
54
+ export class OdspClient {
55
+ properties;
56
+ documentServiceFactory;
57
+ urlResolver;
58
+ configProvider;
59
+ constructor(properties) {
60
+ this.properties = properties;
61
+ this.documentServiceFactory = new OdspDocumentServiceFactory(async (options) => getStorageToken(options, this.properties.connection.tokenProvider), async (options) => getWebsocketToken(options, this.properties.connection.tokenProvider));
62
+ this.urlResolver = new OdspDriverUrlResolver();
63
+ this.configProvider = wrapConfigProvider(properties.configProvider);
64
+ }
65
+ async createContainer(containerSchema) {
66
+ const loader = this.createLoader(containerSchema);
67
+ const container = await loader.createDetachedContainer({
68
+ package: "no-dynamic-package",
69
+ config: {},
70
+ });
71
+ const fluidContainer = await this.createFluidContainer(container, this.properties.connection);
72
+ const services = await this.getContainerServices(container);
73
+ return { container: fluidContainer, services };
74
+ }
75
+ async getContainer(id, containerSchema) {
76
+ const loader = this.createLoader(containerSchema);
77
+ const url = createOdspUrl({
78
+ siteUrl: this.properties.connection.siteUrl,
79
+ driveId: this.properties.connection.driveId,
80
+ itemId: id,
81
+ dataStorePath: "",
82
+ });
83
+ const container = await loader.resolve({ url });
84
+ const fluidContainer = createFluidContainer({
85
+ container,
86
+ rootDataObject: await this.getContainerEntryPoint(container),
87
+ });
88
+ const services = await this.getContainerServices(container);
89
+ return { container: fluidContainer, services };
90
+ }
91
+ createLoader(schema) {
92
+ const runtimeFactory = createDOProviderContainerRuntimeFactory({
93
+ schema,
94
+ compatibilityMode: "2",
95
+ });
96
+ const load = async () => {
97
+ return {
98
+ module: { fluidExport: runtimeFactory },
99
+ details: { package: "no-dynamic-package", config: {} },
100
+ };
101
+ };
102
+ const codeLoader = { load };
103
+ const client = {
104
+ details: {
105
+ capabilities: { interactive: true },
106
+ },
107
+ permission: [],
108
+ scopes: [],
109
+ user: { id: "" },
110
+ mode: "write",
111
+ };
112
+ return new Loader({
113
+ urlResolver: this.urlResolver,
114
+ documentServiceFactory: this.documentServiceFactory,
115
+ codeLoader,
116
+ logger: this.properties.logger,
117
+ options: { client },
118
+ configProvider: this.configProvider,
119
+ });
120
+ }
121
+ async createFluidContainer(container, connection) {
122
+ const rootDataObject = await this.getContainerEntryPoint(container);
123
+ /**
124
+ * See {@link FluidContainer.attach}
125
+ */
126
+ const attach = async (odspProps) => {
127
+ const createNewRequest = createOdspCreateContainerRequest(connection.siteUrl, connection.driveId, odspProps?.filePath ?? "", odspProps?.fileName ?? uuid());
128
+ if (container.attachState !== AttachState.Detached) {
129
+ throw new Error("Cannot attach container. Container is not in detached state");
130
+ }
131
+ await container.attach(createNewRequest);
132
+ const resolvedUrl = container.resolvedUrl;
133
+ if (resolvedUrl === undefined || !isOdspResolvedUrl(resolvedUrl)) {
134
+ throw new Error("Resolved Url not available on attached container");
135
+ }
136
+ /**
137
+ * A unique identifier for the file within the provided SharePoint Embedded container ID. When you attach a container,
138
+ * a new `itemId` is created in the user's drive, which developers can use for various operations
139
+ * like updating, renaming, moving the Fluid file, changing permissions, and more. `itemId` is used to load the container.
140
+ */
141
+ return resolvedUrl.itemId;
142
+ };
143
+ const fluidContainer = createFluidContainer({ container, rootDataObject });
144
+ fluidContainer.attach = attach;
145
+ return fluidContainer;
146
+ }
147
+ async getContainerServices(container) {
148
+ return {
149
+ audience: createServiceAudience({
150
+ container,
151
+ createServiceMember: createOdspAudienceMember,
152
+ }),
153
+ };
154
+ }
155
+ async getContainerEntryPoint(container) {
156
+ const rootDataObject = await container.getEntryPoint();
157
+ assert(rootDataObject.IRootDataObject !== undefined, 0x878 /* entryPoint must be of type IRootDataObject */);
158
+ return rootDataObject.IRootDataObject;
159
+ }
160
+ }
161
+ //# sourceMappingURL=odspClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"odspClient.js","sourceRoot":"","sources":["../src/odspClient.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 { AttachState } from \"@fluidframework/container-definitions\";\nimport {\n\tIContainer,\n\tIFluidModuleWithDetails,\n} from \"@fluidframework/container-definitions/internal\";\nimport { Loader } from \"@fluidframework/container-loader/internal\";\nimport {\n\ttype FluidObject,\n\ttype IConfigProviderBase,\n\ttype IRequest,\n} from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { IClient } from \"@fluidframework/driver-definitions\";\nimport { IDocumentServiceFactory } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tContainerAttachProps,\n\ttype ContainerSchema,\n\tIFluidContainer,\n} from \"@fluidframework/fluid-static\";\nimport {\n\tIRootDataObject,\n\tcreateDOProviderContainerRuntimeFactory,\n\tcreateFluidContainer,\n\tcreateServiceAudience,\n} from \"@fluidframework/fluid-static/internal\";\nimport {\n\tOdspDocumentServiceFactory,\n\tOdspDriverUrlResolver,\n\tcreateOdspCreateContainerRequest,\n\tcreateOdspUrl,\n\tisOdspResolvedUrl,\n} from \"@fluidframework/odsp-driver/internal\";\nimport type {\n\tOdspResourceTokenFetchOptions,\n\tTokenResponse,\n} from \"@fluidframework/odsp-driver-definitions/internal\";\nimport { wrapConfigProviderWithDefaults } from \"@fluidframework/telemetry-utils/internal\";\nimport { v4 as uuid } from \"uuid\";\n\nimport {\n\tOdspClientProps,\n\tOdspConnectionConfig,\n\tOdspContainerAttachProps,\n\tOdspContainerServices,\n} from \"./interfaces.js\";\nimport { createOdspAudienceMember } from \"./odspAudience.js\";\nimport { type IOdspTokenProvider } from \"./token.js\";\n\nasync function getStorageToken(\n\toptions: OdspResourceTokenFetchOptions,\n\ttokenProvider: IOdspTokenProvider,\n): Promise<TokenResponse> {\n\tconst tokenResponse: TokenResponse = await tokenProvider.fetchStorageToken(\n\t\toptions.siteUrl,\n\t\toptions.refresh,\n\t);\n\treturn tokenResponse;\n}\n\nasync function getWebsocketToken(\n\toptions: OdspResourceTokenFetchOptions,\n\ttokenProvider: IOdspTokenProvider,\n): Promise<TokenResponse> {\n\tconst tokenResponse: TokenResponse = await tokenProvider.fetchWebsocketToken(\n\t\toptions.siteUrl,\n\t\toptions.refresh,\n\t);\n\treturn tokenResponse;\n}\n\n/**\n * Default feature gates.\n * These values will only be used if the feature gate is not already set by the supplied config provider.\n */\nconst odspClientFeatureGates = {\n\t// None yet\n};\n\n/**\n * Feature gates required to support runtime compatibility when V1 and V2 clients are collaborating\n */\nconst odspClientV1CompatFeatureGates = {\n\t// Disable Garbage Collection\n\t\"Fluid.GarbageCollection.RunSweep\": false, // To prevent the GC op\n\t\"Fluid.GarbageCollection.DisableAutoRecovery\": true, // To prevent the GC op\n\t\"Fluid.GarbageCollection.ThrowOnTombstoneLoadOverride\": false, // For a consistent story of \"GC is disabled\"\n};\n\n/**\n * Wrap the config provider to fall back on the appropriate defaults for ODSP Client.\n * @param baseConfigProvider - The base config provider to wrap\n * @returns A new config provider with the appropriate defaults applied underneath the given provider\n */\nfunction wrapConfigProvider(baseConfigProvider?: IConfigProviderBase): IConfigProviderBase {\n\tconst defaults = {\n\t\t...odspClientFeatureGates,\n\t\t...odspClientV1CompatFeatureGates,\n\t};\n\treturn wrapConfigProviderWithDefaults(baseConfigProvider, defaults);\n}\n\n/**\n * OdspClient provides the ability to have a Fluid object backed by the ODSP service within the context of Microsoft 365 (M365) tenants.\n * @sealed\n * @beta\n */\nexport class OdspClient {\n\tprivate readonly documentServiceFactory: IDocumentServiceFactory;\n\tprivate readonly urlResolver: OdspDriverUrlResolver;\n\tprivate readonly configProvider: IConfigProviderBase | undefined;\n\n\tpublic constructor(private readonly properties: OdspClientProps) {\n\t\tthis.documentServiceFactory = new OdspDocumentServiceFactory(\n\t\t\tasync (options) => getStorageToken(options, this.properties.connection.tokenProvider),\n\t\t\tasync (options) => getWebsocketToken(options, this.properties.connection.tokenProvider),\n\t\t);\n\n\t\tthis.urlResolver = new OdspDriverUrlResolver();\n\t\tthis.configProvider = wrapConfigProvider(properties.configProvider);\n\t}\n\n\tpublic async createContainer<T extends ContainerSchema>(\n\t\tcontainerSchema: T,\n\t): Promise<{\n\t\tcontainer: IFluidContainer<T>;\n\t\tservices: OdspContainerServices;\n\t}> {\n\t\tconst loader = this.createLoader(containerSchema);\n\n\t\tconst container = await loader.createDetachedContainer({\n\t\t\tpackage: \"no-dynamic-package\",\n\t\t\tconfig: {},\n\t\t});\n\n\t\tconst fluidContainer = await this.createFluidContainer(\n\t\t\tcontainer,\n\t\t\tthis.properties.connection,\n\t\t);\n\n\t\tconst services = await this.getContainerServices(container);\n\n\t\treturn { container: fluidContainer as IFluidContainer<T>, services };\n\t}\n\n\tpublic async getContainer<T extends ContainerSchema>(\n\t\tid: string,\n\t\tcontainerSchema: T,\n\t): Promise<{\n\t\tcontainer: IFluidContainer<T>;\n\t\tservices: OdspContainerServices;\n\t}> {\n\t\tconst loader = this.createLoader(containerSchema);\n\t\tconst url = createOdspUrl({\n\t\t\tsiteUrl: this.properties.connection.siteUrl,\n\t\t\tdriveId: this.properties.connection.driveId,\n\t\t\titemId: id,\n\t\t\tdataStorePath: \"\",\n\t\t});\n\t\tconst container = await loader.resolve({ url });\n\n\t\tconst fluidContainer = createFluidContainer({\n\t\t\tcontainer,\n\t\t\trootDataObject: await this.getContainerEntryPoint(container),\n\t\t});\n\t\tconst services = await this.getContainerServices(container);\n\t\treturn { container: fluidContainer as IFluidContainer<T>, services };\n\t}\n\n\tprivate createLoader(schema: ContainerSchema): Loader {\n\t\tconst runtimeFactory = createDOProviderContainerRuntimeFactory({\n\t\t\tschema,\n\t\t\tcompatibilityMode: \"2\",\n\t\t});\n\t\tconst load = async (): Promise<IFluidModuleWithDetails> => {\n\t\t\treturn {\n\t\t\t\tmodule: { fluidExport: runtimeFactory },\n\t\t\t\tdetails: { package: \"no-dynamic-package\", config: {} },\n\t\t\t};\n\t\t};\n\n\t\tconst codeLoader = { load };\n\t\tconst client: IClient = {\n\t\t\tdetails: {\n\t\t\t\tcapabilities: { interactive: true },\n\t\t\t},\n\t\t\tpermission: [],\n\t\t\tscopes: [],\n\t\t\tuser: { id: \"\" },\n\t\t\tmode: \"write\",\n\t\t};\n\n\t\treturn new Loader({\n\t\t\turlResolver: this.urlResolver,\n\t\t\tdocumentServiceFactory: this.documentServiceFactory,\n\t\t\tcodeLoader,\n\t\t\tlogger: this.properties.logger,\n\t\t\toptions: { client },\n\t\t\tconfigProvider: this.configProvider,\n\t\t});\n\t}\n\n\tprivate async createFluidContainer(\n\t\tcontainer: IContainer,\n\t\tconnection: OdspConnectionConfig,\n\t): Promise<IFluidContainer> {\n\t\tconst rootDataObject = await this.getContainerEntryPoint(container);\n\n\t\t/**\n\t\t * See {@link FluidContainer.attach}\n\t\t */\n\t\tconst attach = async (\n\t\t\todspProps?: ContainerAttachProps<OdspContainerAttachProps>,\n\t\t): Promise<string> => {\n\t\t\tconst createNewRequest: IRequest = createOdspCreateContainerRequest(\n\t\t\t\tconnection.siteUrl,\n\t\t\t\tconnection.driveId,\n\t\t\t\todspProps?.filePath ?? \"\",\n\t\t\t\todspProps?.fileName ?? uuid(),\n\t\t\t);\n\t\t\tif (container.attachState !== AttachState.Detached) {\n\t\t\t\tthrow new Error(\"Cannot attach container. Container is not in detached state\");\n\t\t\t}\n\t\t\tawait container.attach(createNewRequest);\n\n\t\t\tconst resolvedUrl = container.resolvedUrl;\n\n\t\t\tif (resolvedUrl === undefined || !isOdspResolvedUrl(resolvedUrl)) {\n\t\t\t\tthrow new Error(\"Resolved Url not available on attached container\");\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * A unique identifier for the file within the provided SharePoint Embedded container ID. When you attach a container,\n\t\t\t * a new `itemId` is created in the user's drive, which developers can use for various operations\n\t\t\t * like updating, renaming, moving the Fluid file, changing permissions, and more. `itemId` is used to load the container.\n\t\t\t */\n\t\t\treturn resolvedUrl.itemId;\n\t\t};\n\t\tconst fluidContainer = createFluidContainer({ container, rootDataObject });\n\t\tfluidContainer.attach = attach;\n\t\treturn fluidContainer;\n\t}\n\n\tprivate async getContainerServices(container: IContainer): Promise<OdspContainerServices> {\n\t\treturn {\n\t\t\taudience: createServiceAudience({\n\t\t\t\tcontainer,\n\t\t\t\tcreateServiceMember: createOdspAudienceMember,\n\t\t\t}),\n\t\t};\n\t}\n\n\tprivate async getContainerEntryPoint(container: IContainer): Promise<IRootDataObject> {\n\t\tconst rootDataObject: FluidObject<IRootDataObject> = await container.getEntryPoint();\n\t\tassert(\n\t\t\trootDataObject.IRootDataObject !== undefined,\n\t\t\t0x878 /* entryPoint must be of type IRootDataObject */,\n\t\t);\n\t\treturn rootDataObject.IRootDataObject;\n\t}\n}\n"]}
package/lib/token.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { TokenResponse } from "@fluidframework/odsp-driver-definitions/internal";
6
+ /**
7
+ * Abstracts the token fetching mechanism for a hosting application.
8
+ * The hosting application is responsible for providing an implementation.
9
+ * @beta
10
+ */
11
+ export interface IOdspTokenProvider {
12
+ /**
13
+ * Fetches the orderer token from host.
14
+ *
15
+ * @param siteUrl - Site url representing ODSP resource location. It points to the specific SharePoint site where you can store and access the containers you create.
16
+ * @param refresh - Optional flag indicating whether token fetch must bypass local cache.
17
+ * This likely indicates that some previous request failed authorization due to an expired token,
18
+ * and so a fresh token is required.
19
+ *
20
+ * Default: `false`.
21
+ */
22
+ fetchWebsocketToken(siteUrl: string, refresh: boolean): Promise<TokenResponse>;
23
+ /**
24
+ * Fetches the storage token from host.
25
+ *
26
+ * @param siteUrl - Site url representing ODSP resource location. It points to the specific SharePoint site where you can store and access the containers you create.
27
+ * @param refresh - Optional flag indicating whether token fetch must bypass local cache.
28
+ * This likely indicates that some previous request failed authorization due to an expired token,
29
+ * and so a fresh token is required.
30
+ *
31
+ * Default: `false`.
32
+ */
33
+ fetchStorageToken(siteUrl: string, refresh: boolean): Promise<TokenResponse>;
34
+ }
35
+ //# sourceMappingURL=token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,kDAAkD,CAAC;AAEjF;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IAClC;;;;;;;;;OASG;IACH,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAE/E;;;;;;;;;OASG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CAC7E"}
package/lib/token.js ADDED
@@ -0,0 +1,6 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TokenResponse } from \"@fluidframework/odsp-driver-definitions/internal\";\n\n/**\n * Abstracts the token fetching mechanism for a hosting application.\n * The hosting application is responsible for providing an implementation.\n * @beta\n */\nexport interface IOdspTokenProvider {\n\t/**\n\t * Fetches the orderer token from host.\n\t *\n\t * @param siteUrl - Site url representing ODSP resource location. It points to the specific SharePoint site where you can store and access the containers you create.\n\t * @param refresh - Optional flag indicating whether token fetch must bypass local cache.\n\t * This likely indicates that some previous request failed authorization due to an expired token,\n\t * and so a fresh token is required.\n\t *\n\t * Default: `false`.\n\t */\n\tfetchWebsocketToken(siteUrl: string, refresh: boolean): Promise<TokenResponse>;\n\n\t/**\n\t * Fetches the storage token from host.\n\t *\n\t * @param siteUrl - Site url representing ODSP resource location. It points to the specific SharePoint site where you can store and access the containers you create.\n\t * @param refresh - Optional flag indicating whether token fetch must bypass local cache.\n\t * This likely indicates that some previous request failed authorization due to an expired token,\n\t * and so a fresh token is required.\n\t *\n\t * Default: `false`.\n\t */\n\tfetchStorageToken(siteUrl: string, refresh: boolean): Promise<TokenResponse>;\n}\n"]}
@@ -0,0 +1,11 @@
1
+ // This file is read by tools that parse documentation comments conforming to the TSDoc standard.
2
+ // It should be published with your NPM package. It should not be tracked by Git.
3
+ {
4
+ "tsdocVersion": "0.12",
5
+ "toolPackages": [
6
+ {
7
+ "packageName": "@microsoft/api-extractor",
8
+ "packageVersion": "7.45.1"
9
+ }
10
+ ]
11
+ }
package/package.json ADDED
@@ -0,0 +1,138 @@
1
+ {
2
+ "name": "@fluidframework/odsp-client",
3
+ "version": "2.0.0-dev-rc.5.0.0.270401",
4
+ "description": "A tool to enable creation and loading of Fluid containers using the ODSP service",
5
+ "homepage": "https://fluidframework.com",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/microsoft/FluidFramework.git",
9
+ "directory": "packages/service-clients/odsp-client"
10
+ },
11
+ "license": "MIT",
12
+ "author": "Microsoft and contributors",
13
+ "sideEffects": false,
14
+ "type": "module",
15
+ "exports": {
16
+ ".": {
17
+ "import": {
18
+ "types": "./lib/index.d.ts",
19
+ "default": "./lib/index.js"
20
+ },
21
+ "require": {
22
+ "types": "./dist/index.d.ts",
23
+ "default": "./dist/index.js"
24
+ }
25
+ },
26
+ "./beta": {
27
+ "import": {
28
+ "types": "./lib/beta.d.ts",
29
+ "default": "./lib/index.js"
30
+ },
31
+ "require": {
32
+ "types": "./dist/beta.d.ts",
33
+ "default": "./dist/index.js"
34
+ }
35
+ },
36
+ "./internal": {
37
+ "import": {
38
+ "types": "./lib/index.d.ts",
39
+ "default": "./lib/index.js"
40
+ },
41
+ "require": {
42
+ "types": "./dist/index.d.ts",
43
+ "default": "./dist/index.js"
44
+ }
45
+ }
46
+ },
47
+ "main": "lib/index.js",
48
+ "types": "lib/index.d.ts",
49
+ "c8": {
50
+ "all": true,
51
+ "cache-dir": "nyc/.cache",
52
+ "exclude": [
53
+ "src/test/**/*.*ts",
54
+ "dist/test/**/*.*js"
55
+ ],
56
+ "exclude-after-remap": false,
57
+ "include": [
58
+ "src/**/*.*ts",
59
+ "dist/**/*.*js"
60
+ ],
61
+ "report-dir": "nyc/report",
62
+ "reporter": [
63
+ "cobertura",
64
+ "html",
65
+ "text"
66
+ ],
67
+ "temp-directory": "nyc/.nyc_output"
68
+ },
69
+ "dependencies": {
70
+ "@fluidframework/container-definitions": "2.0.0-dev-rc.5.0.0.270401",
71
+ "@fluidframework/container-loader": "2.0.0-dev-rc.5.0.0.270401",
72
+ "@fluidframework/core-interfaces": "2.0.0-dev-rc.5.0.0.270401",
73
+ "@fluidframework/core-utils": "2.0.0-dev-rc.5.0.0.270401",
74
+ "@fluidframework/driver-definitions": "2.0.0-dev-rc.5.0.0.270401",
75
+ "@fluidframework/fluid-static": "2.0.0-dev-rc.5.0.0.270401",
76
+ "@fluidframework/map": "2.0.0-dev-rc.5.0.0.270401",
77
+ "@fluidframework/odsp-doclib-utils": "2.0.0-dev-rc.5.0.0.270401",
78
+ "@fluidframework/odsp-driver": "2.0.0-dev-rc.5.0.0.270401",
79
+ "@fluidframework/odsp-driver-definitions": "2.0.0-dev-rc.5.0.0.270401",
80
+ "@fluidframework/telemetry-utils": "2.0.0-dev-rc.5.0.0.270401",
81
+ "uuid": "^9.0.0"
82
+ },
83
+ "devDependencies": {
84
+ "@arethetypeswrong/cli": "^0.15.2",
85
+ "@biomejs/biome": "^1.7.3",
86
+ "@fluid-internal/mocha-test-setup": "2.0.0-dev-rc.5.0.0.270401",
87
+ "@fluid-tools/build-cli": "^0.39.0-264124",
88
+ "@fluidframework/build-common": "^2.0.3",
89
+ "@fluidframework/build-tools": "^0.39.0-264124",
90
+ "@fluidframework/eslint-config-fluid": "^5.3.0",
91
+ "@fluidframework/test-utils": "2.0.0-dev-rc.5.0.0.270401",
92
+ "@microsoft/api-extractor": "^7.45.1",
93
+ "@types/mocha": "^9.1.1",
94
+ "@types/node": "^18.19.0",
95
+ "@types/uuid": "^9.0.2",
96
+ "c8": "^8.0.1",
97
+ "copyfiles": "^2.4.1",
98
+ "cross-env": "^7.0.3",
99
+ "eslint": "~8.55.0",
100
+ "mocha": "^10.2.0",
101
+ "prettier": "~3.0.3",
102
+ "rimraf": "^4.4.0",
103
+ "typescript": "~5.4.5"
104
+ },
105
+ "typeValidation": {
106
+ "disabled": true,
107
+ "broken": {}
108
+ },
109
+ "scripts": {
110
+ "api": "fluid-build . --task api",
111
+ "api-extractor:commonjs": "flub generate entrypoints --outFileAlpha legacy --outDir ./dist",
112
+ "api-extractor:esnext": "flub generate entrypoints --outFileAlpha legacy --outDir ./lib --node10TypeCompat",
113
+ "build": "fluid-build . --task build",
114
+ "build:commonjs": "fluid-build . --task commonjs",
115
+ "build:compile": "fluid-build . --task compile",
116
+ "build:docs": "api-extractor run --local",
117
+ "build:esnext": "tsc --project ./tsconfig.json",
118
+ "build:test": "npm run build:test:esm && npm run build:test:cjs",
119
+ "build:test:cjs": "fluid-tsc commonjs --project ./src/test/tsconfig.cjs.json",
120
+ "build:test:esm": "tsc --project ./src/test/tsconfig.json",
121
+ "check:are-the-types-wrong": "attw --pack .",
122
+ "check:prettier": "prettier --check . --cache --ignore-path ../../../.prettierignore",
123
+ "check:release-tags": "api-extractor run --local --config ./api-extractor-lint.json",
124
+ "ci:build:docs": "api-extractor run",
125
+ "clean": "rimraf --glob dist lib \"*.d.ts\" \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
126
+ "eslint": "eslint --format stylish src",
127
+ "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
128
+ "format": "fluid-build --task format .",
129
+ "format:prettier": "prettier --write . --cache --ignore-path ../../../.prettierignore",
130
+ "lint": "fluid-build . --task lint",
131
+ "lint:fix": "fluid-build . --task eslint:fix --task format",
132
+ "test": "npm run test:mocha",
133
+ "test:mocha": "npm run test:mocha:esm && echo skipping cjs to avoid overhead - npm run test:mocha:cjs",
134
+ "test:mocha:cjs": "mocha --recursive \"dist/test/**/*.spec.*js\" --exit --timeout 10000",
135
+ "test:mocha:esm": "mocha --recursive \"lib/test/**/*.spec.*js\" --exit --timeout 10000",
136
+ "tsc": "fluid-tsc commonjs --project ./tsconfig.cjs.json && copyfiles -f ../../../common/build/build-common/src/cjs/package.json ./dist"
137
+ }
138
+ }
@@ -0,0 +1,8 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ module.exports = {
7
+ ...require("@fluidframework/build-common/prettier.config.cjs"),
8
+ };
package/src/index.ts ADDED
@@ -0,0 +1,25 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ /**
7
+ * The odsp-client package provides a simple and powerful way to consume collaborative Fluid data with OneDrive/SharePoint (ODSP) storage.
8
+ *
9
+ * @remarks
10
+ * Please note that odsp-client is currently an experimental package.
11
+ * We'd love for you to try it out and provide feedback but it is not yet recommended or supported for production scenarios.
12
+ *
13
+ * @packageDocumentation
14
+ */
15
+
16
+ export { type TokenResponse } from "@fluidframework/odsp-driver-definitions/internal";
17
+ export type {
18
+ OdspConnectionConfig,
19
+ OdspClientProps,
20
+ OdspContainerServices,
21
+ IOdspAudience,
22
+ OdspMember,
23
+ } from "./interfaces.js";
24
+ export { OdspClient } from "./odspClient.js";
25
+ export { type IOdspTokenProvider } from "./token.js";
@@ -0,0 +1,114 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { type ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
7
+ import { IConfigProviderBase } from "@fluidframework/core-interfaces";
8
+ import type { IMember, IServiceAudience } from "@fluidframework/fluid-static";
9
+
10
+ import { IOdspTokenProvider } from "./token.js";
11
+
12
+ /**
13
+ * Defines the necessary properties that will be applied to all containers
14
+ * created by an OdspClient instance. This includes callbacks for the authentication tokens
15
+ * required for ODSP.
16
+ * @beta
17
+ */
18
+ export interface OdspConnectionConfig {
19
+ /**
20
+ * Instance that provides AAD endpoint tokens for Push and SharePoint
21
+ */
22
+ tokenProvider: IOdspTokenProvider;
23
+
24
+ /**
25
+ * Site url representing ODSP resource location. It points to the specific SharePoint site where you can store and access the containers you create.
26
+ */
27
+ siteUrl: string;
28
+
29
+ /**
30
+ * SharePoint Embedded Container Id of the tenant where Fluid containers are created
31
+ */
32
+ driveId: string;
33
+
34
+ /**
35
+ * Specifies the file path where Fluid files are created. If passed an empty string, the Fluid files will be created at the root level.
36
+ */
37
+ filePath: string;
38
+ }
39
+ /**
40
+ * @beta
41
+ */
42
+ export interface OdspClientProps {
43
+ /**
44
+ * Configuration for establishing a connection with the ODSP Fluid Service (Push).
45
+ */
46
+ readonly connection: OdspConnectionConfig;
47
+
48
+ /**
49
+ * Optional. A logger instance to receive diagnostic messages.
50
+ */
51
+ readonly logger?: ITelemetryBaseLogger;
52
+
53
+ /**
54
+ * Base interface for providing configurations to control experimental features. If unsure, leave this undefined.
55
+ */
56
+ readonly configProvider?: IConfigProviderBase;
57
+ }
58
+
59
+ /**
60
+ * @alpha
61
+ */
62
+ export interface OdspContainerAttachProps {
63
+ /**
64
+ * The file path where Fluid containers are created. If undefined, the file is created at the root.
65
+ */
66
+ filePath: string | undefined;
67
+
68
+ /**
69
+ * The file name of the Fluid file. If undefined, the file is named with a GUID.
70
+ */
71
+ fileName: string | undefined;
72
+ }
73
+
74
+ /**
75
+ * OdspContainerServices is returned by the OdspClient alongside a FluidContainer. It holds the
76
+ * functionality specifically tied to the ODSP service, and how the data stored in the
77
+ * FluidContainer is persisted in the backend and consumed by users. Any functionality regarding
78
+ * how the data is handled within the FluidContainer itself, i.e. which data objects or DDSes to
79
+ * use, will not be included here but rather on the FluidContainer class itself.
80
+ * @beta
81
+ */
82
+ export interface OdspContainerServices {
83
+ /**
84
+ * Provides an object that facilitates obtaining information about users present in the Fluid session, as well as listeners for roster changes triggered by users joining or leaving the session.
85
+ */
86
+ audience: IOdspAudience;
87
+ }
88
+
89
+ /**
90
+ * Since ODSP provides user names and email for all of its members, we extend the
91
+ * {@link @fluidframework/fluid-static#IMember} interface to include this service-specific value.
92
+ * It will be returned for all audience members connected.
93
+ * @beta
94
+ */
95
+ export interface OdspMember extends IMember {
96
+ /**
97
+ * The object ID (oid) for the user, unique among each individual user connecting to the session.
98
+ */
99
+ id: string;
100
+ /**
101
+ * The user's name
102
+ */
103
+ name: string;
104
+ /**
105
+ * The user's email
106
+ */
107
+ email: string;
108
+ }
109
+
110
+ /**
111
+ * Audience object for ODSP containers
112
+ * @beta
113
+ */
114
+ export type IOdspAudience = IServiceAudience<OdspMember>;
@@ -0,0 +1,44 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import { assert } from "@fluidframework/core-utils/internal";
7
+ import { type IClient } from "@fluidframework/driver-definitions";
8
+
9
+ import { type OdspMember } from "./interfaces.js";
10
+
11
+ /**
12
+ * Since ODSP provides user names, email and oids for all of its members, we extend the
13
+ * {@link @fluidframework/fluid-static#IMember} interface to include this service-specific value.
14
+ * @internal
15
+ */
16
+ interface OdspUser {
17
+ /**
18
+ * The user's email address
19
+ */
20
+ email: string;
21
+ /**
22
+ * The user's name
23
+ */
24
+ name: string;
25
+ /**
26
+ * The object ID (oid). It is a unique identifier assigned to each user, group, or other entity within AAD or another Microsoft 365 service. It is a GUID that uniquely identifies the object. When making Microsoft Graph API calls, you might need to reference or manipulate objects within the directory, and the `oid` is used to identify these objects.
27
+ */
28
+ oid: string;
29
+ }
30
+
31
+ export function createOdspAudienceMember(audienceMember: IClient): OdspMember {
32
+ const user = audienceMember.user as unknown as OdspUser;
33
+ assert(
34
+ user.name !== undefined || user.email !== undefined || user.oid !== undefined,
35
+ 0x836 /* Provided user was not an "OdspUser". */,
36
+ );
37
+
38
+ return {
39
+ id: user.oid,
40
+ name: user.name,
41
+ email: user.email,
42
+ connections: [],
43
+ };
44
+ }