@esportsplus/typescript 0.31.1 → 0.33.0

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.
Files changed (69) hide show
  1. package/README.md +34 -44
  2. package/build/cli/tsc.d.ts +3 -2
  3. package/build/cli/tsc.js +15 -97
  4. package/build/{probe → guard}/adapter.d.ts +1 -2
  5. package/build/{probe → guard}/adapter.js +1 -4
  6. package/build/{probe → guard}/async/channel.d.ts +1 -1
  7. package/build/{probe → guard}/async/channel.js +12 -192
  8. package/build/{probe → guard}/async/value.d.ts +1 -2
  9. package/build/{probe → guard}/async/value.js +1 -4
  10. package/build/guard/channels.d.ts +4 -0
  11. package/build/guard/channels.js +13 -0
  12. package/build/{probe → guard}/exceptions/channel.d.ts +3 -2
  13. package/build/{probe → guard}/exceptions/channel.js +173 -101
  14. package/build/guard/exceptions/derive.d.ts +49 -0
  15. package/build/guard/exceptions/derive.js +478 -0
  16. package/build/{probe → guard}/exceptions/jsdoc.d.ts +1 -1
  17. package/build/{probe → guard}/exceptions/jsdoc.js +1 -1
  18. package/build/guard/exceptions/resolve-js.d.ts +2 -0
  19. package/build/guard/exceptions/resolve-js.js +26 -0
  20. package/build/{probe → guard}/exceptions/value.d.ts +4 -3
  21. package/build/{probe → guard}/exceptions/value.js +13 -5
  22. package/build/{probe → guard}/kernel/analyze.d.ts +3 -2
  23. package/build/guard/kernel/analyze.js +84 -0
  24. package/build/guard/kernel/ast.d.ts +13 -0
  25. package/build/guard/kernel/ast.js +56 -0
  26. package/build/guard/kernel/config.js +93 -0
  27. package/build/guard/kernel/fixpoint.d.ts +6 -0
  28. package/build/{probe → guard}/kernel/fixpoint.js +8 -48
  29. package/build/guard/kernel/graph.d.ts +4 -0
  30. package/build/guard/kernel/graph.js +268 -0
  31. package/build/{probe → guard}/kernel/ids.d.ts +3 -4
  32. package/build/{probe → guard}/kernel/ids.js +2 -7
  33. package/build/{probe → guard}/kernel/program.d.ts +1 -1
  34. package/build/{probe → guard}/kernel/types.d.ts +4 -33
  35. package/build/{probe → guard}/overlay/base/async.jsonc +1 -1
  36. package/build/{probe → guard}/overlay/base/exceptions.jsonc +16 -3
  37. package/build/{probe → guard}/overlay/base/resources.jsonc +7 -8
  38. package/build/{probe → guard}/overlay/load.d.ts +3 -7
  39. package/build/{probe → guard}/overlay/load.js +38 -121
  40. package/build/{probe → guard}/resources/channel.d.ts +1 -1
  41. package/build/{probe → guard}/resources/channel.js +80 -158
  42. package/build/{probe → guard}/resources/value.d.ts +1 -2
  43. package/build/{probe → guard}/resources/value.js +1 -14
  44. package/build/lsp/diagnostics.d.ts +2 -2
  45. package/build/lsp/diagnostics.js +2 -2
  46. package/build/lsp/server.js +41 -3
  47. package/build/lsp/workspace.d.ts +6 -3
  48. package/build/lsp/workspace.js +19 -5
  49. package/build/tsconfig.d.ts +2 -1
  50. package/build/tsconfig.js +44 -102
  51. package/package.json +8 -8
  52. package/tsconfig.base.json +12 -19
  53. package/tsconfig.package.json +6 -1
  54. package/build/probe/channels.d.ts +0 -4
  55. package/build/probe/channels.js +0 -16
  56. package/build/probe/kernel/analyze.js +0 -68
  57. package/build/probe/kernel/ast.d.ts +0 -11
  58. package/build/probe/kernel/ast.js +0 -49
  59. package/build/probe/kernel/config.js +0 -209
  60. package/build/probe/kernel/fixpoint.d.ts +0 -6
  61. package/build/probe/kernel/graph.d.ts +0 -4
  62. package/build/probe/kernel/graph.js +0 -507
  63. package/build/probe/overlay/presets/express.jsonc +0 -25
  64. package/build/probe/overlay/presets/node.jsonc +0 -17
  65. /package/build/{probe → guard}/kernel/config.d.ts +0 -0
  66. /package/build/{probe → guard}/kernel/format.d.ts +0 -0
  67. /package/build/{probe → guard}/kernel/format.js +0 -0
  68. /package/build/{probe → guard}/kernel/program.js +0 -0
  69. /package/build/{probe → guard}/kernel/types.js +0 -0
