@prestack/thread 0.0.3 → 0.1.1

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 (183) hide show
  1. package/CHANGELOG.md +310 -0
  2. package/dist/core/{asking.d.ts → answers.d.ts} +6 -14
  3. package/dist/core/{asking.js → answers.js} +13 -332
  4. package/dist/core/{asking.ts → answers.ts} +14 -357
  5. package/dist/core/attach.js +2 -2
  6. package/dist/core/attach.ts +2 -3
  7. package/dist/core/chain.js +4 -11
  8. package/dist/core/chain.ts +4 -3
  9. package/dist/core/client.d.ts +57 -0
  10. package/dist/core/client.js +243 -0
  11. package/dist/core/client.ts +279 -0
  12. package/dist/core/descend.d.ts +2 -0
  13. package/dist/core/descend.js +109 -16
  14. package/dist/core/descend.ts +120 -16
  15. package/dist/core/files.d.ts +45 -0
  16. package/dist/core/files.js +145 -0
  17. package/dist/core/files.ts +193 -0
  18. package/dist/core/init.d.ts +1 -0
  19. package/dist/core/init.js +10 -2
  20. package/dist/core/init.ts +8 -2
  21. package/dist/core/invoked.js +1 -1
  22. package/dist/core/invoked.ts +1 -1
  23. package/dist/core/rows.d.ts +2 -0
  24. package/dist/core/rows.js +65 -0
  25. package/dist/core/rows.ts +58 -0
  26. package/dist/core/tree.js +1 -1
  27. package/dist/core/tree.ts +1 -1
  28. package/dist/derivation/attach.js +0 -12
  29. package/dist/derivation/attach.ts +0 -12
  30. package/dist/derivation/generators/build.js +8 -7
  31. package/dist/derivation/generators/build.ts +8 -7
  32. package/dist/derivation/generators/release.d.ts +1 -1
  33. package/dist/derivation/generators/release.js +15 -23
  34. package/dist/derivation/generators/release.ts +15 -15
  35. package/dist/integrations/attach.js +1 -19
  36. package/dist/integrations/attach.ts +1 -19
  37. package/dist/integrations/generators/read.js +2 -2
  38. package/dist/integrations/generators/read.ts +4 -4
  39. package/dist/integrations/generators/vault.js +4 -12
  40. package/dist/integrations/generators/vault.ts +4 -4
  41. package/dist/integrations/module.js +5 -3
  42. package/dist/integrations/module.ts +5 -3
  43. package/dist/integrations/vault.js +5 -5
  44. package/dist/integrations/vault.ts +5 -5
  45. package/dist/integrity/attach.js +0 -12
  46. package/dist/integrity/attach.ts +0 -12
  47. package/dist/integrity/check-threads.js +1 -1
  48. package/dist/integrity/check-threads.ts +1 -1
  49. package/dist/integrity/constraint.d.ts +11 -2
  50. package/dist/integrity/constraint.js +163 -20
  51. package/dist/integrity/constraint.ts +174 -22
  52. package/dist/integrity/generators/compiler.js +7 -1
  53. package/dist/integrity/generators/compiler.ts +10 -1
  54. package/dist/integrity/generators/gate.js +23 -18
  55. package/dist/integrity/generators/gate.ts +29 -9
  56. package/dist/integrity/generators/publish.js +14 -26
  57. package/dist/integrity/generators/publish.ts +14 -17
  58. package/dist/integrity/generators/trial.d.ts +2 -2
  59. package/dist/integrity/generators/trial.js +108 -50
  60. package/dist/integrity/generators/trial.ts +107 -48
  61. package/dist/integrity/lint.js +3 -3
  62. package/dist/integrity/lint.ts +3 -3
  63. package/dist/integrity/lsp/diagnostics.js +1 -1
  64. package/dist/integrity/lsp/diagnostics.ts +1 -1
  65. package/dist/integrity/lsp/lint.js +1 -1
  66. package/dist/integrity/lsp/lint.ts +1 -1
  67. package/dist/integrity/slopnator.d.ts +1 -14
  68. package/dist/integrity/slopnator.js +8 -40
  69. package/dist/integrity/slopnator.ts +9 -51
  70. package/dist/integrity/slopnators/sl_broken_lineage.js +4 -2
  71. package/dist/integrity/slopnators/sl_broken_lineage.ts +4 -2
  72. package/dist/integrity/slopnators/sl_declared_elsewhere.js +24 -3
  73. package/dist/integrity/slopnators/sl_declared_elsewhere.ts +24 -3
  74. package/dist/integrity/slopnators/sl_derived_drift.js +10 -4
  75. package/dist/integrity/slopnators/sl_derived_drift.ts +10 -4
  76. package/dist/integrity/slopnators/sl_inert_island.js +7 -13
  77. package/dist/integrity/slopnators/sl_inert_island.ts +7 -16
  78. package/dist/integrity/slopnators/sl_inert_slopnator.js +8 -8
  79. package/dist/integrity/slopnators/sl_inert_slopnator.ts +8 -8
  80. package/dist/integrity/slopnators/sl_missing_row.js +14 -9
  81. package/dist/integrity/slopnators/sl_missing_row.ts +14 -10
  82. package/dist/integrity/slopnators/sl_no_child_process.js +8 -8
  83. package/dist/integrity/slopnators/sl_no_child_process.ts +8 -8
  84. package/dist/integrity/slopnators/sl_no_import_cycle.js +1 -1
  85. package/dist/integrity/slopnators/sl_no_import_cycle.ts +1 -1
  86. package/dist/integrity/slopnators/sl_no_such_command.js +20 -5
  87. package/dist/integrity/slopnators/sl_no_such_command.ts +22 -5
  88. package/dist/integrity/slopnators/sl_only_takes_a_literal.js +8 -8
  89. package/dist/integrity/slopnators/sl_only_takes_a_literal.ts +8 -8
  90. package/dist/integrity/slopnators/sl_stale_path.js +91 -18
  91. package/dist/integrity/slopnators/sl_stale_path.ts +97 -18
  92. package/dist/integrity/slopnators/sl_twice_meant.js +25 -2
  93. package/dist/integrity/slopnators/sl_twice_meant.ts +28 -2
  94. package/dist/integrity/slopnators/sl_twice_parented.js +26 -5
  95. package/dist/integrity/slopnators/sl_twice_parented.ts +26 -5
  96. package/dist/integrity/slopnators/sl_undeclared_node.js +18 -2
  97. package/dist/integrity/slopnators/sl_undeclared_node.ts +18 -2
  98. package/dist/integrity/slopnators/sl_undeclared_operation.js +3 -1
  99. package/dist/integrity/slopnators/sl_undeclared_operation.ts +3 -1
  100. package/dist/integrity/slopnators/sl_undeclared_variant.js +6 -2
  101. package/dist/integrity/slopnators/sl_undeclared_variant.ts +6 -2
  102. package/dist/integrity/slopnators/sl_ungoverned_island.js +3 -4
  103. package/dist/integrity/slopnators/sl_ungoverned_island.ts +3 -4
  104. package/dist/integrity/slopnators/sl_unkept_rows.js +1 -1
  105. package/dist/integrity/slopnators/sl_unkept_rows.ts +1 -1
  106. package/dist/integrity/slopnators/sl_unpaired_member.js +13 -8
  107. package/dist/integrity/slopnators/sl_unpaired_member.ts +16 -8
  108. package/dist/integrity/slopnators/sl_unpaired_slopnator.js +16 -3
  109. package/dist/integrity/slopnators/sl_unpaired_slopnator.ts +16 -3
  110. package/dist/integrity/slopnators/sl_unthreaded.d.ts +1 -0
  111. package/dist/integrity/slopnators/sl_unthreaded.js +18 -10
  112. package/dist/integrity/slopnators/sl_unthreaded.ts +19 -11
  113. package/dist/integrity/slopnators/sl_untranslated_key.js +1 -1
  114. package/dist/integrity/slopnators/sl_untranslated_key.ts +1 -1
  115. package/dist/integrity/slopnators/sl_unversioned.js +16 -2
  116. package/dist/integrity/slopnators/sl_unversioned.ts +16 -2
  117. package/dist/integrity/sweep.js +17 -3
  118. package/dist/integrity/sweep.ts +20 -3
  119. package/dist/knowledge/attach.js +0 -6
  120. package/dist/knowledge/attach.ts +0 -6
  121. package/dist/knowledge/generators/docsgen.js +12 -3
  122. package/dist/knowledge/generators/docsgen.ts +12 -2
  123. package/dist/knowledge/generators/glossary.js +1 -1
  124. package/dist/knowledge/generators/glossary.ts +1 -1
  125. package/dist/operations/attach.js +2 -26
  126. package/dist/operations/attach.ts +2 -27
  127. package/dist/operations/dispatch.js +2 -3
  128. package/dist/operations/dispatch.ts +2 -3
  129. package/dist/operations/generators/capability.js +4 -7
  130. package/dist/operations/generators/capability.ts +3 -6
  131. package/dist/operations/generators/compile.js +8 -13
  132. package/dist/operations/generators/compile.ts +8 -4
  133. package/dist/operations/generators/permits.js +4 -13
  134. package/dist/operations/generators/permits.ts +3 -3
  135. package/dist/operations/generators/seed.js +5 -2
  136. package/dist/operations/generators/seed.ts +6 -2
  137. package/dist/operations/generators/trial.js +10 -10
  138. package/dist/operations/generators/trial.ts +10 -10
  139. package/dist/operations/http.js +4 -1
  140. package/dist/operations/http.ts +6 -1
  141. package/package.json +2 -2
  142. package/dist/core/cli.d.ts +0 -2
  143. package/dist/core/cli.js +0 -1761
  144. package/dist/core/cli.ts +0 -2004
  145. package/dist/core/generators/meta.d.ts +0 -2
  146. package/dist/core/generators/meta.js +0 -829
  147. package/dist/core/generators/meta.ts +0 -1006
  148. package/dist/derivation/generators/derivation.d.ts +0 -3
  149. package/dist/derivation/generators/derivation.js +0 -273
  150. package/dist/derivation/generators/derivation.ts +0 -347
  151. package/dist/derivation/makers/release.d.ts +0 -1
  152. package/dist/derivation/makers/release.js +0 -107
  153. package/dist/derivation/makers/release.ts +0 -135
  154. package/dist/integrations/generators/secret.d.ts +0 -1
  155. package/dist/integrations/generators/secret.js +0 -233
  156. package/dist/integrations/generators/secret.ts +0 -289
  157. package/dist/integrations/generators/target.d.ts +0 -1
  158. package/dist/integrations/generators/target.js +0 -775
  159. package/dist/integrations/generators/target.ts +0 -944
  160. package/dist/integrity/generators/rule.d.ts +0 -2
  161. package/dist/integrity/generators/rule.js +0 -213
  162. package/dist/integrity/generators/rule.ts +0 -271
  163. package/dist/integrity/generators/seal.d.ts +0 -4
  164. package/dist/integrity/generators/seal.js +0 -101
  165. package/dist/integrity/generators/seal.ts +0 -117
  166. package/dist/integrity/sealed.d.ts +0 -1
  167. package/dist/integrity/sealed.js +0 -56
  168. package/dist/integrity/sealed.ts +0 -56
  169. package/dist/knowledge/generators/skills.d.ts +0 -1
  170. package/dist/knowledge/generators/skills.js +0 -222
  171. package/dist/knowledge/generators/skills.ts +0 -263
  172. package/dist/operations/generators/grant.d.ts +0 -1
  173. package/dist/operations/generators/grant.js +0 -267
  174. package/dist/operations/generators/grant.ts +0 -336
  175. package/dist/operations/generators/operation.d.ts +0 -1
  176. package/dist/operations/generators/operation.js +0 -811
  177. package/dist/operations/generators/operation.ts +0 -972
  178. package/dist/operations/makers/capability.d.ts +0 -1
  179. package/dist/operations/makers/capability.js +0 -117
  180. package/dist/operations/makers/capability.ts +0 -166
  181. package/dist/operations/makers/trial.d.ts +0 -1
  182. package/dist/operations/makers/trial.js +0 -413
  183. package/dist/operations/makers/trial.ts +0 -520
