wattetheria 0.1.0 → 0.1.2
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/.env.release.example +5 -5
- package/lib/cli.js +291 -30
- package/package.json +2 -4
package/.env.release.example
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# Coordinated release image set
|
|
2
|
-
WATTETHERIA_KERNEL_IMAGE=ghcr.io/wattetheria/wattetheria-kernel:
|
|
3
|
-
WATTETHERIA_OBSERVATORY_IMAGE=ghcr.io/wattetheria/wattetheria-observatory:
|
|
4
|
-
WATTSWARM_KERNEL_IMAGE=ghcr.io/wattetheria/wattswarm-kernel:
|
|
5
|
-
WATTSWARM_RUNTIME_IMAGE=ghcr.io/wattetheria/wattswarm-runtime:
|
|
6
|
-
WATTSWARM_WORKER_IMAGE=ghcr.io/wattetheria/wattswarm-worker:
|
|
2
|
+
WATTETHERIA_KERNEL_IMAGE=ghcr.io/wattetheria/wattetheria-kernel:1.0.0
|
|
3
|
+
WATTETHERIA_OBSERVATORY_IMAGE=ghcr.io/wattetheria/wattetheria-observatory:1.0.0
|
|
4
|
+
WATTSWARM_KERNEL_IMAGE=ghcr.io/wattetheria/wattswarm-kernel:1.0.0
|
|
5
|
+
WATTSWARM_RUNTIME_IMAGE=ghcr.io/wattetheria/wattswarm-runtime:1.0.0
|
|
6
|
+
WATTSWARM_WORKER_IMAGE=ghcr.io/wattetheria/wattswarm-worker:1.0.0
|
|
7
7
|
|
|
8
8
|
# Host bindings
|
|
9
9
|
WATTETHERIA_CONTROL_PLANE_BIND_HOST=127.0.0.1
|
package/lib/cli.js
CHANGED
|
@@ -3,9 +3,11 @@ const fs = require("node:fs");
|
|
|
3
3
|
const os = require("node:os");
|
|
4
4
|
const path = require("node:path");
|
|
5
5
|
const { spawnSync } = require("node:child_process");
|
|
6
|
+
const { createInterface } = require("node:readline/promises");
|
|
6
7
|
|
|
7
8
|
const PACKAGE_ROOT = path.resolve(__dirname, "..");
|
|
8
9
|
const PACKAGE_JSON = require(path.join(PACKAGE_ROOT, "package.json"));
|
|
10
|
+
const RELEASE_ENV_TEMPLATE = path.join(PACKAGE_ROOT, ".env.release.example");
|
|
9
11
|
const DEFAULT_DEPLOY_DIR = path.join(os.homedir(), ".wattetheria", "deploy");
|
|
10
12
|
const DEFAULT_PROJECT_NAME = "wattetheria";
|
|
11
13
|
const DEFAULT_COMMAND = "install";
|
|
@@ -16,6 +18,15 @@ const IMAGE_KEYS = [
|
|
|
16
18
|
"WATTSWARM_RUNTIME_IMAGE",
|
|
17
19
|
"WATTSWARM_WORKER_IMAGE"
|
|
18
20
|
];
|
|
21
|
+
const DOCKER_INSTALL_URLS = {
|
|
22
|
+
darwin: "https://www.docker.com/products/docker-desktop/",
|
|
23
|
+
win32: "https://www.docker.com/products/docker-desktop/",
|
|
24
|
+
linux: "https://docs.docker.com/engine/install/"
|
|
25
|
+
};
|
|
26
|
+
const WINDOWS_DOCKER_CANDIDATES = [
|
|
27
|
+
"C:\\Program Files\\Docker\\Docker\\resources\\bin\\docker.exe",
|
|
28
|
+
"C:\\Program Files\\Docker\\cli-plugins\\docker.exe"
|
|
29
|
+
];
|
|
19
30
|
|
|
20
31
|
function printHelp() {
|
|
21
32
|
console.log(`Wattetheria CLI ${PACKAGE_JSON.version}
|
|
@@ -36,6 +47,7 @@ Commands:
|
|
|
36
47
|
help Show this help
|
|
37
48
|
|
|
38
49
|
Options:
|
|
50
|
+
--version Show CLI version
|
|
39
51
|
--dir <path> Deployment directory (default: ${DEFAULT_DEPLOY_DIR})
|
|
40
52
|
--project-name <name> Docker compose project name (default: ${DEFAULT_PROJECT_NAME})
|
|
41
53
|
--tag <tag> Override all release image tags
|
|
@@ -47,6 +59,22 @@ Options:
|
|
|
47
59
|
}
|
|
48
60
|
|
|
49
61
|
function parseArgs(argv) {
|
|
62
|
+
if (argv[0] === "--version" || argv[0] === "-v") {
|
|
63
|
+
return {
|
|
64
|
+
command: "version",
|
|
65
|
+
options: {
|
|
66
|
+
dir: DEFAULT_DEPLOY_DIR,
|
|
67
|
+
projectName: DEFAULT_PROJECT_NAME,
|
|
68
|
+
tag: null,
|
|
69
|
+
force: false,
|
|
70
|
+
healthChecks: true,
|
|
71
|
+
volumes: false,
|
|
72
|
+
purge: false,
|
|
73
|
+
composeArgs: []
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
50
78
|
let command = DEFAULT_COMMAND;
|
|
51
79
|
let index = 0;
|
|
52
80
|
if (argv[0] && !argv[0].startsWith("-")) {
|
|
@@ -57,7 +85,7 @@ function parseArgs(argv) {
|
|
|
57
85
|
const options = {
|
|
58
86
|
dir: DEFAULT_DEPLOY_DIR,
|
|
59
87
|
projectName: DEFAULT_PROJECT_NAME,
|
|
60
|
-
tag:
|
|
88
|
+
tag: null,
|
|
61
89
|
force: false,
|
|
62
90
|
healthChecks: true,
|
|
63
91
|
volumes: false,
|
|
@@ -104,29 +132,228 @@ function requireValue(flag, value) {
|
|
|
104
132
|
return value;
|
|
105
133
|
}
|
|
106
134
|
|
|
107
|
-
function
|
|
108
|
-
|
|
135
|
+
function getDockerInstallUrl() {
|
|
136
|
+
return DOCKER_INSTALL_URLS[process.platform] || DOCKER_INSTALL_URLS.linux;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function getDockerCandidates() {
|
|
140
|
+
if (process.platform === "win32") {
|
|
141
|
+
return ["docker", ...WINDOWS_DOCKER_CANDIDATES];
|
|
142
|
+
}
|
|
143
|
+
return ["docker"];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function resolveDockerCommand() {
|
|
147
|
+
for (const candidate of getDockerCandidates()) {
|
|
148
|
+
const result = spawnSync(candidate, ["--version"], { stdio: "ignore" });
|
|
149
|
+
if (!result.error && result.status === 0) {
|
|
150
|
+
return candidate;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return "";
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function getGitRevision() {
|
|
157
|
+
if (typeof PACKAGE_JSON.gitHead === "string" && PACKAGE_JSON.gitHead.trim()) {
|
|
158
|
+
return PACKAGE_JSON.gitHead.trim();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const result = spawnSync("git", ["rev-parse", "--short=7", "HEAD"], {
|
|
162
|
+
cwd: PACKAGE_ROOT,
|
|
163
|
+
stdio: "pipe",
|
|
164
|
+
encoding: "utf8"
|
|
165
|
+
});
|
|
109
166
|
if (result.error || result.status !== 0) {
|
|
110
|
-
|
|
167
|
+
return "";
|
|
111
168
|
}
|
|
169
|
+
return (result.stdout || "").trim();
|
|
112
170
|
}
|
|
113
171
|
|
|
114
|
-
function
|
|
115
|
-
|
|
116
|
-
"
|
|
117
|
-
|
|
118
|
-
);
|
|
172
|
+
function extractImageTag(imageRef) {
|
|
173
|
+
if (!imageRef) {
|
|
174
|
+
return "";
|
|
175
|
+
}
|
|
176
|
+
const lastColon = imageRef.lastIndexOf(":");
|
|
177
|
+
const lastSlash = imageRef.lastIndexOf("/");
|
|
178
|
+
if (lastColon <= lastSlash) {
|
|
179
|
+
return "";
|
|
180
|
+
}
|
|
181
|
+
return imageRef.slice(lastColon + 1).trim();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function getDefaultReleaseVersion() {
|
|
185
|
+
try {
|
|
186
|
+
const envMap = readEnvFile(RELEASE_ENV_TEMPLATE);
|
|
187
|
+
const tags = IMAGE_KEYS
|
|
188
|
+
.map((key) => extractImageTag(envMap.get(key)))
|
|
189
|
+
.filter(Boolean);
|
|
190
|
+
if (tags.length === IMAGE_KEYS.length && new Set(tags).size === 1) {
|
|
191
|
+
return tags[0];
|
|
192
|
+
}
|
|
193
|
+
} catch (error) {
|
|
194
|
+
// fall through to package version
|
|
195
|
+
}
|
|
196
|
+
return PACKAGE_JSON.version;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function formatVersionString() {
|
|
200
|
+
const revision = getGitRevision();
|
|
201
|
+
const releaseVersion = getDefaultReleaseVersion();
|
|
202
|
+
if (revision) {
|
|
203
|
+
return `Wattetheria ${releaseVersion} (${revision})`;
|
|
204
|
+
}
|
|
205
|
+
return `Wattetheria ${releaseVersion}`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function formatBanner() {
|
|
209
|
+
return `${formatVersionString()} — Local agent runtime with swarm sync and external agent reach.`;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function formatDockerStatusMessage(status) {
|
|
213
|
+
const installUrl = status.installUrl || getDockerInstallUrl();
|
|
214
|
+
switch (status.code) {
|
|
215
|
+
case "missing-docker":
|
|
216
|
+
if (process.platform === "linux") {
|
|
217
|
+
return [
|
|
218
|
+
"Docker runtime not found.",
|
|
219
|
+
"Install Docker Engine or another Docker-compatible runtime, then run the command again.",
|
|
220
|
+
`Install guide: ${installUrl}`
|
|
221
|
+
].join("\n");
|
|
222
|
+
}
|
|
223
|
+
return [
|
|
224
|
+
"Docker runtime not found.",
|
|
225
|
+
"Install Docker Desktop or another Docker-compatible runtime, then run the command again.",
|
|
226
|
+
process.platform === "win32"
|
|
227
|
+
? "If you just installed Docker Desktop, open a new PowerShell window and retry."
|
|
228
|
+
: "",
|
|
229
|
+
`Download: ${installUrl}`
|
|
230
|
+
].filter(Boolean).join("\n");
|
|
231
|
+
case "missing-compose":
|
|
232
|
+
return [
|
|
233
|
+
"Docker Compose v2 is required.",
|
|
234
|
+
process.platform === "linux"
|
|
235
|
+
? "Install or upgrade Docker Engine/Compose so `docker compose` is available."
|
|
236
|
+
: "Install or upgrade Docker Desktop so `docker compose` is available.",
|
|
237
|
+
`Help: ${installUrl}`
|
|
238
|
+
].join("\n");
|
|
239
|
+
case "daemon-unreachable":
|
|
240
|
+
return [
|
|
241
|
+
"Docker is installed but the daemon is not reachable.",
|
|
242
|
+
"Start Docker Desktop or your Docker service, wait until it is ready, then retry."
|
|
243
|
+
].join("\n");
|
|
244
|
+
default:
|
|
245
|
+
return "Docker runtime check failed.";
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function getDockerStatus() {
|
|
250
|
+
const installUrl = getDockerInstallUrl();
|
|
251
|
+
const dockerCommand = resolveDockerCommand();
|
|
252
|
+
if (!dockerCommand) {
|
|
253
|
+
return {
|
|
254
|
+
ready: false,
|
|
255
|
+
code: "missing-docker",
|
|
256
|
+
installUrl
|
|
257
|
+
};
|
|
258
|
+
}
|
|
119
259
|
|
|
120
|
-
const compose = spawnSync(
|
|
260
|
+
const compose = spawnSync(dockerCommand, ["compose", "version"], {
|
|
121
261
|
stdio: "ignore"
|
|
122
262
|
});
|
|
123
263
|
if (compose.error || compose.status !== 0) {
|
|
124
|
-
|
|
264
|
+
return {
|
|
265
|
+
ready: false,
|
|
266
|
+
code: "missing-compose",
|
|
267
|
+
installUrl,
|
|
268
|
+
dockerCommand
|
|
269
|
+
};
|
|
125
270
|
}
|
|
126
271
|
|
|
127
|
-
const info = spawnSync(
|
|
272
|
+
const info = spawnSync(dockerCommand, ["info"], { stdio: "ignore" });
|
|
128
273
|
if (info.error || info.status !== 0) {
|
|
129
|
-
|
|
274
|
+
return {
|
|
275
|
+
ready: false,
|
|
276
|
+
code: "daemon-unreachable",
|
|
277
|
+
installUrl,
|
|
278
|
+
dockerCommand
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return {
|
|
283
|
+
ready: true,
|
|
284
|
+
dockerCommand
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function isInteractiveTerminal() {
|
|
289
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function openUrl(url) {
|
|
293
|
+
let command;
|
|
294
|
+
let args;
|
|
295
|
+
if (process.platform === "darwin") {
|
|
296
|
+
command = "open";
|
|
297
|
+
args = [url];
|
|
298
|
+
} else if (process.platform === "win32") {
|
|
299
|
+
command = "cmd";
|
|
300
|
+
args = ["/c", "start", "", url];
|
|
301
|
+
} else {
|
|
302
|
+
command = "xdg-open";
|
|
303
|
+
args = [url];
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const result = spawnSync(command, args, { stdio: "ignore" });
|
|
307
|
+
return !result.error && result.status === 0;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async function promptForDockerSetup(status) {
|
|
311
|
+
const installUrl = status.installUrl || getDockerInstallUrl();
|
|
312
|
+
const rl = createInterface({
|
|
313
|
+
input: process.stdin,
|
|
314
|
+
output: process.stdout
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
try {
|
|
318
|
+
while (true) {
|
|
319
|
+
console.log("");
|
|
320
|
+
console.log("Wattetheria needs Docker before it can install the local stack.");
|
|
321
|
+
console.log(formatDockerStatusMessage(status));
|
|
322
|
+
console.log("");
|
|
323
|
+
console.log("1. Open runtime install guide");
|
|
324
|
+
console.log("2. Retry Docker check");
|
|
325
|
+
console.log("3. Cancel");
|
|
326
|
+
|
|
327
|
+
const answer = (await rl.question("Select an option [1-3]: ")).trim();
|
|
328
|
+
if (answer === "1") {
|
|
329
|
+
const opened = openUrl(installUrl);
|
|
330
|
+
console.log(opened ? "Opened Docker install page." : `Open this URL in your browser: ${installUrl}`);
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
if (answer === "2") {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
if (answer === "3" || answer === "") {
|
|
337
|
+
throw new Error(formatDockerStatusMessage(status));
|
|
338
|
+
}
|
|
339
|
+
console.log("Please choose 1, 2, or 3.");
|
|
340
|
+
}
|
|
341
|
+
} finally {
|
|
342
|
+
rl.close();
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
async function ensureDockerAvailable(options = {}) {
|
|
347
|
+
const interactive = Boolean(options.interactive);
|
|
348
|
+
while (true) {
|
|
349
|
+
const status = getDockerStatus();
|
|
350
|
+
if (status.ready) {
|
|
351
|
+
return status;
|
|
352
|
+
}
|
|
353
|
+
if (!interactive || !isInteractiveTerminal()) {
|
|
354
|
+
throw new Error(formatDockerStatusMessage(status));
|
|
355
|
+
}
|
|
356
|
+
await promptForDockerSetup(status);
|
|
130
357
|
}
|
|
131
358
|
}
|
|
132
359
|
|
|
@@ -221,8 +448,9 @@ function randomPassword() {
|
|
|
221
448
|
}
|
|
222
449
|
|
|
223
450
|
function runCompose(options, args, capture = false) {
|
|
451
|
+
const dockerCommand = resolveDockerCommand() || "docker";
|
|
224
452
|
const result = spawnSync(
|
|
225
|
-
|
|
453
|
+
dockerCommand,
|
|
226
454
|
[
|
|
227
455
|
"compose",
|
|
228
456
|
"--project-name",
|
|
@@ -242,6 +470,16 @@ function runCompose(options, args, capture = false) {
|
|
|
242
470
|
throw result.error;
|
|
243
471
|
}
|
|
244
472
|
if (result.status !== 0) {
|
|
473
|
+
const stderr = capture ? (result.stderr || "").trim() : "";
|
|
474
|
+
if (stderr.includes("failed to resolve reference") && stderr.includes(": not found")) {
|
|
475
|
+
throw new Error(
|
|
476
|
+
[
|
|
477
|
+
"One or more release images were not found in the container registry.",
|
|
478
|
+
"This usually means the requested image tag has not been published yet.",
|
|
479
|
+
"Publish the matching GHCR images first, or run the command with --tag <published-tag>."
|
|
480
|
+
].join("\n")
|
|
481
|
+
);
|
|
482
|
+
}
|
|
245
483
|
if (capture && result.stderr) {
|
|
246
484
|
throw new Error(result.stderr.trim() || `docker compose ${args.join(" ")} failed`);
|
|
247
485
|
}
|
|
@@ -303,7 +541,7 @@ function printSummary(options) {
|
|
|
303
541
|
}
|
|
304
542
|
|
|
305
543
|
async function install(options) {
|
|
306
|
-
ensureDockerAvailable();
|
|
544
|
+
await ensureDockerAvailable({ interactive: true });
|
|
307
545
|
ensureDeploymentAssets(options);
|
|
308
546
|
runCompose(options, ["config"], true);
|
|
309
547
|
console.log("Pulling release images...");
|
|
@@ -317,7 +555,7 @@ async function install(options) {
|
|
|
317
555
|
}
|
|
318
556
|
|
|
319
557
|
async function start(options) {
|
|
320
|
-
ensureDockerAvailable();
|
|
558
|
+
await ensureDockerAvailable();
|
|
321
559
|
if (!fs.existsSync(composeFilePath(options)) || !fs.existsSync(envFilePath(options))) {
|
|
322
560
|
throw new Error("Deployment is not initialized. Run install first.");
|
|
323
561
|
}
|
|
@@ -328,13 +566,13 @@ async function start(options) {
|
|
|
328
566
|
printSummary(options);
|
|
329
567
|
}
|
|
330
568
|
|
|
331
|
-
function status(options) {
|
|
332
|
-
ensureDockerAvailable();
|
|
569
|
+
async function status(options) {
|
|
570
|
+
await ensureDockerAvailable();
|
|
333
571
|
runCompose(options, ["ps"]);
|
|
334
572
|
}
|
|
335
573
|
|
|
336
574
|
async function update(options) {
|
|
337
|
-
ensureDockerAvailable();
|
|
575
|
+
await ensureDockerAvailable();
|
|
338
576
|
if (!fs.existsSync(composeFilePath(options)) || !fs.existsSync(envFilePath(options))) {
|
|
339
577
|
throw new Error("Deployment is not initialized. Run install first.");
|
|
340
578
|
}
|
|
@@ -349,13 +587,13 @@ async function update(options) {
|
|
|
349
587
|
printSummary(options);
|
|
350
588
|
}
|
|
351
589
|
|
|
352
|
-
function stop(options) {
|
|
353
|
-
ensureDockerAvailable();
|
|
590
|
+
async function stop(options) {
|
|
591
|
+
await ensureDockerAvailable();
|
|
354
592
|
runCompose(options, ["down"]);
|
|
355
593
|
}
|
|
356
594
|
|
|
357
|
-
function uninstall(options) {
|
|
358
|
-
ensureDockerAvailable();
|
|
595
|
+
async function uninstall(options) {
|
|
596
|
+
await ensureDockerAvailable();
|
|
359
597
|
const args = ["down"];
|
|
360
598
|
if (options.volumes) {
|
|
361
599
|
args.push("-v");
|
|
@@ -367,20 +605,40 @@ function uninstall(options) {
|
|
|
367
605
|
}
|
|
368
606
|
}
|
|
369
607
|
|
|
370
|
-
function logs(options) {
|
|
371
|
-
ensureDockerAvailable();
|
|
608
|
+
async function logs(options) {
|
|
609
|
+
await ensureDockerAvailable();
|
|
372
610
|
runCompose(options, ["logs", ...options.composeArgs]);
|
|
373
611
|
}
|
|
374
612
|
|
|
375
613
|
function doctor() {
|
|
376
|
-
|
|
614
|
+
const status = getDockerStatus();
|
|
615
|
+
if (!status.ready) {
|
|
616
|
+
throw new Error(formatDockerStatusMessage(status));
|
|
617
|
+
}
|
|
377
618
|
console.log("Docker runtime is available.");
|
|
378
619
|
console.log(`Node.js ${process.version} is available.`);
|
|
379
620
|
}
|
|
380
621
|
|
|
622
|
+
function printVersion() {
|
|
623
|
+
console.log(formatVersionString());
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
function shouldPrintBanner(command) {
|
|
627
|
+
return !["help", "--help", "-h", "version"].includes(command);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
function printBanner() {
|
|
631
|
+
console.log(formatBanner());
|
|
632
|
+
console.log("");
|
|
633
|
+
}
|
|
634
|
+
|
|
381
635
|
async function run(argv) {
|
|
382
636
|
const { command, options } = parseArgs(argv);
|
|
383
637
|
|
|
638
|
+
if (shouldPrintBanner(command)) {
|
|
639
|
+
printBanner();
|
|
640
|
+
}
|
|
641
|
+
|
|
384
642
|
switch (command) {
|
|
385
643
|
case "install":
|
|
386
644
|
await install(options);
|
|
@@ -390,24 +648,27 @@ async function run(argv) {
|
|
|
390
648
|
await start(options);
|
|
391
649
|
return;
|
|
392
650
|
case "status":
|
|
393
|
-
status(options);
|
|
651
|
+
await status(options);
|
|
394
652
|
return;
|
|
395
653
|
case "update":
|
|
396
654
|
await update(options);
|
|
397
655
|
return;
|
|
398
656
|
case "stop":
|
|
399
657
|
case "down":
|
|
400
|
-
stop(options);
|
|
658
|
+
await stop(options);
|
|
401
659
|
return;
|
|
402
660
|
case "uninstall":
|
|
403
|
-
uninstall(options);
|
|
661
|
+
await uninstall(options);
|
|
404
662
|
return;
|
|
405
663
|
case "logs":
|
|
406
|
-
logs(options);
|
|
664
|
+
await logs(options);
|
|
407
665
|
return;
|
|
408
666
|
case "doctor":
|
|
409
667
|
doctor();
|
|
410
668
|
return;
|
|
669
|
+
case "version":
|
|
670
|
+
printVersion();
|
|
671
|
+
return;
|
|
411
672
|
case "help":
|
|
412
673
|
case "--help":
|
|
413
674
|
case "-h":
|
package/package.json
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wattetheria",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Wattetheria deployment CLI",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "commonjs",
|
|
7
|
-
"bin":
|
|
8
|
-
"wattetheria": "./bin/wattetheria.js"
|
|
9
|
-
},
|
|
7
|
+
"bin": "bin/wattetheria.js",
|
|
10
8
|
"files": [
|
|
11
9
|
"bin/",
|
|
12
10
|
"lib/",
|