@prestack/thread 0.1.2 → 0.1.4

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