rollipop 1.0.0-alpha.26 → 1.0.0-alpha.28

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 (40) hide show
  1. package/client.d.ts +5 -1
  2. package/dist/config/index.d.ts +1 -1
  3. package/dist/config/load-config.js +2 -0
  4. package/dist/config/notice.js +7 -0
  5. package/dist/config/types.d.ts +36 -3
  6. package/dist/constants.js +1 -1
  7. package/dist/core/assets.d.ts +4 -3
  8. package/dist/core/assets.js +124 -78
  9. package/dist/core/bundler.js +2 -2
  10. package/dist/core/plugins/alias-plugin.d.ts +13 -0
  11. package/dist/core/plugins/alias-plugin.js +8 -0
  12. package/dist/core/plugins/dev-server-plugin.d.ts +4 -2
  13. package/dist/core/plugins/dev-server-plugin.js +5 -3
  14. package/dist/core/plugins/import-glob-plugin.d.ts +11 -0
  15. package/dist/core/plugins/import-glob-plugin.js +7 -0
  16. package/dist/core/plugins/index.d.ts +4 -2
  17. package/dist/core/plugins/index.js +7 -1
  18. package/dist/core/plugins/react-native-plugin.d.ts +1 -1
  19. package/dist/core/rolldown.js +44 -5
  20. package/dist/core/types.d.ts +1 -1
  21. package/dist/index.d.ts +4 -4
  22. package/dist/index.js +1 -1
  23. package/dist/internal/react-native.js +2 -5
  24. package/dist/node/commands/bundle/action.js +1 -1
  25. package/dist/node/commands/start/action.js +2 -3
  26. package/dist/package.js +1 -1
  27. package/dist/server/create-dev-server.js +0 -7
  28. package/dist/server/mcp/server.js +1 -1
  29. package/dist/server/mcp/tools/index.js +1 -1
  30. package/dist/server/middlewares/dashboard.js +8 -2
  31. package/dist/server/middlewares/serve-assets.js +5 -4
  32. package/dist/server/middlewares/symbolicate.js +20 -16
  33. package/dist/server/rest/domains/actions.js +2 -2
  34. package/dist/server/state/store.js +9 -1
  35. package/dist/server/symbolicate.js +35 -19
  36. package/dist/storage/file-storage.js +1 -1
  37. package/dist/utils/reset-cache.d.ts +2 -3
  38. package/dist/utils/reset-cache.js +4 -19
  39. package/import-glob.d.ts +129 -0
  40. package/package.json +4 -3
@@ -19,8 +19,10 @@ import { entryPlugin } from "./plugins/entry-plugin.js";
19
19
  import { babelPlugin } from "./plugins/babel-plugin.js";
20
20
  import { swcPlugin } from "./plugins/swc-plugin.js";
21
21
  import { reporterPlugin } from "./plugins/reporter-plugin.js";
22
- import { devServerPlugin } from "./plugins/dev-server-plugin.js";
22
+ import { DEFAULT_REACT_REFRESH_EXCLUDE_PATTERNS, DEFAULT_REACT_REFRESH_INCLUDE_PATTERNS, devServerPlugin } from "./plugins/dev-server-plugin.js";
23
23
  import { analyzePlugin } from "./plugins/analyze-plugin.js";
24
+ import { importGlobPlugin } from "./plugins/import-glob-plugin.js";
25
+ import { aliasPlugin } from "./plugins/alias-plugin.js";
24
26
  import "./plugins/index.js";
25
27
  import fs from "node:fs";
26
28
  import path from "node:path";
@@ -45,12 +47,16 @@ async function resolveRolldownOptions(context, config, buildOptions, devEngineOp
45
47
  const { treeshake: rolldownTreeshake, minify: rolldownMinify, lazyBarrel: rolldownLazyBarrel, ...rolldownOptimization } = config.optimization;
46
48
  const { sourcemap: rolldownSourcemap, sourcemapBaseUrl: rolldownSourcemapBaseUrl, sourcemapDebugIds: rolldownSourcemapDebugIds, sourcemapIgnoreList: rolldownSourcemapIgnoreList, sourcemapPathTransform: rolldownSourcemapPathTransform } = config;
47
49
  const userPlugins = config.plugins;
50
+ const { rolldownAlias, aliasPluginOptions } = resolveAliasPluginOptions(config);
48
51
  const mergedResolveOptions = merge({ extensions: getResolveExtensions({
49
52
  sourceExtensions,
50
53
  assetExtensions,
51
54
  platform,
52
55
  preferNativePlatform
53
- }) }, rolldownResolve);
56
+ }) }, {
57
+ ...rolldownResolve,
58
+ alias: rolldownAlias
59
+ });
54
60
  const mergedTransformOptions = merge({
55
61
  cwd: config.root,
56
62
  target: "esnext",
@@ -67,8 +73,12 @@ async function resolveRolldownOptions(context, config, buildOptions, devEngineOp
67
73
  ...defineEnvFromObject(builtInEnv)
68
74
  },
69
75
  helpers: { mode: "Runtime" }
70
- }, rolldownTransform);
76
+ }, {
77
+ ...rolldownTransform,
78
+ reactCompiler: resolveReactCompilerTransformOptions(rolldownTransform.reactCompiler)
79
+ });
71
80
  const entryPluginOptions = resolveEntryPluginOptions(config);
