@uptrademedia/site-kit 1.0.5 → 1.0.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 (169) hide show
  1. package/dist/analytics/index.js +7 -7
  2. package/dist/analytics/index.mjs +3 -3
  3. package/dist/api-QUIPJJCX.js +77 -0
  4. package/dist/api-QUIPJJCX.js.map +1 -0
  5. package/dist/api-V3BA5PMX.mjs +4 -0
  6. package/dist/api-V3BA5PMX.mjs.map +1 -0
  7. package/dist/blog/index.d.mts +2 -2
  8. package/dist/blog/index.d.ts +2 -2
  9. package/dist/blog/index.js +40 -6
  10. package/dist/blog/index.js.map +1 -1
  11. package/dist/blog/index.mjs +40 -6
  12. package/dist/blog/index.mjs.map +1 -1
  13. package/dist/blog/server.d.mts +3 -2
  14. package/dist/blog/server.d.ts +3 -2
  15. package/dist/blog/server.js +13 -6
  16. package/dist/blog/server.js.map +1 -1
  17. package/dist/blog/server.mjs +13 -6
  18. package/dist/blog/server.mjs.map +1 -1
  19. package/dist/{chunk-FKVJOT2F.mjs → chunk-42EXHJTC.mjs} +196 -7
  20. package/dist/chunk-42EXHJTC.mjs.map +1 -0
  21. package/dist/{scanner-AZV5I6US.mjs → chunk-44OMJFCG.mjs} +354 -14
  22. package/dist/chunk-44OMJFCG.mjs.map +1 -0
  23. package/dist/chunk-4TGJYNHV.js +981 -0
  24. package/dist/chunk-4TGJYNHV.js.map +1 -0
  25. package/dist/chunk-4XPGGLVP.mjs +53 -0
  26. package/dist/{chunk-NYKRE2FL.mjs.map → chunk-4XPGGLVP.mjs.map} +1 -1
  27. package/dist/{generators-TO2FKJR6.mjs → chunk-6ONUXZDO.mjs} +26 -9
  28. package/dist/chunk-6ONUXZDO.mjs.map +1 -0
  29. package/dist/chunk-CG53ASWX.mjs +729 -0
  30. package/dist/chunk-CG53ASWX.mjs.map +1 -0
  31. package/dist/{scanner-ETJAMIT7.js → chunk-DERI27QC.js} +448 -102
  32. package/dist/chunk-DERI27QC.js.map +1 -0
  33. package/dist/chunk-DYM5ML2V.mjs +1518 -0
  34. package/dist/chunk-DYM5ML2V.mjs.map +1 -0
  35. package/dist/chunk-FLZZOX44.js +1526 -0
  36. package/dist/chunk-FLZZOX44.js.map +1 -0
  37. package/dist/{chunk-7H6I3ECV.mjs → chunk-FQVGK746.mjs} +63 -3
  38. package/dist/chunk-FQVGK746.mjs.map +1 -0
  39. package/dist/{chunk-GQ6ZOU2N.mjs → chunk-JGQPAXTL.mjs} +4 -4
  40. package/dist/{chunk-GQ6ZOU2N.mjs.map → chunk-JGQPAXTL.mjs.map} +1 -1
  41. package/dist/{chunk-V3F5J6CV.js → chunk-JUEVN4Q4.js} +196 -7
  42. package/dist/chunk-JUEVN4Q4.js.map +1 -0
  43. package/dist/chunk-KKMGTT7F.mjs +968 -0
  44. package/dist/chunk-KKMGTT7F.mjs.map +1 -0
  45. package/dist/{chunk-XQJX252G.mjs → chunk-MB3WR5KJ.mjs} +28 -18
  46. package/dist/chunk-MB3WR5KJ.mjs.map +1 -0
  47. package/dist/{chunk-2IHTEKHU.mjs → chunk-QD5CN2OI.mjs} +16 -7
  48. package/dist/chunk-QD5CN2OI.mjs.map +1 -0
  49. package/dist/{chunk-SBVEYCSV.js → chunk-QQB4FO4Q.js} +7 -7
  50. package/dist/{chunk-SBVEYCSV.js.map → chunk-QQB4FO4Q.js.map} +1 -1
  51. package/dist/{generators-YZWIGHCO.js → chunk-S2GXR5HY.js} +26 -9
  52. package/dist/chunk-S2GXR5HY.js.map +1 -0
  53. package/dist/{chunk-O2OHHBUD.js → chunk-TDK7DLCH.js} +30 -20
  54. package/dist/chunk-TDK7DLCH.js.map +1 -0
  55. package/dist/{chunk-QP5NCO2E.js → chunk-VDI7KYME.js} +67 -2
  56. package/dist/chunk-VDI7KYME.js.map +1 -0
  57. package/dist/chunk-VOR53RUR.js +753 -0
  58. package/dist/chunk-VOR53RUR.js.map +1 -0
  59. package/dist/{chunk-GAJLEDRD.js → chunk-ZKJ7JKFV.js} +16 -7
  60. package/dist/chunk-ZKJ7JKFV.js.map +1 -0
  61. package/dist/chunk-ZSMWDLMK.js +63 -0
  62. package/dist/{chunk-EQCVQC35.js.map → chunk-ZSMWDLMK.js.map} +1 -1
  63. package/dist/cli/index.js +37269 -0
  64. package/dist/cli/index.js.map +1 -0
  65. package/dist/cli/index.mjs +37233 -0
  66. package/dist/cli/index.mjs.map +1 -0
  67. package/dist/commerce/index.js +1 -1
  68. package/dist/commerce/index.mjs +1 -1
  69. package/dist/commerce/server.d.mts +12 -3
  70. package/dist/commerce/server.d.ts +12 -3
  71. package/dist/commerce/server.js +71 -70
  72. package/dist/commerce/server.js.map +1 -1
  73. package/dist/commerce/server.mjs +71 -70
  74. package/dist/commerce/server.mjs.map +1 -1
  75. package/dist/engage/index.d.mts +6 -4
  76. package/dist/engage/index.d.ts +6 -4
  77. package/dist/engage/index.js +8 -4
  78. package/dist/engage/index.mjs +2 -2
  79. package/dist/forms/index.js +1 -1
  80. package/dist/forms/index.mjs +1 -1
  81. package/dist/generators-5EU4PTVF.js +33 -0
  82. package/dist/generators-5EU4PTVF.js.map +1 -0
  83. package/dist/generators-TYPILCWD.mjs +4 -0
  84. package/dist/generators-TYPILCWD.mjs.map +1 -0
  85. package/dist/images/index.js +11 -11
  86. package/dist/images/index.mjs +4 -4
  87. package/dist/index.d.mts +154 -5
  88. package/dist/index.d.ts +154 -5
  89. package/dist/index.js +940 -24
  90. package/dist/index.js.map +1 -1
  91. package/dist/index.mjs +819 -7
  92. package/dist/index.mjs.map +1 -1
  93. package/dist/llms/index.d.mts +657 -0
  94. package/dist/llms/index.d.ts +657 -0
  95. package/dist/llms/index.js +101 -0
  96. package/dist/llms/index.js.map +1 -0
  97. package/dist/llms/index.mjs +4 -0
  98. package/dist/llms/index.mjs.map +1 -0
  99. package/dist/migrator-ARLHUNB3.mjs +4 -0
  100. package/dist/migrator-ARLHUNB3.mjs.map +1 -0
  101. package/dist/migrator-VZLBH3VY.js +37 -0
  102. package/dist/migrator-VZLBH3VY.js.map +1 -0
  103. package/dist/redirects/index.js +1 -1
  104. package/dist/redirects/index.mjs +1 -1
  105. package/dist/reputation/index.js +1 -1
  106. package/dist/reputation/index.mjs +1 -1
  107. package/dist/{routing-BWjUF7lp.d.ts → routing-CF91y6NO.d.ts} +1 -1
  108. package/dist/{routing-CgmRi9tD.d.mts → routing-CIOFpFCB.d.mts} +1 -1
  109. package/dist/scanner-7ZMUM2P5.mjs +4 -0
  110. package/dist/scanner-7ZMUM2P5.mjs.map +1 -0
  111. package/dist/scanner-OY7UF3WA.js +53 -0
  112. package/dist/scanner-OY7UF3WA.js.map +1 -0
  113. package/dist/seo/index.d.mts +267 -7
  114. package/dist/seo/index.d.ts +267 -7
  115. package/dist/seo/index.js +432 -24
  116. package/dist/seo/index.js.map +1 -1
  117. package/dist/seo/index.mjs +400 -11
  118. package/dist/seo/index.mjs.map +1 -1
  119. package/dist/seo/server.d.mts +11 -4
  120. package/dist/seo/server.d.ts +11 -4
  121. package/dist/seo/server.js +17 -17
  122. package/dist/seo/server.mjs +3 -3
  123. package/dist/setup/client.js +1 -1
  124. package/dist/setup/client.mjs +1 -1
  125. package/dist/setup/index.js +3 -3
  126. package/dist/setup/index.mjs +2 -2
  127. package/dist/setup/server.js +3 -3
  128. package/dist/setup/server.mjs +2 -2
  129. package/dist/sitemap/index.js +2 -2
  130. package/dist/sitemap/index.js.map +1 -1
  131. package/dist/sitemap/index.mjs +2 -2
  132. package/dist/sitemap/index.mjs.map +1 -1
  133. package/dist/{types-C0pJGfbH.d.mts → types-D6FHAVWX.d.mts} +99 -3
  134. package/dist/{types-C0pJGfbH.d.ts → types-D6FHAVWX.d.ts} +99 -3
  135. package/dist/{types-BN4OwtCO.d.mts → types-DI0jnhjJ.d.mts} +2 -0
  136. package/dist/{types-BN4OwtCO.d.ts → types-DI0jnhjJ.d.ts} +2 -0
  137. package/dist/{types-BmzutFwy.d.ts → types-j8X4vUhB.d.mts} +19 -2
  138. package/dist/{types-BmzutFwy.d.mts → types-j8X4vUhB.d.ts} +19 -2
  139. package/dist/{web-vitals-BH55V7EJ.js → web-vitals-444RLW3B.js} +11 -11
  140. package/dist/{web-vitals-BH55V7EJ.js.map → web-vitals-444RLW3B.js.map} +1 -1
  141. package/dist/{web-vitals-RJYPWAR3.mjs → web-vitals-KPICZIEF.mjs} +3 -3
  142. package/dist/{web-vitals-RJYPWAR3.mjs.map → web-vitals-KPICZIEF.mjs.map} +1 -1
  143. package/package.json +9 -2
  144. package/dist/api-N35S3EES.js +0 -57
  145. package/dist/api-N35S3EES.js.map +0 -1
  146. package/dist/api-SYBTK7Z7.mjs +0 -4
  147. package/dist/api-SYBTK7Z7.mjs.map +0 -1
  148. package/dist/chunk-2IHTEKHU.mjs.map +0 -1
  149. package/dist/chunk-7H6I3ECV.mjs.map +0 -1
  150. package/dist/chunk-BGJLOJ7T.mjs +0 -605
  151. package/dist/chunk-BGJLOJ7T.mjs.map +0 -1
  152. package/dist/chunk-EQCVQC35.js +0 -35
  153. package/dist/chunk-FKVJOT2F.mjs.map +0 -1
  154. package/dist/chunk-GAJLEDRD.js.map +0 -1
  155. package/dist/chunk-NYKRE2FL.mjs +0 -31
  156. package/dist/chunk-O2OHHBUD.js.map +0 -1
  157. package/dist/chunk-QAYJV4KK.js +0 -608
  158. package/dist/chunk-QAYJV4KK.js.map +0 -1
  159. package/dist/chunk-QP5NCO2E.js.map +0 -1
  160. package/dist/chunk-V3F5J6CV.js.map +0 -1
  161. package/dist/chunk-XQJX252G.mjs.map +0 -1
  162. package/dist/generators-TO2FKJR6.mjs.map +0 -1
  163. package/dist/generators-YZWIGHCO.js.map +0 -1
  164. package/dist/migrator-V6KS75EA.mjs +0 -265
  165. package/dist/migrator-V6KS75EA.mjs.map +0 -1
  166. package/dist/migrator-XKM7YQCY.js +0 -272
  167. package/dist/migrator-XKM7YQCY.js.map +0 -1
  168. package/dist/scanner-AZV5I6US.mjs.map +0 -1
  169. package/dist/scanner-ETJAMIT7.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkK2HWVOEO_js = require('../chunk-K2HWVOEO.js');
