@ecopages/react 0.2.0-alpha.2 → 0.2.0-alpha.20

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 (66) hide show
  1. package/CHANGELOG.md +19 -39
  2. package/README.md +160 -18
  3. package/package.json +6 -6
  4. package/src/react-hmr-strategy.d.ts +26 -21
  5. package/src/react-hmr-strategy.js +91 -110
  6. package/src/react-renderer.d.ts +165 -41
  7. package/src/react-renderer.js +451 -158
  8. package/src/react.constants.d.ts +1 -0
  9. package/src/react.constants.js +4 -0
  10. package/src/react.plugin.d.ts +37 -108
  11. package/src/react.plugin.js +125 -54
  12. package/src/react.types.d.ts +88 -0
  13. package/src/react.types.js +0 -0
  14. package/src/router-adapter.d.ts +2 -2
  15. package/src/services/react-bundle.service.d.ts +4 -25
  16. package/src/services/react-bundle.service.js +39 -91
  17. package/src/services/react-hmr-page-metadata-cache.d.ts +9 -0
  18. package/src/services/react-hmr-page-metadata-cache.js +18 -2
  19. package/src/services/react-hydration-asset.service.d.ts +7 -6
  20. package/src/services/react-hydration-asset.service.js +29 -17
  21. package/src/services/react-mdx-config-dependency.service.d.ts +36 -0
  22. package/src/services/react-mdx-config-dependency.service.js +122 -0
  23. package/src/services/react-page-module.service.d.ts +8 -2
  24. package/src/services/react-page-module.service.js +44 -37
  25. package/src/services/react-page-payload.service.d.ts +46 -0
  26. package/src/services/react-page-payload.service.js +67 -0
  27. package/src/services/react-runtime-bundle.service.d.ts +14 -12
  28. package/src/services/react-runtime-bundle.service.js +103 -180
  29. package/src/utils/client-graph-boundary-plugin.js +149 -11
  30. package/src/utils/component-config-traversal.d.ts +36 -0
  31. package/src/utils/component-config-traversal.js +54 -0
  32. package/src/utils/declared-modules.d.ts +1 -1
  33. package/src/utils/declared-modules.js +7 -16
  34. package/src/utils/dynamic.test.browser.d.ts +1 -0
  35. package/src/utils/dynamic.test.browser.js +33 -0
  36. package/src/utils/hydration-scripts.d.ts +19 -4
  37. package/src/utils/hydration-scripts.js +102 -39
  38. package/src/utils/hydration-scripts.test.browser.d.ts +1 -0
  39. package/src/utils/hydration-scripts.test.browser.js +126 -0
  40. package/src/utils/reachability-analyzer.d.ts +12 -1
  41. package/src/utils/reachability-analyzer.js +101 -5
  42. package/src/utils/react-dom-runtime-interop-plugin.d.ts +5 -0
  43. package/src/utils/react-dom-runtime-interop-plugin.js +29 -0
  44. package/src/utils/react-mdx-loader-plugin.js +13 -5
  45. package/src/utils/react-runtime-specifier-map.d.ts +6 -0
  46. package/src/utils/react-runtime-specifier-map.js +37 -0
  47. package/src/utils/use-sync-external-store-shim-plugin.d.ts +5 -0
  48. package/src/utils/use-sync-external-store-shim-plugin.js +41 -0
  49. package/src/react-hmr-strategy.ts +0 -444
  50. package/src/react-renderer.ts +0 -403
  51. package/src/react.plugin.ts +0 -241
  52. package/src/router-adapter.ts +0 -95
  53. package/src/services/react-bundle.service.ts +0 -212
  54. package/src/services/react-hmr-page-metadata-cache.ts +0 -24
  55. package/src/services/react-hydration-asset.service.ts +0 -260
  56. package/src/services/react-page-module.service.ts +0 -214
  57. package/src/services/react-runtime-bundle.service.ts +0 -271
  58. package/src/utils/client-graph-boundary-plugin.ts +0 -590
  59. package/src/utils/client-only.ts +0 -27
  60. package/src/utils/declared-modules.ts +0 -99
  61. package/src/utils/dynamic.ts +0 -27
  62. package/src/utils/hmr-scripts.ts +0 -47
  63. package/src/utils/html-boundary.ts +0 -66
  64. package/src/utils/hydration-scripts.ts +0 -338
  65. package/src/utils/reachability-analyzer.ts +0 -440
  66. package/src/utils/react-mdx-loader-plugin.ts +0 -40
