@fluidframework/azure-client 0.52.0 → 0.54.0-47413

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc.js CHANGED
@@ -10,4 +10,5 @@ module.exports = {
10
10
  "parserOptions": {
11
11
  "project": ["./tsconfig.json", "./src/test/tsconfig.json"]
12
12
  },
13
+ "rules": {}
13
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AzureClient.d.ts","sourceRoot":"","sources":["../src/AzureClient.ts"],"names":[],"mappings":"AAYA,OAAO,EACH,eAAe,EAGf,eAAe,EAElB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACH,gBAAgB,EAChB,sBAAsB,EACzB,MAAM,cAAc,CAAC;AAItB;;GAEG;AACH,eAAO,MAAM,oBAAoB,UAAU,CAAC;AAE5C;;;GAGG;AACH,qBAAa,WAAW;IAQR,OAAO,CAAC,QAAQ,CAAC,KAAK;IAPlC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA0B;IACjE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAe;IAE3C;;;OAGG;gBAC0B,KAAK,EAAE,gBAAgB;IAepD;;;;OAIG;IACU,eAAe,CACxB,eAAe,EAAE,eAAe,GACjC,OAAO,CAAC;QAAE,SAAS,EAAE,eAAe,CAAC;QAAC,QAAQ,EAAE,sBAAsB,CAAA;KAAE,CAAC;IA2B5E;;;;;OAKG;IACU,YAAY,CACrB,EAAE,EAAE,MAAM,EACV,eAAe,EAAE,eAAe,GACjC,OAAO,CAAC;QAAE,SAAS,EAAE,eAAe,CAAC;QAAC,QAAQ,EAAE,sBAAsB,CAAA;KAAE,CAAC;IAS5E,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,YAAY;CAgBvB"}
1
+ {"version":3,"file":"AzureClient.d.ts","sourceRoot":"","sources":["../src/AzureClient.ts"],"names":[],"mappings":"AAaA,OAAO,EACH,eAAe,EAGf,eAAe,EAElB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAOxE;;GAEG;AACH,eAAO,MAAM,oBAAoB,UAAU,CAAC;AAE5C;;;GAGG;AACH,qBAAa,WAAW;IAQR,OAAO,CAAC,QAAQ,CAAC,KAAK;IAPlC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA0B;IACjE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAe;IAE3C;;;OAGG;gBAC0B,KAAK,EAAE,gBAAgB;IAYpD;;;;OAIG;IACU,eAAe,CACxB,eAAe,EAAE,eAAe,GACjC,OAAO,CAAC;QACP,SAAS,EAAE,eAAe,CAAC;QAC3B,QAAQ,EAAE,sBAAsB,CAAC;KACpC,CAAC;IAmCF;;;;;OAKG;IACU,YAAY,CACrB,EAAE,EAAE,MAAM,EACV,eAAe,EAAE,eAAe,GACjC,OAAO,CAAC;QACP,SAAS,EAAE,eAAe,CAAC;QAC3B,QAAQ,EAAE,sBAAsB,CAAC;KACpC,CAAC;IAgBF,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,YAAY;CAcvB"}
@@ -28,7 +28,7 @@ class AzureClient {
28
28
  */
29
29
  constructor(props) {
30
30
  this.props = props;
31
- this.urlResolver = new AzureUrlResolver_1.AzureUrlResolver(this.props.connection.tenantId, this.props.connection.orderer, this.props.connection.storage);
31
+ this.urlResolver = new AzureUrlResolver_1.AzureUrlResolver();
32
32
  // The local service implementation differs from the Azure Fluid Relay in blob
33
33
  // storage format. Azure Fluid Relay supports whole summary upload. Local currently does not.
34
34
  const enableWholeSummaryUpload = this.props.connection.tenantId !== exports.LOCAL_MODE_TENANT_ID;
@@ -46,13 +46,13 @@ class AzureClient {
46
46
  config: {},
47
47
  });
48
48
  const rootDataObject = await runtime_utils_1.requestFluidObject(container, "/");
49
+ const createNewRequest = AzureUrlResolver_1.createAzureCreateNewRequest(this.props.connection.orderer, this.props.connection.storage, this.props.connection.tenantId);
49
50
  const fluidContainer = new (class extends fluid_static_1.FluidContainer {
50
51
  async attach() {
51
52
  if (this.attachState !== container_definitions_1.AttachState.Detached) {
52
53
  throw new Error("Cannot attach container. Container is not in detached state");
53
54
  }
54
- const request = AzureUrlResolver_1.createAzureCreateNewRequest();
55
- await container.attach(request);
55
+ await container.attach(createNewRequest);
56
56
  const resolved = container.resolvedUrl;
57
57
  driver_utils_1.ensureFluidResolvedUrl(resolved);
58
58
  return resolved.id;
@@ -69,7 +69,11 @@ class AzureClient {
69
69
  */
70
70
  async getContainer(id, containerSchema) {
71
71
  const loader = this.createLoader(containerSchema);
72
- const container = await loader.resolve({ url: id });
72
+ const url = new URL(this.props.connection.orderer);
73
+ url.searchParams.append("storage", encodeURIComponent(this.props.connection.storage));
74
+ url.searchParams.append("tenantId", encodeURIComponent(this.props.connection.tenantId));
75
+ url.searchParams.append("containerId", encodeURIComponent(id));
76
+ const container = await loader.resolve({ url: url.href });
73
77
  const rootDataObject = await runtime_utils_1.requestFluidObject(container, "/");
74
78
  const fluidContainer = new fluid_static_1.FluidContainer(container, rootDataObject);
75
79
  const services = this.getContainerServices(container);
@@ -1 +1 @@
1
- {"version":3,"file":"AzureClient.js","sourceRoot":"","sources":["../src/AzureClient.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 */\nimport { Container, Loader } from \"@fluidframework/container-loader\";\nimport {\n IDocumentServiceFactory, IUrlResolver,\n} from \"@fluidframework/driver-definitions\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { RouterliciousDocumentServiceFactory } from \"@fluidframework/routerlicious-driver\";\nimport { requestFluidObject } from \"@fluidframework/runtime-utils\";\nimport { ensureFluidResolvedUrl } from \"@fluidframework/driver-utils\";\nimport {\n ContainerSchema,\n DOProviderContainerRuntimeFactory,\n FluidContainer,\n IFluidContainer,\n RootDataObject,\n} from \"@fluidframework/fluid-static\";\n\nimport {\n AzureClientProps,\n AzureContainerServices,\n} from \"./interfaces\";\nimport { AzureAudience } from \"./AzureAudience\";\nimport { AzureUrlResolver, createAzureCreateNewRequest } from \"./AzureUrlResolver\";\n\n/**\n * Strongly typed id for connecting to a local Azure Fluid Relay.\n */\nexport const LOCAL_MODE_TENANT_ID = \"local\";\n\n/**\n * AzureClient provides the ability to have a Fluid object backed by the Azure Fluid Relay or,\n * when running with local tenantId, have it be backed by a local Azure Fluid Relay instance.\n */\nexport class AzureClient {\n private readonly documentServiceFactory: IDocumentServiceFactory;\n private readonly urlResolver: IUrlResolver;\n\n /**\n * Creates a new client instance using configuration parameters.\n * @param props - Properties for initializing a new AzureClient instance\n */\n constructor(private readonly props: AzureClientProps) {\n this.urlResolver = new AzureUrlResolver(\n this.props.connection.tenantId,\n this.props.connection.orderer,\n this.props.connection.storage,\n );\n // The local service implementation differs from the Azure Fluid Relay in blob\n // storage format. Azure Fluid Relay supports whole summary upload. Local currently does not.\n const enableWholeSummaryUpload = this.props.connection.tenantId !== LOCAL_MODE_TENANT_ID;\n this.documentServiceFactory = new RouterliciousDocumentServiceFactory(\n this.props.connection.tokenProvider,\n { enableWholeSummaryUpload },\n );\n }\n\n /**\n * Creates a new detached container instance in the Azure Fluid Relay.\n * @param containerSchema - Container schema for the new container.\n * @returns New detached container instance along with associated services.\n */\n public async createContainer(\n containerSchema: ContainerSchema,\n ): Promise<{ container: IFluidContainer; services: AzureContainerServices }> {\n const loader = this.createLoader(containerSchema);\n\n const container = await loader.createDetachedContainer({\n package: \"no-dynamic-package\",\n config: {},\n });\n\n const rootDataObject = await requestFluidObject<RootDataObject>(container, \"/\");\n\n const fluidContainer = new (class extends FluidContainer {\n async attach() {\n if (this.attachState !== AttachState.Detached) {\n throw new Error(\"Cannot attach container. Container is not in detached state\");\n }\n const request = createAzureCreateNewRequest();\n await container.attach(request);\n const resolved = container.resolvedUrl;\n ensureFluidResolvedUrl(resolved);\n return resolved.id;\n }\n })(container, rootDataObject);\n\n const services = this.getContainerServices(container);\n return { container: fluidContainer, services };\n }\n\n /**\n * Accesses the existing container given its unique ID in the Azure Fluid Relay.\n * @param id - Unique ID of the container in Azure Fluid Relay.\n * @param containerSchema - Container schema used to access data objects in the container.\n * @returns Existing container instance along with associated services.\n */\n public async getContainer(\n id: string,\n containerSchema: ContainerSchema,\n ): Promise<{ container: IFluidContainer; services: AzureContainerServices }> {\n const loader = this.createLoader(containerSchema);\n const container = await loader.resolve({ url: id });\n const rootDataObject = await requestFluidObject<RootDataObject>(container, \"/\");\n const fluidContainer = new FluidContainer(container, rootDataObject);\n const services = this.getContainerServices(container);\n return { container: fluidContainer, services };\n }\n\n private getContainerServices(\n container: Container,\n ): AzureContainerServices {\n return {\n audience: new AzureAudience(container),\n };\n }\n\n private createLoader(\n containerSchema: ContainerSchema,\n ): Loader {\n const runtimeFactory = new DOProviderContainerRuntimeFactory(\n containerSchema,\n );\n const module = { fluidExport: runtimeFactory };\n const codeLoader = { load: async () => module };\n return new Loader({\n urlResolver: this.urlResolver,\n documentServiceFactory: this.documentServiceFactory,\n codeLoader,\n logger: this.props.logger,\n });\n }\n // #endregion\n}\n"]}
1
+ {"version":3,"file":"AzureClient.js","sourceRoot":"","sources":["../src/AzureClient.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 */\nimport { Loader } from \"@fluidframework/container-loader\";\nimport {\n IDocumentServiceFactory,\n IUrlResolver,\n} from \"@fluidframework/driver-definitions\";\nimport { AttachState, IContainer } from \"@fluidframework/container-definitions\";\nimport { RouterliciousDocumentServiceFactory } from \"@fluidframework/routerlicious-driver\";\nimport { requestFluidObject } from \"@fluidframework/runtime-utils\";\nimport { ensureFluidResolvedUrl } from \"@fluidframework/driver-utils\";\nimport {\n ContainerSchema,\n DOProviderContainerRuntimeFactory,\n FluidContainer,\n IFluidContainer,\n RootDataObject,\n} from \"@fluidframework/fluid-static\";\n\nimport { AzureClientProps, AzureContainerServices } from \"./interfaces\";\nimport { AzureAudience } from \"./AzureAudience\";\nimport {\n AzureUrlResolver,\n createAzureCreateNewRequest,\n} from \"./AzureUrlResolver\";\n\n/**\n * Strongly typed id for connecting to a local Azure Fluid Relay.\n */\nexport const LOCAL_MODE_TENANT_ID = \"local\";\n\n/**\n * AzureClient provides the ability to have a Fluid object backed by the Azure Fluid Relay or,\n * when running with local tenantId, have it be backed by a local Azure Fluid Relay instance.\n */\nexport class AzureClient {\n private readonly documentServiceFactory: IDocumentServiceFactory;\n private readonly urlResolver: IUrlResolver;\n\n /**\n * Creates a new client instance using configuration parameters.\n * @param props - Properties for initializing a new AzureClient instance\n */\n constructor(private readonly props: AzureClientProps) {\n this.urlResolver = new AzureUrlResolver();\n // The local service implementation differs from the Azure Fluid Relay in blob\n // storage format. Azure Fluid Relay supports whole summary upload. Local currently does not.\n const enableWholeSummaryUpload =\n this.props.connection.tenantId !== LOCAL_MODE_TENANT_ID;\n this.documentServiceFactory = new RouterliciousDocumentServiceFactory(\n this.props.connection.tokenProvider,\n { enableWholeSummaryUpload },\n );\n }\n\n /**\n * Creates a new detached container instance in the Azure Fluid Relay.\n * @param containerSchema - Container schema for the new container.\n * @returns New detached container instance along with associated services.\n */\n public async createContainer(\n containerSchema: ContainerSchema,\n ): Promise<{\n container: IFluidContainer;\n services: AzureContainerServices;\n }> {\n const loader = this.createLoader(containerSchema);\n\n const container = await loader.createDetachedContainer({\n package: \"no-dynamic-package\",\n config: {},\n });\n\n const rootDataObject = await requestFluidObject<RootDataObject>(\n container,\n \"/\",\n );\n const createNewRequest = createAzureCreateNewRequest(\n this.props.connection.orderer,\n this.props.connection.storage,\n this.props.connection.tenantId,\n );\n const fluidContainer = new (class extends FluidContainer {\n async attach() {\n if (this.attachState !== AttachState.Detached) {\n throw new Error(\n \"Cannot attach container. Container is not in detached state\",\n );\n }\n await container.attach(createNewRequest);\n const resolved = container.resolvedUrl;\n ensureFluidResolvedUrl(resolved);\n return resolved.id;\n }\n })(container, rootDataObject);\n\n const services = this.getContainerServices(container);\n return { container: fluidContainer, services };\n }\n\n /**\n * Accesses the existing container given its unique ID in the Azure Fluid Relay.\n * @param id - Unique ID of the container in Azure Fluid Relay.\n * @param containerSchema - Container schema used to access data objects in the container.\n * @returns Existing container instance along with associated services.\n */\n public async getContainer(\n id: string,\n containerSchema: ContainerSchema,\n ): Promise<{\n container: IFluidContainer;\n services: AzureContainerServices;\n }> {\n const loader = this.createLoader(containerSchema);\n const url = new URL(this.props.connection.orderer);\n url.searchParams.append(\"storage\", encodeURIComponent(this.props.connection.storage));\n url.searchParams.append(\"tenantId\", encodeURIComponent(this.props.connection.tenantId));\n url.searchParams.append(\"containerId\", encodeURIComponent(id));\n const container = await loader.resolve({ url: url.href });\n const rootDataObject = await requestFluidObject<RootDataObject>(\n container,\n \"/\",\n );\n const fluidContainer = new FluidContainer(container, rootDataObject);\n const services = this.getContainerServices(container);\n return { container: fluidContainer, services };\n }\n\n private getContainerServices(container: IContainer): AzureContainerServices {\n return {\n audience: new AzureAudience(container),\n };\n }\n\n private createLoader(containerSchema: ContainerSchema): Loader {\n const runtimeFactory = new DOProviderContainerRuntimeFactory(\n containerSchema,\n );\n const module = { fluidExport: runtimeFactory };\n const codeLoader = { load: async () => module };\n return new Loader({\n urlResolver: this.urlResolver,\n documentServiceFactory: this.documentServiceFactory,\n codeLoader,\n logger: this.props.logger,\n });\n }\n // #endregion\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AzureFunctionTokenProvider.js","sourceRoot":"","sources":["../src/AzureFunctionTokenProvider.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAGH,kDAA0B;AAG1B;;;GAGG;AACH,MAAa,0BAA0B;IACnC;;;;OAIG;IACH,YACqB,aAAqB,EACrB,IAAqE;QADrE,kBAAa,GAAb,aAAa,CAAQ;QACrB,SAAI,GAAJ,IAAI,CAAiE;IACtF,CAAC;IAEE,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAmB;QAChE,OAAO;YACH,GAAG,EAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAkB;QAC/D,OAAO;YACH,GAAG,EAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,UAA8B;;QACnE,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE;YACjD,MAAM,EAAE;gBACJ,QAAQ;gBACR,UAAU;gBACV,MAAM,QAAE,IAAI,CAAC,IAAI,0CAAE,MAAM;gBACzB,QAAQ,QAAE,IAAI,CAAC,IAAI,0CAAE,QAAQ;gBAC7B,iBAAiB,QAAE,IAAI,CAAC,IAAI,0CAAE,iBAAiB;aAClD;SACJ,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAc,CAAC;IACnC,CAAC;CACJ;AAnCD,gEAmCC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITokenProvider, ITokenResponse } from \"@fluidframework/routerlicious-driver\";\nimport axios from \"axios\";\nimport { AzureMember } from \"./interfaces\";\n\n/**\n * Token Provider implementation for connecting to an Azure Function endpoint for\n * Azure Fluid Relay token resolution.\n */\nexport class AzureFunctionTokenProvider implements ITokenProvider {\n /**\n * Creates a new instance using configuration parameters.\n * @param azFunctionUrl - URL to Azure Function endpoint\n * @param user - User object\n */\n constructor(\n private readonly azFunctionUrl: string,\n private readonly user?: Pick<AzureMember, \"userId\" | \"userName\" | \"additionalDetails\">,\n ) { }\n\n public async fetchOrdererToken(tenantId: string, documentId?: string): Promise<ITokenResponse> {\n return {\n jwt: await this.getToken(tenantId, documentId),\n };\n }\n\n public async fetchStorageToken(tenantId: string, documentId: string): Promise<ITokenResponse> {\n return {\n jwt: await this.getToken(tenantId, documentId),\n };\n }\n\n private async getToken(tenantId: string, documentId: string | undefined): Promise<string> {\n const response = await axios.get(this.azFunctionUrl, {\n params: {\n tenantId,\n documentId,\n userId: this.user?.userId,\n userName: this.user?.userName,\n additionalDetails: this.user?.additionalDetails,\n },\n });\n return response.data as string;\n }\n}\n"]}
1
+ {"version":3,"file":"AzureFunctionTokenProvider.js","sourceRoot":"","sources":["../src/AzureFunctionTokenProvider.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAGH,kDAA0B;AAG1B;;;GAGG;AACH,MAAa,0BAA0B;IACnC;;;;OAIG;IACH,YACqB,aAAqB,EACrB,IAAqE;QADrE,kBAAa,GAAb,aAAa,CAAQ;QACrB,SAAI,GAAJ,IAAI,CAAiE;IACtF,CAAC;IAEE,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAmB;QAChE,OAAO;YACH,GAAG,EAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAkB;QAC/D,OAAO;YACH,GAAG,EAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,UAAmB;;QACxD,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE;YACjD,MAAM,EAAE;gBACJ,QAAQ;gBACR,UAAU;gBACV,MAAM,QAAE,IAAI,CAAC,IAAI,0CAAE,MAAM;gBACzB,QAAQ,QAAE,IAAI,CAAC,IAAI,0CAAE,QAAQ;gBAC7B,iBAAiB,QAAE,IAAI,CAAC,IAAI,0CAAE,iBAAiB;aAClD;SACJ,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAc,CAAC;IACnC,CAAC;CACJ;AAnCD,gEAmCC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITokenProvider, ITokenResponse } from \"@fluidframework/routerlicious-driver\";\nimport axios from \"axios\";\nimport { AzureMember } from \"./interfaces\";\n\n/**\n * Token Provider implementation for connecting to an Azure Function endpoint for\n * Azure Fluid Relay token resolution.\n */\nexport class AzureFunctionTokenProvider implements ITokenProvider {\n /**\n * Creates a new instance using configuration parameters.\n * @param azFunctionUrl - URL to Azure Function endpoint\n * @param user - User object\n */\n constructor(\n private readonly azFunctionUrl: string,\n private readonly user?: Pick<AzureMember, \"userId\" | \"userName\" | \"additionalDetails\">,\n ) { }\n\n public async fetchOrdererToken(tenantId: string, documentId?: string): Promise<ITokenResponse> {\n return {\n jwt: await this.getToken(tenantId, documentId),\n };\n }\n\n public async fetchStorageToken(tenantId: string, documentId: string): Promise<ITokenResponse> {\n return {\n jwt: await this.getToken(tenantId, documentId),\n };\n }\n\n private async getToken(tenantId: string, documentId?: string): Promise<string> {\n const response = await axios.get(this.azFunctionUrl, {\n params: {\n tenantId,\n documentId,\n userId: this.user?.userId,\n userName: this.user?.userName,\n additionalDetails: this.user?.additionalDetails,\n },\n });\n return response.data as string;\n }\n}\n"]}
@@ -5,12 +5,9 @@
5
5
  import { IRequest } from "@fluidframework/core-interfaces";
6
6
  import { IFluidResolvedUrl, IResolvedUrl, IUrlResolver } from "@fluidframework/driver-definitions";
7
7
  export declare class AzureUrlResolver implements IUrlResolver {
8
- private readonly tenantId;
9
- private readonly orderer;
10
- private readonly storage;
11
- constructor(tenantId: string, orderer: string, storage: string);
8
+ constructor();
12
9
  resolve(request: IRequest): Promise<IFluidResolvedUrl>;
13
10
  getAbsoluteUrl(resolvedUrl: IResolvedUrl, relativeUrl: string): Promise<string>;
14
11
  }
15
- export declare const createAzureCreateNewRequest: () => IRequest;
12
+ export declare const createAzureCreateNewRequest: (ordererUrl: string, storageUrl: string, tenantId: string) => IRequest;
16
13
  //# sourceMappingURL=AzureUrlResolver.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AzureUrlResolver.d.ts","sourceRoot":"","sources":["../src/AzureUrlResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EAEH,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACf,MAAM,oCAAoC,CAAC;AAM5C,qBAAa,gBAAiB,YAAW,YAAY;IAE7C,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAFP,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM;IAGvB,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAkCtD,cAAc,CAAC,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAM/F;AAED,eAAO,MAAM,2BAA2B,QAAO,QAO9C,CAAC"}
1
+ {"version":3,"file":"AzureUrlResolver.d.ts","sourceRoot":"","sources":["../src/AzureUrlResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EAEH,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACf,MAAM,oCAAoC,CAAC;AAM5C,qBAAa,gBAAiB,YAAW,YAAY;;IAGpC,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAyCtD,cAAc,CACvB,WAAW,EAAE,YAAY,EACzB,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC;CAMrB;AAkCD,eAAO,MAAM,2BAA2B,eACxB,MAAM,cACN,MAAM,YACR,MAAM,KACjB,QAUF,CAAC"}
@@ -11,37 +11,36 @@ const driver_definitions_1 = require("@fluidframework/driver-definitions");
11
11
  // InsecureTokenProvider for basic scenarios or more robust, secure providers that fulfill the
12
12
  // ITokenProvider interface
13
13
  class AzureUrlResolver {
14
- constructor(tenantId, orderer, storage) {
15
- this.tenantId = tenantId;
16
- this.orderer = orderer;
17
- this.storage = storage;
18
- }
14
+ constructor() { }
19
15
  async resolve(request) {
16
+ const { ordererUrl, storageUrl, tenantId, containerId } = decodeAzureUrl(request.url);
20
17
  // determine whether the request is for creating of a new container.
21
18
  // such request has the `createNew` header set to true and doesn't have a container ID.
22
- if (request.headers && request.headers[driver_definitions_1.DriverHeader.createNew] === true) {
19
+ if (request.headers &&
20
+ request.headers[driver_definitions_1.DriverHeader.createNew] === true) {
23
21
  return {
24
22
  endpoints: {
25
- deltaStorageUrl: `${this.orderer}/deltas/${this.tenantId}/new`,
26
- ordererUrl: this.orderer,
27
- storageUrl: `${this.storage}/repos/${this.tenantId}`,
23
+ deltaStorageUrl: `${ordererUrl}/deltas/${tenantId}/new`,
24
+ ordererUrl,
25
+ storageUrl: `${storageUrl}/repos/${tenantId}`,
28
26
  },
29
27
  // id is a mandatory attribute, but it's ignored by the driver for new container requests.
30
28
  id: "",
31
29
  // tokens attribute is redundant as all tokens are generated via ITokenProvider
32
30
  tokens: {},
33
31
  type: "fluid",
34
- url: `${this.orderer}/${this.tenantId}/new`,
32
+ url: `${ordererUrl}/${tenantId}/new`,
35
33
  };
36
34
  }
37
- // for an existing container we'll parse the request URL to determine the document ID.
38
- const containerId = request.url.split("/")[0];
39
- const documentUrl = `${this.orderer}/${this.tenantId}/${containerId}`;
35
+ if (containerId === undefined) {
36
+ throw new Error("Azure URL did not contain containerId");
37
+ }
38
+ const documentUrl = `${ordererUrl}/${tenantId}/${containerId}`;
40
39
  return Promise.resolve({
41
40
  endpoints: {
42
- deltaStorageUrl: `${this.orderer}/deltas/${this.tenantId}/${containerId}`,
43
- ordererUrl: this.orderer,
44
- storageUrl: `${this.storage}/repos/${this.tenantId}`,
41
+ deltaStorageUrl: `${ordererUrl}/deltas/${tenantId}/${containerId}`,
42
+ ordererUrl,
43
+ storageUrl: `${storageUrl}/repos/${tenantId}`,
45
44
  },
46
45
  id: containerId,
47
46
  tokens: {},
@@ -57,11 +56,42 @@ class AzureUrlResolver {
57
56
  }
58
57
  }
59
58
  exports.AzureUrlResolver = AzureUrlResolver;
60
- const createAzureCreateNewRequest = () => ({
61
- url: "",
62
- headers: {
63
- [driver_definitions_1.DriverHeader.createNew]: true,
64
- },
65
- });
59
+ function decodeAzureUrl(urlString) {
60
+ const url = new URL(urlString);
61
+ const ordererUrl = url.origin;
62
+ const searchParams = url.searchParams;
63
+ const storageUrl = searchParams.get("storage");
64
+ // eslint-disable-next-line no-null/no-null
65
+ if (storageUrl === null) {
66
+ throw new Error("Azure URL did not contain a storage URL");
67
+ }
68
+ const tenantId = searchParams.get("tenantId");
69
+ // eslint-disable-next-line no-null/no-null
70
+ if (tenantId === null) {
71
+ throw new Error("Azure URL did not contain a tenant ID");
72
+ }
73
+ const storageUrlDecoded = decodeURIComponent(storageUrl);
74
+ const tenantIdDecoded = decodeURIComponent(tenantId);
75
+ const containerId = searchParams.get("containerId");
76
+ // eslint-disable-next-line no-null/no-null
77
+ const containerIdDecoded = containerId !== null ? decodeURIComponent(containerId) : undefined;
78
+ return {
79
+ ordererUrl,
80
+ storageUrl: storageUrlDecoded,
81
+ tenantId: tenantIdDecoded,
82
+ containerId: containerIdDecoded,
83
+ };
84
+ }
85
+ const createAzureCreateNewRequest = (ordererUrl, storageUrl, tenantId) => {
86
+ const url = new URL(ordererUrl);
87
+ url.searchParams.append("storage", encodeURIComponent(storageUrl));
88
+ url.searchParams.append("tenantId", encodeURIComponent(tenantId));
89
+ return {
90
+ url: url.href,
91
+ headers: {
92
+ [driver_definitions_1.DriverHeader.createNew]: true,
93
+ },
94
+ };
95
+ };
66
96
  exports.createAzureCreateNewRequest = createAzureCreateNewRequest;
67
97
  //# sourceMappingURL=AzureUrlResolver.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AzureUrlResolver.js","sourceRoot":"","sources":["../src/AzureUrlResolver.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,2EAK4C;AAE5C,2FAA2F;AAC3F,sFAAsF;AACtF,8FAA8F;AAC9F,2BAA2B;AAC3B,MAAa,gBAAgB;IACzB,YACqB,QAAgB,EAChB,OAAe,EACf,OAAe;QAFf,aAAQ,GAAR,QAAQ,CAAQ;QAChB,YAAO,GAAP,OAAO,CAAQ;QACf,YAAO,GAAP,OAAO,CAAQ;IAChC,CAAC;IAEE,KAAK,CAAC,OAAO,CAAC,OAAiB;QAClC,oEAAoE;QACpE,uFAAuF;QACvF,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,iCAAY,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;YACrE,OAAO;gBACH,SAAS,EAAE;oBACP,eAAe,EAAE,GAAG,IAAI,CAAC,OAAO,WAAW,IAAI,CAAC,QAAQ,MAAM;oBAC9D,UAAU,EAAE,IAAI,CAAC,OAAO;oBACxB,UAAU,EAAE,GAAG,IAAI,CAAC,OAAO,UAAU,IAAI,CAAC,QAAQ,EAAE;iBACvD;gBACD,0FAA0F;gBAC1F,EAAE,EAAE,EAAE;gBACN,+EAA+E;gBAC/E,MAAM,EAAE,EAAE;gBACV,IAAI,EAAE,OAAO;gBACb,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,MAAM;aAC9C,CAAC;SACL;QACD,sFAAsF;QACtF,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,WAAW,GAAG,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,IAAI,WAAW,EAAE,CAAC;QACtE,OAAO,OAAO,CAAC,OAAO,CAAC;YACnB,SAAS,EAAE;gBACP,eAAe,EAAE,GAAG,IAAI,CAAC,OAAO,WAAW,IAAI,CAAC,QAAQ,IAAI,WAAW,EAAE;gBACzE,UAAU,EAAE,IAAI,CAAC,OAAO;gBACxB,UAAU,EAAE,GAAG,IAAI,CAAC,OAAO,UAAU,IAAI,CAAC,QAAQ,EAAE;aACvD;YACD,EAAE,EAAE,WAAW;YACf,MAAM,EAAE,EAAE;YACV,IAAI,EAAE,OAAO;YACb,GAAG,EAAE,WAAW;SACnB,CAAC,CAAC;IACP,CAAC;IAEM,KAAK,CAAC,cAAc,CAAC,WAAyB,EAAE,WAAmB;QACtE,IAAI,WAAW,CAAC,IAAI,KAAK,OAAO,EAAE;YAC9B,MAAM,KAAK,CAAC,sBAAsB,CAAC,CAAC;SACvC;QACD,OAAO,GAAG,WAAW,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC;IAC/C,CAAC;CACJ;AA/CD,4CA+CC;AAEM,MAAM,2BAA2B,GAAG,GAAa,EAAE,CAAC,CACvD;IACI,GAAG,EAAE,EAAE;IACP,OAAO,EAAE;QACL,CAAC,iCAAY,CAAC,SAAS,CAAC,EAAE,IAAI;KACjC;CACJ,CACJ,CAAC;AAPW,QAAA,2BAA2B,+BAOtC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IRequest } from \"@fluidframework/core-interfaces\";\nimport {\n DriverHeader,\n IFluidResolvedUrl,\n IResolvedUrl,\n IUrlResolver,\n} from \"@fluidframework/driver-definitions\";\n\n// Implementation of a URL resolver to resolve documents stored using the Azure Fluid Relay\n// based off of the orderer and storage URLs provide. The token provider here can be a\n// InsecureTokenProvider for basic scenarios or more robust, secure providers that fulfill the\n// ITokenProvider interface\nexport class AzureUrlResolver implements IUrlResolver {\n constructor(\n private readonly tenantId: string,\n private readonly orderer: string,\n private readonly storage: string,\n ) { }\n\n public async resolve(request: IRequest): Promise<IFluidResolvedUrl> {\n // determine whether the request is for creating of a new container.\n // such request has the `createNew` header set to true and doesn't have a container ID.\n if (request.headers && request.headers[DriverHeader.createNew] === true) {\n return {\n endpoints: {\n deltaStorageUrl: `${this.orderer}/deltas/${this.tenantId}/new`,\n ordererUrl: this.orderer,\n storageUrl: `${this.storage}/repos/${this.tenantId}`,\n },\n // id is a mandatory attribute, but it's ignored by the driver for new container requests.\n id: \"\",\n // tokens attribute is redundant as all tokens are generated via ITokenProvider\n tokens: {},\n type: \"fluid\",\n url: `${this.orderer}/${this.tenantId}/new`,\n };\n }\n // for an existing container we'll parse the request URL to determine the document ID.\n const containerId = request.url.split(\"/\")[0];\n const documentUrl = `${this.orderer}/${this.tenantId}/${containerId}`;\n return Promise.resolve({\n endpoints: {\n deltaStorageUrl: `${this.orderer}/deltas/${this.tenantId}/${containerId}`,\n ordererUrl: this.orderer,\n storageUrl: `${this.storage}/repos/${this.tenantId}`,\n },\n id: containerId,\n tokens: {},\n type: \"fluid\",\n url: documentUrl,\n });\n }\n\n public async getAbsoluteUrl(resolvedUrl: IResolvedUrl, relativeUrl: string): Promise<string> {\n if (resolvedUrl.type !== \"fluid\") {\n throw Error(\"Invalid Resolved Url\");\n }\n return `${resolvedUrl.url}/${relativeUrl}`;\n }\n}\n\nexport const createAzureCreateNewRequest = (): IRequest => (\n {\n url: \"\",\n headers: {\n [DriverHeader.createNew]: true,\n },\n }\n);\n"]}
1
+ {"version":3,"file":"AzureUrlResolver.js","sourceRoot":"","sources":["../src/AzureUrlResolver.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 { IRequest } from \"@fluidframework/core-interfaces\";\nimport {\n DriverHeader,\n IFluidResolvedUrl,\n IResolvedUrl,\n IUrlResolver,\n} from \"@fluidframework/driver-definitions\";\n\n// Implementation of a URL resolver to resolve documents stored using the Azure Fluid Relay\n// based off of the orderer and storage URLs provide. The token provider here can be a\n// InsecureTokenProvider for basic scenarios or more robust, secure providers that fulfill the\n// ITokenProvider interface\nexport class AzureUrlResolver implements IUrlResolver {\n constructor() {}\n\n public async resolve(request: IRequest): Promise<IFluidResolvedUrl> {\n const { ordererUrl, storageUrl, tenantId, containerId } = decodeAzureUrl(\n request.url,\n );\n // determine whether the request is for creating of a new container.\n // such request has the `createNew` header set to true and doesn't have a container ID.\n if (\n request.headers &&\n request.headers[DriverHeader.createNew] === true\n ) {\n return {\n endpoints: {\n deltaStorageUrl: `${ordererUrl}/deltas/${tenantId}/new`,\n ordererUrl,\n storageUrl: `${storageUrl}/repos/${tenantId}`,\n },\n // id is a mandatory attribute, but it's ignored by the driver for new container requests.\n id: \"\",\n // tokens attribute is redundant as all tokens are generated via ITokenProvider\n tokens: {},\n type: \"fluid\",\n url: `${ordererUrl}/${tenantId}/new`,\n };\n }\n if (containerId === undefined) {\n throw new Error(\"Azure URL did not contain containerId\");\n }\n const documentUrl = `${ordererUrl}/${tenantId}/${containerId}`;\n return Promise.resolve({\n endpoints: {\n deltaStorageUrl: `${ordererUrl}/deltas/${tenantId}/${containerId}`,\n ordererUrl,\n storageUrl: `${storageUrl}/repos/${tenantId}`,\n },\n id: containerId,\n tokens: {},\n type: \"fluid\",\n url: documentUrl,\n });\n }\n\n public async getAbsoluteUrl(\n resolvedUrl: IResolvedUrl,\n relativeUrl: string,\n ): Promise<string> {\n if (resolvedUrl.type !== \"fluid\") {\n throw Error(\"Invalid Resolved Url\");\n }\n return `${resolvedUrl.url}/${relativeUrl}`;\n }\n}\n\nfunction decodeAzureUrl(urlString: string): {\n ordererUrl: string;\n storageUrl: string;\n tenantId: string;\n containerId?: string,\n} {\n const url = new URL(urlString);\n const ordererUrl = url.origin;\n const searchParams = url.searchParams;\n const storageUrl = searchParams.get(\"storage\");\n // eslint-disable-next-line no-null/no-null\n if (storageUrl === null) {\n throw new Error(\"Azure URL did not contain a storage URL\");\n }\n const tenantId = searchParams.get(\"tenantId\");\n // eslint-disable-next-line no-null/no-null\n if (tenantId === null) {\n throw new Error(\"Azure URL did not contain a tenant ID\");\n }\n const storageUrlDecoded = decodeURIComponent(storageUrl);\n const tenantIdDecoded = decodeURIComponent(tenantId);\n const containerId = searchParams.get(\"containerId\");\n // eslint-disable-next-line no-null/no-null\n const containerIdDecoded = containerId !== null ? decodeURIComponent(containerId) : undefined;\n return {\n ordererUrl,\n storageUrl: storageUrlDecoded,\n tenantId: tenantIdDecoded,\n containerId: containerIdDecoded,\n };\n}\n\nexport const createAzureCreateNewRequest = (\n ordererUrl: string,\n storageUrl: string,\n tenantId: string,\n): IRequest => {\n const url = new URL(ordererUrl);\n url.searchParams.append(\"storage\", encodeURIComponent(storageUrl));\n url.searchParams.append(\"tenantId\", encodeURIComponent(tenantId));\n return {\n url: url.href,\n headers: {\n [DriverHeader.createNew]: true,\n },\n };\n};\n"]}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export declare const pkgName = "@fluidframework/azure-client";
8
- export declare const pkgVersion = "0.52.0";
8
+ export declare const pkgVersion = "0.54.0-47413";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,iCAAiC,CAAC;AACtD,eAAO,MAAM,UAAU,WAAW,CAAC"}
1
+ {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,iCAAiC,CAAC;AACtD,eAAO,MAAM,UAAU,iBAAiB,CAAC"}
@@ -8,5 +8,5 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.pkgVersion = exports.pkgName = void 0;
10
10
  exports.pkgName = "@fluidframework/azure-client";
11
- exports.pkgVersion = "0.52.0";
11
+ exports.pkgVersion = "0.54.0-47413";
12
12
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,8BAA8B,CAAC;AACzC,QAAA,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/azure-client\";\nexport const pkgVersion = \"0.52.0\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,8BAA8B,CAAC;AACzC,QAAA,UAAU,GAAG,cAAc,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/azure-client\";\nexport const pkgVersion = \"0.54.0-47413\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AzureClient.d.ts","sourceRoot":"","sources":["../src/AzureClient.ts"],"names":[],"mappings":"AAYA,OAAO,EACH,eAAe,EAGf,eAAe,EAElB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACH,gBAAgB,EAChB,sBAAsB,EACzB,MAAM,cAAc,CAAC;AAItB;;GAEG;AACH,eAAO,MAAM,oBAAoB,UAAU,CAAC;AAE5C;;;GAGG;AACH,qBAAa,WAAW;IAQR,OAAO,CAAC,QAAQ,CAAC,KAAK;IAPlC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA0B;IACjE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAe;IAE3C;;;OAGG;gBAC0B,KAAK,EAAE,gBAAgB;IAepD;;;;OAIG;IACU,eAAe,CACxB,eAAe,EAAE,eAAe,GACjC,OAAO,CAAC;QAAE,SAAS,EAAE,eAAe,CAAC;QAAC,QAAQ,EAAE,sBAAsB,CAAA;KAAE,CAAC;IA2B5E;;;;;OAKG;IACU,YAAY,CACrB,EAAE,EAAE,MAAM,EACV,eAAe,EAAE,eAAe,GACjC,OAAO,CAAC;QAAE,SAAS,EAAE,eAAe,CAAC;QAAC,QAAQ,EAAE,sBAAsB,CAAA;KAAE,CAAC;IAS5E,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,YAAY;CAgBvB"}
1
+ {"version":3,"file":"AzureClient.d.ts","sourceRoot":"","sources":["../src/AzureClient.ts"],"names":[],"mappings":"AAaA,OAAO,EACH,eAAe,EAGf,eAAe,EAElB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAOxE;;GAEG;AACH,eAAO,MAAM,oBAAoB,UAAU,CAAC;AAE5C;;;GAGG;AACH,qBAAa,WAAW;IAQR,OAAO,CAAC,QAAQ,CAAC,KAAK;IAPlC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA0B;IACjE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAe;IAE3C;;;OAGG;gBAC0B,KAAK,EAAE,gBAAgB;IAYpD;;;;OAIG;IACU,eAAe,CACxB,eAAe,EAAE,eAAe,GACjC,OAAO,CAAC;QACP,SAAS,EAAE,eAAe,CAAC;QAC3B,QAAQ,EAAE,sBAAsB,CAAC;KACpC,CAAC;IAmCF;;;;;OAKG;IACU,YAAY,CACrB,EAAE,EAAE,MAAM,EACV,eAAe,EAAE,eAAe,GACjC,OAAO,CAAC;QACP,SAAS,EAAE,eAAe,CAAC;QAC3B,QAAQ,EAAE,sBAAsB,CAAC;KACpC,CAAC;IAgBF,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,YAAY;CAcvB"}
@@ -9,7 +9,7 @@ import { requestFluidObject } from "@fluidframework/runtime-utils";
9
9
  import { ensureFluidResolvedUrl } from "@fluidframework/driver-utils";
10
10
  import { DOProviderContainerRuntimeFactory, FluidContainer, } from "@fluidframework/fluid-static";
11
11
  import { AzureAudience } from "./AzureAudience";
12
- import { AzureUrlResolver, createAzureCreateNewRequest } from "./AzureUrlResolver";
12
+ import { AzureUrlResolver, createAzureCreateNewRequest, } from "./AzureUrlResolver";
13
13
  /**
14
14
  * Strongly typed id for connecting to a local Azure Fluid Relay.
15
15
  */
@@ -25,7 +25,7 @@ export class AzureClient {
25
25
  */
26
26
  constructor(props) {
27
27
  this.props = props;
28
- this.urlResolver = new AzureUrlResolver(this.props.connection.tenantId, this.props.connection.orderer, this.props.connection.storage);
28
+ this.urlResolver = new AzureUrlResolver();
29
29
  // The local service implementation differs from the Azure Fluid Relay in blob
30
30
  // storage format. Azure Fluid Relay supports whole summary upload. Local currently does not.
31
31
  const enableWholeSummaryUpload = this.props.connection.tenantId !== LOCAL_MODE_TENANT_ID;
@@ -43,13 +43,13 @@ export class AzureClient {
43
43
  config: {},
44
44
  });
45
45
  const rootDataObject = await requestFluidObject(container, "/");
46
+ const createNewRequest = createAzureCreateNewRequest(this.props.connection.orderer, this.props.connection.storage, this.props.connection.tenantId);
46
47
  const fluidContainer = new (class extends FluidContainer {
47
48
  async attach() {
48
49
  if (this.attachState !== AttachState.Detached) {
49
50
  throw new Error("Cannot attach container. Container is not in detached state");
50
51
  }
51
- const request = createAzureCreateNewRequest();
52
- await container.attach(request);
52
+ await container.attach(createNewRequest);
53
53
  const resolved = container.resolvedUrl;
54
54
  ensureFluidResolvedUrl(resolved);
55
55
  return resolved.id;
@@ -66,7 +66,11 @@ export class AzureClient {
66
66
  */
67
67
  async getContainer(id, containerSchema) {
68
68
  const loader = this.createLoader(containerSchema);
69
- const container = await loader.resolve({ url: id });
69
+ const url = new URL(this.props.connection.orderer);
70
+ url.searchParams.append("storage", encodeURIComponent(this.props.connection.storage));
71
+ url.searchParams.append("tenantId", encodeURIComponent(this.props.connection.tenantId));
72
+ url.searchParams.append("containerId", encodeURIComponent(id));
73
+ const container = await loader.resolve({ url: url.href });
70
74
  const rootDataObject = await requestFluidObject(container, "/");
71
75
  const fluidContainer = new FluidContainer(container, rootDataObject);
72
76
  const services = this.getContainerServices(container);
@@ -1 +1 @@
1
- {"version":3,"file":"AzureClient.js","sourceRoot":"","sources":["../src/AzureClient.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAa,MAAM,EAAE,MAAM,kCAAkC,CAAC;AAIrE,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACpE,OAAO,EAAE,mCAAmC,EAAE,MAAM,sCAAsC,CAAC;AAC3F,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAEH,iCAAiC,EACjC,cAAc,GAGjB,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AAEnF;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAE5C;;;GAGG;AACH,MAAM,OAAO,WAAW;IAIpB;;;OAGG;IACH,YAA6B,KAAuB;QAAvB,UAAK,GAAL,KAAK,CAAkB;QAChD,IAAI,CAAC,WAAW,GAAG,IAAI,gBAAgB,CACnC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,EAC9B,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,EAC7B,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAChC,CAAC;QACF,8EAA8E;QAC9E,6FAA6F;QAC7F,MAAM,wBAAwB,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,QAAQ,KAAK,oBAAoB,CAAC;QACzF,IAAI,CAAC,sBAAsB,GAAG,IAAI,mCAAmC,CACjE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,aAAa,EACnC,EAAE,wBAAwB,EAAE,CAC/B,CAAC;IACN,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,eAAe,CACxB,eAAgC;QAEhC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;QAElD,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC;YACnD,OAAO,EAAE,oBAAoB;YAC7B,MAAM,EAAE,EAAE;SACb,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG,MAAM,kBAAkB,CAAiB,SAAS,EAAE,GAAG,CAAC,CAAC;QAEhF,MAAM,cAAc,GAAG,IAAI,CAAC,KAAM,SAAQ,cAAc;YACpD,KAAK,CAAC,MAAM;gBACR,IAAI,IAAI,CAAC,WAAW,KAAK,WAAW,CAAC,QAAQ,EAAE;oBAC3C,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;iBAClF;gBACD,MAAM,OAAO,GAAG,2BAA2B,EAAE,CAAC;gBAC9C,MAAM,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAChC,MAAM,QAAQ,GAAG,SAAS,CAAC,WAAW,CAAC;gBACvC,sBAAsB,CAAC,QAAQ,CAAC,CAAC;gBACjC,OAAO,QAAQ,CAAC,EAAE,CAAC;YACvB,CAAC;SACJ,CAAC,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QAE9B,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACtD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC;IACnD,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,YAAY,CACrB,EAAU,EACV,eAAgC;QAEhC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;QACpD,MAAM,cAAc,GAAG,MAAM,kBAAkB,CAAiB,SAAS,EAAE,GAAG,CAAC,CAAC;QAChF,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACtD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC;IACnD,CAAC;IAEO,oBAAoB,CACxB,SAAoB;QAEpB,OAAO;YACH,QAAQ,EAAE,IAAI,aAAa,CAAC,SAAS,CAAC;SACzC,CAAC;IACN,CAAC;IAEO,YAAY,CAChB,eAAgC;QAEhC,MAAM,cAAc,GAAG,IAAI,iCAAiC,CACxD,eAAe,CAClB,CAAC;QACF,MAAM,MAAM,GAAG,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;QAC/C,MAAM,UAAU,GAAG,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;QAChD,OAAO,IAAI,MAAM,CAAC;YACd,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,sBAAsB,EAAE,IAAI,CAAC,sBAAsB;YACnD,UAAU;YACV,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;SAC5B,CAAC,CAAC;IACP,CAAC;CAEJ","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { Container, Loader } from \"@fluidframework/container-loader\";\nimport {\n IDocumentServiceFactory, IUrlResolver,\n} from \"@fluidframework/driver-definitions\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { RouterliciousDocumentServiceFactory } from \"@fluidframework/routerlicious-driver\";\nimport { requestFluidObject } from \"@fluidframework/runtime-utils\";\nimport { ensureFluidResolvedUrl } from \"@fluidframework/driver-utils\";\nimport {\n ContainerSchema,\n DOProviderContainerRuntimeFactory,\n FluidContainer,\n IFluidContainer,\n RootDataObject,\n} from \"@fluidframework/fluid-static\";\n\nimport {\n AzureClientProps,\n AzureContainerServices,\n} from \"./interfaces\";\nimport { AzureAudience } from \"./AzureAudience\";\nimport { AzureUrlResolver, createAzureCreateNewRequest } from \"./AzureUrlResolver\";\n\n/**\n * Strongly typed id for connecting to a local Azure Fluid Relay.\n */\nexport const LOCAL_MODE_TENANT_ID = \"local\";\n\n/**\n * AzureClient provides the ability to have a Fluid object backed by the Azure Fluid Relay or,\n * when running with local tenantId, have it be backed by a local Azure Fluid Relay instance.\n */\nexport class AzureClient {\n private readonly documentServiceFactory: IDocumentServiceFactory;\n private readonly urlResolver: IUrlResolver;\n\n /**\n * Creates a new client instance using configuration parameters.\n * @param props - Properties for initializing a new AzureClient instance\n */\n constructor(private readonly props: AzureClientProps) {\n this.urlResolver = new AzureUrlResolver(\n this.props.connection.tenantId,\n this.props.connection.orderer,\n this.props.connection.storage,\n );\n // The local service implementation differs from the Azure Fluid Relay in blob\n // storage format. Azure Fluid Relay supports whole summary upload. Local currently does not.\n const enableWholeSummaryUpload = this.props.connection.tenantId !== LOCAL_MODE_TENANT_ID;\n this.documentServiceFactory = new RouterliciousDocumentServiceFactory(\n this.props.connection.tokenProvider,\n { enableWholeSummaryUpload },\n );\n }\n\n /**\n * Creates a new detached container instance in the Azure Fluid Relay.\n * @param containerSchema - Container schema for the new container.\n * @returns New detached container instance along with associated services.\n */\n public async createContainer(\n containerSchema: ContainerSchema,\n ): Promise<{ container: IFluidContainer; services: AzureContainerServices }> {\n const loader = this.createLoader(containerSchema);\n\n const container = await loader.createDetachedContainer({\n package: \"no-dynamic-package\",\n config: {},\n });\n\n const rootDataObject = await requestFluidObject<RootDataObject>(container, \"/\");\n\n const fluidContainer = new (class extends FluidContainer {\n async attach() {\n if (this.attachState !== AttachState.Detached) {\n throw new Error(\"Cannot attach container. Container is not in detached state\");\n }\n const request = createAzureCreateNewRequest();\n await container.attach(request);\n const resolved = container.resolvedUrl;\n ensureFluidResolvedUrl(resolved);\n return resolved.id;\n }\n })(container, rootDataObject);\n\n const services = this.getContainerServices(container);\n return { container: fluidContainer, services };\n }\n\n /**\n * Accesses the existing container given its unique ID in the Azure Fluid Relay.\n * @param id - Unique ID of the container in Azure Fluid Relay.\n * @param containerSchema - Container schema used to access data objects in the container.\n * @returns Existing container instance along with associated services.\n */\n public async getContainer(\n id: string,\n containerSchema: ContainerSchema,\n ): Promise<{ container: IFluidContainer; services: AzureContainerServices }> {\n const loader = this.createLoader(containerSchema);\n const container = await loader.resolve({ url: id });\n const rootDataObject = await requestFluidObject<RootDataObject>(container, \"/\");\n const fluidContainer = new FluidContainer(container, rootDataObject);\n const services = this.getContainerServices(container);\n return { container: fluidContainer, services };\n }\n\n private getContainerServices(\n container: Container,\n ): AzureContainerServices {\n return {\n audience: new AzureAudience(container),\n };\n }\n\n private createLoader(\n containerSchema: ContainerSchema,\n ): Loader {\n const runtimeFactory = new DOProviderContainerRuntimeFactory(\n containerSchema,\n );\n const module = { fluidExport: runtimeFactory };\n const codeLoader = { load: async () => module };\n return new Loader({\n urlResolver: this.urlResolver,\n documentServiceFactory: this.documentServiceFactory,\n codeLoader,\n logger: this.props.logger,\n });\n }\n // #endregion\n}\n"]}
1
+ {"version":3,"file":"AzureClient.js","sourceRoot":"","sources":["../src/AzureClient.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 */\nimport { Loader } from \"@fluidframework/container-loader\";\nimport {\n IDocumentServiceFactory,\n IUrlResolver,\n} from \"@fluidframework/driver-definitions\";\nimport { AttachState, IContainer } from \"@fluidframework/container-definitions\";\nimport { RouterliciousDocumentServiceFactory } from \"@fluidframework/routerlicious-driver\";\nimport { requestFluidObject } from \"@fluidframework/runtime-utils\";\nimport { ensureFluidResolvedUrl } from \"@fluidframework/driver-utils\";\nimport {\n ContainerSchema,\n DOProviderContainerRuntimeFactory,\n FluidContainer,\n IFluidContainer,\n RootDataObject,\n} from \"@fluidframework/fluid-static\";\n\nimport { AzureClientProps, AzureContainerServices } from \"./interfaces\";\nimport { AzureAudience } from \"./AzureAudience\";\nimport {\n AzureUrlResolver,\n createAzureCreateNewRequest,\n} from \"./AzureUrlResolver\";\n\n/**\n * Strongly typed id for connecting to a local Azure Fluid Relay.\n */\nexport const LOCAL_MODE_TENANT_ID = \"local\";\n\n/**\n * AzureClient provides the ability to have a Fluid object backed by the Azure Fluid Relay or,\n * when running with local tenantId, have it be backed by a local Azure Fluid Relay instance.\n */\nexport class AzureClient {\n private readonly documentServiceFactory: IDocumentServiceFactory;\n private readonly urlResolver: IUrlResolver;\n\n /**\n * Creates a new client instance using configuration parameters.\n * @param props - Properties for initializing a new AzureClient instance\n */\n constructor(private readonly props: AzureClientProps) {\n this.urlResolver = new AzureUrlResolver();\n // The local service implementation differs from the Azure Fluid Relay in blob\n // storage format. Azure Fluid Relay supports whole summary upload. Local currently does not.\n const enableWholeSummaryUpload =\n this.props.connection.tenantId !== LOCAL_MODE_TENANT_ID;\n this.documentServiceFactory = new RouterliciousDocumentServiceFactory(\n this.props.connection.tokenProvider,\n { enableWholeSummaryUpload },\n );\n }\n\n /**\n * Creates a new detached container instance in the Azure Fluid Relay.\n * @param containerSchema - Container schema for the new container.\n * @returns New detached container instance along with associated services.\n */\n public async createContainer(\n containerSchema: ContainerSchema,\n ): Promise<{\n container: IFluidContainer;\n services: AzureContainerServices;\n }> {\n const loader = this.createLoader(containerSchema);\n\n const container = await loader.createDetachedContainer({\n package: \"no-dynamic-package\",\n config: {},\n });\n\n const rootDataObject = await requestFluidObject<RootDataObject>(\n container,\n \"/\",\n );\n const createNewRequest = createAzureCreateNewRequest(\n this.props.connection.orderer,\n this.props.connection.storage,\n this.props.connection.tenantId,\n );\n const fluidContainer = new (class extends FluidContainer {\n async attach() {\n if (this.attachState !== AttachState.Detached) {\n throw new Error(\n \"Cannot attach container. Container is not in detached state\",\n );\n }\n await container.attach(createNewRequest);\n const resolved = container.resolvedUrl;\n ensureFluidResolvedUrl(resolved);\n return resolved.id;\n }\n })(container, rootDataObject);\n\n const services = this.getContainerServices(container);\n return { container: fluidContainer, services };\n }\n\n /**\n * Accesses the existing container given its unique ID in the Azure Fluid Relay.\n * @param id - Unique ID of the container in Azure Fluid Relay.\n * @param containerSchema - Container schema used to access data objects in the container.\n * @returns Existing container instance along with associated services.\n */\n public async getContainer(\n id: string,\n containerSchema: ContainerSchema,\n ): Promise<{\n container: IFluidContainer;\n services: AzureContainerServices;\n }> {\n const loader = this.createLoader(containerSchema);\n const url = new URL(this.props.connection.orderer);\n url.searchParams.append(\"storage\", encodeURIComponent(this.props.connection.storage));\n url.searchParams.append(\"tenantId\", encodeURIComponent(this.props.connection.tenantId));\n url.searchParams.append(\"containerId\", encodeURIComponent(id));\n const container = await loader.resolve({ url: url.href });\n const rootDataObject = await requestFluidObject<RootDataObject>(\n container,\n \"/\",\n );\n const fluidContainer = new FluidContainer(container, rootDataObject);\n const services = this.getContainerServices(container);\n return { container: fluidContainer, services };\n }\n\n private getContainerServices(container: IContainer): AzureContainerServices {\n return {\n audience: new AzureAudience(container),\n };\n }\n\n private createLoader(containerSchema: ContainerSchema): Loader {\n const runtimeFactory = new DOProviderContainerRuntimeFactory(\n containerSchema,\n );\n const module = { fluidExport: runtimeFactory };\n const codeLoader = { load: async () => module };\n return new Loader({\n urlResolver: this.urlResolver,\n documentServiceFactory: this.documentServiceFactory,\n codeLoader,\n logger: this.props.logger,\n });\n }\n // #endregion\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"AzureFunctionTokenProvider.js","sourceRoot":"","sources":["../src/AzureFunctionTokenProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;;GAGG;AACH,MAAM,OAAO,0BAA0B;IACnC;;;;OAIG;IACH,YACqB,aAAqB,EACrB,IAAqE;QADrE,kBAAa,GAAb,aAAa,CAAQ;QACrB,SAAI,GAAJ,IAAI,CAAiE;IACtF,CAAC;IAEE,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAmB;QAChE,OAAO;YACH,GAAG,EAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAkB;QAC/D,OAAO;YACH,GAAG,EAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,UAA8B;;QACnE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE;YACjD,MAAM,EAAE;gBACJ,QAAQ;gBACR,UAAU;gBACV,MAAM,QAAE,IAAI,CAAC,IAAI,0CAAE,MAAM;gBACzB,QAAQ,QAAE,IAAI,CAAC,IAAI,0CAAE,QAAQ;gBAC7B,iBAAiB,QAAE,IAAI,CAAC,IAAI,0CAAE,iBAAiB;aAClD;SACJ,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAc,CAAC;IACnC,CAAC;CACJ","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITokenProvider, ITokenResponse } from \"@fluidframework/routerlicious-driver\";\nimport axios from \"axios\";\nimport { AzureMember } from \"./interfaces\";\n\n/**\n * Token Provider implementation for connecting to an Azure Function endpoint for\n * Azure Fluid Relay token resolution.\n */\nexport class AzureFunctionTokenProvider implements ITokenProvider {\n /**\n * Creates a new instance using configuration parameters.\n * @param azFunctionUrl - URL to Azure Function endpoint\n * @param user - User object\n */\n constructor(\n private readonly azFunctionUrl: string,\n private readonly user?: Pick<AzureMember, \"userId\" | \"userName\" | \"additionalDetails\">,\n ) { }\n\n public async fetchOrdererToken(tenantId: string, documentId?: string): Promise<ITokenResponse> {\n return {\n jwt: await this.getToken(tenantId, documentId),\n };\n }\n\n public async fetchStorageToken(tenantId: string, documentId: string): Promise<ITokenResponse> {\n return {\n jwt: await this.getToken(tenantId, documentId),\n };\n }\n\n private async getToken(tenantId: string, documentId: string | undefined): Promise<string> {\n const response = await axios.get(this.azFunctionUrl, {\n params: {\n tenantId,\n documentId,\n userId: this.user?.userId,\n userName: this.user?.userName,\n additionalDetails: this.user?.additionalDetails,\n },\n });\n return response.data as string;\n }\n}\n"]}
1
+ {"version":3,"file":"AzureFunctionTokenProvider.js","sourceRoot":"","sources":["../src/AzureFunctionTokenProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;;GAGG;AACH,MAAM,OAAO,0BAA0B;IACnC;;;;OAIG;IACH,YACqB,aAAqB,EACrB,IAAqE;QADrE,kBAAa,GAAb,aAAa,CAAQ;QACrB,SAAI,GAAJ,IAAI,CAAiE;IACtF,CAAC;IAEE,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAmB;QAChE,OAAO;YACH,GAAG,EAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAkB;QAC/D,OAAO;YACH,GAAG,EAAE,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,UAAmB;;QACxD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE;YACjD,MAAM,EAAE;gBACJ,QAAQ;gBACR,UAAU;gBACV,MAAM,QAAE,IAAI,CAAC,IAAI,0CAAE,MAAM;gBACzB,QAAQ,QAAE,IAAI,CAAC,IAAI,0CAAE,QAAQ;gBAC7B,iBAAiB,QAAE,IAAI,CAAC,IAAI,0CAAE,iBAAiB;aAClD;SACJ,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,IAAc,CAAC;IACnC,CAAC;CACJ","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITokenProvider, ITokenResponse } from \"@fluidframework/routerlicious-driver\";\nimport axios from \"axios\";\nimport { AzureMember } from \"./interfaces\";\n\n/**\n * Token Provider implementation for connecting to an Azure Function endpoint for\n * Azure Fluid Relay token resolution.\n */\nexport class AzureFunctionTokenProvider implements ITokenProvider {\n /**\n * Creates a new instance using configuration parameters.\n * @param azFunctionUrl - URL to Azure Function endpoint\n * @param user - User object\n */\n constructor(\n private readonly azFunctionUrl: string,\n private readonly user?: Pick<AzureMember, \"userId\" | \"userName\" | \"additionalDetails\">,\n ) { }\n\n public async fetchOrdererToken(tenantId: string, documentId?: string): Promise<ITokenResponse> {\n return {\n jwt: await this.getToken(tenantId, documentId),\n };\n }\n\n public async fetchStorageToken(tenantId: string, documentId: string): Promise<ITokenResponse> {\n return {\n jwt: await this.getToken(tenantId, documentId),\n };\n }\n\n private async getToken(tenantId: string, documentId?: string): Promise<string> {\n const response = await axios.get(this.azFunctionUrl, {\n params: {\n tenantId,\n documentId,\n userId: this.user?.userId,\n userName: this.user?.userName,\n additionalDetails: this.user?.additionalDetails,\n },\n });\n return response.data as string;\n }\n}\n"]}
@@ -5,12 +5,9 @@
5
5
  import { IRequest } from "@fluidframework/core-interfaces";
6
6
  import { IFluidResolvedUrl, IResolvedUrl, IUrlResolver } from "@fluidframework/driver-definitions";
7
7
  export declare class AzureUrlResolver implements IUrlResolver {
8
- private readonly tenantId;
9
- private readonly orderer;
10
- private readonly storage;
11
- constructor(tenantId: string, orderer: string, storage: string);
8
+ constructor();
12
9
  resolve(request: IRequest): Promise<IFluidResolvedUrl>;
13
10
  getAbsoluteUrl(resolvedUrl: IResolvedUrl, relativeUrl: string): Promise<string>;
14
11
  }
15
- export declare const createAzureCreateNewRequest: () => IRequest;
12
+ export declare const createAzureCreateNewRequest: (ordererUrl: string, storageUrl: string, tenantId: string) => IRequest;
16
13
  //# sourceMappingURL=AzureUrlResolver.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AzureUrlResolver.d.ts","sourceRoot":"","sources":["../src/AzureUrlResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EAEH,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACf,MAAM,oCAAoC,CAAC;AAM5C,qBAAa,gBAAiB,YAAW,YAAY;IAE7C,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAFP,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM;IAGvB,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAkCtD,cAAc,CAAC,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAM/F;AAED,eAAO,MAAM,2BAA2B,QAAO,QAO9C,CAAC"}
1
+ {"version":3,"file":"AzureUrlResolver.d.ts","sourceRoot":"","sources":["../src/AzureUrlResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EAEH,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACf,MAAM,oCAAoC,CAAC;AAM5C,qBAAa,gBAAiB,YAAW,YAAY;;IAGpC,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAyCtD,cAAc,CACvB,WAAW,EAAE,YAAY,EACzB,WAAW,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC;CAMrB;AAkCD,eAAO,MAAM,2BAA2B,eACxB,MAAM,cACN,MAAM,YACR,MAAM,KACjB,QAUF,CAAC"}
@@ -8,37 +8,36 @@ import { DriverHeader, } from "@fluidframework/driver-definitions";
8
8
  // InsecureTokenProvider for basic scenarios or more robust, secure providers that fulfill the
9
9
  // ITokenProvider interface
10
10
  export class AzureUrlResolver {
11
- constructor(tenantId, orderer, storage) {
12
- this.tenantId = tenantId;
13
- this.orderer = orderer;
14
- this.storage = storage;
15
- }
11
+ constructor() { }
16
12
  async resolve(request) {
13
+ const { ordererUrl, storageUrl, tenantId, containerId } = decodeAzureUrl(request.url);
17
14
  // determine whether the request is for creating of a new container.
18
15
  // such request has the `createNew` header set to true and doesn't have a container ID.
19
- if (request.headers && request.headers[DriverHeader.createNew] === true) {
16
+ if (request.headers &&
17
+ request.headers[DriverHeader.createNew] === true) {
20
18
  return {
21
19
  endpoints: {
22
- deltaStorageUrl: `${this.orderer}/deltas/${this.tenantId}/new`,
23
- ordererUrl: this.orderer,
24
- storageUrl: `${this.storage}/repos/${this.tenantId}`,
20
+ deltaStorageUrl: `${ordererUrl}/deltas/${tenantId}/new`,
21
+ ordererUrl,
22
+ storageUrl: `${storageUrl}/repos/${tenantId}`,
25
23
  },
26
24
  // id is a mandatory attribute, but it's ignored by the driver for new container requests.
27
25
  id: "",
28
26
  // tokens attribute is redundant as all tokens are generated via ITokenProvider
29
27
  tokens: {},
30
28
  type: "fluid",
31
- url: `${this.orderer}/${this.tenantId}/new`,
29
+ url: `${ordererUrl}/${tenantId}/new`,
32
30
  };
33
31
  }
34
- // for an existing container we'll parse the request URL to determine the document ID.
35
- const containerId = request.url.split("/")[0];
36
- const documentUrl = `${this.orderer}/${this.tenantId}/${containerId}`;
32
+ if (containerId === undefined) {
33
+ throw new Error("Azure URL did not contain containerId");
34
+ }
35
+ const documentUrl = `${ordererUrl}/${tenantId}/${containerId}`;
37
36
  return Promise.resolve({
38
37
  endpoints: {
39
- deltaStorageUrl: `${this.orderer}/deltas/${this.tenantId}/${containerId}`,
40
- ordererUrl: this.orderer,
41
- storageUrl: `${this.storage}/repos/${this.tenantId}`,
38
+ deltaStorageUrl: `${ordererUrl}/deltas/${tenantId}/${containerId}`,
39
+ ordererUrl,
40
+ storageUrl: `${storageUrl}/repos/${tenantId}`,
42
41
  },
43
42
  id: containerId,
44
43
  tokens: {},
@@ -53,10 +52,41 @@ export class AzureUrlResolver {
53
52
  return `${resolvedUrl.url}/${relativeUrl}`;
54
53
  }
55
54
  }
56
- export const createAzureCreateNewRequest = () => ({
57
- url: "",
58
- headers: {
59
- [DriverHeader.createNew]: true,
60
- },
61
- });
55
+ function decodeAzureUrl(urlString) {
56
+ const url = new URL(urlString);
57
+ const ordererUrl = url.origin;
58
+ const searchParams = url.searchParams;
59
+ const storageUrl = searchParams.get("storage");
60
+ // eslint-disable-next-line no-null/no-null
61
+ if (storageUrl === null) {
62
+ throw new Error("Azure URL did not contain a storage URL");
63
+ }
64
+ const tenantId = searchParams.get("tenantId");
65
+ // eslint-disable-next-line no-null/no-null
66
+ if (tenantId === null) {
67
+ throw new Error("Azure URL did not contain a tenant ID");
68
+ }
69
+ const storageUrlDecoded = decodeURIComponent(storageUrl);
70
+ const tenantIdDecoded = decodeURIComponent(tenantId);
71
+ const containerId = searchParams.get("containerId");
72
+ // eslint-disable-next-line no-null/no-null
73
+ const containerIdDecoded = containerId !== null ? decodeURIComponent(containerId) : undefined;
74
+ return {
75
+ ordererUrl,
76
+ storageUrl: storageUrlDecoded,
77
+ tenantId: tenantIdDecoded,
78
+ containerId: containerIdDecoded,
79
+ };
80
+ }
81
+ export const createAzureCreateNewRequest = (ordererUrl, storageUrl, tenantId) => {
82
+ const url = new URL(ordererUrl);
83
+ url.searchParams.append("storage", encodeURIComponent(storageUrl));
84
+ url.searchParams.append("tenantId", encodeURIComponent(tenantId));
85
+ return {
86
+ url: url.href,
87
+ headers: {
88
+ [DriverHeader.createNew]: true,
89
+ },
90
+ };
91
+ };
62
92
  //# sourceMappingURL=AzureUrlResolver.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AzureUrlResolver.js","sourceRoot":"","sources":["../src/AzureUrlResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACH,YAAY,GAIf,MAAM,oCAAoC,CAAC;AAE5C,2FAA2F;AAC3F,sFAAsF;AACtF,8FAA8F;AAC9F,2BAA2B;AAC3B,MAAM,OAAO,gBAAgB;IACzB,YACqB,QAAgB,EAChB,OAAe,EACf,OAAe;QAFf,aAAQ,GAAR,QAAQ,CAAQ;QAChB,YAAO,GAAP,OAAO,CAAQ;QACf,YAAO,GAAP,OAAO,CAAQ;IAChC,CAAC;IAEE,KAAK,CAAC,OAAO,CAAC,OAAiB;QAClC,oEAAoE;QACpE,uFAAuF;QACvF,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;YACrE,OAAO;gBACH,SAAS,EAAE;oBACP,eAAe,EAAE,GAAG,IAAI,CAAC,OAAO,WAAW,IAAI,CAAC,QAAQ,MAAM;oBAC9D,UAAU,EAAE,IAAI,CAAC,OAAO;oBACxB,UAAU,EAAE,GAAG,IAAI,CAAC,OAAO,UAAU,IAAI,CAAC,QAAQ,EAAE;iBACvD;gBACD,0FAA0F;gBAC1F,EAAE,EAAE,EAAE;gBACN,+EAA+E;gBAC/E,MAAM,EAAE,EAAE;gBACV,IAAI,EAAE,OAAO;gBACb,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,MAAM;aAC9C,CAAC;SACL;QACD,sFAAsF;QACtF,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,WAAW,GAAG,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,IAAI,WAAW,EAAE,CAAC;QACtE,OAAO,OAAO,CAAC,OAAO,CAAC;YACnB,SAAS,EAAE;gBACP,eAAe,EAAE,GAAG,IAAI,CAAC,OAAO,WAAW,IAAI,CAAC,QAAQ,IAAI,WAAW,EAAE;gBACzE,UAAU,EAAE,IAAI,CAAC,OAAO;gBACxB,UAAU,EAAE,GAAG,IAAI,CAAC,OAAO,UAAU,IAAI,CAAC,QAAQ,EAAE;aACvD;YACD,EAAE,EAAE,WAAW;YACf,MAAM,EAAE,EAAE;YACV,IAAI,EAAE,OAAO;YACb,GAAG,EAAE,WAAW;SACnB,CAAC,CAAC;IACP,CAAC;IAEM,KAAK,CAAC,cAAc,CAAC,WAAyB,EAAE,WAAmB;QACtE,IAAI,WAAW,CAAC,IAAI,KAAK,OAAO,EAAE;YAC9B,MAAM,KAAK,CAAC,sBAAsB,CAAC,CAAC;SACvC;QACD,OAAO,GAAG,WAAW,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC;IAC/C,CAAC;CACJ;AAED,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAa,EAAE,CAAC,CACvD;IACI,GAAG,EAAE,EAAE;IACP,OAAO,EAAE;QACL,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,IAAI;KACjC;CACJ,CACJ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IRequest } from \"@fluidframework/core-interfaces\";\nimport {\n DriverHeader,\n IFluidResolvedUrl,\n IResolvedUrl,\n IUrlResolver,\n} from \"@fluidframework/driver-definitions\";\n\n// Implementation of a URL resolver to resolve documents stored using the Azure Fluid Relay\n// based off of the orderer and storage URLs provide. The token provider here can be a\n// InsecureTokenProvider for basic scenarios or more robust, secure providers that fulfill the\n// ITokenProvider interface\nexport class AzureUrlResolver implements IUrlResolver {\n constructor(\n private readonly tenantId: string,\n private readonly orderer: string,\n private readonly storage: string,\n ) { }\n\n public async resolve(request: IRequest): Promise<IFluidResolvedUrl> {\n // determine whether the request is for creating of a new container.\n // such request has the `createNew` header set to true and doesn't have a container ID.\n if (request.headers && request.headers[DriverHeader.createNew] === true) {\n return {\n endpoints: {\n deltaStorageUrl: `${this.orderer}/deltas/${this.tenantId}/new`,\n ordererUrl: this.orderer,\n storageUrl: `${this.storage}/repos/${this.tenantId}`,\n },\n // id is a mandatory attribute, but it's ignored by the driver for new container requests.\n id: \"\",\n // tokens attribute is redundant as all tokens are generated via ITokenProvider\n tokens: {},\n type: \"fluid\",\n url: `${this.orderer}/${this.tenantId}/new`,\n };\n }\n // for an existing container we'll parse the request URL to determine the document ID.\n const containerId = request.url.split(\"/\")[0];\n const documentUrl = `${this.orderer}/${this.tenantId}/${containerId}`;\n return Promise.resolve({\n endpoints: {\n deltaStorageUrl: `${this.orderer}/deltas/${this.tenantId}/${containerId}`,\n ordererUrl: this.orderer,\n storageUrl: `${this.storage}/repos/${this.tenantId}`,\n },\n id: containerId,\n tokens: {},\n type: \"fluid\",\n url: documentUrl,\n });\n }\n\n public async getAbsoluteUrl(resolvedUrl: IResolvedUrl, relativeUrl: string): Promise<string> {\n if (resolvedUrl.type !== \"fluid\") {\n throw Error(\"Invalid Resolved Url\");\n }\n return `${resolvedUrl.url}/${relativeUrl}`;\n }\n}\n\nexport const createAzureCreateNewRequest = (): IRequest => (\n {\n url: \"\",\n headers: {\n [DriverHeader.createNew]: true,\n },\n }\n);\n"]}
1
+ {"version":3,"file":"AzureUrlResolver.js","sourceRoot":"","sources":["../src/AzureUrlResolver.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 { IRequest } from \"@fluidframework/core-interfaces\";\nimport {\n DriverHeader,\n IFluidResolvedUrl,\n IResolvedUrl,\n IUrlResolver,\n} from \"@fluidframework/driver-definitions\";\n\n// Implementation of a URL resolver to resolve documents stored using the Azure Fluid Relay\n// based off of the orderer and storage URLs provide. The token provider here can be a\n// InsecureTokenProvider for basic scenarios or more robust, secure providers that fulfill the\n// ITokenProvider interface\nexport class AzureUrlResolver implements IUrlResolver {\n constructor() {}\n\n public async resolve(request: IRequest): Promise<IFluidResolvedUrl> {\n const { ordererUrl, storageUrl, tenantId, containerId } = decodeAzureUrl(\n request.url,\n );\n // determine whether the request is for creating of a new container.\n // such request has the `createNew` header set to true and doesn't have a container ID.\n if (\n request.headers &&\n request.headers[DriverHeader.createNew] === true\n ) {\n return {\n endpoints: {\n deltaStorageUrl: `${ordererUrl}/deltas/${tenantId}/new`,\n ordererUrl,\n storageUrl: `${storageUrl}/repos/${tenantId}`,\n },\n // id is a mandatory attribute, but it's ignored by the driver for new container requests.\n id: \"\",\n // tokens attribute is redundant as all tokens are generated via ITokenProvider\n tokens: {},\n type: \"fluid\",\n url: `${ordererUrl}/${tenantId}/new`,\n };\n }\n if (containerId === undefined) {\n throw new Error(\"Azure URL did not contain containerId\");\n }\n const documentUrl = `${ordererUrl}/${tenantId}/${containerId}`;\n return Promise.resolve({\n endpoints: {\n deltaStorageUrl: `${ordererUrl}/deltas/${tenantId}/${containerId}`,\n ordererUrl,\n storageUrl: `${storageUrl}/repos/${tenantId}`,\n },\n id: containerId,\n tokens: {},\n type: \"fluid\",\n url: documentUrl,\n });\n }\n\n public async getAbsoluteUrl(\n resolvedUrl: IResolvedUrl,\n relativeUrl: string,\n ): Promise<string> {\n if (resolvedUrl.type !== \"fluid\") {\n throw Error(\"Invalid Resolved Url\");\n }\n return `${resolvedUrl.url}/${relativeUrl}`;\n }\n}\n\nfunction decodeAzureUrl(urlString: string): {\n ordererUrl: string;\n storageUrl: string;\n tenantId: string;\n containerId?: string,\n} {\n const url = new URL(urlString);\n const ordererUrl = url.origin;\n const searchParams = url.searchParams;\n const storageUrl = searchParams.get(\"storage\");\n // eslint-disable-next-line no-null/no-null\n if (storageUrl === null) {\n throw new Error(\"Azure URL did not contain a storage URL\");\n }\n const tenantId = searchParams.get(\"tenantId\");\n // eslint-disable-next-line no-null/no-null\n if (tenantId === null) {\n throw new Error(\"Azure URL did not contain a tenant ID\");\n }\n const storageUrlDecoded = decodeURIComponent(storageUrl);\n const tenantIdDecoded = decodeURIComponent(tenantId);\n const containerId = searchParams.get(\"containerId\");\n // eslint-disable-next-line no-null/no-null\n const containerIdDecoded = containerId !== null ? decodeURIComponent(containerId) : undefined;\n return {\n ordererUrl,\n storageUrl: storageUrlDecoded,\n tenantId: tenantIdDecoded,\n containerId: containerIdDecoded,\n };\n}\n\nexport const createAzureCreateNewRequest = (\n ordererUrl: string,\n storageUrl: string,\n tenantId: string,\n): IRequest => {\n const url = new URL(ordererUrl);\n url.searchParams.append(\"storage\", encodeURIComponent(storageUrl));\n url.searchParams.append(\"tenantId\", encodeURIComponent(tenantId));\n return {\n url: url.href,\n headers: {\n [DriverHeader.createNew]: true,\n },\n };\n};\n"]}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export declare const pkgName = "@fluidframework/azure-client";
8
- export declare const pkgVersion = "0.52.0";
8
+ export declare const pkgVersion = "0.54.0-47413";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,iCAAiC,CAAC;AACtD,eAAO,MAAM,UAAU,WAAW,CAAC"}
1
+ {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,iCAAiC,CAAC;AACtD,eAAO,MAAM,UAAU,iBAAiB,CAAC"}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export const pkgName = "@fluidframework/azure-client";
8
- export const pkgVersion = "0.52.0";
8
+ export const pkgVersion = "0.54.0-47413";
9
9
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,8BAA8B,CAAC;AACtD,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/azure-client\";\nexport const pkgVersion = \"0.52.0\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,8BAA8B,CAAC;AACtD,MAAM,CAAC,MAAM,UAAU,GAAG,cAAc,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/azure-client\";\nexport const pkgVersion = \"0.54.0-47413\";\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/azure-client",
3
- "version": "0.52.0",
3
+ "version": "0.54.0-47413",
4
4
  "description": "A tool to enable creation and loading of Fluid containers using the Azure Fluid Relay service",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": "https://github.com/microsoft/FluidFramework",
@@ -38,26 +38,26 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@fluidframework/common-definitions": "^0.20.1",
41
- "@fluidframework/container-definitions": "^0.42.0",
42
- "@fluidframework/container-loader": "^0.52.0",
41
+ "@fluidframework/container-definitions": "^0.44.0-0",
42
+ "@fluidframework/container-loader": "0.54.0-47413",
43
43
  "@fluidframework/core-interfaces": "^0.41.0",
44
- "@fluidframework/driver-definitions": "^0.42.0",
45
- "@fluidframework/driver-utils": "^0.52.0",
46
- "@fluidframework/fluid-static": "^0.52.0",
47
- "@fluidframework/map": "^0.52.0",
44
+ "@fluidframework/driver-definitions": "^0.43.0",
45
+ "@fluidframework/driver-utils": "0.54.0-47413",
46
+ "@fluidframework/fluid-static": "0.54.0-47413",
47
+ "@fluidframework/map": "0.54.0-47413",
48
48
  "@fluidframework/protocol-definitions": "^0.1026.0",
49
- "@fluidframework/routerlicious-driver": "^0.52.0",
50
- "@fluidframework/runtime-utils": "^0.52.0",
49
+ "@fluidframework/routerlicious-driver": "0.54.0-47413",
50
+ "@fluidframework/runtime-utils": "0.54.0-47413",
51
51
  "@fluidframework/server-services-client": "^0.1034.0",
52
52
  "axios": "^0.21.2",
53
53
  "uuid": "^8.3.1"
54
54
  },
55
55
  "devDependencies": {
56
- "@fluidframework/aqueduct": "^0.52.0",
56
+ "@fluidframework/aqueduct": "0.54.0-47413",
57
57
  "@fluidframework/azure-local-service": "^0.1.38773",
58
58
  "@fluidframework/build-common": "^0.23.0",
59
59
  "@fluidframework/eslint-config-fluid": "^0.24.0",
60
- "@fluidframework/test-client-utils": "^0.52.0",
60
+ "@fluidframework/test-client-utils": "0.54.0-47413",
61
61
  "@microsoft/api-extractor": "^7.16.1",
62
62
  "@types/mocha": "^8.2.2",
63
63
  "concurrently": "^6.2.0",
@@ -2,11 +2,12 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { Container, Loader } from "@fluidframework/container-loader";
5
+ import { Loader } from "@fluidframework/container-loader";
6
6
  import {
7
- IDocumentServiceFactory, IUrlResolver,
7
+ IDocumentServiceFactory,
8
+ IUrlResolver,
8
9
  } from "@fluidframework/driver-definitions";
9
- import { AttachState } from "@fluidframework/container-definitions";
10
+ import { AttachState, IContainer } from "@fluidframework/container-definitions";
10
11
  import { RouterliciousDocumentServiceFactory } from "@fluidframework/routerlicious-driver";
11
12
  import { requestFluidObject } from "@fluidframework/runtime-utils";
12
13
  import { ensureFluidResolvedUrl } from "@fluidframework/driver-utils";
@@ -18,12 +19,12 @@ import {
18
19
  RootDataObject,
19
20
  } from "@fluidframework/fluid-static";
20
21
 
21
- import {
22
- AzureClientProps,
23
- AzureContainerServices,
24
- } from "./interfaces";
22
+ import { AzureClientProps, AzureContainerServices } from "./interfaces";
25
23
  import { AzureAudience } from "./AzureAudience";
26
- import { AzureUrlResolver, createAzureCreateNewRequest } from "./AzureUrlResolver";
24
+ import {
25
+ AzureUrlResolver,
26
+ createAzureCreateNewRequest,
27
+ } from "./AzureUrlResolver";
27
28
 
28
29
  /**
29
30
  * Strongly typed id for connecting to a local Azure Fluid Relay.
@@ -43,14 +44,11 @@ export class AzureClient {
43
44
  * @param props - Properties for initializing a new AzureClient instance
44
45
  */
45
46
  constructor(private readonly props: AzureClientProps) {
46
- this.urlResolver = new AzureUrlResolver(
47
- this.props.connection.tenantId,
48
- this.props.connection.orderer,
49
- this.props.connection.storage,
50
- );
47
+ this.urlResolver = new AzureUrlResolver();
51
48
  // The local service implementation differs from the Azure Fluid Relay in blob
52
49
  // storage format. Azure Fluid Relay supports whole summary upload. Local currently does not.
53
- const enableWholeSummaryUpload = this.props.connection.tenantId !== LOCAL_MODE_TENANT_ID;
50
+ const enableWholeSummaryUpload =
51
+ this.props.connection.tenantId !== LOCAL_MODE_TENANT_ID;
54
52
  this.documentServiceFactory = new RouterliciousDocumentServiceFactory(
55
53
  this.props.connection.tokenProvider,
56
54
  { enableWholeSummaryUpload },
@@ -64,7 +62,10 @@ export class AzureClient {
64
62
  */
65
63
  public async createContainer(
66
64
  containerSchema: ContainerSchema,
67
- ): Promise<{ container: IFluidContainer; services: AzureContainerServices }> {
65
+ ): Promise<{
66
+ container: IFluidContainer;
67
+ services: AzureContainerServices;
68
+ }> {
68
69
  const loader = this.createLoader(containerSchema);
69
70
 
70
71
  const container = await loader.createDetachedContainer({
@@ -72,15 +73,23 @@ export class AzureClient {
72
73
  config: {},
73
74
  });
74
75
 
75
- const rootDataObject = await requestFluidObject<RootDataObject>(container, "/");
76
-
76
+ const rootDataObject = await requestFluidObject<RootDataObject>(
77
+ container,
78
+ "/",
79
+ );
80
+ const createNewRequest = createAzureCreateNewRequest(
81
+ this.props.connection.orderer,
82
+ this.props.connection.storage,
83
+ this.props.connection.tenantId,
84
+ );
77
85
  const fluidContainer = new (class extends FluidContainer {
78
86
  async attach() {
79
87
  if (this.attachState !== AttachState.Detached) {
80
- throw new Error("Cannot attach container. Container is not in detached state");
88
+ throw new Error(
89
+ "Cannot attach container. Container is not in detached state",
90
+ );
81
91
  }
82
- const request = createAzureCreateNewRequest();
83
- await container.attach(request);
92
+ await container.attach(createNewRequest);
84
93
  const resolved = container.resolvedUrl;
85
94
  ensureFluidResolvedUrl(resolved);
86
95
  return resolved.id;
@@ -100,26 +109,32 @@ export class AzureClient {
100
109
  public async getContainer(
101
110
  id: string,
102
111
  containerSchema: ContainerSchema,
103
- ): Promise<{ container: IFluidContainer; services: AzureContainerServices }> {
112
+ ): Promise<{
113
+ container: IFluidContainer;
114
+ services: AzureContainerServices;
115
+ }> {
104
116
  const loader = this.createLoader(containerSchema);
105
- const container = await loader.resolve({ url: id });
106
- const rootDataObject = await requestFluidObject<RootDataObject>(container, "/");
117
+ const url = new URL(this.props.connection.orderer);
118
+ url.searchParams.append("storage", encodeURIComponent(this.props.connection.storage));
119
+ url.searchParams.append("tenantId", encodeURIComponent(this.props.connection.tenantId));
120
+ url.searchParams.append("containerId", encodeURIComponent(id));
121
+ const container = await loader.resolve({ url: url.href });
122
+ const rootDataObject = await requestFluidObject<RootDataObject>(
123
+ container,
124
+ "/",
125
+ );
107
126
  const fluidContainer = new FluidContainer(container, rootDataObject);
108
127
  const services = this.getContainerServices(container);
109
128
  return { container: fluidContainer, services };
110
129
  }
111
130
 
112
- private getContainerServices(
113
- container: Container,
114
- ): AzureContainerServices {
131
+ private getContainerServices(container: IContainer): AzureContainerServices {
115
132
  return {
116
133
  audience: new AzureAudience(container),
117
134
  };
118
135
  }
119
136
 
120
- private createLoader(
121
- containerSchema: ContainerSchema,
122
- ): Loader {
137
+ private createLoader(containerSchema: ContainerSchema): Loader {
123
138
  const runtimeFactory = new DOProviderContainerRuntimeFactory(
124
139
  containerSchema,
125
140
  );
@@ -34,7 +34,7 @@ export class AzureFunctionTokenProvider implements ITokenProvider {
34
34
  };
35
35
  }
36
36
 
37
- private async getToken(tenantId: string, documentId: string | undefined): Promise<string> {
37
+ private async getToken(tenantId: string, documentId?: string): Promise<string> {
38
38
  const response = await axios.get(this.azFunctionUrl, {
39
39
  params: {
40
40
  tenantId,
@@ -16,38 +16,41 @@ import {
16
16
  // InsecureTokenProvider for basic scenarios or more robust, secure providers that fulfill the
17
17
  // ITokenProvider interface
18
18
  export class AzureUrlResolver implements IUrlResolver {
19
- constructor(
20
- private readonly tenantId: string,
21
- private readonly orderer: string,
22
- private readonly storage: string,
23
- ) { }
19
+ constructor() {}
24
20
 
25
21
  public async resolve(request: IRequest): Promise<IFluidResolvedUrl> {
22
+ const { ordererUrl, storageUrl, tenantId, containerId } = decodeAzureUrl(
23
+ request.url,
24
+ );
26
25
  // determine whether the request is for creating of a new container.
27
26
  // such request has the `createNew` header set to true and doesn't have a container ID.
28
- if (request.headers && request.headers[DriverHeader.createNew] === true) {
27
+ if (
28
+ request.headers &&
29
+ request.headers[DriverHeader.createNew] === true
30
+ ) {
29
31
  return {
30
32
  endpoints: {
31
- deltaStorageUrl: `${this.orderer}/deltas/${this.tenantId}/new`,
32
- ordererUrl: this.orderer,
33
- storageUrl: `${this.storage}/repos/${this.tenantId}`,
33
+ deltaStorageUrl: `${ordererUrl}/deltas/${tenantId}/new`,
34
+ ordererUrl,
35
+ storageUrl: `${storageUrl}/repos/${tenantId}`,
34
36
  },
35
37
  // id is a mandatory attribute, but it's ignored by the driver for new container requests.
36
38
  id: "",
37
39
  // tokens attribute is redundant as all tokens are generated via ITokenProvider
38
40
  tokens: {},
39
41
  type: "fluid",
40
- url: `${this.orderer}/${this.tenantId}/new`,
42
+ url: `${ordererUrl}/${tenantId}/new`,
41
43
  };
42
44
  }
43
- // for an existing container we'll parse the request URL to determine the document ID.
44
- const containerId = request.url.split("/")[0];
45
- const documentUrl = `${this.orderer}/${this.tenantId}/${containerId}`;
45
+ if (containerId === undefined) {
46
+ throw new Error("Azure URL did not contain containerId");
47
+ }
48
+ const documentUrl = `${ordererUrl}/${tenantId}/${containerId}`;
46
49
  return Promise.resolve({
47
50
  endpoints: {
48
- deltaStorageUrl: `${this.orderer}/deltas/${this.tenantId}/${containerId}`,
49
- ordererUrl: this.orderer,
50
- storageUrl: `${this.storage}/repos/${this.tenantId}`,
51
+ deltaStorageUrl: `${ordererUrl}/deltas/${tenantId}/${containerId}`,
52
+ ordererUrl,
53
+ storageUrl: `${storageUrl}/repos/${tenantId}`,
51
54
  },
52
55
  id: containerId,
53
56
  tokens: {},
@@ -56,7 +59,10 @@ export class AzureUrlResolver implements IUrlResolver {
56
59
  });
57
60
  }
58
61
 
59
- public async getAbsoluteUrl(resolvedUrl: IResolvedUrl, relativeUrl: string): Promise<string> {
62
+ public async getAbsoluteUrl(
63
+ resolvedUrl: IResolvedUrl,
64
+ relativeUrl: string,
65
+ ): Promise<string> {
60
66
  if (resolvedUrl.type !== "fluid") {
61
67
  throw Error("Invalid Resolved Url");
62
68
  }
@@ -64,11 +70,50 @@ export class AzureUrlResolver implements IUrlResolver {
64
70
  }
65
71
  }
66
72
 
67
- export const createAzureCreateNewRequest = (): IRequest => (
68
- {
69
- url: "",
73
+ function decodeAzureUrl(urlString: string): {
74
+ ordererUrl: string;
75
+ storageUrl: string;
76
+ tenantId: string;
77
+ containerId?: string,
78
+ } {
79
+ const url = new URL(urlString);
80
+ const ordererUrl = url.origin;
81
+ const searchParams = url.searchParams;
82
+ const storageUrl = searchParams.get("storage");
83
+ // eslint-disable-next-line no-null/no-null
84
+ if (storageUrl === null) {
85
+ throw new Error("Azure URL did not contain a storage URL");
86
+ }
87
+ const tenantId = searchParams.get("tenantId");
88
+ // eslint-disable-next-line no-null/no-null
89
+ if (tenantId === null) {
90
+ throw new Error("Azure URL did not contain a tenant ID");
91
+ }
92
+ const storageUrlDecoded = decodeURIComponent(storageUrl);
93
+ const tenantIdDecoded = decodeURIComponent(tenantId);
94
+ const containerId = searchParams.get("containerId");
95
+ // eslint-disable-next-line no-null/no-null
96
+ const containerIdDecoded = containerId !== null ? decodeURIComponent(containerId) : undefined;
97
+ return {
98
+ ordererUrl,
99
+ storageUrl: storageUrlDecoded,
100
+ tenantId: tenantIdDecoded,
101
+ containerId: containerIdDecoded,
102
+ };
103
+ }
104
+
105
+ export const createAzureCreateNewRequest = (
106
+ ordererUrl: string,
107
+ storageUrl: string,
108
+ tenantId: string,
109
+ ): IRequest => {
110
+ const url = new URL(ordererUrl);
111
+ url.searchParams.append("storage", encodeURIComponent(storageUrl));
112
+ url.searchParams.append("tenantId", encodeURIComponent(tenantId));
113
+ return {
114
+ url: url.href,
70
115
  headers: {
71
116
  [DriverHeader.createNew]: true,
72
117
  },
73
- }
74
- );
118
+ };
119
+ };
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/azure-client";
9
- export const pkgVersion = "0.52.0";
9
+ export const pkgVersion = "0.54.0-47413";