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

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.
@@ -1,5 +1,8 @@
1
+ // Copyright 2026 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ import { HttpContextIdKeys, HttpUrlHelper } from "@twin.org/api-models";
1
4
  import { ContextIdKeys, ContextIdStore } from "@twin.org/context";
2
- import { Is } from "@twin.org/core";
5
+ import { Guards, Is } from "@twin.org/core";
3
6
  import { EntityStorageConnectorFactory } from "@twin.org/entity-storage-models";
4
7
  /**
5
8
  * Service for performing platform operations.
@@ -72,5 +75,41 @@ export class PlatformService {
72
75
  await method();
73
76
  }
74
77
  }
78
+ /**
79
+ * Determines if the given URL is a local origin.
80
+ * @param url The URL to check.
81
+ * @returns A promise that resolves to true if the URL is a local origin, false otherwise.
82
+ */
83
+ async isLocalOrigin(url) {
84
+ Guards.stringValue(PlatformService.CLASS_NAME, "url", url);
85
+ const origin = HttpUrlHelper.extractOrigin(url);
86
+ if (!Is.stringValue(origin)) {
87
+ return false;
88
+ }
89
+ const contextIds = await ContextIdStore.getContextIds();
90
+ const publicOrigin = contextIds?.[HttpContextIdKeys.PublicOrigin];
91
+ if (publicOrigin === origin) {
92
+ return true;
93
+ }
94
+ const localOrigin = contextIds?.[HttpContextIdKeys.LocalOrigin];
95
+ if (localOrigin === origin) {
96
+ return true;
97
+ }
98
+ if (Is.empty(this._entityStorageConnector)) {
99
+ this._entityStorageConnector = EntityStorageConnectorFactory.get(this._entityStorageConnectorType);
100
+ }
101
+ let cursor;
102
+ do {
103
+ const result = await this._entityStorageConnector.query(undefined, undefined, ["publicOrigin"], cursor);
104
+ for (const tenant of result.entities) {
105
+ const tenantPublicOrigin = tenant.publicOrigin;
106
+ if (Is.stringValue(tenantPublicOrigin) && tenantPublicOrigin === origin) {
107
+ return true;
108
+ }
109
+ }
110
+ cursor = result.cursor;
111
+ } while (Is.stringValue(cursor));
112
+ return false;
113
+ }
75
114
  }
76
115
  //# sourceMappingURL=platformService.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"platformService.js","sourceRoot":"","sources":["../../src/platformService.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AACpC,OAAO,EACN,6BAA6B,EAE7B,MAAM,iCAAiC,CAAC;AAIzC;;GAEG;AACH,MAAM,OAAO,eAAe;IAC3B;;OAEG;IACI,MAAM,CAAU,UAAU,qBAAqC;IAEtE;;;OAGG;IACc,2BAA2B,CAAS;IAErD;;;OAGG;IACK,uBAAuB,CAAoC;IAEnE;;;OAGG;IACc,cAAc,CAAU;IAEzC;;;OAGG;IACH,YAAY,OAA4C;QACvD,IAAI,CAAC,2BAA2B,GAAG,OAAO,EAAE,uBAAuB,IAAI,QAAQ,CAAC;QAChF,IAAI,CAAC,cAAc,GAAG,OAAO,EAAE,MAAM,EAAE,aAAa,IAAI,KAAK,CAAC;IAC/D,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,OAAO,eAAe,CAAC,UAAU,CAAC;IACnC,CAAC;IAED;;;OAGG;IACI,aAAa;QACnB,OAAO,IAAI,CAAC,cAAc,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,OAAO,CAAC,MAA2B;QAC/C,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC,uBAAuB,GAAG,6BAA6B,CAAC,GAAG,CAC/D,IAAI,CAAC,2BAA2B,CAChC,CAAC;YACH,CAAC;YAED,IAAI,MAA0B,CAAC;YAE/B,MAAM,cAAc,GAAG,CAAC,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,CAAC;YAEpE,GAAG,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,KAAK,CACtD,SAAS,EACT,SAAS,EACT,CAAC,IAAI,CAAC,EACN,MAAM,CACN,CAAC;gBAEF,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;oBACtC,MAAM,cAAc,CAAC,GAAG,CACvB,EAAE,GAAG,cAAc,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,EACxD,KAAK,IAAI,EAAE;wBACV,MAAM,MAAM,EAAE,CAAC;oBAChB,CAAC,CACD,CAAC;gBACH,CAAC;gBAED,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YACxB,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE;QAClC,CAAC;aAAM,CAAC;YACP,MAAM,MAAM,EAAE,CAAC;QAChB,CAAC;IACF,CAAC","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IPlatformComponent, ITenant } from \"@twin.org/api-models\";\nimport { ContextIdKeys, ContextIdStore } from \"@twin.org/context\";\nimport { 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"]}