81
+ const importGlobPluginOptions = resolveImportGlobPluginOptions(config);
72
82
  const reactNativePluginOptions = await resolveReactNativePluginOptions(config, context, buildOptions);
73
83
  const babelPluginOptions = resolveBabelPluginOptions(config, context);
74
84
  const swcPluginOptions = resolveSwcPluginOptions(config, context);
@@ -92,6 +102,8 @@ async function resolveRolldownOptions(context, config, buildOptions, devEngineOp
92
102
  },
93
103
  plugins: withTransformBoundary(context, [
94
104
  entryPlugin(entryPluginOptions),
105
+ importGlobPlugin(importGlobPluginOptions),
106
+ aliasPlugin(aliasPluginOptions),
95
107
  reactNativePlugin(reactNativePluginOptions),
96
108
  babelPlugin(babelPluginOptions),
97
109
  swcPlugin(swcPluginOptions),
@@ -134,7 +146,7 @@ async function resolveRolldownOptions(context, config, buildOptions, devEngineOp
134
146
  outro: rolldownOutro,
135
147
  intro: async (chunk) => {
136
148
  return [
137
- ...getGlobalVariables(dev, context.buildType),
149
+ ...getGlobalVariables(dev),
138
150
  ...loadPolyfills(config),
139
151
  typeof rolldownIntro === "function" ? await rolldownIntro(chunk) : rolldownIntro
140
152
  ].filter(isNotNil).join("\n");
@@ -158,6 +170,24 @@ function resolveEntryPluginOptions(config) {
158
170
  preludePaths: config.serializer.prelude
159
171
  };
160
172
  }
173
+ function resolveImportGlobPluginOptions(config) {
174
+ return {
175
+ root: config.root,
176
+ sourcemap: config.mode === "development",
177
+ restoreQueryExtension: false
178
+ };
179
+ }
180
+ function resolveAliasPluginOptions(config) {
181
+ const { alias } = config.resolver;
182
+ if (Array.isArray(alias)) return {
183
+ rolldownAlias: void 0,
184
+ aliasPluginOptions: { entries: alias }
185
+ };
186
+ return {
187
+ rolldownAlias: alias,
188
+ aliasPluginOptions: { entries: [] }
189
+ };
190
+ }
161
191
  async function resolveReactNativePluginOptions(config, context, buildOptions) {
162
192
  return {
163
193
  context,
@@ -195,6 +225,13 @@ function resolveWorkletsConfig(config) {
195
225
  pluginVersion: resolvePackageJson(config.root, "react-native-worklets")?.version
196
226
  }, worklets);
197
227
  }
228
+ function resolveReactCompilerTransformOptions(reactCompiler) {
229
+ if (reactCompiler == null) return;
230
+ return {
231
+ ...reactCompiler,
232
+ exclude: reactCompiler.exclude ?? [/node_modules/]
233
+ };
234
+ }
198
235
  function resolveBabelPluginOptions(config, context) {
199
236
  return {
200
237
  context,
@@ -344,7 +381,9 @@ function getOverrideOptionsForDevServer(buildOptions) {
344
381
  */
345
382
  refresh: {
346
383
  refreshReg: "$RefreshReg$",
347
- refreshSig: "$RefreshSig$"
384
+ refreshSig: "$RefreshSig$",
385
+ include: DEFAULT_REACT_REFRESH_INCLUDE_PATTERNS,
386
+ exclude: DEFAULT_REACT_REFRESH_EXCLUDE_PATTERNS
348
387
  }
349
388
  } },
350
389
  experimental: { incrementalBuild: true },
@@ -1,6 +1,6 @@
1
1
  import { FileStorage } from "../storage/file-storage.js";
2
- import * as rolldown from "@rollipop/rolldown";
3
2
  import { DevEngine, DevOptions } from "@rollipop/rolldown/experimental";
3
+ import * as rolldown from "@rollipop/rolldown";
4
4
 
5
5
  //#region src/core/types.d.ts
6
6
  interface BuildOptions {
package/dist/index.d.ts CHANGED
@@ -4,9 +4,10 @@ import { BundleDetails, DevServer, DevServerContext, DevServerEvents, FastifyIns
4
4
  import { createDevServer } from "./server/create-dev-server.js";
5
5
  import { DEFAULT_HOST, DEFAULT_PORT, DEV_SERVER_ASSET_PATH } from "./server/constants.js";
6
6
  import { Plugin, PluginConfig } from "./core/plugins/types.js";
7
+ import { index_d_exports } from "./core/plugins/index.js";
7
8
  import { InteractiveCommand, InteractiveCommandContext, InteractiveModeOptions, setupInteractiveMode } from "./node/commands/start/setup-interactive-mode.js";
8
9
  import { createCommand, createReactNativeCliCommand } from "./node/cli-utils.js";
9
- 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 "./config/types.js";
10
+ import { AliasConfig, 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 "./config/types.js";
10
11
  import { PluginFlattenConfig, mergeConfig } from "./config/merge-config.js";
11
12
  import { DefaultConfig, InternalConfig, ResolvedConfig, getDefaultConfig } from "./config/defaults.js";
12
13
  import { DefineConfigContext, DynamicUserConfig, UserConfig, defineConfig } from "./config/define-config.js";
@@ -15,12 +16,11 @@ import { resetCache } from "./utils/reset-cache.js";
15
16
  import { runBuild } from "./utils/run-build.js";
16
17
  import { runServer } from "./utils/run-server.js";
17
18
  import { Bundler } from "./core/bundler.js";
18
- import { index_d_exports } from "./core/plugins/index.js";
19
19
  import { assets_d_exports } from "./core/assets.js";
20
20
  import { LoadEnvOptions, loadEnv } from "./core/env.js";
21
21
  import { constants_d_exports } from "./constants.js";
22
22
  import { HMRClientLogLevel, HMRClientMessage, HMRContext, HMRCustomHandler, HMRCustomMessage, HMRServerError, HMRServerMessage } from "./types/hmr.js";
23
23
  import { cli_d_exports } from "./node/cli.js";
24
- import * as rolldown from "@rollipop/rolldown";
25
24
  import * as rolldownExperimental from "@rollipop/rolldown/experimental";
26
- export { type AnalyzerConfig, assets_d_exports as AssetUtils, type AsyncResult, type BabelTransformConfig, type BuildDiagnosticLog, type BuildOptions, type BuildType, type BundleDetails, Bundler, type BundlerContext, type BundlerState, type CodegenConfig, type Config, constants_d_exports as Constants, DEFAULT_HOST, DEFAULT_PORT, DEV_SERVER_ASSET_PATH, type DeepRequired, DefaultConfig, DefineConfigContext, type DevEngine, type DevEngineOptions, type DevModeConfig, type DevServer, type DevServerContext, type DevServerEvents, DynamicUserConfig, type ExperimentalConfig, type FastifyInstance, type FlowConfig, type FormattedError, type HMRClientLogLevel, type HMRClientMessage, type HMRContext, type HMRCustomHandler, type HMRCustomMessage, type HMRServerError, type HMRServerMessage, type HmrConfig, InteractiveCommand, InteractiveCommandContext, InteractiveModeOptions, InternalConfig, LoadConfigOptions, LoadEnvOptions, type MaybePromise, type MetroCompatibleClientLogEvent, type Middlewares, type NullValue, type OptimizationConfig, type PackageJson, type Plugin, type PluginConfig, PluginFlattenConfig, type PluginOption, type Polyfill, type PolyfillOptions, type PolyfillType, type PolyfillWithCode, type PolyfillWithPath, type ReactNativeConfig, type ReportableEvent, type Reporter, ResolvedConfig, type ResolverConfig, type RolldownConfig, type RollipopReactNativeFlowConfig, type RollipopReactNativeWorkletsConfig, type SerializerConfig, type ServerOptions, type SwcTransformConfig, type TerminalConfig, type TransformRule, type TransformerConfig, UserConfig, type WatcherConfig, cli_d_exports as cli, createCommand, createDevServer, createReactNativeCliCommand, defineConfig, flattenPluginOption, getDefaultConfig, invokeConfigResolved, loadConfig, loadEnv, mergeConfig, index_d_exports as plugins, resetCache, resolvePluginConfig, rolldown, rolldownExperimental, runBuild, runServer, setupInteractiveMode };
25
+ import * as rolldown from "@rollipop/rolldown";
26
+ export { type AliasConfig, type AnalyzerConfig, assets_d_exports as AssetUtils, type AsyncResult, type BabelTransformConfig, type BuildDiagnosticLog, type BuildOptions, type BuildType, type BundleDetails, Bundler, type BundlerContext, type BundlerState, type CodegenConfig, type Config, constants_d_exports as Constants, DEFAULT_HOST, DEFAULT_PORT, DEV_SERVER_ASSET_PATH, type DeepRequired, DefaultConfig, DefineConfigContext, type DevEngine, type DevEngineOptions, type DevModeConfig, type DevServer, type DevServerContext, type DevServerEvents, DynamicUserConfig, type ExperimentalConfig, type FastifyInstance, type FlowConfig, type FormattedError, type HMRClientLogLevel, type HMRClientMessage, type HMRContext, type HMRCustomHandler, type HMRCustomMessage, type HMRServerError, type HMRServerMessage, type HmrConfig, InteractiveCommand, InteractiveCommandContext, InteractiveModeOptions, InternalConfig, LoadConfigOptions, LoadEnvOptions, type MaybePromise, type MetroCompatibleClientLogEvent, type Middlewares, type NullValue, type OptimizationConfig, type PackageJson, type Plugin, type PluginConfig, PluginFlattenConfig, type PluginOption, type Polyfill, type PolyfillOptions, type PolyfillType, type PolyfillWithCode, type PolyfillWithPath, type ReactNativeConfig, type ReportableEvent, type Reporter, ResolvedConfig, type ResolverConfig, type RolldownConfig, type RollipopReactNativeFlowConfig, type RollipopReactNativeWorkletsConfig, type SerializerConfig, type ServerOptions, type SwcTransformConfig, type TerminalConfig, type TransformRule, type TransformerConfig, UserConfig, type WatcherConfig, cli_d_exports as cli, createCommand, createDevServer, createReactNativeCliCommand, defineConfig, flattenPluginOption, getDefaultConfig, invokeConfigResolved, loadConfig, loadEnv, mergeConfig, index_d_exports as plugins, resetCache, resolvePluginConfig, rolldown, rolldownExperimental, runBuild, runServer, setupInteractiveMode };
package/dist/index.js CHANGED
@@ -17,6 +17,6 @@ import { runServer } from "./utils/run-server.js";
17
17
  import { setupInteractiveMode } from "./node/commands/start/setup-interactive-mode.js";
18
18
  import { createCommand, createReactNativeCliCommand } from "./node/cli-utils.js";
19
19
  import { cli_exports } from "./node/cli.js";
20
- import * as rolldown from "@rollipop/rolldown";
21
20
  import * as rolldownExperimental from "@rollipop/rolldown/experimental";
21
+ import * as rolldown from "@rollipop/rolldown";
22
22
  export { assets_exports as AssetUtils, Bundler, constants_exports as Constants, DEFAULT_HOST, DEFAULT_PORT, DEV_SERVER_ASSET_PATH, cli_exports as cli, createCommand, createDevServer, createReactNativeCliCommand, defineConfig, flattenPluginOption, getDefaultConfig, invokeConfigResolved, loadConfig, loadEnv, mergeConfig, plugins_exports as plugins, resetCache, resolvePluginConfig, rolldown, rolldownExperimental, runBuild, runServer, setupInteractiveMode };
@@ -9,16 +9,13 @@ function getInitializeCorePath(basePath) {
9
9
  function getPolyfillScriptPaths(reactNativePath) {
10
10
  return __require(path.join(reactNativePath, "rn-get-polyfills"))();
11
11
  }
12
- function getGlobalVariables(dev, buildType) {
13
- const isDevServerMode = dev && buildType === "serve";
12
+ function getGlobalVariables(dev) {
14
13
  return [
15
14
  `var __BUNDLE_START_TIME__ = globalThis.nativePerformanceNow ? nativePerformanceNow() : Date.now();`,
16
15
  `var __DEV__ = ${asLiteral(dev)};`,
17
16
  `var process = globalThis.process || {};`,
18
17
  "process.env = process.env || {};",
19
- `process.env.NODE_ENV = process.env.NODE_ENV || ${asLiteral(dev ? "development" : "production")};`,
20
- isDevServerMode ? `var $RefreshReg$ = () => {};` : null,
21
- isDevServerMode ? `var $RefreshSig$ = () => (v) => v;` : null
18
+ `process.env.NODE_ENV = process.env.NODE_ENV || ${asLiteral(dev ? "development" : "production")};`
22
19
  ].filter(isNotNil);
23
20
  }
24
21
  //#endregion
@@ -15,7 +15,7 @@ const action = async function(options) {
15
15
  context: { command: "bundle" }
16
16
  });
17
17
  if (options.resetCache) {
18
- resetCache(cwd);
18
+ await resetCache();
19
19
  logger.info("The transform cache was reset");
20
20
  }
21
21
  if (options.entryFile) config.entry = path.resolve(cwd, options.entryFile);
@@ -7,15 +7,14 @@ import "../../../index.js";
7
7
  import { noop } from "es-toolkit";
8
8
  //#region src/node/commands/start/action.ts
9
9
  const action = async function(options) {
10
- const cwd = process.cwd();
11
10
  const config = await loadConfig({
12
- cwd,
11
+ cwd: process.cwd(),
13
12
  mode: "development",
14
13
  configFile: options.config,
15
14
  context: { command: "start" }
16
15
  });
17
16
  if (options.resetCache) {
18
- resetCache(cwd);
17
+ await resetCache();
19
18
  logger.info("The transform cache was reset");
20
19
  }
21
20
  if (options.clientLogs === false) config.reporter = { update: noop };
package/dist/package.js CHANGED
@@ -1,4 +1,4 @@
1
1
  //#region package.json
2
- var version = "1.0.0-alpha.26";
2
+ var version = "1.0.0-alpha.28";
3
3
  //#endregion
4
4
  export { version };
@@ -5,13 +5,11 @@ import { BundlerPool } from "./bundler-pool.js";
5
5
  import { DEFAULT_HOST, DEFAULT_PORT } from "./constants.js";
6
6
  import { errorHandler } from "./error.js";
7
7
  import { ServerEventBus } from "./events/event-bus.js";
8
- import { toSSEEvent } from "./sse/adapter.js";
9
8
  import { plugin } from "./mcp/server.js";
10
9
  import { plugin as plugin$1 } from "./middlewares/dashboard.js";
11
10
  import { requestLogger } from "./middlewares/request-logger.js";
12
11
  import { plugin as plugin$2 } from "./middlewares/serve-assets.js";
13
12
  import { plugin as plugin$3 } from "./middlewares/serve-bundle.js";
14
- import { SSEEventPublisher } from "./sse/event-bus.js";
15
13
  import { plugin as plugin$4 } from "./middlewares/sse.js";
16
14
  import { plugin as plugin$5 } from "./middlewares/symbolicate.js";
17
15
  import { plugin as plugin$6 } from "./rest/index.js";
@@ -49,12 +47,7 @@ async function createDevServer(config, options) {
49
47
  host,
50
48
  port
51
49
  }, eventBus);
52
- const ssePublisher = new SSEEventPublisher();
53
50
  const reporter = config.reporter;
54
- eventBus.subscribe((event) => {
55
- const sseEvent = toSSEEvent(event);
56
- if (sseEvent != null) ssePublisher.publish(sseEvent);
57
- });
58
51
  const { middleware: communityMiddleware, websocketEndpoints: communityWebsocketEndpoints, messageSocketEndpoint: { server: messageServer, broadcast }, eventsSocketEndpoint: { server: eventsServer, reportEvent } } = createDevServerMiddleware({
59
52
  port,
60
53
  host,
@@ -9,7 +9,7 @@ import fp from "fastify-plugin";
9
9
  function createMcpServer(options) {
10
10
  const server = new McpServer({
11
11
  name: "rollipop",
12
- version: "1.0.0-alpha.26"
12
+ version: "1.0.0-alpha.28"
13
13
  }, { capabilities: { logging: {} } });
14
14
  registerTools(server, options);
15
15
  return server;
@@ -31,7 +31,7 @@ function registerTools(server, options) {
31
31
  description: "Clear the build cache.",
32
32
  inputSchema: emptyArgs,
33
33
  async handler() {
34
- resetCache(context.config.root);
34
+ await resetCache();
35
35
  context.eventBus.emit({ type: "cache_reset" });
36
36
  return textResult("Cache cleared successfully.");
37
37
  }
@@ -18,8 +18,14 @@ const plugin = fp((fastify, options) => {
18
18
  index: [INDEX_FILE],
19
19
  wildcard: false
20
20
  });
21
- fastify.get(DASHBOARD_PATH, (_request, reply) => reply.sendFile(INDEX_FILE));
22
- fastify.get(`${DASHBOARD_PATH}/analyze-report/:reportFile`, async (request, reply) => {
21
+ fastify.get(DASHBOARD_PATH, (_request, reply) => reply.sendFile(INDEX_FILE)).get(`${DASHBOARD_PATH}/*`, (request, reply) => {
22
+ if (shouldServeNotFoundPage(request)) return reply.sendFile(INDEX_FILE);
23
+ return reply.status(404).send({
24
+ statusCode: 404,
25
+ error: "Not Found",
26
+ message: "Not Found"
27
+ });
28
+ }).get(`${DASHBOARD_PATH}/analyze-report/:reportFile`, async (request, reply) => {
23
29
  const { reportFile } = request.params;
24
30
  if (!reportFile.endsWith(".html")) return reply.status(400).send({ error: {
25
31
  code: "INVALID_ANALYZE_REPORT_ID",
@@ -29,15 +29,16 @@ const plugin = fp((fastify, options) => {
29
29
  const assetPath = resolveAsset(pathname.replace(new RegExp(`^/${DEV_SERVER_ASSET_PATH}/?`), ""));
30
30
  let handle = null;
31
31
  try {
32
- handle = await fs.promises.open(resolveAssetPath(assetPath, {
32
+ const resolvedAssetPath = resolveAssetPath(assetPath, {
33
33
  platform: query.platform,
34
34
  preferNativePlatform: context.config.resolver.preferNativePlatform
35
- }, 1), "r");
35
+ });
36
+ handle = await fs.promises.open(resolvedAssetPath, "r");
36
37
  const assetData = await handle.readFile();
37
38
  const { size } = await handle.stat();
38
- await reply.header("Content-Type", mime.getType(assetPath) ?? "").header("Content-Length", size).send(assetData);
39
+ await reply.header("Content-Type", mime.getType(resolvedAssetPath) ?? "").header("Content-Length", size).send(assetData);
39
40
  } catch (error) {
40
- fastify.log.error(error, "Failed to serve asset (scale assets resolving is not implemented yet)");
41
+ fastify.log.error(error, "Failed to serve asset");
41
42
  await reply.status(500).send();
42
43
  } finally {
43
44
  await handle?.close();
@@ -1,7 +1,7 @@
1
1
  import { isDebugEnabled } from "../../common/env.js";
2
2
  import { getBaseBundleName } from "../../utils/bundle.js";
3
3
  import { parseUrl } from "../../utils/url.js";
4
- import { symbolicate } from "../symbolicate.js";
4
+ import { symbolicateWithBundleResolver } from "../symbolicate.js";
5
5
  import chalk from "chalk";
6
6
  import fp from "fastify-plugin";
7
7
  import { asConst } from "json-schema-to-ts";
@@ -23,31 +23,35 @@ const plugin = fp((fastify, options) => {
23
23
  schema: { body: bodySchema },
24
24
  async handler(request, reply) {
25
25
  const { stack } = request.body;
26
- const bundleUrl = findBundleUrl(stack);
27
- if (bundleUrl == null) {
26
+ const bundleStores = getBundleStoresByFrameUrl(stack, context);
27
+ if (bundleStores.size === 0) {
28
28
  await reply.header("Content-Type", "application/json").send(createFallbackResult(stack));
29
29
  return;
30
30
  }
31
- const { pathname, query } = bundleUrl;
32
- const platform = query.platform;
33
- const dev = query.dev == null ? context.config.mode === "development" : query.dev === "true";
34
- const bundleName = getBaseBundleName(pathname);
35
- const symbolicateResult = await symbolicate(await context.bundlerPool.get(bundleName, {
36
- platform,
37
- dev
38
- }).getBundle(), stack);
31
+ const symbolicateResult = await symbolicateWithBundleResolver(stack, async (frame) => frame.file == null ? void 0 : await bundleStores.get(frame.file));
39
32
  if (isDebugEnabled()) printSymbolicateResult(stack, symbolicateResult);
40
33
  await reply.header("Content-Type", "application/json").send(symbolicateResult);
41
34
  }
42
35
  });
43
36
  }, { name: "symbolicate" });
44
- function findBundleUrl(stack) {
37
+ function getBundleStoresByFrameUrl(stack, context) {
38
+ const bundleStores = /* @__PURE__ */ new Map();
45
39
  for (const frame of stack) {
46
- if (!frame.file?.startsWith("http")) continue;
47
- const parsed = parseStackFrameFile(frame.file);
48
- if (parsed?.query.platform) return parsed;
40
+ const file = frame.file;
41
+ if (!file?.startsWith("http") || bundleStores.has(file)) continue;
42
+ const parsed = parseStackFrameFile(file);
43
+ if (parsed?.query.platform == null) continue;
44
+ const { pathname, query } = parsed;
45
+ const platform = query.platform;
46
+ const dev = query.dev == null ? context.config.mode === "development" : query.dev === "true";
47
+ const bundleName = getBaseBundleName(pathname);
48
+ const bundler = context.bundlerPool.get(bundleName, {
49
+ platform,
50
+ dev
51
+ });
52
+ bundleStores.set(file, bundler.getBundle());
49
53
  }
50
- return null;
54
+ return bundleStores;
51
55
  }
52
56
  function parseStackFrameFile(file) {
53
57
  try {
@@ -7,8 +7,8 @@ const actionsRest = fp((fastify, options) => {
7
7
  context.message.broadcast("reload");
8
8
  return { reloaded: true };
9
9
  });
10
- fastify.post("/reset-cache", () => {
11
- resetCache(context.config.root);
10
+ fastify.post("/reset-cache", async () => {
11
+ await resetCache();
12
12
  context.eventBus.emit({ type: "cache_reset" });
13
13
  return { reset: true };
14
14
  });
@@ -28,7 +28,15 @@ var DevServerState = class {
28
28
  this.clearBuilds();
29
29
  }
30
30
  handleEvent(event) {
31
- this.builds.handleEvent(event);
31
+ switch (event.type) {
32
+ case "bundle_build_started":
33
+ case "bundle_build_done":
34
+ case "bundle_build_failed":
35
+ case "build_log":
36
+ case "build_error":
37
+ this.builds.handleEvent(event);
38
+ break;
39
+ }
32
40
  }
33
41
  };
34
42
  var BuildStore = class {
@@ -26,11 +26,21 @@ const INTERNAL_CALLSITES_REGEX = new RegExp([
26
26
  "^\\[native code\\]$"
27
27
  ].map((pathPattern) => pathPattern.replaceAll("/", "[/\\\\]")).join("|"));
28
28
  async function symbolicate(bundleStore, stack) {
29
- const sourceMapConsumer = await bundleStore.sourceMapConsumer;
30
- const symbolicatedStack = stack.filter((frame) => frame.file?.startsWith("http")).map((frame) => sourceMapConsumer ? originalPositionFor(sourceMapConsumer, frame) : frame).map((frame) => collapseFrame(frame));
29
+ return symbolicateWithBundleResolver(stack, (frame) => frame.file?.startsWith("http") ? bundleStore : void 0);
30
+ }
31
+ async function symbolicateWithBundleResolver(stack, resolveBundleStore) {
32
+ const symbolicatedStack = await Promise.all(stack.map(async (frame) => {
33
+ const bundleStore = frame.file?.startsWith("http") ? await resolveBundleStore(frame) : void 0;
34
+ const sourceMapConsumer = await bundleStore?.sourceMapConsumer;
35
+ return {
36
+ bundleStore,
37
+ frame: collapseFrame(sourceMapConsumer ? originalPositionFor(sourceMapConsumer, frame) : frame),
38
+ sourceMapConsumer
39
+ };
40
+ }));
31
41
  return {
32
- stack: symbolicatedStack,
33
- codeFrame: getCodeFrame(symbolicatedStack, bundleStore, sourceMapConsumer)
42
+ stack: symbolicatedStack.map(({ frame }) => frame),
43
+ codeFrame: getCodeFrame(symbolicatedStack)
34
44
  };
35
45
  }
36
46
  function originalPositionFor(sourceMapConsumer, frame) {
@@ -43,7 +53,7 @@ function originalPositionFor(sourceMapConsumer, frame) {
43
53
  const targetKey = convertFrameKey(key);
44
54
  return {
45
55
  ...frame,
46
- ...value ? { [targetKey]: value } : null
56
+ ...value != null ? { [targetKey]: value } : null
47
57
  };
48
58
  }, frame);
49
59
  }
@@ -62,23 +72,29 @@ function convertFrameKey(key) {
62
72
  else if (key === "name") return "methodName";
63
73
  return key;
64
74
  }
65
- function getCodeFrame(frames, bundleStore, sourceMapConsumer) {
66
- const frame = frames.find((frame) => {
67
- return frame.lineNumber != null && frame.column != null && !isCollapsed(frame);
68
- });
69
- if (frame?.file == null || frame.column == null || frame.lineNumber == null) return null;
75
+ function getCodeFrame(frames) {
76
+ for (const match of frames) {
77
+ const frame = match.frame;
78
+ if (frame.file == null || frame.column == null || frame.lineNumber == null) continue;
79
+ if (isCollapsed(frame)) continue;
80
+ const codeFrame = createCodeFrame(match);
81
+ if (codeFrame != null) return codeFrame;
82
+ }
83
+ return null;
84
+ }
85
+ function createCodeFrame({ bundleStore, frame, sourceMapConsumer }) {
70
86
  try {
71
87
  const { lineNumber, column, file } = frame;
72
- const unresolved = file.startsWith("http");
73
- const source = sourceMapConsumer == null || unresolved ? bundleStore.code : sourceMapConsumer.sourceContentFor(frame.file);
88
+ if (file == null || lineNumber == null || column == null) return null;
89
+ const unresolved = file?.startsWith("http") ?? false;
90
+ const source = sourceMapConsumer == null || unresolved ? bundleStore?.code : sourceMapConsumer.sourceContentFor(file, true);
91
+ if (!source) return null;
74
92
  const fileName = unresolved ? parseUrl(file).pathname ?? "unknown" : file;
75
- let content = "";
76
- if (source) content = codeFrameColumns(source, { start: {
77
- column,
78
- line: lineNumber
79
- } }, { highlightCode: true });
80
93
  return {
81
- content,
94
+ content: codeFrameColumns(source, { start: {
95
+ column: column + 1,
96
+ line: lineNumber
97
+ } }, { highlightCode: true }),
82
98
  fileName,
83
99
  location: {
84
100
  column,
@@ -90,4 +106,4 @@ function getCodeFrame(frames, bundleStore, sourceMapConsumer) {
90
106
  }
91
107
  }
92
108
  //#endregion
93
- export { symbolicate };
109
+ export { symbolicate, symbolicateWithBundleResolver };
@@ -28,7 +28,7 @@ var FileStorage = class FileStorage {
28
28
  this.dataFilePath = path.join(FileStorage.getPath(basePath, { prepare: true }), DATA_FILENAME);
29
29
  if (fs.existsSync(this.dataFilePath)) {
30
30
  const loadedData = JSON.parse(fs.readFileSync(this.dataFilePath, "utf-8"));
31
- if ("version" in loadedData && loadedData.version === "1.0.0-alpha.26") this.data = loadedData;
31
+ if ("version" in loadedData && loadedData.version === "1.0.0-alpha.28") this.data = loadedData;
32
32
  else {
33
33
  this.data = createDefaultData();
34
34
  this.flush();
@@ -1,8 +1,7 @@
1
1
  //#region src/utils/reset-cache.d.ts
2
2
  /**
3
- * Remove the entire build cache directory for the given project root.
4
- * Backs the `reset_cache` MCP tool and the `--reset-cache` CLI flag.
3
+ * Clear the build cache.
5
4
  */
6
- declare function resetCache(projectRoot: string): void;
5
+ declare function resetCache(): Promise<void>;
7
6
  //#endregion
8
7
  export { resetCache };
@@ -1,25 +1,10 @@
1
- import { FileStorage } from "../storage/file-storage.js";
2
- import fs from "node:fs";
3
- import path from "node:path";
1
+ import * as rolldownExperimental from "@rollipop/rolldown/experimental";
4
2
  //#region src/utils/reset-cache.ts
5
3
  /**
6
- * Resolve the build cache directory for the given project root. The cache
7
- * itself is owned by rolldown's native implementation; we keep the path
8
- * here only because `resetCache` — and any tooling that wants to inspect
9
- * the on-disk layout — needs to know where to look.
4
+ * Clear the build cache.
10
5
  */
11
- function getCacheDirectory(projectRoot) {
12
- return path.join(FileStorage.getPath(projectRoot), "cache");
13
- }
14
- /**
15
- * Remove the entire build cache directory for the given project root.
16
- * Backs the `reset_cache` MCP tool and the `--reset-cache` CLI flag.
17
- */
18
- function resetCache(projectRoot) {
19
- fs.rmSync(getCacheDirectory(projectRoot), {
20
- recursive: true,
21
- force: true
22
- });
6
+ function resetCache() {
7
+ return rolldownExperimental.clearCache();
23
8
  }
24
9
  //#endregion
25
10
  export { resetCache };