@eudiplo/cli 8.0.2-main.3b6a116 → 8.0.2-main.4c3e735
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 +5 -1
- package/dist/commands/deployment/action.d.ts +1 -1
- package/dist/commands/deployment/action.d.ts.map +1 -1
- package/dist/commands/deployment/action.js.map +1 -1
- package/dist/commands/deployment/index.d.ts.map +1 -1
- package/dist/commands/deployment/index.js +7 -4
- package/dist/commands/deployment/index.js.map +1 -1
- package/dist/commands/open/action.d.ts +9 -0
- package/dist/commands/open/action.d.ts.map +1 -0
- package/dist/commands/open/action.js +41 -0
- package/dist/commands/open/action.js.map +1 -0
- package/dist/commands/open/index.d.ts +5 -0
- package/dist/commands/open/index.d.ts.map +1 -0
- package/dist/commands/open/index.js +15 -0
- package/dist/commands/open/index.js.map +1 -0
- package/dist/commands/upgrade/action.d.ts +3 -0
- package/dist/commands/upgrade/action.d.ts.map +1 -0
- package/dist/commands/upgrade/action.js +95 -0
- package/dist/commands/upgrade/action.js.map +1 -0
- package/dist/commands/upgrade/index.d.ts +5 -0
- package/dist/commands/upgrade/index.d.ts.map +1 -0
- package/dist/commands/upgrade/index.js +15 -0
- package/dist/commands/upgrade/index.js.map +1 -0
- package/dist/index.js +622 -66
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +4 -0
- package/dist/runtime.js.map +1 -1
- package/dist/services/browser.d.ts +30 -0
- package/dist/services/browser.d.ts.map +1 -0
- package/dist/services/browser.js +102 -0
- package/dist/services/browser.js.map +1 -0
- package/dist/services/compose-args.d.ts +28 -0
- package/dist/services/compose-args.d.ts.map +1 -0
- package/dist/services/compose-args.js +117 -0
- package/dist/services/compose-args.js.map +1 -0
- package/dist/services/compose-upgrade.d.ts +40 -0
- package/dist/services/compose-upgrade.d.ts.map +1 -0
- package/dist/services/compose-upgrade.js +102 -0
- package/dist/services/compose-upgrade.js.map +1 -0
- package/dist/services/deployment-drivers.d.ts +8 -1
- package/dist/services/deployment-drivers.d.ts.map +1 -1
- package/dist/services/deployment-drivers.js +85 -19
- package/dist/services/deployment-drivers.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/templates/schemas/KeyChainConfigFile.schema.json +7 -3
- package/templates/schemas/KeyChainImportDto.schema.json +7 -3
package/dist/index.js
CHANGED
|
@@ -2980,7 +2980,7 @@ var require_compile = __commonJS({
|
|
|
2980
2980
|
const schOrFunc = root.refs[ref];
|
|
2981
2981
|
if (schOrFunc)
|
|
2982
2982
|
return schOrFunc;
|
|
2983
|
-
let _sch =
|
|
2983
|
+
let _sch = resolve9.call(this, root, ref);
|
|
2984
2984
|
if (_sch === void 0) {
|
|
2985
2985
|
const schema = (_a2 = root.localRefs) === null || _a2 === void 0 ? void 0 : _a2[ref];
|
|
2986
2986
|
const { schemaId } = this.opts;
|
|
@@ -3007,7 +3007,7 @@ var require_compile = __commonJS({
|
|
|
3007
3007
|
function sameSchemaEnv(s1, s2) {
|
|
3008
3008
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3009
3009
|
}
|
|
3010
|
-
function
|
|
3010
|
+
function resolve9(root, ref) {
|
|
3011
3011
|
let sch;
|
|
3012
3012
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3013
3013
|
ref = sch;
|
|
@@ -3832,7 +3832,7 @@ var require_fast_uri = __commonJS({
|
|
|
3832
3832
|
}
|
|
3833
3833
|
return uri;
|
|
3834
3834
|
}
|
|
3835
|
-
function
|
|
3835
|
+
function resolve9(baseURI, relativeURI, options) {
|
|
3836
3836
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3837
3837
|
const {
|
|
3838
3838
|
parsed: baseParsed,
|
|
@@ -4194,7 +4194,7 @@ var require_fast_uri = __commonJS({
|
|
|
4194
4194
|
var fastUri = {
|
|
4195
4195
|
SCHEMES,
|
|
4196
4196
|
normalize,
|
|
4197
|
-
resolve:
|
|
4197
|
+
resolve: resolve9,
|
|
4198
4198
|
resolveComponent,
|
|
4199
4199
|
equal,
|
|
4200
4200
|
serialize,
|
|
@@ -21550,8 +21550,107 @@ function createConfigCommand(context, setExitCode) {
|
|
|
21550
21550
|
|
|
21551
21551
|
// src/services/deployment-drivers.ts
|
|
21552
21552
|
import { access as access2, mkdir as mkdir6, rm as rm4, stat as stat2, unlink as unlink2, writeFile as writeFile5 } from "node:fs/promises";
|
|
21553
|
-
import { delimiter, join as join10, resolve as
|
|
21553
|
+
import { delimiter, join as join10, resolve as resolve6 } from "node:path";
|
|
21554
21554
|
import { spawn } from "node:child_process";
|
|
21555
|
+
|
|
21556
|
+
// src/services/compose-args.ts
|
|
21557
|
+
import { resolve as resolve5 } from "node:path";
|
|
21558
|
+
var SERVICE_NAME = /^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/;
|
|
21559
|
+
var DURATION = /^(\d+(\.\d+)?(ns|us|µs|ms|s|m|h))+$/;
|
|
21560
|
+
var TIMESTAMP = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:\d{2})?)?$/;
|
|
21561
|
+
function assertServiceName(service) {
|
|
21562
|
+
if (!SERVICE_NAME.test(service)) {
|
|
21563
|
+
throw new Error(
|
|
21564
|
+
`Invalid service name ${JSON.stringify(service)}. Service names start with a letter or digit and contain only letters, digits, ".", "_" and "-".`
|
|
21565
|
+
);
|
|
21566
|
+
}
|
|
21567
|
+
}
|
|
21568
|
+
function assertSince(since) {
|
|
21569
|
+
const isDuration = DURATION.test(since);
|
|
21570
|
+
const isTimestamp = TIMESTAMP.test(since) && !Number.isNaN(Date.parse(since));
|
|
21571
|
+
if (!isDuration && !isTimestamp) {
|
|
21572
|
+
throw new Error(
|
|
21573
|
+
`Invalid --since value ${JSON.stringify(since)}. Use a duration such as 10m or 2h30m, or a timestamp such as 2026-09-01T12:00:00Z.`
|
|
21574
|
+
);
|
|
21575
|
+
}
|
|
21576
|
+
}
|
|
21577
|
+
function assertTail(tail) {
|
|
21578
|
+
if (!Number.isInteger(tail) || tail < 0) {
|
|
21579
|
+
throw new Error("--tail must be a whole number of lines, 0 or more.");
|
|
21580
|
+
}
|
|
21581
|
+
}
|
|
21582
|
+
function buildComposeBaseArgs(instance, projectDirectory, composeFiles) {
|
|
21583
|
+
const args = ["compose"];
|
|
21584
|
+
if (instance.envFile) {
|
|
21585
|
+
args.push("--env-file", resolve5(projectDirectory, instance.envFile));
|
|
21586
|
+
}
|
|
21587
|
+
for (const composeFile of composeFiles) {
|
|
21588
|
+
args.push("-f", resolve5(projectDirectory, composeFile));
|
|
21589
|
+
}
|
|
21590
|
+
for (const profile of instance.composeProfiles ?? []) {
|
|
21591
|
+
args.push("--profile", profile);
|
|
21592
|
+
}
|
|
21593
|
+
if (instance.projectName) {
|
|
21594
|
+
args.push("--project-name", instance.projectName);
|
|
21595
|
+
}
|
|
21596
|
+
return args;
|
|
21597
|
+
}
|
|
21598
|
+
function buildComposePsArgs() {
|
|
21599
|
+
return ["ps"];
|
|
21600
|
+
}
|
|
21601
|
+
function buildComposeListServicesArgs() {
|
|
21602
|
+
return ["config", "--services"];
|
|
21603
|
+
}
|
|
21604
|
+
function buildComposeLogsArgs(service, options = {}) {
|
|
21605
|
+
const args = ["logs"];
|
|
21606
|
+
if (options.follow === true) {
|
|
21607
|
+
args.push("--follow");
|
|
21608
|
+
}
|
|
21609
|
+
if (options.tail !== void 0) {
|
|
21610
|
+
assertTail(options.tail);
|
|
21611
|
+
args.push("--tail", String(options.tail));
|
|
21612
|
+
}
|
|
21613
|
+
if (options.since !== void 0) {
|
|
21614
|
+
assertSince(options.since);
|
|
21615
|
+
args.push("--since", options.since);
|
|
21616
|
+
}
|
|
21617
|
+
if (service !== void 0) {
|
|
21618
|
+
assertServiceName(service);
|
|
21619
|
+
args.push(service);
|
|
21620
|
+
}
|
|
21621
|
+
return args;
|
|
21622
|
+
}
|
|
21623
|
+
function buildComposePullArgs(service) {
|
|
21624
|
+
const args = ["pull"];
|
|
21625
|
+
if (service !== void 0) {
|
|
21626
|
+
assertServiceName(service);
|
|
21627
|
+
args.push(service);
|
|
21628
|
+
}
|
|
21629
|
+
return args;
|
|
21630
|
+
}
|
|
21631
|
+
function buildComposeUpArgs() {
|
|
21632
|
+
return ["up", "-d"];
|
|
21633
|
+
}
|
|
21634
|
+
function buildComposeRestartArgs(service) {
|
|
21635
|
+
const args = ["restart"];
|
|
21636
|
+
if (service !== void 0) {
|
|
21637
|
+
assertServiceName(service);
|
|
21638
|
+
args.push(service);
|
|
21639
|
+
}
|
|
21640
|
+
return args;
|
|
21641
|
+
}
|
|
21642
|
+
function parseServiceList(stdout) {
|
|
21643
|
+
return stdout.split(/\r?\n/).map((line) => line.trim()).filter((line) => SERVICE_NAME.test(line)).sort();
|
|
21644
|
+
}
|
|
21645
|
+
function assertKnownService(service, known) {
|
|
21646
|
+
if (!known.includes(service)) {
|
|
21647
|
+
throw new Error(
|
|
21648
|
+
`Unknown service ${service}. Services in this project: ${known.join(", ") || "none"}.`
|
|
21649
|
+
);
|
|
21650
|
+
}
|
|
21651
|
+
}
|
|
21652
|
+
|
|
21653
|
+
// src/services/deployment-drivers.ts
|
|
21555
21654
|
var drivers = {
|
|
21556
21655
|
compose: {
|
|
21557
21656
|
target: "compose",
|
|
@@ -21567,7 +21666,7 @@ var drivers = {
|
|
|
21567
21666
|
for (const composeFile of getComposeFiles(instance)) {
|
|
21568
21667
|
let found = true;
|
|
21569
21668
|
try {
|
|
21570
|
-
await access2(
|
|
21669
|
+
await access2(resolve6(projectDirectory, composeFile));
|
|
21571
21670
|
} catch {
|
|
21572
21671
|
found = false;
|
|
21573
21672
|
}
|
|
@@ -21585,8 +21684,41 @@ var drivers = {
|
|
|
21585
21684
|
down(options) {
|
|
21586
21685
|
return runCompose(["down", ...options.args], options);
|
|
21587
21686
|
},
|
|
21588
|
-
logs(options) {
|
|
21589
|
-
|
|
21687
|
+
async logs(options) {
|
|
21688
|
+
const service = await resolveComposeService(options);
|
|
21689
|
+
const { follow, tail } = readLogOptions(options.flags);
|
|
21690
|
+
const since = typeof options.flags.since === "string" ? options.flags.since : void 0;
|
|
21691
|
+
return runCompose(
|
|
21692
|
+
[
|
|
21693
|
+
...buildComposeLogsArgs(service, { follow, tail, since }),
|
|
21694
|
+
...options.args
|
|
21695
|
+
],
|
|
21696
|
+
options
|
|
21697
|
+
);
|
|
21698
|
+
},
|
|
21699
|
+
async ps(options) {
|
|
21700
|
+
return runCompose(
|
|
21701
|
+
[...buildComposePsArgs(), ...options.args],
|
|
21702
|
+
options
|
|
21703
|
+
);
|
|
21704
|
+
},
|
|
21705
|
+
async pull(options) {
|
|
21706
|
+
const service = await resolveComposeService(options);
|
|
21707
|
+
return runCompose(
|
|
21708
|
+
[...buildComposePullArgs(service), ...options.args],
|
|
21709
|
+
options
|
|
21710
|
+
);
|
|
21711
|
+
},
|
|
21712
|
+
async restart(options) {
|
|
21713
|
+
assertWritable(options);
|
|
21714
|
+
const service = await resolveComposeService(options);
|
|
21715
|
+
const restartArgs = buildComposeRestartArgs(service);
|
|
21716
|
+
const runtime = await resolveComposeRuntime(options.context.env);
|
|
21717
|
+
options.context.stdout.write(
|
|
21718
|
+
`Restarting ${service ?? "all services"} of ${options.instanceName}${runtime ? ` with ${runtime.name} compose` : ""}
|
|
21719
|
+
`
|
|
21720
|
+
);
|
|
21721
|
+
return runCompose([...restartArgs, ...options.args], options);
|
|
21590
21722
|
}
|
|
21591
21723
|
},
|
|
21592
21724
|
external: {
|
|
@@ -21606,7 +21738,11 @@ var drivers = {
|
|
|
21606
21738
|
);
|
|
21607
21739
|
return runKubectl(
|
|
21608
21740
|
[
|
|
21609
|
-
...buildLogsArgs(
|
|
21741
|
+
...buildLogsArgs(
|
|
21742
|
+
scope,
|
|
21743
|
+
workload,
|
|
21744
|
+
readLogOptions(options.flags)
|
|
21745
|
+
),
|
|
21610
21746
|
...options.args
|
|
21611
21747
|
],
|
|
21612
21748
|
options
|
|
@@ -21634,14 +21770,17 @@ var drivers = {
|
|
|
21634
21770
|
[...buildRestartArgs(scope, workload), ...options.args],
|
|
21635
21771
|
options
|
|
21636
21772
|
);
|
|
21637
|
-
if (restarted !== 0 || options.flags
|
|
21773
|
+
if (restarted !== 0 || options.flags["no-wait"] === true) {
|
|
21638
21774
|
return restarted;
|
|
21639
21775
|
}
|
|
21640
21776
|
return runKubectl(buildRolloutStatusArgs(scope, workload), options);
|
|
21641
21777
|
}
|
|
21642
21778
|
}
|
|
21643
21779
|
};
|
|
21644
|
-
function assertWritable({
|
|
21780
|
+
function assertWritable({
|
|
21781
|
+
instance,
|
|
21782
|
+
instanceName
|
|
21783
|
+
}) {
|
|
21645
21784
|
if (instance.readOnly === true) {
|
|
21646
21785
|
throw new Error(
|
|
21647
21786
|
`Instance ${instanceName} is registered read-only. Re-register it without --read-only to allow changes.`
|
|
@@ -21847,7 +21986,10 @@ function unreadyEndpoints(stdout) {
|
|
|
21847
21986
|
(endpoint) => isRecord3(endpoint) && // An omitted ready condition means ready, per the API contract.
|
|
21848
21987
|
(!isRecord3(endpoint.conditions) || endpoint.conditions.ready !== false)
|
|
21849
21988
|
);
|
|
21850
|
-
readyByService.set(
|
|
21989
|
+
readyByService.set(
|
|
21990
|
+
service,
|
|
21991
|
+
(readyByService.get(service) ?? false) || ready
|
|
21992
|
+
);
|
|
21851
21993
|
}
|
|
21852
21994
|
return [...readyByService.entries()].filter(([, ready]) => !ready).map(([service]) => service).sort();
|
|
21853
21995
|
}
|
|
@@ -21975,7 +22117,7 @@ async function ensureComposeProject(cwd, options) {
|
|
|
21975
22117
|
composeProfiles: composeProfiles(options),
|
|
21976
22118
|
envFile: envFileName,
|
|
21977
22119
|
projectName: mode === "demo" ? "eudiplo-demo" : "eudiplo",
|
|
21978
|
-
projectDirectory:
|
|
22120
|
+
projectDirectory: resolve6(cwd)
|
|
21979
22121
|
};
|
|
21980
22122
|
}
|
|
21981
22123
|
async function ensureProjectDirectory(directory) {
|
|
@@ -22029,23 +22171,14 @@ function unsupportedCommand(command, target) {
|
|
|
22029
22171
|
}
|
|
22030
22172
|
async function runCompose(args, { instance, context }) {
|
|
22031
22173
|
const projectDirectory = instance.projectDirectory ?? context.cwd;
|
|
22032
|
-
const composeArgs = [
|
|
22033
|
-
|
|
22034
|
-
|
|
22035
|
-
|
|
22036
|
-
|
|
22037
|
-
)
|
|
22038
|
-
|
|
22039
|
-
|
|
22040
|
-
composeArgs.push("-f", resolve5(projectDirectory, composeFile));
|
|
22041
|
-
}
|
|
22042
|
-
for (const profile of instance.composeProfiles ?? []) {
|
|
22043
|
-
composeArgs.push("--profile", profile);
|
|
22044
|
-
}
|
|
22045
|
-
if (instance.projectName) {
|
|
22046
|
-
composeArgs.push("--project-name", instance.projectName);
|
|
22047
|
-
}
|
|
22048
|
-
composeArgs.push(...args);
|
|
22174
|
+
const composeArgs = [
|
|
22175
|
+
...buildComposeBaseArgs(
|
|
22176
|
+
instance,
|
|
22177
|
+
projectDirectory,
|
|
22178
|
+
getComposeFiles(instance)
|
|
22179
|
+
),
|
|
22180
|
+
...args
|
|
22181
|
+
];
|
|
22049
22182
|
const composeRuntime = await resolveComposeRuntime(context.env);
|
|
22050
22183
|
if (!composeRuntime) {
|
|
22051
22184
|
context.stderr.write(
|
|
@@ -22067,6 +22200,64 @@ async function runCompose(args, { instance, context }) {
|
|
|
22067
22200
|
child.on("close", (code) => resolveProcess(code ?? 1));
|
|
22068
22201
|
});
|
|
22069
22202
|
}
|
|
22203
|
+
async function captureCompose(args, { instance, context }) {
|
|
22204
|
+
const projectDirectory = instance.projectDirectory ?? context.cwd;
|
|
22205
|
+
const composeRuntime = await resolveComposeRuntime(context.env);
|
|
22206
|
+
if (!composeRuntime) {
|
|
22207
|
+
throw new Error(
|
|
22208
|
+
"Docker or Podman was not found in a supported install location."
|
|
22209
|
+
);
|
|
22210
|
+
}
|
|
22211
|
+
const composeArgs = [
|
|
22212
|
+
...buildComposeBaseArgs(
|
|
22213
|
+
instance,
|
|
22214
|
+
projectDirectory,
|
|
22215
|
+
getComposeFiles(instance)
|
|
22216
|
+
),
|
|
22217
|
+
...args
|
|
22218
|
+
];
|
|
22219
|
+
return new Promise((resolveProcess) => {
|
|
22220
|
+
const child = spawn(composeRuntime.command, composeArgs, {
|
|
22221
|
+
cwd: projectDirectory,
|
|
22222
|
+
env: context.env,
|
|
22223
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
22224
|
+
});
|
|
22225
|
+
let stdout = "";
|
|
22226
|
+
let stderr = "";
|
|
22227
|
+
child.stdout?.on("data", (chunk) => {
|
|
22228
|
+
stdout += String(chunk);
|
|
22229
|
+
});
|
|
22230
|
+
child.stderr?.on("data", (chunk) => {
|
|
22231
|
+
stderr += String(chunk);
|
|
22232
|
+
});
|
|
22233
|
+
child.on(
|
|
22234
|
+
"error",
|
|
22235
|
+
(error) => resolveProcess({ code: 1, stdout, stderr: error.message })
|
|
22236
|
+
);
|
|
22237
|
+
child.on(
|
|
22238
|
+
"close",
|
|
22239
|
+
(code) => resolveProcess({ code: code ?? 1, stdout, stderr })
|
|
22240
|
+
);
|
|
22241
|
+
});
|
|
22242
|
+
}
|
|
22243
|
+
async function resolveComposeService(options) {
|
|
22244
|
+
const service = readServiceFlag(options.flags);
|
|
22245
|
+
if (service === void 0) {
|
|
22246
|
+
return void 0;
|
|
22247
|
+
}
|
|
22248
|
+
assertServiceName(service);
|
|
22249
|
+
const listed = await captureCompose(
|
|
22250
|
+
buildComposeListServicesArgs(),
|
|
22251
|
+
options
|
|
22252
|
+
);
|
|
22253
|
+
if (listed.code !== 0) {
|
|
22254
|
+
throw new Error(
|
|
22255
|
+
`Could not list Compose services: ${listed.stderr.trim() || `exit code ${listed.code}`}`
|
|
22256
|
+
);
|
|
22257
|
+
}
|
|
22258
|
+
assertKnownService(service, parseServiceList(listed.stdout));
|
|
22259
|
+
return service;
|
|
22260
|
+
}
|
|
22070
22261
|
async function resolveComposeRuntime(env) {
|
|
22071
22262
|
const preferredRuntime = parsePreferredRuntime(
|
|
22072
22263
|
env.EUDIPLO_CONTAINER_RUNTIME
|
|
@@ -22164,7 +22355,7 @@ async function removeIfExists(path2) {
|
|
|
22164
22355
|
}
|
|
22165
22356
|
|
|
22166
22357
|
// src/services/project-directory.ts
|
|
22167
|
-
import { resolve as
|
|
22358
|
+
import { resolve as resolve7 } from "node:path";
|
|
22168
22359
|
function resolveProjectDirectory(parsed, context, promptedDirectory) {
|
|
22169
22360
|
const positionalDirectory = parsed.subject;
|
|
22170
22361
|
const flagDirectory = readStringFlag(parsed.flags, "directory");
|
|
@@ -22176,7 +22367,7 @@ function resolveProjectDirectory(parsed, context, promptedDirectory) {
|
|
|
22176
22367
|
"Specify the project directory either positionally or with --directory."
|
|
22177
22368
|
);
|
|
22178
22369
|
}
|
|
22179
|
-
return
|
|
22370
|
+
return resolve7(
|
|
22180
22371
|
context.cwd,
|
|
22181
22372
|
positionalDirectory ?? flagDirectory ?? promptedDirectory ?? "."
|
|
22182
22373
|
);
|
|
@@ -22302,45 +22493,52 @@ var descriptions = {
|
|
|
22302
22493
|
down: "Stop the selected Compose deployment",
|
|
22303
22494
|
logs: "Stream logs for the selected deployment",
|
|
22304
22495
|
ps: "List the running containers or pods for the selected deployment",
|
|
22305
|
-
restart: "Restart the workloads of the selected deployment"
|
|
22496
|
+
restart: "Restart the workloads of the selected deployment",
|
|
22497
|
+
pull: "Download the configured images without changing configuration"
|
|
22306
22498
|
};
|
|
22307
22499
|
var serviceScoped = /* @__PURE__ */ new Set([
|
|
22308
22500
|
"logs",
|
|
22309
|
-
"restart"
|
|
22501
|
+
"restart",
|
|
22502
|
+
"pull"
|
|
22310
22503
|
]);
|
|
22311
22504
|
function createDeploymentCommands(context, setExitCode) {
|
|
22312
|
-
return ["up", "down", "logs", "ps", "restart"].map(
|
|
22313
|
-
|
|
22314
|
-
|
|
22315
|
-
|
|
22316
|
-
|
|
22317
|
-
|
|
22318
|
-
|
|
22319
|
-
|
|
22320
|
-
|
|
22321
|
-
|
|
22322
|
-
|
|
22323
|
-
|
|
22324
|
-
|
|
22325
|
-
|
|
22326
|
-
|
|
22327
|
-
|
|
22328
|
-
|
|
22329
|
-
|
|
22330
|
-
)
|
|
22505
|
+
return ["up", "down", "logs", "ps", "restart", "pull"].map(
|
|
22506
|
+
(name) => {
|
|
22507
|
+
const command = new Command(name).description(descriptions[name]).argument(
|
|
22508
|
+
"[args...]",
|
|
22509
|
+
"additional arguments passed to the deployment runtime"
|
|
22510
|
+
).option("--instance <name>", "select a configured instance");
|
|
22511
|
+
if (serviceScoped.has(name)) {
|
|
22512
|
+
command.option(
|
|
22513
|
+
"--service <name>",
|
|
22514
|
+
"select a single service (Compose) or configured workload (Kubernetes)"
|
|
22515
|
+
);
|
|
22516
|
+
}
|
|
22517
|
+
if (name === "logs") {
|
|
22518
|
+
command.option("--follow", "stream new output as it arrives").option("--tail <lines>", "number of recent lines to show").option(
|
|
22519
|
+
"--since <time>",
|
|
22520
|
+
"show logs since a duration (10m, 2h) or timestamp (Compose instances)"
|
|
22521
|
+
);
|
|
22522
|
+
}
|
|
22523
|
+
if (name === "restart") {
|
|
22524
|
+
command.option(
|
|
22525
|
+
"--no-wait",
|
|
22526
|
+
"return without waiting for the rollout to finish (Kubernetes instances)"
|
|
22527
|
+
);
|
|
22528
|
+
}
|
|
22529
|
+
return command.action(async (args, options) => {
|
|
22530
|
+
const { config } = await loadCliState(context);
|
|
22531
|
+
setExitCode(
|
|
22532
|
+
await runDriverCommand(
|
|
22533
|
+
config,
|
|
22534
|
+
name,
|
|
22535
|
+
parsedArgs(name, void 0, args, options),
|
|
22536
|
+
context
|
|
22537
|
+
)
|
|
22538
|
+
);
|
|
22539
|
+
});
|
|
22331
22540
|
}
|
|
22332
|
-
|
|
22333
|
-
const { config } = await loadCliState(context);
|
|
22334
|
-
setExitCode(
|
|
22335
|
-
await runDriverCommand(
|
|
22336
|
-
config,
|
|
22337
|
-
name,
|
|
22338
|
-
parsedArgs(name, void 0, args, options),
|
|
22339
|
-
context
|
|
22340
|
-
)
|
|
22341
|
-
);
|
|
22342
|
-
});
|
|
22343
|
-
});
|
|
22541
|
+
);
|
|
22344
22542
|
}
|
|
22345
22543
|
|
|
22346
22544
|
// src/services/diagnostics.ts
|
|
@@ -23020,6 +23218,146 @@ function createInstanceCommand(context, setExitCode) {
|
|
|
23020
23218
|
return instance;
|
|
23021
23219
|
}
|
|
23022
23220
|
|
|
23221
|
+
// src/services/browser.ts
|
|
23222
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
23223
|
+
import { access as access3 } from "node:fs/promises";
|
|
23224
|
+
import { delimiter as delimiter2, join as join11 } from "node:path";
|
|
23225
|
+
function assertWebUrl(value) {
|
|
23226
|
+
let url;
|
|
23227
|
+
try {
|
|
23228
|
+
url = new URL(value);
|
|
23229
|
+
} catch {
|
|
23230
|
+
throw new Error(`${value} is not a valid absolute URL.`);
|
|
23231
|
+
}
|
|
23232
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
23233
|
+
throw new Error(
|
|
23234
|
+
`Refusing to open ${value}: only http and https URLs are supported.`
|
|
23235
|
+
);
|
|
23236
|
+
}
|
|
23237
|
+
return url;
|
|
23238
|
+
}
|
|
23239
|
+
async function chooseLauncher(url, { platform, env, which }) {
|
|
23240
|
+
const browser = env.BROWSER?.trim();
|
|
23241
|
+
if (browser && !/\s|%s/.test(browser)) {
|
|
23242
|
+
const command = await which(browser);
|
|
23243
|
+
if (command) {
|
|
23244
|
+
return { command, args: [url] };
|
|
23245
|
+
}
|
|
23246
|
+
}
|
|
23247
|
+
if (platform === "darwin") {
|
|
23248
|
+
return { command: "open", args: [url] };
|
|
23249
|
+
}
|
|
23250
|
+
if (platform === "win32") {
|
|
23251
|
+
return {
|
|
23252
|
+
command: "rundll32.exe",
|
|
23253
|
+
args: ["url.dll,FileProtocolHandler", url]
|
|
23254
|
+
};
|
|
23255
|
+
}
|
|
23256
|
+
if (env.WSL_DISTRO_NAME) {
|
|
23257
|
+
const wslview = await which("wslview");
|
|
23258
|
+
if (wslview) {
|
|
23259
|
+
return { command: wslview, args: [url] };
|
|
23260
|
+
}
|
|
23261
|
+
}
|
|
23262
|
+
if (env.DISPLAY || env.WAYLAND_DISPLAY) {
|
|
23263
|
+
const xdgOpen = await which("xdg-open");
|
|
23264
|
+
if (xdgOpen) {
|
|
23265
|
+
return { command: xdgOpen, args: [url] };
|
|
23266
|
+
}
|
|
23267
|
+
}
|
|
23268
|
+
return void 0;
|
|
23269
|
+
}
|
|
23270
|
+
function launchBrowser(launcher) {
|
|
23271
|
+
return new Promise((resolveLaunch) => {
|
|
23272
|
+
const child = spawn2(launcher.command, launcher.args, {
|
|
23273
|
+
detached: true,
|
|
23274
|
+
stdio: "ignore"
|
|
23275
|
+
});
|
|
23276
|
+
child.once("error", () => resolveLaunch(false));
|
|
23277
|
+
child.once("spawn", () => {
|
|
23278
|
+
child.unref();
|
|
23279
|
+
resolveLaunch(true);
|
|
23280
|
+
});
|
|
23281
|
+
});
|
|
23282
|
+
}
|
|
23283
|
+
function pathLookup(env, platform = process.platform) {
|
|
23284
|
+
const extensions = platform === "win32" ? ["", ...(env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";")] : [""];
|
|
23285
|
+
return async (name) => {
|
|
23286
|
+
const entries = (env.PATH ?? "").split(delimiter2).filter(Boolean);
|
|
23287
|
+
for (const entry of entries) {
|
|
23288
|
+
for (const extension of extensions) {
|
|
23289
|
+
const candidate = join11(entry, `${name}${extension}`);
|
|
23290
|
+
try {
|
|
23291
|
+
await access3(candidate);
|
|
23292
|
+
return candidate;
|
|
23293
|
+
} catch {
|
|
23294
|
+
}
|
|
23295
|
+
}
|
|
23296
|
+
}
|
|
23297
|
+
return void 0;
|
|
23298
|
+
};
|
|
23299
|
+
}
|
|
23300
|
+
|
|
23301
|
+
// src/commands/open/action.ts
|
|
23302
|
+
var defaultDependencies = {
|
|
23303
|
+
platform: process.platform,
|
|
23304
|
+
launch: launchBrowser
|
|
23305
|
+
};
|
|
23306
|
+
function resolveOpenTarget(instanceName, instance, docs) {
|
|
23307
|
+
if (docs) {
|
|
23308
|
+
const base = instance.url.endsWith("/") ? instance.url : `${instance.url}/`;
|
|
23309
|
+
return assertWebUrl(new URL("api/docs", base).href).href;
|
|
23310
|
+
}
|
|
23311
|
+
if (!instance.clientUrl) {
|
|
23312
|
+
throw new Error(
|
|
23313
|
+
`Instance ${instanceName} has no web client URL. Use --docs to open the API documentation instead.`
|
|
23314
|
+
);
|
|
23315
|
+
}
|
|
23316
|
+
return assertWebUrl(instance.clientUrl).href;
|
|
23317
|
+
}
|
|
23318
|
+
async function runOpenCommand(config, parsed, context, dependencies = defaultDependencies) {
|
|
23319
|
+
const [instanceName, instance] = resolveInstance(config, parsed);
|
|
23320
|
+
const url = resolveOpenTarget(
|
|
23321
|
+
instanceName,
|
|
23322
|
+
instance,
|
|
23323
|
+
parsed.flags.docs === true
|
|
23324
|
+
);
|
|
23325
|
+
if (parsed.flags.print === true || context.interactive !== true) {
|
|
23326
|
+
context.stdout.write(`${url}
|
|
23327
|
+
`);
|
|
23328
|
+
return 0;
|
|
23329
|
+
}
|
|
23330
|
+
const launcher = await chooseLauncher(url, {
|
|
23331
|
+
platform: dependencies.platform,
|
|
23332
|
+
env: context.env,
|
|
23333
|
+
which: pathLookup(context.env, dependencies.platform)
|
|
23334
|
+
});
|
|
23335
|
+
if (!launcher || !await dependencies.launch(launcher)) {
|
|
23336
|
+
context.stdout.write(`No browser is available here. Open: ${url}
|
|
23337
|
+
`);
|
|
23338
|
+
return 0;
|
|
23339
|
+
}
|
|
23340
|
+
context.stdout.write(`Opening ${url}
|
|
23341
|
+
`);
|
|
23342
|
+
return 0;
|
|
23343
|
+
}
|
|
23344
|
+
|
|
23345
|
+
// src/commands/open/index.ts
|
|
23346
|
+
function createOpenCommand(context, setExitCode) {
|
|
23347
|
+
return new Command("open").description(
|
|
23348
|
+
"Open the web client of the selected instance in a browser"
|
|
23349
|
+
).option("--instance <name>", "select a configured instance").option("--docs", "open the management API documentation instead").option("--print", "print the URL instead of opening a browser").action(async (options) => {
|
|
23350
|
+
const { config } = await loadCliState(context);
|
|
23351
|
+
setExitCode(
|
|
23352
|
+
await runOpenCommand(
|
|
23353
|
+
config,
|
|
23354
|
+
parsedArgs("open", void 0, [], options),
|
|
23355
|
+
context
|
|
23356
|
+
)
|
|
23357
|
+
);
|
|
23358
|
+
});
|
|
23359
|
+
}
|
|
23360
|
+
|
|
23023
23361
|
// src/commands/status/action.ts
|
|
23024
23362
|
async function runStatusCommand(config, parsed, context) {
|
|
23025
23363
|
const [instanceName, instance] = resolveInstance(config, parsed);
|
|
@@ -23052,13 +23390,229 @@ function createStatusCommand(context, setExitCode) {
|
|
|
23052
23390
|
});
|
|
23053
23391
|
}
|
|
23054
23392
|
|
|
23393
|
+
// src/commands/upgrade/action.ts
|
|
23394
|
+
import { readFile as readFile9, writeFile as writeFile6 } from "node:fs/promises";
|
|
23395
|
+
import { resolve as resolve8 } from "node:path";
|
|
23396
|
+
|
|
23397
|
+
// src/services/compose-upgrade.ts
|
|
23398
|
+
var managedImages = {
|
|
23399
|
+
EUDIPLO_IMAGE: "ghcr.io/openwallet-foundation/eudiplo",
|
|
23400
|
+
EUDIPLO_CLIENT_IMAGE: "ghcr.io/openwallet-foundation/eudiplo-client"
|
|
23401
|
+
};
|
|
23402
|
+
var TAG = /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,127}$/;
|
|
23403
|
+
function assertImageTag(tag) {
|
|
23404
|
+
if (!TAG.test(tag)) {
|
|
23405
|
+
throw new Error(
|
|
23406
|
+
`Invalid image tag ${JSON.stringify(tag)}. Tags contain letters, digits, "_", "." and "-", and cannot start with "." or "-".`
|
|
23407
|
+
);
|
|
23408
|
+
}
|
|
23409
|
+
}
|
|
23410
|
+
function planImageUpgrade(content, tag) {
|
|
23411
|
+
assertImageTag(tag);
|
|
23412
|
+
const found = /* @__PURE__ */ new Set();
|
|
23413
|
+
const changes = [];
|
|
23414
|
+
const lines = content.split("\n").map((line) => {
|
|
23415
|
+
const match = /^(EUDIPLO_IMAGE|EUDIPLO_CLIENT_IMAGE)=(.*?)(\r?)$/.exec(
|
|
23416
|
+
line
|
|
23417
|
+
);
|
|
23418
|
+
if (!match) {
|
|
23419
|
+
return line;
|
|
23420
|
+
}
|
|
23421
|
+
const key = match[1];
|
|
23422
|
+
const value = match[2];
|
|
23423
|
+
const lineEnding = match[3];
|
|
23424
|
+
const repository = managedImages[key];
|
|
23425
|
+
if (found.has(key)) {
|
|
23426
|
+
throw new Error(
|
|
23427
|
+
`${key} is defined more than once in the env file.`
|
|
23428
|
+
);
|
|
23429
|
+
}
|
|
23430
|
+
found.add(key);
|
|
23431
|
+
const prefix = `${repository}:`;
|
|
23432
|
+
const current = value.startsWith(prefix) ? value.slice(prefix.length) : void 0;
|
|
23433
|
+
if (current === void 0 || !TAG.test(current)) {
|
|
23434
|
+
throw new Error(
|
|
23435
|
+
`${key} is set to ${value}, which is not a CLI-managed image. Update it yourself, or restore ${prefix}<tag> to let the CLI manage it.`
|
|
23436
|
+
);
|
|
23437
|
+
}
|
|
23438
|
+
if (current !== tag) {
|
|
23439
|
+
changes.push({ key, repository, from: current, to: tag });
|
|
23440
|
+
}
|
|
23441
|
+
return `${key}=${prefix}${tag}${lineEnding}`;
|
|
23442
|
+
});
|
|
23443
|
+
if (!found.has("EUDIPLO_IMAGE")) {
|
|
23444
|
+
throw new Error(
|
|
23445
|
+
"The env file does not define EUDIPLO_IMAGE, so there is no CLI-managed image to upgrade."
|
|
23446
|
+
);
|
|
23447
|
+
}
|
|
23448
|
+
return { changes, content: lines.join("\n") };
|
|
23449
|
+
}
|
|
23450
|
+
function parseVersion(tag) {
|
|
23451
|
+
const match = /^v?(\d+)\.(\d+)\.(\d+)$/.exec(tag);
|
|
23452
|
+
if (!match) {
|
|
23453
|
+
return void 0;
|
|
23454
|
+
}
|
|
23455
|
+
return {
|
|
23456
|
+
major: Number(match[1]),
|
|
23457
|
+
minor: Number(match[2]),
|
|
23458
|
+
patch: Number(match[3])
|
|
23459
|
+
};
|
|
23460
|
+
}
|
|
23461
|
+
function compareVersions(a, b) {
|
|
23462
|
+
return a.major - b.major || a.minor - b.minor || a.patch - b.patch;
|
|
23463
|
+
}
|
|
23464
|
+
var migrationBaseUrl = "https://docs.eudiplo.dev/migration";
|
|
23465
|
+
function migrationNotes(from, to) {
|
|
23466
|
+
const fromVersion = parseVersion(from);
|
|
23467
|
+
const toVersion = parseVersion(to);
|
|
23468
|
+
if (!fromVersion || !toVersion) {
|
|
23469
|
+
return [
|
|
23470
|
+
`Cannot compare ${from} and ${to} as versions. Check the release notes and ${migrationBaseUrl} before continuing.`
|
|
23471
|
+
];
|
|
23472
|
+
}
|
|
23473
|
+
const order = compareVersions(fromVersion, toVersion);
|
|
23474
|
+
if (order > 0) {
|
|
23475
|
+
return [
|
|
23476
|
+
`${to} is older than ${from}. Downgrades are not supported once database migrations have run; restore a backup instead if you need to go back.`
|
|
23477
|
+
];
|
|
23478
|
+
}
|
|
23479
|
+
const notes = [];
|
|
23480
|
+
for (let major = fromVersion.major + 1; major <= toVersion.major; major++) {
|
|
23481
|
+
notes.push(
|
|
23482
|
+
`Major version ${major}: read ${migrationBaseUrl}/${major - 1}.x-to-${major}.0 first.`
|
|
23483
|
+
);
|
|
23484
|
+
}
|
|
23485
|
+
return notes;
|
|
23486
|
+
}
|
|
23487
|
+
|
|
23488
|
+
// src/commands/upgrade/action.ts
|
|
23489
|
+
async function runUpgradeCommand(config, parsed, context) {
|
|
23490
|
+
const [instanceName, instance] = resolveInstance(config, parsed);
|
|
23491
|
+
if (instance.target !== "compose") {
|
|
23492
|
+
throw new Error(unsupportedCommand("upgrade", instance.target));
|
|
23493
|
+
}
|
|
23494
|
+
const options = {
|
|
23495
|
+
instanceName,
|
|
23496
|
+
instance,
|
|
23497
|
+
args: [],
|
|
23498
|
+
flags: parsed.flags,
|
|
23499
|
+
context
|
|
23500
|
+
};
|
|
23501
|
+
assertWritable(options);
|
|
23502
|
+
const tag = readStringFlag(parsed.flags, "image-tag");
|
|
23503
|
+
if (!tag) {
|
|
23504
|
+
throw new Error("upgrade requires --image-tag <tag>.");
|
|
23505
|
+
}
|
|
23506
|
+
if (!instance.envFile) {
|
|
23507
|
+
throw new Error(
|
|
23508
|
+
`Instance ${instanceName} has no env file, so its images are not managed by the CLI.`
|
|
23509
|
+
);
|
|
23510
|
+
}
|
|
23511
|
+
const envPath = resolve8(
|
|
23512
|
+
instance.projectDirectory ?? context.cwd,
|
|
23513
|
+
instance.envFile
|
|
23514
|
+
);
|
|
23515
|
+
const original = await readEnvFile(envPath);
|
|
23516
|
+
const plan = planImageUpgrade(original, tag);
|
|
23517
|
+
if (plan.changes.length === 0) {
|
|
23518
|
+
context.stdout.write(
|
|
23519
|
+
`${instanceName} already uses image tag ${tag}.
|
|
23520
|
+
`
|
|
23521
|
+
);
|
|
23522
|
+
return 0;
|
|
23523
|
+
}
|
|
23524
|
+
context.stdout.write(`Upgrade ${instanceName}:
|
|
23525
|
+
`);
|
|
23526
|
+
for (const change of plan.changes) {
|
|
23527
|
+
context.stdout.write(
|
|
23528
|
+
` ${change.repository}: ${change.from} -> ${change.to}
|
|
23529
|
+
`
|
|
23530
|
+
);
|
|
23531
|
+
}
|
|
23532
|
+
const notes = new Set(
|
|
23533
|
+
plan.changes.flatMap(
|
|
23534
|
+
(change) => migrationNotes(change.from, change.to)
|
|
23535
|
+
)
|
|
23536
|
+
);
|
|
23537
|
+
for (const note of notes) {
|
|
23538
|
+
context.stdout.write(`Note: ${note}
|
|
23539
|
+
`);
|
|
23540
|
+
}
|
|
23541
|
+
if (!await confirmUpgrade(parsed, context)) {
|
|
23542
|
+
context.stdout.write("Upgrade cancelled. Nothing was changed.\n");
|
|
23543
|
+
return 0;
|
|
23544
|
+
}
|
|
23545
|
+
await writeFile6(envPath, plan.content, "utf8");
|
|
23546
|
+
const pulled = await runCompose(buildComposePullArgs(void 0), options);
|
|
23547
|
+
if (pulled !== 0) {
|
|
23548
|
+
await writeFile6(envPath, original, "utf8");
|
|
23549
|
+
context.stderr.write(
|
|
23550
|
+
`Pulling the new images failed. Restored the previous image tags in ${envPath}.
|
|
23551
|
+
`
|
|
23552
|
+
);
|
|
23553
|
+
return pulled;
|
|
23554
|
+
}
|
|
23555
|
+
const recreated = await runCompose(buildComposeUpArgs(), options);
|
|
23556
|
+
if (recreated !== 0) {
|
|
23557
|
+
context.stderr.write(
|
|
23558
|
+
`The new images were pulled and ${envPath} now uses ${tag}, but recreating the services failed. Fix the error above and run eudiplo up.
|
|
23559
|
+
`
|
|
23560
|
+
);
|
|
23561
|
+
return recreated;
|
|
23562
|
+
}
|
|
23563
|
+
context.stdout.write(`Upgraded ${instanceName} to ${tag}.
|
|
23564
|
+
`);
|
|
23565
|
+
return 0;
|
|
23566
|
+
}
|
|
23567
|
+
async function readEnvFile(path2) {
|
|
23568
|
+
try {
|
|
23569
|
+
return await readFile9(path2, "utf8");
|
|
23570
|
+
} catch (error) {
|
|
23571
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
23572
|
+
throw new Error(`Env file not found: ${path2}`);
|
|
23573
|
+
}
|
|
23574
|
+
throw error;
|
|
23575
|
+
}
|
|
23576
|
+
}
|
|
23577
|
+
async function confirmUpgrade(parsed, context) {
|
|
23578
|
+
if (parsed.flags.yes === true) {
|
|
23579
|
+
return true;
|
|
23580
|
+
}
|
|
23581
|
+
if (context.interactive !== true) {
|
|
23582
|
+
throw new Error("upgrade requires --yes in non-interactive mode.");
|
|
23583
|
+
}
|
|
23584
|
+
const prompter = createPrompter(context);
|
|
23585
|
+
try {
|
|
23586
|
+
const answer = (await prompter.ask("Continue? [y/N]: ")).trim().toLowerCase();
|
|
23587
|
+
return answer === "y" || answer === "yes";
|
|
23588
|
+
} finally {
|
|
23589
|
+
prompter.close();
|
|
23590
|
+
}
|
|
23591
|
+
}
|
|
23592
|
+
|
|
23593
|
+
// src/commands/upgrade/index.ts
|
|
23594
|
+
function createUpgradeCommand(context, setExitCode) {
|
|
23595
|
+
return new Command("upgrade").description(
|
|
23596
|
+
"Upgrade the EUDIPLO application images of a Compose deployment"
|
|
23597
|
+
).requiredOption("--image-tag <tag>", "image tag to upgrade to").option("--instance <name>", "select a configured instance").option("--yes", "upgrade without asking for confirmation").action(async (options) => {
|
|
23598
|
+
const { config } = await loadCliState(context);
|
|
23599
|
+
setExitCode(
|
|
23600
|
+
await runUpgradeCommand(
|
|
23601
|
+
config,
|
|
23602
|
+
parsedArgs("upgrade", void 0, [], options),
|
|
23603
|
+
context
|
|
23604
|
+
)
|
|
23605
|
+
);
|
|
23606
|
+
});
|
|
23607
|
+
}
|
|
23608
|
+
|
|
23055
23609
|
// src/commands/version/action.ts
|
|
23056
23610
|
import { isSea as isSea2 } from "node:sea";
|
|
23057
23611
|
|
|
23058
23612
|
// package.json
|
|
23059
23613
|
var package_default = {
|
|
23060
23614
|
name: "@eudiplo/cli",
|
|
23061
|
-
version: "8.0.2-main.
|
|
23615
|
+
version: "8.0.2-main.4c3e735",
|
|
23062
23616
|
description: "Deployment-aware command line tools for EUDIPLO",
|
|
23063
23617
|
private: false,
|
|
23064
23618
|
type: "module",
|
|
@@ -23232,6 +23786,8 @@ function createProgram(context, setExitCode) {
|
|
|
23232
23786
|
for (const command of createDeploymentCommands(context, setExitCode)) {
|
|
23233
23787
|
program2.addCommand(command);
|
|
23234
23788
|
}
|
|
23789
|
+
program2.addCommand(createUpgradeCommand(context, setExitCode));
|
|
23790
|
+
program2.addCommand(createOpenCommand(context, setExitCode));
|
|
23235
23791
|
program2.addCommand(createInstanceCommand(context, setExitCode));
|
|
23236
23792
|
program2.addCommand(createConfigCommand(context, setExitCode));
|
|
23237
23793
|
program2.addCommand(createDoctorCommand(context, setExitCode));
|