@stacksjs/commerce 0.75.112 → 0.75.114

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 (230) hide show
  1. package/README.md +15 -0
  2. package/dist/auctions/bids/fetch.js +1 -0
  3. package/dist/auctions/bids/index.js +1 -0
  4. package/dist/auctions/bids/place.js +1 -0
  5. package/dist/auctions/engine/anti-snipe.js +1 -0
  6. package/dist/auctions/engine/increments.js +1 -0
  7. package/dist/auctions/engine/index.js +1 -0
  8. package/dist/auctions/engine/proxy.js +1 -0
  9. package/dist/auctions/engine/winners.js +1 -0
  10. package/dist/auctions/index.js +1 -0
  11. package/dist/auctions/lots/fetch.js +1 -0
  12. package/dist/auctions/lots/index.js +1 -0
  13. package/dist/auctions/lots/lifecycle.js +1 -0
  14. package/dist/auctions/notifications.js +1 -0
  15. package/dist/auctions/pledges/index.js +1 -0
  16. package/dist/auctions/realtime.js +1 -0
  17. package/dist/auctions/rules.js +1 -0
  18. package/dist/auctions/types.js +0 -0
  19. package/dist/carts/destroy.js +1 -0
  20. package/dist/carts/fetch.js +1 -0
  21. package/dist/carts/index.js +1 -0
  22. package/dist/carts/store.js +1 -0
  23. package/dist/carts/update.js +1 -0
  24. package/dist/catalog.js +1 -2
  25. package/dist/coupons/destroy.js +1 -0
  26. package/dist/coupons/fetch.js +1 -0
  27. package/dist/coupons/index.js +1 -0
  28. package/dist/coupons/store.js +1 -0
  29. package/dist/coupons/update.js +7 -0
  30. package/dist/customers/destroy.js +1 -0
  31. package/dist/customers/fetch.js +1 -0
  32. package/dist/customers/index.js +1 -0
  33. package/dist/customers/store.js +1 -0
  34. package/dist/customers/update.js +1 -0
  35. package/dist/devices/destroy.js +1 -0
  36. package/dist/devices/export.js +1 -0
  37. package/dist/devices/fetch.js +1 -0
  38. package/dist/devices/index.js +1 -0
  39. package/dist/devices/store.js +1 -0
  40. package/dist/devices/update.js +1 -0
  41. package/dist/errors/destroy.js +1 -0
  42. package/dist/errors/fetch.js +1 -0
  43. package/dist/errors/index.js +1 -0
  44. package/dist/errors/update.js +1 -0
  45. package/dist/gift-cards/destroy.js +1 -0
  46. package/dist/gift-cards/fetch.js +1 -0
  47. package/dist/gift-cards/index.js +1 -0
  48. package/dist/gift-cards/store.js +1 -0
  49. package/dist/gift-cards/update.js +10 -0
  50. package/dist/imports/account-mapping.js +1 -0
  51. package/dist/imports/account-types.js +0 -0
  52. package/dist/imports/account-writer.js +1 -0
  53. package/dist/imports/admin-http.js +1 -0
  54. package/dist/imports/credentials.js +1 -0
  55. package/dist/imports/http.js +1 -0
  56. package/dist/imports/identity.js +1 -0
  57. package/dist/imports/index.js +1 -0
  58. package/dist/imports/money.js +1 -0
  59. package/dist/imports/shopify-admin.js +1 -0
  60. package/dist/imports/shopify.js +1 -0
  61. package/dist/imports/shopware-admin.js +1 -0
  62. package/dist/imports/shopware.js +1 -0
  63. package/dist/imports/text.js +1 -0
  64. package/dist/imports/types.js +0 -0
  65. package/dist/imports/woocommerce-admin.js +1 -0
  66. package/dist/imports/woocommerce.js +1 -0
  67. package/dist/imports/writer.js +1 -0
  68. package/dist/index.d.ts +3 -0
  69. package/dist/index.js +1 -28
  70. package/dist/inventory.d.ts +2 -0
  71. package/dist/inventory.js +1 -0
  72. package/dist/money.js +1 -2
  73. package/dist/orders/destroy.js +1 -0
  74. package/dist/orders/events.js +1 -0
  75. package/dist/orders/export.js +1 -0
  76. package/dist/orders/fetch.js +1 -0
  77. package/dist/orders/guards.js +1 -0
  78. package/dist/orders/index.js +1 -0
  79. package/dist/orders/place-order.js +1 -0
  80. package/dist/orders/store.js +1 -0
  81. package/dist/orders/totals.js +1 -0
  82. package/dist/orders/transition.js +1 -0
  83. package/dist/orders/update.js +1 -0
  84. package/dist/orders/webhook.js +1 -0
  85. package/dist/payments/destroy.js +1 -0
  86. package/dist/payments/fetch.js +1 -0
  87. package/dist/payments/index.js +1 -0
  88. package/dist/payments/store.js +1 -0
  89. package/dist/payments/update.js +8 -0
  90. package/dist/product.d.ts +1 -0
  91. package/dist/product.js +0 -0
  92. package/dist/products/categories/destroy.js +1 -0
  93. package/dist/products/categories/fetch.js +1 -0
  94. package/dist/products/categories/index.js +1 -0
  95. package/dist/products/categories/store.js +1 -0
  96. package/dist/products/categories/types.js +0 -0
  97. package/dist/products/categories/update.js +1 -0
  98. package/dist/products/index.js +1 -0
  99. package/dist/products/items/destroy.js +1 -0
  100. package/dist/products/items/fetch.js +1 -0
  101. package/dist/products/items/index.d.ts +1 -0
  102. package/dist/products/items/index.js +1 -0
  103. package/dist/products/items/store.js +1 -0
  104. package/dist/products/items/update.d.ts +2 -0
  105. package/dist/products/items/update.js +1 -0
  106. package/dist/products/manufacturers/destroy.js +1 -0
  107. package/dist/products/manufacturers/fetch.js +1 -0
  108. package/dist/products/manufacturers/index.js +1 -0
  109. package/dist/products/manufacturers/store.js +1 -0
  110. package/dist/products/manufacturers/update.js +1 -0
  111. package/dist/products/reviews/destroy.js +1 -0
  112. package/dist/products/reviews/fetch.js +1 -0
  113. package/dist/products/reviews/index.js +1 -0
  114. package/dist/products/reviews/stats.js +1 -0
  115. package/dist/products/reviews/store.js +1 -0
  116. package/dist/products/reviews/update.js +1 -0
  117. package/dist/products/units/destroy.js +1 -0
  118. package/dist/products/units/fetch.js +1 -0
  119. package/dist/products/units/index.js +1 -0
  120. package/dist/products/units/store.js +1 -0
  121. package/dist/products/units/types.js +0 -0
  122. package/dist/products/units/update.js +1 -0
  123. package/dist/products/variants/destroy.js +1 -0
  124. package/dist/products/variants/fetch.js +1 -0
  125. package/dist/products/variants/index.js +1 -0
  126. package/dist/products/variants/store.js +1 -0
  127. package/dist/products/variants/update.js +1 -0
  128. package/dist/receipts/destroy.js +1 -0
  129. package/dist/receipts/export.d.ts +1 -0
  130. package/dist/receipts/export.js +0 -0
  131. package/dist/receipts/fetch.js +1 -0
  132. package/dist/receipts/index.js +1 -0
  133. package/dist/receipts/printer.d.ts +37 -0
  134. package/dist/receipts/printer.js +1 -0
  135. package/dist/receipts/store.js +1 -0
  136. package/dist/receipts/timestamp.js +1 -0
  137. package/dist/receipts/update.js +1 -0
  138. package/dist/refund-allocation.js +1 -2
  139. package/dist/register.js +1 -2
  140. package/dist/releases.js +1 -2
  141. package/dist/sales-tax.js +1 -2
  142. package/dist/shippings/couriers/destroy.js +1 -0
  143. package/dist/shippings/couriers/fetch.js +1 -0
  144. package/dist/shippings/couriers/index.js +1 -0
  145. package/dist/shippings/couriers/store.js +1 -0
  146. package/dist/shippings/couriers/update.js +1 -0
  147. package/dist/shippings/delivery-routes/destroy.js +1 -0
  148. package/dist/shippings/delivery-routes/fetch.js +1 -0
  149. package/dist/shippings/delivery-routes/index.js +1 -0
  150. package/dist/shippings/delivery-routes/store.js +1 -0
  151. package/dist/shippings/delivery-routes/update.js +1 -0
  152. package/dist/shippings/delivery-routes/validate-write.js +1 -0
  153. package/dist/shippings/digital-deliveries/destroy.js +1 -0
  154. package/dist/shippings/digital-deliveries/fetch.js +1 -0
  155. package/dist/shippings/digital-deliveries/index.js +1 -0
  156. package/dist/shippings/digital-deliveries/store.js +1 -0
  157. package/dist/shippings/digital-deliveries/update.js +1 -0
  158. package/dist/shippings/geocoding/index.js +1 -0
  159. package/dist/shippings/geocoding/nominatim.js +1 -0
  160. package/dist/shippings/geocoding/types.js +1 -0
  161. package/dist/shippings/index.js +1 -0
  162. package/dist/shippings/license-keys/destroy.js +1 -0
  163. package/dist/shippings/license-keys/fetch.js +1 -0
  164. package/dist/shippings/license-keys/index.js +1 -0
  165. package/dist/shippings/license-keys/store.js +1 -0
  166. package/dist/shippings/license-keys/update.js +1 -0
  167. package/dist/shippings/license-keys/validate-write.js +1 -0
  168. package/dist/shippings/shipping-methods/destroy.js +1 -0
  169. package/dist/shippings/shipping-methods/fetch.js +1 -0
  170. package/dist/shippings/shipping-methods/index.js +1 -0
  171. package/dist/shippings/shipping-methods/store.js +1 -0
  172. package/dist/shippings/shipping-methods/update.js +1 -0
  173. package/dist/shippings/shipping-rates/destroy.js +1 -0
  174. package/dist/shippings/shipping-rates/fetch.js +1 -0
  175. package/dist/shippings/shipping-rates/index.js +1 -0
  176. package/dist/shippings/shipping-rates/store.js +1 -0
  177. package/dist/shippings/shipping-rates/update.js +1 -0
  178. package/dist/shippings/shipping-rates/validate-write.js +1 -0
  179. package/dist/shippings/shipping-zones/destroy.js +1 -0
  180. package/dist/shippings/shipping-zones/fetch.js +1 -0
  181. package/dist/shippings/shipping-zones/index.js +1 -0
  182. package/dist/shippings/shipping-zones/store.js +1 -0
  183. package/dist/shippings/shipping-zones/update.js +1 -0
  184. package/dist/shippings/tracking/events.js +1 -0
  185. package/dist/shippings/tracking/geo.js +1 -0
  186. package/dist/shippings/tracking/index.js +1 -0
  187. package/dist/shippings/tracking/ping.js +1 -0
  188. package/dist/shippings/tracking/stops.js +1 -0
  189. package/dist/shippings/write-data.js +1 -0
  190. package/dist/tax/breakdown.js +1 -0
  191. package/dist/tax/destroy.js +1 -0
  192. package/dist/tax/fetch.js +1 -0
  193. package/dist/tax/index.js +1 -0
  194. package/dist/tax/store.js +1 -0
  195. package/dist/tax/types.js +0 -0
  196. package/dist/tax/update.js +1 -0
  197. package/dist/tax-input.d.ts +7 -0
  198. package/dist/tax-input.js +1 -0
  199. package/dist/tests/fixtures/returning-all-writes.d.ts +1 -0
  200. package/dist/tests/fixtures/returning-all-writes.js +1 -0
  201. package/dist/tests/fixtures/soft-delete-counts.d.ts +1 -0
  202. package/dist/tests/fixtures/soft-delete-counts.js +1 -0
  203. package/dist/tests/fixtures/write-counts.d.ts +1 -0
  204. package/dist/tests/fixtures/write-counts.js +8 -0
  205. package/dist/tests/setup.d.ts +5 -0
  206. package/dist/tests/setup.js +1 -0
  207. package/dist/types.js +0 -0
  208. package/dist/utils/inserted-id.js +1 -0
  209. package/dist/utils/inventory-adjustment.js +5 -0
  210. package/dist/utils/model-row.js +1 -0
  211. package/dist/utils/mutation-count.js +1 -0
  212. package/dist/utils/typed-stats.js +1 -0
  213. package/dist/waitlists/index.js +1 -0
  214. package/dist/waitlists/products/destroy.js +1 -0
  215. package/dist/waitlists/products/export.d.ts +41 -0
  216. package/dist/waitlists/products/export.js +1 -0
  217. package/dist/waitlists/products/fetch.js +1 -0
  218. package/dist/waitlists/products/index.js +1 -0
  219. package/dist/waitlists/products/store.js +1 -0
  220. package/dist/waitlists/products/update.js +1 -0
  221. package/dist/waitlists/products/write-data.js +1 -0
  222. package/dist/waitlists/restaurant/destroy.js +1 -0
  223. package/dist/waitlists/restaurant/export.d.ts +39 -0
  224. package/dist/waitlists/restaurant/export.js +1 -0
  225. package/dist/waitlists/restaurant/fetch.js +1 -0
  226. package/dist/waitlists/restaurant/index.js +1 -0
  227. package/dist/waitlists/restaurant/store.js +1 -0
  228. package/dist/waitlists/restaurant/update.js +1 -0
  229. package/dist/waitlists/restaurant/write-data.js +1 -0
  230. package/package.json +13 -12
