@rangojs/router 0.0.0-experimental.62 → 0.0.0-experimental.63

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 (39) hide show
  1. package/README.md +61 -8
  2. package/dist/bin/rango.js +2 -1
  3. package/dist/vite/index.js +142 -62
  4. package/dist/vite/index.js.bak +5448 -0
  5. package/package.json +14 -15
  6. package/skills/prerender/SKILL.md +110 -68
  7. package/src/__internal.ts +1 -1
  8. package/src/build/generate-manifest.ts +3 -6
  9. package/src/build/route-types/scan-filter.ts +8 -1
  10. package/src/index.rsc.ts +3 -1
  11. package/src/index.ts +8 -0
  12. package/src/prerender/store.ts +5 -4
  13. package/src/prerender.ts +138 -77
  14. package/src/route-definition/dsl-helpers.ts +37 -18
  15. package/src/route-definition/index.ts +3 -0
  16. package/src/route-definition/resolve-handler-use.ts +149 -0
  17. package/src/route-types.ts +11 -0
  18. package/src/router/handler-context.ts +20 -5
  19. package/src/router/match-api.ts +2 -8
  20. package/src/router/match-middleware/cache-lookup.ts +2 -6
  21. package/src/router/prerender-match.ts +104 -8
  22. package/src/router/router-interfaces.ts +4 -0
  23. package/src/router/segment-resolution/fresh.ts +7 -2
  24. package/src/router/segment-resolution/revalidation.ts +10 -5
  25. package/src/router.ts +9 -1
  26. package/src/server/context.ts +5 -1
  27. package/src/static-handler.ts +18 -6
  28. package/src/types/handler-context.ts +12 -2
  29. package/src/types/route-entry.ts +1 -1
  30. package/src/urls/path-helper-types.ts +5 -1
  31. package/src/urls/path-helper.ts +47 -12
  32. package/src/urls/response-types.ts +16 -6
  33. package/src/vite/discovery/bundle-postprocess.ts +30 -33
  34. package/src/vite/discovery/prerender-collection.ts +14 -1
  35. package/src/vite/discovery/state.ts +13 -4
  36. package/src/vite/index.ts +4 -0
  37. package/src/vite/plugin-types.ts +60 -5
  38. package/src/vite/rango.ts +2 -1
  39. package/src/vite/router-discovery.ts +153 -34
