@octonodes/cli 0.1.13 → 0.2.0
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 +21 -7
- package/dist/plugins/artifact.d.ts.map +1 -1
- package/dist/plugins/artifact.js +10 -0
- package/dist/plugins/artifact.js.map +1 -1
- package/dist/plugins/build.d.ts.map +1 -1
- package/dist/plugins/build.js +14 -1
- package/dist/plugins/build.js.map +1 -1
- package/dist/plugins/create.d.ts.map +1 -1
- package/dist/plugins/create.js +2 -1
- package/dist/plugins/create.js.map +1 -1
- package/dist/plugins/deploy.d.ts +2 -0
- package/dist/plugins/deploy.d.ts.map +1 -0
- package/dist/plugins/deploy.js +95 -0
- package/dist/plugins/deploy.js.map +1 -0
- package/dist/plugins/help.constants.d.ts +1 -1
- package/dist/plugins/help.constants.d.ts.map +1 -1
- package/dist/plugins/help.constants.js +4 -0
- package/dist/plugins/help.constants.js.map +1 -1
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +23 -1
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/publish.d.ts +100 -0
- package/dist/plugins/publish.d.ts.map +1 -1
- package/dist/plugins/publish.js +34 -29
- package/dist/plugins/publish.js.map +1 -1
- package/dist/plugins/release.d.ts +32 -0
- package/dist/plugins/release.d.ts.map +1 -0
- package/dist/plugins/release.js +60 -0
- package/dist/plugins/release.js.map +1 -0
- package/dist/plugins/types.d.ts +9 -1
- package/dist/plugins/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/runtime/plugin-lifecycle.cjs +1061 -493
|
@@ -346,10 +346,10 @@ var require_croner = __commonJS({
|
|
|
346
346
|
if (t && typeof t == "object" || typeof t == "function") for (let s of E(t)) !M.call(n, s) && s !== e && D(n, s, { get: () => t[s], enumerable: !(r = x(t, s)) || r.enumerable });
|
|
347
347
|
return n;
|
|
348
348
|
};
|
|
349
|
-
var
|
|
349
|
+
var z3 = (n) => A(D({}, "__esModule", { value: true }), n);
|
|
350
350
|
var W = {};
|
|
351
351
|
U(W, { Cron: () => N, CronDate: () => h, CronPattern: () => g, scheduledJobs: () => C });
|
|
352
|
-
module2.exports =
|
|
352
|
+
module2.exports = z3(W);
|
|
353
353
|
function f(n, t, e, r, s, i, a, l) {
|
|
354
354
|
return f.fromTZ(f.tp(n, t, e, r, s, i, a), l);
|
|
355
355
|
}
|
|
@@ -830,7 +830,7 @@ var require_constants = __commonJS({
|
|
|
830
830
|
"packages/schema/dist/constants.js"(exports2) {
|
|
831
831
|
"use strict";
|
|
832
832
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
833
|
-
exports2.CAPABILITY_UNAVAILABLE_REASONS = exports2.CAPABILITY_MODES = exports2.PLATFORM_CAPABILITIES = exports2.SOURCE_CONTROL_REGION_KINDS = exports2.TASK_RELEASE_STATES = exports2.TASK_SPRINT_STATES = exports2.TASK_LINK_TYPES = exports2.TASK_VIEW_SORTS = exports2.TASK_VIEW_GROUPS = exports2.TASK_VIEW_LAYOUTS = exports2.TASK_FIELD_TYPES = exports2.WORK_ITEM_PRIORITIES = exports2.BUILTIN_WORK_ITEM_TYPES = exports2.WORK_ITEM_LEVELS = exports2.TASK_STATUS_CATEGORIES = exports2.TASK_SPACE_TEMPLATES = exports2.COLLABORATION_ACTIONS = exports2.AGENT_TOOL_RISKS = exports2.AGENT_ERROR_CODES = exports2.AGENT_RUN_STATUSES = exports2.WORKSPACE_ACTIONS = exports2.SETTINGS_SECTIONS = exports2.SETTINGS_API_VERSION = exports2.MARKETPLACE_SCOPES = exports2.PLUGIN_DEFINITION_FILENAMES = exports2.PLUGIN_MANIFEST_FILENAME = exports2.COMMUNITY_MEDIA_TYPES = exports2.COMMUNITY_MEDIA_BODY_BYTES = exports2.COMMUNITY_MEDIA_VIDEO_BYTES = exports2.COMMUNITY_MEDIA_IMAGE_BYTES = exports2.PROJECT_JOB_PROTOCOL = exports2.PLUGIN_SCHEMA_VERSION = void 0;
|
|
833
|
+
exports2.PLUGIN_PUBLISH_MAX_BYTES = exports2.PLUGIN_CONFIG_MAX_BYTES = exports2.PLUGIN_PUBLISH_AUDIENCE = exports2.PLUGIN_RELEASE_FILES = exports2.CAPABILITY_UNAVAILABLE_REASONS = exports2.CAPABILITY_MODES = exports2.PLATFORM_CAPABILITIES = exports2.SOURCE_CONTROL_REGION_KINDS = exports2.TASK_RELEASE_STATES = exports2.TASK_SPRINT_STATES = exports2.TASK_LINK_TYPES = exports2.TASK_VIEW_SORTS = exports2.TASK_VIEW_GROUPS = exports2.TASK_VIEW_LAYOUTS = exports2.TASK_FIELD_TYPES = exports2.WORK_ITEM_PRIORITIES = exports2.BUILTIN_WORK_ITEM_TYPES = exports2.WORK_ITEM_LEVELS = exports2.TASK_STATUS_CATEGORIES = exports2.TASK_SPACE_TEMPLATES = exports2.COLLABORATION_ACTIONS = exports2.AGENT_TOOL_RISKS = exports2.AGENT_ERROR_CODES = exports2.AGENT_RUN_STATUSES = exports2.WORKSPACE_ACTIONS = exports2.SETTINGS_SECTIONS = exports2.SETTINGS_API_VERSION = exports2.MARKETPLACE_SCOPES = exports2.PLUGIN_DEFINITION_FILENAMES = exports2.PLUGIN_MANIFEST_FILENAME = exports2.COMMUNITY_MEDIA_TYPES = exports2.COMMUNITY_MEDIA_BODY_BYTES = exports2.COMMUNITY_MEDIA_VIDEO_BYTES = exports2.COMMUNITY_MEDIA_IMAGE_BYTES = exports2.PROJECT_JOB_PROTOCOL = exports2.PLUGIN_SCHEMA_VERSION = void 0;
|
|
834
834
|
exports2.PLUGIN_SCHEMA_VERSION = "1";
|
|
835
835
|
exports2.PROJECT_JOB_PROTOCOL = "octonode.project-job.v1";
|
|
836
836
|
exports2.COMMUNITY_MEDIA_IMAGE_BYTES = 8 * 1024 * 1024;
|
|
@@ -1034,6 +1034,10 @@ var require_constants = __commonJS({
|
|
|
1034
1034
|
"missing_entitlement",
|
|
1035
1035
|
"missing_permission"
|
|
1036
1036
|
];
|
|
1037
|
+
exports2.PLUGIN_RELEASE_FILES = ["plugin.octonode.json", "plugin.octonode.yml", "plugin.octonode.yaml"];
|
|
1038
|
+
exports2.PLUGIN_PUBLISH_AUDIENCE = "https://plugins.octonodes.com";
|
|
1039
|
+
exports2.PLUGIN_CONFIG_MAX_BYTES = 65536;
|
|
1040
|
+
exports2.PLUGIN_PUBLISH_MAX_BYTES = 32 * 1024 * 1024;
|
|
1037
1041
|
}
|
|
1038
1042
|
});
|
|
1039
1043
|
|
|
@@ -1316,6 +1320,8 @@ var require_plugin = __commonJS({
|
|
|
1316
1320
|
}).strict().optional(),
|
|
1317
1321
|
icon: icons_1.IconName.optional(),
|
|
1318
1322
|
author: zod_1.z.string().optional(),
|
|
1323
|
+
contributors: zod_1.z.array(zod_1.z.string().trim().min(1).max(240)).max(100).optional(),
|
|
1324
|
+
repository: zod_1.z.string().url().regex(/^https:\/\/github\.com\/[^/]+\/[^/]+\/?$/).optional(),
|
|
1319
1325
|
homepage: zod_1.z.string().optional(),
|
|
1320
1326
|
license: zod_1.z.string().optional(),
|
|
1321
1327
|
/** Distribution tiers this plugin may be discovered/installed from. Private by default. */
|
|
@@ -2639,8 +2645,8 @@ var require_planning = __commonJS({
|
|
|
2639
2645
|
version: collaboration_1.revisionSchema,
|
|
2640
2646
|
createdAt: common_1.taskTimestampSchema,
|
|
2641
2647
|
updatedAt: common_1.taskTimestampSchema
|
|
2642
|
-
}).strict().superRefine((
|
|
2643
|
-
if (
|
|
2648
|
+
}).strict().superRefine((release2, context) => {
|
|
2649
|
+
if (release2.state === "released" && release2.releasedAt === null) {
|
|
2644
2650
|
context.addIssue({
|
|
2645
2651
|
code: zod_1.z.ZodIssueCode.custom,
|
|
2646
2652
|
path: ["releasedAt"],
|
|
@@ -7719,10 +7725,10 @@ var require_build = __commonJS({
|
|
|
7719
7725
|
else out += sub.appendTo();
|
|
7720
7726
|
break;
|
|
7721
7727
|
case Regexp2.Op.ALTERNATE: {
|
|
7722
|
-
let
|
|
7728
|
+
let sep2 = "";
|
|
7723
7729
|
for (let sub of this.subs) {
|
|
7724
|
-
out +=
|
|
7725
|
-
|
|
7730
|
+
out += sep2;
|
|
7731
|
+
sep2 = "|";
|
|
7726
7732
|
out += sub.appendTo();
|
|
7727
7733
|
}
|
|
7728
7734
|
break;
|
|
@@ -11423,6 +11429,7 @@ var require_plugin_version = __commonJS({
|
|
|
11423
11429
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
11424
11430
|
exports2.PluginVersion = void 0;
|
|
11425
11431
|
exports2.comparePluginVersions = comparePluginVersions;
|
|
11432
|
+
exports2.bumpPluginVersion = bumpPluginVersion;
|
|
11426
11433
|
var zod_1 = require("zod");
|
|
11427
11434
|
exports2.PluginVersion = zod_1.z.string().max(200).regex(/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?$/, "Use a semantic version such as 1.2.3 or 2.0.0-beta.1");
|
|
11428
11435
|
function comparePluginVersions(left, right) {
|
|
@@ -11453,6 +11460,120 @@ var require_plugin_version = __commonJS({
|
|
|
11453
11460
|
}
|
|
11454
11461
|
return ap.length - bp.length;
|
|
11455
11462
|
}
|
|
11463
|
+
function bumpPluginVersion(version, release2) {
|
|
11464
|
+
exports2.PluginVersion.parse(version);
|
|
11465
|
+
const core = version.split("+")[0];
|
|
11466
|
+
const prerelease = core.includes("-");
|
|
11467
|
+
let [major, minor, patch] = core.split("-")[0].split(".").map(BigInt);
|
|
11468
|
+
if (release2 === "major") {
|
|
11469
|
+
major += !prerelease || minor !== 0n || patch !== 0n ? 1n : 0n;
|
|
11470
|
+
minor = 0n;
|
|
11471
|
+
patch = 0n;
|
|
11472
|
+
} else if (release2 === "minor") {
|
|
11473
|
+
minor += !prerelease || patch !== 0n ? 1n : 0n;
|
|
11474
|
+
patch = 0n;
|
|
11475
|
+
} else
|
|
11476
|
+
patch += prerelease ? 0n : 1n;
|
|
11477
|
+
return exports2.PluginVersion.parse(`${major}.${minor}.${patch}`);
|
|
11478
|
+
}
|
|
11479
|
+
}
|
|
11480
|
+
});
|
|
11481
|
+
|
|
11482
|
+
// packages/schema/dist/plugin/execution.constants.js
|
|
11483
|
+
var require_execution_constants = __commonJS({
|
|
11484
|
+
"packages/schema/dist/plugin/execution.constants.js"(exports2) {
|
|
11485
|
+
"use strict";
|
|
11486
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
11487
|
+
exports2.PREPARED_RUNTIME_ARCHIVE = exports2.PREPARED_RUNTIME_MAX_FILES = exports2.PREPARED_RUNTIME_MAX_BYTES = exports2.PLUGIN_EXECUTION_TIMEOUT_MS = exports2.PLUGIN_EXECUTION_MAX_BYTES = exports2.PLUGIN_RUNNER_PORT = exports2.PLUGIN_RUNNER_ORIGIN = void 0;
|
|
11488
|
+
exports2.PLUGIN_RUNNER_ORIGIN = "http://plugin-runner.octonode.internal";
|
|
11489
|
+
exports2.PLUGIN_RUNNER_PORT = 4001;
|
|
11490
|
+
exports2.PLUGIN_EXECUTION_MAX_BYTES = 1024 * 1024;
|
|
11491
|
+
exports2.PLUGIN_EXECUTION_TIMEOUT_MS = 5 * 6e4;
|
|
11492
|
+
exports2.PREPARED_RUNTIME_MAX_BYTES = 256 * 1024 * 1024;
|
|
11493
|
+
exports2.PREPARED_RUNTIME_MAX_FILES = 5e4;
|
|
11494
|
+
exports2.PREPARED_RUNTIME_ARCHIVE = "octonode-runtime.tgz";
|
|
11495
|
+
}
|
|
11496
|
+
});
|
|
11497
|
+
|
|
11498
|
+
// packages/schema/dist/plugin/execution.js
|
|
11499
|
+
var require_execution = __commonJS({
|
|
11500
|
+
"packages/schema/dist/plugin/execution.js"(exports2) {
|
|
11501
|
+
"use strict";
|
|
11502
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
11503
|
+
exports2.AuthorizedPluginRelease = exports2.PluginExecutionRequest = exports2.PluginExecutionReference = exports2.PreparedPluginRuntime = void 0;
|
|
11504
|
+
var zod_1 = require("zod");
|
|
11505
|
+
var ipc_envelope_1 = require_ipc_envelope();
|
|
11506
|
+
var plugin_1 = require_plugin();
|
|
11507
|
+
var execution_constants_1 = require_execution_constants();
|
|
11508
|
+
exports2.PreparedPluginRuntime = zod_1.z.object({
|
|
11509
|
+
format: zod_1.z.literal(1),
|
|
11510
|
+
nodeMajor: zod_1.z.literal(24),
|
|
11511
|
+
platform: zod_1.z.enum(["portable", "linux", "darwin"]),
|
|
11512
|
+
arch: zod_1.z.string().max(32).optional(),
|
|
11513
|
+
libc: zod_1.z.string().max(64).optional(),
|
|
11514
|
+
dependencies: zod_1.z.literal(execution_constants_1.PREPARED_RUNTIME_ARCHIVE).optional()
|
|
11515
|
+
}).strict();
|
|
11516
|
+
exports2.PluginExecutionReference = zod_1.z.object({
|
|
11517
|
+
installId: zod_1.z.string().uuid(),
|
|
11518
|
+
sha256: zod_1.z.string().regex(/^sha256:[a-f0-9]{64}$/),
|
|
11519
|
+
nodeId: zod_1.z.string().regex(/^[a-z0-9][a-z0-9_-]*$/i)
|
|
11520
|
+
}).strict();
|
|
11521
|
+
exports2.PluginExecutionRequest = zod_1.z.object({
|
|
11522
|
+
plugin: exports2.PluginExecutionReference,
|
|
11523
|
+
request: ipc_envelope_1.InvokeRequest,
|
|
11524
|
+
environment: zod_1.z.record(zod_1.z.string().regex(/^[a-z_][a-z0-9_]*$/i), zod_1.z.string().max(65536).refine((value) => !value.includes("\0"))).default({}),
|
|
11525
|
+
timeoutMs: zod_1.z.number().int().positive().max(execution_constants_1.PLUGIN_EXECUTION_TIMEOUT_MS).default(execution_constants_1.PLUGIN_EXECUTION_TIMEOUT_MS)
|
|
11526
|
+
}).strict();
|
|
11527
|
+
exports2.AuthorizedPluginRelease = zod_1.z.object({
|
|
11528
|
+
manifest: plugin_1.PluginManifest,
|
|
11529
|
+
archiveSha256: zod_1.z.string().regex(/^[a-f0-9]{64}$/)
|
|
11530
|
+
});
|
|
11531
|
+
}
|
|
11532
|
+
});
|
|
11533
|
+
|
|
11534
|
+
// packages/schema/dist/plugin-publishing.js
|
|
11535
|
+
var require_plugin_publishing = __commonJS({
|
|
11536
|
+
"packages/schema/dist/plugin-publishing.js"(exports2) {
|
|
11537
|
+
"use strict";
|
|
11538
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
11539
|
+
exports2.PluginPublisherConnections = exports2.PluginPublisherConnection = exports2.PluginPublisherPreview = exports2.PluginPublisherConsent = exports2.PluginPublisherInput = exports2.pluginReleaseScope = exports2.PluginReleaseConfig = exports2.PluginConfigPath = void 0;
|
|
11540
|
+
var zod_1 = require("zod");
|
|
11541
|
+
var plugin_version_1 = require_plugin_version();
|
|
11542
|
+
exports2.PluginConfigPath = zod_1.z.string().max(512).refine((path) => /^(?:[a-zA-Z0-9_.-]+\/)*plugin\.octonode\.(json|ya?ml)$/.test(path) && !path.split("/").some((part) => [".", "..", ".git", "node_modules"].includes(part)), "Select a repository-relative plugin.octonode.json or .yml file");
|
|
11543
|
+
exports2.PluginReleaseConfig = zod_1.z.object({
|
|
11544
|
+
apiVersion: zod_1.z.literal("octonode.plugin/v1"),
|
|
11545
|
+
id: zod_1.z.string().max(128).regex(/^[a-z0-9][a-z0-9-]*$/),
|
|
11546
|
+
version: plugin_version_1.PluginVersion,
|
|
11547
|
+
scope: zod_1.z.enum(["user", "team", "organization", "public"]),
|
|
11548
|
+
teamId: zod_1.z.string().min(1).max(128).optional(),
|
|
11549
|
+
orgId: zod_1.z.string().min(1).max(128).optional(),
|
|
11550
|
+
contributors: zod_1.z.array(zod_1.z.string().trim().min(1).max(240)).max(100).optional(),
|
|
11551
|
+
workflow: zod_1.z.string().regex(/^\.github\/workflows\/[a-zA-Z0-9_-]+\.ya?ml$/).default(".github/workflows/octonode-publish.yml")
|
|
11552
|
+
}).strict().superRefine((config, ctx) => {
|
|
11553
|
+
if (config.scope === "team" !== Boolean(config.teamId))
|
|
11554
|
+
ctx.addIssue({ code: "custom", path: ["teamId"], message: "teamId is required only for team scope" });
|
|
11555
|
+
if (config.scope === "organization" !== Boolean(config.orgId))
|
|
11556
|
+
ctx.addIssue({ code: "custom", path: ["orgId"], message: "orgId is required only for organization scope" });
|
|
11557
|
+
});
|
|
11558
|
+
var pluginReleaseScope = (config) => config.scope === "team" ? "group" : config.scope === "organization" ? "org" : config.scope;
|
|
11559
|
+
exports2.pluginReleaseScope = pluginReleaseScope;
|
|
11560
|
+
exports2.PluginPublisherInput = zod_1.z.object({ repositoryId: zod_1.z.number().int().positive(), configPath: exports2.PluginConfigPath }).strict();
|
|
11561
|
+
exports2.PluginPublisherConsent = exports2.PluginPublisherInput.extend({ sha256: zod_1.z.string().regex(/^[a-f0-9]{64}$/) });
|
|
11562
|
+
exports2.PluginPublisherPreview = zod_1.z.object({
|
|
11563
|
+
config: exports2.PluginReleaseConfig,
|
|
11564
|
+
sha256: zod_1.z.string(),
|
|
11565
|
+
repository: zod_1.z.string(),
|
|
11566
|
+
branch: zod_1.z.string()
|
|
11567
|
+
});
|
|
11568
|
+
exports2.PluginPublisherConnection = exports2.PluginPublisherPreview.extend({
|
|
11569
|
+
id: zod_1.z.string().uuid(),
|
|
11570
|
+
repositoryId: zod_1.z.number(),
|
|
11571
|
+
configPath: exports2.PluginConfigPath,
|
|
11572
|
+
lastVersion: zod_1.z.string().nullable(),
|
|
11573
|
+
lastSha: zod_1.z.string().nullable(),
|
|
11574
|
+
lastPublishedAt: zod_1.z.number().nullable()
|
|
11575
|
+
});
|
|
11576
|
+
exports2.PluginPublisherConnections = zod_1.z.object({ items: zod_1.z.array(exports2.PluginPublisherConnection) });
|
|
11456
11577
|
}
|
|
11457
11578
|
});
|
|
11458
11579
|
|
|
@@ -11518,6 +11639,9 @@ var require_dist = __commonJS({
|
|
|
11518
11639
|
__exportStar(require_project_lifecycle(), exports2);
|
|
11519
11640
|
__exportStar(require_project_jobs(), exports2);
|
|
11520
11641
|
__exportStar(require_plugin_version(), exports2);
|
|
11642
|
+
__exportStar(require_execution(), exports2);
|
|
11643
|
+
__exportStar(require_execution_constants(), exports2);
|
|
11644
|
+
__exportStar(require_plugin_publishing(), exports2);
|
|
11521
11645
|
}
|
|
11522
11646
|
});
|
|
11523
11647
|
|
|
@@ -11845,7 +11969,7 @@ var require_runner = __commonJS({
|
|
|
11845
11969
|
let draining = false;
|
|
11846
11970
|
let ended = false;
|
|
11847
11971
|
let done;
|
|
11848
|
-
const finished = new Promise((
|
|
11972
|
+
const finished = new Promise((resolve7) => done = resolve7);
|
|
11849
11973
|
const drain = async () => {
|
|
11850
11974
|
if (draining)
|
|
11851
11975
|
return;
|
|
@@ -11895,190 +12019,13 @@ var require_runner = __commonJS({
|
|
|
11895
12019
|
}
|
|
11896
12020
|
});
|
|
11897
12021
|
|
|
11898
|
-
// packages/plugin-runtime/dist/plugin.js
|
|
11899
|
-
var require_plugin2 = __commonJS({
|
|
11900
|
-
"packages/plugin-runtime/dist/plugin.js"(exports2) {
|
|
11901
|
-
"use strict";
|
|
11902
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
11903
|
-
exports2.definePlugin = definePlugin;
|
|
11904
|
-
exports2.startPlugin = startPlugin;
|
|
11905
|
-
var schema_1 = require_dist();
|
|
11906
|
-
var define_node_1 = require_define_node();
|
|
11907
|
-
var runner_1 = require_runner();
|
|
11908
|
-
function definePlugin(definition, handlers) {
|
|
11909
|
-
const options = definition;
|
|
11910
|
-
if (!handlers && (!options || !Array.isArray(options.nodes)))
|
|
11911
|
-
throw new Error("plugin needs a nodes array");
|
|
11912
|
-
if (!handlers) {
|
|
11913
|
-
for (const node of options.nodes) {
|
|
11914
|
-
if (typeof node.run !== "function")
|
|
11915
|
-
throw new Error(`plugin node "${node.id}" needs a handler`);
|
|
11916
|
-
if (node.kind && node.kind !== "function")
|
|
11917
|
-
throw new Error("plugin nodes must be functions");
|
|
11918
|
-
}
|
|
11919
|
-
}
|
|
11920
|
-
const manifest2 = schema_1.PluginManifest.parse(handlers ? definition : {
|
|
11921
|
-
...options,
|
|
11922
|
-
nodes: options.nodes.map(({ run: _run, ...node }) => ({
|
|
11923
|
-
...node,
|
|
11924
|
-
command: `node dist/index.js ${node.id}`,
|
|
11925
|
-
language: "typescript"
|
|
11926
|
-
}))
|
|
11927
|
-
});
|
|
11928
|
-
const nodeHandlers = handlers ?? Object.fromEntries(options.nodes.map((node) => [node.id, node.run]));
|
|
11929
|
-
for (const node of manifest2.nodes) {
|
|
11930
|
-
for (const field of ["inputs", "outputs", "defaults"]) {
|
|
11931
|
-
const error = node[field] === void 0 ? void 0 : (0, runner_1.jsonSafetyError)(node[field]);
|
|
11932
|
-
if (error)
|
|
11933
|
-
throw new Error(`plugin node "${node.id}" ${field} must be JSON-serializable: ${error}`);
|
|
11934
|
-
}
|
|
11935
|
-
}
|
|
11936
|
-
for (const id of Object.keys(nodeHandlers)) {
|
|
11937
|
-
if (!manifest2.nodes.some((node) => node.id === id))
|
|
11938
|
-
throw new Error(`handler "${id}" has no plugin node`);
|
|
11939
|
-
}
|
|
11940
|
-
return {
|
|
11941
|
-
manifest: manifest2,
|
|
11942
|
-
...!handlers && options.assets ? { assets: options.assets } : {},
|
|
11943
|
-
nodes: Object.fromEntries(manifest2.nodes.map((node) => {
|
|
11944
|
-
if (!Object.hasOwn(nodeHandlers, node.id))
|
|
11945
|
-
throw new Error(`plugin node "${node.id}" needs a handler`);
|
|
11946
|
-
const fields = (node.connections ?? []).flatMap((id) => Object.entries(manifest2.connections?.[id]?.fields ?? {}));
|
|
11947
|
-
return [
|
|
11948
|
-
node.id,
|
|
11949
|
-
(0, define_node_1.defineNode)({
|
|
11950
|
-
...node,
|
|
11951
|
-
run: (inputs, context) => {
|
|
11952
|
-
const missing = fields.filter(([name, field]) => field.required && !process.env[name]).map(([name]) => name);
|
|
11953
|
-
if (missing.length)
|
|
11954
|
-
throw new runner_1.NodeError(`Missing connection credentials: ${missing.join(", ")}`);
|
|
11955
|
-
return nodeHandlers[node.id](inputs, context);
|
|
11956
|
-
}
|
|
11957
|
-
})
|
|
11958
|
-
];
|
|
11959
|
-
}))
|
|
11960
|
-
};
|
|
11961
|
-
}
|
|
11962
|
-
function startPlugin(plugin, nodeId = process.argv[2]) {
|
|
11963
|
-
const id = nodeId ?? (plugin.manifest.nodes.length === 1 ? plugin.manifest.nodes[0].id : void 0);
|
|
11964
|
-
if (!id || !Object.hasOwn(plugin.nodes, id))
|
|
11965
|
-
throw new Error(`Choose a plugin node: ${Object.keys(plugin.nodes).join(", ")}`);
|
|
11966
|
-
(0, runner_1.start)(plugin.nodes[id]);
|
|
11967
|
-
}
|
|
11968
|
-
}
|
|
11969
|
-
});
|
|
11970
|
-
|
|
11971
|
-
// packages/plugin-runtime/dist/plugin-file.js
|
|
11972
|
-
var require_plugin_file = __commonJS({
|
|
11973
|
-
"packages/plugin-runtime/dist/plugin-file.js"(exports2) {
|
|
11974
|
-
"use strict";
|
|
11975
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
11976
|
-
exports2.pluginDefinitionPath = pluginDefinitionPath;
|
|
11977
|
-
exports2.loadPluginDefinition = loadPluginDefinition3;
|
|
11978
|
-
var node_fs_1 = require("node:fs");
|
|
11979
|
-
var node_path_1 = require("node:path");
|
|
11980
|
-
var yaml_1 = require("yaml");
|
|
11981
|
-
var schema_1 = require_dist();
|
|
11982
|
-
function pluginDefinitionPath(dir) {
|
|
11983
|
-
const files = schema_1.PLUGIN_DEFINITION_FILENAMES.map((name) => (0, node_path_1.join)(dir, name)).filter(node_fs_1.existsSync);
|
|
11984
|
-
if (files.length !== 1)
|
|
11985
|
-
throw new Error(files.length ? `Multiple plugin definitions in ${dir}; keep exactly one` : `No plugin definition in ${dir}; create octonode.yml or octonode.json`);
|
|
11986
|
-
const file = files[0];
|
|
11987
|
-
if ((0, node_path_1.dirname)((0, node_fs_1.realpathSync)(file)) !== (0, node_fs_1.realpathSync)(dir))
|
|
11988
|
-
throw new Error("Plugin definition must stay inside its folder");
|
|
11989
|
-
if (!(0, node_fs_1.statSync)(file).isFile() || (0, node_fs_1.statSync)(file).size > 1048576)
|
|
11990
|
-
throw new Error("Plugin definition must be a file smaller than 1 MiB");
|
|
11991
|
-
return file;
|
|
11992
|
-
}
|
|
11993
|
-
function loadPluginDefinition3(dir) {
|
|
11994
|
-
const file = pluginDefinitionPath(dir);
|
|
11995
|
-
const source = (0, node_fs_1.readFileSync)(file, "utf8");
|
|
11996
|
-
const document = (0, yaml_1.parseDocument)(source, { version: "1.2", uniqueKeys: true });
|
|
11997
|
-
(0, yaml_1.visit)(document, {
|
|
11998
|
-
Alias() {
|
|
11999
|
-
throw new Error("Plugin definitions cannot contain YAML aliases");
|
|
12000
|
-
}
|
|
12001
|
-
});
|
|
12002
|
-
if (document.errors.length || document.warnings.length)
|
|
12003
|
-
throw new Error(`${file}: ${[...document.errors, ...document.warnings].map((error) => error.message).join("; ")}`);
|
|
12004
|
-
const raw = file.endsWith(".json") ? JSON.parse(source) : document.toJS({ maxAliasCount: 0 });
|
|
12005
|
-
if (file.endsWith(schema_1.PLUGIN_MANIFEST_FILENAME))
|
|
12006
|
-
return schema_1.PluginManifest.parse(raw);
|
|
12007
|
-
const settings = schema_1.OctonodeSettingsDocument.parse(raw);
|
|
12008
|
-
if (!settings.plugin)
|
|
12009
|
-
throw new Error(`${file} has no plugin section`);
|
|
12010
|
-
return settings.plugin;
|
|
12011
|
-
}
|
|
12012
|
-
}
|
|
12013
|
-
});
|
|
12014
|
-
|
|
12015
|
-
// packages/plugin-runtime/dist/index.js
|
|
12016
|
-
var require_dist2 = __commonJS({
|
|
12017
|
-
"packages/plugin-runtime/dist/index.js"(exports2) {
|
|
12018
|
-
"use strict";
|
|
12019
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
12020
|
-
exports2.PluginConnection = exports2.PluginNode = exports2.PluginManifest = exports2.pluginDefinitionPath = exports2.loadPluginDefinition = exports2.startPlugin = exports2.definePlugin = exports2.validate = exports2.NodeError = exports2.start = exports2.runNode = exports2.defineConst = exports2.defineClass = exports2.defineService = exports2.defineNode = void 0;
|
|
12021
|
-
var define_node_1 = require_define_node();
|
|
12022
|
-
Object.defineProperty(exports2, "defineNode", { enumerable: true, get: function() {
|
|
12023
|
-
return define_node_1.defineNode;
|
|
12024
|
-
} });
|
|
12025
|
-
Object.defineProperty(exports2, "defineService", { enumerable: true, get: function() {
|
|
12026
|
-
return define_node_1.defineService;
|
|
12027
|
-
} });
|
|
12028
|
-
Object.defineProperty(exports2, "defineClass", { enumerable: true, get: function() {
|
|
12029
|
-
return define_node_1.defineClass;
|
|
12030
|
-
} });
|
|
12031
|
-
Object.defineProperty(exports2, "defineConst", { enumerable: true, get: function() {
|
|
12032
|
-
return define_node_1.defineConst;
|
|
12033
|
-
} });
|
|
12034
|
-
var runner_1 = require_runner();
|
|
12035
|
-
Object.defineProperty(exports2, "runNode", { enumerable: true, get: function() {
|
|
12036
|
-
return runner_1.runNode;
|
|
12037
|
-
} });
|
|
12038
|
-
Object.defineProperty(exports2, "start", { enumerable: true, get: function() {
|
|
12039
|
-
return runner_1.start;
|
|
12040
|
-
} });
|
|
12041
|
-
Object.defineProperty(exports2, "NodeError", { enumerable: true, get: function() {
|
|
12042
|
-
return runner_1.NodeError;
|
|
12043
|
-
} });
|
|
12044
|
-
var json_schema_1 = require_json_schema2();
|
|
12045
|
-
Object.defineProperty(exports2, "validate", { enumerable: true, get: function() {
|
|
12046
|
-
return json_schema_1.validate;
|
|
12047
|
-
} });
|
|
12048
|
-
var plugin_1 = require_plugin2();
|
|
12049
|
-
Object.defineProperty(exports2, "definePlugin", { enumerable: true, get: function() {
|
|
12050
|
-
return plugin_1.definePlugin;
|
|
12051
|
-
} });
|
|
12052
|
-
Object.defineProperty(exports2, "startPlugin", { enumerable: true, get: function() {
|
|
12053
|
-
return plugin_1.startPlugin;
|
|
12054
|
-
} });
|
|
12055
|
-
var plugin_file_1 = require_plugin_file();
|
|
12056
|
-
Object.defineProperty(exports2, "loadPluginDefinition", { enumerable: true, get: function() {
|
|
12057
|
-
return plugin_file_1.loadPluginDefinition;
|
|
12058
|
-
} });
|
|
12059
|
-
Object.defineProperty(exports2, "pluginDefinitionPath", { enumerable: true, get: function() {
|
|
12060
|
-
return plugin_file_1.pluginDefinitionPath;
|
|
12061
|
-
} });
|
|
12062
|
-
var schema_1 = require_dist();
|
|
12063
|
-
Object.defineProperty(exports2, "PluginManifest", { enumerable: true, get: function() {
|
|
12064
|
-
return schema_1.PluginManifest;
|
|
12065
|
-
} });
|
|
12066
|
-
Object.defineProperty(exports2, "PluginNode", { enumerable: true, get: function() {
|
|
12067
|
-
return schema_1.PluginNode;
|
|
12068
|
-
} });
|
|
12069
|
-
Object.defineProperty(exports2, "PluginConnection", { enumerable: true, get: function() {
|
|
12070
|
-
return schema_1.PluginConnection;
|
|
12071
|
-
} });
|
|
12072
|
-
}
|
|
12073
|
-
});
|
|
12074
|
-
|
|
12075
12022
|
// packages/common/dist/constants.js
|
|
12076
12023
|
var require_constants2 = __commonJS({
|
|
12077
12024
|
"packages/common/dist/constants.js"(exports2) {
|
|
12078
12025
|
"use strict";
|
|
12079
12026
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
12080
|
-
exports2.
|
|
12081
|
-
exports2.VISUAL_UPDATE = exports2.VISUAL_STORY = exports2.VISUAL_REVIEW_DIR = exports2.VISUAL_FULL = exports2.VISUAL_BASE = exports2.USERNAME = exports2.USER = void 0;
|
|
12027
|
+
exports2.PYTHONPATH = exports2.PORT = exports2.PATH = exports2.OPENROUTER_API_KEY = exports2.CLOUDFLARE_ACCOUNT_ID = exports2.CLOUDFLARE_API_KEY = exports2.OPENAI_API_KEY = exports2.OTEL_SERVICE_NAME = exports2.OTEL_SDK_DISABLED = exports2.OTEL_EXPORTER_OTLP_ENDPOINT = exports2.OCTONODE_WORKSPACE = exports2.OCTONODE_VISUAL_PORT = exports2.OCTONODE_USER_EMAIL = exports2.OCTONODE_USER = exports2.OCTONODE_STUDIO_URL = exports2.OCTONODE_STORE_DIR = exports2.OCTONODE_SOURCE_WATCH_CONCURRENCY = exports2.OCTONODE_SHUTDOWN_TIMEOUT_MS = exports2.OCTONODE_SERVER_PROFILE = exports2.OCTONODE_RUNTIME = exports2.OCTONODE_REPOSITORY_REGISTRY_V2 = exports2.OCTONODE_RUN_RETENTION_COUNT = exports2.OCTONODE_RUN_RETENTION_BYTES = exports2.OCTONODE_RUN_RETENTION_AGE_MS = exports2.OCTONODE_STATE_NAMESPACE = exports2.OCTONODE_RUN_QUEUE = exports2.OCTONODE_RUN_CONCURRENCY = exports2.DEFAULT_MARKETPLACE_URL = exports2.OCTONODE_MARKETPLACE_URL = exports2.OCTONODE_MARKETPLACE_TOKEN = exports2.OCTONODE_PACKAGE_CACHE = exports2.OCTONODE_PROJECT = exports2.OCTONODE_CWD = exports2.OCTONODE_COMMUNITY_ROLLOUT = exports2.OCTONODE_CHAT_SERVICE_URL = exports2.OCTONODE_CHAT_SERVICE_TOKEN = exports2.OCTONODE_CHAT_SERVICE_AVAILABLE = exports2.OCTONODE_CHAT_MODEL = exports2.OCTONODE_CLOUD_INTERNAL_TOKEN = exports2.OCTONODE_CORS_ORIGINS = exports2.OCTONODE_API_TOKEN = exports2.OCTONODE_API_URL = exports2.OCTONODE_AUTH_TOKEN = exports2.OCTONODE_AUTH_PRINCIPAL = exports2.HOST = exports2.CONFIG_PATH = exports2.setEnvironmentVariable = exports2.childProcessEnvironment = exports2.workflowEnvironment = exports2.PROCESS_ENV = void 0;
|
|
12028
|
+
exports2.VISUAL_UPDATE = exports2.VISUAL_STORY = exports2.VISUAL_REVIEW_DIR = exports2.VISUAL_FULL = exports2.VISUAL_BASE = exports2.USERNAME = exports2.USER = exports2.UI_DIR = void 0;
|
|
12082
12029
|
exports2.PROCESS_ENV = typeof process === "undefined" ? {} : process.env;
|
|
12083
12030
|
var workflowEnvironment = (variables = {}) => {
|
|
12084
12031
|
const environment = Object.fromEntries(Object.entries(variables).filter((entry) => typeof entry[1] === "string"));
|
|
@@ -12089,8 +12036,8 @@ var require_constants2 = __commonJS({
|
|
|
12089
12036
|
return environment;
|
|
12090
12037
|
};
|
|
12091
12038
|
exports2.workflowEnvironment = workflowEnvironment;
|
|
12092
|
-
var
|
|
12093
|
-
exports2.childProcessEnvironment =
|
|
12039
|
+
var childProcessEnvironment4 = (overrides = {}) => (0, exports2.workflowEnvironment)({ ...exports2.PROCESS_ENV, ...overrides });
|
|
12040
|
+
exports2.childProcessEnvironment = childProcessEnvironment4;
|
|
12094
12041
|
var setEnvironmentVariable = (name, value) => {
|
|
12095
12042
|
if (value === void 0)
|
|
12096
12043
|
delete exports2.PROCESS_ENV[name];
|
|
@@ -12132,8 +12079,9 @@ var require_constants2 = __commonJS({
|
|
|
12132
12079
|
exports2.OCTONODE_PACKAGE_CACHE = OCTONODE_PACKAGE_CACHE2;
|
|
12133
12080
|
var OCTONODE_MARKETPLACE_TOKEN2 = () => exports2.PROCESS_ENV.OCTONODE_MARKETPLACE_TOKEN ?? exports2.PROCESS_ENV.VITE_OCTONODE_MARKETPLACE_TOKEN ?? exports2.PROCESS_ENV.VITE_PUBLIC_OCTONODE_MARKETPLACE_TOKEN;
|
|
12134
12081
|
exports2.OCTONODE_MARKETPLACE_TOKEN = OCTONODE_MARKETPLACE_TOKEN2;
|
|
12135
|
-
var
|
|
12136
|
-
exports2.OCTONODE_MARKETPLACE_URL =
|
|
12082
|
+
var OCTONODE_MARKETPLACE_URL3 = () => exports2.PROCESS_ENV.OCTONODE_MARKETPLACE_URL ?? exports2.PROCESS_ENV.VITE_OCTONODE_MARKETPLACE_URL ?? exports2.PROCESS_ENV.VITE_PUBLIC_OCTONODE_MARKETPLACE_URL;
|
|
12083
|
+
exports2.OCTONODE_MARKETPLACE_URL = OCTONODE_MARKETPLACE_URL3;
|
|
12084
|
+
exports2.DEFAULT_MARKETPLACE_URL = "https://plugins.octonodes.com";
|
|
12137
12085
|
var OCTONODE_RUN_CONCURRENCY = () => exports2.PROCESS_ENV.OCTONODE_RUN_CONCURRENCY;
|
|
12138
12086
|
exports2.OCTONODE_RUN_CONCURRENCY = OCTONODE_RUN_CONCURRENCY;
|
|
12139
12087
|
var OCTONODE_RUN_QUEUE = () => exports2.PROCESS_ENV.OCTONODE_RUN_QUEUE;
|
|
@@ -12391,38 +12339,248 @@ var require_graph_layout = __commonJS({
|
|
|
12391
12339
|
}
|
|
12392
12340
|
});
|
|
12393
12341
|
|
|
12394
|
-
// packages/common/dist/
|
|
12342
|
+
// packages/common/dist/plugin-nodes.js
|
|
12343
|
+
var require_plugin_nodes = __commonJS({
|
|
12344
|
+
"packages/common/dist/plugin-nodes.js"(exports2) {
|
|
12345
|
+
"use strict";
|
|
12346
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
12347
|
+
exports2.installedPluginNodesPage = installedPluginNodesPage;
|
|
12348
|
+
function isCatalogPlugin(value) {
|
|
12349
|
+
if (!value || typeof value !== "object")
|
|
12350
|
+
return false;
|
|
12351
|
+
const plugin = value;
|
|
12352
|
+
return typeof plugin.id === "string" && typeof plugin.name === "string" && typeof plugin.version === "string" && Array.isArray(plugin.nodes) && plugin.nodes.every((node) => {
|
|
12353
|
+
if (!node || typeof node !== "object")
|
|
12354
|
+
return false;
|
|
12355
|
+
const item = node;
|
|
12356
|
+
return typeof item.id === "string" && (item.icon === void 0 || typeof item.icon === "string") && (item.description === void 0 || typeof item.description === "string");
|
|
12357
|
+
});
|
|
12358
|
+
}
|
|
12359
|
+
function installedPluginNodesPage(inventory, query) {
|
|
12360
|
+
if (!inventory.every(isCatalogPlugin))
|
|
12361
|
+
throw new Error("Plugin node inventory is incomplete");
|
|
12362
|
+
const q = query.q?.trim().toLowerCase();
|
|
12363
|
+
const nodes = inventory.flatMap((plugin) => plugin.nodes.filter((node) => !q || [node.id, node.description ?? "", plugin.id, plugin.name].join(" ").toLowerCase().includes(q)).map((node) => ({ ...node, pluginId: plugin.id, pluginName: plugin.name, pluginVersion: plugin.version }))).sort((a, b) => a.pluginName.localeCompare(b.pluginName) || a.id.localeCompare(b.id));
|
|
12364
|
+
const offset = Math.min(query.offset, nodes.length);
|
|
12365
|
+
return { items: nodes.slice(offset, offset + query.limit), total: nodes.length, offset, limit: query.limit };
|
|
12366
|
+
}
|
|
12367
|
+
}
|
|
12368
|
+
});
|
|
12369
|
+
|
|
12370
|
+
// packages/common/dist/index.js
|
|
12371
|
+
var require_dist2 = __commonJS({
|
|
12372
|
+
"packages/common/dist/index.js"(exports2) {
|
|
12373
|
+
"use strict";
|
|
12374
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
12375
|
+
if (k2 === void 0) k2 = k;
|
|
12376
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12377
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12378
|
+
desc = { enumerable: true, get: function() {
|
|
12379
|
+
return m[k];
|
|
12380
|
+
} };
|
|
12381
|
+
}
|
|
12382
|
+
Object.defineProperty(o, k2, desc);
|
|
12383
|
+
}) : (function(o, m, k, k2) {
|
|
12384
|
+
if (k2 === void 0) k2 = k;
|
|
12385
|
+
o[k2] = m[k];
|
|
12386
|
+
}));
|
|
12387
|
+
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
12388
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
|
|
12389
|
+
};
|
|
12390
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
12391
|
+
exports2.installedPluginNodesPage = exports2.layeredLayout = exports2.packageCacheEnvironment = void 0;
|
|
12392
|
+
__exportStar(require_constants2(), exports2);
|
|
12393
|
+
__exportStar(require_legal_constants(), exports2);
|
|
12394
|
+
var package_cache_1 = require_package_cache();
|
|
12395
|
+
Object.defineProperty(exports2, "packageCacheEnvironment", { enumerable: true, get: function() {
|
|
12396
|
+
return package_cache_1.packageCacheEnvironment;
|
|
12397
|
+
} });
|
|
12398
|
+
__exportStar(require_api_exposure(), exports2);
|
|
12399
|
+
var graph_layout_1 = require_graph_layout();
|
|
12400
|
+
Object.defineProperty(exports2, "layeredLayout", { enumerable: true, get: function() {
|
|
12401
|
+
return graph_layout_1.layeredLayout;
|
|
12402
|
+
} });
|
|
12403
|
+
var plugin_nodes_1 = require_plugin_nodes();
|
|
12404
|
+
Object.defineProperty(exports2, "installedPluginNodesPage", { enumerable: true, get: function() {
|
|
12405
|
+
return plugin_nodes_1.installedPluginNodesPage;
|
|
12406
|
+
} });
|
|
12407
|
+
}
|
|
12408
|
+
});
|
|
12409
|
+
|
|
12410
|
+
// packages/plugin-runtime/dist/plugin.js
|
|
12411
|
+
var require_plugin2 = __commonJS({
|
|
12412
|
+
"packages/plugin-runtime/dist/plugin.js"(exports2) {
|
|
12413
|
+
"use strict";
|
|
12414
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
12415
|
+
exports2.definePlugin = definePlugin;
|
|
12416
|
+
exports2.startPlugin = startPlugin;
|
|
12417
|
+
var common_1 = require_dist2();
|
|
12418
|
+
var schema_1 = require_dist();
|
|
12419
|
+
var define_node_1 = require_define_node();
|
|
12420
|
+
var runner_1 = require_runner();
|
|
12421
|
+
function definePlugin(definition, handlers) {
|
|
12422
|
+
const options = definition;
|
|
12423
|
+
if (!handlers && (!options || !Array.isArray(options.nodes)))
|
|
12424
|
+
throw new Error("plugin needs a nodes array");
|
|
12425
|
+
if (!handlers) {
|
|
12426
|
+
for (const node of options.nodes) {
|
|
12427
|
+
if (typeof node.run !== "function")
|
|
12428
|
+
throw new Error(`plugin node "${node.id}" needs a handler`);
|
|
12429
|
+
if (node.kind && node.kind !== "function")
|
|
12430
|
+
throw new Error("plugin nodes must be functions");
|
|
12431
|
+
}
|
|
12432
|
+
}
|
|
12433
|
+
const manifest2 = schema_1.PluginManifest.parse(handlers ? definition : {
|
|
12434
|
+
...options,
|
|
12435
|
+
nodes: options.nodes.map(({ run: _run, ...node }) => ({
|
|
12436
|
+
...node,
|
|
12437
|
+
command: `node dist/index.js ${node.id}`,
|
|
12438
|
+
language: "typescript"
|
|
12439
|
+
}))
|
|
12440
|
+
});
|
|
12441
|
+
const nodeHandlers = handlers ?? Object.fromEntries(options.nodes.map((node) => [node.id, node.run]));
|
|
12442
|
+
for (const node of manifest2.nodes) {
|
|
12443
|
+
for (const field of ["inputs", "outputs", "defaults"]) {
|
|
12444
|
+
const error = node[field] === void 0 ? void 0 : (0, runner_1.jsonSafetyError)(node[field]);
|
|
12445
|
+
if (error)
|
|
12446
|
+
throw new Error(`plugin node "${node.id}" ${field} must be JSON-serializable: ${error}`);
|
|
12447
|
+
}
|
|
12448
|
+
}
|
|
12449
|
+
for (const id of Object.keys(nodeHandlers)) {
|
|
12450
|
+
if (!manifest2.nodes.some((node) => node.id === id))
|
|
12451
|
+
throw new Error(`handler "${id}" has no plugin node`);
|
|
12452
|
+
}
|
|
12453
|
+
return {
|
|
12454
|
+
manifest: manifest2,
|
|
12455
|
+
...!handlers && options.assets ? { assets: options.assets } : {},
|
|
12456
|
+
nodes: Object.fromEntries(manifest2.nodes.map((node) => {
|
|
12457
|
+
if (!Object.hasOwn(nodeHandlers, node.id))
|
|
12458
|
+
throw new Error(`plugin node "${node.id}" needs a handler`);
|
|
12459
|
+
const fields = (node.connections ?? []).flatMap((id) => Object.entries(manifest2.connections?.[id]?.fields ?? {}));
|
|
12460
|
+
return [
|
|
12461
|
+
node.id,
|
|
12462
|
+
(0, define_node_1.defineNode)({
|
|
12463
|
+
...node,
|
|
12464
|
+
run: (inputs, context) => {
|
|
12465
|
+
const missing = fields.filter(([name, field]) => field.required && !common_1.PROCESS_ENV[name]).map(([name]) => name);
|
|
12466
|
+
if (missing.length)
|
|
12467
|
+
throw new runner_1.NodeError(`Missing connection credentials: ${missing.join(", ")}`);
|
|
12468
|
+
return nodeHandlers[node.id](inputs, context);
|
|
12469
|
+
}
|
|
12470
|
+
})
|
|
12471
|
+
];
|
|
12472
|
+
}))
|
|
12473
|
+
};
|
|
12474
|
+
}
|
|
12475
|
+
function startPlugin(plugin, nodeId = process.argv[2]) {
|
|
12476
|
+
const id = nodeId ?? (plugin.manifest.nodes.length === 1 ? plugin.manifest.nodes[0].id : void 0);
|
|
12477
|
+
if (!id || !Object.hasOwn(plugin.nodes, id))
|
|
12478
|
+
throw new Error(`Choose a plugin node: ${Object.keys(plugin.nodes).join(", ")}`);
|
|
12479
|
+
(0, runner_1.start)(plugin.nodes[id]);
|
|
12480
|
+
}
|
|
12481
|
+
}
|
|
12482
|
+
});
|
|
12483
|
+
|
|
12484
|
+
// packages/plugin-runtime/dist/plugin-file.js
|
|
12485
|
+
var require_plugin_file = __commonJS({
|
|
12486
|
+
"packages/plugin-runtime/dist/plugin-file.js"(exports2) {
|
|
12487
|
+
"use strict";
|
|
12488
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
12489
|
+
exports2.pluginDefinitionPath = pluginDefinitionPath2;
|
|
12490
|
+
exports2.loadPluginDefinition = loadPluginDefinition3;
|
|
12491
|
+
var node_fs_1 = require("node:fs");
|
|
12492
|
+
var node_path_1 = require("node:path");
|
|
12493
|
+
var yaml_1 = require("yaml");
|
|
12494
|
+
var schema_1 = require_dist();
|
|
12495
|
+
function pluginDefinitionPath2(dir) {
|
|
12496
|
+
const files = schema_1.PLUGIN_DEFINITION_FILENAMES.map((name) => (0, node_path_1.join)(dir, name)).filter(node_fs_1.existsSync);
|
|
12497
|
+
if (files.length !== 1)
|
|
12498
|
+
throw new Error(files.length ? `Multiple plugin definitions in ${dir}; keep exactly one` : `No plugin definition in ${dir}; create octonode.yml or octonode.json`);
|
|
12499
|
+
const file = files[0];
|
|
12500
|
+
if ((0, node_path_1.dirname)((0, node_fs_1.realpathSync)(file)) !== (0, node_fs_1.realpathSync)(dir))
|
|
12501
|
+
throw new Error("Plugin definition must stay inside its folder");
|
|
12502
|
+
if (!(0, node_fs_1.statSync)(file).isFile() || (0, node_fs_1.statSync)(file).size > 1048576)
|
|
12503
|
+
throw new Error("Plugin definition must be a file smaller than 1 MiB");
|
|
12504
|
+
return file;
|
|
12505
|
+
}
|
|
12506
|
+
function loadPluginDefinition3(dir) {
|
|
12507
|
+
const file = pluginDefinitionPath2(dir);
|
|
12508
|
+
const source = (0, node_fs_1.readFileSync)(file, "utf8");
|
|
12509
|
+
const document = (0, yaml_1.parseDocument)(source, { version: "1.2", uniqueKeys: true });
|
|
12510
|
+
(0, yaml_1.visit)(document, {
|
|
12511
|
+
Alias() {
|
|
12512
|
+
throw new Error("Plugin definitions cannot contain YAML aliases");
|
|
12513
|
+
}
|
|
12514
|
+
});
|
|
12515
|
+
if (document.errors.length || document.warnings.length)
|
|
12516
|
+
throw new Error(`${file}: ${[...document.errors, ...document.warnings].map((error) => error.message).join("; ")}`);
|
|
12517
|
+
const raw = file.endsWith(".json") ? JSON.parse(source) : document.toJS({ maxAliasCount: 0 });
|
|
12518
|
+
if (file.endsWith(schema_1.PLUGIN_MANIFEST_FILENAME))
|
|
12519
|
+
return schema_1.PluginManifest.parse(raw);
|
|
12520
|
+
const settings = schema_1.OctonodeSettingsDocument.parse(raw);
|
|
12521
|
+
if (!settings.plugin)
|
|
12522
|
+
throw new Error(`${file} has no plugin section`);
|
|
12523
|
+
return settings.plugin;
|
|
12524
|
+
}
|
|
12525
|
+
}
|
|
12526
|
+
});
|
|
12527
|
+
|
|
12528
|
+
// packages/plugin-runtime/dist/index.js
|
|
12395
12529
|
var require_dist3 = __commonJS({
|
|
12396
|
-
"packages/
|
|
12530
|
+
"packages/plugin-runtime/dist/index.js"(exports2) {
|
|
12397
12531
|
"use strict";
|
|
12398
|
-
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
12399
|
-
if (k2 === void 0) k2 = k;
|
|
12400
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12401
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12402
|
-
desc = { enumerable: true, get: function() {
|
|
12403
|
-
return m[k];
|
|
12404
|
-
} };
|
|
12405
|
-
}
|
|
12406
|
-
Object.defineProperty(o, k2, desc);
|
|
12407
|
-
}) : (function(o, m, k, k2) {
|
|
12408
|
-
if (k2 === void 0) k2 = k;
|
|
12409
|
-
o[k2] = m[k];
|
|
12410
|
-
}));
|
|
12411
|
-
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
12412
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
|
|
12413
|
-
};
|
|
12414
12532
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
12415
|
-
exports2.
|
|
12416
|
-
|
|
12417
|
-
|
|
12418
|
-
|
|
12419
|
-
Object.defineProperty(exports2, "packageCacheEnvironment", { enumerable: true, get: function() {
|
|
12420
|
-
return package_cache_1.packageCacheEnvironment;
|
|
12533
|
+
exports2.PluginConnection = exports2.PluginNode = exports2.PluginManifest = exports2.pluginDefinitionPath = exports2.loadPluginDefinition = exports2.startPlugin = exports2.definePlugin = exports2.validate = exports2.NodeError = exports2.start = exports2.runNode = exports2.defineConst = exports2.defineClass = exports2.defineService = exports2.defineNode = void 0;
|
|
12534
|
+
var define_node_1 = require_define_node();
|
|
12535
|
+
Object.defineProperty(exports2, "defineNode", { enumerable: true, get: function() {
|
|
12536
|
+
return define_node_1.defineNode;
|
|
12421
12537
|
} });
|
|
12422
|
-
|
|
12423
|
-
|
|
12424
|
-
|
|
12425
|
-
|
|
12538
|
+
Object.defineProperty(exports2, "defineService", { enumerable: true, get: function() {
|
|
12539
|
+
return define_node_1.defineService;
|
|
12540
|
+
} });
|
|
12541
|
+
Object.defineProperty(exports2, "defineClass", { enumerable: true, get: function() {
|
|
12542
|
+
return define_node_1.defineClass;
|
|
12543
|
+
} });
|
|
12544
|
+
Object.defineProperty(exports2, "defineConst", { enumerable: true, get: function() {
|
|
12545
|
+
return define_node_1.defineConst;
|
|
12546
|
+
} });
|
|
12547
|
+
var runner_1 = require_runner();
|
|
12548
|
+
Object.defineProperty(exports2, "runNode", { enumerable: true, get: function() {
|
|
12549
|
+
return runner_1.runNode;
|
|
12550
|
+
} });
|
|
12551
|
+
Object.defineProperty(exports2, "start", { enumerable: true, get: function() {
|
|
12552
|
+
return runner_1.start;
|
|
12553
|
+
} });
|
|
12554
|
+
Object.defineProperty(exports2, "NodeError", { enumerable: true, get: function() {
|
|
12555
|
+
return runner_1.NodeError;
|
|
12556
|
+
} });
|
|
12557
|
+
var json_schema_1 = require_json_schema2();
|
|
12558
|
+
Object.defineProperty(exports2, "validate", { enumerable: true, get: function() {
|
|
12559
|
+
return json_schema_1.validate;
|
|
12560
|
+
} });
|
|
12561
|
+
var plugin_1 = require_plugin2();
|
|
12562
|
+
Object.defineProperty(exports2, "definePlugin", { enumerable: true, get: function() {
|
|
12563
|
+
return plugin_1.definePlugin;
|
|
12564
|
+
} });
|
|
12565
|
+
Object.defineProperty(exports2, "startPlugin", { enumerable: true, get: function() {
|
|
12566
|
+
return plugin_1.startPlugin;
|
|
12567
|
+
} });
|
|
12568
|
+
var plugin_file_1 = require_plugin_file();
|
|
12569
|
+
Object.defineProperty(exports2, "loadPluginDefinition", { enumerable: true, get: function() {
|
|
12570
|
+
return plugin_file_1.loadPluginDefinition;
|
|
12571
|
+
} });
|
|
12572
|
+
Object.defineProperty(exports2, "pluginDefinitionPath", { enumerable: true, get: function() {
|
|
12573
|
+
return plugin_file_1.pluginDefinitionPath;
|
|
12574
|
+
} });
|
|
12575
|
+
var schema_1 = require_dist();
|
|
12576
|
+
Object.defineProperty(exports2, "PluginManifest", { enumerable: true, get: function() {
|
|
12577
|
+
return schema_1.PluginManifest;
|
|
12578
|
+
} });
|
|
12579
|
+
Object.defineProperty(exports2, "PluginNode", { enumerable: true, get: function() {
|
|
12580
|
+
return schema_1.PluginNode;
|
|
12581
|
+
} });
|
|
12582
|
+
Object.defineProperty(exports2, "PluginConnection", { enumerable: true, get: function() {
|
|
12583
|
+
return schema_1.PluginConnection;
|
|
12426
12584
|
} });
|
|
12427
12585
|
}
|
|
12428
12586
|
});
|
|
@@ -12435,18 +12593,18 @@ __export(index_exports, {
|
|
|
12435
12593
|
module.exports = __toCommonJS(index_exports);
|
|
12436
12594
|
|
|
12437
12595
|
// packages/plugin/src/consumer/lifecycle.ts
|
|
12438
|
-
var
|
|
12439
|
-
var
|
|
12596
|
+
var import_node_fs15 = require("node:fs");
|
|
12597
|
+
var import_node_path15 = require("node:path");
|
|
12440
12598
|
|
|
12441
12599
|
// packages/plugin/src/lifecycle.ts
|
|
12442
|
-
var
|
|
12443
|
-
var
|
|
12600
|
+
var import_node_fs10 = require("node:fs");
|
|
12601
|
+
var import_node_path10 = require("node:path");
|
|
12444
12602
|
|
|
12445
12603
|
// packages/plugin/src/store.ts
|
|
12446
12604
|
var import_node_fs2 = require("node:fs");
|
|
12447
12605
|
var import_node_os = require("node:os");
|
|
12448
12606
|
var import_node_path2 = require("node:path");
|
|
12449
|
-
var import_plugin_runtime = __toESM(
|
|
12607
|
+
var import_plugin_runtime = __toESM(require_dist3());
|
|
12450
12608
|
|
|
12451
12609
|
// packages/plugin/src/integrity.ts
|
|
12452
12610
|
var import_node_crypto = require("node:crypto");
|
|
@@ -12538,7 +12696,7 @@ function addToStore(srcDir, opts = {}) {
|
|
|
12538
12696
|
var import_node_fs4 = require("node:fs");
|
|
12539
12697
|
var import_node_os2 = require("node:os");
|
|
12540
12698
|
var import_node_path4 = require("node:path");
|
|
12541
|
-
var import_plugin_runtime2 = __toESM(
|
|
12699
|
+
var import_plugin_runtime2 = __toESM(require_dist3());
|
|
12542
12700
|
var import_schema2 = __toESM(require_dist());
|
|
12543
12701
|
|
|
12544
12702
|
// packages/plugin/src/lock.ts
|
|
@@ -12551,6 +12709,8 @@ var LockEntry = import_zod.z.object({
|
|
|
12551
12709
|
version: import_zod.z.string(),
|
|
12552
12710
|
/** `sha256:<hex>` dir-content hash (hashPluginDir) — the store address + integrity check. */
|
|
12553
12711
|
sha256: import_zod.z.string(),
|
|
12712
|
+
/** Registry archive checksum, distinct from the unpacked file-tree identity. */
|
|
12713
|
+
archiveSha256: import_zod.z.string().regex(/^[a-f0-9]{64}$/).optional(),
|
|
12554
12714
|
/** Marketplace base URL the bundle came from (absent for local installs). */
|
|
12555
12715
|
registry: import_zod.z.string().optional(),
|
|
12556
12716
|
/** Marketplace tier it was resolved from. */
|
|
@@ -12625,12 +12785,12 @@ function isPluginDir(dir) {
|
|
|
12625
12785
|
|
|
12626
12786
|
// packages/plugin/src/dependencies.ts
|
|
12627
12787
|
var import_node_child_process = require("node:child_process");
|
|
12628
|
-
var
|
|
12629
|
-
var
|
|
12630
|
-
var
|
|
12788
|
+
var import_node_fs6 = require("node:fs");
|
|
12789
|
+
var import_node_os4 = require("node:os");
|
|
12790
|
+
var import_node_path6 = require("node:path");
|
|
12631
12791
|
var import_node_util = require("node:util");
|
|
12632
12792
|
var import_yaml = require("yaml");
|
|
12633
|
-
var import_common = __toESM(
|
|
12793
|
+
var import_common = __toESM(require_dist2());
|
|
12634
12794
|
|
|
12635
12795
|
// packages/plugin/src/dependencies.constants.ts
|
|
12636
12796
|
var DEFAULT_PACKAGE_MANAGER = "pnpm@12.3.4";
|
|
@@ -12644,43 +12804,291 @@ var PACKAGE_MANAGER_LOCKS = {
|
|
|
12644
12804
|
bun: ["bun.lock", "bun.lockb"]
|
|
12645
12805
|
};
|
|
12646
12806
|
|
|
12807
|
+
// packages/plugin/src/dependency/snapshot.ts
|
|
12808
|
+
var import_node_crypto2 = require("node:crypto");
|
|
12809
|
+
var import_node_fs5 = require("node:fs");
|
|
12810
|
+
var import_node_path5 = require("node:path");
|
|
12811
|
+
var import_node_os3 = require("node:os");
|
|
12812
|
+
var import_zod2 = require("zod");
|
|
12813
|
+
|
|
12814
|
+
// packages/plugin/src/dependency/snapshot.constants.ts
|
|
12815
|
+
var DEPENDENCY_SNAPSHOT_FORMAT = 1;
|
|
12816
|
+
var DEPENDENCY_SNAPSHOT_MAX_BYTES = 256 * 1024 * 1024;
|
|
12817
|
+
var DEPENDENCY_SNAPSHOT_MAX_FILES = 5e4;
|
|
12818
|
+
var DEPENDENCY_SNAPSHOT_OUTPUTS = [
|
|
12819
|
+
"node_modules",
|
|
12820
|
+
".pnp.cjs",
|
|
12821
|
+
".pnp.loader.mjs",
|
|
12822
|
+
".pnp.data.json",
|
|
12823
|
+
".yarn/cache",
|
|
12824
|
+
".yarn/unplugged",
|
|
12825
|
+
".yarn/install-state.gz"
|
|
12826
|
+
];
|
|
12827
|
+
|
|
12828
|
+
// packages/plugin/src/dependency/snapshot.ts
|
|
12829
|
+
function inside(root, path) {
|
|
12830
|
+
const local = (0, import_node_path5.relative)(root, path);
|
|
12831
|
+
return local === "" || !(0, import_node_path5.isAbsolute)(local) && local !== ".." && !local.startsWith(`..${import_node_path5.sep}`);
|
|
12832
|
+
}
|
|
12833
|
+
function digestTree(root, paths, projectRoot) {
|
|
12834
|
+
const hash = (0, import_node_crypto2.createHash)("sha256");
|
|
12835
|
+
let bytes = 0;
|
|
12836
|
+
let count = 0;
|
|
12837
|
+
const visit2 = (path) => {
|
|
12838
|
+
if (++count > DEPENDENCY_SNAPSHOT_MAX_FILES) throw new Error("Dependency snapshot file limit");
|
|
12839
|
+
const file = (0, import_node_path5.join)(root, path);
|
|
12840
|
+
for (let parent = (0, import_node_path5.dirname)(file); inside(root, parent); parent = (0, import_node_path5.dirname)(parent)) {
|
|
12841
|
+
if ((0, import_node_fs5.lstatSync)(parent).isSymbolicLink()) throw new Error("Dependency snapshot ancestor is a link");
|
|
12842
|
+
if (parent === root) break;
|
|
12843
|
+
}
|
|
12844
|
+
const stat = (0, import_node_fs5.lstatSync)(file);
|
|
12845
|
+
hash.update(
|
|
12846
|
+
JSON.stringify([
|
|
12847
|
+
path,
|
|
12848
|
+
stat.mode & 511,
|
|
12849
|
+
stat.isDirectory() ? "directory" : stat.isSymbolicLink() ? "link" : "file"
|
|
12850
|
+
])
|
|
12851
|
+
);
|
|
12852
|
+
if (stat.isSymbolicLink()) {
|
|
12853
|
+
const link = (0, import_node_fs5.readlinkSync)(file);
|
|
12854
|
+
if (!inside(projectRoot, (0, import_node_path5.resolve)((0, import_node_path5.dirname)((0, import_node_path5.join)(projectRoot, path)), link)))
|
|
12855
|
+
throw new Error("Dependency snapshot link leaves project");
|
|
12856
|
+
hash.update(JSON.stringify(link));
|
|
12857
|
+
} else if (stat.isDirectory()) {
|
|
12858
|
+
for (const name of (0, import_node_fs5.readdirSync)(file).sort()) visit2((0, import_node_path5.join)(path, name));
|
|
12859
|
+
} else if (stat.isFile()) {
|
|
12860
|
+
bytes += stat.size;
|
|
12861
|
+
if (bytes > DEPENDENCY_SNAPSHOT_MAX_BYTES) throw new Error("Dependency snapshot size limit");
|
|
12862
|
+
hash.update(String(stat.size)).update("\0").update((0, import_node_fs5.readFileSync)(file));
|
|
12863
|
+
} else throw new Error("Unsupported dependency snapshot file");
|
|
12864
|
+
};
|
|
12865
|
+
for (const path of [...paths].sort()) visit2(path);
|
|
12866
|
+
return hash.digest("hex");
|
|
12867
|
+
}
|
|
12868
|
+
function dependencySnapshot(project, cacheRoot, managerVersion, environment) {
|
|
12869
|
+
try {
|
|
12870
|
+
if (inside(cacheRoot, project.root)) return;
|
|
12871
|
+
if (!PACKAGE_MANAGER_LOCKS[project.manager].some((name) => (0, import_node_fs5.existsSync)((0, import_node_path5.join)(project.root, name)))) return;
|
|
12872
|
+
const outputs = new Set(DEPENDENCY_SNAPSHOT_OUTPUTS);
|
|
12873
|
+
let inputCount = 0;
|
|
12874
|
+
if (/--(?:require|import|loader|experimental-loader)(?:[=\s]|$)/.test(environment.NODE_OPTIONS ?? "")) return;
|
|
12875
|
+
const walk = (directory) => (0, import_node_fs5.readdirSync)(directory).sort().flatMap((name) => {
|
|
12876
|
+
const file = (0, import_node_path5.join)(directory, name);
|
|
12877
|
+
const local = (0, import_node_path5.relative)(project.root, file);
|
|
12878
|
+
if (inside(cacheRoot, file) || outputs.has(local) || name === "node_modules" || name === ".git" || name === ".octonode" || name === DEPENDENCY_MUTEX || name.startsWith(".octonode-recovery-"))
|
|
12879
|
+
return [];
|
|
12880
|
+
if (++inputCount > DEPENDENCY_SNAPSHOT_MAX_FILES) throw new Error("Dependency input file limit");
|
|
12881
|
+
const stat = (0, import_node_fs5.lstatSync)(file);
|
|
12882
|
+
if (stat.isSymbolicLink()) throw new Error("Linked source is not snapshot eligible");
|
|
12883
|
+
if (/^\.?pnpmfile\.[cm]?js$/.test(name))
|
|
12884
|
+
throw new Error("Dynamic package-manager hooks require installation");
|
|
12885
|
+
if (name === ".yarnrc.yml" && /^(?:plugins|yarnPath):/m.test((0, import_node_fs5.readFileSync)(file, "utf8")))
|
|
12886
|
+
throw new Error("Custom Yarn code requires installation");
|
|
12887
|
+
if (stat.isDirectory()) return walk(file);
|
|
12888
|
+
else {
|
|
12889
|
+
if (name === "package.json") {
|
|
12890
|
+
const manifest2 = JSON.parse((0, import_node_fs5.readFileSync)(file, "utf8"));
|
|
12891
|
+
for (const dependencies of [
|
|
12892
|
+
manifest2.dependencies,
|
|
12893
|
+
manifest2.devDependencies,
|
|
12894
|
+
manifest2.optionalDependencies
|
|
12895
|
+
]) {
|
|
12896
|
+
for (const spec of Object.values(dependencies ?? {})) {
|
|
12897
|
+
if (typeof spec !== "string") throw new Error("Invalid dependency");
|
|
12898
|
+
const localSpec = /^(?:file:|link:|portal:)(.*)$/.exec(spec);
|
|
12899
|
+
if (localSpec) {
|
|
12900
|
+
const target = (0, import_node_path5.resolve)(directory, localSpec[1]);
|
|
12901
|
+
if (!inside(project.root, target) || inside(cacheRoot, target) || (0, import_node_path5.relative)(project.root, target).split(import_node_path5.sep).some((part) => ["node_modules", ".git", ".octonode"].includes(part)))
|
|
12902
|
+
throw new Error("External or excluded dependency is not snapshot eligible");
|
|
12903
|
+
}
|
|
12904
|
+
}
|
|
12905
|
+
}
|
|
12906
|
+
outputs.add((0, import_node_path5.relative)(project.root, (0, import_node_path5.join)(directory, "node_modules")));
|
|
12907
|
+
}
|
|
12908
|
+
return [local];
|
|
12909
|
+
}
|
|
12910
|
+
});
|
|
12911
|
+
const inputs = walk(project.root);
|
|
12912
|
+
const inputHash = digestTree(project.root, inputs, project.root);
|
|
12913
|
+
const userRoot = environment.HOME ?? (0, import_node_os3.homedir)();
|
|
12914
|
+
const configuration = new Set(
|
|
12915
|
+
[
|
|
12916
|
+
(0, import_node_path5.join)(userRoot, ".npmrc"),
|
|
12917
|
+
(0, import_node_path5.join)(userRoot, ".yarnrc"),
|
|
12918
|
+
(0, import_node_path5.join)(userRoot, ".yarnrc.yml"),
|
|
12919
|
+
(0, import_node_path5.join)(userRoot, ".config/pnpm/rc"),
|
|
12920
|
+
"/etc/npmrc",
|
|
12921
|
+
"/usr/local/etc/npmrc",
|
|
12922
|
+
environment.npm_config_userconfig,
|
|
12923
|
+
environment.NPM_CONFIG_USERCONFIG,
|
|
12924
|
+
environment.npm_config_globalconfig,
|
|
12925
|
+
environment.NPM_CONFIG_GLOBALCONFIG
|
|
12926
|
+
].filter((path) => !!path)
|
|
12927
|
+
);
|
|
12928
|
+
for (let cursor = (0, import_node_path5.dirname)(project.root); ; cursor = (0, import_node_path5.dirname)(cursor)) {
|
|
12929
|
+
for (const name of [".npmrc", ".yarnrc", ".yarnrc.yml"]) configuration.add((0, import_node_path5.join)(cursor, name));
|
|
12930
|
+
if (cursor === (0, import_node_path5.dirname)(cursor)) break;
|
|
12931
|
+
}
|
|
12932
|
+
const configHash = [...configuration].sort().map((file) => {
|
|
12933
|
+
if (!(0, import_node_fs5.existsSync)(file)) return [file, null];
|
|
12934
|
+
if (/(?:yarnPath|plugins|pnpmfile)/.test((0, import_node_fs5.readFileSync)(file, "utf8")))
|
|
12935
|
+
throw new Error("Custom package-manager configuration requires installation");
|
|
12936
|
+
return [file, digestTree((0, import_node_path5.dirname)(file), [(0, import_node_path5.relative)((0, import_node_path5.dirname)(file), file)], (0, import_node_path5.dirname)(file))];
|
|
12937
|
+
});
|
|
12938
|
+
const yarnCache = (0, import_node_path5.join)(cacheRoot, "yarn");
|
|
12939
|
+
const nativeCache = project.manager === "yarn" && (0, import_node_fs5.existsSync)(yarnCache) ? digestTree(yarnCache, (0, import_node_fs5.readdirSync)(yarnCache), yarnCache) : null;
|
|
12940
|
+
const key = (0, import_node_crypto2.createHash)("sha256").update(
|
|
12941
|
+
JSON.stringify({
|
|
12942
|
+
format: DEPENDENCY_SNAPSHOT_FORMAT,
|
|
12943
|
+
root: project.root,
|
|
12944
|
+
cacheRoot,
|
|
12945
|
+
manager: project.manager,
|
|
12946
|
+
managerVersion,
|
|
12947
|
+
declared: project.declared,
|
|
12948
|
+
platform: process.platform,
|
|
12949
|
+
arch: process.arch,
|
|
12950
|
+
kernel: (0, import_node_os3.release)(),
|
|
12951
|
+
runtime: process.versions,
|
|
12952
|
+
environment: Object.entries(environment).sort(([a], [b]) => a.localeCompare(b)),
|
|
12953
|
+
inputHash,
|
|
12954
|
+
configHash,
|
|
12955
|
+
nativeCache
|
|
12956
|
+
})
|
|
12957
|
+
).digest("hex");
|
|
12958
|
+
const projectKey = (0, import_node_crypto2.createHash)("sha256").update(project.root).digest("hex");
|
|
12959
|
+
return {
|
|
12960
|
+
root: project.root,
|
|
12961
|
+
cacheRoot,
|
|
12962
|
+
directory: (0, import_node_path5.join)(cacheRoot, "prepared-v1", projectKey),
|
|
12963
|
+
key,
|
|
12964
|
+
outputs: [...outputs].sort()
|
|
12965
|
+
};
|
|
12966
|
+
} catch {
|
|
12967
|
+
return void 0;
|
|
12968
|
+
}
|
|
12969
|
+
}
|
|
12970
|
+
function copy(source, destination) {
|
|
12971
|
+
(0, import_node_fs5.cpSync)(source, destination, {
|
|
12972
|
+
recursive: true,
|
|
12973
|
+
dereference: false,
|
|
12974
|
+
verbatimSymlinks: true,
|
|
12975
|
+
mode: import_node_fs5.constants.COPYFILE_FICLONE
|
|
12976
|
+
});
|
|
12977
|
+
}
|
|
12978
|
+
function restoreDependencySnapshot(snapshot) {
|
|
12979
|
+
let staging;
|
|
12980
|
+
let activated = [];
|
|
12981
|
+
let previous = [];
|
|
12982
|
+
try {
|
|
12983
|
+
if ((0, import_node_fs5.lstatSync)(snapshot.directory, { throwIfNoEntry: false })?.isSymbolicLink()) return false;
|
|
12984
|
+
const record = import_zod2.z.object({
|
|
12985
|
+
format: import_zod2.z.literal(DEPENDENCY_SNAPSHOT_FORMAT),
|
|
12986
|
+
key: import_zod2.z.literal(snapshot.key),
|
|
12987
|
+
sha256: import_zod2.z.string().regex(/^[a-f0-9]{64}$/),
|
|
12988
|
+
outputs: import_zod2.z.array(import_zod2.z.string()).refine(
|
|
12989
|
+
(paths) => new Set(paths).size === paths.length && paths.every((path) => snapshot.outputs.includes(path))
|
|
12990
|
+
)
|
|
12991
|
+
}).parse(JSON.parse((0, import_node_fs5.readFileSync)((0, import_node_path5.join)(snapshot.directory, "snapshot.json"), "utf8")));
|
|
12992
|
+
const stored = (0, import_node_path5.join)(snapshot.directory, "files");
|
|
12993
|
+
if (!record.outputs.length || digestTree(stored, record.outputs, snapshot.root) !== record.sha256) return false;
|
|
12994
|
+
for (const path of snapshot.outputs) {
|
|
12995
|
+
for (let cursor = (0, import_node_path5.dirname)((0, import_node_path5.join)(snapshot.root, path)); inside(snapshot.root, cursor); cursor = (0, import_node_path5.dirname)(cursor)) {
|
|
12996
|
+
if ((0, import_node_fs5.lstatSync)(cursor, { throwIfNoEntry: false })?.isSymbolicLink()) return false;
|
|
12997
|
+
if (cursor === snapshot.root) break;
|
|
12998
|
+
}
|
|
12999
|
+
}
|
|
13000
|
+
staging = (0, import_node_fs5.mkdtempSync)((0, import_node_path5.join)(snapshot.root, DEPENDENCY_MUTEX, "snapshot-"));
|
|
13001
|
+
for (const path of record.outputs) copy((0, import_node_path5.join)(stored, path), (0, import_node_path5.join)(staging, "next", path));
|
|
13002
|
+
if (digestTree((0, import_node_path5.join)(staging, "next"), record.outputs, snapshot.root) !== record.sha256) return false;
|
|
13003
|
+
for (const path of snapshot.outputs) {
|
|
13004
|
+
const target = (0, import_node_path5.join)(snapshot.root, path);
|
|
13005
|
+
if ((0, import_node_fs5.lstatSync)(target, { throwIfNoEntry: false })) {
|
|
13006
|
+
const backup = (0, import_node_path5.join)(staging, "previous", path);
|
|
13007
|
+
(0, import_node_fs5.mkdirSync)((0, import_node_path5.dirname)(backup), { recursive: true });
|
|
13008
|
+
(0, import_node_fs5.renameSync)(target, backup);
|
|
13009
|
+
previous = [...previous, path];
|
|
13010
|
+
}
|
|
13011
|
+
if (record.outputs.includes(path)) {
|
|
13012
|
+
(0, import_node_fs5.mkdirSync)((0, import_node_path5.dirname)(target), { recursive: true });
|
|
13013
|
+
(0, import_node_fs5.renameSync)((0, import_node_path5.join)(staging, "next", path), target);
|
|
13014
|
+
activated = [...activated, path];
|
|
13015
|
+
}
|
|
13016
|
+
}
|
|
13017
|
+
return true;
|
|
13018
|
+
} catch {
|
|
13019
|
+
try {
|
|
13020
|
+
for (const path of [...activated].reverse()) (0, import_node_fs5.rmSync)((0, import_node_path5.join)(snapshot.root, path), { recursive: true, force: true });
|
|
13021
|
+
for (const path of [...previous].reverse())
|
|
13022
|
+
(0, import_node_fs5.renameSync)((0, import_node_path5.join)(staging, "previous", path), (0, import_node_path5.join)(snapshot.root, path));
|
|
13023
|
+
} catch {
|
|
13024
|
+
const retained = staging;
|
|
13025
|
+
staging = void 0;
|
|
13026
|
+
throw new Error(`Dependency snapshot activation failed; previous files retained in ${retained}`);
|
|
13027
|
+
}
|
|
13028
|
+
return false;
|
|
13029
|
+
} finally {
|
|
13030
|
+
if (staging) (0, import_node_fs5.rmSync)(staging, { recursive: true, force: true });
|
|
13031
|
+
}
|
|
13032
|
+
}
|
|
13033
|
+
function saveDependencySnapshot(snapshot) {
|
|
13034
|
+
let staging;
|
|
13035
|
+
try {
|
|
13036
|
+
const outputs = snapshot.outputs.filter((path) => (0, import_node_fs5.lstatSync)((0, import_node_path5.join)(snapshot.root, path), { throwIfNoEntry: false }));
|
|
13037
|
+
if (!outputs.length) return;
|
|
13038
|
+
const sha256 = digestTree(snapshot.root, outputs, snapshot.root);
|
|
13039
|
+
(0, import_node_fs5.mkdirSync)((0, import_node_path5.dirname)(snapshot.directory), { recursive: true });
|
|
13040
|
+
staging = (0, import_node_fs5.mkdtempSync)((0, import_node_path5.join)((0, import_node_path5.dirname)(snapshot.directory), ".prepared-"));
|
|
13041
|
+
for (const path of outputs) copy((0, import_node_path5.join)(snapshot.root, path), (0, import_node_path5.join)(staging, "files", path));
|
|
13042
|
+
if (digestTree((0, import_node_path5.join)(staging, "files"), outputs, snapshot.root) !== sha256) return;
|
|
13043
|
+
(0, import_node_fs5.writeFileSync)(
|
|
13044
|
+
(0, import_node_path5.join)(staging, "snapshot.json"),
|
|
13045
|
+
JSON.stringify({ format: DEPENDENCY_SNAPSHOT_FORMAT, key: snapshot.key, sha256, outputs })
|
|
13046
|
+
);
|
|
13047
|
+
(0, import_node_fs5.rmSync)(snapshot.directory, { recursive: true, force: true });
|
|
13048
|
+
(0, import_node_fs5.renameSync)(staging, snapshot.directory);
|
|
13049
|
+
} catch {
|
|
13050
|
+
} finally {
|
|
13051
|
+
if (staging) (0, import_node_fs5.rmSync)(staging, { recursive: true, force: true });
|
|
13052
|
+
}
|
|
13053
|
+
}
|
|
13054
|
+
|
|
12647
13055
|
// packages/plugin/src/dependencies.ts
|
|
12648
13056
|
var execute = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
12649
13057
|
var installations = /* @__PURE__ */ new Map();
|
|
12650
13058
|
function checkTransactionPath(root, file) {
|
|
12651
|
-
const local = (0,
|
|
12652
|
-
if (!local || local.startsWith("../") || (0,
|
|
13059
|
+
const local = (0, import_node_path6.relative)(root, file);
|
|
13060
|
+
if (!local || local.startsWith("../") || (0, import_node_path6.resolve)(root, local) !== file)
|
|
12653
13061
|
throw new Error("Transaction path must stay inside its project");
|
|
12654
|
-
for (let cursor = file; cursor !== root; cursor = (0,
|
|
12655
|
-
const stat = (0,
|
|
13062
|
+
for (let cursor = file; cursor !== root; cursor = (0, import_node_path6.dirname)(cursor)) {
|
|
13063
|
+
const stat = (0, import_node_fs6.lstatSync)(cursor, { throwIfNoEntry: false });
|
|
12656
13064
|
if (stat?.isSymbolicLink()) throw new Error("Transaction path contains a symbolic link");
|
|
12657
13065
|
}
|
|
12658
13066
|
}
|
|
12659
13067
|
function manifest(root) {
|
|
12660
|
-
const file = (0,
|
|
12661
|
-
return (0,
|
|
13068
|
+
const file = (0, import_node_path6.join)(root, "package.json");
|
|
13069
|
+
return (0, import_node_fs6.existsSync)(file) ? JSON.parse((0, import_node_fs6.readFileSync)(file, "utf8")) : {};
|
|
12662
13070
|
}
|
|
12663
13071
|
function dependencyCacheRoot(root) {
|
|
12664
|
-
return (0,
|
|
13072
|
+
return (0, import_node_path6.resolve)(root ?? (0, import_common.OCTONODE_PACKAGE_CACHE)() ?? (0, import_node_path6.join)((0, import_node_os4.homedir)(), ".octonode", "package-cache"));
|
|
12665
13073
|
}
|
|
12666
13074
|
function dependencyPaths(cwd) {
|
|
12667
|
-
const start = (0,
|
|
13075
|
+
const start = (0, import_node_fs6.realpathSync)(cwd);
|
|
12668
13076
|
const ancestors = [];
|
|
12669
|
-
for (let path = start; ; path = (0,
|
|
13077
|
+
for (let path = start; ; path = (0, import_node_path6.dirname)(path)) {
|
|
12670
13078
|
ancestors.push(path);
|
|
12671
|
-
if ((0,
|
|
13079
|
+
if ((0, import_node_fs6.existsSync)((0, import_node_path6.join)(path, ".git")) || (0, import_node_path6.dirname)(path) === path) break;
|
|
12672
13080
|
}
|
|
12673
|
-
const repository = ancestors.find((path) => (0,
|
|
12674
|
-
const target = (0,
|
|
13081
|
+
const repository = ancestors.find((path) => (0, import_node_fs6.existsSync)((0, import_node_path6.join)(path, ".git")));
|
|
13082
|
+
const target = (0, import_node_fs6.existsSync)((0, import_node_path6.join)(start, "package.json")) ? start : repository ? ancestors.find((path) => (0, import_node_fs6.existsSync)((0, import_node_path6.join)(path, "package.json"))) ?? start : start;
|
|
12675
13083
|
const root = ancestors.find((path) => {
|
|
12676
|
-
if (path === target || !(0,
|
|
13084
|
+
if (path === target || !(0, import_node_path6.relative)(path, target) || (0, import_node_path6.relative)(path, target).startsWith("..")) return false;
|
|
12677
13085
|
const workspaces = manifest(path).workspaces;
|
|
12678
|
-
const pnpmWorkspace = (0,
|
|
12679
|
-
const patterns = (0,
|
|
13086
|
+
const pnpmWorkspace = (0, import_node_path6.join)(path, "pnpm-workspace.yaml");
|
|
13087
|
+
const patterns = (0, import_node_fs6.existsSync)(pnpmWorkspace) ? (0, import_yaml.parse)((0, import_node_fs6.readFileSync)(pnpmWorkspace, "utf8"))?.packages : Array.isArray(workspaces) ? workspaces : workspaces?.packages;
|
|
12680
13088
|
if (!Array.isArray(patterns)) return false;
|
|
12681
|
-
const local = (0,
|
|
13089
|
+
const local = (0, import_node_path6.relative)(path, target).split("\\").join("/");
|
|
12682
13090
|
const globs = patterns.filter((value) => typeof value === "string");
|
|
12683
|
-
return globs.some((pattern) => !pattern.startsWith("!") && (0,
|
|
13091
|
+
return globs.some((pattern) => !pattern.startsWith("!") && (0, import_node_path6.matchesGlob)(local, pattern.replace(/\/$/, ""))) && !globs.some((pattern) => pattern.startsWith("!") && (0, import_node_path6.matchesGlob)(local, pattern.slice(1).replace(/\/$/, "")));
|
|
12684
13092
|
}) ?? target;
|
|
12685
13093
|
return { root, target };
|
|
12686
13094
|
}
|
|
@@ -12688,7 +13096,7 @@ function resolveDependencyProject(cwd) {
|
|
|
12688
13096
|
const { root, target } = dependencyPaths(cwd);
|
|
12689
13097
|
const declared = manifest(root).packageManager;
|
|
12690
13098
|
const locked = Object.keys(PACKAGE_MANAGER_LOCKS).filter(
|
|
12691
|
-
(manager2) => PACKAGE_MANAGER_LOCKS[manager2].some((file) => (0,
|
|
13099
|
+
(manager2) => PACKAGE_MANAGER_LOCKS[manager2].some((file) => (0, import_node_fs6.existsSync)((0, import_node_path6.join)(root, file)))
|
|
12692
13100
|
);
|
|
12693
13101
|
const manager = declared?.split("@")[0];
|
|
12694
13102
|
if (manager && !(manager in PACKAGE_MANAGER_LOCKS)) throw new Error(`unsupported package manager: ${declared}`);
|
|
@@ -12698,7 +13106,7 @@ function resolveDependencyProject(cwd) {
|
|
|
12698
13106
|
return {
|
|
12699
13107
|
target,
|
|
12700
13108
|
root,
|
|
12701
|
-
manager: manager ?? locked[0] ?? ((0,
|
|
13109
|
+
manager: manager ?? locked[0] ?? ((0, import_node_fs6.existsSync)((0, import_node_path6.join)(root, "pnpm-workspace.yaml")) ? "pnpm" : (0, import_node_fs6.existsSync)((0, import_node_path6.join)(target, "package.json")) ? "npm" : "pnpm"),
|
|
12702
13110
|
declared
|
|
12703
13111
|
};
|
|
12704
13112
|
}
|
|
@@ -12726,42 +13134,48 @@ function installCommand(project, frozen) {
|
|
|
12726
13134
|
return ["npm", [frozen ? "ci" : "install", "--ignore-scripts", "--no-audit", "--no-fund"]];
|
|
12727
13135
|
}
|
|
12728
13136
|
}
|
|
13137
|
+
function installEnvironment(cacheRoot) {
|
|
13138
|
+
return (0, import_common.childProcessEnvironment)({
|
|
13139
|
+
...(0, import_common.packageCacheEnvironment)(dependencyCacheRoot(cacheRoot)),
|
|
13140
|
+
YARN_ENABLE_SCRIPTS: "false",
|
|
13141
|
+
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0",
|
|
13142
|
+
COREPACK_ENABLE_AUTO_PIN: "0"
|
|
13143
|
+
});
|
|
13144
|
+
}
|
|
13145
|
+
function isClassicYarn(project) {
|
|
13146
|
+
return project.manager === "yarn" && (project.declared?.startsWith("yarn@1.") || !project.declared && (0, import_node_fs6.existsSync)((0, import_node_path6.join)(project.root, "yarn.lock")) && (0, import_node_fs6.readFileSync)((0, import_node_path6.join)(project.root, "yarn.lock"), "utf8").includes("# yarn lockfile v1"));
|
|
13147
|
+
}
|
|
12729
13148
|
async function run(project, command, cwd, cacheRoot) {
|
|
12730
13149
|
const [file, args] = command;
|
|
12731
|
-
const yarnClassic =
|
|
13150
|
+
const yarnClassic = isClassicYarn(project);
|
|
12732
13151
|
const flags = yarnClassic ? [
|
|
12733
13152
|
...args.filter((arg) => arg !== "--mode=skip-build").map((arg) => arg === "--immutable" ? "--frozen-lockfile" : arg),
|
|
12734
13153
|
"--ignore-scripts"
|
|
12735
|
-
] : project.manager === "pnpm" && args[0] === "add" && project.root === cwd && (0,
|
|
13154
|
+
] : project.manager === "pnpm" && args[0] === "add" && project.root === cwd && (0, import_node_fs6.existsSync)((0, import_node_path6.join)(cwd, "pnpm-workspace.yaml")) ? [...args, "--workspace-root"] : args;
|
|
12736
13155
|
const pinned = project.declared && file !== "bun" || yarnClassic;
|
|
12737
13156
|
const executable = yarnClassic && !project.declared ? CLASSIC_YARN : file;
|
|
12738
13157
|
await execute(pinned ? "corepack" : file, pinned ? [executable, ...flags] : flags, {
|
|
12739
13158
|
cwd,
|
|
12740
|
-
env: (
|
|
12741
|
-
...(0, import_common.packageCacheEnvironment)(dependencyCacheRoot(cacheRoot)),
|
|
12742
|
-
YARN_ENABLE_SCRIPTS: "false",
|
|
12743
|
-
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0",
|
|
12744
|
-
COREPACK_ENABLE_AUTO_PIN: "0"
|
|
12745
|
-
}),
|
|
13159
|
+
env: installEnvironment(cacheRoot),
|
|
12746
13160
|
timeout: DEPENDENCY_INSTALL_TIMEOUT_MS,
|
|
12747
13161
|
maxBuffer: 4 * 1024 * 1024
|
|
12748
13162
|
});
|
|
12749
13163
|
}
|
|
12750
13164
|
async function verifyProjectDependencies(project, names) {
|
|
12751
13165
|
if (!names.length) return;
|
|
12752
|
-
const pnp = (0,
|
|
12753
|
-
const loader = (0,
|
|
13166
|
+
const pnp = (0, import_node_path6.join)(project.root, ".pnp.cjs");
|
|
13167
|
+
const loader = (0, import_node_path6.join)(project.root, ".pnp.loader.mjs");
|
|
12754
13168
|
await execute(
|
|
12755
13169
|
process.execPath,
|
|
12756
13170
|
[
|
|
12757
|
-
...(0,
|
|
12758
|
-
...(0,
|
|
13171
|
+
...(0, import_node_fs6.existsSync)(pnp) ? ["--require", pnp] : [],
|
|
13172
|
+
...(0, import_node_fs6.existsSync)(loader) ? ["--loader", loader] : [],
|
|
12759
13173
|
"--input-type=module",
|
|
12760
13174
|
"-e",
|
|
12761
13175
|
`import { createRequire } from 'node:module';
|
|
12762
13176
|
import { existsSync } from 'node:fs';
|
|
12763
13177
|
import { fileURLToPath } from 'node:url';
|
|
12764
|
-
const require = createRequire(${JSON.stringify((0,
|
|
13178
|
+
const require = createRequire(${JSON.stringify((0, import_node_path6.join)(project.target, "package.json"))});
|
|
12765
13179
|
for (const name of ${JSON.stringify(names)}) {
|
|
12766
13180
|
try { require.resolve(name); } catch {
|
|
12767
13181
|
const entry = import.meta.resolve(name);
|
|
@@ -12779,19 +13193,19 @@ async function withDependencyInstall(cwd, action) {
|
|
|
12779
13193
|
const previous = installations.get(root) ?? Promise.resolve();
|
|
12780
13194
|
const next = previous.catch(() => {
|
|
12781
13195
|
}).then(async () => {
|
|
12782
|
-
const mutex = (0,
|
|
13196
|
+
const mutex = (0, import_node_path6.join)(root, DEPENDENCY_MUTEX);
|
|
12783
13197
|
try {
|
|
12784
|
-
(0,
|
|
13198
|
+
(0, import_node_fs6.mkdirSync)(mutex);
|
|
12785
13199
|
} catch {
|
|
12786
13200
|
throw new Error(
|
|
12787
13201
|
"Another dependency installation is running or needs recovery; use octonodes plugin recover after it exits"
|
|
12788
13202
|
);
|
|
12789
13203
|
}
|
|
12790
|
-
(0,
|
|
13204
|
+
(0, import_node_fs6.writeFileSync)((0, import_node_path6.join)(mutex, "owner.json"), JSON.stringify({ pid: process.pid }));
|
|
12791
13205
|
try {
|
|
12792
13206
|
return await action();
|
|
12793
13207
|
} finally {
|
|
12794
|
-
if (!(0,
|
|
13208
|
+
if (!(0, import_node_fs6.existsSync)((0, import_node_path6.join)(mutex, "journal.json"))) (0, import_node_fs6.rmSync)(mutex, { recursive: true, force: true });
|
|
12795
13209
|
}
|
|
12796
13210
|
});
|
|
12797
13211
|
installations.set(root, next);
|
|
@@ -12802,6 +13216,8 @@ async function withDependencyInstall(cwd, action) {
|
|
|
12802
13216
|
}
|
|
12803
13217
|
}
|
|
12804
13218
|
async function reconcileDependencies(cwd, dependencies, options = {}) {
|
|
13219
|
+
if (options.metadataOnly && (dependencies.length || options.remove?.length || options.frozen))
|
|
13220
|
+
throw new Error("Metadata-only transactions cannot change or restore dependencies");
|
|
12805
13221
|
if (options.frozen && (dependencies.length || options.remove?.length))
|
|
12806
13222
|
throw new Error("Frozen installation cannot add or remove dependencies");
|
|
12807
13223
|
for (const { name, spec, subpaths } of dependencies) {
|
|
@@ -12815,64 +13231,82 @@ async function reconcileDependencies(cwd, dependencies, options = {}) {
|
|
|
12815
13231
|
}
|
|
12816
13232
|
}
|
|
12817
13233
|
const project = resolveDependencyProject(cwd);
|
|
12818
|
-
const packageJson = (0,
|
|
12819
|
-
if (!dependencies.length && !(0,
|
|
12820
|
-
const hasLock = PACKAGE_MANAGER_LOCKS[project.manager].some((file) => (0,
|
|
13234
|
+
const packageJson = (0, import_node_path6.join)(project.target, "package.json");
|
|
13235
|
+
if (!dependencies.length && !(0, import_node_fs6.existsSync)(packageJson) && !options.commit) return;
|
|
13236
|
+
const hasLock = PACKAGE_MANAGER_LOCKS[project.manager].some((file) => (0, import_node_fs6.existsSync)((0, import_node_path6.join)(project.root, file)));
|
|
12821
13237
|
if (options.frozen && !hasLock)
|
|
12822
13238
|
throw new Error("commit the native package-manager lockfile before preparing this worktree");
|
|
12823
13239
|
const files = [
|
|
12824
13240
|
.../* @__PURE__ */ new Set([
|
|
12825
13241
|
packageJson,
|
|
12826
|
-
(0,
|
|
12827
|
-
...Object.values(PACKAGE_MANAGER_LOCKS).flat().map((file) => (0,
|
|
12828
|
-
(0,
|
|
13242
|
+
(0, import_node_path6.join)(project.root, "package.json"),
|
|
13243
|
+
...Object.values(PACKAGE_MANAGER_LOCKS).flat().map((file) => (0, import_node_path6.join)(project.root, file)),
|
|
13244
|
+
(0, import_node_path6.join)(project.root, "pnpm-workspace.yaml"),
|
|
12829
13245
|
...options.transactionFiles ?? []
|
|
12830
13246
|
])
|
|
12831
13247
|
];
|
|
12832
13248
|
for (const path of files) checkTransactionPath(project.root, path);
|
|
12833
|
-
const before = new Map(files.map((path) => [path, (0,
|
|
12834
|
-
const journal = (0,
|
|
12835
|
-
const hadModules = (0,
|
|
13249
|
+
const before = new Map(files.map((path) => [path, (0, import_node_fs6.existsSync)(path) ? (0, import_node_fs6.readFileSync)(path) : void 0]));
|
|
13250
|
+
const journal = (0, import_node_path6.join)(project.root, DEPENDENCY_MUTEX, "journal.json");
|
|
13251
|
+
const hadModules = (0, import_node_fs6.existsSync)((0, import_node_path6.join)(project.root, "node_modules"));
|
|
12836
13252
|
const pnpFiles = [".pnp.cjs", ".pnp.loader.mjs", ".pnp.data.json"];
|
|
12837
13253
|
const pnpBefore = new Map(
|
|
12838
13254
|
pnpFiles.map((file) => {
|
|
12839
|
-
const path = (0,
|
|
12840
|
-
return [path, (0,
|
|
13255
|
+
const path = (0, import_node_path6.join)(project.root, file);
|
|
13256
|
+
return [path, (0, import_node_fs6.existsSync)(path) ? (0, import_node_fs6.readFileSync)(path) : void 0];
|
|
12841
13257
|
})
|
|
12842
13258
|
);
|
|
12843
|
-
const hadInstall = hadModules || (0,
|
|
13259
|
+
const hadInstall = hadModules || (0, import_node_fs6.existsSync)((0, import_node_path6.join)(project.root, ".pnp.cjs"));
|
|
12844
13260
|
let metadataTouched = false;
|
|
12845
13261
|
const metadata = new Set(options.transactionFiles ?? []);
|
|
12846
13262
|
const restoreBefore = () => {
|
|
12847
13263
|
for (const [path, content] of before) {
|
|
12848
13264
|
if (metadata.has(path) && !metadataTouched) continue;
|
|
12849
|
-
if (content === void 0) (0,
|
|
12850
|
-
else (0,
|
|
13265
|
+
if (content === void 0) (0, import_node_fs6.rmSync)(path, { force: true });
|
|
13266
|
+
else (0, import_node_fs6.writeFileSync)(path, content);
|
|
12851
13267
|
}
|
|
12852
13268
|
};
|
|
12853
|
-
if (hadInstall && !hasLock)
|
|
13269
|
+
if (hadInstall && !hasLock && !options.metadataOnly)
|
|
12854
13270
|
throw new Error(
|
|
12855
13271
|
"create a native lockfile before updating existing dependencies so failed installations can be recovered"
|
|
12856
13272
|
);
|
|
12857
13273
|
try {
|
|
12858
|
-
if ((0,
|
|
12859
|
-
(0,
|
|
13274
|
+
if (options.metadataOnly && (0, import_node_fs6.existsSync)((0, import_node_path6.dirname)(journal)))
|
|
13275
|
+
(0, import_node_fs6.writeFileSync)((0, import_node_path6.join)((0, import_node_path6.dirname)(journal), "metadata-only"), "1");
|
|
13276
|
+
if ((0, import_node_fs6.existsSync)((0, import_node_path6.dirname)(journal)))
|
|
13277
|
+
(0, import_node_fs6.writeFileSync)(
|
|
12860
13278
|
journal,
|
|
12861
13279
|
JSON.stringify(
|
|
12862
13280
|
[...before].map(([path, content]) => ({
|
|
12863
|
-
path: (0,
|
|
13281
|
+
path: (0, import_node_path6.relative)(project.root, path).replaceAll("\\", "/"),
|
|
12864
13282
|
content: content?.toString("base64") ?? null
|
|
12865
13283
|
}))
|
|
12866
13284
|
)
|
|
12867
13285
|
);
|
|
12868
|
-
if (
|
|
12869
|
-
|
|
12870
|
-
(
|
|
13286
|
+
if (options.metadataOnly) {
|
|
13287
|
+
metadataTouched = true;
|
|
13288
|
+
options.commit?.();
|
|
13289
|
+
(0, import_node_fs6.rmSync)(journal, { force: true });
|
|
13290
|
+
(0, import_node_fs6.rmSync)((0, import_node_path6.join)((0, import_node_path6.dirname)(journal), "metadata-only"), { force: true });
|
|
13291
|
+
return;
|
|
13292
|
+
}
|
|
13293
|
+
if (!(0, import_node_fs6.existsSync)(packageJson)) {
|
|
13294
|
+
(0, import_node_fs6.mkdirSync)(project.target, { recursive: true });
|
|
13295
|
+
(0, import_node_fs6.writeFileSync)(
|
|
12871
13296
|
packageJson,
|
|
12872
13297
|
JSON.stringify({ private: true, packageManager: DEFAULT_PACKAGE_MANAGER }, null, 2) + "\n"
|
|
12873
13298
|
);
|
|
12874
13299
|
}
|
|
12875
13300
|
const current = resolveDependencyProject(cwd);
|
|
13301
|
+
const snapshotEnvironment = installEnvironment(options.cacheRoot);
|
|
13302
|
+
const pinnedManager = current.declared && current.manager !== "bun" || isClassicYarn(current);
|
|
13303
|
+
const versionCommand = isClassicYarn(current) && !current.declared ? CLASSIC_YARN : current.manager;
|
|
13304
|
+
const managerVersion = options.frozen && (options.cacheRoot || (0, import_common.OCTONODE_PACKAGE_CACHE)()) ? await execute(
|
|
13305
|
+
pinnedManager ? "corepack" : current.manager,
|
|
13306
|
+
pinnedManager ? [versionCommand, "--version"] : ["--version"],
|
|
13307
|
+
{ cwd: current.root, env: snapshotEnvironment, timeout: 3e4 }
|
|
13308
|
+
).then(({ stdout }) => stdout.trim()).catch(() => void 0) : void 0;
|
|
13309
|
+
const snapshot = managerVersion ? dependencySnapshot(current, dependencyCacheRoot(options.cacheRoot), managerVersion, snapshotEnvironment) : void 0;
|
|
12876
13310
|
if (options.remove?.length) {
|
|
12877
13311
|
for (const name of options.remove)
|
|
12878
13312
|
if (!/^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*$/i.test(name))
|
|
@@ -12880,81 +13314,92 @@ async function reconcileDependencies(cwd, dependencies, options = {}) {
|
|
|
12880
13314
|
const args = current.manager === "npm" ? ["uninstall", "--ignore-scripts", "--no-audit", "--no-fund"] : current.manager === "yarn" ? ["remove", "--mode=skip-build"] : ["remove", "--ignore-scripts"];
|
|
12881
13315
|
await run(current, [current.manager, [...args, ...options.remove]], current.target, options.cacheRoot);
|
|
12882
13316
|
}
|
|
12883
|
-
|
|
12884
|
-
|
|
12885
|
-
|
|
12886
|
-
current
|
|
12887
|
-
|
|
12888
|
-
|
|
12889
|
-
|
|
12890
|
-
|
|
12891
|
-
|
|
13317
|
+
const restored = snapshot ? restoreDependencySnapshot(snapshot) : false;
|
|
13318
|
+
if (!restored)
|
|
13319
|
+
await run(
|
|
13320
|
+
current,
|
|
13321
|
+
dependencies.length ? packageManagerAdd(
|
|
13322
|
+
current.manager,
|
|
13323
|
+
...dependencies.map(({ name, spec }) => spec.startsWith(`${name}@`) ? spec : `${name}@${spec}`)
|
|
13324
|
+
) : installCommand(current, options.frozen ?? false),
|
|
13325
|
+
dependencies.length ? current.target : current.root,
|
|
13326
|
+
options.cacheRoot
|
|
13327
|
+
);
|
|
12892
13328
|
await verifyProjectDependencies(
|
|
12893
13329
|
current,
|
|
12894
13330
|
dependencies.flatMap(({ name, subpaths }) => subpaths ? subpaths.map((path) => name + path.slice(1)) : [name])
|
|
12895
13331
|
);
|
|
12896
13332
|
if (options.frozen) {
|
|
12897
13333
|
for (const [path, content] of before) {
|
|
12898
|
-
const after = (0,
|
|
13334
|
+
const after = (0, import_node_fs6.existsSync)(path) ? (0, import_node_fs6.readFileSync)(path) : void 0;
|
|
12899
13335
|
if (content?.equals(after ?? Buffer.alloc(0)) || !content && !after) continue;
|
|
12900
13336
|
if (path.endsWith("package.json") && content && after && (0, import_node_util.isDeepStrictEqual)(JSON.parse(content.toString()), JSON.parse(after.toString()))) {
|
|
12901
|
-
(0,
|
|
13337
|
+
(0, import_node_fs6.writeFileSync)(path, content);
|
|
12902
13338
|
} else {
|
|
12903
|
-
throw new Error(`frozen installation changed ${(0,
|
|
13339
|
+
throw new Error(`frozen installation changed ${(0, import_node_path6.relative)(project.root, path)}`);
|
|
12904
13340
|
}
|
|
12905
13341
|
}
|
|
12906
13342
|
}
|
|
12907
13343
|
for (const path of metadata) {
|
|
12908
13344
|
const content = before.get(path);
|
|
12909
|
-
const current2 = (0,
|
|
13345
|
+
const current2 = (0, import_node_fs6.existsSync)(path) ? (0, import_node_fs6.readFileSync)(path) : void 0;
|
|
12910
13346
|
if (!(content?.equals(current2 ?? Buffer.alloc(0)) || !content && !current2))
|
|
12911
13347
|
throw new Error(
|
|
12912
|
-
`Owner metadata changed during installation: ${(0,
|
|
13348
|
+
`Owner metadata changed during installation: ${(0, import_node_path6.relative)(project.root, path)}; refresh and retry`
|
|
12913
13349
|
);
|
|
12914
13350
|
}
|
|
12915
13351
|
metadataTouched = true;
|
|
12916
13352
|
options.commit?.();
|
|
12917
|
-
(0,
|
|
13353
|
+
(0, import_node_fs6.rmSync)(journal, { force: true });
|
|
13354
|
+
if (snapshot && !restored) {
|
|
13355
|
+
const after = dependencySnapshot(
|
|
13356
|
+
current,
|
|
13357
|
+
dependencyCacheRoot(options.cacheRoot),
|
|
13358
|
+
managerVersion,
|
|
13359
|
+
snapshotEnvironment
|
|
13360
|
+
);
|
|
13361
|
+
if (after?.key === snapshot.key) saveDependencySnapshot(after);
|
|
13362
|
+
}
|
|
12918
13363
|
} catch (error) {
|
|
12919
|
-
const changed = [...before].filter(([path, content]) => (0,
|
|
13364
|
+
const changed = [...before].filter(([path, content]) => (0, import_node_fs6.existsSync)(path) && !content?.equals((0, import_node_fs6.readFileSync)(path)));
|
|
12920
13365
|
if (changed.length) {
|
|
12921
|
-
const backup = (0,
|
|
13366
|
+
const backup = (0, import_node_path6.join)(project.root, `.octonode-recovery-${Date.now()}`);
|
|
12922
13367
|
for (const [path] of changed) {
|
|
12923
13368
|
checkTransactionPath(project.root, path);
|
|
12924
|
-
const target = (0,
|
|
12925
|
-
(0,
|
|
12926
|
-
(0,
|
|
13369
|
+
const target = (0, import_node_path6.join)(backup, (0, import_node_path6.relative)(project.root, path));
|
|
13370
|
+
(0, import_node_fs6.mkdirSync)((0, import_node_path6.dirname)(target), { recursive: true });
|
|
13371
|
+
(0, import_node_fs6.writeFileSync)(target, (0, import_node_fs6.readFileSync)(path));
|
|
12927
13372
|
}
|
|
12928
13373
|
process.stderr.write(`Pre-rollback files preserved in ${backup}
|
|
12929
13374
|
`);
|
|
12930
13375
|
}
|
|
12931
13376
|
restoreBefore();
|
|
12932
13377
|
let recovery = "";
|
|
12933
|
-
if (hadInstall && hasLock) {
|
|
13378
|
+
if (!options.metadataOnly && hadInstall && hasLock) {
|
|
12934
13379
|
try {
|
|
12935
13380
|
await run(project, installCommand(project, true), project.root, options.cacheRoot);
|
|
12936
13381
|
} catch {
|
|
12937
13382
|
recovery = "; manifests restored, but dependency recovery failed \u2014 run a frozen install before executing workflows";
|
|
12938
13383
|
}
|
|
12939
13384
|
restoreBefore();
|
|
12940
|
-
} else if (!hadInstall) {
|
|
12941
|
-
(0,
|
|
13385
|
+
} else if (!options.metadataOnly && !hadInstall) {
|
|
13386
|
+
(0, import_node_fs6.rmSync)((0, import_node_path6.join)(project.root, "node_modules"), { recursive: true, force: true });
|
|
12942
13387
|
}
|
|
12943
13388
|
for (const [path, content] of pnpBefore) {
|
|
12944
|
-
if (content === void 0) (0,
|
|
12945
|
-
else (0,
|
|
13389
|
+
if (content === void 0) (0, import_node_fs6.rmSync)(path, { force: true });
|
|
13390
|
+
else (0, import_node_fs6.writeFileSync)(path, content);
|
|
12946
13391
|
}
|
|
12947
13392
|
const failure = error;
|
|
12948
|
-
if (!recovery) (0,
|
|
13393
|
+
if (!recovery) (0, import_node_fs6.rmSync)(journal, { force: true });
|
|
12949
13394
|
throw new Error(`package installation failed: ${failure.stderr?.trim() || failure.message}${recovery}`);
|
|
12950
13395
|
}
|
|
12951
13396
|
}
|
|
12952
13397
|
async function recoverDependencyInstall(cwd) {
|
|
12953
13398
|
const project = resolveDependencyProject(cwd);
|
|
12954
|
-
const mutex = (0,
|
|
12955
|
-
if (!(0,
|
|
12956
|
-
checkTransactionPath(project.root, (0,
|
|
12957
|
-
const owner = JSON.parse((0,
|
|
13399
|
+
const mutex = (0, import_node_path6.join)(project.root, DEPENDENCY_MUTEX);
|
|
13400
|
+
if (!(0, import_node_fs6.existsSync)(mutex)) return;
|
|
13401
|
+
checkTransactionPath(project.root, (0, import_node_path6.join)(mutex, "owner.json"));
|
|
13402
|
+
const owner = JSON.parse((0, import_node_fs6.readFileSync)((0, import_node_path6.join)(mutex, "owner.json"), "utf8"));
|
|
12958
13403
|
if (!Number.isInteger(owner.pid) || owner.pid < 1)
|
|
12959
13404
|
throw new Error("Invalid installation owner; inspect the transaction manually");
|
|
12960
13405
|
try {
|
|
@@ -12963,37 +13408,37 @@ async function recoverDependencyInstall(cwd) {
|
|
|
12963
13408
|
} catch (error) {
|
|
12964
13409
|
if (error.code !== "ESRCH") throw error;
|
|
12965
13410
|
}
|
|
12966
|
-
const journal = (0,
|
|
13411
|
+
const journal = (0, import_node_path6.join)(mutex, "journal.json");
|
|
12967
13412
|
checkTransactionPath(project.root, journal);
|
|
12968
|
-
if ((0,
|
|
12969
|
-
const records = JSON.parse((0,
|
|
13413
|
+
if ((0, import_node_fs6.existsSync)(journal)) {
|
|
13414
|
+
const records = JSON.parse((0, import_node_fs6.readFileSync)(journal, "utf8"));
|
|
12970
13415
|
if (!Array.isArray(records)) throw new Error("Invalid recovery journal");
|
|
12971
13416
|
for (const record of records) {
|
|
12972
13417
|
if (!record || typeof record.path !== "string" || !record.path || record.path.includes("\\") || record.path.startsWith("/") || record.path.split("/").some((part) => part === ".." || part === "." || part.includes(":")) || record.content !== null && typeof record.content !== "string")
|
|
12973
13418
|
throw new Error("Invalid recovery journal path");
|
|
12974
|
-
checkTransactionPath(project.root, (0,
|
|
12975
|
-
checkTransactionPath(project.root, (0,
|
|
13419
|
+
checkTransactionPath(project.root, (0, import_node_path6.join)(project.root, record.path));
|
|
13420
|
+
checkTransactionPath(project.root, (0, import_node_path6.join)(mutex, "recovery-backup", record.path));
|
|
12976
13421
|
}
|
|
12977
13422
|
for (const record of records) {
|
|
12978
|
-
const path = (0,
|
|
12979
|
-
if ((0,
|
|
12980
|
-
const backup = (0,
|
|
12981
|
-
(0,
|
|
12982
|
-
if (!(0,
|
|
12983
|
-
}
|
|
12984
|
-
if (record.content === null) (0,
|
|
12985
|
-
else (0,
|
|
13423
|
+
const path = (0, import_node_path6.join)(project.root, record.path);
|
|
13424
|
+
if ((0, import_node_fs6.existsSync)(path)) {
|
|
13425
|
+
const backup = (0, import_node_path6.join)(mutex, "recovery-backup", record.path);
|
|
13426
|
+
(0, import_node_fs6.mkdirSync)((0, import_node_path6.dirname)(backup), { recursive: true });
|
|
13427
|
+
if (!(0, import_node_fs6.existsSync)(backup)) (0, import_node_fs6.writeFileSync)(backup, (0, import_node_fs6.readFileSync)(path));
|
|
13428
|
+
}
|
|
13429
|
+
if (record.content === null) (0, import_node_fs6.rmSync)(path, { force: true });
|
|
13430
|
+
else (0, import_node_fs6.writeFileSync)(path, Buffer.from(record.content, "base64"));
|
|
12986
13431
|
}
|
|
12987
|
-
if (PACKAGE_MANAGER_LOCKS[project.manager].some((file) => (0,
|
|
13432
|
+
if (!(0, import_node_fs6.existsSync)((0, import_node_path6.join)(mutex, "metadata-only")) && PACKAGE_MANAGER_LOCKS[project.manager].some((file) => (0, import_node_fs6.existsSync)((0, import_node_path6.join)(project.root, file))))
|
|
12988
13433
|
await run(project, installCommand(project, true), project.root);
|
|
12989
13434
|
}
|
|
12990
|
-
if ((0,
|
|
12991
|
-
const backup = (0,
|
|
12992
|
-
(0,
|
|
13435
|
+
if ((0, import_node_fs6.existsSync)((0, import_node_path6.join)(mutex, "recovery-backup"))) {
|
|
13436
|
+
const backup = (0, import_node_path6.join)(project.root, `.octonode-recovery-${Date.now()}`);
|
|
13437
|
+
(0, import_node_fs6.renameSync)((0, import_node_path6.join)(mutex, "recovery-backup"), backup);
|
|
12993
13438
|
process.stderr.write(`Pre-recovery files preserved in ${backup}
|
|
12994
13439
|
`);
|
|
12995
13440
|
}
|
|
12996
|
-
(0,
|
|
13441
|
+
(0, import_node_fs6.rmSync)(mutex, { recursive: true, force: true });
|
|
12997
13442
|
}
|
|
12998
13443
|
function installProjectDependencies(cwd, dependencies = [], options = {}) {
|
|
12999
13444
|
return withDependencyInstall(cwd, () => reconcileDependencies(cwd, dependencies, options));
|
|
@@ -13002,15 +13447,15 @@ function installProjectDependencies(cwd, dependencies = [], options = {}) {
|
|
|
13002
13447
|
// packages/plugin/src/generated-package.ts
|
|
13003
13448
|
var import_tar = require("tar");
|
|
13004
13449
|
var import_node_zlib = require("node:zlib");
|
|
13450
|
+
var import_node_crypto4 = require("node:crypto");
|
|
13451
|
+
var import_node_fs8 = require("node:fs");
|
|
13452
|
+
var import_node_os5 = require("node:os");
|
|
13453
|
+
var import_node_path8 = require("node:path");
|
|
13454
|
+
|
|
13455
|
+
// packages/plugin/src/authoring/artifact.ts
|
|
13005
13456
|
var import_node_crypto3 = require("node:crypto");
|
|
13006
13457
|
var import_node_fs7 = require("node:fs");
|
|
13007
|
-
var import_node_os4 = require("node:os");
|
|
13008
13458
|
var import_node_path7 = require("node:path");
|
|
13009
|
-
|
|
13010
|
-
// packages/plugin/src/authoring/artifact.ts
|
|
13011
|
-
var import_node_crypto2 = require("node:crypto");
|
|
13012
|
-
var import_node_fs6 = require("node:fs");
|
|
13013
|
-
var import_node_path6 = require("node:path");
|
|
13014
13459
|
var import_schema3 = __toESM(require_dist());
|
|
13015
13460
|
var import_yaml2 = require("yaml");
|
|
13016
13461
|
|
|
@@ -13030,18 +13475,18 @@ var RESERVED_ASSETS = /* @__PURE__ */ new Set([
|
|
|
13030
13475
|
]);
|
|
13031
13476
|
|
|
13032
13477
|
// packages/plugin/src/authoring/artifact.ts
|
|
13033
|
-
var fileHash = (path) => (0,
|
|
13478
|
+
var fileHash = (path) => (0, import_node_crypto3.createHash)("sha256").update((0, import_node_fs7.readFileSync)(path)).digest("hex");
|
|
13034
13479
|
function safePath(path) {
|
|
13035
|
-
if (!path || (0,
|
|
13480
|
+
if (!path || (0, import_node_path7.isAbsolute)(path) || path.includes("\\") || path.split("/").some((part) => !part || part === "." || part === ".." || part.includes(":") || FORBIDDEN_PART.test(part))) {
|
|
13036
13481
|
throw new Error(`Unsafe plugin file: ${path}`);
|
|
13037
13482
|
}
|
|
13038
13483
|
}
|
|
13039
13484
|
function pluginFiles(root, prefix = "") {
|
|
13040
|
-
if (!(0,
|
|
13041
|
-
return (0,
|
|
13485
|
+
if (!(0, import_node_fs7.lstatSync)((0, import_node_path7.join)(root, prefix)).isDirectory()) throw new Error(`Not a plugin directory: ${root}`);
|
|
13486
|
+
return (0, import_node_fs7.readdirSync)((0, import_node_path7.join)(root, prefix)).sort().flatMap((name) => {
|
|
13042
13487
|
const path = prefix ? `${prefix}/${name}` : name;
|
|
13043
13488
|
safePath(path);
|
|
13044
|
-
const stat = (0,
|
|
13489
|
+
const stat = (0, import_node_fs7.lstatSync)((0, import_node_path7.join)(root, path));
|
|
13045
13490
|
if (stat.isSymbolicLink()) throw new Error(`Plugin files cannot be symbolic links: ${path}`);
|
|
13046
13491
|
if (stat.isDirectory()) return pluginFiles(root, path);
|
|
13047
13492
|
if (!stat.isFile()) throw new Error(`Plugin asset must be a regular file: ${path}`);
|
|
@@ -13049,14 +13494,14 @@ function pluginFiles(root, prefix = "") {
|
|
|
13049
13494
|
});
|
|
13050
13495
|
}
|
|
13051
13496
|
function loadManifest(directory) {
|
|
13052
|
-
if ((0,
|
|
13053
|
-
const definitions = DEFINITION_FILES.filter((name) => (0,
|
|
13497
|
+
if ((0, import_node_fs7.lstatSync)(directory).isSymbolicLink()) throw new Error("Plugin directory cannot be a symbolic link");
|
|
13498
|
+
const definitions = DEFINITION_FILES.filter((name) => (0, import_node_fs7.existsSync)((0, import_node_path7.join)(directory, name)));
|
|
13054
13499
|
if (definitions.length !== 1) throw new Error("Keep exactly one plugin definition in the package");
|
|
13055
|
-
const path = (0,
|
|
13056
|
-
const stat = (0,
|
|
13500
|
+
const path = (0, import_node_path7.join)(directory, definitions[0]);
|
|
13501
|
+
const stat = (0, import_node_fs7.lstatSync)(path);
|
|
13057
13502
|
if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 1048576)
|
|
13058
13503
|
throw new Error("Invalid plugin definition file");
|
|
13059
|
-
const document = (0, import_yaml2.parseDocument)((0,
|
|
13504
|
+
const document = (0, import_yaml2.parseDocument)((0, import_node_fs7.readFileSync)(path, "utf8"), { uniqueKeys: true, version: "1.2" });
|
|
13060
13505
|
(0, import_yaml2.visit)(document, {
|
|
13061
13506
|
Alias() {
|
|
13062
13507
|
throw new Error("Plugin definitions cannot contain YAML aliases");
|
|
@@ -13072,7 +13517,16 @@ function verifyBuild(directory) {
|
|
|
13072
13517
|
const manifest2 = loadManifest(directory);
|
|
13073
13518
|
const files = pluginFiles(directory);
|
|
13074
13519
|
if (!files.includes(BUILD_RECORD)) throw new Error("Missing build record; run octonodes plugin build first");
|
|
13075
|
-
const record = JSON.parse((0,
|
|
13520
|
+
const record = JSON.parse((0, import_node_fs7.readFileSync)((0, import_node_path7.join)(directory, BUILD_RECORD), "utf8"));
|
|
13521
|
+
if (record.runtime) {
|
|
13522
|
+
const runtime = import_schema3.PreparedPluginRuntime.parse(record.runtime);
|
|
13523
|
+
if ((manifest2.integration?.npm || manifest2.integration?.npmDependencies?.length) && !runtime.dependencies)
|
|
13524
|
+
throw new Error("Prepared npm plugins must include their dependency runtime");
|
|
13525
|
+
if (runtime.dependencies && !files.includes(runtime.dependencies))
|
|
13526
|
+
throw new Error("Missing prepared dependency archive");
|
|
13527
|
+
if (runtime.dependencies && (runtime.platform === "portable" || !runtime.arch || runtime.platform === "linux" && !runtime.libc))
|
|
13528
|
+
throw new Error("Prepared dependencies require a platform, architecture and libc identity");
|
|
13529
|
+
}
|
|
13076
13530
|
if (record.format !== 1 || !record.files || typeof record.files !== "object" || Array.isArray(record.files)) {
|
|
13077
13531
|
throw new Error("Invalid plugin build record");
|
|
13078
13532
|
}
|
|
@@ -13081,7 +13535,7 @@ function verifyBuild(directory) {
|
|
|
13081
13535
|
throw new Error("Plugin files changed since build; rebuild before publishing");
|
|
13082
13536
|
}
|
|
13083
13537
|
for (const file of expected) {
|
|
13084
|
-
if (record.files[file] !== fileHash((0,
|
|
13538
|
+
if (record.files[file] !== fileHash((0, import_node_path7.join)(directory, file)))
|
|
13085
13539
|
throw new Error(`Plugin file changed since build: ${file}`);
|
|
13086
13540
|
}
|
|
13087
13541
|
if (!expected.includes("dist/index.js") || !manifest2.nodes.length || manifest2.nodes.some(
|
|
@@ -13102,14 +13556,14 @@ function verifyBuild(directory) {
|
|
|
13102
13556
|
)
|
|
13103
13557
|
);
|
|
13104
13558
|
for (const entry of new Set(ui.map(({ path }) => path))) {
|
|
13105
|
-
if (!expected.includes(entry) || (0,
|
|
13559
|
+
if (!expected.includes(entry) || (0, import_node_fs7.lstatSync)((0, import_node_path7.join)(directory, entry)).size > import_schema3.PLUGIN_UI_BUNDLE_MAX_BYTES)
|
|
13106
13560
|
throw new Error(`Invalid plugin UI bundle: ${entry}`);
|
|
13107
13561
|
}
|
|
13108
13562
|
if (JSON.stringify(record.ui ?? []) !== JSON.stringify(
|
|
13109
13563
|
ui.map((declaration) => ({
|
|
13110
13564
|
...declaration,
|
|
13111
|
-
size: (0,
|
|
13112
|
-
sha256: fileHash((0,
|
|
13565
|
+
size: (0, import_node_fs7.lstatSync)((0, import_node_path7.join)(directory, declaration.path)).size,
|
|
13566
|
+
sha256: fileHash((0, import_node_path7.join)(directory, declaration.path))
|
|
13113
13567
|
}))
|
|
13114
13568
|
))
|
|
13115
13569
|
throw new Error("Invalid plugin UI build record");
|
|
@@ -13134,41 +13588,41 @@ async function generatePluginPackage(cwd, selections, expectedPacker) {
|
|
|
13134
13588
|
const packer = "tar@7.5.22/portable-v1";
|
|
13135
13589
|
if (expectedPacker && expectedPacker !== packer)
|
|
13136
13590
|
throw new Error(`Plugin package restore requires ${expectedPacker}; found ${packer}`);
|
|
13137
|
-
const digest = (0,
|
|
13591
|
+
const digest = (0, import_node_crypto4.createHash)("sha256").update(
|
|
13138
13592
|
JSON.stringify({
|
|
13139
13593
|
format: GENERATED_PLUGIN_FORMAT,
|
|
13140
13594
|
packer,
|
|
13141
13595
|
selections: selected.map(({ alias, sha256 }) => ({ alias, sha256 }))
|
|
13142
13596
|
})
|
|
13143
13597
|
).digest("hex");
|
|
13144
|
-
const stage = (0,
|
|
13598
|
+
const stage = (0, import_node_fs8.mkdtempSync)((0, import_node_path8.join)((0, import_node_os5.tmpdir)(), "octonode-package-"));
|
|
13145
13599
|
try {
|
|
13146
|
-
const packageRoot = (0,
|
|
13147
|
-
(0,
|
|
13600
|
+
const packageRoot = (0, import_node_path8.join)(stage, "package");
|
|
13601
|
+
(0, import_node_fs8.mkdirSync)(packageRoot);
|
|
13148
13602
|
for (const { alias, directory, sha256 } of selected) {
|
|
13149
|
-
if ((0,
|
|
13603
|
+
if ((0, import_node_fs8.lstatSync)(directory).isSymbolicLink())
|
|
13150
13604
|
throw new Error(`Plugin directory cannot be a symbolic link: ${alias}`);
|
|
13151
|
-
const snapshot = (0,
|
|
13152
|
-
(0,
|
|
13605
|
+
const snapshot = (0, import_node_path8.join)(stage, "snapshots", alias);
|
|
13606
|
+
(0, import_node_fs8.mkdirSync)(snapshot, { recursive: true });
|
|
13153
13607
|
for (const file of pluginBundleFiles(directory)) {
|
|
13154
13608
|
safePath(file);
|
|
13155
|
-
(0,
|
|
13156
|
-
(0,
|
|
13609
|
+
(0, import_node_fs8.mkdirSync)((0, import_node_path8.dirname)((0, import_node_path8.join)(snapshot, file)), { recursive: true });
|
|
13610
|
+
(0, import_node_fs8.writeFileSync)((0, import_node_path8.join)(snapshot, file), (0, import_node_fs8.readFileSync)((0, import_node_path8.join)(directory, file)));
|
|
13157
13611
|
}
|
|
13158
13612
|
if (hashPluginDir(snapshot) !== sha256) throw new Error(`Plugin integrity mismatch: ${alias}`);
|
|
13159
|
-
const library = (0,
|
|
13160
|
-
if (!(0,
|
|
13613
|
+
const library = (0, import_node_path8.join)(snapshot, "library");
|
|
13614
|
+
if (!(0, import_node_fs8.existsSync)((0, import_node_path8.join)(library, "index.js")) || !(0, import_node_fs8.existsSync)((0, import_node_path8.join)(library, "index.d.ts")))
|
|
13161
13615
|
throw new Error(`Plugin ${alias} has no importable library; rebuild with a compatible CLI`);
|
|
13162
13616
|
for (const file of pluginFiles(library)) {
|
|
13163
|
-
const target = (0,
|
|
13164
|
-
(0,
|
|
13165
|
-
(0,
|
|
13166
|
-
(0,
|
|
13617
|
+
const target = (0, import_node_path8.join)(packageRoot, alias, file);
|
|
13618
|
+
(0, import_node_fs8.mkdirSync)((0, import_node_path8.dirname)(target), { recursive: true });
|
|
13619
|
+
(0, import_node_fs8.writeFileSync)(target, (0, import_node_fs8.readFileSync)((0, import_node_path8.join)(library, file)));
|
|
13620
|
+
(0, import_node_fs8.chmodSync)(target, 420);
|
|
13167
13621
|
}
|
|
13168
13622
|
}
|
|
13169
13623
|
const subpaths = selected.map(({ alias }) => `./${alias}`);
|
|
13170
|
-
(0,
|
|
13171
|
-
(0,
|
|
13624
|
+
(0, import_node_fs8.writeFileSync)(
|
|
13625
|
+
(0, import_node_path8.join)(packageRoot, "package.json"),
|
|
13172
13626
|
JSON.stringify(
|
|
13173
13627
|
{
|
|
13174
13628
|
name: GENERATED_PLUGIN_PACKAGE,
|
|
@@ -13183,8 +13637,8 @@ async function generatePluginPackage(cwd, selections, expectedPacker) {
|
|
|
13183
13637
|
2
|
|
13184
13638
|
) + "\n"
|
|
13185
13639
|
);
|
|
13186
|
-
(0,
|
|
13187
|
-
const archive = (0,
|
|
13640
|
+
(0, import_node_fs8.chmodSync)((0, import_node_path8.join)(packageRoot, "package.json"), 420);
|
|
13641
|
+
const archive = (0, import_node_path8.join)(stage, "package.tar");
|
|
13188
13642
|
(0, import_tar.create)(
|
|
13189
13643
|
{
|
|
13190
13644
|
file: archive,
|
|
@@ -13197,24 +13651,24 @@ async function generatePluginPackage(cwd, selections, expectedPacker) {
|
|
|
13197
13651
|
},
|
|
13198
13652
|
pluginFiles(packageRoot)
|
|
13199
13653
|
);
|
|
13200
|
-
const bytes = (0, import_node_zlib.gzipSync)((0,
|
|
13654
|
+
const bytes = (0, import_node_zlib.gzipSync)((0, import_node_fs8.readFileSync)(archive), { level: 0 });
|
|
13201
13655
|
bytes[9] = 255;
|
|
13202
|
-
const output = (0,
|
|
13203
|
-
(0,
|
|
13204
|
-
if ((0,
|
|
13205
|
-
const ignore = (0,
|
|
13206
|
-
if (!(0,
|
|
13207
|
-
const destination = (0,
|
|
13208
|
-
if ((0,
|
|
13209
|
-
if ((0,
|
|
13656
|
+
const output = (0, import_node_path8.join)(cwd, GENERATED_PLUGIN_DIRECTORY);
|
|
13657
|
+
(0, import_node_fs8.mkdirSync)(output, { recursive: true });
|
|
13658
|
+
if ((0, import_node_fs8.lstatSync)(output).isSymbolicLink()) throw new Error("Generated plugin directory cannot be a symbolic link");
|
|
13659
|
+
const ignore = (0, import_node_path8.join)(output, ".gitignore");
|
|
13660
|
+
if (!(0, import_node_fs8.existsSync)(ignore)) (0, import_node_fs8.writeFileSync)(ignore, "*\n", { flag: "wx" });
|
|
13661
|
+
const destination = (0, import_node_path8.join)(output, `plugin-${digest}.tgz`);
|
|
13662
|
+
if ((0, import_node_fs8.existsSync)(destination)) {
|
|
13663
|
+
if ((0, import_node_fs8.lstatSync)(destination).isSymbolicLink() || !(0, import_node_fs8.readFileSync)(destination).equals(bytes))
|
|
13210
13664
|
throw new Error("Generated plugin package changed; remove the corrupt generated file and restore again");
|
|
13211
13665
|
} else {
|
|
13212
|
-
const temporary = (0,
|
|
13666
|
+
const temporary = (0, import_node_fs8.mkdtempSync)((0, import_node_path8.join)(output, ".pack-"));
|
|
13213
13667
|
try {
|
|
13214
|
-
(0,
|
|
13215
|
-
(0,
|
|
13668
|
+
(0, import_node_fs8.writeFileSync)((0, import_node_path8.join)(temporary, "package.tgz"), bytes);
|
|
13669
|
+
(0, import_node_fs8.renameSync)((0, import_node_path8.join)(temporary, "package.tgz"), destination);
|
|
13216
13670
|
} finally {
|
|
13217
|
-
(0,
|
|
13671
|
+
(0, import_node_fs8.rmSync)(temporary, { recursive: true, force: true });
|
|
13218
13672
|
}
|
|
13219
13673
|
}
|
|
13220
13674
|
return {
|
|
@@ -13222,10 +13676,10 @@ async function generatePluginPackage(cwd, selections, expectedPacker) {
|
|
|
13222
13676
|
spec: `file:./${GENERATED_PLUGIN_DIRECTORY}/plugin-${digest}.tgz`,
|
|
13223
13677
|
subpaths,
|
|
13224
13678
|
packer,
|
|
13225
|
-
sha256: `sha256:${(0,
|
|
13679
|
+
sha256: `sha256:${(0, import_node_crypto4.createHash)("sha256").update(bytes).digest("hex")}`
|
|
13226
13680
|
};
|
|
13227
13681
|
} finally {
|
|
13228
|
-
(0,
|
|
13682
|
+
(0, import_node_fs8.rmSync)(stage, { recursive: true, force: true });
|
|
13229
13683
|
}
|
|
13230
13684
|
}
|
|
13231
13685
|
|
|
@@ -13234,6 +13688,42 @@ function pluginNpmDependencies(manifest2) {
|
|
|
13234
13688
|
return manifest2.integration?.npmDependencies ?? (manifest2.integration?.npm ? [manifest2.integration.npm] : []);
|
|
13235
13689
|
}
|
|
13236
13690
|
|
|
13691
|
+
// packages/plugin/src/prepared/invocation.ts
|
|
13692
|
+
var import_common3 = __toESM(require_dist2());
|
|
13693
|
+
var import_schema5 = __toESM(require_dist());
|
|
13694
|
+
|
|
13695
|
+
// packages/plugin/src/prepared/runtime.ts
|
|
13696
|
+
var import_node_fs9 = require("node:fs");
|
|
13697
|
+
var import_node_path9 = require("node:path");
|
|
13698
|
+
var import_tar2 = require("tar");
|
|
13699
|
+
var import_common2 = __toESM(require_dist2());
|
|
13700
|
+
var import_schema4 = __toESM(require_dist());
|
|
13701
|
+
function preparedRuntime(directory) {
|
|
13702
|
+
const path = (0, import_node_path9.join)(directory, BUILD_RECORD);
|
|
13703
|
+
if (!(0, import_node_fs9.existsSync)(path)) return;
|
|
13704
|
+
const record = JSON.parse((0, import_node_fs9.readFileSync)(path, "utf8"));
|
|
13705
|
+
if (record.runtime === void 0) return;
|
|
13706
|
+
return import_schema4.PreparedPluginRuntime.parse(record.runtime);
|
|
13707
|
+
}
|
|
13708
|
+
function assertPreparedRuntime(runtime) {
|
|
13709
|
+
const libc = process.platform === "linux" && process.report.getReport().header?.glibcVersionRuntime ? "glibc" : "musl";
|
|
13710
|
+
if (Number(process.versions.node.split(".")[0]) !== runtime.nodeMajor || runtime.platform !== "portable" && (runtime.platform !== process.platform || runtime.arch !== process.arch || runtime.platform === "linux" && runtime.libc !== libc))
|
|
13711
|
+
throw new Error("Prepared plugin runtime is incompatible; rebuild for this Node/platform/architecture/libc");
|
|
13712
|
+
}
|
|
13713
|
+
|
|
13714
|
+
// packages/plugin/src/prepared/invocation.ts
|
|
13715
|
+
function usesPreparedRunner(directory) {
|
|
13716
|
+
if (import_common3.PROCESS_ENV.OCTONODE_PLUGIN_RUNNER !== "true") return false;
|
|
13717
|
+
const runtime = preparedRuntime(directory);
|
|
13718
|
+
if (!runtime) return false;
|
|
13719
|
+
assertPreparedRuntime(runtime);
|
|
13720
|
+
const { manifest: manifest2 } = verifyBuild(directory);
|
|
13721
|
+
return !manifest2.permissions.some((permission) => permission.resource === "project_data");
|
|
13722
|
+
}
|
|
13723
|
+
function preparedPluginPin(directory, pin) {
|
|
13724
|
+
return !!pin?.installId && !!pin.registry && pin.registry.replace(/\/$/, "") === ((0, import_common3.OCTONODE_MARKETPLACE_URL)() ?? import_common3.DEFAULT_MARKETPLACE_URL).replace(/\/$/, "") && usesPreparedRunner(directory);
|
|
13725
|
+
}
|
|
13726
|
+
|
|
13237
13727
|
// packages/plugin/src/lifecycle.ts
|
|
13238
13728
|
async function reconcilePluginLock(cwd, next, options = {}) {
|
|
13239
13729
|
const project = resolveDependencyProject(cwd);
|
|
@@ -13243,21 +13733,21 @@ async function reconcilePluginLock(cwd, next, options = {}) {
|
|
|
13243
13733
|
const manifest2 = loadPluginManifest(directory);
|
|
13244
13734
|
if (manifest2.id !== (pin.pluginId ?? alias) || manifest2.version !== pin.version || hashPluginDir(directory) !== pin.sha256)
|
|
13245
13735
|
throw new Error(`Plugin identity or integrity mismatch: ${alias}`);
|
|
13246
|
-
return { alias, directory, sha256: pin.sha256, manifest: manifest2 };
|
|
13736
|
+
return { alias, directory, sha256: pin.sha256, manifest: manifest2, remote: preparedPluginPin(directory, pin) };
|
|
13247
13737
|
});
|
|
13248
13738
|
const libraries = loaded.filter((item) => item.manifest.library);
|
|
13249
13739
|
const generated = libraries.length ? await generatePluginPackage(project.target, libraries) : void 0;
|
|
13250
|
-
const packageFile = (0,
|
|
13251
|
-
const packageJson = (0,
|
|
13740
|
+
const packageFile = (0, import_node_path10.join)(project.target, "package.json");
|
|
13741
|
+
const packageJson = (0, import_node_fs10.existsSync)(packageFile) ? JSON.parse((0, import_node_fs10.readFileSync)(packageFile, "utf8")) : {};
|
|
13252
13742
|
const declared = { ...packageJson.devDependencies, ...packageJson.optionalDependencies, ...packageJson.dependencies };
|
|
13253
13743
|
if (generated && declared[generated.name] && declared[generated.name].replace(/^file:\.\//, "file:") !== before.generated?.spec.replace(/^file:\.\//, "file:") && !options.migrate)
|
|
13254
13744
|
throw new Error(
|
|
13255
13745
|
"Existing @octonodes/plugin dependency is not managed by this lock; pass --migrate to replace it explicitly"
|
|
13256
13746
|
);
|
|
13257
|
-
const dependencies = loaded.flatMap(
|
|
13747
|
+
const dependencies = loaded.filter((item) => !item.remote || item.manifest.library).flatMap(
|
|
13258
13748
|
({ manifest: manifest2 }) => pluginNpmDependencies(manifest2).map((npm) => {
|
|
13259
13749
|
const spec = npm.spec.startsWith(`${npm.package}@`) ? npm.spec.slice(npm.package.length + 1) : npm.spec;
|
|
13260
|
-
const sameLocal = typeof declared[npm.package] === "string" && declared[npm.package].startsWith("file:") && spec.startsWith("file:") && (0,
|
|
13750
|
+
const sameLocal = typeof declared[npm.package] === "string" && declared[npm.package].startsWith("file:") && spec.startsWith("file:") && (0, import_node_path10.resolve)(project.target, declared[npm.package].slice(5)) === (0, import_node_path10.resolve)(project.target, spec.slice(5));
|
|
13261
13751
|
if (declared[npm.package] && declared[npm.package] !== spec && !sameLocal)
|
|
13262
13752
|
throw new Error(
|
|
13263
13753
|
`Dependency conflict: ${npm.package} is ${declared[npm.package]}, plugin requires ${spec}; reconcile it explicitly first`
|
|
@@ -13276,6 +13766,7 @@ async function reconcilePluginLock(cwd, next, options = {}) {
|
|
|
13276
13766
|
if (generated || before.generated || unique.length || options.commit) {
|
|
13277
13767
|
await reconcileDependencies(project.target, [...unique, ...generated ? [generated] : []], {
|
|
13278
13768
|
cacheRoot: options.cacheRoot,
|
|
13769
|
+
metadataOnly: !generated && !before.generated && !unique.length,
|
|
13279
13770
|
remove: !generated && before.generated ? [before.generated.name] : void 0,
|
|
13280
13771
|
transactionFiles: [lockfilePath(cwd), ...options.transactionFiles ?? []],
|
|
13281
13772
|
commit: () => {
|
|
@@ -13318,20 +13809,20 @@ async function removePluginPin(alias, options = {}) {
|
|
|
13318
13809
|
}
|
|
13319
13810
|
|
|
13320
13811
|
// packages/plugin/src/restore.ts
|
|
13321
|
-
var
|
|
13322
|
-
var
|
|
13812
|
+
var import_node_fs14 = require("node:fs");
|
|
13813
|
+
var import_node_path14 = require("node:path");
|
|
13323
13814
|
|
|
13324
|
-
// packages/plugin/src/remote
|
|
13325
|
-
var
|
|
13326
|
-
var
|
|
13327
|
-
var
|
|
13815
|
+
// packages/plugin/src/remote/registry.ts
|
|
13816
|
+
var import_node_fs13 = require("node:fs");
|
|
13817
|
+
var import_node_os6 = require("node:os");
|
|
13818
|
+
var import_node_path13 = require("node:path");
|
|
13328
13819
|
|
|
13329
13820
|
// packages/plugin/src/install.ts
|
|
13330
|
-
var
|
|
13331
|
-
var
|
|
13821
|
+
var import_node_fs11 = require("node:fs");
|
|
13822
|
+
var import_node_path11 = require("node:path");
|
|
13332
13823
|
var import_node_child_process2 = require("node:child_process");
|
|
13333
13824
|
var import_node_util2 = require("node:util");
|
|
13334
|
-
var
|
|
13825
|
+
var import_common4 = __toESM(require_dist2());
|
|
13335
13826
|
function commandError(err) {
|
|
13336
13827
|
const error = err;
|
|
13337
13828
|
return [error.stderr, error.stdout].map((output) => output?.toString().trim()).find(Boolean) ?? error.message;
|
|
@@ -13347,7 +13838,7 @@ async function installNodeDeps(dir, opts = {}) {
|
|
|
13347
13838
|
if (opts.cacheOnly) {
|
|
13348
13839
|
for (const npm of dependencies)
|
|
13349
13840
|
await (0, import_node_util2.promisify)(import_node_child_process2.execFile)("npm", ["cache", "add", "--ignore-scripts", "--", npm.spec], {
|
|
13350
|
-
env: (0,
|
|
13841
|
+
env: (0, import_common4.childProcessEnvironment)((0, import_common4.packageCacheEnvironment)(dependencyCacheRoot(opts.cacheRoot))),
|
|
13351
13842
|
timeout: 10 * 6e4
|
|
13352
13843
|
});
|
|
13353
13844
|
return {};
|
|
@@ -13364,9 +13855,9 @@ async function installNodeDeps(dir, opts = {}) {
|
|
|
13364
13855
|
return { depsInstalled: false, depsError: commandError(err) };
|
|
13365
13856
|
}
|
|
13366
13857
|
}
|
|
13367
|
-
const pjPath = (0,
|
|
13368
|
-
if (!(0,
|
|
13369
|
-
const pj = JSON.parse((0,
|
|
13858
|
+
const pjPath = (0, import_node_path11.join)(dir, "package.json");
|
|
13859
|
+
if (!(0, import_node_fs11.existsSync)(pjPath)) return {};
|
|
13860
|
+
const pj = JSON.parse((0, import_node_fs11.readFileSync)(pjPath, "utf8"));
|
|
13370
13861
|
if (!pj.dependencies && !pj.optionalDependencies) return {};
|
|
13371
13862
|
try {
|
|
13372
13863
|
await (0, import_node_util2.promisify)(import_node_child_process2.execFile)(
|
|
@@ -13382,7 +13873,7 @@ async function installNodeDeps(dir, opts = {}) {
|
|
|
13382
13873
|
],
|
|
13383
13874
|
{
|
|
13384
13875
|
cwd: dir,
|
|
13385
|
-
env: (0,
|
|
13876
|
+
env: (0, import_common4.childProcessEnvironment)((0, import_common4.packageCacheEnvironment)(dependencyCacheRoot(opts.cacheRoot))),
|
|
13386
13877
|
timeout: 10 * 6e4
|
|
13387
13878
|
}
|
|
13388
13879
|
);
|
|
@@ -13392,7 +13883,7 @@ async function installNodeDeps(dir, opts = {}) {
|
|
|
13392
13883
|
}
|
|
13393
13884
|
}
|
|
13394
13885
|
async function installPlugin(src, opts = {}) {
|
|
13395
|
-
if (!(0,
|
|
13886
|
+
if (!(0, import_node_fs11.existsSync)(src) || !(0, import_node_fs11.statSync)(src).isDirectory()) {
|
|
13396
13887
|
throw new Error(`source "${src}" is not a directory`);
|
|
13397
13888
|
}
|
|
13398
13889
|
if (!isPluginDir(src)) {
|
|
@@ -13400,17 +13891,17 @@ async function installPlugin(src, opts = {}) {
|
|
|
13400
13891
|
}
|
|
13401
13892
|
const { manifest: manifest2 } = loadPlugin(src);
|
|
13402
13893
|
const { root, source } = installRoot(opts);
|
|
13403
|
-
const dest = (0,
|
|
13404
|
-
if ((0,
|
|
13894
|
+
const dest = (0, import_node_path11.join)(root, manifest2.id);
|
|
13895
|
+
if ((0, import_node_fs11.existsSync)(dest)) {
|
|
13405
13896
|
if (!opts.force) {
|
|
13406
13897
|
throw new Error(`plugin "${manifest2.id}" is already installed at ${dest} (use --force to overwrite)`);
|
|
13407
13898
|
}
|
|
13408
13899
|
}
|
|
13409
13900
|
const deps = pluginNpmDependencies(manifest2).length ? await installNodeDeps(src, { ...opts, cacheOnly: opts.cacheOnly ?? !opts.project }) : {};
|
|
13410
13901
|
if (deps.depsError) return { manifest: manifest2, dir: dest, source, ...deps };
|
|
13411
|
-
if ((0,
|
|
13412
|
-
(0,
|
|
13413
|
-
(0,
|
|
13902
|
+
if ((0, import_node_fs11.existsSync)(dest)) (0, import_node_fs11.rmSync)(dest, { recursive: true, force: true });
|
|
13903
|
+
(0, import_node_fs11.mkdirSync)(root, { recursive: true });
|
|
13904
|
+
(0, import_node_fs11.cpSync)(src, dest, { recursive: true });
|
|
13414
13905
|
return {
|
|
13415
13906
|
manifest: manifest2,
|
|
13416
13907
|
dir: dest,
|
|
@@ -13420,14 +13911,14 @@ async function installPlugin(src, opts = {}) {
|
|
|
13420
13911
|
};
|
|
13421
13912
|
}
|
|
13422
13913
|
|
|
13423
|
-
// packages/plugin/src/remote
|
|
13424
|
-
var
|
|
13914
|
+
// packages/plugin/src/remote/registry.ts
|
|
13915
|
+
var import_common5 = __toESM(require_dist2());
|
|
13425
13916
|
|
|
13426
13917
|
// packages/plugin/src/archive.ts
|
|
13427
13918
|
var import_node_zlib2 = require("node:zlib");
|
|
13428
|
-
var
|
|
13429
|
-
var
|
|
13430
|
-
var
|
|
13919
|
+
var import_node_fs12 = require("node:fs");
|
|
13920
|
+
var import_node_path12 = require("node:path");
|
|
13921
|
+
var import_tar3 = require("tar");
|
|
13431
13922
|
|
|
13432
13923
|
// packages/plugin/src/archive.constants.ts
|
|
13433
13924
|
var PLUGIN_ARCHIVE_MAX_BYTES = 64 * 1024 * 1024;
|
|
@@ -13437,11 +13928,11 @@ var PLUGIN_ARCHIVE_MAX_FILES = 1e4;
|
|
|
13437
13928
|
function extractPluginArchive(bytes, stage) {
|
|
13438
13929
|
if (bytes.length > PLUGIN_ARCHIVE_MAX_BYTES) throw new Error("Plugin archive exceeds download limit");
|
|
13439
13930
|
const decoded = (0, import_node_zlib2.gunzipSync)(bytes, { maxOutputLength: PLUGIN_ARCHIVE_MAX_BYTES });
|
|
13440
|
-
const archive = (0,
|
|
13441
|
-
(0,
|
|
13931
|
+
const archive = (0, import_node_path12.join)(stage, "bundle.tar");
|
|
13932
|
+
(0, import_node_fs12.writeFileSync)(archive, decoded);
|
|
13442
13933
|
const seen = /* @__PURE__ */ new Set();
|
|
13443
13934
|
let total = 0;
|
|
13444
|
-
(0,
|
|
13935
|
+
(0, import_tar3.list)({
|
|
13445
13936
|
file: archive,
|
|
13446
13937
|
sync: true,
|
|
13447
13938
|
strict: true,
|
|
@@ -13458,9 +13949,9 @@ function extractPluginArchive(bytes, stage) {
|
|
|
13458
13949
|
throw new Error("Plugin archive exceeds extraction limits");
|
|
13459
13950
|
}
|
|
13460
13951
|
});
|
|
13461
|
-
const output = (0,
|
|
13462
|
-
(0,
|
|
13463
|
-
(0,
|
|
13952
|
+
const output = (0, import_node_path12.join)(stage, "plugin");
|
|
13953
|
+
(0, import_node_fs12.mkdirSync)(output);
|
|
13954
|
+
(0, import_tar3.extract)({
|
|
13464
13955
|
file: archive,
|
|
13465
13956
|
cwd: output,
|
|
13466
13957
|
sync: true,
|
|
@@ -13473,11 +13964,12 @@ function extractPluginArchive(bytes, stage) {
|
|
|
13473
13964
|
return output;
|
|
13474
13965
|
}
|
|
13475
13966
|
|
|
13476
|
-
// packages/plugin/src/remote
|
|
13477
|
-
var
|
|
13967
|
+
// packages/plugin/src/remote/registry.ts
|
|
13968
|
+
var import_tar4 = require("tar");
|
|
13969
|
+
var import_node_crypto5 = require("node:crypto");
|
|
13478
13970
|
var RemoteRegistry = class {
|
|
13479
13971
|
constructor(opts = {}) {
|
|
13480
|
-
const baseUrl = opts.baseUrl ?? (0,
|
|
13972
|
+
const baseUrl = opts.baseUrl ?? (0, import_common5.OCTONODE_MARKETPLACE_URL)() ?? import_common5.DEFAULT_MARKETPLACE_URL;
|
|
13481
13973
|
if (!baseUrl) {
|
|
13482
13974
|
throw new Error("marketplace URL is not configured (set OCTONODE_MARKETPLACE_URL or pass baseUrl)");
|
|
13483
13975
|
}
|
|
@@ -13487,7 +13979,7 @@ var RemoteRegistry = class {
|
|
|
13487
13979
|
);
|
|
13488
13980
|
}
|
|
13489
13981
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
13490
|
-
this.token = opts.token ?? (0,
|
|
13982
|
+
this.token = opts.token ?? (0, import_common5.OCTONODE_MARKETPLACE_TOKEN)();
|
|
13491
13983
|
}
|
|
13492
13984
|
async request(path, init = {}) {
|
|
13493
13985
|
const headers = new Headers(init.headers);
|
|
@@ -13504,19 +13996,49 @@ var RemoteRegistry = class {
|
|
|
13504
13996
|
}
|
|
13505
13997
|
return res;
|
|
13506
13998
|
}
|
|
13999
|
+
async searchPage(filter = {}, offset = 0, limit = 24) {
|
|
14000
|
+
const params = new URLSearchParams({ offset: String(offset), limit: String(limit) });
|
|
14001
|
+
for (const [key, value] of Object.entries(filter)) if (value !== void 0) params.set(key, value);
|
|
14002
|
+
const res = await this.request(`/marketplace/plugins?${params}`);
|
|
14003
|
+
return await res.json();
|
|
14004
|
+
}
|
|
13507
14005
|
async search(filter = {}) {
|
|
13508
|
-
|
|
13509
|
-
for (
|
|
13510
|
-
|
|
13511
|
-
|
|
13512
|
-
|
|
13513
|
-
|
|
14006
|
+
let entries = [];
|
|
14007
|
+
for (; ; ) {
|
|
14008
|
+
const page = await this.searchPage(filter, entries.length, 100);
|
|
14009
|
+
entries = [...entries, ...page.entries];
|
|
14010
|
+
if (!page.entries.length || page.total === void 0 || entries.length >= page.total) return entries;
|
|
14011
|
+
}
|
|
13514
14012
|
}
|
|
13515
14013
|
async detail(id, scope) {
|
|
13516
14014
|
const query = scope ? `?scope=${encodeURIComponent(scope)}` : "";
|
|
13517
14015
|
const res = await this.request(`/marketplace/plugins/${encodeURIComponent(id)}${query}`);
|
|
13518
14016
|
return await res.json();
|
|
13519
14017
|
}
|
|
14018
|
+
/** Reauthorize an immutable pin, including older locks that only recorded the extracted tree hash. */
|
|
14019
|
+
async matchesLockedRelease(id, pin) {
|
|
14020
|
+
const remoteId = pin.remoteId ?? id;
|
|
14021
|
+
const detail = await this.detail(remoteId, pin.scope);
|
|
14022
|
+
const release2 = detail.versions.find((entry) => entry.version === pin.version);
|
|
14023
|
+
if (!release2 || pin.publisher && release2.publishedBy !== pin.publisher) return false;
|
|
14024
|
+
const checksum = release2.archiveSha256 ?? release2.sha256;
|
|
14025
|
+
if (pin.archiveSha256 || checksum?.startsWith("sha256:")) return checksum === (pin.archiveSha256 ?? pin.sha256);
|
|
14026
|
+
if (!/^[a-f0-9]{64}$/.test(checksum)) return false;
|
|
14027
|
+
const directory = await this.downloadBundle(remoteId, pin.version, pin.scope, id, checksum);
|
|
14028
|
+
try {
|
|
14029
|
+
return hashPluginDir(directory) === pin.sha256;
|
|
14030
|
+
} finally {
|
|
14031
|
+
(0, import_node_fs13.rmSync)((0, import_node_path13.dirname)(directory), { recursive: true, force: true });
|
|
14032
|
+
}
|
|
14033
|
+
}
|
|
14034
|
+
async registerInstall(id, version, scope, opts) {
|
|
14035
|
+
const response = await this.request(`/marketplace/plugins/${encodeURIComponent(id)}/install`, {
|
|
14036
|
+
method: "POST",
|
|
14037
|
+
headers: { "content-type": "application/json" },
|
|
14038
|
+
body: JSON.stringify({ version, scope, ownerId: opts.ownerId, environment: opts.environment ?? "self_hosted" })
|
|
14039
|
+
});
|
|
14040
|
+
return (await response.json()).installId;
|
|
14041
|
+
}
|
|
13520
14042
|
/**
|
|
13521
14043
|
* Pack a plugin folder into a tarball and publish it (metadata + bundle).
|
|
13522
14044
|
* `orgId` names the org an org/group-scoped version belongs to; `teamId`
|
|
@@ -13526,6 +14048,13 @@ var RemoteRegistry = class {
|
|
|
13526
14048
|
*/
|
|
13527
14049
|
async publish(pluginDir, opts = {}) {
|
|
13528
14050
|
const manifest2 = loadPluginManifest(pluginDir);
|
|
14051
|
+
const packageFile = (0, import_node_path13.join)(pluginDir, "package.json");
|
|
14052
|
+
if ((0, import_node_fs13.existsSync)(packageFile)) {
|
|
14053
|
+
const metadata = JSON.parse((0, import_node_fs13.readFileSync)(packageFile, "utf8"));
|
|
14054
|
+
if (metadata.version && metadata.version !== manifest2.version) {
|
|
14055
|
+
throw new Error("package.json version must match the plugin version before publishing");
|
|
14056
|
+
}
|
|
14057
|
+
}
|
|
13529
14058
|
const bundle = packPluginDir(pluginDir);
|
|
13530
14059
|
const form = new FormData();
|
|
13531
14060
|
form.set("manifest", JSON.stringify(manifest2));
|
|
@@ -13536,10 +14065,14 @@ var RemoteRegistry = class {
|
|
|
13536
14065
|
method: "POST",
|
|
13537
14066
|
body: form
|
|
13538
14067
|
});
|
|
13539
|
-
|
|
14068
|
+
const release2 = await res.json();
|
|
14069
|
+
const digest = (0, import_node_crypto5.createHash)("sha256").update(bundle).digest("hex");
|
|
14070
|
+
if (release2.sha256 !== digest || release2.archiveSha256 !== void 0 && release2.archiveSha256 !== digest)
|
|
14071
|
+
throw new Error("Marketplace published archive checksum mismatch; check the release before publishing again");
|
|
14072
|
+
return release2;
|
|
13540
14073
|
}
|
|
13541
14074
|
/** Download a version's bundle and extract it to a fresh temp folder. */
|
|
13542
|
-
async downloadBundle(id, version, scope, expectedId = id) {
|
|
14075
|
+
async downloadBundle(id, version, scope, expectedId = id, expectedChecksum) {
|
|
13543
14076
|
const query = scope ? `?scope=${encodeURIComponent(scope)}` : "";
|
|
13544
14077
|
const res = await this.request(
|
|
13545
14078
|
`/marketplace/plugins/${encodeURIComponent(id)}/versions/${encodeURIComponent(version)}/bundle${query}`
|
|
@@ -13560,17 +14093,27 @@ var RemoteRegistry = class {
|
|
|
13560
14093
|
await reader.cancel();
|
|
13561
14094
|
}
|
|
13562
14095
|
const bytes = Buffer.concat(chunks);
|
|
13563
|
-
const
|
|
14096
|
+
const archiveChecksum = res.headers.get("x-octonode-archive-sha256");
|
|
14097
|
+
if (archiveChecksum !== null && !/^[a-f0-9]{64}$/.test(archiveChecksum))
|
|
14098
|
+
throw new Error("Plugin registry archive checksum is invalid");
|
|
14099
|
+
const checksums = [archiveChecksum, res.headers.get("x-octonode-sha256"), expectedChecksum].filter(
|
|
14100
|
+
(checksum) => !!checksum
|
|
14101
|
+
);
|
|
14102
|
+
const digest = (0, import_node_crypto5.createHash)("sha256").update(bytes).digest("hex");
|
|
14103
|
+
for (const expected of checksums)
|
|
14104
|
+
if (/^[a-f0-9]{64}$/.test(expected) && expected !== digest) throw new Error("Plugin registry checksum mismatch");
|
|
14105
|
+
const dir = (0, import_node_fs13.mkdtempSync)((0, import_node_path13.join)((0, import_node_os6.tmpdir)(), "octo-bundle-"));
|
|
13564
14106
|
try {
|
|
13565
14107
|
const extracted = extractPluginArchive(bytes, dir);
|
|
13566
14108
|
const manifest2 = loadPluginManifest(extracted);
|
|
13567
14109
|
if (manifest2.id !== expectedId || manifest2.version !== version)
|
|
13568
14110
|
throw new Error(`Downloaded plugin does not match requested ${id}@${version}`);
|
|
13569
|
-
const
|
|
13570
|
-
|
|
14111
|
+
for (const expected of checksums)
|
|
14112
|
+
if (!/^[a-f0-9]{64}$/.test(expected) && hashPluginDir(extracted) !== expected)
|
|
14113
|
+
throw new Error("Plugin registry checksum mismatch");
|
|
13571
14114
|
return extracted;
|
|
13572
14115
|
} catch (error) {
|
|
13573
|
-
(0,
|
|
14116
|
+
(0, import_node_fs13.rmSync)(dir, { recursive: true, force: true });
|
|
13574
14117
|
throw error;
|
|
13575
14118
|
}
|
|
13576
14119
|
}
|
|
@@ -13582,7 +14125,14 @@ var RemoteRegistry = class {
|
|
|
13582
14125
|
async install(id, opts = {}) {
|
|
13583
14126
|
const detail = await this.detail(id, opts.scope);
|
|
13584
14127
|
const version = opts.version ?? detail.version;
|
|
13585
|
-
const
|
|
14128
|
+
const release2 = detail.versions?.find((entry) => entry.version === version);
|
|
14129
|
+
const dir = await this.downloadBundle(
|
|
14130
|
+
id,
|
|
14131
|
+
version,
|
|
14132
|
+
opts.scope,
|
|
14133
|
+
id,
|
|
14134
|
+
release2?.archiveSha256 ?? release2?.sha256
|
|
14135
|
+
);
|
|
13586
14136
|
const plugin = await installPlugin(dir, opts);
|
|
13587
14137
|
const res = await this.request(`/marketplace/plugins/${encodeURIComponent(id)}/install`, {
|
|
13588
14138
|
method: "POST",
|
|
@@ -13608,19 +14158,21 @@ var RemoteRegistry = class {
|
|
|
13608
14158
|
const detail = await this.detail(id, opts.scope);
|
|
13609
14159
|
const version = opts.version ?? detail.version;
|
|
13610
14160
|
const versionMeta = detail.versions?.find((v) => v.version === version);
|
|
13611
|
-
|
|
14161
|
+
const releaseChecksum = versionMeta?.archiveSha256 ?? versionMeta?.sha256;
|
|
14162
|
+
if (!opts.cacheOnly && !opts.noDeps && !releaseChecksum)
|
|
13612
14163
|
throw new Error("Marketplace release is missing its immutable checksum");
|
|
13613
14164
|
const availableScopes = versionMeta?.scope ?? detail.scope;
|
|
13614
14165
|
const scope = opts.scope && availableScopes.includes(opts.scope) ? opts.scope : availableScopes[0];
|
|
13615
|
-
const dir = await this.downloadBundle(id, version, scope);
|
|
14166
|
+
const dir = await this.downloadBundle(id, version, scope, id, releaseChecksum);
|
|
13616
14167
|
const entry = (() => {
|
|
13617
14168
|
try {
|
|
13618
14169
|
return addToStore(dir, { storeRoot: opts.storeRoot });
|
|
13619
14170
|
} finally {
|
|
13620
|
-
(0,
|
|
14171
|
+
(0, import_node_fs13.rmSync)((0, import_node_path13.dirname)(dir), { recursive: true, force: true });
|
|
13621
14172
|
}
|
|
13622
14173
|
})();
|
|
13623
|
-
|
|
14174
|
+
const archiveSha256 = releaseChecksum && /^[a-f0-9]{64}$/.test(releaseChecksum) ? releaseChecksum : void 0;
|
|
14175
|
+
const prepared = this.baseUrl === ((0, import_common5.OCTONODE_MARKETPLACE_URL)() ?? import_common5.DEFAULT_MARKETPLACE_URL).replace(/\/$/, "") && usesPreparedRunner(entry.dir);
|
|
13624
14176
|
if (entry.manifest.library && opts.noDeps && !opts.cacheOnly)
|
|
13625
14177
|
throw new Error(
|
|
13626
14178
|
"Library installation requires native dependency activation; use frozen --artifacts-only for CI restore"
|
|
@@ -13632,26 +14184,29 @@ var RemoteRegistry = class {
|
|
|
13632
14184
|
remoteId: id,
|
|
13633
14185
|
version: entry.version,
|
|
13634
14186
|
sha256: entry.sha256,
|
|
14187
|
+
archiveSha256,
|
|
13635
14188
|
registry: this.baseUrl,
|
|
13636
14189
|
scope,
|
|
13637
14190
|
permissions: versionMeta?.permissions ?? detail.permissions,
|
|
13638
14191
|
publisher: versionMeta?.publishedBy
|
|
13639
14192
|
};
|
|
13640
|
-
await activatePluginPin(alias2, pin2, opts);
|
|
13641
14193
|
let installId2 = "";
|
|
13642
|
-
if (!opts.dryRun) {
|
|
14194
|
+
if (prepared && !opts.dryRun) {
|
|
14195
|
+
installId2 = await this.registerInstall(id, version, scope, { ...opts, environment: "cloud" });
|
|
14196
|
+
if (!installId2 || !/^[a-f0-9-]{36}$/.test(installId2))
|
|
14197
|
+
throw new Error("Marketplace did not authorize the prepared installation");
|
|
14198
|
+
pin2.installId = installId2;
|
|
14199
|
+
}
|
|
14200
|
+
try {
|
|
14201
|
+
await activatePluginPin(alias2, pin2, opts);
|
|
14202
|
+
} catch (error) {
|
|
14203
|
+
if (installId2) await this.postEvent(installId2, "uninstall").catch(() => {
|
|
14204
|
+
});
|
|
14205
|
+
throw error;
|
|
14206
|
+
}
|
|
14207
|
+
if (!opts.dryRun && !prepared) {
|
|
13643
14208
|
try {
|
|
13644
|
-
|
|
13645
|
-
method: "POST",
|
|
13646
|
-
headers: { "content-type": "application/json" },
|
|
13647
|
-
body: JSON.stringify({
|
|
13648
|
-
version,
|
|
13649
|
-
scope,
|
|
13650
|
-
ownerId: opts.ownerId,
|
|
13651
|
-
environment: opts.environment ?? "self_hosted"
|
|
13652
|
-
})
|
|
13653
|
-
});
|
|
13654
|
-
installId2 = (await response.json()).installId;
|
|
14209
|
+
installId2 = await this.registerInstall(id, version, scope, opts);
|
|
13655
14210
|
if (installId2)
|
|
13656
14211
|
await withDependencyInstall(opts.cwd ?? process.cwd(), async () => {
|
|
13657
14212
|
const current = readLockfile(opts.cwd).plugins[alias2];
|
|
@@ -13665,10 +14220,10 @@ var RemoteRegistry = class {
|
|
|
13665
14220
|
plugin: { manifest: entry.manifest, dir: entry.dir, source: "store" },
|
|
13666
14221
|
entry,
|
|
13667
14222
|
installId: installId2,
|
|
13668
|
-
depsInstalled: !opts.dryRun
|
|
14223
|
+
depsInstalled: !opts.dryRun && (!prepared || !!entry.manifest.library)
|
|
13669
14224
|
};
|
|
13670
14225
|
}
|
|
13671
|
-
const deps = entry.created || entry.manifest.integration?.npm ? await installNodeDeps(entry.dir, {
|
|
14226
|
+
const deps = !prepared && (entry.created || entry.manifest.integration?.npm) ? await installNodeDeps(entry.dir, {
|
|
13672
14227
|
noDeps: opts.noDeps,
|
|
13673
14228
|
cwd: opts.cwd,
|
|
13674
14229
|
cacheRoot: opts.cacheRoot,
|
|
@@ -13681,25 +14236,36 @@ var RemoteRegistry = class {
|
|
|
13681
14236
|
remoteId: id,
|
|
13682
14237
|
version: entry.version,
|
|
13683
14238
|
sha256: entry.sha256,
|
|
14239
|
+
archiveSha256,
|
|
13684
14240
|
registry: this.baseUrl,
|
|
13685
14241
|
scope,
|
|
13686
14242
|
publisher: versionMeta?.publishedBy,
|
|
13687
14243
|
permissions: versionMeta?.permissions ?? detail.permissions
|
|
13688
14244
|
};
|
|
13689
|
-
|
|
13690
|
-
|
|
13691
|
-
if (previous && ((previous.pluginId ?? alias) !== entry.id || previous.registry !== this.baseUrl || previous.publisher !== pin.publisher))
|
|
13692
|
-
throw new Error("Plugin alias belongs to another publisher or registry");
|
|
13693
|
-
upsertLockEntry(opts.cwd ?? process.cwd(), alias, pin);
|
|
13694
|
-
});
|
|
14245
|
+
if (opts.dryRun)
|
|
14246
|
+
return { plugin: { manifest: entry.manifest, dir: entry.dir, source: "store" }, entry, installId: "" };
|
|
13695
14247
|
let installId = "";
|
|
14248
|
+
if (prepared) {
|
|
14249
|
+
installId = await this.registerInstall(id, version, scope, { ...opts, environment: "cloud" });
|
|
14250
|
+
if (!installId || !/^[a-f0-9-]{36}$/.test(installId))
|
|
14251
|
+
throw new Error("Marketplace did not authorize the prepared installation");
|
|
14252
|
+
pin.installId = installId;
|
|
14253
|
+
}
|
|
13696
14254
|
try {
|
|
13697
|
-
|
|
13698
|
-
|
|
13699
|
-
|
|
13700
|
-
|
|
14255
|
+
await withDependencyInstall(opts.cwd ?? process.cwd(), async () => {
|
|
14256
|
+
const previous = readLockfile(opts.cwd).plugins[alias];
|
|
14257
|
+
if (previous && ((previous.pluginId ?? alias) !== entry.id || previous.registry !== this.baseUrl || previous.publisher !== pin.publisher))
|
|
14258
|
+
throw new Error("Plugin alias belongs to another publisher or registry");
|
|
14259
|
+
upsertLockEntry(opts.cwd ?? process.cwd(), alias, pin);
|
|
14260
|
+
});
|
|
14261
|
+
} catch (error) {
|
|
14262
|
+
if (installId) await this.postEvent(installId, "uninstall").catch(() => {
|
|
13701
14263
|
});
|
|
13702
|
-
|
|
14264
|
+
throw error;
|
|
14265
|
+
}
|
|
14266
|
+
if (prepared) return { plugin: { manifest: entry.manifest, dir: entry.dir, source: "store" }, entry, installId };
|
|
14267
|
+
try {
|
|
14268
|
+
installId = await this.registerInstall(id, version, scope, opts);
|
|
13703
14269
|
await withDependencyInstall(opts.cwd ?? process.cwd(), async () => {
|
|
13704
14270
|
const current = readLockfile(opts.cwd).plugins[alias];
|
|
13705
14271
|
if (current?.sha256 === pin.sha256 && current.registry === pin.registry)
|
|
@@ -13725,13 +14291,13 @@ var RemoteRegistry = class {
|
|
|
13725
14291
|
};
|
|
13726
14292
|
function packPluginDir(pluginDir) {
|
|
13727
14293
|
pluginBundleFiles(pluginDir);
|
|
13728
|
-
const staging = (0,
|
|
13729
|
-
const out = (0,
|
|
14294
|
+
const staging = (0, import_node_fs13.mkdtempSync)((0, import_node_path13.join)((0, import_node_os6.tmpdir)(), "octo-pack-"));
|
|
14295
|
+
const out = (0, import_node_path13.join)(staging, "bundle.tar.gz");
|
|
13730
14296
|
try {
|
|
13731
|
-
(0,
|
|
13732
|
-
return (0,
|
|
14297
|
+
(0, import_tar4.create)({ file: out, cwd: pluginDir, sync: true, portable: true, gzip: true }, pluginBundleFiles(pluginDir));
|
|
14298
|
+
return (0, import_node_fs13.readFileSync)(out);
|
|
13733
14299
|
} finally {
|
|
13734
|
-
(0,
|
|
14300
|
+
(0, import_node_fs13.rmSync)(staging, { recursive: true, force: true });
|
|
13735
14301
|
}
|
|
13736
14302
|
}
|
|
13737
14303
|
|
|
@@ -13739,7 +14305,7 @@ function packPluginDir(pluginDir) {
|
|
|
13739
14305
|
async function installFromLock(opts = {}) {
|
|
13740
14306
|
const cwd = resolveDependencyProject(opts.cwd ?? process.cwd()).target;
|
|
13741
14307
|
if (opts.frozen && opts.force) throw new Error("Frozen restore cannot accept changed artifact bytes");
|
|
13742
|
-
if (opts.frozen && !(0,
|
|
14308
|
+
if (opts.frozen && !(0, import_node_fs14.existsSync)((0, import_node_path14.join)(cwd, "octonode.lock"))) throw new Error("Frozen restore requires octonode.lock");
|
|
13743
14309
|
return withDependencyInstall(cwd, async () => {
|
|
13744
14310
|
const lock = readLockfile(cwd);
|
|
13745
14311
|
if (lock.generated && opts.force)
|
|
@@ -13756,9 +14322,8 @@ async function installFromLock(opts = {}) {
|
|
|
13756
14322
|
throw new Error("Frozen restore cannot change the registry");
|
|
13757
14323
|
if (pin.scope && pin.scope !== "public" && registry) {
|
|
13758
14324
|
if (opts.offline) throw new Error("Private plugin access must be reauthorized online before restore");
|
|
13759
|
-
const
|
|
13760
|
-
|
|
13761
|
-
if (!version || version.sha256 !== pin.sha256 || pin.publisher && version.publishedBy !== pin.publisher)
|
|
14325
|
+
const remote = new RemoteRegistry({ baseUrl: registry, token: opts.token });
|
|
14326
|
+
if (!await remote.matchesLockedRelease(id, pin))
|
|
13762
14327
|
throw new Error("Locked private release is not authorized or changed");
|
|
13763
14328
|
}
|
|
13764
14329
|
let directory = storeEntryDir(id, pin.version, pin.sha256, opts.storeRoot);
|
|
@@ -13772,16 +14337,18 @@ async function installFromLock(opts = {}) {
|
|
|
13772
14337
|
remoteId,
|
|
13773
14338
|
pin.version,
|
|
13774
14339
|
pin.scope,
|
|
13775
|
-
id
|
|
14340
|
+
id,
|
|
14341
|
+
opts.force ? void 0 : pin.archiveSha256
|
|
13776
14342
|
);
|
|
13777
14343
|
try {
|
|
13778
14344
|
const actual = hashPluginDir(downloaded);
|
|
13779
14345
|
if (actual !== pin.sha256 && !opts.force) throw new Error("integrity mismatch for " + alias);
|
|
13780
14346
|
const entry = addToStore(downloaded, { storeRoot: opts.storeRoot });
|
|
13781
14347
|
directory = entry.dir;
|
|
13782
|
-
if (actual !== pin.sha256)
|
|
14348
|
+
if (actual !== pin.sha256)
|
|
14349
|
+
upsertLockEntry(cwd, alias, { ...pin, sha256: actual, archiveSha256: void 0 });
|
|
13783
14350
|
} finally {
|
|
13784
|
-
(0,
|
|
14351
|
+
(0, import_node_fs14.rmSync)((0, import_node_path14.dirname)(downloaded), { recursive: true, force: true });
|
|
13785
14352
|
}
|
|
13786
14353
|
result.restored.push(alias);
|
|
13787
14354
|
}
|
|
@@ -13789,9 +14356,10 @@ async function installFromLock(opts = {}) {
|
|
|
13789
14356
|
if (manifest2.id !== id || manifest2.version !== pin.version)
|
|
13790
14357
|
throw new Error("Plugin identity mismatch: " + alias);
|
|
13791
14358
|
if (manifest2.library) libraries.push({ alias, directory, sha256: pin.sha256 });
|
|
14359
|
+
if (!manifest2.library && preparedPluginPin(directory, pin)) continue;
|
|
13792
14360
|
if (!manifest2.library && !pluginNpmDependencies(manifest2).length && !opts.artifactsOnly && !opts.noDeps) {
|
|
13793
|
-
const packagePath = (0,
|
|
13794
|
-
const legacy = (0,
|
|
14361
|
+
const packagePath = (0, import_node_path14.join)(directory, "package.json");
|
|
14362
|
+
const legacy = (0, import_node_fs14.existsSync)(packagePath) ? JSON.parse((0, import_node_fs14.readFileSync)(packagePath, "utf8")) : {};
|
|
13795
14363
|
if (legacy.dependencies || legacy.optionalDependencies) {
|
|
13796
14364
|
if (opts.frozen || opts.offline)
|
|
13797
14365
|
throw new Error(
|
|
@@ -13818,7 +14386,7 @@ async function installFromLock(opts = {}) {
|
|
|
13818
14386
|
const generated = await generatePluginPackage(cwd, libraries, lock.generated.packer);
|
|
13819
14387
|
if (generated.spec !== lock.generated.spec || generated.sha256 !== lock.generated.sha256 || JSON.stringify(generated.subpaths) !== JSON.stringify(lock.generated.subpaths))
|
|
13820
14388
|
throw new Error("Generated package does not match octonode.lock");
|
|
13821
|
-
const manifest2 = JSON.parse((0,
|
|
14389
|
+
const manifest2 = JSON.parse((0, import_node_fs14.readFileSync)((0, import_node_path14.join)(cwd, "package.json"), "utf8"));
|
|
13822
14390
|
if (manifest2.dependencies?.[generated.name]?.replace(/^file:\.\//, "file:") !== generated.spec.replace(/^file:\.\//, "file:"))
|
|
13823
14391
|
throw new Error("package.json disagrees with octonode.lock");
|
|
13824
14392
|
}
|
|
@@ -13838,11 +14406,11 @@ async function installFromLock(opts = {}) {
|
|
|
13838
14406
|
}
|
|
13839
14407
|
|
|
13840
14408
|
// packages/plugin/src/consumer/lifecycle.ts
|
|
13841
|
-
var
|
|
14409
|
+
var import_schema6 = __toESM(require_dist());
|
|
13842
14410
|
async function runPluginLifecycle(command, target, flags) {
|
|
13843
|
-
const cwd = resolveDependencyProject(typeof flags.cwd === "string" ? (0,
|
|
14411
|
+
const cwd = resolveDependencyProject(typeof flags.cwd === "string" ? (0, import_node_path15.resolve)(flags.cwd) : process.cwd()).target;
|
|
13844
14412
|
const scope = typeof flags.scope === "string" ? flags.scope : void 0;
|
|
13845
|
-
if (scope && !
|
|
14413
|
+
if (scope && !import_schema6.MARKETPLACE_SCOPES.includes(scope)) throw new Error("Invalid marketplace scope");
|
|
13846
14414
|
const options = {
|
|
13847
14415
|
cwd,
|
|
13848
14416
|
alias: typeof flags.alias === "string" ? flags.alias : void 0,
|
|
@@ -13870,8 +14438,8 @@ async function runPluginLifecycle(command, target, flags) {
|
|
|
13870
14438
|
await removePluginPin(target, options);
|
|
13871
14439
|
return { removed: target, dryRun: options.dryRun };
|
|
13872
14440
|
}
|
|
13873
|
-
if (command === "install" && (0,
|
|
13874
|
-
const entry = await installLocalArtifact((0,
|
|
14441
|
+
if (command === "install" && (0, import_node_fs15.existsSync)((0, import_node_path15.resolve)(cwd, target))) {
|
|
14442
|
+
const entry = await installLocalArtifact((0, import_node_path15.resolve)(cwd, target), options);
|
|
13875
14443
|
return { id: options.alias ?? entry.id, version: entry.version, sha256: entry.sha256, dryRun: options.dryRun };
|
|
13876
14444
|
}
|
|
13877
14445
|
if (command !== "install" && command !== "update") throw new Error(`Unknown plugin lifecycle command: ${command}`);
|