@agentshouse/mdruntime 0.1.0-cee9c8aa4cd86 → 0.1.0-cef5833f6c689
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 +11 -9
- package/dist/adapter.d.ts +96 -67
- 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 +17 -9
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +143 -94
- package/dist/chain.d.ts +2 -1
- package/dist/chain.d.ts.map +1 -1
- package/dist/client.d.ts +12 -12
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +54 -8
- package/dist/collection.d.ts +7 -4
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +24 -19
- package/dist/compile.d.ts +1 -6
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +118 -247
- package/dist/connection.d.ts +11 -11
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +1598 -1248
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/{chat/context.js → context.js} +1 -4
- package/dist/conversation.d.ts +18 -15
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +268 -171
- 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 +3 -2
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +15 -6
- package/dist/file.d.ts +2 -11
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +6 -4
- package/dist/host.d.ts +3 -6
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +49 -35
- 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 +15 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/job.d.ts +14 -0
- package/dist/job.d.ts.map +1 -0
- package/dist/job.js +28 -0
- package/dist/live.d.ts +2 -1
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +9 -5
- 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 +11 -6
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +178 -101
- package/dist/messages.d.ts +2 -2
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +15 -16
- package/dist/model.d.ts +7 -3
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +7 -13
- package/dist/observation.d.ts +3 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +8 -3
- 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 -205
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +3 -494
- package/dist/reach.d.ts +14 -9
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +81 -71
- package/dist/react.d.ts +3 -1
- package/dist/react.d.ts.map +1 -1
- package/dist/readiness.d.ts +13 -16
- 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 +10 -4
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +104 -30
- package/dist/replica.d.ts +6 -5
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +8 -7
- package/dist/room-draft.d.ts +22 -5
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +131 -51
- package/dist/rows.d.ts +8 -15
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +51 -151
- 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 +12 -63
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +9 -52
- 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 +32 -31
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +67 -63
- package/dist/stored.d.ts +42 -18
- package/dist/stored.d.ts.map +1 -1
- package/dist/stored.js +193 -194
- package/dist/tables.d.ts +60 -40
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js +78 -62
- 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 +39 -97
- package/dist/windows.d.ts +1 -12
- package/dist/windows.d.ts.map +1 -1
- package/dist/windows.js +2 -75
- package/dist/wire.d.ts +6 -9
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +3 -3
- package/package.json +11 -18
- package/AGENTS.md +0 -320
- 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/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/fulltext.d.ts +0 -27
- package/dist/fulltext.d.ts.map +0 -1
- package/dist/fulltext.js +0 -368
- package/dist/reads.d.ts +0 -11
- package/dist/reads.d.ts.map +0 -1
- package/dist/reads.js +0 -98
- package/dist/words.d.ts +0 -19
- package/dist/words.d.ts.map +0 -1
- package/dist/words.js +0 -150
package/dist/stored.js
CHANGED
|
@@ -1,28 +1,38 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { sql } from '@agentshouse/mdmodel';
|
|
2
|
+
import { composedOf } from './collection.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)',
|
|
5
6
|
'CREATE TABLE replica_rooms (locator TEXT PRIMARY KEY, key INTEGER NOT NULL, record TEXT NOT NULL) WITHOUT ROWID',
|
|
6
|
-
'CREATE TABLE
|
|
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)',
|
|
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, outline 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
|
-
|
|
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
|
+
sql.VALUE_TABLE,
|
|
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
|
|
18
|
-
'CREATE TABLE replica_received_parts (key TEXT NOT NULL, part INTEGER NOT NULL, value TEXT NOT NULL, PRIMARY KEY (key, part)) WITHOUT ROWID',
|
|
18
|
+
'CREATE TABLE replica_opened (locator TEXT NOT NULL, path TEXT NOT NULL, PRIMARY KEY (locator, path)) WITHOUT ROWID',
|
|
19
19
|
'CREATE TABLE replica_facts (name TEXT PRIMARY KEY, value TEXT NOT NULL) WITHOUT ROWID',
|
|
20
20
|
'CREATE TABLE replica_presentation (app TEXT PRIMARY KEY, value TEXT NOT NULL) WITHOUT ROWID',
|
|
21
21
|
];
|
|
22
22
|
const CONFIRMED = 0;
|
|
23
23
|
const OVERLAY = 1;
|
|
24
24
|
const REFRESHED = 2;
|
|
25
|
-
const
|
|
25
|
+
const DERIVED_ROWS = 64;
|
|
26
|
+
const ENTRY_WEIGHT = 256;
|
|
27
|
+
const ABSENT = {
|
|
28
|
+
type: null,
|
|
29
|
+
declared: null,
|
|
30
|
+
queried: false,
|
|
31
|
+
folder: '',
|
|
32
|
+
fields: null,
|
|
33
|
+
values: [],
|
|
34
|
+
links: [],
|
|
35
|
+
};
|
|
26
36
|
function text(value) {
|
|
27
37
|
return typeof value === 'string' ? value : null;
|
|
28
38
|
}
|
|
@@ -38,55 +48,22 @@ function flag(value) {
|
|
|
38
48
|
function paths(list) {
|
|
39
49
|
return JSON.stringify(list);
|
|
40
50
|
}
|
|
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
51
|
function dropDerived(connection, doc) {
|
|
70
52
|
connection.run('DELETE FROM replica_values WHERE doc = ?', [doc]);
|
|
71
53
|
connection.run('DELETE FROM replica_links WHERE doc = ?', [doc]);
|
|
72
54
|
}
|
|
73
55
|
function writeDerived(connection, doc, key, made) {
|
|
74
|
-
|
|
75
|
-
|
|
56
|
+
if (made.values.length > 0) {
|
|
57
|
+
const inserted = sql.insertedValues(doc, made.values);
|
|
58
|
+
connection.run(inserted.sql, inserted.bind);
|
|
59
|
+
}
|
|
60
|
+
if (made.links.length > 0) {
|
|
61
|
+
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
62
|
doc,
|
|
77
63
|
key,
|
|
78
|
-
|
|
79
|
-
value.held,
|
|
80
|
-
value.item,
|
|
81
|
-
value.kind,
|
|
82
|
-
value.value,
|
|
83
|
-
value.size,
|
|
84
|
-
flag(value.single),
|
|
64
|
+
JSON.stringify(made.links.map((link) => [link.kind, link.keys, link.places, link.target, link.field])),
|
|
85
65
|
]);
|
|
86
66
|
}
|
|
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
67
|
}
|
|
91
68
|
function entryId(connection, key, layer, path) {
|
|
92
69
|
const [row] = connection.rows('SELECT id FROM replica_entries WHERE key = ? AND layer = ? AND path = ?', [key, layer, path]);
|
|
@@ -97,26 +74,10 @@ function removeEntry(connection, key, layer, path) {
|
|
|
97
74
|
if (id === null)
|
|
98
75
|
return;
|
|
99
76
|
dropDerived(connection, id);
|
|
100
|
-
unindexDocuments(connection, [id]);
|
|
101
77
|
connection.run('DELETE FROM replica_entries WHERE id = ?', [id]);
|
|
102
78
|
}
|
|
103
|
-
function
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
function putEntry(connection, key, layer, entry, present, composition, searched = true) {
|
|
107
|
-
removeEntry(connection, key, layer, entry.path);
|
|
108
|
-
const made = present
|
|
109
|
-
? derived(entry.path, entry.binary === null ? entry.content : null, composition)
|
|
110
|
-
: {
|
|
111
|
-
type: null,
|
|
112
|
-
declared: null,
|
|
113
|
-
queried: false,
|
|
114
|
-
folder: '',
|
|
115
|
-
fields: null,
|
|
116
|
-
values: [],
|
|
117
|
-
links: [],
|
|
118
|
-
};
|
|
119
|
-
connection.run('INSERT INTO replica_entries (key, layer, path, visible, present, queried, content, binary, revision, file_id, change, written, type, declared, folder, fields) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [
|
|
79
|
+
function insertEntry(connection, key, layer, entry, present, made) {
|
|
80
|
+
connection.run('INSERT INTO replica_entries (key, layer, path, visible, present, queried, content, outline, binary, revision, file_id, change, written, type, declared, folder, fields) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [
|
|
120
81
|
key,
|
|
121
82
|
layer,
|
|
122
83
|
entry.path,
|
|
@@ -124,6 +85,7 @@ function putEntry(connection, key, layer, entry, present, composition, searched
|
|
|
124
85
|
flag(present),
|
|
125
86
|
flag(made.queried),
|
|
126
87
|
entry.binary === null ? entry.content : null,
|
|
88
|
+
entry.binary === null && entry.outline !== null ? JSON.stringify(entry.outline) : null,
|
|
127
89
|
entry.binary === null ? null : JSON.stringify(entry.binary),
|
|
128
90
|
entry.revision,
|
|
129
91
|
entry.fileId,
|
|
@@ -134,71 +96,66 @@ function putEntry(connection, key, layer, entry, present, composition, searched
|
|
|
134
96
|
made.folder,
|
|
135
97
|
made.fields,
|
|
136
98
|
]);
|
|
99
|
+
}
|
|
100
|
+
function textOf(entry) {
|
|
101
|
+
return entry.binary === null ? entry.content : null;
|
|
102
|
+
}
|
|
103
|
+
function putEntry(connection, key, layer, entry, present, composition) {
|
|
104
|
+
removeEntry(connection, key, layer, entry.path);
|
|
105
|
+
const content = textOf(entry);
|
|
106
|
+
const made = present ? derived(entry.path, content, entry.outline, composition) : ABSENT;
|
|
107
|
+
insertEntry(connection, key, layer, entry, present, made);
|
|
137
108
|
if (!present)
|
|
138
109
|
return;
|
|
139
110
|
const id = entryId(connection, key, layer, entry.path);
|
|
140
111
|
writeDerived(connection, id, key, made);
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
112
|
+
}
|
|
113
|
+
function placeEntry(connection, key, entry) {
|
|
114
|
+
removeEntry(connection, key, CONFIRMED, entry.path);
|
|
115
|
+
insertEntry(connection, key, CONFIRMED, entry, true, described(entry.path, textOf(entry), entry.outline));
|
|
144
116
|
}
|
|
145
117
|
function revealed(connection, key, touched) {
|
|
146
118
|
if (touched.length === 0)
|
|
147
119
|
return;
|
|
148
120
|
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)]);
|
|
149
121
|
}
|
|
150
|
-
function newKey(connection, locator, transfer,
|
|
151
|
-
|
|
122
|
+
function newKey(connection, locator, transfer, fingerprint, built) {
|
|
123
|
+
const owed = built ? null : 0;
|
|
124
|
+
connection.run('INSERT INTO replica_keys (locator, transfer, fingerprint, rederiving) VALUES (?, ?, ?, ?)', [locator, transfer, fingerprint, owed]);
|
|
152
125
|
const [row] = connection.rows('SELECT last_insert_rowid() AS key');
|
|
153
126
|
return number(row.key);
|
|
154
127
|
}
|
|
155
|
-
function recomposed(connection, key,
|
|
156
|
-
const [row] = connection.rows('SELECT
|
|
157
|
-
|
|
158
|
-
if (before !== null && fingerprint(before) === fingerprint(composition)) {
|
|
159
|
-
connection.run('UPDATE replica_keys SET composition = ? WHERE key = ?', [
|
|
160
|
-
JSON.stringify(composition),
|
|
161
|
-
key,
|
|
162
|
-
]);
|
|
128
|
+
function recomposed(connection, key, fingerprint) {
|
|
129
|
+
const [row] = connection.rows('SELECT fingerprint FROM replica_keys WHERE key = ?', [key]);
|
|
130
|
+
if (row === undefined || text(row.fingerprint) === fingerprint)
|
|
163
131
|
return;
|
|
164
|
-
|
|
165
|
-
connection.run(
|
|
166
|
-
JSON.stringify(composition),
|
|
167
|
-
key,
|
|
168
|
-
]);
|
|
132
|
+
const held = connection.rows('SELECT 1 FROM replica_entries WHERE key = ? LIMIT 1', [key]);
|
|
133
|
+
connection.run(`UPDATE replica_keys SET fingerprint = ?${held.length === 0 ? '' : ', rederiving = 0'} WHERE key = ?`, [fingerprint, key]);
|
|
169
134
|
}
|
|
170
135
|
export function entered(connection, locator, composition, rows) {
|
|
171
|
-
const key = newKey(connection, locator, '', composition);
|
|
136
|
+
const key = newKey(connection, locator, '', composedOf(composition).fingerprint, true);
|
|
172
137
|
for (const entry of rows)
|
|
173
|
-
putEntry(connection, key, CONFIRMED, entry, true, composition
|
|
138
|
+
putEntry(connection, key, CONFIRMED, entry, true, composition);
|
|
174
139
|
return key;
|
|
175
140
|
}
|
|
176
141
|
export function stage(connection, request) {
|
|
177
|
-
const [held] = connection.rows('SELECT key FROM replica_transfers WHERE locator = ?', [
|
|
178
|
-
request.locator,
|
|
179
|
-
]);
|
|
180
142
|
const key = request.key ??
|
|
181
|
-
(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
connection.run('INSERT OR REPLACE INTO replica_transfers (locator, key, record) VALUES (?, ?, ?)', [request.locator, key, request.record]);
|
|
187
|
-
}
|
|
188
|
-
const composition = compositionOf(connection, key);
|
|
189
|
-
for (const entry of request.entries) {
|
|
190
|
-
putEntry(connection, key, CONFIRMED, entry, true, composition);
|
|
191
|
-
}
|
|
143
|
+
newKey(connection, request.locator, request.transfer, request.fingerprint, false);
|
|
144
|
+
recomposed(connection, key, request.fingerprint);
|
|
145
|
+
connection.run('UPDATE replica_keys SET rederiving = coalesce(rederiving, last) FROM (SELECT coalesce(max(id), 0) AS last FROM replica_entries) WHERE key = ?', [key]);
|
|
146
|
+
for (const entry of request.entries)
|
|
147
|
+
placeEntry(connection, key, entry);
|
|
192
148
|
for (const path of request.folders) {
|
|
193
149
|
connection.run('INSERT OR REPLACE INTO replica_folders (key, layer, path, present) VALUES (?, ?, ?, 1)', [key, CONFIRMED, path]);
|
|
194
150
|
}
|
|
195
151
|
return key;
|
|
196
152
|
}
|
|
197
153
|
export function refreshing(connection, request) {
|
|
198
|
-
const held = connection.rows('SELECT 1 FROM
|
|
154
|
+
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]);
|
|
199
155
|
if (held.length === 0)
|
|
200
156
|
return null;
|
|
201
|
-
|
|
157
|
+
recomposed(connection, request.key, request.composed.fingerprint);
|
|
158
|
+
const composition = request.composed.composition;
|
|
202
159
|
for (const entry of request.entries) {
|
|
203
160
|
putEntry(connection, request.key, REFRESHED, entry, true, composition);
|
|
204
161
|
}
|
|
@@ -206,6 +163,7 @@ export function refreshing(connection, request) {
|
|
|
206
163
|
putEntry(connection, request.key, REFRESHED, {
|
|
207
164
|
path,
|
|
208
165
|
content: null,
|
|
166
|
+
outline: null,
|
|
209
167
|
binary: null,
|
|
210
168
|
revision: null,
|
|
211
169
|
fileId: null,
|
|
@@ -224,7 +182,6 @@ export function refreshing(connection, request) {
|
|
|
224
182
|
return null;
|
|
225
183
|
}
|
|
226
184
|
function dropLayer(connection, key, layer) {
|
|
227
|
-
unindexDocuments(connection, heldIds(connection, 'SELECT id FROM replica_entries WHERE key = ? AND layer = ?', [key, layer]));
|
|
228
185
|
for (const table of ['replica_values', 'replica_links']) {
|
|
229
186
|
connection.run(`DELETE FROM ${table} WHERE doc IN (SELECT id FROM replica_entries WHERE key = ? AND layer = ?)`, [key, layer]);
|
|
230
187
|
}
|
|
@@ -243,7 +200,6 @@ function refreshedPaths(connection, key) {
|
|
|
243
200
|
function applyRefresh(connection, key) {
|
|
244
201
|
const touched = refreshedPaths(connection, key);
|
|
245
202
|
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}`;
|
|
246
|
-
unindexDocuments(connection, heldIds(connection, replaced, [key]));
|
|
247
203
|
for (const table of ['replica_values', 'replica_links']) {
|
|
248
204
|
connection.run(`DELETE FROM ${table} WHERE doc IN (${replaced})`, [key]);
|
|
249
205
|
}
|
|
@@ -262,12 +218,11 @@ function applyRefresh(connection, key) {
|
|
|
262
218
|
connection.run('DELETE FROM replica_folders WHERE key = ? AND layer = ?', [key, REFRESHED]);
|
|
263
219
|
return touched;
|
|
264
220
|
}
|
|
221
|
+
function beneathRoots(path) {
|
|
222
|
+
return `EXISTS (SELECT 1 FROM json_each(?) r WHERE ${path} = r.value OR (${path} >= r.value || '/' AND ${path} < r.value || '0'))`;
|
|
223
|
+
}
|
|
265
224
|
function counted(connection, key, roots) {
|
|
266
|
-
const
|
|
267
|
-
const bind = [key];
|
|
268
|
-
for (const root of roots)
|
|
269
|
-
bind.push(root, `${root}/`, `${root}0`);
|
|
270
|
-
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);
|
|
225
|
+
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)]);
|
|
271
226
|
return number(row.held);
|
|
272
227
|
}
|
|
273
228
|
export function counts(connection, rooms) {
|
|
@@ -281,14 +236,12 @@ function erasing(connection, key, locator) {
|
|
|
281
236
|
}
|
|
282
237
|
function commitRoom(connection, room) {
|
|
283
238
|
const touched = new Set();
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
291
|
-
connection.run('DELETE FROM replica_transfers WHERE locator = ?', [room.locator]);
|
|
239
|
+
recomposed(connection, room.key, room.composed.fingerprint);
|
|
240
|
+
const composition = room.composed.composition;
|
|
241
|
+
if (room.published !== undefined &&
|
|
242
|
+
room.published.from !== null &&
|
|
243
|
+
room.published.from !== room.key) {
|
|
244
|
+
erasing(connection, room.published.from, room.locator);
|
|
292
245
|
}
|
|
293
246
|
if (room.refreshed === true) {
|
|
294
247
|
for (const path of applyRefresh(connection, room.key))
|
|
@@ -324,16 +277,16 @@ function commitRoom(connection, room) {
|
|
|
324
277
|
export function commit(connection, rooms) {
|
|
325
278
|
const counted = {};
|
|
326
279
|
const changed = {};
|
|
327
|
-
const
|
|
280
|
+
const indexed = {};
|
|
328
281
|
for (const room of rooms) {
|
|
329
282
|
changed[room.locator] = commitRoom(connection, room);
|
|
330
283
|
counted[room.locator] = counts(connection, [
|
|
331
284
|
{ key: room.key, roots: room.roots ?? rootsOf(connection, room.locator) },
|
|
332
285
|
])[0];
|
|
333
286
|
const [held] = connection.rows('SELECT rederiving FROM replica_keys WHERE key = ?', [room.key]);
|
|
334
|
-
|
|
287
|
+
indexed[room.locator] = held !== undefined && held.rederiving === null;
|
|
335
288
|
}
|
|
336
|
-
return { counts: counted, changed,
|
|
289
|
+
return { counts: counted, changed, indexed };
|
|
337
290
|
}
|
|
338
291
|
function rootsOf(connection, locator) {
|
|
339
292
|
const [row] = connection.rows('SELECT record FROM replica_rooms WHERE locator = ?', [locator]);
|
|
@@ -342,27 +295,25 @@ function rootsOf(connection, locator) {
|
|
|
342
295
|
}
|
|
343
296
|
export function fenceRooms(connection, locators) {
|
|
344
297
|
for (const locator of locators) {
|
|
345
|
-
for (const row of connection.rows('SELECT key FROM replica_keys WHERE locator = ? UNION SELECT key FROM replica_rooms WHERE locator = ?
|
|
298
|
+
for (const row of connection.rows('SELECT key FROM replica_keys WHERE locator = ? UNION SELECT key FROM replica_rooms WHERE locator = ?', [locator, locator])) {
|
|
346
299
|
erasing(connection, number(row.key), locator);
|
|
347
300
|
}
|
|
348
301
|
connection.run('DELETE FROM replica_rooms WHERE locator = ?', [locator]);
|
|
349
|
-
connection.run('DELETE FROM
|
|
302
|
+
connection.run('DELETE FROM replica_opened WHERE locator = ?', [locator]);
|
|
350
303
|
}
|
|
351
304
|
return null;
|
|
352
305
|
}
|
|
353
|
-
export function abandon(connection, locator
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
return number(held.key);
|
|
306
|
+
export function abandon(connection, locator) {
|
|
307
|
+
for (const row of connection.rows(`SELECT k.key FROM replica_keys k WHERE k.locator = ?
|
|
308
|
+
AND NOT EXISTS (SELECT 1 FROM replica_rooms r WHERE r.key = k.key)
|
|
309
|
+
AND NOT EXISTS (SELECT 1 FROM replica_erasing e WHERE e.key = k.key)`, [locator])) {
|
|
310
|
+
erasing(connection, number(row.key), locator);
|
|
311
|
+
}
|
|
312
|
+
return null;
|
|
361
313
|
}
|
|
362
314
|
export function release(connection, key) {
|
|
363
315
|
const [held] = connection.rows(`SELECT k.locator FROM replica_keys k WHERE k.key = ?
|
|
364
|
-
AND NOT EXISTS (SELECT 1 FROM replica_rooms r WHERE r.key = k.key)
|
|
365
|
-
AND NOT EXISTS (SELECT 1 FROM replica_transfers t WHERE t.key = k.key)`, [key]);
|
|
316
|
+
AND NOT EXISTS (SELECT 1 FROM replica_rooms r WHERE r.key = k.key)`, [key]);
|
|
366
317
|
if (held !== undefined)
|
|
367
318
|
erasing(connection, key, text(held.locator));
|
|
368
319
|
return null;
|
|
@@ -373,7 +324,6 @@ export function erase(connection, locator, limit) {
|
|
|
373
324
|
return { remaining: false };
|
|
374
325
|
const key = number(held.key);
|
|
375
326
|
const batch = 'SELECT id FROM replica_entries WHERE key = ? ORDER BY id LIMIT ?';
|
|
376
|
-
unindexDocuments(connection, heldIds(connection, batch, [key, limit]));
|
|
377
327
|
for (const table of ['replica_values', 'replica_links']) {
|
|
378
328
|
connection.run(`DELETE FROM ${table} WHERE doc IN (${batch})`, [key, limit]);
|
|
379
329
|
}
|
|
@@ -387,33 +337,92 @@ export function erase(connection, locator, limit) {
|
|
|
387
337
|
const [more] = connection.rows(`SELECT 1 FROM replica_erasing${locator === null ? '' : ' WHERE locator = ?'} LIMIT 1`, locator === null ? [] : [locator]);
|
|
388
338
|
return { remaining: more !== undefined };
|
|
389
339
|
}
|
|
390
|
-
|
|
340
|
+
function cursor(value) {
|
|
341
|
+
return value === null || value === undefined ? null : number(value);
|
|
342
|
+
}
|
|
343
|
+
export function rederive(connection, key, composed, bytes, ms, floor) {
|
|
344
|
+
const started = performance.now();
|
|
345
|
+
recomposed(connection, key, composed.fingerprint);
|
|
391
346
|
const [held] = connection.rows('SELECT rederiving FROM replica_keys WHERE key = ?', [key]);
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
const composition =
|
|
396
|
-
|
|
347
|
+
const deriving = cursor(held?.rederiving);
|
|
348
|
+
if (deriving === null)
|
|
349
|
+
return { done: true, text: 0 };
|
|
350
|
+
const composition = composed.composition;
|
|
351
|
+
let last = deriving;
|
|
352
|
+
let spent = 0;
|
|
353
|
+
let built = 0;
|
|
354
|
+
let read = false;
|
|
355
|
+
reading: for (;;) {
|
|
356
|
+
const rows = connection.rows('SELECT id, path, content, outline FROM replica_entries WHERE key = ? AND present = 1 AND id > ? ORDER BY id LIMIT ?', [key, last, DERIVED_ROWS]);
|
|
357
|
+
for (const row of rows) {
|
|
358
|
+
const id = number(row.id);
|
|
359
|
+
const path = text(row.path);
|
|
360
|
+
const content = text(row.content);
|
|
361
|
+
const made = derived(path, content, json(row.outline), composition);
|
|
362
|
+
dropDerived(connection, id);
|
|
363
|
+
writeDerived(connection, id, key, made);
|
|
364
|
+
built += content?.length ?? 0;
|
|
365
|
+
last = id;
|
|
366
|
+
spent += ENTRY_WEIGHT + (content?.length ?? 0);
|
|
367
|
+
if (spent >= bytes || (spent >= floor && performance.now() - started >= ms))
|
|
368
|
+
break reading;
|
|
369
|
+
}
|
|
370
|
+
if (rows.length < DERIVED_ROWS) {
|
|
371
|
+
read = true;
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
connection.run('UPDATE replica_keys SET rederiving = ? WHERE key = ?', [read ? null : last, key]);
|
|
376
|
+
return { done: read, text: built };
|
|
377
|
+
}
|
|
378
|
+
function outlinedAgain(connection, row, key, content, composition) {
|
|
379
|
+
const id = number(row.id);
|
|
380
|
+
const path = text(row.path);
|
|
381
|
+
const made = derived(path, content, json(row.outline), composition);
|
|
382
|
+
connection.run('UPDATE replica_entries SET content = ?, type = ?, declared = ?, queried = ?, folder = ?, fields = ? WHERE id = ?', [content, made.type, made.declared, flag(made.queried), made.folder, made.fields, id]);
|
|
383
|
+
dropDerived(connection, id);
|
|
384
|
+
writeDerived(connection, id, key, made);
|
|
385
|
+
}
|
|
386
|
+
export function holdTexts(connection, request) {
|
|
387
|
+
const held = [];
|
|
388
|
+
for (const { path, revision, content } of request.texts) {
|
|
389
|
+
const [row] = connection.rows(`SELECT id, path, outline FROM replica_entries WHERE key = ? AND layer = ${CONFIRMED} AND path = ? AND revision = ? AND content IS NULL AND outline IS NOT NULL`, [request.key, path, revision]);
|
|
390
|
+
if (row === undefined)
|
|
391
|
+
continue;
|
|
392
|
+
outlinedAgain(connection, row, request.key, content, request.composed.composition);
|
|
393
|
+
connection.run('INSERT OR IGNORE INTO replica_opened (locator, path) VALUES (?, ?)', [
|
|
394
|
+
request.locator,
|
|
395
|
+
path,
|
|
396
|
+
]);
|
|
397
|
+
held.push(path);
|
|
398
|
+
}
|
|
399
|
+
return held;
|
|
400
|
+
}
|
|
401
|
+
export function unholdTexts(connection, request) {
|
|
402
|
+
connection.run('DELETE FROM replica_opened WHERE locator = ?', [request.locator]);
|
|
403
|
+
const rows = connection.rows(`SELECT id, path, outline, octet_length(content) AS bytes FROM replica_entries WHERE key = ? AND layer = ${CONFIRMED} AND visible = 1 AND content IS NOT NULL AND outline IS NOT NULL`, [request.key]);
|
|
397
404
|
for (const row of rows) {
|
|
398
|
-
|
|
399
|
-
const path = text(row.path);
|
|
400
|
-
const made = derived(path, text(row.content), composition);
|
|
401
|
-
dropDerived(connection, id);
|
|
402
|
-
connection.run('UPDATE replica_entries SET type = ?, declared = ?, queried = ?, fields = ? WHERE id = ?', [made.type, made.declared, flag(made.queried), made.fields, id]);
|
|
403
|
-
writeDerived(connection, id, key, made);
|
|
405
|
+
outlinedAgain(connection, row, request.key, null, request.composed.composition);
|
|
404
406
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
407
|
+
return {
|
|
408
|
+
paths: rows.map((row) => text(row.path)),
|
|
409
|
+
bytes: rows.reduce((total, row) => total + number(row.bytes), 0),
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
export function remembered(connection, request) {
|
|
413
|
+
connection.run(`INSERT OR IGNORE INTO replica_opened (locator, path) SELECT ?, path FROM replica_entries WHERE key = ? AND layer = ${CONFIRMED} AND content IS NOT NULL AND binary IS NULL AND path IN (SELECT value FROM json_each(?))`, [request.locator, request.key, paths(request.paths)]);
|
|
414
|
+
return null;
|
|
415
|
+
}
|
|
416
|
+
export function wanted(connection, request) {
|
|
417
|
+
return connection
|
|
418
|
+
.rows(`SELECT e.path, e.revision FROM replica_opened o JOIN replica_entries e ON e.key = ? AND e.layer = ${CONFIRMED} AND e.path = o.path WHERE o.locator = ? AND e.content IS NULL AND e.outline IS NOT NULL AND e.revision IS NOT NULL`, [request.key, request.locator])
|
|
419
|
+
.map((row) => ({ path: text(row.path), revision: text(row.revision) }));
|
|
412
420
|
}
|
|
413
421
|
function heldEntry(row) {
|
|
414
422
|
return {
|
|
415
423
|
path: text(row.path),
|
|
416
424
|
content: text(row.content),
|
|
425
|
+
outline: json(row.outline),
|
|
417
426
|
binary: json(row.binary),
|
|
418
427
|
revision: text(row.revision),
|
|
419
428
|
fileId: text(row.file_id),
|
|
@@ -422,13 +431,32 @@ function heldEntry(row) {
|
|
|
422
431
|
type: text(row.type),
|
|
423
432
|
};
|
|
424
433
|
}
|
|
425
|
-
const ENTRY_COLUMNS = 'e.path, e.content, e.binary, e.revision, e.file_id, e.change, e.written, e.type';
|
|
434
|
+
const ENTRY_COLUMNS = 'e.path, e.content, e.outline, e.binary, e.revision, e.file_id, e.change, e.written, e.type';
|
|
435
|
+
function unrefreshed(alias) {
|
|
436
|
+
return `NOT EXISTS (SELECT 1 FROM replica_entries r WHERE r.key = ${alias}.key AND r.layer = ${REFRESHED} AND r.path = ${alias}.path)`;
|
|
437
|
+
}
|
|
426
438
|
function viewed(view, alias) {
|
|
427
439
|
if (view === 'visible')
|
|
428
440
|
return `${alias}.visible = 1 AND ${alias}.present = 1`;
|
|
429
441
|
if (view === 'confirmed')
|
|
430
442
|
return `${alias}.layer = ${CONFIRMED}`;
|
|
431
|
-
return `${alias}.present = 1 AND (${alias}.layer = ${REFRESHED} OR (${alias}.layer = ${CONFIRMED} AND
|
|
443
|
+
return `${alias}.present = 1 AND (${alias}.layer = ${REFRESHED} OR (${alias}.layer = ${CONFIRMED} AND ${unrefreshed(alias)}))`;
|
|
444
|
+
}
|
|
445
|
+
function layers(view) {
|
|
446
|
+
if (view !== 'refreshed')
|
|
447
|
+
return [viewed(view, 'e')];
|
|
448
|
+
return [
|
|
449
|
+
`e.layer = ${REFRESHED} AND e.present = 1`,
|
|
450
|
+
`e.layer = ${CONFIRMED} AND e.present = 1 AND ${unrefreshed('e')}`,
|
|
451
|
+
];
|
|
452
|
+
}
|
|
453
|
+
function pathOrdered(connection, columns, key, view, condition, after, limit) {
|
|
454
|
+
const beyond = after === null ? '' : ' AND e.path > ?';
|
|
455
|
+
const parts = layers(view).map((layer) => `SELECT ${columns} FROM replica_entries e WHERE e.key = ? AND ${layer}${condition}${beyond}`);
|
|
456
|
+
return connection.rows(`${parts.join(' UNION ALL ')} ORDER BY path LIMIT ?`, [
|
|
457
|
+
...parts.flatMap(() => (after === null ? [key] : [key, after])),
|
|
458
|
+
limit,
|
|
459
|
+
]);
|
|
432
460
|
}
|
|
433
461
|
export function entries(connection, key, view, list) {
|
|
434
462
|
if (list.length === 0)
|
|
@@ -459,36 +487,14 @@ export function referrers(connection, key, view, targets, kinds) {
|
|
|
459
487
|
kind: text(row.kind),
|
|
460
488
|
}));
|
|
461
489
|
}
|
|
462
|
-
export function walk(connection, key, view, after, bytes) {
|
|
463
|
-
const found = [];
|
|
464
|
-
let spent = 0;
|
|
465
|
-
let from = after;
|
|
466
|
-
for (;;) {
|
|
467
|
-
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]);
|
|
468
|
-
for (const row of rows) {
|
|
469
|
-
const entry = heldEntry(row);
|
|
470
|
-
found.push(entry);
|
|
471
|
-
spent += 256 + (entry.content?.length ?? 0) * 2;
|
|
472
|
-
if (spent >= bytes)
|
|
473
|
-
return { entries: found, next: entry.path };
|
|
474
|
-
}
|
|
475
|
-
if (rows.length < 64)
|
|
476
|
-
return { entries: found, next: null };
|
|
477
|
-
from = found.at(-1).path;
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
490
|
export function files(connection, key, view, after, limit) {
|
|
481
|
-
return connection
|
|
482
|
-
|
|
483
|
-
|
|
491
|
+
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) }));
|
|
492
|
+
}
|
|
493
|
+
export function folders(connection, key, view, list) {
|
|
494
|
+
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);
|
|
484
495
|
}
|
|
485
496
|
export function typedWithin(connection, key, view, roots, within) {
|
|
486
|
-
|
|
487
|
-
const bind = [key];
|
|
488
|
-
for (const root of roots)
|
|
489
|
-
bind.push(root, `${root}/`, `${root}0`);
|
|
490
|
-
const placed = roots.length === 0 ? (within ? ' AND 0' : '') : ` AND ${within ? '' : 'NOT '}(${inside})`;
|
|
491
|
-
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);
|
|
497
|
+
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);
|
|
492
498
|
}
|
|
493
499
|
export function opened(connection) {
|
|
494
500
|
const facts = {};
|
|
@@ -501,18 +507,13 @@ export function opened(connection) {
|
|
|
501
507
|
key: number(row.key),
|
|
502
508
|
record: text(row.record),
|
|
503
509
|
})),
|
|
504
|
-
transfers: connection.rows('SELECT locator, key, record FROM replica_transfers').map((row) => ({
|
|
505
|
-
locator: text(row.locator),
|
|
506
|
-
key: number(row.key),
|
|
507
|
-
record: text(row.record),
|
|
508
|
-
})),
|
|
509
510
|
keys: connection
|
|
510
511
|
.rows('SELECT key, locator, transfer, rederiving FROM replica_keys')
|
|
511
512
|
.map((row) => ({
|
|
512
513
|
key: number(row.key),
|
|
513
514
|
locator: text(row.locator),
|
|
514
515
|
transfer: text(row.transfer),
|
|
515
|
-
rederiving:
|
|
516
|
+
rederiving: cursor(row.rederiving),
|
|
516
517
|
})),
|
|
517
518
|
facts,
|
|
518
519
|
presentation: connection.rows('SELECT app, value FROM replica_presentation').map((row) => ({
|
|
@@ -525,7 +526,6 @@ export function opened(connection) {
|
|
|
525
526
|
orphans: connection
|
|
526
527
|
.rows(`SELECT k.key FROM replica_keys k
|
|
527
528
|
WHERE NOT EXISTS (SELECT 1 FROM replica_rooms r WHERE r.key = k.key)
|
|
528
|
-
AND NOT EXISTS (SELECT 1 FROM replica_transfers t WHERE t.key = k.key)
|
|
529
529
|
AND NOT EXISTS (SELECT 1 FROM replica_erasing e WHERE e.key = k.key)`)
|
|
530
530
|
.map((row) => number(row.key)),
|
|
531
531
|
erasing: connection.rows('SELECT key, locator FROM replica_erasing').map((row) => ({
|
|
@@ -540,5 +540,4 @@ export function ended(connection) {
|
|
|
540
540
|
if (table !== undefined)
|
|
541
541
|
connection.run(`DELETE FROM ${table}`);
|
|
542
542
|
}
|
|
543
|
-
unindexAll(connection);
|
|
544
543
|
}
|