4
- require('../chunk-EQCVQC35.js');
4
+ require('../chunk-ZSMWDLMK.js');
5
5
 
6
6
 
7
7
 
@@ -1,4 +1,4 @@
1
1
  export { CalendarView, CheckoutForm, EventCalendar, EventEmbed, EventModal, EventTile, EventsWidget, OfferingCard, OfferingList, ProductDetail, ProductEmbed, ProductGrid, ProductPage, RegistrationForm, UpcomingEvents, createCheckoutSession, fetchCategories, fetchLatestOffering, fetchNextEvent, fetchOffering, fetchOfferings, fetchProductBySlug, fetchProducts, fetchProductsPublic, fetchServices, fetchUpcomingEvents, formatDate, formatDateRange, formatDateTime, formatPrice, formatTime, getOfferingUrl, getRelativeTimeUntil, getSpotsRemaining, isEventSoldOut, registerForEvent, useEventModal } from '../chunk-DOHML47I.mjs';
2
- import '../chunk-NYKRE2FL.mjs';
2
+ import '../chunk-4XPGGLVP.mjs';
3
3
  //# sourceMappingURL=index.mjs.map
4
4
  //# sourceMappingURL=index.mjs.map
@@ -5,11 +5,13 @@ import { O as OfferingType, C as CommerceOffering } from '../types-nB206tPK.mjs'
5
5
  *
6
6
  * Helpers for server-side rendering and dynamic routes.
7
7
  * Use in Next.js getStaticPaths, getStaticProps, or App Router.
8
+ *
9
+ * All data fetching goes through the Portal API.
8
10
  */
9
11
 
10
12
  interface ServerConfig {
11
- supabaseUrl: string;
12
- supabaseKey: string;
13
+ apiUrl: string;
14
+ apiKey: string;
13
15
  projectId: string;
14
16
  }
15
17
  /**
@@ -93,6 +95,13 @@ declare function generateOfferingMetadata(offering: CommerceOffering | null, sit
93
95
  url: string;
94
96
  };
95
97
  } | null;
96
- declare function createServerConfig(supabaseUrl: string, supabaseKey: string, projectId: string): ServerConfig;
98
+ /**
99
+ * Create a server config for API calls
100
+ *
101
+ * @param apiUrl - Portal API URL (e.g., 'https://api.uptrademedia.com')
102
+ * @param apiKey - Project API key
103
+ * @param projectId - Project ID
104
+ */
105
+ declare function createServerConfig(apiUrl: string, apiKey: string, projectId: string): ServerConfig;
97
106
 
98
107
  export { createServerConfig, generateOfferingMetadata, getEventPaths, getNextEvent, getOfferingBySlug, getOfferingPaths, getOfferings, getProductPaths, getUpcomingEvents };
@@ -5,11 +5,13 @@ import { O as OfferingType, C as CommerceOffering } from '../types-nB206tPK.js';
5
5
  *
6
6
  * Helpers for server-side rendering and dynamic routes.
7
7
  * Use in Next.js getStaticPaths, getStaticProps, or App Router.
8
+ *
9
+ * All data fetching goes through the Portal API.
8
10
  */
9
11
 
10
12
  interface ServerConfig {
11
- supabaseUrl: string;
12
- supabaseKey: string;
13
+ apiUrl: string;
14
+ apiKey: string;
13
15
  projectId: string;
14
16
  }
15
17
  /**
@@ -93,6 +95,13 @@ declare function generateOfferingMetadata(offering: CommerceOffering | null, sit
93
95
  url: string;
94
96
  };
95
97
  } | null;
96
- declare function createServerConfig(supabaseUrl: string, supabaseKey: string, projectId: string): ServerConfig;
98
+ /**
99
+ * Create a server config for API calls
100
+ *
101
+ * @param apiUrl - Portal API URL (e.g., 'https://api.uptrademedia.com')
102
+ * @param apiKey - Project API key
103
+ * @param projectId - Project ID
104
+ */
105
+ declare function createServerConfig(apiUrl: string, apiKey: string, projectId: string): ServerConfig;
97
106
 
98
107
  export { createServerConfig, generateOfferingMetadata, getEventPaths, getNextEvent, getOfferingBySlug, getOfferingPaths, getOfferings, getProductPaths, getUpcomingEvents };
@@ -1,10 +1,23 @@
1
1
  'use strict';
2
2
 
3
- require('../chunk-EQCVQC35.js');
4
- var supabaseJs = require('@supabase/supabase-js');
3
+ require('../chunk-ZSMWDLMK.js');
5
4
 
