@platformatic/next 3.71.1-alpha.0 → 3.73.0-alpha.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/eslint.config.js +5 -3
- package/lib/caching/valkey-common.js +54 -4
- package/lib/caching/valkey-components-remote.js +2 -1
- package/lib/caching/valkey-components.js +86 -7
- package/lib/caching/valkey-isr.js +22 -0
- package/lib/capability.js +6 -3
- package/lib/loader.js +37 -4
- package/package.json +11 -11
- package/schema.json +1 -1
package/eslint.config.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { globalIgnores } from 'eslint/config'
|
|
1
2
|
import neostandard from 'neostandard'
|
|
2
3
|
|
|
3
|
-
export default
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
export default [
|
|
5
|
+
...neostandard(),
|
|
6
|
+
globalIgnores(['**/.next', '**/dist', '**/tmp', 'test/fixtures/**'])
|
|
7
|
+
]
|
|
@@ -7,9 +7,11 @@ import {
|
|
|
7
7
|
getRoot,
|
|
8
8
|
getValkeyClients,
|
|
9
9
|
getWorkerId,
|
|
10
|
+
isBuilding,
|
|
10
11
|
updateGlobals
|
|
11
12
|
} from '@platformatic/globals'
|
|
12
13
|
import { existsSync, readFileSync } from 'node:fs'
|
|
14
|
+
import { readFile } from 'node:fs/promises'
|
|
13
15
|
import { createRequire } from 'node:module'
|
|
14
16
|
import { hostname } from 'node:os'
|
|
15
17
|
import { resolve } from 'node:path'
|
|
@@ -112,12 +114,60 @@ export function createPlatformaticLogger () {
|
|
|
112
114
|
return pino(pinoOptions)
|
|
113
115
|
}
|
|
114
116
|
|
|
117
|
+
// The subprefix is the build ID. During a build it is null until Next.js writes the ID,
|
|
118
|
+
// so that nothing is stored under a subprefix the application will never read.
|
|
115
119
|
export function getPlatformaticSubprefix () {
|
|
116
|
-
const
|
|
120
|
+
const buildIdPath = resolve(fileURLToPath(getRoot()), '.next/BUILD_ID')
|
|
117
121
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
if (existsSync(buildIdPath)) {
|
|
123
|
+
return readFileSync(buildIdPath, 'utf-8').trim()
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return isBuilding({ throwOnMissing: false }) ? null : 'development'
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Maps each "use cache" function ID to the file defining it, relative to the application.
|
|
130
|
+
export async function loadCacheFunctionsFiles () {
|
|
131
|
+
const nextDir = resolve(fileURLToPath(getRoot()), '.next')
|
|
132
|
+
const files = new Map()
|
|
133
|
+
|
|
134
|
+
const [manifest, serverFiles] = await Promise.all([
|
|
135
|
+
readJSON(resolve(nextDir, 'server/server-reference-manifest.json')),
|
|
136
|
+
readJSON(resolve(nextDir, 'required-server-files.json'))
|
|
137
|
+
])
|
|
138
|
+
|
|
139
|
+
if (!manifest || !serverFiles) {
|
|
140
|
+
return files
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Turbopack reports files relative to the workspace root, which can contain the application
|
|
144
|
+
const appPrefix = serverFiles.relativeAppDir ? serverFiles.relativeAppDir + '/' : ''
|
|
145
|
+
|
|
146
|
+
for (const [id, { filename }] of Object.entries(manifest.node ?? {})) {
|
|
147
|
+
if (filename) {
|
|
148
|
+
files.set(id, filename.startsWith(appPrefix) ? filename.slice(appPrefix.length) : filename)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return files
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Returns null when the file does not exist, like in development.
|
|
156
|
+
async function readJSON (path) {
|
|
157
|
+
try {
|
|
158
|
+
return JSON.parse(await readFile(path, 'utf-8'))
|
|
159
|
+
} catch (e) {
|
|
160
|
+
if (e.code === 'ENOENT') {
|
|
161
|
+
return null
|
|
162
|
+
}
|
|
163
|
+
throw e
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// The cache key is the React-encoded list of the function ID, its arguments and other parts.
|
|
168
|
+
// The ID, a 42 characters hexadecimal string, is the first one of its kind in the key.
|
|
169
|
+
export function getCacheFunctionId (cacheKey) {
|
|
170
|
+
return cacheKey.match(/"([0-9a-f]{42})"/)?.[1]
|
|
121
171
|
}
|
|
122
172
|
|
|
123
173
|
export function getPlatformaticMeta () {
|
|
@@ -11,7 +11,8 @@ export const CACHE_MISS_METRIC = {
|
|
|
11
11
|
|
|
12
12
|
export const sections = {
|
|
13
13
|
values: 'remote:components:values',
|
|
14
|
-
tags: 'remote:components:tags'
|
|
14
|
+
tags: 'remote:components:tags',
|
|
15
|
+
revalidations: 'remote:components:revalidations'
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export default new CacheHandler({
|
|
@@ -6,10 +6,12 @@ import {
|
|
|
6
6
|
deserialize,
|
|
7
7
|
ensureMsgpackr,
|
|
8
8
|
ensureRedis,
|
|
9
|
+
getCacheFunctionId,
|
|
9
10
|
getConnection,
|
|
10
11
|
getPlatformaticMeta,
|
|
11
12
|
getPlatformaticSubprefix,
|
|
12
13
|
keyFor,
|
|
14
|
+
loadCacheFunctionsFiles,
|
|
13
15
|
serialize
|
|
14
16
|
} from './valkey-common.js'
|
|
15
17
|
|
|
@@ -22,10 +24,12 @@ export const CACHE_MISS_METRIC = {
|
|
|
22
24
|
help: 'Next.js Components Cache (Valkey) Miss Count'
|
|
23
25
|
}
|
|
24
26
|
export const MAX_BATCH_SIZE = 100
|
|
27
|
+
export const IMPLICIT_TAG_PREFIX = '_N_T_'
|
|
25
28
|
|
|
26
29
|
export const sections = {
|
|
27
30
|
values: 'components:values',
|
|
28
|
-
tags: 'components:tags'
|
|
31
|
+
tags: 'components:tags',
|
|
32
|
+
revalidations: 'components:revalidations'
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
export class CacheHandler {
|
|
@@ -35,6 +39,7 @@ export class CacheHandler {
|
|
|
35
39
|
#prefix
|
|
36
40
|
#subprefix
|
|
37
41
|
#meta
|
|
42
|
+
#cacheFunctionsFiles
|
|
38
43
|
#maxTTL
|
|
39
44
|
#sections
|
|
40
45
|
#cacheHitMetric
|
|
@@ -82,6 +87,10 @@ export class CacheHandler {
|
|
|
82
87
|
async get (cacheKey, _, isRedisKey) {
|
|
83
88
|
this.#logger.trace({ key: cacheKey }, 'cache get')
|
|
84
89
|
|
|
90
|
+
if (!isRedisKey && !this.#hasSubprefix()) {
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
85
94
|
const key = isRedisKey ? cacheKey : this.#keyFor(cacheKey, this.#sections.values)
|
|
86
95
|
|
|
87
96
|
let rawValue
|
|
@@ -143,8 +152,6 @@ export class CacheHandler {
|
|
|
143
152
|
|
|
144
153
|
this.#logger.trace({ key: cacheKey, value, tags, revalidate }, 'cache set')
|
|
145
154
|
|
|
146
|
-
const key = isRedisKey ? cacheKey : this.#keyFor(cacheKey, this.#sections.values)
|
|
147
|
-
|
|
148
155
|
try {
|
|
149
156
|
// Gather the value
|
|
150
157
|
const chunks = []
|
|
@@ -152,10 +159,24 @@ export class CacheHandler {
|
|
|
152
159
|
chunks.push(chunk)
|
|
153
160
|
}
|
|
154
161
|
|
|
162
|
+
if (!isRedisKey && !this.#hasSubprefix()) {
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const key = isRedisKey ? cacheKey : this.#keyFor(cacheKey, this.#sections.values)
|
|
167
|
+
|
|
155
168
|
// Compute the parameters to save
|
|
169
|
+
|
|
170
|
+
const file = await this.#fileFor(cacheKey)
|
|
171
|
+
|
|
172
|
+
let meta = this.#meta
|
|
173
|
+
if (file) {
|
|
174
|
+
meta = { ...meta, file }
|
|
175
|
+
}
|
|
176
|
+
|
|
156
177
|
const toSerialize = serialize({
|
|
157
178
|
maxTTL: this.#maxTTL,
|
|
158
|
-
meta
|
|
179
|
+
meta,
|
|
159
180
|
value: Buffer.concat(chunks),
|
|
160
181
|
...data
|
|
161
182
|
})
|
|
@@ -193,12 +214,39 @@ export class CacheHandler {
|
|
|
193
214
|
// This function is not necessary as we don't have a local state to synchronize.
|
|
194
215
|
async refreshTags () {}
|
|
195
216
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
217
|
+
// Next.js calls this with the implicit tags of the current request (the ones revalidatePath()
|
|
218
|
+
// targets) and discards any entry created before the returned timestamp.
|
|
219
|
+
async getExpiration (tags) {
|
|
220
|
+
if (!tags?.length || !this.#hasSubprefix()) {
|
|
221
|
+
return 0
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
try {
|
|
225
|
+
const keys = tags.map(tag => this.#keyFor(tag, this.#sections.revalidations))
|
|
226
|
+
const timestamps = await this.#store.mget(keys)
|
|
227
|
+
|
|
228
|
+
let expiration = 0
|
|
229
|
+
for (const timestamp of timestamps) {
|
|
230
|
+
if (timestamp) {
|
|
231
|
+
expiration = Math.max(expiration, Number(timestamp))
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return expiration
|
|
236
|
+
} catch (e) {
|
|
237
|
+
this.#logger.error(
|
|
238
|
+
{ err: ensureLoggableError(e) },
|
|
239
|
+
'Cannot read cache tags expiration from Valkey'
|
|
240
|
+
)
|
|
241
|
+
return 0
|
|
242
|
+
}
|
|
199
243
|
}
|
|
200
244
|
|
|
201
245
|
async updateTags (tags) {
|
|
246
|
+
if (!this.#hasSubprefix()) {
|
|
247
|
+
return
|
|
248
|
+
}
|
|
249
|
+
|
|
202
250
|
if (typeof tags === 'string') {
|
|
203
251
|
tags = [tags]
|
|
204
252
|
}
|
|
@@ -207,6 +255,17 @@ export class CacheHandler {
|
|
|
207
255
|
const toDelete = new Set()
|
|
208
256
|
|
|
209
257
|
for (const tag of tags) {
|
|
258
|
+
// Implicit tags are never attached to entries, so there is nothing to delete.
|
|
259
|
+
// Record when they were revalidated instead, getExpiration() will check it.
|
|
260
|
+
if (tag.startsWith(IMPLICIT_TAG_PREFIX)) {
|
|
261
|
+
if (this.#maxTTL >= 1) {
|
|
262
|
+
const revalidationKey = this.#keyFor(tag, this.#sections.revalidations)
|
|
263
|
+
await this.#store.set(revalidationKey, Date.now(), 'EX', this.#maxTTL)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
continue
|
|
267
|
+
}
|
|
268
|
+
|
|
210
269
|
const tagsKey = this.#keyFor(tag, this.#sections.tags)
|
|
211
270
|
|
|
212
271
|
// For each key in the tag set, expire the key
|
|
@@ -256,6 +315,26 @@ export class CacheHandler {
|
|
|
256
315
|
await Promise.all(promises)
|
|
257
316
|
}
|
|
258
317
|
|
|
318
|
+
// The manifest is read once, on the first write
|
|
319
|
+
async #fileFor (cacheKey) {
|
|
320
|
+
this.#cacheFunctionsFiles ??= loadCacheFunctionsFiles().catch(e => {
|
|
321
|
+
this.#logger.error(
|
|
322
|
+
{ err: ensureLoggableError(e) },
|
|
323
|
+
'Cannot read the server references manifest'
|
|
324
|
+
)
|
|
325
|
+
return new Map()
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
const files = await this.#cacheFunctionsFiles
|
|
329
|
+
return files.get(getCacheFunctionId(cacheKey))
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// During a build, the subprefix is only known once Next.js writes the build ID
|
|
333
|
+
#hasSubprefix () {
|
|
334
|
+
this.#subprefix ??= getPlatformaticSubprefix()
|
|
335
|
+
return this.#subprefix !== null
|
|
336
|
+
}
|
|
337
|
+
|
|
259
338
|
#keyFor (key, section) {
|
|
260
339
|
return keyFor(this.#prefix, this.#subprefix, section, key)
|
|
261
340
|
}
|
|
@@ -88,6 +88,10 @@ export class CacheHandler {
|
|
|
88
88
|
async get (cacheKey, _, isRedisKey) {
|
|
89
89
|
this.#logger.trace({ key: cacheKey }, 'cache get')
|
|
90
90
|
|
|
91
|
+
if (!isRedisKey && !this.#hasSubprefix()) {
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
|
|
91
95
|
const key = this.#standalone || isRedisKey ? cacheKey : this.#keyFor(cacheKey, sections.values)
|
|
92
96
|
|
|
93
97
|
let rawValue
|
|
@@ -134,6 +138,10 @@ export class CacheHandler {
|
|
|
134
138
|
}
|
|
135
139
|
|
|
136
140
|
async set (cacheKey, value, ctx, isRedisKey) {
|
|
141
|
+
if (!isRedisKey && !this.#hasSubprefix()) {
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
|
|
137
145
|
const tags = this.#getTags(ctx.tags, value)
|
|
138
146
|
const revalidate = ctx.revalidate ?? ctx.cacheControl?.revalidate ?? value.revalidate ?? 0
|
|
139
147
|
|
|
@@ -181,6 +189,10 @@ export class CacheHandler {
|
|
|
181
189
|
}
|
|
182
190
|
|
|
183
191
|
async remove (cacheKey, isRedisKey) {
|
|
192
|
+
if (!isRedisKey && !this.#hasSubprefix()) {
|
|
193
|
+
return
|
|
194
|
+
}
|
|
195
|
+
|
|
184
196
|
this.#logger.trace({ key: cacheKey }, 'cache remove')
|
|
185
197
|
|
|
186
198
|
const key = this.#standalone || isRedisKey ? cacheKey : this.#keyFor(cacheKey, sections.values)
|
|
@@ -231,6 +243,10 @@ export class CacheHandler {
|
|
|
231
243
|
}
|
|
232
244
|
|
|
233
245
|
async revalidateTag (tags) {
|
|
246
|
+
if (!this.#hasSubprefix()) {
|
|
247
|
+
return
|
|
248
|
+
}
|
|
249
|
+
|
|
234
250
|
this.#logger.trace({ tags }, 'cache revalidateTag')
|
|
235
251
|
|
|
236
252
|
if (typeof tags === 'string') {
|
|
@@ -309,6 +325,12 @@ export class CacheHandler {
|
|
|
309
325
|
await Promise.all(promises)
|
|
310
326
|
}
|
|
311
327
|
|
|
328
|
+
// During a build, the subprefix is only known once Next.js writes the build ID
|
|
329
|
+
#hasSubprefix () {
|
|
330
|
+
this.#subprefix ??= getPlatformaticSubprefix()
|
|
331
|
+
return this.#subprefix !== null
|
|
332
|
+
}
|
|
333
|
+
|
|
312
334
|
#keyFor (key, section) {
|
|
313
335
|
return keyFor(this.#prefix, this.#subprefix, section, key)
|
|
314
336
|
}
|
package/lib/capability.js
CHANGED
|
@@ -21,6 +21,8 @@ import { parseStandaloneNextConfig, requireStandaloneStartServer, resolveStandal
|
|
|
21
21
|
|
|
22
22
|
export const supportedVersions = ['^14.0.0', '^15.0.0', '^16.0.0']
|
|
23
23
|
|
|
24
|
+
const loaderOptions = { registerHooks: true }
|
|
25
|
+
|
|
24
26
|
export function getCacheHandlerPath (name) {
|
|
25
27
|
return fileURLToPath(new URL(`./caching/${name}.js`, import.meta.url)).replaceAll(sep, '/')
|
|
26
28
|
}
|
|
@@ -166,7 +168,7 @@ export class NextCapability extends BaseCapability {
|
|
|
166
168
|
command = ['node', resolvePath(this.#next, './dist/bin/next'), 'build', this.root]
|
|
167
169
|
}
|
|
168
170
|
|
|
169
|
-
await this.buildWithCommand(command, this.#basePath, { loader, scripts: this.#getChildManagerScripts() })
|
|
171
|
+
await this.buildWithCommand(command, this.#basePath, { loader, loaderOptions, scripts: this.#getChildManagerScripts() })
|
|
170
172
|
await this.#fixRequiredServerFiles()
|
|
171
173
|
}
|
|
172
174
|
|
|
@@ -208,7 +210,7 @@ export class NextCapability extends BaseCapability {
|
|
|
208
210
|
this.#basePath = config.application?.basePath ? cleanBasePath(config.application?.basePath) : ''
|
|
209
211
|
|
|
210
212
|
if (command) {
|
|
211
|
-
return this.startWithCommand(command, loaderUrl, this.#getChildManagerScripts())
|
|
213
|
+
return this.startWithCommand(command, loaderUrl, this.#getChildManagerScripts(), { loaderOptions })
|
|
212
214
|
}
|
|
213
215
|
|
|
214
216
|
const { hostname, port } = this.serverConfig ?? {}
|
|
@@ -321,7 +323,7 @@ export class NextCapability extends BaseCapability {
|
|
|
321
323
|
if (this.#nextVersion.major < 15 || (this.#nextVersion.major <= 15 && this.#nextVersion.minor < 1)) {
|
|
322
324
|
childManagerScripts.push(new URL('./create-context-patch.js', import.meta.url))
|
|
323
325
|
}
|
|
324
|
-
return this.startWithCommand(command, loaderUrl, childManagerScripts)
|
|
326
|
+
return this.startWithCommand(command, loaderUrl, childManagerScripts, { loaderOptions })
|
|
325
327
|
}
|
|
326
328
|
|
|
327
329
|
this.childManager = this.#createChildManager(
|
|
@@ -512,6 +514,7 @@ export class NextCapability extends BaseCapability {
|
|
|
512
514
|
#createChildManager (loader, context, scripts) {
|
|
513
515
|
const childManager = new ChildManager({
|
|
514
516
|
loader,
|
|
517
|
+
loaderOptions,
|
|
515
518
|
context,
|
|
516
519
|
scripts
|
|
517
520
|
})
|
package/lib/loader.js
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
variableDeclaration,
|
|
11
11
|
variableDeclarator
|
|
12
12
|
} from '@babel/types'
|
|
13
|
+
import { readFileSync, realpathSync } from 'node:fs'
|
|
13
14
|
import { readFile, realpath } from 'node:fs/promises'
|
|
14
15
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
15
16
|
|
|
@@ -86,8 +87,8 @@ export function transformESM (source) {
|
|
|
86
87
|
return generate.default(ast).code
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
|
|
90
|
-
const realRoot = pathToFileURL(
|
|
90
|
+
function initializeCandidates (data, realRootPath) {
|
|
91
|
+
const realRoot = pathToFileURL(realRootPath)
|
|
91
92
|
|
|
92
93
|
if (!realRoot.pathname.endsWith('/')) {
|
|
93
94
|
realRoot.pathname += '/'
|
|
@@ -100,6 +101,38 @@ export async function initialize (data) {
|
|
|
100
101
|
candidates = candidates.map(c => new URL(c, realRoot).toString())
|
|
101
102
|
}
|
|
102
103
|
|
|
104
|
+
export function initializeSync (data) {
|
|
105
|
+
initializeCandidates(data, realpathSync(fileURLToPath(data.root)))
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export async function initialize (data) {
|
|
109
|
+
initializeCandidates(data, await realpath(fileURLToPath(data.root)))
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function loadSync (url, context, nextLoad) {
|
|
113
|
+
// Load the original file
|
|
114
|
+
const result = nextLoad(url, context)
|
|
115
|
+
|
|
116
|
+
if (!url.startsWith('file:')) {
|
|
117
|
+
return result
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
url = pathToFileURL(realpathSync(fileURLToPath(url))).toString()
|
|
121
|
+
|
|
122
|
+
if (!candidates.includes(url)) {
|
|
123
|
+
return result
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (result.format === 'commonjs' || result.format == null) {
|
|
127
|
+
result.format ??= 'commonjs'
|
|
128
|
+
result.source = transformCJS(result.source ?? readFileSync(new URL(result.responseURL ?? url), 'utf-8'))
|
|
129
|
+
} else {
|
|
130
|
+
result.source = transformESM(result.source)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return result
|
|
134
|
+
}
|
|
135
|
+
|
|
103
136
|
export async function load (url, context, nextLoad) {
|
|
104
137
|
// Load the original file
|
|
105
138
|
const result = await nextLoad(url, context)
|
|
@@ -114,8 +147,8 @@ export async function load (url, context, nextLoad) {
|
|
|
114
147
|
return result
|
|
115
148
|
}
|
|
116
149
|
|
|
117
|
-
if (result.format === 'commonjs') {
|
|
118
|
-
|
|
150
|
+
if (result.format === 'commonjs' || result.format == null) {
|
|
151
|
+
result.format ??= 'commonjs'
|
|
119
152
|
result.source = transformCJS(result.source ?? (await readFile(new URL(result.responseURL ?? url), 'utf-8')))
|
|
120
153
|
} else {
|
|
121
154
|
result.source = transformESM(result.source)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/next",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.73.0-alpha.0",
|
|
4
4
|
"description": "Platformatic Next.js Capability",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -19,33 +19,33 @@
|
|
|
19
19
|
"@babel/parser": "^7.25.3",
|
|
20
20
|
"@babel/traverse": "^7.25.3",
|
|
21
21
|
"@babel/types": "^7.25.2",
|
|
22
|
+
"@platformatic/basic": "3.73.0-alpha.0",
|
|
23
|
+
"@platformatic/foundation": "3.73.0-alpha.0",
|
|
24
|
+
"@platformatic/globals": "3.73.0-alpha.0",
|
|
22
25
|
"@platformatic/image-optimizer": "^0.2.1",
|
|
23
26
|
"amaro": "^1.0.0",
|
|
24
|
-
"iovalkey": "^0.
|
|
27
|
+
"iovalkey": "^0.4.0",
|
|
25
28
|
"light-my-request": "^6.0.0",
|
|
26
29
|
"msgpackr": "^1.11.2",
|
|
27
|
-
"semver": "^7.6.3"
|
|
28
|
-
"@platformatic/basic": "3.71.1-alpha.0",
|
|
29
|
-
"@platformatic/foundation": "3.71.1-alpha.0",
|
|
30
|
-
"@platformatic/globals": "3.71.1-alpha.0"
|
|
30
|
+
"semver": "^7.6.3"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@fastify/reply-from": "^12.0.0",
|
|
34
|
+
"@platformatic/gateway": "3.73.0-alpha.0",
|
|
35
|
+
"@platformatic/service": "3.73.0-alpha.0",
|
|
34
36
|
"@types/node": "^22.5.0",
|
|
35
37
|
"@types/react": "^19.1.11",
|
|
36
38
|
"@types/react-dom": "^19.1.7",
|
|
37
|
-
"cleaner-spec-reporter": "^0.
|
|
39
|
+
"cleaner-spec-reporter": "^2.0.0",
|
|
38
40
|
"eslint": "9",
|
|
39
41
|
"tstyche": "^7.0.0",
|
|
40
42
|
"execa": "^9.5.1",
|
|
41
43
|
"fastify": "^5.7.3",
|
|
42
44
|
"json-schema-to-typescript": "^15.0.1",
|
|
43
|
-
"neostandard": "^0.
|
|
45
|
+
"neostandard": "^0.14.0",
|
|
44
46
|
"next": "^16.1.0",
|
|
45
47
|
"typescript": "~6.0.3",
|
|
46
|
-
"ws": "^8.18.0"
|
|
47
|
-
"@platformatic/service": "3.71.1-alpha.0",
|
|
48
|
-
"@platformatic/gateway": "3.71.1-alpha.0"
|
|
48
|
+
"ws": "^8.18.0"
|
|
49
49
|
},
|
|
50
50
|
"engines": {
|
|
51
51
|
"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.73.0-alpha.0.json",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
4
|
"title": "Platformatic Next.js Config",
|
|
5
5
|
"type": "object",
|