@topolo/sdk 0.8.2 → 0.8.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 +47 -0
- package/dist/index.d.cts +31 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +47 -0
- package/dist/node/credential-store.cjs +43 -0
- package/dist/node/credential-store.d.cts +5 -1
- package/dist/node/credential-store.d.ts +5 -1
- package/dist/node/credential-store.js +42 -0
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -129,6 +129,7 @@ var APP_API_URLS = {
|
|
|
129
129
|
bugfix: "https://bugfix.topolo.app",
|
|
130
130
|
bytes: "https://bytes.topolo.app",
|
|
131
131
|
calendar: "https://calendar.topolo.app",
|
|
132
|
+
campaigns: "https://campaigns.topolo.app",
|
|
132
133
|
capacity: "https://capacity.topolo.app",
|
|
133
134
|
chat: "https://chat.topolo.app",
|
|
134
135
|
commerce: "https://commerce.topolo.app",
|
|
@@ -389,6 +390,38 @@ var APPLICATIONS = {
|
|
|
389
390
|
}
|
|
390
391
|
]
|
|
391
392
|
},
|
|
393
|
+
"campaigns": {
|
|
394
|
+
"id": "campaigns",
|
|
395
|
+
"appDir": "TopoloCampaigns",
|
|
396
|
+
"name": "topolo-campaigns",
|
|
397
|
+
"packageName": "topolo-campaigns",
|
|
398
|
+
"productionUrl": "https://campaigns.topolo.app",
|
|
399
|
+
"services": [
|
|
400
|
+
"campaigns"
|
|
401
|
+
],
|
|
402
|
+
"deployTargets": [
|
|
403
|
+
{
|
|
404
|
+
"name": "topolo-campaigns",
|
|
405
|
+
"kind": "worker",
|
|
406
|
+
"apiUrl": "https://campaigns.topolo.app",
|
|
407
|
+
"domains": [
|
|
408
|
+
"campaigns.topolo.app"
|
|
409
|
+
],
|
|
410
|
+
"routes": [
|
|
411
|
+
"campaigns.topolo.app"
|
|
412
|
+
],
|
|
413
|
+
"appId": "campaigns"
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
"name": "topolo-campaigns-api",
|
|
417
|
+
"kind": "worker",
|
|
418
|
+
"apiUrl": null,
|
|
419
|
+
"domains": [],
|
|
420
|
+
"routes": [],
|
|
421
|
+
"appId": null
|
|
422
|
+
}
|
|
423
|
+
]
|
|
424
|
+
},
|
|
392
425
|
"capacity": {
|
|
393
426
|
"id": "capacity",
|
|
394
427
|
"appDir": "TopoloCapacity",
|
|
@@ -2570,6 +2603,20 @@ var TopoloClient = class _TopoloClient {
|
|
|
2570
2603
|
}
|
|
2571
2604
|
async callAction(action, input = {}, options = {}) {
|
|
2572
2605
|
const entry = await this.getAction(action);
|
|
2606
|
+
return this.executeResolvedAction(entry, input, options);
|
|
2607
|
+
}
|
|
2608
|
+
async readAction(action, input = {}, options = {}) {
|
|
2609
|
+
const entry = await this.getAction(action);
|
|
2610
|
+
const agentAccess = entry.agentAccess ?? (entry.destructive ? "off" : entry.readOnly && !entry.requiresConfirmation ? "auto" : "confirm");
|
|
2611
|
+
if (entry.method !== "GET" || !entry.readOnly || entry.destructive || entry.requiresConfirmation || agentAccess !== "auto") {
|
|
2612
|
+
throw new TopoloPermissionError(
|
|
2613
|
+
`Topolo action "${entry.actionId}" is not an automatic read-only action.`,
|
|
2614
|
+
entry.requiredPermission ? [entry.requiredPermission] : []
|
|
2615
|
+
);
|
|
2616
|
+
}
|
|
2617
|
+
return this.executeResolvedAction(entry, input, options);
|
|
2618
|
+
}
|
|
2619
|
+
async executeResolvedAction(entry, input, options) {
|
|
2573
2620
|
const agentAccess = entry.agentAccess ?? (entry.destructive ? "off" : entry.readOnly && !entry.requiresConfirmation ? "auto" : "confirm");
|
|
2574
2621
|
if (agentAccess === "off") {
|
|
2575
2622
|
throw new TopoloPermissionError(
|
package/dist/index.d.cts
CHANGED
|
@@ -267,6 +267,13 @@ declare class TopoloClient {
|
|
|
267
267
|
resourceId: string;
|
|
268
268
|
};
|
|
269
269
|
}): Promise<T>;
|
|
270
|
+
readAction<T = unknown>(action: string, input?: Record<string, unknown>, options?: {
|
|
271
|
+
resource?: {
|
|
272
|
+
resourceType: string;
|
|
273
|
+
resourceId: string;
|
|
274
|
+
};
|
|
275
|
+
}): Promise<T>;
|
|
276
|
+
private executeResolvedAction;
|
|
270
277
|
/**
|
|
271
278
|
* Bundled generated registry for tooling that audits platform packaging, not
|
|
272
279
|
* for deciding what the current credential may use.
|
|
@@ -326,6 +333,7 @@ declare const APP_API_URLS: {
|
|
|
326
333
|
readonly bugfix: "https://bugfix.topolo.app";
|
|
327
334
|
readonly bytes: "https://bytes.topolo.app";
|
|
328
335
|
readonly calendar: "https://calendar.topolo.app";
|
|
336
|
+
readonly campaigns: "https://campaigns.topolo.app";
|
|
329
337
|
readonly capacity: "https://capacity.topolo.app";
|
|
330
338
|
readonly chat: "https://chat.topolo.app";
|
|
331
339
|
readonly commerce: "https://commerce.topolo.app";
|
|
@@ -533,6 +541,29 @@ declare const APPLICATIONS: {
|
|
|
533
541
|
readonly appId: null;
|
|
534
542
|
}];
|
|
535
543
|
};
|
|
544
|
+
readonly campaigns: {
|
|
545
|
+
readonly id: "campaigns";
|
|
546
|
+
readonly appDir: "TopoloCampaigns";
|
|
547
|
+
readonly name: "topolo-campaigns";
|
|
548
|
+
readonly packageName: "topolo-campaigns";
|
|
549
|
+
readonly productionUrl: "https://campaigns.topolo.app";
|
|
550
|
+
readonly services: readonly ["campaigns"];
|
|
551
|
+
readonly deployTargets: readonly [{
|
|
552
|
+
readonly name: "topolo-campaigns";
|
|
553
|
+
readonly kind: "worker";
|
|
554
|
+
readonly apiUrl: "https://campaigns.topolo.app";
|
|
555
|
+
readonly domains: readonly ["campaigns.topolo.app"];
|
|
556
|
+
readonly routes: readonly ["campaigns.topolo.app"];
|
|
557
|
+
readonly appId: "campaigns";
|
|
558
|
+
}, {
|
|
559
|
+
readonly name: "topolo-campaigns-api";
|
|
560
|
+
readonly kind: "worker";
|
|
561
|
+
readonly apiUrl: null;
|
|
562
|
+
readonly domains: readonly [];
|
|
563
|
+
readonly routes: readonly [];
|
|
564
|
+
readonly appId: null;
|
|
565
|
+
}];
|
|
566
|
+
};
|
|
536
567
|
readonly capacity: {
|
|
537
568
|
readonly id: "capacity";
|
|
538
569
|
readonly appDir: "TopoloCapacity";
|
package/dist/index.d.ts
CHANGED
|
@@ -267,6 +267,13 @@ declare class TopoloClient {
|
|
|
267
267
|
resourceId: string;
|
|
268
268
|
};
|
|
269
269
|
}): Promise<T>;
|
|
270
|
+
readAction<T = unknown>(action: string, input?: Record<string, unknown>, options?: {
|
|
271
|
+
resource?: {
|
|
272
|
+
resourceType: string;
|
|
273
|
+
resourceId: string;
|
|
274
|
+
};
|
|
275
|
+
}): Promise<T>;
|
|
276
|
+
private executeResolvedAction;
|
|
270
277
|
/**
|
|
271
278
|
* Bundled generated registry for tooling that audits platform packaging, not
|
|
272
279
|
* for deciding what the current credential may use.
|
|
@@ -326,6 +333,7 @@ declare const APP_API_URLS: {
|
|
|
326
333
|
readonly bugfix: "https://bugfix.topolo.app";
|
|
327
334
|
readonly bytes: "https://bytes.topolo.app";
|
|
328
335
|
readonly calendar: "https://calendar.topolo.app";
|
|
336
|
+
readonly campaigns: "https://campaigns.topolo.app";
|
|
329
337
|
readonly capacity: "https://capacity.topolo.app";
|
|
330
338
|
readonly chat: "https://chat.topolo.app";
|
|
331
339
|
readonly commerce: "https://commerce.topolo.app";
|
|
@@ -533,6 +541,29 @@ declare const APPLICATIONS: {
|
|
|
533
541
|
readonly appId: null;
|
|
534
542
|
}];
|
|
535
543
|
};
|
|
544
|
+
readonly campaigns: {
|
|
545
|
+
readonly id: "campaigns";
|
|
546
|
+
readonly appDir: "TopoloCampaigns";
|
|
547
|
+
readonly name: "topolo-campaigns";
|
|
548
|
+
readonly packageName: "topolo-campaigns";
|
|
549
|
+
readonly productionUrl: "https://campaigns.topolo.app";
|
|
550
|
+
readonly services: readonly ["campaigns"];
|
|
551
|
+
readonly deployTargets: readonly [{
|
|
552
|
+
readonly name: "topolo-campaigns";
|
|
553
|
+
readonly kind: "worker";
|
|
554
|
+
readonly apiUrl: "https://campaigns.topolo.app";
|
|
555
|
+
readonly domains: readonly ["campaigns.topolo.app"];
|
|
556
|
+
readonly routes: readonly ["campaigns.topolo.app"];
|
|
557
|
+
readonly appId: "campaigns";
|
|
558
|
+
}, {
|
|
559
|
+
readonly name: "topolo-campaigns-api";
|
|
560
|
+
readonly kind: "worker";
|
|
561
|
+
readonly apiUrl: null;
|
|
562
|
+
readonly domains: readonly [];
|
|
563
|
+
readonly routes: readonly [];
|
|
564
|
+
readonly appId: null;
|
|
565
|
+
}];
|
|
566
|
+
};
|
|
536
567
|
readonly capacity: {
|
|
537
568
|
readonly id: "capacity";
|
|
538
569
|
readonly appDir: "TopoloCapacity";
|
package/dist/index.js
CHANGED
|
@@ -71,6 +71,7 @@ var APP_API_URLS = {
|
|
|
71
71
|
bugfix: "https://bugfix.topolo.app",
|
|
72
72
|
bytes: "https://bytes.topolo.app",
|
|
73
73
|
calendar: "https://calendar.topolo.app",
|
|
74
|
+
campaigns: "https://campaigns.topolo.app",
|
|
74
75
|
capacity: "https://capacity.topolo.app",
|
|
75
76
|
chat: "https://chat.topolo.app",
|
|
76
77
|
commerce: "https://commerce.topolo.app",
|
|
@@ -331,6 +332,38 @@ var APPLICATIONS = {
|
|
|
331
332
|
}
|
|
332
333
|
]
|
|
333
334
|
},
|
|
335
|
+
"campaigns": {
|
|
336
|
+
"id": "campaigns",
|
|
337
|
+
"appDir": "TopoloCampaigns",
|
|
338
|
+
"name": "topolo-campaigns",
|
|
339
|
+
"packageName": "topolo-campaigns",
|
|
340
|
+
"productionUrl": "https://campaigns.topolo.app",
|
|
341
|
+
"services": [
|
|
342
|
+
"campaigns"
|
|
343
|
+
],
|
|
344
|
+
"deployTargets": [
|
|
345
|
+
{
|
|
346
|
+
"name": "topolo-campaigns",
|
|
347
|
+
"kind": "worker",
|
|
348
|
+
"apiUrl": "https://campaigns.topolo.app",
|
|
349
|
+
"domains": [
|
|
350
|
+
"campaigns.topolo.app"
|
|
351
|
+
],
|
|
352
|
+
"routes": [
|
|
353
|
+
"campaigns.topolo.app"
|
|
354
|
+
],
|
|
355
|
+
"appId": "campaigns"
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
"name": "topolo-campaigns-api",
|
|
359
|
+
"kind": "worker",
|
|
360
|
+
"apiUrl": null,
|
|
361
|
+
"domains": [],
|
|
362
|
+
"routes": [],
|
|
363
|
+
"appId": null
|
|
364
|
+
}
|
|
365
|
+
]
|
|
366
|
+
},
|
|
334
367
|
"capacity": {
|
|
335
368
|
"id": "capacity",
|
|
336
369
|
"appDir": "TopoloCapacity",
|
|
@@ -2512,6 +2545,20 @@ var TopoloClient = class _TopoloClient {
|
|
|
2512
2545
|
}
|
|
2513
2546
|
async callAction(action, input = {}, options = {}) {
|
|
2514
2547
|
const entry = await this.getAction(action);
|
|
2548
|
+
return this.executeResolvedAction(entry, input, options);
|
|
2549
|
+
}
|
|
2550
|
+
async readAction(action, input = {}, options = {}) {
|
|
2551
|
+
const entry = await this.getAction(action);
|
|
2552
|
+
const agentAccess = entry.agentAccess ?? (entry.destructive ? "off" : entry.readOnly && !entry.requiresConfirmation ? "auto" : "confirm");
|
|
2553
|
+
if (entry.method !== "GET" || !entry.readOnly || entry.destructive || entry.requiresConfirmation || agentAccess !== "auto") {
|
|
2554
|
+
throw new TopoloPermissionError(
|
|
2555
|
+
`Topolo action "${entry.actionId}" is not an automatic read-only action.`,
|
|
2556
|
+
entry.requiredPermission ? [entry.requiredPermission] : []
|
|
2557
|
+
);
|
|
2558
|
+
}
|
|
2559
|
+
return this.executeResolvedAction(entry, input, options);
|
|
2560
|
+
}
|
|
2561
|
+
async executeResolvedAction(entry, input, options) {
|
|
2515
2562
|
const agentAccess = entry.agentAccess ?? (entry.destructive ? "off" : entry.readOnly && !entry.requiresConfirmation ? "auto" : "confirm");
|
|
2516
2563
|
if (agentAccess === "off") {
|
|
2517
2564
|
throw new TopoloPermissionError(
|
|
@@ -31,6 +31,7 @@ __export(credential_store_exports, {
|
|
|
31
31
|
normalizeEnvironment: () => normalizeEnvironment,
|
|
32
32
|
profileForEnvironment: () => profileForEnvironment,
|
|
33
33
|
readConfig: () => readConfig,
|
|
34
|
+
refreshContextCredentialIfNeeded: () => refreshContextCredentialIfNeeded,
|
|
34
35
|
refreshCredentialIfNeeded: () => refreshCredentialIfNeeded,
|
|
35
36
|
resolveAgentName: () => resolveAgentName,
|
|
36
37
|
resolveCredential: () => resolveCredential,
|
|
@@ -86,6 +87,7 @@ var APP_API_URLS = {
|
|
|
86
87
|
bugfix: "https://bugfix.topolo.app",
|
|
87
88
|
bytes: "https://bytes.topolo.app",
|
|
88
89
|
calendar: "https://calendar.topolo.app",
|
|
90
|
+
campaigns: "https://campaigns.topolo.app",
|
|
89
91
|
capacity: "https://capacity.topolo.app",
|
|
90
92
|
chat: "https://chat.topolo.app",
|
|
91
93
|
commerce: "https://commerce.topolo.app",
|
|
@@ -427,6 +429,46 @@ async function refreshCredentialIfNeeded(environment = selectedEnvironment(), op
|
|
|
427
429
|
return cred;
|
|
428
430
|
}
|
|
429
431
|
}
|
|
432
|
+
async function refreshContextCredentialIfNeeded(environment, key, options = {}) {
|
|
433
|
+
const config = await readConfig();
|
|
434
|
+
const profile = profileForEnvironment(config, environment);
|
|
435
|
+
const context = profile.contexts?.[key];
|
|
436
|
+
const credential = context?.credential;
|
|
437
|
+
if (!credential || credential.kind !== "access_token") return credential ?? null;
|
|
438
|
+
const oauthClientId = context.oauthClientId ?? profile.oauthClientId;
|
|
439
|
+
if (!credential.refreshToken || !credential.expiresAt || !oauthClientId) return credential;
|
|
440
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
441
|
+
if (!options.force && credential.expiresAt - REFRESH_SKEW_SECONDS > now) return credential;
|
|
442
|
+
try {
|
|
443
|
+
const oauth = new TopoloOAuth({
|
|
444
|
+
serviceUrls: resolveServiceUrls(profile.serviceUrls, environment)
|
|
445
|
+
});
|
|
446
|
+
const tokens = await oauth.refreshToken({
|
|
447
|
+
clientId: oauthClientId,
|
|
448
|
+
refreshToken: credential.refreshToken
|
|
449
|
+
});
|
|
450
|
+
const refreshed = {
|
|
451
|
+
kind: "access_token",
|
|
452
|
+
accessToken: tokens.access_token,
|
|
453
|
+
...tokens.refresh_token ? { refreshToken: tokens.refresh_token } : { refreshToken: credential.refreshToken },
|
|
454
|
+
expiresAt: Math.floor(Date.now() / 1e3) + tokens.expires_in
|
|
455
|
+
};
|
|
456
|
+
await writeConfig(writeProfileConfig(config, environment, {
|
|
457
|
+
...profile.activeContext === key ? { credential: refreshed } : {},
|
|
458
|
+
contexts: {
|
|
459
|
+
...profile.contexts ?? {},
|
|
460
|
+
[key]: {
|
|
461
|
+
...context,
|
|
462
|
+
credential: refreshed,
|
|
463
|
+
oauthClientId
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}));
|
|
467
|
+
return refreshed;
|
|
468
|
+
} catch {
|
|
469
|
+
return credential;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
430
472
|
function resolveAgentName(configAgentName) {
|
|
431
473
|
return process.env.TOPOLO_AGENT_NAME ?? configAgentName;
|
|
432
474
|
}
|
|
@@ -470,6 +512,7 @@ function resolvedProfileConfig(config, environment = selectedEnvironment()) {
|
|
|
470
512
|
normalizeEnvironment,
|
|
471
513
|
profileForEnvironment,
|
|
472
514
|
readConfig,
|
|
515
|
+
refreshContextCredentialIfNeeded,
|
|
473
516
|
refreshCredentialIfNeeded,
|
|
474
517
|
resolveAgentName,
|
|
475
518
|
resolveCredential,
|
|
@@ -103,8 +103,12 @@ declare function resolveCredential(environment?: TopoloEnvironment): Promise<Top
|
|
|
103
103
|
declare function refreshCredentialIfNeeded(environment?: TopoloEnvironment, options?: {
|
|
104
104
|
force?: boolean;
|
|
105
105
|
}): Promise<TopoloCredential | null>;
|
|
106
|
+
/** Refresh one stored context without changing which context is active. */
|
|
107
|
+
declare function refreshContextCredentialIfNeeded(environment: TopoloEnvironment, key: string, options?: {
|
|
108
|
+
force?: boolean;
|
|
109
|
+
}): Promise<TopoloCredential | null>;
|
|
106
110
|
declare function resolveAgentName(configAgentName?: string): string | undefined;
|
|
107
111
|
declare function resolveServiceUrls(configUrls?: Record<string, string>, environment?: TopoloEnvironment): Record<string, string> | undefined;
|
|
108
112
|
declare function resolvedProfileConfig(config: TopoloConfig, environment?: TopoloEnvironment): TopoloEnvironmentProfile;
|
|
109
113
|
|
|
110
|
-
export { ENVIRONMENT_DEFAULT_SERVICE_URLS, TOPOLO_ENVIRONMENTS, type TopoloConfig, type TopoloContextCredential, type TopoloEnvironment, type TopoloEnvironmentProfile, activateContext, clearProfileCredential, configPath, contextKey, credentialSourceFromConfig, envVarPrefix, normalizeEnvironment, profileForEnvironment, readConfig, refreshCredentialIfNeeded, resolveAgentName, resolveCredential, resolveServiceUrls, resolvedProfileConfig, selectedEnvironment, writeConfig, writeContextCredential, writeProfileConfig };
|
|
114
|
+
export { ENVIRONMENT_DEFAULT_SERVICE_URLS, TOPOLO_ENVIRONMENTS, type TopoloConfig, type TopoloContextCredential, type TopoloEnvironment, type TopoloEnvironmentProfile, activateContext, clearProfileCredential, configPath, contextKey, credentialSourceFromConfig, envVarPrefix, normalizeEnvironment, profileForEnvironment, readConfig, refreshContextCredentialIfNeeded, refreshCredentialIfNeeded, resolveAgentName, resolveCredential, resolveServiceUrls, resolvedProfileConfig, selectedEnvironment, writeConfig, writeContextCredential, writeProfileConfig };
|
|
@@ -103,8 +103,12 @@ declare function resolveCredential(environment?: TopoloEnvironment): Promise<Top
|
|
|
103
103
|
declare function refreshCredentialIfNeeded(environment?: TopoloEnvironment, options?: {
|
|
104
104
|
force?: boolean;
|
|
105
105
|
}): Promise<TopoloCredential | null>;
|
|
106
|
+
/** Refresh one stored context without changing which context is active. */
|
|
107
|
+
declare function refreshContextCredentialIfNeeded(environment: TopoloEnvironment, key: string, options?: {
|
|
108
|
+
force?: boolean;
|
|
109
|
+
}): Promise<TopoloCredential | null>;
|
|
106
110
|
declare function resolveAgentName(configAgentName?: string): string | undefined;
|
|
107
111
|
declare function resolveServiceUrls(configUrls?: Record<string, string>, environment?: TopoloEnvironment): Record<string, string> | undefined;
|
|
108
112
|
declare function resolvedProfileConfig(config: TopoloConfig, environment?: TopoloEnvironment): TopoloEnvironmentProfile;
|
|
109
113
|
|
|
110
|
-
export { ENVIRONMENT_DEFAULT_SERVICE_URLS, TOPOLO_ENVIRONMENTS, type TopoloConfig, type TopoloContextCredential, type TopoloEnvironment, type TopoloEnvironmentProfile, activateContext, clearProfileCredential, configPath, contextKey, credentialSourceFromConfig, envVarPrefix, normalizeEnvironment, profileForEnvironment, readConfig, refreshCredentialIfNeeded, resolveAgentName, resolveCredential, resolveServiceUrls, resolvedProfileConfig, selectedEnvironment, writeConfig, writeContextCredential, writeProfileConfig };
|
|
114
|
+
export { ENVIRONMENT_DEFAULT_SERVICE_URLS, TOPOLO_ENVIRONMENTS, type TopoloConfig, type TopoloContextCredential, type TopoloEnvironment, type TopoloEnvironmentProfile, activateContext, clearProfileCredential, configPath, contextKey, credentialSourceFromConfig, envVarPrefix, normalizeEnvironment, profileForEnvironment, readConfig, refreshContextCredentialIfNeeded, refreshCredentialIfNeeded, resolveAgentName, resolveCredential, resolveServiceUrls, resolvedProfileConfig, selectedEnvironment, writeConfig, writeContextCredential, writeProfileConfig };
|
|
@@ -43,6 +43,7 @@ var APP_API_URLS = {
|
|
|
43
43
|
bugfix: "https://bugfix.topolo.app",
|
|
44
44
|
bytes: "https://bytes.topolo.app",
|
|
45
45
|
calendar: "https://calendar.topolo.app",
|
|
46
|
+
campaigns: "https://campaigns.topolo.app",
|
|
46
47
|
capacity: "https://capacity.topolo.app",
|
|
47
48
|
chat: "https://chat.topolo.app",
|
|
48
49
|
commerce: "https://commerce.topolo.app",
|
|
@@ -384,6 +385,46 @@ async function refreshCredentialIfNeeded(environment = selectedEnvironment(), op
|
|
|
384
385
|
return cred;
|
|
385
386
|
}
|
|
386
387
|
}
|
|
388
|
+
async function refreshContextCredentialIfNeeded(environment, key, options = {}) {
|
|
389
|
+
const config = await readConfig();
|
|
390
|
+
const profile = profileForEnvironment(config, environment);
|
|
391
|
+
const context = profile.contexts?.[key];
|
|
392
|
+
const credential = context?.credential;
|
|
393
|
+
if (!credential || credential.kind !== "access_token") return credential ?? null;
|
|
394
|
+
const oauthClientId = context.oauthClientId ?? profile.oauthClientId;
|
|
395
|
+
if (!credential.refreshToken || !credential.expiresAt || !oauthClientId) return credential;
|
|
396
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
397
|
+
if (!options.force && credential.expiresAt - REFRESH_SKEW_SECONDS > now) return credential;
|
|
398
|
+
try {
|
|
399
|
+
const oauth = new TopoloOAuth({
|
|
400
|
+
serviceUrls: resolveServiceUrls(profile.serviceUrls, environment)
|
|
401
|
+
});
|
|
402
|
+
const tokens = await oauth.refreshToken({
|
|
403
|
+
clientId: oauthClientId,
|
|
404
|
+
refreshToken: credential.refreshToken
|
|
405
|
+
});
|
|
406
|
+
const refreshed = {
|
|
407
|
+
kind: "access_token",
|
|
408
|
+
accessToken: tokens.access_token,
|
|
409
|
+
...tokens.refresh_token ? { refreshToken: tokens.refresh_token } : { refreshToken: credential.refreshToken },
|
|
410
|
+
expiresAt: Math.floor(Date.now() / 1e3) + tokens.expires_in
|
|
411
|
+
};
|
|
412
|
+
await writeConfig(writeProfileConfig(config, environment, {
|
|
413
|
+
...profile.activeContext === key ? { credential: refreshed } : {},
|
|
414
|
+
contexts: {
|
|
415
|
+
...profile.contexts ?? {},
|
|
416
|
+
[key]: {
|
|
417
|
+
...context,
|
|
418
|
+
credential: refreshed,
|
|
419
|
+
oauthClientId
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}));
|
|
423
|
+
return refreshed;
|
|
424
|
+
} catch {
|
|
425
|
+
return credential;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
387
428
|
function resolveAgentName(configAgentName) {
|
|
388
429
|
return process.env.TOPOLO_AGENT_NAME ?? configAgentName;
|
|
389
430
|
}
|
|
@@ -426,6 +467,7 @@ export {
|
|
|
426
467
|
normalizeEnvironment,
|
|
427
468
|
profileForEnvironment,
|
|
428
469
|
readConfig,
|
|
470
|
+
refreshContextCredentialIfNeeded,
|
|
429
471
|
refreshCredentialIfNeeded,
|
|
430
472
|
resolveAgentName,
|
|
431
473
|
resolveCredential,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topolo/sdk",
|
|
3
|
-
"version": "0.8.
|
|
4
|
-
"topoloPublishedVersion": "0.8.
|
|
3
|
+
"version": "0.8.4",
|
|
4
|
+
"topoloPublishedVersion": "0.8.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",
|