vaderjs 1.3.3-alpha-3 → 1.3.3-alpha-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/README.md CHANGED
@@ -64,6 +64,7 @@ public - used for anything
64
64
 
65
65
  4. And your done - Run `bun run vader --build` and the compiled output is visible inside of the `/dist/` folder!
66
66
 
67
+
67
68
  ## Key Features & Examples
68
69
 
69
70
  ### File based routing
package/package.json CHANGED
@@ -2,20 +2,12 @@
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-3",
5
+ "version": "1.3.3-alpha-5",
6
6
  "bin": {
7
7
  "vader": "./vader.js"
8
8
  },
9
- "scripts": {
10
- "build": "bunx vader --build",
11
- "watch": "bun run vader --watch",
12
- "help": "bunx vader"
13
- },
14
9
  "type": "module",
15
- "devDependencies": {
16
- "@types/bun": "latest"
17
- },
18
- "peerDependencies": {
19
- "typescript": "^5.0.0"
10
+ "dependencies": {
11
+ "glob": "latest"
20
12
  }
21
- }
13
+ }
@@ -10,7 +10,7 @@
10
10
  <body>
11
11
  <div id="root"></div>
12
12
  <script type="module">
13
- import VaderRouter from './public/vader/router.js'
13
+ import VaderRouter from './router.js'
14
14
 
15
15
  const router = new VaderRouter('/', 3000)
16
16
  window.router = router
