pulse-js-framework 1.10.0 → 1.10.3

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 (37) hide show
  1. package/compiler/parser/_extract.js +393 -0
  2. package/compiler/parser/blocks.js +361 -0
  3. package/compiler/parser/core.js +306 -0
  4. package/compiler/parser/expressions.js +386 -0
  5. package/compiler/parser/imports.js +108 -0
  6. package/compiler/parser/index.js +47 -0
  7. package/compiler/parser/state.js +155 -0
  8. package/compiler/parser/style.js +445 -0
  9. package/compiler/parser/view.js +632 -0
  10. package/compiler/parser.js +15 -2372
  11. package/compiler/parser.js.original +2376 -0
  12. package/package.json +2 -1
  13. package/runtime/a11y/announcements.js +213 -0
  14. package/runtime/a11y/contrast.js +125 -0
  15. package/runtime/a11y/focus.js +412 -0
  16. package/runtime/a11y/index.js +35 -0
  17. package/runtime/a11y/preferences.js +121 -0
  18. package/runtime/a11y/utils.js +164 -0
  19. package/runtime/a11y/validation.js +258 -0
  20. package/runtime/a11y/widgets.js +545 -0
  21. package/runtime/a11y.js +15 -1840
  22. package/runtime/a11y.js.original +1844 -0
  23. package/runtime/graphql/cache.js +69 -0
  24. package/runtime/graphql/client.js +563 -0
  25. package/runtime/graphql/hooks.js +492 -0
  26. package/runtime/graphql/index.js +62 -0
  27. package/runtime/graphql/subscriptions.js +241 -0
  28. package/runtime/graphql.js +12 -1322
  29. package/runtime/graphql.js.original +1326 -0
  30. package/runtime/router/core.js +956 -0
  31. package/runtime/router/guards.js +90 -0
  32. package/runtime/router/history.js +204 -0
  33. package/runtime/router/index.js +36 -0
  34. package/runtime/router/lazy.js +180 -0
  35. package/runtime/router/utils.js +226 -0
  36. package/runtime/router.js +12 -1600
  37. package/runtime/router.js.original +1605 -0
