@platformatic/next 2.0.0-alpha.5

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.
Files changed (46) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +13 -0
  3. package/README.md +13 -0
  4. package/config.d.ts +156 -0
  5. package/eslint.config.js +5 -0
  6. package/index.js +135 -0
  7. package/lib/loader.js +137 -0
  8. package/lib/schema.js +26 -0
  9. package/package.json +48 -0
  10. package/schema.json +506 -0
  11. package/test/fixtures/next/composer-autodetect-prefix/next.config.mjs +5 -0
  12. package/test/fixtures/next/composer-autodetect-prefix/package.json +15 -0
  13. package/test/fixtures/next/composer-autodetect-prefix/platformatic.application.json +8 -0
  14. package/test/fixtures/next/composer-autodetect-prefix/platformatic.runtime.json +20 -0
  15. package/test/fixtures/next/composer-autodetect-prefix/src/app/layout.js +7 -0
  16. package/test/fixtures/next/composer-autodetect-prefix/src/app/page.js +5 -0
  17. package/test/fixtures/next/composer-with-prefix/next.config.js +1 -0
  18. package/test/fixtures/next/composer-with-prefix/package.json +15 -0
  19. package/test/fixtures/next/composer-with-prefix/platformatic.application.json +11 -0
  20. package/test/fixtures/next/composer-with-prefix/platformatic.runtime.json +21 -0
  21. package/test/fixtures/next/composer-with-prefix/src/app/layout.js +7 -0
  22. package/test/fixtures/next/composer-with-prefix/src/app/page.js +5 -0
  23. package/test/fixtures/next/composer-without-prefix/next.config.mjs +3 -0
  24. package/test/fixtures/next/composer-without-prefix/package.json +15 -0
  25. package/test/fixtures/next/composer-without-prefix/platformatic.application.json +8 -0
  26. package/test/fixtures/next/composer-without-prefix/platformatic.runtime.json +21 -0
  27. package/test/fixtures/next/composer-without-prefix/src/app/layout.js +7 -0
  28. package/test/fixtures/next/composer-without-prefix/src/app/page.js +5 -0
  29. package/test/fixtures/next/server-side/next.config.js +1 -0
  30. package/test/fixtures/next/server-side/package.json +15 -0
  31. package/test/fixtures/next/server-side/platformatic.application.json +11 -0
  32. package/test/fixtures/next/server-side/platformatic.runtime.json +21 -0
  33. package/test/fixtures/next/server-side/src/app/direct/route.js +3 -0
  34. package/test/fixtures/next/server-side/src/app/layout.js +7 -0
  35. package/test/fixtures/next/server-side/src/app/page.js +12 -0
  36. package/test/fixtures/next/standalone/next.config.mjs +3 -0
  37. package/test/fixtures/next/standalone/package.json +15 -0
  38. package/test/fixtures/next/standalone/platformatic.runtime.json +18 -0
  39. package/test/fixtures/next/standalone/src/app/layout.js +7 -0
  40. package/test/fixtures/next/standalone/src/app/page.js +5 -0
  41. package/test/fixtures/platformatic-composer/platformatic.composer.json +20 -0
  42. package/test/fixtures/platformatic-composer/platformatic.no-prefix.composer.json +23 -0
  43. package/test/fixtures/platformatic-composer/plugin.js +9 -0
  44. package/test/fixtures/platformatic-service/platformatic.service.json +15 -0
  45. package/test/fixtures/platformatic-service/plugin.js +19 -0
  46. package/test/index.test.js +131 -0
