@agentshouse/mdruntime 0.1.0-c5f333dfa0583 → 0.1.0-c5fe3b2cddda7
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/README.md +10 -8
- package/dist/adapter.d.ts +39 -40
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +2 -1
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +28 -4
- package/dist/binary.d.ts +0 -5
- package/dist/binary.d.ts.map +1 -1
- package/dist/binary.js +1 -1
- package/dist/bootstrap.d.ts +16 -8
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +142 -94
- package/dist/change-set.d.ts +1 -7
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +1 -4
- package/dist/client.d.ts +6 -7
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +54 -7
- package/dist/collection.d.ts +5 -3
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +24 -19
- package/dist/compile.d.ts +6 -1
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +94 -33
- package/dist/connection.d.ts +8 -7
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +1160 -1151
- package/dist/conversation.d.ts +7 -5
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +171 -55
- package/dist/durability.d.ts +1 -5
- package/dist/durability.d.ts.map +1 -1
- package/dist/durability.js +5 -0
- package/dist/entry.d.ts +1 -0
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +1 -1
- package/dist/file.d.ts +2 -11
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +6 -4
- package/dist/fulltext.d.ts +27 -0
- package/dist/fulltext.d.ts.map +1 -0
- package/dist/fulltext.js +370 -0
- package/dist/host.d.ts +3 -4
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +42 -18
- package/dist/identity.d.ts +0 -1
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +0 -3
- package/dist/index.d.ts +10 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +2 -1
- package/dist/media.d.ts +8 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +218 -0
- package/dist/memory.d.ts +3 -2
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +93 -38
- package/dist/messages.d.ts +28 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +90 -0
- package/dist/model.d.ts +6 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +7 -10
- package/dist/observation.d.ts +1 -0
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +1 -1
- package/dist/outcome.d.ts +13 -6
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +16 -5
- package/dist/overlay.js +1 -1
- package/dist/paths.d.ts +1 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +4 -0
- package/dist/query.d.ts +10 -1
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +12 -1
- package/dist/reach.d.ts +8 -3
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +69 -46
- package/dist/readiness.d.ts +14 -15
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +2 -8
- package/dist/recovery.d.ts +1 -0
- package/dist/recovery.d.ts.map +1 -1
- package/dist/recovery.js +26 -0
- package/dist/refresh.d.ts +9 -4
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +64 -30
- package/dist/replica.d.ts +5 -5
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +4 -7
- package/dist/room-draft.d.ts +18 -2
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +73 -6
- package/dist/rows.d.ts +15 -6
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +102 -74
- package/dist/save.d.ts +2 -0
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +13 -7
- package/dist/search.d.ts +11 -43
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +0 -296
- package/dist/shared.d.ts +0 -1
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +0 -10
- package/dist/status.d.ts +4 -3
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +3 -1
- package/dist/store.d.ts +23 -58
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +37 -272
- package/dist/stored.d.ts +10 -23
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +217 -218
- package/dist/tables.d.ts +51 -46
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +94 -53
- package/dist/transfer.d.ts +0 -5
- package/dist/transfer.d.ts.map +1 -1
- package/dist/validation.d.ts +3 -4
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +35 -96
- package/dist/wire.d.ts +5 -5
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +2 -2
- package/dist/words.d.ts +19 -0
- package/dist/words.d.ts.map +1 -0
- package/dist/words.js +156 -0
- package/package.json +11 -19
- package/AGENTS.md +0 -312
- package/dist/chat/acts.d.ts +0 -33
- package/dist/chat/acts.d.ts.map +0 -1
- package/dist/chat/acts.js +0 -36
- package/dist/chat/context.d.ts +0 -3
- package/dist/chat/context.d.ts.map +0 -1
- package/dist/chat/context.js +0 -10
- package/dist/chat/earlier.d.ts +0 -10
- package/dist/chat/earlier.d.ts.map +0 -1
- package/dist/chat/earlier.js +0 -54
- package/dist/chat/house.d.ts +0 -25
- package/dist/chat/house.d.ts.map +0 -1
- package/dist/chat/house.js +0 -38
- package/dist/chat/input.d.ts +0 -11
- package/dist/chat/input.d.ts.map +0 -1
- package/dist/chat/input.js +0 -92
- package/dist/chat/kit.d.ts +0 -61
- package/dist/chat/kit.d.ts.map +0 -1
- package/dist/chat/kit.js +0 -123
- package/dist/chat/lasting.d.ts +0 -6
- package/dist/chat/lasting.d.ts.map +0 -1
- package/dist/chat/lasting.js +0 -19
- package/dist/chat/list.d.ts +0 -28
- package/dist/chat/list.d.ts.map +0 -1
- package/dist/chat/list.js +0 -103
- package/dist/chat/markdown.d.ts +0 -21
- package/dist/chat/markdown.d.ts.map +0 -1
- package/dist/chat/markdown.js +0 -246
- package/dist/chat/message.d.ts +0 -7
- package/dist/chat/message.d.ts.map +0 -1
- package/dist/chat/message.js +0 -254
- package/dist/chat/messages.d.ts +0 -35
- package/dist/chat/messages.d.ts.map +0 -1
- package/dist/chat/messages.js +0 -210
- package/dist/chat/name.d.ts +0 -7
- package/dist/chat/name.d.ts.map +0 -1
- package/dist/chat/name.js +0 -37
- package/dist/chat/opened.d.ts +0 -12
- package/dist/chat/opened.d.ts.map +0 -1
- package/dist/chat/opened.js +0 -19
- package/dist/chat/overlay.d.ts +0 -32
- package/dist/chat/overlay.d.ts.map +0 -1
- package/dist/chat/overlay.js +0 -103
- package/dist/chat/parts.d.ts +0 -58
- package/dist/chat/parts.d.ts.map +0 -1
- package/dist/chat/parts.js +0 -120
- package/dist/chat/pieces.d.ts +0 -62
- package/dist/chat/pieces.d.ts.map +0 -1
- package/dist/chat/pieces.js +0 -1110
- package/dist/chat/process.d.ts +0 -20
- package/dist/chat/process.d.ts.map +0 -1
- package/dist/chat/process.js +0 -32
- package/dist/chat/provider.d.ts +0 -70
- package/dist/chat/provider.d.ts.map +0 -1
- package/dist/chat/provider.js +0 -635
- package/dist/chat/question.d.ts +0 -9
- package/dist/chat/question.d.ts.map +0 -1
- package/dist/chat/question.js +0 -69
- package/dist/chat/questions.d.ts +0 -31
- package/dist/chat/questions.d.ts.map +0 -1
- package/dist/chat/questions.js +0 -111
- package/dist/chat/read.d.ts +0 -5
- package/dist/chat/read.d.ts.map +0 -1
- package/dist/chat/read.js +0 -13
- package/dist/chat/ready.d.ts +0 -37
- package/dist/chat/ready.d.ts.map +0 -1
- package/dist/chat/ready.js +0 -93
- package/dist/chat/room-file.d.ts +0 -8
- package/dist/chat/room-file.d.ts.map +0 -1
- package/dist/chat/room-file.js +0 -72
- package/dist/chat/steady.d.ts +0 -3
- package/dist/chat/steady.d.ts.map +0 -1
- package/dist/chat/steady.js +0 -26
- package/dist/chat/style.d.ts +0 -4
- package/dist/chat/style.d.ts.map +0 -1
- package/dist/chat/style.js +0 -307
- package/dist/chat.d.ts +0 -15
- package/dist/chat.d.ts.map +0 -1
- package/dist/chat.js +0 -8
- package/dist/reads.d.ts +0 -11
- package/dist/reads.d.ts.map +0 -1
- package/dist/reads.js +0 -98
package/dist/stored.js
CHANGED
|
@@ -1,28 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { composedOf } from './collection.js';
|
|
2
|
+
import { indexDocument, unindexAll, unindexDocuments } from './fulltext.js';
|
|
3
|
+
import { described, derived } from './rows.js';
|
|
3
4
|
export const REPLICA_TABLES = [
|
|
4
|
-
'CREATE TABLE replica_keys (key INTEGER PRIMARY KEY AUTOINCREMENT, locator TEXT NOT NULL, transfer TEXT NOT NULL,
|
|
5
|
+
'CREATE TABLE replica_keys (key INTEGER PRIMARY KEY AUTOINCREMENT, locator TEXT NOT NULL, transfer TEXT NOT NULL, fingerprint TEXT NOT NULL, rederiving INTEGER, searching INTEGER)',
|
|
5
6
|
'CREATE TABLE replica_rooms (locator TEXT PRIMARY KEY, key INTEGER NOT NULL, record TEXT NOT NULL) WITHOUT ROWID',
|
|
6
|
-
'CREATE TABLE replica_transfers (locator TEXT PRIMARY KEY, key INTEGER NOT NULL, record TEXT NOT NULL) WITHOUT ROWID',
|
|
7
7
|
'CREATE TABLE replica_entries (id INTEGER PRIMARY KEY, key INTEGER NOT NULL, layer INTEGER NOT NULL, path TEXT NOT NULL, visible INTEGER NOT NULL, present INTEGER NOT NULL, queried INTEGER NOT NULL, binary TEXT, revision TEXT, file_id TEXT, change TEXT, written TEXT, type TEXT, declared TEXT, folder TEXT NOT NULL, fields TEXT, content TEXT)',
|
|
8
8
|
'CREATE UNIQUE INDEX replica_entries_path ON replica_entries (key, layer, path)',
|
|
9
|
-
'CREATE INDEX replica_entries_visible ON replica_entries (key, visible, path)',
|
|
9
|
+
'CREATE INDEX replica_entries_visible ON replica_entries (key, visible, present, path, binary)',
|
|
10
10
|
'CREATE INDEX replica_entries_folder ON replica_entries (key, folder, path)',
|
|
11
|
-
'CREATE
|
|
12
|
-
'CREATE INDEX
|
|
13
|
-
'CREATE TABLE
|
|
14
|
-
'CREATE
|
|
11
|
+
'CREATE INDEX replica_entries_type ON replica_entries (key, type, visible, present, queried, folder)',
|
|
12
|
+
'CREATE INDEX replica_entries_key ON replica_entries (key)',
|
|
13
|
+
'CREATE TABLE replica_values (doc INTEGER NOT NULL, keys TEXT NOT NULL, places TEXT NOT NULL, item INTEGER NOT NULL, kind TEXT NOT NULL, value, size INTEGER, PRIMARY KEY (doc, keys, places, item)) WITHOUT ROWID',
|
|
14
|
+
'CREATE TABLE replica_links (doc INTEGER NOT NULL, key INTEGER NOT NULL, kind TEXT NOT NULL, keys TEXT NOT NULL, places TEXT NOT NULL, target TEXT NOT NULL, field TEXT NOT NULL, PRIMARY KEY (doc, kind, keys, places, target)) WITHOUT ROWID',
|
|
15
|
+
'CREATE INDEX replica_links_target ON replica_links (key, target, kind, keys)',
|
|
15
16
|
'CREATE TABLE replica_folders (key INTEGER NOT NULL, layer INTEGER NOT NULL, path TEXT NOT NULL, present INTEGER NOT NULL, PRIMARY KEY (key, layer, path)) WITHOUT ROWID',
|
|
16
17
|
'CREATE TABLE replica_erasing (key INTEGER PRIMARY KEY, locator TEXT NOT NULL)',
|
|
17
|
-
'CREATE TABLE replica_received (key TEXT PRIMARY KEY, head TEXT NOT NULL) WITHOUT ROWID',
|
|
18
|
-
'CREATE TABLE replica_received_parts (key TEXT NOT NULL, part INTEGER NOT NULL, value TEXT NOT NULL, PRIMARY KEY (key, part)) WITHOUT ROWID',
|
|
19
18
|
'CREATE TABLE replica_facts (name TEXT PRIMARY KEY, value TEXT NOT NULL) WITHOUT ROWID',
|
|
20
19
|
'CREATE TABLE replica_presentation (app TEXT PRIMARY KEY, value TEXT NOT NULL) WITHOUT ROWID',
|
|
21
20
|
];
|
|
22
21
|
const CONFIRMED = 0;
|
|
23
22
|
const OVERLAY = 1;
|
|
24
23
|
const REFRESHED = 2;
|
|
25
|
-
const
|
|
24
|
+
const DERIVED_ROWS = 64;
|
|
25
|
+
const ENTRY_WEIGHT = 256;
|
|
26
|
+
const ABSENT = {
|
|
27
|
+
type: null,
|
|
28
|
+
declared: null,
|
|
29
|
+
queried: false,
|
|
30
|
+
folder: '',
|
|
31
|
+
fields: null,
|
|
32
|
+
values: [],
|
|
33
|
+
links: [],
|
|
34
|
+
};
|
|
26
35
|
function text(value) {
|
|
27
36
|
return typeof value === 'string' ? value : null;
|
|
28
37
|
}
|
|
@@ -38,80 +47,54 @@ function flag(value) {
|
|
|
38
47
|
function paths(list) {
|
|
39
48
|
return JSON.stringify(list);
|
|
40
49
|
}
|
|
41
|
-
function compositionOf(connection, key) {
|
|
42
|
-
let held = compositions.get(connection);
|
|
43
|
-
if (held === undefined) {
|
|
44
|
-
held = new Map();
|
|
45
|
-
compositions.set(connection, held);
|
|
46
|
-
}
|
|
47
|
-
const [row] = connection.rows('SELECT composition FROM replica_keys WHERE key = ?', [key]);
|
|
48
|
-
const textual = text(row?.composition) ?? 'null';
|
|
49
|
-
const known = held.get(textual);
|
|
50
|
-
if (known !== undefined)
|
|
51
|
-
return known;
|
|
52
|
-
const parsed = JSON.parse(textual) ?? {
|
|
53
|
-
model: { status: 'unavailable', reason: 'not-acquired' },
|
|
54
|
-
selection: null,
|
|
55
|
-
};
|
|
56
|
-
held.clear();
|
|
57
|
-
held.set(textual, parsed);
|
|
58
|
-
return parsed;
|
|
59
|
-
}
|
|
60
|
-
export function fingerprint(composition) {
|
|
61
|
-
const shape = (model) => model.status === 'unavailable' ? null : model.types;
|
|
62
|
-
return JSON.stringify({
|
|
63
|
-
model: shape(composition.model),
|
|
64
|
-
selection: composition.selection === null
|
|
65
|
-
? null
|
|
66
|
-
: { roots: composition.selection.roots, model: shape(composition.selection.model) },
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
50
|
function dropDerived(connection, doc) {
|
|
70
51
|
connection.run('DELETE FROM replica_values WHERE doc = ?', [doc]);
|
|
71
52
|
connection.run('DELETE FROM replica_links WHERE doc = ?', [doc]);
|
|
72
53
|
}
|
|
54
|
+
function scalarText(value) {
|
|
55
|
+
if (value === Infinity)
|
|
56
|
+
return 'Infinity';
|
|
57
|
+
if (value === -Infinity)
|
|
58
|
+
return '-Infinity';
|
|
59
|
+
return JSON.stringify(value);
|
|
60
|
+
}
|
|
73
61
|
function writeDerived(connection, doc, key, made) {
|
|
74
|
-
|
|
75
|
-
|
|
62
|
+
if (made.values.length > 0) {
|
|
63
|
+
const rows = made.values.map((value) => `[${JSON.stringify(value.keys)},${JSON.stringify(value.places)},${value.item},${JSON.stringify(value.kind)},${scalarText(value.value)},${JSON.stringify(value.size)}]`);
|
|
64
|
+
connection.run('INSERT INTO replica_values (doc, keys, places, item, kind, value, size) SELECT ?, value ->> 0, value ->> 1, value ->> 2, value ->> 3, value ->> 4, value ->> 5 FROM json_each(?)', [doc, `[${rows.join(',')}]`]);
|
|
65
|
+
}
|
|
66
|
+
if (made.links.length > 0) {
|
|
67
|
+
connection.run('INSERT OR IGNORE INTO replica_links (doc, key, kind, keys, places, target, field) SELECT ?, ?, value ->> 0, value ->> 1, value ->> 2, value ->> 3, value ->> 4 FROM json_each(?)', [
|
|
76
68
|
doc,
|
|
77
69
|
key,
|
|
78
|
-
|
|
79
|
-
value.held,
|
|
80
|
-
value.item,
|
|
81
|
-
value.kind,
|
|
82
|
-
value.value,
|
|
83
|
-
value.size,
|
|
84
|
-
flag(value.single),
|
|
70
|
+
JSON.stringify(made.links.map((link) => [link.kind, link.keys, link.places, link.target, link.field])),
|
|
85
71
|
]);
|
|
86
72
|
}
|
|
87
|
-
for (const link of made.links) {
|
|
88
|
-
connection.run('INSERT OR IGNORE INTO replica_links (doc, key, kind, form, target, field) VALUES (?, ?, ?, ?, ?, ?)', [doc, key, link.kind, link.form, link.target, link.field]);
|
|
89
|
-
}
|
|
90
73
|
}
|
|
91
74
|
function entryId(connection, key, layer, path) {
|
|
92
75
|
const [row] = connection.rows('SELECT id FROM replica_entries WHERE key = ? AND layer = ? AND path = ?', [key, layer, path]);
|
|
93
76
|
return row === undefined ? null : number(row.id);
|
|
94
77
|
}
|
|
95
|
-
function
|
|
78
|
+
function words() {
|
|
79
|
+
return { dropped: [], made: [] };
|
|
80
|
+
}
|
|
81
|
+
function wordsWritten(connection, owed) {
|
|
82
|
+
unindexDocuments(connection, owed.dropped);
|
|
83
|
+
for (const { id, path, content } of owed.made)
|
|
84
|
+
indexDocument(connection, id, path, content);
|
|
85
|
+
}
|
|
86
|
+
function removeEntry(connection, key, layer, path, owed) {
|
|
96
87
|
const id = entryId(connection, key, layer, path);
|
|
97
88
|
if (id === null)
|
|
98
89
|
return;
|
|
99
90
|
dropDerived(connection, id);
|
|
91
|
+
owed.dropped.push(id);
|
|
100
92
|
connection.run('DELETE FROM replica_entries WHERE id = ?', [id]);
|
|
101
93
|
}
|
|
102
|
-
function
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
: {
|
|
107
|
-
type: null,
|
|
108
|
-
declared: null,
|
|
109
|
-
queried: false,
|
|
110
|
-
folder: '',
|
|
111
|
-
fields: null,
|
|
112
|
-
values: [],
|
|
113
|
-
links: [],
|
|
114
|
-
};
|
|
94
|
+
function heldIds(connection, sql, bind) {
|
|
95
|
+
return connection.rows(sql, bind).map((row) => number(row.id));
|
|
96
|
+
}
|
|
97
|
+
function insertEntry(connection, key, layer, entry, present, made) {
|
|
115
98
|
connection.run('INSERT INTO replica_entries (key, layer, path, visible, present, queried, content, binary, revision, file_id, change, written, type, declared, folder, fields) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [
|
|
116
99
|
key,
|
|
117
100
|
layer,
|
|
@@ -130,70 +113,76 @@ function putEntry(connection, key, layer, entry, present, composition) {
|
|
|
130
113
|
made.folder,
|
|
131
114
|
made.fields,
|
|
132
115
|
]);
|
|
116
|
+
}
|
|
117
|
+
function textOf(entry) {
|
|
118
|
+
return entry.binary === null ? entry.content : null;
|
|
119
|
+
}
|
|
120
|
+
function putEntry(connection, key, layer, entry, present, composition, owed, searched = true) {
|
|
121
|
+
removeEntry(connection, key, layer, entry.path, owed);
|
|
122
|
+
const content = textOf(entry);
|
|
123
|
+
const made = present ? derived(entry.path, content, composition) : ABSENT;
|
|
124
|
+
insertEntry(connection, key, layer, entry, present, made);
|
|
133
125
|
if (!present)
|
|
134
126
|
return;
|
|
135
127
|
const id = entryId(connection, key, layer, entry.path);
|
|
136
128
|
writeDerived(connection, id, key, made);
|
|
129
|
+
if (searched && content !== null && made.queried)
|
|
130
|
+
owed.made.push({ id, path: entry.path, content });
|
|
131
|
+
}
|
|
132
|
+
function placeEntry(connection, key, entry, owed) {
|
|
133
|
+
removeEntry(connection, key, CONFIRMED, entry.path, owed);
|
|
134
|
+
insertEntry(connection, key, CONFIRMED, entry, true, described(entry.path, textOf(entry)));
|
|
137
135
|
}
|
|
138
136
|
function revealed(connection, key, touched) {
|
|
139
137
|
if (touched.length === 0)
|
|
140
138
|
return;
|
|
141
139
|
connection.run(`UPDATE replica_entries SET visible = CASE WHEN layer = ${OVERLAY} THEN present ELSE NOT EXISTS (SELECT 1 FROM replica_entries o WHERE o.key = replica_entries.key AND o.layer = ${OVERLAY} AND o.path = replica_entries.path) END WHERE key = ? AND layer IN (${CONFIRMED}, ${OVERLAY}) AND path IN (SELECT value FROM json_each(?))`, [key, paths(touched)]);
|
|
142
140
|
}
|
|
143
|
-
function newKey(connection, locator, transfer,
|
|
144
|
-
|
|
141
|
+
function newKey(connection, locator, transfer, fingerprint, built) {
|
|
142
|
+
const owed = built ? null : 0;
|
|
143
|
+
connection.run('INSERT INTO replica_keys (locator, transfer, fingerprint, rederiving, searching) VALUES (?, ?, ?, ?, ?)', [locator, transfer, fingerprint, owed, owed]);
|
|
145
144
|
const [row] = connection.rows('SELECT last_insert_rowid() AS key');
|
|
146
145
|
return number(row.key);
|
|
147
146
|
}
|
|
148
|
-
function recomposed(connection, key,
|
|
149
|
-
const [row] = connection.rows('SELECT
|
|
150
|
-
|
|
151
|
-
if (before !== null && fingerprint(before) === fingerprint(composition)) {
|
|
152
|
-
connection.run('UPDATE replica_keys SET composition = ? WHERE key = ?', [
|
|
153
|
-
JSON.stringify(composition),
|
|
154
|
-
key,
|
|
155
|
-
]);
|
|
147
|
+
function recomposed(connection, key, fingerprint) {
|
|
148
|
+
const [row] = connection.rows('SELECT fingerprint FROM replica_keys WHERE key = ?', [key]);
|
|
149
|
+
if (row === undefined || text(row.fingerprint) === fingerprint)
|
|
156
150
|
return;
|
|
157
|
-
|
|
158
|
-
connection.run(
|
|
159
|
-
JSON.stringify(composition),
|
|
160
|
-
key,
|
|
161
|
-
]);
|
|
151
|
+
const held = connection.rows('SELECT 1 FROM replica_entries WHERE key = ? LIMIT 1', [key]);
|
|
152
|
+
connection.run(`UPDATE replica_keys SET fingerprint = ?${held.length === 0 ? '' : ', rederiving = 0'} WHERE key = ?`, [fingerprint, key]);
|
|
162
153
|
}
|
|
163
154
|
export function entered(connection, locator, composition, rows) {
|
|
164
|
-
const key = newKey(connection, locator, '', composition);
|
|
165
|
-
|
|
166
|
-
|
|
155
|
+
const key = newKey(connection, locator, '', composedOf(composition).fingerprint, true);
|
|
156
|
+
const owed = words();
|
|
157
|
+
for (const entry of rows) {
|
|
158
|
+
putEntry(connection, key, CONFIRMED, entry, true, composition, owed, false);
|
|
159
|
+
}
|
|
160
|
+
wordsWritten(connection, owed);
|
|
167
161
|
return key;
|
|
168
162
|
}
|
|
169
163
|
export function stage(connection, request) {
|
|
170
|
-
const [held] = connection.rows('SELECT key FROM replica_transfers WHERE locator = ?', [
|
|
171
|
-
request.locator,
|
|
172
|
-
]);
|
|
173
164
|
const key = request.key ??
|
|
174
|
-
(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
connection
|
|
180
|
-
}
|
|
181
|
-
const composition = compositionOf(connection, key);
|
|
182
|
-
for (const entry of request.entries) {
|
|
183
|
-
putEntry(connection, key, CONFIRMED, entry, true, composition);
|
|
184
|
-
}
|
|
165
|
+
newKey(connection, request.locator, request.transfer, request.fingerprint, false);
|
|
166
|
+
recomposed(connection, key, request.fingerprint);
|
|
167
|
+
connection.run('UPDATE replica_keys SET rederiving = coalesce(rederiving, last), searching = coalesce(searching, last) FROM (SELECT coalesce(max(id), 0) AS last FROM replica_entries) WHERE key = ?', [key]);
|
|
168
|
+
const owed = words();
|
|
169
|
+
for (const entry of request.entries)
|
|
170
|
+
placeEntry(connection, key, entry, owed);
|
|
185
171
|
for (const path of request.folders) {
|
|
186
172
|
connection.run('INSERT OR REPLACE INTO replica_folders (key, layer, path, present) VALUES (?, ?, ?, 1)', [key, CONFIRMED, path]);
|
|
187
173
|
}
|
|
174
|
+
wordsWritten(connection, owed);
|
|
188
175
|
return key;
|
|
189
176
|
}
|
|
190
177
|
export function refreshing(connection, request) {
|
|
191
|
-
const held = connection.rows('SELECT 1 FROM
|
|
178
|
+
const held = connection.rows('SELECT 1 FROM replica_keys k WHERE k.key = ? AND NOT EXISTS (SELECT 1 FROM replica_erasing e WHERE e.key = k.key)', [request.key]);
|
|
192
179
|
if (held.length === 0)
|
|
193
180
|
return null;
|
|
194
|
-
|
|
181
|
+
recomposed(connection, request.key, request.composed.fingerprint);
|
|
182
|
+
const composition = request.composed.composition;
|
|
183
|
+
const owed = words();
|
|
195
184
|
for (const entry of request.entries) {
|
|
196
|
-
putEntry(connection, request.key, REFRESHED, entry, true, composition);
|
|
185
|
+
putEntry(connection, request.key, REFRESHED, entry, true, composition, owed);
|
|
197
186
|
}
|
|
198
187
|
for (const path of request.removals) {
|
|
199
188
|
putEntry(connection, request.key, REFRESHED, {
|
|
@@ -204,7 +193,7 @@ export function refreshing(connection, request) {
|
|
|
204
193
|
fileId: null,
|
|
205
194
|
change: null,
|
|
206
195
|
written: null,
|
|
207
|
-
}, false, composition);
|
|
196
|
+
}, false, composition, owed);
|
|
208
197
|
}
|
|
209
198
|
for (const [list, present] of [
|
|
210
199
|
[request.folders, 1],
|
|
@@ -214,9 +203,11 @@ export function refreshing(connection, request) {
|
|
|
214
203
|
connection.run('INSERT OR REPLACE INTO replica_folders (key, layer, path, present) VALUES (?, ?, ?, ?)', [request.key, REFRESHED, path, present]);
|
|
215
204
|
}
|
|
216
205
|
}
|
|
206
|
+
wordsWritten(connection, owed);
|
|
217
207
|
return null;
|
|
218
208
|
}
|
|
219
209
|
function dropLayer(connection, key, layer) {
|
|
210
|
+
unindexDocuments(connection, heldIds(connection, 'SELECT id FROM replica_entries WHERE key = ? AND layer = ?', [key, layer]));
|
|
220
211
|
for (const table of ['replica_values', 'replica_links']) {
|
|
221
212
|
connection.run(`DELETE FROM ${table} WHERE doc IN (SELECT id FROM replica_entries WHERE key = ? AND layer = ?)`, [key, layer]);
|
|
222
213
|
}
|
|
@@ -235,6 +226,7 @@ function refreshedPaths(connection, key) {
|
|
|
235
226
|
function applyRefresh(connection, key) {
|
|
236
227
|
const touched = refreshedPaths(connection, key);
|
|
237
228
|
const replaced = `SELECT c.id FROM replica_entries c JOIN replica_entries r ON r.key = c.key AND r.layer = ${REFRESHED} AND r.path = c.path WHERE c.key = ? AND c.layer = ${CONFIRMED}`;
|
|
229
|
+
unindexDocuments(connection, heldIds(connection, replaced, [key]));
|
|
238
230
|
for (const table of ['replica_values', 'replica_links']) {
|
|
239
231
|
connection.run(`DELETE FROM ${table} WHERE doc IN (${replaced})`, [key]);
|
|
240
232
|
}
|
|
@@ -253,12 +245,11 @@ function applyRefresh(connection, key) {
|
|
|
253
245
|
connection.run('DELETE FROM replica_folders WHERE key = ? AND layer = ?', [key, REFRESHED]);
|
|
254
246
|
return touched;
|
|
255
247
|
}
|
|
248
|
+
function beneathRoots(path) {
|
|
249
|
+
return `EXISTS (SELECT 1 FROM json_each(?) r WHERE ${path} = r.value OR (${path} >= r.value || '/' AND ${path} < r.value || '0'))`;
|
|
250
|
+
}
|
|
256
251
|
function counted(connection, key, roots) {
|
|
257
|
-
const
|
|
258
|
-
const bind = [key];
|
|
259
|
-
for (const root of roots)
|
|
260
|
-
bind.push(root, `${root}/`, `${root}0`);
|
|
261
|
-
const [row] = connection.rows(`SELECT count(*) AS held FROM replica_entries WHERE key = ? AND visible = 1 AND present = 1 AND (binary IS NOT NULL OR substr(path, -3) = '.md')${roots.length === 0 ? '' : ` AND NOT (${outside})`}`, bind);
|
|
252
|
+
const [row] = connection.rows(`SELECT count(*) AS held FROM replica_entries WHERE key = ? AND visible = 1 AND present = 1 AND (binary IS NOT NULL OR substr(path, -3) = '.md') AND NOT ${beneathRoots('replica_entries.path')}`, [key, JSON.stringify(roots)]);
|
|
262
253
|
return number(row.held);
|
|
263
254
|
}
|
|
264
255
|
export function counts(connection, rooms) {
|
|
@@ -272,33 +263,32 @@ function erasing(connection, key, locator) {
|
|
|
272
263
|
}
|
|
273
264
|
function commitRoom(connection, room) {
|
|
274
265
|
const touched = new Set();
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
}
|
|
282
|
-
connection.run('DELETE FROM replica_transfers WHERE locator = ?', [room.locator]);
|
|
266
|
+
recomposed(connection, room.key, room.composed.fingerprint);
|
|
267
|
+
const composition = room.composed.composition;
|
|
268
|
+
if (room.published !== undefined &&
|
|
269
|
+
room.published.from !== null &&
|
|
270
|
+
room.published.from !== room.key) {
|
|
271
|
+
erasing(connection, room.published.from, room.locator);
|
|
283
272
|
}
|
|
284
273
|
if (room.refreshed === true) {
|
|
285
274
|
for (const path of applyRefresh(connection, room.key))
|
|
286
275
|
touched.add(path);
|
|
287
276
|
}
|
|
277
|
+
const owed = words();
|
|
288
278
|
for (const entry of room.confirmed?.set ?? []) {
|
|
289
|
-
putEntry(connection, room.key, CONFIRMED, entry, true, composition);
|
|
279
|
+
putEntry(connection, room.key, CONFIRMED, entry, true, composition, owed);
|
|
290
280
|
touched.add(entry.path);
|
|
291
281
|
}
|
|
292
282
|
for (const path of room.confirmed?.removed ?? []) {
|
|
293
|
-
removeEntry(connection, room.key, CONFIRMED, path);
|
|
283
|
+
removeEntry(connection, room.key, CONFIRMED, path, owed);
|
|
294
284
|
touched.add(path);
|
|
295
285
|
}
|
|
296
286
|
for (const entry of room.overlay?.set ?? []) {
|
|
297
|
-
putEntry(connection, room.key, OVERLAY, entry, entry.present, composition);
|
|
287
|
+
putEntry(connection, room.key, OVERLAY, entry, entry.present, composition, owed);
|
|
298
288
|
touched.add(entry.path);
|
|
299
289
|
}
|
|
300
290
|
for (const path of room.overlay?.cleared ?? []) {
|
|
301
|
-
removeEntry(connection, room.key, OVERLAY, path);
|
|
291
|
+
removeEntry(connection, room.key, OVERLAY, path, owed);
|
|
302
292
|
touched.add(path);
|
|
303
293
|
}
|
|
304
294
|
const changed = [...touched];
|
|
@@ -310,21 +300,25 @@ function commitRoom(connection, room) {
|
|
|
310
300
|
room.record,
|
|
311
301
|
]);
|
|
312
302
|
}
|
|
303
|
+
wordsWritten(connection, owed);
|
|
313
304
|
return room.published === undefined ? changed : null;
|
|
314
305
|
}
|
|
315
306
|
export function commit(connection, rooms) {
|
|
316
307
|
const counted = {};
|
|
317
308
|
const changed = {};
|
|
318
|
-
const
|
|
309
|
+
const indexed = {};
|
|
319
310
|
for (const room of rooms) {
|
|
320
311
|
changed[room.locator] = commitRoom(connection, room);
|
|
321
312
|
counted[room.locator] = counts(connection, [
|
|
322
313
|
{ key: room.key, roots: room.roots ?? rootsOf(connection, room.locator) },
|
|
323
314
|
])[0];
|
|
324
|
-
const [held] = connection.rows('SELECT rederiving FROM replica_keys WHERE key = ?', [
|
|
325
|
-
|
|
315
|
+
const [held] = connection.rows('SELECT rederiving, searching FROM replica_keys WHERE key = ?', [
|
|
316
|
+
room.key,
|
|
317
|
+
]);
|
|
318
|
+
indexed[room.locator] =
|
|
319
|
+
held !== undefined && held.rederiving === null && held.searching === null;
|
|
326
320
|
}
|
|
327
|
-
return { counts: counted, changed,
|
|
321
|
+
return { counts: counted, changed, indexed };
|
|
328
322
|
}
|
|
329
323
|
function rootsOf(connection, locator) {
|
|
330
324
|
const [row] = connection.rows('SELECT record FROM replica_rooms WHERE locator = ?', [locator]);
|
|
@@ -333,27 +327,24 @@ function rootsOf(connection, locator) {
|
|
|
333
327
|
}
|
|
334
328
|
export function fenceRooms(connection, locators) {
|
|
335
329
|
for (const locator of locators) {
|
|
336
|
-
for (const row of connection.rows('SELECT key FROM replica_keys WHERE locator = ? UNION SELECT key FROM replica_rooms WHERE locator = ?
|
|
330
|
+
for (const row of connection.rows('SELECT key FROM replica_keys WHERE locator = ? UNION SELECT key FROM replica_rooms WHERE locator = ?', [locator, locator])) {
|
|
337
331
|
erasing(connection, number(row.key), locator);
|
|
338
332
|
}
|
|
339
333
|
connection.run('DELETE FROM replica_rooms WHERE locator = ?', [locator]);
|
|
340
|
-
connection.run('DELETE FROM replica_transfers WHERE locator = ?', [locator]);
|
|
341
334
|
}
|
|
342
335
|
return null;
|
|
343
336
|
}
|
|
344
|
-
export function abandon(connection, locator
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
return number(held.key);
|
|
337
|
+
export function abandon(connection, locator) {
|
|
338
|
+
for (const row of connection.rows(`SELECT k.key FROM replica_keys k WHERE k.locator = ?
|
|
339
|
+
AND NOT EXISTS (SELECT 1 FROM replica_rooms r WHERE r.key = k.key)
|
|
340
|
+
AND NOT EXISTS (SELECT 1 FROM replica_erasing e WHERE e.key = k.key)`, [locator])) {
|
|
341
|
+
erasing(connection, number(row.key), locator);
|
|
342
|
+
}
|
|
343
|
+
return null;
|
|
352
344
|
}
|
|
353
345
|
export function release(connection, key) {
|
|
354
346
|
const [held] = connection.rows(`SELECT k.locator FROM replica_keys k WHERE k.key = ?
|
|
355
|
-
AND NOT EXISTS (SELECT 1 FROM replica_rooms r WHERE r.key = k.key)
|
|
356
|
-
AND NOT EXISTS (SELECT 1 FROM replica_transfers t WHERE t.key = k.key)`, [key]);
|
|
347
|
+
AND NOT EXISTS (SELECT 1 FROM replica_rooms r WHERE r.key = k.key)`, [key]);
|
|
357
348
|
if (held !== undefined)
|
|
358
349
|
erasing(connection, key, text(held.locator));
|
|
359
350
|
return null;
|
|
@@ -364,6 +355,7 @@ export function erase(connection, locator, limit) {
|
|
|
364
355
|
return { remaining: false };
|
|
365
356
|
const key = number(held.key);
|
|
366
357
|
const batch = 'SELECT id FROM replica_entries WHERE key = ? ORDER BY id LIMIT ?';
|
|
358
|
+
unindexDocuments(connection, heldIds(connection, batch, [key, limit]));
|
|
367
359
|
for (const table of ['replica_values', 'replica_links']) {
|
|
368
360
|
connection.run(`DELETE FROM ${table} WHERE doc IN (${batch})`, [key, limit]);
|
|
369
361
|
}
|
|
@@ -377,28 +369,70 @@ export function erase(connection, locator, limit) {
|
|
|
377
369
|
const [more] = connection.rows(`SELECT 1 FROM replica_erasing${locator === null ? '' : ' WHERE locator = ?'} LIMIT 1`, locator === null ? [] : [locator]);
|
|
378
370
|
return { remaining: more !== undefined };
|
|
379
371
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
const
|
|
385
|
-
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
372
|
+
function cursor(value) {
|
|
373
|
+
return value === null || value === undefined ? null : number(value);
|
|
374
|
+
}
|
|
375
|
+
export function rederive(connection, key, composed, bytes, ms, floor) {
|
|
376
|
+
const started = performance.now();
|
|
377
|
+
recomposed(connection, key, composed.fingerprint);
|
|
378
|
+
const [held] = connection.rows('SELECT rederiving, searching FROM replica_keys WHERE key = ?', [
|
|
379
|
+
key,
|
|
380
|
+
]);
|
|
381
|
+
const deriving = cursor(held?.rederiving);
|
|
382
|
+
const searching = cursor(held?.searching);
|
|
383
|
+
if (deriving === null && searching === null)
|
|
384
|
+
return { done: true, text: 0 };
|
|
385
|
+
const composition = composed.composition;
|
|
386
|
+
let last = Math.min(deriving ?? Infinity, searching ?? Infinity);
|
|
387
|
+
let spent = 0;
|
|
388
|
+
let built = 0;
|
|
389
|
+
let read = false;
|
|
390
|
+
const late = () => spent >= floor && performance.now() - started >= ms;
|
|
391
|
+
const owed = [];
|
|
392
|
+
reading: for (;;) {
|
|
393
|
+
const rows = connection.rows('SELECT id, path, content FROM replica_entries WHERE key = ? AND present = 1 AND id > ? ORDER BY id LIMIT ?', [key, last, DERIVED_ROWS]);
|
|
394
|
+
for (const row of rows) {
|
|
395
|
+
const id = number(row.id);
|
|
396
|
+
const path = text(row.path);
|
|
397
|
+
const content = text(row.content);
|
|
398
|
+
const owedRows = deriving !== null && id > deriving;
|
|
399
|
+
const owedWords = searching !== null && id > searching && content !== null;
|
|
400
|
+
if (owedRows) {
|
|
401
|
+
const made = derived(path, content, composition);
|
|
402
|
+
dropDerived(connection, id);
|
|
403
|
+
writeDerived(connection, id, key, made);
|
|
404
|
+
}
|
|
405
|
+
if (owedWords && described(path, content).queried)
|
|
406
|
+
owed.push({ id, path, content });
|
|
407
|
+
else if (owedRows)
|
|
408
|
+
built += content?.length ?? 0;
|
|
409
|
+
last = id;
|
|
410
|
+
spent += ENTRY_WEIGHT + (content?.length ?? 0);
|
|
411
|
+
if (spent >= bytes || late())
|
|
412
|
+
break reading;
|
|
413
|
+
}
|
|
414
|
+
if (rows.length < DERIVED_ROWS) {
|
|
415
|
+
read = true;
|
|
416
|
+
break;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
let searched = last;
|
|
420
|
+
for (const [at, { id, path, content }] of owed.entries()) {
|
|
421
|
+
indexDocument(connection, id, path, content);
|
|
422
|
+
built += content.length;
|
|
423
|
+
const next = owed[at + 1];
|
|
424
|
+
if (next !== undefined && late()) {
|
|
425
|
+
searched = next.id - 1;
|
|
426
|
+
break;
|
|
427
|
+
}
|
|
394
428
|
}
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
done ? null :
|
|
429
|
+
const done = read && searched === last;
|
|
430
|
+
connection.run('UPDATE replica_keys SET rederiving = ?, searching = ? WHERE key = ?', [
|
|
431
|
+
deriving === null || read ? null : Math.max(deriving, last),
|
|
432
|
+
searching === null || done ? null : Math.max(searching, searched),
|
|
399
433
|
key,
|
|
400
434
|
]);
|
|
401
|
-
return { done };
|
|
435
|
+
return { done, text: built };
|
|
402
436
|
}
|
|
403
437
|
function heldEntry(row) {
|
|
404
438
|
return {
|
|
@@ -413,12 +447,31 @@ function heldEntry(row) {
|
|
|
413
447
|
};
|
|
414
448
|
}
|
|
415
449
|
const ENTRY_COLUMNS = 'e.path, e.content, e.binary, e.revision, e.file_id, e.change, e.written, e.type';
|
|
450
|
+
function unrefreshed(alias) {
|
|
451
|
+
return `NOT EXISTS (SELECT 1 FROM replica_entries r WHERE r.key = ${alias}.key AND r.layer = ${REFRESHED} AND r.path = ${alias}.path)`;
|
|
452
|
+
}
|
|
416
453
|
function viewed(view, alias) {
|
|
417
454
|
if (view === 'visible')
|
|
418
455
|
return `${alias}.visible = 1 AND ${alias}.present = 1`;
|
|
419
456
|
if (view === 'confirmed')
|
|
420
457
|
return `${alias}.layer = ${CONFIRMED}`;
|
|
421
|
-
return `${alias}.present = 1 AND (${alias}.layer = ${REFRESHED} OR (${alias}.layer = ${CONFIRMED} AND
|
|
458
|
+
return `${alias}.present = 1 AND (${alias}.layer = ${REFRESHED} OR (${alias}.layer = ${CONFIRMED} AND ${unrefreshed(alias)}))`;
|
|
459
|
+
}
|
|
460
|
+
function layers(view) {
|
|
461
|
+
if (view !== 'refreshed')
|
|
462
|
+
return [viewed(view, 'e')];
|
|
463
|
+
return [
|
|
464
|
+
`e.layer = ${REFRESHED} AND e.present = 1`,
|
|
465
|
+
`e.layer = ${CONFIRMED} AND e.present = 1 AND ${unrefreshed('e')}`,
|
|
466
|
+
];
|
|
467
|
+
}
|
|
468
|
+
function pathOrdered(connection, columns, key, view, condition, after, limit) {
|
|
469
|
+
const beyond = after === null ? '' : ' AND e.path > ?';
|
|
470
|
+
const parts = layers(view).map((layer) => `SELECT ${columns} FROM replica_entries e WHERE e.key = ? AND ${layer}${condition}${beyond}`);
|
|
471
|
+
return connection.rows(`${parts.join(' UNION ALL ')} ORDER BY path LIMIT ?`, [
|
|
472
|
+
...parts.flatMap(() => (after === null ? [key] : [key, after])),
|
|
473
|
+
limit,
|
|
474
|
+
]);
|
|
422
475
|
}
|
|
423
476
|
export function entries(connection, key, view, list) {
|
|
424
477
|
if (list.length === 0)
|
|
@@ -449,64 +502,14 @@ export function referrers(connection, key, view, targets, kinds) {
|
|
|
449
502
|
kind: text(row.kind),
|
|
450
503
|
}));
|
|
451
504
|
}
|
|
452
|
-
export function walk(connection, key, view, after, bytes) {
|
|
453
|
-
const found = [];
|
|
454
|
-
let spent = 0;
|
|
455
|
-
let from = after;
|
|
456
|
-
for (;;) {
|
|
457
|
-
const rows = connection.rows(`SELECT ${ENTRY_COLUMNS} FROM replica_entries e WHERE e.key = ? AND ${viewed(view, 'e')}${from === null ? '' : ' AND e.path > ?'} ORDER BY e.path LIMIT 64`, from === null ? [key] : [key, from]);
|
|
458
|
-
for (const row of rows) {
|
|
459
|
-
const entry = heldEntry(row);
|
|
460
|
-
found.push(entry);
|
|
461
|
-
spent += 256 + (entry.content?.length ?? 0) * 2;
|
|
462
|
-
if (spent >= bytes)
|
|
463
|
-
return { entries: found, next: entry.path };
|
|
464
|
-
}
|
|
465
|
-
if (rows.length < 64)
|
|
466
|
-
return { entries: found, next: null };
|
|
467
|
-
from = found.at(-1).path;
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
505
|
export function files(connection, key, view, after, limit) {
|
|
471
|
-
return connection
|
|
472
|
-
|
|
473
|
-
|
|
506
|
+
return pathOrdered(connection, 'e.path, e.revision', key, view, ' AND e.content IS NOT NULL AND e.revision IS NOT NULL', after, limit).map((row) => ({ path: text(row.path), revision: text(row.revision) }));
|
|
507
|
+
}
|
|
508
|
+
export function folders(connection, key, view, list) {
|
|
509
|
+
return list.filter((path) => connection.rows(`SELECT 1 FROM replica_folders f WHERE f.key = ? AND f.layer = ${CONFIRMED} AND f.present = 1 AND f.path = ? UNION ALL SELECT 1 FROM replica_entries e WHERE e.key = ? AND ${viewed(view, 'e')} AND e.path >= ? AND e.path < ? LIMIT 1`, [key, path, key, `${path}/`, `${path}0`]).length > 0);
|
|
474
510
|
}
|
|
475
511
|
export function typedWithin(connection, key, view, roots, within) {
|
|
476
|
-
|
|
477
|
-
const bind = [key];
|
|
478
|
-
for (const root of roots)
|
|
479
|
-
bind.push(root, `${root}/`, `${root}0`);
|
|
480
|
-
const placed = roots.length === 0 ? (within ? ' AND 0' : '') : ` AND ${within ? '' : 'NOT '}(${inside})`;
|
|
481
|
-
return (connection.rows(`SELECT 1 FROM replica_entries e WHERE e.key = ? AND ${viewed(view, 'e')} AND e.declared IS NOT NULL AND e.declared <> 'any'${placed} LIMIT 1`, bind).length > 0);
|
|
482
|
-
}
|
|
483
|
-
export function searched(connection, key, locator, after, limit, only) {
|
|
484
|
-
const bind = [key];
|
|
485
|
-
if (only !== null)
|
|
486
|
-
bind.push(paths(only));
|
|
487
|
-
if (after !== null)
|
|
488
|
-
bind.push(after);
|
|
489
|
-
bind.push(limit);
|
|
490
|
-
const rows = connection.rows(`SELECT e.path, e.type, e.fields, e.content FROM replica_entries e WHERE e.key = ? AND e.visible = 1 AND e.present = 1 AND e.queried = 1 AND e.type IS NOT NULL${only === null ? '' : ' AND e.path IN (SELECT value FROM json_each(?))'}${after === null ? '' : ' AND e.path > ?'} ORDER BY e.path LIMIT ?`, bind);
|
|
491
|
-
const documents = [];
|
|
492
|
-
for (const row of rows) {
|
|
493
|
-
const path = text(row.path);
|
|
494
|
-
const read = parse(text(row.content) ?? '', path);
|
|
495
|
-
if (!read.ok || !markdownPath(path))
|
|
496
|
-
continue;
|
|
497
|
-
documents.push({
|
|
498
|
-
room: locator,
|
|
499
|
-
path,
|
|
500
|
-
type: text(row.type),
|
|
501
|
-
fields: json(row.fields) ?? {},
|
|
502
|
-
preamble: read.document.preamble,
|
|
503
|
-
sections: read.document.sections,
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
return {
|
|
507
|
-
documents,
|
|
508
|
-
next: rows.length < limit ? null : text(rows.at(-1).path),
|
|
509
|
-
};
|
|
512
|
+
return (connection.rows(`SELECT 1 FROM replica_entries e WHERE e.key = ? AND ${viewed(view, 'e')} AND e.declared IS NOT NULL AND e.declared <> 'any' AND ${within ? '' : 'NOT '}${beneathRoots('e.path')} LIMIT 1`, [key, JSON.stringify(roots)]).length > 0);
|
|
510
513
|
}
|
|
511
514
|
export function opened(connection) {
|
|
512
515
|
const facts = {};
|
|
@@ -519,18 +522,14 @@ export function opened(connection) {
|
|
|
519
522
|
key: number(row.key),
|
|
520
523
|
record: text(row.record),
|
|
521
524
|
})),
|
|
522
|
-
transfers: connection.rows('SELECT locator, key, record FROM replica_transfers').map((row) => ({
|
|
523
|
-
locator: text(row.locator),
|
|
524
|
-
key: number(row.key),
|
|
525
|
-
record: text(row.record),
|
|
526
|
-
})),
|
|
527
525
|
keys: connection
|
|
528
|
-
.rows('SELECT key, locator, transfer, rederiving FROM replica_keys')
|
|
526
|
+
.rows('SELECT key, locator, transfer, rederiving, searching FROM replica_keys')
|
|
529
527
|
.map((row) => ({
|
|
530
528
|
key: number(row.key),
|
|
531
529
|
locator: text(row.locator),
|
|
532
530
|
transfer: text(row.transfer),
|
|
533
|
-
rederiving:
|
|
531
|
+
rederiving: cursor(row.rederiving),
|
|
532
|
+
searching: cursor(row.searching),
|
|
534
533
|
})),
|
|
535
534
|
facts,
|
|
536
535
|
presentation: connection.rows('SELECT app, value FROM replica_presentation').map((row) => ({
|
|
@@ -543,7 +542,6 @@ export function opened(connection) {
|
|
|
543
542
|
orphans: connection
|
|
544
543
|
.rows(`SELECT k.key FROM replica_keys k
|
|
545
544
|
WHERE NOT EXISTS (SELECT 1 FROM replica_rooms r WHERE r.key = k.key)
|
|
546
|
-
AND NOT EXISTS (SELECT 1 FROM replica_transfers t WHERE t.key = k.key)
|
|
547
545
|
AND NOT EXISTS (SELECT 1 FROM replica_erasing e WHERE e.key = k.key)`)
|
|
548
546
|
.map((row) => number(row.key)),
|
|
549
547
|
erasing: connection.rows('SELECT key, locator FROM replica_erasing').map((row) => ({
|
|
@@ -558,4 +556,5 @@ export function ended(connection) {
|
|
|
558
556
|
if (table !== undefined)
|
|
559
557
|
connection.run(`DELETE FROM ${table}`);
|
|
560
558
|
}
|
|
559
|
+
unindexAll(connection);
|
|
561
560
|
}
|