foldkit-crud 0.10.0 → 0.12.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 CHANGED
@@ -113,6 +113,9 @@ What each call does:
113
113
  the selected members in the Selection's order, each with its `key`,
114
114
  `member`, a `label` found the way a form finds one (the schema's `title`,
115
115
  else `Form.label` metadata, else the key), and a `display`.
116
+ `live: true` asks for the list live (`Data.query`'s `live`): rows another
117
+ page writes join, change and leave it while it is shown, given a server
118
+ whose live source watches lists (`pollLive`).
116
119
  - **`Authors.at`** binds it to your Remote domain and your Model. It still does
117
120
  no I/O.
118
121
  - **`AuthorList.active`** is the requirement: while `input` gives a value, the
@@ -127,6 +130,11 @@ What each call does:
127
130
  - **`AuthorList.refresh(model)`** is the Model with the list asked for again. A
128
131
  failed read is not retried on its own, so this is what a retry button's
129
132
  Message returns.
133
+ - **`AuthorList.connection(model)`** is the connection the list reads, an
134
+ `Option`, none while it is not shown: what a write's optimistic insert or
135
+ remove names (`ConnectionChange.prepend(list, Remote.ref(Author, id))`). It
136
+ carries the list's input, so a change cannot name a list rebuilt from
137
+ another input that nothing reads.
130
138
 
131
139
  `AuthorList.row(id)` is a Projection of one row through the list's Selection,
132
140
  whether or not the query finds it now, and `AuthorList.choiceOf(model, id)` is
@@ -209,7 +217,8 @@ const subscriptions = Data.subscriptions({ editor: PostEditor.active })
209
217
  - `onOut` for the placement: a valid submit becomes `Data.mutate`, and the
210
218
  editor remembers the request id.
211
219
  - `active`: while an id is open, what the form writes is fetched and
212
- retained.
220
+ retained. Its `projectionOf(model)` reads that value, typed by the
221
+ members the form writes.
213
222
  - `after(update)`: wraps `update` so the editor fills the form and
214
223
  reconciles its status after every Message. `sync` is that Step on its own,
215
224
  for an `update` composed another way.
@@ -291,8 +300,9 @@ what is in the form.
291
300
 
292
301
  A save the server refuses with `Refusal.field(key, reason)` for one of the
293
302
  form's keys is shown on that key, as the form's own `Refused` would show it: the
294
- key reads invalid with the reason, as text, keeping what was typed, until it is
295
- edited. It is shown once per save, and the status is `SaveFailed`. A refusal
303
+ key reads invalid with the reason, as text, keeping what was typed, until any
304
+ key is edited. It is shown once per save, only while the key still holds what
305
+ the save sent, and the status is `SaveFailed`. A refusal
296
306
  with `Refusal.invalid` (the row the save would leave breaks an invariant) shows
297
307
  its message the same way beside each key its path names. A refusal of a key the
298
308
  form does not have, or of an invariant whose path names none, is left to the
@@ -536,7 +546,8 @@ Entity, so one author list serves `authorId` and `editorId` alike. A picker
536
546
  whose target no list is over, or whose list has no `choice`, throws when
537
547
  `Crud.options` is called, not when the form is drawn. `AuthorList.choices(model)`
538
548
  is one list's choices on its own. Both are empty until the page is loaded, and
539
- hold only the rows loaded so far.
549
+ hold only the rows loaded so far. A refresh that fails keeps the rows it had
550
+ among the choices, as the list still shows them; the failure is in `page`.
540
551
 
541
552
  #### When a picker searches
542
553
 
@@ -0,0 +1,105 @@
1
+ import { AnyEntity, EntityMember } from "foldkit-entity";
2
+ import { Metadata } from "foldkit-metadata";
3
+ /**
4
+ * How one selected member shows: the primitive every kind of Display is a value
5
+ * of. `Display.text()` and `Display.flag()` are values of it, made by
6
+ * `Display.kind`, which is what an application calls for a badge or a relative
7
+ * date. The kinds here are a collection, not a special case.
8
+ */
9
+ export interface Display<Data = unknown> {
10
+ /** The name a renderer is found by. */
11
+ readonly kind: string;
12
+ /** Whether a view draws it. A member read and not shown, usually the id, is `false`. */
13
+ readonly shown: boolean;
14
+ /** What this kind needs: a format, a relation's target. */
15
+ readonly data: Data;
16
+ /**
17
+ * The value as text: what a cell says when nothing draws it specially. It is
18
+ * never given `null` or `undefined`; `Display.show` says `nothing` for those.
19
+ */
20
+ readonly text: (value: unknown, words: DisplayWords) => string;
21
+ }
22
+ /** A kind of Display: how its values are made, and how one is told from another. */
23
+ export interface DisplayKind<Data> {
24
+ readonly kind: string;
25
+ readonly of: (data: Data) => Display<Data>;
26
+ readonly is: (display: Display) => display is Display<Data>;
27
+ }
28
+ /** A selected member with its words and its Display. A list's column, a detail's line. */
29
+ export interface DisplayColumn<Key extends string = string> {
30
+ readonly key: Key;
31
+ readonly label: string;
32
+ readonly member: EntityMember;
33
+ readonly display: Display;
34
+ }
35
+ /** The words a Display needs that are not the value's own. */
36
+ export interface DisplayWords {
37
+ /** Default `yes`. */
38
+ readonly yes?: string;
39
+ /** Default `no`. */
40
+ readonly no?: string;
41
+ /** What stands for nothing: `null`, `undefined`, an empty list. Default the empty string. */
42
+ readonly nothing?: string;
43
+ /** Between the items of a list, and between the members of a nested value. Default `, `. */
44
+ readonly separator?: string;
45
+ }
46
+ /** A kind of Display. The kinds below are made with it, and so is an application's. */
47
+ declare const kind: <Data = Record<string, never>>(name: string, spec: {
48
+ readonly shown?: boolean;
49
+ readonly text: (data: Data, value: unknown, words: DisplayWords) => string;
50
+ }) => DisplayKind<Data>;
51
+ declare const show: (display: Display, value: unknown, words?: DisplayWords) => string;
52
+ export declare const Display: {
53
+ /**
54
+ * A kind of Display. `Display.kind<{ tone: string }>('Badge', { text: (_, value) => String(value) })`
55
+ * gives `.of(data)` to make one and `.is(display)` to tell one, exactly as the
56
+ * kinds below were made. `text` is the floor; a view draws it specially once
57
+ * it is given a renderer for `Badge`.
58
+ */
59
+ kind: typeof kind;
60
+ Text: DisplayKind<{
61
+ readonly format?: ((value: unknown) => string) | undefined;
62
+ }>;
63
+ Number: DisplayKind<{
64
+ readonly format?: ((value: number) => string) | undefined;
65
+ }>;
66
+ Flag: DisplayKind<Record<string, never>>;
67
+ Hidden: DisplayKind<Record<string, never>>;
68
+ Ref: DisplayKind<{
69
+ readonly target: AnyEntity;
70
+ readonly many: boolean;
71
+ }>;
72
+ Nested: DisplayKind<{
73
+ readonly target: AnyEntity;
74
+ readonly shape: 'one' | 'many' | 'page';
75
+ readonly columns: ReadonlyArray<DisplayColumn>;
76
+ }>;
77
+ text: (format?: (value: unknown) => string) => Display;
78
+ number: (format?: (value: number) => string) => Display;
79
+ flag: () => Display;
80
+ /** Read, so a row can be opened or keyed by it, and not shown: usually the id. */
81
+ hidden: () => Display;
82
+ /**
83
+ * Entity metadata: how a member shows wherever it is listed, e.g.
84
+ * `Entity.annotateMembers({ price: Display.of(Display.number(cents => ...)) })`.
85
+ */
86
+ of: (display: Display) => Metadata;
87
+ /**
88
+ * The Display of one selected member, from the most to the least explicit
89
+ * source: the member's `Display.of` metadata, how the relation was selected,
90
+ * then the shape of its schema. `nested` is the columns of a nested Selection,
91
+ * with `shape` saying how many the relation yields.
92
+ */
93
+ resolve: (member: EntityMember, nested?: {
94
+ readonly shape: 'one' | 'many' | 'page';
95
+ readonly columns: ReadonlyArray<DisplayColumn>;
96
+ }) => Display;
97
+ /**
98
+ * A value as the text its Display calls for: what a cell says when nothing
99
+ * draws it specially. A view that wants a link or a badge reads the Display
100
+ * and the value itself; this is the floor every view can stand on.
101
+ */
102
+ show: typeof show;
103
+ };
104
+ export {};
105
+ //# sourceMappingURL=display.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display.d.ts","names":[],"sources":["../src/display.ts"],"mappings":";;;;;;;;iBAgBiB,QAAQ;;WAEd;;WAEA;;WAEA,MAAM;;;;;WAKN,OAAO,gBAAgB,OAAO;;;iBAIxB,YAAY;WAClB;WACA,KAAK,MAAM,SAAS,QAAQ;WAC5B,KAAK,SAAS,YAAY,WAAW,QAAQ;;;iBAIvC,cAAc;WACpB,KAAK;WACL;WACA,QAAQ;WACR,SAAS;;;iBAIH;;WAEN;;WAEA;;WAEA;;WAEA;;;cAoBL,OAAQ,OAAO,uBAAqB,cAC5B;WAED;WACA,OAAO,MAAM,MAAM,gBAAgB,OAAO;MAEpD,YAAY;cAYT,OAAI,SAAa,SAAO,gBAAgB,QAAS;qBAyD1C;;;;;;;;;aAtDyB,WAAE;;;aAGC,WAAE;;;;;aASP,QAAA;aAA0B;;;aAa3C,QAAA;aACD;aACE,SAAA,cAAc;;EA4ChB,OAAA,UAAC,8BAA4B;EAC3B,SAAA,UAAC,6BAA2B;EACpC,YAAA;;EAEE,cAAA;;;;;EAME,KAAA,SAAA,YAAO;;;;;;;EASX,UAAA,QAAA,cAAY;aAET;aACA,SAAS,cAAc;QAEjC"}
@@ -0,0 +1,111 @@
1
+ import { Schema, SchemaAST } from "effect";
2
+ import { SchemaShape } from "foldkit-entity";
3
+ import { Metadata } from "foldkit-metadata";
4
+ // src/display.ts
5
+ /**
6
+ * Displays: how one selected member shows in a list or a detail, described
7
+ * without a renderer. It is `foldkit-form`'s `Input` from the reading side: the
8
+ * member says what it is, a Display says how it reads, and which DOM draws it is
9
+ * the application's.
10
+ */
11
+ const key = Metadata.key("foldkit-crud/display", {
12
+ merge: (displays) => displays.slice(-1),
13
+ summarize: (display) => display.kind
14
+ });
15
+ const fromSchema = (schema) => {
16
+ const members = SchemaShape.present(Schema.toType(schema).ast);
17
+ const [only] = members;
18
+ if (members.length === 1 && only !== void 0) {
19
+ if (SchemaAST.isNumber(only)) return Number_.of({});
20
+ if (SchemaAST.isBoolean(only)) return Flag.of(nothing);
21
+ }
22
+ return Text.of({});
23
+ };
24
+ /** A kind of Display. The kinds below are made with it, and so is an application's. */
25
+ const kind = (name, spec) => ({
26
+ kind: name,
27
+ of: (data) => Object.freeze({
28
+ kind: name,
29
+ shown: spec.shown ?? true,
30
+ data,
31
+ text: (value, words) => spec.text(data, value, words)
32
+ }),
33
+ is: (display) => display.kind === name
34
+ });
35
+ const show = (display, value, words = {}) => value === null || value === void 0 ? words.nothing ?? "" : display.text(value, words);
36
+ const Text = kind("Text", { text: (data, value) => data.format === void 0 ? String(value) : data.format(value) });
37
+ const Number_ = kind("Number", { text: (data, value) => typeof value === "number" && data.format !== void 0 ? data.format(value) : String(value) });
38
+ const Flag = kind("Flag", { text: (_, value, words) => value === true ? words.yes ?? "yes" : words.no ?? "no" });
39
+ const Hidden = kind("Hidden", {
40
+ shown: false,
41
+ text: () => ""
42
+ });
43
+ /** A relation read as refs: which one, with nothing to say about it but its id. */
44
+ const Ref = kind("Ref", { text: (_, value, words) => {
45
+ const ids = (Array.isArray(value) ? value : [value]).map((ref) => typeof ref === "object" && ref !== null && "id" in ref ? String(ref.id) : String(ref));
46
+ return ids.length === 0 ? words.nothing ?? "" : ids.join(words.separator ?? ", ");
47
+ } });
48
+ /**
49
+ * A relation read through a Selection: the target's own members, each with a
50
+ * Display. `shape` is how many there are: one, a list, or a page of a list.
51
+ */
52
+ const Nested = kind("Nested", { text: (data, value, words) => {
53
+ const one = (item) => data.columns.filter((column) => column.display.shown).map((column) => show(column.display, item?.[column.key], words)).filter((text) => text !== "").join(" ");
54
+ const items = data.shape === "one" ? [value] : data.shape === "page" ? value.items ?? [] : value;
55
+ return items.length === 0 ? words.nothing ?? "" : items.map(one).join(words.separator ?? ", ");
56
+ } });
57
+ const nothing = Object.freeze({});
58
+ const Display = {
59
+ /**
60
+ * A kind of Display. `Display.kind<{ tone: string }>('Badge', { text: (_, value) => String(value) })`
61
+ * gives `.of(data)` to make one and `.is(display)` to tell one, exactly as the
62
+ * kinds below were made. `text` is the floor; a view draws it specially once
63
+ * it is given a renderer for `Badge`.
64
+ */
65
+ kind,
66
+ Text,
67
+ Number: Number_,
68
+ Flag,
69
+ Hidden,
70
+ Ref,
71
+ Nested,
72
+ text: (format) => Text.of({ format }),
73
+ number: (format) => Number_.of({ format }),
74
+ flag: () => Flag.of(nothing),
75
+ /** Read, so a row can be opened or keyed by it, and not shown: usually the id. */
76
+ hidden: () => Hidden.of(nothing),
77
+ /**
78
+ * Entity metadata: how a member shows wherever it is listed, e.g.
79
+ * `Entity.annotateMembers({ price: Display.of(Display.number(cents => ...)) })`.
80
+ */
81
+ of: (display) => key.of(display),
82
+ /**
83
+ * The Display of one selected member, from the most to the least explicit
84
+ * source: the member's `Display.of` metadata, how the relation was selected,
85
+ * then the shape of its schema. `nested` is the columns of a nested Selection,
86
+ * with `shape` saying how many the relation yields.
87
+ */
88
+ resolve: (member, nested) => {
89
+ const [explicit] = key.get(member.metadata);
90
+ if (explicit !== void 0) return explicit;
91
+ if (member._tag !== "Relation") return fromSchema(member.schema);
92
+ const target = member.target();
93
+ return nested === void 0 ? Ref.of({
94
+ target,
95
+ many: member.cardinality === "many"
96
+ }) : Nested.of({
97
+ target,
98
+ shape: nested.shape,
99
+ columns: nested.columns
100
+ });
101
+ },
102
+ /**
103
+ * A value as the text its Display calls for: what a cell says when nothing
104
+ * draws it specially. A view that wants a link or a badge reads the Display
105
+ * and the value itself; this is the floor every view can stand on.
106
+ */
107
+ show
108
+ };
109
+ export { Display };
110
+
111
+ //# sourceMappingURL=display.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display.js","names":[],"sources":["../src/display.ts"],"sourcesContent":["/**\n * Displays: how one selected member shows in a list or a detail, described\n * without a renderer. It is `foldkit-form`'s `Input` from the reading side: the\n * member says what it is, a Display says how it reads, and which DOM draws it is\n * the application's.\n */\nimport { Schema, SchemaAST } from 'effect'\nimport { SchemaShape, type AnyEntity, type EntityMember } from 'foldkit-entity'\nimport { Metadata } from 'foldkit-metadata'\n\n/**\n * How one selected member shows: the primitive every kind of Display is a value\n * of. `Display.text()` and `Display.flag()` are values of it, made by\n * `Display.kind`, which is what an application calls for a badge or a relative\n * date. The kinds here are a collection, not a special case.\n */\nexport interface Display<Data = unknown> {\n /** The name a renderer is found by. */\n readonly kind: string\n /** Whether a view draws it. A member read and not shown, usually the id, is `false`. */\n readonly shown: boolean\n /** What this kind needs: a format, a relation's target. */\n readonly data: Data\n /**\n * The value as text: what a cell says when nothing draws it specially. It is\n * never given `null` or `undefined`; `Display.show` says `nothing` for those.\n */\n readonly text: (value: unknown, words: DisplayWords) => string\n}\n\n/** A kind of Display: how its values are made, and how one is told from another. */\nexport interface DisplayKind<Data> {\n readonly kind: string\n readonly of: (data: Data) => Display<Data>\n readonly is: (display: Display) => display is Display<Data>\n}\n\n/** A selected member with its words and its Display. A list's column, a detail's line. */\nexport interface DisplayColumn<Key extends string = string> {\n readonly key: Key\n readonly label: string\n readonly member: EntityMember\n readonly display: Display\n}\n\n/** The words a Display needs that are not the value's own. */\nexport interface DisplayWords {\n /** Default `yes`. */\n readonly yes?: string\n /** Default `no`. */\n readonly no?: string\n /** What stands for nothing: `null`, `undefined`, an empty list. Default the empty string. */\n readonly nothing?: string\n /** Between the items of a list, and between the members of a nested value. Default `, `. */\n readonly separator?: string\n}\n\nconst key = Metadata.key<Display>('foldkit-crud/display', {\n // The last Display attached wins: a later annotation refines an earlier one.\n merge: displays => displays.slice(-1),\n summarize: display => display.kind,\n})\n\nconst fromSchema = (schema: Schema.Top): Display => {\n const members = SchemaShape.present(Schema.toType(schema).ast)\n const [only] = members\n if (members.length === 1 && only !== undefined) {\n if (SchemaAST.isNumber(only)) return Number_.of({})\n if (SchemaAST.isBoolean(only)) return Flag.of(nothing)\n }\n return Text.of({})\n}\n\n/** A kind of Display. The kinds below are made with it, and so is an application's. */\nconst kind = <Data = Record<string, never>>(\n name: string,\n spec: {\n readonly shown?: boolean\n readonly text: (data: Data, value: unknown, words: DisplayWords) => string\n },\n): DisplayKind<Data> => ({\n kind: name,\n of: data =>\n Object.freeze({\n kind: name,\n shown: spec.shown ?? true,\n data,\n text: (value: unknown, words: DisplayWords) => spec.text(data, value, words),\n }),\n is: (display): display is Display<Data> => display.kind === name,\n})\n\nconst show = (display: Display, value: unknown, words: DisplayWords = {}): string =>\n value === null || value === undefined ? (words.nothing ?? '') : display.text(value, words)\n\nconst Text = kind<{ readonly format?: ((value: unknown) => string) | undefined }>('Text', {\n text: (data, value) => (data.format === undefined ? String(value) : data.format(value)),\n})\nconst Number_ = kind<{ readonly format?: ((value: number) => string) | undefined }>('Number', {\n text: (data, value) =>\n typeof value === 'number' && data.format !== undefined ? data.format(value) : String(value),\n})\nconst Flag = kind('Flag', {\n text: (_, value, words) => (value === true ? (words.yes ?? 'yes') : (words.no ?? 'no')),\n})\nconst Hidden = kind('Hidden', { shown: false, text: () => '' })\n/** A relation read as refs: which one, with nothing to say about it but its id. */\nconst Ref = kind<{ readonly target: AnyEntity; readonly many: boolean }>('Ref', {\n text: (_, value, words) => {\n const ids = (Array.isArray(value) ? value : [value]).map(ref =>\n typeof ref === 'object' && ref !== null && 'id' in ref ? String(ref.id) : String(ref),\n )\n return ids.length === 0 ? (words.nothing ?? '') : ids.join(words.separator ?? ', ')\n },\n})\n/**\n * A relation read through a Selection: the target's own members, each with a\n * Display. `shape` is how many there are: one, a list, or a page of a list.\n */\nconst Nested = kind<{\n readonly target: AnyEntity\n readonly shape: 'one' | 'many' | 'page'\n readonly columns: ReadonlyArray<DisplayColumn>\n}>('Nested', {\n text: (data, value, words) => {\n const one = (item: unknown): string =>\n data.columns\n .filter(column => column.display.shown)\n .map(column =>\n show(\n column.display,\n (item as Readonly<Record<string, unknown>> | null)?.[column.key],\n words,\n ),\n )\n .filter(text => text !== '')\n .join(' ')\n const items =\n data.shape === 'one'\n ? [value]\n : data.shape === 'page'\n ? ((value as { readonly items?: ReadonlyArray<unknown> }).items ?? [])\n : (value as ReadonlyArray<unknown>)\n return items.length === 0 ? (words.nothing ?? '') : items.map(one).join(words.separator ?? ', ')\n },\n})\n\nconst nothing: Record<string, never> = Object.freeze({})\n\nexport const Display = {\n /**\n * A kind of Display. `Display.kind<{ tone: string }>('Badge', { text: (_, value) => String(value) })`\n * gives `.of(data)` to make one and `.is(display)` to tell one, exactly as the\n * kinds below were made. `text` is the floor; a view draws it specially once\n * it is given a renderer for `Badge`.\n */\n kind,\n\n // The kinds this package resolves to. A view finds its renderer by `kind`.\n Text,\n Number: Number_,\n Flag,\n Hidden,\n Ref,\n Nested,\n\n text: (format?: (value: unknown) => string): Display => Text.of({ format }),\n number: (format?: (value: number) => string): Display => Number_.of({ format }),\n flag: (): Display => Flag.of(nothing),\n /** Read, so a row can be opened or keyed by it, and not shown: usually the id. */\n hidden: (): Display => Hidden.of(nothing),\n\n /**\n * Entity metadata: how a member shows wherever it is listed, e.g.\n * `Entity.annotateMembers({ price: Display.of(Display.number(cents => ...)) })`.\n */\n of: (display: Display) => key.of(display),\n\n /**\n * The Display of one selected member, from the most to the least explicit\n * source: the member's `Display.of` metadata, how the relation was selected,\n * then the shape of its schema. `nested` is the columns of a nested Selection,\n * with `shape` saying how many the relation yields.\n */\n resolve: (\n member: EntityMember,\n nested?: {\n readonly shape: 'one' | 'many' | 'page'\n readonly columns: ReadonlyArray<DisplayColumn>\n },\n ): Display => {\n const [explicit] = key.get(member.metadata)\n if (explicit !== undefined) return explicit\n if (member._tag !== 'Relation') return fromSchema(member.schema as Schema.Top)\n const target = member.target()\n return nested === undefined\n ? Ref.of({ target, many: member.cardinality === 'many' })\n : Nested.of({ target, shape: nested.shape, columns: nested.columns })\n },\n\n /**\n * A value as the text its Display calls for: what a cell says when nothing\n * draws it specially. A view that wants a link or a badge reads the Display\n * and the value itself; this is the floor every view can stand on.\n */\n show,\n}\n"],"mappings":"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"}