@@ -0,0 +1 @@
1
+ export declare const REACT_PLUGIN_NAME = "react";
@@ -0,0 +1,4 @@
1
+ const REACT_PLUGIN_NAME = "react";
2
+ export {
3
+ REACT_PLUGIN_NAME
4
+ };
@@ -1,94 +1,10 @@
1
- /**
2
- * This module contains the react plugin for Ecopages
3
- * @module
4
- */
5
1
  import { IntegrationPlugin } from '@ecopages/core/plugins/integration-plugin';
6
2
  import type { EcoBuildPlugin } from '@ecopages/core/build/build-types';
7
3
  import type { HmrStrategy } from '@ecopages/core/hmr/hmr-strategy';
8
- import type { IHmrManager } from '@ecopages/core/internal-types';
9
- import type { AssetDefinition } from '@ecopages/core/services/asset-processing-service';
10
- import type { CompileOptions } from '@mdx-js/mdx';
11
4
  import type React from 'react';
12
5
  import { ReactRenderer } from './react-renderer.js';
13
- import type { ReactRouterAdapter } from './router-adapter.js';
14
- import type { ComponentBoundaryPolicyInput } from '@ecopages/core/plugins/integration-plugin';
15
- /**
16
- * MDX configuration options for the React plugin
17
- */
18
- export type ReactMdxOptions = {
19
- /**
20
- * Whether to enable MDX support.
21
- * @default false
22
- */
23
- enabled: boolean;
24
- /**
25
- * Compiler options for MDX.
26
- * @default undefined
27
- */
28
- compilerOptions?: Omit<CompileOptions, 'jsxImportSource' | 'jsxRuntime'>;
29
- /**
30
- * Remark plugins.
31
- * @default undefined
32
- */
33
- remarkPlugins?: CompileOptions['remarkPlugins'];
34
- /**
35
- * Rehype plugins.
36
- * @default undefined
37
- */
38
- rehypePlugins?: CompileOptions['rehypePlugins'];
39
- /**
40
- * Recma plugins.
41
- * @default undefined
42
- */
43
- recmaPlugins?: CompileOptions['recmaPlugins'];
44
- /**
45
- * Custom extensions to be treated as MDX files.
46
- * @default ['.mdx']
47
- */
48
- extensions?: string[];
49
- };
50
- /**
51
- * Options for the React plugin
52
- */
53
- export type ReactPluginOptions = {
54
- extensions?: string[];
55
- dependencies?: AssetDefinition[];
56
- /**
57
- * Enables explicit client graph mode for React page entries.
58
- *
59
- * When enabled, React page-entry bundling relies on explicit dependency declarations
60
- * and skips AST-based `middleware`/`requires` stripping in the React path.
61
- * @default false
62
- */
63
- explicitGraph?: boolean;
64
- /**
65
- * Router adapter for SPA navigation.
66
- * When provided, pages with layouts will be wrapped in the router for client-side navigation.
67
- * @example
68
- * ```ts
69
- * import { ecoRouter } from '@ecopages/react-router';
70
- * reactPlugin({ router: ecoRouter() })
71
- * ```
72
- */
73
- router?: ReactRouterAdapter;
74
- /**
75
- * MDX configuration for handling .mdx files within the React plugin.
76
- * When enabled, MDX files are treated as React pages with full router support.
77
- * @example
78
- * ```ts
79
- * reactPlugin({
80
- * router: ecoRouter(),
81
- * mdx: {
82
- * enabled: true,
83
- * extensions: ['.mdx', '.md'],
84
- * remarkPlugins: [remarkGfm],
85
- * rehypePlugins: [[rehypePrettyCode, { theme: '...' }]],
86
- * }
87
- * })
88
- * ```
89
- */
90
- mdx?: ReactMdxOptions;
91
- };
6
+ import type { ReactPluginOptions } from './react.types.js';
7
+ export type { ReactMdxOptions, ReactPluginOptions, ReactRendererConfig } from './react.types.js';
92
8
  /**
93
9
  * The name of the React plugin
94
10
  */
@@ -99,19 +15,46 @@ export declare const PLUGIN_NAME = "react";
99
15
  */
