kempo 4.2.35 → 4.2.37

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/README.md CHANGED
@@ -416,6 +416,8 @@ npm test
416
416
 
417
417
  `.env.example` has the matching `DATABASE_URL`. The suite seeds its own groups and permissions, and cleans up the rows it creates.
418
418
 
419
+ `npm test` (`kempo-test -n`) only runs the Node-side suite. Admin components that need a real DOM run in an actual browser via `npm run test:browser` — no database or running server required, since it exercises the real component/SDK code with only `window.fetch` intercepted for canned responses. It temporarily junctions `/kempo-ui`, `/kempo-css` and `/kempo` onto `node_modules`/`dist` at the project root so the admin bundle's absolute imports resolve against kempo-testing-framework's static test server, and removes them afterward regardless of pass/fail.
420
+
419
421
  ### Building for Distribution
420
422
 
421
423
  When preparing the framework for npm release, minify and optimize the source code:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kempo",
3
- "version": "4.2.35",
3
+ "version": "4.2.37",
4
4
  "type": "module",
5
5
  "description": "A fullstack CMS framework for creating websites with user authentication",
6
6
  "scripts": {
@@ -14,6 +14,7 @@
14
14
  "test:email": "node ./scripts/test-email.js",
15
15
  "test": "kempo-test -n",
16
16
  "test:node": "kempo-test -n",
17
+ "test:browser": "node scripts/run-browser-tests.js",
17
18
  "link:local": "npm install ../kempo-server ../kempo-ui --no-save",
18
19
  "db:reset": "node ./scripts/reset-db.js"
19
20
  },
package/server/sdk.js CHANGED
@@ -82,6 +82,7 @@ export { default as userHasSomePermissions } from './utils/permissions/userHasSo
82
82
  Settings
83
83
  */
84
84
 
85
+ export { default as declaredValue } from './utils/settings/declaredValue.js';
85
86
  export { default as deleteSetting } from './utils/settings/deleteSetting.js';
86
87
  export { default as getPublicSettings } from './utils/settings/getPublicSettings.js';
87
88
  export { default as getSetting } from './utils/settings/getSetting.js';
@@ -9,6 +9,7 @@ import { randomUUID } from 'crypto';
9
9
  import triggerHook, { clearHandlerCache } from '../hooks/triggerHook.js';
10
10
  import createHook from '../hooks/createHook.js';
11
11
  import setSetting from '../settings/setSetting.js';
12
+ import declaredValue from '../settings/declaredValue.js';
12
13
  import createTablesFromSchema from './createTablesFromSchema.js';
13
14
  import { invalidateScopeCache } from './scopeCache.js';
14
15
  import { getUnmetDependencies } from './dependencies.js';
@@ -91,7 +92,7 @@ export default async ({ name }) => {
91
92
  Create declarative settings
92
93
  */
93
94
  for(const { name: settingName, value, type, description } of kempoConfig.settings || []){
94
- await setSetting(name, settingName, value, type || null, false, description || null);
95
+ await setSetting(name, settingName, declaredValue(value, type), type || null, false, description || null);
95
96
  }
96
97
 
97
98
  /*
@@ -9,6 +9,7 @@ import { execSync } from 'child_process';
9
9
  import triggerHook, { clearHandlerCache } from '../hooks/triggerHook.js';
10
10
  import createHook from '../hooks/createHook.js';
11
11
  import setSetting from '../settings/setSetting.js';
12
+ import declaredValue from '../settings/declaredValue.js';
12
13
  import createTablesFromSchema from './createTablesFromSchema.js';
13
14
 
14
15
  const requireFromProject = createRequire(join(process.cwd(), 'package.json'));
@@ -97,7 +98,7 @@ export default async ({ name, version = 'latest' }) => {
97
98
  const oldSettingNames = new Set((oldKempo.settings || []).map(s => s.name));
98
99
  for(const { name: settingName, value, type, description } of newKempo.settings || []){
99
100
  if(!oldSettingNames.has(settingName)){
100
- await setSetting(name, settingName, value, type || null, false, description || null);
101
+ await setSetting(name, settingName, declaredValue(value, type), type || null, false, description || null);
101
102
  }
102
103
  }
103
104
 
@@ -0,0 +1,28 @@
1
+ /*
2
+ A declared setting's default, turned into the value `setSetting` expects.
3
+
4
+ kempo-config.json declares defaults as strings — `"value": "10"` for a number, `"value": "true"`
5
+ for a boolean — and that is what the extension docs tell authors to write. `setSetting` takes the
6
+ *real* value and serialises it according to the type it is given, and for every scalar type the
7
+ two happen to agree: `serializeValue('10', 'number')` is `String('10')`, which is `'10'`.
8
+
9
+ For `json` they do not. A declared `"value": "[{\"label\":\"sm\"}]"` is a string, and
10
+ `serializeValue(aString, 'json')` is `JSON.stringify(aString)` — the array gets encoded a second
11
+ time, and reading the setting back returns the JSON *text* rather than the array. Nothing errors;
12
+ the extension simply behaves as though the setting were empty, which is a very quiet way to break.
13
+
14
+ So a json default is parsed here before it is stored. A value that is already a real array or
15
+ object (perfectly legal in kempo-config.json, and what you get if you write the JSON inline) is
16
+ passed through untouched, and a string that is not valid JSON is left as-is rather than thrown —
17
+ a malformed default is the author's problem to see in their own settings screen, not a reason to
18
+ fail the whole install.
19
+ */
20
+ export default (value, type) => {
21
+ if(type !== 'json' || typeof value !== 'string') return value;
22
+
23
+ try {
24
+ return JSON.parse(value);
25
+ } catch {
26
+ return value;
27
+ }
28
+ };