@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.
Files changed (270) hide show
  1. package/CHANGELOG.md +563 -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 +38 -67
  7. package/dist/core/attach.ts +34 -80
  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 +91 -23
  14. package/dist/core/descend.ts +90 -21
  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 +1 -1
  27. package/dist/core/init.js +51 -5
  28. package/dist/core/init.ts +58 -5
  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/scope.d.ts +1 -0
  38. package/dist/core/scope.js +1 -0
  39. package/dist/core/scope.ts +2 -0
  40. package/dist/core/thread.d.ts +3 -3
  41. package/dist/core/tree.d.ts +4 -1
  42. package/dist/core/tree.js +26 -6
  43. package/dist/core/tree.ts +29 -6
  44. package/dist/core/types.d.ts +3 -3
  45. package/dist/core/types.js +3 -1
  46. package/dist/core/types.ts +2 -1
  47. package/dist/derivation/attach.js +3 -2
  48. package/dist/derivation/attach.ts +2 -1
  49. package/dist/derivation/generators/build.js +6 -6
  50. package/dist/derivation/generators/build.ts +1 -1
  51. package/dist/derivation/generators/check.js +1 -1
  52. package/dist/derivation/generators/determinism.js +1 -1
  53. package/dist/derivation/generators/release.js +60 -47
  54. package/dist/derivation/generators/release.ts +66 -43
  55. package/dist/derivation/release.d.ts +7 -3
  56. package/dist/derivation/release.js +14 -1
  57. package/dist/derivation/release.ts +22 -2
  58. package/dist/integrations/attach.d.ts +4 -0
  59. package/dist/integrations/attach.js +37 -56
  60. package/dist/integrations/attach.ts +54 -60
  61. package/dist/integrations/cli.d.ts +37 -0
  62. package/dist/integrations/cli.js +440 -0
  63. package/dist/integrations/cli.ts +543 -0
  64. package/dist/{core/files.d.ts → integrations/disk.d.ts} +16 -24
  65. package/dist/integrations/disk.js +435 -0
  66. package/dist/integrations/disk.ts +465 -0
  67. package/dist/integrations/generators/read.js +6 -6
  68. package/dist/integrations/generators/read.ts +4 -4
  69. package/dist/integrations/generators/vault.js +10 -11
  70. package/dist/integrations/generators/vault.ts +4 -5
  71. package/dist/{operations/http.d.ts → integrations/https.d.ts} +10 -6
  72. package/dist/integrations/https.js +170 -0
  73. package/dist/integrations/https.ts +216 -0
  74. package/dist/integrations/pglite.d.ts +26 -0
  75. package/dist/integrations/pglite.js +143 -0
  76. package/dist/integrations/pglite.ts +206 -0
  77. package/dist/integrations/secret.d.ts +8 -2
  78. package/dist/integrations/secret.js +3 -5
  79. package/dist/integrations/secret.ts +10 -6
  80. package/dist/integrations/target.d.ts +155 -14
  81. package/dist/integrations/target.js +171 -50
  82. package/dist/integrations/target.ts +377 -61
  83. package/dist/integrations/vault.d.ts +1 -0
  84. package/dist/integrations/vault.js +20 -5
  85. package/dist/integrations/vault.ts +17 -5
  86. package/dist/integrity/attach.js +8 -77
  87. package/dist/integrity/attach.ts +7 -76
  88. package/dist/integrity/check-threads.js +5 -5
  89. package/dist/integrity/check-threads.ts +2 -2
  90. package/dist/integrity/constraint.d.ts +0 -1
  91. package/dist/integrity/constraint.js +267 -366
  92. package/dist/integrity/constraint.ts +267 -375
  93. package/dist/integrity/generators/compiler.js +14 -17
  94. package/dist/integrity/generators/compiler.ts +10 -15
  95. package/dist/integrity/generators/gate.js +15 -15
  96. package/dist/integrity/generators/gate.ts +10 -10
  97. package/dist/integrity/generators/issues.js +7 -7
  98. package/dist/integrity/generators/publish.js +39 -57
  99. package/dist/integrity/generators/publish.ts +44 -55
  100. package/dist/integrity/generators/trial.d.ts +3 -3
  101. package/dist/integrity/generators/trial.js +133 -165
  102. package/dist/integrity/generators/trial.ts +145 -169
  103. package/dist/integrity/lint.js +9 -13
  104. package/dist/integrity/lint.ts +7 -10
  105. package/dist/integrity/lsp/bin.js +5 -4
  106. package/dist/integrity/lsp/bin.ts +3 -1
  107. package/dist/integrity/lsp/diagnostics.js +3 -3
  108. package/dist/integrity/lsp/diagnostics.ts +1 -1
  109. package/dist/integrity/lsp/lint.js +19 -30
  110. package/dist/integrity/lsp/lint.ts +16 -32
  111. package/dist/integrity/lsp/server.js +3 -3
  112. package/dist/integrity/slopnator.d.ts +3 -13
  113. package/dist/integrity/slopnator.js +59 -38
  114. package/dist/integrity/slopnator.ts +54 -38
  115. package/dist/integrity/slopnators/sl_broken_lineage.js +2 -2
  116. package/dist/integrity/slopnators/sl_declared_elsewhere.js +1 -1
  117. package/dist/integrity/slopnators/sl_derived_drift.js +4 -4
  118. package/dist/integrity/slopnators/sl_derived_drift.ts +1 -1
  119. package/dist/integrity/slopnators/sl_door_in_a_node.js +220 -0
  120. package/dist/integrity/slopnators/sl_door_in_a_node.ts +250 -0
  121. package/dist/integrity/slopnators/sl_inert_island.js +10 -8
  122. package/dist/integrity/slopnators/sl_inert_island.ts +8 -6
  123. package/dist/integrity/slopnators/sl_missing_row.js +6 -51
  124. package/dist/integrity/slopnators/sl_missing_row.ts +4 -50
  125. package/dist/integrity/slopnators/sl_no_barrel.js +1 -1
  126. package/dist/integrity/slopnators/sl_no_child_process.js +36 -18
  127. package/dist/integrity/slopnators/sl_no_child_process.ts +44 -18
  128. package/dist/integrity/slopnators/sl_no_dispatch_bypass.js +80 -149
  129. package/dist/integrity/slopnators/sl_no_dispatch_bypass.ts +95 -147
  130. package/dist/integrity/slopnators/sl_no_import_cycle.js +15 -4
  131. package/dist/integrity/slopnators/sl_no_import_cycle.ts +20 -4
  132. package/dist/integrity/slopnators/sl_no_such_command.js +2 -2
  133. package/dist/integrity/slopnators/sl_no_such_command.ts +1 -1
  134. package/dist/integrity/slopnators/sl_outside_an_operation.js +20 -0
  135. package/dist/integrity/slopnators/sl_outside_an_operation.ts +25 -0
  136. package/dist/integrity/slopnators/sl_screen_holds_only_declared.d.ts +2 -0
  137. package/dist/integrity/slopnators/sl_screen_holds_only_declared.js +61 -0
  138. package/dist/integrity/slopnators/sl_screen_holds_only_declared.ts +70 -0
  139. package/dist/integrity/slopnators/sl_secret_literal.js +1 -33
  140. package/dist/integrity/slopnators/sl_secret_literal.ts +1 -33
  141. package/dist/integrity/slopnators/sl_stale_path.js +5 -22
  142. package/dist/integrity/slopnators/sl_stale_path.ts +4 -20
  143. package/dist/integrity/slopnators/sl_twice_meant.js +1 -1
  144. package/dist/integrity/slopnators/sl_twice_parented.js +29 -5
  145. package/dist/integrity/slopnators/sl_twice_parented.ts +28 -4
  146. package/dist/integrity/slopnators/sl_undeclared_crossing.d.ts +4 -1
  147. package/dist/integrity/slopnators/sl_undeclared_crossing.js +426 -62
  148. package/dist/integrity/slopnators/sl_undeclared_crossing.ts +454 -70
  149. package/dist/integrity/slopnators/sl_undeclared_destination.js +59 -25
  150. package/dist/integrity/slopnators/sl_undeclared_destination.ts +69 -21
  151. package/dist/integrity/slopnators/sl_undeclared_list.d.ts +2 -0
  152. package/dist/integrity/slopnators/sl_undeclared_list.js +363 -0
  153. package/dist/integrity/slopnators/sl_undeclared_list.ts +358 -0
  154. package/dist/integrity/slopnators/sl_undeclared_node.js +1 -11
  155. package/dist/integrity/slopnators/sl_undeclared_node.ts +0 -10
  156. package/dist/integrity/slopnators/sl_undeclared_operation.js +111 -29
  157. package/dist/integrity/slopnators/sl_undeclared_operation.ts +134 -26
  158. package/dist/integrity/slopnators/sl_undeclared_variant.js +2 -2
  159. package/dist/integrity/slopnators/sl_undeclared_webhook.d.ts +2 -0
  160. package/dist/integrity/slopnators/sl_undeclared_webhook.js +90 -0
  161. package/dist/integrity/slopnators/sl_undeclared_webhook.ts +108 -0
  162. package/dist/integrity/slopnators/sl_underived_route.d.ts +2 -0
  163. package/dist/integrity/slopnators/sl_underived_route.js +61 -0
  164. package/dist/integrity/slopnators/sl_underived_route.ts +72 -0
  165. package/dist/integrity/slopnators/sl_ungoverned_island.js +3 -3
  166. package/dist/integrity/slopnators/sl_ungoverned_island.ts +1 -1
  167. package/dist/integrity/slopnators/sl_unlisted_program.d.ts +2 -0
  168. package/dist/integrity/slopnators/sl_unlisted_program.js +39 -0
  169. package/dist/integrity/slopnators/sl_unlisted_program.ts +40 -0
  170. package/dist/integrity/slopnators/sl_unnamed_island.js +1 -1
  171. package/dist/integrity/slopnators/sl_unpaired_member.js +3 -3
  172. package/dist/integrity/slopnators/sl_unpaired_member.ts +1 -1
  173. package/dist/integrity/slopnators/sl_unpaired_slopnator.js +4 -4
  174. package/dist/integrity/slopnators/sl_unpaired_slopnator.ts +1 -1
  175. package/dist/integrity/slopnators/sl_unprefixed_member.js +5 -31
  176. package/dist/integrity/slopnators/sl_unprefixed_member.ts +2 -28
  177. package/dist/integrity/slopnators/sl_unthreaded.js +11 -7
  178. package/dist/integrity/slopnators/sl_unthreaded.ts +6 -7
  179. package/dist/integrity/slopnators/sl_untranslated_key.js +2 -25
  180. package/dist/integrity/slopnators/sl_untranslated_key.ts +1 -25
  181. package/dist/integrity/slopnators/sl_unvaulted_secret.d.ts +2 -0
  182. package/dist/integrity/slopnators/sl_unvaulted_secret.js +107 -0
  183. package/dist/integrity/slopnators/sl_unvaulted_secret.ts +132 -0
  184. package/dist/integrity/slopnators/sl_unversioned.js +6 -4
  185. package/dist/integrity/slopnators/sl_unversioned.ts +5 -3
  186. package/dist/integrity/sweep.d.ts +1 -0
  187. package/dist/integrity/sweep.js +105 -42
  188. package/dist/integrity/sweep.ts +115 -42
  189. package/dist/knowledge/attach.js +4 -3
  190. package/dist/knowledge/attach.ts +3 -2
  191. package/dist/knowledge/generators/docsgen.js +8 -6
  192. package/dist/knowledge/generators/docsgen.ts +4 -2
  193. package/dist/knowledge/generators/glossary.js +4 -4
  194. package/dist/knowledge/generators/glossary.ts +1 -1
  195. package/dist/operations/access.d.ts +23 -0
  196. package/dist/operations/access.js +28 -1
  197. package/dist/operations/access.ts +43 -0
  198. package/dist/operations/attach.js +33 -113
  199. package/dist/operations/attach.ts +51 -117
  200. package/dist/operations/capabilities.d.ts +14 -5
  201. package/dist/operations/capabilities.js +13 -4
  202. package/dist/operations/capabilities.ts +27 -8
  203. package/dist/operations/dispatch.d.ts +8 -2
  204. package/dist/operations/dispatch.js +128 -185
  205. package/dist/operations/dispatch.ts +138 -191
  206. package/dist/operations/error-results.d.ts +1 -1
  207. package/dist/operations/error-results.js +2 -2
  208. package/dist/operations/error-results.ts +2 -2
  209. package/dist/operations/generators/capability.d.ts +11 -1
  210. package/dist/operations/generators/capability.js +481 -224
  211. package/dist/operations/generators/capability.ts +562 -233
  212. package/dist/operations/generators/compile.js +66 -39
  213. package/dist/operations/generators/compile.ts +78 -39
  214. package/dist/operations/generators/permits.js +11 -12
  215. package/dist/operations/generators/permits.ts +3 -4
  216. package/dist/operations/generators/seed.d.ts +1 -0
  217. package/dist/operations/generators/seed.js +19 -17
  218. package/dist/operations/generators/seed.ts +22 -14
  219. package/dist/operations/generators/trial.d.ts +6 -8
  220. package/dist/operations/generators/trial.js +200 -70
  221. package/dist/operations/generators/trial.ts +230 -93
  222. package/dist/operations/nodes.d.ts +15 -16
  223. package/dist/operations/nodes.ts +16 -17
  224. package/dist/operations/operations.d.ts +40 -4
  225. package/dist/operations/operations.js +1 -0
  226. package/dist/operations/operations.ts +61 -4
  227. package/dist/operations/result.d.ts +2 -2
  228. package/dist/operations/result.ts +2 -2
  229. package/package.json +1 -4
  230. package/dist/core/answers.d.ts +0 -171
  231. package/dist/core/answers.js +0 -789
  232. package/dist/core/answers.ts +0 -999
  233. package/dist/core/client.d.ts +0 -63
  234. package/dist/core/client.js +0 -249
  235. package/dist/core/client.ts +0 -289
  236. package/dist/core/files.js +0 -171
  237. package/dist/core/files.ts +0 -222
  238. package/dist/integrations/module.d.ts +0 -6
  239. package/dist/integrations/module.js +0 -153
  240. package/dist/integrations/module.ts +0 -191
  241. package/dist/integrity/slopnators/sl_unkept_rows.js +0 -104
  242. package/dist/integrity/slopnators/sl_unkept_rows.ts +0 -111
  243. package/dist/integrity/slopnators/sl_unseamed_reach.js +0 -73
  244. package/dist/integrity/slopnators/sl_unseamed_reach.ts +0 -79
  245. package/dist/operations/cost.d.ts +0 -14
  246. package/dist/operations/cost.js +0 -37
  247. package/dist/operations/cost.ts +0 -58
  248. package/dist/operations/errors/errors.d.ts +0 -52
  249. package/dist/operations/http.js +0 -124
  250. package/dist/operations/http.ts +0 -169
  251. package/dist/operations/memory.d.ts +0 -104
  252. package/dist/operations/memory.js +0 -365
  253. package/dist/operations/memory.ts +0 -470
  254. package/dist/operations/metering.d.ts +0 -55
  255. package/dist/operations/metering.js +0 -247
  256. package/dist/operations/metering.ts +0 -328
  257. package/dist/operations/queue-policy.d.ts +0 -3
  258. package/dist/operations/queue-policy.js +0 -8
  259. package/dist/operations/queue-policy.ts +0 -10
  260. package/dist/operations/seams.d.ts +0 -239
  261. package/dist/operations/seams.js +0 -45
  262. package/dist/operations/seams.ts +0 -364
  263. package/dist/operations/store.d.ts +0 -14
  264. package/dist/operations/store.js +0 -1
  265. package/dist/operations/store.ts +0 -29
  266. /package/dist/{operations → core}/errors/classes.d.ts +0 -0
  267. /package/dist/{operations → core}/errors/classes.js +0 -0
  268. /package/dist/{operations → core}/errors/classes.ts +0 -0
  269. /package/dist/integrity/slopnators/{sl_unkept_rows.d.ts → sl_door_in_a_node.d.ts} +0 -0
  270. /package/dist/integrity/slopnators/{sl_unseamed_reach.d.ts → sl_outside_an_operation.d.ts} +0 -0
