@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/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
+ }