@flowselections/core 1.0.24 → 1.0.26

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
@@ -4,9 +4,9 @@ Fundament-module: authenticatie, shell-layout (sidebar/header), instellingen en
4
4
  gedeelde UI-componenten. Elke module heeft core als `peerDependency`; de shell
5
5
  bepaalt welke core-versie draait.
6
6
 
7
- ## Gebruik 1.0.23 niet
7
+ ## Gebruik 1.0.23 t/m 1.0.25 niet
8
8
 
9
- **Core 1.0.23 breekt de clientbuild van elke shell** (`"Readable"/"AsyncLocalStorage" is not exported by "__vite-browser-external"`): de handoverpagina trok via een serverfunctie servercode in de clientbundel. Gebruik **1.0.24 of hoger**.
9
+ **Core 1.0.23 tot en met 1.0.25 breken de clientbuild van shells** (`"Readable"/"AsyncLocalStorage" is not exported by "__vite-browser-external"`): servercode van `@tanstack/start-server-core` (`node:async_hooks`, `node:stream`) lekte naar de clientbundel. In 1.0.23 liep dat via de handoverpagina, in 1.0.24 en 1.0.25 via `./server`, dat `@tanstack/react-start/server` statisch importeerde — elke shell met een module die `./server` her-exporteert (zoals de admin-add-on) faalde. Gebruik **1.0.26 of hoger**.
10
10
 
11
11
  Vanaf 1.0.24 wisselt `HandoverPage` de code in via een server-route in de shell. Het dashboard genereert daarvoor `src/routes/api/public/auth/handover.ts`:
12
12
 
