@twin.org/api-tenant-processor 0.0.3-next.4 → 0.0.3-next.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +1 -1
  2. package/dist/es/entities/tenant.js +17 -1
  3. package/dist/es/entities/tenant.js.map +1 -1
  4. package/dist/es/index.js +13 -2
  5. package/dist/es/index.js.map +1 -1
  6. package/dist/es/models/ITenantProcessorConfig.js.map +1 -1
  7. package/dist/es/models/ITenantProcessorConstructorOptions.js.map +1 -1
  8. package/dist/es/models/ITenantServiceConfig.js +4 -0
  9. package/dist/es/models/ITenantServiceConfig.js.map +1 -0
  10. package/dist/es/models/ITenantServiceConstructorOptions.js +2 -0
  11. package/dist/es/models/ITenantServiceConstructorOptions.js.map +1 -0
  12. package/dist/es/models/api/ITenantCreateRequest.js +2 -0
  13. package/dist/es/models/api/ITenantCreateRequest.js.map +1 -0
  14. package/dist/es/models/api/ITenantGetByApiKeyRequest.js +4 -0
  15. package/dist/es/models/api/ITenantGetByApiKeyRequest.js.map +1 -0
  16. package/dist/es/models/api/ITenantGetByIdRequest.js +4 -0
  17. package/dist/es/models/api/ITenantGetByIdRequest.js.map +1 -0
  18. package/dist/es/models/api/ITenantGetByPublicOriginRequest.js +4 -0
  19. package/dist/es/models/api/ITenantGetByPublicOriginRequest.js.map +1 -0
  20. package/dist/es/models/api/ITenantGetResponse.js +2 -0
  21. package/dist/es/models/api/ITenantGetResponse.js.map +1 -0
  22. package/dist/es/models/api/ITenantListRequest.js +4 -0
  23. package/dist/es/models/api/ITenantListRequest.js.map +1 -0
  24. package/dist/es/models/api/ITenantListResponse.js +2 -0
  25. package/dist/es/models/api/ITenantListResponse.js.map +1 -0
  26. package/dist/es/models/api/ITenantRemoveRequest.js +4 -0
  27. package/dist/es/models/api/ITenantRemoveRequest.js.map +1 -0
  28. package/dist/es/models/api/ITenantUpdateRequest.js +2 -0
  29. package/dist/es/models/api/ITenantUpdateRequest.js.map +1 -0
  30. package/dist/es/restEntryPoints.js +10 -0
  31. package/dist/es/restEntryPoints.js.map +1 -0
  32. package/dist/es/tenantAdminService.js +101 -16
  33. package/dist/es/tenantAdminService.js.map +1 -1
  34. package/dist/es/tenantIdContextIdHandler.js +7 -0
  35. package/dist/es/tenantIdContextIdHandler.js.map +1 -1
  36. package/dist/es/tenantProcessor.js +75 -17
  37. package/dist/es/tenantProcessor.js.map +1 -1
  38. package/dist/es/tenantRoutes.js +394 -0
  39. package/dist/es/tenantRoutes.js.map +1 -0
  40. package/dist/es/tenantService.js +51 -0
  41. package/dist/es/tenantService.js.map +1 -0
  42. package/dist/es/utils/tenantIdHelper.js +3 -3
  43. package/dist/es/utils/tenantIdHelper.js.map +1 -1
  44. package/dist/types/entities/tenant.d.ts +8 -0
  45. package/dist/types/index.d.ts +13 -2
  46. package/dist/types/models/ITenantProcessorConfig.d.ts +4 -0
  47. package/dist/types/models/ITenantProcessorConstructorOptions.d.ts +5 -0
  48. package/dist/types/models/ITenantServiceConfig.d.ts +5 -0
  49. package/dist/types/models/ITenantServiceConstructorOptions.d.ts +15 -0
  50. package/dist/types/models/api/ITenantCreateRequest.d.ts +12 -0
  51. package/dist/types/models/api/ITenantGetByApiKeyRequest.d.ts +14 -0
  52. package/dist/types/models/api/ITenantGetByIdRequest.d.ts +14 -0
  53. package/dist/types/models/api/ITenantGetByPublicOriginRequest.d.ts +14 -0
  54. package/dist/types/models/api/ITenantGetResponse.d.ts +10 -0
  55. package/dist/types/models/api/ITenantListRequest.d.ts +23 -0
  56. package/dist/types/models/api/ITenantListResponse.d.ts +17 -0
  57. package/dist/types/models/api/ITenantRemoveRequest.d.ts +14 -0
  58. package/dist/types/models/api/ITenantUpdateRequest.d.ts +19 -0
  59. package/dist/types/restEntryPoints.d.ts +2 -0
  60. package/dist/types/tenantAdminService.d.ts +28 -11
  61. package/dist/types/tenantIdContextIdHandler.d.ts +5 -0
  62. package/dist/types/tenantProcessor.d.ts +1 -1
  63. package/dist/types/tenantRoutes.d.ts +77 -0
  64. package/dist/types/tenantService.d.ts +27 -0
  65. package/docs/changelog.md +546 -15
  66. package/docs/examples.md +81 -1
  67. package/docs/reference/classes/Tenant.md +20 -4
  68. package/docs/reference/classes/TenantAdminService.md +96 -26
  69. package/docs/reference/classes/TenantIdContextIdHandler.md +21 -3
  70. package/docs/reference/classes/TenantIdHelper.md +2 -2
  71. package/docs/reference/classes/TenantProcessor.md +6 -6
  72. package/docs/reference/classes/TenantService.md +79 -0
  73. package/docs/reference/functions/generateRestRoutesTenants.md +25 -0
  74. package/docs/reference/functions/tenantByApiKey.md +31 -0
  75. package/docs/reference/functions/tenantById.md +31 -0
  76. package/docs/reference/functions/tenantByPublicOrigin.md +31 -0
  77. package/docs/reference/functions/tenantCreate.md +31 -0
  78. package/docs/reference/functions/tenantList.md +31 -0
  79. package/docs/reference/functions/tenantRemove.md +31 -0
  80. package/docs/reference/functions/tenantUpdate.md +31 -0
  81. package/docs/reference/index.md +24 -2
  82. package/docs/reference/interfaces/ITenantAdminServiceConstructorOptions.md +4 -4
  83. package/docs/reference/interfaces/ITenantCreateRequest.md +17 -0
  84. package/docs/reference/interfaces/ITenantGetByApiKeyRequest.md +17 -0
  85. package/docs/reference/interfaces/ITenantGetByIdRequest.md +17 -0
  86. package/docs/reference/interfaces/ITenantGetByPublicOriginRequest.md +17 -0
  87. package/docs/reference/interfaces/ITenantGetResponse.md +11 -0
  88. package/docs/reference/interfaces/ITenantListRequest.md +30 -0
  89. package/docs/reference/interfaces/ITenantListResponse.md +23 -0
  90. package/docs/reference/interfaces/ITenantProcessorConfig.md +10 -2
  91. package/docs/reference/interfaces/ITenantProcessorConstructorOptions.md +18 -4
  92. package/docs/reference/interfaces/ITenantRemoveRequest.md +17 -0
  93. package/docs/reference/interfaces/ITenantServiceConfig.md +3 -0
  94. package/docs/reference/interfaces/ITenantServiceConstructorOptions.md +25 -0
  95. package/docs/reference/interfaces/ITenantUpdateRequest.md +25 -0
  96. package/docs/reference/variables/tagsTenants.md +5 -0
  97. package/locales/en.json +8 -2
  98. package/package.json +6 -5
  99. package/dist/es/models/ITenant.js +0 -4
  100. package/dist/es/models/ITenant.js.map +0 -1
  101. package/dist/es/models/ITenantAdminComponent.js +0 -2
  102. package/dist/es/models/ITenantAdminComponent.js.map +0 -1
  103. package/dist/types/models/ITenant.d.ts +0 -21
  104. package/dist/types/models/ITenantAdminComponent.d.ts +0 -41
  105. package/docs/reference/interfaces/ITenant.md +0 -35
  106. package/docs/reference/interfaces/ITenantAdminComponent.md +0 -123
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # TWIN API Tenant Processor
2
2
 
