@prestack/thread 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +563 -0
- package/dist/core/actor.d.ts +1 -1
- package/dist/core/actor.js +5 -4
- package/dist/core/actor.ts +5 -4
- package/dist/core/attach.d.ts +0 -7
- package/dist/core/attach.js +38 -67
- package/dist/core/attach.ts +34 -80
- package/dist/core/chain.js +13 -17
- package/dist/core/chain.ts +11 -15
- package/dist/core/condition.d.ts +4 -4
- package/dist/core/condition.js +2 -2
- package/dist/core/descend.d.ts +4 -2
- package/dist/core/descend.js +91 -23
- package/dist/core/descend.ts +90 -21
- package/dist/core/errors/catalogue.d.ts +52 -0
- package/dist/{operations/errors/errors.js → core/errors/catalogue.js} +1 -1
- package/dist/{operations/errors/errors.ts → core/errors/catalogue.ts} +1 -1
- package/dist/{operations/errors/catalog.d.ts → core/errors/error.d.ts} +2 -3
- package/dist/{operations/errors/catalog.js → core/errors/error.js} +1 -16
- package/dist/{operations/errors/catalog.ts → core/errors/error.ts} +3 -19
- package/dist/core/errors/namespaces.d.ts +3 -0
- package/dist/core/errors/namespaces.js +15 -0
- package/dist/core/errors/namespaces.ts +19 -0
- package/dist/core/finding.js +2 -2
- package/dist/core/finding.ts +1 -2
- package/dist/core/init.d.ts +1 -1
- package/dist/core/init.js +51 -5
- package/dist/core/init.ts +58 -5
- package/dist/core/invoked.d.ts +1 -1
- package/dist/core/invoked.js +3 -1
- package/dist/core/invoked.ts +5 -2
- package/dist/core/round.js +36 -22
- package/dist/core/round.ts +26 -9
- package/dist/core/rows.d.ts +4 -0
- package/dist/core/rows.js +31 -2
- package/dist/core/rows.ts +33 -1
- package/dist/core/scope.d.ts +1 -0
- package/dist/core/scope.js +1 -0
- package/dist/core/scope.ts +2 -0
- package/dist/core/thread.d.ts +3 -3
- package/dist/core/tree.d.ts +4 -1
- package/dist/core/tree.js +26 -6
- package/dist/core/tree.ts +29 -6
- package/dist/core/types.d.ts +3 -3
- package/dist/core/types.js +3 -1
- package/dist/core/types.ts +2 -1
- package/dist/derivation/attach.js +3 -2
- package/dist/derivation/attach.ts +2 -1
- package/dist/derivation/generators/build.js +6 -6
- package/dist/derivation/generators/build.ts +1 -1
- package/dist/derivation/generators/check.js +1 -1
- package/dist/derivation/generators/determinism.js +1 -1
- package/dist/derivation/generators/release.js +60 -47
- package/dist/derivation/generators/release.ts +66 -43
- package/dist/derivation/release.d.ts +7 -3
- package/dist/derivation/release.js +14 -1
- package/dist/derivation/release.ts +22 -2
- package/dist/integrations/attach.d.ts +4 -0
- package/dist/integrations/attach.js +37 -56
- package/dist/integrations/attach.ts +54 -60
- package/dist/integrations/cli.d.ts +37 -0
- package/dist/integrations/cli.js +440 -0
- package/dist/integrations/cli.ts +543 -0
- package/dist/{core/files.d.ts → integrations/disk.d.ts} +16 -24
- package/dist/integrations/disk.js +435 -0
- package/dist/integrations/disk.ts +465 -0
- package/dist/integrations/generators/read.js +6 -6
- package/dist/integrations/generators/read.ts +4 -4
- package/dist/integrations/generators/vault.js +10 -11
- package/dist/integrations/generators/vault.ts +4 -5
- package/dist/{operations/http.d.ts → integrations/https.d.ts} +10 -6
- package/dist/integrations/https.js +170 -0
- package/dist/integrations/https.ts +216 -0
- package/dist/integrations/pglite.d.ts +26 -0
- package/dist/integrations/pglite.js +143 -0
- package/dist/integrations/pglite.ts +206 -0
- package/dist/integrations/secret.d.ts +8 -2
- package/dist/integrations/secret.js +3 -5
- package/dist/integrations/secret.ts +10 -6
- package/dist/integrations/target.d.ts +155 -14
- package/dist/integrations/target.js +171 -50
- package/dist/integrations/target.ts +377 -61
- package/dist/integrations/vault.d.ts +1 -0
- package/dist/integrations/vault.js +20 -5
- package/dist/integrations/vault.ts +17 -5
- package/dist/integrity/attach.js +8 -77
- package/dist/integrity/attach.ts +7 -76
- package/dist/integrity/check-threads.js +5 -5
- package/dist/integrity/check-threads.ts +2 -2
- package/dist/integrity/constraint.d.ts +0 -1
- package/dist/integrity/constraint.js +267 -366
- package/dist/integrity/constraint.ts +267 -375
- package/dist/integrity/generators/compiler.js +14 -17
- package/dist/integrity/generators/compiler.ts +10 -15
- package/dist/integrity/generators/gate.js +15 -15
- package/dist/integrity/generators/gate.ts +10 -10
- package/dist/integrity/generators/issues.js +7 -7
- package/dist/integrity/generators/publish.js +39 -57
- package/dist/integrity/generators/publish.ts +44 -55
- package/dist/integrity/generators/trial.d.ts +3 -3
- package/dist/integrity/generators/trial.js +133 -165
- package/dist/integrity/generators/trial.ts +145 -169
- package/dist/integrity/lint.js +9 -13
- package/dist/integrity/lint.ts +7 -10
- package/dist/integrity/lsp/bin.js +5 -4
- package/dist/integrity/lsp/bin.ts +3 -1
- package/dist/integrity/lsp/diagnostics.js +3 -3
- package/dist/integrity/lsp/diagnostics.ts +1 -1
- package/dist/integrity/lsp/lint.js +19 -30
- package/dist/integrity/lsp/lint.ts +16 -32
- package/dist/integrity/lsp/server.js +3 -3
- package/dist/integrity/slopnator.d.ts +3 -13
- package/dist/integrity/slopnator.js +59 -38
- package/dist/integrity/slopnator.ts +54 -38
- package/dist/integrity/slopnators/sl_broken_lineage.js +2 -2
- package/dist/integrity/slopnators/sl_declared_elsewhere.js +1 -1
- package/dist/integrity/slopnators/sl_derived_drift.js +4 -4
- package/dist/integrity/slopnators/sl_derived_drift.ts +1 -1
- package/dist/integrity/slopnators/sl_door_in_a_node.js +220 -0
- package/dist/integrity/slopnators/sl_door_in_a_node.ts +250 -0
- package/dist/integrity/slopnators/sl_inert_island.js +10 -8
- package/dist/integrity/slopnators/sl_inert_island.ts +8 -6
- package/dist/integrity/slopnators/sl_missing_row.js +6 -51
- package/dist/integrity/slopnators/sl_missing_row.ts +4 -50
- package/dist/integrity/slopnators/sl_no_barrel.js +1 -1
- package/dist/integrity/slopnators/sl_no_child_process.js +36 -18
- package/dist/integrity/slopnators/sl_no_child_process.ts +44 -18
- package/dist/integrity/slopnators/sl_no_dispatch_bypass.js +80 -149
- package/dist/integrity/slopnators/sl_no_dispatch_bypass.ts +95 -147
- package/dist/integrity/slopnators/sl_no_import_cycle.js +15 -4
- package/dist/integrity/slopnators/sl_no_import_cycle.ts +20 -4
- package/dist/integrity/slopnators/sl_no_such_command.js +2 -2
- package/dist/integrity/slopnators/sl_no_such_command.ts +1 -1
- package/dist/integrity/slopnators/sl_outside_an_operation.js +20 -0
- package/dist/integrity/slopnators/sl_outside_an_operation.ts +25 -0
- package/dist/integrity/slopnators/sl_screen_holds_only_declared.d.ts +2 -0
- package/dist/integrity/slopnators/sl_screen_holds_only_declared.js +61 -0
- package/dist/integrity/slopnators/sl_screen_holds_only_declared.ts +70 -0
- package/dist/integrity/slopnators/sl_secret_literal.js +1 -33
- package/dist/integrity/slopnators/sl_secret_literal.ts +1 -33
- package/dist/integrity/slopnators/sl_stale_path.js +5 -22
- package/dist/integrity/slopnators/sl_stale_path.ts +4 -20
- package/dist/integrity/slopnators/sl_twice_meant.js +1 -1
- package/dist/integrity/slopnators/sl_twice_parented.js +29 -5
- package/dist/integrity/slopnators/sl_twice_parented.ts +28 -4
- package/dist/integrity/slopnators/sl_undeclared_crossing.d.ts +4 -1
- package/dist/integrity/slopnators/sl_undeclared_crossing.js +426 -62
- package/dist/integrity/slopnators/sl_undeclared_crossing.ts +454 -70
- package/dist/integrity/slopnators/sl_undeclared_destination.js +59 -25
- package/dist/integrity/slopnators/sl_undeclared_destination.ts +69 -21
- package/dist/integrity/slopnators/sl_undeclared_list.d.ts +2 -0
- package/dist/integrity/slopnators/sl_undeclared_list.js +363 -0
- package/dist/integrity/slopnators/sl_undeclared_list.ts +358 -0
- package/dist/integrity/slopnators/sl_undeclared_node.js +1 -11
- package/dist/integrity/slopnators/sl_undeclared_node.ts +0 -10
- package/dist/integrity/slopnators/sl_undeclared_operation.js +111 -29
- package/dist/integrity/slopnators/sl_undeclared_operation.ts +134 -26
- package/dist/integrity/slopnators/sl_undeclared_variant.js +2 -2
- package/dist/integrity/slopnators/sl_undeclared_webhook.d.ts +2 -0
- package/dist/integrity/slopnators/sl_undeclared_webhook.js +90 -0
- package/dist/integrity/slopnators/sl_undeclared_webhook.ts +108 -0
- package/dist/integrity/slopnators/sl_underived_route.d.ts +2 -0
- package/dist/integrity/slopnators/sl_underived_route.js +61 -0
- package/dist/integrity/slopnators/sl_underived_route.ts +72 -0
- package/dist/integrity/slopnators/sl_ungoverned_island.js +3 -3
- package/dist/integrity/slopnators/sl_ungoverned_island.ts +1 -1
- package/dist/integrity/slopnators/sl_unlisted_program.d.ts +2 -0
- package/dist/integrity/slopnators/sl_unlisted_program.js +39 -0
- package/dist/integrity/slopnators/sl_unlisted_program.ts +40 -0
- package/dist/integrity/slopnators/sl_unnamed_island.js +1 -1
- package/dist/integrity/slopnators/sl_unpaired_member.js +3 -3
- package/dist/integrity/slopnators/sl_unpaired_member.ts +1 -1
- package/dist/integrity/slopnators/sl_unpaired_slopnator.js +4 -4
- package/dist/integrity/slopnators/sl_unpaired_slopnator.ts +1 -1
- package/dist/integrity/slopnators/sl_unprefixed_member.js +5 -31
- package/dist/integrity/slopnators/sl_unprefixed_member.ts +2 -28
- package/dist/integrity/slopnators/sl_unthreaded.js +11 -7
- package/dist/integrity/slopnators/sl_unthreaded.ts +6 -7
- package/dist/integrity/slopnators/sl_untranslated_key.js +2 -25
- package/dist/integrity/slopnators/sl_untranslated_key.ts +1 -25
- package/dist/integrity/slopnators/sl_unvaulted_secret.d.ts +2 -0
- package/dist/integrity/slopnators/sl_unvaulted_secret.js +107 -0
- package/dist/integrity/slopnators/sl_unvaulted_secret.ts +132 -0
- package/dist/integrity/slopnators/sl_unversioned.js +6 -4
- package/dist/integrity/slopnators/sl_unversioned.ts +5 -3
- package/dist/integrity/sweep.d.ts +1 -0
- package/dist/integrity/sweep.js +105 -42
- package/dist/integrity/sweep.ts +115 -42
- package/dist/knowledge/attach.js +4 -3
- package/dist/knowledge/attach.ts +3 -2
- package/dist/knowledge/generators/docsgen.js +8 -6
- package/dist/knowledge/generators/docsgen.ts +4 -2
- package/dist/knowledge/generators/glossary.js +4 -4
- package/dist/knowledge/generators/glossary.ts +1 -1
- package/dist/operations/access.d.ts +23 -0
- package/dist/operations/access.js +28 -1
- package/dist/operations/access.ts +43 -0
- package/dist/operations/attach.js +33 -113
- package/dist/operations/attach.ts +51 -117
- package/dist/operations/capabilities.d.ts +14 -5
- package/dist/operations/capabilities.js +13 -4
- package/dist/operations/capabilities.ts +27 -8
- package/dist/operations/dispatch.d.ts +8 -2
- package/dist/operations/dispatch.js +128 -185
- package/dist/operations/dispatch.ts +138 -191
- package/dist/operations/error-results.d.ts +1 -1
- package/dist/operations/error-results.js +2 -2
- package/dist/operations/error-results.ts +2 -2
- package/dist/operations/generators/capability.d.ts +11 -1
- package/dist/operations/generators/capability.js +481 -224
- package/dist/operations/generators/capability.ts +562 -233
- package/dist/operations/generators/compile.js +66 -39
- package/dist/operations/generators/compile.ts +78 -39
- package/dist/operations/generators/permits.js +11 -12
- package/dist/operations/generators/permits.ts +3 -4
- package/dist/operations/generators/seed.d.ts +1 -0
- package/dist/operations/generators/seed.js +19 -17
- package/dist/operations/generators/seed.ts +22 -14
- package/dist/operations/generators/trial.d.ts +6 -8
- package/dist/operations/generators/trial.js +200 -70
- package/dist/operations/generators/trial.ts +230 -93
- package/dist/operations/nodes.d.ts +15 -16
- package/dist/operations/nodes.ts +16 -17
- package/dist/operations/operations.d.ts +40 -4
- package/dist/operations/operations.js +1 -0
- package/dist/operations/operations.ts +61 -4
- package/dist/operations/result.d.ts +2 -2
- package/dist/operations/result.ts +2 -2
- package/package.json +1 -4
- package/dist/core/answers.d.ts +0 -171
- package/dist/core/answers.js +0 -789
- package/dist/core/answers.ts +0 -999
- package/dist/core/client.d.ts +0 -63
- package/dist/core/client.js +0 -249
- package/dist/core/client.ts +0 -289
- package/dist/core/files.js +0 -171
- package/dist/core/files.ts +0 -222
- package/dist/integrations/module.d.ts +0 -6
- package/dist/integrations/module.js +0 -153
- package/dist/integrations/module.ts +0 -191
- package/dist/integrity/slopnators/sl_unkept_rows.js +0 -104
- package/dist/integrity/slopnators/sl_unkept_rows.ts +0 -111
- package/dist/integrity/slopnators/sl_unseamed_reach.js +0 -73
- package/dist/integrity/slopnators/sl_unseamed_reach.ts +0 -79
- package/dist/operations/cost.d.ts +0 -14
- package/dist/operations/cost.js +0 -37
- package/dist/operations/cost.ts +0 -58
- package/dist/operations/errors/errors.d.ts +0 -52
- package/dist/operations/http.js +0 -124
- package/dist/operations/http.ts +0 -169
- package/dist/operations/memory.d.ts +0 -104
- package/dist/operations/memory.js +0 -365
- package/dist/operations/memory.ts +0 -470
- package/dist/operations/metering.d.ts +0 -55
- package/dist/operations/metering.js +0 -247
- package/dist/operations/metering.ts +0 -328
- package/dist/operations/queue-policy.d.ts +0 -3
- package/dist/operations/queue-policy.js +0 -8
- package/dist/operations/queue-policy.ts +0 -10
- package/dist/operations/seams.d.ts +0 -239
- package/dist/operations/seams.js +0 -45
- package/dist/operations/seams.ts +0 -364
- package/dist/operations/store.d.ts +0 -14
- package/dist/operations/store.js +0 -1
- package/dist/operations/store.ts +0 -29
- /package/dist/{operations → core}/errors/classes.d.ts +0 -0
- /package/dist/{operations → core}/errors/classes.js +0 -0
- /package/dist/{operations → core}/errors/classes.ts +0 -0
- /package/dist/integrity/slopnators/{sl_unkept_rows.d.ts → sl_door_in_a_node.d.ts} +0 -0
- /package/dist/integrity/slopnators/{sl_unseamed_reach.d.ts → sl_outside_an_operation.d.ts} +0 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { join } from 'node:path'
|
|
2
2
|
import { argv, stderr, stdout } from 'node:process'
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import { existsSync, readFileSync, writeFileSync } from '../../core/files.ts'
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync } from '../../integrations/disk.ts'
|
|
6
5
|
import { exit, invoked } from '../../core/invoked.ts'
|
|
7
|
-
import { valuesIn } from '../../core/rows.ts'
|
|
6
|
+
import { marked, valuesIn } from '../../core/rows.ts'
|
|
8
7
|
import { ours } from '../../core/scope.ts'
|
|
9
8
|
import { findTree, inTree } from '../../core/tree.ts'
|
|
10
9
|
|
|
@@ -17,8 +16,12 @@ const MANIFEST = 'package.json'
|
|
|
17
16
|
interface Row {
|
|
18
17
|
readonly id?: string
|
|
19
18
|
readonly at?: string
|
|
19
|
+
readonly derives?: readonly Row[]
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
const addressed = (rows: readonly Row[]): readonly string[] =>
|
|
23
|
+
rows.flatMap((one) => [...(one.at === undefined ? [] : [one.at]), ...addressed(one.derives ?? [])])
|
|
24
|
+
|
|
22
25
|
const mark = (one: Row): string => marked([one.id ?? '', one.at ?? ''])
|
|
23
26
|
|
|
24
27
|
function releases(): readonly Row[] {
|
|
@@ -32,46 +35,44 @@ function releases(): readonly Row[] {
|
|
|
32
35
|
}
|
|
33
36
|
}
|
|
34
37
|
|
|
35
|
-
function
|
|
36
|
-
const at = inTree(TREE, 'secrets.ts')
|
|
37
|
-
if (!existsSync(at)) return []
|
|
38
|
+
function manager(): string {
|
|
38
39
|
try {
|
|
39
|
-
const held =
|
|
40
|
-
|
|
40
|
+
const held = JSON.parse(readFileSync(join(TREE.at, MANIFEST), 'utf8')) as { packageManager?: unknown }
|
|
41
|
+
const said = typeof held.packageManager === 'string' ? held.packageManager.split('@')[0] : undefined
|
|
42
|
+
return said === undefined || said === '' ? 'npm' : said
|
|
41
43
|
} catch {
|
|
42
|
-
return
|
|
44
|
+
return 'npm'
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
function scripted(): { readonly build: string; readonly start: string } {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
scripts?: Readonly<Record<string, string>>
|
|
50
|
-
}
|
|
51
|
-
const scripts = held.scripts ?? {}
|
|
52
|
-
return {
|
|
53
|
-
build: scripts['build'] === undefined ? 'npm run build' : 'npm run build',
|
|
54
|
-
start: scripts['start'] === undefined ? 'npm start' : 'npm start',
|
|
55
|
-
}
|
|
56
|
-
} catch {
|
|
57
|
-
return { build: 'npm run build', start: 'npm start' }
|
|
58
|
-
}
|
|
49
|
+
const tool = manager()
|
|
50
|
+
return { build: `${tool} run build`, start: tool === 'npm' ? 'npm start' : `${tool} start` }
|
|
59
51
|
}
|
|
60
52
|
|
|
61
53
|
function dockerfile(build: string, start: string): string {
|
|
54
|
+
const tool = manager()
|
|
55
|
+
const corepack = tool === 'npm' ? [] : ['RUN corepack enable']
|
|
56
|
+
const lock = tool === 'npm' ? 'package-lock.json*' : `${tool}-lock.yaml*`
|
|
57
|
+
const first =
|
|
58
|
+
tool === 'npm'
|
|
59
|
+
? 'RUN npm ci --omit=dev --ignore-scripts || npm install --omit=dev --ignore-scripts'
|
|
60
|
+
: `RUN ${tool} install --prod --frozen-lockfile --ignore-scripts || ${tool} install --prod --ignore-scripts`
|
|
61
|
+
const all = tool === 'npm' ? 'RUN npm install --ignore-scripts' : `RUN ${tool} install --ignore-scripts`
|
|
62
|
+
|
|
62
63
|
return [
|
|
63
|
-
'# GENERATED by thread — do not edit. It is derived from what this app declares.',
|
|
64
|
-
'',
|
|
65
64
|
'FROM node:22-slim AS build',
|
|
66
65
|
'WORKDIR /app',
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
...corepack,
|
|
67
|
+
`COPY package.json ${lock} ./`,
|
|
68
|
+
first,
|
|
69
69
|
'COPY . .',
|
|
70
|
-
|
|
70
|
+
all,
|
|
71
71
|
`RUN ${build}`,
|
|
72
72
|
'',
|
|
73
73
|
'FROM node:22-slim',
|
|
74
74
|
'WORKDIR /app',
|
|
75
|
+
...corepack,
|
|
75
76
|
'ENV NODE_ENV=production',
|
|
76
77
|
'COPY --from=build /app ./',
|
|
77
78
|
`EXPOSE ${String(LISTENS)}`,
|
|
@@ -80,22 +81,22 @@ function dockerfile(build: string, start: string): string {
|
|
|
80
81
|
].join('\n')
|
|
81
82
|
}
|
|
82
83
|
|
|
83
|
-
function compose(id: string
|
|
84
|
+
function compose(id: string): string {
|
|
84
85
|
return [
|
|
85
|
-
'# GENERATED by thread — do not edit. It is derived from what this app declares.',
|
|
86
|
-
'',
|
|
87
86
|
'services:',
|
|
88
87
|
` ${id}:`,
|
|
89
88
|
' build: .',
|
|
90
89
|
' ports:',
|
|
91
90
|
` - "${String(LISTENS)}:${String(LISTENS)}"`,
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
' environment:',
|
|
91
|
+
'',
|
|
92
|
+
].join('\n')
|
|
93
|
+
}
|
|
96
94
|
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
function withheld(): string {
|
|
96
|
+
return [
|
|
97
|
+
'.thread',
|
|
98
|
+
'node_modules',
|
|
99
|
+
'.git',
|
|
99
100
|
'',
|
|
100
101
|
].join('\n')
|
|
101
102
|
}
|
|
@@ -103,7 +104,6 @@ function compose(id: string, secrets: readonly string[]): string {
|
|
|
103
104
|
function made(): ReadonlyMap<string, string> {
|
|
104
105
|
const found = new Map<string, string>()
|
|
105
106
|
const rows = releases()
|
|
106
|
-
const secrets = named()
|
|
107
107
|
const { build, start } = scripted()
|
|
108
108
|
|
|
109
109
|
for (const one of rows) {
|
|
@@ -113,7 +113,8 @@ function made(): ReadonlyMap<string, string> {
|
|
|
113
113
|
if (kind === undefined) continue
|
|
114
114
|
if (kind === 'docker') {
|
|
115
115
|
found.set('Dockerfile', dockerfile(build, start))
|
|
116
|
-
found.set('compose.yaml', compose(id
|
|
116
|
+
found.set('compose.yaml', compose(id))
|
|
117
|
+
found.set('.dockerignore', withheld())
|
|
117
118
|
}
|
|
118
119
|
}
|
|
119
120
|
return found
|
|
@@ -138,7 +139,14 @@ function run(): number {
|
|
|
138
139
|
return 0
|
|
139
140
|
}
|
|
140
141
|
|
|
141
|
-
const words =
|
|
142
|
+
const words = argv.slice(2).filter((one) => !one.startsWith('-'))
|
|
143
|
+
if (words[0] !== undefined && words[0] !== 'read') {
|
|
144
|
+
stderr.write(
|
|
145
|
+
'release: `' + words[0] + '` is not something this command does. `thread release` writes the release, and ' +
|
|
146
|
+
'`thread release read <mark>` prints one. Nothing was written.\n',
|
|
147
|
+
)
|
|
148
|
+
return 1
|
|
149
|
+
}
|
|
142
150
|
if (words[0] === 'read') {
|
|
143
151
|
const which = words[1]
|
|
144
152
|
const one = rows.find((row) => mark(row) === which)
|
|
@@ -153,10 +161,10 @@ function run(): number {
|
|
|
153
161
|
|
|
154
162
|
const kind = kindOf(one.id ?? '')
|
|
155
163
|
stdout.write(`${String(one.id)} — ${kind === undefined ? 'a release of a kind this generator does not recognise' : SAID[kind]}\n`)
|
|
156
|
-
for (const
|
|
157
|
-
stdout.write(`\n${
|
|
164
|
+
for (const one of kind === undefined ? [] : WRITES[kind]) {
|
|
165
|
+
stdout.write(`\n${one.at} — ${one.describes}\n`)
|
|
158
166
|
try {
|
|
159
|
-
stdout.write(readFileSync(join(TREE.at,
|
|
167
|
+
stdout.write(readFileSync(join(TREE.at, one.at), 'utf8'))
|
|
160
168
|
} catch {
|
|
161
169
|
stdout.write('(nothing is there)\n')
|
|
162
170
|
}
|
|
@@ -167,6 +175,19 @@ function run(): number {
|
|
|
167
175
|
const files = made()
|
|
168
176
|
const checking = argv.includes('--check')
|
|
169
177
|
|
|
178
|
+
const stated = new Set(addressed(rows))
|
|
179
|
+
const stray = [...files.keys()].filter((one) => !stated.has(one))
|
|
180
|
+
if (stray.length > 0) {
|
|
181
|
+
stderr.write(
|
|
182
|
+
`release: this release produces ${stray.join(', ')}, and no row names ${stray.length === 1 ? 'it' : 'them'}. ` +
|
|
183
|
+
`Writing ${stray.length === 1 ? 'it' : 'them'} would leave a file this tree does not declare, and the descent ` +
|
|
184
|
+
'reports that three steps later as a file nobody can account for. Take the release out with `thread remove ' +
|
|
185
|
+
'<its id>` and declare it again — the maker writes one row per file this kind produces, so all of them arrive ' +
|
|
186
|
+
'together. Nothing was written.\n',
|
|
187
|
+
)
|
|
188
|
+
return 1
|
|
189
|
+
}
|
|
190
|
+
|
|
170
191
|
const shipped = installed()
|
|
171
192
|
if (shipped.length > 0) {
|
|
172
193
|
stderr.write(
|
|
@@ -202,8 +223,10 @@ function run(): number {
|
|
|
202
223
|
|
|
203
224
|
for (const [at, text] of files) writeFileSync(join(TREE.at, at), text, 'utf8')
|
|
204
225
|
stdout.write(
|
|
205
|
-
|
|
206
|
-
|
|
226
|
+
'release: wrote ' + [...files.keys()].join(', ') + ' — built and started by what this app\'s own manifest ' +
|
|
227
|
+
'declares, listening on ' + String(LISTENS) + '.\n' +
|
|
228
|
+
'release: no secret is named there. A secret is read from the sealed store at the moment it is used, and ' +
|
|
229
|
+
'naming it here would be telling whoever deploys this to put a credential in the environment instead.\n',
|
|
207
230
|
)
|
|
208
231
|
return 0
|
|
209
232
|
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
export declare const PREFIXES: {
|
|
2
|
-
readonly docker:
|
|
2
|
+
readonly docker: 'dk_';
|
|
3
3
|
};
|
|
4
|
-
export declare const KINDS: readonly [
|
|
5
|
-
export
|
|
4
|
+
export declare const KINDS: readonly ['docker'];
|
|
5
|
+
export interface Written {
|
|
6
|
+
readonly at: string;
|
|
7
|
+
readonly describes: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const WRITES: Readonly<Record<(typeof KINDS)[number], readonly Written[]>>;
|
|
6
10
|
export declare const LISTENS = 3000;
|
|
7
11
|
export declare const SAID: Readonly<Record<(typeof KINDS)[number], string>>;
|
|
8
12
|
export declare const kindOf: (id: string) => (typeof KINDS)[number] | undefined;
|
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
export const PREFIXES = { docker: 'dk_' };
|
|
2
2
|
export const KINDS = ['docker'];
|
|
3
3
|
export const WRITES = {
|
|
4
|
-
docker: [
|
|
4
|
+
docker: [
|
|
5
|
+
{
|
|
6
|
+
at: 'Dockerfile',
|
|
7
|
+
describes: 'How this app becomes an image and what starts it inside one — the build and start commands its own manifest declares, run with the package manager that manifest names, and the port its server listens on.',
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
at: 'compose.yaml',
|
|
11
|
+
describes: 'What runs the image this release builds, named beside it because one row states one address.',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
at: '.dockerignore',
|
|
15
|
+
describes: 'What a build of this image must never carry out of this directory: the sealed store and the key that opens it, the installed packages, and the history. Without it the build copies everything beside it, and every sealed value goes into the image and into whoever pulls it.',
|
|
16
|
+
},
|
|
17
|
+
],
|
|
5
18
|
};
|
|
6
19
|
export const LISTENS = 3000;
|
|
7
20
|
export const SAID = {
|
|
@@ -4,8 +4,28 @@ export const PREFIXES = { docker: 'dk_' } as const
|
|
|
4
4
|
|
|
5
5
|
export const KINDS = ['docker'] as const
|
|
6
6
|
|
|
7
|
-
export
|
|
8
|
-
|
|
7
|
+
export interface Written {
|
|
8
|
+
readonly at: string
|
|
9
|
+
readonly describes: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const WRITES: Readonly<Record<(typeof KINDS)[number], readonly Written[]>> = {
|
|
13
|
+
docker: [
|
|
14
|
+
{
|
|
15
|
+
at: 'Dockerfile',
|
|
16
|
+
describes:
|
|
17
|
+
'How this app becomes an image and what starts it inside one — the build and start commands its own manifest declares, run with the package manager that manifest names, and the port its server listens on.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
at: 'compose.yaml',
|
|
21
|
+
describes: 'What runs the image this release builds, named beside it because one row states one address.',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
at: '.dockerignore',
|
|
25
|
+
describes:
|
|
26
|
+
'What a build of this image must never carry out of this directory: the sealed store and the key that opens it, the installed packages, and the history. Without it the build copies everything beside it, and every sealed value goes into the image and into whoever pulls it.',
|
|
27
|
+
},
|
|
28
|
+
],
|
|
9
29
|
}
|
|
10
30
|
|
|
11
31
|
export const LISTENS = 3000
|
|
@@ -2,5 +2,9 @@ import type { Attaching } from '../core/attach.ts';
|
|
|
2
2
|
export declare const CONCEPTS: readonly {
|
|
3
3
|
readonly id: string;
|
|
4
4
|
readonly describes: string;
|
|
5
|
+
readonly cites: readonly {
|
|
6
|
+
readonly on: string;
|
|
7
|
+
readonly said: string;
|
|
8
|
+
}[];
|
|
5
9
|
}[];
|
|
6
10
|
export declare const ATTACH: Attaching;
|
|
@@ -1,18 +1,35 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SHAPED } from '../core/init.js';
|
|
2
|
+
import { NAMED } from '../core/scope.js';
|
|
2
3
|
const VERSION = 1;
|
|
3
|
-
const DESCRIBES = 'The system that states every place this app reaches and every credential it reaches with. A target is a destination and the prefix on its id is how it is reached; what it accepts is entities if it keeps them, calls if it is called over https,
|
|
4
|
-
const TARGETS = 'Where this app states
|
|
5
|
-
const SECRETS = 'Where this app states every value it must be given and may not hold. A row here is a name and a sentence and never a value
|
|
4
|
+
const DESCRIBES = 'The system that states every place this app reaches and every credential it reaches with. A target is a destination and the prefix on its id is how it is reached; what it accepts is entities if it keeps them, and calls if it is called: an endpoint over https, a subcommand of a program, a method of a package; a disk accepts nothing, because every disk answers the same orders; what it requires is secrets, and the target it is reached through when the place can only be got at by way of another one; where it is goes on the row as its address when anybody may read it, and is one of the secrets when it carries a password. Nothing else in this app names a host, a connection string or an environment variable, so an operation says which place it needs and the rest is worked out from the declaration.';
|
|
5
|
+
const TARGETS = 'Where this app states everything outside itself that it deals with, and every way in. An integration is one outside thing — a vendor, a service, a program on the machine — and nothing is reached that is not part of one; declare it with `thread create integration`. A target is one way out of this app into an integration: `thread create target` prints every way a place can be reached, asks which, and puts that prefix on the id, so how it is reached is the prefix and no field says so. A call is one thing a target can be asked to do, declared beside it with `thread create target call`. A webhook is the way back in: `thread create webhook` asks which integration it sits under, the path something outside posts to, and the operation it invokes, and that operation names the webhook back, so neither half opens a door on its own. Nobody writes the file that answers that address, because `thread capabilities` derives it from those two rows. What a target accepts goes in `takes` — entities where it keeps things, calls where it is called, and nothing for a disk. What it needs goes in `requires`: its credentials, and the target it is reached through; where it is goes in address, and a header every call carries goes in headers. This is the one place the split between what reaches a server and what stays local is written down.';
|
|
6
|
+
const SECRETS = 'Where this app states every value it must be given and may not hold. A row here is a name and a sentence and never a value, and every id wears sec_, because only a server may ever hold a secret: a value anybody may read is not one, and goes on the row that needs it instead, as the address of a target or a header it sends. A secret with a sends goes into a header on every call, one with a signs is the key a body is signed with, and one with neither is the connection string of a database, the one address that carries a password.';
|
|
6
7
|
const VAULT = 'What opens a secret\'s value at the moment of use, written once and then yours. It reads the names off _threads/secrets.ts and opens the values sealed beside the tree, refusing any other name; add a secret with `thread create secret`, which is the only thing that ever takes a value. To open values from somewhere else in production, replace what opens them here.';
|
|
7
|
-
const SECRET = 'A value this app must be given and may never hold
|
|
8
|
-
const CALL = 'One thing a target can be asked to do
|
|
9
|
-
const REACH = 'How a target is got at — over a network to a postgres, inside this process, in the browser\'s own memory, over https, as
|
|
8
|
+
const SECRET = 'A value this app must be given and may never hold: a key, a token, a connection string. The row names it and says what it is for, and there is no field on it for the value, because a row is read by everything and a credential is read by one thing at one moment. Every id wears sec_, and that prefix says only a server may ever hold it: everything a browser bundle reaches is in the bundle, so a target requiring a secret is refused a browser entry when it is built. A value anybody may read is not a secret and is never sealed; it is written on the row that needs it, as the address of a target or a header every call carries.';
|
|
9
|
+
const CALL = 'One thing a target can be asked to do, named so that a node names the call and never writes a url, a subcommand or a method. Over https it is a verb and a path; on a program it is a subcommand; on a package it is a method. It is a row rather than a field because it is a thing with a name and a sentence like everything else here, and because what a place offers is a list that grows: an app reaches one more endpoint, subcommand or method by declaring one more of these, not by editing a body.';
|
|
10
|
+
const REACH = 'How a target is got at — over a network to a postgres, inside this process, in the browser\'s own memory, over https, as a package this app calls in its own process, as a program run at a command line, or as the disk under it. It is the prefix on the target\'s id and never a field, because how a thing is reached decides everything else that may be said about it: what it accepts, whether it can be reached from a page at all, and whether anything has to say where it is. A field beside the id would be a second answer to a question the id already answers.';
|
|
11
|
+
const INTEGRATION = 'Something outside this app that it reaches into: a vendor, a service, a program on the machine. Every target says which integration it is part of, so supabase is one thing made of its postgres, its https endpoint, the calls on each and the secrets they need, rather than five rows that happen to share a word. Declare it before the first target that reaches into it.';
|
|
12
|
+
const WEBHOOK = 'A way in that something outside uses: it posts to one address this app declares, and that address is the whole of what anybody out there is given. It sits under an integration beside the targets that reach the other way, and it names the operation it runs and the secret its signature is checked against, so what arrives is refused or dispatched and never anything else. Declare one with `thread create webhook`.';
|
|
13
|
+
const INVOKES = 'Which operation a webhook runs when something posts to it. That operation names the webhook back, so both halves agree before anything outside reaches it, and a pairing only one of them states is refused.';
|
|
14
|
+
const ARRIVES = 'Which header a value comes in on. A webhook says which one carries its signature, and an entity that names its callers says which one carries their token — one word, because it answers the same question about a request.';
|
|
15
|
+
const SIGNS = 'What a secret does to a body on its way out: its value is the key a signature is computed with, and the digest goes on the header named here. It is `sends` turned around — `sends` puts the value itself on a header, and this puts the value nowhere at all.';
|
|
16
|
+
const ADDRESS = 'Where a target reached over https is: the one absolute url every call on it is written from, stated on the row because a place is a fact anybody may read. Only the address of a database is sealed instead, because a connection string carries a password.';
|
|
17
|
+
const HEADERS = 'The headers every call on a target carries, stated on its row as name and value: the version of an API this app is written against, or a fixed way of asking. A credential never goes here, because anybody may read a row; a value that has to be withheld is a secret with a sends.';
|
|
18
|
+
const SSOT = { on: '2026-08-29', said: 'SSOT for the integrations, as a whole meta inside thread core' };
|
|
19
|
+
const RULED = { on: '2026-09-22', said: 'remove pub then as an acceptable thing, that\'s definitely slop and it\'s not the first time such a fucking thing has surfaced. Delete and redo it properly.' };
|
|
10
20
|
export const CONCEPTS = [
|
|
11
|
-
{ id: 'secret', describes: SECRET },
|
|
12
|
-
{ id: '
|
|
13
|
-
{ id: '
|
|
21
|
+
{ id: 'secret', describes: SECRET, cites: [SSOT] },
|
|
22
|
+
{ id: 'webhook', describes: WEBHOOK, cites: [SSOT] },
|
|
23
|
+
{ id: 'invokes', describes: INVOKES, cites: [SSOT] },
|
|
24
|
+
{ id: 'arrives', describes: ARRIVES, cites: [SSOT] },
|
|
25
|
+
{ id: 'signs', describes: SIGNS, cites: [SSOT] },
|
|
26
|
+
{ id: 'address', describes: ADDRESS, cites: [RULED] },
|
|
27
|
+
{ id: 'headers', describes: HEADERS, cites: [RULED] },
|
|
28
|
+
{ id: 'call', describes: CALL, cites: [SSOT] },
|
|
29
|
+
{ id: 'reach', describes: REACH, cites: [SSOT] },
|
|
30
|
+
{ id: 'integration', describes: INTEGRATION, cites: [SSOT] },
|
|
14
31
|
];
|
|
15
|
-
import { quoted } from
|
|
32
|
+
import { quoted } from '../core/rows.js';
|
|
16
33
|
const concept = (one) => [
|
|
17
34
|
' {',
|
|
18
35
|
` id: '${one.id}',`,
|
|
@@ -20,12 +37,11 @@ const concept = (one) => [
|
|
|
20
37
|
` describes: ${quoted(one.describes)},`,
|
|
21
38
|
` version: ${String(VERSION)},`,
|
|
22
39
|
' cites: [',
|
|
23
|
-
" { on: '
|
|
24
|
-
" { on: '2026-08-29', said: 'seams declare BOTH target AND secrets' },",
|
|
40
|
+
...one.cites.map((each) => " { on: '" + each.on + "', said: " + quoted(each.said) + ' },'),
|
|
25
41
|
' ],',
|
|
26
42
|
' },',
|
|
27
43
|
].join('\n');
|
|
28
|
-
const INTEGRATIONS_SOURCE = `import type { Threaded } from '
|
|
44
|
+
const INTEGRATIONS_SOURCE = `import type { Threaded } from '${SHAPED}'
|
|
29
45
|
|
|
30
46
|
export const INTEGRATIONS: Threaded = {
|
|
31
47
|
id: 'integrations',
|
|
@@ -48,13 +64,17 @@ export const INTEGRATIONS: Threaded = {
|
|
|
48
64
|
],
|
|
49
65
|
}
|
|
50
66
|
`;
|
|
51
|
-
const TARGETS_SOURCE = `import type { Call, Target } from '
|
|
67
|
+
const TARGETS_SOURCE = `import type { Call, Integration, Target, Webhook } from '${NAMED}/integrations/target'
|
|
68
|
+
|
|
69
|
+
export const INTEGRATIONS: readonly Integration[] = []
|
|
52
70
|
|
|
53
71
|
export const TARGETS: readonly Target[] = []
|
|
54
72
|
|
|
55
73
|
export const CALLS: readonly Call[] = []
|
|
74
|
+
|
|
75
|
+
export const WEBHOOKS: readonly Webhook[] = []
|
|
56
76
|
`;
|
|
57
|
-
const SECRETS_SOURCE = `import type { Secret } from '
|
|
77
|
+
const SECRETS_SOURCE = `import type { Secret } from '${NAMED}/integrations/secret'
|
|
58
78
|
|
|
59
79
|
export const SECRETS: readonly Secret[] = []
|
|
60
80
|
`;
|
|
@@ -88,7 +108,7 @@ const SEEDED = {
|
|
|
88
108
|
' {',
|
|
89
109
|
' id: \'integrations\',',
|
|
90
110
|
' at: \'_threads/integrations.ts\',',
|
|
91
|
-
' describes: \'The system that states every place this app reaches and every credential it reaches with. A target is a destination and the prefix on its id is how it is reached; what it accepts is entities if it keeps them, calls if it is called over https,
|
|
111
|
+
' describes: \'The system that states every place this app reaches and every credential it reaches with. A target is a destination and the prefix on its id is how it is reached; what it accepts is entities if it keeps them, and calls if it is called: an endpoint over https, a subcommand of a program, a method of a package; a disk accepts nothing, because every disk answers the same orders; what it requires is secrets, and the target it is reached through when the place can only be got at by way of another one; where it is goes on the row as its address when anybody may read it, and is one of the secrets when it carries a password. Nothing else in this app names a host, a connection string or an environment variable, so an operation says which place it needs and the rest is worked out from the declaration.\',',
|
|
92
112
|
' version: 1,',
|
|
93
113
|
' },',
|
|
94
114
|
].join('\n'),
|
|
@@ -117,43 +137,4 @@ export const ATTACH = {
|
|
|
117
137
|
{ file: 'secrets.ts', source: SECRETS_SOURCE },
|
|
118
138
|
],
|
|
119
139
|
rows: [...OWN, ...SHIPPED],
|
|
120
|
-
retires: [
|
|
121
|
-
{
|
|
122
|
-
into: 'derivation.ts',
|
|
123
|
-
list: 'GENERATORS',
|
|
124
|
-
id: 'read-generator',
|
|
125
|
-
why: 'renamed to `inspect-generator`. `thread read` is a verb of the CLI itself now — it reads FILES, and this package reads ROWS, which is `thread inspect`. Both were called read, and only one of them could answer.',
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
into: 'integrations.ts',
|
|
129
|
-
list: 'declares',
|
|
130
|
-
id: 'trace',
|
|
131
|
-
made: `src/integrations.trace.${'jsonl'}`,
|
|
132
|
-
why: 'the record of what went out through an integration is gone. It sealed every line against the one before it, and a chain nobody reads guards nothing. What an integration did is what the tool itself reports, at the moment it runs',
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
into: 'derivation.ts',
|
|
136
|
-
list: 'GENERATORS',
|
|
137
|
-
id: 'trace-generator',
|
|
138
|
-
why: 'the record it wrote is gone, so there is nothing for it to make and nothing for `--check` to read',
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
into: 'derivation.ts',
|
|
142
|
-
list: 'GENERATORS',
|
|
143
|
-
id: 'sdk-generator',
|
|
144
|
-
why: '`sdk` is a way a target is reached now, not a noun beside one — `thread create target` declares an SDK with ' +
|
|
145
|
-
'`--reach sdk`, which installs it, reads what it answers to, and writes one row instead of three. The noun ' +
|
|
146
|
-
'also raised the collision guard against any app declaring a meta called `sdk`, which made every other ' +
|
|
147
|
-
'withdrawal this package ships undeliverable to the trees that needed them.',
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
into: 'concepts.ts',
|
|
151
|
-
list: 'CONCEPTS',
|
|
152
|
-
id: 'sdk',
|
|
153
|
-
why: '`sdk` is no longer a noun beside a target — it is one of the ways a target is reached, and its meaning is ' +
|
|
154
|
-
`now \`SAID.module\` in \`${named('integrations')}/target\`, beside \`https\` and every other reach, none of which is ` +
|
|
155
|
-
'coined here either. It also collided with an app declaring a meta called `sdk`, which coins the word: two ' +
|
|
156
|
-
'meanings for one word is what `twice-meant` refuses, and it was holding the glossary and the docs red.',
|
|
157
|
-
},
|
|
158
|
-
],
|
|
159
140
|
};
|