@redue/cli 0.1.0-alpha.2 → 0.1.0-alpha.20
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 +467 -0
- package/README.md +107 -2
- package/bin/redue.mjs +130 -49
- package/docs/README.md +2 -1
- package/docs/user/agents.md +299 -15
- package/docs/user/configuration.md +28 -2
- package/docs/user/direct-typescript.md +209 -0
- package/docs/user/getting-started.md +23 -2
- package/docs/user/json.md +2 -0
- package/docs/user/node-script.md +153 -0
- package/docs/user/npm-launcher-notice.md +42 -0
- package/docs/user/pilot.md +146 -0
- package/docs/user/receipt-selection-notice.md +60 -0
- package/docs/user/supported-projects.md +49 -21
- package/docs/user/tests-direct.md +132 -0
- package/package.json +4 -3
- package/src/agent-integration.mjs +388 -0
- package/src/agent-policy.md +28 -0
- package/src/cached-state.mjs +46 -8
- package/src/claude-hook.mjs +449 -0
- package/src/cli.mjs +263 -40
- package/src/daemon.mjs +433 -94
- package/src/decision-profile.mjs +15 -1
- package/src/decision-validation.mjs +10 -0
- package/src/declared-plan.mjs +29 -6
- package/src/direct-run-certificate.mjs +252 -0
- package/src/direct-typescript-probe.mjs +24 -0
- package/src/direct-typescript.mjs +185 -0
- package/src/glob.mjs +8 -0
- package/src/history-worker.mjs +21 -13
- package/src/index.mjs +72 -19
- package/src/installed-inputs.mjs +7 -1
- package/src/linux-inotify.py +39 -10
- package/src/node-onboarding.mjs +157 -48
- package/src/node-script.mjs +362 -0
- package/src/npm-integrity.mjs +124 -0
- package/src/npm-typecheck-environment.mjs +36 -0
- package/src/npmrc.mjs +16 -0
- package/src/observation.mjs +34 -12
- package/src/path-identity.mjs +8 -0
- package/src/plan-worker.mjs +17 -17
- package/src/pnpm-inputs.mjs +114 -54
- package/src/pnpm-shim-templates.json +180 -0
- package/src/pnpm-shims.mjs +54 -0
- package/src/pnpm-typecheck-probe.mjs +11 -6
- package/src/presentation.mjs +9 -1
- package/src/probe-deadline.mjs +37 -0
- package/src/probe-result.mjs +7 -3
- package/src/project-location.mjs +34 -0
- package/src/run-recorder.cjs +91 -0
- package/src/state-store.mjs +37 -1
- package/src/test-direct.mjs +560 -0
- package/src/test-recorder.cjs +406 -0
- package/src/typescript-contract-probe.mjs +4 -187
- package/src/typescript-input-facts.mjs +92 -0
- package/src/typescript-invocation.mjs +92 -0
- package/src/typescript-list.mjs +108 -13
- package/src/typescript-qualification.mjs +29 -49
- package/src/workspace-manifests.mjs +22 -0
- package/src/yarn-workspace-typecheck-probe.mjs +2 -1
package/src/plan-worker.mjs
CHANGED
|
@@ -3,11 +3,14 @@ import fs from 'node:fs';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import {createHash} from 'node:crypto';
|
|
5
5
|
import {discover} from './plan.mjs';
|
|
6
|
-
import {InputIndex} from './index.mjs';
|
|
6
|
+
import {InputIndex,dehydrateIndex} from './index.mjs';
|
|
7
|
+
import {directProject,directQualification} from './direct-typescript.mjs';
|
|
8
|
+
import {checkRun} from './typescript-invocation.mjs';
|
|
7
9
|
import {queriesMatch} from './typescript-list.mjs';
|
|
8
10
|
import {planGuard,inputKey} from './decision-validation.mjs';
|
|
9
|
-
import {timing} from './decision-profile.mjs';
|
|
11
|
+
import {timing,traceBase} from './decision-profile.mjs';
|
|
10
12
|
|
|
13
|
+
traceBase(workerData.diagnostic);
|
|
11
14
|
try {
|
|
12
15
|
const totalStarted=performance.now();
|
|
13
16
|
const configStarted=performance.now();
|
|
@@ -21,7 +24,16 @@ try {
|
|
|
21
24
|
try{
|
|
22
25
|
guard=planGuard(bundle);
|
|
23
26
|
const queryStarted=performance.now();
|
|
24
|
-
|
|
27
|
+
// Cached membership queries load the compiler API; establish its reviewed
|
|
28
|
+
// implementation before that optimization can execute project code.
|
|
29
|
+
// Every direct check (a chain has one per run) uses the root's compiler:
|
|
30
|
+
// its bytes are verified once.
|
|
31
|
+
const directRoots=new Set(config.checks.filter(check=>check.qualification===directQualification)
|
|
32
|
+
.map((check,i)=>directProject(config.root,checkRun(check),{verify:i===0}).tsRoot));
|
|
33
|
+
if(directRoots.size&&(workerData.reuse.queries||[]).some(([kind,,,options])=>
|
|
34
|
+
kind==='readDirectory'&&!directRoots.has(options?.tsRoot)))throw Error('retained compiler implementation changed');
|
|
35
|
+
const queriesValid=guard===workerData.reuse.guard&&
|
|
36
|
+
(!workerData.reuse.queries?.length||queriesMatch(workerData.reuse.queries));
|
|
25
37
|
timing('worker.compiler_queries',queryStarted,{queries:workerData.reuse.queries?.length||0,matched:queriesValid?1:0});
|
|
26
38
|
if(guard!==workerData.reuse.guard||!queriesValid)reuseReason='configuration_or_resolution_changed';
|
|
27
39
|
else {
|
|
@@ -104,26 +116,14 @@ try {
|
|
|
104
116
|
const outside=new InputIndex({root:boundary,plans},{trackGit:false,includeInstalled:true});
|
|
105
117
|
outside.coldScan();
|
|
106
118
|
if(outside.unavailable)throw Error(outside.unavailable);
|
|
107
|
-
external[boundary]=
|
|
108
|
-
aliasDependencies:[...outside.aliasDependencies].map(([name,refs])=>[name,[...refs]]),
|
|
109
|
-
rows:[...outside.checks]
|
|
110
|
-
.map(([name,row])=>({name,files:[...row.files],sum:row.sum.toString('hex'),
|
|
111
|
-
revision:row.revision,lastReason:row.lastReason})),
|
|
112
|
-
eventCount:outside.eventCount,rehashedFiles:outside.rehashedFiles,
|
|
113
|
-
rehashedBytes:outside.rehashedBytes,profile:outside.profile};
|
|
119
|
+
external[boundary]=dehydrateIndex(outside);
|
|
114
120
|
}
|
|
115
121
|
timing('worker.total',totalStarted,{mode:'cold',files:index.files.size});
|
|
116
122
|
parentPort.postMessage({ok:true,bundle,discoveryMs,indexingMs,guard,planReused,
|
|
117
123
|
inputKeys:Object.fromEntries([...index.checks].map(([name,row])=>[name,inputKey(row)])),
|
|
118
124
|
restartMode:'cold-index',
|
|
119
125
|
external,
|
|
120
|
-
index:
|
|
121
|
-
aliasDependencies:[...index.aliasDependencies].map(([name,refs])=>[name,[...refs]]),
|
|
122
|
-
rows:[...index.checks].map(([name,row])=>({
|
|
123
|
-
name,files:[...row.files],sum:row.sum.toString('hex'),revision:row.revision,
|
|
124
|
-
lastReason:row.lastReason})),
|
|
125
|
-
eventCount:index.eventCount,rehashedFiles:index.rehashedFiles,
|
|
126
|
-
rehashedBytes:index.rehashedBytes,profile:index.profile}});
|
|
126
|
+
index:dehydrateIndex(index)});
|
|
127
127
|
}
|
|
128
128
|
} catch(error) {
|
|
129
129
|
parentPort.postMessage({ok:false,error:error?.message||String(error),
|
package/src/pnpm-inputs.mjs
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
//
|
|
1
|
+
// pnpm 9-12 node-modules installation provider. The engine sees only
|
|
2
2
|
// repository-relative input sets and resolution relationships, never pnpm
|
|
3
3
|
// virtual-store names as semantic identities.
|
|
4
|
+
import {probeTimeLeft} from './probe-deadline.mjs';
|
|
4
5
|
import {compilerFiles} from './typescript-list.mjs';
|
|
5
6
|
import fs from 'node:fs';
|
|
6
7
|
import path from 'node:path';
|
|
7
8
|
import {createRequire} from 'node:module';
|
|
8
9
|
import {execFileSync,spawnSync} from 'node:child_process';
|
|
9
|
-
import micromatch from './glob.mjs';
|
|
10
|
+
import micromatch,{patternMatcher} from './glob.mjs';
|
|
10
11
|
import YAML from 'yaml';
|
|
11
12
|
import {resolveLinks} from './installed-inputs.mjs';
|
|
12
13
|
import {withinPath as within,realObservedPath,samePath} from './path-identity.mjs';
|
|
13
14
|
import {timing} from './decision-profile.mjs';
|
|
15
|
+
import {npmrc} from './npmrc.mjs';
|
|
16
|
+
import {runConfig,tscRun,tscRuns} from './typescript-invocation.mjs';
|
|
14
17
|
|
|
15
18
|
const rel=(root,file)=>path.relative(root,file).split(path.sep).join('/');
|
|
16
19
|
const read=file=>JSON.parse(fs.readFileSync(file,'utf8'));
|
|
17
20
|
const exists=file=>{try{fs.lstatSync(file);return true;}catch{return false;}};
|
|
18
|
-
function yaml(file){
|
|
21
|
+
export function yaml(file){
|
|
19
22
|
const doc=YAML.parseDocument(fs.readFileSync(file,'utf8'),{uniqueKeys:true});
|
|
20
23
|
if(doc.errors.length)throw Error(`${path.basename(file)} cannot be interpreted safely`);
|
|
21
24
|
return doc.toJS()||{};
|
|
@@ -26,40 +29,67 @@ function safePatterns(values){
|
|
|
26
29
|
throw Error('pnpm workspace patterns are unsupported');
|
|
27
30
|
return values;
|
|
28
31
|
}
|
|
32
|
+
// The supported pnpm majors. pnpm 9 reads settings from .npmrc, pnpm 10 from
|
|
33
|
+
// pnpm-workspace.yaml first and then .npmrc, pnpm 11 and 12 from
|
|
34
|
+
// pnpm-workspace.yaml only.
|
|
35
|
+
export const pnpmMajors=[9,10,11,12];
|
|
36
|
+
// Settings that move or copy installed files, or run code during install,
|
|
37
|
+
// where the contract does not look; by pnpm-workspace.yaml and .npmrc name.
|
|
38
|
+
// Other settings change only what gets installed, and the installed files are
|
|
39
|
+
// what the contract observes. These are refused when either file sets them,
|
|
40
|
+
// whichever file the installed pnpm reads. Only the project's files are read:
|
|
41
|
+
// user or global rc files and npm_config_* variables at install time are not.
|
|
42
|
+
const refused=[['modulesDir','modules-dir'],['virtualStoreDir','virtual-store-dir'],['lockfileDir','lockfile-dir'],
|
|
43
|
+
['enableGlobalVirtualStore','enable-global-virtual-store'],['injectWorkspacePackages','inject-workspace-packages'],
|
|
44
|
+
['sharedWorkspaceLockfile','shared-workspace-lockfile'],['pnpmfile','pnpmfile'],['globalPnpmfile','global-pnpmfile'],
|
|
45
|
+
['configDependencies','config-dependencies']];
|
|
46
|
+
// Whether a refused setting is set: present at all, except that only
|
|
47
|
+
// sharedWorkspaceLockfile=false and injectWorkspacePackages=true move files.
|
|
48
|
+
const setting=(key,value)=>value!==undefined&&
|
|
49
|
+
(key==='sharedWorkspaceLockfile'?value===false:key==='injectWorkspacePackages'?value===true:true);
|
|
29
50
|
export function pnpmProjectInfo(root){
|
|
30
51
|
root=realObservedPath(root);
|
|
31
52
|
const pkg=read(path.join(root,'package.json'));
|
|
32
|
-
|
|
33
|
-
|
|
53
|
+
// A pin is optional; when present it names pnpm 9-12, and the install must match it.
|
|
54
|
+
const pin=pkg.packageManager===undefined?null:/^pnpm@((\d+)\.\d+\.\d+)(?:\+[^\s]+)?$/.exec(pkg.packageManager);
|
|
55
|
+
if(pkg.packageManager!==undefined&&(!pin||!pnpmMajors.includes(Number(pin[2]))))
|
|
56
|
+
throw Error(`packageManager ${JSON.stringify(String(pkg.packageManager).split('+')[0])} is outside pnpm ${pnpmMajors[0]}-${pnpmMajors.at(-1)}`);
|
|
34
57
|
const workspaceFile=path.join(root,'pnpm-workspace.yaml');
|
|
35
|
-
const
|
|
36
|
-
const patterns=safePatterns(
|
|
37
|
-
|
|
38
|
-
|
|
58
|
+
const workspace=exists(workspaceFile)?yaml(workspaceFile):{},rc=npmrc(path.join(root,'.npmrc'));
|
|
59
|
+
const patterns=safePatterns(workspace.packages||[]);
|
|
60
|
+
// The linker the given pnpm major reads; without a major, the one any reads.
|
|
61
|
+
const linkerFor=major=>(major===9?rc['node-linker']:major>=11?workspace.nodeLinker:
|
|
62
|
+
workspace.nodeLinker??rc['node-linker'])||'isolated';
|
|
63
|
+
const major=pin?Number(pin[2]):null;
|
|
64
|
+
return {version:pin?.[1]??null,linker:linkerFor(major),linkerFor,patterns,settings:workspace,
|
|
65
|
+
refused:refused.filter(([key,name])=>setting(key,workspace[key])||setting(key,rc[name])).map(([key])=>key)};
|
|
39
66
|
}
|
|
40
67
|
export function pnpmInstallInfo(root){
|
|
41
68
|
const started=performance.now();
|
|
42
69
|
root=realObservedPath(root);
|
|
43
|
-
const
|
|
44
|
-
const {version,linker,patterns,settings}=pnpmProjectInfo(root);
|
|
70
|
+
const {version,linkerFor,patterns,settings,refused}=pnpmProjectInfo(root);
|
|
45
71
|
const workspaceFile=path.join(root,'pnpm-workspace.yaml');
|
|
46
|
-
if(
|
|
47
|
-
|
|
48
|
-
throw Error('custom pnpm modules or virtual-store location is recording-only');
|
|
49
|
-
if(settings.injectWorkspacePackages)
|
|
50
|
-
throw Error('injected workspace dependencies are recording-only');
|
|
51
|
-
if(settings.sharedWorkspaceLockfile===false)
|
|
52
|
-
throw Error('separate workspace lockfiles are recording-only');
|
|
53
|
-
if(exists(path.join(root,'.pnpmfile.cjs'))||exists(path.join(root,'.pnpmfile.mjs')))
|
|
72
|
+
if(refused.some(key=>['pnpmfile','globalPnpmfile','configDependencies'].includes(key))||
|
|
73
|
+
exists(path.join(root,'.pnpmfile.cjs'))||exists(path.join(root,'.pnpmfile.mjs')))
|
|
54
74
|
throw Error('custom pnpm installation hooks need review');
|
|
75
|
+
if(refused.some(key=>['modulesDir','virtualStoreDir','lockfileDir','enableGlobalVirtualStore'].includes(key)))
|
|
76
|
+
throw Error('custom pnpm modules or virtual-store location is recording-only');
|
|
77
|
+
if(refused.includes('injectWorkspacePackages'))throw Error('injected workspace dependencies are recording-only');
|
|
78
|
+
if(refused.includes('sharedWorkspaceLockfile'))throw Error('separate workspace lockfiles are recording-only');
|
|
55
79
|
const modulesFile=path.join(root,'node_modules','.modules.yaml');
|
|
56
80
|
if(!exists(modulesFile))throw Error('installed pnpm module metadata is missing');
|
|
57
81
|
const modules=yaml(modulesFile);
|
|
58
|
-
|
|
82
|
+
const installed=/^pnpm@((\d+)\.\d+\.\d+)$/.exec(String(modules.packageManager));
|
|
83
|
+
if(!installed||!pnpmMajors.includes(Number(installed[2])))
|
|
84
|
+
throw Error(`installed by ${JSON.stringify(String(modules.packageManager))}, outside pnpm ${pnpmMajors[0]}-${pnpmMajors.at(-1)}`);
|
|
85
|
+
const linker=linkerFor(Number(installed[2]));
|
|
86
|
+
if(!['isolated','hoisted'].includes(linker))throw Error(`pnpm ${linker} linker is recording-only`);
|
|
87
|
+
if(modules.nodeLinker!==linker||version!==null&&installed[1]!==version)
|
|
59
88
|
throw Error('installed pnpm linker or version differs from project configuration');
|
|
60
89
|
const virtualStore=path.join(root,'node_modules','.pnpm');
|
|
61
|
-
// pnpm
|
|
62
|
-
//
|
|
90
|
+
// pnpm can omit virtualStoreDir when using its project-local default
|
|
91
|
+
// (seen with pnpm 12 on Windows). Accept only the observed, ordinary local
|
|
92
|
+
// directory in that case.
|
|
63
93
|
const declared=modules.virtualStoreDir;
|
|
64
94
|
const selected=declared===undefined?virtualStore:
|
|
65
95
|
path.resolve(path.dirname(modulesFile),declared);
|
|
@@ -71,18 +101,8 @@ export function pnpmInstallInfo(root){
|
|
|
71
101
|
throw Error('nonstandard or incomplete project-local pnpm virtual store');
|
|
72
102
|
if(!exists(path.join(root,'pnpm-lock.yaml')))
|
|
73
103
|
throw Error('pnpm lockfile is missing');
|
|
74
|
-
if(exists(path.join(root,'.npmrc'))){
|
|
75
|
-
// pnpm 12 reads project settings from pnpm-workspace.yaml. Registry/auth
|
|
76
|
-
// entries affect acquisition, not a completed local TypeScript invocation.
|
|
77
|
-
for(const line of fs.readFileSync(path.join(root,'.npmrc'),'utf8').split(/\r?\n/)){
|
|
78
|
-
const trimmed=line.trim();if(!trimmed||/^[#;]/.test(trimmed))continue;
|
|
79
|
-
const key=trimmed.split('=')[0].trim();
|
|
80
|
-
if(key!=='registry'&&!/^\/\/[^\s]+\/:_authToken$/.test(key))
|
|
81
|
-
throw Error('project .npmrc has execution-relevant pnpm settings requiring review');
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
104
|
timing('pnpm.install_metadata',started);
|
|
85
|
-
return {version,linker,patterns,settings,modulesFile,
|
|
105
|
+
return {version:installed[1],linker,patterns,settings,modulesFile,
|
|
86
106
|
configurationInputs:['package.json','pnpm-lock.yaml',
|
|
87
107
|
...(exists(workspaceFile)?['pnpm-workspace.yaml']:[]),
|
|
88
108
|
...(exists(path.join(root,'.npmrc'))?['.npmrc']:[]),
|
|
@@ -96,7 +116,7 @@ export function pnpmWorkspacePackages(root,patterns){
|
|
|
96
116
|
const files=execFileSync('git',['ls-files','--cached','--others','--exclude-standard',
|
|
97
117
|
'-z','--',':(glob)**/package.json'],{cwd:root,
|
|
98
118
|
env:{...process.env,GIT_OPTIONAL_LOCKS:'0'},maxBuffer:32*1024*1024,
|
|
99
|
-
timeout:5000}).toString().split('\0').filter(Boolean);
|
|
119
|
+
timeout:probeTimeLeft(5000)}).toString().split('\0').filter(Boolean);
|
|
100
120
|
for(const file of files){
|
|
101
121
|
const dir=path.posix.dirname(file);
|
|
102
122
|
if(dir==='.'||dir.split('/').includes('node_modules')||
|
|
@@ -172,16 +192,37 @@ function packageAt(root,requester,name){
|
|
|
172
192
|
}
|
|
173
193
|
return {physical:null,candidates};
|
|
174
194
|
}
|
|
175
|
-
|
|
176
|
-
|
|
195
|
+
// Files TypeScript may consume from its own include: each directory its
|
|
196
|
+
// include patterns watch for new files (TypeScript's own
|
|
197
|
+
// wildcardDirectories), and each file it lists. node_modules below them is
|
|
198
|
+
// left out, as TypeScript's wildcards leave it out; installed files a program
|
|
199
|
+
// reads are installed inputs. `exclude` entries stay inputs: an import can
|
|
200
|
+
// still reach an excluded file.
|
|
201
|
+
const sourceFiles='*.{ts,tsx,mts,cts,js,jsx,mjs,cjs,json}';
|
|
202
|
+
function sourcePatterns(root,parsed){
|
|
203
|
+
const patterns=new Set(),excluded=new Set();
|
|
204
|
+
for(const [folder,flags] of Object.entries(parsed.wildcardDirectories||{})){
|
|
205
|
+
// TypeScript 4 lowercases these keys on case-insensitive file systems;
|
|
206
|
+
// the native realpath gives the directory's own spelling.
|
|
207
|
+
let at;try{at=fs.realpathSync.native(folder);}catch{at=path.resolve(folder);}
|
|
208
|
+
if(!within(at,root))throw Error('TypeScript source membership escapes the checkout');
|
|
209
|
+
const prefix=rel(root,at)?rel(root,at)+'/':'';
|
|
210
|
+
if(flags&1){patterns.add(`${prefix}**/${sourceFiles}`);excluded.add(`!${prefix}**/node_modules/**`);}
|
|
211
|
+
else patterns.add(prefix+sourceFiles);
|
|
212
|
+
}
|
|
213
|
+
const included=patternMatcher([...patterns,...excluded]);
|
|
214
|
+
for(const file of parsed.fileNames.map(name=>path.resolve(name))){
|
|
215
|
+
if(!within(file,root))throw Error('TypeScript source membership escapes the checkout');
|
|
216
|
+
if(!included(rel(root,file)))patterns.add(rel(root,file));
|
|
217
|
+
}
|
|
218
|
+
return [...patterns,...excluded];
|
|
219
|
+
}
|
|
220
|
+
function parsedTypeScript(root,dir,ts,configName='tsconfig.json'){
|
|
221
|
+
const config=path.join(root,dir,configName),reads=new Set();
|
|
177
222
|
const host={...ts.sys,readFile(file){reads.add(path.resolve(file));return ts.sys.readFile(file);},
|
|
178
223
|
onUnRecoverableConfigFileDiagnostic(){}};
|
|
179
224
|
const parsed=ts.getParsedCommandLineOfConfigFile(config,{},host);
|
|
180
225
|
if(!parsed||parsed.errors?.length)throw Error('TypeScript configuration unavailable');
|
|
181
|
-
const raw=ts.readConfigFile(config,ts.sys.readFile);
|
|
182
|
-
if(raw.error||!Array.isArray(raw.config?.include)||raw.config.include.length!==1||
|
|
183
|
-
!/^src(?:$|\/)/.test(raw.config.include[0]))
|
|
184
|
-
throw Error('TypeScript source file membership is outside the supported src include');
|
|
185
226
|
if(parsed.options.plugins?.length||parsed.options.incremental||parsed.options.composite||
|
|
186
227
|
parsed.projectReferences?.length||parsed.options.paths||parsed.options.baseUrl||
|
|
187
228
|
parsed.options.rootDirs?.length||parsed.options.typeRoots?.length||
|
|
@@ -193,16 +234,17 @@ function parsedTypeScript(root,dir,ts){
|
|
|
193
234
|
throw Error('TypeScript module resolver is outside the supported Node contract');
|
|
194
235
|
for(const file of reads)if(!within(realObservedPath(file),root))
|
|
195
236
|
throw Error('TypeScript configuration escapes the checkout');
|
|
196
|
-
return {parsed,configs:[...reads].map(file=>rel(root,file)).sort()
|
|
237
|
+
return {parsed,configs:[...reads].map(file=>rel(root,file)).sort(),
|
|
238
|
+
sourcePatterns:sourcePatterns(root,parsed)};
|
|
197
239
|
}
|
|
198
|
-
function listedTypeScriptFiles(root,selected,tsc){
|
|
240
|
+
function listedTypeScriptFiles(root,selected,tsc,configName){
|
|
199
241
|
// --listFilesOnly resolves the compiler's effective module/file set but
|
|
200
242
|
// performs no typecheck and emits no project outputs.
|
|
201
|
-
const out=spawnSync(process.execPath,[tsc,'-p',
|
|
243
|
+
const out=spawnSync(process.execPath,[tsc,'-p',configName,'--listFilesOnly'],
|
|
202
244
|
{cwd:path.join(root,selected.dir),env:process.env,encoding:'utf8',
|
|
203
245
|
// The native NTFS public workspace takes 3-5 s to list ~770 inputs;
|
|
204
246
|
// 5 s sometimes expired despite bounded, progressing compiler work.
|
|
205
|
-
timeout:10000,maxBuffer:32*1024*1024,stdio:['ignore','pipe','pipe']});
|
|
247
|
+
timeout:probeTimeLeft(10000),maxBuffer:32*1024*1024,stdio:['ignore','pipe','pipe']});
|
|
206
248
|
if(out.error||out.signal||out.status!==0)
|
|
207
249
|
throw Error('TypeScript input listing is unavailable');
|
|
208
250
|
const files=out.stdout.trim().split(/\r?\n/).filter(Boolean)
|
|
@@ -235,17 +277,23 @@ function sharedHardlinkIn(folder){
|
|
|
235
277
|
}
|
|
236
278
|
return false;
|
|
237
279
|
}
|
|
238
|
-
|
|
280
|
+
// `run`: the check's {script, part, args}, or a script name for its only run.
|
|
281
|
+
export function pnpmTypecheckInputs(root,workspace,run,{captureQueries=false}={}){
|
|
239
282
|
const totalStarted=performance.now();
|
|
240
283
|
root=realObservedPath(root);
|
|
241
284
|
const install=pnpmInstallInfo(root),members=pnpmWorkspacePackages(root,install.patterns);
|
|
242
285
|
const selected=workspace==='.'?{name:'.',dir:'.',manifest:'package.json',
|
|
243
286
|
pkg:read(path.join(root,'package.json'))}:members.get(workspace);
|
|
244
287
|
if(!selected)throw Error(`workspace ${workspace} is not declared`);
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
288
|
+
// A script name stands for its only run.
|
|
289
|
+
if(typeof run==='string'){const runs=tscRuns(selected.pkg.scripts?.[run]);run={script:run,args:runs?.length===1?runs[0].args:[]};}
|
|
290
|
+
const {run:own,issue}=tscRun(selected.pkg.scripts,run);
|
|
291
|
+
if(issue)throw Error(`typecheck must be standalone TypeScript runs: ${issue}`);
|
|
292
|
+
// `tsc -p .` without --noEmit predates the other forms.
|
|
293
|
+
if(!own.noEmit&&!['-p .','-p tsconfig.json'].includes(run.args.join(' ')))
|
|
294
|
+
throw Error('typecheck must pass --noEmit');
|
|
295
|
+
const configName=runConfig(path.join(root,selected.dir),run.args);
|
|
296
|
+
if(!configName)throw Error('TypeScript project is outside the package');
|
|
249
297
|
const selectedDir=path.join(root,selected.dir),lookup=createRequire(path.join(selectedDir,'package.json'));
|
|
250
298
|
let tsPackage;try{tsPackage=realObservedPath(lookup.resolve('typescript/package.json'));}
|
|
251
299
|
catch{throw Error('installed TypeScript compiler cannot be resolved');}
|
|
@@ -254,7 +302,8 @@ export function pnpmTypecheckInputs(root,workspace,script,{captureQueries=false}
|
|
|
254
302
|
const tsc=path.join(tsRoot,'bin','tsc');
|
|
255
303
|
if(!exists(tsc))throw Error('installed TypeScript executable is missing');
|
|
256
304
|
const configStarted=performance.now();
|
|
257
|
-
const {configs}=parsedTypeScript(root,selected.dir,ts);
|
|
305
|
+
const {configs,sourcePatterns:sources}=parsedTypeScript(root,selected.dir,ts,configName);
|
|
306
|
+
const isSource=patternMatcher(sources);
|
|
258
307
|
timing('pnpm.ts_config',configStarted,{configs:configs.length});
|
|
259
308
|
const closure=new Map(),installed=new Set(),generated=new Set(),
|
|
260
309
|
links=new Set(),candidates=new Set(),absences=[],instances=new Map();
|
|
@@ -304,12 +353,12 @@ export function pnpmTypecheckInputs(root,workspace,script,{captureQueries=false}
|
|
|
304
353
|
resolutionMs:Math.round(resolutionMs),workspaceLinks:links.size,
|
|
305
354
|
candidates:candidates.size});
|
|
306
355
|
const listingStarted=performance.now();
|
|
307
|
-
const captured=captureQueries?compilerFiles(tsRoot,path.join(root,selected.dir)):null;
|
|
308
|
-
const files=captured?captured.files.map(realObservedPath):listedTypeScriptFiles(root,selected,tsc);
|
|
356
|
+
const captured=captureQueries?compilerFiles(tsRoot,path.join(root,selected.dir),configName):null;
|
|
357
|
+
const files=captured?captured.files.map(realObservedPath):listedTypeScriptFiles(root,selected,tsc,configName);
|
|
309
358
|
timing('pnpm.ts_input_listing',listingStarted,{files:files.length});
|
|
310
359
|
const mappingStarted=performance.now();
|
|
311
360
|
for(const file of files){
|
|
312
|
-
if(
|
|
361
|
+
if(isSource(rel(root,file))||
|
|
313
362
|
[...closure.values()].some(member=>within(file,path.join(root,member.dir))))continue;
|
|
314
363
|
const packageRoot=installedPackageRoot(root,file);
|
|
315
364
|
if(!packageRoot)throw Error(`TypeScript consumes a file outside the observed pnpm contract: ${rel(root,file)}`);
|
|
@@ -320,6 +369,16 @@ export function pnpmTypecheckInputs(root,workspace,script,{captureQueries=false}
|
|
|
320
369
|
}
|
|
321
370
|
timing('pnpm.input_mapping',mappingStarted,{instances:instances.size,
|
|
322
371
|
installedPatterns:installed.size});
|
|
372
|
+
// A config extended from an installed package is an installed input too:
|
|
373
|
+
// source patterns leave node_modules out.
|
|
374
|
+
for(const config of configs){
|
|
375
|
+
const file=realObservedPath(path.join(root,config));
|
|
376
|
+
if(!within(file,path.join(root,'node_modules')))continue;
|
|
377
|
+
const packageRoot=installedPackageRoot(root,file);
|
|
378
|
+
if(!packageRoot)throw Error(`TypeScript configuration ${config} is outside an installed package`);
|
|
379
|
+
installed.add(`${rel(root,packageRoot)}/**`);
|
|
380
|
+
installed.add(`!${rel(root,packageRoot)}/node_modules/**`);
|
|
381
|
+
}
|
|
323
382
|
installed.add(`${rel(root,tsRoot)}/**`);
|
|
324
383
|
installed.add(`!${rel(root,tsRoot)}/node_modules/**`);
|
|
325
384
|
if(!instances.has(tsRoot))instances.set(tsRoot,{name:'typescript',physicalRoot:rel(root,tsRoot)});
|
|
@@ -328,11 +387,12 @@ export function pnpmTypecheckInputs(root,workspace,script,{captureQueries=false}
|
|
|
328
387
|
timing('pnpm.hardlink_inspection',sharedStarted,{instances:instances.size,
|
|
329
388
|
shared:shared.length});
|
|
330
389
|
const source=[...new Set([...install.configurationInputs,selected.manifest,
|
|
331
|
-
...configs
|
|
390
|
+
...configs,...sources,
|
|
332
391
|
...closure.values().map(member=>member.manifest),...generated])];
|
|
333
392
|
timing('pnpm.total_discovery',totalStarted,{instances:instances.size,
|
|
334
393
|
inputFiles:files.length});
|
|
335
394
|
return {install,workspace:selected,closure:[...closure.values()],source,
|
|
395
|
+
sourcePatterns:sources,args:run.args,
|
|
336
396
|
installed:[...installed],generated:[...generated],
|
|
337
397
|
// The read-only state probe consumes this same resolved compiler file set.
|
|
338
398
|
// It is deliberately omitted from the persisted user-facing input plan.
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": 1,
|
|
3
|
+
"templates": [
|
|
4
|
+
{
|
|
5
|
+
"versions": [
|
|
6
|
+
"8.0.0",
|
|
7
|
+
"8.1.1",
|
|
8
|
+
"8.2.0",
|
|
9
|
+
"8.3.1",
|
|
10
|
+
"8.4.0",
|
|
11
|
+
"8.5.1",
|
|
12
|
+
"8.6.12",
|
|
13
|
+
"8.7.6",
|
|
14
|
+
"8.8.0",
|
|
15
|
+
"8.9.2",
|
|
16
|
+
"8.10.5",
|
|
17
|
+
"8.11.0",
|
|
18
|
+
"8.12.1",
|
|
19
|
+
"8.13.1",
|
|
20
|
+
"8.14.3",
|
|
21
|
+
"8.15.9",
|
|
22
|
+
"9.0.6",
|
|
23
|
+
"9.1.4",
|
|
24
|
+
"9.2.0",
|
|
25
|
+
"9.3.0",
|
|
26
|
+
"9.4.0",
|
|
27
|
+
"9.5.0",
|
|
28
|
+
"9.6.0",
|
|
29
|
+
"9.7.1",
|
|
30
|
+
"9.8.0",
|
|
31
|
+
"9.9.0",
|
|
32
|
+
"9.10.0",
|
|
33
|
+
"9.11.0",
|
|
34
|
+
"9.12.3",
|
|
35
|
+
"9.13.2",
|
|
36
|
+
"9.14.4",
|
|
37
|
+
"9.15.4",
|
|
38
|
+
"9.15.9",
|
|
39
|
+
"10.0.0",
|
|
40
|
+
"10.1.0",
|
|
41
|
+
"10.2.1",
|
|
42
|
+
"10.3.0",
|
|
43
|
+
"10.4.1",
|
|
44
|
+
"10.5.2",
|
|
45
|
+
"10.6.5",
|
|
46
|
+
"10.7.1",
|
|
47
|
+
"10.8.1",
|
|
48
|
+
"10.9.0"
|
|
49
|
+
],
|
|
50
|
+
"template": "#!/bin/sh\nbasedir=$(dirname \"$(echo \"$0\" | sed -e 's,\\\\,/,g')\")\n\ncase `uname` in\n *CYGWIN*) basedir=`cygpath -w \"$basedir\"`;;\nesac\n\nif [ -z \"$NODE_PATH\" ]; then\n export NODE_PATH=\"@@NODE_PATH@@\"\nelse\n export NODE_PATH=\"@@NODE_PATH@@:$NODE_PATH\"\nfi\nif [ -x \"$basedir/node\" ]; then\n exec \"$basedir/node\" \"$basedir/@@TARGET@@\" \"$@\"\nelse\n exec node \"$basedir/@@TARGET@@\" \"$@\"\nfi\n"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"versions": [
|
|
54
|
+
"10.10.0",
|
|
55
|
+
"10.11.1",
|
|
56
|
+
"10.12.4",
|
|
57
|
+
"10.13.1",
|
|
58
|
+
"10.14.0",
|
|
59
|
+
"10.15.1",
|
|
60
|
+
"10.16.1",
|
|
61
|
+
"10.17.1",
|
|
62
|
+
"10.18.3",
|
|
63
|
+
"10.19.0",
|
|
64
|
+
"10.20.0",
|
|
65
|
+
"10.21.0",
|
|
66
|
+
"10.22.0",
|
|
67
|
+
"10.23.0",
|
|
68
|
+
"10.24.0",
|
|
69
|
+
"10.25.0",
|
|
70
|
+
"10.26.2",
|
|
71
|
+
"10.27.0",
|
|
72
|
+
"10.28.2",
|
|
73
|
+
"10.29.3",
|
|
74
|
+
"10.30.3",
|
|
75
|
+
"10.31.0",
|
|
76
|
+
"10.32.1",
|
|
77
|
+
"10.33.2",
|
|
78
|
+
"10.33.4",
|
|
79
|
+
"10.34.7"
|
|
80
|
+
],
|
|
81
|
+
"template": "#!/bin/sh\nbasedir=$(dirname \"$(echo \"$0\" | sed -e 's,\\\\,/,g')\")\n\ncase `uname` in\n *CYGWIN*|*MINGW*|*MSYS*)\n if command -v cygpath > /dev/null 2>&1; then\n basedir=`cygpath -w \"$basedir\"`\n fi\n ;;\nesac\n\nif [ -z \"$NODE_PATH\" ]; then\n export NODE_PATH=\"@@NODE_PATH@@\"\nelse\n export NODE_PATH=\"@@NODE_PATH@@:$NODE_PATH\"\nfi\nif [ -x \"$basedir/node\" ]; then\n exec \"$basedir/node\" \"$basedir/@@TARGET@@\" \"$@\"\nelse\n exec node \"$basedir/@@TARGET@@\" \"$@\"\nfi\n"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"versions": [
|
|
85
|
+
"11.0.9",
|
|
86
|
+
"11.1.1",
|
|
87
|
+
"11.1.3",
|
|
88
|
+
"11.2.2",
|
|
89
|
+
"11.3.0",
|
|
90
|
+
"11.4.0",
|
|
91
|
+
"11.5.3",
|
|
92
|
+
"11.6.0"
|
|
93
|
+
],
|
|
94
|
+
"template": "#!/bin/sh\nbasedir=$(dirname \"$(echo \"$0\" | sed -e 's,\\\\,/,g')\")\n\ncase `uname` in\n *CYGWIN*|*MINGW*|*MSYS*)\n if command -v cygpath > /dev/null 2>&1; then\n basedir=`cygpath -w \"$basedir\"`\n fi\n ;;\nesac\n\nif [ -z \"$NODE_PATH\" ]; then\n export NODE_PATH=\"@@NODE_PATH@@\"\nelse\n export NODE_PATH=\"@@NODE_PATH@@:$NODE_PATH\"\nfi\nif [ -x \"$basedir/node\" ]; then\n exec \"$basedir/node\" \"$basedir/@@TARGET@@\" \"$@\"\nelse\n exec node \"$basedir/@@TARGET@@\" \"$@\"\nfi\n# cmd-shim-target=@@COMMENT@@\n"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"versions": [
|
|
98
|
+
"11.7.0",
|
|
99
|
+
"11.8.0",
|
|
100
|
+
"11.9.0",
|
|
101
|
+
"11.10.0",
|
|
102
|
+
"11.11.0",
|
|
103
|
+
"11.12.0",
|
|
104
|
+
"11.13.1",
|
|
105
|
+
"11.14.0",
|
|
106
|
+
"11.15.1",
|
|
107
|
+
"11.16.0",
|
|
108
|
+
"11.17.0",
|
|
109
|
+
"11.18.0",
|
|
110
|
+
"11.19.0",
|
|
111
|
+
"11.20.0"
|
|
112
|
+
],
|
|
113
|
+
"template": "#!/bin/sh\nbasedir=$(dirname \"$(echo \"$0\" | sed -e 's,\\\\,/,g')\")\nbasedir_win=\"$basedir\"\nexe=\"\"\nmsys=\"\"\n\ncase `uname -a` in\n *CYGWIN*|*MINGW*|*MSYS*)\n if command -v cygpath > /dev/null 2>&1; then\n basedir_win=`cygpath -w \"$basedir\"`\n fi\n exe=\".exe\"\n msys=\"true\"\n ;;\n *WSL2*)\n if command -v wslpath > /dev/null 2>&1; then\n basedir_win=\"$(wslpath -w \"$basedir\" 2> /dev/null)\"\n if [ $? -ne 0 ] || [ -z \"$basedir_win\" ]; then\n basedir_win=\"$basedir\"\n else\n exe=\".exe\"\n fi\n fi\n ;;\nesac\n\nif [ -z \"$NODE_PATH\" ]; then\n export NODE_PATH=\"@@NODE_PATH@@\"\nelse\n export NODE_PATH=\"@@NODE_PATH@@:$NODE_PATH\"\nfi\nif [ -n \"$exe\" ] && [ -x \"$basedir/node.exe\" ]; then\n exec \"$basedir/node.exe\" \"$basedir_win/@@TARGET@@\" \"$@\"\nelif [ -x \"$basedir/node\" ]; then\n exec \"$basedir/node\" \"$basedir/@@TARGET@@\" \"$@\"\nelif command -v node >/dev/null 2>&1; then\n exec node \"$basedir/@@TARGET@@\" \"$@\"\nelif [ -n \"$exe\" ] && command -v node.exe >/dev/null 2>&1; then\n exec node.exe \"$basedir_win/@@TARGET@@\" \"$@\"\nelse\n exec node \"$basedir/@@TARGET@@\" \"$@\"\nfi\n# cmd-shim-target=@@COMMENT@@\n"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"versions": [
|
|
117
|
+
"11.21.0",
|
|
118
|
+
"11.22.0",
|
|
119
|
+
"11.23.0",
|
|
120
|
+
"11.24.0",
|
|
121
|
+
"11.25.0",
|
|
122
|
+
"11.26.0",
|
|
123
|
+
"12.0.0",
|
|
124
|
+
"12.1.0",
|
|
125
|
+
"12.2.1",
|
|
126
|
+
"12.3.4"
|
|
127
|
+
],
|
|
128
|
+
"template": "#!/bin/sh\n# Resolve $0 through symlinks so basedir is the shim's real directory.\n# Cap hops at the kernel's ELOOP limit so a cycle cannot hang the shim.\nlink=\"$0\"\nhops=0\nwhile [ -L \"$link\" ] && [ \"$hops\" -lt 40 ]; do\n hops=$((hops+1))\n target=$(readlink \"$link\")\n case \"$target\" in\n /*) link=\"$target\" ;;\n *) link=\"$(dirname \"$link\")/$target\" ;;\n esac\ndone\nbasedir=$(dirname \"$(echo \"$link\" | sed -e 's,\\\\,/,g')\")\nbasedir_win=\"$basedir\"\nexe=\"\"\nmsys=\"\"\n\ncase `uname -a` in\n *CYGWIN*|*MINGW*|*MSYS*)\n if command -v cygpath > /dev/null 2>&1; then\n basedir_win=`cygpath -w \"$basedir\"`\n fi\n exe=\".exe\"\n msys=\"true\"\n ;;\n *WSL2*)\n if command -v wslpath > /dev/null 2>&1; then\n basedir_win=\"$(wslpath -w \"$basedir\" 2> /dev/null)\"\n if [ $? -ne 0 ] || [ -z \"$basedir_win\" ]; then\n basedir_win=\"$basedir\"\n else\n exe=\".exe\"\n fi\n fi\n ;;\nesac\n\nif [ -z \"$NODE_PATH\" ]; then\n export NODE_PATH=\"@@NODE_PATH@@\"\nelse\n export NODE_PATH=\"@@NODE_PATH@@:$NODE_PATH\"\nfi\nif [ -n \"$exe\" ] && [ -x \"$basedir/node.exe\" ]; then\n exec \"$basedir/node.exe\" \"$basedir_win/@@TARGET@@\" \"$@\"\nelif [ -x \"$basedir/node\" ]; then\n exec \"$basedir/node\" \"$basedir/@@TARGET@@\" \"$@\"\nelif command -v node >/dev/null 2>&1; then\n exec node \"$basedir/@@TARGET@@\" \"$@\"\nelif [ -n \"$exe\" ] && command -v node.exe >/dev/null 2>&1; then\n exec node.exe \"$basedir_win/@@TARGET@@\" \"$@\"\nelse\n exec node \"$basedir/@@TARGET@@\" \"$@\"\nfi\n# cmd-shim-target=@@COMMENT@@\n"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"versions": [
|
|
132
|
+
"11.27.1"
|
|
133
|
+
],
|
|
134
|
+
"template": "#!/bin/sh\n# Resolve $0 through symlinks so basedir is the shim's real directory.\n# Cap hops at the kernel's ELOOP limit so a cycle cannot hang the shim.\n#\n# A shim runs with node_modules/.bin at the front of PATH, so readlink, sed,\n# uname, and printf go through `command -p`, which searches the system default\n# path instead. A dependency's bin cannot stand in for one of them and take over\n# the shim before it reaches its target. Directories come from `${link%/*}`,\n# which needs no helper at all.\nlink=\"$0\"\n# `${link%/*}` needs a separator to strip. A bare name came from a PATH lookup\n# and stands for a file in the current directory.\ncase \"$link\" in\n */*|*\\\\*) ;;\n *) link=\"./$link\" ;;\nesac\nhops=0\nwhile [ -L \"$link\" ] && [ \"$hops\" -lt 40 ]; do\n hops=$((hops+1))\n target=$(command -p readlink \"$link\")\n case \"$target\" in\n /*) link=\"$target\" ;;\n *) link=\"${link%/*}/$target\" ;;\n esac\ndone\nbasedir=$(command -p printf '%s\\n' \"$link\" | command -p sed -e 's,\\\\,/,g')\nbasedir=\"${basedir%/*}\"\nbasedir_win=\"$basedir\"\nexe=\"\"\nmsys=\"\"\n\ncase `command -p uname -a` in\n *CYGWIN*|*MINGW*|*MSYS*)\n if converted=$(command -p cygpath -w \"$basedir\" 2>/dev/null) && [ -n \"$converted\" ]; then\n basedir_win=\"$converted\"\n elif command -v cygpath > /dev/null 2>&1; then\n basedir_win=`cygpath -w \"$basedir\"`\n fi\n exe=\".exe\"\n msys=\"true\"\n ;;\n *WSL2*)\n if converted=$(command -p wslpath -w \"$basedir\" 2>/dev/null) && [ -n \"$converted\" ]; then\n basedir_win=\"$converted\"\n exe=\".exe\"\n elif command -v wslpath > /dev/null 2>&1; then\n basedir_win=\"$(wslpath -w \"$basedir\" 2> /dev/null)\"\n if [ $? -ne 0 ] || [ -z \"$basedir_win\" ]; then\n basedir_win=\"$basedir\"\n else\n exe=\".exe\"\n fi\n fi\n ;;\nesac\n\nif [ -z \"$NODE_PATH\" ]; then\n export NODE_PATH=\"@@NODE_PATH@@\"\nelse\n export NODE_PATH=\"@@NODE_PATH@@:$NODE_PATH\"\nfi\nif [ -n \"$exe\" ] && [ -x \"$basedir/node.exe\" ]; then\n exec \"$basedir/node.exe\" \"$basedir_win/@@TARGET@@\" \"$@\"\nelif [ -x \"$basedir/node\" ]; then\n exec \"$basedir/node\" \"$basedir/@@TARGET@@\" \"$@\"\nelif command -v node >/dev/null 2>&1; then\n exec node \"$basedir/@@TARGET@@\" \"$@\"\nelif [ -n \"$exe\" ] && command -v node.exe >/dev/null 2>&1; then\n exec node.exe \"$basedir_win/@@TARGET@@\" \"$@\"\nelse\n exec node \"$basedir/@@TARGET@@\" \"$@\"\nfi\n# cmd-shim-target=@@COMMENT@@\n"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"versions": [
|
|
138
|
+
"11.28.2"
|
|
139
|
+
],
|
|
140
|
+
"template": "#!/bin/sh\n# Resolve $0 through symlinks so basedir is the shim's real directory.\n# Cap hops at the kernel's ELOOP limit so a cycle cannot hang the shim.\n#\n# A shim runs with node_modules/.bin at the front of PATH, so readlink, sed,\n# uname, and printf go through `command -p`, which searches the system default\n# path instead. A dependency's bin cannot stand in for one of them and take over\n# the shim before it reaches its target. Directories come from `${link%/*}`,\n# which needs no helper at all.\n#\n# Where no default path is compiled in, as on Nix, `command -p` searches PATH\n# instead, so the helpers run with node_modules and relative entries dropped from\n# PATH.\ncaller_path_set=${PATH+set}\ncaller_path=${PATH-}\nhelper_path=\nrest=$caller_path:\nwhile [ -n \"$rest\" ]; do\n dir=${rest%%:*}\n rest=${rest#*:}\n case \"$dir\" in\n */node_modules/*|*/node_modules) ;;\n /*) helper_path=${helper_path:+$helper_path:}$dir ;;\n esac\ndone\n# An empty PATH searches the current directory.\nPATH=${helper_path:-/}\nlink=\"$0\"\n# `${link%/*}` needs a separator to strip. A bare name came from a PATH lookup\n# and stands for a file in the current directory.\ncase \"$link\" in\n */*|*\\\\*) ;;\n *) link=\"./$link\" ;;\nesac\nhops=0\nwhile [ -L \"$link\" ] && [ \"$hops\" -lt 40 ]; do\n hops=$((hops+1))\n target=$(command -p readlink \"$link\")\n case \"$target\" in\n /*) link=\"$target\" ;;\n *) link=\"${link%/*}/$target\" ;;\n esac\ndone\nbasedir=$(command -p printf '%s\\n' \"$link\" | command -p sed -e 's,\\\\,/,g')\nbasedir=\"${basedir%/*}\"\nbasedir_abs=$(CDPATH= cd -P -- \"$basedir\" && pwd -P) || exit $?\nbasedir=\"$basedir_abs\"\nbasedir_win=\"$basedir\"\nexe=\"\"\nmsys=\"\"\n\ncase `command -p uname -a` in\n *CYGWIN*|*MINGW*|*MSYS*)\n if converted=$(command -p cygpath -w \"$basedir\" 2>/dev/null) && [ -n \"$converted\" ]; then\n basedir_win=\"$converted\"\n elif command -v cygpath > /dev/null 2>&1; then\n basedir_win=`cygpath -w \"$basedir\"`\n fi\n exe=\".exe\"\n msys=\"true\"\n ;;\n *WSL2*)\n if converted=$(command -p wslpath -w \"$basedir\" 2>/dev/null) && [ -n \"$converted\" ]; then\n basedir_win=\"$converted\"\n exe=\".exe\"\n elif command -v wslpath > /dev/null 2>&1; then\n basedir_win=\"$(wslpath -w \"$basedir\" 2> /dev/null)\"\n if [ $? -ne 0 ] || [ -z \"$basedir_win\" ]; then\n basedir_win=\"$basedir\"\n else\n exe=\".exe\"\n fi\n fi\n ;;\nesac\nif [ -n \"$caller_path_set\" ]; then PATH=$caller_path; else unset PATH; fi\n\nif [ -z \"$NODE_PATH\" ]; then\n export NODE_PATH=\"@@NODE_PATH@@\"\nelse\n export NODE_PATH=\"@@NODE_PATH@@:$NODE_PATH\"\nfi\nif [ -n \"$exe\" ] && [ -x \"$basedir/node.exe\" ]; then\n exec \"$basedir/node.exe\" \"$basedir_win/@@TARGET@@\" \"$@\"\nelif [ -x \"$basedir/node\" ]; then\n exec \"$basedir/node\" \"$basedir_abs/@@TARGET@@\" \"$@\"\nelif [ -n \"$msys\" ] && command -v node >/dev/null 2>&1; then\n exec node \"$basedir_win/@@TARGET@@\" \"$@\"\nelif command -v node >/dev/null 2>&1; then\n exec node \"$basedir_abs/@@TARGET@@\" \"$@\"\nelif [ -n \"$exe\" ] && command -v node.exe >/dev/null 2>&1; then\n exec node.exe \"$basedir_win/@@TARGET@@\" \"$@\"\nelse\n exec node \"$basedir_abs/@@TARGET@@\" \"$@\"\nfi\n# cmd-shim-target=@@COMMENT@@\n"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"versions": [
|
|
144
|
+
"11.28.6",
|
|
145
|
+
"12.8.2",
|
|
146
|
+
"12.9.1",
|
|
147
|
+
"12.10.1",
|
|
148
|
+
"12.11.2",
|
|
149
|
+
"12.12.1",
|
|
150
|
+
"12.13.0",
|
|
151
|
+
"12.14.0"
|
|
152
|
+
],
|
|
153
|
+
"template": "#!/bin/sh\n# Resolve $0 through symlinks so basedir is the shim's real directory.\n# Cap hops at the kernel's ELOOP limit so a cycle cannot hang the shim.\n#\n# A shim runs with node_modules/.bin at the front of PATH, so readlink, sed,\n# uname, and printf go through `command -p`, which searches the system default\n# path instead. A dependency's bin cannot stand in for one of them and take over\n# the shim before it reaches its target. Directories come from `${link%/*}`,\n# which needs no helper at all.\n#\n# A helper the default path lacks, as in a Nix build sandbox, comes from PATH\n# instead, with node_modules and relative entries dropped from it.\ncaller_path_set=${PATH+set}\ncaller_path=${PATH-}\nhelper_path=\nrest=$caller_path:\nwhile [ -n \"$rest\" ]; do\n dir=${rest%%:*}\n rest=${rest#*:}\n case \"$dir\" in\n */node_modules/*|*/node_modules) ;;\n /*) helper_path=${helper_path:+$helper_path:}$dir ;;\n esac\ndone\n# An empty PATH searches the current directory.\nPATH=${helper_path:-/}\n# A helper comes from PATH only when the default path lacks it and PATH has it.\n# The bash 3.2 that macOS ships as sh answers `command -p -v` from PATH.\nrun_helper() {\n if command -p -v \"$1\" >/dev/null 2>&1 || ! command -v \"$1\" >/dev/null 2>&1; then command -p \"$@\"; else command \"$@\"; fi\n}\nlink=\"$0\"\n# `${link%/*}` needs a separator to strip. A bare name came from a PATH lookup\n# and stands for a file in the current directory.\ncase \"$link\" in\n */*|*\\\\*) ;;\n *) link=\"./$link\" ;;\nesac\nhops=0\nwhile [ -L \"$link\" ] && [ \"$hops\" -lt 40 ]; do\n hops=$((hops+1))\n target=$(run_helper readlink \"$link\")\n case \"$target\" in\n /*) link=\"$target\" ;;\n *) link=\"${link%/*}/$target\" ;;\n esac\ndone\nbasedir=$(run_helper printf '%s\\n' \"$link\" | run_helper sed -e 's,\\\\,/,g')\nbasedir=\"${basedir%/*}\"\nbasedir_abs=$(CDPATH= cd -P -- \"$basedir\" && pwd -P) || exit $?\nbasedir=\"$basedir_abs\"\nbasedir_win=\"$basedir\"\nexe=\"\"\nmsys=\"\"\n\ncase `run_helper uname -a` in\n *CYGWIN*|*MINGW*|*MSYS*)\n if converted=$(command -p cygpath -w \"$basedir\" 2>/dev/null) && [ -n \"$converted\" ]; then\n basedir_win=\"$converted\"\n elif command -v cygpath > /dev/null 2>&1; then\n basedir_win=`cygpath -w \"$basedir\"`\n fi\n exe=\".exe\"\n msys=\"true\"\n ;;\n *WSL2*)\n if converted=$(command -p wslpath -w \"$basedir\" 2>/dev/null) && [ -n \"$converted\" ]; then\n basedir_win=\"$converted\"\n exe=\".exe\"\n elif command -v wslpath > /dev/null 2>&1; then\n basedir_win=\"$(wslpath -w \"$basedir\" 2> /dev/null)\"\n if [ $? -ne 0 ] || [ -z \"$basedir_win\" ]; then\n basedir_win=\"$basedir\"\n else\n exe=\".exe\"\n fi\n fi\n ;;\nesac\nif [ -n \"$caller_path_set\" ]; then PATH=$caller_path; else unset PATH; fi\n\nif [ -z \"$NODE_PATH\" ]; then\n export NODE_PATH=\"@@NODE_PATH@@\"\nelse\n export NODE_PATH=\"@@NODE_PATH@@:$NODE_PATH\"\nfi\nif [ -n \"$exe\" ] && [ -x \"$basedir/node.exe\" ]; then\n exec \"$basedir/node.exe\" \"$basedir_win/@@TARGET@@\" \"$@\"\nelif [ -x \"$basedir/node\" ]; then\n exec \"$basedir/node\" \"$basedir_abs/@@TARGET@@\" \"$@\"\nelif [ -n \"$msys\" ] && command -v node >/dev/null 2>&1; then\n exec node \"$basedir_win/@@TARGET@@\" \"$@\"\nelif command -v node >/dev/null 2>&1; then\n exec node \"$basedir_abs/@@TARGET@@\" \"$@\"\nelif [ -n \"$exe\" ] && command -v node.exe >/dev/null 2>&1; then\n exec node.exe \"$basedir_win/@@TARGET@@\" \"$@\"\nelse\n exec node \"$basedir_abs/@@TARGET@@\" \"$@\"\nfi\n# cmd-shim-target=@@COMMENT@@\n"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"versions": [
|
|
157
|
+
"12.4.2"
|
|
158
|
+
],
|
|
159
|
+
"template": "#!/bin/sh\n# Resolve $0 through symlinks so basedir is the shim's real directory.\n# Cap hops at the kernel's ELOOP limit so a cycle cannot hang the shim.\n#\n# A shim runs with node_modules/.bin at the front of PATH, so readlink, sed, and\n# uname go through `command -p`, which searches the system default path instead.\n# A dependency's bin cannot stand in for one of them and take over the shim\n# before it reaches its target. Directories come from `${link%/*}`, which needs\n# no helper at all.\nlink=\"$0\"\n# `${link%/*}` needs a separator to strip. A bare name came from a PATH lookup\n# and stands for a file in the current directory.\ncase \"$link\" in\n */*|*\\\\*) ;;\n *) link=\"./$link\" ;;\nesac\nhops=0\nwhile [ -L \"$link\" ] && [ \"$hops\" -lt 40 ]; do\n hops=$((hops+1))\n target=$(command -p readlink \"$link\")\n case \"$target\" in\n /*) link=\"$target\" ;;\n *) link=\"${link%/*}/$target\" ;;\n esac\ndone\nbasedir=$(echo \"$link\" | command -p sed -e 's,\\\\,/,g')\nbasedir=\"${basedir%/*}\"\nbasedir_win=\"$basedir\"\nexe=\"\"\nmsys=\"\"\n\ncase `command -p uname -a` in\n *CYGWIN*|*MINGW*|*MSYS*)\n if command -v cygpath > /dev/null 2>&1; then\n basedir_win=`cygpath -w \"$basedir\"`\n fi\n exe=\".exe\"\n msys=\"true\"\n ;;\n *WSL2*)\n if command -v wslpath > /dev/null 2>&1; then\n basedir_win=\"$(wslpath -w \"$basedir\" 2> /dev/null)\"\n if [ $? -ne 0 ] || [ -z \"$basedir_win\" ]; then\n basedir_win=\"$basedir\"\n else\n exe=\".exe\"\n fi\n fi\n ;;\nesac\n\nif [ -z \"$NODE_PATH\" ]; then\n export NODE_PATH=\"@@NODE_PATH@@\"\nelse\n export NODE_PATH=\"@@NODE_PATH@@:$NODE_PATH\"\nfi\nif [ -n \"$exe\" ] && [ -x \"$basedir/node.exe\" ]; then\n exec \"$basedir/node.exe\" \"$basedir_win/@@TARGET@@\" \"$@\"\nelif [ -x \"$basedir/node\" ]; then\n exec \"$basedir/node\" \"$basedir/@@TARGET@@\" \"$@\"\nelif command -v node >/dev/null 2>&1; then\n exec node \"$basedir/@@TARGET@@\" \"$@\"\nelif [ -n \"$exe\" ] && command -v node.exe >/dev/null 2>&1; then\n exec node.exe \"$basedir_win/@@TARGET@@\" \"$@\"\nelse\n exec node \"$basedir/@@TARGET@@\" \"$@\"\nfi\n# cmd-shim-target=@@COMMENT@@\n"
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"versions": [
|
|
163
|
+
"12.5.1"
|
|
164
|
+
],
|
|
165
|
+
"template": "#!/bin/sh\n# Resolve $0 through symlinks so basedir is the shim's real directory.\n# Cap hops at the kernel's ELOOP limit so a cycle cannot hang the shim.\n#\n# A shim runs with node_modules/.bin at the front of PATH, so readlink, sed,\n# uname, and printf go through `command -p`, which searches the system default\n# path instead. A dependency's bin cannot stand in for one of them and take over\n# the shim before it reaches its target. Directories come from `${link%/*}`,\n# which needs no helper at all.\nlink=\"$0\"\n# `${link%/*}` needs a separator to strip. A bare name came from a PATH lookup\n# and stands for a file in the current directory.\ncase \"$link\" in\n */*|*\\\\*) ;;\n *) link=\"./$link\" ;;\nesac\nhops=0\nwhile [ -L \"$link\" ] && [ \"$hops\" -lt 40 ]; do\n hops=$((hops+1))\n target=$(command -p readlink \"$link\")\n case \"$target\" in\n /*) link=\"$target\" ;;\n *) link=\"${link%/*}/$target\" ;;\n esac\ndone\nbasedir=$(command -p printf '%s\\n' \"$link\" | command -p sed -e 's,\\\\,/,g')\nbasedir=\"${basedir%/*}\"\nbasedir_win=\"$basedir\"\nexe=\"\"\nmsys=\"\"\n\ncase `command -p uname -a` in\n *CYGWIN*|*MINGW*|*MSYS*)\n if command -v cygpath > /dev/null 2>&1; then\n basedir_win=`cygpath -w \"$basedir\"`\n fi\n exe=\".exe\"\n msys=\"true\"\n ;;\n *WSL2*)\n if command -v wslpath > /dev/null 2>&1; then\n basedir_win=\"$(wslpath -w \"$basedir\" 2> /dev/null)\"\n if [ $? -ne 0 ] || [ -z \"$basedir_win\" ]; then\n basedir_win=\"$basedir\"\n else\n exe=\".exe\"\n fi\n fi\n ;;\nesac\n\nif [ -z \"$NODE_PATH\" ]; then\n export NODE_PATH=\"@@NODE_PATH@@\"\nelse\n export NODE_PATH=\"@@NODE_PATH@@:$NODE_PATH\"\nfi\nif [ -n \"$exe\" ] && [ -x \"$basedir/node.exe\" ]; then\n exec \"$basedir/node.exe\" \"$basedir_win/@@TARGET@@\" \"$@\"\nelif [ -x \"$basedir/node\" ]; then\n exec \"$basedir/node\" \"$basedir/@@TARGET@@\" \"$@\"\nelif command -v node >/dev/null 2>&1; then\n exec node \"$basedir/@@TARGET@@\" \"$@\"\nelif [ -n \"$exe\" ] && command -v node.exe >/dev/null 2>&1; then\n exec node.exe \"$basedir_win/@@TARGET@@\" \"$@\"\nelse\n exec node \"$basedir/@@TARGET@@\" \"$@\"\nfi\n# cmd-shim-target=@@COMMENT@@\n"
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"versions": [
|
|
169
|
+
"12.6.0"
|
|
170
|
+
],
|
|
171
|
+
"template": "#!/bin/sh\n# Resolve $0 through symlinks so basedir is the shim's real directory.\n# Cap hops at the kernel's ELOOP limit so a cycle cannot hang the shim.\n#\n# A shim runs with node_modules/.bin at the front of PATH, so readlink, sed,\n# uname, and printf go through `command -p`, which searches the system default\n# path instead. A dependency's bin cannot stand in for one of them and take over\n# the shim before it reaches its target. Directories come from `${link%/*}`,\n# which needs no helper at all.\nlink=\"$0\"\n# `${link%/*}` needs a separator to strip. A bare name came from a PATH lookup\n# and stands for a file in the current directory.\ncase \"$link\" in\n */*|*\\\\*) ;;\n *) link=\"./$link\" ;;\nesac\nhops=0\nwhile [ -L \"$link\" ] && [ \"$hops\" -lt 40 ]; do\n hops=$((hops+1))\n target=$(command -p readlink \"$link\")\n case \"$target\" in\n /*) link=\"$target\" ;;\n *) link=\"${link%/*}/$target\" ;;\n esac\ndone\nbasedir=$(command -p printf '%s\\n' \"$link\" | command -p sed -e 's,\\\\,/,g')\nbasedir=\"${basedir%/*}\"\nbasedir_win=\"$basedir\"\nexe=\"\"\nmsys=\"\"\n\ncase `command -p uname -a` in\n *CYGWIN*|*MINGW*|*MSYS*)\n if converted=$(command -p cygpath -w \"$basedir\" 2>/dev/null) && [ -n \"$converted\" ]; then\n basedir_win=\"$converted\"\n elif command -v cygpath > /dev/null 2>&1; then\n basedir_win=`cygpath -w \"$basedir\"`\n fi\n exe=\".exe\"\n msys=\"true\"\n ;;\n *WSL2*)\n if converted=$(command -p wslpath -w \"$basedir\" 2>/dev/null) && [ -n \"$converted\" ]; then\n basedir_win=\"$converted\"\n exe=\".exe\"\n elif command -v wslpath > /dev/null 2>&1; then\n basedir_win=\"$(wslpath -w \"$basedir\" 2> /dev/null)\"\n if [ $? -ne 0 ] || [ -z \"$basedir_win\" ]; then\n basedir_win=\"$basedir\"\n else\n exe=\".exe\"\n fi\n fi\n ;;\nesac\n\nbasedir_abs=$(CDPATH= cd -P -- \"$basedir\" && pwd -P) || exit $?\nif [ -z \"$NODE_PATH\" ]; then\n export NODE_PATH=\"@@NODE_PATH@@\"\nelse\n export NODE_PATH=\"@@NODE_PATH@@:$NODE_PATH\"\nfi\nif [ -n \"$exe\" ] && [ -x \"$basedir/node.exe\" ]; then\n exec \"$basedir/node.exe\" \"$basedir_win/@@TARGET@@\" \"$@\"\nelif [ -x \"$basedir/node\" ]; then\n exec \"$basedir/node\" \"$basedir_abs/@@TARGET@@\" \"$@\"\nelif command -v node >/dev/null 2>&1; then\n exec node \"$basedir_abs/@@TARGET@@\" \"$@\"\nelif [ -n \"$exe\" ] && command -v node.exe >/dev/null 2>&1; then\n exec node.exe \"$basedir_win/@@TARGET@@\" \"$@\"\nelse\n exec node \"$basedir_abs/@@TARGET@@\" \"$@\"\nfi\n# cmd-shim-target=@@COMMENT@@\n"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"versions": [
|
|
175
|
+
"12.7.0"
|
|
176
|
+
],
|
|
177
|
+
"template": "#!/bin/sh\n# Resolve $0 through symlinks so basedir is the shim's real directory.\n# Cap hops at the kernel's ELOOP limit so a cycle cannot hang the shim.\n#\n# A shim runs with node_modules/.bin at the front of PATH, so readlink, sed,\n# uname, and printf go through `command -p`, which searches the system default\n# path instead. A dependency's bin cannot stand in for one of them and take over\n# the shim before it reaches its target. Directories come from `${link%/*}`,\n# which needs no helper at all.\n#\n# Where no default path is compiled in, as on Nix, `command -p` searches PATH\n# instead, so the helpers run with node_modules and relative entries dropped from\n# PATH.\ncaller_path_set=${PATH+set}\ncaller_path=${PATH-}\nhelper_path=\nrest=$caller_path:\nwhile [ -n \"$rest\" ]; do\n dir=${rest%%:*}\n rest=${rest#*:}\n case \"$dir\" in\n */node_modules/*|*/node_modules) ;;\n /*) helper_path=${helper_path:+$helper_path:}$dir ;;\n esac\ndone\n# An empty PATH searches the current directory.\nPATH=${helper_path:-/}\nlink=\"$0\"\n# `${link%/*}` needs a separator to strip. A bare name came from a PATH lookup\n# and stands for a file in the current directory.\ncase \"$link\" in\n */*|*\\\\*) ;;\n *) link=\"./$link\" ;;\nesac\nhops=0\nwhile [ -L \"$link\" ] && [ \"$hops\" -lt 40 ]; do\n hops=$((hops+1))\n target=$(command -p readlink \"$link\")\n case \"$target\" in\n /*) link=\"$target\" ;;\n *) link=\"${link%/*}/$target\" ;;\n esac\ndone\nbasedir=$(command -p printf '%s\\n' \"$link\" | command -p sed -e 's,\\\\,/,g')\nbasedir=\"${basedir%/*}\"\nbasedir_win=\"$basedir\"\nexe=\"\"\nmsys=\"\"\n\ncase `command -p uname -a` in\n *CYGWIN*|*MINGW*|*MSYS*)\n if converted=$(command -p cygpath -w \"$basedir\" 2>/dev/null) && [ -n \"$converted\" ]; then\n basedir_win=\"$converted\"\n elif command -v cygpath > /dev/null 2>&1; then\n basedir_win=`cygpath -w \"$basedir\"`\n fi\n exe=\".exe\"\n msys=\"true\"\n ;;\n *WSL2*)\n if converted=$(command -p wslpath -w \"$basedir\" 2>/dev/null) && [ -n \"$converted\" ]; then\n basedir_win=\"$converted\"\n exe=\".exe\"\n elif command -v wslpath > /dev/null 2>&1; then\n basedir_win=\"$(wslpath -w \"$basedir\" 2> /dev/null)\"\n if [ $? -ne 0 ] || [ -z \"$basedir_win\" ]; then\n basedir_win=\"$basedir\"\n else\n exe=\".exe\"\n fi\n fi\n ;;\nesac\nif [ -n \"$caller_path_set\" ]; then PATH=$caller_path; else unset PATH; fi\n\nbasedir_abs=$(CDPATH= cd -P -- \"$basedir\" && pwd -P) || exit $?\nif [ -z \"$NODE_PATH\" ]; then\n export NODE_PATH=\"@@NODE_PATH@@\"\nelse\n export NODE_PATH=\"@@NODE_PATH@@:$NODE_PATH\"\nfi\nif [ -n \"$exe\" ] && [ -x \"$basedir/node.exe\" ]; then\n exec \"$basedir/node.exe\" \"$basedir_win/@@TARGET@@\" \"$@\"\nelif [ -x \"$basedir/node\" ]; then\n exec \"$basedir/node\" \"$basedir_abs/@@TARGET@@\" \"$@\"\nelif command -v node >/dev/null 2>&1; then\n exec node \"$basedir_abs/@@TARGET@@\" \"$@\"\nelif [ -n \"$exe\" ] && command -v node.exe >/dev/null 2>&1; then\n exec node.exe \"$basedir_win/@@TARGET@@\" \"$@\"\nelse\n exec node \"$basedir_abs/@@TARGET@@\" \"$@\"\nfi\n# cmd-shim-target=@@COMMENT@@\n"
|
|
178
|
+
}
|
|
179
|
+
]
|
|
180
|
+
}
|