100
16
  export declare class ReactPlugin extends IntegrationPlugin<React.JSX.Element> {
101
17
  renderer: typeof ReactRenderer;
102
- routerAdapter: ReactRouterAdapter | undefined;
103
- private mdxEnabled;
104
- private mdxCompilerOptions?;
105
- private mdxExtensions;
18
+ private readonly routerAdapter;
19
+ private readonly mdxEnabled;
20
+ private readonly mdxCompilerOptions?;
21
+ private readonly mdxExtensions;
106
22
  private mdxLoaderPlugin;
107
- private runtimeBundleService;
23
+ private readonly runtimeBundleService;
108
24
  private readonly hmrPageMetadataCache;
25
+ private runtimeDependenciesInitialized;
109
26
  /**
110
27
  * Indicates whether React explicit graph mode is enabled for renderer/HMR behavior.
111
28
  */
112
- private explicitGraphEnabled;
113
- constructor(options?: Omit<ReactPluginOptions, 'name'>);
29
+ private readonly explicitGraphEnabled;
30
+ private readonly rendererConfig;
31
+ constructor(options?: ReactPluginOptions);
32
+ /**
33
+ * Creates a React renderer with instance-owned runtime configuration.
34
+ *
35
+ * React renderers depend on plugin-owned router, MDX, and HMR metadata state.
36
+ * Keeping that state on the instance avoids cross-plugin static mutation while
37
+ * preserving the same runtime services the base initializer wires up.
38
+ */
39
+ initializeRenderer(options?: {
40
+ rendererModules?: unknown;
41
+ }): ReactRenderer;
42
+ private ensureRuntimeDependencies;
114
43
  get plugins(): EcoBuildPlugin[];
44
+ /**
45
+ * Ensures the optional React MDX loader exists before either config-time
46
+ * manifest sealing or runtime setup needs it.
47
+ */
48
+ private ensureMdxLoaderPlugin;
49
+ /**
50
+ * Prepares React's build-facing loader contributions before config build seals
51
+ * the app manifest.
52
+ */
53
+ prepareBuildContributions(): Promise<void>;
54
+ /**
55
+ * Performs runtime-only React setup after build contributions are already
56
+ * materialized.
57
+ */
115
58
  setup(): Promise<void>;
116
59
  /**
117
60
  * Provides React-specific HMR strategy with Fast Refresh support.
@@ -123,21 +66,7 @@ export declare class ReactPlugin extends IntegrationPlugin<React.JSX.Element> {
123
66
  * @returns ReactHmrStrategy instance for handling React component updates
124
67
  */
125
68
  getHmrStrategy(): HmrStrategy | undefined;
126
- /**
127
- * Override to register React-specific specifier mappings for HMR.
128
- */
129
- setHmrManager(hmrManager: IHmrManager): void;
130
- /**
131
- * Declares React's boundary deferral rule for cross-integration rendering.
132
- *
133
- * React defers when a render pass owned by another integration enters a React
134
- * component boundary. That boundary is then resolved later through the marker
135
- * graph stage using the React renderer.
136
- *
137
- * @param input Boundary metadata for the active render pass.
138
- * @returns `true` when the boundary should be deferred into the marker pass.
139
- */
140
- shouldDeferComponentBoundary(input: ComponentBoundaryPolicyInput): boolean;
69
+ getRuntimeSpecifierMap(): Record<string, string>;
141
70
  }
