-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathindex.js
204 lines (174 loc) · 5.74 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
// @ts-check
import EventEmitter from 'node:events'
import { pino } from 'pino'
import fastify from 'fastify'
import fastifyCompress from '@fastify/compress'
import fastifyCors from '@fastify/cors'
import fastifyCookie from '@fastify/cookie'
import fastifyAccepts from '@fastify/accepts'
import fastifyFormBody from '@fastify/formbody'
import handler from './lib/config/handler.js'
import {
defaultHost,
defaultLogLevel,
defaultLogFormat,
defaultPort,
} from './lib/config/default.js'
import pluginsAssembler from './lib/plugins/assembler.js'
import applyPlugins from './lib/plugins/apply.js'
import templateEngine from './lib/templateEngine.js'
import { errorsHandler, notFoundHandler } from './lib/handlers/index.js'
// Export some useful functions to work with SPARQL
export {
supportedTypes as sparqlSupportedTypes,
serializeFormattedStream as sparqlSerializeFormattedStream,
serializeQuadStream as sparqlSerializeQuadStream,
getRewriteConfiguration as sparqlGetRewriteConfiguration,
} from './lib/sparql.js'
// Export some functions that can be used for testing
export {
assertRejection,
getListenerURL,
} from './lib/test.js'
/**
* Create a new Trifid instance.
*
* @param {import('./types/index.js').TrifidConfigWithExtends?} config Trifid configuration.
* @param {Record<string, {
* order?: number,
* module: import('./types/index.js').TrifidPlugin,
* paths?: string | string[];
* methods?: string | string[];
* hosts?: string | string[];
* config?: Record<string, any>;
* }>?} additionalPlugins Add additional plugins.
* @returns {Promise<{
* start: () => Promise<import('fastify').FastifyInstance>;
* server: import('fastify').FastifyInstance;
* config: import('./types/index.js').TrifidConfig
* }>} Trifid instance.
*/
const trifid = async (config, additionalPlugins = {}) => {
const trifidEvents = new EventEmitter()
const fullConfig = await handler(config)
const serverOptions = fullConfig?.server?.options || {}
// Template configuration
const template = fullConfig?.template || {}
// Dynamic server configuration
const portFromConfig = fullConfig?.server?.listener?.port
const port = (portFromConfig === 0 || portFromConfig === '0') ? 0 : (portFromConfig || defaultPort)
const host = fullConfig?.server?.listener?.host || defaultHost
const portNumber = typeof port === 'string' ? parseInt(port, 10) : port
// Logger configuration
const logLevel = fullConfig?.server?.logLevel || defaultLogLevel
const logFormat = fullConfig?.server?.logFormat || defaultLogFormat
const loggerConfig = {
name: 'trifid-core',
level: logLevel,
}
if (logFormat === 'pretty') {
loggerConfig.transport = {
target: 'pino-pretty',
}
}
// Custom logger instance
const logger = pino(loggerConfig)
const server = fastify({
logger: false,
trustProxy: true,
...serverOptions,
})
// Register fastifyCompress and add custom compressible mime-types (in addition to mime-db)
await server.register(fastifyCompress, { customTypes: /(turtle|n-triples|n-quads|trig|json)(;.+)?$/ })
// Add support for `application/sparql-query` content type
server.addContentTypeParser('application/sparql-query', (_request, payload, done) => {
const data = []
payload.on('data', (chunk) => data.push(chunk))
payload.on('end', () => {
try {
const parsed = data.join('')
done(null, parsed)
} catch (err) {
done(err, undefined)
}
})
})
// This can be used to pass data from multiple plugins
/** @type {Map<string, any>} */
const trifidLocals = new Map()
server.decorate('locals', trifidLocals)
/**
* Handler to add a session to the request.
*
* @param {import('fastify').FastifyRequest & { session: Map<string, any> }} request Request.
* @param {import('fastify').FastifyReply} _reply Reply.
* @param {import('fastify').DoneFuncWithErrOrRes} done Done.
*/
const addSessionHandler = (request, _reply, done) => {
request.session = new Map()
done()
}
server.addHook('onRequest', addSessionHandler)
// Add required plugins
server.register(fastifyCors, {
credentials: true,
origin: true,
})
// Add support for cookies
server.register(fastifyCookie)
// Add support for Accept header parser
server.register(fastifyAccepts)
// Add support for `application/x-www-form-urlencoded` content type
server.register(fastifyFormBody)
// Template engine configuration
const templateEngineInstance = await templateEngine(template, trifidLocals)
const { render } = templateEngineInstance
// Add error and not found handlers (requires template engine to be ready)
server.setErrorHandler(errorsHandler)
server.setNotFoundHandler(await notFoundHandler({ render }))
const plugins = await pluginsAssembler(
fullConfig,
additionalPlugins,
)
await applyPlugins(
server,
fullConfig.globals,
plugins,
logger,
templateEngineInstance,
`http://${host}:${portNumber}/`,
trifidEvents,
)
const start = async () => {
// Forward server events to the Trifid plugins
server.addHook('onListen', () => {
trifidEvents.emit('listen')
})
server.addHook('onClose', () => {
trifidEvents.emit('close')
})
server.addHook('onReady', () => {
trifidEvents.emit('ready')
})
// Start server
await server.listen({
port: portNumber,
host,
})
// Log server address
const fastifyAddresses = server.addresses().map((address) => {
if (typeof address === 'string') {
return address
}
return `http://${address.address}:${address.port}`
})
logger.info(`Server listening on ${fastifyAddresses.join(', ')}`)
return server
}
return {
start,
server,
config: fullConfig,
}
}
export default trifid