@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
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import process$1 from "node:process";
|
|
3
|
-
import { AppConfigLoader, CodemationConsumerConfigLoader,
|
|
4
|
-
import { ApiPaths, AppContainerFactory, AppContainerLifecycle, ApplicationTokens,
|
|
3
|
+
import { AppConfigLoader, CodemationConsumerConfigLoader, CodemationPluginDiscovery, WorkflowDiscoveryPathSegmentsComputer, WorkflowModulePathFinder } from "@codemation/host/server";
|
|
4
|
+
import { ApiPaths, AppContainerFactory, AppContainerLifecycle, ApplicationTokens, CodemationPluginPackageMetadata, DatabaseMigrations, ListUserAccountsQuery, PrismaClient, UpsertLocalBootstrapUserCommand, WorkerRuntime } from "@codemation/host";
|
|
5
5
|
import { AppContainerFactory as AppContainerFactory$1, AppContainerLifecycle as AppContainerLifecycle$1, CodemationHonoApiApp, CodemationPluginListMerger, FrontendRuntime, ServerLoggerFactory, logLevelPolicyFactory } from "@codemation/host/next/server";
|
|
6
|
-
import { randomUUID } from "node:crypto";
|
|
7
|
-
import { access, copyFile, cp, mkdir, open, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
8
|
-
import path from "node:path";
|
|
9
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
10
6
|
import { execFile, spawn } from "node:child_process";
|
|
7
|
+
import path from "node:path";
|
|
11
8
|
import { existsSync, readFileSync } from "node:fs";
|
|
12
9
|
import { config, parse } from "dotenv";
|
|
13
10
|
import { watch } from "chokidar";
|
|
11
|
+
import { randomUUID } from "node:crypto";
|
|
12
|
+
import { access, copyFile, cp, mkdir, open, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
14
13
|
import ts from "typescript";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
15
|
import { PrismaMigrationDeployer } from "@codemation/host/persistence";
|
|
16
16
|
import boxen from "boxen";
|
|
17
17
|
import chalk from "chalk";
|
|
@@ -25,52 +25,6 @@ import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
|
25
25
|
import { createServer as createServer$1 } from "node:net";
|
|
26
26
|
import { Command } from "commander";
|
|
27
27
|
|
|
28
|
-
//#region src/build/ConsumerBuildArtifactsPublisher.ts
|
|
29
|
-
var ConsumerBuildArtifactsPublisher = class {
|
|
30
|
-
async publish(snapshot, discoveredPlugins) {
|
|
31
|
-
const pluginEntryPath = await this.writeDiscoveredPluginsOutput(snapshot, discoveredPlugins);
|
|
32
|
-
return await this.writeBuildManifest(snapshot, pluginEntryPath);
|
|
33
|
-
}
|
|
34
|
-
async writeDiscoveredPluginsOutput(snapshot, discoveredPlugins) {
|
|
35
|
-
const outputPath = path.resolve(snapshot.emitOutputRoot, "plugins.js");
|
|
36
|
-
await mkdir(path.dirname(outputPath), { recursive: true });
|
|
37
|
-
const outputLines = ["const codemationDiscoveredPlugins = [];", ""];
|
|
38
|
-
discoveredPlugins.forEach((discoveredPlugin, index) => {
|
|
39
|
-
const pluginFileUrl = pathToFileURL(path.resolve(discoveredPlugin.packageRoot, discoveredPlugin.manifest.entry)).href;
|
|
40
|
-
const exportNameAccessor = discoveredPlugin.manifest.exportName ? `pluginModule${index}[${JSON.stringify(discoveredPlugin.manifest.exportName)}]` : `pluginModule${index}.default ?? pluginModule${index}.codemationPlugin`;
|
|
41
|
-
outputLines.push(`const pluginModule${index} = await import(${JSON.stringify(pluginFileUrl)});`);
|
|
42
|
-
outputLines.push(`const pluginValue${index} = ${exportNameAccessor};`);
|
|
43
|
-
outputLines.push(`if (pluginValue${index} && typeof pluginValue${index}.register === "function") {`);
|
|
44
|
-
outputLines.push(` codemationDiscoveredPlugins.push(pluginValue${index});`);
|
|
45
|
-
outputLines.push(`} else if (typeof pluginValue${index} === "function" && pluginValue${index}.prototype && typeof pluginValue${index}.prototype.register === "function") {`);
|
|
46
|
-
outputLines.push(` codemationDiscoveredPlugins.push(new pluginValue${index}());`);
|
|
47
|
-
outputLines.push("}");
|
|
48
|
-
outputLines.push("");
|
|
49
|
-
});
|
|
50
|
-
outputLines.push("export { codemationDiscoveredPlugins };");
|
|
51
|
-
outputLines.push("export default codemationDiscoveredPlugins;");
|
|
52
|
-
outputLines.push("");
|
|
53
|
-
await writeFile(outputPath, outputLines.join("\n"), "utf8");
|
|
54
|
-
return outputPath;
|
|
55
|
-
}
|
|
56
|
-
async writeBuildManifest(snapshot, pluginEntryPath) {
|
|
57
|
-
const manifest = {
|
|
58
|
-
buildVersion: snapshot.buildVersion,
|
|
59
|
-
consumerRoot: snapshot.consumerRoot,
|
|
60
|
-
entryPath: snapshot.outputEntryPath,
|
|
61
|
-
manifestPath: snapshot.manifestPath,
|
|
62
|
-
pluginEntryPath,
|
|
63
|
-
workflowSourcePaths: snapshot.workflowSourcePaths
|
|
64
|
-
};
|
|
65
|
-
await mkdir(path.dirname(snapshot.manifestPath), { recursive: true });
|
|
66
|
-
const temporaryManifestPath = `${snapshot.manifestPath}.${snapshot.buildVersion}.${randomUUID()}.tmp`;
|
|
67
|
-
await writeFile(temporaryManifestPath, JSON.stringify(manifest, null, 2), "utf8");
|
|
68
|
-
await rename(temporaryManifestPath, snapshot.manifestPath);
|
|
69
|
-
return manifest;
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
//#endregion
|
|
74
28
|
//#region src/build/ConsumerBuildOptionsParser.ts
|
|
75
29
|
var ConsumerBuildOptionsParser = class {
|
|
76
30
|
parse(args) {
|
|
@@ -90,23 +44,18 @@ var ConsumerBuildOptionsParser = class {
|
|
|
90
44
|
//#endregion
|
|
91
45
|
//#region src/commands/BuildCommand.ts
|
|
92
46
|
var BuildCommand = class {
|
|
93
|
-
constructor(cliLogger, pathResolver,
|
|
47
|
+
constructor(cliLogger, pathResolver, consumerOutputBuilderFactory, tsRuntime) {
|
|
94
48
|
this.cliLogger = cliLogger;
|
|
95
49
|
this.pathResolver = pathResolver;
|
|
96
|
-
this.
|
|
97
|
-
this.artifactsPublisher = artifactsPublisher;
|
|
50
|
+
this.consumerOutputBuilderFactory = consumerOutputBuilderFactory;
|
|
98
51
|
this.tsRuntime = tsRuntime;
|
|
99
|
-
this.outputBuilderLoader = outputBuilderLoader;
|
|
100
52
|
}
|
|
101
53
|
async execute(consumerRoot, buildOptions) {
|
|
102
54
|
const paths = await this.pathResolver.resolve(consumerRoot);
|
|
103
55
|
this.tsRuntime.configure(paths.repoRoot);
|
|
104
|
-
const snapshot = await this.
|
|
105
|
-
const discoveredPlugins = await this.pluginDiscovery.discover(paths.consumerRoot);
|
|
106
|
-
const manifest = await this.artifactsPublisher.publish(snapshot, discoveredPlugins);
|
|
56
|
+
const snapshot = await this.consumerOutputBuilderFactory.create(paths.consumerRoot, { buildOptions }).ensureBuilt();
|
|
107
57
|
this.cliLogger.info(`Built consumer output: ${snapshot.outputEntryPath}`);
|
|
108
|
-
this.cliLogger.info(`
|
|
109
|
-
this.cliLogger.info(`Published build: ${manifest.buildVersion}`);
|
|
58
|
+
this.cliLogger.info(`Workflow modules emitted: ${snapshot.workflowSourcePaths.length}`);
|
|
110
59
|
}
|
|
111
60
|
};
|
|
112
61
|
|
|
@@ -125,7 +74,7 @@ var DbMigrateCommand = class {
|
|
|
125
74
|
//#region src/commands/DevCommand.ts
|
|
126
75
|
var DevCommand = class {
|
|
127
76
|
require = createRequire(import.meta.url);
|
|
128
|
-
constructor(pathResolver, tsRuntime, devLockFactory, devSourceWatcherFactory, cliLogger, session, databaseMigrationsApplyService, devBootstrapSummaryFetcher, devCliBannerRenderer,
|
|
77
|
+
constructor(pathResolver, tsRuntime, devLockFactory, devSourceWatcherFactory, cliLogger, session, databaseMigrationsApplyService, devBootstrapSummaryFetcher, devCliBannerRenderer, consumerEnvDotenvFilePredicate, devTrackedProcessTreeKiller, nextHostConsumerServerCommandFactory, devApiRuntimeFactory, cliDevProxyServerFactory, devRebuildQueueFactory) {
|
|
129
78
|
this.pathResolver = pathResolver;
|
|
130
79
|
this.tsRuntime = tsRuntime;
|
|
131
80
|
this.devLockFactory = devLockFactory;
|
|
@@ -135,7 +84,6 @@ var DevCommand = class {
|
|
|
135
84
|
this.databaseMigrationsApplyService = databaseMigrationsApplyService;
|
|
136
85
|
this.devBootstrapSummaryFetcher = devBootstrapSummaryFetcher;
|
|
137
86
|
this.devCliBannerRenderer = devCliBannerRenderer;
|
|
138
|
-
this.devConsumerPublishBootstrap = devConsumerPublishBootstrap;
|
|
139
87
|
this.consumerEnvDotenvFilePredicate = consumerEnvDotenvFilePredicate;
|
|
140
88
|
this.devTrackedProcessTreeKiller = devTrackedProcessTreeKiller;
|
|
141
89
|
this.nextHostConsumerServerCommandFactory = nextHostConsumerServerCommandFactory;
|
|
@@ -145,10 +93,10 @@ var DevCommand = class {
|
|
|
145
93
|
}
|
|
146
94
|
async execute(args) {
|
|
147
95
|
const paths = await this.pathResolver.resolve(args.consumerRoot);
|
|
96
|
+
const commandName = args.commandName ?? "dev";
|
|
148
97
|
this.devCliBannerRenderer.renderBrandHeader();
|
|
149
98
|
this.tsRuntime.configure(paths.repoRoot);
|
|
150
|
-
await this.databaseMigrationsApplyService.applyForConsumer(paths.consumerRoot);
|
|
151
|
-
await this.devConsumerPublishBootstrap.ensurePublished(paths);
|
|
99
|
+
await this.databaseMigrationsApplyService.applyForConsumer(paths.consumerRoot, { configPath: args.configPathOverride });
|
|
152
100
|
const devMode = this.resolveDevMode(args);
|
|
153
101
|
const { nextPort, gatewayPort } = await this.session.sessionPorts.resolve({
|
|
154
102
|
devMode,
|
|
@@ -160,24 +108,28 @@ var DevCommand = class {
|
|
|
160
108
|
consumerRoot: paths.consumerRoot,
|
|
161
109
|
nextPort: devMode === "watch-framework" ? nextPort : gatewayPort
|
|
162
110
|
});
|
|
163
|
-
const authSettings = await this.session.
|
|
111
|
+
const authSettings = await this.session.nextHostEdgeSeedLoader.loadForConsumer(paths.consumerRoot, { configPathOverride: args.configPathOverride });
|
|
164
112
|
const watcher = this.devSourceWatcherFactory.create();
|
|
165
113
|
const processState = this.createInitialProcessState();
|
|
166
114
|
let proxyServer = null;
|
|
167
115
|
try {
|
|
168
|
-
const prepared = await this.prepareDevRuntime(paths, devMode, nextPort, gatewayPort, authSettings);
|
|
116
|
+
const prepared = await this.prepareDevRuntime(paths, devMode, nextPort, gatewayPort, authSettings, args.configPathOverride);
|
|
169
117
|
const stopPromise = this.wireStopPromise(processState);
|
|
170
|
-
const uiProxyBase = await this.
|
|
118
|
+
const uiProxyBase = await this.preparePackagedUiBaseUrlWhenNeeded(prepared, processState);
|
|
171
119
|
proxyServer = await this.startProxyServer(prepared.gatewayPort, uiProxyBase);
|
|
172
120
|
const gatewayBaseUrl = this.gatewayBaseHttpUrl(gatewayPort);
|
|
173
121
|
await this.bootInitialRuntime(prepared, processState, proxyServer);
|
|
174
122
|
await this.session.devHttpProbe.waitUntilBootstrapSummaryReady(gatewayBaseUrl);
|
|
175
123
|
const initialSummary = await this.devBootstrapSummaryFetcher.fetch(gatewayBaseUrl);
|
|
176
124
|
if (initialSummary) this.devCliBannerRenderer.renderRuntimeSummary(initialSummary);
|
|
125
|
+
await this.startPackagedUiWhenNeeded(prepared, processState, uiProxyBase);
|
|
177
126
|
this.bindShutdownSignalsToChildProcesses(processState, proxyServer);
|
|
178
127
|
await this.spawnDevUiWhenNeeded(prepared, processState, gatewayBaseUrl);
|
|
179
|
-
await this.startWatcherForSourceRestart(prepared, processState, watcher, devMode, gatewayBaseUrl, proxyServer
|
|
180
|
-
|
|
128
|
+
await this.startWatcherForSourceRestart(prepared, processState, watcher, devMode, gatewayBaseUrl, proxyServer, {
|
|
129
|
+
commandName,
|
|
130
|
+
configPathOverride: args.configPathOverride
|
|
131
|
+
});
|
|
132
|
+
this.logPackagedUiDevHintWhenNeeded(devMode, gatewayPort, commandName);
|
|
181
133
|
await stopPromise;
|
|
182
134
|
} finally {
|
|
183
135
|
processState.stopRequested = true;
|
|
@@ -190,14 +142,15 @@ var DevCommand = class {
|
|
|
190
142
|
if (args.watchFramework === true || process$1.env.CODEMATION_DEV_MODE === "framework") return "watch-framework";
|
|
191
143
|
return "packaged-ui";
|
|
192
144
|
}
|
|
193
|
-
async prepareDevRuntime(paths, devMode, nextPort, gatewayPort, authSettings) {
|
|
145
|
+
async prepareDevRuntime(paths, devMode, nextPort, gatewayPort, authSettings, configPathOverride) {
|
|
194
146
|
return {
|
|
195
147
|
paths,
|
|
148
|
+
configPathOverride,
|
|
196
149
|
devMode,
|
|
197
150
|
nextPort,
|
|
198
151
|
gatewayPort,
|
|
199
152
|
authSettings,
|
|
200
|
-
developmentServerToken: this.session.
|
|
153
|
+
developmentServerToken: this.session.nextHostEdgeSeedLoader.resolveDevelopmentServerToken(process$1.env.CODEMATION_DEV_SERVER_TOKEN),
|
|
201
154
|
consumerEnv: this.session.consumerEnvLoader.load(paths.consumerRoot)
|
|
202
155
|
};
|
|
203
156
|
}
|
|
@@ -222,30 +175,30 @@ var DevCommand = class {
|
|
|
222
175
|
gatewayBaseHttpUrl(gatewayPort) {
|
|
223
176
|
return `http://127.0.0.1:${gatewayPort}`;
|
|
224
177
|
}
|
|
225
|
-
async
|
|
178
|
+
async preparePackagedUiBaseUrlWhenNeeded(prepared, state) {
|
|
226
179
|
if (prepared.devMode !== "packaged-ui") return "";
|
|
227
|
-
const websocketPort = prepared.gatewayPort;
|
|
228
180
|
const uiProxyBase = state.currentPackagedUiBaseUrl ?? `http://127.0.0.1:${await this.session.loopbackPortAllocator.allocate()}`;
|
|
229
181
|
state.currentPackagedUiBaseUrl = uiProxyBase;
|
|
230
|
-
await this.spawnPackagedUi(prepared, state, prepared.authSettings, websocketPort, uiProxyBase);
|
|
231
182
|
return uiProxyBase;
|
|
232
183
|
}
|
|
184
|
+
async startPackagedUiWhenNeeded(prepared, state, uiProxyBase) {
|
|
185
|
+
if (prepared.devMode !== "packaged-ui" || uiProxyBase.length === 0) return;
|
|
186
|
+
await this.spawnPackagedUi(prepared, state, prepared.authSettings, prepared.gatewayPort, uiProxyBase);
|
|
187
|
+
}
|
|
233
188
|
async spawnPackagedUi(prepared, state, authSettings, websocketPort, uiProxyBase) {
|
|
234
189
|
const nextHostPackageJsonPath = this.require.resolve("@codemation/next-host/package.json");
|
|
235
190
|
const nextHostRoot = path.dirname(nextHostPackageJsonPath);
|
|
236
191
|
const nextHostCommand = await this.nextHostConsumerServerCommandFactory.create({ nextHostRoot });
|
|
237
|
-
const consumerOutputManifestPath = path.resolve(prepared.paths.consumerRoot, ".codemation", "output", "current.json");
|
|
238
192
|
const uiPort = Number(new URL(uiProxyBase).port);
|
|
239
193
|
const nextHostEnvironment = this.session.nextHostEnvBuilder.buildConsumerUiProxy({
|
|
240
|
-
authConfigJson: authSettings.authConfigJson,
|
|
241
194
|
authSecret: authSettings.authSecret,
|
|
195
|
+
configPathOverride: prepared.configPathOverride,
|
|
242
196
|
consumerRoot: prepared.paths.consumerRoot,
|
|
243
|
-
consumerOutputManifestPath,
|
|
244
197
|
developmentServerToken: prepared.developmentServerToken,
|
|
245
198
|
nextPort: uiPort,
|
|
246
199
|
publicBaseUrl: this.gatewayBaseHttpUrl(prepared.gatewayPort),
|
|
247
200
|
runtimeDevUrl: this.gatewayBaseHttpUrl(prepared.gatewayPort),
|
|
248
|
-
skipUiAuth: authSettings.
|
|
201
|
+
skipUiAuth: !authSettings.uiAuthEnabled,
|
|
249
202
|
websocketPort
|
|
250
203
|
});
|
|
251
204
|
state.currentPackagedUi = spawn(nextHostCommand.command, nextHostCommand.args, {
|
|
@@ -319,11 +272,12 @@ var DevCommand = class {
|
|
|
319
272
|
const nextHostPackageJsonPath = this.require.resolve("@codemation/next-host/package.json");
|
|
320
273
|
const nextHostRoot = path.dirname(nextHostPackageJsonPath);
|
|
321
274
|
const nextHostEnvironment = this.session.nextHostEnvBuilder.build({
|
|
322
|
-
|
|
275
|
+
authSecret: authSettings.authSecret,
|
|
276
|
+
configPathOverride: prepared.configPathOverride,
|
|
323
277
|
consumerRoot: prepared.paths.consumerRoot,
|
|
324
278
|
developmentServerToken: prepared.developmentServerToken,
|
|
325
279
|
nextPort: prepared.nextPort,
|
|
326
|
-
skipUiAuth: authSettings.
|
|
280
|
+
skipUiAuth: !authSettings.uiAuthEnabled,
|
|
327
281
|
websocketPort,
|
|
328
282
|
runtimeDevUrl: gatewayBaseUrl
|
|
329
283
|
});
|
|
@@ -354,7 +308,7 @@ var DevCommand = class {
|
|
|
354
308
|
});
|
|
355
309
|
await this.session.devHttpProbe.waitUntilUrlRespondsOk(`http://127.0.0.1:${prepared.nextPort}/`);
|
|
356
310
|
}
|
|
357
|
-
async startWatcherForSourceRestart(prepared, state, watcher, devMode, gatewayBaseUrl, proxyServer) {
|
|
311
|
+
async startWatcherForSourceRestart(prepared, state, watcher, devMode, gatewayBaseUrl, proxyServer, options) {
|
|
358
312
|
const rebuildQueue = this.devRebuildQueueFactory.create({ run: async (request) => {
|
|
359
313
|
await this.runQueuedRebuild(prepared, state, gatewayBaseUrl, proxyServer, request);
|
|
360
314
|
} });
|
|
@@ -370,18 +324,14 @@ var DevCommand = class {
|
|
|
370
324
|
return;
|
|
371
325
|
}
|
|
372
326
|
try {
|
|
373
|
-
const shouldRepublishConsumerOutput = this.session.sourceChangeClassifier.shouldRepublishConsumerOutput({
|
|
374
|
-
changedPaths,
|
|
375
|
-
consumerRoot: prepared.paths.consumerRoot
|
|
376
|
-
});
|
|
377
327
|
const shouldRestartUi = this.session.sourceChangeClassifier.requiresUiRestart({
|
|
378
328
|
changedPaths,
|
|
379
329
|
consumerRoot: prepared.paths.consumerRoot
|
|
380
330
|
});
|
|
381
|
-
process$1.stdout.write(shouldRestartUi ?
|
|
331
|
+
process$1.stdout.write(shouldRestartUi ? `\n[codemation] Source change detected — rebuilding for \`${options.commandName}\`, restarting the runtime, and restarting the UI…\n` : `\n[codemation] Source change detected — rebuilding for \`${options.commandName}\` and restarting the runtime…\n`);
|
|
382
332
|
await rebuildQueue.enqueue({
|
|
383
333
|
changedPaths,
|
|
384
|
-
|
|
334
|
+
configPathOverride: options.configPathOverride,
|
|
385
335
|
shouldRestartUi
|
|
386
336
|
});
|
|
387
337
|
} catch (error) {
|
|
@@ -395,7 +345,6 @@ var DevCommand = class {
|
|
|
395
345
|
proxyServer.setBuildStatus("building");
|
|
396
346
|
proxyServer.broadcastBuildStarted();
|
|
397
347
|
try {
|
|
398
|
-
if (request.shouldRepublishConsumerOutput) await this.devConsumerPublishBootstrap.ensurePublished(prepared.paths);
|
|
399
348
|
await this.stopCurrentRuntime(state, proxyServer);
|
|
400
349
|
process$1.stdout.write("[codemation] Waiting for runtime to accept traffic…\n");
|
|
401
350
|
const runtime = await this.createRuntime(prepared);
|
|
@@ -418,7 +367,7 @@ var DevCommand = class {
|
|
|
418
367
|
}
|
|
419
368
|
}
|
|
420
369
|
async restartUiAfterSourceChange(prepared, state, gatewayBaseUrl) {
|
|
421
|
-
const refreshedAuthSettings = await this.session.
|
|
370
|
+
const refreshedAuthSettings = await this.session.nextHostEdgeSeedLoader.loadForConsumer(prepared.paths.consumerRoot, { configPathOverride: prepared.configPathOverride });
|
|
422
371
|
process$1.stdout.write("[codemation] Restarting the UI process to apply source changes…\n");
|
|
423
372
|
state.isRestartingUi = true;
|
|
424
373
|
try {
|
|
@@ -465,6 +414,7 @@ var DevCommand = class {
|
|
|
465
414
|
async createRuntime(prepared) {
|
|
466
415
|
const runtimeEnvironment = this.session.consumerEnvLoader.mergeIntoProcessEnvironment(process$1.env, prepared.consumerEnv);
|
|
467
416
|
return await this.devApiRuntimeFactory.create({
|
|
417
|
+
configPathOverride: prepared.configPathOverride,
|
|
468
418
|
consumerRoot: prepared.paths.consumerRoot,
|
|
469
419
|
runtimeWorkingDirectory: process$1.cwd(),
|
|
470
420
|
env: {
|
|
@@ -477,9 +427,27 @@ var DevCommand = class {
|
|
|
477
427
|
}
|
|
478
428
|
});
|
|
479
429
|
}
|
|
480
|
-
logPackagedUiDevHintWhenNeeded(devMode, gatewayPort) {
|
|
430
|
+
logPackagedUiDevHintWhenNeeded(devMode, gatewayPort, commandName) {
|
|
481
431
|
if (devMode !== "packaged-ui") return;
|
|
482
|
-
this.cliLogger.info(`codemation
|
|
432
|
+
this.cliLogger.info(`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.`);
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
//#endregion
|
|
437
|
+
//#region src/commands/DevPluginCommand.ts
|
|
438
|
+
var DevPluginCommand = class {
|
|
439
|
+
constructor(pluginDevConfigFactory, devCommand) {
|
|
440
|
+
this.pluginDevConfigFactory = pluginDevConfigFactory;
|
|
441
|
+
this.devCommand = devCommand;
|
|
442
|
+
}
|
|
443
|
+
async execute(args) {
|
|
444
|
+
const pluginConfig = await this.pluginDevConfigFactory.prepare(args.pluginRoot);
|
|
445
|
+
await this.devCommand.execute({
|
|
446
|
+
commandName: "dev:plugin",
|
|
447
|
+
configPathOverride: pluginConfig.configPath,
|
|
448
|
+
consumerRoot: args.pluginRoot,
|
|
449
|
+
watchFramework: args.watchFramework
|
|
450
|
+
});
|
|
483
451
|
}
|
|
484
452
|
};
|
|
485
453
|
|
|
@@ -487,38 +455,22 @@ var DevCommand = class {
|
|
|
487
455
|
//#region src/commands/ServeWebCommand.ts
|
|
488
456
|
var ServeWebCommand = class {
|
|
489
457
|
require = createRequire(import.meta.url);
|
|
490
|
-
constructor(pathResolver, configLoader,
|
|
458
|
+
constructor(pathResolver, configLoader, tsRuntime, sourceMapNodeOptions, envLoader, listenPortResolver, nextHostConsumerServerCommandFactory) {
|
|
491
459
|
this.pathResolver = pathResolver;
|
|
492
460
|
this.configLoader = configLoader;
|
|
493
|
-
this.pluginDiscovery = pluginDiscovery;
|
|
494
|
-
this.artifactsPublisher = artifactsPublisher;
|
|
495
461
|
this.tsRuntime = tsRuntime;
|
|
496
462
|
this.sourceMapNodeOptions = sourceMapNodeOptions;
|
|
497
|
-
this.outputBuilderLoader = outputBuilderLoader;
|
|
498
463
|
this.envLoader = envLoader;
|
|
499
464
|
this.listenPortResolver = listenPortResolver;
|
|
500
465
|
this.nextHostConsumerServerCommandFactory = nextHostConsumerServerCommandFactory;
|
|
501
|
-
this.frontendAuthSnapshotFactory = frontendAuthSnapshotFactory;
|
|
502
|
-
this.frontendAppConfigJsonCodec = frontendAppConfigJsonCodec;
|
|
503
466
|
}
|
|
504
467
|
async execute(consumerRoot, buildOptions) {
|
|
505
468
|
const paths = await this.pathResolver.resolve(consumerRoot);
|
|
506
469
|
this.tsRuntime.configure(paths.repoRoot);
|
|
507
|
-
const snapshot = await this.outputBuilderLoader.create(paths.consumerRoot, buildOptions).ensureBuilt();
|
|
508
|
-
const discoveredPlugins = await this.pluginDiscovery.discover(paths.consumerRoot);
|
|
509
|
-
const manifest = await this.artifactsPublisher.publish(snapshot, discoveredPlugins);
|
|
510
470
|
const nextHostRoot = path.dirname(this.require.resolve("@codemation/next-host/package.json"));
|
|
511
471
|
const nextHostCommand = await this.nextHostConsumerServerCommandFactory.create({ nextHostRoot });
|
|
512
472
|
const consumerEnv = this.envLoader.load(paths.consumerRoot);
|
|
513
473
|
const configResolution = await this.configLoader.load({ consumerRoot: paths.consumerRoot });
|
|
514
|
-
const frontendAuthSnapshot = this.frontendAuthSnapshotFactory.createFromResolvedInputs({
|
|
515
|
-
authConfig: configResolution.config.auth,
|
|
516
|
-
env: {
|
|
517
|
-
...process$1.env,
|
|
518
|
-
...consumerEnv
|
|
519
|
-
},
|
|
520
|
-
uiAuthEnabled: !(consumerEnv.NODE_ENV !== "production" && configResolution.config.auth?.allowUnauthenticatedInDevelopment === true)
|
|
521
|
-
});
|
|
522
474
|
const nextPort = this.listenPortResolver.resolvePrimaryApplicationPort(process$1.env.PORT);
|
|
523
475
|
const websocketPort = this.listenPortResolver.resolveWebsocketPortRelativeToHttp({
|
|
524
476
|
nextPort,
|
|
@@ -532,13 +484,8 @@ var ServeWebCommand = class {
|
|
|
532
484
|
...process$1.env,
|
|
533
485
|
...consumerEnv,
|
|
534
486
|
PORT: String(nextPort),
|
|
535
|
-
CODEMATION_FRONTEND_APP_CONFIG_JSON: this.frontendAppConfigJsonCodec.serialize({
|
|
536
|
-
auth: frontendAuthSnapshot,
|
|
537
|
-
productName: "Codemation",
|
|
538
|
-
logoUrl: null
|
|
539
|
-
}),
|
|
540
|
-
CODEMATION_CONSUMER_OUTPUT_MANIFEST_PATH: manifest.manifestPath,
|
|
541
487
|
CODEMATION_CONSUMER_ROOT: paths.consumerRoot,
|
|
488
|
+
CODEMATION_UI_AUTH_ENABLED: String(!(consumerEnv.NODE_ENV !== "production" && configResolution.config.auth?.allowUnauthenticatedInDevelopment === true)),
|
|
542
489
|
CODEMATION_WS_PORT: String(websocketPort),
|
|
543
490
|
NEXT_PUBLIC_CODEMATION_WS_PORT: String(websocketPort),
|
|
544
491
|
NODE_OPTIONS: this.sourceMapNodeOptions.appendToNodeOptions(process$1.env.NODE_OPTIONS),
|
|
@@ -978,6 +925,7 @@ var ConsumerOutputBuilder = class ConsumerOutputBuilder {
|
|
|
978
925
|
sourcePath
|
|
979
926
|
});
|
|
980
927
|
}
|
|
928
|
+
await this.emitConfigSourceFile(outputAppRoot, configSourcePath, runtimeSourcePaths);
|
|
981
929
|
}
|
|
982
930
|
});
|
|
983
931
|
}
|
|
@@ -1036,6 +984,14 @@ var ConsumerOutputBuilder = class ConsumerOutputBuilder {
|
|
|
1036
984
|
await writeFile(outputPath, rewrittenOutputText, "utf8");
|
|
1037
985
|
if (transpiledOutput.sourceMapText) await writeFile(`${outputPath}.map`, transpiledOutput.sourceMapText, "utf8");
|
|
1038
986
|
}
|
|
987
|
+
async emitConfigSourceFile(outputAppRoot, configSourcePath, runtimeSourcePaths) {
|
|
988
|
+
const normalizedConfigSourcePath = path.resolve(configSourcePath);
|
|
989
|
+
if (runtimeSourcePaths.some((sourcePath) => path.resolve(sourcePath) === normalizedConfigSourcePath)) return;
|
|
990
|
+
await this.emitSourceFile({
|
|
991
|
+
outputAppRoot,
|
|
992
|
+
sourcePath: normalizedConfigSourcePath
|
|
993
|
+
});
|
|
994
|
+
}
|
|
1039
995
|
createCompilerOptions() {
|
|
1040
996
|
const scriptTarget = this.buildOptions.target === "es2020" ? ts.ScriptTarget.ES2020 : ts.ScriptTarget.ES2022;
|
|
1041
997
|
return {
|
|
@@ -1289,10 +1245,10 @@ var ConsumerOutputBuilder = class ConsumerOutputBuilder {
|
|
|
1289
1245
|
};
|
|
1290
1246
|
|
|
1291
1247
|
//#endregion
|
|
1292
|
-
//#region src/consumer/
|
|
1293
|
-
var
|
|
1294
|
-
create(consumerRoot,
|
|
1295
|
-
return new ConsumerOutputBuilder(consumerRoot,
|
|
1248
|
+
//#region src/consumer/ConsumerOutputBuilderFactory.ts
|
|
1249
|
+
var ConsumerOutputBuilderFactory = class {
|
|
1250
|
+
create(consumerRoot, args) {
|
|
1251
|
+
return new ConsumerOutputBuilder(consumerRoot, args?.logger, args?.buildOptions);
|
|
1296
1252
|
}
|
|
1297
1253
|
};
|
|
1298
1254
|
|
|
@@ -1464,8 +1420,9 @@ var DevCliBannerRenderer = class {
|
|
|
1464
1420
|
title: chalk.bold("Runtime"),
|
|
1465
1421
|
titleAlignment: "center"
|
|
1466
1422
|
});
|
|
1423
|
+
const pluginsSection = this.buildPluginsSection(summary);
|
|
1467
1424
|
const activeSection = this.buildActiveWorkflowsSection(summary);
|
|
1468
|
-
process.stdout.write(`${detailBox}\n${activeSection}\n`);
|
|
1425
|
+
process.stdout.write(`${detailBox}\n${pluginsSection}\n${activeSection}\n`);
|
|
1469
1426
|
}
|
|
1470
1427
|
renderFull(summary) {
|
|
1471
1428
|
this.renderBrandHeader();
|
|
@@ -1492,8 +1449,9 @@ var DevCliBannerRenderer = class {
|
|
|
1492
1449
|
title: chalk.bold("Runtime (updated)"),
|
|
1493
1450
|
titleAlignment: "center"
|
|
1494
1451
|
});
|
|
1452
|
+
const pluginsSection = this.buildPluginsSection(summary);
|
|
1495
1453
|
const activeSection = this.buildActiveWorkflowsSection(summary);
|
|
1496
|
-
process.stdout.write(`\n${detailBox}\n${activeSection}\n`);
|
|
1454
|
+
process.stdout.write(`\n${detailBox}\n${pluginsSection}\n${activeSection}\n`);
|
|
1497
1455
|
}
|
|
1498
1456
|
renderFigletTitle() {
|
|
1499
1457
|
try {
|
|
@@ -1532,28 +1490,23 @@ var DevCliBannerRenderer = class {
|
|
|
1532
1490
|
titleAlignment: "left"
|
|
1533
1491
|
});
|
|
1534
1492
|
}
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
const buildOptions = this.buildOptionsParser.parse({});
|
|
1553
|
-
const snapshot = await this.outputBuilderLoader.create(paths.consumerRoot, buildOptions).ensureBuilt();
|
|
1554
|
-
const discoveredPlugins = await this.pluginDiscovery.discover(paths.consumerRoot);
|
|
1555
|
-
await this.artifactsPublisher.publish(snapshot, discoveredPlugins);
|
|
1556
|
-
this.cliLogger.debug(`Dev: consumer output published (${snapshot.buildVersion}).`);
|
|
1493
|
+
buildPluginsSection(summary) {
|
|
1494
|
+
return boxen((summary.plugins.length === 0 ? [chalk.dim(" (none discovered or configured)")] : summary.plugins.map((plugin) => `${chalk.whiteBright(` • ${plugin.packageName} `)}${chalk.dim(`(${plugin.source})`)}`)).join("\n"), {
|
|
1495
|
+
padding: {
|
|
1496
|
+
top: 0,
|
|
1497
|
+
bottom: 0,
|
|
1498
|
+
left: 0,
|
|
1499
|
+
right: 0
|
|
1500
|
+
},
|
|
1501
|
+
margin: {
|
|
1502
|
+
top: 1,
|
|
1503
|
+
bottom: 0
|
|
1504
|
+
},
|
|
1505
|
+
borderStyle: "single",
|
|
1506
|
+
borderColor: "cyan",
|
|
1507
|
+
title: chalk.bold("Plugins"),
|
|
1508
|
+
titleAlignment: "left"
|
|
1509
|
+
});
|
|
1557
1510
|
}
|
|
1558
1511
|
};
|
|
1559
1512
|
|
|
@@ -2089,7 +2042,8 @@ var CodemationTsyringeTypeInfoRegistrar = class {
|
|
|
2089
2042
|
//#endregion
|
|
2090
2043
|
//#region src/dev/DevApiRuntimeHost.ts
|
|
2091
2044
|
var DevApiRuntimeHost = class {
|
|
2092
|
-
|
|
2045
|
+
pluginPackageMetadata = new CodemationPluginPackageMetadata();
|
|
2046
|
+
pluginListMerger = new CodemationPluginListMerger(this.pluginPackageMetadata);
|
|
2093
2047
|
contextPromise = null;
|
|
2094
2048
|
constructor(configLoader, pluginDiscovery, args) {
|
|
2095
2049
|
this.configLoader = configLoader;
|
|
@@ -2118,14 +2072,17 @@ var DevApiRuntimeHost = class {
|
|
|
2118
2072
|
env.CODEMATION_CONSUMER_ROOT = consumerRoot;
|
|
2119
2073
|
const configResolution = await this.configLoader.load({
|
|
2120
2074
|
consumerRoot,
|
|
2075
|
+
configPathOverride: this.args.configPathOverride,
|
|
2121
2076
|
repoRoot,
|
|
2122
2077
|
env
|
|
2123
2078
|
});
|
|
2124
2079
|
const discoveredPlugins = await this.loadDiscoveredPlugins(consumerRoot);
|
|
2080
|
+
const mergedPlugins = discoveredPlugins.length > 0 ? this.pluginListMerger.merge(configResolution.appConfig.plugins, discoveredPlugins) : configResolution.appConfig.plugins;
|
|
2125
2081
|
const appConfig = {
|
|
2126
2082
|
...configResolution.appConfig,
|
|
2127
2083
|
env,
|
|
2128
|
-
plugins:
|
|
2084
|
+
plugins: mergedPlugins,
|
|
2085
|
+
pluginLoadSummary: this.createPluginLoadSummary(configResolution.appConfig.plugins, discoveredPlugins, mergedPlugins)
|
|
2129
2086
|
};
|
|
2130
2087
|
const container = await new AppContainerFactory$1().create({
|
|
2131
2088
|
appConfig,
|
|
@@ -2145,6 +2102,20 @@ var DevApiRuntimeHost = class {
|
|
|
2145
2102
|
async loadDiscoveredPlugins(consumerRoot) {
|
|
2146
2103
|
return (await this.pluginDiscovery.resolvePlugins(consumerRoot)).map((resolvedPackage) => resolvedPackage.plugin);
|
|
2147
2104
|
}
|
|
2105
|
+
createPluginLoadSummary(configuredPlugins, discoveredPlugins, mergedPlugins) {
|
|
2106
|
+
const configuredPluginSet = new Set(configuredPlugins);
|
|
2107
|
+
const discoveredPluginSet = new Set(discoveredPlugins);
|
|
2108
|
+
const summaries = [];
|
|
2109
|
+
for (const plugin of mergedPlugins) {
|
|
2110
|
+
const packageName = this.pluginPackageMetadata.readPackageName(plugin);
|
|
2111
|
+
if (!packageName) continue;
|
|
2112
|
+
summaries.push({
|
|
2113
|
+
packageName,
|
|
2114
|
+
source: configuredPluginSet.has(plugin) || !discoveredPluginSet.has(plugin) ? "configured" : "discovered"
|
|
2115
|
+
});
|
|
2116
|
+
}
|
|
2117
|
+
return summaries;
|
|
2118
|
+
}
|
|
2148
2119
|
async detectWorkspaceRoot(startDirectory) {
|
|
2149
2120
|
let currentDirectory = path.resolve(startDirectory);
|
|
2150
2121
|
while (true) {
|
|
@@ -2262,6 +2233,7 @@ var DevApiRuntimeFactory = class {
|
|
|
2262
2233
|
const httpPort = await this.portAllocator.allocate();
|
|
2263
2234
|
const workflowWebSocketPort = await this.portAllocator.allocate();
|
|
2264
2235
|
const runtime = new DevApiRuntimeServer(httpPort, workflowWebSocketPort, new DevApiRuntimeHost(this.configLoader, this.pluginDiscovery, {
|
|
2236
|
+
configPathOverride: args.configPathOverride,
|
|
2265
2237
|
consumerRoot: args.consumerRoot,
|
|
2266
2238
|
env: {
|
|
2267
2239
|
...args.env,
|
|
@@ -2318,7 +2290,7 @@ var DevRebuildQueue = class {
|
|
|
2318
2290
|
};
|
|
2319
2291
|
return {
|
|
2320
2292
|
changedPaths: [...new Set([...current.changedPaths, ...next.changedPaths])],
|
|
2321
|
-
|
|
2293
|
+
configPathOverride: next.configPathOverride ?? current.configPathOverride,
|
|
2322
2294
|
shouldRestartUi: current.shouldRestartUi || next.shouldRestartUi
|
|
2323
2295
|
};
|
|
2324
2296
|
}
|
|
@@ -2366,34 +2338,6 @@ var SourceMapNodeOptions = class {
|
|
|
2366
2338
|
}
|
|
2367
2339
|
};
|
|
2368
2340
|
|
|
2369
|
-
//#endregion
|
|
2370
|
-
//#region src/dev/DevAuthSettingsLoader.ts
|
|
2371
|
-
var DevAuthSettingsLoader = class DevAuthSettingsLoader {
|
|
2372
|
-
static defaultDevelopmentAuthSecret = "codemation-dev-auth-secret-not-for-production";
|
|
2373
|
-
constructor(configLoader, consumerEnvLoader) {
|
|
2374
|
-
this.configLoader = configLoader;
|
|
2375
|
-
this.consumerEnvLoader = consumerEnvLoader;
|
|
2376
|
-
}
|
|
2377
|
-
resolveDevelopmentServerToken(rawToken) {
|
|
2378
|
-
if (rawToken && rawToken.trim().length > 0) return rawToken;
|
|
2379
|
-
return randomUUID();
|
|
2380
|
-
}
|
|
2381
|
-
async loadForConsumer(consumerRoot) {
|
|
2382
|
-
const resolution = await this.configLoader.load({ consumerRoot });
|
|
2383
|
-
const envForAuthSecret = this.consumerEnvLoader.mergeConsumerRootIntoProcessEnvironment(consumerRoot, process.env);
|
|
2384
|
-
return {
|
|
2385
|
-
authConfigJson: JSON.stringify(resolution.config.auth ?? null),
|
|
2386
|
-
authSecret: this.resolveDevelopmentAuthSecret(envForAuthSecret),
|
|
2387
|
-
skipUiAuth: resolution.config.auth?.allowUnauthenticatedInDevelopment === true
|
|
2388
|
-
};
|
|
2389
|
-
}
|
|
2390
|
-
resolveDevelopmentAuthSecret(env) {
|
|
2391
|
-
const configuredSecret = env.AUTH_SECRET;
|
|
2392
|
-
if (configuredSecret && configuredSecret.trim().length > 0) return configuredSecret;
|
|
2393
|
-
return DevAuthSettingsLoader.defaultDevelopmentAuthSecret;
|
|
2394
|
-
}
|
|
2395
|
-
};
|
|
2396
|
-
|
|
2397
2341
|
//#endregion
|
|
2398
2342
|
//#region src/dev/DevHttpProbe.ts
|
|
2399
2343
|
var DevHttpProbe = class {
|
|
@@ -2438,24 +2382,21 @@ var DevHttpProbe = class {
|
|
|
2438
2382
|
//#endregion
|
|
2439
2383
|
//#region src/dev/DevNextHostEnvironmentBuilder.ts
|
|
2440
2384
|
var DevNextHostEnvironmentBuilder = class {
|
|
2441
|
-
constructor(consumerEnvLoader, sourceMapNodeOptions
|
|
2385
|
+
constructor(consumerEnvLoader, sourceMapNodeOptions) {
|
|
2442
2386
|
this.consumerEnvLoader = consumerEnvLoader;
|
|
2443
2387
|
this.sourceMapNodeOptions = sourceMapNodeOptions;
|
|
2444
|
-
this.frontendAuthSnapshotFactory = frontendAuthSnapshotFactory;
|
|
2445
|
-
this.frontendAppConfigJsonCodec = frontendAppConfigJsonCodec;
|
|
2446
2388
|
}
|
|
2447
2389
|
buildConsumerUiProxy(args) {
|
|
2448
2390
|
return {
|
|
2449
2391
|
...this.build({
|
|
2450
|
-
authConfigJson: args.authConfigJson,
|
|
2451
2392
|
authSecret: args.authSecret,
|
|
2393
|
+
configPathOverride: args.configPathOverride,
|
|
2452
2394
|
consumerRoot: args.consumerRoot,
|
|
2453
2395
|
developmentServerToken: args.developmentServerToken,
|
|
2454
2396
|
nextPort: args.nextPort,
|
|
2455
2397
|
runtimeDevUrl: args.runtimeDevUrl,
|
|
2456
2398
|
skipUiAuth: args.skipUiAuth,
|
|
2457
|
-
websocketPort: args.websocketPort
|
|
2458
|
-
consumerOutputManifestPath: args.consumerOutputManifestPath
|
|
2399
|
+
websocketPort: args.websocketPort
|
|
2459
2400
|
}),
|
|
2460
2401
|
HOSTNAME: "127.0.0.1",
|
|
2461
2402
|
AUTH_SECRET: args.authSecret,
|
|
@@ -2463,27 +2404,11 @@ var DevNextHostEnvironmentBuilder = class {
|
|
|
2463
2404
|
};
|
|
2464
2405
|
}
|
|
2465
2406
|
build(args) {
|
|
2466
|
-
const merged = this.consumerEnvLoader.mergeConsumerRootIntoProcessEnvironment(args.consumerRoot, process$1.env);
|
|
2467
|
-
const manifestPath = args.consumerOutputManifestPath ?? path.resolve(args.consumerRoot, ".codemation", "output", "current.json");
|
|
2468
|
-
const authSecret = args.authSecret ?? merged.AUTH_SECRET;
|
|
2469
|
-
const authSnapshot = this.frontendAuthSnapshotFactory.createFromResolvedInputs({
|
|
2470
|
-
authConfig: this.parseAuthConfig(args.authConfigJson),
|
|
2471
|
-
env: {
|
|
2472
|
-
...merged,
|
|
2473
|
-
...typeof authSecret === "string" && authSecret.trim().length > 0 ? { AUTH_SECRET: authSecret } : {}
|
|
2474
|
-
},
|
|
2475
|
-
uiAuthEnabled: !args.skipUiAuth
|
|
2476
|
-
});
|
|
2477
2407
|
return {
|
|
2478
|
-
...
|
|
2408
|
+
...this.consumerEnvLoader.mergeConsumerRootIntoProcessEnvironment(args.consumerRoot, process$1.env),
|
|
2479
2409
|
PORT: String(args.nextPort),
|
|
2480
2410
|
CODEMATION_CONSUMER_ROOT: args.consumerRoot,
|
|
2481
|
-
|
|
2482
|
-
CODEMATION_FRONTEND_APP_CONFIG_JSON: this.frontendAppConfigJsonCodec.serialize({
|
|
2483
|
-
auth: authSnapshot,
|
|
2484
|
-
productName: "Codemation",
|
|
2485
|
-
logoUrl: null
|
|
2486
|
-
}),
|
|
2411
|
+
CODEMATION_UI_AUTH_ENABLED: String(!args.skipUiAuth),
|
|
2487
2412
|
CODEMATION_WS_PORT: String(args.websocketPort),
|
|
2488
2413
|
NEXT_PUBLIC_CODEMATION_WS_PORT: String(args.websocketPort),
|
|
2489
2414
|
CODEMATION_DEV_SERVER_TOKEN: args.developmentServerToken,
|
|
@@ -2491,13 +2416,11 @@ var DevNextHostEnvironmentBuilder = class {
|
|
|
2491
2416
|
NODE_OPTIONS: this.sourceMapNodeOptions.appendToNodeOptions(process$1.env.NODE_OPTIONS),
|
|
2492
2417
|
WS_NO_BUFFER_UTIL: "1",
|
|
2493
2418
|
WS_NO_UTF_8_VALIDATE: "1",
|
|
2419
|
+
...args.authSecret && args.authSecret.trim().length > 0 ? { AUTH_SECRET: args.authSecret.trim() } : {},
|
|
2420
|
+
...args.configPathOverride && args.configPathOverride.trim().length > 0 ? { CODEMATION_CONFIG_PATH: args.configPathOverride } : {},
|
|
2494
2421
|
...args.runtimeDevUrl !== void 0 && args.runtimeDevUrl.trim().length > 0 ? { CODEMATION_RUNTIME_DEV_URL: args.runtimeDevUrl.trim() } : {}
|
|
2495
2422
|
};
|
|
2496
2423
|
}
|
|
2497
|
-
parseAuthConfig(authConfigJson) {
|
|
2498
|
-
if (authConfigJson.trim().length === 0) return;
|
|
2499
|
-
return JSON.parse(authConfigJson) ?? void 0;
|
|
2500
|
-
}
|
|
2501
2424
|
};
|
|
2502
2425
|
|
|
2503
2426
|
//#endregion
|
|
@@ -2522,13 +2445,13 @@ var DevSessionPortsResolver = class {
|
|
|
2522
2445
|
* Bundles dependencies for {@link DevCommand} so the command stays a thin orchestrator.
|
|
2523
2446
|
*/
|
|
2524
2447
|
var DevSessionServices = class {
|
|
2525
|
-
constructor(consumerEnvLoader, sourceMapNodeOptions, sessionPorts, loopbackPortAllocator, devHttpProbe,
|
|
2448
|
+
constructor(consumerEnvLoader, sourceMapNodeOptions, sessionPorts, loopbackPortAllocator, devHttpProbe, nextHostEdgeSeedLoader, nextHostEnvBuilder, watchRootsResolver, sourceChangeClassifier) {
|
|
2526
2449
|
this.consumerEnvLoader = consumerEnvLoader;
|
|
2527
2450
|
this.sourceMapNodeOptions = sourceMapNodeOptions;
|
|
2528
2451
|
this.sessionPorts = sessionPorts;
|
|
2529
2452
|
this.loopbackPortAllocator = loopbackPortAllocator;
|
|
2530
2453
|
this.devHttpProbe = devHttpProbe;
|
|
2531
|
-
this.
|
|
2454
|
+
this.nextHostEdgeSeedLoader = nextHostEdgeSeedLoader;
|
|
2532
2455
|
this.nextHostEnvBuilder = nextHostEnvBuilder;
|
|
2533
2456
|
this.watchRootsResolver = watchRootsResolver;
|
|
2534
2457
|
this.sourceChangeClassifier = sourceChangeClassifier;
|
|
@@ -2538,15 +2461,16 @@ var DevSessionServices = class {
|
|
|
2538
2461
|
//#endregion
|
|
2539
2462
|
//#region src/dev/DevSourceChangeClassifier.ts
|
|
2540
2463
|
var DevSourceChangeClassifier = class DevSourceChangeClassifier {
|
|
2541
|
-
static
|
|
2464
|
+
static uiConfigFileNames = new Set([
|
|
2542
2465
|
"codemation.config.ts",
|
|
2543
2466
|
"codemation.config.js",
|
|
2544
2467
|
"codemation.config.mjs"
|
|
2545
2468
|
]);
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2469
|
+
static pluginConfigFileNames = new Set([
|
|
2470
|
+
"codemation.plugin.ts",
|
|
2471
|
+
"codemation.plugin.js",
|
|
2472
|
+
"codemation.plugin.mjs"
|
|
2473
|
+
]);
|
|
2550
2474
|
requiresUiRestart(args) {
|
|
2551
2475
|
const resolvedConsumerRoot = path.resolve(args.consumerRoot);
|
|
2552
2476
|
return args.changedPaths.some((changedPath) => this.pathRequiresUiRestart(path.resolve(changedPath), resolvedConsumerRoot));
|
|
@@ -2559,7 +2483,9 @@ var DevSourceChangeClassifier = class DevSourceChangeClassifier {
|
|
|
2559
2483
|
pathRequiresUiRestart(resolvedPath, consumerRoot) {
|
|
2560
2484
|
if (!this.isPathInsideDirectory(resolvedPath, consumerRoot)) return false;
|
|
2561
2485
|
const relativePath = path.relative(consumerRoot, resolvedPath);
|
|
2562
|
-
|
|
2486
|
+
const fileName = path.basename(relativePath);
|
|
2487
|
+
if (DevSourceChangeClassifier.uiConfigFileNames.has(fileName)) return true;
|
|
2488
|
+
if (DevSourceChangeClassifier.pluginConfigFileNames.has(fileName)) return false;
|
|
2563
2489
|
if (relativePath.startsWith(path.join("src", "workflows"))) return false;
|
|
2564
2490
|
if (relativePath.startsWith(path.join("src", "plugins"))) return false;
|
|
2565
2491
|
if (relativePath.includes("credential")) return true;
|
|
@@ -2588,6 +2514,36 @@ var LoopbackPortAllocator = class {
|
|
|
2588
2514
|
}
|
|
2589
2515
|
};
|
|
2590
2516
|
|
|
2517
|
+
//#endregion
|
|
2518
|
+
//#region src/dev/NextHostEdgeSeedLoader.ts
|
|
2519
|
+
var NextHostEdgeSeedLoader = class NextHostEdgeSeedLoader {
|
|
2520
|
+
static defaultDevelopmentAuthSecret = "codemation-dev-auth-secret-not-for-production";
|
|
2521
|
+
constructor(configLoader, consumerEnvLoader) {
|
|
2522
|
+
this.configLoader = configLoader;
|
|
2523
|
+
this.consumerEnvLoader = consumerEnvLoader;
|
|
2524
|
+
}
|
|
2525
|
+
resolveDevelopmentServerToken(rawToken) {
|
|
2526
|
+
if (rawToken && rawToken.trim().length > 0) return rawToken;
|
|
2527
|
+
return randomUUID();
|
|
2528
|
+
}
|
|
2529
|
+
async loadForConsumer(consumerRoot, options) {
|
|
2530
|
+
const resolution = await this.configLoader.load({
|
|
2531
|
+
consumerRoot,
|
|
2532
|
+
configPathOverride: options?.configPathOverride
|
|
2533
|
+
});
|
|
2534
|
+
const envForAuthSecret = this.consumerEnvLoader.mergeConsumerRootIntoProcessEnvironment(consumerRoot, process.env);
|
|
2535
|
+
return {
|
|
2536
|
+
authSecret: this.resolveDevelopmentAuthSecret(envForAuthSecret),
|
|
2537
|
+
uiAuthEnabled: resolution.config.auth?.allowUnauthenticatedInDevelopment !== true
|
|
2538
|
+
};
|
|
2539
|
+
}
|
|
2540
|
+
resolveDevelopmentAuthSecret(env) {
|
|
2541
|
+
const configuredSecret = env.AUTH_SECRET;
|
|
2542
|
+
if (configuredSecret && configuredSecret.trim().length > 0) return configuredSecret;
|
|
2543
|
+
return NextHostEdgeSeedLoader.defaultDevelopmentAuthSecret;
|
|
2544
|
+
}
|
|
2545
|
+
};
|
|
2546
|
+
|
|
2591
2547
|
//#endregion
|
|
2592
2548
|
//#region src/dev/WatchRootsResolver.ts
|
|
2593
2549
|
var WatchRootsResolver = class {
|
|
@@ -2614,7 +2570,57 @@ var DevSessionServicesBuilder = class {
|
|
|
2614
2570
|
const sourceMapNodeOptions = new SourceMapNodeOptions();
|
|
2615
2571
|
const listenPortResolver = new ListenPortResolver();
|
|
2616
2572
|
const loopbackPortAllocator = new LoopbackPortAllocator();
|
|
2617
|
-
return new DevSessionServices(consumerEnvLoader, sourceMapNodeOptions, new DevSessionPortsResolver(listenPortResolver, loopbackPortAllocator), loopbackPortAllocator, new DevHttpProbe(), new
|
|
2573
|
+
return new DevSessionServices(consumerEnvLoader, sourceMapNodeOptions, new DevSessionPortsResolver(listenPortResolver, loopbackPortAllocator), loopbackPortAllocator, new DevHttpProbe(), new NextHostEdgeSeedLoader(new CodemationConsumerConfigLoader(), consumerEnvLoader), new DevNextHostEnvironmentBuilder(consumerEnvLoader, sourceMapNodeOptions), new WatchRootsResolver(), new DevSourceChangeClassifier());
|
|
2574
|
+
}
|
|
2575
|
+
};
|
|
2576
|
+
|
|
2577
|
+
//#endregion
|
|
2578
|
+
//#region src/dev/PluginDevConfigFactory.ts
|
|
2579
|
+
var PluginDevConfigFactory = class {
|
|
2580
|
+
async prepare(pluginRoot) {
|
|
2581
|
+
const pluginEntryPath = await this.resolvePluginEntryPath(pluginRoot);
|
|
2582
|
+
const configPath = path.resolve(pluginRoot, ".codemation", "plugin-dev", "codemation.config.ts");
|
|
2583
|
+
await mkdir(path.dirname(configPath), { recursive: true });
|
|
2584
|
+
await writeFile(configPath, this.createConfigSource(configPath, pluginEntryPath), "utf8");
|
|
2585
|
+
return { configPath };
|
|
2586
|
+
}
|
|
2587
|
+
async resolvePluginEntryPath(pluginRoot) {
|
|
2588
|
+
const candidates = [
|
|
2589
|
+
path.resolve(pluginRoot, "codemation.plugin.ts"),
|
|
2590
|
+
path.resolve(pluginRoot, "codemation.plugin.js"),
|
|
2591
|
+
path.resolve(pluginRoot, "src", "codemation.plugin.ts"),
|
|
2592
|
+
path.resolve(pluginRoot, "src", "codemation.plugin.js")
|
|
2593
|
+
];
|
|
2594
|
+
for (const candidate of candidates) if (await this.exists(candidate)) return candidate;
|
|
2595
|
+
throw new Error("Plugin config not found. Expected \"codemation.plugin.ts\" in the plugin root or \"src/\".");
|
|
2596
|
+
}
|
|
2597
|
+
createConfigSource(configPath, pluginEntryPath) {
|
|
2598
|
+
const relativeImportPath = this.toRelativeImportPath(configPath, pluginEntryPath);
|
|
2599
|
+
return [
|
|
2600
|
+
"import type { CodemationConfig } from \"@codemation/host\";",
|
|
2601
|
+
`import plugin from ${JSON.stringify(relativeImportPath)};`,
|
|
2602
|
+
"",
|
|
2603
|
+
"const sandbox = plugin.sandbox ?? {};",
|
|
2604
|
+
"const config: CodemationConfig = {",
|
|
2605
|
+
" ...sandbox,",
|
|
2606
|
+
" plugins: [...(sandbox.plugins ?? []), plugin],",
|
|
2607
|
+
"};",
|
|
2608
|
+
"",
|
|
2609
|
+
"export default config;",
|
|
2610
|
+
""
|
|
2611
|
+
].join("\n");
|
|
2612
|
+
}
|
|
2613
|
+
toRelativeImportPath(fromPath, targetPath) {
|
|
2614
|
+
const relativePath = path.relative(path.dirname(fromPath), targetPath).replace(/\\/g, "/");
|
|
2615
|
+
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
2616
|
+
}
|
|
2617
|
+
async exists(filePath) {
|
|
2618
|
+
try {
|
|
2619
|
+
await access(filePath);
|
|
2620
|
+
return true;
|
|
2621
|
+
} catch {
|
|
2622
|
+
return false;
|
|
2623
|
+
}
|
|
2618
2624
|
}
|
|
2619
2625
|
};
|
|
2620
2626
|
|
|
@@ -2870,10 +2876,11 @@ var DevSourceWatcherFactory = class {
|
|
|
2870
2876
|
//#endregion
|
|
2871
2877
|
//#region src/Program.ts
|
|
2872
2878
|
var CliProgram = class {
|
|
2873
|
-
constructor(buildOptionsParser, buildCommand, devCommand, serveWebCommand, serveWorkerCommand, dbMigrateCommand, userCreateCommand, userListCommand) {
|
|
2879
|
+
constructor(buildOptionsParser, buildCommand, devCommand, devPluginCommand, serveWebCommand, serveWorkerCommand, dbMigrateCommand, userCreateCommand, userListCommand) {
|
|
2874
2880
|
this.buildOptionsParser = buildOptionsParser;
|
|
2875
2881
|
this.buildCommand = buildCommand;
|
|
2876
2882
|
this.devCommand = devCommand;
|
|
2883
|
+
this.devPluginCommand = devPluginCommand;
|
|
2877
2884
|
this.serveWebCommand = serveWebCommand;
|
|
2878
2885
|
this.serveWorkerCommand = serveWorkerCommand;
|
|
2879
2886
|
this.dbMigrateCommand = dbMigrateCommand;
|
|
@@ -2893,6 +2900,9 @@ var CliProgram = class {
|
|
|
2893
2900
|
watchFramework: opts.watchFramework === true
|
|
2894
2901
|
});
|
|
2895
2902
|
});
|
|
2903
|
+
program.command("dev:plugin").description("Start plugin sandbox development using `codemation.plugin.ts`.").option("--plugin-root <path>", "Path to the plugin project root (defaults to cwd)").action(async (opts) => {
|
|
2904
|
+
await this.devPluginCommand.execute({ pluginRoot: resolveConsumerRoot(opts.pluginRoot) });
|
|
2905
|
+
});
|
|
2896
2906
|
const serve$1 = program.command("serve").description("Run production web or worker processes (no dev watchers).");
|
|
2897
2907
|
serve$1.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) => {
|
|
2898
2908
|
await this.serveWebCommand.execute(resolveConsumerRoot(opts.consumerRoot), this.buildOptionsParser.parse(opts));
|
|
@@ -3160,9 +3170,7 @@ var CliProgramFactory = class {
|
|
|
3160
3170
|
const appConfigLoader = new AppConfigLoader();
|
|
3161
3171
|
const pathResolver = new CliPathResolver();
|
|
3162
3172
|
const pluginDiscovery = new CodemationPluginDiscovery();
|
|
3163
|
-
const artifactsPublisher = new ConsumerBuildArtifactsPublisher();
|
|
3164
3173
|
const tsRuntime = new TypeScriptRuntimeConfigurator();
|
|
3165
|
-
const outputBuilderLoader = new ConsumerOutputBuilderLoader();
|
|
3166
3174
|
const sourceMapNodeOptions = new SourceMapNodeOptions();
|
|
3167
3175
|
const nextHostConsumerServerCommandFactory = new NextHostConsumerServerCommandFactory();
|
|
3168
3176
|
const devSessionServices = new DevSessionServicesBuilder().build();
|
|
@@ -3172,8 +3180,8 @@ var CliProgramFactory = class {
|
|
|
3172
3180
|
const userAdminCliOptionsParser = new UserAdminCliOptionsParser();
|
|
3173
3181
|
const databaseMigrationsApplyService = new DatabaseMigrationsApplyService(cliLogger, new UserAdminConsumerDotenvLoader(), tsconfigPreparation, new CodemationConsumerConfigLoader(), new ConsumerDatabaseConnectionResolver(), new CliDatabaseUrlDescriptor(), hostPackageRoot, new PrismaMigrationDeployer());
|
|
3174
3182
|
const buildOptionsParser = new ConsumerBuildOptionsParser();
|
|
3175
|
-
const
|
|
3176
|
-
return new CliProgram(buildOptionsParser, new BuildCommand(cliLogger, pathResolver,
|
|
3183
|
+
const devCommand = new DevCommand(pathResolver, tsRuntime, new DevLockFactory(), new DevSourceWatcherFactory(), cliLogger, devSessionServices, databaseMigrationsApplyService, new DevBootstrapSummaryFetcher(), new DevCliBannerRenderer(), new ConsumerEnvDotenvFilePredicate(), new DevTrackedProcessTreeKiller(), nextHostConsumerServerCommandFactory, new DevApiRuntimeFactory(devSessionServices.loopbackPortAllocator, appConfigLoader, pluginDiscovery), new CliDevProxyServerFactory(), new DevRebuildQueueFactory());
|
|
3184
|
+
return new CliProgram(buildOptionsParser, new BuildCommand(cliLogger, pathResolver, new ConsumerOutputBuilderFactory(), tsRuntime), devCommand, new DevPluginCommand(new PluginDevConfigFactory(), devCommand), new ServeWebCommand(pathResolver, new CodemationConsumerConfigLoader(), tsRuntime, sourceMapNodeOptions, new ConsumerEnvLoader(), new ListenPortResolver(), nextHostConsumerServerCommandFactory), new ServeWorkerCommand(pathResolver, appConfigLoader, new AppContainerFactory()), new DbMigrateCommand(databaseMigrationsApplyService), new UserCreateCommand(new LocalUserCreator(userAdminBootstrap), userAdminCliOptionsParser), new UserListCommand(cliLogger, userAdminBootstrap, new CliDatabaseUrlDescriptor(), userAdminCliOptionsParser));
|
|
3177
3185
|
}
|
|
3178
3186
|
};
|
|
3179
3187
|
|