@topolo/sdk 0.10.3 → 0.10.4
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/dist/index.cjs +450 -33
- package/dist/index.d.cts +119 -1
- package/dist/index.d.ts +119 -1
- package/dist/index.js +436 -33
- package/dist/node/credential-store.cjs +254 -25
- package/dist/node/credential-store.d.cts +10 -3
- package/dist/node/credential-store.d.ts +10 -3
- package/dist/node/credential-store.js +251 -25
- package/package.json +2 -2
|
@@ -13,6 +13,90 @@ var TopoloSdkError = class extends Error {
|
|
|
13
13
|
this.code = code;
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
|
+
var PUBLIC_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
17
|
+
"action_app_identity_unavailable",
|
|
18
|
+
"action_authentication_required",
|
|
19
|
+
"action_catalog_summary_unavailable",
|
|
20
|
+
"action_catalog_unavailable",
|
|
21
|
+
"action_contract_mismatch",
|
|
22
|
+
"action_permission_required",
|
|
23
|
+
"action_runtime_authorization_required",
|
|
24
|
+
"action_service_not_allowed",
|
|
25
|
+
"auth_error",
|
|
26
|
+
"authentication_required",
|
|
27
|
+
"authorization_pending",
|
|
28
|
+
"bad_sig",
|
|
29
|
+
"confirmation_required",
|
|
30
|
+
"dependency_unavailable",
|
|
31
|
+
"environment_mismatch",
|
|
32
|
+
"environment_service_url_required",
|
|
33
|
+
"expired_token",
|
|
34
|
+
"forbidden",
|
|
35
|
+
"http_error",
|
|
36
|
+
"immutable_drift",
|
|
37
|
+
"integration_dependency_unavailable",
|
|
38
|
+
"integration_misconfigured",
|
|
39
|
+
"invalid_action",
|
|
40
|
+
"invalid_action_input",
|
|
41
|
+
"invalid_grant",
|
|
42
|
+
"invalid_input",
|
|
43
|
+
"invalid_token",
|
|
44
|
+
"mcp_error",
|
|
45
|
+
"membership_required",
|
|
46
|
+
"network_error",
|
|
47
|
+
"organization_context_required",
|
|
48
|
+
"organization_enrollment_required",
|
|
49
|
+
"permission_denied",
|
|
50
|
+
"rate_limited",
|
|
51
|
+
"request_failed",
|
|
52
|
+
"service_catalog_unavailable",
|
|
53
|
+
"service_path_origin_mismatch",
|
|
54
|
+
"service_required",
|
|
55
|
+
"slow_down",
|
|
56
|
+
"state_conflict",
|
|
57
|
+
"unauthorized",
|
|
58
|
+
"unknown_action",
|
|
59
|
+
"unknown_service"
|
|
60
|
+
]);
|
|
61
|
+
var ERROR_CODE_PATTERN = /^[a-z][a-z0-9_]{0,63}$/;
|
|
62
|
+
var TOPOLO_REQUEST_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
63
|
+
var CLOUDFLARE_RAY_ID_PATTERN = /^[0-9a-f]{16}-[A-Z]{3}$/;
|
|
64
|
+
var PERMISSION_PATTERN = /^[a-z][a-z0-9_-]{0,63}(?:\.[a-z][a-z0-9_-]{0,63})*:(?:[a-z][a-z0-9_-]{0,63}|\*)$/;
|
|
65
|
+
var RETRY_AFTER_DATE_PATTERN = /^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), \d{2} (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d{4} \d{2}:\d{2}:\d{2} GMT$/;
|
|
66
|
+
var PUBLIC_DETAIL_SOURCES = /* @__PURE__ */ new Set([
|
|
67
|
+
"api_key_introspection",
|
|
68
|
+
"api_key_validation",
|
|
69
|
+
"auth_context",
|
|
70
|
+
"auth_validate",
|
|
71
|
+
"catalog",
|
|
72
|
+
"credential",
|
|
73
|
+
"runtime",
|
|
74
|
+
"service_token_provider",
|
|
75
|
+
"service_verify_key",
|
|
76
|
+
"token_validation",
|
|
77
|
+
"upstream"
|
|
78
|
+
]);
|
|
79
|
+
function canonicalTopoloErrorCode(value) {
|
|
80
|
+
if (typeof value !== "string") return null;
|
|
81
|
+
const candidate = value.trim().toLowerCase();
|
|
82
|
+
if (!ERROR_CODE_PATTERN.test(candidate) || !PUBLIC_ERROR_CODES.has(candidate)) return null;
|
|
83
|
+
return candidate;
|
|
84
|
+
}
|
|
85
|
+
function canonicalTopoloRequestId(value) {
|
|
86
|
+
if (typeof value !== "string") return void 0;
|
|
87
|
+
const candidate = value.trim();
|
|
88
|
+
return TOPOLO_REQUEST_ID_PATTERN.test(candidate) || CLOUDFLARE_RAY_ID_PATTERN.test(candidate) ? candidate : void 0;
|
|
89
|
+
}
|
|
90
|
+
function canonicalTopoloRetryAfter(value) {
|
|
91
|
+
if (typeof value !== "string") return void 0;
|
|
92
|
+
const candidate = value.trim();
|
|
93
|
+
if (/^\d{1,10}$/.test(candidate) || RETRY_AFTER_DATE_PATTERN.test(candidate)) return candidate;
|
|
94
|
+
return void 0;
|
|
95
|
+
}
|
|
96
|
+
function canonicalTopoloRequired(value) {
|
|
97
|
+
if (!Array.isArray(value)) return [];
|
|
98
|
+
return [...new Set(value.filter((item) => typeof item === "string" && PERMISSION_PATTERN.test(item)))].slice(0, 32);
|
|
99
|
+
}
|
|
16
100
|
var TopoloAuthError = class extends TopoloSdkError {
|
|
17
101
|
status;
|
|
18
102
|
body;
|
|
@@ -20,27 +104,91 @@ var TopoloAuthError = class extends TopoloSdkError {
|
|
|
20
104
|
path;
|
|
21
105
|
requestId;
|
|
22
106
|
retryAfter;
|
|
107
|
+
details;
|
|
23
108
|
constructor(message, code = "auth_error", options = {}) {
|
|
24
|
-
super(code, message);
|
|
109
|
+
super(canonicalTopoloErrorCode(code) ?? "auth_error", message);
|
|
25
110
|
this.name = "TopoloAuthError";
|
|
26
111
|
this.status = options.status ?? 401;
|
|
27
112
|
this.body = options.body;
|
|
28
113
|
this.service = options.service;
|
|
29
114
|
this.path = options.path;
|
|
30
|
-
this.requestId = options.requestId;
|
|
31
|
-
this.retryAfter = options.retryAfter;
|
|
115
|
+
this.requestId = canonicalTopoloRequestId(options.requestId);
|
|
116
|
+
this.retryAfter = canonicalTopoloRetryAfter(options.retryAfter);
|
|
117
|
+
this.details = extractTopoloServiceErrorDetails(
|
|
118
|
+
options.details === void 0 ? options.body : { details: options.details }
|
|
119
|
+
);
|
|
32
120
|
}
|
|
33
121
|
};
|
|
34
|
-
function
|
|
35
|
-
if (!body || typeof body !== "object" || Array.isArray(body)) return
|
|
122
|
+
function extractTopoloServiceErrorCode(body) {
|
|
123
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) return null;
|
|
36
124
|
const record = body;
|
|
37
|
-
|
|
125
|
+
const topLevel = canonicalTopoloErrorCode(record.code);
|
|
126
|
+
if (topLevel) return topLevel;
|
|
38
127
|
const nested = record.error;
|
|
128
|
+
const nestedString = canonicalTopoloErrorCode(nested);
|
|
129
|
+
if (nestedString) return nestedString;
|
|
39
130
|
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
40
131
|
const code = nested.code;
|
|
41
|
-
|
|
132
|
+
const nestedCode = canonicalTopoloErrorCode(code);
|
|
133
|
+
if (nestedCode) return nestedCode;
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
function serviceErrorCode(body, fallback) {
|
|
138
|
+
return extractTopoloServiceErrorCode(body) ?? fallback;
|
|
139
|
+
}
|
|
140
|
+
function extractTopoloServiceErrorDetails(body) {
|
|
141
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) return void 0;
|
|
142
|
+
const record = body;
|
|
143
|
+
let candidate = record.details;
|
|
144
|
+
const nested = record.error;
|
|
145
|
+
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
146
|
+
const nestedRecord = nested;
|
|
147
|
+
if (candidate === void 0) candidate = nestedRecord.details ?? nestedRecord;
|
|
148
|
+
}
|
|
149
|
+
if (candidate === void 0) candidate = record;
|
|
150
|
+
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) return void 0;
|
|
151
|
+
const source = candidate;
|
|
152
|
+
const safe = {};
|
|
153
|
+
for (const [key, value] of Object.entries(source)) {
|
|
154
|
+
if (/present$/i.test(key) && typeof value === "boolean") {
|
|
155
|
+
safe[key] = value;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (key === "retryable" && typeof value === "boolean") {
|
|
159
|
+
safe.retryable = value;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (key === "code") {
|
|
163
|
+
const sanitized = canonicalTopoloErrorCode(value);
|
|
164
|
+
if (sanitized) safe.code = sanitized;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (key === "source") {
|
|
168
|
+
const sanitized = typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
169
|
+
if (PUBLIC_DETAIL_SOURCES.has(sanitized)) safe.source = sanitized;
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (key === "dependency" || key === "platform") {
|
|
173
|
+
safe[`${key}Present`] = value !== null && value !== void 0;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (key === "error" && !safe.code) {
|
|
177
|
+
const sanitized = canonicalTopoloErrorCode(value);
|
|
178
|
+
if (sanitized) safe.code = sanitized;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (key === "required" && Array.isArray(value)) {
|
|
182
|
+
const required = canonicalTopoloRequired(value);
|
|
183
|
+
if (required.length) safe.required = required;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (["missingFields", "fields", "paths"].includes(key) && Array.isArray(value)) {
|
|
187
|
+
const paths = value.filter((item) => typeof item === "string" && /^[$.a-z0-9_[\]-]{1,160}$/i.test(item));
|
|
188
|
+
if (paths.length) safe[key] = paths;
|
|
189
|
+
}
|
|
42
190
|
}
|
|
43
|
-
return
|
|
191
|
+
return Object.keys(safe).length ? safe : void 0;
|
|
44
192
|
}
|
|
45
193
|
var TopoloHttpError = class extends TopoloSdkError {
|
|
46
194
|
status;
|
|
@@ -49,15 +197,19 @@ var TopoloHttpError = class extends TopoloSdkError {
|
|
|
49
197
|
path;
|
|
50
198
|
requestId;
|
|
51
199
|
retryAfter;
|
|
200
|
+
details;
|
|
52
201
|
constructor(service, path, status, body, message, options = {}) {
|
|
53
|
-
super(
|
|
202
|
+
super(serviceErrorCode(body, "http_error"), message ?? `HTTP ${status} from ${service}${path}`);
|
|
54
203
|
this.name = "TopoloHttpError";
|
|
55
204
|
this.status = status;
|
|
56
205
|
this.body = body;
|
|
57
206
|
this.service = service;
|
|
58
207
|
this.path = path;
|
|
59
|
-
this.requestId = options.requestId;
|
|
60
|
-
this.retryAfter = options.retryAfter;
|
|
208
|
+
this.requestId = canonicalTopoloRequestId(options.requestId);
|
|
209
|
+
this.retryAfter = canonicalTopoloRetryAfter(options.retryAfter);
|
|
210
|
+
this.details = extractTopoloServiceErrorDetails(
|
|
211
|
+
options.details === void 0 ? body : { details: options.details }
|
|
212
|
+
);
|
|
61
213
|
}
|
|
62
214
|
};
|
|
63
215
|
|
|
@@ -170,13 +322,11 @@ var TopoloOAuth = class {
|
|
|
170
322
|
}
|
|
171
323
|
};
|
|
172
324
|
|
|
173
|
-
// src/
|
|
174
|
-
var
|
|
175
|
-
|
|
176
|
-
return contextType === "organization" && organizationId ? `org:${organizationId}` : "personal";
|
|
177
|
-
}
|
|
178
|
-
var ENVIRONMENT_DEFAULT_SERVICE_URLS = {
|
|
325
|
+
// src/environment.ts
|
|
326
|
+
var TOPOLO_RUNTIME_ENVIRONMENTS = ["production", "staging", "development", "local"];
|
|
327
|
+
var TOPOLO_ENVIRONMENT_SERVICE_URLS = {
|
|
179
328
|
production: {
|
|
329
|
+
auth: "https://auth.topolo.app",
|
|
180
330
|
developers: "https://developers.topolo.app"
|
|
181
331
|
},
|
|
182
332
|
staging: {
|
|
@@ -190,6 +340,58 @@ var ENVIRONMENT_DEFAULT_SERVICE_URLS = {
|
|
|
190
340
|
},
|
|
191
341
|
local: {}
|
|
192
342
|
};
|
|
343
|
+
function hostnameHasSuffix(hostname, suffix) {
|
|
344
|
+
return hostname === suffix || hostname.endsWith(`.${suffix}`);
|
|
345
|
+
}
|
|
346
|
+
function workersDevAccountMatches(hostname, account) {
|
|
347
|
+
if (!hostname.endsWith(".workers.dev")) return false;
|
|
348
|
+
const labels = hostname.slice(0, -".workers.dev".length).split(".");
|
|
349
|
+
return labels.length >= 2 && labels.at(-1) === account;
|
|
350
|
+
}
|
|
351
|
+
function originMatchesEnvironment(url, environment) {
|
|
352
|
+
const hostname = url.hostname.toLowerCase();
|
|
353
|
+
if (environment === "local") {
|
|
354
|
+
return hostname === "localhost" || hostname.endsWith(".localhost") || hostname === "127.0.0.1" || hostname === "[::1]";
|
|
355
|
+
}
|
|
356
|
+
if (url.protocol !== "https:") return false;
|
|
357
|
+
if (environment === "production") {
|
|
358
|
+
return hostnameHasSuffix(hostname, "topolo.app") || hostnameHasSuffix(hostname, "topolo.io") || workersDevAccountMatches(hostname, "topolo");
|
|
359
|
+
}
|
|
360
|
+
if (environment === "staging") {
|
|
361
|
+
return hostnameHasSuffix(hostname, "stg.topolo.us") || workersDevAccountMatches(hostname, "topolo-staging");
|
|
362
|
+
}
|
|
363
|
+
return hostnameHasSuffix(hostname, "topolo.dev") || workersDevAccountMatches(hostname, "topolo-development");
|
|
364
|
+
}
|
|
365
|
+
function assertTopoloServiceUrlEnvironment(service, value, environment) {
|
|
366
|
+
let url;
|
|
367
|
+
try {
|
|
368
|
+
url = new URL(value);
|
|
369
|
+
} catch {
|
|
370
|
+
throw new TopoloSdkError("invalid_service_url", `Invalid URL configured for Topolo service "${service}".`);
|
|
371
|
+
}
|
|
372
|
+
if (url.protocol !== "https:" && url.protocol !== "http:" || url.username || url.password || !originMatchesEnvironment(url, environment)) {
|
|
373
|
+
throw new TopoloSdkError(
|
|
374
|
+
"environment_mismatch",
|
|
375
|
+
`Refusing Topolo service "${service}": ${url.origin} does not belong to ${environment}.`
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
return url.origin;
|
|
379
|
+
}
|
|
380
|
+
function topoloServiceOrigins(serviceUrls, environment) {
|
|
381
|
+
return Object.fromEntries(
|
|
382
|
+
Object.entries(serviceUrls ?? {}).sort(([left], [right]) => left.localeCompare(right)).map(([service, value]) => [
|
|
383
|
+
service,
|
|
384
|
+
assertTopoloServiceUrlEnvironment(service, value, environment)
|
|
385
|
+
])
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// src/node/credential-store.ts
|
|
390
|
+
var TOPOLO_ENVIRONMENTS = TOPOLO_RUNTIME_ENVIRONMENTS;
|
|
391
|
+
function contextKey(contextType, organizationId) {
|
|
392
|
+
return contextType === "organization" && organizationId ? `org:${organizationId}` : "personal";
|
|
393
|
+
}
|
|
394
|
+
var ENVIRONMENT_DEFAULT_SERVICE_URLS = TOPOLO_ENVIRONMENT_SERVICE_URLS;
|
|
193
395
|
function configPath() {
|
|
194
396
|
const override = process.env.TOPOLO_CONFIG_PATH;
|
|
195
397
|
if (override) return override;
|
|
@@ -307,15 +509,17 @@ function credentialSourceFromConfig(config, environment = selectedEnvironment())
|
|
|
307
509
|
const prefix = envVarPrefix(environment);
|
|
308
510
|
if (process.env[`${prefix}_API_KEY`]) return `env:${prefix}_API_KEY`;
|
|
309
511
|
if (process.env[`${prefix}_ACCESS_TOKEN`]) return `env:${prefix}_ACCESS_TOKEN`;
|
|
310
|
-
if (process.env.TOPOLO_API_KEY) return "env:TOPOLO_API_KEY";
|
|
311
|
-
if (process.env.TOPOLO_ACCESS_TOKEN)
|
|
512
|
+
if (environment === "production" && process.env.TOPOLO_API_KEY) return "env:TOPOLO_API_KEY";
|
|
513
|
+
if (environment === "production" && process.env.TOPOLO_ACCESS_TOKEN) {
|
|
514
|
+
return "env:TOPOLO_ACCESS_TOKEN";
|
|
515
|
+
}
|
|
312
516
|
return profileForEnvironment(config, environment).credential ? "config-file" : "none";
|
|
313
517
|
}
|
|
314
518
|
async function resolveCredential(environment = selectedEnvironment()) {
|
|
315
519
|
const prefix = envVarPrefix(environment);
|
|
316
|
-
const apiKey = process.env[`${prefix}_API_KEY`] ?? process.env.TOPOLO_API_KEY;
|
|
520
|
+
const apiKey = process.env[`${prefix}_API_KEY`] ?? (environment === "production" ? process.env.TOPOLO_API_KEY : void 0);
|
|
317
521
|
if (apiKey) return { kind: "api_key", apiKey };
|
|
318
|
-
const accessToken = process.env[`${prefix}_ACCESS_TOKEN`] ?? process.env.TOPOLO_ACCESS_TOKEN;
|
|
522
|
+
const accessToken = process.env[`${prefix}_ACCESS_TOKEN`] ?? (environment === "production" ? process.env.TOPOLO_ACCESS_TOKEN : void 0);
|
|
319
523
|
if (accessToken) return { kind: "access_token", accessToken };
|
|
320
524
|
const config = await readConfig();
|
|
321
525
|
return profileForEnvironment(config, environment).credential ?? null;
|
|
@@ -323,7 +527,7 @@ async function resolveCredential(environment = selectedEnvironment()) {
|
|
|
323
527
|
var REFRESH_SKEW_SECONDS = 60;
|
|
324
528
|
async function refreshCredentialIfNeeded(environment = selectedEnvironment(), options = {}) {
|
|
325
529
|
const prefix = envVarPrefix(environment);
|
|
326
|
-
if (process.env[`${prefix}_API_KEY`] || process.env[`${prefix}_ACCESS_TOKEN`] || process.env.TOPOLO_API_KEY || process.env.TOPOLO_ACCESS_TOKEN) {
|
|
530
|
+
if (process.env[`${prefix}_API_KEY`] || process.env[`${prefix}_ACCESS_TOKEN`] || environment === "production" && process.env.TOPOLO_API_KEY || environment === "production" && process.env.TOPOLO_ACCESS_TOKEN) {
|
|
327
531
|
return resolveCredential(environment);
|
|
328
532
|
}
|
|
329
533
|
const config = await readConfig();
|
|
@@ -333,9 +537,16 @@ async function refreshCredentialIfNeeded(environment = selectedEnvironment(), op
|
|
|
333
537
|
if (!cred.refreshToken || !profile.oauthClientId) return cred;
|
|
334
538
|
const now = Math.floor(Date.now() / 1e3);
|
|
335
539
|
if (!options.force && cred.expiresAt && cred.expiresAt - REFRESH_SKEW_SECONDS > now) return cred;
|
|
540
|
+
const serviceUrls = resolveServiceUrls(profile.serviceUrls, environment);
|
|
541
|
+
if (environment === "local" && !serviceUrls?.auth) {
|
|
542
|
+
throw new TopoloSdkError(
|
|
543
|
+
"environment_service_url_required",
|
|
544
|
+
"Local Topolo credential refresh requires an explicit local Auth service origin."
|
|
545
|
+
);
|
|
546
|
+
}
|
|
336
547
|
try {
|
|
337
548
|
const oauth = new TopoloOAuth({
|
|
338
|
-
serviceUrls
|
|
549
|
+
serviceUrls
|
|
339
550
|
});
|
|
340
551
|
const tokens = await oauth.refreshToken({
|
|
341
552
|
clientId: profile.oauthClientId,
|
|
@@ -376,9 +587,16 @@ async function refreshContextCredentialIfNeeded(environment, key, options = {})
|
|
|
376
587
|
if (!credential.refreshToken || !oauthClientId) return credential;
|
|
377
588
|
const now = Math.floor(Date.now() / 1e3);
|
|
378
589
|
if (!options.force && credential.expiresAt && credential.expiresAt - REFRESH_SKEW_SECONDS > now) return credential;
|
|
590
|
+
const serviceUrls = resolveServiceUrls(profile.serviceUrls, environment);
|
|
591
|
+
if (environment === "local" && !serviceUrls?.auth) {
|
|
592
|
+
throw new TopoloSdkError(
|
|
593
|
+
"environment_service_url_required",
|
|
594
|
+
"Local Topolo context refresh requires an explicit local Auth service origin."
|
|
595
|
+
);
|
|
596
|
+
}
|
|
379
597
|
try {
|
|
380
598
|
const oauth = new TopoloOAuth({
|
|
381
|
-
serviceUrls
|
|
599
|
+
serviceUrls
|
|
382
600
|
});
|
|
383
601
|
const tokens = await oauth.refreshToken({
|
|
384
602
|
clientId: oauthClientId,
|
|
@@ -425,7 +643,12 @@ function resolveServiceUrls(configUrls, environment = selectedEnvironment()) {
|
|
|
425
643
|
merged[k.slice("TOPOLO_SERVICE_URL_".length).toLowerCase()] = v;
|
|
426
644
|
}
|
|
427
645
|
}
|
|
428
|
-
|
|
646
|
+
const origins = topoloServiceOrigins(merged, environment);
|
|
647
|
+
return Object.keys(origins).length > 0 ? origins : void 0;
|
|
648
|
+
}
|
|
649
|
+
function assertServiceUrlForEnvironment(service, serviceUrl, environment = selectedEnvironment()) {
|
|
650
|
+
if (!serviceUrl) return;
|
|
651
|
+
assertTopoloServiceUrlEnvironment(service, serviceUrl, environment);
|
|
429
652
|
}
|
|
430
653
|
function resolvedProfileConfig(config, environment = selectedEnvironment()) {
|
|
431
654
|
const profile = profileForEnvironment(config, environment);
|
|
@@ -440,6 +663,8 @@ export {
|
|
|
440
663
|
ENVIRONMENT_DEFAULT_SERVICE_URLS,
|
|
441
664
|
TOPOLO_ENVIRONMENTS,
|
|
442
665
|
activateContext,
|
|
666
|
+
assertServiceUrlForEnvironment,
|
|
667
|
+
assertTopoloServiceUrlEnvironment,
|
|
443
668
|
clearProfileCredential,
|
|
444
669
|
configPath,
|
|
445
670
|
contextKey,
|
|
@@ -455,6 +680,7 @@ export {
|
|
|
455
680
|
resolveServiceUrls,
|
|
456
681
|
resolvedProfileConfig,
|
|
457
682
|
selectedEnvironment,
|
|
683
|
+
topoloServiceOrigins,
|
|
458
684
|
writeConfig,
|
|
459
685
|
writeContextCredential,
|
|
460
686
|
writeProfileConfig
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topolo/sdk",
|
|
3
|
-
"version": "0.10.
|
|
4
|
-
"topoloPublishedVersion": "0.10.
|
|
3
|
+
"version": "0.10.4",
|
|
4
|
+
"topoloPublishedVersion": "0.10.4",
|
|
5
5
|
"description": "Typed client SDK for the Topolo platform. Used by TopoloCli, TopoloMCP, and third-party agents.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|