vaderjs 1.3.3-alpha-119 → 1.3.3-alpha-121

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-119",
5
+ "version": "1.3.3-alpha-121",
6
6
  "bin": {
7
7
  "vader": "./vader.js"
8
8
  },
package/runtime/router.js CHANGED
@@ -1,446 +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
- /**
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
- this.routes.push({
46
- path,
47
- handler,
48
- method: 'get',
49
- });
50
-
51
- }
52
- /**
53
- * @method use
54
- * @description This method allows you to use middlewares
55
- * @param {Function} middleware
56
- */
57
-
58
- use(/* path, */ 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
- window.onpopstate = async (e) => {
76
- let route = window.location.pathname
77
- let baseRoute = `/${route.split('/')[1]}`
78
- if(!this.checkroute(route)){
79
- route = '/404'
80
- }
81
- let html = new DOMParser().parseFromString(await fetch(baseRoute, {
82
- cache: 'reload'
83
- }).then((res)=>res.text()), 'text/html').documentElement
84
-
85
-
86
- document.querySelector('#root').innerHTML = html.querySelector('#root').innerHTML;
87
- document.title = html.querySelector('title').innerHTML;
88
- document.querySelector('script[id="router"]').remove();
89
- let newscript = document.createElement('script');
90
- newscript.id = 'router';
91
- newscript.innerHTML = html.querySelector('script[id="router"]').innerHTML;
92
- newscript.setAttribute('type', 'module');
93
- document.body.appendChild(newscript);
94
- }
95
-
96
- this.listeners.push(port);
97
- if (this.listeners.length === 1) {
98
- console.log(window.location.pathname)
99
- this.handleRoute(window.location.pathname);
100
- }else{
101
- this.listeners.pop();
102
- }
103
- if (callback) {
104
- callback();
105
- }
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('/').filter((part) => part !== '');
119
- const hashParts = hash.split('/').filter((part) => part !== '');
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
- checkroute(hash){
149
- let route = this.routes.find((route) => {
150
- if (route.path === hash) {
151
- return true;
152
- }
153
-
154
- if(hash === '' && route.path === '/'){
155
- return true
156
- }
157
-
158
- if(hash.includes('?')){
159
- hash = hash.split('?')[0]
160
- }
161
- if (route.path.includes('*') || route.path.includes(':')) {
162
- const routeParts = route.path.split('/').filter((part) => part !== '');
163
- const hashParts = hash.split('/').filter((part) => part !== '');
164
- if (routeParts.length !== hashParts.length && !route.path.endsWith('*')) {
165
- return false;
166
- }
167
-
168
- for (let index = 0; index < routeParts.length; index++) {
169
- const routePart = routeParts[index];
170
- const hashPart = hashParts[index];
171
-
172
-
173
- if (routePart.startsWith(':') || routePart.startsWith('*')) {
174
-
175
- continue;
176
- }
177
-
178
- if (routePart !== hashPart) {
179
- return false;
180
- }
181
- }
182
-
183
- return true;
184
- }
185
- const params = this.extractParams(route.path, hash);
186
- return Object.keys(params).length > 0;
187
- });
188
-
189
- return route;
190
-
191
- }
192
- /**
193
- * @method handleRoute
194
- * @param {String} hash
195
- * @description This method is used to handle the route
196
- */
197
-
198
- handleRoute(hash) {
199
- let status = 200;
200
- let paramsCatchall = {}
201
- let hashBefore = hash;
202
-
203
- let route = this.checkroute(hash);
204
- if (!route) {
205
- route = window.routes.find((errorRoute) => {
206
- if (errorRoute.url.includes('/404') && !this.error) {
207
- console.error(`Route ${hash} not found`);
208
- this.error = true;
209
- return false
210
-
211
- } else if (!this.error && errorRoute.url.includes('/404')){
212
- return true
213
- }
214
-
215
- });
216
-
217
- status = route ? 200 : 404;
218
- }
219
-
220
- const queryParams = this.extractQueryParams(hashBefore);
221
- const params = route && route.path ? this.extractParams(route.path, hashBefore) : paramsCatchall;
222
-
223
-
224
- // remove queryparams fromparam
225
- Object.keys(params).forEach((key)=>{
226
- params[key] = params[key].split('?') ? params[key].split('?')[0] : params[key];
227
- })
228
- const req = {
229
- headers: {},
230
- params: params,
231
- query: queryParams,
232
- path: hash,
233
- fileUrl: window.location.href.split(window.location.origin)[1],
234
- url: window.location.href,
235
- method: route ? route.method : 'get',
236
- pause: false,
237
- timestamp: Date.now(),
238
- };
239
-
240
- // @ts-ignore
241
- window.$CURRENT_URL = req.path
242
-
243
- // @ts-ignore
244
- window.$FULL_URL = window.location.href.replace('#', '')
245
-
246
- const res = {
247
- status: status,
248
- /**
249
- * @method log
250
- * @param {String} type
251
- * @description This method is used to log the request and response
252
- */
253
- log: (type) => {
254
- if(type === undefined){
255
- console.log(`${req.path} ${req.method} ${res.status} ${req.timestamp}`);
256
- }else{
257
- console.table({
258
- 'Request Path': req.path,
259
- 'Request Method': route.method,
260
- 'Response Status': res.status,
261
- 'Request Timestamp': req.timestamp,
262
- });
263
- }
264
- },
265
- refresh: () => {
266
- this.handleRoute(window.location.pathname)
267
- },
268
- redirect: (path) => {
269
- !path.startsWith('/') ? path = `/${path}` : null;
270
- window.history.pushState({}, '', path);
271
- window.dispatchEvent(new Event('popstate'));
272
- },
273
- render: async (/**@type {Component} */ component, req, res, metadata) => {
274
- function isClass(funcOrClass) {
275
- return typeof funcOrClass === 'function' &&
276
- /^class\s/.test(Function.prototype.toString.call(funcOrClass));
277
- }
278
-
279
- try {
280
- let c = new Component();
281
- if(!isClass(component.default)){
282
- let render = component.default.toString();
283
- if(render.includes('this.key')){
284
- throw new Error('Using this.key is not supported in functional components use the attribute key="a value" instead')
285
- }
286
-
287
-
288
-
289
- c.key = component.default.toString().split('key="')[1] ? component.default.toString().split('key="')[1].split('"')[0] : null;
290
-
291
- let comp = {
292
- key: c.key,
293
- render: () => {
294
- return component.default.apply(c, [req, res])
295
- },
296
- request: req,
297
- response: res,
298
- params: params,
299
- queryParams: queryParams,
300
- reset: c.reset.bind(c),
301
- onMount: c.onMount.bind(c),
302
- useState: null,
303
- router: {
304
- use: c.router.use.bind(c),
305
- },
306
- bindMount: c.bindMount.bind(c),
307
- memoize: c.memoize.bind(c),
308
- createComponent: c.createComponent.bind(c),
309
- isChild: false,
310
- useState: c.useState.bind(c),
311
- parseStyle: c.parseStyle.bind(c),
312
- bind: c.bind.bind(c),
313
- useRef: c.useRef.bind(c),
314
- useReducer: c.useReducer.bind(c),
315
- onMount: c.onMount.bind(c),
316
- onUnmount: c.onUnmount.bind(c),
317
- hydrate: c.hydrate.bind(c),
318
- }
319
- c.render = comp.render;
320
- c = comp;
321
-
322
- }else{
323
- let comp = new component.default();
324
- c.state = comp.state;
325
- c = comp;
326
- }
327
-
328
-
329
-
330
-
331
-
332
-
333
-
334
-
335
-
336
- // Check if the root element exists
337
- if (!document.querySelector('#root')) {
338
- throw new Error('Root element not found, please add an element with id root');
339
- }
340
-
341
- c.reset();
342
- c.components = {};
343
- c.request = req;
344
- c.response = res;
345
- if (c.router.use && !c.isChild) {
346
- await new Promise(async (resolve) => {
347
- if(!isClass(component.default) ){
348
- await component.default.apply(c, [req, res])
349
- await c.router.use(req, res)
350
- switch(req.pause){
351
- case true:
352
- let timer = setInterval(() => {
353
- if (!req.pause) {
354
- clearInterval(timer);
355
- resolve();
356
- }else{
357
- console.log('still pausing request', req.url)
358
- }
359
- }, 1000);
360
- break;
361
- case false:
362
- resolve();
363
- break;
364
- }
365
- }else if(isClass(component.default)){
366
-
367
- await c.router.use(req, res)
368
- switch(req.pause){
369
- case true:
370
- console.log('pausing', req.pause)
371
- let timer = setInterval(() => {
372
- if (!req.pause) {
373
- clearInterval(timer);
374
- resolve();
375
- }else{
376
- console.log('still pausing', req.pause)
377
- }
378
- }, 1000);
379
- break;
380
- case false:
381
- resolve();
382
- break;
383
- }
384
- }else{
385
- resolve();
386
- }
387
- });
388
-
389
-
390
- } else if (c.router.use && c.isChild) {
391
- console.warn('Router.use() is not supported in child components');
392
- }
393
- const renderedContent = await c.render();
394
- if( document.querySelector('#root').innerHTML !== renderedContent){
395
- document.querySelector('#root').innerHTML = renderedContent;
396
- }
397
- c.bindMount();
398
- c.onMount();
399
-
400
- } catch (error) {
401
- console.error(error);
402
- }
403
- },
404
- setQuery: (query) => {
405
- let queryString = '';
406
- Object.keys(query).forEach((key, index) => {
407
- queryString += `${index === 0 ? '?' : '&'}${key}=${query[key]}`;
408
- });
409
- let route = window.location.hash.split('?')[0];
410
- queryString = queryString.replace('/', '-').replaceAll('/', '-')
411
- window.location.hash = `${route}${queryString}`;
412
- },
413
- send: (data) => {
414
- document.querySelector('#root').innerHTML = data;
415
- },
416
- json: (data) => {
417
- const rootElement = document.querySelector('#root');
418
-
419
- // Clear existing content in #root
420
- rootElement.innerHTML = '';
421
-
422
- // Create a <pre> element
423
- const preElement = document.createElement('pre');
424
-
425
- // Set the text content of the <pre> element with formatted JSON
426
- preElement.textContent = JSON.stringify(data, null, 2);
427
-
428
- // Append the <pre> element to the #root element
429
- rootElement.appendChild(preElement);
430
- }
431
-
432
- };
433
- middlewares.forEach((middleware) => {
434
- middleware(req, res);
435
- });
436
-
437
- route ? route.handler(req, res) : null;
438
- }
439
-
440
-
441
- }
442
-
443
- window.VaderRouter = VaderRouter;
444
-
445
- export default VaderRouter;
446
-
1
+ import{Component}from"./vader.js";let middlewares=[];class VaderRouter{constructor(e,t){this.routes=[],this.middlewares=[],this.errorMiddlewares=[],this.listeners=[],this.basePath=e}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)),window.onpopstate=async e=>{let t=window.location.pathname,r=`/${t.split("/")[1]}`;this.checkroute(t)||window.devMode||(t="/404");let n=(new DOMParser).parseFromString(await fetch(r,{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 o=document.createElement("script");o.id="router",o.innerHTML=n.querySelector('script[id="router"]').innerHTML,o.setAttribute("type","module"),document.body.appendChild(o)},this.listeners.push(e),1===this.listeners.length?this.handleRoute(window.location.pathname):this.listeners.pop(),t&&t()}extractParams(e,t){const r=e.split("/").filter((e=>""!==e)),n=t.split("/").filter((e=>""!==e)),o={};return r.forEach(((e,t)=>{if(e.startsWith(":")){const r=e.slice(1);o[r]=n[t]}else if(e.startsWith("*")){n.slice(t).forEach(((e,t)=>{o[t]=e}))}})),o}extractQueryParams(e){const t=e.split("?")[1];if(!t)return{};const r={};return t.split("&").forEach((e=>{const[t,n]=e.split("=");r[t]=n})),r}checkroute(e){return 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 r=t.path.split("/").filter((e=>""!==e)),n=e.split("/").filter((e=>""!==e));if(r.length!==n.length&&!t.path.endsWith("*"))return!1;for(let e=0;e<r.length;e++){const t=r[e],o=n[e];if(!t.startsWith(":")&&!t.startsWith("*")&&t!==o)return!1}return!0}const r=this.extractParams(t.path,e);return Object.keys(r).length>0}))}handleRoute(e){let t=200,r=e,n=this.checkroute(e);n||(n=window.routes.find((e=>!e.url.includes("/404")||this.error||window.devMode?!(this.error||!e.url.includes("/404"))||void 0:(window.history.pushState({},"","/404"),window.dispatchEvent(new Event("popstate")),this.error=!0,!1))),t=n?200:404);const o=this.extractQueryParams(r),s=n&&n.path?this.extractParams(n.path,r):{};Object.keys(s).forEach((e=>{s[e]=s[e].split("?")?s[e].split("?")[0]:s[e]}));const i={headers:{},params:s,query:o,path:e,fileUrl:window.location.href.split(window.location.origin)[1],url:window.location.href,method:n?n.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":n.method,"Response Status":a.status,"Request Timestamp":i.timestamp})},refresh:()=>{this.handleRoute(window.location.pathname)},redirect:e=>{!e.startsWith("/")&&(e=`/${e}`),window.history.pushState({},"",e),window.dispatchEvent(new Event("popstate"))},render:async(e,t,r,n)=>{function i(e){return"function"==typeof e&&/^class\s/.test(Function.prototype.toString.call(e))}try{let n=new Component;if(i(e.default)){let t=new e.default;n.state=t.state,n=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');n.key=e.default.toString().split('key="')[1]?e.default.toString().split('key="')[1].split('"')[0]:null;let i={key:n.key,render:()=>e.default.apply(n,[t,r]),request:t,response:r,params:s,queryParams:o,reset:n.reset.bind(n),onMount:n.onMount.bind(n),useState:null,router:{use:n.router.use.bind(n)},bindMount:n.bindMount.bind(n),memoize:n.memoize.bind(n),createComponent:n.createComponent.bind(n),isChild:!1,useState:n.useState.bind(n),parseStyle:n.parseStyle.bind(n),bind:n.bind.bind(n),useRef:n.useRef.bind(n),useReducer:n.useReducer.bind(n),onMount:n.onMount.bind(n),onUnmount:n.onUnmount.bind(n),hydrate:n.hydrate.bind(n)};n.render=i.render,n=i}if(!document.querySelector("#root"))throw new Error("Root element not found, please add an element with id root");n.reset(),n.components={},n.request=t,n.response=r,n.router.use&&!n.isChild?await new Promise((async o=>{if(i(e.default))if(i(e.default))switch(await n.router.use(t,r),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(n,[t,r]),await n.router.use(t,r),t.pause){case!0:let e=setInterval((()=>{t.pause?console.log("still pausing request",t.url):(clearInterval(e),o())}),1e3);break;case!1:o()}})):n.router.use&&n.isChild&&console.warn("Router.use() is not supported in child components");const a=await n.render();document.querySelector("#root").innerHTML!==a&&(document.querySelector("#root").innerHTML=a),n.bindMount(),n.onMount()}catch(e){console.error(e)}},setQuery:e=>{let t="";Object.keys(e).forEach(((r,n)=>{t+=`${0===n?"?":"&"}${r}=${e[r]}`}));let r=window.location.hash.split("?")[0];t=t.replace("/","-").replaceAll("/","-"),window.location.hash=`${r}${t}`},send:e=>{document.querySelector("#root").innerHTML=e},json:e=>{const t=document.querySelector("#root");t.innerHTML="";const r=document.createElement("pre");r.textContent=JSON.stringify(e,null,2),t.appendChild(r)}};middlewares.forEach((e=>{e(i,a)})),n&&n.handler(i,a)}}window.VaderRouter=VaderRouter;export default VaderRouter;
package/vader.js CHANGED
@@ -726,13 +726,10 @@ async function Build() {
726
726
  if (route.url.includes(':')) {
727
727
  console.log('Route ' + route.url + ' is a dynamic route and will not be generated')
728
728
  return
729
- }
730
- console.log('Generating html file for route ' + route.url)
731
- let equalparamroute = routes.map((e) => {
732
- console.log(e.url, route.url)
729
+ }
730
+ let equalparamroute = routes.map((e) => {
733
731
  if (e.url.includes(':')) {
734
- let url = e.url.split('/:')[0]
735
- console.log(url, route.url)
732
+ let url = e.url.split('/:')[0]
736
733
  if (url && route.url === url) {
737
734
  return e
738
735
  } else {
@@ -752,6 +749,7 @@ async function Build() {
752
749
  <meta charset="UTF-8">
753
750
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
754
751
  <script type="module" id="meta">
752
+ window.history.pushState({}, '', '${route.url}')
755
753
  window.module = await import('/${route.fileName.replace('.jsx', '.js')}')
756
754
  let metadata = await module.$metadata
757
755
  if(metadata && metadata.title){
@@ -832,8 +830,8 @@ async function Build() {
832
830
  let port = Math.floor(Math.random() * (65535 - 49152 + 1) + 49152)
833
831
 
834
832
  const server = http.createServer((req, res) => {
835
- if (req.url === '/') {
836
- // Respond with the generated HTML
833
+
834
+ if (req.url === '/') {
837
835
  res.writeHead(200, { 'Content-Type': 'text/html' });
838
836
  res.end(document);
839
837
  } else {
@@ -857,14 +855,14 @@ async function Build() {
857
855
  globalThis.listen = true;
858
856
 
859
857
  puppeteer.launch({
860
- headless: "new", args: ['--no-sandbox', '--disable-setuid-sandbox'],
858
+ headless: "new", args: ['--no-sandbox', '--disable-setuid-sandbox'],
861
859
  warning: false,
862
860
  }).then(async (browser) => {
863
861
 
864
862
  // remove /: from route
865
863
  route.url = route.url.replaceAll(/\/:[a-zA-Z0-9_-]+/gs, '')
866
- const page = await browser.newPage();
867
- await page.goto(`http://localhost:${port}` + '#' + route.url, { waitUntil: 'networkidle2' });
864
+ const page = await browser.newPage();
865
+ await page.goto(`http://localhost:${port}/` , { waitUntil: 'networkidle2' });
868
866
  await page.waitForSelector('#root');
869
867
  await page.evaluate(() => {
870
868
  document.getElementById('meta').remove()
@@ -1,3 +0,0 @@
1
- {
2
- "rewrites": [{ "source": "/:path*", "destination": "/index.html" }]
3
- }