@atolljs/cli 0.0.0-stage → 0.1.4
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/LICENSE +21 -0
- package/README.md +41 -2
- package/dist/cli.js +2261 -0
- package/package.json +34 -4
- package/src/cli.ts +97 -0
- package/src/commands.ts +626 -0
- package/src/files.ts +43 -0
- package/src/io.ts +127 -0
- package/src/parse.ts +53 -0
- package/src/project.ts +132 -0
- package/src/templates.ts +1632 -0
package/package.json
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atolljs/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "atoll — scaffold worker pools, shared-memory contracts, and framework islands (experimental)",
|
|
5
|
+
"homepage": "https://jwhenry3.github.io/atolljs/consumer/quickstart/",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"atoll": "./dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
"./package.json": "./package.json"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"src",
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "esbuild src/cli.ts --bundle --format=esm --platform=node --target=node20.12 --outfile=dist/cli.js"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=20.12"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public",
|
|
25
|
+
"registry": "https://registry.npmjs.org"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/jwhenry3/atolljs",
|
|
30
|
+
"directory": "packages/cli"
|
|
31
|
+
},
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/jwhenry3/atolljs/issues"
|
|
34
|
+
},
|
|
35
|
+
"license": "MIT"
|
|
36
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `atoll` — bootstrap multithreading in an app: worker pools, shared-memory
|
|
4
|
+
* contracts, framework islands, and a doctor that checks the setup.
|
|
5
|
+
*
|
|
6
|
+
* Sources stay TypeScript — dev runs this entry via Node's type stripping
|
|
7
|
+
* (`npm run atoll`, vitest, CI smoke). The *published* bin is a bundled
|
|
8
|
+
* dist/cli.js: Node refuses type stripping inside node_modules, which is
|
|
9
|
+
* where npx installs packages. Keep relative imports' `.ts` extensions
|
|
10
|
+
* explicit and stay inside erasable syntax so both paths keep working;
|
|
11
|
+
* `npm run build` (esbuild) regenerates the bundle.
|
|
12
|
+
*/
|
|
13
|
+
import { consoleIo, type Fmt, type Io } from './io.ts';
|
|
14
|
+
import { hasFlag, parseArgs } from './parse.ts';
|
|
15
|
+
import { runAdd, runCreate, runDoctor, runInit, type Ctx } from './commands.ts';
|
|
16
|
+
|
|
17
|
+
const HELP = (fmt: Fmt) => `${fmt.strong('atoll')} — bootstrap multithreading ${fmt.dim('(experimental)')}
|
|
18
|
+
|
|
19
|
+
${fmt.accent('atoll new <dir>')} [--framework react|vue|solid|svelte|node] [--pm npm]
|
|
20
|
+
Scaffold a fresh app — vite shell + a worker-rendered island,
|
|
21
|
+
or a tsx Node service with a pooled worker.
|
|
22
|
+
|
|
23
|
+
${fmt.accent('atoll init')} [--name app] [--force]
|
|
24
|
+
Wire Atoll into the current project: hardened .npmrc, package
|
|
25
|
+
install, and a contract + worker + client spine under src/atoll/.
|
|
26
|
+
|
|
27
|
+
${fmt.accent('atoll add [framework] <kind> [variant] [name]')}
|
|
28
|
+
worker pool + typed client (+ framework bindings on UI projects)
|
|
29
|
+
memory shared-memory contract
|
|
30
|
+
island worker-rendered UI — facade (contract + lazy import) | mono
|
|
31
|
+
service nestjs: @AtollService class facade + pool module + worker
|
|
32
|
+
method nestjs: @AtollTask method-level offload
|
|
33
|
+
module nestjs: registerPool boundary module + worker entry
|
|
34
|
+
housed nestjs: route subtree served entirely inside workers
|
|
35
|
+
route nextjs: api route pool — task | client variants
|
|
36
|
+
component nextjs: 'use client' hooks component over a pool
|
|
37
|
+
instrumentation nextjs: server bootstrap that warms route pools
|
|
38
|
+
|
|
39
|
+
Frameworks: react vue solid svelte angular nestjs nextjs node
|
|
40
|
+
[--dir <path>] [--memory <name>|--no-memory] [--variant <v>] [--force]
|
|
41
|
+
|
|
42
|
+
${fmt.accent('atoll doctor')} [--fix]
|
|
43
|
+
Check the setup — deps, lockfile, .npmrc policy, bundler-detectable
|
|
44
|
+
worker entries, COOP/COEP headers. --fix writes a hardened .npmrc.
|
|
45
|
+
|
|
46
|
+
${fmt.dim(`flags: --yes/-y accepts defaults, --force overwrites existing files,
|
|
47
|
+
--no-install skips dependency installation`)}
|
|
48
|
+
`;
|
|
49
|
+
|
|
50
|
+
const DISCLAIMER =
|
|
51
|
+
'atoll is experimental — report bugs or feedback: ' +
|
|
52
|
+
'https://github.com/jwhenry3/atolljs/issues';
|
|
53
|
+
|
|
54
|
+
export async function runCli(argv: readonly string[], io: Io, cwd: string): Promise<number> {
|
|
55
|
+
const args = parseArgs(argv);
|
|
56
|
+
const ctx: Ctx = { io, cwd, args };
|
|
57
|
+
const [cmd] = args._;
|
|
58
|
+
|
|
59
|
+
io.warn(io.fmt.dim(DISCLAIMER));
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
switch (cmd) {
|
|
63
|
+
case 'new':
|
|
64
|
+
case 'create':
|
|
65
|
+
return await runCreate(ctx);
|
|
66
|
+
case 'init':
|
|
67
|
+
return await runInit(ctx);
|
|
68
|
+
case 'add':
|
|
69
|
+
return await runAdd(ctx);
|
|
70
|
+
case 'doctor':
|
|
71
|
+
return runDoctor(ctx);
|
|
72
|
+
case 'help':
|
|
73
|
+
case undefined:
|
|
74
|
+
io.print(HELP(io.fmt));
|
|
75
|
+
return cmd === undefined ? 0 : 0;
|
|
76
|
+
default:
|
|
77
|
+
io.error(`unknown command ${io.fmt.accent(cmd)}`);
|
|
78
|
+
io.print(HELP(io.fmt));
|
|
79
|
+
return 1;
|
|
80
|
+
}
|
|
81
|
+
} catch (e) {
|
|
82
|
+
io.error(e instanceof Error ? e.message : String(e));
|
|
83
|
+
return 1;
|
|
84
|
+
} finally {
|
|
85
|
+
io.close();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Entry guard — the file is also imported by tests, which pass their own io.
|
|
90
|
+
const invokedAs =
|
|
91
|
+
process.argv[1] && import.meta.url.endsWith(process.argv[1].replaceAll('\\', '/'));
|
|
92
|
+
if (invokedAs) {
|
|
93
|
+
const args = parseArgs(process.argv.slice(2));
|
|
94
|
+
const interactive = process.stdin.isTTY === true && !hasFlag(args, 'yes', 'y');
|
|
95
|
+
const code = await runCli(process.argv.slice(2), consoleIo(interactive), process.cwd());
|
|
96
|
+
process.exit(code);
|
|
97
|
+
}
|