@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,9 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { basename, dirname, join, resolve } from 'node:path'
|
|
4
|
-
import { pathToFileURL } from 'node:url'
|
|
5
|
-
|
|
6
|
-
import { exit, invoked } from '../../core/invoked.ts'
|
|
1
|
+
import { answeredBy, standing } from '../../integrations/disk.ts'
|
|
2
|
+
import { resolve } from 'node:path'
|
|
7
3
|
|
|
8
4
|
import type { Linter as LinterType, Rule } from 'eslint'
|
|
9
5
|
import { Linter } from 'eslint'
|
|
@@ -11,12 +7,9 @@ import { Linter } from 'eslint'
|
|
|
11
7
|
import type { Constraint, Proof, Sourced } from '../constraint.ts'
|
|
12
8
|
|
|
13
9
|
const TREE = findTree()
|
|
14
|
-
import {
|
|
15
|
-
import { NOT_WRITTEN, ROOT, governs, load, proofsOf, reads, rules, slopnatorName, sweeps, write, type Byproduct, type Slopnator } from '../slopnator.ts'
|
|
10
|
+
import { NOT_WRITTEN, ROOT, governs, proofsOf, reads, slopnatorName, sweeps, visits, type Slopnator } from '../slopnator.ts'
|
|
16
11
|
import { forget } from '../slopnators/sl_unthreaded.ts'
|
|
17
|
-
import { findTree
|
|
18
|
-
|
|
19
|
-
export const TRIALS_PATH = `${findTree().name}/_generated/trials.ts`
|
|
12
|
+
import { findTree } from '../../core/tree.ts'
|
|
20
13
|
|
|
21
14
|
const PROBE = 'probe.tsx'
|
|
22
15
|
|
|
@@ -59,6 +52,7 @@ export interface Run {
|
|
|
59
52
|
readonly passed: number
|
|
60
53
|
readonly failed: number
|
|
61
54
|
readonly measured: number
|
|
55
|
+
readonly spent: ReadonlyMap<string, number>
|
|
62
56
|
}
|
|
63
57
|
|
|
64
58
|
const canonical = (at: string): string => at.replace(/^threads\//, `${TREE.name}/`)
|
|
@@ -112,14 +106,6 @@ export function deriveTrials(all: readonly Constraint[], slopnators: ReadonlyMap
|
|
|
112
106
|
return { trials: trials.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)) }
|
|
113
107
|
}
|
|
114
108
|
|
|
115
|
-
export function trialsByproduct(derivation: Derivation): Byproduct {
|
|
116
|
-
return {
|
|
117
|
-
path: TRIALS_PATH,
|
|
118
|
-
content: `export const RULE_TRIALS = ${JSON.stringify(derivation.trials, null, 2)} as const
|
|
119
|
-
`,
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
109
|
function config(rule: Constraint, module: Rule.RuleModule, parser: unknown): Parameters<LinterType['verify']>[1] {
|
|
124
110
|
return [
|
|
125
111
|
{
|
|
@@ -134,90 +120,6 @@ function config(rule: Constraint, module: Rule.RuleModule, parser: unknown): Par
|
|
|
134
120
|
] as unknown as Parameters<LinterType['verify']>[1]
|
|
135
121
|
}
|
|
136
122
|
|
|
137
|
-
const flat = (at: string): string => (at.length > 1 && at.endsWith('/') ? at.replace(/\/+$/, '') : at)
|
|
138
|
-
|
|
139
|
-
const under = (at: string): boolean => at.startsWith(ROOT) || `${at}/` === ROOT
|
|
140
|
-
|
|
141
|
-
const own = (at: string): boolean => under(at) && !at.slice(ROOT.length).split('/').includes('node_modules')
|
|
142
|
-
|
|
143
|
-
function beside(at: string): readonly disk.Dirent[] {
|
|
144
|
-
try {
|
|
145
|
-
return disk.readdirSync(at, { withFileTypes: true })
|
|
146
|
-
} catch {
|
|
147
|
-
return []
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function outside(at: string): Kind {
|
|
152
|
-
const one = disk.statSync(at, { throwIfNoEntry: false })
|
|
153
|
-
if (one === undefined) return 'none'
|
|
154
|
-
return one.isFile() ? 'file' : one.isDirectory() ? 'folder' : 'other'
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const GONE = 'is not in the scenario this trial stands, and while it runs the scenario is the whole tree.'
|
|
158
|
-
|
|
159
|
-
function answering(files: readonly Sourced[]): Answering {
|
|
160
|
-
const held = new Map<string, string>(files.map((one) => [resolve(ROOT, one.at), one.source]))
|
|
161
|
-
const folders = new Set<string>()
|
|
162
|
-
const parents = (at: string): void => {
|
|
163
|
-
for (let up = dirname(at); under(`${up}/`); up = dirname(up)) folders.add(up)
|
|
164
|
-
}
|
|
165
|
-
for (const at of held.keys()) parents(at)
|
|
166
|
-
|
|
167
|
-
const answers: Answering = {
|
|
168
|
-
kind: (at) => (held.has(at) ? 'file' : folders.has(at) ? 'folder' : own(at) ? 'none' : outside(at)),
|
|
169
|
-
read: (at) => {
|
|
170
|
-
const said = held.get(at)
|
|
171
|
-
if (said !== undefined) return said
|
|
172
|
-
if (own(at)) throw new Error(`${at} ${GONE}`)
|
|
173
|
-
return disk.readFileSync(at, 'utf8')
|
|
174
|
-
},
|
|
175
|
-
write: (at, said) => {
|
|
176
|
-
held.set(at, said)
|
|
177
|
-
parents(at)
|
|
178
|
-
},
|
|
179
|
-
list: (at) => {
|
|
180
|
-
const inside = new Map<string, Listed>()
|
|
181
|
-
const found = own(at) ? [] : folders.has(at) ? beside(at) : disk.readdirSync(at, { withFileTypes: true })
|
|
182
|
-
for (const one of found) inside.set(one.name, { name: one.name, kind: one.isDirectory() ? 'folder' : 'file' })
|
|
183
|
-
for (const path of folders) if (dirname(path) === at) inside.set(basename(path), { name: basename(path), kind: 'folder' })
|
|
184
|
-
for (const path of held.keys()) if (dirname(path) === at) inside.set(basename(path), { name: basename(path), kind: 'file' })
|
|
185
|
-
return [...inside.values()]
|
|
186
|
-
},
|
|
187
|
-
stat: (at) => {
|
|
188
|
-
const said = held.get(at)
|
|
189
|
-
if (said !== undefined) return { size: said.length, modified: 0 }
|
|
190
|
-
if (folders.has(at)) return { size: 0, modified: 0 }
|
|
191
|
-
if (own(at)) throw new Error(`${at} ${GONE}`)
|
|
192
|
-
const one = disk.statSync(at)
|
|
193
|
-
return { size: one.size, modified: one.mtimeMs }
|
|
194
|
-
},
|
|
195
|
-
remove: (at) => {
|
|
196
|
-
held.delete(at)
|
|
197
|
-
folders.delete(at)
|
|
198
|
-
},
|
|
199
|
-
real: (at) => (own(at) || held.has(at) || folders.has(at) ? at : disk.realpathSync(at)),
|
|
200
|
-
fetch: () => {
|
|
201
|
-
throw new Error('a trial answers orders against a tree it made up, so there is nowhere here to install anything into.')
|
|
202
|
-
},
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return {
|
|
206
|
-
kind: (at) => answers.kind(flat(at)),
|
|
207
|
-
read: (at) => answers.read(flat(at)),
|
|
208
|
-
write: (at, said) => {
|
|
209
|
-
answers.write(flat(at), said)
|
|
210
|
-
},
|
|
211
|
-
list: (at) => answers.list(flat(at)),
|
|
212
|
-
stat: (at) => answers.stat(flat(at)),
|
|
213
|
-
remove: (at) => {
|
|
214
|
-
answers.remove(flat(at))
|
|
215
|
-
},
|
|
216
|
-
real: (at) => answers.real(flat(at)),
|
|
217
|
-
fetch: (at) => answers.fetch(flat(at)),
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
123
|
export function runTrial(trial: Trial, rule: Constraint, module: Rule.RuleModule, parser: unknown, slopnator?: Slopnator): Outcome {
|
|
222
124
|
const linter = new Linter()
|
|
223
125
|
const failures: string[] = []
|
|
@@ -237,7 +139,7 @@ export function runTrial(trial: Trial, rule: Constraint, module: Rule.RuleModule
|
|
|
237
139
|
let parsed = false
|
|
238
140
|
let satisfied = false
|
|
239
141
|
|
|
240
|
-
answeredBy(
|
|
142
|
+
answeredBy(standing(ROOT, new Map<string, string>(trial.scenario.files.map((one) => [resolve(ROOT, one.at), one.source]))))
|
|
241
143
|
forget()
|
|
242
144
|
|
|
243
145
|
try {
|
|
@@ -287,6 +189,138 @@ export function runTrial(trial: Trial, rule: Constraint, module: Rule.RuleModule
|
|
|
287
189
|
return { id: trial.id, rule: rule.id, passed: failures.length === 0, parsed, failures }
|
|
288
190
|
}
|
|
289
191
|
|
|
192
|
+
const judged = (who: readonly Constraint[], rules: Readonly<Record<string, Rule.RuleModule>>, parser: unknown): Parameters<LinterType['verify']>[1] =>
|
|
193
|
+
[
|
|
194
|
+
{
|
|
195
|
+
files: ['**/*.ts', '**/*.tsx'],
|
|
196
|
+
languageOptions: {
|
|
197
|
+
parser,
|
|
198
|
+
parserOptions: { ecmaVersion: 'latest', sourceType: 'module', ecmaFeatures: { jsx: true } },
|
|
199
|
+
},
|
|
200
|
+
plugins: { rule: { rules: Object.fromEntries(who.map((one) => [one.id, rules[one.id] as Rule.RuleModule])) } },
|
|
201
|
+
rules: Object.fromEntries(who.map((one) => ['rule/' + one.id, 'error'])),
|
|
202
|
+
},
|
|
203
|
+
] as unknown as Parameters<LinterType['verify']>[1]
|
|
204
|
+
|
|
205
|
+
const failed = (thrown: unknown): string => 'could not run on it: ' + (thrown instanceof Error ? thrown.message : String(thrown))
|
|
206
|
+
|
|
207
|
+
const parseable = (source: string, at: string, parser: unknown): ((said: string) => string) =>
|
|
208
|
+
WRAPPINGS.find((wrap) => !new Linter().verify(wrap(source), judged([], {}, parser), at).some((one) => one.fatal === true)) ??
|
|
209
|
+
((said: string): string => said)
|
|
210
|
+
|
|
211
|
+
function refusals(
|
|
212
|
+
scenario: Scenario,
|
|
213
|
+
source: string,
|
|
214
|
+
judges: readonly Constraint[],
|
|
215
|
+
rules: Readonly<Record<string, Rule.RuleModule>>,
|
|
216
|
+
parser: unknown,
|
|
217
|
+
slopnators: ReadonlyMap<string, Slopnator>,
|
|
218
|
+
): ReadonlyMap<string, ReadonlySet<string>> {
|
|
219
|
+
const found = new Map<string, Set<string>>()
|
|
220
|
+
const note = (who: string, said: string): void => {
|
|
221
|
+
const held = found.get(who) ?? new Set<string>()
|
|
222
|
+
held.add(said)
|
|
223
|
+
found.set(who, held)
|
|
224
|
+
}
|
|
225
|
+
const walking = judges.filter((one) => {
|
|
226
|
+
const held = slopnators.get(slopnatorName(one.id))
|
|
227
|
+
return held !== undefined && visits(held) && rules[one.id] !== undefined
|
|
228
|
+
})
|
|
229
|
+
const linted = (who: readonly Constraint[]): void => {
|
|
230
|
+
const messages = new Linter().verify(source, judged(who, rules, parser), scenario.at)
|
|
231
|
+
if (messages.some((one) => one.fatal === true)) return
|
|
232
|
+
for (const one of messages) {
|
|
233
|
+
const by = String(one.ruleId ?? '').replace('rule/', '')
|
|
234
|
+
if (by !== '') note(by, one.message)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const files = scenario.files.map((one) => (one.at === scenario.at ? { at: one.at, source } : one))
|
|
239
|
+
answeredBy(standing(ROOT, new Map<string, string>(files.map((one) => [resolve(ROOT, one.at), one.source]))))
|
|
240
|
+
forget()
|
|
241
|
+
try {
|
|
242
|
+
try {
|
|
243
|
+
linted(walking)
|
|
244
|
+
} catch {
|
|
245
|
+
for (const one of walking) {
|
|
246
|
+
try {
|
|
247
|
+
linted([one])
|
|
248
|
+
} catch (thrown) {
|
|
249
|
+
note(one.id, failed(thrown))
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
for (const one of judges) {
|
|
254
|
+
const held = slopnators.get(slopnatorName(one.id))
|
|
255
|
+
if (held === undefined) continue
|
|
256
|
+
if (visits(held)) continue
|
|
257
|
+
try {
|
|
258
|
+
if (sweeps(held)) {
|
|
259
|
+
const said = held.holds(undefined, { filename: scenario.at, text: source, ancestors: () => [], comments: () => [] })
|
|
260
|
+
if (said !== false && said !== NOT_WRITTEN) note(one.id, typeof said === 'string' ? said : slopnatorName(one.id))
|
|
261
|
+
continue
|
|
262
|
+
}
|
|
263
|
+
if (!reads(held)) for (const said of held.checks(ROOT)) note(one.id, said)
|
|
264
|
+
} catch (thrown) {
|
|
265
|
+
note(one.id, failed(thrown))
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
} finally {
|
|
269
|
+
answeredBy(undefined)
|
|
270
|
+
forget()
|
|
271
|
+
}
|
|
272
|
+
return found
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export function crossed(
|
|
276
|
+
trials: readonly Trial[],
|
|
277
|
+
all: readonly Constraint[],
|
|
278
|
+
rules: Readonly<Record<string, Rule.RuleModule>>,
|
|
279
|
+
parser: unknown,
|
|
280
|
+
slopnators: ReadonlyMap<string, Slopnator> = new Map<string, Slopnator>(),
|
|
281
|
+
spent: Map<string, number> = new Map<string, number>(),
|
|
282
|
+
): readonly Outcome[] {
|
|
283
|
+
const found: Outcome[] = []
|
|
284
|
+
const blanks = new Map<string, ReadonlyMap<string, ReadonlySet<string>>>()
|
|
285
|
+
|
|
286
|
+
for (const trial of trials) {
|
|
287
|
+
if (trial.verdict.reports) continue
|
|
288
|
+
const target = trial.scenario.files.find((one) => one.at === trial.scenario.at)
|
|
289
|
+
if (target === undefined) continue
|
|
290
|
+
|
|
291
|
+
const judges = all.filter((one) => governs(one, trial.scenario.at))
|
|
292
|
+
if (!judges.some((one) => one.id !== trial.rule)) continue
|
|
293
|
+
const began = Date.now()
|
|
294
|
+
|
|
295
|
+
const wrap = parseable(target.source, trial.scenario.at, parser)
|
|
296
|
+
const emptied = JSON.stringify([wrap(''), trial.scenario.files.map((one) => (one.at === trial.scenario.at ? { at: one.at, source: '' } : one))])
|
|
297
|
+
const blank = blanks.get(emptied) ?? refusals(trial.scenario, wrap(''), judges, rules, parser, slopnators)
|
|
298
|
+
blanks.set(emptied, blank)
|
|
299
|
+
const said = refusals(trial.scenario, wrap(target.source), judges, rules, parser, slopnators)
|
|
300
|
+
|
|
301
|
+
spent.set(trial.rule, (spent.get(trial.rule) ?? 0) + Date.now() - began)
|
|
302
|
+
|
|
303
|
+
for (const [who, messages] of said) {
|
|
304
|
+
if (who === trial.rule) continue
|
|
305
|
+
for (const message of messages) {
|
|
306
|
+
if (blank.get(who)?.has(message) === true) continue
|
|
307
|
+
found.push({
|
|
308
|
+
id: trial.id + '_under_' + who.replace(/-/g, '_'),
|
|
309
|
+
rule: trial.rule,
|
|
310
|
+
passed: false,
|
|
311
|
+
parsed: true,
|
|
312
|
+
failures: [
|
|
313
|
+
'the form it recommends is refused by ' + who + ', so this law tells somebody to write what another law bans. ' +
|
|
314
|
+
who + ' said: ' + (message.split('Found: ').pop() ?? message),
|
|
315
|
+
],
|
|
316
|
+
})
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return found
|
|
322
|
+
}
|
|
323
|
+
|
|
290
324
|
export function runTrials(
|
|
291
325
|
trials: readonly Trial[],
|
|
292
326
|
all: readonly Constraint[],
|
|
@@ -295,6 +329,7 @@ export function runTrials(
|
|
|
295
329
|
slopnators?: ReadonlyMap<string, Slopnator>,
|
|
296
330
|
): Run {
|
|
297
331
|
const byName = new Map(all.map((rule) => [rule.id, rule]))
|
|
332
|
+
const spent = new Map<string, number>()
|
|
298
333
|
const outcomes = trials.map((trial): Outcome => {
|
|
299
334
|
const rule = byName.get(trial.rule)
|
|
300
335
|
const module = rules[trial.rule]
|
|
@@ -304,10 +339,13 @@ export function runTrials(
|
|
|
304
339
|
rule: trial.rule,
|
|
305
340
|
passed: false,
|
|
306
341
|
parsed: false,
|
|
307
|
-
failures: [`
|
|
342
|
+
failures: [`the rule "${trial.rule}" has no slopnator on disk, so this trial is about nothing — the file to write is the one its row names in \`at\``],
|
|
308
343
|
}
|
|
309
344
|
}
|
|
310
|
-
|
|
345
|
+
const began = Date.now()
|
|
346
|
+
const outcome = runTrial(trial, rule, module, parser, slopnators?.get(slopnatorName(rule.id)))
|
|
347
|
+
spent.set(trial.rule, (spent.get(trial.rule) ?? 0) + Date.now() - began)
|
|
348
|
+
return outcome
|
|
311
349
|
})
|
|
312
350
|
|
|
313
351
|
return {
|
|
@@ -315,69 +353,7 @@ export function runTrials(
|
|
|
315
353
|
passed: outcomes.filter((outcome) => outcome.passed).length,
|
|
316
354
|
failed: outcomes.filter((outcome) => !outcome.passed).length,
|
|
317
355
|
measured: outcomes.filter((outcome) => outcome.parsed).length,
|
|
356
|
+
spent,
|
|
318
357
|
}
|
|
319
358
|
}
|
|
320
359
|
|
|
321
|
-
if (invoked(import.meta.url)) {
|
|
322
|
-
const own = await rules()
|
|
323
|
-
const governing = own ?? CONSTRAINTS
|
|
324
|
-
const source =
|
|
325
|
-
own === undefined
|
|
326
|
-
? `the ${String(CONSTRAINTS.length)} constraint(s) this tree authors`
|
|
327
|
-
: `the ${String(own.length)} rule(s) this tree declares — a shipped constraint is proved in the package that ships it, against the paths that package governs`
|
|
328
|
-
const slopnators = await load(ROOT, governing)
|
|
329
|
-
const derivation = deriveTrials(governing, slopnators)
|
|
330
|
-
const byproduct = trialsByproduct(derivation)
|
|
331
|
-
|
|
332
|
-
if (process.argv.includes('--check')) {
|
|
333
|
-
const path = join(ROOT, byproduct.path)
|
|
334
|
-
const current = existsSync(path) ? readFileSync(path, 'utf8') : ''
|
|
335
|
-
const drifted = current !== byproduct.content
|
|
336
|
-
if (drifted) console.error(`trial: ${byproduct.path} is not what the rules derive. Run \`thread trials\` and commit the result.`)
|
|
337
|
-
console.log(`trial: ${String(derivation.trials.length)} derived from ${source}, ${String(drifted ? 1 : 0)} findings.`)
|
|
338
|
-
exit(drifted ? 1 : 0)
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
if (process.argv.includes('--try')) {
|
|
342
|
-
const at = process.argv.indexOf('--rule')
|
|
343
|
-
const only = at === -1 ? undefined : (process.argv[at + 1] ?? '').split(',').map((one) => one.trim()).filter(Boolean)
|
|
344
|
-
const unknown = (only ?? []).filter((id) => !governing.some((rule) => rule.id === id))
|
|
345
|
-
if (unknown.length > 0) {
|
|
346
|
-
console.error(`trial: no rule is called ${unknown.join(', ')} — a filter naming nothing would measure nothing and exit 0`)
|
|
347
|
-
exit(1)
|
|
348
|
-
}
|
|
349
|
-
const chosen = only === undefined ? derivation.trials : derivation.trials.filter((trial) => only.includes(trial.rule))
|
|
350
|
-
if (chosen.length === 0) {
|
|
351
|
-
if (only !== undefined) {
|
|
352
|
-
console.error('trial: the filter selected no trials, and measuring nothing must not exit 0')
|
|
353
|
-
exit(1)
|
|
354
|
-
}
|
|
355
|
-
if (governing.length > 0) {
|
|
356
|
-
console.error(
|
|
357
|
-
`trial: ${String(governing.length)} rule(s) govern and none derived a trial — every rule owes a \`wrong\` and a \`right\`, so measuring nothing must not exit 0`,
|
|
358
|
-
)
|
|
359
|
-
exit(1)
|
|
360
|
-
}
|
|
361
|
-
console.log(`trial: nothing to prove — ${source}.`)
|
|
362
|
-
exit(0)
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
const { default: plugin } = await import('../lint.ts')
|
|
366
|
-
const parser = (await import('typescript-eslint')).parser
|
|
367
|
-
const run = runTrials(chosen, governing, plugin.rules, parser, slopnators)
|
|
368
|
-
for (const outcome of run.outcomes) {
|
|
369
|
-
if (outcome.passed) continue
|
|
370
|
-
for (const failure of outcome.failures) console.error(`trial: ${outcome.id} — ${failure}`)
|
|
371
|
-
}
|
|
372
|
-
console.log(`trial: ${String(run.passed)} of ${String(run.outcomes.length)} passed, ${String(run.measured)} measured.`)
|
|
373
|
-
if (only !== undefined) {
|
|
374
|
-
console.log(
|
|
375
|
-
`trial: PARTIAL RUN — ${String(derivation.trials.length - chosen.length)} of ${String(derivation.trials.length)} derived trials did not run. \`thread trials\` with no arguments runs every one.`,
|
|
376
|
-
)
|
|
377
|
-
}
|
|
378
|
-
exit(run.failed === 0 ? 0 : 1)
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
write(ROOT, byproduct)
|
|
382
|
-
console.log(`trial: wrote ${byproduct.path} — ${String(derivation.trials.length)} trials from ${source}.`)
|
|
383
|
-
}
|
package/dist/integrity/lint.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { starts } from '../integrations/cli.js';
|
|
2
2
|
import { Linter } from 'eslint';
|
|
3
3
|
import tseslint from 'typescript-eslint';
|
|
4
|
-
import { THING } from
|
|
5
|
-
import { CONSTRAINTS, shown } from
|
|
6
|
-
import { NOT_WRITTEN, governs, reads, visits, load, ROOT, rules as appRules, slopnatorName, } from
|
|
4
|
+
import { THING } from '../core/scope.js';
|
|
5
|
+
import { CONSTRAINTS, shown } from './constraint.js';
|
|
6
|
+
import { NOT_WRITTEN, governs, subject, reads, visits, load, ROOT, rules as appRules, slopnatorName, } from './slopnator.js';
|
|
7
7
|
const PROBE = {
|
|
8
8
|
filename: 'probe.ts',
|
|
9
9
|
text: '',
|
|
@@ -61,7 +61,7 @@ export function ruleRule(rule, slopnators) {
|
|
|
61
61
|
return {};
|
|
62
62
|
const visit = (node) => {
|
|
63
63
|
const at = {
|
|
64
|
-
filename: context.filename,
|
|
64
|
+
filename: context.filename.startsWith(ROOT) ? context.filename.slice(ROOT.length) : context.filename,
|
|
65
65
|
text: context.sourceCode.getText(),
|
|
66
66
|
ancestors: () => context.sourceCode.getAncestors(node),
|
|
67
67
|
comments: () => context.sourceCode.getAllComments().map((comment) => ({
|
|
@@ -89,7 +89,7 @@ export function ruleRules(slopnators) {
|
|
|
89
89
|
return Object.fromEntries(GOVERNING.map((rule) => [rule.id, ruleRule(rule, slopnators)]));
|
|
90
90
|
}
|
|
91
91
|
export function ruleSeverities() {
|
|
92
|
-
return Object.fromEntries(GOVERNING.map((rule) => [`lint/${rule.id}`, rule.severity === 'warning' ? 'warn' : 'error']));
|
|
92
|
+
return Object.fromEntries(GOVERNING.filter((rule) => subject(rule)).map((rule) => [`lint/${rule.id}`, rule.severity === 'warning' ? 'warn' : 'error']));
|
|
93
93
|
}
|
|
94
94
|
const GOVERNING = [...CONSTRAINTS, ...((await appRules()) ?? [])];
|
|
95
95
|
const SLOPNATORS = await load(ROOT, GOVERNING);
|
|
@@ -98,12 +98,8 @@ export const plugin = { rules: ruleRules(SLOPNATORS) };
|
|
|
98
98
|
export default plugin;
|
|
99
99
|
function ignored() {
|
|
100
100
|
try {
|
|
101
|
-
return
|
|
102
|
-
|
|
103
|
-
encoding: 'utf8',
|
|
104
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
105
|
-
})
|
|
106
|
-
.split('\n')
|
|
101
|
+
return starts('git', ['ls-files', '--others', '--ignored', '--exclude-standard', '--directory'], { at: ROOT })
|
|
102
|
+
.out.split('\n')
|
|
107
103
|
.filter(Boolean)
|
|
108
104
|
.map((one) => (one.endsWith('/') ? one + '**' : one));
|
|
109
105
|
}
|
|
@@ -138,7 +134,7 @@ export function theRules() {
|
|
|
138
134
|
parserOptions: { ecmaVersion: 'latest', sourceType: 'module', ecmaFeatures: { jsx: true } },
|
|
139
135
|
},
|
|
140
136
|
plugins: { [`@${THING}`]: plugin },
|
|
141
|
-
rules: Object.fromEntries(GOVERNING.map((rule) => [`@${THING}/${rule.id}`, rule.severity === 'warning' ? 'warn' : 'error'])),
|
|
137
|
+
rules: Object.fromEntries(GOVERNING.filter((rule) => subject(rule)).map((rule) => [`@${THING}/${rule.id}`, rule.severity === 'warning' ? 'warn' : 'error'])),
|
|
142
138
|
},
|
|
143
139
|
];
|
|
144
140
|
return (file, source) => linter
|
package/dist/integrity/lint.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { starts } from '../integrations/cli.ts'
|
|
2
2
|
import { fileURLToPath } from 'node:url'
|
|
3
3
|
|
|
4
4
|
import { Linter, type Rule } from 'eslint'
|
|
@@ -9,6 +9,7 @@ import { CONSTRAINTS, shown, type Constraint } from './constraint.ts'
|
|
|
9
9
|
import {
|
|
10
10
|
NOT_WRITTEN,
|
|
11
11
|
governs,
|
|
12
|
+
subject,
|
|
12
13
|
reads,
|
|
13
14
|
visits,
|
|
14
15
|
load,
|
|
@@ -91,7 +92,7 @@ export function ruleRule(rule: Constraint, slopnators: ReadonlyMap<string, Slopn
|
|
|
91
92
|
if (found === undefined || !visits(found)) return {}
|
|
92
93
|
const visit = (node: unknown): void => {
|
|
93
94
|
const at: SlopnatorContext = {
|
|
94
|
-
filename: context.filename,
|
|
95
|
+
filename: context.filename.startsWith(ROOT) ? context.filename.slice(ROOT.length) : context.filename,
|
|
95
96
|
text: context.sourceCode.getText(),
|
|
96
97
|
ancestors: () => context.sourceCode.getAncestors(node as never),
|
|
97
98
|
comments: () =>
|
|
@@ -122,7 +123,7 @@ export function ruleRules(slopnators: ReadonlyMap<string, Slopnator>): Readonly<
|
|
|
122
123
|
|
|
123
124
|
export function ruleSeverities(): Readonly<Record<string, 'error' | 'warn'>> {
|
|
124
125
|
return Object.fromEntries(
|
|
125
|
-
GOVERNING.map((rule) => [`lint/${rule.id}`, rule.severity === 'warning' ? ('warn' as const) : ('error' as const)]),
|
|
126
|
+
GOVERNING.filter((rule) => subject(rule)).map((rule) => [`lint/${rule.id}`, rule.severity === 'warning' ? ('warn' as const) : ('error' as const)]),
|
|
126
127
|
)
|
|
127
128
|
}
|
|
128
129
|
|
|
@@ -137,12 +138,8 @@ export default plugin
|
|
|
137
138
|
|
|
138
139
|
function ignored(): readonly string[] {
|
|
139
140
|
try {
|
|
140
|
-
return
|
|
141
|
-
|
|
142
|
-
encoding: 'utf8',
|
|
143
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
144
|
-
})
|
|
145
|
-
.split('\n')
|
|
141
|
+
return starts('git', ['ls-files', '--others', '--ignored', '--exclude-standard', '--directory'], { at: ROOT })
|
|
142
|
+
.out.split('\n')
|
|
146
143
|
.filter(Boolean)
|
|
147
144
|
.map((one) => (one.endsWith('/') ? one + '**' : one))
|
|
148
145
|
} catch {
|
|
@@ -201,7 +198,7 @@ export function theRules(): RuleRunner {
|
|
|
201
198
|
},
|
|
202
199
|
plugins: { [`@${THING}`]: plugin },
|
|
203
200
|
rules: Object.fromEntries(
|
|
204
|
-
GOVERNING.map((rule) => [`@${THING}/${rule.id}`, rule.severity === 'warning' ? 'warn' : 'error']),
|
|
201
|
+
GOVERNING.filter((rule) => subject(rule)).map((rule) => [`@${THING}/${rule.id}`, rule.severity === 'warning' ? 'warn' : 'error']),
|
|
205
202
|
),
|
|
206
203
|
},
|
|
207
204
|
] as unknown as Parameters<InstanceType<typeof Linter>['verify']>[1]
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { cwd,
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { cwd, stderr, stdin, stdout } from 'node:process';
|
|
3
|
+
import { exit } from '../../core/invoked.js';
|
|
4
|
+
import { repoSource } from './diagnostics.js';
|
|
5
|
+
import { encode, MessageBuffer } from './protocol.js';
|
|
6
|
+
import { LspServer } from './server.js';
|
|
6
7
|
const server = new LspServer({
|
|
7
8
|
root: cwd(),
|
|
8
9
|
sourceFor: repoSource,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { cwd,
|
|
3
|
+
import { cwd, stderr, stdin, stdout } from 'node:process'
|
|
4
|
+
|
|
5
|
+
import { exit } from '../../core/invoked.ts'
|
|
4
6
|
|
|
5
7
|
import { repoSource } from './diagnostics.ts'
|
|
6
8
|
import { encode, MessageBuffer } from './protocol.ts'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { readFileSync } from
|
|
1
|
+
import { readFileSync } from '../../integrations/disk.js';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { detailOf, rangeOf } from
|
|
4
|
-
import { lintFindings } from
|
|
3
|
+
import { detailOf, rangeOf } from './findings.js';
|
|
4
|
+
import { lintFindings } from './lint.js';
|
|
5
5
|
export function repoSource(root) {
|
|
6
6
|
return {
|
|
7
7
|
lint: (relative, text) => lintFindings(root, relative, text),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { existsSync } from
|
|
1
|
+
import { started } from '../../integrations/cli.js';
|
|
2
|
+
import { existsSync } from '../../integrations/disk.js';
|
|
3
3
|
import { extname, join } from 'node:path';
|
|
4
|
-
import { theRules } from
|
|
4
|
+
import { theRules } from '../lint.js';
|
|
5
5
|
const LINTABLE = new Set(['.ts', '.tsx', '.mts', '.cts', '.js', '.mjs', '.cjs', '.jsx']);
|
|
6
6
|
export const isLintable = (relative) => LINTABLE.has(extname(relative));
|
|
7
7
|
export const LINT_CONFIG = 'eslint.config.js';
|
|
@@ -64,32 +64,21 @@ export async function lintFindings(root, relative, text) {
|
|
|
64
64
|
...(suggestionsOf(message).length === 0 ? {} : { suggestions: suggestionsOf(message) }),
|
|
65
65
|
})));
|
|
66
66
|
}
|
|
67
|
-
function runEslint(binary, root, relative, text) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
shell: false,
|
|
72
|
-
});
|
|
73
|
-
let out = '';
|
|
74
|
-
let err = '';
|
|
75
|
-
child.stdout.on('data', (chunk) => (out += chunk.toString()));
|
|
76
|
-
child.stderr.on('data', (chunk) => (err += chunk.toString()));
|
|
77
|
-
child.on('error', (error) => reject(new LintUnavailableError(error.message)));
|
|
78
|
-
child.on('close', () => {
|
|
79
|
-
let parsed;
|
|
80
|
-
try {
|
|
81
|
-
parsed = JSON.parse(out);
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
reject(new LintUnavailableError(err.trim() === '' ? `it wrote ${out.length} bytes of non-JSON` : err.trim()));
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
if (!Array.isArray(parsed)) {
|
|
88
|
-
reject(new LintUnavailableError('its JSON report was not an array of files'));
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
resolve(parsed);
|
|
92
|
-
});
|
|
93
|
-
child.stdin.end(text);
|
|
67
|
+
async function runEslint(binary, root, relative, text) {
|
|
68
|
+
const went = await started(binary, ['--format', 'json', '--no-warn-ignored', '--stdin', '--stdin-filename', relative], {
|
|
69
|
+
at: root,
|
|
70
|
+
hears: text,
|
|
94
71
|
});
|
|
72
|
+
if (!went.there)
|
|
73
|
+
throw new LintUnavailableError(went.why);
|
|
74
|
+
let parsed;
|
|
75
|
+
try {
|
|
76
|
+
parsed = JSON.parse(went.out);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
throw new LintUnavailableError(went.err.trim() === '' ? `it wrote ${went.out.length} bytes of non-JSON` : went.err.trim());
|
|
80
|
+
}
|
|
81
|
+
if (!Array.isArray(parsed))
|
|
82
|
+
throw new LintUnavailableError('its JSON report was not an array of files');
|
|
83
|
+
return parsed;
|
|
95
84
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { existsSync } from '../../
|
|
1
|
+
import { started } from '../../integrations/cli.ts'
|
|
2
|
+
import { existsSync } from '../../integrations/disk.ts'
|
|
3
3
|
import { extname, join } from 'node:path'
|
|
4
4
|
|
|
5
5
|
import { theRules } from '../lint.ts'
|
|
@@ -101,40 +101,24 @@ export async function lintFindings(root: string, relative: string, text: string)
|
|
|
101
101
|
)
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
function runEslint(
|
|
104
|
+
async function runEslint(
|
|
105
105
|
binary: string,
|
|
106
106
|
root: string,
|
|
107
107
|
relative: string,
|
|
108
108
|
text: string,
|
|
109
109
|
): Promise<readonly EslintFile[]> {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
cwd: root,
|
|
114
|
-
shell: false,
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
let out = ''
|
|
118
|
-
let err = ''
|
|
119
|
-
child.stdout.on('data', (chunk: Buffer) => (out += chunk.toString()))
|
|
120
|
-
child.stderr.on('data', (chunk: Buffer) => (err += chunk.toString()))
|
|
121
|
-
child.on('error', (error) => reject(new LintUnavailableError(error.message)))
|
|
122
|
-
child.on('close', () => {
|
|
123
|
-
|
|
124
|
-
let parsed: unknown
|
|
125
|
-
try {
|
|
126
|
-
parsed = JSON.parse(out)
|
|
127
|
-
} catch {
|
|
128
|
-
reject(new LintUnavailableError(err.trim() === '' ? `it wrote ${out.length} bytes of non-JSON` : err.trim()))
|
|
129
|
-
return
|
|
130
|
-
}
|
|
131
|
-
if (!Array.isArray(parsed)) {
|
|
132
|
-
reject(new LintUnavailableError('its JSON report was not an array of files'))
|
|
133
|
-
return
|
|
134
|
-
}
|
|
135
|
-
resolve(parsed as readonly EslintFile[])
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
child.stdin.end(text)
|
|
110
|
+
const went = await started(binary, ['--format', 'json', '--no-warn-ignored', '--stdin', '--stdin-filename', relative], {
|
|
111
|
+
at: root,
|
|
112
|
+
hears: text,
|
|
139
113
|
})
|
|
114
|
+
if (!went.there) throw new LintUnavailableError(went.why)
|
|
115
|
+
|
|
116
|
+
let parsed: unknown
|
|
117
|
+
try {
|
|
118
|
+
parsed = JSON.parse(went.out)
|
|
119
|
+
} catch {
|
|
120
|
+
throw new LintUnavailableError(went.err.trim() === '' ? `it wrote ${went.out.length} bytes of non-JSON` : went.err.trim())
|
|
121
|
+
}
|
|
122
|
+
if (!Array.isArray(parsed)) throw new LintUnavailableError('its JSON report was not an array of files')
|
|
123
|
+
return parsed as readonly EslintFile[]
|
|
140
124
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { relative as relativeTo, resolve } from 'node:path';
|
|
2
2
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
3
|
-
import { named } from
|
|
4
|
-
import { report, SOURCE_NAME } from
|
|
5
|
-
import { METHOD_NOT_FOUND } from
|
|
3
|
+
import { named } from '../../core/scope.js';
|
|
4
|
+
import { report, SOURCE_NAME } from './diagnostics.js';
|
|
5
|
+
import { METHOD_NOT_FOUND } from './protocol.js';
|
|
6
6
|
const SYNC_FULL = 1;
|
|
7
7
|
export class LspServer {
|
|
8
8
|
#root;
|