@burdenoff/microfe-store 2026.510.113

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 (141) hide show
  1. package/README.md +217 -0
  2. package/dist/StoreAdminRoot.d.ts +22 -0
  3. package/dist/StoreAdminRoot.js +23 -0
  4. package/dist/StoreAdminRoot.js.map +1 -0
  5. package/dist/StoreAdminRoutes.d.ts +9 -0
  6. package/dist/StoreAdminRoutes.js +69 -0
  7. package/dist/StoreAdminRoutes.js.map +1 -0
  8. package/dist/StoreRoot.d.ts +31 -0
  9. package/dist/StoreRoot.js +139 -0
  10. package/dist/StoreRoot.js.map +1 -0
  11. package/dist/StoreRoutes.d.ts +12 -0
  12. package/dist/StoreRoutes.js +285 -0
  13. package/dist/StoreRoutes.js.map +1 -0
  14. package/dist/components/InstallAppModal.d.ts +26 -0
  15. package/dist/components/InstallAppModal.js +287 -0
  16. package/dist/components/InstallAppModal.js.map +1 -0
  17. package/dist/components/RouteGuards.d.ts +17 -0
  18. package/dist/components/RouteGuards.js +26 -0
  19. package/dist/components/RouteGuards.js.map +1 -0
  20. package/dist/components/cart/CartDrawer.d.ts +35 -0
  21. package/dist/components/cart/CartDrawer.js +162 -0
  22. package/dist/components/cart/CartDrawer.js.map +1 -0
  23. package/dist/components/index.d.ts +9 -0
  24. package/dist/components/index.js +3 -0
  25. package/dist/components/marketplace/ProductCard.d.ts +18 -0
  26. package/dist/components/marketplace/ProductCard.js +2 -0
  27. package/dist/dev/main.d.ts +1 -0
  28. package/dist/generated/global-operations.d.ts +2012 -0
  29. package/dist/generated/global-operations.js +1444 -0
  30. package/dist/generated/global-operations.js.map +1 -0
  31. package/dist/generated/global-types.d.ts +20856 -0
  32. package/dist/generated/global-types.js +14 -0
  33. package/dist/generated/global-types.js.map +1 -0
  34. package/dist/generated/wspace-operations.d.ts +1 -0
  35. package/dist/generated/wspace-types.d.ts +53362 -0
  36. package/dist/hooks/index.d.ts +12 -0
  37. package/dist/hooks/useBackendCart.d.ts +73 -0
  38. package/dist/hooks/useBackendCart.js +171 -0
  39. package/dist/hooks/useBackendCart.js.map +1 -0
  40. package/dist/hooks/useCart.d.ts +62 -0
  41. package/dist/hooks/useCart.js +90 -0
  42. package/dist/hooks/useCart.js.map +1 -0
  43. package/dist/hooks/useInstallations.d.ts +43 -0
  44. package/dist/hooks/useInstallations.js +140 -0
  45. package/dist/hooks/useInstallations.js.map +1 -0
  46. package/dist/hooks/useOrders.d.ts +40 -0
  47. package/dist/hooks/useOrders.js +73 -0
  48. package/dist/hooks/useOrders.js.map +1 -0
  49. package/dist/hooks/useProductSearch.d.ts +22 -0
  50. package/dist/hooks/useProductSearch.js +59 -0
  51. package/dist/hooks/useProductSearch.js.map +1 -0
  52. package/dist/hooks/useStoreGraphQL.d.ts +475 -0
  53. package/dist/hooks/useStoreGraphQL.js +751 -0
  54. package/dist/hooks/useStoreGraphQL.js.map +1 -0
  55. package/dist/hooks/useStoreGraphQLWithContext.d.ts +48 -0
  56. package/dist/hooks/useStoreGraphQLWithContext.js +39 -0
  57. package/dist/hooks/useStoreGraphQLWithContext.js.map +1 -0
  58. package/dist/hooks/useStorePermissions.d.ts +63 -0
  59. package/dist/hooks/useStorePermissions.js +88 -0
  60. package/dist/hooks/useStorePermissions.js.map +1 -0
  61. package/dist/index.d.ts +44 -0
  62. package/dist/index.js +13 -0
  63. package/dist/pages/AdminDashboardPage.d.ts +3 -0
  64. package/dist/pages/AdminDashboardPage.js +491 -0
  65. package/dist/pages/AdminDashboardPage.js.map +1 -0
  66. package/dist/pages/AdminReviewModerationPage.d.ts +3 -0
  67. package/dist/pages/AdminReviewModerationPage.js +247 -0
  68. package/dist/pages/AdminReviewModerationPage.js.map +1 -0
  69. package/dist/pages/AdminStoresPage.d.ts +3 -0
  70. package/dist/pages/AdminStoresPage.js +442 -0
  71. package/dist/pages/AdminStoresPage.js.map +1 -0
  72. package/dist/pages/AdminSubmissionsQueuePage.d.ts +3 -0
  73. package/dist/pages/AdminSubmissionsQueuePage.js +387 -0
  74. package/dist/pages/AdminSubmissionsQueuePage.js.map +1 -0
  75. package/dist/pages/AppDetailPage.d.ts +3 -0
  76. package/dist/pages/AppDetailPage.js +166 -0
  77. package/dist/pages/AppDetailPage.js.map +1 -0
  78. package/dist/pages/AppSettingsPage.d.ts +3 -0
  79. package/dist/pages/AppSettingsPage.js +100 -0
  80. package/dist/pages/AppSettingsPage.js.map +1 -0
  81. package/dist/pages/CartPage.d.ts +8 -0
  82. package/dist/pages/CartPage.js +259 -0
  83. package/dist/pages/CartPage.js.map +1 -0
  84. package/dist/pages/InstalledAppsPage.d.ts +8 -0
  85. package/dist/pages/InstalledAppsPage.js +290 -0
  86. package/dist/pages/InstalledAppsPage.js.map +1 -0
  87. package/dist/pages/MarketplaceHomePage.d.ts +3 -0
  88. package/dist/pages/MarketplaceHomePage.js +1118 -0
  89. package/dist/pages/MarketplaceHomePage.js.map +1 -0
  90. package/dist/pages/MyLicensesPage.d.ts +3 -0
  91. package/dist/pages/MyLicensesPage.js +146 -0
  92. package/dist/pages/MyLicensesPage.js.map +1 -0
  93. package/dist/pages/OrderConfirmationPage.d.ts +3 -0
  94. package/dist/pages/OrderConfirmationPage.js +178 -0
  95. package/dist/pages/OrderConfirmationPage.js.map +1 -0
  96. package/dist/pages/OrdersPage.d.ts +8 -0
  97. package/dist/pages/OrdersPage.js +358 -0
  98. package/dist/pages/OrdersPage.js.map +1 -0
  99. package/dist/pages/ProductCategoryPage.d.ts +3 -0
  100. package/dist/pages/ProductCategoryPage.js +83 -0
  101. package/dist/pages/ProductCategoryPage.js.map +1 -0
  102. package/dist/pages/ProductDetailPage.d.ts +8 -0
  103. package/dist/pages/ProductDetailPage.js +1205 -0
  104. package/dist/pages/ProductDetailPage.js.map +1 -0
  105. package/dist/pages/ProductReviewsPage.d.ts +3 -0
  106. package/dist/pages/ProductReviewsPage.js +86 -0
  107. package/dist/pages/ProductReviewsPage.js.map +1 -0
  108. package/dist/pages/PublisherDashboardPage.d.ts +3 -0
  109. package/dist/pages/PublisherDashboardPage.js +154 -0
  110. package/dist/pages/PublisherDashboardPage.js.map +1 -0
  111. package/dist/pages/PublisherRevenuePage.d.ts +3 -0
  112. package/dist/pages/PublisherRevenuePage.js +138 -0
  113. package/dist/pages/PublisherRevenuePage.js.map +1 -0
  114. package/dist/pages/PublisherSubmissionsPage.d.ts +3 -0
  115. package/dist/pages/PublisherSubmissionsPage.js +174 -0
  116. package/dist/pages/PublisherSubmissionsPage.js.map +1 -0
  117. package/dist/pages/PublisherSubmitPage.d.ts +3 -0
  118. package/dist/pages/PublisherSubmitPage.js +224 -0
  119. package/dist/pages/PublisherSubmitPage.js.map +1 -0
  120. package/dist/pages/SearchResultsPage.d.ts +3 -0
  121. package/dist/pages/SearchResultsPage.js +125 -0
  122. package/dist/pages/SearchResultsPage.js.map +1 -0
  123. package/dist/pages/StoresPage.d.ts +3 -0
  124. package/dist/pages/StoresPage.js +154 -0
  125. package/dist/pages/StoresPage.js.map +1 -0
  126. package/dist/providers/StoreProvider.d.ts +38 -0
  127. package/dist/providers/StoreProvider.js +51 -0
  128. package/dist/providers/StoreProvider.js.map +1 -0
  129. package/dist/store/storeStore.d.ts +69 -0
  130. package/dist/store/storeStore.js +68 -0
  131. package/dist/store/storeStore.js.map +1 -0
  132. package/dist/translations/en.d.ts +518 -0
  133. package/dist/translations/en.js +514 -0
  134. package/dist/translations/en.js.map +1 -0
  135. package/dist/types/index.d.ts +575 -0
  136. package/dist/utils/index.d.ts +67 -0
  137. package/dist/utils/index.js +114 -0
  138. package/dist/utils/index.js.map +1 -0
  139. package/dist/utils/nativeBridge.d.ts +2 -0
  140. package/dist/utils/nativeBridge.js +2 -0
  141. package/package.json +105 -0
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Store Hooks
3
+ *
4
+ * Re-exports all store custom hooks
5
+ */
6
+ export { useCart } from './useCart';
7
+ export { useBackendCart } from './useBackendCart';
8
+ export { useOrders } from './useOrders';
9
+ export { useInstallations } from './useInstallations';
10
+ export { useProductSearch } from './useProductSearch';
11
+ export { useStorePermissions, STORE_PERMISSIONS, type StorePermission, type StorePermissions, } from './useStorePermissions';
12
+ export * from './useStoreGraphQL';
@@ -0,0 +1,73 @@
1
+ import { AddToCartInput, CreateStoreOrderInput } from '../generated/global-types';
2
+
3
+ export interface Cart {
4
+ id: string;
5
+ userId?: string;
6
+ organizationId?: string;
7
+ sessionId?: string;
8
+ status: 'ACTIVE' | 'ABANDONED' | 'CONVERTED' | 'EXPIRED';
9
+ currency: string;
10
+ subtotal: number;
11
+ total: number;
12
+ itemCount: number;
13
+ notes?: string;
14
+ expiresAt?: string;
15
+ lastActivityAt: string;
16
+ createdAt: string;
17
+ updatedAt: string;
18
+ requiresShipping: boolean;
19
+ isEmpty: boolean;
20
+ items: CartItem[];
21
+ }
22
+ export interface CartItem {
23
+ id: string;
24
+ cartId: string;
25
+ productId: string;
26
+ variantId?: string;
27
+ itemType: 'DIGITAL' | 'PHYSICAL' | 'BUNDLE';
28
+ quantity: number;
29
+ unitPrice: number;
30
+ compareAtPrice?: number;
31
+ subtotal: number;
32
+ workspaceId?: string;
33
+ productName: string;
34
+ variantName?: string;
35
+ productIcon?: string;
36
+ product?: {
37
+ id: string;
38
+ name: string;
39
+ slug?: string;
40
+ icon?: string;
41
+ price?: number;
42
+ pricingModel?: string;
43
+ };
44
+ addedAt: string;
45
+ updatedAt: string;
46
+ }
47
+ /**
48
+ * Hook for backend cart operations
49
+ */
50
+ export declare function useBackendCart(): {
51
+ cart: Cart | null;
52
+ cartItems: CartItem[];
53
+ itemCount: number;
54
+ subtotal: number;
55
+ tax: number;
56
+ total: number;
57
+ currency: string;
58
+ loading: boolean;
59
+ addingToCart: boolean;
60
+ updatingCartItem: boolean;
61
+ removingFromCart: boolean;
62
+ clearingCart: boolean;
63
+ checkingOut: boolean;
64
+ error: Error | null;
65
+ addProductToCart: (input: AddToCartInput) => Promise<Cart | undefined>;
66
+ updateQuantity: (cartItemId: string, quantity: number) => Promise<Cart | undefined>;
67
+ removeProductFromCart: (cartItemId: string) => Promise<Cart | undefined>;
68
+ clearAllItems: () => Promise<Cart | undefined>;
69
+ createOrder: (input: CreateStoreOrderInput) => Promise<{
70
+ id: string;
71
+ }>;
72
+ refetchCart: (forceNetwork?: boolean) => Promise<void>;
73
+ };
@@ -0,0 +1,171 @@
1
+ import { useStoreGraphQLWithContext as e } from "./useStoreGraphQLWithContext.js";
2
+ import { AddToCartDocument as t, ClearCartDocument as n, CreateStoreOrderDocument as r, GetCartDocument as i, RemoveFromCartDocument as a, UpdateCartItemDocument as o } from "../generated/global-operations.js";
3
+ import { useCallback as s, useEffect as c, useState as l } from "react";
4
+ import { useApolloClient as u } from "@apollo/client/react";
5
+ //#region src/hooks/useBackendCart.ts
6
+ function d() {
7
+ let d = u(), { query: f, mutate: p, hasOrganizationContext: m } = e(), [h, g] = l(null), [_, v] = l(!0), [y, b] = l(null), [x, S] = l(!1), [C, w] = l(!1), [T, E] = l(!1), [D, O] = l(!1), [k, A] = l(!1), j = s(async (e = !1) => {
8
+ v(!0), b(null);
9
+ try {
10
+ g(m ? (await f({
11
+ query: i,
12
+ fetchPolicy: e ? "network-only" : "cache-first"
13
+ })).data?.myCart || null : (await d.query({
14
+ query: i,
15
+ fetchPolicy: e ? "network-only" : "cache-first"
16
+ })).data?.myCart || null);
17
+ } catch (e) {
18
+ b(e), console.error("Failed to fetch cart:", e);
19
+ } finally {
20
+ v(!1);
21
+ }
22
+ }, [
23
+ d,
24
+ f,
25
+ m
26
+ ]);
27
+ c(() => {
28
+ j();
29
+ }, [j]);
30
+ let M = s(async (e) => {
31
+ if (!d) throw Error("Global client not initialized");
32
+ S(!0);
33
+ try {
34
+ let n;
35
+ if (n = m ? await p({
36
+ mutation: t,
37
+ variables: { input: e }
38
+ }) : await d.mutate({
39
+ mutation: t,
40
+ variables: { input: e }
41
+ }), n.data?.addToCart.errors && n.data.addToCart.errors.length > 0) throw Error(n.data.addToCart.errors[0].message);
42
+ return n.data?.addToCart.cart && g(n.data.addToCart.cart), await j(!0), n.data?.addToCart.cart;
43
+ } catch (e) {
44
+ throw console.error("Failed to add product to cart:", e), e;
45
+ } finally {
46
+ S(!1);
47
+ }
48
+ }, [
49
+ p,
50
+ d,
51
+ m,
52
+ j
53
+ ]), N = s(async (e, t) => {
54
+ if (!d) throw Error("Global client not initialized");
55
+ w(!0);
56
+ try {
57
+ let n;
58
+ if (n = m ? await p({
59
+ mutation: o,
60
+ variables: { input: {
61
+ cartItemId: e,
62
+ quantity: t
63
+ } }
64
+ }) : await d.mutate({
65
+ mutation: o,
66
+ variables: { input: {
67
+ cartItemId: e,
68
+ quantity: t
69
+ } }
70
+ }), n.data?.updateCartItem.errors && n.data.updateCartItem.errors.length > 0) throw Error(n.data.updateCartItem.errors[0].message);
71
+ return n.data?.updateCartItem.cart && g(n.data.updateCartItem.cart), await j(!0), n.data?.updateCartItem.cart;
72
+ } catch (e) {
73
+ throw console.error("Failed to update cart item:", e), e;
74
+ } finally {
75
+ w(!1);
76
+ }
77
+ }, [
78
+ p,
79
+ d,
80
+ m,
81
+ j
82
+ ]), P = s(async (e) => {
83
+ if (!d) throw Error("Global client not initialized");
84
+ E(!0);
85
+ try {
86
+ let t;
87
+ if (t = m ? await p({
88
+ mutation: a,
89
+ variables: { cartItemId: e }
90
+ }) : await d.mutate({
91
+ mutation: a,
92
+ variables: { cartItemId: e }
93
+ }), t.data?.removeFromCart.errors && t.data.removeFromCart.errors.length > 0) throw Error(t.data.removeFromCart.errors[0].message);
94
+ return t.data?.removeFromCart.cart && g(t.data.removeFromCart.cart), await j(!0), t.data?.removeFromCart.cart;
95
+ } catch (e) {
96
+ throw console.error("Failed to remove product from cart:", e), e;
97
+ } finally {
98
+ E(!1);
99
+ }
100
+ }, [
101
+ p,
102
+ d,
103
+ m,
104
+ j
105
+ ]), F = s(async () => {
106
+ O(!0);
107
+ try {
108
+ let e;
109
+ if (e = m ? await p({ mutation: n }) : await d.mutate({ mutation: n }), e.data?.clearCart.errors && e.data.clearCart.errors.length > 0) throw Error(e.data.clearCart.errors[0].message);
110
+ return e.data?.clearCart.cart && g(e.data.clearCart.cart), await j(!0), e.data?.clearCart.cart;
111
+ } catch (e) {
112
+ throw console.error("Failed to clear cart:", e), e;
113
+ } finally {
114
+ O(!1);
115
+ }
116
+ }, [
117
+ p,
118
+ d,
119
+ m,
120
+ j
121
+ ]), I = s(async (e) => {
122
+ if (!d) throw Error("Global client not initialized");
123
+ A(!0);
124
+ try {
125
+ let t;
126
+ if (t = m ? await p({
127
+ mutation: r,
128
+ variables: { input: e }
129
+ }) : await d.mutate({
130
+ mutation: r,
131
+ variables: { input: e }
132
+ }), !t.data?.createStoreOrder?.id) throw Error("Failed to create order");
133
+ return await j(!0), t.data.createStoreOrder;
134
+ } catch (e) {
135
+ throw console.error("Failed to create order:", e), e;
136
+ } finally {
137
+ A(!1);
138
+ }
139
+ }, [
140
+ p,
141
+ d,
142
+ m,
143
+ j
144
+ ]), L = h?.items || [], R = h?.itemCount || 0, z = h?.subtotal || 0, B = h?.total || 0;
145
+ return {
146
+ cart: h,
147
+ cartItems: L,
148
+ itemCount: R,
149
+ subtotal: z,
150
+ tax: B - z,
151
+ total: B,
152
+ currency: h?.currency || "USD",
153
+ loading: _,
154
+ addingToCart: x,
155
+ updatingCartItem: C,
156
+ removingFromCart: T,
157
+ clearingCart: D,
158
+ checkingOut: k,
159
+ error: y,
160
+ addProductToCart: M,
161
+ updateQuantity: N,
162
+ removeProductFromCart: P,
163
+ clearAllItems: F,
164
+ createOrder: I,
165
+ refetchCart: j
166
+ };
167
+ }
168
+ //#endregion
169
+ export { d as useBackendCart };
170
+
171
+ //# sourceMappingURL=useBackendCart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useBackendCart.js","names":[],"sources":["../../src/hooks/useBackendCart.ts"],"sourcesContent":["/**\n * Backend Cart Hook\n *\n * Provides cart operations that interact with the backend store service.\n * All cart data is stored on the backend, not in localStorage.\n */\n\nimport { useState, useEffect, useCallback } from 'react';\nimport { useApolloClient } from '@apollo/client/react';\nimport { useStoreGraphQLWithContext } from './useStoreGraphQLWithContext';\nimport {\n GetCartDocument,\n AddToCartDocument,\n UpdateCartItemDocument,\n RemoveFromCartDocument,\n ClearCartDocument,\n CreateStoreOrderDocument,\n} from '../generated/global-operations';\nimport { type AddToCartInput, type CreateStoreOrderInput } from '../generated/global-types';\n\n// Cart types - defined locally since operations.ts doesn't export them\nexport interface Cart {\n id: string;\n userId?: string;\n organizationId?: string;\n sessionId?: string;\n status: 'ACTIVE' | 'ABANDONED' | 'CONVERTED' | 'EXPIRED';\n currency: string;\n subtotal: number;\n total: number;\n itemCount: number;\n notes?: string;\n expiresAt?: string;\n lastActivityAt: string;\n createdAt: string;\n updatedAt: string;\n requiresShipping: boolean;\n isEmpty: boolean;\n items: CartItem[];\n}\n\nexport interface CartItem {\n id: string;\n cartId: string;\n productId: string;\n variantId?: string;\n itemType: 'DIGITAL' | 'PHYSICAL' | 'BUNDLE';\n quantity: number;\n unitPrice: number;\n compareAtPrice?: number;\n subtotal: number;\n workspaceId?: string;\n productName: string;\n variantName?: string;\n productIcon?: string;\n product?: {\n id: string;\n name: string;\n slug?: string;\n icon?: string;\n price?: number;\n pricingModel?: string;\n };\n addedAt: string;\n updatedAt: string;\n}\n\ninterface CartError {\n field?: string;\n message: string;\n code: string;\n}\n\ninterface CartItemPayload {\n cartItem?: CartItem;\n cart?: Cart;\n errors?: CartError[];\n}\n\ninterface CartPayload {\n cart?: Cart;\n errors?: CartError[];\n}\n\n/**\n * Hook for backend cart operations\n */\nexport function useBackendCart() {\n const globalClient = useApolloClient();\n const {\n query: queryWithContext,\n mutate: mutateWithContext,\n hasOrganizationContext,\n } = useStoreGraphQLWithContext();\n const [cart, setCart] = useState<Cart | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [addingToCart, setAddingToCart] = useState(false);\n const [updatingCartItem, setUpdatingCartItem] = useState(false);\n const [removingFromCart, setRemovingFromCart] = useState(false);\n const [clearingCart, setClearingCart] = useState(false);\n const [checkingOut, setCheckingOut] = useState(false);\n\n // Fetch cart from backend\n const fetchCart = useCallback(\n async (forceNetwork = false) => {\n setLoading(true);\n setError(null);\n try {\n // Use organization-aware query if organization context is available\n if (hasOrganizationContext) {\n const result = (await queryWithContext({\n query: GetCartDocument,\n fetchPolicy: forceNetwork ? 'network-only' : 'cache-first',\n })) as { data?: { myCart: Cart | null } };\n setCart(result.data?.myCart || null);\n } else {\n // Fallback to regular client without organization context\n const result = await globalClient.query<{ myCart: Cart | null }>({\n query: GetCartDocument,\n fetchPolicy: forceNetwork ? 'network-only' : 'cache-first',\n });\n setCart(result.data?.myCart || null);\n }\n } catch (err) {\n setError(err as Error);\n console.error('Failed to fetch cart:', err);\n } finally {\n setLoading(false);\n }\n },\n [globalClient, queryWithContext, hasOrganizationContext]\n );\n\n // Fetch cart on mount and when globalClient changes\n useEffect(() => {\n fetchCart();\n }, [fetchCart]);\n\n // Add product to cart\n const addProductToCart = useCallback(\n async (input: AddToCartInput) => {\n if (!globalClient) {\n throw new Error('Global client not initialized');\n }\n\n setAddingToCart(true);\n try {\n let result;\n\n if (hasOrganizationContext) {\n // Use organization-aware mutation\n result = (await mutateWithContext({\n mutation: AddToCartDocument,\n variables: { input },\n })) as { data?: { addToCart: CartItemPayload } };\n } else {\n // Fallback to global client without organization context\n result = await globalClient.mutate<{ addToCart: CartItemPayload }>({\n mutation: AddToCartDocument,\n variables: { input },\n });\n }\n\n if (result.data?.addToCart.errors && result.data.addToCart.errors.length > 0) {\n throw new Error(result.data.addToCart.errors[0].message);\n }\n\n // Update local cart state\n if (result.data?.addToCart.cart) {\n setCart(result.data.addToCart.cart);\n }\n\n // Refetch to ensure consistency\n await fetchCart(true);\n\n return result.data?.addToCart.cart;\n } catch (error) {\n console.error('Failed to add product to cart:', error);\n throw error;\n } finally {\n setAddingToCart(false);\n }\n },\n [mutateWithContext, globalClient, hasOrganizationContext, fetchCart]\n );\n\n // Update cart item quantity\n const updateQuantity = useCallback(\n async (cartItemId: string, quantity: number) => {\n if (!globalClient) {\n throw new Error('Global client not initialized');\n }\n\n setUpdatingCartItem(true);\n try {\n let result;\n\n if (hasOrganizationContext) {\n // Use organization-aware mutation\n result = (await mutateWithContext({\n mutation: UpdateCartItemDocument,\n variables: { input: { cartItemId, quantity } },\n })) as { data?: { updateCartItem: CartItemPayload } };\n } else {\n // Fallback to global client without organization context\n result = await globalClient.mutate<{ updateCartItem: CartItemPayload }>({\n mutation: UpdateCartItemDocument,\n variables: { input: { cartItemId, quantity } },\n });\n }\n\n if (result.data?.updateCartItem.errors && result.data.updateCartItem.errors.length > 0) {\n throw new Error(result.data.updateCartItem.errors[0].message);\n }\n\n // Update local cart state\n if (result.data?.updateCartItem.cart) {\n setCart(result.data.updateCartItem.cart);\n }\n\n // Refetch to ensure consistency\n await fetchCart(true);\n\n return result.data?.updateCartItem.cart;\n } catch (error) {\n console.error('Failed to update cart item:', error);\n throw error;\n } finally {\n setUpdatingCartItem(false);\n }\n },\n [mutateWithContext, globalClient, hasOrganizationContext, fetchCart]\n );\n\n // Remove product from cart\n const removeProductFromCart = useCallback(\n async (cartItemId: string) => {\n if (!globalClient) {\n throw new Error('Global client not initialized');\n }\n\n setRemovingFromCart(true);\n try {\n let result;\n\n if (hasOrganizationContext) {\n // Use organization-aware mutation\n result = (await mutateWithContext({\n mutation: RemoveFromCartDocument,\n variables: { cartItemId },\n })) as { data?: { removeFromCart: CartPayload } };\n } else {\n // Fallback to global client without organization context\n result = await globalClient.mutate<{ removeFromCart: CartPayload }>({\n mutation: RemoveFromCartDocument,\n variables: { cartItemId },\n });\n }\n\n if (result.data?.removeFromCart.errors && result.data.removeFromCart.errors.length > 0) {\n throw new Error(result.data.removeFromCart.errors[0].message);\n }\n\n // Update local cart state\n if (result.data?.removeFromCart.cart) {\n setCart(result.data.removeFromCart.cart);\n }\n\n // Refetch to ensure consistency\n await fetchCart(true);\n\n return result.data?.removeFromCart.cart;\n } catch (error) {\n console.error('Failed to remove product from cart:', error);\n throw error;\n } finally {\n setRemovingFromCart(false);\n }\n },\n [mutateWithContext, globalClient, hasOrganizationContext, fetchCart]\n );\n\n // Clear all items from cart\n const clearAllItems = useCallback(async () => {\n setClearingCart(true);\n try {\n let result;\n\n if (hasOrganizationContext) {\n // Use organization-aware mutation\n result = (await mutateWithContext({\n mutation: ClearCartDocument,\n })) as { data?: { clearCart: CartPayload } };\n } else {\n // Fallback to global client without organization context\n result = await globalClient.mutate<{ clearCart: CartPayload }>({\n mutation: ClearCartDocument,\n });\n }\n\n if (result.data?.clearCart.errors && result.data.clearCart.errors.length > 0) {\n throw new Error(result.data.clearCart.errors[0].message);\n }\n\n // Update local cart state\n if (result.data?.clearCart.cart) {\n setCart(result.data.clearCart.cart);\n }\n\n // Refetch to ensure consistency\n await fetchCart(true);\n\n return result.data?.clearCart.cart;\n } catch (error) {\n console.error('Failed to clear cart:', error);\n throw error;\n } finally {\n setClearingCart(false);\n }\n }, [mutateWithContext, globalClient, hasOrganizationContext, fetchCart]);\n\n // CreateStoreOrder response type\n interface CreateStoreOrderResponse {\n createStoreOrder: { id: string } | null;\n }\n\n // Create store order from cart\n const createOrder = useCallback(\n async (input: CreateStoreOrderInput) => {\n if (!globalClient) {\n throw new Error('Global client not initialized');\n }\n\n setCheckingOut(true);\n try {\n let result;\n\n if (hasOrganizationContext) {\n // Use organization-aware mutation\n result = (await mutateWithContext({\n mutation: CreateStoreOrderDocument,\n variables: { input },\n })) as { data?: CreateStoreOrderResponse };\n } else {\n // Fallback to global client without organization context\n result = await globalClient.mutate<CreateStoreOrderResponse>({\n mutation: CreateStoreOrderDocument,\n variables: { input },\n });\n }\n\n if (!result.data?.createStoreOrder?.id) {\n throw new Error('Failed to create order');\n }\n\n // Refetch cart after order creation (should be empty or converted)\n await fetchCart(true);\n\n return result.data.createStoreOrder;\n } catch (error) {\n console.error('Failed to create order:', error);\n throw error;\n } finally {\n setCheckingOut(false);\n }\n },\n [mutateWithContext, globalClient, hasOrganizationContext, fetchCart]\n );\n\n const cartItems = cart?.items || [];\n const itemCount = cart?.itemCount || 0;\n const subtotal = cart?.subtotal || 0;\n const total = cart?.total || 0;\n const tax = total - subtotal; // Tax is calculated as difference between total and subtotal\n const currency = cart?.currency || 'USD';\n\n return {\n // Cart data\n cart,\n cartItems,\n itemCount,\n subtotal,\n tax,\n total,\n currency,\n\n // Loading states\n loading,\n addingToCart,\n updatingCartItem,\n removingFromCart,\n clearingCart,\n checkingOut,\n\n // Error state\n error,\n\n // Actions\n addProductToCart,\n updateQuantity,\n removeProductFromCart,\n clearAllItems,\n createOrder,\n refetchCart: fetchCart,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import { Product, ProductVariant } from '../types';
2
+
3
+ /**
4
+ * Hook for cart management (now using backend cart)
5
+ *
6
+ * This hook provides a unified interface for cart operations,
7
+ * using the backend for cart data and Zustand for UI state.
8
+ */
9
+ export declare function useCart(): {
10
+ cart: import('./useBackendCart').Cart | null;
11
+ cartItems: {
12
+ id: string;
13
+ productId: string;
14
+ productName: string;
15
+ productIcon: string | undefined;
16
+ variantName: string | undefined;
17
+ subtotal: number;
18
+ product: {
19
+ id: string;
20
+ name: string;
21
+ displayName: string;
22
+ icon: string | undefined;
23
+ iconUrl: string | undefined;
24
+ publisher: {
25
+ displayName?: string;
26
+ name?: string;
27
+ } | undefined;
28
+ pricingModel: string | undefined;
29
+ };
30
+ variantId: string | undefined;
31
+ variant: {
32
+ name: string;
33
+ version: string;
34
+ } | undefined;
35
+ quantity: number;
36
+ unitPrice: number;
37
+ totalPrice: number;
38
+ itemType: "physical" | "digital" | "bundle";
39
+ }[];
40
+ itemCount: number;
41
+ subtotal: number;
42
+ tax: number;
43
+ total: number;
44
+ cartOpen: boolean;
45
+ loading: boolean;
46
+ addingToCart: boolean;
47
+ updatingCartItem: boolean;
48
+ removingFromCart: boolean;
49
+ clearingCart: boolean;
50
+ checkingOut: boolean;
51
+ addProduct: (product: Product, variant?: ProductVariant, quantity?: number, workspaceId?: string) => Promise<void>;
52
+ removeProduct: (cartItemId: string) => Promise<void>;
53
+ updateQuantity: (cartItemId: string, quantity: number) => Promise<void>;
54
+ clearCart: () => Promise<void>;
55
+ createOrder: (input: import('../generated/global-types').CreateStoreOrderInput) => Promise<{
56
+ id: string;
57
+ }>;
58
+ refetchCart: (forceNetwork?: boolean) => Promise<void>;
59
+ toggleCart: () => void;
60
+ openCart: () => void;
61
+ closeCart: () => void;
62
+ };
@@ -0,0 +1,90 @@
1
+ import { useStoreStore as e } from "../store/storeStore.js";
2
+ import { useBackendCart as t } from "./useBackendCart.js";
3
+ import { useCallback as n } from "react";
4
+ //#region src/hooks/useCart.ts
5
+ function r() {
6
+ let { cart: r, cartItems: i, itemCount: a, subtotal: o, tax: s, total: c, loading: l, addingToCart: u, updatingCartItem: d, removingFromCart: f, clearingCart: p, checkingOut: m, addProductToCart: h, updateQuantity: g, removeProductFromCart: _, clearAllItems: v, createOrder: y, refetchCart: b } = t(), { cartOpen: x, toggleCart: S, setCartOpen: C } = e(), w = n(async (e, t, n = 1, r) => {
7
+ try {
8
+ if (e.pricingModel === "FREE" || e.basePrice === 0) throw Error("Free items cannot be added to cart — use the Install flow instead");
9
+ await h({
10
+ productId: e.id,
11
+ variantId: t?.id,
12
+ quantity: n,
13
+ workspaceId: r
14
+ }), C(!0);
15
+ } catch (e) {
16
+ throw console.error("Failed to add product to cart:", e), e;
17
+ }
18
+ }, [h, C]), T = n(async (e) => {
19
+ try {
20
+ await _(e);
21
+ } catch (e) {
22
+ throw console.error("Failed to remove product from cart:", e), e;
23
+ }
24
+ }, [_]), E = n(async (e, t) => {
25
+ try {
26
+ t <= 0 ? await _(e) : await g(e, t);
27
+ } catch (e) {
28
+ throw console.error("Failed to update cart item quantity:", e), e;
29
+ }
30
+ }, [g, _]), D = n(async () => {
31
+ try {
32
+ await v(), C(!1);
33
+ } catch (e) {
34
+ throw console.error("Failed to clear cart:", e), e;
35
+ }
36
+ }, [v, C]);
37
+ return {
38
+ cart: r,
39
+ cartItems: i.map((e) => ({
40
+ id: e.id,
41
+ productId: e.productId,
42
+ productName: e.productName,
43
+ productIcon: e.productIcon,
44
+ variantName: e.variantName,
45
+ subtotal: e.subtotal,
46
+ product: {
47
+ id: e.productId,
48
+ name: e.productName,
49
+ displayName: e.productName,
50
+ icon: e.productIcon,
51
+ iconUrl: e.productIcon,
52
+ publisher: void 0,
53
+ pricingModel: e.product?.pricingModel || void 0
54
+ },
55
+ variantId: e.variantId,
56
+ variant: e.variantName ? {
57
+ name: e.variantName,
58
+ version: e.variantName
59
+ } : void 0,
60
+ quantity: e.quantity,
61
+ unitPrice: e.unitPrice,
62
+ totalPrice: e.subtotal,
63
+ itemType: e.itemType.toLowerCase()
64
+ })),
65
+ itemCount: a,
66
+ subtotal: o,
67
+ tax: s,
68
+ total: c,
69
+ cartOpen: x,
70
+ loading: l,
71
+ addingToCart: u,
72
+ updatingCartItem: d,
73
+ removingFromCart: f,
74
+ clearingCart: p,
75
+ checkingOut: m,
76
+ addProduct: w,
77
+ removeProduct: T,
78
+ updateQuantity: E,
79
+ clearCart: D,
80
+ createOrder: y,
81
+ refetchCart: b,
82
+ toggleCart: S,
83
+ openCart: () => C(!0),
84
+ closeCart: () => C(!1)
85
+ };
86
+ }
87
+ //#endregion
88
+ export { r as useCart };
89
+
90
+ //# sourceMappingURL=useCart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCart.js","names":[],"sources":["../../src/hooks/useCart.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useStoreStore } from '../store/storeStore';\nimport { useBackendCart } from './useBackendCart';\nimport type { Product, ProductVariant } from '../types';\n\n/**\n * Hook for cart management (now using backend cart)\n *\n * This hook provides a unified interface for cart operations,\n * using the backend for cart data and Zustand for UI state.\n */\nexport function useCart() {\n const {\n cart,\n cartItems: backendCartItems,\n itemCount,\n subtotal,\n tax,\n total,\n loading,\n addingToCart,\n updatingCartItem,\n removingFromCart,\n clearingCart,\n checkingOut,\n addProductToCart,\n updateQuantity: backendUpdateQuantity,\n removeProductFromCart,\n clearAllItems,\n createOrder,\n refetchCart,\n } = useBackendCart();\n\n const { cartOpen, toggleCart, setCartOpen } = useStoreStore();\n\n /**\n * Add a product to cart\n */\n const addProduct = useCallback(\n async (\n product: Product,\n variant?: ProductVariant,\n quantity: number = 1,\n workspaceId?: string\n ) => {\n try {\n if (product.pricingModel === 'FREE' || product.basePrice === 0) {\n throw new Error('Free items cannot be added to cart — use the Install flow instead');\n }\n await addProductToCart({\n productId: product.id,\n variantId: variant?.id,\n quantity,\n workspaceId,\n });\n\n // Open cart drawer after adding\n setCartOpen(true);\n } catch (error) {\n console.error('Failed to add product to cart:', error);\n throw error;\n }\n },\n [addProductToCart, setCartOpen]\n );\n\n /**\n * Remove a product from cart\n */\n const removeProduct = useCallback(\n async (cartItemId: string) => {\n try {\n await removeProductFromCart(cartItemId);\n } catch (error) {\n console.error('Failed to remove product from cart:', error);\n throw error;\n }\n },\n [removeProductFromCart]\n );\n\n /**\n * Update cart item quantity\n */\n const updateQuantity = useCallback(\n async (cartItemId: string, quantity: number) => {\n try {\n if (quantity <= 0) {\n await removeProductFromCart(cartItemId);\n } else {\n await backendUpdateQuantity(cartItemId, quantity);\n }\n } catch (error) {\n console.error('Failed to update cart item quantity:', error);\n throw error;\n }\n },\n [backendUpdateQuantity, removeProductFromCart]\n );\n\n /**\n * Clear all items from cart\n */\n const clearCart = useCallback(async () => {\n try {\n await clearAllItems();\n setCartOpen(false);\n } catch (error) {\n console.error('Failed to clear cart:', error);\n throw error;\n }\n }, [clearAllItems, setCartOpen]);\n\n // Map backend cart items to the frontend CartItem type\n // Backend items include productName, productIcon, variantName from denormalized data\n // We include both backend field names (for direct access) and frontend mapped fields (for type compatibility)\n const cartItems = backendCartItems.map((item) => ({\n id: item.id,\n productId: item.productId,\n // Backend fields (for direct access by components)\n productName: item.productName,\n productIcon: item.productIcon,\n variantName: item.variantName,\n subtotal: item.subtotal,\n // Create a minimal product object from the backend item's denormalized fields\n product: {\n id: item.productId,\n name: item.productName,\n displayName: item.productName,\n icon: item.productIcon,\n iconUrl: item.productIcon,\n // Publisher is not available in cart item - would need separate fetch\n publisher: undefined as { displayName?: string; name?: string } | undefined,\n pricingModel: item.product?.pricingModel || undefined,\n },\n variantId: item.variantId,\n variant: item.variantName\n ? {\n name: item.variantName,\n version: item.variantName,\n }\n : undefined,\n quantity: item.quantity,\n unitPrice: item.unitPrice,\n totalPrice: item.subtotal,\n itemType: item.itemType.toLowerCase() as 'physical' | 'digital' | 'bundle',\n }));\n\n return {\n // Cart data from backend\n cart,\n cartItems,\n itemCount,\n subtotal,\n tax,\n total,\n\n // UI state from Zustand\n cartOpen,\n\n // Loading states\n loading,\n addingToCart,\n updatingCartItem,\n removingFromCart,\n clearingCart,\n checkingOut,\n\n // Actions\n addProduct,\n removeProduct,\n updateQuantity,\n clearCart,\n createOrder,\n refetchCart,\n\n // UI actions\n toggleCart,\n openCart: () => setCartOpen(true),\n closeCart: () => setCartOpen(false),\n };\n}\n"],"mappings":";;;;AAWA,SAAgB,IAAU;CACxB,IAAM,EACJ,SACA,WAAW,GACX,cACA,aACA,QACA,UACA,YACA,iBACA,qBACA,qBACA,iBACA,gBACA,qBACA,gBAAgB,GAChB,0BACA,kBACA,gBACA,mBACE,GAAgB,EAEd,EAAE,aAAU,eAAY,mBAAgB,GAAe,EAKvD,IAAa,EACjB,OACE,GACA,GACA,IAAmB,GACnB,MACG;AACH,MAAI;AACF,OAAI,EAAQ,iBAAiB,UAAU,EAAQ,cAAc,EAC3D,OAAU,MAAM,oEAAoE;AAUtF,GARA,MAAM,EAAiB;IACrB,WAAW,EAAQ;IACnB,WAAW,GAAS;IACpB;IACA;IACD,CAAC,EAGF,EAAY,GAAK;WACV,GAAO;AAEd,SADA,QAAQ,MAAM,kCAAkC,EAAM,EAChD;;IAGV,CAAC,GAAkB,EAAY,CAChC,EAKK,IAAgB,EACpB,OAAO,MAAuB;AAC5B,MAAI;AACF,SAAM,EAAsB,EAAW;WAChC,GAAO;AAEd,SADA,QAAQ,MAAM,uCAAuC,EAAM,EACrD;;IAGV,CAAC,EAAsB,CACxB,EAKK,IAAiB,EACrB,OAAO,GAAoB,MAAqB;AAC9C,MAAI;AACF,GAAI,KAAY,IACd,MAAM,EAAsB,EAAW,GAEvC,MAAM,EAAsB,GAAY,EAAS;WAE5C,GAAO;AAEd,SADA,QAAQ,MAAM,wCAAwC,EAAM,EACtD;;IAGV,CAAC,GAAuB,EAAsB,CAC/C,EAKK,IAAY,EAAY,YAAY;AACxC,MAAI;AAEF,GADA,MAAM,GAAe,EACrB,EAAY,GAAM;WACX,GAAO;AAEd,SADA,QAAQ,MAAM,yBAAyB,EAAM,EACvC;;IAEP,CAAC,GAAe,EAAY,CAAC;AAqChC,QAAO;EAEL;EACA,WAnCgB,EAAiB,KAAK,OAAU;GAChD,IAAI,EAAK;GACT,WAAW,EAAK;GAEhB,aAAa,EAAK;GAClB,aAAa,EAAK;GAClB,aAAa,EAAK;GAClB,UAAU,EAAK;GAEf,SAAS;IACP,IAAI,EAAK;IACT,MAAM,EAAK;IACX,aAAa,EAAK;IAClB,MAAM,EAAK;IACX,SAAS,EAAK;IAEd,WAAW,KAAA;IACX,cAAc,EAAK,SAAS,gBAAgB,KAAA;IAC7C;GACD,WAAW,EAAK;GAChB,SAAS,EAAK,cACV;IACE,MAAM,EAAK;IACX,SAAS,EAAK;IACf,GACD,KAAA;GACJ,UAAU,EAAK;GACf,WAAW,EAAK;GAChB,YAAY,EAAK;GACjB,UAAU,EAAK,SAAS,aAAa;GACtC,EAAE;EAMD;EACA;EACA;EACA;EAGA;EAGA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA,gBAAgB,EAAY,GAAK;EACjC,iBAAiB,EAAY,GAAM;EACpC"}
@@ -0,0 +1,43 @@
1
+ import { StoreInstallationStatus, InstallationFilterInput } from '../generated/global-types';
2
+
3
+ export interface InstalledApp {
4
+ id: string;
5
+ productId: string;
6
+ workspaceId: string;
7
+ organizationId?: string | null;
8
+ status: StoreInstallationStatus;
9
+ installedAt: string;
10
+ version?: string | null;
11
+ updatedAt: string;
12
+ workspaceName?: string | null;
13
+ workspaceType?: string | null;
14
+ installedById: string;
15
+ manifest?: Record<string, unknown> | null;
16
+ metadata?: Record<string, unknown> | null;
17
+ context?: Record<string, unknown> | null;
18
+ uninstalledAt?: string | null;
19
+ uninstalledById?: string | null;
20
+ }
21
+ interface InstallationsState {
22
+ installations: InstalledApp[];
23
+ totalCount: number;
24
+ hasMore: boolean;
25
+ loading: boolean;
26
+ error: Error | null;
27
+ uninstallingIds: Set<string>;
28
+ refetch: () => Promise<void>;
29
+ loadMore: () => void;
30
+ uninstall: (installation: Pick<InstalledApp, 'workspaceId' | 'productId'>, reason?: string) => Promise<boolean>;
31
+ }
32
+ export declare function useInstallations(options?: {
33
+ filter?: InstallationFilterInput;
34
+ limit?: number;
35
+ offset?: number;
36
+ }): InstallationsState;
37
+ export declare function useInstallation(installationId?: string): {
38
+ installation: InstalledApp | null;
39
+ loading: boolean;
40
+ error: Error | null;
41
+ refetch: () => Promise<void>;
42
+ };
43
+ export {};
@@ -0,0 +1,140 @@
1
+ import { useStoreGraphQLWithContext as e } from "./useStoreGraphQLWithContext.js";
2
+ import { GetMyStoreInstallationsDocument as t, GetStoreAppInstallationDocument as n, RecordAppUninstallationDocument as r } from "../generated/global-operations.js";
3
+ import { useCallback as i, useEffect as a, useMemo as o, useState as s } from "react";
4
+ import { useApolloClient as c } from "@apollo/client/react";
5
+ //#region src/hooks/useInstallations.ts
6
+ function l(n) {
7
+ let { query: l, mutate: u, hasOrganizationContext: d } = e(), f = c(), [p, m] = s([]), [h, g] = s([]), [_, v] = s(0), [y, b] = s(!1), [x, S] = s(n?.offset ?? 0), [C, w] = s(!0), [T, E] = s(null), [D, O] = s(/* @__PURE__ */ new Set()), k = n?.limit ?? 50, A = o(() => ({
8
+ limit: k,
9
+ offset: n?.offset ?? 0,
10
+ filter: n?.filter
11
+ }), [
12
+ k,
13
+ n?.offset,
14
+ n?.filter
15
+ ]), j = i(async (e = 0, n = !1) => {
16
+ w(!0), E(null);
17
+ try {
18
+ let r = {
19
+ ...A,
20
+ offset: e
21
+ }, i;
22
+ i = d ? await l({
23
+ query: t,
24
+ variables: r,
25
+ fetchPolicy: "network-only"
26
+ }) : await f.query({
27
+ query: t,
28
+ variables: r,
29
+ fetchPolicy: "network-only"
30
+ });
31
+ let a = i.data?.myStoreAppInstallations?.items ?? [], o = i.data?.myStoreAppInstallations?.hasMore ?? !1;
32
+ g(n ? (e) => [...e, ...a] : a), m(a), v(i.data?.myStoreAppInstallations?.total ?? 0), b(o), S(e);
33
+ } catch (e) {
34
+ E(e);
35
+ } finally {
36
+ w(!1);
37
+ }
38
+ }, [
39
+ f,
40
+ d,
41
+ l,
42
+ A
43
+ ]);
44
+ return a(() => {
45
+ j(0);
46
+ }, [j]), {
47
+ installations: h,
48
+ totalCount: _,
49
+ hasMore: y,
50
+ loading: C,
51
+ error: T,
52
+ uninstallingIds: D,
53
+ refetch: () => j(0),
54
+ loadMore: i(() => {
55
+ !y || C || j(x + k, !0);
56
+ }, [
57
+ j,
58
+ y,
59
+ C,
60
+ x,
61
+ k
62
+ ]),
63
+ uninstall: i(async (e, t) => {
64
+ let n = `${e.workspaceId}:${e.productId}`;
65
+ O((e) => new Set(e).add(n));
66
+ try {
67
+ let t;
68
+ t = d ? await u({
69
+ mutation: r,
70
+ variables: {
71
+ workspaceId: e.workspaceId,
72
+ productId: e.productId
73
+ }
74
+ }) : await f.mutate({
75
+ mutation: r,
76
+ variables: {
77
+ workspaceId: e.workspaceId,
78
+ productId: e.productId
79
+ }
80
+ });
81
+ let n = !!t.data?.recordAppUninstallation?.id;
82
+ return n && await j(), n;
83
+ } catch {
84
+ return !1;
85
+ } finally {
86
+ O((e) => {
87
+ let t = new Set(e);
88
+ return t.delete(n), t;
89
+ });
90
+ }
91
+ }, [
92
+ j,
93
+ f,
94
+ d,
95
+ u
96
+ ])
97
+ };
98
+ }
99
+ function u(t) {
100
+ let { query: r, hasOrganizationContext: o } = e(), l = c(), [u, d] = s(null), [f, p] = s(!!t), [m, h] = s(null), g = i(async () => {
101
+ if (!t) {
102
+ d(null), p(!1);
103
+ return;
104
+ }
105
+ p(!0), h(null);
106
+ try {
107
+ let e;
108
+ e = o ? await r({
109
+ query: n,
110
+ variables: { id: t },
111
+ fetchPolicy: "network-only"
112
+ }) : await l.query({
113
+ query: n,
114
+ variables: { id: t },
115
+ fetchPolicy: "network-only"
116
+ }), d(e.data?.storeAppInstallation ?? null);
117
+ } catch (e) {
118
+ h(e);
119
+ } finally {
120
+ p(!1);
121
+ }
122
+ }, [
123
+ l,
124
+ o,
125
+ t,
126
+ r
127
+ ]);
128
+ return a(() => {
129
+ g();
130
+ }, [g]), {
131
+ installation: u,
132
+ loading: f,
133
+ error: m,
134
+ refetch: g
135
+ };
136
+ }
137
+ //#endregion
138
+ export { u as useInstallation, l as useInstallations };
139
+
140
+ //# sourceMappingURL=useInstallations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useInstallations.js","names":[],"sources":["../../src/hooks/useInstallations.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState } from 'react';\nimport { useApolloClient } from '@apollo/client/react';\nimport {\n GetMyStoreInstallationsDocument,\n GetStoreAppInstallationDocument,\n RecordAppUninstallationDocument,\n} from '../generated/global-operations';\nimport type { StoreInstallationStatus, InstallationFilterInput } from '../generated/global-types';\nimport { useStoreGraphQLWithContext } from './useStoreGraphQLWithContext';\n\nexport interface InstalledApp {\n id: string;\n productId: string;\n workspaceId: string;\n organizationId?: string | null;\n status: StoreInstallationStatus;\n installedAt: string;\n version?: string | null;\n updatedAt: string;\n workspaceName?: string | null;\n workspaceType?: string | null;\n installedById: string;\n manifest?: Record<string, unknown> | null;\n metadata?: Record<string, unknown> | null;\n context?: Record<string, unknown> | null;\n uninstalledAt?: string | null;\n uninstalledById?: string | null;\n}\n\ninterface InstallationsState {\n installations: InstalledApp[];\n totalCount: number;\n hasMore: boolean;\n loading: boolean;\n error: Error | null;\n uninstallingIds: Set<string>;\n refetch: () => Promise<void>;\n loadMore: () => void;\n uninstall: (\n installation: Pick<InstalledApp, 'workspaceId' | 'productId'>,\n reason?: string\n ) => Promise<boolean>;\n}\n\ntype InstallationsQueryData = {\n myStoreAppInstallations: {\n total: number;\n hasMore: boolean;\n items: Array<{\n id: string;\n productId: string;\n workspaceId: string;\n organizationId?: string | null;\n status: StoreInstallationStatus;\n installedAt: string;\n version?: string | null;\n updatedAt: string;\n workspaceName?: string | null;\n workspaceType?: string | null;\n installedById: string;\n }>;\n };\n};\n\ntype UninstallMutationData = {\n recordAppUninstallation?: {\n id: string;\n } | null;\n};\n\ntype InstallationQueryData = {\n storeAppInstallation?: InstalledApp | null;\n};\n\nexport function useInstallations(options?: {\n filter?: InstallationFilterInput;\n limit?: number;\n offset?: number;\n}): InstallationsState {\n const {\n query: queryWithContext,\n mutate: mutateWithContext,\n hasOrganizationContext,\n } = useStoreGraphQLWithContext();\n const globalClient = useApolloClient();\n\n const [installations, setInstallations] = useState<InstalledApp[]>([]);\n const [allInstallations, setAllInstallations] = useState<InstalledApp[]>([]);\n const [totalCount, setTotalCount] = useState(0);\n const [hasMore, setHasMore] = useState(false);\n const [currentOffset, setCurrentOffset] = useState(options?.offset ?? 0);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [uninstallingIds, setUninstallingIds] = useState<Set<string>>(new Set());\n const pageSize = options?.limit ?? 50;\n\n const variables = useMemo(\n () => ({\n limit: pageSize,\n offset: options?.offset ?? 0,\n filter: options?.filter,\n }),\n [pageSize, options?.offset, options?.filter]\n );\n\n const fetchInstallations = useCallback(\n async (fetchOffset = 0, append = false) => {\n setLoading(true);\n setError(null);\n\n try {\n const fetchVars = { ...variables, offset: fetchOffset };\n let result;\n if (hasOrganizationContext) {\n result = (await queryWithContext({\n query: GetMyStoreInstallationsDocument,\n variables: fetchVars,\n fetchPolicy: 'network-only',\n })) as { data?: InstallationsQueryData };\n } else {\n result = await globalClient.query<InstallationsQueryData>({\n query: GetMyStoreInstallationsDocument,\n variables: fetchVars,\n fetchPolicy: 'network-only',\n });\n }\n\n const items = result.data?.myStoreAppInstallations?.items ?? [];\n const more = result.data?.myStoreAppInstallations?.hasMore ?? false;\n if (append) {\n setAllInstallations((prev) => [...prev, ...items]);\n } else {\n setAllInstallations(items);\n }\n setInstallations(items);\n setTotalCount(result.data?.myStoreAppInstallations?.total ?? 0);\n setHasMore(more);\n setCurrentOffset(fetchOffset);\n } catch (err) {\n setError(err as Error);\n } finally {\n setLoading(false);\n }\n },\n [globalClient, hasOrganizationContext, queryWithContext, variables]\n );\n\n useEffect(() => {\n fetchInstallations(0);\n }, [fetchInstallations]);\n\n const loadMore = useCallback(() => {\n if (!hasMore || loading) return;\n fetchInstallations(currentOffset + pageSize, true);\n }, [fetchInstallations, hasMore, loading, currentOffset, pageSize]);\n\n const uninstall = useCallback(\n async (\n installation: Pick<InstalledApp, 'workspaceId' | 'productId'>,\n reason?: string\n ): Promise<boolean> => {\n const installationKey = `${installation.workspaceId}:${installation.productId}`;\n setUninstallingIds((prev) => new Set(prev).add(installationKey));\n try {\n void reason;\n let result: { data?: UninstallMutationData };\n if (hasOrganizationContext) {\n result = (await mutateWithContext({\n mutation: RecordAppUninstallationDocument,\n variables: {\n workspaceId: installation.workspaceId,\n productId: installation.productId,\n },\n })) as { data?: UninstallMutationData };\n } else {\n result = await globalClient.mutate<UninstallMutationData>({\n mutation: RecordAppUninstallationDocument,\n variables: {\n workspaceId: installation.workspaceId,\n productId: installation.productId,\n },\n });\n }\n\n const success = Boolean(result.data?.recordAppUninstallation?.id);\n if (success) {\n await fetchInstallations();\n }\n return success;\n } catch {\n return false;\n } finally {\n setUninstallingIds((prev) => {\n const next = new Set(prev);\n next.delete(installationKey);\n return next;\n });\n }\n },\n [fetchInstallations, globalClient, hasOrganizationContext, mutateWithContext]\n );\n\n return {\n installations: allInstallations,\n totalCount,\n hasMore,\n loading,\n error,\n uninstallingIds,\n refetch: () => fetchInstallations(0),\n loadMore,\n uninstall,\n };\n}\n\nexport function useInstallation(installationId?: string) {\n const { query: queryWithContext, hasOrganizationContext } = useStoreGraphQLWithContext();\n const globalClient = useApolloClient();\n const [installation, setInstallation] = useState<InstalledApp | null>(null);\n const [loading, setLoading] = useState(Boolean(installationId));\n const [error, setError] = useState<Error | null>(null);\n\n const fetchInstallation = useCallback(async () => {\n if (!installationId) {\n setInstallation(null);\n setLoading(false);\n return;\n }\n\n setLoading(true);\n setError(null);\n\n try {\n let result;\n if (hasOrganizationContext) {\n result = (await queryWithContext({\n query: GetStoreAppInstallationDocument,\n variables: { id: installationId },\n fetchPolicy: 'network-only',\n })) as { data?: InstallationQueryData };\n } else {\n result = await globalClient.query<InstallationQueryData>({\n query: GetStoreAppInstallationDocument,\n variables: { id: installationId },\n fetchPolicy: 'network-only',\n });\n }\n\n setInstallation(result.data?.storeAppInstallation ?? null);\n } catch (err) {\n setError(err as Error);\n } finally {\n setLoading(false);\n }\n }, [globalClient, hasOrganizationContext, installationId, queryWithContext]);\n\n useEffect(() => {\n fetchInstallation();\n }, [fetchInstallation]);\n\n return {\n installation,\n loading,\n error,\n refetch: fetchInstallation,\n };\n}\n"],"mappings":"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"}