@octonodes/cli 0.1.12 → 0.1.14
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 +8 -0
- package/dist/connect.d.ts +1 -1
- package/dist/connect.d.ts.map +1 -1
- package/dist/connect.js +11 -4
- package/dist/connect.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- 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/types.d.ts +2 -1
- package/dist/plugins/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/runtime/plugin-lifecycle.cjs +987 -490
|
@@ -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
|
}
|
|
@@ -2639,8 +2639,8 @@ var require_planning = __commonJS({
|
|
|
2639
2639
|
version: collaboration_1.revisionSchema,
|
|
2640
2640
|
createdAt: common_1.taskTimestampSchema,
|
|
2641
2641
|
updatedAt: common_1.taskTimestampSchema
|
|
2642
|
-
}).strict().superRefine((
|
|
2643
|
-
if (
|
|
2642
|
+
}).strict().superRefine((release2, context) => {
|
|
2643
|
+
if (release2.state === "released" && release2.releasedAt === null) {
|
|
2644
2644
|
context.addIssue({
|
|
2645
2645
|
code: zod_1.z.ZodIssueCode.custom,
|
|
2646
2646
|
path: ["releasedAt"],
|
|
@@ -7719,10 +7719,10 @@ var require_build = __commonJS({
|
|
|
7719
7719
|
else out += sub.appendTo();
|
|
7720
7720
|
break;
|
|
7721
7721
|
case Regexp2.Op.ALTERNATE: {
|
|
7722
|
-
let
|
|
7722
|
+
let sep2 = "";
|
|
7723
7723
|
for (let sub of this.subs) {
|
|
7724
|
-
out +=
|
|
7725
|
-
|
|
7724
|
+
out += sep2;
|
|
7725
|
+
sep2 = "|";
|
|
7726
7726
|
out += sub.appendTo();
|
|
7727
7727
|
}
|
|
7728
7728
|
break;
|
|
@@ -11456,6 +11456,58 @@ var require_plugin_version = __commonJS({
|
|
|
11456
11456
|
}
|
|
11457
11457
|
});
|
|
11458
11458
|
|
|
11459
|
+
// packages/schema/dist/plugin/execution.constants.js
|
|
11460
|
+
var require_execution_constants = __commonJS({
|
|
11461
|
+
"packages/schema/dist/plugin/execution.constants.js"(exports2) {
|
|
11462
|
+
"use strict";
|
|
11463
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
11464
|
+
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;
|
|
11465
|
+
exports2.PLUGIN_RUNNER_ORIGIN = "http://plugin-runner.octonode.internal";
|
|
11466
|
+
exports2.PLUGIN_RUNNER_PORT = 4001;
|
|
11467
|
+
exports2.PLUGIN_EXECUTION_MAX_BYTES = 1024 * 1024;
|
|
11468
|
+
exports2.PLUGIN_EXECUTION_TIMEOUT_MS = 5 * 6e4;
|
|
11469
|
+
exports2.PREPARED_RUNTIME_MAX_BYTES = 256 * 1024 * 1024;
|
|
11470
|
+
exports2.PREPARED_RUNTIME_MAX_FILES = 5e4;
|
|
11471
|
+
exports2.PREPARED_RUNTIME_ARCHIVE = "octonode-runtime.tgz";
|
|
11472
|
+
}
|
|
11473
|
+
});
|
|
11474
|
+
|
|
11475
|
+
// packages/schema/dist/plugin/execution.js
|
|
11476
|
+
var require_execution = __commonJS({
|
|
11477
|
+
"packages/schema/dist/plugin/execution.js"(exports2) {
|
|
11478
|
+
"use strict";
|
|
11479
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
11480
|
+
exports2.AuthorizedPluginRelease = exports2.PluginExecutionRequest = exports2.PluginExecutionReference = exports2.PreparedPluginRuntime = void 0;
|
|
11481
|
+
var zod_1 = require("zod");
|
|
11482
|
+
var ipc_envelope_1 = require_ipc_envelope();
|
|
11483
|
+
var plugin_1 = require_plugin();
|
|
11484
|
+
var execution_constants_1 = require_execution_constants();
|
|
11485
|
+
exports2.PreparedPluginRuntime = zod_1.z.object({
|
|
11486
|
+
format: zod_1.z.literal(1),
|
|
11487
|
+
nodeMajor: zod_1.z.literal(24),
|
|
11488
|
+
platform: zod_1.z.enum(["portable", "linux", "darwin"]),
|
|
11489
|
+
arch: zod_1.z.string().max(32).optional(),
|
|
11490
|
+
libc: zod_1.z.string().max(64).optional(),
|
|
11491
|
+
dependencies: zod_1.z.literal(execution_constants_1.PREPARED_RUNTIME_ARCHIVE).optional()
|
|
11492
|
+
}).strict();
|
|
11493
|
+
exports2.PluginExecutionReference = zod_1.z.object({
|
|
11494
|
+
installId: zod_1.z.string().uuid(),
|
|
11495
|
+
sha256: zod_1.z.string().regex(/^sha256:[a-f0-9]{64}$/),
|
|
11496
|
+
nodeId: zod_1.z.string().regex(/^[a-z0-9][a-z0-9_-]*$/i)
|
|
11497
|
+
}).strict();
|
|
11498
|
+
exports2.PluginExecutionRequest = zod_1.z.object({
|
|
11499
|
+
plugin: exports2.PluginExecutionReference,
|
|
11500
|
+
request: ipc_envelope_1.InvokeRequest,
|
|
11501
|
+
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({}),
|
|
11502
|
+
timeoutMs: zod_1.z.number().int().positive().max(execution_constants_1.PLUGIN_EXECUTION_TIMEOUT_MS).default(execution_constants_1.PLUGIN_EXECUTION_TIMEOUT_MS)
|
|
11503
|
+
}).strict();
|
|
11504
|
+
exports2.AuthorizedPluginRelease = zod_1.z.object({
|
|
11505
|
+
manifest: plugin_1.PluginManifest,
|
|
11506
|
+
archiveSha256: zod_1.z.string().regex(/^[a-f0-9]{64}$/)
|
|
11507
|
+
});
|
|
11508
|
+
}
|
|
11509
|
+
});
|
|
11510
|
+
|
|
11459
11511
|
// packages/schema/dist/index.js
|
|
11460
11512
|
var require_dist = __commonJS({
|
|
11461
11513
|
"packages/schema/dist/index.js"(exports2) {
|
|
@@ -11518,6 +11570,8 @@ var require_dist = __commonJS({
|
|
|
11518
11570
|
__exportStar(require_project_lifecycle(), exports2);
|
|
11519
11571
|
__exportStar(require_project_jobs(), exports2);
|
|
11520
11572
|
__exportStar(require_plugin_version(), exports2);
|
|
11573
|
+
__exportStar(require_execution(), exports2);
|
|
11574
|
+
__exportStar(require_execution_constants(), exports2);
|
|
11521
11575
|
}
|
|
11522
11576
|
});
|
|
11523
11577
|
|
|
@@ -11845,7 +11899,7 @@ var require_runner = __commonJS({
|
|
|
11845
11899
|
let draining = false;
|
|
11846
11900
|
let ended = false;
|
|
11847
11901
|
let done;
|
|
11848
|
-
const finished = new Promise((
|
|
11902
|
+
const finished = new Promise((resolve7) => done = resolve7);
|
|
11849
11903
|
const drain = async () => {
|
|
11850
11904
|
if (draining)
|
|
11851
11905
|
return;
|
|
@@ -11895,183 +11949,6 @@ var require_runner = __commonJS({
|
|
|
11895
11949
|
}
|
|
11896
11950
|
});
|
|
11897
11951
|
|
|
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
11952
|
// packages/common/dist/constants.js
|
|
12076
11953
|
var require_constants2 = __commonJS({
|
|
12077
11954
|
"packages/common/dist/constants.js"(exports2) {
|
|
@@ -12089,8 +11966,8 @@ var require_constants2 = __commonJS({
|
|
|
12089
11966
|
return environment;
|
|
12090
11967
|
};
|
|
12091
11968
|
exports2.workflowEnvironment = workflowEnvironment;
|
|
12092
|
-
var
|
|
12093
|
-
exports2.childProcessEnvironment =
|
|
11969
|
+
var childProcessEnvironment4 = (overrides = {}) => (0, exports2.workflowEnvironment)({ ...exports2.PROCESS_ENV, ...overrides });
|
|
11970
|
+
exports2.childProcessEnvironment = childProcessEnvironment4;
|
|
12094
11971
|
var setEnvironmentVariable = (name, value) => {
|
|
12095
11972
|
if (value === void 0)
|
|
12096
11973
|
delete exports2.PROCESS_ENV[name];
|
|
@@ -12132,8 +12009,8 @@ var require_constants2 = __commonJS({
|
|
|
12132
12009
|
exports2.OCTONODE_PACKAGE_CACHE = OCTONODE_PACKAGE_CACHE2;
|
|
12133
12010
|
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
12011
|
exports2.OCTONODE_MARKETPLACE_TOKEN = OCTONODE_MARKETPLACE_TOKEN2;
|
|
12135
|
-
var
|
|
12136
|
-
exports2.OCTONODE_MARKETPLACE_URL =
|
|
12012
|
+
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;
|
|
12013
|
+
exports2.OCTONODE_MARKETPLACE_URL = OCTONODE_MARKETPLACE_URL3;
|
|
12137
12014
|
var OCTONODE_RUN_CONCURRENCY = () => exports2.PROCESS_ENV.OCTONODE_RUN_CONCURRENCY;
|
|
12138
12015
|
exports2.OCTONODE_RUN_CONCURRENCY = OCTONODE_RUN_CONCURRENCY;
|
|
12139
12016
|
var OCTONODE_RUN_QUEUE = () => exports2.PROCESS_ENV.OCTONODE_RUN_QUEUE;
|
|
@@ -12391,38 +12268,248 @@ var require_graph_layout = __commonJS({
|
|
|
12391
12268
|
}
|
|
12392
12269
|
});
|
|
12393
12270
|
|
|
12394
|
-
// packages/common/dist/
|
|
12271
|
+
// packages/common/dist/plugin-nodes.js
|
|
12272
|
+
var require_plugin_nodes = __commonJS({
|
|
12273
|
+
"packages/common/dist/plugin-nodes.js"(exports2) {
|
|
12274
|
+
"use strict";
|
|
12275
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
12276
|
+
exports2.installedPluginNodesPage = installedPluginNodesPage;
|
|
12277
|
+
function isCatalogPlugin(value) {
|
|
12278
|
+
if (!value || typeof value !== "object")
|
|
12279
|
+
return false;
|
|
12280
|
+
const plugin = value;
|
|
12281
|
+
return typeof plugin.id === "string" && typeof plugin.name === "string" && typeof plugin.version === "string" && Array.isArray(plugin.nodes) && plugin.nodes.every((node) => {
|
|
12282
|
+
if (!node || typeof node !== "object")
|
|
12283
|
+
return false;
|
|
12284
|
+
const item = node;
|
|
12285
|
+
return typeof item.id === "string" && (item.icon === void 0 || typeof item.icon === "string") && (item.description === void 0 || typeof item.description === "string");
|
|
12286
|
+
});
|
|
12287
|
+
}
|
|
12288
|
+
function installedPluginNodesPage(inventory, query) {
|
|
12289
|
+
if (!inventory.every(isCatalogPlugin))
|
|
12290
|
+
throw new Error("Plugin node inventory is incomplete");
|
|
12291
|
+
const q = query.q?.trim().toLowerCase();
|
|
12292
|
+
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));
|
|
12293
|
+
const offset = Math.min(query.offset, nodes.length);
|
|
12294
|
+
return { items: nodes.slice(offset, offset + query.limit), total: nodes.length, offset, limit: query.limit };
|
|
12295
|
+
}
|
|
12296
|
+
}
|
|
12297
|
+
});
|
|
12298
|
+
|
|
12299
|
+
// packages/common/dist/index.js
|
|
12300
|
+
var require_dist2 = __commonJS({
|
|
12301
|
+
"packages/common/dist/index.js"(exports2) {
|
|
12302
|
+
"use strict";
|
|
12303
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
12304
|
+
if (k2 === void 0) k2 = k;
|
|
12305
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12306
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12307
|
+
desc = { enumerable: true, get: function() {
|
|
12308
|
+
return m[k];
|
|
12309
|
+
} };
|
|
12310
|
+
}
|
|
12311
|
+
Object.defineProperty(o, k2, desc);
|
|
12312
|
+
}) : (function(o, m, k, k2) {
|
|
12313
|
+
if (k2 === void 0) k2 = k;
|
|
12314
|
+
o[k2] = m[k];
|
|
12315
|
+
}));
|
|
12316
|
+
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
12317
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
|
|
12318
|
+
};
|
|
12319
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
12320
|
+
exports2.installedPluginNodesPage = exports2.layeredLayout = exports2.packageCacheEnvironment = void 0;
|
|
12321
|
+
__exportStar(require_constants2(), exports2);
|
|
12322
|
+
__exportStar(require_legal_constants(), exports2);
|
|
12323
|
+
var package_cache_1 = require_package_cache();
|
|
12324
|
+
Object.defineProperty(exports2, "packageCacheEnvironment", { enumerable: true, get: function() {
|
|
12325
|
+
return package_cache_1.packageCacheEnvironment;
|
|
12326
|
+
} });
|
|
12327
|
+
__exportStar(require_api_exposure(), exports2);
|
|
12328
|
+
var graph_layout_1 = require_graph_layout();
|
|
12329
|
+
Object.defineProperty(exports2, "layeredLayout", { enumerable: true, get: function() {
|
|
12330
|
+
return graph_layout_1.layeredLayout;
|
|
12331
|
+
} });
|
|
12332
|
+
var plugin_nodes_1 = require_plugin_nodes();
|
|
12333
|
+
Object.defineProperty(exports2, "installedPluginNodesPage", { enumerable: true, get: function() {
|
|
12334
|
+
return plugin_nodes_1.installedPluginNodesPage;
|
|
12335
|
+
} });
|
|
12336
|
+
}
|
|
12337
|
+
});
|
|
12338
|
+
|
|
12339
|
+
// packages/plugin-runtime/dist/plugin.js
|
|
12340
|
+
var require_plugin2 = __commonJS({
|
|
12341
|
+
"packages/plugin-runtime/dist/plugin.js"(exports2) {
|
|
12342
|
+
"use strict";
|
|
12343
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
12344
|
+
exports2.definePlugin = definePlugin;
|
|
12345
|
+
exports2.startPlugin = startPlugin;
|
|
12346
|
+
var common_1 = require_dist2();
|
|
12347
|
+
var schema_1 = require_dist();
|
|
12348
|
+
var define_node_1 = require_define_node();
|
|
12349
|
+
var runner_1 = require_runner();
|
|
12350
|
+
function definePlugin(definition, handlers) {
|
|
12351
|
+
const options = definition;
|
|
12352
|
+
if (!handlers && (!options || !Array.isArray(options.nodes)))
|
|
12353
|
+
throw new Error("plugin needs a nodes array");
|
|
12354
|
+
if (!handlers) {
|
|
12355
|
+
for (const node of options.nodes) {
|
|
12356
|
+
if (typeof node.run !== "function")
|
|
12357
|
+
throw new Error(`plugin node "${node.id}" needs a handler`);
|
|
12358
|
+
if (node.kind && node.kind !== "function")
|
|
12359
|
+
throw new Error("plugin nodes must be functions");
|
|
12360
|
+
}
|
|
12361
|
+
}
|
|
12362
|
+
const manifest2 = schema_1.PluginManifest.parse(handlers ? definition : {
|
|
12363
|
+
...options,
|
|
12364
|
+
nodes: options.nodes.map(({ run: _run, ...node }) => ({
|
|
12365
|
+
...node,
|
|
12366
|
+
command: `node dist/index.js ${node.id}`,
|
|
12367
|
+
language: "typescript"
|
|
12368
|
+
}))
|
|
12369
|
+
});
|
|
12370
|
+
const nodeHandlers = handlers ?? Object.fromEntries(options.nodes.map((node) => [node.id, node.run]));
|
|
12371
|
+
for (const node of manifest2.nodes) {
|
|
12372
|
+
for (const field of ["inputs", "outputs", "defaults"]) {
|
|
12373
|
+
const error = node[field] === void 0 ? void 0 : (0, runner_1.jsonSafetyError)(node[field]);
|
|
12374
|
+
if (error)
|
|
12375
|
+
throw new Error(`plugin node "${node.id}" ${field} must be JSON-serializable: ${error}`);
|
|
12376
|
+
}
|
|
12377
|
+
}
|
|
12378
|
+
for (const id of Object.keys(nodeHandlers)) {
|
|
12379
|
+
if (!manifest2.nodes.some((node) => node.id === id))
|
|
12380
|
+
throw new Error(`handler "${id}" has no plugin node`);
|
|
12381
|
+
}
|
|
12382
|
+
return {
|
|
12383
|
+
manifest: manifest2,
|
|
12384
|
+
...!handlers && options.assets ? { assets: options.assets } : {},
|
|
12385
|
+
nodes: Object.fromEntries(manifest2.nodes.map((node) => {
|
|
12386
|
+
if (!Object.hasOwn(nodeHandlers, node.id))
|
|
12387
|
+
throw new Error(`plugin node "${node.id}" needs a handler`);
|
|
12388
|
+
const fields = (node.connections ?? []).flatMap((id) => Object.entries(manifest2.connections?.[id]?.fields ?? {}));
|
|
12389
|
+
return [
|
|
12390
|
+
node.id,
|
|
12391
|
+
(0, define_node_1.defineNode)({
|
|
12392
|
+
...node,
|
|
12393
|
+
run: (inputs, context) => {
|
|
12394
|
+
const missing = fields.filter(([name, field]) => field.required && !common_1.PROCESS_ENV[name]).map(([name]) => name);
|
|
12395
|
+
if (missing.length)
|
|
12396
|
+
throw new runner_1.NodeError(`Missing connection credentials: ${missing.join(", ")}`);
|
|
12397
|
+
return nodeHandlers[node.id](inputs, context);
|
|
12398
|
+
}
|
|
12399
|
+
})
|
|
12400
|
+
];
|
|
12401
|
+
}))
|
|
12402
|
+
};
|
|
12403
|
+
}
|
|
12404
|
+
function startPlugin(plugin, nodeId = process.argv[2]) {
|
|
12405
|
+
const id = nodeId ?? (plugin.manifest.nodes.length === 1 ? plugin.manifest.nodes[0].id : void 0);
|
|
12406
|
+
if (!id || !Object.hasOwn(plugin.nodes, id))
|
|
12407
|
+
throw new Error(`Choose a plugin node: ${Object.keys(plugin.nodes).join(", ")}`);
|
|
12408
|
+
(0, runner_1.start)(plugin.nodes[id]);
|
|
12409
|
+
}
|
|
12410
|
+
}
|
|
12411
|
+
});
|
|
12412
|
+
|
|
12413
|
+
// packages/plugin-runtime/dist/plugin-file.js
|
|
12414
|
+
var require_plugin_file = __commonJS({
|
|
12415
|
+
"packages/plugin-runtime/dist/plugin-file.js"(exports2) {
|
|
12416
|
+
"use strict";
|
|
12417
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
12418
|
+
exports2.pluginDefinitionPath = pluginDefinitionPath2;
|
|
12419
|
+
exports2.loadPluginDefinition = loadPluginDefinition3;
|
|
12420
|
+
var node_fs_1 = require("node:fs");
|
|
12421
|
+
var node_path_1 = require("node:path");
|
|
12422
|
+
var yaml_1 = require("yaml");
|
|
12423
|
+
var schema_1 = require_dist();
|
|
12424
|
+
function pluginDefinitionPath2(dir) {
|
|
12425
|
+
const files = schema_1.PLUGIN_DEFINITION_FILENAMES.map((name) => (0, node_path_1.join)(dir, name)).filter(node_fs_1.existsSync);
|
|
12426
|
+
if (files.length !== 1)
|
|
12427
|
+
throw new Error(files.length ? `Multiple plugin definitions in ${dir}; keep exactly one` : `No plugin definition in ${dir}; create octonode.yml or octonode.json`);
|
|
12428
|
+
const file = files[0];
|
|
12429
|
+
if ((0, node_path_1.dirname)((0, node_fs_1.realpathSync)(file)) !== (0, node_fs_1.realpathSync)(dir))
|
|
12430
|
+
throw new Error("Plugin definition must stay inside its folder");
|
|
12431
|
+
if (!(0, node_fs_1.statSync)(file).isFile() || (0, node_fs_1.statSync)(file).size > 1048576)
|
|
12432
|
+
throw new Error("Plugin definition must be a file smaller than 1 MiB");
|
|
12433
|
+
return file;
|
|
12434
|
+
}
|
|
12435
|
+
function loadPluginDefinition3(dir) {
|
|
12436
|
+
const file = pluginDefinitionPath2(dir);
|
|
12437
|
+
const source = (0, node_fs_1.readFileSync)(file, "utf8");
|
|
12438
|
+
const document = (0, yaml_1.parseDocument)(source, { version: "1.2", uniqueKeys: true });
|
|
12439
|
+
(0, yaml_1.visit)(document, {
|
|
12440
|
+
Alias() {
|
|
12441
|
+
throw new Error("Plugin definitions cannot contain YAML aliases");
|
|
12442
|
+
}
|
|
12443
|
+
});
|
|
12444
|
+
if (document.errors.length || document.warnings.length)
|
|
12445
|
+
throw new Error(`${file}: ${[...document.errors, ...document.warnings].map((error) => error.message).join("; ")}`);
|
|
12446
|
+
const raw = file.endsWith(".json") ? JSON.parse(source) : document.toJS({ maxAliasCount: 0 });
|
|
12447
|
+
if (file.endsWith(schema_1.PLUGIN_MANIFEST_FILENAME))
|
|
12448
|
+
return schema_1.PluginManifest.parse(raw);
|
|
12449
|
+
const settings = schema_1.OctonodeSettingsDocument.parse(raw);
|
|
12450
|
+
if (!settings.plugin)
|
|
12451
|
+
throw new Error(`${file} has no plugin section`);
|
|
12452
|
+
return settings.plugin;
|
|
12453
|
+
}
|
|
12454
|
+
}
|
|
12455
|
+
});
|
|
12456
|
+
|
|
12457
|
+
// packages/plugin-runtime/dist/index.js
|
|
12395
12458
|
var require_dist3 = __commonJS({
|
|
12396
|
-
"packages/
|
|
12459
|
+
"packages/plugin-runtime/dist/index.js"(exports2) {
|
|
12397
12460
|
"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
12461
|
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;
|
|
12462
|
+
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;
|
|
12463
|
+
var define_node_1 = require_define_node();
|
|
12464
|
+
Object.defineProperty(exports2, "defineNode", { enumerable: true, get: function() {
|
|
12465
|
+
return define_node_1.defineNode;
|
|
12421
12466
|
} });
|
|
12422
|
-
|
|
12423
|
-
|
|
12424
|
-
|
|
12425
|
-
|
|
12467
|
+
Object.defineProperty(exports2, "defineService", { enumerable: true, get: function() {
|
|
12468
|
+
return define_node_1.defineService;
|
|
12469
|
+
} });
|
|
12470
|
+
Object.defineProperty(exports2, "defineClass", { enumerable: true, get: function() {
|
|
12471
|
+
return define_node_1.defineClass;
|
|
12472
|
+
} });
|
|
12473
|
+
Object.defineProperty(exports2, "defineConst", { enumerable: true, get: function() {
|
|
12474
|
+
return define_node_1.defineConst;
|
|
12475
|
+
} });
|
|
12476
|
+
var runner_1 = require_runner();
|
|
12477
|
+
Object.defineProperty(exports2, "runNode", { enumerable: true, get: function() {
|
|
12478
|
+
return runner_1.runNode;
|
|
12479
|
+
} });
|
|
12480
|
+
Object.defineProperty(exports2, "start", { enumerable: true, get: function() {
|
|
12481
|
+
return runner_1.start;
|
|
12482
|
+
} });
|
|
12483
|
+
Object.defineProperty(exports2, "NodeError", { enumerable: true, get: function() {
|
|
12484
|
+
return runner_1.NodeError;
|
|
12485
|
+
} });
|
|
12486
|
+
var json_schema_1 = require_json_schema2();
|
|
12487
|
+
Object.defineProperty(exports2, "validate", { enumerable: true, get: function() {
|
|
12488
|
+
return json_schema_1.validate;
|
|
12489
|
+
} });
|
|
12490
|
+
var plugin_1 = require_plugin2();
|
|
12491
|
+
Object.defineProperty(exports2, "definePlugin", { enumerable: true, get: function() {
|
|
12492
|
+
return plugin_1.definePlugin;
|
|
12493
|
+
} });
|
|
12494
|
+
Object.defineProperty(exports2, "startPlugin", { enumerable: true, get: function() {
|
|
12495
|
+
return plugin_1.startPlugin;
|
|
12496
|
+
} });
|
|
12497
|
+
var plugin_file_1 = require_plugin_file();
|
|
12498
|
+
Object.defineProperty(exports2, "loadPluginDefinition", { enumerable: true, get: function() {
|
|
12499
|
+
return plugin_file_1.loadPluginDefinition;
|
|
12500
|
+
} });
|
|
12501
|
+
Object.defineProperty(exports2, "pluginDefinitionPath", { enumerable: true, get: function() {
|
|
12502
|
+
return plugin_file_1.pluginDefinitionPath;
|
|
12503
|
+
} });
|
|
12504
|
+
var schema_1 = require_dist();
|
|
12505
|
+
Object.defineProperty(exports2, "PluginManifest", { enumerable: true, get: function() {
|
|
12506
|
+
return schema_1.PluginManifest;
|
|
12507
|
+
} });
|
|
12508
|
+
Object.defineProperty(exports2, "PluginNode", { enumerable: true, get: function() {
|
|
12509
|
+
return schema_1.PluginNode;
|
|
12510
|
+
} });
|
|
12511
|
+
Object.defineProperty(exports2, "PluginConnection", { enumerable: true, get: function() {
|
|
12512
|
+
return schema_1.PluginConnection;
|
|
12426
12513
|
} });
|
|
12427
12514
|
}
|
|
12428
12515
|
});
|
|
@@ -12435,18 +12522,18 @@ __export(index_exports, {
|
|
|
12435
12522
|
module.exports = __toCommonJS(index_exports);
|
|
12436
12523
|
|
|
12437
12524
|
// packages/plugin/src/consumer/lifecycle.ts
|
|
12438
|
-
var
|
|
12439
|
-
var
|
|
12525
|
+
var import_node_fs15 = require("node:fs");
|
|
12526
|
+
var import_node_path15 = require("node:path");
|
|
12440
12527
|
|
|
12441
12528
|
// packages/plugin/src/lifecycle.ts
|
|
12442
|
-
var
|
|
12443
|
-
var
|
|
12529
|
+
var import_node_fs10 = require("node:fs");
|
|
12530
|
+
var import_node_path10 = require("node:path");
|
|
12444
12531
|
|
|
12445
12532
|
// packages/plugin/src/store.ts
|
|
12446
12533
|
var import_node_fs2 = require("node:fs");
|
|
12447
12534
|
var import_node_os = require("node:os");
|
|
12448
12535
|
var import_node_path2 = require("node:path");
|
|
12449
|
-
var import_plugin_runtime = __toESM(
|
|
12536
|
+
var import_plugin_runtime = __toESM(require_dist3());
|
|
12450
12537
|
|
|
12451
12538
|
// packages/plugin/src/integrity.ts
|
|
12452
12539
|
var import_node_crypto = require("node:crypto");
|
|
@@ -12538,7 +12625,7 @@ function addToStore(srcDir, opts = {}) {
|
|
|
12538
12625
|
var import_node_fs4 = require("node:fs");
|
|
12539
12626
|
var import_node_os2 = require("node:os");
|
|
12540
12627
|
var import_node_path4 = require("node:path");
|
|
12541
|
-
var import_plugin_runtime2 = __toESM(
|
|
12628
|
+
var import_plugin_runtime2 = __toESM(require_dist3());
|
|
12542
12629
|
var import_schema2 = __toESM(require_dist());
|
|
12543
12630
|
|
|
12544
12631
|
// packages/plugin/src/lock.ts
|
|
@@ -12551,6 +12638,8 @@ var LockEntry = import_zod.z.object({
|
|
|
12551
12638
|
version: import_zod.z.string(),
|
|
12552
12639
|
/** `sha256:<hex>` dir-content hash (hashPluginDir) — the store address + integrity check. */
|
|
12553
12640
|
sha256: import_zod.z.string(),
|
|
12641
|
+
/** Registry archive checksum, distinct from the unpacked file-tree identity. */
|
|
12642
|
+
archiveSha256: import_zod.z.string().regex(/^[a-f0-9]{64}$/).optional(),
|
|
12554
12643
|
/** Marketplace base URL the bundle came from (absent for local installs). */
|
|
12555
12644
|
registry: import_zod.z.string().optional(),
|
|
12556
12645
|
/** Marketplace tier it was resolved from. */
|
|
@@ -12625,12 +12714,12 @@ function isPluginDir(dir) {
|
|
|
12625
12714
|
|
|
12626
12715
|
// packages/plugin/src/dependencies.ts
|
|
12627
12716
|
var import_node_child_process = require("node:child_process");
|
|
12628
|
-
var
|
|
12629
|
-
var
|
|
12630
|
-
var
|
|
12717
|
+
var import_node_fs6 = require("node:fs");
|
|
12718
|
+
var import_node_os4 = require("node:os");
|
|
12719
|
+
var import_node_path6 = require("node:path");
|
|
12631
12720
|
var import_node_util = require("node:util");
|
|
12632
12721
|
var import_yaml = require("yaml");
|
|
12633
|
-
var import_common = __toESM(
|
|
12722
|
+
var import_common = __toESM(require_dist2());
|
|
12634
12723
|
|
|
12635
12724
|
// packages/plugin/src/dependencies.constants.ts
|
|
12636
12725
|
var DEFAULT_PACKAGE_MANAGER = "pnpm@12.3.4";
|
|
@@ -12644,43 +12733,291 @@ var PACKAGE_MANAGER_LOCKS = {
|
|
|
12644
12733
|
bun: ["bun.lock", "bun.lockb"]
|
|
12645
12734
|
};
|
|
12646
12735
|
|
|
12736
|
+
// packages/plugin/src/dependency/snapshot.ts
|
|
12737
|
+
var import_node_crypto2 = require("node:crypto");
|
|
12738
|
+
var import_node_fs5 = require("node:fs");
|
|
12739
|
+
var import_node_path5 = require("node:path");
|
|
12740
|
+
var import_node_os3 = require("node:os");
|
|
12741
|
+
var import_zod2 = require("zod");
|
|
12742
|
+
|
|
12743
|
+
// packages/plugin/src/dependency/snapshot.constants.ts
|
|
12744
|
+
var DEPENDENCY_SNAPSHOT_FORMAT = 1;
|
|
12745
|
+
var DEPENDENCY_SNAPSHOT_MAX_BYTES = 256 * 1024 * 1024;
|
|
12746
|
+
var DEPENDENCY_SNAPSHOT_MAX_FILES = 5e4;
|
|
12747
|
+
var DEPENDENCY_SNAPSHOT_OUTPUTS = [
|
|
12748
|
+
"node_modules",
|
|
12749
|
+
".pnp.cjs",
|
|
12750
|
+
".pnp.loader.mjs",
|
|
12751
|
+
".pnp.data.json",
|
|
12752
|
+
".yarn/cache",
|
|
12753
|
+
".yarn/unplugged",
|
|
12754
|
+
".yarn/install-state.gz"
|
|
12755
|
+
];
|
|
12756
|
+
|
|
12757
|
+
// packages/plugin/src/dependency/snapshot.ts
|
|
12758
|
+
function inside(root, path) {
|
|
12759
|
+
const local = (0, import_node_path5.relative)(root, path);
|
|
12760
|
+
return local === "" || !(0, import_node_path5.isAbsolute)(local) && local !== ".." && !local.startsWith(`..${import_node_path5.sep}`);
|
|
12761
|
+
}
|
|
12762
|
+
function digestTree(root, paths, projectRoot) {
|
|
12763
|
+
const hash = (0, import_node_crypto2.createHash)("sha256");
|
|
12764
|
+
let bytes = 0;
|
|
12765
|
+
let count = 0;
|
|
12766
|
+
const visit2 = (path) => {
|
|
12767
|
+
if (++count > DEPENDENCY_SNAPSHOT_MAX_FILES) throw new Error("Dependency snapshot file limit");
|
|
12768
|
+
const file = (0, import_node_path5.join)(root, path);
|
|
12769
|
+
for (let parent = (0, import_node_path5.dirname)(file); inside(root, parent); parent = (0, import_node_path5.dirname)(parent)) {
|
|
12770
|
+
if ((0, import_node_fs5.lstatSync)(parent).isSymbolicLink()) throw new Error("Dependency snapshot ancestor is a link");
|
|
12771
|
+
if (parent === root) break;
|
|
12772
|
+
}
|
|
12773
|
+
const stat = (0, import_node_fs5.lstatSync)(file);
|
|
12774
|
+
hash.update(
|
|
12775
|
+
JSON.stringify([
|
|
12776
|
+
path,
|
|
12777
|
+
stat.mode & 511,
|
|
12778
|
+
stat.isDirectory() ? "directory" : stat.isSymbolicLink() ? "link" : "file"
|
|
12779
|
+
])
|
|
12780
|
+
);
|
|
12781
|
+
if (stat.isSymbolicLink()) {
|
|
12782
|
+
const link = (0, import_node_fs5.readlinkSync)(file);
|
|
12783
|
+
if (!inside(projectRoot, (0, import_node_path5.resolve)((0, import_node_path5.dirname)((0, import_node_path5.join)(projectRoot, path)), link)))
|
|
12784
|
+
throw new Error("Dependency snapshot link leaves project");
|
|
12785
|
+
hash.update(JSON.stringify(link));
|
|
12786
|
+
} else if (stat.isDirectory()) {
|
|
12787
|
+
for (const name of (0, import_node_fs5.readdirSync)(file).sort()) visit2((0, import_node_path5.join)(path, name));
|
|
12788
|
+
} else if (stat.isFile()) {
|
|
12789
|
+
bytes += stat.size;
|
|
12790
|
+
if (bytes > DEPENDENCY_SNAPSHOT_MAX_BYTES) throw new Error("Dependency snapshot size limit");
|
|
12791
|
+
hash.update(String(stat.size)).update("\0").update((0, import_node_fs5.readFileSync)(file));
|
|
12792
|
+
} else throw new Error("Unsupported dependency snapshot file");
|
|
12793
|
+
};
|
|
12794
|
+
for (const path of [...paths].sort()) visit2(path);
|
|
12795
|
+
return hash.digest("hex");
|
|
12796
|
+
}
|
|
12797
|
+
function dependencySnapshot(project, cacheRoot, managerVersion, environment) {
|
|
12798
|
+
try {
|
|
12799
|
+
if (inside(cacheRoot, project.root)) return;
|
|
12800
|
+
if (!PACKAGE_MANAGER_LOCKS[project.manager].some((name) => (0, import_node_fs5.existsSync)((0, import_node_path5.join)(project.root, name)))) return;
|
|
12801
|
+
const outputs = new Set(DEPENDENCY_SNAPSHOT_OUTPUTS);
|
|
12802
|
+
let inputCount = 0;
|
|
12803
|
+
if (/--(?:require|import|loader|experimental-loader)(?:[=\s]|$)/.test(environment.NODE_OPTIONS ?? "")) return;
|
|
12804
|
+
const walk = (directory) => (0, import_node_fs5.readdirSync)(directory).sort().flatMap((name) => {
|
|
12805
|
+
const file = (0, import_node_path5.join)(directory, name);
|
|
12806
|
+
const local = (0, import_node_path5.relative)(project.root, file);
|
|
12807
|
+
if (inside(cacheRoot, file) || outputs.has(local) || name === "node_modules" || name === ".git" || name === ".octonode" || name === DEPENDENCY_MUTEX || name.startsWith(".octonode-recovery-"))
|
|
12808
|
+
return [];
|
|
12809
|
+
if (++inputCount > DEPENDENCY_SNAPSHOT_MAX_FILES) throw new Error("Dependency input file limit");
|
|
12810
|
+
const stat = (0, import_node_fs5.lstatSync)(file);
|
|
12811
|
+
if (stat.isSymbolicLink()) throw new Error("Linked source is not snapshot eligible");
|
|
12812
|
+
if (/^\.?pnpmfile\.[cm]?js$/.test(name))
|
|
12813
|
+
throw new Error("Dynamic package-manager hooks require installation");
|
|
12814
|
+
if (name === ".yarnrc.yml" && /^(?:plugins|yarnPath):/m.test((0, import_node_fs5.readFileSync)(file, "utf8")))
|
|
12815
|
+
throw new Error("Custom Yarn code requires installation");
|
|
12816
|
+
if (stat.isDirectory()) return walk(file);
|
|
12817
|
+
else {
|
|
12818
|
+
if (name === "package.json") {
|
|
12819
|
+
const manifest2 = JSON.parse((0, import_node_fs5.readFileSync)(file, "utf8"));
|
|
12820
|
+
for (const dependencies of [
|
|
12821
|
+
manifest2.dependencies,
|
|
12822
|
+
manifest2.devDependencies,
|
|
12823
|
+
manifest2.optionalDependencies
|
|
12824
|
+
]) {
|
|
12825
|
+
for (const spec of Object.values(dependencies ?? {})) {
|
|
12826
|
+
if (typeof spec !== "string") throw new Error("Invalid dependency");
|
|
12827
|
+
const localSpec = /^(?:file:|link:|portal:)(.*)$/.exec(spec);
|
|
12828
|
+
if (localSpec) {
|
|
12829
|
+
const target = (0, import_node_path5.resolve)(directory, localSpec[1]);
|
|
12830
|
+
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)))
|
|
12831
|
+
throw new Error("External or excluded dependency is not snapshot eligible");
|
|
12832
|
+
}
|
|
12833
|
+
}
|
|
12834
|
+
}
|
|
12835
|
+
outputs.add((0, import_node_path5.relative)(project.root, (0, import_node_path5.join)(directory, "node_modules")));
|
|
12836
|
+
}
|
|
12837
|
+
return [local];
|
|
12838
|
+
}
|
|
12839
|
+
});
|
|
12840
|
+
const inputs = walk(project.root);
|
|
12841
|
+
const inputHash = digestTree(project.root, inputs, project.root);
|
|
12842
|
+
const userRoot = environment.HOME ?? (0, import_node_os3.homedir)();
|
|
12843
|
+
const configuration = new Set(
|
|
12844
|
+
[
|
|
12845
|
+
(0, import_node_path5.join)(userRoot, ".npmrc"),
|
|
12846
|
+
(0, import_node_path5.join)(userRoot, ".yarnrc"),
|
|
12847
|
+
(0, import_node_path5.join)(userRoot, ".yarnrc.yml"),
|
|
12848
|
+
(0, import_node_path5.join)(userRoot, ".config/pnpm/rc"),
|
|
12849
|
+
"/etc/npmrc",
|
|
12850
|
+
"/usr/local/etc/npmrc",
|
|
12851
|
+
environment.npm_config_userconfig,
|
|
12852
|
+
environment.NPM_CONFIG_USERCONFIG,
|
|
12853
|
+
environment.npm_config_globalconfig,
|
|
12854
|
+
environment.NPM_CONFIG_GLOBALCONFIG
|
|
12855
|
+
].filter((path) => !!path)
|
|
12856
|
+
);
|
|
12857
|
+
for (let cursor = (0, import_node_path5.dirname)(project.root); ; cursor = (0, import_node_path5.dirname)(cursor)) {
|
|
12858
|
+
for (const name of [".npmrc", ".yarnrc", ".yarnrc.yml"]) configuration.add((0, import_node_path5.join)(cursor, name));
|
|
12859
|
+
if (cursor === (0, import_node_path5.dirname)(cursor)) break;
|
|
12860
|
+
}
|
|
12861
|
+
const configHash = [...configuration].sort().map((file) => {
|
|
12862
|
+
if (!(0, import_node_fs5.existsSync)(file)) return [file, null];
|
|
12863
|
+
if (/(?:yarnPath|plugins|pnpmfile)/.test((0, import_node_fs5.readFileSync)(file, "utf8")))
|
|
12864
|
+
throw new Error("Custom package-manager configuration requires installation");
|
|
12865
|
+
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))];
|
|
12866
|
+
});
|
|
12867
|
+
const yarnCache = (0, import_node_path5.join)(cacheRoot, "yarn");
|
|
12868
|
+
const nativeCache = project.manager === "yarn" && (0, import_node_fs5.existsSync)(yarnCache) ? digestTree(yarnCache, (0, import_node_fs5.readdirSync)(yarnCache), yarnCache) : null;
|
|
12869
|
+
const key = (0, import_node_crypto2.createHash)("sha256").update(
|
|
12870
|
+
JSON.stringify({
|
|
12871
|
+
format: DEPENDENCY_SNAPSHOT_FORMAT,
|
|
12872
|
+
root: project.root,
|
|
12873
|
+
cacheRoot,
|
|
12874
|
+
manager: project.manager,
|
|
12875
|
+
managerVersion,
|
|
12876
|
+
declared: project.declared,
|
|
12877
|
+
platform: process.platform,
|
|
12878
|
+
arch: process.arch,
|
|
12879
|
+
kernel: (0, import_node_os3.release)(),
|
|
12880
|
+
runtime: process.versions,
|
|
12881
|
+
environment: Object.entries(environment).sort(([a], [b]) => a.localeCompare(b)),
|
|
12882
|
+
inputHash,
|
|
12883
|
+
configHash,
|
|
12884
|
+
nativeCache
|
|
12885
|
+
})
|
|
12886
|
+
).digest("hex");
|
|
12887
|
+
const projectKey = (0, import_node_crypto2.createHash)("sha256").update(project.root).digest("hex");
|
|
12888
|
+
return {
|
|
12889
|
+
root: project.root,
|
|
12890
|
+
cacheRoot,
|
|
12891
|
+
directory: (0, import_node_path5.join)(cacheRoot, "prepared-v1", projectKey),
|
|
12892
|
+
key,
|
|
12893
|
+
outputs: [...outputs].sort()
|
|
12894
|
+
};
|
|
12895
|
+
} catch {
|
|
12896
|
+
return void 0;
|
|
12897
|
+
}
|
|
12898
|
+
}
|
|
12899
|
+
function copy(source, destination) {
|
|
12900
|
+
(0, import_node_fs5.cpSync)(source, destination, {
|
|
12901
|
+
recursive: true,
|
|
12902
|
+
dereference: false,
|
|
12903
|
+
verbatimSymlinks: true,
|
|
12904
|
+
mode: import_node_fs5.constants.COPYFILE_FICLONE
|
|
12905
|
+
});
|
|
12906
|
+
}
|
|
12907
|
+
function restoreDependencySnapshot(snapshot) {
|
|
12908
|
+
let staging;
|
|
12909
|
+
let activated = [];
|
|
12910
|
+
let previous = [];
|
|
12911
|
+
try {
|
|
12912
|
+
if ((0, import_node_fs5.lstatSync)(snapshot.directory, { throwIfNoEntry: false })?.isSymbolicLink()) return false;
|
|
12913
|
+
const record = import_zod2.z.object({
|
|
12914
|
+
format: import_zod2.z.literal(DEPENDENCY_SNAPSHOT_FORMAT),
|
|
12915
|
+
key: import_zod2.z.literal(snapshot.key),
|
|
12916
|
+
sha256: import_zod2.z.string().regex(/^[a-f0-9]{64}$/),
|
|
12917
|
+
outputs: import_zod2.z.array(import_zod2.z.string()).refine(
|
|
12918
|
+
(paths) => new Set(paths).size === paths.length && paths.every((path) => snapshot.outputs.includes(path))
|
|
12919
|
+
)
|
|
12920
|
+
}).parse(JSON.parse((0, import_node_fs5.readFileSync)((0, import_node_path5.join)(snapshot.directory, "snapshot.json"), "utf8")));
|
|
12921
|
+
const stored = (0, import_node_path5.join)(snapshot.directory, "files");
|
|
12922
|
+
if (!record.outputs.length || digestTree(stored, record.outputs, snapshot.root) !== record.sha256) return false;
|
|
12923
|
+
for (const path of snapshot.outputs) {
|
|
12924
|
+
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)) {
|
|
12925
|
+
if ((0, import_node_fs5.lstatSync)(cursor, { throwIfNoEntry: false })?.isSymbolicLink()) return false;
|
|
12926
|
+
if (cursor === snapshot.root) break;
|
|
12927
|
+
}
|
|
12928
|
+
}
|
|
12929
|
+
staging = (0, import_node_fs5.mkdtempSync)((0, import_node_path5.join)(snapshot.root, DEPENDENCY_MUTEX, "snapshot-"));
|
|
12930
|
+
for (const path of record.outputs) copy((0, import_node_path5.join)(stored, path), (0, import_node_path5.join)(staging, "next", path));
|
|
12931
|
+
if (digestTree((0, import_node_path5.join)(staging, "next"), record.outputs, snapshot.root) !== record.sha256) return false;
|
|
12932
|
+
for (const path of snapshot.outputs) {
|
|
12933
|
+
const target = (0, import_node_path5.join)(snapshot.root, path);
|
|
12934
|
+
if ((0, import_node_fs5.lstatSync)(target, { throwIfNoEntry: false })) {
|
|
12935
|
+
const backup = (0, import_node_path5.join)(staging, "previous", path);
|
|
12936
|
+
(0, import_node_fs5.mkdirSync)((0, import_node_path5.dirname)(backup), { recursive: true });
|
|
12937
|
+
(0, import_node_fs5.renameSync)(target, backup);
|
|
12938
|
+
previous = [...previous, path];
|
|
12939
|
+
}
|
|
12940
|
+
if (record.outputs.includes(path)) {
|
|
12941
|
+
(0, import_node_fs5.mkdirSync)((0, import_node_path5.dirname)(target), { recursive: true });
|
|
12942
|
+
(0, import_node_fs5.renameSync)((0, import_node_path5.join)(staging, "next", path), target);
|
|
12943
|
+
activated = [...activated, path];
|
|
12944
|
+
}
|
|
12945
|
+
}
|
|
12946
|
+
return true;
|
|
12947
|
+
} catch {
|
|
12948
|
+
try {
|
|
12949
|
+
for (const path of [...activated].reverse()) (0, import_node_fs5.rmSync)((0, import_node_path5.join)(snapshot.root, path), { recursive: true, force: true });
|
|
12950
|
+
for (const path of [...previous].reverse())
|
|
12951
|
+
(0, import_node_fs5.renameSync)((0, import_node_path5.join)(staging, "previous", path), (0, import_node_path5.join)(snapshot.root, path));
|
|
12952
|
+
} catch {
|
|
12953
|
+
const retained = staging;
|
|
12954
|
+
staging = void 0;
|
|
12955
|
+
throw new Error(`Dependency snapshot activation failed; previous files retained in ${retained}`);
|
|
12956
|
+
}
|
|
12957
|
+
return false;
|
|
12958
|
+
} finally {
|
|
12959
|
+
if (staging) (0, import_node_fs5.rmSync)(staging, { recursive: true, force: true });
|
|
12960
|
+
}
|
|
12961
|
+
}
|
|
12962
|
+
function saveDependencySnapshot(snapshot) {
|
|
12963
|
+
let staging;
|
|
12964
|
+
try {
|
|
12965
|
+
const outputs = snapshot.outputs.filter((path) => (0, import_node_fs5.lstatSync)((0, import_node_path5.join)(snapshot.root, path), { throwIfNoEntry: false }));
|
|
12966
|
+
if (!outputs.length) return;
|
|
12967
|
+
const sha256 = digestTree(snapshot.root, outputs, snapshot.root);
|
|
12968
|
+
(0, import_node_fs5.mkdirSync)((0, import_node_path5.dirname)(snapshot.directory), { recursive: true });
|
|
12969
|
+
staging = (0, import_node_fs5.mkdtempSync)((0, import_node_path5.join)((0, import_node_path5.dirname)(snapshot.directory), ".prepared-"));
|
|
12970
|
+
for (const path of outputs) copy((0, import_node_path5.join)(snapshot.root, path), (0, import_node_path5.join)(staging, "files", path));
|
|
12971
|
+
if (digestTree((0, import_node_path5.join)(staging, "files"), outputs, snapshot.root) !== sha256) return;
|
|
12972
|
+
(0, import_node_fs5.writeFileSync)(
|
|
12973
|
+
(0, import_node_path5.join)(staging, "snapshot.json"),
|
|
12974
|
+
JSON.stringify({ format: DEPENDENCY_SNAPSHOT_FORMAT, key: snapshot.key, sha256, outputs })
|
|
12975
|
+
);
|
|
12976
|
+
(0, import_node_fs5.rmSync)(snapshot.directory, { recursive: true, force: true });
|
|
12977
|
+
(0, import_node_fs5.renameSync)(staging, snapshot.directory);
|
|
12978
|
+
} catch {
|
|
12979
|
+
} finally {
|
|
12980
|
+
if (staging) (0, import_node_fs5.rmSync)(staging, { recursive: true, force: true });
|
|
12981
|
+
}
|
|
12982
|
+
}
|
|
12983
|
+
|
|
12647
12984
|
// packages/plugin/src/dependencies.ts
|
|
12648
12985
|
var execute = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
12649
12986
|
var installations = /* @__PURE__ */ new Map();
|
|
12650
12987
|
function checkTransactionPath(root, file) {
|
|
12651
|
-
const local = (0,
|
|
12652
|
-
if (!local || local.startsWith("../") || (0,
|
|
12988
|
+
const local = (0, import_node_path6.relative)(root, file);
|
|
12989
|
+
if (!local || local.startsWith("../") || (0, import_node_path6.resolve)(root, local) !== file)
|
|
12653
12990
|
throw new Error("Transaction path must stay inside its project");
|
|
12654
|
-
for (let cursor = file; cursor !== root; cursor = (0,
|
|
12655
|
-
const stat = (0,
|
|
12991
|
+
for (let cursor = file; cursor !== root; cursor = (0, import_node_path6.dirname)(cursor)) {
|
|
12992
|
+
const stat = (0, import_node_fs6.lstatSync)(cursor, { throwIfNoEntry: false });
|
|
12656
12993
|
if (stat?.isSymbolicLink()) throw new Error("Transaction path contains a symbolic link");
|
|
12657
12994
|
}
|
|
12658
12995
|
}
|
|
12659
12996
|
function manifest(root) {
|
|
12660
|
-
const file = (0,
|
|
12661
|
-
return (0,
|
|
12997
|
+
const file = (0, import_node_path6.join)(root, "package.json");
|
|
12998
|
+
return (0, import_node_fs6.existsSync)(file) ? JSON.parse((0, import_node_fs6.readFileSync)(file, "utf8")) : {};
|
|
12662
12999
|
}
|
|
12663
13000
|
function dependencyCacheRoot(root) {
|
|
12664
|
-
return (0,
|
|
13001
|
+
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
13002
|
}
|
|
12666
13003
|
function dependencyPaths(cwd) {
|
|
12667
|
-
const start = (0,
|
|
13004
|
+
const start = (0, import_node_fs6.realpathSync)(cwd);
|
|
12668
13005
|
const ancestors = [];
|
|
12669
|
-
for (let path = start; ; path = (0,
|
|
13006
|
+
for (let path = start; ; path = (0, import_node_path6.dirname)(path)) {
|
|
12670
13007
|
ancestors.push(path);
|
|
12671
|
-
if ((0,
|
|
13008
|
+
if ((0, import_node_fs6.existsSync)((0, import_node_path6.join)(path, ".git")) || (0, import_node_path6.dirname)(path) === path) break;
|
|
12672
13009
|
}
|
|
12673
|
-
const repository = ancestors.find((path) => (0,
|
|
12674
|
-
const target = (0,
|
|
13010
|
+
const repository = ancestors.find((path) => (0, import_node_fs6.existsSync)((0, import_node_path6.join)(path, ".git")));
|
|
13011
|
+
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
13012
|
const root = ancestors.find((path) => {
|
|
12676
|
-
if (path === target || !(0,
|
|
13013
|
+
if (path === target || !(0, import_node_path6.relative)(path, target) || (0, import_node_path6.relative)(path, target).startsWith("..")) return false;
|
|
12677
13014
|
const workspaces = manifest(path).workspaces;
|
|
12678
|
-
const pnpmWorkspace = (0,
|
|
12679
|
-
const patterns = (0,
|
|
13015
|
+
const pnpmWorkspace = (0, import_node_path6.join)(path, "pnpm-workspace.yaml");
|
|
13016
|
+
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
13017
|
if (!Array.isArray(patterns)) return false;
|
|
12681
|
-
const local = (0,
|
|
13018
|
+
const local = (0, import_node_path6.relative)(path, target).split("\\").join("/");
|
|
12682
13019
|
const globs = patterns.filter((value) => typeof value === "string");
|
|
12683
|
-
return globs.some((pattern) => !pattern.startsWith("!") && (0,
|
|
13020
|
+
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
13021
|
}) ?? target;
|
|
12685
13022
|
return { root, target };
|
|
12686
13023
|
}
|
|
@@ -12688,7 +13025,7 @@ function resolveDependencyProject(cwd) {
|
|
|
12688
13025
|
const { root, target } = dependencyPaths(cwd);
|
|
12689
13026
|
const declared = manifest(root).packageManager;
|
|
12690
13027
|
const locked = Object.keys(PACKAGE_MANAGER_LOCKS).filter(
|
|
12691
|
-
(manager2) => PACKAGE_MANAGER_LOCKS[manager2].some((file) => (0,
|
|
13028
|
+
(manager2) => PACKAGE_MANAGER_LOCKS[manager2].some((file) => (0, import_node_fs6.existsSync)((0, import_node_path6.join)(root, file)))
|
|
12692
13029
|
);
|
|
12693
13030
|
const manager = declared?.split("@")[0];
|
|
12694
13031
|
if (manager && !(manager in PACKAGE_MANAGER_LOCKS)) throw new Error(`unsupported package manager: ${declared}`);
|
|
@@ -12698,7 +13035,7 @@ function resolveDependencyProject(cwd) {
|
|
|
12698
13035
|
return {
|
|
12699
13036
|
target,
|
|
12700
13037
|
root,
|
|
12701
|
-
manager: manager ?? locked[0] ?? ((0,
|
|
13038
|
+
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
13039
|
declared
|
|
12703
13040
|
};
|
|
12704
13041
|
}
|
|
@@ -12726,42 +13063,48 @@ function installCommand(project, frozen) {
|
|
|
12726
13063
|
return ["npm", [frozen ? "ci" : "install", "--ignore-scripts", "--no-audit", "--no-fund"]];
|
|
12727
13064
|
}
|
|
12728
13065
|
}
|
|
13066
|
+
function installEnvironment(cacheRoot) {
|
|
13067
|
+
return (0, import_common.childProcessEnvironment)({
|
|
13068
|
+
...(0, import_common.packageCacheEnvironment)(dependencyCacheRoot(cacheRoot)),
|
|
13069
|
+
YARN_ENABLE_SCRIPTS: "false",
|
|
13070
|
+
COREPACK_ENABLE_DOWNLOAD_PROMPT: "0",
|
|
13071
|
+
COREPACK_ENABLE_AUTO_PIN: "0"
|
|
13072
|
+
});
|
|
13073
|
+
}
|
|
13074
|
+
function isClassicYarn(project) {
|
|
13075
|
+
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"));
|
|
13076
|
+
}
|
|
12729
13077
|
async function run(project, command, cwd, cacheRoot) {
|
|
12730
13078
|
const [file, args] = command;
|
|
12731
|
-
const yarnClassic =
|
|
13079
|
+
const yarnClassic = isClassicYarn(project);
|
|
12732
13080
|
const flags = yarnClassic ? [
|
|
12733
13081
|
...args.filter((arg) => arg !== "--mode=skip-build").map((arg) => arg === "--immutable" ? "--frozen-lockfile" : arg),
|
|
12734
13082
|
"--ignore-scripts"
|
|
12735
|
-
] : project.manager === "pnpm" && args[0] === "add" && project.root === cwd && (0,
|
|
13083
|
+
] : 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
13084
|
const pinned = project.declared && file !== "bun" || yarnClassic;
|
|
12737
13085
|
const executable = yarnClassic && !project.declared ? CLASSIC_YARN : file;
|
|
12738
13086
|
await execute(pinned ? "corepack" : file, pinned ? [executable, ...flags] : flags, {
|
|
12739
13087
|
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
|
-
}),
|
|
13088
|
+
env: installEnvironment(cacheRoot),
|
|
12746
13089
|
timeout: DEPENDENCY_INSTALL_TIMEOUT_MS,
|
|
12747
13090
|
maxBuffer: 4 * 1024 * 1024
|
|
12748
13091
|
});
|
|
12749
13092
|
}
|
|
12750
13093
|
async function verifyProjectDependencies(project, names) {
|
|
12751
13094
|
if (!names.length) return;
|
|
12752
|
-
const pnp = (0,
|
|
12753
|
-
const loader = (0,
|
|
13095
|
+
const pnp = (0, import_node_path6.join)(project.root, ".pnp.cjs");
|
|
13096
|
+
const loader = (0, import_node_path6.join)(project.root, ".pnp.loader.mjs");
|
|
12754
13097
|
await execute(
|
|
12755
13098
|
process.execPath,
|
|
12756
13099
|
[
|
|
12757
|
-
...(0,
|
|
12758
|
-
...(0,
|
|
13100
|
+
...(0, import_node_fs6.existsSync)(pnp) ? ["--require", pnp] : [],
|
|
13101
|
+
...(0, import_node_fs6.existsSync)(loader) ? ["--loader", loader] : [],
|
|
12759
13102
|
"--input-type=module",
|
|
12760
13103
|
"-e",
|
|
12761
13104
|
`import { createRequire } from 'node:module';
|
|
12762
13105
|
import { existsSync } from 'node:fs';
|
|
12763
13106
|
import { fileURLToPath } from 'node:url';
|
|
12764
|
-
const require = createRequire(${JSON.stringify((0,
|
|
13107
|
+
const require = createRequire(${JSON.stringify((0, import_node_path6.join)(project.target, "package.json"))});
|
|
12765
13108
|
for (const name of ${JSON.stringify(names)}) {
|
|
12766
13109
|
try { require.resolve(name); } catch {
|
|
12767
13110
|
const entry = import.meta.resolve(name);
|
|
@@ -12779,19 +13122,19 @@ async function withDependencyInstall(cwd, action) {
|
|
|
12779
13122
|
const previous = installations.get(root) ?? Promise.resolve();
|
|
12780
13123
|
const next = previous.catch(() => {
|
|
12781
13124
|
}).then(async () => {
|
|
12782
|
-
const mutex = (0,
|
|
13125
|
+
const mutex = (0, import_node_path6.join)(root, DEPENDENCY_MUTEX);
|
|
12783
13126
|
try {
|
|
12784
|
-
(0,
|
|
13127
|
+
(0, import_node_fs6.mkdirSync)(mutex);
|
|
12785
13128
|
} catch {
|
|
12786
13129
|
throw new Error(
|
|
12787
13130
|
"Another dependency installation is running or needs recovery; use octonodes plugin recover after it exits"
|
|
12788
13131
|
);
|
|
12789
13132
|
}
|
|
12790
|
-
(0,
|
|
13133
|
+
(0, import_node_fs6.writeFileSync)((0, import_node_path6.join)(mutex, "owner.json"), JSON.stringify({ pid: process.pid }));
|
|
12791
13134
|
try {
|
|
12792
13135
|
return await action();
|
|
12793
13136
|
} finally {
|
|
12794
|
-
if (!(0,
|
|
13137
|
+
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
13138
|
}
|
|
12796
13139
|
});
|
|
12797
13140
|
installations.set(root, next);
|
|
@@ -12802,6 +13145,8 @@ async function withDependencyInstall(cwd, action) {
|
|
|
12802
13145
|
}
|
|
12803
13146
|
}
|
|
12804
13147
|
async function reconcileDependencies(cwd, dependencies, options = {}) {
|
|
13148
|
+
if (options.metadataOnly && (dependencies.length || options.remove?.length || options.frozen))
|
|
13149
|
+
throw new Error("Metadata-only transactions cannot change or restore dependencies");
|
|
12805
13150
|
if (options.frozen && (dependencies.length || options.remove?.length))
|
|
12806
13151
|
throw new Error("Frozen installation cannot add or remove dependencies");
|
|
12807
13152
|
for (const { name, spec, subpaths } of dependencies) {
|
|
@@ -12815,64 +13160,82 @@ async function reconcileDependencies(cwd, dependencies, options = {}) {
|
|
|
12815
13160
|
}
|
|
12816
13161
|
}
|
|
12817
13162
|
const project = resolveDependencyProject(cwd);
|
|
12818
|
-
const packageJson = (0,
|
|
12819
|
-
if (!dependencies.length && !(0,
|
|
12820
|
-
const hasLock = PACKAGE_MANAGER_LOCKS[project.manager].some((file) => (0,
|
|
13163
|
+
const packageJson = (0, import_node_path6.join)(project.target, "package.json");
|
|
13164
|
+
if (!dependencies.length && !(0, import_node_fs6.existsSync)(packageJson) && !options.commit) return;
|
|
13165
|
+
const hasLock = PACKAGE_MANAGER_LOCKS[project.manager].some((file) => (0, import_node_fs6.existsSync)((0, import_node_path6.join)(project.root, file)));
|
|
12821
13166
|
if (options.frozen && !hasLock)
|
|
12822
13167
|
throw new Error("commit the native package-manager lockfile before preparing this worktree");
|
|
12823
13168
|
const files = [
|
|
12824
13169
|
.../* @__PURE__ */ new Set([
|
|
12825
13170
|
packageJson,
|
|
12826
|
-
(0,
|
|
12827
|
-
...Object.values(PACKAGE_MANAGER_LOCKS).flat().map((file) => (0,
|
|
12828
|
-
(0,
|
|
13171
|
+
(0, import_node_path6.join)(project.root, "package.json"),
|
|
13172
|
+
...Object.values(PACKAGE_MANAGER_LOCKS).flat().map((file) => (0, import_node_path6.join)(project.root, file)),
|
|
13173
|
+
(0, import_node_path6.join)(project.root, "pnpm-workspace.yaml"),
|
|
12829
13174
|
...options.transactionFiles ?? []
|
|
12830
13175
|
])
|
|
12831
13176
|
];
|
|
12832
13177
|
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,
|
|
13178
|
+
const before = new Map(files.map((path) => [path, (0, import_node_fs6.existsSync)(path) ? (0, import_node_fs6.readFileSync)(path) : void 0]));
|
|
13179
|
+
const journal = (0, import_node_path6.join)(project.root, DEPENDENCY_MUTEX, "journal.json");
|
|
13180
|
+
const hadModules = (0, import_node_fs6.existsSync)((0, import_node_path6.join)(project.root, "node_modules"));
|
|
12836
13181
|
const pnpFiles = [".pnp.cjs", ".pnp.loader.mjs", ".pnp.data.json"];
|
|
12837
13182
|
const pnpBefore = new Map(
|
|
12838
13183
|
pnpFiles.map((file) => {
|
|
12839
|
-
const path = (0,
|
|
12840
|
-
return [path, (0,
|
|
13184
|
+
const path = (0, import_node_path6.join)(project.root, file);
|
|
13185
|
+
return [path, (0, import_node_fs6.existsSync)(path) ? (0, import_node_fs6.readFileSync)(path) : void 0];
|
|
12841
13186
|
})
|
|
12842
13187
|
);
|
|
12843
|
-
const hadInstall = hadModules || (0,
|
|
13188
|
+
const hadInstall = hadModules || (0, import_node_fs6.existsSync)((0, import_node_path6.join)(project.root, ".pnp.cjs"));
|
|
12844
13189
|
let metadataTouched = false;
|
|
12845
13190
|
const metadata = new Set(options.transactionFiles ?? []);
|
|
12846
13191
|
const restoreBefore = () => {
|
|
12847
13192
|
for (const [path, content] of before) {
|
|
12848
13193
|
if (metadata.has(path) && !metadataTouched) continue;
|
|
12849
|
-
if (content === void 0) (0,
|
|
12850
|
-
else (0,
|
|
13194
|
+
if (content === void 0) (0, import_node_fs6.rmSync)(path, { force: true });
|
|
13195
|
+
else (0, import_node_fs6.writeFileSync)(path, content);
|
|
12851
13196
|
}
|
|
12852
13197
|
};
|
|
12853
|
-
if (hadInstall && !hasLock)
|
|
13198
|
+
if (hadInstall && !hasLock && !options.metadataOnly)
|
|
12854
13199
|
throw new Error(
|
|
12855
13200
|
"create a native lockfile before updating existing dependencies so failed installations can be recovered"
|
|
12856
13201
|
);
|
|
12857
13202
|
try {
|
|
12858
|
-
if ((0,
|
|
12859
|
-
(0,
|
|
13203
|
+
if (options.metadataOnly && (0, import_node_fs6.existsSync)((0, import_node_path6.dirname)(journal)))
|
|
13204
|
+
(0, import_node_fs6.writeFileSync)((0, import_node_path6.join)((0, import_node_path6.dirname)(journal), "metadata-only"), "1");
|
|
13205
|
+
if ((0, import_node_fs6.existsSync)((0, import_node_path6.dirname)(journal)))
|
|
13206
|
+
(0, import_node_fs6.writeFileSync)(
|
|
12860
13207
|
journal,
|
|
12861
13208
|
JSON.stringify(
|
|
12862
13209
|
[...before].map(([path, content]) => ({
|
|
12863
|
-
path: (0,
|
|
13210
|
+
path: (0, import_node_path6.relative)(project.root, path).replaceAll("\\", "/"),
|
|
12864
13211
|
content: content?.toString("base64") ?? null
|
|
12865
13212
|
}))
|
|
12866
13213
|
)
|
|
12867
13214
|
);
|
|
12868
|
-
if (
|
|
12869
|
-
|
|
12870
|
-
(
|
|
13215
|
+
if (options.metadataOnly) {
|
|
13216
|
+
metadataTouched = true;
|
|
13217
|
+
options.commit?.();
|
|
13218
|
+
(0, import_node_fs6.rmSync)(journal, { force: true });
|
|
13219
|
+
(0, import_node_fs6.rmSync)((0, import_node_path6.join)((0, import_node_path6.dirname)(journal), "metadata-only"), { force: true });
|
|
13220
|
+
return;
|
|
13221
|
+
}
|
|
13222
|
+
if (!(0, import_node_fs6.existsSync)(packageJson)) {
|
|
13223
|
+
(0, import_node_fs6.mkdirSync)(project.target, { recursive: true });
|
|
13224
|
+
(0, import_node_fs6.writeFileSync)(
|
|
12871
13225
|
packageJson,
|
|
12872
13226
|
JSON.stringify({ private: true, packageManager: DEFAULT_PACKAGE_MANAGER }, null, 2) + "\n"
|
|
12873
13227
|
);
|
|
12874
13228
|
}
|
|
12875
13229
|
const current = resolveDependencyProject(cwd);
|
|
13230
|
+
const snapshotEnvironment = installEnvironment(options.cacheRoot);
|
|
13231
|
+
const pinnedManager = current.declared && current.manager !== "bun" || isClassicYarn(current);
|
|
13232
|
+
const versionCommand = isClassicYarn(current) && !current.declared ? CLASSIC_YARN : current.manager;
|
|
13233
|
+
const managerVersion = options.frozen && (options.cacheRoot || (0, import_common.OCTONODE_PACKAGE_CACHE)()) ? await execute(
|
|
13234
|
+
pinnedManager ? "corepack" : current.manager,
|
|
13235
|
+
pinnedManager ? [versionCommand, "--version"] : ["--version"],
|
|
13236
|
+
{ cwd: current.root, env: snapshotEnvironment, timeout: 3e4 }
|
|
13237
|
+
).then(({ stdout }) => stdout.trim()).catch(() => void 0) : void 0;
|
|
13238
|
+
const snapshot = managerVersion ? dependencySnapshot(current, dependencyCacheRoot(options.cacheRoot), managerVersion, snapshotEnvironment) : void 0;
|
|
12876
13239
|
if (options.remove?.length) {
|
|
12877
13240
|
for (const name of options.remove)
|
|
12878
13241
|
if (!/^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*$/i.test(name))
|
|
@@ -12880,81 +13243,92 @@ async function reconcileDependencies(cwd, dependencies, options = {}) {
|
|
|
12880
13243
|
const args = current.manager === "npm" ? ["uninstall", "--ignore-scripts", "--no-audit", "--no-fund"] : current.manager === "yarn" ? ["remove", "--mode=skip-build"] : ["remove", "--ignore-scripts"];
|
|
12881
13244
|
await run(current, [current.manager, [...args, ...options.remove]], current.target, options.cacheRoot);
|
|
12882
13245
|
}
|
|
12883
|
-
|
|
12884
|
-
|
|
12885
|
-
|
|
12886
|
-
current
|
|
12887
|
-
|
|
12888
|
-
|
|
12889
|
-
|
|
12890
|
-
|
|
12891
|
-
|
|
13246
|
+
const restored = snapshot ? restoreDependencySnapshot(snapshot) : false;
|
|
13247
|
+
if (!restored)
|
|
13248
|
+
await run(
|
|
13249
|
+
current,
|
|
13250
|
+
dependencies.length ? packageManagerAdd(
|
|
13251
|
+
current.manager,
|
|
13252
|
+
...dependencies.map(({ name, spec }) => spec.startsWith(`${name}@`) ? spec : `${name}@${spec}`)
|
|
13253
|
+
) : installCommand(current, options.frozen ?? false),
|
|
13254
|
+
dependencies.length ? current.target : current.root,
|
|
13255
|
+
options.cacheRoot
|
|
13256
|
+
);
|
|
12892
13257
|
await verifyProjectDependencies(
|
|
12893
13258
|
current,
|
|
12894
13259
|
dependencies.flatMap(({ name, subpaths }) => subpaths ? subpaths.map((path) => name + path.slice(1)) : [name])
|
|
12895
13260
|
);
|
|
12896
13261
|
if (options.frozen) {
|
|
12897
13262
|
for (const [path, content] of before) {
|
|
12898
|
-
const after = (0,
|
|
13263
|
+
const after = (0, import_node_fs6.existsSync)(path) ? (0, import_node_fs6.readFileSync)(path) : void 0;
|
|
12899
13264
|
if (content?.equals(after ?? Buffer.alloc(0)) || !content && !after) continue;
|
|
12900
13265
|
if (path.endsWith("package.json") && content && after && (0, import_node_util.isDeepStrictEqual)(JSON.parse(content.toString()), JSON.parse(after.toString()))) {
|
|
12901
|
-
(0,
|
|
13266
|
+
(0, import_node_fs6.writeFileSync)(path, content);
|
|
12902
13267
|
} else {
|
|
12903
|
-
throw new Error(`frozen installation changed ${(0,
|
|
13268
|
+
throw new Error(`frozen installation changed ${(0, import_node_path6.relative)(project.root, path)}`);
|
|
12904
13269
|
}
|
|
12905
13270
|
}
|
|
12906
13271
|
}
|
|
12907
13272
|
for (const path of metadata) {
|
|
12908
13273
|
const content = before.get(path);
|
|
12909
|
-
const current2 = (0,
|
|
13274
|
+
const current2 = (0, import_node_fs6.existsSync)(path) ? (0, import_node_fs6.readFileSync)(path) : void 0;
|
|
12910
13275
|
if (!(content?.equals(current2 ?? Buffer.alloc(0)) || !content && !current2))
|
|
12911
13276
|
throw new Error(
|
|
12912
|
-
`Owner metadata changed during installation: ${(0,
|
|
13277
|
+
`Owner metadata changed during installation: ${(0, import_node_path6.relative)(project.root, path)}; refresh and retry`
|
|
12913
13278
|
);
|
|
12914
13279
|
}
|
|
12915
13280
|
metadataTouched = true;
|
|
12916
13281
|
options.commit?.();
|
|
12917
|
-
(0,
|
|
13282
|
+
(0, import_node_fs6.rmSync)(journal, { force: true });
|
|
13283
|
+
if (snapshot && !restored) {
|
|
13284
|
+
const after = dependencySnapshot(
|
|
13285
|
+
current,
|
|
13286
|
+
dependencyCacheRoot(options.cacheRoot),
|
|
13287
|
+
managerVersion,
|
|
13288
|
+
snapshotEnvironment
|
|
13289
|
+
);
|
|
13290
|
+
if (after?.key === snapshot.key) saveDependencySnapshot(after);
|
|
13291
|
+
}
|
|
12918
13292
|
} catch (error) {
|
|
12919
|
-
const changed = [...before].filter(([path, content]) => (0,
|
|
13293
|
+
const changed = [...before].filter(([path, content]) => (0, import_node_fs6.existsSync)(path) && !content?.equals((0, import_node_fs6.readFileSync)(path)));
|
|
12920
13294
|
if (changed.length) {
|
|
12921
|
-
const backup = (0,
|
|
13295
|
+
const backup = (0, import_node_path6.join)(project.root, `.octonode-recovery-${Date.now()}`);
|
|
12922
13296
|
for (const [path] of changed) {
|
|
12923
13297
|
checkTransactionPath(project.root, path);
|
|
12924
|
-
const target = (0,
|
|
12925
|
-
(0,
|
|
12926
|
-
(0,
|
|
13298
|
+
const target = (0, import_node_path6.join)(backup, (0, import_node_path6.relative)(project.root, path));
|
|
13299
|
+
(0, import_node_fs6.mkdirSync)((0, import_node_path6.dirname)(target), { recursive: true });
|
|
13300
|
+
(0, import_node_fs6.writeFileSync)(target, (0, import_node_fs6.readFileSync)(path));
|
|
12927
13301
|
}
|
|
12928
13302
|
process.stderr.write(`Pre-rollback files preserved in ${backup}
|
|
12929
13303
|
`);
|
|
12930
13304
|
}
|
|
12931
13305
|
restoreBefore();
|
|
12932
13306
|
let recovery = "";
|
|
12933
|
-
if (hadInstall && hasLock) {
|
|
13307
|
+
if (!options.metadataOnly && hadInstall && hasLock) {
|
|
12934
13308
|
try {
|
|
12935
13309
|
await run(project, installCommand(project, true), project.root, options.cacheRoot);
|
|
12936
13310
|
} catch {
|
|
12937
13311
|
recovery = "; manifests restored, but dependency recovery failed \u2014 run a frozen install before executing workflows";
|
|
12938
13312
|
}
|
|
12939
13313
|
restoreBefore();
|
|
12940
|
-
} else if (!hadInstall) {
|
|
12941
|
-
(0,
|
|
13314
|
+
} else if (!options.metadataOnly && !hadInstall) {
|
|
13315
|
+
(0, import_node_fs6.rmSync)((0, import_node_path6.join)(project.root, "node_modules"), { recursive: true, force: true });
|
|
12942
13316
|
}
|
|
12943
13317
|
for (const [path, content] of pnpBefore) {
|
|
12944
|
-
if (content === void 0) (0,
|
|
12945
|
-
else (0,
|
|
13318
|
+
if (content === void 0) (0, import_node_fs6.rmSync)(path, { force: true });
|
|
13319
|
+
else (0, import_node_fs6.writeFileSync)(path, content);
|
|
12946
13320
|
}
|
|
12947
13321
|
const failure = error;
|
|
12948
|
-
if (!recovery) (0,
|
|
13322
|
+
if (!recovery) (0, import_node_fs6.rmSync)(journal, { force: true });
|
|
12949
13323
|
throw new Error(`package installation failed: ${failure.stderr?.trim() || failure.message}${recovery}`);
|
|
12950
13324
|
}
|
|
12951
13325
|
}
|
|
12952
13326
|
async function recoverDependencyInstall(cwd) {
|
|
12953
13327
|
const project = resolveDependencyProject(cwd);
|
|
12954
|
-
const mutex = (0,
|
|
12955
|
-
if (!(0,
|
|
12956
|
-
checkTransactionPath(project.root, (0,
|
|
12957
|
-
const owner = JSON.parse((0,
|
|
13328
|
+
const mutex = (0, import_node_path6.join)(project.root, DEPENDENCY_MUTEX);
|
|
13329
|
+
if (!(0, import_node_fs6.existsSync)(mutex)) return;
|
|
13330
|
+
checkTransactionPath(project.root, (0, import_node_path6.join)(mutex, "owner.json"));
|
|
13331
|
+
const owner = JSON.parse((0, import_node_fs6.readFileSync)((0, import_node_path6.join)(mutex, "owner.json"), "utf8"));
|
|
12958
13332
|
if (!Number.isInteger(owner.pid) || owner.pid < 1)
|
|
12959
13333
|
throw new Error("Invalid installation owner; inspect the transaction manually");
|
|
12960
13334
|
try {
|
|
@@ -12963,37 +13337,37 @@ async function recoverDependencyInstall(cwd) {
|
|
|
12963
13337
|
} catch (error) {
|
|
12964
13338
|
if (error.code !== "ESRCH") throw error;
|
|
12965
13339
|
}
|
|
12966
|
-
const journal = (0,
|
|
13340
|
+
const journal = (0, import_node_path6.join)(mutex, "journal.json");
|
|
12967
13341
|
checkTransactionPath(project.root, journal);
|
|
12968
|
-
if ((0,
|
|
12969
|
-
const records = JSON.parse((0,
|
|
13342
|
+
if ((0, import_node_fs6.existsSync)(journal)) {
|
|
13343
|
+
const records = JSON.parse((0, import_node_fs6.readFileSync)(journal, "utf8"));
|
|
12970
13344
|
if (!Array.isArray(records)) throw new Error("Invalid recovery journal");
|
|
12971
13345
|
for (const record of records) {
|
|
12972
13346
|
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
13347
|
throw new Error("Invalid recovery journal path");
|
|
12974
|
-
checkTransactionPath(project.root, (0,
|
|
12975
|
-
checkTransactionPath(project.root, (0,
|
|
13348
|
+
checkTransactionPath(project.root, (0, import_node_path6.join)(project.root, record.path));
|
|
13349
|
+
checkTransactionPath(project.root, (0, import_node_path6.join)(mutex, "recovery-backup", record.path));
|
|
12976
13350
|
}
|
|
12977
13351
|
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,
|
|
13352
|
+
const path = (0, import_node_path6.join)(project.root, record.path);
|
|
13353
|
+
if ((0, import_node_fs6.existsSync)(path)) {
|
|
13354
|
+
const backup = (0, import_node_path6.join)(mutex, "recovery-backup", record.path);
|
|
13355
|
+
(0, import_node_fs6.mkdirSync)((0, import_node_path6.dirname)(backup), { recursive: true });
|
|
13356
|
+
if (!(0, import_node_fs6.existsSync)(backup)) (0, import_node_fs6.writeFileSync)(backup, (0, import_node_fs6.readFileSync)(path));
|
|
13357
|
+
}
|
|
13358
|
+
if (record.content === null) (0, import_node_fs6.rmSync)(path, { force: true });
|
|
13359
|
+
else (0, import_node_fs6.writeFileSync)(path, Buffer.from(record.content, "base64"));
|
|
12986
13360
|
}
|
|
12987
|
-
if (PACKAGE_MANAGER_LOCKS[project.manager].some((file) => (0,
|
|
13361
|
+
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
13362
|
await run(project, installCommand(project, true), project.root);
|
|
12989
13363
|
}
|
|
12990
|
-
if ((0,
|
|
12991
|
-
const backup = (0,
|
|
12992
|
-
(0,
|
|
13364
|
+
if ((0, import_node_fs6.existsSync)((0, import_node_path6.join)(mutex, "recovery-backup"))) {
|
|
13365
|
+
const backup = (0, import_node_path6.join)(project.root, `.octonode-recovery-${Date.now()}`);
|
|
13366
|
+
(0, import_node_fs6.renameSync)((0, import_node_path6.join)(mutex, "recovery-backup"), backup);
|
|
12993
13367
|
process.stderr.write(`Pre-recovery files preserved in ${backup}
|
|
12994
13368
|
`);
|
|
12995
13369
|
}
|
|
12996
|
-
(0,
|
|
13370
|
+
(0, import_node_fs6.rmSync)(mutex, { recursive: true, force: true });
|
|
12997
13371
|
}
|
|
12998
13372
|
function installProjectDependencies(cwd, dependencies = [], options = {}) {
|
|
12999
13373
|
return withDependencyInstall(cwd, () => reconcileDependencies(cwd, dependencies, options));
|
|
@@ -13002,15 +13376,15 @@ function installProjectDependencies(cwd, dependencies = [], options = {}) {
|
|
|
13002
13376
|
// packages/plugin/src/generated-package.ts
|
|
13003
13377
|
var import_tar = require("tar");
|
|
13004
13378
|
var import_node_zlib = require("node:zlib");
|
|
13379
|
+
var import_node_crypto4 = require("node:crypto");
|
|
13380
|
+
var import_node_fs8 = require("node:fs");
|
|
13381
|
+
var import_node_os5 = require("node:os");
|
|
13382
|
+
var import_node_path8 = require("node:path");
|
|
13383
|
+
|
|
13384
|
+
// packages/plugin/src/authoring/artifact.ts
|
|
13005
13385
|
var import_node_crypto3 = require("node:crypto");
|
|
13006
13386
|
var import_node_fs7 = require("node:fs");
|
|
13007
|
-
var import_node_os4 = require("node:os");
|
|
13008
13387
|
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
13388
|
var import_schema3 = __toESM(require_dist());
|
|
13015
13389
|
var import_yaml2 = require("yaml");
|
|
13016
13390
|
|
|
@@ -13030,18 +13404,18 @@ var RESERVED_ASSETS = /* @__PURE__ */ new Set([
|
|
|
13030
13404
|
]);
|
|
13031
13405
|
|
|
13032
13406
|
// packages/plugin/src/authoring/artifact.ts
|
|
13033
|
-
var fileHash = (path) => (0,
|
|
13407
|
+
var fileHash = (path) => (0, import_node_crypto3.createHash)("sha256").update((0, import_node_fs7.readFileSync)(path)).digest("hex");
|
|
13034
13408
|
function safePath(path) {
|
|
13035
|
-
if (!path || (0,
|
|
13409
|
+
if (!path || (0, import_node_path7.isAbsolute)(path) || path.includes("\\") || path.split("/").some((part) => !part || part === "." || part === ".." || part.includes(":") || FORBIDDEN_PART.test(part))) {
|
|
13036
13410
|
throw new Error(`Unsafe plugin file: ${path}`);
|
|
13037
13411
|
}
|
|
13038
13412
|
}
|
|
13039
13413
|
function pluginFiles(root, prefix = "") {
|
|
13040
|
-
if (!(0,
|
|
13041
|
-
return (0,
|
|
13414
|
+
if (!(0, import_node_fs7.lstatSync)((0, import_node_path7.join)(root, prefix)).isDirectory()) throw new Error(`Not a plugin directory: ${root}`);
|
|
13415
|
+
return (0, import_node_fs7.readdirSync)((0, import_node_path7.join)(root, prefix)).sort().flatMap((name) => {
|
|
13042
13416
|
const path = prefix ? `${prefix}/${name}` : name;
|
|
13043
13417
|
safePath(path);
|
|
13044
|
-
const stat = (0,
|
|
13418
|
+
const stat = (0, import_node_fs7.lstatSync)((0, import_node_path7.join)(root, path));
|
|
13045
13419
|
if (stat.isSymbolicLink()) throw new Error(`Plugin files cannot be symbolic links: ${path}`);
|
|
13046
13420
|
if (stat.isDirectory()) return pluginFiles(root, path);
|
|
13047
13421
|
if (!stat.isFile()) throw new Error(`Plugin asset must be a regular file: ${path}`);
|
|
@@ -13049,14 +13423,14 @@ function pluginFiles(root, prefix = "") {
|
|
|
13049
13423
|
});
|
|
13050
13424
|
}
|
|
13051
13425
|
function loadManifest(directory) {
|
|
13052
|
-
if ((0,
|
|
13053
|
-
const definitions = DEFINITION_FILES.filter((name) => (0,
|
|
13426
|
+
if ((0, import_node_fs7.lstatSync)(directory).isSymbolicLink()) throw new Error("Plugin directory cannot be a symbolic link");
|
|
13427
|
+
const definitions = DEFINITION_FILES.filter((name) => (0, import_node_fs7.existsSync)((0, import_node_path7.join)(directory, name)));
|
|
13054
13428
|
if (definitions.length !== 1) throw new Error("Keep exactly one plugin definition in the package");
|
|
13055
|
-
const path = (0,
|
|
13056
|
-
const stat = (0,
|
|
13429
|
+
const path = (0, import_node_path7.join)(directory, definitions[0]);
|
|
13430
|
+
const stat = (0, import_node_fs7.lstatSync)(path);
|
|
13057
13431
|
if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 1048576)
|
|
13058
13432
|
throw new Error("Invalid plugin definition file");
|
|
13059
|
-
const document = (0, import_yaml2.parseDocument)((0,
|
|
13433
|
+
const document = (0, import_yaml2.parseDocument)((0, import_node_fs7.readFileSync)(path, "utf8"), { uniqueKeys: true, version: "1.2" });
|
|
13060
13434
|
(0, import_yaml2.visit)(document, {
|
|
13061
13435
|
Alias() {
|
|
13062
13436
|
throw new Error("Plugin definitions cannot contain YAML aliases");
|
|
@@ -13072,7 +13446,16 @@ function verifyBuild(directory) {
|
|
|
13072
13446
|
const manifest2 = loadManifest(directory);
|
|
13073
13447
|
const files = pluginFiles(directory);
|
|
13074
13448
|
if (!files.includes(BUILD_RECORD)) throw new Error("Missing build record; run octonodes plugin build first");
|
|
13075
|
-
const record = JSON.parse((0,
|
|
13449
|
+
const record = JSON.parse((0, import_node_fs7.readFileSync)((0, import_node_path7.join)(directory, BUILD_RECORD), "utf8"));
|
|
13450
|
+
if (record.runtime) {
|
|
13451
|
+
const runtime = import_schema3.PreparedPluginRuntime.parse(record.runtime);
|
|
13452
|
+
if ((manifest2.integration?.npm || manifest2.integration?.npmDependencies?.length) && !runtime.dependencies)
|
|
13453
|
+
throw new Error("Prepared npm plugins must include their dependency runtime");
|
|
13454
|
+
if (runtime.dependencies && !files.includes(runtime.dependencies))
|
|
13455
|
+
throw new Error("Missing prepared dependency archive");
|
|
13456
|
+
if (runtime.dependencies && (runtime.platform === "portable" || !runtime.arch || runtime.platform === "linux" && !runtime.libc))
|
|
13457
|
+
throw new Error("Prepared dependencies require a platform, architecture and libc identity");
|
|
13458
|
+
}
|
|
13076
13459
|
if (record.format !== 1 || !record.files || typeof record.files !== "object" || Array.isArray(record.files)) {
|
|
13077
13460
|
throw new Error("Invalid plugin build record");
|
|
13078
13461
|
}
|
|
@@ -13081,7 +13464,7 @@ function verifyBuild(directory) {
|
|
|
13081
13464
|
throw new Error("Plugin files changed since build; rebuild before publishing");
|
|
13082
13465
|
}
|
|
13083
13466
|
for (const file of expected) {
|
|
13084
|
-
if (record.files[file] !== fileHash((0,
|
|
13467
|
+
if (record.files[file] !== fileHash((0, import_node_path7.join)(directory, file)))
|
|
13085
13468
|
throw new Error(`Plugin file changed since build: ${file}`);
|
|
13086
13469
|
}
|
|
13087
13470
|
if (!expected.includes("dist/index.js") || !manifest2.nodes.length || manifest2.nodes.some(
|
|
@@ -13102,14 +13485,14 @@ function verifyBuild(directory) {
|
|
|
13102
13485
|
)
|
|
13103
13486
|
);
|
|
13104
13487
|
for (const entry of new Set(ui.map(({ path }) => path))) {
|
|
13105
|
-
if (!expected.includes(entry) || (0,
|
|
13488
|
+
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
13489
|
throw new Error(`Invalid plugin UI bundle: ${entry}`);
|
|
13107
13490
|
}
|
|
13108
13491
|
if (JSON.stringify(record.ui ?? []) !== JSON.stringify(
|
|
13109
13492
|
ui.map((declaration) => ({
|
|
13110
13493
|
...declaration,
|
|
13111
|
-
size: (0,
|
|
13112
|
-
sha256: fileHash((0,
|
|
13494
|
+
size: (0, import_node_fs7.lstatSync)((0, import_node_path7.join)(directory, declaration.path)).size,
|
|
13495
|
+
sha256: fileHash((0, import_node_path7.join)(directory, declaration.path))
|
|
13113
13496
|
}))
|
|
13114
13497
|
))
|
|
13115
13498
|
throw new Error("Invalid plugin UI build record");
|
|
@@ -13134,41 +13517,41 @@ async function generatePluginPackage(cwd, selections, expectedPacker) {
|
|
|
13134
13517
|
const packer = "tar@7.5.22/portable-v1";
|
|
13135
13518
|
if (expectedPacker && expectedPacker !== packer)
|
|
13136
13519
|
throw new Error(`Plugin package restore requires ${expectedPacker}; found ${packer}`);
|
|
13137
|
-
const digest = (0,
|
|
13520
|
+
const digest = (0, import_node_crypto4.createHash)("sha256").update(
|
|
13138
13521
|
JSON.stringify({
|
|
13139
13522
|
format: GENERATED_PLUGIN_FORMAT,
|
|
13140
13523
|
packer,
|
|
13141
13524
|
selections: selected.map(({ alias, sha256 }) => ({ alias, sha256 }))
|
|
13142
13525
|
})
|
|
13143
13526
|
).digest("hex");
|
|
13144
|
-
const stage = (0,
|
|
13527
|
+
const stage = (0, import_node_fs8.mkdtempSync)((0, import_node_path8.join)((0, import_node_os5.tmpdir)(), "octonode-package-"));
|
|
13145
13528
|
try {
|
|
13146
|
-
const packageRoot = (0,
|
|
13147
|
-
(0,
|
|
13529
|
+
const packageRoot = (0, import_node_path8.join)(stage, "package");
|
|
13530
|
+
(0, import_node_fs8.mkdirSync)(packageRoot);
|
|
13148
13531
|
for (const { alias, directory, sha256 } of selected) {
|
|
13149
|
-
if ((0,
|
|
13532
|
+
if ((0, import_node_fs8.lstatSync)(directory).isSymbolicLink())
|
|
13150
13533
|
throw new Error(`Plugin directory cannot be a symbolic link: ${alias}`);
|
|
13151
|
-
const snapshot = (0,
|
|
13152
|
-
(0,
|
|
13534
|
+
const snapshot = (0, import_node_path8.join)(stage, "snapshots", alias);
|
|
13535
|
+
(0, import_node_fs8.mkdirSync)(snapshot, { recursive: true });
|
|
13153
13536
|
for (const file of pluginBundleFiles(directory)) {
|
|
13154
13537
|
safePath(file);
|
|
13155
|
-
(0,
|
|
13156
|
-
(0,
|
|
13538
|
+
(0, import_node_fs8.mkdirSync)((0, import_node_path8.dirname)((0, import_node_path8.join)(snapshot, file)), { recursive: true });
|
|
13539
|
+
(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
13540
|
}
|
|
13158
13541
|
if (hashPluginDir(snapshot) !== sha256) throw new Error(`Plugin integrity mismatch: ${alias}`);
|
|
13159
|
-
const library = (0,
|
|
13160
|
-
if (!(0,
|
|
13542
|
+
const library = (0, import_node_path8.join)(snapshot, "library");
|
|
13543
|
+
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
13544
|
throw new Error(`Plugin ${alias} has no importable library; rebuild with a compatible CLI`);
|
|
13162
13545
|
for (const file of pluginFiles(library)) {
|
|
13163
|
-
const target = (0,
|
|
13164
|
-
(0,
|
|
13165
|
-
(0,
|
|
13166
|
-
(0,
|
|
13546
|
+
const target = (0, import_node_path8.join)(packageRoot, alias, file);
|
|
13547
|
+
(0, import_node_fs8.mkdirSync)((0, import_node_path8.dirname)(target), { recursive: true });
|
|
13548
|
+
(0, import_node_fs8.writeFileSync)(target, (0, import_node_fs8.readFileSync)((0, import_node_path8.join)(library, file)));
|
|
13549
|
+
(0, import_node_fs8.chmodSync)(target, 420);
|
|
13167
13550
|
}
|
|
13168
13551
|
}
|
|
13169
13552
|
const subpaths = selected.map(({ alias }) => `./${alias}`);
|
|
13170
|
-
(0,
|
|
13171
|
-
(0,
|
|
13553
|
+
(0, import_node_fs8.writeFileSync)(
|
|
13554
|
+
(0, import_node_path8.join)(packageRoot, "package.json"),
|
|
13172
13555
|
JSON.stringify(
|
|
13173
13556
|
{
|
|
13174
13557
|
name: GENERATED_PLUGIN_PACKAGE,
|
|
@@ -13183,8 +13566,8 @@ async function generatePluginPackage(cwd, selections, expectedPacker) {
|
|
|
13183
13566
|
2
|
|
13184
13567
|
) + "\n"
|
|
13185
13568
|
);
|
|
13186
|
-
(0,
|
|
13187
|
-
const archive = (0,
|
|
13569
|
+
(0, import_node_fs8.chmodSync)((0, import_node_path8.join)(packageRoot, "package.json"), 420);
|
|
13570
|
+
const archive = (0, import_node_path8.join)(stage, "package.tar");
|
|
13188
13571
|
(0, import_tar.create)(
|
|
13189
13572
|
{
|
|
13190
13573
|
file: archive,
|
|
@@ -13197,24 +13580,24 @@ async function generatePluginPackage(cwd, selections, expectedPacker) {
|
|
|
13197
13580
|
},
|
|
13198
13581
|
pluginFiles(packageRoot)
|
|
13199
13582
|
);
|
|
13200
|
-
const bytes = (0, import_node_zlib.gzipSync)((0,
|
|
13583
|
+
const bytes = (0, import_node_zlib.gzipSync)((0, import_node_fs8.readFileSync)(archive), { level: 0 });
|
|
13201
13584
|
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,
|
|
13585
|
+
const output = (0, import_node_path8.join)(cwd, GENERATED_PLUGIN_DIRECTORY);
|
|
13586
|
+
(0, import_node_fs8.mkdirSync)(output, { recursive: true });
|
|
13587
|
+
if ((0, import_node_fs8.lstatSync)(output).isSymbolicLink()) throw new Error("Generated plugin directory cannot be a symbolic link");
|
|
13588
|
+
const ignore = (0, import_node_path8.join)(output, ".gitignore");
|
|
13589
|
+
if (!(0, import_node_fs8.existsSync)(ignore)) (0, import_node_fs8.writeFileSync)(ignore, "*\n", { flag: "wx" });
|
|
13590
|
+
const destination = (0, import_node_path8.join)(output, `plugin-${digest}.tgz`);
|
|
13591
|
+
if ((0, import_node_fs8.existsSync)(destination)) {
|
|
13592
|
+
if ((0, import_node_fs8.lstatSync)(destination).isSymbolicLink() || !(0, import_node_fs8.readFileSync)(destination).equals(bytes))
|
|
13210
13593
|
throw new Error("Generated plugin package changed; remove the corrupt generated file and restore again");
|
|
13211
13594
|
} else {
|
|
13212
|
-
const temporary = (0,
|
|
13595
|
+
const temporary = (0, import_node_fs8.mkdtempSync)((0, import_node_path8.join)(output, ".pack-"));
|
|
13213
13596
|
try {
|
|
13214
|
-
(0,
|
|
13215
|
-
(0,
|
|
13597
|
+
(0, import_node_fs8.writeFileSync)((0, import_node_path8.join)(temporary, "package.tgz"), bytes);
|
|
13598
|
+
(0, import_node_fs8.renameSync)((0, import_node_path8.join)(temporary, "package.tgz"), destination);
|
|
13216
13599
|
} finally {
|
|
13217
|
-
(0,
|
|
13600
|
+
(0, import_node_fs8.rmSync)(temporary, { recursive: true, force: true });
|
|
13218
13601
|
}
|
|
13219
13602
|
}
|
|
13220
13603
|
return {
|
|
@@ -13222,10 +13605,10 @@ async function generatePluginPackage(cwd, selections, expectedPacker) {
|
|
|
13222
13605
|
spec: `file:./${GENERATED_PLUGIN_DIRECTORY}/plugin-${digest}.tgz`,
|
|
13223
13606
|
subpaths,
|
|
13224
13607
|
packer,
|
|
13225
|
-
sha256: `sha256:${(0,
|
|
13608
|
+
sha256: `sha256:${(0, import_node_crypto4.createHash)("sha256").update(bytes).digest("hex")}`
|
|
13226
13609
|
};
|
|
13227
13610
|
} finally {
|
|
13228
|
-
(0,
|
|
13611
|
+
(0, import_node_fs8.rmSync)(stage, { recursive: true, force: true });
|
|
13229
13612
|
}
|
|
13230
13613
|
}
|
|
13231
13614
|
|
|
@@ -13234,6 +13617,42 @@ function pluginNpmDependencies(manifest2) {
|
|
|
13234
13617
|
return manifest2.integration?.npmDependencies ?? (manifest2.integration?.npm ? [manifest2.integration.npm] : []);
|
|
13235
13618
|
}
|
|
13236
13619
|
|
|
13620
|
+
// packages/plugin/src/prepared/invocation.ts
|
|
13621
|
+
var import_common3 = __toESM(require_dist2());
|
|
13622
|
+
var import_schema5 = __toESM(require_dist());
|
|
13623
|
+
|
|
13624
|
+
// packages/plugin/src/prepared/runtime.ts
|
|
13625
|
+
var import_node_fs9 = require("node:fs");
|
|
13626
|
+
var import_node_path9 = require("node:path");
|
|
13627
|
+
var import_tar2 = require("tar");
|
|
13628
|
+
var import_common2 = __toESM(require_dist2());
|
|
13629
|
+
var import_schema4 = __toESM(require_dist());
|
|
13630
|
+
function preparedRuntime(directory) {
|
|
13631
|
+
const path = (0, import_node_path9.join)(directory, BUILD_RECORD);
|
|
13632
|
+
if (!(0, import_node_fs9.existsSync)(path)) return;
|
|
13633
|
+
const record = JSON.parse((0, import_node_fs9.readFileSync)(path, "utf8"));
|
|
13634
|
+
if (record.runtime === void 0) return;
|
|
13635
|
+
return import_schema4.PreparedPluginRuntime.parse(record.runtime);
|
|
13636
|
+
}
|
|
13637
|
+
function assertPreparedRuntime(runtime) {
|
|
13638
|
+
const libc = process.platform === "linux" && process.report.getReport().header?.glibcVersionRuntime ? "glibc" : "musl";
|
|
13639
|
+
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))
|
|
13640
|
+
throw new Error("Prepared plugin runtime is incompatible; rebuild for this Node/platform/architecture/libc");
|
|
13641
|
+
}
|
|
13642
|
+
|
|
13643
|
+
// packages/plugin/src/prepared/invocation.ts
|
|
13644
|
+
function usesPreparedRunner(directory) {
|
|
13645
|
+
if (import_common3.PROCESS_ENV.OCTONODE_PLUGIN_RUNNER !== "true") return false;
|
|
13646
|
+
const runtime = preparedRuntime(directory);
|
|
13647
|
+
if (!runtime) return false;
|
|
13648
|
+
assertPreparedRuntime(runtime);
|
|
13649
|
+
const { manifest: manifest2 } = verifyBuild(directory);
|
|
13650
|
+
return !manifest2.permissions.some((permission) => permission.resource === "project_data");
|
|
13651
|
+
}
|
|
13652
|
+
function preparedPluginPin(directory, pin) {
|
|
13653
|
+
return !!pin?.installId && !!pin.registry && pin.registry.replace(/\/$/, "") === (0, import_common3.OCTONODE_MARKETPLACE_URL)()?.replace(/\/$/, "") && usesPreparedRunner(directory);
|
|
13654
|
+
}
|
|
13655
|
+
|
|
13237
13656
|
// packages/plugin/src/lifecycle.ts
|
|
13238
13657
|
async function reconcilePluginLock(cwd, next, options = {}) {
|
|
13239
13658
|
const project = resolveDependencyProject(cwd);
|
|
@@ -13243,21 +13662,21 @@ async function reconcilePluginLock(cwd, next, options = {}) {
|
|
|
13243
13662
|
const manifest2 = loadPluginManifest(directory);
|
|
13244
13663
|
if (manifest2.id !== (pin.pluginId ?? alias) || manifest2.version !== pin.version || hashPluginDir(directory) !== pin.sha256)
|
|
13245
13664
|
throw new Error(`Plugin identity or integrity mismatch: ${alias}`);
|
|
13246
|
-
return { alias, directory, sha256: pin.sha256, manifest: manifest2 };
|
|
13665
|
+
return { alias, directory, sha256: pin.sha256, manifest: manifest2, remote: preparedPluginPin(directory, pin) };
|
|
13247
13666
|
});
|
|
13248
13667
|
const libraries = loaded.filter((item) => item.manifest.library);
|
|
13249
13668
|
const generated = libraries.length ? await generatePluginPackage(project.target, libraries) : void 0;
|
|
13250
|
-
const packageFile = (0,
|
|
13251
|
-
const packageJson = (0,
|
|
13669
|
+
const packageFile = (0, import_node_path10.join)(project.target, "package.json");
|
|
13670
|
+
const packageJson = (0, import_node_fs10.existsSync)(packageFile) ? JSON.parse((0, import_node_fs10.readFileSync)(packageFile, "utf8")) : {};
|
|
13252
13671
|
const declared = { ...packageJson.devDependencies, ...packageJson.optionalDependencies, ...packageJson.dependencies };
|
|
13253
13672
|
if (generated && declared[generated.name] && declared[generated.name].replace(/^file:\.\//, "file:") !== before.generated?.spec.replace(/^file:\.\//, "file:") && !options.migrate)
|
|
13254
13673
|
throw new Error(
|
|
13255
13674
|
"Existing @octonodes/plugin dependency is not managed by this lock; pass --migrate to replace it explicitly"
|
|
13256
13675
|
);
|
|
13257
|
-
const dependencies = loaded.flatMap(
|
|
13676
|
+
const dependencies = loaded.filter((item) => !item.remote || item.manifest.library).flatMap(
|
|
13258
13677
|
({ manifest: manifest2 }) => pluginNpmDependencies(manifest2).map((npm) => {
|
|
13259
13678
|
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,
|
|
13679
|
+
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
13680
|
if (declared[npm.package] && declared[npm.package] !== spec && !sameLocal)
|
|
13262
13681
|
throw new Error(
|
|
13263
13682
|
`Dependency conflict: ${npm.package} is ${declared[npm.package]}, plugin requires ${spec}; reconcile it explicitly first`
|
|
@@ -13276,6 +13695,7 @@ async function reconcilePluginLock(cwd, next, options = {}) {
|
|
|
13276
13695
|
if (generated || before.generated || unique.length || options.commit) {
|
|
13277
13696
|
await reconcileDependencies(project.target, [...unique, ...generated ? [generated] : []], {
|
|
13278
13697
|
cacheRoot: options.cacheRoot,
|
|
13698
|
+
metadataOnly: !generated && !before.generated && !unique.length,
|
|
13279
13699
|
remove: !generated && before.generated ? [before.generated.name] : void 0,
|
|
13280
13700
|
transactionFiles: [lockfilePath(cwd), ...options.transactionFiles ?? []],
|
|
13281
13701
|
commit: () => {
|
|
@@ -13318,20 +13738,20 @@ async function removePluginPin(alias, options = {}) {
|
|
|
13318
13738
|
}
|
|
13319
13739
|
|
|
13320
13740
|
// packages/plugin/src/restore.ts
|
|
13321
|
-
var
|
|
13322
|
-
var
|
|
13741
|
+
var import_node_fs14 = require("node:fs");
|
|
13742
|
+
var import_node_path14 = require("node:path");
|
|
13323
13743
|
|
|
13324
|
-
// packages/plugin/src/remote
|
|
13325
|
-
var
|
|
13326
|
-
var
|
|
13327
|
-
var
|
|
13744
|
+
// packages/plugin/src/remote/registry.ts
|
|
13745
|
+
var import_node_fs13 = require("node:fs");
|
|
13746
|
+
var import_node_os6 = require("node:os");
|
|
13747
|
+
var import_node_path13 = require("node:path");
|
|
13328
13748
|
|
|
13329
13749
|
// packages/plugin/src/install.ts
|
|
13330
|
-
var
|
|
13331
|
-
var
|
|
13750
|
+
var import_node_fs11 = require("node:fs");
|
|
13751
|
+
var import_node_path11 = require("node:path");
|
|
13332
13752
|
var import_node_child_process2 = require("node:child_process");
|
|
13333
13753
|
var import_node_util2 = require("node:util");
|
|
13334
|
-
var
|
|
13754
|
+
var import_common4 = __toESM(require_dist2());
|
|
13335
13755
|
function commandError(err) {
|
|
13336
13756
|
const error = err;
|
|
13337
13757
|
return [error.stderr, error.stdout].map((output) => output?.toString().trim()).find(Boolean) ?? error.message;
|
|
@@ -13347,7 +13767,7 @@ async function installNodeDeps(dir, opts = {}) {
|
|
|
13347
13767
|
if (opts.cacheOnly) {
|
|
13348
13768
|
for (const npm of dependencies)
|
|
13349
13769
|
await (0, import_node_util2.promisify)(import_node_child_process2.execFile)("npm", ["cache", "add", "--ignore-scripts", "--", npm.spec], {
|
|
13350
|
-
env: (0,
|
|
13770
|
+
env: (0, import_common4.childProcessEnvironment)((0, import_common4.packageCacheEnvironment)(dependencyCacheRoot(opts.cacheRoot))),
|
|
13351
13771
|
timeout: 10 * 6e4
|
|
13352
13772
|
});
|
|
13353
13773
|
return {};
|
|
@@ -13364,9 +13784,9 @@ async function installNodeDeps(dir, opts = {}) {
|
|
|
13364
13784
|
return { depsInstalled: false, depsError: commandError(err) };
|
|
13365
13785
|
}
|
|
13366
13786
|
}
|
|
13367
|
-
const pjPath = (0,
|
|
13368
|
-
if (!(0,
|
|
13369
|
-
const pj = JSON.parse((0,
|
|
13787
|
+
const pjPath = (0, import_node_path11.join)(dir, "package.json");
|
|
13788
|
+
if (!(0, import_node_fs11.existsSync)(pjPath)) return {};
|
|
13789
|
+
const pj = JSON.parse((0, import_node_fs11.readFileSync)(pjPath, "utf8"));
|
|
13370
13790
|
if (!pj.dependencies && !pj.optionalDependencies) return {};
|
|
13371
13791
|
try {
|
|
13372
13792
|
await (0, import_node_util2.promisify)(import_node_child_process2.execFile)(
|
|
@@ -13382,7 +13802,7 @@ async function installNodeDeps(dir, opts = {}) {
|
|
|
13382
13802
|
],
|
|
13383
13803
|
{
|
|
13384
13804
|
cwd: dir,
|
|
13385
|
-
env: (0,
|
|
13805
|
+
env: (0, import_common4.childProcessEnvironment)((0, import_common4.packageCacheEnvironment)(dependencyCacheRoot(opts.cacheRoot))),
|
|
13386
13806
|
timeout: 10 * 6e4
|
|
13387
13807
|
}
|
|
13388
13808
|
);
|
|
@@ -13392,7 +13812,7 @@ async function installNodeDeps(dir, opts = {}) {
|
|
|
13392
13812
|
}
|
|
13393
13813
|
}
|
|
13394
13814
|
async function installPlugin(src, opts = {}) {
|
|
13395
|
-
if (!(0,
|
|
13815
|
+
if (!(0, import_node_fs11.existsSync)(src) || !(0, import_node_fs11.statSync)(src).isDirectory()) {
|
|
13396
13816
|
throw new Error(`source "${src}" is not a directory`);
|
|
13397
13817
|
}
|
|
13398
13818
|
if (!isPluginDir(src)) {
|
|
@@ -13400,17 +13820,17 @@ async function installPlugin(src, opts = {}) {
|
|
|
13400
13820
|
}
|
|
13401
13821
|
const { manifest: manifest2 } = loadPlugin(src);
|
|
13402
13822
|
const { root, source } = installRoot(opts);
|
|
13403
|
-
const dest = (0,
|
|
13404
|
-
if ((0,
|
|
13823
|
+
const dest = (0, import_node_path11.join)(root, manifest2.id);
|
|
13824
|
+
if ((0, import_node_fs11.existsSync)(dest)) {
|
|
13405
13825
|
if (!opts.force) {
|
|
13406
13826
|
throw new Error(`plugin "${manifest2.id}" is already installed at ${dest} (use --force to overwrite)`);
|
|
13407
13827
|
}
|
|
13408
13828
|
}
|
|
13409
13829
|
const deps = pluginNpmDependencies(manifest2).length ? await installNodeDeps(src, { ...opts, cacheOnly: opts.cacheOnly ?? !opts.project }) : {};
|
|
13410
13830
|
if (deps.depsError) return { manifest: manifest2, dir: dest, source, ...deps };
|
|
13411
|
-
if ((0,
|
|
13412
|
-
(0,
|
|
13413
|
-
(0,
|
|
13831
|
+
if ((0, import_node_fs11.existsSync)(dest)) (0, import_node_fs11.rmSync)(dest, { recursive: true, force: true });
|
|
13832
|
+
(0, import_node_fs11.mkdirSync)(root, { recursive: true });
|
|
13833
|
+
(0, import_node_fs11.cpSync)(src, dest, { recursive: true });
|
|
13414
13834
|
return {
|
|
13415
13835
|
manifest: manifest2,
|
|
13416
13836
|
dir: dest,
|
|
@@ -13420,14 +13840,14 @@ async function installPlugin(src, opts = {}) {
|
|
|
13420
13840
|
};
|
|
13421
13841
|
}
|
|
13422
13842
|
|
|
13423
|
-
// packages/plugin/src/remote
|
|
13424
|
-
var
|
|
13843
|
+
// packages/plugin/src/remote/registry.ts
|
|
13844
|
+
var import_common5 = __toESM(require_dist2());
|
|
13425
13845
|
|
|
13426
13846
|
// packages/plugin/src/archive.ts
|
|
13427
13847
|
var import_node_zlib2 = require("node:zlib");
|
|
13428
|
-
var
|
|
13429
|
-
var
|
|
13430
|
-
var
|
|
13848
|
+
var import_node_fs12 = require("node:fs");
|
|
13849
|
+
var import_node_path12 = require("node:path");
|
|
13850
|
+
var import_tar3 = require("tar");
|
|
13431
13851
|
|
|
13432
13852
|
// packages/plugin/src/archive.constants.ts
|
|
13433
13853
|
var PLUGIN_ARCHIVE_MAX_BYTES = 64 * 1024 * 1024;
|
|
@@ -13437,11 +13857,11 @@ var PLUGIN_ARCHIVE_MAX_FILES = 1e4;
|
|
|
13437
13857
|
function extractPluginArchive(bytes, stage) {
|
|
13438
13858
|
if (bytes.length > PLUGIN_ARCHIVE_MAX_BYTES) throw new Error("Plugin archive exceeds download limit");
|
|
13439
13859
|
const decoded = (0, import_node_zlib2.gunzipSync)(bytes, { maxOutputLength: PLUGIN_ARCHIVE_MAX_BYTES });
|
|
13440
|
-
const archive = (0,
|
|
13441
|
-
(0,
|
|
13860
|
+
const archive = (0, import_node_path12.join)(stage, "bundle.tar");
|
|
13861
|
+
(0, import_node_fs12.writeFileSync)(archive, decoded);
|
|
13442
13862
|
const seen = /* @__PURE__ */ new Set();
|
|
13443
13863
|
let total = 0;
|
|
13444
|
-
(0,
|
|
13864
|
+
(0, import_tar3.list)({
|
|
13445
13865
|
file: archive,
|
|
13446
13866
|
sync: true,
|
|
13447
13867
|
strict: true,
|
|
@@ -13458,9 +13878,9 @@ function extractPluginArchive(bytes, stage) {
|
|
|
13458
13878
|
throw new Error("Plugin archive exceeds extraction limits");
|
|
13459
13879
|
}
|
|
13460
13880
|
});
|
|
13461
|
-
const output = (0,
|
|
13462
|
-
(0,
|
|
13463
|
-
(0,
|
|
13881
|
+
const output = (0, import_node_path12.join)(stage, "plugin");
|
|
13882
|
+
(0, import_node_fs12.mkdirSync)(output);
|
|
13883
|
+
(0, import_tar3.extract)({
|
|
13464
13884
|
file: archive,
|
|
13465
13885
|
cwd: output,
|
|
13466
13886
|
sync: true,
|
|
@@ -13473,11 +13893,12 @@ function extractPluginArchive(bytes, stage) {
|
|
|
13473
13893
|
return output;
|
|
13474
13894
|
}
|
|
13475
13895
|
|
|
13476
|
-
// packages/plugin/src/remote
|
|
13477
|
-
var
|
|
13896
|
+
// packages/plugin/src/remote/registry.ts
|
|
13897
|
+
var import_tar4 = require("tar");
|
|
13898
|
+
var import_node_crypto5 = require("node:crypto");
|
|
13478
13899
|
var RemoteRegistry = class {
|
|
13479
13900
|
constructor(opts = {}) {
|
|
13480
|
-
const baseUrl = opts.baseUrl ?? (0,
|
|
13901
|
+
const baseUrl = opts.baseUrl ?? (0, import_common5.OCTONODE_MARKETPLACE_URL)();
|
|
13481
13902
|
if (!baseUrl) {
|
|
13482
13903
|
throw new Error("marketplace URL is not configured (set OCTONODE_MARKETPLACE_URL or pass baseUrl)");
|
|
13483
13904
|
}
|
|
@@ -13487,7 +13908,7 @@ var RemoteRegistry = class {
|
|
|
13487
13908
|
);
|
|
13488
13909
|
}
|
|
13489
13910
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
13490
|
-
this.token = opts.token ?? (0,
|
|
13911
|
+
this.token = opts.token ?? (0, import_common5.OCTONODE_MARKETPLACE_TOKEN)();
|
|
13491
13912
|
}
|
|
13492
13913
|
async request(path, init = {}) {
|
|
13493
13914
|
const headers = new Headers(init.headers);
|
|
@@ -13504,19 +13925,49 @@ var RemoteRegistry = class {
|
|
|
13504
13925
|
}
|
|
13505
13926
|
return res;
|
|
13506
13927
|
}
|
|
13928
|
+
async searchPage(filter = {}, offset = 0, limit = 24) {
|
|
13929
|
+
const params = new URLSearchParams({ offset: String(offset), limit: String(limit) });
|
|
13930
|
+
for (const [key, value] of Object.entries(filter)) if (value !== void 0) params.set(key, value);
|
|
13931
|
+
const res = await this.request(`/marketplace/plugins?${params}`);
|
|
13932
|
+
return await res.json();
|
|
13933
|
+
}
|
|
13507
13934
|
async search(filter = {}) {
|
|
13508
|
-
|
|
13509
|
-
for (
|
|
13510
|
-
|
|
13511
|
-
|
|
13512
|
-
|
|
13513
|
-
|
|
13935
|
+
let entries = [];
|
|
13936
|
+
for (; ; ) {
|
|
13937
|
+
const page = await this.searchPage(filter, entries.length, 100);
|
|
13938
|
+
entries = [...entries, ...page.entries];
|
|
13939
|
+
if (!page.entries.length || page.total === void 0 || entries.length >= page.total) return entries;
|
|
13940
|
+
}
|
|
13514
13941
|
}
|
|
13515
13942
|
async detail(id, scope) {
|
|
13516
13943
|
const query = scope ? `?scope=${encodeURIComponent(scope)}` : "";
|
|
13517
13944
|
const res = await this.request(`/marketplace/plugins/${encodeURIComponent(id)}${query}`);
|
|
13518
13945
|
return await res.json();
|
|
13519
13946
|
}
|
|
13947
|
+
/** Reauthorize an immutable pin, including older locks that only recorded the extracted tree hash. */
|
|
13948
|
+
async matchesLockedRelease(id, pin) {
|
|
13949
|
+
const remoteId = pin.remoteId ?? id;
|
|
13950
|
+
const detail = await this.detail(remoteId, pin.scope);
|
|
13951
|
+
const release2 = detail.versions.find((entry) => entry.version === pin.version);
|
|
13952
|
+
if (!release2 || pin.publisher && release2.publishedBy !== pin.publisher) return false;
|
|
13953
|
+
const checksum = release2.archiveSha256 ?? release2.sha256;
|
|
13954
|
+
if (pin.archiveSha256 || checksum?.startsWith("sha256:")) return checksum === (pin.archiveSha256 ?? pin.sha256);
|
|
13955
|
+
if (!/^[a-f0-9]{64}$/.test(checksum)) return false;
|
|
13956
|
+
const directory = await this.downloadBundle(remoteId, pin.version, pin.scope, id, checksum);
|
|
13957
|
+
try {
|
|
13958
|
+
return hashPluginDir(directory) === pin.sha256;
|
|
13959
|
+
} finally {
|
|
13960
|
+
(0, import_node_fs13.rmSync)((0, import_node_path13.dirname)(directory), { recursive: true, force: true });
|
|
13961
|
+
}
|
|
13962
|
+
}
|
|
13963
|
+
async registerInstall(id, version, scope, opts) {
|
|
13964
|
+
const response = await this.request(`/marketplace/plugins/${encodeURIComponent(id)}/install`, {
|
|
13965
|
+
method: "POST",
|
|
13966
|
+
headers: { "content-type": "application/json" },
|
|
13967
|
+
body: JSON.stringify({ version, scope, ownerId: opts.ownerId, environment: opts.environment ?? "self_hosted" })
|
|
13968
|
+
});
|
|
13969
|
+
return (await response.json()).installId;
|
|
13970
|
+
}
|
|
13520
13971
|
/**
|
|
13521
13972
|
* Pack a plugin folder into a tarball and publish it (metadata + bundle).
|
|
13522
13973
|
* `orgId` names the org an org/group-scoped version belongs to; `teamId`
|
|
@@ -13526,6 +13977,13 @@ var RemoteRegistry = class {
|
|
|
13526
13977
|
*/
|
|
13527
13978
|
async publish(pluginDir, opts = {}) {
|
|
13528
13979
|
const manifest2 = loadPluginManifest(pluginDir);
|
|
13980
|
+
const packageFile = (0, import_node_path13.join)(pluginDir, "package.json");
|
|
13981
|
+
if ((0, import_node_fs13.existsSync)(packageFile)) {
|
|
13982
|
+
const metadata = JSON.parse((0, import_node_fs13.readFileSync)(packageFile, "utf8"));
|
|
13983
|
+
if (metadata.version && metadata.version !== manifest2.version) {
|
|
13984
|
+
throw new Error("package.json version must match the plugin version before publishing");
|
|
13985
|
+
}
|
|
13986
|
+
}
|
|
13529
13987
|
const bundle = packPluginDir(pluginDir);
|
|
13530
13988
|
const form = new FormData();
|
|
13531
13989
|
form.set("manifest", JSON.stringify(manifest2));
|
|
@@ -13536,10 +13994,14 @@ var RemoteRegistry = class {
|
|
|
13536
13994
|
method: "POST",
|
|
13537
13995
|
body: form
|
|
13538
13996
|
});
|
|
13539
|
-
|
|
13997
|
+
const release2 = await res.json();
|
|
13998
|
+
const digest = (0, import_node_crypto5.createHash)("sha256").update(bundle).digest("hex");
|
|
13999
|
+
if (release2.sha256 !== digest || release2.archiveSha256 !== void 0 && release2.archiveSha256 !== digest)
|
|
14000
|
+
throw new Error("Marketplace published archive checksum mismatch; check the release before publishing again");
|
|
14001
|
+
return release2;
|
|
13540
14002
|
}
|
|
13541
14003
|
/** Download a version's bundle and extract it to a fresh temp folder. */
|
|
13542
|
-
async downloadBundle(id, version, scope, expectedId = id) {
|
|
14004
|
+
async downloadBundle(id, version, scope, expectedId = id, expectedChecksum) {
|
|
13543
14005
|
const query = scope ? `?scope=${encodeURIComponent(scope)}` : "";
|
|
13544
14006
|
const res = await this.request(
|
|
13545
14007
|
`/marketplace/plugins/${encodeURIComponent(id)}/versions/${encodeURIComponent(version)}/bundle${query}`
|
|
@@ -13560,17 +14022,27 @@ var RemoteRegistry = class {
|
|
|
13560
14022
|
await reader.cancel();
|
|
13561
14023
|
}
|
|
13562
14024
|
const bytes = Buffer.concat(chunks);
|
|
13563
|
-
const
|
|
14025
|
+
const archiveChecksum = res.headers.get("x-octonode-archive-sha256");
|
|
14026
|
+
if (archiveChecksum !== null && !/^[a-f0-9]{64}$/.test(archiveChecksum))
|
|
14027
|
+
throw new Error("Plugin registry archive checksum is invalid");
|
|
14028
|
+
const checksums = [archiveChecksum, res.headers.get("x-octonode-sha256"), expectedChecksum].filter(
|
|
14029
|
+
(checksum) => !!checksum
|
|
14030
|
+
);
|
|
14031
|
+
const digest = (0, import_node_crypto5.createHash)("sha256").update(bytes).digest("hex");
|
|
14032
|
+
for (const expected of checksums)
|
|
14033
|
+
if (/^[a-f0-9]{64}$/.test(expected) && expected !== digest) throw new Error("Plugin registry checksum mismatch");
|
|
14034
|
+
const dir = (0, import_node_fs13.mkdtempSync)((0, import_node_path13.join)((0, import_node_os6.tmpdir)(), "octo-bundle-"));
|
|
13564
14035
|
try {
|
|
13565
14036
|
const extracted = extractPluginArchive(bytes, dir);
|
|
13566
14037
|
const manifest2 = loadPluginManifest(extracted);
|
|
13567
14038
|
if (manifest2.id !== expectedId || manifest2.version !== version)
|
|
13568
14039
|
throw new Error(`Downloaded plugin does not match requested ${id}@${version}`);
|
|
13569
|
-
const
|
|
13570
|
-
|
|
14040
|
+
for (const expected of checksums)
|
|
14041
|
+
if (!/^[a-f0-9]{64}$/.test(expected) && hashPluginDir(extracted) !== expected)
|
|
14042
|
+
throw new Error("Plugin registry checksum mismatch");
|
|
13571
14043
|
return extracted;
|
|
13572
14044
|
} catch (error) {
|
|
13573
|
-
(0,
|
|
14045
|
+
(0, import_node_fs13.rmSync)(dir, { recursive: true, force: true });
|
|
13574
14046
|
throw error;
|
|
13575
14047
|
}
|
|
13576
14048
|
}
|
|
@@ -13582,7 +14054,14 @@ var RemoteRegistry = class {
|
|
|
13582
14054
|
async install(id, opts = {}) {
|
|
13583
14055
|
const detail = await this.detail(id, opts.scope);
|
|
13584
14056
|
const version = opts.version ?? detail.version;
|
|
13585
|
-
const
|
|
14057
|
+
const release2 = detail.versions?.find((entry) => entry.version === version);
|
|
14058
|
+
const dir = await this.downloadBundle(
|
|
14059
|
+
id,
|
|
14060
|
+
version,
|
|
14061
|
+
opts.scope,
|
|
14062
|
+
id,
|
|
14063
|
+
release2?.archiveSha256 ?? release2?.sha256
|
|
14064
|
+
);
|
|
13586
14065
|
const plugin = await installPlugin(dir, opts);
|
|
13587
14066
|
const res = await this.request(`/marketplace/plugins/${encodeURIComponent(id)}/install`, {
|
|
13588
14067
|
method: "POST",
|
|
@@ -13608,19 +14087,21 @@ var RemoteRegistry = class {
|
|
|
13608
14087
|
const detail = await this.detail(id, opts.scope);
|
|
13609
14088
|
const version = opts.version ?? detail.version;
|
|
13610
14089
|
const versionMeta = detail.versions?.find((v) => v.version === version);
|
|
13611
|
-
|
|
14090
|
+
const releaseChecksum = versionMeta?.archiveSha256 ?? versionMeta?.sha256;
|
|
14091
|
+
if (!opts.cacheOnly && !opts.noDeps && !releaseChecksum)
|
|
13612
14092
|
throw new Error("Marketplace release is missing its immutable checksum");
|
|
13613
14093
|
const availableScopes = versionMeta?.scope ?? detail.scope;
|
|
13614
14094
|
const scope = opts.scope && availableScopes.includes(opts.scope) ? opts.scope : availableScopes[0];
|
|
13615
|
-
const dir = await this.downloadBundle(id, version, scope);
|
|
14095
|
+
const dir = await this.downloadBundle(id, version, scope, id, releaseChecksum);
|
|
13616
14096
|
const entry = (() => {
|
|
13617
14097
|
try {
|
|
13618
14098
|
return addToStore(dir, { storeRoot: opts.storeRoot });
|
|
13619
14099
|
} finally {
|
|
13620
|
-
(0,
|
|
14100
|
+
(0, import_node_fs13.rmSync)((0, import_node_path13.dirname)(dir), { recursive: true, force: true });
|
|
13621
14101
|
}
|
|
13622
14102
|
})();
|
|
13623
|
-
|
|
14103
|
+
const archiveSha256 = releaseChecksum && /^[a-f0-9]{64}$/.test(releaseChecksum) ? releaseChecksum : void 0;
|
|
14104
|
+
const prepared = this.baseUrl === (0, import_common5.OCTONODE_MARKETPLACE_URL)()?.replace(/\/$/, "") && usesPreparedRunner(entry.dir);
|
|
13624
14105
|
if (entry.manifest.library && opts.noDeps && !opts.cacheOnly)
|
|
13625
14106
|
throw new Error(
|
|
13626
14107
|
"Library installation requires native dependency activation; use frozen --artifacts-only for CI restore"
|
|
@@ -13632,26 +14113,29 @@ var RemoteRegistry = class {
|
|
|
13632
14113
|
remoteId: id,
|
|
13633
14114
|
version: entry.version,
|
|
13634
14115
|
sha256: entry.sha256,
|
|
14116
|
+
archiveSha256,
|
|
13635
14117
|
registry: this.baseUrl,
|
|
13636
14118
|
scope,
|
|
13637
14119
|
permissions: versionMeta?.permissions ?? detail.permissions,
|
|
13638
14120
|
publisher: versionMeta?.publishedBy
|
|
13639
14121
|
};
|
|
13640
|
-
await activatePluginPin(alias2, pin2, opts);
|
|
13641
14122
|
let installId2 = "";
|
|
13642
|
-
if (!opts.dryRun) {
|
|
14123
|
+
if (prepared && !opts.dryRun) {
|
|
14124
|
+
installId2 = await this.registerInstall(id, version, scope, { ...opts, environment: "cloud" });
|
|
14125
|
+
if (!installId2 || !/^[a-f0-9-]{36}$/.test(installId2))
|
|
14126
|
+
throw new Error("Marketplace did not authorize the prepared installation");
|
|
14127
|
+
pin2.installId = installId2;
|
|
14128
|
+
}
|
|
14129
|
+
try {
|
|
14130
|
+
await activatePluginPin(alias2, pin2, opts);
|
|
14131
|
+
} catch (error) {
|
|
14132
|
+
if (installId2) await this.postEvent(installId2, "uninstall").catch(() => {
|
|
14133
|
+
});
|
|
14134
|
+
throw error;
|
|
14135
|
+
}
|
|
14136
|
+
if (!opts.dryRun && !prepared) {
|
|
13643
14137
|
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;
|
|
14138
|
+
installId2 = await this.registerInstall(id, version, scope, opts);
|
|
13655
14139
|
if (installId2)
|
|
13656
14140
|
await withDependencyInstall(opts.cwd ?? process.cwd(), async () => {
|
|
13657
14141
|
const current = readLockfile(opts.cwd).plugins[alias2];
|
|
@@ -13665,10 +14149,10 @@ var RemoteRegistry = class {
|
|
|
13665
14149
|
plugin: { manifest: entry.manifest, dir: entry.dir, source: "store" },
|
|
13666
14150
|
entry,
|
|
13667
14151
|
installId: installId2,
|
|
13668
|
-
depsInstalled: !opts.dryRun
|
|
14152
|
+
depsInstalled: !opts.dryRun && (!prepared || !!entry.manifest.library)
|
|
13669
14153
|
};
|
|
13670
14154
|
}
|
|
13671
|
-
const deps = entry.created || entry.manifest.integration?.npm ? await installNodeDeps(entry.dir, {
|
|
14155
|
+
const deps = !prepared && (entry.created || entry.manifest.integration?.npm) ? await installNodeDeps(entry.dir, {
|
|
13672
14156
|
noDeps: opts.noDeps,
|
|
13673
14157
|
cwd: opts.cwd,
|
|
13674
14158
|
cacheRoot: opts.cacheRoot,
|
|
@@ -13681,25 +14165,36 @@ var RemoteRegistry = class {
|
|
|
13681
14165
|
remoteId: id,
|
|
13682
14166
|
version: entry.version,
|
|
13683
14167
|
sha256: entry.sha256,
|
|
14168
|
+
archiveSha256,
|
|
13684
14169
|
registry: this.baseUrl,
|
|
13685
14170
|
scope,
|
|
13686
14171
|
publisher: versionMeta?.publishedBy,
|
|
13687
14172
|
permissions: versionMeta?.permissions ?? detail.permissions
|
|
13688
14173
|
};
|
|
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
|
-
});
|
|
14174
|
+
if (opts.dryRun)
|
|
14175
|
+
return { plugin: { manifest: entry.manifest, dir: entry.dir, source: "store" }, entry, installId: "" };
|
|
13695
14176
|
let installId = "";
|
|
14177
|
+
if (prepared) {
|
|
14178
|
+
installId = await this.registerInstall(id, version, scope, { ...opts, environment: "cloud" });
|
|
14179
|
+
if (!installId || !/^[a-f0-9-]{36}$/.test(installId))
|
|
14180
|
+
throw new Error("Marketplace did not authorize the prepared installation");
|
|
14181
|
+
pin.installId = installId;
|
|
14182
|
+
}
|
|
13696
14183
|
try {
|
|
13697
|
-
|
|
13698
|
-
|
|
13699
|
-
|
|
13700
|
-
|
|
14184
|
+
await withDependencyInstall(opts.cwd ?? process.cwd(), async () => {
|
|
14185
|
+
const previous = readLockfile(opts.cwd).plugins[alias];
|
|
14186
|
+
if (previous && ((previous.pluginId ?? alias) !== entry.id || previous.registry !== this.baseUrl || previous.publisher !== pin.publisher))
|
|
14187
|
+
throw new Error("Plugin alias belongs to another publisher or registry");
|
|
14188
|
+
upsertLockEntry(opts.cwd ?? process.cwd(), alias, pin);
|
|
14189
|
+
});
|
|
14190
|
+
} catch (error) {
|
|
14191
|
+
if (installId) await this.postEvent(installId, "uninstall").catch(() => {
|
|
13701
14192
|
});
|
|
13702
|
-
|
|
14193
|
+
throw error;
|
|
14194
|
+
}
|
|
14195
|
+
if (prepared) return { plugin: { manifest: entry.manifest, dir: entry.dir, source: "store" }, entry, installId };
|
|
14196
|
+
try {
|
|
14197
|
+
installId = await this.registerInstall(id, version, scope, opts);
|
|
13703
14198
|
await withDependencyInstall(opts.cwd ?? process.cwd(), async () => {
|
|
13704
14199
|
const current = readLockfile(opts.cwd).plugins[alias];
|
|
13705
14200
|
if (current?.sha256 === pin.sha256 && current.registry === pin.registry)
|
|
@@ -13725,13 +14220,13 @@ var RemoteRegistry = class {
|
|
|
13725
14220
|
};
|
|
13726
14221
|
function packPluginDir(pluginDir) {
|
|
13727
14222
|
pluginBundleFiles(pluginDir);
|
|
13728
|
-
const staging = (0,
|
|
13729
|
-
const out = (0,
|
|
14223
|
+
const staging = (0, import_node_fs13.mkdtempSync)((0, import_node_path13.join)((0, import_node_os6.tmpdir)(), "octo-pack-"));
|
|
14224
|
+
const out = (0, import_node_path13.join)(staging, "bundle.tar.gz");
|
|
13730
14225
|
try {
|
|
13731
|
-
(0,
|
|
13732
|
-
return (0,
|
|
14226
|
+
(0, import_tar4.create)({ file: out, cwd: pluginDir, sync: true, portable: true, gzip: true }, pluginBundleFiles(pluginDir));
|
|
14227
|
+
return (0, import_node_fs13.readFileSync)(out);
|
|
13733
14228
|
} finally {
|
|
13734
|
-
(0,
|
|
14229
|
+
(0, import_node_fs13.rmSync)(staging, { recursive: true, force: true });
|
|
13735
14230
|
}
|
|
13736
14231
|
}
|
|
13737
14232
|
|
|
@@ -13739,7 +14234,7 @@ function packPluginDir(pluginDir) {
|
|
|
13739
14234
|
async function installFromLock(opts = {}) {
|
|
13740
14235
|
const cwd = resolveDependencyProject(opts.cwd ?? process.cwd()).target;
|
|
13741
14236
|
if (opts.frozen && opts.force) throw new Error("Frozen restore cannot accept changed artifact bytes");
|
|
13742
|
-
if (opts.frozen && !(0,
|
|
14237
|
+
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
14238
|
return withDependencyInstall(cwd, async () => {
|
|
13744
14239
|
const lock = readLockfile(cwd);
|
|
13745
14240
|
if (lock.generated && opts.force)
|
|
@@ -13756,9 +14251,8 @@ async function installFromLock(opts = {}) {
|
|
|
13756
14251
|
throw new Error("Frozen restore cannot change the registry");
|
|
13757
14252
|
if (pin.scope && pin.scope !== "public" && registry) {
|
|
13758
14253
|
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)
|
|
14254
|
+
const remote = new RemoteRegistry({ baseUrl: registry, token: opts.token });
|
|
14255
|
+
if (!await remote.matchesLockedRelease(id, pin))
|
|
13762
14256
|
throw new Error("Locked private release is not authorized or changed");
|
|
13763
14257
|
}
|
|
13764
14258
|
let directory = storeEntryDir(id, pin.version, pin.sha256, opts.storeRoot);
|
|
@@ -13772,16 +14266,18 @@ async function installFromLock(opts = {}) {
|
|
|
13772
14266
|
remoteId,
|
|
13773
14267
|
pin.version,
|
|
13774
14268
|
pin.scope,
|
|
13775
|
-
id
|
|
14269
|
+
id,
|
|
14270
|
+
opts.force ? void 0 : pin.archiveSha256
|
|
13776
14271
|
);
|
|
13777
14272
|
try {
|
|
13778
14273
|
const actual = hashPluginDir(downloaded);
|
|
13779
14274
|
if (actual !== pin.sha256 && !opts.force) throw new Error("integrity mismatch for " + alias);
|
|
13780
14275
|
const entry = addToStore(downloaded, { storeRoot: opts.storeRoot });
|
|
13781
14276
|
directory = entry.dir;
|
|
13782
|
-
if (actual !== pin.sha256)
|
|
14277
|
+
if (actual !== pin.sha256)
|
|
14278
|
+
upsertLockEntry(cwd, alias, { ...pin, sha256: actual, archiveSha256: void 0 });
|
|
13783
14279
|
} finally {
|
|
13784
|
-
(0,
|
|
14280
|
+
(0, import_node_fs14.rmSync)((0, import_node_path14.dirname)(downloaded), { recursive: true, force: true });
|
|
13785
14281
|
}
|
|
13786
14282
|
result.restored.push(alias);
|
|
13787
14283
|
}
|
|
@@ -13789,9 +14285,10 @@ async function installFromLock(opts = {}) {
|
|
|
13789
14285
|
if (manifest2.id !== id || manifest2.version !== pin.version)
|
|
13790
14286
|
throw new Error("Plugin identity mismatch: " + alias);
|
|
13791
14287
|
if (manifest2.library) libraries.push({ alias, directory, sha256: pin.sha256 });
|
|
14288
|
+
if (!manifest2.library && preparedPluginPin(directory, pin)) continue;
|
|
13792
14289
|
if (!manifest2.library && !pluginNpmDependencies(manifest2).length && !opts.artifactsOnly && !opts.noDeps) {
|
|
13793
|
-
const packagePath = (0,
|
|
13794
|
-
const legacy = (0,
|
|
14290
|
+
const packagePath = (0, import_node_path14.join)(directory, "package.json");
|
|
14291
|
+
const legacy = (0, import_node_fs14.existsSync)(packagePath) ? JSON.parse((0, import_node_fs14.readFileSync)(packagePath, "utf8")) : {};
|
|
13795
14292
|
if (legacy.dependencies || legacy.optionalDependencies) {
|
|
13796
14293
|
if (opts.frozen || opts.offline)
|
|
13797
14294
|
throw new Error(
|
|
@@ -13818,7 +14315,7 @@ async function installFromLock(opts = {}) {
|
|
|
13818
14315
|
const generated = await generatePluginPackage(cwd, libraries, lock.generated.packer);
|
|
13819
14316
|
if (generated.spec !== lock.generated.spec || generated.sha256 !== lock.generated.sha256 || JSON.stringify(generated.subpaths) !== JSON.stringify(lock.generated.subpaths))
|
|
13820
14317
|
throw new Error("Generated package does not match octonode.lock");
|
|
13821
|
-
const manifest2 = JSON.parse((0,
|
|
14318
|
+
const manifest2 = JSON.parse((0, import_node_fs14.readFileSync)((0, import_node_path14.join)(cwd, "package.json"), "utf8"));
|
|
13822
14319
|
if (manifest2.dependencies?.[generated.name]?.replace(/^file:\.\//, "file:") !== generated.spec.replace(/^file:\.\//, "file:"))
|
|
13823
14320
|
throw new Error("package.json disagrees with octonode.lock");
|
|
13824
14321
|
}
|
|
@@ -13838,11 +14335,11 @@ async function installFromLock(opts = {}) {
|
|
|
13838
14335
|
}
|
|
13839
14336
|
|
|
13840
14337
|
// packages/plugin/src/consumer/lifecycle.ts
|
|
13841
|
-
var
|
|
14338
|
+
var import_schema6 = __toESM(require_dist());
|
|
13842
14339
|
async function runPluginLifecycle(command, target, flags) {
|
|
13843
|
-
const cwd = resolveDependencyProject(typeof flags.cwd === "string" ? (0,
|
|
14340
|
+
const cwd = resolveDependencyProject(typeof flags.cwd === "string" ? (0, import_node_path15.resolve)(flags.cwd) : process.cwd()).target;
|
|
13844
14341
|
const scope = typeof flags.scope === "string" ? flags.scope : void 0;
|
|
13845
|
-
if (scope && !
|
|
14342
|
+
if (scope && !import_schema6.MARKETPLACE_SCOPES.includes(scope)) throw new Error("Invalid marketplace scope");
|
|
13846
14343
|
const options = {
|
|
13847
14344
|
cwd,
|
|
13848
14345
|
alias: typeof flags.alias === "string" ? flags.alias : void 0,
|
|
@@ -13870,8 +14367,8 @@ async function runPluginLifecycle(command, target, flags) {
|
|
|
13870
14367
|
await removePluginPin(target, options);
|
|
13871
14368
|
return { removed: target, dryRun: options.dryRun };
|
|
13872
14369
|
}
|
|
13873
|
-
if (command === "install" && (0,
|
|
13874
|
-
const entry = await installLocalArtifact((0,
|
|
14370
|
+
if (command === "install" && (0, import_node_fs15.existsSync)((0, import_node_path15.resolve)(cwd, target))) {
|
|
14371
|
+
const entry = await installLocalArtifact((0, import_node_path15.resolve)(cwd, target), options);
|
|
13875
14372
|
return { id: options.alias ?? entry.id, version: entry.version, sha256: entry.sha256, dryRun: options.dryRun };
|
|
13876
14373
|
}
|
|
13877
14374
|
if (command !== "install" && command !== "update") throw new Error(`Unknown plugin lifecycle command: ${command}`);
|