@cimplify/sdk 0.3.3 → 0.3.5
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/dist/index.d.mts +117 -2
- package/dist/index.d.ts +117 -2
- package/dist/index.js +136 -23
- package/dist/index.mjs +136 -23
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observability hooks for monitoring SDK behavior.
|
|
3
|
+
*
|
|
4
|
+
* These hooks allow you to plug in your own logging, metrics, and tracing
|
|
5
|
+
* without the SDK depending on any specific observability library.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const client = createCimplifyClient({
|
|
10
|
+
* hooks: {
|
|
11
|
+
* onRequestStart: ({ method, path }) => {
|
|
12
|
+
* console.log(`[SDK] ${method} ${path}`);
|
|
13
|
+
* },
|
|
14
|
+
* onRequestSuccess: ({ method, path, durationMs }) => {
|
|
15
|
+
* metrics.histogram('sdk.request.duration', durationMs, { method, path });
|
|
16
|
+
* },
|
|
17
|
+
* onRequestError: ({ method, path, error, retryCount }) => {
|
|
18
|
+
* Sentry.captureException(error, { extra: { method, path, retryCount } });
|
|
19
|
+
* },
|
|
20
|
+
* },
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
/** Context passed to request lifecycle hooks */
|
|
25
|
+
interface RequestContext {
|
|
26
|
+
/** HTTP method */
|
|
27
|
+
method: "GET" | "POST" | "DELETE";
|
|
28
|
+
/** Request path (e.g., "/api/q", "/api/m") */
|
|
29
|
+
path: string;
|
|
30
|
+
/** Full URL */
|
|
31
|
+
url: string;
|
|
32
|
+
/** Request body (for POST requests) */
|
|
33
|
+
body?: unknown;
|
|
34
|
+
/** Timestamp when request started */
|
|
35
|
+
startTime: number;
|
|
36
|
+
}
|
|
37
|
+
/** Passed when a request starts */
|
|
38
|
+
interface RequestStartEvent extends RequestContext {
|
|
39
|
+
}
|
|
40
|
+
/** Passed when a request succeeds */
|
|
41
|
+
interface RequestSuccessEvent extends RequestContext {
|
|
42
|
+
/** HTTP status code */
|
|
43
|
+
status: number;
|
|
44
|
+
/** Duration in milliseconds */
|
|
45
|
+
durationMs: number;
|
|
46
|
+
}
|
|
47
|
+
/** Passed when a request fails */
|
|
48
|
+
interface RequestErrorEvent extends RequestContext {
|
|
49
|
+
/** The error that occurred */
|
|
50
|
+
error: Error;
|
|
51
|
+
/** Duration in milliseconds */
|
|
52
|
+
durationMs: number;
|
|
53
|
+
/** Number of retries attempted before giving up */
|
|
54
|
+
retryCount: number;
|
|
55
|
+
/** Whether the error is retryable */
|
|
56
|
+
retryable: boolean;
|
|
57
|
+
}
|
|
58
|
+
/** Passed when a retry is about to happen */
|
|
59
|
+
interface RetryEvent extends RequestContext {
|
|
60
|
+
/** Which retry attempt (1, 2, 3...) */
|
|
61
|
+
attempt: number;
|
|
62
|
+
/** Delay before retry in milliseconds */
|
|
63
|
+
delayMs: number;
|
|
64
|
+
/** The error that triggered the retry */
|
|
65
|
+
error: Error;
|
|
66
|
+
}
|
|
67
|
+
/** Passed when session token changes */
|
|
68
|
+
interface SessionChangeEvent {
|
|
69
|
+
/** Previous token (null if none) */
|
|
70
|
+
previousToken: string | null;
|
|
71
|
+
/** New token (null if cleared) */
|
|
72
|
+
newToken: string | null;
|
|
73
|
+
/** Source of the change */
|
|
74
|
+
source: "response" | "manual" | "clear";
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Observability hooks configuration.
|
|
78
|
+
* All hooks are optional - only implement what you need.
|
|
79
|
+
*/
|
|
80
|
+
interface ObservabilityHooks {
|
|
81
|
+
/** Called when a request is about to be sent */
|
|
82
|
+
onRequestStart?: (event: RequestStartEvent) => void;
|
|
83
|
+
/** Called when a request completes successfully */
|
|
84
|
+
onRequestSuccess?: (event: RequestSuccessEvent) => void;
|
|
85
|
+
/** Called when a request fails (after all retries exhausted) */
|
|
86
|
+
onRequestError?: (event: RequestErrorEvent) => void;
|
|
87
|
+
/** Called before each retry attempt */
|
|
88
|
+
onRetry?: (event: RetryEvent) => void;
|
|
89
|
+
/** Called when session token changes */
|
|
90
|
+
onSessionChange?: (event: SessionChangeEvent) => void;
|
|
91
|
+
}
|
|
92
|
+
|
|
1
93
|
/** Decimal value represented as string for precision */
|
|
2
94
|
type Money = string;
|
|
3
95
|
/** Supported currencies */
|
|
@@ -2839,6 +2931,8 @@ interface CimplifyConfig {
|
|
|
2839
2931
|
maxRetries?: number;
|
|
2840
2932
|
/** Base delay between retries in milliseconds (default: 1000) */
|
|
2841
2933
|
retryDelay?: number;
|
|
2934
|
+
/** Observability hooks for logging, metrics, and tracing */
|
|
2935
|
+
hooks?: ObservabilityHooks;
|
|
2842
2936
|
}
|
|
2843
2937
|
declare class CimplifyClient {
|
|
2844
2938
|
private baseUrl;
|
|
@@ -2849,6 +2943,9 @@ declare class CimplifyClient {
|
|
|
2849
2943
|
private timeout;
|
|
2850
2944
|
private maxRetries;
|
|
2851
2945
|
private retryDelay;
|
|
2946
|
+
private hooks;
|
|
2947
|
+
/** In-flight request deduplication map */
|
|
2948
|
+
private inflightRequests;
|
|
2852
2949
|
private _catalogue?;
|
|
2853
2950
|
private _cart?;
|
|
2854
2951
|
private _checkout?;
|
|
@@ -2868,11 +2965,29 @@ declare class CimplifyClient {
|
|
|
2868
2965
|
private getHeaders;
|
|
2869
2966
|
private updateSessionFromResponse;
|
|
2870
2967
|
/**
|
|
2871
|
-
* Resilient fetch with timeout
|
|
2968
|
+
* Resilient fetch with timeout, automatic retries, and observability hooks.
|
|
2872
2969
|
* Uses exponential backoff: 1s, 2s, 4s between retries.
|
|
2873
2970
|
*/
|
|
2874
2971
|
private resilientFetch;
|
|
2972
|
+
/**
|
|
2973
|
+
* Generate a deduplication key for a request.
|
|
2974
|
+
* Same query + variables = same key = deduplicated.
|
|
2975
|
+
*/
|
|
2976
|
+
private getDedupeKey;
|
|
2977
|
+
/**
|
|
2978
|
+
* Execute a request with deduplication.
|
|
2979
|
+
* If an identical request is already in-flight, return the same promise.
|
|
2980
|
+
* This prevents redundant network calls when multiple components request the same data.
|
|
2981
|
+
*/
|
|
2982
|
+
private deduplicatedRequest;
|
|
2983
|
+
/**
|
|
2984
|
+
* Execute a query with deduplication.
|
|
2985
|
+
* Multiple identical queries made simultaneously will share a single network request.
|
|
2986
|
+
*/
|
|
2875
2987
|
query<T = unknown>(query: string, variables?: Record<string, unknown>): Promise<T>;
|
|
2988
|
+
/**
|
|
2989
|
+
* Execute a mutation. NOT deduplicated - mutations have side effects.
|
|
2990
|
+
*/
|
|
2876
2991
|
call<T = unknown>(method: string, args?: unknown): Promise<T>;
|
|
2877
2992
|
get<T = unknown>(path: string): Promise<T>;
|
|
2878
2993
|
post<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
@@ -3415,4 +3530,4 @@ interface ApiResponse<T> {
|
|
|
3415
3530
|
metadata?: ResponseMetadata;
|
|
3416
3531
|
}
|
|
3417
3532
|
|
|
3418
|
-
export { AUTHORIZATION_TYPE, AUTH_MUTATION, type AddOn, type AddOnDetails, type AddOnGroupDetails, type AddOnOption, type AddOnOptionDetails, type AddOnOptionPrice, type AddOnWithOptions, type AddToCartInput, type AddressData, type AdjustmentType, type AmountToPay, type ApiError, type ApiResponse, type AppliedDiscount, type AuthResponse, AuthService, type AuthStatus, type AuthorizationType, type AvailabilityCheck, type AvailabilityResult, type AvailableSlot, type BenefitType, type Booking, type BookingRequirementOverride, type BookingStatus, type BookingWithDetails, type BufferTimes, type Bundle, type BundleComponentData, type BundleComponentInfo, type BundlePriceType, type BundleProduct, type BundleSelectionData, type BundleSelectionInput, type BundleStoredSelection, type BundleSummary, type BundleWithDetails, type Business, type BusinessHours, type BusinessPreferences, BusinessService, type BusinessSettings, type BusinessType, type BusinessWithLocations, CHECKOUT_MODE, CHECKOUT_MUTATION, CHECKOUT_STEP, CURRENCY_SYMBOLS, type CancelBookingInput, type CancelOrderInput, type CancellationPolicy, type Cart, type CartAddOn, type CartChannel, type CartItem, type CartItemDetails, CartOperations, type CartStatus, type CartSummary, type CartTotals, CatalogueQueries, type Category, type CategoryInfo, type CategorySummary, type ChangePasswordInput, type CheckSlotAvailabilityInput, type CheckoutAddressInfo, type CheckoutCustomerInfo, type CheckoutFormData, type CheckoutInput, type CheckoutMode, CheckoutService as CheckoutOperations, type CheckoutOrderType, type CheckoutPaymentMethod, type CheckoutResult, CheckoutService, type CheckoutStep, type ChosenPrice, CimplifyClient, type CimplifyConfig, CimplifyError, type Collection, type CollectionProduct, type CollectionSummary, type ComponentGroup, type ComponentGroupWithComponents, type ComponentPriceBreakdown, type ComponentSelectionInput, type ComponentSourceType, type Composite, type CompositeComponent, type CompositePriceBreakdown, type CompositePriceResult, type CompositePricingMode, type CompositeSelectionData, type ComponentSelectionInput as CompositeSelectionInput, type CompositeStoredSelection, type CompositeWithDetails, type ContactType, type CreateAddressInput, type CreateMobileMoneyInput, type Currency, type Customer, type CustomerAddress, type CustomerLinkPreferences, type CustomerMobileMoney, type CustomerServicePreferences, DEFAULT_COUNTRY, DEFAULT_CURRENCY, type DayAvailability, type DepositResult, type DepositType, type DeviceType, type DigitalProductType, type DiscountBreakdown, type DiscountDetails, type DisplayAddOn, type DisplayAddOnOption, type DisplayCart, type DisplayCartItem, type EnrollAndLinkOrderInput, type EnrollAndLinkOrderResult, type EnrollmentData, type Err, ErrorCode, type ErrorCodeType, type FeeBearerType, type FormatCompactOptions, type FormatPriceOptions, type FulfillmentLink, type FulfillmentStatus, type FulfillmentType, type GetAvailableSlotsInput, type GetOrdersOptions, type GetProductsOptions, type GroupPricingBehavior, type InitializePaymentResult, InventoryService, type InventorySummary, type InventoryType, type KitchenOrderItem, type KitchenOrderResult, LINK_MUTATION, LINK_QUERY, type LineConfiguration, type LineItem, type LineType, type LinkData, type LinkEnrollResult, LinkService, type LinkSession, type LinkStatusResult, type LiteBootstrap, LiteService, type Location, type LocationAppointment, type LocationProductPrice, type LocationStock, type LocationTaxBehavior, type LocationTaxOverrides, type LocationTimeProfile, type LocationWithDetails, MOBILE_MONEY_PROVIDER, MOBILE_MONEY_PROVIDERS, type MobileMoneyData, type MobileMoneyDetails, type MobileMoneyProvider, type Money, type MutationRequest, ORDER_MUTATION, ORDER_TYPE, type Ok, type Order, type OrderChannel, type OrderFilter, type OrderFulfillmentSummary, type OrderGroup, type OrderGroupDetails, type OrderGroupPayment, type OrderGroupPaymentState, type OrderGroupPaymentSummary, type OrderHistory, type OrderLineState, type OrderLineStatus, type OrderPaymentEvent, OrderQueries, type OrderSplitDetail, type OrderStatus, type OtpResult, PAYMENT_METHOD, PAYMENT_MUTATION, PAYMENT_STATE, PICKUP_TIME_TYPE, type Pagination, type PaginationParams, type ParsedPrice, type Payment, type PaymentErrorDetails, type PaymentMethod, type PaymentMethodType, type PaymentProcessingState, type PaymentProvider, type PaymentResponse, type PaymentState, type PaymentStatus, type PaymentStatusResponse, type PickupTime, type PickupTimeType, type Price, type PriceAdjustment, type PriceDecisionPath, type PriceEntryType, type PriceInfo, type PricePathTaxInfo, type PriceSource, type PricingOverrides, type Product, type ProductAddOn, type ProductAvailability, type ProductStock, type ProductTimeProfile, type ProductType, type ProductVariant, type ProductVariantValue, type ProductWithDetails, type ProductWithPrice, QueryBuilder, type QueryRequest, type RefundOrderInput, type ReminderMethod, type ReminderSettings, type RequestOtpInput, type RescheduleBookingInput, type ResourceAssignment, type ResourceAvailabilityException, type ResourceAvailabilityRule, type ResourceType, type ResponseMetadata, type Result, type RevokeAllSessionsResult, type RevokeSessionResult, type Room, type SalesChannel, type SchedulingMetadata, type SchedulingResult, SchedulingService, type SearchOptions, type SelectedAddOnOption, type Service, type ServiceAvailabilityException, type ServiceAvailabilityParams, type ServiceAvailabilityResult, type ServiceAvailabilityRule, type ServiceCharge, type ServiceNotes, type ServiceScheduleRequest, type ServiceStaffRequirement, type ServiceStatus, type ServiceWithStaff, type Staff, type StaffAssignment, type StaffAvailabilityException, type StaffAvailabilityRule, type StaffBookingProfile, type StaffRole, type StaffScheduleItem, type Stock, type StockLevel, type StockOwnershipType, type StockStatus, type StorefrontBootstrap, type SubmitAuthorizationInput, type Table, type TableInfo, type TaxComponent, type TaxInfo, type TaxPathComponent, type TimeRange, type TimeRanges, type TimeSlot, type UICart, type UICartBusiness, type UICartCustomer, type UICartLocation, type UICartPricing, type UpdateAddressInput, type UpdateCartItemInput, type UpdateOrderStatusInput, type UpdateProfileInput, type VariantAxis, type VariantAxisSelection, type VariantAxisValue, type VariantAxisWithValues, type VariantDetails, type VariantDetailsDTO, type VariantDisplayAttribute, type VariantLocationAvailability, type VariantStock, type VariantStrategy, type VerifyOtpInput, categorizePaymentError, combine, combineObject, createCimplifyClient, detectMobileMoneyProvider, err, extractPriceInfo, flatMap, formatMoney, formatNumberCompact, formatPrice, formatPriceAdjustment, formatPriceCompact, formatProductPrice, fromPromise, generateIdempotencyKey, getBasePrice, getCurrencySymbol, getDiscountPercentage, getDisplayPrice, getMarkupPercentage, getOrElse, getProductCurrency, isCimplifyError, isErr, isOk, isOnSale, isRetryableError, mapError, mapResult, normalizePaymentResponse, normalizeStatusResponse, ok, parsePrice, parsePricePath, parsedPriceToPriceInfo, query, toNullable, tryCatch, unwrap };
|
|
3533
|
+
export { AUTHORIZATION_TYPE, AUTH_MUTATION, type AddOn, type AddOnDetails, type AddOnGroupDetails, type AddOnOption, type AddOnOptionDetails, type AddOnOptionPrice, type AddOnWithOptions, type AddToCartInput, type AddressData, type AdjustmentType, type AmountToPay, type ApiError, type ApiResponse, type AppliedDiscount, type AuthResponse, AuthService, type AuthStatus, type AuthorizationType, type AvailabilityCheck, type AvailabilityResult, type AvailableSlot, type BenefitType, type Booking, type BookingRequirementOverride, type BookingStatus, type BookingWithDetails, type BufferTimes, type Bundle, type BundleComponentData, type BundleComponentInfo, type BundlePriceType, type BundleProduct, type BundleSelectionData, type BundleSelectionInput, type BundleStoredSelection, type BundleSummary, type BundleWithDetails, type Business, type BusinessHours, type BusinessPreferences, BusinessService, type BusinessSettings, type BusinessType, type BusinessWithLocations, CHECKOUT_MODE, CHECKOUT_MUTATION, CHECKOUT_STEP, CURRENCY_SYMBOLS, type CancelBookingInput, type CancelOrderInput, type CancellationPolicy, type Cart, type CartAddOn, type CartChannel, type CartItem, type CartItemDetails, CartOperations, type CartStatus, type CartSummary, type CartTotals, CatalogueQueries, type Category, type CategoryInfo, type CategorySummary, type ChangePasswordInput, type CheckSlotAvailabilityInput, type CheckoutAddressInfo, type CheckoutCustomerInfo, type CheckoutFormData, type CheckoutInput, type CheckoutMode, CheckoutService as CheckoutOperations, type CheckoutOrderType, type CheckoutPaymentMethod, type CheckoutResult, CheckoutService, type CheckoutStep, type ChosenPrice, CimplifyClient, type CimplifyConfig, CimplifyError, type Collection, type CollectionProduct, type CollectionSummary, type ComponentGroup, type ComponentGroupWithComponents, type ComponentPriceBreakdown, type ComponentSelectionInput, type ComponentSourceType, type Composite, type CompositeComponent, type CompositePriceBreakdown, type CompositePriceResult, type CompositePricingMode, type CompositeSelectionData, type ComponentSelectionInput as CompositeSelectionInput, type CompositeStoredSelection, type CompositeWithDetails, type ContactType, type CreateAddressInput, type CreateMobileMoneyInput, type Currency, type Customer, type CustomerAddress, type CustomerLinkPreferences, type CustomerMobileMoney, type CustomerServicePreferences, DEFAULT_COUNTRY, DEFAULT_CURRENCY, type DayAvailability, type DepositResult, type DepositType, type DeviceType, type DigitalProductType, type DiscountBreakdown, type DiscountDetails, type DisplayAddOn, type DisplayAddOnOption, type DisplayCart, type DisplayCartItem, type EnrollAndLinkOrderInput, type EnrollAndLinkOrderResult, type EnrollmentData, type Err, ErrorCode, type ErrorCodeType, type FeeBearerType, type FormatCompactOptions, type FormatPriceOptions, type FulfillmentLink, type FulfillmentStatus, type FulfillmentType, type GetAvailableSlotsInput, type GetOrdersOptions, type GetProductsOptions, type GroupPricingBehavior, type InitializePaymentResult, InventoryService, type InventorySummary, type InventoryType, type KitchenOrderItem, type KitchenOrderResult, LINK_MUTATION, LINK_QUERY, type LineConfiguration, type LineItem, type LineType, type LinkData, type LinkEnrollResult, LinkService, type LinkSession, type LinkStatusResult, type LiteBootstrap, LiteService, type Location, type LocationAppointment, type LocationProductPrice, type LocationStock, type LocationTaxBehavior, type LocationTaxOverrides, type LocationTimeProfile, type LocationWithDetails, MOBILE_MONEY_PROVIDER, MOBILE_MONEY_PROVIDERS, type MobileMoneyData, type MobileMoneyDetails, type MobileMoneyProvider, type Money, type MutationRequest, ORDER_MUTATION, ORDER_TYPE, type ObservabilityHooks, type Ok, type Order, type OrderChannel, type OrderFilter, type OrderFulfillmentSummary, type OrderGroup, type OrderGroupDetails, type OrderGroupPayment, type OrderGroupPaymentState, type OrderGroupPaymentSummary, type OrderHistory, type OrderLineState, type OrderLineStatus, type OrderPaymentEvent, OrderQueries, type OrderSplitDetail, type OrderStatus, type OtpResult, PAYMENT_METHOD, PAYMENT_MUTATION, PAYMENT_STATE, PICKUP_TIME_TYPE, type Pagination, type PaginationParams, type ParsedPrice, type Payment, type PaymentErrorDetails, type PaymentMethod, type PaymentMethodType, type PaymentProcessingState, type PaymentProvider, type PaymentResponse, type PaymentState, type PaymentStatus, type PaymentStatusResponse, type PickupTime, type PickupTimeType, type Price, type PriceAdjustment, type PriceDecisionPath, type PriceEntryType, type PriceInfo, type PricePathTaxInfo, type PriceSource, type PricingOverrides, type Product, type ProductAddOn, type ProductAvailability, type ProductStock, type ProductTimeProfile, type ProductType, type ProductVariant, type ProductVariantValue, type ProductWithDetails, type ProductWithPrice, QueryBuilder, type QueryRequest, type RefundOrderInput, type ReminderMethod, type ReminderSettings, type RequestContext, type RequestErrorEvent, type RequestOtpInput, type RequestStartEvent, type RequestSuccessEvent, type RescheduleBookingInput, type ResourceAssignment, type ResourceAvailabilityException, type ResourceAvailabilityRule, type ResourceType, type ResponseMetadata, type Result, type RetryEvent, type RevokeAllSessionsResult, type RevokeSessionResult, type Room, type SalesChannel, type SchedulingMetadata, type SchedulingResult, SchedulingService, type SearchOptions, type SelectedAddOnOption, type Service, type ServiceAvailabilityException, type ServiceAvailabilityParams, type ServiceAvailabilityResult, type ServiceAvailabilityRule, type ServiceCharge, type ServiceNotes, type ServiceScheduleRequest, type ServiceStaffRequirement, type ServiceStatus, type ServiceWithStaff, type SessionChangeEvent, type Staff, type StaffAssignment, type StaffAvailabilityException, type StaffAvailabilityRule, type StaffBookingProfile, type StaffRole, type StaffScheduleItem, type Stock, type StockLevel, type StockOwnershipType, type StockStatus, type StorefrontBootstrap, type SubmitAuthorizationInput, type Table, type TableInfo, type TaxComponent, type TaxInfo, type TaxPathComponent, type TimeRange, type TimeRanges, type TimeSlot, type UICart, type UICartBusiness, type UICartCustomer, type UICartLocation, type UICartPricing, type UpdateAddressInput, type UpdateCartItemInput, type UpdateOrderStatusInput, type UpdateProfileInput, type VariantAxis, type VariantAxisSelection, type VariantAxisValue, type VariantAxisWithValues, type VariantDetails, type VariantDetailsDTO, type VariantDisplayAttribute, type VariantLocationAvailability, type VariantStock, type VariantStrategy, type VerifyOtpInput, categorizePaymentError, combine, combineObject, createCimplifyClient, detectMobileMoneyProvider, err, extractPriceInfo, flatMap, formatMoney, formatNumberCompact, formatPrice, formatPriceAdjustment, formatPriceCompact, formatProductPrice, fromPromise, generateIdempotencyKey, getBasePrice, getCurrencySymbol, getDiscountPercentage, getDisplayPrice, getMarkupPercentage, getOrElse, getProductCurrency, isCimplifyError, isErr, isOk, isOnSale, isRetryableError, mapError, mapResult, normalizePaymentResponse, normalizeStatusResponse, ok, parsePrice, parsePricePath, parsedPriceToPriceInfo, query, toNullable, tryCatch, unwrap };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observability hooks for monitoring SDK behavior.
|
|
3
|
+
*
|
|
4
|
+
* These hooks allow you to plug in your own logging, metrics, and tracing
|
|
5
|
+
* without the SDK depending on any specific observability library.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const client = createCimplifyClient({
|
|
10
|
+
* hooks: {
|
|
11
|
+
* onRequestStart: ({ method, path }) => {
|
|
12
|
+
* console.log(`[SDK] ${method} ${path}`);
|
|
13
|
+
* },
|
|
14
|
+
* onRequestSuccess: ({ method, path, durationMs }) => {
|
|
15
|
+
* metrics.histogram('sdk.request.duration', durationMs, { method, path });
|
|
16
|
+
* },
|
|
17
|
+
* onRequestError: ({ method, path, error, retryCount }) => {
|
|
18
|
+
* Sentry.captureException(error, { extra: { method, path, retryCount } });
|
|
19
|
+
* },
|
|
20
|
+
* },
|
|
21
|
+
* });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
/** Context passed to request lifecycle hooks */
|
|
25
|
+
interface RequestContext {
|
|
26
|
+
/** HTTP method */
|
|
27
|
+
method: "GET" | "POST" | "DELETE";
|
|
28
|
+
/** Request path (e.g., "/api/q", "/api/m") */
|
|
29
|
+
path: string;
|
|
30
|
+
/** Full URL */
|
|
31
|
+
url: string;
|
|
32
|
+
/** Request body (for POST requests) */
|
|
33
|
+
body?: unknown;
|
|
34
|
+
/** Timestamp when request started */
|
|
35
|
+
startTime: number;
|
|
36
|
+
}
|
|
37
|
+
/** Passed when a request starts */
|
|
38
|
+
interface RequestStartEvent extends RequestContext {
|
|
39
|
+
}
|
|
40
|
+
/** Passed when a request succeeds */
|
|
41
|
+
interface RequestSuccessEvent extends RequestContext {
|
|
42
|
+
/** HTTP status code */
|
|
43
|
+
status: number;
|
|
44
|
+
/** Duration in milliseconds */
|
|
45
|
+
durationMs: number;
|
|
46
|
+
}
|
|
47
|
+
/** Passed when a request fails */
|
|
48
|
+
interface RequestErrorEvent extends RequestContext {
|
|
49
|
+
/** The error that occurred */
|
|
50
|
+
error: Error;
|
|
51
|
+
/** Duration in milliseconds */
|
|
52
|
+
durationMs: number;
|
|
53
|
+
/** Number of retries attempted before giving up */
|
|
54
|
+
retryCount: number;
|
|
55
|
+
/** Whether the error is retryable */
|
|
56
|
+
retryable: boolean;
|
|
57
|
+
}
|
|
58
|
+
/** Passed when a retry is about to happen */
|
|
59
|
+
interface RetryEvent extends RequestContext {
|
|
60
|
+
/** Which retry attempt (1, 2, 3...) */
|
|
61
|
+
attempt: number;
|
|
62
|
+
/** Delay before retry in milliseconds */
|
|
63
|
+
delayMs: number;
|
|
64
|
+
/** The error that triggered the retry */
|
|
65
|
+
error: Error;
|
|
66
|
+
}
|
|
67
|
+
/** Passed when session token changes */
|
|
68
|
+
interface SessionChangeEvent {
|
|
69
|
+
/** Previous token (null if none) */
|
|
70
|
+
previousToken: string | null;
|
|
71
|
+
/** New token (null if cleared) */
|
|
72
|
+
newToken: string | null;
|
|
73
|
+
/** Source of the change */
|
|
74
|
+
source: "response" | "manual" | "clear";
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Observability hooks configuration.
|
|
78
|
+
* All hooks are optional - only implement what you need.
|
|
79
|
+
*/
|
|
80
|
+
interface ObservabilityHooks {
|
|
81
|
+
/** Called when a request is about to be sent */
|
|
82
|
+
onRequestStart?: (event: RequestStartEvent) => void;
|
|
83
|
+
/** Called when a request completes successfully */
|
|
84
|
+
onRequestSuccess?: (event: RequestSuccessEvent) => void;
|
|
85
|
+
/** Called when a request fails (after all retries exhausted) */
|
|
86
|
+
onRequestError?: (event: RequestErrorEvent) => void;
|
|
87
|
+
/** Called before each retry attempt */
|
|
88
|
+
onRetry?: (event: RetryEvent) => void;
|
|
89
|
+
/** Called when session token changes */
|
|
90
|
+
onSessionChange?: (event: SessionChangeEvent) => void;
|
|
91
|
+
}
|
|
92
|
+
|
|
1
93
|
/** Decimal value represented as string for precision */
|
|
2
94
|
type Money = string;
|
|
3
95
|
/** Supported currencies */
|
|
@@ -2839,6 +2931,8 @@ interface CimplifyConfig {
|
|
|
2839
2931
|
maxRetries?: number;
|
|
2840
2932
|
/** Base delay between retries in milliseconds (default: 1000) */
|
|
2841
2933
|
retryDelay?: number;
|
|
2934
|
+
/** Observability hooks for logging, metrics, and tracing */
|
|
2935
|
+
hooks?: ObservabilityHooks;
|
|
2842
2936
|
}
|
|
2843
2937
|
declare class CimplifyClient {
|
|
2844
2938
|
private baseUrl;
|
|
@@ -2849,6 +2943,9 @@ declare class CimplifyClient {
|
|
|
2849
2943
|
private timeout;
|
|
2850
2944
|
private maxRetries;
|
|
2851
2945
|
private retryDelay;
|
|
2946
|
+
private hooks;
|
|
2947
|
+
/** In-flight request deduplication map */
|
|
2948
|
+
private inflightRequests;
|
|
2852
2949
|
private _catalogue?;
|
|
2853
2950
|
private _cart?;
|
|
2854
2951
|
private _checkout?;
|
|
@@ -2868,11 +2965,29 @@ declare class CimplifyClient {
|
|
|
2868
2965
|
private getHeaders;
|
|
2869
2966
|
private updateSessionFromResponse;
|
|
2870
2967
|
/**
|
|
2871
|
-
* Resilient fetch with timeout
|
|
2968
|
+
* Resilient fetch with timeout, automatic retries, and observability hooks.
|
|
2872
2969
|
* Uses exponential backoff: 1s, 2s, 4s between retries.
|
|
2873
2970
|
*/
|
|
2874
2971
|
private resilientFetch;
|
|
2972
|
+
/**
|
|
2973
|
+
* Generate a deduplication key for a request.
|
|
2974
|
+
* Same query + variables = same key = deduplicated.
|
|
2975
|
+
*/
|
|
2976
|
+
private getDedupeKey;
|
|
2977
|
+
/**
|
|
2978
|
+
* Execute a request with deduplication.
|
|
2979
|
+
* If an identical request is already in-flight, return the same promise.
|
|
2980
|
+
* This prevents redundant network calls when multiple components request the same data.
|
|
2981
|
+
*/
|
|
2982
|
+
private deduplicatedRequest;
|
|
2983
|
+
/**
|
|
2984
|
+
* Execute a query with deduplication.
|
|
2985
|
+
* Multiple identical queries made simultaneously will share a single network request.
|
|
2986
|
+
*/
|
|
2875
2987
|
query<T = unknown>(query: string, variables?: Record<string, unknown>): Promise<T>;
|
|
2988
|
+
/**
|
|
2989
|
+
* Execute a mutation. NOT deduplicated - mutations have side effects.
|
|
2990
|
+
*/
|
|
2876
2991
|
call<T = unknown>(method: string, args?: unknown): Promise<T>;
|
|
2877
2992
|
get<T = unknown>(path: string): Promise<T>;
|
|
2878
2993
|
post<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
@@ -3415,4 +3530,4 @@ interface ApiResponse<T> {
|
|
|
3415
3530
|
metadata?: ResponseMetadata;
|
|
3416
3531
|
}
|
|
3417
3532
|
|
|
3418
|
-
export { AUTHORIZATION_TYPE, AUTH_MUTATION, type AddOn, type AddOnDetails, type AddOnGroupDetails, type AddOnOption, type AddOnOptionDetails, type AddOnOptionPrice, type AddOnWithOptions, type AddToCartInput, type AddressData, type AdjustmentType, type AmountToPay, type ApiError, type ApiResponse, type AppliedDiscount, type AuthResponse, AuthService, type AuthStatus, type AuthorizationType, type AvailabilityCheck, type AvailabilityResult, type AvailableSlot, type BenefitType, type Booking, type BookingRequirementOverride, type BookingStatus, type BookingWithDetails, type BufferTimes, type Bundle, type BundleComponentData, type BundleComponentInfo, type BundlePriceType, type BundleProduct, type BundleSelectionData, type BundleSelectionInput, type BundleStoredSelection, type BundleSummary, type BundleWithDetails, type Business, type BusinessHours, type BusinessPreferences, BusinessService, type BusinessSettings, type BusinessType, type BusinessWithLocations, CHECKOUT_MODE, CHECKOUT_MUTATION, CHECKOUT_STEP, CURRENCY_SYMBOLS, type CancelBookingInput, type CancelOrderInput, type CancellationPolicy, type Cart, type CartAddOn, type CartChannel, type CartItem, type CartItemDetails, CartOperations, type CartStatus, type CartSummary, type CartTotals, CatalogueQueries, type Category, type CategoryInfo, type CategorySummary, type ChangePasswordInput, type CheckSlotAvailabilityInput, type CheckoutAddressInfo, type CheckoutCustomerInfo, type CheckoutFormData, type CheckoutInput, type CheckoutMode, CheckoutService as CheckoutOperations, type CheckoutOrderType, type CheckoutPaymentMethod, type CheckoutResult, CheckoutService, type CheckoutStep, type ChosenPrice, CimplifyClient, type CimplifyConfig, CimplifyError, type Collection, type CollectionProduct, type CollectionSummary, type ComponentGroup, type ComponentGroupWithComponents, type ComponentPriceBreakdown, type ComponentSelectionInput, type ComponentSourceType, type Composite, type CompositeComponent, type CompositePriceBreakdown, type CompositePriceResult, type CompositePricingMode, type CompositeSelectionData, type ComponentSelectionInput as CompositeSelectionInput, type CompositeStoredSelection, type CompositeWithDetails, type ContactType, type CreateAddressInput, type CreateMobileMoneyInput, type Currency, type Customer, type CustomerAddress, type CustomerLinkPreferences, type CustomerMobileMoney, type CustomerServicePreferences, DEFAULT_COUNTRY, DEFAULT_CURRENCY, type DayAvailability, type DepositResult, type DepositType, type DeviceType, type DigitalProductType, type DiscountBreakdown, type DiscountDetails, type DisplayAddOn, type DisplayAddOnOption, type DisplayCart, type DisplayCartItem, type EnrollAndLinkOrderInput, type EnrollAndLinkOrderResult, type EnrollmentData, type Err, ErrorCode, type ErrorCodeType, type FeeBearerType, type FormatCompactOptions, type FormatPriceOptions, type FulfillmentLink, type FulfillmentStatus, type FulfillmentType, type GetAvailableSlotsInput, type GetOrdersOptions, type GetProductsOptions, type GroupPricingBehavior, type InitializePaymentResult, InventoryService, type InventorySummary, type InventoryType, type KitchenOrderItem, type KitchenOrderResult, LINK_MUTATION, LINK_QUERY, type LineConfiguration, type LineItem, type LineType, type LinkData, type LinkEnrollResult, LinkService, type LinkSession, type LinkStatusResult, type LiteBootstrap, LiteService, type Location, type LocationAppointment, type LocationProductPrice, type LocationStock, type LocationTaxBehavior, type LocationTaxOverrides, type LocationTimeProfile, type LocationWithDetails, MOBILE_MONEY_PROVIDER, MOBILE_MONEY_PROVIDERS, type MobileMoneyData, type MobileMoneyDetails, type MobileMoneyProvider, type Money, type MutationRequest, ORDER_MUTATION, ORDER_TYPE, type Ok, type Order, type OrderChannel, type OrderFilter, type OrderFulfillmentSummary, type OrderGroup, type OrderGroupDetails, type OrderGroupPayment, type OrderGroupPaymentState, type OrderGroupPaymentSummary, type OrderHistory, type OrderLineState, type OrderLineStatus, type OrderPaymentEvent, OrderQueries, type OrderSplitDetail, type OrderStatus, type OtpResult, PAYMENT_METHOD, PAYMENT_MUTATION, PAYMENT_STATE, PICKUP_TIME_TYPE, type Pagination, type PaginationParams, type ParsedPrice, type Payment, type PaymentErrorDetails, type PaymentMethod, type PaymentMethodType, type PaymentProcessingState, type PaymentProvider, type PaymentResponse, type PaymentState, type PaymentStatus, type PaymentStatusResponse, type PickupTime, type PickupTimeType, type Price, type PriceAdjustment, type PriceDecisionPath, type PriceEntryType, type PriceInfo, type PricePathTaxInfo, type PriceSource, type PricingOverrides, type Product, type ProductAddOn, type ProductAvailability, type ProductStock, type ProductTimeProfile, type ProductType, type ProductVariant, type ProductVariantValue, type ProductWithDetails, type ProductWithPrice, QueryBuilder, type QueryRequest, type RefundOrderInput, type ReminderMethod, type ReminderSettings, type RequestOtpInput, type RescheduleBookingInput, type ResourceAssignment, type ResourceAvailabilityException, type ResourceAvailabilityRule, type ResourceType, type ResponseMetadata, type Result, type RevokeAllSessionsResult, type RevokeSessionResult, type Room, type SalesChannel, type SchedulingMetadata, type SchedulingResult, SchedulingService, type SearchOptions, type SelectedAddOnOption, type Service, type ServiceAvailabilityException, type ServiceAvailabilityParams, type ServiceAvailabilityResult, type ServiceAvailabilityRule, type ServiceCharge, type ServiceNotes, type ServiceScheduleRequest, type ServiceStaffRequirement, type ServiceStatus, type ServiceWithStaff, type Staff, type StaffAssignment, type StaffAvailabilityException, type StaffAvailabilityRule, type StaffBookingProfile, type StaffRole, type StaffScheduleItem, type Stock, type StockLevel, type StockOwnershipType, type StockStatus, type StorefrontBootstrap, type SubmitAuthorizationInput, type Table, type TableInfo, type TaxComponent, type TaxInfo, type TaxPathComponent, type TimeRange, type TimeRanges, type TimeSlot, type UICart, type UICartBusiness, type UICartCustomer, type UICartLocation, type UICartPricing, type UpdateAddressInput, type UpdateCartItemInput, type UpdateOrderStatusInput, type UpdateProfileInput, type VariantAxis, type VariantAxisSelection, type VariantAxisValue, type VariantAxisWithValues, type VariantDetails, type VariantDetailsDTO, type VariantDisplayAttribute, type VariantLocationAvailability, type VariantStock, type VariantStrategy, type VerifyOtpInput, categorizePaymentError, combine, combineObject, createCimplifyClient, detectMobileMoneyProvider, err, extractPriceInfo, flatMap, formatMoney, formatNumberCompact, formatPrice, formatPriceAdjustment, formatPriceCompact, formatProductPrice, fromPromise, generateIdempotencyKey, getBasePrice, getCurrencySymbol, getDiscountPercentage, getDisplayPrice, getMarkupPercentage, getOrElse, getProductCurrency, isCimplifyError, isErr, isOk, isOnSale, isRetryableError, mapError, mapResult, normalizePaymentResponse, normalizeStatusResponse, ok, parsePrice, parsePricePath, parsedPriceToPriceInfo, query, toNullable, tryCatch, unwrap };
|
|
3533
|
+
export { AUTHORIZATION_TYPE, AUTH_MUTATION, type AddOn, type AddOnDetails, type AddOnGroupDetails, type AddOnOption, type AddOnOptionDetails, type AddOnOptionPrice, type AddOnWithOptions, type AddToCartInput, type AddressData, type AdjustmentType, type AmountToPay, type ApiError, type ApiResponse, type AppliedDiscount, type AuthResponse, AuthService, type AuthStatus, type AuthorizationType, type AvailabilityCheck, type AvailabilityResult, type AvailableSlot, type BenefitType, type Booking, type BookingRequirementOverride, type BookingStatus, type BookingWithDetails, type BufferTimes, type Bundle, type BundleComponentData, type BundleComponentInfo, type BundlePriceType, type BundleProduct, type BundleSelectionData, type BundleSelectionInput, type BundleStoredSelection, type BundleSummary, type BundleWithDetails, type Business, type BusinessHours, type BusinessPreferences, BusinessService, type BusinessSettings, type BusinessType, type BusinessWithLocations, CHECKOUT_MODE, CHECKOUT_MUTATION, CHECKOUT_STEP, CURRENCY_SYMBOLS, type CancelBookingInput, type CancelOrderInput, type CancellationPolicy, type Cart, type CartAddOn, type CartChannel, type CartItem, type CartItemDetails, CartOperations, type CartStatus, type CartSummary, type CartTotals, CatalogueQueries, type Category, type CategoryInfo, type CategorySummary, type ChangePasswordInput, type CheckSlotAvailabilityInput, type CheckoutAddressInfo, type CheckoutCustomerInfo, type CheckoutFormData, type CheckoutInput, type CheckoutMode, CheckoutService as CheckoutOperations, type CheckoutOrderType, type CheckoutPaymentMethod, type CheckoutResult, CheckoutService, type CheckoutStep, type ChosenPrice, CimplifyClient, type CimplifyConfig, CimplifyError, type Collection, type CollectionProduct, type CollectionSummary, type ComponentGroup, type ComponentGroupWithComponents, type ComponentPriceBreakdown, type ComponentSelectionInput, type ComponentSourceType, type Composite, type CompositeComponent, type CompositePriceBreakdown, type CompositePriceResult, type CompositePricingMode, type CompositeSelectionData, type ComponentSelectionInput as CompositeSelectionInput, type CompositeStoredSelection, type CompositeWithDetails, type ContactType, type CreateAddressInput, type CreateMobileMoneyInput, type Currency, type Customer, type CustomerAddress, type CustomerLinkPreferences, type CustomerMobileMoney, type CustomerServicePreferences, DEFAULT_COUNTRY, DEFAULT_CURRENCY, type DayAvailability, type DepositResult, type DepositType, type DeviceType, type DigitalProductType, type DiscountBreakdown, type DiscountDetails, type DisplayAddOn, type DisplayAddOnOption, type DisplayCart, type DisplayCartItem, type EnrollAndLinkOrderInput, type EnrollAndLinkOrderResult, type EnrollmentData, type Err, ErrorCode, type ErrorCodeType, type FeeBearerType, type FormatCompactOptions, type FormatPriceOptions, type FulfillmentLink, type FulfillmentStatus, type FulfillmentType, type GetAvailableSlotsInput, type GetOrdersOptions, type GetProductsOptions, type GroupPricingBehavior, type InitializePaymentResult, InventoryService, type InventorySummary, type InventoryType, type KitchenOrderItem, type KitchenOrderResult, LINK_MUTATION, LINK_QUERY, type LineConfiguration, type LineItem, type LineType, type LinkData, type LinkEnrollResult, LinkService, type LinkSession, type LinkStatusResult, type LiteBootstrap, LiteService, type Location, type LocationAppointment, type LocationProductPrice, type LocationStock, type LocationTaxBehavior, type LocationTaxOverrides, type LocationTimeProfile, type LocationWithDetails, MOBILE_MONEY_PROVIDER, MOBILE_MONEY_PROVIDERS, type MobileMoneyData, type MobileMoneyDetails, type MobileMoneyProvider, type Money, type MutationRequest, ORDER_MUTATION, ORDER_TYPE, type ObservabilityHooks, type Ok, type Order, type OrderChannel, type OrderFilter, type OrderFulfillmentSummary, type OrderGroup, type OrderGroupDetails, type OrderGroupPayment, type OrderGroupPaymentState, type OrderGroupPaymentSummary, type OrderHistory, type OrderLineState, type OrderLineStatus, type OrderPaymentEvent, OrderQueries, type OrderSplitDetail, type OrderStatus, type OtpResult, PAYMENT_METHOD, PAYMENT_MUTATION, PAYMENT_STATE, PICKUP_TIME_TYPE, type Pagination, type PaginationParams, type ParsedPrice, type Payment, type PaymentErrorDetails, type PaymentMethod, type PaymentMethodType, type PaymentProcessingState, type PaymentProvider, type PaymentResponse, type PaymentState, type PaymentStatus, type PaymentStatusResponse, type PickupTime, type PickupTimeType, type Price, type PriceAdjustment, type PriceDecisionPath, type PriceEntryType, type PriceInfo, type PricePathTaxInfo, type PriceSource, type PricingOverrides, type Product, type ProductAddOn, type ProductAvailability, type ProductStock, type ProductTimeProfile, type ProductType, type ProductVariant, type ProductVariantValue, type ProductWithDetails, type ProductWithPrice, QueryBuilder, type QueryRequest, type RefundOrderInput, type ReminderMethod, type ReminderSettings, type RequestContext, type RequestErrorEvent, type RequestOtpInput, type RequestStartEvent, type RequestSuccessEvent, type RescheduleBookingInput, type ResourceAssignment, type ResourceAvailabilityException, type ResourceAvailabilityRule, type ResourceType, type ResponseMetadata, type Result, type RetryEvent, type RevokeAllSessionsResult, type RevokeSessionResult, type Room, type SalesChannel, type SchedulingMetadata, type SchedulingResult, SchedulingService, type SearchOptions, type SelectedAddOnOption, type Service, type ServiceAvailabilityException, type ServiceAvailabilityParams, type ServiceAvailabilityResult, type ServiceAvailabilityRule, type ServiceCharge, type ServiceNotes, type ServiceScheduleRequest, type ServiceStaffRequirement, type ServiceStatus, type ServiceWithStaff, type SessionChangeEvent, type Staff, type StaffAssignment, type StaffAvailabilityException, type StaffAvailabilityRule, type StaffBookingProfile, type StaffRole, type StaffScheduleItem, type Stock, type StockLevel, type StockOwnershipType, type StockStatus, type StorefrontBootstrap, type SubmitAuthorizationInput, type Table, type TableInfo, type TaxComponent, type TaxInfo, type TaxPathComponent, type TimeRange, type TimeRanges, type TimeSlot, type UICart, type UICartBusiness, type UICartCustomer, type UICartLocation, type UICartPricing, type UpdateAddressInput, type UpdateCartItemInput, type UpdateOrderStatusInput, type UpdateProfileInput, type VariantAxis, type VariantAxisSelection, type VariantAxisValue, type VariantAxisWithValues, type VariantDetails, type VariantDetailsDTO, type VariantDisplayAttribute, type VariantLocationAvailability, type VariantStock, type VariantStrategy, type VerifyOtpInput, categorizePaymentError, combine, combineObject, createCimplifyClient, detectMobileMoneyProvider, err, extractPriceInfo, flatMap, formatMoney, formatNumberCompact, formatPrice, formatPriceAdjustment, formatPriceCompact, formatProductPrice, fromPromise, generateIdempotencyKey, getBasePrice, getCurrencySymbol, getDiscountPercentage, getDisplayPrice, getMarkupPercentage, getOrElse, getProductCurrency, isCimplifyError, isErr, isOk, isOnSale, isRetryableError, mapError, mapResult, normalizePaymentResponse, normalizeStatusResponse, ok, parsePrice, parsePricePath, parsedPriceToPriceInfo, query, toNullable, tryCatch, unwrap };
|
package/dist/index.js
CHANGED
|
@@ -1469,6 +1469,8 @@ function deriveUrls() {
|
|
|
1469
1469
|
var CimplifyClient = class {
|
|
1470
1470
|
constructor(config = {}) {
|
|
1471
1471
|
this.sessionToken = null;
|
|
1472
|
+
/** In-flight request deduplication map */
|
|
1473
|
+
this.inflightRequests = /* @__PURE__ */ new Map();
|
|
1472
1474
|
this.publicKey = config.publicKey || "";
|
|
1473
1475
|
const urls = deriveUrls();
|
|
1474
1476
|
this.baseUrl = urls.baseUrl;
|
|
@@ -1477,18 +1479,31 @@ var CimplifyClient = class {
|
|
|
1477
1479
|
this.timeout = config.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
1478
1480
|
this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
1479
1481
|
this.retryDelay = config.retryDelay ?? DEFAULT_RETRY_DELAY_MS;
|
|
1482
|
+
this.hooks = config.hooks ?? {};
|
|
1480
1483
|
this.sessionToken = this.loadSessionToken();
|
|
1481
1484
|
}
|
|
1482
1485
|
getSessionToken() {
|
|
1483
1486
|
return this.sessionToken;
|
|
1484
1487
|
}
|
|
1485
1488
|
setSessionToken(token) {
|
|
1489
|
+
const previous = this.sessionToken;
|
|
1486
1490
|
this.sessionToken = token;
|
|
1487
1491
|
this.saveSessionToken(token);
|
|
1492
|
+
this.hooks.onSessionChange?.({
|
|
1493
|
+
previousToken: previous,
|
|
1494
|
+
newToken: token,
|
|
1495
|
+
source: "manual"
|
|
1496
|
+
});
|
|
1488
1497
|
}
|
|
1489
1498
|
clearSession() {
|
|
1499
|
+
const previous = this.sessionToken;
|
|
1490
1500
|
this.sessionToken = null;
|
|
1491
1501
|
this.saveSessionToken(null);
|
|
1502
|
+
this.hooks.onSessionChange?.({
|
|
1503
|
+
previousToken: previous,
|
|
1504
|
+
newToken: null,
|
|
1505
|
+
source: "clear"
|
|
1506
|
+
});
|
|
1492
1507
|
}
|
|
1493
1508
|
loadSessionToken() {
|
|
1494
1509
|
if (typeof window !== "undefined" && window.localStorage) {
|
|
@@ -1518,15 +1533,33 @@ var CimplifyClient = class {
|
|
|
1518
1533
|
updateSessionFromResponse(response) {
|
|
1519
1534
|
const newToken = response.headers.get(SESSION_TOKEN_HEADER);
|
|
1520
1535
|
if (newToken && newToken !== this.sessionToken) {
|
|
1536
|
+
const previous = this.sessionToken;
|
|
1521
1537
|
this.sessionToken = newToken;
|
|
1522
1538
|
this.saveSessionToken(newToken);
|
|
1539
|
+
this.hooks.onSessionChange?.({
|
|
1540
|
+
previousToken: previous,
|
|
1541
|
+
newToken,
|
|
1542
|
+
source: "response"
|
|
1543
|
+
});
|
|
1523
1544
|
}
|
|
1524
1545
|
}
|
|
1525
1546
|
/**
|
|
1526
|
-
* Resilient fetch with timeout
|
|
1547
|
+
* Resilient fetch with timeout, automatic retries, and observability hooks.
|
|
1527
1548
|
* Uses exponential backoff: 1s, 2s, 4s between retries.
|
|
1528
1549
|
*/
|
|
1529
1550
|
async resilientFetch(url, options) {
|
|
1551
|
+
const method = options.method || "GET";
|
|
1552
|
+
const path = url.replace(this.baseUrl, "").replace(this.linkApiUrl, "");
|
|
1553
|
+
const startTime = Date.now();
|
|
1554
|
+
let retryCount = 0;
|
|
1555
|
+
const context = {
|
|
1556
|
+
method,
|
|
1557
|
+
path,
|
|
1558
|
+
url,
|
|
1559
|
+
body: options.body ? JSON.parse(options.body) : void 0,
|
|
1560
|
+
startTime
|
|
1561
|
+
};
|
|
1562
|
+
this.hooks.onRequestStart?.(context);
|
|
1530
1563
|
let lastError;
|
|
1531
1564
|
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
1532
1565
|
try {
|
|
@@ -1538,39 +1571,113 @@ var CimplifyClient = class {
|
|
|
1538
1571
|
});
|
|
1539
1572
|
clearTimeout(timeoutId);
|
|
1540
1573
|
if (response.ok || response.status >= 400 && response.status < 500) {
|
|
1574
|
+
this.hooks.onRequestSuccess?.({
|
|
1575
|
+
...context,
|
|
1576
|
+
status: response.status,
|
|
1577
|
+
durationMs: Date.now() - startTime
|
|
1578
|
+
});
|
|
1541
1579
|
return response;
|
|
1542
1580
|
}
|
|
1543
1581
|
if (response.status >= 500 && attempt < this.maxRetries) {
|
|
1582
|
+
retryCount++;
|
|
1544
1583
|
const delay = this.retryDelay * Math.pow(2, attempt);
|
|
1584
|
+
this.hooks.onRetry?.({
|
|
1585
|
+
...context,
|
|
1586
|
+
attempt: retryCount,
|
|
1587
|
+
delayMs: delay,
|
|
1588
|
+
error: new Error(`Server error: ${response.status}`)
|
|
1589
|
+
});
|
|
1545
1590
|
await sleep(delay);
|
|
1546
1591
|
continue;
|
|
1547
1592
|
}
|
|
1593
|
+
this.hooks.onRequestSuccess?.({
|
|
1594
|
+
...context,
|
|
1595
|
+
status: response.status,
|
|
1596
|
+
durationMs: Date.now() - startTime
|
|
1597
|
+
});
|
|
1548
1598
|
return response;
|
|
1549
1599
|
} catch (error) {
|
|
1550
1600
|
lastError = error;
|
|
1551
|
-
|
|
1552
|
-
|
|
1601
|
+
const networkError = toNetworkError(error);
|
|
1602
|
+
const errorRetryable = isRetryable(error);
|
|
1603
|
+
if (!errorRetryable || attempt >= this.maxRetries) {
|
|
1604
|
+
this.hooks.onRequestError?.({
|
|
1605
|
+
...context,
|
|
1606
|
+
error: networkError,
|
|
1607
|
+
durationMs: Date.now() - startTime,
|
|
1608
|
+
retryCount,
|
|
1609
|
+
retryable: errorRetryable
|
|
1610
|
+
});
|
|
1611
|
+
throw networkError;
|
|
1553
1612
|
}
|
|
1613
|
+
retryCount++;
|
|
1554
1614
|
const delay = this.retryDelay * Math.pow(2, attempt);
|
|
1615
|
+
this.hooks.onRetry?.({
|
|
1616
|
+
...context,
|
|
1617
|
+
attempt: retryCount,
|
|
1618
|
+
delayMs: delay,
|
|
1619
|
+
error: networkError
|
|
1620
|
+
});
|
|
1555
1621
|
await sleep(delay);
|
|
1556
1622
|
}
|
|
1557
1623
|
}
|
|
1558
|
-
|
|
1624
|
+
const finalError = toNetworkError(lastError);
|
|
1625
|
+
this.hooks.onRequestError?.({
|
|
1626
|
+
...context,
|
|
1627
|
+
error: finalError,
|
|
1628
|
+
durationMs: Date.now() - startTime,
|
|
1629
|
+
retryCount,
|
|
1630
|
+
retryable: false
|
|
1631
|
+
});
|
|
1632
|
+
throw finalError;
|
|
1559
1633
|
}
|
|
1634
|
+
/**
|
|
1635
|
+
* Generate a deduplication key for a request.
|
|
1636
|
+
* Same query + variables = same key = deduplicated.
|
|
1637
|
+
*/
|
|
1638
|
+
getDedupeKey(type, payload) {
|
|
1639
|
+
return `${type}:${JSON.stringify(payload)}`;
|
|
1640
|
+
}
|
|
1641
|
+
/**
|
|
1642
|
+
* Execute a request with deduplication.
|
|
1643
|
+
* If an identical request is already in-flight, return the same promise.
|
|
1644
|
+
* This prevents redundant network calls when multiple components request the same data.
|
|
1645
|
+
*/
|
|
1646
|
+
async deduplicatedRequest(key, requestFn) {
|
|
1647
|
+
const existing = this.inflightRequests.get(key);
|
|
1648
|
+
if (existing) {
|
|
1649
|
+
return existing;
|
|
1650
|
+
}
|
|
1651
|
+
const request = requestFn().finally(() => {
|
|
1652
|
+
this.inflightRequests.delete(key);
|
|
1653
|
+
});
|
|
1654
|
+
this.inflightRequests.set(key, request);
|
|
1655
|
+
return request;
|
|
1656
|
+
}
|
|
1657
|
+
/**
|
|
1658
|
+
* Execute a query with deduplication.
|
|
1659
|
+
* Multiple identical queries made simultaneously will share a single network request.
|
|
1660
|
+
*/
|
|
1560
1661
|
async query(query2, variables) {
|
|
1561
1662
|
const body = { query: query2 };
|
|
1562
1663
|
if (variables) {
|
|
1563
1664
|
body.variables = variables;
|
|
1564
1665
|
}
|
|
1565
|
-
const
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1666
|
+
const key = this.getDedupeKey("query", body);
|
|
1667
|
+
return this.deduplicatedRequest(key, async () => {
|
|
1668
|
+
const response = await this.resilientFetch(`${this.baseUrl}/api/q`, {
|
|
1669
|
+
method: "POST",
|
|
1670
|
+
credentials: this.credentials,
|
|
1671
|
+
headers: this.getHeaders(),
|
|
1672
|
+
body: JSON.stringify(body)
|
|
1673
|
+
});
|
|
1674
|
+
this.updateSessionFromResponse(response);
|
|
1675
|
+
return this.handleResponse(response);
|
|
1570
1676
|
});
|
|
1571
|
-
this.updateSessionFromResponse(response);
|
|
1572
|
-
return this.handleResponse(response);
|
|
1573
1677
|
}
|
|
1678
|
+
/**
|
|
1679
|
+
* Execute a mutation. NOT deduplicated - mutations have side effects.
|
|
1680
|
+
*/
|
|
1574
1681
|
async call(method, args) {
|
|
1575
1682
|
const body = {
|
|
1576
1683
|
method,
|
|
@@ -1586,13 +1693,16 @@ var CimplifyClient = class {
|
|
|
1586
1693
|
return this.handleResponse(response);
|
|
1587
1694
|
}
|
|
1588
1695
|
async get(path) {
|
|
1589
|
-
const
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1696
|
+
const key = this.getDedupeKey("get", path);
|
|
1697
|
+
return this.deduplicatedRequest(key, async () => {
|
|
1698
|
+
const response = await this.resilientFetch(`${this.baseUrl}${path}`, {
|
|
1699
|
+
method: "GET",
|
|
1700
|
+
credentials: this.credentials,
|
|
1701
|
+
headers: this.getHeaders()
|
|
1702
|
+
});
|
|
1703
|
+
this.updateSessionFromResponse(response);
|
|
1704
|
+
return this.handleRestResponse(response);
|
|
1593
1705
|
});
|
|
1594
|
-
this.updateSessionFromResponse(response);
|
|
1595
|
-
return this.handleRestResponse(response);
|
|
1596
1706
|
}
|
|
1597
1707
|
async post(path, body) {
|
|
1598
1708
|
const response = await this.resilientFetch(`${this.baseUrl}${path}`, {
|
|
@@ -1614,13 +1724,16 @@ var CimplifyClient = class {
|
|
|
1614
1724
|
return this.handleRestResponse(response);
|
|
1615
1725
|
}
|
|
1616
1726
|
async linkGet(path) {
|
|
1617
|
-
const
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1727
|
+
const key = this.getDedupeKey("linkGet", path);
|
|
1728
|
+
return this.deduplicatedRequest(key, async () => {
|
|
1729
|
+
const response = await this.resilientFetch(`${this.linkApiUrl}${path}`, {
|
|
1730
|
+
method: "GET",
|
|
1731
|
+
credentials: this.credentials,
|
|
1732
|
+
headers: this.getHeaders()
|
|
1733
|
+
});
|
|
1734
|
+
this.updateSessionFromResponse(response);
|
|
1735
|
+
return this.handleRestResponse(response);
|
|
1621
1736
|
});
|
|
1622
|
-
this.updateSessionFromResponse(response);
|
|
1623
|
-
return this.handleRestResponse(response);
|
|
1624
1737
|
}
|
|
1625
1738
|
async linkPost(path, body) {
|
|
1626
1739
|
const response = await this.resilientFetch(`${this.linkApiUrl}${path}`, {
|
package/dist/index.mjs
CHANGED
|
@@ -1467,6 +1467,8 @@ function deriveUrls() {
|
|
|
1467
1467
|
var CimplifyClient = class {
|
|
1468
1468
|
constructor(config = {}) {
|
|
1469
1469
|
this.sessionToken = null;
|
|
1470
|
+
/** In-flight request deduplication map */
|
|
1471
|
+
this.inflightRequests = /* @__PURE__ */ new Map();
|
|
1470
1472
|
this.publicKey = config.publicKey || "";
|
|
1471
1473
|
const urls = deriveUrls();
|
|
1472
1474
|
this.baseUrl = urls.baseUrl;
|
|
@@ -1475,18 +1477,31 @@ var CimplifyClient = class {
|
|
|
1475
1477
|
this.timeout = config.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
1476
1478
|
this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
1477
1479
|
this.retryDelay = config.retryDelay ?? DEFAULT_RETRY_DELAY_MS;
|
|
1480
|
+
this.hooks = config.hooks ?? {};
|
|
1478
1481
|
this.sessionToken = this.loadSessionToken();
|
|
1479
1482
|
}
|
|
1480
1483
|
getSessionToken() {
|
|
1481
1484
|
return this.sessionToken;
|
|
1482
1485
|
}
|
|
1483
1486
|
setSessionToken(token) {
|
|
1487
|
+
const previous = this.sessionToken;
|
|
1484
1488
|
this.sessionToken = token;
|
|
1485
1489
|
this.saveSessionToken(token);
|
|
1490
|
+
this.hooks.onSessionChange?.({
|
|
1491
|
+
previousToken: previous,
|
|
1492
|
+
newToken: token,
|
|
1493
|
+
source: "manual"
|
|
1494
|
+
});
|
|
1486
1495
|
}
|
|
1487
1496
|
clearSession() {
|
|
1497
|
+
const previous = this.sessionToken;
|
|
1488
1498
|
this.sessionToken = null;
|
|
1489
1499
|
this.saveSessionToken(null);
|
|
1500
|
+
this.hooks.onSessionChange?.({
|
|
1501
|
+
previousToken: previous,
|
|
1502
|
+
newToken: null,
|
|
1503
|
+
source: "clear"
|
|
1504
|
+
});
|
|
1490
1505
|
}
|
|
1491
1506
|
loadSessionToken() {
|
|
1492
1507
|
if (typeof window !== "undefined" && window.localStorage) {
|
|
@@ -1516,15 +1531,33 @@ var CimplifyClient = class {
|
|
|
1516
1531
|
updateSessionFromResponse(response) {
|
|
1517
1532
|
const newToken = response.headers.get(SESSION_TOKEN_HEADER);
|
|
1518
1533
|
if (newToken && newToken !== this.sessionToken) {
|
|
1534
|
+
const previous = this.sessionToken;
|
|
1519
1535
|
this.sessionToken = newToken;
|
|
1520
1536
|
this.saveSessionToken(newToken);
|
|
1537
|
+
this.hooks.onSessionChange?.({
|
|
1538
|
+
previousToken: previous,
|
|
1539
|
+
newToken,
|
|
1540
|
+
source: "response"
|
|
1541
|
+
});
|
|
1521
1542
|
}
|
|
1522
1543
|
}
|
|
1523
1544
|
/**
|
|
1524
|
-
* Resilient fetch with timeout
|
|
1545
|
+
* Resilient fetch with timeout, automatic retries, and observability hooks.
|
|
1525
1546
|
* Uses exponential backoff: 1s, 2s, 4s between retries.
|
|
1526
1547
|
*/
|
|
1527
1548
|
async resilientFetch(url, options) {
|
|
1549
|
+
const method = options.method || "GET";
|
|
1550
|
+
const path = url.replace(this.baseUrl, "").replace(this.linkApiUrl, "");
|
|
1551
|
+
const startTime = Date.now();
|
|
1552
|
+
let retryCount = 0;
|
|
1553
|
+
const context = {
|
|
1554
|
+
method,
|
|
1555
|
+
path,
|
|
1556
|
+
url,
|
|
1557
|
+
body: options.body ? JSON.parse(options.body) : void 0,
|
|
1558
|
+
startTime
|
|
1559
|
+
};
|
|
1560
|
+
this.hooks.onRequestStart?.(context);
|
|
1528
1561
|
let lastError;
|
|
1529
1562
|
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
1530
1563
|
try {
|
|
@@ -1536,39 +1569,113 @@ var CimplifyClient = class {
|
|
|
1536
1569
|
});
|
|
1537
1570
|
clearTimeout(timeoutId);
|
|
1538
1571
|
if (response.ok || response.status >= 400 && response.status < 500) {
|
|
1572
|
+
this.hooks.onRequestSuccess?.({
|
|
1573
|
+
...context,
|
|
1574
|
+
status: response.status,
|
|
1575
|
+
durationMs: Date.now() - startTime
|
|
1576
|
+
});
|
|
1539
1577
|
return response;
|
|
1540
1578
|
}
|
|
1541
1579
|
if (response.status >= 500 && attempt < this.maxRetries) {
|
|
1580
|
+
retryCount++;
|
|
1542
1581
|
const delay = this.retryDelay * Math.pow(2, attempt);
|
|
1582
|
+
this.hooks.onRetry?.({
|
|
1583
|
+
...context,
|
|
1584
|
+
attempt: retryCount,
|
|
1585
|
+
delayMs: delay,
|
|
1586
|
+
error: new Error(`Server error: ${response.status}`)
|
|
1587
|
+
});
|
|
1543
1588
|
await sleep(delay);
|
|
1544
1589
|
continue;
|
|
1545
1590
|
}
|
|
1591
|
+
this.hooks.onRequestSuccess?.({
|
|
1592
|
+
...context,
|
|
1593
|
+
status: response.status,
|
|
1594
|
+
durationMs: Date.now() - startTime
|
|
1595
|
+
});
|
|
1546
1596
|
return response;
|
|
1547
1597
|
} catch (error) {
|
|
1548
1598
|
lastError = error;
|
|
1549
|
-
|
|
1550
|
-
|
|
1599
|
+
const networkError = toNetworkError(error);
|
|
1600
|
+
const errorRetryable = isRetryable(error);
|
|
1601
|
+
if (!errorRetryable || attempt >= this.maxRetries) {
|
|
1602
|
+
this.hooks.onRequestError?.({
|
|
1603
|
+
...context,
|
|
1604
|
+
error: networkError,
|
|
1605
|
+
durationMs: Date.now() - startTime,
|
|
1606
|
+
retryCount,
|
|
1607
|
+
retryable: errorRetryable
|
|
1608
|
+
});
|
|
1609
|
+
throw networkError;
|
|
1551
1610
|
}
|
|
1611
|
+
retryCount++;
|
|
1552
1612
|
const delay = this.retryDelay * Math.pow(2, attempt);
|
|
1613
|
+
this.hooks.onRetry?.({
|
|
1614
|
+
...context,
|
|
1615
|
+
attempt: retryCount,
|
|
1616
|
+
delayMs: delay,
|
|
1617
|
+
error: networkError
|
|
1618
|
+
});
|
|
1553
1619
|
await sleep(delay);
|
|
1554
1620
|
}
|
|
1555
1621
|
}
|
|
1556
|
-
|
|
1622
|
+
const finalError = toNetworkError(lastError);
|
|
1623
|
+
this.hooks.onRequestError?.({
|
|
1624
|
+
...context,
|
|
1625
|
+
error: finalError,
|
|
1626
|
+
durationMs: Date.now() - startTime,
|
|
1627
|
+
retryCount,
|
|
1628
|
+
retryable: false
|
|
1629
|
+
});
|
|
1630
|
+
throw finalError;
|
|
1557
1631
|
}
|
|
1632
|
+
/**
|
|
1633
|
+
* Generate a deduplication key for a request.
|
|
1634
|
+
* Same query + variables = same key = deduplicated.
|
|
1635
|
+
*/
|
|
1636
|
+
getDedupeKey(type, payload) {
|
|
1637
|
+
return `${type}:${JSON.stringify(payload)}`;
|
|
1638
|
+
}
|
|
1639
|
+
/**
|
|
1640
|
+
* Execute a request with deduplication.
|
|
1641
|
+
* If an identical request is already in-flight, return the same promise.
|
|
1642
|
+
* This prevents redundant network calls when multiple components request the same data.
|
|
1643
|
+
*/
|
|
1644
|
+
async deduplicatedRequest(key, requestFn) {
|
|
1645
|
+
const existing = this.inflightRequests.get(key);
|
|
1646
|
+
if (existing) {
|
|
1647
|
+
return existing;
|
|
1648
|
+
}
|
|
1649
|
+
const request = requestFn().finally(() => {
|
|
1650
|
+
this.inflightRequests.delete(key);
|
|
1651
|
+
});
|
|
1652
|
+
this.inflightRequests.set(key, request);
|
|
1653
|
+
return request;
|
|
1654
|
+
}
|
|
1655
|
+
/**
|
|
1656
|
+
* Execute a query with deduplication.
|
|
1657
|
+
* Multiple identical queries made simultaneously will share a single network request.
|
|
1658
|
+
*/
|
|
1558
1659
|
async query(query2, variables) {
|
|
1559
1660
|
const body = { query: query2 };
|
|
1560
1661
|
if (variables) {
|
|
1561
1662
|
body.variables = variables;
|
|
1562
1663
|
}
|
|
1563
|
-
const
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1664
|
+
const key = this.getDedupeKey("query", body);
|
|
1665
|
+
return this.deduplicatedRequest(key, async () => {
|
|
1666
|
+
const response = await this.resilientFetch(`${this.baseUrl}/api/q`, {
|
|
1667
|
+
method: "POST",
|
|
1668
|
+
credentials: this.credentials,
|
|
1669
|
+
headers: this.getHeaders(),
|
|
1670
|
+
body: JSON.stringify(body)
|
|
1671
|
+
});
|
|
1672
|
+
this.updateSessionFromResponse(response);
|
|
1673
|
+
return this.handleResponse(response);
|
|
1568
1674
|
});
|
|
1569
|
-
this.updateSessionFromResponse(response);
|
|
1570
|
-
return this.handleResponse(response);
|
|
1571
1675
|
}
|
|
1676
|
+
/**
|
|
1677
|
+
* Execute a mutation. NOT deduplicated - mutations have side effects.
|
|
1678
|
+
*/
|
|
1572
1679
|
async call(method, args) {
|
|
1573
1680
|
const body = {
|
|
1574
1681
|
method,
|
|
@@ -1584,13 +1691,16 @@ var CimplifyClient = class {
|
|
|
1584
1691
|
return this.handleResponse(response);
|
|
1585
1692
|
}
|
|
1586
1693
|
async get(path) {
|
|
1587
|
-
const
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1694
|
+
const key = this.getDedupeKey("get", path);
|
|
1695
|
+
return this.deduplicatedRequest(key, async () => {
|
|
1696
|
+
const response = await this.resilientFetch(`${this.baseUrl}${path}`, {
|
|
1697
|
+
method: "GET",
|
|
1698
|
+
credentials: this.credentials,
|
|
1699
|
+
headers: this.getHeaders()
|
|
1700
|
+
});
|
|
1701
|
+
this.updateSessionFromResponse(response);
|
|
1702
|
+
return this.handleRestResponse(response);
|
|
1591
1703
|
});
|
|
1592
|
-
this.updateSessionFromResponse(response);
|
|
1593
|
-
return this.handleRestResponse(response);
|
|
1594
1704
|
}
|
|
1595
1705
|
async post(path, body) {
|
|
1596
1706
|
const response = await this.resilientFetch(`${this.baseUrl}${path}`, {
|
|
@@ -1612,13 +1722,16 @@ var CimplifyClient = class {
|
|
|
1612
1722
|
return this.handleRestResponse(response);
|
|
1613
1723
|
}
|
|
1614
1724
|
async linkGet(path) {
|
|
1615
|
-
const
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1725
|
+
const key = this.getDedupeKey("linkGet", path);
|
|
1726
|
+
return this.deduplicatedRequest(key, async () => {
|
|
1727
|
+
const response = await this.resilientFetch(`${this.linkApiUrl}${path}`, {
|
|
1728
|
+
method: "GET",
|
|
1729
|
+
credentials: this.credentials,
|
|
1730
|
+
headers: this.getHeaders()
|
|
1731
|
+
});
|
|
1732
|
+
this.updateSessionFromResponse(response);
|
|
1733
|
+
return this.handleRestResponse(response);
|
|
1619
1734
|
});
|
|
1620
|
-
this.updateSessionFromResponse(response);
|
|
1621
|
-
return this.handleRestResponse(response);
|
|
1622
1735
|
}
|
|
1623
1736
|
async linkPost(path, body) {
|
|
1624
1737
|
const response = await this.resilientFetch(`${this.linkApiUrl}${path}`, {
|