@whatalo/plugin-sdk 1.1.0 → 1.2.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.
Files changed (59) hide show
  1. package/dist/adapters/express.cjs +101 -10
  2. package/dist/adapters/express.cjs.map +1 -1
  3. package/dist/adapters/express.d.cts +9 -7
  4. package/dist/adapters/express.d.ts +9 -7
  5. package/dist/adapters/express.mjs +104 -10
  6. package/dist/adapters/express.mjs.map +1 -1
  7. package/dist/adapters/hono.cjs +94 -7
  8. package/dist/adapters/hono.cjs.map +1 -1
  9. package/dist/adapters/hono.d.cts +4 -3
  10. package/dist/adapters/hono.d.ts +4 -3
  11. package/dist/adapters/hono.mjs +97 -7
  12. package/dist/adapters/hono.mjs.map +1 -1
  13. package/dist/adapters/nextjs.cjs +94 -7
  14. package/dist/adapters/nextjs.cjs.map +1 -1
  15. package/dist/adapters/nextjs.d.cts +4 -3
  16. package/dist/adapters/nextjs.d.ts +4 -3
  17. package/dist/adapters/nextjs.mjs +97 -7
  18. package/dist/adapters/nextjs.mjs.map +1 -1
  19. package/dist/bridge/index.cjs +33 -2
  20. package/dist/bridge/index.cjs.map +1 -1
  21. package/dist/bridge/index.d.cts +17 -5
  22. package/dist/bridge/index.d.ts +17 -5
  23. package/dist/bridge/index.mjs +33 -2
  24. package/dist/bridge/index.mjs.map +1 -1
  25. package/dist/client/index.cjs +36 -2
  26. package/dist/client/index.cjs.map +1 -1
  27. package/dist/client/index.d.cts +31 -4
  28. package/dist/client/index.d.ts +31 -4
  29. package/dist/client/index.mjs +36 -2
  30. package/dist/client/index.mjs.map +1 -1
  31. package/dist/index.cjs +150 -25
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.cts +7 -4
  34. package/dist/index.d.ts +7 -4
  35. package/dist/index.mjs +150 -25
  36. package/dist/index.mjs.map +1 -1
  37. package/dist/manifest/index.cjs +2 -17
  38. package/dist/manifest/index.cjs.map +1 -1
  39. package/dist/manifest/index.d.cts +10 -4
  40. package/dist/manifest/index.d.ts +10 -4
  41. package/dist/manifest/index.mjs +2 -17
  42. package/dist/manifest/index.mjs.map +1 -1
  43. package/dist/{types-M1eLMz6w.d.cts → types-B8BAV362.d.cts} +39 -3
  44. package/dist/{types-M1eLMz6w.d.ts → types-B8BAV362.d.ts} +39 -3
  45. package/dist/types-BU71_xQm.d.cts +25 -0
  46. package/dist/types-BhtVJPgF.d.ts +25 -0
  47. package/dist/types-Bo9GbqrM.d.ts +133 -0
  48. package/dist/types-rA6kVlpV.d.cts +133 -0
  49. package/dist/webhooks/index.cjs +78 -3
  50. package/dist/webhooks/index.cjs.map +1 -1
  51. package/dist/webhooks/index.d.cts +11 -4
  52. package/dist/webhooks/index.d.ts +11 -4
  53. package/dist/webhooks/index.mjs +78 -3
  54. package/dist/webhooks/index.mjs.map +1 -1
  55. package/package.json +32 -15
  56. package/dist/types-D2Efg3EG.d.ts +0 -19
  57. package/dist/types-DZ659i6f.d.ts +0 -68
  58. package/dist/types-Db_BeRCj.d.cts +0 -19
  59. package/dist/types-DdqKKyqX.d.cts +0 -68
