firstly 0.7.1 → 0.7.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # firstly
2
2
 
3
+ ## 0.7.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#313](https://github.com/jycouet/firstly/pull/313) [`501d922`](https://github.com/jycouet/firstly/commit/501d92220ec32a19622eed403c85f445c3ccc68e) Thanks [@jycouet](https://github.com/jycouet)! - `remultApiServerLoad` reads through `event.fetch` instead of `TestApiDataProvider`: concurrency-safe on released remult (no process-global static swap), and the API side runs the app's real auth/hooks.
8
+
3
9
  ## 0.7.1
4
10
 
5
11
  ### Patch Changes
@@ -1,19 +1,25 @@
1
1
  import type { LoadEvent } from '@sveltejs/kit';
2
+ /**
3
+ * Run `body` in a scoped `withRemult` whose reads go through the API via `fetch`
4
+ * (`allowApiRead` / `apiPrefilter` apply); a concurrent load keeps its own
5
+ * provider. `remult.user` is carried in so the body can read it.
6
+ *
7
+ * TODO(remult): framework-agnostic (only needs a fetch) - candidate to live in
8
+ * remult directly.
9
+ */
10
+ export declare function withRemultFetch<T>(fetch: typeof globalThis.fetch, body: () => Promise<T>): Promise<T>;
2
11
  /**
3
12
  * Wrap a SvelteKit UNIVERSAL load (`+page.ts` / `+layout.ts`) so plain global
4
13
  * `repo()` / `ff()` reads through the API (so `allowApiRead` / `apiPrefilter`
5
14
  * apply), on both SSR and CSR.
6
15
  *
7
- * - SSR: runs the body in a nested `withRemult` bound to `event.fetch` - gated, and
8
- * scoped so a concurrent `+page.server.ts` keeps its own provider. SvelteKit
9
- * inlines the response. `remult.user` is carried in so the body can read it.
16
+ * - SSR: runs the body in a scoped `withRemult` bound to `event.fetch` - gated,
17
+ * and a concurrent `+page.server.ts` keeps its own provider. SvelteKit inlines
18
+ * the response.
10
19
  * - CSR / hydration: points the client `remult` at this page's `event.fetch` so the
11
20
  * inlined SSR response is reused, then runs the body.
12
21
  *
13
22
  * (A universal load runs on the client too, so it must use `event.fetch`. For a
14
23
  * server-only load see `remultApiServerLoad` from `firstly/svelte/server`.)
15
- *
16
- * TODO(remult): the SSR branch is framework-agnostic (only needs `event.fetch`) -
17
- * candidate to live in remult (e.g. `withRemultFetch(fetch, body)`).
18
24
  */
19
25
  export declare function remultApiUniversalLoad<T>(body: (event: LoadEvent) => Promise<T>): (event: LoadEvent) => Promise<T>;
@@ -1,20 +1,32 @@
1
1
  import { isBackend, remult, RestDataProvider, withRemult } from 'remult';
2
+ /**
3
+ * Run `body` in a scoped `withRemult` whose reads go through the API via `fetch`
4
+ * (`allowApiRead` / `apiPrefilter` apply); a concurrent load keeps its own
5
+ * provider. `remult.user` is carried in so the body can read it.
6
+ *
7
+ * TODO(remult): framework-agnostic (only needs a fetch) - candidate to live in
8
+ * remult directly.
9
+ */
10
+ export function withRemultFetch(fetch, body) {
11
+ const user = remult.user;
12
+ return withRemult(async () => {
13
+ remult.user = user;
14
+ return body();
15
+ }, { dataProvider: new RestDataProvider(() => ({ httpClient: fetch })) });
16
+ }
2
17
  /**
3
18
  * Wrap a SvelteKit UNIVERSAL load (`+page.ts` / `+layout.ts`) so plain global
4
19
  * `repo()` / `ff()` reads through the API (so `allowApiRead` / `apiPrefilter`
5
20
  * apply), on both SSR and CSR.
6
21
  *
7
- * - SSR: runs the body in a nested `withRemult` bound to `event.fetch` - gated, and
8
- * scoped so a concurrent `+page.server.ts` keeps its own provider. SvelteKit
9
- * inlines the response. `remult.user` is carried in so the body can read it.
22
+ * - SSR: runs the body in a scoped `withRemult` bound to `event.fetch` - gated,
23
+ * and a concurrent `+page.server.ts` keeps its own provider. SvelteKit inlines
24
+ * the response.
10
25
  * - CSR / hydration: points the client `remult` at this page's `event.fetch` so the
11
26
  * inlined SSR response is reused, then runs the body.
12
27
  *
13
28
  * (A universal load runs on the client too, so it must use `event.fetch`. For a
14
29
  * server-only load see `remultApiServerLoad` from `firstly/svelte/server`.)
15
- *
16
- * TODO(remult): the SSR branch is framework-agnostic (only needs `event.fetch`) -
17
- * candidate to live in remult (e.g. `withRemultFetch(fetch, body)`).
18
30
  */
