@confluxjs/conflux 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 +46 -0
- package/dist/cli.cjs +286 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +284 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands.cjs +0 -0
- package/dist/commands.d.cts +4 -0
- package/dist/commands.d.ts +4 -0
- package/dist/commands.js +1 -0
- package/dist/config.cjs +3 -0
- package/dist/config.d.cts +3 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.js +3 -0
- package/dist/conflux-Bx2wI68U.d.ts +18 -0
- package/dist/conflux-Bx2wI68U.d.ts.map +1 -0
- package/dist/conflux-Cff37YF-.d.cts +18 -0
- package/dist/conflux-Cff37YF-.d.cts.map +1 -0
- package/dist/define-config-Bb-dVG_k.js +33 -0
- package/dist/define-config-Bb-dVG_k.js.map +1 -0
- package/dist/define-config-BcOV1lur.d.cts +7 -0
- package/dist/define-config-BcOV1lur.d.cts.map +1 -0
- package/dist/define-config-BsNwuPZR.d.ts +7 -0
- package/dist/define-config-BsNwuPZR.d.ts.map +1 -0
- package/dist/define-config-DW4WVjfh.cjs +80 -0
- package/dist/define-config-DW4WVjfh.cjs.map +1 -0
- package/dist/dev-runner.cjs +14 -0
- package/dist/dev-runner.cjs.map +1 -0
- package/dist/dev-runner.d.cts +1 -0
- package/dist/dev-runner.d.ts +1 -0
- package/dist/dev-runner.js +15 -0
- package/dist/dev-runner.js.map +1 -0
- package/dist/events.cjs +3 -0
- package/dist/events.d.cts +4 -0
- package/dist/events.d.ts +4 -0
- package/dist/events.js +3 -0
- package/dist/index.cjs +479 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +18 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +469 -0
- package/dist/index.js.map +1 -0
- package/dist/parse-args-73A1_Lee.cjs +42 -0
- package/dist/parse-args-73A1_Lee.cjs.map +1 -0
- package/dist/parse-args-fMvnTEQ2.js +30 -0
- package/dist/parse-args-fMvnTEQ2.js.map +1 -0
- package/dist/pipeline-B7aJQrzJ.cjs +33 -0
- package/dist/pipeline-B7aJQrzJ.cjs.map +1 -0
- package/dist/pipeline-BkDu0cvJ.js +15 -0
- package/dist/pipeline-BkDu0cvJ.js.map +1 -0
- package/dist/run-conflux-B_44EsUH.cjs +586 -0
- package/dist/run-conflux-B_44EsUH.cjs.map +1 -0
- package/dist/run-conflux-DMth5S90.js +518 -0
- package/dist/run-conflux-DMth5S90.js.map +1 -0
- package/dist/runtime.cjs +4 -0
- package/dist/runtime.d.cts +3 -0
- package/dist/runtime.d.ts +3 -0
- package/dist/runtime.js +3 -0
- package/dist/start.cjs +12 -0
- package/dist/start.cjs.map +1 -0
- package/dist/start.d.cts +1 -0
- package/dist/start.d.ts +1 -0
- package/dist/start.js +13 -0
- package/dist/start.js.map +1 -0
- package/dist/state-CCmrZeeU.d.cts +8 -0
- package/dist/state-CCmrZeeU.d.cts.map +1 -0
- package/dist/state-CN_liMII.d.ts +8 -0
- package/dist/state-CN_liMII.d.ts.map +1 -0
- package/dist/state-DJDc7S6k.js +13 -0
- package/dist/state-DJDc7S6k.js.map +1 -0
- package/dist/state-EbW_m9jV.cjs +25 -0
- package/dist/state-EbW_m9jV.cjs.map +1 -0
- package/dist/types-BF-O7UjY.d.cts +20 -0
- package/dist/types-BF-O7UjY.d.cts.map +1 -0
- package/dist/types-BNkZrOSn.d.ts +25 -0
- package/dist/types-BNkZrOSn.d.ts.map +1 -0
- package/dist/types-C642X_95.d.cts +25 -0
- package/dist/types-C642X_95.d.cts.map +1 -0
- package/dist/types-CDgj0pfF.d.cts +46 -0
- package/dist/types-CDgj0pfF.d.cts.map +1 -0
- package/dist/types-CYtE8ckK.d.ts +46 -0
- package/dist/types-CYtE8ckK.d.ts.map +1 -0
- package/dist/types-cu2r7p_e.d.ts +20 -0
- package/dist/types-cu2r7p_e.d.ts.map +1 -0
- package/package.json +107 -0
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# @confluxjs/conflux
|
|
2
|
+
|
|
3
|
+
Conflux bot framework CLI and runtime library for Fluxer.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @confluxjs/conflux @fluxerjs/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Import from the package root:
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { defineConfig, createConflux, runConflux } from "@confluxjs/conflux";
|
|
15
|
+
import type { Conflux, MessageCommand, EventHandler } from "@confluxjs/conflux";
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Publishing (maintainers)
|
|
19
|
+
|
|
20
|
+
From the repo root after bumping `version` in each package under `packages/`:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
bun install
|
|
24
|
+
bun run build --filter=@confluxjs/tsconfig --filter=@confluxjs/conflux --filter=@confluxjs/create-conflux
|
|
25
|
+
npm login
|
|
26
|
+
cd packages/tsconfig && npm publish --access public && cd ../..
|
|
27
|
+
cd packages/conflux && npm publish --access public && cd ../..
|
|
28
|
+
cd packages/create-conflux && npm publish --access public && cd ../..
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
See the [getting started guide](https://conflux.js.org/guides/getting-started) on the docs site.
|
|
34
|
+
|
|
35
|
+
## Scripts
|
|
36
|
+
|
|
37
|
+
| Script | Description |
|
|
38
|
+
| --------------------- | ----------------- |
|
|
39
|
+
| `bun run build` | Build with tsdown |
|
|
40
|
+
| `bun run check-types` | Typecheck |
|
|
41
|
+
| `bun run lint` | ESLint |
|
|
42
|
+
|
|
43
|
+
## Links
|
|
44
|
+
|
|
45
|
+
- [Documentation](https://conflux.js.org)
|
|
46
|
+
- [API reference](https://conflux.js.org/api/)
|
package/dist/cli.cjs
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const require_run_conflux = require('./run-conflux-B_44EsUH.cjs');
|
|
3
|
+
const require_parse_args = require('./parse-args-73A1_Lee.cjs');
|
|
4
|
+
let node_child_process = require("node:child_process");
|
|
5
|
+
node_child_process = require_run_conflux.__toESM(node_child_process);
|
|
6
|
+
let node_path = require("node:path");
|
|
7
|
+
node_path = require_run_conflux.__toESM(node_path);
|
|
8
|
+
let node_fs = require("node:fs");
|
|
9
|
+
node_fs = require_run_conflux.__toESM(node_fs);
|
|
10
|
+
|
|
11
|
+
//#region src/loader/command-paths.ts
|
|
12
|
+
function collectCommandTreeModulePaths(commandsDir) {
|
|
13
|
+
const discovered = require_run_conflux.discoverCommandPaths(commandsDir);
|
|
14
|
+
const paths = [
|
|
15
|
+
...discovered.commandPaths,
|
|
16
|
+
...discovered.globalMiddlewarePaths,
|
|
17
|
+
...discovered.directoryMiddlewarePaths.values(),
|
|
18
|
+
...discovered.commandMiddlewarePaths.values()
|
|
19
|
+
];
|
|
20
|
+
return [...new Set(paths)].sort((a, b) => a.localeCompare(b));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/build/build-bot.ts
|
|
25
|
+
async function buildBotProject(options = {}) {
|
|
26
|
+
const config = await require_run_conflux.loadConfluxConfig(options.root ?? process.cwd());
|
|
27
|
+
if (!config.entry) throw new Error("Conflux entry is not configured");
|
|
28
|
+
await require_run_conflux.loadCommandRegistry(config.commandsDir);
|
|
29
|
+
const entrypoints = [
|
|
30
|
+
config.entry,
|
|
31
|
+
...require_run_conflux.collectEventDirectoryModulePaths(config.eventsDir),
|
|
32
|
+
...collectCommandTreeModulePaths(config.commandsDir)
|
|
33
|
+
];
|
|
34
|
+
const outDir = options.outDir ?? config.outDir;
|
|
35
|
+
const relEntrypoints = entrypoints.map((path) => (0, node_path.relative)(config.root, path));
|
|
36
|
+
const relOutDir = (0, node_path.relative)(config.root, outDir);
|
|
37
|
+
const args = [
|
|
38
|
+
"build",
|
|
39
|
+
...relEntrypoints,
|
|
40
|
+
"--outdir",
|
|
41
|
+
relOutDir,
|
|
42
|
+
"--target",
|
|
43
|
+
"node",
|
|
44
|
+
"--packages",
|
|
45
|
+
"bundle",
|
|
46
|
+
"--sourcemap=linked"
|
|
47
|
+
];
|
|
48
|
+
if (options.minify !== false) args.push("--minify");
|
|
49
|
+
const result = (0, node_child_process.spawnSync)("bun", args, {
|
|
50
|
+
cwd: config.root,
|
|
51
|
+
stdio: "inherit"
|
|
52
|
+
});
|
|
53
|
+
if (result.error) throw result.error;
|
|
54
|
+
if (result.status !== 0) process.exit(result.status ?? 1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/cli/build-cmd.ts
|
|
59
|
+
async function runBuildCommand(root) {
|
|
60
|
+
await buildBotProject({ root });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
//#endregion
|
|
64
|
+
//#region src/build/paths.ts
|
|
65
|
+
const SOURCE_MODULE_PATTERN = /\.(tsx?|mts|cts)$/i;
|
|
66
|
+
function sourceModuleToOutputPath(outDir, entry, sourcePath) {
|
|
67
|
+
return (0, node_path.join)(outDir, (0, node_path.relative)((0, node_path.dirname)(entry), sourcePath).replace(SOURCE_MODULE_PATTERN, ".js"));
|
|
68
|
+
}
|
|
69
|
+
function sourceDirToOutputDir(outDir, entry, sourceDir) {
|
|
70
|
+
return (0, node_path.join)(outDir, (0, node_path.relative)((0, node_path.dirname)(entry), sourceDir));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/build/resolve-built-config.ts
|
|
75
|
+
function resolveBuiltConfig(config) {
|
|
76
|
+
const builtEntry = sourceModuleToOutputPath(config.outDir, config.entry, config.entry);
|
|
77
|
+
if (!(0, node_fs.existsSync)(builtEntry)) return null;
|
|
78
|
+
return {
|
|
79
|
+
...config,
|
|
80
|
+
entry: builtEntry,
|
|
81
|
+
eventsDir: sourceDirToOutputDir(config.outDir, config.entry, config.eventsDir),
|
|
82
|
+
commandsDir: sourceDirToOutputDir(config.outDir, config.entry, config.commandsDir)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/dev/dev-out-dir.ts
|
|
88
|
+
const CONFLUX_DEV_OUT_DIR = ".conflux";
|
|
89
|
+
function resolveDevOutDir(projectRoot) {
|
|
90
|
+
return (0, node_path.join)(projectRoot, CONFLUX_DEV_OUT_DIR);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/dev/dev-bootstrap.ts
|
|
95
|
+
function ensureDevBootstrap(projectRoot, built) {
|
|
96
|
+
const dir = resolveDevOutDir(projectRoot);
|
|
97
|
+
const filePath = (0, node_path.join)(dir, "dev.mjs");
|
|
98
|
+
(0, node_fs.mkdirSync)(dir, { recursive: true });
|
|
99
|
+
const source = `import { runConflux } from "@confluxjs/conflux";
|
|
100
|
+
|
|
101
|
+
await runConflux({
|
|
102
|
+
root: ${JSON.stringify(built.root)},
|
|
103
|
+
entry: ${JSON.stringify(built.entry)},
|
|
104
|
+
eventsDir: ${JSON.stringify(built.eventsDir)},
|
|
105
|
+
commandsDir: ${JSON.stringify(built.commandsDir)},
|
|
106
|
+
}).catch((error) => {
|
|
107
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
108
|
+
console.error(message);
|
|
109
|
+
process.exit(1);
|
|
110
|
+
});
|
|
111
|
+
`;
|
|
112
|
+
if (!(0, node_fs.existsSync)(filePath) || (0, node_fs.readFileSync)(filePath, "utf8") !== source) (0, node_fs.writeFileSync)(filePath, source, "utf8");
|
|
113
|
+
return filePath;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
//#endregion
|
|
117
|
+
//#region src/dev/watch-project.ts
|
|
118
|
+
const RESTART_DEBOUNCE_MS = 250;
|
|
119
|
+
function watchDirectory(path, onChange, watchers) {
|
|
120
|
+
try {
|
|
121
|
+
watchers.push((0, node_fs.watch)(path, { recursive: true }, (_eventType, filename) => {
|
|
122
|
+
if (filename === null) return;
|
|
123
|
+
onChange();
|
|
124
|
+
}));
|
|
125
|
+
} catch {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function watchFile(path, onChange, watchers) {
|
|
130
|
+
try {
|
|
131
|
+
watchers.push((0, node_fs.watch)(path, () => onChange()));
|
|
132
|
+
} catch {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async function runProjectDevWatch(root) {
|
|
137
|
+
const projectRoot = root ?? process.cwd();
|
|
138
|
+
const devOutDir = resolveDevOutDir(projectRoot);
|
|
139
|
+
const bunExecutable = process.env.CONFLUX_BUN ?? "bun";
|
|
140
|
+
const watchers = [];
|
|
141
|
+
let child = null;
|
|
142
|
+
let debounceTimer = null;
|
|
143
|
+
let shuttingDown = false;
|
|
144
|
+
let building = false;
|
|
145
|
+
let rebuildQueued = false;
|
|
146
|
+
const stopChild = () => {
|
|
147
|
+
if (!child || child.killed) return;
|
|
148
|
+
child.kill("SIGTERM");
|
|
149
|
+
child = null;
|
|
150
|
+
};
|
|
151
|
+
const startChild = (entryPath) => {
|
|
152
|
+
stopChild();
|
|
153
|
+
child = (0, node_child_process.spawn)(bunExecutable, [entryPath], {
|
|
154
|
+
cwd: projectRoot,
|
|
155
|
+
stdio: "inherit",
|
|
156
|
+
env: {
|
|
157
|
+
...process.env,
|
|
158
|
+
NODE_ENV: "development"
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
child.on("exit", (code, signal) => {
|
|
162
|
+
if (shuttingDown) return;
|
|
163
|
+
if (signal === "SIGTERM") return;
|
|
164
|
+
if (code !== 0 && code !== null) process.exitCode = code;
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
const rebuildAndRestart = async () => {
|
|
168
|
+
if (building) {
|
|
169
|
+
rebuildQueued = true;
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
building = true;
|
|
173
|
+
try {
|
|
174
|
+
await buildBotProject({
|
|
175
|
+
root: projectRoot,
|
|
176
|
+
outDir: devOutDir,
|
|
177
|
+
minify: false
|
|
178
|
+
});
|
|
179
|
+
const built = resolveBuiltConfig({
|
|
180
|
+
...await require_run_conflux.loadConfluxConfig(projectRoot),
|
|
181
|
+
outDir: devOutDir
|
|
182
|
+
});
|
|
183
|
+
if (!built) throw new Error(`Dev build missing entry in ${devOutDir}`);
|
|
184
|
+
startChild(ensureDevBootstrap(projectRoot, built));
|
|
185
|
+
} catch (error) {
|
|
186
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
187
|
+
console.error(message);
|
|
188
|
+
process.exitCode = 1;
|
|
189
|
+
} finally {
|
|
190
|
+
building = false;
|
|
191
|
+
if (rebuildQueued) {
|
|
192
|
+
rebuildQueued = false;
|
|
193
|
+
await rebuildAndRestart();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
const scheduleRestart = () => {
|
|
198
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
199
|
+
debounceTimer = setTimeout(() => {
|
|
200
|
+
debounceTimer = null;
|
|
201
|
+
rebuildAndRestart();
|
|
202
|
+
}, RESTART_DEBOUNCE_MS);
|
|
203
|
+
};
|
|
204
|
+
const config = await require_run_conflux.loadConfluxConfig(projectRoot);
|
|
205
|
+
const watchTargets = new Set([
|
|
206
|
+
(0, node_path.dirname)(config.entry),
|
|
207
|
+
config.eventsDir,
|
|
208
|
+
config.commandsDir
|
|
209
|
+
]);
|
|
210
|
+
const configPath = require_run_conflux.findConfigPath(projectRoot);
|
|
211
|
+
if (configPath) watchFile(configPath, scheduleRestart, watchers);
|
|
212
|
+
for (const target of watchTargets) watchDirectory(target, scheduleRestart, watchers);
|
|
213
|
+
const shutdown = () => {
|
|
214
|
+
shuttingDown = true;
|
|
215
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
216
|
+
for (const watcher of watchers) watcher.close();
|
|
217
|
+
stopChild();
|
|
218
|
+
process.exit(0);
|
|
219
|
+
};
|
|
220
|
+
process.on("SIGINT", shutdown);
|
|
221
|
+
process.on("SIGTERM", shutdown);
|
|
222
|
+
await rebuildAndRestart();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
//#endregion
|
|
226
|
+
//#region src/cli/dev-cmd.ts
|
|
227
|
+
function runDevCommand(root) {
|
|
228
|
+
runProjectDevWatch(root).catch((error) => {
|
|
229
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
230
|
+
console.error(message);
|
|
231
|
+
process.exit(1);
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
//#endregion
|
|
236
|
+
//#region src/cli/start-cmd.ts
|
|
237
|
+
async function runStartCommand(root) {
|
|
238
|
+
const projectRoot = root ?? process.cwd();
|
|
239
|
+
const built = resolveBuiltConfig(await require_run_conflux.loadConfluxConfig(projectRoot));
|
|
240
|
+
if (built) {
|
|
241
|
+
await require_run_conflux.runConflux({
|
|
242
|
+
root: projectRoot,
|
|
243
|
+
entry: built.entry,
|
|
244
|
+
eventsDir: built.eventsDir,
|
|
245
|
+
commandsDir: built.commandsDir,
|
|
246
|
+
production: true
|
|
247
|
+
});
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
await require_run_conflux.runConflux({
|
|
251
|
+
root: projectRoot,
|
|
252
|
+
production: true
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
//#endregion
|
|
257
|
+
//#region src/cli/run.ts
|
|
258
|
+
async function main() {
|
|
259
|
+
const { command, root } = require_parse_args.parseArgs(process.argv.slice(2));
|
|
260
|
+
const projectRoot = root ?? void 0;
|
|
261
|
+
switch (command) {
|
|
262
|
+
case "build":
|
|
263
|
+
await runBuildCommand(projectRoot);
|
|
264
|
+
return;
|
|
265
|
+
case "start":
|
|
266
|
+
await runStartCommand(projectRoot);
|
|
267
|
+
return;
|
|
268
|
+
case "dev":
|
|
269
|
+
case "run":
|
|
270
|
+
case null:
|
|
271
|
+
runDevCommand(projectRoot);
|
|
272
|
+
return;
|
|
273
|
+
default:
|
|
274
|
+
console.error(`Unknown command: ${command}`);
|
|
275
|
+
console.error(require_parse_args.CLI_USAGE);
|
|
276
|
+
process.exit(1);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
main().catch((error) => {
|
|
280
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
281
|
+
console.error(message);
|
|
282
|
+
process.exit(1);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
//#endregion
|
|
286
|
+
//# sourceMappingURL=cli.cjs.map
|
package/dist/cli.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.cjs","names":["discoverCommandPaths","loadConfluxConfig","loadCommandRegistry","collectEventDirectoryModulePaths","watchers: ReturnType<typeof watch>[]","child: ChildProcess | null","debounceTimer: ReturnType<typeof setTimeout> | null","loadConfluxConfig","error: unknown","findConfigPath","loadConfluxConfig","runConflux","parseArgs","CLI_USAGE"],"sources":["../src/loader/command-paths.ts","../src/build/build-bot.ts","../src/cli/build-cmd.ts","../src/build/paths.ts","../src/build/resolve-built-config.ts","../src/dev/dev-out-dir.ts","../src/dev/dev-bootstrap.ts","../src/dev/watch-project.ts","../src/cli/dev-cmd.ts","../src/cli/start-cmd.ts","../src/cli/run.ts"],"sourcesContent":["import { discoverCommandPaths } from \"../commands/discover-paths.js\";\n\nexport function collectCommandTreeModulePaths(commandsDir: string): string[] {\n const discovered = discoverCommandPaths(commandsDir);\n const paths = [\n ...discovered.commandPaths,\n ...discovered.globalMiddlewarePaths,\n ...discovered.directoryMiddlewarePaths.values(),\n ...discovered.commandMiddlewarePaths.values(),\n ];\n return [...new Set(paths)].sort((a, b) => a.localeCompare(b));\n}\n","import { spawnSync } from \"node:child_process\";\nimport { relative } from \"node:path\";\n\nimport { loadCommandRegistry } from \"../commands/load-registry.js\";\nimport { loadConfluxConfig } from \"../config/load-config.js\";\nimport { collectCommandTreeModulePaths } from \"../loader/command-paths.js\";\nimport { collectEventDirectoryModulePaths } from \"../loader/directory-modules.js\";\n\nexport type BuildBotOptions = {\n root?: string;\n outDir?: string;\n minify?: boolean;\n};\n\nexport async function buildBotProject(options: BuildBotOptions = {}): Promise<void> {\n const projectRoot = options.root ?? process.cwd();\n const config = await loadConfluxConfig(projectRoot);\n if (!config.entry) {\n throw new Error(\"Conflux entry is not configured\");\n }\n await loadCommandRegistry(config.commandsDir);\n const entrypoints = [\n config.entry,\n ...collectEventDirectoryModulePaths(config.eventsDir),\n ...collectCommandTreeModulePaths(config.commandsDir),\n ];\n const outDir = options.outDir ?? config.outDir;\n const relEntrypoints = entrypoints.map((path) => relative(config.root, path));\n const relOutDir = relative(config.root, outDir);\n const args = [\n \"build\",\n ...relEntrypoints,\n \"--outdir\",\n relOutDir,\n \"--target\",\n \"node\",\n \"--packages\",\n \"bundle\",\n \"--sourcemap=linked\",\n ];\n if (options.minify !== false) {\n args.push(\"--minify\");\n }\n const result = spawnSync(\"bun\", args, {\n cwd: config.root,\n stdio: \"inherit\",\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n process.exit(result.status ?? 1);\n }\n}\n","import { buildBotProject } from \"../build/build-bot.js\";\n\nexport async function runBuildCommand(root?: string): Promise<void> {\n await buildBotProject({ root });\n}\n","import { dirname, join, relative } from \"node:path\";\n\nconst SOURCE_MODULE_PATTERN = /\\.(tsx?|mts|cts)$/i;\n\nexport function sourceModuleToOutputPath(\n outDir: string,\n entry: string,\n sourcePath: string,\n): string {\n const entryDir = dirname(entry);\n const rel = relative(entryDir, sourcePath);\n const jsRel = rel.replace(SOURCE_MODULE_PATTERN, \".js\");\n return join(outDir, jsRel);\n}\n\nexport function sourceDirToOutputDir(outDir: string, entry: string, sourceDir: string): string {\n const entryDir = dirname(entry);\n const rel = relative(entryDir, sourceDir);\n return join(outDir, rel);\n}\n","import { existsSync } from \"node:fs\";\n\nimport type { ResolvedConfluxConfig } from \"../config/types.js\";\nimport { sourceDirToOutputDir, sourceModuleToOutputPath } from \"./paths.js\";\n\nexport function resolveBuiltConfig(config: ResolvedConfluxConfig): ResolvedConfluxConfig | null {\n const builtEntry = sourceModuleToOutputPath(config.outDir, config.entry, config.entry);\n if (!existsSync(builtEntry)) {\n return null;\n }\n return {\n ...config,\n entry: builtEntry,\n eventsDir: sourceDirToOutputDir(config.outDir, config.entry, config.eventsDir),\n commandsDir: sourceDirToOutputDir(config.outDir, config.entry, config.commandsDir),\n };\n}\n","import { join } from \"node:path\";\n\nexport const CONFLUX_DEV_OUT_DIR = \".conflux\";\n\nexport function resolveDevOutDir(projectRoot: string): string {\n return join(projectRoot, CONFLUX_DEV_OUT_DIR);\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport type { ResolvedConfluxConfig } from \"../config/types.js\";\nimport { resolveDevOutDir } from \"./dev-out-dir.js\";\n\nexport function ensureDevBootstrap(projectRoot: string, built: ResolvedConfluxConfig): string {\n const dir = resolveDevOutDir(projectRoot);\n const filePath = join(dir, \"dev.mjs\");\n mkdirSync(dir, { recursive: true });\n const source = `import { runConflux } from \"@confluxjs/conflux\";\n\nawait runConflux({\n root: ${JSON.stringify(built.root)},\n entry: ${JSON.stringify(built.entry)},\n eventsDir: ${JSON.stringify(built.eventsDir)},\n commandsDir: ${JSON.stringify(built.commandsDir)},\n}).catch((error) => {\n const message = error instanceof Error ? error.message : String(error);\n console.error(message);\n process.exit(1);\n});\n`;\n if (!existsSync(filePath) || readFileSync(filePath, \"utf8\") !== source) {\n writeFileSync(filePath, source, \"utf8\");\n }\n return filePath;\n}\n","import { type ChildProcess, spawn } from \"node:child_process\";\nimport { watch } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nimport { buildBotProject } from \"../build/build-bot.js\";\nimport { resolveBuiltConfig } from \"../build/resolve-built-config.js\";\nimport { findConfigPath, loadConfluxConfig } from \"../config/load-config.js\";\nimport { ensureDevBootstrap } from \"./dev-bootstrap.js\";\nimport { resolveDevOutDir } from \"./dev-out-dir.js\";\n\nconst RESTART_DEBOUNCE_MS = 250;\n\nfunction watchDirectory(\n path: string,\n onChange: () => void,\n watchers: ReturnType<typeof watch>[],\n): void {\n try {\n watchers.push(\n watch(path, { recursive: true }, (_eventType, filename) => {\n if (filename === null) {\n return;\n }\n onChange();\n }),\n );\n } catch {\n return;\n }\n}\n\nfunction watchFile(path: string, onChange: () => void, watchers: ReturnType<typeof watch>[]): void {\n try {\n watchers.push(watch(path, () => onChange()));\n } catch {\n return;\n }\n}\n\nexport async function runProjectDevWatch(root?: string): Promise<void> {\n const projectRoot = root ?? process.cwd();\n const devOutDir = resolveDevOutDir(projectRoot);\n const bunExecutable = process.env.CONFLUX_BUN ?? \"bun\";\n const watchers: ReturnType<typeof watch>[] = [];\n let child: ChildProcess | null = null;\n let debounceTimer: ReturnType<typeof setTimeout> | null = null;\n let shuttingDown = false;\n let building = false;\n let rebuildQueued = false;\n\n const stopChild = (): void => {\n if (!child || child.killed) {\n return;\n }\n child.kill(\"SIGTERM\");\n child = null;\n };\n\n const startChild = (entryPath: string): void => {\n stopChild();\n child = spawn(bunExecutable, [entryPath], {\n cwd: projectRoot,\n stdio: \"inherit\",\n env: { ...process.env, NODE_ENV: \"development\" },\n });\n child.on(\"exit\", (code, signal) => {\n if (shuttingDown) {\n return;\n }\n if (signal === \"SIGTERM\") {\n return;\n }\n if (code !== 0 && code !== null) {\n process.exitCode = code;\n }\n });\n };\n\n const rebuildAndRestart = async (): Promise<void> => {\n if (building) {\n rebuildQueued = true;\n return;\n }\n building = true;\n try {\n await buildBotProject({\n root: projectRoot,\n outDir: devOutDir,\n minify: false,\n });\n const config = await loadConfluxConfig(projectRoot);\n const built = resolveBuiltConfig({ ...config, outDir: devOutDir });\n if (!built) {\n throw new Error(`Dev build missing entry in ${devOutDir}`);\n }\n const runnerPath = ensureDevBootstrap(projectRoot, built);\n startChild(runnerPath);\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(message);\n process.exitCode = 1;\n } finally {\n building = false;\n if (rebuildQueued) {\n rebuildQueued = false;\n await rebuildAndRestart();\n }\n }\n };\n\n const scheduleRestart = (): void => {\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n debounceTimer = setTimeout(() => {\n debounceTimer = null;\n void rebuildAndRestart();\n }, RESTART_DEBOUNCE_MS);\n };\n\n const config = await loadConfluxConfig(projectRoot);\n const watchTargets = new Set<string>([\n dirname(config.entry),\n config.eventsDir,\n config.commandsDir,\n ]);\n const configPath = findConfigPath(projectRoot);\n if (configPath) {\n watchFile(configPath, scheduleRestart, watchers);\n }\n for (const target of watchTargets) {\n watchDirectory(target, scheduleRestart, watchers);\n }\n\n const shutdown = (): void => {\n shuttingDown = true;\n if (debounceTimer) {\n clearTimeout(debounceTimer);\n }\n for (const watcher of watchers) {\n watcher.close();\n }\n stopChild();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n await rebuildAndRestart();\n}\n","import { runProjectDevWatch } from \"../dev/watch-project.js\";\n\nexport function runDevCommand(root?: string): void {\n runProjectDevWatch(root).catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n console.error(message);\n process.exit(1);\n });\n}\n","import { resolveBuiltConfig } from \"../build/resolve-built-config.js\";\nimport { loadConfluxConfig } from \"../config/load-config.js\";\nimport { runConflux } from \"../runtime/run-conflux.js\";\n\nexport async function runStartCommand(root?: string): Promise<void> {\n const projectRoot = root ?? process.cwd();\n const config = await loadConfluxConfig(projectRoot);\n const built = resolveBuiltConfig(config);\n if (built) {\n await runConflux({\n root: projectRoot,\n entry: built.entry,\n eventsDir: built.eventsDir,\n commandsDir: built.commandsDir,\n production: true,\n });\n return;\n }\n await runConflux({ root: projectRoot, production: true });\n}\n","import { runBuildCommand } from \"./build-cmd.js\";\nimport { runDevCommand } from \"./dev-cmd.js\";\nimport { CLI_USAGE, parseArgs } from \"./parse-args.js\";\nimport { runStartCommand } from \"./start-cmd.js\";\n\nasync function main(): Promise<void> {\n const { command, root } = parseArgs(process.argv.slice(2));\n const projectRoot = root ?? undefined;\n switch (command) {\n case \"build\":\n await runBuildCommand(projectRoot);\n return;\n case \"start\":\n await runStartCommand(projectRoot);\n return;\n case \"dev\":\n case \"run\":\n case null:\n runDevCommand(projectRoot);\n return;\n default:\n console.error(`Unknown command: ${command}`);\n console.error(CLI_USAGE);\n process.exit(1);\n }\n}\n\nmain().catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error);\n console.error(message);\n process.exit(1);\n});\n"],"mappings":";;;;;;;;;;;AAEA,SAAgB,8BAA8B,aAA+B;CAC3E,MAAM,aAAaA,yCAAqB,YAAY;CACpD,MAAM,QAAQ;EACZ,GAAG,WAAW;EACd,GAAG,WAAW;EACd,GAAG,WAAW,yBAAyB,QAAQ;EAC/C,GAAG,WAAW,uBAAuB,QAAQ;EAC9C;AACD,QAAO,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,cAAc,EAAE,CAAC;;;;;ACI/D,eAAsB,gBAAgB,UAA2B,EAAE,EAAiB;CAElF,MAAM,SAAS,MAAMC,sCADD,QAAQ,QAAQ,QAAQ,KAAK,CACE;AACnD,KAAI,CAAC,OAAO,MACV,OAAM,IAAI,MAAM,kCAAkC;AAEpD,OAAMC,wCAAoB,OAAO,YAAY;CAC7C,MAAM,cAAc;EAClB,OAAO;EACP,GAAGC,qDAAiC,OAAO,UAAU;EACrD,GAAG,8BAA8B,OAAO,YAAY;EACrD;CACD,MAAM,SAAS,QAAQ,UAAU,OAAO;CACxC,MAAM,iBAAiB,YAAY,KAAK,iCAAkB,OAAO,MAAM,KAAK,CAAC;CAC7E,MAAM,oCAAqB,OAAO,MAAM,OAAO;CAC/C,MAAM,OAAO;EACX;EACA,GAAG;EACH;EACA;EACA;EACA;EACA;EACA;EACA;EACD;AACD,KAAI,QAAQ,WAAW,MACrB,MAAK,KAAK,WAAW;CAEvB,MAAM,2CAAmB,OAAO,MAAM;EACpC,KAAK,OAAO;EACZ,OAAO;EACR,CAAC;AACF,KAAI,OAAO,MACT,OAAM,OAAO;AAEf,KAAI,OAAO,WAAW,EACpB,SAAQ,KAAK,OAAO,UAAU,EAAE;;;;;ACjDpC,eAAsB,gBAAgB,MAA8B;AAClE,OAAM,gBAAgB,EAAE,MAAM,CAAC;;;;;ACDjC,MAAM,wBAAwB;AAE9B,SAAgB,yBACd,QACA,OACA,YACQ;AAIR,4BAAY,uDAHa,MAAM,EACA,WAAW,CACxB,QAAQ,uBAAuB,MAAM,CAC7B;;AAG5B,SAAgB,qBAAqB,QAAgB,OAAe,WAA2B;AAG7F,4BAAY,uDAFa,MAAM,EACA,UAAU,CACjB;;;;;ACb1B,SAAgB,mBAAmB,QAA6D;CAC9F,MAAM,aAAa,yBAAyB,OAAO,QAAQ,OAAO,OAAO,OAAO,MAAM;AACtF,KAAI,yBAAY,WAAW,CACzB,QAAO;AAET,QAAO;EACL,GAAG;EACH,OAAO;EACP,WAAW,qBAAqB,OAAO,QAAQ,OAAO,OAAO,OAAO,UAAU;EAC9E,aAAa,qBAAqB,OAAO,QAAQ,OAAO,OAAO,OAAO,YAAY;EACnF;;;;;ACbH,MAAa,sBAAsB;AAEnC,SAAgB,iBAAiB,aAA6B;AAC5D,4BAAY,aAAa,oBAAoB;;;;;ACC/C,SAAgB,mBAAmB,aAAqB,OAAsC;CAC5F,MAAM,MAAM,iBAAiB,YAAY;CACzC,MAAM,+BAAgB,KAAK,UAAU;AACrC,wBAAU,KAAK,EAAE,WAAW,MAAM,CAAC;CACnC,MAAM,SAAS;;;UAGP,KAAK,UAAU,MAAM,KAAK,CAAC;WAC1B,KAAK,UAAU,MAAM,MAAM,CAAC;eACxB,KAAK,UAAU,MAAM,UAAU,CAAC;iBAC9B,KAAK,UAAU,MAAM,YAAY,CAAC;;;;;;;AAOjD,KAAI,yBAAY,SAAS,8BAAiB,UAAU,OAAO,KAAK,OAC9D,4BAAc,UAAU,QAAQ,OAAO;AAEzC,QAAO;;;;;AChBT,MAAM,sBAAsB;AAE5B,SAAS,eACP,MACA,UACA,UACM;AACN,KAAI;AACF,WAAS,wBACD,MAAM,EAAE,WAAW,MAAM,GAAG,YAAY,aAAa;AACzD,OAAI,aAAa,KACf;AAEF,aAAU;IACV,CACH;SACK;AACN;;;AAIJ,SAAS,UAAU,MAAc,UAAsB,UAA4C;AACjG,KAAI;AACF,WAAS,wBAAW,YAAY,UAAU,CAAC,CAAC;SACtC;AACN;;;AAIJ,eAAsB,mBAAmB,MAA8B;CACrE,MAAM,cAAc,QAAQ,QAAQ,KAAK;CACzC,MAAM,YAAY,iBAAiB,YAAY;CAC/C,MAAM,gBAAgB,QAAQ,IAAI,eAAe;CACjD,MAAMC,WAAuC,EAAE;CAC/C,IAAIC,QAA6B;CACjC,IAAIC,gBAAsD;CAC1D,IAAI,eAAe;CACnB,IAAI,WAAW;CACf,IAAI,gBAAgB;CAEpB,MAAM,kBAAwB;AAC5B,MAAI,CAAC,SAAS,MAAM,OAClB;AAEF,QAAM,KAAK,UAAU;AACrB,UAAQ;;CAGV,MAAM,cAAc,cAA4B;AAC9C,aAAW;AACX,wCAAc,eAAe,CAAC,UAAU,EAAE;GACxC,KAAK;GACL,OAAO;GACP,KAAK;IAAE,GAAG,QAAQ;IAAK,UAAU;IAAe;GACjD,CAAC;AACF,QAAM,GAAG,SAAS,MAAM,WAAW;AACjC,OAAI,aACF;AAEF,OAAI,WAAW,UACb;AAEF,OAAI,SAAS,KAAK,SAAS,KACzB,SAAQ,WAAW;IAErB;;CAGJ,MAAM,oBAAoB,YAA2B;AACnD,MAAI,UAAU;AACZ,mBAAgB;AAChB;;AAEF,aAAW;AACX,MAAI;AACF,SAAM,gBAAgB;IACpB,MAAM;IACN,QAAQ;IACR,QAAQ;IACT,CAAC;GAEF,MAAM,QAAQ,mBAAmB;IAAE,GADpB,MAAMC,sCAAkB,YAAY;IACL,QAAQ;IAAW,CAAC;AAClE,OAAI,CAAC,MACH,OAAM,IAAI,MAAM,8BAA8B,YAAY;AAG5D,cADmB,mBAAmB,aAAa,MAAM,CACnC;WACfC,OAAgB;GACvB,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACtE,WAAQ,MAAM,QAAQ;AACtB,WAAQ,WAAW;YACX;AACR,cAAW;AACX,OAAI,eAAe;AACjB,oBAAgB;AAChB,UAAM,mBAAmB;;;;CAK/B,MAAM,wBAA8B;AAClC,MAAI,cACF,cAAa,cAAc;AAE7B,kBAAgB,iBAAiB;AAC/B,mBAAgB;AAChB,GAAK,mBAAmB;KACvB,oBAAoB;;CAGzB,MAAM,SAAS,MAAMD,sCAAkB,YAAY;CACnD,MAAM,eAAe,IAAI,IAAY;yBAC3B,OAAO,MAAM;EACrB,OAAO;EACP,OAAO;EACR,CAAC;CACF,MAAM,aAAaE,mCAAe,YAAY;AAC9C,KAAI,WACF,WAAU,YAAY,iBAAiB,SAAS;AAElD,MAAK,MAAM,UAAU,aACnB,gBAAe,QAAQ,iBAAiB,SAAS;CAGnD,MAAM,iBAAuB;AAC3B,iBAAe;AACf,MAAI,cACF,cAAa,cAAc;AAE7B,OAAK,MAAM,WAAW,SACpB,SAAQ,OAAO;AAEjB,aAAW;AACX,UAAQ,KAAK,EAAE;;AAGjB,SAAQ,GAAG,UAAU,SAAS;AAC9B,SAAQ,GAAG,WAAW,SAAS;AAE/B,OAAM,mBAAmB;;;;;ACnJ3B,SAAgB,cAAc,MAAqB;AACjD,oBAAmB,KAAK,CAAC,OAAO,UAAmB;EACjD,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACtE,UAAQ,MAAM,QAAQ;AACtB,UAAQ,KAAK,EAAE;GACf;;;;;ACHJ,eAAsB,gBAAgB,MAA8B;CAClE,MAAM,cAAc,QAAQ,QAAQ,KAAK;CAEzC,MAAM,QAAQ,mBADC,MAAMC,sCAAkB,YAAY,CACX;AACxC,KAAI,OAAO;AACT,QAAMC,+BAAW;GACf,MAAM;GACN,OAAO,MAAM;GACb,WAAW,MAAM;GACjB,aAAa,MAAM;GACnB,YAAY;GACb,CAAC;AACF;;AAEF,OAAMA,+BAAW;EAAE,MAAM;EAAa,YAAY;EAAM,CAAC;;;;;ACb3D,eAAe,OAAsB;CACnC,MAAM,EAAE,SAAS,SAASC,6BAAU,QAAQ,KAAK,MAAM,EAAE,CAAC;CAC1D,MAAM,cAAc,QAAQ;AAC5B,SAAQ,SAAR;EACE,KAAK;AACH,SAAM,gBAAgB,YAAY;AAClC;EACF,KAAK;AACH,SAAM,gBAAgB,YAAY;AAClC;EACF,KAAK;EACL,KAAK;EACL,KAAK;AACH,iBAAc,YAAY;AAC1B;EACF;AACE,WAAQ,MAAM,oBAAoB,UAAU;AAC5C,WAAQ,MAAMC,6BAAU;AACxB,WAAQ,KAAK,EAAE;;;AAIrB,MAAM,CAAC,OAAO,UAAmB;CAC/B,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACtE,SAAQ,MAAM,QAAQ;AACtB,SAAQ,KAAK,EAAE;EACf"}
|
package/dist/cli.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { a as discoverCommandPaths, i as loadCommandRegistry, n as findConfigPath, o as collectEventDirectoryModulePaths, r as loadConfluxConfig, t as runConflux } from "./run-conflux-DMth5S90.js";
|
|
3
|
+
import { n as parseArgs, t as CLI_USAGE } from "./parse-args-fMvnTEQ2.js";
|
|
4
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
5
|
+
import { dirname, join, relative } from "node:path";
|
|
6
|
+
import { existsSync, mkdirSync, readFileSync, watch, writeFileSync } from "node:fs";
|
|
7
|
+
|
|
8
|
+
//#region src/loader/command-paths.ts
|
|
9
|
+
function collectCommandTreeModulePaths(commandsDir) {
|
|
10
|
+
const discovered = discoverCommandPaths(commandsDir);
|
|
11
|
+
const paths = [
|
|
12
|
+
...discovered.commandPaths,
|
|
13
|
+
...discovered.globalMiddlewarePaths,
|
|
14
|
+
...discovered.directoryMiddlewarePaths.values(),
|
|
15
|
+
...discovered.commandMiddlewarePaths.values()
|
|
16
|
+
];
|
|
17
|
+
return [...new Set(paths)].sort((a, b) => a.localeCompare(b));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/build/build-bot.ts
|
|
22
|
+
async function buildBotProject(options = {}) {
|
|
23
|
+
const config = await loadConfluxConfig(options.root ?? process.cwd());
|
|
24
|
+
if (!config.entry) throw new Error("Conflux entry is not configured");
|
|
25
|
+
await loadCommandRegistry(config.commandsDir);
|
|
26
|
+
const entrypoints = [
|
|
27
|
+
config.entry,
|
|
28
|
+
...collectEventDirectoryModulePaths(config.eventsDir),
|
|
29
|
+
...collectCommandTreeModulePaths(config.commandsDir)
|
|
30
|
+
];
|
|
31
|
+
const outDir = options.outDir ?? config.outDir;
|
|
32
|
+
const relEntrypoints = entrypoints.map((path) => relative(config.root, path));
|
|
33
|
+
const relOutDir = relative(config.root, outDir);
|
|
34
|
+
const args = [
|
|
35
|
+
"build",
|
|
36
|
+
...relEntrypoints,
|
|
37
|
+
"--outdir",
|
|
38
|
+
relOutDir,
|
|
39
|
+
"--target",
|
|
40
|
+
"node",
|
|
41
|
+
"--packages",
|
|
42
|
+
"bundle",
|
|
43
|
+
"--sourcemap=linked"
|
|
44
|
+
];
|
|
45
|
+
if (options.minify !== false) args.push("--minify");
|
|
46
|
+
const result = spawnSync("bun", args, {
|
|
47
|
+
cwd: config.root,
|
|
48
|
+
stdio: "inherit"
|
|
49
|
+
});
|
|
50
|
+
if (result.error) throw result.error;
|
|
51
|
+
if (result.status !== 0) process.exit(result.status ?? 1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/cli/build-cmd.ts
|
|
56
|
+
async function runBuildCommand(root) {
|
|
57
|
+
await buildBotProject({ root });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/build/paths.ts
|
|
62
|
+
const SOURCE_MODULE_PATTERN = /\.(tsx?|mts|cts)$/i;
|
|
63
|
+
function sourceModuleToOutputPath(outDir, entry, sourcePath) {
|
|
64
|
+
return join(outDir, relative(dirname(entry), sourcePath).replace(SOURCE_MODULE_PATTERN, ".js"));
|
|
65
|
+
}
|
|
66
|
+
function sourceDirToOutputDir(outDir, entry, sourceDir) {
|
|
67
|
+
return join(outDir, relative(dirname(entry), sourceDir));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/build/resolve-built-config.ts
|
|
72
|
+
function resolveBuiltConfig(config) {
|
|
73
|
+
const builtEntry = sourceModuleToOutputPath(config.outDir, config.entry, config.entry);
|
|
74
|
+
if (!existsSync(builtEntry)) return null;
|
|
75
|
+
return {
|
|
76
|
+
...config,
|
|
77
|
+
entry: builtEntry,
|
|
78
|
+
eventsDir: sourceDirToOutputDir(config.outDir, config.entry, config.eventsDir),
|
|
79
|
+
commandsDir: sourceDirToOutputDir(config.outDir, config.entry, config.commandsDir)
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/dev/dev-out-dir.ts
|
|
85
|
+
const CONFLUX_DEV_OUT_DIR = ".conflux";
|
|
86
|
+
function resolveDevOutDir(projectRoot) {
|
|
87
|
+
return join(projectRoot, CONFLUX_DEV_OUT_DIR);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/dev/dev-bootstrap.ts
|
|
92
|
+
function ensureDevBootstrap(projectRoot, built) {
|
|
93
|
+
const dir = resolveDevOutDir(projectRoot);
|
|
94
|
+
const filePath = join(dir, "dev.mjs");
|
|
95
|
+
mkdirSync(dir, { recursive: true });
|
|
96
|
+
const source = `import { runConflux } from "@confluxjs/conflux";
|
|
97
|
+
|
|
98
|
+
await runConflux({
|
|
99
|
+
root: ${JSON.stringify(built.root)},
|
|
100
|
+
entry: ${JSON.stringify(built.entry)},
|
|
101
|
+
eventsDir: ${JSON.stringify(built.eventsDir)},
|
|
102
|
+
commandsDir: ${JSON.stringify(built.commandsDir)},
|
|
103
|
+
}).catch((error) => {
|
|
104
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
105
|
+
console.error(message);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
});
|
|
108
|
+
`;
|
|
109
|
+
if (!existsSync(filePath) || readFileSync(filePath, "utf8") !== source) writeFileSync(filePath, source, "utf8");
|
|
110
|
+
return filePath;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
//#endregion
|
|
114
|
+
//#region src/dev/watch-project.ts
|
|
115
|
+
const RESTART_DEBOUNCE_MS = 250;
|
|
116
|
+
function watchDirectory(path, onChange, watchers) {
|
|
117
|
+
try {
|
|
118
|
+
watchers.push(watch(path, { recursive: true }, (_eventType, filename) => {
|
|
119
|
+
if (filename === null) return;
|
|
120
|
+
onChange();
|
|
121
|
+
}));
|
|
122
|
+
} catch {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function watchFile(path, onChange, watchers) {
|
|
127
|
+
try {
|
|
128
|
+
watchers.push(watch(path, () => onChange()));
|
|
129
|
+
} catch {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
async function runProjectDevWatch(root) {
|
|
134
|
+
const projectRoot = root ?? process.cwd();
|
|
135
|
+
const devOutDir = resolveDevOutDir(projectRoot);
|
|
136
|
+
const bunExecutable = process.env.CONFLUX_BUN ?? "bun";
|
|
137
|
+
const watchers = [];
|
|
138
|
+
let child = null;
|
|
139
|
+
let debounceTimer = null;
|
|
140
|
+
let shuttingDown = false;
|
|
141
|
+
let building = false;
|
|
142
|
+
let rebuildQueued = false;
|
|
143
|
+
const stopChild = () => {
|
|
144
|
+
if (!child || child.killed) return;
|
|
145
|
+
child.kill("SIGTERM");
|
|
146
|
+
child = null;
|
|
147
|
+
};
|
|
148
|
+
const startChild = (entryPath) => {
|
|
149
|
+
stopChild();
|
|
150
|
+
child = spawn(bunExecutable, [entryPath], {
|
|
151
|
+
cwd: projectRoot,
|
|
152
|
+
stdio: "inherit",
|
|
153
|
+
env: {
|
|
154
|
+
...process.env,
|
|
155
|
+
NODE_ENV: "development"
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
child.on("exit", (code, signal) => {
|
|
159
|
+
if (shuttingDown) return;
|
|
160
|
+
if (signal === "SIGTERM") return;
|
|
161
|
+
if (code !== 0 && code !== null) process.exitCode = code;
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
const rebuildAndRestart = async () => {
|
|
165
|
+
if (building) {
|
|
166
|
+
rebuildQueued = true;
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
building = true;
|
|
170
|
+
try {
|
|
171
|
+
await buildBotProject({
|
|
172
|
+
root: projectRoot,
|
|
173
|
+
outDir: devOutDir,
|
|
174
|
+
minify: false
|
|
175
|
+
});
|
|
176
|
+
const built = resolveBuiltConfig({
|
|
177
|
+
...await loadConfluxConfig(projectRoot),
|
|
178
|
+
outDir: devOutDir
|
|
179
|
+
});
|
|
180
|
+
if (!built) throw new Error(`Dev build missing entry in ${devOutDir}`);
|
|
181
|
+
startChild(ensureDevBootstrap(projectRoot, built));
|
|
182
|
+
} catch (error) {
|
|
183
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
184
|
+
console.error(message);
|
|
185
|
+
process.exitCode = 1;
|
|
186
|
+
} finally {
|
|
187
|
+
building = false;
|
|
188
|
+
if (rebuildQueued) {
|
|
189
|
+
rebuildQueued = false;
|
|
190
|
+
await rebuildAndRestart();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
const scheduleRestart = () => {
|
|
195
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
196
|
+
debounceTimer = setTimeout(() => {
|
|
197
|
+
debounceTimer = null;
|
|
198
|
+
rebuildAndRestart();
|
|
199
|
+
}, RESTART_DEBOUNCE_MS);
|
|
200
|
+
};
|
|
201
|
+
const config = await loadConfluxConfig(projectRoot);
|
|
202
|
+
const watchTargets = new Set([
|
|
203
|
+
dirname(config.entry),
|
|
204
|
+
config.eventsDir,
|
|
205
|
+
config.commandsDir
|
|
206
|
+
]);
|
|
207
|
+
const configPath = findConfigPath(projectRoot);
|
|
208
|
+
if (configPath) watchFile(configPath, scheduleRestart, watchers);
|
|
209
|
+
for (const target of watchTargets) watchDirectory(target, scheduleRestart, watchers);
|
|
210
|
+
const shutdown = () => {
|
|
211
|
+
shuttingDown = true;
|
|
212
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
213
|
+
for (const watcher of watchers) watcher.close();
|
|
214
|
+
stopChild();
|
|
215
|
+
process.exit(0);
|
|
216
|
+
};
|
|
217
|
+
process.on("SIGINT", shutdown);
|
|
218
|
+
process.on("SIGTERM", shutdown);
|
|
219
|
+
await rebuildAndRestart();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
//#endregion
|
|
223
|
+
//#region src/cli/dev-cmd.ts
|
|
224
|
+
function runDevCommand(root) {
|
|
225
|
+
runProjectDevWatch(root).catch((error) => {
|
|
226
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
227
|
+
console.error(message);
|
|
228
|
+
process.exit(1);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
//#endregion
|
|
233
|
+
//#region src/cli/start-cmd.ts
|
|
234
|
+
async function runStartCommand(root) {
|
|
235
|
+
const projectRoot = root ?? process.cwd();
|
|
236
|
+
const built = resolveBuiltConfig(await loadConfluxConfig(projectRoot));
|
|
237
|
+
if (built) {
|
|
238
|
+
await runConflux({
|
|
239
|
+
root: projectRoot,
|
|
240
|
+
entry: built.entry,
|
|
241
|
+
eventsDir: built.eventsDir,
|
|
242
|
+
commandsDir: built.commandsDir,
|
|
243
|
+
production: true
|
|
244
|
+
});
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
await runConflux({
|
|
248
|
+
root: projectRoot,
|
|
249
|
+
production: true
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
//#endregion
|
|
254
|
+
//#region src/cli/run.ts
|
|
255
|
+
async function main() {
|
|
256
|
+
const { command, root } = parseArgs(process.argv.slice(2));
|
|
257
|
+
const projectRoot = root ?? void 0;
|
|
258
|
+
switch (command) {
|
|
259
|
+
case "build":
|
|
260
|
+
await runBuildCommand(projectRoot);
|
|
261
|
+
return;
|
|
262
|
+
case "start":
|
|
263
|
+
await runStartCommand(projectRoot);
|
|
264
|
+
return;
|
|
265
|
+
case "dev":
|
|
266
|
+
case "run":
|
|
267
|
+
case null:
|
|
268
|
+
runDevCommand(projectRoot);
|
|
269
|
+
return;
|
|
270
|
+
default:
|
|
271
|
+
console.error(`Unknown command: ${command}`);
|
|
272
|
+
console.error(CLI_USAGE);
|
|
273
|
+
process.exit(1);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
main().catch((error) => {
|
|
277
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
278
|
+
console.error(message);
|
|
279
|
+
process.exit(1);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
//#endregion
|
|
283
|
+
export { };
|
|
284
|
+
//# sourceMappingURL=cli.js.map
|