@noego/forge 0.0.6 → 0.0.8

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 (37) hide show
  1. package/README.md +5 -1
  2. package/dist/client.cjs +1 -1
  3. package/dist/client.cjs.map +1 -1
  4. package/dist/client.d.ts +5 -0
  5. package/dist/client.mjs +32 -32
  6. package/dist/client.mjs.map +1 -1
  7. package/dist/index.plugins.cjs +9 -0
  8. package/dist/index.plugins.cjs.map +1 -0
  9. package/dist/index.plugins.d.ts +2 -0
  10. package/dist/index.plugins.js +2 -0
  11. package/dist/index.plugins.js.map +1 -0
  12. package/dist/page.mjs +1 -1
  13. package/dist/{page.svelte-C4chAYK2.js → page.svelte-Bq1Q01H0.js} +2 -7
  14. package/dist/{page.svelte-C4chAYK2.js.map → page.svelte-Bq1Q01H0.js.map} +1 -1
  15. package/dist/page.svelte-Dvj7306U.cjs.map +1 -1
  16. package/dist/plugins/serverOnlyStub.cjs +226 -0
  17. package/dist/plugins/serverOnlyStub.cjs.map +1 -0
  18. package/dist/plugins/serverOnlyStub.js +200 -0
  19. package/dist/plugins/serverOnlyStub.js.map +1 -0
  20. package/dist/shared.mjs +1 -1
  21. package/dist/stubs/server-only.d.ts +3 -0
  22. package/dist/stubs/server-only.js +7 -0
  23. package/dist/stubs/server-only.js.map +1 -0
  24. package/dist-ssr/{path-ODk1FhWY.js → path-9twSsimy.js} +5 -2
  25. package/dist-ssr/{path-ODk1FhWY.js.map → path-9twSsimy.js.map} +1 -1
  26. package/dist-ssr/{path-CyGuWUeq.cjs → path-Dm_4PXDW.cjs} +5 -2
  27. package/dist-ssr/{path-CyGuWUeq.cjs.map → path-Dm_4PXDW.cjs.map} +1 -1
  28. package/dist-ssr/server.cjs +250 -74
  29. package/dist-ssr/server.cjs.map +1 -1
  30. package/dist-ssr/server.d.ts +6 -1
  31. package/dist-ssr/server.js +245 -69
  32. package/dist-ssr/server.js.map +1 -1
  33. package/dist-ssr/shared.cjs +2 -7
  34. package/dist-ssr/shared.cjs.map +1 -1
  35. package/dist-ssr/shared.js +2 -7
  36. package/dist-ssr/shared.js.map +1 -1
  37. package/package.json +12 -4
@@ -33,7 +33,8 @@ const fs$1 = require("fs/promises");
33
33
  const yaml = require("js-yaml");
34
34
  require("clone-deep");
35
35
  const join = require("url-join");
36
- const path$1 = require("./path-CyGuWUeq.cjs");
36
+ const path$1 = require("./path-Dm_4PXDW.cjs");
37
+ const url = require("url");
37
38
  const server = require("svelte/server");
38
39
  const pathToRegex = require("path-to-regex");
39
40
  const ApplicationRenderer = require("../src/components/RecursiveRender.svelte");
@@ -54,12 +55,15 @@ class ViteComponentLoader {
54
55
  absoluteComponentPath = componentPath;
55
56
  }
56
57
  }
58
+ console.log(`[ViteComponentLoader] Loading component from path: ${absoluteComponentPath}`);
57
59
  let vitePath = path.relative(process.cwd(), absoluteComponentPath);
58
60
  vitePath = vitePath.replace(/\\/g, "/");
59
61
  if (!vitePath.startsWith("/")) {
60
62
  vitePath = "/" + vitePath;
61
63
  }
