@chidchanun/bcp 0.1.22 → 0.1.24
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 +241 -640
- package/docs/README.md +114 -337
- package/docs/auth-route-guards.md +14 -0
- package/docs/developer-tools.md +83 -12
- package/docs/development-logging.md +234 -6
- package/docs/file-upload.md +280 -0
- package/docs/releases/0.1.22.md +66 -1
- package/docs/releases/0.1.23.md +131 -0
- package/docs/releases/0.1.24.md +166 -0
- package/package.json +3 -2
- package/packages/bundler/src/server-production-actions.ts +15 -0
- package/packages/bundler/src/server-production-guards.ts +15 -0
- package/packages/cli/bin/bcp.mjs +111 -0
- package/packages/client/src/form.tsx +20 -13
- package/packages/client/src/server.ts +31 -0
- package/packages/server/src/dev-hmr.ts +131 -9
- package/packages/server/src/dev-route-graph.ts +91 -0
- package/packages/server/src/logger.ts +474 -0
- package/packages/server/src/middleware-dev-server.ts +217 -9
- package/packages/server/src/upload.ts +556 -0
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import * as net from "node:net";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
|
+
import chokidar from "chokidar";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
scanRoutes,
|
|
8
|
+
} from "../../router/src/index.js";
|
|
9
|
+
|
|
4
10
|
import type {
|
|
5
11
|
DevServerOptions,
|
|
6
12
|
} from "./index.js";
|
|
@@ -9,6 +15,10 @@ import {
|
|
|
9
15
|
createCriticalCssProxy,
|
|
10
16
|
} from "./critical-css-proxy.js";
|
|
11
17
|
|
|
18
|
+
import {
|
|
19
|
+
hasDevClientRouteGraphChanged,
|
|
20
|
+
} from "./dev-route-graph.js";
|
|
21
|
+
|
|
12
22
|
import {
|
|
13
23
|
createFormActionDevProxy,
|
|
14
24
|
} from "./form-action-dev-proxy.js";
|
|
@@ -29,6 +39,9 @@ import {
|
|
|
29
39
|
createStaticDevServer,
|
|
30
40
|
} from "./static-dev-server.js";
|
|
31
41
|
|
|
42
|
+
const ROUTE_GRAPH_DEBOUNCE_MS =
|
|
43
|
+
120;
|
|
44
|
+
|
|
32
45
|
export function createMiddlewareDevServer(
|
|
33
46
|
options: DevServerOptions = {}
|
|
34
47
|
) {
|
|
@@ -46,6 +59,15 @@ export function createMiddlewareDevServer(
|
|
|
46
59
|
process.cwd()
|
|
47
60
|
);
|
|
48
61
|
|
|
62
|
+
const appDirectory =
|
|
63
|
+
path.join(
|
|
64
|
+
rootDirectory,
|
|
65
|
+
"app"
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
let applicationPort =
|
|
69
|
+
0;
|
|
70
|
+
|
|
49
71
|
let internalServer:
|
|
50
72
|
ReturnType<
|
|
51
73
|
typeof createStaticDevServer
|
|
@@ -76,6 +98,27 @@ export function createMiddlewareDevServer(
|
|
|
76
98
|
> | null =
|
|
77
99
|
null;
|
|
78
100
|
|
|
101
|
+
let routeWatcher:
|
|
102
|
+
ReturnType<
|
|
103
|
+
typeof chokidar.watch
|
|
104
|
+
> | null =
|
|
105
|
+
null;
|
|
106
|
+
|
|
107
|
+
let routeGraph =
|
|
108
|
+
scanRoutes(
|
|
109
|
+
appDirectory
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
let routeGraphTimer:
|
|
113
|
+
NodeJS.Timeout | null =
|
|
114
|
+
null;
|
|
115
|
+
|
|
116
|
+
let routeRestartRunning =
|
|
117
|
+
false;
|
|
118
|
+
|
|
119
|
+
let routeRestartQueued =
|
|
120
|
+
false;
|
|
121
|
+
|
|
79
122
|
let started =
|
|
80
123
|
false;
|
|
81
124
|
|
|
@@ -84,7 +127,7 @@ export function createMiddlewareDevServer(
|
|
|
84
127
|
return;
|
|
85
128
|
}
|
|
86
129
|
|
|
87
|
-
|
|
130
|
+
applicationPort =
|
|
88
131
|
await findFreePort();
|
|
89
132
|
const actionPort =
|
|
90
133
|
await findFreePort();
|
|
@@ -93,15 +136,13 @@ export function createMiddlewareDevServer(
|
|
|
93
136
|
const securityPort =
|
|
94
137
|
await findFreePort();
|
|
95
138
|
|
|
139
|
+
routeGraph =
|
|
140
|
+
scanRoutes(
|
|
141
|
+
appDirectory
|
|
142
|
+
);
|
|
143
|
+
|
|
96
144
|
internalServer =
|
|
97
|
-
|
|
98
|
-
...options,
|
|
99
|
-
rootDirectory,
|
|
100
|
-
port:
|
|
101
|
-
applicationPort,
|
|
102
|
-
hostname:
|
|
103
|
-
"127.0.0.1",
|
|
104
|
-
});
|
|
145
|
+
createInternalServer();
|
|
105
146
|
|
|
106
147
|
await internalServer.start();
|
|
107
148
|
|
|
@@ -225,6 +266,8 @@ export function createMiddlewareDevServer(
|
|
|
225
266
|
throw error;
|
|
226
267
|
}
|
|
227
268
|
|
|
269
|
+
startRouteGraphWatcher();
|
|
270
|
+
|
|
228
271
|
started =
|
|
229
272
|
true;
|
|
230
273
|
|
|
@@ -244,6 +287,20 @@ export function createMiddlewareDevServer(
|
|
|
244
287
|
}
|
|
245
288
|
|
|
246
289
|
async function stop(): Promise<void> {
|
|
290
|
+
if (routeGraphTimer) {
|
|
291
|
+
clearTimeout(
|
|
292
|
+
routeGraphTimer
|
|
293
|
+
);
|
|
294
|
+
routeGraphTimer =
|
|
295
|
+
null;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (routeWatcher) {
|
|
299
|
+
await routeWatcher.close();
|
|
300
|
+
routeWatcher =
|
|
301
|
+
null;
|
|
302
|
+
}
|
|
303
|
+
|
|
247
304
|
if (criticalCssGateway) {
|
|
248
305
|
await criticalCssGateway.stop();
|
|
249
306
|
criticalCssGateway =
|
|
@@ -278,6 +335,157 @@ export function createMiddlewareDevServer(
|
|
|
278
335
|
false;
|
|
279
336
|
}
|
|
280
337
|
|
|
338
|
+
function createInternalServer() {
|
|
339
|
+
return createStaticDevServer({
|
|
340
|
+
...options,
|
|
341
|
+
rootDirectory,
|
|
342
|
+
port:
|
|
343
|
+
applicationPort,
|
|
344
|
+
hostname:
|
|
345
|
+
"127.0.0.1",
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function startRouteGraphWatcher(): void {
|
|
350
|
+
routeWatcher =
|
|
351
|
+
chokidar.watch(
|
|
352
|
+
appDirectory,
|
|
353
|
+
{
|
|
354
|
+
persistent: true,
|
|
355
|
+
ignoreInitial: true,
|
|
356
|
+
atomic: true,
|
|
357
|
+
ignored: (
|
|
358
|
+
watchedPath,
|
|
359
|
+
stats
|
|
360
|
+
) => {
|
|
361
|
+
if (
|
|
362
|
+
stats?.isDirectory()
|
|
363
|
+
) {
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (!stats) {
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
return !/\.[jt]sx?$/.test(
|
|
372
|
+
watchedPath
|
|
373
|
+
);
|
|
374
|
+
},
|
|
375
|
+
}
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
routeWatcher.on(
|
|
379
|
+
"all",
|
|
380
|
+
(
|
|
381
|
+
eventName
|
|
382
|
+
) => {
|
|
383
|
+
if (
|
|
384
|
+
eventName === "add" ||
|
|
385
|
+
eventName === "change" ||
|
|
386
|
+
eventName === "unlink"
|
|
387
|
+
) {
|
|
388
|
+
scheduleRouteGraphCheck();
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
routeWatcher.on(
|
|
394
|
+
"error",
|
|
395
|
+
(error) => {
|
|
396
|
+
console.error(
|
|
397
|
+
"[BCP Dev] Route graph watcher error:",
|
|
398
|
+
error
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function scheduleRouteGraphCheck(): void {
|
|
405
|
+
if (routeGraphTimer) {
|
|
406
|
+
clearTimeout(
|
|
407
|
+
routeGraphTimer
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
routeGraphTimer =
|
|
412
|
+
setTimeout(
|
|
413
|
+
() => {
|
|
414
|
+
routeGraphTimer =
|
|
415
|
+
null;
|
|
416
|
+
void refreshRouteGraph();
|
|
417
|
+
},
|
|
418
|
+
ROUTE_GRAPH_DEBOUNCE_MS
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
async function refreshRouteGraph(): Promise<void> {
|
|
423
|
+
if (routeRestartRunning) {
|
|
424
|
+
routeRestartQueued =
|
|
425
|
+
true;
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const nextRouteGraph =
|
|
430
|
+
scanRoutes(
|
|
431
|
+
appDirectory
|
|
432
|
+
);
|
|
433
|
+
|
|
434
|
+
if (
|
|
435
|
+
!hasDevClientRouteGraphChanged(
|
|
436
|
+
routeGraph,
|
|
437
|
+
nextRouteGraph
|
|
438
|
+
)
|
|
439
|
+
) {
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
routeRestartRunning =
|
|
444
|
+
true;
|
|
445
|
+
|
|
446
|
+
try {
|
|
447
|
+
console.log(
|
|
448
|
+
"[BCP Dev] Page route graph changed; refreshing client bundler state..."
|
|
449
|
+
);
|
|
450
|
+
|
|
451
|
+
if (internalServer) {
|
|
452
|
+
await internalServer.stop();
|
|
453
|
+
internalServer =
|
|
454
|
+
null;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const nextServer =
|
|
458
|
+
createInternalServer();
|
|
459
|
+
|
|
460
|
+
await nextServer.start();
|
|
461
|
+
|
|
462
|
+
internalServer =
|
|
463
|
+
nextServer;
|
|
464
|
+
routeGraph =
|
|
465
|
+
nextRouteGraph;
|
|
466
|
+
|
|
467
|
+
console.log(
|
|
468
|
+
`[BCP Dev] Client bundle graph synchronized (${nextRouteGraph.length} route(s)).`
|
|
469
|
+
);
|
|
470
|
+
} catch (error) {
|
|
471
|
+
internalServer =
|
|
472
|
+
null;
|
|
473
|
+
console.error(
|
|
474
|
+
"[BCP Dev] Client bundle graph refresh failed:",
|
|
475
|
+
error
|
|
476
|
+
);
|
|
477
|
+
} finally {
|
|
478
|
+
routeRestartRunning =
|
|
479
|
+
false;
|
|
480
|
+
|
|
481
|
+
if (routeRestartQueued) {
|
|
482
|
+
routeRestartQueued =
|
|
483
|
+
false;
|
|
484
|
+
scheduleRouteGraphCheck();
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
281
489
|
return {
|
|
282
490
|
start,
|
|
283
491
|
stop,
|