@decohere/cli 0.0.1-dev.100
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/commonjs/src/cli.js +30 -0
- package/commonjs/src/flux.js +38 -0
- package/commonjs/src/forge.js +37 -0
- package/commonjs/src/logger.setup.js +6 -0
- package/commonjs/src/module.factory.js +62 -0
- package/commonjs/src/product.js +28 -0
- package/commonjs/src/root.command.js +51 -0
- package/commonjs/src/root.module.js +114 -0
- package/commonjs/src/scaffold-host.js +90 -0
- package/es6/src/cli.js +26 -0
- package/es6/src/flux.js +34 -0
- package/es6/src/forge.js +33 -0
- package/es6/src/logger.setup.js +2 -0
- package/es6/src/module.factory.js +56 -0
- package/es6/src/product.js +18 -0
- package/es6/src/root.command.js +41 -0
- package/es6/src/root.module.js +104 -0
- package/es6/src/scaffold-host.js +69 -0
- package/package.json +44 -0
- package/tests/__fixtures__/hmr-slice/projects/mod/web/write-marker.mjs +6 -0
- package/types/src/cli.d.ts +2 -0
- package/types/src/flux.d.ts +2 -0
- package/types/src/forge.d.ts +2 -0
- package/types/src/logger.setup.d.ts +2 -0
- package/types/src/module.factory.d.ts +9 -0
- package/types/src/product.d.ts +15 -0
- package/types/src/root.command.d.ts +7 -0
- package/types/src/root.module.d.ts +20 -0
- package/types/src/scaffold-host.d.ts +34 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
require("./logger.setup.js");
|
|
7
|
+
const _scribe = require("@decohere/scribe");
|
|
8
|
+
const _product = require("./product.js");
|
|
9
|
+
const configIndex = process.argv.indexOf("--config-file");
|
|
10
|
+
const configFile = configIndex !== -1 ? process.argv[configIndex + 1] : undefined;
|
|
11
|
+
const logLevelIndex = process.argv.indexOf("--log-level");
|
|
12
|
+
const logLevel = logLevelIndex !== -1 ? process.argv[logLevelIndex + 1] : undefined;
|
|
13
|
+
_scribe.scribe.withPinoPretty({
|
|
14
|
+
logLevel: (0, _scribe.resolveLogLevel)(logLevel) ?? _scribe.DefaultLogLevel,
|
|
15
|
+
when: "always"
|
|
16
|
+
});
|
|
17
|
+
const logger = _scribe.scribe.logger("@decohere/cli");
|
|
18
|
+
const app = await _product.productCli.create({
|
|
19
|
+
configFile,
|
|
20
|
+
logLevel
|
|
21
|
+
});
|
|
22
|
+
let exitCode = 0;
|
|
23
|
+
try {
|
|
24
|
+
await app.run();
|
|
25
|
+
} catch (err) {
|
|
26
|
+
logger.error(err);
|
|
27
|
+
exitCode = 1;
|
|
28
|
+
} finally{
|
|
29
|
+
_scribe.scribe.flush(()=>process.exit(exitCode));
|
|
30
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
require("./logger.setup.js");
|
|
7
|
+
const _flux = require("@decohere/flux");
|
|
8
|
+
const _scribe = require("@decohere/scribe");
|
|
9
|
+
const _rootmodule = require("./root.module.js");
|
|
10
|
+
const configIndex = process.argv.indexOf("--config-file");
|
|
11
|
+
const configFile = configIndex !== -1 ? process.argv[configIndex + 1] : undefined;
|
|
12
|
+
const logLevelIndex = process.argv.indexOf("--log-level");
|
|
13
|
+
const logLevel = logLevelIndex !== -1 ? process.argv[logLevelIndex + 1] : undefined;
|
|
14
|
+
_scribe.scribe.withPinoPretty({
|
|
15
|
+
logLevel: (0, _scribe.resolveLogLevel)(logLevel) ?? _scribe.DefaultLogLevel,
|
|
16
|
+
when: "always"
|
|
17
|
+
});
|
|
18
|
+
const logger = _scribe.scribe.logger("@decohere/cli");
|
|
19
|
+
const app = await _rootmodule.RootModule.create([
|
|
20
|
+
_flux.FluxModule
|
|
21
|
+
], {
|
|
22
|
+
configFile,
|
|
23
|
+
logLevel
|
|
24
|
+
});
|
|
25
|
+
try {
|
|
26
|
+
// Route directly to the flux module — users invoke as `flux serve`, not `flux flux serve`
|
|
27
|
+
logger.trace("running flux");
|
|
28
|
+
await app.run([
|
|
29
|
+
"flux",
|
|
30
|
+
...process.argv.slice(2)
|
|
31
|
+
]);
|
|
32
|
+
// Don't force an exit: let the script's pending work (timers, open handles) finish, like
|
|
33
|
+
// `node script.js` does (#504).
|
|
34
|
+
_scribe.scribe.flush();
|
|
35
|
+
} catch (err) {
|
|
36
|
+
logger.error(err);
|
|
37
|
+
_scribe.scribe.flush(()=>process.exit(1));
|
|
38
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
require("./logger.setup.js");
|
|
7
|
+
const _forge = require("@decohere/forge");
|
|
8
|
+
const _scribe = require("@decohere/scribe");
|
|
9
|
+
const _rootmodule = require("./root.module.js");
|
|
10
|
+
const configIndex = process.argv.indexOf("--config-file");
|
|
11
|
+
const configFile = configIndex !== -1 ? process.argv[configIndex + 1] : undefined;
|
|
12
|
+
const logLevelIndex = process.argv.indexOf("--log-level");
|
|
13
|
+
const logLevel = logLevelIndex !== -1 ? process.argv[logLevelIndex + 1] : undefined;
|
|
14
|
+
_scribe.scribe.withPinoPretty({
|
|
15
|
+
logLevel: (0, _scribe.resolveLogLevel)(logLevel) ?? _scribe.DefaultLogLevel,
|
|
16
|
+
when: "always"
|
|
17
|
+
});
|
|
18
|
+
const logger = _scribe.scribe.logger("@decohere/cli");
|
|
19
|
+
const app = await _rootmodule.RootModule.create([
|
|
20
|
+
_forge.ForgeModule
|
|
21
|
+
], {
|
|
22
|
+
configFile,
|
|
23
|
+
logLevel
|
|
24
|
+
});
|
|
25
|
+
let exitCode = 0;
|
|
26
|
+
try {
|
|
27
|
+
// Route directly to the forge module — users invoke as `forge build`, not `forge forge build`
|
|
28
|
+
await app.run([
|
|
29
|
+
"forge",
|
|
30
|
+
...process.argv.slice(2)
|
|
31
|
+
]);
|
|
32
|
+
} catch (err) {
|
|
33
|
+
logger.error("Error running forge", err);
|
|
34
|
+
exitCode = 1;
|
|
35
|
+
} finally{
|
|
36
|
+
_scribe.scribe.flush(()=>process.exit(exitCode));
|
|
37
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "ModuleFactory", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return ModuleFactory;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _crucible = require("@decohere/crucible");
|
|
12
|
+
class ModuleFactory {
|
|
13
|
+
static create(module, onResponse, config) {
|
|
14
|
+
const moduleConfig = config?.[module.id];
|
|
15
|
+
const actions = {
|
|
16
|
+
...module.actions,
|
|
17
|
+
...moduleConfig?.actions
|
|
18
|
+
};
|
|
19
|
+
const commands = {
|
|
20
|
+
...module.commands,
|
|
21
|
+
...moduleConfig?.commands
|
|
22
|
+
};
|
|
23
|
+
const workspaceOptions = {
|
|
24
|
+
configFile: config?.configFile,
|
|
25
|
+
rootDir: config?.rootDir
|
|
26
|
+
};
|
|
27
|
+
let container;
|
|
28
|
+
const handler = async (_optionVals, program)=>{
|
|
29
|
+
const commandOptions = program.optsWithGlobals();
|
|
30
|
+
container = await buildContainer(module, actions, workspaceOptions);
|
|
31
|
+
const resolved = resolveActions(container, actions);
|
|
32
|
+
const response = await program.run(resolved, commandOptions);
|
|
33
|
+
onResponse(module.id, response);
|
|
34
|
+
};
|
|
35
|
+
const command = new module.command(commands, handler);
|
|
36
|
+
command.name(module.id);
|
|
37
|
+
return {
|
|
38
|
+
id: module.id,
|
|
39
|
+
command,
|
|
40
|
+
dispose: ()=>container?.[Symbol.dispose](),
|
|
41
|
+
asyncDispose: ()=>container?.[Symbol.asyncDispose]()
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function buildContainer(module, actions, workspaceOptions) {
|
|
46
|
+
const builder = new _crucible.CrucibleBuilder();
|
|
47
|
+
const workspace = await module.createWorkspace(workspaceOptions ?? {});
|
|
48
|
+
if (workspace !== null) {
|
|
49
|
+
builder.registerSingleton(workspace.constructor, workspace);
|
|
50
|
+
}
|
|
51
|
+
module.registerServices(builder);
|
|
52
|
+
for (const ActionClass of Object.values(actions)){
|
|
53
|
+
builder.registerSingleton(ActionClass);
|
|
54
|
+
}
|
|
55
|
+
return builder.build();
|
|
56
|
+
}
|
|
57
|
+
function resolveActions(container, actions) {
|
|
58
|
+
return Object.fromEntries(Object.entries(actions).map(([key, ActionClass])=>[
|
|
59
|
+
key,
|
|
60
|
+
container.resolve(ActionClass)
|
|
61
|
+
]));
|
|
62
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "productCli", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return productCli;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _flux = require("@decohere/flux");
|
|
12
|
+
const _forge = require("@decohere/forge");
|
|
13
|
+
const _rootmodule = require("./root.module.js");
|
|
14
|
+
const _scaffoldhost = require("./scaffold-host.js");
|
|
15
|
+
const modules = [
|
|
16
|
+
_forge.ForgeModule,
|
|
17
|
+
_flux.FluxModule,
|
|
18
|
+
_scaffoldhost.HostCreateModule,
|
|
19
|
+
_scaffoldhost.HostAddModule,
|
|
20
|
+
_scaffoldhost.HostAuth0Module
|
|
21
|
+
];
|
|
22
|
+
function create(options) {
|
|
23
|
+
return _rootmodule.RootModule.create(modules, options);
|
|
24
|
+
}
|
|
25
|
+
const productCli = {
|
|
26
|
+
create,
|
|
27
|
+
modules
|
|
28
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "RootCommand", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return RootCommand;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _mesh = require("@decohere/mesh");
|
|
12
|
+
const _cli = require("@decohere/nexus/cli");
|
|
13
|
+
const _commander = require("commander");
|
|
14
|
+
class RootCommand extends _cli.DecohereCommand {
|
|
15
|
+
#configFile;
|
|
16
|
+
constructor(modules, configFile){
|
|
17
|
+
super();
|
|
18
|
+
this.#configFile = configFile;
|
|
19
|
+
this.addOption(new _cli.ConfigFileOption());
|
|
20
|
+
this.addOption(new _cli.LogLevelOption());
|
|
21
|
+
this.addOption(new _cli.EnvFileOption());
|
|
22
|
+
this.addOption(new _cli.EnvFileIfExistsOption());
|
|
23
|
+
// Explicit opt-in: nothing reads a .env file unless the command line names one.
|
|
24
|
+
this.hook("preAction", (command)=>{
|
|
25
|
+
const { envFile, envFileIfExists } = command.opts();
|
|
26
|
+
if (envFile) process.loadEnvFile(envFile);
|
|
27
|
+
if (envFileIfExists) loadEnvFileIfExists(envFileIfExists);
|
|
28
|
+
});
|
|
29
|
+
for (const mod of modules){
|
|
30
|
+
this.addCommand(mod.command);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async parseAsync(argv, options) {
|
|
34
|
+
if (argv?.includes("--version") || argv?.includes("-V")) {
|
|
35
|
+
const workspace = await _mesh.WorkspaceFactory.create({
|
|
36
|
+
configFile: this.#configFile
|
|
37
|
+
});
|
|
38
|
+
const version = await workspace.getVersion() ?? "unknown";
|
|
39
|
+
process.stdout.write(`${version}\n`);
|
|
40
|
+
throw new _commander.CommanderError(0, "commander.version", version);
|
|
41
|
+
}
|
|
42
|
+
return super.parseAsync(argv, options);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function loadEnvFileIfExists(path) {
|
|
46
|
+
try {
|
|
47
|
+
process.loadEnvFile(path);
|
|
48
|
+
} catch (err) {
|
|
49
|
+
if (err.code !== "ENOENT") throw err;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "RootModule", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return RootModule;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _mesh = require("@decohere/mesh");
|
|
12
|
+
const _cli = require("@decohere/nexus/cli");
|
|
13
|
+
const _diagnostics = require("@decohere/nexus/diagnostics");
|
|
14
|
+
const _commander = require("commander");
|
|
15
|
+
const _modulefactory = require("./module.factory.js");
|
|
16
|
+
const _rootcommand = require("./root.command.js");
|
|
17
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
18
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
19
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
20
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
21
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
22
|
+
}
|
|
23
|
+
function _ts_metadata(k, v) {
|
|
24
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
25
|
+
}
|
|
26
|
+
class RootModule {
|
|
27
|
+
static async create(moduleTypes, options) {
|
|
28
|
+
const userConfig = await _mesh.UserConfigFactory.getUserConfig(options?.configFile);
|
|
29
|
+
return new RootModule(moduleTypes, {
|
|
30
|
+
...userConfig,
|
|
31
|
+
configFile: options?.configFile,
|
|
32
|
+
rootDir: options?.rootDir
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
#command;
|
|
36
|
+
#modules;
|
|
37
|
+
#lastResponse = {};
|
|
38
|
+
constructor(manifestClasses, config){
|
|
39
|
+
const modules = manifestClasses.map((ManifestClass)=>{
|
|
40
|
+
const manifest = new ManifestClass();
|
|
41
|
+
return _modulefactory.ModuleFactory.create(manifest, this.onResponse, config);
|
|
42
|
+
});
|
|
43
|
+
this.#modules = modules;
|
|
44
|
+
this.#command = new _rootcommand.RootCommand(modules, config.configFile);
|
|
45
|
+
}
|
|
46
|
+
onResponse = (_moduleId, response)=>{
|
|
47
|
+
this.#lastResponse = response;
|
|
48
|
+
};
|
|
49
|
+
async run(argv) {
|
|
50
|
+
try {
|
|
51
|
+
await this.#command.parseAsync(argv, argv ? {
|
|
52
|
+
from: "user"
|
|
53
|
+
} : undefined);
|
|
54
|
+
if (this.isBlocking(this.#lastResponse)) {
|
|
55
|
+
await untilStopSignal();
|
|
56
|
+
}
|
|
57
|
+
return this.#lastResponse;
|
|
58
|
+
} catch (error) {
|
|
59
|
+
if (this.isCommanderHelpOrVersion(error)) {
|
|
60
|
+
return _cli.CommandResponse.help();
|
|
61
|
+
}
|
|
62
|
+
throw error;
|
|
63
|
+
} finally{
|
|
64
|
+
await this[Symbol.asyncDispose]();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
get commands() {
|
|
68
|
+
return this.#command.commands;
|
|
69
|
+
}
|
|
70
|
+
[Symbol.dispose]() {
|
|
71
|
+
for (const mod of this.#modules){
|
|
72
|
+
mod.dispose?.();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async [Symbol.asyncDispose]() {
|
|
76
|
+
for (const mod of this.#modules){
|
|
77
|
+
await mod.asyncDispose?.();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
isBlocking(response) {
|
|
81
|
+
return Object.values(response).some((r)=>r?.blocking === true);
|
|
82
|
+
}
|
|
83
|
+
isCommanderHelpOrVersion(error) {
|
|
84
|
+
const isCommanderError = error instanceof _commander.CommanderError;
|
|
85
|
+
const helpCodes = [
|
|
86
|
+
"commander.helpDisplayed",
|
|
87
|
+
"commander.version",
|
|
88
|
+
"commander.help"
|
|
89
|
+
];
|
|
90
|
+
return isCommanderError && helpCodes.includes(error.code);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
RootModule = _ts_decorate([
|
|
94
|
+
_diagnostics.Trace,
|
|
95
|
+
_ts_metadata("design:type", Function),
|
|
96
|
+
_ts_metadata("design:paramtypes", [
|
|
97
|
+
Object,
|
|
98
|
+
typeof Record === "undefined" ? Object : Record
|
|
99
|
+
])
|
|
100
|
+
], RootModule);
|
|
101
|
+
/**
|
|
102
|
+
* Resolves on Ctrl+C (SIGINT) or SIGTERM (Docker, CI, process managers), so long-running
|
|
103
|
+
* commands like `flux serve` shut down cleanly either way (#520).
|
|
104
|
+
*/ function untilStopSignal() {
|
|
105
|
+
return new Promise((resolve)=>{
|
|
106
|
+
const stop = ()=>{
|
|
107
|
+
process.off("SIGINT", stop);
|
|
108
|
+
process.off("SIGTERM", stop);
|
|
109
|
+
resolve();
|
|
110
|
+
};
|
|
111
|
+
process.once("SIGINT", stop);
|
|
112
|
+
process.once("SIGTERM", stop);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get HostAddModule () {
|
|
13
|
+
return HostAddModule;
|
|
14
|
+
},
|
|
15
|
+
get HostAuth0Module () {
|
|
16
|
+
return HostAuth0Module;
|
|
17
|
+
},
|
|
18
|
+
get HostCreateModule () {
|
|
19
|
+
return HostCreateModule;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const _create = require("@decohere/create");
|
|
23
|
+
const _decorators = require("@decohere/crucible/decorators");
|
|
24
|
+
const _scaffold = require("@decohere/scaffold");
|
|
25
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
26
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
27
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
28
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
29
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
30
|
+
}
|
|
31
|
+
class HostWebapiAction extends _scaffold.WebapiAction {
|
|
32
|
+
async run(options) {
|
|
33
|
+
if (process.env.DECOHERE_BUILDER !== "1") {
|
|
34
|
+
(0, _create.runInBuilder)((0, _create.containerArgvFromHost)(process.argv));
|
|
35
|
+
}
|
|
36
|
+
return super.run(options);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
HostWebapiAction = _ts_decorate([
|
|
40
|
+
(0, _decorators.injectable)()
|
|
41
|
+
], HostWebapiAction);
|
|
42
|
+
class HostAddApiAction extends _scaffold.AddApiAction {
|
|
43
|
+
async run(options) {
|
|
44
|
+
if (process.env.DECOHERE_BUILDER !== "1") {
|
|
45
|
+
(0, _create.runInBuilder)((0, _create.containerArgvFromHost)(process.argv));
|
|
46
|
+
}
|
|
47
|
+
return super.run(options);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
HostAddApiAction = _ts_decorate([
|
|
51
|
+
(0, _decorators.injectable)()
|
|
52
|
+
], HostAddApiAction);
|
|
53
|
+
class HostCreateModule extends _scaffold.CreateModule {
|
|
54
|
+
actions = {
|
|
55
|
+
webapi: HostWebapiAction
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
class HostAddModule extends _scaffold.AddModule {
|
|
59
|
+
actions = {
|
|
60
|
+
api: HostAddApiAction
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
class HostAuth0LoginAction extends _scaffold.Auth0LoginAction {
|
|
64
|
+
async run() {
|
|
65
|
+
if (process.env.DECOHERE_BUILDER !== "1") {
|
|
66
|
+
(0, _create.runInBuilder)((0, _create.containerArgvFromHost)(process.argv));
|
|
67
|
+
}
|
|
68
|
+
return super.run();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
HostAuth0LoginAction = _ts_decorate([
|
|
72
|
+
(0, _decorators.injectable)()
|
|
73
|
+
], HostAuth0LoginAction);
|
|
74
|
+
class HostAuth0ConfigureAction extends _scaffold.Auth0ConfigureAction {
|
|
75
|
+
async run(options) {
|
|
76
|
+
if (process.env.DECOHERE_BUILDER !== "1") {
|
|
77
|
+
(0, _create.runInBuilder)((0, _create.containerArgvFromHost)(process.argv));
|
|
78
|
+
}
|
|
79
|
+
return super.run(options);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
HostAuth0ConfigureAction = _ts_decorate([
|
|
83
|
+
(0, _decorators.injectable)()
|
|
84
|
+
], HostAuth0ConfigureAction);
|
|
85
|
+
class HostAuth0Module extends _scaffold.Auth0Module {
|
|
86
|
+
actions = {
|
|
87
|
+
login: HostAuth0LoginAction,
|
|
88
|
+
configure: HostAuth0ConfigureAction
|
|
89
|
+
};
|
|
90
|
+
}
|
package/es6/src/cli.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "./logger.setup.js";
|
|
3
|
+
import { DefaultLogLevel, resolveLogLevel, scribe } from "@decohere/scribe";
|
|
4
|
+
import { productCli } from "./product.js";
|
|
5
|
+
const configIndex = process.argv.indexOf("--config-file");
|
|
6
|
+
const configFile = configIndex !== -1 ? process.argv[configIndex + 1] : undefined;
|
|
7
|
+
const logLevelIndex = process.argv.indexOf("--log-level");
|
|
8
|
+
const logLevel = logLevelIndex !== -1 ? process.argv[logLevelIndex + 1] : undefined;
|
|
9
|
+
scribe.withPinoPretty({
|
|
10
|
+
logLevel: resolveLogLevel(logLevel) ?? DefaultLogLevel,
|
|
11
|
+
when: "always"
|
|
12
|
+
});
|
|
13
|
+
const logger = scribe.logger("@decohere/cli");
|
|
14
|
+
const app = await productCli.create({
|
|
15
|
+
configFile,
|
|
16
|
+
logLevel
|
|
17
|
+
});
|
|
18
|
+
let exitCode = 0;
|
|
19
|
+
try {
|
|
20
|
+
await app.run();
|
|
21
|
+
} catch (err) {
|
|
22
|
+
logger.error(err);
|
|
23
|
+
exitCode = 1;
|
|
24
|
+
} finally{
|
|
25
|
+
scribe.flush(()=>process.exit(exitCode));
|
|
26
|
+
}
|
package/es6/src/flux.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "./logger.setup.js";
|
|
3
|
+
import { FluxModule } from "@decohere/flux";
|
|
4
|
+
import { DefaultLogLevel, resolveLogLevel, scribe } from "@decohere/scribe";
|
|
5
|
+
import { RootModule } from "./root.module.js";
|
|
6
|
+
const configIndex = process.argv.indexOf("--config-file");
|
|
7
|
+
const configFile = configIndex !== -1 ? process.argv[configIndex + 1] : undefined;
|
|
8
|
+
const logLevelIndex = process.argv.indexOf("--log-level");
|
|
9
|
+
const logLevel = logLevelIndex !== -1 ? process.argv[logLevelIndex + 1] : undefined;
|
|
10
|
+
scribe.withPinoPretty({
|
|
11
|
+
logLevel: resolveLogLevel(logLevel) ?? DefaultLogLevel,
|
|
12
|
+
when: "always"
|
|
13
|
+
});
|
|
14
|
+
const logger = scribe.logger("@decohere/cli");
|
|
15
|
+
const app = await RootModule.create([
|
|
16
|
+
FluxModule
|
|
17
|
+
], {
|
|
18
|
+
configFile,
|
|
19
|
+
logLevel
|
|
20
|
+
});
|
|
21
|
+
try {
|
|
22
|
+
// Route directly to the flux module — users invoke as `flux serve`, not `flux flux serve`
|
|
23
|
+
logger.trace("running flux");
|
|
24
|
+
await app.run([
|
|
25
|
+
"flux",
|
|
26
|
+
...process.argv.slice(2)
|
|
27
|
+
]);
|
|
28
|
+
// Don't force an exit: let the script's pending work (timers, open handles) finish, like
|
|
29
|
+
// `node script.js` does (#504).
|
|
30
|
+
scribe.flush();
|
|
31
|
+
} catch (err) {
|
|
32
|
+
logger.error(err);
|
|
33
|
+
scribe.flush(()=>process.exit(1));
|
|
34
|
+
}
|
package/es6/src/forge.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "./logger.setup.js";
|
|
3
|
+
import { ForgeModule } from "@decohere/forge";
|
|
4
|
+
import { DefaultLogLevel, resolveLogLevel, scribe } from "@decohere/scribe";
|
|
5
|
+
import { RootModule } from "./root.module.js";
|
|
6
|
+
const configIndex = process.argv.indexOf("--config-file");
|
|
7
|
+
const configFile = configIndex !== -1 ? process.argv[configIndex + 1] : undefined;
|
|
8
|
+
const logLevelIndex = process.argv.indexOf("--log-level");
|
|
9
|
+
const logLevel = logLevelIndex !== -1 ? process.argv[logLevelIndex + 1] : undefined;
|
|
10
|
+
scribe.withPinoPretty({
|
|
11
|
+
logLevel: resolveLogLevel(logLevel) ?? DefaultLogLevel,
|
|
12
|
+
when: "always"
|
|
13
|
+
});
|
|
14
|
+
const logger = scribe.logger("@decohere/cli");
|
|
15
|
+
const app = await RootModule.create([
|
|
16
|
+
ForgeModule
|
|
17
|
+
], {
|
|
18
|
+
configFile,
|
|
19
|
+
logLevel
|
|
20
|
+
});
|
|
21
|
+
let exitCode = 0;
|
|
22
|
+
try {
|
|
23
|
+
// Route directly to the forge module — users invoke as `forge build`, not `forge forge build`
|
|
24
|
+
await app.run([
|
|
25
|
+
"forge",
|
|
26
|
+
...process.argv.slice(2)
|
|
27
|
+
]);
|
|
28
|
+
} catch (err) {
|
|
29
|
+
logger.error("Error running forge", err);
|
|
30
|
+
exitCode = 1;
|
|
31
|
+
} finally{
|
|
32
|
+
scribe.flush(()=>process.exit(exitCode));
|
|
33
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { CrucibleBuilder } from "@decohere/crucible";
|
|
2
|
+
/**
|
|
3
|
+
* Wires a ModuleManifest into a fully functional ApplicationModule.
|
|
4
|
+
* Handles DI container setup, action registration/resolution, and
|
|
5
|
+
* forwarding the command response to the caller.
|
|
6
|
+
*/ export class ModuleFactory {
|
|
7
|
+
static create(module, onResponse, config) {
|
|
8
|
+
const moduleConfig = config?.[module.id];
|
|
9
|
+
const actions = {
|
|
10
|
+
...module.actions,
|
|
11
|
+
...moduleConfig?.actions
|
|
12
|
+
};
|
|
13
|
+
const commands = {
|
|
14
|
+
...module.commands,
|
|
15
|
+
...moduleConfig?.commands
|
|
16
|
+
};
|
|
17
|
+
const workspaceOptions = {
|
|
18
|
+
configFile: config?.configFile,
|
|
19
|
+
rootDir: config?.rootDir
|
|
20
|
+
};
|
|
21
|
+
let container;
|
|
22
|
+
const handler = async (_optionVals, program)=>{
|
|
23
|
+
const commandOptions = program.optsWithGlobals();
|
|
24
|
+
container = await buildContainer(module, actions, workspaceOptions);
|
|
25
|
+
const resolved = resolveActions(container, actions);
|
|
26
|
+
const response = await program.run(resolved, commandOptions);
|
|
27
|
+
onResponse(module.id, response);
|
|
28
|
+
};
|
|
29
|
+
const command = new module.command(commands, handler);
|
|
30
|
+
command.name(module.id);
|
|
31
|
+
return {
|
|
32
|
+
id: module.id,
|
|
33
|
+
command,
|
|
34
|
+
dispose: ()=>container?.[Symbol.dispose](),
|
|
35
|
+
asyncDispose: ()=>container?.[Symbol.asyncDispose]()
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function buildContainer(module, actions, workspaceOptions) {
|
|
40
|
+
const builder = new CrucibleBuilder();
|
|
41
|
+
const workspace = await module.createWorkspace(workspaceOptions ?? {});
|
|
42
|
+
if (workspace !== null) {
|
|
43
|
+
builder.registerSingleton(workspace.constructor, workspace);
|
|
44
|
+
}
|
|
45
|
+
module.registerServices(builder);
|
|
46
|
+
for (const ActionClass of Object.values(actions)){
|
|
47
|
+
builder.registerSingleton(ActionClass);
|
|
48
|
+
}
|
|
49
|
+
return builder.build();
|
|
50
|
+
}
|
|
51
|
+
function resolveActions(container, actions) {
|
|
52
|
+
return Object.fromEntries(Object.entries(actions).map(([key, ActionClass])=>[
|
|
53
|
+
key,
|
|
54
|
+
container.resolve(ActionClass)
|
|
55
|
+
]));
|
|
56
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { FluxModule } from "@decohere/flux";
|
|
2
|
+
import { ForgeModule } from "@decohere/forge";
|
|
3
|
+
import { RootModule } from "./root.module.js";
|
|
4
|
+
import { HostAddModule, HostAuth0Module, HostCreateModule } from "./scaffold-host.js";
|
|
5
|
+
const modules = [
|
|
6
|
+
ForgeModule,
|
|
7
|
+
FluxModule,
|
|
8
|
+
HostCreateModule,
|
|
9
|
+
HostAddModule,
|
|
10
|
+
HostAuth0Module
|
|
11
|
+
];
|
|
12
|
+
function create(options) {
|
|
13
|
+
return RootModule.create(modules, options);
|
|
14
|
+
}
|
|
15
|
+
/** Shipped `decohere` bin — forge, flux, create, add, auth0. */ export const productCli = {
|
|
16
|
+
create,
|
|
17
|
+
modules
|
|
18
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { WorkspaceFactory } from "@decohere/mesh";
|
|
2
|
+
import { ConfigFileOption, DecohereCommand, EnvFileIfExistsOption, EnvFileOption, LogLevelOption } from "@decohere/nexus/cli";
|
|
3
|
+
import { CommanderError } from "commander";
|
|
4
|
+
export class RootCommand extends DecohereCommand {
|
|
5
|
+
#configFile;
|
|
6
|
+
constructor(modules, configFile){
|
|
7
|
+
super();
|
|
8
|
+
this.#configFile = configFile;
|
|
9
|
+
this.addOption(new ConfigFileOption());
|
|
10
|
+
this.addOption(new LogLevelOption());
|
|
11
|
+
this.addOption(new EnvFileOption());
|
|
12
|
+
this.addOption(new EnvFileIfExistsOption());
|
|
13
|
+
// Explicit opt-in: nothing reads a .env file unless the command line names one.
|
|
14
|
+
this.hook("preAction", (command)=>{
|
|
15
|
+
const { envFile, envFileIfExists } = command.opts();
|
|
16
|
+
if (envFile) process.loadEnvFile(envFile);
|
|
17
|
+
if (envFileIfExists) loadEnvFileIfExists(envFileIfExists);
|
|
18
|
+
});
|
|
19
|
+
for (const mod of modules){
|
|
20
|
+
this.addCommand(mod.command);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async parseAsync(argv, options) {
|
|
24
|
+
if (argv?.includes("--version") || argv?.includes("-V")) {
|
|
25
|
+
const workspace = await WorkspaceFactory.create({
|
|
26
|
+
configFile: this.#configFile
|
|
27
|
+
});
|
|
28
|
+
const version = await workspace.getVersion() ?? "unknown";
|
|
29
|
+
process.stdout.write(`${version}\n`);
|
|
30
|
+
throw new CommanderError(0, "commander.version", version);
|
|
31
|
+
}
|
|
32
|
+
return super.parseAsync(argv, options);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function loadEnvFileIfExists(path) {
|
|
36
|
+
try {
|
|
37
|
+
process.loadEnvFile(path);
|
|
38
|
+
} catch (err) {
|
|
39
|
+
if (err.code !== "ENOENT") throw err;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
}
|
|
7
|
+
function _ts_metadata(k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
}
|
|
10
|
+
import { UserConfigFactory } from "@decohere/mesh";
|
|
11
|
+
import { CommandResponse } from "@decohere/nexus/cli";
|
|
12
|
+
import { Trace } from "@decohere/nexus/diagnostics";
|
|
13
|
+
import { CommanderError } from "commander";
|
|
14
|
+
import { ModuleFactory } from "./module.factory.js";
|
|
15
|
+
import { RootCommand } from "./root.command.js";
|
|
16
|
+
export class RootModule {
|
|
17
|
+
static async create(moduleTypes, options) {
|
|
18
|
+
const userConfig = await UserConfigFactory.getUserConfig(options?.configFile);
|
|
19
|
+
return new RootModule(moduleTypes, {
|
|
20
|
+
...userConfig,
|
|
21
|
+
configFile: options?.configFile,
|
|
22
|
+
rootDir: options?.rootDir
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
#command;
|
|
26
|
+
#modules;
|
|
27
|
+
#lastResponse = {};
|
|
28
|
+
constructor(manifestClasses, config){
|
|
29
|
+
const modules = manifestClasses.map((ManifestClass)=>{
|
|
30
|
+
const manifest = new ManifestClass();
|
|
31
|
+
return ModuleFactory.create(manifest, this.onResponse, config);
|
|
32
|
+
});
|
|
33
|
+
this.#modules = modules;
|
|
34
|
+
this.#command = new RootCommand(modules, config.configFile);
|
|
35
|
+
}
|
|
36
|
+
onResponse = (_moduleId, response)=>{
|
|
37
|
+
this.#lastResponse = response;
|
|
38
|
+
};
|
|
39
|
+
async run(argv) {
|
|
40
|
+
try {
|
|
41
|
+
await this.#command.parseAsync(argv, argv ? {
|
|
42
|
+
from: "user"
|
|
43
|
+
} : undefined);
|
|
44
|
+
if (this.isBlocking(this.#lastResponse)) {
|
|
45
|
+
await untilStopSignal();
|
|
46
|
+
}
|
|
47
|
+
return this.#lastResponse;
|
|
48
|
+
} catch (error) {
|
|
49
|
+
if (this.isCommanderHelpOrVersion(error)) {
|
|
50
|
+
return CommandResponse.help();
|
|
51
|
+
}
|
|
52
|
+
throw error;
|
|
53
|
+
} finally{
|
|
54
|
+
await this[Symbol.asyncDispose]();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
get commands() {
|
|
58
|
+
return this.#command.commands;
|
|
59
|
+
}
|
|
60
|
+
[Symbol.dispose]() {
|
|
61
|
+
for (const mod of this.#modules){
|
|
62
|
+
mod.dispose?.();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async [Symbol.asyncDispose]() {
|
|
66
|
+
for (const mod of this.#modules){
|
|
67
|
+
await mod.asyncDispose?.();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
isBlocking(response) {
|
|
71
|
+
return Object.values(response).some((r)=>r?.blocking === true);
|
|
72
|
+
}
|
|
73
|
+
isCommanderHelpOrVersion(error) {
|
|
74
|
+
const isCommanderError = error instanceof CommanderError;
|
|
75
|
+
const helpCodes = [
|
|
76
|
+
"commander.helpDisplayed",
|
|
77
|
+
"commander.version",
|
|
78
|
+
"commander.help"
|
|
79
|
+
];
|
|
80
|
+
return isCommanderError && helpCodes.includes(error.code);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
RootModule = _ts_decorate([
|
|
84
|
+
Trace,
|
|
85
|
+
_ts_metadata("design:type", Function),
|
|
86
|
+
_ts_metadata("design:paramtypes", [
|
|
87
|
+
Object,
|
|
88
|
+
typeof Record === "undefined" ? Object : Record
|
|
89
|
+
])
|
|
90
|
+
], RootModule);
|
|
91
|
+
/**
|
|
92
|
+
* Resolves on Ctrl+C (SIGINT) or SIGTERM (Docker, CI, process managers), so long-running
|
|
93
|
+
* commands like `flux serve` shut down cleanly either way (#520).
|
|
94
|
+
*/ function untilStopSignal() {
|
|
95
|
+
return new Promise((resolve)=>{
|
|
96
|
+
const stop = ()=>{
|
|
97
|
+
process.off("SIGINT", stop);
|
|
98
|
+
process.off("SIGTERM", stop);
|
|
99
|
+
resolve();
|
|
100
|
+
};
|
|
101
|
+
process.once("SIGINT", stop);
|
|
102
|
+
process.once("SIGTERM", stop);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
function _ts_decorate(decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
}
|
|
7
|
+
import { containerArgvFromHost, runInBuilder } from "@decohere/create";
|
|
8
|
+
import { injectable } from "@decohere/crucible/decorators";
|
|
9
|
+
import { AddApiAction, AddModule, Auth0ConfigureAction, Auth0LoginAction, Auth0Module, CreateModule, WebapiAction } from "@decohere/scaffold";
|
|
10
|
+
class HostWebapiAction extends WebapiAction {
|
|
11
|
+
async run(options) {
|
|
12
|
+
if (process.env.DECOHERE_BUILDER !== "1") {
|
|
13
|
+
runInBuilder(containerArgvFromHost(process.argv));
|
|
14
|
+
}
|
|
15
|
+
return super.run(options);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
HostWebapiAction = _ts_decorate([
|
|
19
|
+
injectable()
|
|
20
|
+
], HostWebapiAction);
|
|
21
|
+
class HostAddApiAction extends AddApiAction {
|
|
22
|
+
async run(options) {
|
|
23
|
+
if (process.env.DECOHERE_BUILDER !== "1") {
|
|
24
|
+
runInBuilder(containerArgvFromHost(process.argv));
|
|
25
|
+
}
|
|
26
|
+
return super.run(options);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
HostAddApiAction = _ts_decorate([
|
|
30
|
+
injectable()
|
|
31
|
+
], HostAddApiAction);
|
|
32
|
+
/** Host `decohere create` — Docker-delegates unless already inside the builder image. */ export class HostCreateModule extends CreateModule {
|
|
33
|
+
actions = {
|
|
34
|
+
webapi: HostWebapiAction
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** Host `decohere add` — Docker-delegates unless already inside the builder image. */ export class HostAddModule extends AddModule {
|
|
38
|
+
actions = {
|
|
39
|
+
api: HostAddApiAction
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
class HostAuth0LoginAction extends Auth0LoginAction {
|
|
43
|
+
async run() {
|
|
44
|
+
if (process.env.DECOHERE_BUILDER !== "1") {
|
|
45
|
+
runInBuilder(containerArgvFromHost(process.argv));
|
|
46
|
+
}
|
|
47
|
+
return super.run();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
HostAuth0LoginAction = _ts_decorate([
|
|
51
|
+
injectable()
|
|
52
|
+
], HostAuth0LoginAction);
|
|
53
|
+
class HostAuth0ConfigureAction extends Auth0ConfigureAction {
|
|
54
|
+
async run(options) {
|
|
55
|
+
if (process.env.DECOHERE_BUILDER !== "1") {
|
|
56
|
+
runInBuilder(containerArgvFromHost(process.argv));
|
|
57
|
+
}
|
|
58
|
+
return super.run(options);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
HostAuth0ConfigureAction = _ts_decorate([
|
|
62
|
+
injectable()
|
|
63
|
+
], HostAuth0ConfigureAction);
|
|
64
|
+
/** Host `decohere auth0` — Docker-delegates unless already inside the builder image. */ export class HostAuth0Module extends Auth0Module {
|
|
65
|
+
actions = {
|
|
66
|
+
login: HostAuth0LoginAction,
|
|
67
|
+
configure: HostAuth0ConfigureAction
|
|
68
|
+
};
|
|
69
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@decohere/cli",
|
|
3
|
+
"version": "0.0.1-dev.100",
|
|
4
|
+
"description": "CLI for the Decohere toolchain — build, serve, publish, and manage TypeScript monorepos",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"typescript",
|
|
7
|
+
"cli",
|
|
8
|
+
"monorepo",
|
|
9
|
+
"build",
|
|
10
|
+
"decohere"
|
|
11
|
+
],
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"author": "Typesmiths",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./types/src/index.d.ts",
|
|
18
|
+
"import": "./es6/src/index.js",
|
|
19
|
+
"require": "./commonjs/src/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"bin": {
|
|
23
|
+
"decohere": "./es6/src/cli.js",
|
|
24
|
+
"forge": "./es6/src/forge.js",
|
|
25
|
+
"flux": "./es6/src/flux.js"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@decohere/create": "0.0.1-dev.100",
|
|
32
|
+
"@decohere/crucible": "0.0.1-dev.100",
|
|
33
|
+
"@decohere/flux": "0.0.1-dev.100",
|
|
34
|
+
"@decohere/forge": "0.0.1-dev.100",
|
|
35
|
+
"@decohere/mesh": "0.0.1-dev.100",
|
|
36
|
+
"@decohere/nexus": "0.0.1-dev.100",
|
|
37
|
+
"@decohere/scaffold": "0.0.1-dev.100",
|
|
38
|
+
"@decohere/scribe": "0.0.1-dev.100",
|
|
39
|
+
"@decohere/scribe-pino": "0.0.1-dev.100",
|
|
40
|
+
"commander": "^13.1.0",
|
|
41
|
+
"pino-pretty": "^13.1.3"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {}
|
|
44
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ApplicationModule, CommandResponse, ModuleManifest } from "@decohere/nexus/cli";
|
|
2
|
+
/**
|
|
3
|
+
* Wires a ModuleManifest into a fully functional ApplicationModule.
|
|
4
|
+
* Handles DI container setup, action registration/resolution, and
|
|
5
|
+
* forwarding the command response to the caller.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ModuleFactory {
|
|
8
|
+
static create(module: ModuleManifest, onResponse: (moduleId: string, response: CommandResponse) => void, config?: Record<string, unknown>): ApplicationModule;
|
|
9
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FluxModule } from "@decohere/flux";
|
|
2
|
+
import { ForgeModule } from "@decohere/forge";
|
|
3
|
+
import { RootModule } from "./root.module.js";
|
|
4
|
+
import { HostAddModule, HostAuth0Module, HostCreateModule } from "./scaffold-host.js";
|
|
5
|
+
declare function create(options?: {
|
|
6
|
+
configFile?: string;
|
|
7
|
+
logLevel?: string;
|
|
8
|
+
rootDir?: string;
|
|
9
|
+
}): Promise<RootModule>;
|
|
10
|
+
/** Shipped `decohere` bin — forge, flux, create, add, auth0. */
|
|
11
|
+
export declare const productCli: {
|
|
12
|
+
create: typeof create;
|
|
13
|
+
modules: readonly [typeof ForgeModule, typeof FluxModule, typeof HostCreateModule, typeof HostAddModule, typeof HostAuth0Module];
|
|
14
|
+
};
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ApplicationModule, DecohereCommand } from "@decohere/nexus/cli";
|
|
2
|
+
import { type ParseOptions } from "commander";
|
|
3
|
+
export declare class RootCommand extends DecohereCommand {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(modules: ApplicationModule[], configFile?: string);
|
|
6
|
+
parseAsync(argv?: readonly string[], options?: ParseOptions): Promise<this>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Actions, ModuleManifest } from "@decohere/nexus/cli";
|
|
2
|
+
import { CommandResponse } from "@decohere/nexus/cli";
|
|
3
|
+
import type { Constructable } from "@decohere/nexus/reflection";
|
|
4
|
+
import type { Command } from "commander";
|
|
5
|
+
export declare class RootModule {
|
|
6
|
+
#private;
|
|
7
|
+
static create(moduleTypes: readonly Constructable<ModuleManifest>[], options?: {
|
|
8
|
+
configFile?: string;
|
|
9
|
+
logLevel?: string;
|
|
10
|
+
rootDir?: string;
|
|
11
|
+
}): Promise<RootModule>;
|
|
12
|
+
private constructor();
|
|
13
|
+
private onResponse;
|
|
14
|
+
run<TActions extends Actions>(argv?: string[]): Promise<CommandResponse<TActions>>;
|
|
15
|
+
get commands(): Command[];
|
|
16
|
+
[Symbol.dispose](): void;
|
|
17
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
18
|
+
private isBlocking;
|
|
19
|
+
private isCommanderHelpOrVersion;
|
|
20
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ActionResponse } from "@decohere/nexus/cli";
|
|
2
|
+
import { AddApiAction, type AddApiOptions, AddModule, Auth0ConfigureAction, type Auth0ConfigureOptions, Auth0LoginAction, Auth0Module, CreateModule, WebapiAction, type WebapiOptions } from "@decohere/scaffold";
|
|
3
|
+
declare class HostWebapiAction extends WebapiAction {
|
|
4
|
+
run(options: WebapiOptions): Promise<ActionResponse>;
|
|
5
|
+
}
|
|
6
|
+
declare class HostAddApiAction extends AddApiAction {
|
|
7
|
+
run(options: AddApiOptions): Promise<ActionResponse>;
|
|
8
|
+
}
|
|
9
|
+
/** Host `decohere create` — Docker-delegates unless already inside the builder image. */
|
|
10
|
+
export declare class HostCreateModule extends CreateModule {
|
|
11
|
+
readonly actions: {
|
|
12
|
+
webapi: typeof HostWebapiAction;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/** Host `decohere add` — Docker-delegates unless already inside the builder image. */
|
|
16
|
+
export declare class HostAddModule extends AddModule {
|
|
17
|
+
readonly actions: {
|
|
18
|
+
api: typeof HostAddApiAction;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
declare class HostAuth0LoginAction extends Auth0LoginAction {
|
|
22
|
+
run(): Promise<ActionResponse>;
|
|
23
|
+
}
|
|
24
|
+
declare class HostAuth0ConfigureAction extends Auth0ConfigureAction {
|
|
25
|
+
run(options: Auth0ConfigureOptions): Promise<ActionResponse>;
|
|
26
|
+
}
|
|
27
|
+
/** Host `decohere auth0` — Docker-delegates unless already inside the builder image. */
|
|
28
|
+
export declare class HostAuth0Module extends Auth0Module {
|
|
29
|
+
readonly actions: {
|
|
30
|
+
login: typeof HostAuth0LoginAction;
|
|
31
|
+
configure: typeof HostAuth0ConfigureAction;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export {};
|