@fougere/app 0.5.0-alpha.1 → 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.
- package/dist/auth.d.ts +1 -7
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js.map +1 -1
- package/dist/boot.d.ts +14 -96
- package/dist/boot.d.ts.map +1 -1
- package/dist/boot.js +19 -217
- package/dist/boot.js.map +1 -1
- package/dist/client.d.ts +5 -24
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +6 -32
- package/dist/client.js.map +1 -1
- package/dist/express.d.ts +2 -12
- package/dist/express.d.ts.map +1 -1
- package/dist/express.js +4 -52
- package/dist/express.js.map +1 -1
- package/dist/form.d.ts +11 -56
- package/dist/form.d.ts.map +1 -1
- package/dist/form.js +15 -33
- package/dist/form.js.map +1 -1
- package/dist/graphql.d.ts +2 -28
- package/dist/graphql.d.ts.map +1 -1
- package/dist/graphql.js +1 -6
- package/dist/graphql.js.map +1 -1
- package/dist/index.d.ts +3 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -12
- package/dist/index.js.map +1 -1
- package/dist/rest.d.ts +2 -16
- package/dist/rest.d.ts.map +1 -1
- package/dist/rest.js +4 -34
- package/dist/rest.js.map +1 -1
- package/dist/serve.d.ts +10 -57
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +12 -55
- package/dist/serve.js.map +1 -1
- package/dist/session.d.ts +2 -7
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +2 -7
- package/dist/session.js.map +1 -1
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +1 -11
- package/dist/state.js.map +1 -1
- package/dist/web.d.ts +3 -19
- package/dist/web.d.ts.map +1 -1
- package/dist/web.js +4 -32
- package/dist/web.js.map +1 -1
- package/package.json +11 -10
- package/src/auth.ts +1 -7
- package/src/boot.ts +31 -260
- package/src/client.ts +7 -33
- package/src/express.ts +4 -52
- package/src/form.ts +20 -73
- package/src/graphql.ts +2 -28
- package/src/index.ts +4 -12
- package/src/rest.ts +4 -34
- package/src/serve.ts +13 -60
- package/src/session.ts +2 -7
- package/src/state.ts +1 -11
- package/src/web.ts +4 -32
package/dist/express.d.ts
CHANGED
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
type Next = (err?: unknown) => void;
|
|
2
2
|
export type ExpressMiddleware = (req: any, res: any, next: Next) => void;
|
|
3
|
-
/**
|
|
4
|
-
* The call envelope, at `/_fougere/call` — the door the browser primitives use.
|
|
5
|
-
*
|
|
6
|
-
* Mounted with `app.use()`, Express strips nothing, so the path still carries the
|
|
7
|
-
* audience segment (`/_fougere/call/public`) that `surfaceOf` reads.
|
|
8
|
-
*/
|
|
3
|
+
/** The call envelope, at `/_fougere/call` — the door the browser primitives use. */
|
|
9
4
|
export declare function fougereCall(mountPath?: string): ExpressMiddleware;
|
|
10
5
|
/** The session view, at `/_fougere/session`. */
|
|
11
6
|
export declare function fougereSession(mountPath?: string): ExpressMiddleware;
|
|
12
|
-
/**
|
|
13
|
-
* The REST projection, under `/api` by default.
|
|
14
|
-
*
|
|
15
|
-
* A path this app does not serve calls `next()` — so an app's own `/api/health` keeps
|
|
16
|
-
* answering whether it was registered before or after this middleware.
|
|
17
|
-
*/
|
|
7
|
+
/** The REST projection, under `/api` by default. */
|
|
18
8
|
export declare function fougereRest(mountPath?: string): ExpressMiddleware;
|
|
19
9
|
/** GraphQL, at `/graphql` by default. Declines when the app declares no such adapter. */
|
|
20
10
|
export declare function fougereGraphQL(mountPath?: string): ExpressMiddleware;
|
package/dist/express.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"express.d.ts","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"AA2BA,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AACpC,MAAM,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;AA+BzE,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,SAAS,SAAmB,GAAG,iBAAiB,CAqB3E;AAED,gDAAgD;AAChD,wBAAgB,cAAc,CAAC,SAAS,SAAsB,GAAG,iBAAiB,CAKjF;AAED,oDAAoD;AACpD,wBAAgB,WAAW,CAAC,SAAS,SAAS,GAAG,iBAAiB,CA4BjE;AAED,yFAAyF;AACzF,wBAAgB,cAAc,CAAC,SAAS,SAAa,GAAG,iBAAiB,CAoBxE;AAED;sDACsD;AACtD,wBAAgB,OAAO,IAAI,iBAAiB,CAY3C"}
|
package/dist/express.js
CHANGED
|
@@ -1,48 +1,10 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The doors as Express middlewares — the form an Express app expects.
|
|
3
|
-
*
|
|
4
|
-
* ```ts
|
|
5
|
-
* const app = express();
|
|
6
|
-
* app.use(express.json());
|
|
7
|
-
* app.use(fougere()); // ← one line, like cors() or express.json()
|
|
8
|
-
* ```
|
|
9
|
-
*
|
|
10
|
-
* This replaces an earlier `mountDoors(createExpressRouter(app))`, which was wrong in
|
|
11
|
-
* two ways at once. It handed the app INTO a function instead of adding something to
|
|
12
|
-
* the app, and it made the caller name Express 5's wildcard syntax (`/api/*splat`) —
|
|
13
|
-
* a detail that belongs to the framework, not to its user. Worse, it mounted all
|
|
14
|
-
* three doors together with no way to take two of them.
|
|
15
|
-
*
|
|
16
|
-
* A middleware fixes both by construction, because Express already says WHERE:
|
|
17
|
-
*
|
|
18
|
-
* ```ts
|
|
19
|
-
* app.use(fougere()); // the three doors, at the paths the client knows
|
|
20
|
-
* app.use('/admin', fougereRest()); // REST only, wherever you want it
|
|
21
|
-
* ```
|
|
22
|
-
*
|
|
23
|
-
* And `next()` is the passthrough these doors were already imitating: `serveRest`
|
|
24
|
-
* answers `{ kind: 'pass' }` for a path it does not serve, which is exactly what
|
|
25
|
-
* Express means by calling the next handler. The middleware stops inventing it.
|
|
26
|
-
*
|
|
27
|
-
* The names mirror `@fougere/app/web` on purpose — same doors, host-shaped. `/web`
|
|
28
|
-
* gives you `Request` → `Response` handlers; this gives you middlewares.
|
|
29
|
-
*
|
|
30
|
-
* Nothing here imports express: the shapes are structural, so the package keeps its
|
|
31
|
-
* dependency list and a test can hand it a plain object.
|
|
32
|
-
*/
|
|
1
|
+
/** The doors as Express middlewares — the form an Express app expects. */
|
|
33
2
|
import { readExpressBody } from '@fougere/http';
|
|
34
3
|
import { serveRest, serveRpc, rpcParseError } from './serve.js';
|
|
35
4
|
import { serveGraphQL } from './graphql.js';
|
|
36
5
|
import { sessionViewOf } from './session.js';
|
|
37
6
|
import { useFougereApp } from './boot.js';
|
|
38
|
-
/**
|
|
39
|
-
* Who the caller is, from what ran before.
|
|
40
|
-
*
|
|
41
|
-
* Express has no ambient request, so an app that resolves its own session says so by
|
|
42
|
-
* putting it on the request — `req.fougereState`, or a bare `req.user`, which is what
|
|
43
|
-
* passport and most middlewares already set. Nothing is taken from the payload: the
|
|
44
|
-
* browser sits outside the topology.
|
|
45
|
-
*/
|
|
7
|
+
/** Who the caller is, from what ran before. */
|
|
46
8
|
function stateOf(req) {
|
|
47
9
|
if (req.fougereState)
|
|
48
10
|
return req.fougereState;
|
|
@@ -66,12 +28,7 @@ function fail(res, next, err) {
|
|
|
66
28
|
}
|
|
67
29
|
next(err);
|
|
68
30
|
}
|
|
69
|
-
/**
|
|
70
|
-
* The call envelope, at `/_fougere/call` — the door the browser primitives use.
|
|
71
|
-
*
|
|
72
|
-
* Mounted with `app.use()`, Express strips nothing, so the path still carries the
|
|
73
|
-
* audience segment (`/_fougere/call/public`) that `surfaceOf` reads.
|
|
74
|
-
*/
|
|
31
|
+
/** The call envelope, at `/_fougere/call` — the door the browser primitives use. */
|
|
75
32
|
export function fougereCall(mountPath = '/_fougere/call') {
|
|
76
33
|
return (req, res, next) => {
|
|
77
34
|
const path = pathOf(req);
|
|
@@ -104,12 +61,7 @@ export function fougereSession(mountPath = '/_fougere/session') {
|
|
|
104
61
|
res.status(200).json(sessionViewOf(stateOf(req)));
|
|
105
62
|
};
|
|
106
63
|
}
|
|
107
|
-
/**
|
|
108
|
-
* The REST projection, under `/api` by default.
|
|
109
|
-
*
|
|
110
|
-
* A path this app does not serve calls `next()` — so an app's own `/api/health` keeps
|
|
111
|
-
* answering whether it was registered before or after this middleware.
|
|
112
|
-
*/
|
|
64
|
+
/** The REST projection, under `/api` by default. */
|
|
113
65
|
export function fougereRest(mountPath = '/api') {
|
|
114
66
|
return (req, res, next) => {
|
|
115
67
|
const path = pathOf(req);
|
package/dist/express.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"express.js","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"express.js","sourceRoot":"","sources":["../src/express.ts"],"names":[],"mappings":"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"}
|
package/dist/form.d.ts
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import type { SchemaView, ValidationError } from '@fougere/schema';
|
|
2
|
-
/**
|
|
3
|
-
* What an entity class exposes to a form — the schema statics it already has.
|
|
4
|
-
*
|
|
5
|
-
* `SchemaView` and the real `Field`, not a local re-description of the axes: this file
|
|
6
|
-
* used to declare its own `FieldLike` with `shape?` optional, so it kept judging by a
|
|
7
|
-
* looser contract than the schema's own and would never have seen `shape` become
|
|
8
|
-
* required.
|
|
9
|
-
*/
|
|
2
|
+
/** What an entity class exposes to a form — the schema statics it already has. */
|
|
10
3
|
export type FormEntity = SchemaView;
|
|
11
4
|
export interface FormField {
|
|
12
5
|
name: string;
|
|
@@ -20,28 +13,8 @@ export interface FormField {
|
|
|
20
13
|
/** Enum values, when control is 'select'. */
|
|
21
14
|
options?: string[];
|
|
22
15
|
/**
|
|
23
|
-
* What the browser enforces, under the names it already knows — spread this on the
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* The shape holds `minLength`/`maximum`/`pattern`; a browser holds `minlength`/
|
|
27
|
-
* `max`/`pattern` and enforces them with no JavaScript at all. Carrying them here
|
|
28
|
-
* is a projection, not a second rule: the judge reads the same shape, and a form
|
|
29
|
-
* that ignores these still gets the same verdict — it just gets it later, and a
|
|
30
|
-
* screen reader never gets it at all.
|
|
31
|
-
*
|
|
32
|
-
* `type` is part of the contract, not decoration: `email` and `url` are formats the
|
|
33
|
-
* shape states and the browser checks live, per field, as one types. A page writing
|
|
34
|
-
* `type="email"` by hand is spelling a second time what the card already said.
|
|
35
|
-
*
|
|
36
|
-
* Three deliberate absences, each one a place where the attribute would mean
|
|
37
|
-
* something the shape does not say:
|
|
38
|
-
* - a `date` field gets no `type` — neither `date` nor `datetime-local` produces the
|
|
39
|
-
* RFC 3339 string a `date-time` shape judges, so the browser would accept what the
|
|
40
|
-
* judge refuses;
|
|
41
|
-
* - `select` and `boolean` are not inputs — the page picks the widget, `control` says
|
|
42
|
-
* which;
|
|
43
|
-
* - a required `boolean` gets no `required` — on a checkbox that attribute means
|
|
44
|
-
* "must be CHECKED", where the shape only says the value must be supplied.
|
|
16
|
+
* What the browser enforces, under the names it already knows — spread this on the input and the
|
|
17
|
+
* page states no rule of its own.
|
|
45
18
|
*/
|
|
46
19
|
attrs?: {
|
|
47
20
|
type?: 'text' | 'email' | 'url' | 'number';
|
|
@@ -52,18 +25,10 @@ export interface FormField {
|
|
|
52
25
|
max?: number;
|
|
53
26
|
pattern?: string;
|
|
54
27
|
};
|
|
55
|
-
/**
|
|
56
|
-
* The value the field is born with — the literal its `lifecycle.create` rule names.
|
|
57
|
-
* Present so the form can SHOW what is about to be written; the storage realizes it
|
|
58
|
-
* either way, so a form that ignores this still produces the same row.
|
|
59
|
-
*/
|
|
28
|
+
/** The value the field is born with — the literal its `lifecycle.create` rule names. */
|
|
60
29
|
default?: unknown;
|
|
61
30
|
}
|
|
62
|
-
/**
|
|
63
|
-
* The fields a create form is made of: membership from the io projection
|
|
64
|
-
* (`Visibility.input` — what a client may supply), requiredness from the
|
|
65
|
-
* lifecycle axis (any create rule makes absence legal).
|
|
66
|
-
*/
|
|
31
|
+
/** The fields a create form is made of. */
|
|
67
32
|
export declare function formFieldsOf(entity: FormEntity, entityKey: string): FormField[];
|
|
68
33
|
export interface TableColumn {
|
|
69
34
|
name: string;
|
|
@@ -75,27 +40,17 @@ export interface TableColumn {
|
|
|
75
40
|
/** The same key a form uses for the same field — one convention, two projections. */
|
|
76
41
|
labelKey: string;
|
|
77
42
|
label: string;
|
|
78
|
-
/**
|
|
79
|
-
* The entity a `link` points at, under the key its door is named by. Always present on a
|
|
80
|
-
* reference: the card carries the target's name, and a card rebuilt with no sibling to
|
|
81
|
-
* resolve to keeps it as a stand-in rather than losing it.
|
|
82
|
-
*/
|
|
43
|
+
/** The entity a `link` points at, under the key its door is named by. */
|
|
83
44
|
to?: string;
|
|
84
45
|
}
|
|
85
|
-
/**
|
|
86
|
-
* The columns a list is made of: membership from the io projection (`Visibility.output` — what
|
|
87
|
-
* may leave), minus collections, because a cell holds one value and a `many()` is a page.
|
|
88
|
-
*
|
|
89
|
-
* Which column identifies the row is NOT answered here — `FieldSet.primary` answers it for a
|
|
90
|
-
* shape, and its own doc records what five private copies of that loop cost.
|
|
91
|
-
*/
|
|
46
|
+
/** The columns a list is made of. */
|
|
92
47
|
export declare function tableColumnsOf(entity: FormEntity, entityKey: string): TableColumn[];
|
|
93
48
|
/**
|
|
94
|
-
* The wire body of the form's values — an empty control is an absent value
|
|
95
|
-
*
|
|
96
|
-
*
|
|
49
|
+
* The wire body of the form's values — an empty control is an absent value at the create boundary
|
|
50
|
+
* (absence is validated by the lifecycle axis, an empty string would be validated as a present bad
|
|
51
|
+
* value).
|
|
97
52
|
*/
|
|
98
53
|
export declare function payloadOf(values: Record<string, unknown>): Record<string, unknown>;
|
|
99
|
-
/** Index
|
|
54
|
+
/** Index validator errors by field — local validator and remote validator share this shape. */
|
|
100
55
|
export declare function errorsByField(errors: ValidationError[]): Record<string, string>;
|
|
101
56
|
//# sourceMappingURL=form.d.ts.map
|
package/dist/form.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAS,UAAU,EAAE,eAAe,EAAoB,MAAM,iBAAiB,CAAC;AAE5F,kFAAkF;AAClF,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC;AAOpC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC7E,QAAQ,EAAE,OAAO,CAAC;IAClB,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE;QACN,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;QAC3C,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,wFAAwF;IACxF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA6DD,2CAA2C;AAC3C,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,CAkB/E;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IACjE,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAaD,qCAAqC;AACrC,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,WAAW,EAAE,CAYnF;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIlF;AAED,+FAA+F;AAC/F,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAO/E"}
|
package/dist/form.js
CHANGED
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
import { Lifecycle } from '@fougere/schema';
|
|
2
2
|
/**
|
|
3
|
-
* Form contract, pure part — derives what a create/edit form is made of
|
|
4
|
-
*
|
|
5
|
-
* usable by any renderer (the page owns the widgets).
|
|
6
|
-
*/
|
|
7
|
-
import { Anatomy, lowerFirst, Role, Visibility } from '@fougere/schema';
|
|
8
|
-
/**
|
|
9
|
-
* The literal a field is born with, when it declares one.
|
|
10
|
-
*
|
|
11
|
-
* `text({ default: 'x' })` and `oneOf('a', 'b', { default: 'a' })` both compile to
|
|
12
|
-
* `lifecycle.create = { value }` — the create rule that answers the field's absence.
|
|
13
|
-
* The other create rules ('now', { generate }, 'optional') name no literal: their value
|
|
14
|
-
* is decided at write time, so a form has nothing to show for them.
|
|
3
|
+
* Form contract, pure part — derives what a create/edit form is made of from the entity's field
|
|
4
|
+
* axes.
|
|
15
5
|
*/
|
|
6
|
+
import { Shapes, lowerFirst, Role, Visibility } from '@fougere/schema';
|
|
7
|
+
/** The literal a field is born with, when it declares one. */
|
|
16
8
|
function defaultOf(field) {
|
|
17
9
|
return Lifecycle.of(field).literal?.value;
|
|
18
10
|
}
|
|
@@ -22,7 +14,7 @@ function baseType(type) {
|
|
|
22
14
|
return type.find((t) => t !== 'null') ?? 'string';
|
|
23
15
|
return type ?? 'string';
|
|
24
16
|
}
|
|
25
|
-
/** The formats a browser has an input type for — the rest stay `text`,
|
|
17
|
+
/** The formats a browser has an input type for — the rest stay `text`, validated later. */
|
|
26
18
|
const CONTROL_BY_FORMAT = {
|
|
27
19
|
'date-time': 'date',
|
|
28
20
|
email: 'email',
|
|
@@ -32,7 +24,7 @@ function controlOf(field) {
|
|
|
32
24
|
// Through `anatomy`, never `shape.type` directly: the nullable form is the `[T,'null']`
|
|
33
25
|
// union, which a direct comparison misses in silence. It is also what narrows the shape
|
|
34
26
|
// union, so `enum` and `format` are only reachable on the branches that carry them.
|
|
35
|
-
const base =
|
|
27
|
+
const base = Shapes.of(field.shape).base;
|
|
36
28
|
if (base?.type === 'string' && base.enum?.length)
|
|
37
29
|
return 'select';
|
|
38
30
|
if (base?.type === 'number' || base?.type === 'integer')
|
|
@@ -45,14 +37,14 @@ function controlOf(field) {
|
|
|
45
37
|
}
|
|
46
38
|
/** A closed set's members, when the shape declares one — `oneOf('draft','live')`. */
|
|
47
39
|
function enumOf(field) {
|
|
48
|
-
const base =
|
|
40
|
+
const base = Shapes.of(field.shape).base;
|
|
49
41
|
return base?.type === 'string' ? base.enum : undefined;
|
|
50
42
|
}
|
|
51
43
|
/** Controls that ARE an `<input type>` — see the two absences on {@link FormField.attrs}. */
|
|
52
44
|
const INPUT_TYPES = new Set(['text', 'email', 'url', 'number']);
|
|
53
45
|
/** The shape's bounds, under the names a browser already enforces. */
|
|
54
46
|
function attrsOf(field, control, required) {
|
|
55
|
-
const base =
|
|
47
|
+
const base = Shapes.of(field.shape).base;
|
|
56
48
|
const text = base?.type === 'string' ? base : undefined;
|
|
57
49
|
const numeric = base?.type === 'number' || base?.type === 'integer' ? base : undefined;
|
|
58
50
|
const attrs = {
|
|
@@ -73,11 +65,7 @@ function attrsOf(field, control, required) {
|
|
|
73
65
|
function labelOf(name, entityKey) {
|
|
74
66
|
return { labelKey: `${entityKey}.${name}`, label: name.charAt(0).toUpperCase() + name.slice(1) };
|
|
75
67
|
}
|
|
76
|
-
/**
|
|
77
|
-
* The fields a create form is made of: membership from the io projection
|
|
78
|
-
* (`Visibility.input` — what a client may supply), requiredness from the
|
|
79
|
-
* lifecycle axis (any create rule makes absence legal).
|
|
80
|
-
*/
|
|
68
|
+
/** The fields a create form is made of. */
|
|
81
69
|
export function formFieldsOf(entity, entityKey) {
|
|
82
70
|
return Object.entries(Visibility.of(entity.getFields()).input).map(([name, field]) => {
|
|
83
71
|
const f = field;
|
|
@@ -101,7 +89,7 @@ export function formFieldsOf(entity, entityKey) {
|
|
|
101
89
|
function renderOf(field) {
|
|
102
90
|
if (Role.of(field).isReference)
|
|
103
91
|
return 'link';
|
|
104
|
-
const base =
|
|
92
|
+
const base = Shapes.of(field.shape).base;
|
|
105
93
|
if (base?.type === 'number' || base?.type === 'integer')
|
|
106
94
|
return 'number';
|
|
107
95
|
if (base?.type === 'boolean')
|
|
@@ -112,13 +100,7 @@ function renderOf(field) {
|
|
|
112
100
|
return 'date';
|
|
113
101
|
return 'text';
|
|
114
102
|
}
|
|
115
|
-
/**
|
|
116
|
-
* The columns a list is made of: membership from the io projection (`Visibility.output` — what
|
|
117
|
-
* may leave), minus collections, because a cell holds one value and a `many()` is a page.
|
|
118
|
-
*
|
|
119
|
-
* Which column identifies the row is NOT answered here — `FieldSet.primary` answers it for a
|
|
120
|
-
* shape, and its own doc records what five private copies of that loop cost.
|
|
121
|
-
*/
|
|
103
|
+
/** The columns a list is made of. */
|
|
122
104
|
export function tableColumnsOf(entity, entityKey) {
|
|
123
105
|
return Object.entries(Visibility.of(entity.getFields()).output)
|
|
124
106
|
.filter(([, field]) => !Role.of(field).isCollection)
|
|
@@ -133,14 +115,14 @@ export function tableColumnsOf(entity, entityKey) {
|
|
|
133
115
|
});
|
|
134
116
|
}
|
|
135
117
|
/**
|
|
136
|
-
* The wire body of the form's values — an empty control is an absent value
|
|
137
|
-
*
|
|
138
|
-
*
|
|
118
|
+
* The wire body of the form's values — an empty control is an absent value at the create boundary
|
|
119
|
+
* (absence is validated by the lifecycle axis, an empty string would be validated as a present bad
|
|
120
|
+
* value).
|
|
139
121
|
*/
|
|
140
122
|
export function payloadOf(values) {
|
|
141
123
|
return Object.fromEntries(Object.entries(values).filter(([, v]) => v !== undefined && v !== ''));
|
|
142
124
|
}
|
|
143
|
-
/** Index
|
|
125
|
+
/** Index validator errors by field — local validator and remote validator share this shape. */
|
|
144
126
|
export function errorsByField(errors) {
|
|
145
127
|
const byField = {};
|
|
146
128
|
for (const err of errors) {
|
package/dist/form.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.js","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C
|
|
1
|
+
{"version":3,"file":"form.js","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"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"}
|
package/dist/graphql.d.ts
CHANGED
|
@@ -1,25 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The GraphQL door — declared like the others, mounted like the others.
|
|
3
|
-
*
|
|
4
|
-
* Until now GraphQL was the odd one out: `adapters: { graphql: true }` was
|
|
5
|
-
* declarable and nothing read it, while an app that wanted a schema wrote fifteen
|
|
6
|
-
* lines of its own (a Pothos builder, a query type, a mutation type, `registerAll`,
|
|
7
|
-
* then `registerGraphQL` on a router). Every one of those lines is convention —
|
|
8
|
-
* there is no decision in them — so the app declaring the adapter is enough.
|
|
9
|
-
*
|
|
10
|
-
* The package is imported LAZILY, the same shape `db: 'sqlite'` uses (`resolveStorage`
|
|
11
|
-
* pulls `@fougere/adapter-sql` only when a database is declared). A schema builder is
|
|
12
|
-
* heavy and most apps serve none, so a host must not carry one to find out. Declaring
|
|
13
|
-
* the adapter without installing it is refused by name, the way an unresolvable dialect is.
|
|
14
|
-
*
|
|
15
|
-
* This file used to BUILD the schema — a Pothos builder, `registerAll`, then `graphql()`
|
|
16
|
-
* — which made it the only schema constructor in the repo, in the package least entitled
|
|
17
|
-
* to be one. Two costs, one cause: the derivation sat away from the adapter whose job it
|
|
18
|
-
* is, and `graphql` guards its types with `instanceOf`, so a schema built on one side of
|
|
19
|
-
* the package boundary was refused on the other as coming *"from another module or
|
|
20
|
-
* realm"*. Both are gone: `@fougere/adapter-graphql` derives and executes, this door
|
|
21
|
-
* translates the result into an `Outcome`.
|
|
22
|
-
*/
|
|
1
|
+
/** The GraphQL door — declared like the others, mounted like the others. */
|
|
23
2
|
import type { App } from '@fougere/core';
|
|
24
3
|
import type { Outcome } from './serve.js';
|
|
25
4
|
/** What a GraphQL request carries, whatever host read it. */
|
|
@@ -31,11 +10,6 @@ export interface GraphQLRequest {
|
|
|
31
10
|
surface?: string;
|
|
32
11
|
state: Record<string, unknown>;
|
|
33
12
|
}
|
|
34
|
-
/**
|
|
35
|
-
* Execute a GraphQL request against the app's own operations.
|
|
36
|
-
*
|
|
37
|
-
* `pass` when the app declares no GraphQL adapter — the same answer `serveRest` gives,
|
|
38
|
-
* so a host that mounted the door takes nothing away from an app that did not ask for it.
|
|
39
|
-
*/
|
|
13
|
+
/** Execute a GraphQL request against the app's own operations. */
|
|
40
14
|
export declare function serveGraphQL(app: App, request: GraphQLRequest): Promise<Outcome>;
|
|
41
15
|
//# sourceMappingURL=graphql.d.ts.map
|
package/dist/graphql.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graphql.d.ts","sourceRoot":"","sources":["../src/graphql.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"graphql.d.ts","sourceRoot":"","sources":["../src/graphql.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,6DAA6D;AAC7D,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAyBD,kEAAkE;AAClE,wBAAsB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAoBtF"}
|
package/dist/graphql.js
CHANGED
|
@@ -10,12 +10,7 @@ async function executor() {
|
|
|
10
10
|
'that out.', { cause });
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
-
/**
|
|
14
|
-
* Execute a GraphQL request against the app's own operations.
|
|
15
|
-
*
|
|
16
|
-
* `pass` when the app declares no GraphQL adapter — the same answer `serveRest` gives,
|
|
17
|
-
* so a host that mounted the door takes nothing away from an app that did not ask for it.
|
|
18
|
-
*/
|
|
13
|
+
/** Execute a GraphQL request against the app's own operations. */
|
|
19
14
|
export async function serveGraphQL(app, request) {
|
|
20
15
|
if (!app.adapters?.graphql)
|
|
21
16
|
return { kind: 'pass' };
|
package/dist/graphql.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graphql.js","sourceRoot":"","sources":["../src/graphql.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"graphql.js","sourceRoot":"","sources":["../src/graphql.ts"],"names":[],"mappings":"AAsBA,KAAK,UAAU,QAAQ;IACrB,IAAI,CAAC;QACH,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;QAC/D,OAAO,SAAiC,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,iFAAiF;YACjF,kFAAkF;YAClF,kFAAkF;YAClF,WAAW,EACX,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;AACH,CAAC;AAED,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAQ,EAAE,OAAuB;IAClE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAEpD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,EAAE,CAAC;IAC5E,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,QAAQ,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE;QAClC,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,oFAAoF;QACpF,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC,CAAC;IAEH,qFAAqF;IACrF,2DAA2D;IAC3D,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAiC,EAAE,CAAC;AAC9E,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Two adapters read this package: `@fougere/nuxt` and `@fougere/next`. Between
|
|
5
|
-
* them they share the boot, the three doors' decisions, the REST table, the form
|
|
6
|
-
* contract and the session view; what they do NOT share is how a request arrives,
|
|
7
|
-
* how routes are mounted, and how a value becomes reactive.
|
|
8
|
-
*
|
|
9
|
-
* The root entry pulls in the boot, which reads the filesystem — client code wants
|
|
10
|
-
* `@fougere/app/client`.
|
|
11
|
-
*/
|
|
12
|
-
export { configureFougere, extendFougere, useFougereApp, reloadFougere, createMemoryOrm, type FougereServerConfig, } from './boot.js';
|
|
1
|
+
/** `@fougere/app` — what an app host needs and what no host owns. */
|
|
2
|
+
export { configureFougere, extendFougere, useFougereApp, reloadFougere, type FougereServerConfig, } from './boot.js';
|
|
13
3
|
export { useFougereAuth } from './auth.js';
|
|
14
4
|
export { tableOf, matchRoute, type Matchable, type RouteMatch, } from './rest.js';
|
|
15
5
|
export { serveRest, shapeRest, serveRpc, surfaceOf, rpcParseError, invokeOn, type DoorRequest, type Outcome, } from './serve.js';
|
|
@@ -17,4 +7,5 @@ export { formFieldsOf, tableColumnsOf, payloadOf, errorsByField, type FormEntity
|
|
|
17
7
|
export { sessionViewOf, type SessionView } from './session.js';
|
|
18
8
|
export { stateFor } from './state.js';
|
|
19
9
|
export { serveGraphQL, type GraphQLRequest } from './graphql.js';
|
|
10
|
+
export { createMemoryStorage } from '@fougere/adapter-memory';
|
|
20
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,aAAa,EACb,KAAK,mBAAmB,GACzB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,EACL,OAAO,EACP,UAAU,EACV,KAAK,SAAS,EACd,KAAK,UAAU,GAChB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,SAAS,EACT,SAAS,EACT,QAAQ,EACR,SAAS,EACT,aAAa,EACb,QAAQ,EACR,KAAK,WAAW,EAChB,KAAK,OAAO,GACb,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,YAAY,EACZ,cAAc,EACd,SAAS,EACT,aAAa,EACb,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,WAAW,GACjB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAE/D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAGjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Two adapters read this package: `@fougere/nuxt` and `@fougere/next`. Between
|
|
5
|
-
* them they share the boot, the three doors' decisions, the REST table, the form
|
|
6
|
-
* contract and the session view; what they do NOT share is how a request arrives,
|
|
7
|
-
* how routes are mounted, and how a value becomes reactive.
|
|
8
|
-
*
|
|
9
|
-
* The root entry pulls in the boot, which reads the filesystem — client code wants
|
|
10
|
-
* `@fougere/app/client`.
|
|
11
|
-
*/
|
|
12
|
-
export { configureFougere, extendFougere, useFougereApp, reloadFougere, createMemoryOrm, } from './boot.js';
|
|
1
|
+
/** `@fougere/app` — what an app host needs and what no host owns. */
|
|
2
|
+
export { configureFougere, extendFougere, useFougereApp, reloadFougere, } from './boot.js';
|
|
13
3
|
export { useFougereAuth } from './auth.js';
|
|
14
4
|
export { tableOf, matchRoute, } from './rest.js';
|
|
15
5
|
export { serveRest, shapeRest, serveRpc, surfaceOf, rpcParseError, invokeOn, } from './serve.js';
|
|
@@ -17,4 +7,6 @@ export { formFieldsOf, tableColumnsOf, payloadOf, errorsByField, } from './form.
|
|
|
17
7
|
export { sessionViewOf } from './session.js';
|
|
18
8
|
export { stateFor } from './state.js';
|
|
19
9
|
export { serveGraphQL } from './graphql.js';
|
|
10
|
+
// Re-exported where every host already looks for it; it lives in its own adapter now.
|
|
11
|
+
export { createMemoryStorage } from '@fougere/adapter-memory';
|
|
20
12
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,aAAa,GAEd,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,EACL,OAAO,EACP,UAAU,GAGX,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,SAAS,EACT,SAAS,EACT,QAAQ,EACR,SAAS,EACT,aAAa,EACb,QAAQ,GAGT,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,YAAY,EACZ,cAAc,EACd,SAAS,EACT,aAAa,GAId,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,aAAa,EAAoB,MAAM,cAAc,CAAC;AAE/D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,YAAY,EAAuB,MAAM,cAAc,CAAC;AAEjE,sFAAsF;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/rest.d.ts
CHANGED
|
@@ -20,22 +20,8 @@ export type RouteMatch = {
|
|
|
20
20
|
}
|
|
21
21
|
/** Not a Fougère path at all: the app's own `/api/*` handlers must still see it. */
|
|
22
22
|
| null;
|
|
23
|
-
/**
|
|
24
|
-
* The table, per frond.
|
|
25
|
-
*
|
|
26
|
-
* `generateRoutes` prefixes every path the same way, while this door addresses a frond by
|
|
27
|
-
* name (`/api/{frond}/{plural}`) — so it runs once per frond, each with its own prefix and
|
|
28
|
-
* a filter naming it. That frond loop is the only thing this file knows that `schema-rest`
|
|
29
|
-
* does not; the verbs, the paths and the membership rule all come from there.
|
|
30
|
-
*/
|
|
23
|
+
/** The table, per frond. */
|
|
31
24
|
export declare function tableOf(app: App): Matchable[];
|
|
32
|
-
/**
|
|
33
|
-
* Path first, method second — a router's order, and what makes a 405 possible at all.
|
|
34
|
-
*
|
|
35
|
-
* The order matters where the two overlap: `/posts/publish` and `/posts/:id` both accept
|
|
36
|
-
* `GET /posts/publish`. Taking the most specific path first means the answer is "that verb
|
|
37
|
-
* is refused here", not `findById('publish')` — and never `publish()`, which is what this
|
|
38
|
-
* door used to do with the caller's session cookie attached.
|
|
39
|
-
*/
|
|
25
|
+
/** Path first, method second — a router's order, and what makes a 405 possible at all. */
|
|
40
26
|
export declare function matchRoute(table: Matchable[], method: string, segments: string[]): RouteMatch;
|
|
41
27
|
//# sourceMappingURL=rest.d.ts.map
|
package/dist/rest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest.d.ts","sourceRoot":"","sources":["../src/rest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rest.d.ts","sourceRoot":"","sources":["../src/rest.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAEzC,6EAA6E;AAC7E,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE;AACrE,mFAAmF;GACjF;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE;AACjD,oFAAoF;GAClF,IAAI,CAAC;AAMT,4BAA4B;AAC5B,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,SAAS,EAAE,CAmB7C;AAuBD,0FAA0F;AAC1F,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,CAkB7F"}
|
package/dist/rest.js
CHANGED
|
@@ -1,24 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The REST table this app serves, and the rule that matches a request against it.
|
|
3
|
-
*
|
|
4
|
-
* Separated from the h3 handler on purpose: this file holds the whole of what the door
|
|
5
|
-
* DECIDES — which operation a verb and a path name — while `api/crud.ts` only translates
|
|
6
|
-
* that decision into h3. The rule was previously inline, untested, and had drifted into a
|
|
7
|
-
* second REST projection that answered differently from `schema-rest` on all three counts
|
|
8
|
-
* (verb, path, exposure).
|
|
9
|
-
*/
|
|
1
|
+
/** The REST table this app serves, and the rule that matches a request against it. */
|
|
10
2
|
import { generateRoutes } from '@fougere/adapter-rest';
|
|
11
3
|
// Keyed on the app, which `useFougereApp` memoizes — the table derives from the boot, so
|
|
12
4
|
// it changes exactly when the app does.
|
|
13
5
|
const tables = new WeakMap();
|
|
14
|
-
/**
|
|
15
|
-
* The table, per frond.
|
|
16
|
-
*
|
|
17
|
-
* `generateRoutes` prefixes every path the same way, while this door addresses a frond by
|
|
18
|
-
* name (`/api/{frond}/{plural}`) — so it runs once per frond, each with its own prefix and
|
|
19
|
-
* a filter naming it. That frond loop is the only thing this file knows that `schema-rest`
|
|
20
|
-
* does not; the verbs, the paths and the membership rule all come from there.
|
|
21
|
-
*/
|
|
6
|
+
/** The table, per frond. */
|
|
22
7
|
export function tableOf(app) {
|
|
23
8
|
const cached = tables.get(app);
|
|
24
9
|
if (cached)
|
|
@@ -54,24 +39,9 @@ function paramsOf(route, segments) {
|
|
|
54
39
|
function openness(route) {
|
|
55
40
|
return route.segments.filter((s) => s.startsWith(':')).length;
|
|
56
41
|
}
|
|
57
|
-
/**
|
|
58
|
-
* Verbs this door accepts in place of the one the table names.
|
|
59
|
-
*
|
|
60
|
-
* `deriveMethod` gives `update` a single verb, PUT, while this door has always served
|
|
61
|
-
* PATCH on it too — and says so (`docs/infra/surfaces`, "PUT · PATCH"). An alias keeps
|
|
62
|
-
* that promise without giving the table a second row: both are mutations on a row, so
|
|
63
|
-
* nothing is widened, and the one thing the table decides — WHICH operation a path names —
|
|
64
|
-
* is still decided there alone.
|
|
65
|
-
*/
|
|
42
|
+
/** Verbs this door accepts in place of the one the table names. */
|
|
66
43
|
const ALIASES = { PATCH: 'PUT' };
|
|
67
|
-
/**
|
|
68
|
-
* Path first, method second — a router's order, and what makes a 405 possible at all.
|
|
69
|
-
*
|
|
70
|
-
* The order matters where the two overlap: `/posts/publish` and `/posts/:id` both accept
|
|
71
|
-
* `GET /posts/publish`. Taking the most specific path first means the answer is "that verb
|
|
72
|
-
* is refused here", not `findById('publish')` — and never `publish()`, which is what this
|
|
73
|
-
* door used to do with the caller's session cookie attached.
|
|
74
|
-
*/
|
|
44
|
+
/** Path first, method second — a router's order, and what makes a 405 possible at all. */
|
|
75
45
|
export function matchRoute(table, method, segments) {
|
|
76
46
|
const matches = table
|
|
77
47
|
.map((route) => ({ route, params: paramsOf(route, segments) }))
|
package/dist/rest.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest.js","sourceRoot":"","sources":["../src/rest.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rest.js","sourceRoot":"","sources":["../src/rest.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAoBvD,yFAAyF;AACzF,wCAAwC;AACxC,MAAM,MAAM,GAAG,IAAI,OAAO,EAAoB,CAAC;AAE/C,4BAA4B;AAC5B,MAAM,UAAU,OAAO,CAAC,GAAQ;IAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CACzC,cAAc,CAAC,GAAG,EAAE;QAClB,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,EAAE;QACxB,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,KAAK,KAAK,CAAC,IAAI;KACzD,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACjB,MAAM,EAAE,KAAK,CAAC,MAAgB;QAC9B,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;QAC/C,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,aAAa,EAAE,KAAK,CAAC,aAAa;KACnC,CAAC,CAAC,CACJ,CAAC;IAEF,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACvB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,6EAA6E;AAC7E,SAAS,QAAQ,CAAC,KAAgB,EAAE,QAAkB;IACpD,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAE3D,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC;QACnC,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC;aACpF,IAAI,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;IAChD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,wEAAwE;AACxE,SAAS,QAAQ,CAAC,KAAgB;IAChC,OAAO,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;AAChE,CAAC;AAED,mEAAmE;AACnE,MAAM,OAAO,GAA2B,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAEzD,0FAA0F;AAC1F,MAAM,UAAU,UAAU,CAAC,KAAkB,EAAE,MAAc,EAAE,QAAkB;IAC/E,MAAM,OAAO,GAAG,KAAK;SAClB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;SAC9D,MAAM,CAAC,CAAC,CAAC,EAA6D,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;IAE/F,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChE,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;IAErE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IAClE,IAAI,OAAO;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;IAEpF,OAAO;QACL,IAAI,EAAE,oBAAoB;QAC1B,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;KAClE,CAAC;AACJ,CAAC"}
|