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.
Files changed (161) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/{chunk-DEq-mXcV.js → _virtual/_rolldown/runtime.js} +1 -1
  3. package/dist/commands.d.ts +2 -4
  4. package/dist/commands.js +10 -3957
  5. package/dist/common/code.js +21 -0
  6. package/dist/common/constants.js +5 -0
  7. package/dist/common/env.js +33 -0
  8. package/dist/common/logger.d.ts +34 -0
  9. package/dist/common/logger.js +82 -0
  10. package/dist/common/logo.js +54 -0
  11. package/dist/common/progress-bar.js +167 -0
  12. package/dist/common/transformer.js +13 -0
  13. package/dist/common/types.d.ts +10 -0
  14. package/dist/config/compose-override.js +18 -0
  15. package/dist/config/defaults.d.ts +74 -0
  16. package/dist/config/defaults.js +74 -0
  17. package/dist/config/define-config.d.ts +13 -0
  18. package/dist/config/define-config.js +6 -0
  19. package/dist/config/index.d.ts +5 -0
  20. package/dist/config/index.js +5 -0
  21. package/dist/config/load-config.d.ts +19 -0
  22. package/dist/config/load-config.js +73 -0
  23. package/dist/config/merge-config.d.ts +12 -0
  24. package/dist/config/merge-config.js +20 -0
  25. package/dist/config/types.d.ts +452 -0
  26. package/dist/constants.d.ts +35 -0
  27. package/dist/constants.js +146 -0
  28. package/dist/core/assets.d.ts +91 -0
  29. package/dist/core/assets.js +244 -0
  30. package/dist/core/bundler.d.ts +15 -0
  31. package/dist/core/bundler.js +80 -0
  32. package/dist/core/env.d.ts +11 -0
  33. package/dist/core/env.js +36 -0
  34. package/dist/core/fs/data.js +9 -0
  35. package/dist/core/fs/storage.d.ts +15 -0
  36. package/dist/core/fs/storage.js +31 -0
  37. package/dist/core/plugins/babel-plugin.d.ts +22 -0
  38. package/dist/core/plugins/babel-plugin.js +74 -0
  39. package/dist/core/plugins/context.d.ts +10 -0
  40. package/dist/core/plugins/context.js +24 -0
  41. package/dist/core/plugins/dev-server-plugin.d.ts +13 -0
  42. package/dist/core/plugins/dev-server-plugin.js +27 -0
  43. package/dist/core/plugins/index.d.ts +13 -0
  44. package/dist/core/plugins/index.js +18 -0
  45. package/dist/core/plugins/prelude-plugin.d.ts +10 -0
  46. package/dist/core/plugins/prelude-plugin.js +23 -0
  47. package/dist/core/plugins/react-native-plugin.d.ts +36 -0
  48. package/dist/core/plugins/react-native-plugin.js +81 -0
  49. package/dist/core/plugins/reporter-plugin.d.ts +11 -0
  50. package/dist/core/plugins/reporter-plugin.js +87 -0
  51. package/dist/core/plugins/shared/filters.js +5 -0
  52. package/dist/core/plugins/swc-plugin.d.ts +26 -0
  53. package/dist/core/plugins/swc-plugin.js +108 -0
  54. package/dist/core/plugins/types.d.ts +18 -0
  55. package/dist/core/plugins/utils/source.js +10 -0
  56. package/dist/core/plugins/utils/transform-utils.js +56 -0
  57. package/dist/core/rolldown.js +313 -0
  58. package/dist/core/settings.js +19 -0
  59. package/dist/core/types.d.ts +83 -0
  60. package/dist/filter.d.ts +1 -0
  61. package/dist/filter.js +2 -0
  62. package/dist/hmr-runtime.iife.js +5 -5
  63. package/dist/index.d.ts +24 -1221
  64. package/dist/index.js +19 -4029
  65. package/dist/internal/react-native.js +24 -0
  66. package/dist/logger.js +5 -0
  67. package/dist/node/cli-utils.d.ts +10 -0
  68. package/dist/node/cli-utils.js +28 -0
  69. package/dist/node/cli.d.ts +6 -0
  70. package/dist/node/cli.js +23 -0
  71. package/dist/node/commands/agent/action.js +91 -0
  72. package/dist/node/commands/agent/command.js +10 -0
  73. package/dist/node/commands/agent/index.js +2 -0
  74. package/dist/node/commands/bundle/action.js +33 -0
  75. package/dist/node/commands/bundle/command.js +96 -0
  76. package/dist/node/commands/bundle/index.js +2 -0
  77. package/dist/node/commands/start/action.js +37 -0
  78. package/dist/node/commands/start/command.js +93 -0
  79. package/dist/node/commands/start/debugger.js +79 -0
  80. package/dist/node/commands/start/index.js +2 -0
  81. package/dist/node/commands/start/setup-interactive-mode.d.ts +20 -0
  82. package/dist/node/commands/start/setup-interactive-mode.js +107 -0
  83. package/dist/node/constants.js +4 -0
  84. package/dist/node/logger.js +5 -0
  85. package/dist/node/types.d.ts +23 -0
  86. package/dist/node/utils.js +23 -0
  87. package/dist/package.js +4 -0
  88. package/dist/runtime.js +1 -1
  89. package/dist/server/bundle.d.ts +12 -0
  90. package/dist/server/bundle.js +55 -0
  91. package/dist/server/bundler-pool.d.ts +51 -0
  92. package/dist/server/bundler-pool.js +197 -0
  93. package/dist/server/common/schema.js +19 -0
  94. package/dist/server/constants.d.ts +6 -0
  95. package/dist/server/constants.js +6 -0
  96. package/dist/server/create-dev-server.d.ts +6 -0
  97. package/dist/server/create-dev-server.js +185 -0
  98. package/dist/server/error.js +9 -0
  99. package/dist/server/events/event-bus.d.ts +12 -0
  100. package/dist/server/events/event-bus.js +16 -0
  101. package/dist/server/events/types.d.ts +37 -0
  102. package/dist/server/events/types.js +6 -0
  103. package/dist/server/index.d.ts +3 -0
  104. package/dist/server/index.js +3 -0
  105. package/dist/server/logger.js +33 -0
  106. package/dist/server/mcp/context.js +14 -0
  107. package/dist/server/mcp/server.js +86 -0
  108. package/dist/server/mcp/tools/app-log-diagnostics.js +37 -0
  109. package/dist/server/mcp/tools/build-diagnostics.js +97 -0
  110. package/dist/server/mcp/tools/build-info.js +33 -0
  111. package/dist/server/mcp/tools/device-diagnostics.js +52 -0
  112. package/dist/server/mcp/tools/index.js +277 -0
  113. package/dist/server/middlewares/request-logger.js +15 -0
  114. package/dist/server/middlewares/serve-assets.js +49 -0
  115. package/dist/server/middlewares/serve-bundle.js +72 -0
  116. package/dist/server/middlewares/sse.js +34 -0
  117. package/dist/server/middlewares/symbolicate.js +71 -0
  118. package/dist/server/sse/adapter.js +74 -0
  119. package/dist/server/sse/event-bus.js +26 -0
  120. package/dist/server/symbolicate.js +93 -0
  121. package/dist/server/types.d.ts +125 -0
  122. package/dist/server/wss/hmr-server.js +209 -0
  123. package/dist/server/wss/server.d.ts +9 -0
  124. package/dist/server/wss/server.js +70 -0
  125. package/dist/{runtime.d.cts → types/hmr.d.ts} +1 -12
  126. package/dist/types.d.ts +78 -0
  127. package/dist/utils/babel.js +11 -0
  128. package/dist/utils/build-options.js +17 -0
  129. package/dist/utils/bundle.js +6 -0
  130. package/dist/utils/config.d.ts +5 -0
  131. package/dist/utils/config.js +32 -0
  132. package/dist/utils/dev-server.js +51 -0
  133. package/dist/utils/env.js +7 -0
  134. package/dist/utils/errors.js +9 -0
  135. package/dist/utils/hash.js +8 -0
  136. package/dist/utils/id.js +28 -0
  137. package/dist/utils/node-resolve.js +42 -0
  138. package/dist/utils/promise.js +15 -0
  139. package/dist/utils/reporters.js +120 -0
  140. package/dist/utils/reset-cache.d.ts +8 -0
  141. package/dist/utils/reset-cache.js +25 -0
  142. package/dist/utils/response.js +91 -0
  143. package/dist/utils/run-build.d.ts +8 -0
  144. package/dist/utils/run-build.js +7 -0
  145. package/dist/utils/run-server.d.ts +6 -0
  146. package/dist/utils/run-server.js +20 -0
  147. package/dist/utils/runtime-target.js +9 -0
  148. package/dist/utils/serialize.js +10 -0
  149. package/dist/utils/server.js +6 -0
  150. package/dist/utils/storage.js +6 -0
  151. package/dist/utils/string.js +6 -0
  152. package/dist/utils/swc.js +10 -0
  153. package/dist/utils/terminal.js +86 -0
  154. package/dist/utils/url.js +23 -0
  155. package/package.json +56 -68
  156. package/dist/commands.cjs +0 -4008
  157. package/dist/commands.d.cts +0 -5
  158. package/dist/pluginutils.d.ts +0 -1
  159. package/dist/pluginutils.js +0 -2
  160. package/dist/runtime.cjs +0 -34
  161. /package/dist/{chunk-DXpK5_cz.js → chunk-DJV587Yu.js} +0 -0
