@platformatic/vite 3.4.1 → 3.5.1

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/index.js CHANGED
@@ -1,416 +1,16 @@
1
- import fastifyStatic from '@fastify/static'
2
- import {
3
- BaseStackable,
4
- transformConfig as basicTransformConfig,
5
- cleanBasePath,
6
- createServerListener,
7
- ensureTrailingSlash,
8
- errors,
9
- getServerUrl,
10
- importFile,
11
- resolvePackage,
12
- schemaOptions
13
- } from '@platformatic/basic'
14
- import { ConfigManager } from '@platformatic/config'
15
- import { NodeStackable } from '@platformatic/node'
16
- import fastify from 'fastify'
17
- import { existsSync } from 'node:fs'
18
- import { readFile, writeFile } from 'node:fs/promises'
19
- import { dirname, resolve } from 'node:path'
20
- import { pathToFileURL } from 'node:url'
21
- import { satisfies } from 'semver'
22
- import { packageJson, schema } from './lib/schema.js'
1
+ import { transform as basicTransform, resolve, validationOptions } from '@platformatic/basic'
2
+ import { kMetadata, loadConfiguration as utilsLoadConfiguration } from '@platformatic/foundation'
3
+ import { ViteCapability, ViteSSRCapability } from './lib/capability.js'
4
+ import { schema } from './lib/schema.js'
23
5
 
