@peektravel/app-utilities 0.9.1 → 0.9.2
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 +81 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -2
- package/dist/index.d.ts +55 -2
- package/dist/index.js +81 -11
- package/dist/index.js.map +1 -1
- package/llms.txt +10 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1112,6 +1112,9 @@ var QUESTION_TYPE_SELECT_ONE = "SELECT_ONE";
|
|
|
1112
1112
|
var QUESTION_TYPE_LOCATION = "LOCATION";
|
|
1113
1113
|
var QUESTION_ID_REGEX = /^cq_[a-z0-9]+$/;
|
|
1114
1114
|
var OPTION_ID_REGEX = /^cqao_[a-z0-9]+$/;
|
|
1115
|
+
function isCustomQuestionId(idOrText) {
|
|
1116
|
+
return QUESTION_ID_REGEX.test(idOrText);
|
|
1117
|
+
}
|
|
1115
1118
|
var CHECKBOX_TRUE = /* @__PURE__ */ new Set(["yes", "true"]);
|
|
1116
1119
|
var CHECKBOX_VALID = /* @__PURE__ */ new Set(["yes", "no", "true", "false"]);
|
|
1117
1120
|
var CHECKBOX_TEXT_TRUE = "Yes";
|
|
@@ -1129,10 +1132,13 @@ var errMissingRequired = (text, id) => `Custom question "${text}" (${id}) is req
|
|
|
1129
1132
|
function normalize(value) {
|
|
1130
1133
|
return value.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1131
1134
|
}
|
|
1132
|
-
function resolveQuestion(idOrText, questions) {
|
|
1135
|
+
function resolveQuestion(idOrText, questions, acceptAllIds) {
|
|
1133
1136
|
if (QUESTION_ID_REGEX.test(idOrText)) {
|
|
1134
1137
|
const byId = questions.find((question) => question.id === idOrText);
|
|
1135
|
-
if (!byId)
|
|
1138
|
+
if (!byId) {
|
|
1139
|
+
if (acceptAllIds) return null;
|
|
1140
|
+
throw new Error(errUnknownQuestionId(idOrText));
|
|
1141
|
+
}
|
|
1136
1142
|
return byId;
|
|
1137
1143
|
}
|
|
1138
1144
|
const target = normalize(idOrText);
|
|
@@ -1157,8 +1163,11 @@ function resolveOption(value, question) {
|
|
|
1157
1163
|
if (matches.length > 1) throw new Error(errAmbiguousOption(value, question.id));
|
|
1158
1164
|
return matches[0];
|
|
1159
1165
|
}
|
|
1160
|
-
function resolveOne(answer, questions) {
|
|
1161
|
-
const question = resolveQuestion(answer.questionIdOrText, questions);
|
|
1166
|
+
function resolveOne(answer, questions, acceptAllIds) {
|
|
1167
|
+
const question = resolveQuestion(answer.questionIdOrText, questions, acceptAllIds);
|
|
1168
|
+
if (!question) {
|
|
1169
|
+
return { questionId: answer.questionIdOrText, questionAnswerText: answer.value };
|
|
1170
|
+
}
|
|
1162
1171
|
if (question.perGuest) {
|
|
1163
1172
|
throw new Error(errPerGuestUnsupported(question.id));
|
|
1164
1173
|
}
|
|
@@ -1191,7 +1200,8 @@ function resolveOne(answer, questions) {
|
|
|
1191
1200
|
}
|
|
1192
1201
|
}
|
|
1193
1202
|
function resolveCustomQuestionAnswers(answers, questions, options) {
|
|
1194
|
-
const
|
|
1203
|
+
const acceptAllIds = options?.acceptAllIds ?? false;
|
|
1204
|
+
const resolved = answers.map((answer) => resolveOne(answer, questions, acceptAllIds));
|
|
1195
1205
|
if (options?.requireRequired) {
|
|
1196
1206
|
assertRequiredAnswered(resolved, questions);
|
|
1197
1207
|
}
|
|
@@ -1799,19 +1809,22 @@ ${note}`;
|
|
|
1799
1809
|
* Resolves the input's custom-question answers into the quote's
|
|
1800
1810
|
* `questionAnswers` payload (each tagged with a fresh `refid`), or `null` when
|
|
1801
1811
|
* none were supplied. Fetches the activity's custom questions to validate
|
|
1802
|
-
* against; throws on the first unmatched/ambiguous/invalid answer.
|
|
1812
|
+
* against; throws on the first unmatched/ambiguous/invalid answer. When
|
|
1813
|
+
* `acceptAllCustomQuestionIds` is set the fetch is skipped if every answer is
|
|
1814
|
+
* given by id (a by-name answer still needs the list to resolve).
|
|
1803
1815
|
*/
|
|
1804
1816
|
async buildQuestionAnswers(input) {
|
|
1805
1817
|
const answers = input.customQuestionAnswers ?? [];
|
|
1806
1818
|
const requireRequired = input.requireRequiredQuestions ?? false;
|
|
1819
|
+
const acceptAllIds = input.acceptAllCustomQuestionIds ?? false;
|
|
1807
1820
|
if (answers.length === 0 && !requireRequired) {
|
|
1808
1821
|
return null;
|
|
1809
1822
|
}
|
|
1810
|
-
const
|
|
1811
|
-
|
|
1812
|
-
);
|
|
1823
|
+
const needsQuestions = !acceptAllIds || requireRequired || answers.some((answer) => !isCustomQuestionId(answer.questionIdOrText));
|
|
1824
|
+
const questions = needsQuestions ? await this.deps.productService.getCustomQuestions(input.activityId) : [];
|
|
1813
1825
|
const resolved = resolveCustomQuestionAnswers(answers, questions, {
|
|
1814
|
-
requireRequired
|
|
1826
|
+
requireRequired,
|
|
1827
|
+
acceptAllIds
|
|
1815
1828
|
});
|
|
1816
1829
|
if (resolved.length === 0) {
|
|
1817
1830
|
return null;
|
|
@@ -2184,7 +2197,7 @@ async function requestWithRetry(http, url, init, label, onResponse) {
|
|
|
2184
2197
|
// src/internal/sdk-headers.ts
|
|
2185
2198
|
var SDK_HEADER_NAME = "x-peek-sdk";
|
|
2186
2199
|
var SDK_PLATFORM = "js";
|
|
2187
|
-
var SDK_VERSION = "0.9.
|
|
2200
|
+
var SDK_VERSION = "0.9.2";
|
|
2188
2201
|
var SDK_HEADER_VALUE = `${SDK_PLATFORM}-${SDK_VERSION}`;
|
|
2189
2202
|
|
|
2190
2203
|
// src/internal/peek/graphql-client.ts
|
|
@@ -2609,6 +2622,23 @@ function fromReviewNode(node) {
|
|
|
2609
2622
|
comment: node.comment ?? null
|
|
2610
2623
|
};
|
|
2611
2624
|
}
|
|
2625
|
+
function fromActivityReviewSummaryNode(node) {
|
|
2626
|
+
const meta = node.reviewMeta;
|
|
2627
|
+
return {
|
|
2628
|
+
productId: node.id,
|
|
2629
|
+
productName: node.name,
|
|
2630
|
+
avgRating: meta?.avgRating ?? null,
|
|
2631
|
+
countTotal: meta?.count ?? 0,
|
|
2632
|
+
countOneStar: meta?.oneStar ?? 0,
|
|
2633
|
+
countTwoStar: meta?.twoStar ?? 0,
|
|
2634
|
+
countThreeStar: meta?.threeStar ?? 0,
|
|
2635
|
+
countFourStar: meta?.fourStar ?? 0,
|
|
2636
|
+
countFiveStar: meta?.fiveStar ?? 0
|
|
2637
|
+
};
|
|
2638
|
+
}
|
|
2639
|
+
function fromActivityReviewSummaryNodes(nodes) {
|
|
2640
|
+
return nodes.map(fromActivityReviewSummaryNode);
|
|
2641
|
+
}
|
|
2612
2642
|
|
|
2613
2643
|
// src/internal/peek/reviews/review-cursor.ts
|
|
2614
2644
|
function encodeCursor(offset, pageSize) {
|
|
@@ -2644,6 +2674,23 @@ function buildReviewsQuery(fullCustomerAccess) {
|
|
|
2644
2674
|
}
|
|
2645
2675
|
`;
|
|
2646
2676
|
}
|
|
2677
|
+
var REVIEW_SUMMARIES_QUERY = `
|
|
2678
|
+
query ReviewSummaries {
|
|
2679
|
+
activities {
|
|
2680
|
+
id
|
|
2681
|
+
name
|
|
2682
|
+
reviewMeta {
|
|
2683
|
+
avgRating
|
|
2684
|
+
count
|
|
2685
|
+
fiveStar
|
|
2686
|
+
fourStar
|
|
2687
|
+
threeStar
|
|
2688
|
+
twoStar
|
|
2689
|
+
oneStar
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
`;
|
|
2647
2694
|
function buildReviewsVariables(params) {
|
|
2648
2695
|
return {
|
|
2649
2696
|
first: params.first,
|
|
@@ -2703,6 +2750,29 @@ var ReviewService = class {
|
|
|
2703
2750
|
const edges = body.data?.reviews?.edges ?? [];
|
|
2704
2751
|
return edges.map((edge) => fromReviewNode(edge.node));
|
|
2705
2752
|
}
|
|
2753
|
+
/**
|
|
2754
|
+
* Returns an aggregate review summary for **every** activity — its average
|
|
2755
|
+
* rating and the count of reviews at each star level. This reads the same
|
|
2756
|
+
* activity list as `getAllProducts`; it carries no per-review detail or PII, so
|
|
2757
|
+
* it is unaffected by `fullCustomerAccess`. An activity with no reviews comes
|
|
2758
|
+
* back with a `null` `avgRating` and zero counts.
|
|
2759
|
+
*
|
|
2760
|
+
* @example
|
|
2761
|
+
* ```ts
|
|
2762
|
+
* const summaries = await peek.getReviewService().getAllReviewSummaries();
|
|
2763
|
+
* for (const s of summaries) {
|
|
2764
|
+
* console.log(s.productName, s.avgRating, s.countTotal);
|
|
2765
|
+
* }
|
|
2766
|
+
* ```
|
|
2767
|
+
*/
|
|
2768
|
+
async getAllReviewSummaries() {
|
|
2769
|
+
const body = await this.client.request(
|
|
2770
|
+
SALES_ENDPOINT,
|
|
2771
|
+
REVIEW_SUMMARIES_QUERY,
|
|
2772
|
+
{}
|
|
2773
|
+
);
|
|
2774
|
+
return fromActivityReviewSummaryNodes(body.data?.activities ?? []);
|
|
2775
|
+
}
|
|
2706
2776
|
validate(productId, reviewCount, reviewOffset) {
|
|
2707
2777
|
if (!productId) {
|
|
2708
2778
|
throw new Error(ERROR_PRODUCT_ID_REQUIRED);
|