@codemation/cli 0.0.15 → 0.0.16
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 +4 -4
- package/dist/{CliBin-BkY_gChN.js → CliBin-C31h2o8w.js} +224 -216
- package/dist/bin.js +1 -1
- package/dist/index.d.ts +203 -258
- package/dist/index.js +1 -1
- package/package.json +3 -3
- package/src/CliProgramFactory.ts +22 -41
- package/src/Program.ts +12 -0
- package/src/commands/BuildCommand.ts +4 -11
- package/src/commands/DevCommand.ts +77 -45
- package/src/commands/DevPluginCommand.ts +19 -0
- package/src/commands/ServeWebCommand.ts +8 -34
- package/src/commands/devCommandLifecycle.types.ts +3 -2
- package/src/consumer/ConsumerOutputBuilder.ts +19 -0
- package/src/consumer/ConsumerOutputBuilderFactory.ts +16 -0
- package/src/dev/Builder.ts +2 -2
- package/src/dev/DevApiRuntimeFactory.ts +1 -0
- package/src/dev/DevApiRuntimeHost.ts +37 -6
- package/src/dev/DevApiRuntimeTypes.ts +1 -0
- package/src/dev/DevCliBannerRenderer.ts +21 -2
- package/src/dev/DevNextHostEnvironmentBuilder.ts +8 -41
- package/src/dev/DevRebuildQueue.ts +2 -2
- package/src/dev/DevSessionServices.ts +2 -2
- package/src/dev/DevSourceChangeClassifier.ts +12 -12
- package/src/dev/{DevAuthSettingsLoader.ts → NextHostEdgeSeedLoader.ts} +13 -9
- package/src/dev/PluginDevConfigFactory.ts +64 -0
- package/src/build/ConsumerBuildArtifactsPublisher.ts +0 -77
- package/src/consumer/Loader.ts +0 -8
- package/src/dev/DevConsumerPublishBootstrap.ts +0 -30
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as CliProgram, i as CliPathResolver, n as CliProgramFactory, o as ConsumerOutputBuilder, r as CodemationCliApplicationSession, s as ConsumerBuildOptionsParser, t as CliBin } from "./CliBin-
|
|
1
|
+
import { a as CliProgram, i as CliPathResolver, n as CliProgramFactory, o as ConsumerOutputBuilder, r as CodemationCliApplicationSession, s as ConsumerBuildOptionsParser, t as CliBin } from "./CliBin-C31h2o8w.js";
|
|
2
2
|
import { CodemationPluginDiscovery } from "@codemation/host/server";
|
|
3
3
|
|
|
4
4
|
export { CliBin, CliPathResolver, CliProgram, CliProgramFactory, CodemationCliApplicationSession, CodemationPluginDiscovery, ConsumerBuildOptionsParser, ConsumerOutputBuilder };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codemation/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"reflect-metadata": "^0.2.2",
|
|
38
38
|
"typescript": "^5.9.3",
|
|
39
39
|
"ws": "^8.19.0",
|
|
40
|
-
"@codemation/host": "0.0.
|
|
41
|
-
"@codemation/next-host": "0.0.
|
|
40
|
+
"@codemation/host": "0.0.16",
|
|
41
|
+
"@codemation/next-host": "0.0.16"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/http-proxy": "^1.17.15",
|
package/src/CliProgramFactory.ts
CHANGED
|
@@ -1,36 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AppConfigLoader,
|
|
3
|
-
CodemationConsumerConfigLoader,
|
|
4
|
-
CodemationFrontendAuthSnapshotFactory,
|
|
5
|
-
CodemationPluginDiscovery,
|
|
6
|
-
FrontendAppConfigJsonCodec,
|
|
7
|
-
} from "@codemation/host/server";
|
|
1
|
+
import { AppConfigLoader, CodemationConsumerConfigLoader, CodemationPluginDiscovery } from "@codemation/host/server";
|
|
8
2
|
import { AppContainerFactory } from "@codemation/host";
|
|
9
3
|
import { logLevelPolicyFactory, ServerLoggerFactory } from "@codemation/host/next/server";
|
|
10
4
|
|
|
11
|
-
import { ConsumerBuildArtifactsPublisher } from "./build/ConsumerBuildArtifactsPublisher";
|
|
12
5
|
import { ConsumerBuildOptionsParser } from "./build/ConsumerBuildOptionsParser";
|
|
13
6
|
import { BuildCommand } from "./commands/BuildCommand";
|
|
14
7
|
import { DbMigrateCommand } from "./commands/DbMigrateCommand";
|
|
15
8
|
import { DevCommand } from "./commands/DevCommand";
|
|
9
|
+
import { DevPluginCommand } from "./commands/DevPluginCommand";
|
|
16
10
|
import { ServeWebCommand } from "./commands/ServeWebCommand";
|
|
17
11
|
import { ServeWorkerCommand } from "./commands/ServeWorkerCommand";
|
|
18
12
|
import { UserCreateCommand } from "./commands/UserCreateCommand";
|
|
19
13
|
import { UserListCommand } from "./commands/UserListCommand";
|
|
20
14
|
import { ConsumerCliTsconfigPreparation } from "./consumer/ConsumerCliTsconfigPreparation";
|
|
21
15
|
import { ConsumerEnvLoader } from "./consumer/ConsumerEnvLoader";
|
|
22
|
-
import {
|
|
16
|
+
import { ConsumerOutputBuilderFactory } from "./consumer/ConsumerOutputBuilderFactory";
|
|
23
17
|
import { ConsumerDatabaseConnectionResolver } from "./database/ConsumerDatabaseConnectionResolver";
|
|
24
18
|
import { DatabaseMigrationsApplyService } from "./database/DatabaseMigrationsApplyService";
|
|
25
19
|
import { HostPackageRootResolver } from "./database/HostPackageRootResolver";
|
|
26
20
|
import { PrismaMigrationDeployer } from "@codemation/host/persistence";
|
|
27
21
|
import { DevBootstrapSummaryFetcher } from "./dev/DevBootstrapSummaryFetcher";
|
|
28
22
|
import { DevCliBannerRenderer } from "./dev/DevCliBannerRenderer";
|
|
29
|
-
import { DevConsumerPublishBootstrap } from "./dev/DevConsumerPublishBootstrap";
|
|
30
23
|
import { CliDevProxyServerFactory } from "./dev/CliDevProxyServerFactory";
|
|
31
24
|
import { DevApiRuntimeFactory } from "./dev/DevApiRuntimeFactory";
|
|
32
25
|
import { DevRebuildQueueFactory } from "./dev/DevRebuildQueueFactory";
|
|
33
26
|
import { DevSessionServicesBuilder } from "./dev/Builder";
|
|
27
|
+
import { PluginDevConfigFactory } from "./dev/PluginDevConfigFactory";
|
|
34
28
|
import { DevLockFactory } from "./dev/Factory";
|
|
35
29
|
import { ConsumerEnvDotenvFilePredicate } from "./dev/ConsumerEnvDotenvFilePredicate";
|
|
36
30
|
import { DevTrackedProcessTreeKiller } from "./dev/DevTrackedProcessTreeKiller";
|
|
@@ -59,9 +53,7 @@ export class CliProgramFactory {
|
|
|
59
53
|
const appConfigLoader = new AppConfigLoader();
|
|
60
54
|
const pathResolver = new CliPathResolver();
|
|
61
55
|
const pluginDiscovery = new CodemationPluginDiscovery();
|
|
62
|
-
const artifactsPublisher = new ConsumerBuildArtifactsPublisher();
|
|
63
56
|
const tsRuntime = new TypeScriptRuntimeConfigurator();
|
|
64
|
-
const outputBuilderLoader = new ConsumerOutputBuilderLoader();
|
|
65
57
|
const sourceMapNodeOptions = new SourceMapNodeOptions();
|
|
66
58
|
const nextHostConsumerServerCommandFactory = new NextHostConsumerServerCommandFactory();
|
|
67
59
|
const devSessionServices = new DevSessionServicesBuilder().build();
|
|
@@ -86,47 +78,36 @@ export class CliProgramFactory {
|
|
|
86
78
|
);
|
|
87
79
|
|
|
88
80
|
const buildOptionsParser = new ConsumerBuildOptionsParser();
|
|
89
|
-
const
|
|
81
|
+
const devCommand = new DevCommand(
|
|
82
|
+
pathResolver,
|
|
83
|
+
tsRuntime,
|
|
84
|
+
new DevLockFactory(),
|
|
85
|
+
new DevSourceWatcherFactory(),
|
|
90
86
|
cliLogger,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
87
|
+
devSessionServices,
|
|
88
|
+
databaseMigrationsApplyService,
|
|
89
|
+
new DevBootstrapSummaryFetcher(),
|
|
90
|
+
new DevCliBannerRenderer(),
|
|
91
|
+
new ConsumerEnvDotenvFilePredicate(),
|
|
92
|
+
new DevTrackedProcessTreeKiller(),
|
|
93
|
+
nextHostConsumerServerCommandFactory,
|
|
94
|
+
new DevApiRuntimeFactory(devSessionServices.loopbackPortAllocator, appConfigLoader, pluginDiscovery),
|
|
95
|
+
new CliDevProxyServerFactory(),
|
|
96
|
+
new DevRebuildQueueFactory(),
|
|
95
97
|
);
|
|
96
98
|
return new CliProgram(
|
|
97
99
|
buildOptionsParser,
|
|
98
|
-
new BuildCommand(cliLogger, pathResolver,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
tsRuntime,
|
|
102
|
-
new DevLockFactory(),
|
|
103
|
-
new DevSourceWatcherFactory(),
|
|
104
|
-
cliLogger,
|
|
105
|
-
devSessionServices,
|
|
106
|
-
databaseMigrationsApplyService,
|
|
107
|
-
new DevBootstrapSummaryFetcher(),
|
|
108
|
-
new DevCliBannerRenderer(),
|
|
109
|
-
devConsumerPublishBootstrap,
|
|
110
|
-
new ConsumerEnvDotenvFilePredicate(),
|
|
111
|
-
new DevTrackedProcessTreeKiller(),
|
|
112
|
-
nextHostConsumerServerCommandFactory,
|
|
113
|
-
new DevApiRuntimeFactory(devSessionServices.loopbackPortAllocator, appConfigLoader, pluginDiscovery),
|
|
114
|
-
new CliDevProxyServerFactory(),
|
|
115
|
-
new DevRebuildQueueFactory(),
|
|
116
|
-
),
|
|
100
|
+
new BuildCommand(cliLogger, pathResolver, new ConsumerOutputBuilderFactory(), tsRuntime),
|
|
101
|
+
devCommand,
|
|
102
|
+
new DevPluginCommand(new PluginDevConfigFactory(), devCommand),
|
|
117
103
|
new ServeWebCommand(
|
|
118
104
|
pathResolver,
|
|
119
105
|
new CodemationConsumerConfigLoader(),
|
|
120
|
-
pluginDiscovery,
|
|
121
|
-
artifactsPublisher,
|
|
122
106
|
tsRuntime,
|
|
123
107
|
sourceMapNodeOptions,
|
|
124
|
-
outputBuilderLoader,
|
|
125
108
|
new ConsumerEnvLoader(),
|
|
126
109
|
new ListenPortResolver(),
|
|
127
110
|
nextHostConsumerServerCommandFactory,
|
|
128
|
-
new CodemationFrontendAuthSnapshotFactory(),
|
|
129
|
-
new FrontendAppConfigJsonCodec(),
|
|
130
111
|
),
|
|
131
112
|
new ServeWorkerCommand(pathResolver, appConfigLoader, new AppContainerFactory()),
|
|
132
113
|
new DbMigrateCommand(databaseMigrationsApplyService),
|
package/src/Program.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { ConsumerBuildOptionsParser } from "./build/ConsumerBuildOptionsParser";
|
|
|
8
8
|
import { BuildCommand } from "./commands/BuildCommand";
|
|
9
9
|
import type { DbMigrateCommand } from "./commands/DbMigrateCommand";
|
|
10
10
|
import { DevCommand } from "./commands/DevCommand";
|
|
11
|
+
import type { DevPluginCommand } from "./commands/DevPluginCommand";
|
|
11
12
|
import { ServeWebCommand } from "./commands/ServeWebCommand";
|
|
12
13
|
import { ServeWorkerCommand } from "./commands/ServeWorkerCommand";
|
|
13
14
|
import { UserCreateCommand } from "./commands/UserCreateCommand";
|
|
@@ -18,6 +19,7 @@ export class CliProgram {
|
|
|
18
19
|
private readonly buildOptionsParser: ConsumerBuildOptionsParser,
|
|
19
20
|
private readonly buildCommand: BuildCommand,
|
|
20
21
|
private readonly devCommand: DevCommand,
|
|
22
|
+
private readonly devPluginCommand: DevPluginCommand,
|
|
21
23
|
private readonly serveWebCommand: ServeWebCommand,
|
|
22
24
|
private readonly serveWorkerCommand: ServeWorkerCommand,
|
|
23
25
|
private readonly dbMigrateCommand: DbMigrateCommand,
|
|
@@ -68,6 +70,16 @@ export class CliProgram {
|
|
|
68
70
|
});
|
|
69
71
|
});
|
|
70
72
|
|
|
73
|
+
program
|
|
74
|
+
.command("dev:plugin")
|
|
75
|
+
.description("Start plugin sandbox development using `codemation.plugin.ts`.")
|
|
76
|
+
.option("--plugin-root <path>", "Path to the plugin project root (defaults to cwd)")
|
|
77
|
+
.action(async (opts: Readonly<{ pluginRoot?: string }>) => {
|
|
78
|
+
await this.devPluginCommand.execute({
|
|
79
|
+
pluginRoot: resolveConsumerRoot(opts.pluginRoot),
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
71
83
|
const serve = program.command("serve").description("Run production web or worker processes (no dev watchers).");
|
|
72
84
|
|
|
73
85
|
serve
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import type { Logger } from "@codemation/host/next/server";
|
|
2
|
-
import { CodemationPluginDiscovery } from "@codemation/host/server";
|
|
3
2
|
|
|
4
|
-
import {
|
|
3
|
+
import type { ConsumerOutputBuilderFactory } from "../consumer/ConsumerOutputBuilderFactory";
|
|
5
4
|
import type { ConsumerBuildOptions } from "../consumer/consumerBuildOptions.types";
|
|
6
|
-
import { ConsumerOutputBuilderLoader } from "../consumer/Loader";
|
|
7
5
|
import { CliPathResolver } from "../path/CliPathResolver";
|
|
8
6
|
import { TypeScriptRuntimeConfigurator } from "../runtime/TypeScriptRuntimeConfigurator";
|
|
9
7
|
|
|
@@ -11,21 +9,16 @@ export class BuildCommand {
|
|
|
11
9
|
constructor(
|
|
12
10
|
private readonly cliLogger: Logger,
|
|
13
11
|
private readonly pathResolver: CliPathResolver,
|
|
14
|
-
private readonly
|
|
15
|
-
private readonly artifactsPublisher: ConsumerBuildArtifactsPublisher,
|
|
12
|
+
private readonly consumerOutputBuilderFactory: ConsumerOutputBuilderFactory,
|
|
16
13
|
private readonly tsRuntime: TypeScriptRuntimeConfigurator,
|
|
17
|
-
private readonly outputBuilderLoader: ConsumerOutputBuilderLoader,
|
|
18
14
|
) {}
|
|
19
15
|
|
|
20
16
|
async execute(consumerRoot: string, buildOptions: ConsumerBuildOptions): Promise<void> {
|
|
21
17
|
const paths = await this.pathResolver.resolve(consumerRoot);
|
|
22
18
|
this.tsRuntime.configure(paths.repoRoot);
|
|
23
|
-
const builder = this.
|
|
19
|
+
const builder = this.consumerOutputBuilderFactory.create(paths.consumerRoot, { buildOptions });
|
|
24
20
|
const snapshot = await builder.ensureBuilt();
|
|
25
|
-
const discoveredPlugins = await this.pluginDiscovery.discover(paths.consumerRoot);
|
|
26
|
-
const manifest = await this.artifactsPublisher.publish(snapshot, discoveredPlugins);
|
|
27
21
|
this.cliLogger.info(`Built consumer output: ${snapshot.outputEntryPath}`);
|
|
28
|
-
this.cliLogger.info(`
|
|
29
|
-
this.cliLogger.info(`Published build: ${manifest.buildVersion}`);
|
|
22
|
+
this.cliLogger.info(`Workflow modules emitted: ${snapshot.workflowSourcePaths.length}`);
|
|
30
23
|
}
|
|
31
24
|
}
|
|
@@ -10,7 +10,6 @@ import type { DevBootstrapSummaryFetcher } from "../dev/DevBootstrapSummaryFetch
|
|
|
10
10
|
import type { CliDevProxyServer } from "../dev/CliDevProxyServer";
|
|
11
11
|
import type { CliDevProxyServerFactory } from "../dev/CliDevProxyServerFactory";
|
|
12
12
|
import type { DevCliBannerRenderer } from "../dev/DevCliBannerRenderer";
|
|
13
|
-
import type { DevConsumerPublishBootstrap } from "../dev/DevConsumerPublishBootstrap";
|
|
14
13
|
import { ConsumerEnvDotenvFilePredicate } from "../dev/ConsumerEnvDotenvFilePredicate";
|
|
15
14
|
import type { DevRebuildQueueFactory } from "../dev/DevRebuildQueueFactory";
|
|
16
15
|
import type { DevSourceWatcher } from "../dev/DevSourceWatcher";
|
|
@@ -18,7 +17,7 @@ import { DevSessionServices } from "../dev/DevSessionServices";
|
|
|
18
17
|
import { DevLockFactory } from "../dev/Factory";
|
|
19
18
|
import { DevTrackedProcessTreeKiller } from "../dev/DevTrackedProcessTreeKiller";
|
|
20
19
|
import { DevSourceWatcherFactory } from "../dev/Runner";
|
|
21
|
-
import type {
|
|
20
|
+
import type { NextHostEdgeSeed } from "../dev/NextHostEdgeSeedLoader";
|
|
22
21
|
import { CliPathResolver, type CliPaths } from "../path/CliPathResolver";
|
|
23
22
|
import { NextHostConsumerServerCommandFactory } from "../runtime/NextHostConsumerServerCommandFactory";
|
|
24
23
|
import { TypeScriptRuntimeConfigurator } from "../runtime/TypeScriptRuntimeConfigurator";
|
|
@@ -38,7 +37,6 @@ export class DevCommand {
|
|
|
38
37
|
private readonly databaseMigrationsApplyService: DatabaseMigrationsApplyService,
|
|
39
38
|
private readonly devBootstrapSummaryFetcher: DevBootstrapSummaryFetcher,
|
|
40
39
|
private readonly devCliBannerRenderer: DevCliBannerRenderer,
|
|
41
|
-
private readonly devConsumerPublishBootstrap: DevConsumerPublishBootstrap,
|
|
42
40
|
private readonly consumerEnvDotenvFilePredicate: ConsumerEnvDotenvFilePredicate,
|
|
43
41
|
private readonly devTrackedProcessTreeKiller: DevTrackedProcessTreeKiller,
|
|
44
42
|
private readonly nextHostConsumerServerCommandFactory: NextHostConsumerServerCommandFactory,
|
|
@@ -47,12 +45,21 @@ export class DevCommand {
|
|
|
47
45
|
private readonly devRebuildQueueFactory: DevRebuildQueueFactory,
|
|
48
46
|
) {}
|
|
49
47
|
|
|
50
|
-
async execute(
|
|
48
|
+
async execute(
|
|
49
|
+
args: Readonly<{
|
|
50
|
+
consumerRoot: string;
|
|
51
|
+
watchFramework?: boolean;
|
|
52
|
+
commandName?: "dev" | "dev:plugin";
|
|
53
|
+
configPathOverride?: string;
|
|
54
|
+
}>,
|
|
55
|
+
): Promise<void> {
|
|
51
56
|
const paths = await this.pathResolver.resolve(args.consumerRoot);
|
|
57
|
+
const commandName = args.commandName ?? "dev";
|
|
52
58
|
this.devCliBannerRenderer.renderBrandHeader();
|
|
53
59
|
this.tsRuntime.configure(paths.repoRoot);
|
|
54
|
-
await this.databaseMigrationsApplyService.applyForConsumer(paths.consumerRoot
|
|
55
|
-
|
|
60
|
+
await this.databaseMigrationsApplyService.applyForConsumer(paths.consumerRoot, {
|
|
61
|
+
configPath: args.configPathOverride,
|
|
62
|
+
});
|
|
56
63
|
const devMode = this.resolveDevMode(args);
|
|
57
64
|
const { nextPort, gatewayPort } = await this.session.sessionPorts.resolve({
|
|
58
65
|
devMode,
|
|
@@ -64,14 +71,23 @@ export class DevCommand {
|
|
|
64
71
|
consumerRoot: paths.consumerRoot,
|
|
65
72
|
nextPort: devMode === "watch-framework" ? nextPort : gatewayPort,
|
|
66
73
|
});
|
|
67
|
-
const authSettings = await this.session.
|
|
74
|
+
const authSettings = await this.session.nextHostEdgeSeedLoader.loadForConsumer(paths.consumerRoot, {
|
|
75
|
+
configPathOverride: args.configPathOverride,
|
|
76
|
+
});
|
|
68
77
|
const watcher = this.devSourceWatcherFactory.create();
|
|
69
78
|
const processState = this.createInitialProcessState();
|
|
70
79
|
let proxyServer: CliDevProxyServer | null = null;
|
|
71
80
|
try {
|
|
72
|
-
const prepared = await this.prepareDevRuntime(
|
|
81
|
+
const prepared = await this.prepareDevRuntime(
|
|
82
|
+
paths,
|
|
83
|
+
devMode,
|
|
84
|
+
nextPort,
|
|
85
|
+
gatewayPort,
|
|
86
|
+
authSettings,
|
|
87
|
+
args.configPathOverride,
|
|
88
|
+
);
|
|
73
89
|
const stopPromise = this.wireStopPromise(processState);
|
|
74
|
-
const uiProxyBase = await this.
|
|
90
|
+
const uiProxyBase = await this.preparePackagedUiBaseUrlWhenNeeded(prepared, processState);
|
|
75
91
|
proxyServer = await this.startProxyServer(prepared.gatewayPort, uiProxyBase);
|
|
76
92
|
const gatewayBaseUrl = this.gatewayBaseHttpUrl(gatewayPort);
|
|
77
93
|
await this.bootInitialRuntime(prepared, processState, proxyServer);
|
|
@@ -80,10 +96,14 @@ export class DevCommand {
|
|
|
80
96
|
if (initialSummary) {
|
|
81
97
|
this.devCliBannerRenderer.renderRuntimeSummary(initialSummary);
|
|
82
98
|
}
|
|
99
|
+
await this.startPackagedUiWhenNeeded(prepared, processState, uiProxyBase);
|
|
83
100
|
this.bindShutdownSignalsToChildProcesses(processState, proxyServer);
|
|
84
101
|
await this.spawnDevUiWhenNeeded(prepared, processState, gatewayBaseUrl);
|
|
85
|
-
await this.startWatcherForSourceRestart(prepared, processState, watcher, devMode, gatewayBaseUrl, proxyServer
|
|
86
|
-
|
|
102
|
+
await this.startWatcherForSourceRestart(prepared, processState, watcher, devMode, gatewayBaseUrl, proxyServer, {
|
|
103
|
+
commandName,
|
|
104
|
+
configPathOverride: args.configPathOverride,
|
|
105
|
+
});
|
|
106
|
+
this.logPackagedUiDevHintWhenNeeded(devMode, gatewayPort, commandName);
|
|
87
107
|
await stopPromise;
|
|
88
108
|
} finally {
|
|
89
109
|
processState.stopRequested = true;
|
|
@@ -105,14 +125,16 @@ export class DevCommand {
|
|
|
105
125
|
devMode: DevMode,
|
|
106
126
|
nextPort: number,
|
|
107
127
|
gatewayPort: number,
|
|
108
|
-
authSettings:
|
|
128
|
+
authSettings: NextHostEdgeSeed,
|
|
129
|
+
configPathOverride?: string,
|
|
109
130
|
): Promise<DevPreparedRuntime> {
|
|
110
|
-
const developmentServerToken = this.session.
|
|
131
|
+
const developmentServerToken = this.session.nextHostEdgeSeedLoader.resolveDevelopmentServerToken(
|
|
111
132
|
process.env.CODEMATION_DEV_SERVER_TOKEN,
|
|
112
133
|
);
|
|
113
134
|
const consumerEnv = this.session.consumerEnvLoader.load(paths.consumerRoot);
|
|
114
135
|
return {
|
|
115
136
|
paths,
|
|
137
|
+
configPathOverride,
|
|
116
138
|
devMode,
|
|
117
139
|
nextPort,
|
|
118
140
|
gatewayPort,
|
|
@@ -146,48 +168,50 @@ export class DevCommand {
|
|
|
146
168
|
return `http://127.0.0.1:${gatewayPort}`;
|
|
147
169
|
}
|
|
148
170
|
|
|
149
|
-
private async
|
|
171
|
+
private async preparePackagedUiBaseUrlWhenNeeded(
|
|
150
172
|
prepared: DevPreparedRuntime,
|
|
151
173
|
state: DevMutableProcessState,
|
|
152
174
|
): Promise<string> {
|
|
153
175
|
if (prepared.devMode !== "packaged-ui") {
|
|
154
176
|
return "";
|
|
155
177
|
}
|
|
156
|
-
const websocketPort = prepared.gatewayPort;
|
|
157
178
|
const uiProxyBase =
|
|
158
179
|
state.currentPackagedUiBaseUrl ?? `http://127.0.0.1:${await this.session.loopbackPortAllocator.allocate()}`;
|
|
159
180
|
state.currentPackagedUiBaseUrl = uiProxyBase;
|
|
160
|
-
await this.spawnPackagedUi(prepared, state, prepared.authSettings, websocketPort, uiProxyBase);
|
|
161
181
|
return uiProxyBase;
|
|
162
182
|
}
|
|
163
183
|
|
|
184
|
+
private async startPackagedUiWhenNeeded(
|
|
185
|
+
prepared: DevPreparedRuntime,
|
|
186
|
+
state: DevMutableProcessState,
|
|
187
|
+
uiProxyBase: string,
|
|
188
|
+
): Promise<void> {
|
|
189
|
+
if (prepared.devMode !== "packaged-ui" || uiProxyBase.length === 0) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
await this.spawnPackagedUi(prepared, state, prepared.authSettings, prepared.gatewayPort, uiProxyBase);
|
|
193
|
+
}
|
|
194
|
+
|
|
164
195
|
private async spawnPackagedUi(
|
|
165
196
|
prepared: DevPreparedRuntime,
|
|
166
197
|
state: DevMutableProcessState,
|
|
167
|
-
authSettings:
|
|
198
|
+
authSettings: NextHostEdgeSeed,
|
|
168
199
|
websocketPort: number,
|
|
169
200
|
uiProxyBase: string,
|
|
170
201
|
): Promise<void> {
|
|
171
202
|
const nextHostPackageJsonPath = this.require.resolve("@codemation/next-host/package.json");
|
|
172
203
|
const nextHostRoot = path.dirname(nextHostPackageJsonPath);
|
|
173
204
|
const nextHostCommand = await this.nextHostConsumerServerCommandFactory.create({ nextHostRoot });
|
|
174
|
-
const consumerOutputManifestPath = path.resolve(
|
|
175
|
-
prepared.paths.consumerRoot,
|
|
176
|
-
".codemation",
|
|
177
|
-
"output",
|
|
178
|
-
"current.json",
|
|
179
|
-
);
|
|
180
205
|
const uiPort = Number(new URL(uiProxyBase).port);
|
|
181
206
|
const nextHostEnvironment = this.session.nextHostEnvBuilder.buildConsumerUiProxy({
|
|
182
|
-
authConfigJson: authSettings.authConfigJson,
|
|
183
207
|
authSecret: authSettings.authSecret,
|
|
208
|
+
configPathOverride: prepared.configPathOverride,
|
|
184
209
|
consumerRoot: prepared.paths.consumerRoot,
|
|
185
|
-
consumerOutputManifestPath,
|
|
186
210
|
developmentServerToken: prepared.developmentServerToken,
|
|
187
211
|
nextPort: uiPort,
|
|
188
212
|
publicBaseUrl: this.gatewayBaseHttpUrl(prepared.gatewayPort),
|
|
189
213
|
runtimeDevUrl: this.gatewayBaseHttpUrl(prepared.gatewayPort),
|
|
190
|
-
skipUiAuth: authSettings.
|
|
214
|
+
skipUiAuth: !authSettings.uiAuthEnabled,
|
|
191
215
|
websocketPort,
|
|
192
216
|
});
|
|
193
217
|
state.currentPackagedUi = spawn(nextHostCommand.command, nextHostCommand.args, {
|
|
@@ -282,17 +306,18 @@ export class DevCommand {
|
|
|
282
306
|
prepared: DevPreparedRuntime,
|
|
283
307
|
state: DevMutableProcessState,
|
|
284
308
|
gatewayBaseUrl: string,
|
|
285
|
-
authSettings:
|
|
309
|
+
authSettings: NextHostEdgeSeed,
|
|
286
310
|
): Promise<void> {
|
|
287
311
|
const websocketPort = prepared.gatewayPort;
|
|
288
312
|
const nextHostPackageJsonPath = this.require.resolve("@codemation/next-host/package.json");
|
|
289
313
|
const nextHostRoot = path.dirname(nextHostPackageJsonPath);
|
|
290
314
|
const nextHostEnvironment = this.session.nextHostEnvBuilder.build({
|
|
291
|
-
|
|
315
|
+
authSecret: authSettings.authSecret,
|
|
316
|
+
configPathOverride: prepared.configPathOverride,
|
|
292
317
|
consumerRoot: prepared.paths.consumerRoot,
|
|
293
318
|
developmentServerToken: prepared.developmentServerToken,
|
|
294
319
|
nextPort: prepared.nextPort,
|
|
295
|
-
skipUiAuth: authSettings.
|
|
320
|
+
skipUiAuth: !authSettings.uiAuthEnabled,
|
|
296
321
|
websocketPort,
|
|
297
322
|
runtimeDevUrl: gatewayBaseUrl,
|
|
298
323
|
});
|
|
@@ -331,6 +356,10 @@ export class DevCommand {
|
|
|
331
356
|
devMode: DevMode,
|
|
332
357
|
gatewayBaseUrl: string,
|
|
333
358
|
proxyServer: CliDevProxyServer,
|
|
359
|
+
options: Readonly<{
|
|
360
|
+
commandName: "dev" | "dev:plugin";
|
|
361
|
+
configPathOverride?: string;
|
|
362
|
+
}>,
|
|
334
363
|
): Promise<void> {
|
|
335
364
|
const rebuildQueue = this.devRebuildQueueFactory.create({
|
|
336
365
|
run: async (request) => {
|
|
@@ -351,22 +380,18 @@ export class DevCommand {
|
|
|
351
380
|
return;
|
|
352
381
|
}
|
|
353
382
|
try {
|
|
354
|
-
const shouldRepublishConsumerOutput = this.session.sourceChangeClassifier.shouldRepublishConsumerOutput({
|
|
355
|
-
changedPaths,
|
|
356
|
-
consumerRoot: prepared.paths.consumerRoot,
|
|
357
|
-
});
|
|
358
383
|
const shouldRestartUi = this.session.sourceChangeClassifier.requiresUiRestart({
|
|
359
384
|
changedPaths,
|
|
360
385
|
consumerRoot: prepared.paths.consumerRoot,
|
|
361
386
|
});
|
|
362
387
|
process.stdout.write(
|
|
363
388
|
shouldRestartUi
|
|
364
|
-
?
|
|
365
|
-
:
|
|
389
|
+
? `\n[codemation] Source change detected — rebuilding for \`${options.commandName}\`, restarting the runtime, and restarting the UI…\n`
|
|
390
|
+
: `\n[codemation] Source change detected — rebuilding for \`${options.commandName}\` and restarting the runtime…\n`,
|
|
366
391
|
);
|
|
367
392
|
await rebuildQueue.enqueue({
|
|
368
393
|
changedPaths,
|
|
369
|
-
|
|
394
|
+
configPathOverride: options.configPathOverride,
|
|
370
395
|
shouldRestartUi,
|
|
371
396
|
});
|
|
372
397
|
} catch (error) {
|
|
@@ -383,7 +408,7 @@ export class DevCommand {
|
|
|
383
408
|
proxyServer: CliDevProxyServer,
|
|
384
409
|
request: Readonly<{
|
|
385
410
|
changedPaths: ReadonlyArray<string>;
|
|
386
|
-
|
|
411
|
+
configPathOverride?: string;
|
|
387
412
|
shouldRestartUi: boolean;
|
|
388
413
|
}>,
|
|
389
414
|
): Promise<void> {
|
|
@@ -391,9 +416,6 @@ export class DevCommand {
|
|
|
391
416
|
proxyServer.setBuildStatus("building");
|
|
392
417
|
proxyServer.broadcastBuildStarted();
|
|
393
418
|
try {
|
|
394
|
-
if (request.shouldRepublishConsumerOutput) {
|
|
395
|
-
await this.devConsumerPublishBootstrap.ensurePublished(prepared.paths);
|
|
396
|
-
}
|
|
397
419
|
await this.stopCurrentRuntime(state, proxyServer);
|
|
398
420
|
process.stdout.write("[codemation] Waiting for runtime to accept traffic…\n");
|
|
399
421
|
const runtime = await this.createRuntime(prepared);
|
|
@@ -425,7 +447,12 @@ export class DevCommand {
|
|
|
425
447
|
state: DevMutableProcessState,
|
|
426
448
|
gatewayBaseUrl: string,
|
|
427
449
|
): Promise<void> {
|
|
428
|
-
const refreshedAuthSettings = await this.session.
|
|
450
|
+
const refreshedAuthSettings = await this.session.nextHostEdgeSeedLoader.loadForConsumer(
|
|
451
|
+
prepared.paths.consumerRoot,
|
|
452
|
+
{
|
|
453
|
+
configPathOverride: prepared.configPathOverride,
|
|
454
|
+
},
|
|
455
|
+
);
|
|
429
456
|
process.stdout.write("[codemation] Restarting the UI process to apply source changes…\n");
|
|
430
457
|
state.isRestartingUi = true;
|
|
431
458
|
try {
|
|
@@ -442,7 +469,7 @@ export class DevCommand {
|
|
|
442
469
|
private async restartPackagedUi(
|
|
443
470
|
prepared: DevPreparedRuntime,
|
|
444
471
|
state: DevMutableProcessState,
|
|
445
|
-
authSettings:
|
|
472
|
+
authSettings: NextHostEdgeSeed,
|
|
446
473
|
): Promise<void> {
|
|
447
474
|
if (
|
|
448
475
|
state.currentPackagedUi &&
|
|
@@ -463,7 +490,7 @@ export class DevCommand {
|
|
|
463
490
|
prepared: DevPreparedRuntime,
|
|
464
491
|
state: DevMutableProcessState,
|
|
465
492
|
gatewayBaseUrl: string,
|
|
466
|
-
authSettings:
|
|
493
|
+
authSettings: NextHostEdgeSeed,
|
|
467
494
|
): Promise<void> {
|
|
468
495
|
if (state.currentDevUi && state.currentDevUi.exitCode === null && state.currentDevUi.signalCode === null) {
|
|
469
496
|
await this.devTrackedProcessTreeKiller.killProcessTreeRootedAt(state.currentDevUi);
|
|
@@ -517,6 +544,7 @@ export class DevCommand {
|
|
|
517
544
|
prepared.consumerEnv,
|
|
518
545
|
);
|
|
519
546
|
return await this.devApiRuntimeFactory.create({
|
|
547
|
+
configPathOverride: prepared.configPathOverride,
|
|
520
548
|
consumerRoot: prepared.paths.consumerRoot,
|
|
521
549
|
runtimeWorkingDirectory: process.cwd(),
|
|
522
550
|
env: {
|
|
@@ -530,12 +558,16 @@ export class DevCommand {
|
|
|
530
558
|
});
|
|
531
559
|
}
|
|
532
560
|
|
|
533
|
-
private logPackagedUiDevHintWhenNeeded(
|
|
561
|
+
private logPackagedUiDevHintWhenNeeded(
|
|
562
|
+
devMode: DevMode,
|
|
563
|
+
gatewayPort: number,
|
|
564
|
+
commandName: "dev" | "dev:plugin",
|
|
565
|
+
): void {
|
|
534
566
|
if (devMode !== "packaged-ui") {
|
|
535
567
|
return;
|
|
536
568
|
}
|
|
537
569
|
this.cliLogger.info(
|
|
538
|
-
`codemation
|
|
570
|
+
`codemation ${commandName}: open http://127.0.0.1:${gatewayPort} — this uses the packaged @codemation/next-host UI. Use \`codemation ${commandName} --watch-framework\` only when working on the framework UI itself.`,
|
|
539
571
|
);
|
|
540
572
|
}
|
|
541
573
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DevCommand } from "./DevCommand";
|
|
2
|
+
import type { PluginDevConfigFactory } from "../dev/PluginDevConfigFactory";
|
|
3
|
+
|
|
4
|
+
export class DevPluginCommand {
|
|
5
|
+
constructor(
|
|
6
|
+
private readonly pluginDevConfigFactory: PluginDevConfigFactory,
|
|
7
|
+
private readonly devCommand: DevCommand,
|
|
8
|
+
) {}
|
|
9
|
+
|
|
10
|
+
async execute(args: Readonly<{ pluginRoot: string; watchFramework?: boolean }>): Promise<void> {
|
|
11
|
+
const pluginConfig = await this.pluginDevConfigFactory.prepare(args.pluginRoot);
|
|
12
|
+
await this.devCommand.execute({
|
|
13
|
+
commandName: "dev:plugin",
|
|
14
|
+
configPathOverride: pluginConfig.configPath,
|
|
15
|
+
consumerRoot: args.pluginRoot,
|
|
16
|
+
watchFramework: args.watchFramework,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -1,18 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CodemationConsumerConfigLoader,
|
|
3
|
-
CodemationFrontendAuthSnapshotFactory,
|
|
4
|
-
CodemationPluginDiscovery,
|
|
5
|
-
FrontendAppConfigJsonCodec,
|
|
6
|
-
} from "@codemation/host/server";
|
|
1
|
+
import { CodemationConsumerConfigLoader } from "@codemation/host/server";
|
|
7
2
|
import { spawn } from "node:child_process";
|
|
8
3
|
import { createRequire } from "node:module";
|
|
9
4
|
import path from "node:path";
|
|
10
5
|
import process from "node:process";
|
|
11
6
|
|
|
12
|
-
import { ConsumerBuildArtifactsPublisher } from "../build/ConsumerBuildArtifactsPublisher";
|
|
13
7
|
import { ConsumerEnvLoader } from "../consumer/ConsumerEnvLoader";
|
|
14
8
|
import type { ConsumerBuildOptions } from "../consumer/consumerBuildOptions.types";
|
|
15
|
-
import { ConsumerOutputBuilderLoader } from "../consumer/Loader";
|
|
16
9
|
import { CliPathResolver } from "../path/CliPathResolver";
|
|
17
10
|
import { ListenPortResolver } from "../runtime/ListenPortResolver";
|
|
18
11
|
import { NextHostConsumerServerCommandFactory } from "../runtime/NextHostConsumerServerCommandFactory";
|
|
@@ -25,40 +18,21 @@ export class ServeWebCommand {
|
|
|
25
18
|
constructor(
|
|
26
19
|
private readonly pathResolver: CliPathResolver,
|
|
27
20
|
private readonly configLoader: CodemationConsumerConfigLoader,
|
|
28
|
-
private readonly pluginDiscovery: CodemationPluginDiscovery,
|
|
29
|
-
private readonly artifactsPublisher: ConsumerBuildArtifactsPublisher,
|
|
30
21
|
private readonly tsRuntime: TypeScriptRuntimeConfigurator,
|
|
31
22
|
private readonly sourceMapNodeOptions: SourceMapNodeOptions,
|
|
32
|
-
private readonly outputBuilderLoader: ConsumerOutputBuilderLoader,
|
|
33
23
|
private readonly envLoader: ConsumerEnvLoader,
|
|
34
24
|
private readonly listenPortResolver: ListenPortResolver,
|
|
35
25
|
private readonly nextHostConsumerServerCommandFactory: NextHostConsumerServerCommandFactory,
|
|
36
|
-
private readonly frontendAuthSnapshotFactory: CodemationFrontendAuthSnapshotFactory,
|
|
37
|
-
private readonly frontendAppConfigJsonCodec: FrontendAppConfigJsonCodec,
|
|
38
26
|
) {}
|
|
39
27
|
|
|
40
28
|
async execute(consumerRoot: string, buildOptions: ConsumerBuildOptions): Promise<void> {
|
|
29
|
+
void buildOptions;
|
|
41
30
|
const paths = await this.pathResolver.resolve(consumerRoot);
|
|
42
31
|
this.tsRuntime.configure(paths.repoRoot);
|
|
43
|
-
const builder = this.outputBuilderLoader.create(paths.consumerRoot, buildOptions);
|
|
44
|
-
const snapshot = await builder.ensureBuilt();
|
|
45
|
-
const discoveredPlugins = await this.pluginDiscovery.discover(paths.consumerRoot);
|
|
46
|
-
const manifest = await this.artifactsPublisher.publish(snapshot, discoveredPlugins);
|
|
47
32
|
const nextHostRoot = path.dirname(this.require.resolve("@codemation/next-host/package.json"));
|
|
48
33
|
const nextHostCommand = await this.nextHostConsumerServerCommandFactory.create({ nextHostRoot });
|
|
49
34
|
const consumerEnv = this.envLoader.load(paths.consumerRoot);
|
|
50
35
|
const configResolution = await this.configLoader.load({ consumerRoot: paths.consumerRoot });
|
|
51
|
-
const frontendAuthSnapshot = this.frontendAuthSnapshotFactory.createFromResolvedInputs({
|
|
52
|
-
authConfig: configResolution.config.auth,
|
|
53
|
-
env: {
|
|
54
|
-
...process.env,
|
|
55
|
-
...consumerEnv,
|
|
56
|
-
},
|
|
57
|
-
uiAuthEnabled: !(
|
|
58
|
-
consumerEnv.NODE_ENV !== "production" &&
|
|
59
|
-
configResolution.config.auth?.allowUnauthenticatedInDevelopment === true
|
|
60
|
-
),
|
|
61
|
-
});
|
|
62
36
|
const nextPort = this.listenPortResolver.resolvePrimaryApplicationPort(process.env.PORT);
|
|
63
37
|
const websocketPort = this.listenPortResolver.resolveWebsocketPortRelativeToHttp({
|
|
64
38
|
nextPort,
|
|
@@ -72,13 +46,13 @@ export class ServeWebCommand {
|
|
|
72
46
|
...process.env,
|
|
73
47
|
...consumerEnv,
|
|
74
48
|
PORT: String(nextPort),
|
|
75
|
-
CODEMATION_FRONTEND_APP_CONFIG_JSON: this.frontendAppConfigJsonCodec.serialize({
|
|
76
|
-
auth: frontendAuthSnapshot,
|
|
77
|
-
productName: "Codemation",
|
|
78
|
-
logoUrl: null,
|
|
79
|
-
}),
|
|
80
|
-
CODEMATION_CONSUMER_OUTPUT_MANIFEST_PATH: manifest.manifestPath,
|
|
81
49
|
CODEMATION_CONSUMER_ROOT: paths.consumerRoot,
|
|
50
|
+
CODEMATION_UI_AUTH_ENABLED: String(
|
|
51
|
+
!(
|
|
52
|
+
consumerEnv.NODE_ENV !== "production" &&
|
|
53
|
+
configResolution.config.auth?.allowUnauthenticatedInDevelopment === true
|
|
54
|
+
),
|
|
55
|
+
),
|
|
82
56
|
CODEMATION_WS_PORT: String(websocketPort),
|
|
83
57
|
NEXT_PUBLIC_CODEMATION_WS_PORT: String(websocketPort),
|
|
84
58
|
NODE_OPTIONS: this.sourceMapNodeOptions.appendToNodeOptions(process.env.NODE_OPTIONS),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ChildProcess } from "node:child_process";
|
|
2
2
|
|
|
3
|
-
import type { DevResolvedAuthSettings } from "../dev/DevAuthSettingsLoader";
|
|
4
3
|
import type { DevApiRuntimeServerHandle } from "../dev/DevApiRuntimeFactory";
|
|
4
|
+
import type { NextHostEdgeSeed } from "../dev/NextHostEdgeSeedLoader";
|
|
5
5
|
import type { CliPaths } from "../path/CliPathResolver";
|
|
6
6
|
|
|
7
7
|
export type DevMode = "packaged-ui" | "watch-framework";
|
|
@@ -21,10 +21,11 @@ export type DevMutableProcessState = {
|
|
|
21
21
|
/** Immutable inputs resolved before any child processes are spawned. */
|
|
22
22
|
export type DevPreparedRuntime = Readonly<{
|
|
23
23
|
paths: CliPaths;
|
|
24
|
+
configPathOverride?: string;
|
|
24
25
|
devMode: DevMode;
|
|
25
26
|
nextPort: number;
|
|
26
27
|
gatewayPort: number;
|
|
27
|
-
authSettings:
|
|
28
|
+
authSettings: NextHostEdgeSeed;
|
|
28
29
|
developmentServerToken: string;
|
|
29
30
|
consumerEnv: Readonly<Record<string, string>>;
|
|
30
31
|
}>;
|