vaderjs 1.4.2-kml56 → 1.4.2-npiml56

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.
@@ -1,5 +1,5 @@
1
1
  import * as Bun from 'bun'
2
- import { Element, Document, DOMParser} from 'vaderjs/binaries/Kalix/index.js'
2
+ import { Document, DOMParser} from 'vaderjs/binaries/Kalix/index.js'
3
3
  import { renderToString } from '../../server'
4
4
  import fs from 'fs'
5
5
  let routes = new Bun.FileSystemRouter({
@@ -11,35 +11,77 @@ async function generate(){
11
11
  let config = await import(process.cwd() + '/vader.config.js').then((config) => { return config.default })
12
12
  let provider = config?.host?.provider
13
13
 
14
- let providerRoutes = []
14
+ let providerRoutes = []
15
+ Object.keys(routes).map((route) => {
16
+ if(route.includes('[')){
17
+
18
+ let root = Object.keys(routes).find((r) => {
19
+ return r === '/'
20
+ } )
21
+
22
+
23
+ let param = route.split('/[')[1].split(']')[0]
24
+ let p = {}
25
+ let existingParams = routes[root]?.params || []
26
+ existingParams.push({
27
+ isCatchAll: route.includes('[[catchall]]') ? true : false,
28
+ name: param,
29
+ file: routes[route],
30
+ baseFolder: route.split('[')[0]
31
+ })
32
+ p.file = routes[root]
33
+ p.params = existingParams
34
+ routes[root] = p
35
+ delete routes[route]
36
+
37
+ }
38
+ })
15
39
  for(var i in routes){
16
- let path = i
40
+ let path = i
17
41
  let file = routes[i]
18
- let comp = require(file).default
19
- let document = new Document()
20
- let div = document.createElement('div')
21
- div.setAttribute('id', 'root')
22
- let dom = await renderToString(comp)
23
- div.setContent(dom)
24
- dom = div.toString("outerHTML")
42
+ if(typeof file === 'object'){
43
+ file = file.file
44
+ }
45
+ let comp = require(file).default
46
+ if(!comp){
47
+ continue;
48
+ }
49
+
50
+ let dom = await renderToString(comp)
51
+ let isHtml = dom.includes('<html')
25
52
  let folder = path.split('/pages')[0]
26
53
  let newPath = process.cwd() + '/build' + folder + '/index.html'
27
- let name = comp.name
54
+ let name = comp.name || 'App'
28
55
  file = file.replace(/\\/g, '/').replace('\/\/', '/').replace(process.cwd().replace(/\\/g, '/'), '').split('/pages')[1].replace('.tsx', '.js').replace('.jsx', '.js')
29
- let isParamRoute = path.includes('[')
56
+ let isParamRoute = routes[i].params ? true : false
30
57
  let baseFolder = ''
31
58
  if(isParamRoute){
32
- baseFolder = path.split('[')[0]
59
+ let route = routes[i].params[0]
60
+ baseFolder = i.split('[')[0]
33
61
  let providerPath;
34
62
  switch(true){
35
63
  case provider === 'vercel':
36
- providerPath = `${baseFolder}:${path.split('[')[1].split(']')[0]}`
37
- providerRoutes.push({source: providerPath, dest: `${path}/index.html`})
64
+ if(route.isCatchAll){
65
+ providerPath = `${baseFolder}/*`
66
+ providerRoutes.push({source: providerPath, destination: `${path}/index.html`})
67
+ break;
68
+ }
69
+ providerPath = `${baseFolder}:${route.name}`
70
+ providerRoutes.push({source: providerPath, dest: `/`})
38
71
  break;
39
72
  case provider === 'nginx':
40
73
  providerPath = `RewriteRule ^${baseFolder.replace('/', '')}.*$ ${path}/index.html [L]`
41
74
  providerRoutes.push(providerPath)
42
75
  break;
76
+ case provider === 'cloudflare':
77
+ if(route.isCatchAll){
78
+ providerPath = `${baseFolder}/*`
79
+ providerRoutes.push({source: providerPath, destination: `${path}/index.html`})
80
+ break;
81
+ }
82
+ providerPath = `${baseFolder}/*`
83
+ providerRoutes.push({source: providerPath, destination: `${path}/index.html`})
84
+ break;
43
85
  }
44
86
  }else{
45
87
  let providerPath;
@@ -55,17 +97,48 @@ async function generate(){
55
97
  providerPath = `RewriteRule ^${path.replace('/', '')}/$ ${path}/index.html [L]`
56
98
  providerRoutes.push(providerPath)
57
99
  break;
100
+
58
101
 
59
102
  }
60
- }
61
- dom = dom + `
62
- <script type="module">
103
+ }
104
+ dom = preRender ? dom : '<div id="root"></div>' + `
105
+ <script type="module">
106
+
63
107
  import { render } from '/src/client.js'
64
- import ${name} from '/pages/${file.replace(process.cwd(), '')}'
108
+ let ${name} = await import('/pages/${file.replace(process.cwd(), '')}')
109
+ if(${name}.default){
110
+ ${name} = ${name}.default
111
+ }else{
112
+ let keys = Object.keys(${name})
113
+ ${name} = ${name}[keys[0]]
114
+ }
65
115
  import Kuai from '/src/router.js'
66
116
  let kuai = new Kuai()
117
+ ${
118
+ routes[i].params ?
119
+ routes[i].params.map((param) => {
120
+ let name = param.name
121
+ let file = param.file.replace(/\\/g, '/').replace('\/\/', '/').replace(process.cwd().replace(/\\/g, '/'), '').split('/pages')[1].replace('.tsx', '.js').replace('.jsx', '.js')
122
+ return `
123
+ // handle if default or named
124
+ let ${name} = await import('/pages/${file}')
125
+ if(${name}.default){
126
+ ${name} = ${name}.default
127
+ }else{
128
+ let keys = Object.keys(${name})
129
+ ${name} = ${name}[keys[0]]
130
+ }
131
+ kuai.get('${param.baseFolder}:${name}', (c) => {
132
+ render(${name}, ${
133
+ isHtml ? `document.documentElement`: `document.body.firstChild`
134
+ }, c.req, c.res)
135
+ })`
136
+ }).join('\n') : ''
137
+ }
67
138
  kuai.get('${path}', (c) => {
68
- render(${name}, document.getElementById('root'), c.req, c.res)
139
+ render(${name}, ${
140
+ isHtml ? `document.documentElement`: `document.body.firstChild`
141
+ }, c.req, c.res)
69
142
  })
70
143
 
71
144
  kuai.listen()
@@ -100,7 +173,7 @@ Header add x-powered-by "vaderjs"
100
173
  </IfModule>
101
174
  `
102
175
  fs.writeFileSync(process.cwd() + '/.htaccess', full)
103
- break;
176
+ break;
104
177
  }
105
178
  console.log(`\x1b[32mSuccess\x1b[0m - Static files generated`)
106
179
 
@@ -0,0 +1,93 @@
1
+ //@ts-nocheck
2
+ function checkIFtailwindInstalled() {
3
+ try {
4
+ require.resolve('tailwindcss');
5
+ return true;
6
+ } catch (e) {
7
+ return false;
8
+ }
9
+ }
10
+
11
+
12
+ export default {
13
+ name: "tailwind",
14
+ description: "A plugin to install tailwindcss",
15
+ once: true,
16
+ init: async () => {
17
+ let config = require(process.cwd() + "/vader.config.js").default;
18
+ const fs = require("fs");
19
+ const path = require("path");
20
+ const { exec} = require("child_process");
21
+ const tailwindConfig = `
22
+ /** @type {import('tailwindcss').Config} */
23
+ module.exports = {
24
+ content: ['./src/**/*.{jsx,tsx,js,ts}', './pages/**/*.{jsx,tsx,js,ts}', './components/**/*.{jsx,tsx,js,ts}'],
25
+ theme: {
26
+ ${
27
+ config?.tailwind?.theme ? JSON.stringify(config.tailwind.theme, null, 2) : ``
28
+ }
29
+ },
30
+ plugins: [
31
+ ${
32
+ config?.tailwind?.plugins ? config?.tailwind?.plugins.map((plugin) => {
33
+ return `require('${plugin}')`
34
+ }).join(",") : ``
35
+ }
36
+ ]
37
+ }
38
+ `;
39
+ fs.writeFileSync(
40
+ path.join(process.cwd(), "tailwind.config.js"),
41
+ tailwindConfig
42
+ );
43
+ if (!checkIFtailwindInstalled()) {
44
+ console.log(`\x1b[36mwait \x1b[0m - installing tailwindcss & ${config?.tailwind?.plugins ? config?.tailwind?.plugins.length + " plugins" : ""} (First time only)`);
45
+ let npmPath = process.platform === "win32" ? "npm.cmd" : "npm";
46
+ Bun.spawnSync({
47
+ cmd: [npmPath, "install", "tailwindcss", "postcss", "autoprefixer" , ...config?.tailwind?.plugins || []],
48
+ cwd: process.cwd(),
49
+ stderr: "inherit",
50
+ })
51
+ console.log(`\x1b[32msuccess \x1b[0m - tailwindcss installed`)
52
+
53
+
54
+ const postcssConfig = `
55
+ module.exports = {
56
+ plugins: {
57
+ tailwindcss: {},
58
+ autoprefixer: {},
59
+ },
60
+ }
61
+ `;
62
+ fs.mkdirSync(path.join(process.cwd(), "src/public/styles"), {
63
+ recursive: true,
64
+ });
65
+ fs.writeFileSync(
66
+ path.join(process.cwd(), "src/public/styles/tailwind.css"),
67
+ `@import 'tailwindcss/base'; @import 'tailwindcss/components'; @import 'tailwindcss/utilities';`
68
+ );
69
+ fs.writeFileSync(
70
+ path.join(process.cwd(), "postcss.config.js"),
71
+ postcssConfig
72
+ );
73
+ }
74
+
75
+ if(!fs.existsSync(path.join(process.cwd(), "src/public/styles/tailwind.css"))){
76
+ fs.mkdirSync(path.join(process.cwd(), "src/public/styles"), {
77
+ recursive: true,
78
+ });
79
+ fs.writeFileSync(
80
+ path.join(process.cwd(), "src/public/styles/tailwind.css"),
81
+ `@import 'tailwindcss/base'; @import 'tailwindcss/components'; @import 'tailwindcss/utilities';`
82
+ );
83
+ }
84
+
85
+ let cmd = process.platform === "win32" ? "npx.cmd" : "npx";
86
+ Bun.spawn({
87
+ cmd: [ cmd, "tailwindcss", process.cwd() + '/tailwind.config.js' , "-i", "src/public/styles/tailwind.css", "-o", config?.tailwind?.output || "public/styles/tailwind.css", "--minify"],
88
+ cwd: process.cwd(),
89
+ stdin: "inherit",
90
+ stderr: "inherit",
91
+ });
92
+ },
93
+ }
package/router/index.ts CHANGED
@@ -56,7 +56,11 @@ function spawn_ssr_server(config: any ){
56
56
  let fileType = handleContentTypes(file)
57
57
  if(fs.existsSync(file)){
58
58
  let content = await Bun.file(file).text()
59
- return new Response(content, {status: 200, headers: {'Content-Type': fileType, 'x-powered-by': 'Vader'}})
59
+ let data = Buffer.from(content, 'utf-8');
60
+ const compressed = Bun.gzipSync(data);
61
+ return new Response(compressed, {status: 200, headers: {'Content-Type': fileType, 'x-powered-by': 'Vader',
62
+ 'Content-Encoding':'gzip',
63
+ ...config?.routes.find(route => route.pathname === "*" || route.pathname === url.pathname)?.headers}})
60
64
  }
61
65
  }
62
66
  let routeMatch = routesRouter.match(url.pathname)
@@ -76,6 +80,7 @@ function spawn_ssr_server(config: any ){
76
80
  if(response instanceof Response){
77
81
  // set x-powered-by header
78
82
  response.headers.set('x-powered-by', 'Vader')
83
+ response.headers.set('Content-Type', 'text/html')
79
84
  return response
80
85
  }
81
86
  throw new Error(`Route ${routeMatch.filePath.split('/routes')[1]} did not return a response in file ${routeMatch.filePath}`)
@@ -89,11 +94,12 @@ function spawn_ssr_server(config: any ){
89
94
  }
90
95
  }
91
96
  let server = Bun.serve({
92
- port: config.env.PORT || 3000,
93
- hostname: config.host.hostname || 'localhost',
97
+ port: config?.env?.PORT || 3000,
98
+ hostname: config?.host?.hostname || 'localhost',
94
99
  reusePort: true,
95
100
  lowMemoryMode: true,
96
101
  development: false,
102
+ ...(config?.Router?.tls && {tls: {cert: config.Router.tls.cert, key: config.Router.tls.key}}),
97
103
  websocket: {
98
104
  message(event){
99
105
 
@@ -137,21 +143,42 @@ function spawnServer(config: any){
137
143
  if(url.pathname.includes('.')){
138
144
  url.pathname = url.pathname.replace('/\/', '/')
139
145
  url.pathname = url.pathname.replace('/build/', '')
140
- if(url.pathname.includes('/build')){
141
- url.pathname = url.pathname.replace('/build', '')
142
- }
143
- let file = process.cwd() + '/build' + url.pathname
146
+
147
+ let file = process.cwd() + '/build' + url.pathname
144
148
  let fileType = handleContentTypes(file)
145
149
  if(fs.existsSync(file)){
146
150
  let content = await Bun.file(file).text()
147
- return new Response(content, {status: 200, headers: {'Content-Type': fileType, 'x-powered-by': 'Vader'}})
151
+ let data = Buffer.from(content, 'utf-8');
152
+ const compressed = Bun.gzipSync(data);
153
+
154
+ return new Response(compressed, {status: 200, headers: {'Content-Type': fileType, 'x-powered-by': 'Vader', 'x-powered-by': 'Vader',
155
+ 'Content-Encoding':'gzip',
156
+ 'Accept-Encoding': 'gzip, deflate, br','Connection': 'keep-alive', 'Cache-Control': 'no-cache', 'Pragma': 'no-cache', 'Expires': '0', ...config?.Router?.headers}})
148
157
  }
149
158
  }
150
159
  let route = router.match(url.pathname)
151
160
  if(route){
161
+ let isParamRoute = route.filePath.includes('[') && route.filePath.includes(']')
152
162
  let path = route.filePath.split('/pages')[1].replace('.jsx', '.js').replace('.tsx', '.js').replace('.ts', '.js')
163
+ path = isParamRoute ? 'index.html' : path
153
164
  let html = fs.readFileSync(process.cwd() + `/build/${path.replace('.js', '.html')}`).toString()
154
- return new Response(html, {status: 200, headers: {'Content-Type': 'text/html', 'x-powered-by': 'Vader'}})
165
+ html = html + `
166
+ <script>
167
+ let ws = new WebSocket('ws://${config.host.hostname || 'localhost'}:${config.env.PORT || 3000}')
168
+ ws.onmessage = function(event){
169
+ console.log(event.data)
170
+ }
171
+ ws.onclose = function(event){
172
+ window.location.reload()
173
+ }
174
+ </script>
175
+ `
176
+ const data = Buffer.from(html, 'utf-8');
177
+ const compressed = Bun.gzipSync(data);
178
+ return new Response(compressed, {status: 200, headers: {'Content-Type': 'text/html', 'x-powered-by': 'Vader',
179
+ 'Content-Encoding':'gzip',
180
+ 'Accept-Encoding': 'gzip, deflate, br','Connection': 'keep-alive', 'Cache-Control': 'no-cache', 'Pragma': 'no-cache', 'Expires': '0',
181
+ ...config?.Router?.headers}})
155
182
  }
156
183
  return new Response('Not Found', {status: 404})
157
184
  }
@@ -171,7 +198,7 @@ export default {
171
198
  if(!globalThis.isListening){
172
199
  let config = require(process.cwd() + '/vader.config.js').default
173
200
  if(process.env.mode === 'production'){
174
- console.log(`Listening at - http://${config.host.hostname}:${config.env.PORT}`)
201
+ console.log(`\x1b[32msuccess \x1b[0m- listening on port ${config.env.PORT || 3000}`)
175
202
  spawnServer(config)
176
203
  }
177
204
  config?.env?.SSR ? spawn_ssr_server(config ) : spawnServer(config)
package/server/index.js CHANGED
@@ -47,8 +47,22 @@ class Component {
47
47
  }
48
48
 
49
49
  }
50
- export async function renderToString(element, args = []) {
51
- let data = typeof element === 'function' ? await element(args) : element
50
+ export async function renderToString(element, args = []) {
51
+ globalThis.isServer = true
52
+ globalThis.preRender = true
53
+ let data = typeof element === 'function' ? await element(args) : element
54
+ if(data?.tagName === 'html'){
55
+ let body = data.querySelector('body') || new Document().createElement('body')
56
+ let innerHTML = body.innerHTML
57
+ innerHTML = `${innerHTML}`
58
+ body.tagName = 'div'
59
+ body.setAttribute('id', 'root')
60
+ body.innerHTML = innerHTML
61
+ data.removeChild(data.querySelector('body'))
62
+ data.appendChild(body)
63
+ }else if(data){
64
+ data.firstChild.setAttribute('id', 'root')
65
+ }
52
66
  let doc = new Document()
53
67
  let el = doc.createElement(data)
54
68
 
File without changes