@elizaos/plugin-shopify-ui 2.0.3-beta.6 → 2.0.3-beta.7

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 (79) hide show
  1. package/dist/CustomersPanel.d.ts +11 -0
  2. package/dist/CustomersPanel.d.ts.map +1 -0
  3. package/dist/CustomersPanel.js +86 -0
  4. package/dist/CustomersPanel.js.map +1 -0
  5. package/dist/InventoryLevelsPanel.d.ts +10 -0
  6. package/dist/InventoryLevelsPanel.d.ts.map +1 -0
  7. package/dist/InventoryLevelsPanel.js +190 -0
  8. package/dist/InventoryLevelsPanel.js.map +1 -0
  9. package/dist/OrdersPanel.d.ts +12 -0
  10. package/dist/OrdersPanel.d.ts.map +1 -0
  11. package/dist/OrdersPanel.js +170 -0
  12. package/dist/OrdersPanel.js.map +1 -0
  13. package/dist/ProductsPanel.d.ts +13 -0
  14. package/dist/ProductsPanel.d.ts.map +1 -0
  15. package/dist/ProductsPanel.js +419 -0
  16. package/dist/ProductsPanel.js.map +1 -0
  17. package/dist/ShopifyAppView.d.ts +3 -0
  18. package/dist/ShopifyAppView.d.ts.map +1 -0
  19. package/dist/ShopifyAppView.helpers.d.ts +11 -0
  20. package/dist/ShopifyAppView.helpers.d.ts.map +1 -0
  21. package/dist/ShopifyAppView.helpers.js +59 -0
  22. package/dist/ShopifyAppView.helpers.js.map +1 -0
  23. package/dist/ShopifyAppView.interact.d.ts +2 -0
  24. package/dist/ShopifyAppView.interact.d.ts.map +1 -0
  25. package/dist/ShopifyAppView.interact.js +93 -0
  26. package/dist/ShopifyAppView.interact.js.map +1 -0
  27. package/dist/ShopifyAppView.js +667 -0
  28. package/dist/ShopifyAppView.js.map +1 -0
  29. package/dist/ShopifyView.d.ts +18 -0
  30. package/dist/ShopifyView.d.ts.map +1 -0
  31. package/dist/ShopifyView.js +143 -0
  32. package/dist/ShopifyView.js.map +1 -0
  33. package/dist/StoreOverviewCard.d.ts +13 -0
  34. package/dist/StoreOverviewCard.d.ts.map +1 -0
  35. package/dist/StoreOverviewCard.js +23 -0
  36. package/dist/StoreOverviewCard.js.map +1 -0
  37. package/dist/components/ShopifySpatialView.d.ts +57 -0
  38. package/dist/components/ShopifySpatialView.d.ts.map +1 -0
  39. package/dist/components/ShopifySpatialView.js +419 -0
  40. package/dist/components/ShopifySpatialView.js.map +1 -0
  41. package/dist/index.d.ts +14 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +20 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/plugin.d.ts +14 -0
  46. package/dist/plugin.d.ts.map +1 -0
  47. package/dist/plugin.js +94 -0
  48. package/dist/plugin.js.map +1 -0
  49. package/dist/register-routes.d.ts +2 -0
  50. package/dist/register-routes.d.ts.map +1 -0
  51. package/dist/register-routes.js +6 -0
  52. package/dist/register-routes.js.map +1 -0
  53. package/dist/register-terminal-view.d.ts +15 -0
  54. package/dist/register-terminal-view.d.ts.map +1 -0
  55. package/dist/register-terminal-view.js +37 -0
  56. package/dist/register-terminal-view.js.map +1 -0
  57. package/dist/register.d.ts +2 -0
  58. package/dist/register.d.ts.map +1 -0
  59. package/dist/register.js +17 -0
  60. package/dist/register.js.map +1 -0
  61. package/dist/routes.d.ts +18 -0
  62. package/dist/routes.d.ts.map +1 -0
  63. package/dist/routes.js +518 -0
  64. package/dist/routes.js.map +1 -0
  65. package/dist/shopify-app.d.ts +11 -0
  66. package/dist/shopify-app.d.ts.map +1 -0
  67. package/dist/shopify-app.js +16 -0
  68. package/dist/shopify-app.js.map +1 -0
  69. package/dist/shopify-view-bundle.d.ts +3 -0
  70. package/dist/shopify-view-bundle.d.ts.map +1 -0
  71. package/dist/shopify-view-bundle.js +7 -0
  72. package/dist/shopify-view-bundle.js.map +1 -0
  73. package/dist/useShopifyDashboard.d.ts +118 -0
  74. package/dist/useShopifyDashboard.d.ts.map +1 -0
  75. package/dist/useShopifyDashboard.js +212 -0
  76. package/dist/useShopifyDashboard.js.map +1 -0
  77. package/dist/views/bundle.js +948 -0
  78. package/dist/views/bundle.js.map +1 -0
  79. package/package.json +5 -5