package/build/tsconfig.js CHANGED
@@ -3,6 +3,18 @@ import * as fs from 'node:fs';
3
3
  import * as path from 'node:path';
4
4
  import { stripJsonc } from './jsonc.js';
5
5
  let require = createRequire(import.meta.url);
6
+ function deepMerge(base, override) {
7
+ if (!isPlainObject(base) || !isPlainObject(override)) {
8
+ return override;
9
+ }
10
+ let result = { ...base };
11
+ for (let key of Object.keys(override)) {
12
+ result[key] = key in result
13
+ ? deepMerge(result[key], override[key])
14
+ : override[key];
15
+ }
16
+ return result;
17
+ }
6
18
  function extendsTarget(specifier, fromDir) {
7
19
  if (typeof specifier !== 'string') {
8
20
  return null;
@@ -30,97 +42,15 @@ function extendsTarget(specifier, fromDir) {
30
42
  }
31
43
  }
32
44
  }
33
- function legacyStripJsonc(text) {
34
- let escaped = false, inBlockComment = false, inLineComment = false, inString = false, stripped = '';
35
- for (let i = 0, n = text.length; i < n; i++) {
36
- let char = text[i], next = text[i + 1];
37
- if (inLineComment) {
38
- if (char === '\n') {
39
- inLineComment = false;
40
- stripped += char;
41
- }
42
- continue;
43
- }
44
- if (inBlockComment) {
45
- if (char === '*' && next === '/') {
46
- inBlockComment = false;
47
- i++;
48
- }
49
- continue;
50
- }
51
- if (inString) {
52
- stripped += char;
53
- if (escaped) {
54
- escaped = false;
55
- }
56
- else if (char === '\\') {
57
- escaped = true;
58
- }
59
- else if (char === '"') {
60
- inString = false;
61
- }
62
- continue;
63
- }
64
- if (char === '"') {
65
- inString = true;
66
- stripped += char;
67
- continue;
68
- }
69
- if (char === '/' && next === '/') {
70
- inLineComment = true;
71
- i++;
72
- continue;
73
- }
74
- if (char === '/' && next === '*') {
75
- inBlockComment = true;
76
- i++;
77
- continue;
78
- }
79
- stripped += char;
80
- }
81
- escaped = false;
82
- inString = false;
83
- let result = '';
84
- for (let i = 0, n = stripped.length; i < n; i++) {
85
- let char = stripped[i];
86
- if (inString) {
87
- result += char;
88
- if (escaped) {
89
- escaped = false;
90
- }
91
- else if (char === '\\') {
92
- escaped = true;
93
- }
94
- else if (char === '"') {
95
- inString = false;
96
- }
97
- continue;
98
- }
99
- if (char === '"') {
100
- inString = true;
101
- result += char;
102
- continue;
103
- }
104
- if (char === ',') {
105
- let j = i + 1;
106
- while (j < n && /\s/.test(stripped[j])) {
107
- j++;
108
- }
109
- if (stripped[j] === ']' || stripped[j] === '}') {
110
- continue;
111
- }
112
- }
113
- result += char;
114
- }
115
- return result;
45
+ function isPlainObject(value) {
46
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
116
47
  }
117
- void legacyStripJsonc;
118
- const readPlugins = (tsconfigPath) => {
119
- let seen = new Set();
120
- function read(configPath) {
121
- let id = path.resolve(configPath);
48
+ function walkExtends(tsconfigPath, fold) {
49
+ const seen = new Set();
50
+ function read(configPath, inherited) {
51
+ const id = path.resolve(configPath);
122
52
  if (seen.has(id)) {
123
- return undefined;
53
+ return inherited;
124
54
  }
125
55
  seen.add(id);
126
56
  let config;
@@ -128,23 +58,35 @@ const readPlugins = (tsconfigPath) => {
128
58
  config = JSON.parse(stripJsonc(fs.readFileSync(id, 'utf8')));
129
59
  }
130
60
  catch {
131
- return undefined;
61
+ return inherited;
132
62
  }
133
- let plugins;
134
63
  if (config.extends !== undefined) {
135
- let bases = Array.isArray(config.extends) ? config.extends : [config.extends];
136
- for (let base of bases) {
137
- let target = extendsTarget(base, path.dirname(id));
64
+ const bases = Array.isArray(config.extends) ? config.extends : [config.extends];
65
+ for (const base of bases) {
66
+ const target = extendsTarget(base, path.dirname(id));
138
67
  if (target) {
139
- let inherited = read(target);
140
- if (inherited !== undefined) {
141
- plugins = inherited;
142
- }
68
+ inherited = read(target, inherited);
143
69
  }
144
70
  }
145
71
  }
146
- return Array.isArray(config.compilerOptions?.plugins) ? config.compilerOptions.plugins : plugins;
72
+ return fold(config, inherited);
73
+ }
74
+ return read(tsconfigPath, undefined);
75
+ }
76
+ const readPlugins = (tsconfigPath) => walkExtends(tsconfigPath, (config, inherited) => {
77
+ const compilerOptions = config['compilerOptions'];
78
+ const plugins = isPlainObject(compilerOptions)
79
+ ? compilerOptions['plugins']
80
+ : undefined;
81
+ return Array.isArray(plugins) ? plugins : inherited;
82
+ });
83
+ const readGuardConfig = (tsconfigPath) => walkExtends(tsconfigPath, (config, inherited) => {
84
+ const own = config['tsc-guard'];
85
+ if (!isPlainObject(own)) {
86
+ return inherited;
147
87
  }
148
- return read(tsconfigPath);
149
- };
150
- export { readPlugins };
88
+ return inherited === undefined
89
+ ? own
90
+ : deepMerge(inherited, own);
91
+ });
92
+ export { readPlugins, readGuardConfig };
package/package.json CHANGED
@@ -10,15 +10,15 @@
10
10
  "dependencies": {
11
11
  "@esportsplus/cli-passthrough": "^0.0.15",
12
12
  "@esportsplus/utilities": "^0.28.0",
13
- "@types/node": "^26.1.1",
14
- "tsc-alias": "^1.9.1",
13
+ "@types/node": "^26.4.1",
14
+ "tsc-alias": "^1.9.4",
15
15
  "typescript": "7.0.2",
16
- "vscode-languageserver": "^10.1.0",
17
- "vscode-languageserver-textdocument": "^1.0.12"
16
+ "vscode-languageserver": "^10.1.1",
17
+ "vscode-languageserver-textdocument": "^1.0.14"
18
18
  },
19
19
  "devDependencies": {
20
- "vite": "^8.1.5",
21
- "vitest": "^4.1.10"
20
+ "vite": "^8.2.2",
21
+ "vitest": "^4.1.11"
22
22
  },
23
23
  "exports": {
24
24
  "./package.json": "./package.json",
@@ -60,13 +60,13 @@
60
60
  },
61
61
  "type": "module",
62
62
  "types": "build/index.d.ts",
63
- "version": "0.31.1",
63
+ "version": "0.33.0",
64
64
  "scripts": {
65
65
  "agent:bench": "pnpm bench:run",
66
66
  "agent:build": "pnpm build",
67
67
  "agent:test": "pnpm typecheck && pnpm test",
68
68
  "bench:run": "vitest bench --run",
69
- "build": "tsc -p tsconfig.package.json && tsc-alias -p tsconfig.package.json && node -e \"const fs=require('fs');fs.cpSync('src/probe/overlay','build/probe/overlay',{recursive:true,filter:(s)=>!/\\.[cm]?tsx?$/.test(s)})\"",
69
+ "build": "tsc -p tsconfig.package.json && tsc-alias -p tsconfig.package.json && node -e \"const fs=require('fs');fs.cpSync('src/guard/overlay','build/guard/overlay',{recursive:true,filter:(s)=>!/\\.[cm]?tsx?$/.test(s)})\"",
70
70
  "test": "vitest run",
71
71
  "typecheck": "tsc"
72
72
  }
@@ -23,25 +23,6 @@
23
23
  "${configDir}/storage/*"
24
24
  ]
25
25
  },
26
- "plugins": [
27
- {
28
- "name": "ts-probe",
29
- // Editor squiggle color; "warn" opts down. CLI/build ignore this.
30
- "severity": "error",
31
- // Fail the tsc/build run when there are findings.
32
- "failOnFindings": true,
33
- "channels": {
34
- "exceptions": {
35
- "enabled": true,
36
- "report": "consumers",
37
- // Flag `throw`s inside `catch` that drop the caught error's cause.
38
- "errorCause": true
39
- }
40
- },
41
- // Model third-party throw behavior: "node", "express".
42
- "presets": ["node"]
43
- }
44
- ],
45
26
  "removeComments": true,
46
27
  "resolveJsonModule": true,
47
28
  "rootDir": "${configDir}/src",
@@ -54,5 +35,17 @@
54
35
  ],
