vaderjs 1.4.3 → 1.4.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.
- package/index.ts +100 -61
- package/main.js +90 -20
- package/package.json +2 -2
package/index.ts
CHANGED
|
@@ -1,18 +1,43 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
1
2
|
let isClassComponent = function(element) {
|
|
2
3
|
return element.toString().startsWith("class");
|
|
3
4
|
};
|
|
4
5
|
|
|
6
|
+
const memoizes = new Map();
|
|
7
|
+
//@ts-ignore
|
|
8
|
+
|
|
5
9
|
declare global {
|
|
6
10
|
interface Window {
|
|
7
11
|
onbeforeunload: any;
|
|
8
12
|
localStorage: any;
|
|
9
13
|
sessionStorage: any;
|
|
14
|
+
state: any;
|
|
10
15
|
}
|
|
11
16
|
const genKey: any;
|
|
12
17
|
let isServer: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* @description - The params object is used to store the query parameters of the current URL
|
|
20
|
+
* @example
|
|
21
|
+
* // URL: https://example.com?name=John
|
|
22
|
+
* console.log(params.name) // John
|
|
23
|
+
* @example
|
|
24
|
+
* // URL: https://example.com/:name/:age
|
|
25
|
+
* // GO: https://example.com/John/20
|
|
26
|
+
* console.log(params.name) // John
|
|
27
|
+
* console.log(params.age) // 20
|
|
28
|
+
*/
|
|
29
|
+
let params: { [key: string]: string };
|
|
13
30
|
}
|
|
14
31
|
//@ts-ignore
|
|
15
32
|
globalThis.isServer = typeof window === "undefined";
|
|
33
|
+
//@ts-ignore
|
|
34
|
+
globalThis.params = {
|
|
35
|
+
[Symbol.iterator]: function* () {
|
|
36
|
+
for (const key in this) {
|
|
37
|
+
yield [key, this[key]];
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
};
|
|
16
41
|
|
|
17
42
|
|
|
18
43
|
/**
|
|
@@ -41,6 +66,17 @@ export const useEffect = (callback:any, dependencies: any[]) => {
|
|
|
41
66
|
}
|
|
42
67
|
}
|
|
43
68
|
|
|
69
|
+
function memoizeComponent(Component: any) {
|
|
70
|
+
let key = Component.toString();
|
|
71
|
+
if (memoizes.has(key)) {
|
|
72
|
+
return memoizes.get(key);
|
|
73
|
+
}
|
|
74
|
+
let instance = new Component();
|
|
75
|
+
memoizes.set(key, instance);
|
|
76
|
+
return instance;
|
|
77
|
+
|
|
78
|
+
}
|
|
79
|
+
|
|
44
80
|
/**
|
|
45
81
|
* @description - Create a new element
|
|
46
82
|
* @param element
|
|
@@ -63,20 +99,16 @@ export const e = (element: any, props: any, ...children: any[]) => {
|
|
|
63
99
|
* @param initialState
|
|
64
100
|
* @returns {state, (newState: any, Element: string) => void, key}
|
|
65
101
|
*/
|
|
66
|
-
export const useState = (
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
instance.setState({ [key]: newState }, Element);
|
|
76
|
-
}, key];
|
|
102
|
+
export const useState = <T>(initialState: T) => {
|
|
103
|
+
const setState = (newState: T, Element: string) => {
|
|
104
|
+
initialState = newState;
|
|
105
|
+
}
|
|
106
|
+
return [initialState, setState];
|
|
107
|
+
}
|
|
108
|
+
//@ts-ignore
|
|
109
|
+
if(!isServer){
|
|
110
|
+
window.state = {};
|
|
77
111
|
}
|
|
78
|
-
//@ts-ignore
|
|
79
|
-
let state = {};
|
|
80
112
|
export class Component {
|
|
81
113
|
props: any;
|
|
82
114
|
state: any;
|
|
@@ -88,21 +120,24 @@ export class Component {
|
|
|
88
120
|
constructor() {
|
|
89
121
|
this.key = Math.random().toString(36).substring(7);
|
|
90
122
|
this.props = {};
|
|
91
|
-
//@ts-ignore
|
|
92
|
-
|
|
93
|
-
|
|
123
|
+
//@ts-ignore
|
|
124
|
+
if(!isServer){
|
|
125
|
+
window.state[this.key] = {};
|
|
126
|
+
this.state = window.state[this.key];
|
|
127
|
+
}else{
|
|
128
|
+
this.state = {};
|
|
129
|
+
}
|
|
94
130
|
this.effect = [];
|
|
95
131
|
this.Mounted = false;
|
|
96
132
|
this.element = null;
|
|
97
133
|
}
|
|
98
134
|
setState(newState: any, Element: string) {
|
|
99
|
-
state[this.key] = { ...this.state, ...newState };
|
|
100
|
-
console.log(state[this.key]);
|
|
135
|
+
globalThis.window.state[this.key] = { ...this.state, ...newState };
|
|
101
136
|
this.forceUpdate(Element);
|
|
102
137
|
}
|
|
103
138
|
|
|
104
139
|
useEffect(callback: any, dependencies: any[]) {
|
|
105
|
-
if (dependencies.length === 0 && this.Mounted && this.effect.length === 0) {
|
|
140
|
+
if (dependencies.length === 0 && this.Mounted && this.effect.length === 0) {
|
|
106
141
|
callback();
|
|
107
142
|
this.effect.push(callback);
|
|
108
143
|
}else{
|
|
@@ -114,34 +149,26 @@ export class Component {
|
|
|
114
149
|
}
|
|
115
150
|
}
|
|
116
151
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
this.state[key] = initialState;
|
|
121
|
-
}
|
|
152
|
+
useState <T> (key: string, defaultValue: T) {
|
|
153
|
+
let value = sessionStorage.getItem("state_" + key) || defaultValue;
|
|
154
|
+
typeof value === "string" ? value = JSON.parse(value) : value;
|
|
122
155
|
|
|
123
|
-
window.onbeforeunload = ()
|
|
124
|
-
sessionStorage.
|
|
156
|
+
window.onbeforeunload = function() {
|
|
157
|
+
sessionStorage.removeItem("state_" + key);
|
|
158
|
+
}
|
|
159
|
+
const setValue = (newValue: T ,element: string) => {
|
|
160
|
+
value = newValue;
|
|
161
|
+
sessionStorage.setItem("state_" + key, JSON.stringify(value));
|
|
162
|
+
this.state[key] = value;
|
|
163
|
+
this.forceUpdate(element)
|
|
125
164
|
}
|
|
126
|
-
|
|
127
|
-
*
|
|
128
|
-
* @param {*} newState
|
|
129
|
-
* @param {*} Element - The element affected by the state change
|
|
130
|
-
*/
|
|
131
|
-
const setState = (newState, Element) => {
|
|
132
|
-
this.prevState = { ...this.state };
|
|
133
|
-
this.state[key] = newState;
|
|
134
|
-
state[this.key] = { ...this.state };
|
|
135
|
-
this.forceUpdate(Element);
|
|
136
|
-
};
|
|
137
|
-
const returnKey = key;
|
|
138
|
-
return [this.state[key], setState, returnKey];
|
|
165
|
+
return [value, setValue];
|
|
139
166
|
}
|
|
167
|
+
|
|
168
|
+
|
|
140
169
|
|
|
141
170
|
useFetch(url, options) {
|
|
142
|
-
const { key } = options;
|
|
143
|
-
|
|
144
|
-
console.log(key);
|
|
171
|
+
const { key } = options;
|
|
145
172
|
if (!key) {
|
|
146
173
|
throw new Error(`You must supply a key for the affected element in the options object`);
|
|
147
174
|
}
|
|
@@ -151,23 +178,23 @@ export class Component {
|
|
|
151
178
|
const dataKey = "_data" + url;
|
|
152
179
|
|
|
153
180
|
// Initialize loading to false if loadingKey doesn't exist in state
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
181
|
+
let [loading, setLoading] = this.useState(loadingKey, false);
|
|
182
|
+
let [error, setError] = this.useState(errorKey, null);
|
|
183
|
+
let [data, setData] = this.useState(dataKey, null);
|
|
157
184
|
|
|
158
185
|
if (loading && !error && !data) {
|
|
159
|
-
state[this.key][loadingKey] = true;
|
|
186
|
+
this.state[this.key][loadingKey] = true;
|
|
160
187
|
|
|
161
188
|
fetch(url, options)
|
|
162
189
|
.then((res) => res.json())
|
|
163
190
|
.then((data) => {
|
|
164
|
-
|
|
165
|
-
|
|
191
|
+
//@ts-ignore
|
|
192
|
+
setLoading(false, options.key);
|
|
193
|
+
setData(data, options.key);
|
|
166
194
|
this.forceUpdate(key);
|
|
167
195
|
})
|
|
168
196
|
.catch((err) => {
|
|
169
|
-
|
|
170
|
-
state[this.key][loadingKey] = false;
|
|
197
|
+
setError(err, options.key);
|
|
171
198
|
this.forceUpdate(key);
|
|
172
199
|
});
|
|
173
200
|
}
|
|
@@ -179,7 +206,7 @@ export class Component {
|
|
|
179
206
|
forceUpdate(key) {
|
|
180
207
|
//@ts-ignore
|
|
181
208
|
let el = Array.from(document.querySelectorAll("*")).filter((el2: any) =>{ return el2.key === key})[0];
|
|
182
|
-
let newl = this.parseToElement(this.render());
|
|
209
|
+
let newl = this.parseToElement(this.render());
|
|
183
210
|
if(newl.key !== key){
|
|
184
211
|
//@ts-ignore
|
|
185
212
|
newl = Array.from(newl.children).filter((el2) => el2.key === key)[0];
|
|
@@ -239,8 +266,7 @@ export class Component {
|
|
|
239
266
|
continue;
|
|
240
267
|
}
|
|
241
268
|
//@ts-ignore
|
|
242
|
-
if (key.startsWith("on")) {
|
|
243
|
-
console.log(key.substring(2).toLowerCase());
|
|
269
|
+
if (key.startsWith("on")) {
|
|
244
270
|
el.addEventListener(key.substring(2).toLowerCase(), attributes[key]);
|
|
245
271
|
continue;
|
|
246
272
|
}
|
|
@@ -281,8 +307,21 @@ export class Component {
|
|
|
281
307
|
render() {
|
|
282
308
|
return "";
|
|
283
309
|
}
|
|
310
|
+
|
|
311
|
+
|
|
284
312
|
}
|
|
285
313
|
|
|
314
|
+
function memoizeClassComponent(Component: any) {
|
|
315
|
+
let key = Component.toString();
|
|
316
|
+
if (memoizes.has(key)) {
|
|
317
|
+
return memoizes.get(key);
|
|
318
|
+
}
|
|
319
|
+
let instance = new Component();
|
|
320
|
+
memoizes.set(key, instance);
|
|
321
|
+
return instance;
|
|
322
|
+
|
|
323
|
+
}
|
|
324
|
+
|
|
286
325
|
export function render(element: any, container) {
|
|
287
326
|
if (isClassComponent(element)) {
|
|
288
327
|
const instance = new element();
|
|
@@ -292,14 +331,14 @@ export function render(element: any, container) {
|
|
|
292
331
|
container.innerHTML = "";
|
|
293
332
|
container.replaceWith(el);
|
|
294
333
|
} else {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
334
|
+
// memoizeComponent(element);
|
|
335
|
+
let memoizedInstance = memoizeClassComponent(Component);
|
|
336
|
+
memoizedInstance.Mounted = true;
|
|
337
|
+
memoizedInstance.render = element.bind(memoizedInstance);
|
|
338
|
+
let el = memoizedInstance.toElement();
|
|
339
|
+
container.innerHTML = "";
|
|
340
|
+
container.replaceWith(el);
|
|
341
|
+
|
|
303
342
|
}
|
|
304
343
|
}
|
|
305
344
|
|
package/main.js
CHANGED
|
@@ -24,7 +24,7 @@ if(!mode){
|
|
|
24
24
|
|
|
25
25
|
let start = Date.now()
|
|
26
26
|
console.log(`Starting build at ${new Date().toLocaleTimeString()}`)
|
|
27
|
-
let { port, host, } = require(process.cwd() + '/config').default
|
|
27
|
+
let { port, host, host_provider } = require(process.cwd() + '/config').default
|
|
28
28
|
|
|
29
29
|
if (!fs.existsSync(process.cwd() + '/jsconfig.json')) {
|
|
30
30
|
let json = {
|
|
@@ -96,21 +96,32 @@ const handleReplacements = (code, file) => {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
|
|
99
|
-
async function generateApp() {
|
|
99
|
+
async function generateApp() {
|
|
100
|
+
// remove files from dist
|
|
101
|
+
fs.rmdirSync(process.cwd() + '/dist', { recursive: true })
|
|
100
102
|
return new Promise(async (resolve, reject) => {
|
|
101
103
|
let routes = new Bun.FileSystemRouter({
|
|
102
104
|
dir: process.cwd() + '/app',
|
|
103
105
|
style: 'nextjs'
|
|
104
106
|
})
|
|
105
|
-
|
|
107
|
+
routes.reload()
|
|
108
|
+
globalThis.routes = routes.routes
|
|
106
109
|
Object.keys(routes.routes).forEach(async (route) => {
|
|
107
110
|
let r = routes.routes[route]
|
|
108
111
|
let code = await Bun.file(r).text()
|
|
109
112
|
code = handleReplacements(code)
|
|
110
113
|
r = r.replace(process.cwd().replace(/\\/g, '/') + '/app', '')
|
|
111
|
-
r = r.replace('.jsx', '.js')
|
|
112
|
-
fs.mkdirSync(path.dirname(process.cwd() + '/dist/' + r), { recursive: true })
|
|
113
|
-
fs.writeFileSync(process.cwd() + '/dist/' + r,
|
|
114
|
+
r = r.replace('.jsx', '.js')
|
|
115
|
+
fs.mkdirSync(path.dirname(process.cwd() + '/dist/' + r), { recursive: true })
|
|
116
|
+
fs.writeFileSync(process.cwd() + '/dist/' + path.dirname(r) + '/' + path.basename(r), `
|
|
117
|
+
let route = window.location.pathname.split('/').filter(v => v !== '')
|
|
118
|
+
let params = {
|
|
119
|
+
${Object.keys(routes.match(route).params || {}).length > 0 ? Object.keys(routes.match(route).params || {}) .map(p => {
|
|
120
|
+
return `${p}: route[${Object.keys(routes.match(route).params).indexOf(p) + 1}]`
|
|
121
|
+
}).join(',') : ""}
|
|
122
|
+
}
|
|
123
|
+
\n${code}
|
|
124
|
+
`)
|
|
114
125
|
fs.mkdirSync(process.cwd() + '/dev', { recursive: true })
|
|
115
126
|
fs.writeFileSync(path.join(process.cwd() + '/dev/bundler.js'), `
|
|
116
127
|
import { Component, e, useState, useEffect, useFetch, useAsyncState } from 'vaderjs'
|
|
@@ -134,14 +145,16 @@ async function generateApp() {
|
|
|
134
145
|
getElementById: (id) => {},
|
|
135
146
|
}
|
|
136
147
|
await Bun.build({
|
|
137
|
-
entrypoints: [process.
|
|
138
|
-
minify:true,
|
|
139
|
-
root:
|
|
140
|
-
outdir: process.cwd() + '/dist',
|
|
141
|
-
|
|
148
|
+
entrypoints: [process.env.ENTRYPOINT],
|
|
149
|
+
minify:true,
|
|
150
|
+
root: process.cwd() + '/dist/',
|
|
151
|
+
outdir: process.cwd() + '/dist/',
|
|
152
|
+
format: 'esm',
|
|
153
|
+
...(process.env.DEV ? { sourcemap: 'inline' } : {})
|
|
154
|
+
})
|
|
142
155
|
let isClass = function(element) {
|
|
143
156
|
return element.toString().startsWith('class');
|
|
144
|
-
};
|
|
157
|
+
};
|
|
145
158
|
const generatePage = async (data = {path: process.env.INPUT, route: process.env.OUT}) => {
|
|
146
159
|
const { path, route } = data
|
|
147
160
|
if(path.includes('root.js')) return
|
|
@@ -168,10 +181,10 @@ async function generateApp() {
|
|
|
168
181
|
let headHtml = ''
|
|
169
182
|
if(head){
|
|
170
183
|
headHtml = document(head())
|
|
171
|
-
}
|
|
184
|
+
}
|
|
172
185
|
Bun.write(process.cwd() + '/dist/' + route + '/index.html', \`<!DOCTYPE html><head>\${headHtml}</head>\${h}
|
|
173
186
|
<script type="module">
|
|
174
|
-
import c from '\${
|
|
187
|
+
import c from '\${process.env.filePath}'
|
|
175
188
|
import {render} from '/src/vader/index.js'
|
|
176
189
|
render(c, document.body.firstChild)
|
|
177
190
|
</script>
|
|
@@ -183,15 +196,20 @@ async function generateApp() {
|
|
|
183
196
|
fs.mkdirSync(process.cwd() + '/dist/src/vader', { recursive: true })
|
|
184
197
|
fs.writeFileSync(process.cwd() + '/dist/src/vader/index.js', await new Bun.Transpiler({
|
|
185
198
|
loader: 'ts',
|
|
186
|
-
|
|
199
|
+
minify: true,
|
|
200
|
+
}).transformSync(await Bun.file(require.resolve('vaderjs')).text()))
|
|
201
|
+
|
|
187
202
|
const spawn = Bun.spawn({
|
|
188
203
|
cmd: ['bun', 'run', './dev/bundler.js'],
|
|
189
204
|
cwd: process.cwd(),
|
|
190
205
|
stdout: 'inherit',
|
|
191
206
|
env: {
|
|
192
|
-
ENTRYPOINT: r,
|
|
207
|
+
ENTRYPOINT: path.join(process.cwd() + '/dist/' + path.dirname(r) + '/' + path.basename(r)),
|
|
193
208
|
ROOT: process.cwd() + '/app/',
|
|
194
|
-
OUT:
|
|
209
|
+
OUT: path.dirname(r),
|
|
210
|
+
file: process.cwd() + '/dist/' + path.dirname(r) + '/index.js',
|
|
211
|
+
DEV: mode === 'development',
|
|
212
|
+
filePath: r,
|
|
195
213
|
INPUT: `../app/${r.replace('.js', '.jsx')}`,
|
|
196
214
|
},
|
|
197
215
|
onExit({exitCode: code}) {
|
|
@@ -205,6 +223,44 @@ async function generateApp() {
|
|
|
205
223
|
})
|
|
206
224
|
|
|
207
225
|
})
|
|
226
|
+
|
|
227
|
+
switch(host_provider){
|
|
228
|
+
case 'vercel':
|
|
229
|
+
|
|
230
|
+
let vercelData = {
|
|
231
|
+
rewrites: []
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
for(let route in routes.routes){
|
|
235
|
+
let {filePath, kind, name, params, pathname,query} = routes.match(route)
|
|
236
|
+
let exists = vercelData.rewrites.find(v => v.source === `/${route}`)
|
|
237
|
+
let paramString = ''
|
|
238
|
+
if(pathname === '/'){
|
|
239
|
+
continue
|
|
240
|
+
}
|
|
241
|
+
if(params){
|
|
242
|
+
paramString = Object.keys(params).map(p => `:${p}`).join('/')
|
|
243
|
+
}
|
|
244
|
+
// replace double slashes
|
|
245
|
+
paramString = paramString.replace(/\/\//g, '/')
|
|
246
|
+
let base = path.dirname(route)
|
|
247
|
+
if(base.includes('[')){
|
|
248
|
+
base = base.split('[')[0].split('/').filter(v => v !== '').join('/')
|
|
249
|
+
}else{
|
|
250
|
+
base = base.split('/').filter(v => v !== '').join('/')
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if(!exists){
|
|
254
|
+
vercelData.rewrites.push({
|
|
255
|
+
source: `/${base}/${paramString}`,
|
|
256
|
+
destination: `${path.dirname(routes.routes[route]).replace(process.cwd().replace(/\\/g, '/') + '/app', '')}/index.html`
|
|
257
|
+
})
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
fs.writeFileSync(process.cwd() + '/vercel.json', JSON.stringify(vercelData, null, 4))
|
|
261
|
+
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
208
264
|
|
|
209
265
|
})
|
|
210
266
|
|
|
@@ -245,6 +301,8 @@ if(mode === 'development'){
|
|
|
245
301
|
watcher.on('change', async (event, filename) => {
|
|
246
302
|
try {
|
|
247
303
|
await generateApp()
|
|
304
|
+
|
|
305
|
+
handleFiles()
|
|
248
306
|
clients.forEach(c => {
|
|
249
307
|
c.send('reload')
|
|
250
308
|
})
|
|
@@ -289,14 +347,26 @@ if(mode === 'development'){
|
|
|
289
347
|
}
|
|
290
348
|
})
|
|
291
349
|
}
|
|
292
|
-
|
|
350
|
+
let router = new Bun.FileSystemRouter({
|
|
351
|
+
dir: process.cwd() + '/app',
|
|
352
|
+
style: 'nextjs'
|
|
353
|
+
})
|
|
354
|
+
router.reload()
|
|
355
|
+
let route = router.match(url.pathname)
|
|
356
|
+
if(!route){
|
|
357
|
+
return new Response('Not found', { status: 404 })
|
|
358
|
+
}
|
|
359
|
+
let p = route.pathname;
|
|
360
|
+
let base = path.dirname(route.filePath)
|
|
361
|
+
base = base.replace(path.join(process.cwd() + '/app'), '')
|
|
362
|
+
base = base.replace(/\\/g, '/').replace('/app', '/dist')
|
|
363
|
+
return new Response(await Bun.file(path.join(base, 'index.html')).text() + `
|
|
293
364
|
<script>
|
|
294
365
|
let ws = new WebSocket('ws://localhost:${server.port}')
|
|
295
366
|
ws.onmessage = (e) => {
|
|
296
367
|
if(e.data === 'reload'){
|
|
297
368
|
window.location.reload()
|
|
298
|
-
}
|
|
299
|
-
console.log(e.data)
|
|
369
|
+
}
|
|
300
370
|
}
|
|
301
371
|
</script>
|
|
302
372
|
`, {
|
package/package.json
CHANGED