@topolo/cli 0.2.3 → 0.2.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.js +106 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -78,6 +78,7 @@ var APP_API_URLS = {
|
|
|
78
78
|
bugfix: "https://bugfix.topolo.app",
|
|
79
79
|
bytes: "https://bytes.topolo.app",
|
|
80
80
|
calendar: "https://calendar.topolo.app",
|
|
81
|
+
campaigns: "https://campaigns.topolo.app",
|
|
81
82
|
capacity: "https://capacity.topolo.app",
|
|
82
83
|
chat: "https://chat.topolo.app",
|
|
83
84
|
commerce: "https://commerce.topolo.app",
|
|
@@ -336,6 +337,38 @@ var APPLICATIONS = {
|
|
|
336
337
|
}
|
|
337
338
|
]
|
|
338
339
|
},
|
|
340
|
+
"campaigns": {
|
|
341
|
+
"id": "campaigns",
|
|
342
|
+
"appDir": "TopoloCampaigns",
|
|
343
|
+
"name": "topolo-campaigns",
|
|
344
|
+
"packageName": "topolo-campaigns",
|
|
345
|
+
"productionUrl": "https://campaigns.topolo.app",
|
|
346
|
+
"services": [
|
|
347
|
+
"campaigns"
|
|
348
|
+
],
|
|
349
|
+
"deployTargets": [
|
|
350
|
+
{
|
|
351
|
+
"name": "topolo-campaigns",
|
|
352
|
+
"kind": "worker",
|
|
353
|
+
"apiUrl": "https://campaigns.topolo.app",
|
|
354
|
+
"domains": [
|
|
355
|
+
"campaigns.topolo.app"
|
|
356
|
+
],
|
|
357
|
+
"routes": [
|
|
358
|
+
"campaigns.topolo.app"
|
|
359
|
+
],
|
|
360
|
+
"appId": "campaigns"
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
"name": "topolo-campaigns-api",
|
|
364
|
+
"kind": "worker",
|
|
365
|
+
"apiUrl": null,
|
|
366
|
+
"domains": [],
|
|
367
|
+
"routes": [],
|
|
368
|
+
"appId": null
|
|
369
|
+
}
|
|
370
|
+
]
|
|
371
|
+
},
|
|
339
372
|
"capacity": {
|
|
340
373
|
"id": "capacity",
|
|
341
374
|
"appDir": "TopoloCapacity",
|
|
@@ -2511,6 +2544,20 @@ var TopoloClient = class _TopoloClient {
|
|
|
2511
2544
|
}
|
|
2512
2545
|
async callAction(action, input2 = {}, options = {}) {
|
|
2513
2546
|
const entry = await this.getAction(action);
|
|
2547
|
+
return this.executeResolvedAction(entry, input2, options);
|
|
2548
|
+
}
|
|
2549
|
+
async readAction(action, input2 = {}, options = {}) {
|
|
2550
|
+
const entry = await this.getAction(action);
|
|
2551
|
+
const agentAccess = entry.agentAccess ?? (entry.destructive ? "off" : entry.readOnly && !entry.requiresConfirmation ? "auto" : "confirm");
|
|
2552
|
+
if (entry.method !== "GET" || !entry.readOnly || entry.destructive || entry.requiresConfirmation || agentAccess !== "auto") {
|
|
2553
|
+
throw new TopoloPermissionError(
|
|
2554
|
+
`Topolo action "${entry.actionId}" is not an automatic read-only action.`,
|
|
2555
|
+
entry.requiredPermission ? [entry.requiredPermission] : []
|
|
2556
|
+
);
|
|
2557
|
+
}
|
|
2558
|
+
return this.executeResolvedAction(entry, input2, options);
|
|
2559
|
+
}
|
|
2560
|
+
async executeResolvedAction(entry, input2, options) {
|
|
2514
2561
|
const agentAccess = entry.agentAccess ?? (entry.destructive ? "off" : entry.readOnly && !entry.requiresConfirmation ? "auto" : "confirm");
|
|
2515
2562
|
if (agentAccess === "off") {
|
|
2516
2563
|
throw new TopoloPermissionError(
|
|
@@ -3070,6 +3117,7 @@ var APP_API_URLS2 = {
|
|
|
3070
3117
|
bugfix: "https://bugfix.topolo.app",
|
|
3071
3118
|
bytes: "https://bytes.topolo.app",
|
|
3072
3119
|
calendar: "https://calendar.topolo.app",
|
|
3120
|
+
campaigns: "https://campaigns.topolo.app",
|
|
3073
3121
|
capacity: "https://capacity.topolo.app",
|
|
3074
3122
|
chat: "https://chat.topolo.app",
|
|
3075
3123
|
commerce: "https://commerce.topolo.app",
|
|
@@ -3394,6 +3442,46 @@ async function refreshCredentialIfNeeded(environment = selectedEnvironment(), op
|
|
|
3394
3442
|
return cred;
|
|
3395
3443
|
}
|
|
3396
3444
|
}
|
|
3445
|
+
async function refreshContextCredentialIfNeeded(environment, key, options = {}) {
|
|
3446
|
+
const config = await readConfig();
|
|
3447
|
+
const profile = profileForEnvironment(config, environment);
|
|
3448
|
+
const context = profile.contexts?.[key];
|
|
3449
|
+
const credential = context?.credential;
|
|
3450
|
+
if (!credential || credential.kind !== "access_token") return credential ?? null;
|
|
3451
|
+
const oauthClientId = context.oauthClientId ?? profile.oauthClientId;
|
|
3452
|
+
if (!credential.refreshToken || !credential.expiresAt || !oauthClientId) return credential;
|
|
3453
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
3454
|
+
if (!options.force && credential.expiresAt - REFRESH_SKEW_SECONDS > now) return credential;
|
|
3455
|
+
try {
|
|
3456
|
+
const oauth = new TopoloOAuth2({
|
|
3457
|
+
serviceUrls: resolveServiceUrls(profile.serviceUrls, environment)
|
|
3458
|
+
});
|
|
3459
|
+
const tokens = await oauth.refreshToken({
|
|
3460
|
+
clientId: oauthClientId,
|
|
3461
|
+
refreshToken: credential.refreshToken
|
|
3462
|
+
});
|
|
3463
|
+
const refreshed = {
|
|
3464
|
+
kind: "access_token",
|
|
3465
|
+
accessToken: tokens.access_token,
|
|
3466
|
+
...tokens.refresh_token ? { refreshToken: tokens.refresh_token } : { refreshToken: credential.refreshToken },
|
|
3467
|
+
expiresAt: Math.floor(Date.now() / 1e3) + tokens.expires_in
|
|
3468
|
+
};
|
|
3469
|
+
await writeConfig(writeProfileConfig(config, environment, {
|
|
3470
|
+
...profile.activeContext === key ? { credential: refreshed } : {},
|
|
3471
|
+
contexts: {
|
|
3472
|
+
...profile.contexts ?? {},
|
|
3473
|
+
[key]: {
|
|
3474
|
+
...context,
|
|
3475
|
+
credential: refreshed,
|
|
3476
|
+
oauthClientId
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
}));
|
|
3480
|
+
return refreshed;
|
|
3481
|
+
} catch {
|
|
3482
|
+
return credential;
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3397
3485
|
function resolveAgentName(configAgentName) {
|
|
3398
3486
|
return process.env.TOPOLO_AGENT_NAME ?? configAgentName;
|
|
3399
3487
|
}
|
|
@@ -10714,11 +10802,25 @@ function registerContextCommand(program2) {
|
|
|
10714
10802
|
}
|
|
10715
10803
|
const wantPersonal = /^(personal|me)$/i.test(target.trim());
|
|
10716
10804
|
let resolved;
|
|
10717
|
-
|
|
10805
|
+
let exchangeCredential = cred;
|
|
10806
|
+
const needle = target.trim().toLowerCase();
|
|
10807
|
+
const storedEntry = Object.entries(profile.contexts ?? {}).find(([, candidate]) => {
|
|
10808
|
+
if (wantPersonal) return candidate.contextType === "personal";
|
|
10809
|
+
return candidate.contextType === "organization" && (candidate.organizationId === target || candidate.organizationSlug?.toLowerCase() === needle || candidate.organizationName?.toLowerCase() === needle);
|
|
10810
|
+
});
|
|
10811
|
+
const storedContext = storedEntry?.[1];
|
|
10812
|
+
if (storedEntry && storedContext?.credential) {
|
|
10813
|
+
exchangeCredential = await refreshContextCredentialIfNeeded(environment, storedEntry[0]) ?? storedContext.credential;
|
|
10814
|
+
resolved = {
|
|
10815
|
+
contextType: storedContext.contextType,
|
|
10816
|
+
organizationId: storedContext.organizationId,
|
|
10817
|
+
organizationSlug: storedContext.organizationSlug,
|
|
10818
|
+
organizationName: storedContext.organizationName
|
|
10819
|
+
};
|
|
10820
|
+
} else if (wantPersonal) {
|
|
10718
10821
|
resolved = { contextType: "personal" };
|
|
10719
10822
|
} else {
|
|
10720
10823
|
const me = await fetchMe(cred, serviceUrls);
|
|
10721
|
-
const needle = target.trim().toLowerCase();
|
|
10722
10824
|
const match = me.memberships.find(
|
|
10723
10825
|
(m) => m.id === target || m.slug?.toLowerCase() === needle || m.name?.toLowerCase() === needle
|
|
10724
10826
|
);
|
|
@@ -10737,13 +10839,13 @@ function registerContextCommand(program2) {
|
|
|
10737
10839
|
}
|
|
10738
10840
|
const key = contextKey(resolved.contextType, resolved.organizationId);
|
|
10739
10841
|
const existing = profile.contexts?.[key];
|
|
10740
|
-
const newCredential = await exchangeForContext(
|
|
10842
|
+
const newCredential = await exchangeForContext(exchangeCredential, serviceUrls, {
|
|
10741
10843
|
type: resolved.contextType,
|
|
10742
10844
|
id: resolved.organizationId
|
|
10743
10845
|
});
|
|
10744
10846
|
resolved.credential = newCredential;
|
|
10745
10847
|
resolved.oauthClientId = existing?.oauthClientId ?? profile.oauthClientId;
|
|
10746
|
-
const updated = writeContextCredential(
|
|
10848
|
+
const updated = writeContextCredential(await readConfig(), environment, resolved, true);
|
|
10747
10849
|
await writeConfig(updated);
|
|
10748
10850
|
emit(
|
|
10749
10851
|
{ environment, active: key, context: { type: resolved.contextType, label: labelFor(resolved) } },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topolo/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Command-line interface for Topolo developers, operators, and agents, with internal first-party scaffolding available under the topolo platform namespace.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|