@prestack/thread 0.1.3 → 0.1.4
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 +105 -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 +37 -65
- package/dist/core/attach.ts +32 -76
- 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 +89 -21
- package/dist/core/descend.ts +86 -17
- 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 +0 -1
- package/dist/core/init.js +48 -4
- package/dist/core/init.ts +54 -4
- 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/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 +1 -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 +33 -54
- package/dist/integrations/attach.ts +50 -57
- 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 +3 -73
- package/dist/integrity/attach.ts +1 -71
- 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 +58 -37
- package/dist/integrity/slopnator.ts +53 -37
- 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 +1 -1
- 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 +28 -109
- package/dist/operations/attach.ts +46 -113
- 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
package/dist/core/chain.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { starts } from '../integrations/cli.js';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { execPath } from 'node:process';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { existsSync, readFileSync, readdirSync } from
|
|
6
|
-
import { valuesIn } from
|
|
7
|
-
import { findTree } from
|
|
5
|
+
import { existsSync, readFileSync, readdirSync } from '../integrations/disk.js';
|
|
6
|
+
import { valuesIn } from './rows.js';
|
|
7
|
+
import { findTree } from './tree.js';
|
|
8
8
|
const STATING = 'derivation.ts';
|
|
9
9
|
export async function generators(tree = findTree()) {
|
|
10
10
|
if (!existsSync(tree.dir))
|
|
@@ -39,12 +39,8 @@ export const REFUSED_BY = 'round: refused';
|
|
|
39
39
|
export function batched(at, commands, within) {
|
|
40
40
|
if (commands.length === 0)
|
|
41
41
|
return [];
|
|
42
|
-
const out =
|
|
43
|
-
|
|
44
|
-
encoding: 'utf8',
|
|
45
|
-
...(within === undefined ? {} : { timeout: within, killSignal: 'SIGKILL' }),
|
|
46
|
-
});
|
|
47
|
-
const lines = `${out.stdout ?? ''}${out.stderr ?? ''}`.split('\n');
|
|
42
|
+
const out = starts(execPath, [...LOADER, RUNNER, ...new Set(commands)], { at, shows: 'errors', within });
|
|
43
|
+
const lines = out.out.split('\n');
|
|
48
44
|
const found = new Map();
|
|
49
45
|
let held = [];
|
|
50
46
|
for (const line of lines) {
|
|
@@ -58,12 +54,12 @@ export function batched(at, commands, within) {
|
|
|
58
54
|
held = [];
|
|
59
55
|
}
|
|
60
56
|
const orphaned = held.join('\n').trim();
|
|
61
|
-
const died = out.
|
|
62
|
-
? ` The runner itself failed to start or was stopped: ${out.
|
|
63
|
-
: out.
|
|
64
|
-
? ` The runner was killed by ${out.
|
|
65
|
-
: found.size === 0 && out.
|
|
66
|
-
? ` The runner exited ${String(out.
|
|
57
|
+
const died = out.why !== ''
|
|
58
|
+
? ` The runner itself failed to start or was stopped: ${out.why}.`
|
|
59
|
+
: out.killed !== null
|
|
60
|
+
? ` The runner was killed by ${out.killed} after ${String(within ?? 0)} ms. The last "settle: running" line above names the command it was inside, and everything after that one is unreported rather than refused.`
|
|
61
|
+
: found.size === 0 && !out.ok
|
|
62
|
+
? ` The runner exited ${String(out.code)} having reported nothing, so it died before the first command finished.`
|
|
67
63
|
: '';
|
|
68
64
|
let firstUnreached = true;
|
|
69
65
|
return commands.map((one) => {
|
|
@@ -93,7 +89,7 @@ export function settling(at, all, skip = []) {
|
|
|
93
89
|
let before;
|
|
94
90
|
while (round < ROUNDS) {
|
|
95
91
|
round += 1;
|
|
96
|
-
const asking =
|
|
92
|
+
const asking = batch(at, mine.map((one) => word(one.runs))).refused;
|
|
97
93
|
const unhappy = mine.filter((one) => asking.includes(word(one.runs)));
|
|
98
94
|
if (unhappy.length === 0)
|
|
99
95
|
return { ran, unsettled: [], rounds: round };
|
package/dist/core/chain.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { starts } from '../integrations/cli.ts'
|
|
2
2
|
import { join } from 'node:path'
|
|
3
3
|
import { execPath } from 'node:process'
|
|
4
4
|
import { fileURLToPath } from 'node:url'
|
|
5
5
|
|
|
6
6
|
import type { Row } from './descend.ts'
|
|
7
|
-
import { existsSync, readFileSync, readdirSync } from '
|
|
7
|
+
import { existsSync, readFileSync, readdirSync } from '../integrations/disk.ts'
|
|
8
8
|
import { valuesIn } from './rows.ts'
|
|
9
9
|
import { findTree, type Tree } from './tree.ts'
|
|
10
10
|
|
|
@@ -58,12 +58,8 @@ export function batched(
|
|
|
58
58
|
): readonly { readonly command: string; readonly ok: boolean; readonly said: string }[] {
|
|
59
59
|
if (commands.length === 0) return []
|
|
60
60
|
|
|
61
|
-
const out =
|
|
62
|
-
|
|
63
|
-
encoding: 'utf8',
|
|
64
|
-
...(within === undefined ? {} : { timeout: within, killSignal: 'SIGKILL' as const }),
|
|
65
|
-
})
|
|
66
|
-
const lines = `${out.stdout ?? ''}${out.stderr ?? ''}`.split('\n')
|
|
61
|
+
const out = starts(execPath, [...LOADER, RUNNER, ...new Set(commands)], { at, shows: 'errors', within })
|
|
62
|
+
const lines = out.out.split('\n')
|
|
67
63
|
|
|
68
64
|
const found = new Map<string, { readonly command: string; readonly ok: boolean; readonly said: string }>()
|
|
69
65
|
let held: string[] = []
|
|
@@ -80,12 +76,12 @@ export function batched(
|
|
|
80
76
|
|
|
81
77
|
const orphaned = held.join('\n').trim()
|
|
82
78
|
const died =
|
|
83
|
-
out.
|
|
84
|
-
? ` The runner itself failed to start or was stopped: ${out.
|
|
85
|
-
: out.
|
|
86
|
-
? ` The runner was killed by ${out.
|
|
87
|
-
: found.size === 0 && out.
|
|
88
|
-
? ` The runner exited ${String(out.
|
|
79
|
+
out.why !== ''
|
|
80
|
+
? ` The runner itself failed to start or was stopped: ${out.why}.`
|
|
81
|
+
: out.killed !== null
|
|
82
|
+
? ` The runner was killed by ${out.killed} after ${String(within ?? 0)} ms. The last "settle: running" line above names the command it was inside, and everything after that one is unreported rather than refused.`
|
|
83
|
+
: found.size === 0 && !out.ok
|
|
84
|
+
? ` The runner exited ${String(out.code)} having reported nothing, so it died before the first command finished.`
|
|
89
85
|
: ''
|
|
90
86
|
let firstUnreached = true
|
|
91
87
|
return commands.map((one) => {
|
|
@@ -127,7 +123,7 @@ export function settling(
|
|
|
127
123
|
while (round < ROUNDS) {
|
|
128
124
|
round += 1
|
|
129
125
|
|
|
130
|
-
const asking =
|
|
126
|
+
const asking = batch(at, mine.map((one) => word(one.runs))).refused
|
|
131
127
|
const unhappy = mine.filter((one) => asking.includes(word(one.runs)))
|
|
132
128
|
if (unhappy.length === 0) return { ran, unsettled: [], rounds: round }
|
|
133
129
|
|
package/dist/core/condition.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type Actor } from './actor.ts';
|
|
2
|
-
export declare const COMPARE_OPS: readonly [
|
|
2
|
+
export declare const COMPARE_OPS: readonly ['eq', 'neq', 'lt', 'lte', 'gt', 'gte', 'in', 'has'];
|
|
3
3
|
export type CompareOp = (typeof COMPARE_OPS)[number];
|
|
4
|
-
export declare const AGGREGATIONS: readonly [
|
|
5
|
-
export declare const ACTOR_FACTS: readonly ["id", "roles", "entitlements", ...("
|
|
4
|
+
export declare const AGGREGATIONS: readonly ['count', 'sum', 'min', 'max', 'avg'];
|
|
5
|
+
export declare const ACTOR_FACTS: readonly ["id", "roles", "entitlements", ...("address" | "device" | "moment" | "replay" | "run")[]];
|
|
6
6
|
export declare const AGO: RegExp;
|
|
7
7
|
export type Operand = {
|
|
8
8
|
readonly value: string | number | boolean | null;
|
|
@@ -41,7 +41,7 @@ export declare function walkOperands(condition: Condition, take: (one: Operand)
|
|
|
41
41
|
export declare function mentionsActor(condition: Condition): boolean;
|
|
42
42
|
export declare function agoSeconds(ago: string): number | undefined;
|
|
43
43
|
export declare function satisfies(condition: Condition, actor: Actor): boolean;
|
|
44
|
-
export declare const CONDITION_ANSWERS: readonly [
|
|
44
|
+
export declare const CONDITION_ANSWERS: readonly ['is', 'than', 'field', 'value', 'actor', 'ago', 'of', 'how', 'over', 'op', 'when', 'joins'];
|
|
45
45
|
export declare function conditioned(ask: (key: string, question: string) => Promise<string>, say: (line: string) => void, subject: {
|
|
46
46
|
readonly id: string;
|
|
47
47
|
readonly fields: readonly string[];
|
package/dist/core/condition.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ENVIRONMENT } from
|
|
1
|
+
import { ENVIRONMENT } from './actor.js';
|
|
2
2
|
export const COMPARE_OPS = ['eq', 'neq', 'lt', 'lte', 'gt', 'gte', 'in', 'has'];
|
|
3
3
|
export const AGGREGATIONS = ['count', 'sum', 'min', 'max', 'avg'];
|
|
4
4
|
export const ACTOR_FACTS = ['id', 'roles', 'entitlements', ...ENVIRONMENT.map(([fact]) => fact)];
|
|
@@ -182,7 +182,7 @@ export async function conditioned(ask, say, subject, all) {
|
|
|
182
182
|
const first = held[0];
|
|
183
183
|
return held.length === 1 ? first : joiner === 'all' ? { all: held } : { any: held };
|
|
184
184
|
}
|
|
185
|
-
import { quoted } from
|
|
185
|
+
import { quoted } from './rows.js';
|
|
186
186
|
export function said(one) {
|
|
187
187
|
if (typeof one === 'string')
|
|
188
188
|
return quoted(one);
|
package/dist/core/descend.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export declare const ROOT: string;
|
|
|
4
4
|
export declare const TREE: string;
|
|
5
5
|
export declare const THREAD_AT: string;
|
|
6
6
|
export declare function unkept(at: string): boolean;
|
|
7
|
-
export declare const LISTS: readonly [
|
|
7
|
+
export declare const LISTS: readonly ['declares', 'derives', 'seeds'];
|
|
8
8
|
export declare const ROW_LISTS: readonly ["declares", "derives", "seeds", "holds"];
|
|
9
9
|
export interface Row {
|
|
10
10
|
readonly at?: string;
|
|
@@ -59,6 +59,7 @@ export declare function shapeFields(named: string, inside?: string): readonly {
|
|
|
59
59
|
readonly map: boolean;
|
|
60
60
|
readonly worded: boolean;
|
|
61
61
|
readonly guide: string;
|
|
62
|
+
readonly record: readonly string[];
|
|
62
63
|
}[];
|
|
63
64
|
export interface Field {
|
|
64
65
|
readonly name: string;
|
|
@@ -68,9 +69,10 @@ export interface Field {
|
|
|
68
69
|
readonly boolean: boolean;
|
|
69
70
|
readonly worded: boolean;
|
|
70
71
|
readonly guide: string;
|
|
72
|
+
readonly record: readonly string[];
|
|
71
73
|
}
|
|
72
74
|
export declare function listShape(at: string, list: string): string | undefined;
|
|
73
|
-
export declare function listFields(at: string, list: string): readonly Field[];
|
|
75
|
+
export declare function listFields(at: string, list: string, within?: number): readonly Field[];
|
|
74
76
|
export declare function rowShape(at: string, list: string): string | undefined;
|
|
75
77
|
interface Held {
|
|
76
78
|
readonly name: string;
|
package/dist/core/descend.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { attached, existsSync, kind, readdirSync, readFileSync, realpathSync, statSync, writeFileSync } from
|
|
1
|
+
import { starts } from '../integrations/cli.js';
|
|
2
|
+
import { attached, beyond, existsSync, here as answering, kind, readdirSync, readFileSync, realpathSync, statSync, writeFileSync } from '../integrations/disk.js';
|
|
3
3
|
import { dirname, join, relative, resolve } from 'node:path';
|
|
4
4
|
import ts from 'typescript';
|
|
5
|
-
import { ignored } from
|
|
6
|
-
import { NAMED, ORGANISATION } from
|
|
7
|
-
import { findTree } from
|
|
5
|
+
import { ignored } from './init.js';
|
|
6
|
+
import { NAMED, ORGANISATION } from './scope.js';
|
|
7
|
+
import { findTree } from './tree.js';
|
|
8
8
|
const BUILT = new Set(ignored()
|
|
9
9
|
.split('\n')
|
|
10
10
|
.map((one) => one.trim())
|
|
@@ -32,7 +32,7 @@ function ownIgnores() {
|
|
|
32
32
|
if (readIgnores)
|
|
33
33
|
return ignores;
|
|
34
34
|
readIgnores = true;
|
|
35
|
-
if (!attached() &&
|
|
35
|
+
if (!attached() && starts('git', ['rev-parse', '--is-inside-work-tree'], { at: ROOT }).ok) {
|
|
36
36
|
return ignores;
|
|
37
37
|
}
|
|
38
38
|
try {
|
|
@@ -55,7 +55,7 @@ export function unkept(at) {
|
|
|
55
55
|
return held;
|
|
56
56
|
const own = ownIgnores();
|
|
57
57
|
const found = own === undefined
|
|
58
|
-
?
|
|
58
|
+
? starts('git', ['check-ignore', '-q', '--', at], { at: ROOT }).ok
|
|
59
59
|
: own.some((one) => at === one || at.startsWith(`${one}/`) || at.split('/').includes(one));
|
|
60
60
|
asked.set(at, found);
|
|
61
61
|
return found;
|
|
@@ -198,7 +198,7 @@ function listing(at, take, skip, only, deep) {
|
|
|
198
198
|
function parsing(from) {
|
|
199
199
|
return {
|
|
200
200
|
useCaseSensitiveFileNames: true,
|
|
201
|
-
fileExists: (at) => existsSync(at),
|
|
201
|
+
fileExists: (at) => !beyond(at) && existsSync(at),
|
|
202
202
|
readFile: (at) => {
|
|
203
203
|
try {
|
|
204
204
|
return readFileSync(at);
|
|
@@ -237,23 +237,34 @@ export function configured() {
|
|
|
237
237
|
}
|
|
238
238
|
return { options: { ...FALLBACK, ...INVARIANT }, from: '' };
|
|
239
239
|
}
|
|
240
|
+
const libraries = new Map();
|
|
241
|
+
const DEPENDENCIES = '/node_' + 'modules/';
|
|
240
242
|
export function hosting(options) {
|
|
241
243
|
const host = ts.createCompilerHost(options, true);
|
|
242
244
|
const lib = host.getDefaultLibLocation?.();
|
|
245
|
+
const settings = JSON.stringify(options);
|
|
243
246
|
const toolchain = (at) => lib !== undefined && (at === lib || at.startsWith(`${lib}/`));
|
|
247
|
+
const seen = (at) => (beyond(at) ? 'none' : kind(at));
|
|
244
248
|
return {
|
|
245
249
|
...host,
|
|
246
|
-
fileExists: (at) => (toolchain(at) ? host.fileExists(at) :
|
|
247
|
-
directoryExists: (at) => (toolchain(at) ? (host.directoryExists?.(at) ?? false) :
|
|
248
|
-
readFile: (at) => (toolchain(at) ? host.readFile(at) :
|
|
250
|
+
fileExists: (at) => (toolchain(at) ? host.fileExists(at) : seen(at) === 'file'),
|
|
251
|
+
directoryExists: (at) => (toolchain(at) ? (host.directoryExists?.(at) ?? false) : seen(at) === 'folder'),
|
|
252
|
+
readFile: (at) => (toolchain(at) ? host.readFile(at) : seen(at) === 'file' ? readFileSync(at) : undefined),
|
|
249
253
|
getSourceFile: (at, version) => {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
if (
|
|
253
|
-
return
|
|
254
|
-
|
|
254
|
+
const lasting = toolchain(at) ? true : at.includes(DEPENDENCIES);
|
|
255
|
+
const key = settings + at + JSON.stringify(version);
|
|
256
|
+
if (lasting && libraries.has(key))
|
|
257
|
+
return libraries.get(key);
|
|
258
|
+
const made = toolchain(at)
|
|
259
|
+
? host.getSourceFile(at, version)
|
|
260
|
+
: seen(at) === 'file'
|
|
261
|
+
? ts.createSourceFile(at, readFileSync(at), version, true)
|
|
262
|
+
: undefined;
|
|
263
|
+
if (lasting)
|
|
264
|
+
libraries.set(key, made);
|
|
265
|
+
return made;
|
|
255
266
|
},
|
|
256
|
-
getDirectories: (at) =>
|
|
267
|
+
getDirectories: (at) => seen(at) === 'folder' ? readdirSync(at, { withFileTypes: true }).filter((one) => one.isDirectory()).map((one) => one.name) : [],
|
|
257
268
|
realpath: (at) => (toolchain(at) ? (host.realpath?.(at) ?? at) : realpathSync(at)),
|
|
258
269
|
writeFile: (at, said) => {
|
|
259
270
|
writeFileSync(at, said);
|
|
@@ -328,8 +339,13 @@ export function read(at) {
|
|
|
328
339
|
source.set(at, text);
|
|
329
340
|
return text;
|
|
330
341
|
}
|
|
342
|
+
const shapes = new WeakMap();
|
|
331
343
|
export function shapesNamed() {
|
|
332
|
-
const
|
|
344
|
+
const held = compiled();
|
|
345
|
+
const known = shapes.get(held);
|
|
346
|
+
if (known !== undefined)
|
|
347
|
+
return known;
|
|
348
|
+
const { program, checker } = held;
|
|
333
349
|
const shape = threadedType(checker, program);
|
|
334
350
|
const found = new Map();
|
|
335
351
|
if (shape === undefined)
|
|
@@ -368,6 +384,7 @@ export function shapesNamed() {
|
|
|
368
384
|
found.set(named, [...where, at]);
|
|
369
385
|
}
|
|
370
386
|
}
|
|
387
|
+
shapes.set(held, found);
|
|
371
388
|
return found;
|
|
372
389
|
}
|
|
373
390
|
export function threading() {
|
|
@@ -408,13 +425,14 @@ export function shapeFields(named, inside) {
|
|
|
408
425
|
map: mapped(kind),
|
|
409
426
|
worded: (kind.isUnion() ? kind.types : [kind]).some((each) => (each.flags & ts.TypeFlags.StringLike) !== 0),
|
|
410
427
|
guide: ts.displayPartsToString(one.getDocumentationComment(checker)).trim(),
|
|
428
|
+
record: recordOf(checker, kind),
|
|
411
429
|
};
|
|
412
430
|
});
|
|
413
431
|
}
|
|
414
432
|
}
|
|
415
433
|
return [];
|
|
416
434
|
}
|
|
417
|
-
function elementAt(at, list) {
|
|
435
|
+
function elementAt(at, list, within) {
|
|
418
436
|
const { program, checker } = compiled();
|
|
419
437
|
const file = program.getSourceFile(resolve(ROOT, at));
|
|
420
438
|
if (file === undefined)
|
|
@@ -424,6 +442,8 @@ function elementAt(at, list) {
|
|
|
424
442
|
const consider = (node) => {
|
|
425
443
|
if (held !== undefined)
|
|
426
444
|
return;
|
|
445
|
+
if (within !== undefined && node.getStart() !== within)
|
|
446
|
+
return;
|
|
427
447
|
const wanted = checker.getContextualType(node) ?? checker.getTypeAtLocation(node);
|
|
428
448
|
const kinds = (wanted.isUnionOrIntersection() ? wanted.types : [wanted])
|
|
429
449
|
.filter((one) => checker.getIndexTypeOfType(one, ts.IndexKind.Number) !== undefined)
|
|
@@ -455,8 +475,8 @@ export function listShape(at, list) {
|
|
|
455
475
|
const held = elementAt(at, list);
|
|
456
476
|
return held === undefined ? undefined : compiled().checker.typeToString(held.type);
|
|
457
477
|
}
|
|
458
|
-
export function listFields(at, list) {
|
|
459
|
-
const held = elementAt(at, list);
|
|
478
|
+
export function listFields(at, list, within) {
|
|
479
|
+
const held = elementAt(at, list, within);
|
|
460
480
|
if (held === undefined)
|
|
461
481
|
return [];
|
|
462
482
|
const { checker } = compiled();
|
|
@@ -480,12 +500,29 @@ export function listFields(at, list) {
|
|
|
480
500
|
boolean: flagged(kind),
|
|
481
501
|
worded: worded(kind),
|
|
482
502
|
guide: ts.displayPartsToString(one.getDocumentationComment(checker)).trim(),
|
|
503
|
+
record: recordOf(checker, kind),
|
|
483
504
|
};
|
|
484
505
|
});
|
|
485
506
|
}
|
|
486
507
|
function elementOf(checker, type) {
|
|
487
508
|
return checker.getIndexTypeOfType(type, ts.IndexKind.Number) ?? type;
|
|
488
509
|
}
|
|
510
|
+
function recordOf(checker, type) {
|
|
511
|
+
for (const each of type.isUnion() ? type.types : [type]) {
|
|
512
|
+
if ((each.flags & ts.TypeFlags.StringLike) !== 0 || checker.getIndexTypeOfType(each, ts.IndexKind.Number) === undefined)
|
|
513
|
+
continue;
|
|
514
|
+
const element = elementOf(checker, each);
|
|
515
|
+
if ((element.flags & ts.TypeFlags.Object) === 0)
|
|
516
|
+
return [];
|
|
517
|
+
const fields = checker.getPropertiesOfType(element);
|
|
518
|
+
const worded = fields.every((one) => {
|
|
519
|
+
const kind = checker.getNonNullableType(checker.getTypeOfSymbol(one));
|
|
520
|
+
return (kind.isUnion() ? kind.types : [kind]).every((part) => (part.flags & ts.TypeFlags.StringLike) !== 0);
|
|
521
|
+
});
|
|
522
|
+
return worded ? fields.map((one) => one.getName()) : [];
|
|
523
|
+
}
|
|
524
|
+
return [];
|
|
525
|
+
}
|
|
489
526
|
export function rowShape(at, list) {
|
|
490
527
|
const { program, checker } = compiled();
|
|
491
528
|
const file = program.getSourceFile(resolve(ROOT, at));
|
|
@@ -666,7 +703,38 @@ let passed;
|
|
|
666
703
|
export function reached() {
|
|
667
704
|
return [THREAD_AT, ...descend().threaded.keys()];
|
|
668
705
|
}
|
|
706
|
+
let world = answering();
|
|
707
|
+
const worlds = new WeakMap();
|
|
708
|
+
function kept() {
|
|
709
|
+
const was = { passed, built, scanned, commands, ignores, readIgnores, source: new Map(source), asked: new Map(asked) };
|
|
710
|
+
return () => {
|
|
711
|
+
passed = was.passed;
|
|
712
|
+
built = was.built;
|
|
713
|
+
scanned = was.scanned;
|
|
714
|
+
commands = was.commands;
|
|
715
|
+
ignores = was.ignores;
|
|
716
|
+
readIgnores = was.readIgnores;
|
|
717
|
+
source.clear();
|
|
718
|
+
for (const [at, text] of was.source)
|
|
719
|
+
source.set(at, text);
|
|
720
|
+
asked.clear();
|
|
721
|
+
for (const [at, ignore] of was.asked)
|
|
722
|
+
asked.set(at, ignore);
|
|
723
|
+
};
|
|
724
|
+
}
|
|
669
725
|
export function forget() {
|
|
726
|
+
const now = answering();
|
|
727
|
+
if (now === world)
|
|
728
|
+
libraries.clear();
|
|
729
|
+
else {
|
|
730
|
+
worlds.set(world, kept());
|
|
731
|
+
world = now;
|
|
732
|
+
const back = worlds.get(now);
|
|
733
|
+
if (back !== undefined) {
|
|
734
|
+
back();
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
670
738
|
passed = undefined;
|
|
671
739
|
built = undefined;
|
|
672
740
|
scanned = undefined;
|
package/dist/core/descend.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { attached, existsSync, kind, readdirSync, readFileSync, realpathSync, statSync, writeFileSync } from '
|
|
1
|
+
import { starts } from '../integrations/cli.ts'
|
|
2
|
+
import { attached, beyond, existsSync, here as answering, kind, readdirSync, readFileSync, realpathSync, statSync, writeFileSync, type Kind } from '../integrations/disk.ts'
|
|
3
3
|
import { dirname, join, relative, resolve } from 'node:path'
|
|
4
4
|
|
|
5
5
|
import ts from 'typescript'
|
|
@@ -41,7 +41,7 @@ let readIgnores = false
|
|
|
41
41
|
function ownIgnores(): readonly string[] | undefined {
|
|
42
42
|
if (readIgnores) return ignores
|
|
43
43
|
readIgnores = true
|
|
44
|
-
if (!attached() &&
|
|
44
|
+
if (!attached() && starts('git', ['rev-parse', '--is-inside-work-tree'], { at: ROOT }).ok) {
|
|
45
45
|
return ignores
|
|
46
46
|
}
|
|
47
47
|
try {
|
|
@@ -65,7 +65,7 @@ export function unkept(at: string): boolean {
|
|
|
65
65
|
const own = ownIgnores()
|
|
66
66
|
const found =
|
|
67
67
|
own === undefined
|
|
68
|
-
?
|
|
68
|
+
? starts('git', ['check-ignore', '-q', '--', at], { at: ROOT }).ok
|
|
69
69
|
: own.some((one) => at === one || at.startsWith(`${one}/`) || at.split('/').includes(one))
|
|
70
70
|
asked.set(at, found)
|
|
71
71
|
return found
|
|
@@ -252,7 +252,7 @@ function listing(at: string, take: readonly string[], skip: readonly string[], o
|
|
|
252
252
|
function parsing(from: string): ts.ParseConfigHost {
|
|
253
253
|
return {
|
|
254
254
|
useCaseSensitiveFileNames: true,
|
|
255
|
-
fileExists: (at) => existsSync(at),
|
|
255
|
+
fileExists: (at) => !beyond(at) && existsSync(at),
|
|
256
256
|
readFile: (at) => {
|
|
257
257
|
try {
|
|
258
258
|
return readFileSync(at)
|
|
@@ -301,22 +301,35 @@ export function configured(): { readonly options: ts.CompilerOptions; readonly f
|
|
|
301
301
|
return { options: { ...FALLBACK, ...INVARIANT }, from: '' }
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
+
const libraries = new Map<string, ReturnType<ts.CompilerHost['getSourceFile']>>()
|
|
305
|
+
|
|
306
|
+
const DEPENDENCIES = '/node_' + 'modules/'
|
|
307
|
+
|
|
304
308
|
export function hosting(options: ts.CompilerOptions): ts.CompilerHost {
|
|
305
309
|
const host = ts.createCompilerHost(options, true)
|
|
306
310
|
const lib = host.getDefaultLibLocation?.()
|
|
311
|
+
const settings = JSON.stringify(options)
|
|
307
312
|
const toolchain = (at: string): boolean => lib !== undefined && (at === lib || at.startsWith(`${lib}/`))
|
|
313
|
+
const seen = (at: string): Kind => (beyond(at) ? 'none' : kind(at))
|
|
308
314
|
return {
|
|
309
315
|
...host,
|
|
310
|
-
fileExists: (at) => (toolchain(at) ? host.fileExists(at) :
|
|
311
|
-
directoryExists: (at) => (toolchain(at) ? (host.directoryExists?.(at) ?? false) :
|
|
312
|
-
readFile: (at) => (toolchain(at) ? host.readFile(at) :
|
|
316
|
+
fileExists: (at) => (toolchain(at) ? host.fileExists(at) : seen(at) === 'file'),
|
|
317
|
+
directoryExists: (at) => (toolchain(at) ? (host.directoryExists?.(at) ?? false) : seen(at) === 'folder'),
|
|
318
|
+
readFile: (at) => (toolchain(at) ? host.readFile(at) : seen(at) === 'file' ? readFileSync(at) : undefined),
|
|
313
319
|
getSourceFile: (at, version) => {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
320
|
+
const lasting = toolchain(at) ? true : at.includes(DEPENDENCIES)
|
|
321
|
+
const key = settings + at + JSON.stringify(version)
|
|
322
|
+
if (lasting && libraries.has(key)) return libraries.get(key)
|
|
323
|
+
const made = toolchain(at)
|
|
324
|
+
? host.getSourceFile(at, version)
|
|
325
|
+
: seen(at) === 'file'
|
|
326
|
+
? ts.createSourceFile(at, readFileSync(at), version, true)
|
|
327
|
+
: undefined
|
|
328
|
+
if (lasting) libraries.set(key, made)
|
|
329
|
+
return made
|
|
317
330
|
},
|
|
318
331
|
getDirectories: (at) =>
|
|
319
|
-
|
|
332
|
+
seen(at) === 'folder' ? readdirSync(at, { withFileTypes: true }).filter((one) => one.isDirectory()).map((one) => one.name) : [],
|
|
320
333
|
realpath: (at) => (toolchain(at) ? (host.realpath?.(at) ?? at) : realpathSync(at)),
|
|
321
334
|
writeFile: (at, said) => {
|
|
322
335
|
writeFileSync(at, said)
|
|
@@ -389,8 +402,13 @@ export function read(at: string): string | undefined {
|
|
|
389
402
|
return text
|
|
390
403
|
}
|
|
391
404
|
|
|
405
|
+
const shapes = new WeakMap<object, ReadonlyMap<string, readonly string[]>>()
|
|
406
|
+
|
|
392
407
|
export function shapesNamed(): ReadonlyMap<string, readonly string[]> {
|
|
393
|
-
const
|
|
408
|
+
const held = compiled()
|
|
409
|
+
const known = shapes.get(held)
|
|
410
|
+
if (known !== undefined) return known
|
|
411
|
+
const { program, checker } = held
|
|
394
412
|
const shape = threadedType(checker, program)
|
|
395
413
|
const found = new Map<string, string[]>()
|
|
396
414
|
if (shape === undefined) return found
|
|
@@ -419,6 +437,7 @@ export function shapesNamed(): ReadonlyMap<string, readonly string[]> {
|
|
|
419
437
|
found.set(named, [...where, at])
|
|
420
438
|
}
|
|
421
439
|
}
|
|
440
|
+
shapes.set(held, found)
|
|
422
441
|
return found
|
|
423
442
|
}
|
|
424
443
|
|
|
@@ -429,7 +448,7 @@ export function threading(): ReadonlySet<string> {
|
|
|
429
448
|
export function shapeFields(
|
|
430
449
|
named: string,
|
|
431
450
|
inside?: string,
|
|
432
|
-
): readonly { readonly name: string; readonly required: boolean; readonly list: boolean; readonly map: boolean; readonly worded: boolean; readonly guide: string }[] {
|
|
451
|
+
): readonly { readonly name: string; readonly required: boolean; readonly list: boolean; readonly map: boolean; readonly worded: boolean; readonly guide: string; readonly record: readonly string[] }[] {
|
|
433
452
|
const { program, checker } = compiled()
|
|
434
453
|
for (const at of [...sources(), ...shipped()]) {
|
|
435
454
|
if (!SOURCE.test(at)) continue
|
|
@@ -466,6 +485,7 @@ export function shapeFields(
|
|
|
466
485
|
map: mapped(kind),
|
|
467
486
|
worded: (kind.isUnion() ? kind.types : [kind]).some((each) => (each.flags & ts.TypeFlags.StringLike) !== 0),
|
|
468
487
|
guide: ts.displayPartsToString(one.getDocumentationComment(checker)).trim(),
|
|
488
|
+
record: recordOf(checker, kind),
|
|
469
489
|
}
|
|
470
490
|
})
|
|
471
491
|
}
|
|
@@ -481,9 +501,10 @@ export interface Field {
|
|
|
481
501
|
readonly boolean: boolean
|
|
482
502
|
readonly worded: boolean
|
|
483
503
|
readonly guide: string
|
|
504
|
+
readonly record: readonly string[]
|
|
484
505
|
}
|
|
485
506
|
|
|
486
|
-
function elementAt(at: string, list: string): { readonly type: ts.Type; readonly node: ts.Node } | undefined {
|
|
507
|
+
function elementAt(at: string, list: string, within?: number): { readonly type: ts.Type; readonly node: ts.Node } | undefined {
|
|
487
508
|
const { program, checker } = compiled()
|
|
488
509
|
const file = program.getSourceFile(resolve(ROOT, at))
|
|
489
510
|
if (file === undefined) return undefined
|
|
@@ -493,6 +514,7 @@ function elementAt(at: string, list: string): { readonly type: ts.Type; readonly
|
|
|
493
514
|
|
|
494
515
|
const consider = (node: ts.ArrayLiteralExpression): void => {
|
|
495
516
|
if (held !== undefined) return
|
|
517
|
+
if (within !== undefined && node.getStart() !== within) return
|
|
496
518
|
const wanted = checker.getContextualType(node) ?? checker.getTypeAtLocation(node)
|
|
497
519
|
const kinds = (wanted.isUnionOrIntersection() ? wanted.types : [wanted])
|
|
498
520
|
.filter((one) => checker.getIndexTypeOfType(one, ts.IndexKind.Number) !== undefined)
|
|
@@ -525,8 +547,8 @@ export function listShape(at: string, list: string): string | undefined {
|
|
|
525
547
|
return held === undefined ? undefined : compiled().checker.typeToString(held.type)
|
|
526
548
|
}
|
|
527
549
|
|
|
528
|
-
export function listFields(at: string, list: string): readonly Field[] {
|
|
529
|
-
const held = elementAt(at, list)
|
|
550
|
+
export function listFields(at: string, list: string, within?: number): readonly Field[] {
|
|
551
|
+
const held = elementAt(at, list, within)
|
|
530
552
|
if (held === undefined) return []
|
|
531
553
|
const { checker } = compiled()
|
|
532
554
|
const bare = (kind: ts.Type): readonly ts.Type[] =>
|
|
@@ -557,6 +579,7 @@ export function listFields(at: string, list: string): readonly Field[] {
|
|
|
557
579
|
boolean: flagged(kind),
|
|
558
580
|
worded: worded(kind),
|
|
559
581
|
guide: ts.displayPartsToString(one.getDocumentationComment(checker)).trim(),
|
|
582
|
+
record: recordOf(checker, kind),
|
|
560
583
|
}
|
|
561
584
|
})
|
|
562
585
|
}
|
|
@@ -565,6 +588,21 @@ function elementOf(checker: ts.TypeChecker, type: ts.Type): ts.Type {
|
|
|
565
588
|
return checker.getIndexTypeOfType(type, ts.IndexKind.Number) ?? type
|
|
566
589
|
}
|
|
567
590
|
|
|
591
|
+
function recordOf(checker: ts.TypeChecker, type: ts.Type): readonly string[] {
|
|
592
|
+
for (const each of type.isUnion() ? type.types : [type]) {
|
|
593
|
+
if ((each.flags & ts.TypeFlags.StringLike) !== 0 || checker.getIndexTypeOfType(each, ts.IndexKind.Number) === undefined) continue
|
|
594
|
+
const element = elementOf(checker, each)
|
|
595
|
+
if ((element.flags & ts.TypeFlags.Object) === 0) return []
|
|
596
|
+
const fields = checker.getPropertiesOfType(element)
|
|
597
|
+
const worded = fields.every((one) => {
|
|
598
|
+
const kind = checker.getNonNullableType(checker.getTypeOfSymbol(one))
|
|
599
|
+
return (kind.isUnion() ? kind.types : [kind]).every((part) => (part.flags & ts.TypeFlags.StringLike) !== 0)
|
|
600
|
+
})
|
|
601
|
+
return worded ? fields.map((one) => one.getName()) : []
|
|
602
|
+
}
|
|
603
|
+
return []
|
|
604
|
+
}
|
|
605
|
+
|
|
568
606
|
export function rowShape(at: string, list: string): string | undefined {
|
|
569
607
|
const { program, checker } = compiled()
|
|
570
608
|
const file = program.getSourceFile(resolve(ROOT, at))
|
|
@@ -751,7 +789,38 @@ export function reached(): readonly string[] {
|
|
|
751
789
|
return [THREAD_AT, ...descend().threaded.keys()]
|
|
752
790
|
}
|
|
753
791
|
|
|
792
|
+
let world: object = answering()
|
|
793
|
+
|
|
794
|
+
const worlds = new WeakMap<object, () => void>()
|
|
795
|
+
|
|
796
|
+
function kept(): () => void {
|
|
797
|
+
const was = { passed, built, scanned, commands, ignores, readIgnores, source: new Map(source), asked: new Map(asked) }
|
|
798
|
+
return () => {
|
|
799
|
+
passed = was.passed
|
|
800
|
+
built = was.built
|
|
801
|
+
scanned = was.scanned
|
|
802
|
+
commands = was.commands
|
|
803
|
+
ignores = was.ignores
|
|
804
|
+
readIgnores = was.readIgnores
|
|
805
|
+
source.clear()
|
|
806
|
+
for (const [at, text] of was.source) source.set(at, text)
|
|
807
|
+
asked.clear()
|
|
808
|
+
for (const [at, ignore] of was.asked) asked.set(at, ignore)
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
754
812
|
export function forget(): void {
|
|
813
|
+
const now = answering()
|
|
814
|
+
if (now === world) libraries.clear()
|
|
815
|
+
else {
|
|
816
|
+
worlds.set(world, kept())
|
|
817
|
+
world = now
|
|
818
|
+
const back = worlds.get(now)
|
|
819
|
+
if (back !== undefined) {
|
|
820
|
+
back()
|
|
821
|
+
return
|
|
822
|
+
}
|
|
823
|
+
}
|
|
755
824
|
passed = undefined
|
|
756
825
|
built = undefined
|
|
757
826
|
scanned = undefined
|