@basaltkit/cli 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.ts +26 -2
- package/dist/index.js +52 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -87,7 +87,7 @@ Without registering anything, `runCli` always provides:
|
|
|
87
87
|
| `basalt list` (or `basalt` with no arguments) | Lists all available commands, with their descriptions |
|
|
88
88
|
| `basalt routes` | Lists the HTTP routes registered by the application (read from the `http:routes` metadata bucket, populated by HTTP adapters such as `@basaltkit/fastify`) |
|
|
89
89
|
| `basalt schedule:list` | Lists scheduled tasks and their cron expressions (read from the `schedule:entries` bucket, populated by `@basaltkit/scheduler`) |
|
|
90
|
-
| `basalt dev [--entry
|
|
90
|
+
| `basalt dev [--entry] [--worker] [--queue] [--no-routes]` | Runs the app with watch + restart, **prints the route table on boot**, and with `--worker` also starts a watched `queue:work` alongside it (server + worker in one command). Delegates watching to `tsx watch` / `node --watch`. |
|
|
91
91
|
| `basalt upgrade [--dry] [--only=<id>]` | Applies framework upgrade codemods (ships the `@machize/*` → `@basaltkit/*` scope rename; `--dry` previews) |
|
|
92
92
|
| `basalt publish [<id>] [--force]` | Copies a bundled stub group into the app — `dockerfile`, `ci`, `editorconfig` (run with no id to list) |
|
|
93
93
|
|
package/dist/index.d.ts
CHANGED
|
@@ -104,7 +104,31 @@ interface DevRunner {
|
|
|
104
104
|
declare function resolveDevRunner(entry: string, options?: {
|
|
105
105
|
tsx?: boolean;
|
|
106
106
|
}): DevRunner;
|
|
107
|
-
/**
|
|
107
|
+
/** A route as published into the `http:routes` metadata bucket by an adapter. */
|
|
108
|
+
interface DevRoute {
|
|
109
|
+
method: string;
|
|
110
|
+
url: string;
|
|
111
|
+
meta?: Record<string, unknown>;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Formats the registered routes into printable rows (method, url, and a compact
|
|
115
|
+
* flags column for auth/rate-limit) — sorted by url then method. Pure: this is
|
|
116
|
+
* what `basalt dev` prints on boot, and `pnpm dev` (plain tsx watch) can't.
|
|
117
|
+
*/
|
|
118
|
+
declare function devRouteRows(routes: DevRoute[]): {
|
|
119
|
+
method: string;
|
|
120
|
+
url: string;
|
|
121
|
+
flags: string;
|
|
122
|
+
}[];
|
|
123
|
+
/**
|
|
124
|
+
* `basalt dev [--entry=<file>] [--worker] [--queue=<name>] [--no-routes]`
|
|
125
|
+
*
|
|
126
|
+
* A richer dev loop than a bare `tsx watch`: prints the app's **route table** on
|
|
127
|
+
* boot (the app is already booted by the CLI runner, so routes are known), then
|
|
128
|
+
* runs the server with watch/restart — and, with `--worker`, also starts a
|
|
129
|
+
* watched queue worker alongside it (server + worker in one command, the real
|
|
130
|
+
* producer/worker topology).
|
|
131
|
+
*/
|
|
108
132
|
declare const devCommand: CommandDefinition;
|
|
109
133
|
|
|
110
134
|
/**
|
|
@@ -190,4 +214,4 @@ declare function nodePublishFs(dir: string): PublishFs;
|
|
|
190
214
|
/** `basalt publish [<id>] [--dir=<path>] [--force]` — list, or copy a stub group. */
|
|
191
215
|
declare const publishCommand: CommandDefinition;
|
|
192
216
|
|
|
193
|
-
export { type CommandContext, type CommandDefinition, type CommandIo, DEV_ENTRY_CANDIDATES, type DevRunner, type Edit, MIGRATIONS, type Migration, PUBLISHABLES, type ParsedArgv, type PublishFs, type PublishResult, type Publishable, type PublishableFile, type RouteMetadata, type RunCliOptions, type ScheduleMetadata, type UpgradeFs, type UpgradeReport, builtinCommands, commandsPlugin, consoleIo, defineCommand, devCommand, memoryIo, nodePublishFs, nodeUpgradeFs, parseArgv, publishCommand, renameMachizeScope, renderTable, resolveDevEntry, resolveDevRunner, routesCommand, runCli, runPublish, runUpgrade, scheduleListCommand, upgradeCommand };
|
|
217
|
+
export { type CommandContext, type CommandDefinition, type CommandIo, DEV_ENTRY_CANDIDATES, type DevRoute, type DevRunner, type Edit, MIGRATIONS, type Migration, PUBLISHABLES, type ParsedArgv, type PublishFs, type PublishResult, type Publishable, type PublishableFile, type RouteMetadata, type RunCliOptions, type ScheduleMetadata, type UpgradeFs, type UpgradeReport, builtinCommands, commandsPlugin, consoleIo, defineCommand, devCommand, devRouteRows, memoryIo, nodePublishFs, nodeUpgradeFs, parseArgv, publishCommand, renameMachizeScope, renderTable, resolveDevEntry, resolveDevRunner, routesCommand, runCli, runPublish, runUpgrade, scheduleListCommand, upgradeCommand };
|
package/dist/index.js
CHANGED
|
@@ -4,12 +4,13 @@ function defineCommand(command) {
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
// src/runner.ts
|
|
7
|
-
import { ensureMetadata } from "@basaltkit/core";
|
|
7
|
+
import { ensureMetadata as ensureMetadata2 } from "@basaltkit/core";
|
|
8
8
|
|
|
9
9
|
// src/builtins.ts
|
|
10
10
|
import { METADATA } from "@basaltkit/core";
|
|
11
11
|
|
|
12
12
|
// src/dev.ts
|
|
13
|
+
import { ensureMetadata } from "@basaltkit/core";
|
|
13
14
|
var DEV_ENTRY_CANDIDATES = ["src/main.ts", "src/server.ts", "src/index.ts", "src/main.js", "src/index.js"];
|
|
14
15
|
function resolveDevEntry(candidates, exists) {
|
|
15
16
|
return candidates.find(exists);
|
|
@@ -20,10 +21,20 @@ function resolveDevRunner(entry, options = {}) {
|
|
|
20
21
|
if (isTs) return { command: "node", args: ["--watch", "--experimental-strip-types", entry] };
|
|
21
22
|
return { command: "node", args: ["--watch", entry] };
|
|
22
23
|
}
|
|
24
|
+
function devRouteRows(routes) {
|
|
25
|
+
return [...routes].sort((a, b) => a.url.localeCompare(b.url) || a.method.localeCompare(b.method)).map((r) => {
|
|
26
|
+
const flags = [];
|
|
27
|
+
if (r.meta?.["auth"] === true) flags.push("auth");
|
|
28
|
+
if (r.meta?.["rateLimit"]) flags.push("rate-limit");
|
|
29
|
+
const tags = r.meta?.["tags"];
|
|
30
|
+
if (Array.isArray(tags) && tags.length) flags.push(...tags.map(String));
|
|
31
|
+
return { method: r.method.toUpperCase(), url: r.url, flags: flags.join(", ") };
|
|
32
|
+
});
|
|
33
|
+
}
|
|
23
34
|
var devCommand = defineCommand({
|
|
24
35
|
name: "dev",
|
|
25
|
-
description: "Run the app with
|
|
26
|
-
async handle({ io, flags }) {
|
|
36
|
+
description: "Run the app with watch + restart, print the route table, and (--worker) an embedded queue worker",
|
|
37
|
+
async handle({ container, io, flags }) {
|
|
27
38
|
const { existsSync } = await import("fs");
|
|
28
39
|
const entry = typeof flags["entry"] === "string" ? flags["entry"] : resolveDevEntry(DEV_ENTRY_CANDIDATES, existsSync);
|
|
29
40
|
if (!entry) {
|
|
@@ -32,22 +43,45 @@ var devCommand = defineCommand({
|
|
|
32
43
|
);
|
|
33
44
|
return 1;
|
|
34
45
|
}
|
|
46
|
+
if (flags["routes"] !== false) {
|
|
47
|
+
const routes = ensureMetadata(container).get("http:routes");
|
|
48
|
+
if (routes.length > 0) {
|
|
49
|
+
io.log(`Routes (${routes.length}):`);
|
|
50
|
+
io.table(devRouteRows(routes));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
35
53
|
const tsx = await canResolve("tsx");
|
|
36
|
-
const
|
|
37
|
-
|
|
54
|
+
const server = resolveDevRunner(entry, { tsx });
|
|
55
|
+
const runners = [{ label: "server", runner: server }];
|
|
56
|
+
if (flags["worker"] === true || flags["w"] === true) {
|
|
57
|
+
const bin = process.argv[1] ?? entry;
|
|
58
|
+
const workerBase = resolveDevRunner(bin, { tsx });
|
|
59
|
+
const queue = typeof flags["queue"] === "string" ? [`--queue=${flags["queue"]}`] : [];
|
|
60
|
+
runners.push({ label: "worker", runner: { command: workerBase.command, args: [...workerBase.args, "queue:work", ...queue] } });
|
|
61
|
+
}
|
|
62
|
+
for (const { label, runner } of runners) {
|
|
63
|
+
io.log(`\u25B6 ${label}: ${runner.command} ${runner.args.join(" ")}`);
|
|
64
|
+
}
|
|
38
65
|
const { spawn } = await import("child_process");
|
|
39
66
|
return await new Promise((resolve) => {
|
|
40
|
-
const
|
|
41
|
-
const stop = () =>
|
|
67
|
+
const children = runners.map(({ runner }) => spawn(runner.command, runner.args, { stdio: "inherit" }));
|
|
68
|
+
const stop = () => children.forEach((c) => c.kill("SIGINT"));
|
|
42
69
|
process.once("SIGINT", stop);
|
|
43
|
-
|
|
70
|
+
let done = false;
|
|
71
|
+
const finish = (code) => {
|
|
72
|
+
if (done) return;
|
|
73
|
+
done = true;
|
|
44
74
|
process.removeListener("SIGINT", stop);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
75
|
+
children.forEach((c) => c.kill("SIGINT"));
|
|
76
|
+
resolve(code);
|
|
77
|
+
};
|
|
78
|
+
children[0]?.on("exit", (code) => finish(code ?? 0));
|
|
79
|
+
children.forEach(
|
|
80
|
+
(child, i) => child.on("error", (error) => {
|
|
81
|
+
io.error(`Failed to start ${runners[i]?.label}: ${error.message}`);
|
|
82
|
+
finish(1);
|
|
83
|
+
})
|
|
84
|
+
);
|
|
51
85
|
});
|
|
52
86
|
}
|
|
53
87
|
});
|
|
@@ -361,7 +395,7 @@ async function runCli(options) {
|
|
|
361
395
|
const { command, args, flags } = parseArgv(options.argv ?? process.argv.slice(2));
|
|
362
396
|
if (app.phase === "created") await app.boot();
|
|
363
397
|
try {
|
|
364
|
-
const registered =
|
|
398
|
+
const registered = ensureMetadata2(app.container).get("commands");
|
|
365
399
|
const commands = [...builtinCommands(), ...registered];
|
|
366
400
|
if (command === void 0 || command === "list") {
|
|
367
401
|
io.log("Available commands:");
|
|
@@ -383,12 +417,12 @@ async function runCli(options) {
|
|
|
383
417
|
}
|
|
384
418
|
|
|
385
419
|
// src/plugin.ts
|
|
386
|
-
import { definePlugin, ensureMetadata as
|
|
420
|
+
import { definePlugin, ensureMetadata as ensureMetadata3 } from "@basaltkit/core";
|
|
387
421
|
function commandsPlugin(commands) {
|
|
388
422
|
return definePlugin({
|
|
389
423
|
name: "basalt:commands",
|
|
390
424
|
register({ container }) {
|
|
391
|
-
const metadata =
|
|
425
|
+
const metadata = ensureMetadata3(container);
|
|
392
426
|
for (const command of commands) metadata.add("commands", command);
|
|
393
427
|
}
|
|
394
428
|
});
|
|
@@ -402,6 +436,7 @@ export {
|
|
|
402
436
|
consoleIo,
|
|
403
437
|
defineCommand,
|
|
404
438
|
devCommand,
|
|
439
|
+
devRouteRows,
|
|
405
440
|
memoryIo,
|
|
406
441
|
nodePublishFs,
|
|
407
442
|
nodeUpgradeFs,
|
package/package.json
CHANGED