@@ -0,0 +1 @@
1
+ import{db}from"@stacksjs/database/runtime";import{asModelRow,asModelRows}from"../../utils/model-row";import{formatDate}from"@stacksjs/orm";export async function fetchById(id){const row=await db.selectFrom("waitlist_products").where("id","=",id).selectAll().executeTakeFirst();return asModelRow(row,!0)}export async function fetchAll(){return asModelRows(await db.selectFrom("waitlist_products").selectAll().execute())}export async function fetchCountBySource(startDate,_endDate){let query=db.selectFrom("waitlist_products").select(["source",db.fn.count("id").as("count")]).groupBy("source");if(startDate&&_endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(_endDate);query=query.where("created_at",">=",startDateStr).where("created_at","<=",endDateStr)}return(await query.execute()).reduce((acc,{source,count})=>{acc[source]=count;return acc},{})}export async function fetchCountByDate(date=new Date){const startOfDay=new Date(date);startOfDay.setHours(0,0,0,0);const endOfDay=new Date(date);endOfDay.setHours(23,59,59,999);const startDateStr=formatDate(startOfDay),endDateStr=formatDate(endOfDay);return(await db.selectFrom("waitlist_products").select(db.fn.count("id").as("count")).where("created_at",">=",startDateStr).where("created_at","<=",endDateStr).executeTakeFirst())?.count??0}export async function fetchCountByQuantity(quantity){return(await db.selectFrom("waitlist_products").select(db.fn.count("id").as("count")).where("quantity","=",quantity).executeTakeFirst())?.count??0}export async function fetchCountByAllQuantities(startDate,_endDate){let query=db.selectFrom("waitlist_products").select(["quantity",db.fn.count("id").as("count")]).groupBy("quantity");if(startDate&&_endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(_endDate);query=query.where("created_at",">=",startDateStr).where("created_at","<=",endDateStr)}return(await query.execute()).reduce((acc,{quantity,count})=>{acc[quantity]=count;return acc},{})}export async function fetchBetweenDates(startDate,endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(endDate),rows=await db.selectFrom("waitlist_products").selectAll().where("created_at",">=",startDateStr).where("created_at","<=",endDateStr).execute();return asModelRows(rows)}export async function fetchNotifiedBetweenDates(startDate,endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(endDate),rows=await db.selectFrom("waitlist_products").selectAll().where("notified_at",">=",startDateStr).where("notified_at","<=",endDateStr).whereNotNull("notified_at").execute();return asModelRows(rows)}export async function fetchPurchasedBetweenDates(startDate,endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(endDate),rows=await db.selectFrom("waitlist_products").selectAll().where("purchased_at",">=",startDateStr).where("purchased_at","<=",endDateStr).whereNotNull("purchased_at").execute();return asModelRows(rows)}export async function fetchCancelledBetweenDates(startDate,endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(endDate),rows=await db.selectFrom("waitlist_products").selectAll().where("cancelled_at",">=",startDateStr).where("cancelled_at","<=",endDateStr).whereNotNull("cancelled_at").execute();return asModelRows(rows)}export async function fetchWaiting(){const rows=await db.selectFrom("waitlist_products").selectAll().where("status","=","waiting").execute();return asModelRows(rows)}export async function fetchCountByStatus(status,startDate,_endDate){let query=db.selectFrom("waitlist_products").select(db.fn.count("id").as("count")).where("status","=",status);if(startDate&&_endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(_endDate);query=query.where("created_at",">=",startDateStr).where("created_at","<=",endDateStr)}return(await query.executeTakeFirst())?.count??0}export async function fetchConversionRates(_startDate,_endDate){let query=db.selectFrom("waitlist_products").select(["status",db.fn.count("id").as("count")]).groupBy("status");if(_startDate&&_endDate){const startDateStr=formatDate(_startDate),endDateStr=formatDate(_endDate);query=query.where("created_at",">=",startDateStr).where("created_at","<=",endDateStr)}const results=await query.execute(),totalCount=results.reduce((sum,{count})=>sum+count,0),purchasedCount=Number(results.find((r)=>r.status==="purchased")?.count??0),totalConversionRate=totalCount>0?purchasedCount/totalCount*100:0,statusBreakdown=results.reduce((acc,{status,count})=>{acc[status]={count,percentage:totalCount>0?count/totalCount*100:0};return acc},{});return{totalConversionRate,statusBreakdown}}export async function fetchCountBetweenDates(startDate,endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(endDate);return(await db.selectFrom("waitlist_products").select(db.fn.count("id").as("count")).where("created_at",">=",startDateStr).where("created_at","<=",endDateStr).executeTakeFirst())?.count??0}export async function fetchCountByDateGrouped(startDate,_endDate){let query=db.selectFrom("waitlist_products").select(["created_at"]);if(startDate&&_endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(_endDate);query=query.where("created_at",">=",startDateStr).where("created_at","<=",endDateStr)}const dateCounts=(await query.execute()).reduce((acc,{created_at})=>{const date=(created_at||"").split("T")[0]||"unknown";acc[date]=(acc[date]||0)+1;return acc},{});return Object.entries(dateCounts).map(([date,count])=>({date,count})).sort((a,b)=>a.date.localeCompare(b.date))}
@@ -0,0 +1 @@
1
+ export{bulkDestroy,destroy}from"./destroy";export{fetchAll,fetchById,fetchCancelledBetweenDates,fetchConversionRates,fetchCountBetweenDates,fetchCountByAllQuantities,fetchCountByDate,fetchCountByDateGrouped,fetchCountByQuantity,fetchCountBySource,fetchCountByStatus,fetchNotifiedBetweenDates,fetchPurchasedBetweenDates,fetchWaiting}from"./fetch";export{bulkStore,store}from"./store";export{update,updatePartySize,updateStatus}from"./update";
@@ -0,0 +1 @@
1
+ import{randomUUIDv7}from"bun";import{db}from"@stacksjs/database/runtime";import{asModelRow}from"../../utils/model-row";import{mutationCount}from"../../utils/mutation-count";import{productWaitlistWriteData}from"./write-data";export async function store(data){try{const uuid=randomUUIDv7(),waitlistData={...productWaitlistWriteData(data),uuid,status:data.status||"waiting"};await db.insertInto("waitlist_products").values(waitlistData).executeTakeFirst();const result=await db.selectFrom("waitlist_products").where("uuid","=",uuid).selectAll().executeTakeFirst();if(!result)throw Error("Failed to create waitlist product");return asModelRow(result)}catch(error){if(error instanceof Error)throw TypeError(`Failed to create waitlist product: ${error.message}`);throw error}}export async function bulkStore(data){if(!data.length)return 0;try{const waitlistDataArray=data.map((item)=>({...productWaitlistWriteData(item),status:item.status||"waiting",uuid:randomUUIDv7()})),result=await db.insertInto("waitlist_products").values(waitlistDataArray).executeTakeFirst();return mutationCount(result)}catch(error){if(error instanceof Error)throw TypeError(`Failed to create waitlist products in bulk: ${error.message}`);throw error}}
@@ -0,0 +1 @@
1
+ import{db}from"@stacksjs/database/runtime";import{asModelRow}from"../../utils/model-row";import{formatDate}from"@stacksjs/orm";import{fetchById}from"./fetch";import{productWaitlistWriteData}from"./write-data";export async function update(id,data){try{if(!id)throw Error("Waitlist product ID is required for update");const existing=await fetchById(id);if(!existing)return;await db.updateTable("waitlist_products").set({...productWaitlistWriteData(data,existing),updated_at:formatDate(new Date)}).where("id","=",id).execute();const result=await fetchById(id);if(!result)return;return asModelRow(result)}catch(error){if(error instanceof Error)throw TypeError(`Failed to update waitlist product: ${error.message}`);throw error}}export async function updateStatus(id,status){return await update(id,{status})}export async function updatePartySize(id,partySize){return await update(id,{quantity:partySize})}
@@ -0,0 +1 @@
1
+ import{formatDate}from"@stacksjs/orm";const statusTimestamp={notified:"notified_at",purchased:"purchased_at",cancelled:"cancelled_at"};function dateValue(value){return typeof value==="number"||value instanceof Date?formatDate(value):value}export function productWaitlistWriteData(data,existing={}){const result=Object.fromEntries(Object.entries(data).filter(([,value])=>value!==void 0));if(result.quantity===void 0&&result.party_size!==void 0)result.quantity=result.party_size;delete result.party_size;for(const field of["notified_at","purchased_at","cancelled_at"])if(result[field]!==void 0)result[field]=dateValue(result[field]);const timestampField=statusTimestamp[result.status];if(timestampField&&result[timestampField]===void 0&&!existing[timestampField])result[timestampField]=formatDate(new Date);return result}
@@ -0,0 +1 @@
1
+ import{db}from"@stacksjs/database/runtime";import{asModelRow}from"../../utils/model-row";import{mutationCount}from"../../utils/mutation-count";export async function destroy(id){try{const waitlistEntry=await db.selectFrom("waitlist_restaurants").where("id","=",id).selectAll().executeTakeFirst();if(!waitlistEntry)return;await db.deleteFrom("waitlist_restaurants").where("id","=",id).execute();return asModelRow(waitlistEntry)}catch(error){if(error instanceof Error)throw TypeError(`Failed to delete restaurant waitlist entry: ${error.message}`);throw error}}export async function bulkDestroy(ids){if(!ids.length)return 0;try{const result=await db.deleteFrom("waitlist_restaurants").where("id","in",ids).executeTakeFirst();return mutationCount(result)}catch(error){if(error instanceof Error)throw TypeError(`Failed to delete restaurant waitlist entries in bulk: ${error.message}`);throw error}}
@@ -0,0 +1,39 @@
1
+ import type { ModelRow, WaitlistRestaurant } from '@stacksjs/orm';
2
+ import type { SpreadsheetWrapper } from 'ts-spreadsheets';
3
+ /**
4
+ * Export restaurant waitlist entries to a spreadsheet
5
+ * @param format The format of the spreadsheet (default is CSV)
6
+ * @returns Spreadsheet object ready for download or storage
7
+ */
8
+ export declare function exportRestaurantWaitlist(format?: 'csv' | 'excel'): Promise<SpreadsheetWrapper>;
9
+ /**
10
+ * Export restaurant waitlist entries and automatically download
11
+ * @param format The format of the spreadsheet (default is CSV)
12
+ * @param filename Optional filename for the download
13
+ * @returns Download response
14
+ */
15
+ export declare function downloadRestaurantWaitlist(format?: 'csv' | 'excel', filename?: string): Promise<Response>;
16
+ /**
17
+ * Store restaurant waitlist export to disk
18
+ * @param format The format of the spreadsheet (default is CSV)
19
+ * @param path Optional path to store the file
20
+ * @returns Path where the file is stored
21
+ */
22
+ export declare function storeRestaurantWaitlistExport(format?: 'csv' | 'excel', path?: string): Promise<void>;
23
+ /**
24
+ * Represents the structure of an exported restaurant waitlist entry
25
+ */
26
+ export declare interface ExportedRestaurantWaitlist {
27
+ 'ID': number
28
+ 'Name': string
29
+ 'Phone': string
30
+ 'Party Size': number
31
+ 'Table Preference': string
32
+ 'Status': string
33
+ 'Quoted Wait Time': number
34
+ 'Actual Wait Time': number
35
+ 'Check In Time': string
36
+ 'Created At': string
37
+ 'Notes': string
38
+ }
39
+ declare type WaitlistRestaurantJsonResponse = ModelRow<typeof WaitlistRestaurant>;
@@ -0,0 +1 @@
1
+ import{createSpreadsheet}from"ts-spreadsheets";import{fetchAll}from"./fetch";export async function exportRestaurantWaitlist(format="csv"){const waitlistEntries=await fetchAll(),spreadsheetData=prepareRestaurantWaitlistForExport(waitlistEntries);return createSpreadsheet(spreadsheetData,{type:format})}function prepareRestaurantWaitlistForExport(waitlistEntries){const headings=["ID","Name","Phone","Party Size","Table Preference","Status","Quoted Wait Time","Actual Wait Time","Check In Time","Created At","Notes"],data=waitlistEntries.map((entry)=>{return[entry.id,entry.name,entry.phone||"N/A",entry.partySize,entry.tablePreference,entry.status,entry.quoted_wait_time||"N/A",entry.actual_wait_time||"N/A",entry.checkInTime||"N/A",entry.created_at,"N/A"]});return{headings,data}}export async function downloadRestaurantWaitlist(format="csv",filename){const spreadsheet=await exportRestaurantWaitlist(format),defaultFilename=`restaurant_waitlist_export_${new Date().toISOString().split("T")[0]}.${format}`;return spreadsheet.download(filename||defaultFilename)}export async function storeRestaurantWaitlistExport(format="csv",path){const spreadsheet=await exportRestaurantWaitlist(format),defaultPath=`restaurant_waitlist_export_${new Date().toISOString().split("T")[0]}.${format}`;spreadsheet.store(path||defaultPath)}
@@ -0,0 +1 @@
1
+ import{db}from"@stacksjs/database/runtime";import{asModelRow,asModelRows}from"../../utils/model-row";import{formatDate}from"@stacksjs/orm";export async function fetchById(id){const row=await db.selectFrom("waitlist_restaurants").where("id","=",id).selectAll().executeTakeFirst();return asModelRow(row,!0)}export async function fetchAll(){return asModelRows(await db.selectFrom("waitlist_restaurants").selectAll().execute())}export async function fetchCountByTablePreference(){return(await db.selectFrom("waitlist_restaurants").select(["table_preference",db.fn.count("id").as("count")]).groupBy("table_preference").execute()).reduce((acc,{table_preference,count})=>{acc[table_preference]=count;return acc},{})}export async function fetchCountByDate(date=new Date){const startOfDay=new Date(date);startOfDay.setHours(0,0,0,0);const endOfDay=new Date(date);endOfDay.setHours(23,59,59,999);const startDateStr=formatDate(startOfDay),endDateStr=formatDate(endOfDay);return(await db.selectFrom("waitlist_restaurants").select(db.fn.count("id").as("count")).where("created_at",">=",startDateStr).where("created_at","<=",endDateStr).executeTakeFirst())?.count??0}export async function fetchCountByPartySize(partySize){return(await db.selectFrom("waitlist_restaurants").select(db.fn.count("id").as("count")).where("party_size","=",partySize).executeTakeFirst())?.count??0}export async function fetchCountByAllPartySizes(){return(await db.selectFrom("waitlist_restaurants").select(["party_size",db.fn.count("id").as("count")]).groupBy("party_size").execute()).reduce((acc,{party_size,count})=>{acc[party_size]=count;return acc},{})}export async function fetchBetweenDates(startDate,_endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(_endDate),rows=await db.selectFrom("waitlist_restaurants").selectAll().where("created_at",">=",startDateStr).where("created_at","<=",endDateStr).execute();return asModelRows(rows)}export async function fetchSeatedBetweenDates(startDate,_endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(_endDate),rows=await db.selectFrom("waitlist_restaurants").selectAll().where("check_in_time",">=",startDateStr).where("check_in_time","<=",endDateStr).where("status","=","seated").execute();return asModelRows(rows)}export async function fetchWaiting(){const rows=await db.selectFrom("waitlist_restaurants").selectAll().where("status","=","waiting").execute();return asModelRows(rows)}export async function fetchConversionRates(){const results=await db.selectFrom("waitlist_restaurants").select(["status",db.fn.count("id").as("count")]).groupBy("status").execute(),totalCount=results.reduce((sum,{count})=>sum+count,0),seatedCount=results.find((r)=>r.status==="seated")?.count??0,totalConversionRate=totalCount>0?Number(seatedCount)/totalCount*100:0,statusBreakdown=results.reduce((acc,{status,count})=>{acc[status]={count,percentage:totalCount>0?count/totalCount*100:0};return acc},{});return{totalConversionRate,statusBreakdown}}export async function fetchAverageWaitTimes(){const result=await db.selectFrom("waitlist_restaurants").select([db.fn.avg("quoted_wait_time").as("avg_quoted_wait_time"),db.fn.avg("actual_wait_time").as("avg_actual_wait_time")]).executeTakeFirst();return{averageQuotedWaitTime:result?.avg_quoted_wait_time??0,averageActualWaitTime:result?.avg_actual_wait_time??0}}export async function fetchWaitingWithQuotedTimes(){const waitingEntries=asModelRows(await db.selectFrom("waitlist_restaurants").selectAll().where("status","=","waiting").execute()),totalQuotedWaitTime=waitingEntries.reduce((sum,entry)=>sum+(entry.quoted_wait_time??0),0),averageQuotedWaitTime=waitingEntries.length>0?totalQuotedWaitTime/waitingEntries.length:0;return{entries:waitingEntries,totalQuotedWaitTime,averageQuotedWaitTime}}export async function fetchWaitingWithPartySizes(){const waitingEntries=asModelRows(await db.selectFrom("waitlist_restaurants").selectAll().where("status","=","waiting").execute()),totalPartySize=waitingEntries.reduce((sum,entry)=>sum+entry.party_size,0),averagePartySize=waitingEntries.length>0?totalPartySize/waitingEntries.length:0,partySizeBreakdown=waitingEntries.reduce((acc,entry)=>{acc[entry.party_size]=(acc[entry.party_size]||0)+1;return acc},{});return{entries:waitingEntries,totalPartySize,averagePartySize,partySizeBreakdown}}export async function fetchTablesTurnedToday(){const today=new Date,startOfDay=new Date(today);startOfDay.setHours(0,0,0,0);const endOfDay=new Date(today);endOfDay.setHours(23,59,59,999);const startDateStr=formatDate(startOfDay),endDateStr=formatDate(endOfDay),seatedEntries=await db.selectFrom("waitlist_restaurants").selectAll().where("status","=","seated").where("check_in_time",">=",startDateStr).where("check_in_time","<=",endDateStr).execute(),totalTablesTurned=seatedEntries.length,totalCustomersSeated=seatedEntries.reduce((sum,entry)=>sum+entry.party_size,0),averagePartySize=totalTablesTurned>0?totalCustomersSeated/totalTablesTurned:0,breakdownByTablePreference=seatedEntries.reduce((acc,entry)=>{acc[entry.table_preference]=(acc[entry.table_preference]||0)+1;return acc},{}),breakdownByPartySize=seatedEntries.reduce((acc,entry)=>{acc[entry.party_size]=(acc[entry.party_size]||0)+1;return acc},{});return{totalTablesTurned,averagePartySize,totalCustomersSeated,breakdownByTablePreference,breakdownByPartySize}}export async function fetchSeatingRate(_startDate,_endDate){const startDateStr=formatDate(_startDate),endDateStr=formatDate(_endDate),results=await db.selectFrom("waitlist_restaurants").select(["status",db.fn.count("id").as("count")]).where("check_in_time",">=",startDateStr).where("check_in_time","<=",endDateStr).groupBy("status").execute(),totalEntries=results.reduce((sum,{count})=>sum+count,0),seatedCount=results.find((r)=>r.status==="seated")?.count??0,seatingRate=totalEntries>0?Number(seatedCount)/totalEntries*100:0,statusBreakdown=results.reduce((acc,{status,count})=>{acc[status]={count,percentage:totalEntries>0?count/totalEntries*100:0};return acc},{});return{totalEntries,seatedEntries:seatedCount,seatingRate,statusBreakdown}}export async function fetchNoShowStats(_startDate,_endDate){const startDateStr=formatDate(_startDate),endDateStr=formatDate(_endDate),noShowQuery=db.selectFrom("waitlist_restaurants").selectAll().where("status","=","no_show").where("check_in_time",">=",startDateStr).where("check_in_time","<=",endDateStr),totalResult=await db.selectFrom("waitlist_restaurants").select(db.fn.count("id").as("count")).where("check_in_time",">=",startDateStr).where("check_in_time","<=",endDateStr).executeTakeFirst(),noShowEntries=await noShowQuery.execute(),totalNoShows=noShowEntries.length,noShowRate=totalResult?.count&&totalResult.count>0?totalNoShows/totalResult.count*100:0,totalQuotedWaitTime=noShowEntries.reduce((sum,entry)=>sum+(entry.quoted_wait_time??0),0),averageQuotedWaitTime=totalNoShows>0?totalQuotedWaitTime/totalNoShows:0,totalPartySize=noShowEntries.reduce((sum,entry)=>sum+entry.party_size,0),averagePartySize=totalNoShows>0?totalPartySize/totalNoShows:0,breakdownByTablePreference=noShowEntries.reduce((acc,entry)=>{acc[entry.table_preference]=(acc[entry.table_preference]||0)+1;return acc},{}),breakdownByPartySize=noShowEntries.reduce((acc,entry)=>{acc[entry.party_size]=(acc[entry.party_size]||0)+1;return acc},{});return{totalNoShows,noShowRate,averageQuotedWaitTime,averagePartySize,breakdownByTablePreference,breakdownByPartySize}}export async function fetchCurrentWaitTimes(){const waitingEntries=await db.selectFrom("waitlist_restaurants").select(["quoted_wait_time","actual_wait_time"]).where("status","=","waiting").execute(),totalQuoted=waitingEntries.reduce((sum,entry)=>sum+(entry.quoted_wait_time||0),0),totalActual=waitingEntries.reduce((sum,entry)=>sum+(entry.actual_wait_time||0),0),count=waitingEntries.length;return{averageQuoted:count>0?totalQuoted/count:0,averageActual:count>0?totalActual/count:0}}export async function fetchSeatedStats(){const twentyFourHoursAgo=Date.now()-86400000,seatedEntries=await db.selectFrom("waitlist_restaurants").select(["seated_at"]).where("status","=","seated").where("seated_at",">=",twentyFourHoursAgo).execute(),byHour=Array.from({length:24},(_,hour)=>({hour,count:seatedEntries.filter((entry)=>{return entry.seated_at===hour}).length}));return{total:seatedEntries.length,byHour}}export async function fetchTimeSeriesStats(){return(await db.selectFrom("waitlist_restaurants").select(["created_at","status"]).execute()).reduce((acc,curr)=>{const date=curr.created_at;if(!acc[date])acc[date]={total:0,waiting:0,seated:0,cancelled:0,no_show:0};acc[date].total++;acc[date][curr.status]++;return acc},{})}
@@ -0,0 +1 @@
1
+ export{bulkDestroy,destroy}from"./destroy";export{fetchAll,fetchAverageWaitTimes,fetchBetweenDates,fetchById,fetchConversionRates,fetchCountByAllPartySizes,fetchCountByDate,fetchCountByPartySize,fetchCountByTablePreference,fetchCurrentWaitTimes,fetchNoShowStats,fetchSeatedBetweenDates,fetchSeatedStats,fetchSeatingRate,fetchTablesTurnedToday,fetchTimeSeriesStats,fetchWaiting,fetchWaitingWithPartySizes,fetchWaitingWithQuotedTimes}from"./fetch";export{bulkStore,store}from"./store";export{update,updatePartySize,updateQueuePosition,updateStatus,updateWaitTimes}from"./update";
@@ -0,0 +1 @@
1
+ import{randomUUIDv7}from"bun";import{db}from"@stacksjs/database/runtime";import{asModelRow}from"../../utils/model-row";import{mutationCount}from"../../utils/mutation-count";import{restaurantWaitlistWriteData}from"./write-data";export async function store(data){try{const uuid=randomUUIDv7(),waitlistData={...restaurantWaitlistWriteData(data),status:data.status||"waiting",uuid};await db.insertInto("waitlist_restaurants").values(waitlistData).executeTakeFirst();const result=await db.selectFrom("waitlist_restaurants").where("uuid","=",uuid).selectAll().executeTakeFirst();if(!result)throw Error("Failed to create restaurant waitlist entry");return asModelRow(result)}catch(error){if(error instanceof Error)throw TypeError(`Failed to create restaurant waitlist entry: ${error.message}`);throw error}}export async function bulkStore(data){if(!data.length)return 0;try{const waitlistDataArray=data.map((item)=>({...restaurantWaitlistWriteData(item),status:item.status||"waiting",uuid:randomUUIDv7()})),result=await db.insertInto("waitlist_restaurants").values(waitlistDataArray).executeTakeFirst();return mutationCount(result)}catch(error){if(error instanceof Error)throw TypeError(`Failed to create restaurant waitlist entries in bulk: ${error.message}`);throw error}}
@@ -0,0 +1 @@
1
+ import{db}from"@stacksjs/database/runtime";import{asModelRow}from"../../utils/model-row";import{formatDate}from"@stacksjs/orm";import{fetchById}from"./fetch";import{restaurantWaitlistWriteData}from"./write-data";export async function update(id,data){try{if(!id)throw Error("Restaurant waitlist entry ID is required for update");const existing=await fetchById(id);if(!existing)return;await db.updateTable("waitlist_restaurants").set({...restaurantWaitlistWriteData(data,existing),updated_at:formatDate(new Date)}).where("id","=",id).execute();const result=await fetchById(id);if(!result)return;return asModelRow(result)}catch(error){if(error instanceof Error)throw TypeError(`Failed to update restaurant waitlist entry: ${error.message}`);throw error}}export async function updateStatus(id,status){return await update(id,{status})}export async function updatePartySize(id,partySize){return await update(id,{party_size:partySize})}export async function updateWaitTimes(id,quotedWaitTime,actualWaitTime){return await update(id,{quoted_wait_time:quotedWaitTime,...actualWaitTime===void 0?{}:{actual_wait_time:actualWaitTime}})}export async function updateQueuePosition(id,queuePosition){return await update(id,{queue_position:queuePosition})}
@@ -0,0 +1 @@
1
+ import{formatDate}from"@stacksjs/orm";const statusTimestamp={seated:"seated_at",no_show:"no_show_at",cancelled:"cancelled_at"};function timestamp(value){if(typeof value==="number")return formatDate(value<=2147483647?value*1000:value);if(value instanceof Date)return formatDate(value);return value}export function restaurantWaitlistWriteData(data,existing={}){const result=Object.fromEntries(Object.entries(data).filter(([,value])=>value!==void 0));for(const field of["check_in_time","seated_at","no_show_at","cancelled_at"])if(result[field]!==void 0)result[field]=timestamp(result[field]);const timestampField=statusTimestamp[result.status];if(timestampField&&result[timestampField]===void 0&&!existing[timestampField])result[timestampField]=formatDate(new Date);return result}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/commerce",
3
3
  "type": "module",
