vaderjs 1.4.2-kml56 → 1.4.2-mpiml56

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.
@@ -67,7 +67,7 @@ export class HTMLTextNode {
67
67
  }
68
68
 
69
69
  insertBefore(node) {
70
- this.nodeValue = `${node.toString()}${this.nodeValue}`;
70
+ this.nodeValue = `${node.nodeValue}${this.nodeValue}`;
71
71
  return this;
72
72
  }
73
73
  }
@@ -155,12 +155,7 @@ export class HTMLElement {
155
155
  .join("");
156
156
  return string;
157
157
 
158
- case "innerText":
159
- return this.children
160
- .map((child) => {
161
- return child.toString();
162
- })
163
- .join("");
158
+
164
159
  default:
165
160
  break;
166
161
  }
@@ -187,8 +182,8 @@ export class HTMLElement {
187
182
  * @returns {HTMLElement}
188
183
  */
189
184
  setContent(content) {
190
- let textNode = new HTMLTextNode(content);
191
- this.children = [textNode];
185
+ let textNode = new HTMLTextNode(content)
186
+ this.children = [textNode];
192
187
  this.outerHTML = this.toString("outerHTML");
193
188
  this.innerHTML = this.toString("innerHTML");
194
189
  return this;
@@ -444,6 +439,9 @@ export class Document {
444
439
  * @returns {HTMLElement}
445
440
  */
446
441
  createElement(nodeData) {
442
+ if(!nodeData){
443
+ return new HTMLElement("div", {}, [])
444
+ }
447
445
  if (typeof nodeData === 'string') {
448
446
  return new HTMLElement(nodeData, {}, [])
449
447
  }
@@ -261,7 +261,7 @@ export async function Compile(){
261
261
  }
262
262
  copy = copy.replace(old, newLine)
263
263
  break;
264
- case !line.includes('import') && line.includes('useState') && !line.includes('let useState'):
264
+ case !line.includes('import') && line.includes('useState') && !line.includes('let useState') && !line.includes('var useState') && !line.includes('console'):
265
265
  let varType = line.split('[', 1)[0];
266
266
  let before = line.split('useState(')[1].split(',')[0];
267
267
  let key = line.split('[')[1].split(',')[0];
@@ -331,19 +331,32 @@ export async function Compile(){
331
331
  old = line;
332
332
  copy = copy.replace(old, newStatereducer);
333
333
  break;
334
+ case line.includes('vaderjs/client') && line.includes('import') || line.includes('vaderjs') && line.includes('import'):
335
+ let b4 = line
336
+ let isUsingProvider = config?.host?.provider
337
+ let replacement = isUsingProvider === 'cloudflare' ? 'remove' : '/src/client.js'
338
+ if(replacement === 'remove'){
339
+ copy = copy.replace(b4, '')
340
+ break;
341
+ }
342
+ let after = line.replace('vaderjs/client', replacement).replace('vaderjs', replacement)
343
+ copy = copy.replace(b4, after)
344
+ break;
334
345
 
335
- case line.includes('vaderjs/client') && line.includes('import') || line.includes('vaderjs') && line.includes('import'):
336
- let b4 = line
337
- let isUsingProvider = config?.host?.provider
338
- let replacement = isUsingProvider === 'cloudflare' ? 'remove' : '/src/client.js'
339
- if(replacement === 'remove'){
340
- copy = copy.replace(b4, '')
341
- break;
342
- }
343
- let after = line.replace('vaderjs/client', replacement).replace('vaderjs', replacement)
344
- copy = copy.replace(b4, after)
345
- break;
346
-
346
+ case line.includes('import') && !line.includes('vaderjs/client') && !line.includes('vaderjs') && !line.includes('import.meta') && !line.includes('import.meta.url') && !line.includes('import.meta.env'):
347
+
348
+ let filePath = line.split('from')[1].trim().replace(/'/g, '').replace(/"/g, '').replace(';', '').replaceAll('../','').replace(/\\/g, '/')
349
+ let contents = fs.readFileSync(filePath, 'utf8')
350
+ // remove default exports
351
+
352
+ if(contents.match(/export\s+default\s+/g)){
353
+ contents = contents.replace(/export\s+default\s+/g, '')
354
+ }
355
+
356
+ copy = copy.replace(line, contents)
357
+
358
+ break;
359
+
347
360
  }
348
361
  }
349
362
  if(!contents.includes('import Element')){
@@ -352,6 +365,7 @@ export async function Compile(){
352
365
  return copy
353
366
  }
354
367
 
368
+
355
369
 
356
370
 
357
371
  async function gen(){
@@ -382,9 +396,11 @@ export async function Compile(){
382
396
  'jsxDev':JSON.stringify('this.Element'),
383
397
  'jsx': JSON.stringify('this.Element'),
384
398
  }
385
- }).transformSync(await Bun.file(process.cwd() + file).text())
386
- let variables = grabVariables(data, file)
387
- let contents = await main(data, file)
399
+ })
400
+ let contents = await Bun.file(process.cwd() + file).text()
401
+ contents = data.transformSync(await main(contents, file))
402
+ contents = contents.split('\n').filter((line) => !line.includes('vaderjs/client') && !line.includes('vaderjs')).join('\n')
403
+ let variables = grabVariables(contents, file)
388
404
 
389
405
  variables.forEach((variable) => {
390
406
  contents.split('\n').forEach((line, index) => {
@@ -408,10 +424,14 @@ export async function Compile(){
408
424
  fs.mkdirSync(process.cwd() + '/build/pages/' + file.split('/').slice(0, -1).join('/'), { recursive: true })
409
425
  file = '/build/pages/' + file.replace('.tsx', '.js').replace('.ts', '.js').replace('.jsx', '.js')
410
426
  break;
427
+ case isUsingProvider === 'vercel':
428
+ fs.mkdirSync(process.cwd() + '/build/pages/' + file.split('/').slice(0, -1).join('/'), { recursive: true })
429
+ file = '/build/pages/' + file.replace('.tsx', '.js').replace('.ts', '.js').replace('.jsx', '.js')
430
+ break;
411
431
  default:
412
432
  file = '/build/' + file.replace('./', '').replace('.tsx', '.js').replace('.ts', '.js').replace('.jsx', '.js')
413
433
  }
414
- }
434
+ }
415
435
  fs.writeFileSync(process.cwd() + file, contents)
416
436
 
417
437
 
@@ -425,6 +445,53 @@ export async function Compile(){
425
445
  await Bun.write(process.cwd() + '/build/src/router.js', await Bun.file(process.cwd() + '/node_modules/vaderjs/client/runtime/router.js').text())
426
446
  }
427
447
 
448
+ // handle src files
449
+ const src = new Glob("/src/**/*.{ts,tsx,js,jsx}", {
450
+ absolute: true,
451
+ ignore: ["**/node_modules/**"]
452
+ });
453
+ let srcArray = await Array.fromAsync(src.scan())
454
+ srcArray = srcArray.map((file) => {
455
+ file = file.replaceAll('\\', '/')
456
+ file ='./' + file
457
+ return file
458
+ })
459
+
460
+ for(var file of srcArray){
461
+ let data = new Bun.Transpiler({
462
+ loader: "tsx",
463
+ tsconfig: {
464
+ 'compilerOptions':{
465
+ 'jsx':'react',
466
+ 'jsxFactory': 'this.Element'
467
+ }
468
+ },
469
+ define:{
470
+
471
+ 'jsxDev':JSON.stringify('this.Element'),
472
+ 'jsx': JSON.stringify('this.Element'),
473
+ }
474
+ }).transformSync(await Bun.file(process.cwd() + file).text())
475
+ let variables = grabVariables(data, file)
476
+ let contents = await main(data, file)
477
+ variables.forEach((variable) => {
478
+ contents.split('\n').forEach((line, index) => {
479
+ if(line.includes(variable) && !line.includes('import') && !line.includes('let') && !line.includes('var') && !line.includes('const')
480
+ && !line.includes(variable + '()') &&
481
+ !line.includes('.' + variable) &&
482
+ // not an occurence like variable1, variable2, variable3 or variabless
483
+ !line.match(new RegExp(variable + '[0-9]')) && !line.match(new RegExp(variable + '(w+)'))
484
+ && !line.includes(variable + ':')
485
+ ){
486
+ let newLine = line.replaceAll(variable, variable + '()')
487
+ contents = contents.replace(line, newLine)
488
+ }
489
+ });
490
+ })
491
+ file = file.split('/src')[1]
492
+
493
+ fs.writeFileSync(process.cwd() + '/build/src' + file, contents)
494
+ }
428
495
 
429
496
  resolve()
430
497
  })
package/binaries/vader.js CHANGED
File without changes
@@ -1,4 +1,5 @@
1
1
  import { watch } from 'fs'
2
+ import fs from 'fs'
2
3
  globalThis.hasLogged = false
3
4
  export function watchDir(cwd, _){
4
5
  process.chdir(cwd)
@@ -12,6 +13,9 @@ export function watchDir(cwd, _){
12
13
  let paths = ['src', 'pages', 'public', 'routes', 'vader.config.ts']
13
14
  for(var i in paths){
14
15
  let path = paths[i]
16
+ if(!fs.existsSync(process.cwd() + '/' + path)){
17
+ continue;
18
+ }
15
19
  watch(process.cwd() + '/' + path, { recursive: true, absolute:true }, (event, filename) => {
16
20
  if(filename && !filename.includes('node_modules') && !globalThis.hasLogged){
17
21
  console.log(`\x1b[36mwait \x1b[0m - compiling (client and server)`)
@@ -2,6 +2,7 @@ window.vader = {
2
2
  version: '1.0.0'
3
3
  }
4
4
  globalThis.isServer = false
5
+ globalThis.preRender = false;
5
6
  window.hasRan = []
6
7
  globalThis.memoizedFunctions = []
7
8
  const memoizedRefs = []
@@ -11,40 +12,40 @@ const memoizedRefs = []
11
12
  * @param {HTMLElement} newNode
12
13
  * @returns
13
14
  */
14
- function calculateDiff(oldNode, newNode){
15
- if(oldNode === undefined || newNode === undefined){
15
+ function calculateDiff(oldNode, newNode) {
16
+ if (oldNode === undefined || newNode === undefined) {
16
17
  return []
17
18
  }
18
- let diff = []
19
- if(oldNode?.children.length > 0){
20
- for(var i = 0; i < oldNode.children.length; i++){
21
- diff.push(...calculateDiff(oldNode.children[i], newNode.children[i]))
22
-
23
- }
19
+ let diff = []
20
+ if (oldNode?.children.length > 0) {
21
+ for (var i = 0; i < oldNode.children.length; i++) {
22
+ diff.push(...calculateDiff(oldNode.children[i], newNode.children[i]))
23
+
24
+ }
24
25
  return diff
25
- }
26
- if(!oldNode?._isRoot){
27
- if(oldNode.nodeType === 3 && oldNode.nodeValue !== newNode.nodeValue){
28
- diff.push({type: 'REPLACE', oldNode, newNode})
26
+ }
27
+ if (!oldNode?._isRoot) {
28
+ if (oldNode.nodeType === 3 && oldNode.nodeValue !== newNode.nodeValue) {
29
+ diff.push({ type: 'REPLACE', oldNode, newNode })
29
30
  }
30
- else if(oldNode.nodeType === 1 && oldNode.innerHTML !== newNode.innerHTML
31
- ){
32
- diff.push({type: 'REPLACE', oldNode, newNode})
31
+ else if (oldNode.nodeType === 1 && oldNode.innerHTML !== newNode.innerHTML
32
+ ) {
33
+ diff.push({ type: 'REPLACE', oldNode, newNode })
33
34
  }
34
- else if(oldNode.nodeType === 1 && oldNode.tagName === newNode.tagName){
35
- for(var i = 0; i < oldNode.attributes.length; i++){
36
- if(oldNode.attributes[i].value !== newNode.attributes[i].value){
37
- diff.push({type: 'PROPS', oldNode, newNode})
35
+ else if (oldNode.nodeType === 1 && oldNode.tagName === newNode.tagName) {
36
+ for (var i = 0; i < oldNode.attributes.length; i++) {
37
+ if (oldNode.attributes[i].value !== newNode.attributes[i].value) {
38
+ diff.push({ type: 'PROPS', oldNode, newNode })
38
39
  }
39
40
  }
40
41
  }
41
- }
42
+ }
43
+
42
44
 
43
-
44
45
 
45
46
  return diff
46
47
  }
47
-
48
+
48
49
  /**
49
50
  * @description This function is used to generate functonal components
50
51
  * @param {Function} tag
@@ -52,38 +53,43 @@ function calculateDiff(oldNode, newNode){
52
53
  * @param {...any} children
53
54
  * @returns {Object} - The first child of the functional component
54
55
  */
55
- function generateJSX(tag, props, ...children){
56
- let node = {
57
- state: {},
58
- mainFunction: tag,
59
- _key: tag.name || Math.random().toString(36).substring(7),
60
- $$typeof: 'JSX_CHILD',
61
- firstChild:null,
62
- children: children,
63
- _name: tag.name,
64
- }
65
-
66
- node.firstChild = tag()
67
- node.firstChild.htmlNode._key = node._key
56
+ function generateJSX(tag, props, ...children) {
57
+ let node = {
58
+ state: {},
59
+ mainFunction: tag,
60
+ _key: tag.name || Math.random().toString(36).substring(7),
61
+ $$typeof: 'JSX_CHILD',
62
+ firstChild: null,
63
+ children: children,
64
+ _name: tag.name,
65
+ }
66
+
67
+ let comp = new Component({ $$key: node._key })
68
+ tag = tag.bind(comp)
69
+ comp.render = () => {
70
+ return tag(props, ...children)
71
+ }
72
+ node.firstChild = comp.render()
73
+ node.firstChild.htmlNode._key = node._key
68
74
  node.firstChild.htmlRoot = node
69
- node.firstChild.htmlNode._isRoot = true
70
- node.firstChild.props = props || {}
75
+ node.firstChild.htmlNode._isRoot = true
76
+ node.firstChild.props = props || {}
71
77
  node.firstChild._isRoot = true
72
78
  node.firstChild._key = node._key
73
- node.firstChild.props['key'] = node._key
74
- return node.firstChild
75
-
79
+ node.firstChild.props['key'] = node._key
80
+ return node.firstChild
81
+
76
82
 
77
83
  }
78
- function handleStyles(styles, nodeEl) {
84
+ function handleStyles(styles, nodeEl) {
79
85
 
80
86
  for (let key in styles) {
81
- if(typeof styles[key] === 'object'){
87
+ if (typeof styles[key] === 'object') {
82
88
  handleStyles(styles[key], nodeEl)
83
89
  }
84
90
  nodeEl.style[key] = styles[key];
85
91
  }
86
-
92
+
87
93
  }
88
94
 
89
95
 
@@ -95,166 +101,166 @@ let hasBeenCalled = []
95
101
  * @param {...any} children
96
102
  * @returns {Object} - The virtual DOM element
97
103
  */
98
- function Element(tag, props, ...children){
104
+ function Element(tag, props, ...children) {
99
105
  !props ? props = {} : null
100
- if(!props?.['$$key']){
106
+ if (!props?.['$$key']) {
101
107
  props['$$key'] = tag.name || Math.random().toString(36).substring(7)
102
108
  }
103
109
 
104
- if(typeof tag === 'function'){
105
- return generateJSX(tag, props, children)
110
+ if (typeof tag === 'function') {
111
+ return generateJSX(tag, props, children)
106
112
  }
107
113
  let node = {
108
114
  tag: tag,
109
115
  props: props,
110
- children: children,
116
+ children: children,
111
117
  _key: props['$$key'],
112
118
  events: [],
113
119
  staticEl: document.createElement(tag),
114
120
  parentNode: null
115
121
  }
116
- for(var i = 0; i < children.length; i++){
117
- if(typeof children[i] === 'string' || typeof children[i] === 'number'){
118
- children[i] = {
119
- tag: 'TEXT_ELEMENT',
120
- props: {nodeValue: children[i]},
121
- _key: props['$$key'],
122
- parentNode: {tag: tag, props: props, children: children, _key: props['$$key']},
123
- children: []
122
+ for (var i = 0; i < children.length; i++) {
123
+ if (typeof children[i] === 'string' || typeof children[i] === 'number') {
124
+ children[i] = {
125
+ tag: 'TEXT_ELEMENT',
126
+ props: { nodeValue: children[i] },
127
+ _key: props['$$key'],
128
+ parentNode: { tag: tag, props: props, children: children, _key: props['$$key'] },
129
+ children: []
130
+ }
131
+ } else {
132
+ if (children[i]) {
133
+ children[i].parentNode = { tag: tag, props: props, children: children }
134
+ }
124
135
  }
125
- }else{
126
- if(children[i]){
127
- children[i].parentNode = {tag: tag, props: props, children: children}
128
- }
129
- }
130
- }
136
+ }
131
137
  let nodeEl = node.tag === 'TEXT_ELEMENT' ? document.createTextNode('') : document.createElement(node.tag)
132
138
  node.staticEl = nodeEl
133
-
134
- for(var key in props){
135
- if(key.toLowerCase().startsWith('on')){
136
- nodeEl.addEventListener(key.substring(2).toLowerCase(), props[key])
137
- node.events.push({type: key.substring(2).toLowerCase(), listener: props[key]})
138
- continue
139
- }
140
- if(key === '$$key' && !nodeEl._key && nodeEl.nodeType === 1
141
- ){
142
- Object.defineProperty(nodeEl, '_key', {
143
- value: props[key],
144
- writable: true
145
- })
146
- continue
147
- }
148
-
149
- if(nodeEl && nodeEl.nodeType === 1){
139
+
140
+ for (var key in props) {
141
+ if (key.toLowerCase().startsWith('on')) {
142
+ nodeEl.addEventListener(key.substring(2).toLowerCase(), props[key])
143
+ node.events.push({ type: key.substring(2).toLowerCase(), listener: props[key] })
144
+ continue
145
+ }
146
+ if (key === '$$key' && !nodeEl._key && nodeEl.nodeType === 1
147
+ ) {
148
+ Object.defineProperty(nodeEl, '_key', {
149
+ value: props[key],
150
+ writable: true
151
+ })
152
+ continue
153
+ }
154
+
155
+ if (nodeEl && nodeEl.nodeType === 1) {
150
156
  nodeEl.setAttribute(key, props[key])
151
157
  }
152
-
158
+
153
159
  }
154
- if(props.style){
160
+ if (props.style) {
155
161
  handleStyles(props.style, nodeEl)
156
162
  }
157
163
 
158
- if(props.id){
164
+ if (props.id) {
159
165
  nodeEl.id = props.id
160
166
  }
161
- if(props.ref){
162
- switch(true){
163
- case Array.isArray(props.ref.current):
164
- if(!props.ref.current.find((el) => el === nodeEl)){
165
- props.ref.current.push(nodeEl)
166
- }
167
- break;
168
- case props.ref.current === HTMLElement:
169
- props.ref.current = nodeEl
170
- break;
171
- case props.ref.current === null:
172
- props.ref.current = nodeEl
173
- break;
174
- case typeof props.ref === 'function' && !window.hasRan.includes(props.ref):
175
- window.hasRan.push(props.ref)
176
- props.ref(nodeEl)
177
- setTimeout(() => {
178
- window.hasRan.filter((el) => el !== props.ref)
179
- }, 0)
180
- break;
181
- default:
182
- props.ref.current = nodeEl
183
- break;
184
-
185
- }
167
+ if (props.ref) {
168
+ switch (true) {
169
+ case Array.isArray(props.ref.current):
170
+ if (!props.ref.current.find((el) => el === nodeEl)) {
171
+ props.ref.current.push(nodeEl)
172
+ }
173
+ break;
174
+ case props.ref.current === HTMLElement:
175
+ props.ref.current = nodeEl
176
+ break;
177
+ case props.ref.current === null:
178
+ props.ref.current = nodeEl
179
+ break;
180
+ case typeof props.ref === 'function' && !window.hasRan.includes(props.ref):
181
+ window.hasRan.push(props.ref)
182
+ props.ref(nodeEl)
183
+ setTimeout(() => {
184
+ window.hasRan.filter((el) => el !== props.ref)
185
+ }, 0)
186
+ break;
187
+ default:
188
+ props.ref.current = nodeEl
189
+ break;
190
+
191
+ }
186
192
  }
187
193
  node['htmlNode'] = nodeEl
188
-
189
-
190
- if(nodeEl.nodeType === 1){
191
- for(var i = 0; i < children.length; i++){
192
- if(children[i]){
193
- if(children[i].tag === 'TEXT_ELEMENT'){
194
- nodeEl.appendChild(document.createTextNode(children[i].props.nodeValue))
195
- }
196
- nodeEl.appendChild(Element(children[i].tag, children[i].props, ...children[i].children).htmlNode)
197
- }
198
- }
199
-
200
- }
201
-
194
+
195
+
196
+ if (nodeEl.nodeType === 1) {
197
+ for (var i = 0; i < children.length; i++) {
198
+ if (children[i]) {
199
+ if (children[i].tag === 'TEXT_ELEMENT') {
200
+ nodeEl.appendChild(document.createTextNode(children[i].props.nodeValue))
201
+ }
202
+ nodeEl.appendChild(Element(children[i].tag, children[i].props, ...children[i].children).htmlNode)
203
+ }
204
+ }
205
+
206
+ }
207
+
202
208
  return node;
203
209
  }
204
-
205
210
 
206
- function handleDiff(diff){
207
- for(var i = 0; i < diff.length; i++){
208
- switch(true){
209
- case diff[i].type === 'REPLACE' && !diff[i].oldNode._isRoot:
210
- let parent = diff[i].oldNode.parentNode
211
+
212
+ function handleDiff(diff) {
213
+ for (var i = 0; i < diff.length; i++) {
214
+ switch (true) {
215
+ case diff[i].type === 'REPLACE' && !diff[i].oldNode._isRoot:
216
+ let parent = diff[i].oldNode.parentNode
211
217
  diff[i].oldNode.parentNode.replaceChild(diff[i].newNode, diff[i].oldNode)
212
218
  break;
213
- case diff[i].type === 'PROPS':
219
+ case diff[i].type === 'PROPS':
214
220
  break;
215
- }
221
+ }
216
222
  }
217
223
 
218
224
  }
219
225
  let states = {}
220
- export const useState = (name, initialValue) => {}
221
- export function useRef(name, initialValue){
226
+ export const useState = (name, initialValue) => { }
227
+ export function useRef(name, initialValue) {
222
228
  let ref = initialValue
223
- if(!memoizedRefs.find((el) => el.name === name)){
224
- memoizedRefs.push({name, ref})
225
- }
226
- let getRef = () => memoizedRefs.find((el) => el.name === name).ref
227
- let setRef = (newValue) => {
228
- memoizedRefs.find((el) => el.name === name).ref = newValue
229
- }
230
- return {
229
+ if (!memoizedRefs.find((el) => el.name === name)) {
230
+ memoizedRefs.push({ name, ref })
231
+ }
232
+ let getRef = () => memoizedRefs.find((el) => el.name === name).ref
233
+ let setRef = (newValue) => {
234
+ memoizedRefs.find((el) => el.name === name).ref = newValue
235
+ }
236
+ return {
231
237
  current: getRef(),
232
238
  name,
233
239
  }
234
240
  }
235
- export function Mounted(fn, node){
236
- let el = Array.from(document.querySelectorAll('*')).find((el) => el._key === memoizedFunctions.find((el) => el.mainFunction === node)._key)
237
- if(el && !hasBeenCalled.find((el) => el === node)){
241
+ export function Mounted(fn, node) {
242
+ let el = Array.from(document.querySelectorAll('*')).find((el) => el._key === memoizedFunctions.find((el) => el.mainFunction === node)._key)
243
+ if (el && !hasBeenCalled.find((el) => el === node)) {
238
244
  fn()
239
245
  hasBeenCalled.push(node)
240
246
  }
241
- else{
247
+ else {
242
248
  setTimeout(() => {
243
249
  Mounted(fn, node)
244
250
  }, 0)
245
251
  }
246
252
  }
247
-
248
-
249
- let effects = [];
250
253
 
251
- export function useEffect(fn, deps){
252
- if(!effects.find((el) => el.fn.toString() === fn.toString())){
253
- effects.push({fn, deps})
254
+
255
+ let effects = [];
256
+
257
+ export function useEffect(fn, deps) {
258
+ if (!effects.find((el) => el.fn.toString() === fn.toString())) {
259
+ effects.push({ fn, deps })
254
260
  }
255
- else{
261
+ else {
256
262
  let effect = effects.find((el) => el.fn.toString() === fn.toString())
257
- if(effect.deps.toString() !== deps.toString()){
263
+ if (effect.deps.toString() !== deps.toString()) {
258
264
  effect.deps = deps
259
265
  effect.fn()
260
266
  }
@@ -264,154 +270,143 @@ export function useEffect(fn, deps){
264
270
  }
265
271
 
266
272
  }
267
- export function useReducer(name, reducer, vnode, initialState){
273
+ export function useReducer(name, reducer, vnode, initialState) {
268
274
  let [state, setState] = useState(name, vnode, initialState)
269
275
  let dispatch = (action) => {
270
276
  let newState = reducer(state, action)
271
277
  setState(newState)
272
278
  }
273
279
 
274
- return [state, dispatch]
280
+ return [state, dispatch]
275
281
 
276
282
  }
277
283
 
278
284
  class Component {
279
- constructor(props){
285
+ constructor(props) {
280
286
  this.props = props
281
287
  this._key = props['$$key'] || Math.random().toString(36).substring(7)
282
288
  this.state = {}
283
289
  this.htmlNode = null
284
290
  this.firstChild = null
285
291
  this.Element = Element
292
+ this.passiveProps = {}
286
293
  }
287
294
 
288
295
 
289
- setState(newState){
296
+ setState(newState) {
290
297
  this.state = newState
291
298
  }
292
299
 
293
- handleDiff(diff){
294
- for(var i = 0; i < diff.length; i++){
295
- switch(true){
296
- case diff[i].type === 'REPLACE' && !diff[i].oldNode._isRoot:
297
- let parent = diff[i].oldNode.parentNode
300
+ handleDiff(diff) {
301
+ for (var i = 0; i < diff.length; i++) {
302
+ switch (true) {
303
+ case diff[i].type === 'REPLACE' && !diff[i].oldNode._isRoot:
304
+ let parent = diff[i].oldNode.parentNode
298
305
  diff[i].oldNode.parentNode.replaceChild(diff[i].newNode, diff[i].oldNode)
299
306
  break;
300
- case diff[i].type === 'PROPS':
307
+ case diff[i].type === 'PROPS':
301
308
  break;
302
- }
309
+ }
303
310
  }
304
311
  }
305
- calculateDiff(oldNode, newNode){
306
- if(oldNode === undefined || newNode === undefined){
312
+ calculateDiff(oldNode, newNode) {
313
+ if (oldNode === undefined || newNode === undefined) {
307
314
  return []
308
315
  }
309
- let diff = []
310
- if(oldNode?.children.length > 0){
311
- for(var i = 0; i < oldNode.children.length; i++){
312
- diff.push(...this.calculateDiff(oldNode.children[i], newNode.children[i]))
313
-
314
- }
316
+ let diff = []
317
+ if (oldNode?.children.length > 0) {
318
+ for (var i = 0; i < oldNode.children.length; i++) {
319
+ diff.push(...this.calculateDiff(oldNode.children[i], newNode.children[i]))
320
+
321
+ }
315
322
  return diff
316
- }
317
- if(!oldNode?._isRoot){
318
- if(oldNode.nodeType === 3 && oldNode.nodeValue !== newNode.nodeValue){
319
- diff.push({type: 'REPLACE', oldNode, newNode})
323
+ }
324
+ if (!oldNode?._isRoot) {
325
+ if (oldNode.nodeType === 3 && oldNode.nodeValue !== newNode.nodeValue) {
326
+ diff.push({ type: 'REPLACE', oldNode, newNode })
320
327
  }
321
- else if(oldNode.nodeType === 1 && oldNode.innerHTML !== newNode.innerHTML
322
- ){
323
- diff.push({type: 'REPLACE', oldNode, newNode})
328
+ else if (oldNode.nodeType === 1 && oldNode.innerHTML !== newNode.innerHTML
329
+ ) {
330
+ diff.push({ type: 'REPLACE', oldNode, newNode })
324
331
  }
325
- else if(oldNode.nodeType === 1 && oldNode.tagName === newNode.tagName){
326
- for(var i = 0; i < oldNode.attributes.length; i++){
327
- if(oldNode.attributes[i].value !== newNode.attributes[i].value){
328
- diff.push({type: 'PROPS', oldNode, newNode})
332
+ else if (oldNode.nodeType === 1 && oldNode.tagName === newNode.tagName) {
333
+ for (var i = 0; i < oldNode.attributes.length; i++) {
334
+ if (oldNode.attributes[i].value !== newNode.attributes[i].value) {
335
+ diff.push({ type: 'PROPS', oldNode, newNode })
329
336
  }
330
337
  }
331
338
  }
332
- }
339
+ }
340
+
333
341
 
334
-
335
342
 
336
343
  return diff
337
344
  }
338
- useState(name, initialValue){
339
- if(!this.state[name]){
345
+ useState(name, initialValue) {
346
+ if (!this.state[name]) {
340
347
  this.state[name] = initialValue
341
- }
342
-
348
+ }
349
+
343
350
  let getState = () => this.state[name]
344
- let setState = (newValue) => {
345
- let dEl = this.firstChild.htmlNode
346
- if(dEl.tagName === 'HTML'){
347
- let firstChild = dEl.querySelector('body').firstChild
348
- dEl = firstChild
349
- }
350
- this.state[name] = newValue
351
- let el = Array.from(document.querySelectorAll('*')).find((el) =>{
351
+ let setState = (newValue) => {
352
+ let dEl = this.firstChild.htmlNode
353
+ if (dEl.tagName === 'HTML') {
354
+ dEl = dEl.querySelector('body')
355
+ dEl.firstChild._key = this._key
356
+ }
357
+ this.state[name] = newValue
358
+ let el = Array.from(document.querySelectorAll('*')).find((el) => {
352
359
  return el._key === dEl._key
353
- })
354
- let diff = calculateDiff(el, this.render().htmlNode.tagName === 'HTML' ? this.render().htmlNode.querySelector('body').firstChild : this.render().htmlNode)
360
+ })
361
+ let diff = calculateDiff(el, this.render(this.passiveProps).htmlNode.tagName === 'HTML' ? this.render(this.passiveProps).htmlNode.querySelector('body') : this.render(this.passiveProps).htmlNode)
355
362
  handleDiff(diff)
356
-
357
- }
358
- return [getState, setState]
363
+
364
+ }
365
+ return [getState, setState]
359
366
 
360
367
  }
361
368
  useEffect = useEffect
362
- useReducer(name, reducer, initialState){
369
+ useReducer(name, reducer, initialState) {
363
370
  let [state, setState] = this.useState(name, initialState)
364
371
  let dispatch = (action) => {
365
- let newState = reducer(state(), action)
372
+ let newState = reducer(state(), action)
366
373
  setState(newState)
367
374
  }
368
375
 
369
- return [state, dispatch]
376
+ return [state, dispatch]
370
377
  }
371
378
 
372
- render(){
379
+ render() {
373
380
  return null
374
381
  }
375
382
 
376
383
  }
377
-
378
- export async function render(vnode, container, ...passProps){
379
-
380
- if(!vnode){
384
+
385
+ export async function render(vnode, container, ...passProps) {
386
+
387
+ if (!vnode) {
381
388
  throw new Error('No vnode was provided')
382
389
  }
383
390
  // create an object for the node then bind to firstChild
384
- let comp = new Component({$$key: vnode.name || Math.random().toString(36).substring(7)})
391
+ let comp = new Component({ $$key: vnode.name || Math.random().toString(36).substring(7) })
385
392
  vnode = vnode.bind(comp)
386
- comp.render = () => {
387
- return vnode(...passProps)
393
+ if(passProps.length > 0){
394
+
395
+ passProps = {
396
+ req: passProps[0],
397
+ res: passProps[1]
398
+ }
399
+ comp.passiveProps = passProps
388
400
  }
389
-
401
+ comp.render = () => {
402
+ return vnode(comp.passiveProps)
403
+ }
404
+
390
405
  comp.firstChild = comp.render()
391
406
 
392
- if(comp.firstChild.htmlNode.tagName === 'HTML'){
393
- let hasHead = comp.firstChild.htmlNode.querySelector('head') ? true : false
394
- let hasBody = comp.firstChild.htmlNode.querySelector('body') ? true : false
395
-
396
- if(hasHead){
397
- document.head.innerHTML = comp.firstChild.htmlNode.querySelector('head').innerHTML
398
- comp.firstChild.children = comp.firstChild.children.filter((el) =>{
399
- return el.htmlNode.tagName !== 'HEAD'
400
- })
401
- }
402
- if(hasBody){
403
- comp.firstChild.children = comp.firstChild.children.filter((el) =>{
404
- if(el.htmlNode.tagName == 'BODY'){
405
- comp.firstChild = el.children[0]
406
- }
407
- })
408
- }
409
- }
410
- container.innerHTML = ''
411
-
412
- container.appendChild(comp.firstChild.htmlNode)
413
-
414
-
407
+ container.innerHTML = ''
408
+ container.replaceWith(comp.firstChild.htmlNode)
409
+
415
410
  }
416
-
411
+
417
412
  export default Element
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "vaderjs",
3
3
  "description": "A reactive framework for building fast and scalable web applications",
4
- "version": "1.4.2-kml56",
5
- "main": "vader.js",
4
+ "version": "1.4.2-mpiml56",
6
5
  "author": {
7
6
  "name": "Malikwhitten67",
8
7
  "email": "malikwhitterb@gmail.com"
@@ -14,7 +13,7 @@
14
13
  },
15
14
  "type": "module",
16
15
  "bin":{
17
- "vader":"./vader.js"
16
+ "vader":"./vader_dev.js"
18
17
  },
19
18
  "dependencies": {
20
19
  "ws": "latest"
@@ -1,5 +1,5 @@
1
1
  import * as Bun from 'bun'
2
- import { Element, Document, DOMParser} from 'vaderjs/binaries/Kalix/index.js'
2
+ import { Document, DOMParser} from 'vaderjs/binaries/Kalix/index.js'
3
3
  import { renderToString } from '../../server'
4
4
  import fs from 'fs'
5
5
  let routes = new Bun.FileSystemRouter({
@@ -11,35 +11,77 @@ async function generate(){
11
11
  let config = await import(process.cwd() + '/vader.config.js').then((config) => { return config.default })
12
12
  let provider = config?.host?.provider
13
13
 
14
- let providerRoutes = []
14
+ let providerRoutes = []
15
+ Object.keys(routes).map((route) => {
16
+ if(route.includes('[')){
17
+
18
+ let root = Object.keys(routes).find((r) => {
19
+ return r === '/'
20
+ } )
21
+
22
+
23
+ let param = route.split('/[')[1].split(']')[0]
24
+ let p = {}
25
+ let existingParams = routes[root]?.params || []
26
+ existingParams.push({
27
+ isCatchAll: route.includes('[[catchall]]') ? true : false,
28
+ name: param,
29
+ file: routes[route],
30
+ baseFolder: route.split('[')[0]
31
+ })
32
+ p.file = routes[root]
33
+ p.params = existingParams
34
+ routes[root] = p
35
+ delete routes[route]
36
+
37
+ }
38
+ })
15
39
  for(var i in routes){
16
- let path = i
40
+ let path = i
17
41
  let file = routes[i]
18
- let comp = require(file).default
19
- let document = new Document()
20
- let div = document.createElement('div')
21
- div.setAttribute('id', 'root')
22
- let dom = await renderToString(comp)
23
- div.setContent(dom)
24
- dom = div.toString("outerHTML")
42
+ if(typeof file === 'object'){
43
+ file = file.file
44
+ }
45
+ let comp = require(file).default
46
+ if(!comp){
47
+ continue;
48
+ }
49
+
50
+ let dom = await renderToString(comp)
51
+ let isHtml = dom.includes('<html')
25
52
  let folder = path.split('/pages')[0]
26
53
  let newPath = process.cwd() + '/build' + folder + '/index.html'
27
- let name = comp.name
54
+ let name = comp.name || 'App'
28
55
  file = file.replace(/\\/g, '/').replace('\/\/', '/').replace(process.cwd().replace(/\\/g, '/'), '').split('/pages')[1].replace('.tsx', '.js').replace('.jsx', '.js')
29
- let isParamRoute = path.includes('[')
56
+ let isParamRoute = routes[i].params ? true : false
30
57
  let baseFolder = ''
31
58
  if(isParamRoute){
32
- baseFolder = path.split('[')[0]
59
+ let route = routes[i].params[0]
60
+ baseFolder = i.split('[')[0]
33
61
  let providerPath;
34
62
  switch(true){
35
63
  case provider === 'vercel':
36
- providerPath = `${baseFolder}:${path.split('[')[1].split(']')[0]}`
37
- providerRoutes.push({source: providerPath, dest: `${path}/index.html`})
64
+ if(route.isCatchAll){
65
+ providerPath = `${baseFolder}/*`
66
+ providerRoutes.push({source: providerPath, destination: `${path}/index.html`})
67
+ break;
68
+ }
69
+ providerPath = `${baseFolder}:${route.name}`
70
+ providerRoutes.push({source: providerPath, dest: `/`})
38
71
  break;
39
72
  case provider === 'nginx':
40
73
  providerPath = `RewriteRule ^${baseFolder.replace('/', '')}.*$ ${path}/index.html [L]`
41
74
  providerRoutes.push(providerPath)
42
75
  break;
76
+ case provider === 'cloudflare':
77
+ if(route.isCatchAll){
78
+ providerPath = `${baseFolder}/*`
79
+ providerRoutes.push({source: providerPath, destination: `${path}/index.html`})
80
+ break;
81
+ }
82
+ providerPath = `${baseFolder}/*`
83
+ providerRoutes.push({source: providerPath, destination: `${path}/index.html`})
84
+ break;
43
85
  }
44
86
  }else{
45
87
  let providerPath;
@@ -55,17 +97,48 @@ async function generate(){
55
97
  providerPath = `RewriteRule ^${path.replace('/', '')}/$ ${path}/index.html [L]`
56
98
  providerRoutes.push(providerPath)
57
99
  break;
100
+
58
101
 
59
102
  }
60
- }
61
- dom = dom + `
62
- <script type="module">
103
+ }
104
+ dom = preRender ? dom : '<div id="root"></div>' + `
105
+ <script type="module">
106
+
63
107
  import { render } from '/src/client.js'
64
- import ${name} from '/pages/${file.replace(process.cwd(), '')}'
108
+ let ${name} = await import('/pages/${file.replace(process.cwd(), '')}')
109
+ if(${name}.default){
110
+ ${name} = ${name}.default
111
+ }else{
112
+ let keys = Object.keys(${name})
113
+ ${name} = ${name}[keys[0]]
114
+ }
65
115
  import Kuai from '/src/router.js'
66
116
  let kuai = new Kuai()
117
+ ${
118
+ routes[i].params ?
119
+ routes[i].params.map((param) => {
120
+ let name = param.name
121
+ let file = param.file.replace(/\\/g, '/').replace('\/\/', '/').replace(process.cwd().replace(/\\/g, '/'), '').split('/pages')[1].replace('.tsx', '.js').replace('.jsx', '.js')
122
+ return `
123
+ // handle if default or named
124
+ let ${name} = await import('/pages/${file}')
125
+ if(${name}.default){
126
+ ${name} = ${name}.default
127
+ }else{
128
+ let keys = Object.keys(${name})
129
+ ${name} = ${name}[keys[0]]
130
+ }
131
+ kuai.get('${param.baseFolder}:${name}', (c) => {
132
+ render(${name}, ${
133
+ isHtml ? `document.documentElement`: `document.body.firstChild`
134
+ }, c.req, c.res)
135
+ })`
136
+ }).join('\n') : ''
137
+ }
67
138
  kuai.get('${path}', (c) => {
68
- render(${name}, document.getElementById('root'), c.req, c.res)
139
+ render(${name}, ${
140
+ isHtml ? `document.documentElement`: `document.body.firstChild`
141
+ }, c.req, c.res)
69
142
  })
70
143
 
71
144
  kuai.listen()
@@ -100,7 +173,7 @@ Header add x-powered-by "vaderjs"
100
173
  </IfModule>
101
174
  `
102
175
  fs.writeFileSync(process.cwd() + '/.htaccess', full)
103
- break;
176
+ break;
104
177
  }
105
178
  console.log(`\x1b[32mSuccess\x1b[0m - Static files generated`)
106
179
 
package/router/index.ts CHANGED
@@ -137,10 +137,8 @@ function spawnServer(config: any){
137
137
  if(url.pathname.includes('.')){
138
138
  url.pathname = url.pathname.replace('/\/', '/')
139
139
  url.pathname = url.pathname.replace('/build/', '')
140
- if(url.pathname.includes('/build')){
141
- url.pathname = url.pathname.replace('/build', '')
142
- }
143
- let file = process.cwd() + '/build' + url.pathname
140
+
141
+ let file = process.cwd() + '/build' + url.pathname
144
142
  let fileType = handleContentTypes(file)
145
143
  if(fs.existsSync(file)){
146
144
  let content = await Bun.file(file).text()
@@ -149,8 +147,21 @@ function spawnServer(config: any){
149
147
  }
150
148
  let route = router.match(url.pathname)
151
149
  if(route){
150
+ let isParamRoute = route.filePath.includes('[') && route.filePath.includes(']')
152
151
  let path = route.filePath.split('/pages')[1].replace('.jsx', '.js').replace('.tsx', '.js').replace('.ts', '.js')
152
+ path = isParamRoute ? 'index.html' : path
153
153
  let html = fs.readFileSync(process.cwd() + `/build/${path.replace('.js', '.html')}`).toString()
154
+ html = html + `
155
+ <script>
156
+ let ws = new WebSocket('ws://${config.host.hostname || 'localhost'}:${config.env.PORT || 3000}')
157
+ ws.onmessage = function(event){
158
+ console.log(event.data)
159
+ }
160
+ ws.onclose = function(event){
161
+ window.location.reload()
162
+ }
163
+ </script>
164
+ `
154
165
  return new Response(html, {status: 200, headers: {'Content-Type': 'text/html', 'x-powered-by': 'Vader'}})
155
166
  }
156
167
  return new Response('Not Found', {status: 404})
@@ -171,7 +182,7 @@ export default {
171
182
  if(!globalThis.isListening){
172
183
  let config = require(process.cwd() + '/vader.config.js').default
173
184
  if(process.env.mode === 'production'){
174
- console.log(`Listening at - http://${config.host.hostname}:${config.env.PORT}`)
185
+ console.log(`\x1b[32msuccess \x1b[0m- listening on port ${config.env.PORT || 3000}`)
175
186
  spawnServer(config)
176
187
  }
177
188
  config?.env?.SSR ? spawn_ssr_server(config ) : spawnServer(config)
package/server/index.js CHANGED
@@ -47,7 +47,7 @@ class Component {
47
47
  }
48
48
 
49
49
  }
50
- export async function renderToString(element, args = []) {
50
+ export async function renderToString(element, args = []) {
51
51
  let data = typeof element === 'function' ? await element(args) : element
52
52
  let doc = new Document()
53
53
  let el = doc.createElement(data)
File without changes