datanotes 3.1.0 → 3.2.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/dist/api/index.cjs +175 -8
- package/dist/api/index.js +175 -8
- package/dist/api/mcp.cjs +175 -8
- package/dist/api/mcp.js +175 -8
- package/dist/datanotes.cjs +591 -139
- package/dist/docs/api/operations/add_column.md +1 -0
- package/dist/docs/api/operations/add_constraint.md +2 -0
- package/dist/docs/api/operations/alter_column.md +1 -1
- package/dist/docs/api/operations/alter_table.md +3 -2
- package/dist/docs/api/operations/check_table.md +1 -1
- package/dist/docs/api/operations/create_table.md +3 -1
- package/dist/docs/api/operations/describe_table.md +1 -1
- package/dist/docs/api/operations/insert_row.md +2 -2
- package/dist/docs/api/operations/tags/rows-dml.md +1 -1
- package/dist/docs/api.md +2 -2
- package/dist/docs/guides/data-quality/check-constraints.md +14 -13
- package/dist/docs/guides/data-quality/hand-edits.md +10 -10
- package/dist/docs/guides/database-objects/bases.md +11 -11
- package/dist/docs/guides/database-objects/catalogs-and-schemas.md +16 -10
- package/dist/docs/guides/database-objects/columns.md +38 -38
- package/dist/docs/guides/database-objects/relations.md +173 -36
- package/dist/docs/guides/database-objects/tables.md +80 -35
- package/dist/docs/guides/database-objects/views.md +44 -44
- package/dist/docs/guides/history/change-data-feed.md +34 -34
- package/dist/docs/guides/history/journal-and-undo.md +12 -12
- package/dist/docs/guides/history/restore.md +20 -20
- package/dist/docs/guides/history/table-history.md +31 -31
- package/dist/docs/guides/read-and-write/automatic-links.md +15 -15
- package/dist/docs/guides/read-and-write/import-notes.md +21 -21
- package/dist/docs/guides/read-and-write/joins-and-aggregates.md +7 -7
- package/dist/docs/guides/read-and-write/read-and-filter.md +10 -10
- package/dist/docs/guides/read-and-write/write-rows.md +10 -10
- package/dist/docs/guides/search/text.md +1 -1
- package/dist/docs/reference/cli.md +1 -1
- package/dist/docs/reference/errors.md +1 -1
- package/dist/docs/reference/operations/auxiliary.md +2 -2
- package/dist/docs/reference/operations/rows.md +1 -1
- package/dist/docs/reference/operations/schema.md +15 -11
- package/dist/docs/reference/operations.md +28 -28
- package/dist/docs/release-notes.md +24 -0
- package/package.json +1 -1
package/dist/datanotes.cjs
CHANGED
|
@@ -370,7 +370,7 @@ var init_catalog = __esm({
|
|
|
370
370
|
},
|
|
371
371
|
{
|
|
372
372
|
"name": "describe_table",
|
|
373
|
-
"description": "Describe a table (`catalog.schema.table` or a shorter unambiguous name): `qualified`, `name`,\n`catalog`, `schema`, `description`, `aliases`, `layout` (`folder`, `row_folder`: the folder pattern\nof new rows, `archive`), `options` (`partition`, `filename`, `archive`, `exclude`), typed `columns`\nwith label/aliases/description and the dense flag, `untyped_fields`, `row_count`, and when set:\n`tags`, `bases` (the bases it inherits from, in order), `constraints` (its CHECKs, name \u2192 where), `row_template`, `history`,\n`autolink_target`, `fields` (their values).\n\nBefore adding a column (e.g. a new metric), read `columns` and match your concept against\n`name`, `label`, `aliases` and `description`; reuse an existing column when it means the same.\n\n`missing_descriptions` (`{table, columns}`), present only when something has no description (a table\ndefined before descriptions were required), names what lacks one: write them with alter_table\n`description` and alter_column `changes.description`, asking the user when the meaning is unclear.",
|
|
373
|
+
"description": "Describe a table (`catalog.schema.table` or a shorter unambiguous name): `qualified`, `name`,\n`catalog`, `schema`, `description`, `aliases`, `layout` (`folder`, `row_folder`: the folder pattern\nof new rows, `archive`), `options` (`partition`, `filename`, `archive`, `exclude`), typed `columns`\nwith label/aliases/description and the dense flag, `untyped_fields`, `row_count`, and when set:\n`tags`, `bases` (the bases it inherits from, in order), `constraints` (its CHECKs, name \u2192 where), `constraint_hints` (their own hints, name \u2192 hint), `instructions` (how to fill a row: follow them before you write one), `row_template`, `history`,\n`autolink_target`, `fields` (their values).\n\nBefore adding a column (e.g. a new metric), read `columns` and match your concept against\n`name`, `label`, `aliases` and `description`; reuse an existing column when it means the same.\n\n`missing_descriptions` (`{table, columns}`), present only when something has no description (a table\ndefined before descriptions were required), names what lacks one: write them with alter_table\n`description` and alter_column `changes.description`, asking the user when the meaning is unclear.",
|
|
374
374
|
"inputSchema": {
|
|
375
375
|
"additionalProperties": false,
|
|
376
376
|
"properties": {
|
|
@@ -493,6 +493,10 @@ var init_catalog = __esm({
|
|
|
493
493
|
"inverse": {
|
|
494
494
|
"type": "string"
|
|
495
495
|
},
|
|
496
|
+
"acyclic": {
|
|
497
|
+
"type": "boolean",
|
|
498
|
+
"description": "Link column to its own table whose links never form a cycle (a write that closes one is refused)."
|
|
499
|
+
},
|
|
496
500
|
"ref_where": {
|
|
497
501
|
"type": "object",
|
|
498
502
|
"description": "Link column: the where filter every linked row must match.",
|
|
@@ -602,6 +606,17 @@ var init_catalog = __esm({
|
|
|
602
606
|
},
|
|
603
607
|
"description": "Its CHECK constraints: name \u2192 the where every row must match."
|
|
604
608
|
},
|
|
609
|
+
"constraint_hints": {
|
|
610
|
+
"type": "object",
|
|
611
|
+
"additionalProperties": {
|
|
612
|
+
"type": "string"
|
|
613
|
+
},
|
|
614
|
+
"description": "The hint of each CHECK that has one: name \u2192 what to do when a row breaks it."
|
|
615
|
+
},
|
|
616
|
+
"instructions": {
|
|
617
|
+
"type": "string",
|
|
618
|
+
"description": "How to fill a row of the table (alter_table instructions): follow them before you write one."
|
|
619
|
+
},
|
|
605
620
|
"row_template": {
|
|
606
621
|
"type": "string",
|
|
607
622
|
"description": "The text of every new row's note."
|
|
@@ -635,7 +650,7 @@ var init_catalog = __esm({
|
|
|
635
650
|
},
|
|
636
651
|
{
|
|
637
652
|
"name": "create_table",
|
|
638
|
-
"description": 'Create a table: `name`, in `catalog` and `schema` (default: the database\'s defaults); the definition\ngoes in metastore.yaml, the rows in `<root>/<catalog>/<schema>/<name>/`. Names: lowercase letters,\ndigits, `_` (no dots: pass the catalog and the schema as their own arguments).\n- `description` (required): what a row of the table records. Every column needs its own `description`\n too, what it holds: the table is refused otherwise, with every missing one listed. Descriptions are how\n agents and people understand the schema, so write them for a reader who never saw the notes. The\n engine writes those of `id` and of `identity` "uuid" / "created" columns.\n- `columns`: specs like `{"name": "kind", "type": "enum", "values": ["a","b"], "required": true,\n "description": "What kind of entry the row is"}`.\n Types: string, integer, number, boolean, date, datetime, enum, link, list (+ `items`), json.\n Attributes: required, default (`"{now}"`/`"{today}"`), min, max, step, values, `ordered` (enum in\n order: filters/avg use the position), ref (link target, full `catalog.schema.table` or "self"),\n unique, label, description, aliases, `generated` (e.g. `"date(occurred_at)"`, `"{name} {surname}"`),\n `identity` ("filename" | "created"), `vocabulary` (allowed values = names of another table\'s rows),\n `hierarchy: true` (one parent link to its own table), `dense` (written on every row),\n `inverse` on a link column: the column of the `ref` table that links back (`friends` \u2194\n `friends`, `children` \u2194 `parents`, `partner` \u2194 `partner`); writes keep both sides in step.\n- `time_column`: rows named by that date/datetime; otherwise `filename` (e.g. `"{name}"`).\n- The table\'s options, as alter_table names them: `aliases` (how agents find it, with the\n description), `partition`, `exclude`, `archive`, `history` (keep its versions; default: the\n database\'s setting), `autolink_target` (true / false: may automatic links link its rows? default:\n yes, unless its rows are named by a date or a time, as with `time_column`).\n- `row_template`: markdown body of new rows. Shared columns come from bases: `set_table_bases`.\n- `tags`: key/value labels of the table, strings (`{"domain": "health"}`); list_tables and\n describe_table return them, alter_table changes them.\nEnum columns: `values` and, for each, its meaning in `value_descriptions` (`{"stated": "the user said it", \u2026}`): describe_table shows them and a refused value lists them.\nGenerated link columns: `generated: "link({occurred_at:YYYY-MM-DD})"` with `ref` = the days table links each row to the row of `ref` named by the template (its folder read from the schema; the target may not exist yet).\nFiltered link targets (link columns): `ref_where` (a `where` every target must match) and `ref_by` (a column of the row picks the target level: `{"column": "kind", "levels": ["area", "project", "workstream"]}` or `{"column": "kind", "map": {"area": null, "project": ["area"]}}`; null = top level, no link; `target_column` when the target names it differently: an enum target column must have every value the map allows, a string one takes any value). A link to no row of the table, or to the row itself, is refused too. Existing rows that break them refuse the change; `list_link_targets` lists the valid targets of a row.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
653
|
+
"description": 'Create a table: `name`, in `catalog` and `schema` (default: the database\'s defaults); the definition\ngoes in metastore.yaml, the rows in `<root>/<catalog>/<schema>/<name>/`. Names: lowercase letters,\ndigits, `_` (no dots: pass the catalog and the schema as their own arguments).\n- `description` (required): what a row of the table records. Every column needs its own `description`\n too, what it holds: the table is refused otherwise, with every missing one listed. Descriptions are how\n agents and people understand the schema, so write them for a reader who never saw the notes. The\n engine writes those of `id` and of `identity` "uuid" / "created" columns.\n- `columns`: specs like `{"name": "kind", "type": "enum", "values": ["a","b"], "required": true,\n "description": "What kind of entry the row is"}`.\n Types: string, integer, number, boolean, date, datetime, enum, link, list (+ `items`), json.\n Attributes: required, default (`"{now}"`/`"{today}"`), min, max, step, values, `ordered` (enum in\n order: filters/avg use the position), ref (link target, full `catalog.schema.table` or "self"),\n unique, label, description, aliases, `generated` (e.g. `"date(occurred_at)"`, `"{name} {surname}"`),\n `identity` ("filename" | "created"), `vocabulary` (allowed values = names of another table\'s rows),\n `hierarchy: true` (one parent link to its own table), `acyclic: true` (links to rows of its own table that never loop back, such as tasks blocked by tasks; with `inverse`, the rule holds on both sides), `dense` (written on every row),\n `inverse` on a link column: the column of the `ref` table that links back (`friends` \u2194\n `friends`, `children` \u2194 `parents`, `partner` \u2194 `partner`); writes keep both sides in step.\n- `time_column`: rows named by that date/datetime; otherwise `filename` (e.g. `"{name}"`).\n- The table\'s options, as alter_table names them: `aliases` (how agents find it, with the\n description), `partition`, `exclude`, `archive`, `history` (keep its versions; default: the\n database\'s setting), `autolink_target` (true / false: may automatic links link its rows? default:\n yes, unless its rows are named by a date or a time, as with `time_column`).\n- `row_template`: markdown body of new rows. Shared columns come from bases: `set_table_bases`.\n- `instructions`: how to fill a row, for agents (Markdown); describe_table returns them.\n- `tags`: key/value labels of the table, strings (`{"domain": "health"}`); list_tables and\n describe_table return them, alter_table changes them.\nEnum columns: `values` and, for each, its meaning in `value_descriptions` (`{"stated": "the user said it", \u2026}`): describe_table shows them and a refused value lists them.\nGenerated link columns: `generated: "link({occurred_at:YYYY-MM-DD})"` with `ref` = the days table links each row to the row of `ref` named by the template (its folder read from the schema; the target may not exist yet).\nFiltered link targets (link columns): `ref_where` (a `where` every target must match) and `ref_by` (a column of the row picks the target level: `{"column": "kind", "levels": ["area", "project", "workstream"]}` or `{"column": "kind", "map": {"area": null, "project": ["area"]}}`; null = top level, no link; `target_column` when the target names it differently: an enum target column must have every value the map allows, a string one takes any value). A link to no row of the table, or to the row itself, is refused too. Existing rows that break them refuse the change; `list_link_targets` lists the valid targets of a row.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
639
654
|
"inputSchema": {
|
|
640
655
|
"additionalProperties": false,
|
|
641
656
|
"properties": {
|
|
@@ -796,6 +811,18 @@ var init_catalog = __esm({
|
|
|
796
811
|
"default": null,
|
|
797
812
|
"description": "Markdown body of new rows; {column} placeholders are filled from the row."
|
|
798
813
|
},
|
|
814
|
+
"instructions": {
|
|
815
|
+
"anyOf": [
|
|
816
|
+
{
|
|
817
|
+
"type": "string"
|
|
818
|
+
},
|
|
819
|
+
{
|
|
820
|
+
"type": "null"
|
|
821
|
+
}
|
|
822
|
+
],
|
|
823
|
+
"default": null,
|
|
824
|
+
"description": "How to fill a row, for agents (Markdown): which columns first, what to ask the user. describe_table returns them."
|
|
825
|
+
},
|
|
799
826
|
"fields": {
|
|
800
827
|
"anyOf": [
|
|
801
828
|
{
|
|
@@ -933,6 +960,10 @@ var init_catalog = __esm({
|
|
|
933
960
|
"type": "string",
|
|
934
961
|
"description": "The CHECK's name (code check)."
|
|
935
962
|
},
|
|
963
|
+
"hint": {
|
|
964
|
+
"type": "string",
|
|
965
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
966
|
+
},
|
|
936
967
|
"code": {
|
|
937
968
|
"type": "string",
|
|
938
969
|
"enum": [
|
|
@@ -1342,6 +1373,10 @@ var init_catalog = __esm({
|
|
|
1342
1373
|
"type": "string",
|
|
1343
1374
|
"description": "The CHECK's name (code check)."
|
|
1344
1375
|
},
|
|
1376
|
+
"hint": {
|
|
1377
|
+
"type": "string",
|
|
1378
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
1379
|
+
},
|
|
1345
1380
|
"code": {
|
|
1346
1381
|
"type": "string",
|
|
1347
1382
|
"enum": [
|
|
@@ -1621,7 +1656,7 @@ var init_catalog = __esm({
|
|
|
1621
1656
|
},
|
|
1622
1657
|
{
|
|
1623
1658
|
"name": "add_column",
|
|
1624
|
-
"description": 'Add a typed column. Sparse by default (written only on rows that have a value \u2014 use for\nmetrics, e.g. `{"name": "metric_mood", "type": "integer", "min": 1, "max": 5, "label":\n"Mood", "aliases": ["mood"], "description": "Mood of the day, 1 = bad, 5 = great"}`).\n`description` is required: what the column holds, for the agents and people who read the schema\n(the engine writes it for `identity` "uuid" / "created" columns).\n`dense: true` in the spec adds it to every row with its `default`. Call `describe_table` first: never add\na column whose meaning an existing column (name/label/aliases/description) already covers.\nColumn names are permanent identifiers; only `rename_column` changes them.\nEnum columns: `values` and, for each, its meaning in `value_descriptions` (`{"stated": "the user said it", \u2026}`): describe_table shows them and a refused value lists them.\nGenerated link columns: `generated: "link({occurred_at:YYYY-MM-DD})"` with `ref` = the days table links each row to the row of `ref` named by the template (its folder read from the schema; the target may not exist yet).\nFiltered link targets (link columns): `ref_where` (a `where` every target must match) and `ref_by` (a column of the row picks the target level: `{"column": "kind", "levels": ["area", "project", "workstream"]}` or `{"column": "kind", "map": {"area": null, "project": ["area"]}}`; null = top level, no link; `target_column` when the target names it differently: an enum target column must have every value the map allows, a string one takes any value). A link to no row of the table, or to the row itself, is refused too. Existing rows that break them refuse the change; `list_link_targets` lists the valid targets of a row.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
1659
|
+
"description": 'Add a typed column. Sparse by default (written only on rows that have a value \u2014 use for\nmetrics, e.g. `{"name": "metric_mood", "type": "integer", "min": 1, "max": 5, "label":\n"Mood", "aliases": ["mood"], "description": "Mood of the day, 1 = bad, 5 = great"}`).\n`description` is required: what the column holds, for the agents and people who read the schema\n(the engine writes it for `identity` "uuid" / "created" columns).\n`dense: true` in the spec adds it to every row with its `default`. Call `describe_table` first: never add\na column whose meaning an existing column (name/label/aliases/description) already covers.\nColumn names are permanent identifiers; only `rename_column` changes them.\nEnum columns: `values` and, for each, its meaning in `value_descriptions` (`{"stated": "the user said it", \u2026}`): describe_table shows them and a refused value lists them.\nGenerated link columns: `generated: "link({occurred_at:YYYY-MM-DD})"` with `ref` = the days table links each row to the row of `ref` named by the template (its folder read from the schema; the target may not exist yet).\nFiltered link targets (link columns): `ref_where` (a `where` every target must match) and `ref_by` (a column of the row picks the target level: `{"column": "kind", "levels": ["area", "project", "workstream"]}` or `{"column": "kind", "map": {"area": null, "project": ["area"]}}`; null = top level, no link; `target_column` when the target names it differently: an enum target column must have every value the map allows, a string one takes any value). A link to no row of the table, or to the row itself, is refused too. Existing rows that break them refuse the change; `list_link_targets` lists the valid targets of a row.\nAcyclic links: `acyclic: true` on a link (or list of links) to the table itself refuses every write that closes a cycle, on either side of an `inverse`; refused while existing rows form one (they are listed).\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
1625
1660
|
"inputSchema": {
|
|
1626
1661
|
"additionalProperties": false,
|
|
1627
1662
|
"properties": {
|
|
@@ -1742,6 +1777,10 @@ var init_catalog = __esm({
|
|
|
1742
1777
|
"type": "string",
|
|
1743
1778
|
"description": "The CHECK's name (code check)."
|
|
1744
1779
|
},
|
|
1780
|
+
"hint": {
|
|
1781
|
+
"type": "string",
|
|
1782
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
1783
|
+
},
|
|
1745
1784
|
"code": {
|
|
1746
1785
|
"type": "string",
|
|
1747
1786
|
"enum": [
|
|
@@ -2144,6 +2183,10 @@ var init_catalog = __esm({
|
|
|
2144
2183
|
"type": "string",
|
|
2145
2184
|
"description": "The CHECK's name (code check)."
|
|
2146
2185
|
},
|
|
2186
|
+
"hint": {
|
|
2187
|
+
"type": "string",
|
|
2188
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
2189
|
+
},
|
|
2147
2190
|
"code": {
|
|
2148
2191
|
"type": "string",
|
|
2149
2192
|
"enum": [
|
|
@@ -2543,6 +2586,10 @@ var init_catalog = __esm({
|
|
|
2543
2586
|
"type": "string",
|
|
2544
2587
|
"description": "The CHECK's name (code check)."
|
|
2545
2588
|
},
|
|
2589
|
+
"hint": {
|
|
2590
|
+
"type": "string",
|
|
2591
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
2592
|
+
},
|
|
2546
2593
|
"code": {
|
|
2547
2594
|
"type": "string",
|
|
2548
2595
|
"enum": [
|
|
@@ -2822,7 +2869,7 @@ var init_catalog = __esm({
|
|
|
2822
2869
|
},
|
|
2823
2870
|
{
|
|
2824
2871
|
"name": "alter_column",
|
|
2825
|
-
"description": 'Change a column\'s attributes (type, min/max/step, values, required, default, label,\naliases, description, note, `ref_where`, `ref_by` (see list_link_targets); `null` removes an attribute, except\n`description`, which changes but never goes (null or "" is refused); `dense` true/false). Refused with\nthe list of violating rows when existing values do not satisfy the new definition. A\ndifferent scale means a different column: add a new one instead of rescaling. To rename one\nenum value use `rename_value`. Dropping an enum value that a `ref_by` (of any table) allows as a\ntarget level is refused, naming it.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
2872
|
+
"description": 'Change a column\'s attributes (type, min/max/step, values, required, default, label,\naliases, description, note, `ref_where`, `ref_by` (see list_link_targets), `acyclic` (refused while the rows already form a cycle: they are listed); `null` removes an attribute, except\n`description`, which changes but never goes (null or "" is refused); `dense` true/false). Refused with\nthe list of violating rows when existing values do not satisfy the new definition. A\ndifferent scale means a different column: add a new one instead of rescaling. To rename one\nenum value use `rename_value`. Dropping an enum value that a `ref_by` (of any table) allows as a\ntarget level is refused, naming it.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
2826
2873
|
"inputSchema": {
|
|
2827
2874
|
"additionalProperties": false,
|
|
2828
2875
|
"properties": {
|
|
@@ -2947,6 +2994,10 @@ var init_catalog = __esm({
|
|
|
2947
2994
|
"type": "string",
|
|
2948
2995
|
"description": "The CHECK's name (code check)."
|
|
2949
2996
|
},
|
|
2997
|
+
"hint": {
|
|
2998
|
+
"type": "string",
|
|
2999
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
3000
|
+
},
|
|
2950
3001
|
"code": {
|
|
2951
3002
|
"type": "string",
|
|
2952
3003
|
"enum": [
|
|
@@ -3226,7 +3277,7 @@ var init_catalog = __esm({
|
|
|
3226
3277
|
},
|
|
3227
3278
|
{
|
|
3228
3279
|
"name": "alter_table",
|
|
3229
|
-
"description": 'Alter a table: move it (`catalog`, `schema`), rename it (`name`), change\n`partition` / `filename` patterns, `description` (changes, never goes: "" is refused), `aliases`,\n`exclude` folders, `row_template`\n("" removes it), `history` (true | false | "default"), `autolink_target`\n(true | false | "default": may automatic links link its rows? default: yes, unless its rows are named by\na date or a time) or `tags` (key/value\nlabels merged into the table\'s, e.g. `{"domain": "health"}`; a `null` value removes that tag;\n`clear_tags: true` removes every tag first, so with `tags` the table keeps exactly those),\n`archive` (folder name inside the table folder) or `fields` (untyped fields, name \u2192 default; a\n`null` value removes one). Rows, archive and transaction log follow; links are updated; renamed\nrows keep their old name in `aliases`. A change of metadata only (tags, description, aliases,\nhistory, autolink_target, row_template, fields) rewrites the table entry alone: no row is moved or rewritten. Refused\nwhen a row cannot fill a pattern. Renaming or moving the table is refused while a CHECK that follows\nlinks, or a `ref_where` / `ref_by`, of another table reads it through a link (link targets are not\nrewritten): the conflicts name them. Use `dry_run` to see `planned_moves`; undo with undo_migration.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
3280
|
+
"description": 'Alter a table: move it (`catalog`, `schema`), rename it (`name`), change\n`partition` / `filename` patterns, `description` (changes, never goes: "" is refused), `aliases`,\n`exclude` folders, `row_template`\n("" removes it), `instructions` (how to fill a row, for agents; "" removes them), `history` (true | false | "default"), `autolink_target`\n(true | false | "default": may automatic links link its rows? default: yes, unless its rows are named by\na date or a time) or `tags` (key/value\nlabels merged into the table\'s, e.g. `{"domain": "health"}`; a `null` value removes that tag;\n`clear_tags: true` removes every tag first, so with `tags` the table keeps exactly those),\n`archive` (folder name inside the table folder) or `fields` (untyped fields, name \u2192 default; a\n`null` value removes one). Rows, archive and transaction log follow; links are updated; renamed\nrows keep their old name in `aliases`. A change of metadata only (tags, description, aliases,\nhistory, autolink_target, row_template, instructions, fields) rewrites the table entry alone: no row is moved or rewritten. Refused\nwhen a row cannot fill a pattern. Renaming or moving the table is refused while a CHECK that follows\nlinks, or a `ref_where` / `ref_by`, of another table reads it through a link (link targets are not\nrewritten): the conflicts name them. Use `dry_run` to see `planned_moves`; undo with undo_migration.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
3230
3281
|
"inputSchema": {
|
|
3231
3282
|
"additionalProperties": false,
|
|
3232
3283
|
"properties": {
|
|
@@ -3376,6 +3427,18 @@ var init_catalog = __esm({
|
|
|
3376
3427
|
"default": null,
|
|
3377
3428
|
"description": 'Markdown body of new rows; "" removes it.'
|
|
3378
3429
|
},
|
|
3430
|
+
"instructions": {
|
|
3431
|
+
"anyOf": [
|
|
3432
|
+
{
|
|
3433
|
+
"type": "string"
|
|
3434
|
+
},
|
|
3435
|
+
{
|
|
3436
|
+
"type": "null"
|
|
3437
|
+
}
|
|
3438
|
+
],
|
|
3439
|
+
"default": null,
|
|
3440
|
+
"description": 'How to fill a row, for agents (Markdown); "" removes them.'
|
|
3441
|
+
},
|
|
3379
3442
|
"tags": {
|
|
3380
3443
|
"anyOf": [
|
|
3381
3444
|
{
|
|
@@ -3536,6 +3599,10 @@ var init_catalog = __esm({
|
|
|
3536
3599
|
"type": "string",
|
|
3537
3600
|
"description": "The CHECK's name (code check)."
|
|
3538
3601
|
},
|
|
3602
|
+
"hint": {
|
|
3603
|
+
"type": "string",
|
|
3604
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
3605
|
+
},
|
|
3539
3606
|
"code": {
|
|
3540
3607
|
"type": "string",
|
|
3541
3608
|
"enum": [
|
|
@@ -3992,6 +4059,10 @@ var init_catalog = __esm({
|
|
|
3992
4059
|
"type": "string",
|
|
3993
4060
|
"description": "The CHECK's name (code check)."
|
|
3994
4061
|
},
|
|
4062
|
+
"hint": {
|
|
4063
|
+
"type": "string",
|
|
4064
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
4065
|
+
},
|
|
3995
4066
|
"code": {
|
|
3996
4067
|
"type": "string",
|
|
3997
4068
|
"enum": [
|
|
@@ -4393,6 +4464,10 @@ var init_catalog = __esm({
|
|
|
4393
4464
|
"type": "string",
|
|
4394
4465
|
"description": "The CHECK's name (code check)."
|
|
4395
4466
|
},
|
|
4467
|
+
"hint": {
|
|
4468
|
+
"type": "string",
|
|
4469
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
4470
|
+
},
|
|
4396
4471
|
"code": {
|
|
4397
4472
|
"type": "string",
|
|
4398
4473
|
"enum": [
|
|
@@ -5455,6 +5530,10 @@ var init_catalog = __esm({
|
|
|
5455
5530
|
"type": "string",
|
|
5456
5531
|
"description": "The CHECK's name (code check)."
|
|
5457
5532
|
},
|
|
5533
|
+
"hint": {
|
|
5534
|
+
"type": "string",
|
|
5535
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
5536
|
+
},
|
|
5458
5537
|
"code": {
|
|
5459
5538
|
"type": "string",
|
|
5460
5539
|
"enum": [
|
|
@@ -5861,6 +5940,10 @@ var init_catalog = __esm({
|
|
|
5861
5940
|
"type": "string",
|
|
5862
5941
|
"description": "The CHECK's name (code check)."
|
|
5863
5942
|
},
|
|
5943
|
+
"hint": {
|
|
5944
|
+
"type": "string",
|
|
5945
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
5946
|
+
},
|
|
5864
5947
|
"code": {
|
|
5865
5948
|
"type": "string",
|
|
5866
5949
|
"enum": [
|
|
@@ -6140,7 +6223,7 @@ var init_catalog = __esm({
|
|
|
6140
6223
|
},
|
|
6141
6224
|
{
|
|
6142
6225
|
"name": "insert_row",
|
|
6143
|
-
"description": "Insert a row (new note). Values are validated against the columns; the note path comes from\nthe table's `path`/`filename` patterns (e.g. an event logged today about last night lands in\nlast night's day folder when you set `occurred_at` to last night). `body` is the note text.\nGenerated / identity columns are computed (do not pass them); CHECK constraints are enforced.\nReturns `migration_id` (undo) and the created path in `planned_creates`.\n`body` links the notes it mentions by name, at their first mention (automatic links; off with\n`autolink: false` or the database's `autolink` setting). `links_added` lists the links made;\n`ambiguous_mentions` lists the mentions left as text with the notes they may name: read those,\nthen link the right one with update_row and `autolink: false`, or leave the text.",
|
|
6226
|
+
"description": "Insert a row (new note). When describe_table gives the table's `instructions`, fill the row as they say. Values are validated against the columns; the note path comes from\nthe table's `path`/`filename` patterns (e.g. an event logged today about last night lands in\nlast night's day folder when you set `occurred_at` to last night). `body` is the note text.\nGenerated / identity columns are computed (do not pass them); CHECK constraints are enforced.\nReturns `migration_id` (undo) and the created path in `planned_creates`.\n`body` links the notes it mentions by name, at their first mention (automatic links; off with\n`autolink: false` or the database's `autolink` setting). `links_added` lists the links made;\n`ambiguous_mentions` lists the mentions left as text with the notes they may name: read those,\nthen link the right one with update_row and `autolink: false`, or leave the text.",
|
|
6144
6227
|
"inputSchema": {
|
|
6145
6228
|
"additionalProperties": false,
|
|
6146
6229
|
"properties": {
|
|
@@ -6295,6 +6378,10 @@ var init_catalog = __esm({
|
|
|
6295
6378
|
"type": "string",
|
|
6296
6379
|
"description": "The CHECK's name (code check)."
|
|
6297
6380
|
},
|
|
6381
|
+
"hint": {
|
|
6382
|
+
"type": "string",
|
|
6383
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
6384
|
+
},
|
|
6298
6385
|
"code": {
|
|
6299
6386
|
"type": "string",
|
|
6300
6387
|
"enum": [
|
|
@@ -6733,6 +6820,10 @@ var init_catalog = __esm({
|
|
|
6733
6820
|
"type": "string",
|
|
6734
6821
|
"description": "The CHECK's name (code check)."
|
|
6735
6822
|
},
|
|
6823
|
+
"hint": {
|
|
6824
|
+
"type": "string",
|
|
6825
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
6826
|
+
},
|
|
6736
6827
|
"code": {
|
|
6737
6828
|
"type": "string",
|
|
6738
6829
|
"enum": [
|
|
@@ -7246,6 +7337,10 @@ var init_catalog = __esm({
|
|
|
7246
7337
|
"type": "string",
|
|
7247
7338
|
"description": "The CHECK's name (code check)."
|
|
7248
7339
|
},
|
|
7340
|
+
"hint": {
|
|
7341
|
+
"type": "string",
|
|
7342
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
7343
|
+
},
|
|
7249
7344
|
"code": {
|
|
7250
7345
|
"type": "string",
|
|
7251
7346
|
"enum": [
|
|
@@ -7677,6 +7772,10 @@ var init_catalog = __esm({
|
|
|
7677
7772
|
"type": "string",
|
|
7678
7773
|
"description": "The CHECK's name (code check)."
|
|
7679
7774
|
},
|
|
7775
|
+
"hint": {
|
|
7776
|
+
"type": "string",
|
|
7777
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
7778
|
+
},
|
|
7680
7779
|
"code": {
|
|
7681
7780
|
"type": "string",
|
|
7682
7781
|
"enum": [
|
|
@@ -8125,6 +8224,10 @@ var init_catalog = __esm({
|
|
|
8125
8224
|
"type": "string",
|
|
8126
8225
|
"description": "The CHECK's name (code check)."
|
|
8127
8226
|
},
|
|
8227
|
+
"hint": {
|
|
8228
|
+
"type": "string",
|
|
8229
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
8230
|
+
},
|
|
8128
8231
|
"code": {
|
|
8129
8232
|
"type": "string",
|
|
8130
8233
|
"enum": [
|
|
@@ -8585,6 +8688,10 @@ var init_catalog = __esm({
|
|
|
8585
8688
|
"type": "string",
|
|
8586
8689
|
"description": "The CHECK's name (code check)."
|
|
8587
8690
|
},
|
|
8691
|
+
"hint": {
|
|
8692
|
+
"type": "string",
|
|
8693
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
8694
|
+
},
|
|
8588
8695
|
"code": {
|
|
8589
8696
|
"type": "string",
|
|
8590
8697
|
"enum": [
|
|
@@ -9093,7 +9200,7 @@ var init_catalog = __esm({
|
|
|
9093
9200
|
},
|
|
9094
9201
|
{
|
|
9095
9202
|
"name": "check_table",
|
|
9096
|
-
"description": "Validate every row against the table (required, types, ranges, enums, links, unknown\ncolumns, CHECK constraints, those that follow links included, filtered link targets (ref_where / ref_by), stale generated/identity values, missing inverse links, front matter that cannot be read: code `unreadable`, with no column, for a note whose `table` line names the table but whose YAML is broken, which every other read leaves out). A CHECK violation has code `check` and the CHECK's name as `constraint` (every other code names its `column`), as in the `violations` of list_changes. Use it to find rows edited by hand that break the schema. Without `table`, every table is checked: each row then names its `table`, `tables_checked` counts the tables checked, and a table that cannot be checked is listed in `errors` ({table, error}) while the others are. The rows with violations are paged: `limit` (default 500, at most 5000) from `offset`; `total` counts them all. (Hand edits are also checked as they happen: see `violations` in list_changes.)",
|
|
9203
|
+
"description": "Validate every row against the table (required, types, ranges, enums, links, unknown\ncolumns, CHECK constraints, those that follow links included, filtered link targets (ref_where / ref_by), stale generated/identity values, missing inverse links, cycles of hierarchy and acyclic columns, front matter that cannot be read: code `unreadable`, with no column, for a note whose `table` line names the table but whose YAML is broken, which every other read leaves out). A CHECK violation has code `check` and the CHECK's name as `constraint` (every other code names its `column`), as in the `violations` of list_changes. Use it to find rows edited by hand that break the schema. Without `table`, every table is checked: each row then names its `table`, `tables_checked` counts the tables checked, and a table that cannot be checked is listed in `errors` ({table, error}) while the others are. The rows with violations are paged: `limit` (default 500, at most 5000) from `offset`; `total` counts them all. (Hand edits are also checked as they happen: see `violations` in list_changes.)",
|
|
9097
9204
|
"inputSchema": {
|
|
9098
9205
|
"additionalProperties": false,
|
|
9099
9206
|
"properties": {
|
|
@@ -9206,6 +9313,10 @@ var init_catalog = __esm({
|
|
|
9206
9313
|
"type": "string",
|
|
9207
9314
|
"description": "The CHECK's name (code check)."
|
|
9208
9315
|
},
|
|
9316
|
+
"hint": {
|
|
9317
|
+
"type": "string",
|
|
9318
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
9319
|
+
},
|
|
9209
9320
|
"code": {
|
|
9210
9321
|
"type": "string",
|
|
9211
9322
|
"enum": [
|
|
@@ -9659,6 +9770,10 @@ var init_catalog = __esm({
|
|
|
9659
9770
|
"type": "string",
|
|
9660
9771
|
"description": "The CHECK's name (code check)."
|
|
9661
9772
|
},
|
|
9773
|
+
"hint": {
|
|
9774
|
+
"type": "string",
|
|
9775
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
9776
|
+
},
|
|
9662
9777
|
"code": {
|
|
9663
9778
|
"type": "string",
|
|
9664
9779
|
"enum": [
|
|
@@ -10102,6 +10217,10 @@ var init_catalog = __esm({
|
|
|
10102
10217
|
"type": "string",
|
|
10103
10218
|
"description": "The CHECK's name (code check)."
|
|
10104
10219
|
},
|
|
10220
|
+
"hint": {
|
|
10221
|
+
"type": "string",
|
|
10222
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
10223
|
+
},
|
|
10105
10224
|
"code": {
|
|
10106
10225
|
"type": "string",
|
|
10107
10226
|
"enum": [
|
|
@@ -11185,6 +11304,10 @@ var init_catalog = __esm({
|
|
|
11185
11304
|
"type": "string",
|
|
11186
11305
|
"description": "The CHECK's name (code check)."
|
|
11187
11306
|
},
|
|
11307
|
+
"hint": {
|
|
11308
|
+
"type": "string",
|
|
11309
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
11310
|
+
},
|
|
11188
11311
|
"code": {
|
|
11189
11312
|
"type": "string",
|
|
11190
11313
|
"enum": [
|
|
@@ -12622,6 +12745,10 @@ var init_catalog = __esm({
|
|
|
12622
12745
|
"type": "string",
|
|
12623
12746
|
"description": "The CHECK's name (code check)."
|
|
12624
12747
|
},
|
|
12748
|
+
"hint": {
|
|
12749
|
+
"type": "string",
|
|
12750
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
12751
|
+
},
|
|
12625
12752
|
"code": {
|
|
12626
12753
|
"type": "string",
|
|
12627
12754
|
"enum": [
|
|
@@ -13032,6 +13159,10 @@ var init_catalog = __esm({
|
|
|
13032
13159
|
"type": "string",
|
|
13033
13160
|
"description": "The CHECK's name (code check)."
|
|
13034
13161
|
},
|
|
13162
|
+
"hint": {
|
|
13163
|
+
"type": "string",
|
|
13164
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
13165
|
+
},
|
|
13035
13166
|
"code": {
|
|
13036
13167
|
"type": "string",
|
|
13037
13168
|
"enum": [
|
|
@@ -13498,7 +13629,7 @@ var init_catalog = __esm({
|
|
|
13498
13629
|
},
|
|
13499
13630
|
{
|
|
13500
13631
|
"name": "add_constraint",
|
|
13501
|
-
"description": 'ALTER TABLE ADD CONSTRAINT `name` CHECK: `check` is a where filter every row must match,\ne.g. `{"value": {"gte": 1, "lte": 5}}`. A condition on a column the row leaves empty passes, like SQL;\ninside `or` / `and` / `not` an empty value is tested as it is (`{"exists": true}` there fails).\nA key may follow a link column to the row it names, as in queries: `{"parent.kind": "project"}`\n(further dots follow further links). An empty link passes at the top level and fails inside `or` / `and` /\n`not`; only the first link of a longer path is skipped when empty (`parent.parent.kind` fails for a row\nwhose parent has no parent). A link to a row that does not exist fails; on a list of links every linked\nrow must match. `not` turns that into a pass: `{"not": {"parent.kind": "area"}}` passes a link to a\nmissing row, so add `"parent.kind": {"exists": true}` to require a real one. Links resolve as in the\nvault (by path, from the row\'s note: same-named rows in two folders stay apart); renaming or moving a\nlinked row keeps them (they follow it).\nRefused while existing rows violate it (they are listed); then enforced on every write, by the same rule.\nA write that changes a linked row re-checks the rows that link to it and is refused, listing them, when\nit breaks them, naming the changed row (in a batch, re-link them first: each step is checked on the vault\nthe earlier ones left); the inverse links a write adds, undo_migration and restore_table are checked too.\nrename_column / rename_value follow into CHECKs; drop_column of a column a CHECK reads is refused.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
13632
|
+
"description": 'ALTER TABLE ADD CONSTRAINT `name` CHECK: `check` is a where filter every row must match,\ne.g. `{"value": {"gte": 1, "lte": 5}}`. A condition on a column the row leaves empty passes, like SQL;\ninside `or` / `and` / `not` an empty value is tested as it is (`{"exists": true}` there fails).\nA key may follow a link column to the row it names, as in queries: `{"parent.kind": "project"}`\n(further dots follow further links). An empty link passes at the top level and fails inside `or` / `and` /\n`not`; only the first link of a longer path is skipped when empty (`parent.parent.kind` fails for a row\nwhose parent has no parent). A link to a row that does not exist fails; on a list of links every linked\nrow must match. `not` turns that into a pass: `{"not": {"parent.kind": "area"}}` passes a link to a\nmissing row, so add `"parent.kind": {"exists": true}` to require a real one. Links resolve as in the\nvault (by path, from the row\'s note: same-named rows in two folders stay apart); renaming or moving a\nlinked row keeps them (they follow it).\nRefused while existing rows violate it (they are listed); then enforced on every write, by the same rule.\nA write that changes a linked row re-checks the rows that link to it and is refused, listing them, when\nit breaks them, naming the changed row (in a batch, re-link them first: each step is checked on the vault\nthe earlier ones left); the inverse links a write adds, undo_migration and restore_table are checked too.\nrename_column / rename_value follow into CHECKs; drop_column of a column a CHECK reads is refused.\n`hint`: what to do when a row breaks the rule, in your words; a refused write puts it first in its hint, and each violation of the CHECK carries it.\n\nThe schema changes only through operations like this one: never edit metastore.yaml by hand (no validation, no undo).',
|
|
13502
13633
|
"inputSchema": {
|
|
13503
13634
|
"additionalProperties": false,
|
|
13504
13635
|
"properties": {
|
|
@@ -13512,6 +13643,18 @@ var init_catalog = __esm({
|
|
|
13512
13643
|
"additionalProperties": true,
|
|
13513
13644
|
"type": "object"
|
|
13514
13645
|
},
|
|
13646
|
+
"hint": {
|
|
13647
|
+
"anyOf": [
|
|
13648
|
+
{
|
|
13649
|
+
"type": "string"
|
|
13650
|
+
},
|
|
13651
|
+
{
|
|
13652
|
+
"type": "null"
|
|
13653
|
+
}
|
|
13654
|
+
],
|
|
13655
|
+
"default": null,
|
|
13656
|
+
"description": "What a refused write tells the agent when a row breaks this CHECK: how to fix the row. It comes first in the refusal's hint; describe_table lists it in constraint_hints."
|
|
13657
|
+
},
|
|
13515
13658
|
"dry_run": {
|
|
13516
13659
|
"default": false,
|
|
13517
13660
|
"type": "boolean"
|
|
@@ -13622,6 +13765,10 @@ var init_catalog = __esm({
|
|
|
13622
13765
|
"type": "string",
|
|
13623
13766
|
"description": "The CHECK's name (code check)."
|
|
13624
13767
|
},
|
|
13768
|
+
"hint": {
|
|
13769
|
+
"type": "string",
|
|
13770
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
13771
|
+
},
|
|
13625
13772
|
"code": {
|
|
13626
13773
|
"type": "string",
|
|
13627
13774
|
"enum": [
|
|
@@ -14020,6 +14167,10 @@ var init_catalog = __esm({
|
|
|
14020
14167
|
"type": "string",
|
|
14021
14168
|
"description": "The CHECK's name (code check)."
|
|
14022
14169
|
},
|
|
14170
|
+
"hint": {
|
|
14171
|
+
"type": "string",
|
|
14172
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
14173
|
+
},
|
|
14023
14174
|
"code": {
|
|
14024
14175
|
"type": "string",
|
|
14025
14176
|
"enum": [
|
|
@@ -14485,6 +14636,10 @@ var init_catalog = __esm({
|
|
|
14485
14636
|
"type": "string",
|
|
14486
14637
|
"description": "The CHECK's name (code check)."
|
|
14487
14638
|
},
|
|
14639
|
+
"hint": {
|
|
14640
|
+
"type": "string",
|
|
14641
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
14642
|
+
},
|
|
14488
14643
|
"code": {
|
|
14489
14644
|
"type": "string",
|
|
14490
14645
|
"enum": [
|
|
@@ -14879,6 +15034,10 @@ var init_catalog = __esm({
|
|
|
14879
15034
|
"type": "string",
|
|
14880
15035
|
"description": "The CHECK's name (code check)."
|
|
14881
15036
|
},
|
|
15037
|
+
"hint": {
|
|
15038
|
+
"type": "string",
|
|
15039
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
15040
|
+
},
|
|
14882
15041
|
"code": {
|
|
14883
15042
|
"type": "string",
|
|
14884
15043
|
"enum": [
|
|
@@ -15304,6 +15463,10 @@ var init_catalog = __esm({
|
|
|
15304
15463
|
"type": "string",
|
|
15305
15464
|
"description": "The CHECK's name (code check)."
|
|
15306
15465
|
},
|
|
15466
|
+
"hint": {
|
|
15467
|
+
"type": "string",
|
|
15468
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
15469
|
+
},
|
|
15307
15470
|
"code": {
|
|
15308
15471
|
"type": "string",
|
|
15309
15472
|
"enum": [
|
|
@@ -15716,6 +15879,10 @@ var init_catalog = __esm({
|
|
|
15716
15879
|
"type": "string",
|
|
15717
15880
|
"description": "The CHECK's name (code check)."
|
|
15718
15881
|
},
|
|
15882
|
+
"hint": {
|
|
15883
|
+
"type": "string",
|
|
15884
|
+
"description": "The CHECK's own hint (code check), when the constraint has one: how to fix the row."
|
|
15885
|
+
},
|
|
15719
15886
|
"code": {
|
|
15720
15887
|
"type": "string",
|
|
15721
15888
|
"enum": [
|
|
@@ -19023,13 +19190,13 @@ var require_stringifyCollection = __commonJS({
|
|
|
19023
19190
|
const stringify3 = flow ? stringifyFlowCollection : stringifyBlockCollection;
|
|
19024
19191
|
return stringify3(collection, ctx, options);
|
|
19025
19192
|
}
|
|
19026
|
-
function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
|
|
19193
|
+
function stringifyBlockCollection({ comment, items: items2 }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
|
|
19027
19194
|
const { indent, options: { commentString } } = ctx;
|
|
19028
19195
|
const itemCtx = Object.assign({}, ctx, { indent: itemIndent, type: null });
|
|
19029
19196
|
let chompKeep = false;
|
|
19030
19197
|
const lines = [];
|
|
19031
|
-
for (let i = 0; i <
|
|
19032
|
-
const item =
|
|
19198
|
+
for (let i = 0; i < items2.length; ++i) {
|
|
19199
|
+
const item = items2[i];
|
|
19033
19200
|
let comment2 = null;
|
|
19034
19201
|
if (identity.isNode(item)) {
|
|
19035
19202
|
if (!chompKeep && item.spaceBefore)
|
|
@@ -19072,7 +19239,7 @@ ${indent}${line}` : "\n";
|
|
|
19072
19239
|
onChompKeep();
|
|
19073
19240
|
return str3;
|
|
19074
19241
|
}
|
|
19075
|
-
function stringifyFlowCollection({ items }, ctx, { flowChars, itemIndent }) {
|
|
19242
|
+
function stringifyFlowCollection({ items: items2 }, ctx, { flowChars, itemIndent }) {
|
|
19076
19243
|
const { indent, indentStep, flowCollectionPadding: fcPadding, options: { commentString } } = ctx;
|
|
19077
19244
|
itemIndent += indentStep;
|
|
19078
19245
|
const itemCtx = Object.assign({}, ctx, {
|
|
@@ -19083,8 +19250,8 @@ ${indent}${line}` : "\n";
|
|
|
19083
19250
|
let reqNewline = false;
|
|
19084
19251
|
let linesAtValue = 0;
|
|
19085
19252
|
const lines = [];
|
|
19086
|
-
for (let i = 0; i <
|
|
19087
|
-
const item =
|
|
19253
|
+
for (let i = 0; i < items2.length; ++i) {
|
|
19254
|
+
const item = items2[i];
|
|
19088
19255
|
let comment = null;
|
|
19089
19256
|
if (identity.isNode(item)) {
|
|
19090
19257
|
if (item.spaceBefore)
|
|
@@ -19115,7 +19282,7 @@ ${indent}${line}` : "\n";
|
|
|
19115
19282
|
reqNewline = true;
|
|
19116
19283
|
let str3 = stringify2.stringify(item, itemCtx, () => comment = null);
|
|
19117
19284
|
reqNewline || (reqNewline = lines.length > linesAtValue || str3.includes("\n"));
|
|
19118
|
-
if (i <
|
|
19285
|
+
if (i < items2.length - 1) {
|
|
19119
19286
|
str3 += ",";
|
|
19120
19287
|
} else if (ctx.options.trailingComma) {
|
|
19121
19288
|
if (ctx.options.lineWidth > 0) {
|
|
@@ -19172,9 +19339,9 @@ var require_YAMLMap = __commonJS({
|
|
|
19172
19339
|
var identity = require_identity();
|
|
19173
19340
|
var Pair = require_Pair();
|
|
19174
19341
|
var Scalar = require_Scalar();
|
|
19175
|
-
function findPair(
|
|
19342
|
+
function findPair(items2, key2) {
|
|
19176
19343
|
const k = identity.isScalar(key2) ? key2.value : key2;
|
|
19177
|
-
for (const it of
|
|
19344
|
+
for (const it of items2) {
|
|
19178
19345
|
if (identity.isPair(it)) {
|
|
19179
19346
|
if (it.key === key2 || it.key === k)
|
|
19180
19347
|
return it;
|
|
@@ -21122,12 +21289,12 @@ var require_util_map_includes = __commonJS({
|
|
|
21122
21289
|
"node_modules/yaml/dist/compose/util-map-includes.js"(exports2) {
|
|
21123
21290
|
"use strict";
|
|
21124
21291
|
var identity = require_identity();
|
|
21125
|
-
function mapIncludes(ctx,
|
|
21292
|
+
function mapIncludes(ctx, items2, search) {
|
|
21126
21293
|
const { uniqueKeys } = ctx.options;
|
|
21127
21294
|
if (uniqueKeys === false)
|
|
21128
21295
|
return false;
|
|
21129
21296
|
const isEqual = typeof uniqueKeys === "function" ? uniqueKeys : (a, b) => a === b || identity.isScalar(a) && identity.isScalar(b) && a.value === b.value;
|
|
21130
|
-
return
|
|
21297
|
+
return items2.some((pair) => isEqual(pair.key, search));
|
|
21131
21298
|
}
|
|
21132
21299
|
exports2.mapIncludes = mapIncludes;
|
|
21133
21300
|
}
|
|
@@ -24835,16 +25002,26 @@ function unknownOperator(bad, operators) {
|
|
|
24835
25002
|
function violationGuidance(code) {
|
|
24836
25003
|
return VIOLATION_GUIDANCE[code];
|
|
24837
25004
|
}
|
|
25005
|
+
function guidanceOfViolation(v) {
|
|
25006
|
+
return v.code === "cycle" && typeof v.message === "string" && ACYCLIC_CYCLE.test(v.message) ? ACYCLIC_GUIDANCE : violationGuidance(v.code);
|
|
25007
|
+
}
|
|
24838
25008
|
function undoGuidance(r) {
|
|
24839
25009
|
if (r.failed.length > 0) return guide("Some files could not be written back: undo_migration again once they are free, or repair them by hand.", "undo");
|
|
24840
25010
|
if (r.conflicts.some((c) => /already undone/.test(c.message))) return guide("This write is undone already: to redo it, undo the undo (its migration_id is in list_migrations).", "undo");
|
|
24841
25011
|
return guide("Later changes touched the same notes: undo those first (list_migrations lists them, newest first), or change the rows with update_row.", "undoConflict");
|
|
24842
25012
|
}
|
|
24843
25013
|
function refusalGuidance(r) {
|
|
24844
|
-
const
|
|
24845
|
-
|
|
24846
|
-
|
|
24847
|
-
|
|
25014
|
+
const all = (r.violations ?? []).flatMap((rv) => rv.violations);
|
|
25015
|
+
const kinds = /* @__PURE__ */ new Map();
|
|
25016
|
+
for (const v of all) {
|
|
25017
|
+
const g = guidanceOfViolation(v);
|
|
25018
|
+
const key2 = g === ACYCLIC_GUIDANCE ? "cycle:acyclic" : v.code;
|
|
25019
|
+
if (!kinds.has(key2)) kinds.set(key2, g);
|
|
25020
|
+
}
|
|
25021
|
+
if (kinds.size > 0) {
|
|
25022
|
+
const gs = [...kinds.values()].slice(0, 3);
|
|
25023
|
+
const own2 = [...new Set(all.map((v) => v.hint).filter((h) => typeof h === "string" && h.trim() !== ""))].slice(0, 3);
|
|
25024
|
+
return { hint: `${[...own2, ...new Set(gs.map((g) => g.hint))].join(" ")} Then call ${r.op} again (dry_run: true checks without writing).`, docs: gs[0].docs };
|
|
24848
25025
|
}
|
|
24849
25026
|
if ((r.failed?.length ?? 0) > 0) {
|
|
24850
25027
|
if (r.rolled_back === true) return guide(`A file could not be written (another program may hold it): the engine put back what it had written, so nothing changed. Close that program, then call ${r.op} again.`, "failedWrite");
|
|
@@ -24856,7 +25033,7 @@ function refusalGuidance(r) {
|
|
|
24856
25033
|
if (known) return known[1](r.op);
|
|
24857
25034
|
return guide(`Resolve what the message names, then call ${r.op} again; dry_run: true checks without writing.`, "errors");
|
|
24858
25035
|
}
|
|
24859
|
-
var DOCS_BASE2, DOCS, GuidedError, fold2, quoted, GENERATED_HINT, OPERATOR_SYNONYMS, VIOLATION_GUIDANCE, CONFLICTS;
|
|
25036
|
+
var DOCS_BASE2, DOCS, GuidedError, fold2, quoted, GENERATED_HINT, OPERATOR_SYNONYMS, VIOLATION_GUIDANCE, ACYCLIC_CYCLE, ACYCLIC_GUIDANCE, CONFLICTS;
|
|
24860
25037
|
var init_hints = __esm({
|
|
24861
25038
|
"src/core/hints.ts"() {
|
|
24862
25039
|
"use strict";
|
|
@@ -24887,6 +25064,8 @@ var init_hints = __esm({
|
|
|
24887
25064
|
linkFilters: "/guides/read-and-write/read-and-filter.md#filter-rows-by-a-link",
|
|
24888
25065
|
vocabulary: "/guides/database-objects/relations.md#take-allowed-values-from-another-table",
|
|
24889
25066
|
tree: "/guides/database-objects/relations.md#build-a-tree-of-rows-with-a-parent-link",
|
|
25067
|
+
acyclic: "/guides/database-objects/relations.md#keep-dependencies-free-of-cycles-with-acyclic",
|
|
25068
|
+
instructions: "/guides/database-objects/tables.md#tell-agents-how-to-fill-a-row-with-instructions",
|
|
24890
25069
|
checkLinks: "/guides/data-quality/check-constraints.md#write-a-check-rule-that-follows-links",
|
|
24891
25070
|
linkTargets: "/guides/database-objects/relations.md#limit-link-targets-with-ref_by-and-ref_where",
|
|
24892
25071
|
inverse: "/guides/database-objects/relations.md#repair-two-way-links-with-align_relations",
|
|
@@ -25021,13 +25200,18 @@ var init_hints = __esm({
|
|
|
25021
25200
|
unknown_column: guide("Write only the table's columns: describe_table lists them. To keep a new front matter key, add_column first.", "describeTable"),
|
|
25022
25201
|
check: guide("The row breaks a CHECK constraint of the table (named in the message, with its rule): change the values so the rule holds. describe_table lists the table's constraints.", "check"),
|
|
25023
25202
|
generated: guide("A generated column is computed by the engine: do not write it; recompute_columns sets it again.", "generated"),
|
|
25024
|
-
cycle: guide("A row cannot be its own ancestor:
|
|
25203
|
+
cycle: guide("A row cannot be its own ancestor in a hierarchy column, nor depend on itself through an acyclic column: the message shows the path. Point the column to a row that is not on that path.", "tree"),
|
|
25025
25204
|
inverse: guide("Both sides of a two-way link must agree: write one side, or run align_relations to repair them.", "inverse"),
|
|
25026
25205
|
unreadable: guide(
|
|
25027
25206
|
"The note's front matter is not valid YAML (the message quotes the parser), so every read leaves the row out: open the note and fix the YAML, such as a quote or bracket left open or a line without `key: value`. read_note shows its text.",
|
|
25028
25207
|
"unreadable"
|
|
25029
25208
|
)
|
|
25030
25209
|
};
|
|
25210
|
+
ACYCLIC_CYCLE = /^(would close|is on) a cycle in "/;
|
|
25211
|
+
ACYCLIC_GUIDANCE = guide(
|
|
25212
|
+
"A row cannot depend on itself through an acyclic column: the message shows the cycle. Remove one of its links, or link to a row that is not on it; check_table lists the cycles already there.",
|
|
25213
|
+
"acyclic"
|
|
25214
|
+
);
|
|
25031
25215
|
CONFLICTS = [
|
|
25032
25216
|
[/^row changed: expected/, (op) => guide(`The row changed since you read it: read it again (select_rows), then retry ${op} with "expect" set to what you read.`, "expect")],
|
|
25033
25217
|
[/^"where" matched \d+ rows, expected \d+/, () => guide(`Check the rows with select_rows and the same "where", then narrow it or change expect_count.`, "updateRows")],
|
|
@@ -25539,17 +25723,17 @@ function parseColumn(raw, index, reserved = /* @__PURE__ */ new Set()) {
|
|
|
25539
25723
|
`"type" must be one of: ${[...SCALAR_COLUMN_TYPES, "list"].join(", ")}`
|
|
25540
25724
|
);
|
|
25541
25725
|
}
|
|
25542
|
-
let
|
|
25726
|
+
let items2;
|
|
25543
25727
|
if (type === "list") {
|
|
25544
25728
|
const it = entry.items ?? "string";
|
|
25545
25729
|
if (!isScalarType(it)) {
|
|
25546
25730
|
throw new MalformedColumnError(index, `"items" must be a scalar column type`);
|
|
25547
25731
|
}
|
|
25548
|
-
|
|
25732
|
+
items2 = it;
|
|
25549
25733
|
} else if (entry.items !== void 0 && entry.items !== null) {
|
|
25550
25734
|
throw new MalformedColumnError(index, `"items" is only valid for list columns`);
|
|
25551
25735
|
}
|
|
25552
|
-
const effective =
|
|
25736
|
+
const effective = items2 ?? type;
|
|
25553
25737
|
const required2 = entry.required ?? false;
|
|
25554
25738
|
if (typeof required2 !== "boolean") {
|
|
25555
25739
|
throw new MalformedColumnError(index, `"required" must be true or false`);
|
|
@@ -25596,7 +25780,7 @@ function parseColumn(raw, index, reserved = /* @__PURE__ */ new Set()) {
|
|
|
25596
25780
|
const spec = {
|
|
25597
25781
|
name,
|
|
25598
25782
|
type,
|
|
25599
|
-
...
|
|
25783
|
+
...items2 !== void 0 ? { items: items2 } : {},
|
|
25600
25784
|
required: required2,
|
|
25601
25785
|
...min !== void 0 ? { min } : {},
|
|
25602
25786
|
...max !== void 0 ? { max } : {},
|
|
@@ -25651,6 +25835,24 @@ function parseColumn(raw, index, reserved = /* @__PURE__ */ new Set()) {
|
|
|
25651
25835
|
if (effective !== "link" || !ref2) throw new MalformedColumnError(index, `"inverse" needs a link column (or list of links) with "ref"`);
|
|
25652
25836
|
spec.inverse = entry.inverse.trim();
|
|
25653
25837
|
}
|
|
25838
|
+
if (entry.acyclic !== void 0 && entry.acyclic !== null) {
|
|
25839
|
+
if (typeof entry.acyclic !== "boolean") throw new MalformedColumnError(index, `"acyclic" must be true or false`, guide("Set acyclic: true to refuse writes that close a cycle, or leave it out.", "acyclic"));
|
|
25840
|
+
if (entry.acyclic && (effective !== "link" || !ref2)) {
|
|
25841
|
+
throw new MalformedColumnError(
|
|
25842
|
+
index,
|
|
25843
|
+
`"acyclic" needs a link column (or list of links) with "ref" to its own table`,
|
|
25844
|
+
guide('Use acyclic on a link column with ref: "self", such as tasks blocked by tasks.', "acyclic")
|
|
25845
|
+
);
|
|
25846
|
+
}
|
|
25847
|
+
if (entry.acyclic && spec.inverse === name) {
|
|
25848
|
+
throw new MalformedColumnError(
|
|
25849
|
+
index,
|
|
25850
|
+
`"acyclic" cannot be set on a column that is its own inverse: every link would close a cycle`,
|
|
25851
|
+
guide("Name another column of the table as the inverse, such as blocks for blocked_by, or drop acyclic.", "acyclic")
|
|
25852
|
+
);
|
|
25853
|
+
}
|
|
25854
|
+
if (entry.acyclic) spec.acyclic = true;
|
|
25855
|
+
}
|
|
25654
25856
|
if (entry.vocabulary !== void 0 && entry.vocabulary !== null) {
|
|
25655
25857
|
if (typeof entry.vocabulary !== "string" || entry.vocabulary.trim() === "") {
|
|
25656
25858
|
throw new MalformedColumnError(index, `"vocabulary" must be a table name`);
|
|
@@ -25807,12 +26009,14 @@ var init_table_loader = __esm({
|
|
|
25807
26009
|
init_types_table();
|
|
25808
26010
|
init_validate();
|
|
25809
26011
|
init_message();
|
|
26012
|
+
init_hints();
|
|
25810
26013
|
init_db_paths();
|
|
25811
26014
|
MalformedColumnError = class extends Error {
|
|
25812
|
-
constructor(index, message) {
|
|
26015
|
+
constructor(index, message, guidance) {
|
|
25813
26016
|
super(`columns[${index}]: ${message}`);
|
|
25814
26017
|
this.index = index;
|
|
25815
26018
|
this.name = "MalformedColumnError";
|
|
26019
|
+
if (guidance) Object.assign(this, guidance);
|
|
25816
26020
|
}
|
|
25817
26021
|
};
|
|
25818
26022
|
MalformedTableOptionsError = class extends Error {
|
|
@@ -25843,6 +26047,7 @@ var init_table_loader = __esm({
|
|
|
25843
26047
|
"generated",
|
|
25844
26048
|
"identity",
|
|
25845
26049
|
"hierarchy",
|
|
26050
|
+
"acyclic",
|
|
25846
26051
|
"vocabulary",
|
|
25847
26052
|
"inverse",
|
|
25848
26053
|
"ref_where",
|
|
@@ -26040,6 +26245,19 @@ function tableTags(entry) {
|
|
|
26040
26245
|
const pairs = isRecord(tags) ? Object.entries(tags).map(([k, v]) => [k, text5(v)]) : (Array.isArray(tags) ? tags : [tags]).map((k) => [text5(k).trim(), ""]).filter(([k]) => k !== "");
|
|
26041
26246
|
return pairs.length === 0 ? void 0 : Object.fromEntries(pairs);
|
|
26042
26247
|
}
|
|
26248
|
+
function constraintHints(entry) {
|
|
26249
|
+
const out = {};
|
|
26250
|
+
const raw = entry.constraint_hints;
|
|
26251
|
+
if (!isRecord(raw)) return out;
|
|
26252
|
+
const checks = entry.constraints ?? {};
|
|
26253
|
+
for (const [name, hint] of Object.entries(raw)) {
|
|
26254
|
+
if (typeof hint === "string" && hint.trim() !== "" && Object.prototype.hasOwnProperty.call(checks, name)) out[name] = hint.trim();
|
|
26255
|
+
}
|
|
26256
|
+
return out;
|
|
26257
|
+
}
|
|
26258
|
+
function tableInstructions(entry) {
|
|
26259
|
+
return typeof entry.instructions === "string" && entry.instructions.trim() !== "" ? entry.instructions : void 0;
|
|
26260
|
+
}
|
|
26043
26261
|
function withTableTags(entry, tags) {
|
|
26044
26262
|
const { tags: _old, ...rest } = entry;
|
|
26045
26263
|
const out = {};
|
|
@@ -27304,12 +27522,12 @@ async function appendDatabaseMove(app, move) {
|
|
|
27304
27522
|
`);
|
|
27305
27523
|
CACHE2.delete(app);
|
|
27306
27524
|
}
|
|
27307
|
-
async function eachLimit(
|
|
27525
|
+
async function eachLimit(items2, limit, fn) {
|
|
27308
27526
|
let next = 0;
|
|
27309
27527
|
const worker = async () => {
|
|
27310
|
-
while (next <
|
|
27528
|
+
while (next < items2.length) await fn(items2[next++]);
|
|
27311
27529
|
};
|
|
27312
|
-
await Promise.all(Array.from({ length: Math.min(limit,
|
|
27530
|
+
await Promise.all(Array.from({ length: Math.min(limit, items2.length) }, worker));
|
|
27313
27531
|
}
|
|
27314
27532
|
function moveLinks(text5, from, to, entries = []) {
|
|
27315
27533
|
const prefix = (t) => t === "" ? "" : `${t}/`;
|
|
@@ -27766,9 +27984,9 @@ function buildInverseSpecs(model) {
|
|
|
27766
27984
|
return out;
|
|
27767
27985
|
}
|
|
27768
27986
|
function linkTargets(app, value, source) {
|
|
27769
|
-
const
|
|
27987
|
+
const items2 = Array.isArray(value) ? value : value === null || value === void 0 ? [] : [value];
|
|
27770
27988
|
const out = [];
|
|
27771
|
-
for (const v of
|
|
27989
|
+
for (const v of items2) {
|
|
27772
27990
|
const m = typeof v === "string" ? LINK_RE.exec(v.trim()) : null;
|
|
27773
27991
|
if (!m) continue;
|
|
27774
27992
|
const dest = app.metadataCache.getFirstLinkpathDest(m[1].trim(), source)?.path;
|
|
@@ -29509,22 +29727,22 @@ async function storeFilesSince(app, moves) {
|
|
|
29509
29727
|
function atOnceFor(count2) {
|
|
29510
29728
|
return count2 >= WRITE_CONCURRENCY.from ? WRITE_CONCURRENCY.atOnce : 1;
|
|
29511
29729
|
}
|
|
29512
|
-
async function inOrder(
|
|
29513
|
-
const results = new Array(
|
|
29730
|
+
async function inOrder(items2, pathOf, fn, limit = atOnceFor(items2.length)) {
|
|
29731
|
+
const results = new Array(items2.length);
|
|
29514
29732
|
let next = 0;
|
|
29515
29733
|
let stop = false;
|
|
29516
29734
|
const worker = async () => {
|
|
29517
|
-
while (!stop && next <
|
|
29735
|
+
while (!stop && next < items2.length) {
|
|
29518
29736
|
const i = next++;
|
|
29519
29737
|
try {
|
|
29520
|
-
results[i] = { ok: true, written: await fn(
|
|
29738
|
+
results[i] = { ok: true, written: await fn(items2[i]) };
|
|
29521
29739
|
} catch (e) {
|
|
29522
29740
|
results[i] = { ok: false, error: messageOf(e) };
|
|
29523
29741
|
stop = true;
|
|
29524
29742
|
}
|
|
29525
29743
|
}
|
|
29526
29744
|
};
|
|
29527
|
-
await Promise.all(Array.from({ length: Math.min(limit,
|
|
29745
|
+
await Promise.all(Array.from({ length: Math.min(limit, items2.length) }, worker));
|
|
29528
29746
|
const first2 = results.findIndex((r) => r !== void 0 && !r.ok);
|
|
29529
29747
|
const kept2 = /* @__PURE__ */ new Set();
|
|
29530
29748
|
if (first2 >= 0) {
|
|
@@ -29543,7 +29761,7 @@ async function inOrder(items, pathOf, fn, limit = atOnceFor(items.length)) {
|
|
|
29543
29761
|
if (r?.ok && (first2 < 0 || i < first2 || kept2.has(i))) done.push(r.written.value);
|
|
29544
29762
|
});
|
|
29545
29763
|
const f = first2 >= 0 ? results[first2] : null;
|
|
29546
|
-
return { done, failed: f ? { path: pathOf(
|
|
29764
|
+
return { done, failed: f ? { path: pathOf(items2[first2]), error: f.error } : null };
|
|
29547
29765
|
}
|
|
29548
29766
|
async function moveFile(app, from, to) {
|
|
29549
29767
|
if (inStore(from)) return storeRename(app, from, to);
|
|
@@ -31269,10 +31487,10 @@ function equalTo(e) {
|
|
|
31269
31487
|
if (typeof e === "string") return (a) => typeof a === "string" ? a === e : JSON.stringify(a) === json3;
|
|
31270
31488
|
return (a) => JSON.stringify(a) === json3;
|
|
31271
31489
|
}
|
|
31272
|
-
function memberOf(
|
|
31490
|
+
function memberOf(items2) {
|
|
31273
31491
|
const strings2 = /* @__PURE__ */ new Set();
|
|
31274
31492
|
const json3 = /* @__PURE__ */ new Set();
|
|
31275
|
-
for (const i of
|
|
31493
|
+
for (const i of items2) {
|
|
31276
31494
|
if (typeof i === "string") strings2.add(i);
|
|
31277
31495
|
json3.add(JSON.stringify(i));
|
|
31278
31496
|
}
|
|
@@ -31739,14 +31957,14 @@ var init_check_links = __esm({
|
|
|
31739
31957
|
if (!via) throw new OperationInputError(`where "${col}": "${head}" is not a link column with ref`);
|
|
31740
31958
|
const key2 = `${t.catalog.ref.full}|${via.ref}`;
|
|
31741
31959
|
const target = this.tables.get(key2);
|
|
31742
|
-
const
|
|
31743
|
-
if (!target || !
|
|
31960
|
+
const byPath3 = target ? this.rows.get(target.catalog.ref.full) : void 0;
|
|
31961
|
+
if (!target || !byPath3) throw new OperationInputError(this.missing.get(key2) ?? `CHECK links not loaded for "${col}"`);
|
|
31744
31962
|
const pred = compileWhere({ [col.slice(dot2 + 1)]: cond }, target, this.settings, rowGetter(null, target, this.settings), this);
|
|
31745
31963
|
return (row) => {
|
|
31746
31964
|
const v = fmGet(row.ordered, head);
|
|
31747
31965
|
const paths = (Array.isArray(v) ? v : [v]).filter((x) => !isEmptyValue(x)).map((x) => this.resolve(x, row.file.path));
|
|
31748
31966
|
return paths.length > 0 && paths.every((p) => {
|
|
31749
|
-
const r = p == null ? void 0 :
|
|
31967
|
+
const r = p == null ? void 0 : byPath3.get(p);
|
|
31750
31968
|
return r !== void 0 && pred(r);
|
|
31751
31969
|
});
|
|
31752
31970
|
};
|
|
@@ -31989,8 +32207,8 @@ function findRow(rows, ref2, table) {
|
|
|
31989
32207
|
const given = ref2.trim();
|
|
31990
32208
|
const want = (parseWikilink(given) ?? given).replace(/^\/+/, "").replace(/\.md$/i, "");
|
|
31991
32209
|
const stem2 = (r) => r.file.path.replace(/\.md$/i, "");
|
|
31992
|
-
const
|
|
31993
|
-
if (
|
|
32210
|
+
const byPath3 = rows.find((r) => r.file.path === given || stem2(r) === want);
|
|
32211
|
+
if (byPath3) return byPath3;
|
|
31994
32212
|
const hits = want.includes("/") ? rows.filter((r) => stem2(r).endsWith(`/${want}`)) : rows.filter((r) => basenameOf(r.file.path) === want);
|
|
31995
32213
|
if (hits.length > 1) {
|
|
31996
32214
|
throw new OperationInputError(
|
|
@@ -32179,6 +32397,8 @@ async function linkedCheckViolationsImpl(app, settings, cs, consequential = /* @
|
|
|
32179
32397
|
const s = await tableIn(app, settings, metastore, ref2.full);
|
|
32180
32398
|
for (const [name, where] of Object.entries(s.catalog.entry.constraints)) {
|
|
32181
32399
|
if (!followsLinks2(where)) continue;
|
|
32400
|
+
const checkHint = constraintHints(s.catalog.entry)[name];
|
|
32401
|
+
const ownHint = checkHint ? { hint: checkHint } : {};
|
|
32182
32402
|
await after.prepare(s, where);
|
|
32183
32403
|
const rows = after.rowsOf(s);
|
|
32184
32404
|
const restored = renewed.has(`${ref2.full}|CHECK ${name}`);
|
|
@@ -32202,7 +32422,7 @@ async function linkedCheckViolationsImpl(app, settings, cs, consequential = /* @
|
|
|
32202
32422
|
if (passes(r)) continue;
|
|
32203
32423
|
const message = `violates CHECK ${name}: ${JSON.stringify(where)}`;
|
|
32204
32424
|
if (own2 === void 0 && restored) {
|
|
32205
|
-
add(r.file.path, { constraint: name, code: "check", message: `${message} (CHECK ${name} comes back with this change)
|
|
32425
|
+
add(r.file.path, { constraint: name, code: "check", message: `${message} (CHECK ${name} comes back with this change)`, ...ownHint });
|
|
32206
32426
|
continue;
|
|
32207
32427
|
}
|
|
32208
32428
|
if (own2 === void 0) {
|
|
@@ -32210,10 +32430,10 @@ async function linkedCheckViolationsImpl(app, settings, cs, consequential = /* @
|
|
|
32210
32430
|
await before.prepare(s, where);
|
|
32211
32431
|
passed = compileCheck(where, s, settings, before);
|
|
32212
32432
|
}
|
|
32213
|
-
if (passed(r)) add(r.file.path, { constraint: name, code: "check", message: `${message}${suffix(r, heads)}
|
|
32433
|
+
if (passed(r)) add(r.file.path, { constraint: name, code: "check", message: `${message}${suffix(r, heads)}`, ...ownHint });
|
|
32214
32434
|
continue;
|
|
32215
32435
|
}
|
|
32216
|
-
add(own2, { constraint: name, code: "check", message: consequential.has(own2) ? `${message}${suffix(r, heads, own2)}` : message });
|
|
32436
|
+
add(own2, { constraint: name, code: "check", message: consequential.has(own2) ? `${message}${suffix(r, heads, own2)}` : message, ...ownHint });
|
|
32217
32437
|
}
|
|
32218
32438
|
}
|
|
32219
32439
|
}
|
|
@@ -32240,17 +32460,177 @@ var init_changeset_checks = __esm({
|
|
|
32240
32460
|
}
|
|
32241
32461
|
});
|
|
32242
32462
|
|
|
32463
|
+
// src/core/acyclic.ts
|
|
32464
|
+
var acyclic_exports = {};
|
|
32465
|
+
__export(acyclic_exports, {
|
|
32466
|
+
acyclicPairs: () => acyclicPairs,
|
|
32467
|
+
acyclicViolations: () => acyclicViolations,
|
|
32468
|
+
changeSetCycles: () => changeSetCycles,
|
|
32469
|
+
cycleThrough: () => cycleThrough
|
|
32470
|
+
});
|
|
32471
|
+
function acyclicPairs(columns, table) {
|
|
32472
|
+
const target = (c) => c.ref === "self" ? table : c.ref;
|
|
32473
|
+
return columns.filter((c) => c.acyclic === true).map((c) => {
|
|
32474
|
+
const declared = c.inverse !== void 0 && c.inverse !== c.name ? c.inverse : void 0;
|
|
32475
|
+
const back = declared ?? columns.find((x) => x.name !== c.name && x.inverse === c.name && target(x) === target(c))?.name;
|
|
32476
|
+
return { column: c.name, inverse: back !== void 0 && columns.some((x) => x.name === back) ? back : null };
|
|
32477
|
+
});
|
|
32478
|
+
}
|
|
32479
|
+
function graphOf(pair, rows) {
|
|
32480
|
+
const names2 = new Set(rows.map((r) => basenameOf(r.path)));
|
|
32481
|
+
const out = /* @__PURE__ */ new Map();
|
|
32482
|
+
const add = (from, to) => {
|
|
32483
|
+
if (!names2.has(from) || !names2.has(to)) return;
|
|
32484
|
+
let s = out.get(from);
|
|
32485
|
+
if (!s) out.set(from, s = /* @__PURE__ */ new Set());
|
|
32486
|
+
s.add(to);
|
|
32487
|
+
};
|
|
32488
|
+
for (const r of rows) {
|
|
32489
|
+
const self = basenameOf(r.path);
|
|
32490
|
+
for (const v of items(fmGet(r.ordered, pair.column))) {
|
|
32491
|
+
const to = linkName(v);
|
|
32492
|
+
if (to !== null) add(self, to);
|
|
32493
|
+
}
|
|
32494
|
+
if (pair.inverse !== null) {
|
|
32495
|
+
for (const v of items(fmGet(r.ordered, pair.inverse))) {
|
|
32496
|
+
const from = linkName(v);
|
|
32497
|
+
if (from !== null) add(from, self);
|
|
32498
|
+
}
|
|
32499
|
+
}
|
|
32500
|
+
}
|
|
32501
|
+
return out;
|
|
32502
|
+
}
|
|
32503
|
+
function cycleThrough(graph, start) {
|
|
32504
|
+
const prev = /* @__PURE__ */ new Map();
|
|
32505
|
+
const seen = /* @__PURE__ */ new Set([start]);
|
|
32506
|
+
const queue = [start];
|
|
32507
|
+
while (queue.length > 0) {
|
|
32508
|
+
const u = queue.shift();
|
|
32509
|
+
for (const v of [...graph.get(u) ?? []].sort()) {
|
|
32510
|
+
if (v === start) {
|
|
32511
|
+
const chain = [u];
|
|
32512
|
+
while (chain[chain.length - 1] !== start) chain.push(prev.get(chain[chain.length - 1]));
|
|
32513
|
+
return [...chain.reverse(), start];
|
|
32514
|
+
}
|
|
32515
|
+
if (!seen.has(v)) {
|
|
32516
|
+
seen.add(v);
|
|
32517
|
+
prev.set(v, u);
|
|
32518
|
+
queue.push(v);
|
|
32519
|
+
}
|
|
32520
|
+
}
|
|
32521
|
+
}
|
|
32522
|
+
return null;
|
|
32523
|
+
}
|
|
32524
|
+
function acyclicViolations(columns, table, rows, opts) {
|
|
32525
|
+
const pairs = acyclicPairs(columns, table).filter((p) => opts.involving === void 0 || p.column === opts.involving || p.inverse === opts.involving);
|
|
32526
|
+
const out = /* @__PURE__ */ new Map();
|
|
32527
|
+
const head = opts.wording === "write" ? "would close a cycle in" : "is on a cycle in";
|
|
32528
|
+
for (const pair of pairs) {
|
|
32529
|
+
const after = graphOf(pair, rows);
|
|
32530
|
+
const before = opts.before ? graphOf(pair, opts.before) : null;
|
|
32531
|
+
for (const r of [...rows].sort(byPath2)) {
|
|
32532
|
+
if (opts.only && !opts.only.has(r.path)) continue;
|
|
32533
|
+
const name = basenameOf(r.path);
|
|
32534
|
+
const cycle = cycleThrough(after, name);
|
|
32535
|
+
if (cycle === null || before !== null && cycleThrough(before, name) !== null) continue;
|
|
32536
|
+
const v = { column: pair.column, code: "cycle", message: `${head} "${pair.column}" (${cycle.join(" \u2192 ")})` };
|
|
32537
|
+
out.set(r.path, [...out.get(r.path) ?? [], v]);
|
|
32538
|
+
}
|
|
32539
|
+
}
|
|
32540
|
+
return [...out].map(([path19, violations]) => ({ path: path19, violations })).sort(byPath2);
|
|
32541
|
+
}
|
|
32542
|
+
function acyclicTables(model) {
|
|
32543
|
+
let out = ACYCLIC_TABLES.get(model);
|
|
32544
|
+
if (!out) {
|
|
32545
|
+
const set = /* @__PURE__ */ new Set();
|
|
32546
|
+
const has = (cols) => cols.some((c) => c.acyclic === true);
|
|
32547
|
+
for (const { ref: ref2, entry } of catalogTables(model)) {
|
|
32548
|
+
const bases = baseChain(model.bases, entry.bases ?? []);
|
|
32549
|
+
if (has(entry.columns) || bases.some((b) => has(model.bases[b].columns))) set.add(ref2.full);
|
|
32550
|
+
}
|
|
32551
|
+
ACYCLIC_TABLES.set(model, out = set);
|
|
32552
|
+
}
|
|
32553
|
+
return out;
|
|
32554
|
+
}
|
|
32555
|
+
async function changeSetCycles(app, settings, cs) {
|
|
32556
|
+
if (cs.texts.some((t) => t.path === metastorePath(settings))) return [];
|
|
32557
|
+
const model = cachedMetastore(app, settings) ?? (await loadMetastore(app, settings)).model;
|
|
32558
|
+
const tables = acyclicTables(model);
|
|
32559
|
+
if (tables.size === 0) return [];
|
|
32560
|
+
const keep = /* @__PURE__ */ new Set([settings.tableKey]);
|
|
32561
|
+
const tableOf = (o) => rowTableFull(model, fmGet(o, settings.tableKey));
|
|
32562
|
+
const moved = new Map(cs.moves.map((m) => [m.from, m.to]));
|
|
32563
|
+
const created = cs.creates.map((c) => ({ path: c.path, ordered: readOrderedFromMarkdown(c.content, keep).ordered }));
|
|
32564
|
+
const touched = /* @__PURE__ */ new Map();
|
|
32565
|
+
const note = (full, x) => {
|
|
32566
|
+
if (full === null || !tables.has(full)) return;
|
|
32567
|
+
touched.set(full, [...touched.get(full) ?? [], x]);
|
|
32568
|
+
};
|
|
32569
|
+
for (const e of cs.edits) note(tableOf(e.after), { path: e.path, final: moved.get(e.path) ?? e.path, before: e.before, after: e.after });
|
|
32570
|
+
for (const c of created) note(tableOf(c.ordered), { path: c.path, final: c.path, before: null, after: c.ordered });
|
|
32571
|
+
if (touched.size === 0) return [];
|
|
32572
|
+
return phase("engine.checks", async () => {
|
|
32573
|
+
const out = [];
|
|
32574
|
+
for (const [full, list2] of [...touched].sort(([a], [b]) => a < b ? -1 : 1)) {
|
|
32575
|
+
const t = await loadTable(app, settings, full);
|
|
32576
|
+
const pairs = acyclicPairs(t.def.columns, full);
|
|
32577
|
+
const cols = pairs.flatMap((p) => p.inverse === null ? [p.column] : [p.column, p.inverse]);
|
|
32578
|
+
const value = (o, c) => JSON.stringify(o === null ? null : fmGet(o, c) ?? null);
|
|
32579
|
+
if (!list2.some((x) => cols.some((c) => value(x.before, c) !== value(x.after, c)))) continue;
|
|
32580
|
+
const before = (await loadRows(app, settings, t)).map((r) => ({ path: r.file.path, ordered: r.ordered }));
|
|
32581
|
+
const after = new Map(before.map((r) => [r.path, r.ordered]));
|
|
32582
|
+
for (const e of cs.edits) {
|
|
32583
|
+
if (tableOf(e.after) === full) after.set(e.path, e.after);
|
|
32584
|
+
else after.delete(e.path);
|
|
32585
|
+
}
|
|
32586
|
+
const archive = `${t.def.layout.archive}/`;
|
|
32587
|
+
for (const m of cs.moves) {
|
|
32588
|
+
const o = after.get(m.from);
|
|
32589
|
+
if (o === void 0) continue;
|
|
32590
|
+
after.delete(m.from);
|
|
32591
|
+
if (!m.to.startsWith(archive)) after.set(m.to, o);
|
|
32592
|
+
}
|
|
32593
|
+
for (const p of cs.deletes) after.delete(p);
|
|
32594
|
+
for (const c of created) if (tableOf(c.ordered) === full) after.set(c.path, c.ordered);
|
|
32595
|
+
const reportAs = new Map(list2.filter((x) => after.has(x.final)).map((x) => [x.final, x.path]));
|
|
32596
|
+
const found = acyclicViolations(t.def.columns, full, [...after].map(([path19, ordered]) => ({ path: path19, ordered })), {
|
|
32597
|
+
only: new Set(reportAs.keys()),
|
|
32598
|
+
before,
|
|
32599
|
+
wording: "write"
|
|
32600
|
+
});
|
|
32601
|
+
for (const v of found) out.push({ path: reportAs.get(v.path), violations: v.violations });
|
|
32602
|
+
}
|
|
32603
|
+
return out;
|
|
32604
|
+
}, { "datanotes.checks.kind": "acyclic" });
|
|
32605
|
+
}
|
|
32606
|
+
var items, byPath2, ACYCLIC_TABLES;
|
|
32607
|
+
var init_acyclic = __esm({
|
|
32608
|
+
"src/core/acyclic.ts"() {
|
|
32609
|
+
"use strict";
|
|
32610
|
+
init_engine();
|
|
32611
|
+
init_frontmatter();
|
|
32612
|
+
init_metastore();
|
|
32613
|
+
init_path_templates();
|
|
32614
|
+
init_tracing();
|
|
32615
|
+
init_where();
|
|
32616
|
+
items = (v) => Array.isArray(v) ? v : v === null || v === void 0 ? [] : [v];
|
|
32617
|
+
byPath2 = (a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0;
|
|
32618
|
+
ACYCLIC_TABLES = /* @__PURE__ */ new WeakMap();
|
|
32619
|
+
}
|
|
32620
|
+
});
|
|
32621
|
+
|
|
32243
32622
|
// src/core/row-checks.ts
|
|
32244
32623
|
function constraintViolationsImpl(t, settings, path19, ordered, links) {
|
|
32245
32624
|
const raw = t.catalog.entry.constraints;
|
|
32246
32625
|
if (!raw || typeof raw !== "object") return [];
|
|
32247
32626
|
const out = [];
|
|
32627
|
+
const hints = constraintHints(t.catalog.entry);
|
|
32248
32628
|
for (const [name, where] of Object.entries(raw)) {
|
|
32249
32629
|
if (!where || typeof where !== "object" || Array.isArray(where)) continue;
|
|
32250
32630
|
if (!links && followsLinks2(where)) continue;
|
|
32251
32631
|
try {
|
|
32252
32632
|
if (!compileCheck(where, t, settings, links)({ file: { path: path19 }, ordered })) {
|
|
32253
|
-
out.push({ constraint: name, code: "check", message: `violates CHECK ${name}: ${JSON.stringify(where)}
|
|
32633
|
+
out.push({ constraint: name, code: "check", message: `violates CHECK ${name}: ${JSON.stringify(where)}`, ...hints[name] ? { hint: hints[name] } : {} });
|
|
32254
32634
|
}
|
|
32255
32635
|
} catch (e) {
|
|
32256
32636
|
out.push({ constraint: name, code: "check", message: `CHECK ${name} is invalid: ${messageOf(e)}` });
|
|
@@ -32289,14 +32669,14 @@ function checkViolation(v) {
|
|
|
32289
32669
|
async function checkOne(app, settings, table, everyUnreadable) {
|
|
32290
32670
|
const t = await loadTable(app, settings, table);
|
|
32291
32671
|
const violations = [];
|
|
32292
|
-
const
|
|
32672
|
+
const byPath3 = /* @__PURE__ */ new Map();
|
|
32293
32673
|
const report = (path19, v) => {
|
|
32294
|
-
const existing =
|
|
32674
|
+
const existing = byPath3.get(path19);
|
|
32295
32675
|
if (existing) existing.violations.push(...v);
|
|
32296
32676
|
else {
|
|
32297
32677
|
const row = { path: path19, violations: v };
|
|
32298
32678
|
violations.push(row);
|
|
32299
|
-
|
|
32679
|
+
byPath3.set(path19, row);
|
|
32300
32680
|
}
|
|
32301
32681
|
};
|
|
32302
32682
|
const links = new CheckLinks(app, settings);
|
|
@@ -32321,6 +32701,7 @@ async function checkOne(app, settings, table, everyUnreadable) {
|
|
|
32321
32701
|
const back = await missingBackLinks(app, settings, t.catalog.model, t.catalog.ref.full, rows.map((r) => ({ path: r.file.path, ordered: r.ordered })));
|
|
32322
32702
|
for (const [path19, list2] of back) report(path19, list2.map((x) => ({ column: x.column, code: "inverse", message: x.message, value: x.value })));
|
|
32323
32703
|
for (const h of await hierarchyViolations(app, settings, t, rows.map((r) => ({ path: r.file.path, ordered: r.ordered })), rows)) report(h.path, h.violations);
|
|
32704
|
+
for (const a of acyclicViolations(t.def.columns, t.catalog.ref.full, rows.map((r) => ({ path: r.file.path, ordered: r.ordered })), { wording: "check" })) report(a.path, a.violations);
|
|
32324
32705
|
const unreadable = everyUnreadable && everyUnreadable.model === t.catalog.model ? everyUnreadable.rows.filter((u) => u.table === t.catalog.ref.full) : await unreadableRows(app, settings, t.catalog.model, t.catalog.ref.full);
|
|
32325
32706
|
for (const u of unreadable) violations.push({ path: u.path, violations: [{ code: "unreadable", message: unreadableMessage(u.error) }] });
|
|
32326
32707
|
return { table: t.def.name, rows: rows.length + unreadable.length, violations };
|
|
@@ -32393,6 +32774,7 @@ var init_row_checks = __esm({
|
|
|
32393
32774
|
init_check_links();
|
|
32394
32775
|
init_link_targets();
|
|
32395
32776
|
init_message();
|
|
32777
|
+
init_acyclic();
|
|
32396
32778
|
init_unreadable();
|
|
32397
32779
|
init_tracing();
|
|
32398
32780
|
CHECK_LIMIT = 500;
|
|
@@ -32459,7 +32841,7 @@ async function ownViolations(app, settings, t, rows, links) {
|
|
|
32459
32841
|
const targetChecks = [];
|
|
32460
32842
|
for (const c of filteredLinkColumns(t)) targetChecks.push(await linkTargetCheck(t, settings, links, c));
|
|
32461
32843
|
const computed = computedColumnNames(t);
|
|
32462
|
-
const whole = t.def.columns.some((c) => c.unique && !computed.has(c.name) || c.hierarchy);
|
|
32844
|
+
const whole = t.def.columns.some((c) => c.unique && !computed.has(c.name) || c.hierarchy || c.acyclic === true);
|
|
32463
32845
|
if (whole) await links.prepare(t, null);
|
|
32464
32846
|
const all = whole ? links.rowsOf(t) : [];
|
|
32465
32847
|
const own2 = new Set(rows.map((r) => r.file.path));
|
|
@@ -32467,6 +32849,7 @@ async function ownViolations(app, settings, t, rows, links) {
|
|
|
32467
32849
|
uniqueViolations(t.def.columns, all.map((r) => ({ path: r.file.path, ordered: r.ordered }))).filter((u) => own2.has(u.path)).map((u) => [u.path, u.violations])
|
|
32468
32850
|
);
|
|
32469
32851
|
const cycles = whole ? await hierarchyViolations(app, settings, t, rows.map((r) => ({ path: r.file.path, ordered: r.ordered })), all) : [];
|
|
32852
|
+
const loops = whole ? acyclicViolations(t.def.columns, t.catalog.ref.full, all.map((r) => ({ path: r.file.path, ordered: r.ordered })), { only: own2, wording: "check" }) : [];
|
|
32470
32853
|
const out = /* @__PURE__ */ new Map();
|
|
32471
32854
|
for (const r of rows) {
|
|
32472
32855
|
const path19 = r.file.path;
|
|
@@ -32475,17 +32858,18 @@ async function ownViolations(app, settings, t, rows, links) {
|
|
|
32475
32858
|
...unique.get(path19) ?? [],
|
|
32476
32859
|
...constraintViolations(t, settings, path19, r.ordered, links),
|
|
32477
32860
|
...targetChecks.flatMap((check) => check(r)),
|
|
32478
|
-
...cycles.filter((c) => c.path === path19).flatMap((c) => c.violations)
|
|
32861
|
+
...cycles.filter((c) => c.path === path19).flatMap((c) => c.violations),
|
|
32862
|
+
...loops.filter((c) => c.path === path19).flatMap((c) => c.violations)
|
|
32479
32863
|
];
|
|
32480
32864
|
out.set(path19, v.filter((x) => x.code === "check" || !computed.has(x.column)));
|
|
32481
32865
|
}
|
|
32482
32866
|
return out;
|
|
32483
32867
|
}
|
|
32484
32868
|
async function checkExternalEdits(app, settings, input) {
|
|
32485
|
-
const
|
|
32869
|
+
const byPath3 = /* @__PURE__ */ new Map();
|
|
32486
32870
|
const tableOf = /* @__PURE__ */ new Map();
|
|
32487
32871
|
const model = input.length > 0 ? (await loadMetastore(app, settings))?.model : void 0;
|
|
32488
|
-
if (!model) return { byPath:
|
|
32872
|
+
if (!model) return { byPath: byPath3, loaded: [], tableOf };
|
|
32489
32873
|
const tp = settings.tableKey;
|
|
32490
32874
|
const edits = /* @__PURE__ */ new Map();
|
|
32491
32875
|
for (const e of input) {
|
|
@@ -32553,15 +32937,15 @@ async function checkExternalEdits(app, settings, input) {
|
|
|
32553
32937
|
}
|
|
32554
32938
|
const add = (at, v, full) => {
|
|
32555
32939
|
if (!v) return;
|
|
32556
|
-
|
|
32940
|
+
byPath3.set(at, [...byPath3.get(at), v]);
|
|
32557
32941
|
tableOf.set(v.path, full);
|
|
32558
32942
|
};
|
|
32559
32943
|
const byTable = /* @__PURE__ */ new Map();
|
|
32560
32944
|
for (const [path19, { row, full }] of now) {
|
|
32561
32945
|
byTable.set(full, [...byTable.get(full) ?? [], row]);
|
|
32562
|
-
|
|
32946
|
+
byPath3.set(path19, []);
|
|
32563
32947
|
}
|
|
32564
|
-
for (const e of edits.values()) if (!now.has(e.path) && gone.has(e.oldPath ?? e.path))
|
|
32948
|
+
for (const e of edits.values()) if (!now.has(e.path) && gone.has(e.oldPath ?? e.path)) byPath3.set(e.path, []);
|
|
32565
32949
|
for (const [full, rows] of byTable) {
|
|
32566
32950
|
const t = await table(full);
|
|
32567
32951
|
const found = await ownViolations(app, settings, t, rows, after);
|
|
@@ -32687,7 +33071,7 @@ async function checkExternalEdits(app, settings, input) {
|
|
|
32687
33071
|
}
|
|
32688
33072
|
}
|
|
32689
33073
|
const loaded = /* @__PURE__ */ new Set([...after.loadedTables(), ...before?.loadedTables() ?? []]);
|
|
32690
|
-
return { byPath:
|
|
33074
|
+
return { byPath: byPath3, loaded: [...loaded].sort(), tableOf };
|
|
32691
33075
|
}
|
|
32692
33076
|
async function checkChangedTables(app, settings, tables) {
|
|
32693
33077
|
const byTable = /* @__PURE__ */ new Map();
|
|
@@ -32721,6 +33105,7 @@ var init_external_edits = __esm({
|
|
|
32721
33105
|
init_check_links();
|
|
32722
33106
|
init_link_targets();
|
|
32723
33107
|
init_row_checks();
|
|
33108
|
+
init_acyclic();
|
|
32724
33109
|
init_message();
|
|
32725
33110
|
}
|
|
32726
33111
|
});
|
|
@@ -32844,7 +33229,7 @@ async function rowsInVaultOrder(app, settings, t, keep, bodies) {
|
|
|
32844
33229
|
return out.sort((a, b) => a.file.path.localeCompare(b.file.path));
|
|
32845
33230
|
}
|
|
32846
33231
|
function uniqueViolations(columns, rows) {
|
|
32847
|
-
const
|
|
33232
|
+
const byPath3 = /* @__PURE__ */ new Map();
|
|
32848
33233
|
const rowOf = /* @__PURE__ */ new Map();
|
|
32849
33234
|
for (const r of rows) if (!rowOf.has(r.path)) rowOf.set(r.path, r);
|
|
32850
33235
|
for (const col of columns.filter((c) => c.unique)) {
|
|
@@ -32860,13 +33245,13 @@ function uniqueViolations(columns, rows) {
|
|
|
32860
33245
|
if (paths.length < 2) continue;
|
|
32861
33246
|
for (const p of paths) {
|
|
32862
33247
|
const others = paths.filter((x) => x !== p).join(", ");
|
|
32863
|
-
let list2 =
|
|
32864
|
-
if (!list2)
|
|
33248
|
+
let list2 = byPath3.get(p);
|
|
33249
|
+
if (!list2) byPath3.set(p, list2 = []);
|
|
32865
33250
|
list2.push({ column: col.name, code: "unique", message: `must be unique (also used by ${others})`, value: fmGet(rowOf.get(p).ordered, col.name) });
|
|
32866
33251
|
}
|
|
32867
33252
|
}
|
|
32868
33253
|
}
|
|
32869
|
-
return [...
|
|
33254
|
+
return [...byPath3.entries()].map(([path19, violations]) => ({ path: path19, violations }));
|
|
32870
33255
|
}
|
|
32871
33256
|
function uniqueKey(v) {
|
|
32872
33257
|
if (isEmptyValue(v)) return null;
|
|
@@ -32893,6 +33278,7 @@ function serializeColumn(c) {
|
|
|
32893
33278
|
if (c.generated !== void 0) out.generated = c.generated;
|
|
32894
33279
|
if (c.identity !== void 0) out.identity = c.identity;
|
|
32895
33280
|
if (c.hierarchy) out.hierarchy = true;
|
|
33281
|
+
if (c.acyclic) out.acyclic = true;
|
|
32896
33282
|
if (c.vocabulary !== void 0) out.vocabulary = c.vocabulary;
|
|
32897
33283
|
if (c.inverse !== void 0) out.inverse = c.inverse;
|
|
32898
33284
|
if (c.ref_where !== void 0) out.ref_where = c.ref_where;
|
|
@@ -32955,6 +33341,8 @@ async function finish(app, settings, cs, conflicts, violations, opts) {
|
|
|
32955
33341
|
const { linkedCheckViolations: linkedCheckViolations2 } = await Promise.resolve().then(() => (init_changeset_checks(), changeset_checks_exports));
|
|
32956
33342
|
violations = [...violations, ...await linkedCheckViolations2(app, settings, cs, mirrored)];
|
|
32957
33343
|
}
|
|
33344
|
+
const { changeSetCycles: changeSetCycles2 } = await Promise.resolve().then(() => (init_acyclic(), acyclic_exports));
|
|
33345
|
+
violations = [...violations, ...await changeSetCycles2(app, settings, cs)];
|
|
32958
33346
|
}
|
|
32959
33347
|
const base = emptyResult(cs.op, dryRun);
|
|
32960
33348
|
base.planned_edits = plannedFrom(cs);
|
|
@@ -33161,12 +33549,12 @@ async function externalViolationCounts(app, settings, changes) {
|
|
|
33161
33549
|
}
|
|
33162
33550
|
const out = /* @__PURE__ */ new Map();
|
|
33163
33551
|
if (edits.length > 0) {
|
|
33164
|
-
const { byPath:
|
|
33552
|
+
const { byPath: byPath3, tableOf } = await checkExternalEdits2(app, settings, edits.map(({ after: _after, ...e }) => e));
|
|
33165
33553
|
const seen = /* @__PURE__ */ new Map();
|
|
33166
33554
|
for (const e of edits) {
|
|
33167
33555
|
for (const full of countsIn.get(e.path)) {
|
|
33168
33556
|
if (!seen.has(full)) seen.set(full, /* @__PURE__ */ new Set());
|
|
33169
|
-
for (const v of
|
|
33557
|
+
for (const v of byPath3.get(e.path) ?? []) if (tableOf.get(v.path) === full) seen.get(full).add(JSON.stringify(v));
|
|
33170
33558
|
}
|
|
33171
33559
|
}
|
|
33172
33560
|
for (const [full, list2] of seen) out.set(full, list2.size);
|
|
@@ -33204,7 +33592,7 @@ function addSchemaChange(cs, t, after, settings) {
|
|
|
33204
33592
|
const before = new Map(t.catalog.entry.columns.map((c) => [String(c.name), c]));
|
|
33205
33593
|
const touched = entry.columns.filter((c) => {
|
|
33206
33594
|
const prev = before.get(String(c.name));
|
|
33207
|
-
return !prev || prev.ref !== c.ref || prev.hierarchy !== c.hierarchy || prev.type !== c.type || prev.items !== c.items || prev.vocabulary !== c.vocabulary || JSON.stringify(prev.ref_by) !== JSON.stringify(c.ref_by);
|
|
33595
|
+
return !prev || prev.ref !== c.ref || prev.hierarchy !== c.hierarchy || prev.acyclic !== c.acyclic || prev.type !== c.type || prev.items !== c.items || prev.vocabulary !== c.vocabulary || JSON.stringify(prev.ref_by) !== JSON.stringify(c.ref_by);
|
|
33208
33596
|
});
|
|
33209
33597
|
checkColumnRefs(t.catalog.model, ref2.full, touched, ref2.full, entry.columns);
|
|
33210
33598
|
def = tableDefinitionFromOrdered(ref2, catalogTablePath(settings, ref2.full), entryToOrdered(ref2, entry, settings, t.catalog.model), settings);
|
|
@@ -33244,6 +33632,12 @@ function checkColumnRefs(model, owner, columns, where, own2 = columns) {
|
|
|
33244
33632
|
if (c.hierarchy === true && ref2 !== owner) {
|
|
33245
33633
|
throw new OperationInputError(`${where}.${String(c.name)}: a hierarchy column must point at its own table (ref: self)`);
|
|
33246
33634
|
}
|
|
33635
|
+
if (c.acyclic === true && ref2 !== owner) {
|
|
33636
|
+
throw new OperationInputError(
|
|
33637
|
+
`${where}.${String(c.name)}: an acyclic column must point at its own table (ref: self)`,
|
|
33638
|
+
guide(`Set ref: "self": acyclic keeps the links between rows of one table free of cycles, such as tasks blocked by tasks.`, "acyclic")
|
|
33639
|
+
);
|
|
33640
|
+
}
|
|
33247
33641
|
if (typeof c.inverse === "string") checkInverse(model, owner, columns, c, ref2, where);
|
|
33248
33642
|
}
|
|
33249
33643
|
}
|
|
@@ -33343,6 +33737,9 @@ function assertColumnName(name, what) {
|
|
|
33343
33737
|
return name;
|
|
33344
33738
|
}
|
|
33345
33739
|
async function createTableImpl(app, settings, input, opts = {}) {
|
|
33740
|
+
if (input.instructions !== void 0 && input.instructions !== null && typeof input.instructions !== "string") {
|
|
33741
|
+
throw new OperationInputError(`"instructions" must be text: how to fill a row of the table`, guide(`Pass instructions as Markdown text, e.g. "1. Ask which film and when.", or leave them out.`, "instructions"));
|
|
33742
|
+
}
|
|
33346
33743
|
const proposal = input.description === null || input.columns.some((c) => c?.description === null);
|
|
33347
33744
|
{
|
|
33348
33745
|
const given = input.columns.find((c) => c.name === SYSTEM_ID_COLUMN);
|
|
@@ -33421,6 +33818,7 @@ async function createTableImpl(app, settings, input, opts = {}) {
|
|
|
33421
33818
|
tableDefinitionFromOrdered(ref2, pseudo, cat, settings);
|
|
33422
33819
|
const entry = withTableTags(orderedToEntry(cat, void 0, settings), tags);
|
|
33423
33820
|
if (typeof input.rowTemplate === "string" && input.rowTemplate.trim() !== "") entry.row_template = input.rowTemplate;
|
|
33821
|
+
if (typeof input.instructions === "string" && input.instructions.trim() !== "") entry.instructions = input.instructions;
|
|
33424
33822
|
if (typeof linkTarget2 === "boolean") entry.options = { ...entry.options, autolink_target: linkTarget2 };
|
|
33425
33823
|
if (typeof input.history === "boolean") entry.options = { ...entry.options, history: input.history };
|
|
33426
33824
|
checkColumnRefs(model, ref2.full, entry.columns, ref2.full);
|
|
@@ -33508,6 +33906,16 @@ async function addColumnImpl(app, settings, input, opts = {}) {
|
|
|
33508
33906
|
violations.push(...uniqueViolations([spec], (await loadRows(app, settings, t)).map((r) => ({ path: r.file.path, ordered: r.ordered }))));
|
|
33509
33907
|
}
|
|
33510
33908
|
violations.push(...await filteredLinkViolations(app, settings, t, [...t.def.columns, spec], spec));
|
|
33909
|
+
const { acyclicPairs: acyclicPairs2, acyclicViolations: acyclicViolations2 } = await Promise.resolve().then(() => (init_acyclic(), acyclic_exports));
|
|
33910
|
+
const withNew = [...t.def.columns, spec];
|
|
33911
|
+
if (acyclicPairs2(withNew, t.catalog.ref.full).some((p) => p.column === spec.name || p.inverse === spec.name)) {
|
|
33912
|
+
const rowsNow = (await loadRows(app, settings, t)).map((r) => {
|
|
33913
|
+
const has = r.ordered.some(([k]) => k === spec.name);
|
|
33914
|
+
const value = has ? fmGet(r.ordered, spec.name) : dense ? fill : void 0;
|
|
33915
|
+
return { path: r.file.path, ordered: value === void 0 ? r.ordered : fmSet(r.ordered, spec.name, value) };
|
|
33916
|
+
});
|
|
33917
|
+
violations.push(...acyclicViolations2(withNew, t.catalog.ref.full, rowsNow, { involving: spec.name, wording: "check" }));
|
|
33918
|
+
}
|
|
33511
33919
|
return finish(app, settings, cs, [], violations, opts);
|
|
33512
33920
|
}
|
|
33513
33921
|
function withRenamedLevels(c, table, from, to) {
|
|
@@ -33700,6 +34108,7 @@ async function alterColumnImpl(app, settings, input, opts = {}) {
|
|
|
33700
34108
|
else merged[k] = v;
|
|
33701
34109
|
}
|
|
33702
34110
|
const spec = parseColumn(merged, idx, META_KEYS);
|
|
34111
|
+
const checked = spec.ref === "self" ? { ...spec, ref: t.catalog.ref.full } : spec;
|
|
33703
34112
|
const columns = t.def.columns.map((c, i) => i === idx ? spec : c);
|
|
33704
34113
|
const reserved = META_KEYS;
|
|
33705
34114
|
let after = withColumns(t.ordered, columns);
|
|
@@ -33726,13 +34135,19 @@ async function alterColumnImpl(app, settings, input, opts = {}) {
|
|
|
33726
34135
|
violations.push({ path: r.file.path, violations: [{ column: spec.name, code: "required", message: requiredMessage(spec) }] });
|
|
33727
34136
|
}
|
|
33728
34137
|
} else {
|
|
33729
|
-
violations.push({ path: r.file.path, violations: validateValue(
|
|
34138
|
+
violations.push({ path: r.file.path, violations: validateValue(checked, v, validationContextFor(app, settings, r.file.path)) });
|
|
33730
34139
|
}
|
|
33731
34140
|
if (makeDense && !has) {
|
|
33732
34141
|
cs.edits.push({ path: r.file.path, before: r.ordered, after: fmAdd(r.ordered, spec.name, fill ?? null) });
|
|
33733
34142
|
}
|
|
33734
34143
|
}
|
|
33735
34144
|
violations.push(...await filteredLinkViolations(app, settings, t, columns, spec));
|
|
34145
|
+
const { acyclicPairs: acyclicPairs2, acyclicViolations: acyclicViolations2 } = await Promise.resolve().then(() => (init_acyclic(), acyclic_exports));
|
|
34146
|
+
if (acyclicPairs2(columns, t.catalog.ref.full).some((p) => p.column === spec.name || p.inverse === spec.name)) {
|
|
34147
|
+
const afterOf = new Map(cs.edits.map((e) => [e.path, e.after]));
|
|
34148
|
+
const rowsNow = existing.map((r) => ({ path: r.file.path, ordered: afterOf.get(r.file.path) ?? r.ordered }));
|
|
34149
|
+
violations.push(...acyclicViolations2(columns, t.catalog.ref.full, rowsNow, { involving: spec.name, wording: "check" }));
|
|
34150
|
+
}
|
|
33736
34151
|
const text5 = cs.texts.find((x) => x.path === t.file.path).after;
|
|
33737
34152
|
const conflicts = levelTargetConflicts(parseMetastore(text5), t.catalog.ref.full, spec.name).map((message) => ({ path: t.file.path, message }));
|
|
33738
34153
|
return finish(app, settings, cs, conflicts, violations, opts);
|
|
@@ -34729,10 +35144,10 @@ var init_otlp = __esm({
|
|
|
34729
35144
|
this.timer.unref?.();
|
|
34730
35145
|
}
|
|
34731
35146
|
}
|
|
34732
|
-
push(
|
|
35147
|
+
push(items2) {
|
|
34733
35148
|
const room = this.maxBatch * 8 - this.buffer.length;
|
|
34734
|
-
if (room <
|
|
34735
|
-
for (let i = 0; i < Math.min(
|
|
35149
|
+
if (room < items2.length) this.dropped += items2.length - Math.max(room, 0);
|
|
35150
|
+
for (let i = 0; i < Math.min(items2.length, Math.max(room, 0)); i++) this.buffer.push(items2[i]);
|
|
34736
35151
|
if (this.buffer.length >= this.maxBatch) void this.flush();
|
|
34737
35152
|
}
|
|
34738
35153
|
resource() {
|
|
@@ -48436,14 +48851,14 @@ var require_codegen = __commonJS({
|
|
|
48436
48851
|
return replaceName(expr);
|
|
48437
48852
|
if (!canOptimize(expr))
|
|
48438
48853
|
return expr;
|
|
48439
|
-
return new code_1._Code(expr._items.reduce((
|
|
48854
|
+
return new code_1._Code(expr._items.reduce((items2, c) => {
|
|
48440
48855
|
if (c instanceof code_1.Name)
|
|
48441
48856
|
c = replaceName(c);
|
|
48442
48857
|
if (c instanceof code_1._Code)
|
|
48443
|
-
|
|
48858
|
+
items2.push(...c._items);
|
|
48444
48859
|
else
|
|
48445
|
-
|
|
48446
|
-
return
|
|
48860
|
+
items2.push(c);
|
|
48861
|
+
return items2;
|
|
48447
48862
|
}, []));
|
|
48448
48863
|
function replaceName(n) {
|
|
48449
48864
|
const c = constants2[n.str];
|
|
@@ -48601,7 +49016,7 @@ var require_util = __commonJS({
|
|
|
48601
49016
|
mergeNames: (gen, from, to) => gen.if((0, codegen_1._)`${to} !== true && ${from} !== undefined`, () => gen.assign(to, (0, codegen_1._)`${from} === true ? true : ${to} > ${from} ? ${to} : ${from}`)),
|
|
48602
49017
|
mergeToName: (gen, from, to) => gen.if((0, codegen_1._)`${to} !== true`, () => gen.assign(to, from === true ? true : (0, codegen_1._)`${to} > ${from} ? ${to} : ${from}`)),
|
|
48603
49018
|
mergeValues: (from, to) => from === true ? true : Math.max(from, to),
|
|
48604
|
-
resultToName: (gen,
|
|
49019
|
+
resultToName: (gen, items2) => gen.var("items", items2)
|
|
48605
49020
|
})
|
|
48606
49021
|
};
|
|
48607
49022
|
function evaluatedPropsToName(gen, ps) {
|
|
@@ -49109,13 +49524,13 @@ var require_defaults = __commonJS({
|
|
|
49109
49524
|
var codegen_1 = require_codegen();
|
|
49110
49525
|
var util_1 = require_util();
|
|
49111
49526
|
function assignDefaults(it, ty) {
|
|
49112
|
-
const { properties, items } = it.schema;
|
|
49527
|
+
const { properties, items: items2 } = it.schema;
|
|
49113
49528
|
if (ty === "object" && properties) {
|
|
49114
49529
|
for (const key2 in properties) {
|
|
49115
49530
|
assignDefault(it, key2, properties[key2].default);
|
|
49116
49531
|
}
|
|
49117
|
-
} else if (ty === "array" && Array.isArray(
|
|
49118
|
-
|
|
49532
|
+
} else if (ty === "array" && Array.isArray(items2)) {
|
|
49533
|
+
items2.forEach((sch, i) => assignDefault(it, i, sch.default));
|
|
49119
49534
|
}
|
|
49120
49535
|
}
|
|
49121
49536
|
exports2.assignDefaults = assignDefaults;
|
|
@@ -49919,11 +50334,11 @@ var require_validate = __commonJS({
|
|
|
49919
50334
|
gen.return((0, codegen_1._)`${names_1.default.errors} === 0`);
|
|
49920
50335
|
}
|
|
49921
50336
|
}
|
|
49922
|
-
function assignEvaluated({ gen, evaluated, props, items }) {
|
|
50337
|
+
function assignEvaluated({ gen, evaluated, props, items: items2 }) {
|
|
49923
50338
|
if (props instanceof codegen_1.Name)
|
|
49924
50339
|
gen.assign((0, codegen_1._)`${evaluated}.props`, props);
|
|
49925
|
-
if (
|
|
49926
|
-
gen.assign((0, codegen_1._)`${evaluated}.items`,
|
|
50340
|
+
if (items2 instanceof codegen_1.Name)
|
|
50341
|
+
gen.assign((0, codegen_1._)`${evaluated}.items`, items2);
|
|
49927
50342
|
}
|
|
49928
50343
|
function schemaKeywords(it, types, typeErrors, errsCount) {
|
|
49929
50344
|
const { gen, schema, data, allErrors, opts, self } = it;
|
|
@@ -50386,12 +50801,12 @@ var require_compile = __commonJS({
|
|
|
50386
50801
|
validate2.source = { validateName, validateCode, scopeValues: gen._values };
|
|
50387
50802
|
}
|
|
50388
50803
|
if (this.opts.unevaluated) {
|
|
50389
|
-
const { props, items } = schemaCxt;
|
|
50804
|
+
const { props, items: items2 } = schemaCxt;
|
|
50390
50805
|
validate2.evaluated = {
|
|
50391
50806
|
props: props instanceof codegen_1.Name ? void 0 : props,
|
|
50392
|
-
items:
|
|
50807
|
+
items: items2 instanceof codegen_1.Name ? void 0 : items2,
|
|
50393
50808
|
dynamicProps: props instanceof codegen_1.Name,
|
|
50394
|
-
dynamicItems:
|
|
50809
|
+
dynamicItems: items2 instanceof codegen_1.Name
|
|
50395
50810
|
};
|
|
50396
50811
|
if (validate2.source)
|
|
50397
50812
|
validate2.source.evaluated = (0, codegen_1.stringify)(validate2.evaluated);
|
|
@@ -52401,8 +52816,8 @@ var require_ref = __commonJS({
|
|
|
52401
52816
|
it.items = util_1.mergeEvaluated.items(gen, schEvaluated.items, it.items);
|
|
52402
52817
|
}
|
|
52403
52818
|
} else {
|
|
52404
|
-
const
|
|
52405
|
-
it.items = util_1.mergeEvaluated.items(gen,
|
|
52819
|
+
const items2 = gen.var("items", (0, codegen_1._)`${source}.evaluated.items`);
|
|
52820
|
+
it.items = util_1.mergeEvaluated.items(gen, items2, it.items, codegen_1.Name);
|
|
52406
52821
|
}
|
|
52407
52822
|
}
|
|
52408
52823
|
}
|
|
@@ -52942,28 +53357,28 @@ var require_additionalItems = __commonJS({
|
|
|
52942
53357
|
error: error2,
|
|
52943
53358
|
code(cxt) {
|
|
52944
53359
|
const { parentSchema, it } = cxt;
|
|
52945
|
-
const { items } = parentSchema;
|
|
52946
|
-
if (!Array.isArray(
|
|
53360
|
+
const { items: items2 } = parentSchema;
|
|
53361
|
+
if (!Array.isArray(items2)) {
|
|
52947
53362
|
(0, util_1.checkStrictMode)(it, '"additionalItems" is ignored when "items" is not an array of schemas');
|
|
52948
53363
|
return;
|
|
52949
53364
|
}
|
|
52950
|
-
validateAdditionalItems(cxt,
|
|
53365
|
+
validateAdditionalItems(cxt, items2);
|
|
52951
53366
|
}
|
|
52952
53367
|
};
|
|
52953
|
-
function validateAdditionalItems(cxt,
|
|
53368
|
+
function validateAdditionalItems(cxt, items2) {
|
|
52954
53369
|
const { gen, schema, data, keyword, it } = cxt;
|
|
52955
53370
|
it.items = true;
|
|
52956
53371
|
const len = gen.const("len", (0, codegen_1._)`${data}.length`);
|
|
52957
53372
|
if (schema === false) {
|
|
52958
|
-
cxt.setParams({ len:
|
|
52959
|
-
cxt.pass((0, codegen_1._)`${len} <= ${
|
|
53373
|
+
cxt.setParams({ len: items2.length });
|
|
53374
|
+
cxt.pass((0, codegen_1._)`${len} <= ${items2.length}`);
|
|
52960
53375
|
} else if (typeof schema == "object" && !(0, util_1.alwaysValidSchema)(it, schema)) {
|
|
52961
|
-
const valid = gen.var("valid", (0, codegen_1._)`${len} <= ${
|
|
53376
|
+
const valid = gen.var("valid", (0, codegen_1._)`${len} <= ${items2.length}`);
|
|
52962
53377
|
gen.if((0, codegen_1.not)(valid), () => validateItems(valid));
|
|
52963
53378
|
cxt.ok(valid);
|
|
52964
53379
|
}
|
|
52965
53380
|
function validateItems(valid) {
|
|
52966
|
-
gen.forRange("i",
|
|
53381
|
+
gen.forRange("i", items2.length, len, (i) => {
|
|
52967
53382
|
cxt.subschema({ keyword, dataProp: i, dataPropType: util_1.Type.Num }, valid);
|
|
52968
53383
|
if (!it.allErrors)
|
|
52969
53384
|
gen.if((0, codegen_1.not)(valid), () => gen.break());
|
|
@@ -56985,6 +57400,10 @@ async function addConstraintImpl(app, settings, input, opts = {}) {
|
|
|
56985
57400
|
if (!input.check || typeof input.check !== "object" || Array.isArray(input.check) || Object.keys(input.check).length === 0) {
|
|
56986
57401
|
throw new OperationInputError(`"check" must be a non-empty where filter`, guide(`A CHECK is a where filter every row must match, e.g. {"or": [{"status": "to watch"}, {"rating": {"exists": true}}]}.`, "check"));
|
|
56987
57402
|
}
|
|
57403
|
+
if (input.hint !== void 0 && input.hint !== null && typeof input.hint !== "string") {
|
|
57404
|
+
throw new OperationInputError(`"hint" must be text: what to do when a row breaks the CHECK`, guide(`Pass hint as one or two sentences, e.g. "A watched film needs a rating: ask for it.", or leave it out.`, "check"));
|
|
57405
|
+
}
|
|
57406
|
+
const hint = typeof input.hint === "string" && input.hint.trim() !== "" ? input.hint.trim() : void 0;
|
|
56988
57407
|
if (cat.entry.constraints?.[input.name]) throw new OperationInputError(`constraint "${input.name}" already exists; drop it first`, guide(`Choose another name, or drop_constraint "${input.name}" first to replace it; describe_table lists the constraints.`, "check"));
|
|
56989
57408
|
const links = new CheckLinks(app, settings);
|
|
56990
57409
|
await links.prepare(t, input.check);
|
|
@@ -56993,7 +57412,13 @@ async function addConstraintImpl(app, settings, input, opts = {}) {
|
|
|
56993
57412
|
for (const r of await loadRows(app, settings, t)) {
|
|
56994
57413
|
if (!passes(r)) conflicts.push({ path: r.file.path, message: `violates CHECK ${input.name}` });
|
|
56995
57414
|
}
|
|
56996
|
-
const
|
|
57415
|
+
const hints = { ...constraintHints(cat.entry), ...hint ? { [input.name]: hint } : {} };
|
|
57416
|
+
const { constraint_hints: _h, ...withoutHints } = cat.entry;
|
|
57417
|
+
const entry = {
|
|
57418
|
+
...withoutHints,
|
|
57419
|
+
constraints: { ...cat.entry.constraints ?? {}, [input.name]: input.check },
|
|
57420
|
+
...Object.keys(hints).length > 0 ? { constraint_hints: hints } : {}
|
|
57421
|
+
};
|
|
56997
57422
|
const cs = emptyChangeSet("add_constraint", `add constraint ${input.name} to ${cat.ref.full}`, t.def.schemaPath);
|
|
56998
57423
|
cs.texts.push({ path: t.file.path, before: cat.text, after: setTableEntry(cat.text, cat.ref, entry) });
|
|
56999
57424
|
return finish(app, settings, cs, conflicts, [], opts);
|
|
@@ -57005,8 +57430,13 @@ async function dropConstraintImpl(app, settings, input, opts = {}) {
|
|
|
57005
57430
|
throw new OperationInputError(`${cat.ref.full} has no constraint "${input.name}"`, unknownName(input.name, Object.keys(cat.entry.constraints ?? {}), `constraints of ${cat.ref.full}`, "describe_table lists them.", "check"));
|
|
57006
57431
|
}
|
|
57007
57432
|
const { [input.name]: _gone, ...rest } = cat.entry.constraints;
|
|
57008
|
-
const {
|
|
57009
|
-
const
|
|
57433
|
+
const { [input.name]: _x, ...hintsLeft } = constraintHints(cat.entry);
|
|
57434
|
+
const { constraints: _c, constraint_hints: _h, ...base } = cat.entry;
|
|
57435
|
+
const entry = {
|
|
57436
|
+
...base,
|
|
57437
|
+
...Object.keys(rest).length > 0 ? { constraints: rest } : {},
|
|
57438
|
+
...Object.keys(hintsLeft).length > 0 ? { constraint_hints: hintsLeft } : {}
|
|
57439
|
+
};
|
|
57010
57440
|
const cs = emptyChangeSet("drop_constraint", `drop constraint ${input.name} from ${cat.ref.full}`, t.def.schemaPath);
|
|
57011
57441
|
cs.texts.push({ path: t.file.path, before: cat.text, after: setTableEntry(cat.text, cat.ref, entry) });
|
|
57012
57442
|
return finish(app, settings, cs, [], [], opts);
|
|
@@ -57148,7 +57578,8 @@ var INFO_COLUMNS = {
|
|
|
57148
57578
|
["comment", "string"],
|
|
57149
57579
|
["row_count", "integer"],
|
|
57150
57580
|
["latest_version", "integer"],
|
|
57151
|
-
["tags", "json"]
|
|
57581
|
+
["tags", "json"],
|
|
57582
|
+
["instructions", "string"]
|
|
57152
57583
|
],
|
|
57153
57584
|
columns: [
|
|
57154
57585
|
["table_catalog", "string"],
|
|
@@ -57164,10 +57595,11 @@ var INFO_COLUMNS = {
|
|
|
57164
57595
|
["is_identity", "string"],
|
|
57165
57596
|
["is_unique", "string"],
|
|
57166
57597
|
["inherited_from", "string"],
|
|
57167
|
-
["is_hierarchy", "string"]
|
|
57598
|
+
["is_hierarchy", "string"],
|
|
57599
|
+
["is_acyclic", "string"]
|
|
57168
57600
|
],
|
|
57169
57601
|
views: [["table_catalog", "string"], ["table_schema", "string"], ["table_name", "string"], ["view_definition", "string"], ["comment", "string"], ["aliases", "list"], ["labels", "string"]],
|
|
57170
|
-
check_constraints: [["table_catalog", "string"], ["table_schema", "string"], ["table_name", "string"], ["constraint_name", "string"], ["check_clause", "string"]]
|
|
57602
|
+
check_constraints: [["table_catalog", "string"], ["table_schema", "string"], ["table_name", "string"], ["constraint_name", "string"], ["check_clause", "string"], ["hint", "string"]]
|
|
57171
57603
|
};
|
|
57172
57604
|
function informationSchemaTable(ref2) {
|
|
57173
57605
|
const parts = ref2.trim().split(".");
|
|
@@ -57210,7 +57642,8 @@ async function informationRows(app, settings, name) {
|
|
|
57210
57642
|
comment: entry.description ?? null,
|
|
57211
57643
|
row_count: rows.get(ref2.full).length,
|
|
57212
57644
|
latest_version: latest,
|
|
57213
|
-
tags: tableTags(entry) ?? null
|
|
57645
|
+
tags: tableTags(entry) ?? null,
|
|
57646
|
+
instructions: tableInstructions(entry) ?? null
|
|
57214
57647
|
});
|
|
57215
57648
|
}
|
|
57216
57649
|
for (const { ref: ref2, view } of catalogViews(model)) {
|
|
@@ -57223,7 +57656,8 @@ async function informationRows(app, settings, name) {
|
|
|
57223
57656
|
comment: view.description ?? null,
|
|
57224
57657
|
row_count: null,
|
|
57225
57658
|
latest_version: null,
|
|
57226
|
-
tags: null
|
|
57659
|
+
tags: null,
|
|
57660
|
+
instructions: null
|
|
57227
57661
|
});
|
|
57228
57662
|
}
|
|
57229
57663
|
return out;
|
|
@@ -57245,7 +57679,8 @@ async function informationRows(app, settings, name) {
|
|
|
57245
57679
|
is_identity: c.identity ? String(c.identity) : "NO",
|
|
57246
57680
|
is_unique: c.unique ? "YES" : "NO",
|
|
57247
57681
|
inherited_from: from.get(String(c.name)) ?? null,
|
|
57248
|
-
is_hierarchy: c.hierarchy ? "YES" : "NO"
|
|
57682
|
+
is_hierarchy: c.hierarchy ? "YES" : "NO",
|
|
57683
|
+
is_acyclic: c.acyclic ? "YES" : "NO"
|
|
57249
57684
|
}));
|
|
57250
57685
|
});
|
|
57251
57686
|
case "views":
|
|
@@ -57259,15 +57694,17 @@ async function informationRows(app, settings, name) {
|
|
|
57259
57694
|
labels: view.labels ? JSON.stringify(view.labels) : null
|
|
57260
57695
|
}));
|
|
57261
57696
|
case "check_constraints":
|
|
57262
|
-
return tables.flatMap(
|
|
57263
|
-
|
|
57697
|
+
return tables.flatMap(({ ref: ref2, entry }) => {
|
|
57698
|
+
const hintsOf = constraintHints(entry);
|
|
57699
|
+
return Object.entries(entry.constraints ?? {}).map(([n, where]) => ({
|
|
57264
57700
|
table_catalog: ref2.catalog,
|
|
57265
57701
|
table_schema: ref2.schema,
|
|
57266
57702
|
table_name: ref2.table,
|
|
57267
57703
|
constraint_name: n,
|
|
57268
|
-
check_clause: JSON.stringify(where)
|
|
57269
|
-
|
|
57270
|
-
|
|
57704
|
+
check_clause: JSON.stringify(where),
|
|
57705
|
+
hint: hintsOf[n] ?? null
|
|
57706
|
+
}));
|
|
57707
|
+
});
|
|
57271
57708
|
}
|
|
57272
57709
|
}
|
|
57273
57710
|
async function informationSchemaTableData(app, settings, name) {
|
|
@@ -57493,7 +57930,7 @@ async function defineBaseImpl(app, settings, input, opts = {}) {
|
|
|
57493
57930
|
const violations = await planInheritedRows(app, settings, next, after, tablesInheriting(next, input.name), rewrite, cs);
|
|
57494
57931
|
return finish(app, settings, cs, [], [...violations, ...await inheritedLinkViolations(app, settings, cs)], opts);
|
|
57495
57932
|
}
|
|
57496
|
-
var CONSTRAINT_KEYS = ["required", "unique", "min", "max", "step", "values", "ordered", "ref", "generated", "identity", "default", "hierarchy", "ref_where", "ref_by"];
|
|
57933
|
+
var CONSTRAINT_KEYS = ["required", "unique", "min", "max", "step", "values", "ordered", "ref", "generated", "identity", "default", "hierarchy", "acyclic", "ref_where", "ref_by"];
|
|
57497
57934
|
async function setTableBasesImpl(app, settings, input, opts = {}) {
|
|
57498
57935
|
const t = await loadTable(app, settings, input.table);
|
|
57499
57936
|
const cat = requireCatalog(t, "Inheritance");
|
|
@@ -57864,8 +58301,8 @@ function groupSelect(t, rows, join, input, known, specs, limit, offset, get) {
|
|
|
57864
58301
|
let keys = [[]];
|
|
57865
58302
|
for (const e of groupExprs) {
|
|
57866
58303
|
const v = e.eval(q);
|
|
57867
|
-
const
|
|
57868
|
-
const options =
|
|
58304
|
+
const items2 = Array.isArray(v) ? [...new Set(v.map((x) => groupDisplay(x)))] : [groupDisplay(v)];
|
|
58305
|
+
const options = items2.length > 0 ? items2 : [null];
|
|
57869
58306
|
keys = keys.flatMap((k) => options.map((o) => [...k, o]));
|
|
57870
58307
|
}
|
|
57871
58308
|
for (const key2 of keys) {
|
|
@@ -58425,7 +58862,7 @@ function mentionsIn(text5, frag, ix, self) {
|
|
|
58425
58862
|
if (matches2.length === 0) continue;
|
|
58426
58863
|
const inMatch = /* @__PURE__ */ new Set();
|
|
58427
58864
|
for (const m of matches2) for (let t = m.ti; t <= m.tj; t++) inMatch.add(t);
|
|
58428
|
-
const
|
|
58865
|
+
const items2 = [];
|
|
58429
58866
|
for (let g = 0; g < matches2.length; ) {
|
|
58430
58867
|
const group = [matches2[g]];
|
|
58431
58868
|
let end = matches2[g].end;
|
|
@@ -58439,16 +58876,16 @@ function mentionsIn(text5, frag, ix, self) {
|
|
|
58439
58876
|
const tj = Math.max(...group.map((m) => m.tj));
|
|
58440
58877
|
if (longest.start === start && longest.end === end) {
|
|
58441
58878
|
const kind = longest.self ? "self" : longest.cands.length > 1 ? "same_name" : "clear";
|
|
58442
|
-
|
|
58879
|
+
items2.push({ frag, start, end, keys: [longest.key], cands: longest.cands, kind, ti, tj });
|
|
58443
58880
|
} else {
|
|
58444
58881
|
const cands = [...new Set(group.flatMap((m) => m.cands))].sort();
|
|
58445
|
-
|
|
58882
|
+
items2.push({ frag, start, end, keys: group.map((m) => m.key), cands, kind: cands.length === 0 ? "self" : "overlap", ti, tj });
|
|
58446
58883
|
}
|
|
58447
58884
|
}
|
|
58448
|
-
for (let i = 0; i <
|
|
58885
|
+
for (let i = 0; i < items2.length; ) {
|
|
58449
58886
|
let j = i;
|
|
58450
|
-
while (j + 1 <
|
|
58451
|
-
const run =
|
|
58887
|
+
while (j + 1 < items2.length && items2[j].kind !== "self" && items2[j + 1].kind !== "self" && PHRASE_SEP.test(text5.slice(items2[j].end, items2[j + 1].start))) j++;
|
|
58888
|
+
const run = items2.slice(i, j + 1);
|
|
58452
58889
|
const cands = [...new Set(run.flatMap((m) => m.cands))].sort();
|
|
58453
58890
|
if (run.length > 1 && cands.length > 1) {
|
|
58454
58891
|
out.push({ frag, start: run[0].start, end: run.at(-1).end, keys: run.flatMap((m) => m.keys), cands, kind: "adjacent" });
|
|
@@ -58681,7 +59118,7 @@ async function verifyUniqueValues(app, settings) {
|
|
|
58681
59118
|
const v = VALUES.get(app).get(full);
|
|
58682
59119
|
const rows = await loadRows(app, settings, t);
|
|
58683
59120
|
const want = new Map(rows.map((r) => [r.file.path, v.columns.map((c) => uniqueKey(fmGet(r.ordered, c)))]));
|
|
58684
|
-
const show = (
|
|
59121
|
+
const show = (byPath3) => JSON.stringify([...byPath3].sort(([a], [b]) => a < b ? -1 : 1));
|
|
58685
59122
|
if (show(v.byPath) !== show(want)) out.push(`unique values of ${full} differ from its rows`);
|
|
58686
59123
|
const byKey = v.columns.map((_, i) => {
|
|
58687
59124
|
const m = /* @__PURE__ */ new Map();
|
|
@@ -59464,6 +59901,7 @@ init_path_templates();
|
|
|
59464
59901
|
init_computed_columns();
|
|
59465
59902
|
init_where();
|
|
59466
59903
|
init_message();
|
|
59904
|
+
init_hints();
|
|
59467
59905
|
init_descriptions();
|
|
59468
59906
|
function escapeRegExp(s) {
|
|
59469
59907
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -59478,7 +59916,7 @@ function archivedRowFiles(app, settings, t) {
|
|
|
59478
59916
|
return rowTableFull(model, fm?.[settings.tableKey]) === full;
|
|
59479
59917
|
});
|
|
59480
59918
|
}
|
|
59481
|
-
async function relocateTable(app, settings, t, dest, changes, opts, properties = {}, rowTemplate2, tags, fields = {}) {
|
|
59919
|
+
async function relocateTable(app, settings, t, dest, changes, opts, properties = {}, rowTemplate2, tags, fields = {}, instructions) {
|
|
59482
59920
|
const conflicts = [];
|
|
59483
59921
|
const merged = { ...serializeOptions(t.def.options)[0] };
|
|
59484
59922
|
for (const [k, v] of Object.entries(changes)) {
|
|
@@ -59518,6 +59956,8 @@ async function relocateTable(app, settings, t, dest, changes, opts, properties =
|
|
|
59518
59956
|
}
|
|
59519
59957
|
if (rowTemplate2 === null || typeof rowTemplate2 === "string" && rowTemplate2.trim() === "") delete entry.row_template;
|
|
59520
59958
|
else if (typeof rowTemplate2 === "string") entry.row_template = rowTemplate2;
|
|
59959
|
+
if (instructions === null || typeof instructions === "string" && instructions.trim() === "") delete entry.instructions;
|
|
59960
|
+
else if (typeof instructions === "string") entry.instructions = instructions;
|
|
59521
59961
|
const after = setTableEntries(text5, [...t.catalog.ref.full !== ref2.full ? [[t.catalog.ref, null]] : [], [ref2, tags === void 0 ? entry : withTableTags(entry, tags)]]);
|
|
59522
59962
|
const from = t.catalog.ref.full;
|
|
59523
59963
|
cs = emptyChangeSet("alter_table", from === ref2.full ? `alter table ${from}` : `move table ${from} to ${ref2.full}`, catalogTablePath(settings, ref2.full));
|
|
@@ -59612,6 +60052,9 @@ function fieldsInput(t, settings, value) {
|
|
|
59612
60052
|
return out;
|
|
59613
60053
|
}
|
|
59614
60054
|
async function alterTableImpl(app, settings, input, opts = {}) {
|
|
60055
|
+
if (input.instructions !== void 0 && input.instructions !== null && typeof input.instructions !== "string") {
|
|
60056
|
+
throw new OperationInputError(`"instructions" must be text: how to fill a row of the table`, guide(`Pass instructions as Markdown text, e.g. "1. Ask which film and when.", or leave them out; "" removes them.`, "instructions"));
|
|
60057
|
+
}
|
|
59615
60058
|
const t = await loadTable(app, settings, input.table);
|
|
59616
60059
|
const cfg = await readDatabaseConfig(app, settings);
|
|
59617
60060
|
const schema = assertIdentifier("schema", input.schema ?? t.def.schema);
|
|
@@ -59661,7 +60104,7 @@ async function alterTableImpl(app, settings, input, opts = {}) {
|
|
|
59661
60104
|
return relocateTable(app, settings, t, { catalogRef: refOf(catalog, schema, name) }, changes, opts, {
|
|
59662
60105
|
...input.history !== void 0 ? { history: input.history } : {},
|
|
59663
60106
|
...input.autolinkTarget !== void 0 ? { autolink_target: input.autolinkTarget } : {}
|
|
59664
|
-
}, input.rowTemplate, tags, fields);
|
|
60107
|
+
}, input.rowTemplate, tags, fields, input.instructions);
|
|
59665
60108
|
}
|
|
59666
60109
|
var alterTable = instrumented("alter_table", alterTableImpl, (i) => ({ table: i.table, schema: i.schema, name: i.name }));
|
|
59667
60110
|
|
|
@@ -60743,13 +61186,13 @@ function inferColumns(app, settings, observed, files, maxEnum) {
|
|
|
60743
61186
|
if (kind === null && kinds.has("list")) kind = "list";
|
|
60744
61187
|
if (kind === null) kind = "string";
|
|
60745
61188
|
if (kind === "list") {
|
|
60746
|
-
const
|
|
60747
|
-
const itemKind = mergeKinds(new Set(
|
|
61189
|
+
const items2 = filled.flatMap((x) => Array.isArray(x.value) ? x.value : [x.value]).filter((v) => !isEmpty(v));
|
|
61190
|
+
const itemKind = mergeKinds(new Set(items2.map(kindOf))) ?? "string";
|
|
60748
61191
|
col.type = "list";
|
|
60749
|
-
const itemDistinct = [...new Set(
|
|
60750
|
-
if (itemKind === "string" && itemDistinct.length > 0 && itemDistinct.length <= maxEnum &&
|
|
61192
|
+
const itemDistinct = [...new Set(items2.map((v) => String(v).trim()))];
|
|
61193
|
+
if (itemKind === "string" && itemDistinct.length > 0 && itemDistinct.length <= maxEnum && items2.length >= 3 && itemDistinct.length * 2 <= items2.length) {
|
|
60751
61194
|
col.items = "enum";
|
|
60752
|
-
col.values = frequencyOrder(
|
|
61195
|
+
col.values = frequencyOrder(items2.map((v) => String(v).trim()));
|
|
60753
61196
|
} else {
|
|
60754
61197
|
col.items = itemKind === "list" ? "string" : itemKind;
|
|
60755
61198
|
}
|
|
@@ -60990,6 +61433,8 @@ async function describeTable(app, settings, table) {
|
|
|
60990
61433
|
const o = def.options;
|
|
60991
61434
|
const e = t.catalog.entry;
|
|
60992
61435
|
const tags = tableTags(e);
|
|
61436
|
+
const hints = constraintHints(e);
|
|
61437
|
+
const instructions = tableInstructions(e);
|
|
60993
61438
|
const missing = missingDescriptions(o.description, def.columns);
|
|
60994
61439
|
return {
|
|
60995
61440
|
qualified: t.catalog.ref.full,
|
|
@@ -61012,6 +61457,8 @@ async function describeTable(app, settings, table) {
|
|
|
61012
61457
|
...missing ? { missing_descriptions: missing } : {},
|
|
61013
61458
|
...e.bases && e.bases.length > 0 ? { bases: [...e.bases] } : {},
|
|
61014
61459
|
...e.constraints && Object.keys(e.constraints).length > 0 ? { constraints: e.constraints } : {},
|
|
61460
|
+
...Object.keys(hints).length > 0 ? { constraint_hints: hints } : {},
|
|
61461
|
+
...instructions !== void 0 ? { instructions } : {},
|
|
61015
61462
|
...typeof e.row_template === "string" ? { row_template: e.row_template } : {},
|
|
61016
61463
|
...typeof e.options?.history === "boolean" ? { history: e.options.history } : {},
|
|
61017
61464
|
...typeof e.options?.autolink_target === "boolean" ? { autolink_target: e.options.autolink_target } : {},
|
|
@@ -61476,17 +61923,17 @@ var SemanticIndex = class {
|
|
|
61476
61923
|
const staged = /* @__PURE__ */ new Map();
|
|
61477
61924
|
const empty = new Int8Array(0);
|
|
61478
61925
|
const flush2 = async () => {
|
|
61479
|
-
const
|
|
61926
|
+
const items2 = queue.filter((x) => staged.has(x.path));
|
|
61480
61927
|
queue = [];
|
|
61481
|
-
if (
|
|
61928
|
+
if (items2.length === 0) return;
|
|
61482
61929
|
try {
|
|
61483
|
-
const vectors = await embed(this.transport, cfg,
|
|
61484
|
-
|
|
61930
|
+
const vectors = await embed(this.transport, cfg, items2.map((x) => x.text));
|
|
61931
|
+
items2.forEach((x, j) => {
|
|
61485
61932
|
staged.get(x.path).vectors[x.i] = normalize(vectors[j]);
|
|
61486
61933
|
});
|
|
61487
61934
|
} catch (e) {
|
|
61488
61935
|
const error2 = messageOf(e);
|
|
61489
|
-
for (const x of new Set(
|
|
61936
|
+
for (const x of new Set(items2.map((y) => y.path))) {
|
|
61490
61937
|
staged.delete(x);
|
|
61491
61938
|
result.failed.push({ path: x, error: error2 });
|
|
61492
61939
|
this.pending.add(x);
|
|
@@ -62781,12 +63228,12 @@ var ChangeFeed = class {
|
|
|
62781
63228
|
};
|
|
62782
63229
|
});
|
|
62783
63230
|
try {
|
|
62784
|
-
const { byPath:
|
|
63231
|
+
const { byPath: byPath3, tableOf } = await checkExternalEdits(this.app, s, edits);
|
|
62785
63232
|
const rows = /* @__PURE__ */ new Set();
|
|
62786
63233
|
const tables = /* @__PURE__ */ new Set();
|
|
62787
63234
|
let n = 0;
|
|
62788
63235
|
for (const [path19, i] of last) {
|
|
62789
|
-
const violations =
|
|
63236
|
+
const violations = byPath3.get(path19) ?? [];
|
|
62790
63237
|
out[i] = { ...out[i], ...capped(violations) };
|
|
62791
63238
|
n += violations.length;
|
|
62792
63239
|
for (const v of violations) {
|
|
@@ -63837,6 +64284,7 @@ function createHandlers(app, getSettings, saveSettings = async () => {
|
|
|
63837
64284
|
if (target !== void 0) options2.autolink_target = target;
|
|
63838
64285
|
const history2 = optBool(b, "history");
|
|
63839
64286
|
const template = text3(b, "row_template");
|
|
64287
|
+
const instructions = text3(b, "instructions");
|
|
63840
64288
|
return opResponse(
|
|
63841
64289
|
await createTable(
|
|
63842
64290
|
app,
|
|
@@ -63853,6 +64301,7 @@ function createHandlers(app, getSettings, saveSettings = async () => {
|
|
|
63853
64301
|
...obj(b, "fields") ? { fields: obj(b, "fields") } : {},
|
|
63854
64302
|
columns: list(b, "columns"),
|
|
63855
64303
|
...template !== void 0 ? { rowTemplate: template } : {},
|
|
64304
|
+
...instructions !== void 0 ? { instructions } : {},
|
|
63856
64305
|
...obj(b, "tags") ? { tags: obj(b, "tags") } : {}
|
|
63857
64306
|
},
|
|
63858
64307
|
runOpts(b)
|
|
@@ -63869,6 +64318,7 @@ function createHandlers(app, getSettings, saveSettings = async () => {
|
|
|
63869
64318
|
const target = b.autolink_target;
|
|
63870
64319
|
const description = text3(b, "description");
|
|
63871
64320
|
const template = text3(b, "row_template");
|
|
64321
|
+
const instructions = text3(b, "instructions");
|
|
63872
64322
|
const archive = text3(b, "archive");
|
|
63873
64323
|
const partition = text3(b, "partition");
|
|
63874
64324
|
return opResponse(
|
|
@@ -63889,6 +64339,8 @@ function createHandlers(app, getSettings, saveSettings = async () => {
|
|
|
63889
64339
|
...target === "default" ? { autolinkTarget: null } : typeof target === "boolean" ? { autolinkTarget: target } : {},
|
|
63890
64340
|
// "" removes the template
|
|
63891
64341
|
...template !== void 0 ? { rowTemplate: template === "" ? null : template } : {},
|
|
64342
|
+
// "" removes the instructions
|
|
64343
|
+
...instructions !== void 0 ? { instructions: instructions === "" ? null : instructions } : {},
|
|
63892
64344
|
...obj(b, "tags") ? { tags: obj(b, "tags") } : {},
|
|
63893
64345
|
...optBool(b, "clear_tags") === true ? { clearTags: true } : {},
|
|
63894
64346
|
...archive !== void 0 ? { archive } : {},
|
|
@@ -63936,7 +64388,7 @@ function createHandlers(app, getSettings, saveSettings = async () => {
|
|
|
63936
64388
|
);
|
|
63937
64389
|
},
|
|
63938
64390
|
set_table_bases: async (b) => opResponse(await setTableBases(app, s(), { table: str(b, "table"), bases: strings(b, "bases") }, runOpts(b))),
|
|
63939
|
-
add_constraint: async (b) => opResponse(await addConstraint(app, s(), { table: str(b, "table"), name: str(b, "name"), check: obj(b, "check") }, runOpts(b))),
|
|
64391
|
+
add_constraint: async (b) => opResponse(await addConstraint(app, s(), { table: str(b, "table"), name: str(b, "name"), check: obj(b, "check"), ...text3(b, "hint") !== void 0 ? { hint: text3(b, "hint") } : {} }, runOpts(b))),
|
|
63940
64392
|
drop_constraint: async (b) => opResponse(await dropConstraint(app, s(), { table: str(b, "table"), name: str(b, "name") }, runOpts(b))),
|
|
63941
64393
|
create_view: async (b) => opResponse(
|
|
63942
64394
|
await createView(
|
|
@@ -71693,7 +72145,7 @@ function setUp(o, vault, home, explicit, self) {
|
|
|
71693
72145
|
// src/node/service.ts
|
|
71694
72146
|
init_local();
|
|
71695
72147
|
init_hints();
|
|
71696
|
-
var VERSION = true ? "3.
|
|
72148
|
+
var VERSION = true ? "3.2.0" : "dev";
|
|
71697
72149
|
function parsePort(raw, from = "--port") {
|
|
71698
72150
|
const n = /^\s*\d+\s*$/.test(raw) ? Number(raw) : NaN;
|
|
71699
72151
|
if (n === 0 || Number.isInteger(n) && n >= 1024 && n <= 65535) return n;
|
|
@@ -72731,7 +73183,7 @@ Docs: https://datanotes.dev`;
|
|
|
72731
73183
|
|
|
72732
73184
|
// src/node/cli.ts
|
|
72733
73185
|
init_message();
|
|
72734
|
-
var VERSION2 = true ? "3.
|
|
73186
|
+
var VERSION2 = true ? "3.2.0" : "dev";
|
|
72735
73187
|
var consoleError = console.error;
|
|
72736
73188
|
async function main5(argv = process.argv.slice(2)) {
|
|
72737
73189
|
const [command, ...rest] = argv;
|