@twin.org/api-service 0.0.3-next.48 → 0.0.3-next.49

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.
@@ -76,24 +76,24 @@ export class PlatformService {
76
76
  }
77
77
  }
78
78
  /**
79
- * Determines if the given URL is a local origin.
79
+ * Get the local origin context IDs for the given URL.
80
80
  * @param url The URL to check.
81
- * @returns A promise that resolves to true if the URL is a local origin, false otherwise.
81
+ * @returns A promise that resolves to the context IDs if the URL is a local origin, undefined otherwise.
82
82
  */
83
- async isLocalOrigin(url) {
83
+ async getLocalOriginContext(url) {
84
84
  Guards.stringValue(PlatformService.CLASS_NAME, "url", url);
85
85
  const origin = HttpUrlHelper.extractOrigin(url);
86
86
  if (!Is.stringValue(origin)) {
87
- return false;
87
+ return undefined;
88
88
  }
89
89
  const contextIds = await ContextIdStore.getContextIds();
90
90
  const publicOrigin = contextIds?.[HttpContextIdKeys.PublicOrigin];
91
91
  if (publicOrigin === origin) {
92
- return true;
92
+ return contextIds;
93
93
  }
94
94
  const localOrigin = contextIds?.[HttpContextIdKeys.LocalOrigin];
95
95
  if (localOrigin === origin) {
96
- return true;
96
+ return contextIds;
97
97
  }
98
98
  if (Is.empty(this._entityStorageConnector)) {
99
99
  this._entityStorageConnector = EntityStorageConnectorFactory.get(this._entityStorageConnectorType);
@@ -104,12 +104,16 @@ export class PlatformService {
104
104
  for (const tenant of result.entities) {
105
105
  const tenantPublicOrigin = tenant.publicOrigin;
106
106
  if (Is.stringValue(tenantPublicOrigin) && tenantPublicOrigin === origin) {
107
- return true;
107
+ return {
108
+ ...contextIds,
109
+ [ContextIdKeys.Tenant]: tenant.id,
110
+ [ContextIdKeys.Organization]: tenant.organizationId,
111
+ [HttpContextIdKeys.PublicOrigin]: tenantPublicOrigin
112
+ };
108
113
  }
109
114
  }
110
115
  cursor = result.cursor;
111
116
  } while (Is.stringValue(cursor));
112
- return false;
113
117
  }
114
118
  }
115
119
  //# sourceMappingURL=platformService.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"platformService.js","sourceRoot":"","sources":["../../src/platformService.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport {\n\tHttpContextIdKeys,\n\tHttpUrlHelper,\n\ttype IPlatformComponent,\n\ttype ITenant\n} from \"@twin.org/api-models\";\nimport { ContextIdKeys, ContextIdStore } from \"@twin.org/context\";\nimport { Guards, Is } from \"@twin.org/core\";\nimport {\n\tEntityStorageConnectorFactory,\n\ttype IEntityStorageConnector\n} from \"@twin.org/entity-storage-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { IPlatformServiceConstructorOptions } from \"./models/IPlatformServiceConstructorOptions.js\";\n\n/**\n * Service for performing platform operations.\n */\nexport class PlatformService implements IPlatformComponent {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<PlatformService>();\n\n\t/**\n\t * The type of entity storage connector to use for tenant lookups, if multi-tenant.\n\t * @internal\n\t */\n\tprivate readonly _entityStorageConnectorType: string;\n\n\t/**\n\t * Entity storage connector used by the service.\n\t * @internal\n\t */\n\tprivate _entityStorageConnector?: IEntityStorageConnector<ITenant>;\n\n\t/**\n\t * Indicates whether the service is running in a multi-tenant environment.\n\t * @internal\n\t */\n\tprivate readonly _isMultiTenant: boolean;\n\n\t/**\n\t * Create a new instance of PlatformService.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options?: IPlatformServiceConstructorOptions) {\n\t\tthis._entityStorageConnectorType = options?.tenantEntityStorageType ?? \"tenant\";\n\t\tthis._isMultiTenant = options?.config?.isMultiTenant ?? false;\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 PlatformService.CLASS_NAME;\n\t}\n\n\t/**\n\t * Indicates whether the component is running in a multi-tenant environment.\n\t * @returns True if the component is running in a multi-tenant environment, false otherwise.\n\t */\n\tpublic isMultiTenant(): boolean {\n\t\treturn this._isMultiTenant;\n\t}\n\n\t/**\n\t * Execute a method, if single tenant will run once, if multi-tenant will run for each tenant.\n\t * @param method The method to run for each tenant.\n\t * @returns A promise that resolves when the method has been executed for all applicable tenants.\n\t */\n\tpublic async execute(method: () => Promise<void>): Promise<void> {\n\t\tif (this._isMultiTenant) {\n\t\t\tif (Is.empty(this._entityStorageConnector)) {\n\t\t\t\tthis._entityStorageConnector = EntityStorageConnectorFactory.get(\n\t\t\t\t\tthis._entityStorageConnectorType\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet cursor: string | undefined;\n\n\t\t\tconst baseContextIds = (await ContextIdStore.getContextIds()) ?? {};\n\n\t\t\tdo {\n\t\t\t\tconst result = await this._entityStorageConnector.query(\n\t\t\t\t\tundefined,\n\t\t\t\t\tundefined,\n\t\t\t\t\t[\"id\"],\n\t\t\t\t\tcursor\n\t\t\t\t);\n\n\t\t\t\tfor (const tenant of result.entities) {\n\t\t\t\t\tawait ContextIdStore.run(\n\t\t\t\t\t\t{ ...baseContextIds, [ContextIdKeys.Tenant]: tenant.id },\n\t\t\t\t\t\tasync () => {\n\t\t\t\t\t\t\tawait method();\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tcursor = result.cursor;\n\t\t\t} while (Is.stringValue(cursor));\n\t\t} else {\n\t\t\tawait method();\n\t\t}\n\t}\n\n\t/**\n\t * Determines if the given URL is a local origin.\n\t * @param url The URL to check.\n\t * @returns A promise that resolves to true if the URL is a local origin, false otherwise.\n\t */\n\tpublic async isLocalOrigin(url: string): Promise<boolean> {\n\t\tGuards.stringValue(PlatformService.CLASS_NAME, nameof(url), url);\n\n\t\tconst origin = HttpUrlHelper.extractOrigin(url);\n\t\tif (!Is.stringValue(origin)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst publicOrigin = contextIds?.[HttpContextIdKeys.PublicOrigin];\n\t\tif (publicOrigin === origin) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst localOrigin = contextIds?.[HttpContextIdKeys.LocalOrigin];\n\t\tif (localOrigin === origin) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (Is.empty(this._entityStorageConnector)) {\n\t\t\tthis._entityStorageConnector = EntityStorageConnectorFactory.get(\n\t\t\t\tthis._entityStorageConnectorType\n\t\t\t);\n\t\t}\n\n\t\tlet cursor: string | undefined;\n\n\t\tdo {\n\t\t\tconst result = await this._entityStorageConnector.query(\n\t\t\t\tundefined,\n\t\t\t\tundefined,\n\t\t\t\t[\"publicOrigin\"],\n\t\t\t\tcursor\n\t\t\t);\n\t\t\tfor (const tenant of result.entities) {\n\t\t\t\tconst tenantPublicOrigin = tenant.publicOrigin;\n\n\t\t\t\tif (Is.stringValue(tenantPublicOrigin) && tenantPublicOrigin === origin) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcursor = result.cursor;\n\t\t} while (Is.stringValue(cursor));\n\n\t\treturn false;\n\t}\n}\n"]}
1
+ {"version":3,"file":"platformService.js","sourceRoot":"","sources":["../../src/platformService.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport {\n\tHttpContextIdKeys,\n\tHttpUrlHelper,\n\ttype IPlatformComponent,\n\ttype ITenant\n} from \"@twin.org/api-models\";\nimport { ContextIdKeys, ContextIdStore, type IContextIds } from \"@twin.org/context\";\nimport { Guards, Is } from \"@twin.org/core\";\nimport {\n\tEntityStorageConnectorFactory,\n\ttype IEntityStorageConnector\n} from \"@twin.org/entity-storage-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { IPlatformServiceConstructorOptions } from \"./models/IPlatformServiceConstructorOptions.js\";\n\n/**\n * Service for performing platform operations.\n */\nexport class PlatformService implements IPlatformComponent {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<PlatformService>();\n\n\t/**\n\t * The type of entity storage connector to use for tenant lookups, if multi-tenant.\n\t * @internal\n\t */\n\tprivate readonly _entityStorageConnectorType: string;\n\n\t/**\n\t * Entity storage connector used by the service.\n\t * @internal\n\t */\n\tprivate _entityStorageConnector?: IEntityStorageConnector<ITenant>;\n\n\t/**\n\t * Indicates whether the service is running in a multi-tenant environment.\n\t * @internal\n\t */\n\tprivate readonly _isMultiTenant: boolean;\n\n\t/**\n\t * Create a new instance of PlatformService.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options?: IPlatformServiceConstructorOptions) {\n\t\tthis._entityStorageConnectorType = options?.tenantEntityStorageType ?? \"tenant\";\n\t\tthis._isMultiTenant = options?.config?.isMultiTenant ?? false;\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 PlatformService.CLASS_NAME;\n\t}\n\n\t/**\n\t * Indicates whether the component is running in a multi-tenant environment.\n\t * @returns True if the component is running in a multi-tenant environment, false otherwise.\n\t */\n\tpublic isMultiTenant(): boolean {\n\t\treturn this._isMultiTenant;\n\t}\n\n\t/**\n\t * Execute a method, if single tenant will run once, if multi-tenant will run for each tenant.\n\t * @param method The method to run for each tenant.\n\t * @returns A promise that resolves when the method has been executed for all applicable tenants.\n\t */\n\tpublic async execute(method: () => Promise<void>): Promise<void> {\n\t\tif (this._isMultiTenant) {\n\t\t\tif (Is.empty(this._entityStorageConnector)) {\n\t\t\t\tthis._entityStorageConnector = EntityStorageConnectorFactory.get(\n\t\t\t\t\tthis._entityStorageConnectorType\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet cursor: string | undefined;\n\n\t\t\tconst baseContextIds = (await ContextIdStore.getContextIds()) ?? {};\n\n\t\t\tdo {\n\t\t\t\tconst result = await this._entityStorageConnector.query(\n\t\t\t\t\tundefined,\n\t\t\t\t\tundefined,\n\t\t\t\t\t[\"id\"],\n\t\t\t\t\tcursor\n\t\t\t\t);\n\n\t\t\t\tfor (const tenant of result.entities) {\n\t\t\t\t\tawait ContextIdStore.run(\n\t\t\t\t\t\t{ ...baseContextIds, [ContextIdKeys.Tenant]: tenant.id },\n\t\t\t\t\t\tasync () => {\n\t\t\t\t\t\t\tawait method();\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tcursor = result.cursor;\n\t\t\t} while (Is.stringValue(cursor));\n\t\t} else {\n\t\t\tawait method();\n\t\t}\n\t}\n\n\t/**\n\t * Get the local origin context IDs for the given URL.\n\t * @param url The URL to check.\n\t * @returns A promise that resolves to the context IDs if the URL is a local origin, undefined otherwise.\n\t */\n\tpublic async getLocalOriginContext(url: string): Promise<IContextIds | undefined> {\n\t\tGuards.stringValue(PlatformService.CLASS_NAME, nameof(url), url);\n\n\t\tconst origin = HttpUrlHelper.extractOrigin(url);\n\t\tif (!Is.stringValue(origin)) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst publicOrigin = contextIds?.[HttpContextIdKeys.PublicOrigin];\n\t\tif (publicOrigin === origin) {\n\t\t\treturn contextIds;\n\t\t}\n\n\t\tconst localOrigin = contextIds?.[HttpContextIdKeys.LocalOrigin];\n\t\tif (localOrigin === origin) {\n\t\t\treturn contextIds;\n\t\t}\n\n\t\tif (Is.empty(this._entityStorageConnector)) {\n\t\t\tthis._entityStorageConnector = EntityStorageConnectorFactory.get(\n\t\t\t\tthis._entityStorageConnectorType\n\t\t\t);\n\t\t}\n\n\t\tlet cursor: string | undefined;\n\n\t\tdo {\n\t\t\tconst result = await this._entityStorageConnector.query(\n\t\t\t\tundefined,\n\t\t\t\tundefined,\n\t\t\t\t[\"publicOrigin\"],\n\t\t\t\tcursor\n\t\t\t);\n\t\t\tfor (const tenant of result.entities) {\n\t\t\t\tconst tenantPublicOrigin = tenant.publicOrigin;\n\n\t\t\t\tif (Is.stringValue(tenantPublicOrigin) && tenantPublicOrigin === origin) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...contextIds,\n\t\t\t\t\t\t[ContextIdKeys.Tenant]: tenant.id,\n\t\t\t\t\t\t[ContextIdKeys.Organization]: tenant.organizationId,\n\t\t\t\t\t\t[HttpContextIdKeys.PublicOrigin]: tenantPublicOrigin\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcursor = result.cursor;\n\t\t} while (Is.stringValue(cursor));\n\t}\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { type IPlatformComponent } from "@twin.org/api-models";
2
+ import { type IContextIds } from "@twin.org/context";
2
3
  import type { IPlatformServiceConstructorOptions } from "./models/IPlatformServiceConstructorOptions.js";
3
4
  /**
4
5
  * Service for performing platform operations.
@@ -30,9 +31,9 @@ export declare class PlatformService implements IPlatformComponent {
30
31
  */
31
32
  execute(method: () => Promise<void>): Promise<void>;
32
33
  /**
33
- * Determines if the given URL is a local origin.
34
+ * Get the local origin context IDs for the given URL.
34
35
  * @param url The URL to check.
35
- * @returns A promise that resolves to true if the URL is a local origin, false otherwise.
36
+ * @returns A promise that resolves to the context IDs if the URL is a local origin, undefined otherwise.
36
37
  */
37
- isLocalOrigin(url: string): Promise<boolean>;
38
+ getLocalOriginContext(url: string): Promise<IContextIds | undefined>;
38
39
  }
package/docs/changelog.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.3-next.49](https://github.com/iotaledger/twin-api/compare/api-service-v0.0.3-next.48...api-service-v0.0.3-next.49) (2026-06-19)
4
+
5
+
6
+ ### Features
7
+
8
+ * add getLocalOriginContext ([bd3162f](https://github.com/iotaledger/twin-api/commit/bd3162f5b06e22bfb09a95bb9aca40471efe6a64))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/api-models bumped from 0.0.3-next.48 to 0.0.3-next.49
16
+
3
17
  ## [0.0.3-next.48](https://github.com/iotaledger/twin-api/compare/api-service-v0.0.3-next.47...api-service-v0.0.3-next.48) (2026-06-19)
4
18
 
5
19
 
@@ -98,11 +98,11 @@ A promise that resolves when the method has been executed for all applicable ten
98
98
 
99
99
  ***
100
100
 
101
- ### isLocalOrigin() {#islocalorigin}
101
+ ### getLocalOriginContext() {#getlocalorigincontext}
102
102
 
103
- > **isLocalOrigin**(`url`): `Promise`\<`boolean`\>
103
+ > **getLocalOriginContext**(`url`): `Promise`\<`IContextIds` \| `undefined`\>
104
104
 
105
- Determines if the given URL is a local origin.
105
+ Get the local origin context IDs for the given URL.
106
106
 
107
107
  #### Parameters
108
108
 
@@ -114,10 +114,10 @@ The URL to check.
114
114
 
115
115
  #### Returns
116
116
 
117
- `Promise`\<`boolean`\>
117
+ `Promise`\<`IContextIds` \| `undefined`\>
118
118
 
119
- A promise that resolves to true if the URL is a local origin, false otherwise.
119
+ A promise that resolves to the context IDs if the URL is a local origin, undefined otherwise.
120
120
 
121
121
  #### Implementation of
122
122
 
123
- `IPlatformComponent.isLocalOrigin`
123
+ `IPlatformComponent.getLocalOriginContext`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/api-service",
3
- "version": "0.0.3-next.48",
3
+ "version": "0.0.3-next.49",
4
4
  "description": "Information and hosting service implementations with generated REST route handlers.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -14,7 +14,7 @@
14
14
  "node": ">=20.0.0"
15
15
  },
16
16
  "dependencies": {
17
- "@twin.org/api-models": "0.0.3-next.48",
17
+ "@twin.org/api-models": "0.0.3-next.49",
18
18
  "@twin.org/context": "next",
19
19
  "@twin.org/core": "next",
20
20
  "@twin.org/engine-models": "next",