@sampleapp.ai/sdk 1.0.29 → 1.0.30
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.
- package/dist/components/guardian/app-layout-no-sidebar.js +8 -0
- package/dist/components/guardian/ask-ai-view.js +249 -0
- package/dist/components/guardian/code-focus-section.d.ts +41 -0
- package/dist/components/guardian/code-focus-section.js +174 -0
- package/dist/components/guardian/context/guardian-context.js +94 -0
- package/dist/components/guardian/context/vm-context.js +28 -0
- package/dist/components/guardian/default-guide-view.js +34 -0
- package/dist/components/guardian/demo/guardian-demo.js +35 -0
- package/dist/components/guardian/demo/left-view/toggle.js +28 -0
- package/dist/components/guardian/demo/left-view.js +49 -0
- package/dist/components/guardian/guardian-component.js +79 -0
- package/dist/components/guardian/guardian-demo.js +35 -0
- package/dist/components/guardian/guardian-home.d.ts +4 -0
- package/dist/components/guardian/guardian-home.js +61 -0
- package/dist/components/guardian/guardian-playground.js +45 -0
- package/dist/components/guardian/guardian-style-wrapper.js +29 -0
- package/dist/components/guardian/guardian-upload-spec.d.ts +14 -0
- package/dist/components/guardian/guardian-upload-spec.js +160 -0
- package/dist/components/guardian/header/glassmorphic-combobox.d.ts +15 -0
- package/dist/components/guardian/header/glassmorphic-combobox.js +30 -0
- package/dist/components/guardian/header.js +61 -0
- package/dist/components/guardian/hooks/use-frame-messages.js +65 -0
- package/dist/components/guardian/hooks/use-frame-params.js +44 -0
- package/dist/components/guardian/hooks/use-sandbox-url-loader.js +101 -0
- package/dist/components/guardian/ide/browser.js +538 -0
- package/dist/components/guardian/index.js +8 -0
- package/dist/components/guardian/layout/app-layout-no-sidebar.js +8 -0
- package/dist/components/guardian/layout/header/glassmorphic-combobox.js +48 -0
- package/dist/components/guardian/layout/header.js +63 -0
- package/dist/components/guardian/right-view/code-view.js +56 -0
- package/dist/components/guardian/right-view/pill-file-selector.js +233 -0
- package/dist/components/guardian/right-view/preview-control-bar.js +25 -0
- package/dist/components/guardian/right-view/right-panel-view.js +38 -0
- package/dist/components/guardian/right-view/right-top-down-view.js +289 -0
- package/dist/components/guardian/right-view/right-view.js +28 -0
- package/dist/components/guardian/right-view/simplified-editor.js +234 -0
- package/dist/components/guardian/types/ide-types.js +162 -0
- package/dist/components/guardian/types.js +3 -0
- package/dist/components/guardian/ui/ai-loader.js +48 -0
- package/dist/components/guardian/ui/badge.js +24 -0
- package/dist/components/guardian/ui/button.js +45 -0
- package/dist/components/guardian/ui/command.js +63 -0
- package/dist/components/guardian/ui/console-with-app.js +17 -0
- package/dist/components/guardian/ui/dialog.js +57 -0
- package/dist/components/guardian/ui/dropdown-menu.js +82 -0
- package/dist/components/guardian/ui/markdown.js +57 -0
- package/dist/components/guardian/ui/popover.js +25 -0
- package/dist/components/guardian/ui/tooltip.js +25 -0
- package/dist/components/guardian/utils.js +88 -0
- package/dist/components/guardian/zip-to-codebase.js +246 -0
- package/dist/components/guardian/zip-to-filetree.js +284 -0
- package/dist/components/icons.js +22 -0
- package/dist/components/sandbox/Sandbox.js +87 -0
- package/dist/components/sandbox/SandboxHome.js +141 -0
- package/dist/components/sandbox/api.js +108 -0
- package/dist/components/sandbox/guardian/app-layout-no-sidebar.js +8 -0
- package/dist/components/sandbox/guardian/ask-ai-view.js +249 -0
- package/dist/components/sandbox/guardian/code-focus-section.js +174 -0
- package/dist/components/sandbox/guardian/context/guardian-context.js +94 -0
- package/dist/components/sandbox/guardian/context/vm-context.js +28 -0
- package/dist/components/sandbox/guardian/default-guide-view.js +34 -0
- package/dist/components/sandbox/guardian/demo/guardian-demo.js +35 -0
- package/dist/components/sandbox/guardian/demo/left-view/toggle.js +28 -0
- package/dist/components/sandbox/guardian/demo/left-view.js +58 -0
- package/dist/components/sandbox/guardian/guardian-component.js +97 -0
- package/dist/components/sandbox/guardian/guardian-demo.js +35 -0
- package/dist/components/sandbox/guardian/guardian-home.d.ts +4 -0
- package/dist/components/sandbox/guardian/guardian-home.js +61 -0
- package/dist/components/sandbox/guardian/guardian-playground.js +45 -0
- package/dist/components/sandbox/guardian/guardian-style-wrapper.js +33 -0
- package/dist/components/sandbox/guardian/guardian-upload-spec.d.ts +14 -0
- package/dist/components/sandbox/guardian/guardian-upload-spec.js +160 -0
- package/dist/components/sandbox/guardian/header/glassmorphic-combobox.js +30 -0
- package/dist/components/sandbox/guardian/header.js +61 -0
- package/dist/components/sandbox/guardian/hooks/use-frame-messages.js +65 -0
- package/dist/components/sandbox/guardian/hooks/use-frame-params.js +44 -0
- package/dist/components/sandbox/guardian/hooks/use-sandbox-url-loader.js +145 -0
- package/dist/components/sandbox/guardian/ide/browser.js +538 -0
- package/dist/components/sandbox/guardian/index.js +8 -0
- package/dist/components/sandbox/guardian/right-view/code-view.js +60 -0
- package/dist/components/sandbox/guardian/right-view/pill-file-selector.js +233 -0
- package/dist/components/sandbox/guardian/right-view/preview-control-bar.js +25 -0
- package/dist/components/sandbox/guardian/right-view/right-panel-view.js +38 -0
- package/dist/components/sandbox/guardian/right-view/right-top-down-view.js +289 -0
- package/dist/components/sandbox/guardian/right-view/right-view.js +28 -0
- package/dist/components/sandbox/guardian/right-view/simplified-editor.js +234 -0
- package/dist/components/sandbox/guardian/types/ide-types.js +162 -0
- package/dist/components/sandbox/guardian/types.js +3 -0
- package/dist/components/sandbox/guardian/ui/ai-loader.js +48 -0
- package/dist/components/sandbox/guardian/ui/badge.js +24 -0
- package/dist/components/sandbox/guardian/ui/button.js +45 -0
- package/dist/components/sandbox/guardian/ui/command.js +63 -0
- package/dist/components/sandbox/guardian/ui/console-with-app.js +17 -0
- package/dist/components/sandbox/guardian/ui/dialog.js +57 -0
- package/dist/components/sandbox/guardian/ui/dropdown-menu.js +82 -0
- package/dist/components/sandbox/guardian/ui/markdown/accordion-group/accordion.js +62 -0
- package/dist/components/sandbox/guardian/ui/markdown/accordion-group.js +23 -0
- package/dist/components/sandbox/guardian/ui/markdown/callout/callout-check.js +4 -0
- package/dist/components/sandbox/guardian/ui/markdown/callout/callout-error.js +4 -0
- package/dist/components/sandbox/guardian/ui/markdown/callout/callout-info.js +4 -0
- package/dist/components/sandbox/guardian/ui/markdown/callout/callout-note.js +4 -0
- package/dist/components/sandbox/guardian/ui/markdown/callout/callout-tip.js +4 -0
- package/dist/components/sandbox/guardian/ui/markdown/callout/callout-warning.js +4 -0
- package/dist/components/sandbox/guardian/ui/markdown/callout/shared/callout.js +9 -0
- package/dist/components/sandbox/guardian/ui/markdown/callout/shared/types.js +1 -0
- package/dist/components/sandbox/guardian/ui/markdown/card-group/card.js +18 -0
- package/dist/components/sandbox/guardian/ui/markdown/card-group.js +25 -0
- package/dist/components/sandbox/guardian/ui/markdown/code-group/code-block.js +87 -0
- package/dist/components/sandbox/guardian/ui/markdown/code-group.js +101 -0
- package/dist/components/sandbox/guardian/ui/markdown/icon.js +31 -0
- package/dist/components/sandbox/guardian/ui/markdown.js +786 -0
- package/dist/components/sandbox/guardian/ui/popover.js +25 -0
- package/dist/components/sandbox/guardian/ui/tooltip.js +25 -0
- package/dist/components/sandbox/guardian/utils.js +88 -0
- package/dist/components/sandbox/guardian/zip-to-codebase.js +259 -0
- package/dist/components/sandbox/guardian/zip-to-filetree.js +284 -0
- package/dist/components/sandbox/index.js +4 -0
- package/dist/components/sandbox/sandbox-control-bar.js +91 -0
- package/dist/components/sandbox/sandbox-header.js +52 -0
- package/dist/components/sandbox/sandbox-home/SandboxCard.js +59 -0
- package/dist/components/sandbox/sandbox-home/SandboxHome.js +174 -0
- package/dist/components/sandbox/sandbox-home/SearchBar.js +12 -0
- package/dist/components/sandbox/sandbox-home/index.js +3 -0
- package/dist/components/sandbox/sandbox-left-panel.js +248 -0
- package/dist/components/sandbox/sandbox-loading.js +48 -0
- package/dist/components/sandbox/sandbox-right-panel.js +247 -0
- package/dist/components/sandbox/types.js +1 -0
- package/dist/components/sandbox.js +32 -0
- package/dist/components/tailwind-example.js +46 -0
- package/dist/index.d.ts +336 -1
- package/dist/index.es.js +90131 -421
- package/dist/index.js +13 -2
- package/dist/index.standalone.js +61 -53
- package/dist/index.standalone.umd.js +17 -24
- package/dist/lib/api-client.example.js +60 -0
- package/dist/lib/api-client.js +98 -0
- package/dist/lib/generated-css.js +4 -0
- package/dist/lib/inject-styles.js +42 -0
- package/dist/lib/shadow-dom-wrapper.js +42 -0
- package/dist/lib/utils.js +5 -0
- package/dist/sdk.css +1 -1
- package/dist/tailwind.css +1 -0
- package/package.json +32 -5
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
import * as React from "react";
|
|
14
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
15
|
+
import { cn } from "../../../../lib/utils";
|
|
16
|
+
const Popover = PopoverPrimitive.Root;
|
|
17
|
+
const PopoverTrigger = PopoverPrimitive.Trigger;
|
|
18
|
+
const PopoverAnchor = PopoverPrimitive.Anchor;
|
|
19
|
+
const PopoverContent = React.forwardRef((_a, ref) => {
|
|
20
|
+
var { className, align = "center", sideOffset = 4 } = _a, props = __rest(_a, ["className", "align", "sideOffset"]);
|
|
21
|
+
return (React.createElement(PopoverPrimitive.Portal, null,
|
|
22
|
+
React.createElement(PopoverPrimitive.Content, Object.assign({ ref: ref, align: align, sideOffset: sideOffset, className: cn("z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className) }, props))));
|
|
23
|
+
});
|
|
24
|
+
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
25
|
+
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
import * as React from "react";
|
|
14
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
15
|
+
import { cn } from "../../../../lib/utils";
|
|
16
|
+
const TooltipProvider = TooltipPrimitive.Provider;
|
|
17
|
+
const Tooltip = TooltipPrimitive.Root;
|
|
18
|
+
const TooltipTrigger = TooltipPrimitive.Trigger;
|
|
19
|
+
const TooltipContent = React.forwardRef((_a, ref) => {
|
|
20
|
+
var { className, sideOffset = 4 } = _a, props = __rest(_a, ["className", "sideOffset"]);
|
|
21
|
+
return (React.createElement(TooltipPrimitive.Portal, null,
|
|
22
|
+
React.createElement(TooltipPrimitive.Content, Object.assign({ ref: ref, sideOffset: sideOffset, className: cn("z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", className) }, props))));
|
|
23
|
+
});
|
|
24
|
+
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
25
|
+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|
|
@@ -0,0 +1,88 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
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
|
+
* Converts codeZipFile (string path or UpdateContainerCodebaseType) to UpdateContainerCodebaseType
|
|
158
|
+
* @param codeZipFile - Either a string path to a zip file OR an UpdateContainerCodebaseType object
|
|
159
|
+
* @returns Promise<UpdateContainerCodebaseType> - A flat record of file paths to CodeOutput
|
|
160
|
+
*/
|
|
161
|
+
export async function codeZipFileToCodebase(codeZipFile) {
|
|
162
|
+
// If it's already an object (generated_code), return it directly
|
|
163
|
+
if (typeof codeZipFile !== "string") {
|
|
164
|
+
return codeZipFile;
|
|
165
|
+
}
|
|
166
|
+
// Otherwise, treat it as a file path and fetch it
|
|
167
|
+
return zipPathToCodebase(codeZipFile);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Reads a zip file from a path and converts it to UpdateContainerCodebaseType
|
|
171
|
+
* @param filePath - The path to the zip file (e.g., "/public/guardian/launchdarkly-guardian/code-1.zip" or "/guardian/launchdarkly-guardian/code-1.zip")
|
|
172
|
+
* @returns Promise<UpdateContainerCodebaseType> - A flat record of file paths to CodeOutput
|
|
173
|
+
*/
|
|
174
|
+
export async function zipPathToCodebase(filePath) {
|
|
175
|
+
try {
|
|
176
|
+
// Normalize the path - remove /public prefix if present (Next.js serves public folder from root)
|
|
177
|
+
let normalizedPath = filePath;
|
|
178
|
+
if (normalizedPath.startsWith("/public/")) {
|
|
179
|
+
normalizedPath = normalizedPath.slice("/public".length);
|
|
180
|
+
}
|
|
181
|
+
// Ensure path starts with /
|
|
182
|
+
if (!normalizedPath.startsWith("/")) {
|
|
183
|
+
normalizedPath = "/" + normalizedPath;
|
|
184
|
+
}
|
|
185
|
+
// Build the URL - handle both client-side (relative) and server-side (absolute) cases
|
|
186
|
+
let url;
|
|
187
|
+
if (typeof window !== "undefined") {
|
|
188
|
+
// Client-side: use relative URL
|
|
189
|
+
url = normalizedPath;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
// Server-side: need absolute URL
|
|
193
|
+
// Try to get base URL from environment or use a default
|
|
194
|
+
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL ||
|
|
195
|
+
process.env.VERCEL_URL ||
|
|
196
|
+
"http://localhost:3000";
|
|
197
|
+
url = `${baseUrl}${normalizedPath}`;
|
|
198
|
+
}
|
|
199
|
+
// Fetch the file from the public folder
|
|
200
|
+
const response = await fetch(url);
|
|
201
|
+
if (!response.ok) {
|
|
202
|
+
throw new Error(`Failed to fetch zip file from ${url}: ${response.status} ${response.statusText}`);
|
|
203
|
+
}
|
|
204
|
+
// Get the file as a blob
|
|
205
|
+
const blob = await response.blob();
|
|
206
|
+
// Convert to UpdateContainerCodebaseType using zipToCodebase
|
|
207
|
+
return await zipToCodebase(blob);
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
console.error(`Error reading zip file from path ${filePath}:`, error);
|
|
211
|
+
throw new Error(`Failed to read zip file from path: ${error instanceof Error ? error.message : String(error)}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Reads a zip file from a path and converts it to UpdateContainerCodebaseType with binary file support
|
|
216
|
+
* Binary files will have their content as base64 encoded strings
|
|
217
|
+
* @param filePath - The path to the zip file (e.g., "/public/guardian/launchdarkly-guardian/code-1.zip" or "/guardian/launchdarkly-guardian/code-1.zip")
|
|
218
|
+
* @returns Promise<UpdateContainerCodebaseType> - A flat record of file paths to CodeOutput
|
|
219
|
+
*/
|
|
220
|
+
export async function zipPathToCodebaseWithBinary(filePath) {
|
|
221
|
+
try {
|
|
222
|
+
// Normalize the path - remove /public prefix if present (Next.js serves public folder from root)
|
|
223
|
+
let normalizedPath = filePath;
|
|
224
|
+
if (normalizedPath.startsWith("/public/")) {
|
|
225
|
+
normalizedPath = normalizedPath.slice("/public".length);
|
|
226
|
+
}
|
|
227
|
+
// Ensure path starts with /
|
|
228
|
+
if (!normalizedPath.startsWith("/")) {
|
|
229
|
+
normalizedPath = "/" + normalizedPath;
|
|
230
|
+
}
|
|
231
|
+
// Build the URL - handle both client-side (relative) and server-side (absolute) cases
|
|
232
|
+
let url;
|
|
233
|
+
if (typeof window !== "undefined") {
|
|
234
|
+
// Client-side: use relative URL
|
|
235
|
+
url = normalizedPath;
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
// Server-side: need absolute URL
|
|
239
|
+
// Try to get base URL from environment or use a default
|
|
240
|
+
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL ||
|
|
241
|
+
process.env.VERCEL_URL ||
|
|
242
|
+
"http://localhost:3000";
|
|
243
|
+
url = `${baseUrl}${normalizedPath}`;
|
|
244
|
+
}
|
|
245
|
+
// Fetch the file from the public folder
|
|
246
|
+
const response = await fetch(url);
|
|
247
|
+
if (!response.ok) {
|
|
248
|
+
throw new Error(`Failed to fetch zip file from ${url}: ${response.status} ${response.statusText}`);
|
|
249
|
+
}
|
|
250
|
+
// Get the file as a blob
|
|
251
|
+
const blob = await response.blob();
|
|
252
|
+
// Convert to UpdateContainerCodebaseType using zipToCodebaseWithBinary
|
|
253
|
+
return await zipToCodebaseWithBinary(blob);
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
console.error(`Error reading zip file from path ${filePath}:`, error);
|
|
257
|
+
throw new Error(`Failed to read zip file from path: ${error instanceof Error ? error.message : String(error)}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
@@ -0,0 +1,284 @@
|
|
|
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
|
+
}
|