@prestack/thread 0.1.21 → 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 +109 -0
- package/dist/core/attach.js +21 -0
- package/dist/core/descend.js +6 -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/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.js +69 -10
- package/dist/integrations/pglite.js +13 -3
- package/dist/integrations/target.d.ts +3 -0
- package/dist/integrity/attach.js +1 -5
- package/dist/integrity/slopnators/sl_stale_path.js +10 -0
- 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.js +150 -50
- 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 -1185
- 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 -506
- 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 -606
- package/dist/integrations/declared.ts +0 -34
- 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 -672
- 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 -233
- 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 -229
- 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
|
@@ -12,7 +12,7 @@ import { argv, cwd, stderr, stdout } from 'node:process';
|
|
|
12
12
|
import { pathToFileURL } from 'node:url';
|
|
13
13
|
import { build, initialize, stop } from 'esbuild-wasm/esm/browser.js';
|
|
14
14
|
import { descend, reached } from '../../core/descend.js';
|
|
15
|
-
import { existsSync, readFileSync, realpathSync, statSync, writeFileSync } from '../../integrations/disk.js';
|
|
15
|
+
import { existsSync, readdirSync, readFileSync, realpathSync, statSync, writeFileSync } from '../../integrations/disk.js';
|
|
16
16
|
import { exit, invoked } from '../../core/invoked.js';
|
|
17
17
|
import { valuesIn } from '../../core/rows.js';
|
|
18
18
|
import { findTree } from '../../core/tree.js';
|
|
@@ -83,35 +83,110 @@ function exported(held, sub, conditions) {
|
|
|
83
83
|
}
|
|
84
84
|
return undefined;
|
|
85
85
|
}
|
|
86
|
-
function
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
function named(specifier) {
|
|
87
|
+
return specifier.split('/').slice(0, specifier.startsWith('@') ? 2 : 1).join('/');
|
|
88
|
+
}
|
|
89
|
+
function rooted(name, from, top) {
|
|
89
90
|
for (let at = from; inside(top, at); at = dirname(at)) {
|
|
90
91
|
const root = join(at, 'node_modules', name);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const held = JSON.parse(readFileSync(manifest, 'utf8'));
|
|
94
|
-
if (held.exports !== undefined) {
|
|
95
|
-
const found = exported(held.exports, sub, conditions);
|
|
96
|
-
return found === undefined ? undefined : located(join(root, found));
|
|
97
|
-
}
|
|
98
|
-
const main = typeof held.main === 'string' ? held.main : typeof held.module === 'string' ? held.module : 'index.js';
|
|
99
|
-
return located(join(root, sub === '.' ? main : sub));
|
|
100
|
-
}
|
|
92
|
+
if (filed(join(root, 'package.json')))
|
|
93
|
+
return root;
|
|
101
94
|
if (at === top)
|
|
102
95
|
return undefined;
|
|
103
96
|
}
|
|
104
97
|
return undefined;
|
|
105
98
|
}
|
|
106
|
-
|
|
99
|
+
function packaged(specifier, from, conditions, top) {
|
|
100
|
+
const name = named(specifier);
|
|
101
|
+
const sub = `.${specifier.slice(name.length)}`;
|
|
102
|
+
const root = rooted(name, from, top);
|
|
103
|
+
if (root === undefined)
|
|
104
|
+
return undefined;
|
|
105
|
+
const held = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'));
|
|
106
|
+
if (held.exports !== undefined) {
|
|
107
|
+
const found = exported(held.exports, sub, conditions);
|
|
108
|
+
return found === undefined ? undefined : located(join(root, found));
|
|
109
|
+
}
|
|
110
|
+
const main = typeof held.main === 'string' ? held.main : typeof held.module === 'string' ? held.module : 'index.js';
|
|
111
|
+
return located(join(root, sub === '.' ? main : sub));
|
|
112
|
+
}
|
|
113
|
+
function binary(at) {
|
|
114
|
+
const bytes = readFileSync(at, 'latin1');
|
|
115
|
+
if (bytes.length < 4)
|
|
116
|
+
return false;
|
|
117
|
+
const byte = (i) => bytes.charCodeAt(i);
|
|
118
|
+
if (byte(0) === 0x7f && bytes.slice(1, 4) === 'ELF')
|
|
119
|
+
return true;
|
|
120
|
+
if (byte(0) === 0x4d && byte(1) === 0x5a)
|
|
121
|
+
return true;
|
|
122
|
+
if (bytes.slice(0, 4) === '\0asm')
|
|
123
|
+
return true;
|
|
124
|
+
if (byte(1) === 0xfa && byte(2) === 0xed && byte(3) === 0xfe && (byte(0) === 0xce || byte(0) === 0xcf))
|
|
125
|
+
return true;
|
|
126
|
+
if (byte(0) === 0xfe && byte(1) === 0xed && byte(2) === 0xfa && (byte(3) === 0xce || byte(3) === 0xcf))
|
|
127
|
+
return true;
|
|
128
|
+
if (byte(0) === 0xca && byte(1) === 0xfe && byte(2) === 0xba && (byte(3) === 0xbe || byte(3) === 0xbf))
|
|
129
|
+
return true;
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
function owned(root) {
|
|
133
|
+
const found = [];
|
|
134
|
+
const seen = new Set();
|
|
135
|
+
const walk = (at) => {
|
|
136
|
+
const real = realpathSync(at);
|
|
137
|
+
if (seen.has(real))
|
|
138
|
+
return;
|
|
139
|
+
seen.add(real);
|
|
140
|
+
for (const one of readdirSync(at)) {
|
|
141
|
+
if (one === 'node_modules')
|
|
142
|
+
continue;
|
|
143
|
+
const path = join(at, one);
|
|
144
|
+
const held = statSync(path, { throwIfNoEntry: false });
|
|
145
|
+
if (held?.isDirectory() === true)
|
|
146
|
+
walk(path);
|
|
147
|
+
else if (held?.isFile() === true)
|
|
148
|
+
found.push(path);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
walk(root);
|
|
152
|
+
return found;
|
|
153
|
+
}
|
|
154
|
+
const staying = new Map();
|
|
155
|
+
function installed(root, top, visiting = new Set()) {
|
|
156
|
+
const cached = staying.get(root);
|
|
157
|
+
if (cached !== undefined)
|
|
158
|
+
return cached;
|
|
159
|
+
if (visiting.has(root))
|
|
160
|
+
return false;
|
|
161
|
+
visiting.add(root);
|
|
162
|
+
let decided = owned(root).some(binary);
|
|
163
|
+
if (!decided) {
|
|
164
|
+
const held = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'));
|
|
165
|
+
const names = Object.keys(held.optionalDependencies ?? {});
|
|
166
|
+
decided = names.some((one) => {
|
|
167
|
+
const found = rooted(one, root, top);
|
|
168
|
+
return found !== undefined && installed(found, top, visiting);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
visiting.delete(root);
|
|
172
|
+
staying.set(root, decided);
|
|
173
|
+
return decided;
|
|
174
|
+
}
|
|
175
|
+
const folder = (outside, top, keeping) => ({
|
|
107
176
|
name: 'thread-folder',
|
|
108
177
|
setup(held) {
|
|
109
178
|
held.onResolve({ filter: /.*/ }, (args) => {
|
|
110
179
|
const bare = !args.path.startsWith('.') && !isAbsolute(args.path);
|
|
111
180
|
if (args.path.startsWith('node:') || RUNTIME.has(args.path))
|
|
112
181
|
return { path: args.path, external: true, sideEffects: false };
|
|
113
|
-
if (bare && outside)
|
|
114
|
-
|
|
182
|
+
if (bare && outside) {
|
|
183
|
+
const name = named(args.path);
|
|
184
|
+
const root = rooted(name, args.resolveDir, top);
|
|
185
|
+
if (root !== undefined && installed(root, top)) {
|
|
186
|
+
keeping?.add(name);
|
|
187
|
+
return { path: args.path, external: true };
|
|
188
|
+
}
|
|
189
|
+
}
|
|
115
190
|
const conditions = args.kind === 'require-call' || args.kind === 'require-resolve' ? REQUIRED : IMPORTED;
|
|
116
191
|
const path = resolve(args.resolveDir, args.path);
|
|
117
192
|
const found = bare ? packaged(args.path, args.resolveDir, conditions, top) : inside(top, path) ? located(path) : undefined;
|
|
@@ -141,13 +216,13 @@ export async function bundle(options) {
|
|
|
141
216
|
hosted.self ??= globalThis;
|
|
142
217
|
await initialize({ wasmModule: compiled, worker: false });
|
|
143
218
|
try {
|
|
144
|
-
const { packages, plugins, absWorkingDir = cwd(), ...rest } = options;
|
|
219
|
+
const { packages, plugins, keeping, absWorkingDir = cwd(), ...rest } = options;
|
|
145
220
|
const made = await build({
|
|
146
221
|
absWorkingDir,
|
|
147
222
|
...rest,
|
|
148
223
|
bundle: true,
|
|
149
224
|
write: false,
|
|
150
|
-
plugins: [...(plugins ?? []), folder(packages === 'external', absWorkingDir)],
|
|
225
|
+
plugins: [...(plugins ?? []), folder(packages === 'external', absWorkingDir, keeping)],
|
|
151
226
|
});
|
|
152
227
|
const text = made.outputFiles?.[0]?.text;
|
|
153
228
|
if (text === undefined)
|
|
@@ -323,13 +398,14 @@ async function main() {
|
|
|
323
398
|
}
|
|
324
399
|
const forBrowser = browsing(entry);
|
|
325
400
|
const refusals = forBrowser ? withheld(pass) : new Map();
|
|
401
|
+
const keeping = forBrowser ? undefined : new Set();
|
|
326
402
|
let held;
|
|
327
403
|
try {
|
|
328
404
|
held = await bundle({
|
|
329
405
|
entryPoints: [resolve(ROOT, entry)],
|
|
330
406
|
format: 'esm',
|
|
331
407
|
platform: forBrowser ? 'browser' : 'node',
|
|
332
|
-
...(
|
|
408
|
+
...(keeping === undefined ? {} : { packages: 'external', keeping }),
|
|
333
409
|
outfile: at,
|
|
334
410
|
plugins: [declared(), ...(refusals.size === 0 ? [] : [withholding(refusals)]), ...compiling],
|
|
335
411
|
logLevel: 'silent',
|
|
@@ -339,16 +415,21 @@ async function main() {
|
|
|
339
415
|
stderr.write(`build: ${out} was not written — ${thrown instanceof Error ? thrown.message : String(thrown)}\n`);
|
|
340
416
|
exit(1);
|
|
341
417
|
}
|
|
418
|
+
const installs = keeping === undefined
|
|
419
|
+
? ''
|
|
420
|
+
: keeping.size === 0
|
|
421
|
+
? ' Every package it imports is compiled in, so npm installs nothing to run it.'
|
|
422
|
+
: ` It still needs npm to install ${String(keeping.size)} package${keeping.size === 1 ? '' : 's'}: ${[...keeping].sort().join(', ')}. Each one loads a native file or starts a program that only exists once npm installs it.`;
|
|
342
423
|
if (checking) {
|
|
343
424
|
if (held !== before) {
|
|
344
425
|
stderr.write(`build: ${out} is not what ${BUILDS} writes. A built artifact has no author — run \`${BUILDS}\` and commit the result.\n`);
|
|
345
426
|
exit(1);
|
|
346
427
|
}
|
|
347
|
-
stdout.write(`build: ${out} is up to date — ${String(new Set(reached()).size)} declared file(s) reachable
|
|
428
|
+
stdout.write(`build: ${out} is up to date — ${String(new Set(reached()).size)} declared file(s) reachable.${installs}\n`);
|
|
348
429
|
continue;
|
|
349
430
|
}
|
|
350
431
|
writeFileSync(at, held, 'utf8');
|
|
351
|
-
stdout.write(`build: wrote ${out} from ${entry} — ${String(new Set(reached()).size)} declared file(s) reachable
|
|
432
|
+
stdout.write(`build: wrote ${out} from ${entry} — ${String(new Set(reached()).size)} declared file(s) reachable.${installs}\n`);
|
|
352
433
|
}
|
|
353
434
|
}
|
|
354
435
|
if (invoked(import.meta.url))
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
2
|
import { argv, stderr, stdout } from 'node:process';
|
|
3
|
-
import { existsSync, readFileSync, writeFileSync } from '../../integrations/disk.js';
|
|
3
|
+
import { existsSync, readFileSync, readdirSync, writeFileSync } from '../../integrations/disk.js';
|
|
4
|
+
import { COPY_AT, PROGRAM } from '../../integrations/cli.js';
|
|
5
|
+
import { VAULT_DIR } from '../../integrations/vault.js';
|
|
4
6
|
import { exit, invoked } from '../../core/invoked.js';
|
|
5
|
-
import {
|
|
7
|
+
import { markOf, valuesIn } from '../../core/rows.js';
|
|
6
8
|
import { ours } from '../../core/scope.js';
|
|
7
|
-
import { findTree, inTree } from '../../core/tree.js';
|
|
9
|
+
import { declaresUi, findTree, inTree } from '../../core/tree.js';
|
|
10
|
+
import { SERVER_OUT } from '../../operations/capabilities.js';
|
|
8
11
|
import { CHECKED_BY, KINDS, LISTENS, SAID, WRITES, WRITTEN_BY, kindOf } from '../release.js';
|
|
9
12
|
const TREE = findTree();
|
|
10
13
|
const MANIFEST = 'package.json';
|
|
14
|
+
const RECEIPT = join(VAULT_DIR, 'gate.json');
|
|
15
|
+
const ROUTE = /^app\/(?:.+\/)?route\.ts$/;
|
|
11
16
|
const addressed = (rows) => rows.flatMap((one) => [...(one.at === undefined ? [] : [one.at]), ...addressed(one.derives ?? [])]);
|
|
12
|
-
const mark = (one) =>
|
|
17
|
+
const mark = (one) => markOf(one);
|
|
13
18
|
function releases() {
|
|
14
19
|
const at = inTree(TREE, 'derivation.ts');
|
|
15
20
|
if (!existsSync(at))
|
|
@@ -32,35 +37,73 @@ function manager() {
|
|
|
32
37
|
return 'npm';
|
|
33
38
|
}
|
|
34
39
|
}
|
|
35
|
-
function
|
|
36
|
-
const
|
|
37
|
-
|
|
40
|
+
function served() {
|
|
41
|
+
const found = new Set();
|
|
42
|
+
const walk = (held) => {
|
|
43
|
+
if (held === null || typeof held !== 'object')
|
|
44
|
+
return;
|
|
45
|
+
const row = held;
|
|
46
|
+
const routes = Array.isArray(row.derives) ? row.derives.filter((one) => ROUTE.test(one.at ?? '')) : [];
|
|
47
|
+
if (typeof row.at === 'string' && !row.at.startsWith(`${TREE.name}/`) && routes.length > 0)
|
|
48
|
+
found.add(row.at);
|
|
49
|
+
for (const one of Object.values(held))
|
|
50
|
+
walk(one);
|
|
51
|
+
};
|
|
52
|
+
for (const name of readdirSync(TREE.dir).filter((one) => one.endsWith('.ts')).sort()) {
|
|
53
|
+
walk(valuesIn(readFileSync(join(TREE.dir, name), 'utf8')));
|
|
54
|
+
}
|
|
55
|
+
return [...found].sort();
|
|
56
|
+
}
|
|
57
|
+
function runsThread() {
|
|
58
|
+
const at = inTree(TREE, 'targets.ts');
|
|
59
|
+
if (!existsSync(at))
|
|
60
|
+
return false;
|
|
61
|
+
const held = valuesIn(readFileSync(at, 'utf8'));
|
|
62
|
+
return (held.TARGETS ?? []).some((one) => one.id === PROGRAM);
|
|
38
63
|
}
|
|
39
|
-
function dockerfile(
|
|
64
|
+
function dockerfile() {
|
|
40
65
|
const tool = manager();
|
|
41
66
|
const corepack = tool === 'npm' ? [] : ['RUN corepack enable'];
|
|
42
67
|
const lock = tool === 'npm' ? 'package-lock.json*' : `${tool}-lock.yaml*`;
|
|
43
|
-
const
|
|
44
|
-
? 'RUN npm ci --
|
|
45
|
-
: `RUN ${tool} install --
|
|
46
|
-
const
|
|
68
|
+
const install = tool === 'npm'
|
|
69
|
+
? 'RUN npm ci --ignore-scripts || npm install --ignore-scripts'
|
|
70
|
+
: `RUN ${tool} install --frozen-lockfile --ignore-scripts || ${tool} install --ignore-scripts`;
|
|
71
|
+
const thread = runsThread();
|
|
72
|
+
const carried = [RECEIPT, ...served(), ...(thread ? [COPY_AT] : [])];
|
|
73
|
+
const running = ['WORKDIR /app', 'ENV NODE_ENV=production', 'ENV HOSTNAME=0.0.0.0', `ENV PORT=${String(LISTENS)}`];
|
|
74
|
+
const ending = [...(thread ? [`RUN mkdir -p ${TREE.name}`] : []), `EXPOSE ${String(LISTENS)}`];
|
|
75
|
+
if (!declaresUi(TREE)) {
|
|
76
|
+
const production = tool === 'npm'
|
|
77
|
+
? 'RUN npm ci --omit=dev --ignore-scripts || npm install --omit=dev --ignore-scripts'
|
|
78
|
+
: `RUN ${tool} install --prod --frozen-lockfile --ignore-scripts || ${tool} install --prod --ignore-scripts`;
|
|
79
|
+
return [
|
|
80
|
+
'FROM node:22-slim',
|
|
81
|
+
...running,
|
|
82
|
+
...corepack,
|
|
83
|
+
`COPY package.json ${lock} ./`,
|
|
84
|
+
production,
|
|
85
|
+
...[SERVER_OUT, ...carried].map((one) => `COPY ${one} ./${one}`),
|
|
86
|
+
...ending,
|
|
87
|
+
`CMD ${JSON.stringify(['node', SERVER_OUT])}`,
|
|
88
|
+
'',
|
|
89
|
+
].join('\n');
|
|
90
|
+
}
|
|
47
91
|
return [
|
|
48
92
|
'FROM node:22-slim AS build',
|
|
49
93
|
'WORKDIR /app',
|
|
50
94
|
...corepack,
|
|
51
95
|
`COPY package.json ${lock} ./`,
|
|
52
|
-
|
|
96
|
+
install,
|
|
53
97
|
'COPY . .',
|
|
54
|
-
|
|
55
|
-
`RUN ${build}`,
|
|
98
|
+
`RUN ${tool} run build`,
|
|
56
99
|
'',
|
|
57
100
|
'FROM node:22-slim',
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
'
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
`CMD ${JSON.stringify(
|
|
101
|
+
...running,
|
|
102
|
+
'COPY --from=build /app/.next/standalone ./',
|
|
103
|
+
'COPY --from=build /app/.next/static ./.next/static',
|
|
104
|
+
...carried.map((one) => `COPY --from=build /app/${one} ./${one}`),
|
|
105
|
+
...ending,
|
|
106
|
+
`CMD ${JSON.stringify(['node', 'server.js'])}`,
|
|
64
107
|
'',
|
|
65
108
|
].join('\n');
|
|
66
109
|
}
|
|
@@ -76,7 +119,10 @@ function compose(id) {
|
|
|
76
119
|
}
|
|
77
120
|
function withheld() {
|
|
78
121
|
return [
|
|
79
|
-
|
|
122
|
+
VAULT_DIR,
|
|
123
|
+
`!${RECEIPT}`,
|
|
124
|
+
...(runsThread() ? [`!${COPY_AT}`] : []),
|
|
125
|
+
'.next',
|
|
80
126
|
'node_modules',
|
|
81
127
|
'.git',
|
|
82
128
|
'',
|
|
@@ -85,7 +131,6 @@ function withheld() {
|
|
|
85
131
|
function made() {
|
|
86
132
|
const found = new Map();
|
|
87
133
|
const rows = releases();
|
|
88
|
-
const { build, start } = scripted();
|
|
89
134
|
for (const one of rows) {
|
|
90
135
|
const id = one.id;
|
|
91
136
|
if (id === undefined)
|
|
@@ -94,7 +139,7 @@ function made() {
|
|
|
94
139
|
if (kind === undefined)
|
|
95
140
|
continue;
|
|
96
141
|
if (kind === 'docker') {
|
|
97
|
-
found.set('Dockerfile', dockerfile(
|
|
142
|
+
found.set('Dockerfile', dockerfile());
|
|
98
143
|
found.set('compose.yaml', compose(id));
|
|
99
144
|
found.set('.dockerignore', withheld());
|
|
100
145
|
}
|
|
@@ -187,8 +232,11 @@ function run() {
|
|
|
187
232
|
}
|
|
188
233
|
for (const [at, text] of files)
|
|
189
234
|
writeFileSync(join(TREE.at, at), text, 'utf8');
|
|
190
|
-
stdout.write('release: wrote ' + [...files.keys()].join(', ') + ' —
|
|
191
|
-
|
|
235
|
+
stdout.write('release: wrote ' + [...files.keys()].join(', ') + ' — ' +
|
|
236
|
+
(declaresUi(TREE)
|
|
237
|
+
? 'built by the build this app\'s own manifest declares, and started by `node server.js` from what that build compiled'
|
|
238
|
+
: 'started by `node ' + SERVER_OUT + '`, the server `thread build` compiled into this tree, beside only the packages installed for production') +
|
|
239
|
+
', listening on ' + String(LISTENS) + '.\n' +
|
|
192
240
|
'release: no secret is named there. A secret is read from the sealed store at the moment it is used, and ' +
|
|
193
241
|
'naming it here would be telling whoever deploys this to put a credential in the environment instead.\n');
|
|
194
242
|
return 0;
|
|
@@ -4,7 +4,7 @@ export const WRITES = {
|
|
|
4
4
|
docker: [
|
|
5
5
|
{
|
|
6
6
|
at: 'Dockerfile',
|
|
7
|
-
describes: 'How this app becomes an image and what starts it inside one
|
|
7
|
+
describes: 'How this app becomes an image, and what starts it inside one. An app that declares `ui` is built inside the image by the build command its own manifest declares, with the package manager that manifest names, and started with `node server.js` from what Next compiled. One that does not builds nothing there: it is started with Node on the server `thread build` compiled into this tree, beside only the packages its manifest installs for production. Either way the image keeps the files its routes read from disk, the receipt of the gate that passed, and the compiled thread command when this app runs one. Nothing of the framework\'s source goes in either way.',
|
|
8
8
|
},
|
|
9
9
|
{
|
|
10
10
|
at: 'compose.yaml',
|
|
@@ -12,13 +12,13 @@ export const WRITES = {
|
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
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.',
|
|
15
|
+
describes: 'What a build of this image must never carry out of this directory: the sealed store and the key that opens it, an earlier build, the installed packages, and the history. From the sealed store\'s folder it lets through only the receipt of the gate that passed and, when this app runs the thread command, the compiled copy of that command. Neither holds a secret. Without it the build copies everything beside it, and every sealed value goes into the image and into whoever pulls it.',
|
|
16
16
|
},
|
|
17
17
|
],
|
|
18
18
|
};
|
|
19
19
|
export const LISTENS = 3000;
|
|
20
20
|
export const SAID = {
|
|
21
|
-
docker: 'A container image built from this app and the compose file that runs it. It
|
|
21
|
+
docker: 'A container image built from this app and the compose file that runs it. It needs no account and no network to be proven, so an app can be taken end to end with it before anybody has chosen where it really lives. What it holds is derived: the server, on the port it listens on, with the files its routes read from disk, the receipt of the gate that passed, and the compiled thread command when this app runs one. An app that declares `ui` is served by what Next compiles, started with `node server.js`; one that does not is served by the server `thread build` compiled into this tree, started with Node beside only the packages its manifest installs for production. It names no secret, because a value is typed by a person and read from the sealed store where it is used.',
|
|
22
22
|
};
|
|
23
23
|
export const kindOf = (id) => KINDS.find((one) => id.startsWith(PREFIXES[one]));
|
|
24
24
|
export const WRITTEN_BY = 'thread release';
|
package/dist/integrations/cli.js
CHANGED
|
@@ -263,6 +263,46 @@ function forgets(one, asked) {
|
|
|
263
263
|
one.known.delete(key);
|
|
264
264
|
}
|
|
265
265
|
}
|
|
266
|
+
const AHEAD = 32;
|
|
267
|
+
const upOf = (at) => (at.includes('/') ? at.slice(0, at.lastIndexOf('/')) : '');
|
|
268
|
+
const nameOf = (at) => at.slice(at.lastIndexOf('/') + 1);
|
|
269
|
+
const inside = (at, name) => (at === '' ? name : at + '/' + name);
|
|
270
|
+
function listedAt(one, at) {
|
|
271
|
+
const held = one.known.get(told({ order: 'list', at }))?.found;
|
|
272
|
+
return Array.isArray(held) ? held : [];
|
|
273
|
+
}
|
|
274
|
+
function realOf(one, at) {
|
|
275
|
+
const held = one.known.get(told({ order: 'real', at }));
|
|
276
|
+
if (held !== undefined || at === '')
|
|
277
|
+
return held;
|
|
278
|
+
const entry = listedAt(one, upOf(at)).find((each) => each.name === nameOf(at));
|
|
279
|
+
if (entry === undefined || entry.kind === 'other')
|
|
280
|
+
return undefined;
|
|
281
|
+
const above = realOf(one, upOf(at));
|
|
282
|
+
return typeof above?.at === 'string' ? { answered: 'real', at: above.at + '/' + nameOf(at) } : undefined;
|
|
283
|
+
}
|
|
284
|
+
function aheadOf(one, asked) {
|
|
285
|
+
if (asked.order === 'real')
|
|
286
|
+
return asked.at === '' || one.known.has(told({ order: 'real', at: '' })) ? [] : [{ order: 'real', at: '', ahead: true }];
|
|
287
|
+
const name = nameOf(asked.at);
|
|
288
|
+
const dot = name.indexOf('.');
|
|
289
|
+
const reading = asked.order === 'read' && dot > 0 && asked.at.split('/').includes(INSTALLED);
|
|
290
|
+
if (!reading && asked.order !== 'stat')
|
|
291
|
+
return [];
|
|
292
|
+
const suffix = reading ? name.slice(dot) : '';
|
|
293
|
+
const up = upOf(asked.at);
|
|
294
|
+
const found = [];
|
|
295
|
+
for (const each of listedAt(one, up)) {
|
|
296
|
+
if (found.length === AHEAD)
|
|
297
|
+
break;
|
|
298
|
+
if (each.kind !== 'file' || each.name === name || !each.name.endsWith(suffix))
|
|
299
|
+
continue;
|
|
300
|
+
const order = { order: asked.order, at: inside(up, each.name), ahead: true };
|
|
301
|
+
if (!one.known.has(told(order)))
|
|
302
|
+
found.push(order);
|
|
303
|
+
}
|
|
304
|
+
return found;
|
|
305
|
+
}
|
|
266
306
|
const plainly = (one) => one.order + ' ' + (one.at === '' ? '.' : one.at);
|
|
267
307
|
const outside = (root, at) => {
|
|
268
308
|
const step = relative(root, at);
|
|
@@ -315,11 +355,22 @@ function watching(one) {
|
|
|
315
355
|
reply(one.dir, short, known);
|
|
316
356
|
continue;
|
|
317
357
|
}
|
|
358
|
+
const derived = asked.order === 'real' ? realOf(one, asked.at) : undefined;
|
|
359
|
+
if (derived !== undefined) {
|
|
360
|
+
reply(one.dir, short, derived);
|
|
361
|
+
kept(one, asked, derived);
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
318
364
|
if (!READS.has(asked.order))
|
|
319
365
|
forgets(one, asked);
|
|
320
366
|
const due = one.replaying.shift();
|
|
321
367
|
if (due !== undefined) {
|
|
322
368
|
if (told(due.order) === told(asked)) {
|
|
369
|
+
while (one.replaying[0]?.order.ahead === true) {
|
|
370
|
+
const extra = one.replaying.shift();
|
|
371
|
+
if (extra !== undefined)
|
|
372
|
+
kept(one, extra.order, extra.answered);
|
|
373
|
+
}
|
|
323
374
|
reply(one.dir, short, due.answered);
|
|
324
375
|
kept(one, asked, due.answered);
|
|
325
376
|
continue;
|
|
@@ -334,7 +385,8 @@ function watching(one) {
|
|
|
334
385
|
}
|
|
335
386
|
one.pending = short;
|
|
336
387
|
one.asking = asked;
|
|
337
|
-
|
|
388
|
+
one.ahead = aheadOf(one, asked);
|
|
389
|
+
hand(one, still(one, [asked, ...one.ahead]));
|
|
338
390
|
}
|
|
339
391
|
}, TICK);
|
|
340
392
|
}
|
|
@@ -362,11 +414,11 @@ function next(one, within) {
|
|
|
362
414
|
}, Math.max(1_000, within - MARGIN));
|
|
363
415
|
});
|
|
364
416
|
}
|
|
365
|
-
function begun(from, word, args, root, hears, called, recording = []) {
|
|
417
|
+
function begun(from, word, args, root, hears, called, recording = [], stash) {
|
|
366
418
|
const of = called ?? randomBytes(6).toString('hex');
|
|
367
419
|
const dir = join(tmpdir(), SERVED, randomBytes(6).toString('hex'));
|
|
368
420
|
writeFileSync(join(dir, 'channel'), '', 'utf8');
|
|
369
|
-
const one = { of, dir, root, out: '', err: '', why: '', pending: '', waiting: [], parked: [], replaying: [...recording], handed: recording.length, known: new Map() };
|
|
421
|
+
const one = { of, dir, root, out: '', err: '', why: '', pending: '', waiting: [], parked: [], replaying: [...recording], handed: recording.length, known: new Map(), ahead: [], ...(stash === undefined ? {} : { stash }) };
|
|
370
422
|
const child = spawn(execPath, [...from.words, word, ...args], {
|
|
371
423
|
cwd: from.own,
|
|
372
424
|
shell: false,
|
|
@@ -397,6 +449,7 @@ function counted(one, held) {
|
|
|
397
449
|
one.last = held;
|
|
398
450
|
return held;
|
|
399
451
|
}
|
|
452
|
+
const stashing = (one, held) => (one.stash === undefined ? held : { ...held, stashed: one.stash });
|
|
400
453
|
async function served(word, args, within, how) {
|
|
401
454
|
const of = how?.of;
|
|
402
455
|
if (of !== undefined) {
|
|
@@ -411,20 +464,26 @@ async function served(word, args, within, how) {
|
|
|
411
464
|
const from = startable();
|
|
412
465
|
if (typeof from === 'string')
|
|
413
466
|
return nowhere(from);
|
|
414
|
-
const again = begun(from, word, args, root, how?.hears, of, recording);
|
|
415
|
-
return counted(again, await next(again, within));
|
|
467
|
+
const again = begun(from, word, args, root, how?.hears, of, recording, how?.stash);
|
|
468
|
+
return stashing(again, counted(again, await next(again, within)));
|
|
416
469
|
}
|
|
417
470
|
const answering = how?.answering;
|
|
418
471
|
if (answering !== undefined && answering < one.handed && one.last !== undefined)
|
|
419
|
-
return one.last;
|
|
420
|
-
const given =
|
|
472
|
+
return stashing(one, one.last);
|
|
473
|
+
const [given, ...rest] = how?.answered ?? [];
|
|
421
474
|
if (one.pending !== '' && given !== undefined) {
|
|
475
|
+
one.ahead.forEach((order, index) => {
|
|
476
|
+
const held = rest[index];
|
|
477
|
+
if (held !== undefined)
|
|
478
|
+
kept(one, order, held);
|
|
479
|
+
});
|
|
480
|
+
one.ahead = [];
|
|
422
481
|
reply(one.dir, one.pending, given);
|
|
423
482
|
if (one.asking !== undefined)
|
|
424
483
|
kept(one, one.asking, given);
|
|
425
484
|
one.pending = '';
|
|
426
485
|
}
|
|
427
|
-
return counted(one, await next(one, within));
|
|
486
|
+
return stashing(one, counted(one, await next(one, within)));
|
|
428
487
|
}
|
|
429
488
|
const root = how?.at ?? '';
|
|
430
489
|
if (root === '')
|
|
@@ -432,8 +491,8 @@ async function served(word, args, within, how) {
|
|
|
432
491
|
const from = startable();
|
|
433
492
|
if (typeof from === 'string')
|
|
434
493
|
return nowhere(from);
|
|
435
|
-
const fresh = begun(from, word, args, root, how?.hears);
|
|
436
|
-
return counted(fresh, await next(fresh, within));
|
|
494
|
+
const fresh = begun(from, word, args, root, how?.hears, undefined, [], how?.stash);
|
|
495
|
+
return stashing(fresh, counted(fresh, await next(fresh, within)));
|
|
437
496
|
}
|
|
438
497
|
export function running(name, subcommands, at) {
|
|
439
498
|
const out = {};
|
|
@@ -52,14 +52,24 @@ export async function shapeOf(sql) {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
export function standing(held) {
|
|
55
|
-
const store = storing({ ...held, at: 'memory://'
|
|
55
|
+
const store = storing({ ...held, at: 'memory://' });
|
|
56
56
|
const keeps = Object.keys(held.tables);
|
|
57
57
|
return {
|
|
58
58
|
keeps,
|
|
59
59
|
store,
|
|
60
60
|
async seed(actor, rows) {
|
|
61
|
-
for (const one of rows)
|
|
61
|
+
for (const one of rows) {
|
|
62
|
+
const by = held.address[one.entity];
|
|
63
|
+
const key = by === undefined ? undefined : one.row[by];
|
|
64
|
+
if (by !== undefined && (typeof key === 'string' || typeof key === 'number')) {
|
|
65
|
+
const there = await store.list(actor, one.entity, { where: { [by]: key }, limit: 1 });
|
|
66
|
+
if (there.length > 0) {
|
|
67
|
+
await store.update(actor, one.entity, key, one.row);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
62
71
|
await store.insert(actor, one.entity, one.row);
|
|
72
|
+
}
|
|
63
73
|
},
|
|
64
74
|
async taken(actor) {
|
|
65
75
|
const found = {};
|
|
@@ -83,7 +93,7 @@ export function storing(held) {
|
|
|
83
93
|
const found = held.address[entity];
|
|
84
94
|
if (found === undefined) {
|
|
85
95
|
throw new Error(entity + ' declares nothing that identifies one of its rows, so a row of it cannot be addressed here. ' +
|
|
86
|
-
'
|
|
96
|
+
'Name the value that does: give `thread edit ' + entity + ' --must` its invariants again with one more, unique over that value alone.');
|
|
87
97
|
}
|
|
88
98
|
return found;
|
|
89
99
|
};
|
|
@@ -68,6 +68,7 @@ export interface Order {
|
|
|
68
68
|
readonly said?: string;
|
|
69
69
|
readonly mode?: number;
|
|
70
70
|
readonly words?: readonly string[];
|
|
71
|
+
readonly ahead?: boolean;
|
|
71
72
|
}
|
|
72
73
|
export interface Answer {
|
|
73
74
|
readonly answered: string;
|
|
@@ -87,6 +88,7 @@ export interface How {
|
|
|
87
88
|
readonly answered?: readonly Answer[];
|
|
88
89
|
readonly recording?: readonly Recorded[];
|
|
89
90
|
readonly answering?: number;
|
|
91
|
+
readonly stash?: unknown;
|
|
90
92
|
}
|
|
91
93
|
export interface Ran {
|
|
92
94
|
readonly there: boolean;
|
|
@@ -99,6 +101,7 @@ export interface Ran {
|
|
|
99
101
|
readonly of?: string;
|
|
100
102
|
readonly asks?: readonly Order[];
|
|
101
103
|
readonly lost?: string;
|
|
104
|
+
readonly stashed?: unknown;
|
|
102
105
|
}
|
|
103
106
|
export type Running<C extends string = string> = Readonly<Record<C, (args: readonly string[], shows?: boolean | 'errors' | 'tee', within?: number, how?: How) => Promise<Ran>>>;
|
|
104
107
|
export type Calling<C extends string = string> = {
|
package/dist/integrity/attach.js
CHANGED
|
@@ -116,11 +116,7 @@ export const ATTACH = {
|
|
|
116
116
|
{ file: 'rules.ts', source: RULES_SOURCE },
|
|
117
117
|
{ file: 'gate.ts', source: GATE_SOURCE },
|
|
118
118
|
],
|
|
119
|
-
ignores: ['.thread/', '
|
|
120
|
-
scripts: {
|
|
121
|
-
build: 'next build',
|
|
122
|
-
start: 'next start',
|
|
123
|
-
},
|
|
119
|
+
ignores: ['.thread/', 'node_modules/', 'tsconfig.tsbuildinfo'],
|
|
124
120
|
needs: {
|
|
125
121
|
'@types/node': '^24.0.0',
|
|
126
122
|
typescript: '^6.0.0',
|
|
@@ -76,6 +76,9 @@ export const slopnator = {
|
|
|
76
76
|
return false;
|
|
77
77
|
if (derived().has(path))
|
|
78
78
|
return false;
|
|
79
|
+
const folder = path.slice(0, path.lastIndexOf('/'));
|
|
80
|
+
if (statSync(resolve(ROOT, folder), { throwIfNoEntry: false })?.isDirectory() !== true)
|
|
81
|
+
return false;
|
|
79
82
|
return `\`${value}\` is not on disk`;
|
|
80
83
|
},
|
|
81
84
|
proves: {
|
|
@@ -152,6 +155,13 @@ export const slopnator = {
|
|
|
152
155
|
],
|
|
153
156
|
at: 'probe.tsx',
|
|
154
157
|
},
|
|
158
|
+
{
|
|
159
|
+
files: [
|
|
160
|
+
{ at: 'docs/_probe_there.md', source: 'there\n' },
|
|
161
|
+
{ at: 'probe.tsx', source: "const at = 'docs/elsewhere/entry.ts'\n" },
|
|
162
|
+
],
|
|
163
|
+
at: 'probe.tsx',
|
|
164
|
+
},
|
|
155
165
|
"const at = 'threads/'",
|
|
156
166
|
"const said = 'a sentence about packages/core/integrity/src/constraint.ts and nothing else'",
|
|
157
167
|
{
|
|
@@ -17,8 +17,9 @@ export function undeclared(answered, offers, which) {
|
|
|
17
17
|
return (`this app declares no ${which === 'roles' ? 'role' : 'entitlement'} called ${stray.map((one) => `\`${one}\``).join(', ')} — ` +
|
|
18
18
|
(offers.length === 0
|
|
19
19
|
? `it declares none at all. A ${which === 'roles' ? 'role' : 'entitlement'} is one of the words the value an ` +
|
|
20
|
-
'entity names as saying what a caller may do is held to. Declare them
|
|
21
|
-
'
|
|
20
|
+
'entity names as saying what a caller may do is held to. Declare them on that entity: give ' +
|
|
21
|
+
'`thread edit <entity> --holds` its values again with that one in the `choice` format and its options stated, ' +
|
|
22
|
+
`and name it as \`${which}\` in \`thread edit <entity> --actor\``
|
|
22
23
|
: `it declares ${offers.map((one) => `\`${one}\``).join(', ')}`));
|
|
23
24
|
}
|
|
24
25
|
export const keyIn = (one) => (one.must ?? []).flatMap((each) => (each.unique?.length === 1 ? [each.unique[0]] : []))[0];
|
|
@@ -9,6 +9,8 @@ export interface Defaults extends Threaded {
|
|
|
9
9
|
readonly live?: readonly Surface[];
|
|
10
10
|
}
|
|
11
11
|
export declare const CAPABILITIES_AT = "operations/_capabilities.json";
|
|
12
|
+
export declare const SERVER_AT = "_generated/server/entry.ts";
|
|
13
|
+
export declare const SERVER_OUT = "_generated/server/server.mjs";
|
|
12
14
|
export declare const CLIENT_AT = "operations/_client.ts";
|
|
13
15
|
export declare const DISPATCHING_AT = "app/_generated/dispatching.ts";
|
|
14
16
|
export declare const COMPILED = "app/_generated/compiled";
|
|
@@ -9,6 +9,8 @@ export const MEANS = {
|
|
|
9
9
|
export const DEFAULTS_AT = '_threads/defaults.ts';
|
|
10
10
|
export const UNSTATED = ['cli'];
|
|
11
11
|
export const CAPABILITIES_AT = 'operations/_capabilities.json';
|
|
12
|
+
export const SERVER_AT = '_generated/server/entry.ts';
|
|
13
|
+
export const SERVER_OUT = '_generated/server/server.mjs';
|
|
12
14
|
export const CLIENT_AT = 'operations/_client.ts';
|
|
13
15
|
export const DISPATCHING_AT = 'app/_generated/dispatching.ts';
|
|
14
16
|
export const COMPILED = 'app/_generated/compiled';
|