rollipop 1.0.0-alpha.23 → 1.0.0-alpha.25

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.
Files changed (97) hide show
  1. package/dist/common/code.js +9 -5
  2. package/dist/common/env.js +2 -2
  3. package/dist/common/progress-bar.js +1 -1
  4. package/dist/config/defaults.d.ts +14 -11
  5. package/dist/config/defaults.js +8 -3
  6. package/dist/config/index.d.ts +2 -2
  7. package/dist/config/load-config.js +4 -2
  8. package/dist/config/types.d.ts +37 -9
  9. package/dist/constants.d.ts +5 -3
  10. package/dist/constants.js +11 -61
  11. package/dist/core/analyze.js +14 -0
  12. package/dist/core/assets.d.ts +1 -1
  13. package/dist/core/bundler.d.ts +2 -1
  14. package/dist/core/bundler.js +2 -2
  15. package/dist/core/plugins/analyze-plugin.d.ts +11 -0
  16. package/dist/core/plugins/analyze-plugin.js +57 -0
  17. package/dist/core/plugins/entry-plugin.d.ts +10 -0
  18. package/dist/core/plugins/entry-plugin.js +28 -0
  19. package/dist/core/plugins/index.d.ts +3 -2
  20. package/dist/core/plugins/index.js +4 -2
  21. package/dist/core/rolldown.js +85 -31
  22. package/dist/core/settings.js +2 -2
  23. package/dist/core/types.d.ts +2 -1
  24. package/dist/hmr-runtime.iife.js +54 -38
  25. package/dist/index.d.ts +4 -4
  26. package/dist/internal/react-native.js +6 -5
  27. package/dist/node/cli-utils.js +12 -2
  28. package/dist/node/cli.js +4 -2
  29. package/dist/node/commands/agent/action.js +11 -1
  30. package/dist/node/commands/bundle/action.js +2 -1
  31. package/dist/node/commands/skills/action.js +49 -0
  32. package/dist/node/commands/skills/command.js +16 -0
  33. package/dist/node/commands/start/setup-interactive-mode.js +1 -1
  34. package/dist/node/types.d.ts +6 -0
  35. package/dist/node/utils.js +2 -2
  36. package/dist/package.js +1 -1
  37. package/dist/runtime.js +4 -4
  38. package/dist/server/bundle.js +2 -2
  39. package/dist/server/bundler-pool.d.ts +9 -2
  40. package/dist/server/bundler-pool.js +46 -7
  41. package/dist/server/create-dev-server.js +22 -17
  42. package/dist/server/events/types.d.ts +4 -4
  43. package/dist/server/mcp/context.js +2 -2
  44. package/dist/server/mcp/server.js +1 -1
  45. package/dist/server/mcp/tools/build-info.js +1 -23
  46. package/dist/server/mcp/tools/{device-diagnostics.js → client-diagnostics.js} +19 -19
  47. package/dist/server/mcp/tools/index.js +5 -5
  48. package/dist/server/middlewares/dashboard.js +60 -0
  49. package/dist/server/middlewares/sse.js +2 -0
  50. package/dist/server/middlewares/symbolicate.js +32 -8
  51. package/dist/server/rest/data.js +47 -0
  52. package/dist/server/rest/devtools-targets.js +25 -0
  53. package/dist/server/rest/domains/actions.js +24 -0
  54. package/dist/server/rest/domains/builds.js +37 -0
  55. package/dist/server/rest/domains/bundlers.js +30 -0
  56. package/dist/server/rest/domains/config.js +14 -0
  57. package/dist/server/rest/domains/dev-server.js +14 -0
  58. package/dist/server/rest/domains/devices.js +20 -0
  59. package/dist/server/rest/domains/feature-flags.js +14 -0
  60. package/dist/server/rest/domains/snapshot.js +14 -0
  61. package/dist/server/rest/index.js +56 -0
  62. package/dist/server/rest/response.js +9 -0
  63. package/dist/server/rest/serializers.js +74 -0
  64. package/dist/server/sse/adapter.js +6 -6
  65. package/dist/server/state/store.d.ts +46 -0
  66. package/dist/server/state/store.js +165 -0
  67. package/dist/server/types.d.ts +10 -5
  68. package/dist/storage/file-storage.d.ts +26 -0
  69. package/dist/storage/file-storage.js +49 -0
  70. package/dist/types/hmr.d.ts +1 -26
  71. package/dist/utils/build-options.d.ts +16 -0
  72. package/dist/utils/build-options.js +7 -6
  73. package/dist/utils/id.js +13 -3
  74. package/dist/utils/reset-cache.js +2 -2
  75. package/dist/utils/serialize.js +24 -1
  76. package/dist/utils/storage.js +4 -1
  77. package/dist/utils/transform.js +23 -0
  78. package/package.json +12 -5
  79. package/skills/build.md +31 -0
  80. package/skills/configuration.md +31 -0
  81. package/skills/core.md +31 -0
  82. package/skills/debugging.md +34 -0
  83. package/skills/dev-server.md +35 -0
  84. package/skills/migration.md +31 -0
  85. package/skills/plugins.md +37 -0
  86. package/skills/troubleshooting.md +36 -0
  87. package/src/runtime/hmr-runtime.ts +14 -22
  88. package/src/runtime/react-refresh-utils.ts +75 -5
  89. package/CHANGELOG.md +0 -204
  90. package/dist/common/constants.js +0 -5
  91. package/dist/common/types.d.ts +0 -10
  92. package/dist/core/fs/data.js +0 -9
  93. package/dist/core/fs/storage.d.ts +0 -15
  94. package/dist/core/fs/storage.js +0 -31
  95. package/dist/core/plugins/prelude-plugin.d.ts +0 -10
  96. package/dist/core/plugins/prelude-plugin.js +0 -23
  97. package/dist/utils/runtime-target.js +0 -9
