@octonodes/cli 0.2.4 → 0.2.6
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 +257 -24
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@octonodes/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
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.6",
|
|
25
25
|
"@supabase/supabase-js": "2.107.0",
|
|
26
26
|
"esbuild": "0.28.1",
|
|
27
27
|
"tar": "7.5.22",
|
|
@@ -11541,7 +11541,7 @@ var require_plugin_publishing = __commonJS({
|
|
|
11541
11541
|
"packages/schema/dist/plugin-publishing.js"(exports2) {
|
|
11542
11542
|
"use strict";
|
|
11543
11543
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
11544
|
-
exports2.PluginCloudBuild = exports2.PluginPublisherBuildDetail = exports2.PluginPublisherBuilds = exports2.PluginPublisherBuildQuery = exports2.PluginPublisherApplied = exports2.PluginPublisherApply = exports2.PluginPublisherReview = exports2.PluginPublisherReviewItem = exports2.PluginPublisherOperation = exports2.PluginPublisherConnections = exports2.PluginPublisherConnection = exports2.PluginPublisherPreview = exports2.PluginPublisherConsent = exports2.PluginPublisherAutomatic = exports2.PluginPublisherRepository = exports2.PluginPublisherInput = exports2.pluginReleaseScope = exports2.PluginReleaseConfig = exports2.PluginConfigPath = void 0;
|
|
11544
|
+
exports2.PluginCloudBuild = exports2.PluginPublisherBuildDetail = exports2.PluginPublisherBuilds = exports2.PluginPublisherBuildQuery = exports2.PluginPublisherListQuery = exports2.PluginPublisherApplied = exports2.PluginPublisherApply = exports2.PluginPublisherReview = exports2.PluginPublisherReviewItem = exports2.PluginPublisherOperation = exports2.PluginPublisherConnections = exports2.PluginPublisherConnection = exports2.PluginPublisherPreview = exports2.PluginPublisherConsent = exports2.PluginPublisherAutomatic = exports2.PluginPublisherRepository = exports2.PluginPublisherInput = exports2.pluginReleaseScope = exports2.PluginReleaseConfig = exports2.PluginConfigPath = void 0;
|
|
11545
11545
|
var zod_1 = require("zod");
|
|
11546
11546
|
var plugin_version_1 = require_plugin_version();
|
|
11547
11547
|
exports2.PluginConfigPath = zod_1.z.string().max(512).refine((path) => /^(?:[a-zA-Z0-9_.-]+\/)*(?:plugin\.octonode\.(?:json|ya?ml)|octonode\.plugin\.json)$/.test(path) && !path.split("/").some((part) => [".", "..", ".git", "node_modules"].includes(part)), "Select a repository-relative octonode.plugin.json file (older plugin.octonode release files also work)");
|
|
@@ -11612,17 +11612,32 @@ var require_plugin_publishing = __commonJS({
|
|
|
11612
11612
|
repositoryId: zod_1.z.number(),
|
|
11613
11613
|
buildId: zod_1.z.number()
|
|
11614
11614
|
});
|
|
11615
|
+
exports2.PluginPublisherListQuery = zod_1.z.object({
|
|
11616
|
+
q: zod_1.z.string().trim().max(200).default(""),
|
|
11617
|
+
offset: zod_1.z.coerce.number().int().min(0).max(1e6).default(0),
|
|
11618
|
+
limit: zod_1.z.coerce.number().int().min(1).max(100).default(25),
|
|
11619
|
+
days: zod_1.z.enum(["7", "30", "90"]).default("30"),
|
|
11620
|
+
scope: zod_1.z.enum(["", "user", "group", "org", "public"]).default(""),
|
|
11621
|
+
source: zod_1.z.enum(["", "sdk", "npm"]).default(""),
|
|
11622
|
+
sort: zod_1.z.enum(["updated", "name", "version", "scope", "source", "installs", "score", "versions"]).default("updated"),
|
|
11623
|
+
direction: zod_1.z.enum(["asc", "desc"]).default("desc")
|
|
11624
|
+
});
|
|
11615
11625
|
exports2.PluginPublisherBuildQuery = zod_1.z.object({
|
|
11616
11626
|
repositoryId: zod_1.z.coerce.number().int().positive().optional(),
|
|
11617
|
-
page: zod_1.z.coerce.number().int().min(1).max(
|
|
11627
|
+
page: zod_1.z.coerce.number().int().min(1).max(1e6).default(1),
|
|
11618
11628
|
search: zod_1.z.string().max(200).default(""),
|
|
11619
11629
|
status: zod_1.z.enum(["", "queued", "in_progress", "success", "failure"]).default(""),
|
|
11620
|
-
sort: zod_1.z.enum(["newest", "oldest", "name"]).default("newest")
|
|
11630
|
+
sort: zod_1.z.enum(["newest", "oldest", "name", "status", "branch", "sha"]).default("newest"),
|
|
11631
|
+
direction: zod_1.z.enum(["asc", "desc"]).default("asc"),
|
|
11632
|
+
limit: zod_1.z.coerce.number().int().min(1).max(100).default(30),
|
|
11633
|
+
branch: zod_1.z.string().trim().max(200).default(""),
|
|
11634
|
+
sha: zod_1.z.string().trim().max(200).default("")
|
|
11621
11635
|
});
|
|
11622
11636
|
exports2.PluginPublisherBuilds = zod_1.z.object({
|
|
11623
11637
|
total: zod_1.z.number(),
|
|
11624
11638
|
page: zod_1.z.number(),
|
|
11625
11639
|
hasMore: zod_1.z.boolean(),
|
|
11640
|
+
limit: zod_1.z.number(),
|
|
11626
11641
|
items: zod_1.z.array(zod_1.z.object({
|
|
11627
11642
|
id: zod_1.z.number(),
|
|
11628
11643
|
repositoryId: zod_1.z.number(),
|
|
@@ -11670,6 +11685,43 @@ var require_plugin_publishing = __commonJS({
|
|
|
11670
11685
|
}
|
|
11671
11686
|
});
|
|
11672
11687
|
|
|
11688
|
+
// packages/schema/dist/plugin-allowlist.js
|
|
11689
|
+
var require_plugin_allowlist = __commonJS({
|
|
11690
|
+
"packages/schema/dist/plugin-allowlist.js"(exports2) {
|
|
11691
|
+
"use strict";
|
|
11692
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
11693
|
+
exports2.PluginAllowlistPage = exports2.PluginAllowlistInput = exports2.PluginAllowlistQuery = exports2.PluginAllowlistKind = void 0;
|
|
11694
|
+
var zod_1 = require("zod");
|
|
11695
|
+
exports2.PluginAllowlistKind = zod_1.z.enum(["org", "team", "user"]);
|
|
11696
|
+
exports2.PluginAllowlistQuery = zod_1.z.object({
|
|
11697
|
+
kind: exports2.PluginAllowlistKind,
|
|
11698
|
+
q: zod_1.z.string().trim().max(200).default(""),
|
|
11699
|
+
status: zod_1.z.enum(["allowed", "available", "all"]).default("allowed"),
|
|
11700
|
+
sort: zod_1.z.enum(["name", "id"]).default("name"),
|
|
11701
|
+
direction: zod_1.z.enum(["asc", "desc"]).default("asc"),
|
|
11702
|
+
offset: zod_1.z.coerce.number().int().min(0).max(1e6).default(0),
|
|
11703
|
+
limit: zod_1.z.coerce.number().int().min(1).max(100).default(25)
|
|
11704
|
+
});
|
|
11705
|
+
exports2.PluginAllowlistInput = zod_1.z.object({
|
|
11706
|
+
kind: exports2.PluginAllowlistKind,
|
|
11707
|
+
id: zod_1.z.string().min(1).max(200)
|
|
11708
|
+
}).strict();
|
|
11709
|
+
exports2.PluginAllowlistPage = zod_1.z.object({
|
|
11710
|
+
items: zod_1.z.array(zod_1.z.object({
|
|
11711
|
+
id: zod_1.z.string(),
|
|
11712
|
+
name: zod_1.z.string(),
|
|
11713
|
+
allowed: zod_1.z.boolean(),
|
|
11714
|
+
inherited: zod_1.z.boolean(),
|
|
11715
|
+
eligible: zod_1.z.boolean()
|
|
11716
|
+
})),
|
|
11717
|
+
total: zod_1.z.number(),
|
|
11718
|
+
offset: zod_1.z.number(),
|
|
11719
|
+
limit: zod_1.z.number(),
|
|
11720
|
+
canAdd: zod_1.z.boolean()
|
|
11721
|
+
});
|
|
11722
|
+
}
|
|
11723
|
+
});
|
|
11724
|
+
|
|
11673
11725
|
// packages/schema/dist/index.js
|
|
11674
11726
|
var require_dist = __commonJS({
|
|
11675
11727
|
"packages/schema/dist/index.js"(exports2) {
|
|
@@ -11735,6 +11787,7 @@ var require_dist = __commonJS({
|
|
|
11735
11787
|
__exportStar(require_execution(), exports2);
|
|
11736
11788
|
__exportStar(require_execution_constants(), exports2);
|
|
11737
11789
|
__exportStar(require_plugin_publishing(), exports2);
|
|
11790
|
+
__exportStar(require_plugin_allowlist(), exports2);
|
|
11738
11791
|
}
|
|
11739
11792
|
});
|
|
11740
11793
|
|
|
@@ -12201,8 +12254,8 @@ var require_constants2 = __commonJS({
|
|
|
12201
12254
|
exports2.OCTONODE_STORE_DIR = OCTONODE_STORE_DIR;
|
|
12202
12255
|
var OCTONODE_STUDIO_URL = () => exports2.PROCESS_ENV.OCTONODE_STUDIO_URL ?? exports2.PROCESS_ENV.VITE_OCTONODE_STUDIO_URL ?? exports2.PROCESS_ENV.VITE_PUBLIC_OCTONODE_STUDIO_URL;
|
|
12203
12256
|
exports2.OCTONODE_STUDIO_URL = OCTONODE_STUDIO_URL;
|
|
12204
|
-
var
|
|
12205
|
-
exports2.OCTONODE_USER =
|
|
12257
|
+
var OCTONODE_USER2 = () => exports2.PROCESS_ENV.OCTONODE_USER;
|
|
12258
|
+
exports2.OCTONODE_USER = OCTONODE_USER2;
|
|
12206
12259
|
var OCTONODE_USER_EMAIL = () => exports2.PROCESS_ENV.OCTONODE_USER_EMAIL;
|
|
12207
12260
|
exports2.OCTONODE_USER_EMAIL = OCTONODE_USER_EMAIL;
|
|
12208
12261
|
var OCTONODE_VISUAL_PORT = () => exports2.PROCESS_ENV.OCTONODE_VISUAL_PORT;
|
|
@@ -12716,6 +12769,7 @@ var PLUGIN_BUNDLE_EXCLUDES = [
|
|
|
12716
12769
|
"*.pem",
|
|
12717
12770
|
"*.key"
|
|
12718
12771
|
];
|
|
12772
|
+
var MAX_CATALOG_MANIFESTS = 512;
|
|
12719
12773
|
|
|
12720
12774
|
// packages/plugin/src/integrity.ts
|
|
12721
12775
|
function collectFiles(dir, base, files) {
|
|
@@ -12875,6 +12929,79 @@ function loadPlugin(dir, source = "user") {
|
|
|
12875
12929
|
function isPluginDir(dir) {
|
|
12876
12930
|
return import_schema2.PLUGIN_DEFINITION_FILENAMES.some((name) => (0, import_node_fs4.existsSync)((0, import_node_path4.join)(dir, name)));
|
|
12877
12931
|
}
|
|
12932
|
+
function pluginDirsIn(root) {
|
|
12933
|
+
if (!(0, import_node_fs4.existsSync)(root)) return [];
|
|
12934
|
+
const out = [];
|
|
12935
|
+
for (const name of (0, import_node_fs4.readdirSync)(root)) {
|
|
12936
|
+
if (name.startsWith(".")) continue;
|
|
12937
|
+
const dir = (0, import_node_path4.join)(root, name);
|
|
12938
|
+
try {
|
|
12939
|
+
if ((0, import_node_fs4.statSync)(dir).isDirectory() && isPluginDir(dir)) out.push(dir);
|
|
12940
|
+
} catch {
|
|
12941
|
+
}
|
|
12942
|
+
}
|
|
12943
|
+
return out;
|
|
12944
|
+
}
|
|
12945
|
+
function discoverPluginCatalog(opts = {}) {
|
|
12946
|
+
return discover(opts, true);
|
|
12947
|
+
}
|
|
12948
|
+
var catalogManifests = /* @__PURE__ */ new Map();
|
|
12949
|
+
function catalogManifest(dir) {
|
|
12950
|
+
const path = (0, import_plugin_runtime2.pluginDefinitionPath)(dir);
|
|
12951
|
+
const stat = (0, import_node_fs4.statSync)(path);
|
|
12952
|
+
const revision = `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeMs}:${stat.ctimeMs}`;
|
|
12953
|
+
const cached = catalogManifests.get(path);
|
|
12954
|
+
if (cached?.revision === revision) return cached.manifest;
|
|
12955
|
+
const manifest2 = loadPluginManifest(dir);
|
|
12956
|
+
if (catalogManifests.size >= MAX_CATALOG_MANIFESTS) catalogManifests.delete(catalogManifests.keys().next().value);
|
|
12957
|
+
catalogManifests.set(path, { revision, manifest: manifest2 });
|
|
12958
|
+
return manifest2;
|
|
12959
|
+
}
|
|
12960
|
+
function discover(opts, metadataOnly) {
|
|
12961
|
+
const plugins = [];
|
|
12962
|
+
const errors = [];
|
|
12963
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12964
|
+
const scanRoot = (root, source) => {
|
|
12965
|
+
for (const dir of pluginDirsIn(root)) {
|
|
12966
|
+
try {
|
|
12967
|
+
const manifest2 = metadataOnly ? catalogManifest(dir) : loadPluginManifest(dir);
|
|
12968
|
+
if (seen.has(manifest2.id)) continue;
|
|
12969
|
+
seen.add(manifest2.id);
|
|
12970
|
+
plugins.push({ manifest: manifest2, dir, source });
|
|
12971
|
+
} catch (err) {
|
|
12972
|
+
errors.push({ dir, message: err.message });
|
|
12973
|
+
}
|
|
12974
|
+
}
|
|
12975
|
+
};
|
|
12976
|
+
scanRoot(projectPluginRoot(opts.cwd), "project");
|
|
12977
|
+
try {
|
|
12978
|
+
const lock = readLockfile(opts.cwd);
|
|
12979
|
+
for (const [id, entry] of Object.entries(lock.plugins)) {
|
|
12980
|
+
if (seen.has(id)) continue;
|
|
12981
|
+
const dir = storeEntryDir(entry.pluginId ?? id, entry.version, entry.sha256, opts.storeRoot);
|
|
12982
|
+
if (!isPluginDir(dir)) {
|
|
12983
|
+
errors.push({
|
|
12984
|
+
dir,
|
|
12985
|
+
message: `plugin "${id}"@${entry.version} is locked but missing from the store \u2014 run \`octonode install\``
|
|
12986
|
+
});
|
|
12987
|
+
continue;
|
|
12988
|
+
}
|
|
12989
|
+
try {
|
|
12990
|
+
const manifest2 = metadataOnly ? catalogManifest(dir) : loadPluginManifest(dir);
|
|
12991
|
+
if (manifest2.id !== (entry.pluginId ?? id) || manifest2.version !== entry.version || !metadataOnly && hashPluginDir(dir) !== entry.sha256)
|
|
12992
|
+
throw new Error(`Locked plugin ${id} failed identity or integrity validation; run octonode install`);
|
|
12993
|
+
seen.add(id);
|
|
12994
|
+
plugins.push({ manifest: { ...manifest2, id }, dir, source: "store" });
|
|
12995
|
+
} catch (err) {
|
|
12996
|
+
errors.push({ dir, message: err.message });
|
|
12997
|
+
}
|
|
12998
|
+
}
|
|
12999
|
+
} catch (err) {
|
|
13000
|
+
errors.push({ dir: opts.cwd ?? process.cwd(), message: err.message });
|
|
13001
|
+
}
|
|
13002
|
+
scanRoot(opts.userRoot ?? userPluginRoot(), "user");
|
|
13003
|
+
return { plugins, errors };
|
|
13004
|
+
}
|
|
12878
13005
|
|
|
12879
13006
|
// packages/plugin/src/dependencies.ts
|
|
12880
13007
|
var import_node_child_process = require("node:child_process");
|
|
@@ -13254,7 +13381,7 @@ async function run(project, command, cwd, cacheRoot) {
|
|
|
13254
13381
|
maxBuffer: 4 * 1024 * 1024
|
|
13255
13382
|
});
|
|
13256
13383
|
}
|
|
13257
|
-
async function verifyProjectDependencies(project, names) {
|
|
13384
|
+
async function verifyProjectDependencies(project, names, versions = {}) {
|
|
13258
13385
|
if (!names.length) return;
|
|
13259
13386
|
const pnp = (0, import_node_path6.join)(project.root, ".pnp.cjs");
|
|
13260
13387
|
const loader = (0, import_node_path6.join)(project.root, ".pnp.loader.mjs");
|
|
@@ -13266,14 +13393,37 @@ async function verifyProjectDependencies(project, names) {
|
|
|
13266
13393
|
"--input-type=module",
|
|
13267
13394
|
"-e",
|
|
13268
13395
|
`import { createRequire } from 'node:module';
|
|
13269
|
-
import { existsSync } from 'node:fs';
|
|
13396
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
13397
|
+
import { dirname, join } from 'node:path';
|
|
13270
13398
|
import { fileURLToPath } from 'node:url';
|
|
13271
13399
|
const require = createRequire(${JSON.stringify((0, import_node_path6.join)(project.target, "package.json"))});
|
|
13400
|
+
const versions = ${JSON.stringify(versions)};
|
|
13272
13401
|
for (const name of ${JSON.stringify(names)}) {
|
|
13273
|
-
|
|
13402
|
+
let resolved;
|
|
13403
|
+
try { resolved = require.resolve(name); } catch {
|
|
13274
13404
|
const entry = import.meta.resolve(name);
|
|
13405
|
+
resolved = entry.startsWith('file:') ? fileURLToPath(entry) : undefined;
|
|
13275
13406
|
if (entry.startsWith('file:') && !existsSync(fileURLToPath(entry))) throw new Error('missing package entry: ' + name);
|
|
13276
13407
|
}
|
|
13408
|
+
const identity = name.startsWith('@') ? name.split('/').slice(0, 2).join('/') : name.split('/')[0];
|
|
13409
|
+
if (Object.hasOwn(versions, identity)) {
|
|
13410
|
+
let directory = resolved ? dirname(resolved) : '';
|
|
13411
|
+
let matched = false;
|
|
13412
|
+
while (directory) {
|
|
13413
|
+
const file = join(directory, 'package.json');
|
|
13414
|
+
if (existsSync(file)) {
|
|
13415
|
+
const pkg = JSON.parse(readFileSync(file, 'utf8'));
|
|
13416
|
+
if (pkg.name === identity) {
|
|
13417
|
+
if (pkg.version !== versions[identity]) throw new Error('installed dependency version mismatch: ' + name);
|
|
13418
|
+
matched = true; break;
|
|
13419
|
+
}
|
|
13420
|
+
}
|
|
13421
|
+
const parent = dirname(directory);
|
|
13422
|
+
if (parent === directory) break;
|
|
13423
|
+
directory = parent;
|
|
13424
|
+
}
|
|
13425
|
+
if (!matched) throw new Error('cannot verify installed package: ' + name);
|
|
13426
|
+
}
|
|
13277
13427
|
}`
|
|
13278
13428
|
],
|
|
13279
13429
|
{ cwd: project.target, env: (0, import_common.childProcessEnvironment)(), timeout: 3e4, maxBuffer: 1024 * 1024 }
|
|
@@ -13323,7 +13473,40 @@ async function reconcileDependencies(cwd, dependencies, options = {}) {
|
|
|
13323
13473
|
throw new Error("invalid npm dependency subpath");
|
|
13324
13474
|
}
|
|
13325
13475
|
}
|
|
13476
|
+
const unique = /* @__PURE__ */ new Map();
|
|
13477
|
+
for (const dependency of dependencies) {
|
|
13478
|
+
const spec = dependency.spec.startsWith(`${dependency.name}@`) ? dependency.spec.slice(dependency.name.length + 1) : dependency.spec;
|
|
13479
|
+
const previous = unique.get(dependency.name);
|
|
13480
|
+
if (previous && previous.spec !== spec) throw new Error(`Conflicting dependency requests for ${dependency.name}`);
|
|
13481
|
+
unique.set(dependency.name, {
|
|
13482
|
+
...dependency,
|
|
13483
|
+
spec,
|
|
13484
|
+
...previous?.subpaths || dependency.subpaths ? { subpaths: [.../* @__PURE__ */ new Set([...previous?.subpaths ?? [], ...dependency.subpaths ?? []])] } : {}
|
|
13485
|
+
});
|
|
13486
|
+
}
|
|
13487
|
+
dependencies = [...unique.values()];
|
|
13326
13488
|
const project = resolveDependencyProject(cwd);
|
|
13489
|
+
const declared = manifest(project.target);
|
|
13490
|
+
const existing = { ...declared.devDependencies, ...declared.optionalDependencies, ...declared.dependencies };
|
|
13491
|
+
if (options.preserveExisting) {
|
|
13492
|
+
for (const { name, spec } of dependencies)
|
|
13493
|
+
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))))
|
|
13494
|
+
throw new Error(
|
|
13495
|
+
`Dependency conflict: ${name} is ${existing[name]}, plugin requires ${spec}; reconcile it explicitly first`
|
|
13496
|
+
);
|
|
13497
|
+
}
|
|
13498
|
+
const reusable = dependencies.length > 0 && !options.remove?.length && dependencies.every(
|
|
13499
|
+
({ name, spec }) => existing[name] === spec && /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(spec)
|
|
13500
|
+
);
|
|
13501
|
+
const reuse = reusable && await verifyProjectDependencies(
|
|
13502
|
+
project,
|
|
13503
|
+
dependencies.flatMap(({ name, subpaths }) => subpaths ? subpaths.map((path) => name + path.slice(1)) : [name]),
|
|
13504
|
+
Object.fromEntries(dependencies.map(({ name, spec }) => [name, spec]))
|
|
13505
|
+
).then(
|
|
13506
|
+
() => true,
|
|
13507
|
+
() => false
|
|
13508
|
+
);
|
|
13509
|
+
const metadataOnly = options.metadataOnly || reuse;
|
|
13327
13510
|
const packageJson = (0, import_node_path6.join)(project.target, "package.json");
|
|
13328
13511
|
if (!dependencies.length && !(0, import_node_fs6.existsSync)(packageJson) && !options.commit) return;
|
|
13329
13512
|
const hasLock = PACKAGE_MANAGER_LOCKS[project.manager].some((file) => (0, import_node_fs6.existsSync)((0, import_node_path6.join)(project.root, file)));
|
|
@@ -13359,13 +13542,12 @@ async function reconcileDependencies(cwd, dependencies, options = {}) {
|
|
|
13359
13542
|
else (0, import_node_fs6.writeFileSync)(path, content);
|
|
13360
13543
|
}
|
|
13361
13544
|
};
|
|
13362
|
-
if (hadInstall && !hasLock && !
|
|
13545
|
+
if (hadInstall && !hasLock && !metadataOnly)
|
|
13363
13546
|
throw new Error(
|
|
13364
13547
|
"create a native lockfile before updating existing dependencies so failed installations can be recovered"
|
|
13365
13548
|
);
|
|
13366
13549
|
try {
|
|
13367
|
-
if (
|
|
13368
|
-
(0, import_node_fs6.writeFileSync)((0, import_node_path6.join)((0, import_node_path6.dirname)(journal), "metadata-only"), "1");
|
|
13550
|
+
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
13551
|
if ((0, import_node_fs6.existsSync)((0, import_node_path6.dirname)(journal)))
|
|
13370
13552
|
(0, import_node_fs6.writeFileSync)(
|
|
13371
13553
|
journal,
|
|
@@ -13376,7 +13558,7 @@ async function reconcileDependencies(cwd, dependencies, options = {}) {
|
|
|
13376
13558
|
}))
|
|
13377
13559
|
)
|
|
13378
13560
|
);
|
|
13379
|
-
if (
|
|
13561
|
+
if (metadataOnly) {
|
|
13380
13562
|
metadataTouched = true;
|
|
13381
13563
|
options.commit?.();
|
|
13382
13564
|
(0, import_node_fs6.rmSync)(journal, { force: true });
|
|
@@ -13468,14 +13650,14 @@ async function reconcileDependencies(cwd, dependencies, options = {}) {
|
|
|
13468
13650
|
}
|
|
13469
13651
|
restoreBefore();
|
|
13470
13652
|
let recovery = "";
|
|
13471
|
-
if (!
|
|
13653
|
+
if (!metadataOnly && hadInstall && hasLock) {
|
|
13472
13654
|
try {
|
|
13473
13655
|
await run(project, installCommand(project, true), project.root, options.cacheRoot);
|
|
13474
13656
|
} catch {
|
|
13475
13657
|
recovery = "; manifests restored, but dependency recovery failed \u2014 run a frozen install before executing workflows";
|
|
13476
13658
|
}
|
|
13477
13659
|
restoreBefore();
|
|
13478
|
-
} else if (!
|
|
13660
|
+
} else if (!metadataOnly && !hadInstall) {
|
|
13479
13661
|
(0, import_node_fs6.rmSync)((0, import_node_path6.join)(project.root, "node_modules"), { recursive: true, force: true });
|
|
13480
13662
|
}
|
|
13481
13663
|
for (const [path, content] of pnpBefore) {
|
|
@@ -13780,6 +13962,19 @@ async function generatePluginPackage(cwd, selections, expectedPacker) {
|
|
|
13780
13962
|
function pluginNpmDependencies(manifest2) {
|
|
13781
13963
|
return manifest2.integration?.npmDependencies ?? (manifest2.integration?.npm ? [manifest2.integration.npm] : []);
|
|
13782
13964
|
}
|
|
13965
|
+
function assertUniqueNpmPlugins(plugins) {
|
|
13966
|
+
const owners = /* @__PURE__ */ new Map();
|
|
13967
|
+
for (const { alias, manifest: manifest2 } of plugins) {
|
|
13968
|
+
const pkg = manifest2.integration?.npm?.package.trim().toLowerCase();
|
|
13969
|
+
if (!pkg) continue;
|
|
13970
|
+
const previous = owners.get(pkg);
|
|
13971
|
+
if (previous && previous !== alias)
|
|
13972
|
+
throw new Error(
|
|
13973
|
+
`Use existing npm integration "${previous}" for ${pkg}; duplicate plugin alias "${alias}" is not allowed`
|
|
13974
|
+
);
|
|
13975
|
+
owners.set(pkg, alias);
|
|
13976
|
+
}
|
|
13977
|
+
}
|
|
13783
13978
|
|
|
13784
13979
|
// packages/plugin/src/prepared/invocation.ts
|
|
13785
13980
|
var import_common3 = __toESM(require_dist2());
|
|
@@ -13828,6 +14023,10 @@ async function reconcilePluginLock(cwd, next, options = {}) {
|
|
|
13828
14023
|
throw new Error(`Plugin identity or integrity mismatch: ${alias}`);
|
|
13829
14024
|
return { alias, directory, sha256: pin.sha256, manifest: manifest2, remote: preparedPluginPin(directory, pin) };
|
|
13830
14025
|
});
|
|
14026
|
+
assertUniqueNpmPlugins([
|
|
14027
|
+
...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 })),
|
|
14028
|
+
...loaded
|
|
14029
|
+
]);
|
|
13831
14030
|
const libraries = loaded.filter((item) => item.manifest.library);
|
|
13832
14031
|
const generated = libraries.length ? await generatePluginPackage(project.target, libraries) : void 0;
|
|
13833
14032
|
const packageFile = (0, import_node_path10.join)(project.target, "package.json");
|
|
@@ -13924,6 +14123,9 @@ function installRoot(opts) {
|
|
|
13924
14123
|
return opts.project ? { root: projectPluginRoot(opts.cwd), source: "project" } : { root: userPluginRoot(), source: "user" };
|
|
13925
14124
|
}
|
|
13926
14125
|
async function installNodeDeps(dir, opts = {}) {
|
|
14126
|
+
return installNodeDepsUnlocked(dir, opts, false);
|
|
14127
|
+
}
|
|
14128
|
+
async function installNodeDepsUnlocked(dir, opts, locked) {
|
|
13927
14129
|
if (opts.noDeps) return {};
|
|
13928
14130
|
const dependencies = pluginNpmDependencies(loadPluginManifest(dir));
|
|
13929
14131
|
if (dependencies.length) {
|
|
@@ -13936,11 +14138,12 @@ async function installNodeDeps(dir, opts = {}) {
|
|
|
13936
14138
|
});
|
|
13937
14139
|
return {};
|
|
13938
14140
|
}
|
|
13939
|
-
await installProjectDependencies(
|
|
14141
|
+
await (locked ? reconcileDependencies : installProjectDependencies)(
|
|
13940
14142
|
opts.cwd ?? process.cwd(),
|
|
13941
14143
|
dependencies.map((npm) => ({ name: npm.package, spec: npm.spec })),
|
|
13942
14144
|
{
|
|
13943
|
-
cacheRoot: opts.cacheRoot
|
|
14145
|
+
cacheRoot: opts.cacheRoot,
|
|
14146
|
+
preserveExisting: true
|
|
13944
14147
|
}
|
|
13945
14148
|
);
|
|
13946
14149
|
return { depsInstalled: true };
|
|
@@ -13976,6 +14179,10 @@ async function installNodeDeps(dir, opts = {}) {
|
|
|
13976
14179
|
}
|
|
13977
14180
|
}
|
|
13978
14181
|
async function installPlugin(src, opts = {}) {
|
|
14182
|
+
if (opts.project) return withDependencyInstall(opts.cwd ?? process.cwd(), () => installPluginUnlocked(src, opts));
|
|
14183
|
+
return installPluginUnlocked(src, opts);
|
|
14184
|
+
}
|
|
14185
|
+
async function installPluginUnlocked(src, opts) {
|
|
13979
14186
|
if (!(0, import_node_fs11.existsSync)(src) || !(0, import_node_fs11.statSync)(src).isDirectory()) {
|
|
13980
14187
|
throw new Error(`source "${src}" is not a directory`);
|
|
13981
14188
|
}
|
|
@@ -13984,13 +14191,20 @@ async function installPlugin(src, opts = {}) {
|
|
|
13984
14191
|
}
|
|
13985
14192
|
const { manifest: manifest2 } = loadPlugin(src);
|
|
13986
14193
|
const { root, source } = installRoot(opts);
|
|
14194
|
+
const installed = discoverPluginCatalog({ cwd: opts.cwd }).plugins.filter(
|
|
14195
|
+
(item) => (opts.project ? item.source !== "user" : item.source === "user") && item.manifest.id !== manifest2.id
|
|
14196
|
+
);
|
|
14197
|
+
assertUniqueNpmPlugins([
|
|
14198
|
+
...installed.map((item) => ({ alias: item.manifest.id, manifest: item.manifest })),
|
|
14199
|
+
{ alias: manifest2.id, manifest: manifest2 }
|
|
14200
|
+
]);
|
|
13987
14201
|
const dest = (0, import_node_path11.join)(root, manifest2.id);
|
|
13988
14202
|
if ((0, import_node_fs11.existsSync)(dest)) {
|
|
13989
14203
|
if (!opts.force) {
|
|
13990
14204
|
throw new Error(`plugin "${manifest2.id}" is already installed at ${dest} (use --force to overwrite)`);
|
|
13991
14205
|
}
|
|
13992
14206
|
}
|
|
13993
|
-
const deps = pluginNpmDependencies(manifest2).length ? await
|
|
14207
|
+
const deps = pluginNpmDependencies(manifest2).length ? await installNodeDepsUnlocked(src, { ...opts, cacheOnly: opts.cacheOnly ?? !opts.project }, !!opts.project) : {};
|
|
13994
14208
|
if (deps.depsError) return { manifest: manifest2, dir: dest, source, ...deps };
|
|
13995
14209
|
if ((0, import_node_fs11.existsSync)(dest)) (0, import_node_fs11.rmSync)(dest, { recursive: true, force: true });
|
|
13996
14210
|
(0, import_node_fs11.mkdirSync)(root, { recursive: true });
|
|
@@ -14000,7 +14214,7 @@ async function installPlugin(src, opts = {}) {
|
|
|
14000
14214
|
dir: dest,
|
|
14001
14215
|
source,
|
|
14002
14216
|
...deps,
|
|
14003
|
-
...pluginNpmDependencies(manifest2).length ? {} : await
|
|
14217
|
+
...pluginNpmDependencies(manifest2).length ? {} : await installNodeDepsUnlocked(dest, opts, !!opts.project)
|
|
14004
14218
|
};
|
|
14005
14219
|
}
|
|
14006
14220
|
|
|
@@ -14073,11 +14287,15 @@ var RemoteRegistry = class {
|
|
|
14073
14287
|
}
|
|
14074
14288
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
14075
14289
|
this.token = opts.token ?? (0, import_common5.OCTONODE_MARKETPLACE_TOKEN)();
|
|
14290
|
+
this.workspace = opts.workspace ?? (0, import_common5.OCTONODE_USER)()?.match(/^workspace:((?:user|org|team):.+)$/)?.[1];
|
|
14076
14291
|
}
|
|
14077
14292
|
async request(path, init = {}) {
|
|
14078
14293
|
const headers = new Headers(init.headers);
|
|
14079
14294
|
if (this.token) headers.set("authorization", `Bearer ${this.token}`);
|
|
14080
|
-
const
|
|
14295
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
14296
|
+
if (this.workspace && (init.method === void 0 || init.method === "GET" || url.pathname.endsWith("/install")))
|
|
14297
|
+
url.searchParams.set("workspace", this.workspace);
|
|
14298
|
+
const res = await fetch(url.toString(), {
|
|
14081
14299
|
...init,
|
|
14082
14300
|
headers,
|
|
14083
14301
|
redirect: "error",
|
|
@@ -14217,13 +14435,15 @@ var RemoteRegistry = class {
|
|
|
14217
14435
|
*/
|
|
14218
14436
|
async install(id, opts = {}) {
|
|
14219
14437
|
const detail = await this.detail(id, opts.scope);
|
|
14438
|
+
if (detail.manifestId && detail.manifestId !== id)
|
|
14439
|
+
throw new Error("Publisher-qualified plugins require installToStore so their registry identity is preserved");
|
|
14220
14440
|
const version = opts.version ?? detail.version;
|
|
14221
14441
|
const release2 = detail.versions?.find((entry) => entry.version === version);
|
|
14222
14442
|
const dir = await this.downloadBundle(
|
|
14223
14443
|
id,
|
|
14224
14444
|
version,
|
|
14225
14445
|
opts.scope,
|
|
14226
|
-
id,
|
|
14446
|
+
detail.manifestId ?? id,
|
|
14227
14447
|
release2?.archiveSha256 ?? release2?.sha256
|
|
14228
14448
|
);
|
|
14229
14449
|
const plugin = await installPlugin(dir, opts);
|
|
@@ -14256,7 +14476,7 @@ var RemoteRegistry = class {
|
|
|
14256
14476
|
throw new Error("Marketplace release is missing its immutable checksum");
|
|
14257
14477
|
const availableScopes = versionMeta?.scope ?? detail.scope;
|
|
14258
14478
|
const scope = opts.scope && availableScopes.includes(opts.scope) ? opts.scope : availableScopes[0];
|
|
14259
|
-
const dir = await this.downloadBundle(id, version, scope, id, releaseChecksum);
|
|
14479
|
+
const dir = await this.downloadBundle(id, version, scope, detail.manifestId ?? id, releaseChecksum);
|
|
14260
14480
|
const entry = (() => {
|
|
14261
14481
|
try {
|
|
14262
14482
|
return addToStore(dir, { storeRoot: opts.storeRoot });
|
|
@@ -14271,7 +14491,7 @@ var RemoteRegistry = class {
|
|
|
14271
14491
|
"Library installation requires native dependency activation; use frozen --artifacts-only for CI restore"
|
|
14272
14492
|
);
|
|
14273
14493
|
if (!opts.cacheOnly && !opts.noDeps) {
|
|
14274
|
-
const alias2 = opts.alias ?? entry.id;
|
|
14494
|
+
const alias2 = opts.alias ?? (detail.manifestId && id !== detail.manifestId ? id : entry.id);
|
|
14275
14495
|
const pin2 = {
|
|
14276
14496
|
pluginId: entry.id,
|
|
14277
14497
|
remoteId: id,
|
|
@@ -14323,7 +14543,7 @@ var RemoteRegistry = class {
|
|
|
14323
14543
|
cacheOnly: opts.cacheOnly
|
|
14324
14544
|
}) : {};
|
|
14325
14545
|
if (deps.depsError) throw new Error(deps.depsError);
|
|
14326
|
-
const alias = opts.alias ?? entry.id;
|
|
14546
|
+
const alias = opts.alias ?? (detail.manifestId && id !== detail.manifestId ? id : entry.id);
|
|
14327
14547
|
const pin = {
|
|
14328
14548
|
pluginId: entry.id,
|
|
14329
14549
|
remoteId: id,
|
|
@@ -14346,7 +14566,20 @@ var RemoteRegistry = class {
|
|
|
14346
14566
|
}
|
|
14347
14567
|
try {
|
|
14348
14568
|
await withDependencyInstall(opts.cwd ?? process.cwd(), async () => {
|
|
14349
|
-
const
|
|
14569
|
+
const pins = readLockfile(opts.cwd).plugins;
|
|
14570
|
+
assertUniqueNpmPlugins([
|
|
14571
|
+
...discoverPluginCatalog({ cwd: opts.cwd, storeRoot: opts.storeRoot }).plugins.filter(
|
|
14572
|
+
(item) => item.source === "project" && item.manifest.id !== alias && !pins[item.manifest.id]
|
|
14573
|
+
).map((item) => ({ alias: item.manifest.id, manifest: item.manifest })),
|
|
14574
|
+
...Object.entries(pins).filter(([key]) => key !== alias).map(([key, locked]) => ({
|
|
14575
|
+
alias: key,
|
|
14576
|
+
manifest: loadPluginManifest(
|
|
14577
|
+
storeEntryDir(locked.pluginId ?? key, locked.version, locked.sha256, opts.storeRoot)
|
|
14578
|
+
)
|
|
14579
|
+
})),
|
|
14580
|
+
{ alias, manifest: entry.manifest }
|
|
14581
|
+
]);
|
|
14582
|
+
const previous = pins[alias];
|
|
14350
14583
|
if (previous && ((previous.pluginId ?? alias) !== entry.id || previous.registry !== this.baseUrl || previous.publisher !== pin.publisher))
|
|
14351
14584
|
throw new Error("Plugin alias belongs to another publisher or registry");
|
|
14352
14585
|
upsertLockEntry(opts.cwd ?? process.cwd(), alias, pin);
|