@decohere/cli 0.0.1-dev.125 → 0.0.1-dev.5

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 ADDED
@@ -0,0 +1 @@
1
+ Placeholder package for npm trusted-publisher setup. Ignore this version; CI publishes the real CLI.
package/package.json CHANGED
@@ -1,54 +1,14 @@
1
1
  {
2
2
  "name": "@decohere/cli",
3
- "version": "0.0.1-dev.125",
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
- "homepage": "https://github.com/typesmiths/decohere/tree/main/projects/cli#readme",
13
- "bugs": {
14
- "url": "https://github.com/typesmiths/decohere/issues"
15
- },
16
- "repository": {
17
- "type": "git",
18
- "url": "git+https://github.com/typesmiths/decohere.git",
19
- "directory": "projects/cli"
20
- },
3
+ "version": "0.0.1-dev.5",
4
+ "description": "Bootstrap placeholder so trusted publishing can be configured. Real artifacts ship from CI.",
21
5
  "license": "ISC",
22
6
  "author": "Typesmiths",
23
- "type": "module",
24
- "exports": {
25
- ".": {
26
- "types": "./types/src/index.d.ts",
27
- "import": "./es6/src/index.js",
28
- "require": "./commonjs/src/index.js"
29
- }
30
- },
31
- "bin": {
32
- "decohere": "./es6/src/cli.js",
33
- "forge": "./es6/src/forge.js",
34
- "flux": "./es6/src/flux.js"
35
- },
36
- "scripts": {
37
- "test": "echo \"Error: no test specified\" && exit 1"
38
- },
39
- "dependencies": {
40
- "@decohere/core": "0.0.1-dev.125",
41
- "@decohere/create": "0.0.1-dev.125",
42
- "@decohere/crucible": "0.0.1-dev.125",
43
- "@decohere/devkit": "0.0.1-dev.125",
44
- "@decohere/flux": "0.0.1-dev.125",
45
- "@decohere/forge": "0.0.1-dev.125",
46
- "@decohere/scaffold": "0.0.1-dev.125",
47
- "@decohere/scribe": "0.0.1-dev.125",
48
- "@decohere/scribe-pino": "0.0.1-dev.125",
49
- "@decohere/workspace": "0.0.1-dev.125",
50
- "commander": "^13.1.0",
51
- "pino-pretty": "^13.1.3"
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/typesmiths/decohere.git"
52
10
  },
53
- "devDependencies": {}
11
+ "publishConfig": {
12
+ "access": "public"
13
+ }
54
14
  }
