@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,52 +1,112 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { execPath } from 'node:process';
|
|
3
|
+
import { SECRECY, secrecyOf } from './secret.js';
|
|
2
4
|
export const REACH = {
|
|
3
5
|
postgres: 'pg_',
|
|
4
6
|
pglite: 'pl_',
|
|
5
7
|
browser: 'zu_',
|
|
6
8
|
https: 'ht_',
|
|
7
|
-
module: 'mod_',
|
|
8
9
|
cli: 'cli_',
|
|
10
|
+
disk: 'dsk_',
|
|
11
|
+
sdk: 'sdk_',
|
|
12
|
+
};
|
|
13
|
+
export const ADDRESS = {
|
|
14
|
+
row: 'reached at the address written on its row, which anybody may read',
|
|
15
|
+
secret: 'reached at a secret, because its address is a connection string and a connection string carries a password',
|
|
16
|
+
nothing: 'addressed by nothing',
|
|
9
17
|
};
|
|
10
18
|
export const HOLDS = {
|
|
11
|
-
postgres: { takes: 'entities', from: 'server', addressed:
|
|
12
|
-
pglite: { takes: 'entities', from: 'either', addressed:
|
|
13
|
-
browser: { takes: 'entities', from: 'browser', addressed:
|
|
14
|
-
https: { takes: 'calls', from: 'either', addressed:
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
postgres: { takes: 'entities', from: 'server', addressed: 'secret', migrations: true, references: true, sql: true, driver: 'postgres' },
|
|
20
|
+
pglite: { takes: 'entities', from: 'either', addressed: 'nothing', migrations: true, references: true, sql: true, driver: '@electric-sql/pglite' },
|
|
21
|
+
browser: { takes: 'entities', from: 'browser', addressed: 'nothing', migrations: false, references: false, sql: false, driver: 'zustand' },
|
|
22
|
+
https: { takes: 'calls', from: 'either', addressed: 'row', migrations: false, references: false, sql: false, driver: null },
|
|
23
|
+
cli: { takes: 'calls', from: 'server', addressed: 'nothing', migrations: false, references: false, sql: false, driver: null },
|
|
24
|
+
disk: { takes: null, from: 'server', addressed: 'nothing', migrations: false, references: false, sql: false, driver: null },
|
|
25
|
+
sdk: { takes: 'calls', from: 'server', addressed: 'nothing', migrations: false, references: false, sql: false, driver: null },
|
|
17
26
|
};
|
|
18
27
|
export const SAID = {
|
|
19
28
|
postgres: 'A postgres this app connects to over the network. It keeps entities and holds everything a declaration can state about their shape — tables, references and invariants — so what is kept here is held to that shape by the database itself rather than by whatever remembered to check. Who may touch a row is not asked of it: that is answered by the app, against the caller who actually arrived. It is reached from a server only: a connection to it from a page is a database somebody else can open. This is where a thing goes when losing it would matter.',
|
|
20
|
-
pglite: 'A postgres running inside the process that opened it. It keeps entities and holds tables, references and invariants, exactly as the networked one does — what differs is who can reach it, not what it can be told to hold. What belongs here is what the caller is already entitled to see: a local copy, a working set, an offline cache.',
|
|
29
|
+
pglite: 'A postgres running inside the process that opened it. It keeps entities and holds tables, references and invariants, exactly as the networked one does — what differs is who can reach it, not what it can be told to hold. It is addressed by nothing: its files sit under .thread beside the tree, in a folder named after the target, so nobody types a path and a fresh clone starts it empty. What belongs here is what the caller is already entitled to see: a local copy, a working set, an offline cache.',
|
|
21
30
|
browser: 'A store in the browser, held in memory the viewer owns. It keeps entities and it is addressed by nothing, because it is already where the code runs. It holds no migration, because a page load builds it from nothing every time. What belongs here is what the interface needs to be responsive and can afford to lose.',
|
|
22
|
-
https: 'Something this app calls over https — a vendor, a service, another app. It accepts calls rather than entities: each is declared with the verb and the path it takes, so a node names the call and never writes a url.
|
|
23
|
-
|
|
24
|
-
|
|
31
|
+
https: 'Something this app calls over https — a vendor, a service, another app. It accepts calls rather than entities: each is declared with the verb and the path it takes, so a node names the call and never writes a url. Where it is goes on its row as address, and a header every call carries goes on its row as headers, because both are facts anybody may read; a credential it sends is a secret, and requiring one is what keeps the target out of a browser.',
|
|
32
|
+
cli: 'A program this app runs as a command. git is the one that made this necessary. It is not installed, because it is not a dependency: it is on the machine or it is not, and a run finds out. What it accepts is the words it is asked with, declared beside it as calls with thread create target call: a subcommand where the program has them, and the option that selects what it does where it has none, each spelled the way the program spells it. A word that is not declared never runs. The program is the one the target is named after, so declaring one runs nothing and reads nothing off the machine. An operation that requires it is handed one function per declared word, and that is the only way this app ever runs it.',
|
|
33
|
+
disk: 'The disk this app runs on. It answers a fixed set of orders — is this there, read it, write it, list what is beside it, how big it is, remove it, and what it really is — and those orders are the same for every disk, because they are what a filesystem does rather than what any one of them chose to offer. None of them runs anything: a disk holds files and a program that installs packages is not a file order, which is why installing what a tree depends on happens where somebody typed the command and is not something a disk can be asked for. It is reached from a server only: a page has no filesystem. A trial stands one of these up out of its own scenario, so a rule can be measured against files that exist for the length of that run and nothing is written where you work.',
|
|
34
|
+
sdk: 'A package this app calls inside its own process — a vendor\'s SDK, fetched from npm, a git link or a tarball. It accepts calls rather than entities: the file this target declares exports `calls`, each call names the function there it runs as its path, and that file is the only place the package is imported, so an operation names the call and never the package. The integration it is part of names what to fetch in needs, and declaring the integration fetches it. It runs where the app runs, so it is addressed by nothing and reached from a server only.',
|
|
35
|
+
};
|
|
36
|
+
const on = (host, names) => names.map((one) => host + '.' + one);
|
|
37
|
+
const driverOfReach = (one) => {
|
|
38
|
+
const driver = HOLDS[one].driver;
|
|
39
|
+
return driver === null ? [] : ['import ' + driver];
|
|
40
|
+
};
|
|
41
|
+
export const OPENS = {
|
|
42
|
+
postgres: driverOfReach('postgres'),
|
|
43
|
+
pglite: driverOfReach('pglite'),
|
|
44
|
+
browser: driverOfReach('browser'),
|
|
45
|
+
https: [
|
|
46
|
+
'fetch',
|
|
47
|
+
'XMLHttpRequest',
|
|
48
|
+
'WebSocket',
|
|
49
|
+
'EventSource',
|
|
50
|
+
...on('window', ['fetch']),
|
|
51
|
+
...on('navigator', ['sendBeacon']),
|
|
52
|
+
'import node:http',
|
|
53
|
+
'import node:https',
|
|
54
|
+
'import node:http2',
|
|
55
|
+
'import node:net',
|
|
56
|
+
'import node:tls',
|
|
57
|
+
'import node:dgram',
|
|
58
|
+
'import node:dns',
|
|
59
|
+
],
|
|
60
|
+
cli: ['import node:child_process', 'import node:worker_threads', 'import node:cluster'],
|
|
61
|
+
disk: ['import node:fs', 'import node:fs/promises'],
|
|
62
|
+
sdk: [],
|
|
63
|
+
};
|
|
64
|
+
export const ORDERS = {
|
|
65
|
+
kind: 'kind',
|
|
66
|
+
read: 'read',
|
|
67
|
+
write: 'written',
|
|
68
|
+
list: 'list',
|
|
69
|
+
stat: 'stat',
|
|
70
|
+
remove: 'removed',
|
|
71
|
+
real: 'real',
|
|
72
|
+
fetch: 'fetched',
|
|
73
|
+
run: 'ran',
|
|
25
74
|
};
|
|
75
|
+
export function isRow(v) {
|
|
76
|
+
return typeof v === 'object' && v !== null && typeof v.id === 'string';
|
|
77
|
+
}
|
|
78
|
+
export function isTransactional(store) {
|
|
79
|
+
return typeof store.transaction === 'function';
|
|
80
|
+
}
|
|
26
81
|
export const CALL_PREFIX = 'cl_';
|
|
27
82
|
const FILLED = /\{([a-z][a-z0-9_]*)\}/g;
|
|
28
83
|
export const fills = (one) => [...one.path.matchAll(FILLED)].map((each) => each[1] ?? '');
|
|
29
84
|
export function reachOf(id) {
|
|
30
85
|
return Object.keys(REACH).find((one) => id.startsWith(REACH[one]));
|
|
31
86
|
}
|
|
87
|
+
export const standsHere = (one, targets) => !one.requires.some((each) => targets.some((two) => two.id === each));
|
|
32
88
|
export function holdsOf(id) {
|
|
33
89
|
const what = reachOf(id);
|
|
34
90
|
return what === undefined ? undefined : HOLDS[what];
|
|
35
91
|
}
|
|
92
|
+
export function requirable(targets, calls) {
|
|
93
|
+
const declared = new Set(calls.map((one) => one.id));
|
|
94
|
+
return targets.filter((one) => holdsOf(one.id)?.takes !== 'calls' || one.takes.some((each) => declared.has(each)));
|
|
95
|
+
}
|
|
36
96
|
export function driverOf(id) {
|
|
37
97
|
return holdsOf(id)?.driver ?? null;
|
|
38
98
|
}
|
|
39
99
|
export function addressOf(one, secrets) {
|
|
40
|
-
if (holdsOf(one.id)?.addressed !==
|
|
100
|
+
if (holdsOf(one.id)?.addressed !== 'secret')
|
|
41
101
|
return undefined;
|
|
42
102
|
const held = new Map(secrets.map((each) => [each.id, each]));
|
|
43
|
-
return one.requires.map((each) => held.get(each)).find((each) => each !== undefined && each.sends === undefined);
|
|
103
|
+
return one.requires.map((each) => held.get(each)).find((each) => each !== undefined && each.sends === undefined && each.signs === undefined);
|
|
44
104
|
}
|
|
45
105
|
export function credentialsOf(one, secrets) {
|
|
46
106
|
const held = new Map(secrets.map((each) => [each.id, each]));
|
|
47
107
|
return one.requires
|
|
48
108
|
.map((each) => held.get(each))
|
|
49
|
-
.filter((each) => each !== undefined && each.sends !== undefined);
|
|
109
|
+
.filter((each) => each !== undefined && (each.sends !== undefined || each.signs !== undefined));
|
|
50
110
|
}
|
|
51
111
|
export function servesBrowser(one, secrets) {
|
|
52
112
|
const holds = holdsOf(one.id);
|
|
@@ -73,23 +133,41 @@ export const unreachable = (targets) => targets
|
|
|
73
133
|
.filter((one) => reachOf(one.id) === undefined)
|
|
74
134
|
.map((one) => `\`${one.id}\` wears none of the prefixes a target is reached by (${Object.values(REACH).join(', ')}), so ` +
|
|
75
135
|
'nothing can tell how to reach it — and how a thing is reached decides what may be declared for it');
|
|
136
|
+
export const LOCKFILES = {
|
|
137
|
+
'pnpm-lock.yaml': 'pnpm',
|
|
138
|
+
'yarn.lock': 'yarn',
|
|
139
|
+
'bun.lockb': 'bun',
|
|
140
|
+
'package-lock.json': 'npm',
|
|
141
|
+
};
|
|
142
|
+
export const PACKAGER = 'packager';
|
|
143
|
+
const NAMED = ['git', 'thread'];
|
|
144
|
+
const RUNTIME = 'node';
|
|
145
|
+
export const managerOf = (at, there) => Object.entries(LOCKFILES).find(([lock]) => there(join(at, lock)))?.[1] ?? 'npm';
|
|
146
|
+
export function programOf(name, at, there) {
|
|
147
|
+
if (NAMED.includes(name))
|
|
148
|
+
return name;
|
|
149
|
+
if (name === RUNTIME)
|
|
150
|
+
return execPath;
|
|
151
|
+
if (name === PACKAGER)
|
|
152
|
+
return managerOf(at, there);
|
|
153
|
+
const installed = join(at, 'node_modules', '.bin', name);
|
|
154
|
+
return there(installed) ? installed : undefined;
|
|
155
|
+
}
|
|
156
|
+
export const unlisted = (name) => '`' + REACH.cli + name + '` names ' + name + ', and nothing lists a program by that name: it is not under node_modules/.bin, so this tree did not install it; it is not git, node or thread; and it is not `' + PACKAGER + '`, the word for whichever package manager the lockfile picks. A program the tree did not install is whatever the machine happens to have, and a target on that is a shell by another name. Add the package that provides it and declare the target again, or ask for it through a declared call on `' + REACH.cli + PACKAGER + '`';
|
|
76
157
|
const SHAPED = {
|
|
77
|
-
|
|
78
|
-
cli: /^[a-z][a-z0-9-]*$/,
|
|
158
|
+
cli: /^-{0,2}[A-Za-z][A-Za-z0-9-]*$/,
|
|
79
159
|
};
|
|
80
160
|
const EVERY_VALUE = new Set(['constructor', '__proto__', 'prototype']);
|
|
81
161
|
export function misnamed(target, name) {
|
|
82
162
|
const reach = reachOf(target);
|
|
83
|
-
if (reach !== '
|
|
163
|
+
if (reach !== 'cli')
|
|
84
164
|
return undefined;
|
|
85
165
|
if (EVERY_VALUE.has(name)) {
|
|
86
|
-
return (`\`${name}\` is a step every JavaScript value has rather than something \`${target}\`
|
|
166
|
+
return (`\`${name}\` is a step every JavaScript value has rather than something \`${target}\` answers to, and walking to ` +
|
|
87
167
|
'it leaves what was declared');
|
|
88
168
|
}
|
|
89
169
|
if (!SHAPED[reach].test(name)) {
|
|
90
|
-
return
|
|
91
|
-
? `\`${name}\` is not a method path — one name, or names joined by dots, e.g. \`customers.list\``
|
|
92
|
-
: `\`${name}\` is not a subcommand — one word as the program spells it, e.g. \`commit\` or \`rev-parse\``;
|
|
170
|
+
return name + ' is not one word as the program spells it. Give a subcommand, e.g. commit or rev-parse, or, where the program has none, the option that selects what it does, e.g. -p';
|
|
93
171
|
}
|
|
94
172
|
return undefined;
|
|
95
173
|
}
|
|
@@ -106,10 +184,8 @@ export function misaccepted(targets, entities, calls) {
|
|
|
106
184
|
continue;
|
|
107
185
|
if (holds.takes === 'calls' && isCall.has(named))
|
|
108
186
|
continue;
|
|
109
|
-
if (holds.takes ===
|
|
110
|
-
found.push(`\`${one.id}\`
|
|
111
|
-
'installed package or a program responds to goes in `offers`, not here. `takes` is a demand, and the ' +
|
|
112
|
-
'descent requires every word on one to be coined by a row in this tree; a method name never can be');
|
|
187
|
+
if (holds.takes === null) {
|
|
188
|
+
found.push(`\`${one.id}\` takes "${named}", and a ${String(reachOf(one.id))} takes nothing: it answers the orders every ${String(reachOf(one.id))} answers, stated once on the target itself`);
|
|
113
189
|
continue;
|
|
114
190
|
}
|
|
115
191
|
found.push(`\`${one.id}\` is reached over ${String(reachOf(one.id))} and so accepts ${holds.takes}, and its \`takes\` names ` +
|
|
@@ -118,6 +194,36 @@ export function misaccepted(targets, entities, calls) {
|
|
|
118
194
|
}
|
|
119
195
|
return found;
|
|
120
196
|
}
|
|
197
|
+
export const placedAt = (targets, id) => targets.find((one) => one.id === id)?.address ?? '';
|
|
198
|
+
export function placed(one) {
|
|
199
|
+
const said = one.address;
|
|
200
|
+
if (said === undefined) {
|
|
201
|
+
return [one.id + ' is reached over https and its row says nothing about where. Give it an address: the absolute url every call on it is written from, scheme and host and nothing after the path'];
|
|
202
|
+
}
|
|
203
|
+
let held;
|
|
204
|
+
try {
|
|
205
|
+
held = new URL(said);
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
return [one.id + ' has the address ' + JSON.stringify(said) + ', and that is not an absolute url. Write the whole of it, scheme and host'];
|
|
209
|
+
}
|
|
210
|
+
if ([held.search, held.hash].some((each) => each !== '')) {
|
|
211
|
+
return [one.id + ' has the address ' + said + ', which carries a query or a fragment. Those belong to a call, so an address ends at its path'];
|
|
212
|
+
}
|
|
213
|
+
const wrong = Object.entries(one.headers ?? {}).filter(([, value]) => typeof value !== 'string');
|
|
214
|
+
if (wrong.length > 0) {
|
|
215
|
+
return [one.id + ' carries the header ' + String(wrong[0]?.[0] ?? '') + ' with a value that is not text. A header every call carries is written as text, exactly as it goes on the wire'];
|
|
216
|
+
}
|
|
217
|
+
return [];
|
|
218
|
+
}
|
|
219
|
+
const stated = (one, holds) => {
|
|
220
|
+
if (holds.addressed === 'row')
|
|
221
|
+
return placed(one);
|
|
222
|
+
const carried = [...(one.address === undefined ? [] : ['an address']), ...(one.headers === undefined ? [] : ['headers'])];
|
|
223
|
+
if (carried.length === 0)
|
|
224
|
+
return [];
|
|
225
|
+
return [one.id + ' carries ' + carried.join(' and ') + ', and a ' + String(reachOf(one.id)) + ' is ' + ADDRESS[holds.addressed] + '. Take it off the row'];
|
|
226
|
+
};
|
|
121
227
|
export function unaddressed(targets, secrets) {
|
|
122
228
|
const held = new Map(secrets.map((one) => [one.id, one]));
|
|
123
229
|
const found = [];
|
|
@@ -125,13 +231,14 @@ export function unaddressed(targets, secrets) {
|
|
|
125
231
|
const holds = holdsOf(one.id);
|
|
126
232
|
if (holds === undefined)
|
|
127
233
|
continue;
|
|
234
|
+
found.push(...stated(one, holds));
|
|
128
235
|
const addresses = one.requires
|
|
129
236
|
.map((each) => held.get(each))
|
|
130
|
-
.filter((each) => each !== undefined && each.sends === undefined);
|
|
131
|
-
if (
|
|
132
|
-
if (
|
|
133
|
-
found.push(
|
|
134
|
-
|
|
237
|
+
.filter((each) => each !== undefined && each.sends === undefined && each.signs === undefined);
|
|
238
|
+
if (holds.addressed !== 'secret') {
|
|
239
|
+
if (addresses.length > 0) {
|
|
240
|
+
found.push(one.id + ' is reached over ' + String(reachOf(one.id)) + ', which is ' + ADDRESS[holds.addressed] + ', and it requires ' +
|
|
241
|
+
(addresses[0]?.id ?? '') + ', a secret with nowhere to be sent. A secret is a credential: give it the header it goes on with sends, or take it off this row');
|
|
135
242
|
}
|
|
136
243
|
continue;
|
|
137
244
|
}
|
|
@@ -148,14 +255,15 @@ export function unaddressed(targets, secrets) {
|
|
|
148
255
|
return found;
|
|
149
256
|
}
|
|
150
257
|
export function unheld(targets, secrets) {
|
|
151
|
-
const known = new Set(secrets.map((one) => one.id));
|
|
258
|
+
const known = new Set([...secrets.map((one) => one.id), ...targets.map((one) => one.id)]);
|
|
152
259
|
const found = [];
|
|
153
260
|
for (const one of targets) {
|
|
154
261
|
for (const named of one.requires) {
|
|
155
262
|
if (known.has(named))
|
|
156
263
|
continue;
|
|
157
|
-
found.push(`\`${one.id}\` requires "${named}", and this app declares no secret by that name. A secret is declared before it ` +
|
|
158
|
-
'is required, so the one place saying who
|
|
264
|
+
found.push(`\`${one.id}\` requires "${named}", and this app declares no secret and no target by that name. A secret is declared before it ` +
|
|
265
|
+
'is required, and a target before it is reached through, so the one place saying who holds a value, or ' +
|
|
266
|
+
'answers for a reach, is never whichever place happened to need it');
|
|
159
267
|
}
|
|
160
268
|
}
|
|
161
269
|
return found;
|
|
@@ -171,8 +279,22 @@ export function unanswered(calls, targets) {
|
|
|
171
279
|
}
|
|
172
280
|
const holds = holdsOf(of.id);
|
|
173
281
|
if (holds !== undefined && holds.takes !== 'calls') {
|
|
174
|
-
found.push(
|
|
175
|
-
|
|
282
|
+
found.push(holds.takes === 'entities'
|
|
283
|
+
? `\`${one.id}\` is a call on \`${of.id}\`, which is reached over ${String(reachOf(of.id))} and keeps entities. A place you keep rows in is not a place you issue verbs at`
|
|
284
|
+
: `\`${one.id}\` is a call on \`${of.id}\`, which is a ${String(reachOf(of.id))} and answers the orders every ${String(reachOf(of.id))} answers, so nothing is declared on it. A node is handed those orders by requiring it`);
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
if (reachOf(of.id) === 'https' && one.method === undefined) {
|
|
288
|
+
found.push(`\`${one.id}\` is a call over https and states no method. A call over https says its verb: GET, POST, PUT, PATCH or DELETE`);
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
if (reachOf(of.id) !== 'https' && one.method !== undefined) {
|
|
292
|
+
found.push(`\`${one.id}\` states the method ${one.method}, and \`${of.id}\` is a ${String(reachOf(of.id))}. A subcommand or a method has no http verb, so take \`method\` off that row`);
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
const shaped = misnamed(of.id, one.path);
|
|
296
|
+
if (shaped !== undefined) {
|
|
297
|
+
found.push(`\`${one.id}\` is a call on \`${of.id}\`, and its path ${shaped}`);
|
|
176
298
|
continue;
|
|
177
299
|
}
|
|
178
300
|
if (!of.takes.includes(one.id)) {
|
|
@@ -182,33 +304,32 @@ export function unanswered(calls, targets) {
|
|
|
182
304
|
}
|
|
183
305
|
return found;
|
|
184
306
|
}
|
|
185
|
-
export function
|
|
307
|
+
export function unplaced(targets, integrations) {
|
|
308
|
+
const known = new Set(integrations.map((one) => one.id));
|
|
186
309
|
const found = [];
|
|
187
310
|
for (const one of targets) {
|
|
188
|
-
const
|
|
189
|
-
if (
|
|
311
|
+
const named = one.of ?? '';
|
|
312
|
+
if (named === '') {
|
|
313
|
+
found.push(`\`${one.id}\` names no integration, and every target is one way into something outside this app — a vendor, ` +
|
|
314
|
+
'a service, a program on the machine. Say which one it reaches into: `thread create integration` lists ' +
|
|
315
|
+
'the ones already declared and declares another');
|
|
190
316
|
continue;
|
|
191
|
-
if (holds.arrives !== null && (one.uses ?? '') === '') {
|
|
192
|
-
found.push(`\`${one.id}\` is reached as ${String(reachOf(one.id))} and does not say what it uses — ` +
|
|
193
|
-
`${holds.arrives === 'npm' ? 'the npm package to install' : 'the program to run'} goes in \`uses\`, because the ` +
|
|
194
|
-
'id is what this app calls it and not what it is');
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
if (holds.arrives === null && one.uses !== undefined) {
|
|
198
|
-
found.push(`\`${one.id}\` is reached over ${String(reachOf(one.id))}, where nothing is installed and nothing is spawned, ` +
|
|
199
|
-
`and it states \`uses: '${one.uses}'\` — there is nothing for that name to be`);
|
|
200
317
|
}
|
|
318
|
+
if (known.has(named))
|
|
319
|
+
continue;
|
|
320
|
+
found.push(`\`${one.id}\` is part of "${named}", and this app declares no integration by that name. Declare it with ` +
|
|
321
|
+
'`thread create integration`, or point this row at one already declared');
|
|
201
322
|
}
|
|
202
323
|
return found;
|
|
203
324
|
}
|
|
204
|
-
export function refusals(targets, secrets, calls, entities) {
|
|
325
|
+
export function refusals(targets, secrets, calls, entities, integrations) {
|
|
205
326
|
return [
|
|
206
327
|
...unreachable(targets),
|
|
328
|
+
...unplaced(targets, integrations),
|
|
207
329
|
...unheld(targets, secrets),
|
|
208
330
|
...unaddressed(targets, secrets),
|
|
209
331
|
...unanswered(calls, targets),
|
|
210
332
|
...misaccepted(targets, entities, calls),
|
|
211
|
-
...misused(targets),
|
|
212
333
|
];
|
|
213
334
|
}
|
|
214
335
|
export function targetOf(entity, targets) {
|