@@ -0,0 +1,552 @@
1
+
2
+ window.params = {};
3
+ window.Vader = {
4
+ version: "1.3.2",
5
+ };
6
+
7
+ let errors = {
8
+ "SyntaxError: Unexpected token '<'": "You forgot to enclose tags in a fragment <></>",
9
+ }
10
+
11
+ const path = {
12
+ basename: (path) => {
13
+ return path.split("/").pop();
14
+ },
15
+
16
+ }
17
+
18
+ window.queryRef = (ref) => {
19
+ return document.querySelector(`[data-ref="${ref}"]`)
20
+ }
21
+ window.reinvoke = (eventtype, element) => {
22
+ const eventListener = (e) => {
23
+ return e
24
+ };
25
+
26
+ // Check if the event listener has not been added before adding it
27
+ if (!element._eventListenerAdded) {
28
+ element.addEventListener(eventtype, eventListener);
29
+
30
+ // Set the flag to indicate that the event listener has been added
31
+ element._eventListenerAdded = true;
32
+
33
+ // Trigger the event without overwriting existing data or listeners
34
+ element.dispatchEvent(new Event(eventtype));
35
+ }
36
+ };
37
+
38
+
39
+
40
+
41
+ let invokes = []
42
+ let hasran = [];
43
+ let states = {};
44
+ let mounts = [];
45
+ export const strictMount = (key, callback) => {
46
+ let interval = setInterval(() => {
47
+ if(mounts.find(mount => mount.key === key)
48
+ && !hasran.includes(callback.toString())
49
+ ){
50
+ callback();
51
+ clearInterval(interval)
52
+
53
+ hasran.push(callback.toString());
54
+ }
55
+ },0);
56
+ };
57
+
58
+ window.delegate = (event) => {
59
+ return event.detail.target
60
+ }
61
+
62
+ let components = {};
63
+
64
+ let style = document.createElement("style");
65
+ document.head.appendChild(style);
66
+
67
+ const parseStyles = async (styles, className = '') => {
68
+ let css = await fetch(styles).then((res) => res.text());
69
+ let classes = css.split("}");
70
+ let parsedClasses = {};
71
+ classes.forEach((cls) => {
72
+
73
+ let name = cls.split(".")[1];
74
+ let value = cls.split("{")[1]
75
+ let keys = value.split(";");
76
+ let newKeys = [];
77
+ keys.forEach((key) => {
78
+ if (key.includes(":")) {
79
+ let newKey = key.split(":")[0].trim();
80
+ let newValue = key.split(":")[1].trim();
81
+ newKeys.push(`${newKey}: "${newValue}"`);
82
+ }
83
+ });
84
+ value = `{${newKeys.join(",")}}`;
85
+
86
+
87
+ parsedClasses[name] = JSON.stringify(value);
88
+ });
89
+ return parsedClasses;
90
+ };
91
+
92
+
93
+ export const stylis = {
94
+ /**
95
+ * @method create
96
+ * @param {*} styles
97
+ * @returns {Object} classes
98
+ * @description This method allows you to create css classes from an object
99
+ */
100
+ create: async (/**@type {string} */ styles) => {
101
+
102
+ return await parseStyles(styles);
103
+ },
104
+ };
105
+
106
+ /**
107
+ * @method mem
108
+ * @param {Component} component
109
+ * @returns {Component} Stateless Component
110
+ * @description This method allows you to memoize a component - this means it will be intialized only once and can be reused multiple times baased on a static key
111
+ */
112
+ export const mem = (/**@type {Component}**/ component) => {
113
+ // ensure component is instance of Component
114
+ switch (true) {
115
+ case !(component instanceof Component):
116
+ throw new Error("component must be an instance of Component");
117
+ case !component.key:
118
+ throw new Error("component must have a static key");
119
+ // check if key was randomly generated
120
+ }
121
+ let key = component.key;
122
+ if (!components[key]) {
123
+ components[key] = component;
124
+ }
125
+
126
+ return components[key];
127
+ };
128
+
129
+ /**
130
+ * @method invoke
131
+ * @description This method allows you to invoke a function from its id
132
+ * @param {*} name
133
+ * @param {*} params
134
+ * @returns
135
+ * @example
136
+ * invoke(this.functions['test'], 'hello') // this will invoke the function test with the params hello
137
+ */
138
+
139
+ let functions = {};
140
+
141
+ export const invoke = (func, params) => {
142
+ let name = func.name;
143
+
144
+ window[name] = function (params) {
145
+ return func(params);
146
+ }
147
+ window[name] = window[name].bind(this);
148
+
149
+
150
+ return `${name}(${params})`;
151
+
152
+ };
153
+
154
+ /**
155
+ * Represents a component in the Vader framework.
156
+ */
157
+ export class Component {
158
+ /**
159
+ * Creates an instance of Component.
160
+ */
161
+ constructor() {
162
+ this.state = {};
163
+ this.key = null;
164
+ this.components = {};
165
+ this.mounted = false;
166
+ this.checkIFMounted();
167
+ this.currenthtml = null;
168
+ window.listeners = [];
169
+ this.functionMap = new Map();
170
+ this.freeMemoryFromFunctions();
171
+ this.memoizes = []
172
+ this.children = []
173
+ }
174
+
175
+ createComponent(/**@type {Component}**/component, props, children) {
176
+
177
+ if (!component) {
178
+ throw new Error("Component must be defined");
179
+ }
180
+ if(!props.key){
181
+ throw new Error('new components must have a key')
182
+ }
183
+ let comp = new component();
184
+
185
+ comp['props'] = props;
186
+ comp.children = children;
187
+ comp.props.children = children.join('')
188
+ comp.parentNode = this;
189
+ comp.key = props.key || null;
190
+ this.components[props.key] = comp
191
+ this.children.push(comp)
192
+ return this.components[props.key]
193
+ }
194
+ memoize(/**@type {Component}**/component){
195
+ if(!component.key){
196
+ throw new Error('Component must have a static key')
197
+ }
198
+ switch(true){
199
+ case !this.memoizes.includes(component.key):
200
+ this.memoizes.push(component.key)
201
+ this.components[component.key] = component;
202
+ break;
203
+ }
204
+
205
+ let comp = this.components[component.key];
206
+ let h = comp.render()
207
+
208
+ if(h && h.split('>,').length > 1){
209
+ h = h.replaceAll('>,', '>')
210
+ }
211
+
212
+ return `<div key="${component.key}">${h}</div>`
213
+ }
214
+ parseStyle(styles){
215
+ let css = ''
216
+ Object.keys(styles).forEach((key) => {
217
+ let value = styles[key]
218
+ key = key.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, '$1-$2').toLowerCase()
219
+ css += `${key}:${value};`
220
+ })
221
+ return css
222
+ }
223
+ bindMount(){
224
+ mounts.push(this)
225
+ }
226
+
227
+ /**
228
+ * Hydrates the component by updating the HTML content if it has changed.
229
+ * @private
230
+ */
231
+ hydrate() {
232
+ if (this.key) {
233
+
234
+ const el = document.querySelector(`[key="${this.key}"]`);
235
+
236
+
237
+ if (el) {
238
+
239
+
240
+ // Render the new HTML content
241
+ const newHtml = this.render();
242
+ // Compare the new HTML with the cached content
243
+ if (newHtml !== this.currentHtml) {
244
+ // Update the HTML only if it has changed
245
+ el.innerHTML = newHtml;
246
+
247
+ // Update the cached HTML content
248
+ this.currentHtml = newHtml;
249
+ }
250
+ }
251
+ }
252
+ }
253
+
254
+ /**
255
+ * Handles an object by parsing it as JSON and evaluating it.
256
+ * @param {string} obj - The object to handle.
257
+ * @returns {*} - The evaluated object.
258
+ * @prvate
259
+ */
260
+ handleObject(obj) {
261
+ try {
262
+ obj = JSON.parse(obj);
263
+ } catch (error) {
264
+ // Handle JSON parsing error if needed
265
+ }
266
+ return eval(obj);
267
+ }
268
+
269
+ /**
270
+ * Frees memory from functions that have not been used for a certain period of time.
271
+ * @private
272
+ */
273
+ freeMemoryFromFunctions() {
274
+ setInterval(() => {
275
+ for (var [key, value] in this.functionMap) {
276
+ if (Date.now() - value.lastUsed > 1000) {
277
+ this.functionMap.delete(key);
278
+ }
279
+ }
280
+ }, 1000);
281
+ }
282
+
283
+ /**
284
+ * Binds a function to the component.
285
+ * @param {string} funcData - The function data.
286
+ * @param {string} p - The parameter.
287
+ * @param {string} ref - The reference.
288
+ * @returns {string} - A valid inline JS function call.
289
+ */
290
+ bind(funcData, d) {
291
+
292
+ const name = `func_${crypto ? crypto.getRandomValues(new Uint32Array(1))[0] : Math.random()}`;
293
+
294
+ var dynamicFunction = (params) => {
295
+ let func = new Function(`return (async (${params}) => {
296
+ console.log('called')
297
+ ${funcData}
298
+ })()`);
299
+ func = func.bind(this);
300
+ func(params);
301
+ };
302
+
303
+ dynamicFunction = dynamicFunction.bind(this);
304
+ if (!this.functionMap.has(name)) {
305
+ document.addEventListener(`call_${name}`, (e) => {
306
+
307
+ dynamicFunction();
308
+ this.functionMap.set(e.detail.name, {
309
+ lastUsed: Date.now(),
310
+ });
311
+ });
312
+ }
313
+
314
+ this.functionMap.set(name, {
315
+ lastUsed: Date.now(),
316
+ });
317
+
318
+ window.call = (name, eventdata, params) => {
319
+ document.dispatchEvent(
320
+ new CustomEvent(`call_${name}`, {
321
+ detail: { name: `call_${name}`, target: eventdata },
322
+ })
323
+ );
324
+ };
325
+
326
+ // Return a valid inline js function call
327
+ return d.jsx ? dynamicFunction : `
328
+ ((event) => {
329
+ event.target.setAttribute('data-ref', '${d.ref}');
330
+ let reference = event.target.getAttribute('data-ref');
331
+ event.target.eventData = event;
332
+ let domquery = queryRef(reference);
333
+ domquery.eventData = event;
334
+ domquery.eventData.detail.target = domquery;
335
+ call('${name}', {event:domquery.eventData}, '${d.params}')
336
+ })(event)
337
+ `;
338
+ }
339
+
340
+ /**
341
+ * Calls a function with the specified parameters. and dispatches an event.
342
+ * @param {string} func - The function name.
343
+ * @param {...*} params - The function parameters.
344
+ */
345
+ callFunction(func, isInlineJsx, ...params) {
346
+ if(!isInlineJsx && params[0] && params[0].detail){
347
+ let el = params[0].detail.target.event.target
348
+ params[0].data = el.value;
349
+ params[0] = params[0].detail.target.event
350
+ }
351
+ func = func.replace(/'/g, '');
352
+ document.dispatchEvent(new CustomEvent(func, { detail: { name: func, params: params } }));
353
+ }
354
+
355
+ /**
356
+ * Uses a function with the specified parameters.
357
+ * @param {Function} func - The function to use.
358
+ * @param {string} params - The function parameters.
359
+ * @param {boolean} [isInlineJsx=false] - Indicates if the function is an inline JSX.
360
+ * @returns {string} - The function call.
361
+ */
362
+ useFunction(func, params, isInlineJsx = false) {
363
+ const sanitizedFuncName = func.name.trim().replace(/\s+/g, '_');
364
+
365
+ if (!invokes.includes(`'${sanitizedFuncName}'${this.key}`)) {
366
+ invokes.push(`'${sanitizedFuncName}'${this.key}`);
367
+ document.addEventListener(`call_${sanitizedFuncName}_${this.key}`, (e) => {
368
+ let { name, params } = e.detail;
369
+ if (name === `call_${sanitizedFuncName}_${this.key}`) {
370
+ let isarray = Array.isArray(params);
371
+
372
+ func(...(isarray ? params : [params]));
373
+ }
374
+ });
375
+
376
+ func = func.bind(this);
377
+ }
378
+
379
+ try {
380
+ params = JSON.parse(params);
381
+ } catch (error) {
382
+ // Handle JSON parsing error if needed
383
+ }
384
+
385
+ const returnString = isInlineJsx
386
+ ? `'call_${sanitizedFuncName}_${this.key}'`
387
+ : `document.dispatchEvent(new CustomEvent('call_${sanitizedFuncName}_${this.key}', { detail: { name: 'call_${sanitizedFuncName}_${this.key}', params: ${JSON.stringify(params)} } }))`;
388
+
389
+ return returnString;
390
+ }
391
+
392
+ /**
393
+ * Uses state to dynamically update the component.
394
+ * @method useState
395
+ * @param {string} [key=null] - The auto-generated key.
396
+ * @param {*} initialState - The initial state.
397
+ * @param {Component.render} [func=null] - The render function.
398
+ * @returns {Array} - An array containing the state value and the setter function.
399
+ */
400
+ useState(key = null, initialState) {
401
+ if (!this.state[key]) {
402
+ this.state[key] = initialState;
403
+ }
404
+ const getValue = () => this.state[key];
405
+ const set = (newValue) => {
406
+ this.state[key] = newValue;
407
+ this.hydrate();
408
+ };
409
+ return [getValue, set];
410
+ }
411
+
412
+ useRef(key = null, initialState) {
413
+ if (!this.state[key]) {
414
+ this.state[key] = initialState;
415
+ }
416
+ const getValue = () => this.state[key];
417
+ const set = (newValue) => {
418
+ this.state[key] = newValue;
419
+ this.hydrate();
420
+ };
421
+ return {
422
+ bind: key,
423
+ current: () => document.querySelector(`[ref="${key}"]`) || this.state[key],
424
+ }
425
+ }
426
+
427
+ useReducer(key = null, initialState, func = null) {
428
+ const getValue = () => this.state[key];
429
+ const set = (newValue) => {
430
+
431
+ this.hydrate();
432
+ };
433
+ return [getValue, set];
434
+ }
435
+
436
+ /**
437
+ * Placeholder for content to be rendered.
438
+ * @method render
439
+ */
440
+ render() {}
441
+
442
+ /**
443
+ * Checks if the component is mounted and triggers the onMount method.
444
+ * @private
445
+ */
446
+ checkIFMounted() {
447
+ if (this.mounted) return;
448
+ let timer = setInterval(() => {
449
+ if (document.querySelector('[key="' + this.key + '"]')) {
450
+ clearInterval(timer);
451
+ this.mounted = true;
452
+ this.onMount();
453
+ }
454
+ }, 120);
455
+ }
456
+
457
+ /**
458
+ * Method that is called when the component is mounted.
459
+ * @method onMount
460
+ */
461
+ onMount() {}
462
+ }
463
+
464
+
465
+
466
+
467
+
468
+ let cache = {};
469
+ /**
470
+ * @method require
471
+ * @description Import CommonJS modules like Node.js for the browser
472
+ * @param {string} path
473
+ * @param {Boolean} noresolve - used to tell if the path should be automatically handled or manually handled - this is false by default
474
+ * @returns
475
+ */
476
+ export const require = async (path, noresolve = false) => {
477
+
478
+ if (cache[path]) {
479
+ return cache[path];
480
+ }
481
+ let file = ''
482
+ try {
483
+ file = await fetch(path).then((res) => res.text());
484
+ } catch (error) {
485
+ console.error(error)
486
+ }
487
+
488
+ file = file + `\n//# sourceURL=${path}\n`;
489
+
490
+ let filetype = path.split(".").pop();
491
+ switch (true) {
492
+ case filetype === "js":
493
+ let exports = file.match(/module.exports\s*=\s*{.*}/gs) || file.match(/exports\s*=\s*{.*}/gs);
494
+ exports = exports ? exports[0] : null;
495
+
496
+ if (exports) {
497
+ let keys = exports.split("{")[1].split("}")[0].split(",");
498
+ let returnstring = "";
499
+ keys.forEach((key) => {
500
+ key = key.trim();
501
+ returnstring += `${key},`;
502
+ });
503
+ returnstring = `return {${returnstring}}`;
504
+ file = file += returnstring;
505
+ file = file.replaceAll(exports, "");
506
+ }
507
+
508
+ return new Function(`return (async () => { ${file} })()`)();
509
+ case filetype === "jsx":
510
+ return new Function(`return (async () => { ${file} })()`)()
511
+
512
+ }
513
+ };
514
+
515
+
516
+ window.require = require;
517
+
518
+ /**
519
+ * @method useState - type
520
+ * @param {*} initialState
521
+ * @returns {Array} [value, set]
522
+ * @description Allows you to use state to dynamically update your component
523
+ */
524
+ export const useState = (initialState) => {
525
+ let value = initialState;
526
+ if (key && !states[key]) {
527
+ this.states[key] = initialState;
528
+ }
529
+ return [value, (newValue) => {}];
530
+ };
531
+
532
+ const constants = {};
533
+ let constantCounter = 0;
534
+
535
+ export const constant = (value) => {
536
+ const key = `constant_${constantCounter++}`;
537
+ if (!constants[key]) {
538
+ constants[key] = value;
539
+ }
540
+ return constants[key];
541
+ };
542
+
543
+ export default {
544
+ Component,
545
+ require,
546
+ invoke,
547
+ mem,
548
+ constant,
549
+ useState,
550
+ strictMount,
551
+ stylis,
552
+ }
package/vader.js CHANGED
@@ -1,24 +1,20 @@
1
- #!/usr/bin/env bun
2
-
3
- import fs, { watchFile } from "fs";
4
-
5
- import { Glob } from "bun";
1
+ #!/usr/bin/env node
2
+ import fs from "fs";
3
+ import { glob, globSync, globStream, globStreamSync, Glob } from 'glob'
4
+
6
5
  let bundleSize = 0;
