vaderjs 1.3.3-alpha-110 → 1.3.3-alpha-111

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-110",
5
+ "version": "1.3.3-alpha-111",
6
6
  "bin": {
7
7
  "vader": "./vader.js"
8
8
  },
package/runtime/router.js CHANGED
@@ -1 +1,444 @@
1
- import{Component}from"./vader.js";let middlewares=[];class VaderRouter{constructor(e,t){this.routes=[],this.middlewares=[],this.errorMiddlewares=[],this.listeners=[],this.basePath=e,console.log(this.basePath)}get(e,t){this.routes.push({path:e,handler:t,method:"get"})}use(e){this.middlewares.push(e)}listen(e,t){e||(e=Math.random().toString(36).substring(7)),this.listeners.push(e),1===this.listeners.length?this.handleRoute(window.location.hash.length>0?window.location.hash:window.location.pathname):this.listeners.pop(),t&&t(),window.onpopstate=async e=>{let t=`/${window.location.pathname.split("/")[1]}`;routes.find((e=>e.url.includes(t)))||(t="/404");let n=(new DOMParser).parseFromString(await fetch(t,{cache:"reload"}).then((e=>e.text())),"text/html").documentElement;document.querySelector("#root").innerHTML=n.querySelector("#root").innerHTML,document.title=n.querySelector("title").innerHTML,document.querySelector('script[id="router"]').remove();let s=document.createElement("script");s.id="router",s.innerHTML=n.querySelector('script[id="router"]').innerHTML,s.setAttribute("type","module"),document.body.appendChild(s)}}extractParams(e,t){const n=e.split("/"),s=t.split("/"),o={};return n.forEach(((e,t)=>{if(e.startsWith(":")){const n=e.slice(1);o[n]=s[t]}else if(e.startsWith("*")){s.slice(t).forEach(((e,t)=>{o[t]=e}))}})),o}extractQueryParams(e){const t=e.split("?")[1];if(!t)return{};const n={};return t.split("&").forEach((e=>{const[t,s]=e.split("=");n[t]=s})),n}handleRoute(e){let t=200,n=e=e.includes("#")?e.slice(1):e,s=this.routes.find((t=>{if(t.path===e)return!0;if(""===e&&"/"===t.path)return!0;if(e.includes("?")&&(e=e.split("?")[0]),t.path.includes("*")||t.path.includes(":")){const n=t.path.split("/"),s=e.split("/");if(n.length!==s.length&&!t.path.endsWith("*"))return!1;for(let e=0;e<n.length;e++){const t=n[e],o=s[e];if(!t.startsWith(":")&&!t.startsWith("*")&&t!==o)return!1}return!0}const s=this.extractParams(t.path,n);return Object.keys(s).length>0}));s||(console.log(window.routes),s=window.routes.find((e=>{if(e.url.includes("/404"))window.history.replaceState({},"","/404");else if(!this.error&&e.url.includes("/404"))return!0})),t=s?200:404);const o=this.extractQueryParams(n),r=s&&s.path?this.extractParams(s.path,n):{};Object.keys(r).forEach((e=>{r[e]=r[e].split("?")?r[e].split("?")[0]:r[e]}));const i={headers:{},params:r,query:o,path:e,fileUrl:window.location.href.split(window.location.origin)[1],url:window.location.href,method:s?s.method:"get",pause:!1,timestamp:Date.now()};window.$CURRENT_URL=i.path,window.$FULL_URL=window.location.href.replace("#","");const a={status:t,log:e=>{void 0===e?console.log(`${i.path} ${i.method} ${a.status} ${i.timestamp}`):console.table({"Request Path":i.path,"Request Method":s.method,"Response Status":a.status,"Request Timestamp":i.timestamp})},refresh:()=>{this.handleRoute(window.location.hash)},redirect:e=>{!e.startsWith("/")&&(e=`/${e}`),window.location.hash=`#${e}`},render:async(e,t,n,s)=>{function isClass(e){return"function"==typeof e&&/^class\s/.test(Function.prototype.toString.call(e))}try{let s=new Component;if(isClass(e.default)){let t=new e.default;s.state=t.state,s=t}else{if(e.default.toString().includes("this.key"))throw new Error('Using this.key is not supported in functional components use the attribute key="a value" instead');s.key=e.default.toString().split('key="')[1]?e.default.toString().split('key="')[1].split('"')[0]:null;let i={key:s.key,render:()=>e.default.apply(s,[t,n]),request:t,response:n,params:r,queryParams:o,reset:s.reset.bind(s),onMount:s.onMount.bind(s),useState:null,router:{use:s.router.use.bind(s)},bindMount:s.bindMount.bind(s),memoize:s.memoize.bind(s),createComponent:s.createComponent.bind(s),isChild:!1,useState:s.useState.bind(s),parseStyle:s.parseStyle.bind(s),bind:s.bind.bind(s),useRef:s.useRef.bind(s),useReducer:s.useReducer.bind(s),onMount:s.onMount.bind(s),onUnmount:s.onUnmount.bind(s),hydrate:s.hydrate.bind(s)};s.render=i.render,s=i,console.log(t)}if(!document.querySelector("#root"))throw new Error("Root element not found, please add an element with id root");s.reset(),s.components={},s.request=t,s.response=n,s.router.use&&!s.isChild?await new Promise((async o=>{if(isClass(e.default))if(isClass(e.default))switch(await s.router.use(t,n),t.pause){case!0:console.log("pausing",t.pause);let e=setInterval((()=>{t.pause?console.log("still pausing",t.pause):(clearInterval(e),o())}),1e3);break;case!1:o()}else o();else switch(await e.default.apply(s,[t,n]),await s.router.use(t,n),t.pause){case!0:let e=setInterval((()=>{t.pause?console.log("still pausing request",t.url):(clearInterval(e),o())}),1e3);break;case!1:o()}})):s.router.use&&s.isChild&&console.warn("Router.use() is not supported in child components");const i=await s.render();document.querySelector("#root").innerHTML!==i&&(console.log("rendering"),document.querySelector("#root").innerHTML=i),s.bindMount(),s.onMount()}catch(e){console.error(e)}},setQuery:e=>{let t="";Object.keys(e).forEach(((n,s)=>{t+=`${0===s?"?":"&"}${n}=${e[n]}`}));let n=window.location.hash.split("?")[0];t=t.replace("/","-").replaceAll("/","-"),window.location.hash=`${n}${t}`},send:e=>{document.querySelector("#root").innerHTML=e},json:e=>{const t=document.querySelector("#root");t.innerHTML="";const n=document.createElement("pre");n.textContent=JSON.stringify(e,null,2),t.appendChild(n)}};middlewares.forEach((e=>{e(i,a)})),s&&s.handler(i,a)}}window.VaderRouter=VaderRouter;export default VaderRouter;
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
+ console.log(this.basePath)
32
+
33
+ }
34
+
35
+ /**
36
+ * @method get
37
+ * @param {String} path
38
+ * @param {Function} handler
39
+ * @param {{a:b}} req request object
40
+ * @description This method is used to register a get route
41
+ * @returns {void}
42
+ * @memberof Express
43
+ */
44
+ get(path, handler) {
45
+
46
+ this.routes.push({
47
+ path,
48
+ handler,
49
+ method: 'get',
50
+ });
51
+
52
+ }
53
+ /**
54
+ * @method use
55
+ * @description This method allows you to use middlewares
56
+ * @param {Function} middleware
57
+ */
58
+
59
+ use(/* path, */ middleware) {
60
+ this.middlewares.push(middleware);
61
+ }
62
+
63
+ /**
64
+ * @method listen
65
+ * @param {String} port - unique id for the listener
66
+ * @param {Function} callback - callback function
67
+ * @description This method is used to start listening to the routes
68
+ * @returns {void}
69
+ *
70
+ */
71
+
72
+ listen(port, callback) {
73
+ if(!port){
74
+ port = Math.random().toString(36).substring(7);
75
+ }
76
+ this.listeners.push(port);
77
+ if (this.listeners.length === 1) {
78
+ this.handleRoute(window.location.hash.length > 0 ? window.location.hash : window.location.pathname);
79
+ }else{
80
+ this.listeners.pop();
81
+ }
82
+ if (callback) {
83
+ callback();
84
+ }
85
+ window.onpopstate = async (e) => {
86
+ let route = window.location.pathname
87
+ console.log(route)
88
+ let baseRoute = `/${route.split('/')[1]}`
89
+ if(!routes.find((route)=>route.url.includes(baseRoute))){
90
+ baseRoute = '/404'
91
+
92
+ }
93
+ let html = new DOMParser().parseFromString(await fetch(baseRoute, {
94
+ cache: 'reload'
95
+ }).then((res)=>res.text()), 'text/html').documentElement
96
+
97
+
98
+ document.querySelector('#root').innerHTML = html.querySelector('#root').innerHTML;
99
+ document.title = html.querySelector('title').innerHTML;
100
+ document.querySelector('script[id="router"]').remove();
101
+ let newscript = document.createElement('script');
102
+ newscript.id = 'router';
103
+ newscript.innerHTML = html.querySelector('script[id="router"]').innerHTML;
104
+ newscript.setAttribute('type', 'module');
105
+ document.body.appendChild(newscript);
106
+ }
107
+ }
108
+ /**
109
+ * @method extractParams
110
+ * @description This method is used to extract parameters from the route path
111
+ * @param {*} routePath
112
+ * @param {*} hash
113
+ * @returns {Object} params
114
+ * @memberof Express
115
+ */
116
+
117
+ extractParams(routePath, hash) {
118
+ const routeParts = routePath.split('/');
119
+ const hashParts = hash.split('/');
120
+ const params = {};
121
+ routeParts.forEach((part, index) => {
122
+ if (part.startsWith(':')) {
123
+ const paramName = part.slice(1);
124
+ params[paramName] = hashParts[index];
125
+ }else if(part.startsWith('*')){
126
+ let array = hashParts.slice(index)
127
+ array.forEach((i, index)=>{
128
+ params[index] = i
129
+ })
130
+ }
131
+ });
132
+ return params;
133
+ }
134
+ extractQueryParams(hash){
135
+
136
+ const queryParams = hash.split('?')[1];
137
+ if(!queryParams){
138
+ return {};
139
+ }
140
+ const params = {};
141
+ queryParams.split('&').forEach((param)=>{
142
+ const [key, value] = param.split('=');
143
+ params[key] = value;
144
+ })
145
+ return params;
146
+ }
147
+
148
+ /**
149
+ * @method handleRoute
150
+ * @param {String} hash
151
+ * @description This method is used to handle the route
152
+ */
153
+
154
+ handleRoute(hash) {
155
+ hash = hash.includes('#') ? hash.slice(1) : hash;
156
+ let status = 200;
157
+ let paramsCatchall = {}
158
+ let hashBefore = hash;
159
+ let route = this.routes.find((route) => {
160
+ if (route.path === hash) {
161
+ return true;
162
+ }
163
+
164
+ if(hash === '' && route.path === '/'){
165
+ return true
166
+ }
167
+
168
+ if(hash.includes('?')){
169
+ hash = hash.split('?')[0]
170
+ }
171
+ if (route.path.includes('*') || route.path.includes(':')) {
172
+ const routeParts = route.path.split('/');
173
+ const hashParts = hash.split('/');
174
+
175
+ if (routeParts.length !== hashParts.length && !route.path.endsWith('*')) {
176
+ return false;
177
+ }
178
+
179
+ for (let index = 0; index < routeParts.length; index++) {
180
+ const routePart = routeParts[index];
181
+ const hashPart = hashParts[index];
182
+
183
+ if (routePart.startsWith(':') || routePart.startsWith('*')) {
184
+
185
+ continue;
186
+ }
187
+
188
+ if (routePart !== hashPart) {
189
+
190
+ return false;
191
+ }
192
+ }
193
+
194
+ return true;
195
+ }
196
+
197
+ const params = this.extractParams(route.path, hashBefore);
198
+ return Object.keys(params).length > 0;
199
+ });
200
+
201
+
202
+ if (!route) {
203
+ console.log(window.routes)
204
+ route = window.routes.find((errorRoute) => {
205
+ if (errorRoute.url.includes('/404')){
206
+ window.history.replaceState({}, '', '/404');
207
+
208
+ } else if (!this.error && errorRoute.url.includes('/404')){
209
+ return true
210
+ }
211
+ });
212
+
213
+ status = route ? 200 : 404;
214
+ }
215
+
216
+ const queryParams = this.extractQueryParams(hashBefore);
217
+ const params = route && route.path ? this.extractParams(route.path, hashBefore) : {};
218
+
219
+ // remove queryparams fromparam
220
+ Object.keys(params).forEach((key)=>{
221
+ params[key] = params[key].split('?') ? params[key].split('?')[0] : params[key];
222
+ })
223
+ const req = {
224
+ headers: {},
225
+ params: params,
226
+ query: queryParams,
227
+ path: hash,
228
+ fileUrl: window.location.href.split(window.location.origin)[1],
229
+ url: window.location.href,
230
+ method: route ? route.method : 'get',
231
+ pause: false,
232
+ timestamp: Date.now(),
233
+ };
234
+
235
+ // @ts-ignore
236
+ window.$CURRENT_URL = req.path
237
+
238
+ // @ts-ignore
239
+ window.$FULL_URL = window.location.href.replace('#', '')
240
+
241
+ const res = {
242
+ status: status,
243
+ /**
244
+ * @method log
245
+ * @param {String} type
246
+ * @description This method is used to log the request and response
247
+ */
248
+ log: (type) => {
249
+ if(type === undefined){
250
+ console.log(`${req.path} ${req.method} ${res.status} ${req.timestamp}`);
251
+ }else{
252
+ console.table({
253
+ 'Request Path': req.path,
254
+ 'Request Method': route.method,
255
+ 'Response Status': res.status,
256
+ 'Request Timestamp': req.timestamp,
257
+ });
258
+ }
259
+ },
260
+ refresh: () => {
261
+ this.handleRoute(window.location.hash);
262
+ },
263
+ redirect: (path) => {
264
+ !path.startsWith('/') ? path = `/${path}` : null;
265
+ window.location.hash = `#${path}`;
266
+ },
267
+ render: async (/**@type {Component} */ component, req, res, metadata) => {
268
+ function isClass(funcOrClass) {
269
+ return typeof funcOrClass === 'function' &&
270
+ /^class\s/.test(Function.prototype.toString.call(funcOrClass));
271
+ }
272
+
273
+ try {
274
+ let c = new Component();
275
+ if(!isClass(component.default)){
276
+ let render = component.default.toString();
277
+ if(render.includes('this.key')){
278
+ throw new Error('Using this.key is not supported in functional components use the attribute key="a value" instead')
279
+ }
280
+
281
+
282
+
283
+ c.key = component.default.toString().split('key="')[1] ? component.default.toString().split('key="')[1].split('"')[0] : null;
284
+
285
+ let comp = {
286
+ key: c.key,
287
+ render: () => {
288
+ return component.default.apply(c, [req, res])
289
+ },
290
+ request: req,
291
+ response: res,
292
+ params: params,
293
+ queryParams: queryParams,
294
+ reset: c.reset.bind(c),
295
+ onMount: c.onMount.bind(c),
296
+ useState: null,
297
+ router: {
298
+ use: c.router.use.bind(c),
299
+ },
300
+ bindMount: c.bindMount.bind(c),
301
+ memoize: c.memoize.bind(c),
302
+ createComponent: c.createComponent.bind(c),
303
+ isChild: false,
304
+ useState: c.useState.bind(c),
305
+ parseStyle: c.parseStyle.bind(c),
306
+ bind: c.bind.bind(c),
307
+ useRef: c.useRef.bind(c),
308
+ useReducer: c.useReducer.bind(c),
309
+ onMount: c.onMount.bind(c),
310
+ onUnmount: c.onUnmount.bind(c),
311
+ hydrate: c.hydrate.bind(c),
312
+ }
313
+ c.render = comp.render;
314
+ c = comp;
315
+
316
+
317
+
318
+ console.log(req)
319
+ }else{
320
+ let comp = new component.default();
321
+ c.state = comp.state;
322
+ c = comp;
323
+ }
324
+
325
+
326
+
327
+
328
+
329
+
330
+
331
+
332
+
333
+ // Check if the root element exists
334
+ if (!document.querySelector('#root')) {
335
+ throw new Error('Root element not found, please add an element with id root');
336
+ }
337
+
338
+ c.reset();
339
+ c.components = {};
340
+ c.request = req;
341
+ c.response = res;
342
+ if (c.router.use && !c.isChild) {
343
+ await new Promise(async (resolve) => {
344
+ if(!isClass(component.default) ){
345
+ await component.default.apply(c, [req, res])
346
+ await c.router.use(req, res)
347
+ switch(req.pause){
348
+ case true:
349
+ let timer = setInterval(() => {
350
+ if (!req.pause) {
351
+ clearInterval(timer);
352
+ resolve();
353
+ }else{
354
+ console.log('still pausing request', req.url)
355
+ }
356
+ }, 1000);
357
+ break;
358
+ case false:
359
+ resolve();
360
+ break;
361
+ }
362
+ }else if(isClass(component.default)){
363
+
364
+ await c.router.use(req, res)
365
+ switch(req.pause){
366
+ case true:
367
+ console.log('pausing', req.pause)
368
+ let timer = setInterval(() => {
369
+ if (!req.pause) {
370
+ clearInterval(timer);
371
+ resolve();
372
+ }else{
373
+ console.log('still pausing', req.pause)
374
+ }
375
+ }, 1000);
376
+ break;
377
+ case false:
378
+ resolve();
379
+ break;
380
+ }
381
+ }else{
382
+ resolve();
383
+ }
384
+ });
385
+
386
+
387
+ } else if (c.router.use && c.isChild) {
388
+ console.warn('Router.use() is not supported in child components');
389
+ }
390
+ const renderedContent = await c.render();
391
+ if( document.querySelector('#root').innerHTML !== renderedContent){
392
+ console.log('rendering')
393
+ document.querySelector('#root').innerHTML = renderedContent;
394
+ }
395
+ c.bindMount();
396
+ c.onMount();
397
+
398
+ } catch (error) {
399
+ console.error(error);
400
+ }
401
+ },
402
+ setQuery: (query) => {
403
+ let queryString = '';
404
+ Object.keys(query).forEach((key, index) => {
405
+ queryString += `${index === 0 ? '?' : '&'}${key}=${query[key]}`;
406
+ });
407
+ let route = window.location.hash.split('?')[0];
408
+ queryString = queryString.replace('/', '-').replaceAll('/', '-')
409
+ window.location.hash = `${route}${queryString}`;
410
+ },
411
+ send: (data) => {
412
+ document.querySelector('#root').innerHTML = data;
413
+ },
414
+ json: (data) => {
415
+ const rootElement = document.querySelector('#root');
416
+
417
+ // Clear existing content in #root
418
+ rootElement.innerHTML = '';
419
+
420
+ // Create a <pre> element
421
+ const preElement = document.createElement('pre');
422
+
423
+ // Set the text content of the <pre> element with formatted JSON
424
+ preElement.textContent = JSON.stringify(data, null, 2);
425
+
426
+ // Append the <pre> element to the #root element
427
+ rootElement.appendChild(preElement);
428
+ }
429
+
430
+ };
431
+ middlewares.forEach((middleware) => {
432
+ middleware(req, res);
433
+ });
434
+
435
+ route ? route.handler(req, res) : null;
436
+ }
437
+
438
+
439
+ }
440
+
441
+ window.VaderRouter = VaderRouter;
442
+
443
+ export default VaderRouter;
444
+
package/runtime/vader.js CHANGED
@@ -645,12 +645,12 @@ window.Vader = {
645
645
  }
646
646
 
647
647
  }
648
-
649
- console.log(Link)
648
+
650
649
  export default {
651
650
  Component,
652
651
  useRef,
653
652
  useReducer,
654
653
  useState,
655
- strictMount
654
+ strictMount,
655
+ Link
656
656
  }