rollipop 0.0.0 → 0.1.0-alpha.1

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/bin/index.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { cli } from '../dist/index.js';
4
+
5
+ cli.run(process.argv);
@@ -0,0 +1,18 @@
1
+ //#region rolldown:runtime
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (all, symbols) => {
4
+ let target = {};
5
+ for (var name in all) {
6
+ __defProp(target, name, {
7
+ get: all[name],
8
+ enumerable: true
9
+ });
10
+ }
11
+ if (symbols) {
12
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
13
+ }
14
+ return target;
15
+ };
16
+
17
+ //#endregion
18
+ export { __export as t };
package/dist/index.cjs ADDED
@@ -0,0 +1,340 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (all, symbols) => {
9
+ let target = {};
10
+ for (var name in all) {
11
+ __defProp(target, name, {
12
+ get: all[name],
13
+ enumerable: true
14
+ });
15
+ }
16
+ if (symbols) {
17
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
18
+ }
19
+ return target;
20
+ };
21
+ var __copyProps = (to, from, except, desc) => {
22
+ if (from && typeof from === "object" || typeof from === "function") {
23
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
24
+ key = keys[i];
25
+ if (!__hasOwnProp.call(to, key) && key !== except) {
26
+ __defProp(to, key, {
27
+ get: ((k) => from[k]).bind(null, key),
28
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
29
+ });
30
+ }
31
+ }
32
+ }
33
+ return to;
34
+ };
35
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
36
+ value: mod,
37
+ enumerable: true
38
+ }) : target, mod));
39
+
40
+ //#endregion
41
+ let _rollipop_common = require("@rollipop/common");
42
+ let _rollipop_core = require("@rollipop/core");
43
+ let _rollipop_dev_server = require("@rollipop/dev-server");
44
+ let _commander_js_extra_typings = require("@commander-js/extra-typings");
45
+ let es_toolkit = require("es-toolkit");
46
+ let _inquirer_prompts = require("@inquirer/prompts");
47
+ let node_readline = require("node:readline");
48
+ node_readline = __toESM(node_readline);
49
+ let node_tty = require("node:tty");
50
+
51
+ //#region src/run-build.ts
52
+ async function runBuild(config, options) {
53
+ return await new _rollipop_core.Bundler(config).build(options);
54
+ }
55
+
56
+ //#endregion
57
+ //#region src/run-server.ts
58
+ async function runServer(config, options) {
59
+ const { port, host } = options;
60
+ const devServer = await (0, _rollipop_dev_server.createDevServer)(config, options);
61
+ await devServer.instance.listen({
62
+ port,
63
+ host
64
+ });
65
+ return devServer;
66
+ }
67
+
68
+ //#endregion
69
+ //#region package.json
70
+ var version = "0.1.0-alpha.1";
71
+
72
+ //#endregion
73
+ //#region src/node/constants.ts
74
+ const UNSUPPORTED_OPTION_DESCRIPTION = "Unsupported option";
75
+
76
+ //#endregion
77
+ //#region src/node/logger.ts
78
+ const logger = new _rollipop_common.Logger("cli");
79
+
80
+ //#endregion
81
+ //#region src/node/utils.ts
82
+ function parseBoolean(value) {
83
+ return value === "true" || value === "1";
84
+ }
85
+
86
+ //#endregion
87
+ //#region src/node/commands/bundle/index.ts
88
+ const command$1 = new _commander_js_extra_typings.Command("bundle").description("Build the bundle for the provided JavaScript entry file.").option("--config <string>", "Path to the CLI configuration file").requiredOption("--entry-file <path>", "Path to the root JS file, either absolute or relative to JS root").requiredOption("--bundle-output <string>", "File name where to store the resulting bundle, ex. /tmp/groups.bundle").option("--platform <string>", "Either \"ios\" or \"android\"", "ios").option("--dev [boolean]", "If false, warnings are disabled and the bundle is minified", parseBoolean, true).option("--minify [boolean]", "Allows overriding whether bundle is minified. This defaults to false if dev is true, and true if dev is false. Disabling minification can be useful for speeding up production builds for testing purposes.", parseBoolean, false).option("--sourcemap-output <string>", "File name where to store the sourcemap file for resulting bundle, ex. /tmp/groups.map").option("--sourcemap-sources-root <string>", "Path to make sourcemap's sources entries relative to, ex. /root/dir").option("--sourcemap-use-absolute-path", "Report SourceMapURL using its full path", false).option("--assets-dest <string>", "Directory name where to store assets referenced in the bundle").option("--cache [boolean]", "If false, the bundler will not cache anything", parseBoolean, true).option("--reset-cache", "Removes cached files").option("--transformer <string>", UNSUPPORTED_OPTION_DESCRIPTION).option("--bundle-encoding <string>", UNSUPPORTED_OPTION_DESCRIPTION, "utf8").option("--max-workers <number>", UNSUPPORTED_OPTION_DESCRIPTION, Number, 0).option("--unstable-transform-profile <string>", UNSUPPORTED_OPTION_DESCRIPTION, "default").option("--asset-catalog-dest [string]", UNSUPPORTED_OPTION_DESCRIPTION).option("--read-global-cache", UNSUPPORTED_OPTION_DESCRIPTION).option("--resolver-option <string...>", UNSUPPORTED_OPTION_DESCRIPTION).action(async (options) => {
89
+ const cwd = process.cwd();
90
+ const config = await Rollipop.loadConfig({
91
+ cwd,
92
+ configFile: options.config,
93
+ context: { command: "bundle" }
94
+ });
95
+ if (options.resetCache) {
96
+ Rollipop.resetCache(cwd);
97
+ logger.info("The transform cache was reset");
98
+ }
99
+ if (options.entryFile) config.entry = options.entryFile;
100
+ await Rollipop.runBuild(config, {
101
+ platform: options.platform,
102
+ dev: options.dev,
103
+ minify: options.minify,
104
+ cache: options.cache,
105
+ outfile: options.bundleOutput,
106
+ sourcemap: options.sourcemapOutput,
107
+ assetsDir: options.assetsDest
108
+ });
109
+ });
110
+
111
+ //#endregion
112
+ //#region src/node/debugger.ts
113
+ var DebuggerOpener = class DebuggerOpener {
114
+ static MAX_TARGETS_SHOWN = 10;
115
+ _prompting = false;
116
+ settings;
117
+ static setAutoOpenEnabled(projectRoot, enabled) {
118
+ (0, _rollipop_common.saveSettings)(projectRoot, { devtools: { autoOpen: enabled } });
119
+ }
120
+ constructor(projectRoot, serverUrl) {
121
+ this.projectRoot = projectRoot;
122
+ this.serverUrl = serverUrl;
123
+ this.settings = (0, _rollipop_common.loadSettings)(projectRoot);
124
+ }
125
+ async openDebuggerForTarget(target) {
126
+ logger.debug(`Opening debugger for target: ${target.id}`);
127
+ try {
128
+ await fetch(new URL("/open-debugger?target=" + encodeURIComponent(target.id), this.serverUrl), { method: "POST" });
129
+ } catch (error) {
130
+ logger.error(`Failed to open debugger for ${target.title}`);
131
+ logger.debug("Reason", error);
132
+ }
133
+ }
134
+ async open() {
135
+ logger.debug("Fetching available debugging targets...");
136
+ const response = await fetch(new URL("/json/list", this.serverUrl), { method: "POST" });
137
+ if (response.status !== 200) throw new Error(`Unexpected status code: ${response.status}`);
138
+ const targets = await response.json();
139
+ if (!Array.isArray(targets)) throw new Error("Unexpected response format");
140
+ logger.debug(`Found ${targets.length} debugging targets:`);
141
+ if (targets.length === 0) logger.warn("No connected targets");
142
+ else if (targets.length === 1) {
143
+ const target = targets[0];
144
+ await this.openDebuggerForTarget(target);
145
+ } else {
146
+ if (targets.length > DebuggerOpener.MAX_TARGETS_SHOWN) logger.warn(`More than ${DebuggerOpener.MAX_TARGETS_SHOWN} debug targets available, showing the first ${DebuggerOpener.MAX_TARGETS_SHOWN}.`);
147
+ const slicedTargets = targets.slice(0, DebuggerOpener.MAX_TARGETS_SHOWN);
148
+ _rollipop_common.Logger.block();
149
+ this._prompting = true;
150
+ try {
151
+ const targetIndex = await (0, _inquirer_prompts.select)({
152
+ message: "Multiple debug targets available, please select:",
153
+ choices: slicedTargets.map((target, index) => ({
154
+ value: index,
155
+ name: `${target.title} (${target.description})`
156
+ }))
157
+ });
158
+ await this.openDebuggerForTarget(slicedTargets[targetIndex]);
159
+ } catch {} finally {
160
+ _rollipop_common.Logger.unblock();
161
+ this._prompting = false;
162
+ }
163
+ }
164
+ }
165
+ isPrompting() {
166
+ return this._prompting;
167
+ }
168
+ isAutoOpenEnabled() {
169
+ return this.settings.devtools?.autoOpen ?? false;
170
+ }
171
+ setAutoOpenEnabled(enabled) {
172
+ const newSettings = this.settings = (0, es_toolkit.merge)(this.settings, { devtools: { autoOpen: enabled } });
173
+ (0, _rollipop_common.saveSettings)(this.projectRoot, newSettings);
174
+ }
175
+ };
176
+
177
+ //#endregion
178
+ //#region src/node/commands/start/setup-interactive-mode.ts
179
+ const CTRL_C = "";
180
+ const CTRL_D = "";
181
+ const BROADCAST_THROTTLE_DELAY = 500;
182
+ const SUPPORTED_COMMANDS = {
183
+ r: {
184
+ description: "Reload app",
185
+ handler: (0, es_toolkit.throttle)((broadcast) => {
186
+ logger.info("Reloading app...");
187
+ broadcast("reload");
188
+ }, BROADCAST_THROTTLE_DELAY)
189
+ },
190
+ j: { description: "Open DevTools" },
191
+ d: {
192
+ description: "Show developer menu",
193
+ handler: (0, es_toolkit.throttle)((broadcast) => {
194
+ logger.info("Showing developer menu...");
195
+ broadcast("devMenu");
196
+ }, BROADCAST_THROTTLE_DELAY)
197
+ }
198
+ };
199
+ function setupInteractiveMode(options) {
200
+ const { broadcast, debuggerOpener } = options;
201
+ if (!(process.stdin.isTTY && process.stdin instanceof node_tty.ReadStream)) {
202
+ logger.warn("Interactive mode is not supported in non-interactive environments");
203
+ return;
204
+ }
205
+ node_readline.default.emitKeypressEvents(process.stdin);
206
+ process.stdin.setRawMode(true);
207
+ process.stdin.on("keypress", (_, key) => {
208
+ const { ctrl, shift } = key;
209
+ const sequence = key.sequence?.toLowerCase();
210
+ if (sequence == null || debuggerOpener.isPrompting()) return;
211
+ if (ctrl && [CTRL_C, CTRL_D].includes(sequence)) {
212
+ process.stdin.setRawMode(false);
213
+ process.stdin.pause();
214
+ process.emit("SIGINT");
215
+ process.exit(0);
216
+ }
217
+ if (shift && sequence.toLowerCase() === "d") {
218
+ const newAutoOpenEnabled = !debuggerOpener.isAutoOpenEnabled();
219
+ debuggerOpener.setAutoOpenEnabled(newAutoOpenEnabled);
220
+ logger.info(`Auto opening developer tools: ${_rollipop_common.chalk.bold(newAutoOpenEnabled ? "enabled" : "disabled")}`);
221
+ return;
222
+ }
223
+ switch (sequence) {
224
+ case "r":
225
+ case "d":
226
+ SUPPORTED_COMMANDS[sequence].handler(broadcast);
227
+ break;
228
+ case "j":
229
+ debuggerOpener.open().catch(() => {
230
+ logger.error("Failed to open debugger");
231
+ });
232
+ break;
233
+ }
234
+ });
235
+ console.log();
236
+ Object.entries(SUPPORTED_COMMANDS).forEach(([key, command$2]) => {
237
+ const keyLabel$1 = `» Press ${_rollipop_common.chalk.bold(key)} │`;
238
+ console.log(`${keyLabel$1} ${command$2.description}`);
239
+ });
240
+ const keyLabel = `» ${_rollipop_common.chalk.bold("shift+d")} │`;
241
+ const autoOpenStatus = `(${debuggerOpener.isAutoOpenEnabled() ? "enabled" : "disabled"})`;
242
+ console.log(`${keyLabel} Toggle auto opening developer tools on startup ${`${_rollipop_common.chalk.gray.bold(autoOpenStatus)}`}`);
243
+ }
244
+
245
+ //#endregion
246
+ //#region src/node/commands/start/index.ts
247
+ const command = new _commander_js_extra_typings.Command("start").description("Start the React Native development server.").option("--config <string>", "Path to the CLI configuration file").option("--host <string>", "Host to start the development server on", _rollipop_dev_server.DEFAULT_HOST).option("--port <number>", "Port to start the development server on", Number, _rollipop_dev_server.DEFAULT_PORT).option("--projectRoot <path>", "Path to a custom project root", "").option("--reset-cache", "Removes cached files").option("--https", "Enables https connections to the server").option("--key <path>", "Path to custom SSL key").option("--cert <path>", "Path to custom SSL cert").option("--no-interactive", "Disables interactive mode").option("--client-logs", "Enable plain text JavaScript log streaming for all connected apps. This feature is deprecated and will be removed in future.", false).option("--watchFolders <list>", UNSUPPORTED_OPTION_DESCRIPTION).option("--assetPlugins <list>", UNSUPPORTED_OPTION_DESCRIPTION).option("--sourceExts <list>", UNSUPPORTED_OPTION_DESCRIPTION).option("--max-workers <list>", UNSUPPORTED_OPTION_DESCRIPTION).option("--transformer", UNSUPPORTED_OPTION_DESCRIPTION).option("--custom-log-reporter-path", UNSUPPORTED_OPTION_DESCRIPTION).action(async (options) => {
248
+ const cwd = process.cwd();
249
+ const config = await Rollipop.loadConfig({
250
+ cwd,
251
+ configFile: options.config,
252
+ context: { command: "start" }
253
+ });
254
+ if (options.resetCache) {
255
+ Rollipop.resetCache(cwd);
256
+ logger.info("The transform cache was reset");
257
+ }
258
+ if (options.clientLogs === false) config.reporter = { update: es_toolkit.noop };
259
+ let debuggerOpened = false;
260
+ const server = await Rollipop.runServer(config, {
261
+ projectRoot: cwd,
262
+ port: options.port,
263
+ host: options.host,
264
+ https: options.https,
265
+ key: options.key,
266
+ cert: options.cert,
267
+ onDeviceConnected: () => {
268
+ if (debuggerOpened === false && debuggerOpener.isAutoOpenEnabled()) {
269
+ debuggerOpener.open().catch((error) => {
270
+ logger.error("Failed to open debugger", { error });
271
+ });
272
+ debuggerOpened = true;
273
+ }
274
+ }
275
+ });
276
+ const debuggerOpener = new DebuggerOpener(cwd, server.instance.listeningOrigin);
277
+ if (options.interactive) setupInteractiveMode({
278
+ broadcast: (message, params) => server.message.broadcast(message, params),
279
+ debuggerOpener
280
+ });
281
+ });
282
+
283
+ //#endregion
284
+ //#region src/node/cli.ts
285
+ var cli_exports = /* @__PURE__ */ __export({ run: () => run });
286
+ function run(argv) {
287
+ _rollipop_common.Logo.printOnce();
288
+ const cli = _commander_js_extra_typings.program.name("rollipop").version(version);
289
+ cli.addCommand(command$1);
290
+ cli.addCommand(command);
291
+ cli.parse(argv);
292
+ }
293
+
294
+ //#endregion
295
+ //#region src/index.ts
296
+ const Rollipop = Object.freeze({
297
+ runBuild,
298
+ runServer,
299
+ loadConfig: _rollipop_core.loadConfig,
300
+ resetCache: _rollipop_common.resetCache
301
+ });
302
+
303
+ //#endregion
304
+ Object.defineProperty(exports, 'DEFAULT_HOST', {
305
+ enumerable: true,
306
+ get: function () {
307
+ return _rollipop_dev_server.DEFAULT_HOST;
308
+ }
309
+ });
310
+ Object.defineProperty(exports, 'DEFAULT_PORT', {
311
+ enumerable: true,
312
+ get: function () {
313
+ return _rollipop_dev_server.DEFAULT_PORT;
314
+ }
315
+ });
316
+ Object.defineProperty(exports, 'PluginUtils', {
317
+ enumerable: true,
318
+ get: function () {
319
+ return _rollipop_core.PluginUtils;
320
+ }
321
+ });
322
+ exports.Rollipop = Rollipop;
323
+ Object.defineProperty(exports, 'cli', {
324
+ enumerable: true,
325
+ get: function () {
326
+ return cli_exports;
327
+ }
328
+ });
329
+ Object.defineProperty(exports, 'defineConfig', {
330
+ enumerable: true,
331
+ get: function () {
332
+ return _rollipop_core.defineConfig;
333
+ }
334
+ });
335
+ Object.defineProperty(exports, 'mergeConfig', {
336
+ enumerable: true,
337
+ get: function () {
338
+ return _rollipop_core.mergeConfig;
339
+ }
340
+ });
@@ -0,0 +1,26 @@
1
+ import { resetCache } from "@rollipop/common";
2
+ import { BuildOptions, BuildOptions as BuildOptions$1, Config, DefaultConfig, Plugin, PluginUtils, ReactNativeConfig, ReportableEvent, Reporter, ResolvedConfig, ResolvedConfig as ResolvedConfig$1, ResolverConfig, RolldownConfig, SerializerConfig, TerminalConfig, TransformerConfig, WatcherConfig, defineConfig, loadConfig, mergeConfig, rolldown } from "@rollipop/core";
3
+ import { DEFAULT_HOST, DEFAULT_PORT, DevServer, DevServer as DevServer$1, ServerOptions, ServerOptions as ServerOptions$1 } from "@rollipop/dev-server";
4
+
5
+ //#region rolldown:runtime
6
+ //#endregion
7
+ //#region src/run-build.d.ts
8
+ declare function runBuild(config: ResolvedConfig$1, options: BuildOptions$1): Promise<rolldown.OutputChunk>;
9
+ //#endregion
10
+ //#region src/run-server.d.ts
11
+ declare function runServer(config: ResolvedConfig$1, options: ServerOptions$1): Promise<DevServer$1>;
12
+ declare namespace cli_d_exports {
13
+ export { run };
14
+ }
15
+ declare function run(argv: string[]): void;
16
+ //#endregion
17
+ //#region src/index.d.ts
18
+ interface Rollipop {
19
+ readonly runBuild: typeof runBuild;
20
+ readonly runServer: typeof runServer;
21
+ readonly loadConfig: typeof loadConfig;
22
+ readonly resetCache: typeof resetCache;
23
+ }
24
+ declare const Rollipop: Rollipop;
25
+ //#endregion
26
+ export { type BuildOptions, type Config, DEFAULT_HOST, DEFAULT_PORT, type DefaultConfig, type DevServer, type Plugin, PluginUtils, type ReactNativeConfig, type ReportableEvent, type Reporter, type ResolvedConfig, type ResolverConfig, type RolldownConfig, Rollipop, type SerializerConfig, type ServerOptions, type TerminalConfig, type TransformerConfig, type WatcherConfig, cli_d_exports as cli, defineConfig, mergeConfig };
@@ -0,0 +1,24 @@
1
+ import { resetCache } from "@rollipop/common";
2
+ import { BuildOptions, BuildOptions as BuildOptions$1, Config, DefaultConfig, Plugin, PluginUtils, ReactNativeConfig, ReportableEvent, Reporter, ResolvedConfig, ResolvedConfig as ResolvedConfig$1, ResolverConfig, RolldownConfig, SerializerConfig, TerminalConfig, TransformerConfig, WatcherConfig, defineConfig, loadConfig, mergeConfig, rolldown } from "@rollipop/core";
3
+ import { DEFAULT_HOST, DEFAULT_PORT, DevServer, DevServer as DevServer$1, ServerOptions, ServerOptions as ServerOptions$1 } from "@rollipop/dev-server";
4
+
5
+ //#region src/run-build.d.ts
6
+ declare function runBuild(config: ResolvedConfig$1, options: BuildOptions$1): Promise<rolldown.OutputChunk>;
7
+ //#endregion
8
+ //#region src/run-server.d.ts
9
+ declare function runServer(config: ResolvedConfig$1, options: ServerOptions$1): Promise<DevServer$1>;
10
+ declare namespace cli_d_exports {
11
+ export { run };
12
+ }
13
+ declare function run(argv: string[]): void;
14
+ //#endregion
15
+ //#region src/index.d.ts
16
+ interface Rollipop {
17
+ readonly runBuild: typeof runBuild;
18
+ readonly runServer: typeof runServer;
19
+ readonly loadConfig: typeof loadConfig;
20
+ readonly resetCache: typeof resetCache;
21
+ }
22
+ declare const Rollipop: Rollipop;
23
+ //#endregion
24
+ export { type BuildOptions, type Config, DEFAULT_HOST, DEFAULT_PORT, type DefaultConfig, type DevServer, type Plugin, PluginUtils, type ReactNativeConfig, type ReportableEvent, type Reporter, type ResolvedConfig, type ResolverConfig, type RolldownConfig, Rollipop, type SerializerConfig, type ServerOptions, type TerminalConfig, type TransformerConfig, type WatcherConfig, cli_d_exports as cli, defineConfig, mergeConfig };
package/dist/index.js ADDED
@@ -0,0 +1,264 @@
1
+ import { t as __export } from "./chunk-BAz01cYq.js";
2
+ import { Logger, Logo, chalk, loadSettings, resetCache, saveSettings } from "@rollipop/common";
3
+ import { Bundler, PluginUtils, defineConfig, loadConfig, mergeConfig } from "@rollipop/core";
4
+ import { DEFAULT_HOST, DEFAULT_HOST as DEFAULT_HOST$1, DEFAULT_PORT, DEFAULT_PORT as DEFAULT_PORT$1, createDevServer } from "@rollipop/dev-server";
5
+ import { Command, program } from "@commander-js/extra-typings";
6
+ import { merge, noop, throttle } from "es-toolkit";
7
+ import { select } from "@inquirer/prompts";
8
+ import readline from "node:readline";
9
+ import { ReadStream } from "node:tty";
10
+
11
+ //#region src/run-build.ts
12
+ async function runBuild(config, options) {
13
+ return await new Bundler(config).build(options);
14
+ }
15
+
16
+ //#endregion
17
+ //#region src/run-server.ts
18
+ async function runServer(config, options) {
19
+ const { port, host } = options;
20
+ const devServer = await createDevServer(config, options);
21
+ await devServer.instance.listen({
22
+ port,
23
+ host
24
+ });
25
+ return devServer;
26
+ }
27
+
28
+ //#endregion
29
+ //#region package.json
30
+ var version = "0.1.0-alpha.1";
31
+
32
+ //#endregion
33
+ //#region src/node/constants.ts
34
+ const UNSUPPORTED_OPTION_DESCRIPTION = "Unsupported option";
35
+
36
+ //#endregion
37
+ //#region src/node/logger.ts
38
+ const logger = new Logger("cli");
39
+
40
+ //#endregion
41
+ //#region src/node/utils.ts
42
+ function parseBoolean(value) {
43
+ return value === "true" || value === "1";
44
+ }
45
+
46
+ //#endregion
47
+ //#region src/node/commands/bundle/index.ts
48
+ const command$1 = new Command("bundle").description("Build the bundle for the provided JavaScript entry file.").option("--config <string>", "Path to the CLI configuration file").requiredOption("--entry-file <path>", "Path to the root JS file, either absolute or relative to JS root").requiredOption("--bundle-output <string>", "File name where to store the resulting bundle, ex. /tmp/groups.bundle").option("--platform <string>", "Either \"ios\" or \"android\"", "ios").option("--dev [boolean]", "If false, warnings are disabled and the bundle is minified", parseBoolean, true).option("--minify [boolean]", "Allows overriding whether bundle is minified. This defaults to false if dev is true, and true if dev is false. Disabling minification can be useful for speeding up production builds for testing purposes.", parseBoolean, false).option("--sourcemap-output <string>", "File name where to store the sourcemap file for resulting bundle, ex. /tmp/groups.map").option("--sourcemap-sources-root <string>", "Path to make sourcemap's sources entries relative to, ex. /root/dir").option("--sourcemap-use-absolute-path", "Report SourceMapURL using its full path", false).option("--assets-dest <string>", "Directory name where to store assets referenced in the bundle").option("--cache [boolean]", "If false, the bundler will not cache anything", parseBoolean, true).option("--reset-cache", "Removes cached files").option("--transformer <string>", UNSUPPORTED_OPTION_DESCRIPTION).option("--bundle-encoding <string>", UNSUPPORTED_OPTION_DESCRIPTION, "utf8").option("--max-workers <number>", UNSUPPORTED_OPTION_DESCRIPTION, Number, 0).option("--unstable-transform-profile <string>", UNSUPPORTED_OPTION_DESCRIPTION, "default").option("--asset-catalog-dest [string]", UNSUPPORTED_OPTION_DESCRIPTION).option("--read-global-cache", UNSUPPORTED_OPTION_DESCRIPTION).option("--resolver-option <string...>", UNSUPPORTED_OPTION_DESCRIPTION).action(async (options) => {
49
+ const cwd = process.cwd();
50
+ const config = await Rollipop.loadConfig({
51
+ cwd,
52
+ configFile: options.config,
53
+ context: { command: "bundle" }
54
+ });
55
+ if (options.resetCache) {
56
+ Rollipop.resetCache(cwd);
57
+ logger.info("The transform cache was reset");
58
+ }
59
+ if (options.entryFile) config.entry = options.entryFile;
60
+ await Rollipop.runBuild(config, {
61
+ platform: options.platform,
62
+ dev: options.dev,
63
+ minify: options.minify,
64
+ cache: options.cache,
65
+ outfile: options.bundleOutput,
66
+ sourcemap: options.sourcemapOutput,
67
+ assetsDir: options.assetsDest
68
+ });
69
+ });
70
+
71
+ //#endregion
72
+ //#region src/node/debugger.ts
73
+ var DebuggerOpener = class DebuggerOpener {
74
+ static MAX_TARGETS_SHOWN = 10;
75
+ _prompting = false;
76
+ settings;
77
+ static setAutoOpenEnabled(projectRoot, enabled) {
78
+ saveSettings(projectRoot, { devtools: { autoOpen: enabled } });
79
+ }
80
+ constructor(projectRoot, serverUrl) {
81
+ this.projectRoot = projectRoot;
82
+ this.serverUrl = serverUrl;
83
+ this.settings = loadSettings(projectRoot);
84
+ }
85
+ async openDebuggerForTarget(target) {
86
+ logger.debug(`Opening debugger for target: ${target.id}`);
87
+ try {
88
+ await fetch(new URL("/open-debugger?target=" + encodeURIComponent(target.id), this.serverUrl), { method: "POST" });
89
+ } catch (error) {
90
+ logger.error(`Failed to open debugger for ${target.title}`);
91
+ logger.debug("Reason", error);
92
+ }
93
+ }
94
+ async open() {
95
+ logger.debug("Fetching available debugging targets...");
96
+ const response = await fetch(new URL("/json/list", this.serverUrl), { method: "POST" });
97
+ if (response.status !== 200) throw new Error(`Unexpected status code: ${response.status}`);
98
+ const targets = await response.json();
99
+ if (!Array.isArray(targets)) throw new Error("Unexpected response format");
100
+ logger.debug(`Found ${targets.length} debugging targets:`);
101
+ if (targets.length === 0) logger.warn("No connected targets");
102
+ else if (targets.length === 1) {
103
+ const target = targets[0];
104
+ await this.openDebuggerForTarget(target);
105
+ } else {
106
+ if (targets.length > DebuggerOpener.MAX_TARGETS_SHOWN) logger.warn(`More than ${DebuggerOpener.MAX_TARGETS_SHOWN} debug targets available, showing the first ${DebuggerOpener.MAX_TARGETS_SHOWN}.`);
107
+ const slicedTargets = targets.slice(0, DebuggerOpener.MAX_TARGETS_SHOWN);
108
+ Logger.block();
109
+ this._prompting = true;
110
+ try {
111
+ const targetIndex = await select({
112
+ message: "Multiple debug targets available, please select:",
113
+ choices: slicedTargets.map((target, index) => ({
114
+ value: index,
115
+ name: `${target.title} (${target.description})`
116
+ }))
117
+ });
118
+ await this.openDebuggerForTarget(slicedTargets[targetIndex]);
119
+ } catch {} finally {
120
+ Logger.unblock();
121
+ this._prompting = false;
122
+ }
123
+ }
124
+ }
125
+ isPrompting() {
126
+ return this._prompting;
127
+ }
128
+ isAutoOpenEnabled() {
129
+ return this.settings.devtools?.autoOpen ?? false;
130
+ }
131
+ setAutoOpenEnabled(enabled) {
132
+ const newSettings = this.settings = merge(this.settings, { devtools: { autoOpen: enabled } });
133
+ saveSettings(this.projectRoot, newSettings);
134
+ }
135
+ };
136
+
137
+ //#endregion
138
+ //#region src/node/commands/start/setup-interactive-mode.ts
139
+ const CTRL_C = "";
140
+ const CTRL_D = "";
141
+ const BROADCAST_THROTTLE_DELAY = 500;
142
+ const SUPPORTED_COMMANDS = {
143
+ r: {
144
+ description: "Reload app",
145
+ handler: throttle((broadcast) => {
146
+ logger.info("Reloading app...");
147
+ broadcast("reload");
148
+ }, BROADCAST_THROTTLE_DELAY)
149
+ },
150
+ j: { description: "Open DevTools" },
151
+ d: {
152
+ description: "Show developer menu",
153
+ handler: throttle((broadcast) => {
154
+ logger.info("Showing developer menu...");
155
+ broadcast("devMenu");
156
+ }, BROADCAST_THROTTLE_DELAY)
157
+ }
158
+ };
159
+ function setupInteractiveMode(options) {
160
+ const { broadcast, debuggerOpener } = options;
161
+ if (!(process.stdin.isTTY && process.stdin instanceof ReadStream)) {
162
+ logger.warn("Interactive mode is not supported in non-interactive environments");
163
+ return;
164
+ }
165
+ readline.emitKeypressEvents(process.stdin);
166
+ process.stdin.setRawMode(true);
167
+ process.stdin.on("keypress", (_, key) => {
168
+ const { ctrl, shift } = key;
169
+ const sequence = key.sequence?.toLowerCase();
170
+ if (sequence == null || debuggerOpener.isPrompting()) return;
171
+ if (ctrl && [CTRL_C, CTRL_D].includes(sequence)) {
172
+ process.stdin.setRawMode(false);
173
+ process.stdin.pause();
174
+ process.emit("SIGINT");
175
+ process.exit(0);
176
+ }
177
+ if (shift && sequence.toLowerCase() === "d") {
178
+ const newAutoOpenEnabled = !debuggerOpener.isAutoOpenEnabled();
179
+ debuggerOpener.setAutoOpenEnabled(newAutoOpenEnabled);
180
+ logger.info(`Auto opening developer tools: ${chalk.bold(newAutoOpenEnabled ? "enabled" : "disabled")}`);
181
+ return;
182
+ }
183
+ switch (sequence) {
184
+ case "r":
185
+ case "d":
186
+ SUPPORTED_COMMANDS[sequence].handler(broadcast);
187
+ break;
188
+ case "j":
189
+ debuggerOpener.open().catch(() => {
190
+ logger.error("Failed to open debugger");
191
+ });
192
+ break;
193
+ }
194
+ });
195
+ console.log();
196
+ Object.entries(SUPPORTED_COMMANDS).forEach(([key, command$2]) => {
197
+ const keyLabel$1 = `» Press ${chalk.bold(key)} │`;
198
+ console.log(`${keyLabel$1} ${command$2.description}`);
199
+ });
200
+ const keyLabel = `» ${chalk.bold("shift+d")} │`;
201
+ const autoOpenStatus = `(${debuggerOpener.isAutoOpenEnabled() ? "enabled" : "disabled"})`;
202
+ console.log(`${keyLabel} Toggle auto opening developer tools on startup ${`${chalk.gray.bold(autoOpenStatus)}`}`);
203
+ }
204
+
205
+ //#endregion
206
+ //#region src/node/commands/start/index.ts
207
+ const command = new Command("start").description("Start the React Native development server.").option("--config <string>", "Path to the CLI configuration file").option("--host <string>", "Host to start the development server on", DEFAULT_HOST$1).option("--port <number>", "Port to start the development server on", Number, DEFAULT_PORT$1).option("--projectRoot <path>", "Path to a custom project root", "").option("--reset-cache", "Removes cached files").option("--https", "Enables https connections to the server").option("--key <path>", "Path to custom SSL key").option("--cert <path>", "Path to custom SSL cert").option("--no-interactive", "Disables interactive mode").option("--client-logs", "Enable plain text JavaScript log streaming for all connected apps. This feature is deprecated and will be removed in future.", false).option("--watchFolders <list>", UNSUPPORTED_OPTION_DESCRIPTION).option("--assetPlugins <list>", UNSUPPORTED_OPTION_DESCRIPTION).option("--sourceExts <list>", UNSUPPORTED_OPTION_DESCRIPTION).option("--max-workers <list>", UNSUPPORTED_OPTION_DESCRIPTION).option("--transformer", UNSUPPORTED_OPTION_DESCRIPTION).option("--custom-log-reporter-path", UNSUPPORTED_OPTION_DESCRIPTION).action(async (options) => {
208
+ const cwd = process.cwd();
209
+ const config = await Rollipop.loadConfig({
210
+ cwd,
211
+ configFile: options.config,
212
+ context: { command: "start" }
213
+ });
214
+ if (options.resetCache) {
215
+ Rollipop.resetCache(cwd);
216
+ logger.info("The transform cache was reset");
217
+ }
218
+ if (options.clientLogs === false) config.reporter = { update: noop };
219
+ let debuggerOpened = false;
220
+ const server = await Rollipop.runServer(config, {
221
+ projectRoot: cwd,
222
+ port: options.port,
223
+ host: options.host,
224
+ https: options.https,
225
+ key: options.key,
226
+ cert: options.cert,
227
+ onDeviceConnected: () => {
228
+ if (debuggerOpened === false && debuggerOpener.isAutoOpenEnabled()) {
229
+ debuggerOpener.open().catch((error) => {
230
+ logger.error("Failed to open debugger", { error });
231
+ });
232
+ debuggerOpened = true;
233
+ }
234
+ }
235
+ });
236
+ const debuggerOpener = new DebuggerOpener(cwd, server.instance.listeningOrigin);
237
+ if (options.interactive) setupInteractiveMode({
238
+ broadcast: (message, params) => server.message.broadcast(message, params),
239
+ debuggerOpener
240
+ });
241
+ });
242
+
243
+ //#endregion
244
+ //#region src/node/cli.ts
245
+ var cli_exports = /* @__PURE__ */ __export({ run: () => run });
246
+ function run(argv) {
247
+ Logo.printOnce();
248
+ const cli = program.name("rollipop").version(version);
249
+ cli.addCommand(command$1);
250
+ cli.addCommand(command);
251
+ cli.parse(argv);
252
+ }
253
+
254
+ //#endregion
255
+ //#region src/index.ts
256
+ const Rollipop = Object.freeze({
257
+ runBuild,
258
+ runServer,
259
+ loadConfig,
260
+ resetCache
261
+ });
262
+
263
+ //#endregion
264
+ export { DEFAULT_HOST, DEFAULT_PORT, PluginUtils, Rollipop, cli_exports as cli, defineConfig, mergeConfig };
package/package.json CHANGED
@@ -1,6 +1,25 @@
1
1
  {
2
2
  "name": "rollipop",
3
- "version": "0.0.0",
3
+ "version": "0.1.0-alpha.1",
4
+ "type": "module",
5
+ "bin": "./bin/index.js",
6
+ "exports": {
7
+ ".": {
8
+ "import": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ },
12
+ "require": {
13
+ "types": "./dist/index.d.cts",
14
+ "default": "./dist/index.cjs"
15
+ }
16
+ },
17
+ "./package.json": "./package.json"
18
+ },
19
+ "files": [
20
+ "bin",
21
+ "dist"
22
+ ],
4
23
  "repository": {
5
24
  "type": "git",
6
25
  "url": "git+https://github.com/leegeunhyeok/rollipop.git",
@@ -11,5 +30,23 @@
11
30
  "bugs": {
12
31
  "url": "https://github.com/leegeunhyeok/rollipop/issues"
13
32
  },
14
- "homepage": "https://github.com/leegeunhyeok/rollipop#readme"
33
+ "homepage": "https://github.com/leegeunhyeok/rollipop#readme",
34
+ "scripts": {
35
+ "prepack": "yarn build",
36
+ "typecheck": "tsc --noEmit",
37
+ "build": "tsdown"
38
+ },
39
+ "dependencies": {
40
+ "@commander-js/extra-typings": "^14.0.0",
41
+ "@inquirer/prompts": "^8.1.0",
42
+ "@rollipop/common": "workspace:*",
43
+ "@rollipop/core": "workspace:*",
44
+ "@rollipop/dev-server": "workspace:*",
45
+ "commander": "^14.0.2",
46
+ "es-toolkit": "catalog:"
47
+ },
48
+ "devDependencies": {
49
+ "tsdown": "catalog:",
50
+ "typescript": "catalog:"
51
+ }
15
52
  }