@lvnt/release-radar 1.7.16 → 1.8.2
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/bin/release-radar-updater.js +0 -0
- package/bin/release-radar.js +0 -0
- package/config/downloads.json +102 -1
- package/config/tools.json +55 -0
- package/dist/asset-mirror.js +18 -7
- package/dist/asset-mirror.test.js +47 -2
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
- package/dist/vsix-mirror.d.ts +0 -15
- package/dist/vsix-mirror.js +0 -96
- package/dist/vsix-mirror.test.d.ts +0 -1
- package/dist/vsix-mirror.test.js +0 -96
|
File without changes
|
package/bin/release-radar.js
CHANGED
|
File without changes
|
package/config/downloads.json
CHANGED
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
"downloadUrl": "{{MIRROR_URL}}",
|
|
13
13
|
"filename": "claude-code-{{VERSION}}-win32-x64.vsix",
|
|
14
14
|
"mirror": {
|
|
15
|
-
"sourceUrl": "marketplace-api"
|
|
15
|
+
"sourceUrl": "marketplace-api",
|
|
16
|
+
"extensionId": "anthropic.claude-code",
|
|
17
|
+
"targetPlatform": "win32-x64"
|
|
16
18
|
}
|
|
17
19
|
},
|
|
18
20
|
"Claude Code CLI": {
|
|
@@ -89,5 +91,104 @@
|
|
|
89
91
|
"displayName": "PowerShell",
|
|
90
92
|
"downloadUrl": "github.com/PowerShell/PowerShell/releases/download/v{{VERSION}}/PowerShell-{{VERSION}}-win-x64.msi",
|
|
91
93
|
"filename": "PowerShell-{{VERSION}}-win-x64.msi"
|
|
94
|
+
},
|
|
95
|
+
"C/C++ Extension Pack": {
|
|
96
|
+
"displayName": "C/C++ Extension Pack",
|
|
97
|
+
"downloadUrl": "{{MIRROR_URL}}",
|
|
98
|
+
"filename": "cpptools-extension-pack-{{VERSION}}.vsix",
|
|
99
|
+
"mirror": {
|
|
100
|
+
"sourceUrl": "marketplace-api",
|
|
101
|
+
"extensionId": "ms-vscode.cpptools-extension-pack"
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
"C/C++ Themes": {
|
|
105
|
+
"displayName": "C/C++ Themes",
|
|
106
|
+
"downloadUrl": "{{MIRROR_URL}}",
|
|
107
|
+
"filename": "cpptools-themes-{{VERSION}}.vsix",
|
|
108
|
+
"mirror": {
|
|
109
|
+
"sourceUrl": "marketplace-api",
|
|
110
|
+
"extensionId": "ms-vscode.cpptools-themes"
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"YAML": {
|
|
114
|
+
"displayName": "YAML Extension",
|
|
115
|
+
"downloadUrl": "{{MIRROR_URL}}",
|
|
116
|
+
"filename": "vscode-yaml-{{VERSION}}.vsix",
|
|
117
|
+
"mirror": {
|
|
118
|
+
"sourceUrl": "marketplace-api",
|
|
119
|
+
"extensionId": "redhat.vscode-yaml"
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
"Python": {
|
|
123
|
+
"displayName": "Python Extension",
|
|
124
|
+
"downloadUrl": "{{MIRROR_URL}}",
|
|
125
|
+
"filename": "python-{{VERSION}}.vsix",
|
|
126
|
+
"mirror": {
|
|
127
|
+
"sourceUrl": "marketplace-api",
|
|
128
|
+
"extensionId": "ms-python.python"
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"Python Debugger": {
|
|
132
|
+
"displayName": "Python Debugger",
|
|
133
|
+
"downloadUrl": "{{MIRROR_URL}}",
|
|
134
|
+
"filename": "debugpy-{{VERSION}}.vsix",
|
|
135
|
+
"mirror": {
|
|
136
|
+
"sourceUrl": "marketplace-api",
|
|
137
|
+
"extensionId": "ms-python.debugpy"
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
"Python Environments": {
|
|
141
|
+
"displayName": "Python Environments",
|
|
142
|
+
"downloadUrl": "{{MIRROR_URL}}",
|
|
143
|
+
"filename": "vscode-python-envs-{{VERSION}}.vsix",
|
|
144
|
+
"mirror": {
|
|
145
|
+
"sourceUrl": "marketplace-api",
|
|
146
|
+
"extensionId": "ms-python.vscode-python-envs"
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
"Pylance": {
|
|
150
|
+
"displayName": "Pylance",
|
|
151
|
+
"downloadUrl": "{{MIRROR_URL}}",
|
|
152
|
+
"filename": "vscode-pylance-{{VERSION}}.vsix",
|
|
153
|
+
"mirror": {
|
|
154
|
+
"sourceUrl": "marketplace-api",
|
|
155
|
+
"extensionId": "ms-python.vscode-pylance"
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"isort": {
|
|
159
|
+
"displayName": "isort Extension",
|
|
160
|
+
"downloadUrl": "{{MIRROR_URL}}",
|
|
161
|
+
"filename": "isort-{{VERSION}}.vsix",
|
|
162
|
+
"mirror": {
|
|
163
|
+
"sourceUrl": "marketplace-api",
|
|
164
|
+
"extensionId": "ms-python.isort"
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
"Go": {
|
|
168
|
+
"displayName": "Go Extension",
|
|
169
|
+
"downloadUrl": "{{MIRROR_URL}}",
|
|
170
|
+
"filename": "go-{{VERSION}}.vsix",
|
|
171
|
+
"mirror": {
|
|
172
|
+
"sourceUrl": "marketplace-api",
|
|
173
|
+
"extensionId": "golang.go"
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
"GitHub Theme": {
|
|
177
|
+
"displayName": "GitHub Theme",
|
|
178
|
+
"downloadUrl": "{{MIRROR_URL}}",
|
|
179
|
+
"filename": "github-vscode-theme-{{VERSION}}.vsix",
|
|
180
|
+
"mirror": {
|
|
181
|
+
"sourceUrl": "marketplace-api",
|
|
182
|
+
"extensionId": "github.github-vscode-theme"
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
"Material Icon Theme": {
|
|
186
|
+
"displayName": "Material Icon Theme",
|
|
187
|
+
"downloadUrl": "{{MIRROR_URL}}",
|
|
188
|
+
"filename": "material-icon-theme-{{VERSION}}.vsix",
|
|
189
|
+
"mirror": {
|
|
190
|
+
"sourceUrl": "marketplace-api",
|
|
191
|
+
"extensionId": "pkief.material-icon-theme"
|
|
192
|
+
}
|
|
92
193
|
}
|
|
93
194
|
}
|
package/config/tools.json
CHANGED
|
@@ -85,6 +85,61 @@
|
|
|
85
85
|
"name": "PowerShell",
|
|
86
86
|
"type": "github",
|
|
87
87
|
"repo": "PowerShell/PowerShell"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"name": "C/C++ Extension Pack",
|
|
91
|
+
"type": "vscode-marketplace",
|
|
92
|
+
"extensionId": "ms-vscode.cpptools-extension-pack"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"name": "C/C++ Themes",
|
|
96
|
+
"type": "vscode-marketplace",
|
|
97
|
+
"extensionId": "ms-vscode.cpptools-themes"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"name": "YAML",
|
|
101
|
+
"type": "vscode-marketplace",
|
|
102
|
+
"extensionId": "redhat.vscode-yaml"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "Python",
|
|
106
|
+
"type": "vscode-marketplace",
|
|
107
|
+
"extensionId": "ms-python.python"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"name": "Python Debugger",
|
|
111
|
+
"type": "vscode-marketplace",
|
|
112
|
+
"extensionId": "ms-python.debugpy"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"name": "Python Environments",
|
|
116
|
+
"type": "vscode-marketplace",
|
|
117
|
+
"extensionId": "ms-python.vscode-python-envs"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"name": "Pylance",
|
|
121
|
+
"type": "vscode-marketplace",
|
|
122
|
+
"extensionId": "ms-python.vscode-pylance"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"name": "isort",
|
|
126
|
+
"type": "vscode-marketplace",
|
|
127
|
+
"extensionId": "ms-python.isort"
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"name": "Go",
|
|
131
|
+
"type": "vscode-marketplace",
|
|
132
|
+
"extensionId": "golang.go"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"name": "GitHub Theme",
|
|
136
|
+
"type": "vscode-marketplace",
|
|
137
|
+
"extensionId": "github.github-vscode-theme"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"name": "Material Icon Theme",
|
|
141
|
+
"type": "vscode-marketplace",
|
|
142
|
+
"extensionId": "pkief.material-icon-theme"
|
|
88
143
|
}
|
|
89
144
|
]
|
|
90
145
|
}
|
package/dist/asset-mirror.js
CHANGED
|
@@ -59,14 +59,15 @@ export class AssetMirror {
|
|
|
59
59
|
}
|
|
60
60
|
async getSourceUrl(config, version) {
|
|
61
61
|
if (config.sourceUrl === 'marketplace-api') {
|
|
62
|
-
|
|
62
|
+
if (!config.extensionId) {
|
|
63
|
+
throw new Error('extensionId is required when sourceUrl is "marketplace-api"');
|
|
64
|
+
}
|
|
65
|
+
return this.getMarketplaceVsixUrl(config.extensionId, version, config.targetPlatform);
|
|
63
66
|
}
|
|
64
67
|
// For direct URLs, just return as-is (curl -L will follow redirects)
|
|
65
68
|
return config.sourceUrl;
|
|
66
69
|
}
|
|
67
|
-
async getMarketplaceVsixUrl(version) {
|
|
68
|
-
const extensionId = 'anthropic.claude-code';
|
|
69
|
-
const targetPlatform = 'win32-x64';
|
|
70
|
+
async getMarketplaceVsixUrl(extensionId, version, targetPlatform) {
|
|
70
71
|
const query = JSON.stringify({
|
|
71
72
|
filters: [{
|
|
72
73
|
criteria: [{ filterType: 7, value: extensionId }],
|
|
@@ -82,13 +83,23 @@ export class AssetMirror {
|
|
|
82
83
|
const response = execSync(cmd, { encoding: 'utf-8', timeout: 30000 });
|
|
83
84
|
const data = JSON.parse(response);
|
|
84
85
|
const versions = data.results?.[0]?.extensions?.[0]?.versions || [];
|
|
85
|
-
|
|
86
|
+
// Find matching version - with or without platform filter
|
|
87
|
+
const targetVersion = versions.find((v) => {
|
|
88
|
+
if (v.version !== version)
|
|
89
|
+
return false;
|
|
90
|
+
if (targetPlatform) {
|
|
91
|
+
return v.targetPlatform === targetPlatform;
|
|
92
|
+
}
|
|
93
|
+
// For universal extensions, targetPlatform is undefined/null
|
|
94
|
+
return !v.targetPlatform;
|
|
95
|
+
});
|
|
86
96
|
if (!targetVersion) {
|
|
87
|
-
|
|
97
|
+
const platformInfo = targetPlatform ? ` for ${targetPlatform}` : ' (universal)';
|
|
98
|
+
throw new Error(`Version ${version}${platformInfo} not found in marketplace for ${extensionId}`);
|
|
88
99
|
}
|
|
89
100
|
const vsixFile = targetVersion.files?.find((f) => f.assetType === 'Microsoft.VisualStudio.Services.VSIXPackage');
|
|
90
101
|
if (!vsixFile?.source) {
|
|
91
|
-
throw new Error(
|
|
102
|
+
throw new Error(`VSIX download URL not found in marketplace response for ${extensionId}`);
|
|
92
103
|
}
|
|
93
104
|
return vsixFile.source;
|
|
94
105
|
}
|
|
@@ -12,7 +12,7 @@ vi.mock('fs', () => ({
|
|
|
12
12
|
describe('AssetMirror', () => {
|
|
13
13
|
let mirror;
|
|
14
14
|
beforeEach(() => {
|
|
15
|
-
vi.
|
|
15
|
+
vi.resetAllMocks();
|
|
16
16
|
mirror = new AssetMirror();
|
|
17
17
|
});
|
|
18
18
|
describe('buildTag', () => {
|
|
@@ -74,11 +74,56 @@ describe('AssetMirror', () => {
|
|
|
74
74
|
vi.mocked(execSync).mockReturnValueOnce('');
|
|
75
75
|
vi.mocked(existsSync).mockReturnValue(true);
|
|
76
76
|
const result = await mirror.mirror('Claude Code VSCode', '2.1.9', {
|
|
77
|
-
sourceUrl: 'marketplace-api'
|
|
77
|
+
sourceUrl: 'marketplace-api',
|
|
78
|
+
extensionId: 'anthropic.claude-code',
|
|
79
|
+
targetPlatform: 'win32-x64'
|
|
78
80
|
}, 'claude-code-{{VERSION}}-win32-x64.vsix');
|
|
79
81
|
expect(result.success).toBe(true);
|
|
80
82
|
expect(result.downloadUrl).toBe('github.com/lvntbkdmr/apps/releases/download/claude-code-vscode-v2.1.9/claude-code-2.1.9-win32-x64.vsix');
|
|
81
83
|
});
|
|
84
|
+
it('handles universal marketplace extensions without targetPlatform', async () => {
|
|
85
|
+
const marketplaceResponse = JSON.stringify({
|
|
86
|
+
results: [{
|
|
87
|
+
extensions: [{
|
|
88
|
+
versions: [{
|
|
89
|
+
version: '1.2.3',
|
|
90
|
+
files: [{
|
|
91
|
+
assetType: 'Microsoft.VisualStudio.Services.VSIXPackage',
|
|
92
|
+
source: 'https://marketplace.visualstudio.com/vsix/download'
|
|
93
|
+
}]
|
|
94
|
+
}]
|
|
95
|
+
}]
|
|
96
|
+
}]
|
|
97
|
+
});
|
|
98
|
+
// 1. gh release view fails
|
|
99
|
+
vi.mocked(execSync).mockImplementationOnce(() => {
|
|
100
|
+
throw new Error('release not found');
|
|
101
|
+
});
|
|
102
|
+
// 2. curl marketplace query succeeds
|
|
103
|
+
vi.mocked(execSync).mockReturnValueOnce(marketplaceResponse);
|
|
104
|
+
// 3. curl download succeeds
|
|
105
|
+
vi.mocked(execSync).mockReturnValueOnce('');
|
|
106
|
+
// 4. gh release create succeeds
|
|
107
|
+
vi.mocked(execSync).mockReturnValueOnce('');
|
|
108
|
+
vi.mocked(existsSync).mockReturnValue(true);
|
|
109
|
+
const result = await mirror.mirror('GitHub Theme', '1.2.3', {
|
|
110
|
+
sourceUrl: 'marketplace-api',
|
|
111
|
+
extensionId: 'github.github-vscode-theme'
|
|
112
|
+
}, 'github-vscode-theme-{{VERSION}}.vsix');
|
|
113
|
+
expect(result.success).toBe(true);
|
|
114
|
+
expect(result.downloadUrl).toBe('github.com/lvntbkdmr/apps/releases/download/github-theme-v1.2.3/github-vscode-theme-1.2.3.vsix');
|
|
115
|
+
});
|
|
116
|
+
it('fails when extensionId is missing for marketplace-api', async () => {
|
|
117
|
+
// gh release view fails
|
|
118
|
+
vi.mocked(execSync).mockImplementationOnce(() => {
|
|
119
|
+
throw new Error('release not found');
|
|
120
|
+
});
|
|
121
|
+
const result = await mirror.mirror('Test Extension', '1.0.0', {
|
|
122
|
+
sourceUrl: 'marketplace-api'
|
|
123
|
+
}, 'test-{{VERSION}}.vsix');
|
|
124
|
+
expect(result.success).toBe(false);
|
|
125
|
+
expect(result.error).toContain('extensionId is required');
|
|
126
|
+
});
|
|
82
127
|
it('successfully mirrors direct URL through full flow', async () => {
|
|
83
128
|
// 1. gh release view fails
|
|
84
129
|
vi.mocked(execSync).mockImplementationOnce(() => {
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
package/dist/vsix-mirror.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export interface MirrorResult {
|
|
2
|
-
success: boolean;
|
|
3
|
-
downloadUrl?: string;
|
|
4
|
-
error?: string;
|
|
5
|
-
}
|
|
6
|
-
export declare class VsixMirror {
|
|
7
|
-
private repo;
|
|
8
|
-
private extensionId;
|
|
9
|
-
private targetPlatform;
|
|
10
|
-
mirror(version: string): Promise<MirrorResult>;
|
|
11
|
-
releaseExists(tag: string): Promise<boolean>;
|
|
12
|
-
private getMarketplaceVsixUrl;
|
|
13
|
-
private downloadVsix;
|
|
14
|
-
private createRelease;
|
|
15
|
-
}
|
package/dist/vsix-mirror.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
// src/vsix-mirror.ts
|
|
2
|
-
import { execSync } from 'child_process';
|
|
3
|
-
import { unlinkSync, existsSync } from 'fs';
|
|
4
|
-
import { tmpdir } from 'os';
|
|
5
|
-
import { join } from 'path';
|
|
6
|
-
export class VsixMirror {
|
|
7
|
-
repo = 'lvntbkdmr/apps';
|
|
8
|
-
extensionId = 'anthropic.claude-code';
|
|
9
|
-
targetPlatform = 'win32-x64';
|
|
10
|
-
async mirror(version) {
|
|
11
|
-
const tag = `claude-code-vsix-v${version}`;
|
|
12
|
-
const filename = `claude-code-${version}-win32-x64.vsix`;
|
|
13
|
-
const downloadUrl = `github.com/${this.repo}/releases/download/${tag}/${filename}`;
|
|
14
|
-
try {
|
|
15
|
-
// Check if release already exists
|
|
16
|
-
if (await this.releaseExists(tag)) {
|
|
17
|
-
console.log(`[VsixMirror] Release ${tag} already exists, skipping`);
|
|
18
|
-
return { success: true, downloadUrl };
|
|
19
|
-
}
|
|
20
|
-
// Get VSIX URL from marketplace
|
|
21
|
-
console.log(`[VsixMirror] Querying marketplace for ${this.extensionId} v${version}...`);
|
|
22
|
-
const vsixUrl = await this.getMarketplaceVsixUrl(version);
|
|
23
|
-
// Download VSIX to temp file
|
|
24
|
-
const tempPath = join(tmpdir(), filename);
|
|
25
|
-
console.log(`[VsixMirror] Downloading VSIX to ${tempPath}...`);
|
|
26
|
-
await this.downloadVsix(vsixUrl, tempPath);
|
|
27
|
-
// Create GitHub release with VSIX attached
|
|
28
|
-
console.log(`[VsixMirror] Creating release ${tag}...`);
|
|
29
|
-
await this.createRelease(tag, tempPath, filename, version);
|
|
30
|
-
// Cleanup temp file
|
|
31
|
-
if (existsSync(tempPath)) {
|
|
32
|
-
unlinkSync(tempPath);
|
|
33
|
-
}
|
|
34
|
-
console.log(`[VsixMirror] Successfully mirrored to ${downloadUrl}`);
|
|
35
|
-
return { success: true, downloadUrl };
|
|
36
|
-
}
|
|
37
|
-
catch (error) {
|
|
38
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
39
|
-
console.error(`[VsixMirror] Failed to mirror: ${message}`);
|
|
40
|
-
return { success: false, error: message };
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
async releaseExists(tag) {
|
|
44
|
-
try {
|
|
45
|
-
execSync(`gh release view ${tag} --repo ${this.repo}`, {
|
|
46
|
-
encoding: 'utf-8',
|
|
47
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
48
|
-
});
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
async getMarketplaceVsixUrl(version) {
|
|
56
|
-
const query = JSON.stringify({
|
|
57
|
-
filters: [{
|
|
58
|
-
criteria: [{ filterType: 7, value: this.extensionId }],
|
|
59
|
-
pageNumber: 1,
|
|
60
|
-
pageSize: 1,
|
|
61
|
-
}],
|
|
62
|
-
flags: 3,
|
|
63
|
-
});
|
|
64
|
-
const cmd = `curl -sS 'https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery' ` +
|
|
65
|
-
`-H 'Accept: application/json; api-version=7.2-preview.1' ` +
|
|
66
|
-
`-H 'Content-Type: application/json' ` +
|
|
67
|
-
`--data '${query}'`;
|
|
68
|
-
const response = execSync(cmd, { encoding: 'utf-8', timeout: 30000 });
|
|
69
|
-
const data = JSON.parse(response);
|
|
70
|
-
const versions = data.results?.[0]?.extensions?.[0]?.versions || [];
|
|
71
|
-
const targetVersion = versions.find((v) => v.version === version && v.targetPlatform === this.targetPlatform);
|
|
72
|
-
if (!targetVersion) {
|
|
73
|
-
throw new Error(`Version ${version} for ${this.targetPlatform} not found in marketplace`);
|
|
74
|
-
}
|
|
75
|
-
const vsixFile = targetVersion.files?.find((f) => f.assetType === 'Microsoft.VisualStudio.Services.VSIXPackage');
|
|
76
|
-
if (!vsixFile?.source) {
|
|
77
|
-
throw new Error('VSIX download URL not found in marketplace response');
|
|
78
|
-
}
|
|
79
|
-
return vsixFile.source;
|
|
80
|
-
}
|
|
81
|
-
async downloadVsix(url, destPath) {
|
|
82
|
-
execSync(`curl -sS -L -o "${destPath}" "${url}"`, {
|
|
83
|
-
encoding: 'utf-8',
|
|
84
|
-
timeout: 300000, // 5 minutes for large files
|
|
85
|
-
});
|
|
86
|
-
if (!existsSync(destPath)) {
|
|
87
|
-
throw new Error('Download failed - file not created');
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
async createRelease(tag, vsixPath, filename, version) {
|
|
91
|
-
const title = `Claude Code VSCode ${version}`;
|
|
92
|
-
const notes = `Mirrored from VS Code Marketplace for Nexus proxy access.\n\nPlatform: win32-x64`;
|
|
93
|
-
execSync(`gh release create "${tag}" "${vsixPath}#${filename}" ` +
|
|
94
|
-
`--repo ${this.repo} --title "${title}" --notes "${notes}"`, { encoding: 'utf-8', timeout: 300000 });
|
|
95
|
-
}
|
|
96
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/vsix-mirror.test.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { VsixMirror } from './vsix-mirror.js';
|
|
3
|
-
import { execSync } from 'child_process';
|
|
4
|
-
import { existsSync, unlinkSync } from 'fs';
|
|
5
|
-
vi.mock('child_process', () => ({
|
|
6
|
-
execSync: vi.fn()
|
|
7
|
-
}));
|
|
8
|
-
vi.mock('fs', () => ({
|
|
9
|
-
existsSync: vi.fn(),
|
|
10
|
-
unlinkSync: vi.fn()
|
|
11
|
-
}));
|
|
12
|
-
describe('VsixMirror', () => {
|
|
13
|
-
let mirror;
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
vi.clearAllMocks();
|
|
16
|
-
mirror = new VsixMirror();
|
|
17
|
-
});
|
|
18
|
-
describe('mirror', () => {
|
|
19
|
-
it('returns existing URL if release already exists', async () => {
|
|
20
|
-
// gh release view succeeds = release exists
|
|
21
|
-
vi.mocked(execSync).mockReturnValueOnce(Buffer.from(''));
|
|
22
|
-
const result = await mirror.mirror('2.1.9');
|
|
23
|
-
expect(result.success).toBe(true);
|
|
24
|
-
expect(result.downloadUrl).toBe('github.com/lvntbkdmr/apps/releases/download/claude-code-vsix-v2.1.9/claude-code-2.1.9-win32-x64.vsix');
|
|
25
|
-
// Should not attempt to create release
|
|
26
|
-
expect(execSync).toHaveBeenCalledTimes(1);
|
|
27
|
-
});
|
|
28
|
-
it('returns error when marketplace query fails', async () => {
|
|
29
|
-
// gh release view fails = release does not exist
|
|
30
|
-
vi.mocked(execSync).mockImplementationOnce(() => {
|
|
31
|
-
throw new Error('release not found');
|
|
32
|
-
});
|
|
33
|
-
// curl for marketplace query fails
|
|
34
|
-
vi.mocked(execSync).mockImplementationOnce(() => {
|
|
35
|
-
throw new Error('network error');
|
|
36
|
-
});
|
|
37
|
-
const result = await mirror.mirror('2.1.9');
|
|
38
|
-
expect(result.success).toBe(false);
|
|
39
|
-
expect(result.error).toContain('network error');
|
|
40
|
-
});
|
|
41
|
-
it('successfully mirrors new version through full flow', async () => {
|
|
42
|
-
const marketplaceResponse = JSON.stringify({
|
|
43
|
-
results: [{
|
|
44
|
-
extensions: [{
|
|
45
|
-
versions: [{
|
|
46
|
-
version: '2.1.9',
|
|
47
|
-
targetPlatform: 'win32-x64',
|
|
48
|
-
files: [{
|
|
49
|
-
assetType: 'Microsoft.VisualStudio.Services.VSIXPackage',
|
|
50
|
-
source: 'https://marketplace.visualstudio.com/vsix/download'
|
|
51
|
-
}]
|
|
52
|
-
}]
|
|
53
|
-
}]
|
|
54
|
-
}]
|
|
55
|
-
});
|
|
56
|
-
// 1. gh release view fails = release does not exist
|
|
57
|
-
vi.mocked(execSync).mockImplementationOnce(() => {
|
|
58
|
-
throw new Error('release not found');
|
|
59
|
-
});
|
|
60
|
-
// 2. curl marketplace query succeeds
|
|
61
|
-
vi.mocked(execSync).mockReturnValueOnce(marketplaceResponse);
|
|
62
|
-
// 3. curl download succeeds (returns empty)
|
|
63
|
-
vi.mocked(execSync).mockReturnValueOnce('');
|
|
64
|
-
// 4. gh release create succeeds
|
|
65
|
-
vi.mocked(execSync).mockReturnValueOnce('');
|
|
66
|
-
// Mock existsSync to return true (file exists after download)
|
|
67
|
-
vi.mocked(existsSync).mockReturnValue(true);
|
|
68
|
-
const result = await mirror.mirror('2.1.9');
|
|
69
|
-
expect(result.success).toBe(true);
|
|
70
|
-
expect(result.downloadUrl).toBe('github.com/lvntbkdmr/apps/releases/download/claude-code-vsix-v2.1.9/claude-code-2.1.9-win32-x64.vsix');
|
|
71
|
-
expect(execSync).toHaveBeenCalledTimes(4);
|
|
72
|
-
// Verify the gh release create was called with correct arguments
|
|
73
|
-
const lastCall = vi.mocked(execSync).mock.calls[3][0];
|
|
74
|
-
expect(lastCall).toContain('gh release create');
|
|
75
|
-
expect(lastCall).toContain('claude-code-vsix-v2.1.9');
|
|
76
|
-
expect(lastCall).toContain('--repo lvntbkdmr/apps');
|
|
77
|
-
// Verify cleanup was called
|
|
78
|
-
expect(unlinkSync).toHaveBeenCalled();
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
describe('releaseExists', () => {
|
|
82
|
-
it('returns true when release exists', async () => {
|
|
83
|
-
vi.mocked(execSync).mockReturnValueOnce(Buffer.from(''));
|
|
84
|
-
const exists = await mirror.releaseExists('claude-code-vsix-v2.1.9');
|
|
85
|
-
expect(exists).toBe(true);
|
|
86
|
-
expect(execSync).toHaveBeenCalledWith('gh release view claude-code-vsix-v2.1.9 --repo lvntbkdmr/apps', expect.any(Object));
|
|
87
|
-
});
|
|
88
|
-
it('returns false when release does not exist', async () => {
|
|
89
|
-
vi.mocked(execSync).mockImplementationOnce(() => {
|
|
90
|
-
throw new Error('release not found');
|
|
91
|
-
});
|
|
92
|
-
const exists = await mirror.releaseExists('claude-code-vsix-v2.1.9');
|
|
93
|
-
expect(exists).toBe(false);
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
});
|