55
36
  "tsc-alias": {
56
37
  "resolveFullPaths": true
38
+ },
39
+ "tsc-guard": {
40
+ "exceptions": {
41
+ "severity": "error",
42
+ "report": "cross-module"
43
+ },
44
+ "resources": {
45
+ "severity": "error"
46
+ },
47
+ "async": {
48
+ "severity": "info"
49
+ }
57
50
  }
58
51
  }
@@ -11,5 +11,10 @@
11
11
  "node"
12
12
  ]
13
13
  },
14
- "extends": "./tsconfig.base.json"
14
+ "extends": "./tsconfig.base.json",
15
+ "tsc-guard": {
16
+ "exceptions": {
17
+ "report": "consumers"
18
+ }
19
+ }
15
20
  }
@@ -1,4 +0,0 @@
1
- import type { Channel } from './kernel/types.js';
2
- declare function channelFor(name: string, config: unknown): Channel<unknown> | undefined;
3
- declare function implementedChannels(): ReadonlyArray<string>;
4
- export { channelFor, implementedChannels };
@@ -1,16 +0,0 @@
1
- import { createAsyncChannel } from './async/channel.js';
2
- import { createExceptionsChannel } from './exceptions/channel.js';
3
- import { createResourcesChannel } from './resources/channel.js';
4
- const FACTORIES = {
5
- async: (config) => createAsyncChannel(config),
6
- exceptions: () => createExceptionsChannel(),
7
- resources: (config) => createResourcesChannel(config),
8
- };
9
- function channelFor(name, config) {
10
- const factory = FACTORIES[name];
11
- return factory ? factory(config) : undefined;
12
- }
13
- function implementedChannels() {
14
- return Object.keys(FACTORIES);
15
- }
16
- export { channelFor, implementedChannels };
@@ -1,68 +0,0 @@
1
- import { channelFor } from '../channels.js';
2
- import { buildCallGraph } from './graph.js';
3
- import { buildProgram } from './program.js';
4
- import { runChannel } from './fixpoint.js';
5
- import { loadOverlays } from '../overlay/load.js';
6
- function analyzeProgram(program, checker, config) {
7
- const overlays = loadOverlays(config);
8
- const effectiveConfig = {
9
- ...config,
10
- handlerBoundaries: [
11
- ...config.handlerBoundaries,
12
- ...overlays.boundariesFromPresets(),
13
- ],
14
- };
15
- const graph = buildCallGraph(program, checker, effectiveConfig, overlays);
16
- const analysis = {
17
- program,
18
- checker,
19
- config: effectiveConfig,
20
- overlays,
21
- graph,
22
- };
23
- const diagnostics = [];
24
- const runnable = new Map();
25
- for (const [name, channelConfig] of Object.entries(effectiveConfig.channels)) {
26
- if (!channelConfig.enabled) {
27
- continue;
28
- }
29
- runnable.set(name, {
30
- config: channelConfig,
31
- channel: channelFor(name, channelConfig.options),
32
- });
33
- }
34
- const ordered = [];
35
- const placed = new Set();
36
- const place = (name, stack) => {
37
- if (placed.has(name) || !runnable.has(name) || stack.has(name)) {
38
- return;
39
- }
40
- const next = new Set(stack).add(name);
41
- for (const dep of runnable.get(name).channel.dependsOn ?? []) {
42
- place(dep, next);
43
- }
44
- placed.add(name);
45
- ordered.push(name);
46
- };
47
- for (const name of runnable.keys()) {
48
- place(name, new Set());
49
- }
50
- const peers = new Map();
51
- for (const name of ordered) {
52
- const { config, channel } = runnable.get(name);
53
- const result = runChannel(analysis, channel, config.dispatch, config.options, peers);
54
- peers.set(name, result.store);
55
- diagnostics.push(...result.diagnostics);
56
- }
57
- return { diagnostics };
58
- }
59
- function analyze(config) {
60
- const built = buildProgram(config.tsconfigPath);
61
- try {
62
- return analyzeProgram(built.program, built.checker, config);
63
- }
64
- finally {
65
- built.dispose();
66
- }
67
- }
68
- export { analyze, analyzeProgram };
@@ -1,11 +0,0 @@
1
- import * as ts from '../../probe/adapter.js';
2
- import type { FunctionLike } from './types.js';
3
- type UnwrapOptions = {
4
- assertions?: boolean;
5
- awaits?: boolean;
6
- };
7
- declare const bodyOf: (node: FunctionLike) => ts.Node | undefined;
8
- declare const calleeSelectors: (callee: ts.Expression) => Set<string>;
9
- declare const paramSymbols: (checker: ts.TypeChecker, fn: FunctionLike) => Map<ts.Symbol, number>;
10
- declare const unwrap: (expr: ts.Expression, options?: UnwrapOptions) => ts.Expression;
11
- export { bodyOf, calleeSelectors, paramSymbols, unwrap };
@@ -1,49 +0,0 @@
1
- import * as ts from '../../probe/adapter.js';
2
- function shouldUnwrap(expr, options) {
3
- return (ts.isParenthesizedExpression(expr) ||
4
- (options.assertions === true &&
5
- (ts.isAsExpression(expr) || ts.isNonNullExpression(expr))) ||
6
- (options.awaits === true && ts.isAwaitExpression(expr)));
7
- }
8
- const bodyOf = (node) => {
9
- return node.body;
10
- };
11
- const calleeSelectors = (callee) => {
12
- let selectors = new Set();
13
- if (ts.isIdentifier(callee)) {
14
- selectors.add(callee.text);
15
- }
16
- else if (ts.isPropertyAccessExpression(callee)) {
17
- let member = callee.name.text;
18
- selectors.add(member);
19
- if (ts.isIdentifier(callee.expression)) {
20
- selectors.add(`${callee.expression.text}.${member}`);
21
- selectors.add(`${callee.expression.text}#${member}`);
22
- }
23
- }
24
- return selectors;
25
- };
26
- const paramSymbols = (checker, fn) => {
27
- let symbols = new Map();
28
- let params = fn
29
- .parameters;
30
- if (params) {
31
- params.forEach((param, index) => {
32
- if (ts.isIdentifier(param.name)) {
33
- let symbol = checker.getSymbolAtLocation(param.name);
34
- if (symbol) {
35
- symbols.set(symbol, index);
36
- }
37
- }
38
- });
39
- }
40
- return symbols;
41
- };
42
- const unwrap = (expr, options = {}) => {
43
- let unwrapped = expr;
44
- while (shouldUnwrap(unwrapped, options)) {
45
- unwrapped = unwrapped.expression;
46
- }
47
- return unwrapped;
48
- };
49
- export { bodyOf, calleeSelectors, paramSymbols, unwrap };
@@ -1,209 +0,0 @@
1
- import * as NodePath from 'node:path';
2
- import { readPlugins } from '../../tsconfig.js';
3
- import { stripJsonc } from '../../jsonc.js';
4
- const CHANNEL_NAMES = ['exceptions', 'resources', 'async'];
5
- const DEFAULT_ENABLED = {
6
- exceptions: true,
7
- resources: false,
8
- async: false,
9
- };
10
- function fail(message) {
11
- throw new Error(`analyze config: ${message}`);
12
- }
13
- function legacyStripJsonc(text) {
14
- let out = '';
15
- let i = 0;
16
- const n = text.length;
17
- let inString = false;
18
- let quote = '';
19
- while (i < n) {
20
- const ch = text[i];
21
- const next = i + 1 < n ? text[i + 1] : '';
22
- if (inString) {
23
- out += ch;
24
- if (ch === '\\') {
25
- out += next;
26
- i += 2;
27
- continue;
28
- }
29
- if (ch === quote) {
30
- inString = false;
31
- }
32
- i += 1;
33
- continue;
34
- }
35
- if (ch === '"' || ch === "'") {
36
- inString = true;
37
- quote = ch;
38
- out += ch;
39
- i += 1;
40
- continue;
41
- }
42
- if (ch === '/' && next === '/') {
43
- while (i < n && text[i] !== '\n') {
44
- i += 1;
45
- }
46
- continue;
47
- }
48
- if (ch === '/' && next === '*') {
49
- i += 2;
50
- while (i < n && !(text[i] === '*' && text[i + 1] === '/')) {
51
- i += 1;
52
- }
53
- i += 2;
54
- continue;
55
- }
56
- out += ch;
57
- i += 1;
58
- }
59
- return out.replace(/,(\s*[}\]])/g, '$1');
60
- }
61
- void legacyStripJsonc;
62
- function asStringArray(value, field) {
63
- if (value === undefined) {
64
- return [];
65
- }
66
- if (!Array.isArray(value) || value.some((v) => typeof v !== 'string')) {
67
- fail(`"${field}" must be an array of strings`);
68
- }
69
- return value;
70
- }
71
- function parseHandlerBoundaries(value) {
72
- if (value === undefined) {
73
- return [];
74
- }
75
- if (!Array.isArray(value)) {
76
- fail(`"handlerBoundaries" must be an array`);
77
- }
78
- return value.map((raw, index) => {
79
- if (typeof raw !== 'object' || raw === null) {
80
- fail(`handlerBoundaries[${index}] must be an object`);
81
- }
82
- const entry = raw;
83
- if (typeof entry['callee'] !== 'string') {
84
- fail(`handlerBoundaries[${index}].callee must be a string`);
85
- }
86
- const callbackArgs = entry['callbackArgs'];
87
- if (!Array.isArray(callbackArgs) ||
88
- callbackArgs.some((v) => typeof v !== 'number' || !Number.isInteger(v))) {
89
- fail(`handlerBoundaries[${index}].callbackArgs must be an array of integers`);
90
- }
91
- return {
92
- callee: entry['callee'],
93
- callbackArgs: callbackArgs,
94
- };
95
- });
96
- }
97
- function parseSinks(value) {
98
- if (value === undefined) {
99
- return [];
100
- }
101
- if (!Array.isArray(value)) {
102
- fail(`"sinks" must be an array`);
103
- }
104
- return value.map((raw, index) => {
105
- if (typeof raw !== 'object' || raw === null) {
106
- fail(`sinks[${index}] must be an object`);
107
- }
108
- const entry = raw;
109
- if (typeof entry['callee'] !== 'string') {
110
- fail(`sinks[${index}].callee must be a string`);
111
- }
112
- let absorbs;
113
- if (entry['absorbs'] !== undefined) {
114
- absorbs = asStringArray(entry['absorbs'], `sinks[${index}].absorbs`);
115
- }
116
- return { callee: entry['callee'], absorbs };
117
- });
118
- }
119
- function parseDispatch(value, channel) {
120
- if (value === undefined) {
121
- return 'optimist';
122
- }
123
- if (value !== 'optimist' && value !== 'pessimist') {
124
- fail(`channels.${channel}.dispatch must be "optimist" or "pessimist"`);
125
- }
126
- return value;
127
- }
128
- function parseChannels(value) {
129
- const channels = {};
130
- const raw = value === undefined ? {} : value;
131
- if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
132
- fail(`"channels" must be an object`);
133
- }
134
- for (const key of Object.keys(raw)) {
135
- if (!CHANNEL_NAMES.includes(key)) {
136
- fail(`unknown channel "${key}" (known: ${CHANNEL_NAMES.join(', ')})`);
137
- }
138
- }
139
- for (const name of CHANNEL_NAMES) {
140
- const entry = (raw[name] ?? {});
141
- if (typeof entry !== 'object' ||
142
- entry === null ||
143
- Array.isArray(entry)) {
144
- fail(`channels.${name} must be an object`);
145
- }
146
- const enabled = entry['enabled'] === undefined
147
- ? DEFAULT_ENABLED[name]
148
- : entry['enabled'];
149
- if (typeof enabled !== 'boolean') {
150
- fail(`channels.${name}.enabled must be a boolean`);
151
- }
152
- const { enabled: _e, dispatch: _d, ...options } = entry;
153
- channels[name] = {
154
- enabled,
155
- dispatch: parseDispatch(entry['dispatch'], name),
156
- options,
157
- };
158
- }
159
- return channels;
160
- }
161
- function normalizeConfig(raw, projectRoot) {
162
- if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
163
- fail(`root must be a JSON object`);
164
- }
165
- const tsconfig = raw.tsconfig === undefined ? 'tsconfig.json' : raw.tsconfig;
166
- if (typeof tsconfig !== 'string') {
167
- fail(`"tsconfig" must be a string`);
168
- }
169
- return {
170
- projectRoot,
171
- tsconfigPath: NodePath.resolve(projectRoot, tsconfig),
172
- entryPoints: asStringArray(raw.entryPoints, 'entryPoints'),
173
- handlerBoundaries: parseHandlerBoundaries(raw.handlerBoundaries),
174
- sinks: parseSinks(raw.sinks),
175
- presets: asStringArray(raw.presets, 'presets'),
176
- overlays: asStringArray(raw.overlays, 'overlays').map((p) => NodePath.resolve(projectRoot, p)),
177
- channels: parseChannels(raw.channels),
178
- failOnFindings: raw.failOnFindings === true,
179
- severity: raw.severity === 'warn' || raw.severity === 'warning'
180
- ? 'warning'
181
- : 'error',
182
- };
183
- }
184
- function parseConfig(text, projectRoot) {
185
- let parsed;
186
- try {
187
- parsed = JSON.parse(stripJsonc(text));
188
- }
189
- catch (error) {
190
- fail(`invalid JSONC: ${error.message}`);
191
- }
192
- return normalizeConfig(parsed, projectRoot);
193
- }
194
- function configFromObject(raw, projectRoot) {
195
- return normalizeConfig(raw, projectRoot);
196
- }
197
- function loadConfigFromTsconfig(tsconfigPath) {
198
- const resolved = NodePath.resolve(tsconfigPath);
199
- const plugins = readPlugins(resolved) ?? [];
200
- const entry = plugins.find((p) => p !== null && typeof p === 'object' && p.name === 'ts-probe');
201
- if (!entry) {
202
- return undefined;
203
- }
204
- return {
205
- ...configFromObject(entry, NodePath.dirname(resolved)),
206
- tsconfigPath: resolved,
207
- };
208
- }
209
- export { configFromObject, loadConfigFromTsconfig, parseConfig };
@@ -1,6 +0,0 @@
1
- import type { Analysis, Channel, Diagnostic, Dispatch, SummaryStore } from './types.js';
2
- declare function runChannel<V>(analysis: Analysis, channel: Channel<V>, dispatch: Dispatch, channelConfig: unknown, peers: ReadonlyMap<string, SummaryStore<unknown>>): {
3
- store: SummaryStore<V>;
4
- diagnostics: Diagnostic[];
5
- };
6
- export { runChannel };
@@ -1,4 +0,0 @@
1
- import * as ts from '../../probe/adapter.js';
2
- import type { CallGraph, OverlaySet, AnalyzeConfig } from './types.js';
3
- declare function buildCallGraph(program: ts.Program, checker: ts.TypeChecker, config: AnalyzeConfig, overlays: OverlaySet): CallGraph;
4
- export { buildCallGraph };