@codemation/cli 0.0.14 → 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/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-BkY_gChN.js";
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.14",
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/next-host": "0.0.14",
41
- "@codemation/host": "0.0.14"
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",
@@ -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 { ConsumerOutputBuilderLoader } from "./consumer/Loader";
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 devConsumerPublishBootstrap = new DevConsumerPublishBootstrap(
81
+ const devCommand = new DevCommand(
82
+ pathResolver,
83
+ tsRuntime,
84
+ new DevLockFactory(),
85
+ new DevSourceWatcherFactory(),
90
86
  cliLogger,
91
- pluginDiscovery,
92
- artifactsPublisher,
93
- outputBuilderLoader,
94
- buildOptionsParser,
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, pluginDiscovery, artifactsPublisher, tsRuntime, outputBuilderLoader),
99
- new DevCommand(
100
- pathResolver,
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 { ConsumerBuildArtifactsPublisher } from "../build/ConsumerBuildArtifactsPublisher";
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 pluginDiscovery: CodemationPluginDiscovery,
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.outputBuilderLoader.create(paths.consumerRoot, buildOptions);
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(`Discovered plugins: ${discoveredPlugins.length}`);
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 { DevResolvedAuthSettings } from "../dev/DevAuthSettingsLoader";
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(args: Readonly<{ consumerRoot: string; watchFramework?: boolean }>): Promise<void> {
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
- await this.devConsumerPublishBootstrap.ensurePublished(paths);
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.devAuthLoader.loadForConsumer(paths.consumerRoot);
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(paths, devMode, nextPort, gatewayPort, authSettings);
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.startPackagedUiWhenNeeded(prepared, processState);
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
- this.logPackagedUiDevHintWhenNeeded(devMode, gatewayPort);
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: DevResolvedAuthSettings,
128
+ authSettings: NextHostEdgeSeed,
129
+ configPathOverride?: string,
109
130
  ): Promise<DevPreparedRuntime> {
110
- const developmentServerToken = this.session.devAuthLoader.resolveDevelopmentServerToken(
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 startPackagedUiWhenNeeded(
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: DevResolvedAuthSettings,
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.skipUiAuth,
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: DevResolvedAuthSettings,
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
- authConfigJson: authSettings.authConfigJson,
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.skipUiAuth,
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
- ? "\n[codemation] Source change detected — rebuilding consumer, restarting the runtime, and restarting the UI…\n"
365
- : "\n[codemation] Source change detected — rebuilding consumer and restarting the runtime…\n",
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
- shouldRepublishConsumerOutput,
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
- shouldRepublishConsumerOutput: boolean;
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.devAuthLoader.loadForConsumer(prepared.paths.consumerRoot);
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: DevResolvedAuthSettings,
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: DevResolvedAuthSettings,
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(devMode: DevMode, gatewayPort: number): void {
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 dev: open http://127.0.0.1:${gatewayPort} — this uses the packaged @codemation/next-host UI. Use \`codemation dev --watch-framework\` only when working on the framework UI itself.`,
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: DevResolvedAuthSettings;
28
+ authSettings: NextHostEdgeSeed;
28
29
  developmentServerToken: string;
29
30
  consumerEnv: Readonly<Record<string, string>>;
30
31
  }>;