@sampleapp.ai/sdk 1.0.35 → 1.0.37

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 (96) hide show
  1. package/dist/components/sandbox/Sandbox.js +20 -8
  2. package/dist/components/sandbox/api.js +3 -2
  3. package/dist/components/sandbox/guardian/ask-ai-view.js +4 -4
  4. package/dist/components/sandbox/guardian/default-guide-view.js +1 -1
  5. package/dist/components/sandbox/guardian/demo/left-view.js +2 -2
  6. package/dist/components/sandbox/guardian/guardian-component.js +7 -38
  7. package/dist/components/sandbox/guardian/guardian-playground.js +3 -3
  8. package/dist/components/sandbox/guardian/guardian-style-wrapper.js +21 -2
  9. package/dist/components/sandbox/guardian/hooks/use-sandbox-url-loader.js +12 -10
  10. package/dist/components/sandbox/guardian/ide/browser.js +30 -30
  11. package/dist/components/sandbox/guardian/index.js +1 -1
  12. package/dist/components/sandbox/guardian/right-view/preview-control-bar.js +3 -3
  13. package/dist/components/sandbox/guardian/right-view/right-top-down-view.js +2 -2
  14. package/dist/components/sandbox/guardian/ui/download-and-open-buttons.js +1 -1
  15. package/dist/components/sandbox/guardian/ui/markdown/code-group/code-block.js +48 -11
  16. package/dist/components/sandbox/guardian/ui/markdown.js +3 -3
  17. package/dist/components/sandbox/guardian/utils.js +0 -18
  18. package/dist/components/sandbox/index.js +1 -1
  19. package/dist/components/sandbox/sandbox-home/SandboxCard.js +4 -4
  20. package/dist/components/sandbox/sandbox-home/SandboxHome.js +14 -9
  21. package/dist/components/sandbox/sandbox-home/SearchBar.js +2 -2
  22. package/dist/index.d.ts +29 -42
  23. package/dist/index.es.js +8208 -7715
  24. package/dist/index.js +1 -1
  25. package/dist/index.standalone.umd.js +1 -1
  26. package/dist/lib/api-client.js +9 -26
  27. package/dist/lib/generated-css.js +1 -1
  28. package/dist/sdk.css +1 -1
  29. package/dist/tailwind.css +1 -1
  30. package/package.json +1 -1
  31. package/dist/components/guardian/app-layout-no-sidebar.js +0 -8
  32. package/dist/components/guardian/ask-ai-view.js +0 -249
  33. package/dist/components/guardian/code-focus-section.d.ts +0 -41
  34. package/dist/components/guardian/code-focus-section.js +0 -174
  35. package/dist/components/guardian/context/guardian-context.js +0 -94
  36. package/dist/components/guardian/context/vm-context.js +0 -28
  37. package/dist/components/guardian/default-guide-view.js +0 -34
  38. package/dist/components/guardian/demo/guardian-demo.js +0 -35
  39. package/dist/components/guardian/demo/left-view/toggle.js +0 -28
  40. package/dist/components/guardian/demo/left-view.js +0 -49
  41. package/dist/components/guardian/guardian-component.js +0 -79
  42. package/dist/components/guardian/guardian-demo.js +0 -35
  43. package/dist/components/guardian/guardian-home.d.ts +0 -4
  44. package/dist/components/guardian/guardian-home.js +0 -61
  45. package/dist/components/guardian/guardian-playground.js +0 -45
  46. package/dist/components/guardian/guardian-style-wrapper.js +0 -29
  47. package/dist/components/guardian/guardian-upload-spec.d.ts +0 -14
  48. package/dist/components/guardian/guardian-upload-spec.js +0 -160
  49. package/dist/components/guardian/header/glassmorphic-combobox.d.ts +0 -15
  50. package/dist/components/guardian/header/glassmorphic-combobox.js +0 -30
  51. package/dist/components/guardian/header.js +0 -61
  52. package/dist/components/guardian/hooks/use-frame-messages.js +0 -65
  53. package/dist/components/guardian/hooks/use-frame-params.js +0 -44
  54. package/dist/components/guardian/hooks/use-sandbox-url-loader.js +0 -101
  55. package/dist/components/guardian/ide/browser.js +0 -538
  56. package/dist/components/guardian/index.js +0 -8
  57. package/dist/components/guardian/layout/app-layout-no-sidebar.js +0 -8
  58. package/dist/components/guardian/layout/header/glassmorphic-combobox.js +0 -48
  59. package/dist/components/guardian/layout/header.js +0 -63
  60. package/dist/components/guardian/right-view/code-view.js +0 -56
  61. package/dist/components/guardian/right-view/pill-file-selector.js +0 -233
  62. package/dist/components/guardian/right-view/preview-control-bar.js +0 -25
  63. package/dist/components/guardian/right-view/right-panel-view.js +0 -38
  64. package/dist/components/guardian/right-view/right-top-down-view.js +0 -289
  65. package/dist/components/guardian/right-view/right-view.js +0 -28
  66. package/dist/components/guardian/right-view/simplified-editor.js +0 -234
  67. package/dist/components/guardian/types/ide-types.js +0 -162
  68. package/dist/components/guardian/types.js +0 -3
  69. package/dist/components/guardian/ui/ai-loader.js +0 -48
  70. package/dist/components/guardian/ui/badge.js +0 -24
  71. package/dist/components/guardian/ui/button.js +0 -45
  72. package/dist/components/guardian/ui/command.js +0 -63
  73. package/dist/components/guardian/ui/console-with-app.js +0 -17
  74. package/dist/components/guardian/ui/dialog.js +0 -57
  75. package/dist/components/guardian/ui/dropdown-menu.js +0 -82
  76. package/dist/components/guardian/ui/markdown.js +0 -57
  77. package/dist/components/guardian/ui/popover.js +0 -25
  78. package/dist/components/guardian/ui/tooltip.js +0 -25
  79. package/dist/components/guardian/utils.js +0 -88
  80. package/dist/components/guardian/zip-to-codebase.js +0 -246
  81. package/dist/components/guardian/zip-to-filetree.js +0 -284
  82. package/dist/components/sandbox/SandboxHome.js +0 -141
  83. package/dist/components/sandbox/guardian/guardian-demo.js +0 -35
  84. package/dist/components/sandbox/guardian/guardian-home.d.ts +0 -4
  85. package/dist/components/sandbox/guardian/guardian-home.js +0 -61
  86. package/dist/components/sandbox/guardian/guardian-upload-spec.d.ts +0 -14
  87. package/dist/components/sandbox/guardian/guardian-upload-spec.js +0 -160
  88. package/dist/components/sandbox/guardian/ui/theme-color-context.d.ts +0 -6
  89. package/dist/components/sandbox/sandbox-control-bar.js +0 -91
  90. package/dist/components/sandbox/sandbox-header.js +0 -52
  91. package/dist/components/sandbox/sandbox-left-panel.js +0 -248
  92. package/dist/components/sandbox/sandbox-loading.js +0 -48
  93. package/dist/components/sandbox/sandbox-right-panel.js +0 -247
  94. package/dist/components/sandbox.js +0 -32
  95. package/dist/lib/api-client.example.js +0 -60
  96. package/dist/lib/ssr-safe-decode-entity.js +0 -16
