@topolo/cli 0.1.27 → 0.1.29
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 +85 -31
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -89,7 +89,7 @@ var SERVICES = {
|
|
|
89
89
|
inventory: "https://inventory.topolo.app",
|
|
90
90
|
learn: "https://learn-api.topolo.app",
|
|
91
91
|
localize: "https://localize.topolo.app",
|
|
92
|
-
mail: "https://mail.topolo.app",
|
|
92
|
+
mail: "https://mail-api.topolo.app",
|
|
93
93
|
mdm: "https://mdm-api.topolo.app",
|
|
94
94
|
messages: "https://messages.topolo.app",
|
|
95
95
|
nexus: "https://nexus-api.topolo.app",
|
|
@@ -925,15 +925,17 @@ var APPLICATIONS = {
|
|
|
925
925
|
"mail.topolo.app"
|
|
926
926
|
],
|
|
927
927
|
"routes": [],
|
|
928
|
-
"serviceId":
|
|
928
|
+
"serviceId": null
|
|
929
929
|
},
|
|
930
930
|
{
|
|
931
931
|
"name": "topolo-mail-api",
|
|
932
932
|
"kind": "worker",
|
|
933
|
-
"apiUrl":
|
|
934
|
-
"domains": [
|
|
933
|
+
"apiUrl": "https://mail-api.topolo.app",
|
|
934
|
+
"domains": [
|
|
935
|
+
"mail-api.topolo.app"
|
|
936
|
+
],
|
|
935
937
|
"routes": [],
|
|
936
|
-
"serviceId":
|
|
938
|
+
"serviceId": "mail"
|
|
937
939
|
}
|
|
938
940
|
]
|
|
939
941
|
},
|
|
@@ -2046,15 +2048,63 @@ function statusRank(status) {
|
|
|
2046
2048
|
return 2;
|
|
2047
2049
|
}
|
|
2048
2050
|
var DEFAULT_SERVICE_URLS = SERVICES;
|
|
2051
|
+
function resolveCatalogServiceUrl(entry, options = {}) {
|
|
2052
|
+
const keys = catalogServiceKeyCandidates(entry, options.serviceKey);
|
|
2053
|
+
const override = resolveServiceUrlOverride(keys, options.overrides);
|
|
2054
|
+
if (override) return override;
|
|
2055
|
+
const apiBaseUrl = firstString(entry.apiBaseUrl, entry.api_base_url);
|
|
2056
|
+
if (apiBaseUrl) return apiBaseUrl;
|
|
2057
|
+
return null;
|
|
2058
|
+
}
|
|
2049
2059
|
function resolveServiceUrl(service, overrides) {
|
|
2050
|
-
const override =
|
|
2060
|
+
const override = resolveServiceUrlOverride([service], overrides);
|
|
2051
2061
|
if (override) return override;
|
|
2052
|
-
const envKey = `TOPOLO_SERVICE_URL_${service.replace(/\./g, "_").toUpperCase()}`;
|
|
2053
|
-
const envValue = typeof process !== "undefined" ? process.env?.[envKey] : void 0;
|
|
2054
|
-
if (envValue) return envValue;
|
|
2055
2062
|
return DEFAULT_SERVICE_URLS[service];
|
|
2056
2063
|
}
|
|
2064
|
+
function catalogServiceKeyCandidates(entry, preferred) {
|
|
2065
|
+
const values = [preferred, entry.slug, entry.name, entry.serviceId].filter(
|
|
2066
|
+
(value) => typeof value === "string" && value.trim().length > 0
|
|
2067
|
+
);
|
|
2068
|
+
const keys = /* @__PURE__ */ new Set();
|
|
2069
|
+
for (const value of values) {
|
|
2070
|
+
for (const candidate of serviceKeyCandidates(value)) keys.add(candidate);
|
|
2071
|
+
}
|
|
2072
|
+
return [...keys];
|
|
2073
|
+
}
|
|
2074
|
+
function serviceKeyCandidates(value) {
|
|
2075
|
+
const normalized = value.trim().toLowerCase().replace(/\s+/g, "-");
|
|
2076
|
+
const withoutTopolo = normalized.startsWith("topolo-") ? normalized.slice("topolo-".length) : normalized;
|
|
2077
|
+
return [.../* @__PURE__ */ new Set([
|
|
2078
|
+
normalized,
|
|
2079
|
+
normalized.replace(/-/g, "_"),
|
|
2080
|
+
withoutTopolo,
|
|
2081
|
+
withoutTopolo.replace(/-/g, "_")
|
|
2082
|
+
])].filter(Boolean);
|
|
2083
|
+
}
|
|
2084
|
+
function resolveServiceUrlOverride(keys, overrides) {
|
|
2085
|
+
for (const key of keys) {
|
|
2086
|
+
const direct = overrides?.[key];
|
|
2087
|
+
if (direct) return direct;
|
|
2088
|
+
const envStyleKey = key.replace(/\./g, "_");
|
|
2089
|
+
const envStyle = overrides?.[envStyleKey];
|
|
2090
|
+
if (envStyle) return envStyle;
|
|
2091
|
+
}
|
|
2092
|
+
for (const key of keys) {
|
|
2093
|
+
const envKey = `TOPOLO_SERVICE_URL_${key.replace(/\./g, "_").toUpperCase()}`;
|
|
2094
|
+
const envValue = typeof process !== "undefined" ? process.env?.[envKey] : void 0;
|
|
2095
|
+
if (envValue) return envValue;
|
|
2096
|
+
}
|
|
2097
|
+
return null;
|
|
2098
|
+
}
|
|
2099
|
+
function firstString(...values) {
|
|
2100
|
+
for (const value of values) {
|
|
2101
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
2102
|
+
}
|
|
2103
|
+
return null;
|
|
2104
|
+
}
|
|
2057
2105
|
var WRITE_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
2106
|
+
var TOPOLO_ACTION_ID_HEADER = "X-Topolo-Action-Id";
|
|
2107
|
+
var TOPOLO_ACTION_NAME_HEADER = "X-Topolo-Action-Name";
|
|
2058
2108
|
var POSITIVE_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
2059
2109
|
var NEGATIVE_CACHE_TTL_MS = 60 * 1e3;
|
|
2060
2110
|
var CATALOG_CACHE_TTL_MS = 60 * 1e3;
|
|
@@ -2222,8 +2272,12 @@ var TopoloClient = class _TopoloClient {
|
|
|
2222
2272
|
async resolveLiveCallableService(serviceKey) {
|
|
2223
2273
|
const catalog = await this.listServices();
|
|
2224
2274
|
const match = catalog.find((entry) => catalogEntryMatches(entry, serviceKey));
|
|
2225
|
-
if (!match
|
|
2226
|
-
|
|
2275
|
+
if (!match) return null;
|
|
2276
|
+
const baseUrl = resolveCatalogServiceUrl(match, {
|
|
2277
|
+
serviceKey,
|
|
2278
|
+
overrides: this.serviceUrls
|
|
2279
|
+
});
|
|
2280
|
+
return baseUrl ? { serviceKey, baseUrl } : null;
|
|
2227
2281
|
}
|
|
2228
2282
|
/**
|
|
2229
2283
|
* Resolve a service-slug → opaque service-id via caller config or TopoloAuth.
|
|
@@ -2316,7 +2370,8 @@ var TopoloClient = class _TopoloClient {
|
|
|
2316
2370
|
slug: typeof s.app_slug === "string" ? s.app_slug : null,
|
|
2317
2371
|
name: typeof s.name === "string" ? s.name : null,
|
|
2318
2372
|
description: typeof s.description === "string" ? s.description : null,
|
|
2319
|
-
|
|
2373
|
+
apiBaseUrl: typeof s.api_base_url === "string" ? s.api_base_url : typeof s.apiBaseUrl === "string" ? s.apiBaseUrl : null,
|
|
2374
|
+
launchUrl: typeof s.launch_url === "string" ? s.launch_url : typeof s.launchUrl === "string" ? s.launchUrl : null,
|
|
2320
2375
|
status: typeof s.status === "string" ? s.status : null,
|
|
2321
2376
|
surfaceKind: typeof s.surface_kind === "string" ? s.surface_kind : null,
|
|
2322
2377
|
launchable: s.launchable === true,
|
|
@@ -2383,6 +2438,10 @@ var TopoloClient = class _TopoloClient {
|
|
|
2383
2438
|
path: mapped.path,
|
|
2384
2439
|
...mapped.query ? { query: mapped.query } : {},
|
|
2385
2440
|
...mapped.body !== void 0 ? { body: mapped.body } : {},
|
|
2441
|
+
headers: {
|
|
2442
|
+
[TOPOLO_ACTION_ID_HEADER]: entry.actionId,
|
|
2443
|
+
[TOPOLO_ACTION_NAME_HEADER]: entry.name
|
|
2444
|
+
},
|
|
2386
2445
|
confirm: options.confirm === true
|
|
2387
2446
|
});
|
|
2388
2447
|
}
|
|
@@ -2397,7 +2456,8 @@ var TopoloClient = class _TopoloClient {
|
|
|
2397
2456
|
slug: app.id,
|
|
2398
2457
|
name: app.name ?? app.id,
|
|
2399
2458
|
description: null,
|
|
2400
|
-
|
|
2459
|
+
apiBaseUrl: null,
|
|
2460
|
+
launchUrl: app.productionUrl ?? null,
|
|
2401
2461
|
status: "bundled",
|
|
2402
2462
|
surfaceKind: "application",
|
|
2403
2463
|
launchable: Boolean(app.productionUrl),
|
|
@@ -2441,7 +2501,7 @@ var TopoloClient = class _TopoloClient {
|
|
|
2441
2501
|
}
|
|
2442
2502
|
};
|
|
2443
2503
|
function resolveConfiguredServiceId(slug, serviceIds) {
|
|
2444
|
-
for (const serviceKey of
|
|
2504
|
+
for (const serviceKey of serviceKeyCandidates2(slug)) {
|
|
2445
2505
|
const configured = serviceIds?.[serviceKey];
|
|
2446
2506
|
if (typeof configured === "string" && configured.trim()) return configured.trim();
|
|
2447
2507
|
const envKey = `TOPOLO_SERVICE_ID_${serviceKey.replace(/\./g, "_").toUpperCase()}`;
|
|
@@ -2451,7 +2511,7 @@ function resolveConfiguredServiceId(slug, serviceIds) {
|
|
|
2451
2511
|
return null;
|
|
2452
2512
|
}
|
|
2453
2513
|
function resolveConfiguredServiceUrl(slug, serviceUrls) {
|
|
2454
|
-
for (const serviceKey of
|
|
2514
|
+
for (const serviceKey of serviceKeyCandidates2(slug)) {
|
|
2455
2515
|
const configured = serviceUrls?.[serviceKey];
|
|
2456
2516
|
if (typeof configured === "string" && configured.trim()) return configured.trim();
|
|
2457
2517
|
const envKey = `TOPOLO_SERVICE_URL_${serviceKey.replace(/\./g, "_").toUpperCase()}`;
|
|
@@ -2460,7 +2520,7 @@ function resolveConfiguredServiceUrl(slug, serviceUrls) {
|
|
|
2460
2520
|
}
|
|
2461
2521
|
return null;
|
|
2462
2522
|
}
|
|
2463
|
-
function
|
|
2523
|
+
function serviceKeyCandidates2(slug) {
|
|
2464
2524
|
const normalized = normalizeLookupKey(slug);
|
|
2465
2525
|
const withoutTopolo = normalized.startsWith("topolo-") ? normalized.slice("topolo-".length) : normalized;
|
|
2466
2526
|
return [.../* @__PURE__ */ new Set([
|
|
@@ -2482,19 +2542,12 @@ function catalogEntryLookupKeys(entry) {
|
|
|
2482
2542
|
for (const value of values) {
|
|
2483
2543
|
const normalized = normalizeLookupKey(value);
|
|
2484
2544
|
if (!normalized) continue;
|
|
2485
|
-
for (const candidate of
|
|
2545
|
+
for (const candidate of serviceKeyCandidates2(normalized)) {
|
|
2486
2546
|
keys.add(candidate);
|
|
2487
2547
|
}
|
|
2488
2548
|
}
|
|
2489
2549
|
return [...keys];
|
|
2490
2550
|
}
|
|
2491
|
-
function isCallableCatalogEntry(entry) {
|
|
2492
|
-
const kind = normalizeLookupKey(entry.surfaceKind || "");
|
|
2493
|
-
if (kind === "api" || kind === "technical_service" || kind === "service") return true;
|
|
2494
|
-
return Boolean(
|
|
2495
|
-
entry.baseUrl && catalogEntryLookupKeys(entry).some((key) => Object.prototype.hasOwnProperty.call(DEFAULT_SERVICE_URLS, key))
|
|
2496
|
-
);
|
|
2497
|
-
}
|
|
2498
2551
|
function normalizeActionCatalogEntry(item) {
|
|
2499
2552
|
if (!item || typeof item !== "object" || Array.isArray(item)) return null;
|
|
2500
2553
|
const a = item;
|
|
@@ -8167,7 +8220,7 @@ function applicationRowsFromCatalog(catalog) {
|
|
|
8167
8220
|
name: entry.name ?? entry.slug ?? entry.serviceId,
|
|
8168
8221
|
appDir: "-",
|
|
8169
8222
|
packageName: null,
|
|
8170
|
-
productionUrl: entry.
|
|
8223
|
+
productionUrl: entry.launchUrl ?? null,
|
|
8171
8224
|
services: [displayCatalogId(entry)],
|
|
8172
8225
|
deployTargets: 0
|
|
8173
8226
|
})).sort((left, right) => left.id.localeCompare(right.id));
|
|
@@ -8754,7 +8807,7 @@ function buildRows(catalog, overrides, environment = selectedEnvironment()) {
|
|
|
8754
8807
|
const resolvedOverrides = resolveServiceUrls(overrides, environment);
|
|
8755
8808
|
return catalog.map((entry) => {
|
|
8756
8809
|
const id = displayServiceId(entry);
|
|
8757
|
-
const defaultUrl = defaultServiceUrl(id, entry
|
|
8810
|
+
const defaultUrl = defaultServiceUrl(id, entry);
|
|
8758
8811
|
const configuredUrl = configuredServiceUrl(id, resolvedOverrides);
|
|
8759
8812
|
const effectiveUrl = configuredUrl || defaultUrl;
|
|
8760
8813
|
return {
|
|
@@ -8764,22 +8817,23 @@ function buildRows(catalog, overrides, environment = selectedEnvironment()) {
|
|
|
8764
8817
|
defaultUrl,
|
|
8765
8818
|
effectiveUrl,
|
|
8766
8819
|
overridden: Boolean(configuredUrl && configuredUrl !== defaultUrl),
|
|
8767
|
-
environmentSafe: environment !== "staging" || isStagingUrl(effectiveUrl),
|
|
8820
|
+
environmentSafe: environment !== "staging" || !effectiveUrl || isStagingUrl(effectiveUrl),
|
|
8768
8821
|
permissions: [...entry.permissions]
|
|
8769
8822
|
};
|
|
8770
8823
|
}).sort((left, right) => left.id.localeCompare(right.id));
|
|
8771
8824
|
}
|
|
8772
8825
|
function formatRows2(rows, environment = selectedEnvironment()) {
|
|
8773
8826
|
const idWidth = Math.max(3, ...rows.map((r) => r.id.length));
|
|
8774
|
-
const urlWidth = Math.max(7, ...rows.map((r) => r.effectiveUrl.length));
|
|
8827
|
+
const urlWidth = Math.max(7, ...rows.map((r) => (r.effectiveUrl ?? "-").length));
|
|
8775
8828
|
const lines = [];
|
|
8776
8829
|
lines.push(`Environment: ${environment}`);
|
|
8777
8830
|
lines.push("");
|
|
8778
8831
|
lines.push(`${"ID".padEnd(idWidth)} ${"URL".padEnd(urlWidth)} OVERRIDE READY`);
|
|
8779
8832
|
lines.push(`${"-".repeat(idWidth)} ${"-".repeat(urlWidth)} -------- -----`);
|
|
8780
8833
|
for (const r of rows) {
|
|
8834
|
+
const effectiveUrl = r.effectiveUrl ?? "-";
|
|
8781
8835
|
lines.push(
|
|
8782
|
-
`${r.id.padEnd(idWidth)} ${
|
|
8836
|
+
`${r.id.padEnd(idWidth)} ${effectiveUrl.padEnd(urlWidth)} ${r.overridden ? "yes" : "".padEnd(8)} ${r.environmentSafe ? "yes" : "no"}`
|
|
8783
8837
|
);
|
|
8784
8838
|
}
|
|
8785
8839
|
return lines.join("\n");
|
|
@@ -8799,8 +8853,8 @@ function displayServiceId(entry) {
|
|
|
8799
8853
|
}
|
|
8800
8854
|
return serviceIdCandidates(entry.slug || entry.serviceId)[0] || entry.serviceId;
|
|
8801
8855
|
}
|
|
8802
|
-
function defaultServiceUrl(id,
|
|
8803
|
-
return
|
|
8856
|
+
function defaultServiceUrl(id, entry) {
|
|
8857
|
+
return resolveCatalogServiceUrl(entry, { serviceKey: id });
|
|
8804
8858
|
}
|
|
8805
8859
|
function configuredServiceUrl(id, overrides) {
|
|
8806
8860
|
if (!overrides) return null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topolo/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.29",
|
|
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": {
|