@@ -111,6 +111,8 @@ var WhataloClient = class {
111
111
  inventory;
112
112
  /** Webhook resource methods */
113
113
  webhooks;
114
+ /** Geo reference data methods */
115
+ geo;
114
116
  constructor(options) {
115
117
  if (typeof window !== "undefined" && typeof process === "undefined") {
116
118
  console.warn(
@@ -132,6 +134,7 @@ var WhataloClient = class {
132
134
  this.store = new StoreResource(this);
133
135
  this.inventory = new InventoryResource(this);
134
136
  this.webhooks = new WebhookResource(this);
137
+ this.geo = new GeoResource(this);
135
138
  }
136
139
  /**
137
140
  * Internal request method shared by all resource namespaces.
@@ -291,6 +294,9 @@ var OrderResource = class {
291
294
  async updateStatus(id, data) {
292
295
  return this.client.request("PATCH", `/orders/${id}`, { body: data });
293
296
  }
297
+ async updatePaymentStatus(id, data) {
298
+ return this.client.request("PATCH", `/orders/${id}`, { body: data });
299
+ }
294
300
  async count(status) {
295
301
  return this.client.request("GET", "/orders/count", {
296
302
  params: status ? { status } : void 0
@@ -370,10 +376,10 @@ var InventoryResource = class {
370
376
  this.client = client;
371
377
  }
372
378
  async get(productId) {
373
- return this.client.request("GET", `/products/${productId}/inventory`);
379
+ return this.client.request("GET", `/inventory/products/${productId}`);
374
380
  }
375
381
  async adjust(productId, data) {
376
- return this.client.request("PATCH", `/products/${productId}/inventory`, {
382
+ return this.client.request("PATCH", `/inventory/products/${productId}`, {
377
383
  body: data
378
384
  });
379
385
  }
@@ -395,6 +401,34 @@ var WebhookResource = class {
395
401
  return this.client.request("DELETE", `/webhooks/${id}`);
396
402
  }
397
403
  };
404
+ var GeoResource = class {
405
+ constructor(client) {
406
+ this.client = client;
407
+ }
408
+ /**
409
+ * List countries.
410
+ * By default returns only supported countries (is_supported=true).
411
+ * Pass `{ all: true }` to retrieve all 250 countries.
412
+ */
413
+ async listCountries(params) {
414
+ return this.client.request("GET", "/geo/countries", {
415
+ params: params?.all !== void 0 ? { all: params.all } : void 0
416
+ });
417
+ }
418
+ /**
419
+ * Get a single country by ISO 3166-1 alpha-2 code.
420
+ */
421
+ async getCountry(iso2) {
422
+ return this.client.request("GET", `/geo/countries/${iso2.toUpperCase()}`);
423
+ }
424
+ /**
425
+ * List provinces (states, departments, regions) for a country.
426
+ * Returns an empty array for countries with no province data.
427
+ */
428
+ async listProvinces(countryIso2) {
429
+ return this.client.request("GET", `/geo/countries/${countryIso2.toUpperCase()}/provinces`);
430
+ }
431
+ };
398
432
  export {
399
433
  WhataloClient
400
434
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/client/errors.ts","../../src/client/whatalo-client.ts"],"sourcesContent":["/**\n * Base error for all SDK errors.\n * Contains the HTTP status code and a machine-readable error code.\n */\nexport class WhataloAPIError extends Error {\n readonly statusCode: number;\n readonly code: string;\n readonly requestId?: string;\n\n constructor(\n message: string,\n statusCode: number,\n code: string,\n requestId?: string\n ) {\n super(message);\n this.name = \"WhataloAPIError\";\n this.statusCode = statusCode;\n this.code = code;\n this.requestId = requestId;\n }\n}\n\n/** 401 — Invalid or missing API key */\nexport class AuthenticationError extends WhataloAPIError {\n constructor(\n message = \"Invalid or missing API key\",\n requestId?: string\n ) {\n super(message, 401, \"authentication_error\", requestId);\n this.name = \"AuthenticationError\";\n }\n}\n\n/** 403 — API key lacks required permission scope */\nexport class AuthorizationError extends WhataloAPIError {\n readonly requiredScope: string;\n\n constructor(\n message: string,\n requiredScope: string,\n requestId?: string\n ) {\n super(message, 403, \"authorization_error\", requestId);\n this.name = \"AuthorizationError\";\n this.requiredScope = requiredScope;\n }\n}\n\n/**\n * 403 — Installation does not have the required permission scope.\n *\n * Thrown when the merchant has not granted a scope that the current\n * API call requires. This is distinct from AuthorizationError:\n * - AuthorizationError = generic 403 (could be any auth reason)\n * - InsufficientScopeError = specific scope missing from granted_scopes\n *\n * The `requiredScope` field tells the developer exactly which scope to add\n * to their plugin manifest so they can request merchant re-consent.\n *\n * Example:\n * try {\n * await client.customers.list()\n * } catch (err) {\n * if (err instanceof InsufficientScopeError) {\n * console.error(`Add \"${err.requiredScope}\" to your manifest.`)\n * }\n * }\n */\nexport class InsufficientScopeError extends WhataloAPIError {\n /** The exact scope string missing from the installation's granted_scopes */\n readonly requiredScope: string;\n /** The scopes currently granted to this installation */\n readonly grantedScopes: string[];\n\n constructor(\n message: string,\n requiredScope: string,\n grantedScopes: string[],\n requestId?: string\n ) {\n super(message, 403, \"insufficient_scope\", requestId);\n this.name = \"InsufficientScopeError\";\n this.requiredScope = requiredScope;\n this.grantedScopes = grantedScopes;\n }\n}\n\n/** 404 — Resource not found */\nexport class NotFoundError extends WhataloAPIError {\n readonly resourceType: string;\n readonly resourceId: string;\n\n constructor(\n resourceType: string,\n resourceId: string,\n requestId?: string\n ) {\n super(\n `${resourceType} '${resourceId}' not found`,\n 404,\n \"not_found\",\n requestId\n );\n this.name = \"NotFoundError\";\n this.resourceType = resourceType;\n this.resourceId = resourceId;\n }\n}\n\n/** 422 — Request body validation failed */\nexport class ValidationError extends WhataloAPIError {\n readonly fieldErrors: Array<{ field: string; message: string }>;\n\n constructor(\n fieldErrors: Array<{ field: string; message: string }>,\n requestId?: string\n ) {\n const message = `Validation failed: ${fieldErrors\n .map((e) => `${e.field} — ${e.message}`)\n .join(\", \")}`;\n super(message, 422, \"validation_error\", requestId);\n this.name = \"ValidationError\";\n this.fieldErrors = fieldErrors;\n }\n}\n\n/** 429 — Rate limit exceeded */\nexport class RateLimitError extends WhataloAPIError {\n /** Seconds until the rate limit resets */\n readonly retryAfter: number;\n\n constructor(retryAfter: number, requestId?: string) {\n super(\n `Rate limit exceeded. Retry after ${retryAfter} seconds.`,\n 429,\n \"rate_limit_exceeded\",\n requestId\n );\n this.name = \"RateLimitError\";\n this.retryAfter = retryAfter;\n }\n}\n\n/** 500 — Server-side error */\nexport class InternalError extends WhataloAPIError {\n constructor(\n message = \"An internal error occurred\",\n requestId?: string\n ) {\n super(message, 500, \"internal_error\", requestId);\n this.name = \"InternalError\";\n }\n}\n","import type {\n WhataloClientOptions,\n RateLimitInfo,\n PaginatedResponse,\n SingleResponse,\n Product,\n Order,\n Customer,\n Category,\n Discount,\n Store,\n InventoryItem,\n Webhook,\n ListProductsParams,\n CreateProductParams,\n UpdateProductParams,\n ListOrdersParams,\n ListCustomersParams,\n ListCategoriesParams,\n CreateCategoryParams,\n UpdateCategoryParams,\n ListDiscountsParams,\n CreateDiscountParams,\n UpdateDiscountParams,\n UpsertWebhookParams,\n UpdateWebhookParams,\n AdjustInventoryParams,\n} from \"./types.js\";\nimport {\n WhataloAPIError,\n AuthenticationError,\n AuthorizationError,\n InsufficientScopeError,\n RateLimitError,\n InternalError,\n NotFoundError,\n ValidationError,\n} from \"./errors.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.whatalo.com/v1\";\nconst DEFAULT_TIMEOUT = 30_000;\n\n/**\n * Official TypeScript client for the Whatalo REST API.\n * Zero runtime dependencies — uses native fetch.\n */\nexport class WhataloClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly maxRetries: number;\n private readonly fetchFn: typeof globalThis.fetch;\n private readonly onRequest?: (url: string, init: RequestInit) => void;\n private readonly onResponse?: (response: Response, durationMs: number) => void;\n\n /** Rate limit info from the most recent API response */\n rateLimit: RateLimitInfo = { limit: 0, remaining: 0, reset: 0 };\n\n /** Product resource methods */\n readonly products: ProductResource;\n /** Order resource methods */\n readonly orders: OrderResource;\n /** Customer resource methods */\n readonly customers: CustomerResource;\n /** Category resource methods */\n readonly categories: CategoryResource;\n /** Discount resource methods */\n readonly discounts: DiscountResource;\n /** Store resource methods */\n readonly store: StoreResource;\n /** Inventory resource methods */\n readonly inventory: InventoryResource;\n /** Webhook resource methods */\n readonly webhooks: WebhookResource;\n\n constructor(options: WhataloClientOptions) {\n // Guard against accidental browser-side instantiation.\n // WhataloClient embeds the API key in every request — exposing it in\n // client-side JavaScript would allow any visitor to make authenticated\n // API calls on behalf of the merchant. Use sessionToken() on the frontend\n // and validate on the backend instead.\n if (typeof window !== \"undefined\" && typeof process === \"undefined\") {\n console.warn(\n \"[WhataloClient] WARNING: WhataloClient should only be used in server-side code. \" +\n \"Exposing your API key in browser JavaScript is a security risk. \" +\n \"Use whatalo.sessionToken() in your frontend and validate it on your backend.\"\n );\n }\n\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.maxRetries = Math.min(options.retries ?? 0, 3);\n this.fetchFn = options.fetch ?? globalThis.fetch;\n this.onRequest = options.onRequest;\n this.onResponse = options.onResponse;\n\n this.products = new ProductResource(this);\n this.orders = new OrderResource(this);\n this.customers = new CustomerResource(this);\n this.categories = new CategoryResource(this);\n this.discounts = new DiscountResource(this);\n this.store = new StoreResource(this);\n this.inventory = new InventoryResource(this);\n this.webhooks = new WebhookResource(this);\n }\n\n /**\n * Internal request method shared by all resource namespaces.\n * Handles headers, timeout, error parsing, and rate limit extraction.\n */\n async request<T>(\n method: string,\n path: string,\n options?: {\n body?: unknown;\n params?: Record<string, string | number | boolean | undefined>;\n }\n ): Promise<T> {\n let url = `${this.baseUrl}${path}`;\n\n // Add query params\n if (options?.params) {\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(options.params)) {\n if (value !== undefined) {\n searchParams.set(key, String(value));\n }\n }\n const qs = searchParams.toString();\n if (qs) url += `?${qs}`;\n }\n\n const headers: Record<string, string> = {\n \"X-API-Key\": this.apiKey,\n \"Content-Type\": \"application/json\",\n };\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n const requestInit: RequestInit = {\n method,\n headers,\n body: options?.body ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n };\n const startedAt = Date.now();\n this.onRequest?.(url, requestInit);\n\n try {\n const response = await this.fetchFn(url, requestInit);\n\n clearTimeout(timeoutId);\n this.onResponse?.(response, Date.now() - startedAt);\n\n // Extract rate limit headers\n this.rateLimit = {\n limit: Number(response.headers.get(\"X-RateLimit-Limit\") ?? 0),\n remaining: Number(\n response.headers.get(\"X-RateLimit-Remaining\") ?? 0\n ),\n reset: Number(response.headers.get(\"X-RateLimit-Reset\") ?? 0),\n };\n\n const requestId =\n response.headers.get(\"X-Request-Id\") ?? undefined;\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n // Handle error responses\n const errorBody = await response.json().catch(() => ({\n error: { code: \"unknown\", message: response.statusText },\n }));\n const errData = (errorBody as { error?: { code?: string; message?: string; details?: Array<{ field: string; message: string }> } }).error;\n\n switch (response.status) {\n case 401:\n throw new AuthenticationError(errData?.message, requestId);\n case 403:\n // Distinguish between a specific scope denial and a generic 403.\n // insufficient_scope means the merchant never granted this permission.\n if (errData?.code === \"insufficient_scope\") {\n const details = errorBody as {\n error?: { required?: string; granted?: string[] };\n };\n throw new InsufficientScopeError(\n errData.message ?? \"Insufficient scope\",\n details.error?.required ?? \"\",\n details.error?.granted ?? [],\n requestId\n );\n }\n throw new AuthorizationError(\n errData?.message ?? \"Forbidden\",\n errData?.code ?? \"unknown_scope\",\n requestId\n );\n case 404:\n throw new NotFoundError(\"Resource\", path, requestId);\n case 422:\n throw new ValidationError(\n errData?.details ?? [\n { field: \"unknown\", message: errData?.message ?? \"Validation failed\" },\n ],\n requestId\n );\n case 429: {\n const retryAfter = Number(\n response.headers.get(\"Retry-After\") ?? 60\n );\n throw new RateLimitError(retryAfter, requestId);\n }\n default:\n if (response.status >= 500 && attempt < this.maxRetries) {\n // Retry on 5xx\n lastError = new InternalError(errData?.message, requestId);\n await this.sleep(Math.pow(2, attempt) * 1000);\n continue;\n }\n throw new WhataloAPIError(\n errData?.message ?? \"API error\",\n response.status,\n errData?.code ?? \"unknown\",\n requestId\n );\n }\n } catch (err) {\n clearTimeout(timeoutId);\n if (err instanceof WhataloAPIError) throw err;\n if ((err as Error).name === \"AbortError\") {\n throw new WhataloAPIError(\n \"Request timed out\",\n 408,\n \"timeout\"\n );\n }\n throw err;\n }\n }\n\n throw lastError ?? new InternalError(\"Request failed after retries\");\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n\n/** Products API namespace */\nclass ProductResource {\n constructor(private readonly client: WhataloClient) {}\n\n async list(\n params?: ListProductsParams\n ): Promise<PaginatedResponse<Product>> {\n return this.client.request(\"GET\", \"/products\", {\n params: params as Record<string, string | number | boolean | undefined>,\n });\n }\n\n async get(id: string): Promise<SingleResponse<Product>> {\n return this.client.request(\"GET\", `/products/${id}`);\n }\n\n async create(\n data: CreateProductParams\n ): Promise<SingleResponse<Product>> {\n return this.client.request(\"POST\", \"/products\", { body: data });\n }\n\n async update(\n id: string,\n data: UpdateProductParams\n ): Promise<SingleResponse<Product>> {\n return this.client.request(\"PATCH\", `/products/${id}`, { body: data });\n }\n\n async delete(id: string): Promise<SingleResponse<{ deleted: boolean }>> {\n return this.client.request(\"DELETE\", `/products/${id}`);\n }\n\n async count(\n status?: \"active\" | \"inactive\" | \"all\"\n ): Promise<SingleResponse<{ count: number }>> {\n return this.client.request(\"GET\", \"/products/count\", {\n params: status ? { status } : undefined,\n });\n }\n}\n\n/** Orders API namespace */\nclass OrderResource {\n constructor(private readonly client: WhataloClient) {}\n\n async list(\n params?: ListOrdersParams\n ): Promise<PaginatedResponse<Order>> {\n return this.client.request(\"GET\", \"/orders\", {\n params: params as Record<string, string | number | boolean | undefined>,\n });\n }\n\n async get(id: string): Promise<SingleResponse<Order>> {\n return this.client.request(\"GET\", `/orders/${id}`);\n }\n\n async updateStatus(\n id: string,\n data: { status: string }\n ): Promise<SingleResponse<Order>> {\n return this.client.request(\"PATCH\", `/orders/${id}`, { body: data });\n }\n\n async count(\n status?: string\n ): Promise<SingleResponse<{ count: number }>> {\n return this.client.request(\"GET\", \"/orders/count\", {\n params: status ? { status } : undefined,\n });\n }\n}\n\n/** Customers API namespace */\nclass CustomerResource {\n constructor(private readonly client: WhataloClient) {}\n\n async list(params?: ListCustomersParams): Promise<PaginatedResponse<Customer>> {\n return this.client.request(\"GET\", \"/customers\", {\n params: params as Record<string, string | number | boolean | undefined>,\n });\n }\n\n async get(id: string): Promise<SingleResponse<Customer>> {\n return this.client.request(\"GET\", `/customers/${id}`);\n }\n}\n\n/** Categories API namespace */\nclass CategoryResource {\n constructor(private readonly client: WhataloClient) {}\n\n async list(\n params?: ListCategoriesParams\n ): Promise<PaginatedResponse<Category>> {\n return this.client.request(\"GET\", \"/categories\", {\n params: params as Record<string, string | number | boolean | undefined>,\n });\n }\n\n async get(id: string): Promise<SingleResponse<Category>> {\n return this.client.request(\"GET\", `/categories/${id}`);\n }\n\n async create(\n data: CreateCategoryParams\n ): Promise<SingleResponse<Category>> {\n return this.client.request(\"POST\", \"/categories\", { body: data });\n }\n\n async update(\n id: string,\n data: UpdateCategoryParams\n ): Promise<SingleResponse<Category>> {\n return this.client.request(\"PATCH\", `/categories/${id}`, { body: data });\n }\n\n async delete(id: string): Promise<SingleResponse<{ deleted: boolean }>> {\n return this.client.request(\"DELETE\", `/categories/${id}`);\n }\n\n async count(): Promise<SingleResponse<{ count: number }>> {\n return this.client.request(\"GET\", \"/categories/count\");\n }\n}\n\n/** Discounts API namespace */\nclass DiscountResource {\n constructor(private readonly client: WhataloClient) {}\n\n async list(\n params?: ListDiscountsParams\n ): Promise<PaginatedResponse<Discount>> {\n return this.client.request(\"GET\", \"/discounts\", {\n params: params as Record<string, string | number | boolean | undefined>,\n });\n }\n\n async get(id: string): Promise<SingleResponse<Discount>> {\n return this.client.request(\"GET\", `/discounts/${id}`);\n }\n\n async create(\n data: CreateDiscountParams\n ): Promise<SingleResponse<Discount>> {\n return this.client.request(\"POST\", \"/discounts\", { body: data });\n }\n\n async update(\n id: string,\n data: UpdateDiscountParams\n ): Promise<SingleResponse<Discount>> {\n return this.client.request(\"PATCH\", `/discounts/${id}`, { body: data });\n }\n\n async delete(id: string): Promise<SingleResponse<{ deleted: boolean }>> {\n return this.client.request(\"DELETE\", `/discounts/${id}`);\n }\n}\n\n/** Store API namespace */\nclass StoreResource {\n constructor(private readonly client: WhataloClient) {}\n\n async get(): Promise<SingleResponse<Store>> {\n return this.client.request(\"GET\", \"/store\");\n }\n}\n\n/** Inventory API namespace */\nclass InventoryResource {\n constructor(private readonly client: WhataloClient) {}\n\n async get(productId: string): Promise<SingleResponse<InventoryItem>> {\n return this.client.request(\"GET\", `/products/${productId}/inventory`);\n }\n\n async adjust(\n productId: string,\n data: AdjustInventoryParams\n ): Promise<SingleResponse<InventoryItem>> {\n return this.client.request(\"PATCH\", `/products/${productId}/inventory`, {\n body: data,\n });\n }\n}\n\n/** Webhooks API namespace */\nclass WebhookResource {\n constructor(private readonly client: WhataloClient) {}\n\n async list(): Promise<PaginatedResponse<Webhook>> {\n return this.client.request(\"GET\", \"/webhooks\");\n }\n\n async create(data: UpsertWebhookParams): Promise<SingleResponse<Webhook>> {\n return this.client.request(\"POST\", \"/webhooks\", { body: data });\n }\n\n async update(\n id: string,\n data: UpdateWebhookParams\n ): Promise<SingleResponse<Webhook>> {\n return this.client.request(\"PATCH\", `/webhooks/${id}`, { body: data });\n }\n\n async delete(id: string): Promise<SingleResponse<{ deleted: boolean }>> {\n return this.client.request(\"DELETE\", `/webhooks/${id}`);\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/client/errors.ts","../../src/client/whatalo-client.ts"],"sourcesContent":["/**\n * Base error for all SDK errors.\n * Contains the HTTP status code and a machine-readable error code.\n */\nexport class WhataloAPIError extends Error {\n readonly statusCode: number;\n readonly code: string;\n readonly requestId?: string;\n\n constructor(\n message: string,\n statusCode: number,\n code: string,\n requestId?: string\n ) {\n super(message);\n this.name = \"WhataloAPIError\";\n this.statusCode = statusCode;\n this.code = code;\n this.requestId = requestId;\n }\n}\n\n/** 401 — Invalid or missing API key */\nexport class AuthenticationError extends WhataloAPIError {\n constructor(\n message = \"Invalid or missing API key\",\n requestId?: string\n ) {\n super(message, 401, \"authentication_error\", requestId);\n this.name = \"AuthenticationError\";\n }\n}\n\n/** 403 — API key lacks required permission scope */\nexport class AuthorizationError extends WhataloAPIError {\n readonly requiredScope: string;\n\n constructor(\n message: string,\n requiredScope: string,\n requestId?: string\n ) {\n super(message, 403, \"authorization_error\", requestId);\n this.name = \"AuthorizationError\";\n this.requiredScope = requiredScope;\n }\n}\n\n/**\n * 403 — Installation does not have the required permission scope.\n *\n * Thrown when the merchant has not granted a scope that the current\n * API call requires. This is distinct from AuthorizationError:\n * - AuthorizationError = generic 403 (could be any auth reason)\n * - InsufficientScopeError = specific scope missing from granted_scopes\n *\n * The `requiredScope` field tells the developer exactly which scope to add\n * to their plugin manifest so they can request merchant re-consent.\n *\n * Example:\n * try {\n * await client.customers.list()\n * } catch (err) {\n * if (err instanceof InsufficientScopeError) {\n * console.error(`Add \"${err.requiredScope}\" to your manifest.`)\n * }\n * }\n */\nexport class InsufficientScopeError extends WhataloAPIError {\n /** The exact scope string missing from the installation's granted_scopes */\n readonly requiredScope: string;\n /** The scopes currently granted to this installation */\n readonly grantedScopes: string[];\n\n constructor(\n message: string,\n requiredScope: string,\n grantedScopes: string[],\n requestId?: string\n ) {\n super(message, 403, \"insufficient_scope\", requestId);\n this.name = \"InsufficientScopeError\";\n this.requiredScope = requiredScope;\n this.grantedScopes = grantedScopes;\n }\n}\n\n/** 404 — Resource not found */\nexport class NotFoundError extends WhataloAPIError {\n readonly resourceType: string;\n readonly resourceId: string;\n\n constructor(\n resourceType: string,\n resourceId: string,\n requestId?: string\n ) {\n super(\n `${resourceType} '${resourceId}' not found`,\n 404,\n \"not_found\",\n requestId\n );\n this.name = \"NotFoundError\";\n this.resourceType = resourceType;\n this.resourceId = resourceId;\n }\n}\n\n/** 422 — Request body validation failed */\nexport class ValidationError extends WhataloAPIError {\n readonly fieldErrors: Array<{ field: string; message: string }>;\n\n constructor(\n fieldErrors: Array<{ field: string; message: string }>,\n requestId?: string\n ) {\n const message = `Validation failed: ${fieldErrors\n .map((e) => `${e.field} — ${e.message}`)\n .join(\", \")}`;\n super(message, 422, \"validation_error\", requestId);\n this.name = \"ValidationError\";\n this.fieldErrors = fieldErrors;\n }\n}\n\n/** 429 — Rate limit exceeded */\nexport class RateLimitError extends WhataloAPIError {\n /** Seconds until the rate limit resets */\n readonly retryAfter: number;\n\n constructor(retryAfter: number, requestId?: string) {\n super(\n `Rate limit exceeded. Retry after ${retryAfter} seconds.`,\n 429,\n \"rate_limit_exceeded\",\n requestId\n );\n this.name = \"RateLimitError\";\n this.retryAfter = retryAfter;\n }\n}\n\n/** 500 — Server-side error */\nexport class InternalError extends WhataloAPIError {\n constructor(\n message = \"An internal error occurred\",\n requestId?: string\n ) {\n super(message, 500, \"internal_error\", requestId);\n this.name = \"InternalError\";\n }\n}\n","import type {\n WhataloClientOptions,\n RateLimitInfo,\n PaginatedResponse,\n SingleResponse,\n Product,\n Order,\n Customer,\n Category,\n Discount,\n Store,\n GeoCountry,\n GeoProvince,\n InventoryItem,\n Webhook,\n ListProductsParams,\n CreateProductParams,\n UpdateProductParams,\n ListOrdersParams,\n UpdateOrderStatusParams,\n UpdateOrderPaymentStatusParams,\n ListCustomersParams,\n ListCategoriesParams,\n CreateCategoryParams,\n UpdateCategoryParams,\n ListDiscountsParams,\n CreateDiscountParams,\n UpdateDiscountParams,\n UpsertWebhookParams,\n UpdateWebhookParams,\n AdjustInventoryParams,\n ListCountriesParams,\n} from \"./types.js\";\nimport {\n WhataloAPIError,\n AuthenticationError,\n AuthorizationError,\n InsufficientScopeError,\n RateLimitError,\n InternalError,\n NotFoundError,\n ValidationError,\n} from \"./errors.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.whatalo.com/v1\";\nconst DEFAULT_TIMEOUT = 30_000;\n\n/**\n * Official TypeScript client for the Whatalo REST API.\n * Zero runtime dependencies — uses native fetch.\n */\nexport class WhataloClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly maxRetries: number;\n private readonly fetchFn: typeof globalThis.fetch;\n private readonly onRequest?: (url: string, init: RequestInit) => void;\n private readonly onResponse?: (response: Response, durationMs: number) => void;\n\n /** Rate limit info from the most recent API response */\n rateLimit: RateLimitInfo = { limit: 0, remaining: 0, reset: 0 };\n\n /** Product resource methods */\n readonly products: ProductResource;\n /** Order resource methods */\n readonly orders: OrderResource;\n /** Customer resource methods */\n readonly customers: CustomerResource;\n /** Category resource methods */\n readonly categories: CategoryResource;\n /** Discount resource methods */\n readonly discounts: DiscountResource;\n /** Store resource methods */\n readonly store: StoreResource;\n /** Inventory resource methods */\n readonly inventory: InventoryResource;\n /** Webhook resource methods */\n readonly webhooks: WebhookResource;\n /** Geo reference data methods */\n readonly geo: GeoResource;\n\n constructor(options: WhataloClientOptions) {\n // Guard against accidental browser-side instantiation.\n // WhataloClient embeds the API key in every request — exposing it in\n // client-side JavaScript would allow any visitor to make authenticated\n // API calls on behalf of the merchant. Use sessionToken() on the frontend\n // and validate on the backend instead.\n if (typeof window !== \"undefined\" && typeof process === \"undefined\") {\n console.warn(\n \"[WhataloClient] WARNING: WhataloClient should only be used in server-side code. \" +\n \"Exposing your API key in browser JavaScript is a security risk. \" +\n \"Use whatalo.sessionToken() in your frontend and validate it on your backend.\"\n );\n }\n\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this.maxRetries = Math.min(options.retries ?? 0, 3);\n this.fetchFn = options.fetch ?? globalThis.fetch;\n this.onRequest = options.onRequest;\n this.onResponse = options.onResponse;\n\n this.products = new ProductResource(this);\n this.orders = new OrderResource(this);\n this.customers = new CustomerResource(this);\n this.categories = new CategoryResource(this);\n this.discounts = new DiscountResource(this);\n this.store = new StoreResource(this);\n this.inventory = new InventoryResource(this);\n this.webhooks = new WebhookResource(this);\n this.geo = new GeoResource(this);\n }\n\n /**\n * Internal request method shared by all resource namespaces.\n * Handles headers, timeout, error parsing, and rate limit extraction.\n */\n async request<T>(\n method: string,\n path: string,\n options?: {\n body?: unknown;\n params?: Record<string, string | number | boolean | undefined>;\n }\n ): Promise<T> {\n let url = `${this.baseUrl}${path}`;\n\n // Add query params\n if (options?.params) {\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(options.params)) {\n if (value !== undefined) {\n searchParams.set(key, String(value));\n }\n }\n const qs = searchParams.toString();\n if (qs) url += `?${qs}`;\n }\n\n const headers: Record<string, string> = {\n \"X-API-Key\": this.apiKey,\n \"Content-Type\": \"application/json\",\n };\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n const requestInit: RequestInit = {\n method,\n headers,\n body: options?.body ? JSON.stringify(options.body) : undefined,\n signal: controller.signal,\n };\n const startedAt = Date.now();\n this.onRequest?.(url, requestInit);\n\n try {\n const response = await this.fetchFn(url, requestInit);\n\n clearTimeout(timeoutId);\n this.onResponse?.(response, Date.now() - startedAt);\n\n // Extract rate limit headers\n this.rateLimit = {\n limit: Number(response.headers.get(\"X-RateLimit-Limit\") ?? 0),\n remaining: Number(\n response.headers.get(\"X-RateLimit-Remaining\") ?? 0\n ),\n reset: Number(response.headers.get(\"X-RateLimit-Reset\") ?? 0),\n };\n\n const requestId =\n response.headers.get(\"X-Request-Id\") ?? undefined;\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n // Handle error responses\n const errorBody = await response.json().catch(() => ({\n error: { code: \"unknown\", message: response.statusText },\n }));\n const errData = (errorBody as { error?: { code?: string; message?: string; details?: Array<{ field: string; message: string }> } }).error;\n\n switch (response.status) {\n case 401:\n throw new AuthenticationError(errData?.message, requestId);\n case 403:\n // Distinguish between a specific scope denial and a generic 403.\n // insufficient_scope means the merchant never granted this permission.\n if (errData?.code === \"insufficient_scope\") {\n const details = errorBody as {\n error?: { required?: string; granted?: string[] };\n };\n throw new InsufficientScopeError(\n errData.message ?? \"Insufficient scope\",\n details.error?.required ?? \"\",\n details.error?.granted ?? [],\n requestId\n );\n }\n throw new AuthorizationError(\n errData?.message ?? \"Forbidden\",\n errData?.code ?? \"unknown_scope\",\n requestId\n );\n case 404:\n throw new NotFoundError(\"Resource\", path, requestId);\n case 422:\n throw new ValidationError(\n errData?.details ?? [\n { field: \"unknown\", message: errData?.message ?? \"Validation failed\" },\n ],\n requestId\n );\n case 429: {\n const retryAfter = Number(\n response.headers.get(\"Retry-After\") ?? 60\n );\n throw new RateLimitError(retryAfter, requestId);\n }\n default:\n if (response.status >= 500 && attempt < this.maxRetries) {\n // Retry on 5xx\n lastError = new InternalError(errData?.message, requestId);\n await this.sleep(Math.pow(2, attempt) * 1000);\n continue;\n }\n throw new WhataloAPIError(\n errData?.message ?? \"API error\",\n response.status,\n errData?.code ?? \"unknown\",\n requestId\n );\n }\n } catch (err) {\n clearTimeout(timeoutId);\n if (err instanceof WhataloAPIError) throw err;\n if ((err as Error).name === \"AbortError\") {\n throw new WhataloAPIError(\n \"Request timed out\",\n 408,\n \"timeout\"\n );\n }\n throw err;\n }\n }\n\n throw lastError ?? new InternalError(\"Request failed after retries\");\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n\n/** Products API namespace */\nclass ProductResource {\n constructor(private readonly client: WhataloClient) {}\n\n async list(\n params?: ListProductsParams\n ): Promise<PaginatedResponse<Product>> {\n return this.client.request(\"GET\", \"/products\", {\n params: params as Record<string, string | number | boolean | undefined>,\n });\n }\n\n async get(id: string): Promise<SingleResponse<Product>> {\n return this.client.request(\"GET\", `/products/${id}`);\n }\n\n async create(\n data: CreateProductParams\n ): Promise<SingleResponse<Product>> {\n return this.client.request(\"POST\", \"/products\", { body: data });\n }\n\n async update(\n id: string,\n data: UpdateProductParams\n ): Promise<SingleResponse<Product>> {\n return this.client.request(\"PATCH\", `/products/${id}`, { body: data });\n }\n\n async delete(id: string): Promise<SingleResponse<{ deleted: boolean }>> {\n return this.client.request(\"DELETE\", `/products/${id}`);\n }\n\n async count(\n status?: \"active\" | \"inactive\" | \"all\"\n ): Promise<SingleResponse<{ count: number }>> {\n return this.client.request(\"GET\", \"/products/count\", {\n params: status ? { status } : undefined,\n });\n }\n}\n\n/** Orders API namespace */\nclass OrderResource {\n constructor(private readonly client: WhataloClient) {}\n\n async list(\n params?: ListOrdersParams\n ): Promise<PaginatedResponse<Order>> {\n return this.client.request(\"GET\", \"/orders\", {\n params: params as Record<string, string | number | boolean | undefined>,\n });\n }\n\n async get(id: string): Promise<SingleResponse<Order>> {\n return this.client.request(\"GET\", `/orders/${id}`);\n }\n\n async updateStatus(\n id: string,\n data: UpdateOrderStatusParams\n ): Promise<SingleResponse<Order>> {\n return this.client.request(\"PATCH\", `/orders/${id}`, { body: data });\n }\n\n async updatePaymentStatus(\n id: string,\n data: UpdateOrderPaymentStatusParams\n ): Promise<SingleResponse<Order>> {\n return this.client.request(\"PATCH\", `/orders/${id}`, { body: data });\n }\n\n async count(\n status?: string\n ): Promise<SingleResponse<{ count: number }>> {\n return this.client.request(\"GET\", \"/orders/count\", {\n params: status ? { status } : undefined,\n });\n }\n}\n\n/** Customers API namespace */\nclass CustomerResource {\n constructor(private readonly client: WhataloClient) {}\n\n async list(params?: ListCustomersParams): Promise<PaginatedResponse<Customer>> {\n return this.client.request(\"GET\", \"/customers\", {\n params: params as Record<string, string | number | boolean | undefined>,\n });\n }\n\n async get(id: string): Promise<SingleResponse<Customer>> {\n return this.client.request(\"GET\", `/customers/${id}`);\n }\n}\n\n/** Categories API namespace */\nclass CategoryResource {\n constructor(private readonly client: WhataloClient) {}\n\n async list(\n params?: ListCategoriesParams\n ): Promise<PaginatedResponse<Category>> {\n return this.client.request(\"GET\", \"/categories\", {\n params: params as Record<string, string | number | boolean | undefined>,\n });\n }\n\n async get(id: string): Promise<SingleResponse<Category>> {\n return this.client.request(\"GET\", `/categories/${id}`);\n }\n\n async create(\n data: CreateCategoryParams\n ): Promise<SingleResponse<Category>> {\n return this.client.request(\"POST\", \"/categories\", { body: data });\n }\n\n async update(\n id: string,\n data: UpdateCategoryParams\n ): Promise<SingleResponse<Category>> {\n return this.client.request(\"PATCH\", `/categories/${id}`, { body: data });\n }\n\n async delete(id: string): Promise<SingleResponse<{ deleted: boolean }>> {\n return this.client.request(\"DELETE\", `/categories/${id}`);\n }\n\n async count(): Promise<SingleResponse<{ count: number }>> {\n return this.client.request(\"GET\", \"/categories/count\");\n }\n}\n\n/** Discounts API namespace */\nclass DiscountResource {\n constructor(private readonly client: WhataloClient) {}\n\n async list(\n params?: ListDiscountsParams\n ): Promise<PaginatedResponse<Discount>> {\n return this.client.request(\"GET\", \"/discounts\", {\n params: params as Record<string, string | number | boolean | undefined>,\n });\n }\n\n async get(id: string): Promise<SingleResponse<Discount>> {\n return this.client.request(\"GET\", `/discounts/${id}`);\n }\n\n async create(\n data: CreateDiscountParams\n ): Promise<SingleResponse<Discount>> {\n return this.client.request(\"POST\", \"/discounts\", { body: data });\n }\n\n async update(\n id: string,\n data: UpdateDiscountParams\n ): Promise<SingleResponse<Discount>> {\n return this.client.request(\"PATCH\", `/discounts/${id}`, { body: data });\n }\n\n async delete(id: string): Promise<SingleResponse<{ deleted: boolean }>> {\n return this.client.request(\"DELETE\", `/discounts/${id}`);\n }\n}\n\n/** Store API namespace */\nclass StoreResource {\n constructor(private readonly client: WhataloClient) {}\n\n async get(): Promise<SingleResponse<Store>> {\n return this.client.request(\"GET\", \"/store\");\n }\n}\n\n/** Inventory API namespace */\nclass InventoryResource {\n constructor(private readonly client: WhataloClient) {}\n\n async get(productId: string): Promise<SingleResponse<InventoryItem>> {\n return this.client.request(\"GET\", `/inventory/products/${productId}`);\n }\n\n async adjust(\n productId: string,\n data: AdjustInventoryParams\n ): Promise<SingleResponse<InventoryItem>> {\n return this.client.request(\"PATCH\", `/inventory/products/${productId}`, {\n body: data,\n });\n }\n}\n\n/** Webhooks API namespace */\nclass WebhookResource {\n constructor(private readonly client: WhataloClient) {}\n\n async list(): Promise<PaginatedResponse<Webhook>> {\n return this.client.request(\"GET\", \"/webhooks\");\n }\n\n async create(data: UpsertWebhookParams): Promise<SingleResponse<Webhook>> {\n return this.client.request(\"POST\", \"/webhooks\", { body: data });\n }\n\n async update(\n id: string,\n data: UpdateWebhookParams\n ): Promise<SingleResponse<Webhook>> {\n return this.client.request(\"PATCH\", `/webhooks/${id}`, { body: data });\n }\n\n async delete(id: string): Promise<SingleResponse<{ deleted: boolean }>> {\n return this.client.request(\"DELETE\", `/webhooks/${id}`);\n }\n}\n\n/** Geo reference data API namespace (countries and provinces). */\nclass GeoResource {\n constructor(private readonly client: WhataloClient) {}\n\n /**\n * List countries.\n * By default returns only supported countries (is_supported=true).\n * Pass `{ all: true }` to retrieve all 250 countries.\n */\n async listCountries(\n params?: ListCountriesParams\n ): Promise<{ data: GeoCountry[] }> {\n return this.client.request(\"GET\", \"/geo/countries\", {\n params: params?.all !== undefined ? { all: params.all } : undefined,\n });\n }\n\n /**\n * Get a single country by ISO 3166-1 alpha-2 code.\n */\n async getCountry(iso2: string): Promise<{ data: GeoCountry }> {\n return this.client.request(\"GET\", `/geo/countries/${iso2.toUpperCase()}`);\n }\n\n /**\n * List provinces (states, departments, regions) for a country.\n * Returns an empty array for countries with no province data.\n */\n async listProvinces(countryIso2: string): Promise<{ data: GeoProvince[] }> {\n return this.client.request(\"GET\", `/geo/countries/${countryIso2.toUpperCase()}/provinces`);\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.cjs CHANGED
@@ -30,10 +30,13 @@ __export(src_exports, {
30
30
  RateLimitError: () => RateLimitError,
31
31
  SDK_VERSION: () => SDK_VERSION,
32
32
  ValidationError: () => ValidationError,
33
+ WEBHOOK_EVENTS: () => WEBHOOK_EVENTS,
33
34
  WhataloAPIError: () => WhataloAPIError,
34
35
  WhataloClient: () => WhataloClient,
35
36
  clearSessionTokenCache: () => clearSessionTokenCache,
36
37
  defineApp: () => defineApp,
38
+ isRuntimeWebhookPayload: () => isRuntimeWebhookPayload,
39
+ isWebhookEvent: () => isWebhookEvent,
37
40
  sessionToken: () => sessionToken,
38
41
  useAppBridge: () => useAppBridge,
39
42
  useWhataloAction: () => useWhataloAction,
@@ -156,6 +159,8 @@ var WhataloClient = class {
156
159
  inventory;
157
160
  /** Webhook resource methods */
158
161
  webhooks;
162
+ /** Geo reference data methods */
163
+ geo;
159
164
  constructor(options) {
160
165
  if (typeof window !== "undefined" && typeof process === "undefined") {
161
166
  console.warn(
@@ -177,6 +182,7 @@ var WhataloClient = class {
177
182
  this.store = new StoreResource(this);
178
183
  this.inventory = new InventoryResource(this);
179
184
  this.webhooks = new WebhookResource(this);
185
+ this.geo = new GeoResource(this);
180
186
  }
181
187
  /**
182
188
  * Internal request method shared by all resource namespaces.
@@ -336,6 +342,9 @@ var OrderResource = class {
336
342
  async updateStatus(id, data) {
337
343
  return this.client.request("PATCH", `/orders/${id}`, { body: data });
338
344
  }
345
+ async updatePaymentStatus(id, data) {
346
+ return this.client.request("PATCH", `/orders/${id}`, { body: data });
347
+ }
339
348
  async count(status) {
340
349
  return this.client.request("GET", "/orders/count", {
341
350
  params: status ? { status } : void 0
@@ -415,10 +424,10 @@ var InventoryResource = class {
415
424
  this.client = client;
416
425
  }
417
426
  async get(productId) {
418
- return this.client.request("GET", `/products/${productId}/inventory`);
427
+ return this.client.request("GET", `/inventory/products/${productId}`);
419
428
  }
420
429
  async adjust(productId, data) {
421
- return this.client.request("PATCH", `/products/${productId}/inventory`, {
430
+ return this.client.request("PATCH", `/inventory/products/${productId}`, {
422
431
  body: data
423
432
  });
424
433
  }
@@ -440,17 +449,57 @@ var WebhookResource = class {
440
449
  return this.client.request("DELETE", `/webhooks/${id}`);
441
450
  }
442
451
  };
452
+ var GeoResource = class {
453
+ constructor(client) {
454
+ this.client = client;
455
+ }
456
+ /**
457
+ * List countries.
458
+ * By default returns only supported countries (is_supported=true).
459
+ * Pass `{ all: true }` to retrieve all 250 countries.
460
+ */
461
+ async listCountries(params) {
462
+ return this.client.request("GET", "/geo/countries", {
463
+ params: params?.all !== void 0 ? { all: params.all } : void 0
464
+ });
465
+ }
466
+ /**
467
+ * Get a single country by ISO 3166-1 alpha-2 code.
468
+ */
469
+ async getCountry(iso2) {
470
+ return this.client.request("GET", `/geo/countries/${iso2.toUpperCase()}`);
471
+ }
472
+ /**
473
+ * List provinces (states, departments, regions) for a country.
474
+ * Returns an empty array for countries with no province data.
475
+ */
476
+ async listProvinces(countryIso2) {
477
+ return this.client.request("GET", `/geo/countries/${countryIso2.toUpperCase()}/provinces`);
478
+ }
479
+ };
443
480
 
444
481
  // src/webhooks/verify.ts
445
482
  var import_node_crypto = require("crypto");
483
+ var DEFAULT_TOLERANCE_SECONDS = 300;
446
484
  function verifyWebhook({
447
485
  payload,
448
486
  signature,
449
- secret
487
+ timestamp,
488
+ secret,
489
+ toleranceSeconds = DEFAULT_TOLERANCE_SECONDS,
490
+ currentTime = Math.floor(Date.now() / 1e3)
450
491
  }) {
451
- if (!payload || !signature || !secret) return false;
452
- const expected = (0, import_node_crypto.createHmac)("sha256", secret).update(payload, "utf8").digest("hex");
492
+ if (!payload || !signature || !secret || timestamp === "") return false;
493
+ const timestampString = String(timestamp);
494
+ const timestampValue = typeof timestamp === "number" ? timestamp : Number(timestamp);
495
+ if (!Number.isInteger(timestampValue)) return false;
496
+ if (!Number.isFinite(toleranceSeconds) || toleranceSeconds < 0) return false;
497
+ if (!Number.isFinite(currentTime)) return false;
498
+ const ageSeconds = Math.abs(currentTime - timestampValue);
499
+ if (ageSeconds > toleranceSeconds) return false;
500
+ const expected = (0, import_node_crypto.createHmac)("sha256", secret).update(`${timestampString}.${payload}`, "utf8").digest("hex");
453
501
  if (expected.length !== signature.length) return false;
502
+ if (!/^[a-f0-9]+$/i.test(signature)) return false;
454
503
  try {
455
504
  return (0, import_node_crypto.timingSafeEqual)(
456
505
  Buffer.from(expected, "hex"),
@@ -461,7 +510,65 @@ function verifyWebhook({
461
510
  }
462
511
  }
463
512
 
513
+ // src/webhooks/types.ts
514
+ var import_events = require("@whatalo/protocol/events");
515
+ var WEBHOOK_EVENTS = import_events.PUBLIC_WEBHOOK_EVENTS;
516
+ function isWebhookEvent(value) {
517
+ return (0, import_events.isPublicWebhookEvent)(value);
518
+ }
519
+ function isRecord(value) {
520
+ return typeof value === "object" && value !== null && !Array.isArray(value);
521
+ }
522
+ function hasStringId(value) {
523
+ return isRecord(value) && typeof value.id === "string";
524
+ }
525
+ function isOptionalString(value, key) {
526
+ return value[key] === void 0 || typeof value[key] === "string";
527
+ }
528
+ function isRuntimeWebhookStore(value) {
529
+ return isRecord(value) && typeof value.id === "string" && typeof value.timezone === "string" && (value.name === void 0 || typeof value.name === "string");
530
+ }
531
+ function hasValidBasePayloadFields(value) {
532
+ if (!isOptionalString(value, "event_id")) return false;
533
+ if (!isOptionalString(value, "occurred_at")) return false;
534
+ return isRuntimeWebhookStore(value.store);
535
+ }
536
+ function isRuntimeOrderWebhookPayload(value) {
537
+ return hasValidBasePayloadFields(value) && hasStringId(value.order) && (value.customer === void 0 || hasStringId(value.customer));
538
+ }
539
+ function isRuntimeProductWebhookPayload(value) {
540
+ return hasValidBasePayloadFields(value) && hasStringId(value.product);
541
+ }
542
+ function isRuntimeCustomerWebhookPayload(value) {
543
+ return hasValidBasePayloadFields(value) && hasStringId(value.customer);
544
+ }
545
+ function isRuntimeCheckoutCompletedWebhookPayload(value) {
546
+ return hasValidBasePayloadFields(value) && hasStringId(value.order) && hasStringId(value.customer) && isRuntimeWebhookStore(value.store);
547
+ }
548
+ function isRuntimeWebhookPayload(value, event) {
549
+ if (!isRecord(value)) return false;
550
+ switch (event) {
551
+ case WEBHOOK_EVENTS.ORDER_CREATED:
552
+ case WEBHOOK_EVENTS.ORDER_UPDATED:
553
+ case WEBHOOK_EVENTS.ORDER_CANCELLED:
554
+ case WEBHOOK_EVENTS.ORDER_COMPLETED:
555
+ return isRuntimeOrderWebhookPayload(value);
556
+ case WEBHOOK_EVENTS.PRODUCT_CREATED:
557
+ case WEBHOOK_EVENTS.PRODUCT_UPDATED:
558
+ case WEBHOOK_EVENTS.PRODUCT_DELETED:
559
+ return isRuntimeProductWebhookPayload(value);
560
+ case WEBHOOK_EVENTS.CUSTOMER_CREATED:
561
+ case WEBHOOK_EVENTS.CUSTOMER_UPDATED:
562
+ return isRuntimeCustomerWebhookPayload(value);
563
+ case WEBHOOK_EVENTS.CHECKOUT_COMPLETED:
564
+ return isRuntimeCheckoutCompletedWebhookPayload(value);
565
+ default:
566
+ return false;
567
+ }
568
+ }
569
+
464
570
  // src/manifest/validate.ts
571
+ var import_scopes = require("@whatalo/protocol/scopes");
465
572
  var ManifestValidationError = class extends Error {
466
573
  errors;
467
574
  constructor(errors) {
@@ -474,23 +581,7 @@ var ManifestValidationError = class extends Error {
474
581
  var ID_REGEX = /^[a-z0-9][a-z0-9-]*[a-z0-9]$/;
475
582
  var SEMVER_REGEX = /^\d+\.\d+\.\d+$/;
476
583
  var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
477
- var VALID_PERMISSIONS = /* @__PURE__ */ new Set([
478
- "read:products",
479
- "write:products",
480
- "read:orders",
481
- "write:orders",
482
- "read:customers",
483
- "write:customers",
484
- "read:inventory",
485
- "write:inventory",
486
- "read:store",
487
- "write:store",
488
- "read:webhooks",
489
- "write:webhooks",
490
- "read:discounts",
491
- "write:discounts",
492
- "read:analytics"
493
- ]);
584
+ var VALID_PERMISSIONS = new Set(import_scopes.SCOPE_LIST.map((s) => s.token));
494
585
  var VALID_CATEGORIES = /* @__PURE__ */ new Set([
495
586
  "analytics",
496
587
  "marketing",
@@ -585,8 +676,11 @@ var DATA_RESOURCE_SCOPE = {
585
676
  products: "read:products",
586
677
  orders: "read:orders",
587
678
  customers: "read:customers",
588
- categories: "read:products"
679
+ categories: "read:products",
589
680
  // categories share the products scope
681
+ store: "read:store",
682
+ geo: "read:store"
683
+ // geo is global reference data, scoped to read:store
590
684
  };
591
685
  var BILLING_OPERATION = {
592
686
  GET_PLANS: "getPlans",
@@ -998,16 +1092,44 @@ function useWhataloData() {
998
1092
  },
999
1093
  [fetchResource]
1000
1094
  );
1095
+ const storeGet = (0, import_react3.useCallback)(async () => {
1096
+ const ack = await fetchResource("store", "get");
1097
+ return extractAckData(ack);
1098
+ }, [fetchResource]);
1099
+ const geoCountries = (0, import_react3.useCallback)(
1100
+ async (params) => {
1101
+ const ack = await fetchResource(
1102
+ "geo",
1103
+ "list",
1104
+ { ...params, _sub: "countries" }
1105
+ );
1106
+ return extractAckData(ack);
1107
+ },
1108
+ [fetchResource]
1109
+ );
1110
+ const geoProvinces = (0, import_react3.useCallback)(
1111
+ async (countryIso2) => {
1112
+ const ack = await fetchResource(
1113
+ "geo",
1114
+ "list",
1115
+ { _sub: "provinces", country: countryIso2 }
1116
+ );
1117
+ return extractAckData(ack);
1118
+ },
1119
+ [fetchResource]
1120
+ );
1001
1121
  return {
1002
1122
  products: { list: productsList, get: productsGet },
1003
1123
  orders: { list: ordersList, get: ordersGet },
1004
1124
  customers: { list: customersList, get: customersGet },
1005
- categories: { list: categoriesList, get: categoriesGet }
1125
+ categories: { list: categoriesList, get: categoriesGet },
1126
+ store: { get: storeGet },
1127
+ geo: { countries: geoCountries, provinces: geoProvinces }
1006
1128
  };
1007
1129
  }
1008
1130
 
1009
1131
  // src/index.ts
1010
- var SDK_VERSION = "0.0.1";
1132
+ var SDK_VERSION = "1.2.0";
1011
1133
  // Annotate the CommonJS export names for ESM import in node:
1012
1134
  0 && (module.exports = {
1013
1135
  AuthenticationError,
@@ -1020,10 +1142,13 @@ var SDK_VERSION = "0.0.1";
1020
1142
  RateLimitError,
1021
1143
  SDK_VERSION,
1022
1144
  ValidationError,
1145
+ WEBHOOK_EVENTS,
1023
1146
  WhataloAPIError,
1024
1147
  WhataloClient,
1025
1148
  clearSessionTokenCache,
1026
1149
  defineApp,
1150
+ isRuntimeWebhookPayload,
1151
+ isWebhookEvent,
1027
1152
  sessionToken,
1028
1153
  useAppBridge,
1029
1154
  useWhataloAction,