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
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
detectProfile,
|
|
5
|
+
hashProfile,
|
|
6
|
+
formatProfile,
|
|
7
|
+
readProfile,
|
|
8
|
+
writeProfile,
|
|
9
|
+
deleteProfile,
|
|
10
|
+
listProfiles,
|
|
11
|
+
getProfilesDir,
|
|
12
|
+
mergeProfile,
|
|
13
|
+
} = require('../profile');
|
|
14
|
+
const { readConfig, writeConfig } = require('../config');
|
|
15
|
+
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// list
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* wyvrnpm configure profile list
|
|
22
|
+
* Show all saved profiles and which one is the default.
|
|
23
|
+
*/
|
|
24
|
+
function list() {
|
|
25
|
+
const config = readConfig();
|
|
26
|
+
const names = listProfiles();
|
|
27
|
+
const dir = getProfilesDir();
|
|
28
|
+
const defName = config.defaultProfile ?? 'default';
|
|
29
|
+
|
|
30
|
+
console.log(`[wyvrn] Profiles directory: ${dir}`);
|
|
31
|
+
console.log(`[wyvrn] Default profile : ${defName}\n`);
|
|
32
|
+
|
|
33
|
+
if (names.length === 0) {
|
|
34
|
+
console.log(' (no profiles saved — run `wyvrnpm configure profile detect` to create one)');
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
for (const name of names) {
|
|
39
|
+
const marker = name === defName ? ' *' : '';
|
|
40
|
+
const p = readProfile(name);
|
|
41
|
+
const summary = p
|
|
42
|
+
? `${p.os}/${p.arch} ${p.compiler} ${p['compiler.version']} C++${p['compiler.cppstd']}` +
|
|
43
|
+
(p['compiler.runtime'] ? ` [${p['compiler.runtime']}]` : '')
|
|
44
|
+
: '(unreadable)';
|
|
45
|
+
console.log(` ${(name + marker).padEnd(24)} ${summary}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// show
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* wyvrnpm configure profile show [--name <name>]
|
|
55
|
+
* Display a specific profile (defaults to the configured default).
|
|
56
|
+
*/
|
|
57
|
+
function show(argv) {
|
|
58
|
+
const config = readConfig();
|
|
59
|
+
const name = argv.name ?? config.defaultProfile ?? 'default';
|
|
60
|
+
const stored = readProfile(name);
|
|
61
|
+
|
|
62
|
+
if (stored) {
|
|
63
|
+
console.log(`[wyvrn] Profile "${name}":`);
|
|
64
|
+
console.log(formatProfile(stored));
|
|
65
|
+
console.log(`\nProfile hash : ${hashProfile(stored)}`);
|
|
66
|
+
} else {
|
|
67
|
+
const detected = detectProfile();
|
|
68
|
+
console.log(`[wyvrn] Profile "${name}" not found — showing auto-detected environment:`);
|
|
69
|
+
console.log(formatProfile(detected));
|
|
70
|
+
console.log(`\nProfile hash : ${hashProfile(detected)}`);
|
|
71
|
+
console.log(`\nRun \`wyvrnpm configure profile detect --name ${name}\` to save this.`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
// detect
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* wyvrnpm configure profile detect [--name <name>] [--dry-run]
|
|
81
|
+
* Auto-detect the current build environment and save it as a named profile.
|
|
82
|
+
*/
|
|
83
|
+
function detect(argv) {
|
|
84
|
+
const config = readConfig();
|
|
85
|
+
const name = argv.name ?? config.defaultProfile ?? 'default';
|
|
86
|
+
const p = detectProfile();
|
|
87
|
+
|
|
88
|
+
console.log('[wyvrn] Detected profile:');
|
|
89
|
+
console.log(formatProfile(p));
|
|
90
|
+
console.log(`\nProfile hash : ${hashProfile(p)}`);
|
|
91
|
+
|
|
92
|
+
if (!argv.dryRun) {
|
|
93
|
+
writeProfile(name, p);
|
|
94
|
+
console.log(`\n[wyvrn] Saved as profile "${name}".`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// set
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* wyvrnpm configure profile set [--name <name>] [field options]
|
|
104
|
+
* Manually override individual fields in a named profile.
|
|
105
|
+
* Starts from the existing saved profile, or auto-detects if none exists yet.
|
|
106
|
+
*/
|
|
107
|
+
function set(argv) {
|
|
108
|
+
const config = readConfig();
|
|
109
|
+
const name = argv.name ?? config.defaultProfile ?? 'default';
|
|
110
|
+
const base = readProfile(name) ?? detectProfile();
|
|
111
|
+
|
|
112
|
+
const updated = mergeProfile(base, {
|
|
113
|
+
os: argv.os ?? null,
|
|
114
|
+
arch: argv.arch ?? null,
|
|
115
|
+
compiler: argv.compiler ?? null,
|
|
116
|
+
'compiler.version': argv.compilerVersion ?? null,
|
|
117
|
+
'compiler.cppstd': argv.cppstd ?? null,
|
|
118
|
+
'compiler.runtime': argv.runtime ?? null,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
writeProfile(name, updated);
|
|
122
|
+
|
|
123
|
+
console.log(`[wyvrn] Profile "${name}" updated:`);
|
|
124
|
+
console.log(formatProfile(updated));
|
|
125
|
+
console.log(`\nProfile hash : ${hashProfile(updated)}`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
// setDefault
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* wyvrnpm configure profile set-default <name>
|
|
134
|
+
* Change which named profile is used by default.
|
|
135
|
+
*/
|
|
136
|
+
function setDefault(argv) {
|
|
137
|
+
const name = argv.name;
|
|
138
|
+
if (!readProfile(name)) {
|
|
139
|
+
console.error(`[wyvrn] Error: profile "${name}" does not exist. Create it first.`);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
const config = readConfig();
|
|
143
|
+
config.defaultProfile = name;
|
|
144
|
+
writeConfig(config);
|
|
145
|
+
console.log(`[wyvrn] Default profile set to "${name}".`);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
149
|
+
// del
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* wyvrnpm configure profile delete <name>
|
|
154
|
+
* Remove a saved profile file.
|
|
155
|
+
*/
|
|
156
|
+
function del(argv) {
|
|
157
|
+
const name = argv.name;
|
|
158
|
+
if (name === 'default') {
|
|
159
|
+
console.error('[wyvrn] Error: cannot delete the "default" profile.');
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
const removed = deleteProfile(name);
|
|
163
|
+
if (removed) {
|
|
164
|
+
console.log(`[wyvrn] Profile "${name}" deleted.`);
|
|
165
|
+
} else {
|
|
166
|
+
console.error(`[wyvrn] Error: profile "${name}" not found.`);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
module.exports = { list, show, detect, set, setDefault, del };
|
package/src/commands/publish.js
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const fs
|
|
3
|
+
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
|
-
const os
|
|
5
|
+
const os = require('os');
|
|
6
6
|
const AdmZip = require('adm-zip');
|
|
7
|
-
|
|
8
|
-
const {
|
|
9
|
-
const {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
|
|
8
|
+
const { readManifest } = require('../manifest');
|
|
9
|
+
const { getProvider } = require('../providers');
|
|
10
|
+
const { readConfig } = require('../config');
|
|
11
|
+
const { loadProfile, hashProfile, sha256Of, getGitSha, getGitRepo } = require('../profile');
|
|
12
|
+
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// .wyvrnignore helpers (unchanged from v1)
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
|
|
15
17
|
function loadIgnorePatterns(ignoreFile) {
|
|
16
18
|
if (!fs.existsSync(ignoreFile)) return [];
|
|
17
19
|
return fs
|
|
@@ -21,46 +23,26 @@ function loadIgnorePatterns(ignoreFile) {
|
|
|
21
23
|
.filter((l) => l.length > 0 && !l.startsWith('#'));
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
/**
|
|
25
|
-
* Convert a glob-style ignore pattern to a RegExp.
|
|
26
|
-
* Supports '*', '**', '?' wildcards and leading '/' to anchor to root.
|
|
27
|
-
*/
|
|
28
26
|
function patternToRegex(pattern) {
|
|
29
|
-
// A leading slash means "anchored to root"; strip it and keep the rest
|
|
30
27
|
const anchored = pattern.startsWith('/');
|
|
31
28
|
const p = anchored ? pattern.slice(1) : pattern;
|
|
32
|
-
|
|
33
29
|
let re = p
|
|
34
|
-
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
35
|
-
.replace(/\*\*/g, '\x00')
|
|
36
|
-
.replace(/\*/g, '[^/]*')
|
|
37
|
-
.replace(/\?/g, '[^/]')
|
|
38
|
-
.replace(/\x00/g, '.*');
|
|
39
|
-
|
|
40
|
-
// If anchored, match from the start; otherwise match any path segment
|
|
30
|
+
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
31
|
+
.replace(/\*\*/g, '\x00')
|
|
32
|
+
.replace(/\*/g, '[^/]*')
|
|
33
|
+
.replace(/\?/g, '[^/]')
|
|
34
|
+
.replace(/\x00/g, '.*');
|
|
41
35
|
return anchored ? new RegExp(`^${re}(/|$)`) : new RegExp(`(^|/)${re}(/|$)`);
|
|
42
36
|
}
|
|
43
37
|
|
|
44
|
-
/**
|
|
45
|
-
* Recursively add files from `dir` into `zip`, skipping any path that
|
|
46
|
-
* matches one of the compiled ignore regexes.
|
|
47
|
-
*
|
|
48
|
-
* @param {AdmZip} zip
|
|
49
|
-
* @param {string} dir Absolute path of the directory being zipped
|
|
50
|
-
* @param {string} base Absolute path of the root publish directory
|
|
51
|
-
* @param {RegExp[]} ignoreRe Compiled ignore patterns
|
|
52
|
-
*/
|
|
53
38
|
function addFolderFiltered(zip, dir, base, ignoreRe) {
|
|
54
39
|
for (const entry of fs.readdirSync(dir)) {
|
|
55
40
|
const fullPath = path.join(dir, entry);
|
|
56
|
-
|
|
57
|
-
const relPath = path.relative(base, fullPath).replace(/\\/g, '/');
|
|
58
|
-
|
|
41
|
+
const relPath = path.relative(base, fullPath).replace(/\\/g, '/');
|
|
59
42
|
if (ignoreRe.some((re) => re.test(relPath))) {
|
|
60
43
|
console.log(`[wyvrn] Ignoring: ${relPath}`);
|
|
61
44
|
continue;
|
|
62
45
|
}
|
|
63
|
-
|
|
64
46
|
const stat = fs.statSync(fullPath);
|
|
65
47
|
if (stat.isDirectory()) {
|
|
66
48
|
addFolderFiltered(zip, fullPath, base, ignoreRe);
|
|
@@ -71,23 +53,23 @@ function addFolderFiltered(zip, dir, base, ignoreRe) {
|
|
|
71
53
|
}
|
|
72
54
|
}
|
|
73
55
|
|
|
74
|
-
|
|
75
|
-
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Source resolution
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
|
|
60
|
+
function resolveSource(argv) {
|
|
61
|
+
let { source, awsProfile, token } = argv;
|
|
62
|
+
const config = readConfig();
|
|
76
63
|
|
|
77
|
-
// Resolve source + auth: CLI > config entry by name > first config entry > raw URL
|
|
78
64
|
if (source) {
|
|
79
|
-
// Check if --source matches a named config entry rather than a raw URL/URI
|
|
80
|
-
const config = readConfig();
|
|
81
65
|
const named = config.publishSources.find((s) => s.name === source);
|
|
82
66
|
if (named) {
|
|
83
67
|
console.log(`[wyvrn] Using publish source "${named.name}" from config`);
|
|
84
|
-
source
|
|
85
|
-
|
|
86
|
-
token
|
|
68
|
+
source = named.url;
|
|
69
|
+
awsProfile = awsProfile ?? named.profile;
|
|
70
|
+
token = token ?? named.token;
|
|
87
71
|
}
|
|
88
72
|
} else {
|
|
89
|
-
// No --source given — fall back to first configured publish source
|
|
90
|
-
const config = readConfig();
|
|
91
73
|
if (config.publishSources.length === 0) {
|
|
92
74
|
console.error(
|
|
93
75
|
'[wyvrn] Error: --source is required (or configure one with: ' +
|
|
@@ -97,12 +79,28 @@ async function publish(argv) {
|
|
|
97
79
|
}
|
|
98
80
|
const first = config.publishSources[0];
|
|
99
81
|
console.log(`[wyvrn] Using publish source "${first.name}" from config`);
|
|
100
|
-
source
|
|
101
|
-
|
|
102
|
-
token
|
|
82
|
+
source = first.url;
|
|
83
|
+
awsProfile = awsProfile ?? first.profile;
|
|
84
|
+
token = token ?? first.token;
|
|
103
85
|
}
|
|
104
86
|
|
|
105
|
-
|
|
87
|
+
return { source, awsProfile, token };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Main publish command
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
async function publish(argv) {
|
|
95
|
+
const { source, awsProfile, token } = resolveSource(argv);
|
|
96
|
+
const {
|
|
97
|
+
profile: profileName,
|
|
98
|
+
path: publishPath,
|
|
99
|
+
force,
|
|
100
|
+
manifest: manifestArg,
|
|
101
|
+
} = argv;
|
|
102
|
+
|
|
103
|
+
// ── Load manifest ─────────────────────────────────────────────────────────
|
|
106
104
|
const manifestPath = path.resolve(manifestArg || './wyvrn.json');
|
|
107
105
|
const manifest = await readManifest(manifestPath);
|
|
108
106
|
if (!manifest) {
|
|
@@ -116,15 +114,13 @@ async function publish(argv) {
|
|
|
116
114
|
process.exit(1);
|
|
117
115
|
}
|
|
118
116
|
|
|
119
|
-
const targetPlatform = platform || 'common';
|
|
120
117
|
const srcDir = path.resolve(publishPath || '.');
|
|
121
|
-
|
|
122
118
|
if (!fs.existsSync(srcDir)) {
|
|
123
119
|
console.error(`[wyvrn] Error: Publish path does not exist: ${srcDir}`);
|
|
124
120
|
process.exit(1);
|
|
125
121
|
}
|
|
126
122
|
|
|
127
|
-
// Resolve provider
|
|
123
|
+
// ── Resolve provider ──────────────────────────────────────────────────────
|
|
128
124
|
let provider;
|
|
129
125
|
try {
|
|
130
126
|
provider = getProvider(source);
|
|
@@ -133,24 +129,62 @@ async function publish(argv) {
|
|
|
133
129
|
process.exit(1);
|
|
134
130
|
}
|
|
135
131
|
|
|
132
|
+
// ── Load build profile ────────────────────────────────────────────────────
|
|
133
|
+
const config = readConfig();
|
|
134
|
+
const activeProfileName = profileName ?? config.defaultProfile ?? 'default';
|
|
135
|
+
const { profile: buildProfile, fromFile } = loadProfile(activeProfileName);
|
|
136
|
+
const profileHash = hashProfile(buildProfile);
|
|
137
|
+
|
|
136
138
|
console.log(
|
|
137
|
-
`[wyvrn] Publishing ${name}@${version}
|
|
139
|
+
`[wyvrn] Publishing ${name}@${version}\n` +
|
|
140
|
+
`[wyvrn] Profile : "${activeProfileName}"${fromFile ? '' : ' (auto-detected — save with `wyvrnpm configure profile detect`)'}\n` +
|
|
141
|
+
`[wyvrn] ${buildProfile.os}/${buildProfile.arch} ` +
|
|
142
|
+
`${buildProfile.compiler} ${buildProfile['compiler.version']} ` +
|
|
143
|
+
`C++${buildProfile['compiler.cppstd']}` +
|
|
144
|
+
(buildProfile['compiler.runtime'] ? ` [${buildProfile['compiler.runtime']}]` : '') + '\n' +
|
|
145
|
+
`[wyvrn] Profile hash: ${profileHash}\n` +
|
|
146
|
+
`[wyvrn] Provider : ${provider.constructor.providerName}`,
|
|
138
147
|
);
|
|
139
148
|
|
|
140
|
-
//
|
|
141
|
-
const
|
|
142
|
-
if (
|
|
149
|
+
// ── Check v2 existence ────────────────────────────────────────────────────
|
|
150
|
+
const v2AlreadyExists = await provider.v2Exists({ source, name, version, profileHash, awsProfile, token });
|
|
151
|
+
if (v2AlreadyExists) {
|
|
143
152
|
if (force) {
|
|
144
|
-
console.warn(`[wyvrn] Warning: ${name}@${version} already exists — overwriting (--force)`);
|
|
153
|
+
console.warn(`[wyvrn] Warning: ${name}@${version} [${profileHash}] already exists — overwriting (--force)`);
|
|
145
154
|
} else {
|
|
146
155
|
console.error(
|
|
147
|
-
`[wyvrn] Error: ${name}@${version} already exists
|
|
156
|
+
`[wyvrn] Error: ${name}@${version} [${profileHash}] already exists.\n` +
|
|
157
|
+
' Bump the version, use a different profile, or pass --force to overwrite.',
|
|
148
158
|
);
|
|
149
159
|
process.exit(1);
|
|
150
160
|
}
|
|
151
161
|
}
|
|
152
162
|
|
|
153
|
-
//
|
|
163
|
+
// ── Read locked dependency versions from wyvrn.lock ──────────────────────
|
|
164
|
+
const lockPath = path.join(path.dirname(manifestPath), 'wyvrn.lock');
|
|
165
|
+
const lockedDependencies = {};
|
|
166
|
+
if (fs.existsSync(lockPath)) {
|
|
167
|
+
try {
|
|
168
|
+
const lock = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
|
|
169
|
+
for (const [pkgName, entry] of Object.entries(lock.packages ?? {})) {
|
|
170
|
+
const ver = typeof entry === 'string' ? entry : entry.version;
|
|
171
|
+
if (ver) lockedDependencies[pkgName] = ver;
|
|
172
|
+
}
|
|
173
|
+
console.log(`[wyvrn] Lock file : ${Object.keys(lockedDependencies).length} pinned package(s)`);
|
|
174
|
+
} catch {
|
|
175
|
+
console.warn('[wyvrn] Warning: could not read wyvrn.lock — dependency versions will be published as-is from wyvrn.json');
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
178
|
+
console.warn('[wyvrn] Warning: no wyvrn.lock found — run `wyvrnpm install` before publishing to pin dependency versions');
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ── Git metadata ──────────────────────────────────────────────────────────
|
|
182
|
+
const gitSha = getGitSha(srcDir);
|
|
183
|
+
const gitRepo = getGitRepo(srcDir);
|
|
184
|
+
if (gitSha) console.log(`[wyvrn] Git commit : ${gitSha}`);
|
|
185
|
+
if (gitRepo) console.log(`[wyvrn] Git remote : ${gitRepo}`);
|
|
186
|
+
|
|
187
|
+
// ── .wyvrnignore ──────────────────────────────────────────────────────────
|
|
154
188
|
const ignoreFile = path.join(srcDir, '.wyvrnignore');
|
|
155
189
|
const ignorePatterns = loadIgnorePatterns(ignoreFile);
|
|
156
190
|
const ignoreRe = ignorePatterns.map(patternToRegex);
|
|
@@ -158,7 +192,7 @@ async function publish(argv) {
|
|
|
158
192
|
console.log(`[wyvrn] Loaded ${ignorePatterns.length} pattern(s) from .wyvrnignore`);
|
|
159
193
|
}
|
|
160
194
|
|
|
161
|
-
// Build
|
|
195
|
+
// ── Build zip ─────────────────────────────────────────────────────────────
|
|
162
196
|
const tmpZipPath = path.join(os.tmpdir(), `wyvrnpm-${name}-${version}-${Date.now()}.zip`);
|
|
163
197
|
try {
|
|
164
198
|
console.log(`[wyvrn] Zipping ${srcDir} ...`);
|
|
@@ -166,12 +200,30 @@ async function publish(argv) {
|
|
|
166
200
|
addFolderFiltered(zip, srcDir, srcDir, ignoreRe);
|
|
167
201
|
zip.writeZip(tmpZipPath);
|
|
168
202
|
|
|
169
|
-
|
|
203
|
+
const contentSha256 = sha256Of(tmpZipPath);
|
|
204
|
+
console.log(`[wyvrn] Content SHA256 : ${contentSha256}`);
|
|
205
|
+
|
|
206
|
+
// ── v2 publish ────────────────────────────────────────────────────────
|
|
207
|
+
console.log('[wyvrn] Publishing (v2) ...');
|
|
208
|
+
await provider.v2Publish(
|
|
170
209
|
{ manifest: manifestPath, zip: tmpZipPath },
|
|
171
|
-
{
|
|
210
|
+
{
|
|
211
|
+
source,
|
|
212
|
+
name,
|
|
213
|
+
version,
|
|
214
|
+
profileHash,
|
|
215
|
+
// buildSettings stored in metadata for debugging — NOT wyvrn.json
|
|
216
|
+
buildSettings: buildProfile,
|
|
217
|
+
contentSha256,
|
|
218
|
+
gitSha,
|
|
219
|
+
gitRepo,
|
|
220
|
+
lockedDependencies,
|
|
221
|
+
awsProfile,
|
|
222
|
+
token,
|
|
223
|
+
},
|
|
172
224
|
);
|
|
173
225
|
|
|
174
|
-
console.log(`[wyvrn] Successfully published ${name}@${version} to ${source}`);
|
|
226
|
+
console.log(`[wyvrn] Successfully published ${name}@${version} [${profileHash}] to ${source}`);
|
|
175
227
|
} finally {
|
|
176
228
|
if (fs.existsSync(tmpZipPath)) fs.unlinkSync(tmpZipPath);
|
|
177
229
|
}
|
package/src/config.js
CHANGED
|
@@ -24,23 +24,25 @@ function getConfigPath() {
|
|
|
24
24
|
/**
|
|
25
25
|
* Read and parse config.json.
|
|
26
26
|
* Returns a default empty config if the file doesn't exist yet.
|
|
27
|
-
* @returns {{ installSources: SourceEntry[], publishSources: SourceEntry[], linkedPackages: Object<string, string
|
|
27
|
+
* @returns {{ installSources: SourceEntry[], publishSources: SourceEntry[], linkedPackages: Object<string, string>, defaultProfile: string }}
|
|
28
28
|
*/
|
|
29
29
|
function readConfig() {
|
|
30
30
|
const configPath = getConfigPath();
|
|
31
31
|
if (!fs.existsSync(configPath)) {
|
|
32
|
-
return { installSources: [], publishSources: [], linkedPackages: {} };
|
|
32
|
+
return { installSources: [], publishSources: [], linkedPackages: {}, defaultProfile: 'default' };
|
|
33
33
|
}
|
|
34
34
|
try {
|
|
35
35
|
const raw = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
36
36
|
return {
|
|
37
|
-
installSources: raw.installSources
|
|
38
|
-
publishSources: raw.publishSources
|
|
39
|
-
linkedPackages: raw.linkedPackages
|
|
37
|
+
installSources: raw.installSources ?? [],
|
|
38
|
+
publishSources: raw.publishSources ?? [],
|
|
39
|
+
linkedPackages: raw.linkedPackages ?? {},
|
|
40
|
+
// Migrate: if old config had an inline `profile` object, drop it; use file-based profiles.
|
|
41
|
+
defaultProfile: raw.defaultProfile ?? 'default',
|
|
40
42
|
};
|
|
41
43
|
} catch {
|
|
42
44
|
console.warn('[wyvrn] Warning: could not parse config.json — using defaults');
|
|
43
|
-
return { installSources: [], publishSources: [], linkedPackages: {} };
|
|
45
|
+
return { installSources: [], publishSources: [], linkedPackages: {}, defaultProfile: 'default' };
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
|