@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.
- package/CHANGELOG.md +193 -0
- package/dist/core/attach.js +21 -0
- package/dist/core/descend.d.ts +2 -0
- package/dist/core/descend.js +18 -3
- package/dist/core/generators/commit.js +55 -3
- package/dist/core/generators/dev.d.ts +1 -0
- package/dist/core/generators/dev.js +68 -0
- package/dist/core/rows.d.ts +5 -0
- package/dist/core/rows.js +45 -0
- package/dist/core/tree.d.ts +1 -0
- package/dist/core/tree.js +7 -1
- package/dist/derivation/generators/build.d.ts +3 -1
- package/dist/derivation/generators/build.js +103 -22
- package/dist/derivation/generators/release.js +74 -26
- package/dist/derivation/release.js +3 -3
- package/dist/integrations/cli.d.ts +3 -9
- package/dist/integrations/cli.js +96 -36
- package/dist/integrations/declared.d.ts +8 -0
- package/dist/integrations/declared.js +22 -0
- package/dist/integrations/pglite.js +13 -3
- package/dist/integrations/target.d.ts +4 -1
- package/dist/integrations/target.js +20 -6
- package/dist/integrity/attach.js +1 -5
- package/dist/integrity/generators/publish.js +2 -1
- package/dist/integrity/slopnators/sl_stale_path.js +10 -0
- package/dist/integrity/slopnators/sl_unlisted_program.js +2 -2
- package/dist/operations/access.js +3 -2
- package/dist/operations/capabilities.d.ts +2 -0
- package/dist/operations/capabilities.js +2 -0
- package/dist/operations/generators/capability.js +234 -24
- package/dist/operations/generators/compile.d.ts +21 -0
- package/dist/operations/generators/compile.js +151 -51
- package/dist/operations/generators/permits.d.ts +2 -1
- package/dist/operations/generators/permits.js +52 -47
- package/dist/operations/generators/seed.d.ts +3 -0
- package/dist/operations/generators/seed.js +25 -3
- package/dist/operations/nodes.d.ts +2 -2
- package/package.json +1 -1
- package/dist/core/actor.ts +0 -21
- package/dist/core/attach.ts +0 -613
- package/dist/core/chain.ts +0 -145
- package/dist/core/condition.ts +0 -227
- package/dist/core/descend.ts +0 -1173
- package/dist/core/errors/catalogue.ts +0 -314
- package/dist/core/errors/classes.ts +0 -51
- package/dist/core/errors/error.ts +0 -152
- package/dist/core/errors/namespaces.ts +0 -19
- package/dist/core/finding.ts +0 -37
- package/dist/core/generators/commit.ts +0 -157
- package/dist/core/init.ts +0 -222
- package/dist/core/invoked.ts +0 -52
- package/dist/core/round.ts +0 -74
- package/dist/core/rows.ts +0 -459
- package/dist/core/scope.ts +0 -20
- package/dist/core/thread.ts +0 -29
- package/dist/core/tree.ts +0 -90
- package/dist/core/types.ts +0 -351
- package/dist/derivation/attach.ts +0 -57
- package/dist/derivation/generators/build.ts +0 -371
- package/dist/derivation/generators/check.ts +0 -118
- package/dist/derivation/generators/determinism.ts +0 -145
- package/dist/derivation/generators/release.ts +0 -236
- package/dist/derivation/release.ts +0 -43
- package/dist/integrations/attach.ts +0 -187
- package/dist/integrations/cli.ts +0 -615
- package/dist/integrations/disk.ts +0 -466
- package/dist/integrations/generators/read.ts +0 -127
- package/dist/integrations/generators/vault.ts +0 -210
- package/dist/integrations/https.ts +0 -216
- package/dist/integrations/pglite.ts +0 -206
- package/dist/integrations/secret.ts +0 -54
- package/dist/integrations/target.ts +0 -656
- package/dist/integrations/vault.ts +0 -148
- package/dist/integrity/attach.ts +0 -150
- package/dist/integrity/check-threads.ts +0 -166
- package/dist/integrity/constraint.ts +0 -1246
- package/dist/integrity/generators/compiler.ts +0 -138
- package/dist/integrity/generators/gate.ts +0 -227
- package/dist/integrity/generators/issues.ts +0 -160
- package/dist/integrity/generators/publish.ts +0 -232
- package/dist/integrity/generators/trial.ts +0 -359
- package/dist/integrity/lint.ts +0 -214
- package/dist/integrity/lsp/bin.ts +0 -44
- package/dist/integrity/lsp/diagnostics.ts +0 -92
- package/dist/integrity/lsp/findings.ts +0 -63
- package/dist/integrity/lsp/lint.ts +0 -124
- package/dist/integrity/lsp/protocol.ts +0 -78
- package/dist/integrity/lsp/server.ts +0 -224
- package/dist/integrity/slopnator.ts +0 -324
- package/dist/integrity/slopnators/sl_broken_lineage.ts +0 -38
- package/dist/integrity/slopnators/sl_declared_elsewhere.ts +0 -60
- package/dist/integrity/slopnators/sl_derived_drift.ts +0 -101
- package/dist/integrity/slopnators/sl_door_in_a_node.ts +0 -250
- package/dist/integrity/slopnators/sl_hardcoded_style.ts +0 -55
- package/dist/integrity/slopnators/sl_inert_island.ts +0 -84
- package/dist/integrity/slopnators/sl_inert_slopnator.ts +0 -93
- package/dist/integrity/slopnators/sl_missing_row.ts +0 -140
- package/dist/integrity/slopnators/sl_no_barrel.ts +0 -48
- package/dist/integrity/slopnators/sl_no_child_process.ts +0 -100
- package/dist/integrity/slopnators/sl_no_comment.ts +0 -43
- package/dist/integrity/slopnators/sl_no_dispatch_bypass.ts +0 -276
- package/dist/integrity/slopnators/sl_no_import_cycle.ts +0 -66
- package/dist/integrity/slopnators/sl_no_such_command.ts +0 -81
- package/dist/integrity/slopnators/sl_only_takes_a_literal.ts +0 -63
- package/dist/integrity/slopnators/sl_outside_an_operation.ts +0 -25
- package/dist/integrity/slopnators/sl_screen_holds_only_declared.ts +0 -70
- package/dist/integrity/slopnators/sl_secret_literal.ts +0 -68
- package/dist/integrity/slopnators/sl_stale_path.ts +0 -178
- package/dist/integrity/slopnators/sl_twice_meant.ts +0 -57
- package/dist/integrity/slopnators/sl_twice_parented.ts +0 -82
- package/dist/integrity/slopnators/sl_undeclared_crossing.ts +0 -481
- package/dist/integrity/slopnators/sl_undeclared_destination.ts +0 -113
- package/dist/integrity/slopnators/sl_undeclared_element.ts +0 -44
- package/dist/integrity/slopnators/sl_undeclared_list.ts +0 -358
- package/dist/integrity/slopnators/sl_undeclared_node.ts +0 -75
- package/dist/integrity/slopnators/sl_undeclared_operation.ts +0 -257
- package/dist/integrity/slopnators/sl_undeclared_variant.ts +0 -152
- package/dist/integrity/slopnators/sl_undeclared_webhook.ts +0 -108
- package/dist/integrity/slopnators/sl_underived_route.ts +0 -72
- package/dist/integrity/slopnators/sl_undescribed.ts +0 -65
- package/dist/integrity/slopnators/sl_ungoverned_island.ts +0 -60
- package/dist/integrity/slopnators/sl_unlisted_program.ts +0 -46
- package/dist/integrity/slopnators/sl_unnamed_island.ts +0 -41
- package/dist/integrity/slopnators/sl_unpaired_member.ts +0 -139
- package/dist/integrity/slopnators/sl_unpaired_slopnator.ts +0 -71
- package/dist/integrity/slopnators/sl_unprefixed_member.ts +0 -110
- package/dist/integrity/slopnators/sl_unthreaded.ts +0 -421
- package/dist/integrity/slopnators/sl_untranslated_key.ts +0 -140
- package/dist/integrity/slopnators/sl_unvaulted_secret.ts +0 -132
- package/dist/integrity/slopnators/sl_unversioned.ts +0 -52
- package/dist/integrity/sweep.ts +0 -395
- package/dist/knowledge/attach.ts +0 -327
- package/dist/knowledge/generators/docsgen.ts +0 -186
- package/dist/knowledge/generators/glossary.ts +0 -73
- package/dist/knowledge/glossary.ts +0 -6
- package/dist/operations/access.ts +0 -131
- package/dist/operations/attach.ts +0 -408
- package/dist/operations/capabilities.ts +0 -88
- package/dist/operations/dispatch.ts +0 -294
- package/dist/operations/error-results.ts +0 -31
- package/dist/operations/generators/capability.ts +0 -1054
- package/dist/operations/generators/compile.ts +0 -701
- package/dist/operations/generators/permits.ts +0 -224
- package/dist/operations/generators/seed.ts +0 -359
- package/dist/operations/generators/trial.ts +0 -666
- package/dist/operations/nodes.ts +0 -53
- package/dist/operations/operations.ts +0 -91
- 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
|
-
}
|
package/dist/core/invoked.ts
DELETED
|
@@ -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
|
-
}
|
package/dist/core/round.ts
DELETED
|
@@ -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
|