@octonodes/cli 0.2.4 → 0.2.5
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/package.json +2 -2
- package/runtime/plugin-lifecycle.cjs +188 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@octonodes/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Octonode API and plugin development CLI.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"prepack": "tsc -b"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@octonodes/sdk": "0.2.
|
|
24
|
+
"@octonodes/sdk": "0.2.5",
|
|
25
25
|
"@supabase/supabase-js": "2.107.0",
|
|
26
26
|
"esbuild": "0.28.1",
|
|
27
27
|
"tar": "7.5.22",
|
|
@@ -12716,6 +12716,7 @@ var PLUGIN_BUNDLE_EXCLUDES = [
|
|
|
12716
12716
|
"*.pem",
|
|
12717
12717
|
"*.key"
|
|
12718
12718
|
];
|
|
12719
|
+
var MAX_CATALOG_MANIFESTS = 512;
|
|
12719
12720
|
|
|
12720
12721
|
// packages/plugin/src/integrity.ts
|
|
12721
12722
|
function collectFiles(dir, base, files) {
|
|
@@ -12875,6 +12876,79 @@ function loadPlugin(dir, source = "user") {
|
|
|
12875
12876
|
function isPluginDir(dir) {
|
|
12876
12877
|
return import_schema2.PLUGIN_DEFINITION_FILENAMES.some((name) => (0, import_node_fs4.existsSync)((0, import_node_path4.join)(dir, name)));
|
|
12877
12878
|
}
|
|
12879
|
+
function pluginDirsIn(root) {
|
|
12880
|
+
if (!(0, import_node_fs4.existsSync)(root)) return [];
|
|
12881
|
+
const out = [];
|
|
12882
|
+
for (const name of (0, import_node_fs4.readdirSync)(root)) {
|
|
12883
|
+
if (name.startsWith(".")) continue;
|
|
12884
|
+
const dir = (0, import_node_path4.join)(root, name);
|
|
12885
|
+
try {
|
|
12886
|
+
if ((0, import_node_fs4.statSync)(dir).isDirectory() && isPluginDir(dir)) out.push(dir);
|
|
12887
|
+
} catch {
|
|
12888
|
+
}
|
|
12889
|
+
}
|
|
12890
|
+
return out;
|
|
12891
|
+
}
|
|
12892
|
+
function discoverPluginCatalog(opts = {}) {
|
|
12893
|
+
return discover(opts, true);
|
|
12894
|
+
}
|
|
12895
|
+
var catalogManifests = /* @__PURE__ */ new Map();
|
|
12896
|
+
function catalogManifest(dir) {
|
|
12897
|
+
const path = (0, import_plugin_runtime2.pluginDefinitionPath)(dir);
|
|
12898
|
+
const stat = (0, import_node_fs4.statSync)(path);
|
|
12899
|
+
const revision = `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeMs}:${stat.ctimeMs}`;
|
|
12900
|
+
const cached = catalogManifests.get(path);
|
|
12901
|
+
if (cached?.revision === revision) return cached.manifest;
|
|
12902
|
+
const manifest2 = loadPluginManifest(dir);
|
|
12903
|
+
if (catalogManifests.size >= MAX_CATALOG_MANIFESTS) catalogManifests.delete(catalogManifests.keys().next().value);
|
|
12904
|
+
catalogManifests.set(path, { revision, manifest: manifest2 });
|
|
12905
|
+
return manifest2;
|
|
12906
|
+
}
|
|
12907
|
+
function discover(opts, metadataOnly) {
|
|
12908
|
+
const plugins = [];
|
|
12909
|
+
const errors = [];
|
|
12910
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12911
|
+
const scanRoot = (root, source) => {
|
|
12912
|
+
for (const dir of pluginDirsIn(root)) {
|
|
12913
|
+
try {
|
|
12914
|
+
const manifest2 = metadataOnly ? catalogManifest(dir) : loadPluginManifest(dir);
|
|
12915
|
+
if (seen.has(manifest2.id)) continue;
|
|
12916
|
+
seen.add(manifest2.id);
|
|
12917
|
+
plugins.push({ manifest: manifest2, dir, source });
|
|
12918
|
+
} catch (err) {
|
|
12919
|
+
errors.push({ dir, message: err.message });
|
|
12920
|
+
}
|
|
12921
|
+
}
|
|
12922
|
+
};
|
|
12923
|
+
scanRoot(projectPluginRoot(opts.cwd), "project");
|
|
12924
|
+
try {
|
|
12925
|
+
const lock = readLockfile(opts.cwd);
|
|
12926
|
+
for (const [id, entry] of Object.entries(lock.plugins)) {
|
|
12927
|
+
if (seen.has(id)) continue;
|
|
12928
|
+
const dir = storeEntryDir(entry.pluginId ?? id, entry.version, entry.sha256, opts.storeRoot);
|
|
12929
|
+
if (!isPluginDir(dir)) {
|
|
12930
|
+
errors.push({
|
|
12931
|
+
dir,
|
|
12932
|
+
message: `plugin "${id}"@${entry.version} is locked but missing from the store \u2014 run \`octonode install\``
|
|
12933
|
+
});
|
|
12934
|
+
continue;
|
|
12935
|
+
}
|
|
12936
|
+
try {
|
|
12937
|
+
const manifest2 = metadataOnly ? catalogManifest(dir) : loadPluginManifest(dir);
|
|
12938
|
+
if (manifest2.id !== (entry.pluginId ?? id) || manifest2.version !== entry.version || !metadataOnly && hashPluginDir(dir) !== entry.sha256)
|
|
12939
|
+
throw new Error(`Locked plugin ${id} failed identity or integrity validation; run octonode install`);
|
|
12940
|
+
seen.add(id);
|
|
12941
|
+
plugins.push({ manifest: { ...manifest2, id }, dir, source: "store" });
|
|
12942
|
+
} catch (err) {
|
|
12943
|
+
errors.push({ dir, message: err.message });
|
|
12944
|
+
}
|
|
12945
|
+
}
|
|
12946
|
+
} catch (err) {
|
|
12947
|
+
errors.push({ dir: opts.cwd ?? process.cwd(), message: err.message });
|
|
12948
|
+
}
|
|
12949
|
+
scanRoot(opts.userRoot ?? userPluginRoot(), "user");
|
|
12950
|
+
return { plugins, errors };
|
|
12951
|
+
}
|
|
12878
12952
|
|
|
12879
12953
|
// packages/plugin/src/dependencies.ts
|
|
12880
12954
|
var import_node_child_process = require("node:child_process");
|
|
@@ -13254,7 +13328,7 @@ async function run(project, command, cwd, cacheRoot) {
|
|
|
13254
13328
|
maxBuffer: 4 * 1024 * 1024
|
|
13255
13329
|
});
|
|
13256
13330
|
}
|
|
13257
|
-
async function verifyProjectDependencies(project, names) {
|
|
13331
|
+
async function verifyProjectDependencies(project, names, versions = {}) {
|
|
13258
13332
|
if (!names.length) return;
|
|
13259
13333
|
const pnp = (0, import_node_path6.join)(project.root, ".pnp.cjs");
|
|
13260
13334
|
const loader = (0, import_node_path6.join)(project.root, ".pnp.loader.mjs");
|
|
@@ -13266,14 +13340,37 @@ async function verifyProjectDependencies(project, names) {
|
|
|
13266
13340
|
"--input-type=module",
|
|
13267
13341
|
"-e",
|
|
13268
13342
|
`import { createRequire } from 'node:module';
|
|
13269
|
-
import { existsSync } from 'node:fs';
|
|
13343
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
13344
|
+
import { dirname, join } from 'node:path';
|
|
13270
13345
|
import { fileURLToPath } from 'node:url';
|
|
13271
13346
|
const require = createRequire(${JSON.stringify((0, import_node_path6.join)(project.target, "package.json"))});
|
|
13347
|
+
const versions = ${JSON.stringify(versions)};
|
|
13272
13348
|
for (const name of ${JSON.stringify(names)}) {
|
|
13273
|
-
|
|
13349
|
+
let resolved;
|
|
13350
|
+
try { resolved = require.resolve(name); } catch {
|
|
13274
13351
|
const entry = import.meta.resolve(name);
|
|
13352
|
+
resolved = entry.startsWith('file:') ? fileURLToPath(entry) : undefined;
|
|
13275
13353
|
if (entry.startsWith('file:') && !existsSync(fileURLToPath(entry))) throw new Error('missing package entry: ' + name);
|
|
13276
13354
|
}
|
|
13355
|
+
const identity = name.startsWith('@') ? name.split('/').slice(0, 2).join('/') : name.split('/')[0];
|
|
13356
|
+
if (Object.hasOwn(versions, identity)) {
|
|
13357
|
+
let directory = resolved ? dirname(resolved) : '';
|
|
13358
|
+
let matched = false;
|
|
13359
|
+
while (directory) {
|
|
13360
|
+
const file = join(directory, 'package.json');
|
|
13361
|
+
if (existsSync(file)) {
|
|
13362
|
+
const pkg = JSON.parse(readFileSync(file, 'utf8'));
|
|
13363
|
+
if (pkg.name === identity) {
|
|
13364
|
+
if (pkg.version !== versions[identity]) throw new Error('installed dependency version mismatch: ' + name);
|
|
13365
|
+
matched = true; break;
|
|
13366
|
+
}
|
|
13367
|
+
}
|
|
13368
|
+
const parent = dirname(directory);
|
|
13369
|
+
if (parent === directory) break;
|
|
13370
|
+
directory = parent;
|
|
13371
|
+
}
|
|
13372
|
+
if (!matched) throw new Error('cannot verify installed package: ' + name);
|
|
13373
|
+
}
|
|
13277
13374
|
}`
|
|
13278
13375
|
],
|
|
13279
13376
|
{ cwd: project.target, env: (0, import_common.childProcessEnvironment)(), timeout: 3e4, maxBuffer: 1024 * 1024 }
|
|
@@ -13323,7 +13420,40 @@ async function reconcileDependencies(cwd, dependencies, options = {}) {
|
|
|
13323
13420
|
throw new Error("invalid npm dependency subpath");
|
|
13324
13421
|
}
|
|
13325
13422
|
}
|
|
13423
|
+
const unique = /* @__PURE__ */ new Map();
|
|
13424
|
+
for (const dependency of dependencies) {
|
|
13425
|
+
const spec = dependency.spec.startsWith(`${dependency.name}@`) ? dependency.spec.slice(dependency.name.length + 1) : dependency.spec;
|
|
13426
|
+
const previous = unique.get(dependency.name);
|
|
13427
|
+
if (previous && previous.spec !== spec) throw new Error(`Conflicting dependency requests for ${dependency.name}`);
|
|
13428
|
+
unique.set(dependency.name, {
|
|
13429
|
+
...dependency,
|
|
13430
|
+
spec,
|
|
13431
|
+
...previous?.subpaths || dependency.subpaths ? { subpaths: [.../* @__PURE__ */ new Set([...previous?.subpaths ?? [], ...dependency.subpaths ?? []])] } : {}
|
|
13432
|
+
});
|
|
13433
|
+
}
|
|
13434
|
+
dependencies = [...unique.values()];
|
|
13326
13435
|
const project = resolveDependencyProject(cwd);
|
|
13436
|
+
const declared = manifest(project.target);
|
|
13437
|
+
const existing = { ...declared.devDependencies, ...declared.optionalDependencies, ...declared.dependencies };
|
|
13438
|
+
if (options.preserveExisting) {
|
|
13439
|
+
for (const { name, spec } of dependencies)
|
|
13440
|
+
if (Object.hasOwn(existing, name) && existing[name] !== spec && !(existing[name].startsWith("file:") && spec.startsWith("file:") && (0, import_node_path6.resolve)(project.target, existing[name].slice(5)) === (0, import_node_path6.resolve)(project.target, spec.slice(5))))
|
|
13441
|
+
throw new Error(
|
|
13442
|
+
`Dependency conflict: ${name} is ${existing[name]}, plugin requires ${spec}; reconcile it explicitly first`
|
|
13443
|
+
);
|
|
13444
|
+
}
|
|
13445
|
+
const reusable = dependencies.length > 0 && !options.remove?.length && dependencies.every(
|
|
13446
|
+
({ name, spec }) => existing[name] === spec && /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(spec)
|
|
13447
|
+
);
|
|
13448
|
+
const reuse = reusable && await verifyProjectDependencies(
|
|
13449
|
+
project,
|
|
13450
|
+
dependencies.flatMap(({ name, subpaths }) => subpaths ? subpaths.map((path) => name + path.slice(1)) : [name]),
|
|
13451
|
+
Object.fromEntries(dependencies.map(({ name, spec }) => [name, spec]))
|
|
13452
|
+
).then(
|
|
13453
|
+
() => true,
|
|
13454
|
+
() => false
|
|
13455
|
+
);
|
|
13456
|
+
const metadataOnly = options.metadataOnly || reuse;
|
|
13327
13457
|
const packageJson = (0, import_node_path6.join)(project.target, "package.json");
|
|
13328
13458
|
if (!dependencies.length && !(0, import_node_fs6.existsSync)(packageJson) && !options.commit) return;
|
|
13329
13459
|
const hasLock = PACKAGE_MANAGER_LOCKS[project.manager].some((file) => (0, import_node_fs6.existsSync)((0, import_node_path6.join)(project.root, file)));
|
|
@@ -13359,13 +13489,12 @@ async function reconcileDependencies(cwd, dependencies, options = {}) {
|
|
|
13359
13489
|
else (0, import_node_fs6.writeFileSync)(path, content);
|
|
13360
13490
|
}
|
|
13361
13491
|
};
|
|
13362
|
-
if (hadInstall && !hasLock && !
|
|
13492
|
+
if (hadInstall && !hasLock && !metadataOnly)
|
|
13363
13493
|
throw new Error(
|
|
13364
13494
|
"create a native lockfile before updating existing dependencies so failed installations can be recovered"
|
|
13365
13495
|
);
|
|
13366
13496
|
try {
|
|
13367
|
-
if (
|
|
13368
|
-
(0, import_node_fs6.writeFileSync)((0, import_node_path6.join)((0, import_node_path6.dirname)(journal), "metadata-only"), "1");
|
|
13497
|
+
if (metadataOnly && (0, import_node_fs6.existsSync)((0, import_node_path6.dirname)(journal))) (0, import_node_fs6.writeFileSync)((0, import_node_path6.join)((0, import_node_path6.dirname)(journal), "metadata-only"), "1");
|
|
13369
13498
|
if ((0, import_node_fs6.existsSync)((0, import_node_path6.dirname)(journal)))
|
|
13370
13499
|
(0, import_node_fs6.writeFileSync)(
|
|
13371
13500
|
journal,
|
|
@@ -13376,7 +13505,7 @@ async function reconcileDependencies(cwd, dependencies, options = {}) {
|
|
|
13376
13505
|
}))
|
|
13377
13506
|
)
|
|
13378
13507
|
);
|
|
13379
|
-
if (
|
|
13508
|
+
if (metadataOnly) {
|
|
13380
13509
|
metadataTouched = true;
|
|
13381
13510
|
options.commit?.();
|
|
13382
13511
|
(0, import_node_fs6.rmSync)(journal, { force: true });
|
|
@@ -13468,14 +13597,14 @@ async function reconcileDependencies(cwd, dependencies, options = {}) {
|
|
|
13468
13597
|
}
|
|
13469
13598
|
restoreBefore();
|
|
13470
13599
|
let recovery = "";
|
|
13471
|
-
if (!
|
|
13600
|
+
if (!metadataOnly && hadInstall && hasLock) {
|
|
13472
13601
|
try {
|
|
13473
13602
|
await run(project, installCommand(project, true), project.root, options.cacheRoot);
|
|
13474
13603
|
} catch {
|
|
13475
13604
|
recovery = "; manifests restored, but dependency recovery failed \u2014 run a frozen install before executing workflows";
|
|
13476
13605
|
}
|
|
13477
13606
|
restoreBefore();
|
|
13478
|
-
} else if (!
|
|
13607
|
+
} else if (!metadataOnly && !hadInstall) {
|
|
13479
13608
|
(0, import_node_fs6.rmSync)((0, import_node_path6.join)(project.root, "node_modules"), { recursive: true, force: true });
|
|
13480
13609
|
}
|
|
13481
13610
|
for (const [path, content] of pnpBefore) {
|
|
@@ -13780,6 +13909,19 @@ async function generatePluginPackage(cwd, selections, expectedPacker) {
|
|
|
13780
13909
|
function pluginNpmDependencies(manifest2) {
|
|
13781
13910
|
return manifest2.integration?.npmDependencies ?? (manifest2.integration?.npm ? [manifest2.integration.npm] : []);
|
|
13782
13911
|
}
|
|
13912
|
+
function assertUniqueNpmPlugins(plugins) {
|
|
13913
|
+
const owners = /* @__PURE__ */ new Map();
|
|
13914
|
+
for (const { alias, manifest: manifest2 } of plugins) {
|
|
13915
|
+
const pkg = manifest2.integration?.npm?.package.trim().toLowerCase();
|
|
13916
|
+
if (!pkg) continue;
|
|
13917
|
+
const previous = owners.get(pkg);
|
|
13918
|
+
if (previous && previous !== alias)
|
|
13919
|
+
throw new Error(
|
|
13920
|
+
`Use existing npm integration "${previous}" for ${pkg}; duplicate plugin alias "${alias}" is not allowed`
|
|
13921
|
+
);
|
|
13922
|
+
owners.set(pkg, alias);
|
|
13923
|
+
}
|
|
13924
|
+
}
|
|
13783
13925
|
|
|
13784
13926
|
// packages/plugin/src/prepared/invocation.ts
|
|
13785
13927
|
var import_common3 = __toESM(require_dist2());
|
|
@@ -13828,6 +13970,10 @@ async function reconcilePluginLock(cwd, next, options = {}) {
|
|
|
13828
13970
|
throw new Error(`Plugin identity or integrity mismatch: ${alias}`);
|
|
13829
13971
|
return { alias, directory, sha256: pin.sha256, manifest: manifest2, remote: preparedPluginPin(directory, pin) };
|
|
13830
13972
|
});
|
|
13973
|
+
assertUniqueNpmPlugins([
|
|
13974
|
+
...discoverPluginCatalog({ cwd, storeRoot: options.storeRoot }).plugins.filter((item) => item.source === "project" && !loaded.some((pin) => pin.alias === item.manifest.id)).map((item) => ({ alias: item.manifest.id, manifest: item.manifest })),
|
|
13975
|
+
...loaded
|
|
13976
|
+
]);
|
|
13831
13977
|
const libraries = loaded.filter((item) => item.manifest.library);
|
|
13832
13978
|
const generated = libraries.length ? await generatePluginPackage(project.target, libraries) : void 0;
|
|
13833
13979
|
const packageFile = (0, import_node_path10.join)(project.target, "package.json");
|
|
@@ -13924,6 +14070,9 @@ function installRoot(opts) {
|
|
|
13924
14070
|
return opts.project ? { root: projectPluginRoot(opts.cwd), source: "project" } : { root: userPluginRoot(), source: "user" };
|
|
13925
14071
|
}
|
|
13926
14072
|
async function installNodeDeps(dir, opts = {}) {
|
|
14073
|
+
return installNodeDepsUnlocked(dir, opts, false);
|
|
14074
|
+
}
|
|
14075
|
+
async function installNodeDepsUnlocked(dir, opts, locked) {
|
|
13927
14076
|
if (opts.noDeps) return {};
|
|
13928
14077
|
const dependencies = pluginNpmDependencies(loadPluginManifest(dir));
|
|
13929
14078
|
if (dependencies.length) {
|
|
@@ -13936,11 +14085,12 @@ async function installNodeDeps(dir, opts = {}) {
|
|
|
13936
14085
|
});
|
|
13937
14086
|
return {};
|
|
13938
14087
|
}
|
|
13939
|
-
await installProjectDependencies(
|
|
14088
|
+
await (locked ? reconcileDependencies : installProjectDependencies)(
|
|
13940
14089
|
opts.cwd ?? process.cwd(),
|
|
13941
14090
|
dependencies.map((npm) => ({ name: npm.package, spec: npm.spec })),
|
|
13942
14091
|
{
|
|
13943
|
-
cacheRoot: opts.cacheRoot
|
|
14092
|
+
cacheRoot: opts.cacheRoot,
|
|
14093
|
+
preserveExisting: true
|
|
13944
14094
|
}
|
|
13945
14095
|
);
|
|
13946
14096
|
return { depsInstalled: true };
|
|
@@ -13976,6 +14126,10 @@ async function installNodeDeps(dir, opts = {}) {
|
|
|
13976
14126
|
}
|
|
13977
14127
|
}
|
|
13978
14128
|
async function installPlugin(src, opts = {}) {
|
|
14129
|
+
if (opts.project) return withDependencyInstall(opts.cwd ?? process.cwd(), () => installPluginUnlocked(src, opts));
|
|
14130
|
+
return installPluginUnlocked(src, opts);
|
|
14131
|
+
}
|
|
14132
|
+
async function installPluginUnlocked(src, opts) {
|
|
13979
14133
|
if (!(0, import_node_fs11.existsSync)(src) || !(0, import_node_fs11.statSync)(src).isDirectory()) {
|
|
13980
14134
|
throw new Error(`source "${src}" is not a directory`);
|
|
13981
14135
|
}
|
|
@@ -13984,13 +14138,20 @@ async function installPlugin(src, opts = {}) {
|
|
|
13984
14138
|
}
|
|
13985
14139
|
const { manifest: manifest2 } = loadPlugin(src);
|
|
13986
14140
|
const { root, source } = installRoot(opts);
|
|
14141
|
+
const installed = discoverPluginCatalog({ cwd: opts.cwd }).plugins.filter(
|
|
14142
|
+
(item) => (opts.project ? item.source !== "user" : item.source === "user") && item.manifest.id !== manifest2.id
|
|
14143
|
+
);
|
|
14144
|
+
assertUniqueNpmPlugins([
|
|
14145
|
+
...installed.map((item) => ({ alias: item.manifest.id, manifest: item.manifest })),
|
|
14146
|
+
{ alias: manifest2.id, manifest: manifest2 }
|
|
14147
|
+
]);
|
|
13987
14148
|
const dest = (0, import_node_path11.join)(root, manifest2.id);
|
|
13988
14149
|
if ((0, import_node_fs11.existsSync)(dest)) {
|
|
13989
14150
|
if (!opts.force) {
|
|
13990
14151
|
throw new Error(`plugin "${manifest2.id}" is already installed at ${dest} (use --force to overwrite)`);
|
|
13991
14152
|
}
|
|
13992
14153
|
}
|
|
13993
|
-
const deps = pluginNpmDependencies(manifest2).length ? await
|
|
14154
|
+
const deps = pluginNpmDependencies(manifest2).length ? await installNodeDepsUnlocked(src, { ...opts, cacheOnly: opts.cacheOnly ?? !opts.project }, !!opts.project) : {};
|
|
13994
14155
|
if (deps.depsError) return { manifest: manifest2, dir: dest, source, ...deps };
|
|
13995
14156
|
if ((0, import_node_fs11.existsSync)(dest)) (0, import_node_fs11.rmSync)(dest, { recursive: true, force: true });
|
|
13996
14157
|
(0, import_node_fs11.mkdirSync)(root, { recursive: true });
|
|
@@ -14000,7 +14161,7 @@ async function installPlugin(src, opts = {}) {
|
|
|
14000
14161
|
dir: dest,
|
|
14001
14162
|
source,
|
|
14002
14163
|
...deps,
|
|
14003
|
-
...pluginNpmDependencies(manifest2).length ? {} : await
|
|
14164
|
+
...pluginNpmDependencies(manifest2).length ? {} : await installNodeDepsUnlocked(dest, opts, !!opts.project)
|
|
14004
14165
|
};
|
|
14005
14166
|
}
|
|
14006
14167
|
|
|
@@ -14346,7 +14507,20 @@ var RemoteRegistry = class {
|
|
|
14346
14507
|
}
|
|
14347
14508
|
try {
|
|
14348
14509
|
await withDependencyInstall(opts.cwd ?? process.cwd(), async () => {
|
|
14349
|
-
const
|
|
14510
|
+
const pins = readLockfile(opts.cwd).plugins;
|
|
14511
|
+
assertUniqueNpmPlugins([
|
|
14512
|
+
...discoverPluginCatalog({ cwd: opts.cwd, storeRoot: opts.storeRoot }).plugins.filter(
|
|
14513
|
+
(item) => item.source === "project" && item.manifest.id !== alias && !pins[item.manifest.id]
|
|
14514
|
+
).map((item) => ({ alias: item.manifest.id, manifest: item.manifest })),
|
|
14515
|
+
...Object.entries(pins).filter(([key]) => key !== alias).map(([key, locked]) => ({
|
|
14516
|
+
alias: key,
|
|
14517
|
+
manifest: loadPluginManifest(
|
|
14518
|
+
storeEntryDir(locked.pluginId ?? key, locked.version, locked.sha256, opts.storeRoot)
|
|
14519
|
+
)
|
|
14520
|
+
})),
|
|
14521
|
+
{ alias, manifest: entry.manifest }
|
|
14522
|
+
]);
|
|
14523
|
+
const previous = pins[alias];
|
|
14350
14524
|
if (previous && ((previous.pluginId ?? alias) !== entry.id || previous.registry !== this.baseUrl || previous.publisher !== pin.publisher))
|
|
14351
14525
|
throw new Error("Plugin alias belongs to another publisher or registry");
|
|
14352
14526
|
upsertLockEntry(opts.cwd ?? process.cwd(), alias, pin);
|