@@ -0,0 +1,146 @@
1
+ import { __exportAll } from "./_virtual/_rolldown/runtime.js";
2
+ //#region src/constants.ts
3
+ var constants_exports = /* @__PURE__ */ __exportAll({
4
+ DEFAULT_ASSET_EXTENSIONS: () => DEFAULT_ASSET_EXTENSIONS,
5
+ DEFAULT_ASSET_REGISTRY_PATH: () => DEFAULT_ASSET_REGISTRY_PATH,
6
+ DEFAULT_ENV_FILE: () => DEFAULT_ENV_FILE,
7
+ DEFAULT_ENV_PREFIX: () => DEFAULT_ENV_PREFIX,
8
+ DEFAULT_HMR_CLIENT_PATH: () => DEFAULT_HMR_CLIENT_PATH,
9
+ DEFAULT_IMAGE_EXTENSIONS: () => DEFAULT_IMAGE_EXTENSIONS,
10
+ DEFAULT_REACT_NATIVE_GLOBAL_IDENTIFIERS: () => DEFAULT_REACT_NATIVE_GLOBAL_IDENTIFIERS,
11
+ DEFAULT_RESOLVER_ALIAS_FIELDS: () => DEFAULT_RESOLVER_ALIAS_FIELDS,
12
+ DEFAULT_RESOLVER_CONDITION_NAMES: () => DEFAULT_RESOLVER_CONDITION_NAMES,
13
+ DEFAULT_RESOLVER_MAIN_FIELDS: () => DEFAULT_RESOLVER_MAIN_FIELDS,
14
+ DEFAULT_RUNTIME_TARGET: () => DEFAULT_RUNTIME_TARGET,
15
+ DEFAULT_SOURCE_EXTENSIONS: () => DEFAULT_SOURCE_EXTENSIONS,
16
+ GLOBAL_IDENTIFIER: () => GLOBAL_IDENTIFIER,
17
+ IMAGE_EXTENSIONS: () => IMAGE_EXTENSIONS,
18
+ ROLLIPOP_VERSION: () => ROLLIPOP_VERSION
19
+ });
20
+ const ROLLIPOP_VERSION = "1.0.0-alpha.23";
21
+ const GLOBAL_IDENTIFIER = "global";
22
+ /**
23
+ * @see {@link https://github.com/facebook/metro/blob/0.81.x/docs/Configuration.md#resolvermainfields}
24
+ */
25
+ const DEFAULT_RESOLVER_MAIN_FIELDS = [
26
+ "react-native",
27
+ "browser",
28
+ "main"
29
+ ];
30
+ const DEFAULT_RESOLVER_ALIAS_FIELDS = [["react-native"], ["browser"]];
31
+ const DEFAULT_RESOLVER_CONDITION_NAMES = ["react-native"];
32
+ /**
33
+ * Unlike the Metro bundler configuration, this prioritizes resolving TypeScript and ESM first.
34
+ *
35
+ * @see {@link https://github.com/facebook/metro/blob/0.81.x/packages/metro-config/src/defaults/defaults.js}
36
+ * @see {@link https://github.com/facebook/metro/blob/0.81.x/packages/metro-file-map/src/workerExclusionList.js}
37
+ */
38
+ const DEFAULT_SOURCE_EXTENSIONS = [
39
+ "ts",
40
+ "tsx",
41
+ "js",
42
+ "jsx",
43
+ "mjs",
44
+ "cjs",
45
+ "json"
46
+ ];
47
+ const DEFAULT_IMAGE_EXTENSIONS = [
48
+ "bmp",
49
+ "gif",
50
+ "jpg",
51
+ "jpeg",
52
+ "png",
53
+ "psd",
54
+ "svg",
55
+ "webp"
56
+ ];
57
+ const IMAGE_EXTENSIONS = [
58
+ ...DEFAULT_IMAGE_EXTENSIONS,
59
+ "tiff",
60
+ "ktx"
61
+ ];
62
+ const DEFAULT_ASSET_EXTENSIONS = [
63
+ ...DEFAULT_IMAGE_EXTENSIONS,
64
+ "xml",
65
+ "m4v",
66
+ "mov",
67
+ "mp4",
68
+ "mpeg",
69
+ "mpg",
70
+ "webm",
71
+ "aac",
72
+ "aiff",
73
+ "caf",
74
+ "m4a",
75
+ "mp3",
76
+ "wav",
77
+ "html",
78
+ "pdf",
79
+ "yaml",
80
+ "yml",
81
+ "otf",
82
+ "ttf",
83
+ "zip"
84
+ ];
85
+ const DEFAULT_ASSET_REGISTRY_PATH = "react-native/Libraries/Image/AssetRegistry.js";
86
+ 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
+ const DEFAULT_ENV_PREFIX = "ROLLIPOP_";
143
+ const DEFAULT_ENV_FILE = ".env";
144
+ const DEFAULT_RUNTIME_TARGET = "hermes-v1";
145
+ //#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 };
@@ -0,0 +1,91 @@
1
+ declare namespace assets_d_exports {
2
+ export { AssetContext, AssetData, AssetDataFiltered, AssetDataWithoutFiles, AssetInfo, AssetScale, copyAssetsToDestination, generateAssetRegistryCode, getAssetPriority, getSuffixedPath, platformSuffixPattern, resolveAssetPath, resolveScaledAssets, stripSuffix };
3
+ }
4
+ /**
5
+ * **NOTE**: Type definitions are ported from `metro` implementation.
6
+ *
7
+ * @see https://github.com/facebook/metro/blob/0.81.x/packages/metro/src/Assets.js
8
+ */
9
+ interface AssetContext {
10
+ platform: string;
11
+ preferNativePlatform: boolean;
12
+ }
13
+ interface AssetInfo {
14
+ files: string[];
15
+ hash: string;
16
+ name: string;
17
+ scales: number[];
18
+ type: string;
19
+ }
20
+ interface AssetDataWithoutFiles {
21
+ __packager_asset: boolean;
22
+ fileSystemLocation: string;
23
+ hash: string;
24
+ httpServerLocation: string;
25
+ name: string;
26
+ scales: AssetScale[];
27
+ type: string;
28
+ width?: number;
29
+ height?: number;
30
+ }
31
+ interface AssetDataFiltered {
32
+ __packager_asset: boolean;
33
+ hash: string;
34
+ httpServerLocation: string;
35
+ name: string;
36
+ scales: AssetScale[];
37
+ type: string;
38
+ width?: number;
39
+ height?: number;
40
+ }
41
+ interface AssetData extends AssetDataWithoutFiles {
42
+ id: string;
43
+ files: string[];
44
+ }
45
+ type AssetScale = 0.75 | 1 | 1.5 | 2 | 3;
46
+ interface ResolveScaledAssetsOptions {
47
+ projectRoot: string;
48
+ assetPath: string;
49
+ platform: string;
50
+ preferNativePlatform: boolean;
51
+ }
52
+ declare function resolveScaledAssets(options: ResolveScaledAssetsOptions): Promise<AssetData>;
53
+ declare function platformSuffixPattern(context: AssetContext): string;
54
+ declare function stripSuffix(assetPath: string, context: AssetContext): string;
55
+ declare function getAssetPriority(assetPath: string, context: AssetContext): 0 | 3 | 2 | 1;
56
+ interface GetSuffixedPathOptions {
57
+ scale?: AssetScale;
58
+ platform?: string;
59
+ }
60
+ /**
61
+ * add suffix to asset path
62
+ *
63
+ * ```js
64
+ * // assetPath input
65
+ * '/path/to/assets/image.png'
66
+ *
67
+ * // `platform` suffixed
68
+ * '/path/to/assets/image.android.png'
69
+ *
70
+ * // `scale` suffixed
71
+ * '/path/to/assets/image@1x.png'
72
+ *
73
+ * // both `platform` and `scale` suffixed
74
+ * '/path/to/assets/image@1x.android.png'
75
+ * ```
76
+ */
77
+ declare function getSuffixedPath(assetPath: string, context: AssetContext, options: GetSuffixedPathOptions): string;
78
+ declare function resolveAssetPath(assetPath: string, context: AssetContext, scale: AssetScale): string;
79
+ interface CopyAssetsToDestinationOptions {
80
+ assets: AssetData[];
81
+ assetsDir: string;
82
+ platform: string;
83
+ preferNativePlatform: boolean;
84
+ }
85
+ /**
86
+ * @see https://github.com/facebook/react-native/blob/0.83-stable/packages/community-cli-plugin/src/commands/bundle/assetPathUtils.js
87
+ */
88
+ declare function copyAssetsToDestination(options: CopyAssetsToDestinationOptions): Promise<undefined>;
89
+ declare function generateAssetRegistryCode(assetRegistryPath: string, asset: AssetData): string;
90
+ //#endregion
91
+ export { assets_d_exports };
@@ -0,0 +1,244 @@
1
+ import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
+ import { IMAGE_EXTENSIONS } from "../constants.js";
3
+ import { md5 } from "../utils/hash.js";
4
+ import { DEV_SERVER_ASSET_PATH } from "../server/constants.js";
5
+ import "../server/index.js";
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ import { isNotNil } from "es-toolkit";
9
+ import { imageSize } from "image-size";
10
+ //#region src/core/assets.ts
11
+ /**
12
+ * **NOTE**: Type definitions are ported from `metro` implementation.
13
+ *
14
+ * @see https://github.com/facebook/metro/blob/0.81.x/packages/metro/src/Assets.js
15
+ */
16
+ var assets_exports = /* @__PURE__ */ __exportAll({
17
+ copyAssetsToDestination: () => copyAssetsToDestination,
18
+ generateAssetRegistryCode: () => generateAssetRegistryCode,
19
+ getAssetPriority: () => getAssetPriority,
20
+ getSuffixedPath: () => getSuffixedPath,
21
+ platformSuffixPattern: () => platformSuffixPattern,
22
+ resolveAssetPath: () => resolveAssetPath,
23
+ resolveScaledAssets: () => resolveScaledAssets,
24
+ stripSuffix: () => stripSuffix
25
+ });
26
+ const SCALE_PATTERN = "@(\\d+\\.?\\d*)x";
27
+ const IMAGE_ASSET_TYPES = new Set(IMAGE_EXTENSIONS);
28
+ /**
29
+ * key: platform,
30
+ * value: allowed scales
31
+ *
32
+ * @see https://github.com/facebook/react-native/blob/0.83-stable/packages/community-cli-plugin/src/commands/bundle/filterPlatformAssetScales.js#L11
33
+ */
34
+ const ALLOW_SCALES = { ios: [
35
+ 1,
36
+ 2,
37
+ 3
38
+ ] };
39
+ /**
40
+ * @see https://developer.android.com/training/multiscreen/screendensities#TaskProvideAltBmp
41
+ */
42
+ const ANDROID_ASSET_QUALIFIER = {
43
+ .75: "ldpi",
44
+ 1: "mdpi",
45
+ 1.5: "hdpi",
46
+ 2: "xhdpi",
47
+ 3: "xxhdpi",
48
+ 4: "xxxhdpi"
49
+ };
50
+ async function resolveScaledAssets(options) {
51
+ const { projectRoot, assetPath, platform, preferNativePlatform } = options;
52
+ const context = {
53
+ platform,
54
+ preferNativePlatform
55
+ };
56
+ const extension = path.extname(assetPath);
57
+ const type = extension.substring(1);
58
+ const relativePath = path.relative(projectRoot, assetPath);
59
+ const dirname = path.dirname(assetPath);
60
+ const files = fs.readdirSync(dirname);
61
+ const stripedBasename = stripSuffix(assetPath, context);
62
+ const suffixPattern = platformSuffixPattern(context);
63
+ const assetRegExp = new RegExp(`${stripedBasename}(${SCALE_PATTERN})?(?:${suffixPattern})?${extension}$`);
64
+ const scaledAssets = {};
65
+ for (const file of files.sort((a, b) => getAssetPriority(b, context) - getAssetPriority(a, context))) {
66
+ const match = assetRegExp.exec(file);
67
+ if (match) {
68
+ const [, , scale = "1"] = match;
69
+ if (scaledAssets[scale]) continue;
70
+ scaledAssets[scale] = file;
71
+ }
72
+ }
73
+ if (!(Object.keys(scaledAssets).length && scaledAssets[1])) throw new Error(`cannot resolve base asset of ${assetPath}`);
74
+ const imageData = fs.readFileSync(assetPath);
75
+ const dimensions = IMAGE_ASSET_TYPES.has(type) ? imageSize(imageData) : void 0;
76
+ const filteredScaledAssets = Object.entries(scaledAssets).map(([scale, file]) => ({
77
+ scale: parseFloat(scale),
78
+ file
79
+ })).filter(({ scale }) => ALLOW_SCALES[platform]?.includes(scale) ?? true).reduce((acc, { scale, file }) => {
80
+ acc.files.push(file);
81
+ acc.scales.push(scale);
82
+ return acc;
83
+ }, {
84
+ scales: [],
85
+ files: []
86
+ });
87
+ return {
88
+ __packager_asset: true,
89
+ id: assetPath,
90
+ name: stripedBasename.replace(extension, ""),
91
+ type,
92
+ width: dimensions?.width,
93
+ height: dimensions?.height,
94
+ files: filteredScaledAssets.files,
95
+ scales: filteredScaledAssets.scales,
96
+ fileSystemLocation: path.dirname(assetPath),
97
+ httpServerLocation: path.join(DEV_SERVER_ASSET_PATH, path.dirname(relativePath)),
98
+ hash: md5(imageData)
99
+ };
100
+ }
101
+ function platformSuffixPattern(context) {
102
+ return [context.platform, context.preferNativePlatform ? "native" : null].filter(isNotNil).map((platform) => `.${platform}`).join("|");
103
+ }
104
+ function stripSuffix(assetPath, context) {
105
+ const basename = path.basename(assetPath);
106
+ const extension = path.extname(assetPath);
107
+ const suffixPattern = platformSuffixPattern(context);
108
+ return basename.replace(new RegExp(`(${SCALE_PATTERN})?(?:${suffixPattern})?${extension}$`), "");
109
+ }
110
+ function getAssetPriority(assetPath, context) {
111
+ const suffixPattern = platformSuffixPattern(context);
112
+ if (new RegExp(`${SCALE_PATTERN}(?:${suffixPattern})`).test(assetPath)) return 3;
113
+ else if (new RegExp(`(?:${suffixPattern})`).test(assetPath)) return 2;
114
+ else if (new RegExp(`${SCALE_PATTERN}`).test(assetPath)) return 1;
115
+ return 0;
116
+ }
117
+ function addSuffix(assetPath, context, options) {
118
+ const extension = path.extname(assetPath);
119
+ return stripSuffix(assetPath, context).concat(options?.scale ? `@${options.scale}x` : "").concat(options?.platform ? `.${options.platform}${extension}` : extension);
120
+ }
121
+ /**
122
+ * add suffix to asset path
123
+ *
124
+ * ```js
125
+ * // assetPath input
126
+ * '/path/to/assets/image.png'
127
+ *
128
+ * // `platform` suffixed
129
+ * '/path/to/assets/image.android.png'
130
+ *
131
+ * // `scale` suffixed
132
+ * '/path/to/assets/image@1x.png'
133
+ *
134
+ * // both `platform` and `scale` suffixed
135
+ * '/path/to/assets/image@1x.android.png'
136
+ * ```
137
+ */
138
+ function getSuffixedPath(assetPath, context, options) {
139
+ const suffixedBasename = addSuffix(assetPath, context, {
140
+ scale: options?.scale,
141
+ platform: options?.platform
142
+ });
143
+ const dirname = path.dirname(assetPath);
144
+ return path.join(dirname, suffixedBasename);
145
+ }
146
+ function resolveAssetPath(assetPath, context, scale) {
147
+ const suffixedPaths = [
148
+ getSuffixedPath(assetPath, context, {
149
+ scale,
150
+ platform: context.platform
151
+ }),
152
+ context.preferNativePlatform ? getSuffixedPath(assetPath, context, {
153
+ scale,
154
+ platform: "native"
155
+ }) : null,
156
+ getSuffixedPath(assetPath, context, { scale })
157
+ ].filter(isNotNil);
158
+ /**
159
+ * When scale is 1, filename can be suffixed or non-suffixed(`image.png`).
160
+ *
161
+ * - Suffixed
162
+ * - `filename.<platform>@<scale>x.ext`
163
+ * - `filename.<platform>.ext`
164
+ * - `filename@<scale>x.ext`
165
+ * - Non suffixed
166
+ * - `filename.ext`
167
+ *
168
+ * 1. Resolve non-suffixed asset first.
169
+ * 2. If file is not exist, resolve suffixed path.
170
+ */
171
+ if (scale === 1) try {
172
+ fs.statSync(assetPath);
173
+ return assetPath;
174
+ } catch {}
175
+ for (const suffixedPath of suffixedPaths) try {
176
+ fs.statSync(suffixedPath);
177
+ return suffixedPath;
178
+ } catch {}
179
+ throw new Error(`cannot resolve asset path for ${assetPath}`);
180
+ }
181
+ /**
182
+ * @see https://github.com/facebook/react-native/blob/0.83-stable/packages/community-cli-plugin/src/commands/bundle/assetPathUtils.js
183
+ */
184
+ async function copyAssetsToDestination(options) {
185
+ const { assets, platform, assetsDir, preferNativePlatform } = options;
186
+ const context = {
187
+ platform,
188
+ preferNativePlatform
189
+ };
190
+ const mkdirWithAssertPath = (targetPath) => {
191
+ const dirname = path.dirname(targetPath);
192
+ fs.mkdirSync(dirname, { recursive: true });
193
+ };
194
+ return Promise.all(assets.map((asset) => {
195
+ return Promise.all(asset.scales.map(async (scale) => {
196
+ if (platform !== "android") {
197
+ const from = resolveAssetPath(asset.id, context, scale);
198
+ const to = path.join(assetsDir, getIosAssetDestinationPath(asset, scale));
199
+ mkdirWithAssertPath(to);
200
+ return fs.copyFileSync(from, to);
201
+ }
202
+ const from = resolveAssetPath(asset.id, context, scale);
203
+ const to = path.join(assetsDir, getAndroidAssetDestinationPath(asset, scale));
204
+ mkdirWithAssertPath(to);
205
+ fs.copyFileSync(from, to);
206
+ })).then(() => void 0);
207
+ })).then(() => void 0);
208
+ }
209
+ /**
210
+ * @see https://github.com/facebook/react-native/blob/0.83-stable/packages/community-cli-plugin/src/commands/bundle/getAssetDestPathIOS.js
211
+ */
212
+ function getIosAssetDestinationPath(asset, scale) {
213
+ const suffix = scale === 1 ? "" : `@${scale}x`;
214
+ const fileName = `${asset.name + suffix}.${asset.type}`;
215
+ const devServerBasePath = asset.httpServerLocation.at(0) === "/" ? asset.httpServerLocation.slice(1) : asset.httpServerLocation;
216
+ return path.join(devServerBasePath.replace(/\.\.\//g, "_"), fileName);
217
+ }
218
+ function getAndroidAssetDestinationPath(asset, scale) {
219
+ const assetQualifierSuffix = ANDROID_ASSET_QUALIFIER[scale];
220
+ const assetName = `${asset.httpServerLocation.at(0) === "/" ? asset.httpServerLocation.slice(1) : asset.httpServerLocation}/${asset.name}`.toLowerCase().replace(/\//g, "_").replace(/(?:[^a-z0-9_])/g, "").replace(/^assets_/, "");
221
+ if (!assetQualifierSuffix) throw new Error(`invalid asset qualifier: ${asset.id}`);
222
+ return path.join(isDrawable(asset.type) ? `drawable-${assetQualifierSuffix}` : "raw", `${assetName}.${asset.type}`);
223
+ }
224
+ /**
225
+ * @see https://developer.android.com/guide/topics/resources/drawable-resource
226
+ */
227
+ function isDrawable(type) {
228
+ return [
229
+ "gif",
230
+ "heic",
231
+ "heif",
232
+ "jpeg",
233
+ "jpg",
234
+ "ktx",
235
+ "png",
236
+ "webp",
237
+ "xml"
238
+ ].includes(type);
239
+ }
240
+ function generateAssetRegistryCode(assetRegistryPath, asset) {
241
+ return `module.exports = require('${assetRegistryPath}').registerAsset(${JSON.stringify(asset)});`;
242
+ }
243
+ //#endregion
244
+ export { assets_exports, copyAssetsToDestination, generateAssetRegistryCode, resolveAssetPath, resolveScaledAssets };
@@ -0,0 +1,15 @@
1
+ import { BuildOptions, DevEngine, DevEngineOptions } from "./types.js";
2
+ import { ResolvedConfig } from "../config/defaults.js";
3
+ import * as rolldown from "@rollipop/rolldown";
4
+
5
+ //#region src/core/bundler.d.ts
6
+ declare class Bundler {
7
+ private readonly config;
8
+ static devEngine(config: ResolvedConfig, buildOptions: Omit<BuildOptions, 'dev' | 'outfile'>, devEngineOptions: DevEngineOptions): Promise<DevEngine>;
9
+ static createId(config: ResolvedConfig, buildOptions: BuildOptions): string;
10
+ private static createContext;
11
+ constructor(config: ResolvedConfig);
12
+ build(buildOptions: BuildOptions): Promise<rolldown.OutputChunk>;
13
+ }
14
+ //#endregion
15
+ export { Bundler };
@@ -0,0 +1,80 @@
1
+ import { Logo } from "../common/logo.js";
2
+ import { resolveBuildOptions } from "../utils/build-options.js";
3
+ import { createId } from "../utils/id.js";
4
+ import { FileStorage } from "./fs/storage.js";
5
+ import { getOverrideOptions, getOverrideOptionsForDevServer, resolveRolldownOptions } from "./rolldown.js";
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ import { invariant, merge } from "es-toolkit";
9
+ import * as rolldown from "@rollipop/rolldown";
10
+ import { dev } from "@rollipop/rolldown/experimental";
11
+ //#region src/core/bundler.ts
12
+ var Bundler = class Bundler {
13
+ config;
14
+ static async devEngine(config, buildOptions, devEngineOptions) {
15
+ const buildType = "serve";
16
+ const resolvedBuildOptions = resolveBuildOptions(config, buildOptions);
17
+ const context = Bundler.createContext(buildType, config, resolvedBuildOptions);
18
+ const { input = {}, output = {} } = await resolveRolldownOptions(context, config, resolvedBuildOptions, devEngineOptions);
19
+ const devServerOptions = getOverrideOptionsForDevServer(resolvedBuildOptions);
20
+ const devEngine = await dev(merge(input, devServerOptions.input), merge(output, devServerOptions.output), {
21
+ watch: config.watcher,
22
+ ...devEngineOptions
23
+ });
24
+ Object.defineProperty(devEngine, "getContext", {
25
+ value: () => context,
26
+ enumerable: true,
27
+ configurable: false
28
+ });
29
+ return devEngine;
30
+ }
31
+ static createId(config, buildOptions) {
32
+ return createId(config, buildOptions);
33
+ }
34
+ static createContext(buildType, config, buildOptions) {
35
+ return {
36
+ id: Bundler.createId(config, buildOptions),
37
+ root: config.root,
38
+ storage: FileStorage.getInstance(config.root),
39
+ buildType,
40
+ state: {
41
+ revision: 0,
42
+ latestBuildStartTime: 0
43
+ }
44
+ };
45
+ }
46
+ constructor(config) {
47
+ this.config = config;
48
+ Logo.printOnce();
49
+ }
50
+ async build(buildOptions) {
51
+ const buildType = "build";
52
+ const resolvedBuildOptions = resolveBuildOptions(this.config, buildOptions);
53
+ const context = Bundler.createContext(buildType, this.config, resolvedBuildOptions);
54
+ const sourcemap = resolvedBuildOptions.sourcemap ? true : false;
55
+ const { input = {}, output = {} } = await resolveRolldownOptions(context, this.config, resolvedBuildOptions);
56
+ const overrideOptions = getOverrideOptions();
57
+ const mergedInput = merge(input, overrideOptions.input);
58
+ const mergedOutput = merge(output, overrideOptions.output);
59
+ const rolldownBuildOptions = {
60
+ ...mergedInput,
61
+ output: {
62
+ ...mergedOutput,
63
+ sourcemap
64
+ },
65
+ write: Boolean(resolvedBuildOptions.outfile)
66
+ };
67
+ const chunk = (await rolldown.build(rolldownBuildOptions)).output[0];
68
+ invariant(chunk, "Bundled chunk is not found");
69
+ if (resolvedBuildOptions.outfile && chunk.sourcemapFileName && resolvedBuildOptions.sourcemapOutfile) {
70
+ const outputDir = path.dirname(resolvedBuildOptions.outfile);
71
+ const sourcemapDir = path.dirname(resolvedBuildOptions.sourcemapOutfile);
72
+ const sourcemapFile = path.join(outputDir, chunk.sourcemapFileName);
73
+ if (!fs.existsSync(sourcemapDir)) fs.mkdirSync(sourcemapDir, { recursive: true });
74
+ fs.renameSync(sourcemapFile, resolvedBuildOptions.sourcemapOutfile);
75
+ }
76
+ return chunk;
77
+ }
78
+ };
79
+ //#endregion
80
+ export { Bundler };
@@ -0,0 +1,11 @@
1
+ import { Config } from "../config/types.js";
2
+ //#region src/core/env.d.ts
3
+ interface LoadEnvOptions {
4
+ envDir: string;
5
+ envPrefix: string;
6
+ envFile: string;
7
+ mode?: Config['mode'];
8
+ }
9
+ declare function loadEnv(options: LoadEnvOptions): Record<string, string>;
10
+ //#endregion
11
+ export { LoadEnvOptions, loadEnv };
@@ -0,0 +1,36 @@
1
+ import { logger } from "../logger.js";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { invariant, isNotNil } from "es-toolkit";
5
+ import dotenv from "dotenv";
6
+ import dotenvExpand from "dotenv-expand";
7
+ //#region src/core/env.ts
8
+ function loadEnv(options) {
9
+ const { envDir, envPrefix, envFile, mode } = options;
10
+ invariant(envPrefix.length > 0, "`envPrefix` is required");
11
+ invariant(envFile.length > 0, "`envFile` is required");
12
+ const env = {};
13
+ const envFilesToLoad = [
14
+ envFile,
15
+ `${envFile}.local`,
16
+ mode ? `${envFile}.${mode}` : null,
17
+ mode ? `${envFile}.${mode}.local` : null
18
+ ].filter(isNotNil);
19
+ for (const file of envFilesToLoad) {
20
+ const envPath = path.resolve(envDir, file);
21
+ if (!fs.existsSync(envPath)) continue;
22
+ logger.trace(`Loading environment variables from ${envPath}`);
23
+ const parsed = dotenv.parse(fs.readFileSync(envPath, "utf-8"));
24
+ const expanded = dotenvExpand.expand({
25
+ parsed,
26
+ processEnv: {}
27
+ });
28
+ if (expanded.parsed) Object.entries(expanded.parsed).forEach(([key, value]) => {
29
+ if (key.startsWith(envPrefix)) env[key] = key in process.env ? process.env[key] : value;
30
+ });
31
+ }
32
+ logger.trace("Loaded environment variables:", env);
33
+ return env;
34
+ }
35
+ //#endregion
36
+ export { loadEnv };
@@ -0,0 +1,9 @@
1
+ import { SHARED_DATA_PATH } from "../../common/constants.js";
2
+ import "node:fs";
3
+ import path from "node:path";
4
+ //#region src/core/fs/data.ts
5
+ function getSharedDataPath(basePath) {
6
+ return path.join(basePath, SHARED_DATA_PATH);
7
+ }
8
+ //#endregion
9
+ export { getSharedDataPath };
@@ -0,0 +1,15 @@
1
+ import { FileStorageData } from "../../common/types.js";
2
+
3
+ //#region src/core/fs/storage.d.ts
4
+ declare class FileStorage {
5
+ private readonly basePath;
6
+ private static instance;
7
+ private dataFilePath;
8
+ private data;
9
+ static getInstance(basePath: string): FileStorage;
10
+ private constructor();
11
+ get(): FileStorageData;
12
+ set(data: Partial<FileStorageData>): void;
13
+ }
14
+ //#endregion
15
+ export { FileStorage };
@@ -0,0 +1,31 @@
1
+ import { getSharedDataPath } from "./data.js";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { merge } from "es-toolkit";
5
+ //#region src/core/fs/storage.ts
6
+ const DEFAULT_DATA = { build: {} };
7
+ var FileStorage = class FileStorage {
8
+ basePath;
9
+ static instance = null;
10
+ dataFilePath;
11
+ data;
12
+ static getInstance(basePath) {
13
+ if (FileStorage.instance == null) FileStorage.instance = new FileStorage(basePath);
14
+ return FileStorage.instance;
15
+ }
16
+ constructor(basePath) {
17
+ this.basePath = basePath;
18
+ this.dataFilePath = path.join(getSharedDataPath(basePath), "rollipop.json");
19
+ if (fs.existsSync(this.dataFilePath)) this.data = JSON.parse(fs.readFileSync(this.dataFilePath, "utf-8"));
20
+ else this.data = DEFAULT_DATA;
21
+ }
22
+ get() {
23
+ return this.data;
24
+ }
25
+ set(data) {
26
+ this.data = merge(this.data, data);
27
+ fs.writeFileSync(this.dataFilePath, JSON.stringify(this.data, null, 2));
28
+ }
29
+ };
30
+ //#endregion
31
+ export { FileStorage };