@fluidframework/tinylicious-driver 0.47.1 → 0.48.0-38105

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.
@@ -8,7 +8,7 @@ import { ITokenProvider, ITokenResponse } from "@fluidframework/routerlicious-dr
8
8
  * to get up and running.
9
9
  */
10
10
  export declare class InsecureTinyliciousTokenProvider implements ITokenProvider {
11
- fetchOrdererToken(tenantId: string, documentId: string): Promise<ITokenResponse>;
11
+ fetchOrdererToken(tenantId: string, documentId?: string): Promise<ITokenResponse>;
12
12
  fetchStorageToken(tenantId: string, documentId: string): Promise<ITokenResponse>;
13
13
  private getSignedToken;
14
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"insecureTinyliciousTokenProvider.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAKtF;;;GAGG;AACH,qBAAa,gCAAiC,YAAW,cAAc;IACtD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAOhF,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAO7F,OAAO,CAAC,cAAc;CAuBzB"}
1
+ {"version":3,"file":"insecureTinyliciousTokenProvider.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAKtF;;;GAGG;AACH,qBAAa,gCAAiC,YAAW,cAAc;IACtD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAOjF,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAO7F,OAAO,CAAC,cAAc;CAuBzB"}
@@ -31,7 +31,7 @@ class InsecureTinyliciousTokenProvider {
31
31
  const now = Math.round((new Date()).getTime() / 1000);
32
32
  const user = { id: uuid_1.v4(), name: server_services_client_1.getRandomName() };
33
33
  const claims = {
34
- documentId,
34
+ documentId: documentId !== null && documentId !== void 0 ? documentId : "",
35
35
  scopes: [protocol_definitions_1.ScopeType.DocRead, protocol_definitions_1.ScopeType.DocWrite, protocol_definitions_1.ScopeType.SummaryWrite],
36
36
  tenantId,
37
37
  user,
@@ -1 +1 @@
1
- {"version":3,"file":"insecureTinyliciousTokenProvider.js","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+EAA+E;AAE/E,mFAAuE;AACvE,yCAA8C;AAC9C,+BAAkC;AAElC;;;GAGG;AACH,MAAa,gCAAgC;IAClC,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAkB;QAC/D,OAAO;YACH,SAAS,EAAE,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAkB;QAC/D,OAAO;YACH,SAAS,EAAE,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEO,cAAc,CAClB,QAAgB,EAChB,UAAkB,EAClB,WAAmB,EAAE,GAAG,EAAE,EAC1B,MAAc,KAAK;QACnB,0BAA0B;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,SAAI,EAAE,EAAE,IAAI,EAAE,sCAAa,EAAE,EAAE,CAAC;QAEnD,MAAM,MAAM,GAAiB;YACzB,UAAU;YACV,MAAM,EAAE,CAAC,gCAAS,CAAC,OAAO,EAAE,gCAAS,CAAC,QAAQ,EAAE,gCAAS,CAAC,YAAY,CAAC;YACvE,QAAQ;YACR,IAAI;YACJ,GAAG,EAAE,GAAG;YACR,GAAG,EAAE,GAAG,GAAG,QAAQ;YACnB,GAAG;SACN,CAAC;QAEF,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAClC,2CAA2C;QAC3C,OAAO,gBAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACtG,CAAC;CACJ;AAtCD,4EAsCC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ScopeType, ITokenClaims } from \"@fluidframework/protocol-definitions\";\nimport { ITokenProvider, ITokenResponse } from \"@fluidframework/routerlicious-driver\";\nimport { getRandomName } from \"@fluidframework/server-services-client\";\nimport { KJUR as jsrsasign } from \"jsrsasign\";\nimport { v4 as uuid } from \"uuid\";\n\n/**\n * As the name implies this is not secure and should not be used in production. It simply makes the example easier\n * to get up and running.\n */\nexport class InsecureTinyliciousTokenProvider implements ITokenProvider {\n public async fetchOrdererToken(tenantId: string, documentId: string): Promise<ITokenResponse> {\n return {\n fromCache: true,\n jwt: this.getSignedToken(tenantId, documentId),\n };\n }\n\n public async fetchStorageToken(tenantId: string, documentId: string): Promise<ITokenResponse> {\n return {\n fromCache: true,\n jwt: this.getSignedToken(tenantId, documentId),\n };\n }\n\n private getSignedToken(\n tenantId: string,\n documentId: string,\n lifetime: number = 60 * 60,\n ver: string = \"1.0\"): string {\n // Current time in seconds\n const now = Math.round((new Date()).getTime() / 1000);\n const user = { id: uuid(), name: getRandomName() };\n\n const claims: ITokenClaims = {\n documentId,\n scopes: [ScopeType.DocRead, ScopeType.DocWrite, ScopeType.SummaryWrite],\n tenantId,\n user,\n iat: now,\n exp: now + lifetime,\n ver,\n };\n\n const utf8Key = { utf8: \"12345\" };\n // eslint-disable-next-line no-null/no-null\n return jsrsasign.jws.JWS.sign(null, JSON.stringify({ alg:\"HS256\", typ: \"JWT\" }), claims, utf8Key);\n }\n}\n"]}
1
+ {"version":3,"file":"insecureTinyliciousTokenProvider.js","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+EAA+E;AAE/E,mFAAuE;AACvE,yCAA8C;AAC9C,+BAAkC;AAElC;;;GAGG;AACH,MAAa,gCAAgC;IAClC,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAmB;QAChE,OAAO;YACH,SAAS,EAAE,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAkB;QAC/D,OAAO;YACH,SAAS,EAAE,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEO,cAAc,CAClB,QAAgB,EAChB,UAA8B,EAC9B,WAAmB,EAAE,GAAG,EAAE,EAC1B,MAAc,KAAK;QACnB,0BAA0B;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,SAAI,EAAE,EAAE,IAAI,EAAE,sCAAa,EAAE,EAAE,CAAC;QAEnD,MAAM,MAAM,GAAiB;YACzB,UAAU,EAAE,UAAU,aAAV,UAAU,cAAV,UAAU,GAAI,EAAE;YAC5B,MAAM,EAAE,CAAC,gCAAS,CAAC,OAAO,EAAE,gCAAS,CAAC,QAAQ,EAAE,gCAAS,CAAC,YAAY,CAAC;YACvE,QAAQ;YACR,IAAI;YACJ,GAAG,EAAE,GAAG;YACR,GAAG,EAAE,GAAG,GAAG,QAAQ;YACnB,GAAG;SACN,CAAC;QAEF,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAClC,2CAA2C;QAC3C,OAAO,gBAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACtG,CAAC;CACJ;AAtCD,4EAsCC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ScopeType, ITokenClaims } from \"@fluidframework/protocol-definitions\";\nimport { ITokenProvider, ITokenResponse } from \"@fluidframework/routerlicious-driver\";\nimport { getRandomName } from \"@fluidframework/server-services-client\";\nimport { KJUR as jsrsasign } from \"jsrsasign\";\nimport { v4 as uuid } from \"uuid\";\n\n/**\n * As the name implies this is not secure and should not be used in production. It simply makes the example easier\n * to get up and running.\n */\nexport class InsecureTinyliciousTokenProvider implements ITokenProvider {\n public async fetchOrdererToken(tenantId: string, documentId?: string): Promise<ITokenResponse> {\n return {\n fromCache: true,\n jwt: this.getSignedToken(tenantId, documentId),\n };\n }\n\n public async fetchStorageToken(tenantId: string, documentId: string): Promise<ITokenResponse> {\n return {\n fromCache: true,\n jwt: this.getSignedToken(tenantId, documentId),\n };\n }\n\n private getSignedToken(\n tenantId: string,\n documentId: string | undefined,\n lifetime: number = 60 * 60,\n ver: string = \"1.0\"): string {\n // Current time in seconds\n const now = Math.round((new Date()).getTime() / 1000);\n const user = { id: uuid(), name: getRandomName() };\n\n const claims: ITokenClaims = {\n documentId: documentId ?? \"\",\n scopes: [ScopeType.DocRead, ScopeType.DocWrite, ScopeType.SummaryWrite],\n tenantId,\n user,\n iat: now,\n exp: now + lifetime,\n ver,\n };\n\n const utf8Key = { utf8: \"12345\" };\n // eslint-disable-next-line no-null/no-null\n return jsrsasign.jws.JWS.sign(null, JSON.stringify({ alg:\"HS256\", typ: \"JWT\" }), claims, utf8Key);\n }\n}\n"]}
@@ -13,13 +13,11 @@ export declare const defaultTinyliciousEndpoint = "http://localhost";
13
13
  * documentId/containerRelativePathing
