@agentshouse/mdmodel 0.1.0-c46ca56158c79 → 0.1.0-c48486966f3a3
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/API.md +81 -46
- package/README.md +6 -4
- package/dist/blocks.d.ts.map +1 -1
- package/dist/blocks.js +29 -7
- package/dist/condition.d.ts +22 -5
- package/dist/condition.d.ts.map +1 -1
- package/dist/condition.js +27 -45
- package/dist/definition.d.ts +1 -0
- package/dist/definition.d.ts.map +1 -1
- package/dist/definition.js +69 -19
- package/dist/document.d.ts +2 -1
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +25 -14
- package/dist/index.d.ts +16 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/kinds.d.ts +18 -0
- package/dist/kinds.d.ts.map +1 -0
- package/dist/kinds.js +141 -0
- package/dist/links.d.ts.map +1 -1
- package/dist/links.js +80 -37
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +4 -1
- package/dist/pattern.d.ts +10 -0
- package/dist/pattern.d.ts.map +1 -0
- package/dist/pattern.js +355 -0
- package/dist/query/language.d.ts +218 -0
- package/dist/query/language.d.ts.map +1 -0
- package/dist/query/language.js +526 -0
- package/dist/query/match.d.ts +12 -0
- package/dist/query/match.d.ts.map +1 -0
- package/dist/query/match.js +118 -0
- package/dist/query/rows.d.ts +32 -0
- package/dist/query/rows.d.ts.map +1 -0
- package/dist/query/rows.js +161 -0
- package/dist/query/sql.d.ts +39 -0
- package/dist/query/sql.d.ts.map +1 -0
- package/dist/query/sql.js +279 -0
- package/dist/reserved.d.ts +5 -0
- package/dist/reserved.d.ts.map +1 -0
- package/dist/reserved.js +20 -0
- package/dist/schema.d.ts +1 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +55 -4
- package/dist/types.d.ts +13 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/validate.d.ts +3 -2
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +137 -27
- package/dist/yaml.d.ts.map +1 -1
- package/dist/yaml.js +36 -3
- package/fixtures/README.md +21 -2
- package/fixtures/cases/conditional-section/context.json +1 -0
- package/fixtures/cases/conditional-section/expected.json +6 -0
- package/fixtures/cases/conditional-section/library/questions/hosting.md +9 -0
- package/fixtures/cases/conditional-section/library/questions/payments.md +12 -0
- package/fixtures/cases/conditional-section/schema.yaml +14 -0
- package/fixtures/cases/link-into-a-reserved-name/context.json +1 -0
- package/fixtures/cases/link-into-a-reserved-name/expected.json +5 -0
- package/fixtures/cases/link-into-a-reserved-name/library/notes/a.md +6 -0
- package/fixtures/cases/link-into-a-reserved-name/schema.yaml +3 -0
- package/fixtures/cases/link-into-a-reserved-name-from-an-untyped-document/context.json +1 -0
- package/fixtures/cases/link-into-a-reserved-name-from-an-untyped-document/expected.json +5 -0
- package/fixtures/cases/link-into-a-reserved-name-from-an-untyped-document/library/notes/b.md +5 -0
- package/fixtures/cases/member-on-an-untyped-document/context.json +1 -0
- package/fixtures/cases/member-on-an-untyped-document/expected.json +6 -0
- package/fixtures/cases/member-on-an-untyped-document/library/note.md +4 -0
- package/fixtures/cases/member-on-another-type/context.json +1 -0
- package/fixtures/cases/member-on-another-type/expected.json +6 -0
- package/fixtures/cases/member-on-another-type/library/note.md +4 -0
- package/fixtures/cases/member-on-another-type/schema.yaml +7 -0
- package/fixtures/cases/reference-into-a-reserved-name/context.json +1 -0
- package/fixtures/cases/reference-into-a-reserved-name/expected.json +6 -0
- package/fixtures/cases/reference-into-a-reserved-name/library/notes/a.md +4 -0
- package/fixtures/cases/reference-into-a-reserved-name/library/settings/brief.md +1 -0
- package/fixtures/cases/reference-into-a-reserved-name/schema.yaml +3 -0
- package/fixtures/cases/room-md-declares-a-type/context.json +1 -0
- package/fixtures/cases/room-md-declares-a-type/expected.json +6 -0
- package/fixtures/cases/room-md-declares-a-type/library/ROOM.md +5 -0
- package/fixtures/cases/typed-path-names-another-type/context.json +11 -0
- package/fixtures/cases/typed-path-names-another-type/expected.json +6 -0
- package/fixtures/cases/typed-path-names-another-type/library/settings/prefs/one.md +3 -0
- package/fixtures/cases/typed-path-names-another-type/schema.yaml +6 -0
- package/fixtures/cases/typed-path-names-its-type/context.json +11 -0
- package/fixtures/cases/typed-path-names-its-type/expected.json +3 -0
- package/fixtures/cases/typed-path-names-its-type/library/settings/prefs/deeper/two.md +1 -0
- package/fixtures/cases/typed-path-names-its-type/library/settings/prefs/one.md +4 -0
- package/fixtures/cases/typed-path-names-its-type/schema.yaml +6 -0
- package/fixtures/cases/typed-path-names-no-type/context.json +11 -0
- package/fixtures/cases/typed-path-names-no-type/expected.json +6 -0
- package/fixtures/cases/typed-path-names-no-type/library/settings/prefs/one.md +1 -0
- package/fixtures/cases/typed-path-names-no-type/schema.yaml +6 -0
- package/fixtures/cases/unnamed-typed-path-checks-its-fields/context.json +11 -0
- package/fixtures/cases/unnamed-typed-path-checks-its-fields/expected.json +6 -0
- package/fixtures/cases/unnamed-typed-path-checks-its-fields/library/rooms/team/tasks/plan.md +4 -0
- package/fixtures/cases/unnamed-typed-path-checks-its-fields/schema.yaml +5 -0
- package/fixtures/cases/unnamed-typed-path-names-a-type/context.json +11 -0
- package/fixtures/cases/unnamed-typed-path-names-a-type/expected.json +6 -0
- package/fixtures/cases/unnamed-typed-path-names-a-type/library/rooms/team/tasks/plan.md +6 -0
- package/fixtures/cases/unnamed-typed-path-names-a-type/schema.yaml +5 -0
- package/fixtures/cases/unnamed-typed-path-reads-its-type/context.json +11 -0
- package/fixtures/cases/unnamed-typed-path-reads-its-type/expected.json +3 -0
- package/fixtures/cases/unnamed-typed-path-reads-its-type/library/rooms/team/plan.md +1 -0
- package/fixtures/cases/unnamed-typed-path-reads-its-type/library/rooms/team/tasks/plan.md +5 -0
- package/fixtures/cases/unnamed-typed-path-reads-its-type/schema.yaml +5 -0
- package/fixtures/cases/unnamed-typed-path-without-a-body/context.json +11 -0
- package/fixtures/cases/unnamed-typed-path-without-a-body/expected.json +5 -0
- package/fixtures/cases/unnamed-typed-path-without-a-body/library/rooms/team/tasks/plan.md +5 -0
- package/fixtures/cases/unnamed-typed-path-without-a-body/schema.yaml +5 -0
- package/fixtures/queries.json +913 -0
- package/package.json +7 -2
package/API.md
CHANGED
|
@@ -46,10 +46,12 @@ JSON Schema of its frontmatter; `$defs` holds shapes the types reuse, reached by
|
|
|
46
46
|
`reference` on a string names one MD Type, several, `any` or `attachment`, and `cross_room: true`
|
|
47
47
|
beside it admits a Document in another Room, of a type that Room declares; `sections` declares a
|
|
48
48
|
type's H2 sections, each `{ kind: text }` or `{ kind: list, items }` over one string, number,
|
|
49
|
-
integer or boolean, optionally `required: true
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
integer or boolean, optionally `required: true`, which the `then` or `else` of an `if` on the type,
|
|
50
|
+
in its `allOf` or in such a branch may repeat to ask a section for text, else `conditional-section`;
|
|
51
|
+
`member_document: true` marks at most one type. A type alone takes `create_roles` and
|
|
52
|
+
`delete_roles`, each a list of role names. `verify(schema, provided)` holds every type of a model
|
|
53
|
+
`provided` as its own, named only for those two and only if `provided.nameable` lists it. On a field
|
|
54
|
+
of a type's own `properties` alone, `change_roles` and `initial_roles` each list role names, and
|
|
53
55
|
`transitions` lists `{ from, to, roles? }`, each end a scalar or `null`, on a field whose `type`,
|
|
54
56
|
`enum`, `const`, `$ref`, `allOf`, `anyOf`, `oneOf`, `if` and `not` admit no list or object.
|
|
55
57
|
|
|
@@ -76,34 +78,34 @@ to their siblings and the variants of `anyOf`, `oneOf`, `then`, `else` and `depe
|
|
|
76
78
|
variant's own keys `conditional`; a path without one `type`, `null` aside, has none. A malformed
|
|
77
79
|
schema is refused whole, naming its `rule`, the keyword or the model's own, and the JSON Pointer
|
|
78
80
|
`location` it concerns, such as `/plan/properties/status/enum`, or `line <n>` outside the YAML
|
|
79
|
-
subset. `pointerFacts(definition, pointer)` reads the facts a frontmatter pointer reaches,
|
|
80
|
-
|
|
81
|
-
`pointerSegments` and `escapePointer` split and write a pointer,
|
|
82
|
-
segment, and `ATTACHMENT` is the `reference` that admits any path.
|
|
83
|
-
|
|
84
|
-
`validate(library, context?, model?)` takes the resulting text Library and one `ValidationContext`
|
|
85
|
-
|
|
86
|
-
canonical collection-relative path namespace; a path declared text and binary is refused. House
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
81
|
+
subset. `pointerFacts(definition, pointer)` reads the facts a frontmatter pointer reaches, `itemFacts`
|
|
82
|
+
and `memberFacts` take one step and `crossedFacts` reads a list's item facts; `JSON_POINTER` matches the
|
|
83
|
+
JSON Pointer grammar, `''` included, `pointerSegments` and `escapePointer` split and write a pointer,
|
|
84
|
+
`ARRAY_INDEX` matches an index segment, and `ATTACHMENT` is the `reference` that admits any path.
|
|
85
|
+
|
|
86
|
+
`validate(library, context?, model?)` takes the resulting text Library and one `ValidationContext` of
|
|
87
|
+
`binaryTargets: readonly string[]`, none when omitted. Library keys and binary targets share one
|
|
88
|
+
canonical collection-relative path namespace; a path declared text and binary is refused. House declares
|
|
89
|
+
every binary file of the Room as a binary target, and the model reads no bytes. Ordinary links and
|
|
90
|
+
images in typed Documents may resolve to either membership, relative to the source Document, and one to
|
|
91
|
+
a path neither holds is not refused: it dangles. One written `/rooms/<handle>/<path>` names a file in
|
|
92
|
+
another Room, which the caller checks; any other absolute path, or one that leaves the collection, is
|
|
93
|
+
`unresolved-link`. A binary target supplies no Document or MD Type. `model` types the Library. A typed
|
|
94
|
+
Document, `any` included, at an `isDocumentPath` (no `isReservedName` of `RESERVED_NAMES` first) linking
|
|
95
|
+
into a reserved name is `unresolved-link`; a typed `ROOM_DESCRIPTION` is `room-md-type`. The context's `typedPaths` bind each `path`, a name's one `*` standing for any nonempty part, to a `type` of `model`: a Document there naming another, or naming any unless `named`, is `unknown-type` at `/type`, one not `named` is checked as it and stays `any`, and one whose body is empty is `required-body` if `body`.
|
|
94
96
|
|
|
95
97
|
A typed Document's frontmatter satisfies its type's schema, every keyword with its JSON Schema
|
|
96
98
|
meaning, formats asserted and defaults never filled, except that an object schema declaring neither
|
|
97
99
|
`additionalProperties` nor `unevaluatedProperties` is closed: an undeclared key is refused as
|
|
98
100
|
`undeclared-field`. `TYPE_FIELD`, `SITE_FIELD` and `RECEIVED_FIELD` count as declared on every type,
|
|
99
|
-
and the string `MEMBER_FIELD` on the `member_document` type
|
|
100
|
-
names the keyword, such as `required`, and the value's JSON
|
|
101
|
-
occurrence of a declared list section is a list of values of
|
|
102
|
-
`structured-section`; a reference item is one ordinary link alone, such as
|
|
103
|
-
reference, at any depth or a section item, reaching a URL, a binary target, another
|
|
104
|
-
`cross_room` or the context's `anyRoom: true`,
|
|
105
|
-
`unresolved-reference`, and a frontmatter one reaching no member is `referenced-missing-file`
|
|
106
|
-
its `referrers`; `attachment` admits any path, and no body link is a referrer. `validating` is
|
|
101
|
+
and the string `MEMBER_FIELD` on the `member_document` type alone, else refused, `any` included;
|
|
102
|
+
`HOUSE_FIELDS` lists the four. A refusal names the keyword, such as `required`, and the value's JSON
|
|
103
|
+
Pointer, such as `/shipping/city`. Every occurrence of a declared list section is a list of values of
|
|
104
|
+
its item schema, else `structured-section`; a reference item is one ordinary link alone, such as
|
|
105
|
+
`- [Ada](ada.md)`. A reference, at any depth or a section item, reaching a URL, a binary target, another
|
|
106
|
+
Room without `cross_room` or the context's `anyRoom: true`, a Document of a type it does not name, or,
|
|
107
|
+
from an `isDocumentPath`, a reserved name is `unresolved-reference`, and a frontmatter one reaching no member is `referenced-missing-file`
|
|
108
|
+
naming its `referrers`; `attachment` admits any path, and no body link is a referrer. `validating` is
|
|
107
109
|
`validate` over a `ReadonlyMap` Library, yielding each path read with the references it `resolved`;
|
|
108
110
|
`assess(file, content, binary, model?, context?)` reads one member, naming its `type` and `targets`,
|
|
109
111
|
and `verdicts()` `add`s assessments in any order, its `verdict()` the one `validate` gives.
|
|
@@ -122,9 +124,9 @@ merged or fenced heading is refused as `overlapping-section` naming that section
|
|
|
122
124
|
does not reformat the rest of the file: an inline value is replaced where it stands, and a value
|
|
123
125
|
written after the key's line, an empty one or a block mapping or list, is written after the key's
|
|
124
126
|
colon in its place. A field holds a `FrontmatterValue`: null, a string, a boolean, a finite number,
|
|
125
|
-
a list without holes or a plain object of them,
|
|
126
|
-
test
|
|
127
|
-
two by value, whatever their key order, as `apply`
|
|
127
|
+
a list without holes or a plain object of them, no cycle, at most 63 deep. `frontmatterValue(value)`
|
|
128
|
+
is that test; `apply` refuses any other value and `parse` a frontmatter past 64 deep as
|
|
129
|
+
`frontmatter-fence`. `equalValue` compares two by value, whatever their key order, as `apply` does.
|
|
128
130
|
|
|
129
131
|
`Document.preamble` is a readonly string holding the exact source after frontmatter and before the
|
|
130
132
|
first section heading the section parser recognizes, `''` when empty, whitespace, newlines, a
|
|
@@ -156,8 +158,7 @@ Independent field, section, and preamble edits keep their own prior values valid
|
|
|
156
158
|
|
|
157
159
|
For moved links, use `links` and one `link` change per destination below, then compare the rewritten
|
|
158
160
|
Document's `preamble` and `sections` to the original and submit the changed values with their
|
|
159
|
-
original priors
|
|
160
|
-
separate call against the resulting Library.
|
|
161
|
+
original priors. Collection validation remains a separate call against the resulting Library.
|
|
161
162
|
|
|
162
163
|
`links(document, file)` is the inventory of that Document's ordinary link and image destinations
|
|
163
164
|
that resolve to a collection Path, each with the destination `href` exactly as written and the
|
|
@@ -186,7 +187,7 @@ context: `ok: false` where it refuses, else its `type`, whether it is `typed`, a
|
|
|
186
187
|
`target` and `to`, which `resolves(reference, typeOf, binary)` says reaches a member `validate`
|
|
187
188
|
accepts. `sectionReferences(file, content, definition)` reads only its `list` sections' references;
|
|
188
189
|
neither names another Room's, which `roomReferences(file, content, definition?)` lists by `kind`.
|
|
189
|
-
`parseFrontmatter(content, file?)` is `parse` without the body: `content`, `type`, `fields`.
|
|
190
|
+
`parseFrontmatter(content, file?)` is `parse` without the body: `content`, `type`, `fields`; `outline(content, file)` is what a reader keeps of a text it does not hold: its `type`, `any` where it declares none, and `fields`, each `null` where its frontmatter is refused, and the distinct targets of its body's `bodyLinks`.
|
|
190
191
|
|
|
191
192
|
`references(document, definition)` lists each frontmatter `reference` string at any depth as
|
|
192
193
|
`pointer`, `value` and `to`; a `{ kind: 'reference', pointer, value, prior }` change rewrites one in
|
|
@@ -256,10 +257,9 @@ A `link` change leaves the projection of every Document it rewrites
|
|
|
256
257
|
byte-identical, while a changed visible label changes it.
|
|
257
258
|
|
|
258
259
|
`divide(document, file, context)` divides that same Embedding projection input into ordered Spans
|
|
259
|
-
under the bound the caller supplies. Each Span carries the `text` to embed and the `start` and
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
the Document itself.
|
|
260
|
+
under the bound the caller supplies. Each Span carries the `text` to embed and the `start` and `end`
|
|
261
|
+
of the extent it addresses in the Document's own source, as UTF-8 byte offsets and never string
|
|
262
|
+
positions, so a caller stores the extent and hydrates the text it shows from the Document itself.
|
|
263
263
|
|
|
264
264
|
```ts
|
|
265
265
|
const parsed = parse(content);
|
|
@@ -307,6 +307,41 @@ divided out of one free-text field value addresses that whole value, because a Y
|
|
|
307
307
|
positions are the only ones its source has, and a Span carrying part of one internal link's label
|
|
308
308
|
addresses that whole link, because a cut never falls inside link syntax.
|
|
309
309
|
|
|
310
|
+
## Queries
|
|
311
|
+
|
|
312
|
+
`planOf(query, rooms)` checks one query against the MD Types of the Rooms `rooms` lists, each
|
|
313
|
+
`{ locator, available, types }` with `listed` when the list is whole, and answers its
|
|
314
|
+
`QueryPlan` or throws a `QueryError` whose `code` is `invalid-query`, `unknown-type`,
|
|
315
|
+
`unknown-field` or `wrong-kind` and whose message names where. A query is data: `types`, `where`
|
|
316
|
+
field predicates by JSON Pointer (`$eq`, `$ne`, `$in`, `$nin`, `$gt`, `$gte`, `$lt`, `$lte`,
|
|
317
|
+
`$all`, `$size`, `$exists`, `$prefix`, `$and`, `$or`), `pathPrefix`, `folder`, `paths`,
|
|
318
|
+
`fileIds`, `hop`, `backlinks`, `text`, then `select` or `groupBy`, `orderBy`, `limit`, `after`
|
|
319
|
+
and `total`. `queryKey` and `identityOf` are a query's and a plan's canonical text, `bodied`
|
|
320
|
+
says a shape reads text, `cursorOf` and `decodedCursor` write and read the `after` a window
|
|
321
|
+
continues from, and `invalid`, `known` and `plain` are the check's refusal and tests.
|
|
322
|
+
|
|
323
|
+
`KINDS` is the one table of kinds a value compares as, `kindOf(facts)` a declared value's kind
|
|
324
|
+
and `fitsKind(kind, facts, value)` whether a value fits it: a `date`, `date-time` or `time` is
|
|
325
|
+
exactly what document validation admits as that format, a `date` is `dated`, a `date-time`
|
|
326
|
+
compares as the instant `instant` reads, which `instantKey` writes as text that sorts as the
|
|
327
|
+
instant does, and a `reference` as the Room Path it resolves to. `compared(left, right,
|
|
328
|
+
ordering)` orders plain values: numbers and booleans, then text by locale or `byCodePoint`,
|
|
329
|
+
then lists item by item.
|
|
330
|
+
|
|
331
|
+
Two evaluators answer a plan's tests on one Document alike, a test on a missing value false and
|
|
332
|
+
its negation (`$ne`, `$nin`, `$exists: false`) true. `matches(plan, candidate)` answers in
|
|
333
|
+
memory over one `Candidate`: its `path`, `type`, `fileId`, `fields`, `definition` and the
|
|
334
|
+
`text` held. The `sql` namespace compiles them to SQL over a collection: `indexed(path, fields,
|
|
335
|
+
definition)` derives a Document's values and field links, its date-times with their instants,
|
|
336
|
+
`sql.VALUE_TABLE` holds those values and `sql.insertedValues` writes them, and `sql.tests(alias,
|
|
337
|
+
plan)` tests a document row of `id`, `path`, `folder`, `type`, `file_id` and `content`, its
|
|
338
|
+
phrase through the function a connection registers as `sql.HOLDS_PHRASE` with `sql.holdsPhrase`.
|
|
339
|
+
`sql.scoped`, `sql.placed`, `sql.sorted`, `sql.beyond`, `sql.following` and `sql.sortValue`
|
|
340
|
+
render a scope, a pointer, an order and a window's continuation, a date-time ordering as its
|
|
341
|
+
instant between numbers and text; `sql.fragment`, `sql.joined`, `sql.all`, `sql.any`,
|
|
342
|
+
`sql.grouped`, `sql.listed` and `sql.exists` build statements, and `heldKind` is the index's value
|
|
343
|
+
kind. `fixtures/queries.json` holds both evaluators to one table.
|
|
344
|
+
|
|
310
345
|
## Conditions
|
|
311
346
|
|
|
312
347
|
`facts(document, { id, path }, model, resolve)` reads one Document as the `DocumentFacts` a
|
|
@@ -347,14 +382,15 @@ moved between Rooms, which a set `moved_between_rooms` must match. `starts_match
|
|
|
347
382
|
Document is in `scope` and holds `match` after the change but not before, a creation only with
|
|
348
383
|
`new_documents: true`. `field_changes` fires when the Document's side, after or for a deletion
|
|
349
384
|
before, is in `scope` and holds `match`, and `field` changed: its facts differ, or with neither
|
|
350
|
-
`from` nor `to` `changed` names it
|
|
351
|
-
creation and `to: 'deleted'` only a deletion, and listed values need that side's `field` `in` them.
|
|
385
|
+
`from` nor `to` `changed` names it, as it names `TEXT_FIELD`, `/text`, at any change of its text. A field on neither
|
|
386
|
+
side never fires; `from: 'new'` admits only a creation and `to: 'deleted'` only a deletion, and listed values need that side's `field` `in` them. `inScope(scope, side)` is the `scope` test `fires` makes of a side, read from its `id`, `path` and `type` alone, `false` for `null`.
|
|
352
387
|
|
|
353
|
-
`itemFires(condition, item)` compares `source` and `address` where given and holds `match` over
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
`
|
|
357
|
-
|
|
388
|
+
`itemFires(condition, item)` compares `source` and `address` where given and holds `match` over the
|
|
389
|
+
`ITEM_PATHS`, a `/json` test unknown for an item with no JSON; `notificationFires(condition, notification)`
|
|
390
|
+
holds `match`, where given, over a delivered notification's Document facts, and `messageFires(condition, message)`
|
|
391
|
+
over a message's `MessageFacts` at the `MESSAGE_PATHS`, a `/routine` or `/path` test unknown where its request names none.
|
|
392
|
+
`prosePaths(facts)` lists the prose and section paths whose text builds `changed`; `pointed(value, pointer)` reads a JSON Pointer,
|
|
393
|
+
`undefined` where nothing is; `dated(value)` checks a `YYYY-MM-DD` date, and `instant(value)` reads what validation admits as a `date-time` as epoch nanoseconds, a `bigint`.
|
|
358
394
|
|
|
359
395
|
What a condition names of one MD Type: `datePointers(fields)` lists, sorted, its date fields as escaped
|
|
360
396
|
`/fields/` pointers, the only `date`s a `DateCondition` takes; `changeFields(definition)` lists each
|
|
@@ -365,5 +401,4 @@ fields referring to `memberType`, alone or in a list. `testOperators(definitions
|
|
|
365
401
|
lists the `CONDITION_OPERATORS` a test on a document `path` takes in any of those types, none where none
|
|
366
402
|
declares it or, for a member path, `memberPointers` lacks it: `exists` alone on a section, prose or an
|
|
367
403
|
object, `contains` and `exists` on a list, `prefix` on a string and `/path`, orderings on a number, date
|
|
368
|
-
or time, and `contains` through a list. `actorOperators(path)` and `
|
|
369
|
-
on a `by` or item path, `itemKind(path)` an item value's kind, or `null`, as on `/json/`.
|
|
404
|
+
or time, and `contains` through a list. `actorOperators(path)`, `itemOperators(path)` and `messageOperators(path)` list the tests on a `by`, item or message path, `itemKind(path)` an item value's kind, or `null`, as on `/json/`.
|
package/README.md
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# `@agentshouse/mdmodel`
|
|
2
2
|
|
|
3
|
-
Typed Markdown documents: MD Types declared in JSON Schema, a parser, a validator,
|
|
4
|
-
deterministic application of one structured change to a Document,
|
|
5
|
-
|
|
3
|
+
Typed Markdown documents: MD Types declared in JSON Schema, a parser, a validator, the
|
|
4
|
+
deterministic application of one structured change to a Document, and one query language
|
|
5
|
+
answered in SQL over a collection or in memory over one Document, plus a conformance
|
|
6
|
+
fixture corpus.
|
|
6
7
|
|
|
7
8
|
It runs in the browser and in Node, makes no network call, and reads no
|
|
8
|
-
filesystem on its own. It ships one ESM artifact that Node 24.
|
|
9
|
+
filesystem on its own. It ships one ESM artifact that Node 24.22.1 and later
|
|
9
10
|
loads through `import` or `require`.
|
|
10
11
|
|
|
11
12
|
## Install
|
|
@@ -45,6 +46,7 @@ if (parsed.ok) {
|
|
|
45
46
|
| `escapePointer` | Write one key as a JSON Pointer token |
|
|
46
47
|
| `project`, `divide` | Embedding projection input and its division into Spans |
|
|
47
48
|
| `facts`, `factKind`, `holds`, `fires` | A condition over a Document and over one of its changes |
|
|
49
|
+
| `planOf`, `matches`, `sql` | Check a query, answer it over one Document or compile it to SQL |
|
|
48
50
|
| `MARKDOWN_SYNTAX_PROFILE`, `VERSION` | The pinned Markdown profile (GFM 0.29) and MD model version |
|
|
49
51
|
| `MEMBER_FIELD`, `SITE_FIELD`, `RECEIVED_FIELD` | The field names validation counts as declared beyond a type's own |
|
|
50
52
|
|
package/dist/blocks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;
|
|
1
|
+
{"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAoDF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,WAAW,EAAE,CA4BrF;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAe/E"}
|
package/dist/blocks.js
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
import { fenceSpans, spanCursor } from './links.js';
|
|
2
|
-
const
|
|
2
|
+
const HEADING_OPEN = /^(#{1,6})(?!#)([ \t]+)/;
|
|
3
|
+
const LINE_BREAK = /[\n\r\u2028\u2029]/;
|
|
4
|
+
function blank(character) {
|
|
5
|
+
return character === ' ' || character === '\t';
|
|
6
|
+
}
|
|
7
|
+
function heading(text) {
|
|
8
|
+
const open = HEADING_OPEN.exec(text);
|
|
9
|
+
if (open === null || LINE_BREAK.test(text))
|
|
10
|
+
return null;
|
|
11
|
+
const level = open[1].length;
|
|
12
|
+
const rest = text.slice(open[0].length);
|
|
13
|
+
if (rest === '')
|
|
14
|
+
return open[2].length > 1 ? { level, name: '' } : null;
|
|
15
|
+
let end = rest.length;
|
|
16
|
+
while (blank(rest[end - 1]))
|
|
17
|
+
end -= 1;
|
|
18
|
+
let hashes = end;
|
|
19
|
+
while (rest[hashes - 1] === '#')
|
|
20
|
+
hashes -= 1;
|
|
21
|
+
let spaced = hashes;
|
|
22
|
+
while (blank(rest[spaced - 1]))
|
|
23
|
+
spaced -= 1;
|
|
24
|
+
const closed = hashes < end && spaced < hashes && spaced > 0;
|
|
25
|
+
return { level, name: rest.slice(0, closed ? spaced : end).trim() };
|
|
26
|
+
}
|
|
3
27
|
function lineAt(content, from, to) {
|
|
4
28
|
const nl = content.indexOf('\n', from);
|
|
5
29
|
const end = nl === -1 || nl >= to ? to : nl;
|
|
@@ -30,13 +54,11 @@ export function headingLines(content, from, to) {
|
|
|
30
54
|
fenced ??= spanCursor(fenceSpans(content.slice(from, to)));
|
|
31
55
|
if (fenced(i - from) === undefined) {
|
|
32
56
|
const { text } = lineAt(content, i, to);
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
const name = match?.[2];
|
|
36
|
-
if (hashes !== undefined && name !== undefined) {
|
|
57
|
+
const read = heading(text);
|
|
58
|
+
if (read !== null) {
|
|
37
59
|
found.push({
|
|
38
|
-
level:
|
|
39
|
-
name: name
|
|
60
|
+
level: read.level,
|
|
61
|
+
name: read.name,
|
|
40
62
|
start: i,
|
|
41
63
|
textEnd: i + text.length,
|
|
42
64
|
next,
|
package/dist/condition.d.ts
CHANGED
|
@@ -76,7 +76,15 @@ export type DateCondition = {
|
|
|
76
76
|
readonly time_zone: string;
|
|
77
77
|
readonly match?: ConditionTest;
|
|
78
78
|
};
|
|
79
|
-
export type
|
|
79
|
+
export type NotificationCondition = {
|
|
80
|
+
readonly on: 'notifications';
|
|
81
|
+
readonly match?: ConditionTest;
|
|
82
|
+
};
|
|
83
|
+
export type MessageCondition = {
|
|
84
|
+
readonly on: 'messages';
|
|
85
|
+
readonly match?: ConditionTest;
|
|
86
|
+
};
|
|
87
|
+
export type Condition = DocumentCondition | ItemCondition | CronCondition | DateCondition | NotificationCondition | MessageCondition;
|
|
80
88
|
export type FactKind = 'string' | 'number' | 'boolean' | 'date' | 'time' | 'enum' | 'reference';
|
|
81
89
|
type Scalar = string | number | boolean;
|
|
82
90
|
export type Fact = {
|
|
@@ -103,11 +111,13 @@ export type DocumentFacts = {
|
|
|
103
111
|
readonly fields: Readonly<Record<string, Fact>>;
|
|
104
112
|
readonly sections: readonly string[];
|
|
105
113
|
};
|
|
106
|
-
export declare const
|
|
114
|
+
export declare const TEXT_FIELD = "/text";
|
|
115
|
+
export declare const WRITE_DOORS: readonly ['browser', 'agent', 'client', 'function'];
|
|
107
116
|
export type WriteDoor = (typeof WRITE_DOORS)[number];
|
|
108
117
|
export type Actor = {
|
|
109
118
|
readonly user?: string;
|
|
110
119
|
readonly site?: string;
|
|
120
|
+
readonly app?: string;
|
|
111
121
|
readonly door?: WriteDoor;
|
|
112
122
|
};
|
|
113
123
|
export type DocumentEvent = {
|
|
@@ -121,7 +131,6 @@ export type ItemFacts = {
|
|
|
121
131
|
readonly delivery: string;
|
|
122
132
|
readonly source: string | null;
|
|
123
133
|
readonly address: string | null;
|
|
124
|
-
readonly has_attachment: boolean;
|
|
125
134
|
readonly container: string | null;
|
|
126
135
|
readonly author: string | null;
|
|
127
136
|
readonly headers: Readonly<Record<string, string>>;
|
|
@@ -129,6 +138,11 @@ export type ItemFacts = {
|
|
|
129
138
|
readonly value: unknown;
|
|
130
139
|
} | null;
|
|
131
140
|
};
|
|
141
|
+
export type MessageFacts = {
|
|
142
|
+
readonly sender: string;
|
|
143
|
+
readonly routine: string | null;
|
|
144
|
+
readonly path: string | null;
|
|
145
|
+
};
|
|
132
146
|
export type Resolved = {
|
|
133
147
|
readonly id: string;
|
|
134
148
|
readonly member?: string;
|
|
@@ -147,16 +161,19 @@ export declare function memberPointers(definition: Definition, memberType: strin
|
|
|
147
161
|
export declare const DOCUMENT_PATHS: readonly string[];
|
|
148
162
|
export declare const ACTOR_PATHS: readonly string[];
|
|
149
163
|
export declare const ITEM_PATHS: readonly string[];
|
|
164
|
+
export declare const MESSAGE_PATHS: readonly string[];
|
|
150
165
|
export declare function testOperators(definitions: readonly Definition[], path: string, memberType: string | null): readonly ConditionOperator[];
|
|
151
166
|
export declare function actorOperators(path: string): readonly ConditionOperator[];
|
|
152
167
|
export declare function itemOperators(path: string): readonly ConditionOperator[];
|
|
168
|
+
export declare function messageOperators(path: string): readonly ConditionOperator[];
|
|
153
169
|
export declare function itemKind(path: string): FactKind | null;
|
|
154
|
-
export declare function dated(value: unknown): value is string;
|
|
155
|
-
export declare function instant(value: unknown): bigint | undefined;
|
|
156
170
|
export declare function pointed(value: unknown, pointer: string): unknown;
|
|
157
171
|
export declare function members(document: DocumentFacts, path: string): readonly string[];
|
|
158
172
|
export declare function holds(test: ConditionTest, document: DocumentFacts): Truth;
|
|
173
|
+
export declare function inScope(scope: ConditionScope, document: Pick<DocumentFacts, 'id' | 'path' | 'type'> | null): boolean;
|
|
159
174
|
export declare function fires(condition: DocumentCondition, event: DocumentEvent): boolean;
|
|
160
175
|
export declare function itemFires(condition: ItemCondition, item: ItemFacts): boolean;
|
|
176
|
+
export declare function notificationFires(condition: NotificationCondition, notification: DocumentFacts): boolean;
|
|
177
|
+
export declare function messageFires(condition: MessageCondition, message: MessageFacts): boolean;
|
|
161
178
|
export {};
|
|
162
179
|
//# sourceMappingURL=condition.d.ts.map
|
package/dist/condition.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"condition.d.ts","sourceRoot":"","sources":["../src/condition.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,UAAU,EAEf,KAAK,UAAU,EAChB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"condition.d.ts","sourceRoot":"","sources":["../src/condition.ts"],"names":[],"mappings":"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"}
|
package/dist/condition.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ARRAY_INDEX, escapePointer, fieldFacts, itemFacts, memberFacts, pointerFacts, pointerSegments, } from './definition.js';
|
|
2
|
+
import { dated, instant, kindOf } from './kinds.js';
|
|
2
3
|
import { roomPath, target } from './paths.js';
|
|
3
4
|
import { plain } from './yaml.js';
|
|
4
5
|
export const CONDITION_OPERATORS = [
|
|
@@ -12,31 +13,23 @@ export const CONDITION_OPERATORS = [
|
|
|
12
13
|
'lte',
|
|
13
14
|
'prefix',
|
|
14
15
|
];
|
|
15
|
-
export const
|
|
16
|
+
export const TEXT_FIELD = '/text';
|
|
17
|
+
export const WRITE_DOORS = ['browser', 'agent', 'client', 'function'];
|
|
16
18
|
const PROSE = { kind: 'prose' };
|
|
17
19
|
const NULL = { kind: 'null' };
|
|
18
20
|
const UNREADABLE = { kind: 'unreadable' };
|
|
19
21
|
const UNREAD = { present: undefined, values: [undefined], items: [undefined] };
|
|
20
22
|
const NO_ITEM = { present: false, values: [], items: [] };
|
|
21
|
-
const DATE = /^\d{4}-\d{2}-\d{2}$/u;
|
|
22
23
|
const HEADER = /^\/headers\/[!#$%&'*+.^_`|~0-9a-z-]+$/u;
|
|
23
|
-
const DATE_TIME = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?(?:[Zz]|([+-])(\d{2}):(\d{2}))$/u;
|
|
24
24
|
export function factKind(facts) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (facts.values !== undefined)
|
|
28
|
-
return 'enum';
|
|
29
|
-
if (facts.type === 'number' || facts.type === 'integer')
|
|
25
|
+
const kind = kindOf(facts);
|
|
26
|
+
if (kind === 'integer')
|
|
30
27
|
return 'number';
|
|
31
|
-
if (
|
|
32
|
-
return 'boolean';
|
|
33
|
-
if (facts.type !== 'string')
|
|
34
|
-
return null;
|
|
35
|
-
if (facts.format === 'date')
|
|
36
|
-
return 'date';
|
|
37
|
-
if (facts.format === 'date-time')
|
|
28
|
+
if (kind === 'date-time')
|
|
38
29
|
return 'time';
|
|
39
|
-
|
|
30
|
+
if (kind === 'time')
|
|
31
|
+
return 'string';
|
|
32
|
+
return kind;
|
|
40
33
|
}
|
|
41
34
|
function fits(kind, facts, value) {
|
|
42
35
|
if (!scalar(value))
|
|
@@ -299,12 +292,12 @@ const DOCUMENT_TESTS = [
|
|
|
299
292
|
const ACTOR_TESTS = [
|
|
300
293
|
envelope('/user', 'enum', (actor) => actor.user),
|
|
301
294
|
envelope('/site', 'enum', (actor) => actor.site),
|
|
295
|
+
envelope('/app', 'enum', (actor) => actor.app),
|
|
302
296
|
envelope('/door', 'enum', (actor) => actor.door),
|
|
303
297
|
];
|
|
304
298
|
const ITEM_TESTS = [
|
|
305
299
|
envelope('/delivery', 'enum', (item) => item.delivery),
|
|
306
300
|
envelope('/source', 'enum', (item) => item.source),
|
|
307
|
-
envelope('/has_attachment', 'boolean', (item) => item.has_attachment),
|
|
308
301
|
envelope('/container', 'string', (item) => item.container),
|
|
309
302
|
envelope('/author', 'string', (item) => item.author),
|
|
310
303
|
{
|
|
@@ -327,9 +320,15 @@ const ITEM_TESTS = [
|
|
|
327
320
|
read: (item, path) => item.json === null ? UNREAD : jsonRead(pointed(item.json.value, path.slice('/json'.length))),
|
|
328
321
|
},
|
|
329
322
|
];
|
|
323
|
+
const MESSAGE_TESTS = [
|
|
324
|
+
envelope('/sender', 'enum', (message) => message.sender),
|
|
325
|
+
envelope('/routine', 'string', (message) => message.routine),
|
|
326
|
+
envelope('/path', 'string', (message) => message.path),
|
|
327
|
+
];
|
|
330
328
|
export const DOCUMENT_PATHS = DOCUMENT_TESTS.map(({ path }) => path);
|
|
331
329
|
export const ACTOR_PATHS = ACTOR_TESTS.map(({ path }) => path);
|
|
332
330
|
export const ITEM_PATHS = ITEM_TESTS.map(({ path }) => path);
|
|
331
|
+
export const MESSAGE_PATHS = MESSAGE_TESTS.map(({ path }) => path);
|
|
333
332
|
export function testOperators(definitions, path, memberType) {
|
|
334
333
|
const own = tested(DOCUMENT_TESTS, path);
|
|
335
334
|
if (own !== undefined)
|
|
@@ -344,36 +343,12 @@ export function actorOperators(path) {
|
|
|
344
343
|
export function itemOperators(path) {
|
|
345
344
|
return tested(ITEM_TESTS, path)?.operators ?? [];
|
|
346
345
|
}
|
|
346
|
+
export function messageOperators(path) {
|
|
347
|
+
return tested(MESSAGE_TESTS, path)?.operators ?? [];
|
|
348
|
+
}
|
|
347
349
|
export function itemKind(path) {
|
|
348
350
|
return tested(ITEM_TESTS, path)?.kind ?? null;
|
|
349
351
|
}
|
|
350
|
-
export function dated(value) {
|
|
351
|
-
return (typeof value === 'string' && DATE.test(value) && instant(`${value}T00:00:00Z`) !== undefined);
|
|
352
|
-
}
|
|
353
|
-
export function instant(value) {
|
|
354
|
-
if (typeof value !== 'string')
|
|
355
|
-
return undefined;
|
|
356
|
-
const parts = DATE_TIME.exec(value);
|
|
357
|
-
if (parts === null)
|
|
358
|
-
return undefined;
|
|
359
|
-
const [year, month, day, hour, minute, second, offsetHours, offsetMinutes] = [
|
|
360
|
-
1, 2, 3, 4, 5, 6, 9, 10,
|
|
361
|
-
].map((at) => Number(parts[at] ?? 0));
|
|
362
|
-
const at = new Date(0);
|
|
363
|
-
at.setUTCFullYear(year, month - 1, day);
|
|
364
|
-
at.setUTCHours(hour, minute, second);
|
|
365
|
-
if (at.getUTCFullYear() !== year ||
|
|
366
|
-
at.getUTCMonth() !== month - 1 ||
|
|
367
|
-
at.getUTCDate() !== day ||
|
|
368
|
-
at.getUTCHours() !== hour ||
|
|
369
|
-
at.getUTCMinutes() !== minute ||
|
|
370
|
-
offsetHours > 23 ||
|
|
371
|
-
offsetMinutes > 59)
|
|
372
|
-
return undefined;
|
|
373
|
-
const offset = (parts[8] === '-' ? -1 : 1) * (offsetHours * 60 + offsetMinutes);
|
|
374
|
-
const fraction = (parts[7] ?? '').padEnd(9, '0').slice(0, 9);
|
|
375
|
-
return (BigInt(at.getTime()) - BigInt(offset) * 60000n) * 1000000n + BigInt(fraction);
|
|
376
|
-
}
|
|
377
352
|
export function pointed(value, pointer) {
|
|
378
353
|
let reached = value;
|
|
379
354
|
for (const token of pointerSegments(pointer)) {
|
|
@@ -522,7 +497,7 @@ export function members(document, path) {
|
|
|
522
497
|
export function holds(test, document) {
|
|
523
498
|
return evaluated(test, (path) => readDocument(document, path));
|
|
524
499
|
}
|
|
525
|
-
function inScope(scope, document) {
|
|
500
|
+
export function inScope(scope, document) {
|
|
526
501
|
if (document === null)
|
|
527
502
|
return false;
|
|
528
503
|
if ('type' in scope)
|
|
@@ -614,3 +589,10 @@ export function itemFires(condition, item) {
|
|
|
614
589
|
return false;
|
|
615
590
|
return (condition.match === undefined || evaluated(condition.match, reader(ITEM_TESTS, item)) === true);
|
|
616
591
|
}
|
|
592
|
+
export function notificationFires(condition, notification) {
|
|
593
|
+
return condition.match === undefined || holds(condition.match, notification) === true;
|
|
594
|
+
}
|
|
595
|
+
export function messageFires(condition, message) {
|
|
596
|
+
return (condition.match === undefined ||
|
|
597
|
+
evaluated(condition.match, reader(MESSAGE_TESTS, message)) === true);
|
|
598
|
+
}
|
package/dist/definition.d.ts
CHANGED
|
@@ -60,6 +60,7 @@ export declare const JSON_TYPES: readonly JsonType[];
|
|
|
60
60
|
export declare const BUILT_IN_TYPE = "any";
|
|
61
61
|
export declare const ATTACHMENT = "attachment";
|
|
62
62
|
export declare const ARRAY_INDEX: RegExp;
|
|
63
|
+
export declare const JSON_POINTER: RegExp;
|
|
63
64
|
export declare function escapePointer(key: string): string;
|
|
64
65
|
export declare function pointerSegments(pointer: string): string[];
|
|
65
66
|
export declare function refTarget(reference: string, defs: Readonly<Record<string, unknown>>): {
|
package/dist/definition.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../src/definition.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../src/definition.ts"],"names":[],"mappings":"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"}
|