@@ -1,21 +1,25 @@
1
- import { GLOBAL_IDENTIFIER } from "../constants.js";
2
1
  import { indent } from "../utils/string.js";
3
2
  import dedent from "dedent";
4
3
  //#region src/common/code.ts
4
+ const GLOBAL_OBJECT_EXPRESSION = [
5
+ `typeof globalThis !== 'undefined' ? globalThis`,
6
+ ` : typeof global !== 'undefined' ? global`,
7
+ ` : typeof window !== 'undefined' ? window`,
8
+ " : this"
9
+ ].join("");
5
10
  function asLiteral(value) {
6
11
  return JSON.stringify(value);
7
12
  }
8
13
  function nodeEnvironment(dev) {
9
14
  return dev ? "development" : "production";
10
15
  }
11
- function iife(body, path = "<unknown>") {
16
+ function iife(body) {
12
17
  const bodyPlaceholder = "__BODY__";
13
18
  return dedent`
14
- // ${path}
15
19
  (function (global) {
16
20
  ${bodyPlaceholder}
17
- })(${GLOBAL_IDENTIFIER});
18
- `.replace(bodyPlaceholder, indent(body, 1));
21
+ })(${GLOBAL_OBJECT_EXPRESSION});
22
+ `.replace(bodyPlaceholder, indent(body, 1, " ")).trim();
19
23
  }
20
24
  //#endregion
21
25
  export { asLiteral, iife, nodeEnvironment };
@@ -1,5 +1,5 @@
1
- import "./constants.js";
2
1
  //#region src/common/env.ts
2
+ const DEBUG_KEY = "rollipop";
3
3
  const TRUTHY_VALUES = [
4
4
  "yes",
5
5
  "on",
@@ -27,7 +27,7 @@ function parseDebugKeys() {
27
27
  let debugKeys = null;
28
28
  function isDebugEnabled() {
29
29
  if (debugKeys == null) debugKeys = parseDebugKeys();
30
- return debugKeys["rollipop"] ?? false;
30
+ return debugKeys[DEBUG_KEY] ?? false;
31
31
  }
32
32
  //#endregion
33
33
  export { isDebugEnabled };
@@ -15,7 +15,7 @@ const runningRenderer = { render(state, context) {
15
15
  const bg = chalk.white(BLOCK_CHAR);
16
16
  const fg = chalk.cyan(BLOCK_CHAR);
17
17
  const bar = range(BAR_LENGTH).map((n) => n < width ? fg : bg).join("");
18
- const progressLabel = unknownTotal ? chalk.gray("(calculating...)") : `(${progress.toFixed(2)}%)`;
18
+ const progressLabel = unknownTotal ? "" : `(${progress.toFixed(2)}%)`;
19
19
  const moduleCountLabel = unknownTotal ? `${current} modules` : `${current}/${total} modules`;
20
20
  return `${[
21
21
  chalk.cyan("●"),
@@ -1,5 +1,5 @@
1
1
  import { Reporter } from "../types.js";
2
- import { Config, DevModeConfig, OptimizationConfig, ReactNativeConfig } from "./types.js";
2
+ import { AnalyzerConfig, Config, DevModeConfig, OptimizationConfig, Polyfill, ReactNativeConfig } from "./types.js";
3
3
  import { PluginFlattenConfig } from "./merge-config.js";
4
4
 
5
5
  //#region src/config/defaults.d.ts
@@ -26,10 +26,7 @@ declare function getDefaultConfig(projectRoot: string, mode?: Config['mode']): P
26
26
  };
27
27
  serializer: {
28
28
  prelude: string[];
29
- polyfills: {
30
- type: "iife";
31
- code: string;
32
- }[];
29
+ polyfills: Polyfill[];
33
30
  };
34
31
  watcher: {
35
32
  skipWrite: true;
@@ -51,24 +48,30 @@ declare function getDefaultConfig(projectRoot: string, mode?: Config['mode']): P
51
48
  };
52
49
  assetRegistryPath: NonNullable<NonNullable<ReactNativeConfig>["assetRegistryPath"]>;
53
50
  hmrClientPath: NonNullable<NonNullable<ReactNativeConfig>["hmrClientPath"]>;
54
- globalIdentifiers: string[];
55
51
  };
56
52
  devMode: {
57
53
  hmr: NonNullable<DevModeConfig["hmr"]>;
58
54
  };
59
55
  reporter: Reporter;
56
+ analyzer: Required<AnalyzerConfig>;
60
57
  terminal: {
61
58
  status: "none" | "compat" | "progress" | undefined;
62
59
  };
63
60
  envDir: string;
64
- envFile: string;
65
- envPrefix: string;
66
- runtimeTarget: "hermes-v1";
61
+ envFile: NonNullable<Config["envFile"]>;
62
+ envPrefix: NonNullable<Config["envPrefix"]>;
63
+ runtimeTarget: NonNullable<Config["runtimeTarget"]>;
67
64
  experimental: {
68
65
  nativeTransformPipeline: boolean;
69
66
  };
70
67
  }>;
68
+ interface InternalConfig {
69
+ /**
70
+ * The path to the config file that was used to load the config.
71
+ */
72
+ configFile: string;
73
+ }
71
74
  type DefaultConfig = Awaited<ReturnType<typeof getDefaultConfig>>;
