vaderjs 1.3.3-alpha-45 → 1.3.3-alpha-47

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 CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "vaderjs",
3
3
  "description": "A Reactive library aimed to helping you build reactive applications inspired by react.js",
4
4
  "module": "vader.js",
5
- "version": "1.3.3-alpha-45",
5
+ "version": "1.3.3-alpha-47",
6
6
  "bin": {
7
7
  "vader": "./vader.js"
8
8
  },
package/runtime/router.js CHANGED
@@ -1,333 +1 @@
1
- import { Component } from "./vader.js";
2
-
3
- let middlewares = [];
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
- console.log(middleware)
59
- this.middlewares.push(middleware);
60
- }
61
-
62
- /**
63
- * @method listen
64
- * @param {String} port - unique id for the listener
65
- * @param {Function} callback - callback function
66
- * @description This method is used to start listening to the routes
67
- * @returns {void}
68
- *
69
- */
70
-
71
- listen(port, callback) {
72
- if(!port){
73
- port = Math.random().toString(36).substring(7);
74
- }
75
- this.listeners.push(port);
76
- if (this.listeners.length === 1) {
77
- this.handleRoute(window.location.hash);
78
- }else{
79
- this.listeners.pop();
80
- }
81
- if (callback) {
82
- callback();
83
- }
84
- window.onhashchange = () => {
85
- this.handleRoute(window.location.hash);
86
- }
87
- }
88
- /**
89
- * @method extractParams
90
- * @description This method is used to extract parameters from the route path
91
- * @param {*} routePath
92
- * @param {*} hash
93
- * @returns {Object} params
94
- * @memberof Express
95
- */
96
-
97
- extractParams(routePath, hash) {
98
- const routeParts = routePath.split('/');
99
- const hashParts = hash.split('/');
100
- const params = {};
101
- routeParts.forEach((part, index) => {
102
- if (part.startsWith(':')) {
103
- const paramName = part.slice(1);
104
- params[paramName] = hashParts[index];
105
- }else if(part.startsWith('*')){
106
- let array = hashParts.slice(index)
107
- array.forEach((i, index)=>{
108
- params[index] = i
109
- })
110
- }
111
- });
112
- return params;
113
- }
114
- extractQueryParams(hash){
115
-
116
- const queryParams = hash.split('?')[1];
117
- if(!queryParams){
118
- return {};
119
- }
120
- const params = {};
121
- queryParams.split('&').forEach((param)=>{
122
- const [key, value] = param.split('=');
123
- params[key] = value;
124
- })
125
- return params;
126
- }
127
-
128
- /**
129
- * @method handleRoute
130
- * @param {String} hash
131
- * @description This method is used to handle the route
132
- */
133
-
134
- handleRoute(hash) {
135
- hash = hash.slice(1);
136
- let status = 200;
137
- let paramsCatchall = {}
138
- let hashBefore = hash;
139
- let route = this.routes.find((route) => {
140
- if (route.path === hash) {
141
- return true;
142
- }
143
-
144
- if(hash === '' && route.path === '/'){
145
- return true
146
- }
147
-
148
- if(hash.includes('?')){
149
- hash = hash.split('?')[0]
150
- }
151
- if (route.path.includes('*') || route.path.includes(':')) {
152
- const routeParts = route.path.split('/');
153
- const hashParts = hash.split('/');
154
-
155
- if (routeParts.length !== hashParts.length && !route.path.endsWith('*')) {
156
- return false;
157
- }
158
-
159
- for (let index = 0; index < routeParts.length; index++) {
160
- const routePart = routeParts[index];
161
- const hashPart = hashParts[index];
162
-
163
- if (routePart.startsWith(':') || routePart.startsWith('*')) {
164
-
165
- continue;
166
- }
167
-
168
- if (routePart !== hashPart) {
169
-
170
- return false;
171
- }
172
- }
173
-
174
- return true;
175
- }
176
-
177
- const params = this.extractParams(route.path, hashBefore);
178
- return Object.keys(params).length > 0;
179
- });
180
-
181
-
182
- if (!route) {
183
- route = this.routes.find((errorRoute) => {
184
- if (errorRoute.path.includes('/404')){
185
- this.error = true;
186
- return true;
187
- } else if (!this.error && errorRoute.path.includes('/404')){
188
- window.location.hash = this.basePath
189
- }
190
- });
191
-
192
- status = route ? 200 : 404;
193
- }
194
-
195
- const queryParams = this.extractQueryParams(hashBefore);
196
- const params = route && route.path ? this.extractParams(route.path, hashBefore) : {};
197
- const req = {
198
- headers: {},
199
- params: params,
200
- query: queryParams,
201
- path: hash,
202
- method: route ? route.method : 'get',
203
- };
204
-
205
- // @ts-ignore
206
- window.$CURRENT_URL = req.path
207
-
208
- // @ts-ignore
209
- window.$FULL_URL = window.location.href.replace('#', '')
210
-
211
- const res = {
212
- status: status,
213
- /**
214
- * @method log
215
- * @param {String} type
216
- * @description This method is used to log the request and response
217
- */
218
- log: (type) => {
219
- if(type === undefined){
220
- console.log(`${req.path} ${req.method} ${res.status} ${req.timestamp}`);
221
- }else{
222
- console.table({
223
- 'Request Path': req.path,
224
- 'Request Method': route.method,
225
- 'Response Status': res.status,
226
- 'Request Timestamp': req.timestamp,
227
- });
228
- }
229
- },
230
- refresh: () => {
231
- this.handleRoute(window.location.hash);
232
- },
233
- redirect: (path) => {
234
- !path.startsWith('/') ? path = `/${path}` : null;
235
- window.location.hash = `#${path}`;
236
- },
237
- render: async (/**@type {Component} */ Component, req, res) => {
238
- try {
239
- if(!Component.default || !Component.default.constructor){
240
- let message = !Component.default ? `Router expected a default exported component ie: export default class Component` : !Component.default.constructor ? 'Component is not a class' : null;
241
- throw new Error(message);
242
- }
243
-
244
-
245
- // Create an instance of the component
246
- Component = Component.default ? new Component.default() : Component.constructor ? new Component() : Component;
247
-
248
- // Set the 'mounted' flag to true
249
- Component.mounted = true;
250
-
251
- // Check if the root element exists
252
- if (!document.querySelector('#root')) {
253
- throw new Error('Root element not found, please add an element with id root');
254
- }
255
-
256
- // Reset component state
257
- Component.reset();
258
- Component.components = {};
259
- Component.request = req;
260
- Component.response = res;
261
-
262
- // Check if the component has a router and is not a child component
263
- if (Component.router.use && !Component.isChild) {
264
-
265
- // Allow pausing the route and run code before rendering
266
- await new Promise(async (resolve) => {
267
- await Component.router.use(req, res)
268
- if(req.pause){
269
- let timer = setInterval(() => {
270
- if(!req.pause){
271
- resolve();
272
- clearInterval(timer);
273
- }
274
- }, 1000);
275
- }else{
276
- resolve();
277
- }
278
- });
279
- } else if (Component.router.use && Component.isChild) {
280
- console.warn('Router.use() is not supported in child components');
281
- }
282
- const renderedContent = await Component.render();
283
- document.querySelector('#root').innerHTML = renderedContent;
284
- Component.bindMount();
285
- Component.onMount();
286
-
287
- } catch (error) {
288
- console.error(error);
289
- }
290
- },
291
- setQuery: (query) => {
292
- let queryString = '';
293
- Object.keys(query).forEach((key, index) => {
294
- queryString += `${index === 0 ? '?' : '&'}${key}=${query[key]}`;
295
- });
296
- let route = window.location.hash.split('?')[0];
297
- queryString = queryString.replace('/', '-').replaceAll('/', '-')
298
- window.location.hash = `${route}${queryString}`;
299
- },
300
- send: (data) => {
301
- document.querySelector('#root').innerHTML = data;
302
- },
303
- json: (data) => {
304
- const rootElement = document.querySelector('#root');
305
-
306
- // Clear existing content in #root
307
- rootElement.innerHTML = '';
308
-
309
- // Create a <pre> element
310
- const preElement = document.createElement('pre');
311
-
312
- // Set the text content of the <pre> element with formatted JSON
313
- preElement.textContent = JSON.stringify(data, null, 2);
314
-
315
- // Append the <pre> element to the #root element
316
- rootElement.appendChild(preElement);
317
- }
318
-
319
- };
320
- middlewares.forEach((middleware) => {
321
- middleware(req, res);
322
- });
323
-
324
- route ? route.handler(req, res) : null;
325
- }
326
-
327
-
328
- }
329
-
330
- window.VaderRouter = VaderRouter;
331
-
332
- export default VaderRouter;
333
-
1
+ import{Component}from"./vader.js";let middlewares=[];class VaderRouter{constructor(t,e){this.routes=[],this.middlewares=[],this.errorMiddlewares=[],this.listeners=[],this.basePath=t}get(t,e){this.routes.push({path:t,handler:e,method:"get"})}use(t){console.log(t),this.middlewares.push(t)}listen(t,e){t||(t=Math.random().toString(36).substring(7)),this.listeners.push(t),1===this.listeners.length?this.handleRoute(window.location.hash):this.listeners.pop(),e&&e(),window.onhashchange=()=>{this.handleRoute(window.location.hash)}}extractParams(t,e){const s=t.split("/"),r=e.split("/"),o={};return s.forEach(((t,e)=>{if(t.startsWith(":")){const s=t.slice(1);o[s]=r[e]}else if(t.startsWith("*")){r.slice(e).forEach(((t,e)=>{o[e]=t}))}})),o}extractQueryParams(t){const e=t.split("?")[1];if(!e)return{};const s={};return e.split("&").forEach((t=>{const[e,r]=t.split("=");s[e]=r})),s}handleRoute(t){let e=200,s=t=t.slice(1),r=this.routes.find((e=>{if(e.path===t)return!0;if(""===t&&"/"===e.path)return!0;if(t.includes("?")&&(t=t.split("?")[0]),e.path.includes("*")||e.path.includes(":")){const s=e.path.split("/"),r=t.split("/");if(s.length!==r.length&&!e.path.endsWith("*"))return!1;for(let t=0;t<s.length;t++){const e=s[t],o=r[t];if(!e.startsWith(":")&&!e.startsWith("*")&&e!==o)return!1}return!0}const r=this.extractParams(e.path,s);return Object.keys(r).length>0}));r||(r=this.routes.find((t=>{if(t.path.includes("/404"))return this.error=!0,!0;!this.error&&t.path.includes("/404")&&(window.location.hash=this.basePath)})),e=r?200:404);const o=this.extractQueryParams(s),n=r&&r.path?this.extractParams(r.path,s):{},a={headers:{},params:n,query:o,path:t,method:r?r.method:"get"};window.$CURRENT_URL=a.path,window.$FULL_URL=window.location.href.replace("#","");const i={status:e,log:t=>{void 0===t?console.log(`${a.path} ${a.method} ${i.status} ${a.timestamp}`):console.table({"Request Path":a.path,"Request Method":r.method,"Response Status":i.status,"Request Timestamp":a.timestamp})},refresh:()=>{this.handleRoute(window.location.hash)},redirect:t=>{!t.startsWith("/")&&(t=`/${t}`),window.location.hash=`#${t}`},render:async(t,e,s)=>{try{let a=new Component;if("function"==typeof(r=t.default)&&/^class\s/.test(Function.prototype.toString.call(r))){let e=new t.default;a.state=e.state,console.log(a.state),a=e}else{let r=t.default.toString(),i=r.split("this.key")[1].split("=")[1].split('"')[1],l=(r.match(/return\s*`([\s\S]*)`/),r.split("return")[1].split("`")[0]);l=l.replace(/,\s*$/,"");let h=t.default.apply?t.default.apply(a,[e,s]):new t.default;a.key=i;let u={key:i,render:()=>h,request:e,response:s,params:n,queryParams:o,reset:a.reset.bind(a),onMount:a.onMount.bind(a),useState:null,router:{use:a.router.use.bind(a)},bindMount:a.bindMount.bind(a),memoize:a.memoize.bind(a),createComponent:a.createComponent.bind(a),isChild:!1};a.render=u.render,a=u}if(!document.querySelector("#root"))throw new Error("Root element not found, please add an element with id root");a.reset(),a.components={},a.request=e,a.response=s,a.router.use&&!a.isChild?await new Promise((async t=>{if(await a.router.use(e,s),e.pause){let s=setInterval((()=>{e.pause||(t(),clearInterval(s))}),1e3)}else t()})):a.router.use&&a.isChild&&console.warn("Router.use() is not supported in child components");const i=await a.render();document.querySelector("#root").innerHTML=i,a.bindMount(),a.onMount()}catch(t){console.error(t)}var r},setQuery:t=>{let e="";Object.keys(t).forEach(((s,r)=>{e+=`${0===r?"?":"&"}${s}=${t[s]}`}));let s=window.location.hash.split("?")[0];e=e.replace("/","-").replaceAll("/","-"),window.location.hash=`${s}${e}`},send:t=>{document.querySelector("#root").innerHTML=t},json:t=>{const e=document.querySelector("#root");e.innerHTML="";const s=document.createElement("pre");s.textContent=JSON.stringify(t,null,2),e.appendChild(s)}};middlewares.forEach((t=>{t(a,i)})),r&&r.handler(a,i)}}window.VaderRouter=VaderRouter;export default VaderRouter;