@getspot/spot-widget 1.3.0 → 2.0.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.
@@ -1,253 +0,0 @@
1
- const apiEndpoint = {
2
- sandbox: "https://api.sandbox.getspot.com/v1/quote",
3
- production: "https://api.getspot.com/v1/quote",
4
- local: "http://localhost:3999/api/v1/quote"
5
- };
6
-
7
- export function validateOptions(options) {
8
- const {
9
- apiConfig = {},
10
- quoteRequestData,
11
- callbacks = {},
12
- location,
13
- theme,
14
- } = options;
15
-
16
-
17
- const {
18
- environment = "sandbox",
19
- partnerId,
20
- endpoint: customEndpoint,
21
- } = apiConfig;
22
-
23
- if (!partnerId || typeof partnerId !== "string") {
24
- throw new Error("Invalid or missing partnerId in apiConfig");
25
- }
26
-
27
- const endpoint = customEndpoint || apiEndpoint[environment];
28
-
29
- if (!endpoint) {
30
- throw new Error(`Invalid environment in apiConfig: ${environment}`);
31
- }
32
-
33
- if (!quoteRequestData || (typeof quoteRequestData !== "object" && !Array.isArray(quoteRequestData))) {
34
- throw new Error("quoteRequestData must be a non-null object or array");
35
- }
36
-
37
- const requiredFields = [
38
- "startDate",
39
- "endDate",
40
- "currencyCode",
41
- "eventType",
42
- "productType",
43
- "productDuration",
44
- "productPrice",
45
- "productId",
46
- "cartId",
47
- "productName",
48
- ];
49
-
50
- function validateQuoteItem(item, index = null) {
51
- const prefix = index !== null ? `quoteRequestData[${index}]` : "quoteRequestData";
52
-
53
- requiredFields.forEach((field) => {
54
- if (
55
- !Object.prototype.hasOwnProperty.call(item, field) ||
56
- item[field] === undefined ||
57
- item[field] === null
58
- ) {
59
- throw new Error(`Missing required ${prefix} field: '${field}'`);
60
- }
61
- });
62
-
63
- const iso8601Regex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/;
64
- if (!iso8601Regex.test(item.startDate)) {
65
- throw new Error(`${prefix}.startDate must be a valid ISO8601 string`);
66
- }
67
- if (!iso8601Regex.test(item.endDate)) {
68
- throw new Error(`${prefix}.endDate must be a valid ISO8601 string`);
69
- }
70
-
71
- if (typeof item.currencyCode !== "string") {
72
- throw new Error(`${prefix}.currencyCode must be a string`);
73
- }
74
-
75
- const validCurrencyCodes = ["USD", "CAD", "AUD"];
76
- if (!validCurrencyCodes.includes(item.currencyCode)) {
77
- throw new Error(`Invalid ${prefix}.currencyCode: ${item.currencyCode}`);
78
- }
79
-
80
- if (typeof item.eventType !== "string") {
81
- throw new Error(`${prefix}.eventType must be a string`);
82
- }
83
-
84
- if (typeof item.productType !== "string") {
85
- throw new Error(`${prefix}.productType must be a string`);
86
- }
87
-
88
- const validProductTypes = ["Pass", "Trip", "Registration"];
89
- if (!validProductTypes.includes(item.productType)) {
90
- throw new Error(
91
- `${prefix}.productType must be one of ${validProductTypes.join(", ")}`
92
- );
93
- }
94
-
95
- if (typeof item.productDuration !== "string") {
96
- throw new Error(`${prefix}.productDuration must be a string`);
97
- }
98
-
99
- const validDurations = ["Daily", "Seasonal", "Trip", "Event"];
100
- if (!validDurations.includes(item.productDuration)) {
101
- throw new Error(
102
- `${prefix}.productDuration must be one of ${validDurations.join(", ")}`
103
- );
104
- }
105
-
106
- if (
107
- typeof item.productPrice !== "number" ||
108
- isNaN(item.productPrice)
109
- ) {
110
- throw new Error(`${prefix}.productPrice must be a valid number`);
111
- }
112
-
113
- if (typeof item.productId !== "string") {
114
- throw new Error(`${prefix}.productId must be a string`);
115
- }
116
-
117
- if (typeof item.cartId !== "string") {
118
- throw new Error(`${prefix}.cartId must be a string`);
119
- }
120
-
121
- if (typeof item.productName !== "string") {
122
- throw new Error(`${prefix}.productName must be a string`);
123
- }
124
- }
125
-
126
- // Check if it's a batch quote format
127
- if (quoteRequestData.cartInfo && quoteRequestData.items) {
128
- // Validate batch format
129
- const { cartInfo, items } = quoteRequestData;
130
-
131
- if (!cartInfo || typeof cartInfo !== "object") {
132
- throw new Error("quoteRequestData.cartInfo must be a non-null object");
133
- }
134
-
135
- // Validate cart-level fields
136
- if (!cartInfo.cartId || typeof cartInfo.cartId !== "string") {
137
- throw new Error("quoteRequestData.cartInfo.cartId must be a string");
138
- }
139
- if (!cartInfo.cartName || typeof cartInfo.cartName !== "string") {
140
- throw new Error("quoteRequestData.cartInfo.cartName must be a string");
141
- }
142
- if (!cartInfo.currencyCode || typeof cartInfo.currencyCode !== "string") {
143
- throw new Error("quoteRequestData.cartInfo.currencyCode must be a string");
144
- }
145
-
146
- const validCurrencyCodes = ["USD", "CAD", "AUD"];
147
- if (!validCurrencyCodes.includes(cartInfo.currencyCode)) {
148
- throw new Error(`Invalid quoteRequestData.cartInfo.currencyCode: ${cartInfo.currencyCode}`);
149
- }
150
-
151
- if (!Array.isArray(items) || items.length === 0) {
152
- throw new Error("quoteRequestData.items must be a non-empty array");
153
- }
154
-
155
- // Validate each item but without cartId and currencyCode since they're at cart level
156
- const itemRequiredFields = requiredFields.filter(f => f !== "cartId" && f !== "currencyCode");
157
-
158
- items.forEach((item, index) => {
159
- if (!item || typeof item !== "object") {
160
- throw new Error(`quoteRequestData.items[${index}] must be a non-null object`);
161
- }
162
-
163
- const prefix = `quoteRequestData.items[${index}]`;
164
-
165
- itemRequiredFields.forEach((field) => {
166
- if (!Object.prototype.hasOwnProperty.call(item, field) || item[field] === undefined || item[field] === null) {
167
- throw new Error(`Missing required ${prefix} field: '${field}'`);
168
- }
169
- });
170
-
171
- // Validate item-specific fields
172
- const iso8601Regex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/;
173
- if (!iso8601Regex.test(item.startDate)) {
174
- throw new Error(`${prefix}.startDate must be a valid ISO8601 string`);
175
- }
176
- if (!iso8601Regex.test(item.endDate)) {
177
- throw new Error(`${prefix}.endDate must be a valid ISO8601 string`);
178
- }
179
-
180
- if (typeof item.eventType !== "string") {
181
- throw new Error(`${prefix}.eventType must be a string`);
182
- }
183
-
184
- if (typeof item.productType !== "string") {
185
- throw new Error(`${prefix}.productType must be a string`);
186
- }
187
-
188
- const validProductTypes = ["Pass", "Trip", "Registration"];
189
- if (!validProductTypes.includes(item.productType)) {
190
- throw new Error(`${prefix}.productType must be one of ${validProductTypes.join(", ")}`);
191
- }
192
-
193
- if (typeof item.productDuration !== "string") {
194
- throw new Error(`${prefix}.productDuration must be a string`);
195
- }
196
-
197
- const validDurations = ["Daily", "Seasonal", "Trip", "Event"];
198
- if (!validDurations.includes(item.productDuration)) {
199
- throw new Error(`${prefix}.productDuration must be one of ${validDurations.join(", ")}`);
200
- }
201
-
202
- if (typeof item.productPrice !== "number" || isNaN(item.productPrice)) {
203
- throw new Error(`${prefix}.productPrice must be a valid number`);
204
- }
205
-
206
- if (typeof item.productId !== "string") {
207
- throw new Error(`${prefix}.productId must be a string`);
208
- }
209
-
210
- if (typeof item.productName !== "string") {
211
- throw new Error(`${prefix}.productName must be a string`);
212
- }
213
- });
214
- } else if (Array.isArray(quoteRequestData)) {
215
- // Legacy array format - kept for backward compatibility
216
- if (quoteRequestData.length === 0) {
217
- throw new Error("quoteRequestData array cannot be empty");
218
- }
219
- quoteRequestData.forEach((item, index) => {
220
- if (!item || typeof item !== "object") {
221
- throw new Error(`quoteRequestData[${index}] must be a non-null object`);
222
- }
223
- validateQuoteItem(item, index);
224
- });
225
- } else {
226
- // Single quote format
227
- validateQuoteItem(quoteRequestData);
228
- }
229
-
230
- const callbackNames = [
231
- "onOptIn",
232
- "onOptOut",
233
- "onQuoteRetrieved",
234
- "onError",
235
- "noMatchingQuote",
236
- ];
237
- callbackNames.forEach((cbName) => {
238
- const cb = callbacks[cbName];
239
- if (cb && typeof cb !== "function") {
240
- throw new Error(`Callback '${cbName}' must be a function.`);
241
- }
242
- });
243
-
244
- if (typeof location === "string" && !document.querySelector(location)) {
245
- throw new Error(`Invalid location selector: '${location}'`);
246
- }
247
-
248
- if (theme && typeof theme !== "object") {
249
- throw new Error(
250
- "Theme must be an object with CSS variables, do not include the '--' prefix"
251
- );
252
- }
253
- }
package/vite.config.js DELETED
@@ -1,17 +0,0 @@
1
- import { defineConfig } from "vite";
2
- import path from "path";
3
-
4
- export default defineConfig({
5
- build: {
6
- outDir: "dist",
7
- lib: {
8
- entry: path.resolve(__dirname, "src/index.js"),
9
- name: "SpotWidget",
10
- fileName: (format) => `index.${format}.js`,
11
- formats: ["umd", "es"],
12
- },
13
- rollupOptions: {
14
- external: [], // no dependencies
15
- },
16
- },
17
- });