@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
|
@@ -3,18 +3,6 @@ export declare const NOT_WRITTEN: unique symbol;
|
|
|
3
3
|
export declare const SHIPPED: string;
|
|
4
4
|
export declare const SEEDED: string;
|
|
5
5
|
export declare const ROOT: string;
|
|
6
|
-
export declare const DEPTH = "THREAD_DEPTH";
|
|
7
|
-
export declare const CEILING = 1;
|
|
8
|
-
export declare const SPAWN_TIMEOUT = 120000;
|
|
9
|
-
export declare const SPAWN_BUFFER: number;
|
|
10
|
-
export declare function nested(): boolean;
|
|
11
|
-
export declare function ran(command: string, options: {
|
|
12
|
-
readonly cwd: string;
|
|
13
|
-
readonly args?: readonly string[];
|
|
14
|
-
}): {
|
|
15
|
-
readonly status: number | null;
|
|
16
|
-
readonly said: string;
|
|
17
|
-
} | undefined;
|
|
18
6
|
export interface SlopnatorContext {
|
|
19
7
|
readonly filename: string;
|
|
20
8
|
readonly text: string;
|
|
@@ -53,7 +41,9 @@ export interface Byproduct {
|
|
|
53
41
|
readonly content: string;
|
|
54
42
|
}
|
|
55
43
|
export declare function slopnatorName(rule: string): string;
|
|
56
|
-
export declare function
|
|
44
|
+
export declare function region(fragment: string, path: readonly string[]): boolean;
|
|
45
|
+
export declare function derivedHere(): ReadonlySet<string> | undefined;
|
|
46
|
+
export declare function subject(rule: Constraint): boolean;
|
|
57
47
|
export declare function governs(rule: Constraint, filename: string): boolean;
|
|
58
48
|
export declare class UnloadableSlopnatorError extends Error {
|
|
59
49
|
constructor(rule: string, at: string, because: string);
|
|
@@ -6,14 +6,15 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
6
6
|
}
|
|
7
7
|
return path;
|
|
8
8
|
};
|
|
9
|
-
import {
|
|
10
|
-
import { existsSync, readFileSync, readdirSync, writeFileSync } from "../core/files.js";
|
|
9
|
+
import { existsSync, readFileSync, readdirSync, writeFileSync } from '../integrations/disk.js';
|
|
11
10
|
import { dirname, join } from 'node:path';
|
|
12
11
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
12
|
+
import { descend } from '../core/descend.js';
|
|
13
|
+
import { governs as reaches, islandsDeclared } from './slopnators/sl_unthreaded.js';
|
|
14
|
+
import { invoked } from '../core/invoked.js';
|
|
15
|
+
import { listBounds, quoted, withSeed } from '../core/rows.js';
|
|
16
|
+
import { CONSTRAINTS } from './constraint.js';
|
|
17
|
+
import { findTree, inTree } from '../core/tree.js';
|
|
17
18
|
export const NOT_WRITTEN = Symbol.for('thread.slopnator.not_written');
|
|
18
19
|
const HOME = dirname(fileURLToPath(import.meta.url));
|
|
19
20
|
export const SHIPPED = `${HOME}/slopnators`;
|
|
@@ -22,29 +23,6 @@ function homes(root) {
|
|
|
22
23
|
return [SHIPPED, join(root, SEEDED)];
|
|
23
24
|
}
|
|
24
25
|
export const ROOT = `${findTree().at}/`;
|
|
25
|
-
export const DEPTH = 'THREAD_DEPTH';
|
|
26
|
-
export const CEILING = 1;
|
|
27
|
-
export const SPAWN_TIMEOUT = 120_000;
|
|
28
|
-
export const SPAWN_BUFFER = 8 * 1024 * 1024;
|
|
29
|
-
export function nested() {
|
|
30
|
-
return Number(process.env[DEPTH] ?? '0') >= CEILING;
|
|
31
|
-
}
|
|
32
|
-
export function ran(command, options) {
|
|
33
|
-
if (nested())
|
|
34
|
-
return undefined;
|
|
35
|
-
const depth = Number(process.env[DEPTH] ?? '0');
|
|
36
|
-
const out = spawnSync(command, [...(options.args ?? [])], {
|
|
37
|
-
shell: options.args === undefined,
|
|
38
|
-
cwd: options.cwd,
|
|
39
|
-
encoding: 'utf8',
|
|
40
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
41
|
-
timeout: SPAWN_TIMEOUT,
|
|
42
|
-
killSignal: 'SIGKILL',
|
|
43
|
-
maxBuffer: SPAWN_BUFFER,
|
|
44
|
-
env: { ...process.env, [DEPTH]: String(depth + 1) },
|
|
45
|
-
});
|
|
46
|
-
return { status: out.status, said: `${String(out.stdout ?? '')}${String(out.stderr ?? '')}` };
|
|
47
|
-
}
|
|
48
26
|
export const reads = (one) => 'holds' in one;
|
|
49
27
|
export const visits = (one) => 'holds' in one && one.on !== undefined;
|
|
50
28
|
export const sweeps = (one) => 'holds' in one && one.on === undefined;
|
|
@@ -63,7 +41,10 @@ function wanted(fragment) {
|
|
|
63
41
|
const all = parts(fragment);
|
|
64
42
|
return all[0] === CANONICAL_TREE ? [TREE, ...all.slice(1)] : all;
|
|
65
43
|
}
|
|
66
|
-
|
|
44
|
+
function holding(want, path, from) {
|
|
45
|
+
return want.every((part, step) => part === path[from + step]);
|
|
46
|
+
}
|
|
47
|
+
export function region(fragment, path) {
|
|
67
48
|
if (fragment === '.')
|
|
68
49
|
return true;
|
|
69
50
|
const want = wanted(fragment);
|
|
@@ -71,17 +52,57 @@ export function names(fragment, path) {
|
|
|
71
52
|
return false;
|
|
72
53
|
if (!fragment.endsWith('/'))
|
|
73
54
|
return want.join('/') === path.join('/');
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
55
|
+
return want.length < path.length && holding(want, path, 0);
|
|
56
|
+
}
|
|
57
|
+
let written;
|
|
58
|
+
export function derivedHere() {
|
|
59
|
+
if (written !== undefined)
|
|
60
|
+
return written;
|
|
61
|
+
try {
|
|
62
|
+
const found = new Set();
|
|
63
|
+
for (const [at, threadings] of descend().threaded) {
|
|
64
|
+
if (threadings.some((one) => one.list === 'derives' && (one.row.by ?? one.row.runs) !== undefined))
|
|
65
|
+
found.add(at);
|
|
66
|
+
}
|
|
67
|
+
written = found;
|
|
68
|
+
return written;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return undefined;
|
|
77
72
|
}
|
|
78
|
-
|
|
73
|
+
}
|
|
74
|
+
const islands = new WeakMap();
|
|
75
|
+
function islandsHere() {
|
|
76
|
+
try {
|
|
77
|
+
const pass = descend();
|
|
78
|
+
const known = islands.get(pass);
|
|
79
|
+
if (known !== undefined)
|
|
80
|
+
return known;
|
|
81
|
+
const named = new Map(islandsDeclared().map((one) => [one.id, one.governs]));
|
|
82
|
+
islands.set(pass, named);
|
|
83
|
+
return named;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export function subject(rule) {
|
|
90
|
+
if (rule.governs === undefined)
|
|
91
|
+
return true;
|
|
92
|
+
const named = islandsHere();
|
|
93
|
+
return named === undefined || named.has(rule.governs);
|
|
79
94
|
}
|
|
80
95
|
export function governs(rule, filename) {
|
|
81
|
-
const
|
|
82
|
-
|
|
96
|
+
const under = filename.startsWith(ROOT) ? filename.slice(ROOT.length) : filename;
|
|
97
|
+
const path = parts(under);
|
|
98
|
+
if (rule.governs !== undefined) {
|
|
99
|
+
const body = islandsHere()?.get(rule.governs);
|
|
100
|
+
if (body !== undefined && reaches(body, under))
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
if (!rule.where.paths.some((fragment) => region(fragment, path)))
|
|
83
104
|
return false;
|
|
84
|
-
return
|
|
105
|
+
return derivedHere()?.has(under) !== true;
|
|
85
106
|
}
|
|
86
107
|
export class UnloadableSlopnatorError extends Error {
|
|
87
108
|
constructor(rule, at, because) {
|
|
@@ -105,7 +126,7 @@ export async function load(root, all) {
|
|
|
105
126
|
for (const rule of all) {
|
|
106
127
|
const name = slopnatorName(rule.id);
|
|
107
128
|
const at = homes(root)
|
|
108
|
-
.flatMap((dir) => [join(dir, `${name}.
|
|
129
|
+
.flatMap((dir) => [join(dir, `${name}.js`), join(dir, `${name}.ts`)])
|
|
109
130
|
.find((one) => existsSync(one));
|
|
110
131
|
if (at === undefined)
|
|
111
132
|
continue;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { existsSync, readFileSync, readdirSync, writeFileSync } from '../core/files.ts'
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, writeFileSync } from '../integrations/disk.ts'
|
|
3
2
|
import { dirname, join } from 'node:path'
|
|
4
3
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
5
4
|
|
|
5
|
+
import { descend } from '../core/descend.ts'
|
|
6
|
+
import { governs as reaches, islandsDeclared } from './slopnators/sl_unthreaded.ts'
|
|
6
7
|
import { invoked } from '../core/invoked.ts'
|
|
7
8
|
|
|
8
9
|
import { listBounds, quoted, withSeed } from '../core/rows.ts'
|
|
@@ -24,34 +25,6 @@ function homes(root: string): readonly string[] {
|
|
|
24
25
|
|
|
25
26
|
export const ROOT = `${findTree().at}/`
|
|
26
27
|
|
|
27
|
-
export const DEPTH = 'THREAD_DEPTH'
|
|
28
|
-
|
|
29
|
-
export const CEILING = 1
|
|
30
|
-
|
|
31
|
-
export const SPAWN_TIMEOUT = 120_000
|
|
32
|
-
|
|
33
|
-
export const SPAWN_BUFFER = 8 * 1024 * 1024
|
|
34
|
-
|
|
35
|
-
export function nested(): boolean {
|
|
36
|
-
return Number(process.env[DEPTH] ?? '0') >= CEILING
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function ran(command: string, options: { readonly cwd: string; readonly args?: readonly string[] }): { readonly status: number | null; readonly said: string } | undefined {
|
|
40
|
-
if (nested()) return undefined
|
|
41
|
-
const depth = Number(process.env[DEPTH] ?? '0')
|
|
42
|
-
const out = spawnSync(command, [...(options.args ?? [])], {
|
|
43
|
-
shell: options.args === undefined,
|
|
44
|
-
cwd: options.cwd,
|
|
45
|
-
encoding: 'utf8',
|
|
46
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
47
|
-
timeout: SPAWN_TIMEOUT,
|
|
48
|
-
killSignal: 'SIGKILL',
|
|
49
|
-
maxBuffer: SPAWN_BUFFER,
|
|
50
|
-
env: { ...process.env, [DEPTH]: String(depth + 1) },
|
|
51
|
-
})
|
|
52
|
-
return { status: out.status, said: `${String(out.stdout ?? '')}${String(out.stderr ?? '')}` }
|
|
53
|
-
}
|
|
54
|
-
|
|
55
28
|
export interface SlopnatorContext {
|
|
56
29
|
readonly filename: string
|
|
57
30
|
readonly text: string
|
|
@@ -119,21 +92,64 @@ function wanted(fragment: string): readonly string[] {
|
|
|
119
92
|
return all[0] === CANONICAL_TREE ? [TREE, ...all.slice(1)] : all
|
|
120
93
|
}
|
|
121
94
|
|
|
122
|
-
|
|
95
|
+
function holding(want: readonly string[], path: readonly string[], from: number): boolean {
|
|
96
|
+
return want.every((part, step) => part === path[from + step])
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function region(fragment: string, path: readonly string[]): boolean {
|
|
123
100
|
if (fragment === '.') return true
|
|
124
101
|
const want = wanted(fragment)
|
|
125
102
|
if (want.length === 0) return false
|
|
126
103
|
if (!fragment.endsWith('/')) return want.join('/') === path.join('/')
|
|
127
|
-
|
|
128
|
-
|
|
104
|
+
return want.length < path.length && holding(want, path, 0)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
let written: ReadonlySet<string> | undefined
|
|
108
|
+
|
|
109
|
+
export function derivedHere(): ReadonlySet<string> | undefined {
|
|
110
|
+
if (written !== undefined) return written
|
|
111
|
+
try {
|
|
112
|
+
const found = new Set<string>()
|
|
113
|
+
for (const [at, threadings] of descend().threaded) {
|
|
114
|
+
if (threadings.some((one) => one.list === 'derives' && (one.row.by ?? one.row.runs) !== undefined)) found.add(at)
|
|
115
|
+
}
|
|
116
|
+
written = found
|
|
117
|
+
return written
|
|
118
|
+
} catch {
|
|
119
|
+
return undefined
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const islands = new WeakMap<object, ReadonlyMap<string, readonly string[]>>()
|
|
124
|
+
|
|
125
|
+
function islandsHere(): ReadonlyMap<string, readonly string[]> | undefined {
|
|
126
|
+
try {
|
|
127
|
+
const pass = descend()
|
|
128
|
+
const known = islands.get(pass)
|
|
129
|
+
if (known !== undefined) return known
|
|
130
|
+
const named = new Map(islandsDeclared().map((one) => [one.id, one.governs]))
|
|
131
|
+
islands.set(pass, named)
|
|
132
|
+
return named
|
|
133
|
+
} catch {
|
|
134
|
+
return undefined
|
|
129
135
|
}
|
|
130
|
-
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function subject(rule: Constraint): boolean {
|
|
139
|
+
if (rule.governs === undefined) return true
|
|
140
|
+
const named = islandsHere()
|
|
141
|
+
return named === undefined || named.has(rule.governs)
|
|
131
142
|
}
|
|
132
143
|
|
|
133
144
|
export function governs(rule: Constraint, filename: string): boolean {
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
145
|
+
const under = filename.startsWith(ROOT) ? filename.slice(ROOT.length) : filename
|
|
146
|
+
const path = parts(under)
|
|
147
|
+
if (rule.governs !== undefined) {
|
|
148
|
+
const body = islandsHere()?.get(rule.governs)
|
|
149
|
+
if (body !== undefined && reaches(body, under)) return false
|
|
150
|
+
}
|
|
151
|
+
if (!rule.where.paths.some((fragment) => region(fragment, path))) return false
|
|
152
|
+
return derivedHere()?.has(under) !== true
|
|
137
153
|
}
|
|
138
154
|
|
|
139
155
|
export class UnloadableSlopnatorError extends Error {
|
|
@@ -164,7 +180,7 @@ export async function load(root: string, all: readonly Constraint[]): Promise<Re
|
|
|
164
180
|
for (const rule of all) {
|
|
165
181
|
const name = slopnatorName(rule.id)
|
|
166
182
|
const at = homes(root)
|
|
167
|
-
.flatMap((dir) => [join(dir, `${name}.
|
|
183
|
+
.flatMap((dir) => [join(dir, `${name}.js`), join(dir, `${name}.ts`)])
|
|
168
184
|
.find((one) => existsSync(one))
|
|
169
185
|
if (at === undefined) continue
|
|
170
186
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { here, names, threaded, unreadable } from
|
|
2
|
-
import { findTree } from
|
|
1
|
+
import { here, names, threaded, unreadable } from './sl_unthreaded.js';
|
|
2
|
+
import { findTree } from '../../core/tree.js';
|
|
3
3
|
const THREAD_AT = `${findTree().name}/thread.ts`;
|
|
4
4
|
export const slopnator = {
|
|
5
5
|
holds: (_node, at) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { filesGoverned, here, islandsDeclared } from
|
|
1
|
+
import { filesGoverned, here, islandsDeclared } from './sl_unthreaded.js';
|
|
2
2
|
const sentence = (describes) => `${describes.split(/ — |\. /)[0] ?? describes}.`;
|
|
3
3
|
export const slopnator = {
|
|
4
4
|
holds: (_node, at) => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { readFileSync } from
|
|
1
|
+
import { readFileSync } from '../../integrations/disk.js';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
|
-
import { atsIn } from
|
|
4
|
-
import { reached } from
|
|
5
|
-
import { findTree } from
|
|
3
|
+
import { atsIn } from './sl_unthreaded.js';
|
|
4
|
+
import { reached } from '../../core/descend.js';
|
|
5
|
+
import { findTree } from '../../core/tree.js';
|
|
6
6
|
const ROOT = `${findTree().at}/`;
|
|
7
7
|
export function derivations(root) {
|
|
8
8
|
const found = [];
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import ts from 'typescript';
|
|
3
|
+
import { ROOT, configured, hosting } from '../../core/descend.js';
|
|
4
|
+
import { kind, readFileSync } from '../../integrations/disk.js';
|
|
5
|
+
import { OPENS } from '../../integrations/target.js';
|
|
6
|
+
import { here } from './sl_unthreaded.js';
|
|
7
|
+
const IMPORTED = 'import ';
|
|
8
|
+
const MADE = 'new ';
|
|
9
|
+
const RUNTIME = 'node:';
|
|
10
|
+
const ANYWHERE = 'globalThis';
|
|
11
|
+
const REQUIRED = 'require';
|
|
12
|
+
const DECLARED = /\.d\.([cm]?)ts$/;
|
|
13
|
+
const READABLE = /\.(?:[cm]?[jt]s|[jt]sx)$/;
|
|
14
|
+
const plain = (specifier) => (specifier.startsWith(RUNTIME) ? specifier.slice(RUNTIME.length) : specifier);
|
|
15
|
+
function doors() {
|
|
16
|
+
const modules = new Map();
|
|
17
|
+
const globals = new Map();
|
|
18
|
+
const properties = new Map();
|
|
19
|
+
for (const [reach, spellings] of Object.entries(OPENS)) {
|
|
20
|
+
for (const spelling of spellings) {
|
|
21
|
+
const door = { reach, spelling };
|
|
22
|
+
if (spelling.startsWith(IMPORTED)) {
|
|
23
|
+
const rest = spelling.slice(IMPORTED.length);
|
|
24
|
+
const dot = rest.lastIndexOf('.');
|
|
25
|
+
modules.set(plain(dot === -1 || rest.slice(dot).includes('/') ? rest : rest.slice(0, dot)), door);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (spelling.startsWith(MADE)) {
|
|
29
|
+
globals.set(spelling.slice(MADE.length), door);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (spelling.includes('.'))
|
|
33
|
+
properties.set(spelling, door);
|
|
34
|
+
else
|
|
35
|
+
globals.set(spelling, door);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return { modules, globals, properties };
|
|
39
|
+
}
|
|
40
|
+
const DOORS = doors();
|
|
41
|
+
const files = new Map();
|
|
42
|
+
function parsed(at, text) {
|
|
43
|
+
const held = files.get(text);
|
|
44
|
+
if (held !== undefined)
|
|
45
|
+
return held;
|
|
46
|
+
const file = ts.createSourceFile(at, text, ts.ScriptTarget.Latest, true, at.endsWith('x') ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
|
|
47
|
+
files.set(text, file);
|
|
48
|
+
return file;
|
|
49
|
+
}
|
|
50
|
+
function brought(file) {
|
|
51
|
+
const found = [];
|
|
52
|
+
const line = (node) => file.getLineAndCharacterOfPosition(node.getStart(file)).line + 1;
|
|
53
|
+
const visit = (node) => {
|
|
54
|
+
if (ts.isImportDeclaration(node) && node.importClause?.isTypeOnly !== true && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
55
|
+
found.push({ specifier: node.moduleSpecifier.text, line: line(node) });
|
|
56
|
+
}
|
|
57
|
+
if (ts.isExportDeclaration(node) && !node.isTypeOnly && node.moduleSpecifier !== undefined && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
58
|
+
found.push({ specifier: node.moduleSpecifier.text, line: line(node) });
|
|
59
|
+
}
|
|
60
|
+
if (ts.isCallExpression(node)) {
|
|
61
|
+
const first = node.arguments[0];
|
|
62
|
+
const loads = node.expression.kind === ts.SyntaxKind.ImportKeyword || (ts.isIdentifier(node.expression) && node.expression.text === REQUIRED);
|
|
63
|
+
if (loads && first !== undefined && ts.isStringLiteral(first))
|
|
64
|
+
found.push({ specifier: first.text, line: line(node) });
|
|
65
|
+
}
|
|
66
|
+
ts.forEachChild(node, visit);
|
|
67
|
+
};
|
|
68
|
+
visit(file);
|
|
69
|
+
return found;
|
|
70
|
+
}
|
|
71
|
+
const binds = (node) => {
|
|
72
|
+
const parent = node.parent;
|
|
73
|
+
return ((ts.isVariableDeclaration(parent) ||
|
|
74
|
+
ts.isParameter(parent) ||
|
|
75
|
+
ts.isBindingElement(parent) ||
|
|
76
|
+
ts.isFunctionDeclaration(parent) ||
|
|
77
|
+
ts.isClassDeclaration(parent) ||
|
|
78
|
+
ts.isImportSpecifier(parent) ||
|
|
79
|
+
ts.isImportClause(parent) ||
|
|
80
|
+
ts.isNamespaceImport(parent)) &&
|
|
81
|
+
parent.name === node);
|
|
82
|
+
};
|
|
83
|
+
const named = (node) => node.parent?.name === node;
|
|
84
|
+
const opened = new Map();
|
|
85
|
+
function opening(at, text) {
|
|
86
|
+
if (opened.has(text))
|
|
87
|
+
return opened.get(text);
|
|
88
|
+
const file = parsed(at, text);
|
|
89
|
+
let found;
|
|
90
|
+
for (const one of brought(file))
|
|
91
|
+
found ??= DOORS.modules.get(plain(one.specifier));
|
|
92
|
+
const bound = new Set();
|
|
93
|
+
const collect = (node) => {
|
|
94
|
+
if (ts.isIdentifier(node) && binds(node))
|
|
95
|
+
bound.add(node.text);
|
|
96
|
+
ts.forEachChild(node, collect);
|
|
97
|
+
};
|
|
98
|
+
collect(file);
|
|
99
|
+
const visit = (node) => {
|
|
100
|
+
if (found !== undefined)
|
|
101
|
+
return;
|
|
102
|
+
if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) && !ts.isPartOfTypeNode(node)) {
|
|
103
|
+
const object = node.expression.text;
|
|
104
|
+
found = DOORS.properties.get(object + '.' + node.name.text) ?? (object === ANYWHERE ? DOORS.globals.get(node.name.text) : undefined);
|
|
105
|
+
}
|
|
106
|
+
if (found === undefined && ts.isIdentifier(node) && !named(node) && !ts.isPartOfTypeNode(node) && !bound.has(node.text)) {
|
|
107
|
+
found = DOORS.globals.get(node.text);
|
|
108
|
+
}
|
|
109
|
+
ts.forEachChild(node, visit);
|
|
110
|
+
};
|
|
111
|
+
visit(file);
|
|
112
|
+
opened.set(text, found);
|
|
113
|
+
return found;
|
|
114
|
+
}
|
|
115
|
+
let options;
|
|
116
|
+
let host;
|
|
117
|
+
function resolvedOf(specifier, from) {
|
|
118
|
+
options ??= configured().options;
|
|
119
|
+
host ??= hosting(options);
|
|
120
|
+
const found = ts.resolveModuleName(specifier, from, options, host).resolvedModule;
|
|
121
|
+
if (found === undefined)
|
|
122
|
+
return undefined;
|
|
123
|
+
const at = found.resolvedFileName;
|
|
124
|
+
if (!DECLARED.test(at))
|
|
125
|
+
return at;
|
|
126
|
+
const emitted = at.replace(DECLARED, '.$1js');
|
|
127
|
+
return kind(emitted) === 'file' ? emitted : undefined;
|
|
128
|
+
}
|
|
129
|
+
const readable = (at) => (READABLE.test(at) && kind(at) === 'file' ? readFileSync(at, 'utf8') : undefined);
|
|
130
|
+
const shown = (chain, door) => chain.map((one) => '`' + one + '`').join(', which imports ') +
|
|
131
|
+
(door.spelling.startsWith(IMPORTED) ? ', which imports ' + door.spelling.slice(IMPORTED.length) : ', which reaches ' + door.spelling) +
|
|
132
|
+
' — the ' +
|
|
133
|
+
door.reach +
|
|
134
|
+
' reach, and no target declares it. Nothing prices that reach, replays it in a trial or refuses it. Declare the place with `thread create target`, require it on the operation, and call what the node is handed instead';
|
|
135
|
+
function through(at, chain, seen) {
|
|
136
|
+
const text = readable(at);
|
|
137
|
+
if (text === undefined)
|
|
138
|
+
return undefined;
|
|
139
|
+
const door = opening(at, text);
|
|
140
|
+
if (door !== undefined)
|
|
141
|
+
return shown(chain, door);
|
|
142
|
+
for (const one of brought(parsed(at, text))) {
|
|
143
|
+
const next = resolvedOf(one.specifier, at);
|
|
144
|
+
if (next === undefined || seen.has(next))
|
|
145
|
+
continue;
|
|
146
|
+
seen.add(next);
|
|
147
|
+
const found = through(next, [...chain, one.specifier], seen);
|
|
148
|
+
if (found !== undefined)
|
|
149
|
+
return found;
|
|
150
|
+
}
|
|
151
|
+
return undefined;
|
|
152
|
+
}
|
|
153
|
+
export const slopnator = {
|
|
154
|
+
holds: (_node, at) => {
|
|
155
|
+
const path = here(at.filename);
|
|
156
|
+
if (!READABLE.test(path))
|
|
157
|
+
return false;
|
|
158
|
+
const from = resolve(ROOT, path);
|
|
159
|
+
const seen = new Set([from]);
|
|
160
|
+
for (const one of brought(parsed(from, at.text))) {
|
|
161
|
+
const next = resolvedOf(one.specifier, from);
|
|
162
|
+
if (next === undefined || seen.has(next))
|
|
163
|
+
continue;
|
|
164
|
+
seen.add(next);
|
|
165
|
+
const found = through(next, [one.specifier], seen);
|
|
166
|
+
if (found !== undefined)
|
|
167
|
+
return 'line ' + String(one.line) + ': imports ' + found;
|
|
168
|
+
}
|
|
169
|
+
return false;
|
|
170
|
+
},
|
|
171
|
+
proves: {
|
|
172
|
+
wrong: [
|
|
173
|
+
{
|
|
174
|
+
files: [
|
|
175
|
+
{ at: 'thread/integrations/cli.ts', source: "import { spawn } from 'node:child_process'\n\nexport const starts = (program: string): void => {\n spawn(program)\n}\n" },
|
|
176
|
+
{ at: 'operations/_probe_node.ts', source: "export { starts } from '../thread/integrations/cli.ts'\n" },
|
|
177
|
+
],
|
|
178
|
+
at: 'operations/_probe_node.ts',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
files: [
|
|
182
|
+
{ at: 'thread/integrations/https.ts', source: "export const sendingHttp = async (address: string): Promise<number> => (await fetch(address)).status\n" },
|
|
183
|
+
{ at: 'src/_probe_helper.ts', source: "import { sendingHttp } from '../thread/integrations/https.ts'\n\nexport const status = (address: string): Promise<number> => sendingHttp(address)\n" },
|
|
184
|
+
{ at: 'operations/_probe_node.ts', source: "import { status } from '../src/_probe_helper.ts'\n\nexport const node = (address: string): Promise<number> => status(address)\n" },
|
|
185
|
+
],
|
|
186
|
+
at: 'operations/_probe_node.ts',
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
files: [
|
|
190
|
+
{ at: 'thread/integrations/disk.ts', source: "import * as disk from 'node:fs'\n\nexport const read = (at: string): string => disk.readFileSync(at, 'utf8')\n" },
|
|
191
|
+
{ at: 'operations/_probe_node.ts', source: "export const node = async (at: string): Promise<string> => (await import('../thread/integrations/disk.ts')).read(at)\n" },
|
|
192
|
+
],
|
|
193
|
+
at: 'operations/_probe_node.ts',
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
right: [
|
|
197
|
+
{
|
|
198
|
+
files: [
|
|
199
|
+
{ at: 'thread/operations/nodes.ts', source: "export const nd_action = <T>(run: T): T => run\n" },
|
|
200
|
+
{ at: 'operations/_probe_node.ts', source: "import { nd_action } from '../thread/operations/nodes.ts'\n\nexport const node = nd_action(async () => 1)\n" },
|
|
201
|
+
],
|
|
202
|
+
at: 'operations/_probe_node.ts',
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
files: [
|
|
206
|
+
{ at: 'thread/integrations/cli.ts', source: "import { spawn } from 'node:child_process'\n\nexport interface Ran {\n readonly out: string\n}\n\nexport const starts = (program: string): void => {\n spawn(program)\n}\n" },
|
|
207
|
+
{ at: 'operations/_probe_node.ts', source: "import type { Ran } from '../thread/integrations/cli.ts'\n\nexport const node = (ran: Ran): string => ran.out\n" },
|
|
208
|
+
],
|
|
209
|
+
at: 'operations/_probe_node.ts',
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
files: [
|
|
213
|
+
{ at: 'src/_probe_helper.ts', source: "const fetch = (said: string): string => said\n\nexport const shout = (said: string): string => fetch(said).toUpperCase()\n" },
|
|
214
|
+
{ at: 'operations/_probe_node.ts', source: "import { shout } from '../src/_probe_helper.ts'\n\nexport const node = (): string => shout('a')\n" },
|
|
215
|
+
],
|
|
216
|
+
at: 'operations/_probe_node.ts',
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
},
|
|
220
|
+
};
|