domma-js 0.10.2 → 0.12.1
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/domma-cli.js +217 -15
- package/package.json +4 -1
- package/public/dist/bundles/domma-complete.css +465 -14
- package/public/dist/bundles/domma-data-focused.css +465 -14
- package/public/dist/bundles/domma-essentials.css +465 -14
- package/public/dist/bundles/domma-full.css +465 -14
- package/public/dist/bundles/domma-grayve.css +465 -14
- package/public/dist/bundles/domma-minimal.css +459 -8
- package/public/dist/domma-syntax.min.js +3 -3
- package/public/dist/domma.css +454 -3
- package/public/dist/domma.esm.js +4 -4
- package/public/dist/domma.min.js +4 -4
- package/public/dist/elements.css +3 -3
- package/public/dist/grid.css +3 -3
- package/public/dist/syntax.css +3 -3
- package/public/dist/themes/domma-themes.css +3 -3
- package/templates/kickstart/frontend/pages/index.html +1 -1
- package/templates/kickstart-spa/.claude/settings.json +68 -0
- package/templates/kickstart-spa/.claude/snippets.md +683 -0
- package/templates/kickstart-spa/backend/README.md +160 -0
- package/templates/kickstart-spa/blueprints/README.md +361 -0
- package/templates/kickstart-spa/blueprints/common/contact.js +135 -0
- package/templates/kickstart-spa/blueprints/common/settings.js +194 -0
- package/templates/kickstart-spa/blueprints/common/user.js +123 -0
- package/templates/kickstart-spa/blueprints/crud/product.js +346 -0
- package/templates/kickstart-spa/blueprints/crud/task.js +419 -0
- package/templates/kickstart-spa/blueprints/forms/login.js +292 -0
- package/templates/kickstart-spa/blueprints/forms/registration.js +254 -0
- package/templates/kickstart-spa/domma.config.json +86 -0
- package/templates/kickstart-spa/frontend/css/custom.css +72 -0
- package/templates/kickstart-spa/frontend/index.html +40 -0
- package/templates/kickstart-spa/frontend/js/app.js +146 -0
- package/templates/kickstart-spa/frontend/js/views/404.js +35 -0
- package/templates/kickstart-spa/frontend/js/views/about.js +69 -0
- package/templates/kickstart-spa/frontend/js/views/contact.js +96 -0
- package/templates/kickstart-spa/frontend/js/views/home.js +90 -0
- package/templates/kickstart-spa/frontend/js/views/index.js +15 -0
- package/templates/view-template/view.js +73 -0
package/bin/domma-cli.js
CHANGED
|
@@ -62,6 +62,8 @@ switch (command) {
|
|
|
62
62
|
*/
|
|
63
63
|
async function handleInit() {
|
|
64
64
|
const quickMode = args.includes('--quick');
|
|
65
|
+
const spaFlag = args.includes('--spa');
|
|
66
|
+
const mpaFlag = args.includes('--mpa');
|
|
65
67
|
|
|
66
68
|
// ASCII Art Banner
|
|
67
69
|
console.log(`
|
|
@@ -78,6 +80,31 @@ async function handleInit() {
|
|
|
78
80
|
let projectName = 'my-app';
|
|
79
81
|
let theme = 'charcoal-dark';
|
|
80
82
|
let includeThemeSelector = false;
|
|
83
|
+
let projectMode = 'mpa'; // Default to multi-page
|
|
84
|
+
|
|
85
|
+
// Determine project mode
|
|
86
|
+
if (spaFlag) {
|
|
87
|
+
projectMode = 'spa';
|
|
88
|
+
} else if (mpaFlag) {
|
|
89
|
+
projectMode = 'mpa';
|
|
90
|
+
} else if (!quickMode) {
|
|
91
|
+
// Prompt user to choose mode
|
|
92
|
+
const rl = readline.createInterface({input, output});
|
|
93
|
+
|
|
94
|
+
console.log(`\n Choose project type:`);
|
|
95
|
+
console.log(` ❯ Multi-Page Application (MPA) - Traditional multi-page website (default)`);
|
|
96
|
+
console.log(` Single Page Application (SPA) - Client-side routing with view switching`);
|
|
97
|
+
|
|
98
|
+
const modeAnswer = await rl.question(`\n Enter choice (mpa/spa): `);
|
|
99
|
+
const modeInput = modeAnswer.trim().toLowerCase();
|
|
100
|
+
|
|
101
|
+
if (modeInput === 'spa' || modeInput === 's') {
|
|
102
|
+
projectMode = 'spa';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
rl.close();
|
|
106
|
+
console.log('');
|
|
107
|
+
}
|
|
81
108
|
|
|
82
109
|
if (!quickMode) {
|
|
83
110
|
const rl = readline.createInterface({input, output});
|
|
@@ -113,8 +140,9 @@ async function handleInit() {
|
|
|
113
140
|
console.log('');
|
|
114
141
|
}
|
|
115
142
|
|
|
116
|
-
// Find templates directory
|
|
117
|
-
const
|
|
143
|
+
// Find templates directory based on mode
|
|
144
|
+
const templateName = projectMode === 'spa' ? 'kickstart-spa' : 'kickstart';
|
|
145
|
+
const templatesDir = join(__dirname, '..', 'templates', templateName);
|
|
118
146
|
const distDir = join(__dirname, '..', 'public', 'dist');
|
|
119
147
|
|
|
120
148
|
if (!existsSync(templatesDir)) {
|
|
@@ -171,12 +199,21 @@ async function handleInit() {
|
|
|
171
199
|
console.log(` ✓ Copied themes/`);
|
|
172
200
|
}
|
|
173
201
|
|
|
174
|
-
console.log(`\n ✓ Done! Your project "${projectName}" is ready.\n`);
|
|
202
|
+
console.log(`\n ✓ Done! Your ${projectMode.toUpperCase()} project "${projectName}" is ready.\n`);
|
|
175
203
|
console.log(` Next steps:`);
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
204
|
+
|
|
205
|
+
if (projectMode === 'spa') {
|
|
206
|
+
console.log(` 1. Open frontend/index.html in your browser`);
|
|
207
|
+
console.log(` 2. Edit domma.config.json to customise routes and navbar`);
|
|
208
|
+
console.log(` 3. Add new views: npx domma-js add view <name>`);
|
|
209
|
+
console.log(` 4. Edit views in frontend/js/views/`);
|
|
210
|
+
} else {
|
|
211
|
+
console.log(` 1. Open frontend/pages/index.html in your browser`);
|
|
212
|
+
console.log(` 2. Edit domma.config.json to customise`);
|
|
213
|
+
console.log(` 3. Add new pages: npx domma-js add page <name>`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
console.log(` ${projectMode === 'spa' ? '5' : '4'}. Read the docs: https://github.com/dcbw-it/domma\n`);
|
|
180
217
|
}
|
|
181
218
|
|
|
182
219
|
/**
|
|
@@ -189,9 +226,14 @@ async function handleAdd() {
|
|
|
189
226
|
case 'page':
|
|
190
227
|
await handleAddPage();
|
|
191
228
|
break;
|
|
229
|
+
case 'view':
|
|
230
|
+
await handleAddView();
|
|
231
|
+
break;
|
|
192
232
|
default:
|
|
193
233
|
console.error(`Unknown add command: ${subCommand}`);
|
|
194
|
-
console.log('Usage:
|
|
234
|
+
console.log('Usage:');
|
|
235
|
+
console.log(' npx domma-js add page <path> # For Multi-Page Applications');
|
|
236
|
+
console.log(' npx domma-js add view <name> # For Single Page Applications');
|
|
195
237
|
process.exit(1);
|
|
196
238
|
}
|
|
197
239
|
}
|
|
@@ -244,6 +286,157 @@ async function handleAddPage() {
|
|
|
244
286
|
createPage(pageDir, pageName);
|
|
245
287
|
}
|
|
246
288
|
|
|
289
|
+
/**
|
|
290
|
+
* Handle adding a new view (SPA only)
|
|
291
|
+
*/
|
|
292
|
+
async function handleAddView() {
|
|
293
|
+
const quickMode = args.includes('--quick');
|
|
294
|
+
let viewName = args[2];
|
|
295
|
+
|
|
296
|
+
// Check if we're in a Domma project
|
|
297
|
+
const configPath = join(process.cwd(), 'domma.config.json');
|
|
298
|
+
if (!existsSync(configPath)) {
|
|
299
|
+
console.error('\n ✗ Error: Not in a Domma project directory');
|
|
300
|
+
console.error(' Run this command from your project root (where domma.config.json is located)\n');
|
|
301
|
+
process.exit(1);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Check if it's an SPA project
|
|
305
|
+
let config;
|
|
306
|
+
try {
|
|
307
|
+
config = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
308
|
+
} catch (e) {
|
|
309
|
+
console.error('\n ✗ Error: Could not read domma.config.json');
|
|
310
|
+
process.exit(1);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (!config.spa || !config.spa.enabled) {
|
|
314
|
+
console.error('\n ✗ Error: This command is only for Single Page Applications');
|
|
315
|
+
console.error(' For Multi-Page Applications, use: npx domma-js add page <path>\n');
|
|
316
|
+
process.exit(1);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (!viewName && quickMode) {
|
|
320
|
+
console.error('View name required with --quick flag');
|
|
321
|
+
console.log('Usage: npx domma-js add view <name> --quick');
|
|
322
|
+
console.log('Example: npx domma-js add view settings --quick');
|
|
323
|
+
process.exit(1);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (!quickMode) {
|
|
327
|
+
const rl = readline.createInterface({input, output});
|
|
328
|
+
|
|
329
|
+
if (!viewName) {
|
|
330
|
+
const nameAnswer = await rl.question(' View name (e.g., settings, profile, dashboard): ');
|
|
331
|
+
viewName = nameAnswer.trim();
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (!viewName) {
|
|
335
|
+
console.error(' ✗ View name is required');
|
|
336
|
+
rl.close();
|
|
337
|
+
process.exit(1);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
rl.close();
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Sanitize view name
|
|
344
|
+
viewName = viewName.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
345
|
+
|
|
346
|
+
// Check if view already exists
|
|
347
|
+
const viewPath = join(process.cwd(), 'frontend', 'js', 'views', `${viewName}.js`);
|
|
348
|
+
if (existsSync(viewPath)) {
|
|
349
|
+
console.error(`\n ✗ View "${viewName}" already exists`);
|
|
350
|
+
process.exit(1);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Read view template
|
|
354
|
+
const viewTemplateDir = join(__dirname, '..', 'templates', 'view-template');
|
|
355
|
+
const viewTemplatePath = join(viewTemplateDir, 'view.js');
|
|
356
|
+
|
|
357
|
+
if (!existsSync(viewTemplatePath)) {
|
|
358
|
+
console.error(`\n ✗ Error: View template not found at ${viewTemplatePath}`);
|
|
359
|
+
process.exit(1);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
let viewTemplate = readFileSync(viewTemplatePath, 'utf-8');
|
|
363
|
+
|
|
364
|
+
// Create title case name
|
|
365
|
+
const titleCase = viewName.split('-').map(w =>
|
|
366
|
+
w.charAt(0).toUpperCase() + w.slice(1)
|
|
367
|
+
).join(' ');
|
|
368
|
+
|
|
369
|
+
// Variable substitution
|
|
370
|
+
const vars = {
|
|
371
|
+
'{{viewName}}': viewName,
|
|
372
|
+
'{{viewTitle}}': titleCase
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
376
|
+
viewTemplate = viewTemplate.replaceAll(key, value);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Write view file
|
|
380
|
+
writeFileSync(viewPath, viewTemplate, 'utf-8');
|
|
381
|
+
console.log(`\n ✓ Created view: frontend/js/views/${viewName}.js`);
|
|
382
|
+
|
|
383
|
+
// Update views/index.js
|
|
384
|
+
const viewsIndexPath = join(process.cwd(), 'frontend', 'js', 'views', 'index.js');
|
|
385
|
+
if (existsSync(viewsIndexPath)) {
|
|
386
|
+
let viewsIndex = readFileSync(viewsIndexPath, 'utf-8');
|
|
387
|
+
|
|
388
|
+
// Add import
|
|
389
|
+
const importStatement = `import {${viewName}View} from './${viewName}.js';\n`;
|
|
390
|
+
viewsIndex = viewsIndex.replace(/(import\s+\{[^}]+\}\s+from\s+['"][^'"]+['"];\n)+/, `$&${importStatement}`);
|
|
391
|
+
|
|
392
|
+
// Add to exports
|
|
393
|
+
const exportPattern = /export const views = \{([^}]*)\};/s;
|
|
394
|
+
const match = viewsIndex.match(exportPattern);
|
|
395
|
+
if (match) {
|
|
396
|
+
const currentExports = match[1].trim();
|
|
397
|
+
const newExport = currentExports.endsWith(',')
|
|
398
|
+
? `\n ${viewName}: ${viewName}View`
|
|
399
|
+
: `,\n ${viewName}: ${viewName}View`;
|
|
400
|
+
viewsIndex = viewsIndex.replace(exportPattern, `export const views = {${currentExports}${newExport}\n};`);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
writeFileSync(viewsIndexPath, viewsIndex, 'utf-8');
|
|
404
|
+
console.log(` ✓ Updated views/index.js`);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// Update domma.config.json - add route
|
|
408
|
+
const routePath = `/${viewName}`;
|
|
409
|
+
const newRoute = {
|
|
410
|
+
path: routePath,
|
|
411
|
+
view: viewName,
|
|
412
|
+
title: `${config.project?.name || 'App'} - ${titleCase}`
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
if (!config.routes) {
|
|
416
|
+
config.routes = [];
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
config.routes.push(newRoute);
|
|
420
|
+
console.log(` ✓ Added route: ${routePath}`);
|
|
421
|
+
|
|
422
|
+
// Update navbar items
|
|
423
|
+
if (config.navbar && config.navbar.items) {
|
|
424
|
+
const newNavItem = {
|
|
425
|
+
text: titleCase,
|
|
426
|
+
url: `#${routePath}`
|
|
427
|
+
};
|
|
428
|
+
config.navbar.items.push(newNavItem);
|
|
429
|
+
console.log(` ✓ Added navbar item: ${titleCase}`);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Write updated config
|
|
433
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
434
|
+
console.log(` ✓ Updated domma.config.json\n`);
|
|
435
|
+
|
|
436
|
+
console.log(` View "${titleCase}" is ready!`);
|
|
437
|
+
console.log(` Navigate to it at: #${routePath}\n`);
|
|
438
|
+
}
|
|
439
|
+
|
|
247
440
|
/**
|
|
248
441
|
* Create a new page from template
|
|
249
442
|
*/
|
|
@@ -466,26 +659,35 @@ function showHelp() {
|
|
|
466
659
|
Domma CLI v${VERSION} - Project scaffolding and management
|
|
467
660
|
|
|
468
661
|
Commands:
|
|
469
|
-
npx domma-js Initialize a new Domma project
|
|
662
|
+
npx domma-js Initialize a new Domma project (interactive)
|
|
470
663
|
npx domma-js init Initialize a new Domma project
|
|
471
|
-
|
|
472
|
-
|
|
664
|
+
--spa Create Single Page Application
|
|
665
|
+
--mpa Create Multi-Page Application (default)
|
|
473
666
|
--quick Skip interactive prompts
|
|
474
667
|
|
|
668
|
+
npx domma-js add page <path> Add a new page (MPA only)
|
|
669
|
+
npx domma-js add view <name> Add a new view (SPA only)
|
|
670
|
+
npx domma-js setup-ai Add AI assistance files to existing project
|
|
671
|
+
|
|
475
672
|
Options:
|
|
476
673
|
--help, -h Show this help message
|
|
477
674
|
--version, -v Show version number
|
|
478
675
|
|
|
479
676
|
Examples:
|
|
480
|
-
|
|
481
|
-
npx domma-js
|
|
677
|
+
# Initialize projects:
|
|
678
|
+
npx domma-js # Interactive setup (choose MPA or SPA)
|
|
679
|
+
npx domma-js --spa # Create SPA with prompts
|
|
680
|
+
npx domma-js --mpa --quick # Create MPA with defaults
|
|
482
681
|
npx domma-js setup-ai # Add AI assistance to existing project
|
|
483
682
|
|
|
484
|
-
# Add pages
|
|
683
|
+
# Add pages (MPA only):
|
|
485
684
|
npx domma-js add page admin # Root level (admin/)
|
|
486
685
|
npx domma-js add page pages/dashboard # One level deep (pages/dashboard/)
|
|
487
686
|
npx domma-js add page frontend/pages/profile # Two levels deep (frontend/pages/profile/)
|
|
488
|
-
|
|
687
|
+
|
|
688
|
+
# Add views (SPA only):
|
|
689
|
+
npx domma-js add view settings # Creates settings view with route
|
|
690
|
+
npx domma-js add view profile # Creates profile view with route
|
|
489
691
|
|
|
490
692
|
Note: Paths are automatically calculated based on folder depth
|
|
491
693
|
`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "domma-js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "Dynamic Object Manipulation & Modeling API - A complete front-end toolkit.",
|
|
5
5
|
"main": "public/dist/domma.min.js",
|
|
6
6
|
"module": "public/dist/domma.esm.js",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"scripts": {
|
|
33
33
|
"postinstall": "node bin/postinstall.js",
|
|
34
34
|
"dev": "NODE_ENV=development npm run generate:bundles && rollup -c && node scripts/build-info.js && npm run build:metadata && npm run copy:themes && npm run build:css && npm run build:miniapps && live-server public --port=3001 --open=/index.html",
|
|
35
|
+
"dev:watch": "NODE_ENV=development npm run generate:bundles && rollup -c && node scripts/build-info.js && npm run build:metadata && npm run copy:themes && npm run build:css && npm run build:miniapps && npm run watch:miniapps",
|
|
35
36
|
"build": "npm run generate:bundles && rollup -c && node scripts/build-info.js && npm run build:metadata && npm run copy:themes && npm run build:css && npm run build:css-bundles && npm run build:archives && npm run build:kickstart && npm run build:miniapps",
|
|
36
37
|
"build:js": "rollup -c",
|
|
37
38
|
"build:css": "node scripts/build-css.js",
|
|
@@ -43,6 +44,8 @@
|
|
|
43
44
|
"build:kickstart": "npm run build:js && npm run build:info && node scripts/build-kickstart-zip.js",
|
|
44
45
|
"build:miniapps": "node scripts/build-miniapp.js && node scripts/copy-miniapps.js",
|
|
45
46
|
"build:miniapp:garage": "node scripts/build-miniapp.js garage",
|
|
47
|
+
"build:miniapp:address": "node scripts/build-miniapp.js address",
|
|
48
|
+
"watch:miniapps": "node scripts/watch-miniapps.js",
|
|
46
49
|
"generate:bundles": "node scripts/generate-bundles.js",
|
|
47
50
|
"release": "bash scripts/release.sh",
|
|
48
51
|
"release:patch": "npm version patch && npm run release",
|