@prestack/thread 0.1.3 → 0.1.5
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/CHANGELOG.md +563 -0
- package/dist/core/actor.d.ts +1 -1
- package/dist/core/actor.js +5 -4
- package/dist/core/actor.ts +5 -4
- package/dist/core/attach.d.ts +0 -7
- package/dist/core/attach.js +38 -67
- package/dist/core/attach.ts +34 -80
- package/dist/core/chain.js +13 -17
- package/dist/core/chain.ts +11 -15
- package/dist/core/condition.d.ts +4 -4
- package/dist/core/condition.js +2 -2
- package/dist/core/descend.d.ts +4 -2
- package/dist/core/descend.js +91 -23
- package/dist/core/descend.ts +90 -21
- package/dist/core/errors/catalogue.d.ts +52 -0
- package/dist/{operations/errors/errors.js → core/errors/catalogue.js} +1 -1
- package/dist/{operations/errors/errors.ts → core/errors/catalogue.ts} +1 -1
- package/dist/{operations/errors/catalog.d.ts → core/errors/error.d.ts} +2 -3
- package/dist/{operations/errors/catalog.js → core/errors/error.js} +1 -16
- package/dist/{operations/errors/catalog.ts → core/errors/error.ts} +3 -19
- package/dist/core/errors/namespaces.d.ts +3 -0
- package/dist/core/errors/namespaces.js +15 -0
- package/dist/core/errors/namespaces.ts +19 -0
- package/dist/core/finding.js +2 -2
- package/dist/core/finding.ts +1 -2
- package/dist/core/init.d.ts +1 -1
- package/dist/core/init.js +51 -5
- package/dist/core/init.ts +58 -5
- package/dist/core/invoked.d.ts +1 -1
- package/dist/core/invoked.js +3 -1
- package/dist/core/invoked.ts +5 -2
- package/dist/core/round.js +36 -22
- package/dist/core/round.ts +26 -9
- package/dist/core/rows.d.ts +4 -0
- package/dist/core/rows.js +31 -2
- package/dist/core/rows.ts +33 -1
- package/dist/core/scope.d.ts +1 -0
- package/dist/core/scope.js +1 -0
- package/dist/core/scope.ts +2 -0
- package/dist/core/thread.d.ts +3 -3
- package/dist/core/tree.d.ts +4 -1
- package/dist/core/tree.js +26 -6
- package/dist/core/tree.ts +29 -6
- package/dist/core/types.d.ts +3 -3
- package/dist/core/types.js +3 -1
- package/dist/core/types.ts +2 -1
- package/dist/derivation/attach.js +3 -2
- package/dist/derivation/attach.ts +2 -1
- package/dist/derivation/generators/build.js +6 -6
- package/dist/derivation/generators/build.ts +1 -1
- package/dist/derivation/generators/check.js +1 -1
- package/dist/derivation/generators/determinism.js +1 -1
- package/dist/derivation/generators/release.js +60 -47
- package/dist/derivation/generators/release.ts +66 -43
- package/dist/derivation/release.d.ts +7 -3
- package/dist/derivation/release.js +14 -1
- package/dist/derivation/release.ts +22 -2
- package/dist/integrations/attach.d.ts +4 -0
- package/dist/integrations/attach.js +37 -56
- package/dist/integrations/attach.ts +54 -60
- package/dist/integrations/cli.d.ts +37 -0
- package/dist/integrations/cli.js +440 -0
- package/dist/integrations/cli.ts +543 -0
- package/dist/{core/files.d.ts → integrations/disk.d.ts} +16 -24
- package/dist/integrations/disk.js +435 -0
- package/dist/integrations/disk.ts +465 -0
- package/dist/integrations/generators/read.js +6 -6
- package/dist/integrations/generators/read.ts +4 -4
- package/dist/integrations/generators/vault.js +10 -11
- package/dist/integrations/generators/vault.ts +4 -5
- package/dist/{operations/http.d.ts → integrations/https.d.ts} +10 -6
- package/dist/integrations/https.js +170 -0
- package/dist/integrations/https.ts +216 -0
- package/dist/integrations/pglite.d.ts +26 -0
- package/dist/integrations/pglite.js +143 -0
- package/dist/integrations/pglite.ts +206 -0
- package/dist/integrations/secret.d.ts +8 -2
- package/dist/integrations/secret.js +3 -5
- package/dist/integrations/secret.ts +10 -6
- package/dist/integrations/target.d.ts +155 -14
- package/dist/integrations/target.js +171 -50
- package/dist/integrations/target.ts +377 -61
- package/dist/integrations/vault.d.ts +1 -0
- package/dist/integrations/vault.js +20 -5
- package/dist/integrations/vault.ts +17 -5
- package/dist/integrity/attach.js +8 -77
- package/dist/integrity/attach.ts +7 -76
- package/dist/integrity/check-threads.js +5 -5
- package/dist/integrity/check-threads.ts +2 -2
- package/dist/integrity/constraint.d.ts +0 -1
- package/dist/integrity/constraint.js +267 -366
- package/dist/integrity/constraint.ts +267 -375
- package/dist/integrity/generators/compiler.js +14 -17
- package/dist/integrity/generators/compiler.ts +10 -15
- package/dist/integrity/generators/gate.js +15 -15
- package/dist/integrity/generators/gate.ts +10 -10
- package/dist/integrity/generators/issues.js +7 -7
- package/dist/integrity/generators/publish.js +39 -57
- package/dist/integrity/generators/publish.ts +44 -55
- package/dist/integrity/generators/trial.d.ts +3 -3
- package/dist/integrity/generators/trial.js +133 -165
- package/dist/integrity/generators/trial.ts +145 -169
- package/dist/integrity/lint.js +9 -13
- package/dist/integrity/lint.ts +7 -10
- package/dist/integrity/lsp/bin.js +5 -4
- package/dist/integrity/lsp/bin.ts +3 -1
- package/dist/integrity/lsp/diagnostics.js +3 -3
- package/dist/integrity/lsp/diagnostics.ts +1 -1
- package/dist/integrity/lsp/lint.js +19 -30
- package/dist/integrity/lsp/lint.ts +16 -32
- package/dist/integrity/lsp/server.js +3 -3
- package/dist/integrity/slopnator.d.ts +3 -13
- package/dist/integrity/slopnator.js +59 -38
- package/dist/integrity/slopnator.ts +54 -38
- package/dist/integrity/slopnators/sl_broken_lineage.js +2 -2
- package/dist/integrity/slopnators/sl_declared_elsewhere.js +1 -1
- package/dist/integrity/slopnators/sl_derived_drift.js +4 -4
- package/dist/integrity/slopnators/sl_derived_drift.ts +1 -1
- package/dist/integrity/slopnators/sl_door_in_a_node.js +220 -0
- package/dist/integrity/slopnators/sl_door_in_a_node.ts +250 -0
- package/dist/integrity/slopnators/sl_inert_island.js +10 -8
- package/dist/integrity/slopnators/sl_inert_island.ts +8 -6
- package/dist/integrity/slopnators/sl_missing_row.js +6 -51
- package/dist/integrity/slopnators/sl_missing_row.ts +4 -50
- package/dist/integrity/slopnators/sl_no_barrel.js +1 -1
- package/dist/integrity/slopnators/sl_no_child_process.js +36 -18
- package/dist/integrity/slopnators/sl_no_child_process.ts +44 -18
- package/dist/integrity/slopnators/sl_no_dispatch_bypass.js +80 -149
- package/dist/integrity/slopnators/sl_no_dispatch_bypass.ts +95 -147
- package/dist/integrity/slopnators/sl_no_import_cycle.js +15 -4
- package/dist/integrity/slopnators/sl_no_import_cycle.ts +20 -4
- package/dist/integrity/slopnators/sl_no_such_command.js +2 -2
- package/dist/integrity/slopnators/sl_no_such_command.ts +1 -1
- package/dist/integrity/slopnators/sl_outside_an_operation.js +20 -0
- package/dist/integrity/slopnators/sl_outside_an_operation.ts +25 -0
- package/dist/integrity/slopnators/sl_screen_holds_only_declared.d.ts +2 -0
- package/dist/integrity/slopnators/sl_screen_holds_only_declared.js +61 -0
- package/dist/integrity/slopnators/sl_screen_holds_only_declared.ts +70 -0
- package/dist/integrity/slopnators/sl_secret_literal.js +1 -33
- package/dist/integrity/slopnators/sl_secret_literal.ts +1 -33
- package/dist/integrity/slopnators/sl_stale_path.js +5 -22
- package/dist/integrity/slopnators/sl_stale_path.ts +4 -20
- package/dist/integrity/slopnators/sl_twice_meant.js +1 -1
- package/dist/integrity/slopnators/sl_twice_parented.js +29 -5
- package/dist/integrity/slopnators/sl_twice_parented.ts +28 -4
- package/dist/integrity/slopnators/sl_undeclared_crossing.d.ts +4 -1
- package/dist/integrity/slopnators/sl_undeclared_crossing.js +426 -62
- package/dist/integrity/slopnators/sl_undeclared_crossing.ts +454 -70
- package/dist/integrity/slopnators/sl_undeclared_destination.js +59 -25
- package/dist/integrity/slopnators/sl_undeclared_destination.ts +69 -21
- package/dist/integrity/slopnators/sl_undeclared_list.d.ts +2 -0
- package/dist/integrity/slopnators/sl_undeclared_list.js +363 -0
- package/dist/integrity/slopnators/sl_undeclared_list.ts +358 -0
- package/dist/integrity/slopnators/sl_undeclared_node.js +1 -11
- package/dist/integrity/slopnators/sl_undeclared_node.ts +0 -10
- package/dist/integrity/slopnators/sl_undeclared_operation.js +111 -29
- package/dist/integrity/slopnators/sl_undeclared_operation.ts +134 -26
- package/dist/integrity/slopnators/sl_undeclared_variant.js +2 -2
- package/dist/integrity/slopnators/sl_undeclared_webhook.d.ts +2 -0
- package/dist/integrity/slopnators/sl_undeclared_webhook.js +90 -0
- package/dist/integrity/slopnators/sl_undeclared_webhook.ts +108 -0
- package/dist/integrity/slopnators/sl_underived_route.d.ts +2 -0
- package/dist/integrity/slopnators/sl_underived_route.js +61 -0
- package/dist/integrity/slopnators/sl_underived_route.ts +72 -0
- package/dist/integrity/slopnators/sl_ungoverned_island.js +3 -3
- package/dist/integrity/slopnators/sl_ungoverned_island.ts +1 -1
- package/dist/integrity/slopnators/sl_unlisted_program.d.ts +2 -0
- package/dist/integrity/slopnators/sl_unlisted_program.js +39 -0
- package/dist/integrity/slopnators/sl_unlisted_program.ts +40 -0
- package/dist/integrity/slopnators/sl_unnamed_island.js +1 -1
- package/dist/integrity/slopnators/sl_unpaired_member.js +3 -3
- package/dist/integrity/slopnators/sl_unpaired_member.ts +1 -1
- package/dist/integrity/slopnators/sl_unpaired_slopnator.js +4 -4
- package/dist/integrity/slopnators/sl_unpaired_slopnator.ts +1 -1
- package/dist/integrity/slopnators/sl_unprefixed_member.js +5 -31
- package/dist/integrity/slopnators/sl_unprefixed_member.ts +2 -28
- package/dist/integrity/slopnators/sl_unthreaded.js +11 -7
- package/dist/integrity/slopnators/sl_unthreaded.ts +6 -7
- package/dist/integrity/slopnators/sl_untranslated_key.js +2 -25
- package/dist/integrity/slopnators/sl_untranslated_key.ts +1 -25
- package/dist/integrity/slopnators/sl_unvaulted_secret.d.ts +2 -0
- package/dist/integrity/slopnators/sl_unvaulted_secret.js +107 -0
- package/dist/integrity/slopnators/sl_unvaulted_secret.ts +132 -0
- package/dist/integrity/slopnators/sl_unversioned.js +6 -4
- package/dist/integrity/slopnators/sl_unversioned.ts +5 -3
- package/dist/integrity/sweep.d.ts +1 -0
- package/dist/integrity/sweep.js +105 -42
- package/dist/integrity/sweep.ts +115 -42
- package/dist/knowledge/attach.js +4 -3
- package/dist/knowledge/attach.ts +3 -2
- package/dist/knowledge/generators/docsgen.js +8 -6
- package/dist/knowledge/generators/docsgen.ts +4 -2
- package/dist/knowledge/generators/glossary.js +4 -4
- package/dist/knowledge/generators/glossary.ts +1 -1
- package/dist/operations/access.d.ts +23 -0
- package/dist/operations/access.js +28 -1
- package/dist/operations/access.ts +43 -0
- package/dist/operations/attach.js +33 -113
- package/dist/operations/attach.ts +51 -117
- package/dist/operations/capabilities.d.ts +14 -5
- package/dist/operations/capabilities.js +13 -4
- package/dist/operations/capabilities.ts +27 -8
- package/dist/operations/dispatch.d.ts +8 -2
- package/dist/operations/dispatch.js +128 -185
- package/dist/operations/dispatch.ts +138 -191
- package/dist/operations/error-results.d.ts +1 -1
- package/dist/operations/error-results.js +2 -2
- package/dist/operations/error-results.ts +2 -2
- package/dist/operations/generators/capability.d.ts +11 -1
- package/dist/operations/generators/capability.js +481 -224
- package/dist/operations/generators/capability.ts +562 -233
- package/dist/operations/generators/compile.js +66 -39
- package/dist/operations/generators/compile.ts +78 -39
- package/dist/operations/generators/permits.js +11 -12
- package/dist/operations/generators/permits.ts +3 -4
- package/dist/operations/generators/seed.d.ts +1 -0
- package/dist/operations/generators/seed.js +19 -17
- package/dist/operations/generators/seed.ts +22 -14
- package/dist/operations/generators/trial.d.ts +6 -8
- package/dist/operations/generators/trial.js +200 -70
- package/dist/operations/generators/trial.ts +230 -93
- package/dist/operations/nodes.d.ts +15 -16
- package/dist/operations/nodes.ts +16 -17
- package/dist/operations/operations.d.ts +40 -4
- package/dist/operations/operations.js +1 -0
- package/dist/operations/operations.ts +61 -4
- package/dist/operations/result.d.ts +2 -2
- package/dist/operations/result.ts +2 -2
- package/package.json +1 -4
- package/dist/core/answers.d.ts +0 -171
- package/dist/core/answers.js +0 -789
- package/dist/core/answers.ts +0 -999
- package/dist/core/client.d.ts +0 -63
- package/dist/core/client.js +0 -249
- package/dist/core/client.ts +0 -289
- package/dist/core/files.js +0 -171
- package/dist/core/files.ts +0 -222
- package/dist/integrations/module.d.ts +0 -6
- package/dist/integrations/module.js +0 -153
- package/dist/integrations/module.ts +0 -191
- package/dist/integrity/slopnators/sl_unkept_rows.js +0 -104
- package/dist/integrity/slopnators/sl_unkept_rows.ts +0 -111
- package/dist/integrity/slopnators/sl_unseamed_reach.js +0 -73
- package/dist/integrity/slopnators/sl_unseamed_reach.ts +0 -79
- package/dist/operations/cost.d.ts +0 -14
- package/dist/operations/cost.js +0 -37
- package/dist/operations/cost.ts +0 -58
- package/dist/operations/errors/errors.d.ts +0 -52
- package/dist/operations/http.js +0 -124
- package/dist/operations/http.ts +0 -169
- package/dist/operations/memory.d.ts +0 -104
- package/dist/operations/memory.js +0 -365
- package/dist/operations/memory.ts +0 -470
- package/dist/operations/metering.d.ts +0 -55
- package/dist/operations/metering.js +0 -247
- package/dist/operations/metering.ts +0 -328
- package/dist/operations/queue-policy.d.ts +0 -3
- package/dist/operations/queue-policy.js +0 -8
- package/dist/operations/queue-policy.ts +0 -10
- package/dist/operations/seams.d.ts +0 -239
- package/dist/operations/seams.js +0 -45
- package/dist/operations/seams.ts +0 -364
- package/dist/operations/store.d.ts +0 -14
- package/dist/operations/store.js +0 -1
- package/dist/operations/store.ts +0 -29
- /package/dist/{operations → core}/errors/classes.d.ts +0 -0
- /package/dist/{operations → core}/errors/classes.js +0 -0
- /package/dist/{operations → core}/errors/classes.ts +0 -0
- /package/dist/integrity/slopnators/{sl_unkept_rows.d.ts → sl_door_in_a_node.d.ts} +0 -0
- /package/dist/integrity/slopnators/{sl_unseamed_reach.d.ts → sl_outside_an_operation.d.ts} +0 -0
package/dist/core/files.js
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from 'node:child_process';
|
|
2
|
-
import * as disk from 'node:fs';
|
|
3
|
-
import { dirname, join } from 'node:path';
|
|
4
|
-
const CHANNEL = 'THREAD_CHANNEL';
|
|
5
|
-
const WAITING = 180000;
|
|
6
|
-
function overFiles(dir) {
|
|
7
|
-
const idle = new Int32Array(new SharedArrayBuffer(4));
|
|
8
|
-
let spun = 0;
|
|
9
|
-
const ask = (body) => {
|
|
10
|
-
spun += 1;
|
|
11
|
-
const name = `${dir}/${String(process.pid)}-${String(spun)}`;
|
|
12
|
-
disk.writeFileSync(`${name}.asking`, JSON.stringify(body));
|
|
13
|
-
disk.renameSync(`${name}.asking`, `${name}.order`);
|
|
14
|
-
const until = Date.now() + WAITING;
|
|
15
|
-
for (;;) {
|
|
16
|
-
let held;
|
|
17
|
-
try {
|
|
18
|
-
held = disk.readFileSync(`${name}.answer`, 'utf8');
|
|
19
|
-
}
|
|
20
|
-
catch {
|
|
21
|
-
held = undefined;
|
|
22
|
-
}
|
|
23
|
-
if (held !== undefined) {
|
|
24
|
-
disk.rmSync(`${name}.answer`, { force: true });
|
|
25
|
-
const said = JSON.parse(held);
|
|
26
|
-
if (said.answered === 'refused')
|
|
27
|
-
throw new Error(String(said.because));
|
|
28
|
-
return said;
|
|
29
|
-
}
|
|
30
|
-
if (Date.now() > until)
|
|
31
|
-
throw new Error('nothing answered ' +
|
|
32
|
-
String(body.order) +
|
|
33
|
-
' ' +
|
|
34
|
-
String(body.at) +
|
|
35
|
-
' for three minutes, so this stopped waiting rather than spinning forever. Whoever was answering is gone. It waits longer than a server waits before giving up on a run, on purpose: if an answer were still coming it would have arrived. Nothing here is half-written — one order is one file, and it was either answered or it was not.');
|
|
36
|
-
Atomics.wait(idle, 0, 0, 2);
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
return {
|
|
40
|
-
kind: (at) => ask({ order: 'kind', at }).held,
|
|
41
|
-
read: (at) => ask({ order: 'read', at }).said,
|
|
42
|
-
write: (at, said) => {
|
|
43
|
-
ask({ order: 'write', at, said });
|
|
44
|
-
},
|
|
45
|
-
list: (at) => ask({ order: 'list', at }).held,
|
|
46
|
-
stat: (at) => ask({ order: 'stat', at }).held,
|
|
47
|
-
remove: (at) => {
|
|
48
|
-
ask({ order: 'remove', at });
|
|
49
|
-
},
|
|
50
|
-
real: (at) => ask({ order: 'real', at }).at,
|
|
51
|
-
fetch: (at) => ask({ order: 'fetch', at }).said,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
const WHERE = process.env[CHANNEL];
|
|
55
|
-
let answering = WHERE !== undefined && WHERE !== '' ? overFiles(WHERE) : undefined;
|
|
56
|
-
export function answeredBy(one) {
|
|
57
|
-
answering = one;
|
|
58
|
-
}
|
|
59
|
-
const asked = (at) => (typeof at === 'string' ? answering : undefined);
|
|
60
|
-
export function attached() {
|
|
61
|
-
return answering !== undefined;
|
|
62
|
-
}
|
|
63
|
-
export function kind(at) {
|
|
64
|
-
const one = answering;
|
|
65
|
-
if (one !== undefined)
|
|
66
|
-
return one.kind(at);
|
|
67
|
-
const held = disk.statSync(at, { throwIfNoEntry: false });
|
|
68
|
-
if (held === undefined)
|
|
69
|
-
return 'none';
|
|
70
|
-
return held.isFile() ? 'file' : held.isDirectory() ? 'folder' : 'other';
|
|
71
|
-
}
|
|
72
|
-
export function existsSync(at) {
|
|
73
|
-
return typeof at === 'string' ? kind(at) !== 'none' : disk.existsSync(at);
|
|
74
|
-
}
|
|
75
|
-
export function readFileSync(at, how) {
|
|
76
|
-
const one = asked(at);
|
|
77
|
-
return one === undefined ? disk.readFileSync(at, how ?? 'utf8') : one.read(at);
|
|
78
|
-
}
|
|
79
|
-
export function writeFileSync(at, said, how) {
|
|
80
|
-
const one = asked(at);
|
|
81
|
-
if (one !== undefined) {
|
|
82
|
-
one.write(at, said);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
if (typeof at === 'string')
|
|
86
|
-
disk.mkdirSync(dirname(at), { recursive: true });
|
|
87
|
-
disk.writeFileSync(at, said, how ?? 'utf8');
|
|
88
|
-
}
|
|
89
|
-
export function readdirSync(at, how) {
|
|
90
|
-
const one = asked(at);
|
|
91
|
-
if (one === undefined)
|
|
92
|
-
return how === undefined ? disk.readdirSync(at) : disk.readdirSync(at, how);
|
|
93
|
-
const held = one.list(at);
|
|
94
|
-
return how === undefined
|
|
95
|
-
? held.map((each) => each.name)
|
|
96
|
-
: held.map((each) => ({ name: each.name, isFile: () => each.kind === 'file', isDirectory: () => each.kind === 'folder' }));
|
|
97
|
-
}
|
|
98
|
-
export function statSync(at, how) {
|
|
99
|
-
const one = asked(at);
|
|
100
|
-
if (one === undefined)
|
|
101
|
-
return (how === undefined ? disk.statSync(at) : disk.statSync(at, how));
|
|
102
|
-
const path = at;
|
|
103
|
-
const held = one.kind(path);
|
|
104
|
-
if (held === 'none') {
|
|
105
|
-
if (how !== undefined)
|
|
106
|
-
return undefined;
|
|
107
|
-
throw new Error(`${path} is not there, so nothing can be said about it.`);
|
|
108
|
-
}
|
|
109
|
-
const measured = one.stat(path);
|
|
110
|
-
return {
|
|
111
|
-
name: path,
|
|
112
|
-
size: measured.size,
|
|
113
|
-
modified: measured.modified,
|
|
114
|
-
mtimeMs: measured.modified,
|
|
115
|
-
isFile: () => held === 'file',
|
|
116
|
-
isDirectory: () => held === 'folder',
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
export function rmSync(at, how) {
|
|
120
|
-
const one = asked(at);
|
|
121
|
-
if (one === undefined)
|
|
122
|
-
disk.rmSync(at, how);
|
|
123
|
-
else
|
|
124
|
-
one.remove(at);
|
|
125
|
-
}
|
|
126
|
-
export function renameSync(from, to) {
|
|
127
|
-
const one = asked(from);
|
|
128
|
-
if (one === undefined) {
|
|
129
|
-
disk.renameSync(from, to);
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
one.write(to, one.read(from));
|
|
133
|
-
one.remove(from);
|
|
134
|
-
}
|
|
135
|
-
export function appendFileSync(at, said) {
|
|
136
|
-
const one = asked(at);
|
|
137
|
-
if (one === undefined) {
|
|
138
|
-
disk.appendFileSync(at, said);
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
const path = at;
|
|
142
|
-
one.write(path, `${one.kind(path) === 'none' ? '' : one.read(path)}${said}`);
|
|
143
|
-
}
|
|
144
|
-
export function realpathSync(at) {
|
|
145
|
-
const one = asked(at);
|
|
146
|
-
return one === undefined ? disk.realpathSync(at) : one.real(at);
|
|
147
|
-
}
|
|
148
|
-
export function manager(into) {
|
|
149
|
-
if (disk.existsSync(join(into, 'pnpm-lock.yaml')))
|
|
150
|
-
return ['pnpm', 'add'];
|
|
151
|
-
if (disk.existsSync(join(into, 'yarn.lock')))
|
|
152
|
-
return ['yarn', 'add'];
|
|
153
|
-
if (disk.existsSync(join(into, 'bun.lockb')))
|
|
154
|
-
return ['bun', 'add'];
|
|
155
|
-
return ['npm', 'install'];
|
|
156
|
-
}
|
|
157
|
-
export function installing(at) {
|
|
158
|
-
const tool = manager(at)[0] ?? 'npm';
|
|
159
|
-
const ran = spawnSync(tool, ['install'], { cwd: at, encoding: 'utf8', shell: false });
|
|
160
|
-
const said = `${ran.stdout ?? ''}${ran.stderr ?? ''}`.trim();
|
|
161
|
-
if (ran.error !== undefined)
|
|
162
|
-
throw new Error(`${tool} is not on this machine, so what ${at} depends on cannot be fetched. Put ${tool} on this machine, ` +
|
|
163
|
-
'or take away the lockfile that picked it and another one is used.');
|
|
164
|
-
if (ran.status !== 0)
|
|
165
|
-
throw new Error(`${tool} could not install what ${at} depends on. It said: ${said === '' ? `nothing, and exited ${String(ran.status)}` : said}`);
|
|
166
|
-
return said;
|
|
167
|
-
}
|
|
168
|
-
export function fetching(at) {
|
|
169
|
-
const one = answering;
|
|
170
|
-
return one === undefined ? installing(at) : one.fetch(at);
|
|
171
|
-
}
|
package/dist/core/files.ts
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from 'node:child_process'
|
|
2
|
-
import * as disk from 'node:fs'
|
|
3
|
-
import { dirname, join } from 'node:path'
|
|
4
|
-
|
|
5
|
-
export type Kind = 'file' | 'folder' | 'other' | 'none'
|
|
6
|
-
|
|
7
|
-
export interface Listed {
|
|
8
|
-
readonly name: string
|
|
9
|
-
readonly kind: Exclude<Kind, 'none'>
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface Measured {
|
|
13
|
-
readonly size: number
|
|
14
|
-
readonly modified: number
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface Answering {
|
|
18
|
-
readonly kind: (at: string) => Kind
|
|
19
|
-
readonly read: (at: string) => string
|
|
20
|
-
readonly write: (at: string, said: string) => void
|
|
21
|
-
readonly list: (at: string) => readonly Listed[]
|
|
22
|
-
readonly stat: (at: string) => Measured
|
|
23
|
-
readonly remove: (at: string) => void
|
|
24
|
-
readonly real: (at: string) => string
|
|
25
|
-
readonly fetch: (at: string) => string
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const CHANNEL = 'THREAD_CHANNEL'
|
|
29
|
-
|
|
30
|
-
const WAITING = 180000
|
|
31
|
-
|
|
32
|
-
function overFiles(dir: string): Answering {
|
|
33
|
-
const idle = new Int32Array(new SharedArrayBuffer(4))
|
|
34
|
-
let spun = 0
|
|
35
|
-
|
|
36
|
-
const ask = (body: Readonly<Record<string, unknown>>): Readonly<Record<string, unknown>> => {
|
|
37
|
-
spun += 1
|
|
38
|
-
const name = `${dir}/${String(process.pid)}-${String(spun)}`
|
|
39
|
-
disk.writeFileSync(`${name}.asking`, JSON.stringify(body))
|
|
40
|
-
disk.renameSync(`${name}.asking`, `${name}.order`)
|
|
41
|
-
const until = Date.now() + WAITING
|
|
42
|
-
for (;;) {
|
|
43
|
-
let held: string | undefined
|
|
44
|
-
try {
|
|
45
|
-
held = disk.readFileSync(`${name}.answer`, 'utf8')
|
|
46
|
-
} catch {
|
|
47
|
-
held = undefined
|
|
48
|
-
}
|
|
49
|
-
if (held !== undefined) {
|
|
50
|
-
disk.rmSync(`${name}.answer`, { force: true })
|
|
51
|
-
const said = JSON.parse(held) as Readonly<Record<string, unknown>>
|
|
52
|
-
if (said.answered === 'refused') throw new Error(String(said.because))
|
|
53
|
-
return said
|
|
54
|
-
}
|
|
55
|
-
if (Date.now() > until)
|
|
56
|
-
throw new Error(
|
|
57
|
-
'nothing answered ' +
|
|
58
|
-
String(body.order) +
|
|
59
|
-
' ' +
|
|
60
|
-
String(body.at) +
|
|
61
|
-
' for three minutes, so this stopped waiting rather than spinning forever. Whoever was answering is gone. It waits longer than a server waits before giving up on a run, on purpose: if an answer were still coming it would have arrived. Nothing here is half-written — one order is one file, and it was either answered or it was not.',
|
|
62
|
-
)
|
|
63
|
-
Atomics.wait(idle, 0, 0, 2)
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
kind: (at) => ask({ order: 'kind', at }).held as Kind,
|
|
69
|
-
read: (at) => ask({ order: 'read', at }).said as string,
|
|
70
|
-
write: (at, said) => {
|
|
71
|
-
ask({ order: 'write', at, said })
|
|
72
|
-
},
|
|
73
|
-
list: (at) => ask({ order: 'list', at }).held as readonly Listed[],
|
|
74
|
-
stat: (at) => ask({ order: 'stat', at }).held as Measured,
|
|
75
|
-
remove: (at) => {
|
|
76
|
-
ask({ order: 'remove', at })
|
|
77
|
-
},
|
|
78
|
-
real: (at) => ask({ order: 'real', at }).at as string,
|
|
79
|
-
fetch: (at) => ask({ order: 'fetch', at }).said as string,
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const WHERE = process.env[CHANNEL]
|
|
84
|
-
|
|
85
|
-
let answering: Answering | undefined = WHERE !== undefined && WHERE !== '' ? overFiles(WHERE) : undefined
|
|
86
|
-
|
|
87
|
-
export function answeredBy(one: Answering | undefined): void {
|
|
88
|
-
answering = one
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const asked = (at: unknown): Answering | undefined => (typeof at === 'string' ? answering : undefined)
|
|
92
|
-
|
|
93
|
-
export function attached(): boolean {
|
|
94
|
-
return answering !== undefined
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export function kind(at: string): Kind {
|
|
98
|
-
const one = answering
|
|
99
|
-
if (one !== undefined) return one.kind(at)
|
|
100
|
-
const held = disk.statSync(at, { throwIfNoEntry: false })
|
|
101
|
-
if (held === undefined) return 'none'
|
|
102
|
-
return held.isFile() ? 'file' : held.isDirectory() ? 'folder' : 'other'
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export function existsSync(at: disk.PathLike): boolean {
|
|
106
|
-
return typeof at === 'string' ? kind(at) !== 'none' : disk.existsSync(at)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export function readFileSync(at: disk.PathOrFileDescriptor, how?: BufferEncoding): string {
|
|
110
|
-
const one = asked(at)
|
|
111
|
-
return one === undefined ? disk.readFileSync(at, how ?? 'utf8') : one.read(at as string)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function writeFileSync(at: disk.PathOrFileDescriptor, said: string, how?: BufferEncoding): void {
|
|
115
|
-
const one = asked(at)
|
|
116
|
-
if (one !== undefined) {
|
|
117
|
-
one.write(at as string, said)
|
|
118
|
-
return
|
|
119
|
-
}
|
|
120
|
-
if (typeof at === 'string') disk.mkdirSync(dirname(at), { recursive: true })
|
|
121
|
-
disk.writeFileSync(at, said, how ?? 'utf8')
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export interface Named {
|
|
125
|
-
readonly name: string
|
|
126
|
-
readonly isFile: () => boolean
|
|
127
|
-
readonly isDirectory: () => boolean
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export function readdirSync(at: disk.PathLike): string[]
|
|
131
|
-
export function readdirSync(at: disk.PathLike, how: { readonly withFileTypes: true }): readonly Named[]
|
|
132
|
-
export function readdirSync(at: disk.PathLike, how?: { readonly withFileTypes: true }): string[] | readonly Named[] {
|
|
133
|
-
const one = asked(at)
|
|
134
|
-
if (one === undefined) return how === undefined ? disk.readdirSync(at) : disk.readdirSync(at, how)
|
|
135
|
-
const held = one.list(at as string)
|
|
136
|
-
return how === undefined
|
|
137
|
-
? held.map((each) => each.name)
|
|
138
|
-
: held.map((each) => ({ name: each.name, isFile: () => each.kind === 'file', isDirectory: () => each.kind === 'folder' }))
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export interface Held extends Named, Measured {
|
|
142
|
-
readonly mtimeMs: number
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export function statSync(at: disk.PathLike): Held
|
|
146
|
-
export function statSync(at: disk.PathLike, how: { readonly throwIfNoEntry: false }): Held | undefined
|
|
147
|
-
export function statSync(at: disk.PathLike, how?: { readonly throwIfNoEntry: false }): Held | undefined {
|
|
148
|
-
const one = asked(at)
|
|
149
|
-
if (one === undefined) return (how === undefined ? disk.statSync(at) : disk.statSync(at, how)) as Held | undefined
|
|
150
|
-
const path = at as string
|
|
151
|
-
const held = one.kind(path)
|
|
152
|
-
if (held === 'none') {
|
|
153
|
-
if (how !== undefined) return undefined
|
|
154
|
-
throw new Error(`${path} is not there, so nothing can be said about it.`)
|
|
155
|
-
}
|
|
156
|
-
const measured = one.stat(path)
|
|
157
|
-
return {
|
|
158
|
-
name: path,
|
|
159
|
-
size: measured.size,
|
|
160
|
-
modified: measured.modified,
|
|
161
|
-
mtimeMs: measured.modified,
|
|
162
|
-
isFile: () => held === 'file',
|
|
163
|
-
isDirectory: () => held === 'folder',
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
export function rmSync(at: disk.PathLike, how?: disk.RmOptions): void {
|
|
168
|
-
const one = asked(at)
|
|
169
|
-
if (one === undefined) disk.rmSync(at, how)
|
|
170
|
-
else one.remove(at as string)
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
export function renameSync(from: disk.PathLike, to: disk.PathLike): void {
|
|
174
|
-
const one = asked(from)
|
|
175
|
-
if (one === undefined) {
|
|
176
|
-
disk.renameSync(from, to)
|
|
177
|
-
return
|
|
178
|
-
}
|
|
179
|
-
one.write(to as string, one.read(from as string))
|
|
180
|
-
one.remove(from as string)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export function appendFileSync(at: disk.PathOrFileDescriptor, said: string): void {
|
|
184
|
-
const one = asked(at)
|
|
185
|
-
if (one === undefined) {
|
|
186
|
-
disk.appendFileSync(at, said)
|
|
187
|
-
return
|
|
188
|
-
}
|
|
189
|
-
const path = at as string
|
|
190
|
-
one.write(path, `${one.kind(path) === 'none' ? '' : one.read(path)}${said}`)
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export function realpathSync(at: disk.PathLike): string {
|
|
194
|
-
const one = asked(at)
|
|
195
|
-
return one === undefined ? disk.realpathSync(at as string) : one.real(at as string)
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
export function manager(into: string): readonly string[] {
|
|
199
|
-
if (disk.existsSync(join(into, 'pnpm-lock.yaml'))) return ['pnpm', 'add']
|
|
200
|
-
if (disk.existsSync(join(into, 'yarn.lock'))) return ['yarn', 'add']
|
|
201
|
-
if (disk.existsSync(join(into, 'bun.lockb'))) return ['bun', 'add']
|
|
202
|
-
return ['npm', 'install']
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export function installing(at: string): string {
|
|
206
|
-
const tool = manager(at)[0] ?? 'npm'
|
|
207
|
-
const ran = spawnSync(tool, ['install'], { cwd: at, encoding: 'utf8', shell: false })
|
|
208
|
-
const said = `${ran.stdout ?? ''}${ran.stderr ?? ''}`.trim()
|
|
209
|
-
if (ran.error !== undefined)
|
|
210
|
-
throw new Error(
|
|
211
|
-
`${tool} is not on this machine, so what ${at} depends on cannot be fetched. Put ${tool} on this machine, ` +
|
|
212
|
-
'or take away the lockfile that picked it and another one is used.',
|
|
213
|
-
)
|
|
214
|
-
if (ran.status !== 0)
|
|
215
|
-
throw new Error(`${tool} could not install what ${at} depends on. It said: ${said === '' ? `nothing, and exited ${String(ran.status)}` : said}`)
|
|
216
|
-
return said
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export function fetching(at: string): string {
|
|
220
|
-
const one = answering
|
|
221
|
-
return one === undefined ? installing(at) : one.fetch(at)
|
|
222
|
-
}
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
-
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
-
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
-
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
-
});
|
|
6
|
-
}
|
|
7
|
-
return path;
|
|
8
|
-
};
|
|
9
|
-
import { spawnSync } from 'node:child_process';
|
|
10
|
-
import { argv, stderr, stdout } from 'node:process';
|
|
11
|
-
import { answer, asking, given, unasked, wordsIn } from "../core/answers.js";
|
|
12
|
-
import { readFileSync } from "../core/files.js";
|
|
13
|
-
import { exit } from "../core/invoked.js";
|
|
14
|
-
import { valuesIn } from "../core/rows.js";
|
|
15
|
-
import { findTree, inTree } from "../core/tree.js";
|
|
16
|
-
import { REACH, reachOf } from "./target.js";
|
|
17
|
-
import { opened } from "./vault.js";
|
|
18
|
-
const PRODUCTION = '--production';
|
|
19
|
-
const METHOD = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/;
|
|
20
|
-
function isClass(fn) {
|
|
21
|
-
return /^class[\s{]/.test(Function.prototype.toString.call(fn));
|
|
22
|
-
}
|
|
23
|
-
const ASKS = [
|
|
24
|
-
{
|
|
25
|
-
key: 'args',
|
|
26
|
-
says: 'a JSON value — an array for positional arguments, anything else for one, blank for none',
|
|
27
|
-
},
|
|
28
|
-
];
|
|
29
|
-
const TAKES = ASKS.map((one) => one.key);
|
|
30
|
-
const ASKED = ASKS.map((one) => `\`${one.key}\`: ${one.says}`);
|
|
31
|
-
export async function ran(name) {
|
|
32
|
-
const say = (because) => {
|
|
33
|
-
stderr.write(`${name}: ${because}\n`);
|
|
34
|
-
exit(1);
|
|
35
|
-
};
|
|
36
|
-
const tree = findTree();
|
|
37
|
-
let targets = [];
|
|
38
|
-
try {
|
|
39
|
-
const taken = valuesIn(readFileSync(inTree(tree, 'targets.ts')));
|
|
40
|
-
targets = taken.TARGETS ?? [];
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
return say('`_threads/targets.ts` could not be read, so nothing says what this integration is.');
|
|
44
|
-
}
|
|
45
|
-
const mine = targets.find((one) => one.id === `${REACH.cli}${name}` || one.id === `${REACH.module}${name}`);
|
|
46
|
-
if (mine === undefined) {
|
|
47
|
-
return say(`no target called \`${REACH.cli}${name}\` or \`${REACH.module}${name}\` is declared here, so this command should ` +
|
|
48
|
-
'not exist. Declare it with `thread create target`, or take its row out of `_threads/derivation.ts`.');
|
|
49
|
-
}
|
|
50
|
-
const does = mine.offers ?? [];
|
|
51
|
-
const passed = argv.slice(2);
|
|
52
|
-
const sub = passed[0];
|
|
53
|
-
if (sub === undefined) {
|
|
54
|
-
stdout.write(`${name}: ${mine.describes}\n\n${String(does.length)} command(s), read off \`${mine.uses ?? ''}\` when \`${mine.id}\` was declared:\n` +
|
|
55
|
-
`${does.join(', ') || '(none were readable — name them with `thread create target edit`)'}\n\n` +
|
|
56
|
-
`thread run ${name} <command> [anything else] — arguments and flags reach \`${mine.uses ?? ''}\` untouched.\n` +
|
|
57
|
-
`It takes ${String(ASKED.length)} answer(s): ${ASKED.join('; ')}.\n`);
|
|
58
|
-
exit(0);
|
|
59
|
-
}
|
|
60
|
-
if (!does.includes(sub)) {
|
|
61
|
-
return say(`\`${sub}\` is not one of the ${String(does.length)} command(s) \`${mine.uses ?? ''}\` stated when \`${mine.id}\` ` +
|
|
62
|
-
`was declared. It declared: ${does.join(', ') || '(nothing)'}. If the tool has changed, read it again with ` +
|
|
63
|
-
`\`thread create target edit ${mine.id}\`.`);
|
|
64
|
-
}
|
|
65
|
-
if (reachOf(mine.id) === 'module') {
|
|
66
|
-
return run({ name, module: mine.uses ?? '', requires: mine.requires });
|
|
67
|
-
}
|
|
68
|
-
const went = spawnSync(mine.uses ?? '', passed, { cwd: tree.at, stdio: 'inherit' });
|
|
69
|
-
exit(went.status ?? 1);
|
|
70
|
-
}
|
|
71
|
-
export async function run(declared) {
|
|
72
|
-
const refuse = (because) => {
|
|
73
|
-
stderr.write(`${declared.name}: ${because}\n`);
|
|
74
|
-
exit(1);
|
|
75
|
-
};
|
|
76
|
-
const method = wordsIn([])[0];
|
|
77
|
-
if (method === undefined) {
|
|
78
|
-
return refuse(`takes the method to call, dot-separated for a namespaced one — e.g. \`thread run ${declared.name} customers.list\`.`);
|
|
79
|
-
}
|
|
80
|
-
if (!METHOD.test(method)) {
|
|
81
|
-
return refuse(`\`${method}\` is not a method path — one name, or names joined by dots, e.g. \`customers.list\``);
|
|
82
|
-
}
|
|
83
|
-
const piped = given();
|
|
84
|
-
unasked(piped, TAKES, `\`thread run ${declared.name} ${method}\``);
|
|
85
|
-
const { ask, shut } = asking(piped);
|
|
86
|
-
const typed = (piped.length > 0
|
|
87
|
-
? (answer(piped, TAKES[0] ?? 'args') ?? '')
|
|
88
|
-
: await ask('args', 'args, as JSON — an array for positional arguments, anything else for one (blank for none): ')).trim();
|
|
89
|
-
shut();
|
|
90
|
-
let args = [];
|
|
91
|
-
if (typed !== '') {
|
|
92
|
-
let parsed;
|
|
93
|
-
try {
|
|
94
|
-
parsed = JSON.parse(typed);
|
|
95
|
-
}
|
|
96
|
-
catch (thrown) {
|
|
97
|
-
return refuse(`that is not JSON: ${thrown instanceof Error ? thrown.message : String(thrown)}. Nothing was called.`);
|
|
98
|
-
}
|
|
99
|
-
args = Array.isArray(parsed) ? parsed : [parsed];
|
|
100
|
-
}
|
|
101
|
-
const env = argv.includes(PRODUCTION) ? 'production' : 'sandbox';
|
|
102
|
-
const opening = opened(findTree().at, declared.requires, env);
|
|
103
|
-
let resolved;
|
|
104
|
-
try {
|
|
105
|
-
resolved = await opening(declared.requires);
|
|
106
|
-
}
|
|
107
|
-
catch (thrown) {
|
|
108
|
-
return refuse(thrown instanceof Error ? thrown.message : String(thrown));
|
|
109
|
-
}
|
|
110
|
-
const credentials = declared.requires.map((one) => resolved[one] ?? '');
|
|
111
|
-
let mod;
|
|
112
|
-
try {
|
|
113
|
-
mod = (await import(__rewriteRelativeImportExtension(declared.module)));
|
|
114
|
-
}
|
|
115
|
-
catch (thrown) {
|
|
116
|
-
return refuse(`\`${declared.module}\` could not be imported: ${thrown instanceof Error ? thrown.message : String(thrown)}. It was ` +
|
|
117
|
-
`installed when this was declared — if it is gone, \`npm install ${declared.module}\` puts it back.`);
|
|
118
|
-
}
|
|
119
|
-
const entry = mod.default ?? mod;
|
|
120
|
-
const asFunction = entry;
|
|
121
|
-
const asConstructor = entry;
|
|
122
|
-
const REACHES = new Set(['constructor', '__proto__', 'prototype']);
|
|
123
|
-
const client = typeof entry !== 'function' ? entry : isClass(asFunction) ? Reflect.construct(asConstructor, credentials) : asFunction(...credentials);
|
|
124
|
-
let owner = client;
|
|
125
|
-
let target = client;
|
|
126
|
-
for (const segment of method.split('.')) {
|
|
127
|
-
if (REACHES.has(segment)) {
|
|
128
|
-
return refuse(`\`${segment}\` is not an operation of \`${declared.module}\` — it is a step every JavaScript value has, and ` +
|
|
129
|
-
'walking to it leaves what was installed. What may run here is what the module exports, and a person fixed that ' +
|
|
130
|
-
'set when they declared it.');
|
|
131
|
-
}
|
|
132
|
-
owner = target;
|
|
133
|
-
target = target?.[segment];
|
|
134
|
-
}
|
|
135
|
-
if (typeof target !== 'function') {
|
|
136
|
-
return refuse(`\`${method}\` on \`${declared.module}\` is ${target === undefined ? 'nothing' : `a ${typeof target}`}, not a method that can be called`);
|
|
137
|
-
}
|
|
138
|
-
let result;
|
|
139
|
-
try {
|
|
140
|
-
result = await target.apply(owner, args);
|
|
141
|
-
}
|
|
142
|
-
catch (thrown) {
|
|
143
|
-
return refuse(`\`${method}\` on \`${declared.module}\` threw: ${thrown instanceof Error ? thrown.message : String(thrown)}`);
|
|
144
|
-
}
|
|
145
|
-
stdout.write(`${declared.name}: ${method} (${env})\n`);
|
|
146
|
-
try {
|
|
147
|
-
stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
148
|
-
}
|
|
149
|
-
catch {
|
|
150
|
-
stdout.write(`${String(result)}\n`);
|
|
151
|
-
}
|
|
152
|
-
exit(0);
|
|
153
|
-
}
|