vaderjs 1.4.2-bml56 → 1.4.2-jpiml56

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,235 +1 @@
1
- /**
2
- * @fileoverview - A simple router for vaderjs - Kuai
3
- * @version - 1.0.0
4
- */
5
- export class Kuai{
6
- constructor(config = { container: '#app'}){
7
- this.routes = [];
8
- this.middleware = [];
9
- this.container = config.container ? config.container : document.getElementById('app');
10
- this.renderPlugins = [];
11
- }
12
-
13
- res = {
14
- /**
15
- * @description render text to the container
16
- * @param {string} data
17
- */
18
- text: (data) => {
19
- this.container.innerHTML = data;
20
- },
21
- /**
22
- * @method html
23
- * @description render html to the container
24
- * @param {any} data
25
- * @returns
26
- */
27
- html: (data) => {
28
- switch(typeof data){
29
- case 'function':
30
- if(this.renderPlugins.length > 0){
31
- this.renderPlugins.forEach((plugin) => {
32
- if(plugin.for === 'html'){
33
- console.log('Plugin', plugin)
34
- plugin.plugin(data, this.container)
35
- }
36
- })
37
- return;
38
- }
39
- this.container.innerHTML = data();
40
- break;
41
- case 'string':
42
- this.container.innerHTML = data;
43
- break;
44
- }
45
-
46
- },
47
- /**
48
- * @method json
49
- * @description render json to the container
50
- * @param {Object} data
51
- */
52
- json: (data) => {
53
- this.container.innerHTML = `<Oject data=${JSON.stringify(data)}></Object>`
54
- }
55
- }
56
- req = {
57
- /**
58
- * @method navigate
59
- * @description - navigate to a new route
60
- * @param {string} path
61
- */
62
- navigate: (path) => {
63
- window.history.pushState({}, '', path);
64
- let currentPath = this.match(window.location.pathname.replace('/index.html', ''))
65
- if(currentPath){
66
- this.currentRoute = currentPath.path
67
- currentPath.callback(this.res, currentPath.params, this.extractQueryParams(window.location.search));
68
- }
69
- },
70
- /**
71
- * @method back
72
- * @description - go back to the previous route
73
- */
74
- back: () => {
75
- window.history.back();
76
- },
77
-
78
- /**
79
- * @method forward
80
- * @description - go forward to the next route
81
- * @returns {void}
82
- * **/
83
- forward: () => {
84
- window.history.forward();
85
- },
86
- url: window.location
87
- }
88
- /**
89
- * @private
90
- */
91
- extractQueryParams(path){
92
- let params = new URLSearchParams(path);
93
- let query = {};
94
- for(let param of params){
95
- query[param[0]] = param[1];
96
- }
97
- return query;
98
- }
99
- /**
100
- * @private
101
- */
102
- extractParams(routePath, currentPath){
103
- const routeParts = routePath.split('/').filter((part) => part !== '');
104
- const hashParts = currentPath.split('/').filter((part) => part !== '');
105
- const params = {};
106
- routeParts.forEach((part, index) => {
107
- if (part.startsWith(':')) {
108
- const paramName = part.slice(1);
109
- params[paramName] = hashParts[index];
110
- }else if(part.startsWith('*')){
111
- let array = hashParts.slice(index)
112
- array.forEach((i, index)=>{
113
- params[index] = i
114
- })
115
- };
116
- });
117
- return params;
118
- }
119
- use(path, middleware){
120
- this.middleware.push({path, middleware});
121
- }
122
- /**
123
- * @method usePlugin
124
- * @description - add a plugin to handle how the route should be rendered
125
- * @param {Function} plugin
126
- * @param {('html')} method
127
- */
128
- usePlugin(plugin, method){
129
- this.renderPlugins.push({plugin, for: method})
130
- }
131
- /**
132
- * @method match
133
- * @description - match a route to the current path and return the route object
134
- * @param {string} route
135
- * @returns {Object} - {path: string, callback: Function, params: Object}
136
- */
137
- match(hash){
138
- hash = hash.endsWith('/') ? hash.slice(0, -1) : hash;
139
- hash.includes('index.html') ? hash = hash.replace('index.html', '') : null;
140
- if(hash.includes('?')){
141
- hash = hash.split('?')[0]
142
- }
143
- let route = this.routes.find((route) => {
144
- if (route.path === hash) {
145
- return true;
146
- }
147
-
148
- if(hash === '' && route.path === '/'){
149
- return true
150
- }
151
-
152
-
153
- if (route.path.includes('*') || route.path.includes(':')) {
154
- const routeParts = route.path.split('/').filter((part) => part !== '');
155
- const hashParts = hash.split('/').filter((part) => part !== '');
156
- if(this.basePath){
157
- hashParts.shift();
158
- }
159
- if (routeParts.length !== hashParts.length && !route.path.endsWith('*')) {
160
- return false;
161
- }
162
-
163
- for (let index = 0; index < routeParts.length; index++) {
164
- const routePart = routeParts[index];
165
- const hashPart = hashParts[index];
166
-
167
-
168
- if (routePart.startsWith(':') || routePart.startsWith('*')) {
169
-
170
- continue;
171
- }
172
-
173
- if (routePart !== hashPart) {
174
- return false;
175
- }
176
- }
177
-
178
-
179
- return true;
180
- }
181
-
182
- });
183
- if(route){
184
- let params = this.extractParams(route.path, hash)
185
- return { ...route, params}
186
- }
187
- return null;
188
-
189
- }
190
-
191
- /**
192
- * @description - create a new route
193
- * @param {string} path
194
- * @param {Function} callback
195
- */
196
- get(path, callback){
197
- this.routes.push({path, callback});
198
- }
199
-
200
- /**
201
- * @method listen
202
- * @description - listen for route changes
203
- */
204
- listen(){
205
- let currentPath = this.match(window.location.pathname.replace('/index.html', ''))
206
- if(currentPath){
207
- this.middleware.forEach((middleware) => {
208
- if(middleware.path === currentPath.path){
209
- middleware.middleware();
210
- }
211
- });
212
- this.currentRoute = currentPath.path
213
- let obj = {
214
- ...this.res,
215
- res: this.res,
216
- req:{
217
- ...this.req,
218
- params: (param) => currentPath.params[param]
219
-
220
- }
221
- }
222
- currentPath.callback(obj);
223
- }
224
- window.onpopstate = () => {
225
- let currentPath = this.match(window.location.pathname.replace('/index.html', ''))
226
- if(currentPath){
227
- this.currentRoute = currentPath.path
228
- currentPath.callback(this.res, currentPath.params, this.extractQueryParams(window.location.search));
229
- }
230
- }
231
-
232
- }
233
- }
234
-
235
- export default Kuai;
1
+ export class Kuai{constructor(t={container:"#app"}){this.routes=[],this.middleware=[],this.container=t.container?t.container:document.getElementById("app"),this.renderPlugins=[]}res={text:t=>{this.container.innerHTML=t},html:t=>{switch(typeof t){case"function":if(this.renderPlugins.length>0)return void this.renderPlugins.forEach((e=>{"html"===e.for&&(console.log("Plugin",e),e.plugin(t,this.container))}));this.container.innerHTML=t();break;case"string":this.container.innerHTML=t}},json:t=>{this.container.innerHTML=`<Oject data=${JSON.stringify(t)}></Object>`}};req={navigate:t=>{window.history.pushState({},"",t);let e=this.match(window.location.pathname.replace("/index.html",""));e&&(this.currentRoute=e.path,e.callback(this.res,e.params,this.extractQueryParams(window.location.search)))},back:()=>{window.history.back()},forward:()=>{window.history.forward()},url:window.location};extractQueryParams(t){let e=new URLSearchParams(t),i={};for(let t of e)i[t[0]]=t[1];return i}extractParams(t,e){const i=t.split("/").filter((t=>""!==t)),r=e.split("/").filter((t=>""!==t)),a={};return i.forEach(((t,e)=>{if(t.startsWith(":")){const i=t.slice(1);a[i]=r[e]}else if(t.startsWith("*")){r.slice(e).forEach(((t,e)=>{a[e]=t}))}})),a}use(t,e){this.middleware.push({path:t,middleware:e})}usePlugin(t,e){this.renderPlugins.push({plugin:t,for:e})}match(t){(t=t.endsWith("/")?t.slice(0,-1):t).includes("index.html")&&(t=t.replace("index.html","")),t.includes("?")&&(t=t.split("?")[0]);let e=this.routes.find((e=>{if(e.path===t)return!0;if(""===t&&"/"===e.path)return!0;if(e.path.includes("*")||e.path.includes(":")){const i=e.path.split("/").filter((t=>""!==t)),r=t.split("/").filter((t=>""!==t));if(this.basePath&&r.shift(),i.length!==r.length&&!e.path.endsWith("*"))return!1;for(let t=0;t<i.length;t++){const e=i[t],a=r[t];if(!e.startsWith(":")&&!e.startsWith("*")&&e!==a)return!1}return!0}}));if(e){let i=this.extractParams(e.path,t);return{...e,params:i}}return null}get(t,e){this.routes.push({path:t,callback:e})}listen(){let t=this.match(window.location.pathname.replace("/index.html",""));if(t){this.middleware.forEach((e=>{e.path===t.path&&e.middleware()})),this.currentRoute=t.path;let e={...this.res,res:this.res,req:{...this.req,params:e=>t.params[e]}};t.callback(e)}window.onpopstate=()=>{let t=this.match(window.location.pathname.replace("/index.html",""));t&&(this.currentRoute=t.path,t.callback(this.res,t.params,this.extractQueryParams(window.location.search)))}}}export default Kuai;
@@ -11,38 +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]
42
+ if(typeof file === 'object'){
43
+ file = file.file
44
+ }
18
45
  let comp = require(file).default
