@prestack/thread 0.1.2 → 0.1.4
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/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 +67 -58
- package/dist/core/attach.ts +61 -68
- 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 +89 -21
- package/dist/core/descend.ts +86 -17
- 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 +0 -2
- package/dist/core/init.js +51 -15
- package/dist/core/init.ts +58 -15
- 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/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 +1 -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 +33 -54
- package/dist/integrations/attach.ts +50 -57
- 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 -20
- 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 +3 -73
- package/dist/integrity/attach.ts +1 -71
- 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 -161
- package/dist/integrity/generators/trial.ts +145 -165
- 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 +58 -37
- package/dist/integrity/slopnator.ts +53 -37
- 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 +1 -1
- 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 +28 -109
- package/dist/operations/attach.ts +46 -113
- 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 -57
- package/dist/core/client.js +0 -247
- package/dist/core/client.ts +0 -286
- package/dist/core/files.js +0 -145
- package/dist/core/files.ts +0 -193
- 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
|
@@ -10,12 +10,12 @@ import { relative, resolve } from 'node:path';
|
|
|
10
10
|
import { argv, stderr, stdout } from 'node:process';
|
|
11
11
|
import { pathToFileURL } from 'node:url';
|
|
12
12
|
import { build } from 'esbuild';
|
|
13
|
-
import { descend, reached } from
|
|
14
|
-
import { existsSync, readFileSync } from
|
|
15
|
-
import { exit, invoked } from
|
|
16
|
-
import { valuesIn } from
|
|
17
|
-
import { findTree } from
|
|
18
|
-
import { servesBrowser } from
|
|
13
|
+
import { descend, reached } from '../../core/descend.js';
|
|
14
|
+
import { existsSync, readFileSync } from '../../integrations/disk.js';
|
|
15
|
+
import { exit, invoked } from '../../core/invoked.js';
|
|
16
|
+
import { valuesIn } from '../../core/rows.js';
|
|
17
|
+
import { findTree } from '../../core/tree.js';
|
|
18
|
+
import { servesBrowser } from '../../integrations/target.js';
|
|
19
19
|
const TREE = findTree();
|
|
20
20
|
const ROOT = TREE.at;
|
|
21
21
|
const OUTSIDE = /(^|\/)node_modules(\/|$)/;
|
|
@@ -5,7 +5,7 @@ import { pathToFileURL } from 'node:url'
|
|
|
5
5
|
import { build } from 'esbuild'
|
|
6
6
|
|
|
7
7
|
import { descend, reached, type Pass } from '../../core/descend.ts'
|
|
8
|
-
import { existsSync, readFileSync } from '../../
|
|
8
|
+
import { existsSync, readFileSync } from '../../integrations/disk.ts'
|
|
9
9
|
import { exit, invoked } from '../../core/invoked.ts'
|
|
10
10
|
import { valuesIn } from '../../core/rows.ts'
|
|
11
11
|
import { findTree } from '../../core/tree.ts'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { bodyHash, parseGenerated } from
|
|
1
|
+
import { bodyHash, parseGenerated } from './determinism.js';
|
|
2
2
|
export function checkGenerated(expected, read, options = {}) {
|
|
3
3
|
const checks = [];
|
|
4
4
|
const expectedPaths = new Set(expected.map((file) => file.path));
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
2
|
import { argv, stderr, stdout } from 'node:process';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { CHECKED_BY, KINDS, LISTENS, SAID, WRITES, WRITTEN_BY, kindOf } from "../release.js";
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync } from '../../integrations/disk.js';
|
|
4
|
+
import { exit, invoked } from '../../core/invoked.js';
|
|
5
|
+
import { marked, valuesIn } from '../../core/rows.js';
|
|
6
|
+
import { ours } from '../../core/scope.js';
|
|
7
|
+
import { findTree, inTree } from '../../core/tree.js';
|
|
8
|
+
import { CHECKED_BY, KINDS, LISTENS, SAID, WRITES, WRITTEN_BY, kindOf } from '../release.js';
|
|
10
9
|
const TREE = findTree();
|
|
11
10
|
const MANIFEST = 'package.json';
|
|
11
|
+
const addressed = (rows) => rows.flatMap((one) => [...(one.at === undefined ? [] : [one.at]), ...addressed(one.derives ?? [])]);
|
|
12
12
|
const mark = (one) => marked([one.id ?? '', one.at ?? '']);
|
|
13
13
|
function releases() {
|
|
14
14
|
const at = inTree(TREE, 'derivation.ts');
|
|
@@ -22,45 +22,41 @@ function releases() {
|
|
|
22
22
|
return [];
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
function
|
|
26
|
-
const at = inTree(TREE, 'secrets.ts');
|
|
27
|
-
if (!existsSync(at))
|
|
28
|
-
return [];
|
|
25
|
+
function manager() {
|
|
29
26
|
try {
|
|
30
|
-
const held =
|
|
31
|
-
|
|
27
|
+
const held = JSON.parse(readFileSync(join(TREE.at, MANIFEST), 'utf8'));
|
|
28
|
+
const said = typeof held.packageManager === 'string' ? held.packageManager.split('@')[0] : undefined;
|
|
29
|
+
return said === undefined || said === '' ? 'npm' : said;
|
|
32
30
|
}
|
|
33
31
|
catch {
|
|
34
|
-
return
|
|
32
|
+
return 'npm';
|
|
35
33
|
}
|
|
36
34
|
}
|
|
37
35
|
function scripted() {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const scripts = held.scripts ?? {};
|
|
41
|
-
return {
|
|
42
|
-
build: scripts['build'] === undefined ? 'npm run build' : 'npm run build',
|
|
43
|
-
start: scripts['start'] === undefined ? 'npm start' : 'npm start',
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
return { build: 'npm run build', start: 'npm start' };
|
|
48
|
-
}
|
|
36
|
+
const tool = manager();
|
|
37
|
+
return { build: `${tool} run build`, start: tool === 'npm' ? 'npm start' : `${tool} start` };
|
|
49
38
|
}
|
|
50
39
|
function dockerfile(build, start) {
|
|
40
|
+
const tool = manager();
|
|
41
|
+
const corepack = tool === 'npm' ? [] : ['RUN corepack enable'];
|
|
42
|
+
const lock = tool === 'npm' ? 'package-lock.json*' : `${tool}-lock.yaml*`;
|
|
43
|
+
const first = tool === 'npm'
|
|
44
|
+
? 'RUN npm ci --omit=dev --ignore-scripts || npm install --omit=dev --ignore-scripts'
|
|
45
|
+
: `RUN ${tool} install --prod --frozen-lockfile --ignore-scripts || ${tool} install --prod --ignore-scripts`;
|
|
46
|
+
const all = tool === 'npm' ? 'RUN npm install --ignore-scripts' : `RUN ${tool} install --ignore-scripts`;
|
|
51
47
|
return [
|
|
52
|
-
'# GENERATED by thread — do not edit. It is derived from what this app declares.',
|
|
53
|
-
'',
|
|
54
48
|
'FROM node:22-slim AS build',
|
|
55
49
|
'WORKDIR /app',
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
...corepack,
|
|
51
|
+
`COPY package.json ${lock} ./`,
|
|
52
|
+
first,
|
|
58
53
|
'COPY . .',
|
|
59
|
-
|
|
54
|
+
all,
|
|
60
55
|
`RUN ${build}`,
|
|
61
56
|
'',
|
|
62
57
|
'FROM node:22-slim',
|
|
63
58
|
'WORKDIR /app',
|
|
59
|
+
...corepack,
|
|
64
60
|
'ENV NODE_ENV=production',
|
|
65
61
|
'COPY --from=build /app ./',
|
|
66
62
|
`EXPOSE ${String(LISTENS)}`,
|
|
@@ -68,28 +64,27 @@ function dockerfile(build, start) {
|
|
|
68
64
|
'',
|
|
69
65
|
].join('\n');
|
|
70
66
|
}
|
|
71
|
-
function compose(id
|
|
67
|
+
function compose(id) {
|
|
72
68
|
return [
|
|
73
|
-
'# GENERATED by thread — do not edit. It is derived from what this app declares.',
|
|
74
|
-
'',
|
|
75
69
|
'services:',
|
|
76
70
|
` ${id}:`,
|
|
77
71
|
' build: .',
|
|
78
72
|
' ports:',
|
|
79
73
|
` - "${String(LISTENS)}:${String(LISTENS)}"`,
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
74
|
+
'',
|
|
75
|
+
].join('\n');
|
|
76
|
+
}
|
|
77
|
+
function withheld() {
|
|
78
|
+
return [
|
|
79
|
+
'.thread',
|
|
80
|
+
'node_modules',
|
|
81
|
+
'.git',
|
|
86
82
|
'',
|
|
87
83
|
].join('\n');
|
|
88
84
|
}
|
|
89
85
|
function made() {
|
|
90
86
|
const found = new Map();
|
|
91
87
|
const rows = releases();
|
|
92
|
-
const secrets = named();
|
|
93
88
|
const { build, start } = scripted();
|
|
94
89
|
for (const one of rows) {
|
|
95
90
|
const id = one.id;
|
|
@@ -100,7 +95,8 @@ function made() {
|
|
|
100
95
|
continue;
|
|
101
96
|
if (kind === 'docker') {
|
|
102
97
|
found.set('Dockerfile', dockerfile(build, start));
|
|
103
|
-
found.set('compose.yaml', compose(id
|
|
98
|
+
found.set('compose.yaml', compose(id));
|
|
99
|
+
found.set('.dockerignore', withheld());
|
|
104
100
|
}
|
|
105
101
|
}
|
|
106
102
|
return found;
|
|
@@ -120,7 +116,12 @@ function run() {
|
|
|
120
116
|
`\`thread create release\` — it is ${KINDS.join(' or ')}, and the prefix on its id says which.\n`);
|
|
121
117
|
return 0;
|
|
122
118
|
}
|
|
123
|
-
const words =
|
|
119
|
+
const words = argv.slice(2).filter((one) => !one.startsWith('-'));
|
|
120
|
+
if (words[0] !== undefined && words[0] !== 'read') {
|
|
121
|
+
stderr.write('release: `' + words[0] + '` is not something this command does. `thread release` writes the release, and ' +
|
|
122
|
+
'`thread release read <mark>` prints one. Nothing was written.\n');
|
|
123
|
+
return 1;
|
|
124
|
+
}
|
|
124
125
|
if (words[0] === 'read') {
|
|
125
126
|
const which = words[1];
|
|
126
127
|
const one = rows.find((row) => mark(row) === which);
|
|
@@ -132,10 +133,10 @@ function run() {
|
|
|
132
133
|
}
|
|
133
134
|
const kind = kindOf(one.id ?? '');
|
|
134
135
|
stdout.write(`${String(one.id)} — ${kind === undefined ? 'a release of a kind this generator does not recognise' : SAID[kind]}\n`);
|
|
135
|
-
for (const
|
|
136
|
-
stdout.write(`\n${
|
|
136
|
+
for (const one of kind === undefined ? [] : WRITES[kind]) {
|
|
137
|
+
stdout.write(`\n${one.at} — ${one.describes}\n`);
|
|
137
138
|
try {
|
|
138
|
-
stdout.write(readFileSync(join(TREE.at,
|
|
139
|
+
stdout.write(readFileSync(join(TREE.at, one.at), 'utf8'));
|
|
139
140
|
}
|
|
140
141
|
catch {
|
|
141
142
|
stdout.write('(nothing is there)\n');
|
|
@@ -145,6 +146,16 @@ function run() {
|
|
|
145
146
|
}
|
|
146
147
|
const files = made();
|
|
147
148
|
const checking = argv.includes('--check');
|
|
149
|
+
const stated = new Set(addressed(rows));
|
|
150
|
+
const stray = [...files.keys()].filter((one) => !stated.has(one));
|
|
151
|
+
if (stray.length > 0) {
|
|
152
|
+
stderr.write(`release: this release produces ${stray.join(', ')}, and no row names ${stray.length === 1 ? 'it' : 'them'}. ` +
|
|
153
|
+
`Writing ${stray.length === 1 ? 'it' : 'them'} would leave a file this tree does not declare, and the descent ` +
|
|
154
|
+
'reports that three steps later as a file nobody can account for. Take the release out with `thread remove ' +
|
|
155
|
+
'<its id>` and declare it again — the maker writes one row per file this kind produces, so all of them arrive ' +
|
|
156
|
+
'together. Nothing was written.\n');
|
|
157
|
+
return 1;
|
|
158
|
+
}
|
|
148
159
|
const shipped = installed();
|
|
149
160
|
if (shipped.length > 0) {
|
|
150
161
|
stderr.write(`release: this app installs ${shipped.join(', ')} as a dependency, and what a host runs may hold ` +
|
|
@@ -176,8 +187,10 @@ function run() {
|
|
|
176
187
|
}
|
|
177
188
|
for (const [at, text] of files)
|
|
178
189
|
writeFileSync(join(TREE.at, at), text, 'utf8');
|
|
179
|
-
stdout.write(
|
|
180
|
-
|
|
190
|
+
stdout.write('release: wrote ' + [...files.keys()].join(', ') + ' — built and started by what this app\'s own manifest ' +
|
|
191
|
+
'declares, listening on ' + String(LISTENS) + '.\n' +
|
|
192
|
+
'release: no secret is named there. A secret is read from the sealed store at the moment it is used, and ' +
|
|
193
|
+
'naming it here would be telling whoever deploys this to put a credential in the environment instead.\n');
|
|
181
194
|
return 0;
|
|
182
195
|
}
|
|
183
196
|
if (invoked(import.meta.url))
|
|
@@ -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;
|