@platformatic/next 3.32.0 → 3.33.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.
- package/config.d.ts +1 -0
- package/lib/capability.js +61 -34
- package/lib/schema.js +3 -0
- package/package.json +5 -5
- package/schema.json +4 -1
package/config.d.ts
CHANGED
package/lib/capability.js
CHANGED
|
@@ -13,6 +13,7 @@ import { ChildProcess } from 'node:child_process'
|
|
|
13
13
|
import { once } from 'node:events'
|
|
14
14
|
import { existsSync } from 'node:fs'
|
|
15
15
|
import { glob, readFile, writeFile } from 'node:fs/promises'
|
|
16
|
+
import { createRequire } from 'node:module'
|
|
16
17
|
import { dirname, resolve as resolvePath, sep } from 'node:path'
|
|
17
18
|
import { fileURLToPath } from 'node:url'
|
|
18
19
|
import { parse, satisfies } from 'semver'
|
|
@@ -32,6 +33,7 @@ export class NextCapability extends BaseCapability {
|
|
|
32
33
|
#child
|
|
33
34
|
#server
|
|
34
35
|
#configModified
|
|
36
|
+
#standaloneEntrypoint
|
|
35
37
|
|
|
36
38
|
constructor (root, config, context) {
|
|
37
39
|
super('next', version, root, config, context)
|
|
@@ -39,7 +41,7 @@ export class NextCapability extends BaseCapability {
|
|
|
39
41
|
this.exitOnUnhandledErrors = false
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
async init () {
|
|
44
|
+
async init (building = false) {
|
|
43
45
|
await super.init()
|
|
44
46
|
|
|
45
47
|
// This is needed to avoid Next.js to throw an error when the lockfile is not correct
|
|
@@ -50,7 +52,13 @@ export class NextCapability extends BaseCapability {
|
|
|
50
52
|
// PS by Paolo: Sob.
|
|
51
53
|
process.env.NEXT_IGNORE_INCORRECT_LOCKFILE = 'true'
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
if (!building && this.isProduction && this.config.next?.standalone) {
|
|
56
|
+
this.#standaloneEntrypoint = await this.#resolveStandaloneEntrypoint()
|
|
57
|
+
this.#next = resolvePath(dirname(await resolvePackageViaCJS(this.#standaloneEntrypoint, 'next')), '../..')
|
|
58
|
+
} else {
|
|
59
|
+
this.#next = resolvePath(dirname(await resolvePackageViaCJS(this.root, 'next')), '../..')
|
|
60
|
+
}
|
|
61
|
+
|
|
54
62
|
const nextPackage = JSON.parse(await readFile(resolvePath(this.#next, 'package.json'), 'utf-8'))
|
|
55
63
|
this.#nextVersion = parse(nextPackage.version)
|
|
56
64
|
|
|
@@ -62,6 +70,10 @@ export class NextCapability extends BaseCapability {
|
|
|
62
70
|
this.config.next.useExperimentalAdapter = false
|
|
63
71
|
}
|
|
64
72
|
|
|
73
|
+
if (this.isProduction) {
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
|
|
65
77
|
/* c8 ignore next 3 */
|
|
66
78
|
if (!supportedVersions.some(v => satisfies(nextPackage.version, v))) {
|
|
67
79
|
throw new basicErrors.UnsupportedVersion('next', nextPackage.version, supportedVersions)
|
|
@@ -123,10 +135,6 @@ export class NextCapability extends BaseCapability {
|
|
|
123
135
|
}
|
|
124
136
|
|
|
125
137
|
async build () {
|
|
126
|
-
if (!this.#nextVersion) {
|
|
127
|
-
await this.init()
|
|
128
|
-
}
|
|
129
|
-
|
|
130
138
|
const config = this.config
|
|
131
139
|
const loader = new URL('./loader.js', import.meta.url)
|
|
132
140
|
this.#basePath = config.application?.basePath ? cleanBasePath(config.application?.basePath) : ''
|
|
@@ -134,7 +142,7 @@ export class NextCapability extends BaseCapability {
|
|
|
134
142
|
let command = config.application.commands.build
|
|
135
143
|
|
|
136
144
|
if (!command) {
|
|
137
|
-
await this.init()
|
|
145
|
+
await this.init(true)
|
|
138
146
|
command = ['node', resolvePath(this.#next, './dist/bin/next'), 'build', this.root]
|
|
139
147
|
}
|
|
140
148
|
|
|
@@ -253,11 +261,10 @@ export class NextCapability extends BaseCapability {
|
|
|
253
261
|
this.#getChildManagerScripts()
|
|
254
262
|
)
|
|
255
263
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
if (existsSync(resolvePath(this.root, '.next/standalone'))) {
|
|
264
|
+
if (this.#standaloneEntrypoint) {
|
|
259
265
|
return this.#startProductionStandaloneNext()
|
|
260
266
|
} else {
|
|
267
|
+
this.verifyOutputDirectory(resolvePath(this.root, '.next'))
|
|
261
268
|
return this.#startProductionNext()
|
|
262
269
|
}
|
|
263
270
|
}
|
|
@@ -300,27 +307,6 @@ export class NextCapability extends BaseCapability {
|
|
|
300
307
|
}
|
|
301
308
|
|
|
302
309
|
async #startProductionStandaloneNext () {
|
|
303
|
-
const rootDir = resolvePath(this.root, '.next', 'standalone')
|
|
304
|
-
|
|
305
|
-
// If built in standalone mode, the generated standalone directory is not on the root of the project but somewhere
|
|
306
|
-
// inside .next/standalone due to turbopack limitations in determining the root of the project.
|
|
307
|
-
// In that case we search a server.js next to a .next folder inside the .next /standalone folder.
|
|
308
|
-
const serverEntrypoints = await Array.fromAsync(
|
|
309
|
-
glob(['**/server.js'], { cwd: rootDir, ignore: ['node_modules', '**/node_modules/**'] })
|
|
310
|
-
)
|
|
311
|
-
|
|
312
|
-
let serverEntrypoint
|
|
313
|
-
for (const entrypoint of serverEntrypoints) {
|
|
314
|
-
if (existsSync(resolvePath(rootDir, dirname(entrypoint), '.next'))) {
|
|
315
|
-
serverEntrypoint = resolvePath(rootDir, entrypoint)
|
|
316
|
-
break
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
if (!serverEntrypoint) {
|
|
321
|
-
throw new errors.StandaloneServerNotFound()
|
|
322
|
-
}
|
|
323
|
-
|
|
324
310
|
// The default Next.js standalone server uses chdir, which is not supported in worker threads.
|
|
325
311
|
// Therefore we need to reproduce the server.js logic here, which what we do in the rest of this method.
|
|
326
312
|
|
|
@@ -328,7 +314,7 @@ export class NextCapability extends BaseCapability {
|
|
|
328
314
|
// For now we use simple regex parsing, if it breaks, we can switch to proper AST parsing.
|
|
329
315
|
let nextConfig
|
|
330
316
|
try {
|
|
331
|
-
const serverJsContent = await readFile(
|
|
317
|
+
const serverJsContent = await readFile(this.#standaloneEntrypoint, 'utf-8')
|
|
332
318
|
const nextConfigMatch = serverJsContent.match(/(?:const|let)\s*nextConfig\s*=\s*(\{.+)/)
|
|
333
319
|
nextConfig = JSON.parse(nextConfigMatch[1])
|
|
334
320
|
} catch (e) {
|
|
@@ -370,10 +356,10 @@ export class NextCapability extends BaseCapability {
|
|
|
370
356
|
|
|
371
357
|
// This is needed by Next.js standalone server to pick up the correct configuration
|
|
372
358
|
process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
|
|
373
|
-
const { startServer } =
|
|
359
|
+
const { startServer } = this.#requireStandaloneEntrypoint(this.#standaloneEntrypoint)
|
|
374
360
|
|
|
375
361
|
await startServer({
|
|
376
|
-
dir: dirname(
|
|
362
|
+
dir: dirname(this.#standaloneEntrypoint),
|
|
377
363
|
isDev: false,
|
|
378
364
|
config: nextConfig,
|
|
379
365
|
hostname: serverOptions.hostname,
|
|
@@ -450,6 +436,47 @@ export class NextCapability extends BaseCapability {
|
|
|
450
436
|
await writeFile(requiredServerFilesPath, JSON.stringify(requiredServerFiles, null, 2))
|
|
451
437
|
}
|
|
452
438
|
}
|
|
439
|
+
|
|
453
440
|
return distDir
|
|
454
441
|
}
|
|
442
|
+
|
|
443
|
+
async #resolveStandaloneEntrypoint () {
|
|
444
|
+
// If built in standalone mode, the generated standalone directory is not on the root of the project but somewhere
|
|
445
|
+
// inside .next/standalone due to turbopack limitations in determining the root of the project.
|
|
446
|
+
// In that case we search a server.js next to a .next folder inside the .next /standalone folder.
|
|
447
|
+
const serverEntrypoints = await Array.fromAsync(
|
|
448
|
+
glob(['**/server.js'], { cwd: this.root, ignore: ['node_modules', '**/node_modules/**'] })
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
let serverEntrypoint
|
|
452
|
+
for (const entrypoint of serverEntrypoints) {
|
|
453
|
+
if (existsSync(resolvePath(this.root, dirname(entrypoint), '.next'))) {
|
|
454
|
+
const candidate = resolvePath(this.root, entrypoint)
|
|
455
|
+
const contents = await readFile(candidate, 'utf-8')
|
|
456
|
+
|
|
457
|
+
if (contents.includes('process.env.__NEXT_PRIVATE_STANDALONE_CONFIG =')) {
|
|
458
|
+
serverEntrypoint = candidate
|
|
459
|
+
break
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
if (!serverEntrypoint) {
|
|
465
|
+
throw new errors.StandaloneServerNotFound()
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return serverEntrypoint
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
#requireStandaloneEntrypoint (serverEntrypoint) {
|
|
472
|
+
let serverModule
|
|
473
|
+
|
|
474
|
+
try {
|
|
475
|
+
serverModule = createRequire(serverEntrypoint)('next/dist/server/lib/start-server.js')
|
|
476
|
+
} catch (e) { // Fallback to bundled capability
|
|
477
|
+
serverModule = createRequire(import.meta.file)('next/dist/server/lib/start-server.js')
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
return serverModule.default ?? serverModule
|
|
481
|
+
}
|
|
455
482
|
}
|
package/lib/schema.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/next",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.33.0-alpha.2",
|
|
4
4
|
"description": "Platformatic Next.js Capability",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"iovalkey": "^0.3.0",
|
|
24
24
|
"msgpackr": "^1.11.2",
|
|
25
25
|
"semver": "^7.6.3",
|
|
26
|
-
"@platformatic/basic": "3.
|
|
27
|
-
"@platformatic/foundation": "3.
|
|
26
|
+
"@platformatic/basic": "3.33.0-alpha.2",
|
|
27
|
+
"@platformatic/foundation": "3.33.0-alpha.2"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@fastify/reply-from": "^12.0.0",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"next": "^16.0.0",
|
|
41
41
|
"typescript": "^5.5.4",
|
|
42
42
|
"ws": "^8.18.0",
|
|
43
|
-
"@platformatic/gateway": "3.
|
|
44
|
-
"@platformatic/service": "3.
|
|
43
|
+
"@platformatic/gateway": "3.33.0-alpha.2",
|
|
44
|
+
"@platformatic/service": "3.33.0-alpha.2"
|
|
45
45
|
},
|
|
46
46
|
"engines": {
|
|
47
47
|
"node": ">=22.19.0"
|
package/schema.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://schemas.platformatic.dev/@platformatic/next/3.
|
|
2
|
+
"$id": "https://schemas.platformatic.dev/@platformatic/next/3.33.0-alpha.2.json",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
4
|
"title": "Platformatic Next.js Config",
|
|
5
5
|
"type": "object",
|
|
@@ -2316,6 +2316,9 @@
|
|
|
2316
2316
|
"next": {
|
|
2317
2317
|
"type": "object",
|
|
2318
2318
|
"properties": {
|
|
2319
|
+
"standalone": {
|
|
2320
|
+
"type": "boolean"
|
|
2321
|
+
},
|
|
2319
2322
|
"trailingSlash": {
|
|
2320
2323
|
"type": "boolean",
|
|
2321
2324
|
"default": false
|