@mmmbuto/qwen-code-termux 0.6.4-termux → 0.6.401
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/README.md +3 -3
- package/dist/cli.js +4 -4
- package/package.json +3 -2
- package/scripts/build.js +55 -0
- package/scripts/build_package.js +37 -0
- package/scripts/build_sandbox.js +196 -0
- package/scripts/build_vscode_companion.js +30 -0
- package/scripts/check-build-status.js +148 -0
- package/scripts/check-i18n.ts +462 -0
- package/scripts/check-lockfile.js +74 -0
- package/scripts/clean.js +59 -0
- package/scripts/copy_bundle_assets.js +128 -0
- package/scripts/copy_files.js +86 -0
- package/scripts/create_alias.sh +39 -0
- package/scripts/esbuild-shims.js +29 -0
- package/scripts/generate-git-commit-info.js +71 -0
- package/scripts/get-release-version.js +411 -0
- package/scripts/lint.js +205 -0
- package/scripts/local_telemetry.js +219 -0
- package/scripts/postinstall.cjs +13 -0
- package/scripts/pre-commit.js +22 -0
- package/scripts/prepare-package.js +162 -0
- package/scripts/sandbox_command.js +126 -0
- package/scripts/start.js +83 -0
- package/scripts/telemetry.js +85 -0
- package/scripts/telemetry_gcp.js +188 -0
- package/scripts/telemetry_utils.js +439 -0
- package/scripts/termux-tools/call.sh +206 -0
- package/scripts/termux-tools/discovery.sh +382 -0
- package/scripts/test-windows-paths.js +51 -0
- package/scripts/tests/get-release-version.test.js +186 -0
- package/scripts/tests/test-setup.ts +12 -0
- package/scripts/tests/vitest.config.ts +26 -0
- package/scripts/unused-keys-only-in-locales.json +61 -0
- package/scripts/version.js +112 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { vi, describe, it, expect, beforeEach } from 'vitest';
|
|
8
|
+
import { getVersion } from '../get-release-version.js';
|
|
9
|
+
import { execSync } from 'node:child_process';
|
|
10
|
+
import { readFileSync } from 'node:fs';
|
|
11
|
+
|
|
12
|
+
vi.mock('node:child_process');
|
|
13
|
+
vi.mock('node:fs');
|
|
14
|
+
|
|
15
|
+
describe('getVersion', () => {
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
vi.resetAllMocks();
|
|
18
|
+
vi.setSystemTime(new Date('2025-09-17T00:00:00.000Z'));
|
|
19
|
+
// Mock package.json being read by getNightlyVersion
|
|
20
|
+
vi.mocked(readFileSync).mockReturnValue(
|
|
21
|
+
JSON.stringify({ version: '0.8.0' }),
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// This is the base mock for a clean state with no conflicts or rollbacks
|
|
26
|
+
const mockExecSync = (command) => {
|
|
27
|
+
// NPM dist-tags
|
|
28
|
+
if (command.includes('npm view') && command.includes('--tag=latest'))
|
|
29
|
+
return '0.6.1';
|
|
30
|
+
if (command.includes('npm view') && command.includes('--tag=preview'))
|
|
31
|
+
return '0.7.0-preview.1';
|
|
32
|
+
if (command.includes('npm view') && command.includes('--tag=nightly'))
|
|
33
|
+
return '0.8.0-nightly.20250916.abcdef';
|
|
34
|
+
|
|
35
|
+
// NPM versions list
|
|
36
|
+
if (command.includes('npm view') && command.includes('versions --json'))
|
|
37
|
+
return JSON.stringify([
|
|
38
|
+
'0.6.0',
|
|
39
|
+
'0.6.1',
|
|
40
|
+
'0.7.0-preview.0',
|
|
41
|
+
'0.7.0-preview.1',
|
|
42
|
+
'0.8.0-nightly.20250916.abcdef',
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
// Deprecation checks (default to not deprecated)
|
|
46
|
+
if (command.includes('deprecated')) return '';
|
|
47
|
+
|
|
48
|
+
// Git Tag Mocks
|
|
49
|
+
if (command.includes("git tag -l 'v[0-9].[0-9].[0-9]'")) return 'v0.6.1';
|
|
50
|
+
if (command.includes("git tag -l 'v*-preview*'")) return 'v0.7.0-preview.1';
|
|
51
|
+
if (command.includes("git tag -l 'v*-nightly*'"))
|
|
52
|
+
return 'v0.8.0-nightly.20250916.abcdef';
|
|
53
|
+
|
|
54
|
+
// Git Hash Mock
|
|
55
|
+
if (command.includes('git rev-parse --short HEAD')) return 'd3bf8a3d';
|
|
56
|
+
|
|
57
|
+
// For doesVersionExist checks - default to not found
|
|
58
|
+
if (
|
|
59
|
+
command.includes('npm view') &&
|
|
60
|
+
command.includes('@qwen-code/qwen-code@')
|
|
61
|
+
) {
|
|
62
|
+
throw new Error('NPM version not found');
|
|
63
|
+
}
|
|
64
|
+
if (command.includes('git tag -l')) return '';
|
|
65
|
+
if (command.includes('gh release view')) {
|
|
66
|
+
throw new Error('GH release not found');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return '';
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
describe('Happy Path - Version Calculation', () => {
|
|
73
|
+
it('should calculate the next stable version from the latest preview', () => {
|
|
74
|
+
vi.mocked(execSync).mockImplementation(mockExecSync);
|
|
75
|
+
const result = getVersion({ type: 'stable' });
|
|
76
|
+
expect(result.releaseVersion).toBe('0.7.0');
|
|
77
|
+
expect(result.npmTag).toBe('latest');
|
|
78
|
+
expect(result.previousReleaseTag).toBe('v0.6.1');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('should calculate the next preview version from the latest nightly', () => {
|
|
82
|
+
vi.mocked(execSync).mockImplementation(mockExecSync);
|
|
83
|
+
const result = getVersion({ type: 'preview' });
|
|
84
|
+
expect(result.releaseVersion).toBe('0.8.0-preview.0');
|
|
85
|
+
expect(result.npmTag).toBe('preview');
|
|
86
|
+
expect(result.previousReleaseTag).toBe('v0.6.1');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should calculate the next nightly version from package.json', () => {
|
|
90
|
+
vi.mocked(execSync).mockImplementation(mockExecSync);
|
|
91
|
+
const result = getVersion({ type: 'nightly' });
|
|
92
|
+
// Note: The base version now comes from package.json, not the previous nightly tag.
|
|
93
|
+
expect(result.releaseVersion).toBe('0.8.0-nightly.20250917.d3bf8a3d');
|
|
94
|
+
expect(result.npmTag).toBe('nightly');
|
|
95
|
+
expect(result.previousReleaseTag).toBe('v0.6.1');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should calculate the next patch version for a stable release', () => {
|
|
99
|
+
vi.mocked(execSync).mockImplementation(mockExecSync);
|
|
100
|
+
const result = getVersion({ type: 'patch', 'patch-from': 'stable' });
|
|
101
|
+
expect(result.releaseVersion).toBe('0.6.2');
|
|
102
|
+
expect(result.npmTag).toBe('latest');
|
|
103
|
+
expect(result.previousReleaseTag).toBe('v0.6.1');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should calculate the next patch version for a preview release', () => {
|
|
107
|
+
vi.mocked(execSync).mockImplementation(mockExecSync);
|
|
108
|
+
const result = getVersion({ type: 'patch', 'patch-from': 'preview' });
|
|
109
|
+
expect(result.releaseVersion).toBe('0.7.0-preview.2');
|
|
110
|
+
expect(result.npmTag).toBe('preview');
|
|
111
|
+
expect(result.previousReleaseTag).toBe('v0.6.1');
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('Advanced Scenarios', () => {
|
|
116
|
+
it('should ignore a deprecated version and use the next highest', () => {
|
|
117
|
+
const mockWithDeprecated = (command) => {
|
|
118
|
+
// The highest nightly is 0.9.0, but it's deprecated
|
|
119
|
+
if (command.includes('npm view') && command.includes('versions --json'))
|
|
120
|
+
return JSON.stringify([
|
|
121
|
+
'0.8.0-nightly.20250916.abcdef',
|
|
122
|
+
'0.9.0-nightly.20250917.deprecated', // This one is deprecated
|
|
123
|
+
]);
|
|
124
|
+
// Mock the deprecation check
|
|
125
|
+
if (
|
|
126
|
+
command.includes(
|
|
127
|
+
'npm view @qwen-code/qwen-code@0.9.0-nightly.20250917.deprecated deprecated',
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
return 'This version is deprecated';
|
|
131
|
+
// The dist-tag still points to the older, valid version
|
|
132
|
+
if (command.includes('npm view') && command.includes('--tag=nightly'))
|
|
133
|
+
return '0.8.0-nightly.20250916.abcdef';
|
|
134
|
+
|
|
135
|
+
return mockExecSync(command);
|
|
136
|
+
};
|
|
137
|
+
vi.mocked(execSync).mockImplementation(mockWithDeprecated);
|
|
138
|
+
|
|
139
|
+
const result = getVersion({ type: 'preview' });
|
|
140
|
+
// It should base the preview off 0.8.0, not the deprecated 0.9.0
|
|
141
|
+
expect(result.releaseVersion).toBe('0.8.0-preview.0');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should auto-increment patch version if the calculated one already exists', () => {
|
|
145
|
+
const mockWithConflict = (command) => {
|
|
146
|
+
// The calculated version 0.7.0 already exists as a git tag
|
|
147
|
+
if (command.includes("git tag -l 'v0.7.0'")) return 'v0.7.0';
|
|
148
|
+
// The next version, 0.7.1, is available
|
|
149
|
+
if (command.includes("git tag -l 'v0.7.1'")) return '';
|
|
150
|
+
|
|
151
|
+
return mockExecSync(command);
|
|
152
|
+
};
|
|
153
|
+
vi.mocked(execSync).mockImplementation(mockWithConflict);
|
|
154
|
+
|
|
155
|
+
const result = getVersion({ type: 'stable' });
|
|
156
|
+
// Should have skipped 0.7.0 and landed on 0.7.1
|
|
157
|
+
expect(result.releaseVersion).toBe('0.7.1');
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('should auto-increment preview number if the calculated one already exists', () => {
|
|
161
|
+
const mockWithConflict = (command) => {
|
|
162
|
+
// The calculated preview 0.8.0-preview.0 already exists on NPM
|
|
163
|
+
if (
|
|
164
|
+
command.includes(
|
|
165
|
+
'npm view @qwen-code/qwen-code@0.8.0-preview.0 version',
|
|
166
|
+
)
|
|
167
|
+
)
|
|
168
|
+
return '0.8.0-preview.0';
|
|
169
|
+
// The next one is available
|
|
170
|
+
if (
|
|
171
|
+
command.includes(
|
|
172
|
+
'npm view @qwen-code/qwen-code@0.8.0-preview.1 version',
|
|
173
|
+
)
|
|
174
|
+
)
|
|
175
|
+
throw new Error('Not found');
|
|
176
|
+
|
|
177
|
+
return mockExecSync(command);
|
|
178
|
+
};
|
|
179
|
+
vi.mocked(execSync).mockImplementation(mockWithConflict);
|
|
180
|
+
|
|
181
|
+
const result = getVersion({ type: 'preview' });
|
|
182
|
+
// Should have skipped preview.0 and landed on preview.1
|
|
183
|
+
expect(result.releaseVersion).toBe('0.8.0-preview.1');
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { defineConfig } from 'vitest/config';
|
|
8
|
+
|
|
9
|
+
export default defineConfig({
|
|
10
|
+
test: {
|
|
11
|
+
globals: true,
|
|
12
|
+
environment: 'node',
|
|
13
|
+
include: ['scripts/tests/**/*.test.js'],
|
|
14
|
+
setupFiles: ['scripts/tests/test-setup.ts'],
|
|
15
|
+
coverage: {
|
|
16
|
+
provider: 'v8',
|
|
17
|
+
reporter: ['text', 'lcov'],
|
|
18
|
+
},
|
|
19
|
+
poolOptions: {
|
|
20
|
+
threads: {
|
|
21
|
+
minThreads: 8,
|
|
22
|
+
maxThreads: 16,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"generatedAt": "2025-12-24T09:15:59.125Z",
|
|
3
|
+
"keys": [
|
|
4
|
+
" - en-US: English",
|
|
5
|
+
" - zh-CN: Simplified Chinese",
|
|
6
|
+
"A checkpoint with the tag {{tag}} already exists. Do you want to overwrite it?",
|
|
7
|
+
"Apply to current session only (temporary)",
|
|
8
|
+
"Approval mode changed to: {{mode}}",
|
|
9
|
+
"Approval mode changed to: {{mode}} (saved to {{scope}} settings{{location}})",
|
|
10
|
+
"Auto-edit mode - Automatically approve file edits",
|
|
11
|
+
"Available approval modes:",
|
|
12
|
+
"Chat history is already compressed.",
|
|
13
|
+
"Clearing terminal and resetting chat.",
|
|
14
|
+
"Clearing terminal.",
|
|
15
|
+
"Conversation checkpoint '{{tag}}' has been deleted.",
|
|
16
|
+
"Conversation checkpoint saved with tag: {{tag}}.",
|
|
17
|
+
"Conversation shared to {{filePath}}",
|
|
18
|
+
"Current approval mode: {{mode}}",
|
|
19
|
+
"Default mode - Require approval for file edits or shell commands",
|
|
20
|
+
"Delete a conversation checkpoint. Usage: /chat delete <tag>",
|
|
21
|
+
"Enable Prompt Completion",
|
|
22
|
+
"Error sharing conversation: {{error}}",
|
|
23
|
+
"Error: No checkpoint found with tag '{{tag}}'.",
|
|
24
|
+
"Failed to change approval mode: {{error}}",
|
|
25
|
+
"Failed to login. Message: {{message}}",
|
|
26
|
+
"Failed to save approval mode: {{error}}",
|
|
27
|
+
"Invalid file format. Only .md and .json are supported.",
|
|
28
|
+
"Invalid language. Available: en-US, zh-CN",
|
|
29
|
+
"List of saved conversations:",
|
|
30
|
+
"List saved conversation checkpoints",
|
|
31
|
+
"Manage conversation history.",
|
|
32
|
+
"Missing tag. Usage: /chat delete <tag>",
|
|
33
|
+
"Missing tag. Usage: /chat resume <tag>",
|
|
34
|
+
"Missing tag. Usage: /chat save <tag>",
|
|
35
|
+
"No chat client available to save conversation.",
|
|
36
|
+
"No chat client available to share conversation.",
|
|
37
|
+
"No conversation found to save.",
|
|
38
|
+
"No conversation found to share.",
|
|
39
|
+
"No saved checkpoint found with tag: {{tag}}.",
|
|
40
|
+
"No saved conversation checkpoints found.",
|
|
41
|
+
"Note: Newest last, oldest first",
|
|
42
|
+
"OpenAI API key is required to use OpenAI authentication.",
|
|
43
|
+
"Persist for this project/workspace",
|
|
44
|
+
"Persist for this user on this machine",
|
|
45
|
+
"Plan mode - Analyze only, do not modify files or execute commands",
|
|
46
|
+
"Qwen OAuth authentication cancelled.",
|
|
47
|
+
"Qwen OAuth authentication timed out. Please try again.",
|
|
48
|
+
"Resume a conversation from a checkpoint. Usage: /chat resume <tag>",
|
|
49
|
+
"Save the current conversation as a checkpoint. Usage: /chat save <tag>",
|
|
50
|
+
"Scope subcommands do not accept additional arguments.",
|
|
51
|
+
"Set UI language to English (en-US)",
|
|
52
|
+
"Set UI language to Simplified Chinese (zh-CN)",
|
|
53
|
+
"Settings service is not available; unable to persist the approval mode.",
|
|
54
|
+
"Share the current conversation to a markdown or json file. Usage: /chat share <file>",
|
|
55
|
+
"Usage: /approval-mode <mode> [--session|--user|--project]",
|
|
56
|
+
"Usage: /language ui [zh-CN|en-US]",
|
|
57
|
+
"YOLO mode - Automatically approve all tools",
|
|
58
|
+
"clear the screen and conversation history"
|
|
59
|
+
],
|
|
60
|
+
"count": 55
|
|
61
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { execSync } from 'node:child_process';
|
|
8
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
9
|
+
import { resolve } from 'node:path';
|
|
10
|
+
|
|
11
|
+
// A script to handle versioning and ensure all related changes are in a single, atomic commit.
|
|
12
|
+
|
|
13
|
+
function run(command) {
|
|
14
|
+
console.log(`> ${command}`);
|
|
15
|
+
execSync(command, { stdio: 'inherit' });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function readJson(filePath) {
|
|
19
|
+
return JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function writeJson(filePath, data) {
|
|
23
|
+
writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 1. Get the version from the command line arguments.
|
|
27
|
+
const versionType = process.argv[2];
|
|
28
|
+
if (!versionType) {
|
|
29
|
+
console.error('Error: No version specified.');
|
|
30
|
+
console.error(
|
|
31
|
+
'Usage: npm run version <version> (e.g., 1.2.3 or patch|minor|major|prerelease)',
|
|
32
|
+
);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// 2. Bump the version in the root and all workspace package.json files.
|
|
37
|
+
run(`npm version ${versionType} --no-git-tag-version --allow-same-version`);
|
|
38
|
+
|
|
39
|
+
// 3. Get all workspaces and filter out the one we don't want to version.
|
|
40
|
+
// We intend to maintain sdk version independently.
|
|
41
|
+
const workspacesToExclude = ['@qwen-code/sdk'];
|
|
42
|
+
let lsOutput;
|
|
43
|
+
try {
|
|
44
|
+
lsOutput = JSON.parse(
|
|
45
|
+
execSync('npm ls --workspaces --json --depth=0').toString(),
|
|
46
|
+
);
|
|
47
|
+
} catch (e) {
|
|
48
|
+
// `npm ls` can exit with a non-zero status code if there are issues
|
|
49
|
+
// with dependencies, but it will still produce the JSON output we need.
|
|
50
|
+
// We'll try to parse the stdout from the error object.
|
|
51
|
+
if (e.stdout) {
|
|
52
|
+
console.warn(
|
|
53
|
+
'Warning: `npm ls` exited with a non-zero status code. Attempting to proceed with the output.',
|
|
54
|
+
);
|
|
55
|
+
try {
|
|
56
|
+
lsOutput = JSON.parse(e.stdout.toString());
|
|
57
|
+
} catch (parseError) {
|
|
58
|
+
console.error(
|
|
59
|
+
'Error: Failed to parse JSON from `npm ls` output even after `npm ls` failed.',
|
|
60
|
+
);
|
|
61
|
+
console.error('npm ls stderr:', e.stderr.toString());
|
|
62
|
+
console.error('Parse error:', parseError);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
console.error('Error: `npm ls` failed with no output.');
|
|
67
|
+
console.error(e.stderr?.toString() || e);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const allWorkspaces = Object.keys(lsOutput.dependencies || {});
|
|
72
|
+
const workspacesToVersion = allWorkspaces.filter(
|
|
73
|
+
(wsName) => !workspacesToExclude.includes(wsName),
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
for (const workspaceName of workspacesToVersion) {
|
|
77
|
+
run(
|
|
78
|
+
`npm version ${versionType} --workspace ${workspaceName} --no-git-tag-version --allow-same-version`,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 4. Get the new version number from the root package.json
|
|
83
|
+
const rootPackageJsonPath = resolve(process.cwd(), 'package.json');
|
|
84
|
+
const newVersion = readJson(rootPackageJsonPath).version;
|
|
85
|
+
|
|
86
|
+
// 5. Update the sandboxImageUri in the root package.json
|
|
87
|
+
const rootPackageJson = readJson(rootPackageJsonPath);
|
|
88
|
+
if (rootPackageJson.config?.sandboxImageUri) {
|
|
89
|
+
rootPackageJson.config.sandboxImageUri =
|
|
90
|
+
rootPackageJson.config.sandboxImageUri.replace(/:.*$/, `:${newVersion}`);
|
|
91
|
+
console.log(`Updated sandboxImageUri in root to use version ${newVersion}`);
|
|
92
|
+
writeJson(rootPackageJsonPath, rootPackageJson);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// 6. Update the sandboxImageUri in the cli package.json
|
|
96
|
+
const cliPackageJsonPath = resolve(process.cwd(), 'packages/cli/package.json');
|
|
97
|
+
const cliPackageJson = readJson(cliPackageJsonPath);
|
|
98
|
+
if (cliPackageJson.config?.sandboxImageUri) {
|
|
99
|
+
cliPackageJson.config.sandboxImageUri =
|
|
100
|
+
cliPackageJson.config.sandboxImageUri.replace(/:.*$/, `:${newVersion}`);
|
|
101
|
+
console.log(
|
|
102
|
+
`Updated sandboxImageUri in cli package to use version ${newVersion}`,
|
|
103
|
+
);
|
|
104
|
+
writeJson(cliPackageJsonPath, cliPackageJson);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 7. Run `npm install` to update package-lock.json.
|
|
108
|
+
run(
|
|
109
|
+
'npm install --workspace packages/cli --workspace packages/core --package-lock-only',
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
console.log(`Successfully bumped versions to v${newVersion}.`);
|