@@ -1,88 +0,0 @@
1
- import { FrameworkLabel, } from "./types/ide-types";
2
- /**
3
- * Creates sandbox URL configs for preloading from a framework's urlsToPreload.
4
- * Only includes URLs that need VM preloading (useVm: true).
5
- * Uses the same sandboxUid for all configs since caching is done by sandboxUid + browserUrl.
6
- */
7
- export function createSandboxUrlConfigs(sandboxUid, urlsToPreload) {
8
- if (!urlsToPreload) {
9
- return [];
10
- }
11
- return urlsToPreload
12
- .filter((config) => config.useVm)
13
- .map((config) => ({
14
- sandboxUid: config.suffix ? `${sandboxUid}-${config.suffix}` : sandboxUid,
15
- browserUrl: config.browserUrl,
16
- useVm: config.useVm,
17
- }));
18
- }
19
- /**
20
- * Builds a nested GuardianConfig from use cases with nested frameworks.
21
- * Returns a structure where config[useCaseId].frameworks[frameworkKey] gives you the full config.
22
- *
23
- * @example
24
- * const config = buildGuardianConfig(USE_CASES, options);
25
- * // Access via: config["full-stack-auth"].frameworks["nextjs"]
26
- */
27
- export function buildGuardianConfig(useCases, options) {
28
- var _a;
29
- const { playgroundUid, playgroundLogo, frameworkLabels, variant } = options;
30
- const result = {};
31
- for (const uc of useCases) {
32
- // Build the use case config
33
- const useCaseConfig = {
34
- id: uc.id,
35
- name: uc.name,
36
- description: uc.description,
37
- themeColor: uc.themeColor,
38
- hasPreview: uc.hasPreview,
39
- frameworks: {},
40
- };
41
- // Compute frameworkOptions from ALL frameworks in this use case
42
- const frameworkOptions = uc.frameworks.map((fw) => {
43
- var _a, _b;
44
- return ({
45
- label: (_b = (_a = (frameworkLabels && frameworkLabels[fw.key])) !== null && _a !== void 0 ? _a : FrameworkLabel[fw.key]) !== null && _b !== void 0 ? _b : fw.key,
46
- value: fw.key,
47
- });
48
- });
49
- // Add each framework to the use case
50
- for (const fw of uc.frameworks) {
51
- useCaseConfig.frameworks[fw.key] = {
52
- frameworkKey: fw.key,
53
- name: uc.name,
54
- description: uc.description,
55
- demoOptions: [], // Will be populated below
56
- frameworkOptions,
57
- firstFrameworkByUseCase: undefined, // Will be passed from guardian-playground
58
- currentFramework: fw.key,
59
- CustomConsole: fw.CustomConsole,
60
- GuideView: fw.GuideView,
61
- playgroundUid,
62
- playgroundLogo,
63
- browserUrl: fw.browserUrl,
64
- useVm: fw.useVm,
65
- sandboxUid: fw.sandboxUid,
66
- codeZipFile: fw.codeZipFile,
67
- completeCodeZipFile: fw.completeCodeZipFile,
68
- consoleUrlConfigs: createSandboxUrlConfigs(fw.sandboxUid, fw.urlsToPreload),
69
- themeColor: (_a = fw.themeColor) !== null && _a !== void 0 ? _a : uc.themeColor,
70
- variant,
71
- hasPreview: uc.hasPreview,
72
- };
73
- }
74
- result[uc.id] = useCaseConfig;
75
- }
76
- // Now populate demoOptions for all frameworks (they all get the same list)
77
- const demoOptions = useCases.map((uc) => ({
78
- label: uc.name,
79
- value: uc.id, // Use the use case ID as the value
80
- }));
81
- // Update all framework configs with the complete demoOptions
82
- for (const useCaseConfig of Object.values(result)) {
83
- for (const frameworkConfig of Object.values(useCaseConfig.frameworks)) {
84
- frameworkConfig.demoOptions = demoOptions;
85
- }
86
- }
87
- return result;
88
- }
@@ -1,246 +0,0 @@
1
- import JSZip from "jszip";
2
- import { filePathToCodeLanguage } from "./types/ide-types";
3
- /**
4
- * Converts a zip file to UpdateContainerCodebaseType (flat Record structure)
5
- * @param zipData - The zip file as Blob, File, ArrayBuffer, or Uint8Array
6
- * @returns Promise<UpdateContainerCodebaseType> - A flat record of file paths to CodeOutput
7
- */
8
- export async function zipToCodebase(zipData) {
9
- try {
10
- const zip = await JSZip.loadAsync(zipData);
11
- const codebase = {};
12
- // Get all file paths (excluding directories and __MACOSX)
13
- const filePaths = Object.keys(zip.files).filter((path) => {
14
- const file = zip.files[path];
15
- return (!file.dir &&
16
- !path.includes("__MACOSX") &&
17
- !path.includes("__pycache__") &&
18
- !path.includes(".DS_Store") &&
19
- !path.startsWith("._") &&
20
- !path.includes("/._"));
21
- });
22
- // Find common root folder prefix
23
- let commonPrefix = "";
24
- if (filePaths.length > 0) {
25
- // Get the first path's root folder
26
- const firstPath = filePaths[0];
27
- const firstSlashIndex = firstPath.indexOf("/");
28
- if (firstSlashIndex > 0) {
29
- const potentialPrefix = firstPath.substring(0, firstSlashIndex + 1);
30
- // Check if all paths start with this prefix
31
- const allHavePrefix = filePaths.every((path) => path.startsWith(potentialPrefix));
32
- if (allHavePrefix) {
33
- commonPrefix = potentialPrefix;
34
- }
35
- }
36
- }
37
- // Process all files in the zip
38
- const filePromises = [];
39
- for (const relativePath of filePaths) {
40
- const file = zip.files[relativePath];
41
- // Get file content as text
42
- const contentPromise = file
43
- .async("string")
44
- .then((content) => {
45
- // Strip common prefix from the file path
46
- let filePath = relativePath;
47
- if (commonPrefix && filePath.startsWith(commonPrefix)) {
48
- filePath = filePath.substring(commonPrefix.length);
49
- }
50
- const fileName = filePath.split("/").pop() || filePath;
51
- const codeLanguage = filePathToCodeLanguage(filePath);
52
- codebase[filePath] = {
53
- response_type: "CodeOutput",
54
- file_path: filePath,
55
- code_file_name: fileName,
56
- code_language: codeLanguage,
57
- dependencies_to_install: [],
58
- framework: null,
59
- full_code: content,
60
- };
61
- })
62
- .catch((error) => {
63
- // If file can't be read as text, skip it or handle binary files
64
- console.warn(`Could not read file ${relativePath} as text:`, error);
65
- });
66
- filePromises.push(contentPromise);
67
- }
68
- // Wait for all files to be processed
69
- await Promise.all(filePromises);
70
- return codebase;
71
- }
72
- catch (error) {
73
- console.error("Error parsing zip file:", error);
74
- throw new Error(`Failed to parse zip file: ${error instanceof Error ? error.message : String(error)}`);
75
- }
76
- }
77
- /**
78
- * Converts a zip file to UpdateContainerCodebaseType with binary file support
79
- * Binary files will have their content as base64 encoded strings
80
- * @param zipData - The zip file as Blob, File, ArrayBuffer, or Uint8Array
81
- * @returns Promise<UpdateContainerCodebaseType> - A flat record of file paths to CodeOutput
82
- */
83
- export async function zipToCodebaseWithBinary(zipData) {
84
- try {
85
- const zip = await JSZip.loadAsync(zipData);
86
- const codebase = {};
87
- // Get all file paths (excluding directories and __MACOSX)
88
- const filePaths = Object.keys(zip.files).filter((path) => {
89
- const file = zip.files[path];
90
- return (!file.dir &&
91
- !path.includes("__MACOSX") &&
92
- !path.includes("__pycache__") &&
93
- !path.includes(".DS_Store") &&
94
- !path.startsWith("._") &&
95
- !path.includes("/._"));
96
- });
97
- // Find common root folder prefix
98
- let commonPrefix = "";
99
- if (filePaths.length > 0) {
100
- // Get the first path's root folder
101
- const firstPath = filePaths[0];
102
- const firstSlashIndex = firstPath.indexOf("/");
103
- if (firstSlashIndex > 0) {
104
- const potentialPrefix = firstPath.substring(0, firstSlashIndex + 1);
105
- // Check if all paths start with this prefix
106
- const allHavePrefix = filePaths.every((path) => path.startsWith(potentialPrefix));
107
- if (allHavePrefix) {
108
- commonPrefix = potentialPrefix;
109
- }
110
- }
111
- }
112
- // Process all files in the zip
113
- const filePromises = [];
114
- for (const relativePath of filePaths) {
115
- const file = zip.files[relativePath];
116
- // Try to read as text first, fallback to base64 for binary files
117
- const contentPromise = (async () => {
118
- let content;
119
- try {
120
- // Try reading as text
121
- content = await file.async("string");
122
- }
123
- catch (_a) {
124
- // If that fails, read as base64
125
- const binary = await file.async("base64");
126
- content = binary;
127
- }
128
- // Strip common prefix from the file path
129
- let filePath = relativePath;
130
- if (commonPrefix && filePath.startsWith(commonPrefix)) {
131
- filePath = filePath.substring(commonPrefix.length);
132
- }
133
- const fileName = filePath.split("/").pop() || filePath;
134
- const codeLanguage = filePathToCodeLanguage(filePath);
135
- codebase[filePath] = {
136
- response_type: "CodeOutput",
137
- file_path: filePath,
138
- code_file_name: fileName,
139
- code_language: codeLanguage,
140
- dependencies_to_install: [],
141
- framework: null,
142
- full_code: content,
143
- };
144
- })();
145
- filePromises.push(contentPromise);
146
- }
147
- // Wait for all files to be processed
148
- await Promise.all(filePromises);
149
- return codebase;
150
- }
151
- catch (error) {
152
- console.error("Error parsing zip file:", error);
153
- throw new Error(`Failed to parse zip file: ${error instanceof Error ? error.message : String(error)}`);
154
- }
155
- }
156
- /**
157
- * Reads a zip file from a path and converts it to UpdateContainerCodebaseType
158
- * @param filePath - The path to the zip file (e.g., "/public/guardian/launchdarkly-guardian/code-1.zip" or "/guardian/launchdarkly-guardian/code-1.zip")
159
- * @returns Promise<UpdateContainerCodebaseType> - A flat record of file paths to CodeOutput
160
- */
161
- export async function zipPathToCodebase(filePath) {
162
- try {
163
- // Normalize the path - remove /public prefix if present (Next.js serves public folder from root)
164
- let normalizedPath = filePath;
165
- if (normalizedPath.startsWith("/public/")) {
166
- normalizedPath = normalizedPath.slice("/public".length);
167
- }
168
- // Ensure path starts with /
169
- if (!normalizedPath.startsWith("/")) {
170
- normalizedPath = "/" + normalizedPath;
171
- }
172
- // Build the URL - handle both client-side (relative) and server-side (absolute) cases
173
- let url;
174
- if (typeof window !== "undefined") {
175
- // Client-side: use relative URL
176
- url = normalizedPath;
177
- }
178
- else {
179
- // Server-side: need absolute URL
180
- // Try to get base URL from environment or use a default
181
- const baseUrl = process.env.NEXT_PUBLIC_BASE_URL ||
182
- process.env.VERCEL_URL ||
183
- "http://localhost:3000";
184
- url = `${baseUrl}${normalizedPath}`;
185
- }
186
- // Fetch the file from the public folder
187
- const response = await fetch(url);
188
- if (!response.ok) {
189
- throw new Error(`Failed to fetch zip file from ${url}: ${response.status} ${response.statusText}`);
190
- }
191
- // Get the file as a blob
192
- const blob = await response.blob();
193
- // Convert to UpdateContainerCodebaseType using zipToCodebase
194
- return await zipToCodebase(blob);
195
- }
196
- catch (error) {
197
- console.error(`Error reading zip file from path ${filePath}:`, error);
198
- throw new Error(`Failed to read zip file from path: ${error instanceof Error ? error.message : String(error)}`);
199
- }
200
- }
201
- /**
202
- * Reads a zip file from a path and converts it to UpdateContainerCodebaseType with binary file support
203
- * Binary files will have their content as base64 encoded strings
204
- * @param filePath - The path to the zip file (e.g., "/public/guardian/launchdarkly-guardian/code-1.zip" or "/guardian/launchdarkly-guardian/code-1.zip")
205
- * @returns Promise<UpdateContainerCodebaseType> - A flat record of file paths to CodeOutput
206
- */
207
- export async function zipPathToCodebaseWithBinary(filePath) {
208
- try {
209
- // Normalize the path - remove /public prefix if present (Next.js serves public folder from root)
210
- let normalizedPath = filePath;
211
- if (normalizedPath.startsWith("/public/")) {
212
- normalizedPath = normalizedPath.slice("/public".length);
213
- }
214
- // Ensure path starts with /
215
- if (!normalizedPath.startsWith("/")) {
216
- normalizedPath = "/" + normalizedPath;
217
- }
218
- // Build the URL - handle both client-side (relative) and server-side (absolute) cases
219
- let url;
220
- if (typeof window !== "undefined") {
221
- // Client-side: use relative URL
222
- url = normalizedPath;
223
- }
224
- else {
225
- // Server-side: need absolute URL
226
- // Try to get base URL from environment or use a default
227
- const baseUrl = process.env.NEXT_PUBLIC_BASE_URL ||
228
- process.env.VERCEL_URL ||
229
- "http://localhost:3000";
230
- url = `${baseUrl}${normalizedPath}`;
231
- }
232
- // Fetch the file from the public folder
233
- const response = await fetch(url);
234
- if (!response.ok) {
235
- throw new Error(`Failed to fetch zip file from ${url}: ${response.status} ${response.statusText}`);
236
- }
237
- // Get the file as a blob
238
- const blob = await response.blob();
239
- // Convert to UpdateContainerCodebaseType using zipToCodebaseWithBinary
240
- return await zipToCodebaseWithBinary(blob);
241
- }
242
- catch (error) {
243
- console.error(`Error reading zip file from path ${filePath}:`, error);
244
- throw new Error(`Failed to read zip file from path: ${error instanceof Error ? error.message : String(error)}`);
245
- }
246
- }
@@ -1,284 +0,0 @@
1
- import JSZip from "jszip";
2
- import { CodeLanguage, filePathToCodeLanguage, } from "./types/ide-types";
3
- /**
4
- * Converts a zip file to a FileTreeNode structure
5
- * @param zipData - The zip file as Blob, File, ArrayBuffer, or Uint8Array
6
- * @returns Promise<FileTreeNode> - The root node of the file tree
7
- */
8
- export async function zipToFileTree(zipData) {
9
- try {
10
- const zip = await JSZip.loadAsync(zipData);
11
- // Create root node
12
- const root = {
13
- name: "root",
14
- children: {},
15
- type: "folder",
16
- metadata: {
17
- response_type: "CodeOutput",
18
- file_path: "",
19
- code_file_name: "",
20
- code_language: CodeLanguage.TEXT,
21
- dependencies_to_install: [],
22
- framework: null,
23
- full_code: "",
24
- },
25
- };
26
- // Process all files in the zip
27
- const filePromises = [];
28
- for (const relativePath in zip.files) {
29
- const file = zip.files[relativePath];
30
- // Skip directories (they're handled by the path structure)
31
- if (file.dir) {
32
- continue;
33
- }
34
- // Get file content as text
35
- const contentPromise = file
36
- .async("string")
37
- .then((content) => {
38
- // Build the tree structure from the path
39
- const pathParts = relativePath.split("/").filter(Boolean);
40
- let currentNode = root;
41
- // Navigate/create folder structure
42
- for (let i = 0; i < pathParts.length - 1; i++) {
43
- const part = pathParts[i];
44
- if (!currentNode.children[part]) {
45
- currentNode.children[part] = {
46
- name: part,
47
- children: {},
48
- type: "folder",
49
- metadata: {
50
- response_type: "CodeOutput",
51
- file_path: pathParts.slice(0, i + 1).join("/"),
52
- code_file_name: part,
53
- code_language: CodeLanguage.TEXT,
54
- dependencies_to_install: [],
55
- framework: null,
56
- full_code: "",
57
- },
58
- };
59
- }
60
- currentNode = currentNode.children[part];
61
- }
62
- // Add the file
63
- const fileName = pathParts[pathParts.length - 1];
64
- const filePath = relativePath;
65
- const codeLanguage = filePathToCodeLanguage(filePath);
66
- currentNode.children[fileName] = {
67
- name: fileName,
68
- children: {},
69
- type: "file",
70
- metadata: {
71
- response_type: "CodeOutput",
72
- file_path: filePath,
73
- code_file_name: fileName,
74
- code_language: codeLanguage,
75
- dependencies_to_install: [],
76
- framework: null,
77
- full_code: content,
78
- },
79
- };
80
- })
81
- .catch((error) => {
82
- // If file can't be read as text, skip it or handle binary files
83
- console.warn(`Could not read file ${relativePath} as text:`, error);
84
- });
85
- filePromises.push(contentPromise);
86
- }
87
- // Wait for all files to be processed
88
- await Promise.all(filePromises);
89
- return root;
90
- }
91
- catch (error) {
92
- console.error("Error parsing zip file:", error);
93
- throw new Error(`Failed to parse zip file: ${error instanceof Error ? error.message : String(error)}`);
94
- }
95
- }
96
- /**
97
- * Reads a zip file from a path and converts it to a FileTreeNode structure
98
- * @param filePath - The path to the zip file (e.g., "/public/code/guardian/launchdarkly-guardian/code-1.zip" or "/code/guardian/launchdarkly-guardian/code-1.zip")
99
- * @returns Promise<FileTreeNode> - The root node of the file tree
100
- */
101
- export async function zipPathToFileTree(filePath) {
102
- try {
103
- // Normalize the path - remove /public prefix if present (Next.js serves public folder from root)
104
- let normalizedPath = filePath;
105
- if (normalizedPath.startsWith("/public/")) {
106
- normalizedPath = normalizedPath.slice("/public".length);
107
- }
108
- // Ensure path starts with /
109
- if (!normalizedPath.startsWith("/")) {
110
- normalizedPath = "/" + normalizedPath;
111
- }
112
- // Build the URL - handle both client-side (relative) and server-side (absolute) cases
113
- let url;
114
- if (typeof window !== "undefined") {
115
- // Client-side: use relative URL
116
- url = normalizedPath;
117
- }
118
- else {
119
- // Server-side: need absolute URL
120
- // Try to get base URL from environment or use a default
121
- const baseUrl = process.env.NEXT_PUBLIC_BASE_URL ||
122
- process.env.VERCEL_URL ||
123
- "http://localhost:3000";
124
- url = `${baseUrl}${normalizedPath}`;
125
- }
126
- // Fetch the file from the public folder
127
- const response = await fetch(url);
128
- if (!response.ok) {
129
- throw new Error(`Failed to fetch zip file from ${url}: ${response.status} ${response.statusText}`);
130
- }
131
- // Get the file as a blob
132
- const blob = await response.blob();
133
- // Convert to FileTreeNode using zipToFileTree
134
- return await zipToFileTree(blob);
135
- }
136
- catch (error) {
137
- console.error(`Error reading zip file from path ${filePath}:`, error);
138
- throw new Error(`Failed to read zip file from path: ${error instanceof Error ? error.message : String(error)}`);
139
- }
140
- }
141
- /**
142
- * Reads a zip file from a path and converts it to a FileTreeNode structure with binary file support
143
- * Binary files will have their content as base64 encoded strings
144
- * @param filePath - The path to the zip file (e.g., "/public/code/guardian/launchdarkly-guardian/code-1.zip" or "/code/guardian/launchdarkly-guardian/code-1.zip")
145
- * @returns Promise<FileTreeNode> - The root node of the file tree
146
- */
147
- export async function zipPathToFileTreeWithBinary(filePath) {
148
- try {
149
- // Normalize the path - remove /public prefix if present (Next.js serves public folder from root)
150
- let normalizedPath = filePath;
151
- if (normalizedPath.startsWith("/public/")) {
152
- normalizedPath = normalizedPath.slice("/public".length);
153
- }
154
- // Ensure path starts with /
155
- if (!normalizedPath.startsWith("/")) {
156
- normalizedPath = "/" + normalizedPath;
157
- }
158
- // Build the URL - handle both client-side (relative) and server-side (absolute) cases
159
- let url;
160
- if (typeof window !== "undefined") {
161
- // Client-side: use relative URL
162
- url = normalizedPath;
163
- }
164
- else {
165
- // Server-side: need absolute URL
166
- // Try to get base URL from environment or use a default
167
- const baseUrl = process.env.NEXT_PUBLIC_BASE_URL ||
168
- process.env.VERCEL_URL ||
169
- "http://localhost:3000";
170
- url = `${baseUrl}${normalizedPath}`;
171
- }
172
- // Fetch the file from the public folder
173
- const response = await fetch(url);
174
- if (!response.ok) {
175
- throw new Error(`Failed to fetch zip file from ${url}: ${response.status} ${response.statusText}`);
176
- }
177
- // Get the file as a blob
178
- const blob = await response.blob();
179
- // Convert to FileTreeNode using zipToFileTreeWithBinary
180
- return await zipToFileTreeWithBinary(blob);
181
- }
182
- catch (error) {
183
- console.error(`Error reading zip file from path ${filePath}:`, error);
184
- throw new Error(`Failed to read zip file from path: ${error instanceof Error ? error.message : String(error)}`);
185
- }
186
- }
187
- /**
188
- * Converts a zip file to a FileTreeNode structure with binary file support
189
- * Binary files will have their content as base64 encoded strings
190
- * @param zipData - The zip file as Blob, File, ArrayBuffer, or Uint8Array
191
- * @returns Promise<FileTreeNode> - The root node of the file tree
192
- */
193
- export async function zipToFileTreeWithBinary(zipData) {
194
- try {
195
- const zip = await JSZip.loadAsync(zipData);
196
- // Create root node
197
- const root = {
198
- name: "root",
199
- children: {},
200
- type: "folder",
201
- metadata: {
202
- response_type: "CodeOutput",
203
- file_path: "",
204
- code_file_name: "",
205
- code_language: CodeLanguage.TEXT,
206
- dependencies_to_install: [],
207
- framework: null,
208
- full_code: "",
209
- },
210
- };
211
- // Process all files in the zip
212
- const filePromises = [];
213
- for (const relativePath in zip.files) {
214
- const file = zip.files[relativePath];
215
- // Skip directories (they're handled by the path structure)
216
- if (file.dir) {
217
- continue;
218
- }
219
- // Try to read as text first, fallback to base64 for binary files
220
- const contentPromise = (async () => {
221
- let content;
222
- try {
223
- // Try reading as text
224
- content = await file.async("string");
225
- }
226
- catch (_a) {
227
- // If that fails, read as base64
228
- const binary = await file.async("base64");
229
- content = binary;
230
- }
231
- // Build the tree structure from the path
232
- const pathParts = relativePath.split("/").filter(Boolean);
233
- let currentNode = root;
234
- // Navigate/create folder structure
235
- for (let i = 0; i < pathParts.length - 1; i++) {
236
- const part = pathParts[i];
237
- if (!currentNode.children[part]) {
238
- currentNode.children[part] = {
239
- name: part,
240
- children: {},
241
- type: "folder",
242
- metadata: {
243
- response_type: "CodeOutput",
244
- file_path: pathParts.slice(0, i + 1).join("/"),
245
- code_file_name: part,
246
- code_language: CodeLanguage.TEXT,
247
- dependencies_to_install: [],
248
- framework: null,
249
- full_code: "",
250
- },
251
- };
252
- }
253
- currentNode = currentNode.children[part];
254
- }
255
- // Add the file
256
- const fileName = pathParts[pathParts.length - 1];
257
- const filePath = relativePath;
258
- const codeLanguage = filePathToCodeLanguage(filePath);
259
- currentNode.children[fileName] = {
260
- name: fileName,
261
- children: {},
262
- type: "file",
263
- metadata: {
264
- response_type: "CodeOutput",
265
- file_path: filePath,
266
- code_file_name: fileName,
267
- code_language: codeLanguage,
268
- dependencies_to_install: [],
269
- framework: null,
270
- full_code: content,
271
- },
272
- };
273
- })();
274
- filePromises.push(contentPromise);
275
- }
276
- // Wait for all files to be processed
277
- await Promise.all(filePromises);
278
- return root;
279
- }
280
- catch (error) {
281
- console.error("Error parsing zip file:", error);
282
- throw new Error(`Failed to parse zip file: ${error instanceof Error ? error.message : String(error)}`);
283
- }
284
- }