@loadbare/app 0.5.5 → 0.6.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 -4
- package/dist/build/assemble.d.ts +1 -1
- package/dist/build/assemble.d.ts.map +1 -1
- package/dist/build/assemble.js +80 -7
- package/dist/build/cli.d.ts +2 -2
- package/dist/build/cli.js +2 -2
- package/dist/build/expand.d.ts.map +1 -1
- package/dist/build/expand.js +30 -34
- package/dist/build/locations.d.ts +3 -3
- package/dist/build/locations.d.ts.map +1 -1
- package/dist/build/locations.js +15 -3
- package/dist/build/origins.d.ts +0 -13
- package/dist/build/origins.d.ts.map +1 -1
- package/dist/build/origins.js +32 -8
- package/dist/build/pages.d.ts +3 -3
- package/dist/build/pages.d.ts.map +1 -1
- package/dist/build/pages.js +9 -7
- package/dist/core/lb-constants.d.ts +17 -12
- package/dist/core/lb-constants.d.ts.map +1 -1
- package/dist/core/lb-constants.js +106 -43
- package/dist/core/lb-types.d.ts +103 -62
- package/dist/core/lb-types.d.ts.map +1 -1
- package/dist/core/lb-types.js +11 -3
- package/dist/hub/lb-apply.d.ts +18 -4
- package/dist/hub/lb-apply.d.ts.map +1 -1
- package/dist/hub/lb-apply.js +184 -34
- 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 +165 -83
- package/dist/server/lb-express.d.ts +7 -4
- package/dist/server/lb-express.d.ts.map +1 -1
- package/dist/server/lb-express.js +45 -33
- package/dist/server/lb-server.d.ts +67 -45
- package/dist/server/lb-server.d.ts.map +1 -1
- package/dist/server/lb-server.js +55 -18
- package/dist/tests/assemble.test.js +154 -2
- package/dist/tests/expand.test.js +30 -3
- package/dist/tests/helpers/hub.d.ts +73 -0
- package/dist/tests/helpers/hub.d.ts.map +1 -0
- package/dist/tests/helpers/hub.js +151 -0
- package/dist/tests/lb-apply.test.js +86 -62
- package/dist/tests/lb-express.test.d.ts +1 -1
- package/dist/tests/lb-express.test.js +43 -38
- package/dist/tests/lb-hub.test.d.ts +14 -0
- package/dist/tests/lb-hub.test.d.ts.map +1 -0
- package/dist/tests/lb-hub.test.js +319 -0
- package/dist/tests/{lb-rows.test.d.ts → lb-list.test.d.ts} +1 -1
- package/dist/tests/lb-list.test.d.ts.map +1 -0
- package/dist/tests/{lb-rows.test.js → lb-list.test.js} +109 -106
- package/dist/tests/lb-server.test.js +151 -100
- package/dist/tests/origins.test.js +19 -1
- package/dist/tests/pages.test.d.ts +1 -1
- package/dist/tests/pages.test.js +64 -14
- package/docs/TECHREF-1.0.md +1000 -0
- package/docs/reference/builder.md +4 -4
- package/docs/reference/chrome.md +56 -5
- package/docs/reference/custom-elements.md +59 -36
- package/docs/reference/data-binding.md +142 -84
- package/docs/reference/overview.md +1 -1
- package/docs/reference/page-files.md +64 -49
- package/docs/reference/server.md +7 -6
- package/docs/reference/widgets.md +43 -32
- package/docs/roadmap.md +68 -22
- package/docs/testing.md +47 -17
- package/docs/theory.md +2 -2
- package/docs/tutorials/010-pages-and-navigation.md +14 -8
- package/docs/tutorials/040-displaying-data.md +9 -9
- package/docs/tutorials/050-actions.md +5 -5
- package/docs/tutorials/060-custom-element-code.md +1 -1
- package/docs/tutorials/065-conditional-rendering.md +4 -4
- package/docs/tutorials/070-displaying-a-list.md +24 -47
- package/docs/tutorials/072-inserting-into-a-list.md +17 -17
- package/docs/tutorials/074-deleting-from-a-list.md +15 -17
- package/docs/tutorials/076-updating-a-list-item.md +20 -22
- package/docs/tutorials/080-widget-requests.md +27 -23
- package/docs/tutorials/090-using-widget-libraries.md +23 -1
- package/package.json +1 -2
- package/dist/hub/lb-rows.d.ts +0 -18
- package/dist/hub/lb-rows.d.ts.map +0 -1
- package/dist/hub/lb-rows.js +0 -106
- package/dist/tests/lb-rows.test.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lb-constants.d.ts","sourceRoot":"","sources":["../../core/lb-constants.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lb-constants.d.ts","sourceRoot":"","sources":["../../core/lb-constants.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,SAAS,YAAY,CAAC;AAQnC,eAAO,MAAM,QAAQ,WAAW,CAAC;AAMjC,eAAO,MAAM,QAAQ,WAAW,CAAC;AAMjC,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAQ7C,eAAO,MAAM,SAAS,YAAY,CAAC;AAEnC,eAAO,MAAM,UAAU,aAAa,CAAC;AAOrC,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAK7C,eAAO,MAAM,aAAa,eAAe,CAAC;AAS1C,eAAO,MAAM,WAAW,cAAc,CAAC;AAYvC,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AAMxC,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAKjD,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAOjD,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AAMjD,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AAInD,eAAO,MAAM,UAAU,gFAKb,CAAC;AAMX,eAAO,MAAM,SAAS,YAAY,CAAC;AAYnC,eAAO,MAAM,aAAa,gBAAgB,CAAC;AAK3C,eAAO,MAAM,aAAa,gBAAgB,CAAC;AAM3C,eAAO,MAAM,SAAS,YAAY,CAAC;AAQnC,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAKvC,eAAO,MAAM,cAAc,eAAe,CAAC;AAC3C,eAAO,MAAM,YAAY,aAAa,CAAC;AAUvC,eAAO,MAAM,iBAAiB,oBAAoB,CAAC;AAQnD,eAAO,MAAM,YAAY,WAAW,CAAC;AAQrC,eAAO,MAAM,YAAY,eAAe,CAAC;AAOzC,eAAO,MAAM,UAAU,aAAa,CAAC;AAMrC,eAAO,MAAM,WAAW,QAAQ,CAAC;AAIjC,eAAO,MAAM,qBAAqB,QAAS,CAAC"}
|
|
@@ -2,49 +2,93 @@
|
|
|
2
2
|
// literal — not a widget, not a page host, not a test. See
|
|
3
3
|
// docs/reference/data-binding.md.
|
|
4
4
|
// --- Binding (docs/reference/data-binding.md) ---------------------------
|
|
5
|
-
|
|
5
|
+
// One containment ladder: a list holds rows, a row holds cells. Both scope
|
|
6
|
+
// attributes take a name the server declares, and a nested one of either
|
|
7
|
+
// kind begins a new scope.
|
|
8
|
+
// Scopes DOM children to a named set of rows.
|
|
9
|
+
export const ATTR_LIST = "lb-list";
|
|
10
|
+
// Scopes DOM children to one named row.
|
|
11
|
+
//
|
|
12
|
+
// A single-row scope is read-only. Every write operation needs a key, and a
|
|
13
|
+
// key exists only on a live row the hub stamped inside a list, so a declared
|
|
14
|
+
// action is the only thing such a scope can send. An application that wants
|
|
15
|
+
// a writable single row declares a list that answers with one row.
|
|
16
|
+
export const ATTR_ROW = "lb-row";
|
|
17
|
+
// Named on a row template by the developer: the column that identifies a row
|
|
18
|
+
// of the list. A property of the list rather than of the template — a list
|
|
19
|
+
// without a fixed key column is meaningless — but written where the rows
|
|
20
|
+
// land, because that is the only place the page says anything about them.
|
|
6
21
|
export const ATTR_KEY = "lb-key";
|
|
22
|
+
// Stamped on a live row by the row machinery: that row's value of the column
|
|
23
|
+
// ATTR_KEY names. Written by the hub, never by a developer, and read back by
|
|
24
|
+
// whatever needs to know which row it is inside — a delete button, an update
|
|
25
|
+
// form, a widget building its own request, or a stylesheet.
|
|
26
|
+
export const ATTR_KEY_VALUE = "lb-key-value";
|
|
27
|
+
// The column an element displays.
|
|
28
|
+
//
|
|
29
|
+
// Its value is a column name and never a cell name. A cell has no name of
|
|
30
|
+
// its own: it is identified by its row and its column, and the row arrives
|
|
31
|
+
// from scope, so the column is all that is left to say. ATTR_KEY holds a
|
|
32
|
+
// column name for the same reason.
|
|
7
33
|
export const ATTR_CELL = "lb-cell";
|
|
8
34
|
export const ATTR_VALUE = "lb-value";
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
// widget for the same reason. Sorting and grouping are one question — where
|
|
16
|
-
// does this row go? — and both answers are local.
|
|
17
|
-
export const ATTR_SORT = "lb-sort";
|
|
18
|
-
// Stamped on a list widget by the shared row machinery: how many rows it is
|
|
19
|
-
// showing. It is HTML's namespace rather than Loadbare App's because nothing
|
|
20
|
-
// binds to it — it is derived from rows the hub already knows, exactly as
|
|
21
|
-
// the section heading in lb-table is. It exists so that "no members yet"
|
|
22
|
-
// is a stylesheet rule rather than a conditional in every list widget.
|
|
23
|
-
export const ATTR_ROW_COUNT = "data-rows";
|
|
35
|
+
// Stamped on a list scope by the shared row machinery: how many rows it is
|
|
36
|
+
// showing. Written by the hub and never bound to — it is derived from rows
|
|
37
|
+
// the hub already knows, exactly as the section heading in lb-table is. A
|
|
38
|
+
// list widget watches it, and it exists so that "no members yet" is a
|
|
39
|
+
// stylesheet rule rather than a conditional in every list widget.
|
|
40
|
+
export const ATTR_ROW_COUNT = "lb-row-count";
|
|
24
41
|
// --- Requests (docs/reference/data-binding.md) --------------------------
|
|
25
42
|
// One event name, used by a widget reaching the server and by a widget
|
|
26
43
|
// reaching an ancestor widget.
|
|
27
44
|
export const LB_EVENT_NAME = "lb-request";
|
|
28
|
-
// Names
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
45
|
+
// Names what an interaction asks for.
|
|
46
|
+
//
|
|
47
|
+
// One attribute name, one wire field, one set of values: the request field
|
|
48
|
+
// `action` carries this attribute's value verbatim, and nothing is
|
|
49
|
+
// translated in between. On a native element the hub turns the element's own
|
|
50
|
+
// event into the request — a form submits, anything else clicks; on a
|
|
51
|
+
// widget, the widget builds it from whatever interaction it owns.
|
|
32
52
|
export const ATTR_ACTION = "lb-action";
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
53
|
+
// --- Reserved names ----------------------------------------------------
|
|
54
|
+
// Loadbare owns every value beginning with this prefix, in every lb-*
|
|
55
|
+
// attribute: a name so prefixed is the hub's own (NAV_ROW), and an
|
|
56
|
+
// lb-action so prefixed is an operation (below). The server refuses a page
|
|
57
|
+
// that declares a query or an action beginning with it, so a new reserved
|
|
58
|
+
// name can never collide with one an application already uses.
|
|
59
|
+
//
|
|
60
|
+
// It is also the whole of the wire discriminant. A request whose `action`
|
|
61
|
+
// begins with it is one of the four operations; anything else is a name the
|
|
62
|
+
// page declared under its requests. Nothing else tells them apart.
|
|
63
|
+
export const LB_RESERVED_PREFIX = "lb-";
|
|
64
|
+
// On a <form> in a list scope: builds a new row on submit. The hub gathers
|
|
65
|
+
// every lb-cell inside the form into a values map — no key, because there is
|
|
66
|
+
// no row yet — and the form's own lb-list says which list it is inserting
|
|
67
|
+
// into.
|
|
68
|
+
export const ACTION_ROW_INSERT = "lb-row-insert";
|
|
69
|
+
// Deletes the row the element is inside. Needs no declared name: it takes
|
|
70
|
+
// only the row's own lb-list/lb-key-value binding, which is all the server
|
|
36
71
|
// needs to know which row and whether the operation is permitted on it.
|
|
37
|
-
export const
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
|
|
72
|
+
export const ACTION_ROW_DELETE = "lb-row-delete";
|
|
73
|
+
// On a <form> inside a live row: commits several cells of that row at once
|
|
74
|
+
// on submit — the batch counterpart to a cell change. The hub gathers the
|
|
75
|
+
// same values map, plus the row's own lb-key-value: a form that is a list's
|
|
76
|
+
// row template root, or sits inside one, has both from its ancestors exactly
|
|
77
|
+
// as a delete button does.
|
|
78
|
+
export const ACTION_ROW_UPDATE = "lb-row-update";
|
|
79
|
+
// On a widget wrapping one control: commits that one cell when the control
|
|
80
|
+
// changes. The hub never sends this itself — a native element has no widget
|
|
81
|
+
// to decide what a change is — so a widget that carries it builds the
|
|
82
|
+
// operation from its own lb-list/lb-key-value/lb-cell binding.
|
|
83
|
+
export const ACTION_CELL_CHANGE = "lb-cell-change";
|
|
84
|
+
// Every reserved lb-action, in one place, so the builder can refuse an
|
|
85
|
+
// unknown one and the hub can refuse to send one it does not implement.
|
|
86
|
+
export const LB_ACTIONS = [
|
|
87
|
+
ACTION_ROW_INSERT,
|
|
88
|
+
ACTION_ROW_DELETE,
|
|
89
|
+
ACTION_ROW_UPDATE,
|
|
90
|
+
ACTION_CELL_CHANGE,
|
|
91
|
+
];
|
|
48
92
|
// --- Expansion (docs/reference/custom-elements.md) ---------------------
|
|
49
93
|
// Marks the element in a definition whose children receive the authored
|
|
50
94
|
// inner content. An attribute rather than an element because HTML content
|
|
@@ -65,14 +109,31 @@ export const ATTR_TEMPLATE = "lb-template";
|
|
|
65
109
|
// Only anchors carrying this are intercepted, so external links are never
|
|
66
110
|
// hijacked.
|
|
67
111
|
export const ATTR_NAV_LINK = "lb-nav-link";
|
|
68
|
-
// A page host ships as <template
|
|
69
|
-
|
|
112
|
+
// A page host ships as <template lb-page="<name>">. An attribute rather than
|
|
113
|
+
// an id: an id lives in the application's own namespace, where a page named
|
|
114
|
+
// for something the chrome also ids would collide, and getElementById()
|
|
115
|
+
// answers a collision by silently picking one.
|
|
116
|
+
export const ATTR_PAGE = "lb-page";
|
|
117
|
+
// The hub's own row. Landed on every navigation, on any subtree inside the
|
|
118
|
+
// hub that names it, through the same applyData() a server answer goes
|
|
119
|
+
// through — so a chrome displays where the page is the way it displays
|
|
120
|
+
// anything else. One row rather than a list, so a subtree binds it with
|
|
121
|
+
// lb-row. A reserved name (LB_RESERVED_PREFIX): the server refuses to
|
|
122
|
+
// declare a query so named.
|
|
123
|
+
export const NAV_ROW = "lb-navigation";
|
|
124
|
+
// Its two columns. The label is the nav's: the text of the lb-nav-link
|
|
125
|
+
// anchor whose href names the current page, and empty when no anchor does.
|
|
126
|
+
// The URI is the path as the browser has it.
|
|
127
|
+
export const NAV_CELL_LABEL = "page-label";
|
|
128
|
+
export const NAV_CELL_URI = "page-uri";
|
|
70
129
|
// Marks the chrome's own <dialog> for a page name that resolves to no
|
|
71
130
|
// template — a routing miss discovered client-side, not an HTTP 404 (every
|
|
72
131
|
// route gets the same 200 response; see docs/tutorials/010-pages-and-navigation.md).
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
//
|
|
132
|
+
// The hub only opens it; what it says comes from NAV_ROW, which the dialog
|
|
133
|
+
// consumes like any other subtree, by naming it in lb-row. Optional: an
|
|
134
|
+
// application that declares none gets today's console.error and nothing
|
|
135
|
+
// more. The builder requires the element it's on to be a <dialog>
|
|
136
|
+
// (build/assemble.ts), since the hub calls showModal() on it.
|
|
76
137
|
export const ATTR_UNKNOWN_PAGE = "lb-unknown-page";
|
|
77
138
|
// The hub's own tag. It is exempt from the rule every other LB-* tag
|
|
78
139
|
// follows: expansion does not require it to have a definition (build/expand.ts),
|
|
@@ -87,16 +148,18 @@ export const HUB_TAG_NAME = "lb-hub";
|
|
|
87
148
|
// meaning beyond "in flight": a stylesheet dims the element, or a custom
|
|
88
149
|
// button widget watches it to disable itself, but the hub itself only sets
|
|
89
150
|
// and clears it.
|
|
90
|
-
export const ATTR_PENDING = "
|
|
151
|
+
export const ATTR_PENDING = "lb-pending";
|
|
91
152
|
// Stamped on the same element if that round trip failed — a non-2xx
|
|
92
153
|
// response, a thrown application error, or a timeout, all alike. Cleared at
|
|
93
154
|
// the start of that element's next request. What (if anything) an
|
|
94
155
|
// application shows for it is undecided; this is only the fact that it
|
|
95
156
|
// happened.
|
|
96
|
-
export const ATTR_ERROR = "
|
|
157
|
+
export const ATTR_ERROR = "lb-error";
|
|
97
158
|
// --- Wire --------------------------------------------------------------
|
|
98
|
-
|
|
99
|
-
|
|
159
|
+
// One path, one method: everything the hub asks of the server is a POST to
|
|
160
|
+
// this path. Navigation is therefore the only GET an application serves,
|
|
161
|
+
// which is what leaves the page name space unrestricted.
|
|
162
|
+
export const LB_ENDPOINT = "/lb";
|
|
100
163
|
// A client-side deadline for one round trip. fetch() has no deadline of its
|
|
101
164
|
// own; past this the request is aborted and treated as a failure.
|
|
102
165
|
export const LB_REQUEST_TIMEOUT_MS = 10_000;
|
package/dist/core/lb-types.d.ts
CHANGED
|
@@ -1,88 +1,129 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { ACTION_CELL_CHANGE, ACTION_ROW_DELETE, ACTION_ROW_INSERT, ACTION_ROW_UPDATE } from "./lb-constants";
|
|
2
|
+
/**
|
|
3
|
+
* One row: its columns, by name.
|
|
4
|
+
*
|
|
5
|
+
* A value is whatever the server serialized. The hub knows nothing about its
|
|
6
|
+
* type and enforces nothing: it hands each value to the browser untouched,
|
|
7
|
+
* and the browser renders it as it sees fit. What a number, a date or a null
|
|
8
|
+
* should look like is the application's decision, made in the query.
|
|
9
|
+
*/
|
|
10
|
+
export type Row = Record<string, unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* Part of a list — see docs/reference/server.md, "Queries".
|
|
13
|
+
*
|
|
14
|
+
* Rows named here arrive or are updated, keys in `drop` are gone, and
|
|
15
|
+
* anything unnamed is left alone: its contents, and its place in whatever
|
|
16
|
+
* order the widget is keeping. Add and remove are one result rather than two
|
|
17
|
+
* because the interesting cases are both at once — a row whose sort key
|
|
18
|
+
* changed has to move, a swap is one out and one in — and two messages would
|
|
19
|
+
* paint the intermediate state.
|
|
20
|
+
*/
|
|
21
|
+
export interface Patch {
|
|
22
|
+
rows?: Row[];
|
|
23
|
+
drop?: unknown[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* What a list answers with.
|
|
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.
|
|
40
|
+
*/
|
|
41
|
+
export type HubResult = Row | ListResult;
|
|
42
|
+
/**
|
|
43
|
+
* Every response on the data channel is the same shape, whether it is a cold
|
|
44
|
+
* start or the narrowest refresh. The hub does not know which case it is in.
|
|
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.
|
|
48
|
+
*/
|
|
49
|
+
export type HubData = Record<string, HubResult>;
|
|
50
|
+
/**
|
|
51
|
+
* The four operations — docs/reference/data-binding.md. The set is closed.
|
|
52
|
+
*
|
|
53
|
+
* `action` carries the value of `lb-action` verbatim, so the attribute, the
|
|
54
|
+
* wire field and the CRUD key are one vocabulary with no translation step.
|
|
55
|
+
* The scope field is `list` here because all four are list operations: each
|
|
56
|
+
* needs a key, and a key exists only on a live row inside a list.
|
|
57
|
+
*/
|
|
58
|
+
export type LbOperation = {
|
|
59
|
+
action: typeof ACTION_ROW_INSERT;
|
|
60
|
+
list: string;
|
|
11
61
|
values: Record<string, string>;
|
|
12
62
|
} | {
|
|
13
|
-
|
|
14
|
-
|
|
63
|
+
action: typeof ACTION_ROW_DELETE;
|
|
64
|
+
list: string;
|
|
65
|
+
key: string;
|
|
66
|
+
} | {
|
|
67
|
+
action: typeof ACTION_ROW_UPDATE;
|
|
68
|
+
list: string;
|
|
15
69
|
key: string;
|
|
16
70
|
values: Record<string, string>;
|
|
17
71
|
} | {
|
|
18
|
-
|
|
19
|
-
|
|
72
|
+
action: typeof ACTION_CELL_CHANGE;
|
|
73
|
+
list: string;
|
|
20
74
|
key: string;
|
|
21
|
-
|
|
75
|
+
cell: string;
|
|
76
|
+
value: string;
|
|
77
|
+
};
|
|
22
78
|
/**
|
|
23
|
-
* Everything that is not
|
|
79
|
+
* Everything that is not one of the four.
|
|
24
80
|
*
|
|
25
81
|
* The name is the application's and is looked up in the page's declared
|
|
26
82
|
* actions. What keeps this from being an RPC endpoint is that the name must
|
|
27
|
-
* already appear in the page's
|
|
83
|
+
* already appear in the page's requests: the browser cannot reach anything the
|
|
28
84
|
* page has not published, and there is no argument list — only where the
|
|
29
85
|
* interaction happened and, where a control has one, its value.
|
|
30
86
|
*
|
|
31
|
-
*
|
|
87
|
+
* The scope field is `list` or `row`, whichever attribute scoped the element
|
|
88
|
+
* the interaction came from, so an action fired from a single-row scope says
|
|
89
|
+
* so. A button carries no value, so the server computes the whole of the new
|
|
32
90
|
* state and the browser never displays a number it has not confirmed. A
|
|
33
91
|
* `<select>` carries one, because the choice is the interaction.
|
|
34
92
|
*/
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
93
|
+
export interface DeclaredAction {
|
|
94
|
+
action: string;
|
|
95
|
+
list?: string;
|
|
96
|
+
row?: string;
|
|
39
97
|
key?: string;
|
|
40
98
|
cell?: string;
|
|
41
99
|
value?: string;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export type QueryResult = Record<string, string>;
|
|
45
|
-
/**
|
|
46
|
-
* A query that returns many tuples — see docs/reference/server.md, "Queries".
|
|
47
|
-
*
|
|
48
|
-
* Two results, because a list widget must be told the difference. `rows` is
|
|
49
|
-
* the entire set and therefore also the order; `patch` names only what
|
|
50
|
-
* changed and leaves everything it does not name alone. Add and remove are
|
|
51
|
-
* one result rather than two because the interesting cases are both at once
|
|
52
|
-
* — a row whose sort key changed has to move, a swap is one out and one in —
|
|
53
|
-
* and two messages would paint the intermediate state.
|
|
54
|
-
*
|
|
55
|
-
* `op` is the same discriminant word the request union uses, so one
|
|
56
|
-
* vocabulary runs in both directions. It is therefore a reserved cell name:
|
|
57
|
-
* a tuple with a cell called `op` whose value is `rows` or `patch` would be
|
|
58
|
-
* read as a projection.
|
|
59
|
-
*/
|
|
60
|
-
export type Projection = {
|
|
61
|
-
op: "rows";
|
|
62
|
-
rows: QueryResult[];
|
|
63
|
-
} | {
|
|
64
|
-
op: "patch";
|
|
65
|
-
rows?: QueryResult[];
|
|
66
|
-
drop?: string[];
|
|
67
|
-
};
|
|
68
|
-
/** A tuple is the sugar and the common case; a projection says so. */
|
|
69
|
-
export type HubResult = QueryResult | Projection;
|
|
70
|
-
export declare function isProjection(result: HubResult): result is Projection;
|
|
100
|
+
}
|
|
101
|
+
export type HubRequest = LbOperation | DeclaredAction;
|
|
71
102
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* it is in.
|
|
103
|
+
* The reserved prefix is the whole of the discriminant. Nothing else tells
|
|
104
|
+
* an operation from a declared action, on the wire or anywhere else.
|
|
75
105
|
*/
|
|
76
|
-
export
|
|
106
|
+
export declare function isOperation(request: HubRequest): request is LbOperation;
|
|
77
107
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
108
|
+
* The two hooks a list widget may implement, both optional.
|
|
109
|
+
*
|
|
110
|
+
* The hub reconciles every list scope itself, so a widget supplies placement
|
|
111
|
+
* and scaffolding and nothing else. A scope that implements neither is a
|
|
112
|
+
* plain element with a row template inside it, which is why there is no
|
|
113
|
+
* repeater widget.
|
|
81
114
|
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
115
|
+
* They are methods on an element the hub does not own, so they carry the
|
|
116
|
+
* `lb` prefix that Loadbare reserves for exactly that — see
|
|
117
|
+
* docs/reference/custom-elements.md.
|
|
84
118
|
*/
|
|
85
|
-
export interface
|
|
86
|
-
|
|
119
|
+
export interface ListHost {
|
|
120
|
+
/**
|
|
121
|
+
* Where a row belongs, called with the row detached on its first
|
|
122
|
+
* appearance. Without it a row lands immediately before the template, so
|
|
123
|
+
* rows accumulate in the order they arrive.
|
|
124
|
+
*/
|
|
125
|
+
lbPlaceRow?(el: Element, row: Row, template: HTMLTemplateElement): void;
|
|
126
|
+
/** Called once after a whole result has landed, for derived scaffolding. */
|
|
127
|
+
lbRowsLanded?(): void;
|
|
87
128
|
}
|
|
88
129
|
//# sourceMappingURL=lb-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lb-types.d.ts","sourceRoot":"","sources":["../../core/lb-types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lb-types.d.ts","sourceRoot":"","sources":["../../core/lb-types.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EAElB,MAAM,gBAAgB,CAAC;AAExB;;;;;;;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;;;;;;;;;GASG;AACH,MAAM,MAAM,UAAU,GAAG,GAAG,EAAE,GAAG,KAAK,CAAC;AAEvC,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,IAAI,KAAK,CAE3D;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,GAAG,GAAG,UAAU,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GACnB;IACE,MAAM,EAAE,OAAO,iBAAiB,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,GACD;IAAE,MAAM,EAAE,OAAO,iBAAiB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC/D;IACE,MAAM,EAAE,OAAO,iBAAiB,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,GACD;IACE,MAAM,EAAE,OAAO,kBAAkB,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEN;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,cAAc,CAAC;AAEtD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,IAAI,WAAW,CAEvE;AAED;;;;;;;;;;;GAWG;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,5 +1,13 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
1
2
|
// The wire vocabulary. Shared by browser and server.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
return
|
|
3
|
+
import { LB_RESERVED_PREFIX, } from "./lb-constants";
|
|
4
|
+
export function isPatch(result) {
|
|
5
|
+
return !Array.isArray(result);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The reserved prefix is the whole of the discriminant. Nothing else tells
|
|
9
|
+
* an operation from a declared action, on the wire or anywhere else.
|
|
10
|
+
*/
|
|
11
|
+
export function isOperation(request) {
|
|
12
|
+
return request.action.startsWith(LB_RESERVED_PREFIX);
|
|
5
13
|
}
|
package/dist/hub/lb-apply.d.ts
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type HubData, type ListResult, type Row } from "../core/lb-types";
|
|
2
2
|
/**
|
|
3
|
-
* Fill one scope from one
|
|
3
|
+
* Fill one scope from one row.
|
|
4
4
|
*
|
|
5
5
|
* The root counts as a cell if it carries one. A `<tr>` holds its cells in
|
|
6
6
|
* `<td>` children, but `<option>`'s content model is text, so an option row
|
|
7
7
|
* has to be the cell it displays. Requiring a wrapper there would require an
|
|
8
8
|
* element HTML does not allow.
|
|
9
9
|
*/
|
|
10
|
-
export declare function
|
|
11
|
-
/**
|
|
10
|
+
export declare function applyRow(root: Element, row: Row): void;
|
|
11
|
+
/**
|
|
12
|
+
* Land a list result in a list scope.
|
|
13
|
+
*
|
|
14
|
+
* An array is the whole set, so it decides membership and order: every row is
|
|
15
|
+
* placed in the order given, and a row whose key did not arrive is gone. A
|
|
16
|
+
* patch disturbs only what it names — a row it did not mention keeps its
|
|
17
|
+
* contents and its position.
|
|
18
|
+
*
|
|
19
|
+
* A widget that carries `lbPlaceRow` decides where a row goes, because only
|
|
20
|
+
* it knows whether it sorts or groups. Without it a row lands immediately
|
|
21
|
+
* before the template, so rows accumulate in the order they arrive and the
|
|
22
|
+
* template stays put as the insertion marker.
|
|
23
|
+
*/
|
|
24
|
+
export declare function applyList(scope: Element, result: ListResult): void;
|
|
25
|
+
/** Land a whole response. Every result arrives through here. */
|
|
12
26
|
export declare function applyData(root: ParentNode, data: HubData): void;
|
|
13
27
|
//# 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":"AA4BA,OAAO,EAEL,KAAK,OAAO,EAEZ,KAAK,UAAU,EACf,KAAK,GAAG,EACT,MAAM,kBAAkB,CAAC;AAiD1B;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAMtD;AAoCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAgElE;AAED,gEAAgE;AAChE,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAkC/D"}
|