@loadbare/app 0.9.0 → 0.10.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/README.md +3 -3
- package/dist/build/assemble.d.ts.map +1 -1
- package/dist/build/assemble.js +74 -66
- package/dist/build/assemble.js.map +1 -1
- package/dist/build/expand.d.ts.map +1 -1
- package/dist/build/expand.js +20 -19
- package/dist/build/expand.js.map +1 -1
- package/dist/build/locations.d.ts +2 -3
- package/dist/build/locations.d.ts.map +1 -1
- package/dist/build/locations.js +2 -3
- package/dist/build/locations.js.map +1 -1
- package/dist/build/pages.d.ts +3 -4
- package/dist/build/pages.d.ts.map +1 -1
- package/dist/build/pages.js +3 -4
- package/dist/build/pages.js.map +1 -1
- package/dist/core/lb-constants.d.ts +25 -24
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +95 -168
- package/dist/core/lb-constants.js.map +1 -1
- package/dist/core/lb-types.d.ts +64 -77
- package/dist/core/lb-types.d.ts.map +1 -1
- package/dist/core/lb-types.js +40 -7
- package/dist/core/lb-types.js.map +1 -1
- package/dist/hub/lb-apply.d.ts +47 -37
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +174 -193
- package/dist/hub/lb-apply.js.map +1 -1
- package/dist/hub/lb-hub.browser.d.ts +1 -1
- package/dist/hub/lb-hub.browser.d.ts.map +1 -1
- package/dist/hub/lb-hub.browser.js +411 -449
- package/dist/hub/lb-hub.browser.js.map +1 -1
- package/dist/server/lb-express.d.ts +5 -5
- package/dist/server/lb-express.d.ts.map +1 -1
- package/dist/server/lb-express.js +35 -66
- package/dist/server/lb-express.js.map +1 -1
- package/dist/server/lb-server.d.ts +77 -135
- package/dist/server/lb-server.d.ts.map +1 -1
- package/dist/server/lb-server.js +132 -79
- package/dist/server/lb-server.js.map +1 -1
- package/docs/TECHREF-1.0.md +861 -587
- package/docs/comparison.md +222 -185
- package/docs/prior-art.md +15 -14
- package/docs/reference/builder.md +9 -3
- package/docs/reference/chrome.md +107 -56
- package/docs/reference/custom-elements.md +199 -173
- package/docs/reference/data-binding.md +374 -374
- package/docs/reference/overview.md +12 -10
- package/docs/reference/page-files.md +135 -99
- package/docs/reference/server.md +2 -2
- package/docs/reference/widgets.md +104 -110
- package/docs/roadmap.md +32 -39
- package/docs/terms-of-art.md +57 -0
- package/docs/testing.md +97 -68
- package/docs/theory.md +92 -58
- package/docs/tutorials/010-pages-and-navigation.md +20 -12
- package/docs/tutorials/020-css.md +6 -3
- package/docs/tutorials/030-html-decomposition.md +9 -7
- package/docs/tutorials/040-displaying-data.md +30 -13
- package/docs/tutorials/{050-actions.md → 050-requests.md} +25 -15
- package/docs/tutorials/060-custom-element-code.md +17 -16
- package/docs/tutorials/065-conditional-rendering.md +34 -23
- package/docs/tutorials/070-displaying-a-list.md +29 -21
- package/docs/tutorials/072-inserting-into-a-list.md +24 -16
- package/docs/tutorials/074-deleting-from-a-list.md +9 -7
- package/docs/tutorials/076-updating-a-list-item.md +11 -10
- package/docs/tutorials/080-widget-requests.md +71 -43
- package/docs/tutorials/090-using-widget-libraries.md +22 -22
- package/package.json +1 -1
- package/skills/loadbare-app/SKILL.md +178 -122
- package/skills/loadbare-app/references/TECHREF-1.0.md +861 -587
- package/skills/loadbare-app/references/builder.md +9 -3
- package/skills/loadbare-app/references/chrome.md +107 -56
- package/skills/loadbare-app/references/custom-elements.md +199 -173
- package/skills/loadbare-app/references/data-binding.md +374 -374
- package/skills/loadbare-app/references/overview.md +12 -10
- package/skills/loadbare-app/references/page-files.md +135 -99
- package/skills/loadbare-app/references/server.md +2 -2
- package/skills/loadbare-app/references/widgets.md +104 -110
- package/docs/analysis-accidental-complexity.md +0 -149
- package/docs/analysis-closed-set.md +0 -210
package/dist/core/lb-types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { KIND_ROW, KIND_ROWS } from "./lb-constants.js";
|
|
2
2
|
/**
|
|
3
3
|
* One row: its columns, by name.
|
|
4
4
|
*
|
|
@@ -9,9 +9,9 @@ import { ACTION_ROW_DELETE, ACTION_ROW_INSERT, ACTION_ROW_UPDATE } from "./lb-co
|
|
|
9
9
|
*/
|
|
10
10
|
export type Row = Record<string, unknown>;
|
|
11
11
|
/**
|
|
12
|
-
* Part of a
|
|
12
|
+
* Part of a `rows` query's answer — see docs/reference/server.md, "Queries".
|
|
13
13
|
*
|
|
14
|
-
* Rows named here
|
|
14
|
+
* Rows named here are added or updated, keys in `drop` are removed, and
|
|
15
15
|
* anything unnamed is left alone: its contents, and its place in whatever
|
|
16
16
|
* order the widget is keeping. Add and remove are one result rather than two
|
|
17
17
|
* because the interesting cases are both at once — a row whose sort key
|
|
@@ -22,77 +22,51 @@ export interface Patch {
|
|
|
22
22
|
rows?: Row[];
|
|
23
23
|
drop?: unknown[];
|
|
24
24
|
}
|
|
25
|
+
/** A query's kind, declared by the server and carried by every answer. */
|
|
26
|
+
export type Kind = typeof KIND_ROW | typeof KIND_ROWS;
|
|
25
27
|
/**
|
|
26
|
-
* What a
|
|
27
|
-
*
|
|
28
|
-
* An array is the entire set and therefore also the order: a row whose key
|
|
29
|
-
* is not in it is gone. A Patch disturbs only what it names.
|
|
30
|
-
*
|
|
31
|
-
* `Array.isArray` tells the two apart, which is why no column name has to be
|
|
32
|
-
* reserved to carry a discriminant. A list answering with an object is a
|
|
33
|
-
* patch, because the declaration already said this name answers with rows.
|
|
34
|
-
*/
|
|
35
|
-
export type ListResult = Row[] | Patch;
|
|
36
|
-
export declare function isPatch(result: ListResult): result is Patch;
|
|
37
|
-
/**
|
|
38
|
-
* What any one name answers with. Which of the two it is comes from the
|
|
39
|
-
* query's own declaration, never from inspecting the value.
|
|
28
|
+
* What a `rows` query answers with: all rows, which is also their order, or
|
|
29
|
+
* a patch. `Array.isArray` tells the two apart.
|
|
40
30
|
*/
|
|
41
|
-
export type
|
|
31
|
+
export type RowsResult = Row[] | Patch;
|
|
32
|
+
export declare function isPatch(result: RowsResult): result is Patch;
|
|
33
|
+
/** What any one query answers with, as the application writes it. */
|
|
34
|
+
export type HubResult = Row | RowsResult;
|
|
42
35
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* A name rides as an object key and is labelled by nothing, which is why the
|
|
47
|
-
* response direction never needed a noun for the addressable thing.
|
|
36
|
+
* What application code hands the engine: answers by query name. The engine
|
|
37
|
+
* turns each into a response item, adding the kind and key the query
|
|
38
|
+
* declared.
|
|
48
39
|
*/
|
|
49
40
|
export type HubData = Record<string, HubResult>;
|
|
50
41
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* wire field and the CRUD key are one vocabulary with no translation step.
|
|
55
|
-
* The scope field is `list` here because all three are list operations: each
|
|
56
|
-
* needs a key, and a key exists only on a live row inside a list.
|
|
42
|
+
* One query's answer on the wire: its name, its kind, its key's column name,
|
|
43
|
+
* and exactly one of a row, all rows, or a patch. A patch answers a `rows`
|
|
44
|
+
* query only.
|
|
57
45
|
*/
|
|
58
|
-
export
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
values: Record<string, string>;
|
|
62
|
-
} | {
|
|
63
|
-
action: typeof ACTION_ROW_DELETE;
|
|
64
|
-
list: string;
|
|
46
|
+
export interface ResponseItem {
|
|
47
|
+
query: string;
|
|
48
|
+
kind: Kind;
|
|
65
49
|
key: string;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
50
|
+
row?: Row;
|
|
51
|
+
rows?: Row[];
|
|
52
|
+
patch?: Patch;
|
|
53
|
+
}
|
|
54
|
+
/** Every response the server sends: a page load and a request alike. */
|
|
55
|
+
export type HubResponse = ResponseItem[];
|
|
72
56
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
* The name is the application's and is looked up in the page's declared
|
|
76
|
-
* actions. What keeps this from being an RPC endpoint is that the name must
|
|
77
|
-
* already appear in the page's requests: the browser cannot reach anything the
|
|
78
|
-
* page has not published, and there is no argument list — only where the
|
|
79
|
-
* interaction happened and, where a control has one, its value.
|
|
80
|
-
*
|
|
81
|
-
* The scope field is `list` or `row`, whichever attribute scoped the element
|
|
82
|
-
* the interaction came from, so an action fired from a single-row scope says
|
|
83
|
-
* so. A button carries no value, so the server computes the whole of the new
|
|
84
|
-
* state and the browser never displays a number it has not confirmed. A
|
|
85
|
-
* `<select>` carries one, because the choice is the interaction.
|
|
57
|
+
* Every request has one shape. The name picks the handler; the rest is
|
|
58
|
+
* present when the hub found it.
|
|
86
59
|
*/
|
|
87
|
-
export interface
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
row?: string;
|
|
60
|
+
export interface HubRequest {
|
|
61
|
+
name: string;
|
|
62
|
+
query?: string;
|
|
91
63
|
key?: string;
|
|
92
|
-
|
|
93
|
-
value?: string;
|
|
64
|
+
values?: Record<string, string>;
|
|
94
65
|
}
|
|
95
|
-
|
|
66
|
+
/** The fields a handler receives: the request, less its name. */
|
|
67
|
+
export type RequestFields = Omit<HubRequest, "name">;
|
|
68
|
+
/** Whether a name is one of the requests Loadbare provides. */
|
|
69
|
+
export declare function isRowRequest(name: string): boolean;
|
|
96
70
|
/**
|
|
97
71
|
* A query string with some parms set, and the rest as they were. An empty
|
|
98
72
|
* value takes its parm out, since empty is every parm's default and a
|
|
@@ -100,30 +74,43 @@ export type HubRequest = LbOperation | DeclaredAction;
|
|
|
100
74
|
*
|
|
101
75
|
* One rule on both sides of the wire: the hub applies it to the address bar,
|
|
102
76
|
* and the server to the query string it loads the page at after a request
|
|
103
|
-
* returned `
|
|
104
|
-
*
|
|
77
|
+
* returned `lb-url`. The two must agree, or what the page shows would differ
|
|
78
|
+
* from what the address bar says.
|
|
105
79
|
*/
|
|
106
80
|
export declare function withQueryParms(search: URLSearchParams, parms: Record<string, string>): URLSearchParams;
|
|
107
81
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
82
|
+
* A path names a page by its stub, and nothing finer. The bare path resolves
|
|
83
|
+
* to `index`, the same convention a static file server follows.
|
|
110
84
|
*/
|
|
111
|
-
export declare function
|
|
85
|
+
export declare function pageNameFor(path: string): string;
|
|
112
86
|
/**
|
|
113
|
-
*
|
|
87
|
+
* Where a row for `lb-url` leads, from a page and its query parms.
|
|
114
88
|
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
89
|
+
* A column whose name begins with `lb-` is Loadbare's, and never a query
|
|
90
|
+
* parm; every other column is one. An `lb-path` naming another page enters
|
|
91
|
+
* it with only the parms the row names. Otherwise the named parms are set,
|
|
92
|
+
* or taken out when empty, and the rest are kept.
|
|
93
|
+
*
|
|
94
|
+
* One rule on both sides of the wire: the server loads the page it names,
|
|
95
|
+
* and the hub writes the URL it names. The two must agree, or what the page
|
|
96
|
+
* shows would differ from what the address bar says.
|
|
97
|
+
*/
|
|
98
|
+
export declare function nextLocation(page: string, parms: URLSearchParams, row: Row): {
|
|
99
|
+
page: string;
|
|
100
|
+
parms: URLSearchParams;
|
|
101
|
+
moved: boolean;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* The two hooks a custom element holding rows may implement, both optional.
|
|
119
105
|
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
106
|
+
* The hub reconciles every row template itself, so a custom element supplies
|
|
107
|
+
* placement and scaffolding and nothing else. They are methods on an element
|
|
108
|
+
* the hub does not own, so they carry the `lb` prefix Loadbare reserves for
|
|
109
|
+
* exactly that — see docs/reference/custom-elements.md.
|
|
123
110
|
*/
|
|
124
|
-
export interface
|
|
111
|
+
export interface RowsHost {
|
|
125
112
|
/**
|
|
126
|
-
* Where a row belongs, called with the row detached on its first
|
|
113
|
+
* Where a live row belongs, called with the row detached on its first
|
|
127
114
|
* appearance. Without it a row lands immediately before the template, so
|
|
128
115
|
* rows accumulate in the order they arrive.
|
|
129
116
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lb-types.d.ts","sourceRoot":"","sources":["../../core/lb-types.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"lb-types.d.ts","sourceRoot":"","sources":["../../core/lb-types.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,QAAQ,EACR,SAAS,EAIV,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;GAOG;AACH,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE1C;;;;;;;;;GASG;AACH,MAAM,WAAW,KAAK;IACpB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;CAClB;AAED,0EAA0E;AAC1E,MAAM,MAAM,IAAI,GAAG,OAAO,QAAQ,GAAG,OAAO,SAAS,CAAC;AAEtD;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,GAAG,EAAE,GAAG,KAAK,CAAC;AAEvC,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,IAAI,KAAK,CAE3D;AAED,qEAAqE;AACrE,MAAM,MAAM,SAAS,GAAG,GAAG,GAAG,UAAU,CAAC;AAEzC;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,IAAI,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACb,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,wEAAwE;AACxE,MAAM,MAAM,WAAW,GAAG,YAAY,EAAE,CAAC;AAEzC;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,iEAAiE;AACjE,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AAErD,+DAA+D;AAC/D,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,eAAe,CAOjB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,eAAe,EACtB,GAAG,EAAE,GAAG,GACP;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAc1D;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,QAAQ;IACvB;;;;OAIG;IACH,UAAU,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAExE,4EAA4E;IAC5E,YAAY,CAAC,IAAI,IAAI,CAAC;CACvB"}
|
package/dist/core/lb-types.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
2
|
// The wire vocabulary. Shared by browser and server.
|
|
3
|
-
import { LB_RESERVED_PREFIX, } from "./lb-constants.js";
|
|
3
|
+
import { LB_RESERVED_PREFIX, LB_ROW_REQUESTS, URL_COLUMN_PATH, } from "./lb-constants.js";
|
|
4
4
|
export function isPatch(result) {
|
|
5
5
|
return !Array.isArray(result);
|
|
6
6
|
}
|
|
7
|
+
/** Whether a name is one of the requests Loadbare provides. */
|
|
8
|
+
export function isRowRequest(name) {
|
|
9
|
+
return LB_ROW_REQUESTS.includes(name);
|
|
10
|
+
}
|
|
7
11
|
/**
|
|
8
12
|
* A query string with some parms set, and the rest as they were. An empty
|
|
9
13
|
* value takes its parm out, since empty is every parm's default and a
|
|
@@ -11,8 +15,8 @@ export function isPatch(result) {
|
|
|
11
15
|
*
|
|
12
16
|
* One rule on both sides of the wire: the hub applies it to the address bar,
|
|
13
17
|
* and the server to the query string it loads the page at after a request
|
|
14
|
-
* returned `
|
|
15
|
-
*
|
|
18
|
+
* returned `lb-url`. The two must agree, or what the page shows would differ
|
|
19
|
+
* from what the address bar says.
|
|
16
20
|
*/
|
|
17
21
|
export function withQueryParms(search, parms) {
|
|
18
22
|
const next = new URLSearchParams(search);
|
|
@@ -25,10 +29,39 @@ export function withQueryParms(search, parms) {
|
|
|
25
29
|
return next;
|
|
26
30
|
}
|
|
27
31
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
32
|
+
* A path names a page by its stub, and nothing finer. The bare path resolves
|
|
33
|
+
* to `index`, the same convention a static file server follows.
|
|
30
34
|
*/
|
|
31
|
-
export function
|
|
32
|
-
|
|
35
|
+
export function pageNameFor(path) {
|
|
36
|
+
const name = path.replace(/^\/+|\/+$/g, "");
|
|
37
|
+
return name === "" ? "index" : name;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Where a row for `lb-url` leads, from a page and its query parms.
|
|
41
|
+
*
|
|
42
|
+
* A column whose name begins with `lb-` is Loadbare's, and never a query
|
|
43
|
+
* parm; every other column is one. An `lb-path` naming another page enters
|
|
44
|
+
* it with only the parms the row names. Otherwise the named parms are set,
|
|
45
|
+
* or taken out when empty, and the rest are kept.
|
|
46
|
+
*
|
|
47
|
+
* One rule on both sides of the wire: the server loads the page it names,
|
|
48
|
+
* and the hub writes the URL it names. The two must agree, or what the page
|
|
49
|
+
* shows would differ from what the address bar says.
|
|
50
|
+
*/
|
|
51
|
+
export function nextLocation(page, parms, row) {
|
|
52
|
+
const named = {};
|
|
53
|
+
for (const [name, value] of Object.entries(row)) {
|
|
54
|
+
if (name.startsWith(LB_RESERVED_PREFIX))
|
|
55
|
+
continue;
|
|
56
|
+
named[name] = value === null || value === undefined ? "" : String(value);
|
|
57
|
+
}
|
|
58
|
+
const path = row[URL_COLUMN_PATH];
|
|
59
|
+
const next = typeof path === "string" ? pageNameFor(path) : page;
|
|
60
|
+
const moved = next !== page;
|
|
61
|
+
return {
|
|
62
|
+
page: next,
|
|
63
|
+
parms: withQueryParms(moved ? new URLSearchParams() : parms, named),
|
|
64
|
+
moved,
|
|
65
|
+
};
|
|
33
66
|
}
|
|
34
67
|
//# sourceMappingURL=lb-types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lb-types.js","sourceRoot":"","sources":["../../core/lb-types.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAE3B,qDAAqD;AAErD,OAAO,
|
|
1
|
+
{"version":3,"file":"lb-types.js","sourceRoot":"","sources":["../../core/lb-types.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAE3B,qDAAqD;AAErD,OAAO,EAGL,kBAAkB,EAClB,eAAe,EACf,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAoC3B,MAAM,UAAU,OAAO,CAAC,MAAkB;IACxC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AA2CD,+DAA+D;AAC/D,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAQ,eAAqC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAuB,EACvB,KAA6B;IAE7B,MAAM,IAAI,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;IACzC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,IAAI,KAAK,KAAK,EAAE;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;;YAC/B,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAC5C,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACtC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAY,EACZ,KAAsB,EACtB,GAAQ;IAER,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAChD,IAAI,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC;YAAE,SAAS;QAClD,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,CAAC,eAAe,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjE,MAAM,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC;IAC5B,OAAO;QACL,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC;QACnE,KAAK;KACN,CAAC;AACJ,CAAC","sourcesContent":["/// <reference lib=\"dom\" />\n\n// The wire vocabulary. Shared by browser and server.\n\nimport {\n KIND_ROW,\n KIND_ROWS,\n LB_RESERVED_PREFIX,\n LB_ROW_REQUESTS,\n URL_COLUMN_PATH,\n} from \"./lb-constants.js\";\n\n/**\n * One row: its columns, by name.\n *\n * A value is whatever the server serialized. The hub knows nothing about its\n * type and enforces nothing: it hands each value to the browser untouched,\n * and the browser renders it as it sees fit. What a number, a date or a null\n * should look like is the application's decision, made in the query.\n */\nexport type Row = Record<string, unknown>;\n\n/**\n * Part of a `rows` query's answer — see docs/reference/server.md, \"Queries\".\n *\n * Rows named here are added or updated, keys in `drop` are removed, and\n * anything unnamed is left alone: its contents, and its place in whatever\n * order the widget is keeping. Add and remove are one result rather than two\n * because the interesting cases are both at once — a row whose sort key\n * changed has to move, a swap is one out and one in — and two messages would\n * paint the intermediate state.\n */\nexport interface Patch {\n rows?: Row[];\n drop?: unknown[];\n}\n\n/** A query's kind, declared by the server and carried by every answer. */\nexport type Kind = typeof KIND_ROW | typeof KIND_ROWS;\n\n/**\n * What a `rows` query answers with: all rows, which is also their order, or\n * a patch. `Array.isArray` tells the two apart.\n */\nexport type RowsResult = Row[] | Patch;\n\nexport function isPatch(result: RowsResult): result is Patch {\n return !Array.isArray(result);\n}\n\n/** What any one query answers with, as the application writes it. */\nexport type HubResult = Row | RowsResult;\n\n/**\n * What application code hands the engine: answers by query name. The engine\n * turns each into a response item, adding the kind and key the query\n * declared.\n */\nexport type HubData = Record<string, HubResult>;\n\n/**\n * One query's answer on the wire: its name, its kind, its key's column name,\n * and exactly one of a row, all rows, or a patch. A patch answers a `rows`\n * query only.\n */\nexport interface ResponseItem {\n query: string;\n kind: Kind;\n key: string;\n row?: Row;\n rows?: Row[];\n patch?: Patch;\n}\n\n/** Every response the server sends: a page load and a request alike. */\nexport type HubResponse = ResponseItem[];\n\n/**\n * Every request has one shape. The name picks the handler; the rest is\n * present when the hub found it.\n */\nexport interface HubRequest {\n name: string;\n query?: string;\n key?: string;\n values?: Record<string, string>;\n}\n\n/** The fields a handler receives: the request, less its name. */\nexport type RequestFields = Omit<HubRequest, \"name\">;\n\n/** Whether a name is one of the requests Loadbare provides. */\nexport function isRowRequest(name: string): boolean {\n return (LB_ROW_REQUESTS as readonly string[]).includes(name);\n}\n\n/**\n * A query string with some parms set, and the rest as they were. An empty\n * value takes its parm out, since empty is every parm's default and a\n * default is left out of the URL.\n *\n * One rule on both sides of the wire: the hub applies it to the address bar,\n * and the server to the query string it loads the page at after a request\n * returned `lb-url`. The two must agree, or what the page shows would differ\n * from what the address bar says.\n */\nexport function withQueryParms(\n search: URLSearchParams,\n parms: Record<string, string>,\n): URLSearchParams {\n const next = new URLSearchParams(search);\n for (const [name, value] of Object.entries(parms)) {\n if (value === \"\") next.delete(name);\n else next.set(name, value);\n }\n return next;\n}\n\n/**\n * A path names a page by its stub, and nothing finer. The bare path resolves\n * to `index`, the same convention a static file server follows.\n */\nexport function pageNameFor(path: string): string {\n const name = path.replace(/^\\/+|\\/+$/g, \"\");\n return name === \"\" ? \"index\" : name;\n}\n\n/**\n * Where a row for `lb-url` leads, from a page and its query parms.\n *\n * A column whose name begins with `lb-` is Loadbare's, and never a query\n * parm; every other column is one. An `lb-path` naming another page enters\n * it with only the parms the row names. Otherwise the named parms are set,\n * or taken out when empty, and the rest are kept.\n *\n * One rule on both sides of the wire: the server loads the page it names,\n * and the hub writes the URL it names. The two must agree, or what the page\n * shows would differ from what the address bar says.\n */\nexport function nextLocation(\n page: string,\n parms: URLSearchParams,\n row: Row,\n): { page: string; parms: URLSearchParams; moved: boolean } {\n const named: Record<string, string> = {};\n for (const [name, value] of Object.entries(row)) {\n if (name.startsWith(LB_RESERVED_PREFIX)) continue;\n named[name] = value === null || value === undefined ? \"\" : String(value);\n }\n const path = row[URL_COLUMN_PATH];\n const next = typeof path === \"string\" ? pageNameFor(path) : page;\n const moved = next !== page;\n return {\n page: next,\n parms: withQueryParms(moved ? new URLSearchParams() : parms, named),\n moved,\n };\n}\n\n/**\n * The two hooks a custom element holding rows may implement, both optional.\n *\n * The hub reconciles every row template itself, so a custom element supplies\n * placement and scaffolding and nothing else. They are methods on an element\n * the hub does not own, so they carry the `lb` prefix Loadbare reserves for\n * exactly that — see docs/reference/custom-elements.md.\n */\nexport interface RowsHost {\n /**\n * Where a live row belongs, called with the row detached on its first\n * appearance. Without it a row lands immediately before the template, so\n * rows accumulate in the order they arrive.\n */\n lbPlaceRow?(el: Element, row: Row, template: HTMLTemplateElement): void;\n\n /** Called once after a whole result has landed, for derived scaffolding. */\n lbRowsLanded?(): void;\n}\n"]}
|
package/dist/hub/lb-apply.d.ts
CHANGED
|
@@ -1,53 +1,63 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ResponseItem, type Row, type RowsResult } from "../core/lb-types.js";
|
|
2
|
+
/** A control's value, whether it is native or a custom element. */
|
|
3
|
+
export interface Control extends Element {
|
|
4
|
+
value: string;
|
|
5
|
+
}
|
|
2
6
|
/**
|
|
3
|
-
* A form
|
|
4
|
-
*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
* element
|
|
7
|
+
* A form-associated custom element with a `value` property. HTML marks one
|
|
8
|
+
* with `static formAssociated = true` on its class, and a control has a value.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isFormAssociated(el: Element): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* A control: an `<input>`, `<select>` or `<textarea>`, or a form-associated
|
|
13
|
+
* custom element with a `value` property. Landing and gathering draw the
|
|
14
|
+
* same line, so a value read back is the one that landed there.
|
|
10
15
|
*/
|
|
11
|
-
export declare function
|
|
16
|
+
export declare function isControl(el: Element): el is Control;
|
|
12
17
|
/**
|
|
13
|
-
* Root if it matches, then every descendant in root's
|
|
14
|
-
* Gathering finds
|
|
15
|
-
* branch, so a
|
|
18
|
+
* Root if it matches, then every descendant in root's query that does.
|
|
19
|
+
* Gathering finds columns through here. It does not reach into an absent
|
|
20
|
+
* branch, so a live row is read back from the places a row lands that are
|
|
21
|
+
* showing.
|
|
16
22
|
*/
|
|
17
23
|
export declare function within(root: Element, selector: string): Element[];
|
|
18
24
|
/**
|
|
19
|
-
* Fill one
|
|
25
|
+
* Fill from one row: every `lb-column` and `lb-show` in root's query.
|
|
20
26
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
27
|
+
* A live row is its own row, so its root counts when it carries
|
|
28
|
+
* `lb-column`: `<option>`'s content model is text, so an option row has to
|
|
29
|
+
* be the column it displays. An element a `row` lands on is not its own
|
|
30
|
+
* ancestor, so its own `lb-column` reads from the row around it and is left
|
|
31
|
+
* alone here.
|
|
32
|
+
*/
|
|
33
|
+
export declare function applyRow(root: Element, row: Row, liveRow?: boolean): void;
|
|
34
|
+
/**
|
|
35
|
+
* The row template: the first `<template>` among the element's descendants,
|
|
36
|
+
* outside any nested `lb-query`. A template holding an absent branch is not a
|
|
37
|
+
* row template: rows land before the row template, so one inside the first
|
|
38
|
+
* live row comes first in document order.
|
|
25
39
|
*/
|
|
26
|
-
export declare function
|
|
40
|
+
export declare function templateIn(el: Element): HTMLTemplateElement | null;
|
|
27
41
|
/**
|
|
28
|
-
* Land
|
|
42
|
+
* Land rows through a row template.
|
|
29
43
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
44
|
+
* All rows decide membership and order: every row is placed in the order
|
|
45
|
+
* given, and a row whose key did not arrive is gone. A patch disturbs only
|
|
46
|
+
* what it names — a row it did not mention keeps its contents and its
|
|
47
|
+
* position.
|
|
34
48
|
*
|
|
35
|
-
* A
|
|
36
|
-
* it knows whether it sorts or groups. Without it a row lands
|
|
37
|
-
* before the template, so rows accumulate in the order they
|
|
38
|
-
* template stays put as the insertion marker.
|
|
49
|
+
* A custom element that carries `lbPlaceRow` decides where a row goes,
|
|
50
|
+
* because only it knows whether it sorts or groups. Without it a row lands
|
|
51
|
+
* immediately before the template, so rows accumulate in the order they
|
|
52
|
+
* arrive and the template stays put as the insertion marker.
|
|
39
53
|
*/
|
|
40
|
-
export declare function
|
|
41
|
-
/** Land a whole response. Every result arrives through here. */
|
|
42
|
-
export declare function applyData(root: ParentNode, data: HubData): void;
|
|
54
|
+
export declare function applyRows(el: Element, template: HTMLTemplateElement, keyColumn: string, result: RowsResult): void;
|
|
43
55
|
/**
|
|
44
|
-
* Land
|
|
45
|
-
* way a cell lands a column. A parm the URL does not carry lands empty, so a
|
|
46
|
-
* control shows what the address bar says after Back as well as after a
|
|
47
|
-
* reload: the URL is what is on screen, and nothing else is.
|
|
56
|
+
* Land response items. Every answer arrives through here.
|
|
48
57
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
58
|
+
* `quiet` names queries that may have nowhere to land without a warning: the
|
|
59
|
+
* hub's own `lb-url` lands wherever a chrome or page names it, and nowhere
|
|
60
|
+
* otherwise.
|
|
51
61
|
*/
|
|
52
|
-
export declare function
|
|
62
|
+
export declare function applyResponse(root: ParentNode, items: ResponseItem[], quiet?: readonly string[]): void;
|
|
53
63
|
//# sourceMappingURL=lb-apply.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lb-apply.d.ts","sourceRoot":"","sources":["../../hub/lb-apply.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lb-apply.d.ts","sourceRoot":"","sources":["../../hub/lb-apply.ts"],"names":[],"mappings":"AAkCA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,GAAG,EAER,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAW7B,mEAAmE;AACnE,MAAM,WAAW,OAAQ,SAAQ,OAAO;IACtC,KAAK,EAAE,MAAM,CAAC;CACf;AAiBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAGrD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,OAAO,GAAG,EAAE,IAAI,OAAO,CAEpD;AAuDD;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAMjE;AA8DD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,UAAQ,GAAG,IAAI,CAgBvE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,OAAO,GAAG,mBAAmB,GAAG,IAAI,CAKlE;AAcD;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CACvB,EAAE,EAAE,OAAO,EACX,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,UAAU,GACjB,IAAI,CA+DN;AAyBD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,YAAY,EAAE,EACrB,KAAK,GAAE,SAAS,MAAM,EAAO,GAC5B,IAAI,CAWN"}
|