142
71
  /**
143
72
  * Factory function to create a React plugin instance
@@ -1,11 +1,65 @@
1
1
  import { IntegrationPlugin } from "@ecopages/core/plugins/integration-plugin";
2
2
  import { Logger } from "@ecopages/logger";
3
+ import { REACT_PLUGIN_NAME } from "./react.constants.js";
3
4
  import { ReactRenderer } from "./react-renderer.js";
4
5
  import { ReactHmrStrategy } from "./react-hmr-strategy.js";
5
6
  import { ReactRuntimeBundleService } from "./services/react-runtime-bundle.service.js";
6
7
  import { ReactHmrPageMetadataCache } from "./services/react-hmr-page-metadata-cache.js";
7
8
  const appLogger = new Logger("[ReactPlugin]");
8
- const PLUGIN_NAME = "react";
9
+ const PLUGIN_NAME = REACT_PLUGIN_NAME;
10
+ const mergePluginLists = (...lists) => {
11
+ const merged = lists.flatMap((list) => list ? [...list] : []);
12
+ return merged.length > 0 ? merged : void 0;
13
+ };
14
+ const appendMdxExtensions = (target, mdxExtensions) => {
15
+ for (const extension of mdxExtensions) {
16
+ if (!target.includes(extension)) {
17
+ target.push(extension);
18
+ }
19
+ }
20
+ };
21
+ const resolveReactMdxCompilerOptions = (mdxOptions) => {
22
+ const { compilerOptions, remarkPlugins, rehypePlugins, recmaPlugins } = mdxOptions;
23
+ const resolved = {
24
+ ...compilerOptions,
25
+ jsxImportSource: "react",
26
+ jsxRuntime: "automatic",
27
+ development: process.env.NODE_ENV === "development"
28
+ };
29
+ const mergedRemark = mergePluginLists(compilerOptions?.remarkPlugins, remarkPlugins);
30
+ const mergedRehype = mergePluginLists(compilerOptions?.rehypePlugins, rehypePlugins);
31
+ const mergedRecma = mergePluginLists(compilerOptions?.recmaPlugins, recmaPlugins);
32
+ if (mergedRemark) resolved.remarkPlugins = mergedRemark;
33
+ if (mergedRehype) resolved.rehypePlugins = mergedRehype;
34
+ if (mergedRecma) resolved.recmaPlugins = mergedRecma;
35
+ return resolved;
36
+ };
37
+ const resolveReactPluginOptions = (options) => {
38
+ const { extensions: userExtensions, router, mdx, explicitGraph, dependencies, ...baseConfig } = options ?? {};
39
+ const extensions = [...userExtensions ?? [".tsx"]];
40
+ const mdxEnabled = mdx?.enabled ?? false;
41
+ const mdxExtensions = mdx?.extensions ?? [".mdx"];
42
+ if (mdxEnabled) {
43
+ appendMdxExtensions(extensions, mdxExtensions);
44
+ } else if (mdx?.extensions?.length) {
45
+ appLogger.warn(
46
+ "MDX extensions provided but MDX is disabled. MDX files will not be processed. Set mdx.enabled to true to enable MDX support."
47
+ );
48
+ }
49
+ const rendererConfig = {
50
+ routerAdapter: router,
51
+ mdxCompilerOptions: mdxEnabled && mdx ? resolveReactMdxCompilerOptions(mdx) : void 0,
52
+ mdxExtensions,
53
+ hmrPageMetadataCache: new ReactHmrPageMetadataCache(),
54
+ explicitGraphEnabled: explicitGraph ?? false
55
+ };
56
+ return {
57
+ ...baseConfig,
58
+ extensions,
59
+ integrationDependencies: dependencies,
60
+ rendererConfig
61
+ };
62
+ };
9
63
  class ReactPlugin extends IntegrationPlugin {
10
64
  renderer = ReactRenderer;
11
65
  routerAdapter;
@@ -14,52 +68,63 @@ class ReactPlugin extends IntegrationPlugin {
14
68
  mdxExtensions;
15
69
  mdxLoaderPlugin;
16
70
  runtimeBundleService;
17
- hmrPageMetadataCache = new ReactHmrPageMetadataCache();
71
+ hmrPageMetadataCache;
72
+ runtimeDependenciesInitialized = false;
18
73
  /**
19
74
  * Indicates whether React explicit graph mode is enabled for renderer/HMR behavior.
20
75
  */
21
76
  explicitGraphEnabled;
