@voyantjs/promotions-react 0.29.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.
@@ -0,0 +1,614 @@
1
+ import { type PromotionalOfferScope } from "@voyantjs/promotions/validation";
2
+ import { defaultFetcher, useVoyantReactContext, type VoyantFetcher, type VoyantReactContextValue, VoyantReactProvider, type VoyantReactProviderProps } from "@voyantjs/react";
3
+ import { z } from "zod";
4
+ export { defaultFetcher, useVoyantReactContext as useVoyantPromotionsContext, type VoyantFetcher, type VoyantReactContextValue as VoyantPromotionsContextValue, VoyantReactProvider as VoyantPromotionsProvider, type VoyantReactProviderProps as VoyantPromotionsProviderProps, };
5
+ export { type PromotionalOfferScope, promotionalOfferScopeSchema, } from "@voyantjs/promotions/validation";
6
+ declare const promotionalOfferRecordSchema: z.ZodObject<{
7
+ id: z.ZodString;
8
+ name: z.ZodString;
9
+ slug: z.ZodString;
10
+ description: z.ZodNullable<z.ZodString>;
11
+ discountType: z.ZodEnum<{
12
+ percentage: "percentage";
13
+ fixed_amount: "fixed_amount";
14
+ }>;
15
+ discountPercent: z.ZodNullable<z.ZodString>;
16
+ discountAmountCents: z.ZodNullable<z.ZodNumber>;
17
+ currency: z.ZodNullable<z.ZodString>;
18
+ scope: z.ZodDiscriminatedUnion<[z.ZodObject<{
19
+ kind: z.ZodLiteral<"global">;
20
+ }, z.core.$strip>, z.ZodObject<{
21
+ kind: z.ZodLiteral<"products">;
22
+ productIds: z.ZodArray<z.ZodString>;
23
+ }, z.core.$strip>, z.ZodObject<{
24
+ kind: z.ZodLiteral<"categories">;
25
+ categoryIds: z.ZodArray<z.ZodString>;
26
+ }, z.core.$strip>, z.ZodObject<{
27
+ kind: z.ZodLiteral<"destinations">;
28
+ destinationIds: z.ZodArray<z.ZodString>;
29
+ }, z.core.$strip>, z.ZodObject<{
30
+ kind: z.ZodLiteral<"markets">;
31
+ marketIds: z.ZodArray<z.ZodString>;
32
+ }, z.core.$strip>, z.ZodObject<{
33
+ kind: z.ZodLiteral<"audiences">;
34
+ audiences: z.ZodArray<z.ZodEnum<{
35
+ staff: "staff";
36
+ customer: "customer";
37
+ partner: "partner";
38
+ supplier: "supplier";
39
+ }>>;
40
+ }, z.core.$strip>], "kind">;
41
+ conditions: z.ZodObject<{
42
+ minPax: z.ZodOptional<z.ZodNumber>;
43
+ }, z.core.$catchall<z.ZodUnknown>>;
44
+ validFrom: z.ZodNullable<z.ZodString>;
45
+ validUntil: z.ZodNullable<z.ZodString>;
46
+ code: z.ZodNullable<z.ZodString>;
47
+ stackable: z.ZodBoolean;
48
+ active: z.ZodBoolean;
49
+ metadata: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
50
+ createdAt: z.ZodString;
51
+ updatedAt: z.ZodString;
52
+ }, z.core.$strip>;
53
+ export type PromotionalOfferRecord = z.infer<typeof promotionalOfferRecordSchema>;
54
+ export interface PromotionsListQuery {
55
+ active?: boolean;
56
+ code?: string;
57
+ limit?: number;
58
+ offset?: number;
59
+ }
60
+ export interface PromotionsClientOptions {
61
+ baseUrl: string;
62
+ fetcher: VoyantFetcher;
63
+ }
64
+ export declare function fetchPromotionsJson<T>(path: string, init: RequestInit, schema: z.ZodType<T>, client: PromotionsClientOptions): Promise<T>;
65
+ export declare function createPromotionsClientOptions(client?: Partial<PromotionsClientOptions>): PromotionsClientOptions;
66
+ export declare class PromotionsApiError extends Error {
67
+ readonly status: number;
68
+ readonly body: unknown;
69
+ constructor(message: string, status: number, body: unknown);
70
+ }
71
+ export declare const promotionsKeys: {
72
+ all: readonly ["promotions"];
73
+ list: (query: PromotionsListQuery) => readonly ["promotions", "list", PromotionsListQuery];
74
+ detail: (id: string) => readonly ["promotions", "detail", string];
75
+ };
76
+ export declare function getPromotionsListQueryOptions(query?: PromotionsListQuery, client?: PromotionsClientOptions): import("@tanstack/react-query").OmitKeyof<import("@tanstack/react-query").UseQueryOptions<{
77
+ data: {
78
+ id: string;
79
+ name: string;
80
+ slug: string;
81
+ description: string | null;
82
+ discountType: "percentage" | "fixed_amount";
83
+ discountPercent: string | null;
84
+ discountAmountCents: number | null;
85
+ currency: string | null;
86
+ scope: {
87
+ kind: "global";
88
+ } | {
89
+ kind: "products";
90
+ productIds: string[];
91
+ } | {
92
+ kind: "categories";
93
+ categoryIds: string[];
94
+ } | {
95
+ kind: "destinations";
96
+ destinationIds: string[];
97
+ } | {
98
+ kind: "markets";
99
+ marketIds: string[];
100
+ } | {
101
+ kind: "audiences";
102
+ audiences: ("staff" | "customer" | "partner" | "supplier")[];
103
+ };
104
+ conditions: {
105
+ [x: string]: unknown;
106
+ minPax?: number | undefined;
107
+ };
108
+ validFrom: string | null;
109
+ validUntil: string | null;
110
+ code: string | null;
111
+ stackable: boolean;
112
+ active: boolean;
113
+ metadata: Record<string, unknown> | null;
114
+ createdAt: string;
115
+ updatedAt: string;
116
+ }[];
117
+ total: number;
118
+ limit: number;
119
+ offset: number;
120
+ }, Error, {
121
+ data: {
122
+ id: string;
123
+ name: string;
124
+ slug: string;
125
+ description: string | null;
126
+ discountType: "percentage" | "fixed_amount";
127
+ discountPercent: string | null;
128
+ discountAmountCents: number | null;
129
+ currency: string | null;
130
+ scope: {
131
+ kind: "global";
132
+ } | {
133
+ kind: "products";
134
+ productIds: string[];
135
+ } | {
136
+ kind: "categories";
137
+ categoryIds: string[];
138
+ } | {
139
+ kind: "destinations";
140
+ destinationIds: string[];
141
+ } | {
142
+ kind: "markets";
143
+ marketIds: string[];
144
+ } | {
145
+ kind: "audiences";
146
+ audiences: ("staff" | "customer" | "partner" | "supplier")[];
147
+ };
148
+ conditions: {
149
+ [x: string]: unknown;
150
+ minPax?: number | undefined;
151
+ };
152
+ validFrom: string | null;
153
+ validUntil: string | null;
154
+ code: string | null;
155
+ stackable: boolean;
156
+ active: boolean;
157
+ metadata: Record<string, unknown> | null;
158
+ createdAt: string;
159
+ updatedAt: string;
160
+ }[];
161
+ total: number;
162
+ limit: number;
163
+ offset: number;
164
+ }, readonly ["promotions", "list", PromotionsListQuery]>, "queryFn"> & {
165
+ queryFn?: import("@tanstack/react-query").QueryFunction<{
166
+ data: {
167
+ id: string;
168
+ name: string;
169
+ slug: string;
170
+ description: string | null;
171
+ discountType: "percentage" | "fixed_amount";
172
+ discountPercent: string | null;
173
+ discountAmountCents: number | null;
174
+ currency: string | null;
175
+ scope: {
176
+ kind: "global";
177
+ } | {
178
+ kind: "products";
179
+ productIds: string[];
180
+ } | {
181
+ kind: "categories";
182
+ categoryIds: string[];
183
+ } | {
184
+ kind: "destinations";
185
+ destinationIds: string[];
186
+ } | {
187
+ kind: "markets";
188
+ marketIds: string[];
189
+ } | {
190
+ kind: "audiences";
191
+ audiences: ("staff" | "customer" | "partner" | "supplier")[];
192
+ };
193
+ conditions: {
194
+ [x: string]: unknown;
195
+ minPax?: number | undefined;
196
+ };
197
+ validFrom: string | null;
198
+ validUntil: string | null;
199
+ code: string | null;
200
+ stackable: boolean;
201
+ active: boolean;
202
+ metadata: Record<string, unknown> | null;
203
+ createdAt: string;
204
+ updatedAt: string;
205
+ }[];
206
+ total: number;
207
+ limit: number;
208
+ offset: number;
209
+ }, readonly ["promotions", "list", PromotionsListQuery], never> | undefined;
210
+ } & {
211
+ queryKey: readonly ["promotions", "list", PromotionsListQuery] & {
212
+ [dataTagSymbol]: {
213
+ data: {
214
+ id: string;
215
+ name: string;
216
+ slug: string;
217
+ description: string | null;
218
+ discountType: "percentage" | "fixed_amount";
219
+ discountPercent: string | null;
220
+ discountAmountCents: number | null;
221
+ currency: string | null;
222
+ scope: {
223
+ kind: "global";
224
+ } | {
225
+ kind: "products";
226
+ productIds: string[];
227
+ } | {
228
+ kind: "categories";
229
+ categoryIds: string[];
230
+ } | {
231
+ kind: "destinations";
232
+ destinationIds: string[];
233
+ } | {
234
+ kind: "markets";
235
+ marketIds: string[];
236
+ } | {
237
+ kind: "audiences";
238
+ audiences: ("staff" | "customer" | "partner" | "supplier")[];
239
+ };
240
+ conditions: {
241
+ [x: string]: unknown;
242
+ minPax?: number | undefined;
243
+ };
244
+ validFrom: string | null;
245
+ validUntil: string | null;
246
+ code: string | null;
247
+ stackable: boolean;
248
+ active: boolean;
249
+ metadata: Record<string, unknown> | null;
250
+ createdAt: string;
251
+ updatedAt: string;
252
+ }[];
253
+ total: number;
254
+ limit: number;
255
+ offset: number;
256
+ };
257
+ [dataTagErrorSymbol]: Error;
258
+ };
259
+ };
260
+ export declare function getPromotionByIdQueryOptions(id: string, client?: PromotionsClientOptions): import("@tanstack/react-query").OmitKeyof<import("@tanstack/react-query").UseQueryOptions<{
261
+ id: string;
262
+ name: string;
263
+ slug: string;
264
+ description: string | null;
265
+ discountType: "percentage" | "fixed_amount";
266
+ discountPercent: string | null;
267
+ discountAmountCents: number | null;
268
+ currency: string | null;
269
+ scope: {
270
+ kind: "global";
271
+ } | {
272
+ kind: "products";
273
+ productIds: string[];
274
+ } | {
275
+ kind: "categories";
276
+ categoryIds: string[];
277
+ } | {
278
+ kind: "destinations";
279
+ destinationIds: string[];
280
+ } | {
281
+ kind: "markets";
282
+ marketIds: string[];
283
+ } | {
284
+ kind: "audiences";
285
+ audiences: ("staff" | "customer" | "partner" | "supplier")[];
286
+ };
287
+ conditions: {
288
+ [x: string]: unknown;
289
+ minPax?: number | undefined;
290
+ };
291
+ validFrom: string | null;
292
+ validUntil: string | null;
293
+ code: string | null;
294
+ stackable: boolean;
295
+ active: boolean;
296
+ metadata: Record<string, unknown> | null;
297
+ createdAt: string;
298
+ updatedAt: string;
299
+ }, Error, {
300
+ id: string;
301
+ name: string;
302
+ slug: string;
303
+ description: string | null;
304
+ discountType: "percentage" | "fixed_amount";
305
+ discountPercent: string | null;
306
+ discountAmountCents: number | null;
307
+ currency: string | null;
308
+ scope: {
309
+ kind: "global";
310
+ } | {
311
+ kind: "products";
312
+ productIds: string[];
313
+ } | {
314
+ kind: "categories";
315
+ categoryIds: string[];
316
+ } | {
317
+ kind: "destinations";
318
+ destinationIds: string[];
319
+ } | {
320
+ kind: "markets";
321
+ marketIds: string[];
322
+ } | {
323
+ kind: "audiences";
324
+ audiences: ("staff" | "customer" | "partner" | "supplier")[];
325
+ };
326
+ conditions: {
327
+ [x: string]: unknown;
328
+ minPax?: number | undefined;
329
+ };
330
+ validFrom: string | null;
331
+ validUntil: string | null;
332
+ code: string | null;
333
+ stackable: boolean;
334
+ active: boolean;
335
+ metadata: Record<string, unknown> | null;
336
+ createdAt: string;
337
+ updatedAt: string;
338
+ }, readonly ["promotions", "detail", string]>, "queryFn"> & {
339
+ queryFn?: import("@tanstack/react-query").QueryFunction<{
340
+ id: string;
341
+ name: string;
342
+ slug: string;
343
+ description: string | null;
344
+ discountType: "percentage" | "fixed_amount";
345
+ discountPercent: string | null;
346
+ discountAmountCents: number | null;
347
+ currency: string | null;
348
+ scope: {
349
+ kind: "global";
350
+ } | {
351
+ kind: "products";
352
+ productIds: string[];
353
+ } | {
354
+ kind: "categories";
355
+ categoryIds: string[];
356
+ } | {
357
+ kind: "destinations";
358
+ destinationIds: string[];
359
+ } | {
360
+ kind: "markets";
361
+ marketIds: string[];
362
+ } | {
363
+ kind: "audiences";
364
+ audiences: ("staff" | "customer" | "partner" | "supplier")[];
365
+ };
366
+ conditions: {
367
+ [x: string]: unknown;
368
+ minPax?: number | undefined;
369
+ };
370
+ validFrom: string | null;
371
+ validUntil: string | null;
372
+ code: string | null;
373
+ stackable: boolean;
374
+ active: boolean;
375
+ metadata: Record<string, unknown> | null;
376
+ createdAt: string;
377
+ updatedAt: string;
378
+ }, readonly ["promotions", "detail", string], never> | undefined;
379
+ } & {
380
+ queryKey: readonly ["promotions", "detail", string] & {
381
+ [dataTagSymbol]: {
382
+ id: string;
383
+ name: string;
384
+ slug: string;
385
+ description: string | null;
386
+ discountType: "percentage" | "fixed_amount";
387
+ discountPercent: string | null;
388
+ discountAmountCents: number | null;
389
+ currency: string | null;
390
+ scope: {
391
+ kind: "global";
392
+ } | {
393
+ kind: "products";
394
+ productIds: string[];
395
+ } | {
396
+ kind: "categories";
397
+ categoryIds: string[];
398
+ } | {
399
+ kind: "destinations";
400
+ destinationIds: string[];
401
+ } | {
402
+ kind: "markets";
403
+ marketIds: string[];
404
+ } | {
405
+ kind: "audiences";
406
+ audiences: ("staff" | "customer" | "partner" | "supplier")[];
407
+ };
408
+ conditions: {
409
+ [x: string]: unknown;
410
+ minPax?: number | undefined;
411
+ };
412
+ validFrom: string | null;
413
+ validUntil: string | null;
414
+ code: string | null;
415
+ stackable: boolean;
416
+ active: boolean;
417
+ metadata: Record<string, unknown> | null;
418
+ createdAt: string;
419
+ updatedAt: string;
420
+ };
421
+ [dataTagErrorSymbol]: Error;
422
+ };
423
+ };
424
+ export declare function usePromotionsList(query?: PromotionsListQuery): import("@tanstack/react-query").UseQueryResult<{
425
+ data: {
426
+ id: string;
427
+ name: string;
428
+ slug: string;
429
+ description: string | null;
430
+ discountType: "percentage" | "fixed_amount";
431
+ discountPercent: string | null;
432
+ discountAmountCents: number | null;
433
+ currency: string | null;
434
+ scope: {
435
+ kind: "global";
436
+ } | {
437
+ kind: "products";
438
+ productIds: string[];
439
+ } | {
440
+ kind: "categories";
441
+ categoryIds: string[];
442
+ } | {
443
+ kind: "destinations";
444
+ destinationIds: string[];
445
+ } | {
446
+ kind: "markets";
447
+ marketIds: string[];
448
+ } | {
449
+ kind: "audiences";
450
+ audiences: ("staff" | "customer" | "partner" | "supplier")[];
451
+ };
452
+ conditions: {
453
+ [x: string]: unknown;
454
+ minPax?: number | undefined;
455
+ };
456
+ validFrom: string | null;
457
+ validUntil: string | null;
458
+ code: string | null;
459
+ stackable: boolean;
460
+ active: boolean;
461
+ metadata: Record<string, unknown> | null;
462
+ createdAt: string;
463
+ updatedAt: string;
464
+ }[];
465
+ total: number;
466
+ limit: number;
467
+ offset: number;
468
+ }, Error>;
469
+ export interface PromotionInsertInput {
470
+ name: string;
471
+ slug: string;
472
+ description?: string | null;
473
+ discountType: "percentage" | "fixed_amount";
474
+ discountPercent?: number | null;
475
+ discountAmountCents?: number | null;
476
+ currency?: string | null;
477
+ scope: PromotionalOfferScope;
478
+ conditions?: {
479
+ minPax?: number;
480
+ };
481
+ validFrom?: string | null;
482
+ validUntil?: string | null;
483
+ code?: string | null;
484
+ stackable?: boolean;
485
+ active?: boolean;
486
+ }
487
+ export type PromotionUpdateInput = Partial<PromotionInsertInput>;
488
+ export declare function useCreatePromotion(): import("@tanstack/react-query").UseMutationResult<{
489
+ id: string;
490
+ name: string;
491
+ slug: string;
492
+ description: string | null;
493
+ discountType: "percentage" | "fixed_amount";
494
+ discountPercent: string | null;
495
+ discountAmountCents: number | null;
496
+ currency: string | null;
497
+ scope: {
498
+ kind: "global";
499
+ } | {
500
+ kind: "products";
501
+ productIds: string[];
502
+ } | {
503
+ kind: "categories";
504
+ categoryIds: string[];
505
+ } | {
506
+ kind: "destinations";
507
+ destinationIds: string[];
508
+ } | {
509
+ kind: "markets";
510
+ marketIds: string[];
511
+ } | {
512
+ kind: "audiences";
513
+ audiences: ("staff" | "customer" | "partner" | "supplier")[];
514
+ };
515
+ conditions: {
516
+ [x: string]: unknown;
517
+ minPax?: number | undefined;
518
+ };
519
+ validFrom: string | null;
520
+ validUntil: string | null;
521
+ code: string | null;
522
+ stackable: boolean;
523
+ active: boolean;
524
+ metadata: Record<string, unknown> | null;
525
+ createdAt: string;
526
+ updatedAt: string;
527
+ }, Error, PromotionInsertInput, unknown>;
528
+ export declare function useUpdatePromotion(): import("@tanstack/react-query").UseMutationResult<{
529
+ id: string;
530
+ name: string;
531
+ slug: string;
532
+ description: string | null;
533
+ discountType: "percentage" | "fixed_amount";
534
+ discountPercent: string | null;
535
+ discountAmountCents: number | null;
536
+ currency: string | null;
537
+ scope: {
538
+ kind: "global";
539
+ } | {
540
+ kind: "products";
541
+ productIds: string[];
542
+ } | {
543
+ kind: "categories";
544
+ categoryIds: string[];
545
+ } | {
546
+ kind: "destinations";
547
+ destinationIds: string[];
548
+ } | {
549
+ kind: "markets";
550
+ marketIds: string[];
551
+ } | {
552
+ kind: "audiences";
553
+ audiences: ("staff" | "customer" | "partner" | "supplier")[];
554
+ };
555
+ conditions: {
556
+ [x: string]: unknown;
557
+ minPax?: number | undefined;
558
+ };
559
+ validFrom: string | null;
560
+ validUntil: string | null;
561
+ code: string | null;
562
+ stackable: boolean;
563
+ active: boolean;
564
+ metadata: Record<string, unknown> | null;
565
+ createdAt: string;
566
+ updatedAt: string;
567
+ }, Error, {
568
+ id: string;
569
+ patch: PromotionUpdateInput;
570
+ }, unknown>;
571
+ export declare function useArchivePromotion(): import("@tanstack/react-query").UseMutationResult<{
572
+ id: string;
573
+ name: string;
574
+ slug: string;
575
+ description: string | null;
576
+ discountType: "percentage" | "fixed_amount";
577
+ discountPercent: string | null;
578
+ discountAmountCents: number | null;
579
+ currency: string | null;
580
+ scope: {
581
+ kind: "global";
582
+ } | {
583
+ kind: "products";
584
+ productIds: string[];
585
+ } | {
586
+ kind: "categories";
587
+ categoryIds: string[];
588
+ } | {
589
+ kind: "destinations";
590
+ destinationIds: string[];
591
+ } | {
592
+ kind: "markets";
593
+ marketIds: string[];
594
+ } | {
595
+ kind: "audiences";
596
+ audiences: ("staff" | "customer" | "partner" | "supplier")[];
597
+ };
598
+ conditions: {
599
+ [x: string]: unknown;
600
+ minPax?: number | undefined;
601
+ };
602
+ validFrom: string | null;
603
+ validUntil: string | null;
604
+ code: string | null;
605
+ stackable: boolean;
606
+ active: boolean;
607
+ metadata: Record<string, unknown> | null;
608
+ createdAt: string;
609
+ updatedAt: string;
610
+ }, Error, string, unknown>;
611
+ export declare function useDeletePromotion(): import("@tanstack/react-query").UseMutationResult<{
612
+ id: string;
613
+ }, Error, string, unknown>;
614
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,162 @@
1
+ "use client";
2
+ import { queryOptions, useMutation, useQuery, useQueryClient, } from "@tanstack/react-query";
3
+ import { promotionalOfferScopeSchema, } from "@voyantjs/promotions/validation";
4
+ import { defaultFetcher, useVoyantReactContext, VoyantReactProvider, } from "@voyantjs/react";
5
+ import { z } from "zod";
6
+ // ---------- Provider ----------
7
+ export { defaultFetcher, useVoyantReactContext as useVoyantPromotionsContext, VoyantReactProvider as VoyantPromotionsProvider, };
8
+ // ---------- Schemas ----------
9
+ export { promotionalOfferScopeSchema, } from "@voyantjs/promotions/validation";
10
+ const promotionalOfferRecordSchema = z.object({
11
+ id: z.string(),
12
+ name: z.string(),
13
+ slug: z.string(),
14
+ description: z.string().nullable(),
15
+ discountType: z.enum(["percentage", "fixed_amount"]),
16
+ discountPercent: z.string().nullable(),
17
+ discountAmountCents: z.number().nullable(),
18
+ currency: z.string().nullable(),
19
+ scope: promotionalOfferScopeSchema,
20
+ conditions: z.object({ minPax: z.number().int().positive().optional() }).catchall(z.unknown()),
21
+ validFrom: z.string().nullable(),
22
+ validUntil: z.string().nullable(),
23
+ code: z.string().nullable(),
24
+ stackable: z.boolean(),
25
+ active: z.boolean(),
26
+ metadata: z.record(z.string(), z.unknown()).nullable(),
27
+ createdAt: z.string(),
28
+ updatedAt: z.string(),
29
+ });
30
+ const listResponseSchema = z.object({
31
+ data: z.array(promotionalOfferRecordSchema),
32
+ total: z.number(),
33
+ limit: z.number(),
34
+ offset: z.number(),
35
+ });
36
+ const singleResponseSchema = z.object({ data: promotionalOfferRecordSchema });
37
+ function buildSearch(query) {
38
+ const params = new URLSearchParams();
39
+ if (query.active !== undefined)
40
+ params.set("active", String(query.active));
41
+ if (query.code)
42
+ params.set("code", query.code);
43
+ if (query.limit !== undefined)
44
+ params.set("limit", String(query.limit));
45
+ if (query.offset !== undefined)
46
+ params.set("offset", String(query.offset));
47
+ const s = params.toString();
48
+ return s ? `?${s}` : "";
49
+ }
50
+ export async function fetchPromotionsJson(path, init, schema, client) {
51
+ const headers = new Headers(init.headers);
52
+ if (init.body !== undefined && !headers.has("Content-Type")) {
53
+ headers.set("Content-Type", "application/json");
54
+ }
55
+ const response = await client.fetcher(joinUrl(client.baseUrl, path), { ...init, headers });
56
+ const body = await safeJson(response);
57
+ if (!response.ok) {
58
+ const message = typeof body === "object" && body && "error" in body
59
+ ? String(body.error)
60
+ : `Promotions API error: ${response.status} ${response.statusText}`;
61
+ throw new PromotionsApiError(message, response.status, body);
62
+ }
63
+ return schema.parse(body);
64
+ }
65
+ async function safeJson(response) {
66
+ const text = await response.text();
67
+ if (!text)
68
+ return undefined;
69
+ try {
70
+ return JSON.parse(text);
71
+ }
72
+ catch {
73
+ return text;
74
+ }
75
+ }
76
+ function joinUrl(baseUrl, path) {
77
+ const resolvedBaseUrl = resolveBaseUrl(baseUrl);
78
+ const trimmedBase = resolvedBaseUrl.endsWith("/") ? resolvedBaseUrl.slice(0, -1) : resolvedBaseUrl;
79
+ const trimmedPath = path.startsWith("/") ? path : `/${path}`;
80
+ return `${trimmedBase}${trimmedPath}`;
81
+ }
82
+ function resolveBaseUrl(baseUrl) {
83
+ if (baseUrl.trim())
84
+ return baseUrl;
85
+ if (typeof window !== "undefined") {
86
+ return `${window.location.origin}/api`;
87
+ }
88
+ return "http://localhost:3300/api";
89
+ }
90
+ export function createPromotionsClientOptions(client) {
91
+ return {
92
+ baseUrl: client?.baseUrl ?? "",
93
+ fetcher: client?.fetcher ?? defaultFetcher,
94
+ };
95
+ }
96
+ export class PromotionsApiError extends Error {
97
+ status;
98
+ body;
99
+ constructor(message, status, body) {
100
+ super(message);
101
+ this.name = "PromotionsApiError";
102
+ this.status = status;
103
+ this.body = body;
104
+ }
105
+ }
106
+ // ---------- Query keys + options ----------
107
+ export const promotionsKeys = {
108
+ all: ["promotions"],
109
+ list: (query) => ["promotions", "list", query],
110
+ detail: (id) => ["promotions", "detail", id],
111
+ };
112
+ export function getPromotionsListQueryOptions(query = {}, client = createPromotionsClientOptions()) {
113
+ return queryOptions({
114
+ queryKey: promotionsKeys.list(query),
115
+ queryFn: () => fetchPromotionsJson(`/v1/admin/promotions${buildSearch(query)}`, { method: "GET" }, listResponseSchema, client),
116
+ });
117
+ }
118
+ export function getPromotionByIdQueryOptions(id, client = createPromotionsClientOptions()) {
119
+ return queryOptions({
120
+ queryKey: promotionsKeys.detail(id),
121
+ queryFn: () => fetchPromotionsJson(`/v1/admin/promotions/${id}`, { method: "GET" }, singleResponseSchema, client).then((r) => r.data),
122
+ });
123
+ }
124
+ export function usePromotionsList(query = {}) {
125
+ const client = useVoyantReactContext();
126
+ return useQuery(getPromotionsListQueryOptions(query, client));
127
+ }
128
+ function invalidatePromotions(qc) {
129
+ return qc.invalidateQueries({ queryKey: promotionsKeys.all });
130
+ }
131
+ export function useCreatePromotion() {
132
+ const qc = useQueryClient();
133
+ const client = useVoyantReactContext();
134
+ return useMutation({
135
+ mutationFn: (input) => fetchPromotionsJson("/v1/admin/promotions", { method: "POST", body: JSON.stringify(input) }, singleResponseSchema, client).then((r) => r.data),
136
+ onSuccess: () => invalidatePromotions(qc),
137
+ });
138
+ }
139
+ export function useUpdatePromotion() {
140
+ const qc = useQueryClient();
141
+ const client = useVoyantReactContext();
142
+ return useMutation({
143
+ mutationFn: ({ id, patch }) => fetchPromotionsJson(`/v1/admin/promotions/${id}`, { method: "PATCH", body: JSON.stringify(patch) }, singleResponseSchema, client).then((r) => r.data),
144
+ onSuccess: () => invalidatePromotions(qc),
145
+ });
146
+ }
147
+ export function useArchivePromotion() {
148
+ const qc = useQueryClient();
149
+ const client = useVoyantReactContext();
150
+ return useMutation({
151
+ mutationFn: (id) => fetchPromotionsJson(`/v1/admin/promotions/${id}/archive`, { method: "POST" }, singleResponseSchema, client).then((r) => r.data),
152
+ onSuccess: () => invalidatePromotions(qc),
153
+ });
154
+ }
155
+ export function useDeletePromotion() {
156
+ const qc = useQueryClient();
157
+ const client = useVoyantReactContext();
158
+ return useMutation({
159
+ mutationFn: (id) => fetchPromotionsJson(`/v1/admin/promotions/${id}`, { method: "DELETE" }, z.object({ data: z.object({ id: z.string() }) }), client).then((r) => r.data),
160
+ onSuccess: () => invalidatePromotions(qc),
161
+ });
162
+ }
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@voyantjs/promotions-react",
3
+ "version": "0.29.0",
4
+ "license": "Apache-2.0",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/voyantjs/voyant.git",
8
+ "directory": "packages/promotions-react"
9
+ },
10
+ "type": "module",
11
+ "sideEffects": false,
12
+ "exports": {
13
+ ".": "./src/index.ts"
14
+ },
15
+ "scripts": {
16
+ "build": "tsc -p tsconfig.json",
17
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
18
+ "prepack": "pnpm run build",
19
+ "typecheck": "tsc --noEmit",
20
+ "lint": "biome check src/",
21
+ "test": "vitest run --passWithNoTests"
22
+ },
23
+ "peerDependencies": {
24
+ "@tanstack/react-query": "^5.0.0",
25
+ "@voyantjs/promotions": "workspace:*",
26
+ "@voyantjs/react": "workspace:*",
27
+ "react": "^19.0.0",
28
+ "react-dom": "^19.0.0",
29
+ "zod": "^4.0.0"
30
+ },
31
+ "devDependencies": {
32
+ "@tanstack/react-query": "^5.96.2",
33
+ "@types/react": "^19.2.14",
34
+ "@types/react-dom": "^19.2.3",
35
+ "@voyantjs/promotions": "workspace:*",
36
+ "@voyantjs/react": "workspace:*",
37
+ "@voyantjs/voyant-typescript-config": "workspace:*",
38
+ "react": "^19.2.4",
39
+ "react-dom": "^19.2.4",
40
+ "typescript": "^6.0.2",
41
+ "vitest": "^4.1.2",
42
+ "zod": "^4.3.6"
43
+ },
44
+ "files": [
45
+ "dist"
46
+ ],
47
+ "publishConfig": {
48
+ "access": "public",
49
+ "exports": {
50
+ ".": {
51
+ "types": "./dist/index.d.ts",
52
+ "import": "./dist/index.js",
53
+ "default": "./dist/index.js"
54
+ }
55
+ },
56
+ "main": "./dist/index.js",
57
+ "types": "./dist/index.d.ts"
58
+ }
59
+ }