pawa-ssr 1.2.2 → 1.2.4

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/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ CHANGELOG.md
2
+ + version 1.0.0 - v1.2.2 on experiment
3
+ + version 1.2.3 bugs fixing on for-key
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  - **Full PawaJS Compatibility:** Renders components and templates using the same PawaJS syntax you use on the client.
11
11
  - **Server-Side Hooks:** Supports server-side implementations of PawaJS hooks like `$state`, `useInsert`, `setContext`, and `useContext`.
12
12
  - **Built-in Directives:** Includes powerful control-flow directives like `if`, `for-each`, `switch`, and `key`.
13
- - **Automatic Hydration:** Embeds necessary data for the client-side PawaJS to "hydrate" the static HTML and make it interactive without a full re-render using pawajs-continue library.
13
+ - **Automatic Hydration:** Embeds necessary data for the client-side PawaJS to "hydrate" the static HTML and make it interactive without a full re-render using [PawaJS-Continue](https://github.com/Allisboy/pawajs-continue) library.
14
14
  - **Client-Only Escape Hatch:** Use the `only-client` attribute to prevent specific components or elements from rendering on the server.
15
15
  - **Extensible Plugin System:** Add your own custom directives and rendering lifecycle hooks.
16
16
 
@@ -28,6 +28,8 @@ Here's a basic example of how to render a PawaJS component on the server using a
28
28
 
29
29
  ```javascript
30
30
  import { RegisterComponent, $state, useInsert, html } from 'pawajs';
31
+ import {isServer} from 'pawajs/server'
32
+ import { initiateResumer } from "pawajs-continue";
31
33
 
32
34
  const App = () => {
33
35
  const message = $state('World');
@@ -40,8 +42,14 @@ const App = () => {
40
42
  </div>
41
43
  `;
42
44
  };
43
-
44
- export const Main=()=>{
45
+ RegisterComponent(App);
46
+ ```
47
+ **2. A server file (`main.js`)
48
+ ```javascript
49
+ import { startApp } from "pawajs-ssr";
50
+ import { App } from "./app.js";
51
+ import {App} from "./app.js"
52
+ const Entry=()=>{
45
53
  return html`
46
54
  <div>
47
55
  <app></app>
@@ -49,10 +57,17 @@ export const Main=()=>{
49
57
  `
50
58
  }
51
59
 
52
- RegisterComponent(App);
60
+ export const main=async({url})=>{
61
+ const template=Entry()
62
+ const {toString,head}=await startApp(template,{url},true)//template string, context for server , true - for development
63
+ const html=await toString()
64
+ return {html,head}
65
+ }
66
+
67
+
53
68
  ```
54
69
 
55
- **2. Create your Server Entrypoint (`server.js`)**
70
+ **3. Create your Server Entrypoint (`server.js`)**
56
71
 
57
72
  ```javascript
58
73
  import express from 'express';
@@ -65,14 +80,8 @@ const port = 3000;
65
80
  app.get('/', async (req, res) => {
66
81
  try {
67
82
  // Get the component's HTML string
68
- const componentHtml = Main();
69
-
70
- // Render it with PawaJS SSR
71
- const { toString, head } = await startApp(
72
- componentHtml,
73
- { /* initial context */ },
74
- true // development mode
75
- );
83
+ const {html,head} =async Main({url:req.origin});
84
+ const
76
85
 
77
86
  const renderedHtml = await toString();
78
87
 
@@ -86,9 +95,9 @@ app.get('/', async (req, res) => {
86
95
  ${head}
87
96
  </head>
88
97
  <body>
89
- <div id="app">${renderedHtml}</div>
98
+ <div id="app">${html}</div>
90
99
  <!-- Add client-side script for continuity using pawajs-continue library-->
91
- <script src="/client.js" type="module"></script>
100
+ <script src="/app.js" type="module"></script>
92
101
  </body>
93
102
  </html>
94
103
  `;
@@ -118,12 +127,14 @@ import { App } from './src/app.js';
118
127
  // Register the same components used on the server
119
128
  RegisterComponent(App);
120
129
 
121
- // Initialize the resumer for hydration
122
- initiateResumer();
123
-
124
- // Start PawaJS on the client to continue the app know as Continue Rendering Model(CRM)
125
- const appElement = document.getElementById('app');
126
- pawaStartApp(appElement);
130
+ if(!isServer()){
131
+ // Initialize the resumer for hydration
132
+ initiateResumer();
133
+
134
+ // Start PawaJS on the client to continue the app know as Continue Rendering Model(CRM)
135
+ const appElement = document.getElementById('app');
136
+ pawaStartApp(appElement);
137
+ }
127
138
  ```
128
139
 
129
140
  ## Core Concepts
package/index.js CHANGED
@@ -112,6 +112,7 @@ const $state=(initialValue)=>{
112
112
  if(res instanceof Promise){
113
113
  state.async=true
114
114
  state.failed=false
115
+ state.retry=()=>{}
115
116
 
116
117
  }else{
117
118
  state.value=initialValue()
@@ -291,24 +292,25 @@ const component=async (el)=>{
291
292
  fromSerialized:{}
292
293
  }
293
294
  Object.assign(appContext.transportContext, oldAppContext?.transportContext || {})
295
+ const slotHydrates={}
294
296
  Array.from(slot.children).forEach(prop =>{
295
297
  if (prop.getAttribute('prop')) {
296
- slots[prop.getAttribute('prop')]=()=>prop.innerHTML
298
+ const html=prop.innerHTML
299
+ slots[prop.getAttribute('prop')]=()=>html
300
+ slotHydrates[prop.getAttribute('prop')]=html
297
301
  }else{
298
302
  console.warn('sloting props must have prop attribute')
299
303
  }
300
304
  })
301
305
  const children=el._componentChildren
302
306
  const hydrate={
303
- children:'',
307
+ children:children,
304
308
  props:{
305
309
  ...el._hydrateProps,
306
310
  },
307
- slots:{...slots},
308
- }
309
- if (isDevelopment) {
310
- hydrate.children=children
311
+ slots:{...slotHydrates},
311
312
  }
313
+
312
314
  const id=pawaGenerateId(10)
313
315
  const encodeJSON = (obj) => Buffer.from(JSON.stringify(obj)).toString('base64').replace(/\+/g, '-');
314
316
  const comment = document.createComment(`component+${id}`);
@@ -342,7 +344,7 @@ appContext.component._prop={children,...el._props,...slots}
342
344
  try {
343
345
  await fn(stateContext,app)
344
346
  } catch (error) {
345
- console.error(`Error in beforeCall for ${el._componentName}:`, error.message)
347
+ console.error(`Error in beforeCall for ${el._componentName}:`, error.message,error.stack)
346
348
  }
347
349
  }
348
350
 
@@ -421,7 +423,7 @@ appContext.component._prop={children,...el._props,...slots}
421
423
  })
422
424
  store.getStore().stateContext=appContext.formerContext
423
425
  } catch (error) {
424
- console.log(error.message,error.stack);
426
+ console.log(error.message,error.stack,`at ${el.tagName} component`);
425
427
 
426
428
  }
427
429
  }
@@ -481,6 +483,9 @@ const textContentHandler = async(el) => {
481
483
  el._context,
482
484
  `from text interpolation @{} - ${expression} at ${currentHtmlString}`
483
485
  );
486
+ if (expression === '') {
487
+ return
488
+ }
484
489
  value = value.replace(fullMatch, String(func));
485
490
  });
486
491
 
@@ -488,7 +493,7 @@ const textContentHandler = async(el) => {
488
493
  });