14
14
  */
15
15
  export declare class InsecureTinyliciousUrlResolver implements IUrlResolver {
16
- private readonly tinyliciousPort;
17
- private readonly tinyliciousEndpoint;
18
16
  private readonly fluidProtocolEndpoint;
19
- constructor(tinyliciousPort?: number, tinyliciousEndpoint?: string);
17
+ private readonly tinyliciousEndpoint;
18
+ constructor(port?: number, endpoint?: string);
20
19
  resolve(request: IRequest): Promise<IResolvedUrl>;
21
20
  getAbsoluteUrl(resolvedUrl: IFluidResolvedUrl, relativeUrl: string): Promise<string>;
22
- private auth;
23
21
  }
24
- export declare const createTinyliciousCreateNewRequest: (documentId: string) => IRequest;
22
+ export declare const createTinyliciousCreateNewRequest: (documentId?: string | undefined) => IRequest;
25
23
  //# sourceMappingURL=insecureTinyliciousUrlResolver.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"insecureTinyliciousUrlResolver.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EACH,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACf,MAAM,oCAAoC,CAAC;AAK5C,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,0BAA0B,qBAAqB,CAAC;AAE7D;;;;;GAKG;AACH,qBAAa,8BAA+B,YAAW,YAAY;IAG3D,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IAHxC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;gBAE1B,eAAe,SAAyB,EACxC,mBAAmB,SAA6B;IAKxD,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IA0BjD,cAAc,CAAC,WAAW,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAajG,OAAO,CAAC,IAAI;CAef;AAED,eAAO,MAAM,iCAAiC,eAC7B,MAAM,KAAG,QAOrB,CAAC"}
1
+ {"version":3,"file":"insecureTinyliciousUrlResolver.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.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;AAE5C,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,0BAA0B,qBAAqB,CAAC;AAE7D;;;;;GAKG;AACH,qBAAa,8BAA+B,YAAW,YAAY;IAC/D,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;gBAEzC,IAAI,SAAyB,EAC7B,QAAQ,SAA6B;IAM5B,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IA6CjD,cAAc,CAAC,WAAW,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAYpG;AAED,eAAO,MAAM,iCAAiC,uCACnB,QAOtB,CAAC"}
@@ -5,8 +5,7 @@
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.createTinyliciousCreateNewRequest = exports.InsecureTinyliciousUrlResolver = exports.defaultTinyliciousEndpoint = exports.defaultTinyliciousPort = void 0;
8
- const jsrsasign_1 = require("jsrsasign");
9
- const uuid_1 = require("uuid");
8
+ const driver_definitions_1 = require("@fluidframework/driver-definitions");
10
9
  exports.defaultTinyliciousPort = 7070;
11
10
  exports.defaultTinyliciousEndpoint = "http://localhost";
12
11
  /**
@@ -16,35 +15,51 @@ exports.defaultTinyliciousEndpoint = "http://localhost";
16
15
  * documentId/containerRelativePathing
17
16
  */
