astro-tractstack 2.3.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +1 -1
  2. package/bin/create-tractstack.js +2 -2
  3. package/dist/index.js +94 -16
  4. package/package.json +2 -2
  5. package/templates/custom/minimal/CodeHook.astro +10 -2
  6. package/templates/custom/shopify/Cart.tsx +100 -73
  7. package/templates/custom/shopify/CheckoutModal.tsx +509 -120
  8. package/templates/custom/shopify/NativeBookingCalendar.tsx +375 -0
  9. package/templates/custom/shopify/ShopifyCartManager.tsx +92 -37
  10. package/templates/custom/shopify/ShopifyProductGrid.tsx +139 -173
  11. package/templates/custom/shopify/ShopifyServiceList.tsx +20 -3
  12. package/templates/custom/with-examples/CodeHook.astro +10 -2
  13. package/templates/src/components/Footer.astro +4 -4
  14. package/templates/src/components/Header.astro +9 -3
  15. package/templates/src/components/edit/pane/AddPanePanel_new.tsx +3 -3
  16. package/templates/src/components/edit/pane/AiRestylePaneModal.tsx +2 -2
  17. package/templates/src/components/edit/pane/steps/AiCreativeDesignStep.tsx +2 -2
  18. package/templates/src/components/edit/pane/steps/AiLibraryCopyStep.tsx +3 -3
  19. package/templates/src/components/edit/pane/steps/AiRefineDesignStep.tsx +2 -2
  20. package/templates/src/components/edit/pane/steps/AiStandardDesignStep.tsx +7 -7
  21. package/templates/src/components/form/advanced/APIConfigSection.tsx +244 -2
  22. package/templates/src/components/form/shopify/SchedulingSection.tsx +354 -0
  23. package/templates/src/components/storykeep/Dashboard.tsx +1 -1
  24. package/templates/src/components/storykeep/Dashboard_Shopify.tsx +253 -110
  25. package/templates/src/components/storykeep/controls/content/BeliefTable.tsx +14 -5
  26. package/templates/src/components/storykeep/controls/content/KnownResourceTable.tsx +5 -2
  27. package/templates/src/components/storykeep/controls/content/MenuTable.tsx +14 -5
  28. package/templates/src/components/storykeep/controls/content/ProductTable.tsx +180 -101
  29. package/templates/src/components/storykeep/controls/content/ResourceBulkIngest.tsx +9 -5
  30. package/templates/src/components/storykeep/controls/content/ResourceTable.tsx +13 -4
  31. package/templates/src/components/storykeep/controls/content/StoryFragmentTable.tsx +14 -5
  32. package/templates/src/components/storykeep/shopify/ShopifyDashboard.tsx +111 -0
  33. package/templates/src/components/storykeep/shopify/ShopifyDashboard_Bookings.tsx +393 -0
  34. package/templates/src/components/storykeep/shopify/ShopifyDashboard_Products.tsx +46 -0
  35. package/templates/src/components/storykeep/shopify/ShopifyDashboard_Schedule.tsx +78 -0
  36. package/templates/src/components/storykeep/shopify/ShopifyDashboard_Search.tsx +55 -0
  37. package/templates/src/components/storykeep/shopify/ShopifyDashboard_Services.tsx +47 -0
  38. package/templates/src/pages/api/auth/lookup-lead.ts +72 -0
  39. package/templates/src/pages/api/booking/availability.ts +72 -0
  40. package/templates/src/pages/api/booking/cancel.ts +73 -0
  41. package/templates/src/pages/api/booking/confirm.ts +82 -0
  42. package/templates/src/pages/api/booking/hold.ts +75 -0
  43. package/templates/src/pages/api/booking/list.ts +66 -0
  44. package/templates/src/pages/api/booking/metrics.ts +60 -0
  45. package/templates/src/pages/api/booking/release.ts +76 -0
  46. package/templates/src/pages/api/sandbox.ts +2 -2
  47. package/templates/src/pages/api/shopify/createCart.ts +4 -8
  48. package/templates/src/pages/api/shopify/getProducts.ts +15 -15
  49. package/templates/src/pages/storykeep/login.astro +21 -14
  50. package/templates/src/stores/shopify.ts +81 -25
  51. package/templates/src/types/tractstack.ts +54 -0
  52. package/templates/src/utils/api/advancedConfig.ts +2 -0
  53. package/templates/src/utils/api/advancedHelpers.ts +40 -3
  54. package/templates/src/utils/api/bookingHelpers.ts +125 -0
  55. package/templates/src/utils/api/brandHelpers.ts +10 -0
  56. package/templates/src/utils/auth.ts +29 -9
  57. package/templates/src/utils/compositor/aiGeneration.ts +3 -3
  58. package/templates/src/utils/compositor/aiPaneParser.ts +2 -2
  59. package/templates/src/utils/customHelpers.ts +0 -21
  60. package/templates/src/utils/profileStorage.ts +5 -0
  61. package/templates/src/utils/tenantResolver.ts +2 -1
  62. package/utils/inject-files.ts +82 -4
  63. package/templates/custom/shopify/CalDotComBooking.tsx +0 -44
