@platformatic/next 3.52.4 → 3.53.0

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 CHANGED
@@ -514,6 +514,10 @@ export interface PlatformaticNextJsConfig {
514
514
  additionalProperties?: never;
515
515
  [k: string]: unknown;
516
516
  };
517
+ /**
518
+ * Enable the OpenTelemetry diagnostic logger. Diagnostic messages are forwarded to the Platformatic global logger using the current logger level.
519
+ */
520
+ diagLogger?: boolean;
517
521
  };
518
522
  verticalScaler?: {
519
523
  enabled?: boolean;
@@ -1,13 +1,91 @@
1
1
  const { resolve } = require('node:path')
2
2
  const { fileURLToPath } = require('node:url')
3
- const fsPromises = require('node:fs').promises
4
- const { transformSync } = require('amaro')
3
+ const fs = require('node:fs')
4
+ const fsPromises = fs.promises
5
+ const generate = require('@babel/generator')
5
6
  const { parse } = require('@babel/parser')
6
7
  const traverse = require('@babel/traverse')
8
+ const {
9
+ blockStatement,
10
+ functionDeclaration,
11
+ identifier,
12
+ restElement,
13
+ returnStatement,
14
+ variableDeclaration,
15
+ variableDeclarator
16
+ } = require('@babel/types')
17
+ const { transformSync } = require('amaro')
7
18
 
8
19
  const originalReadFile = fsPromises.readFile
20
+ const originalReadFileSync = fs.readFileSync
9
21
  const targetFile = resolve(fileURLToPath(globalThis.platformatic.root), 'next.config.ts')
10
22
 
23
+ const originalId = '__pltEnhanceNextConfig'
24
+
25
+ function parseSingleExpression (expr) {
26
+ return parse(expr, { allowAwaitOutsideFunction: true }).program.body[0]
27
+ }
28
+
29
+ function createEvaluatorWrapperFunction (original) {
30
+ return functionDeclaration(
31
+ identifier(originalId),
32
+ [restElement(identifier('args'))],
33
+ blockStatement([
34
+ parseSingleExpression("const { enhanceNextConfig } = await import('@platformatic/next')"),
35
+ variableDeclaration('const', [variableDeclarator(identifier('original'), original)]),
36
+ parseSingleExpression('const enhanced = await enhanceNextConfig(original, ...args)'),
37
+ returnStatement(identifier('enhanced'))
38
+ ]),
39
+ false,
40
+ true
41
+ )
42
+ }
43
+
44
+ function transformCJS (source) {
45
+ const ast = parse(source.toString(), { sourceType: 'module' })
46
+
47
+ traverse.default(ast, {
48
+ AssignmentExpression (path) {
49
+ const { left, right } = path.node
50
+
51
+ if (left.object.name === 'module' && left.property.name === 'exports') {
52
+ path.node.right = createEvaluatorWrapperFunction(right)
53
+ path.skip()
54
+ }
55
+ }
56
+ })
57
+
58
+ return generate.default(ast).code
59
+ }
60
+
61
+ function transformESM (source) {
62
+ const ast = parse(source.toString(), { sourceType: 'module' })
63
+
64
+ traverse.default(ast, {
65
+ ExportDefaultDeclaration (path) {
66
+ const declaration = path.node.declaration
67
+
68
+ if (path.node.declaration.type === 'FunctionDeclaration') {
69
+ path.insertBefore(
70
+ functionDeclaration(
71
+ identifier(originalId + 'Function'),
72
+ declaration.params,
73
+ declaration.body,
74
+ declaration.generator,
75
+ declaration.async
76
+ )
77
+ )
78
+
79
+ path.node.declaration = createEvaluatorWrapperFunction(identifier(originalId + 'Function'))
80
+ } else {
81
+ path.node.declaration = createEvaluatorWrapperFunction(declaration)
82
+ }
83
+ }
84
+ })
85
+
86
+ return generate.default(ast).code
87
+ }
88
+
11
89
  function detectFormat (code) {
12
90
  let format = 'esm'
13
91
 
@@ -29,29 +107,69 @@ function detectFormat (code) {
29
107
  return format
30
108
  }
31
109
 
32
- fsPromises.readFile = async function readAndPatchNextConfigTS (url, options) {
33
- if (url.startsWith('file://')) {
34
- url = fileURLToPath(url)
110
+ function normalizePath (url) {
111
+ if (typeof url === 'string' && url.startsWith('file://')) {
112
+ return fileURLToPath(url)
35
113
  }
36
114
 
37
- const contents = await originalReadFile(url, options)
115
+ return url
116
+ }
38
117
 
39
- if (url !== targetFile) {
40
- return contents
41
- }
118
+ function restoreReadMethods () {
119
+ fsPromises.readFile = originalReadFile
120
+ fs.readFileSync = originalReadFileSync
121
+ }
42
122
 
123
+ async function patchNextConfigTS (contents) {
43
124
  let transformed = contents
44
125
 
45
126
  if (!globalThis.platformatic.config.next?.useExperimentalAdapter) {
46
127
  const { code } = transformSync(contents.toString('utf-8'), { mode: 'strip-only' })
47
-
48
- const { transformESM, transformCJS } = await import('./loader.js')
49
128
  const transformer = detectFormat(code) === 'esm' ? transformESM : transformCJS
50
129
  transformed = transformer(code)
51
130
 
52
- // Restore the original method
53
- fsPromises.readFile = originalReadFile
131
+ restoreReadMethods()
54
132
  }
55
133
 
56
134
  return transformed
57
135
  }
136
+
137
+ fsPromises.readFile = async function readAndPatchNextConfigTS (url, options) {
138
+ url = normalizePath(url)
139
+
140
+ const contents = await originalReadFile(url, options)
141
+
142
+ if (url !== targetFile) {
143
+ return contents
144
+ }
145
+
146
+ return patchNextConfigTS(contents)
147
+ }
148
+
149
+ // Next.js 16.2.3+ loads next.config.ts via next/dist/build/next-config-ts/transpile-config.js,
150
+ // which reads it synchronously before transpiling it.
151
+ fs.readFileSync = function readAndPatchNextConfigTSSync (url, options) {
152
+ url = normalizePath(url)
153
+
154
+ const contents = originalReadFileSync(url, options)
155
+
156
+ if (url !== targetFile) {
157
+ return contents
158
+ }
159
+
160
+ if (globalThis.platformatic.config.next?.useExperimentalAdapter) {
161
+ return contents
162
+ }
163
+
164
+ const { code } = transformSync(contents.toString('utf-8'), { mode: 'strip-only' })
165
+ const transformer = detectFormat(code) === 'esm' ? transformESM : transformCJS
166
+ const transformed = transformer(code)
167
+
168
+ restoreReadMethods()
169
+
170
+ if (typeof options === 'string' || options?.encoding) {
171
+ return transformed
172
+ }
173
+
174
+ return Buffer.from(transformed)
175
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/next",
3
- "version": "3.52.4",
3
+ "version": "3.53.0",
4
4
  "description": "Platformatic Next.js Capability",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -25,8 +25,8 @@
25
25
  "light-my-request": "^6.0.0",
26
26
  "msgpackr": "^1.11.2",
27
27
  "semver": "^7.6.3",
28
- "@platformatic/foundation": "3.52.4",
29
- "@platformatic/basic": "3.52.4"
28
+ "@platformatic/basic": "3.53.0",
29
+ "@platformatic/foundation": "3.53.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@fastify/reply-from": "^12.0.0",
@@ -43,8 +43,8 @@
43
43
  "next": "^16.1.0",
44
44
  "typescript": "^5.5.4",
45
45
  "ws": "^8.18.0",
46
- "@platformatic/gateway": "3.52.4",
47
- "@platformatic/service": "3.52.4"
46
+ "@platformatic/gateway": "3.53.0",
47
+ "@platformatic/service": "3.53.0"
48
48
  },
49
49
  "engines": {
50
50
  "node": ">=22.19.0"
package/schema.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://schemas.platformatic.dev/@platformatic/next/3.52.4.json",
2
+ "$id": "https://schemas.platformatic.dev/@platformatic/next/3.53.0.json",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
4
  "title": "Platformatic Next.js Config",
5
5
  "type": "object",
@@ -1916,6 +1916,10 @@
1916
1916
  }
1917
1917
  }
1918
1918
  ]
1919
+ },
1920
+ "diagLogger": {
1921
+ "type": "boolean",
1922
+ "description": "Enable the OpenTelemetry diagnostic logger. Diagnostic messages are forwarded to the Platformatic global logger using the current logger level."
1919
1923
  }
1920
1924
  },
1921
1925
  "required": [