19
46
  if(!comp){
20
47
  continue;
21
- }
22
- let document = new Document()
23
- let div = document.createElement('div')
24
- div.setAttribute('id', 'root')
25
- let dom = await renderToString(comp)
26
- div.setContent(dom)
27
- dom = div.toString("outerHTML")
48
+ }
49
+
50
+ let dom = await renderToString(comp)
51
+ let isHtml = dom.includes('<html')
28
52
  let folder = path.split('/pages')[0]
29
53
  let newPath = process.cwd() + '/build' + folder + '/index.html'
30
54
  let name = comp.name || 'App'
31
55
  file = file.replace(/\\/g, '/').replace('\/\/', '/').replace(process.cwd().replace(/\\/g, '/'), '').split('/pages')[1].replace('.tsx', '.js').replace('.jsx', '.js')
32
- let isParamRoute = path.includes('[')
56
+ let isParamRoute = routes[i].params ? true : false
33
57
  let baseFolder = ''
34
58
  if(isParamRoute){
35
- baseFolder = path.split('[')[0]
59
+ let route = routes[i].params[0]
60
+ baseFolder = i.split('[')[0]
36
61
  let providerPath;
37
62
  switch(true){
38
63
  case provider === 'vercel':
39
- providerPath = `${baseFolder}:${path.split('[')[1].split(']')[0]}`
40
- 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: `/`})
41
71
  break;
