@platformatic/next 3.33.0-alpha.1 → 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/lib/capability.js CHANGED
@@ -33,7 +33,7 @@ export class NextCapability extends BaseCapability {
33
33
  #child
34
34
  #server
35
35
  #configModified
36
- #isStandalone
36
+ #standaloneEntrypoint
37
37
 
38
38
  constructor (root, config, context) {
39
39
  super('next', version, root, config, context)
@@ -41,15 +41,43 @@ export class NextCapability extends BaseCapability {
41
41
  this.exitOnUnhandledErrors = false
42
42
  }
43
43
 
44
- async init () {
44
+ async init (building = false) {
45
45
  await super.init()
46
46
 
47
- if (this.isProduction && this.config.next?.standalone) {
48
- this.#isStandalone = true
47
+ // This is needed to avoid Next.js to throw an error when the lockfile is not correct
48
+ // and the user is using npm but has pnpm in its $PATH.
49
+ //
50
+ // See: https://github.com/platformatic/composer-next-node-fastify/pull/3
51
+ //
52
+ // PS by Paolo: Sob.
53
+ process.env.NEXT_IGNORE_INCORRECT_LOCKFILE = 'true'
54
+
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
+
62
+ const nextPackage = JSON.parse(await readFile(resolvePath(this.#next, 'package.json'), 'utf-8'))
63
+ this.#nextVersion = parse(nextPackage.version)
64
+
65
+ if (this.#nextVersion.major < 15 || (this.#nextVersion.major <= 15 && this.#nextVersion.minor < 1)) {
66
+ await import('./create-context-patch.js')
67
+ }
68
+
69
+ if (this.#nextVersion.major < 16 && this.config.next?.useExperimentalAdapter === true) {
70
+ this.config.next.useExperimentalAdapter = false
71
+ }
72
+
73
+ if (this.isProduction) {
49
74
  return
50
75
  }
51
76
 
52
- return this.#init()
77
+ /* c8 ignore next 3 */
78
+ if (!supportedVersions.some(v => satisfies(nextPackage.version, v))) {
79
+ throw new basicErrors.UnsupportedVersion('next', nextPackage.version, supportedVersions)
80
+ }
53
81
  }
54
82
 
55
83
  async start ({ listen }) {
@@ -107,10 +135,6 @@ export class NextCapability extends BaseCapability {
107
135
  }
108
136
 
109
137
  async build () {
110
- if (!this.#nextVersion) {
111
- await this.#init()
112
- }
113
-
114
138
  const config = this.config
115
139
  const loader = new URL('./loader.js', import.meta.url)
116
140
  this.#basePath = config.application?.basePath ? cleanBasePath(config.application?.basePath) : ''
@@ -118,7 +142,7 @@ export class NextCapability extends BaseCapability {
118
142
  let command = config.application.commands.build
119
143
 
120
144
  if (!command) {
121
- await this.init()
145
+ await this.init(true)
122
146
  command = ['node', resolvePath(this.#next, './dist/bin/next'), 'build', this.root]
123
147
  }
124
148
 
@@ -156,33 +180,6 @@ export class NextCapability extends BaseCapability {
156
180
  return context
157
181
  }
158
182
 
159
- async #init () {
160
- // This is needed to avoid Next.js to throw an error when the lockfile is not correct
161
- // and the user is using npm but has pnpm in its $PATH.
162
- //
163
- // See: https://github.com/platformatic/composer-next-node-fastify/pull/3
164
- //
165
- // PS by Paolo: Sob.
166
- process.env.NEXT_IGNORE_INCORRECT_LOCKFILE = 'true'
167
-
168
- this.#next = resolvePath(dirname(await resolvePackageViaCJS(this.root, 'next')), '../..')
169
- const nextPackage = JSON.parse(await readFile(resolvePath(this.#next, 'package.json'), 'utf-8'))
170
- this.#nextVersion = parse(nextPackage.version)
171
-
172
- if (this.#nextVersion.major < 15 || (this.#nextVersion.major <= 15 && this.#nextVersion.minor < 1)) {
173
- await import('./create-context-patch.js')
174
- }
175
-
176
- if (this.#nextVersion.major < 16 && this.config.next?.useExperimentalAdapter === true) {
177
- this.config.next.useExperimentalAdapter = false
178
- }
179
-
180
- /* c8 ignore next 3 */
181
- if (!supportedVersions.some(v => satisfies(nextPackage.version, v))) {
182
- throw new basicErrors.UnsupportedVersion('next', nextPackage.version, supportedVersions)
183
- }
184
- }
185
-
186
183
  async #startDevelopment () {
187
184
  const config = this.config
188
185
  const loaderUrl = new URL('./loader.js', import.meta.url)
@@ -264,7 +261,7 @@ export class NextCapability extends BaseCapability {
264
261
  this.#getChildManagerScripts()
265
262
  )
266
263
 
267
- if (this.#isStandalone) {
264
+ if (this.#standaloneEntrypoint) {
268
265
  return this.#startProductionStandaloneNext()
269
266
  } else {
270
267
  this.verifyOutputDirectory(resolvePath(this.root, '.next'))
@@ -310,25 +307,6 @@ export class NextCapability extends BaseCapability {
310
307
  }
311
308
 
312
309
  async #startProductionStandaloneNext () {
313
- // If built in standalone mode, the generated standalone directory is not on the root of the project but somewhere
314
- // inside .next/standalone due to turbopack limitations in determining the root of the project.
315
- // In that case we search a server.js next to a .next folder inside the .next /standalone folder.
316
- const serverEntrypoints = await Array.fromAsync(
317
- glob(['**/server.js'], { cwd: this.root, ignore: ['node_modules', '**/node_modules/**'] })
318
- )
319
-
320
- let serverEntrypoint
321
- for (const entrypoint of serverEntrypoints) {
322
- if (existsSync(resolvePath(this.root, dirname(entrypoint), '.next'))) {
323
- serverEntrypoint = resolvePath(this.root, entrypoint)
324
- break
325
- }
326
- }
327
-
328
- if (!serverEntrypoint) {
329
- throw new errors.StandaloneServerNotFound()
330
- }
331
-
332
310
  // The default Next.js standalone server uses chdir, which is not supported in worker threads.
333
311
  // Therefore we need to reproduce the server.js logic here, which what we do in the rest of this method.
334
312
 
@@ -336,7 +314,7 @@ export class NextCapability extends BaseCapability {
336
314
  // For now we use simple regex parsing, if it breaks, we can switch to proper AST parsing.
337
315
  let nextConfig
338
316
  try {
339
- const serverJsContent = await readFile(serverEntrypoint, 'utf-8')
317
+ const serverJsContent = await readFile(this.#standaloneEntrypoint, 'utf-8')
340
318
  const nextConfigMatch = serverJsContent.match(/(?:const|let)\s*nextConfig\s*=\s*(\{.+)/)
341
319
  nextConfig = JSON.parse(nextConfigMatch[1])
342
320
  } catch (e) {
@@ -378,10 +356,10 @@ export class NextCapability extends BaseCapability {
378
356
 
379
357
  // This is needed by Next.js standalone server to pick up the correct configuration
380
358
  process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
381
- const { startServer } = this.#requireStandaloneEntrypoint(serverEntrypoint)
359
+ const { startServer } = this.#requireStandaloneEntrypoint(this.#standaloneEntrypoint)
382
360
 
383
361
  await startServer({
384
- dir: dirname(serverEntrypoint),
362
+ dir: dirname(this.#standaloneEntrypoint),
385
363
  isDev: false,
386
364
  config: nextConfig,
387
365
  hostname: serverOptions.hostname,
@@ -462,6 +440,34 @@ export class NextCapability extends BaseCapability {
462
440
  return distDir
463
441
  }
464
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
+
465
471
  #requireStandaloneEntrypoint (serverEntrypoint) {
466
472
  let serverModule
467
473
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/next",
3
- "version": "3.33.0-alpha.1",
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.33.0-alpha.1",
27
- "@platformatic/foundation": "3.33.0-alpha.1"
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.33.0-alpha.1",
44
- "@platformatic/service": "3.33.0-alpha.1"
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.33.0-alpha.1.json",
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",