tapline-host 1.6.2 → 1.7.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/accounts.d.ts +129 -12
- package/dist/accounts.js +844 -75
- package/dist/accounts.js.map +1 -1
- package/dist/actionlog.d.ts +11 -4
- package/dist/actionlog.js +22 -1
- package/dist/actionlog.js.map +1 -1
- package/dist/animations.d.ts +4 -2
- package/dist/animations.js +7 -7
- package/dist/animations.js.map +1 -1
- package/dist/api.d.ts +7 -1
- package/dist/api.js +12 -1
- package/dist/api.js.map +1 -1
- package/dist/audit.d.ts +1 -0
- package/dist/auditlog.d.ts +40 -0
- package/dist/auditlog.js +150 -0
- package/dist/auditlog.js.map +1 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +143 -7
- package/dist/cli.js.map +1 -1
- package/dist/control.d.ts +51 -0
- package/dist/control.js +110 -0
- package/dist/control.js.map +1 -1
- package/dist/doctor.d.ts +6 -0
- package/dist/doctor.js +61 -4
- package/dist/doctor.js.map +1 -1
- package/dist/drive.d.ts +5 -2
- package/dist/drive.js +50 -13
- package/dist/drive.js.map +1 -1
- package/dist/elicit.d.ts +47 -0
- package/dist/elicit.js +87 -0
- package/dist/elicit.js.map +1 -1
- package/dist/format.d.ts +6 -0
- package/dist/format.js +25 -4
- package/dist/format.js.map +1 -1
- package/dist/grants.d.ts +297 -0
- package/dist/grants.js +938 -0
- package/dist/grants.js.map +1 -0
- package/dist/grantscmd.d.ts +34 -0
- package/dist/grantscmd.js +100 -0
- package/dist/grantscmd.js.map +1 -0
- package/dist/hostfacts.d.ts +23 -0
- package/dist/hostfacts.js +65 -0
- package/dist/hostfacts.js.map +1 -0
- package/dist/inspect.d.ts +3 -2
- package/dist/inspect.js +20 -8
- package/dist/inspect.js.map +1 -1
- package/dist/mapcmd.d.ts +2 -2
- package/dist/mcp.js +1 -1
- package/dist/nochange.d.ts +1 -0
- package/dist/otpclient.d.ts +79 -0
- package/dist/otpclient.js +362 -0
- package/dist/otpclient.js.map +1 -0
- package/dist/pidlock.d.ts +99 -0
- package/dist/pidlock.js +382 -0
- package/dist/pidlock.js.map +1 -0
- package/dist/places.d.ts +11 -0
- package/dist/places.js +28 -2
- package/dist/places.js.map +1 -1
- package/dist/policy.d.ts +2 -1
- package/dist/policy.js +5 -2
- package/dist/policy.js.map +1 -1
- package/dist/protocol.d.ts +4 -0
- package/dist/protocol.js +2 -0
- package/dist/protocol.js.map +1 -1
- package/dist/report.d.ts +8 -0
- package/dist/report.js +34 -1
- package/dist/report.js.map +1 -1
- package/dist/routes.d.ts +1 -1
- package/dist/routes.js +27 -11
- package/dist/routes.js.map +1 -1
- package/dist/runschedule.d.ts +119 -0
- package/dist/runschedule.js +281 -0
- package/dist/runschedule.js.map +1 -0
- package/dist/runtime.d.ts +48 -1
- package/dist/runtime.js +214 -18
- package/dist/runtime.js.map +1 -1
- package/dist/schedule.d.ts +145 -0
- package/dist/schedule.js +401 -0
- package/dist/schedule.js.map +1 -0
- package/dist/schedulehost.d.ts +73 -0
- package/dist/schedulehost.js +391 -0
- package/dist/schedulehost.js.map +1 -0
- package/dist/script.d.ts +2 -0
- package/dist/script.js +2 -0
- package/dist/script.js.map +1 -1
- package/dist/server.d.ts +6 -0
- package/dist/server.js +3 -1
- package/dist/server.js.map +1 -1
- package/dist/thincall.d.ts +13 -0
- package/dist/thincall.js +139 -59
- package/dist/thincall.js.map +1 -1
- package/dist/tool-text-data.d.ts +1 -1
- package/dist/tool-text-data.js +1 -1
- package/dist/tool-text-data.js.map +1 -1
- package/dist/tool-text.d.ts +1 -1
- package/dist/tools.d.ts +116 -6
- package/dist/tools.js +758 -134
- package/dist/tools.js.map +1 -1
- package/dist/unlockcmd.d.ts +44 -0
- package/dist/unlockcmd.js +80 -0
- package/dist/unlockcmd.js.map +1 -0
- package/dist/uxcheck.d.ts +1 -0
- package/dist/vault.d.ts +75 -0
- package/dist/vault.js +395 -0
- package/dist/vault.js.map +1 -0
- package/package.json +1 -1
- package/skills/tapline/SKILL.md +34 -6
- package/skills/tapline/references/setup.md +11 -1
package/dist/pidlock.js
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { randomBytes } from "node:crypto";
|
|
3
|
+
import { closeSync, linkSync, openSync, readFileSync, renameSync, rmSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
4
|
+
function parseHolder(text) {
|
|
5
|
+
try {
|
|
6
|
+
const parsed = JSON.parse(text);
|
|
7
|
+
return typeof parsed === "object" && parsed !== null ? parsed : {};
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return {};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const runProgram = (file, args) => execFileSync(file, args, { encoding: "utf8", timeout: 5000, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] });
|
|
14
|
+
/**
|
|
15
|
+
* When a process started, as text that is the same each time it is asked for the same process; null when it can't be told. A lock
|
|
16
|
+
* keeps it beside the process id, so a process id that was reused by another program is not mistaken for the holder. Windows asks
|
|
17
|
+
* PowerShell (`Get-Process -Id N`, about half a second, asked only for a lock's own holder and when a lock is found), elsewhere `ps`.
|
|
18
|
+
*/
|
|
19
|
+
export function processStartTime(pid, platform = process.platform, run = runProgram) {
|
|
20
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
21
|
+
return null;
|
|
22
|
+
try {
|
|
23
|
+
const out = platform === "win32"
|
|
24
|
+
? run("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", `(Get-Process -Id ${pid} -ErrorAction Stop).StartTime.ToUniversalTime().ToString('o')`])
|
|
25
|
+
: run("ps", ["-o", "lstart=", "-p", String(pid)]);
|
|
26
|
+
const text = out.trim();
|
|
27
|
+
return text === "" ? null : text;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Whether a process runs (signal 0); a process we may not signal still runs. */
|
|
34
|
+
export function processAlive(pid) {
|
|
35
|
+
try {
|
|
36
|
+
process.kill(pid, 0);
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
return error.code === "EPERM";
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
let ownStart;
|
|
44
|
+
/** The deps of this process for a lock of its own (this process's start time is asked once and kept). */
|
|
45
|
+
export function ownLockDeps() {
|
|
46
|
+
return {
|
|
47
|
+
pid: process.pid,
|
|
48
|
+
alive: processAlive,
|
|
49
|
+
startOf: (pid) => {
|
|
50
|
+
if (pid !== process.pid)
|
|
51
|
+
return processStartTime(pid);
|
|
52
|
+
if (ownStart === undefined)
|
|
53
|
+
ownStart = processStartTime(pid);
|
|
54
|
+
return ownStart;
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** Whether the holder a lock names is provably gone: its process doesn't run, or the process that has that id started at another time. */
|
|
59
|
+
function holderIsDead(deps, holder) {
|
|
60
|
+
if (typeof holder.pid !== "number" || !Number.isInteger(holder.pid))
|
|
61
|
+
return false;
|
|
62
|
+
if (!deps.alive(holder.pid))
|
|
63
|
+
return true;
|
|
64
|
+
if (typeof holder.started === "string" && deps.startOf !== undefined) {
|
|
65
|
+
const now = deps.startOf(holder.pid);
|
|
66
|
+
return now !== null && now !== holder.started;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
/** A lock's text is a leftover only when it names a holder that is provably dead. Empty, cut-short or garbage text never is (no age rule). */
|
|
71
|
+
function isLeftover(deps, text) {
|
|
72
|
+
const holder = parseHolder(text);
|
|
73
|
+
return typeof holder.pid === "number" && typeof holder.owner === "string" && holderIsDead(deps, holder);
|
|
74
|
+
}
|
|
75
|
+
function readText(path) {
|
|
76
|
+
try {
|
|
77
|
+
return readFileSync(path, "utf8");
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const codeOf = (error) => error.code;
|
|
84
|
+
/** Errors that mean this file system can't hard-link (so the fallback is used), as opposed to "the name is taken". */
|
|
85
|
+
const NO_LINK = new Set(["EPERM", "ENOSYS", "EXDEV", "ENOTSUP", "EOPNOTSUPP", "EMLINK", "EACCES"]);
|
|
86
|
+
/**
|
|
87
|
+
* Creates `path` with `text`, whole, only if it doesn't exist: "published", or "exists" (someone's file stands there), or "error".
|
|
88
|
+
* The text is written to a unique temp file first and hard-linked into place, so `path` is never seen empty.
|
|
89
|
+
*/
|
|
90
|
+
export function publishNew(deps, path, text) {
|
|
91
|
+
const temp = `${path}.${randomBytes(6).toString("hex")}.pub`;
|
|
92
|
+
try {
|
|
93
|
+
writeFileSync(temp, text, { flag: "wx", mode: 0o600 });
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return "error";
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
deps.beforePublish?.(path);
|
|
100
|
+
try {
|
|
101
|
+
(deps.link ?? linkSync)(temp, path);
|
|
102
|
+
return "published";
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
const code = codeOf(error);
|
|
106
|
+
if (code === "EEXIST")
|
|
107
|
+
return "exists";
|
|
108
|
+
if (code === undefined || !NO_LINK.has(code))
|
|
109
|
+
return "error";
|
|
110
|
+
}
|
|
111
|
+
// No hard links here: an exclusive create, then the content. Readers treat what can't be read as a holder as a writer in progress.
|
|
112
|
+
let fd;
|
|
113
|
+
try {
|
|
114
|
+
fd = openSync(path, "wx", 0o600);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
return codeOf(error) === "EEXIST" ? "exists" : "error";
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
deps.afterCreate?.(path);
|
|
121
|
+
writeSync(fd, text);
|
|
122
|
+
return "published";
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return "error";
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
closeSync(fd);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
rmSync(temp, { force: true });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/** A unique name for a file moved aside: only the one who moved it ever touches it. */
|
|
136
|
+
function tombstone(path) {
|
|
137
|
+
return `${path}.${randomBytes(6).toString("hex")}.tomb`;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Removes the file at `path` only when it still holds `seen`: it is moved to a name of its own (one move, so only one remover gets
|
|
141
|
+
* it), and what was moved is checked; a file that changed hands in between is put back, never deleted.
|
|
142
|
+
*/
|
|
143
|
+
function removeIfUnchanged(deps, path, seen) {
|
|
144
|
+
const tomb = tombstone(path);
|
|
145
|
+
try {
|
|
146
|
+
renameSync(path, tomb);
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
const moved = readFileSync(tomb, "utf8");
|
|
153
|
+
if (moved === seen)
|
|
154
|
+
return true;
|
|
155
|
+
publishNew(deps, path, moved);
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// put back by someone else already, or unreadable: the next round decides
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
rmSync(tomb, { force: true });
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Takes the lock at `path` (its folder must exist): the owner token, or null when a live holder has it. A live holder is never
|
|
167
|
+
* displaced, however long it takes. A leftover (holder provably dead) is taken over under `<path>.takeover`, published the same way:
|
|
168
|
+
* under it the lock is read again, and only if it is unchanged and its holder is still dead is it deleted and replaced by the taker's.
|
|
169
|
+
* A `.takeover` whose own process is dead is cleared the same way.
|
|
170
|
+
*/
|
|
171
|
+
export function takePidLock(deps, path) {
|
|
172
|
+
const takeoverPath = `${path}.takeover`;
|
|
173
|
+
const token = `${randomBytes(8).toString("hex")}-${deps.pid}`;
|
|
174
|
+
const mine = `${JSON.stringify({ owner: token, pid: deps.pid, started: deps.startOf?.(deps.pid) ?? null })}\n`;
|
|
175
|
+
for (let attempt = 0; attempt < 6; attempt++) {
|
|
176
|
+
// Acquisition honours `.takeover`: while a takeover or an unlock holds it (a live holder), nobody creates the lock.
|
|
177
|
+
const gate = readText(takeoverPath);
|
|
178
|
+
if (gate !== null && typeof parseHolder(gate).pid === "number" && !isLeftover(deps, gate))
|
|
179
|
+
return null;
|
|
180
|
+
const first = publishNew(deps, path, mine);
|
|
181
|
+
if (first === "published")
|
|
182
|
+
return token;
|
|
183
|
+
if (first === "error")
|
|
184
|
+
return null;
|
|
185
|
+
const seen = readText(path);
|
|
186
|
+
if (seen === null)
|
|
187
|
+
continue; // released between our create and our read: try to create again
|
|
188
|
+
if (!isLeftover(deps, seen))
|
|
189
|
+
return null;
|
|
190
|
+
deps.beforeReclaim?.();
|
|
191
|
+
// Under .takeover only one contender at a time looks at a leftover.
|
|
192
|
+
const claimed = publishNew(deps, takeoverPath, mine);
|
|
193
|
+
if (claimed === "error")
|
|
194
|
+
return null;
|
|
195
|
+
if (claimed === "exists") {
|
|
196
|
+
const other = readText(takeoverPath);
|
|
197
|
+
// Someone else is taking it over now (or was, and died): a dead taker's .takeover is cleared, a live one's is waited out.
|
|
198
|
+
if (other !== null && isLeftover(deps, other))
|
|
199
|
+
removeIfUnchanged(deps, takeoverPath, other);
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
const now = readText(path);
|
|
204
|
+
if (now === seen && isLeftover(deps, now)) {
|
|
205
|
+
try {
|
|
206
|
+
unlinkSync(path);
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (publishNew(deps, path, mine) === "published")
|
|
212
|
+
return token;
|
|
213
|
+
continue; // a run that came in first holds it now
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
finally {
|
|
217
|
+
// only our own .takeover is removed
|
|
218
|
+
const held = readText(takeoverPath);
|
|
219
|
+
if (held === mine)
|
|
220
|
+
removeIfUnchanged(deps, takeoverPath, mine);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
/** Releases the lock only while its content is still the holder's own (`token`); another's lock is never removed. */
|
|
226
|
+
export function dropPidLock(path, token) {
|
|
227
|
+
const text = readText(path);
|
|
228
|
+
if (text === null || parseHolder(text).owner !== token)
|
|
229
|
+
return;
|
|
230
|
+
try {
|
|
231
|
+
unlinkSync(path);
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
// already gone
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/** Whether the lock's holder is `token` right now (for a holder that wants to know it still has it). */
|
|
238
|
+
export function holdsPidLock(path, token) {
|
|
239
|
+
const text = readText(path);
|
|
240
|
+
return text !== null && parseHolder(text).owner === token;
|
|
241
|
+
}
|
|
242
|
+
/** Judges the exact bytes of a lock file (a snapshot): the holder is looked at in THIS text, never in a later read of the file. */
|
|
243
|
+
function judgeText(deps, text) {
|
|
244
|
+
if (text.trim() === "")
|
|
245
|
+
return { state: "stuck", why: "empty" };
|
|
246
|
+
const holder = parseHolder(text);
|
|
247
|
+
if (typeof holder.pid !== "number" || !Number.isInteger(holder.pid) || typeof holder.owner !== "string")
|
|
248
|
+
return { state: "stuck", why: "unreadable" };
|
|
249
|
+
return holderIsDead(deps, holder) ? { state: "stuck", why: "dead", pid: holder.pid } : { state: "live", pid: holder.pid };
|
|
250
|
+
}
|
|
251
|
+
function snapshotOf(path) {
|
|
252
|
+
try {
|
|
253
|
+
return { kind: "text", text: readFileSync(path, "utf8") };
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
return codeOf(error) === "ENOENT" ? { kind: "absent" } : { kind: "unreadable" };
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function judgeSnapshot(deps, snap) {
|
|
260
|
+
if (snap.kind === "absent")
|
|
261
|
+
return { state: "absent" };
|
|
262
|
+
return snap.kind === "unreadable" ? { state: "stuck", why: "unreadable" } : judgeText(deps, snap.text);
|
|
263
|
+
}
|
|
264
|
+
/** Looks at the lock at `path` without changing it. */
|
|
265
|
+
export function inspectPidLock(deps, path) {
|
|
266
|
+
return judgeSnapshot(deps, snapshotOf(path));
|
|
267
|
+
}
|
|
268
|
+
/** The words for a stuck lock's cause. */
|
|
269
|
+
export function stuckWords(state) {
|
|
270
|
+
if (state.why === "empty")
|
|
271
|
+
return "empty";
|
|
272
|
+
if (state.why === "unreadable")
|
|
273
|
+
return "unreadable";
|
|
274
|
+
return `held by a process that is gone (pid ${state.pid ?? "?"})`;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Removes the file at `path` that was judged stuck from `snap`, only if it still is what was judged: it is moved to a name of its
|
|
278
|
+
* own, and what was moved is compared with the snapshot (an unreadable snapshot is judged again on what was moved). A file that
|
|
279
|
+
* turns out to be another, live holder's is linked back and never deleted. Answers `removed`, `live` (with the pid of the holder
|
|
280
|
+
* put back) or `failed`.
|
|
281
|
+
*/
|
|
282
|
+
function removeJudged(deps, path, snap) {
|
|
283
|
+
if (snap.kind === "absent")
|
|
284
|
+
return "removed";
|
|
285
|
+
const tomb = tombstone(path);
|
|
286
|
+
try {
|
|
287
|
+
renameSync(path, tomb);
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
return "failed";
|
|
291
|
+
}
|
|
292
|
+
const moved = snapshotOf(tomb);
|
|
293
|
+
const same = snap.kind === "text" ? moved.kind === "text" && moved.text === snap.text : judgeSnapshot(deps, moved).state !== "live";
|
|
294
|
+
if (same) {
|
|
295
|
+
try {
|
|
296
|
+
rmSync(tomb, { force: true });
|
|
297
|
+
return "removed";
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
// can't be deleted (a folder, say): it is put back where it was
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
const state = judgeSnapshot(deps, moved);
|
|
304
|
+
const live = state.state === "live" ? { live: state.pid } : "failed";
|
|
305
|
+
if (moved.kind !== "text") {
|
|
306
|
+
try {
|
|
307
|
+
renameSync(tomb, path);
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
// the name was taken meanwhile: what was moved stays under its tombstone for a person to look at
|
|
311
|
+
}
|
|
312
|
+
return live;
|
|
313
|
+
}
|
|
314
|
+
// Link it back (published whole); a live holder is never unlinked. If the name was taken meanwhile, the tombstone stays for a person.
|
|
315
|
+
if (publishNew(deps, path, moved.text) === "published")
|
|
316
|
+
rmSync(tomb, { force: true });
|
|
317
|
+
return live;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Removes the lock at `path` and its `.takeover`, but only when no holder is proven alive: an empty or unreadable file, or one whose
|
|
321
|
+
* holder is dead (its process is gone, or has another start time). A live holder in either file refuses and removes nothing.
|
|
322
|
+
*
|
|
323
|
+
* It runs under the lock's own `.takeover` (published whole, as a takeover is), so it never overlaps a takeover, and acquisition
|
|
324
|
+
* honours `.takeover` too. Under it the exact bytes of the lock are read once, THAT snapshot's holder is judged, and the file is
|
|
325
|
+
* removed only if it still holds exactly those bytes (moved to a tombstone and compared; a different file is linked back).
|
|
326
|
+
* A `.takeover` that is itself stuck is cleared the same way first.
|
|
327
|
+
*/
|
|
328
|
+
export function unlockPidLock(deps, path) {
|
|
329
|
+
const takeoverPath = `${path}.takeover`;
|
|
330
|
+
const mine = `${JSON.stringify({ owner: `${randomBytes(8).toString("hex")}-${deps.pid}`, pid: deps.pid, started: deps.startOf?.(deps.pid) ?? null })}\n`;
|
|
331
|
+
const removed = [];
|
|
332
|
+
const failed = (file) => ({ status: "failed", removed, path: file });
|
|
333
|
+
let held = false;
|
|
334
|
+
for (let attempt = 0; attempt < 6 && !held; attempt++) {
|
|
335
|
+
const got = publishNew(deps, takeoverPath, mine);
|
|
336
|
+
if (got === "published") {
|
|
337
|
+
held = true;
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
if (got === "error")
|
|
341
|
+
return failed(takeoverPath);
|
|
342
|
+
const snap = snapshotOf(takeoverPath);
|
|
343
|
+
const state = judgeSnapshot(deps, snap);
|
|
344
|
+
if (state.state === "live")
|
|
345
|
+
return { status: "live", pid: state.pid, removed, path: takeoverPath };
|
|
346
|
+
if (state.state === "absent")
|
|
347
|
+
continue;
|
|
348
|
+
deps.beforeRemove?.(takeoverPath);
|
|
349
|
+
const outcome = removeJudged(deps, takeoverPath, snap);
|
|
350
|
+
if (outcome === "removed")
|
|
351
|
+
removed.push({ path: takeoverPath, why: stuckWords(state) });
|
|
352
|
+
else if (outcome === "failed")
|
|
353
|
+
return failed(takeoverPath);
|
|
354
|
+
else
|
|
355
|
+
return { status: "live", pid: outcome.live, removed, path: takeoverPath };
|
|
356
|
+
}
|
|
357
|
+
if (!held)
|
|
358
|
+
return failed(takeoverPath);
|
|
359
|
+
try {
|
|
360
|
+
const snap = snapshotOf(path);
|
|
361
|
+
const state = judgeSnapshot(deps, snap);
|
|
362
|
+
if (state.state === "live")
|
|
363
|
+
return { status: "live", pid: state.pid, removed, path };
|
|
364
|
+
if (state.state === "absent")
|
|
365
|
+
return removed.length === 0 ? { status: "none", removed } : { status: "removed", removed };
|
|
366
|
+
deps.beforeRemove?.(path);
|
|
367
|
+
const outcome = removeJudged(deps, path, snap);
|
|
368
|
+
if (outcome === "removed")
|
|
369
|
+
removed.push({ path, why: stuckWords(state) });
|
|
370
|
+
else if (outcome === "failed")
|
|
371
|
+
return failed(path);
|
|
372
|
+
else
|
|
373
|
+
return { status: "live", pid: outcome.live, removed, path };
|
|
374
|
+
return { status: "removed", removed };
|
|
375
|
+
}
|
|
376
|
+
finally {
|
|
377
|
+
// only our own .takeover is released
|
|
378
|
+
if (readText(takeoverPath) === mine)
|
|
379
|
+
removeIfUnchanged(deps, takeoverPath, mine);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
//# sourceMappingURL=pidlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pidlock.js","sourceRoot":"","sources":["../src/pidlock.ts"],"names":[],"mappings":"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"}
|
package/dist/places.d.ts
CHANGED
|
@@ -114,6 +114,8 @@ export declare class AppMap {
|
|
|
114
114
|
private known;
|
|
115
115
|
private knownFor;
|
|
116
116
|
private dirty;
|
|
117
|
+
/** Set by `discard`: this copy was dropped for a fresh read of the file and never writes again. */
|
|
118
|
+
private dead;
|
|
117
119
|
private version;
|
|
118
120
|
private timer;
|
|
119
121
|
private saving;
|
|
@@ -188,6 +190,13 @@ export declare class AppMap {
|
|
|
188
190
|
private schedule;
|
|
189
191
|
/** Writes what changed now (the close, and tests). A failed write stays dirty and is tried again by the next flush. */
|
|
190
192
|
flush(): Promise<void>;
|
|
193
|
+
/** How the file loaded: "ok", "new" (no file) or "unreadable". */
|
|
194
|
+
loadedStatus(): "ok" | "new" | "unreadable";
|
|
195
|
+
/**
|
|
196
|
+
* Drops this copy without writing it: what it learned and hadn't saved is let go, and it never saves again, so a file a person has
|
|
197
|
+
* edited can't be written over (or a deleted reflex brought back) by a stale copy. A save already under way is waited for.
|
|
198
|
+
*/
|
|
199
|
+
discard(): Promise<void>;
|
|
191
200
|
private write;
|
|
192
201
|
/** The merged file is the map from now on: another tool's work, and a name a clash changed, come with it. */
|
|
193
202
|
private adopt;
|
|
@@ -207,6 +216,8 @@ export declare class MapRegistry {
|
|
|
207
216
|
/** The app's map; none for an app that has no id of its own. */
|
|
208
217
|
forApp(app: MapApp): AppMap | undefined;
|
|
209
218
|
flushAll(): Promise<void>;
|
|
219
|
+
/** Lets go of every map held in memory unsaved; the next `forApp` reads the file again. */
|
|
220
|
+
reload(): Promise<void>;
|
|
210
221
|
}
|
|
211
222
|
export interface PlaceSource {
|
|
212
223
|
capabilities: string[];
|
package/dist/places.js
CHANGED
|
@@ -289,6 +289,8 @@ export class AppMap {
|
|
|
289
289
|
known;
|
|
290
290
|
knownFor;
|
|
291
291
|
dirty = false;
|
|
292
|
+
/** Set by `discard`: this copy was dropped for a fresh read of the file and never writes again. */
|
|
293
|
+
dead = false;
|
|
292
294
|
version = 0;
|
|
293
295
|
timer;
|
|
294
296
|
saving;
|
|
@@ -639,7 +641,7 @@ export class AppMap {
|
|
|
639
641
|
this.schedule();
|
|
640
642
|
}
|
|
641
643
|
schedule() {
|
|
642
|
-
if (this.readOnly || this.timer !== undefined || this.saving !== undefined)
|
|
644
|
+
if (this.dead || this.readOnly || this.timer !== undefined || this.saving !== undefined)
|
|
643
645
|
return;
|
|
644
646
|
const wait = Math.max(0, this.lastWriteAt + this.gapMs - this.clock());
|
|
645
647
|
this.timer = setTimeout(() => {
|
|
@@ -658,9 +660,27 @@ export class AppMap {
|
|
|
658
660
|
return;
|
|
659
661
|
while (this.saving !== undefined)
|
|
660
662
|
await this.saving;
|
|
661
|
-
if (this.dirty)
|
|
663
|
+
if (this.dirty && !this.dead)
|
|
662
664
|
await this.write();
|
|
663
665
|
}
|
|
666
|
+
/** How the file loaded: "ok", "new" (no file) or "unreadable". */
|
|
667
|
+
loadedStatus() {
|
|
668
|
+
return this.loadStatus;
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Drops this copy without writing it: what it learned and hadn't saved is let go, and it never saves again, so a file a person has
|
|
672
|
+
* edited can't be written over (or a deleted reflex brought back) by a stale copy. A save already under way is waited for.
|
|
673
|
+
*/
|
|
674
|
+
async discard() {
|
|
675
|
+
this.dead = true;
|
|
676
|
+
if (this.timer !== undefined) {
|
|
677
|
+
clearTimeout(this.timer);
|
|
678
|
+
this.timer = undefined;
|
|
679
|
+
}
|
|
680
|
+
while (this.saving !== undefined)
|
|
681
|
+
await this.saving;
|
|
682
|
+
this.dirty = false;
|
|
683
|
+
}
|
|
664
684
|
write() {
|
|
665
685
|
if (this.saving !== undefined)
|
|
666
686
|
return this.saving;
|
|
@@ -767,6 +787,12 @@ export class MapRegistry {
|
|
|
767
787
|
async flushAll() {
|
|
768
788
|
await Promise.all([...this.maps.values()].map((map) => map.flush()));
|
|
769
789
|
}
|
|
790
|
+
/** Lets go of every map held in memory unsaved; the next `forApp` reads the file again. */
|
|
791
|
+
async reload() {
|
|
792
|
+
const held = [...this.maps.values()];
|
|
793
|
+
this.maps.clear();
|
|
794
|
+
await Promise.all(held.map((map) => map.discard()));
|
|
795
|
+
}
|
|
770
796
|
}
|
|
771
797
|
/** Where the app was before a move: the host's latest `place` event when it names a route, else the last place seen. */
|
|
772
798
|
export function placeBefore(source, map) {
|