18
17
  class InsecureTinyliciousUrlResolver {
19
- constructor(tinyliciousPort = exports.defaultTinyliciousPort, tinyliciousEndpoint = exports.defaultTinyliciousEndpoint) {
20
- this.tinyliciousPort = tinyliciousPort;
21
- this.tinyliciousEndpoint = tinyliciousEndpoint;
18
+ constructor(port = exports.defaultTinyliciousPort, endpoint = exports.defaultTinyliciousEndpoint) {
19
+ this.tinyliciousEndpoint = `${endpoint}:${port}`;
22
20
  this.fluidProtocolEndpoint = this.tinyliciousEndpoint.replace(/(^\w+:|^)\/\//, "fluid://");
23
21
  }
24
22
  async resolve(request) {
25
- const url = request.url.replace(`${this.tinyliciousEndpoint}:${this.tinyliciousPort}/`, "");
23
+ // determine whether the request is for creating of a new container.
24
+ // such request has the `createNew` header set to true and doesn't have a container ID.
25
+ if (request.headers && request.headers[driver_definitions_1.DriverHeader.createNew] === true) {
26
+ return {
27
+ endpoints: {
28
+ deltaStorageUrl: `${this.tinyliciousEndpoint}/deltas/tinylicious/new`,
29
+ ordererUrl: this.tinyliciousEndpoint,
30
+ storageUrl: `${this.tinyliciousEndpoint}/repos/tinylicious`,
31
+ },
32
+ // id is a mandatory attribute, but it's ignored by the driver for new container requests.
33
+ id: "",
34
+ // tokens attribute is redundant as all tokens are generated via ITokenProvider
35
+ tokens: {},
36
+ type: "fluid",
37
+ url: `${this.fluidProtocolEndpoint}/tinylicious/new`,
38
+ };
39
+ }
40
+ // for an existing container we'll parse the request URL to determine the document ID.
41
+ const url = request.url.replace(`${this.tinyliciousEndpoint}/`, "");
26
42
  const documentId = url.split("/")[0];
27
43
  const encodedDocId = encodeURIComponent(documentId);
28
44
  const documentRelativePath = url.slice(documentId.length);
29
- // eslint-disable-next-line max-len
30
- const documentUrl = `${this.fluidProtocolEndpoint}:${this.tinyliciousPort}/tinylicious/${encodedDocId}${documentRelativePath}`;
31
- const deltaStorageUrl = `${this.tinyliciousEndpoint}:${this.tinyliciousPort}/deltas/tinylicious/${encodedDocId}`;
32
- const storageUrl = `${this.tinyliciousEndpoint}:${this.tinyliciousPort}/repos/tinylicious`;
45
+ const documentUrl = `${this.fluidProtocolEndpoint}/tinylicious/${encodedDocId}${documentRelativePath}`;
46
+ const deltaStorageUrl = `${this.tinyliciousEndpoint}/deltas/tinylicious/${encodedDocId}`;
47
+ const storageUrl = `${this.tinyliciousEndpoint}/repos/tinylicious`;
33
48
  const response = {
34
49
  endpoints: {
35
50
  deltaStorageUrl,
36
- ordererUrl: `${this.tinyliciousEndpoint}:${this.tinyliciousPort}`,
51
+ ordererUrl: this.tinyliciousEndpoint,
37
52
  storageUrl,
38
53
  },
39
54
  id: documentId,
40
- tokens: { jwt: this.auth(documentId) },
55
+ tokens: {},
41
56
  type: "fluid",
42
57
  url: documentUrl,
43
58
  };
44
59
  return response;
45
60
  }
46
61
  async getAbsoluteUrl(resolvedUrl, relativeUrl) {
47
- const documentId = decodeURIComponent(resolvedUrl.url.replace(`${this.fluidProtocolEndpoint}:${this.tinyliciousPort}/tinylicious/`, ""));
62
+ const documentId = decodeURIComponent(resolvedUrl.url.replace(`${this.fluidProtocolEndpoint}/tinylicious/`, ""));
48
63
  /*
49
64
  * The detached container flow will ultimately call getAbsoluteUrl() with the resolved.url produced by
50
65
  * resolve(). The container expects getAbsoluteUrl's return value to be a URL that can then be roundtripped
@@ -53,26 +68,12 @@ class InsecureTinyliciousUrlResolver {
53
68
  */
54
69
  return `${documentId}/${relativeUrl}`;
55
70
  }
56
- auth(documentId) {
57
- const claims = {
58
- documentId,
59
- scopes: ["doc:read", "doc:write", "summary:write"],
60
- tenantId: "tinylicious",
61
- user: { id: uuid_1.v4() },
62
- iat: Math.round(new Date().getTime() / 1000),
63
- exp: Math.round(new Date().getTime() / 1000) + 60 * 60,
64
- ver: "1.0",
65
- };
66
- const utf8Key = { utf8: "12345" };
67
- // eslint-disable-next-line no-null/no-null
68
- return jsrsasign_1.KJUR.jws.JWS.sign(null, JSON.stringify({ alg: "HS256", typ: "JWT" }), claims, utf8Key);
69
- }
70
71
  }
71
72
  exports.InsecureTinyliciousUrlResolver = InsecureTinyliciousUrlResolver;
72
73
  const createTinyliciousCreateNewRequest = (documentId) => ({
73
- url: documentId,
74
+ url: documentId !== null && documentId !== void 0 ? documentId : "",
74
75
  headers: {
75
- createNew: true,
76
+ [driver_definitions_1.DriverHeader.createNew]: true,
76
77
  },
77
78
  });
78
79
  exports.createTinyliciousCreateNewRequest = createTinyliciousCreateNewRequest;
@@ -1 +1 @@
1
- {"version":3,"file":"insecureTinyliciousUrlResolver.js","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.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 IFluidResolvedUrl,\n IResolvedUrl,\n IUrlResolver,\n} from \"@fluidframework/driver-definitions\";\nimport { ITokenClaims } from \"@fluidframework/protocol-definitions\";\nimport { KJUR as jsrsasign } from \"jsrsasign\";\nimport { v4 as uuid } from \"uuid\";\n\nexport const defaultTinyliciousPort = 7070;\nexport const defaultTinyliciousEndpoint = \"http://localhost\";\n\n/**\n * InsecureTinyliciousUrlResolver knows how to get the URLs to the service (in this case Tinylicious) to use\n * for a given request. This particular implementation has a goal to avoid imposing requirements on the app's\n * URL shape, so it expects the request url to have this format (as opposed to a more traditional URL):\n * documentId/containerRelativePathing\n */\nexport class InsecureTinyliciousUrlResolver implements IUrlResolver {\n private readonly fluidProtocolEndpoint: string;\n public constructor(\n private readonly tinyliciousPort = defaultTinyliciousPort,\n private readonly tinyliciousEndpoint = defaultTinyliciousEndpoint,\n ) {\n this.fluidProtocolEndpoint = this.tinyliciousEndpoint.replace(/(^\\w+:|^)\\/\\//, \"fluid://\");\n }\n\n public async resolve(request: IRequest): Promise<IResolvedUrl> {\n const url = request.url.replace(`${this.tinyliciousEndpoint}:${this.tinyliciousPort}/`, \"\");\n const documentId = url.split(\"/\")[0];\n const encodedDocId = encodeURIComponent(documentId);\n const documentRelativePath = url.slice(documentId.length);\n\n // eslint-disable-next-line max-len\n const documentUrl = `${this.fluidProtocolEndpoint}:${this.tinyliciousPort}/tinylicious/${encodedDocId}${documentRelativePath}`;\n const deltaStorageUrl =\n `${this.tinyliciousEndpoint}:${this.tinyliciousPort}/deltas/tinylicious/${encodedDocId}`;\n const storageUrl = `${this.tinyliciousEndpoint}:${this.tinyliciousPort}/repos/tinylicious`;\n\n const response: IFluidResolvedUrl = {\n endpoints: {\n deltaStorageUrl,\n ordererUrl: `${this.tinyliciousEndpoint}:${this.tinyliciousPort}`,\n storageUrl,\n },\n id: documentId,\n tokens: { jwt: this.auth(documentId) },\n type: \"fluid\",\n url: documentUrl,\n };\n return response;\n }\n\n public async getAbsoluteUrl(resolvedUrl: IFluidResolvedUrl, relativeUrl: string): Promise<string> {\n const documentId = decodeURIComponent(\n resolvedUrl.url.replace(`${this.fluidProtocolEndpoint}:${this.tinyliciousPort}/tinylicious/`, \"\"),\n );\n /*\n * The detached container flow will ultimately call getAbsoluteUrl() with the resolved.url produced by\n * resolve(). The container expects getAbsoluteUrl's return value to be a URL that can then be roundtripped\n * back through resolve() again, and get the same result again. So we'll return a \"URL\" with the same format\n * described above.\n */\n return `${documentId}/${relativeUrl}`;\n }\n\n private auth(documentId: string) {\n const claims: ITokenClaims = {\n documentId,\n scopes: [\"doc:read\", \"doc:write\", \"summary:write\"],\n tenantId: \"tinylicious\",\n user: { id: uuid() },\n iat: Math.round(new Date().getTime() / 1000),\n exp: Math.round(new Date().getTime() / 1000) + 60 * 60, // 1 hour expiration\n ver: \"1.0\",\n };\n\n const utf8Key = { utf8: \"12345\" };\n // eslint-disable-next-line no-null/no-null\n return jsrsasign.jws.JWS.sign(null, JSON.stringify({ alg: \"HS256\", typ: \"JWT\" }), claims, utf8Key);\n }\n}\n\nexport const createTinyliciousCreateNewRequest =\n (documentId: string): IRequest => (\n {\n url: documentId,\n headers: {\n createNew: true,\n },\n }\n );\n"]}
1
+ {"version":3,"file":"insecureTinyliciousUrlResolver.js","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,2EAK4C;AAE/B,QAAA,sBAAsB,GAAG,IAAI,CAAC;AAC9B,QAAA,0BAA0B,GAAG,kBAAkB,CAAC;AAE7D;;;;;GAKG;AACH,MAAa,8BAA8B;IAGvC,YACI,IAAI,GAAG,8BAAsB,EAC7B,QAAQ,GAAG,kCAA0B;QAErC,IAAI,CAAC,mBAAmB,GAAG,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC;QACjD,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;IAC/F,CAAC;IAEM,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,mBAAmB,yBAAyB;oBACrE,UAAU,EAAE,IAAI,CAAC,mBAAmB;oBACpC,UAAU,EAAE,GAAG,IAAI,CAAC,mBAAmB,oBAAoB;iBAC9D;gBACD,0FAA0F;gBAC1F,EAAE,EAAE,EAAE;gBACN,+EAA+E;gBAC/E,MAAM,EAAE,EAAE;gBACV,IAAI,EAAE,OAAO;gBACb,GAAG,EAAE,GAAG,IAAI,CAAC,qBAAqB,kBAAkB;aACvD,CAAC;SACL;QACD,sFAAsF;QACtF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,mBAAmB,GAAG,EAAE,EAAE,CAAC,CAAC;QACpE,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,YAAY,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;QACpD,MAAM,oBAAoB,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAE1D,MAAM,WAAW,GACb,GAAG,IAAI,CAAC,qBAAqB,gBAAgB,YAAY,GAAG,oBAAoB,EAAE,CAAC;QACvF,MAAM,eAAe,GACjB,GAAG,IAAI,CAAC,mBAAmB,uBAAuB,YAAY,EAAE,CAAC;QACrE,MAAM,UAAU,GACZ,GAAG,IAAI,CAAC,mBAAmB,oBAAoB,CAAC;QAEpD,MAAM,QAAQ,GAAsB;YAChC,SAAS,EAAE;gBACP,eAAe;gBACf,UAAU,EAAE,IAAI,CAAC,mBAAmB;gBACpC,UAAU;aACb;YACD,EAAE,EAAE,UAAU;YACd,MAAM,EAAE,EAAE;YACV,IAAI,EAAE,OAAO;YACb,GAAG,EAAE,WAAW;SACnB,CAAC;QACF,OAAO,QAAQ,CAAC;IACpB,CAAC;IAEM,KAAK,CAAC,cAAc,CAAC,WAA8B,EAAE,WAAmB;QAC3E,MAAM,UAAU,GAAG,kBAAkB,CACjC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,qBAAqB,eAAe,EAAE,EAAE,CAAC,CAC5E,CAAC;QACF;;;;;WAKG;QACH,OAAO,GAAG,UAAU,IAAI,WAAW,EAAE,CAAC;IAC1C,CAAC;CACJ;AApED,wEAoEC;AAEM,MAAM,iCAAiC,GAC1C,CAAC,UAAmB,EAAY,EAAE,CAAC,CAC/B;IACI,GAAG,EAAE,UAAU,aAAV,UAAU,cAAV,UAAU,GAAI,EAAE;IACrB,OAAO,EAAE;QACL,CAAC,iCAAY,CAAC,SAAS,CAAC,EAAE,IAAI;KACjC;CACJ,CACJ,CAAC;AARO,QAAA,iCAAiC,qCAQxC","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\nexport const defaultTinyliciousPort = 7070;\nexport const defaultTinyliciousEndpoint = \"http://localhost\";\n\n/**\n * InsecureTinyliciousUrlResolver knows how to get the URLs to the service (in this case Tinylicious) to use\n * for a given request. This particular implementation has a goal to avoid imposing requirements on the app's\n * URL shape, so it expects the request url to have this format (as opposed to a more traditional URL):\n * documentId/containerRelativePathing\n */\nexport class InsecureTinyliciousUrlResolver implements IUrlResolver {\n private readonly fluidProtocolEndpoint: string;\n private readonly tinyliciousEndpoint: string;\n public constructor(\n port = defaultTinyliciousPort,\n endpoint = defaultTinyliciousEndpoint,\n ) {\n this.tinyliciousEndpoint = `${endpoint}:${port}`;\n this.fluidProtocolEndpoint = this.tinyliciousEndpoint.replace(/(^\\w+:|^)\\/\\//, \"fluid://\");\n }\n\n public async resolve(request: IRequest): Promise<IResolvedUrl> {\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.tinyliciousEndpoint}/deltas/tinylicious/new`,\n ordererUrl: this.tinyliciousEndpoint,\n storageUrl: `${this.tinyliciousEndpoint}/repos/tinylicious`,\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.fluidProtocolEndpoint}/tinylicious/new`,\n };\n }\n // for an existing container we'll parse the request URL to determine the document ID.\n const url = request.url.replace(`${this.tinyliciousEndpoint}/`, \"\");\n const documentId = url.split(\"/\")[0];\n const encodedDocId = encodeURIComponent(documentId);\n const documentRelativePath = url.slice(documentId.length);\n\n const documentUrl =\n `${this.fluidProtocolEndpoint}/tinylicious/${encodedDocId}${documentRelativePath}`;\n const deltaStorageUrl =\n `${this.tinyliciousEndpoint}/deltas/tinylicious/${encodedDocId}`;\n const storageUrl =\n `${this.tinyliciousEndpoint}/repos/tinylicious`;\n\n const response: IFluidResolvedUrl = {\n endpoints: {\n deltaStorageUrl,\n ordererUrl: this.tinyliciousEndpoint,\n storageUrl,\n },\n id: documentId,\n tokens: {},\n type: \"fluid\",\n url: documentUrl,\n };\n return response;\n }\n\n public async getAbsoluteUrl(resolvedUrl: IFluidResolvedUrl, relativeUrl: string): Promise<string> {\n const documentId = decodeURIComponent(\n resolvedUrl.url.replace(`${this.fluidProtocolEndpoint}/tinylicious/`, \"\"),\n );\n /*\n * The detached container flow will ultimately call getAbsoluteUrl() with the resolved.url produced by\n * resolve(). The container expects getAbsoluteUrl's return value to be a URL that can then be roundtripped\n * back through resolve() again, and get the same result again. So we'll return a \"URL\" with the same format\n * described above.\n */\n return `${documentId}/${relativeUrl}`;\n }\n}\n\nexport const createTinyliciousCreateNewRequest =\n (documentId?: string): IRequest => (\n {\n url: documentId ?? \"\",\n headers: {\n [DriverHeader.createNew]: true,\n },\n }\n );\n"]}
@@ -8,7 +8,7 @@ import { ITokenProvider, ITokenResponse } from "@fluidframework/routerlicious-dr
8
8
  * to get up and running.
