@peektravel/app-utilities 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2778,6 +2778,7 @@ function fromActivity(activity) {
2778
2778
  name: activity.name,
2779
2779
  type: activity.type,
2780
2780
  color: activity.colorHex || "",
2781
+ currency: activity.currency || "",
2781
2782
  tickets: (activity.resourceOptions ?? []).map((option) => ({
2782
2783
  id: option.id,
2783
2784
  name: option.name
@@ -2796,6 +2797,7 @@ function fromItemOptionNodes(nodes) {
2796
2797
  name: node.item.name,
2797
2798
  type: ADD_ON_PRODUCT_TYPE,
2798
2799
  color: ADD_ON_COLOR,
2800
+ currency: "",
2799
2801
  tickets: []
2800
2802
  };
2801
2803
  grouped.set(itemId, product);
@@ -2815,6 +2817,7 @@ var PRODUCTS_QUERY = `
2815
2817
  deletedAt
2816
2818
  type
2817
2819
  colorHex
2820
+ currency
2818
2821
  resourceOptions {
2819
2822
  id
2820
2823
  name
@@ -3041,6 +3044,325 @@ var PromoCodeService = class {
3041
3044
  }
3042
3045
  };
3043
3046
 
3047
+ // src/internal/peek/pricing/pricing-queries.ts
3048
+ var CREATE_PRICING_ENGINE_MUTATION = `
3049
+ mutation CreatePricingEngine($input: CreatePricingEngineInput!) {
3050
+ createPricingEngine(input: $input) {
3051
+ __typename
3052
+ ... on CreatePricingEngineSuccess {
3053
+ engine {
3054
+ id
3055
+ }
3056
+ }
3057
+ ... on InvalidDataError {
3058
+ message
3059
+ }
3060
+ }
3061
+ }
3062
+ `;
3063
+ var UPDATE_PRICING_ENGINE_MUTATION = `
3064
+ mutation UpdatePricingEngine($input: UpdatePricingEngineInput!) {
3065
+ updatePricingEngine(input: $input) {
3066
+ __typename
3067
+ ... on UpdatePricingEngineSuccess {
3068
+ engine {
3069
+ id
3070
+ name
3071
+ }
3072
+ }
3073
+ ... on InvalidDataError {
3074
+ message
3075
+ }
3076
+ ... on NotFoundError {
3077
+ id
3078
+ message
3079
+ }
3080
+ }
3081
+ }
3082
+ `;
3083
+ var DELETE_PRICING_ENGINE_MUTATION = `
3084
+ mutation DeletePricingEngine($id: ID!) {
3085
+ deletePricingEngine(id: $id) {
3086
+ __typename
3087
+ ... on DeletePricingEngineSuccess {
3088
+ engine {
3089
+ id
3090
+ name
3091
+ }
3092
+ }
3093
+ ... on NotFoundError {
3094
+ id
3095
+ message
3096
+ }
3097
+ }
3098
+ }
3099
+ `;
3100
+ var UPSERT_PRICING_OVERRIDES_MUTATION = `
3101
+ mutation UpsertPricingOverridesActivityContexts($input: UpsertPricingOverridesActivityContextsInput!) {
3102
+ upsertPricingOverridesActivityContexts(input: $input) {
3103
+ __typename
3104
+ ... on UpsertPricingOverridesActivityContextsSuccess {
3105
+ activityContexts {
3106
+ date
3107
+ activity {
3108
+ id
3109
+ name
3110
+ }
3111
+ engine {
3112
+ id
3113
+ name
3114
+ }
3115
+ overrides {
3116
+ order
3117
+ resourceOptions {
3118
+ resourceOption {
3119
+ id
3120
+ name
3121
+ }
3122
+ override {
3123
+ ... on PricingOverridesActivityContextResourceOptionPriceOverride {
3124
+ price {
3125
+ amount
3126
+ currency
3127
+ }
3128
+ }
3129
+ ... on PricingOverridesActivityContextResourceOptionPercentageAdjustmentOverride {
3130
+ percentageAdjustment
3131
+ }
3132
+ }
3133
+ }
3134
+ filters {
3135
+ __typename
3136
+ ... on PricingOverridesActivityContextStartTimeRangeFilter {
3137
+ startTimeRange
3138
+ }
3139
+ ... on PricingOverridesActivityContextSpotsTakenFilter {
3140
+ minSpots
3141
+ maxSpots
3142
+ }
3143
+ }
3144
+ }
3145
+ }
3146
+ }
3147
+ ... on InvalidDataError {
3148
+ message
3149
+ }
3150
+ }
3151
+ }
3152
+ `;
3153
+ var SPOTS_TAKEN_FILTER_TYPENAME = "PricingOverridesActivityContextSpotsTakenFilter";
3154
+ function buildCreateEngineInput(input) {
3155
+ const activityIds = input.activityIds ?? [];
3156
+ return activityIds.length > 0 ? { name: input.name, filters: [{ activityIds }] } : { name: input.name };
3157
+ }
3158
+ function buildUpdateEngineInput(input) {
3159
+ const activityIds = input.activityIds ?? [];
3160
+ return {
3161
+ id: input.engineId,
3162
+ name: input.name,
3163
+ filters: activityIds.length > 0 ? [{ activityIds }] : []
3164
+ };
3165
+ }
3166
+ function buildUpsertInput(input) {
3167
+ return {
3168
+ engineId: input.engineId,
3169
+ dateRange: input.dateRange,
3170
+ activities: input.activities.map((activity) => ({
3171
+ activityId: activity.activityId,
3172
+ overrides: activity.overrides.map((override) => ({
3173
+ order: override.order,
3174
+ resourceOptions: override.resourceOptions.map(
3175
+ (option) => option.mode === "fixed" ? { id: option.id, price: option.price } : { id: option.id, percentageAdjustment: option.percentageAdjustment }
3176
+ ),
3177
+ filters: override.filters
3178
+ }))
3179
+ }))
3180
+ };
3181
+ }
3182
+ function buildClearInput(input) {
3183
+ return {
3184
+ engineId: input.engineId,
3185
+ dateRange: input.dateRange,
3186
+ activities: input.activityIds.map((activityId) => ({
3187
+ activityId,
3188
+ overrides: []
3189
+ }))
3190
+ };
3191
+ }
3192
+
3193
+ // src/internal/peek/pricing/pricing-converter.ts
3194
+ function fromActivityContexts(contexts) {
3195
+ return contexts.map(fromActivityContext);
3196
+ }
3197
+ function fromActivityContext(context) {
3198
+ return {
3199
+ date: context.date,
3200
+ activity: { id: context.activity.id, name: context.activity.name },
3201
+ engine: { id: context.engine.id, name: context.engine.name },
3202
+ overrides: context.overrides.map(fromOverride)
3203
+ };
3204
+ }
3205
+ function fromOverride(override) {
3206
+ return {
3207
+ order: override.order,
3208
+ resourceOptions: override.resourceOptions.map(fromResourceOption),
3209
+ filters: override.filters.map(fromFilter)
3210
+ };
3211
+ }
3212
+ function fromResourceOption(option) {
3213
+ return {
3214
+ resourceOption: {
3215
+ id: option.resourceOption.id,
3216
+ name: option.resourceOption.name
3217
+ },
3218
+ override: fromResolvedOverride(option.override)
3219
+ };
3220
+ }
3221
+ function fromResolvedOverride(override) {
3222
+ return "price" in override ? { mode: "fixed", price: override.price } : { mode: "percentage", percentageAdjustment: override.percentageAdjustment };
3223
+ }
3224
+ function fromFilter(filter) {
3225
+ if (filter.__typename === SPOTS_TAKEN_FILTER_TYPENAME) {
3226
+ const spotsTaken = {};
3227
+ if (filter.minSpots !== null) spotsTaken.minSpots = filter.minSpots;
3228
+ if (filter.maxSpots !== null) spotsTaken.maxSpots = filter.maxSpots;
3229
+ return { spotsTaken };
3230
+ }
3231
+ return { startTimeRange: filter.startTimeRange };
3232
+ }
3233
+
3234
+ // src/internal/peek/pricing/pricing-service.ts
3235
+ var CURRENCY_PATTERN2 = /^[A-Z]{3}$/;
3236
+ var PERCENTAGE_FLOOR = -100;
3237
+ var ERROR_NAME_REQUIRED = "name is required";
3238
+ var ERROR_ENGINE_ID_REQUIRED = "engineId is required";
3239
+ var ERROR_DATE_RANGE_REQUIRED = "dateRange is required";
3240
+ var ERROR_ACTIVITIES_REQUIRED = "activities is required";
3241
+ var ERROR_ACTIVITY_ID_REQUIRED = "activityId is required";
3242
+ var ERROR_TICKET_ID_REQUIRED = "resource-option id is required";
3243
+ var ERROR_CURRENCY_FORMAT = "currency must be 3 uppercase letters";
3244
+ var ERROR_AMOUNT_NUMBER = "price amount must be a valid number";
3245
+ var ERROR_PERCENTAGE_NUMBER = "percentageAdjustment must be a valid number";
3246
+ var ERROR_PERCENTAGE_FLOOR = "percentageAdjustment must be greater than -100";
3247
+ var ERROR_NO_DATA = "pricing mutation returned no data";
3248
+ var PricingService = class {
3249
+ constructor(client) {
3250
+ this.client = client;
3251
+ }
3252
+ client;
3253
+ /**
3254
+ * Creates a pricing engine. Store the returned id and reuse it on every
3255
+ * subsequent override upsert. Throws on an InvalidDataError from Peek.
3256
+ */
3257
+ async createEngine(input) {
3258
+ if (!input.name) throw new Error(ERROR_NAME_REQUIRED);
3259
+ const body = await this.client.request(
3260
+ SALES_ENDPOINT,
3261
+ CREATE_PRICING_ENGINE_MUTATION,
3262
+ { input: buildCreateEngineInput(input) }
3263
+ );
3264
+ const result = body.data?.createPricingEngine;
3265
+ if (!result) throw new Error(ERROR_NO_DATA);
3266
+ if (result.__typename !== "CreatePricingEngineSuccess") {
3267
+ throw new Error(result.message);
3268
+ }
3269
+ return { id: result.engine.id };
3270
+ }
3271
+ /**
3272
+ * Updates a pricing engine's name and/or activity scope. Throws on an
3273
+ * InvalidDataError or NotFoundError from Peek.
3274
+ */
3275
+ async updateEngine(input) {
3276
+ if (!input.engineId) throw new Error(ERROR_ENGINE_ID_REQUIRED);
3277
+ if (!input.name) throw new Error(ERROR_NAME_REQUIRED);
3278
+ const body = await this.client.request(
3279
+ SALES_ENDPOINT,
3280
+ UPDATE_PRICING_ENGINE_MUTATION,
3281
+ { input: buildUpdateEngineInput(input) }
3282
+ );
3283
+ const result = body.data?.updatePricingEngine;
3284
+ if (!result) throw new Error(ERROR_NO_DATA);
3285
+ if (result.__typename !== "UpdatePricingEngineSuccess") {
3286
+ throw new Error(result.message);
3287
+ }
3288
+ return { id: result.engine.id, name: result.engine.name };
3289
+ }
3290
+ /**
3291
+ * Deletes a pricing engine. Idempotent — resolves whether the engine existed
3292
+ * or was already gone (Peek's NotFoundError is treated as success).
3293
+ */
3294
+ async deleteEngine(engineId) {
3295
+ if (!engineId) throw new Error(ERROR_ENGINE_ID_REQUIRED);
3296
+ await this.client.request(
3297
+ SALES_ENDPOINT,
3298
+ DELETE_PRICING_ENGINE_MUTATION,
3299
+ { id: engineId }
3300
+ );
3301
+ }
3302
+ /**
3303
+ * Upserts pricing overrides for the engine and date range in `input`. Returns
3304
+ * the resolved contexts Peek stored. Throws on an InvalidDataError from Peek.
3305
+ */
3306
+ async upsertOverrides(input) {
3307
+ this.validateUpsertInput(input);
3308
+ return this.sendUpsert(buildUpsertInput(input));
3309
+ }
3310
+ /**
3311
+ * Clears all overrides for the given activities across a date range. This is
3312
+ * an upsert with empty overrides — never clear by omitting an activity.
3313
+ */
3314
+ async clearOverrides(input) {
3315
+ if (!input.engineId) throw new Error(ERROR_ENGINE_ID_REQUIRED);
3316
+ if (!input.dateRange) throw new Error(ERROR_DATE_RANGE_REQUIRED);
3317
+ if (!Array.isArray(input.activityIds)) throw new Error(ERROR_ACTIVITIES_REQUIRED);
3318
+ for (const activityId of input.activityIds) {
3319
+ if (!activityId) throw new Error(ERROR_ACTIVITY_ID_REQUIRED);
3320
+ }
3321
+ return this.sendUpsert(buildClearInput(input));
3322
+ }
3323
+ async sendUpsert(rawInput) {
3324
+ const body = await this.client.request(
3325
+ SALES_ENDPOINT,
3326
+ UPSERT_PRICING_OVERRIDES_MUTATION,
3327
+ { input: rawInput }
3328
+ );
3329
+ const result = body.data?.upsertPricingOverridesActivityContexts;
3330
+ if (!result) throw new Error(ERROR_NO_DATA);
3331
+ if (result.__typename !== "UpsertPricingOverridesActivityContextsSuccess") {
3332
+ throw new Error(result.message);
3333
+ }
3334
+ return { activityContexts: fromActivityContexts(result.activityContexts) };
3335
+ }
3336
+ validateUpsertInput(input) {
3337
+ if (!input.engineId) throw new Error(ERROR_ENGINE_ID_REQUIRED);
3338
+ if (!input.dateRange) throw new Error(ERROR_DATE_RANGE_REQUIRED);
3339
+ if (!Array.isArray(input.activities)) throw new Error(ERROR_ACTIVITIES_REQUIRED);
3340
+ for (const activity of input.activities) {
3341
+ if (!activity.activityId) throw new Error(ERROR_ACTIVITY_ID_REQUIRED);
3342
+ for (const override of activity.overrides) {
3343
+ for (const option of override.resourceOptions) {
3344
+ this.validateResourceOption(option);
3345
+ }
3346
+ }
3347
+ }
3348
+ }
3349
+ validateResourceOption(option) {
3350
+ if (!option.id) throw new Error(ERROR_TICKET_ID_REQUIRED);
3351
+ if (option.mode === "fixed") {
3352
+ if (!CURRENCY_PATTERN2.test(option.price.currency)) {
3353
+ throw new Error(ERROR_CURRENCY_FORMAT);
3354
+ }
3355
+ if (Number.isNaN(Number.parseFloat(option.price.amount))) {
3356
+ throw new Error(ERROR_AMOUNT_NUMBER);
3357
+ }
3358
+ return;
3359
+ }
3360
+ const percentage = Number.parseFloat(option.percentageAdjustment);
3361
+ if (Number.isNaN(percentage)) throw new Error(ERROR_PERCENTAGE_NUMBER);
3362
+ if (percentage <= PERCENTAGE_FLOOR) throw new Error(ERROR_PERCENTAGE_FLOOR);
3363
+ }
3364
+ };
3365
+
3044
3366
  // src/logger.ts
3045
3367
  var noopLogger = {
3046
3368
  info() {
@@ -3066,6 +3388,7 @@ var PeekAccessService = class {
3066
3388
  timeslotService;
3067
3389
  resellerService;
3068
3390
  promoCodeService;
3391
+ pricingService;
3069
3392
  dailyNoteService;
3070
3393
  availabilityService;
3071
3394
  membershipService;
@@ -3200,6 +3523,16 @@ var PeekAccessService = class {
3200
3523
  }
3201
3524
  return this.promoCodeService;
3202
3525
  }
3526
+ /**
3527
+ * Returns the {@link PricingService} for this install, bound to the shared
3528
+ * authenticated transport. The instance is created lazily and reused.
3529
+ */
3530
+ getPricingService() {
3531
+ if (!this.pricingService) {
3532
+ this.pricingService = new PricingService(this.client);
3533
+ }
3534
+ return this.pricingService;
3535
+ }
3203
3536
  /**
3204
3537
  * Returns the {@link DailyNoteService} for this install, bound to the shared
3205
3538
  * authenticated transport. The instance is created lazily and reused.
@@ -3320,6 +3653,27 @@ var PeekAccessService = class {
3320
3653
  createPromoCode(input) {
3321
3654
  return this.getPromoCodeService().create(input);
3322
3655
  }
3656
+ // ─── Pricing short-forms ──────────────────────────────────────────────────
3657
+ /** Create a pricing engine. Delegates to {@link PricingService.createEngine}. */
3658
+ createPricingEngine(input) {
3659
+ return this.getPricingService().createEngine(input);
3660
+ }
3661
+ /** Update a pricing engine. Delegates to {@link PricingService.updateEngine}. */
3662
+ updatePricingEngine(input) {
3663
+ return this.getPricingService().updateEngine(input);
3664
+ }
3665
+ /** Delete a pricing engine (idempotent). Delegates to {@link PricingService.deleteEngine}. */
3666
+ deletePricingEngine(engineId) {
3667
+ return this.getPricingService().deleteEngine(engineId);
3668
+ }
3669
+ /** Upsert pricing overrides. Delegates to {@link PricingService.upsertOverrides}. */
3670
+ upsertPricingOverrides(input) {
3671
+ return this.getPricingService().upsertOverrides(input);
3672
+ }
3673
+ /** Clear pricing overrides for a set of activities. Delegates to {@link PricingService.clearOverrides}. */
3674
+ clearPricingOverrides(input) {
3675
+ return this.getPricingService().clearOverrides(input);
3676
+ }
3323
3677
  // ─── Daily-note short-forms ───────────────────────────────────────────────
3324
3678
  /** Today's daily note. Delegates to {@link DailyNoteService.getToday}. */
3325
3679
  getDailyNoteToday() {
@@ -3781,6 +4135,6 @@ function extractWaiverNode(payload) {
3781
4135
  return record;
3782
4136
  }
3783
4137
 
3784
- export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, AccountUserService, AcmeAccessService, AcmeApiError, AcmeProductService, AdminAccountRequiredError, AvailabilityService, BookingService, CngAccessService, CngApiError, CngProductService, DailyNoteService, MembershipService, PeekAccessService, PeekGraphQLError, PiiAccessDisabledError, ProductService, PromoCodeService, RENTAL_PRODUCT_TYPE, RateLimitError, ResellerService, ResourcePoolService, ReviewService, TimeslotService, noopLogger, parseBookingWebhook, parseWaiverWebhook };
4138
+ export { ACTIVITY_PRODUCT_TYPE, ADD_ON_PRODUCT_TYPE, AccountUserService, AcmeAccessService, AcmeApiError, AcmeProductService, AdminAccountRequiredError, AvailabilityService, BookingService, CngAccessService, CngApiError, CngProductService, DailyNoteService, MembershipService, PeekAccessService, PeekGraphQLError, PiiAccessDisabledError, PricingService, ProductService, PromoCodeService, RENTAL_PRODUCT_TYPE, RateLimitError, ResellerService, ResourcePoolService, ReviewService, TimeslotService, noopLogger, parseBookingWebhook, parseWaiverWebhook };
3785
4139
  //# sourceMappingURL=index.js.map
3786
4140
  //# sourceMappingURL=index.js.map