77
+ rendererConfig;
22
78
  constructor(options) {
23
- const extensions = [".tsx"];
24
- const mdxExtensions = options?.mdx?.extensions ?? [".mdx"];
25
- if (options?.mdx?.enabled) {
26
- extensions.push(...mdxExtensions);
27
- } else if (options?.mdx?.extensions?.length) {
28
- appLogger.warn(
29
- "MDX extensions provided but MDX is disabled. MDX files will not be processed. Set mdx.enabled to true to enable MDX support."
30
- );
31
- }
79
+ const config = resolveReactPluginOptions(options);
80
+ const { extensions, rendererConfig, integrationDependencies, ...baseConfig } = config;
32
81
  super({
33
82
  name: PLUGIN_NAME,
34
83
  extensions,
35
- ...options
84
+ jsxImportSource: "react",
85
+ integrationDependencies,
86
+ ...baseConfig
36
87
  });
37
- this.mdxEnabled = options?.mdx?.enabled ?? false;
38
- this.mdxExtensions = mdxExtensions;
88
+ this.routerAdapter = rendererConfig.routerAdapter;
89
+ this.mdxCompilerOptions = rendererConfig.mdxCompilerOptions;
90
+ this.mdxEnabled = Boolean(rendererConfig.mdxCompilerOptions);
91
+ this.mdxExtensions = rendererConfig.mdxExtensions ?? [".mdx"];
92
+ this.hmrPageMetadataCache = rendererConfig.hmrPageMetadataCache ?? new ReactHmrPageMetadataCache();
93
+ this.explicitGraphEnabled = rendererConfig.explicitGraphEnabled ?? false;
94
+ this.rendererConfig = {
95
+ ...rendererConfig,
96
+ mdxExtensions: this.mdxExtensions,
97
+ hmrPageMetadataCache: this.hmrPageMetadataCache,
98
+ explicitGraphEnabled: this.explicitGraphEnabled
99
+ };
39
100
  if (this.mdxEnabled) {
40
- const { compilerOptions, remarkPlugins, rehypePlugins, recmaPlugins } = options?.mdx || {};
41
- this.mdxCompilerOptions = {
42
- ...compilerOptions,
43
- remarkPlugins: [...compilerOptions?.remarkPlugins || [], ...remarkPlugins || []],
44
- rehypePlugins: [...compilerOptions?.rehypePlugins || [], ...rehypePlugins || []],
45
- recmaPlugins: [...compilerOptions?.recmaPlugins || [], ...recmaPlugins || []],
46
- jsxImportSource: "react",
47
- jsxRuntime: "automatic",
48
- development: process.env.NODE_ENV === "development"
49
- };
50
101
  appLogger.debug("MDX mode enabled with React jsx runtime");
51
102
  }
52
- this.routerAdapter = options?.router;
53
103
  this.runtimeBundleService = new ReactRuntimeBundleService({
54
104
  routerAdapter: this.routerAdapter
55
105
  });
56
- this.explicitGraphEnabled = options?.explicitGraph ?? false;
57
- ReactRenderer.routerAdapter = this.routerAdapter;
58
- ReactRenderer.mdxCompilerOptions = this.mdxCompilerOptions;
59
- ReactRenderer.mdxExtensions = this.mdxExtensions;
60
- ReactRenderer.explicitGraphEnabled = this.explicitGraphEnabled;
61
- ReactRenderer.hmrPageMetadataCache = this.hmrPageMetadataCache;
106
+ }
107
+ /**
108
+ * Creates a React renderer with instance-owned runtime configuration.
109
+ *
110
+ * React renderers depend on plugin-owned router, MDX, and HMR metadata state.
111
+ * Keeping that state on the instance avoids cross-plugin static mutation while
112
+ * preserving the same runtime services the base initializer wires up.
113
+ */
114
+ initializeRenderer(options) {
115
+ const renderer = new this.renderer({
116
+ ...this.createRendererOptions(options),
117
+ reactConfig: this.rendererConfig
118
+ });
119
+ return this.attachRendererRuntimeServices(renderer);
120
+ }
121
+ ensureRuntimeDependencies() {
122
+ if (this.runtimeDependenciesInitialized) {
123
+ return;
124
+ }
125
+ this.runtimeBundleService.setRootDir(this.appConfig?.rootDir);
62
126
  this.integrationDependencies.unshift(...this.runtimeBundleService.getDependencies());
127
+ this.runtimeDependenciesInitialized = true;
63
128
  }
