@topolo/cli 0.6.5 → 0.6.6
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/generate-wrangler.mjs +9 -3
- package/dist/index.js +298 -168
- package/package.json +16 -16
|
@@ -483,7 +483,9 @@ function emitBindings(lines, bindings, env) {
|
|
|
483
483
|
lines.push(`binding = ${tomlString(d.binding)}`);
|
|
484
484
|
lines.push(`database_name = ${tomlString(cfg.databaseName)}`);
|
|
485
485
|
if (cfg.databaseId) lines.push(`database_id = ${tomlString(cfg.databaseId)}`);
|
|
486
|
-
if (d.
|
|
486
|
+
if (d.manageMigrations !== false && d.migrationsDir) {
|
|
487
|
+
lines.push(`migrations_dir = ${tomlString(d.migrationsDir)}`);
|
|
488
|
+
}
|
|
487
489
|
lines.push('');
|
|
488
490
|
}
|
|
489
491
|
for (const r of bindings.r2 || []) {
|
|
@@ -656,7 +658,11 @@ function emitCloudcontrol() {
|
|
|
656
658
|
const reportedHost = host || publicUrlHost(t, env);
|
|
657
659
|
const reportedRoutes = routes.length ? routes : (host ? [host] : []);
|
|
658
660
|
const d1Migrations = (t.bindings?.d1 || [])
|
|
659
|
-
.filter((binding) =>
|
|
661
|
+
.filter((binding) => (
|
|
662
|
+
bindingAppliesToEnv(binding, env)
|
|
663
|
+
&& binding[env]
|
|
664
|
+
&& binding.manageMigrations !== false
|
|
665
|
+
))
|
|
660
666
|
.map((binding) => ({
|
|
661
667
|
binding: binding.binding,
|
|
662
668
|
...(binding.migrationsDir || binding.migrations_dir
|
|
@@ -687,7 +693,7 @@ function emitCloudcontrol() {
|
|
|
687
693
|
...(Array.isArray(t.requiredSecrets) && t.requiredSecrets.length
|
|
688
694
|
? { required_secrets: t.requiredSecrets }
|
|
689
695
|
: {}),
|
|
690
|
-
...(
|
|
696
|
+
...(t.bindings?.d1?.length ? { migrations: { d1: d1Migrations } } : {}),
|
|
691
697
|
...preservedCloudControlFields,
|
|
692
698
|
});
|
|
693
699
|
}
|
package/dist/index.js
CHANGED
|
@@ -98,13 +98,13 @@ var TopoloHttpError = class extends TopoloSdkError {
|
|
|
98
98
|
path;
|
|
99
99
|
requestId;
|
|
100
100
|
retryAfter;
|
|
101
|
-
constructor(service,
|
|
102
|
-
super(extractHttpErrorCode(body), message ?? `HTTP ${status} from ${service}${
|
|
101
|
+
constructor(service, path9, status, body, message, options = {}) {
|
|
102
|
+
super(extractHttpErrorCode(body), message ?? `HTTP ${status} from ${service}${path9}`);
|
|
103
103
|
this.name = "TopoloHttpError";
|
|
104
104
|
this.status = status;
|
|
105
105
|
this.body = body;
|
|
106
106
|
this.service = service;
|
|
107
|
-
this.path =
|
|
107
|
+
this.path = path9;
|
|
108
108
|
this.requestId = options.requestId;
|
|
109
109
|
this.retryAfter = options.retryAfter;
|
|
110
110
|
}
|
|
@@ -113,6 +113,7 @@ var APP_API_URLS = {
|
|
|
113
113
|
agent: "https://agent.topolo.app",
|
|
114
114
|
auth: "https://auth.topolo.app",
|
|
115
115
|
backup: "https://backup.topolo.app",
|
|
116
|
+
blog: "https://blog.topolo.app",
|
|
116
117
|
books: "https://books.topolo.app",
|
|
117
118
|
brand: "https://brand.topolo.app",
|
|
118
119
|
bugfix: "https://bugfix.topolo.app",
|
|
@@ -125,6 +126,7 @@ var APP_API_URLS = {
|
|
|
125
126
|
compose: "https://compose.topolo.app",
|
|
126
127
|
consent: "https://consent.topolo.app",
|
|
127
128
|
crm: "https://crm.topolo.app",
|
|
129
|
+
design: "https://design.topolo.app",
|
|
128
130
|
developers: "https://developers.topolo.app",
|
|
129
131
|
director: "https://director.topolo.app",
|
|
130
132
|
feed: "https://feed.topolo.app",
|
|
@@ -208,7 +210,9 @@ var APPLICATIONS = {
|
|
|
208
210
|
"domains": [
|
|
209
211
|
"agent.topolo.app"
|
|
210
212
|
],
|
|
211
|
-
"routes": [
|
|
213
|
+
"routes": [
|
|
214
|
+
"agent.topolo.app"
|
|
215
|
+
],
|
|
212
216
|
"appId": "agent"
|
|
213
217
|
},
|
|
214
218
|
{
|
|
@@ -269,6 +273,38 @@ var APPLICATIONS = {
|
|
|
269
273
|
}
|
|
270
274
|
]
|
|
271
275
|
},
|
|
276
|
+
"blog": {
|
|
277
|
+
"id": "blog",
|
|
278
|
+
"appDir": "TopoloBlog",
|
|
279
|
+
"name": "topolo-blog",
|
|
280
|
+
"packageName": "topolo-blog",
|
|
281
|
+
"productionUrl": "https://blog.topolo.app",
|
|
282
|
+
"services": [
|
|
283
|
+
"blog"
|
|
284
|
+
],
|
|
285
|
+
"deployTargets": [
|
|
286
|
+
{
|
|
287
|
+
"name": "topolo-blog",
|
|
288
|
+
"kind": "worker",
|
|
289
|
+
"apiUrl": "https://blog.topolo.app",
|
|
290
|
+
"domains": [
|
|
291
|
+
"blog.topolo.app"
|
|
292
|
+
],
|
|
293
|
+
"routes": [
|
|
294
|
+
"blog.topolo.app"
|
|
295
|
+
],
|
|
296
|
+
"appId": "blog"
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
"name": "topolo-blog-api",
|
|
300
|
+
"kind": "worker",
|
|
301
|
+
"apiUrl": null,
|
|
302
|
+
"domains": [],
|
|
303
|
+
"routes": [],
|
|
304
|
+
"appId": null
|
|
305
|
+
}
|
|
306
|
+
]
|
|
307
|
+
},
|
|
272
308
|
"books": {
|
|
273
309
|
"id": "books",
|
|
274
310
|
"appDir": "TopoloBooks",
|
|
@@ -286,7 +322,9 @@ var APPLICATIONS = {
|
|
|
286
322
|
"domains": [
|
|
287
323
|
"books.topolo.app"
|
|
288
324
|
],
|
|
289
|
-
"routes": [
|
|
325
|
+
"routes": [
|
|
326
|
+
"books.topolo.app"
|
|
327
|
+
],
|
|
290
328
|
"appId": "books"
|
|
291
329
|
},
|
|
292
330
|
{
|
|
@@ -436,7 +474,9 @@ var APPLICATIONS = {
|
|
|
436
474
|
"domains": [
|
|
437
475
|
"campaigns.topolo.app"
|
|
438
476
|
],
|
|
439
|
-
"routes": [
|
|
477
|
+
"routes": [
|
|
478
|
+
"campaigns.topolo.app"
|
|
479
|
+
],
|
|
440
480
|
"appId": "campaigns"
|
|
441
481
|
},
|
|
442
482
|
{
|
|
@@ -646,11 +686,45 @@ var APPLICATIONS = {
|
|
|
646
686
|
"domains": [
|
|
647
687
|
"crm.topolo.app"
|
|
648
688
|
],
|
|
649
|
-
"routes": [
|
|
689
|
+
"routes": [
|
|
690
|
+
"crm.topolo.app"
|
|
691
|
+
],
|
|
650
692
|
"appId": "crm"
|
|
651
693
|
}
|
|
652
694
|
]
|
|
653
695
|
},
|
|
696
|
+
"design": {
|
|
697
|
+
"id": "design",
|
|
698
|
+
"appDir": "TopoloDesign",
|
|
699
|
+
"name": "topolo-design",
|
|
700
|
+
"packageName": "@topolo-io/design",
|
|
701
|
+
"productionUrl": "https://design.topolo.app",
|
|
702
|
+
"services": [
|
|
703
|
+
"design"
|
|
704
|
+
],
|
|
705
|
+
"deployTargets": [
|
|
706
|
+
{
|
|
707
|
+
"name": "topolo-design",
|
|
708
|
+
"kind": "worker",
|
|
709
|
+
"apiUrl": "https://design.topolo.app",
|
|
710
|
+
"domains": [
|
|
711
|
+
"design.topolo.app"
|
|
712
|
+
],
|
|
713
|
+
"routes": [
|
|
714
|
+
"design.topolo.app"
|
|
715
|
+
],
|
|
716
|
+
"appId": "design"
|
|
717
|
+
},
|
|
718
|
+
{
|
|
719
|
+
"name": "topolo-design-api",
|
|
720
|
+
"kind": "worker",
|
|
721
|
+
"apiUrl": null,
|
|
722
|
+
"domains": [],
|
|
723
|
+
"routes": [],
|
|
724
|
+
"appId": null
|
|
725
|
+
}
|
|
726
|
+
]
|
|
727
|
+
},
|
|
654
728
|
"developers": {
|
|
655
729
|
"id": "developers",
|
|
656
730
|
"appDir": "TopoloDevelopers",
|
|
@@ -938,7 +1012,9 @@ var APPLICATIONS = {
|
|
|
938
1012
|
"domains": [
|
|
939
1013
|
"insights.topolo.app"
|
|
940
1014
|
],
|
|
941
|
-
"routes": [
|
|
1015
|
+
"routes": [
|
|
1016
|
+
"insights.topolo.app"
|
|
1017
|
+
],
|
|
942
1018
|
"appId": "insights"
|
|
943
1019
|
},
|
|
944
1020
|
{
|
|
@@ -1322,7 +1398,9 @@ var APPLICATIONS = {
|
|
|
1322
1398
|
"domains": [
|
|
1323
1399
|
"pay.topolo.app"
|
|
1324
1400
|
],
|
|
1325
|
-
"routes": [
|
|
1401
|
+
"routes": [
|
|
1402
|
+
"pay.topolo.app"
|
|
1403
|
+
],
|
|
1326
1404
|
"appId": "pay"
|
|
1327
1405
|
},
|
|
1328
1406
|
{
|
|
@@ -2277,17 +2355,17 @@ function validateTopoloActionInput(schema, input3) {
|
|
|
2277
2355
|
validateNode(schema, input3, "$", schema, errors, 0);
|
|
2278
2356
|
return { valid: errors.length === 0, errors };
|
|
2279
2357
|
}
|
|
2280
|
-
function inspectSchema(schema,
|
|
2281
|
-
if (depth > 128) return { path:
|
|
2358
|
+
function inspectSchema(schema, path9, root, depth) {
|
|
2359
|
+
if (depth > 128) return { path: path9, code: "schema_depth", message: "Schema recursion exceeded 128 levels." };
|
|
2282
2360
|
const unsupportedKeyword = Object.keys(schema).find((keyword) => !SUPPORTED_SCHEMA_KEYWORDS.has(keyword));
|
|
2283
2361
|
if (unsupportedKeyword) {
|
|
2284
|
-
return { path:
|
|
2362
|
+
return { path: path9, code: "unsupported_schema_keyword", message: `Action schema uses unsupported keyword ${unsupportedKeyword}.` };
|
|
2285
2363
|
}
|
|
2286
2364
|
if (typeof schema.format === "string" && !["uri", "email", "date-time"].includes(schema.format)) {
|
|
2287
|
-
return { path:
|
|
2365
|
+
return { path: path9, code: "unsupported_schema_format", message: `Action schema uses unsupported format ${schema.format}.` };
|
|
2288
2366
|
}
|
|
2289
2367
|
if (typeof schema.$ref === "string" && !resolveLocalReference(root, schema.$ref)) {
|
|
2290
|
-
return { path:
|
|
2368
|
+
return { path: path9, code: "unsupported_schema_ref", message: `Cannot resolve schema reference ${schema.$ref}.` };
|
|
2291
2369
|
}
|
|
2292
2370
|
const children = [];
|
|
2293
2371
|
if (isRecord(schema.properties)) children.push(...Object.entries(schema.properties));
|
|
@@ -2303,7 +2381,7 @@ function inspectSchema(schema, path8, root, depth) {
|
|
|
2303
2381
|
);
|
|
2304
2382
|
for (const [key, child] of children) {
|
|
2305
2383
|
if (!isRecord(child)) continue;
|
|
2306
|
-
const issue = inspectSchema(child, `${
|
|
2384
|
+
const issue = inspectSchema(child, `${path9}.${key}`, root, depth + 1);
|
|
2307
2385
|
if (issue) return issue;
|
|
2308
2386
|
}
|
|
2309
2387
|
return null;
|
|
@@ -2311,129 +2389,129 @@ function inspectSchema(schema, path8, root, depth) {
|
|
|
2311
2389
|
function arraySchemaEntries(keyword, value) {
|
|
2312
2390
|
return Array.isArray(value) ? value.map((candidate, index) => [`${keyword}[${index}]`, candidate]) : [];
|
|
2313
2391
|
}
|
|
2314
|
-
function validateNode(schema, value,
|
|
2392
|
+
function validateNode(schema, value, path9, root, errors, depth) {
|
|
2315
2393
|
if (depth > 128) {
|
|
2316
|
-
errors.push({ path:
|
|
2394
|
+
errors.push({ path: path9, code: "schema_depth", message: "Schema recursion exceeded 128 levels." });
|
|
2317
2395
|
return;
|
|
2318
2396
|
}
|
|
2319
2397
|
if (typeof schema.$ref === "string") {
|
|
2320
2398
|
const resolved = resolveLocalReference(root, schema.$ref);
|
|
2321
2399
|
if (!resolved) {
|
|
2322
|
-
errors.push({ path:
|
|
2400
|
+
errors.push({ path: path9, code: "unsupported_schema_ref", message: `Cannot resolve schema reference ${schema.$ref}.` });
|
|
2323
2401
|
return;
|
|
2324
2402
|
}
|
|
2325
|
-
validateNode(resolved, value,
|
|
2403
|
+
validateNode(resolved, value, path9, root, errors, depth + 1);
|
|
2326
2404
|
}
|
|
2327
2405
|
if (Array.isArray(schema.allOf)) {
|
|
2328
2406
|
for (const candidate of schema.allOf) {
|
|
2329
|
-
if (isRecord(candidate)) validateNode(candidate, value,
|
|
2407
|
+
if (isRecord(candidate)) validateNode(candidate, value, path9, root, errors, depth + 1);
|
|
2330
2408
|
}
|
|
2331
2409
|
}
|
|
2332
2410
|
if (Array.isArray(schema.anyOf) && !schema.anyOf.some((candidate) => candidateMatches(candidate, value, root, depth))) {
|
|
2333
|
-
errors.push({ path:
|
|
2411
|
+
errors.push({ path: path9, code: "any_of", message: "Value does not match any allowed schema." });
|
|
2334
2412
|
return;
|
|
2335
2413
|
}
|
|
2336
2414
|
if (Array.isArray(schema.oneOf)) {
|
|
2337
2415
|
const matches = schema.oneOf.filter((candidate) => candidateMatches(candidate, value, root, depth)).length;
|
|
2338
2416
|
if (matches !== 1) {
|
|
2339
|
-
errors.push({ path:
|
|
2417
|
+
errors.push({ path: path9, code: "one_of", message: "Value must match exactly one allowed schema." });
|
|
2340
2418
|
return;
|
|
2341
2419
|
}
|
|
2342
2420
|
}
|
|
2343
2421
|
if (value === null && schema.nullable === true) return;
|
|
2344
2422
|
if (Object.prototype.hasOwnProperty.call(schema, "const") && !sameJsonValue(value, schema.const)) {
|
|
2345
|
-
errors.push({ path:
|
|
2423
|
+
errors.push({ path: path9, code: "const", message: `Value must equal ${JSON.stringify(schema.const)}.` });
|
|
2346
2424
|
return;
|
|
2347
2425
|
}
|
|
2348
2426
|
if (Array.isArray(schema.enum) && !schema.enum.some((candidate) => sameJsonValue(value, candidate))) {
|
|
2349
|
-
errors.push({ path:
|
|
2427
|
+
errors.push({ path: path9, code: "enum", message: `Value must be one of ${schema.enum.map((item) => JSON.stringify(item)).join(", ")}.` });
|
|
2350
2428
|
return;
|
|
2351
2429
|
}
|
|
2352
2430
|
if (!matchesType(schema.type, value)) {
|
|
2353
|
-
errors.push({ path:
|
|
2431
|
+
errors.push({ path: path9, code: "type", message: `Expected ${String(schema.type)}.` });
|
|
2354
2432
|
return;
|
|
2355
2433
|
}
|
|
2356
|
-
if (typeof value === "string") validateString(schema, value,
|
|
2357
|
-
if (typeof value === "number") validateNumber(schema, value,
|
|
2358
|
-
if (Array.isArray(value)) validateArray(schema, value,
|
|
2359
|
-
if (isRecord(value)) validateObject(schema, value,
|
|
2434
|
+
if (typeof value === "string") validateString(schema, value, path9, errors);
|
|
2435
|
+
if (typeof value === "number") validateNumber(schema, value, path9, errors);
|
|
2436
|
+
if (Array.isArray(value)) validateArray(schema, value, path9, root, errors, depth);
|
|
2437
|
+
if (isRecord(value)) validateObject(schema, value, path9, root, errors, depth);
|
|
2360
2438
|
}
|
|
2361
|
-
function validateObject(schema, value,
|
|
2439
|
+
function validateObject(schema, value, path9, root, errors, depth) {
|
|
2362
2440
|
if (typeof schema.minProperties === "number" && Object.keys(value).length < schema.minProperties) {
|
|
2363
|
-
errors.push({ path:
|
|
2441
|
+
errors.push({ path: path9, code: "min_properties", message: `Expected at least ${schema.minProperties} properties.` });
|
|
2364
2442
|
}
|
|
2365
2443
|
if (typeof schema.maxProperties === "number" && Object.keys(value).length > schema.maxProperties) {
|
|
2366
|
-
errors.push({ path:
|
|
2444
|
+
errors.push({ path: path9, code: "max_properties", message: `Expected at most ${schema.maxProperties} properties.` });
|
|
2367
2445
|
}
|
|
2368
2446
|
const properties = isRecord(schema.properties) ? schema.properties : {};
|
|
2369
2447
|
const required = Array.isArray(schema.required) ? schema.required.map(String) : [];
|
|
2370
2448
|
for (const key of required) {
|
|
2371
2449
|
if (!Object.prototype.hasOwnProperty.call(value, key)) {
|
|
2372
|
-
errors.push({ path: `${
|
|
2450
|
+
errors.push({ path: `${path9}.${key}`, code: "required", message: "Required property is missing." });
|
|
2373
2451
|
}
|
|
2374
2452
|
}
|
|
2375
2453
|
if (isRecord(schema.propertyNames)) {
|
|
2376
2454
|
for (const key of Object.keys(value)) {
|
|
2377
|
-
validateNode(schema.propertyNames, key, `${
|
|
2455
|
+
validateNode(schema.propertyNames, key, `${path9}.${key}`, root, errors, depth + 1);
|
|
2378
2456
|
}
|
|
2379
2457
|
}
|
|
2380
2458
|
for (const [key, child] of Object.entries(value)) {
|
|
2381
2459
|
const childSchema = properties[key];
|
|
2382
2460
|
if (isRecord(childSchema)) {
|
|
2383
|
-
validateNode(childSchema, child, `${
|
|
2461
|
+
validateNode(childSchema, child, `${path9}.${key}`, root, errors, depth + 1);
|
|
2384
2462
|
} else if (schema.additionalProperties === false) {
|
|
2385
|
-
errors.push({ path: `${
|
|
2463
|
+
errors.push({ path: `${path9}.${key}`, code: "additional_property", message: "Property is not declared by the action schema." });
|
|
2386
2464
|
} else if (isRecord(schema.additionalProperties)) {
|
|
2387
|
-
validateNode(schema.additionalProperties, child, `${
|
|
2465
|
+
validateNode(schema.additionalProperties, child, `${path9}.${key}`, root, errors, depth + 1);
|
|
2388
2466
|
}
|
|
2389
2467
|
}
|
|
2390
2468
|
}
|
|
2391
|
-
function validateArray(schema, value,
|
|
2469
|
+
function validateArray(schema, value, path9, root, errors, depth) {
|
|
2392
2470
|
if (typeof schema.minItems === "number" && value.length < schema.minItems) {
|
|
2393
|
-
errors.push({ path:
|
|
2471
|
+
errors.push({ path: path9, code: "min_items", message: `Expected at least ${schema.minItems} items.` });
|
|
2394
2472
|
}
|
|
2395
2473
|
if (typeof schema.maxItems === "number" && value.length > schema.maxItems) {
|
|
2396
|
-
errors.push({ path:
|
|
2474
|
+
errors.push({ path: path9, code: "max_items", message: `Expected at most ${schema.maxItems} items.` });
|
|
2397
2475
|
}
|
|
2398
2476
|
if (schema.uniqueItems === true) {
|
|
2399
2477
|
const unique4 = new Set(value.map((item) => JSON.stringify(item)));
|
|
2400
|
-
if (unique4.size !== value.length) errors.push({ path:
|
|
2478
|
+
if (unique4.size !== value.length) errors.push({ path: path9, code: "unique_items", message: "Expected every item to be unique." });
|
|
2401
2479
|
}
|
|
2402
2480
|
if (isRecord(schema.items)) {
|
|
2403
|
-
value.forEach((item, index) => validateNode(schema.items, item, `${
|
|
2481
|
+
value.forEach((item, index) => validateNode(schema.items, item, `${path9}[${index}]`, root, errors, depth + 1));
|
|
2404
2482
|
}
|
|
2405
2483
|
}
|
|
2406
|
-
function validateString(schema, value,
|
|
2484
|
+
function validateString(schema, value, path9, errors) {
|
|
2407
2485
|
if (typeof schema.minLength === "number" && value.length < schema.minLength) {
|
|
2408
|
-
errors.push({ path:
|
|
2486
|
+
errors.push({ path: path9, code: "min_length", message: `Expected at least ${schema.minLength} characters.` });
|
|
2409
2487
|
}
|
|
2410
2488
|
if (typeof schema.maxLength === "number" && value.length > schema.maxLength) {
|
|
2411
|
-
errors.push({ path:
|
|
2489
|
+
errors.push({ path: path9, code: "max_length", message: `Expected at most ${schema.maxLength} characters.` });
|
|
2412
2490
|
}
|
|
2413
2491
|
if (typeof schema.pattern === "string") {
|
|
2414
2492
|
try {
|
|
2415
|
-
if (!new RegExp(schema.pattern).test(value)) errors.push({ path:
|
|
2493
|
+
if (!new RegExp(schema.pattern).test(value)) errors.push({ path: path9, code: "pattern", message: "Value does not match the required pattern." });
|
|
2416
2494
|
} catch {
|
|
2417
|
-
errors.push({ path:
|
|
2495
|
+
errors.push({ path: path9, code: "invalid_schema_pattern", message: "Action schema contains an invalid pattern." });
|
|
2418
2496
|
}
|
|
2419
2497
|
}
|
|
2420
|
-
if (schema.format === "uri" && !isUrl(value)) errors.push({ path:
|
|
2421
|
-
if (schema.format === "email" && !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(value)) errors.push({ path:
|
|
2422
|
-
if (schema.format === "date-time" && !isDateTime(value)) errors.push({ path:
|
|
2498
|
+
if (schema.format === "uri" && !isUrl(value)) errors.push({ path: path9, code: "format_uri", message: "Expected an absolute URL." });
|
|
2499
|
+
if (schema.format === "email" && !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(value)) errors.push({ path: path9, code: "format_email", message: "Expected an email address." });
|
|
2500
|
+
if (schema.format === "date-time" && !isDateTime(value)) errors.push({ path: path9, code: "format_date_time", message: "Expected an ISO-8601 date-time." });
|
|
2423
2501
|
}
|
|
2424
|
-
function validateNumber(schema, value,
|
|
2425
|
-
if (typeof schema.minimum === "number" && value < schema.minimum) errors.push({ path:
|
|
2426
|
-
if (typeof schema.maximum === "number" && value > schema.maximum) errors.push({ path:
|
|
2502
|
+
function validateNumber(schema, value, path9, errors) {
|
|
2503
|
+
if (typeof schema.minimum === "number" && value < schema.minimum) errors.push({ path: path9, code: "minimum", message: `Expected a value of at least ${schema.minimum}.` });
|
|
2504
|
+
if (typeof schema.maximum === "number" && value > schema.maximum) errors.push({ path: path9, code: "maximum", message: `Expected a value of at most ${schema.maximum}.` });
|
|
2427
2505
|
const exclusiveMinimum = typeof schema.exclusiveMinimum === "number" ? schema.exclusiveMinimum : schema.exclusiveMinimum === true && typeof schema.minimum === "number" ? schema.minimum : null;
|
|
2428
2506
|
const exclusiveMaximum = typeof schema.exclusiveMaximum === "number" ? schema.exclusiveMaximum : schema.exclusiveMaximum === true && typeof schema.maximum === "number" ? schema.maximum : null;
|
|
2429
2507
|
if (exclusiveMinimum !== null && value <= exclusiveMinimum) {
|
|
2430
|
-
errors.push({ path:
|
|
2508
|
+
errors.push({ path: path9, code: "exclusive_minimum", message: `Expected a value greater than ${exclusiveMinimum}.` });
|
|
2431
2509
|
}
|
|
2432
2510
|
if (exclusiveMaximum !== null && value >= exclusiveMaximum) {
|
|
2433
|
-
errors.push({ path:
|
|
2511
|
+
errors.push({ path: path9, code: "exclusive_maximum", message: `Expected a value less than ${exclusiveMaximum}.` });
|
|
2434
2512
|
}
|
|
2435
2513
|
if (typeof schema.multipleOf === "number" && !isMultipleOf(value, schema.multipleOf)) {
|
|
2436
|
-
errors.push({ path:
|
|
2514
|
+
errors.push({ path: path9, code: "multiple_of", message: `Expected a multiple of ${schema.multipleOf}.` });
|
|
2437
2515
|
}
|
|
2438
2516
|
}
|
|
2439
2517
|
function candidateMatches(candidate, value, root, depth) {
|
|
@@ -2565,8 +2643,8 @@ function prepareTopoloUrlSessionUploadInput(contractValue, byteLength, input3, o
|
|
|
2565
2643
|
}
|
|
2566
2644
|
};
|
|
2567
2645
|
}
|
|
2568
|
-
function topoloUploadResponseValue(response,
|
|
2569
|
-
return
|
|
2646
|
+
function topoloUploadResponseValue(response, path9) {
|
|
2647
|
+
return path9.split(".").reduce((value, segment) => isRecord2(value) ? value[segment] : void 0, response);
|
|
2570
2648
|
}
|
|
2571
2649
|
function decodeTopoloActionBase64(contentBase64) {
|
|
2572
2650
|
if (!isCanonicalBase64(contentBase64)) {
|
|
@@ -2613,11 +2691,11 @@ function parseCompleteContract(value) {
|
|
|
2613
2691
|
};
|
|
2614
2692
|
}
|
|
2615
2693
|
function requiredPath(value, name) {
|
|
2616
|
-
const
|
|
2617
|
-
if (!/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(
|
|
2694
|
+
const path9 = typeof value === "string" ? value.trim() : "";
|
|
2695
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(path9)) {
|
|
2618
2696
|
throw new TopoloSdkError("invalid_upload_contract", `The action upload contract has an invalid ${name}.`);
|
|
2619
2697
|
}
|
|
2620
|
-
return
|
|
2698
|
+
return path9;
|
|
2621
2699
|
}
|
|
2622
2700
|
function unsupportedInlineProfile() {
|
|
2623
2701
|
return new TopoloSdkError("invalid_upload_contract", "This action does not publish an inline-base64 upload contract.");
|
|
@@ -3572,8 +3650,8 @@ function normalizeActionCatalogEntry(item) {
|
|
|
3572
3650
|
const name = pickActionString(a.name);
|
|
3573
3651
|
const appId = pickActionString(a.app_id) ?? pickActionString(a.appId);
|
|
3574
3652
|
const method = pickActionString(a.method)?.toUpperCase();
|
|
3575
|
-
const
|
|
3576
|
-
if (!actionId || !name || !appId || !method || !
|
|
3653
|
+
const path9 = pickActionString(a.path);
|
|
3654
|
+
if (!actionId || !name || !appId || !method || !path9 || !isHttpMethod(method)) {
|
|
3577
3655
|
return null;
|
|
3578
3656
|
}
|
|
3579
3657
|
return {
|
|
@@ -3588,7 +3666,7 @@ function normalizeActionCatalogEntry(item) {
|
|
|
3588
3666
|
appSlug: pickActionString(a.app_slug) ?? pickActionString(a.appSlug) ?? null,
|
|
3589
3667
|
appName: pickActionString(a.app_name) ?? pickActionString(a.appName) ?? null,
|
|
3590
3668
|
method,
|
|
3591
|
-
path:
|
|
3669
|
+
path: path9,
|
|
3592
3670
|
permissionName: pickActionString(a.permission_name) ?? pickActionString(a.permissionName) ?? "",
|
|
3593
3671
|
requiredPermission: pickActionString(a.required_permission) ?? pickActionString(a.requiredPermission) ?? "",
|
|
3594
3672
|
authorizationMode: pickAuthorizationMode(a.authorization_mode ?? a.authorizationMode),
|
|
@@ -3624,7 +3702,7 @@ function stringArray(value) {
|
|
|
3624
3702
|
}
|
|
3625
3703
|
function mapActionInput(action, input3) {
|
|
3626
3704
|
const remaining = { ...input3 || {} };
|
|
3627
|
-
const
|
|
3705
|
+
const path9 = action.path.replace(/\{([a-zA-Z0-9_]+)\}/g, (_match, key) => {
|
|
3628
3706
|
const value = remaining[key];
|
|
3629
3707
|
if (value === void 0 || value === null || value === "") {
|
|
3630
3708
|
throw new TopoloSdkError(
|
|
@@ -3641,14 +3719,14 @@ function mapActionInput(action, input3) {
|
|
|
3641
3719
|
delete remaining.body;
|
|
3642
3720
|
if (action.method === "GET") {
|
|
3643
3721
|
return {
|
|
3644
|
-
path:
|
|
3722
|
+
path: path9,
|
|
3645
3723
|
query: objectToQuery({ ...remaining, ...explicitQuery })
|
|
3646
3724
|
};
|
|
3647
3725
|
}
|
|
3648
3726
|
const query = objectToQuery(explicitQuery);
|
|
3649
3727
|
const body = explicitBody !== void 0 ? explicitBody : remaining;
|
|
3650
3728
|
return {
|
|
3651
|
-
path:
|
|
3729
|
+
path: path9,
|
|
3652
3730
|
...query ? { query } : {},
|
|
3653
3731
|
body
|
|
3654
3732
|
};
|
|
@@ -3818,8 +3896,8 @@ var TopoloOAuth = class {
|
|
|
3818
3896
|
if (params.clientSecret) body.set("client_secret", params.clientSecret);
|
|
3819
3897
|
return this.#postForm("/api/developer-oauth/token", body);
|
|
3820
3898
|
}
|
|
3821
|
-
async #postForm(
|
|
3822
|
-
const url = new URL(
|
|
3899
|
+
async #postForm(path9, body) {
|
|
3900
|
+
const url = new URL(path9, this.baseUrl.endsWith("/") ? this.baseUrl : `${this.baseUrl}/`);
|
|
3823
3901
|
const res = await this.fetchImpl(url.toString(), {
|
|
3824
3902
|
method: "POST",
|
|
3825
3903
|
headers: {
|
|
@@ -3835,7 +3913,7 @@ var TopoloOAuth = class {
|
|
|
3835
3913
|
const err = parsed;
|
|
3836
3914
|
throw new TopoloAuthError(err.error_description || err.error, err.error);
|
|
3837
3915
|
}
|
|
3838
|
-
throw new TopoloHttpError("auth",
|
|
3916
|
+
throw new TopoloHttpError("auth", path9, res.status, parsed);
|
|
3839
3917
|
}
|
|
3840
3918
|
return parsed;
|
|
3841
3919
|
}
|
|
@@ -3898,13 +3976,13 @@ var TopoloHttpError2 = class extends TopoloSdkError2 {
|
|
|
3898
3976
|
path;
|
|
3899
3977
|
requestId;
|
|
3900
3978
|
retryAfter;
|
|
3901
|
-
constructor(service,
|
|
3902
|
-
super(extractHttpErrorCode2(body), message ?? `HTTP ${status} from ${service}${
|
|
3979
|
+
constructor(service, path9, status, body, message, options = {}) {
|
|
3980
|
+
super(extractHttpErrorCode2(body), message ?? `HTTP ${status} from ${service}${path9}`);
|
|
3903
3981
|
this.name = "TopoloHttpError";
|
|
3904
3982
|
this.status = status;
|
|
3905
3983
|
this.body = body;
|
|
3906
3984
|
this.service = service;
|
|
3907
|
-
this.path =
|
|
3985
|
+
this.path = path9;
|
|
3908
3986
|
this.requestId = options.requestId;
|
|
3909
3987
|
this.retryAfter = options.retryAfter;
|
|
3910
3988
|
}
|
|
@@ -3913,6 +3991,7 @@ var APP_API_URLS2 = {
|
|
|
3913
3991
|
agent: "https://agent.topolo.app",
|
|
3914
3992
|
auth: "https://auth.topolo.app",
|
|
3915
3993
|
backup: "https://backup.topolo.app",
|
|
3994
|
+
blog: "https://blog.topolo.app",
|
|
3916
3995
|
books: "https://books.topolo.app",
|
|
3917
3996
|
brand: "https://brand.topolo.app",
|
|
3918
3997
|
bugfix: "https://bugfix.topolo.app",
|
|
@@ -3925,6 +4004,7 @@ var APP_API_URLS2 = {
|
|
|
3925
4004
|
compose: "https://compose.topolo.app",
|
|
3926
4005
|
consent: "https://consent.topolo.app",
|
|
3927
4006
|
crm: "https://crm.topolo.app",
|
|
4007
|
+
design: "https://design.topolo.app",
|
|
3928
4008
|
developers: "https://developers.topolo.app",
|
|
3929
4009
|
director: "https://director.topolo.app",
|
|
3930
4010
|
feed: "https://feed.topolo.app",
|
|
@@ -4037,8 +4117,8 @@ var TopoloOAuth2 = class {
|
|
|
4037
4117
|
if (params.clientSecret) body.set("client_secret", params.clientSecret);
|
|
4038
4118
|
return this.#postForm("/api/developer-oauth/token", body);
|
|
4039
4119
|
}
|
|
4040
|
-
async #postForm(
|
|
4041
|
-
const url = new URL(
|
|
4120
|
+
async #postForm(path9, body) {
|
|
4121
|
+
const url = new URL(path9, this.baseUrl.endsWith("/") ? this.baseUrl : `${this.baseUrl}/`);
|
|
4042
4122
|
const res = await this.fetchImpl(url.toString(), {
|
|
4043
4123
|
method: "POST",
|
|
4044
4124
|
headers: {
|
|
@@ -4054,7 +4134,7 @@ var TopoloOAuth2 = class {
|
|
|
4054
4134
|
const err = parsed;
|
|
4055
4135
|
throw new TopoloAuthError2(err.error_description || err.error, err.error);
|
|
4056
4136
|
}
|
|
4057
|
-
throw new TopoloHttpError2("auth",
|
|
4137
|
+
throw new TopoloHttpError2("auth", path9, res.status, parsed);
|
|
4058
4138
|
}
|
|
4059
4139
|
return parsed;
|
|
4060
4140
|
}
|
|
@@ -4084,22 +4164,22 @@ function configPath() {
|
|
|
4084
4164
|
return join(base, "topolo", "config.json");
|
|
4085
4165
|
}
|
|
4086
4166
|
async function readConfig() {
|
|
4087
|
-
const
|
|
4088
|
-
if (!existsSync(
|
|
4167
|
+
const path9 = configPath();
|
|
4168
|
+
if (!existsSync(path9)) return {};
|
|
4089
4169
|
try {
|
|
4090
|
-
const raw = await readFile(
|
|
4170
|
+
const raw = await readFile(path9, "utf8");
|
|
4091
4171
|
return JSON.parse(raw);
|
|
4092
4172
|
} catch {
|
|
4093
4173
|
return {};
|
|
4094
4174
|
}
|
|
4095
4175
|
}
|
|
4096
4176
|
async function writeConfig(config) {
|
|
4097
|
-
const
|
|
4098
|
-
await mkdir(dirname(
|
|
4099
|
-
await writeFile(
|
|
4177
|
+
const path9 = configPath();
|
|
4178
|
+
await mkdir(dirname(path9), { recursive: true });
|
|
4179
|
+
await writeFile(path9, JSON.stringify(config, null, 2) + "\n", "utf8");
|
|
4100
4180
|
if (platform() !== "win32") {
|
|
4101
4181
|
try {
|
|
4102
|
-
await chmod(
|
|
4182
|
+
await chmod(path9, 384);
|
|
4103
4183
|
} catch {
|
|
4104
4184
|
}
|
|
4105
4185
|
}
|
|
@@ -4429,9 +4509,9 @@ function readCliVersion() {
|
|
|
4429
4509
|
join2(here, "package.json"),
|
|
4430
4510
|
join2(here, "..", "package.json")
|
|
4431
4511
|
];
|
|
4432
|
-
for (const
|
|
4512
|
+
for (const path9 of candidates) {
|
|
4433
4513
|
try {
|
|
4434
|
-
const pkg = JSON.parse(readFileSync(
|
|
4514
|
+
const pkg = JSON.parse(readFileSync(path9, "utf8"));
|
|
4435
4515
|
if (typeof pkg.version === "string" && pkg.version) return pkg.version;
|
|
4436
4516
|
} catch {
|
|
4437
4517
|
}
|
|
@@ -4791,7 +4871,7 @@ function registerApiCommand(program2) {
|
|
|
4791
4871
|
"-q, --query <kv...>",
|
|
4792
4872
|
"Query params as key=value (repeatable), e.g. --query source=cli page=2"
|
|
4793
4873
|
).option("--resource-type <type>", "Cataloged app-local workspace resource alias for resource-scoped API keys").option("--resource-id <id>", "Workspace resource id for resource-scoped API keys").option("--confirm", "Acknowledge a mutating request").option("--json", "Output JSON", true).option("--no-json", "Output human-readable text").action(
|
|
4794
|
-
async (service, method,
|
|
4874
|
+
async (service, method, path9, opts) => {
|
|
4795
4875
|
const mode = resolveOutputMode(opts.json);
|
|
4796
4876
|
try {
|
|
4797
4877
|
const upperMethod = method.toUpperCase();
|
|
@@ -4830,7 +4910,7 @@ function registerApiCommand(program2) {
|
|
|
4830
4910
|
const result = await topolo.client.request({
|
|
4831
4911
|
service,
|
|
4832
4912
|
method: httpMethod,
|
|
4833
|
-
path:
|
|
4913
|
+
path: path9,
|
|
4834
4914
|
body,
|
|
4835
4915
|
...query ? { query } : {},
|
|
4836
4916
|
...resource ? { resource } : {},
|
|
@@ -5018,13 +5098,13 @@ async function requiredClient() {
|
|
|
5018
5098
|
function parseJsonObject(value) {
|
|
5019
5099
|
let source = value;
|
|
5020
5100
|
if (value.startsWith("@")) {
|
|
5021
|
-
const
|
|
5022
|
-
if (!
|
|
5101
|
+
const path9 = value.slice(1);
|
|
5102
|
+
if (!path9) throw new Error("--data @file path must not be empty");
|
|
5023
5103
|
try {
|
|
5024
|
-
source = readFileSync2(
|
|
5104
|
+
source = readFileSync2(path9, "utf8");
|
|
5025
5105
|
} catch (err) {
|
|
5026
5106
|
const detail = err instanceof Error ? err.message : String(err);
|
|
5027
|
-
throw new Error(`Could not read --data file ${
|
|
5107
|
+
throw new Error(`Could not read --data file ${path9}: ${detail}`);
|
|
5028
5108
|
}
|
|
5029
5109
|
}
|
|
5030
5110
|
let parsed;
|
|
@@ -5038,7 +5118,7 @@ function parseJsonObject(value) {
|
|
|
5038
5118
|
}
|
|
5039
5119
|
return parsed;
|
|
5040
5120
|
}
|
|
5041
|
-
function inferContentType(
|
|
5121
|
+
function inferContentType(path9) {
|
|
5042
5122
|
return {
|
|
5043
5123
|
".avif": "image/avif",
|
|
5044
5124
|
".gif": "image/gif",
|
|
@@ -5051,7 +5131,7 @@ function inferContentType(path8) {
|
|
|
5051
5131
|
".png": "image/png",
|
|
5052
5132
|
".svg": "image/svg+xml",
|
|
5053
5133
|
".webp": "image/webp"
|
|
5054
|
-
}[extname(
|
|
5134
|
+
}[extname(path9).toLowerCase()] ?? null;
|
|
5055
5135
|
}
|
|
5056
5136
|
function formatActionRows(rows, nextCursor = null) {
|
|
5057
5137
|
if (rows.length === 0) return "No actions available for this credential.";
|
|
@@ -5113,8 +5193,8 @@ function formatActionPlan(plan) {
|
|
|
5113
5193
|
|
|
5114
5194
|
// src/commands/apps.ts
|
|
5115
5195
|
import { execSync } from "child_process";
|
|
5116
|
-
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as
|
|
5117
|
-
import
|
|
5196
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync as writeFileSync2 } from "fs";
|
|
5197
|
+
import path6 from "path";
|
|
5118
5198
|
|
|
5119
5199
|
// src/commands/app-audit-local.ts
|
|
5120
5200
|
import {
|
|
@@ -6251,14 +6331,14 @@ import { constants } from "fs";
|
|
|
6251
6331
|
import { access } from "fs/promises";
|
|
6252
6332
|
import { relative, resolve } from "path";
|
|
6253
6333
|
function normalizeHomePath(value) {
|
|
6254
|
-
const
|
|
6255
|
-
if (!
|
|
6334
|
+
const path9 = String(value || "/dashboard").trim();
|
|
6335
|
+
if (!path9.startsWith("/") || path9.startsWith("//") || /[?#]/.test(path9)) {
|
|
6256
6336
|
throw new Error("Invalid home path. Use an absolute application path such as /dashboard.");
|
|
6257
6337
|
}
|
|
6258
|
-
if (["/", "/login", "/auth/callback", "/getting-started"].includes(
|
|
6338
|
+
if (["/", "/login", "/auth/callback", "/getting-started"].includes(path9)) {
|
|
6259
6339
|
throw new Error("Home path must be a protected product route, not a reserved entry route.");
|
|
6260
6340
|
}
|
|
6261
|
-
return
|
|
6341
|
+
return path9.replace(/\/$/, "") || "/dashboard";
|
|
6262
6342
|
}
|
|
6263
6343
|
function normalizeHomeLabel(value) {
|
|
6264
6344
|
const label = String(value || "Dashboard").trim();
|
|
@@ -6389,9 +6469,9 @@ function toTitle(value) {
|
|
|
6389
6469
|
function json(value) {
|
|
6390
6470
|
return JSON.stringify(value, null, 2);
|
|
6391
6471
|
}
|
|
6392
|
-
async function pathExists(
|
|
6472
|
+
async function pathExists(path9) {
|
|
6393
6473
|
try {
|
|
6394
|
-
await access(
|
|
6474
|
+
await access(path9, constants.F_OK);
|
|
6395
6475
|
return true;
|
|
6396
6476
|
} catch {
|
|
6397
6477
|
return false;
|
|
@@ -6421,6 +6501,54 @@ function firstPartyAppPath(appDir, _audience) {
|
|
|
6421
6501
|
return `apps/${appDir}`;
|
|
6422
6502
|
}
|
|
6423
6503
|
|
|
6504
|
+
// src/commands/app-scaffold-platform-versions.ts
|
|
6505
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync4 } from "fs";
|
|
6506
|
+
import path2 from "path";
|
|
6507
|
+
var versionCache = /* @__PURE__ */ new Map();
|
|
6508
|
+
function platformPackagePin(packageName, options = {}) {
|
|
6509
|
+
const workspaceRoot = resolveTopoloRepoRoot(
|
|
6510
|
+
options.repoRoot ?? process.env.TOPOLO_WORKSPACE_ROOT ?? void 0,
|
|
6511
|
+
options.cwd ?? process.cwd()
|
|
6512
|
+
);
|
|
6513
|
+
if (!workspaceRoot) {
|
|
6514
|
+
throw new Error(
|
|
6515
|
+
`Cannot resolve a concrete version for ${packageName}: platform-target scaffolds must run inside the Topolo workspace checkout (a directory containing apps/ and system-apps/), or receive --repo-root. The fleet pinning policy requires exact ^<latest> pins, never "latest".`
|
|
6516
|
+
);
|
|
6517
|
+
}
|
|
6518
|
+
const version = platformPackageVersions(workspaceRoot).get(packageName);
|
|
6519
|
+
if (!version) {
|
|
6520
|
+
throw new Error(
|
|
6521
|
+
`Unknown Topolo platform package: ${packageName} \u2014 no published package with that name under ${path2.join(workspaceRoot, "topolo-platform", "packages")}.`
|
|
6522
|
+
);
|
|
6523
|
+
}
|
|
6524
|
+
return `^${version}`;
|
|
6525
|
+
}
|
|
6526
|
+
function platformPackageVersions(workspaceRoot) {
|
|
6527
|
+
const packagesRoot = path2.join(workspaceRoot, "topolo-platform", "packages");
|
|
6528
|
+
const cached = versionCache.get(packagesRoot);
|
|
6529
|
+
if (cached) return cached;
|
|
6530
|
+
const versions = /* @__PURE__ */ new Map();
|
|
6531
|
+
let entries = [];
|
|
6532
|
+
try {
|
|
6533
|
+
entries = readdirSync2(packagesRoot);
|
|
6534
|
+
} catch {
|
|
6535
|
+
}
|
|
6536
|
+
for (const entry of entries) {
|
|
6537
|
+
let packageJson2;
|
|
6538
|
+
try {
|
|
6539
|
+
packageJson2 = JSON.parse(readFileSync4(path2.join(packagesRoot, entry, "package.json"), "utf8"));
|
|
6540
|
+
} catch {
|
|
6541
|
+
continue;
|
|
6542
|
+
}
|
|
6543
|
+
const version = packageJson2.topoloPublishedVersion || packageJson2.version;
|
|
6544
|
+
if (packageJson2.name && /^@topolo(-io)?\//.test(packageJson2.name) && !packageJson2.private && version) {
|
|
6545
|
+
versions.set(packageJson2.name, version);
|
|
6546
|
+
}
|
|
6547
|
+
}
|
|
6548
|
+
versionCache.set(packagesRoot, versions);
|
|
6549
|
+
return versions;
|
|
6550
|
+
}
|
|
6551
|
+
|
|
6424
6552
|
// src/commands/app-scaffold-cloudflare-constants.ts
|
|
6425
6553
|
var CLOUDFLARE_ACCOUNT_ID = "49ef1ba682ad8cfd720c86699ae17521";
|
|
6426
6554
|
var STAGING_CLOUDFLARE_ACCOUNT_ID = "4f4e1c69a3830946f9fea7b1eb7531ac";
|
|
@@ -6453,7 +6581,7 @@ function packageJson(application, target, options) {
|
|
|
6453
6581
|
devDependencies.tailwindcss = "3.4.19";
|
|
6454
6582
|
dependencies["react-router-dom"] = "^7.6.2";
|
|
6455
6583
|
} else {
|
|
6456
|
-
dependencies["@topolo/login"] = topoloPackageVersion("@topolo/login", target);
|
|
6584
|
+
dependencies["@topolo/login"] = topoloPackageVersion("@topolo/login", target, options.repoRoot);
|
|
6457
6585
|
}
|
|
6458
6586
|
}
|
|
6459
6587
|
if (options.api) {
|
|
@@ -6465,13 +6593,13 @@ function packageJson(application, target, options) {
|
|
|
6465
6593
|
scripts["deploy:staging"] = `DEPLOY_ENVIRONMENT=staging CLOUDFLARE_ACCOUNT_ID=${STAGING_CLOUDFLARE_ACCOUNT_ID} python3 .github/scripts/standard_deploy.py local-deploy`;
|
|
6466
6594
|
scripts["deploy:production"] = `DEPLOY_ENVIRONMENT=production CLOUDFLARE_ACCOUNT_ID=${CLOUDFLARE_ACCOUNT_ID} python3 .github/scripts/standard_deploy.py local-deploy`;
|
|
6467
6595
|
} else {
|
|
6468
|
-
dependencies["@topolo/sdk"] = topoloPackageVersion("@topolo/sdk", target);
|
|
6596
|
+
dependencies["@topolo/sdk"] = topoloPackageVersion("@topolo/sdk", target, options.repoRoot);
|
|
6469
6597
|
scripts.deploy = "npm run build && wrangler deploy";
|
|
6470
6598
|
}
|
|
6471
6599
|
devDependencies.wrangler = "^4.91.0";
|
|
6472
6600
|
}
|
|
6473
6601
|
for (const packageName of options.packages) {
|
|
6474
|
-
dependencies[packageName] = topoloPackageVersion(packageName, target);
|
|
6602
|
+
dependencies[packageName] = topoloPackageVersion(packageName, target, options.repoRoot);
|
|
6475
6603
|
}
|
|
6476
6604
|
if (target === "platform") {
|
|
6477
6605
|
const testDirs = [];
|
|
@@ -6513,14 +6641,16 @@ function packageJson(application, target, options) {
|
|
|
6513
6641
|
})}
|
|
6514
6642
|
`;
|
|
6515
6643
|
}
|
|
6516
|
-
function topoloPackageVersion(packageName, target) {
|
|
6644
|
+
function topoloPackageVersion(packageName, target, repoRoot) {
|
|
6517
6645
|
if (target === "developer") {
|
|
6518
6646
|
if (packageName === "@topolo/login") return "^0.1.0";
|
|
6519
6647
|
if (packageName === "@topolo-io/auth-client") return "^1.0.0";
|
|
6520
6648
|
if (packageName === "@topolo/sdk") return "^0.8.1";
|
|
6521
6649
|
return "^0.1.0";
|
|
6522
6650
|
}
|
|
6523
|
-
if (packageName.startsWith("@topolo/") || packageName.startsWith("@topolo-io/"))
|
|
6651
|
+
if (packageName.startsWith("@topolo/") || packageName.startsWith("@topolo-io/")) {
|
|
6652
|
+
return platformPackagePin(packageName, { repoRoot });
|
|
6653
|
+
}
|
|
6524
6654
|
throw new Error(`Unknown Topolo platform package: ${packageName}`);
|
|
6525
6655
|
}
|
|
6526
6656
|
function hasScaffoldResources(resources) {
|
|
@@ -8489,10 +8619,10 @@ function developerWorkerTs(application) {
|
|
|
8489
8619
|
}
|
|
8490
8620
|
|
|
8491
8621
|
// src/commands/app-scaffold-generate.ts
|
|
8492
|
-
import { existsSync as existsSync3, mkdirSync, mkdtempSync, readFileSync as
|
|
8622
|
+
import { existsSync as existsSync3, mkdirSync, mkdtempSync, readFileSync as readFileSync5, rmSync, writeFileSync } from "fs";
|
|
8493
8623
|
import { spawnSync } from "child_process";
|
|
8494
8624
|
import { tmpdir } from "os";
|
|
8495
|
-
import
|
|
8625
|
+
import path3 from "path";
|
|
8496
8626
|
function resolveGeneratorPath() {
|
|
8497
8627
|
const candidates = [
|
|
8498
8628
|
// Published CLI: vendored alongside dist/index.js at build time.
|
|
@@ -8519,18 +8649,18 @@ var GENERATED = {
|
|
|
8519
8649
|
};
|
|
8520
8650
|
function deriveGeneratedConfigs(files, base) {
|
|
8521
8651
|
const generator = resolveGeneratorPath();
|
|
8522
|
-
const root = mkdtempSync(
|
|
8652
|
+
const root = mkdtempSync(path3.join(tmpdir(), "topolo-scaffold-generate-"));
|
|
8523
8653
|
try {
|
|
8524
8654
|
const prefix = `${base}/`;
|
|
8525
8655
|
for (const file of files) {
|
|
8526
8656
|
if (!file.path.startsWith(prefix)) continue;
|
|
8527
|
-
const abs =
|
|
8528
|
-
mkdirSync(
|
|
8657
|
+
const abs = path3.join(root, file.path.slice(prefix.length));
|
|
8658
|
+
mkdirSync(path3.dirname(abs), { recursive: true });
|
|
8529
8659
|
writeFileSync(abs, file.content, "utf8");
|
|
8530
8660
|
}
|
|
8531
8661
|
const result = spawnSync(
|
|
8532
8662
|
process.execPath,
|
|
8533
|
-
[generator, `--manifest=${
|
|
8663
|
+
[generator, `--manifest=${path3.join(root, "topolo.app.json")}`],
|
|
8534
8664
|
{ cwd: root, encoding: "utf8" }
|
|
8535
8665
|
);
|
|
8536
8666
|
if (result.status !== 0) {
|
|
@@ -8547,7 +8677,7 @@ ${result.stdout ?? ""}`);
|
|
|
8547
8677
|
return written.map((rel) => ({
|
|
8548
8678
|
path: `${base}/${rel}`,
|
|
8549
8679
|
...GENERATED,
|
|
8550
|
-
content:
|
|
8680
|
+
content: readFileSync5(path3.join(root, rel), "utf8")
|
|
8551
8681
|
}));
|
|
8552
8682
|
} finally {
|
|
8553
8683
|
rmSync(root, { recursive: true, force: true });
|
|
@@ -9781,7 +9911,8 @@ function applicationScaffoldPayload(application, options = {}) {
|
|
|
9781
9911
|
target,
|
|
9782
9912
|
browser,
|
|
9783
9913
|
api,
|
|
9784
|
-
ciWorkflow
|
|
9914
|
+
ciWorkflow,
|
|
9915
|
+
repoRoot: options.repoRoot
|
|
9785
9916
|
}),
|
|
9786
9917
|
commands: scaffoldCommands({
|
|
9787
9918
|
id,
|
|
@@ -9869,7 +10000,8 @@ function scaffoldFiles(options) {
|
|
|
9869
10000
|
browser: options.browser,
|
|
9870
10001
|
api: options.api,
|
|
9871
10002
|
resources: options.payload.resources,
|
|
9872
|
-
packages: options.payload.capabilityComposition.packages
|
|
10003
|
+
packages: options.payload.capabilityComposition.packages,
|
|
10004
|
+
repoRoot: options.repoRoot
|
|
9873
10005
|
})
|
|
9874
10006
|
},
|
|
9875
10007
|
{
|
|
@@ -10680,18 +10812,18 @@ import { join as join3 } from "path";
|
|
|
10680
10812
|
|
|
10681
10813
|
// src/commands/app-reconcile.ts
|
|
10682
10814
|
import { readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
|
|
10683
|
-
import
|
|
10815
|
+
import path5 from "path";
|
|
10684
10816
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
10685
10817
|
import { stdin as input2, stdout as output } from "process";
|
|
10686
10818
|
|
|
10687
10819
|
// src/commands/app-capability-composition.ts
|
|
10688
10820
|
import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
|
|
10689
|
-
import
|
|
10821
|
+
import path4 from "path";
|
|
10690
10822
|
async function reconcileApplicationCapabilitySource(options) {
|
|
10691
|
-
const manifestPath =
|
|
10692
|
-
const root =
|
|
10693
|
-
const packagePath =
|
|
10694
|
-
const contractPath =
|
|
10823
|
+
const manifestPath = path4.resolve(options.manifestPath || "topolo.app.json");
|
|
10824
|
+
const root = path4.dirname(manifestPath);
|
|
10825
|
+
const packagePath = path4.join(root, "package.json");
|
|
10826
|
+
const contractPath = path4.join(root, "topolo.capability-contract.json");
|
|
10695
10827
|
const manifest = parseRecord(await readFile3(manifestPath, "utf8"), manifestPath);
|
|
10696
10828
|
const registration = record(manifest.registration);
|
|
10697
10829
|
if (!registration) throw new Error("topolo.app.json must declare registration before capability composition.");
|
|
@@ -10736,7 +10868,7 @@ async function reconcileApplicationCapabilitySource(options) {
|
|
|
10736
10868
|
const nextDependencies = { ...dependencies };
|
|
10737
10869
|
for (const packageName of capabilities.packages) {
|
|
10738
10870
|
if (typeof nextDependencies[packageName] !== "string") {
|
|
10739
|
-
nextDependencies[packageName] = packageVersion(packageName, target);
|
|
10871
|
+
nextDependencies[packageName] = packageVersion(packageName, target, { repoRoot: options.repoRoot, cwd: root });
|
|
10740
10872
|
}
|
|
10741
10873
|
}
|
|
10742
10874
|
const sortedDependencies = sortRecord(nextDependencies);
|
|
@@ -10746,9 +10878,9 @@ async function reconcileApplicationCapabilitySource(options) {
|
|
|
10746
10878
|
compareChange(changes, "topolo.capability-contract.json", existingContract, expectedContract);
|
|
10747
10879
|
const adapter = target === "platform" ? managedCapabilityAdapter(capabilities.selected) : null;
|
|
10748
10880
|
const apiDirectory = resolveApiDirectory(root, manifest, target);
|
|
10749
|
-
const adapterPath =
|
|
10881
|
+
const adapterPath = path4.join(apiDirectory, "src", "topolo-capabilities.ts");
|
|
10750
10882
|
if (adapter) compareChange(changes, relativePath(root, adapterPath), await readOptionalText(adapterPath), adapter);
|
|
10751
|
-
const pricingPath =
|
|
10883
|
+
const pricingPath = path4.join(root, "pricing-manifest.json");
|
|
10752
10884
|
const pricingManifest = capabilities.selected.includes("billing") ? defaultPricingManifest({
|
|
10753
10885
|
appId: String(manifest.appId || manifest.app_id || "").trim(),
|
|
10754
10886
|
displayName: String(registration.displayName || manifest.name || "Application"),
|
|
@@ -10760,7 +10892,7 @@ async function reconcileApplicationCapabilitySource(options) {
|
|
|
10760
10892
|
const missingResources = capabilities.resources.filter((resource) => !manifestProvidesResource(manifest, resource));
|
|
10761
10893
|
const verticalConfiguration = [];
|
|
10762
10894
|
for (const [capability2, fileName, description] of VERTICAL_CAPABILITY_FILES) {
|
|
10763
|
-
if (capabilities.selected.includes(capability2) && !await fileExists(
|
|
10895
|
+
if (capabilities.selected.includes(capability2) && !await fileExists(path4.join(root, fileName))) {
|
|
10764
10896
|
verticalConfiguration.push(`${fileName}: ${description}`);
|
|
10765
10897
|
}
|
|
10766
10898
|
}
|
|
@@ -10775,7 +10907,7 @@ async function reconcileApplicationCapabilitySource(options) {
|
|
|
10775
10907
|
await writeJson(contractPath, expectedContract);
|
|
10776
10908
|
if (pricingManifest) await writeJson(pricingPath, pricingManifest);
|
|
10777
10909
|
if (adapter) {
|
|
10778
|
-
await mkdir3(
|
|
10910
|
+
await mkdir3(path4.dirname(adapterPath), { recursive: true });
|
|
10779
10911
|
await writeFile4(adapterPath, adapter, "utf8");
|
|
10780
10912
|
}
|
|
10781
10913
|
}
|
|
@@ -10878,11 +11010,8 @@ function manifestProvidesResource(manifest, resource) {
|
|
|
10878
11010
|
}
|
|
10879
11011
|
return false;
|
|
10880
11012
|
}
|
|
10881
|
-
function packageVersion(packageName, target) {
|
|
10882
|
-
if (target === "platform")
|
|
10883
|
-
if (packageName === "@topolo-io/notifications") return "^0.6.8";
|
|
10884
|
-
return "latest";
|
|
10885
|
-
}
|
|
11013
|
+
function packageVersion(packageName, target, resolution) {
|
|
11014
|
+
if (target === "platform") return platformPackagePin(packageName, resolution);
|
|
10886
11015
|
if (packageName === "@topolo/login") return "^0.1.0";
|
|
10887
11016
|
if (packageName === "@topolo/sdk") return "^0.8.1";
|
|
10888
11017
|
throw new Error(`Capability registry exposed private package ${packageName} to a third-party application.`);
|
|
@@ -10959,13 +11088,13 @@ function resolveApiDirectory(root, manifest, target) {
|
|
|
10959
11088
|
for (const value of Object.values(record(manifest.targets) ?? {})) {
|
|
10960
11089
|
const targetRecord = record(value);
|
|
10961
11090
|
if (targetRecord?.kind === "worker" && !targetRecord.assets && typeof targetRecord.dir === "string") {
|
|
10962
|
-
return
|
|
11091
|
+
return path4.resolve(root, targetRecord.dir);
|
|
10963
11092
|
}
|
|
10964
11093
|
}
|
|
10965
|
-
return
|
|
11094
|
+
return path4.join(root, "apps", "api");
|
|
10966
11095
|
}
|
|
10967
11096
|
function relativePath(root, filePath) {
|
|
10968
|
-
return
|
|
11097
|
+
return path4.relative(root, filePath).split(path4.sep).join("/");
|
|
10969
11098
|
}
|
|
10970
11099
|
|
|
10971
11100
|
// src/commands/app-reconcile.ts
|
|
@@ -11035,7 +11164,7 @@ function titleFromSlug(value) {
|
|
|
11035
11164
|
return value.replace(/^topolo[-_]/, "").split(/[-_]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
11036
11165
|
}
|
|
11037
11166
|
async function completeApplicationRegistrationInteractively(options) {
|
|
11038
|
-
const manifestPath =
|
|
11167
|
+
const manifestPath = path5.resolve(options.manifestPath || "topolo.app.json");
|
|
11039
11168
|
const manifest = JSON.parse(await readFile4(manifestPath, "utf8"));
|
|
11040
11169
|
const existing = record2(manifest.registration) || {};
|
|
11041
11170
|
const appId = String(manifest.appId || manifest.app_id || "").trim();
|
|
@@ -11115,7 +11244,7 @@ async function completeApplicationRegistrationInteractively(options) {
|
|
|
11115
11244
|
}
|
|
11116
11245
|
}
|
|
11117
11246
|
async function loadApplicationReconcileRequest(options) {
|
|
11118
|
-
const manifestPath =
|
|
11247
|
+
const manifestPath = path5.resolve(options.manifestPath || "topolo.app.json");
|
|
11119
11248
|
const raw = await readFile4(manifestPath, "utf8");
|
|
11120
11249
|
const manifest = JSON.parse(raw);
|
|
11121
11250
|
assertRegistration(manifest.registration);
|
|
@@ -11519,7 +11648,7 @@ function applicationAuditPayload(application, options = {}) {
|
|
|
11519
11648
|
}
|
|
11520
11649
|
function recordApplicationEvidence(application, options = {}) {
|
|
11521
11650
|
const appId = resolveApplication(application).id;
|
|
11522
|
-
const root =
|
|
11651
|
+
const root = path6.resolve(options.appRoot ?? process.cwd());
|
|
11523
11652
|
if (!existsSync4(root)) {
|
|
11524
11653
|
throw new Error(`Application root does not exist: ${root}`);
|
|
11525
11654
|
}
|
|
@@ -11531,12 +11660,12 @@ function recordApplicationEvidence(application, options = {}) {
|
|
|
11531
11660
|
commit = void 0;
|
|
11532
11661
|
}
|
|
11533
11662
|
}
|
|
11534
|
-
const evidenceDir =
|
|
11535
|
-
const evidencePath =
|
|
11663
|
+
const evidenceDir = path6.join(root, ".topolo");
|
|
11664
|
+
const evidencePath = path6.join(evidenceDir, "evidence.json");
|
|
11536
11665
|
let before = null;
|
|
11537
11666
|
if (existsSync4(evidencePath)) {
|
|
11538
11667
|
try {
|
|
11539
|
-
const raw = JSON.parse(
|
|
11668
|
+
const raw = JSON.parse(readFileSync6(evidencePath, "utf8"));
|
|
11540
11669
|
if (raw && typeof raw === "object" && raw.version === 1) {
|
|
11541
11670
|
before = raw;
|
|
11542
11671
|
}
|
|
@@ -11831,14 +11960,14 @@ function statusesAtOrWorse(threshold) {
|
|
|
11831
11960
|
}
|
|
11832
11961
|
|
|
11833
11962
|
// src/commands/platform.ts
|
|
11834
|
-
import { readdirSync as
|
|
11835
|
-
import
|
|
11963
|
+
import { readdirSync as readdirSync3, readFileSync as readFileSync7, statSync as statSync2 } from "fs";
|
|
11964
|
+
import path8 from "path";
|
|
11836
11965
|
|
|
11837
11966
|
// src/commands/app-capability-provision.ts
|
|
11838
11967
|
import { readFile as readFile5, writeFile as writeFile6 } from "fs/promises";
|
|
11839
|
-
import
|
|
11968
|
+
import path7 from "path";
|
|
11840
11969
|
async function provisionApplicationResources(options) {
|
|
11841
|
-
const manifestPath =
|
|
11970
|
+
const manifestPath = path7.resolve(options.manifestPath || "topolo.app.json");
|
|
11842
11971
|
const manifest = parseRecord2(await readFile5(manifestPath, "utf8"), manifestPath);
|
|
11843
11972
|
const environments = requiredRecord(manifest.environments, "topolo.app.json#environments");
|
|
11844
11973
|
const environment = requiredRecord(environments[options.environment], `topolo.app.json#environments.${options.environment}`);
|
|
@@ -12043,7 +12172,8 @@ function registerPlatformCommand(program2) {
|
|
|
12043
12172
|
navigationMode: opts.navigationMode,
|
|
12044
12173
|
workspaceSwitcher: opts.workspaceSwitcher,
|
|
12045
12174
|
uiTemplate: opts.uiTemplate,
|
|
12046
|
-
tagline: opts.tagline
|
|
12175
|
+
tagline: opts.tagline,
|
|
12176
|
+
repoRoot: opts.repoRoot
|
|
12047
12177
|
});
|
|
12048
12178
|
if (opts.workflowOnly && !payload.ciWorkflow) {
|
|
12049
12179
|
throw new Error("--workflow-only is only available for first-party scaffolds.");
|
|
@@ -12110,12 +12240,12 @@ var SKIPPED_SCAN_DIRS = /* @__PURE__ */ new Set([
|
|
|
12110
12240
|
"output"
|
|
12111
12241
|
]);
|
|
12112
12242
|
function scanStagingProductionUrls(rootInput, allowPatterns) {
|
|
12113
|
-
const root =
|
|
12243
|
+
const root = path8.resolve(rootInput);
|
|
12114
12244
|
const allowlist = allowPatterns.map((pattern) => new RegExp(pattern));
|
|
12115
12245
|
const violations = [];
|
|
12116
12246
|
function shouldSkipFile(filePath) {
|
|
12117
|
-
const basename2 =
|
|
12118
|
-
const relativePath2 =
|
|
12247
|
+
const basename2 = path8.basename(filePath);
|
|
12248
|
+
const relativePath2 = path8.relative(root, filePath);
|
|
12119
12249
|
if (basename2 === "package-lock.json" || basename2 === "pnpm-lock.yaml" || basename2 === "yarn.lock") return true;
|
|
12120
12250
|
if (basename2 === "topolo.cloudcontrol.json") return true;
|
|
12121
12251
|
if (basename2 === "wrangler.toml" || basename2 === "wrangler.jsonc") return true;
|
|
@@ -12124,15 +12254,15 @@ function scanStagingProductionUrls(rootInput, allowPatterns) {
|
|
|
12124
12254
|
if (basename2.endsWith(".generated.ts")) return true;
|
|
12125
12255
|
if (basename2.endsWith(".test.ts") || basename2.endsWith(".test.tsx") || basename2.endsWith(".spec.ts")) return true;
|
|
12126
12256
|
if (basename2 === ".env.production") return true;
|
|
12127
|
-
if (relativePath2 ===
|
|
12128
|
-
if (relativePath2.includes(`${
|
|
12129
|
-
if (relativePath2.startsWith(`scripts${
|
|
12130
|
-
return !RUNTIME_EXTENSIONS.has(
|
|
12257
|
+
if (relativePath2 === path8.join("src", "environment.ts") || relativePath2 === path8.join("src", "environmentUrls.ts") || relativePath2.endsWith(path8.join("src", "environment.ts")) || relativePath2.endsWith(path8.join("src", "lib", "environment.ts")) || relativePath2 === path8.join("packages", "topolo-ui-kit", "src", "environmentUrls.ts")) return true;
|
|
12258
|
+
if (relativePath2.includes(`${path8.sep}test${path8.sep}`) || relativePath2.includes(`${path8.sep}tests${path8.sep}`) || relativePath2.includes(`${path8.sep}e2e${path8.sep}`)) return true;
|
|
12259
|
+
if (relativePath2.startsWith(`scripts${path8.sep}`) || relativePath2.includes(`${path8.sep}scripts${path8.sep}`)) return true;
|
|
12260
|
+
return !RUNTIME_EXTENSIONS.has(path8.extname(filePath));
|
|
12131
12261
|
}
|
|
12132
12262
|
function scanFile(filePath) {
|
|
12133
12263
|
if (shouldSkipFile(filePath)) return;
|
|
12134
|
-
const relativePath2 =
|
|
12135
|
-
const content =
|
|
12264
|
+
const relativePath2 = path8.relative(root, filePath);
|
|
12265
|
+
const content = readFileSync7(filePath, "utf8");
|
|
12136
12266
|
const lines = content.split(/\r?\n/);
|
|
12137
12267
|
lines.forEach((line, index) => {
|
|
12138
12268
|
const matches = [...line.matchAll(PRODUCTION_TOPOLO_URL_PATTERN)].map((match) => match[0]);
|
|
@@ -12145,8 +12275,8 @@ function scanStagingProductionUrls(rootInput, allowPatterns) {
|
|
|
12145
12275
|
});
|
|
12146
12276
|
}
|
|
12147
12277
|
function walk(dir) {
|
|
12148
|
-
for (const entry of
|
|
12149
|
-
const fullPath =
|
|
12278
|
+
for (const entry of readdirSync3(dir, { withFileTypes: true })) {
|
|
12279
|
+
const fullPath = path8.join(dir, entry.name);
|
|
12150
12280
|
if (entry.isDirectory()) {
|
|
12151
12281
|
if (!SKIPPED_SCAN_DIRS.has(entry.name)) walk(fullPath);
|
|
12152
12282
|
continue;
|
|
@@ -12314,7 +12444,7 @@ var DEFAULT_SEED_BASE_URL = "https://seed.stg.topolo.us";
|
|
|
12314
12444
|
function seedBaseUrl() {
|
|
12315
12445
|
return process.env.TOPOLO_SEED_URL || DEFAULT_SEED_BASE_URL;
|
|
12316
12446
|
}
|
|
12317
|
-
async function authedFetch(
|
|
12447
|
+
async function authedFetch(path9, init = {}) {
|
|
12318
12448
|
const credential = await refreshCredentialIfNeeded("staging");
|
|
12319
12449
|
if (!credential) {
|
|
12320
12450
|
throw new Error("No staging credential configured. Run `topolo auth login --env staging` or set TOPOLO_STAGING_API_KEY.");
|
|
@@ -12324,7 +12454,7 @@ async function authedFetch(path8, init = {}) {
|
|
|
12324
12454
|
else headers.set("Authorization", `Bearer ${credential.accessToken}`);
|
|
12325
12455
|
headers.set("X-Topolo-Client", `topolo-cli/${CLI_VERSION}`);
|
|
12326
12456
|
if (init.body && !headers.has("Content-Type")) headers.set("Content-Type", "application/json");
|
|
12327
|
-
const response = await fetch(`${seedBaseUrl()}${
|
|
12457
|
+
const response = await fetch(`${seedBaseUrl()}${path9}`, { ...init, headers });
|
|
12328
12458
|
const text = await response.text();
|
|
12329
12459
|
let body;
|
|
12330
12460
|
try {
|
|
@@ -12601,7 +12731,7 @@ function createOAuthClientPayload(options) {
|
|
|
12601
12731
|
logo_url: options.logoUrl
|
|
12602
12732
|
};
|
|
12603
12733
|
}
|
|
12604
|
-
async function authFetchJson(
|
|
12734
|
+
async function authFetchJson(path9, init = {}) {
|
|
12605
12735
|
const environment = selectedEnvironment();
|
|
12606
12736
|
const credential = await refreshCredentialIfNeeded(environment);
|
|
12607
12737
|
if (!credential) {
|
|
@@ -12623,7 +12753,7 @@ async function authFetchJson(path8, init = {}) {
|
|
|
12623
12753
|
throw err;
|
|
12624
12754
|
}
|
|
12625
12755
|
headers.set("Authorization", `Bearer ${credential.accessToken}`);
|
|
12626
|
-
const response = await fetch(`${authBaseUrl}${
|
|
12756
|
+
const response = await fetch(`${authBaseUrl}${path9}`, { ...init, headers });
|
|
12627
12757
|
const text = await response.text();
|
|
12628
12758
|
const payload = text ? JSON.parse(text) : {};
|
|
12629
12759
|
if (!response.ok || payload.success === false) {
|
|
@@ -12878,11 +13008,11 @@ function registerViaOfficialCli(cli, mcp, agentName) {
|
|
|
12878
13008
|
return result.status === 0;
|
|
12879
13009
|
}
|
|
12880
13010
|
async function registerClaudeViaConfig(mcp) {
|
|
12881
|
-
const
|
|
13011
|
+
const path9 = join5(homedir2(), ".claude.json");
|
|
12882
13012
|
let config = {};
|
|
12883
|
-
if (existsSync5(
|
|
13013
|
+
if (existsSync5(path9)) {
|
|
12884
13014
|
try {
|
|
12885
|
-
config = JSON.parse(await readFile7(
|
|
13015
|
+
config = JSON.parse(await readFile7(path9, "utf8"));
|
|
12886
13016
|
} catch {
|
|
12887
13017
|
config = {};
|
|
12888
13018
|
}
|
|
@@ -12895,13 +13025,13 @@ async function registerClaudeViaConfig(mcp) {
|
|
|
12895
13025
|
env: { TOPOLO_AGENT_NAME: AGENT_NAME_FOR.claude }
|
|
12896
13026
|
};
|
|
12897
13027
|
config.mcpServers = servers;
|
|
12898
|
-
await writeFile7(
|
|
13028
|
+
await writeFile7(path9, `${JSON.stringify(config, null, 2)}
|
|
12899
13029
|
`, "utf8");
|
|
12900
13030
|
}
|
|
12901
13031
|
async function registerCodexViaConfig(mcp) {
|
|
12902
|
-
const
|
|
13032
|
+
const path9 = join5(homedir2(), ".codex", "config.toml");
|
|
12903
13033
|
let text = "";
|
|
12904
|
-
if (existsSync5(
|
|
13034
|
+
if (existsSync5(path9)) text = await readFile7(path9, "utf8");
|
|
12905
13035
|
text = text.replace(
|
|
12906
13036
|
/(^|\n)\[mcp_servers\.topolo(?:\.[a-z]+)?\][^\[]*/g,
|
|
12907
13037
|
(match) => match.startsWith("\n") ? "\n" : ""
|
|
@@ -12917,8 +13047,8 @@ command = "${mcp.command}"${argsToml}
|
|
|
12917
13047
|
[mcp_servers.topolo.env]
|
|
12918
13048
|
TOPOLO_AGENT_NAME = "${AGENT_NAME_FOR.codex}"
|
|
12919
13049
|
`;
|
|
12920
|
-
await mkdir4(dirname4(
|
|
12921
|
-
await writeFile7(
|
|
13050
|
+
await mkdir4(dirname4(path9), { recursive: true });
|
|
13051
|
+
await writeFile7(path9, `${text}${block}`, "utf8");
|
|
12922
13052
|
}
|
|
12923
13053
|
async function installForAgent(agent, sourceDir, mcp, opts) {
|
|
12924
13054
|
const skillDir = agent === "claude" ? claudeSkillDir(opts.projectDir) : codexSkillDir();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topolo/cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.6",
|
|
4
4
|
"topoloPublishedVersion": "0.6.5",
|
|
5
5
|
"description": "Command-line interface for Topolo developers, operators, and agents, with internal first-party scaffolding available under the topolo platform namespace.",
|
|
6
6
|
"type": "module",
|
|
@@ -11,20 +11,6 @@
|
|
|
11
11
|
"dist",
|
|
12
12
|
"skills"
|
|
13
13
|
],
|
|
14
|
-
"scripts": {
|
|
15
|
-
"build:sdk": "python3 ../../tooling/with-resource-lock.py ../topolo-sdk -- pnpm --dir ../topolo-sdk build",
|
|
16
|
-
"prebuild": "pnpm run build:sdk",
|
|
17
|
-
"build": "tsup && node scripts/vendor-generator.mjs",
|
|
18
|
-
"dev": "tsup --watch",
|
|
19
|
-
"pretypecheck": "pnpm run build:sdk",
|
|
20
|
-
"typecheck": "tsc --noEmit",
|
|
21
|
-
"start": "node dist/index.js",
|
|
22
|
-
"pretest": "pnpm run build:sdk",
|
|
23
|
-
"test": "vitest run",
|
|
24
|
-
"test:watch": "vitest",
|
|
25
|
-
"precoverage": "pnpm run build:sdk",
|
|
26
|
-
"coverage": "vitest run --coverage"
|
|
27
|
-
},
|
|
28
14
|
"dependencies": {
|
|
29
15
|
"commander": "^12.1.0"
|
|
30
16
|
},
|
|
@@ -38,5 +24,19 @@
|
|
|
38
24
|
},
|
|
39
25
|
"engines": {
|
|
40
26
|
"node": ">=20"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build:sdk": "python3 ../../tooling/with-resource-lock.py ../topolo-sdk -- pnpm --dir ../topolo-sdk build",
|
|
30
|
+
"prebuild": "pnpm run build:sdk",
|
|
31
|
+
"build": "tsup && node scripts/vendor-generator.mjs",
|
|
32
|
+
"dev": "tsup --watch",
|
|
33
|
+
"pretypecheck": "pnpm run build:sdk",
|
|
34
|
+
"typecheck": "tsc --noEmit",
|
|
35
|
+
"start": "node dist/index.js",
|
|
36
|
+
"pretest": "pnpm run build:sdk",
|
|
37
|
+
"test": "vitest run",
|
|
38
|
+
"test:watch": "vitest",
|
|
39
|
+
"precoverage": "pnpm run build:sdk",
|
|
40
|
+
"coverage": "vitest run --coverage"
|
|
41
41
|
}
|
|
42
|
-
}
|
|
42
|
+
}
|