72
- type ResolvedConfig = DefaultConfig & PluginFlattenConfig;
75
+ type ResolvedConfig = DefaultConfig & PluginFlattenConfig & InternalConfig;
73
76
  //#endregion
74
- export { DefaultConfig, ResolvedConfig, getDefaultConfig };
77
+ export { DefaultConfig, InternalConfig, ResolvedConfig, getDefaultConfig };
@@ -1,6 +1,6 @@
1
1
  import { isDebugEnabled } from "../common/env.js";
2
2
  import { stripFlowTypes } from "../common/transformer.js";
3
- import { DEFAULT_ASSET_EXTENSIONS, DEFAULT_ASSET_REGISTRY_PATH, DEFAULT_ENV_FILE, DEFAULT_ENV_PREFIX, DEFAULT_HMR_CLIENT_PATH, DEFAULT_REACT_NATIVE_GLOBAL_IDENTIFIERS, DEFAULT_RESOLVER_ALIAS_FIELDS, DEFAULT_RESOLVER_CONDITION_NAMES, DEFAULT_RESOLVER_MAIN_FIELDS, DEFAULT_RUNTIME_TARGET, DEFAULT_SOURCE_EXTENSIONS } from "../constants.js";
3
+ import { DEFAULT_ANALYZE_FILE, DEFAULT_ANALYZE_REPORT_FILE, DEFAULT_ASSET_EXTENSIONS, DEFAULT_ASSET_REGISTRY_PATH, DEFAULT_ENV_FILE, DEFAULT_ENV_PREFIX, DEFAULT_HMR_CLIENT_PATH, DEFAULT_RESOLVER_ALIAS_FIELDS, DEFAULT_RESOLVER_CONDITION_NAMES, DEFAULT_RESOLVER_MAIN_FIELDS, DEFAULT_RUNTIME_TARGET, DEFAULT_SOURCE_EXTENSIONS } from "../constants.js";
4
4
  import { getInitializeCorePath, getPolyfillScriptPaths } from "../internal/react-native.js";
5
5
  import { resolvePackagePath } from "../utils/node-resolve.js";
6
6
  import { ClientLogReporter } from "../utils/reporters.js";
@@ -53,11 +53,16 @@ async function getDefaultConfig(projectRoot, mode) {
53
53
  */
54
54
  filter: { code: /\bcodegenNativeComponent</ } },
55
55
  assetRegistryPath: DEFAULT_ASSET_REGISTRY_PATH,
56
- hmrClientPath: DEFAULT_HMR_CLIENT_PATH,
57
- globalIdentifiers: DEFAULT_REACT_NATIVE_GLOBAL_IDENTIFIERS
56
+ hmrClientPath: DEFAULT_HMR_CLIENT_PATH
58
57
  },
59
58
  devMode: { hmr: true },
60
59
  reporter: new ClientLogReporter(),
