@tothalex/nulljs 0.0.47 → 0.0.53
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/package.json +22 -32
- package/src/cli.ts +24 -0
- package/src/commands/config.ts +130 -0
- package/src/commands/deploy.ts +182 -123
- package/src/commands/dev.ts +10 -0
- package/src/commands/host.ts +130 -139
- package/src/commands/index.ts +6 -8
- package/src/commands/secret.ts +364 -56
- package/src/commands/status.ts +41 -0
- package/src/components/DeployAnimation.tsx +92 -0
- package/src/components/DeploymentLogsPane.tsx +79 -0
- package/src/components/Header.tsx +57 -0
- package/src/components/HelpModal.tsx +64 -0
- package/src/components/SystemLogsPane.tsx +78 -0
- package/src/config/index.ts +181 -0
- package/src/lib/bundle/function.ts +125 -0
- package/src/lib/bundle/index.ts +3 -0
- package/src/lib/bundle/react.ts +149 -0
- package/src/lib/deploy.ts +103 -0
- package/src/lib/server.ts +160 -0
- package/src/lib/vite.ts +120 -0
- package/src/lib/watcher.ts +274 -0
- package/src/ui.tsx +363 -0
- package/tsconfig.json +30 -0
- package/scripts/install-server.js +0 -199
- package/src/commands/api.ts +0 -16
- package/src/commands/auth.ts +0 -54
- package/src/commands/create.ts +0 -43
- package/src/commands/dev/function/index.ts +0 -221
- package/src/commands/dev/function/utils.ts +0 -99
- package/src/commands/dev/index.tsx +0 -126
- package/src/commands/dev/logging-manager.ts +0 -87
- package/src/commands/dev/server/index.ts +0 -48
- package/src/commands/dev/server/utils.ts +0 -37
- package/src/commands/dev/ui/components/scroll-area.tsx +0 -141
- package/src/commands/dev/ui/components/tab-bar.tsx +0 -67
- package/src/commands/dev/ui/index.tsx +0 -71
- package/src/commands/dev/ui/logging-context.tsx +0 -76
- package/src/commands/dev/ui/tabs/functions-tab.tsx +0 -35
- package/src/commands/dev/ui/tabs/server-tab.tsx +0 -36
- package/src/commands/dev/ui/tabs/vite-tab.tsx +0 -35
- package/src/commands/dev/ui/use-logging.tsx +0 -34
- package/src/commands/dev/vite/index.ts +0 -54
- package/src/commands/dev/vite/utils.ts +0 -71
- package/src/commands/profile.ts +0 -189
- package/src/index.ts +0 -346
- package/src/lib/api.ts +0 -189
- package/src/lib/bundle/function/index.ts +0 -46
- package/src/lib/bundle/react/index.ts +0 -2
- package/src/lib/bundle/react/spa.ts +0 -77
- package/src/lib/bundle/react/ssr/client.ts +0 -93
- package/src/lib/bundle/react/ssr/config.ts +0 -77
- package/src/lib/bundle/react/ssr/index.ts +0 -4
- package/src/lib/bundle/react/ssr/props.ts +0 -71
- package/src/lib/bundle/react/ssr/server.ts +0 -83
- package/src/lib/config.ts +0 -347
- package/src/lib/deployment.ts +0 -244
- package/src/lib/update-server.ts +0 -262
package/src/lib/api.ts
DELETED
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
import { lookup } from 'mime-types'
|
|
2
|
-
import type { Deployment } from './deployment'
|
|
3
|
-
import chalk from 'chalk'
|
|
4
|
-
import { API, loadPrivateKey } from './config'
|
|
5
|
-
|
|
6
|
-
const formDataToString = async (formData: FormData): Promise<string> => {
|
|
7
|
-
const entries: string[] = []
|
|
8
|
-
|
|
9
|
-
const sortedEntries: [string, FormDataEntryValue][] = Array.from(formData.entries()).sort(
|
|
10
|
-
([a], [b]) => a.localeCompare(b)
|
|
11
|
-
)
|
|
12
|
-
|
|
13
|
-
for (const [key, value] of sortedEntries) {
|
|
14
|
-
if (value instanceof Blob) {
|
|
15
|
-
entries.push(`${key}:${value.size}:${value.type}`)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return entries.join('|')
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export const createDeployment = async (deployment: Deployment, logger: any = console) => {
|
|
23
|
-
const form = new FormData()
|
|
24
|
-
|
|
25
|
-
if (deployment.type === 'react') {
|
|
26
|
-
for (const asset of deployment.assets) {
|
|
27
|
-
const mime = lookup(asset.fileName)
|
|
28
|
-
|
|
29
|
-
if (!mime) {
|
|
30
|
-
throw new Error(chalk.yellow(`Couldn't get the mime type for ${asset.fileName}`))
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const buffer = Buffer.from(asset.code)
|
|
34
|
-
const blob = new Blob([buffer], { type: mime })
|
|
35
|
-
|
|
36
|
-
form.append(asset.fileName, blob)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
logger.log(chalk.yellow('Deploying ') + chalk.bgYellow.black(deployment.name))
|
|
40
|
-
deployment.assets.forEach((asset) => {
|
|
41
|
-
logger.log(`-> ${chalk.blue(asset.fileName)}`)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
const privateKey = await loadPrivateKey()
|
|
45
|
-
|
|
46
|
-
const sign = await crypto.subtle.sign(
|
|
47
|
-
'Ed25519',
|
|
48
|
-
privateKey,
|
|
49
|
-
Buffer.from(await formDataToString(form))
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
const signature = btoa(String.fromCharCode(...new Uint8Array(sign)))
|
|
53
|
-
|
|
54
|
-
const response = await fetch(`${API}/deployment/react`, {
|
|
55
|
-
headers: {
|
|
56
|
-
Authorization: signature
|
|
57
|
-
},
|
|
58
|
-
method: 'POST',
|
|
59
|
-
body: form
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
if (response.status !== 200) {
|
|
63
|
-
throw new Error(
|
|
64
|
-
`${chalk.red('Deployment failed')} ${chalk.bgRed.black(response.status)}: ${chalk.red(await response.text())}`
|
|
65
|
-
)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
logger.log(chalk.green('Deployed ') + chalk.bgGreen.black(deployment.name))
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (deployment.type === 'function') {
|
|
72
|
-
const handler = deployment.assets.find((asset) => asset.fileName === 'handler.js')
|
|
73
|
-
|
|
74
|
-
if (!handler) {
|
|
75
|
-
throw new Error(chalk.yellow(`Handler not found for ${deployment.name}`))
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const mime = lookup(handler.fileName)
|
|
79
|
-
|
|
80
|
-
if (!mime) {
|
|
81
|
-
throw new Error(chalk.yellow(`Couldn't get the mime type for ${handler.fileName}`))
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const buffer = Buffer.from(handler.code)
|
|
85
|
-
const blob = new Blob([buffer], { type: mime })
|
|
86
|
-
|
|
87
|
-
form.append(handler.fileName, blob)
|
|
88
|
-
|
|
89
|
-
logger.log(chalk.yellow('Deploying ') + chalk.bgYellow.black(deployment.name))
|
|
90
|
-
logger.log(`-> ${chalk.blue(handler.fileName)}`)
|
|
91
|
-
|
|
92
|
-
const privateKey = await loadPrivateKey()
|
|
93
|
-
|
|
94
|
-
const sign = await crypto.subtle.sign(
|
|
95
|
-
'Ed25519',
|
|
96
|
-
privateKey,
|
|
97
|
-
Buffer.from(await formDataToString(form))
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
const signature = btoa(String.fromCharCode(...new Uint8Array(sign)))
|
|
101
|
-
|
|
102
|
-
const response = await fetch(`${API}/deployment`, {
|
|
103
|
-
headers: {
|
|
104
|
-
authorization: signature
|
|
105
|
-
},
|
|
106
|
-
method: 'POST',
|
|
107
|
-
body: form
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
if (response.status !== 200) {
|
|
111
|
-
throw new Error(
|
|
112
|
-
`${chalk.red('Deployment failed')} ${chalk.bgRed.black(response.status)}: ${chalk.red(await response.text())}`
|
|
113
|
-
)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
logger.log(chalk.green('Deployed ') + chalk.bgGreen.black(deployment.name))
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const createSignatureHeader = async (props: { method: string; url: string; body?: string }) => {
|
|
121
|
-
const timestamp = new Date().toISOString()
|
|
122
|
-
const privateKey = await loadPrivateKey()
|
|
123
|
-
|
|
124
|
-
const raw = `${props.method}-${props.url}-${timestamp}${props.body ? '-' + props.body : ''}`
|
|
125
|
-
|
|
126
|
-
const sign = await crypto.subtle.sign('Ed25519', privateKey, Buffer.from(raw))
|
|
127
|
-
const signature = btoa(String.fromCharCode(...new Uint8Array(sign)))
|
|
128
|
-
|
|
129
|
-
const header: { authorization: string; 'x-time': string; 'x-body'?: string } = {
|
|
130
|
-
authorization: signature,
|
|
131
|
-
'x-time': timestamp
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (props.body) {
|
|
135
|
-
header['x-body'] = btoa(props.body)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return header
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export const fetchSecretKeys = async (): Promise<string[]> => {
|
|
142
|
-
const path = `${API}/secrets`
|
|
143
|
-
|
|
144
|
-
const headers = await createSignatureHeader({
|
|
145
|
-
method: 'GET',
|
|
146
|
-
url: path
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
const response = await fetch(path, {
|
|
150
|
-
headers,
|
|
151
|
-
method: 'GET'
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
if (response.status !== 200) {
|
|
155
|
-
console.log(chalk.red('Request failed'))
|
|
156
|
-
console.log(`${chalk.bgRed.black(response.status)}: ${chalk.red(await response.text())}`)
|
|
157
|
-
return []
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const data = await response.json()
|
|
161
|
-
|
|
162
|
-
return data
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export const postSecret = async (props: { key: string; value: string }) => {
|
|
166
|
-
const path = `${API}/secrets`
|
|
167
|
-
const body = JSON.stringify(props)
|
|
168
|
-
|
|
169
|
-
const headers = await createSignatureHeader({
|
|
170
|
-
method: 'POST',
|
|
171
|
-
url: path,
|
|
172
|
-
body
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
const response = await fetch(path, {
|
|
176
|
-
method: 'POST',
|
|
177
|
-
headers: {
|
|
178
|
-
'Content-Type': 'application/json',
|
|
179
|
-
...headers
|
|
180
|
-
},
|
|
181
|
-
body
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
if (response.status !== 200) {
|
|
185
|
-
throw new Error(
|
|
186
|
-
`${chalk.red('Request failed')} ${chalk.bgRed.black(response.status)}: ${chalk.red(await response.text())}`
|
|
187
|
-
)
|
|
188
|
-
}
|
|
189
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { InlineConfig, Plugin, UserConfig } from 'vite'
|
|
2
|
-
import { external } from '../external'
|
|
3
|
-
import type { PluginOptions } from '../types'
|
|
4
|
-
|
|
5
|
-
const jsFunction = ({ filePath }: PluginOptions): Plugin => {
|
|
6
|
-
return {
|
|
7
|
-
name: 'nulljs-function-plugin',
|
|
8
|
-
apply: 'build',
|
|
9
|
-
config: async (config: UserConfig, { command }) => {
|
|
10
|
-
if (command !== 'build') {
|
|
11
|
-
return config
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return {
|
|
15
|
-
build: {
|
|
16
|
-
rollupOptions: {
|
|
17
|
-
input: {
|
|
18
|
-
handler: filePath
|
|
19
|
-
},
|
|
20
|
-
external,
|
|
21
|
-
output: {
|
|
22
|
-
// preserveModules: false,
|
|
23
|
-
entryFileNames: '[name].js'
|
|
24
|
-
},
|
|
25
|
-
preserveEntrySignatures: 'strict'
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export const functionConfig = (filePath: string): InlineConfig => {
|
|
34
|
-
return {
|
|
35
|
-
logLevel: 'error',
|
|
36
|
-
plugins: [
|
|
37
|
-
jsFunction({
|
|
38
|
-
filePath
|
|
39
|
-
})
|
|
40
|
-
],
|
|
41
|
-
build: {
|
|
42
|
-
outDir: '/tmp',
|
|
43
|
-
minify: false
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { basename, extname } from 'path'
|
|
2
|
-
import type { InlineConfig, Plugin, UserConfig } from 'vite'
|
|
3
|
-
import react from '@vitejs/plugin-react'
|
|
4
|
-
import tailwindcss from '@tailwindcss/vite'
|
|
5
|
-
|
|
6
|
-
import type { PluginOptions } from '../types'
|
|
7
|
-
|
|
8
|
-
const jsSpa = ({ filePath }: PluginOptions): Plugin => {
|
|
9
|
-
const entry = basename(filePath, extname(filePath))
|
|
10
|
-
const virtualPrefix = `virtual:ssr/${entry}.tsx`
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
name: 'nulljs-ssr-client-plugin',
|
|
14
|
-
apply: 'build',
|
|
15
|
-
config: async (config: UserConfig, { command }) => {
|
|
16
|
-
if (command !== 'build') {
|
|
17
|
-
return config
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return {
|
|
21
|
-
build: {
|
|
22
|
-
rollupOptions: {
|
|
23
|
-
input: {
|
|
24
|
-
[entry]: virtualPrefix
|
|
25
|
-
},
|
|
26
|
-
external: ['cloud'],
|
|
27
|
-
output: {
|
|
28
|
-
entryFileNames: '[name].js'
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
plugins: [react()]
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
resolveId: (id: string) => {
|
|
37
|
-
if (id === virtualPrefix) {
|
|
38
|
-
return id
|
|
39
|
-
}
|
|
40
|
-
return null
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
load: (id: string) => {
|
|
44
|
-
if (id === virtualPrefix) {
|
|
45
|
-
const script = `
|
|
46
|
-
import { StrictMode } from 'react'
|
|
47
|
-
import { createRoot } from 'react-dom/client'
|
|
48
|
-
|
|
49
|
-
import { Page } from "${filePath.replace(/\\/g, '\\\\')}";
|
|
50
|
-
|
|
51
|
-
createRoot(document.getElementById('root')!).render(
|
|
52
|
-
<StrictMode>
|
|
53
|
-
<Page />
|
|
54
|
-
</StrictMode>
|
|
55
|
-
)`
|
|
56
|
-
|
|
57
|
-
return script
|
|
58
|
-
}
|
|
59
|
-
return null
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export const spaClientConfig = (filePath: string): InlineConfig => {
|
|
65
|
-
return {
|
|
66
|
-
logLevel: 'error',
|
|
67
|
-
plugins: [
|
|
68
|
-
jsSpa({
|
|
69
|
-
filePath
|
|
70
|
-
}),
|
|
71
|
-
tailwindcss()
|
|
72
|
-
],
|
|
73
|
-
build: {
|
|
74
|
-
outDir: '/tmp'
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { basename, extname } from 'path'
|
|
2
|
-
import type { InlineConfig, Plugin, UserConfig } from 'vite'
|
|
3
|
-
import react from '@vitejs/plugin-react'
|
|
4
|
-
import tailwindcss from '@tailwindcss/vite'
|
|
5
|
-
|
|
6
|
-
import type { PluginOptions } from '../../types'
|
|
7
|
-
|
|
8
|
-
const jsClientSsr = ({ filePath }: PluginOptions): Plugin => {
|
|
9
|
-
const entry = basename(filePath, extname(filePath))
|
|
10
|
-
const virtualPrefix = `virtual:ssr/${entry}.tsx`
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
name: 'nulljs-ssr-client-plugin',
|
|
14
|
-
apply: 'build',
|
|
15
|
-
config: async (config: UserConfig, { command }) => {
|
|
16
|
-
if (command !== 'build') {
|
|
17
|
-
return config
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return {
|
|
21
|
-
build: {
|
|
22
|
-
rollupOptions: {
|
|
23
|
-
input: {
|
|
24
|
-
[entry]: virtualPrefix
|
|
25
|
-
},
|
|
26
|
-
external: ['cloud'],
|
|
27
|
-
output: {
|
|
28
|
-
entryFileNames: '[name].js'
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
plugins: [react()]
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
resolveId: (id: string) => {
|
|
37
|
-
if (id === virtualPrefix) {
|
|
38
|
-
return id
|
|
39
|
-
}
|
|
40
|
-
return null
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
load: (id: string) => {
|
|
44
|
-
if (id === virtualPrefix) {
|
|
45
|
-
const script = `
|
|
46
|
-
import { StrictMode } from 'react'
|
|
47
|
-
import { hydrateRoot } from "react-dom/client";
|
|
48
|
-
import { Page } from "${filePath.replace(/\\/g, '\\\\')}";
|
|
49
|
-
|
|
50
|
-
const domNode = document.getElementById("root");
|
|
51
|
-
if (domNode) {
|
|
52
|
-
const initialProps = window.__INITIAL_PROPS__ || {};
|
|
53
|
-
|
|
54
|
-
hydrateRoot(
|
|
55
|
-
domNode,
|
|
56
|
-
<StrictMode>
|
|
57
|
-
<Page {...initialProps} />
|
|
58
|
-
</StrictMode>,
|
|
59
|
-
)
|
|
60
|
-
}`
|
|
61
|
-
|
|
62
|
-
return script
|
|
63
|
-
}
|
|
64
|
-
return null
|
|
65
|
-
},
|
|
66
|
-
|
|
67
|
-
generateBundle(_, bundle) {
|
|
68
|
-
Object.keys(bundle).forEach((fileName) => {
|
|
69
|
-
const chunk = bundle[fileName]
|
|
70
|
-
if (chunk.type === 'chunk') {
|
|
71
|
-
chunk.code = chunk.code.replace(/import\s+.*?\s+from\s+['"]cloud['"];?\s*/g, '')
|
|
72
|
-
chunk.code = chunk.code.replace('import"cloud";', '')
|
|
73
|
-
chunk.code = chunk.code.replace(/require\(['"]cloud['"]\);?\s*/g, '')
|
|
74
|
-
}
|
|
75
|
-
})
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export const ssrClientConfig = (filePath: string): InlineConfig => {
|
|
81
|
-
return {
|
|
82
|
-
logLevel: 'error',
|
|
83
|
-
plugins: [
|
|
84
|
-
jsClientSsr({
|
|
85
|
-
filePath
|
|
86
|
-
}),
|
|
87
|
-
tailwindcss()
|
|
88
|
-
],
|
|
89
|
-
build: {
|
|
90
|
-
outDir: '/tmp'
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import type { InlineConfig, Plugin, UserConfig } from 'vite'
|
|
3
|
-
import { external } from '../../external'
|
|
4
|
-
|
|
5
|
-
import type { PluginOptions } from '../../types'
|
|
6
|
-
|
|
7
|
-
const jsConfigSsr = ({ filePath }: PluginOptions): Plugin => {
|
|
8
|
-
const entry = path.basename(filePath, path.extname(filePath))
|
|
9
|
-
const virtualPrefix = `virtual:ssr/${entry}.ts`
|
|
10
|
-
|
|
11
|
-
return {
|
|
12
|
-
name: 'nulljs-ssr-props-plugin',
|
|
13
|
-
apply: 'build',
|
|
14
|
-
config: async (config: UserConfig, { command }) => {
|
|
15
|
-
if (command !== 'build') {
|
|
16
|
-
return config
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return {
|
|
20
|
-
build: {
|
|
21
|
-
ssr: true,
|
|
22
|
-
rollupOptions: {
|
|
23
|
-
input: {
|
|
24
|
-
[entry]: virtualPrefix
|
|
25
|
-
},
|
|
26
|
-
external: [...external, 'react', 'react/jsx-runtime'],
|
|
27
|
-
output: {
|
|
28
|
-
entryFileNames: '[name].js'
|
|
29
|
-
},
|
|
30
|
-
preserveEntrySignatures: 'strict'
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
resolveId: (id: string) => {
|
|
37
|
-
if (id === virtualPrefix) {
|
|
38
|
-
return id
|
|
39
|
-
}
|
|
40
|
-
return null
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
load: (id: string) => {
|
|
44
|
-
if (id === virtualPrefix) {
|
|
45
|
-
const script = `
|
|
46
|
-
import { config } from "${filePath.replace(/\\/g, '\\\\')}";
|
|
47
|
-
|
|
48
|
-
export default config;
|
|
49
|
-
`
|
|
50
|
-
|
|
51
|
-
return script
|
|
52
|
-
}
|
|
53
|
-
return null
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
transform: (code, id) => {
|
|
57
|
-
if (id === filePath) {
|
|
58
|
-
const configMatch = code.match(/export const config = \{[^}]*\};/)
|
|
59
|
-
return configMatch ? { code: configMatch[0], map: null } : null
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export const ssrConfigConfig = (filePath: string): InlineConfig => {
|
|
66
|
-
return {
|
|
67
|
-
logLevel: 'error',
|
|
68
|
-
plugins: [
|
|
69
|
-
jsConfigSsr({
|
|
70
|
-
filePath
|
|
71
|
-
})
|
|
72
|
-
],
|
|
73
|
-
build: {
|
|
74
|
-
outDir: '/tmp'
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import type { InlineConfig, Plugin, UserConfig } from 'vite'
|
|
3
|
-
import react from '@vitejs/plugin-react-swc'
|
|
4
|
-
|
|
5
|
-
import type { PluginOptions } from '../../types'
|
|
6
|
-
import { external } from '../../external'
|
|
7
|
-
|
|
8
|
-
const jsPagesSsr = ({ filePath }: PluginOptions): Plugin => {
|
|
9
|
-
const entry = path.basename(filePath, path.extname(filePath))
|
|
10
|
-
const virtualPrefix = `virtual:ssr/${entry}.ts`
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
name: 'nulljs-ssr-server-plugin',
|
|
14
|
-
apply: 'build',
|
|
15
|
-
config: async (config: UserConfig, { command }) => {
|
|
16
|
-
if (command !== 'build') {
|
|
17
|
-
return config
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return {
|
|
21
|
-
build: {
|
|
22
|
-
ssr: true,
|
|
23
|
-
rollupOptions: {
|
|
24
|
-
input: {
|
|
25
|
-
[entry]: virtualPrefix
|
|
26
|
-
},
|
|
27
|
-
external,
|
|
28
|
-
output: {
|
|
29
|
-
entryFileNames: '[name].js'
|
|
30
|
-
},
|
|
31
|
-
preserveEntrySignatures: 'strict'
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
resolveId: (id: string) => {
|
|
38
|
-
if (id === virtualPrefix) {
|
|
39
|
-
return id
|
|
40
|
-
}
|
|
41
|
-
return null
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
load: (id: string) => {
|
|
45
|
-
if (id === virtualPrefix) {
|
|
46
|
-
const script = `
|
|
47
|
-
import { props } from "${filePath.replace(/\\/g, '\\\\')}";
|
|
48
|
-
|
|
49
|
-
export { props }
|
|
50
|
-
`
|
|
51
|
-
|
|
52
|
-
return script
|
|
53
|
-
}
|
|
54
|
-
return null
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export const ssrPropsConfig = (filePath: string): InlineConfig => {
|
|
60
|
-
return {
|
|
61
|
-
logLevel: 'error',
|
|
62
|
-
plugins: [
|
|
63
|
-
jsPagesSsr({
|
|
64
|
-
filePath
|
|
65
|
-
})
|
|
66
|
-
],
|
|
67
|
-
build: {
|
|
68
|
-
outDir: '/tmp'
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import path from 'path'
|
|
2
|
-
import type { InlineConfig, Plugin, UserConfig } from 'vite'
|
|
3
|
-
import react from '@vitejs/plugin-react-swc'
|
|
4
|
-
|
|
5
|
-
import type { PluginOptions } from '../../types'
|
|
6
|
-
import { external } from '../../external'
|
|
7
|
-
|
|
8
|
-
const jsPagesSsr = ({ filePath }: PluginOptions): Plugin => {
|
|
9
|
-
const entry = path.basename(filePath, path.extname(filePath))
|
|
10
|
-
const virtualPrefix = `virtual:ssr/${entry}.tsx`
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
name: 'nulljs-ssr-server-plugin',
|
|
14
|
-
apply: 'build',
|
|
15
|
-
config: async (config: UserConfig, { command }) => {
|
|
16
|
-
if (command !== 'build') {
|
|
17
|
-
return config
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return {
|
|
21
|
-
build: {
|
|
22
|
-
ssr: true,
|
|
23
|
-
rollupOptions: {
|
|
24
|
-
input: {
|
|
25
|
-
[entry]: virtualPrefix
|
|
26
|
-
},
|
|
27
|
-
external,
|
|
28
|
-
output: {
|
|
29
|
-
format: 'iife',
|
|
30
|
-
entryFileNames: '[name].js'
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
ssr: {
|
|
35
|
-
target: 'webworker',
|
|
36
|
-
noExternal: true
|
|
37
|
-
},
|
|
38
|
-
plugins: [react()]
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
resolveId: (id: string) => {
|
|
43
|
-
if (id === virtualPrefix) {
|
|
44
|
-
return id
|
|
45
|
-
}
|
|
46
|
-
return null
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
load: (id: string) => {
|
|
50
|
-
if (id === virtualPrefix) {
|
|
51
|
-
const script = `
|
|
52
|
-
import "fast-text-encoding";
|
|
53
|
-
import React from "react";
|
|
54
|
-
import { renderToString } from "react-dom/server";
|
|
55
|
-
import { Page } from "${filePath.replace(/\\/g, '\\\\')}";
|
|
56
|
-
|
|
57
|
-
export const Index = (props) => {
|
|
58
|
-
const p = props ? JSON.parse(props) : {};
|
|
59
|
-
|
|
60
|
-
return renderToString(<Page {...p} />);
|
|
61
|
-
}
|
|
62
|
-
`
|
|
63
|
-
|
|
64
|
-
return script
|
|
65
|
-
}
|
|
66
|
-
return null
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export const ssrServerConfig = (filePath: string): InlineConfig => {
|
|
72
|
-
return {
|
|
73
|
-
logLevel: 'error',
|
|
74
|
-
plugins: [
|
|
75
|
-
jsPagesSsr({
|
|
76
|
-
filePath
|
|
77
|
-
})
|
|
78
|
-
],
|
|
79
|
-
build: {
|
|
80
|
-
outDir: '/tmp'
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|