42
72
  case provider === 'nginx':
43
73
  providerPath = `RewriteRule ^${baseFolder.replace('/', '')}.*$ ${path}/index.html [L]`
44
74
  providerRoutes.push(providerPath)
45
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;
46
85
  }
47
86
  }else{
48
87
  let providerPath;
@@ -58,17 +97,48 @@ async function generate(){
58
97
  providerPath = `RewriteRule ^${path.replace('/', '')}/$ ${path}/index.html [L]`
59
98
  providerRoutes.push(providerPath)
60
99
  break;
100
+
61
101
 
62
102
  }
63
- }
64
- dom = dom + `
65
- <script type="module">
103
+ }
104
+ dom = preRender ? dom : '<div id="root"></div>' + `
105
+ <script type="module">
106
+
66
107
  import { render } from '/src/client.js'
67
- 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
+ }
68
115
  import Kuai from '/src/router.js'
69
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
+ }
70
138
  kuai.get('${path}', (c) => {
71
- render(${name}, document.getElementById('root'), c.req, c.res)
139
+ render(${name}, ${
140
+ isHtml ? `document.documentElement`: `document.body.firstChild`
141
+ }, c.req, c.res)
72
142
  })
73
143
 
74
144
  kuai.listen()
@@ -103,7 +173,7 @@ Header add x-powered-by "vaderjs"
103
173
  </IfModule>
104
174
  `
105
175
  fs.writeFileSync(process.cwd() + '/.htaccess', full)
106
- break;
176
+ break;
107
177
  }
108
178
  console.log(`\x1b[32mSuccess\x1b[0m - Static files generated`)
109
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
@@ -48,7 +48,21 @@ class Component {
48
48
 
49
49
  }
50
50
  export async function renderToString(element, args = []) {
51
- let data = typeof element === 'function' ? await element(args) : element
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