@fougere/app 0.6.0-alpha.0 → 0.7.0-alpha.0

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.
Files changed (59) hide show
  1. package/dist/auth.d.ts +1 -7
  2. package/dist/auth.d.ts.map +1 -1
  3. package/dist/auth.js.map +1 -1
  4. package/dist/boot.d.ts +14 -85
  5. package/dist/boot.d.ts.map +1 -1
  6. package/dist/boot.js +17 -77
  7. package/dist/boot.js.map +1 -1
  8. package/dist/client.d.ts +5 -24
  9. package/dist/client.d.ts.map +1 -1
  10. package/dist/client.js +6 -32
  11. package/dist/client.js.map +1 -1
  12. package/dist/express.d.ts +2 -12
  13. package/dist/express.d.ts.map +1 -1
  14. package/dist/express.js +4 -52
  15. package/dist/express.js.map +1 -1
  16. package/dist/form.d.ts +11 -56
  17. package/dist/form.d.ts.map +1 -1
  18. package/dist/form.js +15 -33
  19. package/dist/form.js.map +1 -1
  20. package/dist/graphql.d.ts +2 -28
  21. package/dist/graphql.d.ts.map +1 -1
  22. package/dist/graphql.js +1 -6
  23. package/dist/graphql.js.map +1 -1
  24. package/dist/index.d.ts +1 -11
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +1 -11
  27. package/dist/index.js.map +1 -1
  28. package/dist/rest.d.ts +2 -16
  29. package/dist/rest.d.ts.map +1 -1
  30. package/dist/rest.js +4 -34
  31. package/dist/rest.js.map +1 -1
  32. package/dist/serve.d.ts +10 -57
  33. package/dist/serve.d.ts.map +1 -1
  34. package/dist/serve.js +12 -55
  35. package/dist/serve.js.map +1 -1
  36. package/dist/session.d.ts +2 -7
  37. package/dist/session.d.ts.map +1 -1
  38. package/dist/session.js +2 -7
  39. package/dist/session.js.map +1 -1
  40. package/dist/state.d.ts.map +1 -1
  41. package/dist/state.js +1 -11
  42. package/dist/state.js.map +1 -1
  43. package/dist/web.d.ts +3 -19
  44. package/dist/web.d.ts.map +1 -1
  45. package/dist/web.js +4 -32
  46. package/dist/web.js.map +1 -1
  47. package/package.json +11 -11
  48. package/src/auth.ts +1 -7
  49. package/src/boot.ts +28 -134
  50. package/src/client.ts +7 -33
  51. package/src/express.ts +4 -52
  52. package/src/form.ts +20 -73
  53. package/src/graphql.ts +2 -28
  54. package/src/index.ts +1 -11
  55. package/src/rest.ts +4 -34
  56. package/src/serve.ts +13 -60
  57. package/src/session.ts +2 -7
  58. package/src/state.ts +1 -11
  59. package/src/web.ts +4 -32
package/dist/serve.js CHANGED
@@ -1,44 +1,17 @@
1
- /**
2
- * The three doors, decided — and nothing about how a request arrives.
3
- *
4
- * A host (Nuxt, Next) owns exactly two translations: read the request into the
5
- * plain values below, and write the outcome back out. Everything between — which
6
- * operation a verb and a path name, which audience a segment selects, what a
7
- * refusal becomes — is decided here, once, for every host.
8
- *
9
- * The split matters because the alternative was measured in this repo: two copies
10
- * of a REST rule drifted until the Nuxt door answered differently from
11
- * `schema-rest` on the verb, the path AND the exposure. A second host would have
12
- * been a third copy.
13
- */
1
+ /** The three doors, decided — and nothing about how a request arrives. */
14
2
  import { createAppRunner, callValueOf, toHttpError, } from '@fougere/core';
15
3
  import { handleRpc, PARSE_ERROR } from '@fougere/transport-http';
16
4
  import { matchRoute, tableOf } from './rest.js';
17
5
  // ── The call envelope ────────────────────────────
18
- /**
19
- * The audience this door serves — the path segment after `/_fougere/call`.
20
- *
21
- * The envelope is a surface like REST and GraphQL, so it selects its audience like
22
- * they do; the difference is only that it takes it from the path instead of an
23
- * option, because a door is mounted, not called. The same word names the directory
24
- * (`handlers/public/`), the config key (`surfaces: { public: [...] }`) and this
25
- * segment — derived, never configured.
26
- *
27
- * No escalation to guard: a named surface serves the entities it names and nothing
28
- * else (closed by naming), so every one of them is a subset of what the bare path
29
- * already serves.
30
- */
6
+ /** The audience this door serves — the path segment after `/_fougere/call`. */
31
7
  export function surfaceOf(path) {
32
8
  const named = /^\/_fougere\/call\/([A-Za-z0-9_-]+)/.exec(path.replace(/\?.*$/, ''));
33
9
  return named?.[1];
34
10
  }