64
129
  get plugins() {
65
130
  if (this.mdxLoaderPlugin) {
@@ -67,11 +132,32 @@ class ReactPlugin extends IntegrationPlugin {
67
132
  }
68
133
  return [];
69
134
  }
70
- async setup() {
71
- if (this.mdxEnabled && this.mdxCompilerOptions) {
72
- const { createReactMdxLoaderPlugin } = await import("./utils/react-mdx-loader-plugin.js");
73
- this.mdxLoaderPlugin = createReactMdxLoaderPlugin(this.mdxCompilerOptions);
135
+ /**
136
+ * Ensures the optional React MDX loader exists before either config-time
137
+ * manifest sealing or runtime setup needs it.
138
+ */
139
+ async ensureMdxLoaderPlugin() {
140
+ if (!this.mdxEnabled || !this.mdxCompilerOptions || this.mdxLoaderPlugin) {
141
+ return;
74
142
  }
143
+ const { createReactMdxLoaderPlugin } = await import("./utils/react-mdx-loader-plugin.js");
144
+ this.mdxLoaderPlugin = createReactMdxLoaderPlugin(this.mdxCompilerOptions);
145
+ }
146
+ /**
147
+ * Prepares React's build-facing loader contributions before config build seals
148
+ * the app manifest.
149
+ */
150
+ async prepareBuildContributions() {
151
+ this.ensureRuntimeDependencies();
152
+ await this.ensureMdxLoaderPlugin();
153
+ }
154
+ /**
155
+ * Performs runtime-only React setup after build contributions are already
156
+ * materialized.
157
+ */
158
+ async setup() {
159
+ this.ensureRuntimeDependencies();
160
+ await this.ensureMdxLoaderPlugin();
75
161
  await super.setup();
76
162
  }
77
163
  /**
@@ -92,28 +178,13 @@ class ReactPlugin extends IntegrationPlugin {
92
178
  context,
93
179
  this.hmrPageMetadataCache,
94
180
  this.mdxCompilerOptions,
181
+ this.extensions,
182
+ this.appConfig.templatesExt,
95
183
  this.explicitGraphEnabled
96
184
  );
97
185
  }
98
- /**
99
- * Override to register React-specific specifier mappings for HMR.
100
- */
101
- setHmrManager(hmrManager) {
102
- super.setHmrManager(hmrManager);
103
- hmrManager.registerSpecifierMap(this.runtimeBundleService.getSpecifierMap());
104
- }
105
- /**
106
- * Declares React's boundary deferral rule for cross-integration rendering.
107
- *
108
- * React defers when a render pass owned by another integration enters a React
109
- * component boundary. That boundary is then resolved later through the marker
110
- * graph stage using the React renderer.
111
- *
112
- * @param input Boundary metadata for the active render pass.
113
- * @returns `true` when the boundary should be deferred into the marker pass.
114
- */
115
- shouldDeferComponentBoundary(input) {
116
- return input.targetIntegration === this.name && input.currentIntegration !== this.name;
186
+ getRuntimeSpecifierMap() {
187
+ return this.runtimeBundleService.getSpecifierMap();
117
188
  }
118
189
  }
119
190
  function reactPlugin(options) {
@@ -0,0 +1,88 @@
1
+ import type { AssetDefinition } from '@ecopages/core/services/asset-processing-service';
2
+ import type { CompileOptions } from '@mdx-js/mdx';
3
+ import type { ReactRouterAdapter } from './router-adapter.js';
4
+ import type { ReactHmrPageMetadataCache } from './services/react-hmr-page-metadata-cache.js';
5
+ /**
6
+ * MDX configuration options for the React plugin.
7
+ */
8
+ export type ReactMdxOptions = {
9
+ /**
10
+ * Whether to enable MDX support.
11
+ * @default false
12
+ */
13
+ enabled: boolean;
14
+ /**
15
+ * Compiler options for MDX.
16
+ * @default undefined
17
+ */
18
+ compilerOptions?: Omit<CompileOptions, 'jsxImportSource' | 'jsxRuntime'>;
19
+ /**
20
+ * Remark plugins.
21
+ * @default undefined
22
+ */
23
+ remarkPlugins?: CompileOptions['remarkPlugins'];
24
+ /**
25
+ * Rehype plugins.
26
+ * @default undefined
27
+ */
28
+ rehypePlugins?: CompileOptions['rehypePlugins'];
29
+ /**
30
+ * Recma plugins.
31
+ * @default undefined
32
+ */
33
+ recmaPlugins?: CompileOptions['recmaPlugins'];
34
+ /**
35
+ * Custom extensions to be treated as MDX files.
36
+ * @default ['.mdx']
37
+ */
38
+ extensions?: string[];
39
+ };
40
+ /**
41
+ * Options for the React plugin.
42
+ */
43
+ export type ReactPluginOptions = {
44
+ extensions?: string[];
45
+ dependencies?: AssetDefinition[];
46
+ /**
47
+ * Enables explicit client graph mode for React page entries.
48
+ *
49
+ * When enabled, React page-entry bundling relies on explicit dependency declarations
50
+ * and skips AST-based `middleware`/`requires` stripping in the React path.
51
+ * @default false
52
+ */
53
+ explicitGraph?: boolean;
54
+ /**
55
+ * Router adapter for SPA navigation.
56
+ * When provided, pages with layouts will be wrapped in the router for client-side navigation.
57
+ * @example
58
+ * ```ts
59
+ * import { ecoRouter } from '@ecopages/react-router';
60
+ * reactPlugin({ router: ecoRouter() })
61
+ * ```
62
+ */
63
+ router?: ReactRouterAdapter;
64
+ /**
65
+ * MDX configuration for handling .mdx files within the React plugin.
66
+ * When enabled, MDX files are treated as React pages with full router support.
67
+ * @example
68
+ * ```ts
69
+ * reactPlugin({
70
+ * router: ecoRouter(),
71
+ * mdx: {
72
+ * enabled: true,
73
+ * extensions: ['.mdx', '.md'],
74
+ * remarkPlugins: [remarkGfm],
75
+ * rehypePlugins: [[rehypePrettyCode, { theme: '...' }]],
76
+ * }
77
+ * })
78
+ * ```
79
+ */
80
+ mdx?: ReactMdxOptions;
81
+ };
82
+ export type ReactRendererConfig = {
83
+ routerAdapter?: ReactRouterAdapter;
84
+ mdxCompilerOptions?: CompileOptions;
85
+ mdxExtensions?: string[];
86
+ hmrPageMetadataCache?: ReactHmrPageMetadataCache;
87
+ explicitGraphEnabled?: boolean;
88
+ };
File without changes
@@ -46,13 +46,13 @@ export interface ReactRouterAdapter {
46
46
  outputName: string;
47
47
  /**
48
48
  * Packages to externalize when bundling.
49
- * These should be available via import map.
49
+ * These should be available through the runtime bare-specifier map.
50
50
  * @example ['react', 'react-dom', 'react/jsx-runtime']
51
51
  */
52
52
  externals: string[];
53
53
  };
54
54
  /**
55
- * Bare specifier for the import map entry.
55
+ * Bare specifier for the runtime mapping entry.
56
56
  * This is what the hydration script will import from.
57
57
  * @example '@ecopages/react-router'
58
58
  */
@@ -16,13 +16,15 @@ export interface ReactBundleServiceConfig {
16
16
  rootDir: string;
17
17
  routerAdapter?: ReactRouterAdapter;
18
18
  mdxCompilerOptions?: CompileOptions;
19
+ nonReactExtensions?: string[];
20
+ jsxImportSource?: string;
19
21
  }
20
22
  /**
21
23
  * Manages esbuild bundle configuration and plugin creation for React page/component builds.
22
24
  */
23
25
  export declare class ReactBundleService {
24
- private readonly config;
25
26
  private readonly runtimeBundleService;
27
+ private readonly config;
26
28
  constructor(config: ReactBundleServiceConfig);
27
29
  /**
28
30
  * Returns resolved runtime import paths for the React runtime.
@@ -41,28 +43,5 @@ export declare class ReactBundleService {
41
43
  * Creates the esbuild plugin that rewrites bare React specifiers
42
44
  * to their runtime asset URLs.
43
45
  */
44
- createRuntimeAliasPlugin(runtimeImports: ReactRuntimeImports): {
45
- name: string;
46
- setup(build: {
47
- onResolve: (options: {
48
- filter: RegExp;
49
- namespace?: string;
50
- }, callback: (args: {
51
- path: string;
52
- importer: string;
53
- namespace: string;
54
- }) => {
55
- path?: string;
56
- namespace?: string;
57
- external?: boolean;
58
- } | undefined) => void;
59
- }): void;
60
- };
61
- /**
62
- * Creates the esbuild plugin that shims `use-sync-external-store/shim`
63
- * to re-export from React's built-in `useSyncExternalStore`.
64
- * This is needed because some packages use `use-sync-external-store/shim`
65
- * but React 18+ has built-in `useSyncExternalStore`.
66
- */
67
- private createSyncExternalStorePlugin;
46
+ createRuntimeAliasPlugin(runtimeSpecifierMap: Record<string, string>): import("@ecopages/core/build/build-types").EcoBuildPlugin | null;
68
47
  }