@codemation/cli 0.0.15 → 0.0.18
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/CHANGELOG.md +10 -0
- package/LICENSE +37 -0
- package/README.md +4 -4
- package/dist/{CliBin-BkY_gChN.js → CliBin-BYHuUedo.js} +348 -186
- package/dist/bin.js +1 -1
- package/dist/index.d.ts +278 -298
- package/dist/index.js +1 -1
- package/package.json +5 -4
- package/src/CliProgramFactory.ts +31 -37
- package/src/Program.ts +12 -0
- package/src/build/ConsumerBuildArtifactsPublisher.ts +12 -7
- package/src/commands/BuildCommand.ts +9 -9
- package/src/commands/DevCommand.ts +113 -47
- 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 +28 -0
- package/src/consumer/ConsumerOutputBuilderFactory.ts +17 -0
- package/src/dev/Builder.ts +2 -2
- package/src/dev/CliDevProxyServer.ts +20 -0
- 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 +27 -36
- package/src/dev/DevRebuildQueue.ts +2 -2
- package/src/dev/DevSessionServices.ts +2 -2
- package/src/dev/DevSourceChangeClassifier.ts +12 -12
- package/src/dev/ListenPortConflictDescriber.ts +66 -5
- package/src/dev/{DevAuthSettingsLoader.ts → NextHostEdgeSeedLoader.ts} +13 -9
- package/src/dev/PluginDevConfigFactory.ts +64 -0
- package/src/consumer/Loader.ts +0 -8
- package/src/dev/DevConsumerPublishBootstrap.ts +0 -30
|
@@ -1,7 +1,7 @@
|
|
|
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
6
|
import { randomUUID } from "node:crypto";
|
|
7
7
|
import { access, copyFile, cp, mkdir, open, readFile, readdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
@@ -25,6 +25,23 @@ 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/ConsumerBuildOptionsParser.ts
|
|
29
|
+
var ConsumerBuildOptionsParser = class {
|
|
30
|
+
parse(args) {
|
|
31
|
+
return {
|
|
32
|
+
sourceMaps: args.noSourceMaps !== true,
|
|
33
|
+
target: this.parseTarget(args.target)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
parseTarget(raw) {
|
|
37
|
+
if (raw === void 0 || raw.trim() === "") return "es2022";
|
|
38
|
+
const normalized = raw.trim();
|
|
39
|
+
if (normalized === "es2020" || normalized === "es2022") return normalized;
|
|
40
|
+
throw new Error(`Invalid --target "${raw}". Use es2020 or es2022.`);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
//#endregion
|
|
28
45
|
//#region src/build/ConsumerBuildArtifactsPublisher.ts
|
|
29
46
|
var ConsumerBuildArtifactsPublisher = class {
|
|
30
47
|
async publish(snapshot, discoveredPlugins) {
|
|
@@ -36,10 +53,9 @@ var ConsumerBuildArtifactsPublisher = class {
|
|
|
36
53
|
await mkdir(path.dirname(outputPath), { recursive: true });
|
|
37
54
|
const outputLines = ["const codemationDiscoveredPlugins = [];", ""];
|
|
38
55
|
discoveredPlugins.forEach((discoveredPlugin, index) => {
|
|
39
|
-
const pluginFileUrl = pathToFileURL(path.resolve(discoveredPlugin.packageRoot, discoveredPlugin
|
|
40
|
-
const exportNameAccessor = discoveredPlugin.manifest.exportName ? `pluginModule${index}[${JSON.stringify(discoveredPlugin.manifest.exportName)}]` : `pluginModule${index}.default ?? pluginModule${index}.codemationPlugin`;
|
|
56
|
+
const pluginFileUrl = pathToFileURL(path.resolve(discoveredPlugin.packageRoot, this.resolvePluginEntry(discoveredPlugin))).href;
|
|
41
57
|
outputLines.push(`const pluginModule${index} = await import(${JSON.stringify(pluginFileUrl)});`);
|
|
42
|
-
outputLines.push(`const pluginValue${index} = ${
|
|
58
|
+
outputLines.push(`const pluginValue${index} = pluginModule${index}.default ?? pluginModule${index}.codemationPlugin;`);
|
|
43
59
|
outputLines.push(`if (pluginValue${index} && typeof pluginValue${index}.register === "function") {`);
|
|
44
60
|
outputLines.push(` codemationDiscoveredPlugins.push(pluginValue${index});`);
|
|
45
61
|
outputLines.push(`} else if (typeof pluginValue${index} === "function" && pluginValue${index}.prototype && typeof pluginValue${index}.prototype.register === "function") {`);
|
|
@@ -68,45 +84,32 @@ var ConsumerBuildArtifactsPublisher = class {
|
|
|
68
84
|
await rename(temporaryManifestPath, snapshot.manifestPath);
|
|
69
85
|
return manifest;
|
|
70
86
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
//#region src/build/ConsumerBuildOptionsParser.ts
|
|
75
|
-
var ConsumerBuildOptionsParser = class {
|
|
76
|
-
parse(args) {
|
|
77
|
-
return {
|
|
78
|
-
sourceMaps: args.noSourceMaps !== true,
|
|
79
|
-
target: this.parseTarget(args.target)
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
parseTarget(raw) {
|
|
83
|
-
if (raw === void 0 || raw.trim() === "") return "es2022";
|
|
84
|
-
const normalized = raw.trim();
|
|
85
|
-
if (normalized === "es2020" || normalized === "es2022") return normalized;
|
|
86
|
-
throw new Error(`Invalid --target "${raw}". Use es2020 or es2022.`);
|
|
87
|
+
resolvePluginEntry(discoveredPlugin) {
|
|
88
|
+
if (typeof discoveredPlugin.developmentEntry === "string" && discoveredPlugin.developmentEntry.trim().length > 0) return discoveredPlugin.developmentEntry;
|
|
89
|
+
return discoveredPlugin.pluginEntry;
|
|
87
90
|
}
|
|
88
91
|
};
|
|
89
92
|
|
|
90
93
|
//#endregion
|
|
91
94
|
//#region src/commands/BuildCommand.ts
|
|
92
95
|
var BuildCommand = class {
|
|
93
|
-
constructor(cliLogger, pathResolver, pluginDiscovery,
|
|
96
|
+
constructor(cliLogger, pathResolver, consumerOutputBuilderFactory, pluginDiscovery, consumerBuildArtifactsPublisher, tsRuntime) {
|
|
94
97
|
this.cliLogger = cliLogger;
|
|
95
98
|
this.pathResolver = pathResolver;
|
|
99
|
+
this.consumerOutputBuilderFactory = consumerOutputBuilderFactory;
|
|
96
100
|
this.pluginDiscovery = pluginDiscovery;
|
|
97
|
-
this.
|
|
101
|
+
this.consumerBuildArtifactsPublisher = consumerBuildArtifactsPublisher;
|
|
98
102
|
this.tsRuntime = tsRuntime;
|
|
99
|
-
this.outputBuilderLoader = outputBuilderLoader;
|
|
100
103
|
}
|
|
101
104
|
async execute(consumerRoot, buildOptions) {
|
|
102
105
|
const paths = await this.pathResolver.resolve(consumerRoot);
|
|
103
106
|
this.tsRuntime.configure(paths.repoRoot);
|
|
104
|
-
const snapshot = await this.
|
|
107
|
+
const snapshot = await this.consumerOutputBuilderFactory.create(paths.consumerRoot, { buildOptions }).ensureBuilt();
|
|
105
108
|
const discoveredPlugins = await this.pluginDiscovery.discover(paths.consumerRoot);
|
|
106
|
-
const manifest = await this.
|
|
109
|
+
const manifest = await this.consumerBuildArtifactsPublisher.publish(snapshot, discoveredPlugins);
|
|
107
110
|
this.cliLogger.info(`Built consumer output: ${snapshot.outputEntryPath}`);
|
|
108
|
-
this.cliLogger.info(`
|
|
109
|
-
this.cliLogger.info(`
|
|
111
|
+
this.cliLogger.info(`Build manifest: ${manifest.manifestPath}`);
|
|
112
|
+
this.cliLogger.info(`Workflow modules emitted: ${snapshot.workflowSourcePaths.length}`);
|
|
110
113
|
}
|
|
111
114
|
};
|
|
112
115
|
|
|
@@ -125,7 +128,7 @@ var DbMigrateCommand = class {
|
|
|
125
128
|
//#region src/commands/DevCommand.ts
|
|
126
129
|
var DevCommand = class {
|
|
127
130
|
require = createRequire(import.meta.url);
|
|
128
|
-
constructor(pathResolver, tsRuntime, devLockFactory, devSourceWatcherFactory, cliLogger, session, databaseMigrationsApplyService, devBootstrapSummaryFetcher, devCliBannerRenderer,
|
|
131
|
+
constructor(pathResolver, tsRuntime, devLockFactory, devSourceWatcherFactory, cliLogger, session, databaseMigrationsApplyService, consumerOutputBuilderFactory, pluginDiscovery, consumerBuildArtifactsPublisher, devBootstrapSummaryFetcher, devCliBannerRenderer, consumerEnvDotenvFilePredicate, devTrackedProcessTreeKiller, nextHostConsumerServerCommandFactory, devApiRuntimeFactory, cliDevProxyServerFactory, devRebuildQueueFactory) {
|
|
129
132
|
this.pathResolver = pathResolver;
|
|
130
133
|
this.tsRuntime = tsRuntime;
|
|
131
134
|
this.devLockFactory = devLockFactory;
|
|
@@ -133,9 +136,11 @@ var DevCommand = class {
|
|
|
133
136
|
this.cliLogger = cliLogger;
|
|
134
137
|
this.session = session;
|
|
135
138
|
this.databaseMigrationsApplyService = databaseMigrationsApplyService;
|
|
139
|
+
this.consumerOutputBuilderFactory = consumerOutputBuilderFactory;
|
|
140
|
+
this.pluginDiscovery = pluginDiscovery;
|
|
141
|
+
this.consumerBuildArtifactsPublisher = consumerBuildArtifactsPublisher;
|
|
136
142
|
this.devBootstrapSummaryFetcher = devBootstrapSummaryFetcher;
|
|
137
143
|
this.devCliBannerRenderer = devCliBannerRenderer;
|
|
138
|
-
this.devConsumerPublishBootstrap = devConsumerPublishBootstrap;
|
|
139
144
|
this.consumerEnvDotenvFilePredicate = consumerEnvDotenvFilePredicate;
|
|
140
145
|
this.devTrackedProcessTreeKiller = devTrackedProcessTreeKiller;
|
|
141
146
|
this.nextHostConsumerServerCommandFactory = nextHostConsumerServerCommandFactory;
|
|
@@ -145,10 +150,11 @@ var DevCommand = class {
|
|
|
145
150
|
}
|
|
146
151
|
async execute(args) {
|
|
147
152
|
const paths = await this.pathResolver.resolve(args.consumerRoot);
|
|
153
|
+
const commandName = args.commandName ?? "dev";
|
|
154
|
+
const previousDevelopmentServerToken = process$1.env.CODEMATION_DEV_SERVER_TOKEN;
|
|
148
155
|
this.devCliBannerRenderer.renderBrandHeader();
|
|
149
156
|
this.tsRuntime.configure(paths.repoRoot);
|
|
150
|
-
await this.databaseMigrationsApplyService.applyForConsumer(paths.consumerRoot);
|
|
151
|
-
await this.devConsumerPublishBootstrap.ensurePublished(paths);
|
|
157
|
+
await this.databaseMigrationsApplyService.applyForConsumer(paths.consumerRoot, { configPath: args.configPathOverride });
|
|
152
158
|
const devMode = this.resolveDevMode(args);
|
|
153
159
|
const { nextPort, gatewayPort } = await this.session.sessionPorts.resolve({
|
|
154
160
|
devMode,
|
|
@@ -160,26 +166,34 @@ var DevCommand = class {
|
|
|
160
166
|
consumerRoot: paths.consumerRoot,
|
|
161
167
|
nextPort: devMode === "watch-framework" ? nextPort : gatewayPort
|
|
162
168
|
});
|
|
163
|
-
const authSettings = await this.session.
|
|
169
|
+
const authSettings = await this.session.nextHostEdgeSeedLoader.loadForConsumer(paths.consumerRoot, { configPathOverride: args.configPathOverride });
|
|
164
170
|
const watcher = this.devSourceWatcherFactory.create();
|
|
165
171
|
const processState = this.createInitialProcessState();
|
|
166
172
|
let proxyServer = null;
|
|
167
173
|
try {
|
|
168
|
-
const prepared = await this.prepareDevRuntime(paths, devMode, nextPort, gatewayPort, authSettings);
|
|
174
|
+
const prepared = await this.prepareDevRuntime(paths, devMode, nextPort, gatewayPort, authSettings, args.configPathOverride);
|
|
175
|
+
if (prepared.devMode === "packaged-ui") await this.publishConsumerArtifacts(prepared.paths, prepared.configPathOverride);
|
|
176
|
+
process$1.env.CODEMATION_DEV_SERVER_TOKEN = prepared.developmentServerToken;
|
|
169
177
|
const stopPromise = this.wireStopPromise(processState);
|
|
170
|
-
const uiProxyBase = await this.
|
|
178
|
+
const uiProxyBase = await this.preparePackagedUiBaseUrlWhenNeeded(prepared, processState);
|
|
171
179
|
proxyServer = await this.startProxyServer(prepared.gatewayPort, uiProxyBase);
|
|
172
180
|
const gatewayBaseUrl = this.gatewayBaseHttpUrl(gatewayPort);
|
|
173
181
|
await this.bootInitialRuntime(prepared, processState, proxyServer);
|
|
174
182
|
await this.session.devHttpProbe.waitUntilBootstrapSummaryReady(gatewayBaseUrl);
|
|
175
183
|
const initialSummary = await this.devBootstrapSummaryFetcher.fetch(gatewayBaseUrl);
|
|
176
184
|
if (initialSummary) this.devCliBannerRenderer.renderRuntimeSummary(initialSummary);
|
|
185
|
+
await this.startPackagedUiWhenNeeded(prepared, processState, uiProxyBase);
|
|
177
186
|
this.bindShutdownSignalsToChildProcesses(processState, proxyServer);
|
|
178
187
|
await this.spawnDevUiWhenNeeded(prepared, processState, gatewayBaseUrl);
|
|
179
|
-
await this.startWatcherForSourceRestart(prepared, processState, watcher, devMode, gatewayBaseUrl, proxyServer
|
|
180
|
-
|
|
188
|
+
await this.startWatcherForSourceRestart(prepared, processState, watcher, devMode, gatewayBaseUrl, proxyServer, {
|
|
189
|
+
commandName,
|
|
190
|
+
configPathOverride: args.configPathOverride
|
|
191
|
+
});
|
|
192
|
+
this.logPackagedUiDevHintWhenNeeded(devMode, gatewayPort, commandName);
|
|
181
193
|
await stopPromise;
|
|
182
194
|
} finally {
|
|
195
|
+
if (previousDevelopmentServerToken === void 0) delete process$1.env.CODEMATION_DEV_SERVER_TOKEN;
|
|
196
|
+
else process$1.env.CODEMATION_DEV_SERVER_TOKEN = previousDevelopmentServerToken;
|
|
183
197
|
processState.stopRequested = true;
|
|
184
198
|
await this.stopLiveProcesses(processState, proxyServer);
|
|
185
199
|
await watcher.stop();
|
|
@@ -190,14 +204,15 @@ var DevCommand = class {
|
|
|
190
204
|
if (args.watchFramework === true || process$1.env.CODEMATION_DEV_MODE === "framework") return "watch-framework";
|
|
191
205
|
return "packaged-ui";
|
|
192
206
|
}
|
|
193
|
-
async prepareDevRuntime(paths, devMode, nextPort, gatewayPort, authSettings) {
|
|
207
|
+
async prepareDevRuntime(paths, devMode, nextPort, gatewayPort, authSettings, configPathOverride) {
|
|
194
208
|
return {
|
|
195
209
|
paths,
|
|
210
|
+
configPathOverride,
|
|
196
211
|
devMode,
|
|
197
212
|
nextPort,
|
|
198
213
|
gatewayPort,
|
|
199
214
|
authSettings,
|
|
200
|
-
developmentServerToken: this.session.
|
|
215
|
+
developmentServerToken: this.session.nextHostEdgeSeedLoader.resolveDevelopmentServerToken(process$1.env.CODEMATION_DEV_SERVER_TOKEN),
|
|
201
216
|
consumerEnv: this.session.consumerEnvLoader.load(paths.consumerRoot)
|
|
202
217
|
};
|
|
203
218
|
}
|
|
@@ -222,30 +237,30 @@ var DevCommand = class {
|
|
|
222
237
|
gatewayBaseHttpUrl(gatewayPort) {
|
|
223
238
|
return `http://127.0.0.1:${gatewayPort}`;
|
|
224
239
|
}
|
|
225
|
-
async
|
|
240
|
+
async preparePackagedUiBaseUrlWhenNeeded(prepared, state) {
|
|
226
241
|
if (prepared.devMode !== "packaged-ui") return "";
|
|
227
|
-
const websocketPort = prepared.gatewayPort;
|
|
228
242
|
const uiProxyBase = state.currentPackagedUiBaseUrl ?? `http://127.0.0.1:${await this.session.loopbackPortAllocator.allocate()}`;
|
|
229
243
|
state.currentPackagedUiBaseUrl = uiProxyBase;
|
|
230
|
-
await this.spawnPackagedUi(prepared, state, prepared.authSettings, websocketPort, uiProxyBase);
|
|
231
244
|
return uiProxyBase;
|
|
232
245
|
}
|
|
246
|
+
async startPackagedUiWhenNeeded(prepared, state, uiProxyBase) {
|
|
247
|
+
if (prepared.devMode !== "packaged-ui" || uiProxyBase.length === 0) return;
|
|
248
|
+
await this.spawnPackagedUi(prepared, state, prepared.authSettings, prepared.gatewayPort, uiProxyBase);
|
|
249
|
+
}
|
|
233
250
|
async spawnPackagedUi(prepared, state, authSettings, websocketPort, uiProxyBase) {
|
|
234
251
|
const nextHostPackageJsonPath = this.require.resolve("@codemation/next-host/package.json");
|
|
235
252
|
const nextHostRoot = path.dirname(nextHostPackageJsonPath);
|
|
236
253
|
const nextHostCommand = await this.nextHostConsumerServerCommandFactory.create({ nextHostRoot });
|
|
237
|
-
const consumerOutputManifestPath = path.resolve(prepared.paths.consumerRoot, ".codemation", "output", "current.json");
|
|
238
254
|
const uiPort = Number(new URL(uiProxyBase).port);
|
|
239
255
|
const nextHostEnvironment = this.session.nextHostEnvBuilder.buildConsumerUiProxy({
|
|
240
|
-
authConfigJson: authSettings.authConfigJson,
|
|
241
256
|
authSecret: authSettings.authSecret,
|
|
257
|
+
configPathOverride: prepared.configPathOverride,
|
|
242
258
|
consumerRoot: prepared.paths.consumerRoot,
|
|
243
|
-
consumerOutputManifestPath,
|
|
244
259
|
developmentServerToken: prepared.developmentServerToken,
|
|
245
260
|
nextPort: uiPort,
|
|
246
261
|
publicBaseUrl: this.gatewayBaseHttpUrl(prepared.gatewayPort),
|
|
247
262
|
runtimeDevUrl: this.gatewayBaseHttpUrl(prepared.gatewayPort),
|
|
248
|
-
skipUiAuth: authSettings.
|
|
263
|
+
skipUiAuth: !authSettings.uiAuthEnabled,
|
|
249
264
|
websocketPort
|
|
250
265
|
});
|
|
251
266
|
state.currentPackagedUi = spawn(nextHostCommand.command, nextHostCommand.args, {
|
|
@@ -319,11 +334,12 @@ var DevCommand = class {
|
|
|
319
334
|
const nextHostPackageJsonPath = this.require.resolve("@codemation/next-host/package.json");
|
|
320
335
|
const nextHostRoot = path.dirname(nextHostPackageJsonPath);
|
|
321
336
|
const nextHostEnvironment = this.session.nextHostEnvBuilder.build({
|
|
322
|
-
|
|
337
|
+
authSecret: authSettings.authSecret,
|
|
338
|
+
configPathOverride: prepared.configPathOverride,
|
|
323
339
|
consumerRoot: prepared.paths.consumerRoot,
|
|
324
340
|
developmentServerToken: prepared.developmentServerToken,
|
|
325
341
|
nextPort: prepared.nextPort,
|
|
326
|
-
skipUiAuth: authSettings.
|
|
342
|
+
skipUiAuth: !authSettings.uiAuthEnabled,
|
|
327
343
|
websocketPort,
|
|
328
344
|
runtimeDevUrl: gatewayBaseUrl
|
|
329
345
|
});
|
|
@@ -354,7 +370,7 @@ var DevCommand = class {
|
|
|
354
370
|
});
|
|
355
371
|
await this.session.devHttpProbe.waitUntilUrlRespondsOk(`http://127.0.0.1:${prepared.nextPort}/`);
|
|
356
372
|
}
|
|
357
|
-
async startWatcherForSourceRestart(prepared, state, watcher, devMode, gatewayBaseUrl, proxyServer) {
|
|
373
|
+
async startWatcherForSourceRestart(prepared, state, watcher, devMode, gatewayBaseUrl, proxyServer, options) {
|
|
358
374
|
const rebuildQueue = this.devRebuildQueueFactory.create({ run: async (request) => {
|
|
359
375
|
await this.runQueuedRebuild(prepared, state, gatewayBaseUrl, proxyServer, request);
|
|
360
376
|
} });
|
|
@@ -370,18 +386,14 @@ var DevCommand = class {
|
|
|
370
386
|
return;
|
|
371
387
|
}
|
|
372
388
|
try {
|
|
373
|
-
const shouldRepublishConsumerOutput = this.session.sourceChangeClassifier.shouldRepublishConsumerOutput({
|
|
374
|
-
changedPaths,
|
|
375
|
-
consumerRoot: prepared.paths.consumerRoot
|
|
376
|
-
});
|
|
377
389
|
const shouldRestartUi = this.session.sourceChangeClassifier.requiresUiRestart({
|
|
378
390
|
changedPaths,
|
|
379
391
|
consumerRoot: prepared.paths.consumerRoot
|
|
380
392
|
});
|
|
381
|
-
process$1.stdout.write(shouldRestartUi ?
|
|
393
|
+
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
394
|
await rebuildQueue.enqueue({
|
|
383
395
|
changedPaths,
|
|
384
|
-
|
|
396
|
+
configPathOverride: options.configPathOverride,
|
|
385
397
|
shouldRestartUi
|
|
386
398
|
});
|
|
387
399
|
} catch (error) {
|
|
@@ -395,7 +407,7 @@ var DevCommand = class {
|
|
|
395
407
|
proxyServer.setBuildStatus("building");
|
|
396
408
|
proxyServer.broadcastBuildStarted();
|
|
397
409
|
try {
|
|
398
|
-
if (
|
|
410
|
+
if (prepared.devMode === "packaged-ui") await this.publishConsumerArtifacts(prepared.paths, request.configPathOverride);
|
|
399
411
|
await this.stopCurrentRuntime(state, proxyServer);
|
|
400
412
|
process$1.stdout.write("[codemation] Waiting for runtime to accept traffic…\n");
|
|
401
413
|
const runtime = await this.createRuntime(prepared);
|
|
@@ -404,11 +416,11 @@ var DevCommand = class {
|
|
|
404
416
|
httpPort: runtime.httpPort,
|
|
405
417
|
workflowWebSocketPort: runtime.workflowWebSocketPort
|
|
406
418
|
});
|
|
407
|
-
if (request.shouldRestartUi) await this.restartUiAfterSourceChange(prepared, state, gatewayBaseUrl);
|
|
408
419
|
await this.session.devHttpProbe.waitUntilBootstrapSummaryReady(gatewayBaseUrl);
|
|
409
420
|
const json = await this.devBootstrapSummaryFetcher.fetch(gatewayBaseUrl);
|
|
410
421
|
if (json) this.devCliBannerRenderer.renderCompact(json);
|
|
411
422
|
proxyServer.setBuildStatus("idle");
|
|
423
|
+
if (request.shouldRestartUi) await this.restartUiAfterSourceChange(prepared, state, gatewayBaseUrl);
|
|
412
424
|
proxyServer.broadcastBuildCompleted(runtime.buildVersion);
|
|
413
425
|
process$1.stdout.write("[codemation] Runtime ready.\n");
|
|
414
426
|
} catch (error) {
|
|
@@ -418,7 +430,7 @@ var DevCommand = class {
|
|
|
418
430
|
}
|
|
419
431
|
}
|
|
420
432
|
async restartUiAfterSourceChange(prepared, state, gatewayBaseUrl) {
|
|
421
|
-
const refreshedAuthSettings = await this.session.
|
|
433
|
+
const refreshedAuthSettings = await this.session.nextHostEdgeSeedLoader.loadForConsumer(prepared.paths.consumerRoot, { configPathOverride: prepared.configPathOverride });
|
|
422
434
|
process$1.stdout.write("[codemation] Restarting the UI process to apply source changes…\n");
|
|
423
435
|
state.isRestartingUi = true;
|
|
424
436
|
try {
|
|
@@ -465,6 +477,7 @@ var DevCommand = class {
|
|
|
465
477
|
async createRuntime(prepared) {
|
|
466
478
|
const runtimeEnvironment = this.session.consumerEnvLoader.mergeIntoProcessEnvironment(process$1.env, prepared.consumerEnv);
|
|
467
479
|
return await this.devApiRuntimeFactory.create({
|
|
480
|
+
configPathOverride: prepared.configPathOverride,
|
|
468
481
|
consumerRoot: prepared.paths.consumerRoot,
|
|
469
482
|
runtimeWorkingDirectory: process$1.cwd(),
|
|
470
483
|
env: {
|
|
@@ -477,9 +490,33 @@ var DevCommand = class {
|
|
|
477
490
|
}
|
|
478
491
|
});
|
|
479
492
|
}
|
|
480
|
-
|
|
493
|
+
async publishConsumerArtifacts(paths, configPathOverride) {
|
|
494
|
+
const snapshot = await this.consumerOutputBuilderFactory.create(paths.consumerRoot, { configPathOverride }).ensureBuilt();
|
|
495
|
+
const discoveredPlugins = await this.pluginDiscovery.discover(paths.consumerRoot);
|
|
496
|
+
await this.consumerBuildArtifactsPublisher.publish(snapshot, discoveredPlugins);
|
|
497
|
+
this.cliLogger.debug(`Dev: consumer output published (${snapshot.buildVersion}).`);
|
|
498
|
+
}
|
|
499
|
+
logPackagedUiDevHintWhenNeeded(devMode, gatewayPort, commandName) {
|
|
481
500
|
if (devMode !== "packaged-ui") return;
|
|
482
|
-
this.cliLogger.info(`codemation
|
|
501
|
+
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.`);
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
//#endregion
|
|
506
|
+
//#region src/commands/DevPluginCommand.ts
|
|
507
|
+
var DevPluginCommand = class {
|
|
508
|
+
constructor(pluginDevConfigFactory, devCommand) {
|
|
509
|
+
this.pluginDevConfigFactory = pluginDevConfigFactory;
|
|
510
|
+
this.devCommand = devCommand;
|
|
511
|
+
}
|
|
512
|
+
async execute(args) {
|
|
513
|
+
const pluginConfig = await this.pluginDevConfigFactory.prepare(args.pluginRoot);
|
|
514
|
+
await this.devCommand.execute({
|
|
515
|
+
commandName: "dev:plugin",
|
|
516
|
+
configPathOverride: pluginConfig.configPath,
|
|
517
|
+
consumerRoot: args.pluginRoot,
|
|
518
|
+
watchFramework: args.watchFramework
|
|
519
|
+
});
|
|
483
520
|
}
|
|
484
521
|
};
|
|
485
522
|
|
|
@@ -487,38 +524,22 @@ var DevCommand = class {
|
|
|
487
524
|
//#region src/commands/ServeWebCommand.ts
|
|
488
525
|
var ServeWebCommand = class {
|
|
489
526
|
require = createRequire(import.meta.url);
|
|
490
|
-
constructor(pathResolver, configLoader,
|
|
527
|
+
constructor(pathResolver, configLoader, tsRuntime, sourceMapNodeOptions, envLoader, listenPortResolver, nextHostConsumerServerCommandFactory) {
|
|
491
528
|
this.pathResolver = pathResolver;
|
|
492
529
|
this.configLoader = configLoader;
|
|
493
|
-
this.pluginDiscovery = pluginDiscovery;
|
|
494
|
-
this.artifactsPublisher = artifactsPublisher;
|
|
495
530
|
this.tsRuntime = tsRuntime;
|
|
496
531
|
this.sourceMapNodeOptions = sourceMapNodeOptions;
|
|
497
|
-
this.outputBuilderLoader = outputBuilderLoader;
|
|
498
532
|
this.envLoader = envLoader;
|
|
499
533
|
this.listenPortResolver = listenPortResolver;
|
|
500
534
|
this.nextHostConsumerServerCommandFactory = nextHostConsumerServerCommandFactory;
|
|
501
|
-
this.frontendAuthSnapshotFactory = frontendAuthSnapshotFactory;
|
|
502
|
-
this.frontendAppConfigJsonCodec = frontendAppConfigJsonCodec;
|
|
503
535
|
}
|
|
504
536
|
async execute(consumerRoot, buildOptions) {
|
|
505
537
|
const paths = await this.pathResolver.resolve(consumerRoot);
|
|
506
538
|
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
539
|
const nextHostRoot = path.dirname(this.require.resolve("@codemation/next-host/package.json"));
|
|
511
540
|
const nextHostCommand = await this.nextHostConsumerServerCommandFactory.create({ nextHostRoot });
|
|
512
541
|
const consumerEnv = this.envLoader.load(paths.consumerRoot);
|
|
513
542
|
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
543
|
const nextPort = this.listenPortResolver.resolvePrimaryApplicationPort(process$1.env.PORT);
|
|
523
544
|
const websocketPort = this.listenPortResolver.resolveWebsocketPortRelativeToHttp({
|
|
524
545
|
nextPort,
|
|
@@ -532,13 +553,8 @@ var ServeWebCommand = class {
|
|
|
532
553
|
...process$1.env,
|
|
533
554
|
...consumerEnv,
|
|
534
555
|
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
556
|
CODEMATION_CONSUMER_ROOT: paths.consumerRoot,
|
|
557
|
+
CODEMATION_UI_AUTH_ENABLED: String(!(consumerEnv.NODE_ENV !== "production" && configResolution.config.auth?.allowUnauthenticatedInDevelopment === true)),
|
|
542
558
|
CODEMATION_WS_PORT: String(websocketPort),
|
|
543
559
|
NEXT_PUBLIC_CODEMATION_WS_PORT: String(websocketPort),
|
|
544
560
|
NODE_OPTIONS: this.sourceMapNodeOptions.appendToNodeOptions(process$1.env.NODE_OPTIONS),
|
|
@@ -765,8 +781,9 @@ var ConsumerOutputBuilder = class ConsumerOutputBuilder {
|
|
|
765
781
|
lastIssuedBuildVersion = 0;
|
|
766
782
|
log;
|
|
767
783
|
buildOptions;
|
|
768
|
-
constructor(consumerRoot, logOverride, buildOptionsOverride) {
|
|
784
|
+
constructor(consumerRoot, logOverride, buildOptionsOverride, configPathOverride) {
|
|
769
785
|
this.consumerRoot = consumerRoot;
|
|
786
|
+
this.configPathOverride = configPathOverride;
|
|
770
787
|
this.log = logOverride ?? defaultConsumerOutputLogger;
|
|
771
788
|
this.buildOptions = buildOptionsOverride ?? defaultConsumerBuildOptions;
|
|
772
789
|
}
|
|
@@ -978,6 +995,7 @@ var ConsumerOutputBuilder = class ConsumerOutputBuilder {
|
|
|
978
995
|
sourcePath
|
|
979
996
|
});
|
|
980
997
|
}
|
|
998
|
+
await this.emitConfigSourceFile(outputAppRoot, configSourcePath, runtimeSourcePaths);
|
|
981
999
|
}
|
|
982
1000
|
});
|
|
983
1001
|
}
|
|
@@ -1036,6 +1054,14 @@ var ConsumerOutputBuilder = class ConsumerOutputBuilder {
|
|
|
1036
1054
|
await writeFile(outputPath, rewrittenOutputText, "utf8");
|
|
1037
1055
|
if (transpiledOutput.sourceMapText) await writeFile(`${outputPath}.map`, transpiledOutput.sourceMapText, "utf8");
|
|
1038
1056
|
}
|
|
1057
|
+
async emitConfigSourceFile(outputAppRoot, configSourcePath, runtimeSourcePaths) {
|
|
1058
|
+
const normalizedConfigSourcePath = path.resolve(configSourcePath);
|
|
1059
|
+
if (runtimeSourcePaths.some((sourcePath) => path.resolve(sourcePath) === normalizedConfigSourcePath)) return;
|
|
1060
|
+
await this.emitSourceFile({
|
|
1061
|
+
outputAppRoot,
|
|
1062
|
+
sourcePath: normalizedConfigSourcePath
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1039
1065
|
createCompilerOptions() {
|
|
1040
1066
|
const scriptTarget = this.buildOptions.target === "es2020" ? ts.ScriptTarget.ES2020 : ts.ScriptTarget.ES2022;
|
|
1041
1067
|
return {
|
|
@@ -1176,6 +1202,12 @@ var ConsumerOutputBuilder = class ConsumerOutputBuilder {
|
|
|
1176
1202
|
return `${nextBuildVersion}-${process$1.pid}`;
|
|
1177
1203
|
}
|
|
1178
1204
|
async resolveConfigPath(consumerRoot) {
|
|
1205
|
+
const configuredOverride = this.configPathOverride?.trim();
|
|
1206
|
+
if (configuredOverride && configuredOverride.length > 0) {
|
|
1207
|
+
const resolvedOverride = path.resolve(configuredOverride);
|
|
1208
|
+
if (await this.fileExists(resolvedOverride)) return resolvedOverride;
|
|
1209
|
+
throw new Error(`Codemation config override not found at ${resolvedOverride}.`);
|
|
1210
|
+
}
|
|
1179
1211
|
for (const candidate of this.getConventionCandidates(consumerRoot)) if (await this.fileExists(candidate)) return candidate;
|
|
1180
1212
|
return null;
|
|
1181
1213
|
}
|
|
@@ -1289,10 +1321,10 @@ var ConsumerOutputBuilder = class ConsumerOutputBuilder {
|
|
|
1289
1321
|
};
|
|
1290
1322
|
|
|
1291
1323
|
//#endregion
|
|
1292
|
-
//#region src/consumer/
|
|
1293
|
-
var
|
|
1294
|
-
create(consumerRoot,
|
|
1295
|
-
return new ConsumerOutputBuilder(consumerRoot,
|
|
1324
|
+
//#region src/consumer/ConsumerOutputBuilderFactory.ts
|
|
1325
|
+
var ConsumerOutputBuilderFactory = class {
|
|
1326
|
+
create(consumerRoot, args) {
|
|
1327
|
+
return new ConsumerOutputBuilder(consumerRoot, args?.logger, args?.buildOptions, args?.configPathOverride);
|
|
1296
1328
|
}
|
|
1297
1329
|
};
|
|
1298
1330
|
|
|
@@ -1464,8 +1496,9 @@ var DevCliBannerRenderer = class {
|
|
|
1464
1496
|
title: chalk.bold("Runtime"),
|
|
1465
1497
|
titleAlignment: "center"
|
|
1466
1498
|
});
|
|
1499
|
+
const pluginsSection = this.buildPluginsSection(summary);
|
|
1467
1500
|
const activeSection = this.buildActiveWorkflowsSection(summary);
|
|
1468
|
-
process.stdout.write(`${detailBox}\n${activeSection}\n`);
|
|
1501
|
+
process.stdout.write(`${detailBox}\n${pluginsSection}\n${activeSection}\n`);
|
|
1469
1502
|
}
|
|
1470
1503
|
renderFull(summary) {
|
|
1471
1504
|
this.renderBrandHeader();
|
|
@@ -1492,8 +1525,9 @@ var DevCliBannerRenderer = class {
|
|
|
1492
1525
|
title: chalk.bold("Runtime (updated)"),
|
|
1493
1526
|
titleAlignment: "center"
|
|
1494
1527
|
});
|
|
1528
|
+
const pluginsSection = this.buildPluginsSection(summary);
|
|
1495
1529
|
const activeSection = this.buildActiveWorkflowsSection(summary);
|
|
1496
|
-
process.stdout.write(`\n${detailBox}\n${activeSection}\n`);
|
|
1530
|
+
process.stdout.write(`\n${detailBox}\n${pluginsSection}\n${activeSection}\n`);
|
|
1497
1531
|
}
|
|
1498
1532
|
renderFigletTitle() {
|
|
1499
1533
|
try {
|
|
@@ -1532,28 +1566,23 @@ var DevCliBannerRenderer = class {
|
|
|
1532
1566
|
titleAlignment: "left"
|
|
1533
1567
|
});
|
|
1534
1568
|
}
|
|
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}).`);
|
|
1569
|
+
buildPluginsSection(summary) {
|
|
1570
|
+
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"), {
|
|
1571
|
+
padding: {
|
|
1572
|
+
top: 0,
|
|
1573
|
+
bottom: 0,
|
|
1574
|
+
left: 0,
|
|
1575
|
+
right: 0
|
|
1576
|
+
},
|
|
1577
|
+
margin: {
|
|
1578
|
+
top: 1,
|
|
1579
|
+
bottom: 0
|
|
1580
|
+
},
|
|
1581
|
+
borderStyle: "single",
|
|
1582
|
+
borderColor: "cyan",
|
|
1583
|
+
title: chalk.bold("Plugins"),
|
|
1584
|
+
titleAlignment: "left"
|
|
1585
|
+
});
|
|
1557
1586
|
}
|
|
1558
1587
|
};
|
|
1559
1588
|
|
|
@@ -1746,12 +1775,27 @@ var CliDevProxyServer = class {
|
|
|
1746
1775
|
return url.split("?")[0] ?? url;
|
|
1747
1776
|
}
|
|
1748
1777
|
}
|
|
1778
|
+
extractOccupyingPids(listenerDescription) {
|
|
1779
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1780
|
+
const re = /pid=(\d+)/g;
|
|
1781
|
+
let match;
|
|
1782
|
+
while ((match = re.exec(listenerDescription)) !== null) {
|
|
1783
|
+
const pid = Number.parseInt(match[1] ?? "0", 10);
|
|
1784
|
+
if (Number.isFinite(pid) && pid > 0) seen.add(pid);
|
|
1785
|
+
}
|
|
1786
|
+
return [...seen];
|
|
1787
|
+
}
|
|
1749
1788
|
async rejectListenError(error, reject) {
|
|
1750
1789
|
if (error.code !== "EADDRINUSE") {
|
|
1751
1790
|
reject(error);
|
|
1752
1791
|
return;
|
|
1753
1792
|
}
|
|
1754
1793
|
const description = await this.listenPortConflictDescriber.describeLoopbackPort(this.listenPort);
|
|
1794
|
+
const occupyingPids = description !== null ? this.extractOccupyingPids(description) : [];
|
|
1795
|
+
if (occupyingPids.length > 0) {
|
|
1796
|
+
const pidList = occupyingPids.join(", ");
|
|
1797
|
+
process.stderr.write(`[codemation] Dev gateway port ${this.listenPort} is already in use (occupying pid(s): ${pidList}).\n`);
|
|
1798
|
+
}
|
|
1755
1799
|
const baseMessage = `Dev gateway port ${this.listenPort} is already in use on 127.0.0.1.`;
|
|
1756
1800
|
const suffix = description === null ? " Stop the process using that port or change the configured Codemation dev port." : ` Listener: ${description}. Stop that process or change the configured Codemation dev port.`;
|
|
1757
1801
|
reject(new Error(`${baseMessage}${suffix}`, { cause: error instanceof Error ? error : void 0 }));
|
|
@@ -1929,12 +1973,19 @@ var ListenPortConflictDescriber = class {
|
|
|
1929
1973
|
async describeLoopbackPort(port) {
|
|
1930
1974
|
if (!Number.isInteger(port) || port <= 0) return null;
|
|
1931
1975
|
if (this.platform !== "linux" && this.platform !== "darwin") return null;
|
|
1932
|
-
const
|
|
1933
|
-
if (raw === null) return null;
|
|
1934
|
-
const occupants = this.parseLsofOutput(raw);
|
|
1976
|
+
const occupants = await this.resolveLoopbackOccupants(port);
|
|
1935
1977
|
if (occupants.length === 0) return null;
|
|
1936
1978
|
return occupants.map((occupant) => `pid=${occupant.pid} command=${occupant.command} endpoint=${occupant.endpoint}`).join("; ");
|
|
1937
1979
|
}
|
|
1980
|
+
async resolveLoopbackOccupants(port) {
|
|
1981
|
+
const lsofRaw = await this.readLsofOutput(port);
|
|
1982
|
+
const fromLsof = lsofRaw !== null ? this.parseLsofOutput(lsofRaw) : [];
|
|
1983
|
+
if (fromLsof.length > 0) return fromLsof;
|
|
1984
|
+
if (this.platform !== "linux") return [];
|
|
1985
|
+
const ssRaw = await this.readSsOutput(port);
|
|
1986
|
+
if (ssRaw === null) return [];
|
|
1987
|
+
return this.parseSsListenOutput(ssRaw, port);
|
|
1988
|
+
}
|
|
1938
1989
|
async readLsofOutput(port) {
|
|
1939
1990
|
try {
|
|
1940
1991
|
return await new Promise((resolve, reject) => {
|
|
@@ -1980,6 +2031,44 @@ var ListenPortConflictDescriber = class {
|
|
|
1980
2031
|
}
|
|
1981
2032
|
return occupants;
|
|
1982
2033
|
}
|
|
2034
|
+
async readSsOutput(port) {
|
|
2035
|
+
const filtered = await this.execFileStdout("ss", ["-lntp", `sport = :${port}`]);
|
|
2036
|
+
if (filtered !== null && filtered.trim().length > 0) return filtered;
|
|
2037
|
+
return this.execFileStdout("ss", ["-lntp"]);
|
|
2038
|
+
}
|
|
2039
|
+
async execFileStdout(command, args) {
|
|
2040
|
+
try {
|
|
2041
|
+
return await new Promise((resolve, reject) => {
|
|
2042
|
+
execFile(command, [...args], (error, stdout) => {
|
|
2043
|
+
if (error) {
|
|
2044
|
+
reject(error);
|
|
2045
|
+
return;
|
|
2046
|
+
}
|
|
2047
|
+
resolve(stdout);
|
|
2048
|
+
});
|
|
2049
|
+
});
|
|
2050
|
+
} catch {
|
|
2051
|
+
return null;
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
parseSsListenOutput(raw, port) {
|
|
2055
|
+
const occupants = [];
|
|
2056
|
+
const portSuffix = `:${port}`;
|
|
2057
|
+
for (const line of raw.split("\n")) {
|
|
2058
|
+
if (!line.includes("LISTEN") || !line.includes(portSuffix)) continue;
|
|
2059
|
+
const pidMatch = line.match(/pid=(\d+)/);
|
|
2060
|
+
if (!pidMatch) continue;
|
|
2061
|
+
const pid = Number.parseInt(pidMatch[1] ?? "0", 10);
|
|
2062
|
+
const command = line.match(/users:\(\("([^"]*)"/)?.[1] ?? "unknown";
|
|
2063
|
+
const endpoint = line.match(/\s+(\S+:\d+|\[[^\]]+\]:\d+)\s+/)?.[1] ?? `tcp:${String(port)}`;
|
|
2064
|
+
occupants.push({
|
|
2065
|
+
pid,
|
|
2066
|
+
command,
|
|
2067
|
+
endpoint
|
|
2068
|
+
});
|
|
2069
|
+
}
|
|
2070
|
+
return occupants;
|
|
2071
|
+
}
|
|
1983
2072
|
};
|
|
1984
2073
|
|
|
1985
2074
|
//#endregion
|
|
@@ -2089,7 +2178,8 @@ var CodemationTsyringeTypeInfoRegistrar = class {
|
|
|
2089
2178
|
//#endregion
|
|
2090
2179
|
//#region src/dev/DevApiRuntimeHost.ts
|
|
2091
2180
|
var DevApiRuntimeHost = class {
|
|
2092
|
-
|
|
2181
|
+
pluginPackageMetadata = new CodemationPluginPackageMetadata();
|
|
2182
|
+
pluginListMerger = new CodemationPluginListMerger(this.pluginPackageMetadata);
|
|
2093
2183
|
contextPromise = null;
|
|
2094
2184
|
constructor(configLoader, pluginDiscovery, args) {
|
|
2095
2185
|
this.configLoader = configLoader;
|
|
@@ -2118,14 +2208,17 @@ var DevApiRuntimeHost = class {
|
|
|
2118
2208
|
env.CODEMATION_CONSUMER_ROOT = consumerRoot;
|
|
2119
2209
|
const configResolution = await this.configLoader.load({
|
|
2120
2210
|
consumerRoot,
|
|
2211
|
+
configPathOverride: this.args.configPathOverride,
|
|
2121
2212
|
repoRoot,
|
|
2122
2213
|
env
|
|
2123
2214
|
});
|
|
2124
2215
|
const discoveredPlugins = await this.loadDiscoveredPlugins(consumerRoot);
|
|
2216
|
+
const mergedPlugins = discoveredPlugins.length > 0 ? this.pluginListMerger.merge(configResolution.appConfig.plugins, discoveredPlugins) : configResolution.appConfig.plugins;
|
|
2125
2217
|
const appConfig = {
|
|
2126
2218
|
...configResolution.appConfig,
|
|
2127
2219
|
env,
|
|
2128
|
-
plugins:
|
|
2220
|
+
plugins: mergedPlugins,
|
|
2221
|
+
pluginLoadSummary: this.createPluginLoadSummary(configResolution.appConfig.plugins, discoveredPlugins, mergedPlugins)
|
|
2129
2222
|
};
|
|
2130
2223
|
const container = await new AppContainerFactory$1().create({
|
|
2131
2224
|
appConfig,
|
|
@@ -2145,6 +2238,20 @@ var DevApiRuntimeHost = class {
|
|
|
2145
2238
|
async loadDiscoveredPlugins(consumerRoot) {
|
|
2146
2239
|
return (await this.pluginDiscovery.resolvePlugins(consumerRoot)).map((resolvedPackage) => resolvedPackage.plugin);
|
|
2147
2240
|
}
|
|
2241
|
+
createPluginLoadSummary(configuredPlugins, discoveredPlugins, mergedPlugins) {
|
|
2242
|
+
const configuredPluginSet = new Set(configuredPlugins);
|
|
2243
|
+
const discoveredPluginSet = new Set(discoveredPlugins);
|
|
2244
|
+
const summaries = [];
|
|
2245
|
+
for (const plugin of mergedPlugins) {
|
|
2246
|
+
const packageName = this.pluginPackageMetadata.readPackageName(plugin);
|
|
2247
|
+
if (!packageName) continue;
|
|
2248
|
+
summaries.push({
|
|
2249
|
+
packageName,
|
|
2250
|
+
source: configuredPluginSet.has(plugin) || !discoveredPluginSet.has(plugin) ? "configured" : "discovered"
|
|
2251
|
+
});
|
|
2252
|
+
}
|
|
2253
|
+
return summaries;
|
|
2254
|
+
}
|
|
2148
2255
|
async detectWorkspaceRoot(startDirectory) {
|
|
2149
2256
|
let currentDirectory = path.resolve(startDirectory);
|
|
2150
2257
|
while (true) {
|
|
@@ -2262,6 +2369,7 @@ var DevApiRuntimeFactory = class {
|
|
|
2262
2369
|
const httpPort = await this.portAllocator.allocate();
|
|
2263
2370
|
const workflowWebSocketPort = await this.portAllocator.allocate();
|
|
2264
2371
|
const runtime = new DevApiRuntimeServer(httpPort, workflowWebSocketPort, new DevApiRuntimeHost(this.configLoader, this.pluginDiscovery, {
|
|
2372
|
+
configPathOverride: args.configPathOverride,
|
|
2265
2373
|
consumerRoot: args.consumerRoot,
|
|
2266
2374
|
env: {
|
|
2267
2375
|
...args.env,
|
|
@@ -2318,7 +2426,7 @@ var DevRebuildQueue = class {
|
|
|
2318
2426
|
};
|
|
2319
2427
|
return {
|
|
2320
2428
|
changedPaths: [...new Set([...current.changedPaths, ...next.changedPaths])],
|
|
2321
|
-
|
|
2429
|
+
configPathOverride: next.configPathOverride ?? current.configPathOverride,
|
|
2322
2430
|
shouldRestartUi: current.shouldRestartUi || next.shouldRestartUi
|
|
2323
2431
|
};
|
|
2324
2432
|
}
|
|
@@ -2366,34 +2474,6 @@ var SourceMapNodeOptions = class {
|
|
|
2366
2474
|
}
|
|
2367
2475
|
};
|
|
2368
2476
|
|
|
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
2477
|
//#endregion
|
|
2398
2478
|
//#region src/dev/DevHttpProbe.ts
|
|
2399
2479
|
var DevHttpProbe = class {
|
|
@@ -2438,52 +2518,41 @@ var DevHttpProbe = class {
|
|
|
2438
2518
|
//#endregion
|
|
2439
2519
|
//#region src/dev/DevNextHostEnvironmentBuilder.ts
|
|
2440
2520
|
var DevNextHostEnvironmentBuilder = class {
|
|
2441
|
-
constructor(consumerEnvLoader, sourceMapNodeOptions
|
|
2521
|
+
constructor(consumerEnvLoader, sourceMapNodeOptions) {
|
|
2442
2522
|
this.consumerEnvLoader = consumerEnvLoader;
|
|
2443
2523
|
this.sourceMapNodeOptions = sourceMapNodeOptions;
|
|
2444
|
-
this.frontendAuthSnapshotFactory = frontendAuthSnapshotFactory;
|
|
2445
|
-
this.frontendAppConfigJsonCodec = frontendAppConfigJsonCodec;
|
|
2446
2524
|
}
|
|
2447
2525
|
buildConsumerUiProxy(args) {
|
|
2526
|
+
const publicWebsocketPort = this.resolvePublicWebsocketPort(args.publicBaseUrl, args.websocketPort);
|
|
2448
2527
|
return {
|
|
2449
2528
|
...this.build({
|
|
2450
|
-
authConfigJson: args.authConfigJson,
|
|
2451
2529
|
authSecret: args.authSecret,
|
|
2530
|
+
configPathOverride: args.configPathOverride,
|
|
2531
|
+
consumerOutputManifestPath: args.consumerOutputManifestPath,
|
|
2452
2532
|
consumerRoot: args.consumerRoot,
|
|
2453
2533
|
developmentServerToken: args.developmentServerToken,
|
|
2454
2534
|
nextPort: args.nextPort,
|
|
2455
2535
|
runtimeDevUrl: args.runtimeDevUrl,
|
|
2456
2536
|
skipUiAuth: args.skipUiAuth,
|
|
2457
|
-
websocketPort: args.websocketPort
|
|
2458
|
-
consumerOutputManifestPath: args.consumerOutputManifestPath
|
|
2537
|
+
websocketPort: args.websocketPort
|
|
2459
2538
|
}),
|
|
2460
2539
|
HOSTNAME: "127.0.0.1",
|
|
2461
2540
|
AUTH_SECRET: args.authSecret,
|
|
2462
|
-
AUTH_URL: args.publicBaseUrl
|
|
2541
|
+
AUTH_URL: args.publicBaseUrl,
|
|
2542
|
+
CODEMATION_PUBLIC_WS_PORT: String(publicWebsocketPort),
|
|
2543
|
+
NEXT_PUBLIC_CODEMATION_WS_PORT: String(publicWebsocketPort)
|
|
2463
2544
|
};
|
|
2464
2545
|
}
|
|
2465
2546
|
build(args) {
|
|
2466
2547
|
const merged = this.consumerEnvLoader.mergeConsumerRootIntoProcessEnvironment(args.consumerRoot, process$1.env);
|
|
2467
|
-
const
|
|
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
|
-
});
|
|
2548
|
+
const consumerOutputManifestPath = args.consumerOutputManifestPath ?? path.resolve(args.consumerRoot, ".codemation", "output", "current.json");
|
|
2477
2549
|
return {
|
|
2478
2550
|
...merged,
|
|
2479
2551
|
PORT: String(args.nextPort),
|
|
2480
2552
|
CODEMATION_CONSUMER_ROOT: args.consumerRoot,
|
|
2481
|
-
CODEMATION_CONSUMER_OUTPUT_MANIFEST_PATH:
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
productName: "Codemation",
|
|
2485
|
-
logoUrl: null
|
|
2486
|
-
}),
|
|
2553
|
+
CODEMATION_CONSUMER_OUTPUT_MANIFEST_PATH: consumerOutputManifestPath,
|
|
2554
|
+
CODEMATION_UI_AUTH_ENABLED: String(!args.skipUiAuth),
|
|
2555
|
+
CODEMATION_PUBLIC_WS_PORT: String(args.websocketPort),
|
|
2487
2556
|
CODEMATION_WS_PORT: String(args.websocketPort),
|
|
2488
2557
|
NEXT_PUBLIC_CODEMATION_WS_PORT: String(args.websocketPort),
|
|
2489
2558
|
CODEMATION_DEV_SERVER_TOKEN: args.developmentServerToken,
|
|
@@ -2491,12 +2560,18 @@ var DevNextHostEnvironmentBuilder = class {
|
|
|
2491
2560
|
NODE_OPTIONS: this.sourceMapNodeOptions.appendToNodeOptions(process$1.env.NODE_OPTIONS),
|
|
2492
2561
|
WS_NO_BUFFER_UTIL: "1",
|
|
2493
2562
|
WS_NO_UTF_8_VALIDATE: "1",
|
|
2563
|
+
...args.authSecret && args.authSecret.trim().length > 0 ? { AUTH_SECRET: args.authSecret.trim() } : {},
|
|
2564
|
+
...args.configPathOverride && args.configPathOverride.trim().length > 0 ? { CODEMATION_CONFIG_PATH: args.configPathOverride } : {},
|
|
2494
2565
|
...args.runtimeDevUrl !== void 0 && args.runtimeDevUrl.trim().length > 0 ? { CODEMATION_RUNTIME_DEV_URL: args.runtimeDevUrl.trim() } : {}
|
|
2495
2566
|
};
|
|
2496
2567
|
}
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2568
|
+
resolvePublicWebsocketPort(publicBaseUrl, fallbackPort) {
|
|
2569
|
+
try {
|
|
2570
|
+
const parsedUrl = new URL(publicBaseUrl);
|
|
2571
|
+
const parsedPort = Number(parsedUrl.port);
|
|
2572
|
+
if (Number.isInteger(parsedPort) && parsedPort > 0) return parsedPort;
|
|
2573
|
+
} catch {}
|
|
2574
|
+
return fallbackPort;
|
|
2500
2575
|
}
|
|
2501
2576
|
};
|
|
2502
2577
|
|
|
@@ -2522,13 +2597,13 @@ var DevSessionPortsResolver = class {
|
|
|
2522
2597
|
* Bundles dependencies for {@link DevCommand} so the command stays a thin orchestrator.
|
|
2523
2598
|
*/
|
|
2524
2599
|
var DevSessionServices = class {
|
|
2525
|
-
constructor(consumerEnvLoader, sourceMapNodeOptions, sessionPorts, loopbackPortAllocator, devHttpProbe,
|
|
2600
|
+
constructor(consumerEnvLoader, sourceMapNodeOptions, sessionPorts, loopbackPortAllocator, devHttpProbe, nextHostEdgeSeedLoader, nextHostEnvBuilder, watchRootsResolver, sourceChangeClassifier) {
|
|
2526
2601
|
this.consumerEnvLoader = consumerEnvLoader;
|
|
2527
2602
|
this.sourceMapNodeOptions = sourceMapNodeOptions;
|
|
2528
2603
|
this.sessionPorts = sessionPorts;
|
|
2529
2604
|
this.loopbackPortAllocator = loopbackPortAllocator;
|
|
2530
2605
|
this.devHttpProbe = devHttpProbe;
|
|
2531
|
-
this.
|
|
2606
|
+
this.nextHostEdgeSeedLoader = nextHostEdgeSeedLoader;
|
|
2532
2607
|
this.nextHostEnvBuilder = nextHostEnvBuilder;
|
|
2533
2608
|
this.watchRootsResolver = watchRootsResolver;
|
|
2534
2609
|
this.sourceChangeClassifier = sourceChangeClassifier;
|
|
@@ -2538,15 +2613,16 @@ var DevSessionServices = class {
|
|
|
2538
2613
|
//#endregion
|
|
2539
2614
|
//#region src/dev/DevSourceChangeClassifier.ts
|
|
2540
2615
|
var DevSourceChangeClassifier = class DevSourceChangeClassifier {
|
|
2541
|
-
static
|
|
2616
|
+
static uiConfigFileNames = new Set([
|
|
2542
2617
|
"codemation.config.ts",
|
|
2543
2618
|
"codemation.config.js",
|
|
2544
2619
|
"codemation.config.mjs"
|
|
2545
2620
|
]);
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2621
|
+
static pluginConfigFileNames = new Set([
|
|
2622
|
+
"codemation.plugin.ts",
|
|
2623
|
+
"codemation.plugin.js",
|
|
2624
|
+
"codemation.plugin.mjs"
|
|
2625
|
+
]);
|
|
2550
2626
|
requiresUiRestart(args) {
|
|
2551
2627
|
const resolvedConsumerRoot = path.resolve(args.consumerRoot);
|
|
2552
2628
|
return args.changedPaths.some((changedPath) => this.pathRequiresUiRestart(path.resolve(changedPath), resolvedConsumerRoot));
|
|
@@ -2559,7 +2635,9 @@ var DevSourceChangeClassifier = class DevSourceChangeClassifier {
|
|
|
2559
2635
|
pathRequiresUiRestart(resolvedPath, consumerRoot) {
|
|
2560
2636
|
if (!this.isPathInsideDirectory(resolvedPath, consumerRoot)) return false;
|
|
2561
2637
|
const relativePath = path.relative(consumerRoot, resolvedPath);
|
|
2562
|
-
|
|
2638
|
+
const fileName = path.basename(relativePath);
|
|
2639
|
+
if (DevSourceChangeClassifier.uiConfigFileNames.has(fileName)) return true;
|
|
2640
|
+
if (DevSourceChangeClassifier.pluginConfigFileNames.has(fileName)) return false;
|
|
2563
2641
|
if (relativePath.startsWith(path.join("src", "workflows"))) return false;
|
|
2564
2642
|
if (relativePath.startsWith(path.join("src", "plugins"))) return false;
|
|
2565
2643
|
if (relativePath.includes("credential")) return true;
|
|
@@ -2588,6 +2666,36 @@ var LoopbackPortAllocator = class {
|
|
|
2588
2666
|
}
|
|
2589
2667
|
};
|
|
2590
2668
|
|
|
2669
|
+
//#endregion
|
|
2670
|
+
//#region src/dev/NextHostEdgeSeedLoader.ts
|
|
2671
|
+
var NextHostEdgeSeedLoader = class NextHostEdgeSeedLoader {
|
|
2672
|
+
static defaultDevelopmentAuthSecret = "codemation-dev-auth-secret-not-for-production";
|
|
2673
|
+
constructor(configLoader, consumerEnvLoader) {
|
|
2674
|
+
this.configLoader = configLoader;
|
|
2675
|
+
this.consumerEnvLoader = consumerEnvLoader;
|
|
2676
|
+
}
|
|
2677
|
+
resolveDevelopmentServerToken(rawToken) {
|
|
2678
|
+
if (rawToken && rawToken.trim().length > 0) return rawToken;
|
|
2679
|
+
return randomUUID();
|
|
2680
|
+
}
|
|
2681
|
+
async loadForConsumer(consumerRoot, options) {
|
|
2682
|
+
const resolution = await this.configLoader.load({
|
|
2683
|
+
consumerRoot,
|
|
2684
|
+
configPathOverride: options?.configPathOverride
|
|
2685
|
+
});
|
|
2686
|
+
const envForAuthSecret = this.consumerEnvLoader.mergeConsumerRootIntoProcessEnvironment(consumerRoot, process.env);
|
|
2687
|
+
return {
|
|
2688
|
+
authSecret: this.resolveDevelopmentAuthSecret(envForAuthSecret),
|
|
2689
|
+
uiAuthEnabled: resolution.config.auth?.allowUnauthenticatedInDevelopment !== true
|
|
2690
|
+
};
|
|
2691
|
+
}
|
|
2692
|
+
resolveDevelopmentAuthSecret(env) {
|
|
2693
|
+
const configuredSecret = env.AUTH_SECRET;
|
|
2694
|
+
if (configuredSecret && configuredSecret.trim().length > 0) return configuredSecret;
|
|
2695
|
+
return NextHostEdgeSeedLoader.defaultDevelopmentAuthSecret;
|
|
2696
|
+
}
|
|
2697
|
+
};
|
|
2698
|
+
|
|
2591
2699
|
//#endregion
|
|
2592
2700
|
//#region src/dev/WatchRootsResolver.ts
|
|
2593
2701
|
var WatchRootsResolver = class {
|
|
@@ -2614,7 +2722,57 @@ var DevSessionServicesBuilder = class {
|
|
|
2614
2722
|
const sourceMapNodeOptions = new SourceMapNodeOptions();
|
|
2615
2723
|
const listenPortResolver = new ListenPortResolver();
|
|
2616
2724
|
const loopbackPortAllocator = new LoopbackPortAllocator();
|
|
2617
|
-
return new DevSessionServices(consumerEnvLoader, sourceMapNodeOptions, new DevSessionPortsResolver(listenPortResolver, loopbackPortAllocator), loopbackPortAllocator, new DevHttpProbe(), new
|
|
2725
|
+
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());
|
|
2726
|
+
}
|
|
2727
|
+
};
|
|
2728
|
+
|
|
2729
|
+
//#endregion
|
|
2730
|
+
//#region src/dev/PluginDevConfigFactory.ts
|
|
2731
|
+
var PluginDevConfigFactory = class {
|
|
2732
|
+
async prepare(pluginRoot) {
|
|
2733
|
+
const pluginEntryPath = await this.resolvePluginEntryPath(pluginRoot);
|
|
2734
|
+
const configPath = path.resolve(pluginRoot, ".codemation", "plugin-dev", "codemation.config.ts");
|
|
2735
|
+
await mkdir(path.dirname(configPath), { recursive: true });
|
|
2736
|
+
await writeFile(configPath, this.createConfigSource(configPath, pluginEntryPath), "utf8");
|
|
2737
|
+
return { configPath };
|
|
2738
|
+
}
|
|
2739
|
+
async resolvePluginEntryPath(pluginRoot) {
|
|
2740
|
+
const candidates = [
|
|
2741
|
+
path.resolve(pluginRoot, "codemation.plugin.ts"),
|
|
2742
|
+
path.resolve(pluginRoot, "codemation.plugin.js"),
|
|
2743
|
+
path.resolve(pluginRoot, "src", "codemation.plugin.ts"),
|
|
2744
|
+
path.resolve(pluginRoot, "src", "codemation.plugin.js")
|
|
2745
|
+
];
|
|
2746
|
+
for (const candidate of candidates) if (await this.exists(candidate)) return candidate;
|
|
2747
|
+
throw new Error("Plugin config not found. Expected \"codemation.plugin.ts\" in the plugin root or \"src/\".");
|
|
2748
|
+
}
|
|
2749
|
+
createConfigSource(configPath, pluginEntryPath) {
|
|
2750
|
+
const relativeImportPath = this.toRelativeImportPath(configPath, pluginEntryPath);
|
|
2751
|
+
return [
|
|
2752
|
+
"import type { CodemationConfig } from \"@codemation/host\";",
|
|
2753
|
+
`import plugin from ${JSON.stringify(relativeImportPath)};`,
|
|
2754
|
+
"",
|
|
2755
|
+
"const sandbox = plugin.sandbox ?? {};",
|
|
2756
|
+
"const config: CodemationConfig = {",
|
|
2757
|
+
" ...sandbox,",
|
|
2758
|
+
" plugins: [...(sandbox.plugins ?? []), plugin],",
|
|
2759
|
+
"};",
|
|
2760
|
+
"",
|
|
2761
|
+
"export default config;",
|
|
2762
|
+
""
|
|
2763
|
+
].join("\n");
|
|
2764
|
+
}
|
|
2765
|
+
toRelativeImportPath(fromPath, targetPath) {
|
|
2766
|
+
const relativePath = path.relative(path.dirname(fromPath), targetPath).replace(/\\/g, "/");
|
|
2767
|
+
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
2768
|
+
}
|
|
2769
|
+
async exists(filePath) {
|
|
2770
|
+
try {
|
|
2771
|
+
await access(filePath);
|
|
2772
|
+
return true;
|
|
2773
|
+
} catch {
|
|
2774
|
+
return false;
|
|
2775
|
+
}
|
|
2618
2776
|
}
|
|
2619
2777
|
};
|
|
2620
2778
|
|
|
@@ -2870,10 +3028,11 @@ var DevSourceWatcherFactory = class {
|
|
|
2870
3028
|
//#endregion
|
|
2871
3029
|
//#region src/Program.ts
|
|
2872
3030
|
var CliProgram = class {
|
|
2873
|
-
constructor(buildOptionsParser, buildCommand, devCommand, serveWebCommand, serveWorkerCommand, dbMigrateCommand, userCreateCommand, userListCommand) {
|
|
3031
|
+
constructor(buildOptionsParser, buildCommand, devCommand, devPluginCommand, serveWebCommand, serveWorkerCommand, dbMigrateCommand, userCreateCommand, userListCommand) {
|
|
2874
3032
|
this.buildOptionsParser = buildOptionsParser;
|
|
2875
3033
|
this.buildCommand = buildCommand;
|
|
2876
3034
|
this.devCommand = devCommand;
|
|
3035
|
+
this.devPluginCommand = devPluginCommand;
|
|
2877
3036
|
this.serveWebCommand = serveWebCommand;
|
|
2878
3037
|
this.serveWorkerCommand = serveWorkerCommand;
|
|
2879
3038
|
this.dbMigrateCommand = dbMigrateCommand;
|
|
@@ -2893,6 +3052,9 @@ var CliProgram = class {
|
|
|
2893
3052
|
watchFramework: opts.watchFramework === true
|
|
2894
3053
|
});
|
|
2895
3054
|
});
|
|
3055
|
+
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) => {
|
|
3056
|
+
await this.devPluginCommand.execute({ pluginRoot: resolveConsumerRoot(opts.pluginRoot) });
|
|
3057
|
+
});
|
|
2896
3058
|
const serve$1 = program.command("serve").description("Run production web or worker processes (no dev watchers).");
|
|
2897
3059
|
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
3060
|
await this.serveWebCommand.execute(resolveConsumerRoot(opts.consumerRoot), this.buildOptionsParser.parse(opts));
|
|
@@ -3160,9 +3322,7 @@ var CliProgramFactory = class {
|
|
|
3160
3322
|
const appConfigLoader = new AppConfigLoader();
|
|
3161
3323
|
const pathResolver = new CliPathResolver();
|
|
3162
3324
|
const pluginDiscovery = new CodemationPluginDiscovery();
|
|
3163
|
-
const artifactsPublisher = new ConsumerBuildArtifactsPublisher();
|
|
3164
3325
|
const tsRuntime = new TypeScriptRuntimeConfigurator();
|
|
3165
|
-
const outputBuilderLoader = new ConsumerOutputBuilderLoader();
|
|
3166
3326
|
const sourceMapNodeOptions = new SourceMapNodeOptions();
|
|
3167
3327
|
const nextHostConsumerServerCommandFactory = new NextHostConsumerServerCommandFactory();
|
|
3168
3328
|
const devSessionServices = new DevSessionServicesBuilder().build();
|
|
@@ -3172,8 +3332,10 @@ var CliProgramFactory = class {
|
|
|
3172
3332
|
const userAdminCliOptionsParser = new UserAdminCliOptionsParser();
|
|
3173
3333
|
const databaseMigrationsApplyService = new DatabaseMigrationsApplyService(cliLogger, new UserAdminConsumerDotenvLoader(), tsconfigPreparation, new CodemationConsumerConfigLoader(), new ConsumerDatabaseConnectionResolver(), new CliDatabaseUrlDescriptor(), hostPackageRoot, new PrismaMigrationDeployer());
|
|
3174
3334
|
const buildOptionsParser = new ConsumerBuildOptionsParser();
|
|
3175
|
-
const
|
|
3176
|
-
|
|
3335
|
+
const consumerOutputBuilderFactory = new ConsumerOutputBuilderFactory();
|
|
3336
|
+
const consumerBuildArtifactsPublisher = new ConsumerBuildArtifactsPublisher();
|
|
3337
|
+
const devCommand = new DevCommand(pathResolver, tsRuntime, new DevLockFactory(), new DevSourceWatcherFactory(), cliLogger, devSessionServices, databaseMigrationsApplyService, consumerOutputBuilderFactory, pluginDiscovery, consumerBuildArtifactsPublisher, new DevBootstrapSummaryFetcher(), new DevCliBannerRenderer(), new ConsumerEnvDotenvFilePredicate(), new DevTrackedProcessTreeKiller(), nextHostConsumerServerCommandFactory, new DevApiRuntimeFactory(devSessionServices.loopbackPortAllocator, appConfigLoader, pluginDiscovery), new CliDevProxyServerFactory(), new DevRebuildQueueFactory());
|
|
3338
|
+
return new CliProgram(buildOptionsParser, new BuildCommand(cliLogger, pathResolver, consumerOutputBuilderFactory, pluginDiscovery, consumerBuildArtifactsPublisher, 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
3339
|
}
|
|
3178
3340
|
};
|
|
3179
3341
|
|