despia-native 1.0.14 → 1.0.17

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.
Files changed (3) hide show
  1. package/README.md +16 -1
  2. package/index.js +48 -11
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -640,9 +640,24 @@ These CSS variables are automatically provided by the Despia native runtime and
640
640
  - **watch** (string[], optional): Array of variable names to watch for in the response
641
641
 
642
642
  Returns a Promise that resolves when all watched variables are available:
643
- - **Single variable**: 5-second timeout with simple observation
643
+ - **Single variable**: 30-second timeout with observation that ignores empty placeholders and requires a fresh write (Promise always resolves; on timeout it resolves with `undefined`)
644
644
  - **Multiple variables**: Uses VariableTracker with 5-minute auto-cleanup
645
645
 
646
+ ### Timeout behavior
647
+
648
+ When you call `despia(command, ['someVariable'])`, the SDK waits up to 30 seconds for
649
+ `window.someVariable` to be set by the native runtime. If it appears earlier, the
650
+ Promise resolves with that value. If it is never set, the Promise still resolves
651
+ after 30 seconds with `undefined` and a timeout is logged to the console. This
652
+ prevents hanging Promises for long-running or failing native operations.
653
+
654
+ ### Fresh-data behavior
655
+
656
+ Before observing, watched variables are cleared to avoid resolving on stale values.
657
+ The observer ignores empty placeholders (`undefined`, `null`, `"n/a"`, `{}`, `[]`)
658
+ and requires the value to change from its baseline before resolving. This ensures
659
+ each call waits for a fresh write from the native side.
660
+
646
661
  ### Direct Property Access
647
662
 
648
663
  Access any window variable directly through the despia object:
package/index.js CHANGED
@@ -41,21 +41,53 @@
41
41
  processQueue();
42
42
  }
43
43
  }
44
+
45
+ // Generate a safe signature for change detection
46
+ function safeSig(val) {
47
+ if (val === undefined) return 'u';
48
+ if (val === null) return 'n';
49
+ const t = typeof val;
50
+ if (t !== 'object') return `${t}:${String(val)}`;
51
+ try { return `o:${JSON.stringify(val)}`; } catch { return 'o:[unserializable]'; }
52
+ }
44
53
 
45
- // Simple variable observer with 5-second timeout
46
- function observeDespiaVariable(variableName, callback, timeout = 5000) {
54
+ // Simple variable observer with longer timeout, change detection, and guaranteed resolve
55
+ function observeDespiaVariable(variableName, callback, timeout = 30000) {
47
56
  const startTime = Date.now();
48
-
57
+ const initialRef = window[variableName];
58
+ const initialSig = safeSig(initialRef);
59
+
60
+ const ready = (val) => {
61
+ if (val === undefined || val === null || val === "n/a") return false;
62
+ if (Array.isArray(val) && val.length === 0) return false;
63
+ if (val && typeof val === 'object' && !Array.isArray(val) && Object.keys(val).length === 0) return false;
64
+ return true;
65
+ };
66
+
67
+ const changed = (val) => {
68
+ if (val !== initialRef) return true;
69
+ return safeSig(val) !== initialSig;
70
+ };
71
+
49
72
  function checkVariable() {
50
- if (window[variableName] !== undefined) {
51
- callback(window[variableName]);
52
- } else if (Date.now() - startTime < timeout) {
73
+ const val = window[variableName];
74
+
75
+ if (ready(val) && changed(val)) {
76
+ // Fresh, non-empty value arrived → resolve with it
77
+ callback(val);
78
+ return;
79
+ }
80
+
81
+ if (Date.now() - startTime < timeout) {
53
82
  setTimeout(checkVariable, 100);
54
- } else {
55
- console.error(`Despia timeout: ${variableName} was not set within ${timeout} ms`);
83
+ return;
56
84
  }
85
+
86
+ // Timeout: still resolve so promises don't hang
87
+ console.error(`Despia timeout: ${variableName} was not set within ${timeout} ms`);
88
+ callback(undefined);
57
89
  }
58
-
90
+
59
91
  checkVariable();
60
92
  }
61
93
 
@@ -124,12 +156,17 @@
124
156
  return Promise.resolve({});
125
157
  }
126
158
 
159
+ // Pre-clear watched vars to avoid stale immediate resolves
160
+ variables.forEach((name) => {
161
+ try { delete window[name]; } catch (e) { window[name] = undefined; }
162
+ });
163
+
127
164
  if (variables.length === 1) {
128
- // Simple single variable observation with 5-second timeout
165
+ // Simple single variable observation with 30-second timeout
129
166
  return new Promise((resolve) => {
130
167
  observeDespiaVariable(variables[0], (value) => {
131
168
  resolve({ [variables[0]]: value });
132
- }, 5000);
169
+ }, 30000);
133
170
  });
134
171
  } else {
135
172
  // Multiple variables - use VariableTracker (no timeout, expires after 5 minutes)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "despia-native",
3
- "version": "1.0.14",
3
+ "version": "1.0.17",
4
4
  "description": "JavaScript SDK for Despia native integrations with command queuing and variable watching",
5
5
  "main": "index.js",
6
6
  "module": "index.js",