4
- "version": "0.75.112",
4
+ "version": "0.75.114",
5
5
  "description": "Stacks commerce utilities.",
6
6
  "author": "Chris Breuer",
7
7
  "contributors": [
@@ -57,17 +57,18 @@
57
57
  "prepublishOnly": "bun run build"
58
58
  },
59
59
  "dependencies": {
60
- "@stacksjs/cache": "0.75.112",
61
- "@stacksjs/config": "0.75.112",
62
- "@stacksjs/database": "0.75.112",
63
- "@stacksjs/env": "0.75.112",
64
- "@stacksjs/error-handling": "0.75.112",
65
- "@stacksjs/events": "0.75.112",
66
- "@stacksjs/logging": "0.75.112",
67
- "@stacksjs/orm": "0.75.112",
68
- "@stacksjs/payments": "0.75.112",
69
- "@stacksjs/realtime": "0.75.112",
70
- "@stacksjs/strings": "0.75.112",
60
+ "@stacksjs/cache": "0.75.114",
61
+ "@stacksjs/config": "0.75.114",
62
+ "@stacksjs/database": "0.75.114",
63
+ "@stacksjs/env": "0.75.114",
64
+ "@stacksjs/error-handling": "0.75.114",
65
+ "@stacksjs/events": "0.75.114",
66
+ "@stacksjs/logging": "0.75.114",
67
+ "@stacksjs/orm": "0.75.114",
68
+ "@stacksjs/payments": "0.75.114",
69
+ "@stacksjs/realtime": "0.75.114",
70
+ "@stacksjs/strings": "0.75.114",
71
+ "@stacksjs/validation": "0.75.114",
71
72
  "ts-spreadsheets": "^0.2.0"
72
73
  },
73
74
  "devDependencies": {