@application-kit/nestjs-vite 0.2.0 → 0.4.0
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.
- package/CHANGELOG.md +29 -0
- package/README.md +95 -7
- package/dist/cjs/filters/index.d.ts +2 -0
- package/dist/cjs/filters/index.js +18 -0
- package/dist/cjs/filters/not-found.filter.d.ts +11 -0
- package/dist/cjs/filters/not-found.filter.js +48 -0
- package/dist/cjs/filters/unauthorized-redirect.filter.d.ts +7 -0
- package/dist/cjs/filters/unauthorized-redirect.filter.js +42 -0
- package/dist/cjs/index.d.ts +4 -0
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/renderer/html-template.d.ts +5 -0
- package/dist/cjs/renderer/html-template.js +18 -0
- package/dist/cjs/renderer/index.d.ts +3 -0
- package/dist/cjs/renderer/index.js +19 -0
- package/dist/cjs/renderer/render-html-page.d.ts +3 -0
- package/dist/cjs/renderer/render-html-page.js +9 -0
- package/dist/cjs/renderer/vite-application-renderer.d.ts +12 -0
- package/dist/cjs/renderer/vite-application-renderer.js +44 -0
- package/dist/cjs/ssr-entry/ssr-entry-with-vite.d.ts +4 -4
- package/dist/cjs/ssr-entry/ssr-entry.interface.d.ts +9 -7
- package/dist/cjs/vite-application-renderer.interface.d.ts +1 -1
- package/dist/cjs/vite-plugin/application-vite-config-options.interface.d.ts +16 -0
- package/dist/cjs/vite-plugin/application-vite-config-options.interface.js +2 -0
- package/dist/cjs/vite-plugin/define-application-vite-config.d.ts +3 -0
- package/dist/cjs/vite-plugin/define-application-vite-config.js +89 -0
- package/dist/cjs/vite-plugin/index.d.ts +2 -0
- package/dist/cjs/vite-plugin/index.js +2 -0
- package/dist/cjs/vite-ssr-options.interface.d.ts +10 -0
- package/dist/cjs/vite-ssr-options.interface.js +2 -0
- package/dist/cjs/vite-ssr.module.d.ts +5 -0
- package/dist/cjs/vite-ssr.module.js +55 -0
- package/dist/cjs/vite.constants.d.ts +1 -0
- package/dist/cjs/vite.constants.js +2 -1
- package/dist/esm/filters/index.d.ts +2 -0
- package/dist/esm/filters/index.js +2 -0
- package/dist/esm/filters/not-found.filter.d.ts +11 -0
- package/dist/esm/filters/not-found.filter.js +45 -0
- package/dist/esm/filters/unauthorized-redirect.filter.d.ts +7 -0
- package/dist/esm/filters/unauthorized-redirect.filter.js +39 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/renderer/html-template.d.ts +5 -0
- package/dist/esm/renderer/html-template.js +14 -0
- package/dist/esm/renderer/index.d.ts +3 -0
- package/dist/esm/renderer/index.js +3 -0
- package/dist/esm/renderer/render-html-page.d.ts +3 -0
- package/dist/esm/renderer/render-html-page.js +5 -0
- package/dist/esm/renderer/vite-application-renderer.d.ts +12 -0
- package/dist/esm/renderer/vite-application-renderer.js +41 -0
- package/dist/esm/ssr-entry/ssr-entry-with-vite.d.ts +4 -4
- package/dist/esm/ssr-entry/ssr-entry.interface.d.ts +9 -7
- package/dist/esm/vite-application-renderer.interface.d.ts +1 -1
- package/dist/esm/vite-plugin/application-vite-config-options.interface.d.ts +16 -0
- package/dist/esm/vite-plugin/application-vite-config-options.interface.js +1 -0
- package/dist/esm/vite-plugin/define-application-vite-config.d.ts +3 -0
- package/dist/esm/vite-plugin/define-application-vite-config.js +82 -0
- package/dist/esm/vite-plugin/index.d.ts +2 -0
- package/dist/esm/vite-plugin/index.js +2 -0
- package/dist/esm/vite-ssr-options.interface.d.ts +10 -0
- package/dist/esm/vite-ssr-options.interface.js +1 -0
- package/dist/esm/vite-ssr.module.d.ts +5 -0
- package/dist/esm/vite-ssr.module.js +52 -0
- package/dist/esm/vite.constants.d.ts +1 -0
- package/dist/esm/vite.constants.js +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.ViteSsrModule = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
const core_1 = require("@nestjs/core");
|
|
12
|
+
const not_found_filter_js_1 = require("./filters/not-found.filter.js");
|
|
13
|
+
const html_loader_with_vite_js_1 = require("./html-loader/html-loader-with-vite.js");
|
|
14
|
+
const html_loader_interface_js_1 = require("./html-loader/html-loader.interface.js");
|
|
15
|
+
const html_loader_js_1 = require("./html-loader/html-loader.js");
|
|
16
|
+
const vite_application_renderer_js_1 = require("./renderer/vite-application-renderer.js");
|
|
17
|
+
const ssr_entry_with_vite_js_1 = require("./ssr-entry/ssr-entry-with-vite.js");
|
|
18
|
+
const ssr_entry_interface_js_1 = require("./ssr-entry/ssr-entry.interface.js");
|
|
19
|
+
const vite_application_renderer_interface_js_1 = require("./vite-application-renderer.interface.js");
|
|
20
|
+
const vite_constants_js_1 = require("./vite.constants.js");
|
|
21
|
+
const vite_module_js_1 = require("./vite.module.js");
|
|
22
|
+
const productionProviders = (ssrEntry) => [
|
|
23
|
+
{ provide: html_loader_interface_js_1.HTML_LOADER_INTERFACE, useClass: html_loader_js_1.HtmlLoader },
|
|
24
|
+
{ provide: ssr_entry_interface_js_1.SSR_ENTRY_INTERFACE, useExisting: ssrEntry },
|
|
25
|
+
];
|
|
26
|
+
const developmentProviders = (ssrEntry) => [
|
|
27
|
+
{ provide: html_loader_interface_js_1.HTML_LOADER_INTERFACE, useClass: html_loader_with_vite_js_1.HtmlLoaderWithVite },
|
|
28
|
+
{
|
|
29
|
+
inject: [ssrEntry, vite_constants_js_1.VITE_DEV_SERVER],
|
|
30
|
+
provide: ssr_entry_interface_js_1.SSR_ENTRY_INTERFACE,
|
|
31
|
+
useFactory: (entry, server) => new ssr_entry_with_vite_js_1.SsrEntryWithVite(entry, server),
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
let ViteSsrModule = class ViteSsrModule {
|
|
35
|
+
static forRoot(options) {
|
|
36
|
+
const { isProduction, ssrEntry } = options;
|
|
37
|
+
return {
|
|
38
|
+
exports: [vite_application_renderer_interface_js_1.VITE_APPLICATION_RENDERER],
|
|
39
|
+
global: true,
|
|
40
|
+
imports: isProduction ? [] : [vite_module_js_1.ViteModule],
|
|
41
|
+
module: this,
|
|
42
|
+
providers: [
|
|
43
|
+
{ provide: vite_constants_js_1.VITE_SSR_OPTIONS, useValue: options },
|
|
44
|
+
ssrEntry,
|
|
45
|
+
...(isProduction ? productionProviders(ssrEntry) : developmentProviders(ssrEntry)),
|
|
46
|
+
{ provide: vite_application_renderer_interface_js_1.VITE_APPLICATION_RENDERER, useClass: vite_application_renderer_js_1.ViteApplicationRenderer },
|
|
47
|
+
{ provide: core_1.APP_FILTER, useClass: not_found_filter_js_1.NotFoundFilter },
|
|
48
|
+
],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
exports.ViteSsrModule = ViteSsrModule;
|
|
53
|
+
exports.ViteSsrModule = ViteSsrModule = __decorate([
|
|
54
|
+
(0, common_1.Module)({})
|
|
55
|
+
], ViteSsrModule);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VITE_DEV_SERVER = void 0;
|
|
3
|
+
exports.VITE_SSR_OPTIONS = exports.VITE_DEV_SERVER = void 0;
|
|
4
4
|
exports.VITE_DEV_SERVER = Symbol('VITE_DEV_SERVER');
|
|
5
|
+
exports.VITE_SSR_OPTIONS = Symbol('VITE_SSR_OPTIONS');
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ArgumentsHost, ExceptionFilter } from '@nestjs/common';
|
|
2
|
+
import { NotFoundException } from '@nestjs/common';
|
|
3
|
+
import { ModuleRef } from '@nestjs/core';
|
|
4
|
+
import type { ViteSsrOptionsInterface } from '../vite-ssr-options.interface.js';
|
|
5
|
+
export declare class NotFoundFilter implements ExceptionFilter<NotFoundException> {
|
|
6
|
+
private readonly moduleReference;
|
|
7
|
+
private readonly options;
|
|
8
|
+
constructor(moduleReference: ModuleRef, options: Pick<ViteSsrOptionsInterface, 'notFoundPath'>);
|
|
9
|
+
catch(_exception: NotFoundException, host: ArgumentsHost): Promise<void>;
|
|
10
|
+
private resolveRenderer;
|
|
11
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { Catch, Inject, NotFoundException } from '@nestjs/common';
|
|
14
|
+
import { ContextIdFactory, ModuleRef } from '@nestjs/core';
|
|
15
|
+
import { renderHtmlPage } from '../renderer/render-html-page.js';
|
|
16
|
+
import { VITE_APPLICATION_RENDERER } from '../vite-application-renderer.interface.js';
|
|
17
|
+
import { VITE_SSR_OPTIONS } from '../vite.constants.js';
|
|
18
|
+
let NotFoundFilter = class NotFoundFilter {
|
|
19
|
+
moduleReference;
|
|
20
|
+
options;
|
|
21
|
+
constructor(moduleReference, options) {
|
|
22
|
+
this.moduleReference = moduleReference;
|
|
23
|
+
this.options = options;
|
|
24
|
+
}
|
|
25
|
+
async catch(_exception, host) {
|
|
26
|
+
const context = host.switchToHttp();
|
|
27
|
+
const reply = context.getResponse();
|
|
28
|
+
const request = context.getRequest();
|
|
29
|
+
const renderer = await this.resolveRenderer(request);
|
|
30
|
+
request.raw.url = this.options.notFoundPath;
|
|
31
|
+
await reply.send(await renderHtmlPage(renderer, request, reply));
|
|
32
|
+
}
|
|
33
|
+
async resolveRenderer(request) {
|
|
34
|
+
const contextId = ContextIdFactory.getByRequest(request);
|
|
35
|
+
this.moduleReference.registerRequestByContextId(request, contextId);
|
|
36
|
+
return this.moduleReference.resolve(VITE_APPLICATION_RENDERER, contextId);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
NotFoundFilter = __decorate([
|
|
40
|
+
Catch(NotFoundException),
|
|
41
|
+
__param(0, Inject(ModuleRef)),
|
|
42
|
+
__param(1, Inject(VITE_SSR_OPTIONS)),
|
|
43
|
+
__metadata("design:paramtypes", [ModuleRef, Object])
|
|
44
|
+
], NotFoundFilter);
|
|
45
|
+
export { NotFoundFilter };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ArgumentsHost, ExceptionFilter } from '@nestjs/common';
|
|
2
|
+
import { UnauthorizedException } from '@nestjs/common';
|
|
3
|
+
export declare class UnauthorizedRedirectFilter implements ExceptionFilter<UnauthorizedException> {
|
|
4
|
+
private readonly signInPath;
|
|
5
|
+
constructor(signInPath: string);
|
|
6
|
+
catch(exception: UnauthorizedException, host: ArgumentsHost): Promise<void>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Catch, HttpStatus, UnauthorizedException } from '@nestjs/common';
|
|
11
|
+
let UnauthorizedRedirectFilter = class UnauthorizedRedirectFilter {
|
|
12
|
+
signInPath;
|
|
13
|
+
constructor(signInPath) {
|
|
14
|
+
this.signInPath = signInPath;
|
|
15
|
+
}
|
|
16
|
+
async catch(exception, host) {
|
|
17
|
+
if (host.getType() === 'graphql') {
|
|
18
|
+
throw exception;
|
|
19
|
+
}
|
|
20
|
+
const context = host.switchToHttp();
|
|
21
|
+
const reply = context.getResponse();
|
|
22
|
+
const request = context.getRequest();
|
|
23
|
+
const contentType = request.headers['content-type'];
|
|
24
|
+
if (typeof contentType === 'string' && contentType.includes('application/json')) {
|
|
25
|
+
await reply.status(HttpStatus.UNAUTHORIZED).send({
|
|
26
|
+
error: exception.name,
|
|
27
|
+
message: exception.message,
|
|
28
|
+
statusCode: HttpStatus.UNAUTHORIZED,
|
|
29
|
+
});
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
await reply.status(HttpStatus.FOUND).redirect(`${this.signInPath}?continue=${request.url}`);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
UnauthorizedRedirectFilter = __decorate([
|
|
36
|
+
Catch(UnauthorizedException),
|
|
37
|
+
__metadata("design:paramtypes", [String])
|
|
38
|
+
], UnauthorizedRedirectFilter);
|
|
39
|
+
export { UnauthorizedRedirectFilter };
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
export * from './filters/index.js';
|
|
1
2
|
export * from './html-loader/index.js';
|
|
3
|
+
export * from './renderer/index.js';
|
|
2
4
|
export * from './ssr-entry/index.js';
|
|
3
5
|
export * from './vite-plugin/index.js';
|
|
4
6
|
export * from './vite-application-renderer.interface.js';
|
|
7
|
+
export * from './vite-ssr-options.interface.js';
|
|
8
|
+
export * from './vite-ssr.module.js';
|
|
5
9
|
export * from './vite.constants.js';
|
|
6
10
|
export * from './vite.module.js';
|
package/dist/esm/index.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
export * from './filters/index.js';
|
|
1
2
|
export * from './html-loader/index.js';
|
|
3
|
+
export * from './renderer/index.js';
|
|
2
4
|
export * from './ssr-entry/index.js';
|
|
3
5
|
export * from './vite-plugin/index.js';
|
|
4
6
|
export * from './vite-application-renderer.interface.js';
|
|
7
|
+
export * from './vite-ssr-options.interface.js';
|
|
8
|
+
export * from './vite-ssr.module.js';
|
|
5
9
|
export * from './vite.constants.js';
|
|
6
10
|
export * from './vite.module.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SsrPageInterface } from '../ssr-entry/ssr-entry.interface.js';
|
|
2
|
+
export declare const STATE_PLACEHOLDER = "<script id=\"state\"></script>";
|
|
3
|
+
export declare const TEMPLATE_PLACEHOLDER = "<div id=\"app\"></div>";
|
|
4
|
+
export declare const LANG_ATTRIBUTE_PATTERN: RegExp;
|
|
5
|
+
export declare const fillHtmlTemplate: (html: string, page: SsrPageInterface) => string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const STATE_PLACEHOLDER = '<script id="state"></script>';
|
|
2
|
+
export const TEMPLATE_PLACEHOLDER = '<div id="app"></div>';
|
|
3
|
+
export const LANG_ATTRIBUTE_PATTERN = /<html\s+lang="[^"]*"/u;
|
|
4
|
+
const toScriptLiteral = (value) => JSON.stringify(value).replaceAll('<', String.raw `\u003C`);
|
|
5
|
+
const toAttributeValue = (value) => value.replaceAll('&', '&').replaceAll('"', '"');
|
|
6
|
+
const toStateScript = (state) => {
|
|
7
|
+
const assignments = Object.entries(state)
|
|
8
|
+
.map(([key, value]) => `window[${toScriptLiteral(key)}] = ${toScriptLiteral(value)};`);
|
|
9
|
+
return `<script>${assignments.join('')}</script>`;
|
|
10
|
+
};
|
|
11
|
+
export const fillHtmlTemplate = (html, page) => html
|
|
12
|
+
.replace(STATE_PLACEHOLDER, () => toStateScript(page.state))
|
|
13
|
+
.replace(TEMPLATE_PLACEHOLDER, () => `<div id="app">${page.template}</div>`)
|
|
14
|
+
.replace(LANG_ATTRIBUTE_PATTERN, () => `<html lang="${toAttributeValue(page.lang)}"`);
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { FastifyReply, FastifyRequest } from 'fastify';
|
|
2
|
+
import type { ViteApplicationRendererInterface } from '../vite-application-renderer.interface.js';
|
|
3
|
+
export declare const renderHtmlPage: (renderer: ViteApplicationRendererInterface, request: FastifyRequest, reply: FastifyReply) => Promise<string>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { FastifyRequest } from 'fastify';
|
|
2
|
+
import type { HtmlLoaderInterface } from '../html-loader/html-loader.interface.js';
|
|
3
|
+
import type { SsrEntryInterface } from '../ssr-entry/ssr-entry.interface.js';
|
|
4
|
+
import type { ApplicationInterface, ViteApplicationRendererInterface } from '../vite-application-renderer.interface.js';
|
|
5
|
+
import type { ViteSsrOptionsInterface } from '../vite-ssr-options.interface.js';
|
|
6
|
+
export declare class ViteApplicationRenderer implements ViteApplicationRendererInterface {
|
|
7
|
+
private readonly ssrEntry;
|
|
8
|
+
private readonly htmlLoader;
|
|
9
|
+
private readonly options;
|
|
10
|
+
constructor(ssrEntry: SsrEntryInterface, htmlLoader: HtmlLoaderInterface, options: Pick<ViteSsrOptionsInterface, 'buildInitialState' | 'htmlPath'>);
|
|
11
|
+
renderApplication(request: FastifyRequest): Promise<ApplicationInterface>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { Inject, Injectable } from '@nestjs/common';
|
|
14
|
+
import { HTML_LOADER_INTERFACE } from '../html-loader/html-loader.interface.js';
|
|
15
|
+
import { SSR_ENTRY_INTERFACE } from '../ssr-entry/ssr-entry.interface.js';
|
|
16
|
+
import { VITE_SSR_OPTIONS } from '../vite.constants.js';
|
|
17
|
+
import { fillHtmlTemplate } from './html-template.js';
|
|
18
|
+
let ViteApplicationRenderer = class ViteApplicationRenderer {
|
|
19
|
+
ssrEntry;
|
|
20
|
+
htmlLoader;
|
|
21
|
+
options;
|
|
22
|
+
constructor(ssrEntry, htmlLoader, options) {
|
|
23
|
+
this.ssrEntry = ssrEntry;
|
|
24
|
+
this.htmlLoader = htmlLoader;
|
|
25
|
+
this.options = options;
|
|
26
|
+
}
|
|
27
|
+
async renderApplication(request) {
|
|
28
|
+
const { url } = request;
|
|
29
|
+
const html = await this.htmlLoader.loadHtml(this.options.htmlPath, url);
|
|
30
|
+
const page = await this.ssrEntry.render(url, this.options.buildInitialState(request));
|
|
31
|
+
return { html: fillHtmlTemplate(html, page), statusCode: page.statusCode };
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
ViteApplicationRenderer = __decorate([
|
|
35
|
+
Injectable(),
|
|
36
|
+
__param(0, Inject(SSR_ENTRY_INTERFACE)),
|
|
37
|
+
__param(1, Inject(HTML_LOADER_INTERFACE)),
|
|
38
|
+
__param(2, Inject(VITE_SSR_OPTIONS)),
|
|
39
|
+
__metadata("design:paramtypes", [Object, Object, Object])
|
|
40
|
+
], ViteApplicationRenderer);
|
|
41
|
+
export { ViteApplicationRenderer };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ViteDevServer } from 'vite';
|
|
2
|
-
import type { SsrEntryInterface,
|
|
3
|
-
export declare class SsrEntryWithVite implements SsrEntryInterface
|
|
2
|
+
import type { SsrEntryInterface, SsrPageInterface } from './ssr-entry.interface.js';
|
|
3
|
+
export declare class SsrEntryWithVite implements SsrEntryInterface {
|
|
4
4
|
private readonly originSsrEntry;
|
|
5
5
|
private readonly viteDevelopmentServer;
|
|
6
|
-
constructor(originSsrEntry: SsrEntryInterface
|
|
7
|
-
render(url: string, initialState
|
|
6
|
+
constructor(originSsrEntry: SsrEntryInterface, viteDevelopmentServer: ViteDevServer);
|
|
7
|
+
render(url: string, initialState: Record<string, unknown>): Promise<SsrPageInterface>;
|
|
8
8
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import type { HttpStatus } from '@nestjs/common';
|
|
1
2
|
export declare const SSR_ENTRY_INTERFACE: unique symbol;
|
|
2
|
-
export interface SsrEntryInterface
|
|
3
|
-
render(url: string, initialState
|
|
3
|
+
export interface SsrEntryInterface {
|
|
4
|
+
render(url: string, initialState: Record<string, unknown>): Promise<SsrPageInterface>;
|
|
5
|
+
}
|
|
6
|
+
export interface SsrPageInterface {
|
|
7
|
+
readonly lang: string;
|
|
8
|
+
readonly state: Readonly<Record<string, string>>;
|
|
9
|
+
readonly statusCode: HttpStatus;
|
|
10
|
+
readonly template: string;
|
|
4
11
|
}
|
|
5
|
-
export type SsrEntryInterfaceRender<T> = Promise<{
|
|
6
|
-
context: T;
|
|
7
|
-
store: string;
|
|
8
|
-
template: string;
|
|
9
|
-
}>;
|
|
@@ -5,7 +5,7 @@ interface AppInterface {
|
|
|
5
5
|
statusCode: HttpStatus;
|
|
6
6
|
}
|
|
7
7
|
interface ViteAppRendererInterface {
|
|
8
|
-
renderApplication(request: FastifyRequest
|
|
8
|
+
renderApplication(request: FastifyRequest): Promise<AppInterface>;
|
|
9
9
|
}
|
|
10
10
|
export type { AppInterface as ApplicationInterface, ViteAppRendererInterface as ViteApplicationRendererInterface };
|
|
11
11
|
export declare const VITE_APPLICATION_RENDERER: unique symbol;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { BuildOptions, PluginOption } from 'vite';
|
|
2
|
+
export interface ApplicationViteConfigOptionsInterface {
|
|
3
|
+
appPath: string;
|
|
4
|
+
buildPlugins?: BuildPluginsType;
|
|
5
|
+
clientHtml: string;
|
|
6
|
+
environment: ApplicationViteEnvironmentInterface;
|
|
7
|
+
plugins: PluginOption[];
|
|
8
|
+
root: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ApplicationViteEnvironmentInterface {
|
|
11
|
+
NODE_ENV?: string;
|
|
12
|
+
PORT?: string;
|
|
13
|
+
VITE_SERVER_HMR_CLIENT_PORT?: string;
|
|
14
|
+
VITE_SERVER_HMR_PORT?: string;
|
|
15
|
+
}
|
|
16
|
+
export type BuildPluginsType = NonNullable<NonNullable<BuildOptions['rolldownOptions']>['plugins']>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import process from 'node:process';
|
|
3
|
+
import { createLogger } from 'vite';
|
|
4
|
+
import { vitePluginNode } from './vite-plugin-node.js';
|
|
5
|
+
const CLIENT_ENTRY = 'assets/main';
|
|
6
|
+
const DEV_SERVER_PORT = 3000;
|
|
7
|
+
const HMR_PORT = 3001;
|
|
8
|
+
const SOURCEMAP_WARNING = 'Sourcemap for';
|
|
9
|
+
const VENDOR_GROUP = /\/node_modules\/(?<group>[\w\-@]*)/u;
|
|
10
|
+
const vendorGroupName = (moduleId) => {
|
|
11
|
+
const match = VENDOR_GROUP.exec(moduleId);
|
|
12
|
+
return match?.groups ? match.groups.group : 'unknown';
|
|
13
|
+
};
|
|
14
|
+
const outputOf = (isServerBuild) => ({
|
|
15
|
+
assetFileNames: 'assets/[hash][extname]',
|
|
16
|
+
chunkFileNames: isServerBuild ? '[hash].mjs' : 'assets/[hash].js',
|
|
17
|
+
codeSplitting: {
|
|
18
|
+
groups: [
|
|
19
|
+
{ name: 'layout', test: /layouts/u },
|
|
20
|
+
{ maxSize: 200_000, minSize: 100_000, name: vendorGroupName, priority: 10, test: /node_modules/u },
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
comments: false,
|
|
24
|
+
dir: './dist',
|
|
25
|
+
entryFileNames: (chunk) => (chunk.name === CLIENT_ENTRY ? 'assets/[hash].js' : '[name].mjs'),
|
|
26
|
+
format: 'esm',
|
|
27
|
+
hashCharacters: 'base36',
|
|
28
|
+
minifyInternalExports: false,
|
|
29
|
+
});
|
|
30
|
+
const buildOf = (options, isServerBuild) => ({
|
|
31
|
+
chunkSizeWarningLimit: 400,
|
|
32
|
+
emptyOutDir: false,
|
|
33
|
+
manifest: true,
|
|
34
|
+
minify: false,
|
|
35
|
+
rolldownOptions: {
|
|
36
|
+
input: { [CLIENT_ENTRY]: options.clientHtml },
|
|
37
|
+
output: outputOf(isServerBuild),
|
|
38
|
+
plugins: options.buildPlugins ?? [],
|
|
39
|
+
},
|
|
40
|
+
sourcemap: false,
|
|
41
|
+
});
|
|
42
|
+
const portOf = (value, fallback) => Number(value) || fallback;
|
|
43
|
+
const serverOf = (environment) => ({
|
|
44
|
+
allowedHosts: true,
|
|
45
|
+
hmr: {
|
|
46
|
+
clientPort: portOf(environment.VITE_SERVER_HMR_CLIENT_PORT, HMR_PORT),
|
|
47
|
+
port: portOf(environment.VITE_SERVER_HMR_PORT, HMR_PORT),
|
|
48
|
+
},
|
|
49
|
+
host: '0.0.0.0',
|
|
50
|
+
middlewareMode: false,
|
|
51
|
+
port: portOf(environment.PORT, DEV_SERVER_PORT),
|
|
52
|
+
preTransformRequests: environment.NODE_ENV !== 'test',
|
|
53
|
+
strictPort: true,
|
|
54
|
+
watch: {
|
|
55
|
+
ignored: ['**/*.gql', 'reports/**/*'],
|
|
56
|
+
interval: 400,
|
|
57
|
+
usePolling: true,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
const createApplicationLogger = () => {
|
|
61
|
+
const logger = createLogger();
|
|
62
|
+
const warnOnce = logger.warnOnce.bind(logger);
|
|
63
|
+
logger.warnOnce = (message, options) => {
|
|
64
|
+
if (!message.includes(SOURCEMAP_WARNING)) {
|
|
65
|
+
warnOnce(message, options);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
return logger;
|
|
69
|
+
};
|
|
70
|
+
export const defineApplicationViteConfig = (options) => {
|
|
71
|
+
const isServerBuild = process.argv.includes('--ssr');
|
|
72
|
+
return {
|
|
73
|
+
appType: 'custom',
|
|
74
|
+
build: buildOf(options, isServerBuild),
|
|
75
|
+
customLogger: createApplicationLogger(),
|
|
76
|
+
optimizeDeps: { include: ['pino'], noDiscovery: true },
|
|
77
|
+
plugins: [...vitePluginNode({ appPath: options.appPath }), ...options.plugins],
|
|
78
|
+
resolve: { alias: { '@': path.resolve(options.root, 'src') } },
|
|
79
|
+
root: path.resolve(options.root),
|
|
80
|
+
server: serverOf(options.environment),
|
|
81
|
+
};
|
|
82
|
+
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
export * from './application-vite-config-options.interface.js';
|
|
1
2
|
export * from './create-middleware.js';
|
|
3
|
+
export * from './define-application-vite-config.js';
|
|
2
4
|
export * from './nest-handler.js';
|
|
3
5
|
export * from './plugin-config.interface.js';
|
|
4
6
|
export * from './vite-plugin-node.js';
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
export * from './application-vite-config-options.interface.js';
|
|
1
2
|
export * from './create-middleware.js';
|
|
3
|
+
export * from './define-application-vite-config.js';
|
|
2
4
|
export * from './nest-handler.js';
|
|
3
5
|
export * from './plugin-config.interface.js';
|
|
4
6
|
export * from './vite-plugin-node.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Type } from '@nestjs/common';
|
|
2
|
+
import type { FastifyRequest } from 'fastify';
|
|
3
|
+
import type { SsrEntryInterface } from './ssr-entry/ssr-entry.interface.js';
|
|
4
|
+
export interface ViteSsrOptionsInterface {
|
|
5
|
+
buildInitialState(request: FastifyRequest): Record<string, unknown>;
|
|
6
|
+
readonly htmlPath: string;
|
|
7
|
+
readonly isProduction: boolean;
|
|
8
|
+
readonly notFoundPath: string;
|
|
9
|
+
readonly ssrEntry: Type<SsrEntryInterface>;
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { Module } from '@nestjs/common';
|
|
8
|
+
import { APP_FILTER } from '@nestjs/core';
|
|
9
|
+
import { NotFoundFilter } from './filters/not-found.filter.js';
|
|
10
|
+
import { HtmlLoaderWithVite } from './html-loader/html-loader-with-vite.js';
|
|
11
|
+
import { HTML_LOADER_INTERFACE } from './html-loader/html-loader.interface.js';
|
|
12
|
+
import { HtmlLoader } from './html-loader/html-loader.js';
|
|
13
|
+
import { ViteApplicationRenderer } from './renderer/vite-application-renderer.js';
|
|
14
|
+
import { SsrEntryWithVite } from './ssr-entry/ssr-entry-with-vite.js';
|
|
15
|
+
import { SSR_ENTRY_INTERFACE } from './ssr-entry/ssr-entry.interface.js';
|
|
16
|
+
import { VITE_APPLICATION_RENDERER } from './vite-application-renderer.interface.js';
|
|
17
|
+
import { VITE_DEV_SERVER, VITE_SSR_OPTIONS } from './vite.constants.js';
|
|
18
|
+
import { ViteModule } from './vite.module.js';
|
|
19
|
+
const productionProviders = (ssrEntry) => [
|
|
20
|
+
{ provide: HTML_LOADER_INTERFACE, useClass: HtmlLoader },
|
|
21
|
+
{ provide: SSR_ENTRY_INTERFACE, useExisting: ssrEntry },
|
|
22
|
+
];
|
|
23
|
+
const developmentProviders = (ssrEntry) => [
|
|
24
|
+
{ provide: HTML_LOADER_INTERFACE, useClass: HtmlLoaderWithVite },
|
|
25
|
+
{
|
|
26
|
+
inject: [ssrEntry, VITE_DEV_SERVER],
|
|
27
|
+
provide: SSR_ENTRY_INTERFACE,
|
|
28
|
+
useFactory: (entry, server) => new SsrEntryWithVite(entry, server),
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
let ViteSsrModule = class ViteSsrModule {
|
|
32
|
+
static forRoot(options) {
|
|
33
|
+
const { isProduction, ssrEntry } = options;
|
|
34
|
+
return {
|
|
35
|
+
exports: [VITE_APPLICATION_RENDERER],
|
|
36
|
+
global: true,
|
|
37
|
+
imports: isProduction ? [] : [ViteModule],
|
|
38
|
+
module: this,
|
|
39
|
+
providers: [
|
|
40
|
+
{ provide: VITE_SSR_OPTIONS, useValue: options },
|
|
41
|
+
ssrEntry,
|
|
42
|
+
...(isProduction ? productionProviders(ssrEntry) : developmentProviders(ssrEntry)),
|
|
43
|
+
{ provide: VITE_APPLICATION_RENDERER, useClass: ViteApplicationRenderer },
|
|
44
|
+
{ provide: APP_FILTER, useClass: NotFoundFilter },
|
|
45
|
+
],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
ViteSsrModule = __decorate([
|
|
50
|
+
Module({})
|
|
51
|
+
], ViteSsrModule);
|
|
52
|
+
export { ViteSsrModule };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@application-kit/nestjs-vite",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Мост Vite ↔ NestJS для SSR: dev-обвязка, загрузка HTML и ssr-entry",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nestjs",
|
|
@@ -82,6 +82,7 @@
|
|
|
82
82
|
},
|
|
83
83
|
"peerDependencies": {
|
|
84
84
|
"@nestjs/common": "^11.0.0",
|
|
85
|
+
"@nestjs/core": "^11.0.0",
|
|
85
86
|
"@nestjs/platform-fastify": "^11.0.0",
|
|
86
87
|
"fastify": "^5.0.0",
|
|
87
88
|
"vite": "^8.0.0"
|