@@ -0,0 +1,241 @@
1
+ /**
2
+ * Pulse GraphQL - WebSocket Subscriptions
3
+ *
4
+ * Handles GraphQL subscriptions using the graphql-ws protocol
5
+ *
6
+ * @module pulse-js-framework/runtime/graphql/subscriptions
7
+ */
8
+
9
+ import { pulse, effect, onCleanup } from '../pulse.js';
10
+ import { createWebSocket, WebSocketError } from '../websocket.js';
11
+ import { ClientError } from '../errors.js';
12
+
13
+ // ============================================================================
14
+ // Constants
15
+ // ============================================================================
16
+
17
+ /**
18
+ * graphql-ws protocol message types
19
+ * @see https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md
20
+ */
21
+ export const MessageType = {
22
+ // Client -> Server
23
+ ConnectionInit: 'connection_init',
24
+ Subscribe: 'subscribe',
25
+ Complete: 'complete',
26
+ Ping: 'ping',
27
+ Pong: 'pong',
28
+
29
+ // Server -> Client
30
+ ConnectionAck: 'connection_ack',
31
+ Next: 'next',
32
+ Error: 'error'
33
+ // Complete is bidirectional
34
+ };
35
+
36
+ // ============================================================================
37
+ // Subscription Manager
38
+ // ============================================================================
39
+
40
+ /**
41
+ * Manages GraphQL subscriptions over WebSocket
42
+ */
43
+ export class SubscriptionManager {
44
+ #ws = null;
45
+ #subscriptions = new Map();
46
+ #nextId = 1;
47
+ #connectionParams;
48
+ #connected = pulse(false);
49
+ #pending = [];
50
+
51
+ /**
52
+ * @param {Object} ws - WebSocket instance from createWebSocket
53
+ * @param {Object|Function} [connectionParams] - Connection parameters
54
+ */
55
+ constructor(ws, connectionParams) {
56
+ this.#ws = ws;
57
+ this.#connectionParams = connectionParams;
58
+
59
+ // Handle incoming messages
60
+ ws.on('message', (msg) => this.#handleMessage(msg));
61
+ ws.on('open', () => this.#handleOpen());
62
+ ws.on('close', () => this.#handleClose());
63
+ ws.on('error', (err) => this.#handleError(err));
64
+ }
65
+
66
+ /**
67
+ * Get connection state
68
+ */
69
+ get connected() {
70
+ return this.#connected;
71
+ }
72
+
73
+ /**
74
+ * Handle WebSocket open
75
+ */
76
+ async #handleOpen() {
77
+ // Send connection_init
78
+ const params = typeof this.#connectionParams === 'function'
79
+ ? await this.#connectionParams()
80
+ : this.#connectionParams;
81
+
82
+ this.#ws.send({
83
+ type: MessageType.ConnectionInit,
84
+ payload: params || {}
85
+ });
86
+ }
87
+
88
+ /**
89
+ * Handle WebSocket close
90
+ */
91
+ #handleClose() {
92
+ this.#connected.set(false);
93
+ // Notify all active subscriptions
94
+ for (const [id, sub] of this.#subscriptions) {
95
+ sub.handlers.onError?.(new GraphQLError('Connection closed', {
96
+ code: 'SUBSCRIPTION_ERROR'
97
+ }));
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Handle WebSocket error
103
+ */
104
+ #handleError(error) {
105
+ for (const [id, sub] of this.#subscriptions) {
106
+ sub.handlers.onError?.(new GraphQLError(error.message || 'WebSocket error', {
107
+ code: 'SUBSCRIPTION_ERROR'
108
+ }));
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Handle incoming WebSocket message
114
+ * @param {Object} message - Parsed message
115
+ */
116
+ #handleMessage(message) {
117
+ const { id, type, payload } = message;
118
+
119
+ switch (type) {
120
+ case MessageType.ConnectionAck:
121
+ this.#connected.set(true);
122
+ // Send any pending subscriptions
123
+ for (const pending of this.#pending) {
124
+ this.#ws.send(pending);
125
+ }
126
+ this.#pending = [];
127
+ break;
128
+
129
+ case MessageType.Next: {
130
+ const sub = this.#subscriptions.get(id);
131
+ if (sub) {
132
+ sub.handlers.onData?.(payload.data);
133
+ }
134
+ break;
135
+ }
136
+
137
+ case MessageType.Error: {
138
+ const sub = this.#subscriptions.get(id);
139
+ if (sub) {
140
+ sub.handlers.onError?.(new GraphQLError('Subscription error', {
141
+ code: 'SUBSCRIPTION_ERROR',
142
+ errors: Array.isArray(payload) ? payload : [payload]
143
+ }));
144
+ }
145
+ break;
146
+ }
147
+
148
+ case MessageType.Complete: {
149
+ const sub = this.#subscriptions.get(id);
150
+ if (sub) {
151
+ sub.handlers.onComplete?.();
152
+ this.#subscriptions.delete(id);
153
+ }
154
+ break;
155
+ }
156
+
157
+ case MessageType.Ping:
158
+ this.#ws.send({ type: MessageType.Pong });
159
+ break;
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Subscribe to a GraphQL subscription
165
+ * @param {string} query - GraphQL subscription query
166
+ * @param {Object} [variables] - Subscription variables
167
+ * @param {Object} handlers - Event handlers
168
+ * @returns {Function} Unsubscribe function
169
+ */
170
+ subscribe(query, variables, handlers) {
171
+ const id = String(this.#nextId++);
172
+
173
+ const message = {
174
+ id,
175
+ type: MessageType.Subscribe,
176
+ payload: {
177
+ query,
178
+ variables,
179
+ operationName: extractOperationName(query)
180
+ }
181
+ };
182
+
183
+ // Store subscription
184
+ this.#subscriptions.set(id, {
185
+ query,
186
+ variables,
187
+ handlers
188
+ });
189
+
190
+ // Send or queue the subscription message
191
+ if (this.#connected.get()) {
192
+ this.#ws.send(message);
193
+ } else {
194
+ this.#pending.push(message);
195
+ // Ensure WebSocket is connecting
196
+ if (this.#ws.state.get() === 'closed') {
197
+ this.#ws.connect();
198
+ }
199
+ }
200
+
201
+ // Return unsubscribe function
202
+ return () => {
203
+ if (this.#subscriptions.has(id)) {
204
+ this.#subscriptions.delete(id);
205
+ if (this.#connected.get()) {
206
+ this.#ws.send({ id, type: MessageType.Complete });
207
+ }
208
+ }
209
+ };
210
+ }
211
+
212
+ /**
213
+ * Get active subscription count
214
+ * @returns {number}
215
+ */
216
+ get activeCount() {
217
+ return this.#subscriptions.size;
218
+ }
219
+
220
+ /**
221
+ * Close all subscriptions
222
+ */
223
+ closeAll() {
224
+ for (const id of this.#subscriptions.keys()) {
225
+ if (this.#connected.get()) {
226
+ this.#ws.send({ id, type: MessageType.Complete });
227
+ }
228
+ }
229
+ this.#subscriptions.clear();
230
+ }
231
+
232
+ /**
233
+ * Dispose the subscription manager
234
+ */
235
+ dispose() {
236
+ this.closeAll();
237
+ this.#ws.dispose();
238
+ }
239
+ }
240
+
241
+