@eudiplo/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -0
- package/dist/args.d.ts +4 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +35 -0
- package/dist/args.js.map +1 -0
- package/dist/compose-template.d.ts +5 -0
- package/dist/compose-template.d.ts.map +1 -0
- package/dist/compose-template.js +19 -0
- package/dist/compose-template.js.map +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +113 -0
- package/dist/config.js.map +1 -0
- package/dist/doctor.d.ts +11 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +116 -0
- package/dist/doctor.js.map +1 -0
- package/dist/drivers.d.ts +5 -0
- package/dist/drivers.d.ts.map +1 -0
- package/dist/drivers.js +110 -0
- package/dist/drivers.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime.d.ts +3 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +181 -0
- package/dist/runtime.js.map +1 -0
- package/dist/types.d.ts +40 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +55 -0
- package/templates/docker-compose.yml +171 -0
package/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# EUDIPLO CLI
|
|
2
|
+
|
|
3
|
+
The EUDIPLO CLI provides deployment-neutral commands for inspecting an EUDIPLO
|
|
4
|
+
instance and deployment-driver commands for local Docker Compose demos.
|
|
5
|
+
|
|
6
|
+
## Quick Start
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npx @eudiplo/cli demo
|
|
10
|
+
npx @eudiplo/cli instance add production --url https://eudiplo.example.com
|
|
11
|
+
npx @eudiplo/cli doctor --instance production
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`demo` creates a local `.eudiplo.env`, copies the bundled EUDIPLO Docker Compose
|
|
15
|
+
template, and starts the `compose` driver. The Compose template is bundled with
|
|
16
|
+
the npm package and checked during build against the canonical file in
|
|
17
|
+
`deployment/docker-compose/docker-compose.yml`.
|
|
18
|
+
|
|
19
|
+
## Package and Binary Names
|
|
20
|
+
|
|
21
|
+
The npm package is scoped as `@eudiplo/cli`, while the installed binary is
|
|
22
|
+
`eudiplo`. That means one-off usage should use `npx @eudiplo/cli`; after global
|
|
23
|
+
or project installation, run `eudiplo` directly.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pnpm add -D @eudiplo/cli
|
|
27
|
+
pnpm eudiplo status
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Commands
|
|
31
|
+
|
|
32
|
+
Deployment-neutral commands work with any registered EUDIPLO instance and do not
|
|
33
|
+
require Docker:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
eudiplo instance add production --url https://eudiplo.example.com
|
|
37
|
+
eudiplo doctor --instance production
|
|
38
|
+
eudiplo status --instance production
|
|
39
|
+
eudiplo config validate
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Compose driver commands require a `compose` instance:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
eudiplo init --target compose
|
|
46
|
+
eudiplo up
|
|
47
|
+
eudiplo down
|
|
48
|
+
eudiplo logs
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
If a driver-specific command is used with an unsupported target, the CLI exits
|
|
52
|
+
with a clear error, for example:
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
logs is not available for externally managed deployments
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Configuration
|
|
59
|
+
|
|
60
|
+
The CLI stores instance metadata outside the source tree. By default it writes to
|
|
61
|
+
`~/.eudiplo/config.json`. Override the location for tests or isolated runs with:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
EUDIPLO_CLI_HOME=/tmp/eudiplo-cli eudiplo config validate
|
|
65
|
+
EUDIPLO_CLI_CONFIG=/tmp/eudiplo-cli/config.json eudiplo config validate
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Do not store secrets in the CLI config. Commands that need authenticated API
|
|
69
|
+
access read credentials from environment variables such as `EUDIPLO_CLIENT_ID`
|
|
70
|
+
and `EUDIPLO_CLIENT_SECRET`.
|
|
71
|
+
|
|
72
|
+
## Local Development
|
|
73
|
+
|
|
74
|
+
From the repository root:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pnpm --filter @eudiplo/cli test
|
|
78
|
+
pnpm --filter @eudiplo/cli build
|
|
79
|
+
pnpm --filter @eudiplo/cli lint
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The build runs `assets:check`, which fails if the bundled Compose template has
|
|
83
|
+
drifted from the canonical deployment Compose file.
|
package/dist/args.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.d.ts","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAgCpD;AAED,wBAAgB,cAAc,CAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EACvC,IAAI,EAAE,MAAM,GACb,MAAM,GAAG,SAAS,CAGpB"}
|
package/dist/args.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export function parseArgs(args) {
|
|
2
|
+
const flags = {};
|
|
3
|
+
const positionals = [];
|
|
4
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
5
|
+
const token = args[index];
|
|
6
|
+
if (!token.startsWith("--")) {
|
|
7
|
+
positionals.push(token);
|
|
8
|
+
continue;
|
|
9
|
+
}
|
|
10
|
+
const [rawName, rawValue] = token.slice(2).split("=", 2);
|
|
11
|
+
if (rawValue !== undefined) {
|
|
12
|
+
flags[rawName] = rawValue;
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
const next = args[index + 1];
|
|
16
|
+
if (next && !next.startsWith("--")) {
|
|
17
|
+
flags[rawName] = next;
|
|
18
|
+
index += 1;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
flags[rawName] = true;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
command: positionals[0],
|
|
26
|
+
subject: positionals[1],
|
|
27
|
+
positionals: positionals.slice(2),
|
|
28
|
+
flags,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export function readStringFlag(flags, name) {
|
|
32
|
+
const value = flags[name];
|
|
33
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=args.js.map
|
package/dist/args.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,SAAS,CAAC,IAAc;IACpC,MAAM,KAAK,GAAqC,EAAE,CAAC;IACnD,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACxB,SAAS;QACb,CAAC;QAED,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACzD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YACzB,KAAK,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC;YAC1B,SAAS;QACb,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAC7B,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACjC,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;YACtB,KAAK,IAAI,CAAC,CAAC;QACf,CAAC;aAAM,CAAC;YACJ,KAAK,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;QAC1B,CAAC;IACL,CAAC;IAED,OAAO;QACH,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;QACvB,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;QACvB,WAAW,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;QACjC,KAAK;KACR,CAAC;AACN,CAAC;AAED,MAAM,UAAU,cAAc,CAC1B,KAAuC,EACvC,IAAY;IAEZ,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7E,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const defaultComposeFileName = "eudiplo.compose.yaml";
|
|
2
|
+
export declare const defaultEnvFileName = ".eudiplo.env";
|
|
3
|
+
export declare function createDemoEnv(): string;
|
|
4
|
+
export declare function createComposeFile(): Promise<string>;
|
|
5
|
+
//# sourceMappingURL=compose-template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose-template.d.ts","sourceRoot":"","sources":["../src/compose-template.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,sBAAsB,yBAAyB,CAAC;AAC7D,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AAEjD,wBAAgB,aAAa,IAAI,MAAM,CAUtC;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAEzD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
export const defaultComposeFileName = "eudiplo.compose.yaml";
|
|
4
|
+
export const defaultEnvFileName = ".eudiplo.env";
|
|
5
|
+
export function createDemoEnv() {
|
|
6
|
+
return [
|
|
7
|
+
"EUDIPLO_ENV_FILE=.eudiplo.env",
|
|
8
|
+
"EUDIPLO_IMAGE=ghcr.io/openwallet-foundation/eudiplo-demo:main",
|
|
9
|
+
"PUBLIC_URL=http://localhost:3000",
|
|
10
|
+
`MASTER_SECRET=${randomBytes(32).toString("base64")}`,
|
|
11
|
+
"AUTH_CLIENT_ID=root",
|
|
12
|
+
"AUTH_CLIENT_SECRET=root",
|
|
13
|
+
"",
|
|
14
|
+
].join("\n");
|
|
15
|
+
}
|
|
16
|
+
export async function createComposeFile() {
|
|
17
|
+
return readFile(new URL("../templates/docker-compose.yml", import.meta.url), "utf8");
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=compose-template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose-template.js","sourceRoot":"","sources":["../src/compose-template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,MAAM,CAAC,MAAM,sBAAsB,GAAG,sBAAsB,CAAC;AAC7D,MAAM,CAAC,MAAM,kBAAkB,GAAG,cAAc,CAAC;AAEjD,MAAM,UAAU,aAAa;IACzB,OAAO;QACL,+BAA+B;QAC/B,+DAA+D;QAC/D,kCAAkC;QAChC,iBAAiB,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;QACrD,qBAAqB;QACrB,yBAAyB;QACzB,EAAE;KACL,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACnC,OAAO,QAAQ,CAAC,IAAI,GAAG,CAAC,iCAAiC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;AACzF,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CliConfig, InstanceConfig } from "./types.js";
|
|
2
|
+
export declare function resolveConfigPath(env: NodeJS.ProcessEnv): string;
|
|
3
|
+
export declare function loadConfig(path: string): Promise<CliConfig>;
|
|
4
|
+
export declare function saveConfig(path: string, config: CliConfig): Promise<void>;
|
|
5
|
+
export declare function validateConfig(value: unknown): CliConfig;
|
|
6
|
+
export declare function upsertInstance(config: CliConfig, name: string, instance: InstanceConfig): CliConfig;
|
|
7
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAI5D,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAUhE;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAUjE;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAM/E;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAkBxD;AAED,wBAAgB,cAAc,CAC1B,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,cAAc,GACzB,SAAS,CAQX"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
const emptyConfig = () => ({ instances: {} });
|
|
5
|
+
export function resolveConfigPath(env) {
|
|
6
|
+
if (env.EUDIPLO_CLI_CONFIG) {
|
|
7
|
+
return resolve(env.EUDIPLO_CLI_CONFIG);
|
|
8
|
+
}
|
|
9
|
+
const baseDir = env.EUDIPLO_CLI_HOME
|
|
10
|
+
? resolve(env.EUDIPLO_CLI_HOME)
|
|
11
|
+
: join(homedir(), ".eudiplo");
|
|
12
|
+
return join(baseDir, "config.json");
|
|
13
|
+
}
|
|
14
|
+
export async function loadConfig(path) {
|
|
15
|
+
try {
|
|
16
|
+
const contents = await readFile(path, "utf8");
|
|
17
|
+
return validateConfig(JSON.parse(contents));
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
if (isNodeError(error) && error.code === "ENOENT") {
|
|
21
|
+
return emptyConfig();
|
|
22
|
+
}
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export async function saveConfig(path, config) {
|
|
27
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
28
|
+
await writeFile(path, `${JSON.stringify(config, null, 4)}\n`, {
|
|
29
|
+
encoding: "utf8",
|
|
30
|
+
mode: 0o600,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
export function validateConfig(value) {
|
|
34
|
+
if (!isRecord(value)) {
|
|
35
|
+
throw new Error("Config must be a JSON object.");
|
|
36
|
+
}
|
|
37
|
+
if (!isRecord(value.instances)) {
|
|
38
|
+
throw new Error("Config must define an instances object.");
|
|
39
|
+
}
|
|
40
|
+
const instances = {};
|
|
41
|
+
for (const [name, instance] of Object.entries(value.instances)) {
|
|
42
|
+
instances[name] = validateInstanceConfig(name, instance);
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
defaultInstance: validateDefaultInstance(value.defaultInstance, instances),
|
|
46
|
+
instances,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export function upsertInstance(config, name, instance) {
|
|
50
|
+
return {
|
|
51
|
+
defaultInstance: config.defaultInstance ?? name,
|
|
52
|
+
instances: {
|
|
53
|
+
...config.instances,
|
|
54
|
+
[name]: instance,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function isRecord(value) {
|
|
59
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
60
|
+
}
|
|
61
|
+
function isNodeError(error) {
|
|
62
|
+
return error instanceof Error && "code" in error;
|
|
63
|
+
}
|
|
64
|
+
function validateDefaultInstance(value, instances) {
|
|
65
|
+
if (typeof value !== "string") {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
if (!Object.hasOwn(instances, value)) {
|
|
69
|
+
throw new Error(`Default instance ${value} is not defined in instances.`);
|
|
70
|
+
}
|
|
71
|
+
return value;
|
|
72
|
+
}
|
|
73
|
+
function validateInstanceConfig(name, value) {
|
|
74
|
+
if (!isRecord(value)) {
|
|
75
|
+
throw new Error(`Instance ${name} must be an object.`);
|
|
76
|
+
}
|
|
77
|
+
if (value.target !== "compose" && value.target !== "external") {
|
|
78
|
+
throw new Error(`Instance ${name} has unsupported target ${String(value.target)}.`);
|
|
79
|
+
}
|
|
80
|
+
if (typeof value.url !== "string" || value.url.length === 0) {
|
|
81
|
+
throw new Error(`Instance ${name} must define a url.`);
|
|
82
|
+
}
|
|
83
|
+
validateHttpUrl(value.url, `Instance ${name} url`);
|
|
84
|
+
validateOptionalHttpUrl(value.clientUrl, `Instance ${name} clientUrl`);
|
|
85
|
+
return {
|
|
86
|
+
target: value.target,
|
|
87
|
+
url: value.url,
|
|
88
|
+
clientUrl: optionalString(value.clientUrl),
|
|
89
|
+
composeFile: optionalString(value.composeFile),
|
|
90
|
+
envFile: optionalString(value.envFile),
|
|
91
|
+
projectName: optionalString(value.projectName),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function optionalString(value) {
|
|
95
|
+
return typeof value === "string" ? value : undefined;
|
|
96
|
+
}
|
|
97
|
+
function validateOptionalHttpUrl(value, label) {
|
|
98
|
+
if (typeof value === "string") {
|
|
99
|
+
validateHttpUrl(value, label);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function validateHttpUrl(value, label) {
|
|
103
|
+
try {
|
|
104
|
+
const url = new URL(value);
|
|
105
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
106
|
+
throw new Error("Unsupported URL protocol.");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
throw new Error(`${label} must be an absolute HTTP(S) URL.`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/doctor.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CommandContext, InstanceConfig } from "./types.js";
|
|
2
|
+
export type CheckStatus = "pass" | "warn" | "fail";
|
|
3
|
+
export interface DoctorCheck {
|
|
4
|
+
name: string;
|
|
5
|
+
status: CheckStatus;
|
|
6
|
+
message: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function runDoctor(instance: InstanceConfig, context: CommandContext, driverDiagnostics: string[]): Promise<DoctorCheck[]>;
|
|
9
|
+
export declare function hasFailedChecks(checks: DoctorCheck[]): boolean;
|
|
10
|
+
export declare function formatChecks(checks: DoctorCheck[]): string;
|
|
11
|
+
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEnD,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,SAAS,CAC3B,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,cAAc,EACvB,iBAAiB,EAAE,MAAM,EAAE,GAC5B,OAAO,CAAC,WAAW,EAAE,CAAC,CAuDxB;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAE9D;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAI1D"}
|
package/dist/doctor.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
export async function runDoctor(instance, context, driverDiagnostics) {
|
|
2
|
+
const checks = [];
|
|
3
|
+
const baseUrl = parseUrl(instance.url);
|
|
4
|
+
if (!baseUrl) {
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
name: "public URL",
|
|
8
|
+
status: "fail",
|
|
9
|
+
message: `${instance.url} is not a valid absolute URL`,
|
|
10
|
+
},
|
|
11
|
+
];
|
|
12
|
+
}
|
|
13
|
+
checks.push({
|
|
14
|
+
name: "public URL",
|
|
15
|
+
status: baseUrl.protocol === "https:" ? "pass" : "warn",
|
|
16
|
+
message: baseUrl.protocol === "https:"
|
|
17
|
+
? `${baseUrl.href} uses HTTPS`
|
|
18
|
+
: `${baseUrl.href} does not use HTTPS`,
|
|
19
|
+
});
|
|
20
|
+
checks.push(await checkEndpoint("API reachability", baseUrl, "/api/docs", context));
|
|
21
|
+
checks.push(await checkEndpoint("health endpoint", baseUrl, "/health", context));
|
|
22
|
+
checks.push(checkAuthentication(context));
|
|
23
|
+
if (instance.clientUrl) {
|
|
24
|
+
const clientUrl = parseUrl(instance.clientUrl);
|
|
25
|
+
checks.push(clientUrl
|
|
26
|
+
? await checkEndpoint("client connectivity", clientUrl, "/", context)
|
|
27
|
+
: {
|
|
28
|
+
name: "client connectivity",
|
|
29
|
+
status: "fail",
|
|
30
|
+
message: `${instance.clientUrl} is not a valid absolute URL`,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
checks.push({
|
|
35
|
+
name: "client connectivity",
|
|
36
|
+
status: "warn",
|
|
37
|
+
message: "No client URL configured for this instance.",
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
for (const diagnostic of driverDiagnostics) {
|
|
41
|
+
checks.push({
|
|
42
|
+
name: "driver diagnostics",
|
|
43
|
+
status: "warn",
|
|
44
|
+
message: diagnostic,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return checks;
|
|
48
|
+
}
|
|
49
|
+
export function hasFailedChecks(checks) {
|
|
50
|
+
return checks.some((check) => check.status === "fail");
|
|
51
|
+
}
|
|
52
|
+
export function formatChecks(checks) {
|
|
53
|
+
return checks
|
|
54
|
+
.map((check) => `${formatStatus(check.status)} ${check.name}: ${check.message}`)
|
|
55
|
+
.join("\n");
|
|
56
|
+
}
|
|
57
|
+
async function checkEndpoint(name, baseUrl, path, context) {
|
|
58
|
+
const url = new URL(path, baseUrl);
|
|
59
|
+
try {
|
|
60
|
+
const response = await context.fetch(url, { method: "GET" });
|
|
61
|
+
if (response.ok) {
|
|
62
|
+
return {
|
|
63
|
+
name,
|
|
64
|
+
status: "pass",
|
|
65
|
+
message: `${url.href} returned HTTP ${response.status}`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
name,
|
|
70
|
+
status: "fail",
|
|
71
|
+
message: `${url.href} returned HTTP ${response.status}`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
return {
|
|
76
|
+
name,
|
|
77
|
+
status: "fail",
|
|
78
|
+
message: `${url.href} could not be reached: ${String(error)}`,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function checkAuthentication(context) {
|
|
83
|
+
const hasClientId = Boolean(context.env.EUDIPLO_CLIENT_ID);
|
|
84
|
+
const hasClientSecret = Boolean(context.env.EUDIPLO_CLIENT_SECRET);
|
|
85
|
+
if (hasClientId && hasClientSecret) {
|
|
86
|
+
return {
|
|
87
|
+
name: "authentication configuration",
|
|
88
|
+
status: "pass",
|
|
89
|
+
message: "Client credentials are available in environment variables.",
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
name: "authentication configuration",
|
|
94
|
+
status: "warn",
|
|
95
|
+
message: "Set EUDIPLO_CLIENT_ID and EUDIPLO_CLIENT_SECRET when commands need authenticated API access.",
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function parseUrl(value) {
|
|
99
|
+
try {
|
|
100
|
+
const url = new URL(value);
|
|
101
|
+
return url.protocol === "http:" || url.protocol === "https:" ? url : undefined;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function formatStatus(status) {
|
|
108
|
+
if (status === "pass") {
|
|
109
|
+
return "PASS";
|
|
110
|
+
}
|
|
111
|
+
if (status === "warn") {
|
|
112
|
+
return "WARN";
|
|
113
|
+
}
|
|
114
|
+
return "FAIL";
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { DeploymentDriver, DeploymentTarget, InstanceConfig } from "./types.js";
|
|
2
|
+
export declare const drivers: Record<DeploymentTarget, DeploymentDriver>;
|
|
3
|
+
export declare function ensureComposeProject(cwd: string): Promise<InstanceConfig>;
|
|
4
|
+
export declare function unsupportedCommand(command: string, target: DeploymentTarget): string;
|
|
5
|
+
//# sourceMappingURL=drivers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drivers.d.ts","sourceRoot":"","sources":["../src/drivers.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAER,gBAAgB,EAChB,gBAAgB,EAEhB,cAAc,EACjB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,gBAAgB,EAAE,gBAAgB,CAiC9D,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAmB/E;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAKpF"}
|
package/dist/drivers.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { access, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import { createComposeFile, createDemoEnv, defaultComposeFileName, defaultEnvFileName, } from "./compose-template.js";
|
|
5
|
+
export const drivers = {
|
|
6
|
+
compose: {
|
|
7
|
+
target: "compose",
|
|
8
|
+
async diagnostics(instance, context) {
|
|
9
|
+
const messages = [];
|
|
10
|
+
if (!(await commandExists("docker", context))) {
|
|
11
|
+
messages.push("Docker is not available on PATH.");
|
|
12
|
+
}
|
|
13
|
+
if (instance.composeFile) {
|
|
14
|
+
try {
|
|
15
|
+
await access(resolve(context.cwd, instance.composeFile));
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
messages.push(`Compose file not found: ${instance.composeFile}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return messages;
|
|
22
|
+
},
|
|
23
|
+
up(options) {
|
|
24
|
+
return runCompose(["up", "-d", ...options.args], options);
|
|
25
|
+
},
|
|
26
|
+
down(options) {
|
|
27
|
+
return runCompose(["down", ...options.args], options);
|
|
28
|
+
},
|
|
29
|
+
logs(options) {
|
|
30
|
+
return runCompose(["logs", "-f", ...options.args], options);
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
external: {
|
|
34
|
+
target: "external",
|
|
35
|
+
async diagnostics() {
|
|
36
|
+
return [];
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
export async function ensureComposeProject(cwd) {
|
|
41
|
+
const composePath = join(cwd, defaultComposeFileName);
|
|
42
|
+
const envPath = join(cwd, defaultEnvFileName);
|
|
43
|
+
if (!(await exists(composePath))) {
|
|
44
|
+
await writeFile(composePath, await createComposeFile(), "utf8");
|
|
45
|
+
}
|
|
46
|
+
if (!(await exists(envPath))) {
|
|
47
|
+
await writeFile(envPath, createDemoEnv(), { encoding: "utf8", mode: 0o600 });
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
target: "compose",
|
|
51
|
+
url: "http://localhost:3000",
|
|
52
|
+
clientUrl: "http://localhost:4200",
|
|
53
|
+
composeFile: defaultComposeFileName,
|
|
54
|
+
envFile: defaultEnvFileName,
|
|
55
|
+
projectName: "eudiplo-demo",
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function unsupportedCommand(command, target) {
|
|
59
|
+
if (target === "external") {
|
|
60
|
+
return `${command} is not available for externally managed deployments`;
|
|
61
|
+
}
|
|
62
|
+
return `${command} is not available for ${target} deployments`;
|
|
63
|
+
}
|
|
64
|
+
async function runCompose(args, { instance, context }) {
|
|
65
|
+
const composeArgs = ["compose"];
|
|
66
|
+
if (instance.envFile) {
|
|
67
|
+
composeArgs.push("--env-file", resolve(context.cwd, instance.envFile));
|
|
68
|
+
}
|
|
69
|
+
if (instance.composeFile) {
|
|
70
|
+
composeArgs.push("-f", resolve(context.cwd, instance.composeFile));
|
|
71
|
+
}
|
|
72
|
+
if (instance.projectName) {
|
|
73
|
+
composeArgs.push("--project-name", instance.projectName);
|
|
74
|
+
}
|
|
75
|
+
composeArgs.push(...args);
|
|
76
|
+
return new Promise((resolveProcess) => {
|
|
77
|
+
const child = spawn("docker", composeArgs, {
|
|
78
|
+
cwd: context.cwd,
|
|
79
|
+
env: context.env,
|
|
80
|
+
stdio: "inherit",
|
|
81
|
+
});
|
|
82
|
+
child.on("error", (error) => {
|
|
83
|
+
context.stderr.write(`${error.message}\n`);
|
|
84
|
+
resolveProcess(1);
|
|
85
|
+
});
|
|
86
|
+
child.on("close", (code) => resolveProcess(code ?? 1));
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
async function commandExists(command, context) {
|
|
90
|
+
const path = context.env.PATH ?? "";
|
|
91
|
+
const executableNames = process.platform === "win32" ? [command, `${command}.exe`] : [command];
|
|
92
|
+
for (const directory of path.split(process.platform === "win32" ? ";" : ":")) {
|
|
93
|
+
for (const executableName of executableNames) {
|
|
94
|
+
if (await exists(join(directory, executableName))) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
async function exists(path) {
|
|
102
|
+
try {
|
|
103
|
+
await access(path);
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=drivers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drivers.js","sourceRoot":"","sources":["../src/drivers.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACrD,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAa,cAAc,EAAgC,MAAM,YAAY,CAAC;AAE1F,wBAAsB,MAAM,CACxB,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,cAAiC,GAC3C,OAAO,CAAC,MAAM,CAAC,CAajB"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { parseArgs, readStringFlag } from "./args.js";
|
|
2
|
+
import { loadConfig, resolveConfigPath, saveConfig, upsertInstance } from "./config.js";
|
|
3
|
+
import { drivers, ensureComposeProject, unsupportedCommand } from "./drivers.js";
|
|
4
|
+
import { formatChecks, hasFailedChecks, runDoctor } from "./doctor.js";
|
|
5
|
+
export async function runCli(args, context = defaultContext()) {
|
|
6
|
+
const parsed = parseArgs(args);
|
|
7
|
+
if (!parsed.command || parsed.flags.help === true || parsed.command === "help") {
|
|
8
|
+
context.stdout.write(`${helpText()}\n`);
|
|
9
|
+
return 0;
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
return await dispatch(parsed, context);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
context.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
16
|
+
return 1;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function defaultContext() {
|
|
20
|
+
return {
|
|
21
|
+
cwd: process.cwd(),
|
|
22
|
+
env: process.env,
|
|
23
|
+
stdout: process.stdout,
|
|
24
|
+
stderr: process.stderr,
|
|
25
|
+
fetch,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
async function dispatch(parsed, context) {
|
|
29
|
+
const configPath = resolveConfigPath(context.env);
|
|
30
|
+
const config = await loadConfig(configPath);
|
|
31
|
+
switch (parsed.command) {
|
|
32
|
+
case "init":
|
|
33
|
+
return init(configPath, config, parsed, context);
|
|
34
|
+
case "demo":
|
|
35
|
+
return demo(configPath, config, context);
|
|
36
|
+
case "instance":
|
|
37
|
+
return instance(configPath, config, parsed, context);
|
|
38
|
+
case "config":
|
|
39
|
+
return validateConfigCommand(configPath, parsed, context);
|
|
40
|
+
case "doctor":
|
|
41
|
+
return doctor(config, parsed, context);
|
|
42
|
+
case "status":
|
|
43
|
+
return status(config, parsed, context);
|
|
44
|
+
case "up":
|
|
45
|
+
case "down":
|
|
46
|
+
case "logs":
|
|
47
|
+
return driverCommand(config, parsed.command, parsed, context);
|
|
48
|
+
default:
|
|
49
|
+
throw new Error(`Unknown command: ${parsed.command}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function init(configPath, config, parsed, context) {
|
|
53
|
+
const target = parseTarget(readStringFlag(parsed.flags, "target") ?? "compose");
|
|
54
|
+
const name = readStringFlag(parsed.flags, "instance") ?? "local";
|
|
55
|
+
const url = readStringFlag(parsed.flags, "url");
|
|
56
|
+
if (target === "compose") {
|
|
57
|
+
const instance = await ensureComposeProject(context.cwd);
|
|
58
|
+
const nextConfig = upsertInstance(config, name, {
|
|
59
|
+
...instance,
|
|
60
|
+
url: url ?? instance.url,
|
|
61
|
+
});
|
|
62
|
+
await saveConfig(configPath, nextConfig);
|
|
63
|
+
context.stdout.write(`Initialized compose instance ${name}. Run npx @eudiplo/cli up to start it.\n`);
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
66
|
+
if (!url) {
|
|
67
|
+
throw new Error("External instances require --url.");
|
|
68
|
+
}
|
|
69
|
+
const nextConfig = upsertInstance(config, name, { target, url });
|
|
70
|
+
await saveConfig(configPath, nextConfig);
|
|
71
|
+
context.stdout.write(`Initialized external instance ${name}.\n`);
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
74
|
+
async function demo(configPath, config, context) {
|
|
75
|
+
const instance = await ensureComposeProject(context.cwd);
|
|
76
|
+
const nextConfig = upsertInstance(config, "local", instance);
|
|
77
|
+
await saveConfig(configPath, nextConfig);
|
|
78
|
+
context.stdout.write("Starting EUDIPLO demo with Docker Compose...\n");
|
|
79
|
+
return drivers.compose.up?.({
|
|
80
|
+
instanceName: "local",
|
|
81
|
+
instance,
|
|
82
|
+
args: [],
|
|
83
|
+
context,
|
|
84
|
+
}) ?? 1;
|
|
85
|
+
}
|
|
86
|
+
async function instance(configPath, config, parsed, context) {
|
|
87
|
+
if (parsed.subject !== "add") {
|
|
88
|
+
throw new Error("Usage: eudiplo instance add <name> --url <url> [--target external]");
|
|
89
|
+
}
|
|
90
|
+
const name = parsed.positionals[0];
|
|
91
|
+
if (!name) {
|
|
92
|
+
throw new Error("Instance name is required.");
|
|
93
|
+
}
|
|
94
|
+
const url = readStringFlag(parsed.flags, "url");
|
|
95
|
+
if (!url) {
|
|
96
|
+
throw new Error("--url is required.");
|
|
97
|
+
}
|
|
98
|
+
const target = parseTarget(readStringFlag(parsed.flags, "target") ?? "external");
|
|
99
|
+
const clientUrl = readStringFlag(parsed.flags, "client-url");
|
|
100
|
+
const nextConfig = upsertInstance(config, name, { target, url, clientUrl });
|
|
101
|
+
await saveConfig(configPath, nextConfig);
|
|
102
|
+
context.stdout.write(`Added ${target} instance ${name}.\n`);
|
|
103
|
+
return 0;
|
|
104
|
+
}
|
|
105
|
+
async function validateConfigCommand(configPath, parsed, context) {
|
|
106
|
+
if (parsed.subject !== "validate") {
|
|
107
|
+
throw new Error("Usage: eudiplo config validate");
|
|
108
|
+
}
|
|
109
|
+
const config = await loadConfig(configPath);
|
|
110
|
+
const instanceNames = Object.keys(config.instances);
|
|
111
|
+
context.stdout.write(`Config is valid: ${configPath}\n`);
|
|
112
|
+
context.stdout.write(`Instances: ${instanceNames.length}\n`);
|
|
113
|
+
if (config.defaultInstance) {
|
|
114
|
+
context.stdout.write(`Default instance: ${config.defaultInstance}\n`);
|
|
115
|
+
}
|
|
116
|
+
for (const name of instanceNames) {
|
|
117
|
+
const instance = config.instances[name];
|
|
118
|
+
context.stdout.write(`- ${name}: ${instance.target} ${instance.url}\n`);
|
|
119
|
+
}
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
async function doctor(config, parsed, context) {
|
|
123
|
+
const [instanceName, instance] = resolveInstance(config, parsed);
|
|
124
|
+
const driver = drivers[instance.target];
|
|
125
|
+
const checks = await runDoctor(instance, context, await driver.diagnostics(instance, context));
|
|
126
|
+
context.stdout.write(`Doctor for ${instanceName} (${instance.target})\n`);
|
|
127
|
+
context.stdout.write(`${formatChecks(checks)}\n`);
|
|
128
|
+
return hasFailedChecks(checks) ? 1 : 0;
|
|
129
|
+
}
|
|
130
|
+
async function status(config, parsed, context) {
|
|
131
|
+
const [instanceName, instance] = resolveInstance(config, parsed);
|
|
132
|
+
const checks = await runDoctor(instance, context, []);
|
|
133
|
+
const health = checks.find((check) => check.name === "health endpoint");
|
|
134
|
+
context.stdout.write(`${instanceName} (${instance.target}) ${instance.url}\n`);
|
|
135
|
+
if (health) {
|
|
136
|
+
context.stdout.write(`${health.status.toUpperCase()} ${health.message}\n`);
|
|
137
|
+
}
|
|
138
|
+
return health?.status === "fail" ? 1 : 0;
|
|
139
|
+
}
|
|
140
|
+
async function driverCommand(config, command, parsed, context) {
|
|
141
|
+
const [instanceName, instance] = resolveInstance(config, parsed);
|
|
142
|
+
const driver = drivers[instance.target];
|
|
143
|
+
const handler = driver[command];
|
|
144
|
+
if (!handler) {
|
|
145
|
+
throw new Error(unsupportedCommand(command, instance.target));
|
|
146
|
+
}
|
|
147
|
+
return handler({ instanceName, instance, args: parsed.positionals, context });
|
|
148
|
+
}
|
|
149
|
+
function resolveInstance(config, parsed) {
|
|
150
|
+
const name = readStringFlag(parsed.flags, "instance") ?? config.defaultInstance;
|
|
151
|
+
if (!name) {
|
|
152
|
+
throw new Error("No instance selected. Use --instance or add an instance first.");
|
|
153
|
+
}
|
|
154
|
+
const instance = config.instances[name];
|
|
155
|
+
if (!instance) {
|
|
156
|
+
throw new Error(`Unknown instance: ${name}`);
|
|
157
|
+
}
|
|
158
|
+
return [name, instance];
|
|
159
|
+
}
|
|
160
|
+
function parseTarget(value) {
|
|
161
|
+
if (value === "compose" || value === "external") {
|
|
162
|
+
return value;
|
|
163
|
+
}
|
|
164
|
+
throw new Error(`Unsupported target: ${value}`);
|
|
165
|
+
}
|
|
166
|
+
function helpText() {
|
|
167
|
+
return `EUDIPLO CLI
|
|
168
|
+
|
|
169
|
+
Usage:
|
|
170
|
+
eudiplo demo
|
|
171
|
+
eudiplo init --target compose [--instance local]
|
|
172
|
+
eudiplo up|down|logs [--instance local]
|
|
173
|
+
eudiplo instance add <name> --url <url> [--target external] [--client-url <url>]
|
|
174
|
+
eudiplo doctor [--instance name]
|
|
175
|
+
eudiplo status [--instance name]
|
|
176
|
+
eudiplo config validate
|
|
177
|
+
|
|
178
|
+
One-off npm usage:
|
|
179
|
+
npx @eudiplo/cli demo`;
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export type DeploymentTarget = "compose" | "external";
|
|
2
|
+
export interface InstanceConfig {
|
|
3
|
+
target: DeploymentTarget;
|
|
4
|
+
url: string;
|
|
5
|
+
clientUrl?: string;
|
|
6
|
+
composeFile?: string;
|
|
7
|
+
envFile?: string;
|
|
8
|
+
projectName?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface CliConfig {
|
|
11
|
+
defaultInstance?: string;
|
|
12
|
+
instances: Record<string, InstanceConfig>;
|
|
13
|
+
}
|
|
14
|
+
export interface CommandContext {
|
|
15
|
+
cwd: string;
|
|
16
|
+
env: NodeJS.ProcessEnv;
|
|
17
|
+
stdout: Pick<NodeJS.WriteStream, "write">;
|
|
18
|
+
stderr: Pick<NodeJS.WriteStream, "write">;
|
|
19
|
+
fetch: typeof fetch;
|
|
20
|
+
}
|
|
21
|
+
export interface DriverCommandOptions {
|
|
22
|
+
instanceName: string;
|
|
23
|
+
instance: InstanceConfig;
|
|
24
|
+
args: string[];
|
|
25
|
+
context: CommandContext;
|
|
26
|
+
}
|
|
27
|
+
export interface DeploymentDriver {
|
|
28
|
+
target: DeploymentTarget;
|
|
29
|
+
diagnostics(instance: InstanceConfig, context: CommandContext): Promise<string[]>;
|
|
30
|
+
up?(options: DriverCommandOptions): Promise<number>;
|
|
31
|
+
down?(options: DriverCommandOptions): Promise<number>;
|
|
32
|
+
logs?(options: DriverCommandOptions): Promise<number>;
|
|
33
|
+
}
|
|
34
|
+
export interface ParsedArgs {
|
|
35
|
+
command?: string;
|
|
36
|
+
subject?: string;
|
|
37
|
+
positionals: string[];
|
|
38
|
+
flags: Record<string, string | boolean>;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,UAAU,CAAC;AAEtD,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,gBAAgB,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,SAAS;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,cAAc;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC1C,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC1C,KAAK,EAAE,OAAO,KAAK,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,cAAc,CAAC;IACzB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,cAAc,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,gBAAgB,CAAC;IACzB,WAAW,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAClF,EAAE,CAAC,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,CAAC,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACtD,IAAI,CAAC,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,UAAU;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;CAC3C"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@eudiplo/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Deployment-aware command line tools for EUDIPLO",
|
|
5
|
+
"private": false,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"eudiplo": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"templates",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"assets:check": "node ../../scripts/check-cli-assets.js",
|
|
17
|
+
"build": "pnpm assets:check && tsc -p tsconfig.json",
|
|
18
|
+
"dev": "tsx src/index.ts",
|
|
19
|
+
"test": "vitest run",
|
|
20
|
+
"lint": "biome lint .",
|
|
21
|
+
"prepublishOnly": "pnpm build"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"eudiplo",
|
|
25
|
+
"cli",
|
|
26
|
+
"eudi",
|
|
27
|
+
"wallet",
|
|
28
|
+
"oid4vci",
|
|
29
|
+
"oid4vp"
|
|
30
|
+
],
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/openwallet-foundation/eudiplo.git",
|
|
34
|
+
"directory": "apps/cli"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/openwallet-foundation/eudiplo/tree/main/apps/cli#readme",
|
|
37
|
+
"bugs": {
|
|
38
|
+
"url": "https://github.com/openwallet-foundation/eudiplo/issues"
|
|
39
|
+
},
|
|
40
|
+
"author": "OpenWallet Foundation",
|
|
41
|
+
"license": "Apache-2.0",
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=22.0.0"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@biomejs/biome": "2.5.3",
|
|
50
|
+
"@types/node": "^26.0.1",
|
|
51
|
+
"tsx": "^4.22.4",
|
|
52
|
+
"typescript": "^6.0.3",
|
|
53
|
+
"vitest": "4.1.10"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# EUDIPLO Docker Compose - Multi-Profile Deployment
|
|
2
|
+
#
|
|
3
|
+
# Usage:
|
|
4
|
+
# docker compose up # Minimal: just EUDIPLO (SQLite, local storage)
|
|
5
|
+
# docker compose --profile standard up # Standard: + Postgres + MinIO
|
|
6
|
+
# docker compose --profile full up # Full: + Postgres + MinIO + Vault
|
|
7
|
+
#
|
|
8
|
+
# For more information, see the documentation:
|
|
9
|
+
# https://openwallet-foundation.github.io/eudiplo/docs/latest/deployment/docker-compose/
|
|
10
|
+
|
|
11
|
+
services:
|
|
12
|
+
# =============================================================================
|
|
13
|
+
# CORE SERVICES (always run)
|
|
14
|
+
# =============================================================================
|
|
15
|
+
|
|
16
|
+
eudiplo:
|
|
17
|
+
image: ${EUDIPLO_IMAGE:-ghcr.io/openwallet-foundation/eudiplo:latest}
|
|
18
|
+
restart: always
|
|
19
|
+
env_file:
|
|
20
|
+
- ${EUDIPLO_ENV_FILE:-.env}
|
|
21
|
+
ports:
|
|
22
|
+
- '3000:3000'
|
|
23
|
+
volumes:
|
|
24
|
+
- ${EUDIPLO_CONFIG_MOUNT:-eudiplo-config:/app/config}
|
|
25
|
+
- eudiplo-uploads:/app/uploads
|
|
26
|
+
depends_on:
|
|
27
|
+
postgres:
|
|
28
|
+
condition: service_healthy
|
|
29
|
+
required: false
|
|
30
|
+
minio:
|
|
31
|
+
condition: service_healthy
|
|
32
|
+
required: false
|
|
33
|
+
healthcheck:
|
|
34
|
+
test: ['CMD', 'curl', '-f', 'http://localhost:3000/health']
|
|
35
|
+
interval: 30s
|
|
36
|
+
timeout: 10s
|
|
37
|
+
retries: 3
|
|
38
|
+
start_period: 40s
|
|
39
|
+
networks:
|
|
40
|
+
- eudiplo-network
|
|
41
|
+
|
|
42
|
+
eudiplo-client:
|
|
43
|
+
image: ghcr.io/openwallet-foundation/eudiplo-client:latest
|
|
44
|
+
restart: always
|
|
45
|
+
ports:
|
|
46
|
+
- '4200:8080'
|
|
47
|
+
depends_on:
|
|
48
|
+
eudiplo:
|
|
49
|
+
condition: service_healthy
|
|
50
|
+
environment:
|
|
51
|
+
- API_BASE_URL=http://eudiplo:3000
|
|
52
|
+
# Uncomment to serve the client from a subpath behind a reverse proxy:
|
|
53
|
+
# - CLIENT_BASE_HREF=/eudiplo-client/
|
|
54
|
+
healthcheck:
|
|
55
|
+
test: ['CMD', 'wget', '-qO', '/dev/null', 'http://localhost:8080']
|
|
56
|
+
interval: 30s
|
|
57
|
+
timeout: 10s
|
|
58
|
+
retries: 3
|
|
59
|
+
start_period: 10s
|
|
60
|
+
networks:
|
|
61
|
+
- eudiplo-network
|
|
62
|
+
|
|
63
|
+
# =============================================================================
|
|
64
|
+
# STANDARD PROFILE: PostgreSQL + MinIO
|
|
65
|
+
# =============================================================================
|
|
66
|
+
|
|
67
|
+
postgres:
|
|
68
|
+
image: postgres:16
|
|
69
|
+
restart: always
|
|
70
|
+
profiles: ['standard', 'full']
|
|
71
|
+
environment:
|
|
72
|
+
POSTGRES_USER: ${DB_USERNAME:-eudiplo}
|
|
73
|
+
POSTGRES_PASSWORD: ${DB_PASSWORD:-changeme}
|
|
74
|
+
POSTGRES_DB: ${DB_DATABASE:-eudiplo}
|
|
75
|
+
volumes:
|
|
76
|
+
- postgres-data:/var/lib/postgresql/data
|
|
77
|
+
healthcheck:
|
|
78
|
+
test:
|
|
79
|
+
[
|
|
80
|
+
'CMD-SHELL',
|
|
81
|
+
'pg_isready -U ${DB_USERNAME:-eudiplo} -d ${DB_DATABASE:-eudiplo}',
|
|
82
|
+
]
|
|
83
|
+
interval: 10s
|
|
84
|
+
timeout: 5s
|
|
85
|
+
retries: 5
|
|
86
|
+
networks:
|
|
87
|
+
- eudiplo-network
|
|
88
|
+
|
|
89
|
+
minio:
|
|
90
|
+
image: quay.io/minio/minio:latest
|
|
91
|
+
restart: always
|
|
92
|
+
profiles: ['standard', 'full']
|
|
93
|
+
ports:
|
|
94
|
+
- '9000:9000'
|
|
95
|
+
- '9001:9001'
|
|
96
|
+
environment:
|
|
97
|
+
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}
|
|
98
|
+
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin}
|
|
99
|
+
volumes:
|
|
100
|
+
- minio-data:/data
|
|
101
|
+
command: server /data --console-address ":9001"
|
|
102
|
+
healthcheck:
|
|
103
|
+
test: ['CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live']
|
|
104
|
+
interval: 30s
|
|
105
|
+
timeout: 10s
|
|
106
|
+
retries: 3
|
|
107
|
+
start_period: 10s
|
|
108
|
+
networks:
|
|
109
|
+
- eudiplo-network
|
|
110
|
+
|
|
111
|
+
# MinIO bucket initialization job
|
|
112
|
+
minio-init:
|
|
113
|
+
image: quay.io/minio/mc:latest
|
|
114
|
+
profiles: ['standard', 'full']
|
|
115
|
+
depends_on:
|
|
116
|
+
minio:
|
|
117
|
+
condition: service_healthy
|
|
118
|
+
environment:
|
|
119
|
+
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}
|
|
120
|
+
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin}
|
|
121
|
+
MINIO_BUCKET: ${S3_BUCKET:-uploads}
|
|
122
|
+
entrypoint: >
|
|
123
|
+
/bin/sh -c "
|
|
124
|
+
mc alias set local http://minio:9000 $$MINIO_ROOT_USER $$MINIO_ROOT_PASSWORD;
|
|
125
|
+
mc mb -p local/$$MINIO_BUCKET || true;
|
|
126
|
+
mc anonymous set download local/$$MINIO_BUCKET || true;
|
|
127
|
+
echo 'Bucket created successfully';
|
|
128
|
+
"
|
|
129
|
+
networks:
|
|
130
|
+
- eudiplo-network
|
|
131
|
+
|
|
132
|
+
# =============================================================================
|
|
133
|
+
# FULL PROFILE: + HashiCorp Vault
|
|
134
|
+
# =============================================================================
|
|
135
|
+
|
|
136
|
+
vault:
|
|
137
|
+
image: hashicorp/vault:latest
|
|
138
|
+
restart: always
|
|
139
|
+
profiles: ['full']
|
|
140
|
+
ports:
|
|
141
|
+
- '8200:8200'
|
|
142
|
+
environment:
|
|
143
|
+
VAULT_DEV_ROOT_TOKEN_ID: ${VAULT_TOKEN:-root}
|
|
144
|
+
VAULT_DEV_LISTEN_ADDRESS: 0.0.0.0:8200
|
|
145
|
+
VAULT_API_ADDR: http://0.0.0.0:8200
|
|
146
|
+
cap_add:
|
|
147
|
+
- IPC_LOCK
|
|
148
|
+
volumes:
|
|
149
|
+
- vault-data:/vault/data
|
|
150
|
+
- vault-logs:/vault/logs
|
|
151
|
+
command: vault server -dev -dev-listen-address=0.0.0.0:8200
|
|
152
|
+
networks:
|
|
153
|
+
- eudiplo-network
|
|
154
|
+
|
|
155
|
+
networks:
|
|
156
|
+
eudiplo-network:
|
|
157
|
+
driver: bridge
|
|
158
|
+
|
|
159
|
+
volumes:
|
|
160
|
+
eudiplo-config:
|
|
161
|
+
driver: local
|
|
162
|
+
eudiplo-uploads:
|
|
163
|
+
driver: local
|
|
164
|
+
postgres-data:
|
|
165
|
+
driver: local
|
|
166
|
+
minio-data:
|
|
167
|
+
driver: local
|
|
168
|
+
vault-data:
|
|
169
|
+
driver: local
|
|
170
|
+
vault-logs:
|
|
171
|
+
driver: local
|