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.
Files changed (38) hide show
  1. package/bin/domma-cli.js +217 -15
  2. package/package.json +4 -1
  3. package/public/dist/bundles/domma-complete.css +465 -14
  4. package/public/dist/bundles/domma-data-focused.css +465 -14
  5. package/public/dist/bundles/domma-essentials.css +465 -14
  6. package/public/dist/bundles/domma-full.css +465 -14
  7. package/public/dist/bundles/domma-grayve.css +465 -14
  8. package/public/dist/bundles/domma-minimal.css +459 -8
  9. package/public/dist/domma-syntax.min.js +3 -3
  10. package/public/dist/domma.css +454 -3
  11. package/public/dist/domma.esm.js +4 -4
  12. package/public/dist/domma.min.js +4 -4
  13. package/public/dist/elements.css +3 -3
  14. package/public/dist/grid.css +3 -3
  15. package/public/dist/syntax.css +3 -3
  16. package/public/dist/themes/domma-themes.css +3 -3
  17. package/templates/kickstart/frontend/pages/index.html +1 -1
  18. package/templates/kickstart-spa/.claude/settings.json +68 -0
  19. package/templates/kickstart-spa/.claude/snippets.md +683 -0
  20. package/templates/kickstart-spa/backend/README.md +160 -0
  21. package/templates/kickstart-spa/blueprints/README.md +361 -0
  22. package/templates/kickstart-spa/blueprints/common/contact.js +135 -0
  23. package/templates/kickstart-spa/blueprints/common/settings.js +194 -0
  24. package/templates/kickstart-spa/blueprints/common/user.js +123 -0
  25. package/templates/kickstart-spa/blueprints/crud/product.js +346 -0
  26. package/templates/kickstart-spa/blueprints/crud/task.js +419 -0
  27. package/templates/kickstart-spa/blueprints/forms/login.js +292 -0
  28. package/templates/kickstart-spa/blueprints/forms/registration.js +254 -0
  29. package/templates/kickstart-spa/domma.config.json +86 -0
  30. package/templates/kickstart-spa/frontend/css/custom.css +72 -0
  31. package/templates/kickstart-spa/frontend/index.html +40 -0
  32. package/templates/kickstart-spa/frontend/js/app.js +146 -0
  33. package/templates/kickstart-spa/frontend/js/views/404.js +35 -0
  34. package/templates/kickstart-spa/frontend/js/views/about.js +69 -0
  35. package/templates/kickstart-spa/frontend/js/views/contact.js +96 -0
  36. package/templates/kickstart-spa/frontend/js/views/home.js +90 -0
  37. package/templates/kickstart-spa/frontend/js/views/index.js +15 -0
  38. 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 templatesDir = join(__dirname, '..', 'templates', 'kickstart');
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
- console.log(` 1. Open frontend/pages/index.html in your browser`);
177
- console.log(` 2. Edit domma.config.json to customise`);
178
- console.log(` 3. Add new pages: npx domma-js add page <name>`);
179
- console.log(` 4. Read the docs: https://github.com/dcbw-it/domma\n`);
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: npx domma-js add page <name>');
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
- npx domma-js add page <path> Add a new page at specified path
472
- npx domma-js setup-ai Add AI assistance files to existing project
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
- npx domma-js # Interactive project setup
481
- npx domma-js --quick # Quick project setup with defaults
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 at different paths:
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
- npx domma-js add page src/views/settings --quick # Quick mode (non-interactive)
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.10.2",
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",