rollipop 1.0.0-alpha.21 → 1.0.0-alpha.23
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 +19 -0
- package/dist/{chunk-DEq-mXcV.js → _virtual/_rolldown/runtime.js} +1 -1
- package/dist/commands.d.ts +2 -4
- package/dist/commands.js +10 -3957
- package/dist/common/code.js +21 -0
- package/dist/common/constants.js +5 -0
- package/dist/common/env.js +33 -0
- package/dist/common/logger.d.ts +34 -0
- package/dist/common/logger.js +82 -0
- package/dist/common/logo.js +54 -0
- package/dist/common/progress-bar.js +167 -0
- package/dist/common/transformer.js +13 -0
- package/dist/common/types.d.ts +10 -0
- package/dist/config/compose-override.js +18 -0
- package/dist/config/defaults.d.ts +74 -0
- package/dist/config/defaults.js +74 -0
- package/dist/config/define-config.d.ts +13 -0
- package/dist/config/define-config.js +6 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.js +5 -0
- package/dist/config/load-config.d.ts +19 -0
- package/dist/config/load-config.js +73 -0
- package/dist/config/merge-config.d.ts +12 -0
- package/dist/config/merge-config.js +20 -0
- package/dist/config/types.d.ts +452 -0
- package/dist/constants.d.ts +35 -0
- package/dist/constants.js +146 -0
- package/dist/core/assets.d.ts +91 -0
- package/dist/core/assets.js +244 -0
- package/dist/core/bundler.d.ts +15 -0
- package/dist/core/bundler.js +80 -0
- package/dist/core/env.d.ts +11 -0
- package/dist/core/env.js +36 -0
- package/dist/core/fs/data.js +9 -0
- package/dist/core/fs/storage.d.ts +15 -0
- package/dist/core/fs/storage.js +31 -0
- package/dist/core/plugins/babel-plugin.d.ts +22 -0
- package/dist/core/plugins/babel-plugin.js +74 -0
- package/dist/core/plugins/context.d.ts +10 -0
- package/dist/core/plugins/context.js +24 -0
- package/dist/core/plugins/dev-server-plugin.d.ts +13 -0
- package/dist/core/plugins/dev-server-plugin.js +27 -0
- package/dist/core/plugins/index.d.ts +13 -0
- package/dist/core/plugins/index.js +18 -0
- package/dist/core/plugins/prelude-plugin.d.ts +10 -0
- package/dist/core/plugins/prelude-plugin.js +23 -0
- package/dist/core/plugins/react-native-plugin.d.ts +36 -0
- package/dist/core/plugins/react-native-plugin.js +81 -0
- package/dist/core/plugins/reporter-plugin.d.ts +11 -0
- package/dist/core/plugins/reporter-plugin.js +87 -0
- package/dist/core/plugins/shared/filters.js +5 -0
- package/dist/core/plugins/swc-plugin.d.ts +26 -0
- package/dist/core/plugins/swc-plugin.js +108 -0
- package/dist/core/plugins/types.d.ts +18 -0
- package/dist/core/plugins/utils/source.js +10 -0
- package/dist/core/plugins/utils/transform-utils.js +56 -0
- package/dist/core/rolldown.js +313 -0
- package/dist/core/settings.js +19 -0
- package/dist/core/types.d.ts +83 -0
- package/dist/filter.d.ts +1 -0
- package/dist/filter.js +2 -0
- package/dist/hmr-runtime.iife.js +5 -5
- package/dist/index.d.ts +24 -1221
- package/dist/index.js +19 -4029
- package/dist/internal/react-native.js +24 -0
- package/dist/logger.js +5 -0
- package/dist/node/cli-utils.d.ts +10 -0
- package/dist/node/cli-utils.js +28 -0
- package/dist/node/cli.d.ts +6 -0
- package/dist/node/cli.js +23 -0
- package/dist/node/commands/agent/action.js +91 -0
- package/dist/node/commands/agent/command.js +10 -0
- package/dist/node/commands/agent/index.js +2 -0
- package/dist/node/commands/bundle/action.js +33 -0
- package/dist/node/commands/bundle/command.js +96 -0
- package/dist/node/commands/bundle/index.js +2 -0
- package/dist/node/commands/start/action.js +37 -0
- package/dist/node/commands/start/command.js +93 -0
- package/dist/node/commands/start/debugger.js +79 -0
- package/dist/node/commands/start/index.js +2 -0
- package/dist/node/commands/start/setup-interactive-mode.d.ts +20 -0
- package/dist/node/commands/start/setup-interactive-mode.js +107 -0
- package/dist/node/constants.js +4 -0
- package/dist/node/logger.js +5 -0
- package/dist/node/types.d.ts +23 -0
- package/dist/node/utils.js +23 -0
- package/dist/package.js +4 -0
- package/dist/runtime.js +1 -1
- package/dist/server/bundle.d.ts +12 -0
- package/dist/server/bundle.js +55 -0
- package/dist/server/bundler-pool.d.ts +51 -0
- package/dist/server/bundler-pool.js +197 -0
- package/dist/server/common/schema.js +19 -0
- package/dist/server/constants.d.ts +6 -0
- package/dist/server/constants.js +6 -0
- package/dist/server/create-dev-server.d.ts +6 -0
- package/dist/server/create-dev-server.js +185 -0
- package/dist/server/error.js +9 -0
- package/dist/server/events/event-bus.d.ts +12 -0
- package/dist/server/events/event-bus.js +16 -0
- package/dist/server/events/types.d.ts +37 -0
- package/dist/server/events/types.js +6 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +3 -0
- package/dist/server/logger.js +33 -0
- package/dist/server/mcp/context.js +14 -0
- package/dist/server/mcp/server.js +86 -0
- package/dist/server/mcp/tools/app-log-diagnostics.js +37 -0
- package/dist/server/mcp/tools/build-diagnostics.js +97 -0
- package/dist/server/mcp/tools/build-info.js +33 -0
- package/dist/server/mcp/tools/device-diagnostics.js +52 -0
- package/dist/server/mcp/tools/index.js +277 -0
- package/dist/server/middlewares/request-logger.js +15 -0
- package/dist/server/middlewares/serve-assets.js +49 -0
- package/dist/server/middlewares/serve-bundle.js +72 -0
- package/dist/server/middlewares/sse.js +34 -0
- package/dist/server/middlewares/symbolicate.js +71 -0
- package/dist/server/sse/adapter.js +74 -0
- package/dist/server/sse/event-bus.js +26 -0
- package/dist/server/symbolicate.js +93 -0
- package/dist/server/types.d.ts +125 -0
- package/dist/server/wss/hmr-server.js +209 -0
- package/dist/server/wss/server.d.ts +9 -0
- package/dist/server/wss/server.js +70 -0
- package/dist/{runtime.d.cts → types/hmr.d.ts} +1 -12
- package/dist/types.d.ts +78 -0
- package/dist/utils/babel.js +11 -0
- package/dist/utils/build-options.js +17 -0
- package/dist/utils/bundle.js +6 -0
- package/dist/utils/config.d.ts +5 -0
- package/dist/utils/config.js +32 -0
- package/dist/utils/dev-server.js +51 -0
- package/dist/utils/env.js +7 -0
- package/dist/utils/errors.js +9 -0
- package/dist/utils/hash.js +8 -0
- package/dist/utils/id.js +28 -0
- package/dist/utils/node-resolve.js +42 -0
- package/dist/utils/promise.js +15 -0
- package/dist/utils/reporters.js +120 -0
- package/dist/utils/reset-cache.d.ts +8 -0
- package/dist/utils/reset-cache.js +25 -0
- package/dist/utils/response.js +91 -0
- package/dist/utils/run-build.d.ts +8 -0
- package/dist/utils/run-build.js +7 -0
- package/dist/utils/run-server.d.ts +6 -0
- package/dist/utils/run-server.js +20 -0
- package/dist/utils/runtime-target.js +9 -0
- package/dist/utils/serialize.js +10 -0
- package/dist/utils/server.js +6 -0
- package/dist/utils/storage.js +6 -0
- package/dist/utils/string.js +6 -0
- package/dist/utils/swc.js +10 -0
- package/dist/utils/terminal.js +86 -0
- package/dist/utils/url.js +23 -0
- package/package.json +56 -68
- package/dist/commands.cjs +0 -4008
- package/dist/commands.d.cts +0 -5
- package/dist/pluginutils.d.ts +0 -1
- package/dist/pluginutils.js +0 -2
- package/dist/runtime.cjs +0 -34
- /package/dist/{chunk-DXpK5_cz.js → chunk-DJV587Yu.js} +0 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { logger } from "../../logger.js";
|
|
2
|
+
import { DebuggerOpener } from "./debugger.js";
|
|
3
|
+
import { throttle } from "es-toolkit";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import readline from "node:readline";
|
|
6
|
+
import { ReadStream } from "node:tty";
|
|
7
|
+
//#region src/node/commands/start/setup-interactive-mode.ts
|
|
8
|
+
const CTRL_C = "";
|
|
9
|
+
const CTRL_D = "";
|
|
10
|
+
const BROADCAST_THROTTLE_DELAY = 500;
|
|
11
|
+
function setupInteractiveMode(options) {
|
|
12
|
+
const { devServer, extraCommands = [] } = options;
|
|
13
|
+
if (!devServer.instance.server.listening) throw new Error("Dev server is not listening. Please call `devServer.instance.listen()` first.");
|
|
14
|
+
if (!(process.stdin.isTTY && process.stdin instanceof ReadStream)) {
|
|
15
|
+
logger.warn("Interactive mode is not supported in non-interactive environments");
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const debuggerOpener = new DebuggerOpener(devServer.config.root, devServer.instance.listeningOrigin);
|
|
19
|
+
const defaultCommands = getDefaultCommands(devServer, debuggerOpener);
|
|
20
|
+
const allCommands = [...defaultCommands, ...extraCommands];
|
|
21
|
+
assertHasNoDuplicateCommands(defaultCommands, extraCommands);
|
|
22
|
+
readline.emitKeypressEvents(process.stdin);
|
|
23
|
+
process.stdin.setRawMode(true);
|
|
24
|
+
devServer.on("device.connected", () => {
|
|
25
|
+
debuggerOpener.autoOpen().catch(() => {
|
|
26
|
+
logger.error("Failed to open debugger");
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
process.stdin.on("keypress", (_, key) => {
|
|
30
|
+
const { ctrl = false, shift = false } = key;
|
|
31
|
+
const sequence = key.sequence?.toLowerCase();
|
|
32
|
+
if (sequence == null || debuggerOpener.isPrompting()) return;
|
|
33
|
+
if (ctrl && [CTRL_C, CTRL_D].includes(sequence)) {
|
|
34
|
+
process.stdin.setRawMode(false);
|
|
35
|
+
process.stdin.pause();
|
|
36
|
+
process.emit("SIGINT");
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
const targetCommand = allCommands.find((command) => command.key === sequence && (command.shift ?? false) === shift);
|
|
40
|
+
if (targetCommand) targetCommand.handler.call({
|
|
41
|
+
server: devServer,
|
|
42
|
+
logger
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
console.log();
|
|
46
|
+
allCommands.forEach((command, index) => {
|
|
47
|
+
if (defaultCommands.length === index) console.log();
|
|
48
|
+
const leadingLabel = command.shift ? "»" : "» Press";
|
|
49
|
+
const shortcut = chalk.bold(shortcutLabel(command.key, command.shift));
|
|
50
|
+
console.log(`${leadingLabel} ${shortcut} │ ${typeof command.description === "function" ? command.description() : command.description}`);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function getDefaultCommands(devServer, debuggerOpener) {
|
|
54
|
+
return [
|
|
55
|
+
{
|
|
56
|
+
key: "r",
|
|
57
|
+
description: "Reload app",
|
|
58
|
+
handler: throttle(() => {
|
|
59
|
+
logger.info("Reloading app...");
|
|
60
|
+
devServer.message.broadcast("reload");
|
|
61
|
+
}, BROADCAST_THROTTLE_DELAY)
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
key: "j",
|
|
65
|
+
description: "Open DevTools",
|
|
66
|
+
handler: () => {
|
|
67
|
+
debuggerOpener.open().catch(() => {
|
|
68
|
+
logger.error("Failed to open debugger");
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
key: "d",
|
|
74
|
+
description: "Show developer menu",
|
|
75
|
+
handler: throttle(() => {
|
|
76
|
+
logger.info("Showing developer menu...");
|
|
77
|
+
devServer.message.broadcast("devMenu");
|
|
78
|
+
}, BROADCAST_THROTTLE_DELAY)
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
key: "d",
|
|
82
|
+
shift: true,
|
|
83
|
+
description: () => {
|
|
84
|
+
const autoOpenEnabled = debuggerOpener.isAutoOpenEnabled();
|
|
85
|
+
return `Toggle auto opening developer tools on startup (${chalk.bold(autoOpenEnabled ? "enabled" : "disabled")})`;
|
|
86
|
+
},
|
|
87
|
+
handler: () => {
|
|
88
|
+
const newAutoOpenEnabled = !debuggerOpener.isAutoOpenEnabled();
|
|
89
|
+
debuggerOpener.setAutoOpenEnabled(newAutoOpenEnabled);
|
|
90
|
+
logger.info(`Auto opening developer tools: ${chalk.bold(newAutoOpenEnabled ? "enabled" : "disabled")}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
];
|
|
94
|
+
}
|
|
95
|
+
function shortcutLabel(key, shift) {
|
|
96
|
+
if (shift) return `shift+${key}`;
|
|
97
|
+
return key;
|
|
98
|
+
}
|
|
99
|
+
function assertHasNoDuplicateCommands(defaultCommands, commands) {
|
|
100
|
+
const defaultCommandKeys = defaultCommands.map(({ key, shift }) => shortcutLabel(key, shift));
|
|
101
|
+
const duplicateKeys = commands.map(({ key, shift }) => shortcutLabel(key, shift)).filter((key) => defaultCommandKeys.includes(key));
|
|
102
|
+
const invalidCommandKeys = commands.filter(({ key }) => key.length > 1).map(({ key, shift }) => shortcutLabel(key, shift));
|
|
103
|
+
if (invalidCommandKeys.length > 0) throw new Error(`Invalid commands: ${invalidCommandKeys.join(", ")}`);
|
|
104
|
+
if (duplicateKeys.length > 0) throw new Error(`Duplicate commands: ${duplicateKeys.join(", ")}`);
|
|
105
|
+
}
|
|
106
|
+
//#endregion
|
|
107
|
+
export { setupInteractiveMode };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/node/types.d.ts
|
|
2
|
+
interface CommandDefinition<Options> {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
helpText?: string;
|
|
6
|
+
options?: CommandOptionDefinition[];
|
|
7
|
+
action: CommandAction<Options>;
|
|
8
|
+
}
|
|
9
|
+
interface CommandAction<Options> {
|
|
10
|
+
(this: CommandContext, options: Options): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
interface CommandOptionDefinition<T = any> {
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
required?: boolean;
|
|
16
|
+
default?: T;
|
|
17
|
+
parse?: (value: string) => T;
|
|
18
|
+
}
|
|
19
|
+
interface CommandContext {
|
|
20
|
+
platforms: string[];
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { CommandDefinition };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { logger } from "./logger.js";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
//#region src/node/utils.ts
|
|
4
|
+
function parseBoolean(value) {
|
|
5
|
+
return value === "true" || value === "1";
|
|
6
|
+
}
|
|
7
|
+
function resolvePath(value) {
|
|
8
|
+
return path.resolve(value);
|
|
9
|
+
}
|
|
10
|
+
function withErrorHandler(action) {
|
|
11
|
+
return async function(args) {
|
|
12
|
+
try {
|
|
13
|
+
await action.call(this, args);
|
|
14
|
+
} catch (reason) {
|
|
15
|
+
logger.error("An error occurred while executing the command");
|
|
16
|
+
logger.error(`Reason: ${reason instanceof Error ? reason.message : String(reason)}`);
|
|
17
|
+
logger.debug(reason);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { parseBoolean, resolvePath, withErrorHandler };
|
package/dist/package.js
ADDED
package/dist/runtime.js
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BasicSourceMapConsumer, IndexedSourceMapConsumer } from "source-map";
|
|
2
|
+
|
|
3
|
+
//#region src/server/bundle.d.ts
|
|
4
|
+
type SourceMapConsumerType = BasicSourceMapConsumer | IndexedSourceMapConsumer;
|
|
5
|
+
interface BundleStore {
|
|
6
|
+
bundleFilePath: string;
|
|
7
|
+
code: string;
|
|
8
|
+
sourceMap: string | undefined;
|
|
9
|
+
sourceMapConsumer: Promise<SourceMapConsumerType> | undefined;
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { BundleStore };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { logger } from "../logger.js";
|
|
2
|
+
import { getSharedDataPath } from "../core/fs/data.js";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { SourceMapConsumer } from "source-map";
|
|
6
|
+
//#region src/server/bundle.ts
|
|
7
|
+
var FileSystemBundleStore = class {
|
|
8
|
+
bundleFilePath;
|
|
9
|
+
_sourceMap;
|
|
10
|
+
lazySourceMapConsumer = null;
|
|
11
|
+
holder;
|
|
12
|
+
constructor(projectRoot, id, code, sourceMap) {
|
|
13
|
+
const sharedDataPath = getSharedDataPath(projectRoot);
|
|
14
|
+
const bundlesPath = path.join(sharedDataPath, "bundles");
|
|
15
|
+
const bundleFilePath = path.join(bundlesPath, `${id}.bundle`);
|
|
16
|
+
if (!fs.existsSync(bundlesPath)) fs.mkdirSync(bundlesPath, { recursive: true });
|
|
17
|
+
fs.writeFileSync(bundleFilePath, code, { encoding: "utf-8" });
|
|
18
|
+
const stats = fs.statSync(bundleFilePath);
|
|
19
|
+
this.bundleFilePath = bundleFilePath;
|
|
20
|
+
this._sourceMap = sourceMap;
|
|
21
|
+
this.holder = {
|
|
22
|
+
code,
|
|
23
|
+
mtimeMs: stats.mtimeMs
|
|
24
|
+
};
|
|
25
|
+
logger.debug(`File system bundle created at ${bundleFilePath}`);
|
|
26
|
+
}
|
|
27
|
+
update() {
|
|
28
|
+
const code = fs.readFileSync(this.bundleFilePath, { encoding: "utf-8" });
|
|
29
|
+
const stats = fs.statSync(this.bundleFilePath);
|
|
30
|
+
this.holder = {
|
|
31
|
+
code,
|
|
32
|
+
mtimeMs: stats.mtimeMs
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
get code() {
|
|
36
|
+
if (this.isStale()) {
|
|
37
|
+
logger.info("File system bundle is stale, updating...");
|
|
38
|
+
this.update();
|
|
39
|
+
} else logger.trace("File system bundle is up to date");
|
|
40
|
+
return this.holder.code;
|
|
41
|
+
}
|
|
42
|
+
get sourceMap() {
|
|
43
|
+
return this.isStale() ? void 0 : this._sourceMap;
|
|
44
|
+
}
|
|
45
|
+
get sourceMapConsumer() {
|
|
46
|
+
if (this.isStale() || this._sourceMap == null) return;
|
|
47
|
+
if (this.lazySourceMapConsumer == null) this.lazySourceMapConsumer = new SourceMapConsumer(this._sourceMap);
|
|
48
|
+
return this.lazySourceMapConsumer;
|
|
49
|
+
}
|
|
50
|
+
isStale() {
|
|
51
|
+
return this.holder.mtimeMs !== fs.statSync(this.bundleFilePath).mtimeMs;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
//#endregion
|
|
55
|
+
export { FileSystemBundleStore };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { BuildOptions, DevEngine } from "../core/types.js";
|
|
2
|
+
import { BundleStore } from "./bundle.js";
|
|
3
|
+
import { ServerEventBus } from "./events/event-bus.js";
|
|
4
|
+
import { ServerOptions } from "./types.js";
|
|
5
|
+
import { ResolvedConfig } from "../config/defaults.js";
|
|
6
|
+
//#region src/server/bundler-pool.d.ts
|
|
7
|
+
interface DevServerOptions {
|
|
8
|
+
host: string;
|
|
9
|
+
port: number;
|
|
10
|
+
}
|
|
11
|
+
interface BundlerDevEngineOptions {
|
|
12
|
+
server: DevServerOptions;
|
|
13
|
+
}
|
|
14
|
+
type BundlerStatus = 'idle' | 'building' | 'build-done' | 'build-failed';
|
|
15
|
+
declare class BundlerDevEngine {
|
|
16
|
+
private readonly options;
|
|
17
|
+
private readonly config;
|
|
18
|
+
private readonly buildOptions;
|
|
19
|
+
private readonly eventBus;
|
|
20
|
+
private readonly initializeHandle;
|
|
21
|
+
private readonly isHmrEnabled;
|
|
22
|
+
private readonly _id;
|
|
23
|
+
private bundleStore;
|
|
24
|
+
private buildFailedError;
|
|
25
|
+
private _devEngine;
|
|
26
|
+
private _state;
|
|
27
|
+
private _status;
|
|
28
|
+
constructor(options: BundlerDevEngineOptions, config: ResolvedConfig, buildOptions: BuildOptions, eventBus: ServerEventBus);
|
|
29
|
+
get id(): string;
|
|
30
|
+
/** Snapshot of the bundler's current lifecycle state. */
|
|
31
|
+
get status(): BundlerStatus;
|
|
32
|
+
get devEngine(): DevEngine;
|
|
33
|
+
get ensureInitialized(): Promise<void>;
|
|
34
|
+
private initialize;
|
|
35
|
+
private updateBundleStore;
|
|
36
|
+
getBundle(): Promise<BundleStore>;
|
|
37
|
+
}
|
|
38
|
+
declare class BundlerPool {
|
|
39
|
+
private readonly config;
|
|
40
|
+
private readonly resolvedServerOptions;
|
|
41
|
+
private readonly eventBus;
|
|
42
|
+
private static readonly instances;
|
|
43
|
+
constructor(config: ResolvedConfig, resolvedServerOptions: Required<Pick<ServerOptions, 'host' | 'port'>>, eventBus: ServerEventBus);
|
|
44
|
+
get(bundleName: string, buildOptions: Pick<BuildOptions, 'platform' | 'dev'>): BundlerDevEngine;
|
|
45
|
+
/**
|
|
46
|
+
* 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.
|
|
47
|
+
*/
|
|
48
|
+
getInstanceById(id: string): BundlerDevEngine | undefined;
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { BundlerPool };
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { bindReporter } from "../utils/config.js";
|
|
2
|
+
import { logger } from "./logger.js";
|
|
3
|
+
import { getBaseBundleName } from "../utils/bundle.js";
|
|
4
|
+
import { normalizeRolldownError } from "../utils/errors.js";
|
|
5
|
+
import { taskHandler } from "../utils/promise.js";
|
|
6
|
+
import { FileSystemBundleStore } from "./bundle.js";
|
|
7
|
+
import { Bundler } from "../core/bundler.js";
|
|
8
|
+
import { invariant } from "es-toolkit";
|
|
9
|
+
//#region src/server/bundler-pool.ts
|
|
10
|
+
var BundlerDevEngine = class {
|
|
11
|
+
options;
|
|
12
|
+
config;
|
|
13
|
+
buildOptions;
|
|
14
|
+
eventBus;
|
|
15
|
+
initializeHandle;
|
|
16
|
+
isHmrEnabled;
|
|
17
|
+
_id;
|
|
18
|
+
bundleStore = null;
|
|
19
|
+
buildFailedError = null;
|
|
20
|
+
_devEngine = null;
|
|
21
|
+
_state = "idle";
|
|
22
|
+
_status = "idle";
|
|
23
|
+
constructor(options, config, buildOptions, eventBus) {
|
|
24
|
+
this.options = options;
|
|
25
|
+
this.config = config;
|
|
26
|
+
this.buildOptions = buildOptions;
|
|
27
|
+
this.eventBus = eventBus;
|
|
28
|
+
this._id = Bundler.createId(config, buildOptions);
|
|
29
|
+
this.initializeHandle = taskHandler();
|
|
30
|
+
this.isHmrEnabled = Boolean(buildOptions.dev && config.devMode.hmr);
|
|
31
|
+
this.initialize();
|
|
32
|
+
}
|
|
33
|
+
get id() {
|
|
34
|
+
return this._id;
|
|
35
|
+
}
|
|
36
|
+
/** Snapshot of the bundler's current lifecycle state. */
|
|
37
|
+
get status() {
|
|
38
|
+
return this._status;
|
|
39
|
+
}
|
|
40
|
+
get devEngine() {
|
|
41
|
+
invariant(this._devEngine, "DevEngine is not initialized");
|
|
42
|
+
return this._devEngine;
|
|
43
|
+
}
|
|
44
|
+
get ensureInitialized() {
|
|
45
|
+
return this.initializeHandle.task;
|
|
46
|
+
}
|
|
47
|
+
async initialize() {
|
|
48
|
+
if (this._state !== "idle" || this._devEngine != null) return this;
|
|
49
|
+
this._state = "initializing";
|
|
50
|
+
let pendingBuildDoneEvent = null;
|
|
51
|
+
const emitReportableEvent = (event) => {
|
|
52
|
+
switch (event.type) {
|
|
53
|
+
case "bundle_build_started":
|
|
54
|
+
this._status = "building";
|
|
55
|
+
break;
|
|
56
|
+
case "bundle_build_done":
|
|
57
|
+
this._status = "build-done";
|
|
58
|
+
break;
|
|
59
|
+
case "bundle_build_failed":
|
|
60
|
+
this._status = "build-failed";
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
this.eventBus.emit({
|
|
64
|
+
...event,
|
|
65
|
+
bundlerId: this.id
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
const config = bindReporter(this.config, (event) => {
|
|
69
|
+
if (event.type === "bundle_build_started") pendingBuildDoneEvent = null;
|
|
70
|
+
if (event.type === "bundle_build_done") {
|
|
71
|
+
pendingBuildDoneEvent = event;
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
emitReportableEvent(event);
|
|
75
|
+
});
|
|
76
|
+
const devEngine = await Bundler.devEngine(config, this.buildOptions, {
|
|
77
|
+
host: this.options.server.host,
|
|
78
|
+
port: this.options.server.port,
|
|
79
|
+
onHmrUpdates: (errorOrResult) => {
|
|
80
|
+
if (!this.isHmrEnabled) return;
|
|
81
|
+
if (errorOrResult instanceof Error) {
|
|
82
|
+
logger.error("Failed to handle HMR updates", {
|
|
83
|
+
bundlerId: this.id,
|
|
84
|
+
error: errorOrResult
|
|
85
|
+
});
|
|
86
|
+
const event = {
|
|
87
|
+
type: "hmr_failed",
|
|
88
|
+
error: normalizeRolldownError(errorOrResult)
|
|
89
|
+
};
|
|
90
|
+
this.eventBus.emit({
|
|
91
|
+
...event,
|
|
92
|
+
bundlerId: this.id
|
|
93
|
+
});
|
|
94
|
+
} else {
|
|
95
|
+
logger.trace("Detected changed files", {
|
|
96
|
+
bundlerId: this.id,
|
|
97
|
+
changedFiles: errorOrResult.changedFiles
|
|
98
|
+
});
|
|
99
|
+
this.eventBus.emit({
|
|
100
|
+
bundlerId: this.id,
|
|
101
|
+
type: "hmr_updates",
|
|
102
|
+
updates: errorOrResult.updates
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
onOutput: (errorOrResult) => {
|
|
107
|
+
if (errorOrResult instanceof Error) {
|
|
108
|
+
pendingBuildDoneEvent = null;
|
|
109
|
+
const normalizedError = normalizeRolldownError(errorOrResult);
|
|
110
|
+
logger.trace("onOutput", { bundlerId: this.id });
|
|
111
|
+
logger.error(errorOrResult.message);
|
|
112
|
+
this.buildFailedError = normalizedError;
|
|
113
|
+
const event = {
|
|
114
|
+
type: "bundle_build_failed",
|
|
115
|
+
error: normalizedError
|
|
116
|
+
};
|
|
117
|
+
this._status = "build-failed";
|
|
118
|
+
this.eventBus.emit({
|
|
119
|
+
...event,
|
|
120
|
+
bundlerId: this.id
|
|
121
|
+
});
|
|
122
|
+
} else {
|
|
123
|
+
const output = errorOrResult.output[0];
|
|
124
|
+
const bundleStore = this.updateBundleStore(output);
|
|
125
|
+
this.buildFailedError = null;
|
|
126
|
+
logger.debug("Build completed", {
|
|
127
|
+
bundlerId: this.id,
|
|
128
|
+
bundleName: output.name,
|
|
129
|
+
bundleFilePath: bundleStore.bundleFilePath
|
|
130
|
+
});
|
|
131
|
+
if (pendingBuildDoneEvent != null) {
|
|
132
|
+
emitReportableEvent({
|
|
133
|
+
...pendingBuildDoneEvent,
|
|
134
|
+
bundleFilePath: bundleStore.bundleFilePath
|
|
135
|
+
});
|
|
136
|
+
pendingBuildDoneEvent = null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
rebuildStrategy: "auto"
|
|
141
|
+
});
|
|
142
|
+
await devEngine.run();
|
|
143
|
+
this._devEngine = devEngine;
|
|
144
|
+
this._state = "ready";
|
|
145
|
+
this.initializeHandle.resolve();
|
|
146
|
+
}
|
|
147
|
+
updateBundleStore(output) {
|
|
148
|
+
this.bundleStore = new FileSystemBundleStore(this.config.root, this.id, output.code, output.map?.toString());
|
|
149
|
+
return this.bundleStore;
|
|
150
|
+
}
|
|
151
|
+
async getBundle() {
|
|
152
|
+
await this.ensureInitialized;
|
|
153
|
+
const state = await this.devEngine.getBundleState();
|
|
154
|
+
logger.debug("Bundle state", {
|
|
155
|
+
bundlerId: this.id,
|
|
156
|
+
state
|
|
157
|
+
});
|
|
158
|
+
if (state.lastFullBuildFailed) throw new Error(this.buildFailedError?.message ?? "Build failed");
|
|
159
|
+
if (state.hasStaleOutput || this.bundleStore == null) await this.devEngine.ensureLatestBuildOutput();
|
|
160
|
+
invariant(this.bundleStore, "Bundle is not available");
|
|
161
|
+
return this.bundleStore;
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
var BundlerPool = class BundlerPool {
|
|
165
|
+
config;
|
|
166
|
+
resolvedServerOptions;
|
|
167
|
+
eventBus;
|
|
168
|
+
static instances = /* @__PURE__ */ new Map();
|
|
169
|
+
constructor(config, resolvedServerOptions, eventBus) {
|
|
170
|
+
this.config = config;
|
|
171
|
+
this.resolvedServerOptions = resolvedServerOptions;
|
|
172
|
+
this.eventBus = eventBus;
|
|
173
|
+
}
|
|
174
|
+
get(bundleName, buildOptions) {
|
|
175
|
+
const key = `${getBaseBundleName(bundleName)}-${Bundler.createId(this.config, buildOptions)}`;
|
|
176
|
+
const instance = BundlerPool.instances.get(key);
|
|
177
|
+
if (instance) return instance;
|
|
178
|
+
else {
|
|
179
|
+
logger.debug("Preparing new bundler instance", {
|
|
180
|
+
bundleName,
|
|
181
|
+
key
|
|
182
|
+
});
|
|
183
|
+
const instance = new BundlerDevEngine({ server: this.resolvedServerOptions }, this.config, buildOptions, this.eventBus);
|
|
184
|
+
logger.debug("Setting new bundler instance", { key });
|
|
185
|
+
BundlerPool.instances.set(key, instance);
|
|
186
|
+
return instance;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* 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.
|
|
191
|
+
*/
|
|
192
|
+
getInstanceById(id) {
|
|
193
|
+
for (const instance of BundlerPool.instances.values()) if (instance.id === id) return instance;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
//#endregion
|
|
197
|
+
export { BundlerPool };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { asConst } from "json-schema-to-ts";
|
|
2
|
+
import Ajv from "ajv";
|
|
3
|
+
//#region src/server/common/schema.ts
|
|
4
|
+
const bundleRequestSchema = asConst({
|
|
5
|
+
type: "object",
|
|
6
|
+
properties: {
|
|
7
|
+
platform: { type: "string" },
|
|
8
|
+
app: { type: "string" },
|
|
9
|
+
dev: { type: "boolean" },
|
|
10
|
+
minify: { type: "boolean" },
|
|
11
|
+
runModule: { type: "boolean" },
|
|
12
|
+
inlineSourceMap: { type: "boolean" },
|
|
13
|
+
modulesOnly: { type: "boolean" }
|
|
14
|
+
},
|
|
15
|
+
required: ["platform"]
|
|
16
|
+
});
|
|
17
|
+
new Ajv().compile(bundleRequestSchema);
|
|
18
|
+
//#endregion
|
|
19
|
+
export { bundleRequestSchema };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DevServer, ServerOptions } from "./types.js";
|
|
2
|
+
import { ResolvedConfig } from "../config/defaults.js";
|
|
3
|
+
//#region src/server/create-dev-server.d.ts
|
|
4
|
+
declare function createDevServer(config: ResolvedConfig, options?: ServerOptions): Promise<DevServer>;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { createDevServer };
|