@ahoo-wang/fetcher-wow 1.2.1 → 1.2.2

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 CHANGED
@@ -24,7 +24,12 @@ working with the Wow CQRS/DDD framework.
24
24
  responses
25
25
  - **🔍 Powerful Query DSL**: Rich query condition builder with comprehensive operator support for complex querying
26
26
  - **🔍 Query Clients**: Specialized clients for querying snapshot and event stream data with comprehensive query
27
- operations
27
+ operations:
28
+ - Counting resources
29
+ - Listing resources
30
+ - Streaming resources as Server-Sent Events
31
+ - Paging resources
32
+ - Retrieving single resources
28
33
 
29
34
  ## 🚀 Quick Start
30
35
 
@@ -59,46 +64,65 @@ HTTP client for sending commands to the Wow framework. The client provides metho
59
64
  either synchronously or as a stream of events.
60
65
 
61
66
  ```typescript
62
- import { Fetcher, URL_RESOLVE_INTERCEPTOR_ORDER } from '@ahoo-wang/fetcher';
67
+ import { Fetcher, FetchExchange, RequestInterceptor, URL_RESOLVE_INTERCEPTOR_ORDER } from '@ahoo-wang/fetcher';
63
68
  import '@ahoo-wang/fetcher-eventstream';
64
69
  import {
65
70
  CommandClient,
66
71
  CommandRequest,
67
72
  HttpMethod,
68
73
  CommandHttpHeaders,
69
- CommandStage,
74
+ CommandStage
70
75
  } from '@ahoo-wang/fetcher-wow';
71
76
  import { idGenerator } from '@ahoo-wang/fetcher-cosec';
72
77
 
73
- // Create a fetcher instance
74
- const wowFetcher = new Fetcher({
78
+ // Create a fetcher instance with base configuration
79
+ const exampleFetcher = new Fetcher({
75
80
  baseURL: 'http://localhost:8080/',
76
81
  });
77
82
 
78
- // Add interceptor to handle URL parameters
79
- const ownerId = idGenerator.generateId();
80
- wowFetcher.interceptors.request.use({
81
- name: 'AppendOwnerId',
82
- order: URL_RESOLVE_INTERCEPTOR_ORDER - 1,
83
- intercept(exchange) {
83
+ // Define current user ID
84
+ const currentUserId = idGenerator.generateId();
85
+
86
+ // Create an interceptor to handle URL parameters
87
+ class AppendOwnerId implements RequestInterceptor {
88
+ readonly name: string = 'AppendOwnerId';
89
+ readonly order: number = URL_RESOLVE_INTERCEPTOR_ORDER - 1;
90
+
91
+ intercept(exchange: FetchExchange) {
84
92
  exchange.request.urlParams = {
85
93
  path: {
86
94
  ...exchange.request.urlParams?.path,
87
- ownerId,
95
+ ownerId: currentUserId,
88
96
  },
89
97
  query: exchange.request.urlParams?.query,
90
98
  };
91
- },
92
- });
99
+ }
100
+ }
101
+
102
+ // Register the interceptor
103
+ exampleFetcher.interceptors.request.use(new AppendOwnerId());
93
104
 
94
105
  // Create the command client
95
- const commandClient = new CommandClient({
96
- fetcher: wowFetcher,
106
+ const cartCommandClient = new CommandClient({
107
+ fetcher: exampleFetcher,
97
108
  basePath: 'owner/{ownerId}/cart',
98
109
  });
99
110
 
100
- // Define a command request
101
- const command: CommandRequest = {
111
+ // Define command endpoints
112
+ class CartCommandEndpoints {
113
+ static readonly addCartItem = 'add_cart_item';
114
+ }
115
+
116
+ // Define command interfaces
117
+ interface AddCartItem {
118
+ productId: string;
119
+ quantity: number;
120
+ }
121
+
122
+ type AddCartItemCommand = CommandRequest<AddCartItem>
123
+
124
+ // Create a command request
125
+ const addCartItemCommand: AddCartItemCommand = {
102
126
  method: HttpMethod.POST,
103
127
  headers: {
104
128
  [CommandHttpHeaders.WAIT_STAGE]: CommandStage.SNAPSHOT,
@@ -110,12 +134,15 @@ const command: CommandRequest = {
110
134
  };
111
135
 
112
136
  // Send command and wait for result
113
- const commandResult = await commandClient.send('add_cart_item', command);
137
+ const commandResult = await cartCommandClient.send(
138
+ CartCommandEndpoints.addCartItem,
139
+ addCartItemCommand,
140
+ );
114
141
 
115
142
  // Send command and receive results as a stream of events
116
- const commandResultStream = await commandClient.sendAndWaitStream(
117
- 'add_cart_item',
118
- command,
143
+ const commandResultStream = await cartCommandClient.sendAndWaitStream(
144
+ CartCommandEndpoints.addCartItem,
145
+ addCartItemCommand,
119
146
  );
120
147
  for await (const commandResultEvent of commandResultStream) {
121
148
  console.log('Received command result:', commandResultEvent.data);
@@ -181,10 +208,10 @@ const dateConditions = [
181
208
 
182
209
  #### SnapshotQueryClient
183
210
 
184
- Client for querying materialized snapshots:
211
+ Client for querying materialized snapshots with comprehensive query operations:
185
212
 
186
213
  ```typescript
