@prestack/thread 0.1.20 → 0.1.22

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 (148) hide show
  1. package/CHANGELOG.md +193 -0
  2. package/dist/core/attach.js +21 -0
  3. package/dist/core/descend.d.ts +2 -0
  4. package/dist/core/descend.js +18 -3
  5. package/dist/core/generators/commit.js +55 -3
  6. package/dist/core/generators/dev.d.ts +1 -0
  7. package/dist/core/generators/dev.js +68 -0
  8. package/dist/core/rows.d.ts +5 -0
  9. package/dist/core/rows.js +45 -0
  10. package/dist/core/tree.d.ts +1 -0
  11. package/dist/core/tree.js +7 -1
  12. package/dist/derivation/generators/build.d.ts +3 -1
  13. package/dist/derivation/generators/build.js +103 -22
  14. package/dist/derivation/generators/release.js +74 -26
  15. package/dist/derivation/release.js +3 -3
  16. package/dist/integrations/cli.d.ts +3 -9
  17. package/dist/integrations/cli.js +96 -36
  18. package/dist/integrations/declared.d.ts +8 -0
  19. package/dist/integrations/declared.js +22 -0
  20. package/dist/integrations/pglite.js +13 -3
  21. package/dist/integrations/target.d.ts +4 -1
  22. package/dist/integrations/target.js +20 -6
  23. package/dist/integrity/attach.js +1 -5
  24. package/dist/integrity/generators/publish.js +2 -1
  25. package/dist/integrity/slopnators/sl_stale_path.js +10 -0
  26. package/dist/integrity/slopnators/sl_unlisted_program.js +2 -2
  27. package/dist/operations/access.js +3 -2
  28. package/dist/operations/capabilities.d.ts +2 -0
  29. package/dist/operations/capabilities.js +2 -0
  30. package/dist/operations/generators/capability.js +234 -24
  31. package/dist/operations/generators/compile.d.ts +21 -0
  32. package/dist/operations/generators/compile.js +151 -51
  33. package/dist/operations/generators/permits.d.ts +2 -1
  34. package/dist/operations/generators/permits.js +52 -47
  35. package/dist/operations/generators/seed.d.ts +3 -0
  36. package/dist/operations/generators/seed.js +25 -3
  37. package/dist/operations/nodes.d.ts +2 -2
  38. package/package.json +1 -1
  39. package/dist/core/actor.ts +0 -21
  40. package/dist/core/attach.ts +0 -613
  41. package/dist/core/chain.ts +0 -145
  42. package/dist/core/condition.ts +0 -227
  43. package/dist/core/descend.ts +0 -1173
  44. package/dist/core/errors/catalogue.ts +0 -314
  45. package/dist/core/errors/classes.ts +0 -51
  46. package/dist/core/errors/error.ts +0 -152
  47. package/dist/core/errors/namespaces.ts +0 -19
  48. package/dist/core/finding.ts +0 -37
  49. package/dist/core/generators/commit.ts +0 -157
  50. package/dist/core/init.ts +0 -222
  51. package/dist/core/invoked.ts +0 -52
  52. package/dist/core/round.ts +0 -74
  53. package/dist/core/rows.ts +0 -459
  54. package/dist/core/scope.ts +0 -20
  55. package/dist/core/thread.ts +0 -29
  56. package/dist/core/tree.ts +0 -90
  57. package/dist/core/types.ts +0 -351
  58. package/dist/derivation/attach.ts +0 -57
  59. package/dist/derivation/generators/build.ts +0 -371
  60. package/dist/derivation/generators/check.ts +0 -118
  61. package/dist/derivation/generators/determinism.ts +0 -145
  62. package/dist/derivation/generators/release.ts +0 -236
  63. package/dist/derivation/release.ts +0 -43
  64. package/dist/integrations/attach.ts +0 -187
  65. package/dist/integrations/cli.ts +0 -615
  66. package/dist/integrations/disk.ts +0 -466
  67. package/dist/integrations/generators/read.ts +0 -127
  68. package/dist/integrations/generators/vault.ts +0 -210
  69. package/dist/integrations/https.ts +0 -216
  70. package/dist/integrations/pglite.ts +0 -206
  71. package/dist/integrations/secret.ts +0 -54
  72. package/dist/integrations/target.ts +0 -656
  73. package/dist/integrations/vault.ts +0 -148
  74. package/dist/integrity/attach.ts +0 -150
  75. package/dist/integrity/check-threads.ts +0 -166
  76. package/dist/integrity/constraint.ts +0 -1246
  77. package/dist/integrity/generators/compiler.ts +0 -138
  78. package/dist/integrity/generators/gate.ts +0 -227
  79. package/dist/integrity/generators/issues.ts +0 -160
  80. package/dist/integrity/generators/publish.ts +0 -232
  81. package/dist/integrity/generators/trial.ts +0 -359
  82. package/dist/integrity/lint.ts +0 -214
  83. package/dist/integrity/lsp/bin.ts +0 -44
  84. package/dist/integrity/lsp/diagnostics.ts +0 -92
  85. package/dist/integrity/lsp/findings.ts +0 -63
  86. package/dist/integrity/lsp/lint.ts +0 -124
  87. package/dist/integrity/lsp/protocol.ts +0 -78
  88. package/dist/integrity/lsp/server.ts +0 -224
  89. package/dist/integrity/slopnator.ts +0 -324
  90. package/dist/integrity/slopnators/sl_broken_lineage.ts +0 -38
  91. package/dist/integrity/slopnators/sl_declared_elsewhere.ts +0 -60
  92. package/dist/integrity/slopnators/sl_derived_drift.ts +0 -101
  93. package/dist/integrity/slopnators/sl_door_in_a_node.ts +0 -250
  94. package/dist/integrity/slopnators/sl_hardcoded_style.ts +0 -55
  95. package/dist/integrity/slopnators/sl_inert_island.ts +0 -84
  96. package/dist/integrity/slopnators/sl_inert_slopnator.ts +0 -93
  97. package/dist/integrity/slopnators/sl_missing_row.ts +0 -140
  98. package/dist/integrity/slopnators/sl_no_barrel.ts +0 -48
  99. package/dist/integrity/slopnators/sl_no_child_process.ts +0 -100
  100. package/dist/integrity/slopnators/sl_no_comment.ts +0 -43
  101. package/dist/integrity/slopnators/sl_no_dispatch_bypass.ts +0 -276
  102. package/dist/integrity/slopnators/sl_no_import_cycle.ts +0 -66
  103. package/dist/integrity/slopnators/sl_no_such_command.ts +0 -81
  104. package/dist/integrity/slopnators/sl_only_takes_a_literal.ts +0 -63
  105. package/dist/integrity/slopnators/sl_outside_an_operation.ts +0 -25
  106. package/dist/integrity/slopnators/sl_screen_holds_only_declared.ts +0 -70
  107. package/dist/integrity/slopnators/sl_secret_literal.ts +0 -68
  108. package/dist/integrity/slopnators/sl_stale_path.ts +0 -178
  109. package/dist/integrity/slopnators/sl_twice_meant.ts +0 -57
  110. package/dist/integrity/slopnators/sl_twice_parented.ts +0 -82
  111. package/dist/integrity/slopnators/sl_undeclared_crossing.ts +0 -481
  112. package/dist/integrity/slopnators/sl_undeclared_destination.ts +0 -113
  113. package/dist/integrity/slopnators/sl_undeclared_element.ts +0 -44
  114. package/dist/integrity/slopnators/sl_undeclared_list.ts +0 -358
  115. package/dist/integrity/slopnators/sl_undeclared_node.ts +0 -75
  116. package/dist/integrity/slopnators/sl_undeclared_operation.ts +0 -257
  117. package/dist/integrity/slopnators/sl_undeclared_variant.ts +0 -152
  118. package/dist/integrity/slopnators/sl_undeclared_webhook.ts +0 -108
  119. package/dist/integrity/slopnators/sl_underived_route.ts +0 -72
  120. package/dist/integrity/slopnators/sl_undescribed.ts +0 -65
  121. package/dist/integrity/slopnators/sl_ungoverned_island.ts +0 -60
  122. package/dist/integrity/slopnators/sl_unlisted_program.ts +0 -46
  123. package/dist/integrity/slopnators/sl_unnamed_island.ts +0 -41
  124. package/dist/integrity/slopnators/sl_unpaired_member.ts +0 -139
  125. package/dist/integrity/slopnators/sl_unpaired_slopnator.ts +0 -71
  126. package/dist/integrity/slopnators/sl_unprefixed_member.ts +0 -110
  127. package/dist/integrity/slopnators/sl_unthreaded.ts +0 -421
  128. package/dist/integrity/slopnators/sl_untranslated_key.ts +0 -140
  129. package/dist/integrity/slopnators/sl_unvaulted_secret.ts +0 -132
  130. package/dist/integrity/slopnators/sl_unversioned.ts +0 -52
  131. package/dist/integrity/sweep.ts +0 -395
  132. package/dist/knowledge/attach.ts +0 -327
  133. package/dist/knowledge/generators/docsgen.ts +0 -186
  134. package/dist/knowledge/generators/glossary.ts +0 -73
  135. package/dist/knowledge/glossary.ts +0 -6
  136. package/dist/operations/access.ts +0 -131
  137. package/dist/operations/attach.ts +0 -408
  138. package/dist/operations/capabilities.ts +0 -88
  139. package/dist/operations/dispatch.ts +0 -294
  140. package/dist/operations/error-results.ts +0 -31
  141. package/dist/operations/generators/capability.ts +0 -1054
  142. package/dist/operations/generators/compile.ts +0 -701
  143. package/dist/operations/generators/permits.ts +0 -224
  144. package/dist/operations/generators/seed.ts +0 -359
  145. package/dist/operations/generators/trial.ts +0 -666
  146. package/dist/operations/nodes.ts +0 -53
  147. package/dist/operations/operations.ts +0 -91
  148. package/dist/operations/result.ts +0 -28