package/README.md CHANGED
@@ -716,10 +716,12 @@ export const BlogPost = Prerender(
716
716
 
717
717
  ### Passthrough for Unknown Params
718
718
 
719
+ Wrap a `Prerender` definition with `Passthrough()` to add a live handler for unknown params at runtime. The build handler runs at build time, the live handler runs at request time for params not in the prerender cache.
720
+
719
721
  ```tsx
720
- import { Prerender } from "@rangojs/router";
722
+ import { Prerender, Passthrough } from "@rangojs/router";
721
723
 
722
- export const ProductPage = Prerender(
724
+ export const ProductPageDef = Prerender(
723
725
  async () => {
724
726
  const featured = await db.getFeaturedProducts();
725
727
  return featured.map((p) => ({ id: p.id }));
@@ -728,16 +730,22 @@ export const ProductPage = Prerender(
728
730
  const product = await db.getProduct(ctx.params.id);
729
731
  return <Product data={product} />;
730
732
  },
731
- { passthrough: true },
732
733
  );
733
- ```
734
734
 
735
- With `passthrough: true`, known params are served from the build-time cache and unknown params fall through to live rendering.
735
+ // In route definition:
736
+ path(
737
+ "/products/:id",
738
+ Passthrough(ProductPageDef, async (ctx) => {
739
+ const product = await ctx.env.DB.getProduct(ctx.params.id);
740
+ return <Product data={product} />;
741
+ }),
742
+ );
743
+ ```
736
744
 
737
- Handlers can also skip individual param sets with `ctx.passthrough()`, deferring them to the live handler at runtime:
745
+ Build handlers can also skip individual param sets with `ctx.passthrough()`, deferring them to the live handler:
738
746
 
739
747
  ```tsx
740
- export const ProductPage = Prerender(
748
+ export const ProductPageDef = Prerender(
741
749
  async () => {
742
750
  const all = await db.getAllProducts();
743
751
  return all.map((p) => ({ id: p.id }));
@@ -747,10 +755,55 @@ export const ProductPage = Prerender(
747
755
  if (!product.published) return ctx.passthrough();
748
756
  return <Product data={product} />;
749
757
  },
750
- { passthrough: true },
751
758
  );
752
759
  ```
753
760
 
761
+ ### Build-Time Environment Bindings
762
+
763
+ Prerender handlers can access platform bindings (KV, D1, R2) at build time when `buildEnv` is configured in the Vite plugin:
764
+
765
+ ```ts
766
+ // vite.config.ts
767
+ import { rango } from "@rangojs/router/vite";
768
+
769
+ rango({ preset: "cloudflare", buildEnv: "auto" });
770
+ ```
771
+
772
+ With `buildEnv: "auto"`, the plugin calls `wrangler.getPlatformProxy()` to provide local bindings. Handlers then access `ctx.env` during build:
773
+
774
+ ```tsx
775
+ export const BlogPosts = Prerender<{ slug: string }>(
776
+ async (ctx) => {
777
+ const rows = await ctx.env.DB.prepare("SELECT slug FROM posts").all();
778
+ return rows.map((r) => ({ slug: r.slug }));
779
+ },
780
+ async (ctx) => {
781
+ const post = await ctx.env.DB.prepare("SELECT * FROM posts WHERE slug = ?")
782
+ .bind(ctx.params.slug)
783
+ .first();
784
+ return <BlogPost post={post} />;
785
+ },
786
+ );
787
+ ```
788
+
789
+ `buildEnv` also accepts a factory function or plain object:
790
+
791
+ ```ts
792
+ // Custom factory
793
+ rango({
794
+ buildEnv: async (ctx) => {
795
+ const { getPlatformProxy } = await import("wrangler");
796
+ const proxy = await getPlatformProxy();
797
+ return { env: proxy.env, dispose: proxy.dispose };
798
+ },
799
+ });
800
+
801
+ // Plain object (Node.js)
802
+ rango({ buildEnv: { DATABASE_URL: process.env.DATABASE_URL } });
803
+ ```
804
+
805
+ Build-time env applies to both production builds and dev on-demand prerender. Without `buildEnv`, accessing `ctx.env` in a Prerender handler throws with a clear error.
806
+
754
807
  ## Theme
755
808
 
756
809
  ### Router Configuration
package/dist/bin/rango.js CHANGED
@@ -218,7 +218,8 @@ function findTsFiles(dir, filter) {
218
218
  for (const entry of entries) {
219
219
  const fullPath = join(dir, entry.name);
220
220
  if (entry.isDirectory()) {
221
- if (entry.name === "node_modules" || entry.name.startsWith(".")) continue;
221
+ if (entry.name === "node_modules" || entry.name.startsWith(".") || entry.name === "dist" || entry.name === "build" || entry.name === "coverage")
222
+ continue;
222
223
  results.push(...findTsFiles(fullPath, filter));
223
224
  } else if ((entry.name.endsWith(".ts") || entry.name.endsWith(".tsx") || entry.name.endsWith(".js") || entry.name.endsWith(".jsx")) && !entry.name.includes(".gen.")) {
224
225
  if (filter && !filter(fullPath)) continue;
@@ -1745,7 +1745,7 @@ import { resolve } from "node:path";
1745
1745
  // package.json
1746
1746
  var package_default = {
1747
1747
  name: "@rangojs/router",
1748
- version: "0.0.0-experimental.62",
1748
+ version: "0.0.0-experimental.63",
1749
1749
  description: "Django-inspired RSC router with composable URL patterns",
1750
1750
  keywords: [
1751
1751
  "react",
@@ -3141,6 +3141,8 @@ function createCjsToEsmPlugin() {
3141
3141
  import { createServer as createViteServer } from "vite";
3142
3142
  import { resolve as resolve8 } from "node:path";
3143
3143
  import { readFileSync as readFileSync6 } from "node:fs";
3144
+ import { createRequire } from "node:module";
3145
+ import { pathToFileURL } from "node:url";
3144
3146
 
3145
3147
  // src/vite/plugins/virtual-stub-plugin.ts
3146
3148
  function createVirtualStubPlugin() {
@@ -3324,8 +3326,8 @@ function createDiscoveryState(entryPath, opts) {
3324
3326
  perRouterManifestDataMap: /* @__PURE__ */ new Map(),
3325
3327
  prerenderManifestEntries: null,
3326
3328
  staticManifestEntries: null,
3327
- handlerChunkInfo: null,
3328
- staticHandlerChunkInfo: null,
3329
+ handlerChunkInfoMap: /* @__PURE__ */ new Map(),
3330
+ staticHandlerChunkInfoMap: /* @__PURE__ */ new Map(),
3329
3331
  rscEntryFileName: null,
3330
3332
  resolvedPrerenderModules: void 0,
3331
3333
  resolvedStaticModules: void 0,
@@ -3585,11 +3587,12 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
3585
3587
  for (const { manifest } of allManifests) {
3586
3588
  if (!manifest.prerenderRoutes) continue;
3587
3589
  const defs = manifest._prerenderDefs || {};
3590
+ const passthroughSet = new Set(manifest.passthroughRoutes || []);
3588
3591
  for (const routeName of manifest.prerenderRoutes) {
3589
3592
  const pattern = manifest.routeManifest[routeName];
3590
3593
  if (!pattern) continue;
3591
3594
  const def = defs[routeName];
3592
- const isPassthroughRoute = !!def?.options?.passthrough;
3595
+ const isPassthroughRoute = passthroughSet.has(routeName);
3593
3596
  const hasDynamic = pattern.includes(":") || pattern.includes("*");
3594
3597
  if (!hasDynamic) {
3595
3598
  entries.push({
@@ -3602,12 +3605,20 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
3602
3605
  if (def?.getParams) {
3603
3606
  try {
3604
3607
  const buildVars = {};
3608
+ const buildEnv = state.resolvedBuildEnv;
3605
3609
  const getParamsCtx = {
3606
3610
  build: true,
3611
+ dev: !state.isBuildMode,
3607
3612
  set: ((keyOrVar, value) => {
3608
3613
  contextSet(buildVars, keyOrVar, value);
3609
3614
  }),
3610
- reverse: getParamsReverse
3615
+ reverse: getParamsReverse,
3616
+ get env() {
3617
+ if (buildEnv !== void 0) return buildEnv;
3618
+ throw new Error(
3619
+ "[rsc-router] ctx.env is not available during build-time getParams(). Configure buildEnv in your rango() plugin options to enable build-time env access."
3620
+ );
3621
+ }
3611
3622
  };
3612
3623
  const paramsList = await def.getParams(getParamsCtx);
3613
3624
  const concurrency = def.options?.concurrency ?? 1;
@@ -3686,7 +3697,8 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
3686
3697
  entry.urlPath,
3687
3698
  {},
3688
3699
  entry.buildVars,
3689
- entry.isPassthroughRoute
3700
+ entry.isPassthroughRoute,
3701
+ state.resolvedBuildEnv
3690
3702
  );
3691
3703
  if (!result) continue;
3692
3704
  if (result.passthrough) {
@@ -3810,7 +3822,9 @@ async function renderStaticHandlers(state, rscEnv, registry) {
3810
3822
  const result = await routerInstance.renderStaticSegment(
3811
3823
  def.handler,
3812
3824
  def.$$id,
3813
- def.$$routePrefix
3825
+ def.$$routePrefix,
3826
+ state.resolvedBuildEnv,
3827
+ !state.isBuildMode
3814
3828
  );
3815
3829
  if (result) {
3816
3830
  const hasHandles = Object.keys(result.handles).length > 0;
@@ -4388,48 +4402,45 @@ function postprocessBundle(state) {
4388
4402
  );
4389
4403
  const evictionTargets = [
4390
4404
  {
4391
- info: state.handlerChunkInfo,
4405
+ infos: state.handlerChunkInfoMap.values(),
4392
4406
  fnName: "Prerender",
4393
4407
  brand: "prerenderHandler",
4394
4408
  label: "handler code from RSC bundle"
4395
4409
  },
4396
4410
  {
4397
- info: state.staticHandlerChunkInfo,
4411
+ infos: state.staticHandlerChunkInfoMap.values(),
4398
4412
  fnName: "Static",
4399
4413
  brand: "staticHandler",
4400
4414
  label: "static handler code"
4401
4415
  }
4402
4416
  ];
4403
4417
  for (const target of evictionTargets) {
4404
- if (!target.info) continue;
4405
- const chunkPath = resolve7(
4406
- state.projectRoot,
4407
- "dist/rsc",
4408
- target.info.fileName
4409
- );
4410
- try {
4411
- const code = readFileSync5(chunkPath, "utf-8");
4412
- const result = evictHandlerCode(
4413
- code,
4414
- target.info.exports,
4415
- target.fnName,
4416
- target.brand
4417
- );
4418
- if (result) {
4419
- writeFileSync4(chunkPath, result.code);
4420
- const savedKB = (result.savedBytes / 1024).toFixed(1);
4421
- console.log(
4422
- `[rsc-router] Evicted ${target.label} (${savedKB} KB saved): ${target.info.fileName}`
4418
+ for (const info of target.infos) {
4419
+ const chunkPath = resolve7(state.projectRoot, "dist/rsc", info.fileName);
4420
+ try {
4421
+ const code = readFileSync5(chunkPath, "utf-8");
4422
+ const result = evictHandlerCode(
4423
+ code,
4424
+ info.exports,
4425
+ target.fnName,
4426
+ target.brand
4427
+ );
4428
+ if (result) {
4429
+ writeFileSync4(chunkPath, result.code);
4430
+ const savedKB = (result.savedBytes / 1024).toFixed(1);
4431
+ console.log(
4432
+ `[rsc-router] Evicted ${target.label} (${savedKB} KB saved): ${info.fileName}`
4433
+ );
4434
+ }
4435
+ } catch (replaceErr) {
4436
+ console.warn(
4437
+ `[rsc-router] Failed to evict ${target.label}: ${replaceErr.message}`
4423
4438
  );
4424
4439
  }
4425
- } catch (replaceErr) {
4426
- console.warn(
4427
- `[rsc-router] Failed to evict ${target.label}: ${replaceErr.message}`
4428
- );
4429
4440
  }
4430
4441
  }
4431
- state.handlerChunkInfo = null;
4432
- state.staticHandlerChunkInfo = null;
4442
+ state.handlerChunkInfoMap.clear();
4443
+ state.staticHandlerChunkInfoMap.clear();
4433
4444
  if (hasPrerenderData && existsSync6(rscEntryPath)) {
4434
4445
  const rscCode = readFileSync5(rscEntryPath, "utf-8");
4435
4446
  if (!rscCode.includes("__prerender-manifest.js")) {
@@ -4472,7 +4483,7 @@ function postprocessBundle(state) {
4472
4483
  }
4473
4484
  if (hasStaticData && existsSync6(rscEntryPath)) {
4474
4485
  const rscCode = readFileSync5(rscEntryPath, "utf-8");
4475
- if (!rscCode.includes("__STATIC_MANIFEST")) {
4486
+ if (!rscCode.includes("__static-manifest.js")) {
4476
4487
  try {
4477
4488
  const manifestEntries = [];
4478
4489
  let totalBytes = copyStagedBuildAssets(
@@ -4541,8 +4552,67 @@ async function createTempRscServer(state, options = {}) {
4541
4552
  ]
4542
4553
  });
4543
4554
  }
4555
+ async function resolveBuildEnv(option, factoryCtx) {
4556
+ if (!option) return null;
4557
+ if (option === "auto") {
4558
+ if (factoryCtx.preset !== "cloudflare") {
4559
+ throw new Error(
4560
+ '[rsc-router] buildEnv: "auto" is only supported with preset: "cloudflare". Use a factory function or plain object for other presets.'
4561
+ );
4562
+ }
4563
+ try {
4564
+ const userRequire = createRequire(
4565
+ resolve8(factoryCtx.root, "package.json")
4566
+ );
4567
+ const wranglerPath = userRequire.resolve("wrangler");
4568
+ const { getPlatformProxy } = await import(pathToFileURL(wranglerPath).href);
4569
+ const proxy = await getPlatformProxy();
4570
+ return {
4571
+ env: proxy.env,
4572
+ dispose: proxy.dispose
4573
+ };
4574
+ } catch (err) {
4575
+ throw new Error(
4576
+ `[rsc-router] buildEnv: "auto" requires wrangler to be installed.
4577
+ Install it with: pnpm add -D wrangler
4578
+ ${err.message}`
4579
+ );
4580
+ }
4581
+ }
4582
+ if (typeof option === "function") {
4583
+ return await option(factoryCtx);
4584
+ }
4585
+ return { env: option };
4586
+ }
4587
+ async function acquireBuildEnv(s, command, mode) {
4588
+ const option = s.opts?.buildEnv;
4589
+ if (!option) return false;
4590
+ const result = await resolveBuildEnv(option, {
4591
+ root: s.projectRoot,
4592
+ mode,
4593
+ command,
4594
+ preset: s.opts?.preset ?? "node"
4595
+ });
4596
+ if (!result) return false;
4597
+ s.resolvedBuildEnv = result.env;
4598
+ s.buildEnvDispose = result.dispose ?? null;
4599
+ return true;
4600
+ }
4601
+ async function releaseBuildEnv(s) {
4602
+ if (s.buildEnvDispose) {
4603
+ try {
4604
+ await s.buildEnvDispose();
4605
+ } catch (err) {
4606
+ console.warn(`[rsc-router] buildEnv dispose failed: ${err.message}`);
4607
+ }
4608
+ s.buildEnvDispose = null;
4609
+ }
4610
+ s.resolvedBuildEnv = void 0;
4611
+ }
4544
4612
  function createRouterDiscoveryPlugin(entryPath, opts) {
4545
4613
  const s = createDiscoveryState(entryPath, opts);
4614
+ let viteCommand = "build";
4615
+ let viteMode = "production";
4546
4616
  return {
4547
4617
  name: "@rangojs/router:discovery",
4548
4618
  config() {
@@ -4551,31 +4621,13 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
4551
4621
  __RANGO_DEBUG__: JSON.stringify(!!process.env.INTERNAL_RANGO_DEBUG)
4552
4622
  }
4553
4623
  };
4554
- if (opts?.enableBuildPrerender) {
4555
- config.environments = {
4556
- rsc: {
4557
- build: {
4558
- rollupOptions: {
4559
- output: {
4560
- manualChunks(id) {
4561
- if (s.resolvedPrerenderModules?.has(id)) {
4562
- return "__prerender-handlers";
4563
- }
4564
- if (s.resolvedStaticModules?.has(id)) {
4565
- return "__static-handlers";
4566
- }
4567
- }
4568
- }
4569
- }
4570
- }
4571
- }
4572
- };
4573
- }
4574
4624
  return config;
4575
4625
  },
4576
4626
  configResolved(config) {
4577
4627
  s.projectRoot = config.root;
4578
4628
  s.isBuildMode = config.command === "build";
4629
+ viteCommand = config.command;
4630
+ viteMode = config.mode;
4579
4631
  s.userResolveAlias = config.resolve.alias;
4580
4632
  if (!s.resolvedEntryPath && opts?.routerPathRef?.path) {
4581
4633
  s.resolvedEntryPath = opts.routerPathRef.path;
@@ -4620,6 +4672,8 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
4620
4672
  });
4621
4673
  prerenderTempServer = null;
4622
4674
  }
4675
+ releaseBuildEnv(s).catch(() => {
4676
+ });
4623
4677
  });
4624
4678
  async function getOrCreateTempServer() {
4625
4679
  if (prerenderNodeRegistry) {
@@ -4650,6 +4704,7 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
4650
4704
  if (!rscEnv?.runner) {
4651
4705
  s.devServerOrigin = getDevServerOrigin();
4652
4706
  try {
4707
+ await acquireBuildEnv(s, viteCommand, viteMode);
4653
4708
  const tempRscEnv = await getOrCreateTempServer();
4654
4709
  if (tempRscEnv) {
4655
4710
  await discoverRouters(s, tempRscEnv);
@@ -4665,6 +4720,7 @@ ${err.stack}`
4665
4720
  return;
4666
4721
  }
4667
4722
  try {
4723
+ await acquireBuildEnv(s, viteCommand, viteMode);
4668
4724
  const serverMod = await rscEnv.runner.import(
4669
4725
  "@rangojs/router/server"
4670
4726
  );
@@ -4751,7 +4807,10 @@ ${err.stack}`
4751
4807
  pathname,
4752
4808
  {},
4753
4809
  void 0,
4754
- wantPassthrough
4810
+ wantPassthrough,
4811
+ s.resolvedBuildEnv,
4812
+ true
4813
+ // devMode: check getParams for passthrough routes
4755
4814
  );
4756
4815
  if (!result) continue;
4757
4816
  if (result.passthrough) continue;
@@ -4887,6 +4946,7 @@ ${err.stack}`
4887
4946
  resetStagedBuildAssets(s.projectRoot);
4888
4947
  s.prerenderManifestEntries = null;
4889
4948
  s.staticManifestEntries = null;
4949
+ await acquireBuildEnv(s, viteCommand, viteMode);
4890
4950
  let tempServer = null;
4891
4951
  globalThis.__rscRouterDiscoveryActive = true;
4892
4952
  try {
@@ -4926,6 +4986,7 @@ ${details}`
4926
4986
  if (tempServer) {
4927
4987
  await tempServer.close();
4928
4988
  }
4989
+ await releaseBuildEnv(s);
4929
4990
  }
4930
4991
  },
4931
4992
  // Virtual module: provides the pre-generated route manifest as a JS module
@@ -4968,20 +5029,30 @@ ${details}`
4968
5029
  }
4969
5030
  if (!s.resolvedPrerenderModules?.size && !s.resolvedStaticModules?.size)
4970
5031
  return;
5032
+ s.handlerChunkInfoMap.clear();
5033
+ s.staticHandlerChunkInfoMap.clear();
4971
5034
  for (const [fileName, chunk] of Object.entries(bundle)) {
4972
5035
  if (chunk.type !== "chunk") continue;
4973
- if (fileName.includes("__prerender-handlers") && s.resolvedPrerenderModules?.size) {
5036
+ if (s.resolvedPrerenderModules?.size) {
4974
5037
  const handlers = extractHandlerExportsFromChunk(
4975
5038
  chunk.code,
4976
5039
  s.resolvedPrerenderModules,
4977
5040
  "Prerender",
4978
- true
5041
+ false
4979
5042
  );
4980
5043
  if (handlers.length > 0) {
4981
- s.handlerChunkInfo = { fileName, exports: handlers };
5044
+ const existing = s.handlerChunkInfoMap.get(fileName);
5045
+ if (existing) {
5046
+ existing.exports.push(...handlers);
5047
+ } else {
5048
+ s.handlerChunkInfoMap.set(fileName, {
5049
+ fileName,
5050
+ exports: handlers
5051
+ });
5052
+ }
4982
5053
  }
4983
5054
  }
4984
- if (fileName.includes("__static-handlers") && s.resolvedStaticModules?.size) {
5055
+ if (s.resolvedStaticModules?.size) {
4985
5056
  const handlers = extractHandlerExportsFromChunk(
4986
5057
  chunk.code,
4987
5058
  s.resolvedStaticModules,
@@ -4989,7 +5060,15 @@ ${details}`
4989
5060
  false
4990
5061
  );
4991
5062
  if (handlers.length > 0) {
4992
- s.staticHandlerChunkInfo = { fileName, exports: handlers };
5063
+ const existing = s.staticHandlerChunkInfoMap.get(fileName);
5064
+ if (existing) {
5065
+ existing.exports.push(...handlers);
5066
+ } else {
5067
+ s.staticHandlerChunkInfoMap.set(fileName, {
5068
+ fileName,
5069
+ exports: handlers
5070
+ });
5071
+ }
4993
5072
  }
4994
5073
  }
4995
5074
  }
@@ -5281,7 +5360,8 @@ ${list}`);
5281
5360
  createRouterDiscoveryPlugin(discoveryEntryPath, {
5282
5361
  routerPathRef: discoveryRouterRef,
5283
5362
  enableBuildPrerender: prerenderEnabled,
5284
- staticRouteTypesGeneration: resolvedOptions.staticRouteTypesGeneration
5363
+ buildEnv: options?.buildEnv,
5364
+ preset
5285
5365
  })
5286
5366
  );
5287
5367
  return plugins;