vaderjs 1.3.6 → 1.3.7-alpha-1
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/README.md +167 -0
- package/logo.png +0 -0
- package/package.json +15 -23
- package/runtime/router.js +261 -0
- package/runtime/static/index.html +21 -0
- package/vader +0 -0
- package/.vscode/settings.json +0 -5
- package/.vscode/vaderjs.autosense.json +0 -5
- package/index.js +0 -12
- package/jsconfig.json +0 -17
- package/readme.md +0 -262
- package/ts.config.json +0 -1
- package/tsconfig.json +0 -18
- package/vader-min.js +0 -1
- package/vader.js +0 -1141
- package/vaderRouter.js +0 -231
- package/worker-min.js +0 -9
- package/worker.js +0 -325
package/README.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://vader-js.pages.dev">
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="/icon.jpeg">
|
|
5
|
+
<img src="logo.png" height="128">
|
|
6
|
+
</picture>
|
|
7
|
+
<h1 align="center">Vader.js</h1>
|
|
8
|
+
</a>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
# VaderJS: A Powerful Reactive Framework for SPAs inspired by react.js!
|
|
12
|
+
|
|
13
|
+
[](https://github.com/Postr-Inc/Vader.js/blob/main/LICENSE) [](https://www.npmjs.com/package/vaderjs)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## Get Started
|
|
18
|
+
|
|
19
|
+
1. Install Bun.js
|
|
20
|
+
|
|
21
|
+
Need more help? [Bun guide](https://bun.sh/docs/installation)
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
curl -fsSL https://bun.sh/install | bash # for macOS, Linux, and WSL
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
> Skip if you are not using windows!
|
|
28
|
+
[How to open folder in wsl](https://code.visualstudio.com/docs/remote/wsl)
|
|
29
|
+
|
|
30
|
+
1. Open a WSL terminal window (using the start menu item or by typing wsl from a command prompt / PowerShell).
|
|
31
|
+
|
|
32
|
+
2. Navigate to a folder you'd like to open in VS Code (including, but not limited to, Windows filesystem mounts like /mnt/c)
|
|
33
|
+
|
|
34
|
+
3. Type code . in the terminal. When doing this for the first time, you should see VS Code fetching components needed to run in WSL. This should only take a short while, and is only needed once.
|
|
35
|
+
|
|
36
|
+
Open folder in vsc - open terminal and type wsl then type `code .` and continue to the next step
|
|
37
|
+
|
|
38
|
+
2. Installing vaderjs
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm i vaderjs
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
3. Create Proper Folders
|
|
45
|
+
|
|
46
|
+
Create a pages folder - which allows you to have nextjs page like routing via buns file based router
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
/pages/index.jsx = /
|
|
50
|
+
/pages/home/[page].jsx = /home/:page
|
|
51
|
+
/pages/path/index.jsx = /path/file
|
|
52
|
+
```
|
|
53
|
+
Keyword folders - all files are passed from these folders to the `dist` folder
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
|
|
57
|
+
pages - used for jsx route files
|
|
58
|
+
src - used for your jsx components / javascript files
|
|
59
|
+
public - used for anything
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
4. And your done - Run `npm run build` and the compiled output is visible inside of the `/dist/` folder!
|
|
66
|
+
|
|
67
|
+
## Key Features & Examples
|
|
68
|
+
|
|
69
|
+
### File based routing
|
|
70
|
+
vader's compiler automatically handles routing so you wont need to!
|
|
71
|
+
below is valid paths for parsing per [Buns fileSystem Routing Api](https://bun.sh/docs/api/file-system-router)
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
/pages/index.jsx = /
|
|
75
|
+
/pages/home/[page].jsx = /home/:page
|
|
76
|
+
/pages/path/index.jsx = /path/file
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
You can grab the request object from `this.request` and response object from `this.response!`
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
### Simplified Component Creation
|
|
84
|
+
|
|
85
|
+
```jsx
|
|
86
|
+
// pages/home.jsx
|
|
87
|
+
let {Component, useState} = await import('./vader.js') // always use ./vader.js as files reference vaders main file
|
|
88
|
+
let Mycomponent = await require('./pages/mycomponent')
|
|
89
|
+
class Home extends Vader {
|
|
90
|
+
constructor() {
|
|
91
|
+
super();
|
|
92
|
+
this.key = '2'
|
|
93
|
+
}
|
|
94
|
+
render() {
|
|
95
|
+
return <>
|
|
96
|
+
<div key={this.key}>
|
|
97
|
+
<p>Hello World</p>
|
|
98
|
+
</div>
|
|
99
|
+
<Mycomponent ..props />
|
|
100
|
+
</>
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {default:Home}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
### State Management
|
|
110
|
+
|
|
111
|
+
```jsx
|
|
112
|
+
let {Component, useState} = await import('./vader.js')
|
|
113
|
+
|
|
114
|
+
class MyApp extends Component{
|
|
115
|
+
contructor(){
|
|
116
|
+
super()
|
|
117
|
+
this.key = 'static key for state changes'
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
render(){
|
|
121
|
+
let [count, setCount] = useState(0)
|
|
122
|
+
function increment(){
|
|
123
|
+
setCount(count()+ 1)
|
|
124
|
+
}
|
|
125
|
+
return <>
|
|
126
|
+
<p>Count is ${count}</p>
|
|
127
|
+
<button onclick={()=>increment()}>Increment</button>
|
|
128
|
+
</>
|
|
129
|
+
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return {default:MyApp}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
### Function Binding
|
|
138
|
+
|
|
139
|
+
Vaderjs allows you to bind functions directly to html elements just like react
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
// vader uses params[0] as the event target object and other parameters resolve after
|
|
143
|
+
|
|
144
|
+
function click(event, otherparams){
|
|
145
|
+
console.log(event.target, otherparams)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return <>
|
|
149
|
+
<button onclick={()=>click()}>Click Me</button>
|
|
150
|
+
</>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
VaderJS is released under the MIT License. See the [LICENSE](https://github.com/Postr-Inc/Vader.js/blob/main/LICENSE) file for details.
|
|
164
|
+
|
|
165
|
+
## Join the Community
|
|
166
|
+
|
|
167
|
+
Connect with the VaderJS community on [GitHub](https://github.com/Postr-Inc/Vader.js). Contribute, share feedback, and improve VaderJS for SPA development.
|
package/logo.png
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,29 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vaderjs",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
},
|
|
9
|
-
"repository": {
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/Postr-Inc/Vader.js.git"
|
|
3
|
+
"description": "A Reactive library aimed to helping you build reactive applications inspired by react.js",
|
|
4
|
+
"module": "vader.js",
|
|
5
|
+
"version": "1.3.7-alpha-1",
|
|
6
|
+
"bin": {
|
|
7
|
+
"vader": "./vader"
|
|
12
8
|
},
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"Nextjs",
|
|
18
|
-
"Vaderjs"
|
|
19
|
-
],
|
|
20
|
-
"author": "Malikwhitten67",
|
|
21
|
-
"license": "MIT",
|
|
22
|
-
"bugs": {
|
|
23
|
-
"url": "https://github.com/Postr-Inc/Vader.js/issues"
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "bunx vader --build",
|
|
11
|
+
"watch": "bun run vader --watch",
|
|
12
|
+
"help": "bunx vader"
|
|
24
13
|
},
|
|
25
|
-
"
|
|
14
|
+
"type": "module",
|
|
26
15
|
"devDependencies": {
|
|
27
|
-
"
|
|
16
|
+
"@types/bun": "latest"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"typescript": "^5.0.0"
|
|
28
20
|
}
|
|
29
|
-
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { Component } from "./vader.js";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @class VaderRouter
|
|
9
|
+
* @description - creates an instance of Vader Express Router
|
|
10
|
+
*
|
|
11
|
+
* @param {String} path
|
|
12
|
+
* @param {Function} handler
|
|
13
|
+
* @param {object} req request object
|
|
14
|
+
* @param {object} res response object
|
|
15
|
+
* @returns {Object} Express
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
class VaderRouter{
|
|
19
|
+
/**
|
|
20
|
+
* @constructor
|
|
21
|
+
* @param {*} basePath
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
24
|
+
constructor(/**@type {string}**/basePath, /**@type {number}**/port) {
|
|
25
|
+
this.routes = [];
|
|
26
|
+
this.middlewares = [];
|
|
27
|
+
this.errorMiddlewares = [];
|
|
28
|
+
this.listeners = [];
|
|
29
|
+
|
|
30
|
+
this.basePath = basePath;
|
|
31
|
+
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @method get
|
|
36
|
+
* @param {String} path
|
|
37
|
+
* @param {Function} handler
|
|
38
|
+
* @param {{a:b}} req request object
|
|
39
|
+
* @description This method is used to register a get route
|
|
40
|
+
* @returns {void}
|
|
41
|
+
* @memberof Express
|
|
42
|
+
*/
|
|
43
|
+
get(path, handler) {
|
|
44
|
+
|
|
45
|
+
this.routes.push({
|
|
46
|
+
path,
|
|
47
|
+
handler,
|
|
48
|
+
method: 'get',
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* @method use
|
|
53
|
+
* @description This method allows you to use middlewares
|
|
54
|
+
* @param {Function} middleware
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
use(/* path, */ middleware) {
|
|
58
|
+
this.middlewares.push(middleware);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @method listen
|
|
63
|
+
* @param {String} port - unique id for the listener
|
|
64
|
+
* @param {Function} callback - callback function
|
|
65
|
+
* @description This method is used to start listening to the routes
|
|
66
|
+
* @returns {void}
|
|
67
|
+
*
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
listen(port, callback) {
|
|
71
|
+
if(!port){
|
|
72
|
+
port = Math.random().toString(36).substring(7);
|
|
73
|
+
}
|
|
74
|
+
this.listeners.push(port);
|
|
75
|
+
if (this.listeners.length === 1) {
|
|
76
|
+
this.handleRoute(window.location.hash);
|
|
77
|
+
}else{
|
|
78
|
+
this.listeners.pop();
|
|
79
|
+
}
|
|
80
|
+
if (callback) {
|
|
81
|
+
callback();
|
|
82
|
+
}
|
|
83
|
+
window.onhashchange = () => {
|
|
84
|
+
this.handleRoute(window.location.hash);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* @method extractParams
|
|
89
|
+
* @description This method is used to extract parameters from the route path
|
|
90
|
+
* @param {*} routePath
|
|
91
|
+
* @param {*} hash
|
|
92
|
+
* @returns {Object} params
|
|
93
|
+
* @memberof Express
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
extractParams(routePath, hash) {
|
|
97
|
+
const routeParts = routePath.split('/');
|
|
98
|
+
const hashParts = hash.split('/');
|
|
99
|
+
const params = {};
|
|
100
|
+
routeParts.forEach((part, index) => {
|
|
101
|
+
if (part.startsWith(':')) {
|
|
102
|
+
const paramName = part.slice(1);
|
|
103
|
+
params[paramName] = hashParts[index];
|
|
104
|
+
}else if(part.startsWith('*')){
|
|
105
|
+
// remove queries from this par
|
|
106
|
+
params[0] = hashParts.slice(index).join('/').split('?')[0];
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
return params;
|
|
110
|
+
}
|
|
111
|
+
extractQueryParams(hash){
|
|
112
|
+
|
|
113
|
+
const queryParams = hash.split('?')[1];
|
|
114
|
+
if(!queryParams){
|
|
115
|
+
return {};
|
|
116
|
+
}
|
|
117
|
+
const params = {};
|
|
118
|
+
queryParams.split('&').forEach((param)=>{
|
|
119
|
+
const [key, value] = param.split('=');
|
|
120
|
+
params[key] = value;
|
|
121
|
+
})
|
|
122
|
+
return params;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* @method handleRoute
|
|
127
|
+
* @param {String} hash
|
|
128
|
+
* @description This method is used to handle the route
|
|
129
|
+
*/
|
|
130
|
+
|
|
131
|
+
handleRoute(hash) {
|
|
132
|
+
hash = hash.slice(1);
|
|
133
|
+
let status = 200;
|
|
134
|
+
let route = this.routes.find((route) => {
|
|
135
|
+
|
|
136
|
+
if (route.path === hash) {
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
const routePathParts = route.path.split('/');
|
|
140
|
+
const hashParts = hash.split('/');
|
|
141
|
+
if (routePathParts.length !== hashParts.length) {
|
|
142
|
+
return false;
|
|
143
|
+
}else if(routePathParts[routePathParts.length-1].startsWith('*')){
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
const params = this.extractParams( route.path, hash);
|
|
147
|
+
return Object.keys(params).length > 0;
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
if (!route) {
|
|
151
|
+
route = this.routes.find((route) => {
|
|
152
|
+
|
|
153
|
+
if(route.path === '/404'){
|
|
154
|
+
return true;
|
|
155
|
+
}else{
|
|
156
|
+
window.location.hash = this.basePath
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
route ? status = 200 :
|
|
161
|
+
|
|
162
|
+
status = 404;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
const queryParams = this.extractQueryParams(hash);
|
|
167
|
+
const params = route && route.path ? this.extractParams(route.path, hash) : {};
|
|
168
|
+
const req = {
|
|
169
|
+
headers: {},
|
|
170
|
+
params: params,
|
|
171
|
+
query: queryParams,
|
|
172
|
+
path: hash,
|
|
173
|
+
method: route ? route.method : 'get',
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
// @ts-ignore
|
|
177
|
+
window.$CURRENT_URL = req.path
|
|
178
|
+
|
|
179
|
+
// @ts-ignore
|
|
180
|
+
window.$FULL_URL = window.location.href.replace('#', '')
|
|
181
|
+
|
|
182
|
+
const res = {
|
|
183
|
+
status: status,
|
|
184
|
+
/**
|
|
185
|
+
* @method log
|
|
186
|
+
* @param {String} type
|
|
187
|
+
* @description This method is used to log the request and response
|
|
188
|
+
*/
|
|
189
|
+
log: (type) => {
|
|
190
|
+
if(type === undefined){
|
|
191
|
+
console.log(`${req.path} ${req.method} ${res.status} ${req.timestamp}`);
|
|
192
|
+
}else{
|
|
193
|
+
console.table({
|
|
194
|
+
'Request Path': req.path,
|
|
195
|
+
'Request Method': route.method,
|
|
196
|
+
'Response Status': res.status,
|
|
197
|
+
'Request Timestamp': req.timestamp,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
render: async (/**@type {Component} */ Component, req, res) => {
|
|
202
|
+
|
|
203
|
+
if(!Component.default || !Component.constructor){
|
|
204
|
+
let message = !Component.default ? 'default' : 'constructor';
|
|
205
|
+
switch(message){
|
|
206
|
+
case 'default':
|
|
207
|
+
throw new Error(`Component must have a default export ex: return {default: Component}`);
|
|
208
|
+
|
|
209
|
+
case 'constructor':
|
|
210
|
+
throw new Error(`Component is invalid, please check the constructor`);
|
|
211
|
+
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
Component = Component.default ? new Component.default() : Component.constructor ? new Component() : Component;
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
Component.mounted = true;
|
|
220
|
+
|
|
221
|
+
if(!document.querySelector('#root')){
|
|
222
|
+
throw new Error('Root element not found, please add an element with id root');
|
|
223
|
+
}
|
|
224
|
+
Component.request = req;
|
|
225
|
+
Component.response = res;
|
|
226
|
+
document.querySelector('#root').innerHTML = Component.render()
|
|
227
|
+
Component.bindMount();
|
|
228
|
+
Component.onMount()
|
|
229
|
+
|
|
230
|
+
},
|
|
231
|
+
send: (data) => {
|
|
232
|
+
document.querySelector('#root').innerHTML = data;
|
|
233
|
+
},
|
|
234
|
+
json: (selector, data) => {
|
|
235
|
+
|
|
236
|
+
if(typeof selector === 'string'){
|
|
237
|
+
// @ts-ignore
|
|
238
|
+
let obj = document.createElement('object');
|
|
239
|
+
// data url
|
|
240
|
+
obj.data = URL.createObjectURL(new Blob([JSON.stringify(data)], {type: 'application/json'}));
|
|
241
|
+
// @ts-ignore
|
|
242
|
+
document.querySelector(selector).appendChild(obj);
|
|
243
|
+
}else{
|
|
244
|
+
throw new Error('Selector must be a string');
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
this.middlewares.forEach((middleware) => {
|
|
249
|
+
middleware(req, res);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
route ? route.handler(req, res) : null;
|
|
253
|
+
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
window.VaderRouter = VaderRouter;
|
|
259
|
+
|
|
260
|
+
export default VaderRouter;
|
|
261
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Vaderjs v1.3.3</title>
|
|
7
|
+
<meta name="description" content="Vader.js is a modern web framework for building web applications.">
|
|
8
|
+
<link rel="shortcut icon" href="https://raw.githubusercontent.com/Postr-Inc/Vader.js/vader1.3.3-beta/logo.png" type="image/x-icon">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="root"></div>
|
|
12
|
+
<script type="module">
|
|
13
|
+
import VaderRouter from './public/vader/router.js'
|
|
14
|
+
|
|
15
|
+
const router = new VaderRouter('/', 3000)
|
|
16
|
+
window.router = router
|
|
17
|
+
await import('./app.js')
|
|
18
|
+
router.listen(3000)
|
|
19
|
+
</script>
|
|
20
|
+
</body>
|
|
21
|
+
</html>
|
package/vader
ADDED
|
Binary file
|
package/.vscode/settings.json
DELETED
package/index.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file index.js
|
|
3
|
-
* @description This is the entry point for the library. This file exports all the necessary classes and functions.
|
|
4
|
-
* @version 1.1.5
|
|
5
|
-
*
|
|
6
|
-
*/
|
|
7
|
-
import Vader, { include} from './vader.js';
|
|
8
|
-
// @ts-ignore
|
|
9
|
-
import VaderRouter from './vaderRouter.js';
|
|
10
|
-
|
|
11
|
-
export { include, VaderRouter };
|
|
12
|
-
export default Vader;
|
package/jsconfig.json
DELETED