35
11
  /**
36
- * Receiving end for the browser — same wire as process-to-process (JSON-RPC),
37
- * different trust boundary: the browser sits outside the topology, so `state` is
38
- * whatever the host resolved server-side, never what the payload claims.
39
- *
40
- * The runner follows the app's topology: local façades and remote doublures alike
41
- * — the browser never knows where a Frond lives.
12
+ * Receiving end for the browser — same wire as process-to-process (JSON-RPC), different trust
13
+ * boundary: the browser sits outside the topology, so `state` is whatever the host resolved
14
+ * server-side, never what the payload claims.
42
15
  */
43
16
  export async function serveRpc(app, request) {
44
17
  const runner = createAppRunner(app, surfaceOf(request.path));
@@ -50,12 +23,7 @@ export function rpcParseError() {
50
23
  }
51
24
  // ── REST ─────────────────────────────────────────
52
25
  /**
53
- * Match the URL against the canonical table, invoke the call it names, shape the
54
- * result for HTTP. The decision lives in `rest.ts`; dispatch belongs to the runner.
55
- *
56
- * `path` is what follows the REST mount point, so `/api/blog/posts/1` arrives as
57
- * `blog/posts/1`. A path this door does not serve returns `pass`, and that is what
58
- * lets an app keep its own `/api/*` handlers.
26
+ * Match the URL against the canonical table, invoke the call it names, shape the result for HTTP.
59
27
  */
60
28
  export async function serveRest(app, request) {
61
29
  // The app decides, not the host. A route file may exist and a middleware may be
@@ -84,7 +52,7 @@ export async function serveRest(app, request) {
84
52
  const { route, params } = match;
85
53
  let result;
86
54
  try {
87
- result = await invokeOn(app, { entity: route.entityName, op: route.operationName }, { params, query: request.query, body: request.body }, undefined, request.state);
55
+ result = await invokeOn(app, { entity: route.entityName, op: route.operationName }, { params, query: request.query, input: request.body }, undefined, request.state);
88
56
  }
89
57
  catch (err) {
90
58
  const { status, body } = toHttpError(err);
@@ -92,13 +60,7 @@ export async function serveRest(app, request) {
92
60
  }
93
61
  return shapeRest(route.operationName, result);
94
62
  }
95
- /**
96
- * What an operation's return becomes on the wire.
97
- *
98
- * Separate from `serveRest` because it is a DECISION and dispatch is not: it can be
99
- * pinned without a runner, and both hosts get it whether the call ran in memory or
100
- * came back over JSON-RPC.
101
- */
63
+ /** What an operation's return becomes on the wire. */
102
64
  export function shapeRest(operationName, result) {
103
65
  if (result === null)
104
66
  return { kind: 'error', status: 404, body: { message: 'Not found' } };
@@ -118,19 +80,14 @@ export function shapeRest(operationName, result) {
118
80
  return { kind: 'ok', status: 200, body: result };
119
81
  }
120
82
  /**
121
- * Name a call server-side and let the runner place it — local façade → direct
122
- * in-memory execution, a frond in `remotes` → JSON-RPC on the wire. The caller
123
- * never knows which.
124
- *
125
- * `state` is explicit here. Each host wraps this with its own way of finding the
126
- * current request (Nitro's async context, Next's `headers()` scope), because that
127
- * is the one part a host actually owns.
83
+ * Name a call server-side and let the runner place it — local façade → direct in-memory execution,
84
+ * a frond in `remotes` → JSON-RPC on the wire.
128
85
  */
129
86
  export async function invokeOn(app, target, opOrInput, input, state = {}) {
130
87
  const { call, invocation } = callValueOf(target, opOrInput, input);
131
88
  // An explicit `state` on the input wins over the request's — the caller who spells
132
89
  // it is answering for it, which is what makes a call outside any request possible.
133
- const given = typeof opOrInput === 'string' ? input : opOrInput;
134
- return (await createAppRunner(app)(call, { ...invocation, state: given?.state ?? state }));
90
+ const explicit = typeof opOrInput === 'string' ? input : opOrInput;
91
+ return (await createAppRunner(app)(call, { ...invocation, state: explicit?.state ?? state }));
135
92
  }
136
93
  //# sourceMappingURL=serve.js.map
package/dist/serve.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EACL,eAAe,EACf,WAAW,EACX,WAAW,GAIZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwBhD,oDAAoD;AAEpD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,KAAK,GAAG,qCAAqC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IACpF,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,GAAQ,EAAE,OAAqD;IAC5F,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7D,OAAO,SAAS,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,GAAG,UAAU,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;AAC9G,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,aAAa;IAC3B,OAAO,EAAE,OAAO,EAAE,KAAc,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,CAAC;AACrG,CAAC;AAED,oDAAoD;AAEpD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAQ,EAAE,OAAoB;IAC5D,gFAAgF;IAChF,iFAAiF;IACjF,oFAAoF;IACpF,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAEjD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAEjD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IACzD,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAEpC,IAAI,KAAK,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;QACxC,OAAO;YACL,IAAI,EAAE,OAAO;YACb,MAAM,EAAE,GAAG;YACX,IAAI,EAAE;gBACJ,OAAO,EAAE,UAAU,MAAM,oBAAoB,OAAO,CAAC,IAAI,UAAU,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAC3F,KAAK,EAAE,KAAK,CAAC,KAAK;aACnB;YACD,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;SAC3C,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAChC,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,QAAQ,CACrB,GAAG,EACH,EAAE,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,EAAE,EAAE,KAAK,CAAC,aAAa,EAAE,EACrD,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,EACpD,SAAS,EACT,OAAO,CAAC,KAAK,CACd,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QAC1C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAqD,EAAE,CAAC;IAChG,CAAC;IAED,OAAO,SAAS,CAAC,KAAK,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;AAChD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,aAAqB,EAAE,MAAe;IAC9D,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,CAAC;IAE3F,oFAAoF;IACpF,6EAA6E;IAC7E,IAAI,aAAa,KAAK,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,GAAG,MAA8E,CAAC;QAC5F,OAAO;YACL,IAAI,EAAE,IAAI;YACV,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE;SAClG,CAAC;IACJ,CAAC;IAED,oFAAoF;IACpF,oFAAoF;IACpF,6EAA6E;IAC7E,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AACnD,CAAC;AAOD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,GAAQ,EACR,MAA+B,EAC/B,SAA8B,EAC9B,KAAiB,EACjB,KAAK,GAA4B,EAAE;IAEnC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IACnE,mFAAmF;IACnF,mFAAmF;IACnF,MAAM,KAAK,GAAG,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAChE,OAAO,CAAC,MAAM,eAAe,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,KAAK,EAAE,CAAC,CAAM,CAAC;AAClG,CAAC"}
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"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"}
package/dist/session.d.ts CHANGED
@@ -1,11 +1,6 @@
1
1
  /**
2
- * The session view — the one place that turns the server-resolved
3
- * request context (filled by the auth middleware) into what the client
4
- * is allowed to see. One resolution, three readers: the page by
5
- * hydration, the refresh route over the wire, handlers by invocation.
6
- *
7
- * The app-declared context (viewer enrichment) will attach here when
8
- * a real case lands — this function is the seam.
2
+ * The session view — the one place that turns the server-resolved request context (filled by the
3
+ * auth middleware) into what the client is allowed to see.
9
4
  */
10
5
  export interface SessionView {
11
6
  user: Record<string, unknown> | null;
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACtC;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAK3E"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACtC;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAK3E"}
package/dist/session.js CHANGED
@@ -1,11 +1,6 @@
1
1
  /**
2
- * The session view — the one place that turns the server-resolved
3
- * request context (filled by the auth middleware) into what the client
4
- * is allowed to see. One resolution, three readers: the page by
5
- * hydration, the refresh route over the wire, handlers by invocation.
6
- *
7
- * The app-declared context (viewer enrichment) will attach here when
8
- * a real case lands — this function is the seam.
2
+ * The session view — the one place that turns the server-resolved request context (filled by the
3
+ * auth middleware) into what the client is allowed to see.
9
4
  */
10
5
  export function sessionViewOf(context) {
11
6
  const raw = context.user;
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,MAAM,UAAU,aAAa,CAAC,OAAgC;IAC5D,MAAM,GAAG,GAAG,OAAO,CAAC,IAA2C,CAAC;IAChE,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAChC,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,CAAC;IACrD,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,UAAU,aAAa,CAAC,OAAgC;IAC5D,MAAM,GAAG,GAAG,OAAO,CAAC,IAA2C,CAAC;IAChE,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAChC,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,CAAC;IACrD,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAiBA,mGAAmG;AACnG,wBAAsB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAcjF"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAOA,mGAAmG;AACnG,wBAAsB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAcjF"}
package/dist/state.js CHANGED
@@ -1,14 +1,4 @@
1
- /**
2
- * Who the caller is, resolved server-side from the request's own headers.
3
- *
4
- * Nuxt answers this with a Nitro middleware that stamps `event.context`; a
5
- * Web-standard host has no such seam on a route handler, so it resolves here
6
- * instead. Same source (the auth runtime mounted on `app.auth`), same result shape
7
- * (`{ user, session }`), so `serveRpc` and `serveRest` cannot tell hosts apart.
8
- *
9
- * What must stay true in both: this is what the SERVER resolved. A browser sits
10
- * outside the topology, so nothing here may come from the payload.
11
- */
1
+ /** Who the caller is, resolved server-side from the request's own headers. */
12
2
  import { useFougereApp } from './boot.js';
13
3
  /** The request state for these headers. Empty when no auth is declared, or nobody is signed in. */
14
4
  export async function stateFor(headers) {
package/dist/state.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAM1C,mGAAmG;AACnG,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAgB;IAC7C,MAAM,GAAG,GAAG,MAAM,aAAa,EAAE,CAAC;IAClC,IAAI,CAAC,GAAG,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACzB,wFAAwF;IACxF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IAEtC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAO,GAAG,CAAC,IAAI,CAAC,GAA6B,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QACrF,IAAI,MAAM,EAAE,OAAO,IAAI,MAAM,EAAE,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IAC7F,CAAC;IAAC,MAAM,CAAC;QACP,8EAA8E;QAC9E,wEAAwE;IAC1E,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAM1C,mGAAmG;AACnG,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAgB;IAC7C,MAAM,GAAG,GAAG,MAAM,aAAa,EAAE,CAAC;IAClC,IAAI,CAAC,GAAG,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACzB,wFAAwF;IACxF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IAEtC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAO,GAAG,CAAC,IAAI,CAAC,GAA6B,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QACrF,IAAI,MAAM,EAAE,OAAO,IAAI,MAAM,EAAE,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;IAC7F,CAAC;IAAC,MAAM,CAAC;QACP,8EAA8E;QAC9E,wEAAwE;IAC1E,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}
package/dist/web.d.ts CHANGED
@@ -1,25 +1,9 @@
1
- /**
2
- * The call envelope. A named surface is the path segment after the door —
3
- * `/_fougere/call/public` serves the `public` audience — and `surfaceOf` reads it,
4
- * so a host only has to mount this at a path that keeps the segments.
5
- */
1
+ /** The call envelope. */
6
2
  export declare function fougereCall(request: Request): Promise<Response>;
7
- /**
8
- * The REST projection, mounted under `/api`.
9
- *
10
- * `pass` — a path this app does not serve — becomes a 404 here rather than a
11
- * fall-through, because a Web handler has nobody to fall through to. Hosts that
12
- * resolve a static route before a catch-all (Next does) still let an app keep its
13
- * own `/api/*` handlers: they are reached BEFORE this one, not after.
14
- */
3
+ /** The REST projection, mounted under `/api`. */
15
4
  export declare function fougereRest(request: Request): Promise<Response>;
16
5
  /** The session view over the wire, for a client refreshing after login or logout. */
17
6
  export declare function fougereSession(request: Request): Promise<Response>;
18
- /**
19
- * GraphQL, at whatever path the host mounted it — `/graphql` by convention.
20
- *
21
- * Answers `404` when the app declares no GraphQL adapter, because unlike REST this
22
- * door is mounted at a path of its own: there is no app route underneath it to pass to.
23
- */
7
+ /** GraphQL, at whatever path the host mounted it — `/graphql` by convention. */
24
8
  export declare function fougereGraphQL(request: Request): Promise<Response>;
25
9
  //# sourceMappingURL=web.d.ts.map
package/dist/web.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAqBrE;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAoBrE;AAED,qFAAqF;AACrF,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAExE;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkBxE"}
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AAQA,yBAAyB;AACzB,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAqBrE;AAED,iDAAiD;AACjD,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAoBrE;AAED,qFAAqF;AACrF,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAExE;AAED,gFAAgF;AAChF,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkBxE"}
package/dist/web.js CHANGED
@@ -1,26 +1,10 @@
1
- /**
2
- * The three doors as Web-standard handlers: `Request` in, `Response` out.
3
- *
4
- * This is the whole server surface for any host built on fetch semantics — Next
5
- * route handlers, TanStack Start server routes, Hono, a bare `Deno.serve`. Such a
6
- * host mounts these; it does not translate anything, because there is nothing left
7
- * to translate.
8
- *
9
- * Nuxt is the exception and keeps its own translation, for a reason worth stating:
10
- * an h3 event is not a `Request`, and reading its body has to straddle two h3
11
- * majors (`server/routes/call.post.ts` carries that hundred lines). That file is
12
- * what a NON-Web-standard host costs.
13
- */
1
+ /** The three doors as Web-standard handlers: `Request` in, `Response` out. */
14
2
  import { serveRest, serveRpc, rpcParseError, useFougereApp, serveGraphQL } from './index.js';
15
3
  import { MAX_BODY_BYTES } from '@fougere/core';
16
4
  import { sessionViewOf } from './session.js';
17
5
  import { stateFor } from './state.js';
18
6
  const WITH_BODY = new Set(['POST', 'PUT', 'PATCH']);
19
- /**
20
- * The call envelope. A named surface is the path segment after the door —
21
- * `/_fougere/call/public` serves the `public` audience — and `surfaceOf` reads it,
22
- * so a host only has to mount this at a path that keeps the segments.
23
- */
7
+ /** The call envelope. */
24
8
  export async function fougereCall(request) {
25
9
  const declared = Number(request.headers.get('content-length'));
26
10
  if (Number.isFinite(declared) && declared > MAX_BODY_BYTES) {
@@ -40,14 +24,7 @@ export async function fougereCall(request) {
40
24
  state: await stateFor(request.headers),
41
25
  }));
42
26
  }
43
- /**
44
- * The REST projection, mounted under `/api`.
45
- *
46
- * `pass` — a path this app does not serve — becomes a 404 here rather than a
47
- * fall-through, because a Web handler has nobody to fall through to. Hosts that
48
- * resolve a static route before a catch-all (Next does) still let an app keep its
49
- * own `/api/*` handlers: they are reached BEFORE this one, not after.
50
- */
27
+ /** The REST projection, mounted under `/api`. */
51
28
  export async function fougereRest(request) {
52
29
  const app = await useFougereApp();
53
30
  const url = new URL(request.url);
@@ -71,12 +48,7 @@ export async function fougereRest(request) {
71
48
  export async function fougereSession(request) {
72
49
  return Response.json(sessionViewOf(await stateFor(request.headers)));
73
50
  }
74
- /**
75
- * GraphQL, at whatever path the host mounted it — `/graphql` by convention.
76
- *
77
- * Answers `404` when the app declares no GraphQL adapter, because unlike REST this
78
- * door is mounted at a path of its own: there is no app route underneath it to pass to.
79
- */
51
+ /** GraphQL, at whatever path the host mounted it — `/graphql` by convention. */
80
52
  export async function fougereGraphQL(request) {
81
53
  const app = await useFougereApp();
82
54
  const body = (await request.json().catch(() => ({})));
package/dist/web.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"web.js","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAEpD,yBAAyB;AACzB,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAgB;IAChD,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC/D,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,cAAc,EAAE,CAAC;QAC3D,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,mBAAmB,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,aAAa,EAAE,CAAC;IAClC,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,CAClB,MAAM,QAAQ,CAAC,GAAG,EAAE;QAClB,IAAI,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ;QACnC,IAAI;QACJ,KAAK,EAAE,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC;KACvC,CAAC,CACH,CAAC;AACJ,CAAC;AAED,iDAAiD;AACjD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAgB;IAChD,MAAM,GAAG,GAAG,MAAM,aAAa,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;IAE5C,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE;QACnC,MAAM;QACN,IAAI,EAAE,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;QAC1C,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC;QAC3C,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS;QACrF,KAAK,EAAE,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC;KACvC,CAAC,CAAC;IAEH,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5B,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,gBAAgB,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/F,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC7B,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3F,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAgB;IACnD,OAAO,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAgB;IACnD,MAAM,GAAG,GAAG,MAAM,aAAa,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAInD,CAAC;IAEF,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE;QACtC,GAAG,IAAI;QACP,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACpE,KAAK,EAAE,MAAM,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC;KACvC,CAAC,CAAC;IAEH,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5B,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,mCAAmC,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AACjE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fougere/app",
3
- "version": "0.6.0-alpha.0",
3
+ "version": "0.7.0-alpha.0",
4
4
  "description": "The host-independent half of a Fougere app: boot, call envelope, REST table, form contract.",
5
5
  "keywords": [
6
6
  "fougere",
@@ -42,24 +42,24 @@
42
42
  ],
43
43
  "dependencies": {
44
44
  "jiti": "^2.6.1",
45
- "@fougere/core": "0.6.0-alpha.0",
46
- "@fougere/defaults": "0.6.0-alpha.0",
47
- "@fougere/adapter-rest": "0.6.0-alpha.0",
48
- "@fougere/transport-http": "0.6.0-alpha.0",
49
- "@fougere/http": "0.6.0-alpha.0",
50
- "@fougere/container": "0.6.0-alpha.0",
51
- "@fougere/adapter-memory": "0.6.0-alpha.0",
52
- "@fougere/schema": "0.6.0-alpha.0"
45
+ "@fougere/core": "0.7.0-alpha.0",
46
+ "@fougere/adapter-rest": "0.7.0-alpha.0",
47
+ "@fougere/defaults": "0.7.0-alpha.0",
48
+ "@fougere/schema": "0.7.0-alpha.0",
49
+ "@fougere/http": "0.7.0-alpha.0",
50
+ "@fougere/container": "0.7.0-alpha.0",
51
+ "@fougere/adapter-memory": "0.7.0-alpha.0",
52
+ "@fougere/transport-http": "0.7.0-alpha.0"
53
53
  },
54
54
  "devDependencies": {
55
55
  "vitest": "^4.1.0",
56
- "@fougere/adapter-graphql": "0.6.0-alpha.0"
56
+ "@fougere/adapter-graphql": "0.7.0-alpha.0"
57
57
  },
58
58
  "publishConfig": {
59
59
  "access": "public"
60
60
  },
61
61
  "peerDependencies": {
62
- "@fougere/adapter-graphql": "0.6.0-alpha.0"
62
+ "@fougere/adapter-graphql": "0.7.0-alpha.0"
63
63
  },
64
64
  "peerDependenciesMeta": {
65
65
  "@fougere/adapter-graphql": {
package/src/auth.ts CHANGED
@@ -1,10 +1,4 @@
1
- /**
2
- * Auth accessor — reads the AuthRuntime that the core mounted on the app.
3
- *
4
- * Auth is no longer a separate singleton: it lives on `app.auth`, built once
5
- * during boot from the `auth` field of fougere.config.ts. This accessor is a
6
- * thin async helper for server code (middleware, routes, /api/me).
7
- */
1
+ /** Auth accessor — reads the AuthRuntime that the core mounted on the app. */
8
2
  import type { AuthRuntime } from '@fougere/core';
9
3
  import { useFougereApp } from './boot.js';
10
4
 
package/src/boot.ts CHANGED
@@ -1,99 +1,35 @@
1
1
  import { Role } from '@fougere/schema';
2
2
  import { Lifecycle } from '@fougere/schema';
3
- /**
4
- * Fougere server bootstrap — single entry point for an app's lifecycle,
5
- * whatever hosts it.
6
- *
7
- * Nothing here knows h3, Nitro, Vue or React: a boot reads `fougere.config.ts`,
8
- * scans fronds off the filesystem and hands back an `App`. That is why it lives
9
- * in `@fougere/app` rather than in one of the two adapters — the second host
10
- * would otherwise have copied it, and a copied boot drifts (the seeding loop
11
- * already did, `core/src/boot/seed.ts`).
12
- *
13
- * Default path (zero-config): fougere.config.ts declares `db: 'sqlite'` and
14
- * everything else; this module auto-resolves the storage handle, builds an
15
- * storageFactory, runs auto-DDL from the entities, and boots the app.
16
- *
17
- * Escape hatch: `configureFougere({ db, storageFactory })` can be called from the
18
- * host's own startup (a Nitro plugin, a Next instrumentation hook) if the user
19
- * wants a custom data layer — alternative driver, managed migrations, etc.
20
- */
3
+ /** Fougere server bootstrap — single entry point for an app's lifecycle, whatever hosts it. */
21
4
  import { createApp, identityFromEnv, Logger, migrating, seeding } from '@fougere/core';
22
5
  import { scanProject, loadCascadedConfig, setModuleLoader, frondAliases, resolveConventions } from '@fougere/core/node';
23
6
  import type { Extension } from '@fougere/core';
24
7
  import { createContainer } from '@fougere/container';
25
8
  import { createMemoryStorage } from '@fougere/adapter-memory';
26
9
  import type { App, CreateAppOptions, Storage, FougereConfig, Transport } from '@fougere/core';
10
+ import type { ResolvedStorage } from '@fougere/defaults';
27
11
  import { applyCreate, applyUpdate, type SchemaView } from '@fougere/schema';
28
12
 
29
13
  // ── Public types ─────────────────────────────────
30
14
 
31
15
  export interface FougereServerConfig {
32
- /** Storage handle. Forwarded to the auth provider via AuthContext.db. */
33
- db?: unknown;
34
- /** Per-entity storage factory. */
35
- storageFactory?: (entity: SchemaView, name: string) => Storage;
36
16
  /**
37
- * What this app takes on beyond its fronds, each stating what it does and what it undoes.
38
- *
39
- * It replaced `afterBoot`, which a host used to CLAIM the whole post-boot to get its own
40
- * seeding — Nuxt's generated plugin did exactly that, and its copy of the seeding loop
41
- * drifted. Declaring `{ name: 'seeds', up }` replaces that one member and leaves the
42
- * rest of the ascent alone.
17
+ * The whole data layer, as `resolveStorage` composed it where the rows are, which source
18
+ * transacts, what to close. Handed over as ONE subject: a host that passed the factory alone
19
+ * lost the transaction and the connection's owner, and nothing said so.
43
20
  */
21
+ storage?: ResolvedStorage;
22
+ /** What this app takes on beyond its fronds, each stating what it does and what it undoes. */
44
23
  extensions?: CreateAppOptions['extensions'];
45
- /**
46
- * What the boot line names as the host — 'Nuxt/Nitro', 'Next'. Stated by the
47
- * adapter, never sniffed: a boot that guesses its host from what happens to be
48
- * importable is the hidden runtime the doctrine refuses.
49
- */
24
+ /** What the boot line names as the host — 'Nuxt/Nitro', 'Next'. */
50
25
  host?: string;
51
- /**
52
- * What this app is built from, when the host already knows.
53
- *
54
- * Absent, `boot()` reads the fronds off the disk — right on a server, impossible on a
55
- * runtime that has none: measured on workerd, `readdir` throws through unenv's shim and
56
- * the app comes up with ZERO fronds, so every page renders and every door answers
57
- * NOT_FOUND. A host that scanned at BUILD time can say so instead, and `fougere build`
58
- * writes exactly this value down.
59
- *
60
- * Same slot as `CreateAppOptions.scan` and for the same reason: producing the value
61
- * reads a disk, consuming it does not.
62
- */
26
+ /** What this app is built from, when the host already knows. */
63
27
  scan?: CreateAppOptions['scan'];
64
- /**
65
- * What this app STATES it hosts — `frond('blog', { entities: [Post] })`.
66
- *
67
- * Stating this and no `scan` is how a host stops scanning at boot: nothing reads a
68
- * disk, nothing loads `typescript`, and what was not named does not exist. It is the
69
- * one door Next, Vite, React, Svelte and a bare Express share — none of them scans on
70
- * its own, they all arrive here, and this line used to end in a scan for every one.
71
- */
28
+ /** What this app STATES it hosts — `frond('blog', { entities: [Post] })`. */
72
29
  fronds?: CreateAppOptions['fronds'];
73
- /**
74
- * What `fougere.config.ts` says, when the host already read it.
75
- *
76
- * The same rule as `scan`, and found the same way: `boot()` re-reads the file at
77
- * runtime, which a Worker cannot do — measured, a consumer's `remotes:` never reached
78
- * the boot and its pages rendered empty with nothing said. A host that read the config
79
- * at BUILD time states it here instead.
80
- *
81
- * `auth` is deliberately not part of what a codegen'd host can carry: it holds a live
82
- * provider, not a value. An app that authenticates reads its own config.
83
- */
30
+ /** What `fougere.config.ts` says, when the host already read it. */
84
31
  config?: Partial<FougereConfig>;
85
- /**
86
- * Who performs an outgoing call, when the default cannot.
87
- *
88
- * `boot()` builds an HTTP transport from `remotes:` and that is right nearly
89
- * everywhere. It is not right on Cloudflare: a Worker calling a sibling's public URL
90
- * is refused by the edge with error 1042, so two Workers of one account reach each
91
- * other through a SERVICE BINDING and through nothing else. A binding is a value only
92
- * the host holds, so only the host can state this.
93
- *
94
- * It replaces the default entirely — signing included, since a host that builds its
95
- * own transport is the one that knows what to put on the wire.
96
- */
32
+ /** Who performs an outgoing call, when the default cannot. */
97
33
  remoteTransport?: (url: string) => Transport;
98
34
  }
99
35
 
@@ -113,15 +49,7 @@ export function configureFougere(config: FougereServerConfig) {
113
49
  _appPromise = null;
114
50
  }
115
51
 
116
- /**
117
- * Add to what is already stated, instead of replacing it.
118
- *
119
- * A host states its app in PIECES when the pieces are known at different moments: a
120
- * build writes the scan and the config into a generated plugin, and a value only the
121
- * running process holds — a Cloudflare service binding — cannot be written there at all.
122
- * Its dual is `configureFougere`, which replaces; `reloadFougere` depends on that
123
- * replacement, so merging silently would have broken the turn of the ring.
124
- */
52
+ /** Add to what is already stated, instead of replacing it. */
125
53
  export function extendFougere(config: Partial<FougereServerConfig>) {
126
54
  _config = { ..._config, ...config };
127
55
  _appPromise = null;
@@ -135,22 +63,7 @@ export function useFougereApp(): Promise<App> {
135
63
  return _appPromise;
136
64
  }
137
65
 
138
- /**
139
- * Turn the ring: instantiate the app again, then let the previous one go.
140
- *
141
- * This is what "reload" means for anything the config CONSUMED — a value that built
142
- * something cannot move under what it built, so the thing is built again. Its dual is
143
- * `applyConfig`, for values that are merely consulted and need no turn at all.
144
- *
145
- * Every door reaches the app through `useFougereApp()` inside the request it serves and
146
- * none holds it across two, which is what makes the swap invisible: the next request
147
- * lands on the new app whether or not the old one has finished being released.
148
- *
149
- * A call already running finishes on the OLD app: it is drained before being released,
150
- * so nothing has its storage closed underneath it. `timeoutMs` bounds that wait, and a
151
- * drain that runs out REJECTS — the app is left alone rather than released under work,
152
- * because a caller who cannot wait must choose that on purpose.
153
- */
66
+ /** Turn the ring. */
154
67
  export async function reloadFougere(timeoutMs?: number): Promise<App> {
155
68
  const previous = _appPromise;
156
69
  _appPromise = null;
@@ -209,32 +122,16 @@ async function boot(): Promise<App> {
209
122
  // Auto-resolve the data layer from config.db when the user didn't provide a
210
123
  // custom one via configureFougere. The resolution itself lives in @fougere/defaults
211
124
  // — this host must not know which storage package backs `db:`.
212
- let db = _config.db;
213
- let storageFactory = _config.storageFactory;
214
- // The storage's two halves, kept together: its ascent is an extension, its connection
215
- // is not — it is opened here, before the container, so it closes after the container.
216
- let storageMigrate: Extension['up'] | undefined;
217
- let closeStorage: (() => Promise<void>) | undefined;
218
- // Where the rows are, and how to open a transaction there — read from the same storage
219
- // resolution, because a frame's realization is decided by `sources:` and nothing else.
220
- let sourceOf: ((entityName: string) => string) | undefined;
221
- let transacted: CreateAppOptions['transacted'];
222
- if (!storageFactory) {
125
+ let storage = _config.storage;
126
+ if (!storage) {
223
127
  const { resolveStorage } = await import('@fougere/defaults');
224
- const storage = resolveStorage(fileConfig.db as never, (fileConfig as { sources?: unknown }).sources as never);
225
- if (storage.storageFactory) {
226
- log.debug('auto-resolving storage from config.db');
227
- db = storage.db;
228
- storageFactory = storage.storageFactory;
229
- sourceOf = storage.sourceOf;
230
- transacted = storage.transacted as never;
231
- storageMigrate = storage.migrate;
232
- closeStorage = storage.close;
233
- } else {
234
- log.debug('no db declared — falling back to in-memory storage');
235
- storageFactory = createMemoryStorage;
236
- }
128
+ storage = resolveStorage(fileConfig.db as never, (fileConfig as { sources?: unknown }).sources as never);
129
+ log.debug(storage.storageFactory ? 'auto-resolving storage from config.db' : 'no db declared — falling back to in-memory storage');
237
130
  }
131
+ // The storage's two halves, kept together: its ascent is an extension, its connection
132
+ // is not — it is opened here, before the container, so it closes after the container.
133
+ const storageFactory = storage.storageFactory ?? createMemoryStorage;
134
+ const storageMigrate: Extension['up'] | undefined = storage.migrate;
238
135
 
239
136
  // Layer-2 wiring: `remotes: { catalog: 'http://...' }` in fougere.config.ts
240
137
  // is all the user writes — the default transport comes from here.
@@ -267,18 +164,15 @@ async function boot(): Promise<App> {
267
164
  : {}),
268
165
  createContainer,
269
166
  storageFactory,
270
- sourceOf,
271
- transacted,
272
- db,
167
+ sourceOf: storage.sourceOf,
168
+ transacts: storage.transacts,
169
+ transacted: storage.transacted as never,
170
+ db: storage.db,
273
171
  auth: fileConfig.auth,
274
172
  adapters: fileConfig.adapters,
275
173
  remotes: fileConfig.remotes,
276
174
  remoteTransport,
277
- /**
278
- * The whole ascent, one ordered list: tables, then rows, then what the host adds.
279
- * A host wanting its OWN seeding declares `{ name: 'seeds', … }` and replaces that
280
- * member — it no longer has to claim everything after the boot to get it.
281
- */
175
+ /** The whole ascent, one ordered list. */
282
176
  extensions: [
283
177
  // The slot is declared even when this host resolved no storage — a host that resolved
284
178
  // its own (the Nitro plugin does, for its bundler) then REPLACES this member in place
@@ -290,7 +184,7 @@ async function boot(): Promise<App> {
290
184
  // Opened before the container, so released after it. Never wired here until now:
291
185
  // this host boots the storage and no host closed one, which is what made a reload
292
186
  // leak the pool of every app it discarded.
293
- onDispose: closeStorage,
187
+ onDispose: storage.close,
294
188
  });
295
189
 
296
190
  log.info(`ascent: ${app.extensions().join(' → ') || 'nothing declared'}`);