9
9
  */
10
10
  export declare class InsecureTinyliciousTokenProvider implements ITokenProvider {
11
- fetchOrdererToken(tenantId: string, documentId: string): Promise<ITokenResponse>;
11
+ fetchOrdererToken(tenantId: string, documentId?: string): Promise<ITokenResponse>;
12
12
  fetchStorageToken(tenantId: string, documentId: string): Promise<ITokenResponse>;
13
13
  private getSignedToken;
14
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"insecureTinyliciousTokenProvider.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAKtF;;;GAGG;AACH,qBAAa,gCAAiC,YAAW,cAAc;IACtD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAOhF,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAO7F,OAAO,CAAC,cAAc;CAuBzB"}
1
+ {"version":3,"file":"insecureTinyliciousTokenProvider.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAKtF;;;GAGG;AACH,qBAAa,gCAAiC,YAAW,cAAc;IACtD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAOjF,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAO7F,OAAO,CAAC,cAAc;CAuBzB"}
@@ -28,7 +28,7 @@ export class InsecureTinyliciousTokenProvider {
28
28
  const now = Math.round((new Date()).getTime() / 1000);
29
29
  const user = { id: uuid(), name: getRandomName() };
30
30
  const claims = {
31
- documentId,
31
+ documentId: documentId !== null && documentId !== void 0 ? documentId : "",
32
32
  scopes: [ScopeType.DocRead, ScopeType.DocWrite, ScopeType.SummaryWrite],
33
33
  tenantId,
34
34
  user,
@@ -1 +1 @@
1
- {"version":3,"file":"insecureTinyliciousTokenProvider.js","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAgB,MAAM,sCAAsC,CAAC;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AACvE,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC;AAElC;;;GAGG;AACH,MAAM,OAAO,gCAAgC;IAClC,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAkB;QAC/D,OAAO;YACH,SAAS,EAAE,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAkB;QAC/D,OAAO;YACH,SAAS,EAAE,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEO,cAAc,CAClB,QAAgB,EAChB,UAAkB,EAClB,WAAmB,EAAE,GAAG,EAAE,EAC1B,MAAc,KAAK;QACnB,0BAA0B;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,CAAC;QAEnD,MAAM,MAAM,GAAiB;YACzB,UAAU;YACV,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,QAAQ,EAAE,SAAS,CAAC,YAAY,CAAC;YACvE,QAAQ;YACR,IAAI;YACJ,GAAG,EAAE,GAAG;YACR,GAAG,EAAE,GAAG,GAAG,QAAQ;YACnB,GAAG;SACN,CAAC;QAEF,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAClC,2CAA2C;QAC3C,OAAO,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACtG,CAAC;CACJ","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ScopeType, ITokenClaims } from \"@fluidframework/protocol-definitions\";\nimport { ITokenProvider, ITokenResponse } from \"@fluidframework/routerlicious-driver\";\nimport { getRandomName } from \"@fluidframework/server-services-client\";\nimport { KJUR as jsrsasign } from \"jsrsasign\";\nimport { v4 as uuid } from \"uuid\";\n\n/**\n * As the name implies this is not secure and should not be used in production. It simply makes the example easier\n * to get up and running.\n */\nexport class InsecureTinyliciousTokenProvider implements ITokenProvider {\n public async fetchOrdererToken(tenantId: string, documentId: string): Promise<ITokenResponse> {\n return {\n fromCache: true,\n jwt: this.getSignedToken(tenantId, documentId),\n };\n }\n\n public async fetchStorageToken(tenantId: string, documentId: string): Promise<ITokenResponse> {\n return {\n fromCache: true,\n jwt: this.getSignedToken(tenantId, documentId),\n };\n }\n\n private getSignedToken(\n tenantId: string,\n documentId: string,\n lifetime: number = 60 * 60,\n ver: string = \"1.0\"): string {\n // Current time in seconds\n const now = Math.round((new Date()).getTime() / 1000);\n const user = { id: uuid(), name: getRandomName() };\n\n const claims: ITokenClaims = {\n documentId,\n scopes: [ScopeType.DocRead, ScopeType.DocWrite, ScopeType.SummaryWrite],\n tenantId,\n user,\n iat: now,\n exp: now + lifetime,\n ver,\n };\n\n const utf8Key = { utf8: \"12345\" };\n // eslint-disable-next-line no-null/no-null\n return jsrsasign.jws.JWS.sign(null, JSON.stringify({ alg:\"HS256\", typ: \"JWT\" }), claims, utf8Key);\n }\n}\n"]}
1
+ {"version":3,"file":"insecureTinyliciousTokenProvider.js","sourceRoot":"","sources":["../src/insecureTinyliciousTokenProvider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAgB,MAAM,sCAAsC,CAAC;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AACvE,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC;AAElC;;;GAGG;AACH,MAAM,OAAO,gCAAgC;IAClC,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAmB;QAChE,OAAO;YACH,SAAS,EAAE,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAkB;QAC/D,OAAO;YACH,SAAS,EAAE,IAAI;YACf,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC;SACjD,CAAC;IACN,CAAC;IAEO,cAAc,CAClB,QAAgB,EAChB,UAA8B,EAC9B,WAAmB,EAAE,GAAG,EAAE,EAC1B,MAAc,KAAK;QACnB,0BAA0B;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,CAAC;QAEnD,MAAM,MAAM,GAAiB;YACzB,UAAU,EAAE,UAAU,aAAV,UAAU,cAAV,UAAU,GAAI,EAAE;YAC5B,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,QAAQ,EAAE,SAAS,CAAC,YAAY,CAAC;YACvE,QAAQ;YACR,IAAI;YACJ,GAAG,EAAE,GAAG;YACR,GAAG,EAAE,GAAG,GAAG,QAAQ;YACnB,GAAG;SACN,CAAC;QAEF,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAClC,2CAA2C;QAC3C,OAAO,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACtG,CAAC;CACJ","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ScopeType, ITokenClaims } from \"@fluidframework/protocol-definitions\";\nimport { ITokenProvider, ITokenResponse } from \"@fluidframework/routerlicious-driver\";\nimport { getRandomName } from \"@fluidframework/server-services-client\";\nimport { KJUR as jsrsasign } from \"jsrsasign\";\nimport { v4 as uuid } from \"uuid\";\n\n/**\n * As the name implies this is not secure and should not be used in production. It simply makes the example easier\n * to get up and running.\n */\nexport class InsecureTinyliciousTokenProvider implements ITokenProvider {\n public async fetchOrdererToken(tenantId: string, documentId?: string): Promise<ITokenResponse> {\n return {\n fromCache: true,\n jwt: this.getSignedToken(tenantId, documentId),\n };\n }\n\n public async fetchStorageToken(tenantId: string, documentId: string): Promise<ITokenResponse> {\n return {\n fromCache: true,\n jwt: this.getSignedToken(tenantId, documentId),\n };\n }\n\n private getSignedToken(\n tenantId: string,\n documentId: string | undefined,\n lifetime: number = 60 * 60,\n ver: string = \"1.0\"): string {\n // Current time in seconds\n const now = Math.round((new Date()).getTime() / 1000);\n const user = { id: uuid(), name: getRandomName() };\n\n const claims: ITokenClaims = {\n documentId: documentId ?? \"\",\n scopes: [ScopeType.DocRead, ScopeType.DocWrite, ScopeType.SummaryWrite],\n tenantId,\n user,\n iat: now,\n exp: now + lifetime,\n ver,\n };\n\n const utf8Key = { utf8: \"12345\" };\n // eslint-disable-next-line no-null/no-null\n return jsrsasign.jws.JWS.sign(null, JSON.stringify({ alg:\"HS256\", typ: \"JWT\" }), claims, utf8Key);\n }\n}\n"]}
@@ -13,13 +13,11 @@ export declare const defaultTinyliciousEndpoint = "http://localhost";
13
13
  * documentId/containerRelativePathing
14
14
  */
15
15
  export declare class InsecureTinyliciousUrlResolver implements IUrlResolver {
16
- private readonly tinyliciousPort;
17
- private readonly tinyliciousEndpoint;
18
16
  private readonly fluidProtocolEndpoint;
19
- constructor(tinyliciousPort?: number, tinyliciousEndpoint?: string);
17
+ private readonly tinyliciousEndpoint;
18
+ constructor(port?: number, endpoint?: string);
20
19
  resolve(request: IRequest): Promise<IResolvedUrl>;
21
20
  getAbsoluteUrl(resolvedUrl: IFluidResolvedUrl, relativeUrl: string): Promise<string>;
22
- private auth;
23
21
  }
24
- export declare const createTinyliciousCreateNewRequest: (documentId: string) => IRequest;
22
+ export declare const createTinyliciousCreateNewRequest: (documentId?: string | undefined) => IRequest;
25
23
  //# sourceMappingURL=insecureTinyliciousUrlResolver.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"insecureTinyliciousUrlResolver.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAC3D,OAAO,EACH,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACf,MAAM,oCAAoC,CAAC;AAK5C,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,0BAA0B,qBAAqB,CAAC;AAE7D;;;;;GAKG;AACH,qBAAa,8BAA+B,YAAW,YAAY;IAG3D,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IAHxC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;gBAE1B,eAAe,SAAyB,EACxC,mBAAmB,SAA6B;IAKxD,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IA0BjD,cAAc,CAAC,WAAW,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAajG,OAAO,CAAC,IAAI;CAef;AAED,eAAO,MAAM,iCAAiC,eAC7B,MAAM,KAAG,QAOrB,CAAC"}
1
+ {"version":3,"file":"insecureTinyliciousUrlResolver.d.ts","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.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;AAE5C,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAC3C,eAAO,MAAM,0BAA0B,qBAAqB,CAAC;AAE7D;;;;;GAKG;AACH,qBAAa,8BAA+B,YAAW,YAAY;IAC/D,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;gBAEzC,IAAI,SAAyB,EAC7B,QAAQ,SAA6B;IAM5B,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IA6CjD,cAAc,CAAC,WAAW,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAYpG;AAED,eAAO,MAAM,iCAAiC,uCACnB,QAOtB,CAAC"}
@@ -2,8 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { KJUR as jsrsasign } from "jsrsasign";
6
- import { v4 as uuid } from "uuid";
5
+ import { DriverHeader, } from "@fluidframework/driver-definitions";
7
6
  export const defaultTinyliciousPort = 7070;
8
7
  export const defaultTinyliciousEndpoint = "http://localhost";
9
8
  /**
@@ -13,35 +12,51 @@ export const defaultTinyliciousEndpoint = "http://localhost";
13
12
  * documentId/containerRelativePathing
14
13
  */
15
14
  export class InsecureTinyliciousUrlResolver {
16
- constructor(tinyliciousPort = defaultTinyliciousPort, tinyliciousEndpoint = defaultTinyliciousEndpoint) {
17
- this.tinyliciousPort = tinyliciousPort;
18
- this.tinyliciousEndpoint = tinyliciousEndpoint;
15
+ constructor(port = defaultTinyliciousPort, endpoint = defaultTinyliciousEndpoint) {
16
+ this.tinyliciousEndpoint = `${endpoint}:${port}`;
19
17
  this.fluidProtocolEndpoint = this.tinyliciousEndpoint.replace(/(^\w+:|^)\/\//, "fluid://");
20
18
  }
21
19
  async resolve(request) {
22
- const url = request.url.replace(`${this.tinyliciousEndpoint}:${this.tinyliciousPort}/`, "");
20
+ // determine whether the request is for creating of a new container.
21
+ // such request has the `createNew` header set to true and doesn't have a container ID.
22
+ if (request.headers && request.headers[DriverHeader.createNew] === true) {
23
+ return {
24
+ endpoints: {
25
+ deltaStorageUrl: `${this.tinyliciousEndpoint}/deltas/tinylicious/new`,
26
+ ordererUrl: this.tinyliciousEndpoint,
27
+ storageUrl: `${this.tinyliciousEndpoint}/repos/tinylicious`,
28
+ },
29
+ // id is a mandatory attribute, but it's ignored by the driver for new container requests.
30
+ id: "",
31
+ // tokens attribute is redundant as all tokens are generated via ITokenProvider
32
+ tokens: {},
33
+ type: "fluid",
34
+ url: `${this.fluidProtocolEndpoint}/tinylicious/new`,
35
+ };
36
+ }
37
+ // for an existing container we'll parse the request URL to determine the document ID.
38
+ const url = request.url.replace(`${this.tinyliciousEndpoint}/`, "");
23
39
  const documentId = url.split("/")[0];
24
40
  const encodedDocId = encodeURIComponent(documentId);
25
41
  const documentRelativePath = url.slice(documentId.length);
26
- // eslint-disable-next-line max-len
27
- const documentUrl = `${this.fluidProtocolEndpoint}:${this.tinyliciousPort}/tinylicious/${encodedDocId}${documentRelativePath}`;
28
- const deltaStorageUrl = `${this.tinyliciousEndpoint}:${this.tinyliciousPort}/deltas/tinylicious/${encodedDocId}`;
29
- const storageUrl = `${this.tinyliciousEndpoint}:${this.tinyliciousPort}/repos/tinylicious`;
42
+ const documentUrl = `${this.fluidProtocolEndpoint}/tinylicious/${encodedDocId}${documentRelativePath}`;
43
+ const deltaStorageUrl = `${this.tinyliciousEndpoint}/deltas/tinylicious/${encodedDocId}`;
44
+ const storageUrl = `${this.tinyliciousEndpoint}/repos/tinylicious`;
30
45
  const response = {
31
46
  endpoints: {
32
47
  deltaStorageUrl,
33
- ordererUrl: `${this.tinyliciousEndpoint}:${this.tinyliciousPort}`,
48
+ ordererUrl: this.tinyliciousEndpoint,
34
49
  storageUrl,
35
50
  },
36
51
  id: documentId,
37
- tokens: { jwt: this.auth(documentId) },
52
+ tokens: {},
38
53
  type: "fluid",
39
54
  url: documentUrl,
40
55
  };
41
56
  return response;
42
57
  }
43
58
  async getAbsoluteUrl(resolvedUrl, relativeUrl) {
44
- const documentId = decodeURIComponent(resolvedUrl.url.replace(`${this.fluidProtocolEndpoint}:${this.tinyliciousPort}/tinylicious/`, ""));
59
+ const documentId = decodeURIComponent(resolvedUrl.url.replace(`${this.fluidProtocolEndpoint}/tinylicious/`, ""));
45
60
  /*
46
61
  * The detached container flow will ultimately call getAbsoluteUrl() with the resolved.url produced by
47
62
  * resolve(). The container expects getAbsoluteUrl's return value to be a URL that can then be roundtripped
@@ -50,25 +65,11 @@ export class InsecureTinyliciousUrlResolver {
50
65
  */
51
66
  return `${documentId}/${relativeUrl}`;
52
67
  }
53
- auth(documentId) {
54
- const claims = {
55
- documentId,
56
- scopes: ["doc:read", "doc:write", "summary:write"],
57
- tenantId: "tinylicious",
58
- user: { id: uuid() },
59
- iat: Math.round(new Date().getTime() / 1000),
60
- exp: Math.round(new Date().getTime() / 1000) + 60 * 60,
61
- ver: "1.0",
62
- };
63
- const utf8Key = { utf8: "12345" };
64
- // eslint-disable-next-line no-null/no-null
65
- return jsrsasign.jws.JWS.sign(null, JSON.stringify({ alg: "HS256", typ: "JWT" }), claims, utf8Key);
66
- }
67
68
  }
68
69
  export const createTinyliciousCreateNewRequest = (documentId) => ({
69
- url: documentId,
70
+ url: documentId !== null && documentId !== void 0 ? documentId : "",
70
71
  headers: {
71
- createNew: true,
72
+ [DriverHeader.createNew]: true,
72
73
  },
73
74
  });
74
75
  //# sourceMappingURL=insecureTinyliciousUrlResolver.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"insecureTinyliciousUrlResolver.js","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.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 IFluidResolvedUrl,\n IResolvedUrl,\n IUrlResolver,\n} from \"@fluidframework/driver-definitions\";\nimport { ITokenClaims } from \"@fluidframework/protocol-definitions\";\nimport { KJUR as jsrsasign } from \"jsrsasign\";\nimport { v4 as uuid } from \"uuid\";\n\nexport const defaultTinyliciousPort = 7070;\nexport const defaultTinyliciousEndpoint = \"http://localhost\";\n\n/**\n * InsecureTinyliciousUrlResolver knows how to get the URLs to the service (in this case Tinylicious) to use\n * for a given request. This particular implementation has a goal to avoid imposing requirements on the app's\n * URL shape, so it expects the request url to have this format (as opposed to a more traditional URL):\n * documentId/containerRelativePathing\n */\nexport class InsecureTinyliciousUrlResolver implements IUrlResolver {\n private readonly fluidProtocolEndpoint: string;\n public constructor(\n private readonly tinyliciousPort = defaultTinyliciousPort,\n private readonly tinyliciousEndpoint = defaultTinyliciousEndpoint,\n ) {\n this.fluidProtocolEndpoint = this.tinyliciousEndpoint.replace(/(^\\w+:|^)\\/\\//, \"fluid://\");\n }\n\n public async resolve(request: IRequest): Promise<IResolvedUrl> {\n const url = request.url.replace(`${this.tinyliciousEndpoint}:${this.tinyliciousPort}/`, \"\");\n const documentId = url.split(\"/\")[0];\n const encodedDocId = encodeURIComponent(documentId);\n const documentRelativePath = url.slice(documentId.length);\n\n // eslint-disable-next-line max-len\n const documentUrl = `${this.fluidProtocolEndpoint}:${this.tinyliciousPort}/tinylicious/${encodedDocId}${documentRelativePath}`;\n const deltaStorageUrl =\n `${this.tinyliciousEndpoint}:${this.tinyliciousPort}/deltas/tinylicious/${encodedDocId}`;\n const storageUrl = `${this.tinyliciousEndpoint}:${this.tinyliciousPort}/repos/tinylicious`;\n\n const response: IFluidResolvedUrl = {\n endpoints: {\n deltaStorageUrl,\n ordererUrl: `${this.tinyliciousEndpoint}:${this.tinyliciousPort}`,\n storageUrl,\n },\n id: documentId,\n tokens: { jwt: this.auth(documentId) },\n type: \"fluid\",\n url: documentUrl,\n };\n return response;\n }\n\n public async getAbsoluteUrl(resolvedUrl: IFluidResolvedUrl, relativeUrl: string): Promise<string> {\n const documentId = decodeURIComponent(\n resolvedUrl.url.replace(`${this.fluidProtocolEndpoint}:${this.tinyliciousPort}/tinylicious/`, \"\"),\n );\n /*\n * The detached container flow will ultimately call getAbsoluteUrl() with the resolved.url produced by\n * resolve(). The container expects getAbsoluteUrl's return value to be a URL that can then be roundtripped\n * back through resolve() again, and get the same result again. So we'll return a \"URL\" with the same format\n * described above.\n */\n return `${documentId}/${relativeUrl}`;\n }\n\n private auth(documentId: string) {\n const claims: ITokenClaims = {\n documentId,\n scopes: [\"doc:read\", \"doc:write\", \"summary:write\"],\n tenantId: \"tinylicious\",\n user: { id: uuid() },\n iat: Math.round(new Date().getTime() / 1000),\n exp: Math.round(new Date().getTime() / 1000) + 60 * 60, // 1 hour expiration\n ver: \"1.0\",\n };\n\n const utf8Key = { utf8: \"12345\" };\n // eslint-disable-next-line no-null/no-null\n return jsrsasign.jws.JWS.sign(null, JSON.stringify({ alg: \"HS256\", typ: \"JWT\" }), claims, utf8Key);\n }\n}\n\nexport const createTinyliciousCreateNewRequest =\n (documentId: string): IRequest => (\n {\n url: documentId,\n headers: {\n createNew: true,\n },\n }\n );\n"]}
1
+ {"version":3,"file":"insecureTinyliciousUrlResolver.js","sourceRoot":"","sources":["../src/insecureTinyliciousUrlResolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACH,YAAY,GAIf,MAAM,oCAAoC,CAAC;AAE5C,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAC3C,MAAM,CAAC,MAAM,0BAA0B,GAAG,kBAAkB,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,OAAO,8BAA8B;IAGvC,YACI,IAAI,GAAG,sBAAsB,EAC7B,QAAQ,GAAG,0BAA0B;QAErC,IAAI,CAAC,mBAAmB,GAAG,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC;QACjD,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;IAC/F,CAAC;IAEM,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,mBAAmB,yBAAyB;oBACrE,UAAU,EAAE,IAAI,CAAC,mBAAmB;oBACpC,UAAU,EAAE,GAAG,IAAI,CAAC,mBAAmB,oBAAoB;iBAC9D;gBACD,0FAA0F;gBAC1F,EAAE,EAAE,EAAE;gBACN,+EAA+E;gBAC/E,MAAM,EAAE,EAAE;gBACV,IAAI,EAAE,OAAO;gBACb,GAAG,EAAE,GAAG,IAAI,CAAC,qBAAqB,kBAAkB;aACvD,CAAC;SACL;QACD,sFAAsF;QACtF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,mBAAmB,GAAG,EAAE,EAAE,CAAC,CAAC;QACpE,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,YAAY,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;QACpD,MAAM,oBAAoB,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAE1D,MAAM,WAAW,GACb,GAAG,IAAI,CAAC,qBAAqB,gBAAgB,YAAY,GAAG,oBAAoB,EAAE,CAAC;QACvF,MAAM,eAAe,GACjB,GAAG,IAAI,CAAC,mBAAmB,uBAAuB,YAAY,EAAE,CAAC;QACrE,MAAM,UAAU,GACZ,GAAG,IAAI,CAAC,mBAAmB,oBAAoB,CAAC;QAEpD,MAAM,QAAQ,GAAsB;YAChC,SAAS,EAAE;gBACP,eAAe;gBACf,UAAU,EAAE,IAAI,CAAC,mBAAmB;gBACpC,UAAU;aACb;YACD,EAAE,EAAE,UAAU;YACd,MAAM,EAAE,EAAE;YACV,IAAI,EAAE,OAAO;YACb,GAAG,EAAE,WAAW;SACnB,CAAC;QACF,OAAO,QAAQ,CAAC;IACpB,CAAC;IAEM,KAAK,CAAC,cAAc,CAAC,WAA8B,EAAE,WAAmB;QAC3E,MAAM,UAAU,GAAG,kBAAkB,CACjC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,qBAAqB,eAAe,EAAE,EAAE,CAAC,CAC5E,CAAC;QACF;;;;;WAKG;QACH,OAAO,GAAG,UAAU,IAAI,WAAW,EAAE,CAAC;IAC1C,CAAC;CACJ;AAED,MAAM,CAAC,MAAM,iCAAiC,GAC1C,CAAC,UAAmB,EAAY,EAAE,CAAC,CAC/B;IACI,GAAG,EAAE,UAAU,aAAV,UAAU,cAAV,UAAU,GAAI,EAAE;IACrB,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\nexport const defaultTinyliciousPort = 7070;\nexport const defaultTinyliciousEndpoint = \"http://localhost\";\n\n/**\n * InsecureTinyliciousUrlResolver knows how to get the URLs to the service (in this case Tinylicious) to use\n * for a given request. This particular implementation has a goal to avoid imposing requirements on the app's\n * URL shape, so it expects the request url to have this format (as opposed to a more traditional URL):\n * documentId/containerRelativePathing\n */\nexport class InsecureTinyliciousUrlResolver implements IUrlResolver {\n private readonly fluidProtocolEndpoint: string;\n private readonly tinyliciousEndpoint: string;\n public constructor(\n port = defaultTinyliciousPort,\n endpoint = defaultTinyliciousEndpoint,\n ) {\n this.tinyliciousEndpoint = `${endpoint}:${port}`;\n this.fluidProtocolEndpoint = this.tinyliciousEndpoint.replace(/(^\\w+:|^)\\/\\//, \"fluid://\");\n }\n\n public async resolve(request: IRequest): Promise<IResolvedUrl> {\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.tinyliciousEndpoint}/deltas/tinylicious/new`,\n ordererUrl: this.tinyliciousEndpoint,\n storageUrl: `${this.tinyliciousEndpoint}/repos/tinylicious`,\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.fluidProtocolEndpoint}/tinylicious/new`,\n };\n }\n // for an existing container we'll parse the request URL to determine the document ID.\n const url = request.url.replace(`${this.tinyliciousEndpoint}/`, \"\");\n const documentId = url.split(\"/\")[0];\n const encodedDocId = encodeURIComponent(documentId);\n const documentRelativePath = url.slice(documentId.length);\n\n const documentUrl =\n `${this.fluidProtocolEndpoint}/tinylicious/${encodedDocId}${documentRelativePath}`;\n const deltaStorageUrl =\n `${this.tinyliciousEndpoint}/deltas/tinylicious/${encodedDocId}`;\n const storageUrl =\n `${this.tinyliciousEndpoint}/repos/tinylicious`;\n\n const response: IFluidResolvedUrl = {\n endpoints: {\n deltaStorageUrl,\n ordererUrl: this.tinyliciousEndpoint,\n storageUrl,\n },\n id: documentId,\n tokens: {},\n type: \"fluid\",\n url: documentUrl,\n };\n return response;\n }\n\n public async getAbsoluteUrl(resolvedUrl: IFluidResolvedUrl, relativeUrl: string): Promise<string> {\n const documentId = decodeURIComponent(\n resolvedUrl.url.replace(`${this.fluidProtocolEndpoint}/tinylicious/`, \"\"),\n );\n /*\n * The detached container flow will ultimately call getAbsoluteUrl() with the resolved.url produced by\n * resolve(). The container expects getAbsoluteUrl's return value to be a URL that can then be roundtripped\n * back through resolve() again, and get the same result again. So we'll return a \"URL\" with the same format\n * described above.\n */\n return `${documentId}/${relativeUrl}`;\n }\n}\n\nexport const createTinyliciousCreateNewRequest =\n (documentId?: string): IRequest => (\n {\n url: documentId ?? \"\",\n headers: {\n [DriverHeader.createNew]: true,\n },\n }\n );\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/tinylicious-driver",
3
- "version": "0.47.1",
3
+ "version": "0.48.0-38105",
4
4
  "description": "Driver for tinylicious",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": "https://github.com/microsoft/FluidFramework",
@@ -29,15 +29,15 @@
29
29
  "dependencies": {
30
30
  "@fluidframework/core-interfaces": "^0.39.7",
31
31
  "@fluidframework/driver-definitions": "^0.39.6",
32
- "@fluidframework/driver-utils": "^0.47.1",
32
+ "@fluidframework/driver-utils": "0.48.0-38105",
33
33
  "@fluidframework/protocol-definitions": "^0.1024.0",
34
- "@fluidframework/routerlicious-driver": "^0.47.1",
35
- "@fluidframework/server-services-client": "^0.1030.0",
34
+ "@fluidframework/routerlicious-driver": "0.48.0-38105",
35
+ "@fluidframework/server-services-client": "^0.1031.0-37526",
36
36
  "jsrsasign": "^10.2.0",
37
37
  "uuid": "^8.3.1"
38
38
  },
39
39
  "devDependencies": {
40
- "@fluidframework/build-common": "^0.23.0",
40
+ "@fluidframework/build-common": "^0.23.0-0",
41
41
  "@fluidframework/eslint-config-fluid": "^0.23.0",
42
42
  "@fluidframework/test-tools": "^0.2.3074",
43
43
  "@types/jsrsasign": "^8.0.8",
@@ -14,7 +14,7 @@ import { v4 as uuid } from "uuid";
14
14
  * to get up and running.
15
15
  */
16
16
  export class InsecureTinyliciousTokenProvider implements ITokenProvider {
17
- public async fetchOrdererToken(tenantId: string, documentId: string): Promise<ITokenResponse> {
17
+ public async fetchOrdererToken(tenantId: string, documentId?: string): Promise<ITokenResponse> {
18
18
  return {
19
19
  fromCache: true,
20
20
  jwt: this.getSignedToken(tenantId, documentId),
@@ -30,7 +30,7 @@ export class InsecureTinyliciousTokenProvider implements ITokenProvider {
30
30
 
31
31
  private getSignedToken(
32
32
  tenantId: string,
33
- documentId: string,
33
+ documentId: string | undefined,
34
34
  lifetime: number = 60 * 60,
35
35
  ver: string = "1.0"): string {
36
36
  // Current time in seconds
@@ -38,7 +38,7 @@ export class InsecureTinyliciousTokenProvider implements ITokenProvider {
38
38
  const user = { id: uuid(), name: getRandomName() };
39
39
 
40
40
  const claims: ITokenClaims = {
41
- documentId,
41
+ documentId: documentId ?? "",
42
42
  scopes: [ScopeType.DocRead, ScopeType.DocWrite, ScopeType.SummaryWrite],
43
43
  tenantId,
44
44
  user,
@@ -5,13 +5,11 @@
5
5
 
6
6
  import { IRequest } from "@fluidframework/core-interfaces";
7
7
  import {
8
+ DriverHeader,
8
9
  IFluidResolvedUrl,
9
10
  IResolvedUrl,
10
11
  IUrlResolver,
11
12
  } from "@fluidframework/driver-definitions";
12
- import { ITokenClaims } from "@fluidframework/protocol-definitions";
13
- import { KJUR as jsrsasign } from "jsrsasign";
14
- import { v4 as uuid } from "uuid";
15
13
 
16
14
  export const defaultTinyliciousPort = 7070;
17
15
  export const defaultTinyliciousEndpoint = "http://localhost";
@@ -24,33 +22,54 @@ export const defaultTinyliciousEndpoint = "http://localhost";
24
22
  */
25
23
  export class InsecureTinyliciousUrlResolver implements IUrlResolver {
26
24
  private readonly fluidProtocolEndpoint: string;
25
+ private readonly tinyliciousEndpoint: string;
27
26
  public constructor(
28
- private readonly tinyliciousPort = defaultTinyliciousPort,
29
- private readonly tinyliciousEndpoint = defaultTinyliciousEndpoint,
30
- ) {
31
- this.fluidProtocolEndpoint = this.tinyliciousEndpoint.replace(/(^\w+:|^)\/\//, "fluid://");
32
- }
27
+ port = defaultTinyliciousPort,
28
+ endpoint = defaultTinyliciousEndpoint,
29
+ ) {
30
+ this.tinyliciousEndpoint = `${endpoint}:${port}`;
31
+ this.fluidProtocolEndpoint = this.tinyliciousEndpoint.replace(/(^\w+:|^)\/\//, "fluid://");
32
+ }
33
33
 
34
34
  public async resolve(request: IRequest): Promise<IResolvedUrl> {
35
- const url = request.url.replace(`${this.tinyliciousEndpoint}:${this.tinyliciousPort}/`, "");
35
+ // determine whether the request is for creating of a new container.
36
+ // such request has the `createNew` header set to true and doesn't have a container ID.
37
+ if (request.headers && request.headers[DriverHeader.createNew] === true) {
38
+ return {
39
+ endpoints: {
40
+ deltaStorageUrl: `${this.tinyliciousEndpoint}/deltas/tinylicious/new`,
41
+ ordererUrl: this.tinyliciousEndpoint,
42
+ storageUrl: `${this.tinyliciousEndpoint}/repos/tinylicious`,
43
+ },
44
+ // id is a mandatory attribute, but it's ignored by the driver for new container requests.
45
+ id: "",
46
+ // tokens attribute is redundant as all tokens are generated via ITokenProvider
47
+ tokens: {},
48
+ type: "fluid",
49
+ url: `${this.fluidProtocolEndpoint}/tinylicious/new`,
50
+ };
51
+ }
52
+ // for an existing container we'll parse the request URL to determine the document ID.
53
+ const url = request.url.replace(`${this.tinyliciousEndpoint}/`, "");
36
54
  const documentId = url.split("/")[0];
37
55
  const encodedDocId = encodeURIComponent(documentId);
38
56
  const documentRelativePath = url.slice(documentId.length);
39
57
 
40
- // eslint-disable-next-line max-len
41
- const documentUrl = `${this.fluidProtocolEndpoint}:${this.tinyliciousPort}/tinylicious/${encodedDocId}${documentRelativePath}`;
58
+ const documentUrl =
59
+ `${this.fluidProtocolEndpoint}/tinylicious/${encodedDocId}${documentRelativePath}`;
42
60
  const deltaStorageUrl =
43
- `${this.tinyliciousEndpoint}:${this.tinyliciousPort}/deltas/tinylicious/${encodedDocId}`;
44
- const storageUrl = `${this.tinyliciousEndpoint}:${this.tinyliciousPort}/repos/tinylicious`;
61
+ `${this.tinyliciousEndpoint}/deltas/tinylicious/${encodedDocId}`;
62
+ const storageUrl =
63
+ `${this.tinyliciousEndpoint}/repos/tinylicious`;
45
64
 
46
65
  const response: IFluidResolvedUrl = {
47
66
  endpoints: {
48
67
  deltaStorageUrl,
49
- ordererUrl: `${this.tinyliciousEndpoint}:${this.tinyliciousPort}`,
68
+ ordererUrl: this.tinyliciousEndpoint,
50
69
  storageUrl,
51
70
  },
52
71
  id: documentId,
53
- tokens: { jwt: this.auth(documentId) },
72
+ tokens: {},
54
73
  type: "fluid",
55
74
  url: documentUrl,
56
75
  };
@@ -59,7 +78,7 @@ export class InsecureTinyliciousUrlResolver implements IUrlResolver {
59
78
 
60
79
  public async getAbsoluteUrl(resolvedUrl: IFluidResolvedUrl, relativeUrl: string): Promise<string> {
61
80
  const documentId = decodeURIComponent(
62
- resolvedUrl.url.replace(`${this.fluidProtocolEndpoint}:${this.tinyliciousPort}/tinylicious/`, ""),
81
+ resolvedUrl.url.replace(`${this.fluidProtocolEndpoint}/tinylicious/`, ""),
63
82
  );
64
83
  /*
65
84
  * The detached container flow will ultimately call getAbsoluteUrl() with the resolved.url produced by
@@ -69,30 +88,14 @@ export class InsecureTinyliciousUrlResolver implements IUrlResolver {
69
88
  */
70
89
  return `${documentId}/${relativeUrl}`;
71
90
  }
72
-
73
- private auth(documentId: string) {
74
- const claims: ITokenClaims = {
75
- documentId,
76
- scopes: ["doc:read", "doc:write", "summary:write"],
77
- tenantId: "tinylicious",
78
- user: { id: uuid() },
79
- iat: Math.round(new Date().getTime() / 1000),
80
- exp: Math.round(new Date().getTime() / 1000) + 60 * 60, // 1 hour expiration
81
- ver: "1.0",
82
- };
83
-
84
- const utf8Key = { utf8: "12345" };
85
- // eslint-disable-next-line no-null/no-null
86
- return jsrsasign.jws.JWS.sign(null, JSON.stringify({ alg: "HS256", typ: "JWT" }), claims, utf8Key);
87
- }
88
91
  }
89
92
 
90
93
  export const createTinyliciousCreateNewRequest =
91
- (documentId: string): IRequest => (
94
+ (documentId?: string): IRequest => (
92
95
  {
93
- url: documentId,
96
+ url: documentId ?? "",
94
97
  headers: {
95
- createNew: true,
98
+ [DriverHeader.createNew]: true,
96
99
  },
97
100
  }
98
101
  );