@@ -0,0 +1,72 @@
1
+ import type { APIRoute } from '@/types/astro';
2
+
3
+ export const GET: APIRoute = async ({ request, locals }) => {
4
+ const GO_BACKEND =
5
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
6
+
7
+ try {
8
+ const url = new URL(request.url);
9
+ const searchParams = url.searchParams;
10
+
11
+ const controller = new AbortController();
12
+ const timeoutId = setTimeout(() => controller.abort(), 10000);
13
+ const tenantId =
14
+ locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
15
+
16
+ try {
17
+ const response = await fetch(
18
+ `${GO_BACKEND}/api/v1/bookings/availability?${searchParams.toString()}`,
19
+ {
20
+ method: 'GET',
21
+ headers: {
22
+ 'Content-Type': 'application/json',
23
+ 'X-Tenant-ID': tenantId,
24
+ ...(request.headers.get('Authorization') && {
25
+ Authorization: request.headers.get('Authorization')!,
26
+ }),
27
+ },
28
+ signal: controller.signal,
29
+ }
30
+ );
31
+
32
+ clearTimeout(timeoutId);
33
+
34
+ const data = await response.json();
35
+
36
+ return new Response(JSON.stringify(data), {
37
+ status: response.status,
38
+ headers: {
39
+ 'Content-Type': 'application/json',
40
+ },
41
+ });
42
+ } catch (fetchError) {
43
+ clearTimeout(timeoutId);
44
+
45
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
46
+ return new Response(
47
+ JSON.stringify({
48
+ success: false,
49
+ error: 'Availability lookup timeout',
50
+ }),
51
+ {
52
+ status: 408,
53
+ headers: { 'Content-Type': 'application/json' },
54
+ }
55
+ );
56
+ }
57
+ throw fetchError;
58
+ }
59
+ } catch (error) {
60
+ console.error('Availability API proxy error:', error);
61
+ return new Response(
62
+ JSON.stringify({
63
+ success: false,
64
+ error: 'Failed to connect to backend service',
65
+ }),
66
+ {
67
+ status: 500,
68
+ headers: { 'Content-Type': 'application/json' },
69
+ }
70
+ );
71
+ }
72
+ };
@@ -0,0 +1,73 @@
1
+ import type { APIRoute } from '@/types/astro';
2
+ import { getAdminToken } from '@/utils/auth';
3
+
4
+ export const POST: APIRoute = async (context) => {
5
+ const { request, locals } = context;
6
+ const GO_BACKEND =
7
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
8
+
9
+ try {
10
+ const body = await request.json();
11
+ const { traceId } = body;
12
+
13
+ if (!traceId) {
14
+ return new Response(
15
+ JSON.stringify({ success: false, error: 'traceId is required' }),
16
+ { status: 400, headers: { 'Content-Type': 'application/json' } }
17
+ );
18
+ }
19
+
20
+ const controller = new AbortController();
21
+ const timeoutId = setTimeout(() => controller.abort(), 10000);
22
+ const tenantId =
23
+ locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
24
+ const token = getAdminToken(context);
25
+
26
+ try {
27
+ const response = await fetch(
28
+ `${GO_BACKEND}/api/v1/bookings/${traceId}/cancel`,
29
+ {
30
+ method: 'POST',
31
+ headers: {
32
+ 'Content-Type': 'application/json',
33
+ 'X-Tenant-ID': tenantId,
34
+ ...(token && { Authorization: `Bearer ${token}` }),
35
+ ...(request.headers.get('Authorization') && {
36
+ Authorization: request.headers.get('Authorization')!,
37
+ }),
38
+ },
39
+ signal: controller.signal,
40
+ }
41
+ );
42
+
43
+ clearTimeout(timeoutId);
44
+ const data = await response.json();
45
+
46
+ return new Response(JSON.stringify(data), {
47
+ status: response.status,
48
+ headers: { 'Content-Type': 'application/json' },
49
+ });
50
+ } catch (fetchError) {
51
+ clearTimeout(timeoutId);
52
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
53
+ return new Response(
54
+ JSON.stringify({
55
+ success: false,
56
+ error: 'Booking cancellation timeout',
57
+ }),
58
+ { status: 408, headers: { 'Content-Type': 'application/json' } }
59
+ );
60
+ }
61
+ throw fetchError;
62
+ }
63
+ } catch (error) {
64
+ console.error('Booking cancellation API proxy error:', error);
65
+ return new Response(
66
+ JSON.stringify({
67
+ success: false,
68
+ error: 'Failed to connect to backend service',
69
+ }),
70
+ { status: 500, headers: { 'Content-Type': 'application/json' } }
71
+ );
72
+ }
73
+ };
@@ -0,0 +1,82 @@
1
+ import type { APIRoute } from '@/types/astro';
2
+
3
+ export const POST: APIRoute = async ({ request, locals }) => {
4
+ const GO_BACKEND =
5
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
6
+
7
+ try {
8
+ const { traceId } = await request.json();
9
+
10
+ if (!traceId) {
11
+ return new Response(JSON.stringify({ error: 'traceId is required' }), {
12
+ status: 400,
13
+ headers: { 'Content-Type': 'application/json' },
14
+ });
15
+ }
16
+
17
+ const controller = new AbortController();
18
+ const timeoutId = setTimeout(() => controller.abort(), 10000);
19
+ const tenantId =
20
+ locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
21
+
22
+ try {
23
+ const response = await fetch(`${GO_BACKEND}/api/v1/bookings/confirm`, {
24
+ method: 'POST',
25
+ headers: {
26
+ 'Content-Type': 'application/json',
27
+ 'X-Tenant-ID': tenantId,
28
+ ...(request.headers.get('Authorization') && {
29
+ Authorization: request.headers.get('Authorization')!,
30
+ }),
31
+ },
32
+ body: JSON.stringify({ traceId }),
33
+ signal: controller.signal,
34
+ });
35
+
36
+ clearTimeout(timeoutId);
37
+
38
+ const data = await response.json();
39
+
40
+ return new Response(JSON.stringify(data), {
41
+ status: response.status,
42
+ headers: {
43
+ 'Content-Type': 'application/json',
44
+ },
45
+ });
46
+ } catch (fetchError) {
47
+ clearTimeout(timeoutId);
48
+
49
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
50
+ console.error('Confirm-booking request timeout');
51
+ return new Response(
52
+ JSON.stringify({
53
+ success: false,
54
+ error: 'Request timeout - please try again',
55
+ }),
56
+ {
57
+ status: 408,
58
+ headers: {
59
+ 'Content-Type': 'application/json',
60
+ },
61
+ }
62
+ );
63
+ }
64
+ throw fetchError;
65
+ }
66
+ } catch (error) {
67
+ console.error('Confirm-booking API proxy error:', error);
68
+
69
+ return new Response(
70
+ JSON.stringify({
71
+ success: false,
72
+ error: 'Failed to connect to backend service',
73
+ }),
74
+ {
75
+ status: 500,
76
+ headers: {
77
+ 'Content-Type': 'application/json',
78
+ },
79
+ }
80
+ );
81
+ }
82
+ };
@@ -0,0 +1,75 @@
1
+ import type { APIRoute } from '@/types/astro';
2
+
3
+ export const POST: APIRoute = async ({ request, locals }) => {
4
+ const GO_BACKEND =
5
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
6
+
7
+ try {
8
+ const body = await request.text();
9
+
10
+ const controller = new AbortController();
11
+ const timeoutId = setTimeout(() => controller.abort(), 30000);
12
+ const tenantId =
13
+ locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
14
+
15
+ try {
16
+ const response = await fetch(`${GO_BACKEND}/api/v1/bookings/hold`, {
17
+ method: 'POST',
18
+ headers: {
19
+ 'Content-Type': 'application/json',
20
+ 'X-Tenant-ID': tenantId,
21
+ ...(request.headers.get('Authorization') && {
22
+ Authorization: request.headers.get('Authorization')!,
23
+ }),
24
+ },
25
+ body: body,
26
+ signal: controller.signal,
27
+ });
28
+
29
+ clearTimeout(timeoutId);
30
+
31
+ const data = await response.json();
32
+
33
+ return new Response(JSON.stringify(data), {
34
+ status: response.status,
35
+ headers: {
36
+ 'Content-Type': 'application/json',
37
+ },
38
+ });
39
+ } catch (fetchError) {
40
+ clearTimeout(timeoutId);
41
+
42
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
43
+ console.error('Hold-slot request timeout');
44
+ return new Response(
45
+ JSON.stringify({
46
+ success: false,
47
+ error: 'Request timeout - please try again',
48
+ }),
49
+ {
50
+ status: 408,
51
+ headers: {
52
+ 'Content-Type': 'application/json',
53
+ },
54
+ }
55
+ );
56
+ }
57
+ throw fetchError;
58
+ }
59
+ } catch (error) {
60
+ console.error('Hold-slot API proxy error:', error);
61
+
62
+ return new Response(
63
+ JSON.stringify({
64
+ success: false,
65
+ error: 'Failed to connect to backend service',
66
+ }),
67
+ {
68
+ status: 500,
69
+ headers: {
70
+ 'Content-Type': 'application/json',
71
+ },
72
+ }
73
+ );
74
+ }
75
+ };
@@ -0,0 +1,66 @@
1
+ import type { APIRoute } from '@/types/astro';
2
+ import { getAdminToken } from '@/utils/auth';
3
+
4
+ export const GET: APIRoute = async (context) => {
5
+ const { request, locals } = context;
6
+ const GO_BACKEND =
7
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
8
+
9
+ try {
10
+ const url = new URL(request.url);
11
+ const searchParams = url.searchParams;
12
+
13
+ const controller = new AbortController();
14
+ const timeoutId = setTimeout(() => controller.abort(), 10000);
15
+ const tenantId =
16
+ locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
17
+ const token = getAdminToken(context);
18
+
19
+ try {
20
+ const response = await fetch(
21
+ `${GO_BACKEND}/api/v1/bookings/list?${searchParams.toString()}`,
22
+ {
23
+ method: 'GET',
24
+ headers: {
25
+ 'Content-Type': 'application/json',
26
+ 'X-Tenant-ID': tenantId,
27
+ ...(token && { Authorization: `Bearer ${token}` }),
28
+ ...(request.headers.get('Authorization') && {
29
+ Authorization: request.headers.get('Authorization')!,
30
+ }),
31
+ },
32
+ signal: controller.signal,
33
+ }
34
+ );
35
+
36
+ clearTimeout(timeoutId);
37
+ const data = await response.json();
38
+
39
+ return new Response(JSON.stringify(data), {
40
+ status: response.status,
41
+ headers: { 'Content-Type': 'application/json' },
42
+ });
43
+ } catch (fetchError) {
44
+ clearTimeout(timeoutId);
45
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
46
+ return new Response(
47
+ JSON.stringify({
48
+ success: false,
49
+ error: 'Booking list lookup timeout',
50
+ }),
51
+ { status: 408, headers: { 'Content-Type': 'application/json' } }
52
+ );
53
+ }
54
+ throw fetchError;
55
+ }
56
+ } catch (error) {
57
+ console.error('Booking list API proxy error:', error);
58
+ return new Response(
59
+ JSON.stringify({
60
+ success: false,
61
+ error: 'Failed to connect to backend service',
62
+ }),
63
+ { status: 500, headers: { 'Content-Type': 'application/json' } }
64
+ );
65
+ }
66
+ };
@@ -0,0 +1,60 @@
1
+ import type { APIRoute } from '@/types/astro';
2
+ import { getAdminToken } from '@/utils/auth';
3
+
4
+ export const GET: APIRoute = async (context) => {
5
+ const { request, locals } = context;
6
+ const GO_BACKEND =
7
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
8
+
9
+ try {
10
+ const controller = new AbortController();
11
+ const timeoutId = setTimeout(() => controller.abort(), 10000);
12
+ const tenantId =
13
+ locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
14
+ const token = getAdminToken(context);
15
+
16
+ try {
17
+ const response = await fetch(`${GO_BACKEND}/api/v1/bookings/metrics`, {
18
+ method: 'GET',
19
+ headers: {
20
+ 'Content-Type': 'application/json',
21
+ 'X-Tenant-ID': tenantId,
22
+ ...(token && { Authorization: `Bearer ${token}` }),
23
+ ...(request.headers.get('Authorization') && {
24
+ Authorization: request.headers.get('Authorization')!,
25
+ }),
26
+ },
27
+ signal: controller.signal,
28
+ });
29
+
30
+ clearTimeout(timeoutId);
31
+ const data = await response.json();
32
+
33
+ return new Response(JSON.stringify(data), {
34
+ status: response.status,
35
+ headers: { 'Content-Type': 'application/json' },
36
+ });
37
+ } catch (fetchError) {
38
+ clearTimeout(timeoutId);
39
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
40
+ return new Response(
41
+ JSON.stringify({
42
+ success: false,
43
+ error: 'Booking metrics lookup timeout',
44
+ }),
45
+ { status: 408, headers: { 'Content-Type': 'application/json' } }
46
+ );
47
+ }
48
+ throw fetchError;
49
+ }
50
+ } catch (error) {
51
+ console.error('Booking metrics API proxy error:', error);
52
+ return new Response(
53
+ JSON.stringify({
54
+ success: false,
55
+ error: 'Failed to connect to backend service',
56
+ }),
57
+ { status: 500, headers: { 'Content-Type': 'application/json' } }
58
+ );
59
+ }
60
+ };
@@ -0,0 +1,76 @@
1
+ import type { APIRoute } from '@/types/astro';
2
+
3
+ export const POST: APIRoute = async ({ request, locals }) => {
4
+ const GO_BACKEND =
5
+ import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
6
+
7
+ try {
8
+ const { traceId } = await request.json();
9
+
10
+ if (!traceId) {
11
+ return new Response(JSON.stringify({ error: 'traceId is required' }), {
12
+ status: 400,
13
+ headers: { 'Content-Type': 'application/json' },
14
+ });
15
+ }
16
+
17
+ const controller = new AbortController();
18
+ const timeoutId = setTimeout(() => controller.abort(), 10000);
19
+ const tenantId =
20
+ locals.tenant?.id || import.meta.env.PUBLIC_TENANTID || 'default';
21
+
22
+ try {
23
+ const response = await fetch(
24
+ `${GO_BACKEND}/api/v1/bookings/hold/${traceId}`,
25
+ {
26
+ method: 'DELETE',
27
+ headers: {
28
+ 'X-Tenant-ID': tenantId,
29
+ ...(request.headers.get('Authorization') && {
30
+ Authorization: request.headers.get('Authorization')!,
31
+ }),
32
+ },
33
+ signal: controller.signal,
34
+ }
35
+ );
36
+
37
+ clearTimeout(timeoutId);
38
+
39
+ return new Response(JSON.stringify({ success: response.ok }), {
40
+ status: response.status,
41
+ headers: {
42
+ 'Content-Type': 'application/json',
43
+ },
44
+ });
45
+ } catch (fetchError) {
46
+ clearTimeout(timeoutId);
47
+
48
+ if (fetchError instanceof Error && fetchError.name === 'AbortError') {
49
+ return new Response(
50
+ JSON.stringify({
51
+ success: false,
52
+ error: 'Release-hold request timeout',
53
+ }),
54
+ {
55
+ status: 408,
56
+ headers: { 'Content-Type': 'application/json' },
57
+ }
58
+ );
59
+ }
60
+ throw fetchError;
61
+ }
62
+ } catch (error) {
63
+ console.error('Release-hold API proxy error:', error);
64
+
65
+ return new Response(
66
+ JSON.stringify({
67
+ success: false,
68
+ error: 'Failed to connect to backend service',
69
+ }),
70
+ {
71
+ status: 500,
72
+ headers: { 'Content-Type': 'application/json' },
73
+ }
74
+ );
75
+ }
76
+ };
@@ -69,14 +69,14 @@ export const POST: APIRoute = async ({ request, locals }) => {
69
69
  const body = await request.json();
70
70
  const { action, payload } = body;
71
71
 
72
- if (action !== 'askLemur') {
72
+ if (action !== 'aai') {
73
73
  return new Response(
74
74
  JSON.stringify({ success: false, error: 'Invalid action.' }),
75
75
  { status: 400, headers: { 'Content-Type': 'application/json' } }
76
76
  );
77
77
  }
78
78
 
79
- const backendResponse = await fetch(`${goBackend}/api/v1/aai/askLemur`, {
79
+ const backendResponse = await fetch(`${goBackend}/api/v1/aai/aai`, {
80
80
  method: 'POST',
81
81
  headers: {
82
82
  'Content-Type': 'application/json',
@@ -7,16 +7,18 @@ interface CreateCartPayload {
7
7
  lines: Array<{
8
8
  merchandiseId: string;
9
9
  quantity: number;
10
+ attributes?: Array<{ key: string; value: string }>;
10
11
  }>;
11
12
  attributes?: Array<{
12
13
  key: string;
13
14
  value: string;
14
15
  }>;
15
16
  email?: string;
17
+ traceId?: string;
16
18
  }
17
19
 
18
20
  const getBackendUrl = () => {
19
- return import.meta.env.PUBLIC_API_URL || 'http://localhost:8080';
21
+ return import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
20
22
  };
21
23
 
22
24
  export const POST: APIRoute = async ({ request }) => {
@@ -29,12 +31,6 @@ export const POST: APIRoute = async ({ request }) => {
29
31
  try {
30
32
  const body = (await request.json()) as CreateCartPayload;
31
33
 
32
- const payload: CreateCartPayload = {
33
- lines: body.lines,
34
- attributes: body.attributes || [],
35
- email: body.email,
36
- };
37
-
38
34
  const backendResponse = await fetch(backendEndpoint, {
39
35
  method: 'POST',
40
36
  headers: {
@@ -42,7 +38,7 @@ export const POST: APIRoute = async ({ request }) => {
42
38
  'X-Tenant-ID': tenantId,
43
39
  Cookie: cookieHeader,
44
40
  },
45
- body: JSON.stringify(payload),
41
+ body: JSON.stringify(body),
46
42
  });
47
43
 
48
44
  if (!backendResponse.ok) {
@@ -1,24 +1,32 @@
1
1
  import type { APIRoute } from '@/types/astro';
2
- import { shopifyData } from '@/stores/shopify';
3
2
  import { resolveTenantId } from '@/utils/tenantResolver';
4
3
 
5
4
  export const prerender = false;
6
5
 
7
6
  const getBackendUrl = () => {
8
- return import.meta.env.PUBLIC_API_URL || 'http://localhost:8080';
7
+ return import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
9
8
  };
10
9
 
11
10
  export const GET: APIRoute = async ({ request }) => {
12
- // 1. Resolve Tenant Identity
13
11
  const resolution = await resolveTenantId(request);
14
12
  const tenantId = resolution.id;
15
13
 
16
- // 2. Fetch from Backend Proxy
17
- const backendEndpoint = `${getBackendUrl()}/api/v1/shopify/products`;
14
+ const url = new URL(request.url);
15
+ const q = url.searchParams.get('q') || '';
16
+ const cursor = url.searchParams.get('cursor') || '';
17
+
18
+ const backendUrl = new URL(`${getBackendUrl()}/api/v1/shopify/products`);
19
+ if (q) {
20
+ backendUrl.searchParams.set('q', q);
21
+ }
22
+ if (cursor) {
23
+ backendUrl.searchParams.set('cursor', cursor);
24
+ }
25
+
18
26
  const cookieHeader = request.headers.get('cookie') || '';
19
27
 
20
28
  try {
21
- const backendResponse = await fetch(backendEndpoint, {
29
+ const backendResponse = await fetch(backendUrl.toString(), {
22
30
  method: 'GET',
23
31
  headers: {
24
32
  'Content-Type': 'application/json',
@@ -36,15 +44,7 @@ export const GET: APIRoute = async ({ request }) => {
36
44
 
37
45
  const result = await backendResponse.json();
38
46
 
39
- // 3. Update Client Store
40
- const newState = {
41
- products: result.products || [],
42
- lastFetched: Date.now(),
43
- };
44
-
45
- shopifyData.set(newState);
46
-
47
- return new Response(JSON.stringify(newState), {
47
+ return new Response(JSON.stringify(result), {
48
48
  status: 200,
49
49
  headers: { 'Content-Type': 'application/json' },
50
50
  });
@@ -55,20 +55,27 @@ const mainStylesUrl = isDev
55
55
  <div class="mx-auto pb-6">
56
56
  <!-- Logo and Wordmark -->
57
57
  <div class="flex flex-col items-center justify-center gap-4">
58
- <div class="h-16 w-auto">
59
- <img
60
- src={logo}
61
- class="pointer-events-none h-full w-auto"
62
- alt="Logo"
63
- />
64
- </div>
65
- <div class="h-16 w-auto">
66
- <img
67
- src={wordmark}
68
- class="pointer-events-none h-full w-auto max-w-48 md:max-w-72"
69
- alt="Wordmark"
70
- />
71
- </div>
58
+ {
59
+ brandConfig?.WORDMARK_MODE !== 'wordmark' && (
60
+ <img
61
+ id="t8k-logo"
62
+ src={logo}
63
+ class="pointer-events-none h-16 w-auto"
64
+ alt="Logo"
65
+ />
66
+ )
67
+ }
68
+
69
+ {
70
+ brandConfig?.WORDMARK_MODE !== 'logo' && (
71
+ <img
72
+ id="t8k-wordmark"
73
+ src={wordmark}
74
+ class="pointer-events-none h-16 w-auto max-w-48 md:max-w-72"
75
+ alt="Wordmark"
76
+ />
77
+ )
78
+ }
72
79
  </div>
73
80
 
74
81
  <h2