@srfnstack/spliffy 1.2.5 → 1.2.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.
- package/LICENSE.txt +20 -20
- package/README.md +43 -43
- package/package.json +47 -44
- package/src/content.mjs +97 -97
- package/src/decorator.mjs +209 -209
- package/src/handler.mjs +256 -256
- package/src/index.mjs +30 -30
- package/src/log.mjs +59 -59
- package/src/middleware.mjs +89 -89
- package/src/nodeModuleHandler.mjs +75 -75
- package/src/routes.mjs +205 -205
- package/src/server.mjs +141 -141
- package/src/serverConfig.mjs +100 -100
- package/src/start.mjs +25 -25
- package/src/staticHandler.mjs +74 -74
- package/src/url.mjs +24 -24
package/src/routes.mjs
CHANGED
|
@@ -1,205 +1,205 @@
|
|
|
1
|
-
import { validateMiddleware, mergeMiddleware } from './middleware.mjs'
|
|
2
|
-
import { createStaticHandler } from './staticHandler.mjs'
|
|
3
|
-
import { getContentTypeByExtension } from './content.mjs'
|
|
4
|
-
import fs from 'fs'
|
|
5
|
-
import path from 'path'
|
|
6
|
-
import { HTTP_METHODS } from './handler.mjs'
|
|
7
|
-
import util from 'util'
|
|
8
|
-
|
|
9
|
-
const { promisify } = util
|
|
10
|
-
|
|
11
|
-
const readdir = promisify(fs.readdir)
|
|
12
|
-
|
|
13
|
-
const isVariable = part => part.startsWith('$')
|
|
14
|
-
const getVariableName = part => part.substr(1)
|
|
15
|
-
const getPathPart = name => {
|
|
16
|
-
if (name === 'index') {
|
|
17
|
-
return ''
|
|
18
|
-
}
|
|
19
|
-
if (name.startsWith('$')) {
|
|
20
|
-
return `:${name.substr(1)}`
|
|
21
|
-
} else if (name.endsWith('+')) {
|
|
22
|
-
return `${name.substr(0, name.length - 1)}/*`
|
|
23
|
-
} else {
|
|
24
|
-
return name
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
const filterTestFiles = config => f => (!f.name.endsWith('.test.js') && !f.name.endsWith('.test.mjs')) || config.allowTestFileRoutes
|
|
28
|
-
const filterIgnoredFiles = config => f => !config.ignoreFilesMatching.filter(p => p).find(pattern => f.name.match(pattern))
|
|
29
|
-
const ignoreHandlerFields = { middleware: true, streamRequestBody: true }
|
|
30
|
-
|
|
31
|
-
const isRouteFile = name => name.endsWith('.rt.js') || name.endsWith('.rt.mjs') || name.endsWith('.rt.cjs')
|
|
32
|
-
const isMiddlewareFile = name => name.endsWith('.mw.js') || name.endsWith('.mw.mjs') || name.endsWith('.mw.cjs')
|
|
33
|
-
|
|
34
|
-
const doFindRoutes = async (config, currentFile, filePath, urlPath, pathParameters, inheritedMiddleware) => {
|
|
35
|
-
const routes = []
|
|
36
|
-
const name = currentFile.name
|
|
37
|
-
if (currentFile.isDirectory()) {
|
|
38
|
-
routes.push(...(await findRoutesInDir(name, filePath, urlPath, inheritedMiddleware, pathParameters, config)))
|
|
39
|
-
} else if (!config.staticMode && isRouteFile(name)) {
|
|
40
|
-
routes.push(await buildJSHandlerRoute(name, filePath, urlPath, inheritedMiddleware, pathParameters))
|
|
41
|
-
} else {
|
|
42
|
-
routes.push(...buildStaticRoutes(name, filePath, urlPath, inheritedMiddleware, pathParameters, config))
|
|
43
|
-
}
|
|
44
|
-
return routes
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const wrapSyntaxError = (e, path) => {
|
|
48
|
-
// Hack to workaround https://github.com/nodejs/modules/issues/471
|
|
49
|
-
if (e instanceof SyntaxError) {
|
|
50
|
-
const newError = new SyntaxError(`${e.message}. In file: ${path}`)
|
|
51
|
-
newError.stack += `\nCaused By: ${e.stack}`
|
|
52
|
-
throw newError
|
|
53
|
-
}
|
|
54
|
-
throw e
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const importModules = async (config, dirPath, files) => Promise.all(
|
|
58
|
-
files
|
|
59
|
-
.filter(filterTestFiles(config))
|
|
60
|
-
.filter(filterIgnoredFiles(config))
|
|
61
|
-
.map(f => path.join(dirPath, f.name))
|
|
62
|
-
.map(mwPath => import(`file://${mwPath}`)
|
|
63
|
-
.then(module => ({ module, mwPath }))
|
|
64
|
-
.catch(e => wrapSyntaxError(e, mwPath))
|
|
65
|
-
))
|
|
66
|
-
|
|
67
|
-
const findRoutesInDir = async (name, filePath, urlPath, inheritedMiddleware, pathParameters, config) => {
|
|
68
|
-
if (isVariable(name)) {
|
|
69
|
-
pathParameters = pathParameters.concat(getVariableName(name))
|
|
70
|
-
}
|
|
71
|
-
const files = await readdir(filePath, { withFileTypes: true })
|
|
72
|
-
|
|
73
|
-
const middlewareModules = await importModules(config, filePath, files.filter(f => isMiddlewareFile(f.name)))
|
|
74
|
-
const dirMiddleware = middlewareModules.map(({ module, mwPath }) => {
|
|
75
|
-
const middleware = module.middleware || module.default?.middleware
|
|
76
|
-
if (!middleware) {
|
|
77
|
-
throw new Error(`${mwPath} must export a middleware property or have a middleware property on the default export`)
|
|
78
|
-
}
|
|
79
|
-
try {
|
|
80
|
-
validateMiddleware(middleware)
|
|
81
|
-
} catch (e) {
|
|
82
|
-
throw new Error('Failed to load middleware in file ' + mwPath + '\n' + e.message + '\n' + e.stack)
|
|
83
|
-
}
|
|
84
|
-
return middleware
|
|
85
|
-
})
|
|
86
|
-
.reduce((result, incoming) => mergeMiddleware(incoming, result), inheritedMiddleware)
|
|
87
|
-
|
|
88
|
-
return Promise.all(files
|
|
89
|
-
.filter(f => !isMiddlewareFile(f.name))
|
|
90
|
-
.filter(filterTestFiles(config))
|
|
91
|
-
.filter(filterIgnoredFiles(config))
|
|
92
|
-
.map(
|
|
93
|
-
(f) => doFindRoutes(
|
|
94
|
-
config,
|
|
95
|
-
f,
|
|
96
|
-
path.join(filePath, f.name),
|
|
97
|
-
urlPath + '/' + getPathPart(name),
|
|
98
|
-
pathParameters,
|
|
99
|
-
dirMiddleware
|
|
100
|
-
)
|
|
101
|
-
))
|
|
102
|
-
.then(routes => routes.flat())
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const buildJSHandlerRoute = async (name, filePath, urlPath, inheritedMiddleware, pathParameters) => {
|
|
106
|
-
if (name.endsWith('.mjs') || name.endsWith('.cjs')) {
|
|
107
|
-
name = name.substr(0, name.length - '.rt.mjs'.length)
|
|
108
|
-
} else {
|
|
109
|
-
name = name.substr(0, name.length - '.rt.js'.length)
|
|
110
|
-
}
|
|
111
|
-
if (isVariable(name)) {
|
|
112
|
-
pathParameters = pathParameters.concat(getVariableName(name))
|
|
113
|
-
}
|
|
114
|
-
const route = {
|
|
115
|
-
pathParameters,
|
|
116
|
-
urlPath: `${urlPath}/${getPathPart(name)}`,
|
|
117
|
-
filePath,
|
|
118
|
-
handlers: {}
|
|
119
|
-
}
|
|
120
|
-
let module
|
|
121
|
-
try {
|
|
122
|
-
module = await import(`file://${filePath}`)
|
|
123
|
-
} catch (e) {
|
|
124
|
-
wrapSyntaxError(e, filePath)
|
|
125
|
-
}
|
|
126
|
-
const handlers = module.default
|
|
127
|
-
try {
|
|
128
|
-
route.middleware = mergeMiddleware(handlers.middleware || [], inheritedMiddleware)
|
|
129
|
-
} catch (e) {
|
|
130
|
-
const err = new Error(`Failed to load middleware for route: ${filePath}`)
|
|
131
|
-
err.stack += `\nCaused By: ${e.stack}`
|
|
132
|
-
throw err
|
|
133
|
-
}
|
|
134
|
-
for (const method of Object.keys(handlers).filter(k => !ignoreHandlerFields[k])) {
|
|
135
|
-
if (HTTP_METHODS.indexOf(method) === -1) {
|
|
136
|
-
throw new Error(`Method: ${method} in file ${filePath} is not a valid http method. It must be one of: ${HTTP_METHODS}. Method names must be all uppercase.`)
|
|
137
|
-
}
|
|
138
|
-
const loadedHandler = handlers[method]
|
|
139
|
-
let handler = loadedHandler
|
|
140
|
-
if (typeof loadedHandler.handler === 'function') {
|
|
141
|
-
handler = loadedHandler.handler
|
|
142
|
-
}
|
|
143
|
-
if (typeof handler !== 'function' && method !== 'WEBSOCKET') {
|
|
144
|
-
throw new Error(`Request method ${method} in file ${filePath} must be a function. Got: ${typeof handlers[method]}`)
|
|
145
|
-
} else if (method === 'WEBSOCKET' && typeof handler !== 'object') {
|
|
146
|
-
throw new Error(`Websocket in file ${filePath} must be an object. Got: ${typeof handlers[method]}`)
|
|
147
|
-
}
|
|
148
|
-
if (!('streamRequestBody' in loadedHandler)) {
|
|
149
|
-
handler.streamRequestBody = handlers.streamRequestBody
|
|
150
|
-
} else {
|
|
151
|
-
handler.streamRequestBody = loadedHandler.streamRequestBody
|
|
152
|
-
}
|
|
153
|
-
route.handlers[method] = handler
|
|
154
|
-
}
|
|
155
|
-
return route
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const buildStaticRoutes = (name, filePath, urlPath, inheritedMiddleware, pathParameters, config) => {
|
|
159
|
-
const routes = []
|
|
160
|
-
if (isVariable(name)) {
|
|
161
|
-
pathParameters = pathParameters.concat(getVariableName(name))
|
|
162
|
-
}
|
|
163
|
-
const contentType = getContentTypeByExtension(name, config.staticContentTypes)
|
|
164
|
-
const route = {
|
|
165
|
-
pathParameters,
|
|
166
|
-
urlPath: `${urlPath}/${getPathPart(name)}`,
|
|
167
|
-
filePath,
|
|
168
|
-
handlers: createStaticHandler(filePath, contentType, config.cacheStatic, config.staticCacheControl),
|
|
169
|
-
middleware: inheritedMiddleware
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
routes.push(route)
|
|
173
|
-
|
|
174
|
-
for (const ext of config.resolveWithoutExtension) {
|
|
175
|
-
if (name.endsWith(ext)) {
|
|
176
|
-
const strippedName = name.substr(0, name.length - ext.length)
|
|
177
|
-
// in the index case we need to add both the stripped and an empty path so it will resolve the parent
|
|
178
|
-
if (strippedName === 'index') {
|
|
179
|
-
const noExtRoute = Object.assign({}, route)
|
|
180
|
-
noExtRoute.urlPath = `${urlPath}/${strippedName}`
|
|
181
|
-
routes.push(noExtRoute)
|
|
182
|
-
}
|
|
183
|
-
const noExtRoute = Object.assign({}, route)
|
|
184
|
-
noExtRoute.urlPath = `${urlPath}/${getPathPart(strippedName)}`
|
|
185
|
-
routes.push(noExtRoute)
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return routes
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
export async function findRoutes (config) {
|
|
192
|
-
const fullRouteDir = path.resolve(config.routeDir)
|
|
193
|
-
if (!fs.existsSync(fullRouteDir)) {
|
|
194
|
-
throw new Error(`can't find route directory: ${fullRouteDir}`)
|
|
195
|
-
}
|
|
196
|
-
const appMiddleware = mergeMiddleware(config.middleware || [], {})
|
|
197
|
-
const files = await readdir(fullRouteDir, { withFileTypes: true })
|
|
198
|
-
return Promise.all(files
|
|
199
|
-
.filter(filterTestFiles(config))
|
|
200
|
-
.filter(filterIgnoredFiles(config))
|
|
201
|
-
.map(
|
|
202
|
-
f => doFindRoutes(config, f, path.join(fullRouteDir, f.name), '', [], appMiddleware)
|
|
203
|
-
))
|
|
204
|
-
.then(routes => routes.flat())
|
|
205
|
-
}
|
|
1
|
+
import { validateMiddleware, mergeMiddleware } from './middleware.mjs'
|
|
2
|
+
import { createStaticHandler } from './staticHandler.mjs'
|
|
3
|
+
import { getContentTypeByExtension } from './content.mjs'
|
|
4
|
+
import fs from 'fs'
|
|
5
|
+
import path from 'path'
|
|
6
|
+
import { HTTP_METHODS } from './handler.mjs'
|
|
7
|
+
import util from 'util'
|
|
8
|
+
|
|
9
|
+
const { promisify } = util
|
|
10
|
+
|
|
11
|
+
const readdir = promisify(fs.readdir)
|
|
12
|
+
|
|
13
|
+
const isVariable = part => part.startsWith('$')
|
|
14
|
+
const getVariableName = part => part.substr(1)
|
|
15
|
+
const getPathPart = name => {
|
|
16
|
+
if (name === 'index') {
|
|
17
|
+
return ''
|
|
18
|
+
}
|
|
19
|
+
if (name.startsWith('$')) {
|
|
20
|
+
return `:${name.substr(1)}`
|
|
21
|
+
} else if (name.endsWith('+')) {
|
|
22
|
+
return `${name.substr(0, name.length - 1)}/*`
|
|
23
|
+
} else {
|
|
24
|
+
return name
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const filterTestFiles = config => f => (!f.name.endsWith('.test.js') && !f.name.endsWith('.test.mjs')) || config.allowTestFileRoutes
|
|
28
|
+
const filterIgnoredFiles = config => f => !config.ignoreFilesMatching.filter(p => p).find(pattern => f.name.match(pattern))
|
|
29
|
+
const ignoreHandlerFields = { middleware: true, streamRequestBody: true }
|
|
30
|
+
|
|
31
|
+
const isRouteFile = name => name.endsWith('.rt.js') || name.endsWith('.rt.mjs') || name.endsWith('.rt.cjs')
|
|
32
|
+
const isMiddlewareFile = name => name.endsWith('.mw.js') || name.endsWith('.mw.mjs') || name.endsWith('.mw.cjs')
|
|
33
|
+
|
|
34
|
+
const doFindRoutes = async (config, currentFile, filePath, urlPath, pathParameters, inheritedMiddleware) => {
|
|
35
|
+
const routes = []
|
|
36
|
+
const name = currentFile.name
|
|
37
|
+
if (currentFile.isDirectory()) {
|
|
38
|
+
routes.push(...(await findRoutesInDir(name, filePath, urlPath, inheritedMiddleware, pathParameters, config)))
|
|
39
|
+
} else if (!config.staticMode && isRouteFile(name)) {
|
|
40
|
+
routes.push(await buildJSHandlerRoute(name, filePath, urlPath, inheritedMiddleware, pathParameters))
|
|
41
|
+
} else {
|
|
42
|
+
routes.push(...buildStaticRoutes(name, filePath, urlPath, inheritedMiddleware, pathParameters, config))
|
|
43
|
+
}
|
|
44
|
+
return routes
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const wrapSyntaxError = (e, path) => {
|
|
48
|
+
// Hack to workaround https://github.com/nodejs/modules/issues/471
|
|
49
|
+
if (e instanceof SyntaxError) {
|
|
50
|
+
const newError = new SyntaxError(`${e.message}. In file: ${path}`)
|
|
51
|
+
newError.stack += `\nCaused By: ${e.stack}`
|
|
52
|
+
throw newError
|
|
53
|
+
}
|
|
54
|
+
throw e
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const importModules = async (config, dirPath, files) => Promise.all(
|
|
58
|
+
files
|
|
59
|
+
.filter(filterTestFiles(config))
|
|
60
|
+
.filter(filterIgnoredFiles(config))
|
|
61
|
+
.map(f => path.join(dirPath, f.name))
|
|
62
|
+
.map(mwPath => import(`file://${mwPath}`)
|
|
63
|
+
.then(module => ({ module, mwPath }))
|
|
64
|
+
.catch(e => wrapSyntaxError(e, mwPath))
|
|
65
|
+
))
|
|
66
|
+
|
|
67
|
+
const findRoutesInDir = async (name, filePath, urlPath, inheritedMiddleware, pathParameters, config) => {
|
|
68
|
+
if (isVariable(name)) {
|
|
69
|
+
pathParameters = pathParameters.concat(getVariableName(name))
|
|
70
|
+
}
|
|
71
|
+
const files = await readdir(filePath, { withFileTypes: true })
|
|
72
|
+
|
|
73
|
+
const middlewareModules = await importModules(config, filePath, files.filter(f => isMiddlewareFile(f.name)))
|
|
74
|
+
const dirMiddleware = middlewareModules.map(({ module, mwPath }) => {
|
|
75
|
+
const middleware = module.middleware || module.default?.middleware
|
|
76
|
+
if (!middleware) {
|
|
77
|
+
throw new Error(`${mwPath} must export a middleware property or have a middleware property on the default export`)
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
validateMiddleware(middleware)
|
|
81
|
+
} catch (e) {
|
|
82
|
+
throw new Error('Failed to load middleware in file ' + mwPath + '\n' + e.message + '\n' + e.stack)
|
|
83
|
+
}
|
|
84
|
+
return middleware
|
|
85
|
+
})
|
|
86
|
+
.reduce((result, incoming) => mergeMiddleware(incoming, result), inheritedMiddleware)
|
|
87
|
+
|
|
88
|
+
return Promise.all(files
|
|
89
|
+
.filter(f => !isMiddlewareFile(f.name))
|
|
90
|
+
.filter(filterTestFiles(config))
|
|
91
|
+
.filter(filterIgnoredFiles(config))
|
|
92
|
+
.map(
|
|
93
|
+
(f) => doFindRoutes(
|
|
94
|
+
config,
|
|
95
|
+
f,
|
|
96
|
+
path.join(filePath, f.name),
|
|
97
|
+
urlPath + '/' + getPathPart(name),
|
|
98
|
+
pathParameters,
|
|
99
|
+
dirMiddleware
|
|
100
|
+
)
|
|
101
|
+
))
|
|
102
|
+
.then(routes => routes.flat())
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const buildJSHandlerRoute = async (name, filePath, urlPath, inheritedMiddleware, pathParameters) => {
|
|
106
|
+
if (name.endsWith('.mjs') || name.endsWith('.cjs')) {
|
|
107
|
+
name = name.substr(0, name.length - '.rt.mjs'.length)
|
|
108
|
+
} else {
|
|
109
|
+
name = name.substr(0, name.length - '.rt.js'.length)
|
|
110
|
+
}
|
|
111
|
+
if (isVariable(name)) {
|
|
112
|
+
pathParameters = pathParameters.concat(getVariableName(name))
|
|
113
|
+
}
|
|
114
|
+
const route = {
|
|
115
|
+
pathParameters,
|
|
116
|
+
urlPath: `${urlPath}/${getPathPart(name)}`,
|
|
117
|
+
filePath,
|
|
118
|
+
handlers: {}
|
|
119
|
+
}
|
|
120
|
+
let module
|
|
121
|
+
try {
|
|
122
|
+
module = await import(`file://${filePath}`)
|
|
123
|
+
} catch (e) {
|
|
124
|
+
wrapSyntaxError(e, filePath)
|
|
125
|
+
}
|
|
126
|
+
const handlers = module.default
|
|
127
|
+
try {
|
|
128
|
+
route.middleware = mergeMiddleware(handlers.middleware || [], inheritedMiddleware)
|
|
129
|
+
} catch (e) {
|
|
130
|
+
const err = new Error(`Failed to load middleware for route: ${filePath}`)
|
|
131
|
+
err.stack += `\nCaused By: ${e.stack}`
|
|
132
|
+
throw err
|
|
133
|
+
}
|
|
134
|
+
for (const method of Object.keys(handlers).filter(k => !ignoreHandlerFields[k])) {
|
|
135
|
+
if (HTTP_METHODS.indexOf(method) === -1) {
|
|
136
|
+
throw new Error(`Method: ${method} in file ${filePath} is not a valid http method. It must be one of: ${HTTP_METHODS}. Method names must be all uppercase.`)
|
|
137
|
+
}
|
|
138
|
+
const loadedHandler = handlers[method]
|
|
139
|
+
let handler = loadedHandler
|
|
140
|
+
if (typeof loadedHandler.handler === 'function') {
|
|
141
|
+
handler = loadedHandler.handler
|
|
142
|
+
}
|
|
143
|
+
if (typeof handler !== 'function' && method !== 'WEBSOCKET') {
|
|
144
|
+
throw new Error(`Request method ${method} in file ${filePath} must be a function. Got: ${typeof handlers[method]}`)
|
|
145
|
+
} else if (method === 'WEBSOCKET' && typeof handler !== 'object') {
|
|
146
|
+
throw new Error(`Websocket in file ${filePath} must be an object. Got: ${typeof handlers[method]}`)
|
|
147
|
+
}
|
|
148
|
+
if (!('streamRequestBody' in loadedHandler)) {
|
|
149
|
+
handler.streamRequestBody = handlers.streamRequestBody
|
|
150
|
+
} else {
|
|
151
|
+
handler.streamRequestBody = loadedHandler.streamRequestBody
|
|
152
|
+
}
|
|
153
|
+
route.handlers[method] = handler
|
|
154
|
+
}
|
|
155
|
+
return route
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const buildStaticRoutes = (name, filePath, urlPath, inheritedMiddleware, pathParameters, config) => {
|
|
159
|
+
const routes = []
|
|
160
|
+
if (isVariable(name)) {
|
|
161
|
+
pathParameters = pathParameters.concat(getVariableName(name))
|
|
162
|
+
}
|
|
163
|
+
const contentType = getContentTypeByExtension(name, config.staticContentTypes)
|
|
164
|
+
const route = {
|
|
165
|
+
pathParameters,
|
|
166
|
+
urlPath: `${urlPath}/${getPathPart(name)}`,
|
|
167
|
+
filePath,
|
|
168
|
+
handlers: createStaticHandler(filePath, contentType, config.cacheStatic, config.staticCacheControl),
|
|
169
|
+
middleware: inheritedMiddleware
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
routes.push(route)
|
|
173
|
+
|
|
174
|
+
for (const ext of config.resolveWithoutExtension) {
|
|
175
|
+
if (name.endsWith(ext)) {
|
|
176
|
+
const strippedName = name.substr(0, name.length - ext.length)
|
|
177
|
+
// in the index case we need to add both the stripped and an empty path so it will resolve the parent
|
|
178
|
+
if (strippedName === 'index') {
|
|
179
|
+
const noExtRoute = Object.assign({}, route)
|
|
180
|
+
noExtRoute.urlPath = `${urlPath}/${strippedName}`
|
|
181
|
+
routes.push(noExtRoute)
|
|
182
|
+
}
|
|
183
|
+
const noExtRoute = Object.assign({}, route)
|
|
184
|
+
noExtRoute.urlPath = `${urlPath}/${getPathPart(strippedName)}`
|
|
185
|
+
routes.push(noExtRoute)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return routes
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export async function findRoutes (config) {
|
|
192
|
+
const fullRouteDir = path.resolve(config.routeDir)
|
|
193
|
+
if (!fs.existsSync(fullRouteDir)) {
|
|
194
|
+
throw new Error(`can't find route directory: ${fullRouteDir}`)
|
|
195
|
+
}
|
|
196
|
+
const appMiddleware = mergeMiddleware(config.middleware || [], {})
|
|
197
|
+
const files = await readdir(fullRouteDir, { withFileTypes: true })
|
|
198
|
+
return Promise.all(files
|
|
199
|
+
.filter(filterTestFiles(config))
|
|
200
|
+
.filter(filterIgnoredFiles(config))
|
|
201
|
+
.map(
|
|
202
|
+
f => doFindRoutes(config, f, path.join(fullRouteDir, f.name), '', [], appMiddleware)
|
|
203
|
+
))
|
|
204
|
+
.then(routes => routes.flat())
|
|
205
|
+
}
|