rollipop 1.0.0-alpha.21 → 1.0.0-alpha.22
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 +11 -0
- package/dist/commands.cjs +292 -189
- package/dist/commands.js +291 -188
- package/dist/index.d.ts +15 -8
- package/dist/index.js +293 -190
- package/package.json +3 -3
package/dist/commands.js
CHANGED
|
@@ -15,7 +15,6 @@ import { createDevMiddleware } from "@react-native/dev-middleware";
|
|
|
15
15
|
import Fastify from "fastify";
|
|
16
16
|
import mitt from "mitt";
|
|
17
17
|
import http from "node:http";
|
|
18
|
-
import EventEmitter from "node:events";
|
|
19
18
|
import * as rolldown from "@rollipop/rolldown";
|
|
20
19
|
import { dev, rollipopReactNativePlugin, rollipopReactRefreshWrapperPlugin } from "@rollipop/rolldown/experimental";
|
|
21
20
|
import crypto, { randomUUID } from "node:crypto";
|
|
@@ -40,6 +39,7 @@ import { asConst } from "json-schema-to-ts";
|
|
|
40
39
|
import mime from "mime";
|
|
41
40
|
import Ajv from "ajv";
|
|
42
41
|
import { codeFrameColumns } from "@babel/code-frame";
|
|
42
|
+
import EventEmitter from "node:events";
|
|
43
43
|
import * as ws from "ws";
|
|
44
44
|
import * as c12 from "c12";
|
|
45
45
|
//#region \0rolldown/runtime.js
|
|
@@ -785,30 +785,14 @@ function getGlobalVariables(dev, buildType) {
|
|
|
785
785
|
}
|
|
786
786
|
//#endregion
|
|
787
787
|
//#region src/utils/config.ts
|
|
788
|
-
function bindReporter(config,
|
|
789
|
-
const
|
|
790
|
-
config.reporter = { update(event) {
|
|
791
|
-
switch (event.type) {
|
|
792
|
-
case "bundle_build_started":
|
|
793
|
-
eventSource.emit("buildStart");
|
|
794
|
-
break;
|
|
795
|
-
case "bundle_build_done":
|
|
796
|
-
eventSource.emit("buildDone");
|
|
797
|
-
break;
|
|
798
|
-
case "bundle_build_failed":
|
|
799
|
-
eventSource.emit("buildFailed", event.error);
|
|
800
|
-
break;
|
|
801
|
-
case "transform":
|
|
802
|
-
eventSource.emit("transform", event.id, event.totalModules, event.transformedModules);
|
|
803
|
-
break;
|
|
804
|
-
case "watch_change":
|
|
805
|
-
eventSource.emit("watchChange", event.id);
|
|
806
|
-
break;
|
|
807
|
-
}
|
|
808
|
-
originalReporter?.update(event);
|
|
788
|
+
function bindReporter(config, onEvent) {
|
|
789
|
+
const reporter = { update(event) {
|
|
809
790
|
onEvent?.(event);
|
|
810
791
|
} };
|
|
811
|
-
return
|
|
792
|
+
return {
|
|
793
|
+
...config,
|
|
794
|
+
reporter
|
|
795
|
+
};
|
|
812
796
|
}
|
|
813
797
|
function resolveHmrConfig(config) {
|
|
814
798
|
if (config.mode !== "development") return null;
|
|
@@ -1147,6 +1131,8 @@ var ProgressBarStatusReporter = class {
|
|
|
1147
1131
|
update(event) {
|
|
1148
1132
|
switch (event.type) {
|
|
1149
1133
|
case "bundle_build_started":
|
|
1134
|
+
this.progressBar.setCurrent(0);
|
|
1135
|
+
if (this.flags & ProgressFlags.FILE_CHANGED) this.progressBar.setTotal(0);
|
|
1150
1136
|
this.flags |= ProgressFlags.BUILD_IN_PROGRESS;
|
|
1151
1137
|
this.progressBar.start();
|
|
1152
1138
|
this.renderManager.start();
|
|
@@ -1163,10 +1149,6 @@ var ProgressBarStatusReporter = class {
|
|
|
1163
1149
|
break;
|
|
1164
1150
|
case "transform":
|
|
1165
1151
|
const { id, totalModules, transformedModules } = event;
|
|
1166
|
-
if (this.flags & ProgressFlags.FILE_CHANGED) {
|
|
1167
|
-
logger.debug("Transformed changed file", { id });
|
|
1168
|
-
return;
|
|
1169
|
-
}
|
|
1170
1152
|
this.renderProgress(id, totalModules, transformedModules);
|
|
1171
1153
|
break;
|
|
1172
1154
|
case "watch_change":
|
|
@@ -1852,21 +1834,45 @@ function reporterPlugin(options) {
|
|
|
1852
1834
|
let totalModules = initialTotalModules;
|
|
1853
1835
|
let startedAt = 0;
|
|
1854
1836
|
let transformedModules = 0;
|
|
1837
|
+
let cacheHitModules = 0;
|
|
1855
1838
|
let unknownTotalModules = totalModules === 0;
|
|
1839
|
+
let rebuildPending = false;
|
|
1840
|
+
function getProcessedModules() {
|
|
1841
|
+
return transformedModules + cacheHitModules;
|
|
1842
|
+
}
|
|
1843
|
+
function reportProgress(id) {
|
|
1844
|
+
const processedModules = getProcessedModules();
|
|
1845
|
+
if (!unknownTotalModules && totalModules < processedModules) totalModules = processedModules;
|
|
1846
|
+
reporter?.update({
|
|
1847
|
+
type: "transform",
|
|
1848
|
+
id,
|
|
1849
|
+
totalModules: unknownTotalModules ? void 0 : totalModules,
|
|
1850
|
+
transformedModules: processedModules
|
|
1851
|
+
});
|
|
1852
|
+
}
|
|
1856
1853
|
return {
|
|
1857
1854
|
name: "rollipop:status",
|
|
1858
1855
|
buildStart() {
|
|
1859
1856
|
startedAt = performance.now();
|
|
1860
1857
|
transformedModules = 0;
|
|
1858
|
+
cacheHitModules = 0;
|
|
1859
|
+
if (rebuildPending) {
|
|
1860
|
+
totalModules = 0;
|
|
1861
|
+
unknownTotalModules = false;
|
|
1862
|
+
rebuildPending = false;
|
|
1863
|
+
}
|
|
1861
1864
|
reporter?.update({ type: "bundle_build_started" });
|
|
1862
1865
|
},
|
|
1863
1866
|
buildEnd(error) {
|
|
1864
1867
|
const endedAt = performance.now();
|
|
1865
|
-
|
|
1868
|
+
const processedModules = getProcessedModules();
|
|
1869
|
+
if (processedModules !== 0) totalModules = processedModules;
|
|
1866
1870
|
unknownTotalModules = false;
|
|
1867
1871
|
reporter?.update(error == null ? {
|
|
1868
1872
|
type: "bundle_build_done",
|
|
1869
1873
|
totalModules,
|
|
1874
|
+
transformedModules,
|
|
1875
|
+
cacheHitModules,
|
|
1870
1876
|
duration: endedAt - startedAt
|
|
1871
1877
|
} : {
|
|
1872
1878
|
type: "bundle_build_failed",
|
|
@@ -1877,16 +1883,15 @@ function reporterPlugin(options) {
|
|
|
1877
1883
|
order: "post",
|
|
1878
1884
|
handler(_code, id) {
|
|
1879
1885
|
++transformedModules;
|
|
1880
|
-
|
|
1881
|
-
reporter?.update({
|
|
1882
|
-
type: "transform",
|
|
1883
|
-
id,
|
|
1884
|
-
totalModules: unknownTotalModules ? void 0 : totalModules,
|
|
1885
|
-
transformedModules
|
|
1886
|
-
});
|
|
1886
|
+
reportProgress(id);
|
|
1887
1887
|
}
|
|
1888
1888
|
},
|
|
1889
|
+
transformCacheHit(id) {
|
|
1890
|
+
++cacheHitModules;
|
|
1891
|
+
reportProgress(id);
|
|
1892
|
+
},
|
|
1889
1893
|
watchChange(id) {
|
|
1894
|
+
rebuildPending = true;
|
|
1890
1895
|
reporter?.update({
|
|
1891
1896
|
type: "watch_change",
|
|
1892
1897
|
id
|
|
@@ -2301,7 +2306,7 @@ var FileSystemBundleStore = class {
|
|
|
2301
2306
|
};
|
|
2302
2307
|
//#endregion
|
|
2303
2308
|
//#region src/server/bundler-pool.ts
|
|
2304
|
-
var BundlerDevEngine = class
|
|
2309
|
+
var BundlerDevEngine = class {
|
|
2305
2310
|
initializeHandle;
|
|
2306
2311
|
isHmrEnabled;
|
|
2307
2312
|
_id;
|
|
@@ -2310,24 +2315,14 @@ var BundlerDevEngine = class extends EventEmitter {
|
|
|
2310
2315
|
_devEngine = null;
|
|
2311
2316
|
_state = "idle";
|
|
2312
2317
|
_status = "idle";
|
|
2313
|
-
constructor(options, config, buildOptions,
|
|
2314
|
-
super();
|
|
2318
|
+
constructor(options, config, buildOptions, eventBus) {
|
|
2315
2319
|
this.options = options;
|
|
2316
2320
|
this.config = config;
|
|
2317
2321
|
this.buildOptions = buildOptions;
|
|
2318
|
-
this.
|
|
2322
|
+
this.eventBus = eventBus;
|
|
2319
2323
|
this._id = Bundler.createId(config, buildOptions);
|
|
2320
2324
|
this.initializeHandle = taskHandler();
|
|
2321
2325
|
this.isHmrEnabled = Boolean(buildOptions.dev && config.devMode.hmr);
|
|
2322
|
-
this.on("buildStart", () => {
|
|
2323
|
-
this._status = "building";
|
|
2324
|
-
});
|
|
2325
|
-
this.on("buildDone", () => {
|
|
2326
|
-
this._status = "build-done";
|
|
2327
|
-
});
|
|
2328
|
-
this.on("buildFailed", () => {
|
|
2329
|
-
this._status = "build-failed";
|
|
2330
|
-
});
|
|
2331
2326
|
this.initialize();
|
|
2332
2327
|
}
|
|
2333
2328
|
get id() {
|
|
@@ -2347,8 +2342,24 @@ var BundlerDevEngine = class extends EventEmitter {
|
|
|
2347
2342
|
async initialize() {
|
|
2348
2343
|
if (this._state !== "idle" || this._devEngine != null) return this;
|
|
2349
2344
|
this._state = "initializing";
|
|
2350
|
-
const
|
|
2351
|
-
|
|
2345
|
+
const config = bindReporter(this.config, (event) => {
|
|
2346
|
+
switch (event.type) {
|
|
2347
|
+
case "bundle_build_started":
|
|
2348
|
+
this._status = "building";
|
|
2349
|
+
break;
|
|
2350
|
+
case "bundle_build_done":
|
|
2351
|
+
this._status = "build-done";
|
|
2352
|
+
break;
|
|
2353
|
+
case "bundle_build_failed":
|
|
2354
|
+
this._status = "build-failed";
|
|
2355
|
+
break;
|
|
2356
|
+
}
|
|
2357
|
+
this.eventBus.emit({
|
|
2358
|
+
...event,
|
|
2359
|
+
bundlerId: this.id
|
|
2360
|
+
});
|
|
2361
|
+
});
|
|
2362
|
+
const devEngine = await Bundler.devEngine(config, this.buildOptions, {
|
|
2352
2363
|
host: this.options.server.host,
|
|
2353
2364
|
port: this.options.server.port,
|
|
2354
2365
|
onHmrUpdates: (errorOrResult) => {
|
|
@@ -2358,17 +2369,25 @@ var BundlerDevEngine = class extends EventEmitter {
|
|
|
2358
2369
|
bundlerId: this.id,
|
|
2359
2370
|
error: errorOrResult
|
|
2360
2371
|
});
|
|
2361
|
-
const
|
|
2362
|
-
this.config.reporter?.update({
|
|
2372
|
+
const event = {
|
|
2363
2373
|
type: "bundle_build_failed",
|
|
2364
|
-
error:
|
|
2374
|
+
error: normalizeRolldownError(errorOrResult)
|
|
2375
|
+
};
|
|
2376
|
+
this._status = "build-failed";
|
|
2377
|
+
this.eventBus.emit({
|
|
2378
|
+
...event,
|
|
2379
|
+
bundlerId: this.id
|
|
2365
2380
|
});
|
|
2366
2381
|
} else {
|
|
2367
2382
|
logger$1.trace("Detected changed files", {
|
|
2368
2383
|
bundlerId: this.id,
|
|
2369
2384
|
changedFiles: errorOrResult.changedFiles
|
|
2370
2385
|
});
|
|
2371
|
-
this.emit(
|
|
2386
|
+
this.eventBus.emit({
|
|
2387
|
+
bundlerId: this.id,
|
|
2388
|
+
type: "hmr_updates",
|
|
2389
|
+
updates: errorOrResult.updates
|
|
2390
|
+
});
|
|
2372
2391
|
}
|
|
2373
2392
|
},
|
|
2374
2393
|
onOutput: (errorOrResult) => {
|
|
@@ -2377,7 +2396,15 @@ var BundlerDevEngine = class extends EventEmitter {
|
|
|
2377
2396
|
logger$1.trace("onOutput", { bundlerId: this.id });
|
|
2378
2397
|
logger$1.error(errorOrResult.message);
|
|
2379
2398
|
this.buildFailedError = normalizedError;
|
|
2380
|
-
|
|
2399
|
+
const event = {
|
|
2400
|
+
type: "bundle_build_failed",
|
|
2401
|
+
error: normalizedError
|
|
2402
|
+
};
|
|
2403
|
+
this._status = "build-failed";
|
|
2404
|
+
this.eventBus.emit({
|
|
2405
|
+
...event,
|
|
2406
|
+
bundlerId: this.id
|
|
2407
|
+
});
|
|
2381
2408
|
} else {
|
|
2382
2409
|
const output = errorOrResult.output[0];
|
|
2383
2410
|
this.updateBundleStore(output);
|
|
@@ -2413,16 +2440,13 @@ var BundlerDevEngine = class extends EventEmitter {
|
|
|
2413
2440
|
};
|
|
2414
2441
|
var BundlerPool = class BundlerPool {
|
|
2415
2442
|
static instances = /* @__PURE__ */ new Map();
|
|
2416
|
-
constructor(config, resolvedServerOptions,
|
|
2443
|
+
constructor(config, resolvedServerOptions, eventBus) {
|
|
2417
2444
|
this.config = config;
|
|
2418
2445
|
this.resolvedServerOptions = resolvedServerOptions;
|
|
2419
|
-
this.
|
|
2420
|
-
}
|
|
2421
|
-
instanceKey(bundleName, buildOptions) {
|
|
2422
|
-
return `${bundleName}-${Bundler.createId(this.config, buildOptions)}`;
|
|
2446
|
+
this.eventBus = eventBus;
|
|
2423
2447
|
}
|
|
2424
2448
|
get(bundleName, buildOptions) {
|
|
2425
|
-
const key =
|
|
2449
|
+
const key = `${getBaseBundleName(bundleName)}-${Bundler.createId(this.config, buildOptions)}`;
|
|
2426
2450
|
const instance = BundlerPool.instances.get(key);
|
|
2427
2451
|
if (instance) return instance;
|
|
2428
2452
|
else {
|
|
@@ -2430,16 +2454,14 @@ var BundlerPool = class BundlerPool {
|
|
|
2430
2454
|
bundleName,
|
|
2431
2455
|
key
|
|
2432
2456
|
});
|
|
2433
|
-
const instance = new BundlerDevEngine({ server: this.resolvedServerOptions }, this.config, buildOptions, this.
|
|
2457
|
+
const instance = new BundlerDevEngine({ server: this.resolvedServerOptions }, this.config, buildOptions, this.eventBus);
|
|
2434
2458
|
logger$1.debug("Setting new bundler instance", { key });
|
|
2435
2459
|
BundlerPool.instances.set(key, instance);
|
|
2436
2460
|
return instance;
|
|
2437
2461
|
}
|
|
2438
2462
|
}
|
|
2439
2463
|
/**
|
|
2440
|
-
* Look up a cached bundler by
|
|
2441
|
-
* in SSE events such as `bundle_build_done`). Returns `undefined` when no
|
|
2442
|
-
* instance with that id has been created yet.
|
|
2464
|
+
* Look up a cached bundler by the id carried as `bundlerId` in events such as `bundle_build_done`. Returns `undefined` when no instance with that id has been created yet.
|
|
2443
2465
|
*/
|
|
2444
2466
|
getInstanceById(id) {
|
|
2445
2467
|
for (const instance of BundlerPool.instances.values()) if (instance.id === id) return instance;
|
|
@@ -2458,6 +2480,21 @@ function errorHandler(error, request, reply) {
|
|
|
2458
2480
|
reply.status(500).send("Internal Server Error");
|
|
2459
2481
|
}
|
|
2460
2482
|
//#endregion
|
|
2483
|
+
//#region src/server/events/event-bus.ts
|
|
2484
|
+
var EventBus = class {
|
|
2485
|
+
listeners = /* @__PURE__ */ new Set();
|
|
2486
|
+
emit(event) {
|
|
2487
|
+
for (const listener of this.listeners) listener(event);
|
|
2488
|
+
}
|
|
2489
|
+
subscribe(listener) {
|
|
2490
|
+
this.listeners.add(listener);
|
|
2491
|
+
return () => {
|
|
2492
|
+
this.listeners.delete(listener);
|
|
2493
|
+
};
|
|
2494
|
+
}
|
|
2495
|
+
};
|
|
2496
|
+
var ServerEventBus = class extends EventBus {};
|
|
2497
|
+
//#endregion
|
|
2461
2498
|
//#region src/utils/reset-cache.ts
|
|
2462
2499
|
/**
|
|
2463
2500
|
* Resolve the build cache directory for the given project root. The cache
|
|
@@ -2480,6 +2517,67 @@ function resetCache(projectRoot) {
|
|
|
2480
2517
|
});
|
|
2481
2518
|
}
|
|
2482
2519
|
//#endregion
|
|
2520
|
+
//#region src/server/sse/adapter.ts
|
|
2521
|
+
function toSSEEvent(event) {
|
|
2522
|
+
switch (event.type) {
|
|
2523
|
+
case "client_log": return {
|
|
2524
|
+
type: "client_log",
|
|
2525
|
+
...event.bundlerId != null ? { bundlerId: event.bundlerId } : {},
|
|
2526
|
+
data: event.data
|
|
2527
|
+
};
|
|
2528
|
+
case "device_connected": return {
|
|
2529
|
+
type: "device_connected",
|
|
2530
|
+
clientId: event.client.id
|
|
2531
|
+
};
|
|
2532
|
+
case "device_disconnected": return {
|
|
2533
|
+
type: "device_disconnected",
|
|
2534
|
+
clientId: event.client.id
|
|
2535
|
+
};
|
|
2536
|
+
case "server_ready":
|
|
2537
|
+
case "cache_reset": return event;
|
|
2538
|
+
case "bundle_build_started":
|
|
2539
|
+
case "bundle_build_done":
|
|
2540
|
+
case "bundle_build_failed":
|
|
2541
|
+
case "watch_change": return reporterEventToSSEEvent(event);
|
|
2542
|
+
case "hmr_updates":
|
|
2543
|
+
case "device_message":
|
|
2544
|
+
case "device_error":
|
|
2545
|
+
case "transform": return null;
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
function reporterEventToSSEEvent(event) {
|
|
2549
|
+
switch (event.type) {
|
|
2550
|
+
case "bundle_build_started": return {
|
|
2551
|
+
type: "bundle_build_started",
|
|
2552
|
+
bundlerId: event.bundlerId
|
|
2553
|
+
};
|
|
2554
|
+
case "bundle_build_done": return {
|
|
2555
|
+
type: "bundle_build_done",
|
|
2556
|
+
bundlerId: event.bundlerId,
|
|
2557
|
+
totalModules: event.totalModules,
|
|
2558
|
+
transformedModules: event.transformedModules,
|
|
2559
|
+
cacheHitModules: event.cacheHitModules,
|
|
2560
|
+
duration: event.duration
|
|
2561
|
+
};
|
|
2562
|
+
case "bundle_build_failed": return {
|
|
2563
|
+
type: "bundle_build_failed",
|
|
2564
|
+
bundlerId: event.bundlerId,
|
|
2565
|
+
error: stripAnsi(event.error.message)
|
|
2566
|
+
};
|
|
2567
|
+
case "watch_change": return {
|
|
2568
|
+
type: "watch_change",
|
|
2569
|
+
bundlerId: event.bundlerId,
|
|
2570
|
+
file: event.id
|
|
2571
|
+
};
|
|
2572
|
+
case "client_log": return {
|
|
2573
|
+
type: "client_log",
|
|
2574
|
+
bundlerId: event.bundlerId,
|
|
2575
|
+
data: event.data
|
|
2576
|
+
};
|
|
2577
|
+
case "transform": return null;
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
//#endregion
|
|
2483
2581
|
//#region src/server/mcp/server.ts
|
|
2484
2582
|
function createMcpServer(options) {
|
|
2485
2583
|
const { projectRoot, eventBus } = options;
|
|
@@ -2500,11 +2598,14 @@ function createMcpServer(options) {
|
|
|
2500
2598
|
});
|
|
2501
2599
|
server.registerTool("get_build_events", {
|
|
2502
2600
|
title: "Get Build Events",
|
|
2503
|
-
description: "Subscribe to bundler events for a duration. Returns all events (build start/done/fail, watch changes, client logs, device connections) collected during the wait period.",
|
|
2601
|
+
description: "Subscribe to bundler events for a duration. Returns all events (build start/done/fail, watch changes, client logs, device connections) collected during the wait period. Bundler-scoped events include bundlerId.",
|
|
2504
2602
|
inputSchema: { duration: z.number().min(1e3).max(6e4).default(1e4).describe("How long to listen for events in milliseconds (1000-60000, default 10000)") }
|
|
2505
2603
|
}, async ({ duration }) => {
|
|
2506
2604
|
const events = [];
|
|
2507
|
-
const unsubscribe = eventBus.
|
|
2605
|
+
const unsubscribe = eventBus.subscribe((event) => {
|
|
2606
|
+
const sseEvent = toSSEEvent(event);
|
|
2607
|
+
if (sseEvent != null) events.push(sseEvent);
|
|
2608
|
+
});
|
|
2508
2609
|
await new Promise((resolve) => setTimeout(resolve, duration));
|
|
2509
2610
|
unsubscribe();
|
|
2510
2611
|
if (events.length === 0) return { content: [{
|
|
@@ -2761,6 +2862,11 @@ const bundleRequestSchema = asConst({
|
|
|
2761
2862
|
});
|
|
2762
2863
|
new Ajv().compile(bundleRequestSchema);
|
|
2763
2864
|
//#endregion
|
|
2865
|
+
//#region src/server/events/types.ts
|
|
2866
|
+
function isBundlerEventForId(event, bundlerId) {
|
|
2867
|
+
return "bundlerId" in event && event.bundlerId === bundlerId;
|
|
2868
|
+
}
|
|
2869
|
+
//#endregion
|
|
2764
2870
|
//#region src/server/middlewares/serve-bundle.ts
|
|
2765
2871
|
const routeParamSchema = asConst({
|
|
2766
2872
|
type: "object",
|
|
@@ -2772,7 +2878,7 @@ function withGetBundleErrorHandler(reply, task) {
|
|
|
2772
2878
|
});
|
|
2773
2879
|
}
|
|
2774
2880
|
const plugin$2 = fp((fastify, options) => {
|
|
2775
|
-
const { getBundler } = options;
|
|
2881
|
+
const { eventBus, getBundler } = options;
|
|
2776
2882
|
const getBundleOptions = (buildOptions) => {
|
|
2777
2883
|
return {
|
|
2778
2884
|
platform: buildOptions.platform,
|
|
@@ -2796,11 +2902,10 @@ const plugin$2 = fp((fastify, options) => {
|
|
|
2796
2902
|
const bundler = getBundler(params.name, buildOptions);
|
|
2797
2903
|
if (accept?.includes("multipart/mixed") ?? false) {
|
|
2798
2904
|
const bundleResponse = new BundleResponse(reply);
|
|
2799
|
-
const
|
|
2800
|
-
bundleResponse.writeBundleState(transformedModules, totalModules);
|
|
2801
|
-
};
|
|
2802
|
-
bundler.
|
|
2803
|
-
await bundler.getBundle().then((bundle) => bundleResponse.endWithBundle(bundle.code)).catch((error) => bundleResponse.endWithError(error)).finally(() => bundler.off("transform", transformHandler));
|
|
2905
|
+
const unsubscribe = eventBus.subscribe((event) => {
|
|
2906
|
+
if (isBundlerEventForId(event, bundler.id) && event.type === "transform") bundleResponse.writeBundleState(event.transformedModules, event.totalModules ?? 0);
|
|
2907
|
+
});
|
|
2908
|
+
await bundler.getBundle().then((bundle) => bundleResponse.endWithBundle(bundle.code)).catch((error) => bundleResponse.endWithError(error)).finally(unsubscribe);
|
|
2804
2909
|
} else {
|
|
2805
2910
|
this.log.debug(`client is not support multipart/mixed content: ${accept ?? "<empty>"}`);
|
|
2806
2911
|
const code = (await withGetBundleErrorHandler(reply, bundler.getBundle())).code;
|
|
@@ -2828,7 +2933,7 @@ const plugin$2 = fp((fastify, options) => {
|
|
|
2828
2933
|
}, { name: "serve-bundle" });
|
|
2829
2934
|
//#endregion
|
|
2830
2935
|
//#region src/server/middlewares/sse.ts
|
|
2831
|
-
const plugin$1 = fp((fastify, {
|
|
2936
|
+
const plugin$1 = fp((fastify, { publisher }) => {
|
|
2832
2937
|
fastify.get("/sse/events", (request, reply) => {
|
|
2833
2938
|
const res = reply.raw;
|
|
2834
2939
|
res.writeHead(200, {
|
|
@@ -2839,8 +2944,8 @@ const plugin$1 = fp((fastify, { eventBus }) => {
|
|
|
2839
2944
|
});
|
|
2840
2945
|
request.raw.socket.setNoDelay(true);
|
|
2841
2946
|
res.write(":ok\n\n");
|
|
2842
|
-
|
|
2843
|
-
request.raw.on("close", () =>
|
|
2947
|
+
publisher.addClient(res);
|
|
2948
|
+
request.raw.on("close", () => publisher.removeClient(res));
|
|
2844
2949
|
});
|
|
2845
2950
|
}, { name: "sse" });
|
|
2846
2951
|
//#endregion
|
|
@@ -3016,14 +3121,12 @@ function printSymbolicateResult(rawStackFrame, symbolicateResult) {
|
|
|
3016
3121
|
}
|
|
3017
3122
|
//#endregion
|
|
3018
3123
|
//#region src/server/sse/event-bus.ts
|
|
3019
|
-
var
|
|
3124
|
+
var SSEEventPublisher = class {
|
|
3020
3125
|
clients = /* @__PURE__ */ new Set();
|
|
3021
|
-
|
|
3022
|
-
emit(event) {
|
|
3126
|
+
publish(event) {
|
|
3023
3127
|
const data = JSON.stringify(event);
|
|
3024
3128
|
const message = `event: ${event.type}\ndata: ${data}\n\n`;
|
|
3025
3129
|
for (const client of this.clients) if (!client.closed) client.write(message);
|
|
3026
|
-
for (const listener of this.listeners) listener(event);
|
|
3027
3130
|
}
|
|
3028
3131
|
/**
|
|
3029
3132
|
* Subscribe an SSE HTTP response client.
|
|
@@ -3037,51 +3140,11 @@ var SSEEventBus = class {
|
|
|
3037
3140
|
removeClient(res) {
|
|
3038
3141
|
this.clients.delete(res);
|
|
3039
3142
|
}
|
|
3040
|
-
/**
|
|
3041
|
-
* Subscribe a listener that collects events into the given array.
|
|
3042
|
-
* Returns an unsubscribe function.
|
|
3043
|
-
*/
|
|
3044
|
-
collect(collector) {
|
|
3045
|
-
const listener = (event) => collector.push(event);
|
|
3046
|
-
this.listeners.add(listener);
|
|
3047
|
-
return () => this.listeners.delete(listener);
|
|
3048
|
-
}
|
|
3049
3143
|
get clientCount() {
|
|
3050
3144
|
return this.clients.size;
|
|
3051
3145
|
}
|
|
3052
3146
|
};
|
|
3053
3147
|
//#endregion
|
|
3054
|
-
//#region src/server/sse/reporter.ts
|
|
3055
|
-
function toSSEEvent(id, event) {
|
|
3056
|
-
switch (event.type) {
|
|
3057
|
-
case "bundle_build_started": return {
|
|
3058
|
-
type: "bundle_build_started",
|
|
3059
|
-
id
|
|
3060
|
-
};
|
|
3061
|
-
case "bundle_build_done": return {
|
|
3062
|
-
type: "bundle_build_done",
|
|
3063
|
-
id,
|
|
3064
|
-
totalModules: event.totalModules,
|
|
3065
|
-
duration: event.duration
|
|
3066
|
-
};
|
|
3067
|
-
case "bundle_build_failed": return {
|
|
3068
|
-
type: "bundle_build_failed",
|
|
3069
|
-
id,
|
|
3070
|
-
error: stripAnsi(event.error.message)
|
|
3071
|
-
};
|
|
3072
|
-
case "watch_change": return {
|
|
3073
|
-
type: "watch_change",
|
|
3074
|
-
id,
|
|
3075
|
-
file: event.id
|
|
3076
|
-
};
|
|
3077
|
-
case "client_log": return {
|
|
3078
|
-
type: "client_log",
|
|
3079
|
-
data: event.data
|
|
3080
|
-
};
|
|
3081
|
-
case "transform": return null;
|
|
3082
|
-
}
|
|
3083
|
-
}
|
|
3084
|
-
//#endregion
|
|
3085
3148
|
//#region src/server/wss/server.ts
|
|
3086
3149
|
var WebSocketServer = class extends EventEmitter {
|
|
3087
3150
|
clientId = 0;
|
|
@@ -3150,13 +3213,13 @@ function getWebSocketUpgradeHandler(websocketEndpoints) {
|
|
|
3150
3213
|
//#region src/server/wss/hmr-server.ts
|
|
3151
3214
|
var HMRServer = class extends WebSocketServer {
|
|
3152
3215
|
bundlerPool;
|
|
3153
|
-
|
|
3216
|
+
eventBus;
|
|
3154
3217
|
instances = /* @__PURE__ */ new Map();
|
|
3155
3218
|
bindings = /* @__PURE__ */ new Map();
|
|
3156
|
-
constructor({ bundlerPool,
|
|
3219
|
+
constructor({ bundlerPool, eventBus }) {
|
|
3157
3220
|
super("hmr", { noServer: true });
|
|
3158
3221
|
this.bundlerPool = bundlerPool;
|
|
3159
|
-
this.
|
|
3222
|
+
this.eventBus = eventBus;
|
|
3160
3223
|
}
|
|
3161
3224
|
parseClientMessage(data) {
|
|
3162
3225
|
const parsedData = JSON.parse(this.rawDataToString(data));
|
|
@@ -3183,33 +3246,34 @@ var HMRServer = class extends WebSocketServer {
|
|
|
3183
3246
|
}
|
|
3184
3247
|
bindEvents(client, instance) {
|
|
3185
3248
|
if (this.bindings.get(client.id) == null) {
|
|
3186
|
-
const
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
}
|
|
3200
|
-
}));
|
|
3201
|
-
};
|
|
3202
|
-
instance.addListener("hmrUpdates", handleHmrUpdates);
|
|
3203
|
-
instance.addListener("watchChange", handleWatchChange);
|
|
3204
|
-
instance.addListener("buildFailed", handleBuildFailed);
|
|
3205
|
-
this.bindings.set(client.id, {
|
|
3206
|
-
hmrUpdates: handleHmrUpdates,
|
|
3207
|
-
watchChange: handleWatchChange,
|
|
3208
|
-
buildFailed: handleBuildFailed
|
|
3249
|
+
const unsubscribe = this.eventBus.subscribe((event) => {
|
|
3250
|
+
if (!isBundlerEventForId(event, instance.id)) return;
|
|
3251
|
+
switch (event.type) {
|
|
3252
|
+
case "hmr_updates":
|
|
3253
|
+
this.handleUpdates(client, event.updates);
|
|
3254
|
+
break;
|
|
3255
|
+
case "watch_change":
|
|
3256
|
+
this.send(client, JSON.stringify({ type: "hmr:update-start" }));
|
|
3257
|
+
break;
|
|
3258
|
+
case "bundle_build_failed":
|
|
3259
|
+
this.sendBuildFailed(client, event.error);
|
|
3260
|
+
break;
|
|
3261
|
+
}
|
|
3209
3262
|
});
|
|
3263
|
+
this.bindings.set(client.id, { unsubscribe });
|
|
3210
3264
|
this.logger.trace(`HMR event binding established (clientId: ${client.id})`);
|
|
3211
3265
|
}
|
|
3212
3266
|
}
|
|
3267
|
+
sendBuildFailed(client, error) {
|
|
3268
|
+
this.send(client, JSON.stringify({
|
|
3269
|
+
type: "hmr:error",
|
|
3270
|
+
payload: {
|
|
3271
|
+
type: "BuildError",
|
|
3272
|
+
errors: [{ description: error.message }],
|
|
3273
|
+
message: error.message
|
|
3274
|
+
}
|
|
3275
|
+
}));
|
|
3276
|
+
}
|
|
3213
3277
|
async handleModuleRegistered(client, modules) {
|
|
3214
3278
|
try {
|
|
3215
3279
|
const instance = this.instances.get(client.id);
|
|
@@ -3276,11 +3340,7 @@ var HMRServer = class extends WebSocketServer {
|
|
|
3276
3340
|
this.logger.trace(`HMR client cleanup (clientId: ${client.id})`);
|
|
3277
3341
|
const binding = this.bindings.get(client.id);
|
|
3278
3342
|
const instance = this.instances.get(client.id);
|
|
3279
|
-
if (binding != null
|
|
3280
|
-
instance.removeListener("hmrUpdates", binding.hmrUpdates);
|
|
3281
|
-
instance.removeListener("watchChange", binding.watchChange);
|
|
3282
|
-
instance.removeListener("buildFailed", binding.buildFailed);
|
|
3283
|
-
}
|
|
3343
|
+
if (binding != null) binding.unsubscribe();
|
|
3284
3344
|
if (instance != null) try {
|
|
3285
3345
|
instance.devEngine.removeClient(String(client.id));
|
|
3286
3346
|
} catch (error) {
|
|
@@ -3327,13 +3387,16 @@ var HMRServer = class extends WebSocketServer {
|
|
|
3327
3387
|
case "hmr:invalidate":
|
|
3328
3388
|
this.handleInvalidate(client, message.moduleId);
|
|
3329
3389
|
break;
|
|
3330
|
-
case "hmr:log":
|
|
3331
|
-
this.
|
|
3390
|
+
case "hmr:log": {
|
|
3391
|
+
const instance = this.instances.get(client.id);
|
|
3392
|
+
this.eventBus.emit({
|
|
3332
3393
|
type: "client_log",
|
|
3394
|
+
...instance != null ? { bundlerId: instance.id } : {},
|
|
3333
3395
|
level: message.level,
|
|
3334
3396
|
data: message.data
|
|
3335
3397
|
});
|
|
3336
3398
|
break;
|
|
3399
|
+
}
|
|
3337
3400
|
}
|
|
3338
3401
|
}
|
|
3339
3402
|
onConnection(client) {
|
|
@@ -3374,22 +3437,58 @@ async function createDevServer(config, options) {
|
|
|
3374
3437
|
loggerInstance: new DevServerLogger(),
|
|
3375
3438
|
disableRequestLogging: true
|
|
3376
3439
|
});
|
|
3377
|
-
const
|
|
3378
|
-
const
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
if (sseEvent) sseEventBus.emit(sseEvent);
|
|
3440
|
+
const eventBus = new ServerEventBus();
|
|
3441
|
+
const ssePublisher = new SSEEventPublisher();
|
|
3442
|
+
const reporter = config.reporter;
|
|
3443
|
+
eventBus.subscribe((event) => {
|
|
3444
|
+
const sseEvent = toSSEEvent(event);
|
|
3445
|
+
if (sseEvent != null) ssePublisher.publish(sseEvent);
|
|
3384
3446
|
});
|
|
3385
|
-
const getBundler = (bundleName, buildOptions) => {
|
|
3386
|
-
return bundlerPool.get(bundleName, merge(options?.buildOptions ?? {}, buildOptions));
|
|
3387
|
-
};
|
|
3388
3447
|
const { middleware: communityMiddleware, websocketEndpoints: communityWebsocketEndpoints, messageSocketEndpoint: { server: messageServer, broadcast }, eventsSocketEndpoint: { server: eventsServer, reportEvent } } = createDevServerMiddleware({
|
|
3389
3448
|
port,
|
|
3390
3449
|
host,
|
|
3391
3450
|
watchFolders: []
|
|
3392
3451
|
});
|
|
3452
|
+
eventBus.subscribe((event) => {
|
|
3453
|
+
switch (event.type) {
|
|
3454
|
+
case "bundle_build_started":
|
|
3455
|
+
case "bundle_build_done":
|
|
3456
|
+
case "bundle_build_failed":
|
|
3457
|
+
case "transform":
|
|
3458
|
+
case "watch_change":
|
|
3459
|
+
reporter?.update(event);
|
|
3460
|
+
break;
|
|
3461
|
+
case "client_log":
|
|
3462
|
+
reportEvent?.(event);
|
|
3463
|
+
reporter?.update(event);
|
|
3464
|
+
break;
|
|
3465
|
+
case "device_connected":
|
|
3466
|
+
emitter.emit("device.connected", { client: event.client });
|
|
3467
|
+
break;
|
|
3468
|
+
case "device_message":
|
|
3469
|
+
emitter.emit("device.message", {
|
|
3470
|
+
client: event.client,
|
|
3471
|
+
data: event.data
|
|
3472
|
+
});
|
|
3473
|
+
break;
|
|
3474
|
+
case "device_error":
|
|
3475
|
+
emitter.emit("device.error", {
|
|
3476
|
+
client: event.client,
|
|
3477
|
+
error: event.error
|
|
3478
|
+
});
|
|
3479
|
+
break;
|
|
3480
|
+
case "device_disconnected":
|
|
3481
|
+
emitter.emit("device.disconnected", { client: event.client });
|
|
3482
|
+
break;
|
|
3483
|
+
}
|
|
3484
|
+
});
|
|
3485
|
+
const bundlerPool = new BundlerPool(config, {
|
|
3486
|
+
host,
|
|
3487
|
+
port
|
|
3488
|
+
}, eventBus);
|
|
3489
|
+
const getBundler = (bundleName, buildOptions) => {
|
|
3490
|
+
return bundlerPool.get(bundleName, merge(options?.buildOptions ?? {}, buildOptions));
|
|
3491
|
+
};
|
|
3393
3492
|
const { middleware: devMiddleware, websocketEndpoints } = createDevMiddleware({
|
|
3394
3493
|
serverBaseUrl,
|
|
3395
3494
|
logger: {
|
|
@@ -3407,29 +3506,22 @@ async function createDevServer(config, options) {
|
|
|
3407
3506
|
});
|
|
3408
3507
|
const hmrServer = new HMRServer({
|
|
3409
3508
|
bundlerPool,
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
}).on("
|
|
3415
|
-
|
|
3416
|
-
sseEventBus.emit({
|
|
3417
|
-
type: "device_connected",
|
|
3418
|
-
clientId: client.id
|
|
3419
|
-
});
|
|
3420
|
-
}).on("message", (client, data) => emitter.emit("device.message", {
|
|
3509
|
+
eventBus
|
|
3510
|
+
}).on("connection", (client) => eventBus.emit({
|
|
3511
|
+
type: "device_connected",
|
|
3512
|
+
client
|
|
3513
|
+
})).on("message", (client, data) => eventBus.emit({
|
|
3514
|
+
type: "device_message",
|
|
3421
3515
|
client,
|
|
3422
3516
|
data
|
|
3423
|
-
})).on("error", (client, error) =>
|
|
3517
|
+
})).on("error", (client, error) => eventBus.emit({
|
|
3518
|
+
type: "device_error",
|
|
3424
3519
|
client,
|
|
3425
3520
|
error
|
|
3426
|
-
})).on("close", (client) => {
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
clientId: client.id
|
|
3431
|
-
});
|
|
3432
|
-
});
|
|
3521
|
+
})).on("close", (client) => eventBus.emit({
|
|
3522
|
+
type: "device_disconnected",
|
|
3523
|
+
client
|
|
3524
|
+
}));
|
|
3433
3525
|
await fastify.register(import("@fastify/middie"));
|
|
3434
3526
|
const devServer = {
|
|
3435
3527
|
...emitter,
|
|
@@ -3454,13 +3546,16 @@ async function createDevServer(config, options) {
|
|
|
3454
3546
|
})
|
|
3455
3547
|
};
|
|
3456
3548
|
const { invokePostConfigureServer } = await invokeConfigureServer(devServer, config.plugins ?? []);
|
|
3457
|
-
fastify.use(requestLogger).use(communityMiddleware).use(devMiddleware).register(plugin$1, {
|
|
3549
|
+
fastify.use(requestLogger).use(communityMiddleware).use(devMiddleware).register(plugin$1, { publisher: ssePublisher }).register(plugin$4, {
|
|
3458
3550
|
projectRoot,
|
|
3459
|
-
eventBus
|
|
3551
|
+
eventBus
|
|
3460
3552
|
}).register(plugin$5, { bundlerPool }).register(plugin$6, {
|
|
3461
3553
|
projectRoot,
|
|
3462
|
-
eventBus
|
|
3463
|
-
}).register(plugin, { getBundler }).register(plugin$2, {
|
|
3554
|
+
eventBus
|
|
3555
|
+
}).register(plugin, { getBundler }).register(plugin$2, {
|
|
3556
|
+
eventBus,
|
|
3557
|
+
getBundler
|
|
3558
|
+
}).register(plugin$3, {
|
|
3464
3559
|
projectRoot,
|
|
3465
3560
|
host,
|
|
3466
3561
|
port,
|
|
@@ -3473,7 +3568,7 @@ async function createDevServer(config, options) {
|
|
|
3473
3568
|
"/hot": hmrServer.server
|
|
3474
3569
|
}));
|
|
3475
3570
|
await invokePostConfigureServer();
|
|
3476
|
-
|
|
3571
|
+
eventBus.emit({
|
|
3477
3572
|
type: "server_ready",
|
|
3478
3573
|
host,
|
|
3479
3574
|
port
|
|
@@ -3522,6 +3617,7 @@ function getAgentGuide(baseUrl = defaultBaseUrl) {
|
|
|
3522
3617
|
" Event format:",
|
|
3523
3618
|
" event: <event_type>",
|
|
3524
3619
|
" data: <json_payload>",
|
|
3620
|
+
" bundler-scoped events include bundlerId",
|
|
3525
3621
|
"",
|
|
3526
3622
|
" Useful event types:",
|
|
3527
3623
|
" bundle_build_started, bundle_build_done, bundle_build_failed",
|
|
@@ -3650,6 +3746,7 @@ function mergeConfig(baseConfig, ...overrideConfigs) {
|
|
|
3650
3746
|
//#endregion
|
|
3651
3747
|
//#region src/config/load-config.ts
|
|
3652
3748
|
const CONFIG_FILE_NAME = "rollipop";
|
|
3749
|
+
const INTERNAL_PLUGIN_HOOKS = ["transformCacheHit"];
|
|
3653
3750
|
async function loadConfig(options = {}) {
|
|
3654
3751
|
const { cwd = process.cwd(), configFile, mode, context = {} } = options;
|
|
3655
3752
|
const defaultConfig = await getDefaultConfig(cwd, mode);
|
|
@@ -3684,7 +3781,12 @@ async function flattenPluginOption(pluginOption) {
|
|
|
3684
3781
|
const awaitedPluginOption = await pluginOption;
|
|
3685
3782
|
if (Array.isArray(awaitedPluginOption)) return (await Promise.all(awaitedPluginOption.map(flattenPluginOption))).flat();
|
|
3686
3783
|
if (awaitedPluginOption == null || awaitedPluginOption === false) return [];
|
|
3687
|
-
return [awaitedPluginOption];
|
|
3784
|
+
return [stripInternalPluginHooks(awaitedPluginOption)];
|
|
3785
|
+
}
|
|
3786
|
+
function stripInternalPluginHooks(plugin) {
|
|
3787
|
+
const maybeInternalPlugin = plugin;
|
|
3788
|
+
if (!INTERNAL_PLUGIN_HOOKS.some((hook) => hook in maybeInternalPlugin)) return plugin;
|
|
3789
|
+
return omit(maybeInternalPlugin, INTERNAL_PLUGIN_HOOKS);
|
|
3688
3790
|
}
|
|
3689
3791
|
async function resolvePluginConfig(baseConfig, plugins) {
|
|
3690
3792
|
let mergedConfig = omit(baseConfig, ["plugins"]);
|
|
@@ -3854,6 +3956,7 @@ const action = async function(options) {
|
|
|
3854
3956
|
dev: options.dev,
|
|
3855
3957
|
minify: options.minify,
|
|
3856
3958
|
cache: options.cache,
|
|
3959
|
+
...options.sourcemapOutput ? { sourcemap: true } : {},
|
|
3857
3960
|
outfile: options.bundleOutput,
|
|
3858
3961
|
sourcemapOutfile: options.sourcemapOutput,
|
|
3859
3962
|
assetsDir: options.assetsDest
|