60
+ analyzer: {
61
+ enabled: false,
62
+ analyzeFile: DEFAULT_ANALYZE_FILE,
63
+ reportFile: DEFAULT_ANALYZE_REPORT_FILE,
64
+ autoOpen: false
65
+ },
61
66
  terminal: { status: (() => {
62
67
  if (isDebugEnabled()) return "compat";
63
68
  if (process.stderr.isTTY) return "progress";
@@ -1,5 +1,5 @@
1
- import { BabelTransformConfig, CodegenConfig, Config, DevModeConfig, ExperimentalConfig, FlowConfig, HmrConfig, OptimizationConfig, PluginOption, Polyfill, PolyfillType, PolyfillWithCode, PolyfillWithPath, ReactNativeConfig, ResolverConfig, RolldownConfig, RollipopReactNativeFlowConfig, RollipopReactNativeWorkletsConfig, SerializerConfig, SwcTransformConfig, TerminalConfig, TransformRule, TransformerConfig, WatcherConfig } from "./types.js";
1
+ import { AnalyzerConfig, BabelTransformConfig, CodegenConfig, Config, DevModeConfig, ExperimentalConfig, FlowConfig, HmrConfig, OptimizationConfig, PluginOption, Polyfill, PolyfillOptions, PolyfillType, PolyfillWithCode, PolyfillWithPath, ReactNativeConfig, ResolverConfig, RolldownConfig, RollipopReactNativeFlowConfig, RollipopReactNativeWorkletsConfig, SerializerConfig, SwcTransformConfig, TerminalConfig, TransformRule, TransformerConfig, WatcherConfig } from "./types.js";
2
2
  import { PluginFlattenConfig, mergeConfig } from "./merge-config.js";
3
- import { DefaultConfig, ResolvedConfig, getDefaultConfig } from "./defaults.js";
3
+ import { DefaultConfig, InternalConfig, ResolvedConfig, getDefaultConfig } from "./defaults.js";
4
4
  import { DefineConfigContext, DynamicUserConfig, UserConfig, defineConfig } from "./define-config.js";
5
5
  import { LoadConfigOptions, flattenPluginOption, invokeConfigResolved, loadConfig, resolvePluginConfig } from "./load-config.js";
@@ -2,7 +2,7 @@ import { getDefaultConfig } from "./defaults.js";
2
2
  import { createPluginContext } from "../core/plugins/context.js";
3
3
  import { mergeConfig } from "./merge-config.js";
4
4
  import path from "node:path";
5
- import { omit } from "es-toolkit";
5
+ import { invariant, omit } from "es-toolkit";
6
6
  import * as c12 from "c12";
7
7
  //#region src/config/load-config.ts
8
8
  const CONFIG_FILE_NAME = "rollipop";
@@ -17,7 +17,7 @@ async function loadConfig(options = {}) {
17
17
  },
18
18
  rcFile: false
19
19
  };
20
- const { config: userConfig } = await c12.loadConfig(configFile ? {
20
+ const { config: userConfig, configFile: resolvedConfigFile } = await c12.loadConfig(configFile ? {
21
21
  configFile: path.resolve(cwd, configFile),
22
22
  configFileRequired: true
23
23
  } : {
@@ -26,12 +26,14 @@ async function loadConfig(options = {}) {
26
26
  name: CONFIG_FILE_NAME,
27
27
  ...commonOptions
28
28
  });
29
+ invariant(resolvedConfigFile != null, "Failed to get resolved config file");
29
30
  const plugins = await flattenPluginOption(userConfig.plugins);
30
31
  const resolvedConfig = {
31
32
  ...await resolvePluginConfig(mergeConfig(defaultConfig, {
32
33
  ...userConfig,
33
34
  plugins
34
35
  }), plugins),
36
+ configFile: resolvedConfigFile,
35
37
  plugins
36
38
  };
37
39
  if (!path.isAbsolute(resolvedConfig.entry)) resolvedConfig.entry = path.resolve(resolvedConfig.root, resolvedConfig.entry);
@@ -57,6 +57,10 @@ interface Config {
57
57
  * Reporter configuration.
58
58
  */
59
59
  reporter?: Reporter;
60
+ /**
61
+ * Bundle analyzer configuration.
62
+ */
63
+ analyzer?: AnalyzerConfig;
60
64
  /**
61
65
  * Dev mode specific configuration. (for dev server)
62
66
  */
@@ -327,14 +331,17 @@ interface SerializerConfig {
327
331
  shimMissingExports?: rolldown.InputOptions['shimMissingExports'];
328
332
  }
329
333
  type Polyfill = string | PolyfillWithCode | PolyfillWithPath;
334
+ type PolyfillOptions = {
335
+ withTransform?: boolean;
336
+ };
330
337
  type PolyfillWithCode = {
331
338
  type: PolyfillType;
332
339
  code: string;
333
- };
340
+ } & PolyfillOptions;
334
341
  type PolyfillWithPath = {
335
342
  type: PolyfillType;
336
343
  path: string;
337
- };
344
+ } & PolyfillOptions;
338
345
  type PolyfillType = 'plain' | 'iife';
339
346
  type OptimizationConfig = rolldown.OptimizationOptions & {
340
347
  /**
@@ -419,12 +426,6 @@ interface ReactNativeConfig {
419
426
  * Defaults to: `react-native/Libraries/Utilities/HMRClient.js`
420
427
  */
421
428
  hmrClientPath?: string | ((root: string) => MaybePromise<string>);
422
- /**
423
- * Reserved global identifiers of React Native.
424
- *
425
- * Defaults to: Global identifier list of React Native 0.83
426
- */
427
- globalIdentifiers?: string[];
428
429
  }
429
430
  interface CodegenConfig {
430
431
  /**
@@ -432,6 +433,33 @@ interface CodegenConfig {
432
433
  */
433
434
  filter?: rolldown.HookFilter | TopLevelFilterExpression[];
434
435
  }
436
+ interface AnalyzerConfig {
437
+ /**
438
+ * Whether to enable the bundle analyzer.
439
+ *
440
+ * Defaults to: `false`
441
+ */
442
+ enabled?: boolean;
443
+ /**
444
+ * Output filename for the analysis data.
445
+ *
446
+ * Defaults to: `analyze-data.json`
447
+ */
448
+ analyzeFile?: string;
449
+ /**
450
+ * Output filename for the generated HTML report.
451
+ *
452
+ * Defaults to: `report.html`
453
+ */
454
+ reportFile?: string;
455
+ /**
456
+ * Automatically open the generated report in the browser.
457
+ * (Only available in `build` mode)
458
+ *
459
+ * Defaults to: `false`
460
+ */
461
+ autoOpen?: boolean;
462
+ }
435
463
  interface TerminalConfig {
436
464
  /**
437
465
  * Status of the terminal.
@@ -449,4 +477,4 @@ interface RolldownConfig {
449
477
  output?: rolldown.OutputOptions;
450
478
  }
451
479
  //#endregion
452
- export { BabelTransformConfig, CodegenConfig, Config, DevModeConfig, ExperimentalConfig, FlowConfig, HmrConfig, OptimizationConfig, PluginOption, Polyfill, PolyfillType, PolyfillWithCode, PolyfillWithPath, ReactNativeConfig, ResolverConfig, RolldownConfig, type RollipopReactNativeFlowConfig, type RollipopReactNativeWorkletsConfig, SerializerConfig, SwcTransformConfig, TerminalConfig, TransformRule, TransformerConfig, WatcherConfig };
480
+ export { AnalyzerConfig, BabelTransformConfig, CodegenConfig, Config, DevModeConfig, ExperimentalConfig, FlowConfig, HmrConfig, OptimizationConfig, PluginOption, Polyfill, PolyfillOptions, PolyfillType, PolyfillWithCode, PolyfillWithPath, ReactNativeConfig, ResolverConfig, RolldownConfig, type RollipopReactNativeFlowConfig, type RollipopReactNativeWorkletsConfig, SerializerConfig, SwcTransformConfig, TerminalConfig, TransformRule, TransformerConfig, WatcherConfig };
@@ -1,5 +1,5 @@
1
1
  declare namespace constants_d_exports {
2
- export { DEFAULT_ASSET_EXTENSIONS, DEFAULT_ASSET_REGISTRY_PATH, DEFAULT_ENV_FILE, DEFAULT_ENV_PREFIX, DEFAULT_HMR_CLIENT_PATH, DEFAULT_IMAGE_EXTENSIONS, DEFAULT_REACT_NATIVE_GLOBAL_IDENTIFIERS, DEFAULT_RESOLVER_ALIAS_FIELDS, DEFAULT_RESOLVER_CONDITION_NAMES, DEFAULT_RESOLVER_MAIN_FIELDS, DEFAULT_RUNTIME_TARGET, DEFAULT_SOURCE_EXTENSIONS, GLOBAL_IDENTIFIER, IMAGE_EXTENSIONS, ROLLIPOP_VERSION };
2
+ export { DEFAULT_ANALYZE_FILE, DEFAULT_ANALYZE_REPORT_FILE, DEFAULT_ASSET_EXTENSIONS, DEFAULT_ASSET_REGISTRY_PATH, DEFAULT_ENV_FILE, DEFAULT_ENV_PREFIX, DEFAULT_HMR_CLIENT_PATH, DEFAULT_IMAGE_EXTENSIONS, DEFAULT_RESOLVER_ALIAS_FIELDS, DEFAULT_RESOLVER_CONDITION_NAMES, DEFAULT_RESOLVER_MAIN_FIELDS, DEFAULT_RUNTIME_TARGET, DEFAULT_SOURCE_EXTENSIONS, IMAGE_EXTENSIONS, ROLLIPOP_VERSION, ROLLIPOP_VIRTUAL_ENTRY_ID, ROLLIPOP_VIRTUAL_PREFIX };
3
3
  }
4
4
  /**
5
5
  * @see `vite.config.ts`
@@ -8,7 +8,8 @@ declare global {
8
8
  var __ROLLIPOP_VERSION__: string;
9
9
  }
10
10
  declare const ROLLIPOP_VERSION: string;
11
- declare const GLOBAL_IDENTIFIER = "global";
11
+ declare const ROLLIPOP_VIRTUAL_PREFIX = "\0rollipop/";
12
+ declare const ROLLIPOP_VIRTUAL_ENTRY_ID = "\0rollipop/entry";
12
13
  /**
13
14
  * @see {@link https://github.com/facebook/metro/blob/0.81.x/docs/Configuration.md#resolvermainfields}
14
15
  */
@@ -27,9 +28,10 @@ declare const IMAGE_EXTENSIONS: string[];
27
28
  declare const DEFAULT_ASSET_EXTENSIONS: string[];
28
29
  declare const DEFAULT_ASSET_REGISTRY_PATH = "react-native/Libraries/Image/AssetRegistry.js";
29
30
  declare const DEFAULT_HMR_CLIENT_PATH = "react-native/Libraries/Utilities/HMRClient.js";
30
- declare const DEFAULT_REACT_NATIVE_GLOBAL_IDENTIFIERS: string[];
31
31
  declare const DEFAULT_ENV_PREFIX = "ROLLIPOP_";
32
32
  declare const DEFAULT_ENV_FILE = ".env";
33
33
  declare const DEFAULT_RUNTIME_TARGET = "hermes-v1";
34
+ declare const DEFAULT_ANALYZE_FILE = "analyze-data.json";
35
+ declare const DEFAULT_ANALYZE_REPORT_FILE = "report.html";
34
36
  //#endregion
35
37
  export { constants_d_exports };
package/dist/constants.js CHANGED
@@ -1,24 +1,27 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.js";
2
2
  //#region src/constants.ts
3
3
  var constants_exports = /* @__PURE__ */ __exportAll({
4
+ DEFAULT_ANALYZE_FILE: () => DEFAULT_ANALYZE_FILE,
5
+ DEFAULT_ANALYZE_REPORT_FILE: () => DEFAULT_ANALYZE_REPORT_FILE,
4
6
  DEFAULT_ASSET_EXTENSIONS: () => DEFAULT_ASSET_EXTENSIONS,
5
7
  DEFAULT_ASSET_REGISTRY_PATH: () => DEFAULT_ASSET_REGISTRY_PATH,
6
8
  DEFAULT_ENV_FILE: () => DEFAULT_ENV_FILE,
7
9
  DEFAULT_ENV_PREFIX: () => DEFAULT_ENV_PREFIX,
8
10
  DEFAULT_HMR_CLIENT_PATH: () => DEFAULT_HMR_CLIENT_PATH,
9
11
  DEFAULT_IMAGE_EXTENSIONS: () => DEFAULT_IMAGE_EXTENSIONS,
10
- DEFAULT_REACT_NATIVE_GLOBAL_IDENTIFIERS: () => DEFAULT_REACT_NATIVE_GLOBAL_IDENTIFIERS,
11
12
  DEFAULT_RESOLVER_ALIAS_FIELDS: () => DEFAULT_RESOLVER_ALIAS_FIELDS,
12
13
  DEFAULT_RESOLVER_CONDITION_NAMES: () => DEFAULT_RESOLVER_CONDITION_NAMES,
13
14
  DEFAULT_RESOLVER_MAIN_FIELDS: () => DEFAULT_RESOLVER_MAIN_FIELDS,
14
15
  DEFAULT_RUNTIME_TARGET: () => DEFAULT_RUNTIME_TARGET,
15
16
  DEFAULT_SOURCE_EXTENSIONS: () => DEFAULT_SOURCE_EXTENSIONS,
16
- GLOBAL_IDENTIFIER: () => GLOBAL_IDENTIFIER,
17
17
  IMAGE_EXTENSIONS: () => IMAGE_EXTENSIONS,
18
- ROLLIPOP_VERSION: () => ROLLIPOP_VERSION
18
+ ROLLIPOP_VERSION: () => ROLLIPOP_VERSION,
19
+ ROLLIPOP_VIRTUAL_ENTRY_ID: () => ROLLIPOP_VIRTUAL_ENTRY_ID,
20
+ ROLLIPOP_VIRTUAL_PREFIX: () => ROLLIPOP_VIRTUAL_PREFIX
19
21
  });
20
- const ROLLIPOP_VERSION = "1.0.0-alpha.23";
21
- const GLOBAL_IDENTIFIER = "global";
22
+ const ROLLIPOP_VERSION = "1.0.0-alpha.25";
23
+ const ROLLIPOP_VIRTUAL_PREFIX = "\0rollipop/";
24
+ const ROLLIPOP_VIRTUAL_ENTRY_ID = `${ROLLIPOP_VIRTUAL_PREFIX}entry`;
22
25
  /**
23
26
  * @see {@link https://github.com/facebook/metro/blob/0.81.x/docs/Configuration.md#resolvermainfields}
24
27
  */
@@ -84,63 +87,10 @@ const DEFAULT_ASSET_EXTENSIONS = [
84
87
  ];
85
88
  const DEFAULT_ASSET_REGISTRY_PATH = "react-native/Libraries/Image/AssetRegistry.js";
86
89
  const DEFAULT_HMR_CLIENT_PATH = "react-native/Libraries/Utilities/HMRClient.js";
87
- const DEFAULT_REACT_NATIVE_GLOBAL_IDENTIFIERS = [
88
- GLOBAL_IDENTIFIER,
89
- "Promise",
90
- "regeneratorRuntime",
91
- "XMLHttpRequest",
92
- "FormData",
93
- "fetch",
94
- "Headers",
95
- "Request",
96
- "Response",
97
- "WebSocket",
98
- "Blob",
99
- "File",
100
- "FileReader",
101
- "URL",
102
- "URLSearchParams",
103
- "AbortController",
104
- "AbortSignal",
105
- "queueMicrotask",
106
- "setImmediate",
107
- "clearImmediate",
108
- "requestIdleCallback",
109
- "cancelIdleCallback",
110
- "setTimeout",
111
- "clearTimeout",
112
- "setInterval",
113
- "clearInterval",
114
- "requestAnimationFrame",
115
- "cancelAnimationFrame",
116
- "DOMRect",
117
- "DOMRectReadOnly",
118
- "DOMRectList",
119
- "HTMLCollection",
120
- "NodeList",
121
- "Node",
122
- "Document",
123
- "CharacterData",
124
- "Text",
125
- "Element",
126
- "HTMLElement",
127
- "IntersectionObserver",
128
- "MutationObserver",
129
- "MutationRecord",
130
- "EventCounts",
131
- "Performance",
132
- "PerformanceEntry",
133
- "PerformanceEventTiming",
134
- "PerformanceLongTaskTiming",
135
- "PerformanceMark",
136
- "PerformanceMeasure",
137
- "PerformanceObserver",
138
- "PerformanceObserverEntryList",
139
- "PerformanceResourceTiming",
140
- "TaskAttributionTiming"
141
- ];
142
90
  const DEFAULT_ENV_PREFIX = "ROLLIPOP_";
143
91
  const DEFAULT_ENV_FILE = ".env";
144
92
  const DEFAULT_RUNTIME_TARGET = "hermes-v1";
93
+ const DEFAULT_ANALYZE_FILE = "analyze-data.json";
94
+ const DEFAULT_ANALYZE_REPORT_FILE = "report.html";
145
95
  //#endregion
146
- export { DEFAULT_ASSET_EXTENSIONS, DEFAULT_ASSET_REGISTRY_PATH, DEFAULT_ENV_FILE, DEFAULT_ENV_PREFIX, DEFAULT_HMR_CLIENT_PATH, DEFAULT_REACT_NATIVE_GLOBAL_IDENTIFIERS, DEFAULT_RESOLVER_ALIAS_FIELDS, DEFAULT_RESOLVER_CONDITION_NAMES, DEFAULT_RESOLVER_MAIN_FIELDS, DEFAULT_RUNTIME_TARGET, DEFAULT_SOURCE_EXTENSIONS, GLOBAL_IDENTIFIER, IMAGE_EXTENSIONS, ROLLIPOP_VERSION, constants_exports };
96
+ export { DEFAULT_ANALYZE_FILE, DEFAULT_ANALYZE_REPORT_FILE, DEFAULT_ASSET_EXTENSIONS, DEFAULT_ASSET_REGISTRY_PATH, DEFAULT_ENV_FILE, DEFAULT_ENV_PREFIX, DEFAULT_HMR_CLIENT_PATH, DEFAULT_RESOLVER_ALIAS_FIELDS, DEFAULT_RESOLVER_CONDITION_NAMES, DEFAULT_RESOLVER_MAIN_FIELDS, DEFAULT_RUNTIME_TARGET, DEFAULT_SOURCE_EXTENSIONS, IMAGE_EXTENSIONS, ROLLIPOP_VERSION, ROLLIPOP_VIRTUAL_ENTRY_ID, ROLLIPOP_VIRTUAL_PREFIX, constants_exports };
@@ -0,0 +1,14 @@
1
+ import { FileStorage } from "../storage/file-storage.js";
2
+ import path from "node:path";
3
+ //#region src/core/analyze.ts
4
+ function getAnalyzeDirectory(projectRoot) {
5
+ return path.join(FileStorage.getPath(projectRoot), "analyze");
6
+ }
7
+ function getAnalyzeDataPath(projectRoot, bundlerId) {
8
+ return path.join(getAnalyzeDirectory(projectRoot), `${bundlerId}.json`);
9
+ }
10
+ function getAnalyzeReportPath(projectRoot, bundlerId) {
11
+ return path.join(getAnalyzeDirectory(projectRoot), `${bundlerId}.html`);
12
+ }
13
+ //#endregion
14
+ export { getAnalyzeDataPath, getAnalyzeReportPath };
@@ -52,7 +52,7 @@ interface ResolveScaledAssetsOptions {
52
52
  declare function resolveScaledAssets(options: ResolveScaledAssetsOptions): Promise<AssetData>;
53
53
  declare function platformSuffixPattern(context: AssetContext): string;
54
54
  declare function stripSuffix(assetPath: string, context: AssetContext): string;
55
- declare function getAssetPriority(assetPath: string, context: AssetContext): 0 | 3 | 2 | 1;
55
+ declare function getAssetPriority(assetPath: string, context: AssetContext): 3 | 2 | 1 | 0;
56
56
  interface GetSuffixedPathOptions {
57
57
  scale?: AssetScale;
58
58
  platform?: string;
@@ -1,4 +1,5 @@
1
1
  import { BuildOptions, DevEngine, DevEngineOptions } from "./types.js";
2
+ import { ResolvedBuildOptions } from "../utils/build-options.js";
2
3
  import { ResolvedConfig } from "../config/defaults.js";
3
4
  import * as rolldown from "@rollipop/rolldown";
4
5
 
@@ -6,7 +7,7 @@ import * as rolldown from "@rollipop/rolldown";
6
7
  declare class Bundler {
7
8
  private readonly config;
8
9
  static devEngine(config: ResolvedConfig, buildOptions: Omit<BuildOptions, 'dev' | 'outfile'>, devEngineOptions: DevEngineOptions): Promise<DevEngine>;
9
- static createId(config: ResolvedConfig, buildOptions: BuildOptions): string;
10
+ static createId(config: ResolvedConfig, buildOptions: ResolvedBuildOptions): string;
10
11
  private static createContext;
11
12
  constructor(config: ResolvedConfig);
12
13
  build(buildOptions: BuildOptions): Promise<rolldown.OutputChunk>;
@@ -1,7 +1,7 @@
1
+ import { FileStorage } from "../storage/file-storage.js";
1
2
  import { Logo } from "../common/logo.js";
2
3
  import { resolveBuildOptions } from "../utils/build-options.js";
3
4
  import { createId } from "../utils/id.js";
4
- import { FileStorage } from "./fs/storage.js";
5
5
  import { getOverrideOptions, getOverrideOptionsForDevServer, resolveRolldownOptions } from "./rolldown.js";
6
6
  import fs from "node:fs";
7
7
  import path from "node:path";
@@ -29,7 +29,7 @@ var Bundler = class Bundler {
29
29
  return devEngine;
30
30
  }
31
31
  static createId(config, buildOptions) {
32
- return createId(config, buildOptions);
32
+ return createId(config, resolveBuildOptions(config, buildOptions));
33
33
  }
34
34
  static createContext(buildType, config, buildOptions) {
35
35
  return {
@@ -0,0 +1,11 @@
1
+ import { BundlerContext } from "../types.js";
2
+ import { AnalyzerConfig } from "../../config/types.js";
3
+ import * as rolldown from "@rollipop/rolldown";
4
+
5
+ //#region src/core/plugins/analyze-plugin.d.ts
6
+ interface AnalyzePluginOptions extends Required<AnalyzerConfig> {
7
+ context: BundlerContext;
8
+ }
9
+ declare function analyzePlugin(options: AnalyzePluginOptions): rolldown.Plugin[] | null;
10
+ //#endregion
11
+ export { AnalyzePluginOptions, analyzePlugin };
@@ -0,0 +1,57 @@
1
+ import { getAnalyzeDataPath, getAnalyzeReportPath } from "../analyze.js";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import * as rolldownExperimental from "@rollipop/rolldown/experimental";
5
+ import open from "open";
6
+ import { generateReport } from "rolldown-analyzer/node";
7
+ //#region src/core/plugins/analyze-plugin.ts
8
+ function analyzePlugin(options) {
9
+ if (!options.enabled) return null;
10
+ const { analyzeFile, reportFile, autoOpen, context } = options;
11
+ return [rolldownExperimental.bundleAnalyzerPlugin({ fileName: analyzeFile }), {
12
+ name: "rollipop:analyze",
13
+ async generateBundle(outputOptions, output) {
14
+ const targetAsset = output[analyzeFile];
15
+ if (targetAsset?.type !== "asset") {
16
+ this.debug(`Analyzer plugin: No asset found for ${analyzeFile}`);
17
+ return;
18
+ }
19
+ const outDir = getOutDir(outputOptions);
20
+ let analyzeFilePath;
21
+ let reportFilePath;
22
+ if (outDir == null || context.buildType === "serve") {
23
+ analyzeFilePath = getAnalyzeDataPath(context.root, context.id);
24
+ reportFilePath = getAnalyzeReportPath(context.root, context.id);
25
+ } else {
26
+ analyzeFilePath = path.resolve(outDir, analyzeFile);
27
+ reportFilePath = path.resolve(outDir, reportFile);
28
+ }
29
+ fs.mkdirSync(path.dirname(analyzeFilePath), { recursive: true });
30
+ fs.mkdirSync(path.dirname(reportFilePath), { recursive: true });
31
+ fs.writeFileSync(analyzeFilePath, targetAsset.source);
32
+ await generateReport({
33
+ preset: "lite",
34
+ dataPath: analyzeFilePath,
35
+ filename: reportFilePath
36
+ });
37
+ if (context.buildType === "build") {
38
+ this.info(`Analysis data generated at '${analyzeFilePath}'`);
39
+ this.info(`Analysis report generated at '${reportFilePath}'`);
40
+ if (autoOpen) {
41
+ this.info(`Opening analysis report in your browser...`);
42
+ open(reportFilePath).catch((error) => {
43
+ this.warn("Failed to open analysis report automatically");
44
+ this.debug(error instanceof Error ? error.message : String(error));
45
+ });
46
+ }
47
+ }
48
+ }
49
+ }];
50
+ }
51
+ function getOutDir(options) {
52
+ if (options.dir) return options.dir;
53
+ if (options.file) return path.dirname(options.file);
54
+ return null;
55
+ }
56
+ //#endregion
57
+ export { analyzePlugin };
@@ -0,0 +1,10 @@
1
+ import * as rolldown from "@rollipop/rolldown";
2
+
3
+ //#region src/core/plugins/entry-plugin.d.ts
4
+ interface EntryPluginOptions {
5
+ entryPath: string;
6
+ preludePaths?: string[];
7
+ }
8
+ declare function entryPlugin(options: EntryPluginOptions): rolldown.Plugin;
9
+ //#endregion
10
+ export { EntryPluginOptions, entryPlugin };
@@ -0,0 +1,28 @@
1
+ import { ROLLIPOP_VIRTUAL_ENTRY_ID } from "../../constants.js";
2
+ import { exactRegex, id, include } from "@rollipop/rolldown/filter";
3
+ //#region src/core/plugins/entry-plugin.ts
4
+ const VIRTUAL_ENTRY_FILTER = [include(id(exactRegex(ROLLIPOP_VIRTUAL_ENTRY_ID)))];
5
+ function entryPlugin(options) {
6
+ const { entryPath, preludePaths = [] } = options;
7
+ const importStatements = [...preludePaths, entryPath].map((modulePath) => `import ${JSON.stringify(modulePath)};`).join("\n");
8
+ return {
9
+ name: "rollipop:entry",
10
+ resolveId: {
11
+ filter: VIRTUAL_ENTRY_FILTER,
12
+ handler() {
13
+ return ROLLIPOP_VIRTUAL_ENTRY_ID;
14
+ }
15
+ },
16
+ load: {
17
+ filter: VIRTUAL_ENTRY_FILTER,
18
+ handler() {
19
+ return {
20
+ code: importStatements,
21
+ moduleType: "js"
22
+ };
23
+ }
24
+ }
25
+ };
26
+ }
27
+ //#endregion
28
+ export { entryPlugin };
@@ -1,13 +1,14 @@
1
1
  import { ReactNativePluginOptions, reactNativePlugin } from "./react-native-plugin.js";
2
- import { PreludePluginOptions, preludePlugin } from "./prelude-plugin.js";
2
+ import { EntryPluginOptions, entryPlugin } from "./entry-plugin.js";
3
3
  import { BabelPluginOptions, babelPlugin } from "./babel-plugin.js";
4
4
  import { SwcPluginOptions, swcPlugin } from "./swc-plugin.js";
5
5
  import { ReporterPluginOptions, reporterPlugin } from "./reporter-plugin.js";
6
6
  import { DevServerPluginOptions, devServerPlugin } from "./dev-server-plugin.js";
7
+ import { AnalyzePluginOptions, analyzePlugin } from "./analyze-plugin.js";
7
8
 
8
9
  //#region src/core/plugins/index.d.ts
9
10
  declare namespace index_d_exports {
10
- export { BabelPluginOptions, DevServerPluginOptions, PreludePluginOptions, ReactNativePluginOptions, ReporterPluginOptions, SwcPluginOptions, babelPlugin as babel, devServerPlugin as devServer, preludePlugin as prelude, reactNativePlugin as reactNative, reporterPlugin as reporter, swcPlugin as swc };
11
+ export { AnalyzePluginOptions, BabelPluginOptions, DevServerPluginOptions, EntryPluginOptions, ReactNativePluginOptions, ReporterPluginOptions, SwcPluginOptions, analyzePlugin as analyze, babelPlugin as babel, devServerPlugin as devServer, entryPlugin as entry, reactNativePlugin as reactNative, reporterPlugin as reporter, swcPlugin as swc };
11
12
  }
12
13
  //#endregion
13
14
  export { index_d_exports };
@@ -1,15 +1,17 @@
1
1
  import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
2
2
  import { reactNativePlugin } from "./react-native-plugin.js";
3
- import { preludePlugin } from "./prelude-plugin.js";
3
+ import { entryPlugin } from "./entry-plugin.js";
4
4
  import { babelPlugin } from "./babel-plugin.js";
5
5
  import { swcPlugin } from "./swc-plugin.js";
6
6
  import { reporterPlugin } from "./reporter-plugin.js";
7
7
  import { devServerPlugin } from "./dev-server-plugin.js";
8
+ import { analyzePlugin } from "./analyze-plugin.js";
8
9
  //#region src/core/plugins/index.ts
9
10
  var plugins_exports = /* @__PURE__ */ __exportAll({
11
+ analyze: () => analyzePlugin,
10
12
  babel: () => babelPlugin,
11
13
  devServer: () => devServerPlugin,
12
- prelude: () => preludePlugin,
14
+ entry: () => entryPlugin,
13
15
  reactNative: () => reactNativePlugin,
14
16
  reporter: () => reporterPlugin,
15
17
  swc: () => swcPlugin