@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,25 +1,26 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync } from '../../
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, type Answering, type Listed } from '../../integrations/disk.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
6
|
import { ANONYMOUS, type Actor } from '../../core/actor.ts'
|
|
7
|
-
import { ROOT,
|
|
7
|
+
import { ROOT, descend } from '../../core/descend.ts'
|
|
8
8
|
import { exit, invoked } from '../../core/invoked.ts'
|
|
9
|
+
import { reachOf, standsHere, type Call, type Row, type Target } from '../../integrations/target.ts'
|
|
9
10
|
|
|
10
|
-
import { recordingHttp, type ScriptedAnswer } from '
|
|
11
|
-
import {
|
|
11
|
+
import { recordingHttp, type RecordedCall, type Scripted, type ScriptedAnswer } from '../../integrations/https.ts'
|
|
12
|
+
import { standing, type Kept, type Stood } from '../../integrations/pglite.ts'
|
|
12
13
|
import { TRIALS_AT, type Operation } from '../operations.ts'
|
|
13
14
|
import { PERMITS_AT } from '../access.ts'
|
|
14
15
|
import type { Result } from '../result.ts'
|
|
15
|
-
import type {
|
|
16
|
+
import type { Vault } from '../../integrations/secret.ts'
|
|
16
17
|
import { operations, types } from './seed.ts'
|
|
17
18
|
|
|
18
19
|
export { TRIALS_AT }
|
|
19
20
|
|
|
20
21
|
const DISPATCH_AT = 'operations/_dispatch.ts'
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
|
|
23
24
|
|
|
24
25
|
const ACCESS_AT = '_threads/access.ts'
|
|
25
26
|
|
|
@@ -36,9 +37,11 @@ export interface Scenario {
|
|
|
36
37
|
|
|
37
38
|
readonly rows?: readonly { readonly entity: string; readonly row: Row }[]
|
|
38
39
|
|
|
39
|
-
readonly answers?: Readonly<Record<string,
|
|
40
|
+
readonly answers?: Readonly<Record<string, Scripted>>
|
|
40
41
|
|
|
41
42
|
readonly views?: Readonly<Record<string, readonly unknown[]>>
|
|
43
|
+
|
|
44
|
+
readonly files?: Readonly<Record<string, string>>
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
export interface Trial {
|
|
@@ -53,7 +56,6 @@ export interface Trial {
|
|
|
53
56
|
|
|
54
57
|
readonly kept: unknown
|
|
55
58
|
|
|
56
|
-
readonly observed: unknown
|
|
57
59
|
|
|
58
60
|
readonly called: unknown
|
|
59
61
|
}
|
|
@@ -99,55 +101,185 @@ const asking = (scenario: Scenario): Actor => ({
|
|
|
99
101
|
...(scenario.actor ?? ANONYMOUS),
|
|
100
102
|
run: 'trial',
|
|
101
103
|
replay: `trial_${scenario.id}`,
|
|
104
|
+
moment: new Date(WHEN).toISOString(),
|
|
102
105
|
})
|
|
103
106
|
|
|
104
|
-
function
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
107
|
+
function programmed(word: string, names: readonly string[]): Record<string, unknown> {
|
|
108
|
+
const made: Record<string, unknown> = {}
|
|
109
|
+
for (const order of names) {
|
|
110
|
+
made[order] = (): never => {
|
|
111
|
+
throw new Error(
|
|
112
|
+
word + ' was asked to run ' + order + ', and this scenario says nothing about what that did. A trial stands a ' +
|
|
113
|
+
'disk up out of the files its scenario states, and there is nowhere yet to state what a program or a package answered, so ' +
|
|
114
|
+
'a scenario cannot give either an order. This says that rather than inventing a result for one.',
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return made
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function packaged(
|
|
122
|
+
word: string,
|
|
123
|
+
names: readonly string[],
|
|
124
|
+
script: Readonly<Record<string, Scripted>>,
|
|
125
|
+
into: RecordedCall[],
|
|
126
|
+
): Record<string, unknown> {
|
|
127
|
+
const spent = new Map<string, number>()
|
|
128
|
+
const made: Record<string, unknown> = {}
|
|
129
|
+
for (const name of names) {
|
|
130
|
+
made[name] = async (given?: unknown): Promise<unknown> => {
|
|
131
|
+
const key = word + ' ' + name
|
|
132
|
+
into.push({ target: word, method: 'CALL', path: name, headers: {}, body: JSON.stringify(stable(given ?? null)) })
|
|
133
|
+
const held = script[key]
|
|
134
|
+
if (held === undefined) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
'this scenario scripts no answer for "' + key + '", so nothing here knows what ' + word + ' would hand back. Add ' +
|
|
137
|
+
'that key to the scenario\'s answers, with what the call returns written as JSON in its body.',
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
const each = Array.isArray(held) ? (held as readonly ScriptedAnswer[]) : undefined
|
|
141
|
+
const at = spent.get(key) ?? 0
|
|
142
|
+
spent.set(key, at + 1)
|
|
143
|
+
const answer = each === undefined ? (held as ScriptedAnswer) : each[at]
|
|
144
|
+
if (answer === undefined) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
'this scenario scripts ' + String(each?.length ?? 0) + ' answer(s) for "' + key + '" and it has now been called ' +
|
|
147
|
+
String(at + 1) + ' time(s). A node that calls the same thing again needs one answer per call, in the order they come back.',
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
if (answer.status !== 200) throw new Error(answer.body ?? word + ' ' + name + ' failed with ' + String(answer.status))
|
|
151
|
+
return answer.body === undefined ? undefined : (JSON.parse(answer.body) as unknown)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return made
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function disked(files: Readonly<Record<string, string>>): Answering {
|
|
158
|
+
const held = new Map<string, string>(Object.entries(files))
|
|
159
|
+
const under = (at: string): boolean => [...held.keys()].some((one) => one.startsWith(at + '/'))
|
|
160
|
+
const gone = (at: string): Error =>
|
|
161
|
+
new Error(at + ' is not in this scenario, and a trial answers a file order against the files its scenario states')
|
|
162
|
+
return {
|
|
163
|
+
kind: (at) => (held.has(at) ? 'file' : under(at) ? 'folder' : 'none'),
|
|
164
|
+
read: (at) => {
|
|
165
|
+
const said = held.get(at)
|
|
166
|
+
if (said === undefined) throw gone(at)
|
|
167
|
+
return said
|
|
168
|
+
},
|
|
169
|
+
write: (at, said) => {
|
|
170
|
+
held.set(at, said)
|
|
171
|
+
},
|
|
172
|
+
list: (at) => {
|
|
173
|
+
const inside = new Map<string, Listed>()
|
|
174
|
+
for (const one of held.keys()) {
|
|
175
|
+
if (!one.startsWith(at + '/')) continue
|
|
176
|
+
const rest = one.slice(at.length + 1)
|
|
177
|
+
const cut = rest.indexOf('/')
|
|
178
|
+
const name = cut === -1 ? rest : rest.slice(0, cut)
|
|
179
|
+
inside.set(name, { name, kind: cut === -1 ? 'file' : 'folder' })
|
|
180
|
+
}
|
|
181
|
+
return [...inside.values()]
|
|
182
|
+
},
|
|
183
|
+
stat: (at) => {
|
|
184
|
+
const said = held.get(at)
|
|
185
|
+
if (said === undefined) throw gone(at)
|
|
186
|
+
return { size: said.length, modified: 0 }
|
|
187
|
+
},
|
|
188
|
+
remove: (at) => {
|
|
189
|
+
held.delete(at)
|
|
127
190
|
},
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
191
|
+
real: (at) => at,
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function vaulting(stood: Readonly<Record<string, string>>): Vault {
|
|
196
|
+
return {
|
|
197
|
+
async resolve(refs) {
|
|
198
|
+
const found: Record<string, string> = {}
|
|
199
|
+
for (const ref of refs) {
|
|
200
|
+
const value = stood[ref]
|
|
201
|
+
if (value === undefined) {
|
|
202
|
+
throw new Error(
|
|
203
|
+
ref + ' is not a secret this app declares, so a trial has nothing to stand in for it. Declare it with ' +
|
|
204
|
+
'`thread create secret`, or stop requiring the target that asks for it.',
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
found[ref] = value
|
|
208
|
+
}
|
|
209
|
+
return found
|
|
131
210
|
},
|
|
132
211
|
}
|
|
212
|
+
}
|
|
133
213
|
|
|
214
|
+
async function standingStore(row: Target): Promise<Stood | string> {
|
|
215
|
+
const said = row.derives?.find((each) => each.id === row.id + '_store')?.at
|
|
216
|
+
if (said === undefined) {
|
|
217
|
+
return row.id + ' keeps rows and its row derives no store, so a trial has nothing to stand up. Run `thread schema`'
|
|
218
|
+
}
|
|
219
|
+
const at = resolve(ROOT, said)
|
|
220
|
+
if (!existsSync(at)) return said + ' is not there, so ' + row.id + ' cannot be stood up. Run `thread schema`'
|
|
221
|
+
const made = (await import(pathToFileURL(at).href)) as { readonly kept?: Kept }
|
|
222
|
+
const held = made.kept
|
|
223
|
+
if (held === undefined) {
|
|
224
|
+
return said + ' says nothing about what ' + row.id + ' keeps or with what schema. Run `thread schema`'
|
|
225
|
+
}
|
|
226
|
+
return standing(held)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async function openedFor(
|
|
230
|
+
one: Operation<unknown>,
|
|
231
|
+
scenario: Scenario,
|
|
232
|
+
stood: Readonly<Record<string, string>>,
|
|
233
|
+
targets: readonly Target[] = [],
|
|
234
|
+
calls: readonly Call[] = [],
|
|
235
|
+
): Promise<{
|
|
236
|
+
readonly opened: Readonly<Record<string, unknown>>
|
|
237
|
+
readonly opening: Vault
|
|
238
|
+
readonly stores: readonly Stood[]
|
|
239
|
+
readonly calls: () => unknown
|
|
240
|
+
} | string> {
|
|
134
241
|
const recorder = recordingHttp(scenario.answers ?? {})
|
|
135
|
-
|
|
242
|
+
const packages: RecordedCall[] = []
|
|
243
|
+
const opening = vaulting(stood)
|
|
244
|
+
const opened: Record<string, unknown> = {}
|
|
245
|
+
const stores: Stood[] = []
|
|
246
|
+
|
|
247
|
+
const answering = (row: Target): readonly string[] =>
|
|
248
|
+
calls.filter((each) => each.of === row.id && row.takes.includes(each.id)).map((each) => each.id.replace(/^cl_/, ''))
|
|
249
|
+
for (const word of one.requires) {
|
|
250
|
+
const row = targets.find((each) => each.id === word)
|
|
251
|
+
if (row === undefined || !standsHere(row, targets)) continue
|
|
252
|
+
const reach = reachOf(row.id)
|
|
253
|
+
if (reach === 'disk') opened[word] = disked(scenario.files ?? {})
|
|
254
|
+
else if (reach === 'cli') opened[word] = programmed(word, answering(row))
|
|
255
|
+
else if (reach === 'https') opened[word] = recorder
|
|
256
|
+
else if (reach === 'sdk') opened[word] = packaged(word, answering(row), scenario.answers ?? {}, packages)
|
|
257
|
+
else {
|
|
258
|
+
const held = await standingStore(row)
|
|
259
|
+
if (typeof held === 'string') return held
|
|
260
|
+
opened[word] = held.store
|
|
261
|
+
stores.push(held)
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
136
265
|
|
|
137
|
-
|
|
266
|
+
|
|
267
|
+
return { opened, opening, stores, calls: () => [...recorder['calls'], ...packages] }
|
|
138
268
|
}
|
|
139
269
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
270
|
+
const BEFORE = new Set(['denied', 'invalid'])
|
|
271
|
+
|
|
272
|
+
function entered(result: unknown): boolean {
|
|
273
|
+
if (typeof result !== 'object' || result === null) return false
|
|
274
|
+
const held = result as { readonly ok?: unknown; readonly code?: unknown }
|
|
275
|
+
if (held.ok === true) return true
|
|
276
|
+
return held.ok === false && !BEFORE.has(String(held.code))
|
|
145
277
|
}
|
|
146
278
|
|
|
147
279
|
function denied(result: unknown): boolean {
|
|
148
280
|
if (typeof result !== 'object' || result === null) return false
|
|
149
281
|
const held = result as { readonly ok?: unknown; readonly code?: unknown }
|
|
150
|
-
return held.ok === false && held.code
|
|
282
|
+
return held.ok === false && BEFORE.has(String(held.code))
|
|
151
283
|
}
|
|
152
284
|
|
|
153
285
|
export async function runScenario(
|
|
@@ -157,38 +289,48 @@ export async function runScenario(
|
|
|
157
289
|
operation: Operation<unknown>,
|
|
158
290
|
input: unknown,
|
|
159
291
|
actor: Actor,
|
|
160
|
-
|
|
292
|
+
opened: Readonly<Record<string, unknown>>,
|
|
293
|
+
opening: Vault,
|
|
161
294
|
) => Promise<Result<unknown>>,
|
|
162
295
|
stood: Readonly<Record<string, string>> = {},
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
): Promise<Trial> {
|
|
296
|
+
targets: readonly Target[] = [],
|
|
297
|
+
calls: readonly Call[] = [],
|
|
298
|
+
): Promise<Trial | string> {
|
|
166
299
|
|
|
167
|
-
const made =
|
|
300
|
+
const made = await openedFor(one, scenario, stood, targets, calls)
|
|
301
|
+
if (typeof made === 'string') return made
|
|
168
302
|
|
|
169
303
|
const actor = asking(scenario)
|
|
170
304
|
|
|
171
|
-
for (const
|
|
172
|
-
const held = made.
|
|
173
|
-
|
|
174
|
-
|
|
305
|
+
for (const each of scenario.rows ?? []) {
|
|
306
|
+
const held = made.stores.find((store) => store.keeps.includes(each.entity))
|
|
307
|
+
if (held === undefined) {
|
|
308
|
+
return (
|
|
309
|
+
'`' + one.id + '` is tried with a row of "' + each.entity + '" and no target it requires keeps that entity, ' +
|
|
310
|
+
'so there is nowhere to put it. Require the target that keeps it, or take that row off the scenario'
|
|
311
|
+
)
|
|
312
|
+
}
|
|
313
|
+
await held.seed(actor, [each])
|
|
175
314
|
}
|
|
176
315
|
|
|
177
316
|
let result: unknown
|
|
178
317
|
try {
|
|
179
|
-
result = await dispatch(one, scenario
|
|
318
|
+
result = await dispatch(one, scenario['input'], actor, made.opened, made.opening)
|
|
180
319
|
} catch (thrown) {
|
|
181
320
|
result = { threw: thrown instanceof Error ? thrown.message : String(thrown) }
|
|
182
321
|
}
|
|
183
322
|
|
|
323
|
+
const kept: Record<string, unknown> = {}
|
|
324
|
+
for (const held of made.stores) Object.assign(kept, await held.taken(actor))
|
|
325
|
+
|
|
184
326
|
return {
|
|
185
327
|
operation: one.id,
|
|
186
328
|
scenario: scenario.id,
|
|
187
329
|
refused: denied(result),
|
|
188
|
-
measured: entered(
|
|
330
|
+
measured: entered(result),
|
|
189
331
|
result,
|
|
190
|
-
kept
|
|
191
|
-
|
|
332
|
+
kept,
|
|
333
|
+
|
|
192
334
|
called: made.calls(),
|
|
193
335
|
}
|
|
194
336
|
}
|
|
@@ -252,15 +394,15 @@ export function compared(was: readonly Trial[], now: readonly Trial[]): Run {
|
|
|
252
394
|
|
|
253
395
|
if (one.refused && one.measured) {
|
|
254
396
|
failures.push(
|
|
255
|
-
'this
|
|
256
|
-
'
|
|
397
|
+
'this run was refused before the operation could start and REACHED THE OPERATION anyway — dispatch let a ' +
|
|
398
|
+
'refused request through to the compiled function, which is the gate not holding rather than a trial drifting',
|
|
257
399
|
)
|
|
258
400
|
}
|
|
259
401
|
|
|
260
402
|
if (older === undefined) {
|
|
261
403
|
failures.push('no trial holds this scenario. Run `thread trials` and commit the result')
|
|
262
404
|
} else {
|
|
263
|
-
for (const part of ['result', 'kept', '
|
|
405
|
+
for (const part of ['result', 'kept', 'called'] as const) {
|
|
264
406
|
const then = printed(older[part])
|
|
265
407
|
const said = printed(one[part])
|
|
266
408
|
if (then === said) continue
|
|
@@ -318,7 +460,7 @@ export function unproven(run: Run): readonly string[] {
|
|
|
318
460
|
const how = [
|
|
319
461
|
denied === 0
|
|
320
462
|
? ''
|
|
321
|
-
: `${String(denied)} were
|
|
463
|
+
: `${String(denied)} were refused before the operation could start — by the gate, or because what they were given is not what it takes — which proves the refusal and nothing whatever about the operation`,
|
|
322
464
|
neither === 0 ? '' : `${String(neither)} neither reached it nor were denied`,
|
|
323
465
|
].filter((one) => one !== '')
|
|
324
466
|
|
|
@@ -331,13 +473,13 @@ export function unproven(run: Run): readonly string[] {
|
|
|
331
473
|
return said
|
|
332
474
|
}
|
|
333
475
|
|
|
334
|
-
async function
|
|
476
|
+
async function standIns(): Promise<Readonly<Record<string, string>> | string> {
|
|
335
477
|
const at = resolve(ROOT, '_threads/secrets.ts')
|
|
336
478
|
if (!existsSync(at)) return {}
|
|
337
|
-
let held: readonly { readonly id: string; readonly sends?: unknown }[]
|
|
479
|
+
let held: readonly { readonly id: string; readonly sends?: unknown; readonly signs?: unknown }[]
|
|
338
480
|
try {
|
|
339
481
|
const taken = (await import(pathToFileURL(at).href)) as {
|
|
340
|
-
readonly SECRETS?: readonly { readonly id: string; readonly sends?: unknown }[]
|
|
482
|
+
readonly SECRETS?: readonly { readonly id: string; readonly sends?: unknown; readonly signs?: unknown }[]
|
|
341
483
|
}
|
|
342
484
|
held = taken.SECRETS ?? []
|
|
343
485
|
} catch (thrown) {
|
|
@@ -349,11 +491,26 @@ async function standing(): Promise<Readonly<Record<string, string>> | string> {
|
|
|
349
491
|
}
|
|
350
492
|
const found: Record<string, string> = {}
|
|
351
493
|
for (const one of held) {
|
|
352
|
-
found[one.id] = one.sends === undefined ? `https://${one.id.replace(/_/g, '-')}.invalid` : `${one.id}-stood-in-for`
|
|
494
|
+
found[one.id] = one.sends === undefined && one.signs === undefined ? `https://${one.id.replace(/_/g, '-')}.invalid` : `${one.id}-stood-in-for`
|
|
353
495
|
}
|
|
354
496
|
return found
|
|
355
497
|
}
|
|
356
498
|
|
|
499
|
+
async function reaching(): Promise<{ readonly targets: readonly Target[]; readonly calls: readonly Call[] } | string> {
|
|
500
|
+
const at = resolve(ROOT, '_threads/targets.ts')
|
|
501
|
+
if (!existsSync(at)) return { targets: [], calls: [] }
|
|
502
|
+
try {
|
|
503
|
+
const taken = (await import(pathToFileURL(at).href)) as { readonly TARGETS?: readonly Target[]; readonly CALLS?: readonly Call[] }
|
|
504
|
+
return { targets: taken.TARGETS ?? [], calls: taken.CALLS ?? [] }
|
|
505
|
+
} catch (thrown) {
|
|
506
|
+
return (
|
|
507
|
+
`_threads/targets.ts is there and could not be read: ${thrown instanceof Error ? thrown.message : String(thrown)}. ` +
|
|
508
|
+
'Which disk a trial hands an operation is read from that sheet, so every trial would run with no disk at all and ' +
|
|
509
|
+
'the failures would name the operation instead of the sheet'
|
|
510
|
+
)
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
357
514
|
export async function record(): Promise<{ readonly trials: readonly Trial[]; readonly refusals: readonly string[] }> {
|
|
358
515
|
const pass = descend()
|
|
359
516
|
const known = types(pass)
|
|
@@ -363,9 +520,13 @@ export async function record(): Promise<{ readonly trials: readonly Trial[]; rea
|
|
|
363
520
|
const declared = [...operations(pass, known)].filter(([, one]) => one.body !== undefined)
|
|
364
521
|
if (declared.length === 0) return { trials: [], refusals: [] }
|
|
365
522
|
|
|
366
|
-
const stood = await
|
|
523
|
+
const stood = await standIns()
|
|
367
524
|
if (typeof stood === 'string') return { trials: [], refusals: [stood] }
|
|
368
525
|
|
|
526
|
+
const reached = await reaching()
|
|
527
|
+
if (typeof reached === 'string') return { trials: [], refusals: [reached] }
|
|
528
|
+
const { targets, calls } = reached
|
|
529
|
+
|
|
369
530
|
const at = resolve(ROOT, DISPATCH_AT)
|
|
370
531
|
if (!existsSync(at)) {
|
|
371
532
|
return {
|
|
@@ -380,7 +541,8 @@ export async function record(): Promise<{ readonly trials: readonly Trial[]; rea
|
|
|
380
541
|
operation: Operation<unknown>,
|
|
381
542
|
input: unknown,
|
|
382
543
|
actor: Actor,
|
|
383
|
-
|
|
544
|
+
opened: Readonly<Record<string, unknown>>,
|
|
545
|
+
opening: Vault,
|
|
384
546
|
) => Promise<Result<unknown>>
|
|
385
547
|
}
|
|
386
548
|
const dispatch = made.dispatch
|
|
@@ -388,28 +550,6 @@ export async function record(): Promise<{ readonly trials: readonly Trial[]; rea
|
|
|
388
550
|
return { trials: [], refusals: [`${DISPATCH_AT} exports no \`dispatch\`, so nothing here can run an operation`] }
|
|
389
551
|
}
|
|
390
552
|
|
|
391
|
-
const kept = resolve(ROOT, ENTITIES_AT)
|
|
392
|
-
const entities = new Map<string, ReadonlySet<string>>()
|
|
393
|
-
const keys = new Map<string, string>()
|
|
394
|
-
if (existsSync(kept)) {
|
|
395
|
-
const sheet = (await import(pathToFileURL(kept).href)) as {
|
|
396
|
-
readonly ENTITIES?: readonly {
|
|
397
|
-
readonly id: string
|
|
398
|
-
readonly holds?: readonly { readonly id: string }[]
|
|
399
|
-
readonly links?: readonly { readonly id: string }[]
|
|
400
|
-
readonly must?: readonly { readonly unique?: readonly string[] }[]
|
|
401
|
-
}[]
|
|
402
|
-
}
|
|
403
|
-
for (const one of sheet.ENTITIES ?? []) {
|
|
404
|
-
entities.set(
|
|
405
|
-
one.id,
|
|
406
|
-
new Set([...(one.holds ?? []).map((each) => each.id), ...(one.links ?? []).map((each) => `${each.id}_id`)]),
|
|
407
|
-
)
|
|
408
|
-
const named = (one.must ?? []).flatMap((each) => (each.unique?.length === 1 ? [each.unique[0] as string] : []))
|
|
409
|
-
if (named.length === 1) keys.set(one.id, named[0] as string)
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
553
|
const permitted = resolve(ROOT, ACCESS_AT)
|
|
414
554
|
const may = new Map<string, string[]>()
|
|
415
555
|
if (existsSync(permitted)) {
|
|
@@ -438,11 +578,6 @@ export async function record(): Promise<{ readonly trials: readonly Trial[]; rea
|
|
|
438
578
|
refusals: [`${PERMITS_AT} exports no \`permits\`, so a trial cannot be answered by the gate this app derives`],
|
|
439
579
|
}
|
|
440
580
|
}
|
|
441
|
-
const gate: NonNullable<Seams['permits']> | undefined =
|
|
442
|
-
permits === undefined
|
|
443
|
-
? undefined
|
|
444
|
-
: { check: (actor, action, resource) => Promise.resolve(permits(actor, action, resource)) }
|
|
445
|
-
|
|
446
581
|
for (const [id, one] of [...declared].sort((a, b) => compare(a[0], b[0]))) {
|
|
447
582
|
if (one.body === undefined) continue
|
|
448
583
|
const from = resolve(ROOT, one.body)
|
|
@@ -471,7 +606,9 @@ export async function record(): Promise<{ readonly trials: readonly Trial[]; rea
|
|
|
471
606
|
}
|
|
472
607
|
|
|
473
608
|
for (const scenario of scenarios) {
|
|
474
|
-
|
|
609
|
+
const ran = await runScenario(operation, scenario, dispatch, stood, targets, calls)
|
|
610
|
+
if (typeof ran === 'string') refusals.push(ran)
|
|
611
|
+
else trials.push(ran)
|
|
475
612
|
}
|
|
476
613
|
}
|
|
477
614
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { Threaded } from '../core/thread.ts';
|
|
2
|
-
import type { Operation } from './operations.ts';
|
|
3
|
-
import type { Handed, Reads, Supplied } from './seams.ts';
|
|
2
|
+
import type { Opened, Operation, Reads } from './operations.ts';
|
|
4
3
|
export interface Node extends Threaded {
|
|
5
4
|
readonly version: number;
|
|
6
5
|
}
|
|
@@ -9,27 +8,27 @@ export declare const STOPPED: unique symbol;
|
|
|
9
8
|
export declare function stopped(thrown: unknown): {
|
|
10
9
|
readonly value: unknown;
|
|
11
10
|
} | undefined;
|
|
12
|
-
export declare const nd_read: <I, R extends string =
|
|
13
|
-
type:
|
|
11
|
+
export declare const nd_read: <I, R extends string = never>(block: (opened: Reads<Opened<R>>, held: Held<I>) => Promise<unknown>) => {
|
|
12
|
+
type: 'nd_read';
|
|
14
13
|
};
|
|
15
|
-
export declare const nd_action: <I, R extends string =
|
|
16
|
-
type:
|
|
14
|
+
export declare const nd_action: <I, R extends string = never>(block: (opened: Opened<R>, held: Held<I>) => Promise<unknown>) => {
|
|
15
|
+
type: 'nd_action';
|
|
17
16
|
};
|
|
18
|
-
export declare const nd_branch: <I, R extends string =
|
|
19
|
-
type:
|
|
17
|
+
export declare const nd_branch: <I, R extends string = never>(choose: (opened: Reads<Opened<R>>, held: Held<I>) => Promise<string>, ways: Readonly<Record<string, (opened: Opened<R>, held: Held<I>) => Promise<unknown>>>) => {
|
|
18
|
+
type: 'nd_branch';
|
|
20
19
|
};
|
|
21
|
-
export declare const nd_each: <I, R extends string =
|
|
22
|
-
type:
|
|
20
|
+
export declare const nd_each: <I, R extends string = never>(over: (held: Held<I>) => readonly unknown[], block: (item: unknown, opened: Opened<R>, held: Held<I>) => Promise<unknown>) => {
|
|
21
|
+
type: 'nd_each';
|
|
23
22
|
};
|
|
24
|
-
export declare const nd_parallel: <I, R extends string =
|
|
25
|
-
type:
|
|
23
|
+
export declare const nd_parallel: <I, R extends string = never>(blocks: readonly ((opened: Opened<R>, held: Held<I>) => Promise<unknown>)[]) => {
|
|
24
|
+
type: 'nd_parallel';
|
|
26
25
|
};
|
|
27
|
-
export declare const nd_repeat: <I, R extends string =
|
|
26
|
+
export declare const nd_repeat: <I, R extends string = never>(ceiling: number, block: (pass: number, carried: unknown, opened: Opened<R>, held: Held<I>) => Promise<{
|
|
28
27
|
readonly done: boolean;
|
|
29
28
|
readonly value: unknown;
|
|
30
29
|
}>) => {
|
|
31
|
-
type:
|
|
30
|
+
type: 'nd_repeat';
|
|
32
31
|
};
|
|
33
|
-
export declare const nd_stop: <I, R extends string =
|
|
34
|
-
type:
|
|
32
|
+
export declare const nd_stop: <I, R extends string = never>(block: (opened: Reads<Opened<R>>, held: Held<I>) => Promise<unknown>) => {
|
|
33
|
+
type: 'nd_stop';
|
|
35
34
|
};
|
package/dist/operations/nodes.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { Threaded } from '../core/thread.ts'
|
|
2
2
|
|
|
3
|
-
import type { Operation } from './operations.ts'
|
|
4
|
-
import type { Handed, Reads, Supplied } from './seams.ts'
|
|
3
|
+
import type { Opened, Operation, Reads } from './operations.ts'
|
|
5
4
|
|
|
6
5
|
export interface Node extends Threaded {
|
|
7
6
|
readonly version: number
|
|
@@ -17,38 +16,38 @@ export function stopped(thrown: unknown): { readonly value: unknown } | undefine
|
|
|
17
16
|
return { value: (thrown as { readonly value?: unknown }).value }
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
export const nd_read = <I, R extends string =
|
|
21
|
-
block: (
|
|
19
|
+
export const nd_read = <I, R extends string = never>(
|
|
20
|
+
block: (opened: Reads<Opened<R>>, held: Held<I>) => Promise<unknown>,
|
|
22
21
|
) => ({ type: 'nd_read' as const })
|
|
23
22
|
|
|
24
|
-
export const nd_action = <I, R extends string =
|
|
25
|
-
block: (
|
|
23
|
+
export const nd_action = <I, R extends string = never>(
|
|
24
|
+
block: (opened: Opened<R>, held: Held<I>) => Promise<unknown>,
|
|
26
25
|
) => ({ type: 'nd_action' as const })
|
|
27
26
|
|
|
28
|
-
export const nd_branch = <I, R extends string =
|
|
29
|
-
choose: (
|
|
30
|
-
ways: Readonly<Record<string, (
|
|
27
|
+
export const nd_branch = <I, R extends string = never>(
|
|
28
|
+
choose: (opened: Reads<Opened<R>>, held: Held<I>) => Promise<string>,
|
|
29
|
+
ways: Readonly<Record<string, (opened: Opened<R>, held: Held<I>) => Promise<unknown>>>,
|
|
31
30
|
) => ({ type: 'nd_branch' as const })
|
|
32
31
|
|
|
33
|
-
export const nd_each = <I, R extends string =
|
|
32
|
+
export const nd_each = <I, R extends string = never>(
|
|
34
33
|
over: (held: Held<I>) => readonly unknown[],
|
|
35
|
-
block: (item: unknown,
|
|
34
|
+
block: (item: unknown, opened: Opened<R>, held: Held<I>) => Promise<unknown>,
|
|
36
35
|
) => ({ type: 'nd_each' as const })
|
|
37
36
|
|
|
38
|
-
export const nd_parallel = <I, R extends string =
|
|
39
|
-
blocks: readonly ((
|
|
37
|
+
export const nd_parallel = <I, R extends string = never>(
|
|
38
|
+
blocks: readonly ((opened: Opened<R>, held: Held<I>) => Promise<unknown>)[],
|
|
40
39
|
) => ({ type: 'nd_parallel' as const })
|
|
41
40
|
|
|
42
|
-
export const nd_repeat = <I, R extends string =
|
|
41
|
+
export const nd_repeat = <I, R extends string = never>(
|
|
43
42
|
ceiling: number,
|
|
44
43
|
block: (
|
|
45
44
|
pass: number,
|
|
46
45
|
carried: unknown,
|
|
47
|
-
|
|
46
|
+
opened: Opened<R>,
|
|
48
47
|
held: Held<I>,
|
|
49
48
|
) => Promise<{ readonly done: boolean; readonly value: unknown }>,
|
|
50
49
|
) => ({ type: 'nd_repeat' as const })
|
|
51
50
|
|
|
52
|
-
export const nd_stop = <I, R extends string =
|
|
53
|
-
block: (
|
|
51
|
+
export const nd_stop = <I, R extends string = never>(
|
|
52
|
+
block: (opened: Reads<Opened<R>>, held: Held<I>) => Promise<unknown>,
|
|
54
53
|
) => ({ type: 'nd_stop' as const })
|
|
@@ -1,18 +1,54 @@
|
|
|
1
1
|
import type { z } from 'zod';
|
|
2
|
+
import type { Actor } from '../core/actor.ts';
|
|
2
3
|
import type { Member } from '../core/thread.ts';
|
|
3
|
-
import type
|
|
4
|
+
import { REACH, type Answering, type Calling, type HttpResponse, type Row, type Running, type Store } from '../integrations/target.ts';
|
|
5
|
+
import type { Surface } from './capabilities.ts';
|
|
4
6
|
export declare const OPERATIONS_FILE = "operations.ts";
|
|
5
7
|
export declare const TRIALS_AT = "operations/_trials.json";
|
|
6
8
|
export declare const NODES_FILE = "nodes.ts";
|
|
7
9
|
export declare const MEMBERS_LIST = "MEMBERS";
|
|
8
|
-
export interface
|
|
10
|
+
export interface Reaching {
|
|
11
|
+
}
|
|
12
|
+
type CallsOf<K extends string> = K extends keyof Reaching ? (Reaching[K] extends string ? Reaching[K] : string) : string;
|
|
13
|
+
export type Opened<R extends string = never> = {
|
|
14
|
+
readonly actor: Actor;
|
|
15
|
+
readonly tell: (said: unknown) => void;
|
|
16
|
+
} & {
|
|
17
|
+
readonly [K in R]: K extends `${typeof REACH.disk}${string}` ? Answering : K extends `${typeof REACH.cli}${string}` ? Running<CallsOf<K>> : K extends `${typeof REACH.postgres}${string}` | `${typeof REACH.pglite}${string}` | `${typeof REACH.browser}${string}` ? Store : K extends `${typeof REACH.sdk}${string}` ? Calling<CallsOf<K>> : Readonly<Record<CallsOf<K>, (given?: {
|
|
18
|
+
readonly fills?: Readonly<Record<string, string | number>>;
|
|
19
|
+
readonly json?: unknown;
|
|
20
|
+
readonly body?: Uint8Array;
|
|
21
|
+
readonly contentType?: string;
|
|
22
|
+
readonly told?: (said: unknown) => void;
|
|
23
|
+
}) => Promise<HttpResponse>>>;
|
|
24
|
+
};
|
|
25
|
+
export type Reads<H> = {
|
|
26
|
+
readonly [K in keyof H]: H[K] extends Store ? Pick<Store, 'get' | 'list'> : H[K];
|
|
27
|
+
};
|
|
28
|
+
export declare const WINDOWS: readonly ['second', 'minute', 'hour', 'day', 'week', 'month'];
|
|
29
|
+
export type Window = (typeof WINDOWS)[number];
|
|
30
|
+
export interface Allowance {
|
|
31
|
+
readonly runs: number;
|
|
32
|
+
readonly per: Window;
|
|
33
|
+
}
|
|
34
|
+
export interface Counting {
|
|
35
|
+
readonly seen: (key: string, per: Window) => Promise<number>;
|
|
36
|
+
}
|
|
37
|
+
export interface Operation<I = unknown, R extends string = never> {
|
|
9
38
|
readonly id: string;
|
|
10
39
|
readonly input: z.ZodType<I>;
|
|
11
40
|
readonly requires: readonly string[];
|
|
12
|
-
readonly
|
|
41
|
+
readonly webhooks?: readonly string[];
|
|
42
|
+
readonly off?: readonly Surface[];
|
|
43
|
+
readonly signed?: boolean;
|
|
44
|
+
readonly entitled?: string;
|
|
45
|
+
readonly rate?: Allowance;
|
|
46
|
+
readonly quota?: Allowance;
|
|
47
|
+
readonly run: (opened: Opened<R>, held: {
|
|
13
48
|
readonly input: I;
|
|
14
49
|
} & Readonly<Record<string, unknown>>) => Promise<unknown>;
|
|
15
|
-
readonly
|
|
50
|
+
readonly timeout: number;
|
|
16
51
|
readonly resource: (input: I) => Row | null;
|
|
17
52
|
}
|
|
18
53
|
export declare const OPERATIONS: readonly Member[];
|
|
54
|
+
export {};
|