6
- function getSupabaseClient(config) {
7
- return supabaseJs.createClient(config.supabaseUrl, config.supabaseKey);
5
+ // src/commerce/server.ts
6
+ async function apiFetch(config, endpoint) {
7
+ try {
8
+ const response = await fetch(`${config.apiUrl}${endpoint}`, {
9
+ headers: {
10
+ "X-API-Key": config.apiKey,
11
+ "X-Project-ID": config.projectId,
12
+ "Content-Type": "application/json"
13
+ }
14
+ });
15
+ if (!response.ok) return null;
16
+ return response.json();
17
+ } catch (error) {
18
+ console.error("API fetch error:", error);
19
+ return null;
20
+ }
8
21
  }
9
22
  function transformOffering(data) {
10
23
  return {
@@ -19,7 +32,7 @@ function transformOffering(data) {
19
32
  long_description: data.long_description,
20
33
  featured_image_url: data.featured_image_url,
21
34
  gallery_images: data.gallery_image_urls || [],
22
- price_type: data.price_type,
35
+ price_type: data.price_type || "fixed",
23
36
  price: data.price,
24
37
  compare_at_price: data.compare_at_price,
25
38
  currency: data.currency || "USD",
@@ -49,97 +62,85 @@ function transformOffering(data) {
49
62
  };
50
63
  }
51
64
  async function getProductPaths(config) {
52
- const supabase = getSupabaseClient(config);
53
- const { data, error } = await supabase.from("commerce_offerings").select("slug").eq("project_id", config.projectId).eq("type", "product").eq("status", "active");
54
- if (error || !data) return [];
55
- return data.map((item) => ({ params: { slug: item.slug } }));
65
+ const data = await apiFetch(
66
+ config,
67
+ `/public/commerce/offerings?type=product&status=active&fields=slug`
68
+ );
69
+ if (!data?.offerings) return [];
70
+ return data.offerings.map((item) => ({ params: { slug: item.slug } }));
56
71
  }
57
72
  async function getEventPaths(config) {
58
- const supabase = getSupabaseClient(config);
59
- const { data, error } = await supabase.from("commerce_offerings").select("slug").eq("project_id", config.projectId).eq("type", "event").eq("status", "active");
60
- if (error || !data) return [];
61
- return data.map((item) => ({ params: { slug: item.slug } }));
73
+ const data = await apiFetch(
74
+ config,
75
+ `/public/commerce/offerings?type=event&status=active&fields=slug`
76
+ );
77
+ if (!data?.offerings) return [];
78
+ return data.offerings.map((item) => ({ params: { slug: item.slug } }));
62
79
  }
63
80
  async function getOfferingPaths(config, type) {
64
- const supabase = getSupabaseClient(config);
65
- let query = supabase.from("commerce_offerings").select("slug").eq("project_id", config.projectId).eq("status", "active");
81
+ let typeParam = "";
66
82
  if (type) {
67
83
  if (Array.isArray(type)) {
68
- query = query.in("type", type);
84
+ typeParam = `&type=${type.join(",")}`;
69
85
  } else {
70
- query = query.eq("type", type);
86
+ typeParam = `&type=${type}`;
71
87
  }
72
88
  }
73
- const { data, error } = await query;
74
- if (error || !data) return [];
75
- return data.map((item) => ({ params: { slug: item.slug } }));
89
+ const data = await apiFetch(
90
+ config,
91
+ `/public/commerce/offerings?status=active&fields=slug${typeParam}`
92
+ );
93
+ if (!data?.offerings) return [];
94
+ return data.offerings.map((item) => ({ params: { slug: item.slug } }));
76
95
  }
77
96
  async function getOfferingBySlug(config, slug) {
78
- const supabase = getSupabaseClient(config);
79
- const { data, error } = await supabase.from("commerce_offerings").select(`
80
- *,
81
- category:commerce_categories(id, name, slug),
82
- variants:commerce_variants(*),
83
- schedules:commerce_schedules(*)
84
- `).eq("project_id", config.projectId).eq("slug", slug).single();
85
- if (error || !data) return null;
86
- return transformOffering(data);
97
+ const data = await apiFetch(
98
+ config,
99
+ `/public/commerce/offerings/${slug}`
100
+ );
101
+ if (!data?.offering) return null;
102
+ return transformOffering(data.offering);
87
103
  }
88
104
  async function getOfferings(config, options = {}) {
89
- const supabase = getSupabaseClient(config);
90
- let query = supabase.from("commerce_offerings").select(`
91
- *,
92
- category:commerce_categories(id, name, slug),
93
- variants:commerce_variants(*),
94
- schedules:commerce_schedules(*)
95
- `).eq("project_id", config.projectId).eq("status", options.status || "active").order("sort_order", { ascending: true });
105
+ const params = new URLSearchParams();
106
+ params.set("status", options.status || "active");
96
107
  if (options.type) {
97
108
  if (Array.isArray(options.type)) {
98
- query = query.in("type", options.type);
109
+ params.set("type", options.type.join(","));
99
110
  } else {
100
- query = query.eq("type", options.type);
111
+ params.set("type", options.type);
101
112
  }
102
113
  }
103
114
  if (options.category) {
104
- query = query.eq("category_id", options.category);
115
+ params.set("category", options.category);
105
116
  }
106
117
  if (options.limit) {
107
- query = query.limit(options.limit);
118
+ params.set("limit", options.limit.toString());
108
119
  }
109
- const { data, error } = await query;
110
- if (error || !data) return [];
111
- return data.map(transformOffering);
120
+ const data = await apiFetch(
121
+ config,
122
+ `/public/commerce/offerings?${params.toString()}`
123
+ );
124
+ if (!data?.offerings) return [];
125
+ return data.offerings.map(transformOffering);
112
126
  }
113
127
  async function getUpcomingEvents(config, options = {}) {
114
- const supabase = getSupabaseClient(config);
115
- const now = (/* @__PURE__ */ new Date()).toISOString();
116
- let query = supabase.from("commerce_offerings").select(`
117
- *,
118
- category:commerce_categories(id, name, slug),
119
- schedules:commerce_schedules(*)
120
- `).eq("project_id", config.projectId).eq("type", "event").eq("status", "active");
128
+ const params = new URLSearchParams();
129
+ params.set("type", "event");
130
+ params.set("status", "active");
131
+ params.set("upcoming", "true");
121
132
  if (options.category) {
122
- query = query.eq("category_id", options.category);
133
+ params.set("category", options.category);
123
134
  }
124
- const { data, error } = await query;
125
- if (error || !data) return [];
126
- const eventsWithSchedules = data.map((event) => {
127
- const schedules = (event.schedules || []).filter((s) => new Date(s.starts_at) >= new Date(now) && s.status === "scheduled").sort((a, b) => new Date(a.starts_at).getTime() - new Date(b.starts_at).getTime());
128
- return {
129
- ...transformOffering(event),
130
- schedules,
131
- next_schedule: schedules[0] || null
132
- };
133
- }).filter((event) => event.schedules.length > 0).sort((a, b) => {
134
- const aDate = a.next_schedule?.starts_at;
135
- const bDate = b.next_schedule?.starts_at;
136
- if (!aDate || !bDate) return 0;
137
- return new Date(aDate).getTime() - new Date(bDate).getTime();
138
- });
139
135
  if (options.limit) {
140
- return eventsWithSchedules.slice(0, options.limit);
136
+ params.set("limit", options.limit.toString());
141
137
  }
142
- return eventsWithSchedules;
138
+ const data = await apiFetch(
139
+ config,
140
+ `/public/commerce/offerings?${params.toString()}`
141
+ );
142
+ if (!data?.offerings) return [];
143
+ return data.offerings.map(transformOffering);
143
144
  }
144
145
  async function getNextEvent(config, category) {
145
146
  const events = await getUpcomingEvents(config, { limit: 1, category });
@@ -169,8 +170,8 @@ function generateOfferingMetadata(offering, siteUrl) {
169
170
  }
170
171
  };
171
172
  }
172
- function createServerConfig(supabaseUrl, supabaseKey, projectId) {
173
- return { supabaseUrl, supabaseKey, projectId };
173
+ function createServerConfig(apiUrl, apiKey, projectId) {
174
+ return { apiUrl, apiKey, projectId };
174
175
  }
175
176
 
176
177
  exports.createServerConfig = createServerConfig;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commerce/server.ts"],"names":["createClient"],"mappings":"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","file":"server.js","sourcesContent":["/**\n * @uptrade/site-kit/commerce - Server-side utilities\n * \n * Helpers for server-side rendering and dynamic routes.\n * Use in Next.js getStaticPaths, getStaticProps, or App Router.\n */\n\nimport { createClient } from '@supabase/supabase-js'\nimport type { CommerceOffering, OfferingType } from './types'\n\ninterface ServerConfig {\n supabaseUrl: string\n supabaseKey: string\n projectId: string\n}\n\nfunction getSupabaseClient(config: ServerConfig) {\n return createClient(config.supabaseUrl, config.supabaseKey)\n}\n\nfunction transformOffering(data: any): CommerceOffering {\n return {\n id: data.id,\n project_id: data.project_id,\n type: data.type,\n status: data.status,\n name: data.name,\n slug: data.slug,\n description: data.description,\n short_description: data.short_description,\n long_description: data.long_description,\n featured_image_url: data.featured_image_url,\n gallery_images: data.gallery_image_urls || [],\n price_type: data.price_type,\n price: data.price,\n compare_at_price: data.compare_at_price,\n currency: data.currency || 'USD',\n price_is_public: data.price_is_public ?? true,\n billing_period: data.billing_period,\n track_inventory: data.track_inventory,\n inventory_count: data.inventory_count,\n allow_backorder: data.allow_backorder,\n duration_minutes: data.duration_minutes,\n capacity: data.capacity,\n location: data.location,\n is_virtual: data.is_virtual,\n virtual_meeting_url: data.virtual_meeting_url,\n requires_booking: data.requires_booking,\n booking_lead_time_hours: data.booking_lead_time_hours,\n category: data.category,\n category_id: data.category_id,\n tags: data.tags || [],\n seo_title: data.seo_title,\n seo_description: data.seo_description,\n features: data.features || [],\n specifications: data.specifications || {},\n schedules: data.schedules || [],\n variants: data.variants || [],\n created_at: data.created_at,\n updated_at: data.updated_at,\n }\n}\n\n// ============================================\n// Static Path Generators\n// ============================================\n\n/**\n * Get all product slugs for static generation\n * \n * @example Next.js Pages Router\n * export async function getStaticPaths() {\n * const paths = await getProductPaths(config)\n * return { paths, fallback: 'blocking' }\n * }\n */\nexport async function getProductPaths(config: ServerConfig): Promise<{ params: { slug: string } }[]> {\n const supabase = getSupabaseClient(config)\n \n const { data, error } = await supabase\n .from('commerce_offerings')\n .select('slug')\n .eq('project_id', config.projectId)\n .eq('type', 'product')\n .eq('status', 'active')\n \n if (error || !data) return []\n \n return data.map(item => ({ params: { slug: item.slug } }))\n}\n\n/**\n * Get all event slugs for static generation\n */\nexport async function getEventPaths(config: ServerConfig): Promise<{ params: { slug: string } }[]> {\n const supabase = getSupabaseClient(config)\n \n const { data, error } = await supabase\n .from('commerce_offerings')\n .select('slug')\n .eq('project_id', config.projectId)\n .eq('type', 'event')\n .eq('status', 'active')\n \n if (error || !data) return []\n \n return data.map(item => ({ params: { slug: item.slug } }))\n}\n\n/**\n * Get all offering slugs for static generation (any type)\n */\nexport async function getOfferingPaths(\n config: ServerConfig,\n type?: OfferingType | OfferingType[]\n): Promise<{ params: { slug: string } }[]> {\n const supabase = getSupabaseClient(config)\n \n let query = supabase\n .from('commerce_offerings')\n .select('slug')\n .eq('project_id', config.projectId)\n .eq('status', 'active')\n \n if (type) {\n if (Array.isArray(type)) {\n query = query.in('type', type)\n } else {\n query = query.eq('type', type)\n }\n }\n \n const { data, error } = await query\n \n if (error || !data) return []\n \n return data.map(item => ({ params: { slug: item.slug } }))\n}\n\n// ============================================\n// Data Fetchers\n// ============================================\n\n/**\n * Fetch a single offering by slug (server-side)\n * \n * @example Next.js Pages Router\n * export async function getStaticProps({ params }) {\n * const product = await getOfferingBySlug(config, params.slug)\n * if (!product) return { notFound: true }\n * return { props: { product }, revalidate: 60 }\n * }\n */\nexport async function getOfferingBySlug(\n config: ServerConfig,\n slug: string\n): Promise<CommerceOffering | null> {\n const supabase = getSupabaseClient(config)\n \n const { data, error } = await supabase\n .from('commerce_offerings')\n .select(`\n *,\n category:commerce_categories(id, name, slug),\n variants:commerce_variants(*),\n schedules:commerce_schedules(*)\n `)\n .eq('project_id', config.projectId)\n .eq('slug', slug)\n .single()\n \n if (error || !data) return null\n \n return transformOffering(data)\n}\n\n/**\n * Fetch all offerings of a type (server-side)\n */\nexport async function getOfferings(\n config: ServerConfig,\n options: {\n type?: OfferingType | OfferingType[]\n category?: string\n limit?: number\n status?: string\n } = {}\n): Promise<CommerceOffering[]> {\n const supabase = getSupabaseClient(config)\n \n let query = supabase\n .from('commerce_offerings')\n .select(`\n *,\n category:commerce_categories(id, name, slug),\n variants:commerce_variants(*),\n schedules:commerce_schedules(*)\n `)\n .eq('project_id', config.projectId)\n .eq('status', options.status || 'active')\n .order('sort_order', { ascending: true })\n \n if (options.type) {\n if (Array.isArray(options.type)) {\n query = query.in('type', options.type)\n } else {\n query = query.eq('type', options.type)\n }\n }\n \n if (options.category) {\n query = query.eq('category_id', options.category)\n }\n \n if (options.limit) {\n query = query.limit(options.limit)\n }\n \n const { data, error } = await query\n \n if (error || !data) return []\n \n return data.map(transformOffering)\n}\n\n/**\n * Fetch upcoming events (server-side)\n */\nexport async function getUpcomingEvents(\n config: ServerConfig,\n options: { limit?: number; category?: string } = {}\n): Promise<CommerceOffering[]> {\n const supabase = getSupabaseClient(config)\n const now = new Date().toISOString()\n \n let query = supabase\n .from('commerce_offerings')\n .select(`\n *,\n category:commerce_categories(id, name, slug),\n schedules:commerce_schedules(*)\n `)\n .eq('project_id', config.projectId)\n .eq('type', 'event')\n .eq('status', 'active')\n \n if (options.category) {\n query = query.eq('category_id', options.category)\n }\n \n const { data, error } = await query\n \n if (error || !data) return []\n \n // Filter events with upcoming schedules and sort\n const eventsWithSchedules = data\n .map(event => {\n const schedules = (event.schedules || [])\n .filter((s: any) => new Date(s.starts_at) >= new Date(now) && s.status === 'scheduled')\n .sort((a: any, b: any) => new Date(a.starts_at).getTime() - new Date(b.starts_at).getTime())\n \n return {\n ...transformOffering(event),\n schedules,\n next_schedule: schedules[0] || null,\n }\n })\n .filter(event => event.schedules.length > 0)\n .sort((a, b) => {\n const aDate = (a as any).next_schedule?.starts_at\n const bDate = (b as any).next_schedule?.starts_at\n if (!aDate || !bDate) return 0\n return new Date(aDate).getTime() - new Date(bDate).getTime()\n })\n \n if (options.limit) {\n return eventsWithSchedules.slice(0, options.limit)\n }\n \n return eventsWithSchedules\n}\n\n/**\n * Get next upcoming event (server-side)\n */\nexport async function getNextEvent(\n config: ServerConfig,\n category?: string\n): Promise<CommerceOffering | null> {\n const events = await getUpcomingEvents(config, { limit: 1, category })\n return events[0] || null\n}\n\n// ============================================\n// Metadata Helpers\n// ============================================\n\n/**\n * Generate page metadata for an offering\n * \n * @example Next.js App Router\n * export async function generateMetadata({ params }) {\n * const product = await getOfferingBySlug(config, params.slug)\n * return generateOfferingMetadata(product, 'https://example.com')\n * }\n */\nexport function generateOfferingMetadata(\n offering: CommerceOffering | null,\n siteUrl: string\n): {\n title: string\n description: string\n openGraph: {\n title: string\n description: string\n images: string[]\n type: string\n url: string\n }\n} | null {\n if (!offering) return null\n \n const title = offering.seo_title || offering.name\n const description = offering.seo_description || offering.short_description || offering.description || ''\n const images = offering.featured_image_url ? [offering.featured_image_url] : []\n \n const typeMap: Record<OfferingType, string> = {\n product: 'product',\n service: 'website',\n event: 'website',\n class: 'website',\n subscription: 'product',\n }\n \n return {\n title,\n description,\n openGraph: {\n title,\n description,\n images,\n type: typeMap[offering.type] || 'website',\n url: `${siteUrl}/${offering.type}s/${offering.slug}`,\n },\n }\n}\n\n// ============================================\n// Export config builder\n// ============================================\n\nexport function createServerConfig(\n supabaseUrl: string,\n supabaseKey: string,\n projectId: string\n): ServerConfig {\n return { supabaseUrl, supabaseKey, projectId }\n}\n"]}
1
+ {"version":3,"sources":["../../src/commerce/server.ts"],"names":[],"mappings":"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","file":"server.js","sourcesContent":["/**\n * @uptrade/site-kit/commerce - Server-side utilities\n * \n * Helpers for server-side rendering and dynamic routes.\n * Use in Next.js getStaticPaths, getStaticProps, or App Router.\n * \n * All data fetching goes through the Portal API.\n */\n\nimport type { CommerceOffering, OfferingType } from './types'\n\ninterface ServerConfig {\n apiUrl: string\n apiKey: string\n projectId: string\n}\n\ninterface SlugItem {\n slug: string\n}\n\nasync function apiFetch<T>(config: ServerConfig, endpoint: string): Promise<T | null> {\n try {\n const response = await fetch(`${config.apiUrl}${endpoint}`, {\n headers: {\n 'X-API-Key': config.apiKey,\n 'X-Project-ID': config.projectId,\n 'Content-Type': 'application/json',\n },\n })\n \n if (!response.ok) return null\n return response.json()\n } catch (error) {\n console.error('API fetch error:', error)\n return null\n }\n}\n\nfunction transformOffering(data: Record<string, unknown>): CommerceOffering {\n return {\n id: data.id as string,\n project_id: data.project_id as string,\n type: data.type as OfferingType,\n status: data.status as 'draft' | 'active' | 'archived' | 'sold_out',\n name: data.name as string,\n slug: data.slug as string,\n description: data.description as string | undefined,\n short_description: data.short_description as string | undefined,\n long_description: data.long_description as string | undefined,\n featured_image_url: data.featured_image_url as string | undefined,\n gallery_images: (data.gallery_image_urls as string[]) || [],\n price_type: (data.price_type as 'fixed' | 'variable' | 'quote' | 'free') || 'fixed',\n price: data.price as number | undefined,\n compare_at_price: data.compare_at_price as number | undefined,\n currency: (data.currency as string) || 'USD',\n price_is_public: (data.price_is_public as boolean) ?? true,\n billing_period: data.billing_period as 'weekly' | 'monthly' | 'quarterly' | 'yearly' | undefined,\n track_inventory: data.track_inventory as boolean | undefined,\n inventory_count: data.inventory_count as number | undefined,\n allow_backorder: data.allow_backorder as boolean | undefined,\n duration_minutes: data.duration_minutes as number | undefined,\n capacity: data.capacity as number | undefined,\n location: data.location as string | undefined,\n is_virtual: data.is_virtual as boolean | undefined,\n virtual_meeting_url: data.virtual_meeting_url as string | undefined,\n requires_booking: data.requires_booking as boolean | undefined,\n booking_lead_time_hours: data.booking_lead_time_hours as number | undefined,\n category: data.category as CommerceOffering['category'],\n category_id: data.category_id as string | undefined,\n tags: (data.tags as string[]) || [],\n seo_title: data.seo_title as string | undefined,\n seo_description: data.seo_description as string | undefined,\n features: (data.features as string[]) || [],\n specifications: (data.specifications as Record<string, string>) || {},\n schedules: (data.schedules as CommerceOffering['schedules']) || [],\n variants: (data.variants as CommerceOffering['variants']) || [],\n created_at: data.created_at as string,\n updated_at: data.updated_at as string,\n }\n}\n\n// ============================================\n// Static Path Generators\n// ============================================\n\n/**\n * Get all product slugs for static generation\n * \n * @example Next.js Pages Router\n * export async function getStaticPaths() {\n * const paths = await getProductPaths(config)\n * return { paths, fallback: 'blocking' }\n * }\n */\nexport async function getProductPaths(config: ServerConfig): Promise<{ params: { slug: string } }[]> {\n const data = await apiFetch<{ offerings: SlugItem[] }>(\n config,\n `/public/commerce/offerings?type=product&status=active&fields=slug`\n )\n \n if (!data?.offerings) return []\n \n return data.offerings.map((item: SlugItem) => ({ params: { slug: item.slug } }))\n}\n\n/**\n * Get all event slugs for static generation\n */\nexport async function getEventPaths(config: ServerConfig): Promise<{ params: { slug: string } }[]> {\n const data = await apiFetch<{ offerings: SlugItem[] }>(\n config,\n `/public/commerce/offerings?type=event&status=active&fields=slug`\n )\n \n if (!data?.offerings) return []\n \n return data.offerings.map((item: SlugItem) => ({ params: { slug: item.slug } }))\n}\n\n/**\n * Get all offering slugs for static generation (any type)\n */\nexport async function getOfferingPaths(\n config: ServerConfig,\n type?: OfferingType | OfferingType[]\n): Promise<{ params: { slug: string } }[]> {\n let typeParam = ''\n if (type) {\n if (Array.isArray(type)) {\n typeParam = `&type=${type.join(',')}`\n } else {\n typeParam = `&type=${type}`\n }\n }\n \n const data = await apiFetch<{ offerings: SlugItem[] }>(\n config,\n `/public/commerce/offerings?status=active&fields=slug${typeParam}`\n )\n \n if (!data?.offerings) return []\n \n return data.offerings.map((item: SlugItem) => ({ params: { slug: item.slug } }))\n}\n\n// ============================================\n// Data Fetchers\n// ============================================\n\n/**\n * Fetch a single offering by slug (server-side)\n * \n * @example Next.js Pages Router\n * export async function getStaticProps({ params }) {\n * const product = await getOfferingBySlug(config, params.slug)\n * if (!product) return { notFound: true }\n * return { props: { product }, revalidate: 60 }\n * }\n */\nexport async function getOfferingBySlug(\n config: ServerConfig,\n slug: string\n): Promise<CommerceOffering | null> {\n const data = await apiFetch<{ offering: Record<string, unknown> }>(\n config,\n `/public/commerce/offerings/${slug}`\n )\n \n if (!data?.offering) return null\n \n return transformOffering(data.offering)\n}\n\n/**\n * Fetch all offerings of a type (server-side)\n */\nexport async function getOfferings(\n config: ServerConfig,\n options: {\n type?: OfferingType | OfferingType[]\n category?: string\n limit?: number\n status?: string\n } = {}\n): Promise<CommerceOffering[]> {\n const params = new URLSearchParams()\n params.set('status', options.status || 'active')\n \n if (options.type) {\n if (Array.isArray(options.type)) {\n params.set('type', options.type.join(','))\n } else {\n params.set('type', options.type)\n }\n }\n \n if (options.category) {\n params.set('category', options.category)\n }\n \n if (options.limit) {\n params.set('limit', options.limit.toString())\n }\n \n const data = await apiFetch<{ offerings: Record<string, unknown>[] }>(\n config,\n `/public/commerce/offerings?${params.toString()}`\n )\n \n if (!data?.offerings) return []\n \n return data.offerings.map(transformOffering)\n}\n\n/**\n * Fetch upcoming events (server-side)\n */\nexport async function getUpcomingEvents(\n config: ServerConfig,\n options: { limit?: number; category?: string } = {}\n): Promise<CommerceOffering[]> {\n const params = new URLSearchParams()\n params.set('type', 'event')\n params.set('status', 'active')\n params.set('upcoming', 'true')\n \n if (options.category) {\n params.set('category', options.category)\n }\n \n if (options.limit) {\n params.set('limit', options.limit.toString())\n }\n \n const data = await apiFetch<{ offerings: Record<string, unknown>[] }>(\n config,\n `/public/commerce/offerings?${params.toString()}`\n )\n \n if (!data?.offerings) return []\n \n return data.offerings.map(transformOffering)\n}\n\n/**\n * Get next upcoming event (server-side)\n */\nexport async function getNextEvent(\n config: ServerConfig,\n category?: string\n): Promise<CommerceOffering | null> {\n const events = await getUpcomingEvents(config, { limit: 1, category })\n return events[0] || null\n}\n\n// ============================================\n// Metadata Helpers\n// ============================================\n\n/**\n * Generate page metadata for an offering\n * \n * @example Next.js App Router\n * export async function generateMetadata({ params }) {\n * const product = await getOfferingBySlug(config, params.slug)\n * return generateOfferingMetadata(product, 'https://example.com')\n * }\n */\nexport function generateOfferingMetadata(\n offering: CommerceOffering | null,\n siteUrl: string\n): {\n title: string\n description: string\n openGraph: {\n title: string\n description: string\n images: string[]\n type: string\n url: string\n }\n} | null {\n if (!offering) return null\n \n const title = offering.seo_title || offering.name\n const description = offering.seo_description || offering.short_description || offering.description || ''\n const images = offering.featured_image_url ? [offering.featured_image_url] : []\n \n const typeMap: Record<OfferingType, string> = {\n product: 'product',\n service: 'website',\n event: 'website',\n class: 'website',\n subscription: 'product',\n }\n \n return {\n title,\n description,\n openGraph: {\n title,\n description,\n images,\n type: typeMap[offering.type] || 'website',\n url: `${siteUrl}/${offering.type}s/${offering.slug}`,\n },\n }\n}\n\n// ============================================\n// Export config builder\n// ============================================\n\n/**\n * Create a server config for API calls\n * \n * @param apiUrl - Portal API URL (e.g., 'https://api.uptrademedia.com')\n * @param apiKey - Project API key\n * @param projectId - Project ID\n */\nexport function createServerConfig(\n apiUrl: string,\n apiKey: string,\n projectId: string\n): ServerConfig {\n return { apiUrl, apiKey, projectId }\n}\n"]}
@@ -1,8 +1,21 @@
1
- import '../chunk-NYKRE2FL.mjs';
2
- import { createClient } from '@supabase/supabase-js';
1
+ import '../chunk-4XPGGLVP.mjs';
3
2
 
4
- function getSupabaseClient(config) {
5
- return createClient(config.supabaseUrl, config.supabaseKey);
3
+ // src/commerce/server.ts
4
+ async function apiFetch(config, endpoint) {
5
+ try {
6
+ const response = await fetch(`${config.apiUrl}${endpoint}`, {
7
+ headers: {
8
+ "X-API-Key": config.apiKey,
9
+ "X-Project-ID": config.projectId,
10
+ "Content-Type": "application/json"
11
+ }
12
+ });
13
+ if (!response.ok) return null;
14
+ return response.json();
15
+ } catch (error) {
16
+ console.error("API fetch error:", error);
17
+ return null;
18
+ }
6
19
  }
7
20
  function transformOffering(data) {
8
21
  return {
@@ -17,7 +30,7 @@ function transformOffering(data) {
17
30
  long_description: data.long_description,
18
31
  featured_image_url: data.featured_image_url,
19
32
  gallery_images: data.gallery_image_urls || [],
20
- price_type: data.price_type,
33
+ price_type: data.price_type || "fixed",
21
34
  price: data.price,
22
35
  compare_at_price: data.compare_at_price,
23
36
  currency: data.currency || "USD",
@@ -47,97 +60,85 @@ function transformOffering(data) {
47
60
  };
48
61
  }
49
62
  async function getProductPaths(config) {
50
- const supabase = getSupabaseClient(config);
51
- const { data, error } = await supabase.from("commerce_offerings").select("slug").eq("project_id", config.projectId).eq("type", "product").eq("status", "active");
52
- if (error || !data) return [];
53
- return data.map((item) => ({ params: { slug: item.slug } }));
63
+ const data = await apiFetch(
64
+ config,
65
+ `/public/commerce/offerings?type=product&status=active&fields=slug`
66
+ );
67
+ if (!data?.offerings) return [];
68
+ return data.offerings.map((item) => ({ params: { slug: item.slug } }));
54
69
  }
55
70
  async function getEventPaths(config) {
56
- const supabase = getSupabaseClient(config);
57
- const { data, error } = await supabase.from("commerce_offerings").select("slug").eq("project_id", config.projectId).eq("type", "event").eq("status", "active");
58
- if (error || !data) return [];
59
- return data.map((item) => ({ params: { slug: item.slug } }));
71
+ const data = await apiFetch(
72
+ config,
73
+ `/public/commerce/offerings?type=event&status=active&fields=slug`
74
+ );
75
+ if (!data?.offerings) return [];
76
+ return data.offerings.map((item) => ({ params: { slug: item.slug } }));
60
77
  }
61
78
  async function getOfferingPaths(config, type) {
62
- const supabase = getSupabaseClient(config);
63
- let query = supabase.from("commerce_offerings").select("slug").eq("project_id", config.projectId).eq("status", "active");
79
+ let typeParam = "";
64
80
  if (type) {
65
81
  if (Array.isArray(type)) {
66
- query = query.in("type", type);
82
+ typeParam = `&type=${type.join(",")}`;
67
83
  } else {
68
- query = query.eq("type", type);
84
+ typeParam = `&type=${type}`;
69
85
  }
70
86
  }
71
- const { data, error } = await query;
72
- if (error || !data) return [];
73
- return data.map((item) => ({ params: { slug: item.slug } }));
87
+ const data = await apiFetch(
88
+ config,
89
+ `/public/commerce/offerings?status=active&fields=slug${typeParam}`
90
+ );
91
+ if (!data?.offerings) return [];
92
+ return data.offerings.map((item) => ({ params: { slug: item.slug } }));
74
93
  }
75
94
  async function getOfferingBySlug(config, slug) {
76
- const supabase = getSupabaseClient(config);
77
- const { data, error } = await supabase.from("commerce_offerings").select(`
78
- *,
79
- category:commerce_categories(id, name, slug),
80
- variants:commerce_variants(*),
81
- schedules:commerce_schedules(*)
82
- `).eq("project_id", config.projectId).eq("slug", slug).single();
83
- if (error || !data) return null;
84
- return transformOffering(data);
95
+ const data = await apiFetch(
96
+ config,
97
+ `/public/commerce/offerings/${slug}`
98
+ );
99
+ if (!data?.offering) return null;
100
+ return transformOffering(data.offering);
85
101
  }
86
102
  async function getOfferings(config, options = {}) {
87
- const supabase = getSupabaseClient(config);
88
- let query = supabase.from("commerce_offerings").select(`
89
- *,
90
- category:commerce_categories(id, name, slug),
91
- variants:commerce_variants(*),
92
- schedules:commerce_schedules(*)
93
- `).eq("project_id", config.projectId).eq("status", options.status || "active").order("sort_order", { ascending: true });
103
+ const params = new URLSearchParams();
104
+ params.set("status", options.status || "active");
94
105
  if (options.type) {
95
106
  if (Array.isArray(options.type)) {
96
- query = query.in("type", options.type);
107
+ params.set("type", options.type.join(","));
97
108
  } else {
98
- query = query.eq("type", options.type);
109
+ params.set("type", options.type);
99
110
  }
100
111
  }
101
112
  if (options.category) {
102
- query = query.eq("category_id", options.category);
113
+ params.set("category", options.category);
103
114
  }
104
115
  if (options.limit) {
105
- query = query.limit(options.limit);
116
+ params.set("limit", options.limit.toString());
106
117
  }
107
- const { data, error } = await query;
108
- if (error || !data) return [];
109
- return data.map(transformOffering);
118
+ const data = await apiFetch(
119
+ config,
120
+ `/public/commerce/offerings?${params.toString()}`
121
+ );
122
+ if (!data?.offerings) return [];
123
+ return data.offerings.map(transformOffering);
110
124
  }
111
125
  async function getUpcomingEvents(config, options = {}) {
112
- const supabase = getSupabaseClient(config);
113
- const now = (/* @__PURE__ */ new Date()).toISOString();
114
- let query = supabase.from("commerce_offerings").select(`
115
- *,
116
- category:commerce_categories(id, name, slug),
117
- schedules:commerce_schedules(*)
118
- `).eq("project_id", config.projectId).eq("type", "event").eq("status", "active");
126
+ const params = new URLSearchParams();
127
+ params.set("type", "event");
128
+ params.set("status", "active");
129
+ params.set("upcoming", "true");
119
130
  if (options.category) {
120
- query = query.eq("category_id", options.category);
131
+ params.set("category", options.category);
121
132
  }
122
- const { data, error } = await query;
123
- if (error || !data) return [];
124
- const eventsWithSchedules = data.map((event) => {
125
- const schedules = (event.schedules || []).filter((s) => new Date(s.starts_at) >= new Date(now) && s.status === "scheduled").sort((a, b) => new Date(a.starts_at).getTime() - new Date(b.starts_at).getTime());
126
- return {
127
- ...transformOffering(event),
128
- schedules,
129
- next_schedule: schedules[0] || null
130
- };
131
- }).filter((event) => event.schedules.length > 0).sort((a, b) => {
132
- const aDate = a.next_schedule?.starts_at;
133
- const bDate = b.next_schedule?.starts_at;
134
- if (!aDate || !bDate) return 0;
135
- return new Date(aDate).getTime() - new Date(bDate).getTime();
136
- });
137
133
  if (options.limit) {
138
- return eventsWithSchedules.slice(0, options.limit);
134
+ params.set("limit", options.limit.toString());
139
135
  }
140
- return eventsWithSchedules;
136
+ const data = await apiFetch(
137
+ config,
138
+ `/public/commerce/offerings?${params.toString()}`
139
+ );
140
+ if (!data?.offerings) return [];
141
+ return data.offerings.map(transformOffering);
141
142
  }
142
143
  async function getNextEvent(config, category) {
143
144
  const events = await getUpcomingEvents(config, { limit: 1, category });
@@ -167,8 +168,8 @@ function generateOfferingMetadata(offering, siteUrl) {
167
168
  }
168
169
  };
169
170
  }
170
- function createServerConfig(supabaseUrl, supabaseKey, projectId) {
171
- return { supabaseUrl, supabaseKey, projectId };
171
+ function createServerConfig(apiUrl, apiKey, projectId) {
172
+ return { apiUrl, apiKey, projectId };
172
173
  }
173
174
 
174
175
  export { createServerConfig, generateOfferingMetadata, getEventPaths, getNextEvent, getOfferingBySlug, getOfferingPaths, getOfferings, getProductPaths, getUpcomingEvents };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commerce/server.ts"],"names":[],"mappings":"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","file":"server.mjs","sourcesContent":["/**\n * @uptrade/site-kit/commerce - Server-side utilities\n * \n * Helpers for server-side rendering and dynamic routes.\n * Use in Next.js getStaticPaths, getStaticProps, or App Router.\n */\n\nimport { createClient } from '@supabase/supabase-js'\nimport type { CommerceOffering, OfferingType } from './types'\n\ninterface ServerConfig {\n supabaseUrl: string\n supabaseKey: string\n projectId: string\n}\n\nfunction getSupabaseClient(config: ServerConfig) {\n return createClient(config.supabaseUrl, config.supabaseKey)\n}\n\nfunction transformOffering(data: any): CommerceOffering {\n return {\n id: data.id,\n project_id: data.project_id,\n type: data.type,\n status: data.status,\n name: data.name,\n slug: data.slug,\n description: data.description,\n short_description: data.short_description,\n long_description: data.long_description,\n featured_image_url: data.featured_image_url,\n gallery_images: data.gallery_image_urls || [],\n price_type: data.price_type,\n price: data.price,\n compare_at_price: data.compare_at_price,\n currency: data.currency || 'USD',\n price_is_public: data.price_is_public ?? true,\n billing_period: data.billing_period,\n track_inventory: data.track_inventory,\n inventory_count: data.inventory_count,\n allow_backorder: data.allow_backorder,\n duration_minutes: data.duration_minutes,\n capacity: data.capacity,\n location: data.location,\n is_virtual: data.is_virtual,\n virtual_meeting_url: data.virtual_meeting_url,\n requires_booking: data.requires_booking,\n booking_lead_time_hours: data.booking_lead_time_hours,\n category: data.category,\n category_id: data.category_id,\n tags: data.tags || [],\n seo_title: data.seo_title,\n seo_description: data.seo_description,\n features: data.features || [],\n specifications: data.specifications || {},\n schedules: data.schedules || [],\n variants: data.variants || [],\n created_at: data.created_at,\n updated_at: data.updated_at,\n }\n}\n\n// ============================================\n// Static Path Generators\n// ============================================\n\n/**\n * Get all product slugs for static generation\n * \n * @example Next.js Pages Router\n * export async function getStaticPaths() {\n * const paths = await getProductPaths(config)\n * return { paths, fallback: 'blocking' }\n * }\n */\nexport async function getProductPaths(config: ServerConfig): Promise<{ params: { slug: string } }[]> {\n const supabase = getSupabaseClient(config)\n \n const { data, error } = await supabase\n .from('commerce_offerings')\n .select('slug')\n .eq('project_id', config.projectId)\n .eq('type', 'product')\n .eq('status', 'active')\n \n if (error || !data) return []\n \n return data.map(item => ({ params: { slug: item.slug } }))\n}\n\n/**\n * Get all event slugs for static generation\n */\nexport async function getEventPaths(config: ServerConfig): Promise<{ params: { slug: string } }[]> {\n const supabase = getSupabaseClient(config)\n \n const { data, error } = await supabase\n .from('commerce_offerings')\n .select('slug')\n .eq('project_id', config.projectId)\n .eq('type', 'event')\n .eq('status', 'active')\n \n if (error || !data) return []\n \n return data.map(item => ({ params: { slug: item.slug } }))\n}\n\n/**\n * Get all offering slugs for static generation (any type)\n */\nexport async function getOfferingPaths(\n config: ServerConfig,\n type?: OfferingType | OfferingType[]\n): Promise<{ params: { slug: string } }[]> {\n const supabase = getSupabaseClient(config)\n \n let query = supabase\n .from('commerce_offerings')\n .select('slug')\n .eq('project_id', config.projectId)\n .eq('status', 'active')\n \n if (type) {\n if (Array.isArray(type)) {\n query = query.in('type', type)\n } else {\n query = query.eq('type', type)\n }\n }\n \n const { data, error } = await query\n \n if (error || !data) return []\n \n return data.map(item => ({ params: { slug: item.slug } }))\n}\n\n// ============================================\n// Data Fetchers\n// ============================================\n\n/**\n * Fetch a single offering by slug (server-side)\n * \n * @example Next.js Pages Router\n * export async function getStaticProps({ params }) {\n * const product = await getOfferingBySlug(config, params.slug)\n * if (!product) return { notFound: true }\n * return { props: { product }, revalidate: 60 }\n * }\n */\nexport async function getOfferingBySlug(\n config: ServerConfig,\n slug: string\n): Promise<CommerceOffering | null> {\n const supabase = getSupabaseClient(config)\n \n const { data, error } = await supabase\n .from('commerce_offerings')\n .select(`\n *,\n category:commerce_categories(id, name, slug),\n variants:commerce_variants(*),\n schedules:commerce_schedules(*)\n `)\n .eq('project_id', config.projectId)\n .eq('slug', slug)\n .single()\n \n if (error || !data) return null\n \n return transformOffering(data)\n}\n\n/**\n * Fetch all offerings of a type (server-side)\n */\nexport async function getOfferings(\n config: ServerConfig,\n options: {\n type?: OfferingType | OfferingType[]\n category?: string\n limit?: number\n status?: string\n } = {}\n): Promise<CommerceOffering[]> {\n const supabase = getSupabaseClient(config)\n \n let query = supabase\n .from('commerce_offerings')\n .select(`\n *,\n category:commerce_categories(id, name, slug),\n variants:commerce_variants(*),\n schedules:commerce_schedules(*)\n `)\n .eq('project_id', config.projectId)\n .eq('status', options.status || 'active')\n .order('sort_order', { ascending: true })\n \n if (options.type) {\n if (Array.isArray(options.type)) {\n query = query.in('type', options.type)\n } else {\n query = query.eq('type', options.type)\n }\n }\n \n if (options.category) {\n query = query.eq('category_id', options.category)\n }\n \n if (options.limit) {\n query = query.limit(options.limit)\n }\n \n const { data, error } = await query\n \n if (error || !data) return []\n \n return data.map(transformOffering)\n}\n\n/**\n * Fetch upcoming events (server-side)\n */\nexport async function getUpcomingEvents(\n config: ServerConfig,\n options: { limit?: number; category?: string } = {}\n): Promise<CommerceOffering[]> {\n const supabase = getSupabaseClient(config)\n const now = new Date().toISOString()\n \n let query = supabase\n .from('commerce_offerings')\n .select(`\n *,\n category:commerce_categories(id, name, slug),\n schedules:commerce_schedules(*)\n `)\n .eq('project_id', config.projectId)\n .eq('type', 'event')\n .eq('status', 'active')\n \n if (options.category) {\n query = query.eq('category_id', options.category)\n }\n \n const { data, error } = await query\n \n if (error || !data) return []\n \n // Filter events with upcoming schedules and sort\n const eventsWithSchedules = data\n .map(event => {\n const schedules = (event.schedules || [])\n .filter((s: any) => new Date(s.starts_at) >= new Date(now) && s.status === 'scheduled')\n .sort((a: any, b: any) => new Date(a.starts_at).getTime() - new Date(b.starts_at).getTime())\n \n return {\n ...transformOffering(event),\n schedules,\n next_schedule: schedules[0] || null,\n }\n })\n .filter(event => event.schedules.length > 0)\n .sort((a, b) => {\n const aDate = (a as any).next_schedule?.starts_at\n const bDate = (b as any).next_schedule?.starts_at\n if (!aDate || !bDate) return 0\n return new Date(aDate).getTime() - new Date(bDate).getTime()\n })\n \n if (options.limit) {\n return eventsWithSchedules.slice(0, options.limit)\n }\n \n return eventsWithSchedules\n}\n\n/**\n * Get next upcoming event (server-side)\n */\nexport async function getNextEvent(\n config: ServerConfig,\n category?: string\n): Promise<CommerceOffering | null> {\n const events = await getUpcomingEvents(config, { limit: 1, category })\n return events[0] || null\n}\n\n// ============================================\n// Metadata Helpers\n// ============================================\n\n/**\n * Generate page metadata for an offering\n * \n * @example Next.js App Router\n * export async function generateMetadata({ params }) {\n * const product = await getOfferingBySlug(config, params.slug)\n * return generateOfferingMetadata(product, 'https://example.com')\n * }\n */\nexport function generateOfferingMetadata(\n offering: CommerceOffering | null,\n siteUrl: string\n): {\n title: string\n description: string\n openGraph: {\n title: string\n description: string\n images: string[]\n type: string\n url: string\n }\n} | null {\n if (!offering) return null\n \n const title = offering.seo_title || offering.name\n const description = offering.seo_description || offering.short_description || offering.description || ''\n const images = offering.featured_image_url ? [offering.featured_image_url] : []\n \n const typeMap: Record<OfferingType, string> = {\n product: 'product',\n service: 'website',\n event: 'website',\n class: 'website',\n subscription: 'product',\n }\n \n return {\n title,\n description,\n openGraph: {\n title,\n description,\n images,\n type: typeMap[offering.type] || 'website',\n url: `${siteUrl}/${offering.type}s/${offering.slug}`,\n },\n }\n}\n\n// ============================================\n// Export config builder\n// ============================================\n\nexport function createServerConfig(\n supabaseUrl: string,\n supabaseKey: string,\n projectId: string\n): ServerConfig {\n return { supabaseUrl, supabaseKey, projectId }\n}\n"]}
1
+ {"version":3,"sources":["../../src/commerce/server.ts"],"names":[],"mappings":"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","file":"server.mjs","sourcesContent":["/**\n * @uptrade/site-kit/commerce - Server-side utilities\n * \n * Helpers for server-side rendering and dynamic routes.\n * Use in Next.js getStaticPaths, getStaticProps, or App Router.\n * \n * All data fetching goes through the Portal API.\n */\n\nimport type { CommerceOffering, OfferingType } from './types'\n\ninterface ServerConfig {\n apiUrl: string\n apiKey: string\n projectId: string\n}\n\ninterface SlugItem {\n slug: string\n}\n\nasync function apiFetch<T>(config: ServerConfig, endpoint: string): Promise<T | null> {\n try {\n const response = await fetch(`${config.apiUrl}${endpoint}`, {\n headers: {\n 'X-API-Key': config.apiKey,\n 'X-Project-ID': config.projectId,\n 'Content-Type': 'application/json',\n },\n })\n \n if (!response.ok) return null\n return response.json()\n } catch (error) {\n console.error('API fetch error:', error)\n return null\n }\n}\n\nfunction transformOffering(data: Record<string, unknown>): CommerceOffering {\n return {\n id: data.id as string,\n project_id: data.project_id as string,\n type: data.type as OfferingType,\n status: data.status as 'draft' | 'active' | 'archived' | 'sold_out',\n name: data.name as string,\n slug: data.slug as string,\n description: data.description as string | undefined,\n short_description: data.short_description as string | undefined,\n long_description: data.long_description as string | undefined,\n featured_image_url: data.featured_image_url as string | undefined,\n gallery_images: (data.gallery_image_urls as string[]) || [],\n price_type: (data.price_type as 'fixed' | 'variable' | 'quote' | 'free') || 'fixed',\n price: data.price as number | undefined,\n compare_at_price: data.compare_at_price as number | undefined,\n currency: (data.currency as string) || 'USD',\n price_is_public: (data.price_is_public as boolean) ?? true,\n billing_period: data.billing_period as 'weekly' | 'monthly' | 'quarterly' | 'yearly' | undefined,\n track_inventory: data.track_inventory as boolean | undefined,\n inventory_count: data.inventory_count as number | undefined,\n allow_backorder: data.allow_backorder as boolean | undefined,\n duration_minutes: data.duration_minutes as number | undefined,\n capacity: data.capacity as number | undefined,\n location: data.location as string | undefined,\n is_virtual: data.is_virtual as boolean | undefined,\n virtual_meeting_url: data.virtual_meeting_url as string | undefined,\n requires_booking: data.requires_booking as boolean | undefined,\n booking_lead_time_hours: data.booking_lead_time_hours as number | undefined,\n category: data.category as CommerceOffering['category'],\n category_id: data.category_id as string | undefined,\n tags: (data.tags as string[]) || [],\n seo_title: data.seo_title as string | undefined,\n seo_description: data.seo_description as string | undefined,\n features: (data.features as string[]) || [],\n specifications: (data.specifications as Record<string, string>) || {},\n schedules: (data.schedules as CommerceOffering['schedules']) || [],\n variants: (data.variants as CommerceOffering['variants']) || [],\n created_at: data.created_at as string,\n updated_at: data.updated_at as string,\n }\n}\n\n// ============================================\n// Static Path Generators\n// ============================================\n\n/**\n * Get all product slugs for static generation\n * \n * @example Next.js Pages Router\n * export async function getStaticPaths() {\n * const paths = await getProductPaths(config)\n * return { paths, fallback: 'blocking' }\n * }\n */\nexport async function getProductPaths(config: ServerConfig): Promise<{ params: { slug: string } }[]> {\n const data = await apiFetch<{ offerings: SlugItem[] }>(\n config,\n `/public/commerce/offerings?type=product&status=active&fields=slug`\n )\n \n if (!data?.offerings) return []\n \n return data.offerings.map((item: SlugItem) => ({ params: { slug: item.slug } }))\n}\n\n/**\n * Get all event slugs for static generation\n */\nexport async function getEventPaths(config: ServerConfig): Promise<{ params: { slug: string } }[]> {\n const data = await apiFetch<{ offerings: SlugItem[] }>(\n config,\n `/public/commerce/offerings?type=event&status=active&fields=slug`\n )\n \n if (!data?.offerings) return []\n \n return data.offerings.map((item: SlugItem) => ({ params: { slug: item.slug } }))\n}\n\n/**\n * Get all offering slugs for static generation (any type)\n */\nexport async function getOfferingPaths(\n config: ServerConfig,\n type?: OfferingType | OfferingType[]\n): Promise<{ params: { slug: string } }[]> {\n let typeParam = ''\n if (type) {\n if (Array.isArray(type)) {\n typeParam = `&type=${type.join(',')}`\n } else {\n typeParam = `&type=${type}`\n }\n }\n \n const data = await apiFetch<{ offerings: SlugItem[] }>(\n config,\n `/public/commerce/offerings?status=active&fields=slug${typeParam}`\n )\n \n if (!data?.offerings) return []\n \n return data.offerings.map((item: SlugItem) => ({ params: { slug: item.slug } }))\n}\n\n// ============================================\n// Data Fetchers\n// ============================================\n\n/**\n * Fetch a single offering by slug (server-side)\n * \n * @example Next.js Pages Router\n * export async function getStaticProps({ params }) {\n * const product = await getOfferingBySlug(config, params.slug)\n * if (!product) return { notFound: true }\n * return { props: { product }, revalidate: 60 }\n * }\n */\nexport async function getOfferingBySlug(\n config: ServerConfig,\n slug: string\n): Promise<CommerceOffering | null> {\n const data = await apiFetch<{ offering: Record<string, unknown> }>(\n config,\n `/public/commerce/offerings/${slug}`\n )\n \n if (!data?.offering) return null\n \n return transformOffering(data.offering)\n}\n\n/**\n * Fetch all offerings of a type (server-side)\n */\nexport async function getOfferings(\n config: ServerConfig,\n options: {\n type?: OfferingType | OfferingType[]\n category?: string\n limit?: number\n status?: string\n } = {}\n): Promise<CommerceOffering[]> {\n const params = new URLSearchParams()\n params.set('status', options.status || 'active')\n \n if (options.type) {\n if (Array.isArray(options.type)) {\n params.set('type', options.type.join(','))\n } else {\n params.set('type', options.type)\n }\n }\n \n if (options.category) {\n params.set('category', options.category)\n }\n \n if (options.limit) {\n params.set('limit', options.limit.toString())\n }\n \n const data = await apiFetch<{ offerings: Record<string, unknown>[] }>(\n config,\n `/public/commerce/offerings?${params.toString()}`\n )\n \n if (!data?.offerings) return []\n \n return data.offerings.map(transformOffering)\n}\n\n/**\n * Fetch upcoming events (server-side)\n */\nexport async function getUpcomingEvents(\n config: ServerConfig,\n options: { limit?: number; category?: string } = {}\n): Promise<CommerceOffering[]> {\n const params = new URLSearchParams()\n params.set('type', 'event')\n params.set('status', 'active')\n params.set('upcoming', 'true')\n \n if (options.category) {\n params.set('category', options.category)\n }\n \n if (options.limit) {\n params.set('limit', options.limit.toString())\n }\n \n const data = await apiFetch<{ offerings: Record<string, unknown>[] }>(\n config,\n `/public/commerce/offerings?${params.toString()}`\n )\n \n if (!data?.offerings) return []\n \n return data.offerings.map(transformOffering)\n}\n\n/**\n * Get next upcoming event (server-side)\n */\nexport async function getNextEvent(\n config: ServerConfig,\n category?: string\n): Promise<CommerceOffering | null> {\n const events = await getUpcomingEvents(config, { limit: 1, category })\n return events[0] || null\n}\n\n// ============================================\n// Metadata Helpers\n// ============================================\n\n/**\n * Generate page metadata for an offering\n * \n * @example Next.js App Router\n * export async function generateMetadata({ params }) {\n * const product = await getOfferingBySlug(config, params.slug)\n * return generateOfferingMetadata(product, 'https://example.com')\n * }\n */\nexport function generateOfferingMetadata(\n offering: CommerceOffering | null,\n siteUrl: string\n): {\n title: string\n description: string\n openGraph: {\n title: string\n description: string\n images: string[]\n type: string\n url: string\n }\n} | null {\n if (!offering) return null\n \n const title = offering.seo_title || offering.name\n const description = offering.seo_description || offering.short_description || offering.description || ''\n const images = offering.featured_image_url ? [offering.featured_image_url] : []\n \n const typeMap: Record<OfferingType, string> = {\n product: 'product',\n service: 'website',\n event: 'website',\n class: 'website',\n subscription: 'product',\n }\n \n return {\n title,\n description,\n openGraph: {\n title,\n description,\n images,\n type: typeMap[offering.type] || 'website',\n url: `${siteUrl}/${offering.type}s/${offering.slug}`,\n },\n }\n}\n\n// ============================================\n// Export config builder\n// ============================================\n\n/**\n * Create a server config for API calls\n * \n * @param apiUrl - Portal API URL (e.g., 'https://api.uptrademedia.com')\n * @param apiKey - Project API key\n * @param projectId - Project ID\n */\nexport function createServerConfig(\n apiUrl: string,\n apiKey: string,\n projectId: string\n): ServerConfig {\n return { apiUrl, apiKey, projectId }\n}\n"]}