64
+ console.log(`[ViteComponentLoader] Resolved Vite path: ${vitePath} from componentPath: ${componentPath}`);
62
65
  try {
66
+ console.log(`[ViteComponentLoader] Loading module for vitePath: ${vitePath}`);
63
67
  const module2 = await this.vite.ssrLoadModule(vitePath);
64
68
  console.log(`[ViteComponentLoader] Module loaded successfully for: ${vitePath}`);
65
69
  if (!module2 || !module2.default) {
@@ -137,6 +141,23 @@ class LiveHTMLRender {
137
141
  return file_content;
138
142
  }
139
143
  }
144
+ const HTTP_METHODS = /* @__PURE__ */ new Set([
145
+ "get",
146
+ "post",
147
+ "put",
148
+ "delete",
149
+ "patch",
150
+ "head",
151
+ "options",
152
+ "trace"
153
+ ]);
154
+ function getGlobalPathsMiddleware(openapi) {
155
+ if (!openapi || !openapi.paths) {
156
+ return [];
157
+ }
158
+ const value = openapi.paths["x-middleware"];
159
+ return Array.isArray(value) ? [...value] : [];
160
+ }
140
161
  function parseConfigfile(file_content) {
141
162
  let config = null;
142
163
  try {
@@ -146,7 +167,7 @@ function parseConfigfile(file_content) {
146
167
  }
147
168
  return config;
148
169
  }
149
- function parse_modules(openapi) {
170
+ function parse_modules(openapi, inheritedMiddleware = []) {
150
171
  const modules_config = openapi.modules || openapi.module;
151
172
  if (!modules_config) {
152
173
  return;
@@ -154,16 +175,20 @@ function parse_modules(openapi) {
154
175
  const modules = Object.entries(modules_config).map(([_, module2]) => {
155
176
  return module2;
156
177
  });
178
+ const globalMiddleware = [...inheritedMiddleware, ...getGlobalPathsMiddleware(openapi)];
157
179
  const modules_path = modules.map((module2) => {
158
180
  const basePath = module2.basePath || "";
159
181
  const baseLayouts = module2.baseLayouts || [];
182
+ const moduleMiddleware = Array.isArray(module2["x-middleware"]) ? module2["x-middleware"] : [];
183
+ const inherited = [...globalMiddleware, ...moduleMiddleware];
160
184
  const paths = module2.paths;
161
185
  if (!paths) {
162
186
  return;
163
187
  }
164
- const configurations = Object.entries(paths).map(([path2, method_config]) => {
165
- return Object.entries(method_config).map(([method, config]) => {
166
- return path$1.parsePathConfig(path2, method, config);
188
+ const configurations = Object.entries(paths).filter(([path2]) => typeof path2 === "string" && path2.startsWith("/")).map(([path2, method_config]) => {
189
+ return Object.entries(method_config).filter(([method]) => HTTP_METHODS.has(String(method).toLowerCase())).map(([method, config]) => {
190
+ const methodName = String(method);
191
+ return path$1.parsePathConfig(path2, methodName, config, inherited);
167
192
  });
168
193
  });
169
194
  const routes = configurations.reduce((flat_config, config) => {
@@ -177,19 +202,24 @@ function parse_modules(openapi) {
177
202
  });
178
203
  return modules_path.reduce(
179
204
  (flat_config, config) => {
205
+ if (!config) {
206
+ return flat_config;
207
+ }
180
208
  return flat_config.concat(config);
181
209
  },
182
210
  []
183
211
  );
184
212
  }
185
- function parse_paths(openapi) {
213
+ function parse_paths(openapi, inheritedMiddleware = []) {
186
214
  const paths = openapi.paths;
187
215
  if (!paths) {
188
216
  return;
189
217
  }
190
- const configurations = Object.entries(paths).map(([path2, method_config]) => {
191
- return Object.entries(method_config).map(([method, config]) => {
192
- return path$1.parsePathConfig(path2, method, config);
218
+ const globalMiddleware = [...inheritedMiddleware, ...getGlobalPathsMiddleware(openapi)];
219
+ const configurations = Object.entries(paths).filter(([path2]) => typeof path2 === "string" && path2.startsWith("/")).map(([path2, method_config]) => {
220
+ return Object.entries(method_config).filter(([method]) => HTTP_METHODS.has(String(method).toLowerCase())).map(([method, config]) => {
221
+ const methodName = String(method);
222
+ return path$1.parsePathConfig(path2, methodName, config, globalMiddleware);
193
223
  });
194
224
  });
195
225
  const routes = configurations.reduce((flat_config, config) => {
@@ -229,13 +259,16 @@ async function parse_openapi_config(openapi_config_path) {
229
259
  } else {
230
260
  throw new Error(`Invalid OpenAPI or stitch configuration file: ${openapi_config_path}. File must contain either 'stitch', 'paths', 'module', or 'modules' at the root level.`);
231
261
  }
262
+ const globalPathsMiddleware = getGlobalPathsMiddleware(openapi_config);
232
263
  let modules = parse_modules(openapi_config) || [];
233
264
  let paths = parse_paths(openapi_config) || [];
234
265
  let fallback_layout = openapi_config["x-fallback-layout"] || null;
235
266
  let fallback_view = openapi_config["x-fallback-view"] || null;
267
+ const fallback_middleware = Array.isArray(openapi_config["x-fallback-middleware"]) ? [...openapi_config["x-fallback-middleware"]] : [...globalPathsMiddleware];
236
268
  let fallback = {
237
269
  layout: fallback_layout ? [fallback_layout] : [],
238
- view: fallback_view
270
+ view: fallback_view,
271
+ middleware: fallback_middleware
239
272
  };
240
273
  const routes = [...modules, ...paths];
241
274
  let config = {
@@ -261,7 +294,8 @@ const defaultOptions = {
261
294
  build_dir: "dist_ssr",
262
295
  renderer: "default",
263
296
  open_api_path: path.join(process.cwd(), "openapi.yaml"),
264
- manifest_endpoint: "/manifest.json"
297
+ manifest_endpoint: "/manifest.json",
298
+ middleware_path: void 0
265
299
  };
266
300
  class ManifestBuilder {
267
301
  constructor(openapi_path, loader, options) {
@@ -401,61 +435,186 @@ class ComponentManager {
401
435
  return view.default;
402
436
  }
403
437
  }
438
+ const EXTENSION_CANDIDATES = [".js", ".mjs", ".cjs", ".ts", ".tsx"];
404
439
  class MiddlewareAdapter {
405
- constructor(manager) {
406
- this.manager = manager;
440
+ constructor(middlewarePath, fallbackPath) {
441
+ __publicField(this, "cache", /* @__PURE__ */ new Map());
442
+ this.middlewarePath = middlewarePath;
443
+ this.fallbackPath = fallbackPath;
407
444
  }
408
- async handleMiddleware(req, reply, route, request_data, callback) {
409
- let components = await this.manager.getLayoutComponents(route);
410
- let middleware_stack = await Promise.all(components.map(async (component) => {
411
- const middleware = [...component.middleware || [], ...component.middlewares || []];
412
- return middleware;
413
- }));
414
- const layout_middlewares = middleware_stack.flat() || [];
415
- console.log("middleware stack loaded", layout_middlewares);
416
- req.params = request_data.params;
417
- await new Promise((resolve) => {
418
- this.runMiddleware(layout_middlewares, req, reply, resolve);
419
- });
420
- console.log("layout middleware executed");
421
- console.log("view middleware loaded");
422
- console.log("view middleware", route.view);
423
- let view = {};
424
- if (route.view) {
425
- view = await this.manager.getViewComponent(route);
426
- }
427
- let view_middlewares = [...view.middleware || [], ...view.middlewares || []];
428
- await new Promise((resolve) => {
429
- this.runMiddleware(view_middlewares, req, reply, resolve);
430
- });
431
- callback();
445
+ static build(middlewarePath, fallbackPath) {
446
+ return new MiddlewareAdapter(middlewarePath, fallbackPath);
432
447
  }
433
- runMiddleware(middleware, req, reply, callback) {
434
- middleware = this.dedupe(middleware);
435
- let index = 0;
436
- if (middleware.length === 0) {
437
- callback();
448
+ async handleMiddleware(req, res, middlewareConfig = []) {
449
+ if (!Array.isArray(middlewareConfig) || middlewareConfig.length === 0) {
438
450
  return;
439
451
  }
440
- let next = () => {
441
- if (index >= middleware.length) {
442
- callback();
443
- return;
452
+ const resolution = await this.resolveMiddlewareFunctions(middlewareConfig);
453
+ console.log(resolution);
454
+ if (resolution.errors.length > 0) {
455
+ throw new Error(`Middleware resolution failed: ${resolution.errors.join(", ")}`);
456
+ }
457
+ for (const middleware of resolution.functions) {
458
+ await this.executeMiddleware(middleware, req, res);
459
+ if (res.headersSent) {
460
+ break;
444
461
  }
445
- const mw = middleware[index];
446
- index++;
447
- if (typeof mw === "function") {
448
- if (!reply.sent)
449
- mw(req, reply, next);
450
- } else {
451
- if (!reply.sent)
452
- next();
462
+ }
463
+ }
464
+ async resolveMiddlewareFunctions(middlewareConfig) {
465
+ const functions = [];
466
+ const errors = [];
467
+ for (const spec of middlewareConfig) {
468
+ if (!spec) {
469
+ continue;
453
470
  }
471
+ try {
472
+ let resolved = this.cache.get(spec);
473
+ if (!resolved) {
474
+ resolved = await this.resolveMiddlewareSpec(spec);
475
+ this.cache.set(spec, [...resolved]);
476
+ }
477
+ functions.push(...resolved);
478
+ } catch (error) {
479
+ errors.push(`${spec}: ${error.message}`);
480
+ }
481
+ }
482
+ return {
483
+ functions: this.dedupe(functions),
484
+ errors
454
485
  };
455
- next();
456
486
  }
457
- dedupe(middlewares) {
458
- return Array.from(new Set(middlewares));
487
+ async resolveMiddlewareSpec(spec) {
488
+ const [filePath, selector] = this.parseMiddlewareSpec(spec);
489
+ const fullPath = this.resolveMiddlewareFilePath(filePath);
490
+ const module2 = await this.importMiddlewareModule(fullPath, spec);
491
+ return this.extractMiddlewareFunctions(module2, selector, spec);
492
+ }
493
+ parseMiddlewareSpec(spec) {
494
+ const colonIndex = spec.indexOf(":");
495
+ if (colonIndex === -1) {
496
+ return [spec, void 0];
497
+ }
498
+ return [spec.substring(0, colonIndex), spec.substring(colonIndex + 1)];
499
+ }
500
+ resolveMiddlewareFilePath(filePath) {
501
+ const basePath = this.middlewarePath || this.fallbackPath || process.cwd();
502
+ const transformed = this.middlewareFileTransform(filePath);
503
+ const baseCandidate = path.resolve(process.cwd(), path.join(basePath, transformed));
504
+ const resolvedWithExt = this.findExistingFile(baseCandidate);
505
+ if (resolvedWithExt) {
506
+ return resolvedWithExt;
507
+ }
508
+ throw new Error(`Middleware file not found: ${transformed}`);
509
+ }
510
+ middlewareFileTransform(filePath) {
511
+ return filePath.split(".").join(path.sep);
512
+ }
513
+ findExistingFile(basePathWithoutExt) {
514
+ const ext = path.extname(basePathWithoutExt);
515
+ if (ext) {
516
+ return fs.existsSync(basePathWithoutExt) ? basePathWithoutExt : null;
517
+ }
518
+ const directCandidates = EXTENSION_CANDIDATES.map((extCandidate) => `${basePathWithoutExt}${extCandidate}`);
519
+ for (const candidate of directCandidates) {
520
+ if (fs.existsSync(candidate)) {
521
+ return candidate;
522
+ }
523
+ }
524
+ const indexCandidates = EXTENSION_CANDIDATES.map((extCandidate) => path.join(basePathWithoutExt, `index${extCandidate}`));
525
+ for (const candidate of indexCandidates) {
526
+ if (fs.existsSync(candidate)) {
527
+ return candidate;
528
+ }
529
+ }
530
+ return null;
531
+ }
532
+ async importMiddlewareModule(fullPath, spec) {
533
+ try {
534
+ const url$1 = url.pathToFileURL(fullPath).href;
535
+ return await import(url$1);
536
+ } catch (error) {
537
+ throw new Error(`Unable to import middleware '${spec}' from ${fullPath}`);
538
+ }
539
+ }
540
+ extractMiddlewareFunctions(module2, selector, spec) {
541
+ if (!selector) {
542
+ return this.extractDefaultFunction(module2, spec);
543
+ }
544
+ if (selector === "*") {
545
+ return this.extractAllFunctions(module2, spec);
546
+ }
547
+ return this.extractSpecificFunctions(module2, selector, spec);
548
+ }
549
+ extractDefaultFunction(module2, spec) {
550
+ if (!(module2 == null ? void 0 : module2.default)) {
551
+ throw new Error(`Middleware '${spec}' is missing a default export`);
552
+ }
553
+ if (typeof module2.default !== "function") {
554
+ throw new Error(`Default export for middleware '${spec}' is not a function`);
555
+ }
556
+ return [module2.default];
557
+ }
558
+ extractAllFunctions(module2, spec) {
559
+ const functions = Object.values(module2).filter((value) => typeof value === "function");
560
+ if (functions.length === 0) {
561
+ throw new Error(`No functions exported by middleware '${spec}'`);
562
+ }
563
+ return functions;
564
+ }
565
+ extractSpecificFunctions(module2, selector, spec) {
566
+ const names = selector.split(",").map((name) => name.trim()).filter(Boolean);
567
+ const functions = [];
568
+ const missing = [];
569
+ const invalid = [];
570
+ for (const name of names) {
571
+ const value = name === "default" ? module2 == null ? void 0 : module2.default : module2 == null ? void 0 : module2[name];
572
+ if (value === void 0) {
573
+ missing.push(name);
574
+ continue;
575
+ }
576
+ if (typeof value !== "function") {
577
+ invalid.push(name);
578
+ continue;
579
+ }
580
+ functions.push(value);
581
+ }
582
+ if (missing.length) {
583
+ throw new Error(`Middleware '${spec}' is missing export(s): ${missing.join(", ")}`);
584
+ }
585
+ if (invalid.length) {
586
+ throw new Error(`Middleware '${spec}' export(s) not functions: ${invalid.join(", ")}`);
587
+ }
588
+ if (functions.length === 0) {
589
+ throw new Error(`Middleware '${spec}' did not resolve any functions for selector '${selector}'`);
590
+ }
591
+ return functions;
592
+ }
593
+ executeMiddleware(fn, req, res) {
594
+ return new Promise((resolve, reject) => {
595
+ try {
596
+ fn(req, res, (error) => {
597
+ if (error) {
598
+ reject(error);
599
+ return;
600
+ }
601
+ resolve();
602
+ });
603
+ } catch (error) {
604
+ reject(error);
605
+ }
606
+ });
607
+ }
608
+ dedupe(functions) {
609
+ const seen = /* @__PURE__ */ new Set();
610
+ const ordered = [];
611
+ for (const fn of functions) {
612
+ if (!seen.has(fn)) {
613
+ seen.add(fn);
614
+ ordered.push(fn);
615
+ }
616
+ }
617
+ return ordered;
459
618
  }
460
619
  }
461
620
  function makeUrlParser(pattern) {
@@ -475,13 +634,14 @@ function initialize_route_matchers(routes) {
475
634
  class ServerAdapter {
476
635
  }
477
636
  class ExpressServerAdapter extends ServerAdapter {
478
- constructor(server2, manager, htmlRender, api_adapter, middleware_adapter) {
637
+ constructor(server2, manager, htmlRender, api_adapter, middleware_adapter, context_builder) {
479
638
  super();
480
639
  this.server = server2;
481
640
  this.manager = manager;
482
641
  this.htmlRender = htmlRender;
483
642
  this.api_adapter = api_adapter;
484
643
  this.middleware_adapter = middleware_adapter;
644
+ this.context_builder = context_builder;
485
645
  }
486
646
  async handleRoutes(routes, manifest) {
487
647
  const matchers = initialize_route_matchers(routes);
@@ -517,13 +677,18 @@ class ExpressServerAdapter extends ServerAdapter {
517
677
  return;
518
678
  });
519
679
  }
520
- async handleResponse(url, matcher, route, routes, manifest, req, res) {
680
+ async handleResponse(url2, matcher, route, routes, manifest, req, res) {
521
681
  var _a, _b;
522
682
  let accepts = req.headers.accept || "";
523
683
  let server_api_call = accepts.toLowerCase().includes("application/json");
684
+ console.log(JSON.stringify(route, null, 2));
524
685
  const context = {};
686
+ if (this.context_builder) {
687
+ const built_context = await this.context_builder(req, res);
688
+ Object.assign(context, built_context);
689
+ }
525
690
  req["context"] = context;
526
- const cleanPath = url.split("?")[0];
691
+ const cleanPath = url2.split("?")[0];
527
692
  const pathParams = matcher.parser(cleanPath);
528
693
  const queryParams = {};
529
694
  for (const [key, value] of Object.entries(req.query)) {
@@ -537,7 +702,7 @@ class ExpressServerAdapter extends ServerAdapter {
537
702
  }
538
703
  const combinedParams = { ...pathParams, ...queryParams };
539
704
  let request_data = {
540
- url,
705
+ url: url2,
541
706
  query: req.query,
542
707
  params: combinedParams,
543
708
  headers: req.headers,
@@ -545,9 +710,7 @@ class ExpressServerAdapter extends ServerAdapter {
545
710
  context
546
711
  };
547
712
  try {
548
- await new Promise((resolve, reject) => {
549
- this.middleware_adapter.handleMiddleware(req, res, route, request_data, resolve).catch(reject);
550
- });
713
+ await this.middleware_adapter.handleMiddleware(req, res, route.middleware || []);
551
714
  } catch (e) {
552
715
  console.log("Error in middleware", e);
553
716
  res.status(500).send(`
@@ -637,10 +800,10 @@ view: ${route.view}</pre>`;
637
800
  let route = server_config.fallback;
638
801
  let accepts = req.headers.accept || "";
639
802
  let server_api_call = accepts.toLowerCase().includes("application/json");
640
- const url = req.url || "/";
803
+ const url2 = req.url || "/";
641
804
  const context = {};
642
805
  let fallback_data = {
643
- url,
806
+ url: url2,
644
807
  query: req.query,
645
808
  params: {},
646
809
  headers: req.headers,
@@ -648,9 +811,16 @@ view: ${route.view}</pre>`;
648
811
  context
649
812
  };
650
813
  let request_data = fallback_data;
651
- await new Promise((resolve) => {
652
- this.middleware_adapter.handleMiddleware(req, res, route, request_data, resolve);
653
- });
814
+ try {
815
+ await this.middleware_adapter.handleMiddleware(req, res, route.middleware || []);
816
+ } catch (e) {
817
+ console.log("Error in fallback middleware", e);
818
+ res.status(500).send(`
819
+ <h1>500 Internal Server Error</h1>
820
+ <pre>${e}</pre>
821
+ `);
822
+ return;
823
+ }
654
824
  console.log("Completed fallback middleware");
655
825
  let server_data = await this.api_adapter.getApiData(route, request_data);
656
826
  console.log("Completed fallback API call");
@@ -685,11 +855,11 @@ async function createServer(app, options) {
685
855
  full_options.open_api_path = ensureFullPath(full_options.viteOptions.root, full_options.open_api_path);
686
856
  const isProd = full_options.development === false;
687
857
  console.log(`Running in ${isProd ? "production" : "development"} mode`);
688
- const COMPONENT_DIR = path.join(full_options.viteOptions.root, full_options.component_dir);
858
+ const COMPONENT_DIR = !full_options.component_dir ? full_options.viteOptions.root : path.join(full_options.viteOptions.root, full_options.component_dir);
689
859
  const root = full_options.viteOptions.root;
690
860
  let componentLoader;
691
861
  let vite;
692
- console.log(`Serving components from ${COMPONENT_DIR} at /components/`);
862
+ console.log(`Serving components from ${COMPONENT_DIR}`);
693
863
  if (full_options.assets) {
694
864
  for (const [asset_path, asset_dir] of Object.entries(full_options.assets)) {
695
865
  for (const asset of asset_dir) {
@@ -705,8 +875,9 @@ async function createServer(app, options) {
705
875
  console.log("Starting Vite in development mode...");
706
876
  const { createServer: createViteServer } = await import("vite");
707
877
  vite = await createViteServer(options.viteOptions || full_options.viteOptions);
878
+ console.log(`Vite server created options
879
+ ${JSON.stringify(options, null, 2)}`);
708
880
  componentLoader = new ViteComponentLoader(COMPONENT_DIR, vite);
709
- console.log("loaded");
710
881
  } else {
711
882
  console.log("Starting Vite in production mode...");
712
883
  app.use("/", express.static(path.join(options.viteOptions.root, full_options.build_dir)));
@@ -723,13 +894,18 @@ async function createServer(app, options) {
723
894
  const routeDefs = server_config.routes;
724
895
  const manager = new ComponentManager(componentLoader);
725
896
  const api_adapter = new ApiAdapter(manager);
726
- const middleware_adapter = new MiddlewareAdapter(manager);
897
+ let middlewareRoot;
898
+ if (full_options.middleware_path) {
899
+ middlewareRoot = path.isAbsolute(full_options.middleware_path) ? full_options.middleware_path : path.resolve(full_options.viteOptions.root, full_options.middleware_path);
900
+ }
901
+ const middleware_adapter = MiddlewareAdapter.build(middlewareRoot, COMPONENT_DIR);
727
902
  const adapter = new ExpressServerAdapter(
728
903
  app,
729
904
  manager,
730
905
  htmlRenderer,
731
906
  api_adapter,
732
- middleware_adapter
907
+ middleware_adapter,
908
+ full_options.context_builder
733
909
  );
734
910
  await adapter.handleRoutes(routeDefs, manifest);
735
911
  console.log("Routes registered");