24
- const supportedVersions = '^5.0.0'
6
+ /* c8 ignore next 5 */
7
+ export async function transform (config, schema, options) {
8
+ config = await basicTransform(config, schema, options)
25
9
 
26
- export class ViteStackable extends BaseStackable {
27
- #vite
28
- #app
29
- #server
30
- #basePath
10
+ config.watch = { enabled: false }
31
11
 
32
- constructor (options, root, configManager) {
33
- super('vite', packageJson.version, options, root, configManager)
34
- }
35
-
36
- async init () {
37
- this.#vite = dirname(resolvePackage(this.root, 'vite'))
38
- const vitePackage = JSON.parse(await readFile(resolve(this.#vite, 'package.json'), 'utf-8'))
39
-
40
- /* c8 ignore next 3 */
41
- if (!satisfies(vitePackage.version, supportedVersions)) {
42
- throw new errors.UnsupportedVersion('vite', vitePackage.version, supportedVersions)
43
- }
44
- }
45
-
46
- async start ({ listen }) {
47
- // Make this idempotent
48
- if (this.url) {
49
- return this.url
50
- }
51
-
52
- if (this.isProduction) {
53
- await this.#startProduction(listen)
54
- } else {
55
- await this.#startDevelopment(listen)
56
- }
57
- }
58
-
59
- async stop () {
60
- if (this.subprocess) {
61
- return this.stopCommand()
62
- }
63
-
64
- return this.#app.close()
65
- }
66
-
67
- async build () {
68
- const config = this.configManager.current
69
- const command = config.application.commands.build
70
- const configFile = config.vite.configFile ? resolve(this.root, config.vite.configFile) : undefined
71
- let basePath = config.application?.basePath
72
- ? ensureTrailingSlash(cleanBasePath(config.application?.basePath))
73
- : undefined
74
- let outDir
75
-
76
- if (command) {
77
- return this.buildWithCommand(command, basePath)
78
- }
79
-
80
- await this.init()
81
- const { build } = await importFile(resolve(this.#vite, 'dist/node/index.js'))
82
-
83
- await build({
84
- root: this.root,
85
- base: basePath,
86
- mode: 'production',
87
- configFile,
88
- logLevel: this.logger.level,
89
- build: {
90
- outDir: config.application.outputDirectory
91
- },
92
- plugins: [
93
- {
94
- name: 'platformatic-build',
95
- configResolved: config => {
96
- basePath = ensureTrailingSlash(cleanBasePath(config.base))
97
- outDir = resolve(this.root, config.build.outDir)
98
- }
99
- }
100
- ]
101
- })
102
-
103
- await writeFile(resolve(outDir, '.platformatic-build.json'), JSON.stringify({ basePath }), 'utf-8')
104
- }
105
-
106
- /* c8 ignore next 5 */
107
- async getWatchConfig () {
108
- return {
109
- enabled: false
110
- }
111
- }
112
-
113
- // This is only used in production mode
114
- async inject (injectParams, onInject) {
115
- const res = await this.#app.inject(injectParams, onInject)
116
-
117
- /* c8 ignore next 3 */
118
- if (onInject) {
119
- return
120
- }
121
-
122
- // Since inject might be called from the main thread directly via ITC, let's clean it up
123
- const { statusCode, headers, body, payload, rawPayload } = res
124
- return { statusCode, headers, body, payload, rawPayload }
125
- }
126
-
127
- getMeta () {
128
- const config = this.subprocessConfig ?? this.#app?.config
129
-
130
- const composer = {
131
- tcp: typeof this.url !== 'undefined',
132
- url: this.url,
133
- prefix: this.basePath ?? config?.base ?? this.#basePath,
134
- wantsAbsoluteUrls: true,
135
- needsRootRedirect: true
136
- }
137
-
138
- return { composer }
139
- }
140
-
141
- _getVite () {
142
- return this.#app
143
- }
144
-
145
- async #startDevelopment () {
146
- const config = this.configManager.current
147
- const command = this.configManager.current.application.commands.development
148
-
149
- this.#basePath = config.application?.basePath
150
- ? ensureTrailingSlash(cleanBasePath(config.application?.basePath))
151
- : undefined
152
-
153
- this.registerGlobals({
154
- id: this.id,
155
- // Always use URL to avoid serialization problem in Windows
156
- root: pathToFileURL(this.root).toString(),
157
- basePath: this.#basePath,
158
- logLevel: this.logger.level
159
- })
160
-
161
- if (command) {
162
- return this.startWithCommand(command)
163
- }
164
-
165
- // Prepare options
166
- const { hostname, port, https, cors } = this.serverConfig ?? {}
167
- const configFile = config.vite.configFile ? resolve(this.root, config.vite.configFile) : undefined
168
-
169
- const serverOptions = {
170
- host: hostname || '127.0.0.1',
171
- port: port || 0,
172
- strictPort: false,
173
- https,
174
- cors,
175
- origin: 'http://localhost',
176
- hmr: true,
177
- fs: {
178
- strict: config.vite.devServer.strict
179
- }
180
- }
181
-
182
- // Require Vite
183
- const serverPromise = createServerListener(
184
- (this.isEntrypoint ? serverOptions?.port : undefined) ?? true,
185
- (this.isEntrypoint ? serverOptions?.hostname : undefined) ?? true
186
- )
187
- const { createServer } = await importFile(resolve(this.#vite, 'dist/node/index.js'))
188
-
189
- // Create the server and listen
190
- this.#app = await createServer({
191
- root: this.root,
192
- base: this.#basePath,
193
- mode: 'development',
194
- configFile,
195
- logLevel: this.logger.level,
196
- clearScreen: false,
197
- optimizeDeps: { force: false },
198
- server: serverOptions
199
- })
200
-
201
- await this.#app.listen()
202
- this.#server = await serverPromise
203
- this.url = getServerUrl(this.#server)
204
- }
205
-
206
- async #startProduction (listen) {
207
- const config = this.configManager.current
208
- const command = this.configManager.current.application.commands.production
209
-
210
- this.#basePath = config.application?.basePath
211
- ? ensureTrailingSlash(cleanBasePath(config.application?.basePath))
212
- : undefined
213
-
214
- this.registerGlobals({
215
- id: this.id,
216
- // Always use URL to avoid serialization problem in Windows
217
- root: pathToFileURL(this.root).toString(),
218
- basePath: this.#basePath,
219
- logLevel: this.logger.level
220
- })
221
- if (command) {
222
- return this.startWithCommand(command)
223
- }
224
-
225
- if (this.#app && listen) {
226
- const serverOptions = this.serverConfig
227
- await this.#app.listen({ host: serverOptions?.hostname || '127.0.0.1', port: serverOptions?.port || 0 })
228
- this.url = getServerUrl(this.#app.server)
229
- return this.url
230
- }
231
-
232
- this.#app = fastify({ logger: { level: 'info' } })
233
-
234
- const outputDirectory = resolve(this.root, config.application.outputDirectory)
235
- this.verifyOutputDirectory(outputDirectory)
236
- const buildInfoPath = resolve(outputDirectory, '.platformatic-build.json')
237
-
238
- if (!this.#basePath && existsSync(buildInfoPath)) {
239
- try {
240
- const buildInfo = JSON.parse(await readFile(buildInfoPath, 'utf-8'))
241
- this.#basePath = buildInfo.basePath
242
- } catch (e) {
243
- console.log(e)
244
- }
245
- }
246
-
247
- await this.#app.register(fastifyStatic, {
248
- root: outputDirectory,
249
- prefix: this.#basePath,
250
- prefixAvoidTrailingSlash: true,
251
- schemaHide: true
252
- })
253
-
254
- await this.#app.ready()
255
- }
256
- }
257
-
258
- export class ViteSSRStackable extends NodeStackable {
259
- #basePath
260
-
261
- constructor (options, root, configManager) {
262
- super(options, root, configManager)
263
-
264
- this.type = 'vite'
265
- }
266
-
267
- _getWantsAbsoluteUrls () {
268
- return true
269
- }
270
-
271
- async init () {
272
- const config = this.configManager.current
273
-
274
- this.#basePath = config.application?.basePath
275
- ? ensureTrailingSlash(cleanBasePath(config.application?.basePath))
276
- : undefined
277
-
278
- this.registerGlobals({
279
- id: this.id,
280
- // Always use URL to avoid serialization problem in Windows
281
- root: pathToFileURL(this.root).toString(),
282
- basePath: this.#basePath,
283
- logLevel: this.logger.level
284
- })
285
- }
286
-
287
- async start ({ listen }) {
288
- // Make this idempotent
289
- /* c8 ignore next 3 */
290
- if (this.url) {
291
- return this.url
292
- }
293
-
294
- const config = this.configManager.current
295
- const command = config.application.commands[this.isProduction ? 'production' : 'development']
296
-
297
- if (command) {
298
- return this.startWithCommand(command)
299
- }
300
-
301
- if (this.isProduction) {
302
- const clientDirectory = config.vite.ssr.clientDirectory
303
- const clientOutDir = resolve(this.root, clientDirectory, config.application.outputDirectory, clientDirectory)
304
-
305
- this.verifyOutputDirectory(clientOutDir)
306
-
307
- const buildInfoPath = resolve(clientOutDir, '.platformatic-build.json')
308
- if (!this.#basePath && existsSync(buildInfoPath)) {
309
- try {
310
- const buildInfo = JSON.parse(await readFile(buildInfoPath, 'utf-8'))
311
- this.#basePath = buildInfo.basePath
312
- } catch (e) {
313
- console.log(e)
314
- }
315
- }
316
- }
317
-
318
- await super.start({ listen })
319
- await super._listen()
320
- }
321
-
322
- async build () {
323
- const config = this.configManager.current
324
- const command = config.application.commands.build
325
- const configFile = config.vite.configFile ? resolve(this.root, config.vite.configFile) : undefined
326
- let basePath = config.application?.basePath
327
- ? ensureTrailingSlash(cleanBasePath(config.application?.basePath))
328
- : undefined
329
-
330
- if (command) {
331
- return this.buildWithCommand(command, basePath)
332
- }
333
-
334
- const clientDirectory = config.vite.ssr.clientDirectory
335
- const serverDirectory = config.vite.ssr.serverDirectory
336
- let clientOutDir = resolve(this.root, clientDirectory, config.application.outputDirectory, clientDirectory)
337
-
338
- await this.init()
339
- const vite = dirname(resolvePackage(this.root, 'vite'))
340
- const { build } = await importFile(resolve(vite, 'dist/node/index.js'))
341
-
342
- // Build the client
343
- await build({
344
- root: resolve(this.root, clientDirectory),
345
- base: basePath,
346
- mode: 'production',
347
- configFile,
348
- logLevel: this.logger.level,
349
- build: {
350
- outDir: clientOutDir,
351
- ssrManifest: true
352
- },
353
- plugins: [
354
- {
355
- name: 'platformatic-build',
356
- configResolved: config => {
357
- basePath = ensureTrailingSlash(cleanBasePath(config.base))
358
- clientOutDir = resolve(this.root, clientDirectory, config.build.outDir)
359
- }
360
- }
361
- ]
362
- })
363
-
364
- await writeFile(resolve(clientOutDir, '.platformatic-build.json'), JSON.stringify({ basePath }), 'utf-8')
365
-
366
- // Build the server
367
- await build({
368
- root: this.root,
369
- base: basePath,
370
- mode: 'production',
371
- configFile,
372
- logLevel: this.logger.level,
373
- build: {
374
- outDir: resolve(this.root, clientDirectory, config.application.outputDirectory, serverDirectory),
375
- ssr: resolve(this.root, clientDirectory, 'index.js')
376
- }
377
- })
378
- }
379
-
380
- getMeta () {
381
- const vite = this._getApplication()?.vite
382
- const config = vite?.devServer?.config ?? vite?.config.vite
383
- const applicationBasePath = config?.base
384
-
385
- const composer = {
386
- tcp: typeof this.url !== 'undefined',
387
- url: this.url,
388
- prefix: this.basePath ?? applicationBasePath ?? this.#basePath,
389
- wantsAbsoluteUrls: true,
390
- needsRootRedirect: true
391
- }
392
-
393
- return { composer }
394
- }
395
-
396
- _findEntrypoint () {
397
- const config = this.configManager.current.vite ?? {}
398
- return resolve(this.root, config.ssr.entrypoint)
399
- }
400
- }
401
-
402
- /* c8 ignore next 9 */
403
- export function transformConfig () {
404
- if (this.current.watch === undefined) {
405
- this.current.watch = { enabled: false }
406
- }
407
-
408
- if (typeof this.current.watch !== 'object') {
409
- this.current.watch = { enabled: this.current.watch || false }
410
- }
411
-
412
- if (this.current.vite.ssr === true) {
413
- this.current.vite.ssr = {
12
+ if (config.vite.ssr === true) {
13
+ config.vite.ssr = {
414
14
  enabled: true,
415
15
  entrypoint: 'server.js',
416
16
  clientDirectory: 'client',
@@ -418,40 +18,28 @@ export function transformConfig () {
418
18
  }
419
19
  }
420
20
 
421
- basicTransformConfig.call(this)
21
+ return config
422
22
  }
423
23
 
424
- export async function buildStackable (opts) {
425
- const root = opts.context.directory
24
+ export async function loadConfiguration (configOrRoot, sourceOrConfig, context) {
25
+ const { root, source } = await resolve(configOrRoot, sourceOrConfig, 'application')
426
26
 
427
- const configManager = new ConfigManager({
428
- schema,
429
- source: opts.config ?? {},
430
- schemaOptions,
431
- transformConfig,
432
- dirname: root
27
+ return utilsLoadConfiguration(source, context?.schema ?? schema, {
28
+ validationOptions,
29
+ transform,
30
+ replaceEnv: true,
31
+ root,
32
+ ...context
433
33
  })
434
- await configManager.parseAndValidate()
435
-
436
- // When in SSR mode, we use ViteSSRStackable, which is a subclass of @platformatic/node
437
- const viteConfig = configManager.current.vite ?? {}
438
-
439
- if (viteConfig.ssr?.enabled) {
440
- return new ViteSSRStackable(opts, root, configManager)
441
- }
442
-
443
- return new ViteStackable(opts, root, configManager)
444
34
  }
445
35
 
446
- export { schema, schemaComponents } from './lib/schema.js'
36
+ export async function create (configOrRoot, sourceOrConfig, context) {
37
+ const config = await loadConfiguration(configOrRoot, sourceOrConfig, context)
447
38
 
448
- export default {
449
- configType: 'vite',
450
- configManagerConfig: {
451
- schemaOptions,
452
- transformConfig
453
- },
454
- buildStackable,
455
- schema,
456
- version: packageJson.version
39
+ // When in SSR mode, we use ViteSSRCapability, which is a subclass of @platformatic/node
40
+ const Capability = config.vite?.ssr?.enabled ? ViteSSRCapability : ViteCapability
41
+ return new Capability(config[kMetadata].root, config, context)
457
42
  }
43
+
44
+ export * from './lib/capability.js'
45
+ export { packageJson, schema, schemaComponents, version } from './lib/schema.js'