@tensorix/metahub 0.4.1 → 0.5.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/cli.js +2311 -1633
- package/dist/cli.js.map +26 -22
- package/dist/core/audit.d.ts +97 -0
- package/dist/core/audit.d.ts.map +1 -0
- package/dist/core/crdt.d.ts +13 -1
- package/dist/core/crdt.d.ts.map +1 -1
- package/dist/core/databases.d.ts.map +1 -1
- package/dist/core/documents.d.ts +6 -0
- package/dist/core/documents.d.ts.map +1 -1
- package/dist/core/grants-core.d.ts.map +1 -1
- package/dist/core/history.d.ts +31 -0
- package/dist/core/history.d.ts.map +1 -1
- package/dist/core/indexing.d.ts +1 -1
- package/dist/core/integrity.d.ts +1 -1
- package/dist/core/integrity.d.ts.map +1 -1
- package/dist/core/properties.d.ts +1 -1
- package/dist/core/properties.d.ts.map +1 -1
- package/dist/core/records.d.ts +5 -0
- package/dist/core/records.d.ts.map +1 -1
- package/dist/core/relation-cells.d.ts +23 -0
- package/dist/core/relation-cells.d.ts.map +1 -0
- package/dist/core/resolve.d.ts +4 -0
- package/dist/core/resolve.d.ts.map +1 -1
- package/dist/core/sync/files.d.ts.map +1 -1
- package/dist/core/sync/server.d.ts.map +1 -1
- package/dist/core/sync/share-serve.d.ts.map +1 -1
- package/dist/db-worker.js +100 -98
- package/dist/edge-worker.js +74 -26
- package/dist/index.js +2267 -1423
- package/dist/index.js.map +18 -16
- package/dist/metahub-sdk.js +7 -7
- package/dist/mh-runtime.js +1 -1
- package/dist/sw.js +7 -7
- package/dist/webui/server/assets.d.ts +3 -1
- package/dist/webui/server/assets.d.ts.map +1 -1
- package/dist/webui/server/changes-route.d.ts +7 -0
- package/dist/webui/server/changes-route.d.ts.map +1 -0
- package/dist/webui/server/routes.d.ts.map +1 -1
- package/dist/webui-fmt-clang.js +1 -1
- package/dist/webui-fmt-gofmt.js +1 -1
- package/dist/webui-fmt-lua.js +2 -2
- package/dist/webui-fmt-ruff.js +2 -2
- package/dist/webui-fmt-sh.js +8 -8
- package/dist/webui-fmt-taplo.js +2 -2
- package/dist/webui-fmt.js +346 -346
- package/dist/webui.js +178 -174
- package/package.json +1 -1
package/dist/edge-worker.js
CHANGED
|
@@ -327,6 +327,7 @@ function intentSubmissionExpired(submittedAt, now = Date.now()) {
|
|
|
327
327
|
var CHANGE_COLS = ["hlc", "node_id", "dataset", "row_id", "col", "value", "txn"];
|
|
328
328
|
var CHANGE_SELECT = CHANGE_COLS.join(", ");
|
|
329
329
|
var currentTxn = null;
|
|
330
|
+
var currentActor = null;
|
|
330
331
|
var currentNodeOverride = null;
|
|
331
332
|
function withNodeId(node, fn) {
|
|
332
333
|
const prev = currentNodeOverride;
|
|
@@ -340,7 +341,7 @@ function withNodeId(node, fn) {
|
|
|
340
341
|
function withChangeGroup(label, fn) {
|
|
341
342
|
if (currentTxn !== null)
|
|
342
343
|
return fn();
|
|
343
|
-
currentTxn = (label ? label + ":" : "") + randomSuffix(8);
|
|
344
|
+
currentTxn = (currentActor ? currentActor + "/" : "") + (label ? label + ":" : "") + randomSuffix(8);
|
|
344
345
|
try {
|
|
345
346
|
return fn();
|
|
346
347
|
} finally {
|
|
@@ -565,7 +566,7 @@ function ensurePropIndex(db, databaseId, propId) {
|
|
|
565
566
|
function maybeAutoIndex(db, databaseId, prop) {
|
|
566
567
|
if (hasIndex(db, databaseId, prop.id))
|
|
567
568
|
return;
|
|
568
|
-
if (prop.type !== "relation") {
|
|
569
|
+
if (prop.type !== "relation" && prop.type !== "doc") {
|
|
569
570
|
const row = db.query("SELECT COUNT(*) AS c FROM records WHERE database_id = ? AND __deleted = 0").get(databaseId);
|
|
570
571
|
if (row.c < AUTO_INDEX_ROW_THRESHOLD)
|
|
571
572
|
return;
|
|
@@ -582,6 +583,7 @@ var PROP_TYPES = new Set([
|
|
|
582
583
|
"multi_select",
|
|
583
584
|
"date",
|
|
584
585
|
"relation",
|
|
586
|
+
"doc",
|
|
585
587
|
"url"
|
|
586
588
|
]);
|
|
587
589
|
var PROPERTY_COLS = ["id", "database_id", "name", "type", "config", "position"];
|
|
@@ -614,7 +616,7 @@ var addProperty = grouped(function addProperty2(db, databaseId, opts) {
|
|
|
614
616
|
emit(db, "properties", id, "type", opts.type);
|
|
615
617
|
emit(db, "properties", id, "config", config);
|
|
616
618
|
emit(db, "properties", id, "position", opts.position ?? nextPosition(db, databaseId));
|
|
617
|
-
if (opts.type === "relation" || opts.indexed === true)
|
|
619
|
+
if (opts.type === "relation" || opts.type === "doc" || opts.indexed === true)
|
|
618
620
|
ensurePropIndex(db, databaseId, id);
|
|
619
621
|
return getProperty(db, id);
|
|
620
622
|
});
|
|
@@ -886,6 +888,20 @@ function resolveRelation(db, prop, value) {
|
|
|
886
888
|
}
|
|
887
889
|
throw new MhError("ambiguous", `${prop.name}: ambiguous relation "${value}" (${cands.length} matches); use a full id`);
|
|
888
890
|
}
|
|
891
|
+
function resolveDoc(db, prop, value) {
|
|
892
|
+
const cands = resolveCandidates(db, value, { kind: "doc" });
|
|
893
|
+
const exact = cands.find((c) => c.id === value);
|
|
894
|
+
if (exact)
|
|
895
|
+
return exact.id;
|
|
896
|
+
if (cands.length === 1)
|
|
897
|
+
return cands[0].id;
|
|
898
|
+
if (cands.length === 0) {
|
|
899
|
+
if (idKind(value) === "doc")
|
|
900
|
+
return value;
|
|
901
|
+
throw new MhError("not_found", `${prop.name}: no such document: ${value}`);
|
|
902
|
+
}
|
|
903
|
+
throw new MhError("ambiguous", `${prop.name}: ambiguous document "${value}" (${cands.length} matches); use a full id`);
|
|
904
|
+
}
|
|
889
905
|
function coerce(db, prop, value) {
|
|
890
906
|
switch (prop.type) {
|
|
891
907
|
case "text":
|
|
@@ -934,6 +950,10 @@ function coerce(db, prop, value) {
|
|
|
934
950
|
const arr = value === null ? [] : Array.isArray(value) ? value : [value];
|
|
935
951
|
return arr.map((v) => resolveRelation(db, prop, String(v)));
|
|
936
952
|
}
|
|
953
|
+
case "doc": {
|
|
954
|
+
const arr = value === null ? [] : Array.isArray(value) ? value : [value];
|
|
955
|
+
return arr.map((v) => resolveDoc(db, prop, String(v)));
|
|
956
|
+
}
|
|
937
957
|
}
|
|
938
958
|
}
|
|
939
959
|
function propsByName(props) {
|
|
@@ -1147,11 +1167,16 @@ var moveRecord = grouped(function moveRecord2(db, id, targetId, where) {
|
|
|
1147
1167
|
return getRecord(db, id);
|
|
1148
1168
|
});
|
|
1149
1169
|
var updateRecordPrepared = grouped(function updateRecordPrepared2(db, id, cells) {
|
|
1150
|
-
const rec = db.query("SELECT id, database_id FROM records WHERE id = ? AND __deleted = 0").get(id);
|
|
1170
|
+
const rec = db.query("SELECT id, database_id, data FROM records WHERE id = ? AND __deleted = 0").get(id);
|
|
1151
1171
|
if (!rec)
|
|
1152
1172
|
throw new MhError("not_found", `no such record: ${id}`);
|
|
1153
|
-
|
|
1154
|
-
|
|
1173
|
+
const cur = JSON.parse(rec.data || "{}");
|
|
1174
|
+
for (const { prop, value } of cells) {
|
|
1175
|
+
const exists = Object.hasOwn(cur, prop.id);
|
|
1176
|
+
const same = value === undefined ? !exists : exists && JSON.stringify(value) === JSON.stringify(cur[prop.id]);
|
|
1177
|
+
if (!same)
|
|
1178
|
+
emit(db, "records", id, prop.id, value);
|
|
1179
|
+
}
|
|
1155
1180
|
return getRecord(db, id);
|
|
1156
1181
|
});
|
|
1157
1182
|
var updateRecord = grouped(function updateRecord2(db, id, data) {
|
|
@@ -1212,19 +1237,38 @@ var duplicateDatabase = grouped(function duplicateDatabase2(db, id, opts = {}) {
|
|
|
1212
1237
|
emit(db, "databases", dup.id, "meta", meta);
|
|
1213
1238
|
}
|
|
1214
1239
|
const propIdMap = new Map;
|
|
1240
|
+
const selfRelNew = new Set;
|
|
1215
1241
|
for (const p of listProperties(db, id)) {
|
|
1216
|
-
const
|
|
1242
|
+
const self = p.type === "relation" && p.config?.database === id;
|
|
1243
|
+
const config = self ? { ...p.config, database: dup.id } : p.config ?? undefined;
|
|
1217
1244
|
const np = addProperty(db, dup.id, { name: p.name, type: p.type, config, position: p.position });
|
|
1218
1245
|
propIdMap.set(p.id, np.id);
|
|
1246
|
+
if (self)
|
|
1247
|
+
selfRelNew.add(np.id);
|
|
1219
1248
|
}
|
|
1220
|
-
|
|
1249
|
+
const srcRecords = listRecords(db, id);
|
|
1250
|
+
const recIdMap = new Map;
|
|
1251
|
+
for (const r of srcRecords) {
|
|
1221
1252
|
const data = {};
|
|
1222
1253
|
for (const [pid, v] of Object.entries(r.cells)) {
|
|
1223
1254
|
const nid = propIdMap.get(pid);
|
|
1224
|
-
if (nid)
|
|
1225
|
-
|
|
1255
|
+
if (!nid)
|
|
1256
|
+
continue;
|
|
1257
|
+
if (selfRelNew.has(nid) && Array.isArray(v) && v.length > 0)
|
|
1258
|
+
continue;
|
|
1259
|
+
data[nid] = v;
|
|
1260
|
+
}
|
|
1261
|
+
recIdMap.set(r.id, createRecord(db, dup.id, data).id);
|
|
1262
|
+
}
|
|
1263
|
+
for (const r of srcRecords) {
|
|
1264
|
+
const patch = {};
|
|
1265
|
+
for (const [pid, v] of Object.entries(r.cells)) {
|
|
1266
|
+
const nid = propIdMap.get(pid);
|
|
1267
|
+
if (nid && selfRelNew.has(nid) && Array.isArray(v) && v.length > 0)
|
|
1268
|
+
patch[nid] = v.map((x) => recIdMap.get(String(x)) ?? x);
|
|
1226
1269
|
}
|
|
1227
|
-
|
|
1270
|
+
if (Object.keys(patch).length)
|
|
1271
|
+
updateRecord(db, recIdMap.get(r.id), patch);
|
|
1228
1272
|
}
|
|
1229
1273
|
return getDatabase(db, dup.id);
|
|
1230
1274
|
});
|
|
@@ -1363,29 +1407,33 @@ function liveRowCount(db, databaseId) {
|
|
|
1363
1407
|
}
|
|
1364
1408
|
function assertRelationAllowed(set, principalKind, prop) {
|
|
1365
1409
|
if (principalKind === "public")
|
|
1366
|
-
throw new MhError("invalid_input", `${prop.name}:
|
|
1410
|
+
throw new MhError("invalid_input", `${prop.name}: ${prop.type} properties are not writable anonymously`);
|
|
1411
|
+
if (prop.type === "doc")
|
|
1412
|
+
throw new MhError("invalid_input", `${prop.name}: doc properties are not writable via shares (grants cannot scope documents)`);
|
|
1367
1413
|
const target = prop.config?.database;
|
|
1368
1414
|
if (!target || !grantFor(set, target))
|
|
1369
1415
|
throw new MhError("invalid_input", `${prop.name}: relation target database is not in this share's grants`);
|
|
1370
1416
|
}
|
|
1417
|
+
function isLiveRefValue(prop, value) {
|
|
1418
|
+
return (prop.type === "relation" || prop.type === "doc") && value != null && !(Array.isArray(value) && value.length === 0);
|
|
1419
|
+
}
|
|
1371
1420
|
function assertGuestPayload(db, set, principal, database, values, opts = {}) {
|
|
1372
1421
|
const limits = opts.limits ?? GUEST_LIMITS;
|
|
1373
1422
|
const entries = Object.entries(values);
|
|
1374
1423
|
if (entries.length > limits.maxCells)
|
|
1375
1424
|
throw new MhError("invalid_input", `too many cells (max ${limits.maxCells})`);
|
|
1376
1425
|
const props = listProperties(db, database.id);
|
|
1377
|
-
const resolved = resolveData(props, values).map(({ prop, value }) =>
|
|
1378
|
-
prop,
|
|
1379
|
-
|
|
1380
|
-
|
|
1426
|
+
const resolved = resolveData(props, values).map(({ prop, value }) => {
|
|
1427
|
+
if (isLiveRefValue(prop, value))
|
|
1428
|
+
assertRelationAllowed(set, principal.kind, prop);
|
|
1429
|
+
return { prop, value: coerce(db, prop, value) };
|
|
1430
|
+
});
|
|
1381
1431
|
let total = 0;
|
|
1382
1432
|
for (const { prop, value } of resolved) {
|
|
1383
1433
|
const size = utf8Len(JSON.stringify(value ?? null));
|
|
1384
1434
|
if (size > limits.maxValueBytes)
|
|
1385
1435
|
throw new MhError("invalid_input", `${prop.name}: value too large (max ${limits.maxValueBytes} bytes)`);
|
|
1386
1436
|
total += size;
|
|
1387
|
-
if (prop.type === "relation" && value != null && !(Array.isArray(value) && value.length === 0))
|
|
1388
|
-
assertRelationAllowed(set, principal.kind, prop);
|
|
1389
1437
|
}
|
|
1390
1438
|
if (total > limits.maxBodyBytes)
|
|
1391
1439
|
throw new MhError("invalid_input", `payload too large (max ${limits.maxBodyBytes} bytes)`);
|
|
@@ -4026,13 +4074,13 @@ var edge_worker_default = {
|
|
|
4026
4074
|
}
|
|
4027
4075
|
};
|
|
4028
4076
|
export {
|
|
4029
|
-
|
|
4030
|
-
createInboxFetch,
|
|
4031
|
-
MhRoom,
|
|
4032
|
-
EDGE_WORKER_VERSION,
|
|
4033
|
-
EDGE_WORKER_MARKER,
|
|
4034
|
-
EDGE_SCHEMA_SQL,
|
|
4035
|
-
DROP_ENVELOPE_LIMIT_BYTES,
|
|
4077
|
+
DROP_DEFAULT_MAX_BYTES,
|
|
4036
4078
|
DROP_DEFAULT_MAX_ENVELOPES,
|
|
4037
|
-
|
|
4079
|
+
DROP_ENVELOPE_LIMIT_BYTES,
|
|
4080
|
+
EDGE_SCHEMA_SQL,
|
|
4081
|
+
EDGE_WORKER_MARKER,
|
|
4082
|
+
EDGE_WORKER_VERSION,
|
|
4083
|
+
MhRoom,
|
|
4084
|
+
createInboxFetch,
|
|
4085
|
+
edge_worker_default as default
|
|
4038
4086
|
};
|