7
- switch (true) {
8
- case !fs.existsSync(process.cwd() + "/pages"):
9
- fs.mkdirSync(process.cwd() + "/pages");
10
- break;
11
- case !fs.existsSync(process.cwd() + "/dist"):
12
- fs.mkdirSync(process.cwd() + "/dist");
13
- console.log("Created dist folder");
14
- case !fs.existsSync(process.cwd() + "/public"):
15
- fs.mkdirSync(process.cwd() + "/public");
16
- break;
17
- case !fs.existsSync(process.cwd() + "/src"):
18
- fs.mkdirSync(process.cwd() + "/src");
19
- break;
6
+ if(!fs.existsSync(process.cwd() + '/dist')){
7
+ fs.mkdirSync(process.cwd() + '/dist')
8
+ fs.mkdirSync(process.cwd() + '/dist/public')
9
+ fs.mkdirSync(process.cwd() + '/dist/src')
10
+ fs.mkdirSync(process.cwd() + '/dist/pages')
11
+ }else if(!fs.existsSync(process.cwd() + '/dist/public')){
12
+ fs.mkdirSync(process.cwd() + '/dist/public')
13
+ }else if(!fs.existsSync(process.cwd() + '/src') && !fs.existsSync(process.cwd() + '/dist/src')){
14
+ fs.mkdirSync(process.cwd() + '/dist/src')
15
+ fs.mkdirSync(process.cwd() + '/src')
20
16
  }
21
-
17
+
22
18
  function Compiler(func) {
23
19
  let string = func;
24
20
  let comments = string
@@ -222,7 +218,8 @@ function Compiler(func) {
222
218
  otherdata["jsx"] = isJSXComponent;
223
219
  otherdata["ref"] = ref;
224
220
 
225
- newvalue = newvalue.replaceAll(/\s+/g, "\n");
221
+ newvalue = newvalue.split('\n').map(line => line.trim() ? line.trim() + ';' : line).join('\n');
222
+
226
223
  let newatribute = `${attributeName}="\${this.bind(\`${newvalue}\` ${isJSXComponent ? "" : ","
227
224
  }${JSON.stringify(otherdata)} )}"`;
228
225
 
@@ -258,8 +255,9 @@ function Compiler(func) {
258
255
  params ? (otherdata["params"] = params) : null;
259
256
  otherdata["jsx"] = isJSXComponent;
260
257
  otherdata["ref"] = ref;
261
- newvalue = newvalue.replaceAll(/\s+/g, ";");
262
- let newattribute = `${attributeName}="\${this.bind(\`${newvalue}\`, ${isJSXComponent ? "" : ","}${JSON.stringify(otherdata)} )}"`;
258
+ // since js is all in one line split it
259
+ newvalue = newvalue.split('\n').map(line => line.trim() ? line.trim() + ';' : line).join('\n');
260
+ let newattribute = `${attributeName}="\${this.bind(\`${newvalue}\` ${isJSXComponent ? "" : ","}${JSON.stringify(otherdata)} )}"`;
263
261
  newattribute = newattribute.replace(/\s+/g, " ")
264
262
  string = string.replace(old, newattribute);
265
263
  }
@@ -581,91 +579,86 @@ async function Build() {
581
579
  globalThis.isBuilding = true
582
580
  console.log('Compiling......')
583
581
  let reader = async (file) => {
584
- let text = await Bun.file(file).text();
582
+ let text = await fs.readFileSync(file, "utf8");
585
583
  return text;
586
584
  };
587
585
  let writer = async (file, data) => {
588
- await Bun.write(file, data);
586
+ switch (true) {
587
+ case !fs.existsSync(file):
588
+ fs.mkdirSync(file.split('/').slice(0, -1).join('/'), { recursive: true })
589
+ break;
590
+ }
591
+ await fs.writeFileSync(file, data);
589
592
 
590
593
  return { _written: true };
591
594
  };
592
595
 
593
596
 
594
- const glob = new Glob("**/*.{jsx,js}");
595
- for await (let file of glob.scan({ cwd: process.cwd() + '/pages/', absolute: true })) {
596
- let origin = file.split(process.cwd())[1] || file
597
+ const glb = await glob("**/**/**/**.{jsx,js}", {
598
+ ignore: ["node_modules/**/*", "dist/**/*"],
599
+ cwd: process.cwd() + '/pages/',
600
+ absolute: true,
601
+ recursive: true
602
+ });
603
+ for await (let file of glb) {
604
+
605
+ let origin = file.split(process.cwd())[1] || file
606
+ let fileName = file.split(process.cwd() + '/pages/')[1]
597
607
  file = file.split(process.cwd() + '/pages/')[1]
598
- bindings[file] = ''
599
- const router = new Bun.FileSystemRouter({
600
- style: "nextjs",
601
- dir: process.cwd() + "/pages/",
602
- origin: process.env.ORIGIN || "http://localhost:3000",
603
- assetPrefix: "_next/static/",
604
- fileExtensions: [".jsx", ".js"],
605
- });
606
-
607
-
608
- let m = router.match(origin.includes('/pages/index.jsx') ? '/' : '/' + file)
609
- router.reload()
610
-
611
- if (!m) {
612
- console.error(`Error: ${file} is not a valid route\nFollow Proper Routing Structure:
613
- `)
614
- console.info(`
615
- /pages/index.jsx
616
- /pages/folder/index.jsx
617
- /pages/folder/[param].jsx
618
- `)
619
- process.exit(1)
620
- }
608
+
609
+ file === 'index.jsx' ? file = '/' : null
610
+ let isBasePath = file === '/' ? true : false
611
+ // ex: /pages/index.jsx - / or /pages/[id].jsx - /:id or /pages/folder/index.jsx - /folder
612
+ let aburl = origin.split('pages')[1].split('.jsx')[0].replace('.jsx', '').replace('/index', '').replace('/_', '/:').replace('/[', '/:').replace(']', '')
621
613
 
614
+ aburl.includes('[') ? aburl = '/' + aburl.split('[')[0].replace('/', '') : null
615
+
622
616
 
623
- let writtenpath = ''
624
- // change /home/[app].jsx to /home
625
- m && m.kind === 'dynamic' ? writtenpath = m.pathname.split('[')[0] : null
617
+
618
+
619
+
626
620
 
627
621
  let obj = {
628
- filePath: m.filePath,
629
- kind: m.kind,
630
- params: m.params,
631
- query: m.query,
632
- scriptSrc: m.scriptSrc,
633
- src: m.src,
634
- pathname: writtenpath || m.pathname,
635
- }
636
-
637
- let data = await reader(process.cwd() + "/pages/" + file)
622
+ url: isBasePath ? '/' : aburl,
623
+ pathname: origin,
624
+ }
625
+ let data = await reader(process.cwd() + origin)
626
+
638
627
  data = Compiler(data)
639
- await writer(process.cwd() + "/dist/pages/" + file, data);
628
+ await writer(process.cwd() + "/dist/pages/" + fileName, data);
640
629
  let params = obj.params ? Object.keys(obj.params).map((r) => {
641
630
  r = r.replace('[', '').replace(']', '')
642
631
  return `:${r}`
643
632
  }) : ''
644
633
 
645
- obj.pathname === '//' ? obj.pathname = '/' : null
634
+
646
635
 
647
636
 
648
637
 
649
638
  let js = `
650
- router.get('${obj.pathname.includes('.jsx') ? obj.pathname.replace('.jsx', '') + params : obj.pathname + params}', async (req, res) => {
651
- res.render(await require('./pages/${file}'), req, res)
639
+ router.get('${obj.url}', async (req, res) => {
640
+ res.render(await require('.${obj.pathname}'), req, res)
652
641
  })
653
- //@desc ${obj.filePath}
642
+ //@desc ${obj.pathname}
654
643
  ` + '\n'
655
644
 
656
645
 
657
646
 
658
- let before = await Bun.file(process.cwd() + "/dist/app.js").exists() ? await reader(process.cwd() + "/dist/app.js") : ''
647
+ let before = fs.existsSync(process.cwd() + "/dist/app.js") ? await reader(process.cwd() + "/dist/app.js") : ''
659
648
 
660
649
  let newfile = before + '\n' + js
661
- if (!before.includes(`//@desc ${obj.filePath}`)) {
650
+ if (!before.includes(`//@desc ${obj.pathname}`)) {
662
651
  await writer(process.cwd() + "/dist/app.js", newfile);
663
652
  }
664
653
 
665
654
  }
666
655
 
667
- const gb = new Glob("*");
668
- const scannedSourceFiles = await Array.fromAsync(gb.scan({ cwd: process.cwd() + '/src/', absolute: true }));
656
+
657
+ const scannedSourceFiles = await glob("**/**.{jsx,js}", {
658
+ ignore: ["node_modules/**/*", "dist/**/*"],
659
+ cwd: process.cwd() + '/src/',
660
+ absolute: true,
661
+ });
669
662
  scannedSourceFiles.forEach(async (file) => {
670
663
 
671
664
  file = file.split(process.cwd() + '/src/')[1]
@@ -678,57 +671,43 @@ async function Build() {
678
671
  await writer(process.cwd() + "/dist/src/" + file, data);
679
672
  })
680
673
 
681
- const scannedPublicFiles = await Array.fromAsync(gb.scan({ cwd: process.cwd() + '/public/', absolute: true }));
674
+ const scannedPublicFiles = await glob("**/**.{css,js,html}", {
675
+ ignore: ["node_modules/**/*", "dist/**/*"],
676
+ cwd: process.cwd() + '/public/',
677
+ absolute: true,
678
+ });
682
679
  scannedPublicFiles.forEach(async (file) => {
683
680
  file = file.split(process.cwd() + '/public/')[1]
684
681
  let data = await reader(process.cwd() + "/public/" + file)
685
682
  bundleSize += fs.statSync(process.cwd() + "/public/" + file).size;
686
683
  await writer(process.cwd() + "/dist/public/" + file, data);
687
- })
688
- const scannedFiles = await Array.fromAsync(gb.scan({ cwd: process.cwd() + '/node_modules/vaderjs/' + './runtime/static' }));
689
- const scannedVaderFiles = await Array.fromAsync(
690
- gb.scan({ cwd: process.cwd() + '/node_modules/vaderjs/' + "/runtime/" })
691
- );
684
+ })
685
+ const scannedFiles = await glob("**/**.{css,js,html}", {
686
+ ignore: ["node_modules/**/*", "dist/**/*"],
687
+ cwd: process.cwd() + "/runtime/",
688
+ absolute: true,
689
+ })
692
690
 
693
691
  if (!fs.existsSync(process.cwd() + "/dist/index.html")) {
694
692
  scannedFiles.forEach(async (file) => {
693
+ file = file.split(process.cwd() + '/runtime/')[1]
695
694
 
696
695
  if (file === "app.js") {
697
696
  return
698
697
  }
699
- bundleSize += fs.statSync(process.cwd() + '/node_modules/vaderjs/' + "/runtime/static/" + file).size;
700
- let data = await reader(process.cwd() + '/node_modules/vaderjs/' + "/runtime/static/" + file);
698
+ bundleSize += fs.statSync(process.cwd() + "/runtime/" + file).size;
699
+ let data = await reader(process.cwd() + "/runtime/" + file)
701
700
  await writer(process.cwd() + "/dist/" + file, data);
702
701
  });
703
- scannedVaderFiles.forEach(async (file) => {
704
- bundleSize += fs.statSync(
705
- process.cwd() + '/node_modules/vaderjs/' + "/runtime/" + file
706
- ).size;
707
- let data = await reader(process.cwd() + '/node_modules/vaderjs/' + "/runtime/" + file);
708
- await writer(process.cwd() + "/dist/public/vader/" + file, data);
709
- });
702
+
710
703
  }
711
704
 
712
-
713
- if (!fs.existsSync(process.cwd() + "/dist/index.html")) {
714
- scannedFiles.forEach(async (file) => {
715
-
716
- bundleSize += fs.statSync(process.cwd() + '/node_modules/vaderjs/' + "/runtime/static/" + file).size;
717
- let data = await reader(process.cwd() + '/node_modules/vaderjs/' + "/runtime/static/" + file);
718
- await writer(process.cwd() + "/dist/" + file, data);
719
- });
720
- scannedVaderFiles.forEach(async (file) => {
721
- bundleSize += fs.statSync(
722
- process.cwd() + "/runtime/" + file
723
- ).size;
724
- let data = await reader(process.cwd() + "/runtime/" + file);
725
- await writer(process.cwd() + '/node_modules/vaderjs/' + "/dist/public/vader/" + file, data);
726
- });
727
- }
705
+
728
706
  console.log(`Compilation completed`)
729
707
  globalThis.isBuilding = false
730
708
  }
731
709
  import { watch } from "fs";
710
+ import { url } from "inspector";
732
711
 
733
712
  switch (true) {
734
713
  case process.argv.includes('--watch'):
@@ -737,19 +716,20 @@ switch (true) {
737
716
  Vader.js v1.3.3
738
717
  `)
739
718
  Build()
740
- const watcher = watch(
741
- process.cwd() + '/pages',
742
- { recursive: true },
743
- (event, filename) => {
744
- if (event == 'change'
745
- && !globalThis.isBuilding
746
- ) {
747
- Build()
748
- }
749
- },
750
- );
751
- watcher.on('error', (err) => console.log(err))
752
- console.log('Watching for changes')
719
+
720
+ const watcher = watch(
721
+ process.cwd() + '/pages',
722
+ { recursive: true },
723
+ (event, filename) => {
724
+ if (event == 'change'
725
+ && !globalThis.isBuilding
726
+ ) {
727
+ Build()
728
+ }
729
+ },
730
+ );
731
+ watcher.on('error', (err) => console.log(err))
732
+
753
733
  break;
754
734
  case process.argv.includes('--build'):
755
735