@@ -21,7 +21,7 @@ export const Route = createFileRoute("/api/public/auth/handover")({
21
21
 
22
22
  Ander pad? Geef `exchangePath` mee aan `HandoverPage` of `handoverRoute`. Zonder dit bestand mislukt alleen de handover (neutrale foutmelding); `/login` blijft werken.
23
23
 
24
- `build:pkg` controleert met `scripts/check-client-graph.mjs` dat de hoofdbarrel en `./routes` geen servercode importeren. `npm run verify:consumer` bouwt een minimale consumer-app tegen het gepakte pakket.
24
+ `build:pkg` controleert met `scripts/check-client-graph.mjs` dat de hoofdbarrel, `./routes` én `./server` geen letterlijke serverimport bevatten (statisch of `import("…")`). `npm run verify:consumer` bouwt twee minimale consumer-apps tegen het gepakte pakket: één zonder en één met `./server` in de clientgraaf (het geval van de admin-add-on).
25
25
 
26
26
  ## Modulecontract
27
27
 
@@ -11,8 +11,13 @@ export type PermissionLevel = "none" | "view" | "edit";
11
11
  *
12
12
  * - Ontbreekt de RPC (add-on niet geïnstalleerd) → toegestaan (default-allow).
13
13
  * - Geen geldige sessie → 401. Onvoldoende rechten → 403.
14
+ *
15
+ * `request` is optioneel: geef `getRequest()` mee (uit de code van je eigen
16
+ * shell, die door de Start-compiler wél getransformeerd wordt) als jouw runtime
17
+ * het actuele verzoek niet zelf blootgeeft. Aan het antwoord verandert niets:
18
+ * het token wordt hoe dan ook bij Supabase Auth gevalideerd.
14
19
  */
15
- export declare function requireModulePermission(supabase: SupabaseClient<any, any, any>, moduleId: string, featureId?: string | null, level?: PermissionLevel): Promise<PermissionLevel>;
20
+ export declare function requireModulePermission(supabase: SupabaseClient<any, any, any>, moduleId: string, featureId?: string | null, level?: PermissionLevel, request?: Request | null): Promise<PermissionLevel>;
16
21
  export { getRoleFlags };
17
22
  /**
18
23
  * Sinds 1.0.23. Superadmin? Claims eerst, terugval tabel `user_roles` (RLS:
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.server.d.ts","sourceRoot":"","sources":["../../src/core/server/permissions.server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAuCvD;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACvC,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAM,GAAG,IAAW,EAC/B,KAAK,GAAE,eAAwB,GAC9B,OAAO,CAAC,eAAe,CAAC,CAyB1B;AAED,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACvC,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACtC,OAAO,CAAC,OAAO,CAAC,CAKlB"}
1
+ {"version":3,"file":"permissions.server.d.ts","sourceRoot":"","sources":["../../src/core/server/permissions.server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA8BhD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAuCvD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACvC,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAM,GAAG,IAAW,EAC/B,KAAK,GAAE,eAAwB,EAC/B,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,GACvB,OAAO,CAAC,eAAe,CAAC,CAyB1B;AAED,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACvC,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACtC,OAAO,CAAC,OAAO,CAAC,CAKlB"}
@@ -1,5 +1,28 @@
1
- import { getRequest } from "@tanstack/react-start/server";
2
1
  import { getRoleFlags } from "../auth/roles.js";
2
+ /**
3
+ * `@tanstack/react-start/server` mag hier **niet** statisch geïmporteerd worden
4
+ * (ook niet als letterlijke `import()`): het trekt `@tanstack/start-server-core`
5
+ * (node:async_hooks) in de bundel. Elke shell waarvan een module `./server` in
6
+ * zijn hoofdbarrel her-exporteert, breekt dan op de clientbuild.
7
+ *
8
+ * De specifier wordt pas ter plaatse in mekaar gezet, zodat geen enkele bundler
9
+ * hem statisch kan ontleden. De import draait dus uitsluitend op de server.
10
+ */
11
+ const REACT_START_SERVER = ["@tanstack", "react-start", "server"].join("/");
12
+ /** Het actuele verzoek, voor zover de runtime dat prijsgeeft. */
13
+ async function ambientRequest() {
14
+ try {
15
+ const mod = (await import(/* @vite-ignore */ REACT_START_SERVER));
16
+ return mod.getRequest?.() ?? null;
17
+ }
18
+ catch {
19
+ return null;
20
+ }
21
+ }
22
+ async function readRequestHeader(name, request) {
23
+ const req = request ?? (await ambientRequest());
24
+ return req?.headers?.get(name) ?? null;
25
+ }
3
26
  const RANK = { none: 0, view: 1, edit: 2 };
4
27
  function isMissingRpc(error) {
5
28
  const e = (error ?? {});
@@ -13,21 +36,17 @@ function isMissingRpc(error) {
13
36
  message.includes("could not find the function"));
14
37
  }
15
38
  /** Bearer-token van het huidige verzoek, of null. */
16
- function requestToken() {
17
- try {
18
- const header = getRequest()?.headers?.get("authorization") ?? "";
19
- return header.startsWith("Bearer ") ? header.slice(7) || null : null;
20
- }
21
- catch {
22
- return null;
23
- }
39
+ async function requestToken(request) {
40
+ const header = (await readRequestHeader("authorization", request)) ?? "";
41
+ return header.startsWith("Bearer ") ? header.slice(7) || null : null;
24
42
  }
25
43
  /**
26
44
  * Geverifieerde user-id: uitsluitend uit het token van het verzoek, gevalideerd
27
- * bij Supabase Auth (`getUser(token)`). Geen aanroeper-input.
45
+ * bij Supabase Auth (`getUser(token)`). Geen aanroeper-input: een meegegeven
46
+ * `request` is het verzoek zelf, geen ingevulde user-id.
28
47
  */
29
- async function verifiedUserId(supabase) {
30
- const token = requestToken();
48
+ async function verifiedUserId(supabase, request) {
49
+ const token = await requestToken(request);
31
50
  const { data, error } = token ? await supabase.auth.getUser(token) : await supabase.auth.getUser();
32
51
  if (error || !data?.user?.id)
33
52
  throw new Response("Unauthorized", { status: 401 });
@@ -43,9 +62,14 @@ async function verifiedUserId(supabase) {
43
62
  *
44
63
  * - Ontbreekt de RPC (add-on niet geïnstalleerd) → toegestaan (default-allow).
45
64
  * - Geen geldige sessie → 401. Onvoldoende rechten → 403.
65
+ *
66
+ * `request` is optioneel: geef `getRequest()` mee (uit de code van je eigen
67
+ * shell, die door de Start-compiler wél getransformeerd wordt) als jouw runtime
68
+ * het actuele verzoek niet zelf blootgeeft. Aan het antwoord verandert niets:
69
+ * het token wordt hoe dan ook bij Supabase Auth gevalideerd.
46
70
  */
47
- export async function requireModulePermission(supabase, moduleId, featureId = null, level = "view") {
48
- const userId = await verifiedUserId(supabase);
71
+ export async function requireModulePermission(supabase, moduleId, featureId = null, level = "view", request) {
72
+ const userId = await verifiedUserId(supabase, request);
49
73
  const { data, error } = await supabase.rpc("effective_module_permission", {
50
74
  _user_id: userId,
51
75
  _module_id: moduleId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowselections/core",
3
- "version": "1.0.24",
3
+ "version": "1.0.26",
4
4
  "private": false,
5
5
  "sideEffects": false,
6
6
  "type": "module",