489
494
  } catch (error) {
490
495
  console.warn(`error at ${el._template} textcontent`);
491
- console.error(error.message, error.stack);
496
+ console.error(error.message, error.stack,`error at ${el._template} textcontent`);
492
497
  }
493
498
  };
494
499
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pawa-ssr",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "type":"module",
5
5
  "description": "pawajs ssr libary",
6
6
  "main": "index.js",
package/power.js CHANGED
@@ -117,7 +117,8 @@ let latestChain
117
117
  export const Switch = async(el, attr) => {
118
118
  if (el._running) return;
119
119
  el._running = true;
120
-
120
+ try {
121
+
121
122
  const nextSiblings = el.nextElementSibling || null;
122
123
  const cases =el.getAttribute('case')
123
124
  const chained=[{
@@ -230,6 +231,9 @@ const switchFunc=evaluateExpr(attr.value,el._context,`at switch directive ${attr
230
231
  comment.parentElement.insertBefore(template, endComment);
231
232
  // No element rendered
232
233
  }
234
+ } catch (error) {
235
+ console.log(error.message,error.stack,`at switch directive ${el._template}`)
236
+ }
233
237
  };
234
238
 
235
239
  export const For=async(el,attr)=>{
@@ -322,7 +326,7 @@ export const For=async(el,attr)=>{
322
326
  }
323
327
 
324
328
  } catch (error) {
325
- console.error(error.message,error.stack)
329
+ console.error(error.message,error.stack,`at for directive ${el._template}`)
326
330
  }
327
331
  }
328
332
 
@@ -339,7 +343,7 @@ export const State=async(el,attr)=>{
339
343
  el._context[name]={value:result}
340
344
  el.removeAttribute(attr.name)
341
345
  } catch (error) {
342
- console.log(error.message,error.stack)
346
+ console.log(error.message,error.stack,`at ${el._template} from state`)
343
347
  }
344
348
 
345
349
  }
@@ -377,6 +381,6 @@ export const Key=async(el,attr)=>{
377
381
  endComment.parentElement.insertBefore(newElement,endComment)
378
382
  await render(newElement,el._context)
379
383
  }catch(error){
380
- console.error(error.message,error.stack)
384
+ console.error(error.message,error.stack,`at key ${el._template}`)
381
385
  }
382
386
  }
package/utils.js CHANGED
@@ -69,18 +69,9 @@ export const processNode = (node, itemContext) => {
69
69
  if (typeof itemContext === 'number') {
70
70
  return
71
71
  }
72
-
73
- if (node.nodeType === 3) { // Text node
74
- const text = node.textContent
75
- const newText = text.replace(/{{(.+?)}}/g, (match, exp) => {
76
- // Use the cached expression evaluator for performance
77
- const result = evaluateExpr(exp, itemContext, `in processNode for text: ${exp}`);
78
- return result !== null ? String(result) : match;
79
- })
80
- //console.log(newText)
81
- node.textContent = newText
82
- } else if (node.attributes) {
72
+ if (node.attributes) {
83
73
  Array.from(node.attributes).forEach(attr => {
74
+ if (attr.name !== 'for-key') return
84
75
  const newValue = attr.value.replace(/{{(.+?)}}/g, (match, exp) => {
85
76
  // Use the cached expression evaluator for performance
86
77
  const result = evaluateExpr(exp, itemContext, `in processNode for attribute ${attr.name}: ${exp}`);
@@ -89,9 +80,6 @@ export const processNode = (node, itemContext) => {
89
80
  attr.value = newValue
90
81
  })
91
82
  }
92
- Array.from(node.childNodes).forEach((n) => {
93
- processNode(n, itemContext)
94
- })
95
83
  }
96
84
 
97
85
  export const extractAtExpressions=(template) =>{