@nestjs-ssr/react 0.1.4 → 0.1.6

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.
@@ -1,4 +1,4 @@
1
- export { E as ErrorPageDevelopment, f as ErrorPageProduction, b as RenderInterceptor, R as RenderModule, a as RenderService, S as StreamingErrorHandler, T as TemplateParserService } from '../index-C7qZ7BPg.mjs';
1
+ export { E as ErrorPageDevelopment, f as ErrorPageProduction, b as RenderInterceptor, R as RenderModule, a as RenderService, S as StreamingErrorHandler, T as TemplateParserService } from '../index-Bpzo1KfR.mjs';
2
2
  import '@nestjs/common';
3
3
  import 'react';
4
4
  import 'vite';
@@ -1,4 +1,4 @@
1
- export { E as ErrorPageDevelopment, f as ErrorPageProduction, b as RenderInterceptor, R as RenderModule, a as RenderService, S as StreamingErrorHandler, T as TemplateParserService } from '../index-C7qZ7BPg.js';
1
+ export { E as ErrorPageDevelopment, f as ErrorPageProduction, b as RenderInterceptor, R as RenderModule, a as RenderService, S as StreamingErrorHandler, T as TemplateParserService } from '../index-Bpzo1KfR.js';
2
2
  import '@nestjs/common';
3
3
  import 'react';
4
4
  import 'vite';