187
- import { Fetcher, URL_RESOLVE_INTERCEPTOR_ORDER } from '@ahoo-wang/fetcher';
214
+ import { Fetcher, FetchExchange, RequestInterceptor, URL_RESOLVE_INTERCEPTOR_ORDER } from '@ahoo-wang/fetcher';
188
215
  import '@ahoo-wang/fetcher-eventstream';
189
216
  import {
190
217
  SnapshotQueryClient,
@@ -200,59 +227,64 @@ interface CartItem {
200
227
  quantity: number;
201
228
  }
202
229
 
203
- interface CartState {
204
- id: string;
230
+ interface CartState extends Identifier {
205
231
  items: CartItem[];
206
232
  }
207
233
 
208
- // Create a fetcher instance
209
- const wowFetcher = new Fetcher({
234
+ // Create a fetcher instance with base configuration
235
+ const exampleFetcher = new Fetcher({
210
236
  baseURL: 'http://localhost:8080/',
211
237
  });
212
238
 
213
- // Add interceptor to handle URL parameters
214
- const ownerId = idGenerator.generateId();
215
- wowFetcher.interceptors.request.use({
216
- name: 'AppendOwnerId',
217
- order: URL_RESOLVE_INTERCEPTOR_ORDER - 1,
218
- intercept(exchange) {
239
+ // Define current user ID
240
+ const currentUserId = idGenerator.generateId();
241
+
242
+ // Create an interceptor to handle URL parameters
243
+ class AppendOwnerId implements RequestInterceptor {
244
+ readonly name: string = 'AppendOwnerId';
245
+ readonly order: number = URL_RESOLVE_INTERCEPTOR_ORDER - 1;
246
+
247
+ intercept(exchange: FetchExchange) {
219
248
  exchange.request.urlParams = {
220
249
  path: {
221
250
  ...exchange.request.urlParams?.path,
222
- ownerId,
251
+ ownerId: currentUserId,
223
252
  },
224
253
  query: exchange.request.urlParams?.query,
225
254
  };
226
- },
227
- });
255
+ }
256
+ }
257
+
258
+ // Register the interceptor
259
+ exampleFetcher.interceptors.request.use(new AppendOwnerId());
228
260
 
229
261
  // Create the snapshot query client
230
- const snapshotQueryClient = new SnapshotQueryClient<CartState>({
231
- fetcher: wowFetcher,
262
+ const cartSnapshotQueryClient = new SnapshotQueryClient<CartState>({
263
+ fetcher: exampleFetcher,
232
264
  basePath: 'owner/{ownerId}/cart',
233
265
  });
234
266
 
235
267
  // Count snapshots
236
- const count = await snapshotQueryClient.count(all());
268
+ const count = await cartSnapshotQueryClient.count(all());
237
269
 
238
270
  // List snapshots
239
271
  const listQuery: ListQuery = {
240
272
  condition: all(),
241
273
  };
242
- const list = await snapshotQueryClient.list(listQuery);
274
+ const list = await cartSnapshotQueryClient.list(listQuery);
243
275
 
244
276
  // List snapshots as stream
245
- const listStream = await snapshotQueryClient.listStream(listQuery);
277
+ const listStream = await cartSnapshotQueryClient.listStream(listQuery);
246
278
  for await (const event of listStream) {
247
279
  const snapshot = event.data;
248
280
  console.log('Received snapshot:', snapshot);
249
281
  }
250
282
 
251
283
  // List snapshot states
252
- const stateList = await snapshotQueryClient.listState(listQuery);
284
+ const stateList = await cartSnapshotQueryClient.listState(listQuery);
253
285
 
254
286
  // List snapshot states as stream
255
- const stateStream = await snapshotQueryClient.listStateStream(listQuery);
287
+ const stateStream = await cartSnapshotQueryClient.listStateStream(listQuery);
256
288
  for await (const event of stateStream) {
257
289
  const state = event.data;
258
290
  console.log('Received state:', state);
@@ -262,27 +294,44 @@ for await (const event of stateStream) {
262
294
  const pagedQuery: PagedQuery = {
263
295
  condition: all(),
264
296
  };
265
- const paged = await snapshotQueryClient.paged(pagedQuery);
297
+ const paged = await cartSnapshotQueryClient.paged(pagedQuery);
266
298
 
267
299
  // Paged snapshot states
268
- const pagedState = await snapshotQueryClient.pagedState(pagedQuery);
300
+ const pagedState = await cartSnapshotQueryClient.pagedState(pagedQuery);
269
301
 
270
302
  // Single snapshot
271
303
  const singleQuery: SingleQuery = {
272
304
  condition: all(),
273
305
  };
274
- const single = await snapshotQueryClient.single(singleQuery);
306
+ const single = await cartSnapshotQueryClient.single(singleQuery);
275
307
 
276
308
  // Single snapshot state
277
- const singleState = await snapshotQueryClient.singleState(singleQuery);
309
+ const singleState = await cartSnapshotQueryClient.singleState(singleQuery);
278
310
  ```
279
311
 
312
+ ##### Methods
313
+
314
+ - `count(condition: Condition): Promise<number>` - Counts the number of snapshots that match the given condition.
315
+ - `list(listQuery: ListQuery): Promise<Partial<MaterializedSnapshot<S>>[]>` - Retrieves a list of materialized
316
+ snapshots.
317
+ - `listStream(listQuery: ListQuery): Promise<ReadableStream<JsonServerSentEvent<Partial<MaterializedSnapshot<S>>>>>` -
318
+ Retrieves a stream of materialized snapshots as Server-Sent Events.
319
+ - `listState(listQuery: ListQuery): Promise<Partial<S>[]>` - Retrieves a list of snapshot states.
320
+ - `listStateStream(listQuery: ListQuery): Promise<ReadableStream<JsonServerSentEvent<Partial<S>>>>` - Retrieves a stream
321
+ of snapshot states as Server-Sent Events.
322
+ - `paged(pagedQuery: PagedQuery): Promise<PagedList<Partial<MaterializedSnapshot<S>>>>` - Retrieves a paged list of
323
+ materialized snapshots.
324
+ - `pagedState(pagedQuery: PagedQuery): Promise<PagedList<Partial<S>>>` - Retrieves a paged list of snapshot states.
325
+ - `single(singleQuery: SingleQuery): Promise<Partial<MaterializedSnapshot<S>>>` - Retrieves a single materialized
326
+ snapshot.
327
+ - `singleState(singleQuery: SingleQuery): Promise<Partial<S>>` - Retrieves a single snapshot state.
328
+
280
329
  #### EventStreamQueryClient
281
330
 
282
- Client for querying domain event streams:
331
+ Client for querying domain event streams with comprehensive query operations:
283
332
 
284
333
  ```typescript
285
- import { Fetcher, URL_RESOLVE_INTERCEPTOR_ORDER } from '@ahoo-wang/fetcher';
334
+ import { Fetcher, FetchExchange, RequestInterceptor, URL_RESOLVE_INTERCEPTOR_ORDER } from '@ahoo-wang/fetcher';
286
335
  import '@ahoo-wang/fetcher-eventstream';
287
336
  import {
288
337
  EventStreamQueryClient,
@@ -292,44 +341,50 @@ import {
292
341
  } from '@ahoo-wang/fetcher-wow';
293
342
  import { idGenerator } from '@ahoo-wang/fetcher-cosec';
294
343
 
295
- // Create a fetcher instance
296
- const wowFetcher = new Fetcher({
344
+ // Create a fetcher instance with base configuration
345
+ const exampleFetcher = new Fetcher({
297
346
  baseURL: 'http://localhost:8080/',
298
347
  });
299
348
 
300
- // Add interceptor to handle URL parameters
301
- const ownerId = idGenerator.generateId();
302
- wowFetcher.interceptors.request.use({
303
- name: 'AppendOwnerId',
304
- order: URL_RESOLVE_INTERCEPTOR_ORDER - 1,
305
- intercept(exchange) {
349
+ // Define current user ID
350
+ const currentUserId = idGenerator.generateId();
351
+
352
+ // Create an interceptor to handle URL parameters
353
+ class AppendOwnerId implements RequestInterceptor {
354
+ readonly name: string = 'AppendOwnerId';
355
+ readonly order: number = URL_RESOLVE_INTERCEPTOR_ORDER - 1;
356
+
357
+ intercept(exchange: FetchExchange) {
306
358
  exchange.request.urlParams = {
307
359
  path: {
308
360
  ...exchange.request.urlParams?.path,
309
- ownerId,
361
+ ownerId: currentUserId,
310
362
  },
311
363
  query: exchange.request.urlParams?.query,
312
364
  };
313
- },
314
- });
365
+ }
366
+ }
367
+
368
+ // Register the interceptor
369
+ exampleFetcher.interceptors.request.use(new AppendOwnerId());
315
370
 
316
371
  // Create the event stream query client
317
- const eventStreamQueryClient = new EventStreamQueryClient({
318
- fetcher: wowFetcher,
372
+ const cartEventStreamQueryClient = new EventStreamQueryClient({
373
+ fetcher: exampleFetcher,
319
374
  basePath: 'owner/{ownerId}/cart',
320
375
  });
321
376
 
322
377
  // Count event streams
323
- const count = await eventStreamQueryClient.count(all());
378
+ const count = await cartEventStreamQueryClient.count(all());
324
379
 
325
380
  // List event streams
326
381
  const listQuery: ListQuery = {
327
382
  condition: all(),
328
383
  };
329
- const list = await eventStreamQueryClient.list(listQuery);
384
+ const list = await cartEventStreamQueryClient.list(listQuery);
330
385
 
331
386
  // List event streams as stream
332
- const listStream = await eventStreamQueryClient.listStream(listQuery);
387
+ const listStream = await cartEventStreamQueryClient.listStream(listQuery);
333
388
  for await (const event of listStream) {
334
389
  const domainEventStream = event.data;
335
390
  console.log('Received event stream:', domainEventStream);
@@ -339,15 +394,25 @@ for await (const event of listStream) {
339
394
  const pagedQuery: PagedQuery = {
340
395
  condition: all(),
341
396
  };
342
- const paged = await eventStreamQueryClient.paged(pagedQuery);
397
+ const paged = await cartEventStreamQueryClient.paged(pagedQuery);
343
398
  ```
344
399
 
400
+ ##### Methods
401
+
402
+ - `count(condition: Condition): Promise<number>` - Counts the number of domain event streams that match the given
403
+ condition.
404
+ - `list(listQuery: ListQuery): Promise<Partial<DomainEventStream>[]>` - Retrieves a list of domain event streams.
405
+ - `listStream(listQuery: ListQuery): Promise<ReadableStream<JsonServerSentEvent<Partial<DomainEventStream>>>>` -
406
+ Retrieves a stream of domain event streams as Server-Sent Events.
407
+ - `paged(pagedQuery: PagedQuery): Promise<PagedList<Partial<DomainEventStream>>>` - Retrieves a paged list of domain
408
+ event streams.
409
+
345
410
  ## 🛠️ Advanced Usage
346
411
 
347
412
  ### Complete Example with Command and Query Flow
348
413
 
349
414
  ```typescript
350
- import { Fetcher, URL_RESOLVE_INTERCEPTOR_ORDER } from '@ahoo-wang/fetcher';
415
+ import { Fetcher, FetchExchange, RequestInterceptor, URL_RESOLVE_INTERCEPTOR_ORDER } from '@ahoo-wang/fetcher';
351
416
  import '@ahoo-wang/fetcher-eventstream';
352
417
  import {
353
418
  CommandClient,
@@ -372,39 +437,58 @@ interface CartState {
372
437
  }
373
438
 
374
439
  // Create a fetcher instance
375
- const wowFetcher = new Fetcher({
440
+ const exampleFetcher = new Fetcher({
376
441
  baseURL: 'http://localhost:8080/',
377
442
  });
378
443
 
379
- // Add interceptor to handle URL parameters
380
- const ownerId = idGenerator.generateId();
381
- wowFetcher.interceptors.request.use({
382
- name: 'AppendOwnerId',
383
- order: URL_RESOLVE_INTERCEPTOR_ORDER - 1,
384
- intercept(exchange) {
444
+ // Define current user ID
445
+ const currentUserId = idGenerator.generateId();
446
+
447
+ // Create an interceptor to handle URL parameters
448
+ class AppendOwnerId implements RequestInterceptor {
449
+ readonly name: string = 'AppendOwnerId';
450
+ readonly order: number = URL_RESOLVE_INTERCEPTOR_ORDER - 1;
451
+
452
+ intercept(exchange: FetchExchange) {
385
453
  exchange.request.urlParams = {
386
454
  path: {
387
455
  ...exchange.request.urlParams?.path,
388
- ownerId,
456
+ ownerId: currentUserId,
389
457
  },
390
458
  query: exchange.request.urlParams?.query,
391
459
  };
392
- },
393
- });
460
+ }
461
+ }
462
+
463
+ // Register the interceptor
464
+ exampleFetcher.interceptors.request.use(new AppendOwnerId());
394
465
 
395
466
  // Create clients
396
- const commandClient = new CommandClient({
397
- fetcher: wowFetcher,
467
+ const cartCommandClient = new CommandClient({
468
+ fetcher: exampleFetcher,
398
469
  basePath: 'owner/{ownerId}/cart',
399
470
  });
400
471
 
401
- const snapshotQueryClient = new SnapshotQueryClient<CartState>({
402
- fetcher: wowFetcher,
472
+ const cartSnapshotQueryClient = new SnapshotQueryClient<CartState>({
473
+ fetcher: exampleFetcher,
403
474
  basePath: 'owner/{ownerId}/cart',
404
475
  });
405
476
 
477
+ // Define command endpoints
478
+ class CartCommandEndpoints {
479
+ static readonly addCartItem = 'add_cart_item';
480
+ }
481
+
482
+ // Define command interfaces
483
+ interface AddCartItem {
484
+ productId: string;
485
+ quantity: number;
486
+ }
487
+
488
+ type AddCartItemCommand = CommandRequest<AddCartItem>
489
+
406
490
  // 1. Send command to add item to cart
407
- const addItemCommand: CommandRequest = {
491
+ const addItemCommand: AddCartItemCommand = {
408
492
  method: HttpMethod.POST,
409
493
  headers: {
410
494
  [CommandHttpHeaders.WAIT_STAGE]: CommandStage.SNAPSHOT,
@@ -415,21 +499,24 @@ const addItemCommand: CommandRequest = {
415
499
  },
416
500
  };
417
501
 
418
- const commandResult = await commandClient.send('add_cart_item', addItemCommand);
502
+ const commandResult = await cartCommandClient.send(
503
+ CartCommandEndpoints.addCartItem,
504
+ addItemCommand
505
+ );
419
506
  console.log('Command executed:', commandResult);
420
507
 
421
508
  // 2. Query the updated cart
422
509
  const listQuery: ListQuery = {
423
510
  condition: all(),
424
511
  };
425
- const carts = await snapshotQueryClient.list(listQuery);
512
+ const carts = await cartSnapshotQueryClient.list(listQuery);
426
513
 
427
514
  for (const cart of carts) {
428
515
  console.log('Cart:', cart.state);
429
516
  }
430
517
 
431
518
  // 3. Stream cart updates
432
- const listStream = await snapshotQueryClient.listStream(listQuery);
519
+ const listStream = await cartSnapshotQueryClient.listStream(listQuery);
433
520
  for await (const event of listStream) {
434
521
  const cart = event.data;
435
522
  console.log('Cart updated:', cart.state);
@@ -459,4 +546,4 @@ Apache-2.0
459
546
 
460
547
  <p align="center">
461
548
  Part of the <a href="https://github.com/Ahoo-Wang/fetcher">Fetcher</a> ecosystem
462
- </p>
549
+ </p>