@hf-chimera/store 0.0.4 → 0.0.6
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/.changeset/README.md +8 -0
- package/CHANGELOG.md +24 -0
- package/README.md +635 -2
- package/dist/index-CqYNg3Vx.d.ts +22 -0
- package/dist/index-CqYNg3Vx.d.ts.map +1 -0
- package/dist/index-DgwhyIVQ.d.cts +800 -0
- package/dist/index-DgwhyIVQ.d.cts.map +1 -0
- package/dist/index-Mu4KG7Z7.d.cts +22 -0
- package/dist/index-Mu4KG7Z7.d.cts.map +1 -0
- package/dist/index-kFATKhTP.d.ts +800 -0
- package/dist/index-kFATKhTP.d.ts.map +1 -0
- package/dist/index.cjs +27 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -1
- package/dist/qb-Cg4Q_DkJ.cjs +49 -0
- package/dist/qb-DHuihkTp.js +45 -0
- package/dist/qb-DHuihkTp.js.map +1 -0
- package/dist/qb.cjs +4 -0
- package/dist/qb.d.cts +3 -0
- package/dist/qb.d.ts +3 -0
- package/dist/qb.js +4 -0
- package/dist/src-Bx-gbHfm.js +1882 -0
- package/dist/src-Bx-gbHfm.js.map +1 -0
- package/dist/src-u2_wgi_K.cjs +2031 -0
- package/package.json +53 -13
- package/dist/index.d.mts +0 -2
- package/dist/index.mjs +0 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Changesets
|
|
2
|
+
|
|
3
|
+
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
|
|
4
|
+
with multi-package repos, or single-package repos to help you version and publish your code. You can
|
|
5
|
+
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
|
|
6
|
+
|
|
7
|
+
We have a quick list of common questions to get you started engaging with this project in
|
|
8
|
+
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @hf-chimera/store
|
|
2
2
|
|
|
3
|
+
## 0.0.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Update npmignore
|
|
8
|
+
|
|
9
|
+
## 0.0.5
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Implement library with adapters
|
|
14
|
+
|
|
15
|
+
This patch release introduces the complete implementation of the
|
|
16
|
+
`@hf-chimera/store` library with a flexible adapter system:
|
|
17
|
+
|
|
18
|
+
- **React Adapter** (`packages/adapters/react`): Hooks and context for
|
|
19
|
+
integrating the store with React applications
|
|
20
|
+
- **Query Builder** (`packages/qb`): Fluent API for constructing complex queries
|
|
21
|
+
- **CRUD Example**: Full-stack example application demonstrating store usage
|
|
22
|
+
with customers and orders
|
|
23
|
+
- **Core Improvements**: Bug fixes in ordering logic (using the first non-equal
|
|
24
|
+
result) and enhanced type safety
|
|
25
|
+
- **Testing Infrastructure**: Added Vitest UI and comprehensive test coverage
|
|
26
|
+
|
|
3
27
|
## 0.0.4
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,3 +1,636 @@
|
|
|
1
|
-
Chimera Store
|
|
1
|
+
# Chimera Store
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A cross-platform, reactive cache management library with intelligent
|
|
4
|
+
deduplication and efficient data synchronization. Chimera Store provides a
|
|
5
|
+
powerful API for managing cached data with built-in querying, filtering,
|
|
6
|
+
ordering, and real-time updates.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **🔄 Cross-Platform Reactivity**: Works seamlessly across web, mobile, and
|
|
11
|
+
desktop platforms
|
|
12
|
+
- **💾 Intelligent Cache Management**: Automatic deduplication and
|
|
13
|
+
memory-efficient caching
|
|
14
|
+
- **🔍 Advanced Querying**: Built-in filtering, and sorting support (Pagination
|
|
15
|
+
in development)
|
|
16
|
+
- **⚡ Real-Time Updates**: Event-driven architecture with automatic cache
|
|
17
|
+
invalidation
|
|
18
|
+
- **🎯 Type Safety**: Full TypeScript support with comprehensive type definitions
|
|
19
|
+
- **🛡️ Error Handling**: Robust error handling with detailed error messages
|
|
20
|
+
- **📦 Modular Architecture**: Composable components for flexible integration
|
|
21
|
+
- **🌐 Universal Compatibility**: Works with any data source (REST APIs, GraphQL,
|
|
22
|
+
WebSockets, etc.)
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install @hf-chimera/store
|
|
28
|
+
# or
|
|
29
|
+
yarn add @hf-chimera/store
|
|
30
|
+
# or
|
|
31
|
+
pnpm add @hf-chimera/store
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
### Basic Setup
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { ChimeraStore } from '@hf-chimera/store';
|
|
40
|
+
|
|
41
|
+
// Define your entity types
|
|
42
|
+
type User = {
|
|
43
|
+
id: string;
|
|
44
|
+
name: string;
|
|
45
|
+
email: string;
|
|
46
|
+
age: number;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
type Post = {
|
|
50
|
+
id: string;
|
|
51
|
+
title: string;
|
|
52
|
+
content: string;
|
|
53
|
+
authorId: string;
|
|
54
|
+
createdAt: Date;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// Define your entity map
|
|
58
|
+
type EntityMap = {
|
|
59
|
+
users: User;
|
|
60
|
+
posts: Post;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// Create store configuration
|
|
64
|
+
const store = new ChimeraStore<EntityMap>({
|
|
65
|
+
query: {
|
|
66
|
+
defaults: {
|
|
67
|
+
trustQuery: true,
|
|
68
|
+
updateDebounceTimeout: 0,
|
|
69
|
+
// idGetter can be a string (object key) or a function
|
|
70
|
+
// String: Uses the specified property as the ID (e.g., 'id', 'uuid', 'key')
|
|
71
|
+
// Function: Custom ID extraction logic (entityName, value) => string | number
|
|
72
|
+
idGetter: 'id',
|
|
73
|
+
collectionFetcher: async (entityName, params, requestParams) => {
|
|
74
|
+
// Implement your data fetching logic
|
|
75
|
+
const response = await fetch(`/api/${entityName}`, {
|
|
76
|
+
signal: requestParams.signal,
|
|
77
|
+
// Add your request logic here
|
|
78
|
+
});
|
|
79
|
+
return {data: await response.json()};
|
|
80
|
+
},
|
|
81
|
+
itemFetcher: async (entityName, params, requestParams) => {
|
|
82
|
+
const response = await fetch(`/api/${entityName}/${params.id}`, {
|
|
83
|
+
signal: requestParams.signal,
|
|
84
|
+
});
|
|
85
|
+
return {data: await response.json()};
|
|
86
|
+
},
|
|
87
|
+
itemUpdater: async (entityName, item, requestParams) => {
|
|
88
|
+
const response = await fetch(`/api/${entityName}/${item.id}`, {
|
|
89
|
+
method: 'PUT',
|
|
90
|
+
body: JSON.stringify(item),
|
|
91
|
+
signal: requestParams.signal,
|
|
92
|
+
});
|
|
93
|
+
return {data: await response.json()};
|
|
94
|
+
},
|
|
95
|
+
itemDeleter: async (entityName, id, requestParams) => {
|
|
96
|
+
await fetch(`/api/${entityName}/${id}`, {
|
|
97
|
+
method: 'DELETE',
|
|
98
|
+
signal: requestParams.signal,
|
|
99
|
+
});
|
|
100
|
+
return {result: {id, success: true}};
|
|
101
|
+
},
|
|
102
|
+
itemCreator: async (entityName, item, requestParams) => {
|
|
103
|
+
const response = await fetch(`/api/${entityName}`, {
|
|
104
|
+
method: 'POST',
|
|
105
|
+
body: JSON.stringify(item),
|
|
106
|
+
signal: requestParams.signal,
|
|
107
|
+
});
|
|
108
|
+
return {data: await response.json()};
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
entities: {
|
|
112
|
+
// Define configuration for each entity in your EntityMap
|
|
113
|
+
// At minimum, provide empty objects to register entities with the store
|
|
114
|
+
// You can override defaults or add entity-specific configuration here
|
|
115
|
+
users: {
|
|
116
|
+
// Entity-specific configuration (optional)
|
|
117
|
+
// Overrides defaults for this entity
|
|
118
|
+
},
|
|
119
|
+
posts: {
|
|
120
|
+
// Entity-specific configuration (optional)
|
|
121
|
+
// Overrides defaults for this entity
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
debug: {
|
|
126
|
+
devMode: true,
|
|
127
|
+
logs: true,
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Working with Data
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import {
|
|
136
|
+
ChimeraStore,
|
|
137
|
+
chimeraCreateConjunction,
|
|
138
|
+
chimeraCreateOperator,
|
|
139
|
+
chimeraCreateOrderBy,
|
|
140
|
+
ChimeraOrderNulls
|
|
141
|
+
} from '@hf-chimera/store';
|
|
142
|
+
|
|
143
|
+
// Get a repository for a specific entity
|
|
144
|
+
const userRepo = store.from('users');
|
|
145
|
+
const postRepo = store.from('posts');
|
|
146
|
+
|
|
147
|
+
// Create a new user
|
|
148
|
+
const newUserQuery = userRepo.createItem({
|
|
149
|
+
name: 'John Doe',
|
|
150
|
+
email: 'john@example.com',
|
|
151
|
+
age: 30,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// Listen for creation events
|
|
155
|
+
newUserQuery.on('created', (query) => {
|
|
156
|
+
console.log('User created:', query.data);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Get a specific user
|
|
160
|
+
const userQuery = userRepo.getItem('user-123');
|
|
161
|
+
|
|
162
|
+
// Listen for data updates
|
|
163
|
+
userQuery.on('ready', (query) => {
|
|
164
|
+
console.log('User loaded:', query.data);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Update user data
|
|
168
|
+
userQuery.mutable.name = 'Jane Doe';
|
|
169
|
+
await userQuery.commit();
|
|
170
|
+
|
|
171
|
+
// Get a collection with filtering and sorting
|
|
172
|
+
const activeUsersQuery = userRepo.getCollection({
|
|
173
|
+
filter: chimeraCreateConjunction('and', [
|
|
174
|
+
chimeraCreateOperator('gte', 'age', 18),
|
|
175
|
+
]),
|
|
176
|
+
order: [
|
|
177
|
+
chimeraCreateOrderBy('name', false, ChimeraOrderNulls.Last),
|
|
178
|
+
],
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// Listen for collection updates
|
|
182
|
+
activeUsersQuery.on('updated', (query, items, oldItems) => {
|
|
183
|
+
console.log('Active users updated:', items);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// External updates (e.g., from WebSocket)
|
|
187
|
+
store.updateOne('users', {
|
|
188
|
+
id: 'user-123',
|
|
189
|
+
name: 'Updated Name',
|
|
190
|
+
email: 'updated@example.com',
|
|
191
|
+
age: 31,
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Core Concepts
|
|
196
|
+
|
|
197
|
+
### Store Architecture
|
|
198
|
+
|
|
199
|
+
Chimera Store is built around several key concepts:
|
|
200
|
+
|
|
201
|
+
1. **Store**: The main entry point that manages all entities
|
|
202
|
+
2. **Repository**: Entity-specific data management with query capabilities
|
|
203
|
+
3. **Query**: Represents a specific data request (single item or collection)
|
|
204
|
+
4. **Cache**: Intelligent deduplication and memory management
|
|
205
|
+
5. **Events**: Real-time updates and state synchronization
|
|
206
|
+
|
|
207
|
+
### Query Types
|
|
208
|
+
|
|
209
|
+
- **Item Query**: Manages a single entity instance
|
|
210
|
+
- **Collection Query**: Manages a filtered/sorted collection of entities
|
|
211
|
+
|
|
212
|
+
### Filtering System
|
|
213
|
+
|
|
214
|
+
Chimera Store provides a powerful filtering system with support for:
|
|
215
|
+
|
|
216
|
+
- **Operators**: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `contains`,
|
|
217
|
+
`startsWith`, `endsWith`, `in`, `notIn`
|
|
218
|
+
- **Conjunctions**: `and`, `or` for complex filter combinations
|
|
219
|
+
- **Custom Operators**: Extensible operator system for custom logic
|
|
220
|
+
- **Utility Functions**: Use `chimeraCreateOperator` and
|
|
221
|
+
`chimeraCreateConjunction` to build filters
|
|
222
|
+
|
|
223
|
+
### Ordering System
|
|
224
|
+
|
|
225
|
+
Flexible ordering with support for:
|
|
226
|
+
|
|
227
|
+
- **Multiple Fields**: Sort by multiple properties
|
|
228
|
+
- **Direction**: Ascending/descending order
|
|
229
|
+
- **Null Handling**: Configurable null value positioning using
|
|
230
|
+
`ChimeraOrderNulls.First` or `ChimeraOrderNulls.Last`
|
|
231
|
+
- **Utility Functions**: Use `chimeraCreateOrderBy` to build order descriptors
|
|
232
|
+
|
|
233
|
+
## API Reference
|
|
234
|
+
|
|
235
|
+
### ChimeraStore
|
|
236
|
+
|
|
237
|
+
The main store class that manages all entities and provides cross-entity
|
|
238
|
+
operations.
|
|
239
|
+
|
|
240
|
+
#### Constructor
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
new ChimeraStore<EntityMap, FilterConfig, Config>(config
|
|
244
|
+
:
|
|
245
|
+
Config
|
|
246
|
+
)
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
#### Methods
|
|
250
|
+
|
|
251
|
+
- `from<EntityName>(entityName: EntityName)`: Get repository for specific entity
|
|
252
|
+
- `updateOne<EntityName>(entityName: EntityName, item: EntityMap[EntityName])`:
|
|
253
|
+
Update single item
|
|
254
|
+
-
|
|
255
|
+
|
|
256
|
+
`updateMany<EntityName>(entityName: EntityName, items: Iterable<EntityMap[EntityName]>)`:
|
|
257
|
+
Update multiple items
|
|
258
|
+
|
|
259
|
+
- `deleteOne<EntityName>(entityName: EntityName, id: ChimeraEntityId)`: Delete
|
|
260
|
+
single item
|
|
261
|
+
-
|
|
262
|
+
|
|
263
|
+
`deleteMany<EntityName>(entityName: EntityName, ids: Iterable<ChimeraEntityId>)`:
|
|
264
|
+
Delete multiple items
|
|
265
|
+
|
|
266
|
+
### ChimeraEntityRepository
|
|
267
|
+
|
|
268
|
+
Entity-specific repository with query capabilities.
|
|
269
|
+
|
|
270
|
+
#### Methods
|
|
271
|
+
|
|
272
|
+
- `createItem(item: DeepPartial<Item>, meta?: any)`: Create new item
|
|
273
|
+
- `getItem(id: ChimeraEntityId, meta?: any)`: Get single item
|
|
274
|
+
- `getCollection(params: ChimeraCollectionParams)`: Get filtered/sorted
|
|
275
|
+
collection
|
|
276
|
+
|
|
277
|
+
### ChimeraItemQuery
|
|
278
|
+
|
|
279
|
+
Represents a single item query with full CRUD operations.
|
|
280
|
+
|
|
281
|
+
#### Properties
|
|
282
|
+
|
|
283
|
+
- `data`: Current item data (throws if not ready)
|
|
284
|
+
- `mutable`: Mutable reference for updates
|
|
285
|
+
- `state`: Current query state
|
|
286
|
+
- `ready`: Whether data is available
|
|
287
|
+
- `inProgress`: Whether operation is in progress
|
|
288
|
+
|
|
289
|
+
#### Methods
|
|
290
|
+
|
|
291
|
+
- `refetch(force?: boolean)`: Refetch data
|
|
292
|
+
- `update(item: Item, force?: boolean)`: Update item
|
|
293
|
+
- `mutate(mutator: (draft: Item) => Item, force?: boolean)`: Update using
|
|
294
|
+
mutator function
|
|
295
|
+
- `commit(force?: boolean)`: Commit mutable changes
|
|
296
|
+
- `delete(force?: boolean)`: Delete item
|
|
297
|
+
|
|
298
|
+
#### Events
|
|
299
|
+
|
|
300
|
+
- `initialized`: Query initialized
|
|
301
|
+
- `created`: Item created
|
|
302
|
+
- `ready`: Data ready
|
|
303
|
+
- `updated`: Data updated
|
|
304
|
+
- `selfUpdated`: Self-initiated update
|
|
305
|
+
- `deleted`: Item deleted
|
|
306
|
+
- `selfDeleted`: Self-initiated deletion
|
|
307
|
+
- `error`: Error occurred
|
|
308
|
+
|
|
309
|
+
### ChimeraCollectionQuery
|
|
310
|
+
|
|
311
|
+
Represents a collection query with filtering and sorting.
|
|
312
|
+
|
|
313
|
+
#### Properties
|
|
314
|
+
|
|
315
|
+
- `length`: Number of items
|
|
316
|
+
- `state`: Current query state
|
|
317
|
+
- `ready`: Whether data is available
|
|
318
|
+
- `inProgress`: Whether operation is in progress
|
|
319
|
+
|
|
320
|
+
#### Methods
|
|
321
|
+
|
|
322
|
+
- `refetch(force?: boolean)`: Refetch data
|
|
323
|
+
- `update(item: Item)`: Update single item
|
|
324
|
+
- `batchedUpdate(items: Iterable<Item>)`: Update multiple items
|
|
325
|
+
- `delete(id: ChimeraEntityId)`: Delete single item
|
|
326
|
+
- `batchedDelete(ids: Iterable<ChimeraEntityId>)`: Delete multiple items
|
|
327
|
+
- `create(item: DeepPartial<Item>)`: Create new item
|
|
328
|
+
- `batchedCreate(items: Iterable<DeepPartial<Item>>)`: Create multiple items
|
|
329
|
+
|
|
330
|
+
#### Array-like Methods
|
|
331
|
+
|
|
332
|
+
Collection queries implement the standard Array interface:
|
|
333
|
+
|
|
334
|
+
- `at(index: number)`: Get item at index
|
|
335
|
+
- `find(predicate)`: Find item by predicate
|
|
336
|
+
- `filter(predicate)`: Filter items
|
|
337
|
+
- `map(transform)`: Transform items
|
|
338
|
+
- `forEach(callback)`: Iterate over items
|
|
339
|
+
- `slice(start?, end?)`: Get subset of items
|
|
340
|
+
- And many more...
|
|
341
|
+
|
|
342
|
+
#### Events
|
|
343
|
+
|
|
344
|
+
- `initialized`: Query initialized
|
|
345
|
+
- `ready`: Data ready
|
|
346
|
+
- `updated`: Data updated
|
|
347
|
+
- `selfUpdated`: Self-initiated update
|
|
348
|
+
- `itemAdded`: Item added
|
|
349
|
+
- `itemUpdated`: Item updated
|
|
350
|
+
- `selfItemUpdated`: Self-initiated item update
|
|
351
|
+
- `itemDeleted`: Item deleted
|
|
352
|
+
- `selfItemDeleted`: Self-initiated item deletion
|
|
353
|
+
- `error`: Error occurred
|
|
354
|
+
|
|
355
|
+
## Advanced Usage
|
|
356
|
+
|
|
357
|
+
### Custom Filter Operators
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
const customFilterConfig = {
|
|
361
|
+
...chimeraDefaultFilterConfig,
|
|
362
|
+
operators: {
|
|
363
|
+
...chimeraDefaultFilterConfig.operators,
|
|
364
|
+
// Custom operator for text search
|
|
365
|
+
textSearch: (text: string, searchTerm: string) =>
|
|
366
|
+
text.toLowerCase().includes(searchTerm.toLowerCase()),
|
|
367
|
+
},
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
const store = new ChimeraStore({
|
|
371
|
+
filter: customFilterConfig,
|
|
372
|
+
// ... other config
|
|
373
|
+
});
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Complex Filtering Examples
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
import {
|
|
380
|
+
chimeraCreateConjunction,
|
|
381
|
+
chimeraCreateOperator,
|
|
382
|
+
chimeraCreateOrderBy,
|
|
383
|
+
ChimeraOrderNulls
|
|
384
|
+
} from '@hf-chimera/store';
|
|
385
|
+
|
|
386
|
+
// Simple filter: users with age >= 18
|
|
387
|
+
const adultUsers = userRepo.getCollection({
|
|
388
|
+
filter: chimeraCreateOperator('gte', 'age', 18),
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// Complex filter: active users with specific age range and email domain
|
|
392
|
+
const activeUsers = userRepo.getCollection({
|
|
393
|
+
filter: chimeraCreateConjunction('and', [
|
|
394
|
+
chimeraCreateOperator('gte', 'age', 18),
|
|
395
|
+
chimeraCreateOperator('lte', 'age', 65),
|
|
396
|
+
chimeraCreateOperator('endsWith', 'email', '@company.com'),
|
|
397
|
+
chimeraCreateOperator('eq', 'isActive', true),
|
|
398
|
+
]),
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
// OR filter: users with specific names or email domains
|
|
402
|
+
const specificUsers = userRepo.getCollection({
|
|
403
|
+
filter: chimeraCreateConjunction('or', [
|
|
404
|
+
chimeraCreateOperator('in', 'name', ['John', 'Jane', 'Bob']),
|
|
405
|
+
chimeraCreateOperator('endsWith', 'email', '@gmail.com'),
|
|
406
|
+
]),
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// Nested filters: complex business logic
|
|
410
|
+
const premiumUsers = userRepo.getCollection({
|
|
411
|
+
filter: chimeraCreateConjunction('and', [
|
|
412
|
+
chimeraCreateOperator('gte', 'age', 21),
|
|
413
|
+
chimeraCreateConjunction('or', [
|
|
414
|
+
chimeraCreateOperator('gte', 'subscriptionLevel', 'premium'),
|
|
415
|
+
chimeraCreateOperator('gte', 'totalSpent', 1000),
|
|
416
|
+
]),
|
|
417
|
+
chimeraCreateOperator('neq', 'status', 'suspended'),
|
|
418
|
+
]),
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
// Text search with multiple conditions
|
|
422
|
+
const searchResults = userRepo.getCollection({
|
|
423
|
+
filter: chimeraCreateConjunction('and', [
|
|
424
|
+
chimeraCreateConjunction('or', [
|
|
425
|
+
chimeraCreateOperator('contains', 'name', searchTerm),
|
|
426
|
+
chimeraCreateOperator('contains', 'email', searchTerm),
|
|
427
|
+
]),
|
|
428
|
+
chimeraCreateOperator('eq', 'isActive', true),
|
|
429
|
+
]),
|
|
430
|
+
order: [
|
|
431
|
+
chimeraCreateOrderBy('name', false, ChimeraOrderNulls.Last),
|
|
432
|
+
chimeraCreateOrderBy('createdAt', true, ChimeraOrderNulls.Last), // newest first
|
|
433
|
+
],
|
|
434
|
+
});
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Custom Order Comparators
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
const customOrderConfig = {
|
|
441
|
+
...chimeraDefaultOrderConfig,
|
|
442
|
+
primitiveComparator: (a: unknown, b: unknown, nulls: ChimeraOrderNulls) => {
|
|
443
|
+
// Custom comparison logic
|
|
444
|
+
if (typeof a === 'string' && typeof b === 'string') {
|
|
445
|
+
return a.localeCompare(b, undefined, {numeric: true});
|
|
446
|
+
}
|
|
447
|
+
return chimeraDefaultOrderConfig.primitiveComparator(a, b, nulls);
|
|
448
|
+
},
|
|
449
|
+
};
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### Event Handling
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
// Listen to store-level events
|
|
456
|
+
store.on('itemAdded', (repository, item) => {
|
|
457
|
+
console.log('Item added to', repository, item);
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
// Listen to repository events
|
|
461
|
+
const userRepo = store.from('users');
|
|
462
|
+
userRepo.on('itemUpdated', (repo, item, oldItem) => {
|
|
463
|
+
console.log('User updated:', item, 'was:', oldItem);
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
// Listen to query events
|
|
467
|
+
const userQuery = userRepo.getItem('user-123');
|
|
468
|
+
userQuery.on('updated', (query, item, oldItem) => {
|
|
469
|
+
console.log('Query updated:', item);
|
|
470
|
+
});
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### Optimistic Updates
|
|
474
|
+
|
|
475
|
+
```typescript
|
|
476
|
+
// Optimistic update with rollback
|
|
477
|
+
const userQuery = userRepo.getItem('user-123');
|
|
478
|
+
|
|
479
|
+
// Update optimistically
|
|
480
|
+
userQuery.mutable.name = 'New Name';
|
|
481
|
+
|
|
482
|
+
try {
|
|
483
|
+
await userQuery.commit();
|
|
484
|
+
console.log('Update successful');
|
|
485
|
+
} catch (error) {
|
|
486
|
+
// Rollback on error
|
|
487
|
+
await userQuery.refetch();
|
|
488
|
+
console.log('Update failed, rolled back');
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
## Configuration Options
|
|
493
|
+
|
|
494
|
+
### Query Configuration
|
|
495
|
+
|
|
496
|
+
```typescript
|
|
497
|
+
{
|
|
498
|
+
query: {
|
|
499
|
+
defaults: {
|
|
500
|
+
trustQuery: boolean, // Trust external data providers
|
|
501
|
+
updateDebounceTimeout
|
|
502
|
+
:
|
|
503
|
+
number, // Debounce update operations
|
|
504
|
+
idGetter
|
|
505
|
+
:
|
|
506
|
+
Function, // Default ID getter
|
|
507
|
+
collectionFetcher
|
|
508
|
+
:
|
|
509
|
+
Function, // Default collection fetcher
|
|
510
|
+
itemFetcher
|
|
511
|
+
:
|
|
512
|
+
Function, // Default item fetcher
|
|
513
|
+
itemUpdater
|
|
514
|
+
:
|
|
515
|
+
Function, // Default item updater
|
|
516
|
+
itemDeleter
|
|
517
|
+
:
|
|
518
|
+
Function, // Default item deleter
|
|
519
|
+
itemCreator
|
|
520
|
+
:
|
|
521
|
+
Function, // Default item creator
|
|
522
|
+
// ... batched operations
|
|
523
|
+
}
|
|
524
|
+
,
|
|
525
|
+
entities: {
|
|
526
|
+
[entityName]
|
|
527
|
+
:
|
|
528
|
+
{
|
|
529
|
+
// Entity-specific overrides
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### Filter Configuration
|
|
537
|
+
|
|
538
|
+
```typescript
|
|
539
|
+
{
|
|
540
|
+
filter: {
|
|
541
|
+
conjunctions: {
|
|
542
|
+
and: Function,
|
|
543
|
+
or
|
|
544
|
+
:
|
|
545
|
+
Function,
|
|
546
|
+
}
|
|
547
|
+
,
|
|
548
|
+
operators: {
|
|
549
|
+
eq: Function,
|
|
550
|
+
neq
|
|
551
|
+
:
|
|
552
|
+
Function,
|
|
553
|
+
gt
|
|
554
|
+
:
|
|
555
|
+
Function,
|
|
556
|
+
// ... custom operators
|
|
557
|
+
}
|
|
558
|
+
,
|
|
559
|
+
getKey: Function, // Cache key generator
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
### Order Configuration
|
|
565
|
+
|
|
566
|
+
```typescript
|
|
567
|
+
{
|
|
568
|
+
order: {
|
|
569
|
+
primitiveComparator: Function, // Custom comparator
|
|
570
|
+
getKey
|
|
571
|
+
:
|
|
572
|
+
Function, // Cache key generator
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
### Debug Configuration
|
|
578
|
+
|
|
579
|
+
```typescript
|
|
580
|
+
{
|
|
581
|
+
debug: {
|
|
582
|
+
name: string, // Debug name
|
|
583
|
+
devMode
|
|
584
|
+
:
|
|
585
|
+
boolean, // Development mode
|
|
586
|
+
logs
|
|
587
|
+
:
|
|
588
|
+
boolean, // Enable logging
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
## Performance Considerations
|
|
594
|
+
|
|
595
|
+
### Memory Management
|
|
596
|
+
|
|
597
|
+
- Chimera Store uses weak references for automatic memory cleanup
|
|
598
|
+
- Queries are automatically cached and deduplicated
|
|
599
|
+
- Stale references are cleaned up automatically
|
|
600
|
+
|
|
601
|
+
### Caching Strategy
|
|
602
|
+
|
|
603
|
+
- Collection queries are cached by filter/order combination
|
|
604
|
+
- Item queries are cached by ID
|
|
605
|
+
- Cache keys are generated automatically for optimal performance
|
|
606
|
+
|
|
607
|
+
### Update Optimization
|
|
608
|
+
|
|
609
|
+
- Batch operations for multiple updates
|
|
610
|
+
- Debounced updates to reduce API calls
|
|
611
|
+
- Optimistic updates for better UX
|
|
612
|
+
|
|
613
|
+
## Browser Support
|
|
614
|
+
|
|
615
|
+
- **Modern Browsers**: Full support for ES2021+ features
|
|
616
|
+
- **Node.js**: 14.17.0+ with `--harmony-weak-refs` flag, 16.0.0+ stable
|
|
617
|
+
- **TypeScript**: 4.5+ recommended
|
|
618
|
+
|
|
619
|
+
## Contributing
|
|
620
|
+
|
|
621
|
+
1. Fork the repository
|
|
622
|
+
2. Create a feature branch
|
|
623
|
+
3. Make your changes
|
|
624
|
+
4. Add tests for new functionality
|
|
625
|
+
5. Submit a pull request
|
|
626
|
+
|
|
627
|
+
## License
|
|
628
|
+
|
|
629
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
630
|
+
|
|
631
|
+
## Support
|
|
632
|
+
|
|
633
|
+
- **Issues**: [GitHub Issues](https://github.com/hf-chimera/store/issues)
|
|
634
|
+
- **Documentation**: [GitHub Wiki](https://github.com/hf-chimera/store/wiki)
|
|
635
|
+
- **Discussions
|
|
636
|
+
**: [GitHub Discussions](https://github.com/hf-chimera/store/discussions)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Ct as ChimeraPropertyGetter, at as ChimeraOrderNulls, dt as ChimeraConjunctionType, h as ChimeraStoreEntities, it as ChimeraOrderDescriptor, mt as ChimeraFilterDescriptor, p as AnyChimeraStore, wt as KeysOfType, y as ChimeraStoreOperatorMap } from "./index-kFATKhTP.js";
|
|
2
|
+
|
|
3
|
+
//#region packages/qb/index.d.ts
|
|
4
|
+
type QueryBuilderCreator<Store extends AnyChimeraStore, Entity extends ChimeraStoreEntities<Store>, OperatorsMap extends ChimeraStoreOperatorMap<Store> = ChimeraStoreOperatorMap<Store>> = (q: ChimeraQueryBuilder<Store, Entity, OperatorsMap>) => any;
|
|
5
|
+
declare class ChimeraQueryBuilder<Store extends AnyChimeraStore, Entity extends ChimeraStoreEntities<Store>, OperatorsMap extends ChimeraStoreOperatorMap<Store> = ChimeraStoreOperatorMap<Store>> {
|
|
6
|
+
private orderRules;
|
|
7
|
+
orderBy(key: ChimeraPropertyGetter<Entity> | (keyof Entity & string), desc?: boolean, nulls?: ChimeraOrderNulls): this;
|
|
8
|
+
private filters;
|
|
9
|
+
private rootConjunction;
|
|
10
|
+
private conjunction;
|
|
11
|
+
private buildFilter;
|
|
12
|
+
where<Op extends keyof OperatorsMap & string>(value: ChimeraPropertyGetter<Entity, Parameters<OperatorsMap[Op]>[0]> | (KeysOfType<Entity, Parameters<OperatorsMap[Op]>[0]> & string), op: Op, test: Parameters<OperatorsMap[Op]>[1]): this;
|
|
13
|
+
group(conjunction: ChimeraConjunctionType, builder: QueryBuilderCreator<Store, Entity, OperatorsMap>): this;
|
|
14
|
+
whereNot<Op extends keyof OperatorsMap & string>(value: ChimeraPropertyGetter<Entity, Parameters<OperatorsMap[Op]>[0]> | (KeysOfType<Entity, Parameters<OperatorsMap[Op]>[0]> & string), op: Op, test: Parameters<OperatorsMap[Op]>[1]): this;
|
|
15
|
+
build(): {
|
|
16
|
+
filter: ChimeraFilterDescriptor<OperatorsMap, Entity> | null;
|
|
17
|
+
order: ChimeraOrderDescriptor<Entity>[] | null;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { QueryBuilderCreator as n, ChimeraQueryBuilder as t };
|
|
22
|
+
//# sourceMappingURL=index-CqYNg3Vx.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-CqYNg3Vx.d.ts","names":[],"sources":["../../packages/qb/index.ts"],"sourcesContent":[],"mappings":";;;AAoBY,KAAA,mBAAmB,CAAA,cAChB,eADgB,EAAA,eAEf,oBAFe,CAEM,KAFN,CAAA,EAAA,qBAGT,uBAHS,CAGe,KAHf,CAAA,GAGwB,uBAHxB,CAGgD,KAHhD,CAAA,CAAA,GAAA,CAAA,CAAA,EAIvB,mBAJuB,CAIH,KAJG,EAII,MAJJ,EAIY,YAJZ,CAAA,EAAA,GAAA,GAAA;AAAA,cAMlB,mBANkB,CAAA,cAOhB,eAPgB,EAAA,eAQf,oBARe,CAQM,KARN,CAAA,EAAA,qBAST,uBATS,CASe,KATf,CAAA,GASwB,uBATxB,CASgD,KAThD,CAAA,CAAA,CAAA;UAChB,UAAA;SACsB,CAAA,GAAA,EAY9B,qBAZ8B,CAYR,MAZQ,CAAA,GAAA,CAAA,MAYS,MAZT,GAAA,MAAA,CAAA,EAAA,IAAA,CAAA,EAAA,OAAA,EAAA,KAAA,CAAA,EAc5B,iBAd4B,CAAA,EAAA,IAAA;UAArB,OAAA;UAC8B,eAAA;UAAxB,WAAA;UAAyD,WAAA;OAAxB,CAAA,WAAA,MAgC/B,YAhC+B,GAAA,MAAA,CAAA,CAAA,KAAA,EAkClD,qBAlCkD,CAkC5B,MAlC4B,EAkCpB,UAlCoB,CAkCT,YAlCS,CAkCI,EAlCJ,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,CAmCjD,UAnCiD,CAmCtC,MAnCsC,EAmC9B,UAnC8B,CAmCnB,YAnCmB,CAmCN,EAnCM,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,MAAA,CAAA,EAAA,EAAA,EAoCjD,EApCiD,EAAA,IAAA,EAqC/C,UArC+C,CAqCpC,YArCoC,CAqCvB,EArCuB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAA,IAAA;OAC3B,CAAA,WAAA,EA0CR,sBA1CQ,EAAA,OAAA,EA0CyB,mBA1CzB,CA0C6C,KA1C7C,EA0CoD,MA1CpD,EA0C4D,YA1C5D,CAAA,CAAA,EAAA,IAAA;UAAO,CAAA,WAAA,MAwDR,YAxDQ,GAAA,MAAA,CAAA,CAAA,KAAA,EA0D9B,qBA1D8B,CA0DR,MA1DQ,EA0DA,UA1DA,CA0DW,YA1DX,CA0DwB,EA1DxB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,CA2D7B,UA3D6B,CA2DlB,MA3DkB,EA2DV,UA3DU,CA2DC,YA3DD,CA2Dc,EA3Dd,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,GAAA,MAAA,CAAA,EAAA,EAAA,EA4D7B,EA5D6B,EAAA,IAAA,EA6D3B,UA7D2B,CA6DhB,YA7DgB,CA6DH,EA7DG,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,EAAA,IAAA;OAAQ,CAAA,CAAA,EAAA;IAAnC,MAAA,EAsEE,uBAtEF,CAsE0B,YAtE1B,EAsEwC,MAtExC,CAAA,GAAA,IAAA;IAAmB,KAAA,EAuElB,sBAvEkB,CAuEK,MAvEL,CAAA,EAAA,GAAA,IAAA;EAEd,CAAA"}
|