1
- import path from 'path' ;
2
-
3
- import express from 'express' ;
4
- import formidable from 'express-formidable' ;
5
- import AdminBro , { Router } from 'admin-bro' ;
1
+ /* eslint-disable no-underscore-dangle */
2
+ import AdminBro from 'admin-bro' ;
6
3
import { Injectable } from '@nestjs/common' ;
7
4
import { AbstractHttpAdapter } from '@nestjs/core' ;
8
5
import { loadPackage } from '@nestjs/common/utils/load-package.util' ;
@@ -20,144 +17,49 @@ export class ExpressLoader extends AbstractLoader {
20
17
) {
21
18
const app = httpAdapter . getInstance ( ) ;
22
19
23
- const router = express . Router ( ) ;
20
+ loadPackage ( 'express' , '@admin-bro/nestjs' ) ;
21
+ const adminBroExpressjs = loadPackage ( '@admin-bro/express' , '@admin-bro/nestjs' , ( ) =>
22
+ require ( '@admin-bro/express' )
23
+ ) ;
24
+ loadPackage ( 'express-formidable' , '@admin-bro/nestjs' ) ;
25
+
26
+ let jsonParser ;
27
+ let urlencodedParser ;
28
+
29
+ // Nestjs uses bodyParser under the hood which is in conflict with admin-bro setup.
30
+ // Due to admin-bro-expressjs usage of formidable we have to move body parser in layer tree after admin-bro init.
31
+ // Notice! This is not documented feature of express, so this may change in the future. We have to keep an eye on it.
32
+ if ( app && app . _router && app . _router . stack ) {
33
+ const jsonParserIndex = app . _router . stack . findIndex ( layer => layer . name === 'jsonParser' ) ;
34
+ if ( jsonParserIndex >= 0 ) {
35
+ jsonParser = app . _router . stack . splice ( jsonParserIndex , 1 ) ;
36
+ }
24
37
25
- router . use ( formidable ( options . formidableOptions ) ) ;
38
+ const urlencodedParserIndex = app . _router . stack . findIndex ( layer => layer . name === 'urlencodedParser' ) ;
39
+ if ( urlencodedParserIndex >= 0 ) {
40
+ urlencodedParser = app . _router . stack . splice ( urlencodedParserIndex , 1 ) ;
41
+ }
42
+ }
26
43
27
- const { assets , routes } = Router ;
44
+ let router ;
28
45
29
46
if ( 'auth' in options ) {
30
- this . configureSession ( router , admin , options ) ;
47
+ loadPackage ( 'express-session' , '@admin-bro/nestjs' ) ;
48
+ router = adminBroExpressjs . buildAuthenticatedRouter (
49
+ admin , options . auth , undefined , options . sessionOptions , options . formidableOptions
50
+ ) ;
51
+ } else {
52
+ router = adminBroExpressjs . buildRouter ( admin , undefined , options . formidableOptions ) ;
31
53
}
32
54
33
- this . registerAssets ( router , assets , options ) ;
34
- this . registerRoutes ( router , admin , routes , options ) ;
35
-
36
55
app . use ( options . adminBroOptions . rootPath , router ) ;
37
- }
38
-
39
- private registerAssets ( app , assets , options : AdminModuleOptions ) {
40
- assets . forEach ( asset => {
41
- app . get ( asset . path , ( _req , res ) => {
42
- res . sendFile ( path . resolve ( asset . src ) )
43
- } )
44
- } )
45
- }
46
56
47
- private registerRoutes ( app , admin : AdminBro , routes , options : AdminModuleOptions ) {
48
- routes . forEach ( ( route ) => {
49
- // we have to change routes defined in AdminBro from {recordId} to :recordId
50
- const expressPath = `${ route . path . replace ( / { / g, ':' ) . replace ( / } / g, '' ) as string } `
51
-
52
- const handler = async ( req , res , next ) => {
53
- try {
54
- const controller = new route . Controller ( { admin } , req . session && req . session . adminUser )
55
- const { params, query } = req
56
- const method = req . method . toLowerCase ( )
57
- const payload = {
58
- ...( req . fields || { } ) ,
59
- ...( req . files || { } ) ,
60
- }
61
- const html = await controller [ route . action ] ( {
62
- ...req ,
63
- params,
64
- query,
65
- payload,
66
- method,
67
- } , res )
68
- if ( route . contentType ) {
69
- res . set ( { 'Content-Type' : route . contentType } )
70
- }
71
- if ( html ) {
72
- res . send ( html )
73
- }
74
- } catch ( e ) {
75
- next ( e )
76
- }
77
- }
78
-
79
- if ( route . method === 'GET' ) {
80
- app . get ( expressPath , handler )
81
- }
82
-
83
- if ( route . method === 'POST' ) {
84
- app . post ( expressPath , handler )
85
- }
86
- } )
87
- }
88
-
89
- private configureSession ( app , admin : AdminBro , options : AdminModuleOptions ) {
90
- const session = loadPackage ( 'express-session' , '@admin-bro/nestjs' , ( ) =>
91
- require ( 'express-session' )
92
- ) ;
93
-
94
- app . use ( session ( {
95
- ...options . sessionOptions ,
96
- secret : options . auth ?. cookiePassword ,
97
- name : options . auth ?. cookieName || 'adminbro' ,
98
- } ) ) ;
57
+ if ( jsonParser ) {
58
+ app . _router . stack . push ( ...jsonParser ) ;
59
+ }
99
60
100
- const { rootPath } = admin . options ;
101
- let { loginPath, logoutPath } = admin . options ;
102
- loginPath = loginPath . replace ( rootPath , '' )
103
- logoutPath = logoutPath . replace ( rootPath , '' )
104
-
105
- app . get ( loginPath , async ( _req , res ) => {
106
- const login = await admin . renderLogin ( {
107
- action : admin . options . loginPath ,
108
- errorMessage : null ,
109
- } ) ;
110
- res . send ( login ) ;
111
- } ) ;
112
-
113
- app . post ( loginPath , async ( req , res , next ) => {
114
- console . log ( 'login post' ) ;
115
- const { email, password } = req . fields ;
116
- const adminUser = await options . auth ?. authenticate ( email , password ) ;
117
- if ( adminUser ) {
118
- req . session . adminUser = adminUser ;
119
- req . session . save ( ( err ) => {
120
- if ( err ) {
121
- next ( err ) ;
122
- }
123
- if ( req . session . redirectTo ) {
124
- res . redirect ( req . session . redirectTo ) ;
125
- } else {
126
- res . redirect ( rootPath ) ;
127
- }
128
- } )
129
- } else {
130
- const login = await admin . renderLogin ( {
131
- action : admin . options . loginPath ,
132
- errorMessage : 'invalidCredentials' ,
133
- } ) ;
134
- res . send ( login ) ;
135
- }
136
- } ) ;
137
-
138
- app . use ( ( req , res , next ) => {
139
- console . log ( 'redirect?' )
140
- if ( AdminBro . Router . assets . some ( asset => req . originalUrl . match ( asset . path ) ) ) {
141
- next ( ) ;
142
- } else if ( req . session . adminUser ) {
143
- next ( ) ;
144
- } else {
145
- // If the redirection is caused by API call to some action just redirect to resource
146
- const [ redirectTo ] = req . originalUrl . split ( '/actions' ) ;
147
- req . session . redirectTo = redirectTo . includes ( `${ rootPath } /api` ) ? rootPath : redirectTo ;
148
- req . session . save ( ( err ) => {
149
- if ( err ) {
150
- next ( err ) ;
151
- }
152
- res . redirect ( admin . options . loginPath ) ;
153
- } )
154
- }
155
- } )
156
-
157
- app . get ( logoutPath , ( req , res ) => {
158
- req . session . destroy ( ( ) => {
159
- res . redirect ( admin . options . loginPath )
160
- } ) ;
161
- } ) ;
61
+ if ( urlencodedParser ) {
62
+ app . _router . stack . push ( ...urlencodedParser ) ;
63
+ }
162
64
}
163
65
}
0 commit comments