wyvrnpm 2.10.2 → 2.12.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 +1914 -1860
- package/bin/{wyvrn.js → wyvrnpm.js} +66 -0
- package/cmake/cpp.cmake +9 -9
- package/cmake/functions.cmake +224 -224
- package/cmake/macros.cmake +284 -284
- package/package.json +3 -2
- package/src/auth.js +66 -66
- package/src/binary-dir.js +95 -0
- package/src/bootstrap/cookbook.js +196 -196
- package/src/bootstrap/detect.js +150 -150
- package/src/bootstrap/index.js +220 -220
- package/src/bootstrap/version.js +72 -72
- package/src/build/cache.js +344 -344
- package/src/build/clone.js +170 -170
- package/src/build/cmake.js +342 -342
- package/src/build/index.js +299 -297
- package/src/build/msvc-env.js +260 -260
- package/src/build/recipe.js +188 -188
- package/src/commands/add.js +141 -141
- package/src/commands/bootstrap.js +96 -96
- package/src/commands/build.js +482 -452
- package/src/commands/cache.js +189 -189
- package/src/commands/clean.js +80 -80
- package/src/commands/configure.js +92 -92
- package/src/commands/init.js +70 -70
- package/src/commands/install-skill.js +115 -115
- package/src/commands/install.js +730 -674
- package/src/commands/link.js +320 -320
- package/src/commands/profile.js +237 -237
- package/src/commands/publish.js +584 -555
- package/src/commands/show.js +252 -252
- package/src/commands/version.js +187 -0
- package/src/compat.js +273 -273
- package/src/conf/index.js +415 -391
- package/src/conf/namespaces.js +94 -94
- package/src/context.js +230 -230
- package/src/http-fetch.js +53 -53
- package/src/ignore.js +118 -118
- package/src/logger.js +122 -122
- package/src/options.js +303 -303
- package/src/settings-overrides.js +152 -152
- package/src/toolchain/deps.js +164 -164
- package/src/toolchain/index.js +212 -212
- package/src/toolchain/presets.js +356 -340
- package/src/toolchain/template.cmake +77 -77
- package/src/upload-built.js +265 -265
- package/src/version-range.js +301 -301
- package/src/zip-safe.js +52 -52
- package/src/zip-stream.js +126 -0
package/src/commands/show.js
CHANGED
|
@@ -1,252 +1,252 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { getProvider } = require('../providers');
|
|
4
|
-
const { buildContext } = require('../context');
|
|
5
|
-
const log = require('../logger');
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* `wyvrnpm show <pkg>` — surface registry metadata for a package.
|
|
9
|
-
*
|
|
10
|
-
* Accepts:
|
|
11
|
-
* name → list every published version + profile.
|
|
12
|
-
* name@version → list every profile for that version,
|
|
13
|
-
* fetch full metadata for each, highlight
|
|
14
|
-
* consumer (`uploadedBy`) vs author builds.
|
|
15
|
-
* name@version@profileHash → dump full metadata for one build.
|
|
16
|
-
*
|
|
17
|
-
* Sources: CLI `--source` overrides config.installSources. First source
|
|
18
|
-
* that returns data wins (same first-match policy as `install`).
|
|
19
|
-
*
|
|
20
|
-
* Added for PLAN-UPLOAD-BUILT phase 3 so maintainers can spot-check which
|
|
21
|
-
* profileHashes were uploaded by consumers vs published by an author. The
|
|
22
|
-
* `uploadedBy` block is the signal; its absence means "author publish"
|
|
23
|
-
* by convention.
|
|
24
|
-
*
|
|
25
|
-
* @param {object} argv
|
|
26
|
-
* @param {string} argv.pkg e.g. "zlib", "zlib@1.3.0.0", "zlib@1.3.0.0@a1b2..."
|
|
27
|
-
* @param {string[]} [argv.source] source URLs
|
|
28
|
-
* @param {string} [argv.awsProfile]
|
|
29
|
-
* @param {string} [argv.token]
|
|
30
|
-
* @returns {Promise<void>}
|
|
31
|
-
*/
|
|
32
|
-
async function show(argv) {
|
|
33
|
-
const { name, version, profileHash } = parseSpec(argv.pkg);
|
|
34
|
-
if (!name) {
|
|
35
|
-
log.error('Usage: wyvrnpm show <name>[@<version>[@<profileHash>]]');
|
|
36
|
-
process.exit(1);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Shared per-invocation state (config, auth, JSON-mode toggle). `show`
|
|
40
|
-
// never reads the manifest, which is why ctx.manifest is lazy. See
|
|
41
|
-
// src/context.js + claude/PLAN-COMMAND-CONTEXT.md.
|
|
42
|
-
let ctx;
|
|
43
|
-
try {
|
|
44
|
-
ctx = buildContext(argv);
|
|
45
|
-
} catch (err) {
|
|
46
|
-
log.error(err.message);
|
|
47
|
-
process.exit(1);
|
|
48
|
-
}
|
|
49
|
-
const jsonOut = ctx.flags.format === 'json';
|
|
50
|
-
|
|
51
|
-
const { sources, awsProfile, token } = resolveSources(argv, ctx);
|
|
52
|
-
if (sources.length === 0) {
|
|
53
|
-
log.error(
|
|
54
|
-
'no sources configured. ' +
|
|
55
|
-
'Pass --source <url> or run: wyvrnpm configure add-source --kind install ...',
|
|
56
|
-
);
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
for (const source of sources) {
|
|
61
|
-
let provider;
|
|
62
|
-
try { provider = getProvider(source); } catch { continue; }
|
|
63
|
-
|
|
64
|
-
const idx = await provider.v2GetVersionsIndex({ source, name, awsProfile, token });
|
|
65
|
-
if (!idx?.versions) continue;
|
|
66
|
-
|
|
67
|
-
const versionKeys = version
|
|
68
|
-
? (idx.versions[version] ? [version] : [])
|
|
69
|
-
: Object.keys(idx.versions).sort();
|
|
70
|
-
|
|
71
|
-
if (version && versionKeys.length === 0) {
|
|
72
|
-
log.error(`Version ${version} not found on ${source}`);
|
|
73
|
-
process.exit(1);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Collect a single structured result as we walk. Text rendering happens
|
|
77
|
-
// inline in the legacy path; JSON mode emits the whole object at the
|
|
78
|
-
// end of the first source that answered.
|
|
79
|
-
const result = {
|
|
80
|
-
command: 'show',
|
|
81
|
-
wyvrnpmVersion: require('../../package.json').version,
|
|
82
|
-
source,
|
|
83
|
-
package: name,
|
|
84
|
-
latest: idx.latest ?? null,
|
|
85
|
-
versions: {},
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
if (!jsonOut) {
|
|
89
|
-
console.log(`${name} (source: ${source})`);
|
|
90
|
-
if (idx.latest) console.log(` latest: ${idx.latest}`);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
for (const v of versionKeys) {
|
|
94
|
-
const ventry = idx.versions[v];
|
|
95
|
-
const profiles = ventry?.profiles ?? {};
|
|
96
|
-
const profileKeys = profileHash
|
|
97
|
-
? (profiles[profileHash] ? [profileHash] : [])
|
|
98
|
-
: Object.keys(profiles).sort();
|
|
99
|
-
|
|
100
|
-
if (profileHash && profileKeys.length === 0) {
|
|
101
|
-
log.error(`ProfileHash ${profileHash} not found for ${name}@${v}`);
|
|
102
|
-
process.exit(1);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (!jsonOut) {
|
|
106
|
-
console.log(`\n ${name}@${v} (${profileKeys.length} profile${profileKeys.length === 1 ? '' : 's'})`);
|
|
107
|
-
if (ventry.source?.gitSha) {
|
|
108
|
-
console.log(` git: ${ventry.source.gitRepo ?? '?'} @ ${ventry.source.gitSha}`);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// For bare `name` queries we'd fetch O(M×N) manifests (versions ×
|
|
113
|
-
// profiles) — too noisy. Only deep-fetch when the user has narrowed
|
|
114
|
-
// to a specific version.
|
|
115
|
-
const deepFetch = Boolean(version);
|
|
116
|
-
|
|
117
|
-
const profileArr = [];
|
|
118
|
-
for (const hash of profileKeys) {
|
|
119
|
-
const entry = profiles[hash];
|
|
120
|
-
if (!jsonOut) {
|
|
121
|
-
console.log(`\n [${hash}]`);
|
|
122
|
-
if (entry.buildSettings) {
|
|
123
|
-
console.log(` profile : ${formatBuildSettings(entry.buildSettings)}`);
|
|
124
|
-
if (entry.buildSettings.options && Object.keys(entry.buildSettings.options).length > 0) {
|
|
125
|
-
console.log(` options : ${formatOptions(entry.buildSettings.options)}`);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
console.log(` sha256 : ${entry.contentSha256 ?? '?'}`);
|
|
129
|
-
if (entry.publishedAt) console.log(` published: ${entry.publishedAt}`);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
let meta = null;
|
|
133
|
-
if (deepFetch) {
|
|
134
|
-
meta = await provider.v2GetMeta({
|
|
135
|
-
source, name, version: v, profileHash: hash, awsProfile, token,
|
|
136
|
-
});
|
|
137
|
-
if (!jsonOut) {
|
|
138
|
-
if (meta?.uploadedBy) {
|
|
139
|
-
console.log(` origin : consumer upload (${meta.uploadedBy.kind})`);
|
|
140
|
-
console.log(` uploadedAt : ${meta.uploadedBy.uploadedAt}`);
|
|
141
|
-
console.log(` wyvrnpmVersion : ${meta.uploadedBy.wyvrnpmVersion ?? '?'}`);
|
|
142
|
-
if (meta.uploadedBy.builtFromGit) {
|
|
143
|
-
console.log(` builtFromGit : ${meta.uploadedBy.builtFromGit}`);
|
|
144
|
-
}
|
|
145
|
-
if (meta.uploadedBy.builtFromSha) {
|
|
146
|
-
console.log(` builtFromSha : ${meta.uploadedBy.builtFromSha}`);
|
|
147
|
-
}
|
|
148
|
-
} else if (meta) {
|
|
149
|
-
console.log(` origin : author publish`);
|
|
150
|
-
}
|
|
151
|
-
if (meta?.compatibility) {
|
|
152
|
-
console.log(` compat : ${JSON.stringify(meta.compatibility)}`);
|
|
153
|
-
}
|
|
154
|
-
if (meta?.options && Object.keys(meta.options).length > 0) {
|
|
155
|
-
console.log(` declared: ${formatDeclaredOptions(meta.options)}`);
|
|
156
|
-
}
|
|
157
|
-
// PLAN-CONF.md §4.6 — surface publisher's publishedConf.
|
|
158
|
-
// Informational only; absent for pre-2.6.0 author publishes.
|
|
159
|
-
if (meta?.publishedConf && Object.keys(meta.publishedConf).length > 0) {
|
|
160
|
-
console.log(` conf : ${JSON.stringify(meta.publishedConf)}`);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
profileArr.push({
|
|
166
|
-
profileHash: hash,
|
|
167
|
-
contentSha256: entry.contentSha256 ?? null,
|
|
168
|
-
publishedAt: entry.publishedAt ?? null,
|
|
169
|
-
buildSettings: entry.buildSettings ?? null,
|
|
170
|
-
origin: meta?.uploadedBy ? 'consumer-source-build' : (meta ? 'author-publish' : null),
|
|
171
|
-
uploadedBy: meta?.uploadedBy ?? null,
|
|
172
|
-
compatibility: meta?.compatibility ?? null,
|
|
173
|
-
declaredOptions: meta?.options ?? null,
|
|
174
|
-
publishedConf: meta?.publishedConf ?? null,
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
result.versions[v] = {
|
|
179
|
-
source: ventry.source ?? null,
|
|
180
|
-
profiles: profileArr,
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (jsonOut) {
|
|
185
|
-
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
186
|
-
}
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
log.error(`Package ${name} not found in any configured source`);
|
|
191
|
-
process.exit(1);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/**
|
|
195
|
-
* Parse a package spec "name[@version[@profileHash]]".
|
|
196
|
-
* @param {string} spec
|
|
197
|
-
* @returns {{ name?: string, version?: string, profileHash?: string }}
|
|
198
|
-
*/
|
|
199
|
-
function parseSpec(spec) {
|
|
200
|
-
if (!spec || typeof spec !== 'string') return {};
|
|
201
|
-
const parts = spec.split('@');
|
|
202
|
-
const [name, version, profileHash] = parts;
|
|
203
|
-
return {
|
|
204
|
-
name: name || undefined,
|
|
205
|
-
version: version || undefined,
|
|
206
|
-
profileHash: profileHash || undefined,
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
function resolveSources(argv, ctx) {
|
|
211
|
-
const { config } = ctx;
|
|
212
|
-
const sources = (argv.source && argv.source.length > 0)
|
|
213
|
-
? argv.source
|
|
214
|
-
: config.installSources.map((s) => s.url);
|
|
215
|
-
|
|
216
|
-
const firstConfig = config.installSources?.[0];
|
|
217
|
-
return {
|
|
218
|
-
sources,
|
|
219
|
-
awsProfile: argv.awsProfile ?? firstConfig?.profile,
|
|
220
|
-
token: ctx.auth.for(firstConfig).token,
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
function formatBuildSettings(bs) {
|
|
225
|
-
const parts = [
|
|
226
|
-
`${bs.os}/${bs.arch}`,
|
|
227
|
-
`${bs.compiler} ${bs['compiler.version']}`,
|
|
228
|
-
`C++${bs['compiler.cppstd']}`,
|
|
229
|
-
];
|
|
230
|
-
if (bs['compiler.runtime']) parts.push(`[${bs['compiler.runtime']}]`);
|
|
231
|
-
return parts.join(' ');
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
function formatOptions(options) {
|
|
235
|
-
return Object.entries(options)
|
|
236
|
-
.sort(([a], [b]) => a.localeCompare(b))
|
|
237
|
-
.map(([k, v]) => `${k}=${typeof v === 'string' ? v : String(v)}`)
|
|
238
|
-
.join(', ');
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
function formatDeclaredOptions(declared) {
|
|
242
|
-
return Object.entries(declared)
|
|
243
|
-
.sort(([a], [b]) => a.localeCompare(b))
|
|
244
|
-
.map(([name, spec]) => {
|
|
245
|
-
const allowed = Array.isArray(spec?.allowed) ? spec.allowed : [];
|
|
246
|
-
return `${name} (default=${String(spec?.default)}, allowed=${allowed.map(String).join('|')})`;
|
|
247
|
-
})
|
|
248
|
-
.join('; ');
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
module.exports = show;
|
|
252
|
-
module.exports.parseSpec = parseSpec;
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { getProvider } = require('../providers');
|
|
4
|
+
const { buildContext } = require('../context');
|
|
5
|
+
const log = require('../logger');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* `wyvrnpm show <pkg>` — surface registry metadata for a package.
|
|
9
|
+
*
|
|
10
|
+
* Accepts:
|
|
11
|
+
* name → list every published version + profile.
|
|
12
|
+
* name@version → list every profile for that version,
|
|
13
|
+
* fetch full metadata for each, highlight
|
|
14
|
+
* consumer (`uploadedBy`) vs author builds.
|
|
15
|
+
* name@version@profileHash → dump full metadata for one build.
|
|
16
|
+
*
|
|
17
|
+
* Sources: CLI `--source` overrides config.installSources. First source
|
|
18
|
+
* that returns data wins (same first-match policy as `install`).
|
|
19
|
+
*
|
|
20
|
+
* Added for PLAN-UPLOAD-BUILT phase 3 so maintainers can spot-check which
|
|
21
|
+
* profileHashes were uploaded by consumers vs published by an author. The
|
|
22
|
+
* `uploadedBy` block is the signal; its absence means "author publish"
|
|
23
|
+
* by convention.
|
|
24
|
+
*
|
|
25
|
+
* @param {object} argv
|
|
26
|
+
* @param {string} argv.pkg e.g. "zlib", "zlib@1.3.0.0", "zlib@1.3.0.0@a1b2..."
|
|
27
|
+
* @param {string[]} [argv.source] source URLs
|
|
28
|
+
* @param {string} [argv.awsProfile]
|
|
29
|
+
* @param {string} [argv.token]
|
|
30
|
+
* @returns {Promise<void>}
|
|
31
|
+
*/
|
|
32
|
+
async function show(argv) {
|
|
33
|
+
const { name, version, profileHash } = parseSpec(argv.pkg);
|
|
34
|
+
if (!name) {
|
|
35
|
+
log.error('Usage: wyvrnpm show <name>[@<version>[@<profileHash>]]');
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Shared per-invocation state (config, auth, JSON-mode toggle). `show`
|
|
40
|
+
// never reads the manifest, which is why ctx.manifest is lazy. See
|
|
41
|
+
// src/context.js + claude/PLAN-COMMAND-CONTEXT.md.
|
|
42
|
+
let ctx;
|
|
43
|
+
try {
|
|
44
|
+
ctx = buildContext(argv);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
log.error(err.message);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
const jsonOut = ctx.flags.format === 'json';
|
|
50
|
+
|
|
51
|
+
const { sources, awsProfile, token } = resolveSources(argv, ctx);
|
|
52
|
+
if (sources.length === 0) {
|
|
53
|
+
log.error(
|
|
54
|
+
'no sources configured. ' +
|
|
55
|
+
'Pass --source <url> or run: wyvrnpm configure add-source --kind install ...',
|
|
56
|
+
);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
for (const source of sources) {
|
|
61
|
+
let provider;
|
|
62
|
+
try { provider = getProvider(source); } catch { continue; }
|
|
63
|
+
|
|
64
|
+
const idx = await provider.v2GetVersionsIndex({ source, name, awsProfile, token });
|
|
65
|
+
if (!idx?.versions) continue;
|
|
66
|
+
|
|
67
|
+
const versionKeys = version
|
|
68
|
+
? (idx.versions[version] ? [version] : [])
|
|
69
|
+
: Object.keys(idx.versions).sort();
|
|
70
|
+
|
|
71
|
+
if (version && versionKeys.length === 0) {
|
|
72
|
+
log.error(`Version ${version} not found on ${source}`);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Collect a single structured result as we walk. Text rendering happens
|
|
77
|
+
// inline in the legacy path; JSON mode emits the whole object at the
|
|
78
|
+
// end of the first source that answered.
|
|
79
|
+
const result = {
|
|
80
|
+
command: 'show',
|
|
81
|
+
wyvrnpmVersion: require('../../package.json').version,
|
|
82
|
+
source,
|
|
83
|
+
package: name,
|
|
84
|
+
latest: idx.latest ?? null,
|
|
85
|
+
versions: {},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
if (!jsonOut) {
|
|
89
|
+
console.log(`${name} (source: ${source})`);
|
|
90
|
+
if (idx.latest) console.log(` latest: ${idx.latest}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
for (const v of versionKeys) {
|
|
94
|
+
const ventry = idx.versions[v];
|
|
95
|
+
const profiles = ventry?.profiles ?? {};
|
|
96
|
+
const profileKeys = profileHash
|
|
97
|
+
? (profiles[profileHash] ? [profileHash] : [])
|
|
98
|
+
: Object.keys(profiles).sort();
|
|
99
|
+
|
|
100
|
+
if (profileHash && profileKeys.length === 0) {
|
|
101
|
+
log.error(`ProfileHash ${profileHash} not found for ${name}@${v}`);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!jsonOut) {
|
|
106
|
+
console.log(`\n ${name}@${v} (${profileKeys.length} profile${profileKeys.length === 1 ? '' : 's'})`);
|
|
107
|
+
if (ventry.source?.gitSha) {
|
|
108
|
+
console.log(` git: ${ventry.source.gitRepo ?? '?'} @ ${ventry.source.gitSha}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// For bare `name` queries we'd fetch O(M×N) manifests (versions ×
|
|
113
|
+
// profiles) — too noisy. Only deep-fetch when the user has narrowed
|
|
114
|
+
// to a specific version.
|
|
115
|
+
const deepFetch = Boolean(version);
|
|
116
|
+
|
|
117
|
+
const profileArr = [];
|
|
118
|
+
for (const hash of profileKeys) {
|
|
119
|
+
const entry = profiles[hash];
|
|
120
|
+
if (!jsonOut) {
|
|
121
|
+
console.log(`\n [${hash}]`);
|
|
122
|
+
if (entry.buildSettings) {
|
|
123
|
+
console.log(` profile : ${formatBuildSettings(entry.buildSettings)}`);
|
|
124
|
+
if (entry.buildSettings.options && Object.keys(entry.buildSettings.options).length > 0) {
|
|
125
|
+
console.log(` options : ${formatOptions(entry.buildSettings.options)}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
console.log(` sha256 : ${entry.contentSha256 ?? '?'}`);
|
|
129
|
+
if (entry.publishedAt) console.log(` published: ${entry.publishedAt}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
let meta = null;
|
|
133
|
+
if (deepFetch) {
|
|
134
|
+
meta = await provider.v2GetMeta({
|
|
135
|
+
source, name, version: v, profileHash: hash, awsProfile, token,
|
|
136
|
+
});
|
|
137
|
+
if (!jsonOut) {
|
|
138
|
+
if (meta?.uploadedBy) {
|
|
139
|
+
console.log(` origin : consumer upload (${meta.uploadedBy.kind})`);
|
|
140
|
+
console.log(` uploadedAt : ${meta.uploadedBy.uploadedAt}`);
|
|
141
|
+
console.log(` wyvrnpmVersion : ${meta.uploadedBy.wyvrnpmVersion ?? '?'}`);
|
|
142
|
+
if (meta.uploadedBy.builtFromGit) {
|
|
143
|
+
console.log(` builtFromGit : ${meta.uploadedBy.builtFromGit}`);
|
|
144
|
+
}
|
|
145
|
+
if (meta.uploadedBy.builtFromSha) {
|
|
146
|
+
console.log(` builtFromSha : ${meta.uploadedBy.builtFromSha}`);
|
|
147
|
+
}
|
|
148
|
+
} else if (meta) {
|
|
149
|
+
console.log(` origin : author publish`);
|
|
150
|
+
}
|
|
151
|
+
if (meta?.compatibility) {
|
|
152
|
+
console.log(` compat : ${JSON.stringify(meta.compatibility)}`);
|
|
153
|
+
}
|
|
154
|
+
if (meta?.options && Object.keys(meta.options).length > 0) {
|
|
155
|
+
console.log(` declared: ${formatDeclaredOptions(meta.options)}`);
|
|
156
|
+
}
|
|
157
|
+
// PLAN-CONF.md §4.6 — surface publisher's publishedConf.
|
|
158
|
+
// Informational only; absent for pre-2.6.0 author publishes.
|
|
159
|
+
if (meta?.publishedConf && Object.keys(meta.publishedConf).length > 0) {
|
|
160
|
+
console.log(` conf : ${JSON.stringify(meta.publishedConf)}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
profileArr.push({
|
|
166
|
+
profileHash: hash,
|
|
167
|
+
contentSha256: entry.contentSha256 ?? null,
|
|
168
|
+
publishedAt: entry.publishedAt ?? null,
|
|
169
|
+
buildSettings: entry.buildSettings ?? null,
|
|
170
|
+
origin: meta?.uploadedBy ? 'consumer-source-build' : (meta ? 'author-publish' : null),
|
|
171
|
+
uploadedBy: meta?.uploadedBy ?? null,
|
|
172
|
+
compatibility: meta?.compatibility ?? null,
|
|
173
|
+
declaredOptions: meta?.options ?? null,
|
|
174
|
+
publishedConf: meta?.publishedConf ?? null,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
result.versions[v] = {
|
|
179
|
+
source: ventry.source ?? null,
|
|
180
|
+
profiles: profileArr,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (jsonOut) {
|
|
185
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
186
|
+
}
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
log.error(`Package ${name} not found in any configured source`);
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Parse a package spec "name[@version[@profileHash]]".
|
|
196
|
+
* @param {string} spec
|
|
197
|
+
* @returns {{ name?: string, version?: string, profileHash?: string }}
|
|
198
|
+
*/
|
|
199
|
+
function parseSpec(spec) {
|
|
200
|
+
if (!spec || typeof spec !== 'string') return {};
|
|
201
|
+
const parts = spec.split('@');
|
|
202
|
+
const [name, version, profileHash] = parts;
|
|
203
|
+
return {
|
|
204
|
+
name: name || undefined,
|
|
205
|
+
version: version || undefined,
|
|
206
|
+
profileHash: profileHash || undefined,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function resolveSources(argv, ctx) {
|
|
211
|
+
const { config } = ctx;
|
|
212
|
+
const sources = (argv.source && argv.source.length > 0)
|
|
213
|
+
? argv.source
|
|
214
|
+
: config.installSources.map((s) => s.url);
|
|
215
|
+
|
|
216
|
+
const firstConfig = config.installSources?.[0];
|
|
217
|
+
return {
|
|
218
|
+
sources,
|
|
219
|
+
awsProfile: argv.awsProfile ?? firstConfig?.profile,
|
|
220
|
+
token: ctx.auth.for(firstConfig).token,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function formatBuildSettings(bs) {
|
|
225
|
+
const parts = [
|
|
226
|
+
`${bs.os}/${bs.arch}`,
|
|
227
|
+
`${bs.compiler} ${bs['compiler.version']}`,
|
|
228
|
+
`C++${bs['compiler.cppstd']}`,
|
|
229
|
+
];
|
|
230
|
+
if (bs['compiler.runtime']) parts.push(`[${bs['compiler.runtime']}]`);
|
|
231
|
+
return parts.join(' ');
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function formatOptions(options) {
|
|
235
|
+
return Object.entries(options)
|
|
236
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
237
|
+
.map(([k, v]) => `${k}=${typeof v === 'string' ? v : String(v)}`)
|
|
238
|
+
.join(', ');
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function formatDeclaredOptions(declared) {
|
|
242
|
+
return Object.entries(declared)
|
|
243
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
244
|
+
.map(([name, spec]) => {
|
|
245
|
+
const allowed = Array.isArray(spec?.allowed) ? spec.allowed : [];
|
|
246
|
+
return `${name} (default=${String(spec?.default)}, allowed=${allowed.map(String).join('|')})`;
|
|
247
|
+
})
|
|
248
|
+
.join('; ');
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
module.exports = show;
|
|
252
|
+
module.exports.parseSpec = parseSpec;
|