@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,15 +1,14 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from '../../integrations/disk.js';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import { argv, stdout } from 'node:process';
|
|
4
4
|
import ts from 'typescript';
|
|
5
|
-
import { ROOT, descend } from
|
|
6
|
-
import { runChecker } from
|
|
7
|
-
import { exit, invoked } from
|
|
8
|
-
import { inCode, valuesIn } from
|
|
9
|
-
import {
|
|
10
|
-
import { DISPATCH_AT, dispatched } from
|
|
11
|
-
import {
|
|
12
|
-
import { beside, blockIn, builtFrom, operations, problem, quoted, runtime, types } from "./seed.js";
|
|
5
|
+
import { ROOT, descend } from '../../core/descend.js';
|
|
6
|
+
import { runChecker } from '../../core/finding.js';
|
|
7
|
+
import { exit, invoked } from '../../core/invoked.js';
|
|
8
|
+
import { inCode, valuesIn } from '../../core/rows.js';
|
|
9
|
+
import { credentialsOf, holdsOf, reachOf } from '../../integrations/target.js';
|
|
10
|
+
import { DISPATCH_AT, dispatched } from '../dispatch.js';
|
|
11
|
+
import { beside, blockIn, builtFrom, operations, problem, quoted, runtime, types } from './seed.js';
|
|
13
12
|
async function reaching() {
|
|
14
13
|
const held = async (file, list) => {
|
|
15
14
|
const path = resolve(ROOT, `_threads/${file}`);
|
|
@@ -34,18 +33,27 @@ function reached(targets, calls, secrets) {
|
|
|
34
33
|
const mine = calls.filter((each) => each.of === one.id && one.takes.includes(each.id));
|
|
35
34
|
out[one.id] = {
|
|
36
35
|
reach: reachOf(one.id) ?? 'nothing known',
|
|
37
|
-
address:
|
|
38
|
-
|
|
36
|
+
address: one.address,
|
|
37
|
+
headers: one.headers ?? {},
|
|
38
|
+
signs: credentialsOf(one, secrets)
|
|
39
|
+
.filter((each) => each.signs !== undefined)
|
|
40
|
+
.map((each) => ({
|
|
41
|
+
secret: each.id,
|
|
42
|
+
header: each.signs?.header ?? '',
|
|
43
|
+
prefix: each.signs?.prefix ?? '',
|
|
44
|
+
})),
|
|
45
|
+
sends: credentialsOf(one, secrets).filter((each) => each.sends !== undefined).map((each) => ({
|
|
39
46
|
secret: each.id,
|
|
40
47
|
header: each.sends?.header ?? '',
|
|
41
48
|
prefix: each.sends?.prefix ?? '',
|
|
42
49
|
})),
|
|
43
|
-
calls: Object.fromEntries(mine.map((each) => [each.id.replace(/^cl_/, ''), { method: each.method, path: each.path }])),
|
|
50
|
+
calls: Object.fromEntries(mine.map((each) => [each.id.replace(/^cl_/, ''), { method: each.method ?? null, path: each.path }])),
|
|
44
51
|
};
|
|
45
52
|
}
|
|
46
53
|
return out;
|
|
47
54
|
}
|
|
48
55
|
const OWN = '$';
|
|
56
|
+
const OPENED = 'opened';
|
|
49
57
|
const ENTERED = `${OWN}at`;
|
|
50
58
|
const PLAIN = /^(?:[A-Za-z_][A-Za-z0-9_]*|'(?:[^'\\]|\\.)*')$/;
|
|
51
59
|
export function parts(text) {
|
|
@@ -91,10 +99,10 @@ function keyed(text) {
|
|
|
91
99
|
}
|
|
92
100
|
const OPENS = 'const $ = ';
|
|
93
101
|
const ROLES = {
|
|
94
|
-
block: ['
|
|
102
|
+
block: ['opened', 'held'],
|
|
95
103
|
over: ['held'],
|
|
96
|
-
item: ['item', '
|
|
97
|
-
again: ['pass', 'carried', '
|
|
104
|
+
item: ['item', 'opened', 'held'],
|
|
105
|
+
again: ['pass', 'carried', 'opened', 'held'],
|
|
98
106
|
};
|
|
99
107
|
function arrowIn(text, roles) {
|
|
100
108
|
const file = ts.createSourceFile('block.ts', `${OPENS}${text}`, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
@@ -208,6 +216,10 @@ function spliced(text, names, mine, roles) {
|
|
|
208
216
|
const body = again.arrow.body;
|
|
209
217
|
if (again.arrow.parameters.length > 1)
|
|
210
218
|
return { form: 'call', text: whole, whole };
|
|
219
|
+
const opens = again.arrow.parameters[0];
|
|
220
|
+
if (opens !== undefined && ts.isIdentifier(opens.name) && opens.name.text !== OPENED) {
|
|
221
|
+
return { form: 'call', text: whole, whole };
|
|
222
|
+
}
|
|
211
223
|
if (!ts.isBlock(body))
|
|
212
224
|
return { form: 'expression', text: body.getText(), whole };
|
|
213
225
|
const found = [];
|
|
@@ -220,15 +232,15 @@ function spliced(text, names, mine, roles) {
|
|
|
220
232
|
return { form: 'call', text: whole, whole };
|
|
221
233
|
}
|
|
222
234
|
const ANSWERS = `${OWN}ANSWER`;
|
|
223
|
-
function answered(name, one,
|
|
235
|
+
function answered(name, one, opened, kind) {
|
|
224
236
|
if (one.form === 'expression')
|
|
225
237
|
return [`${kind} ${name}: unknown = ${one.text}`];
|
|
226
238
|
if (one.form === 'statements') {
|
|
227
239
|
return [`let ${name}: unknown`, '{', ...one.text.split('\n').map((line) => ` ${line.replace(ANSWERS, name)}`), '}'];
|
|
228
240
|
}
|
|
229
|
-
return [`${kind} ${name}: unknown = await ${asFn(one.whole,
|
|
241
|
+
return [`${kind} ${name}: unknown = await ${asFn(one.whole, opened)}(opened)`];
|
|
230
242
|
}
|
|
231
|
-
const asFn = (text,
|
|
243
|
+
const asFn = (text, opened, more = '') => `((${text}) as (${more}opened: ${opened}) => Promise<unknown>)`;
|
|
232
244
|
function forked(name, said, shape) {
|
|
233
245
|
if (said.length !== 2)
|
|
234
246
|
return `takes a chooser and the ways it chooses between, and was handed ${String(said.length)} thing(s)`;
|
|
@@ -245,7 +257,7 @@ function forked(name, said, shape) {
|
|
|
245
257
|
`let ${name}: unknown`,
|
|
246
258
|
chose.form === 'expression'
|
|
247
259
|
? `const ${picked}: string = await (${chose.text})`
|
|
248
|
-
: `const ${picked}: string = await ((${said[0] ?? ''}) as (
|
|
260
|
+
: `const ${picked}: string = await ((${said[0] ?? ''}) as (opened: ${shape.reads}) => Promise<string>)(opened)`,
|
|
249
261
|
`switch (${picked}) {`,
|
|
250
262
|
];
|
|
251
263
|
for (const way of named) {
|
|
@@ -258,7 +270,7 @@ function forked(name, said, shape) {
|
|
|
258
270
|
else if (each.form === 'statements')
|
|
259
271
|
runs.push(...each.text.split('\n').map((line) => ` ${line.replace(ANSWERS, name)}`));
|
|
260
272
|
else
|
|
261
|
-
runs.push(` ${name} = await ${asFn(each.whole, shape.all)}(
|
|
273
|
+
runs.push(` ${name} = await ${asFn(each.whole, shape.all)}(opened)`);
|
|
262
274
|
runs.push(' break');
|
|
263
275
|
runs.push(' }');
|
|
264
276
|
}
|
|
@@ -285,9 +297,9 @@ const SHAPES = {
|
|
|
285
297
|
return {
|
|
286
298
|
runs: [
|
|
287
299
|
`const ${all}: unknown[] = []`,
|
|
288
|
-
`const ${each} = (${block.whole}) as (item: unknown,
|
|
300
|
+
`const ${each} = (${block.whole}) as (item: unknown, opened: ${shape.all}) => Promise<unknown>`,
|
|
289
301
|
`for (const ${item} of ${over.form === 'expression' ? `(${over.text})` : `((${over.whole}) as () => readonly unknown[])()`} as readonly unknown[]) {`,
|
|
290
|
-
` ${all}.push(await ${each}(${item},
|
|
302
|
+
` ${all}.push(await ${each}(${item}, opened))`,
|
|
291
303
|
'}',
|
|
292
304
|
`const ${name}: unknown = ${all}`,
|
|
293
305
|
],
|
|
@@ -307,7 +319,7 @@ const SHAPES = {
|
|
|
307
319
|
const each = spliced(one, shape.names, shape.mine, ROLES.block);
|
|
308
320
|
if (typeof each === 'string')
|
|
309
321
|
return `runs a block at position ${String(order + 1)} that ${each}`;
|
|
310
|
-
calls.push(each.form === 'expression' ? `(async () => ${each.text})()` : `${asFn(each.whole, shape.all)}(
|
|
322
|
+
calls.push(each.form === 'expression' ? `(async () => ${each.text})()` : `${asFn(each.whole, shape.all)}(opened)`);
|
|
311
323
|
}
|
|
312
324
|
return { runs: [`const ${name}: unknown = await Promise.all([${calls.join(', ')}])`] };
|
|
313
325
|
},
|
|
@@ -327,11 +339,11 @@ const SHAPES = {
|
|
|
327
339
|
runs: [
|
|
328
340
|
`let ${name}: unknown`,
|
|
329
341
|
`const ${ceiling}: number = ${said[0] ?? ''}`,
|
|
330
|
-
`const ${again} = (${block.whole}) as (pass: number, carried: unknown,
|
|
342
|
+
`const ${again} = (${block.whole}) as (pass: number, carried: unknown, opened: ${shape.all}) => Promise<{ readonly done: boolean; readonly value: unknown }>`,
|
|
331
343
|
`let ${carried}: unknown`,
|
|
332
344
|
`let ${done} = false`,
|
|
333
345
|
`for (let ${pass} = 0; ${pass} < ${ceiling}; ${pass} += 1) {`,
|
|
334
|
-
` const ${answer} = await ${again}(${pass}, ${carried},
|
|
346
|
+
` const ${answer} = await ${again}(${pass}, ${carried}, opened)`,
|
|
335
347
|
` if (${answer}.done) { ${name} = ${answer}.value; ${done} = true; break }`,
|
|
336
348
|
` ${carried} = ${answer}.value`,
|
|
337
349
|
'}',
|
|
@@ -342,21 +354,23 @@ const SHAPES = {
|
|
|
342
354
|
nd_branch: forked,
|
|
343
355
|
};
|
|
344
356
|
const STOPS = "Symbol.for('thread.operation.stopped')";
|
|
345
|
-
function plainly(name, said, shape,
|
|
357
|
+
function plainly(name, said, shape, opened, ends) {
|
|
346
358
|
if (said.length !== 1)
|
|
347
359
|
return `takes one block, and was handed ${String(said.length)} thing(s)`;
|
|
348
360
|
const one = spliced(said[0] ?? '', shape.names, shape.mine, ROLES.block);
|
|
349
361
|
if (typeof one === 'string')
|
|
350
362
|
return one;
|
|
351
363
|
if (!ends)
|
|
352
|
-
return { runs: answered(name, one,
|
|
364
|
+
return { runs: answered(name, one, opened, 'const') };
|
|
353
365
|
return {
|
|
354
366
|
runs: [
|
|
355
|
-
...answered(name, one,
|
|
367
|
+
...answered(name, one, opened, 'const'),
|
|
356
368
|
`throw Object.assign(new Error(${quoted(`${name} ended the operation`)}), { [${STOPS}]: true, value: ${name} })`,
|
|
357
369
|
],
|
|
358
370
|
};
|
|
359
371
|
}
|
|
372
|
+
const saidIn = (held) => held !== undefined && ts.isStringLiteral(held) ? held.text : undefined;
|
|
373
|
+
const sourceIn = (held) => held?.getText();
|
|
360
374
|
function compiled(at, id, one, known) {
|
|
361
375
|
const because = problem(id, one);
|
|
362
376
|
if (because !== undefined)
|
|
@@ -364,6 +378,18 @@ function compiled(at, id, one, known) {
|
|
|
364
378
|
const takes = one.takes[0]?.at;
|
|
365
379
|
if (takes === undefined)
|
|
366
380
|
return { because: `\`${id}\` seeds what it takes and states no file for it` };
|
|
381
|
+
const { timeout } = one;
|
|
382
|
+
const fields = descend().stated.get(id)?.fields;
|
|
383
|
+
const entitled = saidIn(fields?.get('entitled'));
|
|
384
|
+
const rate = sourceIn(fields?.get('rate'));
|
|
385
|
+
const quota = sourceIn(fields?.get('quota'));
|
|
386
|
+
if (timeout === undefined) {
|
|
387
|
+
return {
|
|
388
|
+
because: `\`${id}\` states no \`timeout\`, and an operation says how long it waits. Add \`timeout: 10_000\` to its row in ` +
|
|
389
|
+
'_threads/operations.ts, or change it with `thread edit ' + id + ' --timeout <milliseconds>`. How long a call may ' +
|
|
390
|
+
'run is part of the operation, not something the place it reaches decides',
|
|
391
|
+
};
|
|
392
|
+
}
|
|
367
393
|
const only = one.requires.length === 0 ? 'never' : one.requires.map((each) => quoted(each)).join(' | ');
|
|
368
394
|
const mine = new Set(['input', ...one.nodes.map((row) => String(row.id))]);
|
|
369
395
|
const runs = [];
|
|
@@ -392,7 +418,7 @@ function compiled(at, id, one, known) {
|
|
|
392
418
|
if (held === undefined) {
|
|
393
419
|
return { because: `the node \`${name}\` states no block this can read in ${row.at} — run \`thread seed\` and write it again` };
|
|
394
420
|
}
|
|
395
|
-
const shape = { all: `
|
|
421
|
+
const shape = { all: `Opened<${only}>`, reads: `Reads<Opened<${only}>>`, names, mine };
|
|
396
422
|
const made = (SHAPES[from] ?? ownType)(name, parts(held), shape);
|
|
397
423
|
if (typeof made === 'string')
|
|
398
424
|
return { because: `the node \`${name}\` ${made}` };
|
|
@@ -407,18 +433,21 @@ function compiled(at, id, one, known) {
|
|
|
407
433
|
"import type { z } from 'zod'",
|
|
408
434
|
'',
|
|
409
435
|
`import type { Operation } from ${quoted(runtime(at, '../operations.ts'))}`,
|
|
410
|
-
|
|
436
|
+
'import type { Opened, Reads } from ' + quoted(runtime(at, '../operations.ts')),
|
|
411
437
|
'',
|
|
412
|
-
`import {
|
|
438
|
+
`import { input, resource } from ${quoted(beside(at, takes))}`,
|
|
413
439
|
'',
|
|
414
440
|
`export const operation: Operation<z.infer<typeof input>, ${only}> = {`,
|
|
415
441
|
` id: ${quoted(id)},`,
|
|
416
442
|
' input,',
|
|
417
|
-
|
|
443
|
+
` timeout: ${String(timeout)},`,
|
|
418
444
|
' resource,',
|
|
419
445
|
` requires: [${one.requires.map((each) => quoted(each)).join(', ')}],`,
|
|
446
|
+
...(entitled === undefined ? [] : [` entitled: ${quoted(entitled)},`]),
|
|
447
|
+
...(rate === undefined ? [] : [` rate: ${rate},`]),
|
|
448
|
+
...(quota === undefined ? [] : [` quota: ${quota},`]),
|
|
420
449
|
'',
|
|
421
|
-
' run: async (
|
|
450
|
+
' run: async (opened, held) => {',
|
|
422
451
|
' const input = held.input',
|
|
423
452
|
` let ${ENTERED} = ''`,
|
|
424
453
|
' try {',
|
|
@@ -440,8 +469,8 @@ async function planned() {
|
|
|
440
469
|
const known = types(pass);
|
|
441
470
|
const reach = await reaching();
|
|
442
471
|
const found = [];
|
|
443
|
-
const answers = Object.keys(reach).filter((one) => Object.keys(reach[one]?.calls ?? {}).length > 0);
|
|
444
|
-
const may = [...
|
|
472
|
+
const answers = Object.keys(reach).filter((one) => Object.keys(reach[one]?.calls ?? {}).length > 0 || holdsOf(one)?.takes !== 'calls');
|
|
473
|
+
const may = [...answers];
|
|
445
474
|
for (const [id, one] of operations(pass, known)) {
|
|
446
475
|
if (one.body === undefined)
|
|
447
476
|
continue;
|
|
@@ -452,11 +481,9 @@ async function planned() {
|
|
|
452
481
|
because: silent
|
|
453
482
|
.map((each) => {
|
|
454
483
|
const how = reach[each]?.reach ?? 'nothing known';
|
|
455
|
-
const instead =
|
|
456
|
-
? 'run it with `thread run ' + each.replace(/^[a-z]+_/, '') + '`'
|
|
457
|
-
: 'reach the rows it keeps with `sm_store`';
|
|
484
|
+
const instead = 'declare what it answers with `thread create target call ' + each + ' <name>`';
|
|
458
485
|
return ('`' + id + '` requires `' + each + '`, which is reached over ' + how + ' and answers no call, so there ' +
|
|
459
|
-
'is nothing for a node to be handed. ' + instead + ',
|
|
486
|
+
'is nothing for a node to be handed. ' + instead + ', ' +
|
|
460
487
|
'or take the word off that operation\'s row');
|
|
461
488
|
})
|
|
462
489
|
.join('; '),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from '../../
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from '../../integrations/disk.ts'
|
|
2
2
|
import { dirname, resolve } from 'node:path'
|
|
3
3
|
import { argv, stdout } from 'node:process'
|
|
4
4
|
|
|
@@ -9,11 +9,10 @@ import { runChecker, type Finding } from '../../core/finding.ts'
|
|
|
9
9
|
import { exit, invoked } from '../../core/invoked.ts'
|
|
10
10
|
import { inCode, valuesIn } from '../../core/rows.ts'
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { credentialsOf, holdsOf, reachOf, type Call, type Target } from '../../integrations/target.ts'
|
|
13
13
|
import type { Secret } from '../../integrations/secret.ts'
|
|
14
14
|
|
|
15
15
|
import { DISPATCH_AT, dispatched } from '../dispatch.ts'
|
|
16
|
-
import { SUPPLIES } from '../seams.ts'
|
|
17
16
|
import { beside, blockIn, builtFrom, operations, problem, quoted, runtime, types } from './seed.ts'
|
|
18
17
|
|
|
19
18
|
async function reaching(): Promise<Readonly<Record<string, ReturnType<typeof reached>[string]>>> {
|
|
@@ -42,10 +41,11 @@ function reached(
|
|
|
42
41
|
string,
|
|
43
42
|
{
|
|
44
43
|
readonly reach: string
|
|
45
|
-
readonly address
|
|
46
|
-
readonly
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
readonly address?: string
|
|
45
|
+
readonly headers: Readonly<Record<string, string>>
|
|
46
|
+
readonly sends: readonly { readonly secret: string; readonly header: string; readonly prefix: string }[]
|
|
47
|
+
readonly signs: readonly { readonly secret: string; readonly header: string; readonly prefix: string }[]
|
|
48
|
+
readonly calls: Readonly<Record<string, { readonly method: string | null; readonly path: string }>>
|
|
49
49
|
}
|
|
50
50
|
>
|
|
51
51
|
> {
|
|
@@ -54,15 +54,23 @@ function reached(
|
|
|
54
54
|
const mine = calls.filter((each) => each.of === one.id && one.takes.includes(each.id))
|
|
55
55
|
out[one.id] = {
|
|
56
56
|
reach: reachOf(one.id) ?? 'nothing known',
|
|
57
|
-
address:
|
|
58
|
-
|
|
57
|
+
address: one.address,
|
|
58
|
+
headers: one.headers ?? {},
|
|
59
|
+
signs: credentialsOf(one, secrets)
|
|
60
|
+
.filter((each) => each.signs !== undefined)
|
|
61
|
+
.map((each) => ({
|
|
62
|
+
secret: each.id,
|
|
63
|
+
header: each.signs?.header ?? '',
|
|
64
|
+
prefix: each.signs?.prefix ?? '',
|
|
65
|
+
})),
|
|
66
|
+
sends: credentialsOf(one, secrets).filter((each) => each.sends !== undefined).map((each) => ({
|
|
59
67
|
secret: each.id,
|
|
60
68
|
header: each.sends?.header ?? '',
|
|
61
69
|
prefix: each.sends?.prefix ?? '',
|
|
62
70
|
})),
|
|
63
71
|
|
|
64
72
|
calls: Object.fromEntries(
|
|
65
|
-
mine.map((each) => [each.id.replace(/^cl_/, ''), { method: each.method, path: each.path }]),
|
|
73
|
+
mine.map((each) => [each.id.replace(/^cl_/, ''), { method: each.method ?? null, path: each.path }]),
|
|
66
74
|
),
|
|
67
75
|
}
|
|
68
76
|
}
|
|
@@ -71,6 +79,8 @@ function reached(
|
|
|
71
79
|
|
|
72
80
|
const OWN = '$'
|
|
73
81
|
|
|
82
|
+
const OPENED = 'opened'
|
|
83
|
+
|
|
74
84
|
const ENTERED = `${OWN}at`
|
|
75
85
|
|
|
76
86
|
const PLAIN = /^(?:[A-Za-z_][A-Za-z0-9_]*|'(?:[^'\\]|\\.)*')$/
|
|
@@ -115,10 +125,10 @@ function keyed(text: string): { readonly key: string; readonly held: string } |
|
|
|
115
125
|
const OPENS = 'const $ = '
|
|
116
126
|
|
|
117
127
|
const ROLES = {
|
|
118
|
-
block: ['
|
|
128
|
+
block: ['opened', 'held'],
|
|
119
129
|
over: ['held'],
|
|
120
|
-
item: ['item', '
|
|
121
|
-
again: ['pass', 'carried', '
|
|
130
|
+
item: ['item', 'opened', 'held'],
|
|
131
|
+
again: ['pass', 'carried', 'opened', 'held'],
|
|
122
132
|
} as const satisfies Readonly<Record<string, readonly string[]>>
|
|
123
133
|
|
|
124
134
|
interface Read {
|
|
@@ -261,6 +271,11 @@ function spliced(
|
|
|
261
271
|
|
|
262
272
|
if (again.arrow.parameters.length > 1) return { form: 'call', text: whole, whole }
|
|
263
273
|
|
|
274
|
+
const opens = again.arrow.parameters[0]
|
|
275
|
+
if (opens !== undefined && ts.isIdentifier(opens.name) && opens.name.text !== OPENED) {
|
|
276
|
+
return { form: 'call', text: whole, whole }
|
|
277
|
+
}
|
|
278
|
+
|
|
264
279
|
if (!ts.isBlock(body)) return { form: 'expression', text: body.getText(), whole }
|
|
265
280
|
|
|
266
281
|
const found: ts.ReturnStatement[] = []
|
|
@@ -287,16 +302,16 @@ interface Shape {
|
|
|
287
302
|
readonly mine: ReadonlySet<string>
|
|
288
303
|
}
|
|
289
304
|
|
|
290
|
-
function answered(name: string, one: Spliced,
|
|
305
|
+
function answered(name: string, one: Spliced, opened: string, kind: 'const' | 'let'): readonly string[] {
|
|
291
306
|
if (one.form === 'expression') return [`${kind} ${name}: unknown = ${one.text}`]
|
|
292
307
|
if (one.form === 'statements') {
|
|
293
308
|
return [`let ${name}: unknown`, '{', ...one.text.split('\n').map((line) => ` ${line.replace(ANSWERS, name)}`), '}']
|
|
294
309
|
}
|
|
295
|
-
return [`${kind} ${name}: unknown = await ${asFn(one.whole,
|
|
310
|
+
return [`${kind} ${name}: unknown = await ${asFn(one.whole, opened)}(opened)`]
|
|
296
311
|
}
|
|
297
312
|
|
|
298
|
-
const asFn = (text: string,
|
|
299
|
-
`((${text}) as (${more}
|
|
313
|
+
const asFn = (text: string, opened: string, more: string = ''): string =>
|
|
314
|
+
`((${text}) as (${more}opened: ${opened}) => Promise<unknown>)`
|
|
300
315
|
|
|
301
316
|
function forked(name: string, said: readonly string[], shape: Shape): Made | string {
|
|
302
317
|
if (said.length !== 2) return `takes a chooser and the ways it chooses between, and was handed ${String(said.length)} thing(s)`
|
|
@@ -314,7 +329,7 @@ function forked(name: string, said: readonly string[], shape: Shape): Made | str
|
|
|
314
329
|
`let ${name}: unknown`,
|
|
315
330
|
chose.form === 'expression'
|
|
316
331
|
? `const ${picked}: string = await (${chose.text})`
|
|
317
|
-
: `const ${picked}: string = await ((${said[0] ?? ''}) as (
|
|
332
|
+
: `const ${picked}: string = await ((${said[0] ?? ''}) as (opened: ${shape.reads}) => Promise<string>)(opened)`,
|
|
318
333
|
`switch (${picked}) {`,
|
|
319
334
|
]
|
|
320
335
|
|
|
@@ -324,7 +339,7 @@ function forked(name: string, said: readonly string[], shape: Shape): Made | str
|
|
|
324
339
|
runs.push(` case ${(way?.key ?? '').startsWith("'") ? (way?.key ?? '') : quoted(way?.key ?? '')}: {`)
|
|
325
340
|
if (each.form === 'expression') runs.push(` ${name} = ${each.text}`)
|
|
326
341
|
else if (each.form === 'statements') runs.push(...each.text.split('\n').map((line) => ` ${line.replace(ANSWERS, name)}`))
|
|
327
|
-
else runs.push(` ${name} = await ${asFn(each.whole, shape.all)}(
|
|
342
|
+
else runs.push(` ${name} = await ${asFn(each.whole, shape.all)}(opened)`)
|
|
328
343
|
runs.push(' break')
|
|
329
344
|
runs.push(' }')
|
|
330
345
|
}
|
|
@@ -351,9 +366,9 @@ const SHAPES: Readonly<Record<string, (name: string, said: readonly string[], sh
|
|
|
351
366
|
return {
|
|
352
367
|
runs: [
|
|
353
368
|
`const ${all}: unknown[] = []`,
|
|
354
|
-
`const ${each} = (${block.whole}) as (item: unknown,
|
|
369
|
+
`const ${each} = (${block.whole}) as (item: unknown, opened: ${shape.all}) => Promise<unknown>`,
|
|
355
370
|
`for (const ${item} of ${over.form === 'expression' ? `(${over.text})` : `((${over.whole}) as () => readonly unknown[])()`} as readonly unknown[]) {`,
|
|
356
|
-
` ${all}.push(await ${each}(${item},
|
|
371
|
+
` ${all}.push(await ${each}(${item}, opened))`,
|
|
357
372
|
'}',
|
|
358
373
|
`const ${name}: unknown = ${all}`,
|
|
359
374
|
],
|
|
@@ -371,7 +386,7 @@ const SHAPES: Readonly<Record<string, (name: string, said: readonly string[], sh
|
|
|
371
386
|
for (const [order, one] of every.entries()) {
|
|
372
387
|
const each = spliced(one, shape.names, shape.mine, ROLES.block)
|
|
373
388
|
if (typeof each === 'string') return `runs a block at position ${String(order + 1)} that ${each}`
|
|
374
|
-
calls.push(each.form === 'expression' ? `(async () => ${each.text})()` : `${asFn(each.whole, shape.all)}(
|
|
389
|
+
calls.push(each.form === 'expression' ? `(async () => ${each.text})()` : `${asFn(each.whole, shape.all)}(opened)`)
|
|
375
390
|
}
|
|
376
391
|
return { runs: [`const ${name}: unknown = await Promise.all([${calls.join(', ')}])`] }
|
|
377
392
|
},
|
|
@@ -390,11 +405,11 @@ const SHAPES: Readonly<Record<string, (name: string, said: readonly string[], sh
|
|
|
390
405
|
runs: [
|
|
391
406
|
`let ${name}: unknown`,
|
|
392
407
|
`const ${ceiling}: number = ${said[0] ?? ''}`,
|
|
393
|
-
`const ${again} = (${block.whole}) as (pass: number, carried: unknown,
|
|
408
|
+
`const ${again} = (${block.whole}) as (pass: number, carried: unknown, opened: ${shape.all}) => Promise<{ readonly done: boolean; readonly value: unknown }>`,
|
|
394
409
|
`let ${carried}: unknown`,
|
|
395
410
|
`let ${done} = false`,
|
|
396
411
|
`for (let ${pass} = 0; ${pass} < ${ceiling}; ${pass} += 1) {`,
|
|
397
|
-
` const ${answer} = await ${again}(${pass}, ${carried},
|
|
412
|
+
` const ${answer} = await ${again}(${pass}, ${carried}, opened)`,
|
|
398
413
|
` if (${answer}.done) { ${name} = ${answer}.value; ${done} = true; break }`,
|
|
399
414
|
` ${carried} = ${answer}.value`,
|
|
400
415
|
'}',
|
|
@@ -408,20 +423,24 @@ const SHAPES: Readonly<Record<string, (name: string, said: readonly string[], sh
|
|
|
408
423
|
|
|
409
424
|
const STOPS = "Symbol.for('thread.operation.stopped')"
|
|
410
425
|
|
|
411
|
-
function plainly(name: string, said: readonly string[], shape: Shape,
|
|
426
|
+
function plainly(name: string, said: readonly string[], shape: Shape, opened: string, ends: boolean): Made | string {
|
|
412
427
|
if (said.length !== 1) return `takes one block, and was handed ${String(said.length)} thing(s)`
|
|
413
428
|
const one = spliced(said[0] ?? '', shape.names, shape.mine, ROLES.block)
|
|
414
429
|
if (typeof one === 'string') return one
|
|
415
430
|
|
|
416
|
-
if (!ends) return { runs: answered(name, one,
|
|
431
|
+
if (!ends) return { runs: answered(name, one, opened, 'const') }
|
|
417
432
|
|
|
418
433
|
return {
|
|
419
434
|
runs: [
|
|
420
|
-
...answered(name, one,
|
|
435
|
+
...answered(name, one, opened, 'const'),
|
|
421
436
|
`throw Object.assign(new Error(${quoted(`${name} ended the operation`)}), { [${STOPS}]: true, value: ${name} })`,
|
|
422
437
|
],
|
|
423
438
|
}
|
|
424
439
|
}
|
|
440
|
+
const saidIn = (held: ts.Expression | undefined): string | undefined =>
|
|
441
|
+
held !== undefined && ts.isStringLiteral(held) ? held.text : undefined
|
|
442
|
+
|
|
443
|
+
const sourceIn = (held: ts.Expression | undefined): string | undefined => held?.getText()
|
|
425
444
|
|
|
426
445
|
function compiled(
|
|
427
446
|
at: string,
|
|
@@ -435,6 +454,21 @@ function compiled(
|
|
|
435
454
|
const takes = one.takes[0]?.at
|
|
436
455
|
if (takes === undefined) return { because: `\`${id}\` seeds what it takes and states no file for it` }
|
|
437
456
|
|
|
457
|
+
const { timeout } = one
|
|
458
|
+
|
|
459
|
+
const fields = descend().stated.get(id)?.fields
|
|
460
|
+
const entitled = saidIn(fields?.get('entitled'))
|
|
461
|
+
const rate = sourceIn(fields?.get('rate'))
|
|
462
|
+
const quota = sourceIn(fields?.get('quota'))
|
|
463
|
+
if (timeout === undefined) {
|
|
464
|
+
return {
|
|
465
|
+
because:
|
|
466
|
+
`\`${id}\` states no \`timeout\`, and an operation says how long it waits. Add \`timeout: 10_000\` to its row in ` +
|
|
467
|
+
'_threads/operations.ts, or change it with `thread edit ' + id + ' --timeout <milliseconds>`. How long a call may ' +
|
|
468
|
+
'run is part of the operation, not something the place it reaches decides',
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
438
472
|
const only = one.requires.length === 0 ? 'never' : one.requires.map((each) => quoted(each)).join(' | ')
|
|
439
473
|
const mine = new Set<string>(['input', ...one.nodes.map((row) => String(row.id))])
|
|
440
474
|
|
|
@@ -466,7 +500,7 @@ function compiled(
|
|
|
466
500
|
return { because: `the node \`${name}\` states no block this can read in ${row.at} — run \`thread seed\` and write it again` }
|
|
467
501
|
}
|
|
468
502
|
|
|
469
|
-
const shape: Shape = { all: `
|
|
503
|
+
const shape: Shape = { all: `Opened<${only}>`, reads: `Reads<Opened<${only}>>`, names, mine }
|
|
470
504
|
const made = (SHAPES[from] ?? ownType)(name, parts(held), shape)
|
|
471
505
|
if (typeof made === 'string') return { because: `the node \`${name}\` ${made}` }
|
|
472
506
|
|
|
@@ -481,18 +515,21 @@ function compiled(
|
|
|
481
515
|
"import type { z } from 'zod'",
|
|
482
516
|
'',
|
|
483
517
|
`import type { Operation } from ${quoted(runtime(at, '../operations.ts'))}`,
|
|
484
|
-
|
|
518
|
+
'import type { Opened, Reads } from ' + quoted(runtime(at, '../operations.ts')),
|
|
485
519
|
'',
|
|
486
|
-
`import {
|
|
520
|
+
`import { input, resource } from ${quoted(beside(at, takes))}`,
|
|
487
521
|
'',
|
|
488
522
|
`export const operation: Operation<z.infer<typeof input>, ${only}> = {`,
|
|
489
523
|
` id: ${quoted(id)},`,
|
|
490
524
|
' input,',
|
|
491
|
-
|
|
525
|
+
` timeout: ${String(timeout)},`,
|
|
492
526
|
' resource,',
|
|
493
527
|
` requires: [${one.requires.map((each) => quoted(each)).join(', ')}],`,
|
|
528
|
+
...(entitled === undefined ? [] : [` entitled: ${quoted(entitled)},`]),
|
|
529
|
+
...(rate === undefined ? [] : [` rate: ${rate},`]),
|
|
530
|
+
...(quota === undefined ? [] : [` quota: ${quota},`]),
|
|
494
531
|
'',
|
|
495
|
-
' run: async (
|
|
532
|
+
' run: async (opened, held) => {',
|
|
496
533
|
' const input = held.input',
|
|
497
534
|
` let ${ENTERED} = ''`,
|
|
498
535
|
' try {',
|
|
@@ -524,8 +561,10 @@ async function planned(): Promise<readonly Wanted[]> {
|
|
|
524
561
|
const reach = await reaching()
|
|
525
562
|
const found: Wanted[] = []
|
|
526
563
|
|
|
527
|
-
const answers = Object.keys(reach).filter(
|
|
528
|
-
|
|
564
|
+
const answers = Object.keys(reach).filter(
|
|
565
|
+
(one) => Object.keys(reach[one]?.calls ?? {}).length > 0 || holdsOf(one)?.takes !== 'calls',
|
|
566
|
+
)
|
|
567
|
+
const may = [...answers]
|
|
529
568
|
for (const [id, one] of operations(pass, known)) {
|
|
530
569
|
if (one.body === undefined) continue
|
|
531
570
|
const silent = one.requires.filter((each) => reach[each] !== undefined && !answers.includes(each))
|
|
@@ -535,13 +574,13 @@ async function planned(): Promise<readonly Wanted[]> {
|
|
|
535
574
|
because: silent
|
|
536
575
|
.map((each) => {
|
|
537
576
|
const how = reach[each]?.reach ?? 'nothing known'
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
577
|
+
const instead = 'declare what it answers with `thread create target call ' + each + ' <name>`'
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
|
|
542
581
|
return (
|
|
543
582
|
'`' + id + '` requires `' + each + '`, which is reached over ' + how + ' and answers no call, so there ' +
|
|
544
|
-
|
|
583
|
+
'is nothing for a node to be handed. ' + instead + ', ' +
|
|
545
584
|
'or take the word off that operation\'s row'
|
|
546
585
|
)
|
|
547
586
|
})
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from
|
|
2
|
-
import { valuesIn } from
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from '../../integrations/disk.js';
|
|
2
|
+
import { valuesIn } from '../../core/rows.js';
|
|
3
3
|
import { resolve } from 'node:path';
|
|
4
4
|
import { argv, stderr, stdout } from 'node:process';
|
|
5
|
-
import { exit } from
|
|
6
|
-
import { PUBLIC_ROLE as PUBLIC } from
|
|
7
|
-
import { ROOT, descend } from
|
|
8
|
-
import { forbids, runChecker } from
|
|
9
|
-
import { findTree, inTree } from
|
|
10
|
-
import { PERMITS_AT, grantedTwice, opensToEverybody, unanswerable } from
|
|
11
|
-
import {
|
|
12
|
-
import { operations as woven, runtime, types } from "./seed.js";
|
|
5
|
+
import { exit } from '../../core/invoked.js';
|
|
6
|
+
import { PUBLIC_ROLE as PUBLIC } from '../../core/actor.js';
|
|
7
|
+
import { ROOT, descend } from '../../core/descend.js';
|
|
8
|
+
import { forbids, runChecker } from '../../core/finding.js';
|
|
9
|
+
import { findTree, inTree } from '../../core/tree.js';
|
|
10
|
+
import { PERMITS_AT, grantedTwice, opensToEverybody, unanswerable } from '../access.js';
|
|
11
|
+
import { operations as woven, runtime, types } from './seed.js';
|
|
13
12
|
function stop(why) {
|
|
14
13
|
stderr.write(`permits: ${why}\n`);
|
|
15
14
|
exit(1);
|
|
@@ -153,7 +152,7 @@ function permitting() {
|
|
|
153
152
|
];
|
|
154
153
|
return [
|
|
155
154
|
`import type { Actor } from '${runtime(PERMITS_AT, '../../core/actor.ts')}'`,
|
|
156
|
-
|
|
155
|
+
"import type { Row } from '" + runtime(PERMITS_AT, '../../integrations/target.ts') + "'",
|
|
157
156
|
'',
|
|
158
157
|
...(grants.some((one) => one.when !== undefined) ? [...READS, ''] : []),
|
|
159
158
|
...(grants.some((one) => one.to !== undefined) ? [...WEARS, ''] : []),
|
|
@@ -183,5 +182,5 @@ if (CHECKING) {
|
|
|
183
182
|
exit(findings.length === 0 ? 0 : 1);
|
|
184
183
|
}
|
|
185
184
|
writeFileSync(permitted, content);
|
|
186
|
-
stdout.write(`permits: wrote ${PERMITS_AT} — ${count}.
|
|
185
|
+
stdout.write(`permits: wrote ${PERMITS_AT} — ${count}. Dispatch imports this check itself, so every operation passes it; ` +
|
|
187
186
|
'`thread grant` adds a grant, and a refusal no grant can say is an invariant on the entity, or a rule from `thread create rule`.\n');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from '../../
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from '../../integrations/disk.ts'
|
|
2
2
|
import { valuesIn } from '../../core/rows.ts'
|
|
3
3
|
import { dirname, resolve } from 'node:path'
|
|
4
4
|
import { argv, stderr, stdout } from 'node:process'
|
|
@@ -12,7 +12,6 @@ import type { Condition, Operand } from '../../core/condition.ts'
|
|
|
12
12
|
import { findTree, inTree } from '../../core/tree.ts'
|
|
13
13
|
|
|
14
14
|
import { PERMITS_AT, grantedTwice, opensToEverybody, unanswerable, type Grant } from '../access.ts'
|
|
15
|
-
import { DECLARED_SEAMS_AT } from '../capabilities.ts'
|
|
16
15
|
import { operations as woven, runtime, types } from './seed.ts'
|
|
17
16
|
|
|
18
17
|
function stop(why: string): never {
|
|
@@ -180,7 +179,7 @@ function permitting(): string {
|
|
|
180
179
|
|
|
181
180
|
return [
|
|
182
181
|
`import type { Actor } from '${runtime(PERMITS_AT, '../../core/actor.ts')}'`,
|
|
183
|
-
|
|
182
|
+
"import type { Row } from '" + runtime(PERMITS_AT, '../../integrations/target.ts') + "'",
|
|
184
183
|
'',
|
|
185
184
|
...(grants.some((one) => one.when !== undefined) ? [...READS, ''] : []),
|
|
186
185
|
...(grants.some((one) => one.to !== undefined) ? [...WEARS, ''] : []),
|
|
@@ -218,6 +217,6 @@ if (CHECKING) {
|
|
|
218
217
|
|
|
219
218
|
writeFileSync(permitted, content)
|
|
220
219
|
stdout.write(
|
|
221
|
-
`permits: wrote ${PERMITS_AT} — ${count}.
|
|
220
|
+
`permits: wrote ${PERMITS_AT} — ${count}. Dispatch imports this check itself, so every operation passes it; ` +
|
|
222
221
|
'`thread grant` adds a grant, and a refusal no grant can say is an invariant on the entity, or a rule from `thread create rule`.\n',
|
|
223
222
|
)
|
|
@@ -11,6 +11,7 @@ interface Woven {
|
|
|
11
11
|
readonly body?: string;
|
|
12
12
|
readonly requires: readonly string[];
|
|
13
13
|
readonly stray: readonly string[];
|
|
14
|
+
readonly timeout?: number;
|
|
14
15
|
}
|
|
15
16
|
export declare function operations(pass: Pass, known: ReadonlySet<string>): ReadonlyMap<string, Woven>;
|
|
16
17
|
export declare const problem: (id: string, one: Woven) => string | undefined;
|