package/LICENSE DELETED
@@ -1,15 +0,0 @@
1
- ISC License
2
-
3
- Copyright (c) 2025-2026 Typesmiths
4
-
5
- Permission to use, copy, modify, and/or distribute this software for any
6
- purpose with or without fee is hereby granted, provided that the above
7
- copyright notice and this permission notice appear in all copies.
8
-
9
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@@ -1,31 +0,0 @@
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 _loglevel = require("./log-level.js");
9
- const _product = require("./product.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, _loglevel.cliLogLevel)(logLevel),
16
- when: "always"
17
- });
18
- const logger = _scribe.scribe.logger("@decohere/cli");
19
- const app = await _product.productCli.create({
20
- configFile,
21
- logLevel
22
- });
23
- let exitCode = 0;
24
- try {
25
- await app.run();
26
- } catch (err) {
27
- logger.error(err);
28
- exitCode = 1;
29
- } finally{
30
- _scribe.scribe.flush(()=>process.exit(exitCode));
31
- }
@@ -1,39 +0,0 @@
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 _loglevel = require("./log-level.js");
10
- const _rootmodule = require("./root.module.js");
11
- const configIndex = process.argv.indexOf("--config-file");
12
- const configFile = configIndex !== -1 ? process.argv[configIndex + 1] : undefined;
13
- const logLevelIndex = process.argv.indexOf("--log-level");
14
- const logLevel = logLevelIndex !== -1 ? process.argv[logLevelIndex + 1] : undefined;
15
- _scribe.scribe.withPinoPretty({
16
- logLevel: (0, _loglevel.cliLogLevel)(logLevel),
17
- when: "always"
18
- });
19
- const logger = _scribe.scribe.logger("@decohere/cli");
20
- const app = await _rootmodule.RootModule.create([
21
- _flux.FluxModule
22
- ], {
23
- configFile,
24
- logLevel
25
- });
26
- try {
27
- // Route directly to the flux module — users invoke as `flux serve`, not `flux flux serve`
28
- logger.trace("running flux");
29
- await app.run([
30
- "flux",
31
- ...process.argv.slice(2)
32
- ]);
33
- // Don't force an exit: let the script's pending work (timers, open handles) finish, like
34
- // `node script.js` does (#504).
35
- _scribe.scribe.flush();
36
- } catch (err) {
37
- logger.error(err);
38
- _scribe.scribe.flush(()=>process.exit(1));
39
- }
@@ -1,38 +0,0 @@
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 _loglevel = require("./log-level.js");
10
- const _rootmodule = require("./root.module.js");
11
- const configIndex = process.argv.indexOf("--config-file");
12
- const configFile = configIndex !== -1 ? process.argv[configIndex + 1] : undefined;
13
- const logLevelIndex = process.argv.indexOf("--log-level");
14
- const logLevel = logLevelIndex !== -1 ? process.argv[logLevelIndex + 1] : undefined;
15
- _scribe.scribe.withPinoPretty({
16
- logLevel: (0, _loglevel.cliLogLevel)(logLevel),
17
- when: "always"
18
- });
19
- const logger = _scribe.scribe.logger("@decohere/cli");
20
- const app = await _rootmodule.RootModule.create([
21
- _forge.ForgeModule
22
- ], {
23
- configFile,
24
- logLevel
25
- });
26
- let exitCode = 0;
27
- try {
28
- // Route directly to the forge module — users invoke as `forge build`, not `forge forge build`
29
- await app.run([
30
- "forge",
31
- ...process.argv.slice(2)
32
- ]);
33
- } catch (err) {
34
- logger.error("Error running forge", err);
35
- exitCode = 1;
36
- } finally{
37
- _scribe.scribe.flush(()=>process.exit(exitCode));
38
- }
@@ -1,14 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- Object.defineProperty(exports, "cliLogLevel", {
6
- enumerable: true,
7
- get: function() {
8
- return cliLogLevel;
9
- }
10
- });
11
- const _scribe = require("@decohere/scribe");
12
- function cliLogLevel(flag) {
13
- return (0, _scribe.resolveLogLevel)(flag) ?? (process.env.FORGE_TRACE != null ? "trace" : _scribe.DefaultLogLevel);
14
- }
@@ -1,6 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- require("@decohere/scribe-pino");
6
- require("pino-pretty");
@@ -1,62 +0,0 @@
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.ServiceContainerBuilder();
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
- }
@@ -1,28 +0,0 @@
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
- };
@@ -1,51 +0,0 @@
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 _workspace = require("@decohere/workspace");
12
- const _cli = require("@decohere/devkit/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 _workspace.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
- }
@@ -1,132 +0,0 @@
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 _workspace = require("@decohere/workspace");
12
- const _cli = require("@decohere/devkit/cli");
13
- const _diagnostics = require("@decohere/devkit/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 _workspace.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
- #stop;
39
- constructor(manifestClasses, config){
40
- const modules = manifestClasses.map((ManifestClass)=>{
41
- const manifest = new ManifestClass();
42
- return _modulefactory.ModuleFactory.create(manifest, this.onResponse, config);
43
- });
44
- this.#modules = modules;
45
- this.#command = new _rootcommand.RootCommand(modules, config.configFile);
46
- // Before the command runs, not after it returns: a stop signal while `flux serve` boots
47
- // (`docker stop` during start-up) is held for the shutdown below instead of killing the
48
- // process before anything is disposed.
49
- this.#command.hook("preAction", (_root, actionCommand)=>{
50
- if (actionCommand instanceof _cli.DecohereCommand && actionCommand.runsUntilStopped(actionCommand.opts())) {
51
- this.#stop ??= stopSignal();
52
- }
53
- });
54
- }
55
- onResponse = (_moduleId, response)=>{
56
- this.#lastResponse = response;
57
- };
58
- async run(argv) {
59
- try {
60
- await this.#command.parseAsync(argv, argv ? {
61
- from: "user"
62
- } : undefined);
63
- if (this.isBlocking(this.#lastResponse)) {
64
- this.#stop ??= stopSignal();
65
- await this.#stop.received;
66
- }
67
- return this.#lastResponse;
68
- } catch (error) {
69
- if (this.isCommanderHelpOrVersion(error)) {
70
- return _cli.CommandResponse.help();
71
- }
72
- throw error;
73
- } finally{
74
- this.#stop?.dispose();
75
- this.#stop = undefined;
76
- await this[Symbol.asyncDispose]();
77
- }
78
- }
79
- get commands() {
80
- return this.#command.commands;
81
- }
82
- [Symbol.dispose]() {
83
- for (const mod of this.#modules){
84
- mod.dispose?.();
85
- }
86
- }
87
- async [Symbol.asyncDispose]() {
88
- for (const mod of this.#modules){
89
- await mod.asyncDispose?.();
90
- }
91
- }
92
- isBlocking(response) {
93
- return Object.values(response).some((r)=>r?.blocking === true);
94
- }
95
- isCommanderHelpOrVersion(error) {
96
- const isCommanderError = error instanceof _commander.CommanderError;
97
- const helpCodes = [
98
- "commander.helpDisplayed",
99
- "commander.version",
100
- "commander.help"
101
- ];
102
- return isCommanderError && helpCodes.includes(error.code);
103
- }
104
- }
105
- RootModule = _ts_decorate([
106
- _diagnostics.Trace,
107
- _ts_metadata("design:type", Function),
108
- _ts_metadata("design:paramtypes", [
109
- Object,
110
- typeof Record === "undefined" ? Object : Record
111
- ])
112
- ], RootModule);
113
- function stopSignal() {
114
- let onSignal = ()=>{};
115
- const received = new Promise((resolve)=>{
116
- onSignal = resolve;
117
- });
118
- const stop = ()=>{
119
- dispose();
120
- onSignal();
121
- };
122
- const dispose = ()=>{
123
- process.off("SIGINT", stop);
124
- process.off("SIGTERM", stop);
125
- };
126
- process.once("SIGINT", stop);
127
- process.once("SIGTERM", stop);
128
- return {
129
- received,
130
- dispose
131
- };
132
- }
@@ -1,90 +0,0 @@
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 DELETED
@@ -1,27 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./logger.setup.js";
3
- import { scribe } from "@decohere/scribe";
4
- import { cliLogLevel } from "./log-level.js";
5
- import { productCli } from "./product.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: cliLogLevel(logLevel),
12
- when: "always"
13
- });
14
- const logger = scribe.logger("@decohere/cli");
15
- const app = await productCli.create({
16
- configFile,
17
- logLevel
18
- });
19
- let exitCode = 0;
20
- try {
21
- await app.run();
22
- } catch (err) {
23
- logger.error(err);
24
- exitCode = 1;
25
- } finally{
26
- scribe.flush(()=>process.exit(exitCode));
27
- }
package/es6/src/flux.js DELETED
@@ -1,35 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./logger.setup.js";
3
- import { FluxModule } from "@decohere/flux";
4
- import { scribe } from "@decohere/scribe";
5
- import { cliLogLevel } from "./log-level.js";
6
- import { RootModule } from "./root.module.js";
7
- const configIndex = process.argv.indexOf("--config-file");
8
- const configFile = configIndex !== -1 ? process.argv[configIndex + 1] : undefined;
9
- const logLevelIndex = process.argv.indexOf("--log-level");
10
- const logLevel = logLevelIndex !== -1 ? process.argv[logLevelIndex + 1] : undefined;
11
- scribe.withPinoPretty({
12
- logLevel: cliLogLevel(logLevel),
13
- when: "always"
14
- });
15
- const logger = scribe.logger("@decohere/cli");
16
- const app = await RootModule.create([
17
- FluxModule
18
- ], {
19
- configFile,
20
- logLevel
21
- });
22
- try {
23
- // Route directly to the flux module — users invoke as `flux serve`, not `flux flux serve`
24
- logger.trace("running flux");
25
- await app.run([
26
- "flux",
27
- ...process.argv.slice(2)
28
- ]);
29
- // Don't force an exit: let the script's pending work (timers, open handles) finish, like
30
- // `node script.js` does (#504).
31
- scribe.flush();
32
- } catch (err) {
33
- logger.error(err);
34
- scribe.flush(()=>process.exit(1));
35
- }
package/es6/src/forge.js DELETED
@@ -1,34 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./logger.setup.js";
3
- import { ForgeModule } from "@decohere/forge";
4
- import { scribe } from "@decohere/scribe";
5
- import { cliLogLevel } from "./log-level.js";
6
- import { RootModule } from "./root.module.js";
7
- const configIndex = process.argv.indexOf("--config-file");
8
- const configFile = configIndex !== -1 ? process.argv[configIndex + 1] : undefined;
9
- const logLevelIndex = process.argv.indexOf("--log-level");
10
- const logLevel = logLevelIndex !== -1 ? process.argv[logLevelIndex + 1] : undefined;
11
- scribe.withPinoPretty({
12
- logLevel: cliLogLevel(logLevel),
13
- when: "always"
14
- });
15
- const logger = scribe.logger("@decohere/cli");
16
- const app = await RootModule.create([
17
- ForgeModule
18
- ], {
19
- configFile,
20
- logLevel
21
- });
22
- let exitCode = 0;
23
- try {
24
- // Route directly to the forge module — users invoke as `forge build`, not `forge forge build`
25
- await app.run([
26
- "forge",
27
- ...process.argv.slice(2)
28
- ]);
29
- } catch (err) {
30
- logger.error("Error running forge", err);
31
- exitCode = 1;
32
- } finally{
33
- scribe.flush(()=>process.exit(exitCode));
34
- }
@@ -1,7 +0,0 @@
1
- import { DefaultLogLevel, resolveLogLevel } from "@decohere/scribe";
2
- /**
3
- * The level a bin logs at: `--log-level`, then a level from the environment, then `trace` when
4
- * FORGE_TRACE is set (so `@trace` timings show), then scribe's default.
5
- */ export function cliLogLevel(flag) {
6
- return resolveLogLevel(flag) ?? (process.env.FORGE_TRACE != null ? "trace" : DefaultLogLevel);
7
- }
@@ -1,2 +0,0 @@
1
- import "@decohere/scribe-pino";
2
- import "pino-pretty";
@@ -1,56 +0,0 @@
1
- import { ServiceContainerBuilder } 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 ServiceContainerBuilder();
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
- }
@@ -1,18 +0,0 @@
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
- };
@@ -1,41 +0,0 @@
1
- import { WorkspaceFactory } from "@decohere/workspace";
2
- import { ConfigFileOption, DecohereCommand, EnvFileIfExistsOption, EnvFileOption, LogLevelOption } from "@decohere/devkit/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
- }
@@ -1,122 +0,0 @@
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/workspace";
11
- import { CommandResponse, DecohereCommand } from "@decohere/devkit/cli";
12
- import { Trace } from "@decohere/devkit/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
- #stop;
29
- constructor(manifestClasses, config){
30
- const modules = manifestClasses.map((ManifestClass)=>{
31
- const manifest = new ManifestClass();
32
- return ModuleFactory.create(manifest, this.onResponse, config);
33
- });
34
- this.#modules = modules;
35
- this.#command = new RootCommand(modules, config.configFile);
36
- // Before the command runs, not after it returns: a stop signal while `flux serve` boots
37
- // (`docker stop` during start-up) is held for the shutdown below instead of killing the
38
- // process before anything is disposed.
39
- this.#command.hook("preAction", (_root, actionCommand)=>{
40
- if (actionCommand instanceof DecohereCommand && actionCommand.runsUntilStopped(actionCommand.opts())) {
41
- this.#stop ??= stopSignal();
42
- }
43
- });
44
- }
45
- onResponse = (_moduleId, response)=>{
46
- this.#lastResponse = response;
47
- };
48
- async run(argv) {
49
- try {
50
- await this.#command.parseAsync(argv, argv ? {
51
- from: "user"
52
- } : undefined);
53
- if (this.isBlocking(this.#lastResponse)) {
54
- this.#stop ??= stopSignal();
55
- await this.#stop.received;
56
- }
57
- return this.#lastResponse;
58
- } catch (error) {
59
- if (this.isCommanderHelpOrVersion(error)) {
60
- return CommandResponse.help();
61
- }
62
- throw error;
63
- } finally{
64
- this.#stop?.dispose();
65
- this.#stop = undefined;
66
- await this[Symbol.asyncDispose]();
67
- }
68
- }
69
- get commands() {
70
- return this.#command.commands;
71
- }
72
- [Symbol.dispose]() {
73
- for (const mod of this.#modules){
74
- mod.dispose?.();
75
- }
76
- }
77
- async [Symbol.asyncDispose]() {
78
- for (const mod of this.#modules){
79
- await mod.asyncDispose?.();
80
- }
81
- }
82
- isBlocking(response) {
83
- return Object.values(response).some((r)=>r?.blocking === true);
84
- }
85
- isCommanderHelpOrVersion(error) {
86
- const isCommanderError = error instanceof CommanderError;
87
- const helpCodes = [
88
- "commander.helpDisplayed",
89
- "commander.version",
90
- "commander.help"
91
- ];
92
- return isCommanderError && helpCodes.includes(error.code);
93
- }
94
- }
95
- RootModule = _ts_decorate([
96
- Trace,
97
- _ts_metadata("design:type", Function),
98
- _ts_metadata("design:paramtypes", [
99
- Object,
100
- typeof Record === "undefined" ? Object : Record
101
- ])
102
- ], RootModule);
103
- function stopSignal() {
104
- let onSignal = ()=>{};
105
- const received = new Promise((resolve)=>{
106
- onSignal = resolve;
107
- });
108
- const stop = ()=>{
109
- dispose();
110
- onSignal();
111
- };
112
- const dispose = ()=>{
113
- process.off("SIGINT", stop);
114
- process.off("SIGTERM", stop);
115
- };
116
- process.once("SIGINT", stop);
117
- process.once("SIGTERM", stop);
118
- return {
119
- received,
120
- dispose
121
- };
122
- }
@@ -1,69 +0,0 @@
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
- }
@@ -1,6 +0,0 @@
1
- import { writeFileSync } from "node:fs";
2
- import { dirname, join } from "node:path";
3
- import { fileURLToPath } from "node:url";
4
-
5
- writeFileSync(join(dirname(fileURLToPath(import.meta.url)), "deferred.marker"), "1");
6
- setInterval(() => {}, 60_000);
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./logger.setup.js";
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./logger.setup.js";
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./logger.setup.js";
@@ -1,5 +0,0 @@
1
- /**
2
- * The level a bin logs at: `--log-level`, then a level from the environment, then `trace` when
3
- * FORGE_TRACE is set (so `@trace` timings show), then scribe's default.
4
- */
5
- export declare function cliLogLevel(flag?: string): string;
@@ -1,2 +0,0 @@
1
- import "@decohere/scribe-pino";
2
- import "pino-pretty";
@@ -1,9 +0,0 @@
1
- import type { ApplicationModule, CommandResponse, ModuleManifest } from "@decohere/devkit/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
- }
@@ -1,15 +0,0 @@
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 {};
@@ -1,7 +0,0 @@
1
- import { type ApplicationModule, DecohereCommand } from "@decohere/devkit/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
- }
@@ -1,20 +0,0 @@
1
- import type { Actions, ModuleManifest } from "@decohere/devkit/cli";
2
- import { CommandResponse } from "@decohere/devkit/cli";
3
- import type { Constructable } from "@decohere/core/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
- }
@@ -1,34 +0,0 @@
1
- import type { ActionResponse } from "@decohere/devkit/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 {};