@@ -109,7 +109,7 @@ exports.TemplateParserService = class TemplateParserService {
109
109
  * This library handles all edge cases including escaping dangerous characters,
110
110
  * functions, dates, regexes, and prevents prototype pollution.
111
111
  */
112
- buildInlineScripts(data, context, componentPath) {
112
+ buildInlineScripts(data, context, componentName) {
113
113
  return `<script>
114
114
  window.__INITIAL_STATE__ = ${serialize__default.default(data, {
115
115
  isJSON: true
@@ -117,7 +117,7 @@ window.__INITIAL_STATE__ = ${serialize__default.default(data, {
117
117
  window.__CONTEXT__ = ${serialize__default.default(context, {
118
118
  isJSON: true
119
119
  })};
120
- window.__COMPONENT_PATH__ = ${serialize__default.default(componentPath, {
120
+ window.__COMPONENT_NAME__ = ${serialize__default.default(componentName, {
121
121
  isJSON: true
122
122
  })};
123
123
  </script>`;
@@ -428,18 +428,26 @@ exports.RenderService = class _RenderService {
428
428
  isDevelopment;
429
429
  ssrMode;
430
430
  entryServerPath;
431
+ entryClientPath;
431
432
  constructor(templateParser, streamingErrorHandler, ssrMode, defaultHead) {
432
433
  this.templateParser = templateParser;
433
434
  this.streamingErrorHandler = streamingErrorHandler;
434
435
  this.defaultHead = defaultHead;
435
436
  this.isDevelopment = process.env.NODE_ENV !== "production";
436
437
  this.ssrMode = ssrMode || process.env.SSR_MODE || "string";
437
- const absoluteTemplatePath = path.join(__dirname, "templates/entry-server.tsx");
438
- const relativeToApp = path.relative(process.cwd(), absoluteTemplatePath);
439
- if (relativeToApp.startsWith("..")) {
440
- this.entryServerPath = absoluteTemplatePath;
438
+ const absoluteServerPath = path.join(__dirname, "/templates/entry-server.tsx");
439
+ const relativeServerPath = path.relative(process.cwd(), absoluteServerPath);
440
+ if (relativeServerPath.startsWith("..")) {
441
+ this.entryServerPath = absoluteServerPath;
441
442
  } else {
442
- this.entryServerPath = "/" + relativeToApp.replace(/\\/g, "/");
443
+ this.entryServerPath = "/" + relativeServerPath.replace(/\\/g, "/");
444
+ }
445
+ const absoluteClientPath = path.join(__dirname, "/templates/entry-client.tsx");
446
+ const relativeClientPath = path.relative(process.cwd(), absoluteClientPath);
447
+ if (relativeClientPath.startsWith("..")) {
448
+ this.entryClientPath = absoluteClientPath;
449
+ } else {
450
+ this.entryClientPath = "/" + relativeClientPath.replace(/\\/g, "/");
443
451
  }
444
452
  let templatePath;
445
453
  if (this.isDevelopment) {
@@ -492,15 +500,15 @@ exports.RenderService = class _RenderService {
492
500
  /**
493
501
  * Main render method that routes to string or stream mode
494
502
  */
495
- async render(viewPath, data = {}, res, head) {
503
+ async render(viewComponent, data = {}, res, head) {
496
504
  const mergedHead = this.mergeHead(this.defaultHead, head);
497
505
  if (this.ssrMode === "stream") {
498
506
  if (!res) {
499
507
  throw new Error("Response object is required for streaming SSR mode. Pass res as third parameter.");
500
508
  }
501
- return this.renderToStream(viewPath, data, res, mergedHead);
509
+ return this.renderToStream(viewComponent, data, res, mergedHead);
502
510
  }
503
- return this.renderToString(viewPath, data, mergedHead);
511
+ return this.renderToString(viewComponent, data, mergedHead);
504
512
  }
505
513
  /**
506
514
  * Merge default head with page-specific head
@@ -527,7 +535,7 @@ exports.RenderService = class _RenderService {
527
535
  /**
528
536
  * Traditional string-based SSR using renderToString
529
537
  */
530
- async renderToString(viewPath, data = {}, head) {
538
+ async renderToString(viewComponent, data = {}, head) {
531
539
  const startTime = Date.now();
532
540
  try {
533
541
  let template = this.template;
@@ -552,7 +560,8 @@ exports.RenderService = class _RenderService {
552
560
  }
553
561
  }
554
562
  const { data: pageData, __context: context } = data;
555
- const appHtml = await renderModule.renderComponent(viewPath, data);
563
+ const appHtml = await renderModule.renderComponent(viewComponent, data);
564
+ const componentName = viewComponent.displayName || viewComponent.name || "Component";
556
565
  const initialStateScript = `
557
566
  <script>
558
567
  window.__INITIAL_STATE__ = ${serialize__default.default(pageData, {
@@ -561,7 +570,7 @@ exports.RenderService = class _RenderService {
561
570
  window.__CONTEXT__ = ${serialize__default.default(context, {
562
571
  isJSON: true
563
572
  })};
564
- window.__COMPONENT_PATH__ = ${serialize__default.default(viewPath, {
573
+ window.__COMPONENT_NAME__ = ${serialize__default.default(componentName, {
565
574
  isJSON: true
566
575
  })};
567
576
  </script>
@@ -569,7 +578,7 @@ exports.RenderService = class _RenderService {
569
578
  let clientScript = "";
570
579
  let styles = "";
571
580
  if (this.vite) {
572
- clientScript = `<script type="module" src="/src/entry-client.tsx"></script>`;
581
+ clientScript = `<script type="module" src="${this.entryClientPath}"></script>`;
573
582
  styles = "";
574
583
  } else {
575
584
  if (this.manifest) {
@@ -599,7 +608,8 @@ exports.RenderService = class _RenderService {
599
608
  html = html.replace("<!--head-meta-->", headTags);
600
609
  if (this.isDevelopment) {
601
610
  const duration = Date.now() - startTime;
602
- this.logger.log(`[SSR] ${viewPath} rendered in ${duration}ms (string mode)`);
611
+ const componentName2 = typeof viewComponent === "function" ? viewComponent.name : String(viewComponent);
612
+ this.logger.log(`[SSR] ${componentName2} rendered in ${duration}ms (string mode)`);
603
613
  }
604
614
  return html;
605
615
  } catch (error) {
@@ -609,7 +619,7 @@ exports.RenderService = class _RenderService {
609
619
  /**
610
620
  * Modern streaming SSR using renderToPipeableStream
611
621
  */
612
- async renderToStream(viewPath, data = {}, res, head) {
622
+ async renderToStream(viewComponent, data = {}, res, head) {
613
623
  const startTime = Date.now();
614
624
  let shellReadyTime = 0;
615
625
  try {
@@ -636,12 +646,13 @@ exports.RenderService = class _RenderService {
636
646
  }
637
647
  }
638
648
  const { data: pageData, __context: context } = data;
639
- const inlineScripts = this.templateParser.buildInlineScripts(pageData, context, viewPath);
649
+ const componentName = viewComponent.displayName || viewComponent.name || "Component";
650
+ const inlineScripts = this.templateParser.buildInlineScripts(pageData, context, componentName);
640
651
  const clientScript = this.templateParser.getClientScriptTag(this.isDevelopment, this.manifest);
641
652
  const stylesheetTags = this.templateParser.getStylesheetTags(this.isDevelopment, this.manifest);
642
653
  const headTags = this.templateParser.buildHeadTags(head);
643
654
  let didError = false;
644
- const { pipe, abort } = renderModule.renderComponentStream(viewPath, data, {
655
+ const { pipe, abort } = renderModule.renderComponentStream(viewComponent, data, {
645
656
  onShellReady: /* @__PURE__ */ __name(() => {
646
657
  shellReadyTime = Date.now();
647
658
  res.statusCode = didError ? 500 : 200;
@@ -654,15 +665,15 @@ exports.RenderService = class _RenderService {
654
665
  pipe(res);
655
666
  if (this.isDevelopment) {
656
667
  const ttfb = shellReadyTime - startTime;
657
- this.logger.log(`[SSR] ${viewPath} shell ready in ${ttfb}ms (stream mode - TTFB)`);
668
+ this.logger.log(`[SSR] ${componentName} shell ready in ${ttfb}ms (stream mode - TTFB)`);
658
669
  }
659
670
  }, "onShellReady"),
660
671
  onShellError: /* @__PURE__ */ __name((error) => {
661
- this.streamingErrorHandler.handleShellError(error, res, viewPath, this.isDevelopment);
672
+ this.streamingErrorHandler.handleShellError(error, res, componentName, this.isDevelopment);
662
673
  }, "onShellError"),
663
674
  onError: /* @__PURE__ */ __name((error) => {
664
675
  didError = true;
665
- this.streamingErrorHandler.handleStreamError(error, viewPath);
676
+ this.streamingErrorHandler.handleStreamError(error, componentName);
666
677
  }, "onError"),
667
678
  onAllReady: /* @__PURE__ */ __name(() => {
668
679
  res.write(inlineScripts);
@@ -673,7 +684,7 @@ exports.RenderService = class _RenderService {
673
684
  if (this.isDevelopment) {
674
685
  const totalTime = Date.now() - startTime;
675
686
  const streamTime = Date.now() - shellReadyTime;
676
- this.logger.log(`[SSR] ${viewPath} streaming complete in ${totalTime}ms total (${streamTime}ms streaming)`);
687
+ this.logger.log(`[SSR] ${componentName} streaming complete in ${totalTime}ms total (${streamTime}ms streaming)`);
677
688
  }
678
689
  }, "onAllReady")
679
690
  });
@@ -681,7 +692,8 @@ exports.RenderService = class _RenderService {
681
692
  abort();
682
693
  });
683
694
  } catch (error) {
684
- this.streamingErrorHandler.handleShellError(error, res, viewPath, this.isDevelopment);
695
+ const componentName = typeof viewComponent === "function" ? viewComponent.name : String(viewComponent);
696
+ this.streamingErrorHandler.handleShellError(error, res, componentName, this.isDevelopment);
685
697
  }
686
698
  }
687
699
  };
@@ -728,8 +740,8 @@ exports.RenderInterceptor = class RenderInterceptor {
728
740
  this.renderService = renderService;
729
741
  }
730
742
  intercept(context, next) {
731
- const viewPath = this.reflector.get(RENDER_KEY, context.getHandler());
732
- if (!viewPath) {
743
+ const viewPathOrComponent = this.reflector.get(RENDER_KEY, context.getHandler());
744
+ if (!viewPathOrComponent) {
733
745
  return next.handle();
734
746
  }
735
747
  return next.handle().pipe(operators.switchMap(async (data) => {
@@ -753,7 +765,7 @@ exports.RenderInterceptor = class RenderInterceptor {
753
765
  __context: renderContext
754
766
  };
755
767
  try {
756
- const html = await this.renderService.render(viewPath, fullData, response, renderResponse.head);
768
+ const html = await this.renderService.render(viewPathOrComponent, fullData, response, renderResponse.head);
757
769
  if (html !== void 0) {
758
770
  response.type("text/html");
759
771
  return html;
@@ -799,6 +811,7 @@ var ViteInitializerService = class _ViteInitializerService {
799
811
  logger = new common.Logger(_ViteInitializerService.name);
800
812
  viteMode;
801
813
  vitePort;
814
+ viteServer = null;
802
815
  constructor(renderService, httpAdapterHost, viteConfig) {
803
816
  this.renderService = renderService;
804
817
  this.httpAdapterHost = httpAdapterHost;
@@ -816,15 +829,15 @@ var ViteInitializerService = class _ViteInitializerService {
816
829
  async setupDevelopmentMode() {
817
830
  try {
818
831
  const { createServer: createViteServer } = await import('vite');
819
- const vite = await createViteServer({
832
+ this.viteServer = await createViteServer({
820
833
  server: {
821
834
  middlewareMode: true
822
835
  },
823
836
  appType: "custom"
824
837
  });
825
- this.renderService.setViteServer(vite);
838
+ this.renderService.setViteServer(this.viteServer);
826
839
  if (this.viteMode === "embedded") {
827
- await this.mountViteMiddleware(vite);
840
+ await this.mountViteMiddleware(this.viteServer);
828
841
  } else if (this.viteMode === "proxy") {
829
842
  await this.setupViteProxy();
830
843
  }
@@ -887,6 +900,20 @@ var ViteInitializerService = class _ViteInitializerService {
887
900
  this.logger.warn(`Failed to setup static assets: ${error.message}`);
888
901
  }
889
902
  }
903
+ /**
904
+ * Cleanup: Close Vite server on module destroy
905
+ * This prevents port conflicts on hot reload
906
+ */
907
+ async onModuleDestroy() {
908
+ if (this.viteServer) {
909
+ try {
910
+ await this.viteServer.close();
911
+ this.logger.log("\u2713 Vite server closed");
912
+ } catch (error) {
913
+ this.logger.warn(`Failed to close Vite server: ${error.message}`);
914
+ }
915
+ }
916
+ }
890
917
  };
891
918
  ViteInitializerService = _ts_decorate5([
892
919
  common.Injectable(),