19
31
  export function remultApiUniversalLoad(body) {
20
32
  return (event) => {
@@ -22,10 +34,6 @@ export function remultApiUniversalLoad(body) {
22
34
  remult.apiClient.httpClient = event.fetch;
23
35
  return body(event);
24
36
  }
25
- const user = remult.user;
26
- return withRemult(async () => {
27
- remult.user = user;
28
- return body(event);
29
- }, { dataProvider: new RestDataProvider(() => ({ httpClient: event.fetch })) });
37
+ return withRemultFetch(event.fetch, () => body(event));
30
38
  };
31
39
  }
@@ -1,12 +1,13 @@
1
1
  import type { ServerLoadEvent } from '@sveltejs/kit';
2
2
  /**
3
3
  * Wrap a SvelteKit SERVER load (`+page.server.ts`) so plain global `repo()` reads
4
- * apply the API gate (as the current user) instead of the privileged in-process
5
- * provider. Use it only when a server load should see exactly what the API exposes;
6
- * otherwise a server load keeps the DB provider (gate rows with `backendPrefilter`).
7
- * Gates direct `repo()` reads; BackendMethods keep their own `allowed` gate.
4
+ * apply the API gate (as the current user) instead of the privileged DB provider.
8
5
  *
9
- * TODO(remult): framework-agnostic (event passed through; provider read from
10
- * `remult`) - candidate to live in remult directly.
6
+ * Reads go through `event.fetch`: SvelteKit dispatches same-origin server fetch
7
+ * in-process (no network) and forwards cookies, so the app's real auth/hooks run
8
+ * for each read. Use it only when a server load should see exactly what the API
9
+ * exposes; otherwise a server load keeps the DB provider (gate rows with
10
+ * `backendPrefilter`). Gates direct `repo()` reads; BackendMethods keep their own
11
+ * `allowed` gate.
11
12
  */
12
13
  export declare function remultApiServerLoad<T>(body: (event: ServerLoadEvent) => Promise<T>): (event: ServerLoadEvent) => Promise<T>;
@@ -1,27 +1,15 @@
1
- import { remult, withRemult } from 'remult';
2
- import { TestApiDataProvider } from 'remult/server';
3
- // SERVER-ONLY (imports `remult/server`). Never import from client-reachable code.
4
- // Lazily wrap the app's dataProvider once. TestApiDataProvider dispatches repo()
5
- // through the API pipeline in-process (so allowApiRead / apiPrefilter apply) and
6
- // carries the current user - no event.fetch, no `/api` round-trip.
7
- let apiDataProvider;
1
+ import { withRemultFetch } from '../remultApiLoad.js';
8
2
  /**
9
3
  * Wrap a SvelteKit SERVER load (`+page.server.ts`) so plain global `repo()` reads
10
- * apply the API gate (as the current user) instead of the privileged in-process
11
- * provider. Use it only when a server load should see exactly what the API exposes;
12
- * otherwise a server load keeps the DB provider (gate rows with `backendPrefilter`).
13
- * Gates direct `repo()` reads; BackendMethods keep their own `allowed` gate.
4
+ * apply the API gate (as the current user) instead of the privileged DB provider.
14
5
  *
15
- * TODO(remult): framework-agnostic (event passed through; provider read from
16
- * `remult`) - candidate to live in remult directly.
6
+ * Reads go through `event.fetch`: SvelteKit dispatches same-origin server fetch
7
+ * in-process (no network) and forwards cookies, so the app's real auth/hooks run
8
+ * for each read. Use it only when a server load should see exactly what the API
9
+ * exposes; otherwise a server load keeps the DB provider (gate rows with
10
+ * `backendPrefilter`). Gates direct `repo()` reads; BackendMethods keep their own
11
+ * `allowed` gate.
17
12
  */
18
13
  export function remultApiServerLoad(body) {
19
- return (event) => {
20
- apiDataProvider ??= TestApiDataProvider({ dataProvider: remult.dataProvider });
21
- const user = remult.user;
22
- return withRemult(async () => {
23
- remult.user = user;
24
- return body(event);
25
- }, { dataProvider: apiDataProvider });
26
- };
14
+ return (event) => withRemultFetch(event.fetch, () => body(event));
27
15
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firstly",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "type": "module",
5
5
  "description": "Firstly, an opinionated Remult setup!",
6
6
  "funding": "https://github.com/sponsors/jycouet",