Skip to content

Commit

Permalink
feat(): routing platform independence (resolved PR remarks)
Browse files Browse the repository at this point in the history
  • Loading branch information
flamewow committed Apr 13, 2022
1 parent 2913391 commit ea85683
Show file tree
Hide file tree
Showing 7 changed files with 6,293 additions and 14,451 deletions.
19 changes: 9 additions & 10 deletions e2e/manual-e2e.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { NestFactory } from '@nestjs/core';
import { ApplicationModule } from './src/app.module';
import { DocumentBuilder, SwaggerModule } from '../lib';
import {
FastifyAdapter,
NestFastifyApplication
} from '@nestjs/platform-fastify';
import { FastifyAdapter } from '@nestjs/platform-fastify';
import { INestApplication, Logger } from '@nestjs/common';
import { ExpressAdapter } from '@nestjs/platform-express';

const port = 4001;
const host = 'localhost';
const docRelPath = '/api-docs';

const USE_FASTIFY = false;

const adapter = USE_FASTIFY ? new FastifyAdapter() : new ExpressAdapter();

async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(
const app = await NestFactory.create<INestApplication>(
ApplicationModule,
new FastifyAdapter()
// new ExpressAdapter()
adapter
);

app.setGlobalPrefix('/api/v1');
Expand Down Expand Up @@ -45,15 +44,15 @@ async function bootstrap() {
});

SwaggerModule.setup(docRelPath, app, document, {
customSiteTitle: 'Demo API - Swagger UI',
customSiteTitle: 'Demo API - Swagger UI 1',
swaggerOptions: {
persistAuthorization: true,
defaultModelsExpandDepth: -1
}
});

SwaggerModule.setup('/swagger-docs', app, document, {
customSiteTitle: 'Demo API - Swagger UI',
customSiteTitle: 'Demo API - Swagger UI 2',
swaggerOptions: {
persistAuthorization: true,
defaultModelsExpandDepth: -1
Expand Down
8 changes: 8 additions & 0 deletions lib/interfaces/swagger-ui-init-options.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { SwaggerCustomOptions } from './swagger-custom-options.interface';
import { OpenAPIObject } from './open-api-spec.interface';

export interface SwaggerUIInitOptions {
swaggerDoc: OpenAPIObject;
customOptions: SwaggerCustomOptions;
swaggerUrl: string;
}
11 changes: 5 additions & 6 deletions lib/swagger-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,16 @@ export class SwaggerModule {
const httpAdapter = app.getHttpAdapter();

if (httpAdapter && httpAdapter.getType() === 'fastify') {
const fastifyApp = app as NestFastifyApplication; // TODO: figure out cleaner solution
fastifyApp.useStaticAssets({
(app as NestFastifyApplication).useStaticAssets({
root: swaggerAssetsAbsoluteFSPath,
prefix: `${finalPath}/`,
decorateReply: false
});
} else {
const expressApp = app as NestExpressApplication; // TODO: figure out cleaner solution
expressApp.useStaticAssets(swaggerAssetsAbsoluteFSPath, {
prefix: finalPath
});
(app as NestExpressApplication).useStaticAssets(
swaggerAssetsAbsoluteFSPath,
{ prefix: finalPath }
);
}
}

Expand Down
24 changes: 24 additions & 0 deletions lib/swagger-ui/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { SwaggerUIInitOptions } from '../interfaces/swagger-ui-init-options.interface';

/**
* Transforms options JS object into a string that can be inserted as 'variable' into JS file
*/
export function buildJSInitOptions(initOptions: SwaggerUIInitOptions) {
const functionPlaceholder = '____FUNCTION_PLACEHOLDER____';
const fns = [];
let json = JSON.stringify(
initOptions,
(key, value) => {
if (typeof value === 'function') {
fns.push(value);
return functionPlaceholder;
}
return value;
},
2
);

json = json.replace(new RegExp(functionPlaceholder, 'g'), () => fns.shift());

return `let options = ${json};`;
}
86 changes: 38 additions & 48 deletions lib/swagger-ui/swagger-ui.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,46 @@
import * as swaggerUi from 'swagger-ui-dist';
import { favIconHtml, htmlTemplateString, jsTemplateString } from './constants';
import { SwaggerCustomOptions } from '../interfaces';

const buildJSInitOptions = (obj) => {
const placeholder = '____FUNCTIONPLACEHOLDER____';
const fns = [];
let json = JSON.stringify(
obj,
function (key, value) {
if (typeof value === 'function') {
fns.push(value);
return placeholder;
}
return value;
},
2
);
import { OpenAPIObject, SwaggerCustomOptions } from '../interfaces';
import { buildJSInitOptions } from './helpers';

/**
* Used to create swagger ui initialization js file (
*/
export function buildSwaggerInitJS(
swaggerDoc: OpenAPIObject,
customOptions: SwaggerCustomOptions = {}
) {
const { swaggerOptions, swaggerUrl } = customOptions;
const swaggerInitOptions = {
swaggerDoc,
swaggerUrl,
customOptions: swaggerOptions
};

json = json.replace(new RegExp('"' + placeholder + '"', 'g'), function (_) {
return fns.shift();
});
const jsInitOptions = buildJSInitOptions(swaggerInitOptions);
return jsTemplateString.replace('<% swaggerOptions %>', jsInitOptions);
}

return `let options = ${json};`;
};
/**
* Stores absolute path to swagger-ui assets
*/
export const swaggerAssetsAbsoluteFSPath = swaggerUi.getAbsoluteFSPath();

export const buildSwaggerHTML = function (
baseUrl,
swaggerDoc,
options: SwaggerCustomOptions
/**
* Used to build swagger-ui custom html
*/
export function buildSwaggerHTML(
baseUrl: string,
swaggerDoc: OpenAPIObject,
customOptions: SwaggerCustomOptions = {}
) {
const customCss = options?.customCss ?? '';
const customJs = options?.customJs ?? '';
const customfavIcon = options?.customfavIcon ?? false;
const customSiteTitle = options?.customSiteTitle ?? 'Swagger UI';
const customCssUrl = options?.customCssUrl ?? '';
const {
customCss = '',
customJs = '',
customfavIcon = false,
customSiteTitle = 'Swagger UI',
customCssUrl = ''
} = customOptions;

const favIconString = customfavIcon
? `<link rel="icon" href="${customfavIcon}" />`
Expand All @@ -52,21 +59,4 @@ export const buildSwaggerHTML = function (
customCssUrl ? `<link href="${customCssUrl}" rel="stylesheet">` : ''
)
.replace('<% title %>', customSiteTitle);
};

export const buildSwaggerInitJS = (
swaggerDoc,
options: SwaggerCustomOptions = {}
) => {
const initOptions = {
swaggerDoc: swaggerDoc ?? undefined,
customOptions: options.swaggerOptions ?? {},
swaggerUrl: options.swaggerUrl ?? {}
};

return jsTemplateString
.toString()
.replace('<% swaggerOptions %>', buildJSInitOptions(initOptions));
};

export const swaggerAssetsAbsoluteFSPath = swaggerUi.getAbsoluteFSPath();
}

0 comments on commit ea85683

Please sign in to comment.