@lark-apaas/coding-template-nestjs-react-fullstack 0.1.27-alpha.20260824122815 → 0.1.27

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.
@@ -1,445 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import fs from 'node:fs';
4
- import net from 'node:net';
5
- import path from 'node:path';
6
- import { spawn } from 'node:child_process';
7
- import { fileURLToPath } from 'node:url';
8
-
9
- const projectRoot = path.resolve(
10
- process.env.MIAODA_WORKSPACE_ROOT || process.cwd()
11
- );
12
-
13
- // The bundle orchestrator may be started directly by the image before the
14
- // project npm task exists. Load the same project .env contract as dev.js so the
15
- // later source service receives identical application configuration.
16
- const projectEnvFile = path.join(projectRoot, '.env');
17
- if (fs.existsSync(projectEnvFile)) {
18
- for (const line of fs.readFileSync(projectEnvFile, 'utf8').split('\n')) {
19
- const trimmed = line.trim();
20
- if (!trimmed || trimmed.startsWith('#')) continue;
21
- const separator = trimmed.indexOf('=');
22
- if (separator < 1) continue;
23
- const key = trimmed.slice(0, separator).trim();
24
- const value = trimmed.slice(separator + 1).trim();
25
- if (!(key in process.env)) process.env[key] = value;
26
- }
27
- }
28
- const scriptsRoot = path.dirname(fileURLToPath(import.meta.url));
29
- const swcRuntimeConfigRelativePath = path.join(
30
- '.miaoda-runtime',
31
- 'nest-cli.swc.json'
32
- );
33
- const workspaceReadyFile = path.resolve(
34
- process.env.MIAODA_WORKSPACE_READY_FILE || '/tmp/event/WORKSPACE_READY'
35
- );
36
- const actionPluginReadyFile = path.resolve(
37
- process.env.MIAODA_ACTION_PLUGIN_READY_FILE ||
38
- '/tmp/event/MIAODA_ACTION_PLUGIN_READY.json'
39
- );
40
- const bundleFallbackFile = path.resolve(
41
- process.env.MIAODA_NEST_BUNDLE_FALLBACK_FILE ||
42
- '/tmp/event/MIAODA_NEST_BUNDLE_FALLBACK'
43
- );
44
- const serverHost = process.env.SERVER_HOST || '0.0.0.0';
45
- const serverPort = Number(process.env.SERVER_PORT || 3000);
46
- const requestedMode = process.env.MIAODA_NEST_START_MODE || 'workspace';
47
- const skipActionPluginInit =
48
- process.env.MIAODA_NEST_SKIP_ACTION_PLUGIN_INIT === 'true';
49
- const expectedRestoreEpochMs =
50
- process.env.MIAODA_PLATFORM_ENV_NOT_BEFORE_MS || '';
51
- const supportedModes = new Set([
52
- 'bundle-handoff',
53
- 'workspace',
54
- 'swc',
55
- ]);
56
- const runtimeStartedAtEpochMs = Date.now();
57
- const startedAt = process.hrtime.bigint();
58
- let stopping = false;
59
- let serviceChild;
60
- let compilerChild;
61
-
62
- if (!supportedModes.has(requestedMode)) {
63
- throw new Error(`MIAODA_NEST_START_MODE_INVALID: ${requestedMode}`);
64
- }
65
- if (
66
- !Number.isSafeInteger(serverPort) ||
67
- serverPort <= 0 ||
68
- serverPort > 65_535
69
- ) {
70
- throw new Error('MIAODA_NEST_SERVER_PORT_INVALID');
71
- }
72
-
73
- function durationMs(since = startedAt) {
74
- return Number(process.hrtime.bigint() - since) / 1_000_000;
75
- }
76
-
77
- function emit(phase, since, details = {}) {
78
- const atEpochMs = Date.now();
79
- const phaseDurationMs = Number(durationMs(since).toFixed(3));
80
- process.stdout.write(
81
- `${JSON.stringify({
82
- event: 'miaoda_workspace_runtime_phase',
83
- runtime: 'nest',
84
- mode: requestedMode,
85
- phase,
86
- atEpochMs,
87
- phaseStartedAtEpochMs: Number((atEpochMs - phaseDurationMs).toFixed(3)),
88
- runtimeStartedAtEpochMs,
89
- durationMs: phaseDurationMs,
90
- ...details,
91
- })}\n`
92
- );
93
- }
94
-
95
- function delay(ms) {
96
- return new Promise(resolve => setTimeout(resolve, ms));
97
- }
98
-
99
- function markBundleFallback(reason) {
100
- fs.mkdirSync(path.dirname(bundleFallbackFile), { recursive: true });
101
- const temporaryFile = `${bundleFallbackFile}.${process.pid}.tmp`;
102
- fs.writeFileSync(
103
- temporaryFile,
104
- `${JSON.stringify({ schemaVersion: 1, reason, at: new Date().toISOString() })}\n`,
105
- { mode: 0o600 }
106
- );
107
- fs.renameSync(temporaryFile, bundleFallbackFile);
108
- }
109
-
110
- function childRunning(child) {
111
- return Boolean(
112
- child?.pid && child.exitCode === null && child.signalCode === null
113
- );
114
- }
115
-
116
- function terminate(child, signal = 'SIGTERM') {
117
- if (!child?.pid) return;
118
- try {
119
- process.kill(-child.pid, signal);
120
- } catch {
121
- try {
122
- child.kill(signal);
123
- } catch {}
124
- }
125
- }
126
-
127
- function workspaceDependenciesReady() {
128
- try {
129
- return (
130
- fs.statSync(workspaceReadyFile).isFile() &&
131
- fs.statSync(path.join(projectRoot, 'node_modules')).isDirectory()
132
- );
133
- } catch {
134
- return false;
135
- }
136
- }
137
-
138
- async function waitForDependencies() {
139
- const waitStartedAt = process.hrtime.bigint();
140
- while (!stopping && !workspaceDependenciesReady()) await delay(100);
141
- if (stopping) throw new Error('MIAODA_NEST_STARTUP_STOPPING');
142
- emit('dependency_wait', waitStartedAt, { workspaceReadyFile });
143
- }
144
-
145
- function actionPluginPreconditionReady() {
146
- try {
147
- const marker = JSON.parse(fs.readFileSync(actionPluginReadyFile, 'utf8'));
148
- return (
149
- marker?.schemaVersion === 1 &&
150
- (!expectedRestoreEpochMs ||
151
- String(marker.restoreEpochMs || '') === expectedRestoreEpochMs)
152
- );
153
- } catch {
154
- return false;
155
- }
156
- }
157
-
158
- async function waitForActionPluginPrecondition() {
159
- const waitStartedAt = process.hrtime.bigint();
160
- while (!stopping && !actionPluginPreconditionReady()) await delay(100);
161
- if (stopping) throw new Error('MIAODA_NEST_STARTUP_STOPPING');
162
- emit('action_plugin_wait', waitStartedAt, {
163
- actionPluginReadyFile,
164
- ownership: 'shared-parent',
165
- });
166
- }
167
-
168
- function probeHost(host) {
169
- if (!host || host === '0.0.0.0') return '127.0.0.1';
170
- if (host === '::' || host === '[::]') return '::1';
171
- return host.replace(/^\[|\]$/g, '');
172
- }
173
-
174
- async function waitForPort(child = serviceChild) {
175
- const listenStartedAt = process.hrtime.bigint();
176
- const deadline = Date.now() + 60_000;
177
- const host = probeHost(serverHost);
178
- while (!stopping && Date.now() < deadline) {
179
- if (child && !childRunning(child)) {
180
- throw new Error('MIAODA_NEST_PROCESS_EXITED_BEFORE_READY');
181
- }
182
- const connected = await new Promise(resolve => {
183
- const socket = net.createConnection({ host, port: serverPort });
184
- socket.once('connect', () => {
185
- socket.destroy();
186
- resolve(true);
187
- });
188
- socket.once('error', () => resolve(false));
189
- });
190
- if (connected) {
191
- emit('listen_ready', listenStartedAt, {
192
- host: serverHost,
193
- port: serverPort,
194
- });
195
- return;
196
- }
197
- await delay(100);
198
- }
199
- throw new Error('MIAODA_NEST_READY_TIMEOUT');
200
- }
201
-
202
- function spawnInherited(command, args, extraEnv = {}) {
203
- return spawn(command, args, {
204
- cwd: projectRoot,
205
- detached: true,
206
- stdio: 'inherit',
207
- env: {
208
- ...process.env,
209
- ...extraEnv,
210
- MIAODA_CACHE_BOOTSTRAP_ENABLED: 'false',
211
- },
212
- });
213
- }
214
-
215
- async function runCommand(command, args, phase) {
216
- const phaseStartedAt = process.hrtime.bigint();
217
- compilerChild = spawnInherited(command, args);
218
- const result = await new Promise((resolve, reject) => {
219
- compilerChild.once('error', reject);
220
- compilerChild.once('exit', (code, signal) => resolve({ code, signal }));
221
- });
222
- compilerChild = undefined;
223
- emit(phase, phaseStartedAt, result);
224
- if (result.code !== 0) {
225
- throw new Error(
226
- `MIAODA_NEST_COMMAND_FAILED: ${command} ${args.join(' ')} code=${result.code} signal=${result.signal}`
227
- );
228
- }
229
- }
230
-
231
- async function initializeActionPlugins() {
232
- if (skipActionPluginInit) {
233
- await waitForActionPluginPrecondition();
234
- emit('action_plugin_init_skipped', process.hrtime.bigint(), {
235
- reason: 'shared-parent-initialized',
236
- });
237
- return;
238
- }
239
- if (actionPluginPreconditionReady()) {
240
- emit('action_plugin_init_skipped', process.hrtime.bigint(), {
241
- reason: 'shared-parent-initialized',
242
- });
243
- return;
244
- }
245
- const cli = [
246
- process.env.MIAODA_FULLSTACK_CLI_BIN,
247
- path.join(
248
- projectRoot,
249
- 'node_modules',
250
- '@lark-apaas',
251
- 'fullstack-cli',
252
- 'bin',
253
- 'cli.js'
254
- ),
255
- '/usr/lib/node_modules/@lark-apaas/fullstack-cli/bin/cli.js',
256
- ].find(candidate => candidate && fs.existsSync(candidate));
257
- if (!cli) {
258
- throw new Error('MIAODA_ACTION_PLUGIN_CLI_MISSING');
259
- }
260
- try {
261
- await runCommand(
262
- process.execPath,
263
- [cli, 'action-plugin', 'init'],
264
- 'action_plugin_init'
265
- );
266
- } catch (error) {
267
- // Match the original dev.js contract: plugin discovery failure is visible
268
- // in logs but does not replace the Nest process with a platform failure.
269
- process.stderr.write(
270
- `${JSON.stringify({
271
- event: 'miaoda_action_plugin_init_failed',
272
- continueStartup: true,
273
- error: error instanceof Error ? error.message : String(error),
274
- })}\n`
275
- );
276
- }
277
- }
278
-
279
- function spawnWorkspaceService() {
280
- const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
281
- return spawnInherited(npmCommand, ['run', 'dev:server'], {
282
- NODE_ENV: 'development',
283
- MIAODA_NEST_CLI_INSTRUMENTATION: 'true',
284
- });
285
- }
286
-
287
- function prepareSwcRuntimeConfig() {
288
- const sourceConfigPath = path.join(projectRoot, 'nest-cli.json');
289
- const runtimeConfigPath = path.join(
290
- projectRoot,
291
- swcRuntimeConfigRelativePath
292
- );
293
- const configuration = JSON.parse(fs.readFileSync(sourceConfigPath, 'utf8'));
294
- const compilerOptions = configuration.compilerOptions || {};
295
- const configuredBuilder = compilerOptions.builder;
296
- const configuredSwcOptions =
297
- configuredBuilder &&
298
- typeof configuredBuilder === 'object' &&
299
- configuredBuilder.type === 'swc'
300
- ? configuredBuilder.options || {}
301
- : {};
302
- configuration.compilerOptions = {
303
- ...compilerOptions,
304
- builder: {
305
- type: 'swc',
306
- options: {
307
- ...configuredSwcOptions,
308
- extensions: ['.ts'],
309
- },
310
- },
311
- };
312
- fs.mkdirSync(path.dirname(runtimeConfigPath), { recursive: true });
313
- const temporaryPath = `${runtimeConfigPath}.${process.pid}.tmp`;
314
- fs.writeFileSync(
315
- temporaryPath,
316
- `${JSON.stringify(configuration, null, 2)}\n`
317
- );
318
- fs.renameSync(temporaryPath, runtimeConfigPath);
319
- return swcRuntimeConfigRelativePath;
320
- }
321
-
322
- function spawnSwcService() {
323
- const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
324
- const runtimeConfig = prepareSwcRuntimeConfig();
325
- return spawnInherited(
326
- npmCommand,
327
- ['run', 'dev:server', '--', '--config', runtimeConfig],
328
- {
329
- NODE_ENV: 'development',
330
- MIAODA_NEST_CLI_INSTRUMENTATION: 'true',
331
- }
332
- );
333
- }
334
-
335
- async function waitForServiceLifetime() {
336
- if (!serviceChild) return { code: 1, signal: null };
337
- return new Promise((resolve, reject) => {
338
- serviceChild.once('error', reject);
339
- serviceChild.once('exit', (code, signal) => resolve({ code, signal }));
340
- });
341
- }
342
-
343
- async function runDependencyBackedMode(mode) {
344
- await waitForDependencies();
345
- await initializeActionPlugins();
346
- if (mode === 'workspace') {
347
- const spawnStartedAt = process.hrtime.bigint();
348
- serviceChild = spawnWorkspaceService();
349
- emit('process_spawn', spawnStartedAt, { pid: serviceChild.pid });
350
- } else if (mode === 'swc') {
351
- const spawnStartedAt = process.hrtime.bigint();
352
- serviceChild = spawnSwcService();
353
- emit('process_spawn', spawnStartedAt, {
354
- pid: serviceChild.pid,
355
- builder: 'swc',
356
- config: swcRuntimeConfigRelativePath,
357
- sourceExtensions: ['.ts'],
358
- });
359
- } else {
360
- throw new Error(`MIAODA_NEST_DEPENDENCY_MODE_INVALID: ${mode}`);
361
- }
362
- await waitForPort();
363
- emit('startup', startedAt, { pid: serviceChild.pid, port: serverPort });
364
- return waitForServiceLifetime();
365
- }
366
-
367
- async function runBundleHandoff() {
368
- const dependenciesReadyAtEntry = workspaceDependenciesReady();
369
- // Once dependencies exist, never put the stale bundle back in front during
370
- // a supervisor retry. This preserves the original Preview failure/retry UI
371
- // when the complete workspace service fails after the transition window.
372
- if (dependenciesReadyAtEntry) {
373
- emit('bundle_skipped', process.hrtime.bigint(), {
374
- reason: 'workspace-dependencies-ready',
375
- });
376
- return runDependencyBackedMode('workspace');
377
- }
378
- const runtime = path.join(scriptsRoot, 'server-cache-runtime.mjs');
379
- if (!fs.existsSync(runtime)) {
380
- markBundleFallback('runtime-missing');
381
- process.stderr.write(
382
- `${JSON.stringify({
383
- event: 'miaoda_nest_bundle_unavailable',
384
- reason: 'runtime-missing',
385
- })}\n`
386
- );
387
- return runDependencyBackedMode('workspace');
388
- }
389
- const spawnStartedAt = process.hrtime.bigint();
390
- serviceChild = spawnInherited(process.execPath, [runtime], {
391
- MIAODA_NEST_SKIP_ACTION_PLUGIN_INIT: 'true',
392
- });
393
- emit('process_spawn', spawnStartedAt, {
394
- pid: serviceChild.pid,
395
- childRuntime: 'server-cache-runtime',
396
- });
397
- const exitPromise = new Promise((resolve, reject) => {
398
- serviceChild.once('error', reject);
399
- serviceChild.once('exit', (code, signal) => resolve({ code, signal }));
400
- });
401
- try {
402
- await Promise.race([
403
- waitForPort(),
404
- exitPromise.then(exit => {
405
- throw new Error(
406
- `MIAODA_NEST_BUNDLE_EXITED_BEFORE_READY: code=${exit.code} signal=${exit.signal}`
407
- );
408
- }),
409
- ]);
410
- emit('startup', startedAt, { pid: serviceChild.pid, port: serverPort });
411
- return exitPromise;
412
- } catch (error) {
413
- const reason = error instanceof Error ? error.message : String(error);
414
- markBundleFallback(reason);
415
- process.stderr.write(
416
- `${JSON.stringify({
417
- event: 'miaoda_nest_bundle_fallback',
418
- reason,
419
- })}\n`
420
- );
421
- terminate(serviceChild);
422
- return runDependencyBackedMode('workspace');
423
- }
424
- }
425
-
426
- async function close(signal) {
427
- if (stopping) return;
428
- stopping = true;
429
- terminate(compilerChild, signal);
430
- terminate(serviceChild, signal);
431
- setTimeout(() => {
432
- terminate(compilerChild, 'SIGKILL');
433
- terminate(serviceChild, 'SIGKILL');
434
- }, 1_000).unref();
435
- }
436
-
437
- for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP']) {
438
- process.once(signal, () => void close(signal));
439
- }
440
-
441
- const exit =
442
- requestedMode === 'bundle-handoff'
443
- ? await runBundleHandoff()
444
- : await runDependencyBackedMode(requestedMode);
445
- process.exit(exit?.code ?? (stopping ? 0 : 1));