shopstack 0.2.6 → 0.3.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/README.md +139 -55
- package/SKILL.md +60 -43
- package/bin/shopstack +1 -3
- package/package.json +13 -23
- package/specs/openapi.json +3322 -0
- package/src/checkout-monitor.js +126 -0
- package/src/cli.js +364 -183
- package/src/client.d.ts +285 -51
- package/src/client.js +225 -205
- package/src/config.d.ts +19 -10
- package/src/config.js +46 -34
- package/src/reservation-progress.js +132 -0
- package/LICENSE +0 -21
package/src/client.d.ts
CHANGED
|
@@ -2,7 +2,100 @@ export interface ShopstackClientOptions {
|
|
|
2
2
|
apiKey?: string;
|
|
3
3
|
baseUrl?: string;
|
|
4
4
|
fetch?: typeof fetch;
|
|
5
|
-
|
|
5
|
+
/** Uses the runtime WebSocket when available; null selects bounded HTTP waits. */
|
|
6
|
+
webSocket?: typeof WebSocket | null;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface ShippingAddress {
|
|
10
|
+
city: string;
|
|
11
|
+
country: string;
|
|
12
|
+
line1: string;
|
|
13
|
+
line2?: string;
|
|
14
|
+
postal_code: string;
|
|
15
|
+
region?: string;
|
|
16
|
+
suburb?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface CreateCheckoutRequest {
|
|
20
|
+
currency: string;
|
|
21
|
+
customer: {
|
|
22
|
+
/** When absent or blank, the service uses a checkout-scoped temporary inbox. */
|
|
23
|
+
email?: string;
|
|
24
|
+
name: string;
|
|
25
|
+
phone?: string;
|
|
26
|
+
shipping_address: ShippingAddress;
|
|
27
|
+
};
|
|
28
|
+
external_reference?: string;
|
|
29
|
+
instructions?: string;
|
|
30
|
+
item_url: string;
|
|
31
|
+
maximum_amount: string;
|
|
32
|
+
model_handle?: "qwen";
|
|
33
|
+
payment_provider?: "link";
|
|
34
|
+
proxy?: {
|
|
35
|
+
country?: string;
|
|
36
|
+
/** Explicit browser locale; the service does not infer it from country. */
|
|
37
|
+
locale?: string;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ReservationDiner {
|
|
42
|
+
country: string;
|
|
43
|
+
/** Optional booking contact address. If omitted, Shopstack creates a temporary inbox. */
|
|
44
|
+
email?: string;
|
|
45
|
+
first_name: string;
|
|
46
|
+
last_name: string;
|
|
47
|
+
phone_number: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface CreateReservationRequest {
|
|
51
|
+
diner: ReservationDiner;
|
|
52
|
+
external_reference?: string;
|
|
53
|
+
/** The service resolves this place name and its local time zone. */
|
|
54
|
+
location: { query: string };
|
|
55
|
+
/** Include all known search details. The service asks for missing information. */
|
|
56
|
+
request: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface ReservationProgress {
|
|
60
|
+
type: "progress";
|
|
61
|
+
request_id: string;
|
|
62
|
+
sequence: number;
|
|
63
|
+
call_id: number;
|
|
64
|
+
operation:
|
|
65
|
+
| "resolve_location"
|
|
66
|
+
| "get_search_filters"
|
|
67
|
+
| "search_restaurants"
|
|
68
|
+
| "prepare_booking"
|
|
69
|
+
| "confirm_booking"
|
|
70
|
+
| "decline_booking"
|
|
71
|
+
| "ask_user"
|
|
72
|
+
| "reply"
|
|
73
|
+
| "request"
|
|
74
|
+
| "model_decision"
|
|
75
|
+
| "model_request"
|
|
76
|
+
| "model_retry_wait"
|
|
77
|
+
| "restaurant_request"
|
|
78
|
+
| "provider_session"
|
|
79
|
+
| "location_lookup"
|
|
80
|
+
| "availability_recheck"
|
|
81
|
+
| "slot_lock"
|
|
82
|
+
| "slot_unlock"
|
|
83
|
+
| "guest_profile"
|
|
84
|
+
| "booking_submit"
|
|
85
|
+
| "booking_status"
|
|
86
|
+
| "booking_cancel"
|
|
87
|
+
| "guest_inbox";
|
|
88
|
+
phase: "started" | "completed" | "failed" | "selected";
|
|
89
|
+
elapsed_ms: number;
|
|
90
|
+
duration_ms?: number;
|
|
91
|
+
http_status?: number;
|
|
92
|
+
failure?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface ReservationMutationOptions {
|
|
96
|
+
idempotencyKey?: string;
|
|
97
|
+
/** Display only. Callback failure does not retry or cancel the operation. */
|
|
98
|
+
onProgress?: (event: ReservationProgress) => unknown;
|
|
6
99
|
}
|
|
7
100
|
|
|
8
101
|
export interface PaymentCard {
|
|
@@ -34,6 +127,7 @@ export interface Checkout {
|
|
|
34
127
|
| "failed"
|
|
35
128
|
| "cancelled";
|
|
36
129
|
revision: number;
|
|
130
|
+
/** Monotonic display version; it can advance without a lifecycle change. */
|
|
37
131
|
presentation_revision: number;
|
|
38
132
|
activity: string;
|
|
39
133
|
intent?: {
|
|
@@ -42,6 +136,7 @@ export interface Checkout {
|
|
|
42
136
|
updated_at: string;
|
|
43
137
|
};
|
|
44
138
|
item_url: string;
|
|
139
|
+
/** Present this exact owner-only URL verbatim. Never reconstruct its token. */
|
|
45
140
|
live_view_url?: string;
|
|
46
141
|
required_input?: { type: "payment_card" };
|
|
47
142
|
approval?: PaymentApproval;
|
|
@@ -52,9 +147,124 @@ export interface Checkout {
|
|
|
52
147
|
expires_at: string;
|
|
53
148
|
}
|
|
54
149
|
|
|
150
|
+
export interface Reservation {
|
|
151
|
+
id: string;
|
|
152
|
+
status:
|
|
153
|
+
| "active"
|
|
154
|
+
| "confirmation_required"
|
|
155
|
+
| "confirmed"
|
|
156
|
+
| "cancelled"
|
|
157
|
+
| "booking_unknown"
|
|
158
|
+
| "cancellation_unknown";
|
|
159
|
+
revision: number;
|
|
160
|
+
turn: ReservationTurn;
|
|
161
|
+
created_at: string;
|
|
162
|
+
updated_at: string;
|
|
163
|
+
/** Search-session expiry; it does not end the life of a confirmed booking. */
|
|
164
|
+
expires_at: string;
|
|
165
|
+
/** Last retained time for reading and managing the confirmed booking. */
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export type ReservationTurn =
|
|
169
|
+
| { type: "question" | "message"; message: string }
|
|
170
|
+
| {
|
|
171
|
+
type: "location_options";
|
|
172
|
+
message: string;
|
|
173
|
+
locations: { location_id: string; label: string }[];
|
|
174
|
+
}
|
|
175
|
+
| {
|
|
176
|
+
type: "options";
|
|
177
|
+
message: string;
|
|
178
|
+
options: ReservationCompactOption[];
|
|
179
|
+
more_available: number;
|
|
180
|
+
}
|
|
181
|
+
| {
|
|
182
|
+
type: "confirmation_required";
|
|
183
|
+
message: string;
|
|
184
|
+
confirmation_prompt: {
|
|
185
|
+
restaurant: string;
|
|
186
|
+
address: string;
|
|
187
|
+
date_time: string;
|
|
188
|
+
party_size: number;
|
|
189
|
+
option_id: string;
|
|
190
|
+
time_id: string;
|
|
191
|
+
diner: ReservationDiner;
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
| {
|
|
195
|
+
type: "confirmation";
|
|
196
|
+
message: string;
|
|
197
|
+
confirmation: {
|
|
198
|
+
confirmation_number: string;
|
|
199
|
+
restaurant: string;
|
|
200
|
+
date_time: string;
|
|
201
|
+
party_size: number;
|
|
202
|
+
status: string;
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
| {
|
|
206
|
+
type: "cancellation";
|
|
207
|
+
message: string;
|
|
208
|
+
cancellation: { confirmation_number: string; status: string };
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
export interface ReservationTime {
|
|
212
|
+
date_time: string;
|
|
213
|
+
time_id: string;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export interface ReservationCompactOption {
|
|
217
|
+
address: string;
|
|
218
|
+
available_times: ReservationTime[];
|
|
219
|
+
caveats: string[];
|
|
220
|
+
cuisines: string[];
|
|
221
|
+
cover_photo_url?: string;
|
|
222
|
+
description_excerpt?: string;
|
|
223
|
+
fit: string[];
|
|
224
|
+
name: string;
|
|
225
|
+
option_id: string;
|
|
226
|
+
price_label?: string;
|
|
227
|
+
rating?: number;
|
|
228
|
+
review_count?: number;
|
|
229
|
+
tags: ("more_availability" | "most_proven")[];
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export interface ReservationOption extends Omit<
|
|
233
|
+
ReservationCompactOption,
|
|
234
|
+
| "available_times"
|
|
235
|
+
| "caveats"
|
|
236
|
+
| "cover_photo_url"
|
|
237
|
+
| "description_excerpt"
|
|
238
|
+
| "fit"
|
|
239
|
+
| "tags"
|
|
240
|
+
> {
|
|
241
|
+
description?: string;
|
|
242
|
+
match_reasons: string[];
|
|
243
|
+
photo_urls: string[];
|
|
244
|
+
times: ReservationTime[];
|
|
245
|
+
unverified: string[];
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export interface ReservationOptionPage {
|
|
249
|
+
limit: number;
|
|
250
|
+
more_available: number;
|
|
251
|
+
next_offset?: number;
|
|
252
|
+
offset: number;
|
|
253
|
+
options: ReservationCompactOption[];
|
|
254
|
+
total_available: number;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export interface RunReservationOptions {
|
|
258
|
+
idempotencyKey?: string;
|
|
259
|
+
onTurn?(reservation: Reservation): void | Promise<void>;
|
|
260
|
+
respond?(
|
|
261
|
+
reservation: Reservation,
|
|
262
|
+
): string | Promise<string | undefined> | undefined;
|
|
263
|
+
}
|
|
264
|
+
|
|
55
265
|
export interface RunCheckoutOptions {
|
|
56
266
|
idempotencyKey?: string;
|
|
57
|
-
|
|
267
|
+
/** @deprecated Checkout monitoring uses revision notifications and bounded waits. */
|
|
58
268
|
pollIntervalMs?: number;
|
|
59
269
|
timeoutMs?: number;
|
|
60
270
|
onProgress?(checkout: Checkout): void | Promise<void>;
|
|
@@ -70,19 +280,7 @@ export interface RunCheckoutOptions {
|
|
|
70
280
|
): string | Promise<string | undefined> | undefined;
|
|
71
281
|
}
|
|
72
282
|
|
|
73
|
-
export interface
|
|
74
|
-
socket_url: string;
|
|
75
|
-
protocol: "shopstack.v1";
|
|
76
|
-
token: string;
|
|
77
|
-
expires_at: string;
|
|
78
|
-
presentation_revision: number;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export interface LiveViewCapability {
|
|
82
|
-
live_view_url: string;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export interface AccountLoginStarted {
|
|
283
|
+
export interface AccountSignupStarted {
|
|
86
284
|
id: string;
|
|
87
285
|
account_type: "personal" | "developer";
|
|
88
286
|
email: string;
|
|
@@ -92,7 +290,7 @@ export interface AccountLoginStarted {
|
|
|
92
290
|
poll_token: string;
|
|
93
291
|
}
|
|
94
292
|
|
|
95
|
-
export interface
|
|
293
|
+
export interface VerifiedAccountSignup {
|
|
96
294
|
id: string;
|
|
97
295
|
status: "verified";
|
|
98
296
|
verified_at: string;
|
|
@@ -102,43 +300,45 @@ export interface VerifiedAccountLogin {
|
|
|
102
300
|
user?: Record<string, unknown>;
|
|
103
301
|
}
|
|
104
302
|
|
|
105
|
-
export interface
|
|
303
|
+
export interface SignupOptions {
|
|
106
304
|
accountType: "personal" | "developer";
|
|
107
305
|
email: string;
|
|
108
306
|
pollIntervalMs?: number;
|
|
109
307
|
timeoutMs?: number;
|
|
110
|
-
persistence?:
|
|
111
|
-
onProgress?(progress:
|
|
308
|
+
persistence?: SignupPersistence;
|
|
309
|
+
onProgress?(progress: SignupProgress): void | Promise<void>;
|
|
112
310
|
onVerificationRequired?(
|
|
113
|
-
|
|
311
|
+
signup: Omit<AccountSignupStarted, "poll_token">,
|
|
114
312
|
): void | Promise<void>;
|
|
115
313
|
}
|
|
116
314
|
|
|
117
|
-
export interface
|
|
315
|
+
export interface PendingSignupState {
|
|
118
316
|
accountType: "personal" | "developer";
|
|
119
317
|
attemptId: string;
|
|
318
|
+
/** Exact API base URL that issued this signup; never send its capabilities elsewhere. */
|
|
319
|
+
baseUrl?: string;
|
|
120
320
|
email: string;
|
|
121
321
|
expiresAt?: string;
|
|
122
322
|
idempotencyKey: string;
|
|
123
323
|
pollToken?: string;
|
|
124
324
|
recoveryKey: string;
|
|
125
|
-
|
|
325
|
+
signupId?: string;
|
|
126
326
|
}
|
|
127
327
|
|
|
128
|
-
export interface
|
|
328
|
+
export interface SignupPersistence {
|
|
129
329
|
loadPending(input: {
|
|
130
330
|
accountType: "personal" | "developer";
|
|
131
331
|
email: string;
|
|
132
|
-
}): Promise<
|
|
133
|
-
savePending(state:
|
|
332
|
+
}): Promise<PendingSignupState | undefined>;
|
|
333
|
+
savePending(state: PendingSignupState): Promise<void>;
|
|
134
334
|
completePending(
|
|
135
|
-
state:
|
|
136
|
-
result:
|
|
335
|
+
state: PendingSignupState,
|
|
336
|
+
result: VerifiedAccountSignup,
|
|
137
337
|
): Promise<void>;
|
|
138
|
-
deletePending(state:
|
|
338
|
+
deletePending(state: PendingSignupState): Promise<void>;
|
|
139
339
|
}
|
|
140
340
|
|
|
141
|
-
export interface
|
|
341
|
+
export interface SignupProgress {
|
|
142
342
|
state:
|
|
143
343
|
| "pending"
|
|
144
344
|
| "email_sent"
|
|
@@ -155,7 +355,7 @@ export interface LoginProgress {
|
|
|
155
355
|
key_type?: "user" | "developer";
|
|
156
356
|
}
|
|
157
357
|
|
|
158
|
-
export type
|
|
358
|
+
export type CompletedAccountSignup = Omit<VerifiedAccountSignup, "api_key">;
|
|
159
359
|
|
|
160
360
|
export class ShopstackApiError extends Error {
|
|
161
361
|
code: string;
|
|
@@ -165,20 +365,21 @@ export class ShopstackApiError extends Error {
|
|
|
165
365
|
|
|
166
366
|
export class ShopstackClient {
|
|
167
367
|
constructor(options?: ShopstackClientOptions);
|
|
168
|
-
|
|
368
|
+
baseUrl: string;
|
|
369
|
+
startAccountSignup(input: {
|
|
169
370
|
accountType: "personal" | "developer";
|
|
170
371
|
email: string;
|
|
171
|
-
}): Promise<
|
|
172
|
-
|
|
173
|
-
|
|
372
|
+
}): Promise<AccountSignupStarted>;
|
|
373
|
+
pollAccountSignup(
|
|
374
|
+
signupId: string,
|
|
174
375
|
pollToken: string,
|
|
175
|
-
): Promise<Omit<
|
|
176
|
-
|
|
177
|
-
|
|
376
|
+
): Promise<Omit<AccountSignupStarted, "poll_token"> | VerifiedAccountSignup>;
|
|
377
|
+
waitForAccountSignup(
|
|
378
|
+
signupId: string,
|
|
178
379
|
pollToken: string,
|
|
179
380
|
options?: { pollIntervalMs?: number; timeoutMs?: number },
|
|
180
|
-
): Promise<
|
|
181
|
-
|
|
381
|
+
): Promise<VerifiedAccountSignup>;
|
|
382
|
+
signup(input: SignupOptions): Promise<CompletedAccountSignup>;
|
|
182
383
|
createUser(input: {
|
|
183
384
|
externalId: string;
|
|
184
385
|
idempotencyKey?: string;
|
|
@@ -199,23 +400,57 @@ export class ShopstackClient {
|
|
|
199
400
|
paymentProvider?: "link",
|
|
200
401
|
options?: { idempotencyKey?: string },
|
|
201
402
|
): Promise<Record<string, unknown>>;
|
|
403
|
+
createReservation(
|
|
404
|
+
reservation: CreateReservationRequest,
|
|
405
|
+
options?: ReservationMutationOptions,
|
|
406
|
+
): Promise<Reservation>;
|
|
407
|
+
getReservation(reservationId: string): Promise<Reservation>;
|
|
408
|
+
listReservationOptions(
|
|
409
|
+
reservationId: string,
|
|
410
|
+
options?: { limit?: number; offset?: number },
|
|
411
|
+
): Promise<ReservationOptionPage>;
|
|
412
|
+
getReservationOption(
|
|
413
|
+
reservationId: string,
|
|
414
|
+
optionId: string,
|
|
415
|
+
): Promise<ReservationOption>;
|
|
416
|
+
sendReservationMessage(
|
|
417
|
+
reservationId: string,
|
|
418
|
+
content: string,
|
|
419
|
+
expectedRevision: number,
|
|
420
|
+
options?: ReservationMutationOptions,
|
|
421
|
+
): Promise<Reservation>;
|
|
422
|
+
cancelReservation(
|
|
423
|
+
reservationId: string,
|
|
424
|
+
expectedRevision: number,
|
|
425
|
+
options?: ReservationMutationOptions,
|
|
426
|
+
): Promise<Reservation>;
|
|
427
|
+
runReservation(
|
|
428
|
+
reservation: CreateReservationRequest,
|
|
429
|
+
options?: RunReservationOptions,
|
|
430
|
+
): Promise<Reservation>;
|
|
202
431
|
createCheckout(
|
|
203
|
-
checkout:
|
|
432
|
+
checkout: CreateCheckoutRequest,
|
|
204
433
|
options?: { idempotencyKey?: string },
|
|
205
434
|
): Promise<Checkout>;
|
|
206
435
|
getCheckout(checkoutId: string): Promise<Checkout>;
|
|
207
|
-
createLiveView(
|
|
208
|
-
checkoutId: string,
|
|
209
|
-
options?: { idempotencyKey?: string },
|
|
210
|
-
): Promise<LiveViewCapability>;
|
|
211
|
-
createCheckoutUpdateSubscription(
|
|
212
|
-
checkoutId: string,
|
|
213
|
-
): Promise<CheckoutUpdateSubscription>;
|
|
214
436
|
waitForCheckoutUpdate(
|
|
215
437
|
checkoutId: string,
|
|
216
|
-
|
|
217
|
-
waitSeconds?: number,
|
|
438
|
+
options: { after: number; wait?: number; signal?: AbortSignal },
|
|
218
439
|
): Promise<Checkout | undefined>;
|
|
440
|
+
subscribeToCheckoutUpdates(
|
|
441
|
+
checkoutId: string,
|
|
442
|
+
options?: { signal?: AbortSignal },
|
|
443
|
+
): Promise<{
|
|
444
|
+
socket_url: string;
|
|
445
|
+
protocol: "shopstack.v1";
|
|
446
|
+
token: string;
|
|
447
|
+
expires_at: string;
|
|
448
|
+
presentation_revision: number;
|
|
449
|
+
}>;
|
|
450
|
+
createLiveView(
|
|
451
|
+
checkoutId: string,
|
|
452
|
+
options?: { idempotencyKey?: string },
|
|
453
|
+
): Promise<{ live_view_url: string }>;
|
|
219
454
|
cancelCheckout(
|
|
220
455
|
checkoutId: string,
|
|
221
456
|
options?: { idempotencyKey?: string },
|
|
@@ -227,7 +462,6 @@ export class ShopstackClient {
|
|
|
227
462
|
): Promise<Record<string, unknown>>;
|
|
228
463
|
listMessages(checkoutId: string): Promise<Record<string, unknown>>;
|
|
229
464
|
listEvents(checkoutId: string): Promise<Record<string, unknown>>;
|
|
230
|
-
listArtifacts(checkoutId: string): Promise<Record<string, unknown>>;
|
|
231
465
|
providePaymentDetails(
|
|
232
466
|
checkoutId: string,
|
|
233
467
|
card: PaymentCard,
|
|
@@ -240,7 +474,7 @@ export class ShopstackClient {
|
|
|
240
474
|
options?: { idempotencyKey?: string },
|
|
241
475
|
): Promise<Checkout>;
|
|
242
476
|
runCheckout(
|
|
243
|
-
checkout:
|
|
477
|
+
checkout: CreateCheckoutRequest,
|
|
244
478
|
options?: RunCheckoutOptions,
|
|
245
479
|
): Promise<Checkout>;
|
|
246
480
|
}
|