@prestack/thread 0.0.2 → 0.1.0
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 +98 -0
- package/dist/core/{asking.d.ts → answers.d.ts} +6 -14
- package/dist/core/{asking.js → answers.js} +13 -332
- package/dist/core/{asking.ts → answers.ts} +14 -357
- package/dist/core/attach.js +2 -2
- package/dist/core/attach.ts +2 -3
- package/dist/core/chain.js +4 -11
- package/dist/core/chain.ts +4 -3
- package/dist/core/client.d.ts +57 -0
- package/dist/core/client.js +186 -0
- package/dist/core/client.ts +227 -0
- package/dist/core/descend.d.ts +2 -0
- package/dist/core/descend.js +109 -16
- package/dist/core/descend.ts +120 -16
- package/dist/core/files.d.ts +45 -0
- package/dist/core/files.js +95 -0
- package/dist/core/files.ts +137 -0
- package/dist/core/init.d.ts +1 -0
- package/dist/core/init.js +10 -2
- package/dist/core/init.ts +8 -2
- package/dist/core/invoked.js +1 -1
- package/dist/core/invoked.ts +1 -1
- package/dist/core/rows.d.ts +2 -0
- package/dist/core/rows.js +65 -0
- package/dist/core/rows.ts +58 -0
- package/dist/core/tree.js +1 -1
- package/dist/core/tree.ts +1 -1
- package/dist/derivation/attach.js +0 -12
- package/dist/derivation/attach.ts +0 -12
- package/dist/derivation/generators/build.js +8 -7
- package/dist/derivation/generators/build.ts +8 -7
- package/dist/derivation/generators/release.d.ts +1 -1
- package/dist/derivation/generators/release.js +15 -23
- package/dist/derivation/generators/release.ts +15 -15
- package/dist/integrations/attach.js +1 -19
- package/dist/integrations/attach.ts +1 -19
- package/dist/integrations/generators/read.js +2 -2
- package/dist/integrations/generators/read.ts +4 -4
- package/dist/integrations/generators/vault.js +4 -12
- package/dist/integrations/generators/vault.ts +4 -4
- package/dist/integrations/module.js +5 -3
- package/dist/integrations/module.ts +5 -3
- package/dist/integrations/vault.js +5 -5
- package/dist/integrations/vault.ts +5 -5
- package/dist/integrity/attach.js +0 -12
- package/dist/integrity/attach.ts +0 -12
- package/dist/integrity/check-threads.js +1 -1
- package/dist/integrity/check-threads.ts +1 -1
- package/dist/integrity/constraint.d.ts +11 -2
- package/dist/integrity/constraint.js +163 -20
- package/dist/integrity/constraint.ts +174 -22
- package/dist/integrity/generators/compiler.js +1 -1
- package/dist/integrity/generators/compiler.ts +1 -1
- package/dist/integrity/generators/gate.js +8 -16
- package/dist/integrity/generators/gate.ts +8 -7
- package/dist/integrity/generators/publish.js +14 -26
- package/dist/integrity/generators/publish.ts +14 -17
- package/dist/integrity/generators/trial.d.ts +2 -2
- package/dist/integrity/generators/trial.js +108 -50
- package/dist/integrity/generators/trial.ts +107 -48
- package/dist/integrity/lint.js +3 -3
- package/dist/integrity/lint.ts +3 -3
- package/dist/integrity/lsp/diagnostics.js +1 -1
- package/dist/integrity/lsp/diagnostics.ts +1 -1
- package/dist/integrity/lsp/lint.js +1 -1
- package/dist/integrity/lsp/lint.ts +1 -1
- package/dist/integrity/slopnator.d.ts +1 -14
- package/dist/integrity/slopnator.js +8 -40
- package/dist/integrity/slopnator.ts +9 -51
- package/dist/integrity/slopnators/sl_broken_lineage.js +4 -2
- package/dist/integrity/slopnators/sl_broken_lineage.ts +4 -2
- package/dist/integrity/slopnators/sl_declared_elsewhere.js +24 -3
- package/dist/integrity/slopnators/sl_declared_elsewhere.ts +24 -3
- package/dist/integrity/slopnators/sl_derived_drift.js +10 -4
- package/dist/integrity/slopnators/sl_derived_drift.ts +10 -4
- package/dist/integrity/slopnators/sl_inert_island.js +7 -13
- package/dist/integrity/slopnators/sl_inert_island.ts +7 -16
- package/dist/integrity/slopnators/sl_inert_slopnator.js +8 -8
- package/dist/integrity/slopnators/sl_inert_slopnator.ts +8 -8
- package/dist/integrity/slopnators/sl_missing_row.js +14 -9
- package/dist/integrity/slopnators/sl_missing_row.ts +14 -10
- package/dist/integrity/slopnators/sl_no_child_process.js +8 -8
- package/dist/integrity/slopnators/sl_no_child_process.ts +8 -8
- package/dist/integrity/slopnators/sl_no_import_cycle.js +1 -1
- package/dist/integrity/slopnators/sl_no_import_cycle.ts +1 -1
- package/dist/integrity/slopnators/sl_no_such_command.js +20 -5
- package/dist/integrity/slopnators/sl_no_such_command.ts +22 -5
- package/dist/integrity/slopnators/sl_only_takes_a_literal.js +8 -8
- package/dist/integrity/slopnators/sl_only_takes_a_literal.ts +8 -8
- package/dist/integrity/slopnators/sl_stale_path.js +91 -18
- package/dist/integrity/slopnators/sl_stale_path.ts +97 -18
- package/dist/integrity/slopnators/sl_twice_meant.js +25 -2
- package/dist/integrity/slopnators/sl_twice_meant.ts +28 -2
- package/dist/integrity/slopnators/sl_twice_parented.js +26 -5
- package/dist/integrity/slopnators/sl_twice_parented.ts +26 -5
- package/dist/integrity/slopnators/sl_undeclared_node.js +18 -2
- package/dist/integrity/slopnators/sl_undeclared_node.ts +18 -2
- package/dist/integrity/slopnators/sl_undeclared_operation.js +3 -1
- package/dist/integrity/slopnators/sl_undeclared_operation.ts +3 -1
- package/dist/integrity/slopnators/sl_undeclared_variant.js +6 -2
- package/dist/integrity/slopnators/sl_undeclared_variant.ts +6 -2
- package/dist/integrity/slopnators/sl_ungoverned_island.js +3 -4
- package/dist/integrity/slopnators/sl_ungoverned_island.ts +3 -4
- package/dist/integrity/slopnators/sl_unkept_rows.js +1 -1
- package/dist/integrity/slopnators/sl_unkept_rows.ts +1 -1
- package/dist/integrity/slopnators/sl_unpaired_member.js +13 -8
- package/dist/integrity/slopnators/sl_unpaired_member.ts +16 -8
- package/dist/integrity/slopnators/sl_unpaired_slopnator.js +16 -3
- package/dist/integrity/slopnators/sl_unpaired_slopnator.ts +16 -3
- package/dist/integrity/slopnators/sl_unthreaded.d.ts +1 -0
- package/dist/integrity/slopnators/sl_unthreaded.js +18 -10
- package/dist/integrity/slopnators/sl_unthreaded.ts +19 -11
- package/dist/integrity/slopnators/sl_untranslated_key.js +1 -1
- package/dist/integrity/slopnators/sl_untranslated_key.ts +1 -1
- package/dist/integrity/slopnators/sl_unversioned.js +16 -2
- package/dist/integrity/slopnators/sl_unversioned.ts +16 -2
- package/dist/integrity/sweep.js +17 -3
- package/dist/integrity/sweep.ts +20 -3
- package/dist/knowledge/attach.js +0 -6
- package/dist/knowledge/attach.ts +0 -6
- package/dist/knowledge/generators/docsgen.js +12 -3
- package/dist/knowledge/generators/docsgen.ts +12 -2
- package/dist/knowledge/generators/glossary.js +1 -1
- package/dist/knowledge/generators/glossary.ts +1 -1
- package/dist/operations/attach.js +2 -26
- package/dist/operations/attach.ts +2 -27
- package/dist/operations/dispatch.js +2 -3
- package/dist/operations/dispatch.ts +2 -3
- package/dist/operations/generators/capability.js +4 -7
- package/dist/operations/generators/capability.ts +3 -6
- package/dist/operations/generators/compile.js +8 -13
- package/dist/operations/generators/compile.ts +8 -4
- package/dist/operations/generators/permits.js +4 -13
- package/dist/operations/generators/permits.ts +3 -3
- package/dist/operations/generators/seed.js +5 -2
- package/dist/operations/generators/seed.ts +6 -2
- package/dist/operations/generators/trial.js +10 -10
- package/dist/operations/generators/trial.ts +10 -10
- package/dist/operations/http.js +4 -1
- package/dist/operations/http.ts +6 -1
- package/package.json +2 -2
- package/dist/core/cli.d.ts +0 -2
- package/dist/core/cli.js +0 -1761
- package/dist/core/cli.ts +0 -2004
- package/dist/core/generators/meta.d.ts +0 -2
- package/dist/core/generators/meta.js +0 -829
- package/dist/core/generators/meta.ts +0 -1006
- package/dist/derivation/generators/derivation.d.ts +0 -3
- package/dist/derivation/generators/derivation.js +0 -273
- package/dist/derivation/generators/derivation.ts +0 -347
- package/dist/derivation/makers/release.d.ts +0 -1
- package/dist/derivation/makers/release.js +0 -107
- package/dist/derivation/makers/release.ts +0 -135
- package/dist/integrations/generators/secret.d.ts +0 -1
- package/dist/integrations/generators/secret.js +0 -233
- package/dist/integrations/generators/secret.ts +0 -289
- package/dist/integrations/generators/target.d.ts +0 -1
- package/dist/integrations/generators/target.js +0 -775
- package/dist/integrations/generators/target.ts +0 -944
- package/dist/integrity/generators/rule.d.ts +0 -2
- package/dist/integrity/generators/rule.js +0 -213
- package/dist/integrity/generators/rule.ts +0 -271
- package/dist/integrity/generators/seal.d.ts +0 -4
- package/dist/integrity/generators/seal.js +0 -101
- package/dist/integrity/generators/seal.ts +0 -117
- package/dist/integrity/sealed.d.ts +0 -1
- package/dist/integrity/sealed.js +0 -56
- package/dist/integrity/sealed.ts +0 -56
- package/dist/knowledge/generators/skills.d.ts +0 -1
- package/dist/knowledge/generators/skills.js +0 -222
- package/dist/knowledge/generators/skills.ts +0 -263
- package/dist/operations/generators/grant.d.ts +0 -1
- package/dist/operations/generators/grant.js +0 -267
- package/dist/operations/generators/grant.ts +0 -336
- package/dist/operations/generators/operation.d.ts +0 -1
- package/dist/operations/generators/operation.js +0 -811
- package/dist/operations/generators/operation.ts +0 -972
- package/dist/operations/makers/capability.d.ts +0 -1
- package/dist/operations/makers/capability.js +0 -117
- package/dist/operations/makers/capability.ts +0 -166
- package/dist/operations/makers/trial.d.ts +0 -1
- package/dist/operations/makers/trial.js +0 -413
- package/dist/operations/makers/trial.ts +0 -520
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { named } from "../core/scope.js";
|
|
2
|
+
import { LISTS } from "../core/descend.js";
|
|
2
3
|
import { quoted } from "../core/rows.js";
|
|
3
4
|
import { PERMITS_AT } from "./access.js";
|
|
4
5
|
import { CAPABILITIES_AT, CLIENT_AT, DECLARED_SEAMS_AT, DISPATCHING_AT, MCP_AT, OPENAPI_AT, SEAMS_AT } from "./capabilities.js";
|
|
@@ -7,7 +8,6 @@ import { TRIALS_AT } from "./operations.js";
|
|
|
7
8
|
import { MEMBERS_LIST, NODES_FILE, OPERATIONS_FILE } from "./operations.js";
|
|
8
9
|
import { SUPPLIES } from "./seams.js";
|
|
9
10
|
const HOME = `node_modules/${named('operations')}/dist`;
|
|
10
|
-
const LISTS = ['declares', 'derives', 'seeds'];
|
|
11
11
|
const VERSION = 1;
|
|
12
12
|
const ROOT = 'operations';
|
|
13
13
|
const NODES_AT = '_threads/nodes.ts';
|
|
@@ -70,7 +70,7 @@ export const said = (one, pad) => {
|
|
|
70
70
|
const ACCESS = 'Who may ask this app to do what. A row says which operations it permits, on what, to whom, and under what condition. Nothing is permitted by default: an operation no row grants here cannot be run at all.';
|
|
71
71
|
const PERMITS = 'The check compiled from the grants in _threads/access.ts: one branch per grant, so who may ask for what comes from one statement. Nobody edits it, because an edit here widens or narrows access nobody granted. An app that grants nothing permits nothing.';
|
|
72
72
|
const SEAMS = 'What this app hands its operations, written once and then yours. It starts by handing on everything src/_generated/seams.ts settles from your declarations. Replace a seam or add one by naming it in SEAMS: the queue, the events, telemetry, whatever a real deployment needs.';
|
|
73
|
-
const DECLARED_SEAMS = 'The seams your declarations settle. Rows go to the store each target derived,
|
|
73
|
+
const DECLARED_SEAMS = 'The seams your declarations settle. Rows go to the store each target derived, and until one does no store is handed, so an operation that needs one is refused; who is calling is read off the entity that names the caller; calls leave through http with credentials the vault opens. Nobody edits it: `thread capabilities` writes it again from the rows.';
|
|
74
74
|
const ACCESS_SOURCE = `import type { Grant } from './access.ts'
|
|
75
75
|
|
|
76
76
|
export const GRANTS: readonly Grant[] = []
|
|
@@ -290,18 +290,6 @@ const SHIPPED = [
|
|
|
290
290
|
id: 'capability-generator',
|
|
291
291
|
source: " {\n id: 'capability-generator',\n at: 'node_modules/@prestack/thread/dist/operations/generators/capability.js',\n describes: 'Writes what can be reached and how, and refuses it once it has drifted. It reads each operation for its name, what it does and the shape of its input, so adding or renaming one changes what is reachable without anybody editing a list.',\n version: 1,\n by: 'thread capabilities',\n runs: 'thread capabilities --check',\n },",
|
|
292
292
|
},
|
|
293
|
-
{
|
|
294
|
-
into: 'derivation.ts',
|
|
295
|
-
list: 'GENERATORS',
|
|
296
|
-
id: 'capability-noun',
|
|
297
|
-
source: " {\n id: 'capability-noun',\n at: 'node_modules/@prestack/thread/dist/operations/makers/capability.js',\n describes: 'Reads and changes what this app exposes. `thread create capability` lists every operation with the surfaces it answers on, and `edit` switches one on or off.',\n version: 1,\n by: 'thread create capability',\n },",
|
|
298
|
-
},
|
|
299
|
-
{
|
|
300
|
-
into: 'derivation.ts',
|
|
301
|
-
list: 'GENERATORS',
|
|
302
|
-
id: 'trial-noun',
|
|
303
|
-
source: " {\n id: 'trial-noun',\n at: 'node_modules/@prestack/thread/dist/operations/makers/trial.js',\n describes: 'Runs one operation against an input you supply, and records what happened. `thread run trial <operation>` asks for that input, because what to run an operation on is the one thing nothing else can work out for you.',\n version: 1,\n by: 'thread run trial',\n },",
|
|
304
|
-
},
|
|
305
293
|
{
|
|
306
294
|
into: 'derivation.ts',
|
|
307
295
|
list: 'GENERATORS',
|
|
@@ -320,18 +308,6 @@ const SHIPPED = [
|
|
|
320
308
|
id: 'permits-generator',
|
|
321
309
|
source: " {\n id: 'permits-generator',\n at: 'node_modules/@prestack/thread/dist/operations/generators/permits.js',\n describes: 'Writes the check this app runs before any operation — one branch per grant, so who may ask for what comes from one statement rather than being repeated in every handler. It refuses a grant it cannot check honestly, such as one that would admit a caller nobody authenticated.',\n version: 1,\n by: 'thread permits',\n runs: 'thread permits --check',\n },",
|
|
322
310
|
},
|
|
323
|
-
{
|
|
324
|
-
into: 'derivation.ts',
|
|
325
|
-
list: 'GENERATORS',
|
|
326
|
-
id: 'grant-generator',
|
|
327
|
-
source: " {\n id: 'grant-generator',\n at: 'node_modules/@prestack/thread/dist/operations/generators/grant.js',\n describes: 'Records who may ask this app to do what. Run with nothing, it lists every operation and every grant already written. It builds the condition one answer at a time, offering only what the answer before it allows, so an impossible comparison is refused as it is typed.',\n version: 1,\n by: 'thread grant',\n },",
|
|
328
|
-
},
|
|
329
|
-
{
|
|
330
|
-
into: 'derivation.ts',
|
|
331
|
-
list: 'GENERATORS',
|
|
332
|
-
id: 'operation-noun',
|
|
333
|
-
source: " {\n id: 'operation-noun',\n at: 'node_modules/@prestack/thread/dist/operations/generators/operation.js',\n describes: 'Declares something this app can be asked to do, and the steps it is done in. This row is what makes `operation` one of the things `thread create` offers — the nouns are not a list inside the command, but rows like this one.',\n version: 1,\n by: 'thread create operation',\n },",
|
|
334
|
-
},
|
|
335
311
|
{
|
|
336
312
|
into: 'derivation.ts',
|
|
337
313
|
list: 'GENERATORS',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Attaching } from '../core/attach.ts'
|
|
2
2
|
import { named } from '../core/scope.ts'
|
|
3
3
|
|
|
4
|
+
import { LISTS } from '../core/descend.ts'
|
|
4
5
|
import { quoted } from '../core/rows.ts'
|
|
5
6
|
import type { Threaded } from '../core/thread.ts'
|
|
6
7
|
|
|
@@ -13,8 +14,6 @@ import { SUPPLIES, type Supplied } from './seams.ts'
|
|
|
13
14
|
|
|
14
15
|
const HOME = `node_modules/${named('operations')}/dist`
|
|
15
16
|
|
|
16
|
-
const LISTS = ['declares', 'derives', 'seeds'] as const
|
|
17
|
-
|
|
18
17
|
const VERSION = 1
|
|
19
18
|
|
|
20
19
|
const ROOT = 'operations'
|
|
@@ -115,7 +114,7 @@ const SEAMS =
|
|
|
115
114
|
'What this app hands its operations, written once and then yours. It starts by handing on everything src/_generated/seams.ts settles from your declarations. Replace a seam or add one by naming it in SEAMS: the queue, the events, telemetry, whatever a real deployment needs.'
|
|
116
115
|
|
|
117
116
|
const DECLARED_SEAMS =
|
|
118
|
-
'The seams your declarations settle. Rows go to the store each target derived,
|
|
117
|
+
'The seams your declarations settle. Rows go to the store each target derived, and until one does no store is handed, so an operation that needs one is refused; who is calling is read off the entity that names the caller; calls leave through http with credentials the vault opens. Nobody edits it: `thread capabilities` writes it again from the rows.'
|
|
119
118
|
|
|
120
119
|
const ACCESS_SOURCE = `import type { Grant } from './access.ts'
|
|
121
120
|
|
|
@@ -348,18 +347,6 @@ const SHIPPED: readonly { readonly into: string; readonly list: string; readonly
|
|
|
348
347
|
id: 'capability-generator',
|
|
349
348
|
source: " {\n id: 'capability-generator',\n at: 'node_modules/@prestack/thread/dist/operations/generators/capability.js',\n describes: 'Writes what can be reached and how, and refuses it once it has drifted. It reads each operation for its name, what it does and the shape of its input, so adding or renaming one changes what is reachable without anybody editing a list.',\n version: 1,\n by: 'thread capabilities',\n runs: 'thread capabilities --check',\n },",
|
|
350
349
|
},
|
|
351
|
-
{
|
|
352
|
-
into: 'derivation.ts',
|
|
353
|
-
list: 'GENERATORS',
|
|
354
|
-
id: 'capability-noun',
|
|
355
|
-
source: " {\n id: 'capability-noun',\n at: 'node_modules/@prestack/thread/dist/operations/makers/capability.js',\n describes: 'Reads and changes what this app exposes. `thread create capability` lists every operation with the surfaces it answers on, and `edit` switches one on or off.',\n version: 1,\n by: 'thread create capability',\n },",
|
|
356
|
-
},
|
|
357
|
-
{
|
|
358
|
-
into: 'derivation.ts',
|
|
359
|
-
list: 'GENERATORS',
|
|
360
|
-
id: 'trial-noun',
|
|
361
|
-
source: " {\n id: 'trial-noun',\n at: 'node_modules/@prestack/thread/dist/operations/makers/trial.js',\n describes: 'Runs one operation against an input you supply, and records what happened. `thread run trial <operation>` asks for that input, because what to run an operation on is the one thing nothing else can work out for you.',\n version: 1,\n by: 'thread run trial',\n },",
|
|
362
|
-
},
|
|
363
350
|
{
|
|
364
351
|
into: 'derivation.ts',
|
|
365
352
|
list: 'GENERATORS',
|
|
@@ -378,18 +365,6 @@ const SHIPPED: readonly { readonly into: string; readonly list: string; readonly
|
|
|
378
365
|
id: 'permits-generator',
|
|
379
366
|
source: " {\n id: 'permits-generator',\n at: 'node_modules/@prestack/thread/dist/operations/generators/permits.js',\n describes: 'Writes the check this app runs before any operation — one branch per grant, so who may ask for what comes from one statement rather than being repeated in every handler. It refuses a grant it cannot check honestly, such as one that would admit a caller nobody authenticated.',\n version: 1,\n by: 'thread permits',\n runs: 'thread permits --check',\n },",
|
|
380
367
|
},
|
|
381
|
-
{
|
|
382
|
-
into: 'derivation.ts',
|
|
383
|
-
list: 'GENERATORS',
|
|
384
|
-
id: 'grant-generator',
|
|
385
|
-
source: " {\n id: 'grant-generator',\n at: 'node_modules/@prestack/thread/dist/operations/generators/grant.js',\n describes: 'Records who may ask this app to do what. Run with nothing, it lists every operation and every grant already written. It builds the condition one answer at a time, offering only what the answer before it allows, so an impossible comparison is refused as it is typed.',\n version: 1,\n by: 'thread grant',\n },",
|
|
386
|
-
},
|
|
387
|
-
{
|
|
388
|
-
into: 'derivation.ts',
|
|
389
|
-
list: 'GENERATORS',
|
|
390
|
-
id: 'operation-noun',
|
|
391
|
-
source: " {\n id: 'operation-noun',\n at: 'node_modules/@prestack/thread/dist/operations/generators/operation.js',\n describes: 'Declares something this app can be asked to do, and the steps it is done in. This row is what makes `operation` one of the things `thread create` offers — the nouns are not a list inside the command, but rows like this one.',\n version: 1,\n by: 'thread create operation',\n },",
|
|
392
|
-
},
|
|
393
368
|
{
|
|
394
369
|
into: 'derivation.ts',
|
|
395
370
|
list: 'GENERATORS',
|
|
@@ -171,9 +171,8 @@ export const dispatched = (reached) => [
|
|
|
171
171
|
' operation: Operation<I, R>,',
|
|
172
172
|
' rawInput: unknown,',
|
|
173
173
|
' asking: Actor,',
|
|
174
|
-
'
|
|
174
|
+
' seams: Seams,',
|
|
175
175
|
'): Promise<Result<unknown>> {',
|
|
176
|
-
' const seams = running(handed)',
|
|
177
176
|
' const id = operation.id',
|
|
178
177
|
' const who = person(asking)',
|
|
179
178
|
' const run = who?.run ?? seams.random.uuid()',
|
|
@@ -186,7 +185,7 @@ export const dispatched = (reached) => [
|
|
|
186
185
|
' let granted: string | undefined',
|
|
187
186
|
'',
|
|
188
187
|
' const sank = (what: string) => (thrown: unknown): void => {',
|
|
189
|
-
" seams.log
|
|
188
|
+
" seams.log.write('error', id, actor, {",
|
|
190
189
|
' [`${what}_failed`]: thrown instanceof Error ? thrown.message : String(thrown),',
|
|
191
190
|
' })',
|
|
192
191
|
' }',
|
|
@@ -192,9 +192,8 @@ export const dispatched = (
|
|
|
192
192
|
' operation: Operation<I, R>,',
|
|
193
193
|
' rawInput: unknown,',
|
|
194
194
|
' asking: Actor,',
|
|
195
|
-
'
|
|
195
|
+
' seams: Seams,',
|
|
196
196
|
'): Promise<Result<unknown>> {',
|
|
197
|
-
' const seams = running(handed)',
|
|
198
197
|
' const id = operation.id',
|
|
199
198
|
' const who = person(asking)',
|
|
200
199
|
' const run = who?.run ?? seams.random.uuid()',
|
|
@@ -207,7 +206,7 @@ export const dispatched = (
|
|
|
207
206
|
' let granted: string | undefined',
|
|
208
207
|
'',
|
|
209
208
|
' const sank = (what: string) => (thrown: unknown): void => {',
|
|
210
|
-
" seams.log
|
|
209
|
+
" seams.log.write('error', id, actor, {",
|
|
211
210
|
' [`${what}_failed`]: thrown instanceof Error ? thrown.message : String(thrown),',
|
|
212
211
|
' })',
|
|
213
212
|
' }',
|
|
@@ -6,11 +6,11 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
6
6
|
}
|
|
7
7
|
return path;
|
|
8
8
|
};
|
|
9
|
-
import { existsSync,
|
|
10
|
-
import {
|
|
9
|
+
import { existsSync, readdirSync, readFileSync, writeFileSync } from "../../core/files.js";
|
|
10
|
+
import { resolve } from 'node:path';
|
|
11
11
|
import { argv, stdout } from 'node:process';
|
|
12
12
|
import { pathToFileURL } from 'node:url';
|
|
13
|
-
import { marked, wordsIn } from "../../core/
|
|
13
|
+
import { marked, wordsIn } from "../../core/answers.js";
|
|
14
14
|
import { ROOT, TREE, descend } from "../../core/descend.js";
|
|
15
15
|
import { exit, invoked } from "../../core/invoked.js";
|
|
16
16
|
import { named as packageOf } from "../../core/scope.js";
|
|
@@ -460,7 +460,7 @@ const width = Math.max(...Object.keys(HANDED).map((one) => one.length));
|
|
|
460
460
|
const handing = (stores, keeping, vaulted) => [
|
|
461
461
|
`capabilities: seeded ${SEAMS_AT} — what this app hands its operations, and yours from here.`,
|
|
462
462
|
` It hands on everything ${DECLARED_SEAMS_AT} settles from your declarations: rows go to ` +
|
|
463
|
-
(stores.length === 0 ? '
|
|
463
|
+
(stores.length === 0 ? 'no store yet — no target keeps entities, so an operation that needs one is refused' : stores.join(', ')) +
|
|
464
464
|
`, who is asking is ${keeping ? 'read off the entity that names the caller' : 'nobody until an entity names the caller'}, ` +
|
|
465
465
|
`calls leave through http${vaulted ? ' with credentials opened by the vault' : ''}.`,
|
|
466
466
|
' Replace a seam, or add one, by naming it in SEAMS. Every seam an operation can be handed:',
|
|
@@ -561,7 +561,6 @@ if (invoked(import.meta.url)) {
|
|
|
561
561
|
console.error(`capabilities: ${DECLARED_SEAMS_AT} is not what the declarations settle. Run \`thread capabilities\` and commit the result.`);
|
|
562
562
|
}
|
|
563
563
|
else {
|
|
564
|
-
mkdirSync(dirname(at), { recursive: true });
|
|
565
564
|
writeFileSync(at, text, 'utf8');
|
|
566
565
|
console.log(`capabilities: wrote ${DECLARED_SEAMS_AT} — the seams your targets, entities, grants and secrets settle.`);
|
|
567
566
|
}
|
|
@@ -573,7 +572,6 @@ if (invoked(import.meta.url)) {
|
|
|
573
572
|
console.error(`capabilities: ${SEAMS_AT} is not there, and it is what hands every operation its seams. Run \`thread capabilities\` — it seeds the file once, and from then on it is yours.`);
|
|
574
573
|
}
|
|
575
574
|
else {
|
|
576
|
-
mkdirSync(dirname(seed), { recursive: true });
|
|
577
575
|
writeFileSync(seed, seeded(), 'utf8');
|
|
578
576
|
stdout.write(handing(stores, keeping, vaulted));
|
|
579
577
|
}
|
|
@@ -603,7 +601,6 @@ if (invoked(import.meta.url)) {
|
|
|
603
601
|
}
|
|
604
602
|
for (const one of written) {
|
|
605
603
|
const path = resolve(ROOT, one.at);
|
|
606
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
607
604
|
writeFileSync(path, one.text);
|
|
608
605
|
}
|
|
609
606
|
const shipped = found.filter(held).length;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { existsSync,
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, writeFileSync } from '../../core/files.ts'
|
|
2
2
|
import { dirname, resolve } from 'node:path'
|
|
3
3
|
import { argv, stdout } from 'node:process'
|
|
4
4
|
import { pathToFileURL } from 'node:url'
|
|
5
5
|
|
|
6
|
-
import { marked, wordsIn } from '../../core/
|
|
6
|
+
import { marked, wordsIn } from '../../core/answers.ts'
|
|
7
7
|
import { ROOT, TREE, descend } from '../../core/descend.ts'
|
|
8
8
|
import { exit, invoked } from '../../core/invoked.ts'
|
|
9
9
|
import { named as packageOf } from '../../core/scope.ts'
|
|
@@ -509,7 +509,7 @@ const handing = (stores: readonly string[], keeping: boolean, vaulted: boolean):
|
|
|
509
509
|
[
|
|
510
510
|
`capabilities: seeded ${SEAMS_AT} — what this app hands its operations, and yours from here.`,
|
|
511
511
|
` It hands on everything ${DECLARED_SEAMS_AT} settles from your declarations: rows go to ` +
|
|
512
|
-
(stores.length === 0 ? '
|
|
512
|
+
(stores.length === 0 ? 'no store yet — no target keeps entities, so an operation that needs one is refused' : stores.join(', ')) +
|
|
513
513
|
`, who is asking is ${keeping ? 'read off the entity that names the caller' : 'nobody until an entity names the caller'}, ` +
|
|
514
514
|
`calls leave through http${vaulted ? ' with credentials opened by the vault' : ''}.`,
|
|
515
515
|
' Replace a seam, or add one, by naming it in SEAMS. Every seam an operation can be handed:',
|
|
@@ -635,7 +635,6 @@ if (invoked(import.meta.url)) {
|
|
|
635
635
|
`capabilities: ${DECLARED_SEAMS_AT} is not what the declarations settle. Run \`thread capabilities\` and commit the result.`,
|
|
636
636
|
)
|
|
637
637
|
} else {
|
|
638
|
-
mkdirSync(dirname(at), { recursive: true })
|
|
639
638
|
writeFileSync(at, text, 'utf8')
|
|
640
639
|
console.log(`capabilities: wrote ${DECLARED_SEAMS_AT} — the seams your targets, entities, grants and secrets settle.`)
|
|
641
640
|
}
|
|
@@ -649,7 +648,6 @@ if (invoked(import.meta.url)) {
|
|
|
649
648
|
`capabilities: ${SEAMS_AT} is not there, and it is what hands every operation its seams. Run \`thread capabilities\` — it seeds the file once, and from then on it is yours.`,
|
|
650
649
|
)
|
|
651
650
|
} else {
|
|
652
|
-
mkdirSync(dirname(seed), { recursive: true })
|
|
653
651
|
writeFileSync(seed, seeded(), 'utf8')
|
|
654
652
|
stdout.write(handing(stores, keeping, vaulted))
|
|
655
653
|
}
|
|
@@ -690,7 +688,6 @@ if (invoked(import.meta.url)) {
|
|
|
690
688
|
|
|
691
689
|
for (const one of written) {
|
|
692
690
|
const path = resolve(ROOT, one.at)
|
|
693
|
-
mkdirSync(dirname(path), { recursive: true })
|
|
694
691
|
writeFileSync(path, one.text)
|
|
695
692
|
}
|
|
696
693
|
|
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
-
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
-
});
|
|
6
|
-
}
|
|
7
|
-
return path;
|
|
8
|
-
};
|
|
9
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
10
|
-
import { dirname, resolve } from 'node:path';
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "../../core/files.js";
|
|
2
|
+
import { resolve } from 'node:path';
|
|
11
3
|
import { argv, stdout } from 'node:process';
|
|
12
4
|
import ts from 'typescript';
|
|
13
5
|
import { ROOT, descend } from "../../core/descend.js";
|
|
14
6
|
import { runChecker } from "../../core/finding.js";
|
|
15
7
|
import { exit, invoked } from "../../core/invoked.js";
|
|
16
|
-
import { inCode } from "../../core/rows.js";
|
|
8
|
+
import { inCode, valuesIn } from "../../core/rows.js";
|
|
17
9
|
import { addressOf, credentialsOf, reachOf } from "../../integrations/target.js";
|
|
18
10
|
import { DISPATCH_AT, dispatched } from "../dispatch.js";
|
|
19
11
|
import { SUPPLIES } from "../seams.js";
|
|
@@ -24,7 +16,7 @@ async function reaching() {
|
|
|
24
16
|
if (!existsSync(path))
|
|
25
17
|
return [];
|
|
26
18
|
try {
|
|
27
|
-
const taken = (
|
|
19
|
+
const taken = valuesIn(readFileSync(path, 'utf8'));
|
|
28
20
|
return taken[list] ?? [];
|
|
29
21
|
}
|
|
30
22
|
catch {
|
|
@@ -488,6 +480,10 @@ async function planned() {
|
|
|
488
480
|
return found;
|
|
489
481
|
}
|
|
490
482
|
function checked(plan) {
|
|
483
|
+
if (plan.length === 0) {
|
|
484
|
+
stdout.write('compile: no operation here states a body to compile, so there is nothing to check.\n');
|
|
485
|
+
exit(0);
|
|
486
|
+
}
|
|
491
487
|
const findings = plan.flatMap((one) => {
|
|
492
488
|
const path = resolve(ROOT, one.at);
|
|
493
489
|
if (one.because !== undefined) {
|
|
@@ -538,7 +534,6 @@ export async function compile(say = true) {
|
|
|
538
534
|
const path = resolve(ROOT, one.at);
|
|
539
535
|
if (existsSync(path) && readFileSync(path, 'utf8') === one.text)
|
|
540
536
|
continue;
|
|
541
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
542
537
|
writeFileSync(path, one.text, 'utf8');
|
|
543
538
|
written += 1;
|
|
544
539
|
if (say)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync,
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from '../../core/files.ts'
|
|
2
2
|
import { dirname, resolve } from 'node:path'
|
|
3
3
|
import { argv, stdout } from 'node:process'
|
|
4
4
|
|
|
@@ -7,7 +7,7 @@ import ts from 'typescript'
|
|
|
7
7
|
import { ROOT, descend } from '../../core/descend.ts'
|
|
8
8
|
import { runChecker, type Finding } from '../../core/finding.ts'
|
|
9
9
|
import { exit, invoked } from '../../core/invoked.ts'
|
|
10
|
-
import { inCode } from '../../core/rows.ts'
|
|
10
|
+
import { inCode, valuesIn } from '../../core/rows.ts'
|
|
11
11
|
|
|
12
12
|
import { addressOf, credentialsOf, reachOf, type Call, type Target } from '../../integrations/target.ts'
|
|
13
13
|
import type { Secret } from '../../integrations/secret.ts'
|
|
@@ -21,7 +21,7 @@ async function reaching(): Promise<Readonly<Record<string, ReturnType<typeof rea
|
|
|
21
21
|
const path = resolve(ROOT, `_threads/${file}`)
|
|
22
22
|
if (!existsSync(path)) return []
|
|
23
23
|
try {
|
|
24
|
-
const taken = (
|
|
24
|
+
const taken = valuesIn(readFileSync(path, 'utf8')) as Record<string, readonly T[] | undefined>
|
|
25
25
|
return taken[list] ?? []
|
|
26
26
|
} catch {
|
|
27
27
|
return []
|
|
@@ -568,6 +568,11 @@ async function planned(): Promise<readonly Wanted[]> {
|
|
|
568
568
|
}
|
|
569
569
|
|
|
570
570
|
function checked(plan: readonly Wanted[]): void {
|
|
571
|
+
if (plan.length === 0) {
|
|
572
|
+
stdout.write('compile: no operation here states a body to compile, so there is nothing to check.\n')
|
|
573
|
+
exit(0)
|
|
574
|
+
}
|
|
575
|
+
|
|
571
576
|
const findings: Finding[] = plan.flatMap((one): Finding[] => {
|
|
572
577
|
const path = resolve(ROOT, one.at)
|
|
573
578
|
|
|
@@ -622,7 +627,6 @@ export async function compile(say: boolean = true): Promise<number> {
|
|
|
622
627
|
}
|
|
623
628
|
const path = resolve(ROOT, one.at)
|
|
624
629
|
if (existsSync(path) && readFileSync(path, 'utf8') === one.text) continue
|
|
625
|
-
mkdirSync(dirname(path), { recursive: true })
|
|
626
630
|
writeFileSync(path, one.text, 'utf8')
|
|
627
631
|
written += 1
|
|
628
632
|
if (say) stdout.write(`compile: wrote ${one.at}\n`)
|
|
@@ -1,15 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
-
});
|
|
6
|
-
}
|
|
7
|
-
return path;
|
|
8
|
-
};
|
|
9
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
10
|
-
import { dirname, resolve } from 'node:path';
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "../../core/files.js";
|
|
2
|
+
import { valuesIn } from "../../core/rows.js";
|
|
3
|
+
import { resolve } from 'node:path';
|
|
11
4
|
import { argv, stderr, stdout } from 'node:process';
|
|
12
|
-
import { pathToFileURL } from 'node:url';
|
|
13
5
|
import { exit } from "../../core/invoked.js";
|
|
14
6
|
import { PUBLIC_ROLE as PUBLIC } from "../../core/actor.js";
|
|
15
7
|
import { ROOT, descend } from "../../core/descend.js";
|
|
@@ -35,7 +27,7 @@ async function taken(file, name, what) {
|
|
|
35
27
|
stop(`${at} is where this app states ${what}, and it is not there`);
|
|
36
28
|
let held;
|
|
37
29
|
try {
|
|
38
|
-
held = (
|
|
30
|
+
held = valuesIn(readFileSync(at));
|
|
39
31
|
}
|
|
40
32
|
catch (thrown) {
|
|
41
33
|
stop(`${at} could not be read: ${thrown instanceof Error ? thrown.message : String(thrown)}. A tree whose access ` +
|
|
@@ -190,7 +182,6 @@ if (CHECKING) {
|
|
|
190
182
|
runChecker('permits', findings, count);
|
|
191
183
|
exit(findings.length === 0 ? 0 : 1);
|
|
192
184
|
}
|
|
193
|
-
mkdirSync(dirname(permitted), { recursive: true });
|
|
194
185
|
writeFileSync(permitted, content);
|
|
195
186
|
stdout.write(`permits: wrote ${PERMITS_AT} — ${count}. ${DECLARED_SEAMS_AT} hands it to dispatch as the gate every operation passes; ` +
|
|
196
187
|
'`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,5 @@
|
|
|
1
|
-
import { existsSync,
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from '../../core/files.ts'
|
|
2
|
+
import { valuesIn } from '../../core/rows.ts'
|
|
2
3
|
import { dirname, resolve } from 'node:path'
|
|
3
4
|
import { argv, stderr, stdout } from 'node:process'
|
|
4
5
|
import { pathToFileURL } from 'node:url'
|
|
@@ -36,7 +37,7 @@ async function taken<T>(file: string, name: string, what: string): Promise<reado
|
|
|
36
37
|
if (!existsSync(at)) stop(`${at} is where this app states ${what}, and it is not there`)
|
|
37
38
|
let held: Record<string, unknown>
|
|
38
39
|
try {
|
|
39
|
-
held = (
|
|
40
|
+
held = valuesIn(readFileSync(at)) as Record<string, unknown>
|
|
40
41
|
} catch (thrown) {
|
|
41
42
|
stop(
|
|
42
43
|
`${at} could not be read: ${thrown instanceof Error ? thrown.message : String(thrown)}. A tree whose access ` +
|
|
@@ -215,7 +216,6 @@ if (CHECKING) {
|
|
|
215
216
|
exit(findings.length === 0 ? 0 : 1)
|
|
216
217
|
}
|
|
217
218
|
|
|
218
|
-
mkdirSync(dirname(permitted), { recursive: true })
|
|
219
219
|
writeFileSync(permitted, content)
|
|
220
220
|
stdout.write(
|
|
221
221
|
`permits: wrote ${PERMITS_AT} — ${count}. ${DECLARED_SEAMS_AT} hands it to dispatch as the gate every operation passes; ` +
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync,
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "../../core/files.js";
|
|
2
2
|
import { dirname, relative, resolve } from 'node:path';
|
|
3
3
|
import { argv, stdout } from 'node:process';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
@@ -194,6 +194,10 @@ function planned(bodies) {
|
|
|
194
194
|
return found;
|
|
195
195
|
}
|
|
196
196
|
function checked(plan) {
|
|
197
|
+
if (plan.length === 0) {
|
|
198
|
+
stdout.write('seed: this app declares no operation and no node type of its own, so there is no file to write or check.\n');
|
|
199
|
+
exit(0);
|
|
200
|
+
}
|
|
197
201
|
const findings = plan.flatMap((one) => {
|
|
198
202
|
const path = resolve(ROOT, one.at);
|
|
199
203
|
if (one.because !== undefined) {
|
|
@@ -267,7 +271,6 @@ export function seed(bodies = new Map(), say = true) {
|
|
|
267
271
|
}
|
|
268
272
|
if (held === one.text)
|
|
269
273
|
continue;
|
|
270
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
271
274
|
writeFileSync(path, one.text, 'utf8');
|
|
272
275
|
written += 1;
|
|
273
276
|
if (say)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync,
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from '../../core/files.ts'
|
|
2
2
|
import { dirname, relative, resolve } from 'node:path'
|
|
3
3
|
import { argv, stdout } from 'node:process'
|
|
4
4
|
import { fileURLToPath } from 'node:url'
|
|
@@ -249,6 +249,11 @@ function planned(bodies: ReadonlyMap<string, string>): readonly Wanted[] {
|
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
function checked(plan: readonly Wanted[]): void {
|
|
252
|
+
if (plan.length === 0) {
|
|
253
|
+
stdout.write('seed: this app declares no operation and no node type of its own, so there is no file to write or check.\n')
|
|
254
|
+
exit(0)
|
|
255
|
+
}
|
|
256
|
+
|
|
252
257
|
const findings: Finding[] = plan.flatMap((one): Finding[] => {
|
|
253
258
|
const path = resolve(ROOT, one.at)
|
|
254
259
|
|
|
@@ -332,7 +337,6 @@ export function seed(bodies: ReadonlyMap<string, string> = new Map(), say: boole
|
|
|
332
337
|
}
|
|
333
338
|
if (held === one.text) continue
|
|
334
339
|
|
|
335
|
-
mkdirSync(dirname(path), { recursive: true })
|
|
336
340
|
writeFileSync(path, one.text, 'utf8')
|
|
337
341
|
written += 1
|
|
338
342
|
if (say) stdout.write(`seed: wrote ${one.at}\n`)
|
|
@@ -6,8 +6,8 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
6
6
|
}
|
|
7
7
|
return path;
|
|
8
8
|
};
|
|
9
|
-
import { existsSync,
|
|
10
|
-
import {
|
|
9
|
+
import { existsSync, readFileSync, writeFileSync } from "../../core/files.js";
|
|
10
|
+
import { resolve } from 'node:path';
|
|
11
11
|
import { argv, stdout } from 'node:process';
|
|
12
12
|
import { pathToFileURL } from 'node:url';
|
|
13
13
|
import { ANONYMOUS } from "../../core/actor.js";
|
|
@@ -59,11 +59,8 @@ function seamsFor(one, scenario, stood, gate, known) {
|
|
|
59
59
|
...(known === undefined ? {} : { entities: known.entities, keys: known.keys }),
|
|
60
60
|
});
|
|
61
61
|
const found = made.seams;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return Promise.resolve({ allow: true, because: 'this app derives no gate, so nothing here can refuse' });
|
|
65
|
-
},
|
|
66
|
-
};
|
|
62
|
+
if (gate !== undefined)
|
|
63
|
+
found['permits'] = gate;
|
|
67
64
|
found['clock'] = { now: () => WHEN };
|
|
68
65
|
let drawn = 0;
|
|
69
66
|
found['random'] = {
|
|
@@ -239,8 +236,10 @@ async function standing() {
|
|
|
239
236
|
const taken = (await import(__rewriteRelativeImportExtension(pathToFileURL(at).href)));
|
|
240
237
|
held = taken.SECRETS ?? [];
|
|
241
238
|
}
|
|
242
|
-
catch {
|
|
243
|
-
return {}
|
|
239
|
+
catch (thrown) {
|
|
240
|
+
return (`_threads/secrets.ts is there and could not be read: ${thrown instanceof Error ? thrown.message : String(thrown)}. ` +
|
|
241
|
+
'A secrets sheet that cannot be read reports exactly like an app that declares none, so every trial would run ' +
|
|
242
|
+
'as though nothing were sealed and pass having proved that');
|
|
244
243
|
}
|
|
245
244
|
const found = {};
|
|
246
245
|
for (const one of held) {
|
|
@@ -257,6 +256,8 @@ export async function record() {
|
|
|
257
256
|
if (declared.length === 0)
|
|
258
257
|
return { trials: [], refusals: [] };
|
|
259
258
|
const stood = await standing();
|
|
259
|
+
if (typeof stood === 'string')
|
|
260
|
+
return { trials: [], refusals: [stood] };
|
|
260
261
|
const at = resolve(ROOT, DISPATCH_AT);
|
|
261
262
|
if (!existsSync(at)) {
|
|
262
263
|
return {
|
|
@@ -371,7 +372,6 @@ if (invoked(import.meta.url)) {
|
|
|
371
372
|
exit(1);
|
|
372
373
|
}
|
|
373
374
|
const at = resolve(ROOT, TRIALS_AT);
|
|
374
|
-
mkdirSync(dirname(at), { recursive: true });
|
|
375
375
|
writeFileSync(at, printed(trials));
|
|
376
376
|
const measured = trials.filter((one) => one.measured).length;
|
|
377
377
|
stdout.write(`trial: wrote ${TRIALS_AT} — ${String(trials.length)} trial(s) from ${String(measured)} run(s) that reached an operation.\n`);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync,
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from '../../core/files.ts'
|
|
2
2
|
import { dirname, resolve } from 'node:path'
|
|
3
3
|
import { argv, stdout } from 'node:process'
|
|
4
4
|
import { pathToFileURL } from 'node:url'
|
|
@@ -116,11 +116,7 @@ function seamsFor(
|
|
|
116
116
|
|
|
117
117
|
const found = made.seams as unknown as Record<string, unknown>
|
|
118
118
|
|
|
119
|
-
found['permits'] = gate
|
|
120
|
-
check() {
|
|
121
|
-
return Promise.resolve({ allow: true, because: 'this app derives no gate, so nothing here can refuse' })
|
|
122
|
-
},
|
|
123
|
-
}
|
|
119
|
+
if (gate !== undefined) found['permits'] = gate
|
|
124
120
|
found['clock'] = { now: () => WHEN }
|
|
125
121
|
|
|
126
122
|
let drawn = 0
|
|
@@ -335,7 +331,7 @@ export function unproven(run: Run): readonly string[] {
|
|
|
335
331
|
return said
|
|
336
332
|
}
|
|
337
333
|
|
|
338
|
-
async function standing(): Promise<Readonly<Record<string, string
|
|
334
|
+
async function standing(): Promise<Readonly<Record<string, string>> | string> {
|
|
339
335
|
const at = resolve(ROOT, '_threads/secrets.ts')
|
|
340
336
|
if (!existsSync(at)) return {}
|
|
341
337
|
let held: readonly { readonly id: string; readonly sends?: unknown }[]
|
|
@@ -344,8 +340,12 @@ async function standing(): Promise<Readonly<Record<string, string>>> {
|
|
|
344
340
|
readonly SECRETS?: readonly { readonly id: string; readonly sends?: unknown }[]
|
|
345
341
|
}
|
|
346
342
|
held = taken.SECRETS ?? []
|
|
347
|
-
} catch {
|
|
348
|
-
return
|
|
343
|
+
} catch (thrown) {
|
|
344
|
+
return (
|
|
345
|
+
`_threads/secrets.ts is there and could not be read: ${thrown instanceof Error ? thrown.message : String(thrown)}. ` +
|
|
346
|
+
'A secrets sheet that cannot be read reports exactly like an app that declares none, so every trial would run ' +
|
|
347
|
+
'as though nothing were sealed and pass having proved that'
|
|
348
|
+
)
|
|
349
349
|
}
|
|
350
350
|
const found: Record<string, string> = {}
|
|
351
351
|
for (const one of held) {
|
|
@@ -364,6 +364,7 @@ export async function record(): Promise<{ readonly trials: readonly Trial[]; rea
|
|
|
364
364
|
if (declared.length === 0) return { trials: [], refusals: [] }
|
|
365
365
|
|
|
366
366
|
const stood = await standing()
|
|
367
|
+
if (typeof stood === 'string') return { trials: [], refusals: [stood] }
|
|
367
368
|
|
|
368
369
|
const at = resolve(ROOT, DISPATCH_AT)
|
|
369
370
|
if (!existsSync(at)) {
|
|
@@ -519,7 +520,6 @@ if (invoked(import.meta.url)) {
|
|
|
519
520
|
}
|
|
520
521
|
|
|
521
522
|
const at = resolve(ROOT, TRIALS_AT)
|
|
522
|
-
mkdirSync(dirname(at), { recursive: true })
|
|
523
523
|
writeFileSync(at, printed(trials))
|
|
524
524
|
const measured = trials.filter((one) => one.measured).length
|
|
525
525
|
stdout.write(
|
package/dist/operations/http.js
CHANGED
|
@@ -105,7 +105,10 @@ export function recordingHttp(script = {}) {
|
|
|
105
105
|
headers: Object.fromEntries(Object.keys(request.headers ?? {}).map((one) => [one, REDACTED])),
|
|
106
106
|
body,
|
|
107
107
|
});
|
|
108
|
-
const answer = script[`${request.method} ${request.path}`]
|
|
108
|
+
const answer = script[`${request.method} ${request.path}`];
|
|
109
|
+
if (answer === undefined) {
|
|
110
|
+
throw new Error(`this scenario scripts no answer for "${request.method} ${request.path}", so nothing here knows what ${request.target} would say. Add that key to the scenario's answers — a call answered by something nobody scripted proves it was made and nothing about what came back.`);
|
|
111
|
+
}
|
|
109
112
|
const answered = new TextEncoder().encode(answer.body ?? '');
|
|
110
113
|
const headers = answer.headers ?? {};
|
|
111
114
|
return {
|
package/dist/operations/http.ts
CHANGED
|
@@ -147,7 +147,12 @@ export function recordingHttp(
|
|
|
147
147
|
body,
|
|
148
148
|
})
|
|
149
149
|
|
|
150
|
-
const answer = script[`${request.method} ${request.path}`]
|
|
150
|
+
const answer = script[`${request.method} ${request.path}`]
|
|
151
|
+
if (answer === undefined) {
|
|
152
|
+
throw new Error(
|
|
153
|
+
`this scenario scripts no answer for "${request.method} ${request.path}", so nothing here knows what ${request.target} would say. Add that key to the scenario's answers — a call answered by something nobody scripted proves it was made and nothing about what came back.`,
|
|
154
|
+
)
|
|
155
|
+
}
|
|
151
156
|
const answered = new TextEncoder().encode(answer.body ?? '')
|
|
152
157
|
const headers = answer.headers ?? {}
|
|
153
158
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prestack/thread",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"./*": "./dist/*.js"
|
|
12
12
|
},
|
|
13
13
|
"bin": {
|
|
14
|
-
"thread": "dist/core/
|
|
14
|
+
"thread": "dist/core/client.js"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"esbuild": "^0.28.2",
|
package/dist/core/cli.d.ts
DELETED