roomzin-js 1.0.0
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/LICENSE +68 -0
- package/README.md +467 -0
- package/dist/api/client.d.ts +86 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +3 -0
- package/dist/api/client.js.map +1 -0
- package/dist/cluster/api.d.ts +34 -0
- package/dist/cluster/api.d.ts.map +1 -0
- package/dist/cluster/api.js +250 -0
- package/dist/cluster/api.js.map +1 -0
- package/dist/cluster/config.d.ts +30 -0
- package/dist/cluster/config.d.ts.map +1 -0
- package/dist/cluster/config.js +86 -0
- package/dist/cluster/config.js.map +1 -0
- package/dist/cluster/index.d.ts +3 -0
- package/dist/cluster/index.d.ts.map +1 -0
- package/dist/cluster/index.js +21 -0
- package/dist/cluster/index.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/cluster/handler.d.ts +60 -0
- package/dist/internal/cluster/handler.d.ts.map +1 -0
- package/dist/internal/cluster/handler.js +589 -0
- package/dist/internal/cluster/handler.js.map +1 -0
- package/dist/internal/cluster/httputil.d.ts +25 -0
- package/dist/internal/cluster/httputil.d.ts.map +1 -0
- package/dist/internal/cluster/httputil.js +193 -0
- package/dist/internal/cluster/httputil.js.map +1 -0
- package/dist/internal/command/dec_room_avl.d.ts +5 -0
- package/dist/internal/command/dec_room_avl.d.ts.map +1 -0
- package/dist/internal/command/dec_room_avl.js +49 -0
- package/dist/internal/command/dec_room_avl.js.map +1 -0
- package/dist/internal/command/del_prop.d.ts +4 -0
- package/dist/internal/command/del_prop.d.ts.map +1 -0
- package/dist/internal/command/del_prop.js +43 -0
- package/dist/internal/command/del_prop.js.map +1 -0
- package/dist/internal/command/del_prop_day.d.ts +5 -0
- package/dist/internal/command/del_prop_day.d.ts.map +1 -0
- package/dist/internal/command/del_prop_day.js +47 -0
- package/dist/internal/command/del_prop_day.js.map +1 -0
- package/dist/internal/command/del_prop_room.d.ts +5 -0
- package/dist/internal/command/del_prop_room.d.ts.map +1 -0
- package/dist/internal/command/del_prop_room.js +46 -0
- package/dist/internal/command/del_prop_room.js.map +1 -0
- package/dist/internal/command/del_room_day.d.ts +5 -0
- package/dist/internal/command/del_room_day.d.ts.map +1 -0
- package/dist/internal/command/del_room_day.js +47 -0
- package/dist/internal/command/del_room_day.js.map +1 -0
- package/dist/internal/command/del_segment.d.ts +4 -0
- package/dist/internal/command/del_segment.d.ts.map +1 -0
- package/dist/internal/command/del_segment.js +43 -0
- package/dist/internal/command/del_segment.js.map +1 -0
- package/dist/internal/command/get_codecs.d.ts +5 -0
- package/dist/internal/command/get_codecs.d.ts.map +1 -0
- package/dist/internal/command/get_codecs.js +38 -0
- package/dist/internal/command/get_codecs.js.map +1 -0
- package/dist/internal/command/get_prop_room_day.d.ts +7 -0
- package/dist/internal/command/get_prop_room_day.d.ts.map +1 -0
- package/dist/internal/command/get_prop_room_day.js +59 -0
- package/dist/internal/command/get_prop_room_day.js.map +1 -0
- package/dist/internal/command/get_segments.d.ts +5 -0
- package/dist/internal/command/get_segments.d.ts.map +1 -0
- package/dist/internal/command/get_segments.js +47 -0
- package/dist/internal/command/get_segments.js.map +1 -0
- package/dist/internal/command/inc_room_avl.d.ts +5 -0
- package/dist/internal/command/inc_room_avl.d.ts.map +1 -0
- package/dist/internal/command/inc_room_avl.js +46 -0
- package/dist/internal/command/inc_room_avl.js.map +1 -0
- package/dist/internal/command/index.d.ts +20 -0
- package/dist/internal/command/index.d.ts.map +1 -0
- package/dist/internal/command/index.js +61 -0
- package/dist/internal/command/index.js.map +1 -0
- package/dist/internal/command/prop_exist.d.ts +4 -0
- package/dist/internal/command/prop_exist.d.ts.map +1 -0
- package/dist/internal/command/prop_exist.js +43 -0
- package/dist/internal/command/prop_exist.js.map +1 -0
- package/dist/internal/command/prop_room_date_list.d.ts +5 -0
- package/dist/internal/command/prop_room_date_list.d.ts.map +1 -0
- package/dist/internal/command/prop_room_date_list.js +50 -0
- package/dist/internal/command/prop_room_date_list.js.map +1 -0
- package/dist/internal/command/prop_room_exist.d.ts +5 -0
- package/dist/internal/command/prop_room_exist.d.ts.map +1 -0
- package/dist/internal/command/prop_room_exist.js +44 -0
- package/dist/internal/command/prop_room_exist.js.map +1 -0
- package/dist/internal/command/prop_room_list.d.ts +4 -0
- package/dist/internal/command/prop_room_list.d.ts.map +1 -0
- package/dist/internal/command/prop_room_list.js +45 -0
- package/dist/internal/command/prop_room_list.js.map +1 -0
- package/dist/internal/command/search_avail.d.ts +7 -0
- package/dist/internal/command/search_avail.d.ts.map +1 -0
- package/dist/internal/command/search_avail.js +129 -0
- package/dist/internal/command/search_avail.js.map +1 -0
- package/dist/internal/command/search_prop.d.ts +5 -0
- package/dist/internal/command/search_prop.d.ts.map +1 -0
- package/dist/internal/command/search_prop.js +73 -0
- package/dist/internal/command/search_prop.js.map +1 -0
- package/dist/internal/command/set_prop.d.ts +5 -0
- package/dist/internal/command/set_prop.d.ts.map +1 -0
- package/dist/internal/command/set_prop.js +47 -0
- package/dist/internal/command/set_prop.js.map +1 -0
- package/dist/internal/command/set_room_avl.d.ts +5 -0
- package/dist/internal/command/set_room_avl.d.ts.map +1 -0
- package/dist/internal/command/set_room_avl.js +46 -0
- package/dist/internal/command/set_room_avl.js.map +1 -0
- package/dist/internal/command/set_room_pkg.d.ts +5 -0
- package/dist/internal/command/set_room_pkg.d.ts.map +1 -0
- package/dist/internal/command/set_room_pkg.js +76 -0
- package/dist/internal/command/set_room_pkg.js.map +1 -0
- package/dist/internal/err.d.ts +16 -0
- package/dist/internal/err.d.ts.map +1 -0
- package/dist/internal/err.js +39 -0
- package/dist/internal/err.js.map +1 -0
- package/dist/internal/protocol/frame.d.ts +6 -0
- package/dist/internal/protocol/frame.d.ts.map +1 -0
- package/dist/internal/protocol/frame.js +118 -0
- package/dist/internal/protocol/frame.js.map +1 -0
- package/dist/internal/protocol/helpers.d.ts +8 -0
- package/dist/internal/protocol/helpers.d.ts.map +1 -0
- package/dist/internal/protocol/helpers.js +101 -0
- package/dist/internal/protocol/helpers.js.map +1 -0
- package/dist/internal/protocol/login.d.ts +2 -0
- package/dist/internal/protocol/login.d.ts.map +1 -0
- package/dist/internal/protocol/login.js +30 -0
- package/dist/internal/protocol/login.js.map +1 -0
- package/dist/internal/protocol/types.d.ts +19 -0
- package/dist/internal/protocol/types.d.ts.map +1 -0
- package/dist/internal/protocol/types.js +8 -0
- package/dist/internal/protocol/types.js.map +1 -0
- package/dist/internal/single/handler.d.ts +30 -0
- package/dist/internal/single/handler.d.ts.map +1 -0
- package/dist/internal/single/handler.js +197 -0
- package/dist/internal/single/handler.js.map +1 -0
- package/dist/single/api.d.ts +38 -0
- package/dist/single/api.d.ts.map +1 -0
- package/dist/single/api.js +240 -0
- package/dist/single/api.js.map +1 -0
- package/dist/single/config.d.ts +21 -0
- package/dist/single/config.d.ts.map +1 -0
- package/dist/single/config.js +64 -0
- package/dist/single/config.js.map +1 -0
- package/dist/single/index.d.ts +3 -0
- package/dist/single/index.d.ts.map +1 -0
- package/dist/single/index.js +21 -0
- package/dist/single/index.js.map +1 -0
- package/dist/types/codecs.d.ts +5 -0
- package/dist/types/codecs.d.ts.map +1 -0
- package/dist/types/codecs.js +16 -0
- package/dist/types/codecs.js.map +1 -0
- package/dist/types/discovery.d.ts +7 -0
- package/dist/types/discovery.d.ts.map +1 -0
- package/dist/types/discovery.js +3 -0
- package/dist/types/discovery.js.map +1 -0
- package/dist/types/err.d.ts +20 -0
- package/dist/types/err.d.ts.map +1 -0
- package/dist/types/err.js +38 -0
- package/dist/types/err.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +21 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/request.d.ts +94 -0
- package/dist/types/request.d.ts.map +1 -0
- package/dist/types/request.js +207 -0
- package/dist/types/request.js.map +1 -0
- package/dist/types/response.d.ts +22 -0
- package/dist/types/response.d.ts.map +1 -0
- package/dist/types/response.js +3 -0
- package/dist/types/response.js.map +1 -0
- package/package.json +34 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
Business Source License 1.1
|
|
2
|
+
|
|
3
|
+
Licensor: m-javani (or your company name)
|
|
4
|
+
|
|
5
|
+
Licensed Work: Roomzin Go SDK
|
|
6
|
+
The Licensed Work is (c) 2024 m-javani (or your company)
|
|
7
|
+
|
|
8
|
+
Additional Use Grant: You may use the Licensed Work in production
|
|
9
|
+
provided that your use does not include offering the Licensed Work
|
|
10
|
+
as a service to third parties, or creating a derivative work that
|
|
11
|
+
is offered as a service to third parties.
|
|
12
|
+
|
|
13
|
+
Change Date: 2030-01-01
|
|
14
|
+
|
|
15
|
+
Change License: GNU General Public License v3.0 or later
|
|
16
|
+
|
|
17
|
+
Terms:
|
|
18
|
+
|
|
19
|
+
The Licensor hereby grants you the right to copy, modify, create derivative
|
|
20
|
+
works, redistribute, and make non-production use of the Licensed Work. The
|
|
21
|
+
Licensor may make an Additional Use Grant, above, permitting limited
|
|
22
|
+
production use.
|
|
23
|
+
|
|
24
|
+
Effective on the Change Date, or the fourth anniversary of the first publicly
|
|
25
|
+
available distribution of a specific version of the Licensed Work under this
|
|
26
|
+
License, whichever comes first, the Licensor hereby grants you rights under
|
|
27
|
+
the terms of the Change License, and the rights granted in the paragraph
|
|
28
|
+
above terminate.
|
|
29
|
+
|
|
30
|
+
If your use of the Licensed Work does not comply with the requirements
|
|
31
|
+
currently in effect as described in this License, you must purchase a
|
|
32
|
+
commercial license from the Licensor, its affiliated entities, or authorized
|
|
33
|
+
resellers, or you must refrain from using the Licensed Work.
|
|
34
|
+
|
|
35
|
+
All copies of the original and modified Licensed Work, and derivative works
|
|
36
|
+
of the Licensed Work, are subject to this License. This License applies
|
|
37
|
+
separately for each version of the Licensed Work and the Change Date may
|
|
38
|
+
vary for each version of the Licensed Work.
|
|
39
|
+
|
|
40
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
41
|
+
of this Licensed Work (the "Software"), to use, copy, modify, merge, publish,
|
|
42
|
+
and/or distribute copies of the Software, subject to the conditions:
|
|
43
|
+
|
|
44
|
+
1. Redistributions of source code must retain the above copyright notice,
|
|
45
|
+
this list of conditions and the following disclaimers.
|
|
46
|
+
|
|
47
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
48
|
+
this list of conditions and the following disclaimers in the documentation
|
|
49
|
+
and/or other materials provided with the distribution.
|
|
50
|
+
|
|
51
|
+
3. Neither the names of the Licensor, nor the names of its contributors
|
|
52
|
+
may be used to endorse or promote products derived from this Software
|
|
53
|
+
without specific prior written permission.
|
|
54
|
+
|
|
55
|
+
4. You must not use the Software in any manner that is primarily intended for
|
|
56
|
+
or directed toward commercial advantage or private monetary compensation,
|
|
57
|
+
unless you have obtained a commercial license from the Licensor.
|
|
58
|
+
|
|
59
|
+
Disclaimer of Warranty. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
60
|
+
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
|
|
61
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
|
62
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
63
|
+
DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR
|
|
64
|
+
OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
65
|
+
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
66
|
+
|
|
67
|
+
THE LICENSOR DOES NOT PROVIDE ANY SUPPORT FOR THE LICENSED WORK, EXCEPT AS
|
|
68
|
+
EXPRESSLY STATED IN A SEPARATE AGREEMENT.
|
package/README.md
ADDED
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
# Roomzin Node.js SDK
|
|
2
|
+
|
|
3
|
+
Official Node.js SDK for [Roomzin](https://m-javani.github.io/roomzin-doc/) — a high-performance in-memory inventory engine for booking platforms.
|
|
4
|
+
|
|
5
|
+
The SDK provides a modern TypeScript API for communicating with Roomzin servers in both standalone and clustered deployments. It automatically manages routing, failover, connection pooling, and cluster topology changes.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- Automatic request routing (leader for writes, followers for reads)
|
|
12
|
+
- Built-in failover and cluster discovery
|
|
13
|
+
- Connection pooling
|
|
14
|
+
- Standalone and clustered deployment support
|
|
15
|
+
- Fully typed TypeScript API
|
|
16
|
+
- Promise-based asynchronous API
|
|
17
|
+
- Reusable, concurrency-safe client
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Requirements
|
|
22
|
+
|
|
23
|
+
- Node.js 18 or later
|
|
24
|
+
- Roomzin Server v1.x
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install roomzin-js
|
|
32
|
+
# or
|
|
33
|
+
yarn add roomzin-js
|
|
34
|
+
# or
|
|
35
|
+
pnpm add roomzin-js
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Client Setup
|
|
41
|
+
|
|
42
|
+
### Standalone
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { SingleClient } from 'roomzin-js';
|
|
46
|
+
|
|
47
|
+
const client = await SingleClient.create({
|
|
48
|
+
host: '127.0.0.1',
|
|
49
|
+
tcpPort: 7777,
|
|
50
|
+
authToken: 'abc123',
|
|
51
|
+
timeout: 5000, // 5 seconds
|
|
52
|
+
keepAlive: 30000, // 30 seconds
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Use client...
|
|
56
|
+
await client.close();
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Cluster (Static Discovery)
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { ClusterClient, ClusterConfigBuilder } from 'roomzin-js';
|
|
63
|
+
import type { NodeAddr } from 'roomzin-js';
|
|
64
|
+
|
|
65
|
+
const staticDiscovery: NodeAddr[] = [
|
|
66
|
+
{ node_id: 'roomzin-0', addr: '172.20.0.10', tcp_port: 7777, api_port: 8080 },
|
|
67
|
+
{ node_id: 'roomzin-1', addr: '172.20.0.11', tcp_port: 7777, api_port: 8080 },
|
|
68
|
+
{ node_id: 'roomzin-2', addr: '172.20.0.12', tcp_port: 7777, api_port: 8080 },
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
const cfg = ClusterConfigBuilder.new()
|
|
72
|
+
.withSeedNodeIds('roomzin-0,roomzin-1,roomzin-2')
|
|
73
|
+
.withStaticDiscovery(staticDiscovery)
|
|
74
|
+
.withAPIPort(8080)
|
|
75
|
+
.withTCPPort(7777)
|
|
76
|
+
.withToken('abc123')
|
|
77
|
+
.withTimeout(5000)
|
|
78
|
+
.withHttpTimeout(5000)
|
|
79
|
+
.withKeepAlive(30000)
|
|
80
|
+
.withMaxActiveConns(100)
|
|
81
|
+
.build();
|
|
82
|
+
|
|
83
|
+
const client = await ClusterClient.create(cfg);
|
|
84
|
+
await client.close();
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Cluster (HTTP Discovery)
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
const cfg = ClusterConfigBuilder.new()
|
|
91
|
+
.withSeedNodeIds('roomzin-0,roomzin-1,roomzin-2')
|
|
92
|
+
.withHTTPDiscovery('http://discovery-service:8080/nodes')
|
|
93
|
+
.withAPIPort(8080)
|
|
94
|
+
.withTCPPort(7777)
|
|
95
|
+
.withToken('abc123')
|
|
96
|
+
.withTimeout(5000)
|
|
97
|
+
.withHttpTimeout(5000)
|
|
98
|
+
.withKeepAlive(30000)
|
|
99
|
+
.build();
|
|
100
|
+
|
|
101
|
+
const client = await ClusterClient.create(cfg);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Discovery Configuration
|
|
107
|
+
|
|
108
|
+
Roomzin SDKs need to know how to reach each Roomzin node in the cluster. The cluster nodes communicate with each other using internal address resolvers, but the SDK as an external client needs actual network addresses (IP:port or hostname:port) to connect.
|
|
109
|
+
|
|
110
|
+
The SDK fetches the cluster topology from the Roomzin cluster itself. This topology includes the node identities of the leader and followers. The SDK then uses discovery to resolve these node identities into actual network addresses.
|
|
111
|
+
|
|
112
|
+
Two discovery modes are supported:
|
|
113
|
+
|
|
114
|
+
### Static Discovery
|
|
115
|
+
|
|
116
|
+
The SDK gets the mapping once in config and never updates it. Use this when your cluster nodes have stable, predictable addresses.
|
|
117
|
+
|
|
118
|
+
### HTTP Discovery
|
|
119
|
+
|
|
120
|
+
The SDK periodically fetches the mapping from an HTTP endpoint. Use this when cluster nodes are dynamic (e.g., Kubernetes pods with changing IPs).
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Property Management
|
|
125
|
+
|
|
126
|
+
### setProp
|
|
127
|
+
Adds or updates a property.
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
await client.setProp({
|
|
131
|
+
segment: 'downtown',
|
|
132
|
+
area: 'manhattan',
|
|
133
|
+
propertyID: 'hotel_123',
|
|
134
|
+
propertyType: 'hotel',
|
|
135
|
+
category: 'luxury',
|
|
136
|
+
stars: 4,
|
|
137
|
+
latitude: 40.7128,
|
|
138
|
+
longitude: -74.0060,
|
|
139
|
+
amenities: ['wifi', 'pool', 'gym'],
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### searchProp
|
|
144
|
+
Searches properties by segment, area, type, or location.
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
// By segment
|
|
148
|
+
const ids = await client.searchProp({ segment: 'downtown' });
|
|
149
|
+
|
|
150
|
+
// By area
|
|
151
|
+
const ids = await client.searchProp({
|
|
152
|
+
segment: 'downtown',
|
|
153
|
+
area: 'manhattan',
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// By location (radius search)
|
|
157
|
+
const ids = await client.searchProp({
|
|
158
|
+
segment: 'downtown',
|
|
159
|
+
latitude: 40.7128,
|
|
160
|
+
longitude: -74.0060,
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### propExist
|
|
165
|
+
Checks if a property exists.
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
const exists = await client.propExist('hotel_123');
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### propRoomExist
|
|
172
|
+
Checks if a specific room type exists for a property.
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
const exists = await client.propRoomExist({
|
|
176
|
+
propertyID: 'hotel_123',
|
|
177
|
+
roomType: 'suite',
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### propRoomList
|
|
182
|
+
Lists all room types for a property.
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
const rooms = await client.propRoomList('hotel_123');
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### propRoomDateList
|
|
189
|
+
Lists dates with availability data for a property and room type.
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
const dates = await client.propRoomDateList({
|
|
193
|
+
propertyID: 'hotel_123',
|
|
194
|
+
roomType: 'suite',
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Room Package Management
|
|
201
|
+
|
|
202
|
+
### setRoomPkg
|
|
203
|
+
Sets availability, price, and rate features for a room type on a date.
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
await client.setRoomPkg({
|
|
207
|
+
propertyID: 'hotel_123',
|
|
208
|
+
roomType: 'suite',
|
|
209
|
+
date: '2026-07-20',
|
|
210
|
+
availability: 10,
|
|
211
|
+
finalPrice: 199,
|
|
212
|
+
rateFeature: ['free_cancellation', 'breakfast_included'],
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### setRoomAvl
|
|
217
|
+
Sets exact availability for a room type on a specific date.
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
const newAvail = await client.setRoomAvl({
|
|
221
|
+
propertyID: 'hotel_123',
|
|
222
|
+
roomType: 'suite',
|
|
223
|
+
date: '2026-07-20',
|
|
224
|
+
amount: 20,
|
|
225
|
+
});
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### incRoomAvl
|
|
229
|
+
Increases availability (e.g., on cancellation).
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
const newAvail = await client.incRoomAvl({
|
|
233
|
+
propertyID: 'hotel_123',
|
|
234
|
+
roomType: 'suite',
|
|
235
|
+
date: '2026-07-20',
|
|
236
|
+
amount: 1,
|
|
237
|
+
});
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### decRoomAvl
|
|
241
|
+
Decreases availability (e.g., on booking).
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
const newAvail = await client.decRoomAvl({
|
|
245
|
+
propertyID: 'hotel_123',
|
|
246
|
+
roomType: 'suite',
|
|
247
|
+
date: '2026-07-20',
|
|
248
|
+
amount: 2,
|
|
249
|
+
});
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### getPropRoomDay
|
|
253
|
+
Gets availability and pricing for a specific room on a specific date.
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
const day = await client.getPropRoomDay({
|
|
257
|
+
propertyID: 'hotel_123',
|
|
258
|
+
roomType: 'suite',
|
|
259
|
+
date: '2026-07-20',
|
|
260
|
+
});
|
|
261
|
+
console.log(`Avail: ${day.availability}, Price: ${day.finalPrice}`);
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Search & Query
|
|
267
|
+
|
|
268
|
+
### searchAvail
|
|
269
|
+
Searches available rooms by filters.
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
const results = await client.searchAvail({
|
|
273
|
+
segment: 'downtown',
|
|
274
|
+
roomType: 'suite',
|
|
275
|
+
date: ['2026-07-20', '2026-07-21'],
|
|
276
|
+
limit: 50,
|
|
277
|
+
minPrice: 100,
|
|
278
|
+
maxPrice: 300,
|
|
279
|
+
amenities: ['wifi', 'pool'],
|
|
280
|
+
rateFeature: ['free_cancellation'],
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
for (const result of results) {
|
|
284
|
+
console.log(`Property: ${result.propertyID}`);
|
|
285
|
+
for (const day of result.days) {
|
|
286
|
+
console.log(` ${day.date}: Avail ${day.availability}, Price ${day.finalPrice}`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### getSegments
|
|
292
|
+
Lists all active segments with their property counts.
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
const segments = await client.getSegments();
|
|
296
|
+
for (const seg of segments) {
|
|
297
|
+
console.log(`${seg.segment}: ${seg.count} properties`);
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### getCodecs
|
|
302
|
+
Gets the current codec registry (used internally for validation).
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
const codecs = await client.getCodecs();
|
|
306
|
+
console.log(codecs.rateFeatures);
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## Delete Operations
|
|
312
|
+
|
|
313
|
+
### delRoomDay
|
|
314
|
+
Deletes availability for a specific room on a specific date.
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
await client.delRoomDay({
|
|
318
|
+
propertyID: 'hotel_123',
|
|
319
|
+
roomType: 'suite',
|
|
320
|
+
date: '2026-07-20',
|
|
321
|
+
});
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### delPropDay
|
|
325
|
+
Deletes all data for a property on a specific date.
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
await client.delPropDay({
|
|
329
|
+
propertyID: 'hotel_123',
|
|
330
|
+
date: '2026-07-20',
|
|
331
|
+
});
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### delPropRoom
|
|
335
|
+
Deletes a room type from a property.
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
await client.delPropRoom({
|
|
339
|
+
propertyID: 'hotel_123',
|
|
340
|
+
roomType: 'suite',
|
|
341
|
+
});
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### delProp
|
|
345
|
+
Deletes an entire property.
|
|
346
|
+
|
|
347
|
+
```typescript
|
|
348
|
+
await client.delProp('hotel_123');
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### delSegment
|
|
352
|
+
Deletes a segment and all properties within it.
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
await client.delSegment('downtown');
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## Error Handling
|
|
361
|
+
|
|
362
|
+
Every SDK operation may reject with a `RoomzinError`. Use the provided helper functions to classify errors:
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
import { IsRequest, IsRetry, IsClient, IsInternal } from 'roomzin-js';
|
|
366
|
+
|
|
367
|
+
try {
|
|
368
|
+
await client.setRoomPkg(payload);
|
|
369
|
+
} catch (err) {
|
|
370
|
+
if (IsRequest(err)) {
|
|
371
|
+
// Business rule violation - fix the request
|
|
372
|
+
console.log('Request error:', err.code);
|
|
373
|
+
} else if (IsRetry(err)) {
|
|
374
|
+
// Temporary condition - retry with backoff
|
|
375
|
+
await sleep(100);
|
|
376
|
+
await client.setRoomPkg(payload);
|
|
377
|
+
} else if (IsClient(err)) {
|
|
378
|
+
// Authentication or protocol errors
|
|
379
|
+
console.log('Client error:', err.message);
|
|
380
|
+
} else if (IsInternal(err)) {
|
|
381
|
+
// Unexpected server response
|
|
382
|
+
throw new Error('Internal error', { cause: err });
|
|
383
|
+
} else {
|
|
384
|
+
// Fatal error
|
|
385
|
+
throw err;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Error Categories
|
|
391
|
+
|
|
392
|
+
| Category | Description | Action |
|
|
393
|
+
|----------|-------------|--------|
|
|
394
|
+
| **Client** | Authentication or protocol errors | Check credentials and configuration |
|
|
395
|
+
| **Request** | Invalid input or business rule violation | Fix request, don't retry |
|
|
396
|
+
| **Retry** | Temporary server condition (429, 503, 308) | Retry with backoff |
|
|
397
|
+
| **Internal** | Unexpected server response | Log and investigate |
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## Client Lifecycle
|
|
402
|
+
|
|
403
|
+
Create a **single client** during application startup and reuse it throughout your application.
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
// ✅ Good - create once, reuse
|
|
407
|
+
const client = await SingleClient.create(config);
|
|
408
|
+
// Use client everywhere...
|
|
409
|
+
await client.close();
|
|
410
|
+
|
|
411
|
+
// ❌ Bad - creating per request
|
|
412
|
+
for (const req of requests) {
|
|
413
|
+
const client = await SingleClient.create(config); // Don't do this
|
|
414
|
+
await client.setRoomPkg(req);
|
|
415
|
+
await client.close();
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
The client is safe for concurrent use and manages TCP connections internally.
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## API Reference
|
|
424
|
+
|
|
425
|
+
For the complete interface definition, see [`src/api/client.ts`](src/api/client.ts). All types are documented with JSDoc comments.
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## Documentation
|
|
430
|
+
|
|
431
|
+
For Roomzin concepts, deployment, and administration:
|
|
432
|
+
|
|
433
|
+
[https://m-javani.github.io/roomzin-doc/docs.html](https://m-javani.github.io/roomzin-doc/docs.html)
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## Contributing
|
|
438
|
+
|
|
439
|
+
Contributions are welcome! Please open an issue before proposing large changes.
|
|
440
|
+
|
|
441
|
+
All contributions are subject to the BUSL-1.1 License terms.
|
|
442
|
+
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
## License
|
|
446
|
+
|
|
447
|
+
This SDK is licensed under the [BUSL-1.1 License](LICENSE).
|
|
448
|
+
|
|
449
|
+
**Note:** This SDK communicates with Roomzin Server, which requires a valid Roomzin license.
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## Support
|
|
454
|
+
|
|
455
|
+
- **Documentation**: [roomzin-doc](https://m-javani.github.io/roomzin-doc/)
|
|
456
|
+
- **Community Q&A**: [GitHub Discussions](https://github.com/m-javani/roomzin-doc/discussions)
|
|
457
|
+
- **Issues**: [GitHub Issues](https://github.com/roomzin/roomzin-js/issues)
|
|
458
|
+
- **Security**: [mehdy.javany@gmail.com](mailto:mehdy.javany@gmail.com)
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
## Related Repositories
|
|
463
|
+
|
|
464
|
+
- [Roomzin Quickstart](https://github.com/m-javani/roomzin-quickstart) — Local Docker cluster
|
|
465
|
+
- [Roomzin Bench](https://github.com/m-javani/roomzin-bench) — Benchmarking tool
|
|
466
|
+
|
|
467
|
+
---
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { PropertyAvail, GetRoomDayResult, SegmentInfo } from '../types/response';
|
|
2
|
+
import type { Codecs } from '../types/codecs';
|
|
3
|
+
import type { SetPropPayload, SearchPropPayload, SearchAvailPayload, SetRoomPkgPayload, UpdRoomAvlPayload, PropRoomExistPayload, PropRoomDateListPayload, DelPropDayRequest, DelPropRoomPayload, DelRoomDayRequest, GetRoomDayRequest } from '../types/request';
|
|
4
|
+
export interface CacheClientAPI {
|
|
5
|
+
/**
|
|
6
|
+
* Returns the current codec registry (field IDs, compression, etc.)
|
|
7
|
+
*/
|
|
8
|
+
getCodecs(): Promise<Codecs>;
|
|
9
|
+
/**
|
|
10
|
+
* Set property metadata
|
|
11
|
+
*/
|
|
12
|
+
setProp(p: SetPropPayload): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Search properties by filters
|
|
15
|
+
*/
|
|
16
|
+
searchProp(p: SearchPropPayload): Promise<string[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Search availability across properties/dates
|
|
19
|
+
*/
|
|
20
|
+
searchAvail(p: SearchAvailPayload): Promise<PropertyAvail[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Assign a package/pricing to a room type
|
|
23
|
+
*/
|
|
24
|
+
setRoomPkg(p: SetRoomPkgPayload): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Absolute set of room availability
|
|
27
|
+
*/
|
|
28
|
+
setRoomAvl(p: UpdRoomAvlPayload): Promise<number>;
|
|
29
|
+
/**
|
|
30
|
+
* Increment room availability (e.g. on cancellation)
|
|
31
|
+
*/
|
|
32
|
+
incRoomAvl(p: UpdRoomAvlPayload): Promise<number>;
|
|
33
|
+
/**
|
|
34
|
+
* Decrement room availability (e.g. on booking)
|
|
35
|
+
*/
|
|
36
|
+
decRoomAvl(p: UpdRoomAvlPayload): Promise<number>;
|
|
37
|
+
/**
|
|
38
|
+
* Check if property exists
|
|
39
|
+
*/
|
|
40
|
+
propExist(propertyID: string): Promise<boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* Check if specific room type exists in property
|
|
43
|
+
*/
|
|
44
|
+
propRoomExist(p: PropRoomExistPayload): Promise<boolean>;
|
|
45
|
+
/**
|
|
46
|
+
* List all room type IDs for a property
|
|
47
|
+
*/
|
|
48
|
+
propRoomList(propertyID: string): Promise<string[]>;
|
|
49
|
+
/**
|
|
50
|
+
* List dates that have availability data for a property+room
|
|
51
|
+
*/
|
|
52
|
+
propRoomDateList(p: PropRoomDateListPayload): Promise<string[]>;
|
|
53
|
+
/**
|
|
54
|
+
* Delete entire property
|
|
55
|
+
*/
|
|
56
|
+
delProp(propertyID: string): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Delete a segment (rate plan, channel, etc.)
|
|
59
|
+
*/
|
|
60
|
+
delSegment(segment: string): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Delete all data for a property on a specific date
|
|
63
|
+
*/
|
|
64
|
+
delPropDay(p: DelPropDayRequest): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Delete a room type from a property
|
|
67
|
+
*/
|
|
68
|
+
delPropRoom(p: DelPropRoomPayload): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Delete availability for a specific room+date
|
|
71
|
+
*/
|
|
72
|
+
delRoomDay(p: DelRoomDayRequest): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Get availability & pricing for a specific room+date
|
|
75
|
+
*/
|
|
76
|
+
getPropRoomDay(p: GetRoomDayRequest): Promise<GetRoomDayResult>;
|
|
77
|
+
/**
|
|
78
|
+
* List all active segments
|
|
79
|
+
*/
|
|
80
|
+
getSegments(): Promise<SegmentInfo[]>;
|
|
81
|
+
/**
|
|
82
|
+
* Close connection and release resources
|
|
83
|
+
*/
|
|
84
|
+
close(): Promise<void>;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,aAAa,EACb,gBAAgB,EAChB,WAAW,EACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EACR,MAAM,EACT,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EACR,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACpB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,cAAc;IAC3B;;OAEG;IACH,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAE7B;;OAEG;IACH,OAAO,CAAC,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1C;;OAEG;IACH,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEpD;;OAEG;IACH,WAAW,CAAC,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAE7D;;OAEG;IACH,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhD;;OAEG;IACH,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAElD;;OAEG;IACH,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAElD;;OAEG;IACH,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAElD;;OAEG;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEhD;;OAEG;IACH,aAAa,CAAC,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEzD;;OAEG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEpD;;OAEG;IACH,gBAAgB,CAAC,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEhE;;OAEG;IACH,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3C;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3C;;OAEG;IACH,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhD;;OAEG;IACH,WAAW,CAAC,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElD;;OAEG;IACH,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhD;;OAEG;IACH,cAAc,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAEhE;;OAEG;IACH,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAEtC;;OAEG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ClusterConfig } from './config';
|
|
2
|
+
import type { CacheClientAPI } from '../api/client';
|
|
3
|
+
import type { Codecs } from '../types/codecs';
|
|
4
|
+
import { DelPropDayRequest, DelPropRoomPayload, DelRoomDayRequest, GetRoomDayRequest, PropRoomDateListPayload, PropRoomExistPayload, SearchAvailPayload, SearchPropPayload, SetPropPayload, SetRoomPkgPayload, UpdRoomAvlPayload } from '../types/request';
|
|
5
|
+
export declare class Client implements CacheClientAPI {
|
|
6
|
+
private handler;
|
|
7
|
+
private codecs;
|
|
8
|
+
private constructor();
|
|
9
|
+
static create(cfg: ClusterConfig): Promise<Client>;
|
|
10
|
+
private getCodecsInternal;
|
|
11
|
+
private fetchCodecs;
|
|
12
|
+
private assertOk;
|
|
13
|
+
getCodecs(): Promise<Codecs>;
|
|
14
|
+
setProp(p: SetPropPayload): Promise<void>;
|
|
15
|
+
setRoomPkg(p: SetRoomPkgPayload): Promise<void>;
|
|
16
|
+
setRoomAvl(p: UpdRoomAvlPayload): Promise<number>;
|
|
17
|
+
incRoomAvl(p: UpdRoomAvlPayload): Promise<number>;
|
|
18
|
+
decRoomAvl(p: UpdRoomAvlPayload): Promise<number>;
|
|
19
|
+
searchProp(p: SearchPropPayload): Promise<string[]>;
|
|
20
|
+
searchAvail(p: SearchAvailPayload): Promise<any[]>;
|
|
21
|
+
propExist(propertyID: string): Promise<boolean>;
|
|
22
|
+
propRoomExist(p: PropRoomExistPayload): Promise<boolean>;
|
|
23
|
+
propRoomList(propertyID: string): Promise<string[]>;
|
|
24
|
+
propRoomDateList(p: PropRoomDateListPayload): Promise<string[]>;
|
|
25
|
+
delProp(propertyID: string): Promise<void>;
|
|
26
|
+
delSegment(segment: string): Promise<void>;
|
|
27
|
+
delPropDay(p: DelPropDayRequest): Promise<void>;
|
|
28
|
+
delPropRoom(p: DelPropRoomPayload): Promise<void>;
|
|
29
|
+
delRoomDay(p: DelRoomDayRequest): Promise<void>;
|
|
30
|
+
getPropRoomDay(p: GetRoomDayRequest): Promise<any>;
|
|
31
|
+
getSegments(): Promise<any[]>;
|
|
32
|
+
close(): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/cluster/api.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AA4C9C,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,cAAc,EAAE,iBAAiB,EAAE,iBAAiB,EAAwM,MAAM,kBAAkB,CAAC;AAIjc,qBAAa,MAAO,YAAW,cAAc;IACzC,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,MAAM,CAAuB;IAErC,OAAO;WASM,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;YAmC1C,iBAAiB;YAQjB,WAAW;IAWzB,OAAO,CAAC,QAAQ;IAYV,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC;IAM5B,OAAO,CAAC,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAYzC,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAY/C,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAUjD,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAUjD,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAUjD,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAWnD,WAAW,CAAC,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAWlD,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ/C,aAAa,CAAC,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC;IAUxD,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAQnD,gBAAgB,CAAC,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAU/D,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS1C,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ1C,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAU/C,WAAW,CAAC,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUjD,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAU/C,cAAc,CAAC,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,GAAG,CAAC;IAWlD,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAO7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG/B"}
|