@platformatic/service 1.51.8 → 2.0.0-alpha.2

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.
@@ -1,217 +0,0 @@
1
- 'use strict'
2
-
3
- const { join } = require('node:path')
4
- const { readFile } = require('node:fs/promises')
5
- const deepClone = require('rfdc')({ proto: true })
6
- const compareOpenApiSchemas = require('openapi-schema-diff')
7
- const fp = require('fastify-plugin')
8
- const {
9
- changeOpenapiSchemaPrefix,
10
- convertOpenApiToFastifyPath
11
- } = require('../utils')
12
-
13
- const wrapperPath = join(__dirname, 'sandbox-wrapper.js')
14
-
15
- const Swagger = require('@fastify/swagger')
16
- const ScalarApiReference = require('@scalar/fastify-api-reference')
17
-
18
- async function loadVersions (app) {
19
- const configManager = app.platformatic.configManager
20
- const config = configManager.current
21
-
22
- const versions = config.versions ?? {}
23
- const versionsConfigs = versions.configs ?? []
24
-
25
- const latestVersionConfig = versionsConfigs.at(-1)
26
- const latestVersion = latestVersionConfig.version
27
- const latestVersionPrefix = latestVersionConfig.openapi.prefix ?? ''
28
-
29
- const latestVersionPlugin = fp(async function (app) {
30
- app.register(Swagger, {
31
- exposeRoute: true,
32
- openapi: {
33
- info: {
34
- title: 'Platformatic',
35
- description: 'This is a service built on top of Platformatic',
36
- version: latestVersion
37
- }
38
- },
39
- refResolver: {
40
- buildLocalReference (json, baseUri, fragment, i) {
41
- /* istanbul ignore next */
42
- return json.$id || `def-${i}`
43
- }
44
- }
45
- })
46
-
47
- app.get('/documentation/json', { schema: { hide: true } }, async () => app.swagger())
48
- app.get('/documentation/yaml', { schema: { hide: true } }, async () => app.swagger({ yaml: true }))
49
-
50
- app.register(ScalarApiReference, {
51
- logLevel: 'warn',
52
- routePrefix: '/documentation'
53
- })
54
-
55
- if (latestVersionConfig.plugins) {
56
- await app.register(require(wrapperPath), latestVersionConfig.plugins)
57
- }
58
- }, {
59
- name: latestVersion,
60
- encapsulate: true
61
- })
62
-
63
- await app.register(latestVersionPlugin, {
64
- prefix: latestVersionPrefix
65
- })
66
-
67
- const latestOpenapiSchemaPath = latestVersionConfig.openapi.path
68
- const latestOpenapiSchemaFile = await readFile(latestOpenapiSchemaPath, 'utf8')
69
- const latestOpenapiSchema = JSON.parse(latestOpenapiSchemaFile)
70
-
71
- let nextVersionPrefix = latestVersionPrefix
72
- let nextNormalizedOpenapiSchema = changeOpenapiSchemaPrefix(
73
- latestOpenapiSchema,
74
- latestVersionConfig.openapi.prefix,
75
- ''
76
- )
77
-
78
- for (let i = versionsConfigs.length - 2; i >= 0; i--) {
79
- const prevVersionConfig = versionsConfigs[i]
80
- const prevVersion = prevVersionConfig.version
81
- const prevVersionPrefix = prevVersionConfig.openapi.prefix ?? ''
82
- const prevOpenapiSchemaPath = prevVersionConfig.openapi.path
83
-
84
- const prevOpenapiSchemaFile = await readFile(prevOpenapiSchemaPath, 'utf8')
85
- const prevOpenapiSchema = JSON.parse(prevOpenapiSchemaFile)
86
-
87
- const prevNormalizedOpenapiSchema = changeOpenapiSchemaPrefix(
88
- prevOpenapiSchema,
89
- prevVersionConfig.openapi.prefix,
90
- ''
91
- )
92
-
93
- const schemaDiff = compareOpenApiSchemas(
94
- prevNormalizedOpenapiSchema,
95
- nextNormalizedOpenapiSchema
96
- )
97
-
98
- const versionPlugin = fp(async function (app) {
99
- app.register(Swagger, {
100
- exposeRoute: true,
101
- openapi: {
102
- info: {
103
- title: 'Platformatic',
104
- description: 'This is a service built on top of Platformatic',
105
- version: prevVersion
106
- }
107
- },
108
- refResolver: {
109
- buildLocalReference (json, baseUri, fragment, i) {
110
- /* istanbul ignore next */
111
- return json.$id || `def-${i}`
112
- }
113
- }
114
- })
115
-
116
- app.get('/documentation/json', { schema: { hide: true } }, async () => app.swagger())
117
- app.get('/documentation/yaml', { schema: { hide: true } }, async () => app.swagger({ yaml: true }))
118
-
119
- app.register(ScalarApiReference, {
120
- logLevel: 'warn',
121
- routePrefix: '/documentation'
122
- })
123
-
124
- const componentSchemas = prevOpenapiSchema.components?.schemas ?? {}
125
- for (const componentSchemaId of Object.keys(componentSchemas)) {
126
- const componentSchema = componentSchemas[componentSchemaId]
127
- app.addSchema({ $id: componentSchemaId, ...componentSchema })
128
- }
129
-
130
- if (prevVersionConfig.plugins) {
131
- await app.register(require(wrapperPath), prevVersionConfig.plugins)
132
- }
133
-
134
- for (const routeDiff of [...schemaDiff.deletedRoutes, ...schemaDiff.changedRoutes]) {
135
- const method = routeDiff.method.toUpperCase()
136
- const prevVersionPath = prevVersionPrefix + convertOpenApiToFastifyPath(routeDiff.path)
137
-
138
- const hasRouteMapper = app.hasRoute({ url: prevVersionPath, method })
139
- if (!hasRouteMapper) {
140
- app.log.warn(`Missing route ${method} "${prevVersionPath}" in the "${prevVersion}" API version`)
141
- }
142
- }
143
-
144
- const sameSchema = deepClone(prevNormalizedOpenapiSchema)
145
- for (const normalizedPath in sameSchema.paths ?? {}) {
146
- for (const method in sameSchema.paths[normalizedPath] ?? {}) {
147
- const prevVersionPath = prevVersionPrefix + convertOpenApiToFastifyPath(normalizedPath)
148
- const hasRouteMapper = app.hasRoute({
149
- url: prevVersionPath,
150
- method: method.toUpperCase()
151
- })
152
-
153
- const isSameRoute = schemaDiff.sameRoutes.find(
154
- routeDiff =>
155
- routeDiff.method === method.toLowerCase() &&
156
- routeDiff.path === normalizedPath
157
- )
158
-
159
- if (!isSameRoute || hasRouteMapper) {
160
- delete sameSchema.paths[normalizedPath][method]
161
- }
162
- }
163
- if (Object.keys(sameSchema.paths[normalizedPath]).length === 0) {
164
- delete sameSchema.paths[normalizedPath]
165
- }
166
- }
167
-
168
- if (Object.keys(sameSchema.paths).length > 0) {
169
- const versionPrefix = nextVersionPrefix
170
-
171
- await app.register(await import('fastify-openapi-glue'), {
172
- specification: sameSchema,
173
- operationResolver: (operationId, method) => {
174
- return {
175
- handler: async (req, reply) => {
176
- const prevVersionUrl = req.raw.url
177
- const nextVersionUrl = prevVersionUrl.replace(
178
- prevVersionPrefix,
179
- versionPrefix
180
- )
181
-
182
- const headers = req.headers
183
- delete headers.connection
184
- delete headers['content-length']
185
- delete headers['transfer-encoding']
186
-
187
- const res = await app.inject({
188
- method: method.toUpperCase(),
189
- url: nextVersionUrl,
190
- headers,
191
- payload: req.body
192
- })
193
-
194
- reply
195
- .code(res.statusCode)
196
- .headers(res.headers)
197
- .send(res.body)
198
- }
199
- }
200
- }
201
- })
202
- }
203
- }, {
204
- name: prevVersion,
205
- encapsulate: true
206
- })
207
-
208
- await app.register(versionPlugin, {
209
- prefix: prevVersionPrefix
210
- })
211
-
212
- nextVersionPrefix = prevVersionPrefix
213
- nextNormalizedOpenapiSchema = prevNormalizedOpenapiSchema
214
- }
215
- }
216
-
217
- module.exports = fp(loadVersions)