wyvrnpm 1.3.2 → 2.0.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/README.md +704 -413
- package/bin/wyvrn.js +158 -105
- package/package.json +1 -1
- package/src/commands/clean.js +40 -40
- package/src/commands/configure.js +80 -80
- package/src/commands/init.js +33 -33
- package/src/commands/install.js +78 -31
- package/src/commands/link.js +316 -316
- package/src/commands/profile.js +171 -0
- package/src/commands/publish.js +116 -64
- package/src/config.js +8 -6
- package/src/download.js +252 -89
- package/src/index.js +5 -4
- package/src/link-utils.js +95 -95
- package/src/manifest.js +58 -2
- package/src/profile.js +377 -0
- package/src/providers/base.js +89 -12
- package/src/providers/file.js +123 -13
- package/src/providers/http.js +217 -67
- package/src/providers/index.js +43 -43
- package/src/providers/s3.js +207 -70
- package/src/resolve.js +19 -5
package/src/manifest.js
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
|
|
6
|
+
/** Current manifest schema version emitted by v2 tooling. */
|
|
7
|
+
const SCHEMA_VERSION = 2;
|
|
8
|
+
|
|
6
9
|
/**
|
|
7
10
|
* Valid project kind values, matching the C# serialisation enum.
|
|
8
11
|
* @type {string[]}
|
|
@@ -19,21 +22,72 @@ const VALID_KINDS = [
|
|
|
19
22
|
];
|
|
20
23
|
|
|
21
24
|
/**
|
|
22
|
-
* Returns a blank manifest object populated with sensible defaults.
|
|
25
|
+
* Returns a blank v2 manifest object populated with sensible defaults.
|
|
26
|
+
*
|
|
27
|
+
* Build profile settings are NOT stored in wyvrn.json — they live in named
|
|
28
|
+
* profile files under the wyvrnpm config directory
|
|
29
|
+
* (%LOCALAPPDATA%\wyvrnpm\profiles\ on Windows).
|
|
30
|
+
*
|
|
31
|
+
* Dependencies can optionally carry per-package settings overrides that are
|
|
32
|
+
* merged on top of the active machine profile at install/publish time:
|
|
33
|
+
*
|
|
34
|
+
* "dependencies": {
|
|
35
|
+
* "zlib": "1.2.11",
|
|
36
|
+
* "openssl": { "version": "3.0.0", "settings": { "compiler.runtime": "static" } }
|
|
37
|
+
* }
|
|
23
38
|
*
|
|
24
39
|
* @param {string} name - Project name (typically the directory basename).
|
|
25
40
|
* @returns {object}
|
|
26
41
|
*/
|
|
27
42
|
function defaultManifest(name) {
|
|
28
43
|
return {
|
|
29
|
-
name
|
|
44
|
+
name,
|
|
30
45
|
version: '1.0.0.0',
|
|
46
|
+
schemaVersion: SCHEMA_VERSION,
|
|
31
47
|
description: '',
|
|
32
48
|
kind: 'ConsoleApp',
|
|
33
49
|
dependencies: {},
|
|
34
50
|
};
|
|
35
51
|
}
|
|
36
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Normalise the raw `dependencies` field from a manifest into a consistent
|
|
55
|
+
* `{ name → { version, settings } }` map, regardless of the input format:
|
|
56
|
+
*
|
|
57
|
+
* • String value : "1.0.0" → { version: "1.0.0", settings: {} }
|
|
58
|
+
* • Object value : { version, settings? } → kept (settings defaults to {})
|
|
59
|
+
* • Array format : [{ Name, Version }] → converted
|
|
60
|
+
*
|
|
61
|
+
* @param {object|Array|undefined} rawDeps
|
|
62
|
+
* @returns {Record<string, { version: string, settings: object }>}
|
|
63
|
+
*/
|
|
64
|
+
function normalizeDependencies(rawDeps) {
|
|
65
|
+
if (!rawDeps || typeof rawDeps !== 'object') return {};
|
|
66
|
+
|
|
67
|
+
if (Array.isArray(rawDeps)) {
|
|
68
|
+
const result = {};
|
|
69
|
+
for (const d of rawDeps) {
|
|
70
|
+
const n = d.Name ?? d.name;
|
|
71
|
+
const v = d.Version ?? d.version;
|
|
72
|
+
if (n && v) result[n] = { version: v, settings: {} };
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const result = {};
|
|
78
|
+
for (const [n, value] of Object.entries(rawDeps)) {
|
|
79
|
+
if (typeof value === 'string') {
|
|
80
|
+
result[n] = { version: value, settings: {} };
|
|
81
|
+
} else if (value && typeof value === 'object') {
|
|
82
|
+
result[n] = {
|
|
83
|
+
version: value.version ?? value.Version ?? '',
|
|
84
|
+
settings: value.settings ?? {},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
|
|
37
91
|
/**
|
|
38
92
|
* Reads and parses a wyvrn.json manifest from disk.
|
|
39
93
|
*
|
|
@@ -70,8 +124,10 @@ function writeManifest(manifestPath, data) {
|
|
|
70
124
|
}
|
|
71
125
|
|
|
72
126
|
module.exports = {
|
|
127
|
+
SCHEMA_VERSION,
|
|
73
128
|
VALID_KINDS,
|
|
74
129
|
defaultManifest,
|
|
130
|
+
normalizeDependencies,
|
|
75
131
|
readManifest,
|
|
76
132
|
writeManifest,
|
|
77
133
|
};
|
package/src/profile.js
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const crypto = require('crypto');
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// OS / Arch mapping (Node → Conan-style names)
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
const OS_MAP = {
|
|
12
|
+
win32: 'Windows',
|
|
13
|
+
linux: 'Linux',
|
|
14
|
+
darwin: 'Macos',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const ARCH_MAP = {
|
|
18
|
+
x64: 'x86_64',
|
|
19
|
+
ia32: 'x86',
|
|
20
|
+
arm: 'armv7',
|
|
21
|
+
arm64: 'armv8',
|
|
22
|
+
ppc64: 'ppc64le',
|
|
23
|
+
s390x: 's390x',
|
|
24
|
+
mips: 'mips',
|
|
25
|
+
mipsel: 'mipsel',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Helpers
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
function tryExec(cmd) {
|
|
32
|
+
try {
|
|
33
|
+
return execSync(cmd, { stdio: ['ignore', 'pipe', 'pipe'], timeout: 5000 })
|
|
34
|
+
.toString()
|
|
35
|
+
.trim();
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function detectOs() {
|
|
42
|
+
return OS_MAP[process.platform] ?? process.platform;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function detectArch() {
|
|
46
|
+
return ARCH_MAP[process.arch] ?? process.arch;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Compiler detection (per platform)
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
|
|
53
|
+
function detectCompilerWindows() {
|
|
54
|
+
// 1) MSVC via vswhere
|
|
55
|
+
const vswhere = tryExec(
|
|
56
|
+
'"C:\\Program Files (x86)\\Microsoft Visual Studio\\Installer\\vswhere.exe"' +
|
|
57
|
+
' -latest -property installationVersion',
|
|
58
|
+
);
|
|
59
|
+
if (vswhere) {
|
|
60
|
+
const major = parseInt(vswhere.split('.')[0], 10);
|
|
61
|
+
// VS17 → MSVC 193x, VS16 → 192x, VS15 → 191x, VS14 → 190x
|
|
62
|
+
const vsToMsvc = { 17: '193', 16: '192', 15: '191', 14: '190' };
|
|
63
|
+
return {
|
|
64
|
+
compiler: 'msvc',
|
|
65
|
+
'compiler.version': vsToMsvc[major] ?? String(major),
|
|
66
|
+
'compiler.runtime': 'dynamic',
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// 2) Clang / clang-cl
|
|
71
|
+
const clang = tryExec('clang --version');
|
|
72
|
+
if (clang) {
|
|
73
|
+
const m = clang.match(/version (\d+)/);
|
|
74
|
+
return {
|
|
75
|
+
compiler: 'clang',
|
|
76
|
+
'compiler.version': m ? m[1] : 'unknown',
|
|
77
|
+
'compiler.runtime': null,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// 3) MinGW GCC
|
|
82
|
+
const gcc = tryExec('gcc --version');
|
|
83
|
+
if (gcc) {
|
|
84
|
+
const m = gcc.match(/(\d+\.\d+\.\d+)/);
|
|
85
|
+
return {
|
|
86
|
+
compiler: 'gcc',
|
|
87
|
+
'compiler.version': m ? m[1].split('.')[0] : 'unknown',
|
|
88
|
+
'compiler.runtime': null,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return { compiler: 'unknown', 'compiler.version': 'unknown', 'compiler.runtime': null };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function detectCompilerMacos() {
|
|
96
|
+
const clang = tryExec('clang --version');
|
|
97
|
+
if (clang) {
|
|
98
|
+
const appleMatch = clang.match(/Apple clang version (\d+)/i);
|
|
99
|
+
if (appleMatch) {
|
|
100
|
+
return { compiler: 'apple-clang', 'compiler.version': appleMatch[1], 'compiler.runtime': null };
|
|
101
|
+
}
|
|
102
|
+
const llvmMatch = clang.match(/version (\d+)/);
|
|
103
|
+
return {
|
|
104
|
+
compiler: 'clang',
|
|
105
|
+
'compiler.version': llvmMatch ? llvmMatch[1] : 'unknown',
|
|
106
|
+
'compiler.runtime': null,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return { compiler: 'unknown', 'compiler.version': 'unknown', 'compiler.runtime': null };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function detectCompilerLinux() {
|
|
113
|
+
// Prefer GCC on Linux
|
|
114
|
+
const gcc = tryExec('gcc --version');
|
|
115
|
+
if (gcc) {
|
|
116
|
+
const m = gcc.match(/(\d+\.\d+\.\d+)/);
|
|
117
|
+
if (m) {
|
|
118
|
+
return {
|
|
119
|
+
compiler: 'gcc',
|
|
120
|
+
'compiler.version': m[1].split('.')[0],
|
|
121
|
+
'compiler.runtime': null,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const clang = tryExec('clang --version');
|
|
127
|
+
if (clang) {
|
|
128
|
+
const m = clang.match(/version (\d+)/);
|
|
129
|
+
return {
|
|
130
|
+
compiler: 'clang',
|
|
131
|
+
'compiler.version': m ? m[1] : 'unknown',
|
|
132
|
+
'compiler.runtime': null,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return { compiler: 'unknown', 'compiler.version': 'unknown', 'compiler.runtime': null };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ---------------------------------------------------------------------------
|
|
140
|
+
// Public API
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Auto-detect the current build environment profile.
|
|
145
|
+
* Mirrors Conan 2.0 profile structure.
|
|
146
|
+
*
|
|
147
|
+
* @returns {WyvrnProfile}
|
|
148
|
+
*/
|
|
149
|
+
function detectProfile() {
|
|
150
|
+
const compilerInfo =
|
|
151
|
+
process.platform === 'win32' ? detectCompilerWindows()
|
|
152
|
+
: process.platform === 'darwin' ? detectCompilerMacos()
|
|
153
|
+
: detectCompilerLinux();
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
os: detectOs(),
|
|
157
|
+
arch: detectArch(),
|
|
158
|
+
compiler: compilerInfo.compiler,
|
|
159
|
+
'compiler.version': compilerInfo['compiler.version'],
|
|
160
|
+
'compiler.cppstd': '20',
|
|
161
|
+
'compiler.runtime': compilerInfo['compiler.runtime'],
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Compute a stable 16-char SHA256 prefix that identifies a unique build profile.
|
|
167
|
+
* Only non-null, non-wildcard fields contribute to the hash.
|
|
168
|
+
*
|
|
169
|
+
* @param {WyvrnProfile} profile
|
|
170
|
+
* @returns {string} 16-character lowercase hex string
|
|
171
|
+
*/
|
|
172
|
+
function hashProfile(profile) {
|
|
173
|
+
const significant = Object.fromEntries(
|
|
174
|
+
Object.entries(profile)
|
|
175
|
+
.filter(([, v]) => v !== null && v !== undefined && v !== '*' && v !== '')
|
|
176
|
+
.sort(([a], [b]) => a.localeCompare(b)),
|
|
177
|
+
);
|
|
178
|
+
return crypto
|
|
179
|
+
.createHash('sha256')
|
|
180
|
+
.update(JSON.stringify(significant))
|
|
181
|
+
.digest('hex')
|
|
182
|
+
.slice(0, 16);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Compute the SHA256 hash of a file or Buffer.
|
|
187
|
+
*
|
|
188
|
+
* @param {string|Buffer} source - Absolute path to a file, or a Buffer.
|
|
189
|
+
* @returns {string} Full 64-character lowercase hex SHA256.
|
|
190
|
+
*/
|
|
191
|
+
function sha256Of(source) {
|
|
192
|
+
const buf = Buffer.isBuffer(source) ? source : fs.readFileSync(source);
|
|
193
|
+
return crypto.createHash('sha256').update(buf).digest('hex');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Try to get the current git commit SHA in the given directory.
|
|
198
|
+
*
|
|
199
|
+
* @param {string} [cwd] - Directory to run git in (defaults to process.cwd()).
|
|
200
|
+
* @returns {string|null}
|
|
201
|
+
*/
|
|
202
|
+
function getGitSha(cwd) {
|
|
203
|
+
const result = tryExec(`git -C "${cwd || '.'}" rev-parse HEAD`);
|
|
204
|
+
return result && /^[0-9a-f]{40}$/i.test(result) ? result : null;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Try to get the remote origin URL for the current git repo.
|
|
209
|
+
*
|
|
210
|
+
* @param {string} [cwd]
|
|
211
|
+
* @returns {string|null}
|
|
212
|
+
*/
|
|
213
|
+
function getGitRepo(cwd) {
|
|
214
|
+
return tryExec(`git -C "${cwd || '.'}" remote get-url origin`) || null;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Format a profile for human-readable display (Conan-style).
|
|
219
|
+
*
|
|
220
|
+
* @param {WyvrnProfile} profile
|
|
221
|
+
* @returns {string}
|
|
222
|
+
*/
|
|
223
|
+
function formatProfile(profile) {
|
|
224
|
+
const fieldOrder = [
|
|
225
|
+
'os', 'arch', 'compiler', 'compiler.version', 'compiler.cppstd', 'compiler.runtime',
|
|
226
|
+
];
|
|
227
|
+
const lines = ['[settings]'];
|
|
228
|
+
for (const key of fieldOrder) {
|
|
229
|
+
const val = profile[key];
|
|
230
|
+
if (val !== null && val !== undefined) {
|
|
231
|
+
lines.push(`${key}=${val}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return lines.join('\n');
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Merge a partial override into a base profile, ignoring null/undefined overrides.
|
|
239
|
+
*
|
|
240
|
+
* @param {WyvrnProfile} base
|
|
241
|
+
* @param {Partial<WyvrnProfile>} overrides
|
|
242
|
+
* @returns {WyvrnProfile}
|
|
243
|
+
*/
|
|
244
|
+
function mergeProfile(base, overrides) {
|
|
245
|
+
return {
|
|
246
|
+
...base,
|
|
247
|
+
...Object.fromEntries(Object.entries(overrides).filter(([, v]) => v != null)),
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// ---------------------------------------------------------------------------
|
|
252
|
+
// Profile file management
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Returns the directory where named build profiles are stored.
|
|
257
|
+
* Windows : %LOCALAPPDATA%\wyvrnpm\profiles
|
|
258
|
+
* Other : ~/.config/wyvrnpm/profiles
|
|
259
|
+
*
|
|
260
|
+
* @returns {string}
|
|
261
|
+
*/
|
|
262
|
+
function getProfilesDir() {
|
|
263
|
+
const base = process.env.LOCALAPPDATA
|
|
264
|
+
? path.join(process.env.LOCALAPPDATA, 'wyvrnpm')
|
|
265
|
+
: path.join(require('os').homedir(), '.config', 'wyvrnpm');
|
|
266
|
+
return path.join(base, 'profiles');
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Read a named profile from the profiles directory.
|
|
271
|
+
* Looks for `{name}.json`, then `{name}` without extension.
|
|
272
|
+
*
|
|
273
|
+
* @param {string} name - Profile name (e.g. "default", "msvc_release").
|
|
274
|
+
* @returns {WyvrnProfile|null} Parsed profile, or null if not found.
|
|
275
|
+
*/
|
|
276
|
+
function readProfile(name) {
|
|
277
|
+
const dir = getProfilesDir();
|
|
278
|
+
for (const filename of [`${name}.json`, name]) {
|
|
279
|
+
const p = path.join(dir, filename);
|
|
280
|
+
if (fs.existsSync(p)) {
|
|
281
|
+
try { return JSON.parse(fs.readFileSync(p, 'utf8')); }
|
|
282
|
+
catch { return null; }
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Write a named profile to the profiles directory as `{name}.json`.
|
|
290
|
+
*
|
|
291
|
+
* @param {string} name
|
|
292
|
+
* @param {WyvrnProfile} profile
|
|
293
|
+
*/
|
|
294
|
+
function writeProfile(name, profile) {
|
|
295
|
+
const dir = getProfilesDir();
|
|
296
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
297
|
+
fs.writeFileSync(
|
|
298
|
+
path.join(dir, `${name}.json`),
|
|
299
|
+
JSON.stringify(profile, null, 2) + '\n',
|
|
300
|
+
'utf8',
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Delete a named profile file. Does nothing if the profile does not exist.
|
|
306
|
+
*
|
|
307
|
+
* @param {string} name
|
|
308
|
+
* @returns {boolean} true if a file was deleted.
|
|
309
|
+
*/
|
|
310
|
+
function deleteProfile(name) {
|
|
311
|
+
const dir = getProfilesDir();
|
|
312
|
+
for (const filename of [`${name}.json`, name]) {
|
|
313
|
+
const p = path.join(dir, filename);
|
|
314
|
+
if (fs.existsSync(p)) {
|
|
315
|
+
fs.unlinkSync(p);
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* List all profile names available in the profiles directory.
|
|
324
|
+
*
|
|
325
|
+
* @returns {string[]} Sorted list of profile names (without `.json` extension).
|
|
326
|
+
*/
|
|
327
|
+
function listProfiles() {
|
|
328
|
+
const dir = getProfilesDir();
|
|
329
|
+
if (!fs.existsSync(dir)) return [];
|
|
330
|
+
return fs
|
|
331
|
+
.readdirSync(dir)
|
|
332
|
+
.filter((f) => f.endsWith('.json'))
|
|
333
|
+
.map((f) => f.slice(0, -5))
|
|
334
|
+
.sort();
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Load the active build profile by name. Falls back to auto-detection if the
|
|
339
|
+
* named profile file does not exist yet.
|
|
340
|
+
*
|
|
341
|
+
* @param {string} [name='default']
|
|
342
|
+
* @returns {{ profile: WyvrnProfile, fromFile: boolean }}
|
|
343
|
+
*/
|
|
344
|
+
function loadProfile(name = 'default') {
|
|
345
|
+
const stored = readProfile(name);
|
|
346
|
+
if (stored) return { profile: stored, fromFile: true };
|
|
347
|
+
return { profile: detectProfile(), fromFile: false };
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
module.exports = {
|
|
351
|
+
// Detection
|
|
352
|
+
detectProfile,
|
|
353
|
+
hashProfile,
|
|
354
|
+
sha256Of,
|
|
355
|
+
getGitSha,
|
|
356
|
+
getGitRepo,
|
|
357
|
+
formatProfile,
|
|
358
|
+
mergeProfile,
|
|
359
|
+
// Profile file management
|
|
360
|
+
getProfilesDir,
|
|
361
|
+
readProfile,
|
|
362
|
+
writeProfile,
|
|
363
|
+
deleteProfile,
|
|
364
|
+
listProfiles,
|
|
365
|
+
loadProfile,
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* @typedef {{
|
|
370
|
+
* os: string,
|
|
371
|
+
* arch: string,
|
|
372
|
+
* compiler: string,
|
|
373
|
+
* 'compiler.version': string,
|
|
374
|
+
* 'compiler.cppstd': string,
|
|
375
|
+
* 'compiler.runtime': string|null,
|
|
376
|
+
* }} WyvrnProfile
|
|
377
|
+
*/
|
package/src/providers/base.js
CHANGED
|
@@ -6,6 +6,19 @@
|
|
|
6
6
|
* To add a new provider:
|
|
7
7
|
* 1. Create src/providers/<name>.js that extends BaseProvider
|
|
8
8
|
* 2. Register it in src/providers/index.js
|
|
9
|
+
*
|
|
10
|
+
* ─── Schema versions ────────────────────────────────────────────────────────
|
|
11
|
+
*
|
|
12
|
+
* v1 (legacy): {source}/{platform}/{name}/{version}/wyvrn.{json,zip}
|
|
13
|
+
* {source}/{platform}/{name}/latest.json
|
|
14
|
+
*
|
|
15
|
+
* v2: {source}/v2/{name}/{version}/{profileHash}/wyvrn.{json,zip}
|
|
16
|
+
* {source}/v2/{name}/{version}/source.json
|
|
17
|
+
* {source}/v2/{name}/versions.json
|
|
18
|
+
* {source}/v2/{name}/latest.json
|
|
19
|
+
*
|
|
20
|
+
* Publishing with v2 tooling writes both v2 AND v1 paths by default so that
|
|
21
|
+
* v1 clients can still consume the packages.
|
|
9
22
|
*/
|
|
10
23
|
class BaseProvider {
|
|
11
24
|
/**
|
|
@@ -18,18 +31,13 @@ class BaseProvider {
|
|
|
18
31
|
return false;
|
|
19
32
|
}
|
|
20
33
|
|
|
34
|
+
// ── v1 (legacy) API ────────────────────────────────────────────────────────
|
|
35
|
+
|
|
21
36
|
/**
|
|
22
|
-
* Publish package files to the destination.
|
|
37
|
+
* Publish package files to the v1 destination path.
|
|
23
38
|
*
|
|
24
39
|
* @param {{ manifest: string, zip: string }} files
|
|
25
|
-
*
|
|
26
|
-
* @param {{ source: string, platform: string, name: string, version: string, profile?: string, token?: string }} options
|
|
27
|
-
* `source` – the raw --source value (URL / URI)
|
|
28
|
-
* `platform` – target platform string (e.g. win_x64)
|
|
29
|
-
* `name` – package name from manifest
|
|
30
|
-
* `version` – package version from manifest
|
|
31
|
-
* `profile` – AWS SSO profile (S3 provider)
|
|
32
|
-
* `token` – Bearer token (HTTP provider)
|
|
40
|
+
* @param {{ source: string, platform: string, name: string, version: string, awsProfile?: string, token?: string }} options
|
|
33
41
|
* @returns {Promise<void>}
|
|
34
42
|
*/
|
|
35
43
|
async publish(_files, _options) {
|
|
@@ -37,16 +45,85 @@ class BaseProvider {
|
|
|
37
45
|
}
|
|
38
46
|
|
|
39
47
|
/**
|
|
40
|
-
* Returns true if the given package version already exists at the destination.
|
|
41
|
-
* Providers should override this; the default assumes it does not exist.
|
|
48
|
+
* Returns true if the given package version already exists at the v1 destination.
|
|
42
49
|
*
|
|
43
|
-
* @param {{ source: string, platform: string, name: string, version: string,
|
|
50
|
+
* @param {{ source: string, platform: string, name: string, version: string, awsProfile?: string, token?: string }} _options
|
|
44
51
|
* @returns {Promise<boolean>}
|
|
45
52
|
*/
|
|
46
53
|
async exists(_options) {
|
|
47
54
|
return false;
|
|
48
55
|
}
|
|
49
56
|
|
|
57
|
+
// ── v2 API ─────────────────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Returns true if a prebuilt binary matching the given profile hash already
|
|
61
|
+
* exists at the v2 destination.
|
|
62
|
+
*
|
|
63
|
+
* @param {{ source: string, name: string, version: string, profileHash: string, awsProfile?: string, token?: string }} _options
|
|
64
|
+
* @returns {Promise<boolean>}
|
|
65
|
+
*/
|
|
66
|
+
async v2Exists(_options) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Publish to the v2 path.
|
|
72
|
+
* Writes wyvrn.json + wyvrn.zip under profileHash, updates versions.json and latest.json.
|
|
73
|
+
*
|
|
74
|
+
* @param {{ manifest: string, zip: string }} files - local file paths
|
|
75
|
+
* @param {{
|
|
76
|
+
* source: string,
|
|
77
|
+
* name: string,
|
|
78
|
+
* version: string,
|
|
79
|
+
* profileHash: string,
|
|
80
|
+
* buildSettings: import('../profile').WyvrnProfile, // stored in metadata for debugging
|
|
81
|
+
* contentSha256: string,
|
|
82
|
+
* gitSha: string|null,
|
|
83
|
+
* gitRepo: string|null,
|
|
84
|
+
* awsProfile?: string,
|
|
85
|
+
* token?: string,
|
|
86
|
+
* }} options
|
|
87
|
+
* @returns {Promise<void>}
|
|
88
|
+
*/
|
|
89
|
+
async v2Publish(_files, _options) {
|
|
90
|
+
throw new Error(`v2Publish() is not implemented in ${this.constructor.name}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Fetch the wyvrn.json metadata object for a specific v2 build.
|
|
95
|
+
* Returns null if the build does not exist.
|
|
96
|
+
*
|
|
97
|
+
* @param {{ source: string, name: string, version: string, profileHash: string, awsProfile?: string, token?: string }} _options
|
|
98
|
+
* @returns {Promise<object|null>}
|
|
99
|
+
*/
|
|
100
|
+
async v2GetMeta(_options) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Fetch and return the parsed versions.json index for a package.
|
|
106
|
+
* Returns null if no index exists yet.
|
|
107
|
+
*
|
|
108
|
+
* @param {{ source: string, name: string, awsProfile?: string, token?: string }} _options
|
|
109
|
+
* @returns {Promise<object|null>}
|
|
110
|
+
*/
|
|
111
|
+
async v2GetVersionsIndex(_options) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Download the prebuilt binary zip for a specific v2 build to destPath.
|
|
117
|
+
*
|
|
118
|
+
* @param {{ source: string, name: string, version: string, profileHash: string, awsProfile?: string, token?: string }} options
|
|
119
|
+
* @param {string} destPath - absolute path to write the zip to
|
|
120
|
+
* @param {number} timeoutMs
|
|
121
|
+
* @returns {Promise<boolean>} true on success
|
|
122
|
+
*/
|
|
123
|
+
async v2DownloadZip(_options, _destPath, _timeoutMs) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
|
|
50
127
|
/** Human-readable provider name shown in log output. */
|
|
51
128
|
static get providerName() {
|
|
52
129
|
return 'BaseProvider';
|