@relax.js/core 1.0.3 → 1.0.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 +194 -188
- package/dist/DependencyInjection.d.ts +45 -27
- package/dist/collections/LinkedList.d.ts +9 -8
- package/dist/collections/index.js +1 -1
- package/dist/collections/index.js.map +3 -3
- package/dist/collections/index.mjs +1 -1
- package/dist/collections/index.mjs.map +3 -3
- package/dist/di/index.js +1 -1
- package/dist/di/index.js.map +3 -3
- package/dist/di/index.mjs +1 -1
- package/dist/di/index.mjs.map +3 -3
- package/dist/elements/index.js +1 -1
- package/dist/elements/index.js.map +1 -1
- package/dist/errors.d.ts +20 -0
- package/dist/forms/FormValidator.d.ts +3 -22
- package/dist/forms/ValidationRules.d.ts +4 -6
- package/dist/forms/index.js +1 -1
- package/dist/forms/index.js.map +4 -4
- package/dist/forms/index.mjs +1 -1
- package/dist/forms/index.mjs.map +4 -4
- package/dist/forms/setFormData.d.ts +39 -1
- package/dist/html/TableRenderer.d.ts +1 -0
- package/dist/html/index.js +1 -1
- package/dist/html/index.js.map +3 -3
- package/dist/html/index.mjs +1 -1
- package/dist/html/index.mjs.map +3 -3
- package/dist/html/template.d.ts +4 -0
- package/dist/http/ServerSentEvents.d.ts +1 -1
- package/dist/http/SimpleWebSocket.d.ts +1 -1
- package/dist/http/http.d.ts +1 -0
- package/dist/http/index.js +1 -1
- package/dist/http/index.js.map +3 -3
- package/dist/http/index.mjs +1 -1
- package/dist/http/index.mjs.map +3 -3
- package/dist/i18n/icu.d.ts +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/i18n/index.js.map +2 -2
- package/dist/i18n/index.mjs +1 -1
- package/dist/i18n/index.mjs.map +2 -2
- package/dist/index.js +3 -3
- package/dist/index.js.map +3 -3
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +3 -3
- package/dist/routing/NavigateRouteEvent.d.ts +4 -4
- package/dist/routing/index.js +3 -3
- package/dist/routing/index.js.map +3 -3
- package/dist/routing/index.mjs +3 -3
- package/dist/routing/index.mjs.map +3 -3
- package/dist/routing/navigation.d.ts +1 -1
- package/dist/routing/routeTargetRegistry.d.ts +1 -0
- package/dist/routing/types.d.ts +2 -1
- package/dist/templates/NodeTemplate.d.ts +3 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +3 -3
- package/dist/utils/index.mjs +1 -1
- package/dist/utils/index.mjs.map +3 -3
- package/docs/Architecture.md +333 -333
- package/docs/DependencyInjection.md +277 -237
- package/docs/Errors.md +87 -87
- package/docs/GettingStarted.md +238 -231
- package/docs/Pipes.md +5 -5
- package/docs/Translations.md +167 -312
- package/docs/WhyRelaxjs.md +336 -336
- package/docs/api.json +93193 -0
- package/docs/elements/dom.md +102 -102
- package/docs/forms/creating-form-components.md +924 -924
- package/docs/forms/form-api.md +94 -94
- package/docs/forms/forms.md +99 -99
- package/docs/forms/patterns.md +311 -311
- package/docs/forms/reading-writing.md +465 -365
- package/docs/forms/validation.md +351 -351
- package/docs/html/TableRenderer.md +291 -291
- package/docs/html/html.md +175 -175
- package/docs/html/index.md +54 -54
- package/docs/html/template.md +422 -422
- package/docs/http/HttpClient.md +459 -459
- package/docs/http/ServerSentEvents.md +184 -184
- package/docs/http/index.md +109 -109
- package/docs/i18n/i18n.md +49 -4
- package/docs/i18n/intl-standard.md +178 -178
- package/docs/routing/RouteLink.md +98 -98
- package/docs/routing/Routing.md +332 -332
- package/docs/routing/layouts.md +207 -207
- package/docs/setup/bootstrapping.md +154 -0
- package/docs/setup/build-and-deploy.md +183 -0
- package/docs/setup/project-structure.md +170 -0
- package/docs/setup/vite.md +175 -0
- package/docs/utilities.md +143 -143
- package/package.json +4 -2
|
@@ -1,184 +1,184 @@
|
|
|
1
|
-
# Server-Sent Events
|
|
2
|
-
|
|
3
|
-
SSE client that dispatches received server events as DOM events.
|
|
4
|
-
|
|
5
|
-
## Quick Start
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
import { SSEClient, SSEDataEvent } from '
|
|
9
|
-
|
|
10
|
-
const sse = new SSEClient('/api/events', {
|
|
11
|
-
eventTypes: ['user-updated', 'notification']
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
sse.connect();
|
|
15
|
-
|
|
16
|
-
document.addEventListener('user-updated', (e: SSEDataEvent) => {
|
|
17
|
-
console.log('User updated:', e.data);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
// When done
|
|
21
|
-
sse.disconnect();
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Configuration
|
|
25
|
-
|
|
26
|
-
```typescript
|
|
27
|
-
interface SSEOptions {
|
|
28
|
-
target?: string | Element; // CSS selector or element (default: document)
|
|
29
|
-
withCredentials?: boolean; // Send credentials (default: false)
|
|
30
|
-
eventTypes?: string[]; // SSE event types to listen for
|
|
31
|
-
eventFactory?: SSEEventFactory; // Custom event factory
|
|
32
|
-
onConnect?: (client: SSEClient) => void;
|
|
33
|
-
onError?: (client: SSEClient, error: Event) => void;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
type SSEEventFactory = (eventName: string, data: unknown) => Event;
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Event Types
|
|
40
|
-
|
|
41
|
-
### Default (message)
|
|
42
|
-
|
|
43
|
-
Without `eventTypes`, listens to the default `message` event:
|
|
44
|
-
|
|
45
|
-
```typescript
|
|
46
|
-
// Server sends: data: {"text": "hello"}
|
|
47
|
-
const sse = new SSEClient('/api/events');
|
|
48
|
-
sse.connect();
|
|
49
|
-
|
|
50
|
-
document.addEventListener('message', (e: SSEDataEvent) => {
|
|
51
|
-
console.log(e.data); // { text: 'hello' }
|
|
52
|
-
});
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### Named Events
|
|
56
|
-
|
|
57
|
-
With `eventTypes`, listens to specific SSE event types:
|
|
58
|
-
|
|
59
|
-
```typescript
|
|
60
|
-
// Server sends: event: notification\ndata: {"text": "hello"}
|
|
61
|
-
const sse = new SSEClient('/api/events', {
|
|
62
|
-
eventTypes: ['notification', 'alert']
|
|
63
|
-
});
|
|
64
|
-
sse.connect();
|
|
65
|
-
|
|
66
|
-
document.addEventListener('notification', (e: SSEDataEvent) => {
|
|
67
|
-
console.log(e.data);
|
|
68
|
-
});
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Target Element
|
|
72
|
-
|
|
73
|
-
Dispatch events to a specific element instead of document:
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
const sse = new SSEClient('/api/events', {
|
|
77
|
-
target: '#notifications',
|
|
78
|
-
eventTypes: ['notification']
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
sse.connect();
|
|
82
|
-
|
|
83
|
-
document.querySelector('#notifications')
|
|
84
|
-
.addEventListener('notification', (e: SSEDataEvent) => {
|
|
85
|
-
showNotification(e.data);
|
|
86
|
-
});
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
## Event Factory
|
|
90
|
-
|
|
91
|
-
Use `eventFactory` to create custom event instances:
|
|
92
|
-
|
|
93
|
-
```typescript
|
|
94
|
-
class UserUpdatedEvent extends Event {
|
|
95
|
-
constructor(public user: User) {
|
|
96
|
-
super('user-updated', { bubbles: true });
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
class OrderCreatedEvent extends Event {
|
|
101
|
-
constructor(public order: Order) {
|
|
102
|
-
super('order-created', { bubbles: true });
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const sse = new SSEClient('/api/events', {
|
|
107
|
-
eventTypes: ['user-updated', 'order-created'],
|
|
108
|
-
eventFactory: (eventName, data) => {
|
|
109
|
-
switch (eventName) {
|
|
110
|
-
case 'user-updated':
|
|
111
|
-
return new UserUpdatedEvent(data as User);
|
|
112
|
-
case 'order-created':
|
|
113
|
-
return new OrderCreatedEvent(data as Order);
|
|
114
|
-
default:
|
|
115
|
-
return new SSEDataEvent(eventName, data);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
sse.connect();
|
|
121
|
-
|
|
122
|
-
// Now events are properly typed
|
|
123
|
-
document.addEventListener('user-updated', (e: UserUpdatedEvent) => {
|
|
124
|
-
console.log(e.user);
|
|
125
|
-
});
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## Type Registration
|
|
129
|
-
|
|
130
|
-
Register event types for TypeScript support:
|
|
131
|
-
|
|
132
|
-
```typescript
|
|
133
|
-
declare global {
|
|
134
|
-
interface DocumentEventMap {
|
|
135
|
-
'user-updated': UserUpdatedEvent;
|
|
136
|
-
'order-created': OrderCreatedEvent;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// TypeScript now knows the event type
|
|
141
|
-
document.addEventListener('user-updated', (e) => {
|
|
142
|
-
console.log(e.user); // Typed as User
|
|
143
|
-
});
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
## Reconnection
|
|
147
|
-
|
|
148
|
-
EventSource has built-in automatic reconnection. The `onError` callback fires when errors occur, but the browser handles reconnection automatically.
|
|
149
|
-
|
|
150
|
-
```typescript
|
|
151
|
-
const sse = new SSEClient('/api/events', {
|
|
152
|
-
onConnect: () => console.log('Connected'),
|
|
153
|
-
onError: () => console.log('Error (will auto-reconnect)')
|
|
154
|
-
});
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
## API Reference
|
|
158
|
-
|
|
159
|
-
### SSEClient
|
|
160
|
-
|
|
161
|
-
| Method/Property | Description |
|
|
162
|
-
|-----------------|-------------|
|
|
163
|
-
| `connect()` | Establish SSE connection |
|
|
164
|
-
| `disconnect()` | Close connection |
|
|
165
|
-
| `connected` | `boolean` - Current connection state |
|
|
166
|
-
|
|
167
|
-
### SSEDataEvent
|
|
168
|
-
|
|
169
|
-
| Property | Type | Description |
|
|
170
|
-
|----------|------|-------------|
|
|
171
|
-
| `type` | `string` | Event name from SSE |
|
|
172
|
-
| `data` | `unknown` | Parsed data (JSON auto-parsed) |
|
|
173
|
-
| `bubbles` | `boolean` | Always `true` |
|
|
174
|
-
|
|
175
|
-
### Exports
|
|
176
|
-
|
|
177
|
-
```typescript
|
|
178
|
-
import {
|
|
179
|
-
SSEClient,
|
|
180
|
-
SSEOptions,
|
|
181
|
-
SSEDataEvent,
|
|
182
|
-
SSEEventFactory
|
|
183
|
-
} from '
|
|
184
|
-
```
|
|
1
|
+
# Server-Sent Events
|
|
2
|
+
|
|
3
|
+
SSE client that dispatches received server events as DOM events.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { SSEClient, SSEDataEvent } from '@relax.js/core/http';
|
|
9
|
+
|
|
10
|
+
const sse = new SSEClient('/api/events', {
|
|
11
|
+
eventTypes: ['user-updated', 'notification']
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
sse.connect();
|
|
15
|
+
|
|
16
|
+
document.addEventListener('user-updated', (e: SSEDataEvent) => {
|
|
17
|
+
console.log('User updated:', e.data);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// When done
|
|
21
|
+
sse.disconnect();
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Configuration
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
interface SSEOptions {
|
|
28
|
+
target?: string | Element; // CSS selector or element (default: document)
|
|
29
|
+
withCredentials?: boolean; // Send credentials (default: false)
|
|
30
|
+
eventTypes?: string[]; // SSE event types to listen for
|
|
31
|
+
eventFactory?: SSEEventFactory; // Custom event factory
|
|
32
|
+
onConnect?: (client: SSEClient) => void;
|
|
33
|
+
onError?: (client: SSEClient, error: Event) => void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
type SSEEventFactory = (eventName: string, data: unknown) => Event;
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Event Types
|
|
40
|
+
|
|
41
|
+
### Default (message)
|
|
42
|
+
|
|
43
|
+
Without `eventTypes`, listens to the default `message` event:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// Server sends: data: {"text": "hello"}
|
|
47
|
+
const sse = new SSEClient('/api/events');
|
|
48
|
+
sse.connect();
|
|
49
|
+
|
|
50
|
+
document.addEventListener('message', (e: SSEDataEvent) => {
|
|
51
|
+
console.log(e.data); // { text: 'hello' }
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Named Events
|
|
56
|
+
|
|
57
|
+
With `eventTypes`, listens to specific SSE event types:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// Server sends: event: notification\ndata: {"text": "hello"}
|
|
61
|
+
const sse = new SSEClient('/api/events', {
|
|
62
|
+
eventTypes: ['notification', 'alert']
|
|
63
|
+
});
|
|
64
|
+
sse.connect();
|
|
65
|
+
|
|
66
|
+
document.addEventListener('notification', (e: SSEDataEvent) => {
|
|
67
|
+
console.log(e.data);
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Target Element
|
|
72
|
+
|
|
73
|
+
Dispatch events to a specific element instead of document:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
const sse = new SSEClient('/api/events', {
|
|
77
|
+
target: '#notifications',
|
|
78
|
+
eventTypes: ['notification']
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
sse.connect();
|
|
82
|
+
|
|
83
|
+
document.querySelector('#notifications')
|
|
84
|
+
.addEventListener('notification', (e: SSEDataEvent) => {
|
|
85
|
+
showNotification(e.data);
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Event Factory
|
|
90
|
+
|
|
91
|
+
Use `eventFactory` to create custom event instances:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
class UserUpdatedEvent extends Event {
|
|
95
|
+
constructor(public user: User) {
|
|
96
|
+
super('user-updated', { bubbles: true });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
class OrderCreatedEvent extends Event {
|
|
101
|
+
constructor(public order: Order) {
|
|
102
|
+
super('order-created', { bubbles: true });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const sse = new SSEClient('/api/events', {
|
|
107
|
+
eventTypes: ['user-updated', 'order-created'],
|
|
108
|
+
eventFactory: (eventName, data) => {
|
|
109
|
+
switch (eventName) {
|
|
110
|
+
case 'user-updated':
|
|
111
|
+
return new UserUpdatedEvent(data as User);
|
|
112
|
+
case 'order-created':
|
|
113
|
+
return new OrderCreatedEvent(data as Order);
|
|
114
|
+
default:
|
|
115
|
+
return new SSEDataEvent(eventName, data);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
sse.connect();
|
|
121
|
+
|
|
122
|
+
// Now events are properly typed
|
|
123
|
+
document.addEventListener('user-updated', (e: UserUpdatedEvent) => {
|
|
124
|
+
console.log(e.user);
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Type Registration
|
|
129
|
+
|
|
130
|
+
Register event types for TypeScript support:
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
declare global {
|
|
134
|
+
interface DocumentEventMap {
|
|
135
|
+
'user-updated': UserUpdatedEvent;
|
|
136
|
+
'order-created': OrderCreatedEvent;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// TypeScript now knows the event type
|
|
141
|
+
document.addEventListener('user-updated', (e) => {
|
|
142
|
+
console.log(e.user); // Typed as User
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Reconnection
|
|
147
|
+
|
|
148
|
+
EventSource has built-in automatic reconnection. The `onError` callback fires when errors occur, but the browser handles reconnection automatically.
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
const sse = new SSEClient('/api/events', {
|
|
152
|
+
onConnect: () => console.log('Connected'),
|
|
153
|
+
onError: () => console.log('Error (will auto-reconnect)')
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## API Reference
|
|
158
|
+
|
|
159
|
+
### SSEClient
|
|
160
|
+
|
|
161
|
+
| Method/Property | Description |
|
|
162
|
+
|-----------------|-------------|
|
|
163
|
+
| `connect()` | Establish SSE connection |
|
|
164
|
+
| `disconnect()` | Close connection |
|
|
165
|
+
| `connected` | `boolean` - Current connection state |
|
|
166
|
+
|
|
167
|
+
### SSEDataEvent
|
|
168
|
+
|
|
169
|
+
| Property | Type | Description |
|
|
170
|
+
|----------|------|-------------|
|
|
171
|
+
| `type` | `string` | Event name from SSE |
|
|
172
|
+
| `data` | `unknown` | Parsed data (JSON auto-parsed) |
|
|
173
|
+
| `bubbles` | `boolean` | Always `true` |
|
|
174
|
+
|
|
175
|
+
### Exports
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
import {
|
|
179
|
+
SSEClient,
|
|
180
|
+
SSEOptions,
|
|
181
|
+
SSEDataEvent,
|
|
182
|
+
SSEEventFactory
|
|
183
|
+
} from '@relax.js/core/http';
|
|
184
|
+
```
|
package/docs/http/index.md
CHANGED
|
@@ -1,109 +1,109 @@
|
|
|
1
|
-
# HTTP, WebSocket & SSE
|
|
2
|
-
|
|
3
|
-
This module provides HTTP, WebSocket, and Server-Sent Events clients for network communication.
|
|
4
|
-
|
|
5
|
-
## Available Features
|
|
6
|
-
|
|
7
|
-
| Feature | Description | Use Case |
|
|
8
|
-
|---------|-------------|----------|
|
|
9
|
-
| [HTTP Client](HttpClient.md#http-client) | Type-safe HTTP functions | REST API calls with JWT handling |
|
|
10
|
-
| [WebSocketClient](HttpClient.md#websocket-client) | WebSocket client with auto-reconnect | Real-time bidirectional messaging |
|
|
11
|
-
| [SSEClient](ServerSentEvents.md) | Server-Sent Events as DOM events | Server push notifications |
|
|
12
|
-
|
|
13
|
-
## Quick Start
|
|
14
|
-
|
|
15
|
-
### HTTP Requests
|
|
16
|
-
|
|
17
|
-
```typescript
|
|
18
|
-
import { configure, get, post } from '
|
|
19
|
-
|
|
20
|
-
configure({ baseUrl: '/api/v1' });
|
|
21
|
-
|
|
22
|
-
// GET with query parameters
|
|
23
|
-
const response = await get('/users', { status: 'active' });
|
|
24
|
-
if (response.success) {
|
|
25
|
-
const users = response.as<User[]>();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// POST with JSON body
|
|
29
|
-
const result = await post('/users', JSON.stringify({ name: 'John' }));
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### WebSocket Messaging
|
|
33
|
-
|
|
34
|
-
```typescript
|
|
35
|
-
import { WebSocketClient } from '
|
|
36
|
-
|
|
37
|
-
const ws = new WebSocketClient<Message>('wss://api.example.com');
|
|
38
|
-
ws.connect();
|
|
39
|
-
|
|
40
|
-
// Check connection state
|
|
41
|
-
console.log(ws.connected); // true when connected
|
|
42
|
-
|
|
43
|
-
// Send (queued if disconnected)
|
|
44
|
-
ws.send({ type: 'chat', text: 'Hello' });
|
|
45
|
-
|
|
46
|
-
// Receive (rejects if connection closes)
|
|
47
|
-
try {
|
|
48
|
-
const message = await ws.receive();
|
|
49
|
-
} catch (e) {
|
|
50
|
-
console.log('Connection closed');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Disconnect when done
|
|
54
|
-
ws.disconnect();
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Server-Sent Events
|
|
58
|
-
|
|
59
|
-
```typescript
|
|
60
|
-
import { SSEClient } from '
|
|
61
|
-
|
|
62
|
-
const sse = new SSEClient('/api/events', {
|
|
63
|
-
eventTypes: ['user-updated', 'notification']
|
|
64
|
-
});
|
|
65
|
-
sse.connect();
|
|
66
|
-
|
|
67
|
-
// Events dispatch to document by default
|
|
68
|
-
document.addEventListener('notification', (e: SSEMessageEvent) => {
|
|
69
|
-
showNotification(e.data);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
// Disconnect when done
|
|
73
|
-
sse.disconnect();
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Key Features
|
|
77
|
-
|
|
78
|
-
### HTTP Client
|
|
79
|
-
|
|
80
|
-
- Standalone functions (`get`, `post`, `put`, `del`, `request`)
|
|
81
|
-
- Module-wide configuration via `configure()`
|
|
82
|
-
- Automatic base URL prefixing
|
|
83
|
-
- JWT token from localStorage (configurable)
|
|
84
|
-
- Query string building
|
|
85
|
-
- Type-safe response casting
|
|
86
|
-
- Replaceable fetch for testing via `setFetch()`
|
|
87
|
-
|
|
88
|
-
### WebSocketClient
|
|
89
|
-
|
|
90
|
-
- Auto-reconnect with exponential backoff
|
|
91
|
-
- Message queuing when disconnected
|
|
92
|
-
- Custom message codecs
|
|
93
|
-
- Type-safe generic messages
|
|
94
|
-
- Connection state tracking
|
|
95
|
-
- Graceful disconnect support
|
|
96
|
-
|
|
97
|
-
### SSEClient
|
|
98
|
-
|
|
99
|
-
- Dispatches SSE events as DOM events
|
|
100
|
-
- Configurable target element or document
|
|
101
|
-
- Auto-reconnect with exponential backoff
|
|
102
|
-
- Automatic JSON parsing
|
|
103
|
-
|
|
104
|
-
## Choosing the Right Tool
|
|
105
|
-
|
|
106
|
-
- **REST API calls?** → Use `get`, `post`, `put`, `del`
|
|
107
|
-
- **Bidirectional real-time?** → Use `WebSocketClient`
|
|
108
|
-
- **Server push only?** → Use `SSEClient`
|
|
109
|
-
- **Both?** → Use `HttpClient` for requests, `WebSocketClient` or `SSEClient` for subscriptions
|
|
1
|
+
# HTTP, WebSocket & SSE
|
|
2
|
+
|
|
3
|
+
This module provides HTTP, WebSocket, and Server-Sent Events clients for network communication.
|
|
4
|
+
|
|
5
|
+
## Available Features
|
|
6
|
+
|
|
7
|
+
| Feature | Description | Use Case |
|
|
8
|
+
|---------|-------------|----------|
|
|
9
|
+
| [HTTP Client](HttpClient.md#http-client) | Type-safe HTTP functions | REST API calls with JWT handling |
|
|
10
|
+
| [WebSocketClient](HttpClient.md#websocket-client) | WebSocket client with auto-reconnect | Real-time bidirectional messaging |
|
|
11
|
+
| [SSEClient](ServerSentEvents.md) | Server-Sent Events as DOM events | Server push notifications |
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### HTTP Requests
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { configure, get, post } from '@relax.js/core/http';
|
|
19
|
+
|
|
20
|
+
configure({ baseUrl: '/api/v1' });
|
|
21
|
+
|
|
22
|
+
// GET with query parameters
|
|
23
|
+
const response = await get('/users', { status: 'active' });
|
|
24
|
+
if (response.success) {
|
|
25
|
+
const users = response.as<User[]>();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// POST with JSON body
|
|
29
|
+
const result = await post('/users', JSON.stringify({ name: 'John' }));
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### WebSocket Messaging
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { WebSocketClient } from '@relax.js/core/http';
|
|
36
|
+
|
|
37
|
+
const ws = new WebSocketClient<Message>('wss://api.example.com');
|
|
38
|
+
ws.connect();
|
|
39
|
+
|
|
40
|
+
// Check connection state
|
|
41
|
+
console.log(ws.connected); // true when connected
|
|
42
|
+
|
|
43
|
+
// Send (queued if disconnected)
|
|
44
|
+
ws.send({ type: 'chat', text: 'Hello' });
|
|
45
|
+
|
|
46
|
+
// Receive (rejects if connection closes)
|
|
47
|
+
try {
|
|
48
|
+
const message = await ws.receive();
|
|
49
|
+
} catch (e) {
|
|
50
|
+
console.log('Connection closed');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Disconnect when done
|
|
54
|
+
ws.disconnect();
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Server-Sent Events
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { SSEClient } from '@relax.js/core/http';
|
|
61
|
+
|
|
62
|
+
const sse = new SSEClient('/api/events', {
|
|
63
|
+
eventTypes: ['user-updated', 'notification']
|
|
64
|
+
});
|
|
65
|
+
sse.connect();
|
|
66
|
+
|
|
67
|
+
// Events dispatch to document by default
|
|
68
|
+
document.addEventListener('notification', (e: SSEMessageEvent) => {
|
|
69
|
+
showNotification(e.data);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Disconnect when done
|
|
73
|
+
sse.disconnect();
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Key Features
|
|
77
|
+
|
|
78
|
+
### HTTP Client
|
|
79
|
+
|
|
80
|
+
- Standalone functions (`get`, `post`, `put`, `del`, `request`)
|
|
81
|
+
- Module-wide configuration via `configure()`
|
|
82
|
+
- Automatic base URL prefixing
|
|
83
|
+
- JWT token from localStorage (configurable)
|
|
84
|
+
- Query string building
|
|
85
|
+
- Type-safe response casting
|
|
86
|
+
- Replaceable fetch for testing via `setFetch()`
|
|
87
|
+
|
|
88
|
+
### WebSocketClient
|
|
89
|
+
|
|
90
|
+
- Auto-reconnect with exponential backoff
|
|
91
|
+
- Message queuing when disconnected
|
|
92
|
+
- Custom message codecs
|
|
93
|
+
- Type-safe generic messages
|
|
94
|
+
- Connection state tracking
|
|
95
|
+
- Graceful disconnect support
|
|
96
|
+
|
|
97
|
+
### SSEClient
|
|
98
|
+
|
|
99
|
+
- Dispatches SSE events as DOM events
|
|
100
|
+
- Configurable target element or document
|
|
101
|
+
- Auto-reconnect with exponential backoff
|
|
102
|
+
- Automatic JSON parsing
|
|
103
|
+
|
|
104
|
+
## Choosing the Right Tool
|
|
105
|
+
|
|
106
|
+
- **REST API calls?** → Use `get`, `post`, `put`, `del`
|
|
107
|
+
- **Bidirectional real-time?** → Use `WebSocketClient`
|
|
108
|
+
- **Server push only?** → Use `SSEClient`
|
|
109
|
+
- **Both?** → Use `HttpClient` for requests, `WebSocketClient` or `SSEClient` for subscriptions
|
package/docs/i18n/i18n.md
CHANGED
|
@@ -5,7 +5,7 @@ Namespace-based translations with ICU message format, lazy loading, and locale c
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
7
7
|
```typescript
|
|
8
|
-
import { setLocale, loadNamespaces, t } from '
|
|
8
|
+
import { setLocale, loadNamespaces, t } from '@relax.js/core/i18n';
|
|
9
9
|
|
|
10
10
|
await setLocale('sv');
|
|
11
11
|
await loadNamespaces(['r-pipes', 'r-validation']);
|
|
@@ -106,6 +106,51 @@ t('status', { role: 'editor' }); // "Can edit"
|
|
|
106
106
|
t('status', { role: 'viewer' }); // "Read only" (other)
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
+
### Number and Date Formatting
|
|
110
|
+
|
|
111
|
+
ICU format supports locale-aware number and date formatting:
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{
|
|
115
|
+
"price": "Price: {amount, number, currency}",
|
|
116
|
+
"date": "Date: {date, date, medium}"
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Example Translation Files
|
|
121
|
+
|
|
122
|
+
**`src/i18n/locales/en/r-common.json`**:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"welcome": "Welcome to our site!",
|
|
127
|
+
"greeting": "Hello, {name}!",
|
|
128
|
+
"items": "{count, plural, =0 {No items} one {# item} other {# items}}",
|
|
129
|
+
"goodbye": "Goodbye!"
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**`src/i18n/locales/en/errors.json`**:
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"notFound": "Page not found",
|
|
138
|
+
"unauthorized": "You are not authorized to view this page",
|
|
139
|
+
"serverError": "An unexpected error occurred"
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**`src/i18n/locales/sv/r-common.json`**:
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"welcome": "Välkommen till vår sida!",
|
|
148
|
+
"greeting": "Hej, {name}!",
|
|
149
|
+
"items": "{count, plural, =0 {Inga föremål} one {# föremål} other {# föremål}}",
|
|
150
|
+
"goodbye": "Hejdå!"
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
109
154
|
## Built-in Namespaces
|
|
110
155
|
|
|
111
156
|
### r-common
|
|
@@ -173,7 +218,7 @@ The event has a typed `locale` property (the normalized locale code) and is regi
|
|
|
173
218
|
Register a callback for when `t()` encounters a missing key. Useful for development tooling, logging, or collecting untranslated strings:
|
|
174
219
|
|
|
175
220
|
```typescript
|
|
176
|
-
import { onMissingTranslation } from '
|
|
221
|
+
import { onMissingTranslation } from '@relax.js/core/i18n';
|
|
177
222
|
|
|
178
223
|
onMissingTranslation((key, namespace, locale) => {
|
|
179
224
|
console.warn(`Missing: ${namespace}:${key} [${locale}]`);
|
|
@@ -197,7 +242,7 @@ onMissingTranslation(null);
|
|
|
197
242
|
The built-in formatter supports interpolation, pluralization, and select. For advanced ICU features (nested arguments, date/time formatting in messages), use an external library:
|
|
198
243
|
|
|
199
244
|
```typescript
|
|
200
|
-
import { setMessageFormatter } from '
|
|
245
|
+
import { setMessageFormatter } from '@relax.js/core/i18n';
|
|
201
246
|
import { IntlMessageFormat } from 'intl-messageformat';
|
|
202
247
|
|
|
203
248
|
setMessageFormatter((message, values, locale) => {
|
|
@@ -284,7 +329,7 @@ type MissingTranslationHandler = (
|
|
|
284
329
|
import {
|
|
285
330
|
setLocale, loadNamespaces, t,
|
|
286
331
|
getCurrentLocale, onMissingTranslation,
|
|
287
|
-
} from '
|
|
332
|
+
} from '@relax.js/core/i18n';
|
|
288
333
|
|
|
289
334
|
async function initI18n() {
|
|
290
335
|
// Dev-time missing key logging
|