@peektravel/app-utilities 0.3.0 → 0.4.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.
- package/dist/index.cjs +157 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +158 -7
- package/dist/index.d.ts +158 -7
- package/dist/index.js +155 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1426,6 +1426,13 @@ declare class PromoCodeService {
|
|
|
1426
1426
|
create(input: CreatePromoCodeInput): Promise<CreatedPromoCode>;
|
|
1427
1427
|
}
|
|
1428
1428
|
|
|
1429
|
+
/**
|
|
1430
|
+
* Platform that embedded the app for this session. Verification is
|
|
1431
|
+
* brand-agnostic — one peek-auth JWT is minted for every platform — so this
|
|
1432
|
+
* claim is the single thing that identifies which platform a request came from.
|
|
1433
|
+
* New platforms extend this union.
|
|
1434
|
+
*/
|
|
1435
|
+
type PeekPlatform = "peek" | "cng" | "acme";
|
|
1429
1436
|
/** User context embedded in a Peek auth token. */
|
|
1430
1437
|
interface PeekAuthTokenUser {
|
|
1431
1438
|
/** User's email address. */
|
|
@@ -1438,6 +1445,8 @@ interface PeekAuthTokenUser {
|
|
|
1438
1445
|
locale: string;
|
|
1439
1446
|
/** User's display name. */
|
|
1440
1447
|
name: string;
|
|
1448
|
+
/** Which platform embedded the app for this session. */
|
|
1449
|
+
platform: PeekPlatform;
|
|
1441
1450
|
}
|
|
1442
1451
|
/** Claims returned by {@link PeekAccessService.verifyPeekAuthToken}. */
|
|
1443
1452
|
interface PeekAuthTokenClaims {
|
|
@@ -1659,7 +1668,7 @@ declare class PeekAccessService {
|
|
|
1659
1668
|
getReviews(productId: string, reviewCount?: number, reviewOffset?: number): Promise<Review[]>;
|
|
1660
1669
|
}
|
|
1661
1670
|
|
|
1662
|
-
interface RestClientOptions {
|
|
1671
|
+
interface RestClientOptions$1 {
|
|
1663
1672
|
/** Base URL of the backoffice gateway (no trailing slash). */
|
|
1664
1673
|
baseUrl: string;
|
|
1665
1674
|
/** App ID, used in the endpoint path. */
|
|
@@ -1675,9 +1684,9 @@ interface RestClientOptions {
|
|
|
1675
1684
|
/** `fetch` implementation to use. */
|
|
1676
1685
|
fetchFn: typeof fetch;
|
|
1677
1686
|
}
|
|
1678
|
-
declare class RestClient {
|
|
1687
|
+
declare class RestClient$1 {
|
|
1679
1688
|
private readonly options;
|
|
1680
|
-
constructor(options: RestClientOptions);
|
|
1689
|
+
constructor(options: RestClientOptions$1);
|
|
1681
1690
|
/**
|
|
1682
1691
|
* Issues a GET against the named REST path and returns the parsed JSON body.
|
|
1683
1692
|
* Retries on HTTP 429 per the configured backoff (via the shared
|
|
@@ -1737,7 +1746,7 @@ interface ActivityTicket {
|
|
|
1737
1746
|
|
|
1738
1747
|
declare class CngProductService {
|
|
1739
1748
|
private readonly client;
|
|
1740
|
-
constructor(client: RestClient);
|
|
1749
|
+
constructor(client: RestClient$1);
|
|
1741
1750
|
/**
|
|
1742
1751
|
* Returns every activity as a single flat list.
|
|
1743
1752
|
*
|
|
@@ -1788,6 +1797,133 @@ declare class CngAccessService {
|
|
|
1788
1797
|
getAllActivities(): Promise<Activity[]>;
|
|
1789
1798
|
}
|
|
1790
1799
|
|
|
1800
|
+
interface RestClientOptions {
|
|
1801
|
+
/** Base URL of the backoffice gateway (no trailing slash). */
|
|
1802
|
+
baseUrl: string;
|
|
1803
|
+
/** App ID, used in the endpoint path. */
|
|
1804
|
+
appId: string;
|
|
1805
|
+
/** Fixed extendable slug inserted between `appId` and the REST path. */
|
|
1806
|
+
extendableSlug: string;
|
|
1807
|
+
/** Supplies a valid bearer token for each request. */
|
|
1808
|
+
getToken: () => string;
|
|
1809
|
+
/** Backoff delays (ms) applied on successive HTTP 429 responses. */
|
|
1810
|
+
retryDelaysMs: number[];
|
|
1811
|
+
/** Diagnostics sink. */
|
|
1812
|
+
logger: Logger;
|
|
1813
|
+
/** `fetch` implementation to use. */
|
|
1814
|
+
fetchFn: typeof fetch;
|
|
1815
|
+
}
|
|
1816
|
+
declare class RestClient {
|
|
1817
|
+
private readonly options;
|
|
1818
|
+
constructor(options: RestClientOptions);
|
|
1819
|
+
/**
|
|
1820
|
+
* Issues a GET against the named REST path and returns the parsed JSON body.
|
|
1821
|
+
* Retries on HTTP 429 per the configured backoff (via the shared
|
|
1822
|
+
* {@link requestWithRetry} loop).
|
|
1823
|
+
*
|
|
1824
|
+
* @throws {AdminAccountRequiredError} on HTTP 418
|
|
1825
|
+
* @throws {RateLimitError} on HTTP 429 after retries are exhausted
|
|
1826
|
+
* @throws {AcmeApiError} on any other non-2xx response
|
|
1827
|
+
*/
|
|
1828
|
+
get<T>(path: string): Promise<T>;
|
|
1829
|
+
/** Reads the response body as JSON, falling back to raw text when unparseable. */
|
|
1830
|
+
private parseBody;
|
|
1831
|
+
private endpoint;
|
|
1832
|
+
private buildHeaders;
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
/**
|
|
1836
|
+
* The clean, transport-agnostic data model for an ACME event template.
|
|
1837
|
+
*
|
|
1838
|
+
* The ACME sibling of `../cng/product.ts`. Kept as a separate model because the
|
|
1839
|
+
* ACME gateway is a distinct backoffice, but the shape deliberately mirrors the
|
|
1840
|
+
* CNG `Activity` so consumers can treat every brand uniformly. The raw ACME
|
|
1841
|
+
* REST response types and the conversion logic live inside the package and are
|
|
1842
|
+
* never exposed here.
|
|
1843
|
+
*/
|
|
1844
|
+
/**
|
|
1845
|
+
* A bookable activity in an ACME account (an event template).
|
|
1846
|
+
*
|
|
1847
|
+
* `AcmeAccessService.getAllActivities()` returns these as a flat list, filtered
|
|
1848
|
+
* to published templates only. ACME does not expose tickets today, so
|
|
1849
|
+
* {@link AcmeActivity.tickets} is always an empty list.
|
|
1850
|
+
*/
|
|
1851
|
+
interface AcmeActivity {
|
|
1852
|
+
/** Stable unique identifier for the activity. */
|
|
1853
|
+
productId: string;
|
|
1854
|
+
/** Human-readable display name. */
|
|
1855
|
+
name: string;
|
|
1856
|
+
/** Product type reported by ACME (e.g. `"standard"`). */
|
|
1857
|
+
type: string;
|
|
1858
|
+
/**
|
|
1859
|
+
* Display color as a hex string (e.g. `"#00695c"`). Falls back to a neutral
|
|
1860
|
+
* gray (`"#d1d1d1"`) when no color is set.
|
|
1861
|
+
*/
|
|
1862
|
+
color: string;
|
|
1863
|
+
/** The bookable sub-options (tickets) of this activity. Always empty today. */
|
|
1864
|
+
tickets: AcmeActivityTicket[];
|
|
1865
|
+
}
|
|
1866
|
+
/** A single bookable sub-option (ticket) of an {@link AcmeActivity}. */
|
|
1867
|
+
interface AcmeActivityTicket {
|
|
1868
|
+
/** Unique identifier of the ticket. */
|
|
1869
|
+
id: string;
|
|
1870
|
+
/** Human-readable name of the ticket. */
|
|
1871
|
+
name: string;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
declare class AcmeProductService {
|
|
1875
|
+
private readonly client;
|
|
1876
|
+
constructor(client: RestClient);
|
|
1877
|
+
/**
|
|
1878
|
+
* Returns every published event template as a single flat list of activities.
|
|
1879
|
+
*
|
|
1880
|
+
* @example
|
|
1881
|
+
* ```ts
|
|
1882
|
+
* const activities = await acme.getProductService().getAllActivities();
|
|
1883
|
+
* ```
|
|
1884
|
+
*/
|
|
1885
|
+
getAllActivities(): Promise<AcmeActivity[]>;
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
/**
|
|
1889
|
+
* Configuration for an {@link AcmeAccessService} instance. ACME adds no fields
|
|
1890
|
+
* beyond {@link BaseAccessServiceConfig} — it authenticates on the app JWT
|
|
1891
|
+
* alone (no `pk-api-key`, so no `gatewayKey`).
|
|
1892
|
+
*/
|
|
1893
|
+
type AcmeAccessServiceConfig = BaseAccessServiceConfig;
|
|
1894
|
+
/**
|
|
1895
|
+
* Authenticated root entry point to the ACME backoffice REST gateway.
|
|
1896
|
+
*
|
|
1897
|
+
* @example
|
|
1898
|
+
* ```ts
|
|
1899
|
+
* import { AcmeAccessService, type AcmeActivity } from "@peektravel/app-utilities";
|
|
1900
|
+
*
|
|
1901
|
+
* const acme = new AcmeAccessService({
|
|
1902
|
+
* installId: "install-123",
|
|
1903
|
+
* jwtSecret: process.env.PEEK_APP_SECRET!,
|
|
1904
|
+
* issuer: process.env.PEEK_APP_ID!,
|
|
1905
|
+
* appId: process.env.PEEK_APP_ID!,
|
|
1906
|
+
* });
|
|
1907
|
+
*
|
|
1908
|
+
* const activities: AcmeActivity[] = await acme.getAllActivities();
|
|
1909
|
+
* ```
|
|
1910
|
+
*
|
|
1911
|
+
* @throws {Error} from the constructor when any required config field
|
|
1912
|
+
* (`installId`, `jwtSecret`, `issuer`, `appId`) is empty.
|
|
1913
|
+
*/
|
|
1914
|
+
declare class AcmeAccessService {
|
|
1915
|
+
private readonly client;
|
|
1916
|
+
private productService?;
|
|
1917
|
+
constructor(config: AcmeAccessServiceConfig);
|
|
1918
|
+
/**
|
|
1919
|
+
* Returns the {@link AcmeProductService} for this install, bound to the shared
|
|
1920
|
+
* authenticated transport. The instance is created lazily and reused.
|
|
1921
|
+
*/
|
|
1922
|
+
getProductService(): AcmeProductService;
|
|
1923
|
+
/** All activities. Delegates to {@link AcmeProductService.getAllActivities}. */
|
|
1924
|
+
getAllActivities(): Promise<AcmeActivity[]>;
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1791
1927
|
/**
|
|
1792
1928
|
* Public webhook surface for bookings.
|
|
1793
1929
|
*
|
|
@@ -1873,8 +2009,9 @@ declare function parseWaiverWebhook(payload: unknown): Waiver;
|
|
|
1873
2009
|
* GraphQL gateway (or the CNG REST gateway) so callers can branch on the error
|
|
1874
2010
|
* type rather than parsing messages.
|
|
1875
2011
|
*
|
|
1876
|
-
* `AdminAccountRequiredError` and `RateLimitError` are shared by
|
|
1877
|
-
* `PeekGraphQLError` is Peek-only; `CngApiError` is CNG-only
|
|
2012
|
+
* `AdminAccountRequiredError` and `RateLimitError` are shared by all gateways.
|
|
2013
|
+
* `PeekGraphQLError` is Peek-only; `CngApiError` is CNG-only; `AcmeApiError` is
|
|
2014
|
+
* ACME-only.
|
|
1878
2015
|
*/
|
|
1879
2016
|
/**
|
|
1880
2017
|
* Thrown when the gateway responds with HTTP 418, indicating the install is not
|
|
@@ -1916,5 +2053,19 @@ declare class CngApiError extends Error {
|
|
|
1916
2053
|
readonly body: unknown;
|
|
1917
2054
|
constructor(statusCode: number, body: unknown, message?: string);
|
|
1918
2055
|
}
|
|
2056
|
+
/**
|
|
2057
|
+
* Thrown when the ACME REST gateway returns a non-2xx response that is not one
|
|
2058
|
+
* of the specifically-handled statuses (418/429). The offending status is
|
|
2059
|
+
* preserved on {@link AcmeApiError.statusCode}, and the raw response body
|
|
2060
|
+
* (parsed JSON when possible, otherwise the raw text) on
|
|
2061
|
+
* {@link AcmeApiError.body}.
|
|
2062
|
+
*/
|
|
2063
|
+
declare class AcmeApiError extends Error {
|
|
2064
|
+
/** The HTTP status that triggered this error. */
|
|
2065
|
+
readonly statusCode: number;
|
|
2066
|
+
/** The raw response body (parsed JSON when possible, otherwise text). */
|
|
2067
|
+
readonly body: unknown;
|
|
2068
|
+
constructor(statusCode: number, body: unknown, message?: string);
|
|
2069
|
+
}
|
|
1919
2070
|
|
|
1920
|
-
export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, type AccountUser, AccountUserService, type AccountUserServiceOptions, type Activity, type ActivityTicket, type AddAddonInput, AdminAccountRequiredError, type Agent, type AssignGuideResult, type AssignedActivity, type AssignedResource, type Availability, AvailabilityService, type AvailabilityTime, type AvailabilityTimesQuery, type Booking, type BookingAddon, type BookingAddonMoney, type BookingAddonOption, type BookingAddons, type BookingAddonsMutationResult, type BookingPaymentsOnFile, type BookingReadOptions, type BookingSearchBy, BookingService, type BookingServiceOptions, type BookingTimeRangeSearch, type CancelBookingResult, type Channel, CngAccessService, type CngAccessServiceConfig, CngApiError, CngProductService, type CreateBookingGuest, type CreateBookingInput, type CreateBookingTicket, type CreatePromoCodeInput, type CreatedBooking, type CreatedPromoCode, type CustomQuestionAnswer, type DailyNote, DailyNoteService, type Duration, type Guest, type GuestMetadata, type Guide, type GuideAssignment, type InvoiceLinkResult, type Logger, type MakePaymentInput, type MakePaymentResult, type Membership, type MembershipPurchaseInput, MembershipService, type NoteMode, type Payment, type PaymentSource, PeekAccessService, type PeekAccessServiceConfig, type PeekAuthTokenClaims, type PeekAuthTokenUser, PeekGraphQLError, type Price, type Product, ProductService, type ProductServiceOptions, type ProductTicket, type PromoCode, type PromoCodeFixedAmount, PromoCodeService, type PromoCodeServiceOptions, type PurchasedMembership, RENTAL_PRODUCT_TYPE, RateLimitError, type RefundInput, type RefundResult, ResellerService, type Resource, type ResourceOptionQuantity, type ResourcePool, type ResourcePoolAccountUser, type ResourcePoolAssignment, type ResourcePoolMode, ResourcePoolService, type Review, ReviewService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateTimeslotResult, type Waiver, noopLogger, parseBookingWebhook, parseWaiverWebhook };
|
|
2071
|
+
export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, type AccountUser, AccountUserService, type AccountUserServiceOptions, AcmeAccessService, type AcmeAccessServiceConfig, type AcmeActivity, type AcmeActivityTicket, AcmeApiError, AcmeProductService, type Activity, type ActivityTicket, type AddAddonInput, AdminAccountRequiredError, type Agent, type AssignGuideResult, type AssignedActivity, type AssignedResource, type Availability, AvailabilityService, type AvailabilityTime, type AvailabilityTimesQuery, type Booking, type BookingAddon, type BookingAddonMoney, type BookingAddonOption, type BookingAddons, type BookingAddonsMutationResult, type BookingPaymentsOnFile, type BookingReadOptions, type BookingSearchBy, BookingService, type BookingServiceOptions, type BookingTimeRangeSearch, type CancelBookingResult, type Channel, CngAccessService, type CngAccessServiceConfig, CngApiError, CngProductService, type CreateBookingGuest, type CreateBookingInput, type CreateBookingTicket, type CreatePromoCodeInput, type CreatedBooking, type CreatedPromoCode, type CustomQuestionAnswer, type DailyNote, DailyNoteService, type Duration, type Guest, type GuestMetadata, type Guide, type GuideAssignment, type InvoiceLinkResult, type Logger, type MakePaymentInput, type MakePaymentResult, type Membership, type MembershipPurchaseInput, MembershipService, type NoteMode, type Payment, type PaymentSource, PeekAccessService, type PeekAccessServiceConfig, type PeekAuthTokenClaims, type PeekAuthTokenUser, PeekGraphQLError, type PeekPlatform, type Price, type Product, ProductService, type ProductServiceOptions, type ProductTicket, type PromoCode, type PromoCodeFixedAmount, PromoCodeService, type PromoCodeServiceOptions, type PurchasedMembership, RENTAL_PRODUCT_TYPE, RateLimitError, type RefundInput, type RefundResult, ResellerService, type Resource, type ResourceOptionQuantity, type ResourcePool, type ResourcePoolAccountUser, type ResourcePoolAssignment, type ResourcePoolMode, ResourcePoolService, type Review, ReviewService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateTimeslotResult, type Waiver, noopLogger, parseBookingWebhook, parseWaiverWebhook };
|
package/dist/index.d.ts
CHANGED
|
@@ -1426,6 +1426,13 @@ declare class PromoCodeService {
|
|
|
1426
1426
|
create(input: CreatePromoCodeInput): Promise<CreatedPromoCode>;
|
|
1427
1427
|
}
|
|
1428
1428
|
|
|
1429
|
+
/**
|
|
1430
|
+
* Platform that embedded the app for this session. Verification is
|
|
1431
|
+
* brand-agnostic — one peek-auth JWT is minted for every platform — so this
|
|
1432
|
+
* claim is the single thing that identifies which platform a request came from.
|
|
1433
|
+
* New platforms extend this union.
|
|
1434
|
+
*/
|
|
1435
|
+
type PeekPlatform = "peek" | "cng" | "acme";
|
|
1429
1436
|
/** User context embedded in a Peek auth token. */
|
|
1430
1437
|
interface PeekAuthTokenUser {
|
|
1431
1438
|
/** User's email address. */
|
|
@@ -1438,6 +1445,8 @@ interface PeekAuthTokenUser {
|
|
|
1438
1445
|
locale: string;
|
|
1439
1446
|
/** User's display name. */
|
|
1440
1447
|
name: string;
|
|
1448
|
+
/** Which platform embedded the app for this session. */
|
|
1449
|
+
platform: PeekPlatform;
|
|
1441
1450
|
}
|
|
1442
1451
|
/** Claims returned by {@link PeekAccessService.verifyPeekAuthToken}. */
|
|
1443
1452
|
interface PeekAuthTokenClaims {
|
|
@@ -1659,7 +1668,7 @@ declare class PeekAccessService {
|
|
|
1659
1668
|
getReviews(productId: string, reviewCount?: number, reviewOffset?: number): Promise<Review[]>;
|
|
1660
1669
|
}
|
|
1661
1670
|
|
|
1662
|
-
interface RestClientOptions {
|
|
1671
|
+
interface RestClientOptions$1 {
|
|
1663
1672
|
/** Base URL of the backoffice gateway (no trailing slash). */
|
|
1664
1673
|
baseUrl: string;
|
|
1665
1674
|
/** App ID, used in the endpoint path. */
|
|
@@ -1675,9 +1684,9 @@ interface RestClientOptions {
|
|
|
1675
1684
|
/** `fetch` implementation to use. */
|
|
1676
1685
|
fetchFn: typeof fetch;
|
|
1677
1686
|
}
|
|
1678
|
-
declare class RestClient {
|
|
1687
|
+
declare class RestClient$1 {
|
|
1679
1688
|
private readonly options;
|
|
1680
|
-
constructor(options: RestClientOptions);
|
|
1689
|
+
constructor(options: RestClientOptions$1);
|
|
1681
1690
|
/**
|
|
1682
1691
|
* Issues a GET against the named REST path and returns the parsed JSON body.
|
|
1683
1692
|
* Retries on HTTP 429 per the configured backoff (via the shared
|
|
@@ -1737,7 +1746,7 @@ interface ActivityTicket {
|
|
|
1737
1746
|
|
|
1738
1747
|
declare class CngProductService {
|
|
1739
1748
|
private readonly client;
|
|
1740
|
-
constructor(client: RestClient);
|
|
1749
|
+
constructor(client: RestClient$1);
|
|
1741
1750
|
/**
|
|
1742
1751
|
* Returns every activity as a single flat list.
|
|
1743
1752
|
*
|
|
@@ -1788,6 +1797,133 @@ declare class CngAccessService {
|
|
|
1788
1797
|
getAllActivities(): Promise<Activity[]>;
|
|
1789
1798
|
}
|
|
1790
1799
|
|
|
1800
|
+
interface RestClientOptions {
|
|
1801
|
+
/** Base URL of the backoffice gateway (no trailing slash). */
|
|
1802
|
+
baseUrl: string;
|
|
1803
|
+
/** App ID, used in the endpoint path. */
|
|
1804
|
+
appId: string;
|
|
1805
|
+
/** Fixed extendable slug inserted between `appId` and the REST path. */
|
|
1806
|
+
extendableSlug: string;
|
|
1807
|
+
/** Supplies a valid bearer token for each request. */
|
|
1808
|
+
getToken: () => string;
|
|
1809
|
+
/** Backoff delays (ms) applied on successive HTTP 429 responses. */
|
|
1810
|
+
retryDelaysMs: number[];
|
|
1811
|
+
/** Diagnostics sink. */
|
|
1812
|
+
logger: Logger;
|
|
1813
|
+
/** `fetch` implementation to use. */
|
|
1814
|
+
fetchFn: typeof fetch;
|
|
1815
|
+
}
|
|
1816
|
+
declare class RestClient {
|
|
1817
|
+
private readonly options;
|
|
1818
|
+
constructor(options: RestClientOptions);
|
|
1819
|
+
/**
|
|
1820
|
+
* Issues a GET against the named REST path and returns the parsed JSON body.
|
|
1821
|
+
* Retries on HTTP 429 per the configured backoff (via the shared
|
|
1822
|
+
* {@link requestWithRetry} loop).
|
|
1823
|
+
*
|
|
1824
|
+
* @throws {AdminAccountRequiredError} on HTTP 418
|
|
1825
|
+
* @throws {RateLimitError} on HTTP 429 after retries are exhausted
|
|
1826
|
+
* @throws {AcmeApiError} on any other non-2xx response
|
|
1827
|
+
*/
|
|
1828
|
+
get<T>(path: string): Promise<T>;
|
|
1829
|
+
/** Reads the response body as JSON, falling back to raw text when unparseable. */
|
|
1830
|
+
private parseBody;
|
|
1831
|
+
private endpoint;
|
|
1832
|
+
private buildHeaders;
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
/**
|
|
1836
|
+
* The clean, transport-agnostic data model for an ACME event template.
|
|
1837
|
+
*
|
|
1838
|
+
* The ACME sibling of `../cng/product.ts`. Kept as a separate model because the
|
|
1839
|
+
* ACME gateway is a distinct backoffice, but the shape deliberately mirrors the
|
|
1840
|
+
* CNG `Activity` so consumers can treat every brand uniformly. The raw ACME
|
|
1841
|
+
* REST response types and the conversion logic live inside the package and are
|
|
1842
|
+
* never exposed here.
|
|
1843
|
+
*/
|
|
1844
|
+
/**
|
|
1845
|
+
* A bookable activity in an ACME account (an event template).
|
|
1846
|
+
*
|
|
1847
|
+
* `AcmeAccessService.getAllActivities()` returns these as a flat list, filtered
|
|
1848
|
+
* to published templates only. ACME does not expose tickets today, so
|
|
1849
|
+
* {@link AcmeActivity.tickets} is always an empty list.
|
|
1850
|
+
*/
|
|
1851
|
+
interface AcmeActivity {
|
|
1852
|
+
/** Stable unique identifier for the activity. */
|
|
1853
|
+
productId: string;
|
|
1854
|
+
/** Human-readable display name. */
|
|
1855
|
+
name: string;
|
|
1856
|
+
/** Product type reported by ACME (e.g. `"standard"`). */
|
|
1857
|
+
type: string;
|
|
1858
|
+
/**
|
|
1859
|
+
* Display color as a hex string (e.g. `"#00695c"`). Falls back to a neutral
|
|
1860
|
+
* gray (`"#d1d1d1"`) when no color is set.
|
|
1861
|
+
*/
|
|
1862
|
+
color: string;
|
|
1863
|
+
/** The bookable sub-options (tickets) of this activity. Always empty today. */
|
|
1864
|
+
tickets: AcmeActivityTicket[];
|
|
1865
|
+
}
|
|
1866
|
+
/** A single bookable sub-option (ticket) of an {@link AcmeActivity}. */
|
|
1867
|
+
interface AcmeActivityTicket {
|
|
1868
|
+
/** Unique identifier of the ticket. */
|
|
1869
|
+
id: string;
|
|
1870
|
+
/** Human-readable name of the ticket. */
|
|
1871
|
+
name: string;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
declare class AcmeProductService {
|
|
1875
|
+
private readonly client;
|
|
1876
|
+
constructor(client: RestClient);
|
|
1877
|
+
/**
|
|
1878
|
+
* Returns every published event template as a single flat list of activities.
|
|
1879
|
+
*
|
|
1880
|
+
* @example
|
|
1881
|
+
* ```ts
|
|
1882
|
+
* const activities = await acme.getProductService().getAllActivities();
|
|
1883
|
+
* ```
|
|
1884
|
+
*/
|
|
1885
|
+
getAllActivities(): Promise<AcmeActivity[]>;
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
/**
|
|
1889
|
+
* Configuration for an {@link AcmeAccessService} instance. ACME adds no fields
|
|
1890
|
+
* beyond {@link BaseAccessServiceConfig} — it authenticates on the app JWT
|
|
1891
|
+
* alone (no `pk-api-key`, so no `gatewayKey`).
|
|
1892
|
+
*/
|
|
1893
|
+
type AcmeAccessServiceConfig = BaseAccessServiceConfig;
|
|
1894
|
+
/**
|
|
1895
|
+
* Authenticated root entry point to the ACME backoffice REST gateway.
|
|
1896
|
+
*
|
|
1897
|
+
* @example
|
|
1898
|
+
* ```ts
|
|
1899
|
+
* import { AcmeAccessService, type AcmeActivity } from "@peektravel/app-utilities";
|
|
1900
|
+
*
|
|
1901
|
+
* const acme = new AcmeAccessService({
|
|
1902
|
+
* installId: "install-123",
|
|
1903
|
+
* jwtSecret: process.env.PEEK_APP_SECRET!,
|
|
1904
|
+
* issuer: process.env.PEEK_APP_ID!,
|
|
1905
|
+
* appId: process.env.PEEK_APP_ID!,
|
|
1906
|
+
* });
|
|
1907
|
+
*
|
|
1908
|
+
* const activities: AcmeActivity[] = await acme.getAllActivities();
|
|
1909
|
+
* ```
|
|
1910
|
+
*
|
|
1911
|
+
* @throws {Error} from the constructor when any required config field
|
|
1912
|
+
* (`installId`, `jwtSecret`, `issuer`, `appId`) is empty.
|
|
1913
|
+
*/
|
|
1914
|
+
declare class AcmeAccessService {
|
|
1915
|
+
private readonly client;
|
|
1916
|
+
private productService?;
|
|
1917
|
+
constructor(config: AcmeAccessServiceConfig);
|
|
1918
|
+
/**
|
|
1919
|
+
* Returns the {@link AcmeProductService} for this install, bound to the shared
|
|
1920
|
+
* authenticated transport. The instance is created lazily and reused.
|
|
1921
|
+
*/
|
|
1922
|
+
getProductService(): AcmeProductService;
|
|
1923
|
+
/** All activities. Delegates to {@link AcmeProductService.getAllActivities}. */
|
|
1924
|
+
getAllActivities(): Promise<AcmeActivity[]>;
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1791
1927
|
/**
|
|
1792
1928
|
* Public webhook surface for bookings.
|
|
1793
1929
|
*
|
|
@@ -1873,8 +2009,9 @@ declare function parseWaiverWebhook(payload: unknown): Waiver;
|
|
|
1873
2009
|
* GraphQL gateway (or the CNG REST gateway) so callers can branch on the error
|
|
1874
2010
|
* type rather than parsing messages.
|
|
1875
2011
|
*
|
|
1876
|
-
* `AdminAccountRequiredError` and `RateLimitError` are shared by
|
|
1877
|
-
* `PeekGraphQLError` is Peek-only; `CngApiError` is CNG-only
|
|
2012
|
+
* `AdminAccountRequiredError` and `RateLimitError` are shared by all gateways.
|
|
2013
|
+
* `PeekGraphQLError` is Peek-only; `CngApiError` is CNG-only; `AcmeApiError` is
|
|
2014
|
+
* ACME-only.
|
|
1878
2015
|
*/
|
|
1879
2016
|
/**
|
|
1880
2017
|
* Thrown when the gateway responds with HTTP 418, indicating the install is not
|
|
@@ -1916,5 +2053,19 @@ declare class CngApiError extends Error {
|
|
|
1916
2053
|
readonly body: unknown;
|
|
1917
2054
|
constructor(statusCode: number, body: unknown, message?: string);
|
|
1918
2055
|
}
|
|
2056
|
+
/**
|
|
2057
|
+
* Thrown when the ACME REST gateway returns a non-2xx response that is not one
|
|
2058
|
+
* of the specifically-handled statuses (418/429). The offending status is
|
|
2059
|
+
* preserved on {@link AcmeApiError.statusCode}, and the raw response body
|
|
2060
|
+
* (parsed JSON when possible, otherwise the raw text) on
|
|
2061
|
+
* {@link AcmeApiError.body}.
|
|
2062
|
+
*/
|
|
2063
|
+
declare class AcmeApiError extends Error {
|
|
2064
|
+
/** The HTTP status that triggered this error. */
|
|
2065
|
+
readonly statusCode: number;
|
|
2066
|
+
/** The raw response body (parsed JSON when possible, otherwise text). */
|
|
2067
|
+
readonly body: unknown;
|
|
2068
|
+
constructor(statusCode: number, body: unknown, message?: string);
|
|
2069
|
+
}
|
|
1919
2070
|
|
|
1920
|
-
export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, type AccountUser, AccountUserService, type AccountUserServiceOptions, type Activity, type ActivityTicket, type AddAddonInput, AdminAccountRequiredError, type Agent, type AssignGuideResult, type AssignedActivity, type AssignedResource, type Availability, AvailabilityService, type AvailabilityTime, type AvailabilityTimesQuery, type Booking, type BookingAddon, type BookingAddonMoney, type BookingAddonOption, type BookingAddons, type BookingAddonsMutationResult, type BookingPaymentsOnFile, type BookingReadOptions, type BookingSearchBy, BookingService, type BookingServiceOptions, type BookingTimeRangeSearch, type CancelBookingResult, type Channel, CngAccessService, type CngAccessServiceConfig, CngApiError, CngProductService, type CreateBookingGuest, type CreateBookingInput, type CreateBookingTicket, type CreatePromoCodeInput, type CreatedBooking, type CreatedPromoCode, type CustomQuestionAnswer, type DailyNote, DailyNoteService, type Duration, type Guest, type GuestMetadata, type Guide, type GuideAssignment, type InvoiceLinkResult, type Logger, type MakePaymentInput, type MakePaymentResult, type Membership, type MembershipPurchaseInput, MembershipService, type NoteMode, type Payment, type PaymentSource, PeekAccessService, type PeekAccessServiceConfig, type PeekAuthTokenClaims, type PeekAuthTokenUser, PeekGraphQLError, type Price, type Product, ProductService, type ProductServiceOptions, type ProductTicket, type PromoCode, type PromoCodeFixedAmount, PromoCodeService, type PromoCodeServiceOptions, type PurchasedMembership, RENTAL_PRODUCT_TYPE, RateLimitError, type RefundInput, type RefundResult, ResellerService, type Resource, type ResourceOptionQuantity, type ResourcePool, type ResourcePoolAccountUser, type ResourcePoolAssignment, type ResourcePoolMode, ResourcePoolService, type Review, ReviewService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateTimeslotResult, type Waiver, noopLogger, parseBookingWebhook, parseWaiverWebhook };
|
|
2071
|
+
export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, type AccountUser, AccountUserService, type AccountUserServiceOptions, AcmeAccessService, type AcmeAccessServiceConfig, type AcmeActivity, type AcmeActivityTicket, AcmeApiError, AcmeProductService, type Activity, type ActivityTicket, type AddAddonInput, AdminAccountRequiredError, type Agent, type AssignGuideResult, type AssignedActivity, type AssignedResource, type Availability, AvailabilityService, type AvailabilityTime, type AvailabilityTimesQuery, type Booking, type BookingAddon, type BookingAddonMoney, type BookingAddonOption, type BookingAddons, type BookingAddonsMutationResult, type BookingPaymentsOnFile, type BookingReadOptions, type BookingSearchBy, BookingService, type BookingServiceOptions, type BookingTimeRangeSearch, type CancelBookingResult, type Channel, CngAccessService, type CngAccessServiceConfig, CngApiError, CngProductService, type CreateBookingGuest, type CreateBookingInput, type CreateBookingTicket, type CreatePromoCodeInput, type CreatedBooking, type CreatedPromoCode, type CustomQuestionAnswer, type DailyNote, DailyNoteService, type Duration, type Guest, type GuestMetadata, type Guide, type GuideAssignment, type InvoiceLinkResult, type Logger, type MakePaymentInput, type MakePaymentResult, type Membership, type MembershipPurchaseInput, MembershipService, type NoteMode, type Payment, type PaymentSource, PeekAccessService, type PeekAccessServiceConfig, type PeekAuthTokenClaims, type PeekAuthTokenUser, PeekGraphQLError, type PeekPlatform, type Price, type Product, ProductService, type ProductServiceOptions, type ProductTicket, type PromoCode, type PromoCodeFixedAmount, PromoCodeService, type PromoCodeServiceOptions, type PurchasedMembership, RENTAL_PRODUCT_TYPE, RateLimitError, type RefundInput, type RefundResult, ResellerService, type Resource, type ResourceOptionQuantity, type ResourcePool, type ResourcePoolAccountUser, type ResourcePoolAssignment, type ResourcePoolMode, ResourcePoolService, type Review, ReviewService, type Ticket, type Timeslot, type TimeslotFilter, TimeslotService, type UpdateTimeslotResult, type Waiver, noopLogger, parseBookingWebhook, parseWaiverWebhook };
|
package/dist/index.js
CHANGED
|
@@ -1858,6 +1858,18 @@ var CngApiError = class extends Error {
|
|
|
1858
1858
|
this.body = body;
|
|
1859
1859
|
}
|
|
1860
1860
|
};
|
|
1861
|
+
var AcmeApiError = class extends Error {
|
|
1862
|
+
/** The HTTP status that triggered this error. */
|
|
1863
|
+
statusCode;
|
|
1864
|
+
/** The raw response body (parsed JSON when possible, otherwise text). */
|
|
1865
|
+
body;
|
|
1866
|
+
constructor(statusCode, body, message) {
|
|
1867
|
+
super(message ?? `ACME request failed with HTTP ${statusCode}`);
|
|
1868
|
+
this.name = "AcmeApiError";
|
|
1869
|
+
this.statusCode = statusCode;
|
|
1870
|
+
this.body = body;
|
|
1871
|
+
}
|
|
1872
|
+
};
|
|
1861
1873
|
|
|
1862
1874
|
// src/internal/http-transport.ts
|
|
1863
1875
|
var RATE_LIMIT_STATUS = 429;
|
|
@@ -3063,7 +3075,8 @@ var PeekAccessService = class {
|
|
|
3063
3075
|
id: u.id,
|
|
3064
3076
|
isAdmin: u.is_admin,
|
|
3065
3077
|
locale: u.locale,
|
|
3066
|
-
name: u.name
|
|
3078
|
+
name: u.name,
|
|
3079
|
+
platform: u.platform
|
|
3067
3080
|
}
|
|
3068
3081
|
};
|
|
3069
3082
|
}
|
|
@@ -3483,6 +3496,146 @@ var CngAccessService = class {
|
|
|
3483
3496
|
}
|
|
3484
3497
|
};
|
|
3485
3498
|
|
|
3499
|
+
// src/internal/acme/endpoints.ts
|
|
3500
|
+
var ACME_EXTENDABLE_SLUG = "acme_backoffice_api@v1";
|
|
3501
|
+
var TEMPLATES_PATH = "v2/b2b/event/templates/names?pageSize=-1&page=1";
|
|
3502
|
+
|
|
3503
|
+
// src/models/acme/product.ts
|
|
3504
|
+
var ACME_ACTIVITY_TYPE = "standard";
|
|
3505
|
+
|
|
3506
|
+
// src/internal/acme/products/product-queries.ts
|
|
3507
|
+
var PUBLISHED_REVIEW_STATE = "published";
|
|
3508
|
+
|
|
3509
|
+
// src/internal/acme/products/product-converter.ts
|
|
3510
|
+
function fromTemplateNodes(nodes) {
|
|
3511
|
+
return nodes.filter((node) => node.reviewState === PUBLISHED_REVIEW_STATE).map(fromTemplateNode);
|
|
3512
|
+
}
|
|
3513
|
+
function fromTemplateNode(node) {
|
|
3514
|
+
return {
|
|
3515
|
+
productId: node.id || "",
|
|
3516
|
+
name: node.name || "",
|
|
3517
|
+
type: node.type || ACME_ACTIVITY_TYPE,
|
|
3518
|
+
color: node.colorCategory?.backgroundColor || "#d1d1d1",
|
|
3519
|
+
tickets: []
|
|
3520
|
+
};
|
|
3521
|
+
}
|
|
3522
|
+
|
|
3523
|
+
// src/internal/acme/products/product-service.ts
|
|
3524
|
+
var AcmeProductService = class {
|
|
3525
|
+
constructor(client) {
|
|
3526
|
+
this.client = client;
|
|
3527
|
+
}
|
|
3528
|
+
client;
|
|
3529
|
+
/**
|
|
3530
|
+
* Returns every published event template as a single flat list of activities.
|
|
3531
|
+
*
|
|
3532
|
+
* @example
|
|
3533
|
+
* ```ts
|
|
3534
|
+
* const activities = await acme.getProductService().getAllActivities();
|
|
3535
|
+
* ```
|
|
3536
|
+
*/
|
|
3537
|
+
async getAllActivities() {
|
|
3538
|
+
const body = await this.client.get(
|
|
3539
|
+
TEMPLATES_PATH
|
|
3540
|
+
);
|
|
3541
|
+
const nodes = Array.isArray(body) ? body : body?.list ?? [];
|
|
3542
|
+
return fromTemplateNodes(nodes ?? []);
|
|
3543
|
+
}
|
|
3544
|
+
};
|
|
3545
|
+
|
|
3546
|
+
// src/internal/acme/rest-client.ts
|
|
3547
|
+
var RestClient2 = class {
|
|
3548
|
+
constructor(options) {
|
|
3549
|
+
this.options = options;
|
|
3550
|
+
}
|
|
3551
|
+
options;
|
|
3552
|
+
/**
|
|
3553
|
+
* Issues a GET against the named REST path and returns the parsed JSON body.
|
|
3554
|
+
* Retries on HTTP 429 per the configured backoff (via the shared
|
|
3555
|
+
* {@link requestWithRetry} loop).
|
|
3556
|
+
*
|
|
3557
|
+
* @throws {AdminAccountRequiredError} on HTTP 418
|
|
3558
|
+
* @throws {RateLimitError} on HTTP 429 after retries are exhausted
|
|
3559
|
+
* @throws {AcmeApiError} on any other non-2xx response
|
|
3560
|
+
*/
|
|
3561
|
+
async get(path) {
|
|
3562
|
+
const { logger } = this.options;
|
|
3563
|
+
const url = this.endpoint(path);
|
|
3564
|
+
logger.info("Making ACME request", { url, path });
|
|
3565
|
+
return requestWithRetry(
|
|
3566
|
+
this.options,
|
|
3567
|
+
url,
|
|
3568
|
+
{ method: "GET", headers: this.buildHeaders() },
|
|
3569
|
+
path,
|
|
3570
|
+
async (response) => {
|
|
3571
|
+
const body = await this.parseBody(response);
|
|
3572
|
+
if (!response.ok) {
|
|
3573
|
+
logger.error(`ACME request failed with HTTP ${response.status}`, { url });
|
|
3574
|
+
throw new AcmeApiError(response.status, body);
|
|
3575
|
+
}
|
|
3576
|
+
return body;
|
|
3577
|
+
}
|
|
3578
|
+
);
|
|
3579
|
+
}
|
|
3580
|
+
/** Reads the response body as JSON, falling back to raw text when unparseable. */
|
|
3581
|
+
async parseBody(response) {
|
|
3582
|
+
const text = await response.text();
|
|
3583
|
+
try {
|
|
3584
|
+
return JSON.parse(text);
|
|
3585
|
+
} catch {
|
|
3586
|
+
return text;
|
|
3587
|
+
}
|
|
3588
|
+
}
|
|
3589
|
+
endpoint(path) {
|
|
3590
|
+
const { baseUrl, appId, extendableSlug } = this.options;
|
|
3591
|
+
return `${baseUrl}/${appId}/${extendableSlug}/${path}`;
|
|
3592
|
+
}
|
|
3593
|
+
buildHeaders() {
|
|
3594
|
+
return {
|
|
3595
|
+
"X-Peek-Auth": `Bearer ${this.options.getToken()}`,
|
|
3596
|
+
"Content-Type": "application/json"
|
|
3597
|
+
};
|
|
3598
|
+
}
|
|
3599
|
+
};
|
|
3600
|
+
|
|
3601
|
+
// src/acme-access-service.ts
|
|
3602
|
+
var DEFAULT_BASE_URL3 = "https://app-registry.peeklabs.com/installations-api";
|
|
3603
|
+
var AcmeAccessService = class {
|
|
3604
|
+
client;
|
|
3605
|
+
productService;
|
|
3606
|
+
constructor(config) {
|
|
3607
|
+
requireNonEmpty(config.installId, "installId", "AcmeAccessService");
|
|
3608
|
+
requireNonEmpty(config.jwtSecret, "jwtSecret", "AcmeAccessService");
|
|
3609
|
+
requireNonEmpty(config.issuer, "issuer", "AcmeAccessService");
|
|
3610
|
+
requireNonEmpty(config.appId, "appId", "AcmeAccessService");
|
|
3611
|
+
const logger = config.logger ?? noopLogger;
|
|
3612
|
+
const tokens = createTokenManager(config);
|
|
3613
|
+
this.client = new RestClient2({
|
|
3614
|
+
baseUrl: config.baseUrl ?? DEFAULT_BASE_URL3,
|
|
3615
|
+
appId: config.appId,
|
|
3616
|
+
extendableSlug: ACME_EXTENDABLE_SLUG,
|
|
3617
|
+
getToken: () => tokens.getToken(),
|
|
3618
|
+
retryDelaysMs: config.retryDelaysMs ?? DEFAULT_RETRY_DELAYS_MS,
|
|
3619
|
+
logger,
|
|
3620
|
+
fetchFn: config.fetch ?? globalThis.fetch
|
|
3621
|
+
});
|
|
3622
|
+
}
|
|
3623
|
+
/**
|
|
3624
|
+
* Returns the {@link AcmeProductService} for this install, bound to the shared
|
|
3625
|
+
* authenticated transport. The instance is created lazily and reused.
|
|
3626
|
+
*/
|
|
3627
|
+
getProductService() {
|
|
3628
|
+
if (!this.productService) {
|
|
3629
|
+
this.productService = new AcmeProductService(this.client);
|
|
3630
|
+
}
|
|
3631
|
+
return this.productService;
|
|
3632
|
+
}
|
|
3633
|
+
/** All activities. Delegates to {@link AcmeProductService.getAllActivities}. */
|
|
3634
|
+
getAllActivities() {
|
|
3635
|
+
return this.getProductService().getAllActivities();
|
|
3636
|
+
}
|
|
3637
|
+
};
|
|
3638
|
+
|
|
3486
3639
|
// src/internal/peek/bookings/booking-webhook.ts
|
|
3487
3640
|
var PAYLOAD_BOOKING_KEY = "booking";
|
|
3488
3641
|
var VALUE_OPEN_TOKEN = "value {";
|
|
@@ -3568,6 +3721,6 @@ function extractWaiverNode(payload) {
|
|
|
3568
3721
|
return record;
|
|
3569
3722
|
}
|
|
3570
3723
|
|
|
3571
|
-
export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, AccountUserService, AdminAccountRequiredError, AvailabilityService, BookingService, CngAccessService, CngApiError, CngProductService, DailyNoteService, MembershipService, PeekAccessService, PeekGraphQLError, ProductService, PromoCodeService, RENTAL_PRODUCT_TYPE, RateLimitError, ResellerService, ResourcePoolService, ReviewService, TimeslotService, noopLogger, parseBookingWebhook, parseWaiverWebhook };
|
|
3724
|
+
export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, AccountUserService, AcmeAccessService, AcmeApiError, AcmeProductService, AdminAccountRequiredError, AvailabilityService, BookingService, CngAccessService, CngApiError, CngProductService, DailyNoteService, MembershipService, PeekAccessService, PeekGraphQLError, ProductService, PromoCodeService, RENTAL_PRODUCT_TYPE, RateLimitError, ResellerService, ResourcePoolService, ReviewService, TimeslotService, noopLogger, parseBookingWebhook, parseWaiverWebhook };
|
|
3572
3725
|
//# sourceMappingURL=index.js.map
|
|
3573
3726
|
//# sourceMappingURL=index.js.map
|