@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.cjs +355 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +289 -1
- package/dist/index.d.ts +289 -1
- package/dist/index.js +355 -1
- package/dist/index.js.map +1 -1
- package/llms.txt +27 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2800,6 +2800,7 @@ function fromActivity(activity) {
|
|
|
2800
2800
|
name: activity.name,
|
|
2801
2801
|
type: activity.type,
|
|
2802
2802
|
color: activity.colorHex || "",
|
|
2803
|
+
currency: activity.currency || "",
|
|
2803
2804
|
tickets: (activity.resourceOptions ?? []).map((option) => ({
|
|
2804
2805
|
id: option.id,
|
|
2805
2806
|
name: option.name
|
|
@@ -2818,6 +2819,7 @@ function fromItemOptionNodes(nodes) {
|
|
|
2818
2819
|
name: node.item.name,
|
|
2819
2820
|
type: ADD_ON_PRODUCT_TYPE,
|
|
2820
2821
|
color: ADD_ON_COLOR,
|
|
2822
|
+
currency: "",
|
|
2821
2823
|
tickets: []
|
|
2822
2824
|
};
|
|
2823
2825
|
grouped.set(itemId, product);
|
|
@@ -2837,6 +2839,7 @@ var PRODUCTS_QUERY = `
|
|
|
2837
2839
|
deletedAt
|
|
2838
2840
|
type
|
|
2839
2841
|
colorHex
|
|
2842
|
+
currency
|
|
2840
2843
|
resourceOptions {
|
|
2841
2844
|
id
|
|
2842
2845
|
name
|
|
@@ -3063,6 +3066,325 @@ var PromoCodeService = class {
|
|
|
3063
3066
|
}
|
|
3064
3067
|
};
|
|
3065
3068
|
|
|
3069
|
+
// src/internal/peek/pricing/pricing-queries.ts
|
|
3070
|
+
var CREATE_PRICING_ENGINE_MUTATION = `
|
|
3071
|
+
mutation CreatePricingEngine($input: CreatePricingEngineInput!) {
|
|
3072
|
+
createPricingEngine(input: $input) {
|
|
3073
|
+
__typename
|
|
3074
|
+
... on CreatePricingEngineSuccess {
|
|
3075
|
+
engine {
|
|
3076
|
+
id
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
3079
|
+
... on InvalidDataError {
|
|
3080
|
+
message
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
}
|
|
3084
|
+
`;
|
|
3085
|
+
var UPDATE_PRICING_ENGINE_MUTATION = `
|
|
3086
|
+
mutation UpdatePricingEngine($input: UpdatePricingEngineInput!) {
|
|
3087
|
+
updatePricingEngine(input: $input) {
|
|
3088
|
+
__typename
|
|
3089
|
+
... on UpdatePricingEngineSuccess {
|
|
3090
|
+
engine {
|
|
3091
|
+
id
|
|
3092
|
+
name
|
|
3093
|
+
}
|
|
3094
|
+
}
|
|
3095
|
+
... on InvalidDataError {
|
|
3096
|
+
message
|
|
3097
|
+
}
|
|
3098
|
+
... on NotFoundError {
|
|
3099
|
+
id
|
|
3100
|
+
message
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3104
|
+
`;
|
|
3105
|
+
var DELETE_PRICING_ENGINE_MUTATION = `
|
|
3106
|
+
mutation DeletePricingEngine($id: ID!) {
|
|
3107
|
+
deletePricingEngine(id: $id) {
|
|
3108
|
+
__typename
|
|
3109
|
+
... on DeletePricingEngineSuccess {
|
|
3110
|
+
engine {
|
|
3111
|
+
id
|
|
3112
|
+
name
|
|
3113
|
+
}
|
|
3114
|
+
}
|
|
3115
|
+
... on NotFoundError {
|
|
3116
|
+
id
|
|
3117
|
+
message
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
}
|
|
3121
|
+
`;
|
|
3122
|
+
var UPSERT_PRICING_OVERRIDES_MUTATION = `
|
|
3123
|
+
mutation UpsertPricingOverridesActivityContexts($input: UpsertPricingOverridesActivityContextsInput!) {
|
|
3124
|
+
upsertPricingOverridesActivityContexts(input: $input) {
|
|
3125
|
+
__typename
|
|
3126
|
+
... on UpsertPricingOverridesActivityContextsSuccess {
|
|
3127
|
+
activityContexts {
|
|
3128
|
+
date
|
|
3129
|
+
activity {
|
|
3130
|
+
id
|
|
3131
|
+
name
|
|
3132
|
+
}
|
|
3133
|
+
engine {
|
|
3134
|
+
id
|
|
3135
|
+
name
|
|
3136
|
+
}
|
|
3137
|
+
overrides {
|
|
3138
|
+
order
|
|
3139
|
+
resourceOptions {
|
|
3140
|
+
resourceOption {
|
|
3141
|
+
id
|
|
3142
|
+
name
|
|
3143
|
+
}
|
|
3144
|
+
override {
|
|
3145
|
+
... on PricingOverridesActivityContextResourceOptionPriceOverride {
|
|
3146
|
+
price {
|
|
3147
|
+
amount
|
|
3148
|
+
currency
|
|
3149
|
+
}
|
|
3150
|
+
}
|
|
3151
|
+
... on PricingOverridesActivityContextResourceOptionPercentageAdjustmentOverride {
|
|
3152
|
+
percentageAdjustment
|
|
3153
|
+
}
|
|
3154
|
+
}
|
|
3155
|
+
}
|
|
3156
|
+
filters {
|
|
3157
|
+
__typename
|
|
3158
|
+
... on PricingOverridesActivityContextStartTimeRangeFilter {
|
|
3159
|
+
startTimeRange
|
|
3160
|
+
}
|
|
3161
|
+
... on PricingOverridesActivityContextSpotsTakenFilter {
|
|
3162
|
+
minSpots
|
|
3163
|
+
maxSpots
|
|
3164
|
+
}
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
}
|
|
3169
|
+
... on InvalidDataError {
|
|
3170
|
+
message
|
|
3171
|
+
}
|
|
3172
|
+
}
|
|
3173
|
+
}
|
|
3174
|
+
`;
|
|
3175
|
+
var SPOTS_TAKEN_FILTER_TYPENAME = "PricingOverridesActivityContextSpotsTakenFilter";
|
|
3176
|
+
function buildCreateEngineInput(input) {
|
|
3177
|
+
const activityIds = input.activityIds ?? [];
|
|
3178
|
+
return activityIds.length > 0 ? { name: input.name, filters: [{ activityIds }] } : { name: input.name };
|
|
3179
|
+
}
|
|
3180
|
+
function buildUpdateEngineInput(input) {
|
|
3181
|
+
const activityIds = input.activityIds ?? [];
|
|
3182
|
+
return {
|
|
3183
|
+
id: input.engineId,
|
|
3184
|
+
name: input.name,
|
|
3185
|
+
filters: activityIds.length > 0 ? [{ activityIds }] : []
|
|
3186
|
+
};
|
|
3187
|
+
}
|
|
3188
|
+
function buildUpsertInput(input) {
|
|
3189
|
+
return {
|
|
3190
|
+
engineId: input.engineId,
|
|
3191
|
+
dateRange: input.dateRange,
|
|
3192
|
+
activities: input.activities.map((activity) => ({
|
|
3193
|
+
activityId: activity.activityId,
|
|
3194
|
+
overrides: activity.overrides.map((override) => ({
|
|
3195
|
+
order: override.order,
|
|
3196
|
+
resourceOptions: override.resourceOptions.map(
|
|
3197
|
+
(option) => option.mode === "fixed" ? { id: option.id, price: option.price } : { id: option.id, percentageAdjustment: option.percentageAdjustment }
|
|
3198
|
+
),
|
|
3199
|
+
filters: override.filters
|
|
3200
|
+
}))
|
|
3201
|
+
}))
|
|
3202
|
+
};
|
|
3203
|
+
}
|
|
3204
|
+
function buildClearInput(input) {
|
|
3205
|
+
return {
|
|
3206
|
+
engineId: input.engineId,
|
|
3207
|
+
dateRange: input.dateRange,
|
|
3208
|
+
activities: input.activityIds.map((activityId) => ({
|
|
3209
|
+
activityId,
|
|
3210
|
+
overrides: []
|
|
3211
|
+
}))
|
|
3212
|
+
};
|
|
3213
|
+
}
|
|
3214
|
+
|
|
3215
|
+
// src/internal/peek/pricing/pricing-converter.ts
|
|
3216
|
+
function fromActivityContexts(contexts) {
|
|
3217
|
+
return contexts.map(fromActivityContext);
|
|
3218
|
+
}
|
|
3219
|
+
function fromActivityContext(context) {
|
|
3220
|
+
return {
|
|
3221
|
+
date: context.date,
|
|
3222
|
+
activity: { id: context.activity.id, name: context.activity.name },
|
|
3223
|
+
engine: { id: context.engine.id, name: context.engine.name },
|
|
3224
|
+
overrides: context.overrides.map(fromOverride)
|
|
3225
|
+
};
|
|
3226
|
+
}
|
|
3227
|
+
function fromOverride(override) {
|
|
3228
|
+
return {
|
|
3229
|
+
order: override.order,
|
|
3230
|
+
resourceOptions: override.resourceOptions.map(fromResourceOption),
|
|
3231
|
+
filters: override.filters.map(fromFilter)
|
|
3232
|
+
};
|
|
3233
|
+
}
|
|
3234
|
+
function fromResourceOption(option) {
|
|
3235
|
+
return {
|
|
3236
|
+
resourceOption: {
|
|
3237
|
+
id: option.resourceOption.id,
|
|
3238
|
+
name: option.resourceOption.name
|
|
3239
|
+
},
|
|
3240
|
+
override: fromResolvedOverride(option.override)
|
|
3241
|
+
};
|
|
3242
|
+
}
|
|
3243
|
+
function fromResolvedOverride(override) {
|
|
3244
|
+
return "price" in override ? { mode: "fixed", price: override.price } : { mode: "percentage", percentageAdjustment: override.percentageAdjustment };
|
|
3245
|
+
}
|
|
3246
|
+
function fromFilter(filter) {
|
|
3247
|
+
if (filter.__typename === SPOTS_TAKEN_FILTER_TYPENAME) {
|
|
3248
|
+
const spotsTaken = {};
|
|
3249
|
+
if (filter.minSpots !== null) spotsTaken.minSpots = filter.minSpots;
|
|
3250
|
+
if (filter.maxSpots !== null) spotsTaken.maxSpots = filter.maxSpots;
|
|
3251
|
+
return { spotsTaken };
|
|
3252
|
+
}
|
|
3253
|
+
return { startTimeRange: filter.startTimeRange };
|
|
3254
|
+
}
|
|
3255
|
+
|
|
3256
|
+
// src/internal/peek/pricing/pricing-service.ts
|
|
3257
|
+
var CURRENCY_PATTERN2 = /^[A-Z]{3}$/;
|
|
3258
|
+
var PERCENTAGE_FLOOR = -100;
|
|
3259
|
+
var ERROR_NAME_REQUIRED = "name is required";
|
|
3260
|
+
var ERROR_ENGINE_ID_REQUIRED = "engineId is required";
|
|
3261
|
+
var ERROR_DATE_RANGE_REQUIRED = "dateRange is required";
|
|
3262
|
+
var ERROR_ACTIVITIES_REQUIRED = "activities is required";
|
|
3263
|
+
var ERROR_ACTIVITY_ID_REQUIRED = "activityId is required";
|
|
3264
|
+
var ERROR_TICKET_ID_REQUIRED = "resource-option id is required";
|
|
3265
|
+
var ERROR_CURRENCY_FORMAT = "currency must be 3 uppercase letters";
|
|
3266
|
+
var ERROR_AMOUNT_NUMBER = "price amount must be a valid number";
|
|
3267
|
+
var ERROR_PERCENTAGE_NUMBER = "percentageAdjustment must be a valid number";
|
|
3268
|
+
var ERROR_PERCENTAGE_FLOOR = "percentageAdjustment must be greater than -100";
|
|
3269
|
+
var ERROR_NO_DATA = "pricing mutation returned no data";
|
|
3270
|
+
var PricingService = class {
|
|
3271
|
+
constructor(client) {
|
|
3272
|
+
this.client = client;
|
|
3273
|
+
}
|
|
3274
|
+
client;
|
|
3275
|
+
/**
|
|
3276
|
+
* Creates a pricing engine. Store the returned id and reuse it on every
|
|
3277
|
+
* subsequent override upsert. Throws on an InvalidDataError from Peek.
|
|
3278
|
+
*/
|
|
3279
|
+
async createEngine(input) {
|
|
3280
|
+
if (!input.name) throw new Error(ERROR_NAME_REQUIRED);
|
|
3281
|
+
const body = await this.client.request(
|
|
3282
|
+
SALES_ENDPOINT,
|
|
3283
|
+
CREATE_PRICING_ENGINE_MUTATION,
|
|
3284
|
+
{ input: buildCreateEngineInput(input) }
|
|
3285
|
+
);
|
|
3286
|
+
const result = body.data?.createPricingEngine;
|
|
3287
|
+
if (!result) throw new Error(ERROR_NO_DATA);
|
|
3288
|
+
if (result.__typename !== "CreatePricingEngineSuccess") {
|
|
3289
|
+
throw new Error(result.message);
|
|
3290
|
+
}
|
|
3291
|
+
return { id: result.engine.id };
|
|
3292
|
+
}
|
|
3293
|
+
/**
|
|
3294
|
+
* Updates a pricing engine's name and/or activity scope. Throws on an
|
|
3295
|
+
* InvalidDataError or NotFoundError from Peek.
|
|
3296
|
+
*/
|
|
3297
|
+
async updateEngine(input) {
|
|
3298
|
+
if (!input.engineId) throw new Error(ERROR_ENGINE_ID_REQUIRED);
|
|
3299
|
+
if (!input.name) throw new Error(ERROR_NAME_REQUIRED);
|
|
3300
|
+
const body = await this.client.request(
|
|
3301
|
+
SALES_ENDPOINT,
|
|
3302
|
+
UPDATE_PRICING_ENGINE_MUTATION,
|
|
3303
|
+
{ input: buildUpdateEngineInput(input) }
|
|
3304
|
+
);
|
|
3305
|
+
const result = body.data?.updatePricingEngine;
|
|
3306
|
+
if (!result) throw new Error(ERROR_NO_DATA);
|
|
3307
|
+
if (result.__typename !== "UpdatePricingEngineSuccess") {
|
|
3308
|
+
throw new Error(result.message);
|
|
3309
|
+
}
|
|
3310
|
+
return { id: result.engine.id, name: result.engine.name };
|
|
3311
|
+
}
|
|
3312
|
+
/**
|
|
3313
|
+
* Deletes a pricing engine. Idempotent — resolves whether the engine existed
|
|
3314
|
+
* or was already gone (Peek's NotFoundError is treated as success).
|
|
3315
|
+
*/
|
|
3316
|
+
async deleteEngine(engineId) {
|
|
3317
|
+
if (!engineId) throw new Error(ERROR_ENGINE_ID_REQUIRED);
|
|
3318
|
+
await this.client.request(
|
|
3319
|
+
SALES_ENDPOINT,
|
|
3320
|
+
DELETE_PRICING_ENGINE_MUTATION,
|
|
3321
|
+
{ id: engineId }
|
|
3322
|
+
);
|
|
3323
|
+
}
|
|
3324
|
+
/**
|
|
3325
|
+
* Upserts pricing overrides for the engine and date range in `input`. Returns
|
|
3326
|
+
* the resolved contexts Peek stored. Throws on an InvalidDataError from Peek.
|
|
3327
|
+
*/
|
|
3328
|
+
async upsertOverrides(input) {
|
|
3329
|
+
this.validateUpsertInput(input);
|
|
3330
|
+
return this.sendUpsert(buildUpsertInput(input));
|
|
3331
|
+
}
|
|
3332
|
+
/**
|
|
3333
|
+
* Clears all overrides for the given activities across a date range. This is
|
|
3334
|
+
* an upsert with empty overrides — never clear by omitting an activity.
|
|
3335
|
+
*/
|
|
3336
|
+
async clearOverrides(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.activityIds)) throw new Error(ERROR_ACTIVITIES_REQUIRED);
|
|
3340
|
+
for (const activityId of input.activityIds) {
|
|
3341
|
+
if (!activityId) throw new Error(ERROR_ACTIVITY_ID_REQUIRED);
|
|
3342
|
+
}
|
|
3343
|
+
return this.sendUpsert(buildClearInput(input));
|
|
3344
|
+
}
|
|
3345
|
+
async sendUpsert(rawInput) {
|
|
3346
|
+
const body = await this.client.request(
|
|
3347
|
+
SALES_ENDPOINT,
|
|
3348
|
+
UPSERT_PRICING_OVERRIDES_MUTATION,
|
|
3349
|
+
{ input: rawInput }
|
|
3350
|
+
);
|
|
3351
|
+
const result = body.data?.upsertPricingOverridesActivityContexts;
|
|
3352
|
+
if (!result) throw new Error(ERROR_NO_DATA);
|
|
3353
|
+
if (result.__typename !== "UpsertPricingOverridesActivityContextsSuccess") {
|
|
3354
|
+
throw new Error(result.message);
|
|
3355
|
+
}
|
|
3356
|
+
return { activityContexts: fromActivityContexts(result.activityContexts) };
|
|
3357
|
+
}
|
|
3358
|
+
validateUpsertInput(input) {
|
|
3359
|
+
if (!input.engineId) throw new Error(ERROR_ENGINE_ID_REQUIRED);
|
|
3360
|
+
if (!input.dateRange) throw new Error(ERROR_DATE_RANGE_REQUIRED);
|
|
3361
|
+
if (!Array.isArray(input.activities)) throw new Error(ERROR_ACTIVITIES_REQUIRED);
|
|
3362
|
+
for (const activity of input.activities) {
|
|
3363
|
+
if (!activity.activityId) throw new Error(ERROR_ACTIVITY_ID_REQUIRED);
|
|
3364
|
+
for (const override of activity.overrides) {
|
|
3365
|
+
for (const option of override.resourceOptions) {
|
|
3366
|
+
this.validateResourceOption(option);
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3369
|
+
}
|
|
3370
|
+
}
|
|
3371
|
+
validateResourceOption(option) {
|
|
3372
|
+
if (!option.id) throw new Error(ERROR_TICKET_ID_REQUIRED);
|
|
3373
|
+
if (option.mode === "fixed") {
|
|
3374
|
+
if (!CURRENCY_PATTERN2.test(option.price.currency)) {
|
|
3375
|
+
throw new Error(ERROR_CURRENCY_FORMAT);
|
|
3376
|
+
}
|
|
3377
|
+
if (Number.isNaN(Number.parseFloat(option.price.amount))) {
|
|
3378
|
+
throw new Error(ERROR_AMOUNT_NUMBER);
|
|
3379
|
+
}
|
|
3380
|
+
return;
|
|
3381
|
+
}
|
|
3382
|
+
const percentage = Number.parseFloat(option.percentageAdjustment);
|
|
3383
|
+
if (Number.isNaN(percentage)) throw new Error(ERROR_PERCENTAGE_NUMBER);
|
|
3384
|
+
if (percentage <= PERCENTAGE_FLOOR) throw new Error(ERROR_PERCENTAGE_FLOOR);
|
|
3385
|
+
}
|
|
3386
|
+
};
|
|
3387
|
+
|
|
3066
3388
|
// src/logger.ts
|
|
3067
3389
|
var noopLogger = {
|
|
3068
3390
|
info() {
|
|
@@ -3088,6 +3410,7 @@ var PeekAccessService = class {
|
|
|
3088
3410
|
timeslotService;
|
|
3089
3411
|
resellerService;
|
|
3090
3412
|
promoCodeService;
|
|
3413
|
+
pricingService;
|
|
3091
3414
|
dailyNoteService;
|
|
3092
3415
|
availabilityService;
|
|
3093
3416
|
membershipService;
|
|
@@ -3222,6 +3545,16 @@ var PeekAccessService = class {
|
|
|
3222
3545
|
}
|
|
3223
3546
|
return this.promoCodeService;
|
|
3224
3547
|
}
|
|
3548
|
+
/**
|
|
3549
|
+
* Returns the {@link PricingService} for this install, bound to the shared
|
|
3550
|
+
* authenticated transport. The instance is created lazily and reused.
|
|
3551
|
+
*/
|
|
3552
|
+
getPricingService() {
|
|
3553
|
+
if (!this.pricingService) {
|
|
3554
|
+
this.pricingService = new PricingService(this.client);
|
|
3555
|
+
}
|
|
3556
|
+
return this.pricingService;
|
|
3557
|
+
}
|
|
3225
3558
|
/**
|
|
3226
3559
|
* Returns the {@link DailyNoteService} for this install, bound to the shared
|
|
3227
3560
|
* authenticated transport. The instance is created lazily and reused.
|
|
@@ -3342,6 +3675,27 @@ var PeekAccessService = class {
|
|
|
3342
3675
|
createPromoCode(input) {
|
|
3343
3676
|
return this.getPromoCodeService().create(input);
|
|
3344
3677
|
}
|
|
3678
|
+
// ─── Pricing short-forms ──────────────────────────────────────────────────
|
|
3679
|
+
/** Create a pricing engine. Delegates to {@link PricingService.createEngine}. */
|
|
3680
|
+
createPricingEngine(input) {
|
|
3681
|
+
return this.getPricingService().createEngine(input);
|
|
3682
|
+
}
|
|
3683
|
+
/** Update a pricing engine. Delegates to {@link PricingService.updateEngine}. */
|
|
3684
|
+
updatePricingEngine(input) {
|
|
3685
|
+
return this.getPricingService().updateEngine(input);
|
|
3686
|
+
}
|
|
3687
|
+
/** Delete a pricing engine (idempotent). Delegates to {@link PricingService.deleteEngine}. */
|
|
3688
|
+
deletePricingEngine(engineId) {
|
|
3689
|
+
return this.getPricingService().deleteEngine(engineId);
|
|
3690
|
+
}
|
|
3691
|
+
/** Upsert pricing overrides. Delegates to {@link PricingService.upsertOverrides}. */
|
|
3692
|
+
upsertPricingOverrides(input) {
|
|
3693
|
+
return this.getPricingService().upsertOverrides(input);
|
|
3694
|
+
}
|
|
3695
|
+
/** Clear pricing overrides for a set of activities. Delegates to {@link PricingService.clearOverrides}. */
|
|
3696
|
+
clearPricingOverrides(input) {
|
|
3697
|
+
return this.getPricingService().clearOverrides(input);
|
|
3698
|
+
}
|
|
3345
3699
|
// ─── Daily-note short-forms ───────────────────────────────────────────────
|
|
3346
3700
|
/** Today's daily note. Delegates to {@link DailyNoteService.getToday}. */
|
|
3347
3701
|
getDailyNoteToday() {
|
|
@@ -3820,6 +4174,7 @@ exports.MembershipService = MembershipService;
|
|
|
3820
4174
|
exports.PeekAccessService = PeekAccessService;
|
|
3821
4175
|
exports.PeekGraphQLError = PeekGraphQLError;
|
|
3822
4176
|
exports.PiiAccessDisabledError = PiiAccessDisabledError;
|
|
4177
|
+
exports.PricingService = PricingService;
|
|
3823
4178
|
exports.ProductService = ProductService;
|
|
3824
4179
|
exports.PromoCodeService = PromoCodeService;
|
|
3825
4180
|
exports.RENTAL_PRODUCT_TYPE = RENTAL_PRODUCT_TYPE;
|