.`, where the hash is the SHA of the commit being reverted.
196 |
197 | ### Type
198 | Must be one of the following:
199 |
200 | * **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
201 | * **chore**: Updating tasks etc; no production code change
202 | * **ci**: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
203 | * **docs**: Documentation only changes
204 | * **feat**: A new feature
205 | * **fix**: A bug fix
206 | * **perf**: A code change that improves performance
207 | * **refactor**: A code change that neither fixes a bug nor adds a feature
208 | * **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
209 | * **test**: Adding missing tests or correcting existing tests
210 |
211 | ### Subject
212 | The subject contains succinct description of the change:
213 |
214 | * use the imperative, present tense: "change" not "changed" nor "changes"
215 | * don't capitalize first letter
216 | * no dot (.) at the end
217 |
218 | ### Body
219 | Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
220 | The body should include the motivation for the change and contrast this with previous behavior.
221 |
222 | ### Footer
223 | The footer should contain any information about **Breaking Changes** and is also the place to
224 | reference GitHub issues that this commit **Closes**.
225 |
226 | **Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
227 |
228 | A detailed explanation can be found in this [document][commit-message-format].
229 |
230 |
238 |
239 |
240 |
241 |
242 | [commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
243 | [corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
244 | [dev-doc]: https://github.com/nestjs/nest/blob/master/docs/DEVELOPER.md
245 | [github]: https://github.com/nestjs/nest
246 | [discord]: https://discord.gg/nestjs
247 | [individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
248 | [js-style-guide]: https://google.github.io/styleguide/jsguide.html
249 | [jsfiddle]: http://jsfiddle.net
250 | [plunker]: http://plnkr.co/edit
251 | [runnable]: http://runnable.com
252 |
253 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | (The MIT License)
2 |
3 | Copyright (c)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | 'Software'), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Node server
2 |
3 | [travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master
4 | [travis-url]: https://travis-ci.org/nestjs/nest
5 | [linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux
6 | [linux-url]: https://travis-ci.org/nestjs/nest
7 |
8 | A progressive Node.js framework for building efficient and scalable server-side applications.
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | ## Description
20 |
21 | `@nestjs/serve-static` package for [Nest](https://github.com/nestjs/nest), useful to serve static content like Single Page Applications (SPA). However, if you are building MVC application or want to serve assets files (images, docs), use the `useStaticAssets()` method (read more [here](https://docs.nestjs.com/techniques/mvc)) instead.
22 |
23 | ## Installation
24 |
25 | ```bash
26 | $ npm i --save @nestjs/serve-static
27 | ```
28 |
29 | ## Example
30 |
31 | See full example [here](https://github.com/nestjs/nest/tree/master/sample/24-serve-static).
32 |
33 | ## Usage
34 |
35 | Simply import `ServeStaticModule` in your Nest application.
36 |
37 | ```typescript
38 | import { Module } from '@nestjs/common';
39 | import { join } from 'path';
40 | import { ServeStaticModule } from '@nestjs/serve-static';
41 |
42 | @Module({
43 | imports: [
44 | ServeStaticModule.forRoot({
45 | rootPath: join(__dirname, '..', 'client')
46 | })
47 | ]
48 | })
49 | export class ApplicationModule {}
50 | ```
51 |
52 | ## API Spec
53 |
54 | The `forRoot()` method takes an options object with a few useful properties.
55 |
56 | | Property | Type | Description |
57 | | -------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
58 | | `rootPath` | string | Static files root directory. Default: `"client"` |
59 | | `serveRoot` | string | Root path under which static app will be served. Default: `""` |
60 | | `renderPath` | string / RegExp | Path to render static app (concatenated with the `serveRoot` value). Default: \* (wildcard - all paths). Note: `RegExp` is not supported by the `@nestjs/platform-fastify`. |
61 | | `exclude` | string[] | Paths to exclude when serving the static app. WARNING! Not supported by `fastify`. If you use `fastify`, you can exclude routes using regexp (set the `renderPath` to a regular expression) instead. |
62 | | `serveStaticOptions` | Object | Serve static options (static files) |
63 |
64 | ## Support
65 |
66 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
67 |
68 | ## Stay in touch
69 |
70 | - Author - [Kamil Myśliwiec](https://twitter.com/kammysliwiec)
71 | - Website - [https://nestjs.com](https://nestjs.com/)
72 | - Twitter - [@nestframework](https://twitter.com/nestframework)
73 |
74 | ## License
75 |
76 | Nest is [MIT licensed](LICENSE).
77 |
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './dist';
2 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | function __export(m) {
3 | for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
4 | }
5 | exports.__esModule = true;
6 | __export(require("./dist"));
7 |
--------------------------------------------------------------------------------
/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dist/serve-static.constants';
2 | export * from './dist/serve-static.module';
3 | export * from './dist/serve-static.providers';
4 |
--------------------------------------------------------------------------------
/lib/index.ts:
--------------------------------------------------------------------------------
1 | export * from './interfaces/serve-static-options.interface';
2 | export * from './loaders/abstract.loader';
3 | export * from './loaders/express.loader';
4 | export * from './loaders/fastify.loader';
5 | export * from './loaders/noop.loader';
6 | export * from './serve-static.constants';
7 | export * from './serve-static.module';
8 | export * from './serve-static.providers';
9 |
--------------------------------------------------------------------------------
/lib/interfaces/serve-static-options.interface.ts:
--------------------------------------------------------------------------------
1 | import { Provider, Type } from '@nestjs/common';
2 | import { ModuleMetadata } from '@nestjs/common/interfaces';
3 |
4 | export interface ServeStaticModuleOptions {
5 | /**
6 | * Static files root directory. Default: "client"
7 | */
8 | rootPath?: string;
9 | /**
10 | * Path to render static app (concatenated with the `serveRoot` value). Default: * (wildcard - all paths). Note: `RegExp` is not supported by the `@nestjs/platform-fastify`.
11 | */
12 | renderPath?: string | RegExp;
13 | /**
14 | * Root path under which static app will be served. Default: ""
15 | */
16 | serveRoot?: string;
17 | /**
18 | * Paths to exclude when serving the static app. WARNING! Not supported by `fastify`. If you use `fastify`, you can exclude routes using regexp (set the `renderPath` to a regular expression) instead.
19 | */
20 | exclude?: string[];
21 | /**
22 | * Serve static options (static files)
23 | * Passed down to the underlying either `express.static` or `fastify-static.send`
24 | */
25 | serveStaticOptions?: {
26 | /**
27 | * Enable or disable setting Cache-Control response header, defaults to true.
28 | * Disabling this will ignore the immutable and maxAge options.
29 | */
30 | cacheControl?: boolean;
31 |
32 | /**
33 | * Set how "dotfiles" are treated when encountered. A dotfile is a file or directory that begins with a dot (".").
34 | * Note this check is done on the path itself without checking if the path actually exists on the disk.
35 | * If root is specified, only the dotfiles above the root are checked
36 | * (i.e. the root itself can be within a dotfile when when set to "deny").
37 | * The default value is 'ignore'.
38 | * 'allow' No special treatment for dotfiles
39 | * 'deny' Send a 403 for any request for a dotfile
40 | * 'ignore' Pretend like the dotfile does not exist and call next()
41 | */
42 | dotfiles?: string;
43 |
44 | /**
45 | * Enable or disable etag generation, defaults to true.
46 | */
47 | etag?: boolean;
48 |
49 | /**
50 | * Enable or disable client setting errors fall-through as unhandled requests, defaults to true, otherwise forward a client error.
51 | */
52 | fallthrough?: boolean;
53 |
54 | /**
55 | * Set file extension fallbacks. When set, if a file is not found, the given extensions
56 | * will be added to the file name and search for.
57 | * The first that exists will be served. Example: ['html', 'htm'].
58 | * The default value is false.
59 | */
60 | extensions?: string[];
61 |
62 | /**
63 | * Enable or disable the immutable directive in the Cache-Control response header.
64 | * If enabled, the maxAge option should also be specified to enable caching.
65 | * The immutable directive will prevent supported clients from making conditional
66 | * requests during the life of the maxAge option to check if the file has changed.
67 | */
68 | immutable?: boolean;
69 |
70 | /**
71 | * By default this module will send "index.html" files in response to a request on a directory.
72 | * To disable this set false or to supply a new index pass a string or an array in preferred order.
73 | */
74 | index?: boolean | string | string[];
75 |
76 | /**
77 | * Enable or disable Last-Modified header, defaults to true. Uses the file system's last modified value.
78 | */
79 | lastModified?: boolean;
80 |
81 | /**
82 | * Provide a max-age in milliseconds for http caching, defaults to 0.
83 | * This can also be a string accepted by the ms module.
84 | */
85 | maxAge?: number | string;
86 |
87 | /**
88 | * Redirect to trailing "/" when the pathname is a dir. Defaults to true.
89 | */
90 | redirect?: boolean;
91 |
92 | /**
93 | * Function to set custom headers on response. Alterations to the headers need to occur synchronously.
94 | * The function is called as fn(res, path, stat), where the arguments are:
95 | * res the response object
96 | * path the file path that is being sent
97 | * stat the stat object of the file that is being sent
98 | */
99 | setHeaders?: (res: any, path: string, stat: any) => any;
100 | };
101 | }
102 |
103 | export interface ServeStaticModuleOptionsFactory {
104 | createLoggerOptions():
105 | | Promise
106 | | ServeStaticModuleOptions[];
107 | }
108 |
109 | export interface ServeStaticModuleAsyncOptions
110 | extends Pick {
111 | isGlobal?: boolean;
112 | useExisting?: Type;
113 | useClass?: Type;
114 | useFactory?: (
115 | ...args: any[]
116 | ) => Promise | ServeStaticModuleOptions[];
117 | inject?: any[];
118 | extraProviders?: Provider[];
119 | }
120 |
--------------------------------------------------------------------------------
/lib/loaders/abstract.loader.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { AbstractHttpAdapter } from '@nestjs/core';
3 | import { join } from 'path';
4 | import { ServeStaticModuleOptions } from '../interfaces/serve-static-options.interface';
5 |
6 | @Injectable()
7 | export abstract class AbstractLoader {
8 | public abstract register(
9 | httpAdapter: AbstractHttpAdapter,
10 | options: ServeStaticModuleOptions[]
11 | );
12 |
13 | public getIndexFilePath(clientPath: string): string {
14 | return join(clientPath, 'index.html');
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/lib/loaders/express.loader.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { loadPackage } from '@nestjs/common/utils/load-package.util';
3 | import * as fs from 'fs';
4 | import { AbstractHttpAdapter } from '@nestjs/core';
5 | import { ServeStaticModuleOptions } from '../interfaces/serve-static-options.interface';
6 | import {
7 | DEFAULT_RENDER_PATH,
8 | DEFAULT_ROOT_PATH
9 | } from '../serve-static.constants';
10 | import { isRouteExcluded } from '../utils/is-route-excluded.util';
11 | import { validatePath } from '../utils/validate-path.util';
12 | import { AbstractLoader } from './abstract.loader';
13 |
14 | @Injectable()
15 | export class ExpressLoader extends AbstractLoader {
16 | public register(
17 | httpAdapter: AbstractHttpAdapter,
18 | optionsArr: ServeStaticModuleOptions[]
19 | ) {
20 | const app = httpAdapter.getInstance();
21 | const express = loadPackage('express', 'ServeStaticModule', () =>
22 | require('express')
23 | );
24 | optionsArr.forEach(options => {
25 | options.renderPath = options.renderPath || DEFAULT_RENDER_PATH;
26 | const clientPath = options.rootPath || DEFAULT_ROOT_PATH;
27 | const indexFilePath = this.getIndexFilePath(clientPath);
28 |
29 | const renderFn = (req: unknown, res: any, next: Function) => {
30 | if (!isRouteExcluded(req, options.exclude)) {
31 | if (
32 | options.serveStaticOptions &&
33 | options.serveStaticOptions.setHeaders
34 | ) {
35 | const stat = fs.statSync(indexFilePath);
36 | options.serveStaticOptions.setHeaders(res, indexFilePath, stat);
37 | }
38 | res.sendFile(indexFilePath);
39 | } else {
40 | next();
41 | }
42 | };
43 |
44 | if (options.serveRoot) {
45 | app.use(
46 | options.serveRoot,
47 | express.static(clientPath, options.serveStaticOptions)
48 | );
49 | const renderPath =
50 | typeof options.serveRoot === 'string'
51 | ? options.serveRoot + validatePath(options.renderPath as string)
52 | : options.serveRoot;
53 |
54 | app.get(renderPath, renderFn);
55 | } else {
56 | app.use(express.static(clientPath, options.serveStaticOptions));
57 | app.get(options.renderPath, renderFn);
58 | }
59 | });
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/lib/loaders/fastify.loader.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { loadPackage } from '@nestjs/common/utils/load-package.util';
3 | import { AbstractHttpAdapter } from '@nestjs/core';
4 | import * as fs from 'fs';
5 | import { ServeStaticModuleOptions } from '../interfaces/serve-static-options.interface';
6 | import {
7 | DEFAULT_RENDER_PATH,
8 | DEFAULT_ROOT_PATH
9 | } from '../serve-static.constants';
10 | import { validatePath } from '../utils/validate-path.util';
11 | import { AbstractLoader } from './abstract.loader';
12 |
13 | @Injectable()
14 | export class FastifyLoader extends AbstractLoader {
15 | public register(
16 | httpAdapter: AbstractHttpAdapter,
17 | optionsArr: ServeStaticModuleOptions[]
18 | ) {
19 | const app = httpAdapter.getInstance();
20 | const fastifyStatic = loadPackage(
21 | '@fastify/static',
22 | 'ServeStaticModule',
23 | () => require('@fastify/static')
24 | );
25 |
26 | optionsArr.forEach((options) => {
27 | options.renderPath = options.renderPath || DEFAULT_RENDER_PATH;
28 |
29 | const clientPath = options.rootPath || DEFAULT_ROOT_PATH;
30 | const indexFilePath = this.getIndexFilePath(clientPath);
31 |
32 | if (options.serveRoot) {
33 | app.register(fastifyStatic, {
34 | root: clientPath,
35 | ...(options.serveStaticOptions || {}),
36 | wildcard: false,
37 | prefix: options.serveRoot
38 | });
39 |
40 | const renderPath =
41 | typeof options.serveRoot === 'string'
42 | ? options.serveRoot + validatePath(options.renderPath as string)
43 | : options.serveRoot;
44 |
45 | app.get(renderPath, (req: any, res: any) => {
46 | const stream = fs.createReadStream(indexFilePath);
47 | res.type('text/html').send(stream);
48 | });
49 | } else {
50 | app.register(fastifyStatic, {
51 | root: clientPath,
52 | ...(options.serveStaticOptions || {}),
53 | wildcard: false
54 | });
55 | app.get(options.renderPath, (req: any, res: any) => {
56 | const stream = fs.createReadStream(indexFilePath);
57 | if (
58 | options.serveStaticOptions &&
59 | options.serveStaticOptions.setHeaders
60 | ) {
61 | const stat = fs.statSync(indexFilePath);
62 | options.serveStaticOptions.setHeaders(res, indexFilePath, stat);
63 | }
64 | res.type('text/html').send(stream);
65 | });
66 | }
67 | });
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/lib/loaders/noop.loader.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-unused-vars */
2 | /* eslint-disable @typescript-eslint/no-empty-function */
3 | import { Injectable } from '@nestjs/common';
4 | import { AbstractHttpAdapter } from '@nestjs/core';
5 | import { ServeStaticModuleOptions } from '../interfaces/serve-static-options.interface';
6 | import { AbstractLoader } from './abstract.loader';
7 |
8 | @Injectable()
9 | export class NoopLoader extends AbstractLoader {
10 | public register(
11 | httpAdapter: AbstractHttpAdapter,
12 | options: ServeStaticModuleOptions[]
13 | ) {}
14 | }
15 |
--------------------------------------------------------------------------------
/lib/serve-static.constants.ts:
--------------------------------------------------------------------------------
1 | export const SERVE_STATIC_MODULE_OPTIONS = 'SERVE_STATIC_MODULE_OPTIONS';
2 |
3 | export const DEFAULT_ROOT_PATH = 'client';
4 | export const DEFAULT_RENDER_PATH = '*';
5 |
--------------------------------------------------------------------------------
/lib/serve-static.module.ts:
--------------------------------------------------------------------------------
1 | import {
2 | DynamicModule,
3 | Inject,
4 | Module,
5 | OnModuleInit,
6 | Provider
7 | } from '@nestjs/common';
8 | import { HttpAdapterHost } from '@nestjs/core';
9 | import {
10 | ServeStaticModuleAsyncOptions,
11 | ServeStaticModuleOptions,
12 | ServeStaticModuleOptionsFactory
13 | } from './interfaces/serve-static-options.interface';
14 | import { AbstractLoader } from './loaders/abstract.loader';
15 | import { SERVE_STATIC_MODULE_OPTIONS } from './serve-static.constants';
16 | import { serveStaticProviders } from './serve-static.providers';
17 |
18 | @Module({
19 | providers: [...serveStaticProviders]
20 | })
21 | export class ServeStaticModule implements OnModuleInit {
22 | constructor(
23 | @Inject(SERVE_STATIC_MODULE_OPTIONS)
24 | private readonly ngOptions: ServeStaticModuleOptions[],
25 | private readonly loader: AbstractLoader,
26 | private readonly httpAdapterHost: HttpAdapterHost
27 | ) {}
28 |
29 | public static forRoot(...options: ServeStaticModuleOptions[]): DynamicModule {
30 | return {
31 | module: ServeStaticModule,
32 | providers: [
33 | {
34 | provide: SERVE_STATIC_MODULE_OPTIONS,
35 | useValue: options
36 | }
37 | ]
38 | };
39 | }
40 |
41 | public static forRootAsync(
42 | options: ServeStaticModuleAsyncOptions
43 | ): DynamicModule {
44 | return {
45 | module: ServeStaticModule,
46 | imports: options.imports,
47 | providers: [
48 | ...this.createAsyncProviders(options),
49 | ...(options.extraProviders || [])
50 | ],
51 | exports: [SERVE_STATIC_MODULE_OPTIONS]
52 | };
53 | }
54 |
55 | private static createAsyncProviders(
56 | options: ServeStaticModuleAsyncOptions
57 | ): Provider[] {
58 | if (options.useExisting || options.useFactory) {
59 | return [this.createAsyncOptionsProvider(options)];
60 | }
61 | return [
62 | this.createAsyncOptionsProvider(options),
63 | {
64 | provide: options.useClass,
65 | useClass: options.useClass
66 | }
67 | ];
68 | }
69 |
70 | private static createAsyncOptionsProvider(
71 | options: ServeStaticModuleAsyncOptions
72 | ): Provider {
73 | if (options.useFactory) {
74 | return {
75 | provide: SERVE_STATIC_MODULE_OPTIONS,
76 | useFactory: options.useFactory,
77 | inject: options.inject || []
78 | };
79 | }
80 | return {
81 | provide: SERVE_STATIC_MODULE_OPTIONS,
82 | useFactory: async (optionsFactory: ServeStaticModuleOptionsFactory) =>
83 | optionsFactory.createLoggerOptions(),
84 | inject: [options.useExisting || options.useClass]
85 | };
86 | }
87 |
88 | public async onModuleInit() {
89 | const httpAdapter = this.httpAdapterHost.httpAdapter;
90 | this.loader.register(httpAdapter, this.ngOptions);
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/lib/serve-static.providers.ts:
--------------------------------------------------------------------------------
1 | import { Provider } from '@nestjs/common';
2 | import { HttpAdapterHost } from '@nestjs/core';
3 | import { AbstractLoader } from './loaders/abstract.loader';
4 | import { ExpressLoader } from './loaders/express.loader';
5 | import { FastifyLoader } from './loaders/fastify.loader';
6 | import { NoopLoader } from './loaders/noop.loader';
7 |
8 | export const serveStaticProviders: Provider[] = [
9 | {
10 | provide: AbstractLoader,
11 | useFactory: (httpAdapterHost: HttpAdapterHost) => {
12 | if (!httpAdapterHost || !httpAdapterHost.httpAdapter) {
13 | return new NoopLoader();
14 | }
15 | const httpAdapter = httpAdapterHost.httpAdapter;
16 | if (
17 | httpAdapter &&
18 | httpAdapter.constructor &&
19 | httpAdapter.constructor.name === 'FastifyAdapter'
20 | ) {
21 | return new FastifyLoader();
22 | }
23 | return new ExpressLoader();
24 | },
25 | inject: [HttpAdapterHost]
26 | }
27 | ];
28 |
--------------------------------------------------------------------------------
/lib/utils/is-route-excluded.util.ts:
--------------------------------------------------------------------------------
1 | import * as pathToRegexp from 'path-to-regexp';
2 |
3 | export const isRouteExcluded = (req: any, paths: string[] = []) => {
4 | return paths.some(path => {
5 | const re = pathToRegexp(path);
6 | const queryParamsIndex = req.originalUrl.indexOf('?');
7 | const pathname =
8 | queryParamsIndex >= 0
9 | ? req.originalUrl.slice(0, queryParamsIndex)
10 | : req.originalUrl;
11 |
12 | if (!re.exec(pathname + '/')) {
13 | return false;
14 | }
15 | return true;
16 | });
17 | };
18 |
--------------------------------------------------------------------------------
/lib/utils/validate-path.util.ts:
--------------------------------------------------------------------------------
1 | export const validatePath = (path: string) =>
2 | path && path.charAt(0) !== '/' ? `/${path}` : path;
3 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nestjs/serve-static",
3 | "version": "3.0.0",
4 | "description": "Nest - modern, fast, powerful node.js web framework (@serve-static)",
5 | "author": "Kamil Mysliwiec",
6 | "license": "MIT",
7 | "scripts": {
8 | "build": "npm run build:lib",
9 | "build:lib": "tsc -p tsconfig.json",
10 | "format": "prettier --write \"**/*.ts\"",
11 | "lint": "eslint 'lib/**/*.ts' --fix",
12 | "prepublish:npm": "npm run build",
13 | "publish:npm": "npm publish --access public",
14 | "prepublish:next": "npm run build",
15 | "publish:next": "npm publish --access public --tag next",
16 | "prerelease": "npm run build",
17 | "release": "release-it",
18 | "prepare": "husky install"
19 | },
20 | "peerDependencies": {
21 | "@nestjs/common": "^9.0.0",
22 | "@nestjs/core": "^9.0.0"
23 | },
24 | "devDependencies": {
25 | "@commitlint/cli": "17.0.3",
26 | "@commitlint/config-angular": "17.0.3",
27 | "@nestjs/common": "9.0.11",
28 | "@nestjs/core": "9.0.11",
29 | "@types/node": "16.11.53",
30 | "@typescript-eslint/eslint-plugin": "5.34.0",
31 | "@typescript-eslint/parser": "5.34.0",
32 | "eslint": "8.22.0",
33 | "eslint-config-prettier": "8.5.0",
34 | "eslint-plugin-import": "2.26.0",
35 | "express": "4.18.1",
36 | "fastify": "4.5.2",
37 | "@fastify/static": "6.5.0",
38 | "husky": "8.0.1",
39 | "lint-staged": "13.0.3",
40 | "prettier": "2.7.1",
41 | "reflect-metadata": "0.1.13",
42 | "release-it": "15.3.0",
43 | "rxjs": "7.5.6",
44 | "typescript": "4.7.4"
45 | },
46 | "lint-staged": {
47 | "*.ts": [
48 | "prettier --write"
49 | ]
50 | },
51 | "repository": {
52 | "type": "git",
53 | "url": "https://github.com/nestjs/serve-static"
54 | },
55 | "dependencies": {
56 | "path-to-regexp": "0.2.5"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "semanticCommits": true,
3 | "packageRules": [{
4 | "depTypeList": ["devDependencies"],
5 | "automerge": true
6 | }],
7 | "extends": [
8 | "config:base"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "noImplicitAny": false,
6 | "removeComments": true,
7 | "noLib": false,
8 | "emitDecoratorMetadata": true,
9 | "experimentalDecorators": true,
10 | "target": "es6",
11 | "sourceMap": false,
12 | "outDir": "./dist",
13 | "skipLibCheck": true
14 | },
15 | "include": ["lib/**/*", "../index.ts"],
16 | "exclude": ["node_modules", "**/*.spec.ts"]
17 | }
18 |
--------------------------------------------------------------------------------