@brightsideoy/kama 1.0.0-alpha.11 → 1.0.0-alpha.13
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/bin/cli.js +51 -32
- package/dist/assets/{index-BVkEzCNs.js → index-B1ogCRCg.js} +1 -1
- package/dist/build-seed.js +37 -28
- package/dist/index.html +1 -1
- package/package.json +3 -2
package/bin/cli.js
CHANGED
|
@@ -50,8 +50,8 @@ try {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
- 🎯 SECURE SECRET MANAGER
|
|
54
|
+
- Gracefully retrieves an existing workspace secret, or generates and injects one if missing.
|
|
55
55
|
*/
|
|
56
56
|
function getOrGenerateWorkspaceSecret(workerDir) {
|
|
57
57
|
const envPath = join(workerDir, '.env');
|
|
@@ -89,7 +89,7 @@ function getOrGenerateWorkspaceSecret(workerDir) {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
|
-
|
|
92
|
+
- 🎯 BULLETPROOF WRANGLER EXECUTION RESOLVER
|
|
93
93
|
*/
|
|
94
94
|
function getWranglerCmd() {
|
|
95
95
|
try {
|
|
@@ -101,7 +101,7 @@ function getWranglerCmd() {
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
/**
|
|
104
|
-
|
|
104
|
+
- 🎯 ROBUST WRANGLER RUNNER
|
|
105
105
|
*/
|
|
106
106
|
function runWrangler(cmd, options = {}) {
|
|
107
107
|
const baseWrangler = getWranglerCmd();
|
|
@@ -121,7 +121,7 @@ function runWrangler(cmd, options = {}) {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
/**
|
|
124
|
-
|
|
124
|
+
- 🎯 BULLETPROOF KV PROVISIONING ENGINE
|
|
125
125
|
*/
|
|
126
126
|
function getOrCreateKV(title) {
|
|
127
127
|
const out = runWrangler(`kv namespace create "${title}"`);
|
|
@@ -154,7 +154,7 @@ function showHelp() {
|
|
|
154
154
|
console.log(pc.cyan('Workspace Scripts (Run from project root):'));
|
|
155
155
|
console.log(' npm update Update to latest KAMA version');
|
|
156
156
|
console.log(' npm run setup Initialize database schema (Run Once)');
|
|
157
|
-
console.log(' npm run seed -w kama-worker Seed the database with mock test data');
|
|
157
|
+
console.log(' npm run seed -w kama-worker Seed the database with mock test data');
|
|
158
158
|
console.log(' npm run dev Boot up the CMS backend and Astro frontend concurrently');
|
|
159
159
|
console.log(' npm run deploy:cms Deploy the backend worker and database to Cloudflare');
|
|
160
160
|
console.log(' npm run deploy:site Deploy the Astro frontend site to Cloudflare\n');
|
|
@@ -224,7 +224,7 @@ function convertAstroConfigToCloudflare(siteDir) {
|
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
/**
|
|
227
|
-
|
|
227
|
+
- COMMAND: npx kama init
|
|
228
228
|
*/
|
|
229
229
|
async function createFullWorkspace() {
|
|
230
230
|
const cwdName = basename(process.cwd());
|
|
@@ -407,15 +407,16 @@ async function createFullWorkspace() {
|
|
|
407
407
|
type: 'module',
|
|
408
408
|
version: '1.0.0',
|
|
409
409
|
scripts: {
|
|
410
|
-
|
|
411
|
-
"seed": "node ../node_modules/@brightsideoy/kama/dist/build-seed.js && wrangler d1 execute " + dbName + " --local --file
|
|
410
|
+
"seed": "npm run seed:local",
|
|
411
|
+
"seed:local": "node ../node_modules/@brightsideoy/kama/dist/build-seed.js && for f in seed-*.sql; do wrangler d1 execute " + dbName + " --local --file=\"$f\"; done",
|
|
412
|
+
"seed:remote": "node ../node_modules/@brightsideoy/kama/dist/build-seed.js && for f in seed-*.sql; do wrangler d1 execute " + dbName + " --remote --file=\"$f\"; done",
|
|
412
413
|
"setup:local": `wrangler d1 execute ${dbName} --local --file=../node_modules/@brightsideoy/kama/schema.sql > /dev/null 2>&1`,
|
|
413
414
|
"setup:remote": `wrangler d1 execute ${dbName} --remote --file=../node_modules/@brightsideoy/kama/schema.sql`,
|
|
414
415
|
"dev": "wrangler dev --port 8787 --inspector-port 9239",
|
|
415
416
|
"deploy": "npm run setup:remote && wrangler deploy"
|
|
416
417
|
},
|
|
417
418
|
dependencies: { '@brightsideoy/kama': currentKamaVersion, '@libsql/client': '^0.14.0' },
|
|
418
|
-
devDependencies: { "wrangler": WRANGLER_LATEST },
|
|
419
|
+
devDependencies: { "wrangler": WRANGLER_LATEST },
|
|
419
420
|
}, null, 2)
|
|
420
421
|
);
|
|
421
422
|
|
|
@@ -442,7 +443,6 @@ async function createFullWorkspace() {
|
|
|
442
443
|
|
|
443
444
|
writeFileSync(join(cmsDir, 'wrangler.json'), JSON.stringify(cmsWranglerConfig, null, 2));
|
|
444
445
|
|
|
445
|
-
// 🎯 Inject API Secret directly into .dev.vars
|
|
446
446
|
const publicFrontendUrl = (shouldCreateSite) ? (siteDomain && siteDomain !== 'localhost:4321' ? `https://${siteDomain}` : 'http://localhost:4321') : 'http://localhost:4321';
|
|
447
447
|
writeFileSync(join(cmsDir, '.dev.vars'), `# Cloudflare Edge Cache Purging Secrets\nCLOUDFLARE_API_TOKEN=cfut_YOUR_CUSTOM_PURGE_TOKEN\n\n# Local Development Overrides\nCDN_DOMAIN=\nPUBLIC_FRONTEND_URL=${publicFrontendUrl}\n\n# Server-to-Server API Security\nFRONTEND_API_SECRET="${frontendApiSecret}"\n`);
|
|
448
448
|
} else {
|
|
@@ -456,18 +456,17 @@ async function createFullWorkspace() {
|
|
|
456
456
|
type: 'module',
|
|
457
457
|
version: '1.0.0',
|
|
458
458
|
scripts: {
|
|
459
|
-
|
|
460
|
-
"seed": "node ../node_modules/@brightsideoy/kama/dist/build-seed.js && sqlite3 kama.db
|
|
459
|
+
"seed": "npm run seed:local",
|
|
460
|
+
"seed:local": "node ../node_modules/@brightsideoy/kama/dist/build-seed.js && cat seed-*.sql | sqlite3 kama.db",
|
|
461
461
|
"setup:local": "sqlite3 kama.db < ../node_modules/@brightsideoy/kama/schema.sql",
|
|
462
462
|
"dev": "tsx server.js",
|
|
463
463
|
"start": "node server.js"
|
|
464
464
|
},
|
|
465
465
|
dependencies: { '@brightsideoy/kama': currentKamaVersion, '@hono/node-server': '^1.13.0', '@libsql/client': '^0.14.0', 'sharp': '^0.33.5', 'dotenv': '^16.4.5' },
|
|
466
|
-
devDependencies: { "tsx": "^4.19.0" },
|
|
466
|
+
devDependencies: { "tsx": "^4.19.0" },
|
|
467
467
|
}, null, 2)
|
|
468
468
|
);
|
|
469
469
|
|
|
470
|
-
// 🎯 Inject API Secret directly into .env
|
|
471
470
|
writeFileSync(join(cmsDir, '.env'), `PORT=8787\nKAMA_RUNTIME=node\nDB_PATH=./kama.db\nLOCAL_MEDIA_PATH=./public/media\nPUBLIC_CMS_URL=http://127.0.0.1:8787\nPUBLIC_API_URL=http://127.0.0.1:8787\nPUBLIC_FRONTEND_URL=http://127.0.0.1:4321\n\n# Server-to-Server API Security\nFRONTEND_API_SECRET="${frontendApiSecret}"\n`);
|
|
472
471
|
}
|
|
473
472
|
|
|
@@ -476,7 +475,6 @@ async function createFullWorkspace() {
|
|
|
476
475
|
|
|
477
476
|
if (shouldCreateSite) {
|
|
478
477
|
s.message(`Scaffolding Astro site (${siteFolderName})...`);
|
|
479
|
-
// 🎯 Pass secret to the frontend generator
|
|
480
478
|
await generateAstroSite(rootDir, siteFolderName, siteDomain, cmsFullUrl, workerName, isCloudflare, frontendApiSecret);
|
|
481
479
|
}
|
|
482
480
|
|
|
@@ -501,7 +499,7 @@ async function createFullWorkspace() {
|
|
|
501
499
|
}
|
|
502
500
|
|
|
503
501
|
/**
|
|
504
|
-
|
|
502
|
+
- COMMAND: npx kama add site
|
|
505
503
|
*/
|
|
506
504
|
async function createNewSiteOnly() {
|
|
507
505
|
const rootDir = process.cwd();
|
|
@@ -525,7 +523,6 @@ async function createNewSiteOnly() {
|
|
|
525
523
|
} catch (e) { }
|
|
526
524
|
}
|
|
527
525
|
|
|
528
|
-
// 🎯 Ensure secret exists in worker before provisioning site
|
|
529
526
|
const frontendApiSecret = existsSync(workerDir) ? getOrGenerateWorkspaceSecret(workerDir) : crypto.randomBytes(32).toString('hex');
|
|
530
527
|
|
|
531
528
|
const isCloudflare = handleCancel(await select({
|
|
@@ -558,7 +555,6 @@ async function createNewSiteOnly() {
|
|
|
558
555
|
const s = spinner();
|
|
559
556
|
s.start(`Generating Astro site...`);
|
|
560
557
|
|
|
561
|
-
// 🎯 Pass secret to the frontend generator
|
|
562
558
|
await generateAstroSite(rootDir, siteFolder, siteDomain, cmsFullUrl, targetWorkerName, isCloudflare, frontendApiSecret);
|
|
563
559
|
|
|
564
560
|
s.stop(`Site created in sites/${siteFolder}!`);
|
|
@@ -568,7 +564,7 @@ async function createNewSiteOnly() {
|
|
|
568
564
|
}
|
|
569
565
|
|
|
570
566
|
/**
|
|
571
|
-
|
|
567
|
+
- COMMAND: npx kama bundle
|
|
572
568
|
*/
|
|
573
569
|
async function bundleWorkspaceSchemas(targetRootDir, silent = false) {
|
|
574
570
|
let rootDir = targetRootDir || process.cwd();
|
|
@@ -587,7 +583,7 @@ async function bundleWorkspaceSchemas(targetRootDir, silent = false) {
|
|
|
587
583
|
}
|
|
588
584
|
|
|
589
585
|
/**
|
|
590
|
-
|
|
586
|
+
- COMMAND: npx kama promote
|
|
591
587
|
*/
|
|
592
588
|
async function promoteLocalToCloudflare() {
|
|
593
589
|
const rootDir = process.cwd();
|
|
@@ -599,7 +595,6 @@ async function promoteLocalToCloudflare() {
|
|
|
599
595
|
process.exit(1);
|
|
600
596
|
}
|
|
601
597
|
|
|
602
|
-
// 🎯 Safely persist the secret during promotion
|
|
603
598
|
const frontendApiSecret = getOrGenerateWorkspaceSecret(workerDir);
|
|
604
599
|
|
|
605
600
|
const s = spinner();
|
|
@@ -635,12 +630,34 @@ async function promoteLocalToCloudflare() {
|
|
|
635
630
|
|
|
636
631
|
const projName = basename(rootDir);
|
|
637
632
|
let dbName = `${projName}-db`.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
633
|
+
|
|
634
|
+
// 🎯 1. ARCHITECTURE FIX: Check if the database already exists
|
|
638
635
|
let d1DatabaseId = '00000000-0000-0000-0000-000000000000';
|
|
636
|
+
const listOutput = runWrangler('d1 list --json');
|
|
637
|
+
let dbExists = false;
|
|
639
638
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
639
|
+
if (listOutput) {
|
|
640
|
+
try {
|
|
641
|
+
const jsonStart = listOutput.indexOf('[');
|
|
642
|
+
const jsonEnd = listOutput.lastIndexOf(']') + 1;
|
|
643
|
+
if (jsonStart !== -1 && jsonEnd !== -1) {
|
|
644
|
+
const databases = JSON.parse(listOutput.substring(jsonStart, jsonEnd));
|
|
645
|
+
const existingDb = databases.find(db => db.name === dbName);
|
|
646
|
+
if (existingDb) {
|
|
647
|
+
d1DatabaseId = existingDb.uuid;
|
|
648
|
+
dbExists = true;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
} catch (e) { }
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// 2. If it doesn't exist, create it safely
|
|
655
|
+
if (!dbExists) {
|
|
656
|
+
const d1Output = runWrangler(`d1 create ${dbName}`);
|
|
657
|
+
if (d1Output) {
|
|
658
|
+
const match = d1Output.match(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/);
|
|
659
|
+
if (match) d1DatabaseId = match[0];
|
|
660
|
+
}
|
|
644
661
|
}
|
|
645
662
|
|
|
646
663
|
const workerName = `${projName}-worker`.toLowerCase().replace(/[^a-z0-9_-]/g, '-');
|
|
@@ -687,12 +704,13 @@ async function promoteLocalToCloudflare() {
|
|
|
687
704
|
workerPkg.scripts["setup:local"] = `wrangler d1 execute ${dbName} --local --file=../node_modules/@brightsideoy/kama/schema.sql`;
|
|
688
705
|
workerPkg.scripts["setup:remote"] = `wrangler d1 execute ${dbName} --remote --file=../node_modules/@brightsideoy/kama/schema.sql`;
|
|
689
706
|
|
|
690
|
-
|
|
691
|
-
|
|
707
|
+
workerPkg.scripts["seed"] = "npm run seed:local";
|
|
708
|
+
// 🎯 3. ARCHITECTURE FIX: Chunked seed loops for promoted worker
|
|
709
|
+
workerPkg.scripts["seed:local"] = `node ../node_modules/@brightsideoy/kama/dist/build-seed.js && for f in seed-*.sql; do wrangler d1 execute ${dbName} --local --file="$f"; done`;
|
|
710
|
+
workerPkg.scripts["seed:remote"] = `node ../node_modules/@brightsideoy/kama/dist/build-seed.js && for f in seed-*.sql; do wrangler d1 execute ${dbName} --remote --file="$f"; done`;
|
|
692
711
|
|
|
693
712
|
workerPkg.devDependencies = workerPkg.devDependencies || {};
|
|
694
713
|
workerPkg.devDependencies.wrangler = WRANGLER_LATEST;
|
|
695
|
-
// 🎯 explicit deletion of TSX addition on promotion
|
|
696
714
|
if (workerPkg.devDependencies.tsx) delete workerPkg.devDependencies.tsx;
|
|
697
715
|
|
|
698
716
|
writeFileSync(workerPkgPath, JSON.stringify(workerPkg, null, 2));
|
|
@@ -714,7 +732,8 @@ async function promoteLocalToCloudflare() {
|
|
|
714
732
|
assets: { directory: "./dist/client", binding: "ASSETS", run_worker_first: true },
|
|
715
733
|
kv_namespaces: [{ binding: "SESSION", id: sessionId }, { binding: "HTML_CACHE", id: htmlCacheId }],
|
|
716
734
|
services: [{ binding: "CMS_WORKER", service: currentConfig.name }],
|
|
717
|
-
|
|
735
|
+
// 🎯 2. ARCHITECTURE FIX: Removed strict zone_name requirement
|
|
736
|
+
routes: [{ pattern: siteDomain, custom_domain: true, enabled: true, previews_enabled: false }],
|
|
718
737
|
vars: { PUBLIC_CMS_URL: `https://${cmsDomain}`, PUBLIC_API_URL: `https://${cmsDomain}` }
|
|
719
738
|
};
|
|
720
739
|
writeFileSync(siteWranglerPath, JSON.stringify(siteConfig, null, 2));
|
|
@@ -739,7 +758,7 @@ async function promoteLocalToCloudflare() {
|
|
|
739
758
|
}
|
|
740
759
|
|
|
741
760
|
/**
|
|
742
|
-
|
|
761
|
+
- Helper: Copies the Astro starter template and hydrates runtime tokens
|
|
743
762
|
*/
|
|
744
763
|
async function generateAstroSite(rootDir, siteFolder, siteDomain, cmsFullUrl, workerName = 'kama-worker', isCloudflare = false, frontendApiSecret = '') {
|
|
745
764
|
const siteDir = join(rootDir, 'sites', siteFolder);
|
|
@@ -800,6 +819,7 @@ async function generateAstroSite(rootDir, siteFolder, siteDomain, cmsFullUrl, wo
|
|
|
800
819
|
assets: { directory: "./dist/client", binding: "ASSETS", run_worker_first: true },
|
|
801
820
|
kv_namespaces: [{ binding: "SESSION", id: sessionId }, { binding: "HTML_CACHE", id: htmlCacheId }],
|
|
802
821
|
services: [{ binding: "CMS_WORKER", service: workerName }],
|
|
822
|
+
routes: [{ pattern: siteDomain, custom_domain: true, enabled: true, previews_enabled: false }],
|
|
803
823
|
vars: { PUBLIC_CMS_URL: cmsFullUrl, PUBLIC_API_URL: cmsFullUrl, PUBLIC_CHANNEL_ID: channelKey, PUBLIC_TREE_ID: treeKey, PUBLIC_SITE_NAME: siteLabel }
|
|
804
824
|
};
|
|
805
825
|
|
|
@@ -807,7 +827,6 @@ async function generateAstroSite(rootDir, siteFolder, siteDomain, cmsFullUrl, wo
|
|
|
807
827
|
writeFileSync(join(siteDir, 'wrangler.json'), JSON.stringify(siteConfig, null, 2));
|
|
808
828
|
}
|
|
809
829
|
|
|
810
|
-
// 🎯 Dynamically append the secret to the Astro environment setup
|
|
811
830
|
let envContent = `# Local Development Overrides\nPUBLIC_CMS_URL="http://127.0.0.1:8787"\nPUBLIC_API_URL="http://127.0.0.1:8787"\nPUBLIC_CHANNEL_ID="${channelKey}"\nPUBLIC_TREE_ID="${treeKey}"\nPUBLIC_SITE_NAME="${siteLabel.replace(/"/g, '\\"')}"\n`;
|
|
812
831
|
|
|
813
832
|
if (frontendApiSecret) {
|