@topolo/sdk 0.2.12 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +220 -73
- package/dist/index.d.cts +105 -42
- package/dist/index.d.ts +105 -42
- package/dist/index.js +220 -72
- package/package.json +5 -2
- package/src/application-requirements.ts +10 -6
- package/src/applications.generated.ts +61 -40
- package/src/client.test.ts +172 -6
- package/src/client.ts +214 -2
- package/src/index.ts +1 -1
- package/src/modules/p2p.test.ts +27 -11
- package/src/services.generated.ts +2 -24
- package/src/services.test.ts +5 -13
- package/src/services.ts +1 -2
- package/src/widgets.test.ts +7 -7
package/README.md
CHANGED
|
@@ -103,7 +103,7 @@ their own `GET /api/widget` endpoint. The SDK owns the shared payload contract:
|
|
|
103
103
|
import { createTopoloWidgetResponse } from '@topolo/sdk';
|
|
104
104
|
|
|
105
105
|
return Response.json(createTopoloWidgetResponse({
|
|
106
|
-
serviceId: '
|
|
106
|
+
serviceId: '<runtime-service-id>',
|
|
107
107
|
serviceName: 'Example',
|
|
108
108
|
widgets: [
|
|
109
109
|
{
|
package/dist/index.cjs
CHANGED
|
@@ -27,7 +27,6 @@ __export(index_exports, {
|
|
|
27
27
|
DEFAULT_SERVICE_URLS: () => DEFAULT_SERVICE_URLS,
|
|
28
28
|
IdentityModule: () => IdentityModule,
|
|
29
29
|
P2PModule: () => P2PModule,
|
|
30
|
-
PLATFORM_SERVICE_IDS: () => PLATFORM_SERVICE_IDS,
|
|
31
30
|
TOPOLO_WIDGET_ENDPOINT: () => TOPOLO_WIDGET_ENDPOINT,
|
|
32
31
|
TOPOLO_WIDGET_REFRESH_INTERVAL_MS: () => TOPOLO_WIDGET_REFRESH_INTERVAL_MS,
|
|
33
32
|
TopoloAuthError: () => TopoloAuthError,
|
|
@@ -146,41 +145,20 @@ var SERVICES = {
|
|
|
146
145
|
p2p: "https://p2p.topolo.app",
|
|
147
146
|
pay: "https://pay.topolo.app",
|
|
148
147
|
people: "https://people.topolo.app",
|
|
148
|
+
pulse: "https://pulse.topolo.app",
|
|
149
149
|
"quro.api": "https://api.ol0.me",
|
|
150
150
|
"quro.redirect": "https://ol0.me",
|
|
151
151
|
roadmapper: "https://roadmapper-api.topolo.app",
|
|
152
152
|
sign: "https://sign.topolo.app",
|
|
153
153
|
social_studio: "https://studio-api.topolo.app",
|
|
154
154
|
socialize: "https://socialize-api.topolo.app",
|
|
155
|
+
spaces: "https://spaces.topolo.app",
|
|
155
156
|
status: "https://status.topolo.app",
|
|
156
157
|
support: "https://support.topolo.app",
|
|
157
158
|
survey: "https://survey.topolo.app",
|
|
158
159
|
voice: "https://voice.topolo.app",
|
|
159
160
|
web: "https://web-api.topolo.app"
|
|
160
161
|
};
|
|
161
|
-
var PLATFORM_SERVICE_IDS = {
|
|
162
|
-
books: "srv_0g260hbN8oqv",
|
|
163
|
-
bugfix: "srv_kQ1t8qUSDgNs",
|
|
164
|
-
compose: "srv_aR3ETYmgygmd",
|
|
165
|
-
consent: "srv_8FIGR7Q7zP9r",
|
|
166
|
-
crm: "srv_iCwM4jGXcwlj",
|
|
167
|
-
customer_success: "srv_RWpOxkgZdZbH",
|
|
168
|
-
developers: "srv_NjDq9G9qyyjr",
|
|
169
|
-
director: "srv_wRCnLLbtvmVT",
|
|
170
|
-
flow: "srv_GBCuKkHhnRXv",
|
|
171
|
-
forms: "srv_UE7IcGe80J5o",
|
|
172
|
-
home: "srv_hE6HBldVzjth",
|
|
173
|
-
insights: "srv_DgbBMwWSIhmC",
|
|
174
|
-
inventory: "srv_hmvjbv3ZxDnh",
|
|
175
|
-
localize: "srv_Ze1g9OmXuZjF",
|
|
176
|
-
notify: "srv_9pRdkIjYyKX0",
|
|
177
|
-
p2p: "srv_4BzeLqH0wCve",
|
|
178
|
-
people: "srv_VDMBAonA5fKb",
|
|
179
|
-
sign: "srv_Bd8pRw5ZqRBT",
|
|
180
|
-
status: "srv_topolo_status",
|
|
181
|
-
survey: "srv_RCOi7CJkwf7R",
|
|
182
|
-
voice: "srv_BZANHkshGAK5"
|
|
183
|
-
};
|
|
184
162
|
|
|
185
163
|
// src/applications.generated.ts
|
|
186
164
|
var APPLICATIONS = {
|
|
@@ -260,6 +238,24 @@ var APPLICATIONS = {
|
|
|
260
238
|
}
|
|
261
239
|
]
|
|
262
240
|
},
|
|
241
|
+
"backup": {
|
|
242
|
+
"id": "backup",
|
|
243
|
+
"appDir": "TopoloBackup",
|
|
244
|
+
"name": "topolo-backup",
|
|
245
|
+
"packageName": "topolo-backup",
|
|
246
|
+
"productionUrl": null,
|
|
247
|
+
"services": [],
|
|
248
|
+
"deployTargets": [
|
|
249
|
+
{
|
|
250
|
+
"name": "topolo-backup",
|
|
251
|
+
"kind": "worker",
|
|
252
|
+
"apiUrl": null,
|
|
253
|
+
"domains": [],
|
|
254
|
+
"routes": [],
|
|
255
|
+
"serviceId": null
|
|
256
|
+
}
|
|
257
|
+
]
|
|
258
|
+
},
|
|
263
259
|
"books": {
|
|
264
260
|
"id": "books",
|
|
265
261
|
"appDir": "TopoloBooks",
|
|
@@ -410,15 +406,6 @@ var APPLICATIONS = {
|
|
|
410
406
|
}
|
|
411
407
|
]
|
|
412
408
|
},
|
|
413
|
-
"cli": {
|
|
414
|
-
"id": "cli",
|
|
415
|
-
"appDir": "TopoloCli",
|
|
416
|
-
"name": "@topolo/cli",
|
|
417
|
-
"packageName": "@topolo/cli",
|
|
418
|
-
"productionUrl": null,
|
|
419
|
-
"services": [],
|
|
420
|
-
"deployTargets": []
|
|
421
|
-
},
|
|
422
409
|
"cloudcontrol": {
|
|
423
410
|
"id": "cloudcontrol",
|
|
424
411
|
"appDir": "TopoloCloudControl",
|
|
@@ -584,24 +571,6 @@ var APPLICATIONS = {
|
|
|
584
571
|
}
|
|
585
572
|
]
|
|
586
573
|
},
|
|
587
|
-
"d1_backup": {
|
|
588
|
-
"id": "d1_backup",
|
|
589
|
-
"appDir": "TopoloD1Backup",
|
|
590
|
-
"name": "topolo-d1-backup",
|
|
591
|
-
"packageName": "topolo-d1-backup",
|
|
592
|
-
"productionUrl": null,
|
|
593
|
-
"services": [],
|
|
594
|
-
"deployTargets": [
|
|
595
|
-
{
|
|
596
|
-
"name": "topolo-d1-backup",
|
|
597
|
-
"kind": "worker",
|
|
598
|
-
"apiUrl": null,
|
|
599
|
-
"domains": [],
|
|
600
|
-
"routes": [],
|
|
601
|
-
"serviceId": null
|
|
602
|
-
}
|
|
603
|
-
]
|
|
604
|
-
},
|
|
605
574
|
"developers": {
|
|
606
575
|
"id": "developers",
|
|
607
576
|
"appDir": "TopoloDevelopers",
|
|
@@ -944,15 +913,6 @@ var APPLICATIONS = {
|
|
|
944
913
|
}
|
|
945
914
|
]
|
|
946
915
|
},
|
|
947
|
-
"mcp": {
|
|
948
|
-
"id": "mcp",
|
|
949
|
-
"appDir": "TopoloMCP",
|
|
950
|
-
"name": "@topolo/mcp",
|
|
951
|
-
"packageName": "@topolo/mcp",
|
|
952
|
-
"productionUrl": null,
|
|
953
|
-
"services": [],
|
|
954
|
-
"deployTargets": []
|
|
955
|
-
},
|
|
956
916
|
"mdm": {
|
|
957
917
|
"id": "mdm",
|
|
958
918
|
"appDir": "TopoloMDM",
|
|
@@ -1087,7 +1047,7 @@ var APPLICATIONS = {
|
|
|
1087
1047
|
"one": {
|
|
1088
1048
|
"id": "one",
|
|
1089
1049
|
"appDir": "TopoloOne",
|
|
1090
|
-
"name": "
|
|
1050
|
+
"name": "TopoloOne",
|
|
1091
1051
|
"packageName": "topolo-oneclick-sso",
|
|
1092
1052
|
"productionUrl": "https://one.topolo.app",
|
|
1093
1053
|
"services": [
|
|
@@ -1208,9 +1168,24 @@ var APPLICATIONS = {
|
|
|
1208
1168
|
"appDir": "TopoloPulse",
|
|
1209
1169
|
"name": "topolo-pulse",
|
|
1210
1170
|
"packageName": "topolo-pulse",
|
|
1211
|
-
"productionUrl":
|
|
1212
|
-
"services": [
|
|
1213
|
-
|
|
1171
|
+
"productionUrl": "https://pulse.topolo.app",
|
|
1172
|
+
"services": [
|
|
1173
|
+
"pulse"
|
|
1174
|
+
],
|
|
1175
|
+
"deployTargets": [
|
|
1176
|
+
{
|
|
1177
|
+
"name": "topolo-pulse",
|
|
1178
|
+
"kind": "worker",
|
|
1179
|
+
"apiUrl": "https://pulse.topolo.app",
|
|
1180
|
+
"domains": [
|
|
1181
|
+
"pulse.topolo.app"
|
|
1182
|
+
],
|
|
1183
|
+
"routes": [
|
|
1184
|
+
"pulse.topolo.app"
|
|
1185
|
+
],
|
|
1186
|
+
"serviceId": "pulse"
|
|
1187
|
+
}
|
|
1188
|
+
]
|
|
1214
1189
|
},
|
|
1215
1190
|
"quro": {
|
|
1216
1191
|
"id": "quro",
|
|
@@ -1393,6 +1368,30 @@ var APPLICATIONS = {
|
|
|
1393
1368
|
}
|
|
1394
1369
|
]
|
|
1395
1370
|
},
|
|
1371
|
+
"spaces": {
|
|
1372
|
+
"id": "spaces",
|
|
1373
|
+
"appDir": "TopoloSpaces",
|
|
1374
|
+
"name": "topolo-spaces",
|
|
1375
|
+
"packageName": "@topolo/spaces",
|
|
1376
|
+
"productionUrl": "https://spaces.topolo.app",
|
|
1377
|
+
"services": [
|
|
1378
|
+
"spaces"
|
|
1379
|
+
],
|
|
1380
|
+
"deployTargets": [
|
|
1381
|
+
{
|
|
1382
|
+
"name": "topolo-spaces",
|
|
1383
|
+
"kind": "worker",
|
|
1384
|
+
"apiUrl": "https://spaces.topolo.app",
|
|
1385
|
+
"domains": [
|
|
1386
|
+
"spaces.topolo.app"
|
|
1387
|
+
],
|
|
1388
|
+
"routes": [
|
|
1389
|
+
"spaces.topolo.app"
|
|
1390
|
+
],
|
|
1391
|
+
"serviceId": "spaces"
|
|
1392
|
+
}
|
|
1393
|
+
]
|
|
1394
|
+
},
|
|
1396
1395
|
"status": {
|
|
1397
1396
|
"id": "status",
|
|
1398
1397
|
"appDir": "TopoloStatus",
|
|
@@ -1574,12 +1573,12 @@ var APPLICATION_REQUIREMENTS = [
|
|
|
1574
1573
|
summary: "Applications must derive identity, organization, scopes, and service entitlement from TopoloAuth rather than inventing parallel auth state.",
|
|
1575
1574
|
appliesTo: ["browser", "api", "tooling", "agent_surface"],
|
|
1576
1575
|
evidence: [
|
|
1577
|
-
"@topolo/auth-client or @topolo/
|
|
1576
|
+
"@topolo/auth-client or @topolo-io/worker-runtime is used where applicable",
|
|
1578
1577
|
"No public command, tool, or SDK method accepts orgId",
|
|
1579
1578
|
"Service slug and Auth service registration are documented for protected services"
|
|
1580
1579
|
],
|
|
1581
1580
|
implementation: [
|
|
1582
|
-
"Use shared auth packages instead of copying token parsing or browser storage flows",
|
|
1581
|
+
"Use shared auth/runtime packages instead of copying token parsing, gateway, or browser storage flows",
|
|
1583
1582
|
"Derive organization from the credential on every request",
|
|
1584
1583
|
"Route OAuth, refresh, logout, and SSO paths according to the shared Auth contract"
|
|
1585
1584
|
]
|
|
@@ -1719,14 +1718,15 @@ var APPLICATION_REQUIREMENTS = [
|
|
|
1719
1718
|
];
|
|
1720
1719
|
function applicationRequirementScopes(application) {
|
|
1721
1720
|
const scopes = /* @__PURE__ */ new Set(["all"]);
|
|
1721
|
+
const appId = application.id;
|
|
1722
1722
|
const hasBrowserSurface = Boolean(application.productionUrl) || application.deployTargets.some((target) => target.kind === "pages");
|
|
1723
1723
|
const hasApiSurface = application.services.length > 0 || application.deployTargets.some((target) => Boolean(target.apiUrl));
|
|
1724
1724
|
if (hasBrowserSurface) scopes.add("browser");
|
|
1725
1725
|
if (hasApiSurface) scopes.add("api");
|
|
1726
|
-
if (
|
|
1726
|
+
if (appId === "cli" || appId === "mcp" || appId === "cloudcontrol") {
|
|
1727
1727
|
scopes.add("tooling");
|
|
1728
1728
|
}
|
|
1729
|
-
if (
|
|
1729
|
+
if (appId === "cli" || appId === "mcp" || hasApiSurface) {
|
|
1730
1730
|
scopes.add("agent_surface");
|
|
1731
1731
|
}
|
|
1732
1732
|
return Array.from(scopes);
|
|
@@ -1845,12 +1845,13 @@ function evaluateRequirement(application, requirement) {
|
|
|
1845
1845
|
return finding(requirement, "met", "CloudControl deploy target metadata is present.", evidence);
|
|
1846
1846
|
}
|
|
1847
1847
|
case "agent-and-operator-surfaces": {
|
|
1848
|
+
const appId = application.id;
|
|
1848
1849
|
if (application.services.length > 0) {
|
|
1849
1850
|
evidence.push(`services=${application.services.join(",")}`);
|
|
1850
1851
|
return finding(requirement, "partial", "SDK service discovery exists; typed SDK/CLI/MCP workflow coverage should be checked as APIs stabilize.", evidence);
|
|
1851
1852
|
}
|
|
1852
|
-
if (
|
|
1853
|
-
evidence.push(`tooling=${
|
|
1853
|
+
if (appId === "cli" || appId === "mcp" || appId === "cloudcontrol") {
|
|
1854
|
+
evidence.push(`tooling=${appId}`);
|
|
1854
1855
|
return finding(requirement, "met", "This application is itself an agent/operator surface.", evidence);
|
|
1855
1856
|
}
|
|
1856
1857
|
return finding(requirement, "missing", "No SDK service or tooling surface is registered.", evidence);
|
|
@@ -1925,20 +1926,38 @@ function resolveServiceUrl(service, overrides) {
|
|
|
1925
1926
|
|
|
1926
1927
|
// src/client.ts
|
|
1927
1928
|
var WRITE_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
1928
|
-
var
|
|
1929
|
+
var POSITIVE_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
1930
|
+
var NEGATIVE_CACHE_TTL_MS = 60 * 1e3;
|
|
1931
|
+
var TopoloClient = class _TopoloClient {
|
|
1929
1932
|
credential;
|
|
1930
1933
|
agent;
|
|
1931
1934
|
serviceUrls;
|
|
1935
|
+
serviceIds;
|
|
1932
1936
|
requireConfirmForWrites;
|
|
1933
1937
|
timeoutMs;
|
|
1934
1938
|
fetchImpl;
|
|
1935
1939
|
debug;
|
|
1940
|
+
/**
|
|
1941
|
+
* Process-wide cache for slug → service-id lookups. Keyed by
|
|
1942
|
+
* `${authBaseUrl}|${slug}` so multiple `TopoloClient` instances pointing at
|
|
1943
|
+
* the same Auth share, but staging vs prod don't poison each other.
|
|
1944
|
+
* Cleared via `TopoloClient.clearServiceIdCache()` if a test needs it.
|
|
1945
|
+
*/
|
|
1946
|
+
static serviceIdCache = /* @__PURE__ */ new Map();
|
|
1947
|
+
/**
|
|
1948
|
+
* Drop the slug→service-id cache. Test-only — production callers should
|
|
1949
|
+
* let the 5-minute TTL expire naturally.
|
|
1950
|
+
*/
|
|
1951
|
+
static clearServiceIdCache() {
|
|
1952
|
+
_TopoloClient.serviceIdCache.clear();
|
|
1953
|
+
}
|
|
1936
1954
|
constructor(options) {
|
|
1937
1955
|
if (!options.credential) throw new TopoloAuthError("credential is required");
|
|
1938
1956
|
if (!options.agent?.clientName) throw new TopoloAuthError("agent.clientName is required");
|
|
1939
1957
|
this.credential = options.credential;
|
|
1940
1958
|
this.agent = options.agent;
|
|
1941
1959
|
this.serviceUrls = options.serviceUrls;
|
|
1960
|
+
this.serviceIds = options.serviceIds;
|
|
1942
1961
|
this.requireConfirmForWrites = options.requireConfirmForWrites !== false;
|
|
1943
1962
|
this.timeoutMs = options.timeoutMs ?? 3e4;
|
|
1944
1963
|
this.fetchImpl = options.fetch ?? fetch;
|
|
@@ -1973,7 +1992,7 @@ var TopoloClient = class {
|
|
|
1973
1992
|
const headers = new Headers();
|
|
1974
1993
|
headers.set("Accept", "application/json");
|
|
1975
1994
|
if (opts.body !== void 0) headers.set("Content-Type", "application/json");
|
|
1976
|
-
const platformServiceId =
|
|
1995
|
+
const platformServiceId = resolveConfiguredServiceId(opts.service, this.serviceIds);
|
|
1977
1996
|
if (platformServiceId) headers.set("X-Service-ID", platformServiceId);
|
|
1978
1997
|
applyAuthHeaders(headers, this.credential);
|
|
1979
1998
|
const requestId = generateRequestId();
|
|
@@ -2047,6 +2066,115 @@ var TopoloClient = class {
|
|
|
2047
2066
|
});
|
|
2048
2067
|
return parsed;
|
|
2049
2068
|
}
|
|
2069
|
+
/**
|
|
2070
|
+
* Resolve a service-slug → opaque service-id via caller config or TopoloAuth.
|
|
2071
|
+
*
|
|
2072
|
+
* Cache: 5 minutes per process per `(slug, auth_base_url)`. Negative
|
|
2073
|
+
* results (404) are cached for 60s so a typo doesn't hot-loop the
|
|
2074
|
+
* resolver. Returns null when the slug isn't registered — callers decide
|
|
2075
|
+
* whether to throw.
|
|
2076
|
+
*
|
|
2077
|
+
* No credential is sent: the endpoint is public (slugs aren't secret).
|
|
2078
|
+
* This keeps the resolver usable during early bootstrap before a caller
|
|
2079
|
+
* has acquired an access token.
|
|
2080
|
+
*/
|
|
2081
|
+
async getServiceIdBySlug(slug) {
|
|
2082
|
+
if (typeof slug !== "string") return null;
|
|
2083
|
+
const normalized = slug.trim().toLowerCase();
|
|
2084
|
+
if (!normalized) return null;
|
|
2085
|
+
const configuredServiceId = resolveConfiguredServiceId(normalized, this.serviceIds);
|
|
2086
|
+
if (configuredServiceId) return configuredServiceId;
|
|
2087
|
+
const authBase = resolveServiceUrl("auth", this.serviceUrls);
|
|
2088
|
+
const cacheKey = `${authBase}|${normalized}`;
|
|
2089
|
+
const now = Date.now();
|
|
2090
|
+
const cached = _TopoloClient.serviceIdCache.get(cacheKey);
|
|
2091
|
+
if (cached && cached.expiresAt > now) {
|
|
2092
|
+
return cached.value;
|
|
2093
|
+
}
|
|
2094
|
+
const url = new URL(
|
|
2095
|
+
`/api/services/by-slug/${encodeURIComponent(normalized)}`,
|
|
2096
|
+
authBase.endsWith("/") ? authBase : `${authBase}/`
|
|
2097
|
+
).toString();
|
|
2098
|
+
let res;
|
|
2099
|
+
try {
|
|
2100
|
+
res = await this.fetchImpl(url, {
|
|
2101
|
+
method: "GET",
|
|
2102
|
+
headers: { Accept: "application/json" }
|
|
2103
|
+
});
|
|
2104
|
+
} catch {
|
|
2105
|
+
return null;
|
|
2106
|
+
}
|
|
2107
|
+
if (res.status === 404) {
|
|
2108
|
+
_TopoloClient.serviceIdCache.set(cacheKey, {
|
|
2109
|
+
value: null,
|
|
2110
|
+
expiresAt: now + NEGATIVE_CACHE_TTL_MS
|
|
2111
|
+
});
|
|
2112
|
+
return null;
|
|
2113
|
+
}
|
|
2114
|
+
if (!res.ok) {
|
|
2115
|
+
return null;
|
|
2116
|
+
}
|
|
2117
|
+
const body = await res.json().catch(() => null);
|
|
2118
|
+
const serviceId = body?.data?.service_id;
|
|
2119
|
+
const value = typeof serviceId === "string" && serviceId ? serviceId : null;
|
|
2120
|
+
_TopoloClient.serviceIdCache.set(cacheKey, {
|
|
2121
|
+
value,
|
|
2122
|
+
expiresAt: now + POSITIVE_CACHE_TTL_MS
|
|
2123
|
+
});
|
|
2124
|
+
return value;
|
|
2125
|
+
}
|
|
2126
|
+
/**
|
|
2127
|
+
* List the platform service catalog from the live registry
|
|
2128
|
+
* (`GET /api/services/catalog` on TopoloAuth). Credential-aware: the
|
|
2129
|
+
* caller's credential is attached, so an authenticated caller in an
|
|
2130
|
+
* entitled org also receives the `developer_only` services its role
|
|
2131
|
+
* permits; an unauthenticated/agent caller receives `active` only.
|
|
2132
|
+
*
|
|
2133
|
+
* Resilient: on any network/HTTP failure this falls back to the
|
|
2134
|
+
* build-time generated `APPLICATIONS` snapshot so offline/degraded
|
|
2135
|
+
* callers still get a usable (if static) catalog. The live result is
|
|
2136
|
+
* authoritative; the snapshot is a floor, not a cap.
|
|
2137
|
+
*/
|
|
2138
|
+
async listServices() {
|
|
2139
|
+
try {
|
|
2140
|
+
const res = await this.request({ service: "auth", method: "GET", path: "/api/services/catalog" });
|
|
2141
|
+
const raw = res.data?.services ?? res.services;
|
|
2142
|
+
if (Array.isArray(raw) && raw.length > 0) {
|
|
2143
|
+
const entries = [];
|
|
2144
|
+
for (const item of raw) {
|
|
2145
|
+
const s = item;
|
|
2146
|
+
const serviceId = typeof s.service_id === "string" ? s.service_id : typeof s.id === "string" ? s.id : null;
|
|
2147
|
+
if (!serviceId) continue;
|
|
2148
|
+
entries.push({
|
|
2149
|
+
serviceId,
|
|
2150
|
+
slug: typeof s.app_slug === "string" ? s.app_slug : null,
|
|
2151
|
+
name: typeof s.name === "string" ? s.name : null,
|
|
2152
|
+
description: typeof s.description === "string" ? s.description : null,
|
|
2153
|
+
baseUrl: typeof s.base_url === "string" ? s.base_url : null,
|
|
2154
|
+
status: typeof s.status === "string" ? s.status : null,
|
|
2155
|
+
surfaceKind: typeof s.surface_kind === "string" ? s.surface_kind : null,
|
|
2156
|
+
launchable: s.launchable === true
|
|
2157
|
+
});
|
|
2158
|
+
}
|
|
2159
|
+
if (entries.length > 0) return entries;
|
|
2160
|
+
}
|
|
2161
|
+
} catch {
|
|
2162
|
+
}
|
|
2163
|
+
return this.generatedCatalogFallback();
|
|
2164
|
+
}
|
|
2165
|
+
generatedCatalogFallback() {
|
|
2166
|
+
const apps = Object.values(APPLICATIONS);
|
|
2167
|
+
return apps.map((app) => ({
|
|
2168
|
+
serviceId: app.id,
|
|
2169
|
+
slug: app.id,
|
|
2170
|
+
name: app.name ?? app.id,
|
|
2171
|
+
description: null,
|
|
2172
|
+
baseUrl: app.productionUrl ?? null,
|
|
2173
|
+
status: "active",
|
|
2174
|
+
surfaceKind: "application",
|
|
2175
|
+
launchable: Boolean(app.productionUrl)
|
|
2176
|
+
}));
|
|
2177
|
+
}
|
|
2050
2178
|
/**
|
|
2051
2179
|
* Introspect the current credential. Returns the caller's resolved identity,
|
|
2052
2180
|
* organization, and permission set. Used by CLI `whoami` and by MCP to gate
|
|
@@ -2083,6 +2211,26 @@ var TopoloClient = class {
|
|
|
2083
2211
|
};
|
|
2084
2212
|
}
|
|
2085
2213
|
};
|
|
2214
|
+
function resolveConfiguredServiceId(slug, serviceIds) {
|
|
2215
|
+
for (const serviceKey of serviceKeyCandidates(slug)) {
|
|
2216
|
+
const configured = serviceIds?.[serviceKey];
|
|
2217
|
+
if (typeof configured === "string" && configured.trim()) return configured.trim();
|
|
2218
|
+
const envKey = `TOPOLO_SERVICE_ID_${serviceKey.replace(/\./g, "_").toUpperCase()}`;
|
|
2219
|
+
const envValue = typeof process !== "undefined" ? process.env?.[envKey] : void 0;
|
|
2220
|
+
if (typeof envValue === "string" && envValue.trim()) return envValue.trim();
|
|
2221
|
+
}
|
|
2222
|
+
return null;
|
|
2223
|
+
}
|
|
2224
|
+
function serviceKeyCandidates(slug) {
|
|
2225
|
+
const normalized = slug.trim().toLowerCase();
|
|
2226
|
+
const withoutTopolo = normalized.startsWith("topolo-") ? normalized.slice("topolo-".length) : normalized;
|
|
2227
|
+
return [.../* @__PURE__ */ new Set([
|
|
2228
|
+
normalized,
|
|
2229
|
+
normalized.replace(/-/g, "_"),
|
|
2230
|
+
withoutTopolo,
|
|
2231
|
+
withoutTopolo.replace(/-/g, "_")
|
|
2232
|
+
])];
|
|
2233
|
+
}
|
|
2086
2234
|
function describeError(body, fallback) {
|
|
2087
2235
|
if (body && typeof body === "object") {
|
|
2088
2236
|
const maybe = body;
|
|
@@ -2649,7 +2797,6 @@ function createTopolo(options) {
|
|
|
2649
2797
|
DEFAULT_SERVICE_URLS,
|
|
2650
2798
|
IdentityModule,
|
|
2651
2799
|
P2PModule,
|
|
2652
|
-
PLATFORM_SERVICE_IDS,
|
|
2653
2800
|
TOPOLO_WIDGET_ENDPOINT,
|
|
2654
2801
|
TOPOLO_WIDGET_REFRESH_INTERVAL_MS,
|
|
2655
2802
|
TopoloAuthError,
|