@ahoo-wang/fetcher-wow 3.16.10 → 3.17.1
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 +83 -62
- package/README.zh-CN.md +70 -51
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +793 -317
- package/dist/index.es.js.map +1 -1
- package/dist/query/condition.d.ts +52 -0
- package/dist/query/condition.d.ts.map +1 -1
- package/dist/query/cursorQuery.d.ts +10 -1
- package/dist/query/cursorQuery.d.ts.map +1 -1
- package/dist/query/event/eventStreamQueryClient.d.ts +21 -21
- package/dist/query/event/eventStreamQueryClient.d.ts.map +1 -1
- package/dist/query/filter.d.ts +204 -0
- package/dist/query/filter.d.ts.map +1 -0
- package/dist/query/index.d.ts +1 -0
- package/dist/query/index.d.ts.map +1 -1
- package/dist/query/locale/en_US.cjs.js.map +1 -1
- package/dist/query/locale/en_US.d.ts +1 -0
- package/dist/query/locale/en_US.d.ts.map +1 -1
- package/dist/query/locale/en_US.es.js.map +1 -1
- package/dist/query/locale/operatorLocale.d.ts +1 -0
- package/dist/query/locale/operatorLocale.d.ts.map +1 -1
- package/dist/query/locale/zh_CN.cjs.js.map +1 -1
- package/dist/query/locale/zh_CN.d.ts +1 -0
- package/dist/query/locale/zh_CN.d.ts.map +1 -1
- package/dist/query/locale/zh_CN.es.js.map +1 -1
- package/dist/query/operator.d.ts +3 -0
- package/dist/query/operator.d.ts.map +1 -1
- package/dist/query/queryApi.d.ts +9 -8
- package/dist/query/queryApi.d.ts.map +1 -1
- package/dist/query/queryable.d.ts +34 -4
- package/dist/query/queryable.d.ts.map +1 -1
- package/dist/query/snapshot/snapshotQueryApi.d.ts +5 -5
- package/dist/query/snapshot/snapshotQueryApi.d.ts.map +1 -1
- package/dist/query/snapshot/snapshotQueryClient.d.ts +40 -42
- package/dist/query/snapshot/snapshotQueryClient.d.ts.map +1 -1
- package/package.json +15 -14
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ working with the Wow CQRS/DDD framework.
|
|
|
23
23
|
updates
|
|
24
24
|
- **🚀 Command Client**: High-level client for sending commands to Wow services with both synchronous and streaming
|
|
25
25
|
responses
|
|
26
|
-
- **🔍 Powerful Query DSL**:
|
|
26
|
+
- **🔍 Powerful Query DSL**: Typed `FilterExpression` builders with comprehensive operator support
|
|
27
27
|
- **🔍 Query Clients**: Specialized clients for querying snapshot and event stream data with comprehensive query
|
|
28
28
|
operations:
|
|
29
29
|
- Counting resources
|
|
@@ -68,6 +68,7 @@ either synchronously or as a stream of events.
|
|
|
68
68
|
import {
|
|
69
69
|
Fetcher,
|
|
70
70
|
FetchExchange,
|
|
71
|
+
HttpMethod,
|
|
71
72
|
RequestInterceptor,
|
|
72
73
|
URL_RESOLVE_INTERCEPTOR_ORDER,
|
|
73
74
|
} from '@ahoo-wang/fetcher';
|
|
@@ -75,8 +76,7 @@ import '@ahoo-wang/fetcher-eventstream';
|
|
|
75
76
|
import {
|
|
76
77
|
CommandClient,
|
|
77
78
|
CommandRequest,
|
|
78
|
-
|
|
79
|
-
CommandHttpHeaders,
|
|
79
|
+
CommandHeaders,
|
|
80
80
|
CommandStage,
|
|
81
81
|
} from '@ahoo-wang/fetcher-wow';
|
|
82
82
|
import { idGenerator } from '@ahoo-wang/fetcher-cosec';
|
|
@@ -126,7 +126,7 @@ type AddCartItemCommand = CommandRequest<AddCartItem>;
|
|
|
126
126
|
const addCartItemCommand: AddCartItemCommand = {
|
|
127
127
|
method: HttpMethod.POST,
|
|
128
128
|
headers: {
|
|
129
|
-
[
|
|
129
|
+
[CommandHeaders.WAIT_STAGE]: CommandStage.SNAPSHOT,
|
|
130
130
|
},
|
|
131
131
|
body: {
|
|
132
132
|
productId: 'productId',
|
|
@@ -159,9 +159,29 @@ for await (const commandResultEvent of commandResultStream) {
|
|
|
159
159
|
|
|
160
160
|
### Query Module
|
|
161
161
|
|
|
162
|
-
####
|
|
162
|
+
#### Filter Expression Builder
|
|
163
|
+
|
|
164
|
+
Wow 8.11+ queries use `FilterExpression`:
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
import { DeletionState, filter } from '@ahoo-wang/fetcher-wow';
|
|
168
|
+
|
|
169
|
+
const expression = filter.and(
|
|
170
|
+
filter.deletion(DeletionState.ACTIVE),
|
|
171
|
+
filter.eq('state.status', 'PAID'),
|
|
172
|
+
filter.elementMatch('state.items', filter.gt('quantity', 0)),
|
|
173
|
+
filter.search('wow', 'state.name'),
|
|
174
|
+
);
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Builders are grouped under `filter`: `matchAll`, `matchNone`, `and`, `or`,
|
|
178
|
+
`nor`, comparisons, string/collection predicates, presence checks,
|
|
179
|
+
`elementMatch`, `search`, deletion scope, and relative-time filters.
|
|
180
|
+
|
|
181
|
+
#### Condition Builder (Deprecated)
|
|
163
182
|
|
|
164
|
-
|
|
183
|
+
The legacy Condition API remains available for compatibility with older Wow
|
|
184
|
+
servers. New code should use `FilterExpression` and `filter.*`.
|
|
165
185
|
|
|
166
186
|
```typescript
|
|
167
187
|
import {
|
|
@@ -246,7 +266,7 @@ const arrayConditions = [
|
|
|
246
266
|
// Date conditions
|
|
247
267
|
const dateConditions = [
|
|
248
268
|
today('createdAt'),
|
|
249
|
-
beforeToday('lastLogin',
|
|
269
|
+
beforeToday('lastLogin', '09:30'),
|
|
250
270
|
tomorrow('scheduledDate'),
|
|
251
271
|
thisWeek('updatedAt'),
|
|
252
272
|
nextWeek('startDate'),
|
|
@@ -282,7 +302,7 @@ const rawCondition = raw({ $text: { $search: 'keywords' } });
|
|
|
282
302
|
| String | `contains`, `startsWith`, `endsWith`, `match` |
|
|
283
303
|
| Collection | `isIn`, `notIn`, `allIn`, `elemMatch` |
|
|
284
304
|
| Null/Boolean | `isNull`, `notNull`, `isTrue`, `isFalse`, `exists` |
|
|
285
|
-
| Date | `today`, `beforeToday(
|
|
305
|
+
| Date | `today`, `beforeToday(time)`, `tomorrow`, `thisWeek`, `nextWeek`, `lastWeek`, `thisMonth`, `lastMonth`, `recentDays(days)`, `earlierDays(days)` |
|
|
286
306
|
| ID | `id`, `ids`, `aggregateId`, `aggregateIds`, `tenantId`, `ownerId` |
|
|
287
307
|
| State | `active`, `all`, `deleted` |
|
|
288
308
|
| Special | `raw` (for advanced database-specific queries) |
|
|
@@ -301,10 +321,10 @@ import {
|
|
|
301
321
|
import '@ahoo-wang/fetcher-eventstream';
|
|
302
322
|
import {
|
|
303
323
|
SnapshotQueryClient,
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
324
|
+
filter,
|
|
325
|
+
FilterListQuery,
|
|
326
|
+
FilterPagedQuery,
|
|
327
|
+
FilterSingleQuery,
|
|
308
328
|
} from '@ahoo-wang/fetcher-wow';
|
|
309
329
|
import { idGenerator } from '@ahoo-wang/fetcher-cosec';
|
|
310
330
|
|
|
@@ -346,11 +366,11 @@ const cartSnapshotQueryClient = new SnapshotQueryClient<CartState>({
|
|
|
346
366
|
});
|
|
347
367
|
|
|
348
368
|
// Count snapshots
|
|
349
|
-
const count = await cartSnapshotQueryClient.count(
|
|
369
|
+
const count = await cartSnapshotQueryClient.count(filter.matchAll());
|
|
350
370
|
|
|
351
371
|
// List snapshots
|
|
352
|
-
const listQuery:
|
|
353
|
-
|
|
372
|
+
const listQuery: FilterListQuery = {
|
|
373
|
+
filter: filter.matchAll(),
|
|
354
374
|
};
|
|
355
375
|
const list = await cartSnapshotQueryClient.list(listQuery);
|
|
356
376
|
|
|
@@ -372,8 +392,8 @@ for await (const event of stateStream) {
|
|
|
372
392
|
}
|
|
373
393
|
|
|
374
394
|
// Paged snapshots
|
|
375
|
-
const pagedQuery:
|
|
376
|
-
|
|
395
|
+
const pagedQuery: FilterPagedQuery = {
|
|
396
|
+
filter: filter.matchAll(),
|
|
377
397
|
};
|
|
378
398
|
const paged = await cartSnapshotQueryClient.paged(pagedQuery);
|
|
379
399
|
|
|
@@ -381,8 +401,8 @@ const paged = await cartSnapshotQueryClient.paged(pagedQuery);
|
|
|
381
401
|
const pagedState = await cartSnapshotQueryClient.pagedState(pagedQuery);
|
|
382
402
|
|
|
383
403
|
// Single snapshot
|
|
384
|
-
const singleQuery:
|
|
385
|
-
|
|
404
|
+
const singleQuery: FilterSingleQuery = {
|
|
405
|
+
filter: filter.matchAll(),
|
|
386
406
|
};
|
|
387
407
|
const single = await cartSnapshotQueryClient.single(singleQuery);
|
|
388
408
|
|
|
@@ -392,20 +412,20 @@ const singleState = await cartSnapshotQueryClient.singleState(singleQuery);
|
|
|
392
412
|
|
|
393
413
|
##### Methods
|
|
394
414
|
|
|
395
|
-
- `count(
|
|
396
|
-
- `list(listQuery:
|
|
415
|
+
- `count(filter: FilterExpression): Promise<number>` - Counts snapshots matching the filter expression.
|
|
416
|
+
- `list(listQuery: FilterListQuery): Promise<Partial<MaterializedSnapshot<S>>[]>` - Retrieves a list of materialized
|
|
397
417
|
snapshots.
|
|
398
|
-
- `listStream(listQuery:
|
|
418
|
+
- `listStream(listQuery: FilterListQuery): Promise<ReadableStream<JsonServerSentEvent<Partial<MaterializedSnapshot<S>>>>>` -
|
|
399
419
|
Retrieves a stream of materialized snapshots as Server-Sent Events.
|
|
400
|
-
- `listState(listQuery:
|
|
401
|
-
- `listStateStream(listQuery:
|
|
420
|
+
- `listState(listQuery: FilterListQuery): Promise<Partial<S>[]>` - Retrieves a list of snapshot states.
|
|
421
|
+
- `listStateStream(listQuery: FilterListQuery): Promise<ReadableStream<JsonServerSentEvent<Partial<S>>>>` - Retrieves a stream
|
|
402
422
|
of snapshot states as Server-Sent Events.
|
|
403
|
-
- `paged(pagedQuery:
|
|
423
|
+
- `paged(pagedQuery: FilterPagedQuery): Promise<PagedList<Partial<MaterializedSnapshot<S>>>>` - Retrieves a paged list of
|
|
404
424
|
materialized snapshots.
|
|
405
|
-
- `pagedState(pagedQuery:
|
|
406
|
-
- `single(singleQuery:
|
|
425
|
+
- `pagedState(pagedQuery: FilterPagedQuery): Promise<PagedList<Partial<S>>>` - Retrieves a paged list of snapshot states.
|
|
426
|
+
- `single(singleQuery: FilterSingleQuery): Promise<Partial<MaterializedSnapshot<S>>>` - Retrieves a single materialized
|
|
407
427
|
snapshot.
|
|
408
|
-
- `singleState(singleQuery:
|
|
428
|
+
- `singleState(singleQuery: FilterSingleQuery): Promise<Partial<S>>` - Retrieves a single snapshot state.
|
|
409
429
|
|
|
410
430
|
#### QueryClientFactory
|
|
411
431
|
|
|
@@ -413,9 +433,9 @@ Factory for creating pre-configured query clients. Useful when you need multiple
|
|
|
413
433
|
|
|
414
434
|
```typescript
|
|
415
435
|
import {
|
|
436
|
+
filter,
|
|
416
437
|
QueryClientFactory,
|
|
417
438
|
ResourceAttributionPathSpec,
|
|
418
|
-
all,
|
|
419
439
|
} from '@ahoo-wang/fetcher-wow';
|
|
420
440
|
import { idGenerator } from '@ahoo-wang/fetcher-cosec';
|
|
421
441
|
|
|
@@ -431,7 +451,7 @@ const factory = new QueryClientFactory({
|
|
|
431
451
|
const snapshotClient = factory.createSnapshotQueryClient({
|
|
432
452
|
aggregateName: 'cart',
|
|
433
453
|
});
|
|
434
|
-
const carts = await snapshotClient.listState({
|
|
454
|
+
const carts = await snapshotClient.listState({ filter: filter.matchAll() });
|
|
435
455
|
|
|
436
456
|
// Create a state aggregate client
|
|
437
457
|
const stateClient = factory.createLoadStateAggregateClient({
|
|
@@ -443,7 +463,7 @@ const cart = await stateClient.load('cart-123');
|
|
|
443
463
|
const eventClient = factory.createEventStreamQueryClient({
|
|
444
464
|
aggregateName: 'cart',
|
|
445
465
|
});
|
|
446
|
-
const events = await eventClient.list({
|
|
466
|
+
const events = await eventClient.list({ filter: filter.matchAll() });
|
|
447
467
|
```
|
|
448
468
|
|
|
449
469
|
**Methods:**
|
|
@@ -467,9 +487,9 @@ import {
|
|
|
467
487
|
import '@ahoo-wang/fetcher-eventstream';
|
|
468
488
|
import {
|
|
469
489
|
EventStreamQueryClient,
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
490
|
+
filter,
|
|
491
|
+
FilterListQuery,
|
|
492
|
+
FilterPagedQuery,
|
|
473
493
|
} from '@ahoo-wang/fetcher-wow';
|
|
474
494
|
import { idGenerator } from '@ahoo-wang/fetcher-cosec';
|
|
475
495
|
|
|
@@ -502,11 +522,11 @@ const cartEventStreamQueryClient = new EventStreamQueryClient({
|
|
|
502
522
|
});
|
|
503
523
|
|
|
504
524
|
// Count event streams
|
|
505
|
-
const count = await cartEventStreamQueryClient.count(
|
|
525
|
+
const count = await cartEventStreamQueryClient.count(filter.matchAll());
|
|
506
526
|
|
|
507
527
|
// List event streams
|
|
508
|
-
const listQuery:
|
|
509
|
-
|
|
528
|
+
const listQuery: FilterListQuery = {
|
|
529
|
+
filter: filter.matchAll(),
|
|
510
530
|
};
|
|
511
531
|
const list = await cartEventStreamQueryClient.list(listQuery);
|
|
512
532
|
|
|
@@ -518,20 +538,19 @@ for await (const event of listStream) {
|
|
|
518
538
|
}
|
|
519
539
|
|
|
520
540
|
// Paged event streams
|
|
521
|
-
const pagedQuery:
|
|
522
|
-
|
|
541
|
+
const pagedQuery: FilterPagedQuery = {
|
|
542
|
+
filter: filter.matchAll(),
|
|
523
543
|
};
|
|
524
544
|
const paged = await cartEventStreamQueryClient.paged(pagedQuery);
|
|
525
545
|
```
|
|
526
546
|
|
|
527
547
|
##### Methods
|
|
528
548
|
|
|
529
|
-
- `count(
|
|
530
|
-
|
|
531
|
-
- `
|
|
532
|
-
- `listStream(listQuery: ListQuery): Promise<ReadableStream<JsonServerSentEvent<Partial<DomainEventStream>>>>` -
|
|
549
|
+
- `count(filter: FilterExpression): Promise<number>` - Counts domain event streams matching the filter expression.
|
|
550
|
+
- `list(listQuery: FilterListQuery): Promise<Partial<DomainEventStream>[]>` - Retrieves a list of domain event streams.
|
|
551
|
+
- `listStream(listQuery: FilterListQuery): Promise<ReadableStream<JsonServerSentEvent<Partial<DomainEventStream>>>>` -
|
|
533
552
|
Retrieves a stream of domain event streams as Server-Sent Events.
|
|
534
|
-
- `paged(pagedQuery:
|
|
553
|
+
- `paged(pagedQuery: FilterPagedQuery): Promise<PagedList<Partial<DomainEventStream>>>` - Retrieves a paged list of domain
|
|
535
554
|
event streams.
|
|
536
555
|
|
|
537
556
|
## 🚀 Advanced Usage Examples
|
|
@@ -673,8 +692,9 @@ Create complex queries with reactive real-time updates:
|
|
|
673
692
|
|
|
674
693
|
```typescript
|
|
675
694
|
import {
|
|
676
|
-
SnapshotQueryClient,
|
|
677
695
|
EventStreamQueryClient,
|
|
696
|
+
filter,
|
|
697
|
+
SnapshotQueryClient,
|
|
678
698
|
} from '@ahoo-wang/fetcher-wow';
|
|
679
699
|
|
|
680
700
|
// Advanced query manager with reactive updates
|
|
@@ -725,17 +745,16 @@ class ReactiveQueryManager {
|
|
|
725
745
|
async getUserDashboardStats(userId: string) {
|
|
726
746
|
const [userProfile, recentActivity, stats] = await Promise.all([
|
|
727
747
|
this.snapshotClient.single({
|
|
728
|
-
|
|
729
|
-
projection: { name: 1, email: 1, createdAt: 1 },
|
|
748
|
+
filter: filter.eq('aggregateId', userId),
|
|
730
749
|
}),
|
|
731
750
|
this.snapshotClient.list({
|
|
732
|
-
|
|
733
|
-
|
|
751
|
+
filter: filter.and(
|
|
752
|
+
filter.eq('state.userId', userId),
|
|
753
|
+
filter.eq('state.type', 'activity'),
|
|
754
|
+
),
|
|
734
755
|
limit: 10,
|
|
735
756
|
}),
|
|
736
|
-
this.snapshotClient.count(
|
|
737
|
-
condition: { userId },
|
|
738
|
-
}),
|
|
757
|
+
this.snapshotClient.count(filter.eq('state.userId', userId)),
|
|
739
758
|
]);
|
|
740
759
|
|
|
741
760
|
return {
|
|
@@ -758,8 +777,10 @@ console.log('Dashboard:', dashboard);
|
|
|
758
777
|
queryManager.subscribeToQuery(
|
|
759
778
|
'user-activity',
|
|
760
779
|
{
|
|
761
|
-
|
|
762
|
-
|
|
780
|
+
filter: filter.and(
|
|
781
|
+
filter.eq('state.userId', 'user-123'),
|
|
782
|
+
filter.eq('state.type', 'activity'),
|
|
783
|
+
),
|
|
763
784
|
},
|
|
764
785
|
update => {
|
|
765
786
|
console.log('New activity:', update);
|
|
@@ -774,6 +795,7 @@ queryManager.subscribeToQuery(
|
|
|
774
795
|
import {
|
|
775
796
|
Fetcher,
|
|
776
797
|
FetchExchange,
|
|
798
|
+
HttpMethod,
|
|
777
799
|
RequestInterceptor,
|
|
778
800
|
URL_RESOLVE_INTERCEPTOR_ORDER,
|
|
779
801
|
} from '@ahoo-wang/fetcher';
|
|
@@ -781,12 +803,11 @@ import '@ahoo-wang/fetcher-eventstream';
|
|
|
781
803
|
import {
|
|
782
804
|
CommandClient,
|
|
783
805
|
CommandRequest,
|
|
784
|
-
|
|
806
|
+
CommandHeaders,
|
|
785
807
|
CommandStage,
|
|
786
|
-
HttpMethod,
|
|
787
808
|
SnapshotQueryClient,
|
|
788
|
-
|
|
789
|
-
|
|
809
|
+
filter,
|
|
810
|
+
FilterListQuery,
|
|
790
811
|
} from '@ahoo-wang/fetcher-wow';
|
|
791
812
|
import { idGenerator } from '@ahoo-wang/fetcher-cosec';
|
|
792
813
|
|
|
@@ -850,7 +871,7 @@ type AddCartItemCommand = CommandRequest<AddCartItem>;
|
|
|
850
871
|
const addItemCommand: AddCartItemCommand = {
|
|
851
872
|
method: HttpMethod.POST,
|
|
852
873
|
headers: {
|
|
853
|
-
[
|
|
874
|
+
[CommandHeaders.WAIT_STAGE]: CommandStage.SNAPSHOT,
|
|
854
875
|
},
|
|
855
876
|
body: {
|
|
856
877
|
productId: 'product-123',
|
|
@@ -865,8 +886,8 @@ const commandResult = await cartCommandClient.send(
|
|
|
865
886
|
console.log('Command executed:', commandResult);
|
|
866
887
|
|
|
867
888
|
// 2. Query the updated cart
|
|
868
|
-
const listQuery:
|
|
869
|
-
|
|
889
|
+
const listQuery: FilterListQuery = {
|
|
890
|
+
filter: filter.matchAll(),
|
|
870
891
|
};
|
|
871
892
|
const carts = await cartSnapshotQueryClient.list(listQuery);
|
|
872
893
|
|
|
@@ -895,7 +916,7 @@ pnpm test --coverage
|
|
|
895
916
|
## 🤝 Contributing
|
|
896
917
|
|
|
897
918
|
Contributions are welcome! Please see
|
|
898
|
-
the [contributing guide](https://github.com/Ahoo-Wang/fetcher/blob/main/
|
|
919
|
+
the [contributing guide](https://github.com/Ahoo-Wang/fetcher/blob/main/wiki/guide/contributing.md) for more details.
|
|
899
920
|
|
|
900
921
|
## 📄 License
|
|
901
922
|
|
package/README.zh-CN.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
- **📦 完整的 TypeScript 支持**:为所有 Wow 框架实体提供完整的类型定义,包括命令、事件和查询
|
|
17
17
|
- **🚀 命令客户端**:用于向 Wow 服务发送命令的高级客户端,支持同步和流式响应
|
|
18
|
-
- **🔍 强大的查询 DSL
|
|
18
|
+
- **🔍 强大的查询 DSL**:类型安全的 `FilterExpression` 构建器,支持完整的查询操作符
|
|
19
19
|
- **📡 实时事件流**:内置对服务器发送事件的支持,用于接收实时命令结果和数据更新
|
|
20
20
|
- **🔄 CQRS 模式实现**:对命令查询责任分离架构模式的一流支持
|
|
21
21
|
- **🧱 DDD 基础构件**:基本的领域驱动设计构建块,包括聚合、事件和值对象
|
|
@@ -61,6 +61,7 @@ import { CommandResult, CommandStage } from '@ahoo-wang/fetcher-wow';
|
|
|
61
61
|
import {
|
|
62
62
|
Fetcher,
|
|
63
63
|
FetchExchange,
|
|
64
|
+
HttpMethod,
|
|
64
65
|
RequestInterceptor,
|
|
65
66
|
URL_RESOLVE_INTERCEPTOR_ORDER,
|
|
66
67
|
} from '@ahoo-wang/fetcher';
|
|
@@ -68,8 +69,7 @@ import '@ahoo-wang/fetcher-eventstream';
|
|
|
68
69
|
import {
|
|
69
70
|
CommandClient,
|
|
70
71
|
CommandRequest,
|
|
71
|
-
|
|
72
|
-
CommandHttpHeaders,
|
|
72
|
+
CommandHeaders,
|
|
73
73
|
CommandStage,
|
|
74
74
|
} from '@ahoo-wang/fetcher-wow';
|
|
75
75
|
import { idGenerator } from '@ahoo-wang/fetcher-cosec';
|
|
@@ -119,7 +119,7 @@ type AddCartItemCommand = CommandRequest<AddCartItem>;
|
|
|
119
119
|
const addCartItemCommand: AddCartItemCommand = {
|
|
120
120
|
method: HttpMethod.POST,
|
|
121
121
|
headers: {
|
|
122
|
-
[
|
|
122
|
+
[CommandHeaders.WAIT_STAGE]: CommandStage.SNAPSHOT,
|
|
123
123
|
},
|
|
124
124
|
body: {
|
|
125
125
|
productId: 'productId',
|
|
@@ -151,9 +151,28 @@ for await (const commandResultEvent of commandResultStream) {
|
|
|
151
151
|
|
|
152
152
|
### 查询模块
|
|
153
153
|
|
|
154
|
-
####
|
|
154
|
+
#### FilterExpression 构建器
|
|
155
|
+
|
|
156
|
+
Wow 8.11+ 查询使用 `FilterExpression`:
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import { DeletionState, filter } from '@ahoo-wang/fetcher-wow';
|
|
160
|
+
|
|
161
|
+
const expression = filter.and(
|
|
162
|
+
filter.deletion(DeletionState.ACTIVE),
|
|
163
|
+
filter.eq('state.status', 'PAID'),
|
|
164
|
+
filter.elementMatch('state.items', filter.gt('quantity', 0)),
|
|
165
|
+
filter.search('wow', 'state.name'),
|
|
166
|
+
);
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
所有构建器集中在 `filter`:`matchAll`、`matchNone`、`and`、`or`、`nor`、
|
|
170
|
+
比较、字符串/集合谓词、存在性检查、`elementMatch`、`search`、删除范围和相对时间过滤器。
|
|
171
|
+
|
|
172
|
+
#### 条件构建器(已弃用)
|
|
155
173
|
|
|
156
|
-
|
|
174
|
+
旧 Condition API 仅为兼容旧版 Wow 服务保留。新代码应使用
|
|
175
|
+
`FilterExpression` 和 `filter.*`。
|
|
157
176
|
|
|
158
177
|
```typescript
|
|
159
178
|
import {
|
|
@@ -238,7 +257,7 @@ const arrayConditions = [
|
|
|
238
257
|
// 日期条件
|
|
239
258
|
const dateConditions = [
|
|
240
259
|
today('createdAt'),
|
|
241
|
-
beforeToday('lastLogin',
|
|
260
|
+
beforeToday('lastLogin', '09:30'),
|
|
242
261
|
tomorrow('scheduledDate'),
|
|
243
262
|
thisWeek('updatedAt'),
|
|
244
263
|
nextWeek('startDate'),
|
|
@@ -274,7 +293,7 @@ const rawCondition = raw({ $text: { $search: 'keywords' } });
|
|
|
274
293
|
| 字符串 | `contains`, `startsWith`, `endsWith`, `match` |
|
|
275
294
|
| 集合 | `isIn`, `notIn`, `allIn`, `elemMatch` |
|
|
276
295
|
| 空值/布尔 | `isNull`, `notNull`, `isTrue`, `isFalse`, `exists` |
|
|
277
|
-
| 日期 | `today`, `beforeToday(
|
|
296
|
+
| 日期 | `today`, `beforeToday(time)`, `tomorrow`, `thisWeek`, `nextWeek`, `lastWeek`, `thisMonth`, `lastMonth`, `recentDays(days)`, `earlierDays(days)` |
|
|
278
297
|
| ID | `id`, `ids`, `aggregateId`, `aggregateIds`, `tenantId`, `ownerId` |
|
|
279
298
|
| 状态 | `active`, `all`, `deleted` |
|
|
280
299
|
| 特殊 | `raw`(用于高级数据库特定查询) |
|
|
@@ -293,10 +312,10 @@ import {
|
|
|
293
312
|
import '@ahoo-wang/fetcher-eventstream';
|
|
294
313
|
import {
|
|
295
314
|
SnapshotQueryClient,
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
315
|
+
filter,
|
|
316
|
+
FilterListQuery,
|
|
317
|
+
FilterPagedQuery,
|
|
318
|
+
FilterSingleQuery,
|
|
300
319
|
} from '@ahoo-wang/fetcher-wow';
|
|
301
320
|
import { idGenerator } from '@ahoo-wang/fetcher-cosec';
|
|
302
321
|
|
|
@@ -338,11 +357,11 @@ const cartSnapshotQueryClient = new SnapshotQueryClient<CartState>({
|
|
|
338
357
|
});
|
|
339
358
|
|
|
340
359
|
// 统计快照数量
|
|
341
|
-
const count = await cartSnapshotQueryClient.count(
|
|
360
|
+
const count = await cartSnapshotQueryClient.count(filter.matchAll());
|
|
342
361
|
|
|
343
362
|
// 列出快照
|
|
344
|
-
const listQuery:
|
|
345
|
-
|
|
363
|
+
const listQuery: FilterListQuery = {
|
|
364
|
+
filter: filter.matchAll(),
|
|
346
365
|
};
|
|
347
366
|
const list = await cartSnapshotQueryClient.list(listQuery);
|
|
348
367
|
|
|
@@ -364,8 +383,8 @@ for await (const event of stateStream) {
|
|
|
364
383
|
}
|
|
365
384
|
|
|
366
385
|
// 分页查询快照
|
|
367
|
-
const pagedQuery:
|
|
368
|
-
|
|
386
|
+
const pagedQuery: FilterPagedQuery = {
|
|
387
|
+
filter: filter.matchAll(),
|
|
369
388
|
};
|
|
370
389
|
const paged = await cartSnapshotQueryClient.paged(pagedQuery);
|
|
371
390
|
|
|
@@ -373,8 +392,8 @@ const paged = await cartSnapshotQueryClient.paged(pagedQuery);
|
|
|
373
392
|
const pagedState = await cartSnapshotQueryClient.pagedState(pagedQuery);
|
|
374
393
|
|
|
375
394
|
// 查询单个快照
|
|
376
|
-
const singleQuery:
|
|
377
|
-
|
|
395
|
+
const singleQuery: FilterSingleQuery = {
|
|
396
|
+
filter: filter.matchAll(),
|
|
378
397
|
};
|
|
379
398
|
const single = await cartSnapshotQueryClient.single(singleQuery);
|
|
380
399
|
|
|
@@ -384,17 +403,17 @@ const singleState = await cartSnapshotQueryClient.singleState(singleQuery);
|
|
|
384
403
|
|
|
385
404
|
##### 方法
|
|
386
405
|
|
|
387
|
-
- `count(
|
|
388
|
-
- `list(listQuery:
|
|
389
|
-
- `listStream(listQuery:
|
|
406
|
+
- `count(filter: FilterExpression): Promise<number>` - 统计匹配过滤表达式的快照数量。
|
|
407
|
+
- `list(listQuery: FilterListQuery): Promise<Partial<MaterializedSnapshot<S>>[]>` - 检索物化快照列表。
|
|
408
|
+
- `listStream(listQuery: FilterListQuery): Promise<ReadableStream<JsonServerSentEvent<Partial<MaterializedSnapshot<S>>>>>` -
|
|
390
409
|
以服务器发送事件的形式检索物化快照流。
|
|
391
|
-
- `listState(listQuery:
|
|
392
|
-
- `listStateStream(listQuery:
|
|
410
|
+
- `listState(listQuery: FilterListQuery): Promise<Partial<S>[]>` - 检索快照状态列表。
|
|
411
|
+
- `listStateStream(listQuery: FilterListQuery): Promise<ReadableStream<JsonServerSentEvent<Partial<S>>>>` -
|
|
393
412
|
以服务器发送事件的形式检索快照状态流。
|
|
394
|
-
- `paged(pagedQuery:
|
|
395
|
-
- `pagedState(pagedQuery:
|
|
396
|
-
- `single(singleQuery:
|
|
397
|
-
- `singleState(singleQuery:
|
|
413
|
+
- `paged(pagedQuery: FilterPagedQuery): Promise<PagedList<Partial<MaterializedSnapshot<S>>>>` - 检索物化快照的分页列表。
|
|
414
|
+
- `pagedState(pagedQuery: FilterPagedQuery): Promise<PagedList<Partial<S>>>` - 检索快照状态的分页列表。
|
|
415
|
+
- `single(singleQuery: FilterSingleQuery): Promise<Partial<MaterializedSnapshot<S>>>` - 检索单个物化快照。
|
|
416
|
+
- `singleState(singleQuery: FilterSingleQuery): Promise<Partial<S>>` - 检索单个快照状态。
|
|
398
417
|
|
|
399
418
|
#### QueryClientFactory
|
|
400
419
|
|
|
@@ -402,9 +421,9 @@ const singleState = await cartSnapshotQueryClient.singleState(singleQuery);
|
|
|
402
421
|
|
|
403
422
|
```typescript
|
|
404
423
|
import {
|
|
424
|
+
filter,
|
|
405
425
|
QueryClientFactory,
|
|
406
426
|
ResourceAttributionPathSpec,
|
|
407
|
-
all,
|
|
408
427
|
} from '@ahoo-wang/fetcher-wow';
|
|
409
428
|
import { idGenerator } from '@ahoo-wang/fetcher-cosec';
|
|
410
429
|
|
|
@@ -420,7 +439,7 @@ const factory = new QueryClientFactory({
|
|
|
420
439
|
const snapshotClient = factory.createSnapshotQueryClient({
|
|
421
440
|
aggregateName: 'cart',
|
|
422
441
|
});
|
|
423
|
-
const carts = await snapshotClient.listState({
|
|
442
|
+
const carts = await snapshotClient.listState({ filter: filter.matchAll() });
|
|
424
443
|
|
|
425
444
|
// 创建状态聚合客户端
|
|
426
445
|
const stateClient = factory.createLoadStateAggregateClient({
|
|
@@ -432,7 +451,7 @@ const cart = await stateClient.load('cart-123');
|
|
|
432
451
|
const eventClient = factory.createEventStreamQueryClient({
|
|
433
452
|
aggregateName: 'cart',
|
|
434
453
|
});
|
|
435
|
-
const events = await eventClient.list({
|
|
454
|
+
const events = await eventClient.list({ filter: filter.matchAll() });
|
|
436
455
|
```
|
|
437
456
|
|
|
438
457
|
**方法:**
|
|
@@ -456,9 +475,9 @@ import {
|
|
|
456
475
|
import '@ahoo-wang/fetcher-eventstream';
|
|
457
476
|
import {
|
|
458
477
|
EventStreamQueryClient,
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
478
|
+
filter,
|
|
479
|
+
FilterListQuery,
|
|
480
|
+
FilterPagedQuery,
|
|
462
481
|
} from '@ahoo-wang/fetcher-wow';
|
|
463
482
|
import { idGenerator } from '@ahoo-wang/fetcher-cosec';
|
|
464
483
|
|
|
@@ -491,11 +510,11 @@ const cartEventStreamQueryClient = new EventStreamQueryClient({
|
|
|
491
510
|
});
|
|
492
511
|
|
|
493
512
|
// 统计事件流数量
|
|
494
|
-
const count = await cartEventStreamQueryClient.count(
|
|
513
|
+
const count = await cartEventStreamQueryClient.count(filter.matchAll());
|
|
495
514
|
|
|
496
515
|
// 列出事件流
|
|
497
|
-
const listQuery:
|
|
498
|
-
|
|
516
|
+
const listQuery: FilterListQuery = {
|
|
517
|
+
filter: filter.matchAll(),
|
|
499
518
|
};
|
|
500
519
|
const list = await cartEventStreamQueryClient.list(listQuery);
|
|
501
520
|
|
|
@@ -507,19 +526,19 @@ for await (const event of listStream) {
|
|
|
507
526
|
}
|
|
508
527
|
|
|
509
528
|
// 分页查询事件流
|
|
510
|
-
const pagedQuery:
|
|
511
|
-
|
|
529
|
+
const pagedQuery: FilterPagedQuery = {
|
|
530
|
+
filter: filter.matchAll(),
|
|
512
531
|
};
|
|
513
532
|
const paged = await cartEventStreamQueryClient.paged(pagedQuery);
|
|
514
533
|
```
|
|
515
534
|
|
|
516
535
|
##### 方法
|
|
517
536
|
|
|
518
|
-
- `count(
|
|
519
|
-
- `list(listQuery:
|
|
520
|
-
- `listStream(listQuery:
|
|
537
|
+
- `count(filter: FilterExpression): Promise<number>` - 统计匹配过滤表达式的领域事件流数量。
|
|
538
|
+
- `list(listQuery: FilterListQuery): Promise<Partial<DomainEventStream>[]>` - 检索领域事件流列表。
|
|
539
|
+
- `listStream(listQuery: FilterListQuery): Promise<ReadableStream<JsonServerSentEvent<Partial<DomainEventStream>>>>` -
|
|
521
540
|
以服务器发送事件的形式检索领域事件流。
|
|
522
|
-
- `paged(pagedQuery:
|
|
541
|
+
- `paged(pagedQuery: FilterPagedQuery): Promise<PagedList<Partial<DomainEventStream>>>` - 检索领域事件流的分页列表。
|
|
523
542
|
|
|
524
543
|
## 🛠️ 高级用法
|
|
525
544
|
|
|
@@ -529,6 +548,7 @@ const paged = await cartEventStreamQueryClient.paged(pagedQuery);
|
|
|
529
548
|
import {
|
|
530
549
|
Fetcher,
|
|
531
550
|
FetchExchange,
|
|
551
|
+
HttpMethod,
|
|
532
552
|
RequestInterceptor,
|
|
533
553
|
URL_RESOLVE_INTERCEPTOR_ORDER,
|
|
534
554
|
} from '@ahoo-wang/fetcher';
|
|
@@ -536,12 +556,11 @@ import '@ahoo-wang/fetcher-eventstream';
|
|
|
536
556
|
import {
|
|
537
557
|
CommandClient,
|
|
538
558
|
CommandRequest,
|
|
539
|
-
|
|
559
|
+
CommandHeaders,
|
|
540
560
|
CommandStage,
|
|
541
|
-
HttpMethod,
|
|
542
561
|
SnapshotQueryClient,
|
|
543
|
-
|
|
544
|
-
|
|
562
|
+
filter,
|
|
563
|
+
FilterListQuery,
|
|
545
564
|
} from '@ahoo-wang/fetcher-wow';
|
|
546
565
|
import { idGenerator } from '@ahoo-wang/fetcher-cosec';
|
|
547
566
|
|
|
@@ -605,7 +624,7 @@ type AddCartItemCommand = CommandRequest<AddCartItem>;
|
|
|
605
624
|
const addItemCommand: AddCartItemCommand = {
|
|
606
625
|
method: HttpMethod.POST,
|
|
607
626
|
headers: {
|
|
608
|
-
[
|
|
627
|
+
[CommandHeaders.WAIT_STAGE]: CommandStage.SNAPSHOT,
|
|
609
628
|
},
|
|
610
629
|
body: {
|
|
611
630
|
productId: 'product-123',
|
|
@@ -620,8 +639,8 @@ const commandResult = await cartCommandClient.send(
|
|
|
620
639
|
console.log('命令执行完成:', commandResult);
|
|
621
640
|
|
|
622
641
|
// 2. 查询更新后的购物车
|
|
623
|
-
const listQuery:
|
|
624
|
-
|
|
642
|
+
const listQuery: FilterListQuery = {
|
|
643
|
+
filter: filter.matchAll(),
|
|
625
644
|
};
|
|
626
645
|
const carts = await cartSnapshotQueryClient.list(listQuery);
|
|
627
646
|
|
|
@@ -650,7 +669,7 @@ pnpm test --coverage
|
|
|
650
669
|
## 🤝 贡献
|
|
651
670
|
|
|
652
671
|
欢迎贡献!请查看
|
|
653
|
-
[贡献指南](https://github.com/Ahoo-Wang/fetcher/blob/main/
|
|
672
|
+
[贡献指南](https://github.com/Ahoo-Wang/fetcher/blob/main/wiki/guide/contributing.md) 获取更多详情。
|
|
654
673
|
|
|
655
674
|
## 📄 许可证
|
|
656
675
|
|