@w5s/dev 3.2.2 → 3.3.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.
- package/dist/index.cjs +1 -390
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -250
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +1 -250
- package/dist/index.js +2 -379
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/index.ts +0 -6
- package/src/block.ts +0 -153
- package/src/directory.ts +0 -73
- package/src/exec.ts +0 -73
- package/src/file.ts +0 -99
- package/src/json.ts +0 -58
- package/src/yarnConfig.ts +0 -61
- package/src/yarnVersion.ts +0 -56
package/src/block.ts
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import { type FileOptions, file, fileSync } from './file.js';
|
|
2
|
-
|
|
3
|
-
export interface BlockOptions {
|
|
4
|
-
/**
|
|
5
|
-
* The marker builder function that will take either `markerBegin` or `markerEnd`
|
|
6
|
-
*
|
|
7
|
-
* @default '# ${mark} MANAGED BLOCK'
|
|
8
|
-
*/
|
|
9
|
-
marker?: (mark: 'Begin' | 'End') => string;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* File path
|
|
13
|
-
*/
|
|
14
|
-
path: string;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Block content to insert
|
|
18
|
-
*/
|
|
19
|
-
block: string;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Insert position
|
|
23
|
-
*/
|
|
24
|
-
insertPosition?: ['before', 'BeginningOfFile' | RegExp] | ['after', 'EndOfFile' | RegExp];
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Block target state
|
|
28
|
-
*/
|
|
29
|
-
state?: 'present' | 'absent';
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const EOF = 'EndOfFile';
|
|
33
|
-
const BOF = 'BeginningOfFile';
|
|
34
|
-
const insertAt = (str: string, index: number, toInsert: string) => str.slice(0, index) + toInsert + str.slice(index);
|
|
35
|
-
const matchLast = (string: string, regexp: RegExp) => {
|
|
36
|
-
const matcher = new RegExp(regexp.source, `${regexp.flags}g`);
|
|
37
|
-
let firstIndex = -1;
|
|
38
|
-
let lastIndex = -1;
|
|
39
|
-
let matches;
|
|
40
|
-
|
|
41
|
-
while (true) {
|
|
42
|
-
matches = matcher.exec(string);
|
|
43
|
-
if (matches == null) {
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
|
-
firstIndex = matches.index;
|
|
47
|
-
lastIndex = matcher.lastIndex;
|
|
48
|
-
}
|
|
49
|
-
return { firstIndex, lastIndex };
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
function toFileOptions(options: BlockOptions): FileOptions {
|
|
53
|
-
const {
|
|
54
|
-
marker = (mark) => `# ${mark.toUpperCase()} MANAGED BLOCK`,
|
|
55
|
-
path,
|
|
56
|
-
block: blockName,
|
|
57
|
-
insertPosition = ['after', EOF],
|
|
58
|
-
state = 'present',
|
|
59
|
-
} = options;
|
|
60
|
-
|
|
61
|
-
const EOL = '\n';
|
|
62
|
-
const beginBlock = marker('Begin');
|
|
63
|
-
const endBlock = marker('End');
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* @param content
|
|
67
|
-
*/
|
|
68
|
-
function findBlock(content: string) {
|
|
69
|
-
const startIndex = content.indexOf(beginBlock);
|
|
70
|
-
const endIndex = content.indexOf(endBlock) + endBlock.length;
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
endIndex,
|
|
74
|
-
exists: startIndex !== -1 && endIndex >= 0,
|
|
75
|
-
startIndex,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function apply(fullContent: string, blockContent: string) {
|
|
80
|
-
const found = findBlock(fullContent);
|
|
81
|
-
const remove = state === 'absent';
|
|
82
|
-
const replaceBlock = remove ? '' : beginBlock + EOL + blockContent + EOL + endBlock;
|
|
83
|
-
const [positionDirection, positionAnchor] = insertPosition;
|
|
84
|
-
|
|
85
|
-
if (found.exists) {
|
|
86
|
-
return fullContent.slice(0, found.startIndex) + replaceBlock + fullContent.slice(found.endIndex);
|
|
87
|
-
}
|
|
88
|
-
if (remove) {
|
|
89
|
-
return fullContent;
|
|
90
|
-
}
|
|
91
|
-
switch (positionDirection) {
|
|
92
|
-
case 'before': {
|
|
93
|
-
if (positionAnchor !== BOF) {
|
|
94
|
-
const { firstIndex } = matchLast(fullContent, positionAnchor);
|
|
95
|
-
if (firstIndex >= 0) {
|
|
96
|
-
return insertAt(fullContent, firstIndex, replaceBlock + EOL);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Beginning of file
|
|
101
|
-
return replaceBlock + EOL + fullContent;
|
|
102
|
-
}
|
|
103
|
-
case 'after': {
|
|
104
|
-
// insert
|
|
105
|
-
if (positionAnchor !== EOF) {
|
|
106
|
-
const { lastIndex } = matchLast(fullContent, positionAnchor);
|
|
107
|
-
if (lastIndex >= 0) {
|
|
108
|
-
return insertAt(fullContent, lastIndex, EOL + replaceBlock);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// end of file
|
|
113
|
-
return fullContent + EOL + replaceBlock;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
default: {
|
|
117
|
-
throw new Error(`Unsupported position ${String(positionDirection)}`);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return {
|
|
123
|
-
path,
|
|
124
|
-
state: 'present',
|
|
125
|
-
update: (sourceContent) => apply(sourceContent, blockName),
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Replace asynchronously a block in file that follows pattern :
|
|
131
|
-
*
|
|
132
|
-
* marker(markerBegin)
|
|
133
|
-
* ...
|
|
134
|
-
* marker(markerEnd)
|
|
135
|
-
*
|
|
136
|
-
* @param options
|
|
137
|
-
*/
|
|
138
|
-
export function block(options: BlockOptions) {
|
|
139
|
-
return file(toFileOptions(options));
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Replace synchronously a block in file that follows pattern :
|
|
144
|
-
*
|
|
145
|
-
* marker(markerBegin)
|
|
146
|
-
* ...
|
|
147
|
-
* marker(markerEnd)
|
|
148
|
-
*
|
|
149
|
-
* @param options
|
|
150
|
-
*/
|
|
151
|
-
export function blockSync(options: BlockOptions) {
|
|
152
|
-
return fileSync(toFileOptions(options));
|
|
153
|
-
}
|
package/src/directory.ts
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, rmSync } from 'node:fs';
|
|
2
|
-
import { access, constants, mkdir, rm } from 'node:fs/promises';
|
|
3
|
-
|
|
4
|
-
async function exists(path: string) {
|
|
5
|
-
try {
|
|
6
|
-
await access(path, constants.F_OK);
|
|
7
|
-
return true;
|
|
8
|
-
} catch {
|
|
9
|
-
return false;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface DirectoryOptions {
|
|
14
|
-
/**
|
|
15
|
-
* Directory path
|
|
16
|
-
*/
|
|
17
|
-
readonly path: string;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Directory target state
|
|
21
|
-
*/
|
|
22
|
-
readonly state: 'present' | 'absent';
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Ensure directory is present/absent
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* ```ts
|
|
30
|
-
* await directory({
|
|
31
|
-
* path: 'foo/bar',
|
|
32
|
-
* state: 'present',
|
|
33
|
-
* })
|
|
34
|
-
* ```
|
|
35
|
-
*
|
|
36
|
-
* @param options
|
|
37
|
-
*/
|
|
38
|
-
export async function directory(options: DirectoryOptions): Promise<void> {
|
|
39
|
-
const { path, state } = options;
|
|
40
|
-
const isPresent = await exists(path);
|
|
41
|
-
if (state === 'present') {
|
|
42
|
-
if (!isPresent) {
|
|
43
|
-
await mkdir(path, { recursive: true });
|
|
44
|
-
}
|
|
45
|
-
} else if (isPresent) {
|
|
46
|
-
await rm(path, { recursive: true });
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Ensure directory is present/absent
|
|
52
|
-
*
|
|
53
|
-
* @example
|
|
54
|
-
* ```ts
|
|
55
|
-
* await directorySync({
|
|
56
|
-
* path: 'foo/bar',
|
|
57
|
-
* state: 'present',
|
|
58
|
-
* })
|
|
59
|
-
* ```
|
|
60
|
-
*
|
|
61
|
-
* @param options
|
|
62
|
-
*/
|
|
63
|
-
export function directorySync(options: DirectoryOptions): void {
|
|
64
|
-
const { path, state } = options;
|
|
65
|
-
const isPresent = existsSync(path);
|
|
66
|
-
if (state === 'present') {
|
|
67
|
-
if (!isPresent) {
|
|
68
|
-
mkdirSync(path, { recursive: true });
|
|
69
|
-
}
|
|
70
|
-
} else if (isPresent) {
|
|
71
|
-
rmSync(path, { recursive: true });
|
|
72
|
-
}
|
|
73
|
-
}
|
package/src/exec.ts
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { spawn, spawnSync } from 'node:child_process';
|
|
2
|
-
|
|
3
|
-
export interface ExecOptions {
|
|
4
|
-
/**
|
|
5
|
-
* Current working directory
|
|
6
|
-
*/
|
|
7
|
-
cwd?: string;
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Stdio options
|
|
11
|
-
*/
|
|
12
|
-
stdio?: 'inherit' | 'pipe' | 'ignore';
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Runs a command in a shell and returns a promise that resolves with an object
|
|
17
|
-
* containing the stdout and stderr strings.
|
|
18
|
-
*
|
|
19
|
-
* @param command The command to run
|
|
20
|
-
* @param args The arguments to pass to the command
|
|
21
|
-
* @param options
|
|
22
|
-
* @returns A promise that resolves with an object like `{ stdout: string, stderr: string }`
|
|
23
|
-
*/
|
|
24
|
-
export function execSync(
|
|
25
|
-
command: string,
|
|
26
|
-
args: ReadonlyArray<string>,
|
|
27
|
-
options?: ExecOptions,
|
|
28
|
-
): { stdout: string; stderr: string } {
|
|
29
|
-
const result = spawnSync(command, args, { ...options });
|
|
30
|
-
const encoding = 'utf8';
|
|
31
|
-
|
|
32
|
-
return { stdout: result.stdout.toString(encoding), stderr: result.stderr.toString(encoding) };
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Runs a command in a shell and returns a promise that resolves with an object
|
|
37
|
-
* containing the stdout and stderr strings.
|
|
38
|
-
*
|
|
39
|
-
* @param command The command to run
|
|
40
|
-
* @param args The arguments to pass to the command
|
|
41
|
-
* @param options
|
|
42
|
-
*/
|
|
43
|
-
export async function exec(
|
|
44
|
-
command: string,
|
|
45
|
-
args: ReadonlyArray<string>,
|
|
46
|
-
options?: ExecOptions,
|
|
47
|
-
): Promise<{ stdout: string; stderr: string }> {
|
|
48
|
-
return new Promise((resolve, reject) => {
|
|
49
|
-
const encoding = 'utf8';
|
|
50
|
-
const child = spawn(command, args, { ...options });
|
|
51
|
-
let stdout = '';
|
|
52
|
-
let stderr = '';
|
|
53
|
-
|
|
54
|
-
// Capture the stdout and stderr streams
|
|
55
|
-
if (child.stdout != null) {
|
|
56
|
-
child.stdout.on('data', (data) => {
|
|
57
|
-
stdout += data.toString(encoding);
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
if (child.stderr != null) {
|
|
61
|
-
child.stderr.on('data', (data) => {
|
|
62
|
-
stderr += data.toString(encoding);
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
// Handle process exit
|
|
66
|
-
child.on('close', (_code) => {
|
|
67
|
-
resolve({ stdout, stderr });
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
// Handle errors
|
|
71
|
-
child.on('error', reject);
|
|
72
|
-
});
|
|
73
|
-
}
|
package/src/file.ts
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { readFile, rm, writeFile, access } from 'node:fs/promises';
|
|
2
|
-
import { accessSync, constants, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
-
|
|
4
|
-
async function exists(path: string) {
|
|
5
|
-
try {
|
|
6
|
-
await access(path, constants.F_OK);
|
|
7
|
-
return true;
|
|
8
|
-
} catch {
|
|
9
|
-
return false;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function existsSync(path: string) {
|
|
14
|
-
try {
|
|
15
|
-
accessSync(path, constants.F_OK);
|
|
16
|
-
return true;
|
|
17
|
-
} catch {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface FileOptions {
|
|
23
|
-
/**
|
|
24
|
-
* File path
|
|
25
|
-
*/
|
|
26
|
-
readonly path: string;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* File target state
|
|
30
|
-
*/
|
|
31
|
-
readonly state: 'present' | 'absent';
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* File content mapping function
|
|
35
|
-
*
|
|
36
|
-
*/
|
|
37
|
-
readonly update?: ((content: string) => string | undefined) | undefined;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* File encoding
|
|
41
|
-
*/
|
|
42
|
-
readonly encoding?: BufferEncoding;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Ensure file is present/absent with content initialized or modified with `update
|
|
47
|
-
*
|
|
48
|
-
* @example
|
|
49
|
-
* ```ts
|
|
50
|
-
* await file({
|
|
51
|
-
* path: 'foo/bar',
|
|
52
|
-
* state: 'present',
|
|
53
|
-
* update: (content) => content + '_test', // This will append '_test' after current content
|
|
54
|
-
* })
|
|
55
|
-
* ```
|
|
56
|
-
*
|
|
57
|
-
* @param options
|
|
58
|
-
*/
|
|
59
|
-
export async function file(options: FileOptions): Promise<void> {
|
|
60
|
-
const { path, state, update, encoding = 'utf8' } = options;
|
|
61
|
-
if (state === 'present') {
|
|
62
|
-
const isPresent = await exists(path);
|
|
63
|
-
const previousContent = isPresent ? await readFile(path, encoding) : '';
|
|
64
|
-
const newContent = update == null ? '' : update(previousContent);
|
|
65
|
-
if (newContent != null) {
|
|
66
|
-
await writeFile(path, newContent, encoding);
|
|
67
|
-
}
|
|
68
|
-
} else {
|
|
69
|
-
await rm(path, { force: true });
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Ensure file is present/absent with content initialized or modified with `update
|
|
75
|
-
*
|
|
76
|
-
* @example
|
|
77
|
-
* ```ts
|
|
78
|
-
* fileSync({
|
|
79
|
-
* path: 'foo/bar',
|
|
80
|
-
* state: 'present',
|
|
81
|
-
* update: (content) => content + '_test', // This will append '_test' after current content
|
|
82
|
-
* })
|
|
83
|
-
* ```
|
|
84
|
-
*
|
|
85
|
-
* @param options
|
|
86
|
-
*/
|
|
87
|
-
export function fileSync(options: FileOptions): void {
|
|
88
|
-
const { path, state, update, encoding = 'utf8' } = options;
|
|
89
|
-
if (state === 'present') {
|
|
90
|
-
const isPresent = existsSync(path);
|
|
91
|
-
const previousContent = isPresent ? readFileSync(path, encoding) : '';
|
|
92
|
-
const newContent = update == null ? '' : update(previousContent);
|
|
93
|
-
if (newContent != null) {
|
|
94
|
-
writeFileSync(path, newContent, encoding);
|
|
95
|
-
}
|
|
96
|
-
} else {
|
|
97
|
-
rmSync(path, { force: true });
|
|
98
|
-
}
|
|
99
|
-
}
|
package/src/json.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { type FileOptions, file, fileSync } from './file.js';
|
|
2
|
-
|
|
3
|
-
export type JSONValue = null | number | string | boolean | JSONValue[] | { [key: string]: JSONValue };
|
|
4
|
-
|
|
5
|
-
export interface JSONOption<V = JSONValue> {
|
|
6
|
-
/**
|
|
7
|
-
* File path
|
|
8
|
-
*/
|
|
9
|
-
readonly path: string;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* File target state
|
|
13
|
-
*/
|
|
14
|
-
readonly state: 'present' | 'absent';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* File content mapping function
|
|
18
|
-
*/
|
|
19
|
-
readonly update?: ((content: V | undefined) => V | undefined) | undefined;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* File encoding
|
|
23
|
-
*/
|
|
24
|
-
readonly encoding?: BufferEncoding;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function toFileOption<Value>({ update, ...otherOptions }: JSONOption<Value>): FileOptions {
|
|
28
|
-
return {
|
|
29
|
-
...otherOptions,
|
|
30
|
-
|
|
31
|
-
update:
|
|
32
|
-
update == null
|
|
33
|
-
? update
|
|
34
|
-
: (content) => {
|
|
35
|
-
const jsonValue = content === '' ? undefined : (JSON.parse(content) as Value);
|
|
36
|
-
|
|
37
|
-
return JSON.stringify(update(jsonValue));
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Ensure file is present/absent asynchronously with content value initialized or modified with `update`
|
|
44
|
-
*
|
|
45
|
-
* @param options
|
|
46
|
-
*/
|
|
47
|
-
export async function json<Value>(options: JSONOption<Value>): Promise<void> {
|
|
48
|
-
return file(toFileOption(options));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Ensure file is present/absent synchronously with content value initialized or modified with `update`
|
|
53
|
-
*
|
|
54
|
-
* @param options
|
|
55
|
-
*/
|
|
56
|
-
export function jsonSync<Value>(options: JSONOption<Value>): void {
|
|
57
|
-
return fileSync(toFileOption(options));
|
|
58
|
-
}
|
package/src/yarnConfig.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { exec, execSync } from './exec.js';
|
|
2
|
-
|
|
3
|
-
export interface YarnConfigOptions {
|
|
4
|
-
/**
|
|
5
|
-
* Configuration key
|
|
6
|
-
*/
|
|
7
|
-
readonly key: string;
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Option target state
|
|
11
|
-
*/
|
|
12
|
-
readonly state: 'present' | 'absent';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* File content mapping function
|
|
16
|
-
*
|
|
17
|
-
*/
|
|
18
|
-
readonly update?: ((content: string) => string | undefined) | undefined;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Synchronous version of {@link yarnConfig}
|
|
23
|
-
*
|
|
24
|
-
* @param options
|
|
25
|
-
* @example
|
|
26
|
-
* yarnConfigSync({
|
|
27
|
-
* key: 'nodeLinker',
|
|
28
|
-
* state: 'present',
|
|
29
|
-
* update: (content) => content.replace('node-modules', 'hoisted'),
|
|
30
|
-
* })
|
|
31
|
-
*/
|
|
32
|
-
export function yarnConfigSync(options: YarnConfigOptions) {
|
|
33
|
-
const { key, state, update } = options;
|
|
34
|
-
if (state === 'present') {
|
|
35
|
-
const { stdout } = execSync('yarn', ['config', 'get', String(key)]);
|
|
36
|
-
execSync('yarn', ['config', 'set', String(key), `${update == null ? '' : update(stdout)}`]);
|
|
37
|
-
} else {
|
|
38
|
-
execSync('yarn', ['config', 'unset']);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Set/Unset yarn configuration value
|
|
44
|
-
*
|
|
45
|
-
* @param options
|
|
46
|
-
* @example
|
|
47
|
-
* await yarnConfig({
|
|
48
|
-
* key: 'nodeLinker',
|
|
49
|
-
* state: 'present',
|
|
50
|
-
* update: (content) => content.replace('node-modules', 'hoisted'),
|
|
51
|
-
* })
|
|
52
|
-
*/
|
|
53
|
-
export async function yarnConfig(options: YarnConfigOptions): Promise<void> {
|
|
54
|
-
const { key, state, update } = options;
|
|
55
|
-
if (state === 'present') {
|
|
56
|
-
const { stdout } = await exec('yarn', ['config', 'get', String(key)]);
|
|
57
|
-
await exec('yarn', ['config', 'set', String(key), `${update == null ? '' : update(stdout)}`]);
|
|
58
|
-
} else {
|
|
59
|
-
await exec('yarn', ['config', 'unset']);
|
|
60
|
-
}
|
|
61
|
-
}
|
package/src/yarnVersion.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { exec, execSync } from './exec.js';
|
|
2
|
-
|
|
3
|
-
export type YarnVersionKind = 'berry' | 'classic';
|
|
4
|
-
|
|
5
|
-
export interface YarnVersionOptions {
|
|
6
|
-
/**
|
|
7
|
-
* Option target state
|
|
8
|
-
*/
|
|
9
|
-
readonly state: 'present' | 'absent';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Version mapping function
|
|
13
|
-
*
|
|
14
|
-
*/
|
|
15
|
-
readonly update?: (() => YarnVersionKind | undefined) | undefined;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Synchronous version of {@link yarnVersion}
|
|
20
|
-
*
|
|
21
|
-
* @param options
|
|
22
|
-
* @example
|
|
23
|
-
* yarnVersionSync({
|
|
24
|
-
* state: 'present',
|
|
25
|
-
* update: () => 'berry', // or 'classic'
|
|
26
|
-
* })
|
|
27
|
-
*/
|
|
28
|
-
export function yarnVersionSync(options: YarnVersionOptions) {
|
|
29
|
-
const { state, update } = options;
|
|
30
|
-
if (state === 'present') {
|
|
31
|
-
execSync('yarn', ['set', 'version', `${update == null ? 'berry' : update()}`]);
|
|
32
|
-
} else {
|
|
33
|
-
// TODO: remove yarn.lock
|
|
34
|
-
throw new Error('Not implemented');
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Set/Unset yarn configuration value
|
|
40
|
-
*
|
|
41
|
-
* @param options
|
|
42
|
-
* @example
|
|
43
|
-
* await yarnVersion({
|
|
44
|
-
* state: 'present',
|
|
45
|
-
* update: () => 'berry', // or 'classic'
|
|
46
|
-
* })
|
|
47
|
-
*/
|
|
48
|
-
export async function yarnVersion(options: YarnVersionOptions): Promise<void> {
|
|
49
|
-
const { state, update } = options;
|
|
50
|
-
if (state === 'present') {
|
|
51
|
-
await exec('yarn', ['set', 'version', `${update == null ? 'berry' : update()}`]);
|
|
52
|
-
} else {
|
|
53
|
-
// TODO: remove yarn.lock
|
|
54
|
-
throw new Error('Not implemented');
|
|
55
|
-
}
|
|
56
|
-
}
|