@@ -0,0 +1,15 @@
1
+ export const NAMESPACES = [
2
+ 'auth',
3
+ 'quota',
4
+ 'rate_limit',
5
+ 'feature',
6
+ 'db',
7
+ 'workflow',
8
+ 'queue',
9
+ 'ai',
10
+ 'search',
11
+ 'comms',
12
+ 'config',
13
+ 'net',
14
+ 'internal',
15
+ ];
@@ -0,0 +1,19 @@
1
+ export const NAMESPACES = [
2
+ 'auth',
3
+ 'quota',
4
+ 'rate_limit',
5
+ 'feature',
6
+ 'db',
7
+ 'workflow',
8
+ 'queue',
9
+ 'ai',
10
+ 'search',
11
+ 'comms',
12
+ 'config',
13
+ 'net',
14
+ 'internal',
15
+ ] as const
16
+
17
+ export type Namespace = (typeof NAMESPACES)[number]
18
+
19
+ export type ErrorCode = `${Namespace}.${string}`
@@ -11,7 +11,6 @@ function locate(finding) {
11
11
  export function runChecker(name, findings, measured) {
12
12
  if (findings.length === 0) {
13
13
  stdout.write(`${name}: ${measured} — no findings.\n`);
14
- process.exitCode = 0;
15
14
  return;
16
15
  }
17
16
  const lines = findings.map((finding) => ` ${forbids(finding) ? '' : 'warning: '}${finding.detail}${locate(finding)}\n Instead: ${finding.instead}`);
@@ -19,5 +18,6 @@ export function runChecker(name, findings, measured) {
19
18
  stdout.write(`${name}: ${String(findings.length)} finding${findings.length === 1 ? '' : 's'}` +
20
19
  `${forbidding === findings.length ? '' : `, ${String(findings.length - forbidding)} of them warnings`} — ${measured}\n\n` +
21
20
  `${lines.join('\n')}\n`);
22
- process.exitCode = forbidding === 0 ? 0 : 1;
21
+ if (forbidding > 0)
22
+ process.exitCode = 1;
23
23
  }
@@ -21,7 +21,6 @@ function locate(finding: Finding): string {
21
21
  export function runChecker(name: string, findings: readonly Finding[], measured: string): void {
22
22
  if (findings.length === 0) {
23
23
  stdout.write(`${name}: ${measured} — no findings.\n`)
24
- process.exitCode = 0
25
24
  return
26
25
  }
27
26
 
@@ -34,5 +33,5 @@ export function runChecker(name: string, findings: readonly Finding[], measured:
34
33
  `${forbidding === findings.length ? '' : `, ${String(findings.length - forbidding)} of them warnings`} — ${measured}\n\n` +
35
34
  `${lines.join('\n')}\n`,
36
35
  )
37
- process.exitCode = forbidding === 0 ? 0 : 1
36
+ if (forbidding > 0) process.exitCode = 1
38
37
  }
@@ -1,11 +1,11 @@
1
1
  export declare const TREE = "_threads";
2
2
  export declare const ROOT = "thread.ts";
3
+ export declare const SHAPED = "@prestack/thread/core/thread";
3
4
  export declare class AlreadyThreadedError extends Error {
4
5
  readonly at: string;
5
6
  constructor(at: string);
6
7
  }
7
8
  export declare const COMPILER = "tsconfig.json";
8
- export declare const LOCKFILES: readonly ["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb"];
9
9
  export declare const MANIFEST = "package.json";
10
10
  export declare const REGISTRY: string;
11
11
  export declare const IGNORED: string;
package/dist/core/init.js CHANGED
@@ -1,8 +1,13 @@
1
- import { existsSync, readFileSync, writeFileSync } from "./files.js";
1
+ import { LOCKFILES, installing, manager } from '../integrations/cli.js';
2
+ import { existsSync, readFileSync, writeFileSync } from '../integrations/disk.js';
3
+ import { createRequire } from 'node:module';
2
4
  import { join, relative, resolve } from 'node:path';
3
- import { quoted } from "./rows.js";
5
+ import { fileURLToPath } from 'node:url';
6
+ import { quoted } from './rows.js';
7
+ import { NAMED } from './scope.js';
4
8
  export const TREE = '_threads';
5
9
  export const ROOT = 'thread.ts';
10
+ export const SHAPED = `${NAMED}/core/thread`;
6
11
  export class AlreadyThreadedError extends Error {
7
12
  at;
8
13
  constructor(at) {
@@ -14,9 +19,11 @@ export class AlreadyThreadedError extends Error {
14
19
  }
15
20
  }
16
21
  export const COMPILER = 'tsconfig.json';
17
- export const LOCKFILES = ['package-lock.json', 'pnpm-lock.yaml', 'yarn.lock', 'bun.lockb'];
18
22
  export const MANIFEST = 'package.json';
23
+ const BUILT = '_gener' + 'ated/packages/core';
19
24
  const MODULE = 'module';
25
+ const NPM = 'npm';
26
+ const LATEST = 'latest';
20
27
  export const REGISTRY = '.npm' + 'rc';
21
28
  export const IGNORED = '.git' + 'ignore';
22
29
  export function ignored() {
@@ -46,7 +53,7 @@ export function compiler() {
46
53
  }, null, 2)}\n`;
47
54
  }
48
55
  function owned(into) {
49
- const held = LOCKFILES.filter((one) => existsSync(join(into, one)));
56
+ const held = Object.keys(LOCKFILES).filter((one) => existsSync(join(into, one)));
50
57
  return [
51
58
  {
52
59
  id: 'manifest',
@@ -85,7 +92,7 @@ export function root(into) {
85
92
  ' },',
86
93
  ]);
87
94
  return [
88
- "import type { Threaded } from './thread.ts'",
95
+ `import type { Threaded } from '${SHAPED}'`,
89
96
  '',
90
97
  'export const THREAD: Threaded = {',
91
98
  " id: 'thread',",
@@ -99,6 +106,35 @@ export function root(into) {
99
106
  '',
100
107
  ].join('\n');
101
108
  }
109
+ const own = createRequire(import.meta.url);
110
+ function manifested(at) {
111
+ try {
112
+ return own(at);
113
+ }
114
+ catch {
115
+ return undefined;
116
+ }
117
+ }
118
+ function shipped() {
119
+ let at = fileURLToPath(new URL('.', import.meta.url));
120
+ for (;;) {
121
+ const read = manifested(join(at, MANIFEST));
122
+ if (read !== undefined) {
123
+ if (read.name !== undefined && read.version !== undefined)
124
+ return [read.name, read.version];
125
+ const core = manifested(join(at, BUILT, MANIFEST));
126
+ if (core?.name !== undefined && core.version !== undefined)
127
+ return [core.name, core.version];
128
+ }
129
+ const up = resolve(at, '..');
130
+ if (up === at) {
131
+ throw new Error('this framework cannot find the package it is running from, so it has no name to install into your project. ' +
132
+ 'That name is read off the manifest beside this code rather than written down anywhere, which is what keeps it ' +
133
+ 'right when the package is renamed.');
134
+ }
135
+ at = up;
136
+ }
137
+ }
102
138
  export function init(into) {
103
139
  const dir = resolve(into, TREE);
104
140
  const at = join(dir, ROOT);
@@ -121,11 +157,21 @@ export function init(into) {
121
157
  writeFileSync(manifest, `${JSON.stringify({ ...stated, type: MODULE }, null, 2)}\n`, 'utf8');
122
158
  written.push(MANIFEST);
123
159
  }
160
+ const [from, version] = shipped();
161
+ const holds = JSON.parse(readFileSync(manifest, 'utf8'));
162
+ const dev = holds.devDependencies ?? {};
163
+ const wanted = { [from]: '^' + version, ...(manager(into) === NPM ? { [NPM]: LATEST } : {}) };
164
+ const missing = Object.entries(wanted).filter(([name]) => dev[name] === undefined);
165
+ if (missing.length > 0) {
166
+ writeFileSync(manifest, JSON.stringify({ ...holds, devDependencies: { ...dev, ...Object.fromEntries(missing) } }, null, 2) + '\n', 'utf8');
167
+ written.push(MANIFEST);
168
+ }
124
169
  const ignore = join(into, IGNORED);
125
170
  if (!existsSync(ignore)) {
126
171
  writeFileSync(ignore, ignored(), 'utf8');
127
172
  written.push(IGNORED);
128
173
  }
174
+ installing(into);
129
175
  for (const [name, text] of [[ROOT, root(into)]]) {
130
176
  writeFileSync(join(dir, name), text, 'utf8');
131
177
  written.push(relative(into, join(dir, name)));
package/dist/core/init.ts CHANGED
@@ -1,12 +1,18 @@
1
- import { existsSync, readFileSync, writeFileSync } from './files.ts'
1
+ import { LOCKFILES, installing, manager } from '../integrations/cli.ts'
2
+ import { existsSync, readFileSync, writeFileSync } from '../integrations/disk.ts'
3
+ import { createRequire } from 'node:module'
2
4
  import { join, relative, resolve } from 'node:path'
5
+ import { fileURLToPath } from 'node:url'
3
6
 
4
7
  import { quoted } from './rows.ts'
8
+ import { NAMED } from './scope.ts'
5
9
 
6
10
 
7
11
  export const TREE = '_threads'
8
12
  export const ROOT = 'thread.ts'
9
13
 
14
+ export const SHAPED = `${NAMED}/core/thread`
15
+
10
16
  export class AlreadyThreadedError extends Error {
11
17
  readonly at: string
12
18
  constructor(at: string) {
@@ -23,12 +29,16 @@ export class AlreadyThreadedError extends Error {
23
29
 
24
30
  export const COMPILER = 'tsconfig.json'
25
31
 
26
- export const LOCKFILES = ['package-lock.json', 'pnpm-lock.yaml', 'yarn.lock', 'bun.lockb'] as const
27
-
28
32
  export const MANIFEST = 'package.json'
29
33
 
34
+ const BUILT = '_gener' + 'ated/packages/core'
35
+
30
36
  const MODULE = 'module'
31
37
 
38
+ const NPM = 'npm'
39
+
40
+ const LATEST = 'latest'
41
+
32
42
  export const REGISTRY = '.npm' + 'rc'
33
43
 
34
44
  export const IGNORED = '.git' + 'ignore'
@@ -71,7 +81,7 @@ export function compiler(): string {
71
81
  }
72
82
 
73
83
  function owned(into: string): readonly { readonly id: string; readonly at: string; readonly describes: string; readonly runs?: string }[] {
74
- const held = LOCKFILES.filter((one) => existsSync(join(into, one)))
84
+ const held = Object.keys(LOCKFILES).filter((one) => existsSync(join(into, one)))
75
85
  return [
76
86
  {
77
87
  id: 'manifest',
@@ -116,7 +126,7 @@ export function root(into: string): string {
116
126
  ' },',
117
127
  ])
118
128
  return [
119
- "import type { Threaded } from './thread.ts'",
129
+ `import type { Threaded } from '${SHAPED}'`,
120
130
  '',
121
131
  'export const THREAD: Threaded = {',
122
132
  " id: 'thread',",
@@ -131,6 +141,37 @@ export function root(into: string): string {
131
141
  ].join('\n')
132
142
  }
133
143
 
144
+ const own = createRequire(import.meta.url)
145
+
146
+ function manifested(at: string): { readonly name?: string; readonly version?: string } | undefined {
147
+ try {
148
+ return own(at) as { readonly name?: string; readonly version?: string }
149
+ } catch {
150
+ return undefined
151
+ }
152
+ }
153
+
154
+ function shipped(): readonly [string, string] {
155
+ let at = fileURLToPath(new URL('.', import.meta.url))
156
+ for (;;) {
157
+ const read = manifested(join(at, MANIFEST))
158
+ if (read !== undefined) {
159
+ if (read.name !== undefined && read.version !== undefined) return [read.name, read.version]
160
+ const core = manifested(join(at, BUILT, MANIFEST))
161
+ if (core?.name !== undefined && core.version !== undefined) return [core.name, core.version]
162
+ }
163
+ const up = resolve(at, '..')
164
+ if (up === at) {
165
+ throw new Error(
166
+ 'this framework cannot find the package it is running from, so it has no name to install into your project. ' +
167
+ 'That name is read off the manifest beside this code rather than written down anywhere, which is what keeps it ' +
168
+ 'right when the package is renamed.',
169
+ )
170
+ }
171
+ at = up
172
+ }
173
+ }
174
+
134
175
  export function init(into: string): readonly string[] {
135
176
  const dir = resolve(into, TREE)
136
177
  const at = join(dir, ROOT)
@@ -155,12 +196,24 @@ export function init(into: string): readonly string[] {
155
196
  written.push(MANIFEST)
156
197
  }
157
198
 
199
+ const [from, version] = shipped()
200
+ const holds = JSON.parse(readFileSync(manifest, 'utf8')) as { devDependencies?: Record<string, string> }
201
+ const dev = holds.devDependencies ?? {}
202
+ const wanted: Readonly<Record<string, string>> = { [from]: '^' + version, ...(manager(into) === NPM ? { [NPM]: LATEST } : {}) }
203
+ const missing = Object.entries(wanted).filter(([name]) => dev[name] === undefined)
204
+ if (missing.length > 0) {
205
+ writeFileSync(manifest, JSON.stringify({ ...holds, devDependencies: { ...dev, ...Object.fromEntries(missing) } }, null, 2) + '\n', 'utf8')
206
+ written.push(MANIFEST)
207
+ }
208
+
158
209
  const ignore = join(into, IGNORED)
159
210
  if (!existsSync(ignore)) {
160
211
  writeFileSync(ignore, ignored(), 'utf8')
161
212
  written.push(IGNORED)
162
213
  }
163
214
 
215
+ installing(into)
216
+
164
217
  for (const [name, text] of [[ROOT, root(into)]] as const) {
165
218
  writeFileSync(join(dir, name), text, 'utf8')
166
219
  written.push(relative(into, join(dir, name)))
@@ -4,6 +4,6 @@ export declare const BESIDE: (name: string) => string;
4
4
  export declare const LOADER: readonly string[];
5
5
  export declare const CLI: readonly string[];
6
6
  export declare const REFUSED: unique symbol;
7
- export declare const shared: (on: boolean) => void;
7
+ export declare const shared: (on: boolean) => boolean;
8
8
  export declare function exit(code?: number): never;
9
9
  export declare const refusal: (thrown: unknown) => number | undefined;
@@ -1,7 +1,7 @@
1
- import { realpathSync } from 'node:fs';
2
1
  import { dirname, join } from 'node:path';
3
2
  import { argv, exit as ending } from 'node:process';
4
3
  import { fileURLToPath } from 'node:url';
4
+ import { realpathSync } from '../integrations/disk.js';
5
5
  export function invoked(url) {
6
6
  const named = argv[1];
7
7
  if (named === undefined)
@@ -26,7 +26,9 @@ export const CLI = [
26
26
  export const REFUSED = Symbol.for('thread.refused');
27
27
  let sharing = false;
28
28
  export const shared = (on) => {
29
+ const was = sharing;
29
30
  sharing = on;
31
+ return was;
30
32
  };
31
33
  export function exit(code) {
32
34
  if (!sharing)
@@ -1,8 +1,9 @@
1
- import { realpathSync } from 'node:fs'
2
1
  import { dirname, join } from 'node:path'
3
2
  import { argv, exit as ending } from 'node:process'
4
3
  import { fileURLToPath } from 'node:url'
5
4
 
5
+ import { realpathSync } from '../integrations/disk.ts'
6
+
6
7
  export function invoked(url: string): boolean {
7
8
  const named = argv[1]
8
9
  if (named === undefined) return false
@@ -31,8 +32,10 @@ export const REFUSED = Symbol.for('thread.refused')
31
32
 
32
33
  let sharing = false
33
34
 
34
- export const shared = (on: boolean): void => {
35
+ export const shared = (on: boolean): boolean => {
36
+ const was = sharing
35
37
  sharing = on
38
+ return was
36
39
  }
37
40
 
38
41
  export function exit(code?: number): never {
@@ -7,17 +7,19 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
7
7
  return path;
8
8
  };
9
9
  import { resolve } from 'node:path';
10
- import { argv, exitCode, stdout } from 'node:process';
10
+ import { argv, exitCode, stderr, stdout } from 'node:process';
11
11
  import { pathToFileURL } from 'node:url';
12
- import { generators, RAN, REFUSED_BY } from "./chain.js";
13
- import { forget } from "./descend.js";
14
- import { refusal, shared } from "./invoked.js";
15
- import { findTree } from "./tree.js";
12
+ import { generators, RAN, REFUSED_BY } from './chain.js';
13
+ import { attached, here } from '../integrations/disk.js';
14
+ import { forget } from './descend.js';
15
+ import { refusal, shared } from './invoked.js';
16
+ import { findTree } from './tree.js';
16
17
  let spun = 0;
17
18
  const words = (command) => command.trim().split(/\s+/).slice(1);
18
19
  shared(true);
19
20
  const tree = findTree();
20
21
  const rows = await generators(tree);
22
+ let stale = true;
21
23
  for (const command of argv.slice(2).filter((one) => one !== '')) {
22
24
  const said = words(command);
23
25
  const name = said[0];
@@ -25,33 +27,45 @@ for (const command of argv.slice(2).filter((one) => one !== '')) {
25
27
  continue;
26
28
  const held = rows.find((one) => one.by === `thread ${name}`);
27
29
  if (held?.at === undefined) {
28
- stdout.write(`${REFUSED_BY} ${command}\n`);
29
30
  stdout.write(`round: no command named "${name}", so \`${command}\` was not run\n`);
31
+ stdout.write(`${REFUSED_BY} ${command}\n`);
30
32
  continue;
31
33
  }
32
34
  const found = resolve(tree.at, held.at);
33
- forget();
35
+ if (stale)
36
+ forget();
34
37
  argv.length = 1;
35
38
  argv.push(found, ...said.slice(1));
36
39
  spun += 1;
37
40
  process.exitCode = 0;
38
- try {
39
- await import(__rewriteRelativeImportExtension(`${pathToFileURL(found).href}?round=${String(spun)}`));
40
- if (exitCode !== undefined && exitCode !== 0)
41
- stdout.write(`${REFUSED_BY} ${command}\n`);
42
- else
43
- stdout.write(`${RAN} ${command}\n`);
41
+ const began = Date.now();
42
+ stderr.write(`settle: running ${command}\n`);
43
+ let ok = true;
44
+ const ran = attached() ? here().run(found, said.slice(1)) : undefined;
45
+ if (ran !== undefined) {
46
+ stdout.write(ran.out);
47
+ stderr.write(ran.err);
48
+ ok = ran.there && ran.ok;
49
+ if (!ran.there)
50
+ stdout.write('round: ' + command + ' could not be started where the tree is: ' + ran.why + '\n');
44
51
  }
45
- catch (thrown) {
46
- const code = refusal(thrown);
47
- if (code === undefined) {
48
- stdout.write(`${REFUSED_BY} ${command}\n`);
49
- stdout.write(`round: \`${command}\` threw: ${thrown instanceof Error ? thrown.message : String(thrown)}\n`);
52
+ else {
53
+ try {
54
+ await import(__rewriteRelativeImportExtension(`${pathToFileURL(found).href}?round=${String(spun)}`));
55
+ ok = exitCode === undefined || exitCode === 0;
56
+ }
57
+ catch (thrown) {
58
+ const code = refusal(thrown);
59
+ if (code === undefined) {
60
+ ok = false;
61
+ stdout.write(`round: \`${command}\` threw: ${thrown instanceof Error ? thrown.message : String(thrown)}\n`);
62
+ }
63
+ else
64
+ ok = code === 0;
50
65
  }
51
- else if (code === 0)
52
- stdout.write(`${RAN} ${command}\n`);
53
- else
54
- stdout.write(`${REFUSED_BY} ${command}\n`);
55
66
  }
67
+ stdout.write(`${ok ? RAN : REFUSED_BY} ${command}\n`);
68
+ stderr.write(`settle: ${command} — ${String(Date.now() - began)} ms, ${ok ? 'ran' : 'refused'}\n`);
69
+ stale = !command.trim().endsWith('--check');
56
70
  }
57
71
  process.exitCode = 0;
@@ -1,8 +1,9 @@
1
1
  import { resolve } from 'node:path'
2
- import { argv, exitCode, stdout } from 'node:process'
2
+ import { argv, exitCode, stderr, stdout } from 'node:process'
3
3
  import { pathToFileURL } from 'node:url'
4
4
 
5
5
  import { generators, RAN, REFUSED_BY } from './chain.ts'
6
+ import { attached, here } from '../integrations/disk.ts'
6
7
  import { forget } from './descend.ts'
7
8
  import { refusal, shared } from './invoked.ts'
8
9
  import { findTree } from './tree.ts'
@@ -16,6 +17,8 @@ shared(true)
16
17
  const tree = findTree()
17
18
  const rows = await generators(tree)
18
19
 
20
+ let stale = true
21
+
19
22
  for (const command of argv.slice(2).filter((one) => one !== '')) {
20
23
  const said = words(command)
21
24
  const name = said[0]
@@ -23,14 +26,14 @@ for (const command of argv.slice(2).filter((one) => one !== '')) {
23
26
 
24
27
  const held = rows.find((one) => one.by === `thread ${name}`)
25
28
  if (held?.at === undefined) {
26
- stdout.write(`${REFUSED_BY} ${command}\n`)
27
29
  stdout.write(`round: no command named "${name}", so \`${command}\` was not run\n`)
30
+ stdout.write(`${REFUSED_BY} ${command}\n`)
28
31
  continue
29
32
  }
30
33
 
31
34
  const found = resolve(tree.at, held.at)
32
35
 
33
- forget()
36
+ if (stale) forget()
34
37
 
35
38
  argv.length = 1
36
39
  argv.push(found, ...said.slice(1))
@@ -39,19 +42,33 @@ for (const command of argv.slice(2).filter((one) => one !== '')) {
39
42
 
40
43
  process.exitCode = 0
41
44
 
45
+ const began = Date.now()
46
+ stderr.write(`settle: running ${command}\n`)
47
+
48
+ let ok = true
49
+ const ran = attached() ? here().run(found, said.slice(1)) : undefined
50
+ if (ran !== undefined) {
51
+ stdout.write(ran.out)
52
+ stderr.write(ran.err)
53
+ ok = ran.there && ran.ok
54
+ if (!ran.there) stdout.write('round: ' + command + ' could not be started where the tree is: ' + ran.why + '\n')
55
+ } else {
42
56
  try {
43
57
  await import(`${pathToFileURL(found).href}?round=${String(spun)}`)
44
- if (exitCode !== undefined && exitCode !== 0) stdout.write(`${REFUSED_BY} ${command}\n`)
45
- else stdout.write(`${RAN} ${command}\n`)
58
+ ok = exitCode === undefined || exitCode === 0
46
59
  } catch (thrown) {
47
60
  const code = refusal(thrown)
48
61
  if (code === undefined) {
49
-
50
- stdout.write(`${REFUSED_BY} ${command}\n`)
62
+ ok = false
51
63
  stdout.write(`round: \`${command}\` threw: ${thrown instanceof Error ? thrown.message : String(thrown)}\n`)
52
- } else if (code === 0) stdout.write(`${RAN} ${command}\n`)
53
- else stdout.write(`${REFUSED_BY} ${command}\n`)
64
+ } else ok = code === 0
65
+ }
54
66
  }
67
+
68
+ stdout.write(`${ok ? RAN : REFUSED_BY} ${command}\n`)
69
+ stderr.write(`settle: ${command} — ${String(Date.now() - began)} ms, ${ok ? 'ran' : 'refused'}\n`)
70
+
71
+ stale = !command.trim().endsWith('--check')
55
72
  }
56
73
 
57
74
  process.exitCode = 0
@@ -5,6 +5,7 @@ export interface Bounds {
5
5
  export declare function inCode(text: string): readonly boolean[];
6
6
  export declare function matched(text: string, code: readonly boolean[], from: number, open: string, close: string): number;
7
7
  export declare function listBounds(text: string, list: string): Bounds | undefined;
8
+ export declare function nestedBounds(text: string, where: Bounds, parent: string, list: string): Bounds | undefined;
8
9
  export declare function holdsRow(text: string, where: Bounds, id: string): boolean;
9
10
  export declare function seededAt(text: string, where: Bounds, id: string): string | undefined;
10
11
  export declare function rowsIn(text: string, where: Bounds): readonly {
@@ -24,5 +25,8 @@ export declare const STATED: string[];
24
25
  export declare function reconciled(held: string, source: string, fields: readonly string[]): string;
25
26
  export declare function fieldIn(text: string, where: Bounds, id: string, field: string): string | undefined;
26
27
  export declare function withField(text: string, where: Bounds, id: string, field: string, value: string): string | undefined;
28
+ export declare function withTopField(text: string, field: string, value: string): string | undefined;
29
+ export declare function withoutField(text: string, where: Bounds, id: string, field: string): string;
27
30
  export declare function withoutRow(text: string, where: Bounds, id: string): string;
31
+ export declare function marked(parts: readonly string[]): string;
28
32
  export declare function showing(row: object, only?: readonly string[]): string;
package/dist/core/rows.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { createHash } from 'node:crypto';
1
2
  import ts from 'typescript';
2
3
  const PARSED = new Map();
3
4
  function tree(text) {
@@ -109,6 +110,13 @@ export function listBounds(text, list) {
109
110
  const inside = listy(held, list);
110
111
  return inside === undefined ? undefined : spanned(inside);
111
112
  }
113
+ export function nestedBounds(text, where, parent, list) {
114
+ const row = rowAt(text, where, parent);
115
+ if (row === undefined)
116
+ return undefined;
117
+ const inside = listy(row, list);
118
+ return inside === undefined ? undefined : spanned(inside);
119
+ }
112
120
  function elements(text, where) {
113
121
  let found;
114
122
  walk(tree(text), (node) => {
@@ -341,8 +349,26 @@ export function fieldIn(text, where, id, field) {
341
349
  }
342
350
  export function withField(text, where, id, field, value) {
343
351
  const held = rowAt(text, where, id);
344
- if (held === undefined)
345
- return undefined;
352
+ return held === undefined ? undefined : fieldOn(text, held, field, value);
353
+ }
354
+ export function withTopField(text, field, value) {
355
+ const held = headed(text);
356
+ return held === undefined ? undefined : fieldOn(text, held, field, value);
357
+ }
358
+ export function withoutField(text, where, id, field) {
359
+ const held = rowAt(text, where, id);
360
+ const one = held?.properties.find((each) => ts.isPropertyAssignment(each) && keyed(each) === field);
361
+ if (held === undefined || one === undefined)
362
+ return text;
363
+ let ends = one.getEnd();
364
+ if (text[ends] === ',')
365
+ ends += 1;
366
+ const line = text.lastIndexOf('\n', one.getStart());
367
+ if (line > held.getStart())
368
+ return text.slice(0, line) + text.slice(ends);
369
+ return text.slice(0, one.getStart()) + text.slice(text[ends] === ' ' ? ends + 1 : ends);
370
+ }
371
+ function fieldOn(text, held, field, value) {
346
372
  for (const one of held.properties) {
347
373
  if (!ts.isPropertyAssignment(one) || keyed(one) !== field)
348
374
  continue;
@@ -403,6 +429,9 @@ const lines = (held, pad) => {
403
429
  }
404
430
  return [String(held)];
405
431
  };
432
+ export function marked(parts) {
433
+ return createHash('sha256').update(parts.join('\n')).digest('hex').slice(0, 6);
434
+ }
406
435
  export function showing(row, only = []) {
407
436
  const held = row;
408
437
  const keys = Object.keys(held);
package/dist/core/rows.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { createHash } from 'node:crypto'
2
+
1
3
  import ts from 'typescript'
2
4
 
3
5
  export interface Bounds {
@@ -117,6 +119,13 @@ export function listBounds(text: string, list: string): Bounds | undefined {
117
119
  return inside === undefined ? undefined : spanned(inside)
118
120
  }
119
121
 
122
+ export function nestedBounds(text: string, where: Bounds, parent: string, list: string): Bounds | undefined {
123
+ const row = rowAt(text, where, parent)
124
+ if (row === undefined) return undefined
125
+ const inside = listy(row, list)
126
+ return inside === undefined ? undefined : spanned(inside)
127
+ }
128
+
120
129
  function elements(text: string, where: Bounds): readonly ts.ObjectLiteralExpression[] {
121
130
  let found: ts.ArrayLiteralExpression | undefined
122
131
  walk(tree(text), (node) => {
@@ -351,7 +360,26 @@ export function withField(
351
360
  value: string,
352
361
  ): string | undefined {
353
362
  const held = rowAt(text, where, id)
354
- if (held === undefined) return undefined
363
+ return held === undefined ? undefined : fieldOn(text, held, field, value)
364
+ }
365
+
366
+ export function withTopField(text: string, field: string, value: string): string | undefined {
367
+ const held = headed(text)
368
+ return held === undefined ? undefined : fieldOn(text, held, field, value)
369
+ }
370
+
371
+ export function withoutField(text: string, where: Bounds, id: string, field: string): string {
372
+ const held = rowAt(text, where, id)
373
+ const one = held?.properties.find((each) => ts.isPropertyAssignment(each) && keyed(each) === field)
374
+ if (held === undefined || one === undefined) return text
375
+ let ends = one.getEnd()
376
+ if (text[ends] === ',') ends += 1
377
+ const line = text.lastIndexOf('\n', one.getStart())
378
+ if (line > held.getStart()) return text.slice(0, line) + text.slice(ends)
379
+ return text.slice(0, one.getStart()) + text.slice(text[ends] === ' ' ? ends + 1 : ends)
380
+ }
381
+
382
+ function fieldOn(text: string, held: ts.ObjectLiteralExpression, field: string, value: string): string | undefined {
355
383
  for (const one of held.properties) {
356
384
  if (!ts.isPropertyAssignment(one) || keyed(one) !== field) continue
357
385
  return `${text.slice(0, one.initializer.getStart())}${value}${text.slice(one.initializer.getEnd())}`
@@ -409,6 +437,10 @@ const lines = (held: unknown, pad: string): readonly string[] => {
409
437
  return [String(held)]
410
438
  }
411
439
 
440
+ export function marked(parts: readonly string[]): string {
441
+ return createHash('sha256').update(parts.join('\n')).digest('hex').slice(0, 6)
442
+ }
443
+
412
444
  export function showing(row: object, only: readonly string[] = []): string {
413
445
  const held = row as Record<string, unknown>
414
446
  const keys = Object.keys(held)
@@ -4,3 +4,4 @@ export declare const NAMED = "@prestack/thread";
4
4
  export declare const named: (id: string) => string;
5
5
  export declare const idOf: (name: string) => string | undefined;
6
6
  export declare const ours: (name: string) => boolean;
7
+ export declare const installed: (at: string) => boolean;
@@ -10,3 +10,4 @@ export const idOf = (name) => {
10
10
  return name.startsWith(HEAD) ? name.slice(HEAD.length) : undefined;
11
11
  };
12
12
  export const ours = (name) => idOf(name) !== undefined;
13
+ export const installed = (at) => at.startsWith('node_modules/') && ours(at.split('/').slice(1, 3).join('/'));