@@ -0,0 +1,3 @@
1
+ export default function () {
2
+ return {}
3
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "next",
3
+ "private": true,
4
+ "version": "0.1.0",
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start"
9
+ },
10
+ "dependencies": {
11
+ "react": "^18.0.0",
12
+ "react-dom": "^18.0.0",
13
+ "next": "^14.2.5"
14
+ }
15
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "https://schemas.platformatic.dev/@platformatic/next/2.0.0.json",
3
+ "server": {
4
+ "logger": {
5
+ "level": "error"
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "https://schemas.platformatic.dev/@platformatic/runtime/1.52.0.json",
3
+ "entrypoint": "main",
4
+ "watch": false,
5
+ "managementApi": false,
6
+ "metrics": false,
7
+ "server": {
8
+ "logger": {
9
+ "level": "error"
10
+ }
11
+ },
12
+ "services": [
13
+ {
14
+ "id": "frontend",
15
+ "path": ".",
16
+ "config": "platformatic.application.json"
17
+ },
18
+ { "id": "service", "config": "platformatic.service.json", "path": "../../platformatic-service" },
19
+ { "id": "main", "config": "platformatic.no-prefix.composer.json", "path": "../../platformatic-composer" }
20
+ ]
21
+ }
@@ -0,0 +1,7 @@
1
+ export default function RootLayout ({ children }) {
2
+ return (
3
+ <html lang='en'>
4
+ <body>{children}</body>
5
+ </html>
6
+ )
7
+ }
@@ -0,0 +1,5 @@
1
+ import { version } from '../../../../../tmp/version.js'
2
+
3
+ export default function Home () {
4
+ return <div>Hello from {version}</div>
5
+ }
@@ -0,0 +1 @@
1
+ module.exports = {}
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "next",
3
+ "private": true,
4
+ "version": "0.1.0",
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start"
9
+ },
10
+ "dependencies": {
11
+ "react": "^18.0.0",
12
+ "react-dom": "^18.0.0",
13
+ "next": "^14.2.5"
14
+ }
15
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "https://schemas.platformatic.dev/@platformatic/next/2.0.0.json",
3
+ "server": {
4
+ "logger": {
5
+ "level": "error"
6
+ }
7
+ },
8
+ "application": {
9
+ "basePath": "/frontend"
10
+ }
11
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "https://schemas.platformatic.dev/@platformatic/runtime/1.52.0.json",
3
+ "entrypoint": "main",
4
+ "watch": false,
5
+ "managementApi": false,
6
+ "metrics": false,
7
+ "server": {
8
+ "logger": {
9
+ "level": "error"
10
+ }
11
+ },
12
+ "services": [
13
+ {
14
+ "id": "frontend",
15
+ "path": ".",
16
+ "config": "platformatic.application.json"
17
+ },
18
+ { "id": "service", "config": "platformatic.service.json", "path": "../../platformatic-service" },
19
+ { "id": "main", "config": "platformatic.composer.json", "path": "../../platformatic-composer" }
20
+ ]
21
+ }
@@ -0,0 +1,3 @@
1
+ export async function GET () {
2
+ return Response.json({ ok: true })
3
+ }
@@ -0,0 +1,7 @@
1
+ export default function RootLayout ({ children }) {
2
+ return (
3
+ <html lang='en'>
4
+ <body>{children}</body>
5
+ </html>
6
+ )
7
+ }
@@ -0,0 +1,12 @@
1
+ import { version } from '../../../../../tmp/version.js'
2
+
3
+ export default async function Home () {
4
+ const response = await fetch('http://service.plt.local/time')
5
+ const { time } = await response.json()
6
+
7
+ return (
8
+ <div>
9
+ Hello from v{version} t{time}
10
+ </div>
11
+ )
12
+ }
@@ -0,0 +1,3 @@
1
+ const nextConfig = {}
2
+
3
+ export default nextConfig
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "next",
3
+ "private": true,
4
+ "version": "0.1.0",
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start"
9
+ },
10
+ "dependencies": {
11
+ "react": "^18.0.0",
12
+ "react-dom": "^18.0.0",
13
+ "next": "^14.2.5"
14
+ }
15
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://schemas.platformatic.dev/@platformatic/runtime/1.52.0.json",
3
+ "entrypoint": "main",
4
+ "watch": false,
5
+ "managementApi": false,
6
+ "metrics": false,
7
+ "server": {
8
+ "logger": {
9
+ "level": "error"
10
+ }
11
+ },
12
+ "services": [
13
+ {
14
+ "id": "main",
15
+ "path": "."
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,7 @@
1
+ export default function RootLayout ({ children }) {
2
+ return (
3
+ <html lang='en'>
4
+ <body>{children}</body>
5
+ </html>
6
+ )
7
+ }
@@ -0,0 +1,5 @@
1
+ import { version } from '../../../../../tmp/version.js'
2
+
3
+ export default function Home () {
4
+ return <div>Hello from {version}</div>
5
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://schemas.platformatic.dev/@platformatic/composer/1.52.0.json",
3
+ "composer": {
4
+ "services": [
5
+ {
6
+ "id": "frontend"
7
+ },
8
+ {
9
+ "id": "service"
10
+ }
11
+ ]
12
+ },
13
+ "plugins": {
14
+ "paths": [
15
+ {
16
+ "path": "./plugin.js"
17
+ }
18
+ ]
19
+ }
20
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://schemas.platformatic.dev/@platformatic/composer/1.52.0.json",
3
+ "composer": {
4
+ "services": [
5
+ {
6
+ "id": "frontend",
7
+ "proxy": {
8
+ "prefix": ""
9
+ }
10
+ },
11
+ {
12
+ "id": "service"
13
+ }
14
+ ]
15
+ },
16
+ "plugins": {
17
+ "paths": [
18
+ {
19
+ "path": "./plugin.js"
20
+ }
21
+ ]
22
+ }
23
+ }
@@ -0,0 +1,9 @@
1
+ export default async function (app) {
2
+ app.get('/plugin', async () => {
3
+ return { ok: true }
4
+ })
5
+
6
+ app.get('/frontend/plugin', async () => {
7
+ return { ok: true }
8
+ })
9
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "$schema": "https://schemas.platformatic.dev/@platformatic/service/1.52.0.json",
3
+ "server": {
4
+ "logger": {
5
+ "level": "error"
6
+ }
7
+ },
8
+ "plugins": {
9
+ "paths": [
10
+ {
11
+ "path": "./plugin.js"
12
+ }
13
+ ]
14
+ }
15
+ }
@@ -0,0 +1,19 @@
1
+ 'use strict'
2
+
3
+ export default async function (app) {
4
+ app.get('/mesh', async () => {
5
+ const meta = await globalThis[Symbol.for('plt.runtime.itc')].send('getServiceMeta', 'frontend')
6
+
7
+ const url = new URL(`${meta.composer.prefix}/direct`.replaceAll(/\/+/g, '/'), 'http://frontend.plt.local')
8
+ const response = await fetch(url)
9
+ return response.json()
10
+ })
11
+
12
+ app.get('/direct', async () => {
13
+ return { ok: true }
14
+ })
15
+
16
+ app.get('/time', async () => {
17
+ return { time: Date.now() }
18
+ })
19
+ }
@@ -0,0 +1,131 @@
1
+ import { dirname, resolve } from 'node:path'
2
+ import { test } from 'node:test'
3
+ import {
4
+ createRuntime,
5
+ fixturesDir,
6
+ setFixturesDir,
7
+ updateHMRVersion,
8
+ verifyHMR,
9
+ verifyHTMLViaHTTP,
10
+ verifyHTMLViaInject,
11
+ verifyJSONViaHTTP,
12
+ verifyJSONViaInject,
13
+ } from '../../basic/test/helper.js'
14
+ import { safeRemove } from '../../utils/index.js'
15
+
16
+ function websocketHMRHandler (message, resolveConnection, resolveReload) {
17
+ switch (message.action) {
18
+ case 'sync':
19
+ resolveConnection()
20
+ break
21
+ case 'serverComponentChanges':
22
+ resolveReload()
23
+ }
24
+ }
25
+
26
+ function cleanNext (configFile) {
27
+ const root = dirname(resolve(fixturesDir, configFile))
28
+ return safeRemove(resolve(root, '.next'))
29
+ }
30
+
31
+ const packageRoot = resolve(import.meta.dirname, '..')
32
+ setFixturesDir(resolve(import.meta.dirname, './fixtures'))
33
+
34
+ test('can detect and start a Next application', async t => {
35
+ await updateHMRVersion()
36
+ await cleanNext('next/standalone/platformatic.runtime.json')
37
+
38
+ const { url } = await createRuntime(t, 'next/standalone/platformatic.runtime.json', packageRoot)
39
+
40
+ await verifyHTMLViaHTTP(url, '/', ['<script src="/_next/static/chunks/main-app.js'])
41
+ await verifyHMR(url, '/_next/webpack-hmr', undefined, websocketHMRHandler)
42
+ })
43
+
44
+ test('can detect and start a Next application when exposed in a composer with a prefix', async t => {
45
+ await updateHMRVersion()
46
+ await cleanNext('next/composer-with-prefix/platformatic.runtime.json')
47
+
48
+ const { runtime, url } = await createRuntime(t, 'next/composer-with-prefix/platformatic.runtime.json', packageRoot)
49
+
50
+ const htmlContents = ['<script src="/frontend/_next/static/chunks/main-app.js']
51
+
52
+ await verifyHTMLViaHTTP(url, '/frontend/', htmlContents)
53
+ await verifyHTMLViaInject(runtime, 'main', '/frontend', htmlContents)
54
+ await verifyHMR(url, '/frontend/_next/webpack-hmr', undefined, websocketHMRHandler)
55
+
56
+ await verifyJSONViaHTTP(url, '/plugin', 200, { ok: true })
57
+ await verifyJSONViaHTTP(url, '/frontend/plugin', 200, { ok: true })
58
+ await verifyJSONViaHTTP(url, '/service/direct', 200, { ok: true })
59
+
60
+ await verifyJSONViaInject(runtime, 'main', 'GET', 'plugin', 200, { ok: true })
61
+ await verifyJSONViaInject(runtime, 'main', 'GET', '/frontend/plugin', 200, { ok: true })
62
+ await verifyJSONViaInject(runtime, 'service', 'GET', '/direct', 200, { ok: true })
63
+ })
64
+
65
+ test('can detect and start a Next application when exposed in a composer without a prefix', async t => {
66
+ await updateHMRVersion()
67
+ await cleanNext('next/composer-without-prefix/platformatic.runtime.json')
68
+
69
+ const { runtime, url } = await createRuntime(t, 'next/composer-without-prefix/platformatic.runtime.json', packageRoot)
70
+
71
+ const htmlContents = ['<script src="/_next/static/chunks/main-app.js']
72
+
73
+ await verifyHTMLViaHTTP(url, '/', htmlContents)
74
+ await verifyHTMLViaInject(runtime, 'main', '/', htmlContents)
75
+ await verifyHMR(url, '/_next/webpack-hmr', undefined, websocketHMRHandler)
76
+
77
+ await verifyJSONViaHTTP(url, '/plugin', 200, { ok: true })
78
+ await verifyJSONViaHTTP(url, '/frontend/plugin', 200, { ok: true })
79
+ await verifyJSONViaHTTP(url, '/service/direct', 200, { ok: true })
80
+
81
+ await verifyJSONViaInject(runtime, 'main', 'GET', 'plugin', 200, { ok: true })
82
+ await verifyJSONViaInject(runtime, 'main', 'GET', '/frontend/plugin', 200, { ok: true })
83
+ await verifyJSONViaInject(runtime, 'service', 'GET', '/direct', 200, { ok: true })
84
+ })
85
+
86
+ // In this file the application purposely does not specify a platformatic.application.json to see if we automatically detect one
87
+ test('can detect and start a Next application when exposed in a composer with a custom config and by autodetecting the prefix', async t => {
88
+ await updateHMRVersion()
89
+ await cleanNext('next/composer-autodetect-prefix/platformatic.runtime.json')
90
+
91
+ const { runtime, url } = await createRuntime(
92
+ t,
93
+ 'next/composer-autodetect-prefix/platformatic.runtime.json',
94
+ packageRoot
95
+ )
96
+
97
+ const htmlContents = ['<script src="/nested/base/dir/_next/static/chunks/main-app.js']
98
+
99
+ await verifyHTMLViaHTTP(url, '/nested/base/dir/', htmlContents)
100
+ await verifyHTMLViaInject(runtime, 'main', '/nested/base/dir', htmlContents)
101
+ await verifyHMR(url, '/nested/base/dir/_next/webpack-hmr', undefined, websocketHMRHandler)
102
+
103
+ await verifyJSONViaHTTP(url, '/plugin', 200, { ok: true })
104
+ await verifyJSONViaHTTP(url, '/frontend/plugin', 200, { ok: true })
105
+ await verifyJSONViaHTTP(url, '/service/direct', 200, { ok: true })
106
+
107
+ await verifyJSONViaInject(runtime, 'main', 'GET', 'plugin', 200, { ok: true })
108
+ await verifyJSONViaInject(runtime, 'main', 'GET', '/frontend/plugin', 200, { ok: true })
109
+ await verifyJSONViaInject(runtime, 'service', 'GET', '/direct', 200, { ok: true })
110
+ })
111
+
112
+ test('can detect and start a Next application with working React Server Components and Next server API', async t => {
113
+ await updateHMRVersion()
114
+ await cleanNext('next/server-side/platformatic.runtime.json')
115
+ const { runtime, url } = await createRuntime(t, 'next/server-side/platformatic.runtime.json', packageRoot)
116
+
117
+ const htmlContents = ['<script src="/frontend/_next/static/chunks/main-app.js']
118
+
119
+ await verifyHTMLViaHTTP(url, '/frontend/', htmlContents)
120
+ await verifyHTMLViaInject(runtime, 'main', '/frontend', htmlContents)
121
+ await verifyHMR(url, '/frontend/_next/webpack-hmr', undefined, websocketHMRHandler)
122
+
123
+ await verifyJSONViaHTTP(url, '/plugin', 200, { ok: true })
124
+ await verifyJSONViaHTTP(url, '/frontend/plugin', 200, { ok: true })
125
+ await verifyJSONViaHTTP(url, '/service/direct', 200, { ok: true })
126
+
127
+ await verifyJSONViaInject(runtime, 'main', 'GET', 'plugin', 200, { ok: true })
128
+ await verifyJSONViaInject(runtime, 'main', 'GET', '/frontend/plugin', 200, { ok: true })
129
+ await verifyJSONViaInject(runtime, 'service', 'GET', '/direct', 200, { ok: true })
130
+ await verifyJSONViaInject(runtime, 'service', 'GET', '/mesh', 200, { ok: true })
131
+ })