@uptrademedia/site-kit 1.0.0

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 (120) hide show
  1. package/README.md +305 -0
  2. package/dist/analytics/index.js +88 -0
  3. package/dist/analytics/index.js.map +1 -0
  4. package/dist/analytics/index.mjs +70 -0
  5. package/dist/analytics/index.mjs.map +1 -0
  6. package/dist/api-N35S3EES.js +57 -0
  7. package/dist/api-N35S3EES.js.map +1 -0
  8. package/dist/api-SYBTK7Z7.mjs +4 -0
  9. package/dist/api-SYBTK7Z7.mjs.map +1 -0
  10. package/dist/blog/index.js +200 -0
  11. package/dist/blog/index.js.map +1 -0
  12. package/dist/blog/index.mjs +194 -0
  13. package/dist/blog/index.mjs.map +1 -0
  14. package/dist/chunk-3MUOUXHV.js +3721 -0
  15. package/dist/chunk-3MUOUXHV.js.map +1 -0
  16. package/dist/chunk-4HVYXYQL 2.mjs +255 -0
  17. package/dist/chunk-4HVYXYQL.mjs +255 -0
  18. package/dist/chunk-4HVYXYQL.mjs.map +1 -0
  19. package/dist/chunk-7H6I3ECV.mjs +120 -0
  20. package/dist/chunk-7H6I3ECV.mjs.map +1 -0
  21. package/dist/chunk-COI6GOX2.mjs +3679 -0
  22. package/dist/chunk-COI6GOX2.mjs.map +1 -0
  23. package/dist/chunk-EQCVQC35.js +35 -0
  24. package/dist/chunk-EQCVQC35.js 2.map +1 -0
  25. package/dist/chunk-EQCVQC35.js.map +1 -0
  26. package/dist/chunk-FEBYQGY4 2.mjs +251 -0
  27. package/dist/chunk-FEBYQGY4.mjs +251 -0
  28. package/dist/chunk-FEBYQGY4.mjs.map +1 -0
  29. package/dist/chunk-FKVJOT2F.mjs +796 -0
  30. package/dist/chunk-FKVJOT2F.mjs.map +1 -0
  31. package/dist/chunk-GQ6ZOU2N.mjs +134 -0
  32. package/dist/chunk-GQ6ZOU2N.mjs.map +1 -0
  33. package/dist/chunk-HCFPU7TU.js +137 -0
  34. package/dist/chunk-HCFPU7TU.js.map +1 -0
  35. package/dist/chunk-NYKRE2FL 2.mjs +31 -0
  36. package/dist/chunk-NYKRE2FL.mjs +31 -0
  37. package/dist/chunk-NYKRE2FL.mjs 2.map +1 -0
  38. package/dist/chunk-NYKRE2FL.mjs.map +1 -0
  39. package/dist/chunk-QP5NCO2E.js +133 -0
  40. package/dist/chunk-QP5NCO2E.js.map +1 -0
  41. package/dist/chunk-RV7H3I6J.js +255 -0
  42. package/dist/chunk-RV7H3I6J.js 2.map +1 -0
  43. package/dist/chunk-RV7H3I6J.js.map +1 -0
  44. package/dist/chunk-SBVEYCSV.js +140 -0
  45. package/dist/chunk-SBVEYCSV.js.map +1 -0
  46. package/dist/chunk-TUKGA3UK.js +257 -0
  47. package/dist/chunk-TUKGA3UK.js 2.map +1 -0
  48. package/dist/chunk-TUKGA3UK.js.map +1 -0
  49. package/dist/chunk-V3F5J6CV.js +801 -0
  50. package/dist/chunk-V3F5J6CV.js.map +1 -0
  51. package/dist/chunk-WPSRS352.mjs +135 -0
  52. package/dist/chunk-WPSRS352.mjs.map +1 -0
  53. package/dist/commerce/index.js +157 -0
  54. package/dist/commerce/index.js.map +1 -0
  55. package/dist/commerce/index.mjs +4 -0
  56. package/dist/commerce/index.mjs.map +1 -0
  57. package/dist/commerce/server.js +186 -0
  58. package/dist/commerce/server.js.map +1 -0
  59. package/dist/commerce/server.mjs +176 -0
  60. package/dist/commerce/server.mjs.map +1 -0
  61. package/dist/engage/index.js +50 -0
  62. package/dist/engage/index.js.map +1 -0
  63. package/dist/engage/index.mjs +44 -0
  64. package/dist/engage/index.mjs.map +1 -0
  65. package/dist/forms/index.js +1053 -0
  66. package/dist/forms/index.js.map +1 -0
  67. package/dist/forms/index.mjs +1035 -0
  68. package/dist/forms/index.mjs.map +1 -0
  69. package/dist/generators-7Y5ABRYV 2.mjs +161 -0
  70. package/dist/generators-7Y5ABRYV.mjs +161 -0
  71. package/dist/generators-7Y5ABRYV.mjs 2.map +1 -0
  72. package/dist/generators-7Y5ABRYV.mjs.map +1 -0
  73. package/dist/generators-GWIYCA5M.js +171 -0
  74. package/dist/generators-GWIYCA5M.js 2.map +1 -0
  75. package/dist/generators-GWIYCA5M.js.map +1 -0
  76. package/dist/index 2.mjs +74 -0
  77. package/dist/index.js +326 -0
  78. package/dist/index.js 2.map +1 -0
  79. package/dist/index.js.map +1 -0
  80. package/dist/index.mjs +222 -0
  81. package/dist/index.mjs.map +1 -0
  82. package/dist/migrator-V6KS75EA 2.mjs +265 -0
  83. package/dist/migrator-V6KS75EA.mjs +265 -0
  84. package/dist/migrator-V6KS75EA.mjs 2.map +1 -0
  85. package/dist/migrator-V6KS75EA.mjs.map +1 -0
  86. package/dist/migrator-XKM7YQCY.js +272 -0
  87. package/dist/migrator-XKM7YQCY.js 2.map +1 -0
  88. package/dist/migrator-XKM7YQCY.js.map +1 -0
  89. package/dist/scanner-MF7P3CDE 2.mjs +14386 -0
  90. package/dist/scanner-MF7P3CDE.mjs +14386 -0
  91. package/dist/scanner-MF7P3CDE.mjs 2.map +1 -0
  92. package/dist/scanner-MF7P3CDE.mjs.map +1 -0
  93. package/dist/scanner-NT6YG4TD 2.js +14397 -0
  94. package/dist/scanner-NT6YG4TD.js +14397 -0
  95. package/dist/scanner-NT6YG4TD.js 2.map +1 -0
  96. package/dist/scanner-NT6YG4TD.js.map +1 -0
  97. package/dist/seo/index.js +447 -0
  98. package/dist/seo/index.js.map +1 -0
  99. package/dist/seo/index.mjs +411 -0
  100. package/dist/seo/index.mjs.map +1 -0
  101. package/dist/seo/server.js +66 -0
  102. package/dist/seo/server.js.map +1 -0
  103. package/dist/seo/server.mjs +5 -0
  104. package/dist/seo/server.mjs.map +1 -0
  105. package/dist/setup/index.js +1050 -0
  106. package/dist/setup/index.js.map +1 -0
  107. package/dist/setup/index.mjs +1046 -0
  108. package/dist/setup/index.mjs.map +1 -0
  109. package/dist/sitemap/index.js +212 -0
  110. package/dist/sitemap/index.js.map +1 -0
  111. package/dist/sitemap/index.mjs +206 -0
  112. package/dist/sitemap/index.mjs.map +1 -0
  113. package/dist/web-vitals-BH55V7EJ.js +252 -0
  114. package/dist/web-vitals-BH55V7EJ.js 2.map +1 -0
  115. package/dist/web-vitals-BH55V7EJ.js.map +1 -0
  116. package/dist/web-vitals-RJYPWAR3 2.mjs +241 -0
  117. package/dist/web-vitals-RJYPWAR3.mjs +241 -0
  118. package/dist/web-vitals-RJYPWAR3.mjs 2.map +1 -0
  119. package/dist/web-vitals-RJYPWAR3.mjs.map +1 -0
  120. package/package.json +118 -0