3
- Will read `x-api-key` from HTTP header or query params and convert it to a tenant id, to be used for partitioning data.
3
+ This package provides tenant resolution services and route handlers that derive tenant context from API keys.
4
4
 
5
5
  ## Installation
6
6
 
@@ -21,13 +21,21 @@ let Tenant = class Tenant {
21
21
  * The date the tenant was created.
22
22
  */
23
23
  dateCreated;
24
+ /**
25
+ * The date the tenant was modified.
26
+ */
27
+ dateModified;
28
+ /**
29
+ * The origin available to the public for accessing the API.
30
+ */
31
+ publicOrigin;
24
32
  };
25
33
  __decorate([
26
34
  property({ type: "string", isPrimary: true }),
27
35
  __metadata("design:type", String)
28
36
  ], Tenant.prototype, "id", void 0);
29
37
  __decorate([
30
- property({ type: "string" }),
38
+ property({ type: "string", isSecondary: true }),
31
39
  __metadata("design:type", String)
32
40
  ], Tenant.prototype, "apiKey", void 0);
33
41
  __decorate([
@@ -38,6 +46,14 @@ __decorate([
38
46
  property({ type: "string" }),
39
47
  __metadata("design:type", String)
40
48
  ], Tenant.prototype, "dateCreated", void 0);
49
+ __decorate([
50
+ property({ type: "string" }),
51
+ __metadata("design:type", String)
52
+ ], Tenant.prototype, "dateModified", void 0);
53
+ __decorate([
54
+ property({ type: "string", optional: true, isSecondary: true }),
55
+ __metadata("design:type", String)
56
+ ], Tenant.prototype, "publicOrigin", void 0);
41
57
  Tenant = __decorate([
42
58
  entity()
43
59
  ], Tenant);
@@ -1 +1 @@
1
- {"version":3,"file":"tenant.js","sourceRoot":"","sources":["../../../src/entities/tenant.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;GAEG;AAEI,IAAM,MAAM,GAAZ,MAAM,MAAM;IAClB;;OAEG;IAEI,EAAE,CAAU;IAEnB;;OAEG;IAEI,MAAM,CAAU;IAEvB;;OAEG;IAEI,KAAK,CAAU;IAEtB;;OAEG;IAEI,WAAW,CAAU;CAC5B,CAAA;AAnBO;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;;kCAC3B;AAMZ;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;sCACN;AAMhB;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;qCACP;AAMf;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;2CACD;AAvBhB,MAAM;IADlB,MAAM,EAAE;GACI,MAAM,CAwBlB","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { entity, property } from \"@twin.org/entity\";\n\n/**\n * Class defining the storage for node tenants.\n */\n@entity()\nexport class Tenant {\n\t/**\n\t * The unique identifier for the tenant.\n\t */\n\t@property({ type: \"string\", isPrimary: true })\n\tpublic id!: string;\n\n\t/**\n\t * The api key for the tenant.\n\t */\n\t@property({ type: \"string\" })\n\tpublic apiKey!: string;\n\n\t/**\n\t * The label of the tenant.\n\t */\n\t@property({ type: \"string\" })\n\tpublic label!: string;\n\n\t/**\n\t * The date the tenant was created.\n\t */\n\t@property({ type: \"string\" })\n\tpublic dateCreated!: string;\n}\n"]}
1
+ {"version":3,"file":"tenant.js","sourceRoot":"","sources":["../../../src/entities/tenant.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;GAEG;AAEI,IAAM,MAAM,GAAZ,MAAM,MAAM;IAClB;;OAEG;IAEI,EAAE,CAAU;IAEnB;;OAEG;IAEI,MAAM,CAAU;IAEvB;;OAEG;IAEI,KAAK,CAAU;IAEtB;;OAEG;IAEI,WAAW,CAAU;IAE5B;;OAEG;IAEI,YAAY,CAAU;IAE7B;;OAEG;IAEI,YAAY,CAAU;CAC7B,CAAA;AA/BO;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;;kCAC3B;AAMZ;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;;sCACzB;AAMhB;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;qCACP;AAMf;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;2CACD;AAMrB;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;;4CACA;AAMtB;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;;4CACnC;AAnCjB,MAAM;IADlB,MAAM,EAAE;GACI,MAAM,CAoClB","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { entity, property } from \"@twin.org/entity\";\n\n/**\n * Class defining the storage for node tenants.\n */\n@entity()\nexport class Tenant {\n\t/**\n\t * The unique identifier for the tenant.\n\t */\n\t@property({ type: \"string\", isPrimary: true })\n\tpublic id!: string;\n\n\t/**\n\t * The api key for the tenant.\n\t */\n\t@property({ type: \"string\", isSecondary: true })\n\tpublic apiKey!: string;\n\n\t/**\n\t * The label of the tenant.\n\t */\n\t@property({ type: \"string\" })\n\tpublic label!: string;\n\n\t/**\n\t * The date the tenant was created.\n\t */\n\t@property({ type: \"string\" })\n\tpublic dateCreated!: string;\n\n\t/**\n\t * The date the tenant was modified.\n\t */\n\t@property({ type: \"string\" })\n\tpublic dateModified!: string;\n\n\t/**\n\t * The origin available to the public for accessing the API.\n\t */\n\t@property({ type: \"string\", optional: true, isSecondary: true })\n\tpublic publicOrigin?: string;\n}\n"]}
package/dist/es/index.js CHANGED
@@ -1,15 +1,26 @@
1
1
  // Copyright 2025 IOTA Stiftung.
2
2
  // SPDX-License-Identifier: Apache-2.0.
3
3
  export * from "./entities/tenant.js";
4
- export * from "./models/ITenant.js";
5
- export * from "./models/ITenantAdminComponent.js";
4
+ export * from "./models/api/ITenantCreateRequest.js";
5
+ export * from "./models/api/ITenantGetByApiKeyRequest.js";
6
+ export * from "./models/api/ITenantGetByIdRequest.js";
7
+ export * from "./models/api/ITenantGetByPublicOriginRequest.js";
8
+ export * from "./models/api/ITenantGetResponse.js";
9
+ export * from "./models/api/ITenantListRequest.js";
10
+ export * from "./models/api/ITenantListResponse.js";
11
+ export * from "./models/api/ITenantRemoveRequest.js";
12
+ export * from "./models/api/ITenantUpdateRequest.js";
6
13
  export * from "./models/ITenantAdminServiceConfig.js";
7
14
  export * from "./models/ITenantAdminServiceConstructorOptions.js";
8
15
  export * from "./models/ITenantProcessorConfig.js";
9
16
  export * from "./models/ITenantProcessorConstructorOptions.js";
17
+ export * from "./models/ITenantServiceConfig.js";
18
+ export * from "./models/ITenantServiceConstructorOptions.js";
10
19
  export * from "./schema.js";
11
20
  export * from "./tenantAdminService.js";
12
21
  export * from "./tenantIdContextIdHandler.js";
13
22
  export * from "./tenantProcessor.js";
23
+ export * from "./tenantRoutes.js";
24
+ export * from "./tenantService.js";
14
25
  export * from "./utils/tenantIdHelper.js";
15
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mCAAmC,CAAC;AAClD,cAAc,uCAAuC,CAAC;AACtD,cAAc,mDAAmD,CAAC;AAClE,cAAc,oCAAoC,CAAC;AACnD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./entities/tenant.js\";\nexport * from \"./models/ITenant.js\";\nexport * from \"./models/ITenantAdminComponent.js\";\nexport * from \"./models/ITenantAdminServiceConfig.js\";\nexport * from \"./models/ITenantAdminServiceConstructorOptions.js\";\nexport * from \"./models/ITenantProcessorConfig.js\";\nexport * from \"./models/ITenantProcessorConstructorOptions.js\";\nexport * from \"./schema.js\";\nexport * from \"./tenantAdminService.js\";\nexport * from \"./tenantIdContextIdHandler.js\";\nexport * from \"./tenantProcessor.js\";\nexport * from \"./utils/tenantIdHelper.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sCAAsC,CAAC;AACrD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,uCAAuC,CAAC;AACtD,cAAc,iDAAiD,CAAC;AAChE,cAAc,oCAAoC,CAAC;AACnD,cAAc,oCAAoC,CAAC;AACnD,cAAc,qCAAqC,CAAC;AACpD,cAAc,sCAAsC,CAAC;AACrD,cAAc,sCAAsC,CAAC;AACrD,cAAc,uCAAuC,CAAC;AACtD,cAAc,mDAAmD,CAAC;AAClE,cAAc,oCAAoC,CAAC;AACnD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,kCAAkC,CAAC;AACjD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,aAAa,CAAC;AAC5B,cAAc,yBAAyB,CAAC;AACxC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./entities/tenant.js\";\nexport * from \"./models/api/ITenantCreateRequest.js\";\nexport * from \"./models/api/ITenantGetByApiKeyRequest.js\";\nexport * from \"./models/api/ITenantGetByIdRequest.js\";\nexport * from \"./models/api/ITenantGetByPublicOriginRequest.js\";\nexport * from \"./models/api/ITenantGetResponse.js\";\nexport * from \"./models/api/ITenantListRequest.js\";\nexport * from \"./models/api/ITenantListResponse.js\";\nexport * from \"./models/api/ITenantRemoveRequest.js\";\nexport * from \"./models/api/ITenantUpdateRequest.js\";\nexport * from \"./models/ITenantAdminServiceConfig.js\";\nexport * from \"./models/ITenantAdminServiceConstructorOptions.js\";\nexport * from \"./models/ITenantProcessorConfig.js\";\nexport * from \"./models/ITenantProcessorConstructorOptions.js\";\nexport * from \"./models/ITenantServiceConfig.js\";\nexport * from \"./models/ITenantServiceConstructorOptions.js\";\nexport * from \"./schema.js\";\nexport * from \"./tenantAdminService.js\";\nexport * from \"./tenantIdContextIdHandler.js\";\nexport * from \"./tenantProcessor.js\";\nexport * from \"./tenantRoutes.js\";\nexport * from \"./tenantService.js\";\nexport * from \"./utils/tenantIdHelper.js\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ITenantProcessorConfig.js","sourceRoot":"","sources":["../../../src/models/ITenantProcessorConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Configuration for the tenant processor\n */\nexport interface ITenantProcessorConfig {\n\t/**\n\t * The key to look for in the header or query params for the api key.\n\t * @default x-api-key\n\t */\n\tapiKeyName?: string;\n}\n"]}
1
+ {"version":3,"file":"ITenantProcessorConfig.js","sourceRoot":"","sources":["../../../src/models/ITenantProcessorConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Configuration for the tenant processor\n */\nexport interface ITenantProcessorConfig {\n\t/**\n\t * The key to look for in the header or query params for the api key.\n\t * @default x-api-key\n\t */\n\tapiKeyName?: string;\n\n\t/**\n\t * The list of endpoint paths that should be checked for an api key header, can be regexp strings. Defaults to [\"/login$\"].\n\t */\n\tapiKeyEndpoints?: string[];\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ITenantProcessorConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/ITenantProcessorConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ITenantProcessorConfig } from \"./ITenantProcessorConfig.js\";\n\n/**\n * Options for the Tenant Processor constructor.\n */\nexport interface ITenantProcessorConstructorOptions {\n\t/**\n\t * The entity storage for the tenants.\n\t * @default tenant\n\t */\n\ttenantEntityStorageType?: string;\n\n\t/**\n\t * Configuration for the processor.\n\t */\n\tconfig?: ITenantProcessorConfig;\n}\n"]}
1
+ {"version":3,"file":"ITenantProcessorConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/ITenantProcessorConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ITenantProcessorConfig } from \"./ITenantProcessorConfig.js\";\n\n/**\n * Options for the Tenant Processor constructor.\n */\nexport interface ITenantProcessorConstructorOptions {\n\t/**\n\t * The entity storage for the tenants.\n\t * @default tenant\n\t */\n\ttenantEntityStorageType?: string;\n\n\t/**\n\t * The URL transformer component for the tenants.\n\t * @default url-transformer\n\t */\n\turlTransformerComponentType?: string;\n\n\t/**\n\t * Configuration for the processor.\n\t */\n\tconfig?: ITenantProcessorConfig;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2026 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=ITenantServiceConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ITenantServiceConfig.js","sourceRoot":"","sources":["../../../src/models/ITenantServiceConfig.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * Configuration for the tenant service\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface ITenantServiceConfig {}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ITenantServiceConstructorOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ITenantServiceConstructorOptions.js","sourceRoot":"","sources":["../../../src/models/ITenantServiceConstructorOptions.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ITenantServiceConfig } from \"./ITenantServiceConfig.js\";\n\n/**\n * Options for the Tenant Service constructor.\n */\nexport interface ITenantServiceConstructorOptions {\n\t/**\n\t * The entity storage for the tenants.\n\t * @default tenant\n\t */\n\ttenantEntityStorageType?: string;\n\n\t/**\n\t * Configuration for the service.\n\t */\n\tconfig?: ITenantServiceConfig;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ITenantCreateRequest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ITenantCreateRequest.js","sourceRoot":"","sources":["../../../../src/models/api/ITenantCreateRequest.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ITenant } from \"@twin.org/api-models\";\n\n/**\n * The tenant to create.\n */\nexport interface ITenantCreateRequest {\n\t/**\n\t * The tenant to create.\n\t */\n\tbody: Omit<ITenant, \"id\" | \"dateCreated\" | \"dateModified\"> & { id?: string };\n}\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=ITenantGetByApiKeyRequest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ITenantGetByApiKeyRequest.js","sourceRoot":"","sources":["../../../../src/models/api/ITenantGetByApiKeyRequest.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * The tenant to get by API key.\n */\nexport interface ITenantGetByApiKeyRequest {\n\t/**\n\t * The path parameters.\n\t */\n\tpathParams: {\n\t\t/**\n\t\t * The API key of the tenant to get.\n\t\t */\n\t\tapiKey: string;\n\t};\n}\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=ITenantGetByIdRequest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ITenantGetByIdRequest.js","sourceRoot":"","sources":["../../../../src/models/api/ITenantGetByIdRequest.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * The tenant to get by id.\n */\nexport interface ITenantGetByIdRequest {\n\t/**\n\t * The path parameters.\n\t */\n\tpathParams: {\n\t\t/**\n\t\t * The id of the tenant to get.\n\t\t */\n\t\tid: string;\n\t};\n}\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=ITenantGetByPublicOriginRequest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ITenantGetByPublicOriginRequest.js","sourceRoot":"","sources":["../../../../src/models/api/ITenantGetByPublicOriginRequest.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * The tenant to get by public origin.\n */\nexport interface ITenantGetByPublicOriginRequest {\n\t/**\n\t * The path parameters.\n\t */\n\tpathParams: {\n\t\t/**\n\t\t * The public origin of the tenant to get.\n\t\t */\n\t\tpublicOrigin: string;\n\t};\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ITenantGetResponse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ITenantGetResponse.js","sourceRoot":"","sources":["../../../../src/models/api/ITenantGetResponse.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ITenant } from \"@twin.org/api-models\";\n\n/**\n * The tenant get response.\n */\nexport interface ITenantGetResponse {\n\t/**\n\t * The tenant.\n\t */\n\tbody: ITenant;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=ITenantListRequest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ITenantListRequest.js","sourceRoot":"","sources":["../../../../src/models/api/ITenantListRequest.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * The list of tenants.\n */\nexport interface ITenantListRequest {\n\t/**\n\t * The query parameters.\n\t */\n\tquery: {\n\t\t/**\n\t\t * The properties to include in the returned tenants, separated by commas.\n\t\t * If not provided, all properties will be returned.\n\t\t */\n\t\tproperties?: string;\n\n\t\t/**\n\t\t * The cursor to get the next chunk of tenants.\n\t\t */\n\t\tcursor?: string;\n\n\t\t/**\n\t\t * The number of tenants to return.\n\t\t */\n\t\tlimit?: string;\n\t};\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ITenantListResponse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ITenantListResponse.js","sourceRoot":"","sources":["../../../../src/models/api/ITenantListResponse.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ITenant } from \"@twin.org/api-models\";\nimport type { HeaderTypes } from \"@twin.org/web\";\n\n/**\n * The list of tenants.\n */\nexport interface ITenantListResponse {\n\t/**\n\t * The headers which can be used to include the cursor.\n\t */\n\theaders?: {\n\t\t[HeaderTypes.Link]?: string | string[];\n\t};\n\n\t/**\n\t * The list of tenants.\n\t */\n\tbody: ITenant[];\n}\n"]}
@@ -0,0 +1,4 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ export {};
4
+ //# sourceMappingURL=ITenantRemoveRequest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ITenantRemoveRequest.js","sourceRoot":"","sources":["../../../../src/models/api/ITenantRemoveRequest.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n\n/**\n * The tenant to remove by id.\n */\nexport interface ITenantRemoveRequest {\n\t/**\n\t * The path parameters.\n\t */\n\tpathParams: {\n\t\t/**\n\t\t * The id of the tenant to remove.\n\t\t */\n\t\tid: string;\n\t};\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ITenantUpdateRequest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ITenantUpdateRequest.js","sourceRoot":"","sources":["../../../../src/models/api/ITenantUpdateRequest.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ITenant } from \"@twin.org/api-models\";\n\n/**\n * The tenant to update.\n */\nexport interface ITenantUpdateRequest {\n\t/**\n\t * The path parameters.\n\t */\n\tpathParams: {\n\t\t/**\n\t\t * The id of the tenant to update.\n\t\t */\n\t\tid: string;\n\t};\n\n\t/**\n\t * The tenant to update.\n\t */\n\tbody: Omit<ITenant, \"id\" | \"dateCreated\" | \"dateModified\">;\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import { generateRestRoutesTenants, tagsTenants } from "./tenantRoutes.js";
2
+ export const restEntryPoints = [
3
+ {
4
+ name: "tenants",
5
+ defaultBaseRoute: "tenants",
6
+ tags: tagsTenants,
7
+ generateRoutes: generateRestRoutesTenants
8
+ }
9
+ ];
10
+ //# sourceMappingURL=restEntryPoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restEntryPoints.js","sourceRoot":"","sources":["../../src/restEntryPoints.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE3E,MAAM,CAAC,MAAM,eAAe,GAA2B;IACtD;QACC,IAAI,EAAE,SAAS;QACf,gBAAgB,EAAE,SAAS;QAC3B,IAAI,EAAE,WAAW;QACjB,cAAc,EAAE,yBAAyB;KACzC;CACD,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IRestRouteEntryPoint } from \"@twin.org/api-models\";\nimport { generateRestRoutesTenants, tagsTenants } from \"./tenantRoutes.js\";\n\nexport const restEntryPoints: IRestRouteEntryPoint[] = [\n\t{\n\t\tname: \"tenants\",\n\t\tdefaultBaseRoute: \"tenants\",\n\t\ttags: tagsTenants,\n\t\tgenerateRoutes: generateRestRoutesTenants\n\t}\n];\n"]}
@@ -1,10 +1,9 @@
1
- // Copyright 2024 IOTA Stiftung.
2
- // SPDX-License-Identifier: Apache-2.0.
3
- import { Guards } from "@twin.org/core";
1
+ import { GeneralError, Guards, Is, NotFoundError, Url } from "@twin.org/core";
4
2
  import { EntityStorageConnectorFactory } from "@twin.org/entity-storage-models";
5
3
  import { Tenant } from "./entities/tenant.js";
4
+ import { TenantIdHelper } from "./utils/tenantIdHelper.js";
6
5
  /**
7
- * Service for performing email messaging operations to a connector.
6
+ * Service for performing tenant administration operations.
8
7
  */
9
8
  export class TenantAdminService {
10
9
  /**
@@ -33,43 +32,128 @@ export class TenantAdminService {
33
32
  /**
34
33
  * Get a tenant by its id.
35
34
  * @param tenantId The id of the tenant.
36
- * @returns The tenant or undefined if not found.
35
+ * @returns The tenant.
36
+ * @throws Error if the tenant is not found.
37
37
  */
38
38
  async get(tenantId) {
39
- Guards.stringValue(TenantAdminService.CLASS_NAME, "tenantId", tenantId);
39
+ Guards.stringHexLength(TenantAdminService.CLASS_NAME, "tenantId", tenantId, 32);
40
40
  let tenant;
41
41
  try {
42
42
  tenant = await this._entityStorageConnector.get(tenantId);
43
43
  }
44
44
  catch { }
45
+ if (!Is.object(tenant)) {
46
+ throw new NotFoundError(TenantAdminService.CLASS_NAME, "tenantNotFound", tenantId);
47
+ }
45
48
  return tenant;
46
49
  }
47
50
  /**
48
51
  * Get a tenant by its api key.
49
52
  * @param apiKey The api key of the tenant.
50
- * @returns The tenant or undefined if not found.
53
+ * @returns The tenant.
54
+ * @throws Error if the tenant is not found.
51
55
  */
52
56
  async getByApiKey(apiKey) {
53
- Guards.stringValue(TenantAdminService.CLASS_NAME, "apiKey", apiKey);
57
+ Guards.stringHexLength(TenantAdminService.CLASS_NAME, "apiKey", apiKey, 32);
54
58
  let tenant;
55
59
  try {
56
60
  tenant = await this._entityStorageConnector.get(apiKey, "apiKey");
57
61
  }
58
62
  catch { }
63
+ if (!Is.object(tenant)) {
64
+ throw new NotFoundError(TenantAdminService.CLASS_NAME, "tenantNotFound", apiKey);
65
+ }
66
+ return tenant;
67
+ }
68
+ /**
69
+ * Get a tenant by its public origin.
70
+ * @param publicOrigin The origin of the tenant.
71
+ * @returns The tenant.
72
+ * @throws Error if the tenant is not found.
73
+ */
74
+ async getByPublicOrigin(publicOrigin) {
75
+ Guards.stringValue(TenantAdminService.CLASS_NAME, "publicOrigin", publicOrigin);
76
+ let tenant;
77
+ try {
78
+ tenant = await this._entityStorageConnector.get(publicOrigin, "publicOrigin");
79
+ }
80
+ catch { }
81
+ if (!Is.object(tenant)) {
82
+ throw new NotFoundError(TenantAdminService.CLASS_NAME, "tenantNotFound", publicOrigin);
83
+ }
59
84
  return tenant;
60
85
  }
61
86
  /**
62
- * Set a tenant.
87
+ * Create a tenant.
63
88
  * @param tenant The tenant to store.
64
- * @returns Nothing.
89
+ * @returns The tenant id.
65
90
  */
66
- async set(tenant) {
91
+ async create(tenant) {
67
92
  Guards.objectValue(TenantAdminService.CLASS_NAME, "tenant", tenant);
93
+ if (Is.stringValue(tenant.id)) {
94
+ Guards.stringHexLength(TenantAdminService.CLASS_NAME, "tenant.id", tenant.id, 32);
95
+ }
96
+ if (Is.stringValue(tenant.apiKey)) {
97
+ Guards.stringHexLength(TenantAdminService.CLASS_NAME, "tenant.apiKey", tenant.apiKey, 32);
98
+ }
99
+ let publicOrigin;
100
+ if (Is.stringValue(tenant.publicOrigin)) {
101
+ Url.guard(TenantAdminService.CLASS_NAME, "tenant.publicOrigin", tenant.publicOrigin);
102
+ const url = new Url(tenant.publicOrigin);
103
+ const parts = url.parts();
104
+ publicOrigin = `${parts.schema}://${parts.host}${Is.integer(parts.port) ? `:${parts.port}` : ""}`;
105
+ }
106
+ if (Is.stringValue(tenant.apiKey)) {
107
+ const existingApiKey = await this._entityStorageConnector.get(tenant.apiKey, "apiKey");
108
+ if (Is.object(existingApiKey) && existingApiKey.id !== tenant.id) {
109
+ throw new GeneralError(TenantAdminService.CLASS_NAME, "apiKeyAlreadyInUse");
110
+ }
111
+ }
68
112
  const tenantEntity = new Tenant();
69
- tenantEntity.id = tenant.id;
70
- tenantEntity.apiKey = tenant.apiKey;
113
+ tenantEntity.id = tenant.id ?? TenantIdHelper.generateTenantId();
114
+ tenantEntity.apiKey = tenant.apiKey ?? TenantIdHelper.generateApiKey();
71
115
  tenantEntity.dateCreated = new Date(Date.now()).toISOString();
116
+ tenantEntity.dateModified = tenantEntity.dateCreated;
72
117
  tenantEntity.label = tenant.label;
118
+ tenantEntity.publicOrigin = publicOrigin;
119
+ await this._entityStorageConnector.set(tenantEntity);
120
+ return tenantEntity.id;
121
+ }
122
+ /**
123
+ * Update a tenant.
124
+ * @param tenant The tenant to update.
125
+ * @returns The nothing.
126
+ */
127
+ async update(tenant) {
128
+ Guards.objectValue(TenantAdminService.CLASS_NAME, "tenant", tenant);
129
+ Guards.stringHexLength(TenantAdminService.CLASS_NAME, "tenant.id", tenant.id, 32);
130
+ if (Is.stringValue(tenant.apiKey)) {
131
+ Guards.stringHexLength(TenantAdminService.CLASS_NAME, "tenant.apiKey", tenant.apiKey, 32);
132
+ }
133
+ let publicOrigin;
134
+ if (Is.stringValue(tenant.publicOrigin)) {
135
+ Url.guard(TenantAdminService.CLASS_NAME, "tenant.publicOrigin", tenant.publicOrigin);
136
+ const url = new Url(tenant.publicOrigin);
137
+ const parts = url.parts();
138
+ publicOrigin = `${parts.schema}://${parts.host}${Is.integer(parts.port) ? `:${parts.port}` : ""}`;
139
+ }
140
+ const currentTenant = await this._entityStorageConnector.get(tenant.id);
141
+ if (!Is.object(currentTenant)) {
142
+ throw new NotFoundError(TenantAdminService.CLASS_NAME, "tenantNotFound", tenant.id);
143
+ }
144
+ if (Is.stringValue(tenant.apiKey)) {
145
+ const existingApiKey = await this._entityStorageConnector.get(tenant.apiKey, "apiKey");
146
+ if (Is.object(existingApiKey) && existingApiKey.id !== currentTenant.id) {
147
+ throw new GeneralError(TenantAdminService.CLASS_NAME, "apiKeyAlreadyInUse");
148
+ }
149
+ }
150
+ const tenantEntity = new Tenant();
151
+ tenantEntity.id = tenant.id;
152
+ tenantEntity.apiKey = tenant.apiKey ?? currentTenant.apiKey;
153
+ tenantEntity.dateCreated = currentTenant.dateCreated;
154
+ tenantEntity.dateModified = new Date(Date.now()).toISOString();
155
+ tenantEntity.label = tenant.label ?? currentTenant.label;
156
+ tenantEntity.publicOrigin = publicOrigin ?? currentTenant.publicOrigin;
73
157
  await this._entityStorageConnector.set(tenantEntity);
74
158
  }
75
159
  /**
@@ -78,17 +162,18 @@ export class TenantAdminService {
78
162
  * @returns Nothing.
79
163
  */
80
164
  async remove(tenantId) {
81
- Guards.stringValue(TenantAdminService.CLASS_NAME, "tenantId", tenantId);
165
+ Guards.stringHexLength(TenantAdminService.CLASS_NAME, "tenantId", tenantId, 32);
82
166
  return this._entityStorageConnector.remove(tenantId);
83
167
  }
84
168
  /**
85
169
  * Query tenants with pagination.
170
+ * @param properties The properties to include in the returned tenants.
86
171
  * @param cursor The cursor to start from.
87
172
  * @param limit The maximum number of tenants to return.
88
173
  * @returns The tenants and the next cursor if more tenants are available.
89
174
  */
90
- async query(cursor, limit) {
91
- const result = await this._entityStorageConnector.query(undefined, undefined, undefined, cursor, limit);
175
+ async query(properties, cursor, limit) {
176
+ const result = await this._entityStorageConnector.query(undefined, undefined, properties, cursor, limit);
92
177
  return {
93
178
  tenants: result.entities,
94
179
  cursor: result.cursor
@@ -1 +1 @@
1
- {"version":3,"file":"tenantAdminService.js","sourceRoot":"","sources":["../../src/tenantAdminService.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EACN,6BAA6B,EAE7B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAK9C;;GAEG;AACH,MAAM,OAAO,kBAAkB;IAC9B;;OAEG;IACI,MAAM,CAAU,UAAU,wBAAwC;IAEzE;;;OAGG;IACc,uBAAuB,CAAkC;IAE1E;;;OAGG;IACH,YAAY,OAA+C;QAC1D,IAAI,CAAC,uBAAuB,GAAG,6BAA6B,CAAC,GAAG,CAC/D,OAAO,EAAE,uBAAuB,IAAI,QAAQ,CAC5C,CAAC;IACH,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,OAAO,kBAAkB,CAAC,UAAU,CAAC;IACtC,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,GAAG,CAAC,QAAgB;QAChC,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,UAAU,cAAoB,QAAQ,CAAC,CAAC;QAE9E,IAAI,MAAM,CAAC;QAEX,IAAI,CAAC;YACJ,MAAM,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QAEV,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,WAAW,CAAC,MAAc;QACtC,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,UAAU,YAAkB,MAAM,CAAC,CAAC;QAE1E,IAAI,MAAM,CAAC;QAEX,IAAI,CAAC;YACJ,MAAM,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACnE,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QAEV,OAAO,MAAM,CAAC;IACf,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,GAAG,CAAC,MAAe;QAC/B,MAAM,CAAC,WAAW,CAAU,kBAAkB,CAAC,UAAU,YAAkB,MAAM,CAAC,CAAC;QAEnF,MAAM,YAAY,GAAG,IAAI,MAAM,EAAE,CAAC;QAClC,YAAY,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;QAC5B,YAAY,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QACpC,YAAY,CAAC,WAAW,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9D,YAAY,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAElC,MAAM,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACtD,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,MAAM,CAAC,QAAgB;QACnC,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,UAAU,cAAoB,QAAQ,CAAC,CAAC;QAE9E,OAAO,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtD,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,KAAK,CACjB,MAAe,EACf,KAAc;QAEd,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,KAAK,CACtD,SAAS,EACT,SAAS,EACT,SAAS,EACT,MAAM,EACN,KAAK,CACL,CAAC;QAEF,OAAO;YACN,OAAO,EAAE,MAAM,CAAC,QAAqB;YACrC,MAAM,EAAE,MAAM,CAAC,MAAM;SACrB,CAAC;IACH,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Guards } from \"@twin.org/core\";\nimport {\n\tEntityStorageConnectorFactory,\n\ttype IEntityStorageConnector\n} from \"@twin.org/entity-storage-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { Tenant } from \"./entities/tenant.js\";\nimport type { ITenant } from \"./models/ITenant.js\";\nimport type { ITenantAdminComponent } from \"./models/ITenantAdminComponent.js\";\nimport type { ITenantAdminServiceConstructorOptions } from \"./models/ITenantAdminServiceConstructorOptions.js\";\n\n/**\n * Service for performing email messaging operations to a connector.\n */\nexport class TenantAdminService implements ITenantAdminComponent {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<TenantAdminService>();\n\n\t/**\n\t * Entity storage connector used by the service.\n\t * @internal\n\t */\n\tprivate readonly _entityStorageConnector: IEntityStorageConnector<Tenant>;\n\n\t/**\n\t * Create a new instance of TenantAdminService.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options?: ITenantAdminServiceConstructorOptions) {\n\t\tthis._entityStorageConnector = EntityStorageConnectorFactory.get(\n\t\t\toptions?.tenantEntityStorageType ?? \"tenant\"\n\t\t);\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn TenantAdminService.CLASS_NAME;\n\t}\n\n\t/**\n\t * Get a tenant by its id.\n\t * @param tenantId The id of the tenant.\n\t * @returns The tenant or undefined if not found.\n\t */\n\tpublic async get(tenantId: string): Promise<ITenant | undefined> {\n\t\tGuards.stringValue(TenantAdminService.CLASS_NAME, nameof(tenantId), tenantId);\n\n\t\tlet tenant;\n\n\t\ttry {\n\t\t\ttenant = await this._entityStorageConnector.get(tenantId);\n\t\t} catch {}\n\n\t\treturn tenant;\n\t}\n\n\t/**\n\t * Get a tenant by its api key.\n\t * @param apiKey The api key of the tenant.\n\t * @returns The tenant or undefined if not found.\n\t */\n\tpublic async getByApiKey(apiKey: string): Promise<ITenant | undefined> {\n\t\tGuards.stringValue(TenantAdminService.CLASS_NAME, nameof(apiKey), apiKey);\n\n\t\tlet tenant;\n\n\t\ttry {\n\t\t\ttenant = await this._entityStorageConnector.get(apiKey, \"apiKey\");\n\t\t} catch {}\n\n\t\treturn tenant;\n\t}\n\n\t/**\n\t * Set a tenant.\n\t * @param tenant The tenant to store.\n\t * @returns Nothing.\n\t */\n\tpublic async set(tenant: ITenant): Promise<void> {\n\t\tGuards.objectValue<ITenant>(TenantAdminService.CLASS_NAME, nameof(tenant), tenant);\n\n\t\tconst tenantEntity = new Tenant();\n\t\ttenantEntity.id = tenant.id;\n\t\ttenantEntity.apiKey = tenant.apiKey;\n\t\ttenantEntity.dateCreated = new Date(Date.now()).toISOString();\n\t\ttenantEntity.label = tenant.label;\n\n\t\tawait this._entityStorageConnector.set(tenantEntity);\n\t}\n\n\t/**\n\t * Remove a tenant by its id.\n\t * @param tenantId The id of the tenant.\n\t * @returns Nothing.\n\t */\n\tpublic async remove(tenantId: string): Promise<void> {\n\t\tGuards.stringValue(TenantAdminService.CLASS_NAME, nameof(tenantId), tenantId);\n\n\t\treturn this._entityStorageConnector.remove(tenantId);\n\t}\n\n\t/**\n\t * Query tenants with pagination.\n\t * @param cursor The cursor to start from.\n\t * @param limit The maximum number of tenants to return.\n\t * @returns The tenants and the next cursor if more tenants are available.\n\t */\n\tpublic async query(\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{ tenants: ITenant[]; cursor?: string }> {\n\t\tconst result = await this._entityStorageConnector.query(\n\t\t\tundefined,\n\t\t\tundefined,\n\t\t\tundefined,\n\t\t\tcursor,\n\t\t\tlimit\n\t\t);\n\n\t\treturn {\n\t\t\ttenants: result.entities as ITenant[],\n\t\t\tcursor: result.cursor\n\t\t};\n\t}\n}\n"]}
1
+ {"version":3,"file":"tenantAdminService.js","sourceRoot":"","sources":["../../src/tenantAdminService.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { ITenant, ITenantAdminComponent } from \"@twin.org/api-models\";\nimport { GeneralError, Guards, Is, NotFoundError, Url } from \"@twin.org/core\";\nimport {\n\tEntityStorageConnectorFactory,\n\ttype IEntityStorageConnector\n} from \"@twin.org/entity-storage-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { Tenant } from \"./entities/tenant.js\";\nimport type { ITenantAdminServiceConstructorOptions } from \"./models/ITenantAdminServiceConstructorOptions.js\";\nimport { TenantIdHelper } from \"./utils/tenantIdHelper.js\";\n\n/**\n * Service for performing tenant administration operations.\n */\nexport class TenantAdminService implements ITenantAdminComponent {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<TenantAdminService>();\n\n\t/**\n\t * Entity storage connector used by the service.\n\t * @internal\n\t */\n\tprivate readonly _entityStorageConnector: IEntityStorageConnector<Tenant>;\n\n\t/**\n\t * Create a new instance of TenantAdminService.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options?: ITenantAdminServiceConstructorOptions) {\n\t\tthis._entityStorageConnector = EntityStorageConnectorFactory.get(\n\t\t\toptions?.tenantEntityStorageType ?? \"tenant\"\n\t\t);\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn TenantAdminService.CLASS_NAME;\n\t}\n\n\t/**\n\t * Get a tenant by its id.\n\t * @param tenantId The id of the tenant.\n\t * @returns The tenant.\n\t * @throws Error if the tenant is not found.\n\t */\n\tpublic async get(tenantId: string): Promise<ITenant> {\n\t\tGuards.stringHexLength(TenantAdminService.CLASS_NAME, nameof(tenantId), tenantId, 32);\n\n\t\tlet tenant;\n\n\t\ttry {\n\t\t\ttenant = await this._entityStorageConnector.get(tenantId);\n\t\t} catch {}\n\n\t\tif (!Is.object(tenant)) {\n\t\t\tthrow new NotFoundError(TenantAdminService.CLASS_NAME, \"tenantNotFound\", tenantId);\n\t\t}\n\n\t\treturn tenant;\n\t}\n\n\t/**\n\t * Get a tenant by its api key.\n\t * @param apiKey The api key of the tenant.\n\t * @returns The tenant.\n\t * @throws Error if the tenant is not found.\n\t */\n\tpublic async getByApiKey(apiKey: string): Promise<ITenant> {\n\t\tGuards.stringHexLength(TenantAdminService.CLASS_NAME, nameof(apiKey), apiKey, 32);\n\n\t\tlet tenant;\n\n\t\ttry {\n\t\t\ttenant = await this._entityStorageConnector.get(apiKey, \"apiKey\");\n\t\t} catch {}\n\n\t\tif (!Is.object(tenant)) {\n\t\t\tthrow new NotFoundError(TenantAdminService.CLASS_NAME, \"tenantNotFound\", apiKey);\n\t\t}\n\n\t\treturn tenant;\n\t}\n\n\t/**\n\t * Get a tenant by its public origin.\n\t * @param publicOrigin The origin of the tenant.\n\t * @returns The tenant.\n\t * @throws Error if the tenant is not found.\n\t */\n\tpublic async getByPublicOrigin(publicOrigin: string): Promise<ITenant> {\n\t\tGuards.stringValue(TenantAdminService.CLASS_NAME, nameof(publicOrigin), publicOrigin);\n\n\t\tlet tenant;\n\n\t\ttry {\n\t\t\ttenant = await this._entityStorageConnector.get(publicOrigin, \"publicOrigin\");\n\t\t} catch {}\n\n\t\tif (!Is.object(tenant)) {\n\t\t\tthrow new NotFoundError(TenantAdminService.CLASS_NAME, \"tenantNotFound\", publicOrigin);\n\t\t}\n\n\t\treturn tenant;\n\t}\n\n\t/**\n\t * Create a tenant.\n\t * @param tenant The tenant to store.\n\t * @returns The tenant id.\n\t */\n\tpublic async create(\n\t\ttenant: Omit<ITenant, \"id\" | \"dateCreated\" | \"dateModified\"> & { id?: string }\n\t): Promise<string> {\n\t\tGuards.objectValue<ITenant>(TenantAdminService.CLASS_NAME, nameof(tenant), tenant);\n\t\tif (Is.stringValue(tenant.id)) {\n\t\t\tGuards.stringHexLength(TenantAdminService.CLASS_NAME, nameof(tenant.id), tenant.id, 32);\n\t\t}\n\t\tif (Is.stringValue(tenant.apiKey)) {\n\t\t\tGuards.stringHexLength(\n\t\t\t\tTenantAdminService.CLASS_NAME,\n\t\t\t\tnameof(tenant.apiKey),\n\t\t\t\ttenant.apiKey,\n\t\t\t\t32\n\t\t\t);\n\t\t}\n\n\t\tlet publicOrigin: string | undefined;\n\t\tif (Is.stringValue(tenant.publicOrigin)) {\n\t\t\tUrl.guard(TenantAdminService.CLASS_NAME, nameof(tenant.publicOrigin), tenant.publicOrigin);\n\n\t\t\tconst url = new Url(tenant.publicOrigin);\n\t\t\tconst parts = url.parts();\n\t\t\tpublicOrigin = `${parts.schema}://${parts.host}${Is.integer(parts.port) ? `:${parts.port}` : \"\"}`;\n\t\t}\n\n\t\tif (Is.stringValue(tenant.apiKey)) {\n\t\t\tconst existingApiKey = await this._entityStorageConnector.get(tenant.apiKey, \"apiKey\");\n\t\t\tif (Is.object(existingApiKey) && existingApiKey.id !== tenant.id) {\n\t\t\t\tthrow new GeneralError(TenantAdminService.CLASS_NAME, \"apiKeyAlreadyInUse\");\n\t\t\t}\n\t\t}\n\n\t\tconst tenantEntity = new Tenant();\n\t\ttenantEntity.id = tenant.id ?? TenantIdHelper.generateTenantId();\n\t\ttenantEntity.apiKey = tenant.apiKey ?? TenantIdHelper.generateApiKey();\n\t\ttenantEntity.dateCreated = new Date(Date.now()).toISOString();\n\t\ttenantEntity.dateModified = tenantEntity.dateCreated;\n\t\ttenantEntity.label = tenant.label;\n\t\ttenantEntity.publicOrigin = publicOrigin;\n\n\t\tawait this._entityStorageConnector.set(tenantEntity);\n\n\t\treturn tenantEntity.id;\n\t}\n\n\t/**\n\t * Update a tenant.\n\t * @param tenant The tenant to update.\n\t * @returns The nothing.\n\t */\n\tpublic async update(\n\t\ttenant: Partial<Omit<ITenant, \"dateCreated\" | \"dateModified\">>\n\t): Promise<void> {\n\t\tGuards.objectValue<ITenant>(TenantAdminService.CLASS_NAME, nameof(tenant), tenant);\n\t\tGuards.stringHexLength(TenantAdminService.CLASS_NAME, nameof(tenant.id), tenant.id, 32);\n\t\tif (Is.stringValue(tenant.apiKey)) {\n\t\t\tGuards.stringHexLength(\n\t\t\t\tTenantAdminService.CLASS_NAME,\n\t\t\t\tnameof(tenant.apiKey),\n\t\t\t\ttenant.apiKey,\n\t\t\t\t32\n\t\t\t);\n\t\t}\n\n\t\tlet publicOrigin: string | undefined;\n\t\tif (Is.stringValue(tenant.publicOrigin)) {\n\t\t\tUrl.guard(TenantAdminService.CLASS_NAME, nameof(tenant.publicOrigin), tenant.publicOrigin);\n\n\t\t\tconst url = new Url(tenant.publicOrigin);\n\t\t\tconst parts = url.parts();\n\t\t\tpublicOrigin = `${parts.schema}://${parts.host}${Is.integer(parts.port) ? `:${parts.port}` : \"\"}`;\n\t\t}\n\n\t\tconst currentTenant = await this._entityStorageConnector.get(tenant.id);\n\t\tif (!Is.object(currentTenant)) {\n\t\t\tthrow new NotFoundError(TenantAdminService.CLASS_NAME, \"tenantNotFound\", tenant.id);\n\t\t}\n\n\t\tif (Is.stringValue(tenant.apiKey)) {\n\t\t\tconst existingApiKey = await this._entityStorageConnector.get(tenant.apiKey, \"apiKey\");\n\t\t\tif (Is.object(existingApiKey) && existingApiKey.id !== currentTenant.id) {\n\t\t\t\tthrow new GeneralError(TenantAdminService.CLASS_NAME, \"apiKeyAlreadyInUse\");\n\t\t\t}\n\t\t}\n\n\t\tconst tenantEntity = new Tenant();\n\t\ttenantEntity.id = tenant.id;\n\t\ttenantEntity.apiKey = tenant.apiKey ?? currentTenant.apiKey;\n\t\ttenantEntity.dateCreated = currentTenant.dateCreated;\n\t\ttenantEntity.dateModified = new Date(Date.now()).toISOString();\n\t\ttenantEntity.label = tenant.label ?? currentTenant.label;\n\t\ttenantEntity.publicOrigin = publicOrigin ?? currentTenant.publicOrigin;\n\n\t\tawait this._entityStorageConnector.set(tenantEntity);\n\t}\n\n\t/**\n\t * Remove a tenant by its id.\n\t * @param tenantId The id of the tenant.\n\t * @returns Nothing.\n\t */\n\tpublic async remove(tenantId: string): Promise<void> {\n\t\tGuards.stringHexLength(TenantAdminService.CLASS_NAME, nameof(tenantId), tenantId, 32);\n\n\t\treturn this._entityStorageConnector.remove(tenantId);\n\t}\n\n\t/**\n\t * Query tenants with pagination.\n\t * @param properties The properties to include in the returned tenants.\n\t * @param cursor The cursor to start from.\n\t * @param limit The maximum number of tenants to return.\n\t * @returns The tenants and the next cursor if more tenants are available.\n\t */\n\tpublic async query(\n\t\tproperties: (keyof ITenant)[] | undefined,\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{ tenants: ITenant[]; cursor?: string }> {\n\t\tconst result = await this._entityStorageConnector.query(\n\t\t\tundefined,\n\t\t\tundefined,\n\t\t\tproperties,\n\t\t\tcursor,\n\t\t\tlimit\n\t\t);\n\n\t\treturn {\n\t\t\ttenants: result.entities as ITenant[],\n\t\t\tcursor: result.cursor\n\t\t};\n\t}\n}\n"]}
@@ -7,6 +7,13 @@ export class TenantIdContextIdHandler {
7
7
  * Runtime name for the class.
8
8
  */
9
9
  static CLASS_NAME = "TenantIdContextIdHandler";
10
+ /**
11
+ * The class name of the component.
12
+ * @returns The class name.
13
+ */
14
+ className() {
15
+ return TenantIdContextIdHandler.CLASS_NAME;
16
+ }
10
17
  /**
11
18
  * The short form of the tenant id is the base64 version to compact.
12
19
  * @param value The full context id value.
@@ -1 +1 @@
1
- {"version":3,"file":"tenantIdContextIdHandler.js","sourceRoot":"","sources":["../../src/tenantIdContextIdHandler.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAGnD;;GAEG;AACH,MAAM,OAAO,wBAAwB;IACpC;;OAEG;IACI,MAAM,CAAU,UAAU,8BAA8C;IAE/E;;;;OAIG;IACI,KAAK,CAAC,KAAa;QACzB,OAAO,SAAS,CAAC,gBAAgB,CAAC,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IAChE,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,KAAa;QACzB,MAAM,CAAC,eAAe,CAAC,wBAAwB,CAAC,UAAU,WAAiB,KAAK,EAAE,EAAE,CAAC,CAAC;IACvF,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IContextIdHandler } from \"@twin.org/context\";\nimport { Converter, Guards } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\n\n/**\n * Context Id handler for testing as a tenant id.\n */\nexport class TenantIdContextIdHandler implements IContextIdHandler {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<TenantIdContextIdHandler>();\n\n\t/**\n\t * The short form of the tenant id is the base64 version to compact.\n\t * @param value The full context id value.\n\t * @returns Short form string.\n\t */\n\tpublic short(value: string): string {\n\t\treturn Converter.bytesToBase64Url(Converter.hexToBytes(value));\n\t}\n\n\t/**\n\t * Guard the value ensuring length.\n\t * @param value The value to guard.\n\t * @throws GeneralError if the value is too short.\n\t */\n\tpublic guard(value: string): void {\n\t\tGuards.stringHexLength(TenantIdContextIdHandler.CLASS_NAME, nameof(value), value, 32);\n\t}\n}\n"]}
1
+ {"version":3,"file":"tenantIdContextIdHandler.js","sourceRoot":"","sources":["../../src/tenantIdContextIdHandler.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAGnD;;GAEG;AACH,MAAM,OAAO,wBAAwB;IACpC;;OAEG;IACI,MAAM,CAAU,UAAU,8BAA8C;IAE/E;;;OAGG;IACI,SAAS;QACf,OAAO,wBAAwB,CAAC,UAAU,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,KAAa;QACzB,OAAO,SAAS,CAAC,gBAAgB,CAAC,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IAChE,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,KAAa;QACzB,MAAM,CAAC,eAAe,CAAC,wBAAwB,CAAC,UAAU,WAAiB,KAAK,EAAE,EAAE,CAAC,CAAC;IACvF,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IContextIdHandler } from \"@twin.org/context\";\nimport { Converter, Guards } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\n\n/**\n * Context Id handler for testing as a tenant id.\n */\nexport class TenantIdContextIdHandler implements IContextIdHandler {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<TenantIdContextIdHandler>();\n\n\t/**\n\t * The class name of the component.\n\t * @returns The class name.\n\t */\n\tpublic className(): string {\n\t\treturn TenantIdContextIdHandler.CLASS_NAME;\n\t}\n\n\t/**\n\t * The short form of the tenant id is the base64 version to compact.\n\t * @param value The full context id value.\n\t * @returns Short form string.\n\t */\n\tpublic short(value: string): string {\n\t\treturn Converter.bytesToBase64Url(Converter.hexToBytes(value));\n\t}\n\n\t/**\n\t * Guard the value ensuring length.\n\t * @param value The value to guard.\n\t * @throws GeneralError if the value is too short.\n\t */\n\tpublic guard(value: string): void {\n\t\tGuards.stringHexLength(TenantIdContextIdHandler.CLASS_NAME, nameof(value), value, 32);\n\t}\n}\n"]}