@@ -0,0 +1,419 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import {
3
+ Button,
4
+ Card,
5
+ Divider,
6
+ Field,
7
+ HStack,
8
+ List,
9
+ Text,
10
+ VStack
11
+ } from "@elizaos/ui/spatial";
12
+ const TABS = [
13
+ { id: "overview", label: "Overview" },
14
+ { id: "products", label: "Products" },
15
+ { id: "orders", label: "Orders" },
16
+ { id: "inventory", label: "Inventory" },
17
+ { id: "customers", label: "Customers" }
18
+ ];
19
+ function financialTone(status) {
20
+ switch (status) {
21
+ case "PAID":
22
+ return "success";
23
+ case "PENDING":
24
+ return "warning";
25
+ case "REFUNDED":
26
+ case "PARTIALLY_REFUNDED":
27
+ return "danger";
28
+ default:
29
+ return "muted";
30
+ }
31
+ }
32
+ function productStatusTone(status) {
33
+ switch (status) {
34
+ case "ACTIVE":
35
+ return "success";
36
+ case "DRAFT":
37
+ return "warning";
38
+ default:
39
+ return "muted";
40
+ }
41
+ }
42
+ function inventoryTone(available) {
43
+ if (available === 0) return "danger";
44
+ if (available <= 5) return "warning";
45
+ return "default";
46
+ }
47
+ function CountTile({
48
+ label,
49
+ value,
50
+ tone,
51
+ agent,
52
+ onPress
53
+ }) {
54
+ return /* @__PURE__ */ jsxs(VStack, { gap: 0, grow: 1, children: [
55
+ /* @__PURE__ */ jsx(Text, { style: "subheading", tone, bold: true, children: value.toLocaleString() }),
56
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", tone: "default", agent, onPress, children: label })
57
+ ] });
58
+ }
59
+ function OverviewSection({
60
+ snapshot,
61
+ onAction
62
+ }) {
63
+ const lowInventory = snapshot.inventoryItems.filter(
64
+ (item) => item.available <= 5
65
+ );
66
+ const urgent = lowInventory.filter((item) => item.available === 0).length;
67
+ const go = (tab) => () => onAction?.(`tab:${tab}`);
68
+ return /* @__PURE__ */ jsxs(VStack, { gap: 1, width: "100%", children: [
69
+ /* @__PURE__ */ jsxs(HStack, { gap: 1, wrap: true, width: "100%", children: [
70
+ /* @__PURE__ */ jsx(
71
+ CountTile,
72
+ {
73
+ label: "Products",
74
+ value: snapshot.counts.productCount,
75
+ tone: "primary",
76
+ agent: "overview-products",
77
+ onPress: go("products")
78
+ }
79
+ ),
80
+ /* @__PURE__ */ jsx(
81
+ CountTile,
82
+ {
83
+ label: "Orders",
84
+ value: snapshot.counts.orderCount,
85
+ tone: "success",
86
+ agent: "overview-orders",
87
+ onPress: go("orders")
88
+ }
89
+ ),
90
+ /* @__PURE__ */ jsx(
91
+ CountTile,
92
+ {
93
+ label: "Low stock",
94
+ value: lowInventory.length,
95
+ tone: urgent > 0 ? "danger" : "warning",
96
+ agent: "overview-inventory",
97
+ onPress: go("inventory")
98
+ }
99
+ ),
100
+ /* @__PURE__ */ jsx(
101
+ CountTile,
102
+ {
103
+ label: "Customers",
104
+ value: snapshot.counts.customerCount,
105
+ tone: "muted",
106
+ agent: "overview-customers",
107
+ onPress: go("customers")
108
+ }
109
+ )
110
+ ] }),
111
+ /* @__PURE__ */ jsx(Divider, { label: "recent orders" }),
112
+ snapshot.orders.length === 0 ? /* @__PURE__ */ jsx(Text, { tone: "muted", align: "center", style: "caption", children: "None" }) : /* @__PURE__ */ jsx(List, { gap: 0, width: "100%", children: snapshot.orders.slice(0, 3).map((order) => /* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", width: "100%", children: [
113
+ /* @__PURE__ */ jsx(Text, { bold: true, wrap: false, width: 9, children: order.name }),
114
+ /* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", grow: 1, wrap: false, children: order.email || "guest" }),
115
+ /* @__PURE__ */ jsxs(Text, { wrap: false, children: [
116
+ order.totalPrice,
117
+ " ",
118
+ order.currencyCode
119
+ ] })
120
+ ] }, order.id)) }),
121
+ /* @__PURE__ */ jsx(Divider, { label: "low inventory" }),
122
+ lowInventory.length === 0 ? /* @__PURE__ */ jsx(Text, { tone: "muted", align: "center", style: "caption", children: "Stock levels look good" }) : /* @__PURE__ */ jsx(List, { gap: 0, width: "100%", children: lowInventory.slice(0, 3).map((item) => /* @__PURE__ */ jsxs(
123
+ HStack,
124
+ {
125
+ gap: 1,
126
+ align: "center",
127
+ width: "100%",
128
+ children: [
129
+ /* @__PURE__ */ jsxs(Text, { grow: 1, wrap: false, children: [
130
+ item.productTitle,
131
+ item.variantTitle ? ` / ${item.variantTitle}` : ""
132
+ ] }),
133
+ /* @__PURE__ */ jsx(Text, { tone: inventoryTone(item.available), bold: true, children: item.available })
134
+ ]
135
+ },
136
+ `${item.id}:${item.locationName}`
137
+ )) })
138
+ ] });
139
+ }
140
+ const PRODUCTS_PAGE_SIZE = 20;
141
+ function ProductsSection({
142
+ snapshot,
143
+ onAction
144
+ }) {
145
+ const totalPages = Math.max(
146
+ 1,
147
+ Math.ceil(snapshot.productsTotal / PRODUCTS_PAGE_SIZE)
148
+ );
149
+ return /* @__PURE__ */ jsxs(VStack, { gap: 1, width: "100%", children: [
150
+ /* @__PURE__ */ jsx(
151
+ Field,
152
+ {
153
+ label: "Search products",
154
+ placeholder: "filter by title",
155
+ value: snapshot.productSearch,
156
+ agent: "products-search",
157
+ onChange: (value) => onAction?.(`products:search:${value}`)
158
+ }
159
+ ),
160
+ /* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", width: "100%", children: [
161
+ /* @__PURE__ */ jsx(
162
+ Field,
163
+ {
164
+ label: "New product",
165
+ placeholder: "product title",
166
+ agent: "products-create-title",
167
+ grow: 1,
168
+ onChange: (value) => onAction?.(`products:create-title:${value}`)
169
+ }
170
+ ),
171
+ /* @__PURE__ */ jsx(
172
+ Button,
173
+ {
174
+ variant: "solid",
175
+ tone: "primary",
176
+ agent: "products-create",
177
+ onPress: () => onAction?.("products:create"),
178
+ children: "Create"
179
+ }
180
+ )
181
+ ] }),
182
+ /* @__PURE__ */ jsxs(Text, { style: "caption", tone: "muted", children: [
183
+ snapshot.productSearch ? `search "${snapshot.productSearch}"` : "all products",
184
+ " ",
185
+ "| page ",
186
+ snapshot.productsPage,
187
+ " of ",
188
+ totalPages,
189
+ " |",
190
+ " ",
191
+ snapshot.productsTotal,
192
+ " total"
193
+ ] }),
194
+ snapshot.products.length === 0 ? /* @__PURE__ */ jsx(Text, { tone: "muted", align: "center", style: "caption", children: "None" }) : /* @__PURE__ */ jsx(List, { gap: 0, width: "100%", children: snapshot.products.slice(0, 6).map((product) => /* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", width: "100%", children: [
195
+ /* @__PURE__ */ jsx(Text, { tone: productStatusTone(product.status), children: product.status === "ACTIVE" ? "+" : product.status === "DRAFT" ? "." : "x" }),
196
+ /* @__PURE__ */ jsxs(VStack, { gap: 0, grow: 1, children: [
197
+ /* @__PURE__ */ jsx(Text, { bold: true, wrap: false, children: product.title }),
198
+ /* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", wrap: false, children: product.vendor || product.productType || "uncategorized" })
199
+ ] }),
200
+ /* @__PURE__ */ jsx(Text, { wrap: false, children: product.priceRange.min === product.priceRange.max ? product.priceRange.min : `${product.priceRange.min}-${product.priceRange.max}` })
201
+ ] }, product.id)) }),
202
+ snapshot.productsTotal > PRODUCTS_PAGE_SIZE ? /* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", width: "100%", children: [
203
+ /* @__PURE__ */ jsx(
204
+ Button,
205
+ {
206
+ variant: "outline",
207
+ tone: "default",
208
+ agent: "products-prev-page",
209
+ disabled: snapshot.productsPage <= 1,
210
+ onPress: () => onAction?.("products:prev-page"),
211
+ children: "Prev"
212
+ }
213
+ ),
214
+ /* @__PURE__ */ jsx(
215
+ Button,
216
+ {
217
+ variant: "outline",
218
+ tone: "default",
219
+ agent: "products-next-page",
220
+ disabled: snapshot.productsPage >= totalPages,
221
+ onPress: () => onAction?.("products:next-page"),
222
+ children: "Next"
223
+ }
224
+ )
225
+ ] }) : null
226
+ ] });
227
+ }
228
+ const ORDER_FILTERS = [
229
+ { id: "any", label: "All" },
230
+ { id: "unfulfilled", label: "Unfulfilled" },
231
+ { id: "fulfilled", label: "Fulfilled" }
232
+ ];
233
+ function OrdersSection({
234
+ snapshot,
235
+ onAction
236
+ }) {
237
+ return /* @__PURE__ */ jsxs(VStack, { gap: 1, width: "100%", children: [
238
+ /* @__PURE__ */ jsx(HStack, { gap: 1, wrap: true, width: "100%", children: ORDER_FILTERS.map((filter) => /* @__PURE__ */ jsx(
239
+ Button,
240
+ {
241
+ variant: snapshot.orderStatusFilter === filter.id ? "solid" : "outline",
242
+ tone: snapshot.orderStatusFilter === filter.id ? "primary" : "default",
243
+ agent: `orders-filter-${filter.id}`,
244
+ onPress: () => onAction?.(`orders:filter:${filter.id}`),
245
+ children: filter.label
246
+ },
247
+ filter.id
248
+ )) }),
249
+ /* @__PURE__ */ jsxs(Text, { style: "caption", tone: "muted", children: [
250
+ "filter ",
251
+ snapshot.orderStatusFilter,
252
+ " | ",
253
+ snapshot.ordersTotal,
254
+ " total"
255
+ ] }),
256
+ snapshot.orders.length === 0 ? /* @__PURE__ */ jsx(Text, { tone: "muted", align: "center", style: "caption", children: "None" }) : /* @__PURE__ */ jsx(List, { gap: 0, width: "100%", children: snapshot.orders.slice(0, 6).map((order) => /* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", width: "100%", children: [
257
+ /* @__PURE__ */ jsx(Text, { bold: true, wrap: false, width: 9, children: order.name }),
258
+ /* @__PURE__ */ jsx(
259
+ Text,
260
+ {
261
+ style: "caption",
262
+ tone: financialTone(order.financialStatus),
263
+ wrap: false,
264
+ grow: 1,
265
+ children: order.financialStatus.toLowerCase()
266
+ }
267
+ ),
268
+ /* @__PURE__ */ jsxs(Text, { wrap: false, children: [
269
+ order.totalPrice,
270
+ " ",
271
+ order.currencyCode
272
+ ] })
273
+ ] }, order.id)) })
274
+ ] });
275
+ }
276
+ function InventorySection({ snapshot }) {
277
+ return /* @__PURE__ */ jsxs(VStack, { gap: 1, width: "100%", children: [
278
+ /* @__PURE__ */ jsxs(Text, { style: "caption", tone: "muted", children: [
279
+ snapshot.inventoryItems.length,
280
+ " rows |",
281
+ " ",
282
+ snapshot.inventoryLocations.length,
283
+ " locations"
284
+ ] }),
285
+ snapshot.inventoryItems.length === 0 ? /* @__PURE__ */ jsx(Text, { tone: "muted", align: "center", style: "caption", children: "None" }) : /* @__PURE__ */ jsx(List, { gap: 0, width: "100%", children: snapshot.inventoryItems.slice(0, 6).map((item) => /* @__PURE__ */ jsxs(
286
+ HStack,
287
+ {
288
+ gap: 1,
289
+ align: "center",
290
+ width: "100%",
291
+ children: [
292
+ /* @__PURE__ */ jsxs(VStack, { gap: 0, grow: 1, children: [
293
+ /* @__PURE__ */ jsxs(Text, { bold: true, wrap: false, children: [
294
+ item.productTitle,
295
+ item.variantTitle ? ` / ${item.variantTitle}` : ""
296
+ ] }),
297
+ /* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", wrap: false, children: item.locationName })
298
+ ] }),
299
+ /* @__PURE__ */ jsx(Text, { tone: inventoryTone(item.available), bold: true, children: item.available }),
300
+ /* @__PURE__ */ jsxs(Text, { style: "caption", tone: "muted", children: [
301
+ "+",
302
+ item.incoming
303
+ ] })
304
+ ]
305
+ },
306
+ `${item.id}:${item.locationName}`
307
+ )) })
308
+ ] });
309
+ }
310
+ function CustomersSection({
311
+ snapshot,
312
+ onAction
313
+ }) {
314
+ return /* @__PURE__ */ jsxs(VStack, { gap: 1, width: "100%", children: [
315
+ /* @__PURE__ */ jsx(
316
+ Field,
317
+ {
318
+ label: "Search customers",
319
+ placeholder: "filter by name or email",
320
+ value: snapshot.customerSearch,
321
+ agent: "customers-search",
322
+ onChange: (value) => onAction?.(`customers:search:${value}`)
323
+ }
324
+ ),
325
+ /* @__PURE__ */ jsxs(Text, { style: "caption", tone: "muted", children: [
326
+ snapshot.customerSearch ? `search "${snapshot.customerSearch}"` : "all customers",
327
+ " ",
328
+ "| ",
329
+ snapshot.customersTotal,
330
+ " total"
331
+ ] }),
332
+ snapshot.customers.length === 0 ? /* @__PURE__ */ jsx(Text, { tone: "muted", align: "center", style: "caption", children: "None" }) : /* @__PURE__ */ jsx(List, { gap: 0, width: "100%", children: snapshot.customers.slice(0, 6).map((customer) => /* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", width: "100%", children: [
333
+ /* @__PURE__ */ jsxs(VStack, { gap: 0, grow: 1, children: [
334
+ /* @__PURE__ */ jsx(Text, { bold: true, wrap: false, children: `${customer.firstName} ${customer.lastName}`.trim() || customer.email || "Customer" }),
335
+ /* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", wrap: false, children: customer.email })
336
+ ] }),
337
+ /* @__PURE__ */ jsxs(Text, { style: "caption", tone: "muted", wrap: false, children: [
338
+ customer.ordersCount,
339
+ " orders"
340
+ ] }),
341
+ /* @__PURE__ */ jsxs(Text, { wrap: false, children: [
342
+ customer.totalSpent,
343
+ " ",
344
+ customer.currencyCode
345
+ ] })
346
+ ] }, customer.id)) })
347
+ ] });
348
+ }
349
+ function Section({
350
+ snapshot,
351
+ onAction
352
+ }) {
353
+ switch (snapshot.tab) {
354
+ case "products":
355
+ return /* @__PURE__ */ jsx(ProductsSection, { snapshot, onAction });
356
+ case "orders":
357
+ return /* @__PURE__ */ jsx(OrdersSection, { snapshot, onAction });
358
+ case "inventory":
359
+ return /* @__PURE__ */ jsx(InventorySection, { snapshot });
360
+ case "customers":
361
+ return /* @__PURE__ */ jsx(CustomersSection, { snapshot, onAction });
362
+ default:
363
+ return /* @__PURE__ */ jsx(OverviewSection, { snapshot, onAction });
364
+ }
365
+ }
366
+ function ShopifySpatialView({
367
+ snapshot,
368
+ onAction
369
+ }) {
370
+ const dispatch = (action) => () => onAction?.(action);
371
+ const connected = snapshot.status?.connected ?? false;
372
+ const shop = snapshot.status?.shop ?? null;
373
+ return /* @__PURE__ */ jsxs(Card, { gap: 1, padding: 1, children: [
374
+ /* @__PURE__ */ jsxs(HStack, { gap: 1, align: "center", width: "100%", children: [
375
+ /* @__PURE__ */ jsx(
376
+ Text,
377
+ {
378
+ style: "caption",
379
+ tone: connected ? "success" : "danger",
380
+ wrap: false,
381
+ children: connected ? "connected" : "offline"
382
+ }
383
+ ),
384
+ /* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", grow: 1, align: "end", wrap: false, children: snapshot.loading ? "loading" : shop?.name ?? "no shop" })
385
+ ] }),
386
+ /* @__PURE__ */ jsx(Text, { style: "caption", tone: "muted", width: "100%", wrap: false, children: shop?.domain ?? "no domain" }),
387
+ snapshot.error ? /* @__PURE__ */ jsx(Text, { tone: "danger", style: "caption", children: snapshot.error }) : null,
388
+ !connected && !snapshot.loading ? /* @__PURE__ */ jsx(Text, { tone: "muted", style: "caption", children: "Set SHOPIFY_STORE_DOMAIN and SHOPIFY_ACCESS_TOKEN for live data." }) : null,
389
+ /* @__PURE__ */ jsxs(HStack, { gap: 1, wrap: true, width: "100%", children: [
390
+ TABS.map((tab) => /* @__PURE__ */ jsx(
391
+ Button,
392
+ {
393
+ variant: snapshot.tab === tab.id ? "solid" : "outline",
394
+ tone: snapshot.tab === tab.id ? "primary" : "default",
395
+ agent: `tab-${tab.id}`,
396
+ onPress: dispatch(`tab:${tab.id}`),
397
+ children: tab.label
398
+ },
399
+ tab.id
400
+ )),
401
+ /* @__PURE__ */ jsx(
402
+ Button,
403
+ {
404
+ variant: "ghost",
405
+ tone: "default",
406
+ agent: "refresh",
407
+ onPress: dispatch("refresh"),
408
+ children: "Refresh"
409
+ }
410
+ )
411
+ ] }),
412
+ /* @__PURE__ */ jsx(Divider, { label: snapshot.tab }),
413
+ /* @__PURE__ */ jsx(Section, { snapshot, onAction })
414
+ ] });
415
+ }
416
+ export {
417
+ ShopifySpatialView
418
+ };
419
+ //# sourceMappingURL=ShopifySpatialView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/ShopifySpatialView.tsx"],"sourcesContent":["/**\n * ShopifySpatialView - the Shopify store dashboard authored once with the\n * spatial vocabulary, so it renders correctly wherever it is displayed:\n *\n * - GUI / XR - mounted in `<SpatialSurface>` (DOM; XR scales up).\n * - TUI - rendered to real terminal lines by the agent terminal, via\n * `registerSpatialTerminalView` (see `register-terminal-view.tsx`).\n *\n * It is purely presentational (a snapshot + an action callback in, primitives\n * out) and imports only the cross-modality primitives plus type-only views of\n * the dashboard data shapes, so it is safe to render in the Node agent process\n * where the terminal lives (no React-DOM / browser runtime import).\n *\n * GUI Tabs map to spatial sections: the dashboard shows a counts strip\n * (overview) and one focused commerce section per active tab. On every surface\n * tab selection is a row of `Button`s; the host swaps `snapshot.tab` and\n * re-renders, so the same authored view drives GUI tab clicks, XR spatial\n * selection, and TUI grid sections from one source of truth.\n */\n\nimport {\n Button,\n Card,\n Divider,\n Field,\n HStack,\n List,\n type SpatialTone,\n Text,\n VStack,\n} from \"@elizaos/ui/spatial\";\nimport type {\n ShopifyCustomer,\n ShopifyInventoryItem,\n ShopifyOrder,\n ShopifyProduct,\n ShopifyStatus,\n} from \"../useShopifyDashboard.js\";\n\nexport type ShopifyTab =\n | \"overview\"\n | \"products\"\n | \"orders\"\n | \"inventory\"\n | \"customers\";\n\nexport interface ShopifySnapshot {\n status: ShopifyStatus | null;\n tab: ShopifyTab;\n counts: { productCount: number; orderCount: number; customerCount: number };\n products: ShopifyProduct[];\n productsTotal: number;\n productsPage: number;\n productSearch: string;\n orders: ShopifyOrder[];\n ordersTotal: number;\n orderStatusFilter: string;\n inventoryItems: ShopifyInventoryItem[];\n inventoryLocations: string[];\n customers: ShopifyCustomer[];\n customersTotal: number;\n customerSearch: string;\n loading?: boolean;\n error?: string | null;\n}\n\nconst TABS: { id: ShopifyTab; label: string }[] = [\n { id: \"overview\", label: \"Overview\" },\n { id: \"products\", label: \"Products\" },\n { id: \"orders\", label: \"Orders\" },\n { id: \"inventory\", label: \"Inventory\" },\n { id: \"customers\", label: \"Customers\" },\n];\n\nfunction financialTone(status: ShopifyOrder[\"financialStatus\"]): SpatialTone {\n switch (status) {\n case \"PAID\":\n return \"success\";\n case \"PENDING\":\n return \"warning\";\n case \"REFUNDED\":\n case \"PARTIALLY_REFUNDED\":\n return \"danger\";\n default:\n return \"muted\";\n }\n}\n\nfunction productStatusTone(status: ShopifyProduct[\"status\"]): SpatialTone {\n switch (status) {\n case \"ACTIVE\":\n return \"success\";\n case \"DRAFT\":\n return \"warning\";\n default:\n return \"muted\";\n }\n}\n\nfunction inventoryTone(available: number): SpatialTone {\n if (available === 0) return \"danger\";\n if (available <= 5) return \"warning\";\n return \"default\";\n}\n\nfunction CountTile({\n label,\n value,\n tone,\n agent,\n onPress,\n}: {\n label: string;\n value: number;\n tone: SpatialTone;\n agent: string;\n onPress: () => void;\n}) {\n // Borderless stat block — sections use the outer frame + dividers, not nested\n // boxes. The trailing Button is the cross-modal hit target that navigates to\n // the matching tab (GUI parity with the clickable overview tiles).\n return (\n <VStack gap={0} grow={1}>\n <Text style=\"subheading\" tone={tone} bold>\n {value.toLocaleString()}\n </Text>\n <Button variant=\"ghost\" tone=\"default\" agent={agent} onPress={onPress}>\n {label}\n </Button>\n </VStack>\n );\n}\n\nfunction OverviewSection({\n snapshot,\n onAction,\n}: {\n snapshot: ShopifySnapshot;\n onAction?: (action: string) => void;\n}) {\n const lowInventory = snapshot.inventoryItems.filter(\n (item) => item.available <= 5,\n );\n const urgent = lowInventory.filter((item) => item.available === 0).length;\n const go = (tab: ShopifyTab) => () => onAction?.(`tab:${tab}`);\n return (\n <VStack gap={1} width=\"100%\">\n <HStack gap={1} wrap width=\"100%\">\n <CountTile\n label=\"Products\"\n value={snapshot.counts.productCount}\n tone=\"primary\"\n agent=\"overview-products\"\n onPress={go(\"products\")}\n />\n <CountTile\n label=\"Orders\"\n value={snapshot.counts.orderCount}\n tone=\"success\"\n agent=\"overview-orders\"\n onPress={go(\"orders\")}\n />\n <CountTile\n label=\"Low stock\"\n value={lowInventory.length}\n tone={urgent > 0 ? \"danger\" : \"warning\"}\n agent=\"overview-inventory\"\n onPress={go(\"inventory\")}\n />\n <CountTile\n label=\"Customers\"\n value={snapshot.counts.customerCount}\n tone=\"muted\"\n agent=\"overview-customers\"\n onPress={go(\"customers\")}\n />\n </HStack>\n\n <Divider label=\"recent orders\" />\n {snapshot.orders.length === 0 ? (\n <Text tone=\"muted\" align=\"center\" style=\"caption\">\n None\n </Text>\n ) : (\n <List gap={0} width=\"100%\">\n {snapshot.orders.slice(0, 3).map((order) => (\n <HStack key={order.id} gap={1} align=\"center\" width=\"100%\">\n <Text bold wrap={false} width={9}>\n {order.name}\n </Text>\n <Text style=\"caption\" tone=\"muted\" grow={1} wrap={false}>\n {order.email || \"guest\"}\n </Text>\n <Text wrap={false}>\n {order.totalPrice} {order.currencyCode}\n </Text>\n </HStack>\n ))}\n </List>\n )}\n\n <Divider label=\"low inventory\" />\n {lowInventory.length === 0 ? (\n <Text tone=\"muted\" align=\"center\" style=\"caption\">\n Stock levels look good\n </Text>\n ) : (\n <List gap={0} width=\"100%\">\n {lowInventory.slice(0, 3).map((item) => (\n <HStack\n key={`${item.id}:${item.locationName}`}\n gap={1}\n align=\"center\"\n width=\"100%\"\n >\n <Text grow={1} wrap={false}>\n {item.productTitle}\n {item.variantTitle ? ` / ${item.variantTitle}` : \"\"}\n </Text>\n <Text tone={inventoryTone(item.available)} bold>\n {item.available}\n </Text>\n </HStack>\n ))}\n </List>\n )}\n </VStack>\n );\n}\n\nconst PRODUCTS_PAGE_SIZE = 20;\n\nfunction ProductsSection({\n snapshot,\n onAction,\n}: {\n snapshot: ShopifySnapshot;\n onAction?: (action: string) => void;\n}) {\n const totalPages = Math.max(\n 1,\n Math.ceil(snapshot.productsTotal / PRODUCTS_PAGE_SIZE),\n );\n return (\n <VStack gap={1} width=\"100%\">\n <Field\n label=\"Search products\"\n placeholder=\"filter by title\"\n value={snapshot.productSearch}\n agent=\"products-search\"\n onChange={(value) => onAction?.(`products:search:${value}`)}\n />\n <HStack gap={1} align=\"center\" width=\"100%\">\n <Field\n label=\"New product\"\n placeholder=\"product title\"\n agent=\"products-create-title\"\n grow={1}\n onChange={(value) => onAction?.(`products:create-title:${value}`)}\n />\n <Button\n variant=\"solid\"\n tone=\"primary\"\n agent=\"products-create\"\n onPress={() => onAction?.(\"products:create\")}\n >\n Create\n </Button>\n </HStack>\n <Text style=\"caption\" tone=\"muted\">\n {snapshot.productSearch\n ? `search \"${snapshot.productSearch}\"`\n : \"all products\"}{\" \"}\n | page {snapshot.productsPage} of {totalPages} |{\" \"}\n {snapshot.productsTotal} total\n </Text>\n {snapshot.products.length === 0 ? (\n <Text tone=\"muted\" align=\"center\" style=\"caption\">\n None\n </Text>\n ) : (\n <List gap={0} width=\"100%\">\n {snapshot.products.slice(0, 6).map((product) => (\n <HStack key={product.id} gap={1} align=\"center\" width=\"100%\">\n <Text tone={productStatusTone(product.status)}>\n {product.status === \"ACTIVE\"\n ? \"+\"\n : product.status === \"DRAFT\"\n ? \".\"\n : \"x\"}\n </Text>\n <VStack gap={0} grow={1}>\n <Text bold wrap={false}>\n {product.title}\n </Text>\n <Text style=\"caption\" tone=\"muted\" wrap={false}>\n {product.vendor || product.productType || \"uncategorized\"}\n </Text>\n </VStack>\n <Text wrap={false}>\n {product.priceRange.min === product.priceRange.max\n ? product.priceRange.min\n : `${product.priceRange.min}-${product.priceRange.max}`}\n </Text>\n </HStack>\n ))}\n </List>\n )}\n {snapshot.productsTotal > PRODUCTS_PAGE_SIZE ? (\n <HStack gap={1} align=\"center\" width=\"100%\">\n <Button\n variant=\"outline\"\n tone=\"default\"\n agent=\"products-prev-page\"\n disabled={snapshot.productsPage <= 1}\n onPress={() => onAction?.(\"products:prev-page\")}\n >\n Prev\n </Button>\n <Button\n variant=\"outline\"\n tone=\"default\"\n agent=\"products-next-page\"\n disabled={snapshot.productsPage >= totalPages}\n onPress={() => onAction?.(\"products:next-page\")}\n >\n Next\n </Button>\n </HStack>\n ) : null}\n </VStack>\n );\n}\n\nconst ORDER_FILTERS: { id: string; label: string }[] = [\n { id: \"any\", label: \"All\" },\n { id: \"unfulfilled\", label: \"Unfulfilled\" },\n { id: \"fulfilled\", label: \"Fulfilled\" },\n];\n\nfunction OrdersSection({\n snapshot,\n onAction,\n}: {\n snapshot: ShopifySnapshot;\n onAction?: (action: string) => void;\n}) {\n return (\n <VStack gap={1} width=\"100%\">\n <HStack gap={1} wrap width=\"100%\">\n {ORDER_FILTERS.map((filter) => (\n <Button\n key={filter.id}\n variant={\n snapshot.orderStatusFilter === filter.id ? \"solid\" : \"outline\"\n }\n tone={\n snapshot.orderStatusFilter === filter.id ? \"primary\" : \"default\"\n }\n agent={`orders-filter-${filter.id}`}\n onPress={() => onAction?.(`orders:filter:${filter.id}`)}\n >\n {filter.label}\n </Button>\n ))}\n </HStack>\n <Text style=\"caption\" tone=\"muted\">\n filter {snapshot.orderStatusFilter} | {snapshot.ordersTotal} total\n </Text>\n {snapshot.orders.length === 0 ? (\n <Text tone=\"muted\" align=\"center\" style=\"caption\">\n None\n </Text>\n ) : (\n <List gap={0} width=\"100%\">\n {snapshot.orders.slice(0, 6).map((order) => (\n <HStack key={order.id} gap={1} align=\"center\" width=\"100%\">\n <Text bold wrap={false} width={9}>\n {order.name}\n </Text>\n <Text\n style=\"caption\"\n tone={financialTone(order.financialStatus)}\n wrap={false}\n grow={1}\n >\n {order.financialStatus.toLowerCase()}\n </Text>\n <Text wrap={false}>\n {order.totalPrice} {order.currencyCode}\n </Text>\n </HStack>\n ))}\n </List>\n )}\n </VStack>\n );\n}\n\nfunction InventorySection({ snapshot }: { snapshot: ShopifySnapshot }) {\n return (\n <VStack gap={1} width=\"100%\">\n <Text style=\"caption\" tone=\"muted\">\n {snapshot.inventoryItems.length} rows |{\" \"}\n {snapshot.inventoryLocations.length} locations\n </Text>\n {snapshot.inventoryItems.length === 0 ? (\n <Text tone=\"muted\" align=\"center\" style=\"caption\">\n None\n </Text>\n ) : (\n <List gap={0} width=\"100%\">\n {snapshot.inventoryItems.slice(0, 6).map((item) => (\n <HStack\n key={`${item.id}:${item.locationName}`}\n gap={1}\n align=\"center\"\n width=\"100%\"\n >\n <VStack gap={0} grow={1}>\n <Text bold wrap={false}>\n {item.productTitle}\n {item.variantTitle ? ` / ${item.variantTitle}` : \"\"}\n </Text>\n <Text style=\"caption\" tone=\"muted\" wrap={false}>\n {item.locationName}\n </Text>\n </VStack>\n <Text tone={inventoryTone(item.available)} bold>\n {item.available}\n </Text>\n <Text style=\"caption\" tone=\"muted\">\n +{item.incoming}\n </Text>\n </HStack>\n ))}\n </List>\n )}\n </VStack>\n );\n}\n\nfunction CustomersSection({\n snapshot,\n onAction,\n}: {\n snapshot: ShopifySnapshot;\n onAction?: (action: string) => void;\n}) {\n return (\n <VStack gap={1} width=\"100%\">\n <Field\n label=\"Search customers\"\n placeholder=\"filter by name or email\"\n value={snapshot.customerSearch}\n agent=\"customers-search\"\n onChange={(value) => onAction?.(`customers:search:${value}`)}\n />\n <Text style=\"caption\" tone=\"muted\">\n {snapshot.customerSearch\n ? `search \"${snapshot.customerSearch}\"`\n : \"all customers\"}{\" \"}\n | {snapshot.customersTotal} total\n </Text>\n {snapshot.customers.length === 0 ? (\n <Text tone=\"muted\" align=\"center\" style=\"caption\">\n None\n </Text>\n ) : (\n <List gap={0} width=\"100%\">\n {snapshot.customers.slice(0, 6).map((customer) => (\n <HStack key={customer.id} gap={1} align=\"center\" width=\"100%\">\n <VStack gap={0} grow={1}>\n <Text bold wrap={false}>\n {`${customer.firstName} ${customer.lastName}`.trim() ||\n customer.email ||\n \"Customer\"}\n </Text>\n <Text style=\"caption\" tone=\"muted\" wrap={false}>\n {customer.email}\n </Text>\n </VStack>\n <Text style=\"caption\" tone=\"muted\" wrap={false}>\n {customer.ordersCount} orders\n </Text>\n <Text wrap={false}>\n {customer.totalSpent} {customer.currencyCode}\n </Text>\n </HStack>\n ))}\n </List>\n )}\n </VStack>\n );\n}\n\nfunction Section({\n snapshot,\n onAction,\n}: {\n snapshot: ShopifySnapshot;\n onAction?: (action: string) => void;\n}) {\n switch (snapshot.tab) {\n case \"products\":\n return <ProductsSection snapshot={snapshot} onAction={onAction} />;\n case \"orders\":\n return <OrdersSection snapshot={snapshot} onAction={onAction} />;\n case \"inventory\":\n return <InventorySection snapshot={snapshot} />;\n case \"customers\":\n return <CustomersSection snapshot={snapshot} onAction={onAction} />;\n default:\n return <OverviewSection snapshot={snapshot} onAction={onAction} />;\n }\n}\n\nexport interface ShopifySpatialViewProps {\n snapshot: ShopifySnapshot;\n /**\n * Dispatch by agent id. Supported actions:\n * `tab:<id>`, `refresh`,\n * `products:search:<q>`, `products:create-title:<q>`, `products:create`,\n * `products:prev-page`, `products:next-page`,\n * `orders:filter:<status>`, `customers:search:<q>`.\n */\n onAction?: (action: string) => void;\n}\n\nexport function ShopifySpatialView({\n snapshot,\n onAction,\n}: ShopifySpatialViewProps) {\n const dispatch = (action: string) => () => onAction?.(action);\n const connected = snapshot.status?.connected ?? false;\n const shop = snapshot.status?.shop ?? null;\n\n return (\n <Card gap={1} padding={1}>\n <HStack gap={1} align=\"center\" width=\"100%\">\n <Text\n style=\"caption\"\n tone={connected ? \"success\" : \"danger\"}\n wrap={false}\n >\n {connected ? \"connected\" : \"offline\"}\n </Text>\n <Text style=\"caption\" tone=\"muted\" grow={1} align=\"end\" wrap={false}>\n {snapshot.loading ? \"loading\" : (shop?.name ?? \"no shop\")}\n </Text>\n </HStack>\n <Text style=\"caption\" tone=\"muted\" width=\"100%\" wrap={false}>\n {shop?.domain ?? \"no domain\"}\n </Text>\n\n {snapshot.error ? (\n <Text tone=\"danger\" style=\"caption\">\n {snapshot.error}\n </Text>\n ) : null}\n\n {!connected && !snapshot.loading ? (\n <Text tone=\"muted\" style=\"caption\">\n Set SHOPIFY_STORE_DOMAIN and SHOPIFY_ACCESS_TOKEN for live data.\n </Text>\n ) : null}\n\n <HStack gap={1} wrap width=\"100%\">\n {TABS.map((tab) => (\n <Button\n key={tab.id}\n variant={snapshot.tab === tab.id ? \"solid\" : \"outline\"}\n tone={snapshot.tab === tab.id ? \"primary\" : \"default\"}\n agent={`tab-${tab.id}`}\n onPress={dispatch(`tab:${tab.id}`)}\n >\n {tab.label}\n </Button>\n ))}\n <Button\n variant=\"ghost\"\n tone=\"default\"\n agent=\"refresh\"\n onPress={dispatch(\"refresh\")}\n >\n Refresh\n </Button>\n </HStack>\n\n <Divider label={snapshot.tab} />\n <Section snapshot={snapshot} onAction={onAction} />\n </Card>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,14 @@
1
+ export * from "./CustomersPanel";
2
+ export * from "./InventoryLevelsPanel";
3
+ export * from "./OrdersPanel";
4
+ export * from "./ProductsPanel";
5
+ export { shopifyPlugin } from "./plugin";
6
+ export * from "./register";
7
+ export * from "./routes";
8
+ export * from "./ShopifyAppView";
9
+ export * from "./ShopifyAppView.helpers";
10
+ export { ShopifyView } from "./ShopifyView";
11
+ export * from "./StoreOverviewCard";
12
+ export { SHOPIFY_APP_NAME, shopifyApp } from "./shopify-app";
13
+ export * from "./useShopifyDashboard";
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,cAAc,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ export * from "./CustomersPanel.js";
2
+ export * from "./InventoryLevelsPanel.js";
3
+ export * from "./OrdersPanel.js";
4
+ export * from "./ProductsPanel.js";
5
+ import { shopifyPlugin } from "./plugin.js";
6
+ export * from "./register.js";
7
+ export * from "./routes.js";
8
+ export * from "./ShopifyAppView.js";
9
+ export * from "./ShopifyAppView.helpers";
10
+ import { ShopifyView } from "./ShopifyView.js";
11
+ export * from "./StoreOverviewCard.js";
12
+ import { SHOPIFY_APP_NAME, shopifyApp } from "./shopify-app.js";
13
+ export * from "./useShopifyDashboard.js";
14
+ export {
15
+ SHOPIFY_APP_NAME,
16
+ ShopifyView,
17
+ shopifyApp,
18
+ shopifyPlugin
19
+ };
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./CustomersPanel.js\";\nexport * from \"./InventoryLevelsPanel.js\";\nexport * from \"./OrdersPanel.js\";\nexport * from \"./ProductsPanel.js\";\nexport { shopifyPlugin } from \"./plugin.js\";\nexport * from \"./register.js\";\nexport * from \"./routes.js\";\nexport * from \"./ShopifyAppView.js\";\nexport * from \"./ShopifyAppView.helpers\";\nexport { ShopifyView } from \"./ShopifyView.js\";\nexport * from \"./StoreOverviewCard.js\";\nexport { SHOPIFY_APP_NAME, shopifyApp } from \"./shopify-app.js\";\nexport * from \"./useShopifyDashboard.js\";\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,qBAAqB;AAC9B,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,mBAAmB;AAC5B,cAAc;AACd,SAAS,kBAAkB,kBAAkB;AAC7C,cAAc;","names":[]}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Shopify plugin — registers all Shopify dashboard routes with the
3
+ * elizaOS runtime plugin route system.
4
+ *
5
+ * All routes use `rawPath: true` to preserve the legacy `/api/shopify/*`
6
+ * paths without a plugin-name prefix.
7
+ *
8
+ * The existing `handleShopifyRoute` handler operates on raw
9
+ * `http.IncomingMessage` / `http.ServerResponse`, which the runtime
10
+ * plugin route bridge already passes through (see runtime-plugin-routes.ts).
11
+ */
12
+ import type { Plugin } from "@elizaos/core";
13
+ export declare const shopifyPlugin: Plugin;
14
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAS,MAAM,eAAe,CAAC;AA+FnD,eAAO,MAAM,aAAa,EAAE,MAyB3B,CAAC"}
package/dist/plugin.js ADDED
@@ -0,0 +1,94 @@
1
+ import { handleShopifyRoute } from "./routes.js";
2
+ function shopifyRouteHandler(pathname) {
3
+ return async (req, res, _runtime) => {
4
+ const httpReq = req;
5
+ const httpRes = res;
6
+ const method = (httpReq.method ?? "GET").toUpperCase();
7
+ await handleShopifyRoute(httpReq, httpRes, pathname, method);
8
+ };
9
+ }
10
+ const shopifyRoutes = [
11
+ // GET /api/shopify/status
12
+ {
13
+ type: "GET",
14
+ path: "/api/shopify/status",
15
+ rawPath: true,
16
+ handler: shopifyRouteHandler("/api/shopify/status")
17
+ },
18
+ // GET /api/shopify/products
19
+ {
20
+ type: "GET",
21
+ path: "/api/shopify/products",
22
+ rawPath: true,
23
+ handler: shopifyRouteHandler("/api/shopify/products")
24
+ },
25
+ // POST /api/shopify/products
26
+ {
27
+ type: "POST",
28
+ path: "/api/shopify/products",
29
+ rawPath: true,
30
+ handler: shopifyRouteHandler("/api/shopify/products")
31
+ },
32
+ // GET /api/shopify/orders
33
+ {
34
+ type: "GET",
35
+ path: "/api/shopify/orders",
36
+ rawPath: true,
37
+ handler: shopifyRouteHandler("/api/shopify/orders")
38
+ },
39
+ // GET /api/shopify/inventory
40
+ {
41
+ type: "GET",
42
+ path: "/api/shopify/inventory",
43
+ rawPath: true,
44
+ handler: shopifyRouteHandler("/api/shopify/inventory")
45
+ },
46
+ // POST /api/shopify/inventory/:itemId/adjust
47
+ {
48
+ type: "POST",
49
+ path: "/api/shopify/inventory/:itemId/adjust",
50
+ rawPath: true,
51
+ handler: async (req, res, _runtime) => {
52
+ const httpReq = req;
53
+ const httpRes = res;
54
+ const method = (httpReq.method ?? "GET").toUpperCase();
55
+ const url = new URL(httpReq.url ?? "/", "http://localhost");
56
+ await handleShopifyRoute(httpReq, httpRes, url.pathname, method);
57
+ }
58
+ },
59
+ // GET /api/shopify/customers
60
+ {
61
+ type: "GET",
62
+ path: "/api/shopify/customers",
63
+ rawPath: true,
64
+ handler: shopifyRouteHandler("/api/shopify/customers")
65
+ }
66
+ ];
67
+ const shopifyPlugin = {
68
+ name: "@elizaos/plugin-shopify-ui",
69
+ description: "Shopify store management dashboard routes (extracted from app-core server.ts)",
70
+ routes: shopifyRoutes,
71
+ views: [
72
+ // ONE declaration → GUI + XR + TUI, all drawn from the single ShopifyView
73
+ // spatial source. `modalities` is a plain literal here (plugin.ts is not in
74
+ // the view bundle), so no brand-new `@elizaos/core` runtime export reaches
75
+ // the bundle build.
76
+ {
77
+ id: "shopify",
78
+ label: "Shopify",
79
+ description: "Shopify store management \u2014 orders, products, customers, and inventory",
80
+ icon: "ShoppingBag",
81
+ path: "/shopify",
82
+ modalities: ["gui", "xr", "tui"],
83
+ bundlePath: "dist/views/bundle.js",
84
+ componentExport: "ShopifyView",
85
+ tags: ["shopify", "ecommerce", "store"],
86
+ visibleInManager: true,
87
+ desktopTabEnabled: true
88
+ }
89
+ ]
90
+ };
91
+ export {
92
+ shopifyPlugin
93
+ };
94
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugin.ts"],"sourcesContent":["/**\n * Shopify plugin — registers all Shopify dashboard routes with the\n * elizaOS runtime plugin route system.\n *\n * All routes use `rawPath: true` to preserve the legacy `/api/shopify/*`\n * paths without a plugin-name prefix.\n *\n * The existing `handleShopifyRoute` handler operates on raw\n * `http.IncomingMessage` / `http.ServerResponse`, which the runtime\n * plugin route bridge already passes through (see runtime-plugin-routes.ts).\n */\n\nimport type http from \"node:http\";\nimport type { Plugin, Route } from \"@elizaos/core\";\nimport { handleShopifyRoute } from \"./routes.js\";\n\n// ---------------------------------------------------------------------------\n// Shared wrapper: adapt the monolithic handleShopifyRoute to a plugin Route\n// handler. The runtime bridge passes the raw req/res objects.\n// ---------------------------------------------------------------------------\n\nfunction shopifyRouteHandler(pathname: string) {\n return async (\n req: unknown,\n res: unknown,\n _runtime: unknown,\n ): Promise<void> => {\n const httpReq = req as http.IncomingMessage;\n const httpRes = res as http.ServerResponse;\n const method = (httpReq.method ?? \"GET\").toUpperCase();\n await handleShopifyRoute(httpReq, httpRes, pathname, method);\n };\n}\n\n// ---------------------------------------------------------------------------\n// Route definitions\n// ---------------------------------------------------------------------------\n\nconst shopifyRoutes: Route[] = [\n // GET /api/shopify/status\n {\n type: \"GET\",\n path: \"/api/shopify/status\",\n rawPath: true,\n handler: shopifyRouteHandler(\"/api/shopify/status\"),\n },\n // GET /api/shopify/products\n {\n type: \"GET\",\n path: \"/api/shopify/products\",\n rawPath: true,\n handler: shopifyRouteHandler(\"/api/shopify/products\"),\n },\n // POST /api/shopify/products\n {\n type: \"POST\",\n path: \"/api/shopify/products\",\n rawPath: true,\n handler: shopifyRouteHandler(\"/api/shopify/products\"),\n },\n // GET /api/shopify/orders\n {\n type: \"GET\",\n path: \"/api/shopify/orders\",\n rawPath: true,\n handler: shopifyRouteHandler(\"/api/shopify/orders\"),\n },\n // GET /api/shopify/inventory\n {\n type: \"GET\",\n path: \"/api/shopify/inventory\",\n rawPath: true,\n handler: shopifyRouteHandler(\"/api/shopify/inventory\"),\n },\n // POST /api/shopify/inventory/:itemId/adjust\n {\n type: \"POST\",\n path: \"/api/shopify/inventory/:itemId/adjust\",\n rawPath: true,\n handler: async (\n req: unknown,\n res: unknown,\n _runtime: unknown,\n ): Promise<void> => {\n const httpReq = req as http.IncomingMessage;\n const httpRes = res as http.ServerResponse;\n const method = (httpReq.method ?? \"GET\").toUpperCase();\n // The runtime bridge augments req with `url` from the parsed URL,\n // but handleShopifyRoute expects the raw pathname from req.url.\n // We pass the pathname derived from req.url so the regex inside\n // handleShopifyRoute can match the :itemId segment.\n const url = new URL(httpReq.url ?? \"/\", \"http://localhost\");\n await handleShopifyRoute(httpReq, httpRes, url.pathname, method);\n },\n },\n // GET /api/shopify/customers\n {\n type: \"GET\",\n path: \"/api/shopify/customers\",\n rawPath: true,\n handler: shopifyRouteHandler(\"/api/shopify/customers\"),\n },\n];\n\n// ---------------------------------------------------------------------------\n// Plugin export\n// ---------------------------------------------------------------------------\n\nexport const shopifyPlugin: Plugin = {\n name: \"@elizaos/plugin-shopify-ui\",\n description:\n \"Shopify store management dashboard routes (extracted from app-core server.ts)\",\n routes: shopifyRoutes,\n views: [\n // ONE declaration → GUI + XR + TUI, all drawn from the single ShopifyView\n // spatial source. `modalities` is a plain literal here (plugin.ts is not in\n // the view bundle), so no brand-new `@elizaos/core` runtime export reaches\n // the bundle build.\n {\n id: \"shopify\",\n label: \"Shopify\",\n description:\n \"Shopify store management — orders, products, customers, and inventory\",\n icon: \"ShoppingBag\",\n path: \"/shopify\",\n modalities: [\"gui\", \"xr\", \"tui\"],\n bundlePath: \"dist/views/bundle.js\",\n componentExport: \"ShopifyView\",\n tags: [\"shopify\", \"ecommerce\", \"store\"],\n visibleInManager: true,\n desktopTabEnabled: true,\n },\n ],\n};\n"],"mappings":"AAcA,SAAS,0BAA0B;AAOnC,SAAS,oBAAoB,UAAkB;AAC7C,SAAO,OACL,KACA,KACA,aACkB;AAClB,UAAM,UAAU;AAChB,UAAM,UAAU;AAChB,UAAM,UAAU,QAAQ,UAAU,OAAO,YAAY;AACrD,UAAM,mBAAmB,SAAS,SAAS,UAAU,MAAM;AAAA,EAC7D;AACF;AAMA,MAAM,gBAAyB;AAAA;AAAA,EAE7B;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS,oBAAoB,qBAAqB;AAAA,EACpD;AAAA;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS,oBAAoB,uBAAuB;AAAA,EACtD;AAAA;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS,oBAAoB,uBAAuB;AAAA,EACtD;AAAA;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS,oBAAoB,qBAAqB;AAAA,EACpD;AAAA;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS,oBAAoB,wBAAwB;AAAA,EACvD;AAAA;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS,OACP,KACA,KACA,aACkB;AAClB,YAAM,UAAU;AAChB,YAAM,UAAU;AAChB,YAAM,UAAU,QAAQ,UAAU,OAAO,YAAY;AAKrD,YAAM,MAAM,IAAI,IAAI,QAAQ,OAAO,KAAK,kBAAkB;AAC1D,YAAM,mBAAmB,SAAS,SAAS,IAAI,UAAU,MAAM;AAAA,IACjE;AAAA,EACF;AAAA;AAAA,EAEA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS,oBAAoB,wBAAwB;AAAA,EACvD;AACF;AAMO,MAAM,gBAAwB;AAAA,EACnC,MAAM;AAAA,EACN,aACE;AAAA,EACF,QAAQ;AAAA,EACR,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,IAKL;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,aACE;AAAA,MACF,MAAM;AAAA,MACN,MAAM;AAAA,MACN,YAAY,CAAC,OAAO,MAAM,KAAK;AAAA,MAC/B,YAAY;AAAA,MACZ,iBAAiB;AAAA,MACjB,MAAM,CAAC,WAAW,aAAa,OAAO;AAAA,MACtC,kBAAkB;AAAA,MAClB,mBAAmB;AAAA,IACrB;AAAA,EACF;AACF;","names":[]}