datanotes 1.5.0 → 2.0.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 +8 -5
- package/dist/api/index.js +8 -5
- package/dist/datanotes.cjs +160 -819
- package/package.json +1 -1
package/dist/datanotes.cjs
CHANGED
|
@@ -431,9 +431,9 @@ var require_anchors = __commonJS({
|
|
|
431
431
|
}
|
|
432
432
|
return true;
|
|
433
433
|
}
|
|
434
|
-
function anchorNames(
|
|
434
|
+
function anchorNames(root) {
|
|
435
435
|
const anchors = /* @__PURE__ */ new Set();
|
|
436
|
-
visit.visit(
|
|
436
|
+
visit.visit(root, {
|
|
437
437
|
Value(_key, node) {
|
|
438
438
|
if (node.anchor)
|
|
439
439
|
anchors.add(node.anchor);
|
|
@@ -7233,7 +7233,7 @@ var require_public_api = __commonJS({
|
|
|
7233
7233
|
}
|
|
7234
7234
|
return doc;
|
|
7235
7235
|
}
|
|
7236
|
-
function
|
|
7236
|
+
function parse2(src, reviver, options) {
|
|
7237
7237
|
let _reviver = void 0;
|
|
7238
7238
|
if (typeof reviver === "function") {
|
|
7239
7239
|
_reviver = reviver;
|
|
@@ -7274,7 +7274,7 @@ var require_public_api = __commonJS({
|
|
|
7274
7274
|
return value.toString(options);
|
|
7275
7275
|
return new Document.Document(value, _replacer, options).toString(options);
|
|
7276
7276
|
}
|
|
7277
|
-
exports2.parse =
|
|
7277
|
+
exports2.parse = parse2;
|
|
7278
7278
|
exports2.parseAllDocuments = parseAllDocuments;
|
|
7279
7279
|
exports2.parseDocument = parseDocument3;
|
|
7280
7280
|
exports2.stringify = stringify2;
|
|
@@ -7413,9 +7413,6 @@ function dot(a, b) {
|
|
|
7413
7413
|
|
|
7414
7414
|
// src/core/settings.ts
|
|
7415
7415
|
var DEFAULT_SETTINGS = {
|
|
7416
|
-
templateProperty: "template",
|
|
7417
|
-
migrationsProperty: "_migrations",
|
|
7418
|
-
journalFolder: "_meta/migrations",
|
|
7419
7416
|
storeFolder: ".datanotes",
|
|
7420
7417
|
journalRetentionDays: 90,
|
|
7421
7418
|
fileLogEnabled: true,
|
|
@@ -7428,7 +7425,6 @@ var DEFAULT_SETTINGS = {
|
|
|
7428
7425
|
telemetryHeaders: {},
|
|
7429
7426
|
telemetryProtocol: "http/protobuf",
|
|
7430
7427
|
autoRecompute: true,
|
|
7431
|
-
viewNotes: true,
|
|
7432
7428
|
semanticEnabled: false,
|
|
7433
7429
|
semanticProvider: "ollama",
|
|
7434
7430
|
semanticBaseUrl: "",
|
|
@@ -7440,9 +7436,6 @@ var DEFAULT_SETTINGS = {
|
|
|
7440
7436
|
httpServerToken: ""
|
|
7441
7437
|
};
|
|
7442
7438
|
var KEYS = [
|
|
7443
|
-
"templateProperty",
|
|
7444
|
-
"migrationsProperty",
|
|
7445
|
-
"journalFolder",
|
|
7446
7439
|
"storeFolder",
|
|
7447
7440
|
"journalRetentionDays",
|
|
7448
7441
|
"fileLogEnabled",
|
|
@@ -7455,7 +7448,6 @@ var KEYS = [
|
|
|
7455
7448
|
"telemetryHeaders",
|
|
7456
7449
|
"telemetryProtocol",
|
|
7457
7450
|
"autoRecompute",
|
|
7458
|
-
"viewNotes",
|
|
7459
7451
|
"semanticEnabled",
|
|
7460
7452
|
"semanticProvider",
|
|
7461
7453
|
"semanticBaseUrl",
|
|
@@ -7466,19 +7458,6 @@ var KEYS = [
|
|
|
7466
7458
|
"httpServerPort",
|
|
7467
7459
|
"httpServerToken"
|
|
7468
7460
|
];
|
|
7469
|
-
var RESERVED_MIGRATIONS_KEYS = /* @__PURE__ */ new Set([
|
|
7470
|
-
"_protected",
|
|
7471
|
-
"_extend",
|
|
7472
|
-
"_inherits",
|
|
7473
|
-
"_table",
|
|
7474
|
-
"_columns"
|
|
7475
|
-
]);
|
|
7476
|
-
function normalizeMigrationsProperty(out) {
|
|
7477
|
-
const m = out.migrationsProperty;
|
|
7478
|
-
if (m.length === 0 || m === out.templateProperty || RESERVED_MIGRATIONS_KEYS.has(m)) {
|
|
7479
|
-
out.migrationsProperty = DEFAULT_SETTINGS.migrationsProperty;
|
|
7480
|
-
}
|
|
7481
|
-
}
|
|
7482
7461
|
function mergeWithDefaults(loaded) {
|
|
7483
7462
|
const out = { ...DEFAULT_SETTINGS };
|
|
7484
7463
|
for (const key of KEYS) {
|
|
@@ -7486,18 +7465,6 @@ function mergeWithDefaults(loaded) {
|
|
|
7486
7465
|
const raw = loaded[key];
|
|
7487
7466
|
if (raw === void 0) continue;
|
|
7488
7467
|
switch (key) {
|
|
7489
|
-
case "templateProperty": {
|
|
7490
|
-
if (typeof raw === "string" && raw.length > 0) {
|
|
7491
|
-
out.templateProperty = raw;
|
|
7492
|
-
}
|
|
7493
|
-
break;
|
|
7494
|
-
}
|
|
7495
|
-
case "migrationsProperty": {
|
|
7496
|
-
if (typeof raw === "string" && raw.length > 0) {
|
|
7497
|
-
out.migrationsProperty = raw;
|
|
7498
|
-
}
|
|
7499
|
-
break;
|
|
7500
|
-
}
|
|
7501
7468
|
case "telemetryEndpoint": {
|
|
7502
7469
|
if (typeof raw === "string" && /^https?:\/\/\S+$/.test(raw.trim())) {
|
|
7503
7470
|
out.telemetryEndpoint = raw.trim().replace(/\/+$/, "");
|
|
@@ -7544,12 +7511,6 @@ function mergeWithDefaults(loaded) {
|
|
|
7544
7511
|
if (typeof raw === "number" && Number.isInteger(raw) && raw >= 1) out[key] = raw;
|
|
7545
7512
|
break;
|
|
7546
7513
|
}
|
|
7547
|
-
case "journalFolder": {
|
|
7548
|
-
if (typeof raw === "string" && raw.trim().replace(/^\/+|\/+$/g, "").length > 0) {
|
|
7549
|
-
out.journalFolder = raw.trim().replace(/^\/+|\/+$/g, "");
|
|
7550
|
-
}
|
|
7551
|
-
break;
|
|
7552
|
-
}
|
|
7553
7514
|
case "semanticProvider": {
|
|
7554
7515
|
if (typeof raw === "string" && raw in PROVIDER_PRESETS) out.semanticProvider = raw;
|
|
7555
7516
|
break;
|
|
@@ -7585,8 +7546,7 @@ function mergeWithDefaults(loaded) {
|
|
|
7585
7546
|
case "telemetryEnabled":
|
|
7586
7547
|
case "fileLogEnabled":
|
|
7587
7548
|
case "semanticEnabled":
|
|
7588
|
-
case "autoRecompute":
|
|
7589
|
-
case "viewNotes": {
|
|
7549
|
+
case "autoRecompute": {
|
|
7590
7550
|
if (typeof raw === "boolean") {
|
|
7591
7551
|
out[key] = raw;
|
|
7592
7552
|
}
|
|
@@ -7594,7 +7554,6 @@ function mergeWithDefaults(loaded) {
|
|
|
7594
7554
|
}
|
|
7595
7555
|
}
|
|
7596
7556
|
}
|
|
7597
|
-
normalizeMigrationsProperty(out);
|
|
7598
7557
|
return out;
|
|
7599
7558
|
}
|
|
7600
7559
|
|
|
@@ -7834,14 +7793,6 @@ function valuesFromFilename(pattern, basename3) {
|
|
|
7834
7793
|
|
|
7835
7794
|
// src/core/frontmatter.ts
|
|
7836
7795
|
var import_yaml = __toESM(require_dist(), 1);
|
|
7837
|
-
var DEFAULT_MIGRATIONS_KEY = "_migrations";
|
|
7838
|
-
var UnsupportedNestedMappingError = class extends Error {
|
|
7839
|
-
constructor(message, keyPath) {
|
|
7840
|
-
super(message);
|
|
7841
|
-
this.keyPath = keyPath;
|
|
7842
|
-
this.name = "UnsupportedNestedMappingError";
|
|
7843
|
-
}
|
|
7844
|
-
};
|
|
7845
7796
|
var FRONTMATTER_BLOCK = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n([\s\S]*))?$/;
|
|
7846
7797
|
function splitFrontmatter(markdown) {
|
|
7847
7798
|
const m = markdown.match(FRONTMATTER_BLOCK);
|
|
@@ -7850,131 +7801,6 @@ function splitFrontmatter(markdown) {
|
|
|
7850
7801
|
if (yamlText === void 0) return null;
|
|
7851
7802
|
return { yamlText, body: m[2] ?? "" };
|
|
7852
7803
|
}
|
|
7853
|
-
function normalizeFlowStyleOpKeys(entry) {
|
|
7854
|
-
const compound = /^(op|from|to|key):(.+)$/;
|
|
7855
|
-
const out = { ...entry };
|
|
7856
|
-
const toDelete = [];
|
|
7857
|
-
for (const k of Object.keys(out)) {
|
|
7858
|
-
const m = k.match(compound);
|
|
7859
|
-
if (m == null) continue;
|
|
7860
|
-
const fieldRaw = m[1];
|
|
7861
|
-
const suffixRaw = m[2];
|
|
7862
|
-
if (fieldRaw === void 0 || suffixRaw === void 0) continue;
|
|
7863
|
-
const field = fieldRaw;
|
|
7864
|
-
const suffix = suffixRaw.trim();
|
|
7865
|
-
if (suffix.length === 0) continue;
|
|
7866
|
-
const raw = out[k];
|
|
7867
|
-
const preferred = raw !== null && raw !== void 0 && raw !== "" ? raw : suffix;
|
|
7868
|
-
const cur = out[field];
|
|
7869
|
-
if (cur !== void 0 && cur !== null && String(cur) !== String(preferred)) {
|
|
7870
|
-
continue;
|
|
7871
|
-
}
|
|
7872
|
-
out[field] = preferred;
|
|
7873
|
-
toDelete.push(k);
|
|
7874
|
-
}
|
|
7875
|
-
for (const k of toDelete) {
|
|
7876
|
-
delete out[k];
|
|
7877
|
-
}
|
|
7878
|
-
return out;
|
|
7879
|
-
}
|
|
7880
|
-
function migrationEntryMapToObject(map, entryPath, listRoot) {
|
|
7881
|
-
const out = {};
|
|
7882
|
-
for (const pair of map.items) {
|
|
7883
|
-
const kn = pair.key;
|
|
7884
|
-
const k = (0, import_yaml.isScalar)(kn) ? String(kn.value) : String(kn);
|
|
7885
|
-
const v = pair.value;
|
|
7886
|
-
if (v == null) {
|
|
7887
|
-
out[k] = null;
|
|
7888
|
-
continue;
|
|
7889
|
-
}
|
|
7890
|
-
if ((0, import_yaml.isScalar)(v)) {
|
|
7891
|
-
out[k] = v.value;
|
|
7892
|
-
continue;
|
|
7893
|
-
}
|
|
7894
|
-
throw new UnsupportedNestedMappingError(
|
|
7895
|
-
`Invalid value in ${listRoot} entry (path: ${entryPath}.${k})`,
|
|
7896
|
-
`${entryPath}.${k}`
|
|
7897
|
-
);
|
|
7898
|
-
}
|
|
7899
|
-
return normalizeFlowStyleOpKeys(out);
|
|
7900
|
-
}
|
|
7901
|
-
function parseMigrationsSequence(node, listRoot) {
|
|
7902
|
-
if (node == null) return [];
|
|
7903
|
-
if (!(node instanceof import_yaml.YAMLSeq)) {
|
|
7904
|
-
throw new UnsupportedNestedMappingError(
|
|
7905
|
-
`${listRoot} must be a YAML sequence (path: ${listRoot})`,
|
|
7906
|
-
listRoot
|
|
7907
|
-
);
|
|
7908
|
-
}
|
|
7909
|
-
return node.items.map((item, i) => {
|
|
7910
|
-
const p = `${listRoot}[${i}]`;
|
|
7911
|
-
if (item == null || !(item instanceof import_yaml.YAMLMap)) {
|
|
7912
|
-
throw new Error(`${p}: expected a mapping`);
|
|
7913
|
-
}
|
|
7914
|
-
return migrationEntryMapToObject(item, p, listRoot);
|
|
7915
|
-
});
|
|
7916
|
-
}
|
|
7917
|
-
function tableEntryMapToObject(map, entryPath) {
|
|
7918
|
-
const out = {};
|
|
7919
|
-
for (const pair of map.items) {
|
|
7920
|
-
const kn = pair.key;
|
|
7921
|
-
const k = (0, import_yaml.isScalar)(kn) ? String(kn.value) : String(kn);
|
|
7922
|
-
const v = pair.value;
|
|
7923
|
-
if (v == null) {
|
|
7924
|
-
out[k] = null;
|
|
7925
|
-
} else if ((0, import_yaml.isScalar)(v)) {
|
|
7926
|
-
out[k] = v.value;
|
|
7927
|
-
} else if (v instanceof import_yaml.YAMLSeq) {
|
|
7928
|
-
out[k] = v.items.map((item, i) => {
|
|
7929
|
-
if (item == null) return null;
|
|
7930
|
-
if ((0, import_yaml.isScalar)(item)) return item.value;
|
|
7931
|
-
throw new UnsupportedNestedMappingError(
|
|
7932
|
-
`Invalid list item in ${entryPath}.${k}[${i}]`,
|
|
7933
|
-
`${entryPath}.${k}[${i}]`
|
|
7934
|
-
);
|
|
7935
|
-
});
|
|
7936
|
-
} else {
|
|
7937
|
-
throw new UnsupportedNestedMappingError(
|
|
7938
|
-
`Invalid value in ${entryPath}.${k}`,
|
|
7939
|
-
`${entryPath}.${k}`
|
|
7940
|
-
);
|
|
7941
|
-
}
|
|
7942
|
-
}
|
|
7943
|
-
return out;
|
|
7944
|
-
}
|
|
7945
|
-
function parseTableEntriesSequence(node, listRoot) {
|
|
7946
|
-
if (node == null || (0, import_yaml.isScalar)(node) && node.value == null) return [];
|
|
7947
|
-
if (!(node instanceof import_yaml.YAMLSeq)) {
|
|
7948
|
-
throw new UnsupportedNestedMappingError(
|
|
7949
|
-
`${listRoot} must be a YAML sequence (path: ${listRoot})`,
|
|
7950
|
-
listRoot
|
|
7951
|
-
);
|
|
7952
|
-
}
|
|
7953
|
-
return node.items.map((item, i) => {
|
|
7954
|
-
const p = `${listRoot}[${i}]`;
|
|
7955
|
-
if (item == null || !(item instanceof import_yaml.YAMLMap)) {
|
|
7956
|
-
throw new Error(`${p}: expected a mapping`);
|
|
7957
|
-
}
|
|
7958
|
-
return tableEntryMapToObject(item, p);
|
|
7959
|
-
});
|
|
7960
|
-
}
|
|
7961
|
-
var TABLE_SEQUENCE_KEYS = /* @__PURE__ */ new Set(["_table", "_columns"]);
|
|
7962
|
-
function assertPlainValueAtPath(node, keyPath) {
|
|
7963
|
-
if (node == null) return null;
|
|
7964
|
-
if ((0, import_yaml.isScalar)(node)) return node.value;
|
|
7965
|
-
if (node instanceof import_yaml.YAMLMap) {
|
|
7966
|
-
throw new UnsupportedNestedMappingError(
|
|
7967
|
-
`Nested YAML mapping is not supported in v1 (path: ${keyPath})`,
|
|
7968
|
-
keyPath
|
|
7969
|
-
);
|
|
7970
|
-
}
|
|
7971
|
-
if (node instanceof import_yaml.YAMLSeq) {
|
|
7972
|
-
return node.items.map(
|
|
7973
|
-
(item, i) => assertPlainValueAtPath(item, `${keyPath}[${i}]`)
|
|
7974
|
-
);
|
|
7975
|
-
}
|
|
7976
|
-
throw new Error(`Unsupported YAML node at ${keyPath}`);
|
|
7977
|
-
}
|
|
7978
7804
|
function coerceMisparsedYamlWikilinkToString(value) {
|
|
7979
7805
|
let cur = value;
|
|
7980
7806
|
const steps = [];
|
|
@@ -7990,7 +7816,7 @@ function coerceMisparsedYamlWikilinkToString(value) {
|
|
|
7990
7816
|
}
|
|
7991
7817
|
return `[[${cur}]]`;
|
|
7992
7818
|
}
|
|
7993
|
-
function
|
|
7819
|
+
function yamlNodeToPlain(node, keyPath) {
|
|
7994
7820
|
if (node == null) return null;
|
|
7995
7821
|
if ((0, import_yaml.isScalar)(node)) return node.value;
|
|
7996
7822
|
if (node instanceof import_yaml.YAMLMap) {
|
|
@@ -7998,55 +7824,34 @@ function yamlNodeToPlainForChildNote(node, keyPath) {
|
|
|
7998
7824
|
for (const pair of node.items) {
|
|
7999
7825
|
const kn = pair.key;
|
|
8000
7826
|
const k = (0, import_yaml.isScalar)(kn) ? String(kn.value) : String(kn);
|
|
8001
|
-
out[k] =
|
|
7827
|
+
out[k] = yamlNodeToPlain(pair.value, `${keyPath}.${k}`);
|
|
8002
7828
|
}
|
|
8003
7829
|
return out;
|
|
8004
7830
|
}
|
|
8005
7831
|
if (node instanceof import_yaml.YAMLSeq) {
|
|
8006
7832
|
return node.items.map(
|
|
8007
|
-
(item, i) =>
|
|
7833
|
+
(item, i) => yamlNodeToPlain(item, `${keyPath}[${i}]`)
|
|
8008
7834
|
);
|
|
8009
7835
|
}
|
|
8010
7836
|
throw new Error(`Unsupported YAML node at ${keyPath}`);
|
|
8011
7837
|
}
|
|
8012
|
-
function parseYamlBlockToOrdered(yamlText,
|
|
8013
|
-
if (yamlText.trim() === "") return [];
|
|
8014
|
-
const doc = (0, import_yaml.parseDocument)(yamlText);
|
|
8015
|
-
if (doc.errors.length > 0) {
|
|
8016
|
-
const first = doc.errors[0];
|
|
8017
|
-
throw new Error(first?.message ?? "YAML parse error");
|
|
8018
|
-
}
|
|
8019
|
-
const root2 = doc.contents;
|
|
8020
|
-
if (root2 == null) return [];
|
|
8021
|
-
if (!(root2 instanceof import_yaml.YAMLMap)) {
|
|
8022
|
-
throw new Error("Frontmatter root must be a YAML mapping (object)");
|
|
8023
|
-
}
|
|
8024
|
-
const entries = [];
|
|
8025
|
-
for (const pair of root2.items) {
|
|
8026
|
-
const kn = pair.key;
|
|
8027
|
-
const key = (0, import_yaml.isScalar)(kn) ? String(kn.value) : String(kn);
|
|
8028
|
-
const value = key === migrationsKey || key === "_inherits" ? parseMigrationsSequence(pair.value, key) : TABLE_SEQUENCE_KEYS.has(key) ? parseTableEntriesSequence(pair.value, key) : assertPlainValueAtPath(pair.value, key);
|
|
8029
|
-
entries.push([key, value]);
|
|
8030
|
-
}
|
|
8031
|
-
return entries;
|
|
8032
|
-
}
|
|
8033
|
-
function parseYamlBlockToOrderedForChildNote(yamlText, migrationsKey = DEFAULT_MIGRATIONS_KEY, wikilinkStringKeys = /* @__PURE__ */ new Set(["template"])) {
|
|
7838
|
+
function parseYamlBlockToOrdered(yamlText, wikilinkStringKeys = /* @__PURE__ */ new Set()) {
|
|
8034
7839
|
if (yamlText.trim() === "") return [];
|
|
8035
7840
|
const doc = (0, import_yaml.parseDocument)(yamlText);
|
|
8036
7841
|
if (doc.errors.length > 0) {
|
|
8037
7842
|
const first = doc.errors[0];
|
|
8038
7843
|
throw new Error(first?.message ?? "YAML parse error");
|
|
8039
7844
|
}
|
|
8040
|
-
const
|
|
8041
|
-
if (
|
|
8042
|
-
if (!(
|
|
7845
|
+
const root = doc.contents;
|
|
7846
|
+
if (root == null) return [];
|
|
7847
|
+
if (!(root instanceof import_yaml.YAMLMap)) {
|
|
8043
7848
|
throw new Error("Frontmatter root must be a YAML mapping (object)");
|
|
8044
7849
|
}
|
|
8045
7850
|
const entries = [];
|
|
8046
|
-
for (const pair of
|
|
7851
|
+
for (const pair of root.items) {
|
|
8047
7852
|
const kn = pair.key;
|
|
8048
7853
|
const key = (0, import_yaml.isScalar)(kn) ? String(kn.value) : String(kn);
|
|
8049
|
-
let value =
|
|
7854
|
+
let value = yamlNodeToPlain(pair.value, key);
|
|
8050
7855
|
if (wikilinkStringKeys.has(key)) {
|
|
8051
7856
|
value = coerceMisparsedYamlWikilinkToString(value);
|
|
8052
7857
|
}
|
|
@@ -8054,27 +7859,13 @@ function parseYamlBlockToOrderedForChildNote(yamlText, migrationsKey = DEFAULT_M
|
|
|
8054
7859
|
}
|
|
8055
7860
|
return entries;
|
|
8056
7861
|
}
|
|
8057
|
-
function
|
|
7862
|
+
function readOrderedFromMarkdown(markdown, wikilinkStringKeys = /* @__PURE__ */ new Set()) {
|
|
8058
7863
|
const split2 = splitFrontmatter(markdown);
|
|
8059
7864
|
if (!split2) {
|
|
8060
7865
|
return { ordered: [], body: markdown };
|
|
8061
7866
|
}
|
|
8062
7867
|
return {
|
|
8063
|
-
ordered:
|
|
8064
|
-
split2.yamlText,
|
|
8065
|
-
migrationsKey,
|
|
8066
|
-
wikilinkStringKeys
|
|
8067
|
-
),
|
|
8068
|
-
body: split2.body
|
|
8069
|
-
};
|
|
8070
|
-
}
|
|
8071
|
-
function readOrderedFromMarkdown(markdown, migrationsKey = DEFAULT_MIGRATIONS_KEY) {
|
|
8072
|
-
const split2 = splitFrontmatter(markdown);
|
|
8073
|
-
if (!split2) {
|
|
8074
|
-
return { ordered: [], body: markdown };
|
|
8075
|
-
}
|
|
8076
|
-
return {
|
|
8077
|
-
ordered: parseYamlBlockToOrdered(split2.yamlText, migrationsKey),
|
|
7868
|
+
ordered: parseYamlBlockToOrdered(split2.yamlText, wikilinkStringKeys),
|
|
8078
7869
|
body: split2.body
|
|
8079
7870
|
};
|
|
8080
7871
|
}
|
|
@@ -8149,21 +7940,9 @@ function fmReorder(ordered, keysInOrder) {
|
|
|
8149
7940
|
}
|
|
8150
7941
|
return out;
|
|
8151
7942
|
}
|
|
8152
|
-
async function writeFrontmatter(app, file, mutator,
|
|
7943
|
+
async function writeFrontmatter(app, file, mutator, wikilinkStringKeys = /* @__PURE__ */ new Set()) {
|
|
8153
7944
|
const text2 = await app.vault.read(file);
|
|
8154
|
-
const { ordered: before } = readOrderedFromMarkdown(text2,
|
|
8155
|
-
const after = mutator(before);
|
|
8156
|
-
await app.fileManager.processFrontMatter(file, (fm) => {
|
|
8157
|
-
applyOrderedFrontmatter(fm, after);
|
|
8158
|
-
});
|
|
8159
|
-
}
|
|
8160
|
-
async function writeChildFrontmatter(app, file, mutator, migrationsKey = DEFAULT_MIGRATIONS_KEY, wikilinkStringKeys = /* @__PURE__ */ new Set(["template"])) {
|
|
8161
|
-
const text2 = await app.vault.read(file);
|
|
8162
|
-
const { ordered: before } = readOrderedFromMarkdownForChildNote(
|
|
8163
|
-
text2,
|
|
8164
|
-
migrationsKey,
|
|
8165
|
-
wikilinkStringKeys
|
|
8166
|
-
);
|
|
7945
|
+
const { ordered: before } = readOrderedFromMarkdown(text2, wikilinkStringKeys);
|
|
8167
7946
|
const after = mutator(before);
|
|
8168
7947
|
await app.fileManager.processFrontMatter(file, (fm) => {
|
|
8169
7948
|
applyOrderedFrontmatter(fm, after);
|
|
@@ -8202,16 +7981,7 @@ var DEFAULT_TODAY = "{today}";
|
|
|
8202
7981
|
var DEFAULT_SCHEMA = "public";
|
|
8203
7982
|
|
|
8204
7983
|
// src/core/reserved-keys.ts
|
|
8205
|
-
|
|
8206
|
-
return [
|
|
8207
|
-
settings.migrationsProperty,
|
|
8208
|
-
"_protected",
|
|
8209
|
-
"_extend",
|
|
8210
|
-
"_inherits",
|
|
8211
|
-
TABLE_KEY,
|
|
8212
|
-
COLUMNS_KEY
|
|
8213
|
-
];
|
|
8214
|
-
}
|
|
7984
|
+
var TABLE_META_KEYS = [TABLE_KEY, COLUMNS_KEY];
|
|
8215
7985
|
|
|
8216
7986
|
// src/core/validate.ts
|
|
8217
7987
|
var DATE_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
@@ -8344,7 +8114,7 @@ function validateRow(table, row, options, ctx = {}) {
|
|
|
8344
8114
|
const known = /* @__PURE__ */ new Set([
|
|
8345
8115
|
...table.columns.map((c) => c.name),
|
|
8346
8116
|
...table.untypedFields,
|
|
8347
|
-
options.
|
|
8117
|
+
options.tableProperty,
|
|
8348
8118
|
...options.extraAllowedKeys ?? []
|
|
8349
8119
|
]);
|
|
8350
8120
|
for (const [k, v] of row) {
|
|
@@ -8503,7 +8273,7 @@ var COLUMN_ATTRS = /* @__PURE__ */ new Set([
|
|
|
8503
8273
|
"vocabulary",
|
|
8504
8274
|
"inverse"
|
|
8505
8275
|
]);
|
|
8506
|
-
var TABLE_ATTRS = /* @__PURE__ */ new Set(["name", "
|
|
8276
|
+
var TABLE_ATTRS = /* @__PURE__ */ new Set(["name", "partition", "filename", "archive", "exclude", "description", "aliases"]);
|
|
8507
8277
|
var COLUMN_NAME_RE = /^[A-Za-z][A-Za-z0-9_-]*$/;
|
|
8508
8278
|
function isScalarType(t) {
|
|
8509
8279
|
return typeof t === "string" && SCALAR_COLUMN_TYPES.includes(t);
|
|
@@ -8747,43 +8517,17 @@ function parseTableOptions(raw) {
|
|
|
8747
8517
|
}
|
|
8748
8518
|
return out;
|
|
8749
8519
|
}
|
|
8750
|
-
function basenameWithoutMd(path6) {
|
|
8751
|
-
const base = path6.split("/").pop() ?? path6;
|
|
8752
|
-
return base.replace(/\.md$/i, "");
|
|
8753
|
-
}
|
|
8754
|
-
var SCHEMA_BASENAME = "_schema";
|
|
8755
8520
|
var DEFAULT_DATABASE_FOLDER = "Database";
|
|
8756
|
-
function schemaOfTable(schemaPath, databaseFolder = DEFAULT_DATABASE_FOLDER) {
|
|
8757
|
-
const root2 = databaseFolder.replace(/^\/+|\/+$/g, "");
|
|
8758
|
-
if (!schemaPath.startsWith(`${root2}/`)) return DEFAULT_SCHEMA;
|
|
8759
|
-
const rel = schemaPath.slice(root2.length + 1).split("/");
|
|
8760
|
-
return rel.length >= 3 && !rel[0].startsWith("_") ? rel[0] : DEFAULT_SCHEMA;
|
|
8761
|
-
}
|
|
8762
|
-
function isDatabaseTable(schemaPath, databaseFolder = DEFAULT_DATABASE_FOLDER) {
|
|
8763
|
-
const root2 = databaseFolder.replace(/^\/+|\/+$/g, "");
|
|
8764
|
-
if (!schemaPath.startsWith(`${root2}/`)) return false;
|
|
8765
|
-
const rel = schemaPath.slice(root2.length + 1).split("/");
|
|
8766
|
-
return rel[rel.length - 1] === `${SCHEMA_BASENAME}.md` && (rel.length === 2 || rel.length === 3) && !rel[0].startsWith("_");
|
|
8767
|
-
}
|
|
8768
|
-
function tableLayout(schemaPath, options, databaseFolder = DEFAULT_DATABASE_FOLDER) {
|
|
8769
|
-
const cut = schemaPath.lastIndexOf("/");
|
|
8770
|
-
const folder = cut < 0 ? "" : schemaPath.slice(0, cut);
|
|
8771
|
-
const inDatabase = isDatabaseTable(schemaPath, databaseFolder);
|
|
8772
|
-
const join = (a, b) => a === "" ? b : `${a}/${b}`;
|
|
8773
|
-
let rowPath;
|
|
8774
|
-
if (options.path) rowPath = options.path;
|
|
8775
|
-
else if (inDatabase) rowPath = options.partition ? join(folder, options.partition) : folder;
|
|
8776
|
-
let archive;
|
|
8777
|
-
if (options.archive) archive = inDatabase && !options.archive.includes("/") ? join(folder, options.archive) : options.archive;
|
|
8778
|
-
else archive = join(folder, inDatabase ? DEFAULT_ARCHIVE_FOLDER : "_archivio");
|
|
8779
|
-
return { folder, inDatabase, ...rowPath !== void 0 ? { rowPath } : {}, archive };
|
|
8780
|
-
}
|
|
8781
8521
|
var DEFAULT_ARCHIVE_FOLDER = "_archive";
|
|
8782
|
-
function
|
|
8783
|
-
const
|
|
8784
|
-
|
|
8785
|
-
|
|
8786
|
-
|
|
8522
|
+
function catalogLayout(root, ref2, options) {
|
|
8523
|
+
const folder = `${root}/${ref2.catalog}/${ref2.schema}/${ref2.table}`;
|
|
8524
|
+
const archiveName = options.archive && !options.archive.includes("/") ? options.archive : DEFAULT_ARCHIVE_FOLDER;
|
|
8525
|
+
return {
|
|
8526
|
+
folder,
|
|
8527
|
+
inDatabase: true,
|
|
8528
|
+
rowPath: options.partition ? `${folder}/${options.partition}` : folder,
|
|
8529
|
+
archive: options.archive && options.archive.includes("/") ? options.archive : `${folder}/${archiveName}`
|
|
8530
|
+
};
|
|
8787
8531
|
}
|
|
8788
8532
|
function checkGeneratedColumns(specs, known) {
|
|
8789
8533
|
specs.forEach((c, index) => {
|
|
@@ -8811,8 +8555,8 @@ function checkGeneratedColumns(specs, known) {
|
|
|
8811
8555
|
}
|
|
8812
8556
|
});
|
|
8813
8557
|
}
|
|
8814
|
-
function tableDefinitionFromOrdered(schemaPath, ordered, settings) {
|
|
8815
|
-
const reserved =
|
|
8558
|
+
function tableDefinitionFromOrdered(ref2, schemaPath, ordered, settings) {
|
|
8559
|
+
const reserved = new Set(TABLE_META_KEYS);
|
|
8816
8560
|
const options = parseTableOptions(fmGet(ordered, TABLE_KEY));
|
|
8817
8561
|
const specs = parseColumns(fmGet(ordered, COLUMNS_KEY), reserved);
|
|
8818
8562
|
const fieldKeys = ordered.map(([k]) => k).filter((k) => !reserved.has(k));
|
|
@@ -8822,9 +8566,10 @@ function tableDefinitionFromOrdered(schemaPath, ordered, settings) {
|
|
|
8822
8566
|
checkGeneratedColumns(specs, /* @__PURE__ */ new Set([...columnNames, ...fieldKeys]));
|
|
8823
8567
|
return {
|
|
8824
8568
|
schemaPath,
|
|
8825
|
-
name:
|
|
8826
|
-
schema:
|
|
8827
|
-
|
|
8569
|
+
name: ref2.table,
|
|
8570
|
+
schema: ref2.schema,
|
|
8571
|
+
catalog: ref2.catalog,
|
|
8572
|
+
layout: catalogLayout(settings.databaseFolder.replace(/^\/+|\/+$/g, ""), ref2, options),
|
|
8828
8573
|
options,
|
|
8829
8574
|
columns,
|
|
8830
8575
|
untypedFields: fieldKeys.filter((k) => !columnNames.has(k))
|
|
@@ -9052,16 +8797,6 @@ function rowTableFull(model, value) {
|
|
|
9052
8797
|
}
|
|
9053
8798
|
}
|
|
9054
8799
|
var TABLE_PROPERTY_KEYS = ["partition", "filename", "archive", "exclude"];
|
|
9055
|
-
function catalogLayout(root2, ref2, options) {
|
|
9056
|
-
const folder = `${root2}/${ref2.catalog}/${ref2.schema}/${ref2.table}`;
|
|
9057
|
-
const archiveName = options.archive && !options.archive.includes("/") ? options.archive : "_archive";
|
|
9058
|
-
return {
|
|
9059
|
-
folder,
|
|
9060
|
-
inDatabase: true,
|
|
9061
|
-
rowPath: options.partition ? `${folder}/${options.partition}` : folder,
|
|
9062
|
-
archive: options.archive && options.archive.includes("/") ? options.archive : `${folder}/${archiveName}`
|
|
9063
|
-
};
|
|
9064
|
-
}
|
|
9065
8800
|
function entryToOrdered(ref2, entry, settings, model) {
|
|
9066
8801
|
const columns = model ? effectiveColumns(model, ref2, entry) : entry.columns.map((c) => withSelf(c, ref2.full));
|
|
9067
8802
|
const ordered = [[settings.tableProperty, ref2.full]];
|
|
@@ -9103,7 +8838,7 @@ function orderedToEntry(ordered, previous, settings, ctx) {
|
|
|
9103
8838
|
const options = parseTableOptions(fmGet(ordered, TABLE_KEY));
|
|
9104
8839
|
const columnsRaw = fmGet(ordered, COLUMNS_KEY) ?? [];
|
|
9105
8840
|
const columnNames = new Set(columnsRaw.map((c) => String(c.name)));
|
|
9106
|
-
const reserved = /* @__PURE__ */ new Set([settings.tableProperty,
|
|
8841
|
+
const reserved = /* @__PURE__ */ new Set([settings.tableProperty, ...TABLE_META_KEYS]);
|
|
9107
8842
|
const dense = /* @__PURE__ */ new Set();
|
|
9108
8843
|
const defaults = {};
|
|
9109
8844
|
for (const [k, v] of ordered) {
|
|
@@ -9314,11 +9049,11 @@ async function readHashed(app, f) {
|
|
|
9314
9049
|
e.hash ??= contentHash(e.content);
|
|
9315
9050
|
return { content: e.content, hash: e.hash };
|
|
9316
9051
|
}
|
|
9317
|
-
async function readParsed(app, f, key,
|
|
9052
|
+
async function readParsed(app, f, key, parse2) {
|
|
9318
9053
|
const e = await entryFor(app, f);
|
|
9319
9054
|
e.parsed ??= /* @__PURE__ */ new Map();
|
|
9320
9055
|
let p = e.parsed.get(key);
|
|
9321
|
-
if (!p) e.parsed.set(key, p =
|
|
9056
|
+
if (!p) e.parsed.set(key, p = parse2(e.content));
|
|
9322
9057
|
return { ordered: p.ordered.map(([k, v]) => [k, v]), body: p.body };
|
|
9323
9058
|
}
|
|
9324
9059
|
function invalidateFiles(app, paths) {
|
|
@@ -9441,24 +9176,9 @@ async function findInStore(app, settings, id) {
|
|
|
9441
9176
|
}
|
|
9442
9177
|
return entry ? { entry: await unpack(app, settings, entry), undone, path: `${path6}#${id}` } : null;
|
|
9443
9178
|
}
|
|
9444
|
-
var JSON_BLOCK = /```json\n([\s\S]*?)\n```/;
|
|
9445
|
-
function parseLegacyNote(text2, path6) {
|
|
9446
|
-
const m = text2.match(JSON_BLOCK);
|
|
9447
|
-
if (!m) throw new Error(`Journal ${path6} has no JSON block`);
|
|
9448
|
-
const entry = JSON.parse(m[1]);
|
|
9449
|
-
const { ordered } = readOrderedFromMarkdownForChildNote(text2);
|
|
9450
|
-
const undone = ordered.some(([k, v]) => k === "undone" && v === true);
|
|
9451
|
-
const by = ordered.find(([k]) => k === "undone_by")?.[1];
|
|
9452
|
-
return { entry, undone, ...typeof by === "string" ? { undoneBy: by } : {} };
|
|
9453
|
-
}
|
|
9454
9179
|
async function readJournal(app, settings, migrationId) {
|
|
9455
9180
|
const hit = await findInStore(app, settings, migrationId);
|
|
9456
9181
|
if (hit) return hit;
|
|
9457
|
-
const f = app.vault.getAbstractFileByPath(`${settings.journalFolder}/${migrationId}.md`);
|
|
9458
|
-
if (f != null && "extension" in f) {
|
|
9459
|
-
const { entry, undone } = parseLegacyNote(await app.vault.read(f), f.path);
|
|
9460
|
-
return { entry, undone, path: f.path };
|
|
9461
|
-
}
|
|
9462
9182
|
throw new MigrationNotFoundError(migrationId);
|
|
9463
9183
|
}
|
|
9464
9184
|
async function markUndone(app, settings, migrationId, undoneBy, now) {
|
|
@@ -9531,41 +9251,6 @@ async function compactJournal(app, settings, now = /* @__PURE__ */ new Date()) {
|
|
|
9531
9251
|
}
|
|
9532
9252
|
return res;
|
|
9533
9253
|
}
|
|
9534
|
-
async function importLegacyJournal(app, settings, opts = {}) {
|
|
9535
|
-
const res = { imported: 0, skipped: 0, removed: 0, errors: [] };
|
|
9536
|
-
const folder = settings.journalFolder.replace(/^\/+|\/+$/g, "");
|
|
9537
|
-
if (!folder) return res;
|
|
9538
|
-
const notes = app.vault.getMarkdownFiles().filter((f) => f.path.startsWith(`${folder}/`) && !f.path.slice(folder.length + 1).includes("/")).sort((a, b) => a.path.localeCompare(b.path));
|
|
9539
|
-
const known = /* @__PURE__ */ new Map();
|
|
9540
|
-
const done = [];
|
|
9541
|
-
for (const f of notes) {
|
|
9542
|
-
try {
|
|
9543
|
-
const { entry, undone, undoneBy } = parseLegacyNote(await app.vault.read(f), f.path);
|
|
9544
|
-
const file = journalFileFor(settings, entry.migration_id);
|
|
9545
|
-
if (!known.has(file)) known.set(file, await idsIn(app, file));
|
|
9546
|
-
if (known.get(file).has(entry.migration_id)) {
|
|
9547
|
-
res.skipped++;
|
|
9548
|
-
} else {
|
|
9549
|
-
await appendEntry(app, settings, entry);
|
|
9550
|
-
if (undone) await markUndone(app, settings, entry.migration_id, undoneBy ?? "", new Date(entry.executed_at));
|
|
9551
|
-
known.get(file).add(entry.migration_id);
|
|
9552
|
-
res.imported++;
|
|
9553
|
-
}
|
|
9554
|
-
done.push(f);
|
|
9555
|
-
} catch (e) {
|
|
9556
|
-
res.errors.push({ path: f.path, error: e instanceof Error ? e.message : String(e) });
|
|
9557
|
-
}
|
|
9558
|
-
}
|
|
9559
|
-
if (opts.remove !== false) {
|
|
9560
|
-
for (const f of done) {
|
|
9561
|
-
await app.vault.delete(f);
|
|
9562
|
-
res.removed++;
|
|
9563
|
-
}
|
|
9564
|
-
const dir = app.vault.getAbstractFileByPath(folder);
|
|
9565
|
-
if (dir && Array.isArray(dir.children) && dir.children.length === 0) await app.vault.delete(dir, true);
|
|
9566
|
-
}
|
|
9567
|
-
return res;
|
|
9568
|
-
}
|
|
9569
9254
|
|
|
9570
9255
|
// src/core/changeset.ts
|
|
9571
9256
|
function bodyChanges(e) {
|
|
@@ -9657,22 +9342,8 @@ async function ensureFolder(app, folder) {
|
|
|
9657
9342
|
await ensureFolder(app, parentFolder(folder));
|
|
9658
9343
|
await app.vault.createFolder(folder);
|
|
9659
9344
|
}
|
|
9660
|
-
async function readOrderedFor(app, file
|
|
9661
|
-
|
|
9662
|
-
return strict ? readOrderedFromMarkdown(text2, settings.migrationsProperty).ordered : readOrderedFromMarkdownForChildNote(text2, settings.migrationsProperty, /* @__PURE__ */ new Set([settings.templateProperty])).ordered;
|
|
9663
|
-
}
|
|
9664
|
-
async function writeOrderedDiff(app, file, strict, settings, mutate) {
|
|
9665
|
-
if (strict) {
|
|
9666
|
-
await writeFrontmatter(app, file, mutate, settings.migrationsProperty);
|
|
9667
|
-
} else {
|
|
9668
|
-
await writeChildFrontmatter(
|
|
9669
|
-
app,
|
|
9670
|
-
file,
|
|
9671
|
-
mutate,
|
|
9672
|
-
settings.migrationsProperty,
|
|
9673
|
-
/* @__PURE__ */ new Set([settings.templateProperty])
|
|
9674
|
-
);
|
|
9675
|
-
}
|
|
9345
|
+
async function readOrderedFor(app, file) {
|
|
9346
|
+
return readOrderedFromMarkdown(await app.vault.read(file)).ordered;
|
|
9676
9347
|
}
|
|
9677
9348
|
async function moveFile(app, from, to) {
|
|
9678
9349
|
if (from.startsWith(".")) return storeRename(app, from, to);
|
|
@@ -9733,12 +9404,11 @@ async function applyChangeSet(app, settings, cs, now = /* @__PURE__ */ new Date(
|
|
|
9733
9404
|
const order = e.after.map(([k]) => k);
|
|
9734
9405
|
const fmChanged = d.set.length > 0 || d.remove.length > 0 || !same(e.before.map(([k]) => k), order);
|
|
9735
9406
|
if (fmChanged) {
|
|
9736
|
-
await
|
|
9407
|
+
await writeFrontmatter(app, file, (fm) => applyDiff(fm, d.set, d.remove, order));
|
|
9737
9408
|
}
|
|
9738
9409
|
if (bodyChanges(e)) await writeBody(app, file, e.bodyBefore, e.bodyAfter);
|
|
9739
9410
|
rows.push({
|
|
9740
9411
|
path: e.path,
|
|
9741
|
-
strict: e.strict,
|
|
9742
9412
|
before: d.beforeValues,
|
|
9743
9413
|
before_absent: d.beforeAbsent,
|
|
9744
9414
|
before_order: e.before.map(([k]) => k),
|
|
@@ -9830,7 +9500,7 @@ async function undoMigration(app, settings, migrationId, now = /* @__PURE__ */ n
|
|
|
9830
9500
|
conflicts.push({ path: r.path, message: "note no longer exists" });
|
|
9831
9501
|
continue;
|
|
9832
9502
|
}
|
|
9833
|
-
const cur = new Map(await readOrderedFor(app, f
|
|
9503
|
+
const cur = new Map(await readOrderedFor(app, f));
|
|
9834
9504
|
for (const [k, v] of Object.entries(r.after)) {
|
|
9835
9505
|
if (!cur.has(k) || !same(cur.get(k), v)) {
|
|
9836
9506
|
conflicts.push({ path: r.path, message: `"${k}" changed since the operation` });
|
|
@@ -9875,18 +9545,15 @@ async function undoMigration(app, settings, migrationId, now = /* @__PURE__ */ n
|
|
|
9875
9545
|
for (const r of entry.rows) {
|
|
9876
9546
|
const f = fileOrNull(app, currentPath(r.path));
|
|
9877
9547
|
if (Object.keys(r.after).length > 0 || r.after_absent.length > 0 || Object.keys(r.before).length > 0) {
|
|
9878
|
-
await
|
|
9548
|
+
await writeFrontmatter(
|
|
9879
9549
|
app,
|
|
9880
9550
|
f,
|
|
9881
|
-
r.strict,
|
|
9882
|
-
settings,
|
|
9883
9551
|
(fm) => applyDiff(fm, Object.entries(r.before), r.before_absent, r.before_order)
|
|
9884
9552
|
);
|
|
9885
9553
|
}
|
|
9886
9554
|
if (r.body_after !== void 0) await writeBody(app, f, r.body_after, r.body_before);
|
|
9887
9555
|
undoRows.push({
|
|
9888
9556
|
path: currentPath(r.path),
|
|
9889
|
-
strict: r.strict,
|
|
9890
9557
|
before: r.after,
|
|
9891
9558
|
before_absent: r.after_absent,
|
|
9892
9559
|
before_order: [],
|
|
@@ -10104,14 +9771,14 @@ async function readCurrentStates(app, settings, model, touched, only) {
|
|
|
10104
9771
|
const fm = app.metadataCache.getFileCache(f)?.frontmatter;
|
|
10105
9772
|
if (fm && fm[settings.tableProperty] != null) candidates.add(f.path);
|
|
10106
9773
|
}
|
|
10107
|
-
const key =
|
|
9774
|
+
const key = "member-tolerant";
|
|
10108
9775
|
const resolved = /* @__PURE__ */ new Map();
|
|
10109
9776
|
for (const path6 of [...candidates].sort()) {
|
|
10110
9777
|
const file = app.vault.getAbstractFileByPath(path6);
|
|
10111
9778
|
if (file == null || !("extension" in file)) continue;
|
|
10112
9779
|
let raw;
|
|
10113
9780
|
try {
|
|
10114
|
-
const { ordered } = await readParsed(app, file, key, (c) =>
|
|
9781
|
+
const { ordered } = await readParsed(app, file, key, (c) => readOrderedFromMarkdown(c));
|
|
10115
9782
|
raw = fmGet(ordered, settings.tableProperty);
|
|
10116
9783
|
} catch {
|
|
10117
9784
|
continue;
|
|
@@ -10307,13 +9974,13 @@ function linkTo(app, path6, source) {
|
|
|
10307
9974
|
return `[[${clash ? path6.replace(/\.md$/i, "") : base}]]`;
|
|
10308
9975
|
}
|
|
10309
9976
|
function rowKey(settings) {
|
|
10310
|
-
return `row|${settings.
|
|
9977
|
+
return `row|${settings.tableProperty}`;
|
|
10311
9978
|
}
|
|
10312
9979
|
async function readRowFrontmatter(app, settings, path6) {
|
|
10313
9980
|
const f = app.vault.getAbstractFileByPath(path6);
|
|
10314
9981
|
if (!f || !("extension" in f)) return null;
|
|
10315
|
-
const keep = /* @__PURE__ */ new Set([settings.
|
|
10316
|
-
const { ordered } = await readParsed(app, f, rowKey(settings), (t) =>
|
|
9982
|
+
const keep = /* @__PURE__ */ new Set([settings.tableProperty]);
|
|
9983
|
+
const { ordered } = await readParsed(app, f, rowKey(settings), (t) => readOrderedFromMarkdown(t, keep));
|
|
10317
9984
|
return ordered;
|
|
10318
9985
|
}
|
|
10319
9986
|
function inverseTargets(app, specs, ordered, source) {
|
|
@@ -10418,8 +10085,8 @@ async function inverseEditsFor(app, settings, rows, finalPath) {
|
|
|
10418
10085
|
return planInverse(app, settings, ms.model, changes, { known, finalPath });
|
|
10419
10086
|
}
|
|
10420
10087
|
function withFrontmatter(content, ordered, settings) {
|
|
10421
|
-
const keep = /* @__PURE__ */ new Set([settings.
|
|
10422
|
-
const { body } =
|
|
10088
|
+
const keep = /* @__PURE__ */ new Set([settings.tableProperty]);
|
|
10089
|
+
const { body } = readOrderedFromMarkdown(content, keep);
|
|
10423
10090
|
return buildMarkdownWithFrontmatter(ordered, body);
|
|
10424
10091
|
}
|
|
10425
10092
|
var InverseWatcher = class {
|
|
@@ -10521,14 +10188,6 @@ var TableNotFoundError = class extends Error {
|
|
|
10521
10188
|
this.name = "TableNotFoundError";
|
|
10522
10189
|
}
|
|
10523
10190
|
};
|
|
10524
|
-
var AmbiguousTableError = class extends Error {
|
|
10525
|
-
constructor(ref2, paths) {
|
|
10526
|
-
super(`Table name "${ref2}" matches several tables (${paths.join(", ")}); use schema.table`);
|
|
10527
|
-
this.ref = ref2;
|
|
10528
|
-
this.paths = paths;
|
|
10529
|
-
this.name = "AmbiguousTableError";
|
|
10530
|
-
}
|
|
10531
|
-
};
|
|
10532
10191
|
function frontmatterOf(app, file) {
|
|
10533
10192
|
const fm = app.metadataCache.getFileCache(file)?.frontmatter;
|
|
10534
10193
|
return fm && typeof fm === "object" ? fm : void 0;
|
|
@@ -10566,8 +10225,8 @@ function vocabularyOf(app, settings, table) {
|
|
|
10566
10225
|
}
|
|
10567
10226
|
const hit = entry.sets.get(table);
|
|
10568
10227
|
if (hit) return hit;
|
|
10569
|
-
const ms = cachedMetastore(app, { databaseFolder: settings.databaseFolder
|
|
10570
|
-
if (!ms
|
|
10228
|
+
const ms = cachedMetastore(app, { databaseFolder: settings.databaseFolder });
|
|
10229
|
+
if (!ms) return null;
|
|
10571
10230
|
const names = /* @__PURE__ */ new Set();
|
|
10572
10231
|
for (const f of app.vault.getMarkdownFiles()) {
|
|
10573
10232
|
const fm = frontmatterOf(app, f);
|
|
@@ -10586,8 +10245,8 @@ function validationContextFor(app, settings, sourcePath) {
|
|
|
10586
10245
|
tableOfPath: (path6) => {
|
|
10587
10246
|
const f = markdownFile(app, path6);
|
|
10588
10247
|
if (!f) return null;
|
|
10589
|
-
const ms = cachedMetastore(app, { databaseFolder: settings.databaseFolder
|
|
10590
|
-
const full = ms
|
|
10248
|
+
const ms = cachedMetastore(app, { databaseFolder: settings.databaseFolder });
|
|
10249
|
+
const full = ms ? rowTableFull(ms, frontmatterOf(app, f)?.[settings.tableProperty]) : null;
|
|
10591
10250
|
return full ?? null;
|
|
10592
10251
|
}
|
|
10593
10252
|
};
|
|
@@ -10734,7 +10393,7 @@ async function writeDatabaseConfig(app, settings, cfg) {
|
|
|
10734
10393
|
primeMetastore(app, settings, after);
|
|
10735
10394
|
}
|
|
10736
10395
|
async function describeDatabase(app, settings) {
|
|
10737
|
-
const
|
|
10396
|
+
const root = databaseRoot(settings);
|
|
10738
10397
|
const config = await readDatabaseConfig(app, settings);
|
|
10739
10398
|
const ms = await loadMetastore(app, settings);
|
|
10740
10399
|
const catalogs = [];
|
|
@@ -10768,7 +10427,7 @@ async function describeDatabase(app, settings) {
|
|
|
10768
10427
|
}
|
|
10769
10428
|
}
|
|
10770
10429
|
return {
|
|
10771
|
-
root
|
|
10430
|
+
root,
|
|
10772
10431
|
metastore: metastorePath(settings),
|
|
10773
10432
|
journal: storePath(settings, "journal"),
|
|
10774
10433
|
config,
|
|
@@ -10831,9 +10490,6 @@ async function configureDatabase(app, settings, input, saveSettings) {
|
|
|
10831
10490
|
}
|
|
10832
10491
|
}
|
|
10833
10492
|
settings.databaseFolder = newRoot;
|
|
10834
|
-
if (settings.journalFolder === oldRoot || settings.journalFolder.startsWith(`${oldRoot}/`)) {
|
|
10835
|
-
settings.journalFolder = newRoot + settings.journalFolder.slice(oldRoot.length);
|
|
10836
|
-
}
|
|
10837
10493
|
await saveSettings();
|
|
10838
10494
|
}
|
|
10839
10495
|
}
|
|
@@ -10851,15 +10507,8 @@ var OperationInputError = class extends Error {
|
|
|
10851
10507
|
function catalogLoadedTable(settings, ms, ref2) {
|
|
10852
10508
|
const entry = ms.model.catalogs[ref2.catalog].schemas[ref2.schema].tables[ref2.table];
|
|
10853
10509
|
const ordered = entryToOrdered(ref2, entry, settings, ms.model);
|
|
10854
|
-
const
|
|
10855
|
-
|
|
10856
|
-
...base,
|
|
10857
|
-
name: ref2.table,
|
|
10858
|
-
schema: ref2.schema,
|
|
10859
|
-
catalog: ref2.catalog,
|
|
10860
|
-
layout: catalogLayout(settings.databaseFolder.replace(/^\/+|\/+$/g, ""), ref2, base.options)
|
|
10861
|
-
};
|
|
10862
|
-
return { file: ms.file, ordered, def, protectedKeys: /* @__PURE__ */ new Set(), catalog: { ref: ref2, entry, text: ms.text, model: ms.model } };
|
|
10510
|
+
const def = tableDefinitionFromOrdered(ref2, catalogTablePath(settings, ref2.full), ordered, settings);
|
|
10511
|
+
return { file: ms.file, ordered, def, catalog: { ref: ref2, entry, text: ms.text, model: ms.model } };
|
|
10863
10512
|
}
|
|
10864
10513
|
var INDEX_RETRY = { attempts: 8, delayMs: 150 };
|
|
10865
10514
|
async function loadTable(app, settings, ref2) {
|
|
@@ -10871,23 +10520,20 @@ async function loadTable(app, settings, ref2) {
|
|
|
10871
10520
|
await new Promise((r) => setTimeout(r, INDEX_RETRY.delayMs));
|
|
10872
10521
|
}
|
|
10873
10522
|
}
|
|
10874
|
-
function memberKey(settings, t) {
|
|
10875
|
-
return settings.tableProperty;
|
|
10876
|
-
}
|
|
10877
10523
|
function memberEntry(settings, t) {
|
|
10878
10524
|
return [settings.tableProperty, t.catalog.ref.full];
|
|
10879
10525
|
}
|
|
10880
10526
|
async function loadRows(app, settings, t) {
|
|
10881
10527
|
const out = [];
|
|
10882
10528
|
const files = catalogRowFiles(app, settings, t.catalog.ref.full, t.def);
|
|
10883
|
-
const key = `row|${settings.
|
|
10884
|
-
const keep = /* @__PURE__ */ new Set([settings.
|
|
10529
|
+
const key = `row|${settings.tableProperty}`;
|
|
10530
|
+
const keep = /* @__PURE__ */ new Set([settings.tableProperty]);
|
|
10885
10531
|
for (const f of files) {
|
|
10886
10532
|
const { ordered, body } = await readParsed(
|
|
10887
10533
|
app,
|
|
10888
10534
|
f,
|
|
10889
10535
|
key,
|
|
10890
|
-
(text2) =>
|
|
10536
|
+
(text2) => readOrderedFromMarkdown(text2, keep)
|
|
10891
10537
|
);
|
|
10892
10538
|
out.push({ file: f, ordered, body });
|
|
10893
10539
|
}
|
|
@@ -10916,12 +10562,7 @@ function uniqueViolations(columns, rows) {
|
|
|
10916
10562
|
}
|
|
10917
10563
|
return [...byPath.entries()].map(([path6, violations]) => ({ path: path6, violations }));
|
|
10918
10564
|
}
|
|
10919
|
-
|
|
10920
|
-
return new Set(rowReservedKeys(settings));
|
|
10921
|
-
}
|
|
10922
|
-
function reservedNames(settings) {
|
|
10923
|
-
return /* @__PURE__ */ new Set([...rowReservedKeys(settings), settings.templateProperty]);
|
|
10924
|
-
}
|
|
10565
|
+
var META_KEYS = new Set(TABLE_META_KEYS);
|
|
10925
10566
|
function serializeColumn(c) {
|
|
10926
10567
|
const out = { name: c.name, type: c.type };
|
|
10927
10568
|
if (c.items !== void 0) out.items = c.items;
|
|
@@ -10949,7 +10590,7 @@ function serializeColumn(c) {
|
|
|
10949
10590
|
}
|
|
10950
10591
|
function serializeOptions(o) {
|
|
10951
10592
|
const entry = {};
|
|
10952
|
-
for (const k of ["name", "description", "
|
|
10593
|
+
for (const k of ["name", "description", "partition", "filename", "archive"]) {
|
|
10953
10594
|
if (o[k] !== void 0) entry[k] = o[k];
|
|
10954
10595
|
}
|
|
10955
10596
|
if (o.aliases && o.aliases.length > 0) entry.aliases = [...o.aliases];
|
|
@@ -11047,11 +10688,11 @@ async function finish(app, settings, cs, conflicts, violations, opts) {
|
|
|
11047
10688
|
var INVERSE_OPS = /* @__PURE__ */ new Set(["insert_row", "update_rows", "merge_rows", "adopt_rows", "move_rows", "recompute"]);
|
|
11048
10689
|
async function addInverseEdits(app, settings, cs, conflicts) {
|
|
11049
10690
|
if (cs.skipInverse || !INVERSE_OPS.has(cs.op)) return;
|
|
11050
|
-
const keep = /* @__PURE__ */ new Set([settings.
|
|
10691
|
+
const keep = /* @__PURE__ */ new Set([settings.tableProperty]);
|
|
11051
10692
|
const created = new Map(cs.creates.map((c) => [c.path, c]));
|
|
11052
10693
|
const rows = [
|
|
11053
|
-
...cs.edits.
|
|
11054
|
-
...cs.creates.map((c) => ({ path: c.path, before: [], after:
|
|
10694
|
+
...cs.edits.map((e) => ({ path: e.path, before: e.before, after: e.after })),
|
|
10695
|
+
...cs.creates.map((c) => ({ path: c.path, before: [], after: readOrderedFromMarkdown(c.content, keep).ordered }))
|
|
11055
10696
|
];
|
|
11056
10697
|
const moved = new Map(cs.moves.map((m) => [m.from, m.to]));
|
|
11057
10698
|
const plan = await inverseEditsFor(app, settings, rows, (p) => moved.get(p) ?? p);
|
|
@@ -11062,7 +10703,7 @@ async function addInverseEdits(app, settings, cs, conflicts) {
|
|
|
11062
10703
|
const create = created.get(path6);
|
|
11063
10704
|
if (own) own.after = w.after;
|
|
11064
10705
|
else if (create) create.content = withFrontmatter(create.content, w.after, settings);
|
|
11065
|
-
else cs.edits.push({ path: path6,
|
|
10706
|
+
else cs.edits.push({ path: path6, before: w.before, after: w.after });
|
|
11066
10707
|
}
|
|
11067
10708
|
}
|
|
11068
10709
|
var DELTA_OPERATIONS = {
|
|
@@ -11151,7 +10792,7 @@ function addSchemaChange(cs, t, after, settings, target) {
|
|
|
11151
10792
|
return !prev || prev.ref !== c.ref || prev.hierarchy !== c.hierarchy || prev.type !== c.type || prev.items !== c.items || prev.vocabulary !== c.vocabulary;
|
|
11152
10793
|
});
|
|
11153
10794
|
checkColumnRefs(t.catalog.model, ref2.full, touched, ref2.full);
|
|
11154
|
-
def = tableDefinitionFromOrdered(catalogTablePath(settings, ref2.full), entryToOrdered(ref2, entry, settings, t.catalog.model), settings);
|
|
10795
|
+
def = tableDefinitionFromOrdered(ref2, catalogTablePath(settings, ref2.full), entryToOrdered(ref2, entry, settings, t.catalog.model), settings);
|
|
11155
10796
|
} catch (e) {
|
|
11156
10797
|
if (e instanceof MetastoreError) throw new OperationInputError(e.message);
|
|
11157
10798
|
throw e;
|
|
@@ -11247,7 +10888,7 @@ async function createTableImpl(app, settings, input, opts = {}) {
|
|
|
11247
10888
|
}
|
|
11248
10889
|
input = { ...input, columns: [{ ...SYSTEM_ID_SPEC, dense: true }, ...input.columns.filter((c) => c.name !== SYSTEM_ID_COLUMN)] };
|
|
11249
10890
|
}
|
|
11250
|
-
const reserved =
|
|
10891
|
+
const reserved = META_KEYS;
|
|
11251
10892
|
const conflicts = [];
|
|
11252
10893
|
const columns = input.columns.map((raw, i) => {
|
|
11253
10894
|
const { dense: _dense, ...spec } = raw;
|
|
@@ -11276,7 +10917,7 @@ async function createTableImpl(app, settings, input, opts = {}) {
|
|
|
11276
10917
|
extra.filename = `{${tc.name}:${cfg.filename}}`;
|
|
11277
10918
|
}
|
|
11278
10919
|
const given = { ...input.options ?? {} };
|
|
11279
|
-
if (
|
|
10920
|
+
if ("path" in given) throw new OperationInputError(`database tables take "partition", not "path"`);
|
|
11280
10921
|
const catOptions = parseTableOptions(serializeOptions({ ...extra, ...given, name: ref2.table }));
|
|
11281
10922
|
if (!catOptions.filename) {
|
|
11282
10923
|
throw new OperationInputError(`pass "time_column" or options.filename (e.g. "{name}") so rows get file names`);
|
|
@@ -11298,7 +10939,7 @@ async function createTableImpl(app, settings, input, opts = {}) {
|
|
|
11298
10939
|
});
|
|
11299
10940
|
cat = fmSet(cat, TABLE_KEY, serializeOptions(catOptions));
|
|
11300
10941
|
cat = withColumns(cat, columns);
|
|
11301
|
-
tableDefinitionFromOrdered(pseudo, cat, settings);
|
|
10942
|
+
tableDefinitionFromOrdered(ref2, pseudo, cat, settings);
|
|
11302
10943
|
const entry = orderedToEntry(cat, void 0, settings);
|
|
11303
10944
|
if (typeof input.body === "string" && input.body.trim() !== "") entry.row_template = input.body;
|
|
11304
10945
|
checkColumnRefs(model, ref2.full, entry.columns, ref2.full);
|
|
@@ -11339,14 +10980,14 @@ function columnExists(t, name) {
|
|
|
11339
10980
|
}
|
|
11340
10981
|
async function addColumnImpl(app, settings, input, opts = {}) {
|
|
11341
10982
|
const t = await loadTable(app, settings, input.table);
|
|
11342
|
-
const reserved =
|
|
10983
|
+
const reserved = META_KEYS;
|
|
11343
10984
|
const spec = parseColumn(input.column, t.def.columns.length, reserved);
|
|
11344
10985
|
if (columnExists(t, spec.name)) {
|
|
11345
10986
|
throw new OperationInputError(`column "${spec.name}" already exists in table "${t.def.name}"`);
|
|
11346
10987
|
}
|
|
11347
10988
|
const dense = input.dense === true;
|
|
11348
10989
|
let after = withColumns(t.ordered, [...t.def.columns, spec]);
|
|
11349
|
-
if (dense) after = addFieldBeforeMeta(after, spec.name, spec.default ?? null,
|
|
10990
|
+
if (dense) after = addFieldBeforeMeta(after, spec.name, spec.default ?? null, META_KEYS);
|
|
11350
10991
|
const cs = emptyChangeSet("add_column", `add column ${spec.name} to ${t.def.name}`, t.file.path);
|
|
11351
10992
|
addSchemaChange(cs, t, after, settings);
|
|
11352
10993
|
const violations = [];
|
|
@@ -11367,7 +11008,6 @@ async function addColumnImpl(app, settings, input, opts = {}) {
|
|
|
11367
11008
|
if (dense && !has) {
|
|
11368
11009
|
cs.edits.push({
|
|
11369
11010
|
path: r.file.path,
|
|
11370
|
-
strict: false,
|
|
11371
11011
|
before: r.ordered,
|
|
11372
11012
|
after: fmAdd(r.ordered, spec.name, spec.default ?? null)
|
|
11373
11013
|
});
|
|
@@ -11382,12 +11022,11 @@ async function renameColumnImpl(app, settings, input, opts = {}) {
|
|
|
11382
11022
|
const t = await loadTable(app, settings, input.table);
|
|
11383
11023
|
const from = input.from;
|
|
11384
11024
|
const to = assertColumnName(input.to, `"to"`);
|
|
11385
|
-
const reserved =
|
|
11025
|
+
const reserved = META_KEYS;
|
|
11386
11026
|
if (!columnExists(t, from)) throw new OperationInputError(`column "${from}" not found in table "${t.def.name}"`);
|
|
11387
11027
|
if (reserved.has(to)) throw new OperationInputError(`"${to}" is a reserved key`);
|
|
11388
11028
|
if (columnExists(t, to)) throw new OperationInputError(`column "${to}" already exists in table "${t.def.name}"`);
|
|
11389
11029
|
const conflicts = [];
|
|
11390
|
-
if (t.protectedKeys.has(from)) conflicts.push({ path: t.file.path, message: `"${from}" is protected` });
|
|
11391
11030
|
const columns = t.def.columns.map((c) => c.name === from ? { ...c, name: to } : c);
|
|
11392
11031
|
let after = t.def.columns.some((c) => c.name === from) ? withColumns(t.ordered, columns) : t.ordered;
|
|
11393
11032
|
after = fmRename(after, from, to);
|
|
@@ -11406,7 +11045,7 @@ async function renameColumnImpl(app, settings, input, opts = {}) {
|
|
|
11406
11045
|
}
|
|
11407
11046
|
next = fmDelete(next, to);
|
|
11408
11047
|
}
|
|
11409
|
-
cs.edits.push({ path: r.file.path,
|
|
11048
|
+
cs.edits.push({ path: r.file.path, before: r.ordered, after: fmRename(next, from, to) });
|
|
11410
11049
|
}
|
|
11411
11050
|
return finish(app, settings, cs, conflicts, [], opts);
|
|
11412
11051
|
}
|
|
@@ -11427,7 +11066,6 @@ async function renameValueImpl(app, settings, input, opts = {}) {
|
|
|
11427
11066
|
}
|
|
11428
11067
|
const conflicts = [];
|
|
11429
11068
|
if (values.includes(to)) conflicts.push({ path: t.file.path, message: `"${to}" is already a value of ${col.name}` });
|
|
11430
|
-
if (t.protectedKeys.has(col.name)) conflicts.push({ path: t.file.path, message: `"${col.name}" is protected` });
|
|
11431
11069
|
const spec = {
|
|
11432
11070
|
...col,
|
|
11433
11071
|
values: values.map((v) => v === from ? to : v),
|
|
@@ -11444,7 +11082,7 @@ async function renameValueImpl(app, settings, input, opts = {}) {
|
|
|
11444
11082
|
if (isEmptyValue(v)) continue;
|
|
11445
11083
|
const next = swap(v);
|
|
11446
11084
|
if (JSON.stringify(next) === JSON.stringify(v)) continue;
|
|
11447
|
-
cs.edits.push({ path: r.file.path,
|
|
11085
|
+
cs.edits.push({ path: r.file.path, before: r.ordered, after: fmSet(r.ordered, col.name, next) });
|
|
11448
11086
|
}
|
|
11449
11087
|
return finish(app, settings, cs, conflicts, [], opts);
|
|
11450
11088
|
}
|
|
@@ -11453,14 +11091,13 @@ async function dropColumnImpl(app, settings, input, opts = {}) {
|
|
|
11453
11091
|
const name = input.name;
|
|
11454
11092
|
if (!columnExists(t, name)) throw new OperationInputError(`column "${name}" not found in table "${t.def.name}"`);
|
|
11455
11093
|
const conflicts = [];
|
|
11456
|
-
if (t.protectedKeys.has(name)) conflicts.push({ path: t.file.path, message: `"${name}" is protected` });
|
|
11457
11094
|
let after = t.def.columns.some((c) => c.name === name) ? withColumns(t.ordered, t.def.columns.filter((c) => c.name !== name)) : t.ordered;
|
|
11458
11095
|
after = fmDelete(after, name);
|
|
11459
11096
|
const cs = emptyChangeSet("drop_column", `drop column ${name} from ${t.def.name}`, t.file.path);
|
|
11460
11097
|
addSchemaChange(cs, t, after, settings);
|
|
11461
11098
|
for (const r of await loadRows(app, settings, t)) {
|
|
11462
11099
|
if (!r.ordered.some(([k]) => k === name)) continue;
|
|
11463
|
-
cs.edits.push({ path: r.file.path,
|
|
11100
|
+
cs.edits.push({ path: r.file.path, before: r.ordered, after: fmDelete(r.ordered, name) });
|
|
11464
11101
|
}
|
|
11465
11102
|
return finish(app, settings, cs, conflicts, [], opts);
|
|
11466
11103
|
}
|
|
@@ -11478,12 +11115,12 @@ async function alterColumnImpl(app, settings, input, opts = {}) {
|
|
|
11478
11115
|
if (v === null) delete merged[k];
|
|
11479
11116
|
else merged[k] = v;
|
|
11480
11117
|
}
|
|
11481
|
-
const spec = parseColumn(merged, idx,
|
|
11118
|
+
const spec = parseColumn(merged, idx, META_KEYS);
|
|
11482
11119
|
const columns = t.def.columns.map((c, i) => i === idx ? spec : c);
|
|
11483
|
-
const reserved =
|
|
11120
|
+
const reserved = META_KEYS;
|
|
11484
11121
|
let after = withColumns(t.ordered, columns);
|
|
11485
11122
|
const makeDense = dense === true && !old.dense;
|
|
11486
|
-
if (makeDense) after = addFieldBeforeMeta(after, spec.name, spec.default ?? null,
|
|
11123
|
+
if (makeDense) after = addFieldBeforeMeta(after, spec.name, spec.default ?? null, META_KEYS);
|
|
11487
11124
|
if (dense === false && old.dense) after = fmDelete(after, spec.name);
|
|
11488
11125
|
const cs = emptyChangeSet("alter_column", `alter column ${spec.name} in ${t.def.name}`, t.file.path);
|
|
11489
11126
|
addSchemaChange(cs, t, after, settings);
|
|
@@ -11496,7 +11133,7 @@ async function alterColumnImpl(app, settings, input, opts = {}) {
|
|
|
11496
11133
|
let v = fmGet(r.ordered, spec.name);
|
|
11497
11134
|
if (widen && typeof v === "string" && /^\d{4}-\d{2}-\d{2}$/.test(v)) {
|
|
11498
11135
|
const cast = normalizeDatetime(`${v}T00:00`, tz);
|
|
11499
|
-
cs.edits.push({ path: r.file.path,
|
|
11136
|
+
cs.edits.push({ path: r.file.path, before: r.ordered, after: fmSet(r.ordered, spec.name, cast) });
|
|
11500
11137
|
v = cast;
|
|
11501
11138
|
}
|
|
11502
11139
|
if (isEmptyValue(v)) {
|
|
@@ -11507,7 +11144,7 @@ async function alterColumnImpl(app, settings, input, opts = {}) {
|
|
|
11507
11144
|
violations.push({ path: r.file.path, violations: validateValue(spec, v, validationContextFor(app, settings, r.file.path)) });
|
|
11508
11145
|
}
|
|
11509
11146
|
if (makeDense && !has) {
|
|
11510
|
-
cs.edits.push({ path: r.file.path,
|
|
11147
|
+
cs.edits.push({ path: r.file.path, before: r.ordered, after: fmAdd(r.ordered, spec.name, spec.default ?? null) });
|
|
11511
11148
|
}
|
|
11512
11149
|
}
|
|
11513
11150
|
return finish(app, settings, cs, [], violations, opts);
|
|
@@ -11669,10 +11306,9 @@ async function loadTableAsOf(app, settings, table, asOf2) {
|
|
|
11669
11306
|
const file = ms?.file ?? pseudoFile(metastorePath(settings));
|
|
11670
11307
|
const t = catalogLoadedTable(settings, { file, text: "", model: modelWith(ref2, state, ms?.model.bases ?? {}) }, ref2);
|
|
11671
11308
|
const rows = [...state.files.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([path6, f]) => {
|
|
11672
|
-
const { ordered, body } =
|
|
11309
|
+
const { ordered, body } = readOrderedFromMarkdown(
|
|
11673
11310
|
f.content,
|
|
11674
|
-
settings.
|
|
11675
|
-
/* @__PURE__ */ new Set([settings.templateProperty, settings.tableProperty])
|
|
11311
|
+
/* @__PURE__ */ new Set([settings.tableProperty])
|
|
11676
11312
|
);
|
|
11677
11313
|
return { file: pseudoFile(path6), ordered, body };
|
|
11678
11314
|
});
|
|
@@ -11714,12 +11350,11 @@ var restoreTable = instrumented("restore_table", restoreTableImpl, (i) => ({
|
|
|
11714
11350
|
timestamp: i.timestamp
|
|
11715
11351
|
}));
|
|
11716
11352
|
function rowValues(content, settings) {
|
|
11717
|
-
const { ordered } =
|
|
11353
|
+
const { ordered } = readOrderedFromMarkdown(
|
|
11718
11354
|
content,
|
|
11719
|
-
settings.
|
|
11720
|
-
/* @__PURE__ */ new Set([settings.templateProperty, settings.tableProperty])
|
|
11355
|
+
/* @__PURE__ */ new Set([settings.tableProperty])
|
|
11721
11356
|
);
|
|
11722
|
-
return Object.fromEntries(ordered.filter(([k]) => k !== settings.tableProperty
|
|
11357
|
+
return Object.fromEntries(ordered.filter(([k]) => k !== settings.tableProperty));
|
|
11723
11358
|
}
|
|
11724
11359
|
async function tableChanges(app, settings, input) {
|
|
11725
11360
|
const ref2 = await historyTableName(app, settings, input.table);
|
|
@@ -11886,82 +11521,6 @@ function resolveThisTokens(query, host) {
|
|
|
11886
11521
|
return walk(query);
|
|
11887
11522
|
}
|
|
11888
11523
|
|
|
11889
|
-
// src/core/view-notes.ts
|
|
11890
|
-
var VIEW_NOTE_KEY = "view";
|
|
11891
|
-
var GENERATED_MARK = "Generated by Datanotes";
|
|
11892
|
-
function root(settings) {
|
|
11893
|
-
return settings.databaseFolder.replace(/^\/+|\/+$/g, "");
|
|
11894
|
-
}
|
|
11895
|
-
function viewNotePath(settings, ref2) {
|
|
11896
|
-
return `${root(settings)}/${ref2.catalog}/${ref2.schema}/${ref2.table}.md`;
|
|
11897
|
-
}
|
|
11898
|
-
function viewNoteText(ref2, view) {
|
|
11899
|
-
const lines = ["---", `${VIEW_NOTE_KEY}: ${ref2.full}`];
|
|
11900
|
-
if (view.aliases && view.aliases.length > 0) {
|
|
11901
|
-
lines.push("aliases:", ...view.aliases.map((a) => ` - ${JSON.stringify(a)}`));
|
|
11902
|
-
}
|
|
11903
|
-
lines.push("---", "");
|
|
11904
|
-
if (view.comment) lines.push(...view.comment.split("\n").map((l) => `> ${l}`), "");
|
|
11905
|
-
lines.push("```datanotes", `view: ${ref2.full}`, "```", "");
|
|
11906
|
-
lines.push(`%% ${GENERATED_MARK} from the view in database.yaml: change the view (create_view with replace, drop_view), not this note. %%`, "");
|
|
11907
|
-
return lines.join("\n");
|
|
11908
|
-
}
|
|
11909
|
-
function viewOfNote(text2) {
|
|
11910
|
-
const m = /^---\r?\n([\s\S]*?)\r?\n---/.exec(text2);
|
|
11911
|
-
if (!m) return null;
|
|
11912
|
-
const line = m[1].split(/\r?\n/).find((l) => l.startsWith(`${VIEW_NOTE_KEY}:`));
|
|
11913
|
-
return line ? line.slice(VIEW_NOTE_KEY.length + 1).trim().replace(/^["']|["']$/g, "") || null : null;
|
|
11914
|
-
}
|
|
11915
|
-
async function viewNoteBlocked(app, settings, ref2) {
|
|
11916
|
-
if (settings.viewNotes === false) return null;
|
|
11917
|
-
const path6 = viewNotePath(settings, ref2);
|
|
11918
|
-
const f = app.vault.getAbstractFileByPath(path6);
|
|
11919
|
-
if (f == null) return null;
|
|
11920
|
-
if (!("extension" in f)) return path6;
|
|
11921
|
-
return viewOfNote(await app.vault.read(f)) === ref2.full ? null : path6;
|
|
11922
|
-
}
|
|
11923
|
-
async function syncViewNotes(app, settings, model) {
|
|
11924
|
-
const out = { created: [], updated: [], removed: [], skipped: [] };
|
|
11925
|
-
const ms = model ?? (await loadMetastore(app, settings))?.model ?? null;
|
|
11926
|
-
if (!ms) return out;
|
|
11927
|
-
const wanted = /* @__PURE__ */ new Map();
|
|
11928
|
-
if (settings.viewNotes !== false) {
|
|
11929
|
-
for (const { ref: ref2, view } of catalogViews(ms)) wanted.set(viewNotePath(settings, ref2), viewNoteText(ref2, view));
|
|
11930
|
-
}
|
|
11931
|
-
for (const [path6, text2] of wanted) {
|
|
11932
|
-
const f = app.vault.getAbstractFileByPath(path6);
|
|
11933
|
-
if (f == null) {
|
|
11934
|
-
await ensureFolder(app, parentFolder(path6));
|
|
11935
|
-
await app.vault.create(path6, text2);
|
|
11936
|
-
out.created.push(path6);
|
|
11937
|
-
continue;
|
|
11938
|
-
}
|
|
11939
|
-
if (!("extension" in f)) {
|
|
11940
|
-
out.skipped.push(path6);
|
|
11941
|
-
continue;
|
|
11942
|
-
}
|
|
11943
|
-
const current2 = await app.vault.read(f);
|
|
11944
|
-
const expected = viewOfNote(text2);
|
|
11945
|
-
if (viewOfNote(current2) !== expected) {
|
|
11946
|
-
out.skipped.push(path6);
|
|
11947
|
-
continue;
|
|
11948
|
-
}
|
|
11949
|
-
if (current2 !== text2) {
|
|
11950
|
-
await app.vault.process(f, () => text2);
|
|
11951
|
-
out.updated.push(path6);
|
|
11952
|
-
}
|
|
11953
|
-
}
|
|
11954
|
-
const depth = root(settings).split("/").length + 3;
|
|
11955
|
-
for (const f of app.vault.getMarkdownFiles()) {
|
|
11956
|
-
if (wanted.has(f.path) || !f.path.startsWith(`${root(settings)}/`) || f.path.split("/").length !== depth) continue;
|
|
11957
|
-
const text2 = await app.vault.read(f);
|
|
11958
|
-
if (viewOfNote(text2) == null || !text2.includes(GENERATED_MARK)) continue;
|
|
11959
|
-
await trash(app, f);
|
|
11960
|
-
out.removed.push(f.path);
|
|
11961
|
-
}
|
|
11962
|
-
return out;
|
|
11963
|
-
}
|
|
11964
|
-
|
|
11965
11524
|
// src/core/catalog-ops.ts
|
|
11966
11525
|
var IDENT2 = /^[a-z][a-z0-9_]*$/;
|
|
11967
11526
|
function ident(kind, value) {
|
|
@@ -12063,8 +11622,6 @@ async function createViewImpl(app, settings, input, opts = {}) {
|
|
|
12063
11622
|
const conflicts = [];
|
|
12064
11623
|
if (sch?.tables[ref2.table]) conflicts.push({ path: ref2.full, message: `${ref2.full} is a table` });
|
|
12065
11624
|
if (sch?.views[ref2.table] && input.replace !== true) conflicts.push({ path: ref2.full, message: `${ref2.full} already exists (pass replace)` });
|
|
12066
|
-
const blocked = await viewNoteBlocked(app, settings, ref2);
|
|
12067
|
-
if (blocked) conflicts.push({ path: blocked, message: `${blocked} exists and is not this view's note: rename it or choose another view name` });
|
|
12068
11625
|
if (hasThisTokens(input.query)) viewQueryToSelect(input.query);
|
|
12069
11626
|
else await select(app, settings, { ...viewQueryToSelect(input.query), limit: 1 });
|
|
12070
11627
|
for (const [k, v] of Object.entries(input.labels ?? {})) {
|
|
@@ -12078,11 +11635,7 @@ async function createViewImpl(app, settings, input, opts = {}) {
|
|
|
12078
11635
|
};
|
|
12079
11636
|
const cs = emptyChangeSet("create_view", `create view ${ref2.full}`, `${metastorePath(settings)}#${ref2.full}`);
|
|
12080
11637
|
cs.texts.push({ path: metastorePath(settings), before: text2, after: setViewEntry(text2, ref2, view) });
|
|
12081
|
-
return
|
|
12082
|
-
}
|
|
12083
|
-
async function withViewNotes(app, settings, r) {
|
|
12084
|
-
if (r.ok && !r.dryRun) await syncViewNotes(app, settings);
|
|
12085
|
-
return r;
|
|
11638
|
+
return finish(app, settings, cs, conflicts, [], opts);
|
|
12086
11639
|
}
|
|
12087
11640
|
async function dropViewImpl(app, settings, input, opts = {}) {
|
|
12088
11641
|
const { text: text2, model } = await metastoreOrEmpty(app, settings);
|
|
@@ -12090,7 +11643,7 @@ async function dropViewImpl(app, settings, input, opts = {}) {
|
|
|
12090
11643
|
if (!ref2) throw new TableNotFoundError(input.view);
|
|
12091
11644
|
const cs = emptyChangeSet("drop_view", `drop view ${ref2.full}`, `${metastorePath(settings)}#${ref2.full}`);
|
|
12092
11645
|
cs.texts.push({ path: metastorePath(settings), before: text2, after: setViewEntry(text2, ref2, null) });
|
|
12093
|
-
return
|
|
11646
|
+
return finish(app, settings, cs, [], [], opts);
|
|
12094
11647
|
}
|
|
12095
11648
|
var createView = instrumented("create_view", createViewImpl, (i) => ({ name: i.name, catalog: i.catalog, schema: i.schema }));
|
|
12096
11649
|
var dropView = instrumented("drop_view", dropViewImpl, (i) => ({ view: i.view }));
|
|
@@ -12347,9 +11900,9 @@ async function planInheritedRows(app, settings, model, text2, refs, rewrite, cs)
|
|
|
12347
11900
|
let after = rewrite(r.ordered);
|
|
12348
11901
|
for (const c of dense) if (!after.some(([k]) => k === c.name)) after = fmSet(after, c.name, c.default ?? null);
|
|
12349
11902
|
after = await fillIdentities(app, settings, t, after, r.file.path);
|
|
12350
|
-
const v = validateRow(t.def, after, {
|
|
11903
|
+
const v = validateRow(t.def, after, { tableProperty: settings.tableProperty }, validationContextFor(app, settings, r.file.path));
|
|
12351
11904
|
if (v.length > 0) violations.push({ path: r.file.path, violations: v });
|
|
12352
|
-
if (JSON.stringify(after) !== JSON.stringify(r.ordered)) cs.edits.push({ path: r.file.path,
|
|
11905
|
+
if (JSON.stringify(after) !== JSON.stringify(r.ordered)) cs.edits.push({ path: r.file.path, before: r.ordered, after });
|
|
12353
11906
|
}
|
|
12354
11907
|
}
|
|
12355
11908
|
return violations;
|
|
@@ -12801,7 +12354,7 @@ function knownKeys(t, settings) {
|
|
|
12801
12354
|
return /* @__PURE__ */ new Set([
|
|
12802
12355
|
...t.def.columns.map((c) => c.name),
|
|
12803
12356
|
...t.def.untypedFields,
|
|
12804
|
-
|
|
12357
|
+
settings.tableProperty,
|
|
12805
12358
|
"path"
|
|
12806
12359
|
]);
|
|
12807
12360
|
}
|
|
@@ -12881,18 +12434,18 @@ async function resolveWithin(app, settings, t, where) {
|
|
|
12881
12434
|
const rows = await loadRows(app, settings, target);
|
|
12882
12435
|
const names = new Set(rows.map((r) => basenameOf(r.file.path)));
|
|
12883
12436
|
const raw = cond.within;
|
|
12884
|
-
let
|
|
12885
|
-
if (
|
|
12437
|
+
let root = linkName(raw) ?? (typeof raw === "string" ? basenameOf(raw.trim()) : null);
|
|
12438
|
+
if (root != null && !names.has(root)) {
|
|
12886
12439
|
const hit = rows.find((r) => r.ordered.some(([k, v]) => (k === "name" || k === "title") && v === raw));
|
|
12887
|
-
|
|
12440
|
+
root = hit ? basenameOf(hit.file.path) : null;
|
|
12888
12441
|
}
|
|
12889
|
-
if (
|
|
12442
|
+
if (root == null) throw new OperationInputError(`"within": no row of ${spec.ref} named ${JSON.stringify(raw)}`);
|
|
12890
12443
|
const children = /* @__PURE__ */ new Map();
|
|
12891
12444
|
for (const r of rows) {
|
|
12892
12445
|
const p = linkName(fmGet(r.ordered, h.name));
|
|
12893
12446
|
if (p) children.set(p, [...children.get(p) ?? [], basenameOf(r.file.path)]);
|
|
12894
12447
|
}
|
|
12895
|
-
const subtree = /* @__PURE__ */ new Set([
|
|
12448
|
+
const subtree = /* @__PURE__ */ new Set([root]);
|
|
12896
12449
|
for (const n of subtree) for (const c of children.get(n) ?? []) subtree.add(c);
|
|
12897
12450
|
const { within: _w, ...rest } = cond;
|
|
12898
12451
|
out ??= { ...where };
|
|
@@ -13066,7 +12619,7 @@ async function selectOn(app, settings, input, hist) {
|
|
|
13066
12619
|
const tz = (await readDatabaseConfig(app, settings)).timezone;
|
|
13067
12620
|
const now = /* @__PURE__ */ new Date();
|
|
13068
12621
|
const get = rowGetter(app, t, settings, tz);
|
|
13069
|
-
const hidden2 = /* @__PURE__ */ new Set([settings.
|
|
12622
|
+
const hidden2 = /* @__PURE__ */ new Set([settings.tableProperty]);
|
|
13070
12623
|
const specs = new Map(t.def.columns.map((c) => [c.name, c]));
|
|
13071
12624
|
for (const c of [...input.columns ?? [], ...input.expand ?? []]) {
|
|
13072
12625
|
if (!known.has(c)) throw new OperationInputError(`unknown column: "${c}"`);
|
|
@@ -13209,7 +12762,7 @@ async function checkImpl(app, settings, input) {
|
|
|
13209
12762
|
);
|
|
13210
12763
|
for (const r of rows) {
|
|
13211
12764
|
const v = [
|
|
13212
|
-
...validateRow(t.def, r.ordered, {
|
|
12765
|
+
...validateRow(t.def, r.ordered, { tableProperty: settings.tableProperty }, validationContextFor(app, settings, r.file.path)),
|
|
13213
12766
|
...unique.get(r.file.path) ?? [],
|
|
13214
12767
|
...constraintViolations(t, settings, r.file.path, r.ordered),
|
|
13215
12768
|
...generatedMismatches(t, settings, r)
|
|
@@ -13253,7 +12806,7 @@ function rowTemplate(t, values) {
|
|
|
13253
12806
|
function planInsert(app, settings, t, input, env) {
|
|
13254
12807
|
const known = knownKeys(t, settings);
|
|
13255
12808
|
known.delete("path");
|
|
13256
|
-
known.delete(
|
|
12809
|
+
known.delete(settings.tableProperty);
|
|
13257
12810
|
for (const k of Object.keys(input.values)) {
|
|
13258
12811
|
if (!known.has(k)) throw new OperationInputError(`unknown column "${k}" for table "${t.def.name}"`);
|
|
13259
12812
|
}
|
|
@@ -13286,8 +12839,8 @@ function planInsert(app, settings, t, input, env) {
|
|
|
13286
12839
|
const values = new Map(ordered);
|
|
13287
12840
|
let path6 = input.path;
|
|
13288
12841
|
if (path6 == null) {
|
|
13289
|
-
if (
|
|
13290
|
-
throw new OperationInputError(`table "${t.def.name}" has no
|
|
12842
|
+
if (!t.def.options.filename) {
|
|
12843
|
+
throw new OperationInputError(`table "${t.def.name}" has no filename pattern; pass "path"`);
|
|
13291
12844
|
}
|
|
13292
12845
|
const base = `${renderPathTemplate(t.def.layout.rowPath, values)}/${renderPathTemplate(t.def.options.filename, values)}`;
|
|
13293
12846
|
path6 = `${base}.md`;
|
|
@@ -13300,7 +12853,7 @@ function planInsert(app, settings, t, input, env) {
|
|
|
13300
12853
|
ordered = withIdentity(t, ordered, path6, false, { now, tz });
|
|
13301
12854
|
ordered = withGenerated(t, settings, ordered, path6);
|
|
13302
12855
|
const violations = [
|
|
13303
|
-
...validateRow(t.def, ordered, {
|
|
12856
|
+
...validateRow(t.def, ordered, { tableProperty: settings.tableProperty }, validationContextFor(app, settings, path6)),
|
|
13304
12857
|
...constraintViolations(t, settings, path6, ordered)
|
|
13305
12858
|
];
|
|
13306
12859
|
return { path: path6, ordered, conflicts, violations };
|
|
@@ -13368,7 +12921,7 @@ async function mergeRowsImpl(app, settings, input, opts = {}) {
|
|
|
13368
12921
|
let after = r.ordered;
|
|
13369
12922
|
for (const [k, v] of normalized) {
|
|
13370
12923
|
if (input.on.includes(k)) continue;
|
|
13371
|
-
if (!known.has(k) || k === "path" || k ===
|
|
12924
|
+
if (!known.has(k) || k === "path" || k === settings.tableProperty) throw new OperationInputError(`unknown column "${k}" for table "${t.def.name}"`);
|
|
13372
12925
|
if (computed.has(k)) throw new OperationInputError(`"${k}" is a generated column: its value is computed`);
|
|
13373
12926
|
after = fmSet(after, k, v);
|
|
13374
12927
|
}
|
|
@@ -13383,7 +12936,7 @@ async function mergeRowsImpl(app, settings, input, opts = {}) {
|
|
|
13383
12936
|
return validateValue(spec, v, ctx);
|
|
13384
12937
|
});
|
|
13385
12938
|
violations.push({ path: r.file.path, violations: [...rowViolations, ...constraintViolations(t, settings, r.file.path, after)] });
|
|
13386
|
-
cs.edits.push({ path: r.file.path,
|
|
12939
|
+
cs.edits.push({ path: r.file.path, before: r.ordered, after });
|
|
13387
12940
|
continue;
|
|
13388
12941
|
}
|
|
13389
12942
|
if (input.whenNotMatched === "ignore") continue;
|
|
@@ -13395,7 +12948,7 @@ async function mergeRowsImpl(app, settings, input, opts = {}) {
|
|
|
13395
12948
|
}
|
|
13396
12949
|
if (t.def.columns.some((c) => c.unique)) {
|
|
13397
12950
|
const afterByPath = new Map(cs.edits.map((e) => [e.path, e.after]));
|
|
13398
|
-
const created = cs.creates.map((c) => ({ path: c.path, ordered:
|
|
12951
|
+
const created = cs.creates.map((c) => ({ path: c.path, ordered: readOrderedFromMarkdown(c.content, /* @__PURE__ */ new Set([settings.tableProperty])).ordered }));
|
|
13399
12952
|
const touched = /* @__PURE__ */ new Set([...afterByPath.keys(), ...created.map((c) => c.path)]);
|
|
13400
12953
|
violations.push(
|
|
13401
12954
|
...uniqueViolations(t.def.columns, [
|
|
@@ -13482,7 +13035,7 @@ async function recomputeImpl(app, settings, input, opts = {}) {
|
|
|
13482
13035
|
return isEmptyValue(v) ? [] : validateValue(c, v, ctx);
|
|
13483
13036
|
})
|
|
13484
13037
|
});
|
|
13485
|
-
cs.edits.push({ path: r.file.path,
|
|
13038
|
+
cs.edits.push({ path: r.file.path, before: r.ordered, after });
|
|
13486
13039
|
}
|
|
13487
13040
|
}
|
|
13488
13041
|
if (cs.edits.length === 0) return { ...emptyResult("recompute", opts.dryRun === true), ok: true };
|
|
@@ -13493,19 +13046,17 @@ async function updateRowsImpl(app, settings, input, opts = {}) {
|
|
|
13493
13046
|
const t = await loadTable(app, settings, input.table);
|
|
13494
13047
|
const known = knownKeys(t, settings);
|
|
13495
13048
|
known.delete("path");
|
|
13496
|
-
known.delete(
|
|
13049
|
+
known.delete(settings.tableProperty);
|
|
13497
13050
|
const set = input.set ?? {};
|
|
13498
13051
|
const unset = input.unset ?? [];
|
|
13499
13052
|
if (Object.keys(set).length === 0 && unset.length === 0 && input.body === void 0) {
|
|
13500
13053
|
throw new OperationInputError(`nothing to update: pass "set", "unset" or "body"`);
|
|
13501
13054
|
}
|
|
13502
|
-
const reservedOnRows = new Set(rowReservedKeys(settings));
|
|
13503
13055
|
for (const k of Object.keys(set)) {
|
|
13504
13056
|
if (!known.has(k)) throw new OperationInputError(`unknown column "${k}" for table "${t.def.name}"`);
|
|
13505
13057
|
}
|
|
13506
13058
|
for (const k of unset) {
|
|
13507
|
-
if (k ===
|
|
13508
|
-
void reservedOnRows;
|
|
13059
|
+
if (k === settings.tableProperty || k === "path") throw new OperationInputError(`cannot unset "${k}"`);
|
|
13509
13060
|
}
|
|
13510
13061
|
const computed = computedColumnNames(t);
|
|
13511
13062
|
for (const k of [...Object.keys(set), ...unset]) {
|
|
@@ -13524,7 +13075,7 @@ async function updateRowsImpl(app, settings, input, opts = {}) {
|
|
|
13524
13075
|
if (input.body !== void 0 && matched.length !== 1) {
|
|
13525
13076
|
throw new OperationInputError(`"body" updates exactly one row; "where" matched ${matched.length}`);
|
|
13526
13077
|
}
|
|
13527
|
-
const nameTemplate = t.def.
|
|
13078
|
+
const nameTemplate = t.def.options.filename ? `${t.def.layout.rowPath}/${t.def.options.filename}` : null;
|
|
13528
13079
|
const nameCols = new Set([...(nameTemplate ?? "").matchAll(/\{([A-Za-z][A-Za-z0-9_-]*)(?::[^}]+)?\}/g)].map((m) => m[1]));
|
|
13529
13080
|
const renames = [...Object.keys(set), ...unset].some((k) => nameCols.has(k));
|
|
13530
13081
|
const movedTo = /* @__PURE__ */ new Set();
|
|
@@ -13572,7 +13123,6 @@ async function updateRowsImpl(app, settings, input, opts = {}) {
|
|
|
13572
13123
|
violations.push({ path: r.file.path, violations: rowViolations });
|
|
13573
13124
|
cs.edits.push({
|
|
13574
13125
|
path: r.file.path,
|
|
13575
|
-
strict: false,
|
|
13576
13126
|
before: r.ordered,
|
|
13577
13127
|
after,
|
|
13578
13128
|
...input.body !== void 0 ? { bodyBefore: r.body, bodyAfter: input.body } : {}
|
|
@@ -13677,8 +13227,8 @@ async function deleteRowsImpl(app, settings, input, opts = {}) {
|
|
|
13677
13227
|
const f = app.vault.getAbstractFileByPath(src);
|
|
13678
13228
|
if (!f || !("extension" in f) || f.extension !== "md") continue;
|
|
13679
13229
|
const text2 = await app.vault.read(f);
|
|
13680
|
-
const before =
|
|
13681
|
-
cs.edits.push({ path: src,
|
|
13230
|
+
const before = readOrderedFromMarkdown(text2).ordered;
|
|
13231
|
+
cs.edits.push({ path: src, before, after: clearLinksTo(app, src, before, doomed) });
|
|
13682
13232
|
}
|
|
13683
13233
|
}
|
|
13684
13234
|
const folder = archiveFolder(t.def);
|
|
@@ -13697,7 +13247,7 @@ async function deleteRowsImpl(app, settings, input, opts = {}) {
|
|
|
13697
13247
|
}
|
|
13698
13248
|
function checkRetarget(dst, settings, r) {
|
|
13699
13249
|
const dstKnown = knownKeys(dst, settings);
|
|
13700
|
-
const membership = /* @__PURE__ */ new Set([settings.
|
|
13250
|
+
const membership = /* @__PURE__ */ new Set([settings.tableProperty]);
|
|
13701
13251
|
const computed = computedColumnNames(dst);
|
|
13702
13252
|
for (const [from, to] of Object.entries(r.rename)) {
|
|
13703
13253
|
if (typeof to !== "string" || !dstKnown.has(to)) {
|
|
@@ -13717,7 +13267,7 @@ function checkRetarget(dst, settings, r) {
|
|
|
13717
13267
|
}
|
|
13718
13268
|
async function retargetRows(app, settings, dst, notes, r, cs, opts) {
|
|
13719
13269
|
const dstKnown = knownKeys(dst, settings);
|
|
13720
|
-
const membership = /* @__PURE__ */ new Set([settings.
|
|
13270
|
+
const membership = /* @__PURE__ */ new Set([settings.tableProperty]);
|
|
13721
13271
|
const tz = (await readDatabaseConfig(app, settings)).timezone;
|
|
13722
13272
|
const violations = [];
|
|
13723
13273
|
const conflicts = [];
|
|
@@ -13749,7 +13299,7 @@ async function retargetRows(app, settings, dst, notes, r, cs, opts) {
|
|
|
13749
13299
|
after = withGenerated(dst, settings, after, n.path);
|
|
13750
13300
|
let to = n.path;
|
|
13751
13301
|
if (r.relocate) {
|
|
13752
|
-
if (
|
|
13302
|
+
if (!dst.def.options.filename) {
|
|
13753
13303
|
throw new OperationInputError(`table "${dst.def.name}" has no filename pattern: cannot relocate rows`);
|
|
13754
13304
|
}
|
|
13755
13305
|
try {
|
|
@@ -13772,11 +13322,11 @@ async function retargetRows(app, settings, dst, notes, r, cs, opts) {
|
|
|
13772
13322
|
violations.push({
|
|
13773
13323
|
path: n.path,
|
|
13774
13324
|
violations: [
|
|
13775
|
-
...validateRow(dst.def, after, {
|
|
13325
|
+
...validateRow(dst.def, after, { tableProperty: settings.tableProperty }, validationContextFor(app, settings, n.path)),
|
|
13776
13326
|
...constraintViolations(dst, settings, n.path, after)
|
|
13777
13327
|
]
|
|
13778
13328
|
});
|
|
13779
|
-
cs.edits.push({ path: n.path,
|
|
13329
|
+
cs.edits.push({ path: n.path, before: n.ordered, after });
|
|
13780
13330
|
if (to !== n.path) cs.moves.push({ from: n.path, to });
|
|
13781
13331
|
}
|
|
13782
13332
|
if (dst.def.columns.some((c) => c.unique)) {
|
|
@@ -13826,10 +13376,9 @@ async function adoptRowsImpl(app, settings, input, opts = {}) {
|
|
|
13826
13376
|
for (const p of paths) {
|
|
13827
13377
|
const f = app.vault.getAbstractFileByPath(p);
|
|
13828
13378
|
if (f == null || !("extension" in f)) throw new OperationInputError(`note not found: ${p}`);
|
|
13829
|
-
const { ordered } =
|
|
13379
|
+
const { ordered } = readOrderedFromMarkdown(
|
|
13830
13380
|
await app.vault.read(f),
|
|
13831
|
-
settings.
|
|
13832
|
-
/* @__PURE__ */ new Set([settings.templateProperty, settings.tableProperty])
|
|
13381
|
+
/* @__PURE__ */ new Set([settings.tableProperty])
|
|
13833
13382
|
);
|
|
13834
13383
|
const owner = model ? rowTableFull(model, fmGet(ordered, settings.tableProperty)) : null;
|
|
13835
13384
|
if (owner) conflicts.push({ path: p, message: `already a row of ${owner}: use move_rows` });
|
|
@@ -13862,8 +13411,7 @@ async function relocateTable(app, settings, t, dest, changes, opts, properties =
|
|
|
13862
13411
|
if (v === null) delete merged[k];
|
|
13863
13412
|
else merged[k] = v;
|
|
13864
13413
|
}
|
|
13865
|
-
const
|
|
13866
|
-
const membership = /* @__PURE__ */ new Set([tp, settings.tableProperty]);
|
|
13414
|
+
const membership = /* @__PURE__ */ new Set([settings.tableProperty]);
|
|
13867
13415
|
let options;
|
|
13868
13416
|
let layout;
|
|
13869
13417
|
let member;
|
|
@@ -13871,7 +13419,6 @@ async function relocateTable(app, settings, t, dest, changes, opts, properties =
|
|
|
13871
13419
|
let cs;
|
|
13872
13420
|
{
|
|
13873
13421
|
const ref2 = dest.catalogRef;
|
|
13874
|
-
delete merged.path;
|
|
13875
13422
|
options = parseTableOptions([{ ...merged, name: ref2.table }]);
|
|
13876
13423
|
layout = catalogLayout(databaseRoot(settings), ref2, options);
|
|
13877
13424
|
member = (o) => withRowId([[settings.tableProperty, ref2.full], ...o.filter(([k]) => !membership.has(k))]);
|
|
@@ -13933,14 +13480,14 @@ async function relocateTable(app, settings, t, dest, changes, opts, properties =
|
|
|
13933
13480
|
if (!list2.includes(oldName)) after = fmSet(after, "aliases", [...list2, oldName]);
|
|
13934
13481
|
}
|
|
13935
13482
|
if (JSON.stringify(after) !== JSON.stringify(r.ordered)) {
|
|
13936
|
-
cs.edits.push({ path: r.path,
|
|
13483
|
+
cs.edits.push({ path: r.path, before: r.ordered, after });
|
|
13937
13484
|
}
|
|
13938
13485
|
if (to !== r.path) cs.moves.push({ from: r.path, to });
|
|
13939
13486
|
};
|
|
13940
13487
|
const excluded = (p) => (options.exclude ?? []).some((dir) => p.startsWith(`${dir.replace(/\/+$/, "")}/`));
|
|
13941
13488
|
const rows = (await loadRows(app, settings, t)).filter((r) => !excluded(r.file.path));
|
|
13942
13489
|
const bases = /* @__PURE__ */ new Map();
|
|
13943
|
-
if (
|
|
13490
|
+
if (options.filename) {
|
|
13944
13491
|
for (const r of rows) {
|
|
13945
13492
|
try {
|
|
13946
13493
|
const values = new Map(r.ordered);
|
|
@@ -13965,14 +13512,14 @@ async function relocateTable(app, settings, t, dest, changes, opts, properties =
|
|
|
13965
13512
|
}
|
|
13966
13513
|
for (const r of rows) {
|
|
13967
13514
|
const base = bases.get(r.file.path);
|
|
13968
|
-
if (
|
|
13515
|
+
if (options.filename && base === void 0) continue;
|
|
13969
13516
|
const to = base === void 0 ? r.file.path : base.startsWith("\0") ? base.slice(1) : claim(base, r.file.path);
|
|
13970
13517
|
relink({ path: r.file.path, ordered: r.ordered }, to);
|
|
13971
13518
|
}
|
|
13972
13519
|
const oldArchive = t.def.layout.archive;
|
|
13973
13520
|
const newArchive = layout.archive;
|
|
13974
13521
|
for (const f of archivedRowFiles(app, settings, t)) {
|
|
13975
|
-
const { ordered } =
|
|
13522
|
+
const { ordered } = readOrderedFromMarkdown(await app.vault.read(f), membership);
|
|
13976
13523
|
const to = newArchive === oldArchive ? f.path : claim(`${newArchive}/${basenameOf(f.path)}`, f.path);
|
|
13977
13524
|
relink({ path: f.path, ordered }, to);
|
|
13978
13525
|
}
|
|
@@ -13981,25 +13528,15 @@ async function relocateTable(app, settings, t, dest, changes, opts, properties =
|
|
|
13981
13528
|
async function alterTableImpl(app, settings, input, opts = {}) {
|
|
13982
13529
|
const t = await loadTable(app, settings, input.table);
|
|
13983
13530
|
const cfg = await readDatabaseConfig(app, settings);
|
|
13984
|
-
const schema = assertIdentifier("schema", input.schema ??
|
|
13531
|
+
const schema = assertIdentifier("schema", input.schema ?? t.def.schema);
|
|
13985
13532
|
const name = assertIdentifier("table", input.name ?? t.def.name);
|
|
13986
|
-
const catalog = assertIdentifier("catalog", input.catalog ?? t.def.catalog
|
|
13533
|
+
const catalog = assertIdentifier("catalog", input.catalog ?? t.def.catalog);
|
|
13534
|
+
const changes = { name: null };
|
|
13535
|
+
if (input.partition !== void 0) changes.partition = input.partition ? input.partition : null;
|
|
13987
13536
|
const cur = t.def.options;
|
|
13988
|
-
const changes = { path: null, name: null };
|
|
13989
|
-
let partition = input.partition ?? cur.partition;
|
|
13990
|
-
if (input.partition === void 0 && cur.path) {
|
|
13991
|
-
const own = t.def.layout.folder;
|
|
13992
|
-
if (cur.path === own) partition = "";
|
|
13993
|
-
else if (cur.path.startsWith(`${own}/`)) partition = cur.path.slice(own.length + 1);
|
|
13994
|
-
else {
|
|
13995
|
-
const brace = cur.path.indexOf("{");
|
|
13996
|
-
partition = brace < 0 ? "" : cur.path.slice(cur.path.lastIndexOf("/", brace) + 1);
|
|
13997
|
-
}
|
|
13998
|
-
}
|
|
13999
|
-
changes.partition = partition ? partition : null;
|
|
14000
13537
|
if (!cur.archive || cur.archive.includes("/")) {
|
|
14001
13538
|
const own = t.def.layout.archive;
|
|
14002
|
-
changes.archive =
|
|
13539
|
+
changes.archive = own.startsWith(`${t.def.layout.folder}/`) && !own.slice(t.def.layout.folder.length + 1).includes("/") ? own.slice(t.def.layout.folder.length + 1) : cfg.archive_folder;
|
|
14003
13540
|
}
|
|
14004
13541
|
if (input.filename !== void 0) changes.filename = input.filename;
|
|
14005
13542
|
if (input.description !== void 0) changes.description = input.description;
|
|
@@ -14040,7 +13577,7 @@ async function syncRelations(app, settings, changes, opts = {}) {
|
|
|
14040
13577
|
if (plan.edits.size === 0) return null;
|
|
14041
13578
|
const cs = emptyChangeSet("sync_relations", `mirror links of ${changes.map((c) => c.path).join(", ")}`.slice(0, 200));
|
|
14042
13579
|
cs.skipInverse = true;
|
|
14043
|
-
for (const [path6, w] of plan.edits) cs.edits.push({ path: path6,
|
|
13580
|
+
for (const [path6, w] of plan.edits) cs.edits.push({ path: path6, before: w.before, after: w.after });
|
|
14044
13581
|
return finish(app, settings, cs, plan.conflicts, [], opts);
|
|
14045
13582
|
}
|
|
14046
13583
|
async function alignRelationsImpl(app, settings, input, opts = {}) {
|
|
@@ -14058,7 +13595,7 @@ async function alignRelationsImpl(app, settings, input, opts = {}) {
|
|
|
14058
13595
|
const plan = await planInverse(app, settings, t.catalog.model, changes, { keepSingles: true });
|
|
14059
13596
|
const cs = emptyChangeSet("align_relations", `align inverse links of ${t.catalog.ref.full}`, t.def.schemaPath);
|
|
14060
13597
|
cs.skipInverse = true;
|
|
14061
|
-
for (const [path6, w] of plan.edits) cs.edits.push({ path: path6,
|
|
13598
|
+
for (const [path6, w] of plan.edits) cs.edits.push({ path: path6, before: w.before, after: w.after });
|
|
14062
13599
|
return finish(app, settings, cs, plan.conflicts, [], opts);
|
|
14063
13600
|
}
|
|
14064
13601
|
function alignRelations(app, settings, input, opts = {}) {
|
|
@@ -14094,7 +13631,7 @@ async function adoptCreatedNote(app, settings, file) {
|
|
|
14094
13631
|
const target = await adoptTargetFor(app, settings, file.path);
|
|
14095
13632
|
if (!target) return { adopted: false };
|
|
14096
13633
|
const text2 = await app.vault.read(file);
|
|
14097
|
-
const { ordered, body } =
|
|
13634
|
+
const { ordered, body } = readOrderedFromMarkdown(text2, /* @__PURE__ */ new Set([settings.tableProperty]));
|
|
14098
13635
|
const declared = ordered.find(([k]) => k === settings.tableProperty)?.[1];
|
|
14099
13636
|
if (declared !== void 0) {
|
|
14100
13637
|
if (declared !== target.table && !target.table.endsWith(`.${String(declared)}`)) return { adopted: false };
|
|
@@ -14534,7 +14071,7 @@ function frontmatter(app, f) {
|
|
|
14534
14071
|
}
|
|
14535
14072
|
async function inferTable(app, settings, input) {
|
|
14536
14073
|
const maxEnum = input.maxEnumValues ?? 12;
|
|
14537
|
-
const skip = /* @__PURE__ */ new Set([
|
|
14074
|
+
const skip = /* @__PURE__ */ new Set([settings.tableProperty, "id", ...SKIP_KEYS]);
|
|
14538
14075
|
const notes = [];
|
|
14539
14076
|
if (input.table !== void 0) {
|
|
14540
14077
|
const t = await loadTable(app, settings, input.table);
|
|
@@ -15429,139 +14966,6 @@ var OtlpSink = class {
|
|
|
15429
14966
|
}
|
|
15430
14967
|
};
|
|
15431
14968
|
|
|
15432
|
-
// src/core/view-block.ts
|
|
15433
|
-
var import_yaml3 = __toESM(require_dist(), 1);
|
|
15434
|
-
var BLOCK_KEYS = /* @__PURE__ */ new Set(["view", "table", "columns", "where", "order_by", "limit", "join", "group_by", "aggregates", "expand", "labels", "row_link", "chart", "with_table"]);
|
|
15435
|
-
function parseChart(raw) {
|
|
15436
|
-
if (raw == null || typeof raw !== "object" || Array.isArray(raw)) throw new OperationInputError(`datanotes block: "chart" must be a mapping (type, x, y)`);
|
|
15437
|
-
const c = raw;
|
|
15438
|
-
for (const k of Object.keys(c)) {
|
|
15439
|
-
if (!["type", "x", "y", "targets", "title"].includes(k)) throw new OperationInputError(`datanotes block: unknown chart key "${k}" (allowed: type, x, y, targets, title)`);
|
|
15440
|
-
}
|
|
15441
|
-
const type = c.type ?? "line";
|
|
15442
|
-
if (type !== "line" && type !== "bar") throw new OperationInputError(`datanotes block: chart type must be line or bar`);
|
|
15443
|
-
if (typeof c.x !== "string" || !c.x.trim()) throw new OperationInputError(`datanotes block: chart needs "x" (the column along the axis)`);
|
|
15444
|
-
const y = typeof c.y === "string" ? [c.y] : Array.isArray(c.y) ? c.y.map(String) : [];
|
|
15445
|
-
if (!y.length) throw new OperationInputError(`datanotes block: chart needs "y" (a column or a list of columns)`);
|
|
15446
|
-
const targets = {};
|
|
15447
|
-
if (c.targets != null) {
|
|
15448
|
-
if (typeof c.targets !== "object" || Array.isArray(c.targets)) throw new OperationInputError(`datanotes block: chart "targets" must be a mapping label \u2192 number`);
|
|
15449
|
-
for (const [k, v] of Object.entries(c.targets)) {
|
|
15450
|
-
const n = Number(v);
|
|
15451
|
-
if (!Number.isFinite(n)) throw new OperationInputError(`datanotes block: chart target "${k}" must be a number`);
|
|
15452
|
-
targets[k] = n;
|
|
15453
|
-
}
|
|
15454
|
-
}
|
|
15455
|
-
return { type, x: c.x.trim(), y, targets, ...typeof c.title === "string" ? { title: c.title } : {} };
|
|
15456
|
-
}
|
|
15457
|
-
function parseViewBlock(source) {
|
|
15458
|
-
let raw;
|
|
15459
|
-
try {
|
|
15460
|
-
raw = (0, import_yaml3.parse)(source);
|
|
15461
|
-
} catch (e) {
|
|
15462
|
-
throw new OperationInputError(`datanotes block: invalid YAML (${e instanceof Error ? e.message : String(e)})`);
|
|
15463
|
-
}
|
|
15464
|
-
if (raw == null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
15465
|
-
throw new OperationInputError(`datanotes block: write "view: <catalog.schema.view>" or a query ("table: \u2026")`);
|
|
15466
|
-
}
|
|
15467
|
-
const b = raw;
|
|
15468
|
-
for (const k of Object.keys(b)) {
|
|
15469
|
-
if (!BLOCK_KEYS.has(k)) throw new OperationInputError(`datanotes block: unknown key "${k}" (allowed: ${[...BLOCK_KEYS].join(", ")})`);
|
|
15470
|
-
}
|
|
15471
|
-
if (b.view !== void 0 && b.table !== void 0) throw new OperationInputError(`datanotes block: pass "view" or "table", not both`);
|
|
15472
|
-
const target = b.view ?? b.table;
|
|
15473
|
-
if (typeof target !== "string" || target.trim() === "") throw new OperationInputError(`datanotes block needs "view" or "table"`);
|
|
15474
|
-
const { view: _v, labels, row_link, chart, with_table, ...query } = b;
|
|
15475
|
-
const labelMap = {};
|
|
15476
|
-
if (labels != null) {
|
|
15477
|
-
if (typeof labels !== "object" || Array.isArray(labels)) throw new OperationInputError(`datanotes block: "labels" must be a mapping`);
|
|
15478
|
-
for (const [k, v] of Object.entries(labels)) labelMap[k] = String(v);
|
|
15479
|
-
}
|
|
15480
|
-
const select2 = viewQueryToSelect({ ...query, table: target.trim() });
|
|
15481
|
-
return {
|
|
15482
|
-
select: select2,
|
|
15483
|
-
labels: labelMap,
|
|
15484
|
-
rowLink: row_link !== false,
|
|
15485
|
-
...select2.columns ? { columns: select2.columns } : {},
|
|
15486
|
-
...chart !== void 0 ? { chart: parseChart(chart) } : {},
|
|
15487
|
-
withTable: with_table === true
|
|
15488
|
-
};
|
|
15489
|
-
}
|
|
15490
|
-
function chartValue(v) {
|
|
15491
|
-
if (v === null || v === void 0 || v === "") return "null";
|
|
15492
|
-
const n = Number(v);
|
|
15493
|
-
return Number.isFinite(n) ? String(Math.round(n * 100) / 100) : "null";
|
|
15494
|
-
}
|
|
15495
|
-
function chartLabel(v) {
|
|
15496
|
-
const text2 = cell(v);
|
|
15497
|
-
const d = text2.match(/^(\d{4})-(\d{2})-(\d{2})(?: (\d{2}:\d{2}))?$/);
|
|
15498
|
-
const shown = d ? `${d[3]}/${d[2]}${d[4] ? ` ${d[4]}` : ""}` : text2.replace(/\[\[(?:[^|\]]*\|)?([^\]]*)\]\]/g, "$1");
|
|
15499
|
-
return JSON.stringify(shown);
|
|
15500
|
-
}
|
|
15501
|
-
function chartMarkdown(result, chart, labels) {
|
|
15502
|
-
if (result.rows.length === 0) return "_No data to chart._";
|
|
15503
|
-
const missing = [chart.x, ...chart.y].filter((c) => !(c in result.rows[0]));
|
|
15504
|
-
if (missing.length) return `> [!warning] datanotes
|
|
15505
|
-
> chart: no column ${missing.map((m) => `"${m}"`).join(", ")} in the rows (columns: ${Object.keys(result.rows[0]).filter((k) => k !== "path").join(", ")})`;
|
|
15506
|
-
const lines = ["```chart", `type: ${chart.type}`, `labels: [${result.rows.map((r) => chartLabel(r[chart.x])).join(", ")}]`, "series:"];
|
|
15507
|
-
for (const col of chart.y) {
|
|
15508
|
-
lines.push(` - title: ${JSON.stringify(labels[col] ?? col)}`, ` data: [${result.rows.map((r) => chartValue(r[col])).join(", ")}]`);
|
|
15509
|
-
}
|
|
15510
|
-
for (const [label, value] of Object.entries(chart.targets)) {
|
|
15511
|
-
lines.push(` - title: ${JSON.stringify(label)}`, ` data: [${result.rows.map(() => String(value)).join(", ")}]`);
|
|
15512
|
-
}
|
|
15513
|
-
lines.push("tension: 0.3", "width: 100%", "fill: false", "beginAtZero: false", "spanGaps: true", "```");
|
|
15514
|
-
if (chart.title) lines.unshift(`**${chart.title}**`, "");
|
|
15515
|
-
return lines.join("\n");
|
|
15516
|
-
}
|
|
15517
|
-
function cell(v) {
|
|
15518
|
-
if (v === null || v === void 0) return "";
|
|
15519
|
-
if (Array.isArray(v)) return v.map(cell).filter((x) => x !== "").join(", ");
|
|
15520
|
-
if (typeof v === "boolean") return v ? "\u2713" : "";
|
|
15521
|
-
if (typeof v === "object") return JSON.stringify(v).replace(/\|/g, "\\|");
|
|
15522
|
-
const text2 = String(v);
|
|
15523
|
-
const dt = text2.match(/^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}):\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/);
|
|
15524
|
-
if (dt) return `${dt[1]} ${dt[2]}`;
|
|
15525
|
-
return text2.replace(/\r?\n/g, " ").replace(/\|/g, "\\|");
|
|
15526
|
-
}
|
|
15527
|
-
function viewMarkdown(result, opts) {
|
|
15528
|
-
if (result.rows.length === 0) return "_No rows._";
|
|
15529
|
-
const grouped = !("path" in result.rows[0]);
|
|
15530
|
-
let columns = opts.columns ?? Object.keys(result.rows[0]).filter((k) => k !== "path");
|
|
15531
|
-
if (grouped) columns = Object.keys(result.rows[0]);
|
|
15532
|
-
const link = !grouped && opts.rowLink && !columns.includes("file_link");
|
|
15533
|
-
const heads = [...link ? [opts.labels.file_link ?? "Note"] : [], ...columns.map((c) => opts.labels[c] ?? c)];
|
|
15534
|
-
const lines = [`| ${heads.map(cell).join(" | ")} |`, `| ${heads.map(() => "---").join(" | ")} |`];
|
|
15535
|
-
for (const r of result.rows) {
|
|
15536
|
-
const path6 = typeof r.path === "string" ? r.path : "";
|
|
15537
|
-
const name = path6.split("/").pop().replace(/\.md$/i, "");
|
|
15538
|
-
const cells = [...link ? [cell(`[[${path6.replace(/\.md$/i, "")}|${name}]]`)] : [], ...columns.map((c) => cell(r[c]))];
|
|
15539
|
-
lines.push(`| ${cells.join(" | ")} |`);
|
|
15540
|
-
}
|
|
15541
|
-
const shown = result.rows.length;
|
|
15542
|
-
lines.push("", `<small>${result.total === shown ? `${shown} ${shown === 1 ? "row" : "rows"}` : `${shown} of ${result.total} rows`}${result.view ? ` \xB7 view ${result.view}` : ""}</small>`);
|
|
15543
|
-
return lines.join("\n");
|
|
15544
|
-
}
|
|
15545
|
-
async function renderViewBlock(app, settings, source, host) {
|
|
15546
|
-
try {
|
|
15547
|
-
const block = parseViewBlock(source);
|
|
15548
|
-
const result = await select(app, settings, { ...block.select, ...host ? { host } : {} });
|
|
15549
|
-
let labels = block.labels;
|
|
15550
|
-
if (result.view) {
|
|
15551
|
-
const ms = await loadMetastore(app, settings);
|
|
15552
|
-
const ref2 = ms ? resolveCatalogRef(ms.model, result.view, "view") : null;
|
|
15553
|
-
const own = ref2 ? ms.model.catalogs[ref2.catalog].schemas[ref2.schema].views[ref2.table].labels : void 0;
|
|
15554
|
-
labels = { ...own ?? {}, ...block.labels };
|
|
15555
|
-
}
|
|
15556
|
-
const table = () => viewMarkdown(result, { labels, rowLink: block.rowLink, ...block.select.columns ? { columns: block.select.columns } : {} });
|
|
15557
|
-
const markdown = block.chart ? [chartMarkdown(result, block.chart, labels), ...block.withTable ? ["", table()] : []].join("\n") : table();
|
|
15558
|
-
return { markdown, total: result.total, ...result.view ? { view: result.view } : {} };
|
|
15559
|
-
} catch (e) {
|
|
15560
|
-
return { markdown: `> [!warning] datanotes
|
|
15561
|
-
> ${(e instanceof Error ? e.message : String(e)).replace(/\n/g, "\n> ")}`, total: 0 };
|
|
15562
|
-
}
|
|
15563
|
-
}
|
|
15564
|
-
|
|
15565
14969
|
// src/server/rest.ts
|
|
15566
14970
|
var ROUTE_PREFIX = "/datanotes";
|
|
15567
14971
|
var BadRequest = class extends Error {
|
|
@@ -15630,9 +15034,8 @@ function errorResponse(e) {
|
|
|
15630
15034
|
return { status: 404, json: { error: message } };
|
|
15631
15035
|
}
|
|
15632
15036
|
if (e instanceof Forbidden) return { status: 403, json: { error: message } };
|
|
15633
|
-
if (e instanceof AmbiguousTableError) return { status: 409, json: { error: message, paths: e.paths } };
|
|
15634
15037
|
if (e instanceof AmbiguousCatalogRefError) return { status: 409, json: { error: message, tables: e.candidates } };
|
|
15635
|
-
if (e instanceof BadRequest || e instanceof OperationInputError || e instanceof MalformedColumnError || e instanceof MalformedTableOptionsError || e instanceof
|
|
15038
|
+
if (e instanceof BadRequest || e instanceof OperationInputError || e instanceof MalformedColumnError || e instanceof MalformedTableOptionsError || e instanceof QueryInputError || e instanceof DatabaseConfigError || e instanceof EmbeddingError || e instanceof MetastoreError) {
|
|
15636
15039
|
return { status: 400, json: { error: message } };
|
|
15637
15040
|
}
|
|
15638
15041
|
return { status: 500, json: { error: message } };
|
|
@@ -15816,16 +15219,6 @@ function createHandlers(app, getSettings, saveSettings = async () => {
|
|
|
15816
15219
|
},
|
|
15817
15220
|
"/tables/describe/": async (body) => ({ status: 200, json: await describeTable(app, s(), str(body, "table")) }),
|
|
15818
15221
|
"/ddl/": ddl,
|
|
15819
|
-
// The engine's API itself, method by method (camelCase inputs as in public-api.ts), for the
|
|
15820
|
-
// owner: `remote-api.ts` is its client.
|
|
15821
|
-
"/api/": async (body) => {
|
|
15822
|
-
const method = str(body, "method");
|
|
15823
|
-
const args = list(body, "args") ?? [];
|
|
15824
|
-
const fn = pub[method];
|
|
15825
|
-
if (typeof fn !== "function" || API_EXCLUDED.has(method)) throw new BadRequest(`"method" must be a method of the engine API`);
|
|
15826
|
-
const result = await fn.apply(pub, args);
|
|
15827
|
-
return { status: 200, json: { result: result === void 0 ? null : result } };
|
|
15828
|
-
},
|
|
15829
15222
|
"/batch/": async (body) => {
|
|
15830
15223
|
const ops = list(body, "operations");
|
|
15831
15224
|
if (!ops || ops.length === 0) throw new BadRequest(`"operations" must be a non-empty list`);
|
|
@@ -15907,22 +15300,6 @@ function createHandlers(app, getSettings, saveSettings = async () => {
|
|
|
15907
15300
|
throw new BadRequest(e instanceof Error ? e.message : String(e));
|
|
15908
15301
|
}
|
|
15909
15302
|
},
|
|
15910
|
-
"/views/render/": async (body) => {
|
|
15911
|
-
const blockText = str(body, "block", false);
|
|
15912
|
-
const view = str(body, "view", false);
|
|
15913
|
-
if (!blockText && !view) throw new BadRequest(`pass "view" (a view name) or "block" (the text of an datanotes block)`);
|
|
15914
|
-
const where = obj(body, "where", false);
|
|
15915
|
-
const source = blockText ?? `view: ${view}${where ? `
|
|
15916
|
-
where: ${JSON.stringify(where)}` : ""}`;
|
|
15917
|
-
const notePath = str(body, "note", false);
|
|
15918
|
-
let host;
|
|
15919
|
-
if (notePath) {
|
|
15920
|
-
const f = app.vault.getAbstractFileByPath(notePath);
|
|
15921
|
-
if (!f || !("extension" in f)) throw new BadRequest(`note not found: ${notePath}`);
|
|
15922
|
-
host = { path: notePath, frontmatter: app.metadataCache.getFileCache(f)?.frontmatter ?? {} };
|
|
15923
|
-
}
|
|
15924
|
-
return { status: 200, json: await renderViewBlock(app, s(), source, host) };
|
|
15925
|
-
},
|
|
15926
15303
|
"/webhooks/": async () => {
|
|
15927
15304
|
try {
|
|
15928
15305
|
return { status: 200, json: { webhooks: pub.listWebhooks() } };
|
|
@@ -16233,7 +15610,6 @@ where: ${JSON.stringify(where)}` : ""}`;
|
|
|
16233
15610
|
};
|
|
16234
15611
|
return handlers;
|
|
16235
15612
|
}
|
|
16236
|
-
var API_EXCLUDED = /* @__PURE__ */ new Set(["withActor"]);
|
|
16237
15613
|
function batchArgs(op, args) {
|
|
16238
15614
|
const out = { ...args };
|
|
16239
15615
|
const move = (from, to) => {
|
|
@@ -16597,7 +15973,7 @@ var OPERATIONS = [
|
|
|
16597
15973
|
},
|
|
16598
15974
|
"path": {
|
|
16599
15975
|
"type": "string",
|
|
16600
|
-
"description": "database.yaml#catalog.schema.table
|
|
15976
|
+
"description": "database.yaml#catalog.schema.table."
|
|
16601
15977
|
},
|
|
16602
15978
|
"description": {
|
|
16603
15979
|
"type": "string",
|
|
@@ -16612,6 +15988,7 @@ var OPERATIONS = [
|
|
|
16612
15988
|
},
|
|
16613
15989
|
"required": [
|
|
16614
15990
|
"name",
|
|
15991
|
+
"catalog",
|
|
16615
15992
|
"schema",
|
|
16616
15993
|
"qualified",
|
|
16617
15994
|
"path"
|
|
@@ -16709,7 +16086,8 @@ var OPERATIONS = [
|
|
|
16709
16086
|
"description": "Folder of the table's rows."
|
|
16710
16087
|
},
|
|
16711
16088
|
"inDatabase": {
|
|
16712
|
-
"type": "boolean"
|
|
16089
|
+
"type": "boolean",
|
|
16090
|
+
"description": "Always true."
|
|
16713
16091
|
},
|
|
16714
16092
|
"rowPath": {
|
|
16715
16093
|
"type": "string",
|
|
@@ -16723,6 +16101,7 @@ var OPERATIONS = [
|
|
|
16723
16101
|
"required": [
|
|
16724
16102
|
"folder",
|
|
16725
16103
|
"inDatabase",
|
|
16104
|
+
"rowPath",
|
|
16726
16105
|
"archive"
|
|
16727
16106
|
],
|
|
16728
16107
|
"additionalProperties": true
|
|
@@ -16809,7 +16188,7 @@ var OPERATIONS = [
|
|
|
16809
16188
|
},
|
|
16810
16189
|
"dense": {
|
|
16811
16190
|
"type": "boolean",
|
|
16812
|
-
"description": "
|
|
16191
|
+
"description": "Written on every row (with its default)."
|
|
16813
16192
|
}
|
|
16814
16193
|
},
|
|
16815
16194
|
"required": [
|
|
@@ -16828,7 +16207,7 @@ var OPERATIONS = [
|
|
|
16828
16207
|
"items": {
|
|
16829
16208
|
"type": "string"
|
|
16830
16209
|
},
|
|
16831
|
-
"description": "
|
|
16210
|
+
"description": "Table defaults without a column (written on every new row), and the table property."
|
|
16832
16211
|
},
|
|
16833
16212
|
"qualified": {
|
|
16834
16213
|
"type": "string",
|
|
@@ -26768,7 +26147,7 @@ var OPERATIONS = [
|
|
|
26768
26147
|
},
|
|
26769
26148
|
{
|
|
26770
26149
|
"name": "create_view",
|
|
26771
|
-
"description": "Create (or `replace`) a view: a named select stored in database.yaml. Name it with the prefix\n`vw_` (e.g. `vw_open_tasks`): views share names and folders with tables. `query` takes the\nselect_rows parameters (table, columns, where, order_by, limit, join, group_by, aggregates, expand;\nrelative dates keep it current) and must run now. `comment` and `aliases` let agents find it;\n`labels` are column headings.
|
|
26150
|
+
"description": "Create (or `replace`) a view: a named select stored in database.yaml. Name it with the prefix\n`vw_` (e.g. `vw_open_tasks`): views share names and folders with tables. `query` takes the\nselect_rows parameters (table, columns, where, order_by, limit, join, group_by, aggregates, expand;\nrelative dates keep it current) and must run now. `comment` and `aliases` let agents find it;\n`labels` are column headings. Views are selected with select_rows(table=<view>), which may narrow them further\n(where, columns, order_by, limit). A view writes no note: it lives only in database.yaml.",
|
|
26772
26151
|
"inputSchema": {
|
|
26773
26152
|
"additionalProperties": false,
|
|
26774
26153
|
"properties": {
|
|
@@ -28623,7 +28002,6 @@ var READ_ROUTES = /* @__PURE__ */ new Set([
|
|
|
28623
28002
|
"/tables/infer/",
|
|
28624
28003
|
"/select/",
|
|
28625
28004
|
"/check/",
|
|
28626
|
-
"/views/render/",
|
|
28627
28005
|
"/changes/",
|
|
28628
28006
|
"/search/semantic/",
|
|
28629
28007
|
"/search/semantic/status/",
|
|
@@ -28902,22 +28280,6 @@ function openApiDocument(version) {
|
|
|
28902
28280
|
body: { type: "object", properties: { rebuild: { type: "boolean", default: false } } },
|
|
28903
28281
|
result: resultOf("semantic_index") ?? { type: "object" }
|
|
28904
28282
|
},
|
|
28905
|
-
{
|
|
28906
|
-
route: "/views/render/",
|
|
28907
|
-
operationId: "render_view",
|
|
28908
|
-
summary: "Render a view, or the text of a ```datanotes block, as Markdown (what a note shows).",
|
|
28909
|
-
body: {
|
|
28910
|
-
type: "object",
|
|
28911
|
-
properties: {
|
|
28912
|
-
view: { type: "string", description: "A view's name." },
|
|
28913
|
-
block: { type: "string", description: "The text of a ```datanotes block (instead of `view`)." },
|
|
28914
|
-
where: { type: "object", description: "Extra filter (with `view`)." },
|
|
28915
|
-
note: { type: "string", description: "The note the block is in: its frontmatter fills `{this.*}`." }
|
|
28916
|
-
}
|
|
28917
|
-
},
|
|
28918
|
-
result: { type: "object", additionalProperties: true },
|
|
28919
|
-
namesTable: true
|
|
28920
|
-
},
|
|
28921
28283
|
{
|
|
28922
28284
|
route: "/sessions/identify/",
|
|
28923
28285
|
operationId: "identify_session",
|
|
@@ -28939,17 +28301,6 @@ function openApiDocument(version) {
|
|
|
28939
28301
|
result: ok,
|
|
28940
28302
|
writes: true
|
|
28941
28303
|
},
|
|
28942
|
-
{
|
|
28943
|
-
route: "/api/",
|
|
28944
|
-
operationId: "engine_api",
|
|
28945
|
-
summary: "Call the engine's API method by method (owner only): what the remote engine client uses.",
|
|
28946
|
-
description: "`method` is a method of the engine's public API (camelCase, as in `src/core/public-api.ts`), `args` its positional arguments. Answers `{result}`.",
|
|
28947
|
-
body: { type: "object", required: ["method"], properties: { method: { type: "string" }, args: { type: "array", items: {} } } },
|
|
28948
|
-
bodyRequired: true,
|
|
28949
|
-
result: { type: "object", properties: { result: {} } },
|
|
28950
|
-
namesTable: true,
|
|
28951
|
-
writes: true
|
|
28952
|
-
},
|
|
28953
28304
|
{
|
|
28954
28305
|
route: "/openapi/",
|
|
28955
28306
|
operationId: "openapi_post",
|
|
@@ -30360,7 +29711,7 @@ var AppRegistry = class {
|
|
|
30360
29711
|
return null;
|
|
30361
29712
|
}
|
|
30362
29713
|
const keys = ROW_ROUTES[route];
|
|
30363
|
-
if (!keys) return a.maintain && !OWNER_ADMIN_ROUTES.has(route)
|
|
29714
|
+
if (!keys) return a.maintain && !OWNER_ADMIN_ROUTES.has(route) ? null : `app ${a.name} may not call ${route} (reserved to the owner)`;
|
|
30364
29715
|
const model = (await loadMetastore(this.deps.app, this.deps.getSettings()).catch(() => null))?.model ?? null;
|
|
30365
29716
|
for (const k of keys) {
|
|
30366
29717
|
const ref2 = b[k];
|
|
@@ -30692,22 +30043,13 @@ var EngineRuntime = class {
|
|
|
30692
30043
|
return this.httpServer !== null;
|
|
30693
30044
|
}
|
|
30694
30045
|
/**
|
|
30695
|
-
* Housekeeping of the hidden store: journal
|
|
30696
|
-
*
|
|
30046
|
+
* Housekeeping of the hidden store: journal entries and log files past their retention are
|
|
30047
|
+
* dropped.
|
|
30697
30048
|
*/
|
|
30698
30049
|
async maintainStore() {
|
|
30699
30050
|
const app = this.o.app;
|
|
30700
30051
|
const s = this.o.getSettings();
|
|
30701
30052
|
try {
|
|
30702
|
-
const imported = await importLegacyJournal(app, s);
|
|
30703
|
-
if (imported.imported > 0 || imported.errors.length > 0) {
|
|
30704
|
-
telemetry().log(imported.errors.length > 0 ? "WARN" : "INFO", "datanotes imported journal notes into the store", {
|
|
30705
|
-
imported: imported.imported,
|
|
30706
|
-
skipped: imported.skipped,
|
|
30707
|
-
removed: imported.removed,
|
|
30708
|
-
errors: imported.errors.length
|
|
30709
|
-
});
|
|
30710
|
-
}
|
|
30711
30053
|
const compacted = await compactJournal(app, s);
|
|
30712
30054
|
const logs = await pruneLogs(app, s);
|
|
30713
30055
|
if (compacted.dropped > 0 || compacted.blobsRemoved > 0 || logs.length > 0) {
|
|
@@ -30726,7 +30068,7 @@ var EngineRuntime = class {
|
|
|
30726
30068
|
const refreshMetastore = () => loadMetastore(app, s()).then((ms) => {
|
|
30727
30069
|
this.inverse.init();
|
|
30728
30070
|
return ms;
|
|
30729
|
-
}).
|
|
30071
|
+
}).catch((e) => telemetry().log("WARN", "datanotes could not read database.yaml", { error: errorText(e) }));
|
|
30730
30072
|
const logSoon = () => {
|
|
30731
30073
|
if (this.logTimer) clearTimeout(this.logTimer);
|
|
30732
30074
|
this.logTimer = setTimeout(() => {
|
|
@@ -30734,7 +30076,7 @@ var EngineRuntime = class {
|
|
|
30734
30076
|
void logExternalEdits(app, s());
|
|
30735
30077
|
}, EXTERNAL_EDIT_DELAY_MS);
|
|
30736
30078
|
};
|
|
30737
|
-
const watched = (path6) => path6 === metastorePath(s()) || path6.endsWith(".md")
|
|
30079
|
+
const watched = (path6) => path6 === metastorePath(s()) || path6.endsWith(".md");
|
|
30738
30080
|
const v = app.vault;
|
|
30739
30081
|
const mc = app.metadataCache;
|
|
30740
30082
|
this.listen(v, "modify", (f) => {
|
|
@@ -31211,8 +30553,8 @@ var DEFAULT_VAULT_CONFIG = {
|
|
|
31211
30553
|
trashOption: "system",
|
|
31212
30554
|
userIgnoreFilters: []
|
|
31213
30555
|
};
|
|
31214
|
-
function readVaultConfig(
|
|
31215
|
-
const file = import_node_path2.default.join(
|
|
30556
|
+
function readVaultConfig(root) {
|
|
30557
|
+
const file = import_node_path2.default.join(root, ".obsidian", "app.json");
|
|
31216
30558
|
let raw = {};
|
|
31217
30559
|
try {
|
|
31218
30560
|
raw = JSON.parse(import_node_fs2.default.readFileSync(file, "utf8"));
|
|
@@ -31230,7 +30572,6 @@ function readVaultConfig(root2) {
|
|
|
31230
30572
|
}
|
|
31231
30573
|
|
|
31232
30574
|
// src/node/node-app.ts
|
|
31233
|
-
var KEEP_ALL = "\0";
|
|
31234
30575
|
var NodeFile = class {
|
|
31235
30576
|
constructor(path6, stat) {
|
|
31236
30577
|
this.path = path6;
|
|
@@ -31283,19 +30624,19 @@ async function atomicWrite(abs, data) {
|
|
|
31283
30624
|
}
|
|
31284
30625
|
}
|
|
31285
30626
|
}
|
|
31286
|
-
function resolveInVault(
|
|
30627
|
+
function resolveInVault(root, rel) {
|
|
31287
30628
|
const parts = String(rel).split("/").filter((s) => s !== "" && s !== ".");
|
|
31288
30629
|
for (const s of parts) {
|
|
31289
30630
|
if (s === ".." || s.includes("\\") || s.includes("\0") || /^[A-Za-z]:/.test(s)) throw new Error(`path outside the vault refused: ${rel}`);
|
|
31290
30631
|
}
|
|
31291
|
-
const base = import_node_path3.default.resolve(
|
|
30632
|
+
const base = import_node_path3.default.resolve(root);
|
|
31292
30633
|
const abs = import_node_path3.default.resolve(base, ...parts);
|
|
31293
30634
|
if (abs !== base && !abs.startsWith(base + import_node_path3.default.sep)) throw new Error(`path outside the vault refused: ${rel}`);
|
|
31294
30635
|
return abs;
|
|
31295
30636
|
}
|
|
31296
30637
|
var NodeAdapter = class {
|
|
31297
|
-
constructor(
|
|
31298
|
-
this.root =
|
|
30638
|
+
constructor(root) {
|
|
30639
|
+
this.root = root;
|
|
31299
30640
|
}
|
|
31300
30641
|
abs(p) {
|
|
31301
30642
|
return resolveInVault(this.root, p);
|
|
@@ -31686,7 +31027,7 @@ var NodeMetadataCache = class {
|
|
|
31686
31027
|
let frontmatter2;
|
|
31687
31028
|
let body = text2;
|
|
31688
31029
|
try {
|
|
31689
|
-
const r =
|
|
31030
|
+
const r = readOrderedFromMarkdown(text2);
|
|
31690
31031
|
body = r.body;
|
|
31691
31032
|
if (r.ordered.length > 0) frontmatter2 = Object.fromEntries(r.ordered);
|
|
31692
31033
|
} catch {
|
|
@@ -31835,7 +31176,7 @@ var NodeFileManager = class {
|
|
|
31835
31176
|
const f = this.vault.getAbstractFileByPath(file.path);
|
|
31836
31177
|
if (!f) throw new Error(`file not found: ${file.path}`);
|
|
31837
31178
|
const text2 = await this.vault.read(f);
|
|
31838
|
-
const { ordered, body } =
|
|
31179
|
+
const { ordered, body } = readOrderedFromMarkdown(text2);
|
|
31839
31180
|
const fm = Object.fromEntries(ordered);
|
|
31840
31181
|
const before = JSON.stringify(fm);
|
|
31841
31182
|
fn(fm);
|
|
@@ -31847,8 +31188,8 @@ var NodeFileManager = class {
|
|
|
31847
31188
|
return this.vault.trash(file, true);
|
|
31848
31189
|
}
|
|
31849
31190
|
};
|
|
31850
|
-
function openNodeVault(
|
|
31851
|
-
const vault = new NodeVault(import_node_path3.default.resolve(
|
|
31191
|
+
function openNodeVault(root, config) {
|
|
31192
|
+
const vault = new NodeVault(import_node_path3.default.resolve(root), { ...readVaultConfig(root), ...config ?? {} });
|
|
31852
31193
|
vault.scanSync();
|
|
31853
31194
|
const metadataCache = new NodeMetadataCache(vault);
|
|
31854
31195
|
metadataCache.indexAll();
|
|
@@ -31923,7 +31264,7 @@ var NodeWatcher = class {
|
|
|
31923
31264
|
};
|
|
31924
31265
|
|
|
31925
31266
|
// src/node/service.ts
|
|
31926
|
-
var VERSION = true ? "
|
|
31267
|
+
var VERSION = true ? "2.0.0" : "dev";
|
|
31927
31268
|
function parseArgs(argv, env = process.env) {
|
|
31928
31269
|
const get = (name) => {
|
|
31929
31270
|
const i = argv.indexOf(`--${name}`);
|
|
@@ -32098,7 +31439,7 @@ Docs: https://datanotes.dev`;
|
|
|
32098
31439
|
}
|
|
32099
31440
|
|
|
32100
31441
|
// src/node/cli.ts
|
|
32101
|
-
var VERSION2 = true ? "
|
|
31442
|
+
var VERSION2 = true ? "2.0.0" : "dev";
|
|
32102
31443
|
async function main2(argv = process.argv.slice(2)) {
|
|
32103
31444
|
const [command, ...rest] = argv;
|
|
32104
31445
|
if (command === "--version" || command === "-v" || command === "version") return void process.stdout.write(`${VERSION2}
|