1
+ {"version":3,"file":"platformService.js","sourceRoot":"","sources":["../../src/platformService.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EACN,iBAAiB,EACjB,aAAa,EAGb,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EACN,6BAA6B,EAE7B,MAAM,iCAAiC,CAAC;AAIzC;;GAEG;AACH,MAAM,OAAO,eAAe;IAC3B;;OAEG;IACI,MAAM,CAAU,UAAU,qBAAqC;IAEtE;;;OAGG;IACc,2BAA2B,CAAS;IAErD;;;OAGG;IACK,uBAAuB,CAAoC;IAEnE;;;OAGG;IACc,cAAc,CAAU;IAEzC;;;OAGG;IACH,YAAY,OAA4C;QACvD,IAAI,CAAC,2BAA2B,GAAG,OAAO,EAAE,uBAAuB,IAAI,QAAQ,CAAC;QAChF,IAAI,CAAC,cAAc,GAAG,OAAO,EAAE,MAAM,EAAE,aAAa,IAAI,KAAK,CAAC;IAC/D,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,OAAO,eAAe,CAAC,UAAU,CAAC;IACnC,CAAC;IAED;;;OAGG;IACI,aAAa;QACnB,OAAO,IAAI,CAAC,cAAc,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,OAAO,CAAC,MAA2B;QAC/C,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC,uBAAuB,GAAG,6BAA6B,CAAC,GAAG,CAC/D,IAAI,CAAC,2BAA2B,CAChC,CAAC;YACH,CAAC;YAED,IAAI,MAA0B,CAAC;YAE/B,MAAM,cAAc,GAAG,CAAC,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,CAAC;YAEpE,GAAG,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,KAAK,CACtD,SAAS,EACT,SAAS,EACT,CAAC,IAAI,CAAC,EACN,MAAM,CACN,CAAC;gBAEF,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;oBACtC,MAAM,cAAc,CAAC,GAAG,CACvB,EAAE,GAAG,cAAc,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,EACxD,KAAK,IAAI,EAAE;wBACV,MAAM,MAAM,EAAE,CAAC;oBAChB,CAAC,CACD,CAAC;gBACH,CAAC;gBAED,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YACxB,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE;QAClC,CAAC;aAAM,CAAC;YACP,MAAM,MAAM,EAAE,CAAC;QAChB,CAAC;IACF,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,aAAa,CAAC,GAAW;QACrC,MAAM,CAAC,WAAW,CAAC,eAAe,CAAC,UAAU,SAAe,GAAG,CAAC,CAAC;QAEjE,MAAM,MAAM,GAAG,aAAa,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAChD,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,OAAO,KAAK,CAAC;QACd,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,YAAY,GAAG,UAAU,EAAE,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAClE,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,WAAW,GAAG,UAAU,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;QAChE,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QACb,CAAC;QAED,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,EAAE,CAAC;YAC5C,IAAI,CAAC,uBAAuB,GAAG,6BAA6B,CAAC,GAAG,CAC/D,IAAI,CAAC,2BAA2B,CAChC,CAAC;QACH,CAAC;QAED,IAAI,MAA0B,CAAC;QAE/B,GAAG,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,KAAK,CACtD,SAAS,EACT,SAAS,EACT,CAAC,cAAc,CAAC,EAChB,MAAM,CACN,CAAC;YACF,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACtC,MAAM,kBAAkB,GAAG,MAAM,CAAC,YAAY,CAAC;gBAE/C,IAAI,EAAE,CAAC,WAAW,CAAC,kBAAkB,CAAC,IAAI,kBAAkB,KAAK,MAAM,EAAE,CAAC;oBACzE,OAAO,IAAI,CAAC;gBACb,CAAC;YACF,CAAC;YAED,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QACxB,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE;QAEjC,OAAO,KAAK,CAAC;IACd,CAAC","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,4 +1,4 @@
1
- import type { IPlatformComponent } from "@twin.org/api-models";
1
+ import { type IPlatformComponent } from "@twin.org/api-models";
2
2
  import type { IPlatformServiceConstructorOptions } from "./models/IPlatformServiceConstructorOptions.js";
3
3
  /**
4
4
  * Service for performing platform operations.
@@ -29,4 +29,10 @@ export declare class PlatformService implements IPlatformComponent {
29
29
  * @returns A promise that resolves when the method has been executed for all applicable tenants.
30
30
  */
31
31
  execute(method: () => Promise<void>): Promise<void>;
32
+ /**
33
+ * Determines if the given URL is a local origin.
34
+ * @param url The URL to check.
35
+ * @returns A promise that resolves to true if the URL is a local origin, false otherwise.
36
+ */
37
+ isLocalOrigin(url: string): Promise<boolean>;
32
38
  }
package/docs/changelog.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [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
+
5
+
6
+ ### Features
7
+
8
+ * add platform isLocalOrigin ([#173](https://github.com/iotaledger/twin-api/issues/173)) ([5e024d5](https://github.com/iotaledger/twin-api/commit/5e024d55c0201a5109ad9c688c0e755fe50cb554))
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.47 to 0.0.3-next.48
16
+
3
17
  ## [0.0.3-next.47](https://github.com/iotaledger/twin-api/compare/api-service-v0.0.3-next.46...api-service-v0.0.3-next.47) (2026-06-18)
4
18
 
5
19
 
@@ -95,3 +95,29 @@ A promise that resolves when the method has been executed for all applicable ten
95
95
  #### Implementation of
96
96
 
97
97
  `IPlatformComponent.execute`
98
+
99
+ ***
100
+
101
+ ### isLocalOrigin() {#islocalorigin}
102
+
103
+ > **isLocalOrigin**(`url`): `Promise`\<`boolean`\>
104
+
105
+ Determines if the given URL is a local origin.
106
+
107
+ #### Parameters
108
+
109
+ ##### url
110
+
111
+ `string`
112
+
113
+ The URL to check.
114
+
115
+ #### Returns
116
+
117
+ `Promise`\<`boolean`\>
118
+
119
+ A promise that resolves to true if the URL is a local origin, false otherwise.
120
+
121
+ #### Implementation of
122
+
123
+ `IPlatformComponent.isLocalOrigin`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/api-service",
3
- "version": "0.0.3-next.47",
3
+ "version": "0.0.3-next.48",
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.47",
17
+ "@twin.org/api-models": "0.0.3-next.48",
18
18
  "@twin.org/context": "next",
19
19
  "@twin.org/core": "next",
20
20
  "@twin.org/engine-models": "next",