@platformatic/next 2.0.0-alpha.10
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/LICENSE +201 -0
- package/NOTICE +13 -0
- package/README.md +13 -0
- package/config.d.ts +167 -0
- package/eslint.config.js +5 -0
- package/index.js +256 -0
- package/lib/loader.js +152 -0
- package/lib/schema.js +26 -0
- package/package.json +49 -0
- package/schema.json +543 -0
package/lib/loader.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import generate from '@babel/generator'
|
|
2
|
+
import { parse } from '@babel/parser'
|
|
3
|
+
import traverse from '@babel/traverse'
|
|
4
|
+
import {
|
|
5
|
+
blockStatement,
|
|
6
|
+
functionDeclaration,
|
|
7
|
+
identifier,
|
|
8
|
+
restElement,
|
|
9
|
+
returnStatement,
|
|
10
|
+
variableDeclaration,
|
|
11
|
+
variableDeclarator
|
|
12
|
+
} from '@babel/types'
|
|
13
|
+
import { readFile, realpath } from 'node:fs/promises'
|
|
14
|
+
import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
15
|
+
|
|
16
|
+
const originalId = '__pltOriginalNextConfig'
|
|
17
|
+
|
|
18
|
+
let candidates
|
|
19
|
+
let basePath
|
|
20
|
+
|
|
21
|
+
function parseSingleExpression (expr) {
|
|
22
|
+
return parse(expr, { allowAwaitOutsideFunction: true }).program.body[0]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/*
|
|
26
|
+
Generates:
|
|
27
|
+
async function (...args) {
|
|
28
|
+
let __pltOriginalNextConfig = $ORIGINAL;
|
|
29
|
+
|
|
30
|
+
if (typeof __pltOriginalNextConfig === 'function') {
|
|
31
|
+
__pltOriginalNextConfig = await __pltOriginalNextConfig(...args);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if(typeof __pltOriginalNextConfig.basePath === 'undefined') {
|
|
35
|
+
__pltOriginalNextConfig.basePath = basePath
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// This is to send the configuraion when Next is executed in a child process (development)
|
|
39
|
+
globalThis[Symbol.for('plt.children.itc')]?.notify('config', __pltOriginalNextConfig)
|
|
40
|
+
|
|
41
|
+
// This is to send the configuraion when Next is executed in the same process (production)
|
|
42
|
+
process.emit('plt:next:config', __pltOriginalNextConfig)
|
|
43
|
+
|
|
44
|
+
return __pltOriginalNextConfig;
|
|
45
|
+
}
|
|
46
|
+
*/
|
|
47
|
+
function createEvaluatorWrapperFunction (original) {
|
|
48
|
+
return functionDeclaration(
|
|
49
|
+
null,
|
|
50
|
+
[restElement(identifier('args'))],
|
|
51
|
+
blockStatement([
|
|
52
|
+
variableDeclaration('let', [variableDeclarator(identifier(originalId), original)]),
|
|
53
|
+
parseSingleExpression(
|
|
54
|
+
`if (typeof ${originalId} === 'function') { ${originalId} = await ${originalId}(...args) }`
|
|
55
|
+
),
|
|
56
|
+
parseSingleExpression(
|
|
57
|
+
`if (typeof ${originalId}.basePath === 'undefined') { ${originalId}.basePath = "${basePath}" }`
|
|
58
|
+
),
|
|
59
|
+
parseSingleExpression(`globalThis[Symbol.for('plt.children.itc')]?.notify('config', ${originalId})`),
|
|
60
|
+
parseSingleExpression(`process.emit('plt:next:config', ${originalId})`),
|
|
61
|
+
returnStatement(identifier(originalId))
|
|
62
|
+
]),
|
|
63
|
+
false,
|
|
64
|
+
true
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function transformCJS (source) {
|
|
69
|
+
const ast = parse(source.toString(), { sourceType: 'module' })
|
|
70
|
+
|
|
71
|
+
// Manipulate the AST
|
|
72
|
+
traverse.default(ast, {
|
|
73
|
+
AssignmentExpression (path) {
|
|
74
|
+
const { left, right } = path.node
|
|
75
|
+
|
|
76
|
+
// module.exports = $EXPRESSION
|
|
77
|
+
if (left.object.name === 'module' && left.property.name === 'exports') {
|
|
78
|
+
path.node.right = createEvaluatorWrapperFunction(right)
|
|
79
|
+
path.skip()
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
return generate.default(ast).code
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function transformESM (source) {
|
|
88
|
+
const ast = parse(source.toString(), { sourceType: 'module' })
|
|
89
|
+
|
|
90
|
+
// Manipulate the AST
|
|
91
|
+
traverse.default(ast, {
|
|
92
|
+
ExportDefaultDeclaration (path) {
|
|
93
|
+
const declaration = path.node.declaration
|
|
94
|
+
|
|
95
|
+
// export default [async] function
|
|
96
|
+
if (path.node.declaration.type === 'FunctionDeclaration') {
|
|
97
|
+
path.insertBefore(
|
|
98
|
+
functionDeclaration(
|
|
99
|
+
identifier(originalId + 'Function'),
|
|
100
|
+
declaration.params,
|
|
101
|
+
declaration.body,
|
|
102
|
+
declaration.generator,
|
|
103
|
+
declaration.async
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
path.node.declaration = createEvaluatorWrapperFunction(identifier(originalId + 'Function'))
|
|
108
|
+
} else {
|
|
109
|
+
// export default $EXPRESSION
|
|
110
|
+
path.node.declaration = createEvaluatorWrapperFunction(declaration)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
return generate.default(ast).code
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export async function initialize (data) {
|
|
119
|
+
const realRoot = pathToFileURL(await realpath(fileURLToPath(data.root)))
|
|
120
|
+
|
|
121
|
+
if (!realRoot.pathname.endsWith('/')) {
|
|
122
|
+
realRoot.pathname += '/'
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Keep in sync with https://github.com/vercel/next.js/blob/main/packages/next/src/shared/lib/constants.ts
|
|
126
|
+
candidates = ['next.config.js', 'next.config.mjs'].map(c => new URL(c, realRoot).toString())
|
|
127
|
+
basePath = data.basePath ?? ''
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export async function load (url, context, nextLoad) {
|
|
131
|
+
// Load the original file
|
|
132
|
+
const result = await nextLoad(url, context)
|
|
133
|
+
|
|
134
|
+
if (!url.startsWith('file:')) {
|
|
135
|
+
return result
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
url = pathToFileURL(await realpath(fileURLToPath(url))).toString()
|
|
139
|
+
|
|
140
|
+
if (!candidates.includes(url)) {
|
|
141
|
+
return result
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (result.format === 'commonjs') {
|
|
145
|
+
await readFile(new URL(result.responseURL ?? url), 'utf-8')
|
|
146
|
+
result.source = transformCJS(result.source ?? (await readFile(new URL(result.responseURL ?? url), 'utf-8')))
|
|
147
|
+
} else {
|
|
148
|
+
result.source = transformESM(result.source)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return result
|
|
152
|
+
}
|
package/lib/schema.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { schemaComponents } from '@platformatic/basic'
|
|
2
|
+
import { schemaComponents as utilsSchemaComponents } from '@platformatic/utils'
|
|
3
|
+
import { readFileSync } from 'node:fs'
|
|
4
|
+
|
|
5
|
+
export const packageJson = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8'))
|
|
6
|
+
|
|
7
|
+
export const schema = {
|
|
8
|
+
$id: `https://schemas.platformatic.dev/@platformatic/next/${packageJson.version}.json`,
|
|
9
|
+
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
10
|
+
title: 'Platformatic Next.js Stackable',
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
$schema: {
|
|
14
|
+
type: 'string'
|
|
15
|
+
},
|
|
16
|
+
server: utilsSchemaComponents.server,
|
|
17
|
+
watch: schemaComponents.watch,
|
|
18
|
+
application: schemaComponents.application,
|
|
19
|
+
},
|
|
20
|
+
additionalProperties: false
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* c8 ignore next 3 */
|
|
24
|
+
if (process.argv[1] === import.meta.filename) {
|
|
25
|
+
console.log(JSON.stringify(schema, null, 2))
|
|
26
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@platformatic/next",
|
|
3
|
+
"version": "2.0.0-alpha.10",
|
|
4
|
+
"description": "Platformatic Next.js Stackable",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/platformatic/platformatic.git"
|
|
10
|
+
},
|
|
11
|
+
"author": "Paolo Insogna <paolo@cowtech.it>",
|
|
12
|
+
"license": "Apache-2.0",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/platformatic/platformatic/issues"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://github.com/platformatic/platformatic#readme",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@babel/generator": "^7.25.0",
|
|
19
|
+
"@babel/parser": "^7.25.3",
|
|
20
|
+
"@babel/traverse": "^7.25.3",
|
|
21
|
+
"@babel/types": "^7.25.2",
|
|
22
|
+
"semver": "^7.6.3",
|
|
23
|
+
"@platformatic/basic": "2.0.0-alpha.10",
|
|
24
|
+
"@platformatic/config": "2.0.0-alpha.10",
|
|
25
|
+
"@platformatic/utils": "2.0.0-alpha.10"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"borp": "^0.17.0",
|
|
29
|
+
"eslint": "9",
|
|
30
|
+
"fastify": "5.0.0-alpha.4",
|
|
31
|
+
"json-schema-to-typescript": "^15.0.1",
|
|
32
|
+
"neostandard": "^0.11.1",
|
|
33
|
+
"next": "^14.2.5",
|
|
34
|
+
"react": "^18.3.1",
|
|
35
|
+
"react-dom": "^18.3.1",
|
|
36
|
+
"typescript": "^5.5.4",
|
|
37
|
+
"ws": "^8.18.0",
|
|
38
|
+
"@platformatic/composer": "2.0.0-alpha.10",
|
|
39
|
+
"@platformatic/service": "2.0.0-alpha.10"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"test": "npm run lint && borp --concurrency=1 --no-timeout",
|
|
43
|
+
"coverage": "npm run lint && borp -C -X test -X test/fixtures --concurrency=1 --no-timeout",
|
|
44
|
+
"gen-schema": "node lib/schema.js > schema.json",
|
|
45
|
+
"gen-types": "json2ts > config.d.ts < schema.json",
|
|
46
|
+
"build": "pnpm run gen-schema && pnpm run gen-types",
|
|
47
|
+
"lint": "eslint"
|
|
48
|
+
}
|
|
49
|
+
}
|