@@ -0,0 +1,133 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+
5
+ // src/seo/api.ts
6
+ function getApiConfig() {
7
+ const apiUrl = process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.uptrademedia.com";
8
+ const apiKey = process.env.NEXT_PUBLIC_UPTRADE_API_KEY || "";
9
+ return { apiUrl, apiKey };
10
+ }
11
+ async function apiPost(endpoint, body = {}) {
12
+ const { apiUrl, apiKey } = getApiConfig();
13
+ if (!apiKey) {
14
+ console.error("@uptrade/seo: No API key configured. Set NEXT_PUBLIC_UPTRADE_API_KEY.");
15
+ return null;
16
+ }
17
+ try {
18
+ const response = await fetch(`${apiUrl}${endpoint}`, {
19
+ method: "POST",
20
+ headers: {
21
+ "Content-Type": "application/json",
22
+ "x-api-key": apiKey
23
+ },
24
+ body: JSON.stringify(body),
25
+ next: { revalidate: 60 }
26
+ // Cache for 60 seconds
27
+ });
28
+ if (!response.ok) {
29
+ console.error(`@uptrade/seo: API error: ${response.statusText}`);
30
+ return null;
31
+ }
32
+ return await response.json();
33
+ } catch (error) {
34
+ console.error("@uptrade/seo: Network error:", error);
35
+ return null;
36
+ }
37
+ }
38
+ var getSEOPageData = react.cache(async (projectId, path) => {
39
+ const result = await apiPost("/api/public/seo/page", { path });
40
+ return result?.page || null;
41
+ });
42
+ var getSchemaMarkups = react.cache(async (projectId, path, options) => {
43
+ const result = await apiPost("/api/public/seo/schemas", {
44
+ path,
45
+ includeTypes: options?.includeTypes,
46
+ excludeTypes: options?.excludeTypes
47
+ });
48
+ return result?.schemas || [];
49
+ });
50
+ var getFAQData = react.cache(async (projectId, path) => {
51
+ const result = await apiPost("/api/public/seo/faq", { path });
52
+ return result?.faq || null;
53
+ });
54
+ var getInternalLinks = react.cache(async (projectId, sourcePath, options) => {
55
+ const result = await apiPost("/api/public/seo/internal-links", {
56
+ sourcePath,
57
+ position: options?.position,
58
+ limit: options?.limit
59
+ });
60
+ return result?.links || [];
61
+ });
62
+ var getContentBlock = react.cache(async (projectId, path, section) => {
63
+ const result = await apiPost("/api/public/seo/content", { path, section });
64
+ return result?.content || null;
65
+ });
66
+ var getABTest = react.cache(async (projectId, path, field) => {
67
+ const result = await apiPost("/api/public/seo/ab-test", { path, field });
68
+ return result?.test || null;
69
+ });
70
+ async function recordABImpression(testId, variant, sessionId) {
71
+ await apiPost("/api/public/seo/ab-impression", { testId, variant, sessionId });
72
+ }
73
+ var getRedirectData = react.cache(async (projectId, path) => {
74
+ const result = await apiPost("/api/public/seo/redirect", { path });
75
+ return result?.redirect || null;
76
+ });
77
+ var getManagedScripts = react.cache(async (projectId, position, currentPath) => {
78
+ const result = await apiPost("/api/public/seo/scripts", {
79
+ position,
80
+ currentPath
81
+ });
82
+ return result?.scripts || [];
83
+ });
84
+ var getRobotsData = react.cache(async (projectId, path) => {
85
+ const result = await apiPost("/api/public/seo/page", { path });
86
+ return result?.page?.managed_robots || null;
87
+ });
88
+ var getSitemapEntries = react.cache(async (projectId, options) => {
89
+ const result = await apiPost("/api/public/seo/sitemap", {
90
+ publishedOnly: options?.publishedOnly
91
+ });
92
+ return result?.entries || [];
93
+ });
94
+ async function registerSitemap(entries) {
95
+ const { apiUrl, apiKey } = getApiConfig();
96
+ if (!apiKey) {
97
+ console.error("@uptrade/seo: No API key configured. Set NEXT_PUBLIC_UPTRADE_API_KEY.");
98
+ return { success: false, created: 0, updated: 0 };
99
+ }
100
+ try {
101
+ const response = await fetch(`${apiUrl}/api/public/seo/register-sitemap`, {
102
+ method: "POST",
103
+ headers: {
104
+ "Content-Type": "application/json",
105
+ "x-api-key": apiKey
106
+ },
107
+ body: JSON.stringify({ entries })
108
+ });
109
+ if (!response.ok) {
110
+ console.error(`@uptrade/seo: Sitemap registration failed: ${response.statusText}`);
111
+ return { success: false, created: 0, updated: 0 };
112
+ }
113
+ return await response.json();
114
+ } catch (error) {
115
+ console.error("@uptrade/seo: Sitemap registration error:", error);
116
+ return { success: false, created: 0, updated: 0 };
117
+ }
118
+ }
119
+
120
+ exports.getABTest = getABTest;
121
+ exports.getContentBlock = getContentBlock;
122
+ exports.getFAQData = getFAQData;
123
+ exports.getInternalLinks = getInternalLinks;
124
+ exports.getManagedScripts = getManagedScripts;
125
+ exports.getRedirectData = getRedirectData;
126
+ exports.getRobotsData = getRobotsData;
127
+ exports.getSEOPageData = getSEOPageData;
128
+ exports.getSchemaMarkups = getSchemaMarkups;
129
+ exports.getSitemapEntries = getSitemapEntries;
130
+ exports.recordABImpression = recordABImpression;
131
+ exports.registerSitemap = registerSitemap;
132
+ //# sourceMappingURL=chunk-QP5NCO2E.js.map
133
+ //# sourceMappingURL=chunk-QP5NCO2E.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/seo/api.ts"],"names":["cache"],"mappings":"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","file":"chunk-QP5NCO2E.js","sourcesContent":["/**\n * @uptrade/site-kit/seo - API Functions\n * \n * All SEO data fetching goes through Portal API with API key auth.\n * These functions are designed for server-side use (RSC/SSR).\n */\n\nimport { cache } from 'react'\n\n// ============================================\n// API Config\n// ============================================\n\nfunction getApiConfig() {\n const apiUrl = process.env.NEXT_PUBLIC_UPTRADE_API_URL || 'https://api.uptrademedia.com'\n const apiKey = process.env.NEXT_PUBLIC_UPTRADE_API_KEY || ''\n return { apiUrl, apiKey }\n}\n\nasync function apiPost<T>(endpoint: string, body: Record<string, any> = {}): Promise<T | null> {\n const { apiUrl, apiKey } = getApiConfig()\n \n if (!apiKey) {\n console.error('@uptrade/seo: No API key configured. Set NEXT_PUBLIC_UPTRADE_API_KEY.')\n return null\n }\n \n try {\n const response = await fetch(`${apiUrl}${endpoint}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: JSON.stringify(body),\n next: { revalidate: 60 }, // Cache for 60 seconds\n })\n \n if (!response.ok) {\n console.error(`@uptrade/seo: API error: ${response.statusText}`)\n return null\n }\n \n return await response.json()\n } catch (error) {\n console.error('@uptrade/seo: Network error:', error)\n return null\n }\n}\n\n// ============================================\n// Cached Data Fetchers\n// ============================================\n\n/**\n * Fetch SEO page data - cached per request\n */\nexport const getSEOPageData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ page: any }>('/api/public/seo/page', { path })\n return result?.page || null\n})\n\n/**\n * Fetch schema markups for a page - cached per request\n */\nexport const getSchemaMarkups = cache(async (\n projectId: string,\n path: string,\n options?: { includeTypes?: string[]; excludeTypes?: string[] }\n) => {\n const result = await apiPost<{ schemas: any[] }>('/api/public/seo/schemas', {\n path,\n includeTypes: options?.includeTypes,\n excludeTypes: options?.excludeTypes,\n })\n return result?.schemas || []\n})\n\n/**\n * Fetch FAQ data for a page - cached per request\n */\nexport const getFAQData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ faq: any }>('/api/public/seo/faq', { path })\n return result?.faq || null\n})\n\n/**\n * Fetch internal links for a page - cached per request\n */\nexport const getInternalLinks = cache(async (\n projectId: string,\n sourcePath: string,\n options?: { position?: string; limit?: number }\n) => {\n const result = await apiPost<{ links: any[] }>('/api/public/seo/internal-links', {\n sourcePath,\n position: options?.position,\n limit: options?.limit,\n })\n return result?.links || []\n})\n\n/**\n * Fetch content block - cached per request\n */\nexport const getContentBlock = cache(async (\n projectId: string,\n path: string,\n section: string\n) => {\n const result = await apiPost<{ content: any }>('/api/public/seo/content', { path, section })\n return result?.content || null\n})\n\n/**\n * Fetch A/B test and determine variant - cached per request\n */\nexport const getABTest = cache(async (\n projectId: string,\n path: string,\n field: string\n) => {\n const result = await apiPost<{ test: any }>('/api/public/seo/ab-test', { path, field })\n return result?.test || null\n})\n\n/**\n * Record A/B test impression\n */\nexport async function recordABImpression(\n testId: string,\n variant: 'a' | 'b',\n sessionId?: string\n): Promise<void> {\n await apiPost('/api/public/seo/ab-impression', { testId, variant, sessionId })\n}\n\n/**\n * Fetch redirect for a path - cached per request\n */\nexport const getRedirectData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ redirect: any }>('/api/public/seo/redirect', { path })\n return result?.redirect || null\n})\n\n/**\n * Fetch managed scripts - cached per request\n */\nexport const getManagedScripts = cache(async (\n projectId: string,\n position: string,\n currentPath?: string\n) => {\n const result = await apiPost<{ scripts: any[] }>('/api/public/seo/scripts', {\n position,\n currentPath,\n })\n return result?.scripts || []\n})\n\n/**\n * Fetch robots directive for a page - cached per request\n */\nexport const getRobotsData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ page: any }>('/api/public/seo/page', { path })\n return result?.page?.managed_robots || null\n})\n\n/**\n * Fetch sitemap entries - cached per request\n */\nexport const getSitemapEntries = cache(async (\n projectId: string,\n options?: { publishedOnly?: boolean }\n) => {\n const result = await apiPost<{ entries: any[] }>('/api/public/seo/sitemap', {\n publishedOnly: options?.publishedOnly,\n })\n return result?.entries || []\n})\n\n/**\n * Register/sync sitemap entries from the client site\n * Call this at build time to populate seo_pages from your sitemap.xml\n * \n * @example\n * ```ts\n * // scripts/register-sitemap.ts (run at build time)\n * import { registerSitemap } from '@uptrade/seo/server'\n * \n * await registerSitemap([\n * { path: '/', priority: 1.0, changefreq: 'daily' },\n * { path: '/about', priority: 0.8, changefreq: 'weekly' },\n * ])\n * ```\n */\nexport async function registerSitemap(\n entries: Array<{\n path: string\n title?: string\n priority?: number\n changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'\n }>\n): Promise<{ success: boolean; created: number; updated: number }> {\n const { apiUrl, apiKey } = getApiConfig()\n \n if (!apiKey) {\n console.error('@uptrade/seo: No API key configured. Set NEXT_PUBLIC_UPTRADE_API_KEY.')\n return { success: false, created: 0, updated: 0 }\n }\n \n try {\n const response = await fetch(`${apiUrl}/api/public/seo/register-sitemap`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: JSON.stringify({ entries }),\n })\n \n if (!response.ok) {\n console.error(`@uptrade/seo: Sitemap registration failed: ${response.statusText}`)\n return { success: false, created: 0, updated: 0 }\n }\n \n return await response.json()\n } catch (error) {\n console.error('@uptrade/seo: Sitemap registration error:', error)\n return { success: false, created: 0, updated: 0 }\n }\n}\n"]}
@@ -0,0 +1,255 @@
1
+ 'use strict';
2
+
3
+ // src/forms/formsApi.ts
4
+ var config = null;
5
+ function configureFormsApi(options) {
6
+ config = options;
7
+ }
8
+ function getConfig() {
9
+ if (config) return config;
10
+ if (typeof window !== "undefined") {
11
+ const apiUrl = window.__SITE_KIT_API_URL__;
12
+ const apiKey = window.__SITE_KIT_API_KEY__;
13
+ if (apiUrl && apiKey) {
14
+ return { baseUrl: apiUrl, apiKey };
15
+ }
16
+ }
17
+ throw new Error(
18
+ "Forms API not configured. Either wrap your app in SiteKitProvider or call configureFormsApi() first."
19
+ );
20
+ }
21
+ async function apiRequest(method, path, body) {
22
+ const { baseUrl, apiKey, getAuthToken } = getConfig();
23
+ const headers = {
24
+ "Content-Type": "application/json"
25
+ };
26
+ if (apiKey) {
27
+ headers["x-api-key"] = apiKey;
28
+ } else if (getAuthToken) {
29
+ const token = await getAuthToken();
30
+ headers["Authorization"] = `Bearer ${token}`;
31
+ }
32
+ const response = await fetch(`${baseUrl}${path}`, {
33
+ method,
34
+ headers,
35
+ body: body ? JSON.stringify(body) : void 0
36
+ });
37
+ if (!response.ok) {
38
+ const error = await response.json().catch(() => ({ message: response.statusText }));
39
+ throw new Error(error.message || `API error: ${response.status}`);
40
+ }
41
+ if (response.status === 204) {
42
+ return void 0;
43
+ }
44
+ return response.json();
45
+ }
46
+ var formsApi = {
47
+ /**
48
+ * List all forms for a project
49
+ */
50
+ async list(options = {}) {
51
+ const params = new URLSearchParams();
52
+ if (options.projectId) params.set("projectId", options.projectId);
53
+ if (options.formType) params.set("formType", options.formType);
54
+ if (options.isActive !== void 0) params.set("isActive", String(options.isActive));
55
+ if (options.search) params.set("search", options.search);
56
+ const query = params.toString();
57
+ const result = await apiRequest("GET", `/forms${query ? `?${query}` : ""}`);
58
+ return result.data;
59
+ },
60
+ /**
61
+ * Get a single form by ID or slug
62
+ */
63
+ async get(idOrSlug) {
64
+ return apiRequest("GET", `/forms/${idOrSlug}`);
65
+ },
66
+ /**
67
+ * Create a new form
68
+ */
69
+ async create(input) {
70
+ return apiRequest("POST", "/forms", input);
71
+ },
72
+ /**
73
+ * Update an existing form
74
+ */
75
+ async update(id, input) {
76
+ return apiRequest("PUT", `/forms/${id}`, input);
77
+ },
78
+ /**
79
+ * Delete a form
80
+ */
81
+ async delete(id) {
82
+ return apiRequest("DELETE", `/forms/${id}`);
83
+ },
84
+ /**
85
+ * Add a field to an existing form
86
+ */
87
+ async addField(formId, field2) {
88
+ const form = await formsApi.get(formId);
89
+ const maxSortOrder = Math.max(0, ...(form.fields || []).map((f) => f.sortOrder || 0));
90
+ return formsApi.update(formId, {
91
+ fields: [
92
+ ...form.fields || [],
93
+ { ...field2, sortOrder: field2.sortOrder ?? maxSortOrder + 1 }
94
+ ]
95
+ });
96
+ },
97
+ /**
98
+ * Update a field in an existing form
99
+ */
100
+ async updateField(formId, fieldSlug, updates) {
101
+ const form = await formsApi.get(formId);
102
+ return formsApi.update(formId, {
103
+ fields: (form.fields || []).map(
104
+ (f) => f.slug === fieldSlug ? { ...f, ...updates } : f
105
+ )
106
+ });
107
+ },
108
+ /**
109
+ * Remove a field from a form
110
+ */
111
+ async removeField(formId, fieldSlug) {
112
+ const form = await formsApi.get(formId);
113
+ return formsApi.update(formId, {
114
+ fields: (form.fields || []).filter((f) => f.slug !== fieldSlug)
115
+ });
116
+ },
117
+ /**
118
+ * Reorder fields in a form
119
+ */
120
+ async reorderFields(formId, fieldSlugs) {
121
+ const form = await formsApi.get(formId);
122
+ const fieldsMap = new Map((form.fields || []).map((f) => [f.slug, f]));
123
+ const orderedFields = fieldSlugs.map((slug, index) => {
124
+ const field2 = fieldsMap.get(slug);
125
+ if (!field2) throw new Error(`Field not found: ${slug}`);
126
+ return { ...field2, sortOrder: index };
127
+ });
128
+ return formsApi.update(formId, { fields: orderedFields });
129
+ },
130
+ /**
131
+ * Clone a form
132
+ */
133
+ async clone(formId, newSlug, newName) {
134
+ const form = await formsApi.get(formId);
135
+ return formsApi.create({
136
+ projectId: form.projectId,
137
+ slug: newSlug,
138
+ name: newName || `${form.name} (Copy)`,
139
+ description: form.description,
140
+ formType: form.formType,
141
+ successMessage: form.successMessage,
142
+ redirectUrl: form.redirectUrl,
143
+ notificationEmails: form.notificationEmails,
144
+ submitButtonText: form.submitButtonText,
145
+ layout: form.layout,
146
+ showProgress: form.showProgress,
147
+ enableSaveDraft: form.enableSaveDraft,
148
+ isActive: false,
149
+ // Clone as inactive
150
+ fields: (form.fields || []).map(({ id, ...field2 }) => field2),
151
+ // Remove IDs
152
+ steps: (form.steps || []).map(({ id, ...step }) => step)
153
+ // Remove IDs
154
+ });
155
+ },
156
+ /**
157
+ * Activate or deactivate a form
158
+ */
159
+ async setActive(formId, isActive) {
160
+ return formsApi.update(formId, { isActive });
161
+ }
162
+ };
163
+ var field = {
164
+ text: (slug, label, options) => ({
165
+ slug,
166
+ label,
167
+ fieldType: "text",
168
+ ...options
169
+ }),
170
+ email: (slug, label, options) => ({
171
+ slug,
172
+ label,
173
+ fieldType: "email",
174
+ isRequired: true,
175
+ ...options
176
+ }),
177
+ phone: (slug, label, options) => ({
178
+ slug,
179
+ label,
180
+ fieldType: "phone",
181
+ ...options
182
+ }),
183
+ textarea: (slug, label, options) => ({
184
+ slug,
185
+ label,
186
+ fieldType: "textarea",
187
+ ...options
188
+ }),
189
+ select: (slug, label, choices, options) => ({
190
+ slug,
191
+ label,
192
+ fieldType: "select",
193
+ options: choices,
194
+ ...options
195
+ }),
196
+ radio: (slug, label, choices, options) => ({
197
+ slug,
198
+ label,
199
+ fieldType: "radio",
200
+ options: choices,
201
+ ...options
202
+ }),
203
+ checkbox: (slug, label, options) => ({
204
+ slug,
205
+ label,
206
+ fieldType: "checkbox",
207
+ ...options
208
+ }),
209
+ date: (slug, label, options) => ({
210
+ slug,
211
+ label,
212
+ fieldType: "date",
213
+ ...options
214
+ }),
215
+ number: (slug, label, options) => ({
216
+ slug,
217
+ label,
218
+ fieldType: "number",
219
+ ...options
220
+ }),
221
+ rating: (slug, label, options) => ({
222
+ slug,
223
+ label,
224
+ fieldType: "rating",
225
+ ...options
226
+ }),
227
+ file: (slug, label, options) => ({
228
+ slug,
229
+ label,
230
+ fieldType: "file",
231
+ ...options
232
+ }),
233
+ hidden: (slug, defaultValue) => ({
234
+ slug,
235
+ label: "",
236
+ fieldType: "hidden",
237
+ defaultValue
238
+ }),
239
+ heading: (slug, label) => ({
240
+ slug,
241
+ label,
242
+ fieldType: "heading"
243
+ }),
244
+ paragraph: (slug, label) => ({
245
+ slug,
246
+ label,
247
+ fieldType: "paragraph"
248
+ })
249
+ };
250
+
251
+ exports.configureFormsApi = configureFormsApi;
252
+ exports.field = field;
253
+ exports.formsApi = formsApi;
254
+ //# sourceMappingURL=chunk-RV7H3I6J.js.map
255
+ //# sourceMappingURL=chunk-RV7H3I6J.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/forms/formsApi.ts"],"names":["field"],"mappings":"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","file":"chunk-RV7H3I6J.js","sourcesContent":["/**\n * @uptrade/site-kit/forms - Forms API Client\n * \n * Full API client for form management. Allows developers to create, update,\n * and delete forms programmatically. Changes sync to Portal automatically.\n * \n * @example\n * ```tsx\n * import { formsApi } from '@uptrade/site-kit/forms'\n * \n * // Create a new form\n * const form = await formsApi.create({\n * projectId: 'xxx',\n * slug: 'contact-us',\n * name: 'Contact Form',\n * formType: 'prospect',\n * fields: [\n * { slug: 'name', label: 'Name', fieldType: 'text', isRequired: true },\n * { slug: 'email', label: 'Email', fieldType: 'email', isRequired: true },\n * { slug: 'message', label: 'Message', fieldType: 'textarea' },\n * ]\n * })\n * \n * // Update fields\n * await formsApi.update(form.id, {\n * fields: [...form.fields, { slug: 'phone', label: 'Phone', fieldType: 'phone' }]\n * })\n * ```\n */\n\n// ============================================\n// Types\n// ============================================\n\nexport type FormType = \n | 'prospect' // → CRM leads\n | 'contact' // → Contact form\n | 'support' // → Support tickets\n | 'feedback' // → Feedback entries\n | 'newsletter' // → Email subscribers\n | 'custom' // → Custom webhook\n\nexport type FieldType =\n | 'text'\n | 'email'\n | 'phone'\n | 'number'\n | 'textarea'\n | 'select'\n | 'multi_select'\n | 'radio'\n | 'checkbox'\n | 'date'\n | 'time'\n | 'datetime'\n | 'url'\n | 'file'\n | 'rating'\n | 'slider'\n | 'hidden'\n | 'heading'\n | 'paragraph'\n\nexport type FieldWidth = 'full' | 'half' | 'third' | 'quarter'\n\nexport interface FieldOption {\n value: string\n label: string\n disabled?: boolean\n}\n\nexport interface FieldValidation {\n min?: number\n max?: number\n minLength?: number\n maxLength?: number\n pattern?: string\n patternMessage?: string\n}\n\nexport interface FieldConditional {\n field: string\n operator: 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'is_empty' | 'not_empty' | 'greater_than' | 'less_than'\n value?: string | number | boolean\n}\n\nexport interface FormField {\n id?: string\n slug: string\n label: string\n fieldType: FieldType\n placeholder?: string\n helpText?: string\n defaultValue?: string\n isRequired?: boolean\n validation?: FieldValidation\n options?: FieldOption[]\n conditional?: FieldConditional\n width?: FieldWidth\n sortOrder?: number\n destinationField?: string\n stepId?: string\n}\n\nexport interface FormStep {\n id?: string\n stepNumber: number\n title?: string\n description?: string\n condition?: FieldConditional\n}\n\nexport interface Form {\n id: string\n projectId: string\n slug: string\n name: string\n description?: string\n formType: FormType\n successMessage: string\n redirectUrl?: string\n notificationEmails?: string[]\n submitButtonText: string\n layout: 'stacked' | 'inline' | 'grid'\n showProgress: boolean\n enableSaveDraft: boolean\n isActive: boolean\n createdAt: string\n updatedAt: string\n fields?: FormField[]\n steps?: FormStep[]\n}\n\nexport interface CreateFormInput {\n projectId: string\n slug: string\n name: string\n description?: string\n formType?: FormType\n successMessage?: string\n redirectUrl?: string\n notificationEmails?: string[]\n submitButtonText?: string\n layout?: 'stacked' | 'inline' | 'grid'\n showProgress?: boolean\n enableSaveDraft?: boolean\n isActive?: boolean\n fields?: FormField[]\n steps?: FormStep[]\n}\n\nexport interface UpdateFormInput {\n slug?: string\n name?: string\n description?: string\n formType?: FormType\n successMessage?: string\n redirectUrl?: string\n notificationEmails?: string[]\n submitButtonText?: string\n layout?: 'stacked' | 'inline' | 'grid'\n showProgress?: boolean\n enableSaveDraft?: boolean\n isActive?: boolean\n fields?: FormField[]\n steps?: FormStep[]\n}\n\nexport interface FormsListOptions {\n projectId?: string\n formType?: FormType\n isActive?: boolean\n search?: string\n}\n\n// ============================================\n// API Client Configuration\n// ============================================\n\ninterface FormsApiConfig {\n baseUrl: string\n apiKey?: string\n getAuthToken?: () => Promise<string> | string\n}\n\nlet config: FormsApiConfig | null = null\n\n/**\n * Configure the forms API client\n */\nexport function configureFormsApi(options: FormsApiConfig) {\n config = options\n}\n\n/**\n * Get API config, falling back to SiteKitProvider globals\n */\nfunction getConfig(): FormsApiConfig {\n if (config) return config\n \n // Try to get from window globals (set by SiteKitProvider)\n if (typeof window !== 'undefined') {\n const apiUrl = (window as any).__SITE_KIT_API_URL__\n const apiKey = (window as any).__SITE_KIT_API_KEY__\n \n if (apiUrl && apiKey) {\n return { baseUrl: apiUrl, apiKey }\n }\n }\n \n throw new Error(\n 'Forms API not configured. Either wrap your app in SiteKitProvider or call configureFormsApi() first.'\n )\n}\n\n// ============================================\n// HTTP Helpers\n// ============================================\n\nasync function apiRequest<T>(\n method: 'GET' | 'POST' | 'PUT' | 'DELETE',\n path: string,\n body?: any\n): Promise<T> {\n const { baseUrl, apiKey, getAuthToken } = getConfig()\n \n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n \n // Use API key for public endpoints, auth token for admin endpoints\n if (apiKey) {\n headers['x-api-key'] = apiKey\n } else if (getAuthToken) {\n const token = await getAuthToken()\n headers['Authorization'] = `Bearer ${token}`\n }\n \n const response = await fetch(`${baseUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n })\n \n if (!response.ok) {\n const error = await response.json().catch(() => ({ message: response.statusText }))\n throw new Error(error.message || `API error: ${response.status}`)\n }\n \n if (response.status === 204) {\n return undefined as T\n }\n \n return response.json()\n}\n\n// ============================================\n// Forms API\n// ============================================\n\nexport const formsApi = {\n /**\n * List all forms for a project\n */\n async list(options: FormsListOptions = {}): Promise<Form[]> {\n const params = new URLSearchParams()\n if (options.projectId) params.set('projectId', options.projectId)\n if (options.formType) params.set('formType', options.formType)\n if (options.isActive !== undefined) params.set('isActive', String(options.isActive))\n if (options.search) params.set('search', options.search)\n \n const query = params.toString()\n const result = await apiRequest<{ data: Form[] }>('GET', `/forms${query ? `?${query}` : ''}`)\n return result.data\n },\n \n /**\n * Get a single form by ID or slug\n */\n async get(idOrSlug: string): Promise<Form> {\n return apiRequest<Form>('GET', `/forms/${idOrSlug}`)\n },\n \n /**\n * Create a new form\n */\n async create(input: CreateFormInput): Promise<Form> {\n return apiRequest<Form>('POST', '/forms', input)\n },\n \n /**\n * Update an existing form\n */\n async update(id: string, input: UpdateFormInput): Promise<Form> {\n return apiRequest<Form>('PUT', `/forms/${id}`, input)\n },\n \n /**\n * Delete a form\n */\n async delete(id: string): Promise<void> {\n return apiRequest<void>('DELETE', `/forms/${id}`)\n },\n \n /**\n * Add a field to an existing form\n */\n async addField(formId: string, field: FormField): Promise<Form> {\n const form = await formsApi.get(formId)\n const maxSortOrder = Math.max(0, ...(form.fields || []).map(f => f.sortOrder || 0))\n \n return formsApi.update(formId, {\n fields: [\n ...(form.fields || []),\n { ...field, sortOrder: field.sortOrder ?? maxSortOrder + 1 }\n ]\n })\n },\n \n /**\n * Update a field in an existing form\n */\n async updateField(formId: string, fieldSlug: string, updates: Partial<FormField>): Promise<Form> {\n const form = await formsApi.get(formId)\n \n return formsApi.update(formId, {\n fields: (form.fields || []).map(f => \n f.slug === fieldSlug ? { ...f, ...updates } : f\n )\n })\n },\n \n /**\n * Remove a field from a form\n */\n async removeField(formId: string, fieldSlug: string): Promise<Form> {\n const form = await formsApi.get(formId)\n \n return formsApi.update(formId, {\n fields: (form.fields || []).filter(f => f.slug !== fieldSlug)\n })\n },\n \n /**\n * Reorder fields in a form\n */\n async reorderFields(formId: string, fieldSlugs: string[]): Promise<Form> {\n const form = await formsApi.get(formId)\n const fieldsMap = new Map((form.fields || []).map(f => [f.slug, f]))\n \n const orderedFields = fieldSlugs.map((slug, index) => {\n const field = fieldsMap.get(slug)\n if (!field) throw new Error(`Field not found: ${slug}`)\n return { ...field, sortOrder: index }\n })\n \n return formsApi.update(formId, { fields: orderedFields })\n },\n \n /**\n * Clone a form\n */\n async clone(formId: string, newSlug: string, newName?: string): Promise<Form> {\n const form = await formsApi.get(formId)\n \n return formsApi.create({\n projectId: form.projectId,\n slug: newSlug,\n name: newName || `${form.name} (Copy)`,\n description: form.description,\n formType: form.formType,\n successMessage: form.successMessage,\n redirectUrl: form.redirectUrl,\n notificationEmails: form.notificationEmails,\n submitButtonText: form.submitButtonText,\n layout: form.layout,\n showProgress: form.showProgress,\n enableSaveDraft: form.enableSaveDraft,\n isActive: false, // Clone as inactive\n fields: (form.fields || []).map(({ id, ...field }) => field), // Remove IDs\n steps: (form.steps || []).map(({ id, ...step }) => step), // Remove IDs\n })\n },\n \n /**\n * Activate or deactivate a form\n */\n async setActive(formId: string, isActive: boolean): Promise<Form> {\n return formsApi.update(formId, { isActive })\n },\n}\n\n// ============================================\n// Field Builder Helpers\n// ============================================\n\n/**\n * Helper functions to build field definitions\n */\nexport const field = {\n text: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'text',\n ...options,\n }),\n \n email: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'email',\n isRequired: true,\n ...options,\n }),\n \n phone: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'phone',\n ...options,\n }),\n \n textarea: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'textarea',\n ...options,\n }),\n \n select: (slug: string, label: string, choices: Array<{ value: string; label: string }>, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'select',\n options: choices,\n ...options,\n }),\n \n radio: (slug: string, label: string, choices: Array<{ value: string; label: string }>, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'radio',\n options: choices,\n ...options,\n }),\n \n checkbox: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'checkbox',\n ...options,\n }),\n \n date: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'date',\n ...options,\n }),\n \n number: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'number',\n ...options,\n }),\n \n rating: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'rating',\n ...options,\n }),\n \n file: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'file',\n ...options,\n }),\n \n hidden: (slug: string, defaultValue: string): FormField => ({\n slug,\n label: '',\n fieldType: 'hidden',\n defaultValue,\n }),\n \n heading: (slug: string, label: string): FormField => ({\n slug,\n label,\n fieldType: 'heading',\n }),\n \n paragraph: (slug: string, label: string): FormField => ({\n slug,\n label,\n fieldType: 'paragraph',\n }),\n}\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/forms/formsApi.ts"],"names":["field"],"mappings":"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","file":"chunk-RV7H3I6J.js","sourcesContent":["/**\n * @uptrade/site-kit/forms - Forms API Client\n * \n * Full API client for form management. Allows developers to create, update,\n * and delete forms programmatically. Changes sync to Portal automatically.\n * \n * @example\n * ```tsx\n * import { formsApi } from '@uptrade/site-kit/forms'\n * \n * // Create a new form\n * const form = await formsApi.create({\n * projectId: 'xxx',\n * slug: 'contact-us',\n * name: 'Contact Form',\n * formType: 'prospect',\n * fields: [\n * { slug: 'name', label: 'Name', fieldType: 'text', isRequired: true },\n * { slug: 'email', label: 'Email', fieldType: 'email', isRequired: true },\n * { slug: 'message', label: 'Message', fieldType: 'textarea' },\n * ]\n * })\n * \n * // Update fields\n * await formsApi.update(form.id, {\n * fields: [...form.fields, { slug: 'phone', label: 'Phone', fieldType: 'phone' }]\n * })\n * ```\n */\n\n// ============================================\n// Types\n// ============================================\n\nexport type FormType = \n | 'prospect' // → CRM leads\n | 'contact' // → Contact form\n | 'support' // → Support tickets\n | 'feedback' // → Feedback entries\n | 'newsletter' // → Email subscribers\n | 'custom' // → Custom webhook\n\nexport type FieldType =\n | 'text'\n | 'email'\n | 'phone'\n | 'number'\n | 'textarea'\n | 'select'\n | 'multi_select'\n | 'radio'\n | 'checkbox'\n | 'date'\n | 'time'\n | 'datetime'\n | 'url'\n | 'file'\n | 'rating'\n | 'slider'\n | 'hidden'\n | 'heading'\n | 'paragraph'\n\nexport type FieldWidth = 'full' | 'half' | 'third' | 'quarter'\n\nexport interface FieldOption {\n value: string\n label: string\n disabled?: boolean\n}\n\nexport interface FieldValidation {\n min?: number\n max?: number\n minLength?: number\n maxLength?: number\n pattern?: string\n patternMessage?: string\n}\n\nexport interface FieldConditional {\n field: string\n operator: 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'is_empty' | 'not_empty' | 'greater_than' | 'less_than'\n value?: string | number | boolean\n}\n\nexport interface FormField {\n id?: string\n slug: string\n label: string\n fieldType: FieldType\n placeholder?: string\n helpText?: string\n defaultValue?: string\n isRequired?: boolean\n validation?: FieldValidation\n options?: FieldOption[]\n conditional?: FieldConditional\n width?: FieldWidth\n sortOrder?: number\n destinationField?: string\n stepId?: string\n}\n\nexport interface FormStep {\n id?: string\n stepNumber: number\n title?: string\n description?: string\n condition?: FieldConditional\n}\n\nexport interface Form {\n id: string\n projectId: string\n slug: string\n name: string\n description?: string\n formType: FormType\n successMessage: string\n redirectUrl?: string\n notificationEmails?: string[]\n submitButtonText: string\n layout: 'stacked' | 'inline' | 'grid'\n showProgress: boolean\n enableSaveDraft: boolean\n isActive: boolean\n createdAt: string\n updatedAt: string\n fields?: FormField[]\n steps?: FormStep[]\n}\n\nexport interface CreateFormInput {\n projectId: string\n slug: string\n name: string\n description?: string\n formType?: FormType\n successMessage?: string\n redirectUrl?: string\n notificationEmails?: string[]\n submitButtonText?: string\n layout?: 'stacked' | 'inline' | 'grid'\n showProgress?: boolean\n enableSaveDraft?: boolean\n isActive?: boolean\n fields?: FormField[]\n steps?: FormStep[]\n}\n\nexport interface UpdateFormInput {\n slug?: string\n name?: string\n description?: string\n formType?: FormType\n successMessage?: string\n redirectUrl?: string\n notificationEmails?: string[]\n submitButtonText?: string\n layout?: 'stacked' | 'inline' | 'grid'\n showProgress?: boolean\n enableSaveDraft?: boolean\n isActive?: boolean\n fields?: FormField[]\n steps?: FormStep[]\n}\n\nexport interface FormsListOptions {\n projectId?: string\n formType?: FormType\n isActive?: boolean\n search?: string\n}\n\n// ============================================\n// API Client Configuration\n// ============================================\n\ninterface FormsApiConfig {\n baseUrl: string\n apiKey?: string\n getAuthToken?: () => Promise<string> | string\n}\n\nlet config: FormsApiConfig | null = null\n\n/**\n * Configure the forms API client\n */\nexport function configureFormsApi(options: FormsApiConfig) {\n config = options\n}\n\n/**\n * Get API config, falling back to SiteKitProvider globals\n */\nfunction getConfig(): FormsApiConfig {\n if (config) return config\n \n // Try to get from window globals (set by SiteKitProvider)\n if (typeof window !== 'undefined') {\n const apiUrl = (window as any).__SITE_KIT_API_URL__\n const apiKey = (window as any).__SITE_KIT_API_KEY__\n \n if (apiUrl && apiKey) {\n return { baseUrl: apiUrl, apiKey }\n }\n }\n \n throw new Error(\n 'Forms API not configured. Either wrap your app in SiteKitProvider or call configureFormsApi() first.'\n )\n}\n\n// ============================================\n// HTTP Helpers\n// ============================================\n\nasync function apiRequest<T>(\n method: 'GET' | 'POST' | 'PUT' | 'DELETE',\n path: string,\n body?: any\n): Promise<T> {\n const { baseUrl, apiKey, getAuthToken } = getConfig()\n \n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n \n // Use API key for public endpoints, auth token for admin endpoints\n if (apiKey) {\n headers['x-api-key'] = apiKey\n } else if (getAuthToken) {\n const token = await getAuthToken()\n headers['Authorization'] = `Bearer ${token}`\n }\n \n const response = await fetch(`${baseUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n })\n \n if (!response.ok) {\n const error = await response.json().catch(() => ({ message: response.statusText }))\n throw new Error(error.message || `API error: ${response.status}`)\n }\n \n if (response.status === 204) {\n return undefined as T\n }\n \n return response.json()\n}\n\n// ============================================\n// Forms API\n// ============================================\n\nexport const formsApi = {\n /**\n * List all forms for a project\n */\n async list(options: FormsListOptions = {}): Promise<Form[]> {\n const params = new URLSearchParams()\n if (options.projectId) params.set('projectId', options.projectId)\n if (options.formType) params.set('formType', options.formType)\n if (options.isActive !== undefined) params.set('isActive', String(options.isActive))\n if (options.search) params.set('search', options.search)\n \n const query = params.toString()\n const result = await apiRequest<{ data: Form[] }>('GET', `/forms${query ? `?${query}` : ''}`)\n return result.data\n },\n \n /**\n * Get a single form by ID or slug\n */\n async get(idOrSlug: string): Promise<Form> {\n return apiRequest<Form>('GET', `/forms/${idOrSlug}`)\n },\n \n /**\n * Create a new form\n */\n async create(input: CreateFormInput): Promise<Form> {\n return apiRequest<Form>('POST', '/forms', input)\n },\n \n /**\n * Update an existing form\n */\n async update(id: string, input: UpdateFormInput): Promise<Form> {\n return apiRequest<Form>('PUT', `/forms/${id}`, input)\n },\n \n /**\n * Delete a form\n */\n async delete(id: string): Promise<void> {\n return apiRequest<void>('DELETE', `/forms/${id}`)\n },\n \n /**\n * Add a field to an existing form\n */\n async addField(formId: string, field: FormField): Promise<Form> {\n const form = await formsApi.get(formId)\n const maxSortOrder = Math.max(0, ...(form.fields || []).map(f => f.sortOrder || 0))\n \n return formsApi.update(formId, {\n fields: [\n ...(form.fields || []),\n { ...field, sortOrder: field.sortOrder ?? maxSortOrder + 1 }\n ]\n })\n },\n \n /**\n * Update a field in an existing form\n */\n async updateField(formId: string, fieldSlug: string, updates: Partial<FormField>): Promise<Form> {\n const form = await formsApi.get(formId)\n \n return formsApi.update(formId, {\n fields: (form.fields || []).map(f => \n f.slug === fieldSlug ? { ...f, ...updates } : f\n )\n })\n },\n \n /**\n * Remove a field from a form\n */\n async removeField(formId: string, fieldSlug: string): Promise<Form> {\n const form = await formsApi.get(formId)\n \n return formsApi.update(formId, {\n fields: (form.fields || []).filter(f => f.slug !== fieldSlug)\n })\n },\n \n /**\n * Reorder fields in a form\n */\n async reorderFields(formId: string, fieldSlugs: string[]): Promise<Form> {\n const form = await formsApi.get(formId)\n const fieldsMap = new Map((form.fields || []).map(f => [f.slug, f]))\n \n const orderedFields = fieldSlugs.map((slug, index) => {\n const field = fieldsMap.get(slug)\n if (!field) throw new Error(`Field not found: ${slug}`)\n return { ...field, sortOrder: index }\n })\n \n return formsApi.update(formId, { fields: orderedFields })\n },\n \n /**\n * Clone a form\n */\n async clone(formId: string, newSlug: string, newName?: string): Promise<Form> {\n const form = await formsApi.get(formId)\n \n return formsApi.create({\n projectId: form.projectId,\n slug: newSlug,\n name: newName || `${form.name} (Copy)`,\n description: form.description,\n formType: form.formType,\n successMessage: form.successMessage,\n redirectUrl: form.redirectUrl,\n notificationEmails: form.notificationEmails,\n submitButtonText: form.submitButtonText,\n layout: form.layout,\n showProgress: form.showProgress,\n enableSaveDraft: form.enableSaveDraft,\n isActive: false, // Clone as inactive\n fields: (form.fields || []).map(({ id, ...field }) => field), // Remove IDs\n steps: (form.steps || []).map(({ id, ...step }) => step), // Remove IDs\n })\n },\n \n /**\n * Activate or deactivate a form\n */\n async setActive(formId: string, isActive: boolean): Promise<Form> {\n return formsApi.update(formId, { isActive })\n },\n}\n\n// ============================================\n// Field Builder Helpers\n// ============================================\n\n/**\n * Helper functions to build field definitions\n */\nexport const field = {\n text: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'text',\n ...options,\n }),\n \n email: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'email',\n isRequired: true,\n ...options,\n }),\n \n phone: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'phone',\n ...options,\n }),\n \n textarea: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'textarea',\n ...options,\n }),\n \n select: (slug: string, label: string, choices: Array<{ value: string; label: string }>, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'select',\n options: choices,\n ...options,\n }),\n \n radio: (slug: string, label: string, choices: Array<{ value: string; label: string }>, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'radio',\n options: choices,\n ...options,\n }),\n \n checkbox: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'checkbox',\n ...options,\n }),\n \n date: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'date',\n ...options,\n }),\n \n number: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'number',\n ...options,\n }),\n \n rating: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'rating',\n ...options,\n }),\n \n file: (slug: string, label: string, options?: Partial<FormField>): FormField => ({\n slug,\n label,\n fieldType: 'file',\n ...options,\n }),\n \n hidden: (slug: string, defaultValue: string): FormField => ({\n slug,\n label: '',\n fieldType: 'hidden',\n defaultValue,\n }),\n \n heading: (slug: string, label: string): FormField => ({\n slug,\n label,\n fieldType: 'heading',\n }),\n \n paragraph: (slug: string, label: string): FormField => ({\n slug,\n label,\n fieldType: 'paragraph',\n }),\n}\n"]}
@@ -0,0 +1,140 @@
1
+ 'use strict';
2
+
3
+ var chunkQP5NCO2E_js = require('./chunk-QP5NCO2E.js');
4
+
5
+ // src/seo/routing.ts
6
+ async function getRedirect(options) {
7
+ const { projectId, path } = options;
8
+ const redirect = await chunkQP5NCO2E_js.getRedirectData(projectId, path);
9
+ if (!redirect) {
10
+ return null;
11
+ }
12
+ if (redirect.expires_at && new Date(redirect.expires_at) < /* @__PURE__ */ new Date()) {
13
+ return null;
14
+ }
15
+ const destination = redirect.destination_url || redirect.destination_path;
16
+ const isExternal = destination.startsWith("http://") || destination.startsWith("https://");
17
+ return {
18
+ destination,
19
+ statusCode: redirect.status_code,
20
+ isExternal
21
+ };
22
+ }
23
+ function parseRobotsString(robots) {
24
+ const directive = {
25
+ index: true,
26
+ follow: true
27
+ };
28
+ const parts = robots.toLowerCase().split(",").map((p) => p.trim());
29
+ for (const part of parts) {
30
+ if (part === "noindex") directive.index = false;
31
+ if (part === "nofollow") directive.follow = false;
32
+ if (part === "noarchive") directive.noarchive = true;
33
+ if (part === "nosnippet") directive.nosnippet = true;
34
+ if (part === "noimageindex") directive.noimageindex = true;
35
+ if (part.startsWith("max-snippet:")) {
36
+ directive.max_snippet = parseInt(part.split(":")[1], 10);
37
+ }
38
+ if (part.startsWith("max-image-preview:")) {
39
+ const value = part.split(":")[1];
40
+ directive.max_image_preview = value;
41
+ }
42
+ if (part.startsWith("max-video-preview:")) {
43
+ directive.max_video_preview = parseInt(part.split(":")[1], 10);
44
+ }
45
+ }
46
+ return directive;
47
+ }
48
+ async function getRobotsDirective(options) {
49
+ const { projectId, path } = options;
50
+ const robotsString = await chunkQP5NCO2E_js.getRobotsData(projectId, path);
51
+ if (!robotsString) {
52
+ return { index: true, follow: true };
53
+ }
54
+ return parseRobotsString(robotsString);
55
+ }
56
+ async function generateSitemap(options) {
57
+ const { projectId, baseUrl, publishedOnly = true } = options;
58
+ const pages = await chunkQP5NCO2E_js.getSitemapEntries(projectId, { publishedOnly });
59
+ const normalizedBase = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
60
+ return pages.map((page) => ({
61
+ path: page.path,
62
+ url: `${normalizedBase}${page.path}`,
63
+ lastmod: page.updated_at,
64
+ changefreq: page.sitemap_changefreq || "weekly",
65
+ priority: page.sitemap_priority || 0.5
66
+ }));
67
+ }
68
+ async function registerLocalSitemap(options) {
69
+ const { registerSitemap } = await import('./api-N35S3EES.js');
70
+ let entries = options.entries || [];
71
+ if (options.autoDiscover && entries.length === 0) {
72
+ try {
73
+ const fs = await import('fs');
74
+ const path = await import('path');
75
+ const appDir = path.join(process.cwd(), "app");
76
+ if (fs.existsSync(appDir)) {
77
+ entries = discoverNextJsRoutes(appDir, fs, path);
78
+ console.log(`[Uptrade] Auto-discovered ${entries.length} routes from app directory`);
79
+ }
80
+ } catch (error) {
81
+ console.error("[Uptrade] Auto-discovery failed:", error);
82
+ }
83
+ }
84
+ if (entries.length === 0) {
85
+ console.warn("[Uptrade] No sitemap entries to register");
86
+ return { success: true, created: 0, updated: 0 };
87
+ }
88
+ console.log(`[Uptrade] Registering ${entries.length} sitemap entries...`);
89
+ const result = await registerSitemap(entries);
90
+ if (result.success) {
91
+ console.log(`[Uptrade] Sitemap registered: ${result.created} new, ${result.updated} updated`);
92
+ }
93
+ return result;
94
+ }
95
+ function discoverNextJsRoutes(appDir, fs, path, basePath = "") {
96
+ const entries = [];
97
+ const items = fs.readdirSync(appDir, { withFileTypes: true });
98
+ for (const item of items) {
99
+ if (item.name.startsWith("_") || item.name.startsWith(".")) continue;
100
+ if (item.name === "api") continue;
101
+ if (item.name === "node_modules") continue;
102
+ const itemPath = path.join(appDir, item.name);
103
+ if (item.isDirectory()) {
104
+ const hasPage = fs.existsSync(path.join(itemPath, "page.tsx")) || fs.existsSync(path.join(itemPath, "page.js")) || fs.existsSync(path.join(itemPath, "page.jsx"));
105
+ const isRouteGroup = item.name.startsWith("(") && item.name.endsWith(")");
106
+ const isDynamic = item.name.startsWith("[") && item.name.endsWith("]");
107
+ let routePath = basePath;
108
+ if (!isRouteGroup && !isDynamic) {
109
+ routePath = `${basePath}/${item.name}`;
110
+ }
111
+ if (hasPage && !isDynamic) {
112
+ const priority = routePath === "" ? 1 : 0.8;
113
+ entries.push({ path: routePath || "/", priority });
114
+ }
115
+ if (!isDynamic) {
116
+ const subEntries = discoverNextJsRoutes(itemPath, fs, path, isRouteGroup ? basePath : routePath);
117
+ entries.push(...subEntries);
118
+ }
119
+ }
120
+ }
121
+ if (basePath === "") {
122
+ const hasRootPage = fs.existsSync(path.join(appDir, "page.tsx")) || fs.existsSync(path.join(appDir, "page.js")) || fs.existsSync(path.join(appDir, "page.jsx"));
123
+ if (hasRootPage) {
124
+ entries.unshift({ path: "/", priority: 1 });
125
+ }
126
+ }
127
+ return entries;
128
+ }
129
+ async function isIndexable(projectId, path) {
130
+ const directive = await getRobotsDirective({ projectId, path });
131
+ return directive.index;
132
+ }
133
+
134
+ exports.generateSitemap = generateSitemap;
135
+ exports.getRedirect = getRedirect;
136
+ exports.getRobotsDirective = getRobotsDirective;
137
+ exports.isIndexable = isIndexable;
138
+ exports.registerLocalSitemap = registerLocalSitemap;
139
+ //# sourceMappingURL=chunk-SBVEYCSV.js.map
140
+ //# sourceMappingURL=chunk-SBVEYCSV.js.map