kempo 4.2.21 → 4.2.23

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
@@ -362,13 +362,45 @@ Refer to the [kempo-css docs](https://github.com/dustinpoissant/kempo-css) and [
362
362
 
363
363
  ## Development
364
364
 
365
- ### Running the Dev Server
365
+ ### Running the framework
366
+
367
+ Kempo is developed against **[kempo-demo](https://github.com/dustinpoissant/kempo-demo)**, a real consumer project that installs kempo, kempo-blog and the rest the way a user would. Running a server inside this repo instead was misleading: paths resolve differently when the framework runs from within `node_modules/kempo` than when it runs from its own directory, so problems appeared here that users never hit, and vice versa.
368
+
369
+ ```bash
370
+ cd ../kempo-demo
371
+ npm install
372
+ npm run link:local # symlink the sibling checkouts into node_modules
373
+ npm start # http://localhost:9876
374
+ ```
375
+
376
+ After editing `src/` here, rebuild so the demo picks it up — `dist/` is what actually gets served:
377
+
378
+ ```bash
379
+ npm run build:deps # from kempo-demo; builds kempo, kempo-server, kempo-ui, kempo-css
380
+ ```
381
+
382
+ To edit the admin portal without rebuilding on every change, point the middleware at the source instead of the build by adding `adminRoot` to the demo's `public/.config.json`:
383
+
384
+ ```json
385
+ {
386
+ "middleware": {
387
+ "custom": ["../node_modules/kempo/middleware/kempo.js"],
388
+ "adminRoot": "node_modules/kempo/src/admin"
389
+ }
390
+ }
391
+ ```
392
+
393
+ ### Running the tests
394
+
395
+ Most of the suite needs nothing, but the extension-lifecycle and HTTP-contract tests drive a real database and skip themselves when none is reachable. To run everything:
366
396
 
367
397
  ```bash
368
- npm run dev
398
+ docker compose up -d # postgres on 5434, separate from kempo-demo's on 5433
399
+ npx drizzle-kit push --force # apply the schema
400
+ npm test
369
401
  ```
370
402
 
371
- This serves `app-public/` at `http://localhost:9876` for testing the consumer-facing boilerplate. The dev server watches for changes and auto-reloads.
403
+ `.env.example` has the matching `DATABASE_URL`. The suite seeds its own groups and permissions, and cleans up the rows it creates.
372
404
 
373
405
  ### Building for Distribution
374
406
 
@@ -1,2 +1,2 @@
1
- import e from"../../../../../server/utils/settings/getPublicSettings.js";export default async t=>{const[s,n]=await e();return s?new Response(JSON.stringify({error:s.msg}),{status:s.code,headers:{"Content-Type":"application/json"}}):new Response(JSON.stringify(n),{headers:{"Content-Type":"application/json"}})};
1
+ import t from"../../../../../server/utils/settings/getPublicSettings.js";export default async(s,e)=>{const[r,o]=await t();if(r)return e.status(r.code).json({error:r.msg});e.json(o)};
2
2
  //# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\kempo\api\settings\public\GET.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"src\\kempo\\api\\settings\\public\\GET.js","names":["getPublicSettings","async","request","error","settings","Response","JSON","stringify","msg","status","code","headers"],"sources":["0"],"sourcesContent":["import getPublicSettings from '../../../../../server/utils/settings/getPublicSettings.js';\r\n\r\nexport default async (request) => {\r\n const [error, settings] = await getPublicSettings();\r\n\r\n if(error){\r\n return new Response(JSON.stringify({ error: error.msg }), {\r\n status: error.code,\r\n headers: { 'Content-Type': 'application/json' }\r\n });\r\n }\r\n\r\n return new Response(JSON.stringify(settings), {\r\n headers: { 'Content-Type': 'application/json' }\r\n });\r\n};\r\n"],"mappings":"OAAOA,MAAuB,2EAEfC,MAAOC,IACpB,MAAOC,EAAOC,SAAkBJ,IAEhC,OAAGG,EACM,IAAIE,SAASC,KAAKC,UAAU,CAAEJ,MAAOA,EAAMK,MAAQ,CACxDC,OAAQN,EAAMO,KACdC,QAAS,CAAE,eAAgB,sBAIxB,IAAIN,SAASC,KAAKC,UAAUH,GAAW,CAC5CO,QAAS,CAAE,eAAgB","ignoreList":[]}
1
+ {"version":3,"file":"src\\kempo\\api\\settings\\public\\GET.js","names":["getPublicSettings","async","request","response","error","settings","status","code","json","msg"],"sources":["0"],"sourcesContent":["import getPublicSettings from '../../../../../server/utils/settings/getPublicSettings.js';\n\nexport default async (request, response) => {\n const [error, settings] = await getPublicSettings();\n\n if(error){\n return response.status(error.code).json({ error: error.msg });\n }\n\n response.json(settings);\n};\n"],"mappings":"OAAOA,MAAuB,2EAEfC,MAAOC,EAASC,KAC7B,MAAOC,EAAOC,SAAkBL,IAEhC,GAAGI,EACD,OAAOD,EAASG,OAAOF,EAAMG,MAAMC,KAAK,CAAEJ,MAAOA,EAAMK,MAGzDN,EAASK,KAAKH","ignoreList":[]}
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "kempo",
3
- "version": "4.2.21",
3
+ "version": "4.2.23",
4
4
  "type": "module",
5
5
  "description": "A fullstack CMS framework for creating websites with user authentication",
6
6
  "scripts": {
7
- "dev": "node scripts/dev.js",
8
7
  "build": "node scripts/build.js",
9
8
  "db:generate": "drizzle-kit generate",
10
9
  "db:migrate": "drizzle-kit migrate",
11
10
  "db:push": "drizzle-kit push",
12
11
  "db:studio": "drizzle-kit studio",
13
12
  "makeAdmin": "node ./scripts/make-admin.js",
14
- "removeAdmin": "node ./scripts/removeAdmin.js",
13
+ "removeAdmin": "node ./scripts/remove-admin.js",
15
14
  "test:email": "node ./scripts/test-email.js",
16
15
  "test": "kempo-test -n",
17
16
  "test:node": "kempo-test -n",
18
- "link:local": "npm install ../kempo-server ../kempo-ui --no-save"
17
+ "link:local": "npm install ../kempo-server ../kempo-ui --no-save",
18
+ "db:reset": "node ./scripts/reset-db.js"
19
19
  },
20
20
  "author": "Dustin Poissant",
21
21
  "license": "MIT",
@@ -46,10 +46,10 @@
46
46
  "bcrypt": "^6.0.0",
47
47
  "dotenv": "^17.2.3",
48
48
  "drizzle-kit": "^0.31.7",
49
- "drizzle-orm": "^0.44.7",
49
+ "drizzle-orm": "^0.45.2",
50
50
  "inquirer": "^12.6.1",
51
51
  "lexical": "^0.42.0",
52
- "monaco-editor": "^0.55.1",
52
+ "monaco-editor": "^0.56.0",
53
53
  "postgres": "^3.4.7",
54
54
  "resend": "^6.5.2"
55
55
  },
@@ -1,24 +1,28 @@
1
1
  import getSession from '../auth/getSession.js';
2
2
  import userHasPermission from './userHasPermission.js';
3
3
 
4
+ /*
5
+ Distinguishes "not signed in" from "signed in but not allowed", because they are different
6
+ answers: 401 means authenticate and try again, 403 means authenticating again will not help.
7
+
8
+ A missing permission name is a caller mistake rather than anything about the request, so it stays
9
+ a 400. Returning [null, false] is reserved for a valid session that simply lacks the permission,
10
+ which callers turn into 403.
11
+ */
4
12
  export default async (token, permissionName) => {
5
- if(!token){
6
- return [{ code: 400, msg: 'Session token is required' }, null];
7
- }
8
-
9
13
  if(!permissionName){
10
14
  return [{ code: 400, msg: 'Permission name is required' }, null];
11
15
  }
12
-
13
- const [error, sessionData] = await getSession({ token });
14
-
15
- if(error){
16
- return [null, false];
16
+
17
+ if(!token){
18
+ return [{ code: 401, msg: 'Authentication required' }, null];
17
19
  }
18
-
19
- if(!sessionData || !sessionData.user){
20
- return [null, false];
20
+
21
+ const [error, sessionData] = await getSession({ token });
22
+
23
+ if(error || !sessionData?.user){
24
+ return [{ code: 401, msg: 'Authentication required' }, null];
21
25
  }
22
-
26
+
23
27
  return await userHasPermission(sessionData.user.id, permissionName);
24
28
  };