@thomasfosterau/pulpit 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +1272 -2
- package/dist/blobs.d.ts +249 -0
- package/dist/blobs.d.ts.map +1 -0
- package/dist/blobs.js +193 -0
- package/dist/blobs.js.map +1 -0
- package/dist/budgets.d.ts +255 -0
- package/dist/budgets.d.ts.map +1 -0
- package/dist/budgets.js +211 -0
- package/dist/budgets.js.map +1 -0
- package/dist/cache.d.ts +154 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +118 -0
- package/dist/cache.js.map +1 -0
- package/dist/collections.d.ts +242 -0
- package/dist/collections.d.ts.map +1 -0
- package/dist/collections.js +215 -0
- package/dist/collections.js.map +1 -0
- package/dist/comments.d.ts +212 -0
- package/dist/comments.d.ts.map +1 -0
- package/dist/comments.js +192 -0
- package/dist/comments.js.map +1 -0
- package/dist/content.d.ts +231 -0
- package/dist/content.d.ts.map +1 -0
- package/dist/content.js +204 -0
- package/dist/content.js.map +1 -0
- package/dist/documents.d.ts +184 -0
- package/dist/documents.d.ts.map +1 -0
- package/dist/documents.js +190 -0
- package/dist/documents.js.map +1 -0
- package/dist/edges.d.ts +645 -0
- package/dist/edges.d.ts.map +1 -0
- package/dist/edges.js +558 -0
- package/dist/edges.js.map +1 -0
- package/dist/filter.d.ts +461 -0
- package/dist/filter.d.ts.map +1 -0
- package/dist/filter.js +387 -0
- package/dist/filter.js.map +1 -0
- package/dist/index.d.ts +133 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +133 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/filter-columns.d.ts +8 -0
- package/dist/internal/filter-columns.d.ts.map +1 -0
- package/dist/internal/filter-columns.js +43 -0
- package/dist/internal/filter-columns.js.map +1 -0
- package/dist/internal/list-order.d.ts +26 -0
- package/dist/internal/list-order.d.ts.map +1 -0
- package/dist/internal/list-order.js +92 -0
- package/dist/internal/list-order.js.map +1 -0
- package/dist/internal/owned-columns.d.ts +93 -0
- package/dist/internal/owned-columns.d.ts.map +1 -0
- package/dist/internal/owned-columns.js +98 -0
- package/dist/internal/owned-columns.js.map +1 -0
- package/dist/internal/plain-rows.d.ts +32 -0
- package/dist/internal/plain-rows.d.ts.map +1 -0
- package/dist/internal/plain-rows.js +32 -0
- package/dist/internal/plain-rows.js.map +1 -0
- package/dist/internal/reference-columns.d.ts +80 -0
- package/dist/internal/reference-columns.d.ts.map +1 -0
- package/dist/internal/reference-columns.js +102 -0
- package/dist/internal/reference-columns.js.map +1 -0
- package/dist/moderation.d.ts +392 -0
- package/dist/moderation.d.ts.map +1 -0
- package/dist/moderation.js +375 -0
- package/dist/moderation.js.map +1 -0
- package/dist/paths.d.ts +204 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +165 -0
- package/dist/paths.js.map +1 -0
- package/dist/proposals.d.ts +523 -0
- package/dist/proposals.d.ts.map +1 -0
- package/dist/proposals.js +505 -0
- package/dist/proposals.js.map +1 -0
- package/dist/publication.d.ts +148 -0
- package/dist/publication.d.ts.map +1 -0
- package/dist/publication.js +183 -0
- package/dist/publication.js.map +1 -0
- package/dist/purge.d.ts +224 -0
- package/dist/purge.d.ts.map +1 -0
- package/dist/purge.js +151 -0
- package/dist/purge.js.map +1 -0
- package/dist/reactions.d.ts +246 -0
- package/dist/reactions.d.ts.map +1 -0
- package/dist/reactions.js +183 -0
- package/dist/reactions.js.map +1 -0
- package/dist/registry.d.ts +316 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +305 -0
- package/dist/registry.js.map +1 -0
- package/dist/search.d.ts +366 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +273 -0
- package/dist/search.js.map +1 -0
- package/dist/social.d.ts +311 -0
- package/dist/social.d.ts.map +1 -0
- package/dist/social.js +205 -0
- package/dist/social.js.map +1 -0
- package/dist/subtype.d.ts +1613 -0
- package/dist/subtype.d.ts.map +1 -0
- package/dist/subtype.js +1300 -0
- package/dist/subtype.js.map +1 -0
- package/dist/testing.d.ts +675 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +1022 -0
- package/dist/testing.js.map +1 -0
- package/dist/version-chain.d.ts +702 -0
- package/dist/version-chain.d.ts.map +1 -0
- package/dist/version-chain.js +489 -0
- package/dist/version-chain.js.map +1 -0
- package/dist/working-copy.d.ts +116 -0
- package/dist/working-copy.d.ts.map +1 -0
- package/dist/working-copy.js +95 -0
- package/dist/working-copy.js.map +1 -0
- package/package.json +145 -3
- package/src/blobs.ts +384 -0
- package/src/budgets.ts +338 -0
- package/src/cache.ts +218 -0
- package/src/collections.ts +427 -0
- package/src/comments.ts +392 -0
- package/src/content.ts +238 -0
- package/src/documents.ts +284 -0
- package/src/edges.ts +1185 -0
- package/src/filter.ts +523 -0
- package/src/index.ts +153 -0
- package/src/internal/filter-columns.ts +50 -0
- package/src/internal/list-order.ts +117 -0
- package/src/internal/owned-columns.ts +140 -0
- package/src/internal/plain-rows.ts +54 -0
- package/src/internal/reference-columns.ts +156 -0
- package/src/moderation.ts +728 -0
- package/src/paths.ts +267 -0
- package/src/proposals.ts +1014 -0
- package/src/publication.ts +225 -0
- package/src/purge.ts +313 -0
- package/src/reactions.ts +347 -0
- package/src/registry.ts +524 -0
- package/src/search.ts +540 -0
- package/src/social.ts +469 -0
- package/src/subtype.ts +3095 -0
- package/src/testing.ts +1873 -0
- package/src/version-chain.ts +1093 -0
- package/src/working-copy.ts +192 -0
package/dist/edges.js
ADDED
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **The edge operations factory** — a relation between nodes as its own
|
|
3
|
+
* family: a bounded list, a read by id, an idempotent create and a hard
|
|
4
|
+
* delete, gated by the visibility of the nodes the edge joins.
|
|
5
|
+
*
|
|
6
|
+
* The behavioural spec is gardeneria's `apps/api/src/operations/edge-ops.ts`
|
|
7
|
+
* (`defineEdgeOpsE`), which exists because hand-rolled edge families drift,
|
|
8
|
+
* and the ninth family's viewer gate or `LIMIT` gets forgotten. Its
|
|
9
|
+
* hand-rolled owned-child family (`disorders.ts`, the observation → disorder
|
|
10
|
+
* edge) is the spec for the endpoint gates. A `#NNN` here names a gardeneria
|
|
11
|
+
* issue.
|
|
12
|
+
*
|
|
13
|
+
* ## What an edge is
|
|
14
|
+
*
|
|
15
|
+
* An edge is a plain row in its own table: an id, a `createdAt`, one column
|
|
16
|
+
* per **end** holding the id of the node at that end, and any qualifier
|
|
17
|
+
* columns of the family's own. It is **not** a node: it has no version chain,
|
|
18
|
+
* so the chain invariants (`VERSION-CHAIN-001/002`) do not govern it. A delete
|
|
19
|
+
* is a hard `DELETE`, and there is no update: correcting an edge is deleting
|
|
20
|
+
* it and asserting the right one. A family declares zero, one or two (or
|
|
21
|
+
* more) ends; with none, it is a plain bounded row family (gardeneria's
|
|
22
|
+
* `page_collections`).
|
|
23
|
+
*
|
|
24
|
+
* ## The invariants
|
|
25
|
+
*
|
|
26
|
+
* - **An edge is readable only if the viewer can read every end**
|
|
27
|
+
* (`EDGE-001`). Each end's node is checked against its own leaf's access
|
|
28
|
+
* declaration, as that leaf's own `get` and list filter read it (a
|
|
29
|
+
* reference leaf's followers arm included, pulpit#92). `get` answers a
|
|
30
|
+
* hidden edge as {@link EdgeNotFound} and `list` omits it, never `Forbidden`
|
|
31
|
+
* (`SEC-AUTH-ENUM-001`); a related list (the edges at one node) is a `list`
|
|
32
|
+
* filtered on that end, so it omits every edge whose other end is hidden.
|
|
33
|
+
* - **The list filter and the per-edge predicate never disagree.**
|
|
34
|
+
* {@link endpointFilter} renders the same facts {@link canViewEndpoint}
|
|
35
|
+
* reads, over the ends' joined views; `tests/edges.test.ts` checks every
|
|
36
|
+
* endpoint state × viewer.
|
|
37
|
+
* - **A tombstoned end hides its edges** from every viewer below the
|
|
38
|
+
* view-deleted rung. That rung reads a tombstoned end as the leaf's own
|
|
39
|
+
* `get` reads the tombstone, by its access rule (pulpit#93), so it can
|
|
40
|
+
* list, read and delete an edge whose only hidden end is tombstoned; an
|
|
41
|
+
* end hidden for any other reason (a `private` node below the
|
|
42
|
+
* view-private rung, say) still hides the edge from it. Nothing is
|
|
43
|
+
* deleted: restoring the node (the explicit `restore`,
|
|
44
|
+
* `VERSION-CHAIN-006`) brings its edges back as they were.
|
|
45
|
+
* - **A create names only live nodes the viewer can read.** An end naming a
|
|
46
|
+
* missing, hidden or tombstoned node fails `NodeNotFound` (the
|
|
47
|
+
* view-deleted rung included), so a create cannot confirm a node exists.
|
|
48
|
+
* - **Cardinality is declared, and a create past it fails**
|
|
49
|
+
* ({@link EdgeCardinalityExceeded}). An end's `maxEdges` bounds how many
|
|
50
|
+
* edges may share one node at that end, counting only the edges the
|
|
51
|
+
* caller can read whose every end is live (pulpit#77, pulpit#93). A
|
|
52
|
+
* hidden edge never counts, so a refusal discloses nothing the caller
|
|
53
|
+
* can't read; the cost is a limit that holds only over what each caller
|
|
54
|
+
* sees, and a restore that can bring a node past it (see
|
|
55
|
+
* {@link EdgeEnd.maxEdges}). A re-assertion of a stored edge resolves
|
|
56
|
+
* before the count, so it stays idempotent at a full node.
|
|
57
|
+
* - **A write discloses no hidden edge's state.** A create runs in the
|
|
58
|
+
* order ends → write gate → unique-key collision → cardinality count.
|
|
59
|
+
* Under `"fail"` a collision with a hidden edge answers exactly as one
|
|
60
|
+
* with a readable edge; under `"ignore"` only a readable, live edge
|
|
61
|
+
* resolves, and any other collision is {@link EdgeConflict}. The count
|
|
62
|
+
* reads only readable edges (README → `./edges` → What a write
|
|
63
|
+
* discloses).
|
|
64
|
+
* - **Every list is bounded** (`SEC-INPUT-003`): a page is capped at
|
|
65
|
+
* `MAX_PAGE_LIMIT`.
|
|
66
|
+
*
|
|
67
|
+
* ## The seam
|
|
68
|
+
*
|
|
69
|
+
* The edges are read and written through an {@link EdgeStore} the
|
|
70
|
+
* application supplies (a Drizzle store over the edge table, joining each
|
|
71
|
+
* end's current-version view; see the package README → Seams). Each end
|
|
72
|
+
* reads its nodes through an {@link EndpointView}, which a `./subtype`
|
|
73
|
+
* `LeafStore` already satisfies.
|
|
74
|
+
*
|
|
75
|
+
* @copyright Thomas Foster
|
|
76
|
+
* @module pulpit/edges
|
|
77
|
+
* @since 0.1.0
|
|
78
|
+
*/
|
|
79
|
+
import * as Arr from "effect/Array";
|
|
80
|
+
import * as Effect from "effect/Effect";
|
|
81
|
+
import * as Formatter from "effect/Formatter";
|
|
82
|
+
import * as HashMap from "effect/HashMap";
|
|
83
|
+
import * as Option from "effect/Option";
|
|
84
|
+
import * as Order from "effect/Order";
|
|
85
|
+
import * as Predicate from "effect/Predicate";
|
|
86
|
+
import * as Record from "effect/Record";
|
|
87
|
+
import * as Schema from "effect/Schema";
|
|
88
|
+
import { always, and, anyOf, eq, gt, isIn, isNull, lt, lte, isNotIn, MAX_SET_VALUES, never, or, } from "./filter.js";
|
|
89
|
+
import { renameColumns } from "./internal/filter-columns.js";
|
|
90
|
+
import { canViewOwnedRow, declaresColumns, ownedFacts } from "./internal/owned-columns.js";
|
|
91
|
+
import { canViewReferenceRow, referenceListFilter } from "./internal/reference-columns.js";
|
|
92
|
+
import { Forbidden, MAX_PAGE_LIMIT, ownedListFilter, readScopeFor, Unauthorized, } from "./subtype.js";
|
|
93
|
+
import { NodeNotFound } from "./version-chain.js";
|
|
94
|
+
/** A column value as text for an error: a string as itself, anything else formatted (never `[object Object]`). */
|
|
95
|
+
const columnText = (value) => Predicate.isString(value) ? value : Formatter.format(value);
|
|
96
|
+
// ── Errors ────────────────────────────────────────────────────────────
|
|
97
|
+
/**
|
|
98
|
+
* No edge with this id that the viewer may read: missing, or hidden because
|
|
99
|
+
* an end is (`SEC-AUTH-ENUM-001`, `EDGE-001`). The wire's 404.
|
|
100
|
+
*
|
|
101
|
+
* @since 0.1.0
|
|
102
|
+
*/
|
|
103
|
+
export class EdgeNotFound extends Schema.TaggedError()("EdgeNotFound", {
|
|
104
|
+
type: Schema.String,
|
|
105
|
+
id: Schema.String,
|
|
106
|
+
}) {
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* A create collided with a stored edge on the family's unique key, and the
|
|
110
|
+
* family's conflict policy does not resolve it: `onConflict: "fail"`, or the
|
|
111
|
+
* edge it collided with is one the viewer may not read or has a tombstoned
|
|
112
|
+
* end. The wire's 409. It carries only the family's type, so under `"fail"`
|
|
113
|
+
* a collision with a hidden edge is the same answer as one with a readable
|
|
114
|
+
* edge (`SEC-AUTH-ENUM-001`, pulpit#93); under `"ignore"` only a readable,
|
|
115
|
+
* live edge resolves, and any other collision is this error. It says the
|
|
116
|
+
* key is taken, never by which edge.
|
|
117
|
+
*
|
|
118
|
+
* @since 0.1.0
|
|
119
|
+
*/
|
|
120
|
+
export class EdgeConflict extends Schema.TaggedError()("EdgeConflict", {
|
|
121
|
+
type: Schema.String,
|
|
122
|
+
}) {
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* A create would put more edges at one node than its end's declared
|
|
126
|
+
* `maxEdges` allows, counting only the edges the caller can read whose every
|
|
127
|
+
* end is live ({@link EdgeEnd.maxEdges}). The wire's 409.
|
|
128
|
+
*
|
|
129
|
+
* @since 0.1.0
|
|
130
|
+
*/
|
|
131
|
+
export class EdgeCardinalityExceeded extends Schema.TaggedError()("EdgeCardinalityExceeded", {
|
|
132
|
+
/** The edge family's wire type. */
|
|
133
|
+
type: Schema.String,
|
|
134
|
+
/** The end (its alias in the declaration) whose limit was reached. */
|
|
135
|
+
end: Schema.String,
|
|
136
|
+
/** The node at that end, which already holds `max` edges the caller can read. */
|
|
137
|
+
nodeId: Schema.String,
|
|
138
|
+
/** The declared limit. */
|
|
139
|
+
max: Schema.Int,
|
|
140
|
+
}) {
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* An edge family declared against the rules: an end's alias contains a `.`,
|
|
144
|
+
* or its `maxEdges` is not a positive safe integer. Thrown by
|
|
145
|
+
* {@link defineEdgeOps} when the family is declared, never an Effect failure,
|
|
146
|
+
* like `RegistryDeclarationError`: a malformed family must stop its module
|
|
147
|
+
* loading rather than fail open (a `NaN` limit admits every create) or
|
|
148
|
+
* refuse every create (a limit of `0`).
|
|
149
|
+
*
|
|
150
|
+
* @since 0.1.0
|
|
151
|
+
*/
|
|
152
|
+
export class EdgeDeclarationError extends Schema.TaggedError()("EdgeDeclarationError", { message: Schema.String }) {
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* The list-filter column naming `column` of the node at end `alias`:
|
|
156
|
+
* `alias.column`. {@link endpointFilter} writes these, a family's own list
|
|
157
|
+
* filter may too, and a store renders each against the view it joined under
|
|
158
|
+
* that alias.
|
|
159
|
+
*
|
|
160
|
+
* @since 0.1.0
|
|
161
|
+
*/
|
|
162
|
+
export const endpointColumn = (alias, column) => `${alias}.${column}`;
|
|
163
|
+
/** Every column of `filter` rewritten to name the node at end `alias`. */
|
|
164
|
+
const qualify = (alias, filter) => renameColumns(filter, (column) => endpointColumn(alias, column));
|
|
165
|
+
/** A live node: its head is a `create` or an `update`, never a tombstone. */
|
|
166
|
+
const isLive = (row) => row.action === "create" || row.action === "update";
|
|
167
|
+
/** {@link isLive} as a list filter over one view's columns. */
|
|
168
|
+
const liveFilter = () => or(eq("action", "create"), eq("action", "update"));
|
|
169
|
+
/**
|
|
170
|
+
* Whether the viewer may read the node at one end (`EDGE-001`): it exists,
|
|
171
|
+
* it is live or the viewer holds the view-deleted rung (a tombstone is read
|
|
172
|
+
* as the leaf's own `get` reads it, pulpit#93), and its leaf's access admits
|
|
173
|
+
* the viewer, a tombstone's included. A reference node is
|
|
174
|
+
* readable when its view has no `visibility` column, the viewer holds the
|
|
175
|
+
* view-private rung, it is `public`, or it is `followers` and the viewer is,
|
|
176
|
+
* or follows, the account its leaf's declared `followersOfColumn` names (the
|
|
177
|
+
* predicate `defineSubtype`'s `get` runs, pulpit#92); an owned node through
|
|
178
|
+
* `canViewOwned`'s predicate, where an owner column holding no string reads
|
|
179
|
+
* as no owner, matching no viewer and never asked of the follower seam. An
|
|
180
|
+
* owned declaration naming a column the view lacks reads nothing. Never
|
|
181
|
+
* fails.
|
|
182
|
+
*
|
|
183
|
+
* @since 0.1.0
|
|
184
|
+
*/
|
|
185
|
+
export const canViewEndpoint = (end, viewer, policy, followers, node) => {
|
|
186
|
+
if (Option.isNone(node))
|
|
187
|
+
return Effect.succeed(false);
|
|
188
|
+
if (!isLive(node.value) && !Option.exists(viewer, policy.canViewDeleted)) {
|
|
189
|
+
return Effect.succeed(false);
|
|
190
|
+
}
|
|
191
|
+
const { access } = end;
|
|
192
|
+
const { columns } = end.nodes;
|
|
193
|
+
if (access.kind === "reference") {
|
|
194
|
+
return canViewReferenceRow(access, columns, viewer, policy, followers, node.value);
|
|
195
|
+
}
|
|
196
|
+
if (!declaresColumns(access, columns))
|
|
197
|
+
return Effect.succeed(false);
|
|
198
|
+
return canViewOwnedRow(viewer, policy, followers, ownedFacts(access, node.value));
|
|
199
|
+
};
|
|
200
|
+
/**
|
|
201
|
+
* The list arm of `EDGE-001`: for every end, its node is live (or the viewer
|
|
202
|
+
* holds the view-deleted rung) and readable by the viewer, over the columns
|
|
203
|
+
* {@link endpointColumn} names. The same facts as {@link canViewEndpoint},
|
|
204
|
+
* rendered as a `ListFilter` — the owned arm is `ownedListFilter`, the
|
|
205
|
+
* reference arm `referencePrivacyFilter`'s, followers arm included
|
|
206
|
+
* (pulpit#92) — so the two never disagree. A
|
|
207
|
+
* family with no ends gets `always`.
|
|
208
|
+
*
|
|
209
|
+
* @since 0.1.0
|
|
210
|
+
*/
|
|
211
|
+
export const endpointFilter = (ends, viewer, policy, followers) => {
|
|
212
|
+
const scope = readScopeFor(viewer, policy, followers);
|
|
213
|
+
const lifecycle = Option.exists(viewer, policy.canViewDeleted) ? always : liveFilter();
|
|
214
|
+
return and(...Record.toEntries(ends).map(([alias, end]) => qualify(alias, and(lifecycle, end.access.kind === "owned"
|
|
215
|
+
? ownedListFilter(end.access, end.nodes.columns, scope)
|
|
216
|
+
: referenceListFilter(end.access, end.nodes.columns, scope)))));
|
|
217
|
+
};
|
|
218
|
+
/** Every end's node is live, over the columns {@link endpointColumn} names: the cardinality count's other arm. */
|
|
219
|
+
const liveEndsFilter = (ends) => and(...Record.toEntries(ends).map(([alias]) => qualify(alias, liveFilter())));
|
|
220
|
+
/**
|
|
221
|
+
* A gate on one rung of the role axes: anonymous fails `Unauthorized`, a
|
|
222
|
+
* signed-in viewer below the rung `Forbidden`. `rungGate((policy) =>
|
|
223
|
+
* policy.canModerate)` is the moderator rung gardeneria's CMS edges take.
|
|
224
|
+
*
|
|
225
|
+
* @since 0.1.0
|
|
226
|
+
*/
|
|
227
|
+
export const rungGate = (rung) => (request) => Option.match(request.viewer, {
|
|
228
|
+
onNone: () => Effect.fail(new Unauthorized()),
|
|
229
|
+
onSome: (account) => rung(request.policy)(account) ? Effect.succeed(account) : Effect.fail(new Forbidden()),
|
|
230
|
+
});
|
|
231
|
+
/**
|
|
232
|
+
* The default write gate: the corpus-write rung. Right for an edge joining
|
|
233
|
+
* reference rows, which is itself reference data.
|
|
234
|
+
*
|
|
235
|
+
* @since 0.1.0
|
|
236
|
+
*/
|
|
237
|
+
export const corpusWriteGate = rungGate((policy) => policy.canWriteCorpus);
|
|
238
|
+
/**
|
|
239
|
+
* An edge's validity interval is malformed: a bound that is neither a
|
|
240
|
+
* `Date` nor `NULL`, `from` after `to`, or a close that would widen it. The
|
|
241
|
+
* wire's 422.
|
|
242
|
+
*
|
|
243
|
+
* @since 0.1.0
|
|
244
|
+
*/
|
|
245
|
+
export class InvalidValidity extends Schema.TaggedError()("InvalidValidity", {
|
|
246
|
+
type: Schema.String,
|
|
247
|
+
reason: Schema.String,
|
|
248
|
+
}) {
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* The edges valid at `at` (pulpit#210), as a list filter over a family's
|
|
252
|
+
* {@link EdgeValidity} columns: `from` is `NULL` or at or before `at`, and
|
|
253
|
+
* `to` is `NULL` or after it. Pass it as a list's `where`, so "who held
|
|
254
|
+
* the office on that day" is one gated read.
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* ```ts
|
|
258
|
+
* import { strictEqual } from "node:assert";
|
|
259
|
+
* import { validAt } from "@thomasfosterau/pulpit/edges";
|
|
260
|
+
* import { evaluate } from "@thomasfosterau/pulpit/filter";
|
|
261
|
+
*
|
|
262
|
+
* const filter = validAt({ from: "validFrom", to: "validTo" }, new Date("2020-06-01"));
|
|
263
|
+
* const context = { now: new Date(0), contains: () => false };
|
|
264
|
+
* const row = { validFrom: new Date("2020-01-01"), validTo: null };
|
|
265
|
+
* strictEqual(evaluate(filter, row, context), true);
|
|
266
|
+
* strictEqual(evaluate(filter, { ...row, validTo: new Date("2020-03-01") }, context), false);
|
|
267
|
+
* ```
|
|
268
|
+
*
|
|
269
|
+
* @since 0.1.0
|
|
270
|
+
*/
|
|
271
|
+
export const validAt = (validity, at) => and(or(isNull(validity.from), lte(validity.from, at)), or(isNull(validity.to), gt(validity.to, at)));
|
|
272
|
+
/**
|
|
273
|
+
* The edges whose interval overlaps `[from, to)` (either bound none for
|
|
274
|
+
* open): `NULL`-or-before `to` on the `from` column, and `NULL`-or-after
|
|
275
|
+
* `from` on the `to` column.
|
|
276
|
+
*/
|
|
277
|
+
const overlapping = (validity, from, to) => and(Option.match(to, {
|
|
278
|
+
onNone: () => always,
|
|
279
|
+
onSome: (end) => or(isNull(validity.from), lt(validity.from, end)),
|
|
280
|
+
}), Option.match(from, {
|
|
281
|
+
onNone: () => always,
|
|
282
|
+
onSome: (start) => or(isNull(validity.to), gt(validity.to, start)),
|
|
283
|
+
}));
|
|
284
|
+
/** A validity bound: a `Date`, none for `NULL` or absent, or a malformed value. */
|
|
285
|
+
const boundOf = (values, column) => Option.match(Option.fromNullishOr(values[column]), {
|
|
286
|
+
onNone: () => Option.some(Option.none()),
|
|
287
|
+
onSome: (value) => Predicate.isDate(value) && !Number.isNaN(value.getTime())
|
|
288
|
+
? Option.some(Option.some(value))
|
|
289
|
+
: Option.none(),
|
|
290
|
+
});
|
|
291
|
+
/** What is wrong with one end's declaration: an alias with a `.`, or a `maxEdges` that is not a positive safe integer. */
|
|
292
|
+
const declarationProblem = ([alias, end]) => {
|
|
293
|
+
if (alias.includes(".")) {
|
|
294
|
+
return Option.some(`the end alias '${alias}' contains a '.', which endpointColumn reserves`);
|
|
295
|
+
}
|
|
296
|
+
const max = end.maxEdges;
|
|
297
|
+
if (max !== undefined && !(Number.isSafeInteger(max) && max > 0)) {
|
|
298
|
+
return Option.some(`the end '${alias}' declares maxEdges ${String(max)}, not a positive safe integer`);
|
|
299
|
+
}
|
|
300
|
+
return Option.none();
|
|
301
|
+
};
|
|
302
|
+
/** Throw {@link EdgeDeclarationError} on the first malformed end. */
|
|
303
|
+
const validateEnds = (type, ends) => {
|
|
304
|
+
const problem = Arr.findFirst(Record.toEntries(ends), declarationProblem);
|
|
305
|
+
if (Option.isSome(problem)) {
|
|
306
|
+
throw new EdgeDeclarationError({ message: `${type}: ${problem.value}` });
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
/** The request's page window: the limit clamped to `[1, MAX_PAGE_LIMIT]` (`SEC-INPUT-003`), the offset to `≥ 0`. */
|
|
310
|
+
const pageWindow = (request) => ({
|
|
311
|
+
limit: Math.max(1, Math.min(Math.trunc(request.limit), MAX_PAGE_LIMIT)),
|
|
312
|
+
offset: Math.max(0, Math.trunc(request.offset)),
|
|
313
|
+
});
|
|
314
|
+
/** The ends a create bounds, in the order their nodes are locked: ascending `nodeId`, so no two creates lock a pair in opposite orders. */
|
|
315
|
+
const byNodeId = Order.mapInput(Order.String, (at) => at.nodeId);
|
|
316
|
+
/**
|
|
317
|
+
* Bind an edge family's operations. Every produced operation is traced as
|
|
318
|
+
* `${type}.<operation>`; the writes run in the caller's transaction (the
|
|
319
|
+
* boundary is the caller's, website #1883), and a create's cardinality
|
|
320
|
+
* count and insert share it (README → Seams).
|
|
321
|
+
*
|
|
322
|
+
* Throws {@link EdgeDeclarationError}, when the family is declared, for an
|
|
323
|
+
* end alias containing a `.` or a `maxEdges` that is not a positive safe
|
|
324
|
+
* integer.
|
|
325
|
+
*
|
|
326
|
+
* @since 0.1.0
|
|
327
|
+
*/
|
|
328
|
+
export const defineEdgeOps = (definition) => {
|
|
329
|
+
const { type, ends, edges, policy, followers, toResource } = definition;
|
|
330
|
+
validateEnds(type, ends);
|
|
331
|
+
const validity = Option.fromUndefinedOr(definition.validity);
|
|
332
|
+
if (Option.isSome(validity)) {
|
|
333
|
+
if (validity.value.from === validity.value.to) {
|
|
334
|
+
throw new EdgeDeclarationError({ message: `${type}: validity names one column twice` });
|
|
335
|
+
}
|
|
336
|
+
if (edges.closeValidity === undefined) {
|
|
337
|
+
throw new EdgeDeclarationError({
|
|
338
|
+
message: `${type}: validity needs an edge store with closeValidity`,
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
const endEntries = Record.toEntries(ends);
|
|
343
|
+
const writeGate = definition.writeGate ?? corpusWriteGate;
|
|
344
|
+
const onConflict = definition.onConflict ?? "fail";
|
|
345
|
+
/** The node `edge` names at `end`, if the viewer may read it; none for a missing or non-string id. */
|
|
346
|
+
const readableNode = (end, viewer, edge) => {
|
|
347
|
+
const nodeId = edge[end.column];
|
|
348
|
+
return Predicate.isString(nodeId)
|
|
349
|
+
? Effect.flatMap(end.nodes.get(nodeId), (node) => Effect.map(canViewEndpoint(end, viewer, policy, followers, node), (readable) => readable ? node : Option.none()))
|
|
350
|
+
: Effect.succeed(Option.none());
|
|
351
|
+
};
|
|
352
|
+
/**
|
|
353
|
+
* The node `edge` names at `end`, if the viewer may read it and it is
|
|
354
|
+
* live: what a create's ends must name, and the per-edge form of the
|
|
355
|
+
* cardinality count's filter (`endpointFilter` and `liveEndsFilter`).
|
|
356
|
+
*/
|
|
357
|
+
const liveNode = (end, viewer, edge) => Effect.map(readableNode(end, viewer, edge), Option.filter(isLive));
|
|
358
|
+
/** The stored edge, if `node` finds every end's node for the viewer. */
|
|
359
|
+
const storedEdge = (node) => (viewer, id) => Effect.filterOrElse(edges.get(id), Option.isNone, (row) => Effect.map(Effect.forEach(endEntries, ([, end]) => node(end, viewer, row.value), {
|
|
360
|
+
concurrency: 1,
|
|
361
|
+
}), (found) => (Arr.every(found, Option.isSome) ? row : Option.none())));
|
|
362
|
+
/** The stored edge, if the viewer may read it (`EDGE-001`: every end's node is readable). */
|
|
363
|
+
const visibleEdge = storedEdge(readableNode);
|
|
364
|
+
/** The stored edge, if the cardinality count would admit it: readable, every end live. */
|
|
365
|
+
const countedEdge = storedEdge(liveNode);
|
|
366
|
+
/**
|
|
367
|
+
* A unique-key collision, settled by the conflict policy: only ever the id
|
|
368
|
+
* of an edge the count would admit, readable with every end live (owner
|
|
369
|
+
* decision on pulpit#93). The view-deleted rung reads an edge to a
|
|
370
|
+
* tombstone but can't link to one, so it can't resolve to one either.
|
|
371
|
+
*/
|
|
372
|
+
const resolveCollision = (viewer, id) => Effect.gen(function* () {
|
|
373
|
+
if (onConflict === "fail")
|
|
374
|
+
return yield* new EdgeConflict({ type });
|
|
375
|
+
if (Option.isNone(yield* countedEdge(viewer, id)))
|
|
376
|
+
return yield* new EdgeConflict({ type });
|
|
377
|
+
return { id, created: false };
|
|
378
|
+
});
|
|
379
|
+
/**
|
|
380
|
+
* An end's declared `maxEdges`, checked against the edges its node already
|
|
381
|
+
* holds that `counted` admits: those the viewer can read, every end live.
|
|
382
|
+
*/
|
|
383
|
+
const withinLimit = (counted) => (at) => Option.match(Option.fromNullishOr(at.end.maxEdges), {
|
|
384
|
+
onNone: () => Effect.void,
|
|
385
|
+
onSome: (max) => Effect.flatMap(edges.countAt({ column: at.end.column, nodeId: at.nodeId, where: counted }), (held) => held >= max
|
|
386
|
+
? Effect.fail(new EdgeCardinalityExceeded({ type, end: at.alias, nodeId: at.nodeId, max }))
|
|
387
|
+
: Effect.void),
|
|
388
|
+
});
|
|
389
|
+
const list = Effect.fn(`${type}.list`)(function* (request) {
|
|
390
|
+
const viewer = yield* definition.viewer;
|
|
391
|
+
const where = and(endpointFilter(ends, viewer, policy, followers), request.where);
|
|
392
|
+
const { rows, total } = yield* edges.list({ where, ...pageWindow(request) });
|
|
393
|
+
return { rows: Arr.map(rows, toResource), total };
|
|
394
|
+
});
|
|
395
|
+
const get = Effect.fn(`${type}.get`)(function* (id) {
|
|
396
|
+
const row = yield* visibleEdge(yield* definition.viewer, id);
|
|
397
|
+
// Hidden and missing are the same answer (SEC-AUTH-ENUM-001).
|
|
398
|
+
if (Option.isNone(row))
|
|
399
|
+
return yield* new EdgeNotFound({ type, id });
|
|
400
|
+
return toResource(row.value);
|
|
401
|
+
});
|
|
402
|
+
/** The create's interval, checked (`from ≤ to`, each a `Date` or open), or none without one. */
|
|
403
|
+
const intervalOf = (values) => Option.match(validity, {
|
|
404
|
+
onNone: () => Effect.succeed(Option.none()),
|
|
405
|
+
onSome: (columns) => {
|
|
406
|
+
const from = boundOf(values, columns.from);
|
|
407
|
+
const to = boundOf(values, columns.to);
|
|
408
|
+
if (Option.isNone(from) || Option.isNone(to)) {
|
|
409
|
+
return Effect.fail(new InvalidValidity({ type, reason: "a validity bound is neither a date nor open" }));
|
|
410
|
+
}
|
|
411
|
+
const reversed = Option.isSome(from.value) &&
|
|
412
|
+
Option.isSome(to.value) &&
|
|
413
|
+
from.value.value.getTime() > to.value.value.getTime();
|
|
414
|
+
return reversed
|
|
415
|
+
? Effect.fail(new InvalidValidity({ type, reason: "validity starts after it ends" }))
|
|
416
|
+
: Effect.succeedSome([from.value, to.value]);
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
const create = Effect.fn(`${type}.create`)(function* (input) {
|
|
420
|
+
const viewer = yield* definition.viewer;
|
|
421
|
+
const values = definition.values(input);
|
|
422
|
+
// The interval is the input's own shape: checked first, it reads nothing.
|
|
423
|
+
const interval = yield* intervalOf(values);
|
|
424
|
+
// Every end first, before the gate: a node the viewer cannot read is
|
|
425
|
+
// `NodeNotFound` whoever asks, so a gate's 403 never confirms it (#1306).
|
|
426
|
+
// An end must be live as well as readable: the view-deleted rung reads a
|
|
427
|
+
// tombstone, and still can't link to one.
|
|
428
|
+
const nodes = yield* Effect.forEach(endEntries, ([alias, end]) => Effect.flatMap(liveNode(end, viewer, values), (node) => Option.match(node, {
|
|
429
|
+
onNone: () => Effect.fail(new NodeNotFound({ type: end.type, id: columnText(values[end.column]) })),
|
|
430
|
+
onSome: (row) => Effect.succeed({ alias, end, nodeId: row.id }),
|
|
431
|
+
})), { concurrency: 1 });
|
|
432
|
+
yield* writeGate({ viewer, policy, edge: values });
|
|
433
|
+
// A re-assertion resolves before the cardinality check, so asserting an
|
|
434
|
+
// edge that is already there stays idempotent at a full end.
|
|
435
|
+
const collided = yield* edges.existing(values);
|
|
436
|
+
if (Option.isSome(collided))
|
|
437
|
+
return yield* resolveCollision(viewer, collided.value);
|
|
438
|
+
// Each bounded end's count locks its node (README → Seams), so the nodes
|
|
439
|
+
// are visited in one global order: a self-referential family's two
|
|
440
|
+
// bounded ends cannot deadlock two creates naming the pair both ways.
|
|
441
|
+
// Only edges the viewer can read with every end live count (pulpit#77,
|
|
442
|
+
// pulpit#93): a hidden edge must not shape the answer.
|
|
443
|
+
// With an interval, only the edges valid at the same time count (owner decision on pulpit#210).
|
|
444
|
+
const counted = and(endpointFilter(ends, viewer, policy, followers), liveEndsFilter(ends), Option.match(Option.all([validity, interval]), {
|
|
445
|
+
onNone: () => always,
|
|
446
|
+
onSome: ([columns, [from, to]]) => overlapping(columns, from, to),
|
|
447
|
+
}));
|
|
448
|
+
yield* Effect.forEach(Arr.sort(nodes, byNodeId), withinLimit(counted), {
|
|
449
|
+
concurrency: 1,
|
|
450
|
+
discard: true,
|
|
451
|
+
});
|
|
452
|
+
const inserted = yield* edges.insert(values);
|
|
453
|
+
if (Option.isSome(inserted))
|
|
454
|
+
return { id: inserted.value, created: true };
|
|
455
|
+
// A racing writer took the key between `existing` and the insert.
|
|
456
|
+
const raced = yield* edges.existing(values);
|
|
457
|
+
if (Option.isNone(raced))
|
|
458
|
+
return yield* new EdgeConflict({ type });
|
|
459
|
+
return yield* resolveCollision(viewer, raced.value);
|
|
460
|
+
});
|
|
461
|
+
const closeValidity = Effect.fn(`${type}.closeValidity`)(function* (id, at) {
|
|
462
|
+
const viewer = yield* definition.viewer;
|
|
463
|
+
const row = yield* visibleEdge(viewer, id);
|
|
464
|
+
if (Option.isNone(row))
|
|
465
|
+
return yield* new EdgeNotFound({ type, id });
|
|
466
|
+
yield* writeGate({ viewer, policy, edge: row.value });
|
|
467
|
+
const close = edges.closeValidity;
|
|
468
|
+
if (Option.isNone(validity) || close === undefined) {
|
|
469
|
+
return yield* new InvalidValidity({ type, reason: "the family declares no validity" });
|
|
470
|
+
}
|
|
471
|
+
const from = Option.flatten(boundOf(row.value, validity.value.from));
|
|
472
|
+
const to = Option.flatten(boundOf(row.value, validity.value.to));
|
|
473
|
+
// Only ever narrowing (EDGE-002): never past a closed end, never before the start.
|
|
474
|
+
if (Number.isNaN(at.getTime()) ||
|
|
475
|
+
Option.exists(to, (end) => at.getTime() > end.getTime()) ||
|
|
476
|
+
Option.exists(from, (start) => at.getTime() < start.getTime())) {
|
|
477
|
+
return yield* new InvalidValidity({ type, reason: "a close may only narrow the interval" });
|
|
478
|
+
}
|
|
479
|
+
if (!(yield* close(id, validity.value.to, at)))
|
|
480
|
+
return yield* new EdgeNotFound({ type, id });
|
|
481
|
+
return { id };
|
|
482
|
+
});
|
|
483
|
+
const remove = Effect.fn(`${type}.delete`)(function* (id) {
|
|
484
|
+
const viewer = yield* definition.viewer;
|
|
485
|
+
const row = yield* visibleEdge(viewer, id);
|
|
486
|
+
if (Option.isNone(row))
|
|
487
|
+
return yield* new EdgeNotFound({ type, id });
|
|
488
|
+
yield* writeGate({ viewer, policy, edge: row.value });
|
|
489
|
+
// A hard DELETE: an edge has no version chain to append a tombstone to.
|
|
490
|
+
if (!(yield* edges.delete(id)))
|
|
491
|
+
return yield* new EdgeNotFound({ type, id });
|
|
492
|
+
return { id };
|
|
493
|
+
});
|
|
494
|
+
/**
|
|
495
|
+
* The store's `members` set for `end` against `otherIds`, under the
|
|
496
|
+
* viewer's `EDGE-001` filter; none, without reading the store, for no ids,
|
|
497
|
+
* more than `MAX_SET_VALUES`, a misnamed end or a family of other than two
|
|
498
|
+
* ends. `memberFilter` reads none as `never`, `nonMemberFilter` as `always`.
|
|
499
|
+
*/
|
|
500
|
+
const readableMembers = Effect.fnUntraced(function* (end, otherIds) {
|
|
501
|
+
const member = Record.get(ends, end);
|
|
502
|
+
const others = endEntries.filter(([alias]) => alias !== end);
|
|
503
|
+
const [other] = others;
|
|
504
|
+
if (Option.isNone(member) || other === undefined || others.length !== 1) {
|
|
505
|
+
return Option.none();
|
|
506
|
+
}
|
|
507
|
+
const otherColumn = other[1].column;
|
|
508
|
+
const named = anyOf(otherColumn, otherIds);
|
|
509
|
+
// No ids, or past MAX_SET_VALUES: `anyOf` is `never`.
|
|
510
|
+
if (named.kind === "never")
|
|
511
|
+
return Option.none();
|
|
512
|
+
const viewer = yield* definition.viewer;
|
|
513
|
+
const following = yield* edges.members({
|
|
514
|
+
column: member.value.column,
|
|
515
|
+
otherColumn,
|
|
516
|
+
ids: otherIds,
|
|
517
|
+
where: and(endpointFilter(ends, viewer, policy, followers), named),
|
|
518
|
+
});
|
|
519
|
+
return Option.some(following);
|
|
520
|
+
});
|
|
521
|
+
/** A membership filter traced as `${type}.<name>`: `whenNone` for no set, `wrap` over the readable members. */
|
|
522
|
+
const membershipFilter = (name, whenNone, wrap) => Effect.fn(`${type}.${name}`)(function* (end, otherIds) {
|
|
523
|
+
const following = yield* readableMembers(end, otherIds);
|
|
524
|
+
return Option.match(following, { onNone: () => whenNone, onSome: wrap });
|
|
525
|
+
});
|
|
526
|
+
const memberFilter = membershipFilter("memberFilter", never, (set) => isIn("id", set));
|
|
527
|
+
// An exclusion fails closed by excluding nothing.
|
|
528
|
+
const nonMemberFilter = membershipFilter("nonMemberFilter", always, (set) => isNotIn("id", set));
|
|
529
|
+
const countBy = Effect.fn(`${type}.countBy`)(function* (end, ids, where = always) {
|
|
530
|
+
const wanted = Arr.dedupe(ids);
|
|
531
|
+
const zero = HashMap.fromIterable(Arr.map(wanted, (id) => [id, 0]));
|
|
532
|
+
const counted = Record.get(ends, end);
|
|
533
|
+
// A misnamed end, no ids, or past MAX_SET_VALUES: every count 0, unread.
|
|
534
|
+
if (Option.isNone(counted) ||
|
|
535
|
+
!Arr.isReadonlyArrayNonEmpty(wanted) ||
|
|
536
|
+
wanted.length > MAX_SET_VALUES) {
|
|
537
|
+
return zero;
|
|
538
|
+
}
|
|
539
|
+
const viewer = yield* definition.viewer;
|
|
540
|
+
const counts = yield* edges.countBy({
|
|
541
|
+
column: counted.value.column,
|
|
542
|
+
ids: wanted,
|
|
543
|
+
where: and(endpointFilter(ends, viewer, policy, followers), where),
|
|
544
|
+
});
|
|
545
|
+
return HashMap.union(zero, HashMap.filter(counts, (_, id) => HashMap.has(zero, id)));
|
|
546
|
+
});
|
|
547
|
+
return {
|
|
548
|
+
list,
|
|
549
|
+
get,
|
|
550
|
+
create,
|
|
551
|
+
delete: remove,
|
|
552
|
+
closeValidity,
|
|
553
|
+
memberFilter,
|
|
554
|
+
nonMemberFilter,
|
|
555
|
+
countBy,
|
|
556
|
+
};
|
|
557
|
+
};
|
|
558
|
+
//# sourceMappingURL=edges.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edges.js","sourceRoot":"","sources":["../src/edges.ts"],"names":[],"mappings":"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"}
|