@topolo/cli 0.6.1 → 0.6.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/generate-wrangler.mjs +17 -1
- package/dist/index.js +53 -24
- package/package.json +3 -3
|
@@ -288,6 +288,7 @@ function emitWranglerToml(targetName, target) {
|
|
|
288
288
|
lines.push(`directory = ${tomlString(target.assets.directory || target.outputDir || 'dist')}`);
|
|
289
289
|
if (target.assets.binding) lines.push(`binding = ${tomlString(target.assets.binding)}`);
|
|
290
290
|
else lines.push(`binding = "ASSETS"`);
|
|
291
|
+
if (target.assets.htmlHandling) lines.push(`html_handling = ${tomlString(target.assets.htmlHandling)}`);
|
|
291
292
|
if (target.assets.notFoundHandling) lines.push(`not_found_handling = ${tomlString(target.assets.notFoundHandling)}`);
|
|
292
293
|
if (target.assets.runWorkerFirst !== undefined) lines.push(`run_worker_first = ${tomlString(target.assets.runWorkerFirst)}`);
|
|
293
294
|
lines.push('');
|
|
@@ -390,6 +391,7 @@ function emitWranglerToml(targetName, target) {
|
|
|
390
391
|
lines.push(`[env.${env}.assets]`);
|
|
391
392
|
lines.push(`directory = ${tomlString(target.assets.directory || target.outputDir || 'dist')}`);
|
|
392
393
|
lines.push(`binding = ${tomlString(target.assets.binding || 'ASSETS')}`);
|
|
394
|
+
if (target.assets.htmlHandling) lines.push(`html_handling = ${tomlString(target.assets.htmlHandling)}`);
|
|
393
395
|
if (target.assets.notFoundHandling) lines.push(`not_found_handling = ${tomlString(target.assets.notFoundHandling)}`);
|
|
394
396
|
if (target.assets.runWorkerFirst !== undefined) lines.push(`run_worker_first = ${tomlString(target.assets.runWorkerFirst)}`);
|
|
395
397
|
lines.push('');
|
|
@@ -572,6 +574,20 @@ function emitBindings(lines, bindings, env) {
|
|
|
572
574
|
lines.push(`service = ${tomlString(service)}`);
|
|
573
575
|
lines.push('');
|
|
574
576
|
}
|
|
577
|
+
// Cloudflare Secrets Store bindings — the durable data-at-rest key escrow
|
|
578
|
+
// (docs/data-at-rest-encryption-architecture.md). Store ids differ per env
|
|
579
|
+
// (per-env Cloudflare accounts), so the shape mirrors d1/kv: per-env config
|
|
580
|
+
// objects under the binding.
|
|
581
|
+
for (const s of bindings.secretsStore || []) {
|
|
582
|
+
if (!bindingAppliesToEnv(s, env)) continue;
|
|
583
|
+
const cfg = s[env];
|
|
584
|
+
if (!cfg) continue;
|
|
585
|
+
lines.push(`[[env.${env}.secrets_store_secrets]]`);
|
|
586
|
+
lines.push(`binding = ${tomlString(s.binding)}`);
|
|
587
|
+
lines.push(`store_id = ${tomlString(cfg.storeId)}`);
|
|
588
|
+
lines.push(`secret_name = ${tomlString(cfg.secretName)}`);
|
|
589
|
+
lines.push('');
|
|
590
|
+
}
|
|
575
591
|
for (const a of bindings.ai || []) {
|
|
576
592
|
lines.push(`[env.${env}.ai]`);
|
|
577
593
|
lines.push(`binding = ${tomlString(a.binding)}`);
|
|
@@ -595,7 +611,7 @@ function emitCloudcontrol() {
|
|
|
595
611
|
deployableTargets.flatMap((target) => target.environments || ENVS),
|
|
596
612
|
);
|
|
597
613
|
cc.deploy_method = deployableTargets.length ? 'wrangler' : 'none';
|
|
598
|
-
cc.ci_provider = existing.ci_provider || '
|
|
614
|
+
cc.ci_provider = existing.ci_provider || 'local';
|
|
599
615
|
cc.quality_policy = existing.quality_policy || {
|
|
600
616
|
profile: 'first_party_app',
|
|
601
617
|
coverage: { mode: 'ratchet' },
|
package/dist/index.js
CHANGED
|
@@ -277,7 +277,9 @@ var APPLICATIONS = {
|
|
|
277
277
|
"domains": [
|
|
278
278
|
"brand.topolo.app"
|
|
279
279
|
],
|
|
280
|
-
"routes": [
|
|
280
|
+
"routes": [
|
|
281
|
+
"brand.topolo.app"
|
|
282
|
+
],
|
|
281
283
|
"appId": "brand"
|
|
282
284
|
},
|
|
283
285
|
{
|
|
@@ -307,7 +309,9 @@ var APPLICATIONS = {
|
|
|
307
309
|
"domains": [
|
|
308
310
|
"bugfix.topolo.app"
|
|
309
311
|
],
|
|
310
|
-
"routes": [
|
|
312
|
+
"routes": [
|
|
313
|
+
"bugfix.topolo.app"
|
|
314
|
+
],
|
|
311
315
|
"appId": "bugfix"
|
|
312
316
|
}
|
|
313
317
|
]
|
|
@@ -361,7 +365,9 @@ var APPLICATIONS = {
|
|
|
361
365
|
"domains": [
|
|
362
366
|
"calendar.topolo.app"
|
|
363
367
|
],
|
|
364
|
-
"routes": [
|
|
368
|
+
"routes": [
|
|
369
|
+
"calendar.topolo.app"
|
|
370
|
+
],
|
|
365
371
|
"appId": "calendar"
|
|
366
372
|
},
|
|
367
373
|
{
|
|
@@ -421,7 +427,9 @@ var APPLICATIONS = {
|
|
|
421
427
|
"domains": [
|
|
422
428
|
"capacity.topolo.app"
|
|
423
429
|
],
|
|
424
|
-
"routes": [
|
|
430
|
+
"routes": [
|
|
431
|
+
"capacity.topolo.app"
|
|
432
|
+
],
|
|
425
433
|
"appId": "capacity"
|
|
426
434
|
}
|
|
427
435
|
]
|
|
@@ -443,7 +451,9 @@ var APPLICATIONS = {
|
|
|
443
451
|
"domains": [
|
|
444
452
|
"chat.topolo.app"
|
|
445
453
|
],
|
|
446
|
-
"routes": [
|
|
454
|
+
"routes": [
|
|
455
|
+
"chat.topolo.app"
|
|
456
|
+
],
|
|
447
457
|
"appId": "chat"
|
|
448
458
|
},
|
|
449
459
|
{
|
|
@@ -1003,7 +1013,9 @@ var APPLICATIONS = {
|
|
|
1003
1013
|
"domains": [
|
|
1004
1014
|
"mail.topolo.app"
|
|
1005
1015
|
],
|
|
1006
|
-
"routes": [
|
|
1016
|
+
"routes": [
|
|
1017
|
+
"mail.topolo.app"
|
|
1018
|
+
],
|
|
1007
1019
|
"appId": "mail"
|
|
1008
1020
|
},
|
|
1009
1021
|
{
|
|
@@ -1163,7 +1175,9 @@ var APPLICATIONS = {
|
|
|
1163
1175
|
"domains": [
|
|
1164
1176
|
"observability-watch.topolo.app"
|
|
1165
1177
|
],
|
|
1166
|
-
"routes": [
|
|
1178
|
+
"routes": [
|
|
1179
|
+
"observability-watch.topolo.app"
|
|
1180
|
+
],
|
|
1167
1181
|
"appId": "observability_watch"
|
|
1168
1182
|
}
|
|
1169
1183
|
]
|
|
@@ -1798,7 +1812,7 @@ var APPLICATION_REQUIREMENTS = [
|
|
|
1798
1812
|
"Use TopoloAppMetricCard, TopoloAppEmptyState, TopoloAppStatusBadge, TopoloAppGrid, and TopoloAppSection for repeated app body patterns",
|
|
1799
1813
|
"Keep visual QA fixtures available through visualQa=1 or __devpreview=1 so screenshot checks do not depend on live API state",
|
|
1800
1814
|
"Keep mobile and desktop shell behavior aligned with the platform UI kit",
|
|
1801
|
-
"Constrain app
|
|
1815
|
+
"Constrain the app workspace-view layout wrappers with min-width: 0, width: auto, and viewport-aware max-width so shell padding cannot create page-level horizontal overflow"
|
|
1802
1816
|
]
|
|
1803
1817
|
},
|
|
1804
1818
|
{
|
|
@@ -3403,6 +3417,7 @@ var CrmModule = class {
|
|
|
3403
3417
|
constructor(client) {
|
|
3404
3418
|
this.client = client;
|
|
3405
3419
|
}
|
|
3420
|
+
client;
|
|
3406
3421
|
async listContacts(options = {}) {
|
|
3407
3422
|
const res = await this.client.request({
|
|
3408
3423
|
service: "crm",
|
|
@@ -3448,6 +3463,7 @@ var IdentityModule = class {
|
|
|
3448
3463
|
constructor(client) {
|
|
3449
3464
|
this.client = client;
|
|
3450
3465
|
}
|
|
3466
|
+
client;
|
|
3451
3467
|
/** Returns the resolved user, organization, and permission set for the
|
|
3452
3468
|
* current credential. Equivalent to `TopoloClient.introspect()` — exposed
|
|
3453
3469
|
* on this module for symmetry with the other domain modules. */
|
|
@@ -9461,20 +9477,13 @@ function scaffoldFiles(options) {
|
|
|
9461
9477
|
`CREATE TABLE IF NOT EXISTS ${tablePrefix}_workspaces (`,
|
|
9462
9478
|
" id TEXT PRIMARY KEY,",
|
|
9463
9479
|
` ${tenantColumn} TEXT NOT NULL,`,
|
|
9464
|
-
"
|
|
9465
|
-
" slug TEXT NOT NULL,",
|
|
9466
|
-
" created_by_user_id TEXT,",
|
|
9467
|
-
" created_by_email TEXT,",
|
|
9480
|
+
" status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'archived')),",
|
|
9468
9481
|
" created_at TEXT NOT NULL,",
|
|
9469
|
-
" updated_at TEXT NOT NULL
|
|
9470
|
-
` UNIQUE(${tenantColumn}, slug)`,
|
|
9482
|
+
" updated_at TEXT NOT NULL",
|
|
9471
9483
|
");",
|
|
9472
9484
|
"",
|
|
9473
9485
|
`CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workspaces_${tenantColumn}`,
|
|
9474
9486
|
` ON ${tablePrefix}_workspaces(${tenantColumn});`,
|
|
9475
|
-
"",
|
|
9476
|
-
`CREATE INDEX IF NOT EXISTS idx_${tablePrefix}_workspaces_slug`,
|
|
9477
|
-
` ON ${tablePrefix}_workspaces(${tenantColumn}, slug);`,
|
|
9478
9487
|
""
|
|
9479
9488
|
].join("\n");
|
|
9480
9489
|
const base = target === "platform" ? firstPartyAppPath(application.appDir, options.payload.audience) : application.appDir;
|
|
@@ -10037,10 +10046,10 @@ export default defineConfig({
|
|
|
10037
10046
|
if (options.payload.resources.d1) {
|
|
10038
10047
|
files.push({
|
|
10039
10048
|
path: `${apiBase}/migrations/0001_initial.sql`,
|
|
10040
|
-
purpose: "Canonical multi-tenant baseline: the
|
|
10049
|
+
purpose: "Canonical multi-tenant baseline: the identity-only workspace mirror (platform owns the record).",
|
|
10041
10050
|
requiredSignals: [
|
|
10042
|
-
`${tablePrefix}_workspaces
|
|
10043
|
-
|
|
10051
|
+
`${tablePrefix}_workspaces is an identity-only mirror (id, ${tenantColumn}, status) \u2014 no name/slug/is_default; the workspace record lives in TopoloAuth`,
|
|
10052
|
+
`every domain table added later carries ${tenantColumn} and a workspace_id scope column`
|
|
10044
10053
|
],
|
|
10045
10054
|
content: workspacesMigrationSql
|
|
10046
10055
|
});
|
|
@@ -10332,6 +10341,22 @@ async function reconcileApplicationCapabilitySource(options) {
|
|
|
10332
10341
|
distributionModel: registration.distributionModel === "marketplace" ? "marketplace" : "organization_internal",
|
|
10333
10342
|
requested: [...existing, ...options.additions ?? []]
|
|
10334
10343
|
});
|
|
10344
|
+
const marketplace = record(registration.marketplace);
|
|
10345
|
+
const unlistedNativeArtifact = options.ownerType === "topolo_first_party" && registration.surfaceModel === "mobile_container" && registration.distributionModel === "organization_internal" && marketplace?.intent === "unlisted";
|
|
10346
|
+
if (unlistedNativeArtifact) {
|
|
10347
|
+
return {
|
|
10348
|
+
mode: options.mode,
|
|
10349
|
+
applied: false,
|
|
10350
|
+
status: "in_sync",
|
|
10351
|
+
manifestPath,
|
|
10352
|
+
packagePath,
|
|
10353
|
+
contractPath,
|
|
10354
|
+
capabilities,
|
|
10355
|
+
changes: [],
|
|
10356
|
+
missingResources: [],
|
|
10357
|
+
verticalConfiguration: []
|
|
10358
|
+
};
|
|
10359
|
+
}
|
|
10335
10360
|
const expectedComposition = capabilityCompositionProjection(capabilities);
|
|
10336
10361
|
const expectedNotifications = capabilities.selected.includes("notification_producer") ? { role: "producer", contracts: "topolo.notification-contracts.json" } : capabilities.selected.includes("notifications") ? { role: "consumer_only" } : { role: "internal_non_producer" };
|
|
10337
10362
|
const changes = [];
|
|
@@ -10598,6 +10623,9 @@ function resolveManifestApplicationUrl(manifest, environment) {
|
|
|
10598
10623
|
if (hostOverride) return `https://${hostOverride.replace(/^https?:\/\//, "").replace(/\/+$/, "")}`;
|
|
10599
10624
|
const domain = manifest.environments?.[environment]?.domain;
|
|
10600
10625
|
if (!target.subdomain || !domain) {
|
|
10626
|
+
if (manifest.registration?.productionUrl) {
|
|
10627
|
+
return manifest.registration.productionUrl.replace(/\/+$/, "");
|
|
10628
|
+
}
|
|
10601
10629
|
throw new Error(`Cannot derive the ${environment} application URL from target ${targetName}.`);
|
|
10602
10630
|
}
|
|
10603
10631
|
return `https://${target.subdomain}.${domain}`;
|
|
@@ -10623,10 +10651,11 @@ function assertRegistration(value) {
|
|
|
10623
10651
|
"version",
|
|
10624
10652
|
"pricing",
|
|
10625
10653
|
"supportEmail",
|
|
10626
|
-
"auth",
|
|
10627
10654
|
"capabilities",
|
|
10628
10655
|
"marketplace"
|
|
10629
10656
|
];
|
|
10657
|
+
const marketplace = record2(registration?.marketplace);
|
|
10658
|
+
if (marketplace?.intent !== "unlisted") required.push("auth");
|
|
10630
10659
|
const missing = required.filter((field) => registration?.[field] == null || registration[field] === "");
|
|
10631
10660
|
if (missing.length) {
|
|
10632
10661
|
throw new Error(
|
|
@@ -10730,7 +10759,7 @@ async function loadApplicationReconcileRequest(options) {
|
|
|
10730
10759
|
}
|
|
10731
10760
|
const environment = options.environment || selectedEnvironment();
|
|
10732
10761
|
const productionUrl = resolveManifestApplicationUrl(manifest, environment);
|
|
10733
|
-
const callbackPath = registration.auth.callbackPath.startsWith("/") ? registration.auth.callbackPath : `/${registration.auth.callbackPath}
|
|
10762
|
+
const callbackPath = registration.auth ? registration.auth.callbackPath.startsWith("/") ? registration.auth.callbackPath : `/${registration.auth.callbackPath}` : null;
|
|
10734
10763
|
const appId = String(manifest.appId || manifest.app_id || "").trim();
|
|
10735
10764
|
if (!appId) throw new Error("topolo.app.json must declare the immutable appId.");
|
|
10736
10765
|
return {
|
|
@@ -10760,8 +10789,8 @@ async function loadApplicationReconcileRequest(options) {
|
|
|
10760
10789
|
supportEmail: registration.supportEmail,
|
|
10761
10790
|
tags: registration.tags ?? [],
|
|
10762
10791
|
screenshots: registration.screenshots ?? [],
|
|
10763
|
-
callbackUrls: [`${productionUrl}${callbackPath}`],
|
|
10764
|
-
requestedScopes: registration.auth
|
|
10792
|
+
callbackUrls: callbackPath ? [`${productionUrl}${callbackPath}`] : [],
|
|
10793
|
+
requestedScopes: registration.auth?.requestedScopes ?? [],
|
|
10765
10794
|
capabilities: registration.capabilities,
|
|
10766
10795
|
marketplace: { ...registration.marketplace, appUrl: productionUrl },
|
|
10767
10796
|
notifications: manifest.notifications ?? null
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topolo/cli",
|
|
3
|
-
"version": "0.6.
|
|
4
|
-
"topoloPublishedVersion": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
|
+
"topoloPublishedVersion": "0.6.4",
|
|
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",
|
|
7
7
|
"bin": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"skills"
|
|
13
13
|
],
|
|
14
14
|
"scripts": {
|
|
15
|
-
"build:sdk": "pnpm --dir ../topolo-sdk build",
|
|
15
|
+
"build:sdk": "python3 ../../tooling/with-resource-lock.py ../topolo-sdk -- pnpm --dir ../topolo-sdk build",
|
|
16
16
|
"prebuild": "pnpm run build:sdk",
|
|
17
17
|
"build": "tsup && node scripts/vendor-generator.mjs",
|
|
18
18
|
"dev": "tsup --watch",
|