@codemation/cli 0.0.2 → 0.0.3

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.
@@ -120,7 +120,7 @@ var DbMigrateCommand = class {
120
120
  //#region src/commands/DevCommand.ts
121
121
  var DevCommand = class {
122
122
  require = createRequire(import.meta.url);
123
- constructor(pathResolver, pluginDiscovery, tsRuntime, devLockFactory, devSourceWatcherFactory, cliLogger, session, databaseMigrationsApplyService, devBootstrapSummaryFetcher, devCliBannerRenderer, devConsumerPublishBootstrap, consumerEnvDotenvFilePredicate, devTrackedProcessTreeKiller) {
123
+ constructor(pathResolver, pluginDiscovery, tsRuntime, devLockFactory, devSourceWatcherFactory, cliLogger, session, databaseMigrationsApplyService, devBootstrapSummaryFetcher, devCliBannerRenderer, devConsumerPublishBootstrap, consumerEnvDotenvFilePredicate, devTrackedProcessTreeKiller, nextHostConsumerServerCommandFactory) {
124
124
  this.pathResolver = pathResolver;
125
125
  this.pluginDiscovery = pluginDiscovery;
126
126
  this.tsRuntime = tsRuntime;
@@ -134,6 +134,7 @@ var DevCommand = class {
134
134
  this.devConsumerPublishBootstrap = devConsumerPublishBootstrap;
135
135
  this.consumerEnvDotenvFilePredicate = consumerEnvDotenvFilePredicate;
136
136
  this.devTrackedProcessTreeKiller = devTrackedProcessTreeKiller;
137
+ this.nextHostConsumerServerCommandFactory = nextHostConsumerServerCommandFactory;
137
138
  }
138
139
  async execute(consumerRoot) {
139
140
  const paths = await this.pathResolver.resolve(consumerRoot);
@@ -235,13 +236,10 @@ var DevCommand = class {
235
236
  const uiProxyBase = `http://127.0.0.1:${uiPort}`;
236
237
  const nextHostPackageJsonPath = this.require.resolve("@codemation/next-host/package.json");
237
238
  const nextHostRoot = path.dirname(nextHostPackageJsonPath);
239
+ const nextHostCommand = await this.nextHostConsumerServerCommandFactory.create({ nextHostRoot });
238
240
  const consumerOutputManifestPath = path.resolve(prepared.paths.consumerRoot, ".codemation", "output", "current.json");
239
- state.currentUiNext = spawn("pnpm", [
240
- "exec",
241
- "next",
242
- "start"
243
- ], {
244
- cwd: nextHostRoot,
241
+ state.currentUiNext = spawn(nextHostCommand.command, nextHostCommand.args, {
242
+ cwd: nextHostCommand.cwd,
245
243
  ...this.devDetachedChildSpawnOptions(),
246
244
  env: {
247
245
  ...process$1.env,
@@ -251,6 +249,8 @@ var DevCommand = class {
251
249
  CODEMATION_CONSUMER_ROOT: prepared.paths.consumerRoot,
252
250
  CODEMATION_CONSUMER_OUTPUT_MANIFEST_PATH: consumerOutputManifestPath,
253
251
  CODEMATION_SKIP_UI_AUTH: prepared.authSettings.skipUiAuth ? "true" : "false",
252
+ AUTH_SECRET: prepared.authSettings.authSecret,
253
+ NEXTAUTH_SECRET: prepared.authSettings.authSecret,
254
254
  NEXT_PUBLIC_CODEMATION_SKIP_UI_AUTH: prepared.authSettings.skipUiAuth ? "true" : "false",
255
255
  CODEMATION_WS_PORT: String(websocketPort),
256
256
  NEXT_PUBLIC_CODEMATION_WS_PORT: String(websocketPort),
@@ -416,7 +416,7 @@ var DevCommand = class {
416
416
  }
417
417
  logConsumerDevHintWhenNeeded(devMode, gatewayPort) {
418
418
  if (devMode !== "consumer") return;
419
- this.cliLogger.info(`codemation dev (consumer): open http://127.0.0.1:${gatewayPort} — requires a built @codemation/next-host (next build). For Next HMR use CODEMATION_DEV_MODE=framework.`);
419
+ this.cliLogger.info(`codemation dev (consumer): open http://127.0.0.1:${gatewayPort} — uses the packaged @codemation/next-host UI. For framework UI HMR, set CODEMATION_DEV_MODE=framework.`);
420
420
  }
421
421
  };
422
422
 
@@ -424,7 +424,7 @@ var DevCommand = class {
424
424
  //#region src/commands/ServeWebCommand.ts
425
425
  var ServeWebCommand = class {
426
426
  require = createRequire(import.meta.url);
427
- constructor(pathResolver, pluginDiscovery, artifactsPublisher, tsRuntime, sourceMapNodeOptions, outputBuilderLoader, envLoader, listenPortResolver) {
427
+ constructor(pathResolver, pluginDiscovery, artifactsPublisher, tsRuntime, sourceMapNodeOptions, outputBuilderLoader, envLoader, listenPortResolver, nextHostConsumerServerCommandFactory) {
428
428
  this.pathResolver = pathResolver;
429
429
  this.pluginDiscovery = pluginDiscovery;
430
430
  this.artifactsPublisher = artifactsPublisher;
@@ -433,6 +433,7 @@ var ServeWebCommand = class {
433
433
  this.outputBuilderLoader = outputBuilderLoader;
434
434
  this.envLoader = envLoader;
435
435
  this.listenPortResolver = listenPortResolver;
436
+ this.nextHostConsumerServerCommandFactory = nextHostConsumerServerCommandFactory;
436
437
  }
437
438
  async execute(consumerRoot, buildOptions) {
438
439
  const paths = await this.pathResolver.resolve(consumerRoot);
@@ -441,6 +442,7 @@ var ServeWebCommand = class {
441
442
  const discoveredPlugins = await this.pluginDiscovery.discover(paths.consumerRoot);
442
443
  const manifest = await this.artifactsPublisher.publish(snapshot, discoveredPlugins);
443
444
  const nextHostRoot = path.dirname(this.require.resolve("@codemation/next-host/package.json"));
445
+ const nextHostCommand = await this.nextHostConsumerServerCommandFactory.create({ nextHostRoot });
444
446
  const consumerEnv = this.envLoader.load(paths.consumerRoot);
445
447
  const nextPort = this.listenPortResolver.resolvePrimaryApplicationPort(process$1.env.PORT);
446
448
  const websocketPort = this.listenPortResolver.resolveWebsocketPortRelativeToHttp({
@@ -448,12 +450,8 @@ var ServeWebCommand = class {
448
450
  publicWebsocketPort: process$1.env.NEXT_PUBLIC_CODEMATION_WS_PORT,
449
451
  websocketPort: process$1.env.CODEMATION_WS_PORT
450
452
  });
451
- const child = spawn("pnpm", [
452
- "exec",
453
- "next",
454
- "start"
455
- ], {
456
- cwd: nextHostRoot,
453
+ const child = spawn(nextHostCommand.command, nextHostCommand.args, {
454
+ cwd: nextHostCommand.cwd,
457
455
  stdio: "inherit",
458
456
  env: {
459
457
  ...process$1.env,
@@ -1504,7 +1502,8 @@ var DevelopmentGatewayNotifier = class {
1504
1502
 
1505
1503
  //#endregion
1506
1504
  //#region src/dev/DevAuthSettingsLoader.ts
1507
- var DevAuthSettingsLoader = class {
1505
+ var DevAuthSettingsLoader = class DevAuthSettingsLoader {
1506
+ static defaultDevelopmentAuthSecret = "codemation-dev-auth-secret-not-for-production";
1508
1507
  constructor(configLoader) {
1509
1508
  this.configLoader = configLoader;
1510
1509
  }
@@ -1516,9 +1515,15 @@ var DevAuthSettingsLoader = class {
1516
1515
  const resolution = await this.configLoader.load({ consumerRoot });
1517
1516
  return {
1518
1517
  authConfigJson: JSON.stringify(resolution.config.auth ?? null),
1518
+ authSecret: this.resolveDevelopmentAuthSecret(process.env),
1519
1519
  skipUiAuth: resolution.config.auth?.allowUnauthenticatedInDevelopment === true
1520
1520
  };
1521
1521
  }
1522
+ resolveDevelopmentAuthSecret(env) {
1523
+ const configuredSecret = env.AUTH_SECRET ?? env.NEXTAUTH_SECRET;
1524
+ if (configuredSecret && configuredSecret.trim().length > 0) return configuredSecret;
1525
+ return DevAuthSettingsLoader.defaultDevelopmentAuthSecret;
1526
+ }
1522
1527
  };
1523
1528
 
1524
1529
  //#endregion
@@ -2022,11 +2027,11 @@ var CliProgram = class {
2022
2027
  program.command("build").description("Build consumer workflows/plugins output and write the manifest.").option("--consumer-root <path>", "Path to the consumer project root (defaults to cwd)").option("--no-source-maps", "Disable .js.map files for emitted workflow modules (recommended for locked-down production bundles).").option("--target <es2020|es2022>", "ECMAScript language version for emitted workflow JavaScript (default: es2022).", "es2022").action(async (opts) => {
2023
2028
  await this.buildCommand.execute(resolveConsumerRoot(opts.consumerRoot), this.buildOptionsParser.parse(opts));
2024
2029
  });
2025
- program.command("dev", { isDefault: true }).description("Start the dev gateway and runtime child. Use CODEMATION_DEV_MODE=framework with Next dev for framework UI HMR; default consumer mode serves API/WebSocket from the gateway only.").option("--consumer-root <path>", "Path to the consumer project root (defaults to cwd)").action(async (opts) => {
2030
+ program.command("dev", { isDefault: true }).description("Start the dev gateway and runtime child. Default consumer mode uses the packaged Codemation UI; use CODEMATION_DEV_MODE=framework for Next dev HMR when working on the host itself.").option("--consumer-root <path>", "Path to the consumer project root (defaults to cwd)").action(async (opts) => {
2026
2031
  await this.devCommand.execute(resolveConsumerRoot(opts.consumerRoot));
2027
2032
  });
2028
2033
  const serve = program.command("serve").description("Run production web or worker processes (no dev watchers).");
2029
- serve.command("web").description("Start the built Next.js Codemation host (next start).").option("--consumer-root <path>", "Path to the consumer project root (defaults to cwd)").option("--no-source-maps", "Disable .js.map files for emitted workflow modules when this command runs the consumer build step.").option("--target <es2020|es2022>", "ECMAScript language version for emitted workflow JavaScript when building consumer output (default: es2022).", "es2022").action(async (opts) => {
2034
+ serve.command("web").description("Start the packaged Codemation web host.").option("--consumer-root <path>", "Path to the consumer project root (defaults to cwd)").option("--no-source-maps", "Disable .js.map files for emitted workflow modules when this command runs the consumer build step.").option("--target <es2020|es2022>", "ECMAScript language version for emitted workflow JavaScript when building consumer output (default: es2022).", "es2022").action(async (opts) => {
2030
2035
  await this.serveWebCommand.execute(resolveConsumerRoot(opts.consumerRoot), this.buildOptionsParser.parse(opts));
2031
2036
  });
2032
2037
  serve.command("worker").description("Start the Codemation worker process.").option("--consumer-root <path>", "Path to the consumer project root (defaults to cwd)").option("--config <path>", "Override path to codemation.config.ts / .js").action(async (opts) => {
@@ -2087,6 +2092,36 @@ var CliPathResolver = class {
2087
2092
  }
2088
2093
  };
2089
2094
 
2095
+ //#endregion
2096
+ //#region src/runtime/NextHostConsumerServerCommandFactory.ts
2097
+ var NextHostConsumerServerCommandFactory = class {
2098
+ async create(args) {
2099
+ const standaloneServerPath = path.resolve(args.nextHostRoot, ".next", "standalone", "packages", "next-host", "server.js");
2100
+ if (await this.exists(standaloneServerPath)) return {
2101
+ command: process$1.execPath,
2102
+ args: [standaloneServerPath],
2103
+ cwd: path.dirname(standaloneServerPath)
2104
+ };
2105
+ return {
2106
+ command: "pnpm",
2107
+ args: [
2108
+ "exec",
2109
+ "next",
2110
+ "start"
2111
+ ],
2112
+ cwd: args.nextHostRoot
2113
+ };
2114
+ }
2115
+ async exists(filePath) {
2116
+ try {
2117
+ await access(filePath);
2118
+ return true;
2119
+ } catch {
2120
+ return false;
2121
+ }
2122
+ }
2123
+ };
2124
+
2090
2125
  //#endregion
2091
2126
  //#region src/runtime/TypeScriptRuntimeConfigurator.ts
2092
2127
  var TypeScriptRuntimeConfigurator = class {
@@ -2276,6 +2311,7 @@ var CliProgramFactory = class {
2276
2311
  const tsRuntime = new TypeScriptRuntimeConfigurator();
2277
2312
  const outputBuilderLoader = new ConsumerOutputBuilderLoader();
2278
2313
  const sourceMapNodeOptions = new SourceMapNodeOptions();
2314
+ const nextHostConsumerServerCommandFactory = new NextHostConsumerServerCommandFactory();
2279
2315
  const tsconfigPreparation = new ConsumerCliTsconfigPreparation();
2280
2316
  const databasePersistenceResolver = new DatabasePersistenceResolver();
2281
2317
  const userAdminBootstrap = new UserAdminCliBootstrap(new CodemationConsumerConfigLoader(), pathResolver, new UserAdminConsumerDotenvLoader(), tsconfigPreparation, databasePersistenceResolver);
@@ -2284,7 +2320,7 @@ var CliProgramFactory = class {
2284
2320
  const databaseMigrationsApplyService = new DatabaseMigrationsApplyService(cliLogger, new UserAdminConsumerDotenvLoader(), tsconfigPreparation, new CodemationConsumerConfigLoader(), new ConsumerDatabaseConnectionResolver(), new CliDatabaseUrlDescriptor(), hostPackageRoot, new PrismaMigrationDeployer());
2285
2321
  const buildOptionsParser = new ConsumerBuildOptionsParser();
2286
2322
  const devConsumerPublishBootstrap = new DevConsumerPublishBootstrap(cliLogger, pluginDiscovery, artifactsPublisher, outputBuilderLoader, buildOptionsParser);
2287
- return new CliProgram(buildOptionsParser, new BuildCommand(cliLogger, pathResolver, pluginDiscovery, artifactsPublisher, tsRuntime, outputBuilderLoader), new DevCommand(pathResolver, pluginDiscovery, tsRuntime, new DevLockFactory(), new DevSourceWatcherFactory(), cliLogger, new DevSessionServicesBuilder(loggerFactory).build(), databaseMigrationsApplyService, new DevBootstrapSummaryFetcher(), new DevCliBannerRenderer(), devConsumerPublishBootstrap, new ConsumerEnvDotenvFilePredicate(), new DevTrackedProcessTreeKiller()), new ServeWebCommand(pathResolver, pluginDiscovery, artifactsPublisher, tsRuntime, sourceMapNodeOptions, outputBuilderLoader, new ConsumerEnvLoader(), new ListenPortResolver()), new ServeWorkerCommand(sourceMapNodeOptions), new DbMigrateCommand(databaseMigrationsApplyService), new UserCreateCommand(new LocalUserCreator(userAdminBootstrap), userAdminCliOptionsParser), new UserListCommand(cliLogger, userAdminBootstrap, new CliDatabaseUrlDescriptor(), userAdminCliOptionsParser));
2323
+ return new CliProgram(buildOptionsParser, new BuildCommand(cliLogger, pathResolver, pluginDiscovery, artifactsPublisher, tsRuntime, outputBuilderLoader), new DevCommand(pathResolver, pluginDiscovery, tsRuntime, new DevLockFactory(), new DevSourceWatcherFactory(), cliLogger, new DevSessionServicesBuilder(loggerFactory).build(), databaseMigrationsApplyService, new DevBootstrapSummaryFetcher(), new DevCliBannerRenderer(), devConsumerPublishBootstrap, new ConsumerEnvDotenvFilePredicate(), new DevTrackedProcessTreeKiller(), nextHostConsumerServerCommandFactory), new ServeWebCommand(pathResolver, pluginDiscovery, artifactsPublisher, tsRuntime, sourceMapNodeOptions, outputBuilderLoader, new ConsumerEnvLoader(), new ListenPortResolver(), nextHostConsumerServerCommandFactory), new ServeWorkerCommand(sourceMapNodeOptions), new DbMigrateCommand(databaseMigrationsApplyService), new UserCreateCommand(new LocalUserCreator(userAdminBootstrap), userAdminCliOptionsParser), new UserListCommand(cliLogger, userAdminBootstrap, new CliDatabaseUrlDescriptor(), userAdminCliOptionsParser));
2288
2324
  }
2289
2325
  };
2290
2326
 
package/dist/bin.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as CliBin } from "./CliBin-DTTnbKz7.js";
1
+ import { t as CliBin } from "./CliBin-900C8Din.js";
2
2
  import process from "node:process";
3
3
  import "reflect-metadata";
4
4
 
package/dist/index.d.ts CHANGED
@@ -23098,13 +23098,16 @@ declare class SourceMapNodeOptions {
23098
23098
  //#region src/dev/DevAuthSettingsLoader.d.ts
23099
23099
  type DevResolvedAuthSettings = Readonly<{
23100
23100
  authConfigJson: string;
23101
+ authSecret: string;
23101
23102
  skipUiAuth: boolean;
23102
23103
  }>;
23103
23104
  declare class DevAuthSettingsLoader {
23104
23105
  private readonly configLoader;
23106
+ static readonly defaultDevelopmentAuthSecret = "codemation-dev-auth-secret-not-for-production";
23105
23107
  constructor(configLoader: CodemationConsumerConfigLoader);
23106
23108
  resolveDevelopmentServerToken(rawToken: string | undefined): string;
23107
23109
  loadForConsumer(consumerRoot: string): Promise<DevResolvedAuthSettings>;
23110
+ resolveDevelopmentAuthSecret(env: NodeJS.ProcessEnv): string;
23108
23111
  }
23109
23112
  //#endregion
23110
23113
  //#region src/dev/DevHttpProbe.d.ts
@@ -23300,6 +23303,19 @@ declare class DevSourceWatcherFactory {
23300
23303
  create(): DevSourceWatcher;
23301
23304
  }
23302
23305
  //#endregion
23306
+ //#region src/runtime/NextHostConsumerServerCommandFactory.d.ts
23307
+ type NextHostConsumerServerCommand = Readonly<{
23308
+ args: ReadonlyArray<string>;
23309
+ command: string;
23310
+ cwd: string;
23311
+ }>;
23312
+ declare class NextHostConsumerServerCommandFactory {
23313
+ create(args: Readonly<{
23314
+ nextHostRoot: string;
23315
+ }>): Promise<NextHostConsumerServerCommand>;
23316
+ private exists;
23317
+ }
23318
+ //#endregion
23303
23319
  //#region src/commands/DevCommand.d.ts
23304
23320
  declare class DevCommand {
23305
23321
  private readonly pathResolver;
@@ -23315,8 +23331,9 @@ declare class DevCommand {
23315
23331
  private readonly devConsumerPublishBootstrap;
23316
23332
  private readonly consumerEnvDotenvFilePredicate;
23317
23333
  private readonly devTrackedProcessTreeKiller;
23334
+ private readonly nextHostConsumerServerCommandFactory;
23318
23335
  private readonly require;
23319
- constructor(pathResolver: CliPathResolver, pluginDiscovery: CodemationPluginDiscovery, tsRuntime: TypeScriptRuntimeConfigurator, devLockFactory: DevLockFactory, devSourceWatcherFactory: DevSourceWatcherFactory, cliLogger: Logger, session: DevSessionServices, databaseMigrationsApplyService: DatabaseMigrationsApplyService, devBootstrapSummaryFetcher: DevBootstrapSummaryFetcher, devCliBannerRenderer: DevCliBannerRenderer, devConsumerPublishBootstrap: DevConsumerPublishBootstrap, consumerEnvDotenvFilePredicate: ConsumerEnvDotenvFilePredicate, devTrackedProcessTreeKiller: DevTrackedProcessTreeKiller);
23336
+ constructor(pathResolver: CliPathResolver, pluginDiscovery: CodemationPluginDiscovery, tsRuntime: TypeScriptRuntimeConfigurator, devLockFactory: DevLockFactory, devSourceWatcherFactory: DevSourceWatcherFactory, cliLogger: Logger, session: DevSessionServices, databaseMigrationsApplyService: DatabaseMigrationsApplyService, devBootstrapSummaryFetcher: DevBootstrapSummaryFetcher, devCliBannerRenderer: DevCliBannerRenderer, devConsumerPublishBootstrap: DevConsumerPublishBootstrap, consumerEnvDotenvFilePredicate: ConsumerEnvDotenvFilePredicate, devTrackedProcessTreeKiller: DevTrackedProcessTreeKiller, nextHostConsumerServerCommandFactory: NextHostConsumerServerCommandFactory);
23320
23337
  execute(consumerRoot: string): Promise<void>;
23321
23338
  private resolveDevModeFromEnv;
23322
23339
  private prepareDevRuntime;
@@ -23349,8 +23366,9 @@ declare class ServeWebCommand {
23349
23366
  private readonly outputBuilderLoader;
23350
23367
  private readonly envLoader;
23351
23368
  private readonly listenPortResolver;
23369
+ private readonly nextHostConsumerServerCommandFactory;
23352
23370
  private readonly require;
23353
- constructor(pathResolver: CliPathResolver, pluginDiscovery: CodemationPluginDiscovery, artifactsPublisher: ConsumerBuildArtifactsPublisher, tsRuntime: TypeScriptRuntimeConfigurator, sourceMapNodeOptions: SourceMapNodeOptions, outputBuilderLoader: ConsumerOutputBuilderLoader, envLoader: ConsumerEnvLoader, listenPortResolver: ListenPortResolver);
23371
+ constructor(pathResolver: CliPathResolver, pluginDiscovery: CodemationPluginDiscovery, artifactsPublisher: ConsumerBuildArtifactsPublisher, tsRuntime: TypeScriptRuntimeConfigurator, sourceMapNodeOptions: SourceMapNodeOptions, outputBuilderLoader: ConsumerOutputBuilderLoader, envLoader: ConsumerEnvLoader, listenPortResolver: ListenPortResolver, nextHostConsumerServerCommandFactory: NextHostConsumerServerCommandFactory);
23354
23372
  execute(consumerRoot: string, buildOptions: ConsumerBuildOptions): Promise<void>;
23355
23373
  }
23356
23374
  //#endregion
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-DTTnbKz7.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-900C8Din.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.2",
3
+ "version": "0.0.3",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -28,11 +28,11 @@
28
28
  "figlet": "^1.11.0",
29
29
  "reflect-metadata": "^0.2.2",
30
30
  "typescript": "^5.9.3",
31
- "@codemation/host": "0.0.2",
32
- "@codemation/next-host": "0.0.2",
33
- "@codemation/dev-gateway": "0.0.2",
34
- "@codemation/runtime-dev": "0.0.2",
35
- "@codemation/worker-cli": "0.0.2"
31
+ "@codemation/dev-gateway": "0.0.3",
32
+ "@codemation/host": "0.0.3",
33
+ "@codemation/runtime-dev": "0.0.3",
34
+ "@codemation/next-host": "0.0.3",
35
+ "@codemation/worker-cli": "0.0.3"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/node": "^25.3.5",
@@ -28,6 +28,7 @@ import { DevSourceWatcherFactory } from "./dev/Runner";
28
28
  import { CliProgram } from "./Program";
29
29
  import { CliPathResolver } from "./path/CliPathResolver";
30
30
  import { ListenPortResolver } from "./runtime/ListenPortResolver";
31
+ import { NextHostConsumerServerCommandFactory } from "./runtime/NextHostConsumerServerCommandFactory";
31
32
  import { SourceMapNodeOptions } from "./runtime/SourceMapNodeOptions";
32
33
  import { TypeScriptRuntimeConfigurator } from "./runtime/TypeScriptRuntimeConfigurator";
33
34
  import { LocalUserCreator } from "./user/LocalUserCreator";
@@ -51,6 +52,7 @@ export class CliProgramFactory {
51
52
  const tsRuntime = new TypeScriptRuntimeConfigurator();
52
53
  const outputBuilderLoader = new ConsumerOutputBuilderLoader();
53
54
  const sourceMapNodeOptions = new SourceMapNodeOptions();
55
+ const nextHostConsumerServerCommandFactory = new NextHostConsumerServerCommandFactory();
54
56
  const tsconfigPreparation = new ConsumerCliTsconfigPreparation();
55
57
  const databasePersistenceResolver = new DatabasePersistenceResolver();
56
58
  const userAdminBootstrap = new UserAdminCliBootstrap(
@@ -98,6 +100,7 @@ export class CliProgramFactory {
98
100
  devConsumerPublishBootstrap,
99
101
  new ConsumerEnvDotenvFilePredicate(),
100
102
  new DevTrackedProcessTreeKiller(),
103
+ nextHostConsumerServerCommandFactory,
101
104
  ),
102
105
  new ServeWebCommand(
103
106
  pathResolver,
@@ -108,6 +111,7 @@ export class CliProgramFactory {
108
111
  outputBuilderLoader,
109
112
  new ConsumerEnvLoader(),
110
113
  new ListenPortResolver(),
114
+ nextHostConsumerServerCommandFactory,
111
115
  ),
112
116
  new ServeWorkerCommand(sourceMapNodeOptions),
113
117
  new DbMigrateCommand(databaseMigrationsApplyService),
package/src/Program.ts CHANGED
@@ -57,7 +57,7 @@ export class CliProgram {
57
57
  program
58
58
  .command("dev", { isDefault: true })
59
59
  .description(
60
- "Start the dev gateway and runtime child. Use CODEMATION_DEV_MODE=framework with Next dev for framework UI HMR; default consumer mode serves API/WebSocket from the gateway only.",
60
+ "Start the dev gateway and runtime child. Default consumer mode uses the packaged Codemation UI; use CODEMATION_DEV_MODE=framework for Next dev HMR when working on the host itself.",
61
61
  )
62
62
  .option("--consumer-root <path>", "Path to the consumer project root (defaults to cwd)")
63
63
  .action(async (opts: Readonly<{ consumerRoot?: string }>) => {
@@ -68,7 +68,7 @@ export class CliProgram {
68
68
 
69
69
  serve
70
70
  .command("web")
71
- .description("Start the built Next.js Codemation host (next start).")
71
+ .description("Start the packaged Codemation web host.")
72
72
  .option("--consumer-root <path>", "Path to the consumer project root (defaults to cwd)")
73
73
  .option(
74
74
  "--no-source-maps",
@@ -17,6 +17,7 @@ import { DevTrackedProcessTreeKiller } from "../dev/DevTrackedProcessTreeKiller"
17
17
  import { DevSourceWatcherFactory } from "../dev/Runner";
18
18
  import { CliPathResolver, type CliPaths } from "../path/CliPathResolver";
19
19
  import { TypeScriptRuntimeConfigurator } from "../runtime/TypeScriptRuntimeConfigurator";
20
+ import { NextHostConsumerServerCommandFactory } from "../runtime/NextHostConsumerServerCommandFactory";
20
21
 
21
22
  import type { DevResolvedAuthSettings } from "../dev/DevAuthSettingsLoader";
22
23
 
@@ -39,6 +40,7 @@ export class DevCommand {
39
40
  private readonly devConsumerPublishBootstrap: DevConsumerPublishBootstrap,
40
41
  private readonly consumerEnvDotenvFilePredicate: ConsumerEnvDotenvFilePredicate,
41
42
  private readonly devTrackedProcessTreeKiller: DevTrackedProcessTreeKiller,
43
+ private readonly nextHostConsumerServerCommandFactory: NextHostConsumerServerCommandFactory,
42
44
  ) {}
43
45
 
44
46
  async execute(consumerRoot: string): Promise<void> {
@@ -163,14 +165,15 @@ export class DevCommand {
163
165
  const uiProxyBase = `http://127.0.0.1:${uiPort}`;
164
166
  const nextHostPackageJsonPath = this.require.resolve("@codemation/next-host/package.json");
165
167
  const nextHostRoot = path.dirname(nextHostPackageJsonPath);
168
+ const nextHostCommand = await this.nextHostConsumerServerCommandFactory.create({ nextHostRoot });
166
169
  const consumerOutputManifestPath = path.resolve(
167
170
  prepared.paths.consumerRoot,
168
171
  ".codemation",
169
172
  "output",
170
173
  "current.json",
171
174
  );
172
- state.currentUiNext = spawn("pnpm", ["exec", "next", "start"], {
173
- cwd: nextHostRoot,
175
+ state.currentUiNext = spawn(nextHostCommand.command, nextHostCommand.args, {
176
+ cwd: nextHostCommand.cwd,
174
177
  ...this.devDetachedChildSpawnOptions(),
175
178
  env: {
176
179
  ...process.env,
@@ -180,6 +183,8 @@ export class DevCommand {
180
183
  CODEMATION_CONSUMER_ROOT: prepared.paths.consumerRoot,
181
184
  CODEMATION_CONSUMER_OUTPUT_MANIFEST_PATH: consumerOutputManifestPath,
182
185
  CODEMATION_SKIP_UI_AUTH: prepared.authSettings.skipUiAuth ? "true" : "false",
186
+ AUTH_SECRET: prepared.authSettings.authSecret,
187
+ NEXTAUTH_SECRET: prepared.authSettings.authSecret,
183
188
  NEXT_PUBLIC_CODEMATION_SKIP_UI_AUTH: prepared.authSettings.skipUiAuth ? "true" : "false",
184
189
  CODEMATION_WS_PORT: String(websocketPort),
185
190
  NEXT_PUBLIC_CODEMATION_WS_PORT: String(websocketPort),
@@ -385,7 +390,7 @@ export class DevCommand {
385
390
  return;
386
391
  }
387
392
  this.cliLogger.info(
388
- `codemation dev (consumer): open http://127.0.0.1:${gatewayPort} — requires a built @codemation/next-host (next build). For Next HMR use CODEMATION_DEV_MODE=framework.`,
393
+ `codemation dev (consumer): open http://127.0.0.1:${gatewayPort} — uses the packaged @codemation/next-host UI. For framework UI HMR, set CODEMATION_DEV_MODE=framework.`,
389
394
  );
390
395
  }
391
396
  }
@@ -10,6 +10,7 @@ import type { ConsumerBuildOptions } from "../consumer/consumerBuildOptions.type
10
10
  import { ConsumerOutputBuilderLoader } from "../consumer/Loader";
11
11
  import { CliPathResolver } from "../path/CliPathResolver";
12
12
  import { ListenPortResolver } from "../runtime/ListenPortResolver";
13
+ import { NextHostConsumerServerCommandFactory } from "../runtime/NextHostConsumerServerCommandFactory";
13
14
  import { SourceMapNodeOptions } from "../runtime/SourceMapNodeOptions";
14
15
  import { TypeScriptRuntimeConfigurator } from "../runtime/TypeScriptRuntimeConfigurator";
15
16
 
@@ -25,6 +26,7 @@ export class ServeWebCommand {
25
26
  private readonly outputBuilderLoader: ConsumerOutputBuilderLoader,
26
27
  private readonly envLoader: ConsumerEnvLoader,
27
28
  private readonly listenPortResolver: ListenPortResolver,
29
+ private readonly nextHostConsumerServerCommandFactory: NextHostConsumerServerCommandFactory,
28
30
  ) {}
29
31
 
30
32
  async execute(consumerRoot: string, buildOptions: ConsumerBuildOptions): Promise<void> {
@@ -35,6 +37,7 @@ export class ServeWebCommand {
35
37
  const discoveredPlugins = await this.pluginDiscovery.discover(paths.consumerRoot);
36
38
  const manifest = await this.artifactsPublisher.publish(snapshot, discoveredPlugins);
37
39
  const nextHostRoot = path.dirname(this.require.resolve("@codemation/next-host/package.json"));
40
+ const nextHostCommand = await this.nextHostConsumerServerCommandFactory.create({ nextHostRoot });
38
41
  const consumerEnv = this.envLoader.load(paths.consumerRoot);
39
42
  const nextPort = this.listenPortResolver.resolvePrimaryApplicationPort(process.env.PORT);
40
43
  const websocketPort = this.listenPortResolver.resolveWebsocketPortRelativeToHttp({
@@ -42,8 +45,8 @@ export class ServeWebCommand {
42
45
  publicWebsocketPort: process.env.NEXT_PUBLIC_CODEMATION_WS_PORT,
43
46
  websocketPort: process.env.CODEMATION_WS_PORT,
44
47
  });
45
- const child = spawn("pnpm", ["exec", "next", "start"], {
46
- cwd: nextHostRoot,
48
+ const child = spawn(nextHostCommand.command, nextHostCommand.args, {
49
+ cwd: nextHostCommand.cwd,
47
50
  stdio: "inherit",
48
51
  env: {
49
52
  ...process.env,
@@ -4,10 +4,13 @@ import { CodemationConsumerConfigLoader } from "@codemation/host/server";
4
4
 
5
5
  export type DevResolvedAuthSettings = Readonly<{
6
6
  authConfigJson: string;
7
+ authSecret: string;
7
8
  skipUiAuth: boolean;
8
9
  }>;
9
10
 
10
11
  export class DevAuthSettingsLoader {
12
+ static readonly defaultDevelopmentAuthSecret = "codemation-dev-auth-secret-not-for-production";
13
+
11
14
  constructor(private readonly configLoader: CodemationConsumerConfigLoader) {}
12
15
 
13
16
  resolveDevelopmentServerToken(rawToken: string | undefined): string {
@@ -21,7 +24,16 @@ export class DevAuthSettingsLoader {
21
24
  const resolution = await this.configLoader.load({ consumerRoot });
22
25
  return {
23
26
  authConfigJson: JSON.stringify(resolution.config.auth ?? null),
27
+ authSecret: this.resolveDevelopmentAuthSecret(process.env),
24
28
  skipUiAuth: resolution.config.auth?.allowUnauthenticatedInDevelopment === true,
25
29
  };
26
30
  }
31
+
32
+ resolveDevelopmentAuthSecret(env: NodeJS.ProcessEnv): string {
33
+ const configuredSecret = env.AUTH_SECRET ?? env.NEXTAUTH_SECRET;
34
+ if (configuredSecret && configuredSecret.trim().length > 0) {
35
+ return configuredSecret;
36
+ }
37
+ return DevAuthSettingsLoader.defaultDevelopmentAuthSecret;
38
+ }
27
39
  }
@@ -0,0 +1,36 @@
1
+ import { access } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import process from "node:process";
4
+
5
+ export type NextHostConsumerServerCommand = Readonly<{
6
+ args: ReadonlyArray<string>;
7
+ command: string;
8
+ cwd: string;
9
+ }>;
10
+
11
+ export class NextHostConsumerServerCommandFactory {
12
+ async create(args: Readonly<{ nextHostRoot: string }>): Promise<NextHostConsumerServerCommand> {
13
+ const standaloneServerPath = path.resolve(args.nextHostRoot, ".next", "standalone", "packages", "next-host", "server.js");
14
+ if (await this.exists(standaloneServerPath)) {
15
+ return {
16
+ command: process.execPath,
17
+ args: [standaloneServerPath],
18
+ cwd: path.dirname(standaloneServerPath),
19
+ };
20
+ }
21
+ return {
22
+ command: "pnpm",
23
+ args: ["exec", "next", "start"],
24
+ cwd: args.nextHostRoot,
25
+ };
26
+ }
27
+
28
+ private async exists(filePath: string): Promise<boolean> {
29
+ try {
30
+ await access(filePath);
31
+ return true;
32
+ } catch {
33
+ return false;
34
+ }
35
+ }
36
+ }