@@ -1,157 +0,0 @@
1
- import { createHash } from 'node:crypto'
2
- import { deflateSync, inflateSync } from 'node:zlib'
3
- import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs'
4
- import { join, relative, sep } from 'node:path'
5
- import { argv, cwd, stdout, stderr } from 'node:process'
6
-
7
- const dir = cwd()
8
- const message = (argv[2] ?? 'thread').slice(0, 400)
9
- const NL = String.fromCharCode(10)
10
- const NUL = String.fromCharCode(0)
11
- const SLASH = String.fromCharCode(47)
12
- const matches = (pat: string, name: string): boolean => {
13
- const parts = pat.split('*')
14
- if (parts.length === 1) return name === pat
15
- const first = parts[0]
16
- if (!name.startsWith(first)) return false
17
- let at = first.length
18
- for (let k = 1; k < parts.length - 1; k += 1) {
19
- const found = name.indexOf(parts[k], at)
20
- if (found === -1) return false
21
- at = found + parts[k].length
22
- }
23
- const last = parts[parts.length - 1]
24
- return name.length - last.length >= at && name.endsWith(last)
25
- }
26
-
27
- interface Ignore {
28
- readonly negate: boolean
29
- readonly dirOnly: boolean
30
- readonly anchored: boolean
31
- readonly pat: string
32
- }
33
-
34
- let text = ''
35
- try {
36
- text = readFileSync(join(dir, '.gitignore'), 'utf8')
37
- } catch {
38
- text = ''
39
- }
40
- const patterns: Ignore[] = []
41
- for (const raw of text.split(NL)) {
42
- let line = raw.trim()
43
- if (line === '' || line.startsWith('#')) continue
44
- const negate = line.startsWith('!')
45
- if (negate) line = line.slice(1)
46
- const dirOnly = line.endsWith(SLASH)
47
- if (dirOnly) line = line.slice(0, -1)
48
- let anchored = line.startsWith(SLASH)
49
- if (anchored) line = line.slice(1)
50
- if (line.includes(SLASH)) anchored = true
51
- if (line !== '') patterns.push({ negate, dirOnly, anchored, pat: line })
52
- }
53
-
54
- const ignored = (rel: string, name: string, isDir: boolean): boolean => {
55
- if (name === '.git') return true
56
- let hit = false
57
- for (const one of patterns) {
58
- if (one.dirOnly && !isDir) continue
59
- if (matches(one.pat, one.anchored ? rel : name)) hit = !one.negate
60
- }
61
- return hit
62
- }
63
- const BRANCH = ['refs', 'heads', 'main'].join(SLASH)
64
-
65
- interface Entry {
66
- readonly mode: string
67
- readonly name: string
68
- readonly sha: string
69
- }
70
-
71
- const store = (kind: string, body: Buffer): string => {
72
- const whole = Buffer.concat([Buffer.from(kind + ' ' + String(body.length) + NUL), body])
73
- const sha = createHash('sha1').update(whole).digest('hex')
74
- const at = join(dir, '.git', 'objects', sha.slice(0, 2), sha.slice(2))
75
- if (!existsSync(at)) {
76
- mkdirSync(join(dir, '.git', 'objects', sha.slice(0, 2)), { recursive: true })
77
- writeFileSync(at, deflateSync(whole))
78
- }
79
- return sha
80
- }
81
-
82
- const tree = (at: string): string => {
83
- const entries: Entry[] = []
84
- for (const name of readdirSync(at)) {
85
- const full = join(at, name)
86
- const stat = statSync(full)
87
- const rel = relative(dir, full).split(sep).join(SLASH)
88
- if (ignored(rel, name, stat.isDirectory())) continue
89
- if (stat.isDirectory()) {
90
- const sub = tree(full)
91
- if (sub !== '') entries.push({ mode: '40000', name, sha: sub })
92
- } else if (stat.isFile()) {
93
- const sha = store('blob', readFileSync(full))
94
- entries.push({ mode: (stat.mode & 0o111) !== 0 ? '100755' : '100644', name, sha })
95
- }
96
- }
97
- if (entries.length === 0) return ''
98
- const key = (one: Entry): string => one.name + (one.mode === '40000' ? SLASH : '')
99
- entries.sort((one, two) => (key(one) < key(two) ? -1 : key(one) > key(two) ? 1 : 0))
100
- const body = Buffer.concat(
101
- entries.map((one) => Buffer.concat([Buffer.from(one.mode + ' ' + one.name + NUL), Buffer.from(one.sha, 'hex')])),
102
- )
103
- return store('tree', body)
104
- }
105
-
106
- const treeOf = (sha: string): string => {
107
- const at = join(dir, '.git', 'objects', sha.slice(0, 2), sha.slice(2))
108
- const raw = inflateSync(readFileSync(at))
109
- const body = raw.slice(raw.indexOf(0) + 1).toString('utf8')
110
- const first = body.split(NL)[0] ?? ''
111
- return first.startsWith('tree ') ? first.slice(5) : ''
112
- }
113
-
114
- const record = (): void => {
115
- const gitDir = join(dir, '.git')
116
- if (!existsSync(join(gitDir, 'HEAD'))) {
117
- mkdirSync(join(gitDir, 'objects'), { recursive: true })
118
- mkdirSync(join(gitDir, 'refs', 'heads'), { recursive: true })
119
- writeFileSync(join(gitDir, 'HEAD'), 'ref: ' + BRANCH + NL)
120
- }
121
- const head = readFileSync(join(gitDir, 'HEAD'), 'utf8').trim()
122
- const ref = head.startsWith('ref: ') ? head.slice(5) : BRANCH
123
- const refAt = join(gitDir, ref)
124
- const parent = existsSync(refAt) ? readFileSync(refAt, 'utf8').trim() : ''
125
-
126
- const root = tree(dir)
127
- if (root === '') {
128
- stdout.write('commit: nothing to commit' + NL)
129
- return
130
- }
131
- if (parent !== '' && treeOf(parent) === root) {
132
- stdout.write('commit: nothing changed' + NL)
133
- return
134
- }
135
-
136
- const when = String(Math.floor(Date.now() / 1000)) + ' +0000'
137
- const who = 'thread <thread@prestack> ' + when
138
- const body = [
139
- 'tree ' + root,
140
- ...(parent === '' ? [] : ['parent ' + parent]),
141
- 'author ' + who,
142
- 'committer ' + who,
143
- '',
144
- message,
145
- '',
146
- ].join(NL)
147
- const sha = store('commit', Buffer.from(body))
148
- writeFileSync(refAt, sha + NL)
149
- stdout.write('commit: ' + sha.slice(0, 8) + ' on ' + (ref.split(SLASH).pop() ?? 'main') + NL)
150
- }
151
-
152
- try {
153
- record()
154
- } catch (thrown) {
155
- stderr.write('commit: ' + (thrown instanceof Error ? thrown.message : String(thrown)) + NL)
156
- process.exit(1)
157
- }
package/dist/core/init.ts DELETED
@@ -1,222 +0,0 @@
1
- import { LOCKFILES, installing, manager } from '../integrations/cli.ts'
2
- import { existsSync, readFileSync, writeFileSync } from '../integrations/disk.ts'
3
- import { createRequire } from 'node:module'
4
- import { join, relative, resolve } from 'node:path'
5
- import { fileURLToPath } from 'node:url'
6
-
7
- import { quoted } from './rows.ts'
8
- import { NAMED } from './scope.ts'
9
-
10
-
11
- export const TREE = '_threads'
12
- export const ROOT = 'thread.ts'
13
-
14
- export const SHAPED = `${NAMED}/core/thread`
15
-
16
- export class AlreadyThreadedError extends Error {
17
- readonly at: string
18
- constructor(at: string) {
19
- super(
20
-
21
- `${at} already exists, so this repository already has a root. A tree has one root and it is written once. ` +
22
- 'Declare something under it with `thread create` — run it bare to see what this tree makes — or take on ' +
23
- 'a package with `thread attach`, which brings its rows with it. Neither is written by hand.',
24
- )
25
- this.name = 'AlreadyThreadedError'
26
- this.at = at
27
- }
28
- }
29
-
30
- export const COMPILER = 'tsconfig.json'
31
-
32
- export const MANIFEST = 'package.json'
33
-
34
- const BUILT = '_gener' + 'ated/packages/core'
35
-
36
- const MODULE = 'module'
37
-
38
- const NPM = 'npm'
39
-
40
- const LATEST = 'latest'
41
-
42
- export const REGISTRY = '.npm' + 'rc'
43
-
44
- export const IGNORED = '.git' + 'ignore'
45
-
46
- export function ignored(): string {
47
- return [
48
- 'node_' + 'modules/',
49
- '.next/',
50
- 'dist/',
51
-
52
- '*.tsbuildinfo',
53
-
54
- 'next-env.d.ts',
55
- '.DS_Store',
56
- '',
57
- ].join('\n')
58
- }
59
-
60
- export function compiler(): string {
61
- return `${JSON.stringify(
62
- {
63
- compilerOptions: {
64
- target: 'ES2022',
65
- module: 'ESNext',
66
- moduleResolution: 'bundler',
67
- strict: true,
68
-
69
- allowImportingTsExtensions: true,
70
-
71
- skipLibCheck: true,
72
-
73
- types: ['node'],
74
- jsx: 'react-jsx',
75
- noEmit: true,
76
- },
77
- },
78
- null,
79
- 2,
80
- )}\n`
81
- }
82
-
83
- function owned(into: string): readonly { readonly id: string; readonly at: string; readonly describes: string; readonly runs?: string }[] {
84
- const held = Object.keys(LOCKFILES).filter((one) => existsSync(join(into, one)))
85
- return [
86
- {
87
- id: 'manifest',
88
- at: 'package.json',
89
- describes:
90
- 'What this app is made of and what may be run against it — the packages it installs and the commands that build it, serve it and refuse it.',
91
- },
92
-
93
- ...(existsSync(join(into, REGISTRY))
94
- ? [
95
- {
96
- id: 'registry',
97
- at: REGISTRY,
98
- describes:
99
- 'Which registry this app’s packages come from, and any credential scoped to it. Declared beside the lockfile because an install is not reproducible without it: the lockfile says which versions answered, and this says who answered.',
100
- },
101
- ]
102
- : []),
103
- {
104
- id: 'ignored',
105
- at: IGNORED,
106
- describes:
107
- 'What is built rather than written, so the checks that read this repository can tell the two apart. Every surface here asks which files are tracked, and without it an app that has been served once answers with its whole build cache.',
108
- },
109
- ...held.map((one) => ({
110
- id: 'lockfile',
111
- at: one,
112
- describes:
113
- 'The exact version of every package this app resolved to, so an install here and an install anywhere else are the same install.',
114
- })),
115
- ]
116
- }
117
-
118
- export function root(into: string): string {
119
- const rows = owned(into).flatMap((one) => [
120
- ' {',
121
- ` id: ${quoted(one.id)},`,
122
- ` at: ${quoted(one.at)},`,
123
- ` describes: ${quoted(one.describes)},`,
124
- ' version: 1,',
125
- ...(one.runs === undefined ? [] : [` runs: ${quoted(one.runs)},`]),
126
- ' },',
127
- ])
128
- return [
129
- `import type { Threaded } from '${SHAPED}'`,
130
- '',
131
- 'export const THREAD: Threaded = {',
132
- " id: 'thread',",
133
- ` at: '${TREE}/${ROOT}',`,
134
- " describes: 'The framework that declares what must exist, forbids what is not declared, and derives what can be derived.',",
135
- ' version: 1,',
136
- ' declares: [',
137
- ...rows,
138
- ' ],',
139
- '}',
140
- '',
141
- ].join('\n')
142
- }
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
-
175
- export function init(into: string): readonly string[] {
176
- const dir = resolve(into, TREE)
177
- const at = join(dir, ROOT)
178
- if (existsSync(at)) throw new AlreadyThreadedError(relative(into, at))
179
- const written: string[] = []
180
-
181
- const held = join(into, COMPILER)
182
- if (!existsSync(held)) {
183
- writeFileSync(held, compiler(), 'utf8')
184
- written.push(COMPILER)
185
- }
186
-
187
- const manifest = join(into, MANIFEST)
188
- if (!existsSync(manifest)) {
189
- const called = (into.split('/').filter(Boolean).pop() ?? 'app').toLowerCase().replace(/[^a-z0-9-]+/g, '-')
190
- writeFileSync(manifest, JSON.stringify({ name: called, version: '0.0.0', type: MODULE }, null, 2) + '\n', 'utf8')
191
- written.push(MANIFEST)
192
- }
193
- const stated = JSON.parse(readFileSync(manifest, 'utf8')) as { type?: string }
194
- if (stated.type !== MODULE) {
195
- writeFileSync(manifest, `${JSON.stringify({ ...stated, type: MODULE }, null, 2)}\n`, 'utf8')
196
- written.push(MANIFEST)
197
- }
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
-
209
- const ignore = join(into, IGNORED)
210
- if (!existsSync(ignore)) {
211
- writeFileSync(ignore, ignored(), 'utf8')
212
- written.push(IGNORED)
213
- }
214
-
215
- installing(into)
216
-
217
- for (const [name, text] of [[ROOT, root(into)]] as const) {
218
- writeFileSync(join(dir, name), text, 'utf8')
219
- written.push(relative(into, join(dir, name)))
220
- }
221
- return written
222
- }
@@ -1,52 +0,0 @@
1
- import { dirname, join } from 'node:path'
2
- import { argv, exit as ending } from 'node:process'
3
- import { fileURLToPath } from 'node:url'
4
-
5
- import { realpathSync } from '../integrations/disk.ts'
6
-
7
- export function invoked(url: string): boolean {
8
- const named = argv[1]
9
- if (named === undefined) return false
10
- try {
11
- const held = new URL(url)
12
- held.search = ''
13
- held.hash = ''
14
- return realpathSync(named) === realpathSync(fileURLToPath(held))
15
- } catch {
16
- return false
17
- }
18
- }
19
-
20
- export const SOURCE = import.meta.url.endsWith('.ts')
21
-
22
- export const BESIDE = (name: string): string => `${name}${SOURCE ? '.ts' : '.js'}`
23
-
24
- export const BUILT = (at: string): string => (SOURCE ? at : at.replace(/\.tsx?$/, '.js'))
25
-
26
- export const LOADER: readonly string[] = SOURCE ? ['--import', 'tsx'] : []
27
-
28
- export const CLI: readonly string[] = [
29
- ...LOADER,
30
- join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'cli', BESIDE('cli')),
31
- ]
32
-
33
- export const REFUSED = Symbol.for('thread.refused')
34
-
35
- let sharing = false
36
-
37
- export const shared = (on: boolean): boolean => {
38
- const was = sharing
39
- sharing = on
40
- return was
41
- }
42
-
43
- export function exit(code?: number): never {
44
- if (!sharing) ending(code)
45
- throw Object.assign(new Error(`refused with ${String(code ?? 0)}`), { [REFUSED]: code ?? 0 })
46
- }
47
-
48
- export const refusal = (thrown: unknown): number | undefined => {
49
- if (typeof thrown !== 'object' || thrown === null) return undefined
50
- const held = (thrown as Record<symbol, unknown>)[REFUSED]
51
- return typeof held === 'number' ? held : undefined
52
- }
@@ -1,74 +0,0 @@
1
- import { resolve } from 'node:path'
2
- import { argv, exitCode, stderr, stdout } from 'node:process'
3
- import { pathToFileURL } from 'node:url'
4
-
5
- import { generators, RAN, REFUSED_BY } from './chain.ts'
6
- import { attached, here } from '../integrations/disk.ts'
7
- import { forget } from './descend.ts'
8
- import { refusal, shared } from './invoked.ts'
9
- import { findTree } from './tree.ts'
10
-
11
- let spun = 0
12
-
13
- const words = (command: string): readonly string[] => command.trim().split(/\s+/).slice(1)
14
-
15
- shared(true)
16
-
17
- const tree = findTree()
18
- const rows = await generators(tree)
19
-
20
- let stale = true
21
-
22
- for (const command of argv.slice(2).filter((one) => one !== '')) {
23
- const said = words(command)
24
- const name = said[0]
25
- if (name === undefined) continue
26
-
27
- const held = rows.find((one) => one.by === `thread ${name}`)
28
- if (held?.at === undefined) {
29
- stdout.write(`round: no command named "${name}", so \`${command}\` was not run\n`)
30
- stdout.write(`${REFUSED_BY} ${command}\n`)
31
- continue
32
- }
33
-
34
- const found = resolve(tree.at, held.at)
35
-
36
- if (stale) forget()
37
-
38
- argv.length = 1
39
- argv.push(found, ...said.slice(1))
40
-
41
- spun += 1
42
-
43
- process.exitCode = 0
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 {
56
- try {
57
- await import(`${pathToFileURL(found).href}?round=${String(spun)}`)
58
- ok = exitCode === undefined || exitCode === 0
59
- } catch (thrown) {
60
- const code = refusal(thrown)
61
- if (code === undefined) {
62
- ok = false
63
- stdout.write(`round: \`${command}\` threw: ${thrown instanceof Error ? thrown.message : String(thrown)}\n`)
64
- } else ok = code === 0
65
- }
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')
72
- }
73
-
74
- process.exitCode = 0