domma-cms 0.44.0 → 0.45.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/CLAUDE.md +53 -53
- package/README.md +27 -27
- package/admin/css/admin.css +1 -1
- package/admin/dist/domma/domma-tools.css +3 -3
- package/admin/dist/domma/domma-tools.min.js +3 -3
- package/admin/index.html +2 -2
- package/admin/js/app.js +1 -1
- package/admin/js/lib/card-builder.js +2 -2
- package/admin/js/lib/crud-tutorial.js +1 -1
- package/admin/js/lib/effect-defs.js +1 -1
- package/admin/js/lib/effects-builder.js +1 -1
- package/admin/js/lib/image-editor.js +1 -1
- package/admin/js/lib/markdown-toolbar.js +2 -2
- package/admin/js/lib/project-context.js +1 -1
- package/admin/js/lib/project-quick-create.js +1 -1
- package/admin/js/lib/scribe-composer.js +1 -1
- package/admin/js/lib/server-restart.js +1 -1
- package/admin/js/lib/shortcode-context-menu.js +2 -2
- package/admin/js/lib/simple-editor.js +1 -1
- package/admin/js/lib/themes.js +1 -1
- package/admin/js/lib/timeline-builder.js +1 -1
- package/admin/js/templates/action-editor.html +8 -8
- package/admin/js/templates/api-endpoint-editor.html +7 -7
- package/admin/js/templates/api-endpoints.html +1 -1
- package/admin/js/templates/api-reference.html +1 -1
- package/admin/js/templates/block-editor.html +6 -6
- package/admin/js/templates/collection-editor.html +1 -1
- package/admin/js/templates/component-editor.html +2 -2
- package/admin/js/templates/dashboard/cache.html +3 -3
- package/admin/js/templates/dashboard/journeys.html +3 -3
- package/admin/js/templates/dashboard/kpi-strip.html +3 -3
- package/admin/js/templates/dashboard/top-pages.html +1 -1
- package/admin/js/templates/dashboard/traffic-chart.html +1 -1
- package/admin/js/templates/docs/api-actions.html +1 -1
- package/admin/js/templates/docs/api-collections.html +4 -4
- package/admin/js/templates/docs/api-pages.html +2 -2
- package/admin/js/templates/docs/api-plugins.html +1 -1
- package/admin/js/templates/docs/api-settings.html +2 -2
- package/admin/js/templates/docs/api-users.html +1 -1
- package/admin/js/templates/docs/components-howto.html +4 -4
- package/admin/js/templates/docs/components-reference.html +21 -21
- package/admin/js/templates/docs/components-rules.html +14 -14
- package/admin/js/templates/docs/components-walkthrough.html +13 -13
- package/admin/js/templates/docs/tutorial-crud.html +49 -49
- package/admin/js/templates/docs/tutorial-forms.html +4 -4
- package/admin/js/templates/docs/tutorial-plugin.html +10 -10
- package/admin/js/templates/docs/usage-actions.html +6 -6
- package/admin/js/templates/docs/usage-cta-shortcode.html +9 -9
- package/admin/js/templates/docs/usage-dconfig.html +4 -4
- package/admin/js/templates/docs/usage-navigation.html +1 -1
- package/admin/js/templates/docs/usage-pages.html +1 -1
- package/admin/js/templates/docs/usage-shortcodes.html +24 -24
- package/admin/js/templates/docs/usage-users-roles.html +3 -3
- package/admin/js/templates/docs/usage-views.html +4 -4
- package/admin/js/templates/documentation.html +1 -1
- package/admin/js/templates/effects.html +752 -752
- package/admin/js/templates/form-editor.html +5 -5
- package/admin/js/templates/forms.html +17 -17
- package/admin/js/templates/login.html +5 -5
- package/admin/js/templates/menu-editor.html +10 -10
- package/admin/js/templates/my-profile.html +17 -17
- package/admin/js/templates/navigation.html +11 -11
- package/admin/js/templates/notifications.html +1 -1
- package/admin/js/templates/page-editor.html +4 -4
- package/admin/js/templates/pro-docs.html +14 -14
- package/admin/js/templates/role-editor.html +70 -70
- package/admin/js/templates/roles.html +10 -10
- package/admin/js/templates/settings.html +10 -10
- package/admin/js/templates/tutorials.html +3 -3
- package/admin/js/templates/view-editor.html +15 -15
- package/admin/js/views/action-editor.js +1 -1
- package/admin/js/views/actions-list.js +1 -1
- package/admin/js/views/api-endpoint-editor.js +2 -2
- package/admin/js/views/api-endpoints.js +2 -2
- package/admin/js/views/api-tokens.js +3 -3
- package/admin/js/views/blocks.js +2 -2
- package/admin/js/views/collection-editor.js +1 -1
- package/admin/js/views/collection-entries.js +1 -1
- package/admin/js/views/collections.js +1 -1
- package/admin/js/views/component-editor.js +1 -1
- package/admin/js/views/components.js +4 -4
- package/admin/js/views/dashboard/widgets/cache.js +1 -1
- package/admin/js/views/dashboard/widgets/journeys.js +1 -1
- package/admin/js/views/dashboard/widgets/kpi-strip.js +1 -1
- package/admin/js/views/form-editor.js +7 -7
- package/admin/js/views/form-submissions.js +1 -1
- package/admin/js/views/forms.js +1 -1
- package/admin/js/views/layouts.js +1 -1
- package/admin/js/views/login.js +2 -2
- package/admin/js/views/menu-editor.js +3 -3
- package/admin/js/views/menu-locations.js +1 -1
- package/admin/js/views/menus.js +3 -3
- package/admin/js/views/navigation.js +8 -8
- package/admin/js/views/page-editor.js +40 -40
- package/admin/js/views/pages.js +3 -3
- package/admin/js/views/plugin-code.js +2 -2
- package/admin/js/views/plugins.js +1 -1
- package/admin/js/views/project-settings.js +1 -1
- package/admin/js/views/projects.js +1 -1
- package/admin/js/views/roles.js +1 -1
- package/admin/js/views/user-editor.js +1 -1
- package/admin/js/views/users.js +3 -3
- package/admin/js/views/view-editor.js +1 -1
- package/admin/js/views/view-preview.js +1 -1
- package/admin/js/views/views-list.js +1 -1
- package/bin/cli.js +8 -8
- package/bin/lib/config-merge.js +44 -44
- package/bin/update.js +16 -16
- package/config/plugins.json +1 -1
- package/package.json +2 -2
- package/plugins/_template/admin/views/index.js +1 -1
- package/plugins/_template/config.js +1 -1
- package/plugins/_template/plugin.js +1 -1
- package/plugins/analytics/admin/templates/analytics.html +3 -3
- package/plugins/analytics/admin/views/analytics.js +1 -1
- package/plugins/analytics/config.js +1 -1
- package/plugins/analytics/plugin.js +4 -4
- package/plugins/analytics/plugin.json +1 -1
- package/plugins/analytics/public/inject-body.html +2 -2
- package/plugins/analytics/public/inject-head.html +1 -1
- package/plugins/blog/admin/templates/blog.html +4 -4
- package/plugins/blog/admin/views/blog.js +3 -3
- package/plugins/blog/admin/views/categories.js +2 -2
- package/plugins/blog/admin/views/comments.js +4 -4
- package/plugins/blog/admin/views/post-editor.js +1 -1
- package/plugins/blog/plugin.js +2 -2
- package/plugins/blog/plugin.json +4 -4
- package/plugins/contacts/admin/views/contacts.js +8 -8
- package/plugins/contacts/plugin.js +4 -4
- package/plugins/contacts/plugin.json +1 -1
- package/plugins/invoice/admin/templates/editor.html +6 -6
- package/plugins/invoice/admin/templates/index.html +4 -4
- package/plugins/invoice/admin/views/editor.js +3 -3
- package/plugins/invoice/admin/views/index.js +4 -4
- package/plugins/invoice/admin/views/issuers.js +1 -1
- package/plugins/invoice/admin/views/party-view.js +3 -3
- package/plugins/invoice/admin/views/receivers.js +1 -1
- package/plugins/invoice/config.js +1 -1
- package/plugins/invoice/plugin.js +1 -1
- package/plugins/invoice/plugin.json +4 -4
- package/plugins/notes/admin/views/notes.js +4 -4
- package/plugins/notes/plugin.js +1 -1
- package/plugins/notes/plugin.json +1 -1
- package/plugins/site-search/admin/templates/site-search.html +3 -3
- package/plugins/site-search/admin/views/site-search.js +1 -1
- package/plugins/site-search/config.js +1 -1
- package/plugins/site-search/plugin.js +4 -4
- package/plugins/site-search/plugin.json +1 -1
- package/plugins/surveys/admin/templates/results.html +1 -1
- package/plugins/surveys/admin/templates/survey-editor.html +4 -4
- package/plugins/surveys/admin/views/audience.js +6 -6
- package/plugins/surveys/admin/views/results.js +3 -3
- package/plugins/surveys/admin/views/survey-editor.js +1 -1
- package/plugins/surveys/admin/views/surveys.js +2 -2
- package/plugins/surveys/plugin.js +1 -1
- package/plugins/surveys/plugin.json +4 -4
- package/plugins/theme-switcher/admin/views/theme-switcher.js +1 -1
- package/plugins/theme-switcher/plugin.json +3 -3
- package/plugins/theme-switcher/public/inject-body.html +28 -28
- package/plugins/theme-switcher/public/inject-head.html +1 -1
- package/plugins/todo/plugin.js +1 -1
- package/public/css/forms.css +1 -1
- package/public/js/collection-browser.js +1 -1
- package/public/js/collection-context.js +1 -1
- package/public/js/form-logic-engine.js +1 -1
- package/public/js/forms.js +2 -1
- package/public/js/site.js +1 -1
- package/scripts/build.js +14 -14
- package/scripts/create-plugin.js +2 -2
- package/scripts/fresh.js +2 -2
- package/scripts/gen-instance-secret.js +1 -1
- package/scripts/pro.js +12 -12
- package/scripts/reset.js +2 -2
- package/scripts/setup.js +15 -15
- package/scripts/users.js +5 -5
- package/scripts/verify-assets.mjs +6 -6
- package/server/config.js +1 -1
- package/server/middleware/auth.js +253 -253
- package/server/middleware/managerAuth.js +3 -3
- package/server/routes/api/actions.js +4 -4
- package/server/routes/api/api-endpoints.js +7 -7
- package/server/routes/api/api-tokens.js +5 -5
- package/server/routes/api/auth.js +309 -309
- package/server/routes/api/blocks.js +3 -3
- package/server/routes/api/collections.js +18 -18
- package/server/routes/api/dashboard.js +5 -5
- package/server/routes/api/effects.js +2 -2
- package/server/routes/api/endpoints-public.js +5 -5
- package/server/routes/api/forms.js +47 -47
- package/server/routes/api/menu-locations.js +3 -3
- package/server/routes/api/menus.js +7 -7
- package/server/routes/api/navigation.js +42 -42
- package/server/routes/api/notifications.js +2 -2
- package/server/routes/api/pages.js +14 -2
- package/server/routes/api/plugin-marketplace.js +3 -3
- package/server/routes/api/plugins.js +6 -6
- package/server/routes/api/projects.js +9 -9
- package/server/routes/api/scaffold.js +7 -7
- package/server/routes/api/settings.js +6 -6
- package/server/routes/api/sidebar.js +1 -1
- package/server/routes/api/users.js +5 -5
- package/server/routes/api/versions.js +1 -1
- package/server/routes/api/views.js +1 -1
- package/server/routes/docs-public.js +3 -3
- package/server/routes/public.js +14 -14
- package/server/server.js +34 -16
- package/server/services/actions.js +19 -19
- package/server/services/adapters/FileAdapter.js +2 -2
- package/server/services/adapters/MongoAdapter.js +5 -5
- package/server/services/apiEndpoints.js +15 -15
- package/server/services/apiTokens.js +7 -7
- package/server/services/blocks.js +13 -13
- package/server/services/cache/drivers/MemoryDriver.js +3 -3
- package/server/services/cache/drivers/NoneDriver.js +1 -1
- package/server/services/cache/index.js +5 -5
- package/server/services/collections.js +14 -14
- package/server/services/components.js +9 -9
- package/server/services/connectionManager.js +4 -4
- package/server/services/content.js +25 -2
- package/server/services/docs.js +14 -14
- package/server/services/email.js +167 -167
- package/server/services/filterEngine.js +6 -6
- package/server/services/forms.js +18 -10
- package/server/services/health.js +1 -1
- package/server/services/hooks.js +7 -7
- package/server/services/images.js +4 -4
- package/server/services/managerClient.js +1 -1
- package/server/services/markdown.js +79 -79
- package/server/services/menuRender.js +5 -5
- package/server/services/menus-migration.js +3 -3
- package/server/services/menus.js +31 -31
- package/server/services/permissionRegistry.js +1 -1
- package/server/services/pluginFiles.js +5 -5
- package/server/services/pluginInstaller.js +17 -17
- package/server/services/pluginScaffold.js +1 -1
- package/server/services/plugins.js +17 -17
- package/server/services/presetCollections.js +2 -2
- package/server/services/projects.js +35 -26
- package/server/services/recipes/contact-list.json +1 -1
- package/server/services/recipes/onboarding.json +8 -8
- package/server/services/references.js +8 -8
- package/server/services/renderer.js +9 -9
- package/server/services/roles.js +9 -9
- package/server/services/rowAccess.js +10 -10
- package/server/services/scaffolder.js +30 -30
- package/server/services/sidebar-migration.js +10 -10
- package/server/services/sitemap.js +1 -1
- package/server/services/userProfiles.js +199 -199
- package/server/services/userRoles.js +7 -7
- package/server/services/users.js +302 -302
- package/server/services/versions.js +3 -3
- package/server/services/viewPipeline.js +6 -6
- package/server/services/views.js +11 -11
- package/server/templates/page.html +5 -5
package/scripts/build.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Build script
|
|
2
|
+
* Build script - creates a publishable staging copy in _publish/
|
|
3
3
|
* Browser-facing JS/CSS is minified; server-side code is copied as-is.
|
|
4
4
|
* Run: node scripts/build.js
|
|
5
5
|
*/
|
|
@@ -29,7 +29,7 @@ const COPY_AS_IS = [
|
|
|
29
29
|
];
|
|
30
30
|
|
|
31
31
|
// Glob patterns for browser-facing assets to minify. NOTE: both .js AND .mjs
|
|
32
|
-
// must be listed
|
|
32
|
+
// must be listed - the browser ESM modules served raw (e.g. public/js/*.mjs)
|
|
33
33
|
// use the .mjs extension, and omitting it silently drops those files from the
|
|
34
34
|
// published package (this is the bug that shipped 0.22.1 without menu-decor.mjs).
|
|
35
35
|
const MINIFY_PATTERNS = [
|
|
@@ -177,7 +177,7 @@ async function stampPluginVersions() {
|
|
|
177
177
|
* `/dist/domma/domma.min.js` is served straight from `node_modules/domma-js` (server.js), so a
|
|
178
178
|
* `npm install domma-js@next` silently upgrades one half of the admin and leaves the other on
|
|
179
179
|
* whatever version was last copied across. The tools bundle's own banner says
|
|
180
|
-
* `Requires: domma.min.js`
|
|
180
|
+
* `Requires: domma.min.js` - it is built against a specific core and is not version-independent.
|
|
181
181
|
*
|
|
182
182
|
* That skew is invisible: both files load, no import dangles, nothing throws. It surfaces later as
|
|
183
183
|
* a Theme Roller or Page Roller that misbehaves against a core it was not built for. This is the
|
|
@@ -203,14 +203,14 @@ function verifyDommaToolsVersion(toolsRelPaths) {
|
|
|
203
203
|
// admin/index.html loads both unconditionally, so an absent file is a dead <script>/<link>
|
|
204
204
|
// in the published admin. The copy step already tolerates absence; flag it rather than
|
|
205
205
|
// silently agreeing.
|
|
206
|
-
problems.push(`${rel} is missing
|
|
206
|
+
problems.push(`${rel} is missing - the published admin will reference a file that isn't there`);
|
|
207
207
|
continue;
|
|
208
208
|
}
|
|
209
209
|
// The banner is in the first few lines; no need to read a 230 KB bundle in full.
|
|
210
210
|
const head = readFileSync(src, 'utf8').slice(0, 512);
|
|
211
211
|
const match = head.match(BANNER);
|
|
212
212
|
if (!match) {
|
|
213
|
-
problems.push(`${rel} carries no recognisable Domma Tools banner
|
|
213
|
+
problems.push(`${rel} carries no recognisable Domma Tools banner - cannot confirm its version`);
|
|
214
214
|
found.push({rel, version: null});
|
|
215
215
|
continue;
|
|
216
216
|
}
|
|
@@ -238,7 +238,7 @@ async function build() {
|
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
// Strip prepublishOnly from _publish/package.json
|
|
241
|
+
// Strip prepublishOnly from _publish/package.json - the guard is for the
|
|
242
242
|
// source tree only; running npm publish inside _publish/ must succeed.
|
|
243
243
|
const pkgPath = join(OUT, 'package.json');
|
|
244
244
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
@@ -247,7 +247,7 @@ async function build() {
|
|
|
247
247
|
|
|
248
248
|
// Scrub this machine's local config out of the staged copy. config/site.json
|
|
249
249
|
// is a working file on a development install, so it carries whatever SMTP
|
|
250
|
-
// host and site URL were last set here
|
|
250
|
+
// host and site URL were last set here - published releases up to 0.43.1 put
|
|
251
251
|
// a LAN address on the public registry and handed every manual installer a
|
|
252
252
|
// mail host that does not exist for them. Same reasoning as the analytics
|
|
253
253
|
// counters in .npmignore: runtime state must not ride along in the tarball.
|
|
@@ -265,7 +265,7 @@ async function build() {
|
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
// .bak files are migration leftovers from whichever machine built the
|
|
268
|
-
// release
|
|
268
|
+
// release - never something an installer should receive.
|
|
269
269
|
for (const rel of ['config/navigation.json.bak', 'config/connections.json.bak']) {
|
|
270
270
|
const bak = join(OUT, rel);
|
|
271
271
|
if (existsSync(bak)) rmSync(bak, {force: true});
|
|
@@ -293,14 +293,14 @@ async function build() {
|
|
|
293
293
|
'admin/dist/domma/domma-tools.min.js',
|
|
294
294
|
];
|
|
295
295
|
|
|
296
|
-
// Version-skew gate
|
|
296
|
+
// Version-skew gate - see verifyDommaToolsVersion() for why this cannot be left to npm.
|
|
297
297
|
const toolsCheck = verifyDommaToolsVersion(dommaTools);
|
|
298
298
|
if (toolsCheck.ok) {
|
|
299
|
-
console.log(`Domma Tools v${toolsCheck.installed}
|
|
299
|
+
console.log(`Domma Tools v${toolsCheck.installed} - matches installed domma-js`);
|
|
300
300
|
} else {
|
|
301
301
|
for (const problem of toolsCheck.problems) console.error(` ${problem}`);
|
|
302
302
|
throw new Error(
|
|
303
|
-
`Domma Tools is out of step with domma-js v${toolsCheck.installed}
|
|
303
|
+
`Domma Tools is out of step with domma-js v${toolsCheck.installed} - copy `
|
|
304
304
|
+ `domma-tools.min.js and domma-tools.css from that version's build into admin/dist/domma/, `
|
|
305
305
|
+ `then rebuild`,
|
|
306
306
|
);
|
|
@@ -338,16 +338,16 @@ async function build() {
|
|
|
338
338
|
|
|
339
339
|
await stampPluginVersions();
|
|
340
340
|
|
|
341
|
-
console.log(`Built into _publish/
|
|
341
|
+
console.log(`Built into _publish/ - JS: ${jsCount} minified, CSS: ${cssCount} minified, ${totalCopied} entries copied`);
|
|
342
342
|
|
|
343
|
-
// Integrity gate
|
|
343
|
+
// Integrity gate - fail the build (and therefore `make pack` / `make
|
|
344
344
|
// release-npm`) if the staged set ships any ESM import pointing at a file
|
|
345
345
|
// that isn't there. This is what stops a "shipped code that imports a missing
|
|
346
346
|
// file" release (the 0.22.1 menu-decor.mjs incident) from ever publishing.
|
|
347
347
|
const integrity = await verifyAssetImports({projectRoot: OUT});
|
|
348
348
|
console.log(formatReport(integrity, '_publish/'));
|
|
349
349
|
if (!integrity.ok) {
|
|
350
|
-
throw new Error(`asset integrity check failed
|
|
350
|
+
throw new Error(`asset integrity check failed - ${integrity.missing.length} dangling import(s); refusing to package a broken release`);
|
|
351
351
|
}
|
|
352
352
|
}
|
|
353
353
|
|
package/scripts/create-plugin.js
CHANGED
|
@@ -69,12 +69,12 @@ const templateDir = join(ROOT, 'plugins', '_template');
|
|
|
69
69
|
const targetDir = join(ROOT, 'plugins', slug);
|
|
70
70
|
|
|
71
71
|
if (!existsSync(templateDir)) {
|
|
72
|
-
console.error(`Template not found at plugins/_template/
|
|
72
|
+
console.error(`Template not found at plugins/_template/ - cannot scaffold.`);
|
|
73
73
|
process.exit(1);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
if (existsSync(targetDir)) {
|
|
77
|
-
console.error(`plugins/${slug}/ already exists
|
|
77
|
+
console.error(`plugins/${slug}/ already exists - choose a different name.`);
|
|
78
78
|
process.exit(1);
|
|
79
79
|
}
|
|
80
80
|
|
package/scripts/fresh.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Domma CMS
|
|
3
|
+
* Domma CMS - Fresh Install
|
|
4
4
|
* Chains: reset → setup
|
|
5
5
|
* Gives you a clean CMS install ready to use.
|
|
6
6
|
* Run: npm run fresh
|
|
@@ -24,7 +24,7 @@ function run(script) {
|
|
|
24
24
|
|
|
25
25
|
console.log('');
|
|
26
26
|
console.log(' ╔══════════════════════════════════════╗');
|
|
27
|
-
console.log(' ║ Domma CMS
|
|
27
|
+
console.log(' ║ Domma CMS - Fresh Install ║');
|
|
28
28
|
console.log(' ║ reset → setup ║');
|
|
29
29
|
console.log(' ╚══════════════════════════════════════╝');
|
|
30
30
|
console.log('');
|
|
@@ -36,7 +36,7 @@ async function writeEnv(env) {
|
|
|
36
36
|
|
|
37
37
|
const env = await readEnv();
|
|
38
38
|
if (env.INSTANCE_SECRET && env.INSTANCE_SECRET.length >= 32) {
|
|
39
|
-
console.log(' ✓ INSTANCE_SECRET already set
|
|
39
|
+
console.log(' ✓ INSTANCE_SECRET already set - skipping.');
|
|
40
40
|
process.exit(0);
|
|
41
41
|
}
|
|
42
42
|
|
package/scripts/pro.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Domma CMS
|
|
3
|
+
* Domma CMS - Pro Mode Toggle
|
|
4
4
|
*
|
|
5
5
|
* Enables or disables MongoDB storage adapter (Pro feature).
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
|
-
* npm run pro enable
|
|
9
|
-
* npm run pro disable
|
|
10
|
-
* npm run pro status
|
|
8
|
+
* npm run pro enable - copy connections.json.example, prompt for URI/DB, install mongodb
|
|
9
|
+
* npm run pro disable - back up connections.json, optionally uninstall mongodb
|
|
10
|
+
* npm run pro status - report current mode and connection summary
|
|
11
11
|
*/
|
|
12
12
|
import {createInterface} from 'node:readline/promises';
|
|
13
13
|
import {copyFile, readFile, rename, writeFile} from 'node:fs/promises';
|
|
@@ -75,7 +75,7 @@ async function cmdStatus() {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
console.log(' Mode : Pro (MongoDB)');
|
|
78
|
-
console.log(` mongodb : ${mongoInstalled ? 'installed ✓' : 'NOT installed
|
|
78
|
+
console.log(` mongodb : ${mongoInstalled ? 'installed ✓' : 'NOT installed - run: npm install mongodb'}`);
|
|
79
79
|
|
|
80
80
|
try {
|
|
81
81
|
const raw = await readFile(CONNECTIONS_FILE, 'utf8');
|
|
@@ -95,7 +95,7 @@ async function cmdStatus() {
|
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
} catch (err) {
|
|
98
|
-
console.log(` Warning : Could not parse connections.json
|
|
98
|
+
console.log(` Warning : Could not parse connections.json - ${err.message}`);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
console.log('');
|
|
@@ -105,7 +105,7 @@ async function cmdEnable() {
|
|
|
105
105
|
section('Enable Pro Mode');
|
|
106
106
|
|
|
107
107
|
if (existsSync(CONNECTIONS_FILE)) {
|
|
108
|
-
console.log(' ✓ config/connections.json already exists
|
|
108
|
+
console.log(' ✓ config/connections.json already exists - Pro mode is already enabled.');
|
|
109
109
|
console.log(' Run "npm run pro status" to review the current configuration.\n');
|
|
110
110
|
return;
|
|
111
111
|
}
|
|
@@ -140,7 +140,7 @@ async function cmdEnable() {
|
|
|
140
140
|
await writeFile(CONNECTIONS_FILE, JSON.stringify(cfg, null, 4) + '\n', 'utf8');
|
|
141
141
|
|
|
142
142
|
console.log('\n ✓ config/connections.json updated with your connection details.');
|
|
143
|
-
console.log(' (This file is gitignored
|
|
143
|
+
console.log(' (This file is gitignored - credentials stay local.)\n');
|
|
144
144
|
|
|
145
145
|
// Install mongodb package
|
|
146
146
|
console.log(' Installing mongodb package…');
|
|
@@ -168,13 +168,13 @@ async function cmdDisable() {
|
|
|
168
168
|
section('Disable Pro Mode');
|
|
169
169
|
|
|
170
170
|
if (!existsSync(CONNECTIONS_FILE)) {
|
|
171
|
-
console.log(' Already in file-based mode
|
|
171
|
+
console.log(' Already in file-based mode - nothing to disable.\n');
|
|
172
172
|
return;
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
// Back up connections.json
|
|
176
176
|
if (existsSync(CONNECTIONS_BAK)) {
|
|
177
|
-
console.log(' Note: connections.json.bak already exists
|
|
177
|
+
console.log(' Note: connections.json.bak already exists - it will be overwritten.');
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
await rename(CONNECTIONS_FILE, CONNECTIONS_BAK);
|
|
@@ -195,7 +195,7 @@ async function cmdDisable() {
|
|
|
195
195
|
console.log('\n Warning: npm uninstall mongodb failed. Remove it manually if needed.');
|
|
196
196
|
}
|
|
197
197
|
} else {
|
|
198
|
-
console.log(' Skipping uninstall
|
|
198
|
+
console.log(' Skipping uninstall - mongodb package remains (unused).');
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
console.log('');
|
|
@@ -209,7 +209,7 @@ async function cmdDisable() {
|
|
|
209
209
|
function printUsage() {
|
|
210
210
|
console.log('');
|
|
211
211
|
console.log(' ┌─────────────────────────────────────┐');
|
|
212
|
-
console.log(' │ Domma CMS
|
|
212
|
+
console.log(' │ Domma CMS - Pro Mode Toggle │');
|
|
213
213
|
console.log(' └─────────────────────────────────────┘');
|
|
214
214
|
console.log('');
|
|
215
215
|
console.log(' Usage: npm run pro <command>');
|
package/scripts/reset.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Domma CMS
|
|
3
|
+
* Domma CMS - Factory Reset
|
|
4
4
|
* Wipes all content, users, and resets config to defaults.
|
|
5
5
|
* Run: npm run reset
|
|
6
6
|
*/
|
|
@@ -74,7 +74,7 @@ async function resetEnv() {
|
|
|
74
74
|
|
|
75
75
|
console.log('');
|
|
76
76
|
console.log(' ┌──────────────────────────────────┐');
|
|
77
|
-
console.log(' │ Domma CMS
|
|
77
|
+
console.log(' │ Domma CMS - Factory Reset │');
|
|
78
78
|
console.log(' └──────────────────────────────────┘');
|
|
79
79
|
console.log('');
|
|
80
80
|
console.log(' This will permanently delete:');
|
package/scripts/setup.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Domma CMS
|
|
3
|
+
* Domma CMS - Interactive Setup Wizard
|
|
4
4
|
*
|
|
5
5
|
* Run once after cloning: npm run setup
|
|
6
|
-
* Operates directly on files
|
|
6
|
+
* Operates directly on files - does NOT import the Fastify server.
|
|
7
7
|
*
|
|
8
8
|
* Steps:
|
|
9
9
|
* 1. Generate JWT_SECRET (skips if already set)
|
|
@@ -134,7 +134,7 @@ console.log(' │ Domma CMS Setup Wizard │');
|
|
|
134
134
|
console.log(' └────────────────────────────┘');
|
|
135
135
|
|
|
136
136
|
// ---------------------------------------------------------------------------
|
|
137
|
-
// Step 1
|
|
137
|
+
// Step 1 - JWT Secret
|
|
138
138
|
// ---------------------------------------------------------------------------
|
|
139
139
|
section('1. JWT Secret');
|
|
140
140
|
|
|
@@ -145,7 +145,7 @@ const isPlaceholder = !existingSecret
|
|
|
145
145
|
|| existingSecret.length < 32;
|
|
146
146
|
|
|
147
147
|
if (!isPlaceholder) {
|
|
148
|
-
console.log(' ✓ JWT_SECRET already configured
|
|
148
|
+
console.log(' ✓ JWT_SECRET already configured - skipping.');
|
|
149
149
|
} else {
|
|
150
150
|
const secret = randomBytes(48).toString('hex');
|
|
151
151
|
env.JWT_SECRET = secret;
|
|
@@ -155,18 +155,18 @@ if (!isPlaceholder) {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
// ---------------------------------------------------------------------------
|
|
158
|
-
// Step 2
|
|
158
|
+
// Step 2 - Instance Secret
|
|
159
159
|
// ---------------------------------------------------------------------------
|
|
160
160
|
section('2. Instance Secret');
|
|
161
161
|
|
|
162
|
-
// Distinct name from step 1's existingSecret
|
|
162
|
+
// Distinct name from step 1's existingSecret - both are module-scope consts,
|
|
163
163
|
// so reusing the identifier made the whole file a SyntaxError and setup could
|
|
164
164
|
// not run at all.
|
|
165
165
|
const existingInstanceSecret = env.INSTANCE_SECRET ?? '';
|
|
166
166
|
const isInstanceSecretSet = existingInstanceSecret && existingInstanceSecret.length >= 32;
|
|
167
167
|
|
|
168
168
|
if (isInstanceSecretSet) {
|
|
169
|
-
console.log(' ✓ INSTANCE_SECRET already configured
|
|
169
|
+
console.log(' ✓ INSTANCE_SECRET already configured - skipping.');
|
|
170
170
|
} else {
|
|
171
171
|
const secret = randomBytes(32).toString('hex');
|
|
172
172
|
env.INSTANCE_SECRET = secret;
|
|
@@ -175,13 +175,13 @@ if (isInstanceSecretSet) {
|
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
// ---------------------------------------------------------------------------
|
|
178
|
-
// Step 3
|
|
178
|
+
// Step 3 - Admin Account
|
|
179
179
|
// ---------------------------------------------------------------------------
|
|
180
180
|
section('3. Admin Account');
|
|
181
181
|
|
|
182
182
|
const userCount = await countUsers();
|
|
183
183
|
if (userCount > 0) {
|
|
184
|
-
console.log(` ✓ ${userCount} user(s) already exist
|
|
184
|
+
console.log(` ✓ ${userCount} user(s) already exist - skipping admin creation.`);
|
|
185
185
|
} else {
|
|
186
186
|
console.log(' No users found. Create the first admin account.\n');
|
|
187
187
|
|
|
@@ -228,7 +228,7 @@ if (userCount > 0) {
|
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
// ---------------------------------------------------------------------------
|
|
231
|
-
// Step 4
|
|
231
|
+
// Step 4 - Site Identity
|
|
232
232
|
// ---------------------------------------------------------------------------
|
|
233
233
|
section('4. Site Identity');
|
|
234
234
|
|
|
@@ -256,7 +256,7 @@ section('4. Site Identity');
|
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
// ---------------------------------------------------------------------------
|
|
259
|
-
// Step 5
|
|
259
|
+
// Step 5 - Theme
|
|
260
260
|
// ---------------------------------------------------------------------------
|
|
261
261
|
section('5. Theme');
|
|
262
262
|
|
|
@@ -268,7 +268,7 @@ THEMES.forEach((t, i) => {
|
|
|
268
268
|
|
|
269
269
|
{
|
|
270
270
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
271
|
-
const choice = (await rl.question(`\n Choice (1
|
|
271
|
+
const choice = (await rl.question(`\n Choice (1-${THEMES.length}, Enter = charcoal-dark): `)).trim();
|
|
272
272
|
rl.close();
|
|
273
273
|
|
|
274
274
|
const idx = parseInt(choice, 10) - 1;
|
|
@@ -282,7 +282,7 @@ THEMES.forEach((t, i) => {
|
|
|
282
282
|
}
|
|
283
283
|
|
|
284
284
|
// ---------------------------------------------------------------------------
|
|
285
|
-
// Step 6
|
|
285
|
+
// Step 6 - Port
|
|
286
286
|
// ---------------------------------------------------------------------------
|
|
287
287
|
section('6. Server Port');
|
|
288
288
|
|
|
@@ -305,7 +305,7 @@ section('6. Server Port');
|
|
|
305
305
|
// Git hooks
|
|
306
306
|
// ---------------------------------------------------------------------------
|
|
307
307
|
// The hooks in .githooks/ are committed, but git will not run them until this
|
|
308
|
-
// clone points at that directory
|
|
308
|
+
// clone points at that directory - core.hooksPath is local config, so it cannot
|
|
309
309
|
// travel with the repository. Every clone that misses this step silently loses
|
|
310
310
|
// both hooks: the commit-msg trailer strip and the pre-commit minified-source
|
|
311
311
|
// guard. Enable it here so a fresh clone is protected by default.
|
|
@@ -315,7 +315,7 @@ try {
|
|
|
315
315
|
execSync('git config core.hooksPath .githooks', {stdio: 'ignore'});
|
|
316
316
|
console.log(' ✓ Git hooks enabled (core.hooksPath = .githooks)');
|
|
317
317
|
} catch {
|
|
318
|
-
// Not a git checkout
|
|
318
|
+
// Not a git checkout - an npm install of the published package, most
|
|
319
319
|
// likely. Nothing to enable, and nothing worth warning about.
|
|
320
320
|
}
|
|
321
321
|
|
package/scripts/users.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Domma CMS
|
|
3
|
+
* Domma CMS - User Management CLI
|
|
4
4
|
*
|
|
5
5
|
* Run from the project root:
|
|
6
6
|
* npm run users -- <command> [args] [options]
|
|
@@ -105,7 +105,7 @@ async function cmdList() {
|
|
|
105
105
|
name: u.name,
|
|
106
106
|
role: u.role,
|
|
107
107
|
active: u.isActive ? 'yes' : 'no',
|
|
108
|
-
last: u.lastLogin ? u.lastLogin.slice(0, 16).replace('T', ' ') : '
|
|
108
|
+
last: u.lastLogin ? u.lastLogin.slice(0, 16).replace('T', ' ') : '-'
|
|
109
109
|
}));
|
|
110
110
|
printTable(['email', 'name', 'role', 'active', 'last'], rows);
|
|
111
111
|
}
|
|
@@ -203,7 +203,7 @@ async function resolvePassword({confirm: requireConfirm = false} = {}) {
|
|
|
203
203
|
if (flags.has('generate')) {
|
|
204
204
|
const pw = generatePassword(20);
|
|
205
205
|
console.log(`\n Generated password: ${pw}`);
|
|
206
|
-
console.log(' (this is the only time it will be shown
|
|
206
|
+
console.log(' (this is the only time it will be shown - copy it now)\n');
|
|
207
207
|
return pw;
|
|
208
208
|
}
|
|
209
209
|
|
|
@@ -221,7 +221,7 @@ function generatePassword(bytes) {
|
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
/**
|
|
224
|
-
* Prompt with masked echo
|
|
224
|
+
* Prompt with masked echo - reads raw TTY input so keystrokes don't appear on screen.
|
|
225
225
|
* Falls back to a plain (visible) readline when stdin isn't a TTY (e.g. piped input).
|
|
226
226
|
*
|
|
227
227
|
* @param {string} prompt
|
|
@@ -286,7 +286,7 @@ function printTable(headers, rows) {
|
|
|
286
286
|
|
|
287
287
|
function printHelp() {
|
|
288
288
|
console.log(`
|
|
289
|
-
Domma CMS
|
|
289
|
+
Domma CMS - User Management CLI
|
|
290
290
|
|
|
291
291
|
Usage:
|
|
292
292
|
npm run users -- <command> [args] [options]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Asset Import Verifier
|
|
2
|
+
* Asset Import Verifier - build/publish gate
|
|
3
3
|
*
|
|
4
4
|
* Statically resolves every local ESM import under the browser-facing code
|
|
5
5
|
* (admin/ + public/) against the files that actually exist, and fails if any
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* import natively (no bundler). If a release ships consumer code that imports a
|
|
12
12
|
* new module but forgets to include the module file (as 0.22.1 did with
|
|
13
13
|
* /public/js/menu-decor.mjs), every page 404s on the import and the whole site
|
|
14
|
-
* breaks
|
|
14
|
+
* breaks - with no signal but a browser console error, and it cascades to every
|
|
15
15
|
* downstream project that copies these dirs on update. A bundler would catch
|
|
16
16
|
* this at build time; because we don't bundle, this gate stands in for that.
|
|
17
17
|
*
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
* Exits 1 (with a report) on any dangling import, 0 otherwise. Wired into
|
|
22
22
|
* scripts/build.js so `make pack` / `make release-npm` cannot ship a broken set.
|
|
23
23
|
*
|
|
24
|
-
* Scope (deliberately conservative
|
|
25
|
-
* only STATIC, LOCAL specifiers with an explicit extension are checked
|
|
24
|
+
* Scope (deliberately conservative - zero false positives is the whole point):
|
|
25
|
+
* only STATIC, LOCAL specifiers with an explicit extension are checked - the
|
|
26
26
|
* only kind this codebase emits. Bare (npm) specifiers, URLs, dynamic/template
|
|
27
27
|
* specifiers, commented-out imports, and extension-less paths are all ignored.
|
|
28
28
|
*/
|
|
@@ -160,12 +160,12 @@ export async function verifyAssetImports({ projectRoot, roots = ['admin', 'publi
|
|
|
160
160
|
|
|
161
161
|
export function formatReport(result, label) {
|
|
162
162
|
if (result.ok) {
|
|
163
|
-
return `[verify-assets] OK
|
|
163
|
+
return `[verify-assets] OK - ${result.scanned} files scanned, all local imports resolve (${label}).`;
|
|
164
164
|
}
|
|
165
165
|
const lines = [
|
|
166
166
|
'',
|
|
167
167
|
' ╔════════════════════════════════════════════════════════════════╗',
|
|
168
|
-
' ║ ASSET INTEGRITY FAILURE
|
|
168
|
+
' ║ ASSET INTEGRITY FAILURE - dangling front-end imports detected ║',
|
|
169
169
|
' ╚════════════════════════════════════════════════════════════════╝',
|
|
170
170
|
` Context: ${label}`,
|
|
171
171
|
` ${result.missing.length} import(s) reference files that do not exist:`,
|
package/server/config.js
CHANGED
|
@@ -43,7 +43,7 @@ export function saveConfig(name, data) {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
|
-
* Structural config
|
|
46
|
+
* Structural config - loaded once at startup.
|
|
47
47
|
* Do not use for admin-editable settings (site, navigation, presets, plugins).
|
|
48
48
|
*/
|
|
49
49
|
const serverConfig = loadJson('server');
|