@@ -1,41 +1,33 @@
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 { existsSync, readFileSync, writeFileSync } from 'node:fs';
10
1
  import { join } from 'node:path';
11
2
  import { argv, stderr, stdout } from 'node:process';
12
- import { pathToFileURL } from 'node:url';
13
- import { marked, wordsIn } from "../../core/asking.js";
3
+ import { marked, wordsIn } from "../../core/answers.js";
4
+ import { existsSync, readFileSync, writeFileSync } from "../../core/files.js";
14
5
  import { exit, invoked } from "../../core/invoked.js";
6
+ import { valuesIn } from "../../core/rows.js";
15
7
  import { ours } from "../../core/scope.js";
16
8
  import { findTree, inTree } from "../../core/tree.js";
17
9
  import { CHECKED_BY, KINDS, LISTENS, SAID, WRITES, WRITTEN_BY, kindOf } from "../release.js";
18
10
  const TREE = findTree();
19
11
  const MANIFEST = 'package.json';
20
12
  const mark = (one) => marked([one.id ?? '', one.at ?? '']);
21
- async function releases() {
13
+ function releases() {
22
14
  const at = inTree(TREE, 'derivation.ts');
23
15
  if (!existsSync(at))
24
16
  return [];
25
17
  try {
26
- const held = (await import(__rewriteRelativeImportExtension(pathToFileURL(at).href)));
18
+ const held = valuesIn(readFileSync(at, 'utf8'));
27
19
  return held.DERIVATION?.derives ?? [];
28
20
  }
29
21
  catch {
30
22
  return [];
31
23
  }
32
24
  }
33
- async function named() {
25
+ function named() {
34
26
  const at = inTree(TREE, 'secrets.ts');
35
27
  if (!existsSync(at))
36
28
  return [];
37
29
  try {
38
- const held = (await import(__rewriteRelativeImportExtension(pathToFileURL(at).href)));
30
+ const held = valuesIn(readFileSync(at, 'utf8'));
39
31
  return (held.SECRETS ?? []).map((one) => one.id.toUpperCase()).sort();
40
32
  }
41
33
  catch {
@@ -94,10 +86,10 @@ function compose(id, secrets) {
94
86
  '',
95
87
  ].join('\n');
96
88
  }
97
- async function made() {
89
+ function made() {
98
90
  const found = new Map();
99
- const rows = await releases();
100
- const secrets = await named();
91
+ const rows = releases();
92
+ const secrets = named();
101
93
  const { build, start } = scripted();
102
94
  for (const one of rows) {
103
95
  const id = one.id;
@@ -121,8 +113,8 @@ function installed() {
121
113
  const held = JSON.parse(readFileSync(at, 'utf8'));
122
114
  return Object.keys(held.dependencies ?? {}).filter((one) => ours(one)).sort();
123
115
  }
124
- async function run() {
125
- const rows = await releases();
116
+ function run() {
117
+ const rows = releases();
126
118
  if (rows.length === 0) {
127
119
  stdout.write(`release: this app declares no release, so there is nowhere for it to go yet. Declare one with ` +
128
120
  `\`thread create release\` — it is ${KINDS.join(' or ')}, and the prefix on its id says which.\n`);
@@ -151,7 +143,7 @@ async function run() {
151
143
  }
152
144
  return 0;
153
145
  }
154
- const files = await made();
146
+ const files = made();
155
147
  const checking = argv.includes('--check');
156
148
  const shipped = installed();
157
149
  if (shipped.length > 0) {
@@ -185,9 +177,9 @@ async function run() {
185
177
  for (const [at, text] of files)
186
178
  writeFileSync(join(TREE.at, at), text, 'utf8');
187
179
  stdout.write(`release: wrote ${[...files.keys()].join(', ')} — built and started by what this app's own manifest ` +
188
- `declares, listening on ${String(LISTENS)}, naming ${String((await named()).length)} secret(s) and holding none of them.\n`);
180
+ `declares, listening on ${String(LISTENS)}, naming ${String(named().length)} secret(s) and holding none of them.\n`);
189
181
  return 0;
190
182
  }
191
183
  if (invoked(import.meta.url))
192
- exit(await run());
184
+ exit(run());
193
185
  export { CHECKED_BY, WRITES, made };
@@ -1,10 +1,10 @@
1
- import { existsSync, readFileSync, writeFileSync } from 'node:fs'
2
1
  import { join } from 'node:path'
3
2
  import { argv, stderr, stdout } from 'node:process'
4
- import { pathToFileURL } from 'node:url'
5
3
 
6
- import { marked, wordsIn } from '../../core/asking.ts'
4
+ import { marked, wordsIn } from '../../core/answers.ts'
5
+ import { existsSync, readFileSync, writeFileSync } from '../../core/files.ts'
7
6
  import { exit, invoked } from '../../core/invoked.ts'
7
+ import { valuesIn } from '../../core/rows.ts'
8
8
  import { ours } from '../../core/scope.ts'
9
9
  import { findTree, inTree } from '../../core/tree.ts'
10
10
 
@@ -21,22 +21,22 @@ interface Row {
21
21
 
22
22
  const mark = (one: Row): string => marked([one.id ?? '', one.at ?? ''])
23
23
 
24
- async function releases(): Promise<readonly Row[]> {
24
+ function releases(): readonly Row[] {
25
25
  const at = inTree(TREE, 'derivation.ts')
26
26
  if (!existsSync(at)) return []
27
27
  try {
28
- const held = (await import(pathToFileURL(at).href)) as { DERIVATION?: { readonly derives?: readonly Row[] } }
28
+ const held = valuesIn(readFileSync(at, 'utf8')) as { DERIVATION?: { readonly derives?: readonly Row[] } }
29
29
  return held.DERIVATION?.derives ?? []
30
30
  } catch {
31
31
  return []
32
32
  }
33
33
  }
34
34
 
35
- async function named(): Promise<readonly string[]> {
35
+ function named(): readonly string[] {
36
36
  const at = inTree(TREE, 'secrets.ts')
37
37
  if (!existsSync(at)) return []
38
38
  try {
39
- const held = (await import(pathToFileURL(at).href)) as { SECRETS?: readonly { readonly id: string }[] }
39
+ const held = valuesIn(readFileSync(at, 'utf8')) as { SECRETS?: readonly { readonly id: string }[] }
40
40
  return (held.SECRETS ?? []).map((one) => one.id.toUpperCase()).sort()
41
41
  } catch {
42
42
  return []
@@ -100,10 +100,10 @@ function compose(id: string, secrets: readonly string[]): string {
100
100
  ].join('\n')
101
101
  }
102
102
 
103
- async function made(): Promise<ReadonlyMap<string, string>> {
103
+ function made(): ReadonlyMap<string, string> {
104
104
  const found = new Map<string, string>()
105
- const rows = await releases()
106
- const secrets = await named()
105
+ const rows = releases()
106
+ const secrets = named()
107
107
  const { build, start } = scripted()
108
108
 
109
109
  for (const one of rows) {
@@ -128,8 +128,8 @@ function installed(): readonly string[] {
128
128
  return Object.keys(held.dependencies ?? {}).filter((one) => ours(one)).sort()
129
129
  }
130
130
 
131
- async function run(): Promise<number> {
132
- const rows = await releases()
131
+ function run(): number {
132
+ const rows = releases()
133
133
  if (rows.length === 0) {
134
134
  stdout.write(
135
135
  `release: this app declares no release, so there is nowhere for it to go yet. Declare one with ` +
@@ -164,7 +164,7 @@ async function run(): Promise<number> {
164
164
  return 0
165
165
  }
166
166
 
167
- const files = await made()
167
+ const files = made()
168
168
  const checking = argv.includes('--check')
169
169
 
170
170
  const shipped = installed()
@@ -203,11 +203,11 @@ async function run(): Promise<number> {
203
203
  for (const [at, text] of files) writeFileSync(join(TREE.at, at), text, 'utf8')
204
204
  stdout.write(
205
205
  `release: wrote ${[...files.keys()].join(', ')} — built and started by what this app's own manifest ` +
206
- `declares, listening on ${String(LISTENS)}, naming ${String((await named()).length)} secret(s) and holding none of them.\n`,
206
+ `declares, listening on ${String(LISTENS)}, naming ${String(named().length)} secret(s) and holding none of them.\n`,
207
207
  )
208
208
  return 0
209
209
  }
210
210
 
211
- if (invoked(import.meta.url)) exit(await run())
211
+ if (invoked(import.meta.url)) exit(run())
212
212
 
213
213
  export { CHECKED_BY, WRITES, made }
@@ -82,7 +82,7 @@ const OWN = [
82
82
  },
83
83
  ];
84
84
  const SEEDED = {
85
- attaches: ['@prestack/thread/derivation/attach'],
85
+ attaches: ['@prestack/thread/derivation/attach', '@prestack/thread/knowledge/attach'],
86
86
  id: 'integrations',
87
87
  declares: [
88
88
  ' {',
@@ -94,18 +94,6 @@ const SEEDED = {
94
94
  ].join('\n'),
95
95
  };
96
96
  const SHIPPED = [
97
- {
98
- into: 'derivation.ts',
99
- list: 'GENERATORS',
100
- id: 'target-generator',
101
- source: " {\n id: 'target-generator',\n at: 'node_modules/@prestack/thread/dist/integrations/generators/target.js',\n describes: 'The command that declares a place this app reaches. Asked for nothing it lists every target already here with what it accepts and what it requires, every way a target may be reached and what each way can hold, and every secret this app declares. It then asks what the place is called and how it is reached, puts the prefix on the id, asks which secret is its address and which go into a header, and writes the row — so a target arrives declared with its credential named rather than with an environment variable typed into whatever needed it.',\n version: 1,\n by: 'thread create target',\n },",
102
- },
103
- {
104
- into: 'derivation.ts',
105
- list: 'GENERATORS',
106
- id: 'secret-generator',
107
- source: " {\n id: 'secret-generator',\n at: 'node_modules/@prestack/thread/dist/integrations/generators/secret.js',\n describes: 'The command that declares a value this app must be given, and the only thing that ever takes one. It asks what the secret is for and who may hold it, puts `sec_` or `pub_` on the id accordingly, and writes the row. Then it asks a person for the value, with the terminal\\'s echo off, and seals it into the store beside the tree under a key it generates and never prints. The value goes from the keyboard into the sealed store and nowhere else: not into the row, not into the output, not into whatever transcript is being kept of the session that ran it.',\n version: 1,\n by: 'thread create secret',\n },",
108
- },
109
97
  {
110
98
  into: 'derivation.ts',
111
99
  list: 'GENERATORS',
@@ -118,12 +106,6 @@ const SHIPPED = [
118
106
  id: 'inspect-generator',
119
107
  source: " {\n id: 'inspect-generator',\n at: 'node_modules/@prestack/thread/dist/integrations/generators/read.js',\n describes: 'The one command for reading what this app declares. Asked for nothing it prints every sheet and what each holds; asked for a word it prints every row whose id or sentence carries it. It reads the tree rather than the files, which is the whole reason it exists: a row is a nested TypeScript literal and a search over lines answers questions about text while the questions people actually ask are about rows.',\n version: 1,\n by: 'thread inspect',\n },",
120
108
  },
121
- {
122
- into: 'derivation.ts',
123
- list: 'GENERATORS',
124
- id: 'call-noun',
125
- source: " {\n id: 'call-noun',\n at: 'node_modules/@prestack/thread/dist/integrations/generators/target.js',\n describes: 'The command that makes an already-declared call happen. `thread run call <id>` asks for whatever its path leaves to be filled in — `{like_this}` — by name, and for a call that writes (POST, PUT, PATCH) a JSON body, then resolves the target\\'s address and every credential it requires through the vault at the moment of the call and never before. Nothing here ever names a vendor: a call already states its target, its method and its path, and which one runs is read off its own id, exactly as `thread run trial` reads an operation\\'s.',\n version: 1,\n by: 'thread run call',\n },",
126
- },
127
109
  ];
128
110
  export const ATTACH = {
129
111
  attaches: SEEDED.attaches,
@@ -107,7 +107,7 @@ const OWN: readonly { readonly into: string; readonly list: string; readonly id:
107
107
  ]
108
108
 
109
109
  const SEEDED = {
110
- attaches: ['@prestack/thread/derivation/attach'] as const,
110
+ attaches: ['@prestack/thread/derivation/attach', '@prestack/thread/knowledge/attach'] as const,
111
111
  id: 'integrations',
112
112
  declares: [
113
113
  ' {',
@@ -120,18 +120,6 @@ const SEEDED = {
120
120
  }
121
121
 
122
122
  const SHIPPED: readonly { readonly into: string; readonly list: string; readonly id: string; readonly source: string }[] = [
123
- {
124
- into: 'derivation.ts',
125
- list: 'GENERATORS',
126
- id: 'target-generator',
127
- source: " {\n id: 'target-generator',\n at: 'node_modules/@prestack/thread/dist/integrations/generators/target.js',\n describes: 'The command that declares a place this app reaches. Asked for nothing it lists every target already here with what it accepts and what it requires, every way a target may be reached and what each way can hold, and every secret this app declares. It then asks what the place is called and how it is reached, puts the prefix on the id, asks which secret is its address and which go into a header, and writes the row — so a target arrives declared with its credential named rather than with an environment variable typed into whatever needed it.',\n version: 1,\n by: 'thread create target',\n },",
128
- },
129
- {
130
- into: 'derivation.ts',
131
- list: 'GENERATORS',
132
- id: 'secret-generator',
133
- source: " {\n id: 'secret-generator',\n at: 'node_modules/@prestack/thread/dist/integrations/generators/secret.js',\n describes: 'The command that declares a value this app must be given, and the only thing that ever takes one. It asks what the secret is for and who may hold it, puts `sec_` or `pub_` on the id accordingly, and writes the row. Then it asks a person for the value, with the terminal\\'s echo off, and seals it into the store beside the tree under a key it generates and never prints. The value goes from the keyboard into the sealed store and nowhere else: not into the row, not into the output, not into whatever transcript is being kept of the session that ran it.',\n version: 1,\n by: 'thread create secret',\n },",
134
- },
135
123
  {
136
124
  into: 'derivation.ts',
137
125
  list: 'GENERATORS',
@@ -144,12 +132,6 @@ const SHIPPED: readonly { readonly into: string; readonly list: string; readonly
144
132
  id: 'inspect-generator',
145
133
  source: " {\n id: 'inspect-generator',\n at: 'node_modules/@prestack/thread/dist/integrations/generators/read.js',\n describes: 'The one command for reading what this app declares. Asked for nothing it prints every sheet and what each holds; asked for a word it prints every row whose id or sentence carries it. It reads the tree rather than the files, which is the whole reason it exists: a row is a nested TypeScript literal and a search over lines answers questions about text while the questions people actually ask are about rows.',\n version: 1,\n by: 'thread inspect',\n },",
146
134
  },
147
- {
148
- into: 'derivation.ts',
149
- list: 'GENERATORS',
150
- id: 'call-noun',
151
- source: " {\n id: 'call-noun',\n at: 'node_modules/@prestack/thread/dist/integrations/generators/target.js',\n describes: 'The command that makes an already-declared call happen. `thread run call <id>` asks for whatever its path leaves to be filled in — `{like_this}` — by name, and for a call that writes (POST, PUT, PATCH) a JSON body, then resolves the target\\'s address and every credential it requires through the vault at the moment of the call and never before. Nothing here ever names a vendor: a call already states its target, its method and its path, and which one runs is read off its own id, exactly as `thread run trial` reads an operation\\'s.',\n version: 1,\n by: 'thread run call',\n },",
152
- },
153
135
  ]
154
136
  export const ATTACH: Attaching = {
155
137
  attaches: SEEDED.attaches,
@@ -1,6 +1,6 @@
1
1
  import { stdout } from 'node:process';
2
2
  import { exit } from "../../core/invoked.js";
3
- import { wordsIn } from "../../core/asking.js";
3
+ import { TYPED, wordsIn } from "../../core/answers.js";
4
4
  import { descend } from "../../core/descend.js";
5
5
  const words = wordsIn([]);
6
6
  const looking = words.join(' ').trim().toLowerCase();
@@ -43,7 +43,7 @@ if (looking === '') {
43
43
  out.push(` ${String(held.length).padStart(4)} ${file}`);
44
44
  }
45
45
  out.unshift(`${String(files.length)} sheet(s) in this tree, and what each holds:`, '');
46
- out.push('', 'Name a word to read the rows themselves — every row whose id, sentence, path, command or', 'requirement carries it, each with what it means:', '', ' npx thread inspect element', ' npx thread inspect variant', ' npx thread inspect <any word above, or any word this tree coins>', '');
46
+ out.push('', 'Name a word to read the rows themselves — every row whose id, sentence, path, command or', 'requirement carries it, each with what it means:', '', ` ${TYPED} inspect element`, ` ${TYPED} inspect variant`, ` ${TYPED} inspect <any word above, or any word this tree coins>`, '');
47
47
  stdout.write(`${out.join('\n')}\n`);
48
48
  stdout.write(`read: ${String(rows)} row(s) across ${String(pass.declarations)} declaration(s), ` +
49
49
  `and ${String(pass.findings.length)} finding(s) the gate would report.\n`);
@@ -1,7 +1,7 @@
1
1
  import { stdout } from 'node:process'
2
2
 
3
3
  import { exit } from '../../core/invoked.ts'
4
- import { wordsIn } from '../../core/asking.ts'
4
+ import { TYPED, wordsIn } from '../../core/answers.ts'
5
5
  import { descend, type Row } from '../../core/descend.ts'
6
6
 
7
7
  const words = wordsIn([])
@@ -63,9 +63,9 @@ if (looking === '') {
63
63
  'Name a word to read the rows themselves — every row whose id, sentence, path, command or',
64
64
  'requirement carries it, each with what it means:',
65
65
  '',
66
- ' npx thread inspect element',
67
- ' npx thread inspect variant',
68
- ' npx thread inspect <any word above, or any word this tree coins>',
66
+ ` ${TYPED} inspect element`,
67
+ ` ${TYPED} inspect variant`,
68
+ ` ${TYPED} inspect <any word above, or any word this tree coins>`,
69
69
  '',
70
70
  )
71
71
  stdout.write(`${out.join('\n')}\n`)
@@ -1,12 +1,5 @@
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 { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
1
+ import { existsSync, readFileSync, writeFileSync } from "../../core/files.js";
2
+ import { valuesIn } from "../../core/rows.js";
10
3
  import { dirname, join, relative } from 'node:path';
11
4
  import { argv, stderr, stdout } from 'node:process';
12
5
  import { fileURLToPath } from 'node:url';
@@ -31,7 +24,7 @@ function refuse(because) {
31
24
  }
32
25
  let secrets = [];
33
26
  try {
34
- const taken = (await import(__rewriteRelativeImportExtension(new URL(`file://${from}`).href)));
27
+ const taken = valuesIn(readFileSync(from));
35
28
  secrets = taken.SECRETS ?? [];
36
29
  }
37
30
  catch {
@@ -80,7 +73,7 @@ async function taken(file, list) {
80
73
  if (!existsSync(at))
81
74
  return [];
82
75
  try {
83
- const held = (await import(__rewriteRelativeImportExtension(new URL(`file://${at}`).href)));
76
+ const held = valuesIn(readFileSync(at));
84
77
  return held[list] ?? [];
85
78
  }
86
79
  catch {
@@ -187,7 +180,6 @@ if (existsSync(path) && readFileSync(path, 'utf8') === SOURCE) {
187
180
  stdout.write(`vault: ${AT} is already yours — it opens ${opening}, read off ${here(from)} as they are declared.\n`);
188
181
  exit(0);
189
182
  }
190
- mkdirSync(dirname(path), { recursive: true });
191
183
  writeFileSync(path, SOURCE, 'utf8');
192
184
  stdout.write(`vault: wrote ${AT} — what opens a secret's value at the moment of use.\n` +
193
185
  ` It opens the values sealed under ${SEALED_AT} for the secrets declared in ${here(from)}, and refuses every other name.\n` +
@@ -1,4 +1,5 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
1
+ import { existsSync, readFileSync, writeFileSync } from '../../core/files.ts'
2
+ import { valuesIn } from '../../core/rows.ts'
2
3
  import { dirname, join, relative } from 'node:path'
3
4
  import { argv, stderr, stdout } from 'node:process'
4
5
  import { fileURLToPath } from 'node:url'
@@ -36,7 +37,7 @@ function refuse(because: string): never {
36
37
 
37
38
  let secrets: readonly Secret[] = []
38
39
  try {
39
- const taken = (await import(new URL(`file://${from}`).href)) as { SECRETS?: readonly Secret[] }
40
+ const taken = valuesIn(readFileSync(from)) as { SECRETS?: readonly Secret[] }
40
41
  secrets = taken.SECRETS ?? []
41
42
  } catch {
42
43
  refuse(`${here(from)} could not be read. Attach \`${packageOf('integrations')}\` first — an app states its secrets there.`)
@@ -86,7 +87,7 @@ async function taken<T>(file: string, list: string): Promise<readonly T[]> {
86
87
  const at = inTree(TREE, file)
87
88
  if (!existsSync(at)) return []
88
89
  try {
89
- const held = (await import(new URL(`file://${at}`).href)) as Record<string, readonly T[] | undefined>
90
+ const held = valuesIn(readFileSync(at)) as Record<string, readonly T[] | undefined>
90
91
  return held[list] ?? []
91
92
  } catch {
92
93
  return []
@@ -201,7 +202,6 @@ if (existsSync(path) && readFileSync(path, 'utf8') === SOURCE) {
201
202
  exit(0)
202
203
  }
203
204
 
204
- mkdirSync(dirname(path), { recursive: true })
205
205
  writeFileSync(path, SOURCE, 'utf8')
206
206
  stdout.write(
207
207
  `vault: wrote ${AT} — what opens a secret's value at the moment of use.\n` +
@@ -8,8 +8,10 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
8
8
  };
9
9
  import { spawnSync } from 'node:child_process';
10
10
  import { argv, stderr, stdout } from 'node:process';
11
- import { answer, asking, given, only, wordsIn } from "../core/asking.js";
11
+ import { answer, asking, given, unasked, wordsIn } from "../core/answers.js";
12
+ import { readFileSync } from "../core/files.js";
12
13
  import { exit } from "../core/invoked.js";
14
+ import { valuesIn } from "../core/rows.js";
13
15
  import { findTree, inTree } from "../core/tree.js";
14
16
  import { REACH, reachOf } from "./target.js";
15
17
  import { opened } from "./vault.js";
@@ -34,7 +36,7 @@ export async function ran(name) {
34
36
  const tree = findTree();
35
37
  let targets = [];
36
38
  try {
37
- const taken = (await import(__rewriteRelativeImportExtension(new URL(`file://${inTree(tree, 'targets.ts')}`).href)));
39
+ const taken = valuesIn(readFileSync(inTree(tree, 'targets.ts')));
38
40
  targets = taken.TARGETS ?? [];
39
41
  }
40
42
  catch {
@@ -79,7 +81,7 @@ export async function run(declared) {
79
81
  return refuse(`\`${method}\` is not a method path — one name, or names joined by dots, e.g. \`customers.list\``);
80
82
  }
81
83
  const piped = given();
82
- only(piped, TAKES, `\`thread run ${declared.name} ${method}\``);
84
+ unasked(piped, TAKES, `\`thread run ${declared.name} ${method}\``);
83
85
  const { ask, shut } = asking(piped);
84
86
  const typed = (piped.length > 0
85
87
  ? (answer(piped, TAKES[0] ?? 'args') ?? '')
@@ -2,8 +2,10 @@ import { spawnSync } from 'node:child_process'
2
2
  import { argv, stderr, stdout } from 'node:process'
3
3
 
4
4
  import type { Env } from '../core/actor.ts'
5
- import { answer, asking, given, only, wordsIn } from '../core/asking.ts'
5
+ import { answer, asking, given, unasked, wordsIn } from '../core/answers.ts'
6
+ import { readFileSync } from '../core/files.ts'
6
7
  import { exit } from '../core/invoked.ts'
8
+ import { valuesIn } from '../core/rows.ts'
7
9
  import { findTree, inTree } from '../core/tree.ts'
8
10
 
9
11
  import { REACH, reachOf, type Target } from './target.ts'
@@ -37,7 +39,7 @@ export async function ran(name: string): Promise<void> {
37
39
  const tree = findTree()
38
40
  let targets: readonly Target[] = []
39
41
  try {
40
- const taken = (await import(new URL(`file://${inTree(tree, 'targets.ts')}`).href)) as {
42
+ const taken = valuesIn(readFileSync(inTree(tree, 'targets.ts'))) as {
41
43
  TARGETS?: readonly Target[]
42
44
  }
43
45
  targets = taken.TARGETS ?? []
@@ -104,7 +106,7 @@ export async function run(declared: {
104
106
  }
105
107
 
106
108
  const piped = given()
107
- only(piped, TAKES, `\`thread run ${declared.name} ${method}\``)
109
+ unasked(piped, TAKES, `\`thread run ${declared.name} ${method}\``)
108
110
  const { ask, shut } = asking(piped)
109
111
  const typed = (
110
112
  piped.length > 0
@@ -1,6 +1,7 @@
1
1
  import { createCipheriv, createDecipheriv, randomBytes } from 'node:crypto';
2
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
- import { dirname, join } from 'node:path';
2
+ import * as disk from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { existsSync, readFileSync, writeFileSync } from "../core/files.js";
4
5
  export const VAULT_DIR = '.thread';
5
6
  export const SEALED_NAME = 'vault.sealed.json';
6
7
  export const KEY_NAME = 'vault.key';
@@ -48,8 +49,8 @@ export function keyed(root) {
48
49
  if (held !== undefined)
49
50
  return held;
50
51
  const made = randomBytes(KEY_BYTES);
51
- mkdirSync(join(root, VAULT_DIR), { recursive: true });
52
- writeFileSync(join(root, KEY_AT), `${made.toString('base64')}\n`, { mode: 0o600 });
52
+ disk.mkdirSync(join(root, VAULT_DIR), { recursive: true });
53
+ disk.writeFileSync(join(root, KEY_AT), `${made.toString('base64')}\n`, { mode: 0o600 });
53
54
  return made;
54
55
  }
55
56
  export function seal(root, named, env, value) {
@@ -61,7 +62,6 @@ export function seal(root, named, env, value) {
61
62
  held[named] = { ...held[named], [env]: [iv, cipher.getAuthTag(), body].map((one) => one.toString('base64')).join('.') };
62
63
  const sorted = Object.fromEntries(Object.keys(held).sort().map((one) => [one, held[one]]));
63
64
  const at = join(root, SEALED_AT);
64
- mkdirSync(dirname(at), { recursive: true });
65
65
  writeFileSync(at, `${JSON.stringify(sorted, null, 2)}\n`);
66
66
  }
67
67
  export const sealedIn = (root, env) => Object.entries(store(root))
@@ -1,8 +1,9 @@
1
1
  import { createCipheriv, createDecipheriv, randomBytes } from 'node:crypto'
2
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
3
- import { dirname, join } from 'node:path'
2
+ import * as disk from 'node:fs'
3
+ import { join } from 'node:path'
4
4
 
5
5
  import type { Env } from '../core/actor.ts'
6
+ import { existsSync, readFileSync, writeFileSync } from '../core/files.ts'
6
7
 
7
8
  export const VAULT_DIR = '.thread'
8
9
 
@@ -74,8 +75,8 @@ export function keyed(root: string): Buffer {
74
75
  const held = keyOf(root)
75
76
  if (held !== undefined) return held
76
77
  const made = randomBytes(KEY_BYTES)
77
- mkdirSync(join(root, VAULT_DIR), { recursive: true })
78
- writeFileSync(join(root, KEY_AT), `${made.toString('base64')}\n`, { mode: 0o600 })
78
+ disk.mkdirSync(join(root, VAULT_DIR), { recursive: true })
79
+ disk.writeFileSync(join(root, KEY_AT), `${made.toString('base64')}\n`, { mode: 0o600 })
79
80
  return made
80
81
  }
81
82
 
@@ -88,7 +89,6 @@ export function seal(root: string, named: string, env: Env, value: string): void
88
89
  held[named] = { ...held[named], [env]: [iv, cipher.getAuthTag(), body].map((one) => one.toString('base64')).join('.') }
89
90
  const sorted = Object.fromEntries(Object.keys(held).sort().map((one) => [one, held[one]]))
90
91
  const at = join(root, SEALED_AT)
91
- mkdirSync(dirname(at), { recursive: true })
92
92
  writeFileSync(at, `${JSON.stringify(sorted, null, 2)}\n`)
93
93
  }
94
94
 
@@ -105,18 +105,6 @@ const SHIPPED = [
105
105
  id: 'publish-runner',
106
106
  source: " {\n id: 'publish-runner',\n at: 'node_modules/@prestack/thread/dist/integrity/generators/publish.js',\n describes: 'Sends this repository\\'s packages to a registry. It derives what each package says about itself first, then builds, then refuses to send anything until the gate, the typecheck, the lint and the seal have each passed, and commits what it derived once the packages are out. The seal is checked rather than regenerated, because a release that rewrites its own seal can never fail it.',\n version: 1,\n by: 'thread publish',\n },",
107
107
  },
108
- {
109
- into: 'derivation.ts',
110
- list: 'GENERATORS',
111
- id: 'rule-noun',
112
- source: " {\n id: 'rule-noun',\n at: 'node_modules/@prestack/thread/dist/integrity/generators/rule.js',\n describes: 'Declares a rule this app holds itself to. `thread create rule` writes the row and seeds the check beside it, so a new rule goes through the same wizard as everything else rather than being written by hand.',\n version: 1,\n by: 'thread create rule',\n },",
113
- },
114
- {
115
- into: 'derivation.ts',
116
- list: 'GENERATORS',
117
- id: 'seal-generator',
118
- source: " {\n id: 'seal-generator',\n at: 'node_modules/@prestack/thread/dist/integrity/generators/seal.js',\n describes: 'Writes the seal: a hash of every built file the integrity package ships, so an installed copy can prove it is the one that went out. With --check it writes nothing and refuses a seal that no longer matches the built files.',\n version: 1,\n by: 'thread seal',\n runs: 'thread seal --check',\n },",
119
- },
120
108
  ];
121
109
  export const ATTACH = {
122
110
  attaches: SEEDED.attaches,
@@ -123,18 +123,6 @@ const SHIPPED: readonly { readonly into: string; readonly list: string; readonly
123
123
  id: 'publish-runner',
124
124
  source: " {\n id: 'publish-runner',\n at: 'node_modules/@prestack/thread/dist/integrity/generators/publish.js',\n describes: 'Sends this repository\\'s packages to a registry. It derives what each package says about itself first, then builds, then refuses to send anything until the gate, the typecheck, the lint and the seal have each passed, and commits what it derived once the packages are out. The seal is checked rather than regenerated, because a release that rewrites its own seal can never fail it.',\n version: 1,\n by: 'thread publish',\n },",
125
125
  },
126
- {
127
- into: 'derivation.ts',
128
- list: 'GENERATORS',
129
- id: 'rule-noun',
130
- source: " {\n id: 'rule-noun',\n at: 'node_modules/@prestack/thread/dist/integrity/generators/rule.js',\n describes: 'Declares a rule this app holds itself to. `thread create rule` writes the row and seeds the check beside it, so a new rule goes through the same wizard as everything else rather than being written by hand.',\n version: 1,\n by: 'thread create rule',\n },",
131
- },
132
- {
133
- into: 'derivation.ts',
134
- list: 'GENERATORS',
135
- id: 'seal-generator',
136
- source: " {\n id: 'seal-generator',\n at: 'node_modules/@prestack/thread/dist/integrity/generators/seal.js',\n describes: 'Writes the seal: a hash of every built file the integrity package ships, so an installed copy can prove it is the one that went out. With --check it writes nothing and refuses a seal that no longer matches the built files.',\n version: 1,\n by: 'thread seal',\n runs: 'thread seal --check',\n },",
137
- },
138
126
  ]
139
127
  export const ATTACH: Attaching = {
140
128
  attaches: SEEDED.attaches,
@@ -1,4 +1,4 @@
1
- import { readdirSync } from 'node:fs';
1
+ import { readdirSync } from "../core/files.js";
2
2
  import { dirname, join } from 'node:path';
3
3
  import { argv, stdout } from 'node:process';
4
4
  import { exit, invoked } from "../core/invoked.js";
@@ -1,4 +1,4 @@
1
- import { readdirSync } from 'node:fs'
1
+ import { readdirSync } from '../core/files.ts'
2
2
  import { dirname, join } from 'node:path'
3
3
  import { argv, stdout } from 'node:process'
4
4
 
@@ -1,4 +1,13 @@
1
1
  import type { Threaded } from '../core/thread.ts';
2
+ export interface Sourced {
3
+ readonly at: string;
4
+ readonly source: string;
5
+ }
6
+ export type Proof = string | {
7
+ readonly files: readonly Sourced[];
8
+ readonly at: string;
9
+ };
10
+ export declare function shown(proof: Proof): string;
2
11
  export interface Constraint extends Threaded {
3
12
  readonly version: number;
4
13
  readonly where: {
@@ -8,8 +17,8 @@ export interface Constraint extends Threaded {
8
17
  readonly bans: string;
9
18
  readonly because: string;
10
19
  readonly instead: string;
11
- readonly wrong: string;
12
- readonly right: string;
20
+ readonly wrong: Proof;
21
+ readonly right: Proof;
13
22
  readonly governs?: string;
14
23
  readonly severity?: 'forbidden' | 'warning';
15
24
  }