@brightsideoy/kama 0.1.0-alpha.1 ā 0.1.0-alpha.14
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 +248 -0
- package/package.json +10 -6
package/bin/cli.js
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execSync } from 'node:child_process';
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import * as readline from 'node:readline/promises';
|
|
6
|
+
|
|
7
|
+
const rl = readline.createInterface({
|
|
8
|
+
input: process.stdin,
|
|
9
|
+
output: process.stdout,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
async function main() {
|
|
13
|
+
console.log('\nš„ --- KAMA SITE GENERATOR --- š„\n');
|
|
14
|
+
|
|
15
|
+
console.log('Select mode:');
|
|
16
|
+
console.log(' 1) Kickstart new Kama Monorepo (CMS + Initial Site)');
|
|
17
|
+
console.log(' 2) Add a new Astro Site to current workspace (sites/)');
|
|
18
|
+
|
|
19
|
+
const choice = await rl.question('\nChoice [1/2]: ');
|
|
20
|
+
|
|
21
|
+
if (choice.trim() === '2') {
|
|
22
|
+
await createNewSiteOnly();
|
|
23
|
+
} else {
|
|
24
|
+
await createFullWorkspace();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
rl.close();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* MODE 1: Kickstart full Monorepo Workspace
|
|
32
|
+
*/
|
|
33
|
+
async function createFullWorkspace() {
|
|
34
|
+
const projName = (await rl.question('Project folder name [kama-network]: ')) || 'kama-network';
|
|
35
|
+
const domain = (await rl.question('Base domain [t3cloud.eu]: ')) || 't3cloud.eu';
|
|
36
|
+
const sitePrefix = (await rl.question('First site prefix/subdomain [kamafe]: ')) || 'kamafe';
|
|
37
|
+
|
|
38
|
+
const rootDir = join(process.cwd(), projName);
|
|
39
|
+
const cmsDomain = `kama.${domain}`;
|
|
40
|
+
const siteDomain = `${sitePrefix}.${domain}`;
|
|
41
|
+
|
|
42
|
+
console.log(`\nš Creating workspace folder at ./${projName}...`);
|
|
43
|
+
mkdirSync(rootDir, { recursive: true });
|
|
44
|
+
|
|
45
|
+
// 1. Root package.json
|
|
46
|
+
writeFileSync(
|
|
47
|
+
join(rootDir, 'package.json'),
|
|
48
|
+
JSON.stringify(
|
|
49
|
+
{
|
|
50
|
+
name: projName,
|
|
51
|
+
private: true,
|
|
52
|
+
type: 'module',
|
|
53
|
+
workspaces: ['cms-worker', 'sites/*'],
|
|
54
|
+
scripts: {
|
|
55
|
+
'dev:cms': 'npm run dev -w cms-worker',
|
|
56
|
+
'deploy:cms': 'npm run deploy -w cms-worker',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
null,
|
|
60
|
+
2
|
|
61
|
+
)
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
// 2. Setup CMS Worker
|
|
65
|
+
console.log(`\nāļø Configuring CMS Worker (${cmsDomain})...`);
|
|
66
|
+
const cmsDir = join(rootDir, 'cms-worker');
|
|
67
|
+
mkdirSync(cmsDir, { recursive: true });
|
|
68
|
+
|
|
69
|
+
writeFileSync(
|
|
70
|
+
join(cmsDir, 'package.json'),
|
|
71
|
+
JSON.stringify(
|
|
72
|
+
{
|
|
73
|
+
name: 'kama-worker',
|
|
74
|
+
type: 'module',
|
|
75
|
+
version: '1.0.0',
|
|
76
|
+
scripts: {
|
|
77
|
+
dev: 'wrangler dev',
|
|
78
|
+
deploy: 'wrangler deploy',
|
|
79
|
+
},
|
|
80
|
+
dependencies: {
|
|
81
|
+
'@brightsideoy/kama': 'latest',
|
|
82
|
+
},
|
|
83
|
+
devDependencies: {
|
|
84
|
+
wrangler: '^4.127.1',
|
|
85
|
+
tsx: '^4.19.2',
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
null,
|
|
89
|
+
2
|
|
90
|
+
)
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
writeFileSync(
|
|
94
|
+
join(cmsDir, 'wrangler.json'),
|
|
95
|
+
JSON.stringify(
|
|
96
|
+
{
|
|
97
|
+
$schema: 'node_modules/wrangler/config-schema.json',
|
|
98
|
+
name: 'kama-worker',
|
|
99
|
+
main: 'node_modules/@brightsideoy/kama/dist/index.js',
|
|
100
|
+
compatibility_date: '2026-08-01',
|
|
101
|
+
compatibility_flags: ['nodejs_compat'],
|
|
102
|
+
assets: { directory: './dist', binding: 'ASSETS' },
|
|
103
|
+
routes: [{ pattern: cmsDomain, custom_domain: true }],
|
|
104
|
+
vars: { CDN_DOMAIN: cmsDomain },
|
|
105
|
+
d1_databases: [
|
|
106
|
+
{
|
|
107
|
+
binding: 'DB',
|
|
108
|
+
database_name: 'kama_cms_db',
|
|
109
|
+
database_id: 'REPLACE_WITH_YOUR_D1_ID',
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
r2_buckets: [
|
|
113
|
+
{
|
|
114
|
+
binding: 'MEDIA_BUCKET',
|
|
115
|
+
bucket_name: 'kama-media-prod',
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
null,
|
|
120
|
+
2
|
|
121
|
+
)
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// 3. Setup First Astro Site
|
|
125
|
+
await generateAstroSite(rootDir, sitePrefix, siteDomain, cmsDomain);
|
|
126
|
+
|
|
127
|
+
console.log(`\n⨠Workspace ready! Next steps:`);
|
|
128
|
+
console.log(` 1. cd ${projName}`);
|
|
129
|
+
console.log(` 2. npm install`);
|
|
130
|
+
console.log(` 3. Update D1 ID in cms-worker/wrangler.json`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* MODE 2: Add Site to existing workspace
|
|
135
|
+
*/
|
|
136
|
+
async function createNewSiteOnly() {
|
|
137
|
+
const rootDir = process.cwd();
|
|
138
|
+
|
|
139
|
+
if (!existsSync(join(rootDir, 'package.json'))) {
|
|
140
|
+
console.error('ā Error: Must run this command inside the root of your workspace.');
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const siteName = await rl.question('Site folder name (e.g., site-two): ');
|
|
145
|
+
const customDomain = await rl.question('Custom domain (e.g., brand.com or brand.t3cloud.eu): ');
|
|
146
|
+
const cmsDomain = (await rl.question('CMS API URL [https://kama.t3cloud.eu]: ')) || 'https://kama.t3cloud.eu';
|
|
147
|
+
|
|
148
|
+
await generateAstroSite(rootDir, siteName, customDomain, cmsDomain.replace(/^https?:\/\//, ''));
|
|
149
|
+
|
|
150
|
+
console.log(`\n⨠Site created in sites/${siteName}! Run 'npm install' at workspace root.`);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Helper: Scaffolds the Astro site with middleware, wrangler.json, & slug page
|
|
155
|
+
*/
|
|
156
|
+
async function generateAstroSite(rootDir, siteFolder, siteDomain, cmsDomain) {
|
|
157
|
+
console.log(`\nš Scaffolding Astro site (${siteFolder}) mapped to ${siteDomain}...`);
|
|
158
|
+
|
|
159
|
+
const siteDir = join(rootDir, 'sites', siteFolder);
|
|
160
|
+
mkdirSync(join(siteDir, 'src/pages'), { recursive: true });
|
|
161
|
+
mkdirSync(join(siteDir, 'src/layouts'), { recursive: true });
|
|
162
|
+
mkdirSync(join(siteDir, 'src/components/blocks'), { recursive: true });
|
|
163
|
+
mkdirSync(join(siteDir, 'src/lib'), { recursive: true });
|
|
164
|
+
|
|
165
|
+
// 1. package.json
|
|
166
|
+
writeFileSync(
|
|
167
|
+
join(siteDir, 'package.json'),
|
|
168
|
+
JSON.stringify(
|
|
169
|
+
{
|
|
170
|
+
name: siteFolder,
|
|
171
|
+
type: 'module',
|
|
172
|
+
version: '0.0.1',
|
|
173
|
+
engines: { node: '>=22.12.0' },
|
|
174
|
+
scripts: {
|
|
175
|
+
dev: 'astro dev',
|
|
176
|
+
build: 'astro build',
|
|
177
|
+
preview: 'astro preview',
|
|
178
|
+
deploy: 'astro build && wrangler deploy',
|
|
179
|
+
},
|
|
180
|
+
dependencies: {
|
|
181
|
+
'@astrojs/cloudflare': '^14.2.5',
|
|
182
|
+
'@brightsideoy/kama': 'latest',
|
|
183
|
+
astro: '^7.2.2',
|
|
184
|
+
wrangler: '^4.127.1',
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
null,
|
|
188
|
+
2
|
|
189
|
+
)
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
// 2. wrangler.json
|
|
193
|
+
writeFileSync(
|
|
194
|
+
join(siteDir, 'wrangler.json'),
|
|
195
|
+
JSON.stringify(
|
|
196
|
+
{
|
|
197
|
+
$schema: 'node_modules/wrangler/config-schema.json',
|
|
198
|
+
name: siteFolder,
|
|
199
|
+
compatibility_date: '2026-08-01',
|
|
200
|
+
compatibility_flags: ['nodejs_compat'],
|
|
201
|
+
assets: {
|
|
202
|
+
directory: './dist',
|
|
203
|
+
binding: 'ASSETS',
|
|
204
|
+
html_handling: 'drop-trailing-slash',
|
|
205
|
+
not_found_handling: '404-page',
|
|
206
|
+
},
|
|
207
|
+
services: [{ binding: 'CMS_WORKER', service: 'kama-worker' }],
|
|
208
|
+
routes: [{ pattern: siteDomain, custom_domain: true }],
|
|
209
|
+
vars: {
|
|
210
|
+
PUBLIC_CMS_URL: `https://${cmsDomain}`,
|
|
211
|
+
PUBLIC_API_URL: `https://${cmsDomain}`,
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
null,
|
|
215
|
+
2
|
|
216
|
+
)
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
// 3. astro.config.mjs
|
|
220
|
+
const astroConfig = `import { defineConfig } from 'astro/config';
|
|
221
|
+
import cloudflare from '@astrojs/cloudflare';
|
|
222
|
+
|
|
223
|
+
export default defineConfig({
|
|
224
|
+
output: 'static',
|
|
225
|
+
trailingSlash: 'ignore',
|
|
226
|
+
image: {
|
|
227
|
+
remotePatterns: [
|
|
228
|
+
{ protocol: 'http', hostname: 'localhost', port: '3000' },
|
|
229
|
+
{ protocol: 'https', hostname: '${cmsDomain}' }
|
|
230
|
+
]
|
|
231
|
+
},
|
|
232
|
+
build: {
|
|
233
|
+
inlineStylesheets: 'always',
|
|
234
|
+
},
|
|
235
|
+
adapter: cloudflare({
|
|
236
|
+
imageService: 'cloudflare',
|
|
237
|
+
})
|
|
238
|
+
});`;
|
|
239
|
+
writeFileSync(join(siteDir, 'astro.config.mjs'), astroConfig);
|
|
240
|
+
|
|
241
|
+
// 4. .env file
|
|
242
|
+
writeFileSync(
|
|
243
|
+
join(siteDir, '.env'),
|
|
244
|
+
`PUBLIC_CMS_URL="https://${cmsDomain}"\nPUBLIC_API_URL="https://${cmsDomain}"\n`
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
main().catch(console.error);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brightsideoy/kama",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -10,18 +10,22 @@
|
|
|
10
10
|
"import": "./dist/index.js"
|
|
11
11
|
}
|
|
12
12
|
},
|
|
13
|
+
"bin": {
|
|
14
|
+
"kama": "./bin/cli.js",
|
|
15
|
+
"create-kama": "./bin/cli.js"
|
|
16
|
+
},
|
|
13
17
|
"files": [
|
|
14
|
-
"dist"
|
|
18
|
+
"dist",
|
|
19
|
+
"bin"
|
|
15
20
|
],
|
|
16
21
|
"scripts": {
|
|
17
22
|
"dev": "concurrently \"vite\" \"tsx watch server/index.ts\"",
|
|
18
23
|
"build": "vite build",
|
|
19
|
-
"build:cms": "
|
|
24
|
+
"build:cms": "vite build",
|
|
20
25
|
"build:seed-sql": "tsx src/db/generate-sql.ts",
|
|
21
26
|
"db:seed": "npm run build:seed-sql && tsx -e \"import Database from 'better-sqlite3'; import fs from 'node:fs'; const db = new Database('data/cms.db'); db.exec(fs.readFileSync('seed.sql', 'utf8')); console.log('ā
Database seeded successfully!');\"",
|
|
22
27
|
"d1:seed:remote": "npm run build:seed-sql && npx wrangler d1 execute YOUR_D1_NAME --remote --file=./seed.sql",
|
|
23
|
-
"serve": "tsx server/index.ts"
|
|
24
|
-
"prepublishOnly": "npm run build:cms"
|
|
28
|
+
"serve": "tsx server/index.ts"
|
|
25
29
|
},
|
|
26
30
|
"publishConfig": {
|
|
27
31
|
"access": "public"
|
|
@@ -67,4 +71,4 @@
|
|
|
67
71
|
"vite": "^8.2.1",
|
|
68
72
|
"vue-tsc": "^2.2.0"
|
|
69
73
|
}
|
|
70
|
-
}
|
|
74
|
+
}
|