create-stylus-ide 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.
- package/Readme.MD +1515 -0
- package/cli.js +28 -0
- package/frontend/.vscode/settings.json +9 -0
- package/frontend/app/api/chat/route.ts +101 -0
- package/frontend/app/api/check-setup/route.ts +93 -0
- package/frontend/app/api/cleanup/route.ts +14 -0
- package/frontend/app/api/compile/route.ts +95 -0
- package/frontend/app/api/compile-stream/route.ts +98 -0
- package/frontend/app/api/complete/route.ts +86 -0
- package/frontend/app/api/deploy/route.ts +118 -0
- package/frontend/app/api/export-abi/route.ts +58 -0
- package/frontend/app/favicon.ico +0 -0
- package/frontend/app/globals.css +177 -0
- package/frontend/app/layout.tsx +29 -0
- package/frontend/app/ml/page.tsx +694 -0
- package/frontend/app/page.tsx +1132 -0
- package/frontend/app/providers.tsx +18 -0
- package/frontend/app/qlearning/page.tsx +188 -0
- package/frontend/app/raytracing/page.tsx +268 -0
- package/frontend/components/abi/ABIDialog.tsx +132 -0
- package/frontend/components/ai/AICompletionPopup.tsx +76 -0
- package/frontend/components/ai/ChatPanel.tsx +292 -0
- package/frontend/components/ai/QuickActions.tsx +128 -0
- package/frontend/components/blockchain/BlockchainContractBanner.tsx +64 -0
- package/frontend/components/blockchain/BlockchainLoadingDialog.tsx +188 -0
- package/frontend/components/deploy/DeployDialog.tsx +334 -0
- package/frontend/components/editor/FileTabs.tsx +181 -0
- package/frontend/components/editor/MonacoEditor.tsx +306 -0
- package/frontend/components/file-tree/ContextMenu.tsx +110 -0
- package/frontend/components/file-tree/DeleteConfirmDialog.tsx +61 -0
- package/frontend/components/file-tree/FileInputDialog.tsx +97 -0
- package/frontend/components/file-tree/FileNode.tsx +60 -0
- package/frontend/components/file-tree/FileTree.tsx +259 -0
- package/frontend/components/file-tree/FileTreeSkeleton.tsx +26 -0
- package/frontend/components/file-tree/FolderNode.tsx +105 -0
- package/frontend/components/github/GitHubLoadingDialog.tsx +201 -0
- package/frontend/components/github/GitHubMetadataBanner.tsx +61 -0
- package/frontend/components/github/LoadFromGitHubDialog.tsx +125 -0
- package/frontend/components/github/URLCopyButton.tsx +60 -0
- package/frontend/components/interact/ContractInteraction.tsx +323 -0
- package/frontend/components/interact/ContractPlaceholder.tsx +41 -0
- package/frontend/components/orbit/BenchmarkDialog.tsx +342 -0
- package/frontend/components/orbit/OrbitExplorer.tsx +273 -0
- package/frontend/components/project/ProjectActions.tsx +176 -0
- package/frontend/components/q-learning/ContractConfig.tsx +172 -0
- package/frontend/components/q-learning/MazeGrid.tsx +346 -0
- package/frontend/components/q-learning/PathAnimation.tsx +384 -0
- package/frontend/components/q-learning/QTableHeatmap.tsx +300 -0
- package/frontend/components/q-learning/TrainingForm.tsx +349 -0
- package/frontend/components/ray-tracing/ContractConfig.tsx +245 -0
- package/frontend/components/ray-tracing/MintingForm.tsx +280 -0
- package/frontend/components/ray-tracing/RenderCanvas.tsx +228 -0
- package/frontend/components/ray-tracing/RenderingPanel.tsx +259 -0
- package/frontend/components/ray-tracing/StyleControls.tsx +217 -0
- package/frontend/components/setup/SetupGuide.tsx +290 -0
- package/frontend/components/ui/KeyboardShortcutHint.tsx +74 -0
- package/frontend/components/ui/alert-dialog.tsx +157 -0
- package/frontend/components/ui/alert.tsx +66 -0
- package/frontend/components/ui/badge.tsx +46 -0
- package/frontend/components/ui/button.tsx +62 -0
- package/frontend/components/ui/card.tsx +92 -0
- package/frontend/components/ui/context-menu.tsx +252 -0
- package/frontend/components/ui/dialog.tsx +143 -0
- package/frontend/components/ui/dropdown-menu.tsx +257 -0
- package/frontend/components/ui/input.tsx +21 -0
- package/frontend/components/ui/label.tsx +24 -0
- package/frontend/components/ui/progress.tsx +31 -0
- package/frontend/components/ui/scroll-area.tsx +58 -0
- package/frontend/components/ui/select.tsx +190 -0
- package/frontend/components/ui/separator.tsx +28 -0
- package/frontend/components/ui/sheet.tsx +139 -0
- package/frontend/components/ui/skeleton.tsx +13 -0
- package/frontend/components/ui/slider.tsx +63 -0
- package/frontend/components/ui/sonner.tsx +40 -0
- package/frontend/components/ui/tabs.tsx +66 -0
- package/frontend/components/ui/textarea.tsx +18 -0
- package/frontend/components/wallet/ConnectButton.tsx +167 -0
- package/frontend/components/wallet/FaucetButton.tsx +256 -0
- package/frontend/components.json +22 -0
- package/frontend/eslint.config.mjs +18 -0
- package/frontend/hooks/useAICompletion.ts +75 -0
- package/frontend/hooks/useBlockchainLoader.ts +58 -0
- package/frontend/hooks/useChats.ts +137 -0
- package/frontend/hooks/useCompilation.ts +173 -0
- package/frontend/hooks/useFileTabs.ts +178 -0
- package/frontend/hooks/useGitHubLoader.ts +50 -0
- package/frontend/hooks/useKeyboardShortcuts.ts +47 -0
- package/frontend/hooks/usePanelState.ts +115 -0
- package/frontend/hooks/useProjectState.ts +276 -0
- package/frontend/hooks/useResponsive.ts +29 -0
- package/frontend/lib/abi-parser.ts +58 -0
- package/frontend/lib/blockchain-api.ts +374 -0
- package/frontend/lib/blockchain-explorers.ts +75 -0
- package/frontend/lib/blockchain-loader.ts +112 -0
- package/frontend/lib/cargo-template.ts +64 -0
- package/frontend/lib/compilation.ts +529 -0
- package/frontend/lib/constants.ts +31 -0
- package/frontend/lib/deployment.ts +176 -0
- package/frontend/lib/file-utils.ts +83 -0
- package/frontend/lib/github-api.ts +246 -0
- package/frontend/lib/github-loader.ts +369 -0
- package/frontend/lib/ml-contract-template.txt +900 -0
- package/frontend/lib/orbit-chains.ts +181 -0
- package/frontend/lib/output-formatter.ts +68 -0
- package/frontend/lib/project-manager.ts +632 -0
- package/frontend/lib/ray-tracing-abi.ts +206 -0
- package/frontend/lib/storage.ts +189 -0
- package/frontend/lib/templates.ts +1662 -0
- package/frontend/lib/url-parser.ts +188 -0
- package/frontend/lib/utils.ts +6 -0
- package/frontend/lib/wagmi-config.ts +24 -0
- package/frontend/next.config.ts +7 -0
- package/frontend/package-lock.json +16259 -0
- package/frontend/package.json +60 -0
- package/frontend/postcss.config.mjs +7 -0
- package/frontend/public/file.svg +1 -0
- package/frontend/public/globe.svg +1 -0
- package/frontend/public/ml-weights/.gitkeep +0 -0
- package/frontend/public/ml-weights/model.pkl +0 -0
- package/frontend/public/ml-weights/model_weights.json +27102 -0
- package/frontend/public/ml-weights/test_samples.json +7888 -0
- package/frontend/public/next.svg +1 -0
- package/frontend/public/vercel.svg +1 -0
- package/frontend/public/window.svg +1 -0
- package/frontend/scripts/check-env.js +52 -0
- package/frontend/scripts/setup.js +285 -0
- package/frontend/tailwind.config.ts +64 -0
- package/frontend/tsconfig.json +34 -0
- package/frontend/types/blockchain.ts +63 -0
- package/frontend/types/github.ts +54 -0
- package/frontend/types/project.ts +106 -0
- package/ml-training/README.md +56 -0
- package/ml-training/train_tiny_model.py +325 -0
- package/ml-training/update_template.py +59 -0
- package/package.json +30 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState, useCallback, useEffect, useRef } from "react";
|
|
4
|
+
import { ProjectState, FileNode } from "@/types/project";
|
|
5
|
+
import {
|
|
6
|
+
createProject,
|
|
7
|
+
addFile,
|
|
8
|
+
addFolder,
|
|
9
|
+
deleteFile,
|
|
10
|
+
deleteFolder,
|
|
11
|
+
renameFile,
|
|
12
|
+
updateFileContent,
|
|
13
|
+
setActiveFile,
|
|
14
|
+
toggleFileOpen,
|
|
15
|
+
getFileByPath,
|
|
16
|
+
} from "@/lib/project-manager";
|
|
17
|
+
import { saveProject, loadProject } from "@/lib/storage";
|
|
18
|
+
|
|
19
|
+
export function useProjectState(initialName: string = "my-stylus-project") {
|
|
20
|
+
// ✅ FIXED: Always start with default project (server + client match)
|
|
21
|
+
const [project, setProject] = useState<ProjectState>(() =>
|
|
22
|
+
createProject(initialName)
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
// ✅ FIXED: Track if we've loaded from localStorage
|
|
26
|
+
const [isHydrated, setIsHydrated] = useState(false);
|
|
27
|
+
|
|
28
|
+
// ✅ FIXED: Load from localStorage AFTER mount (client-only)
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (typeof window !== "undefined" && !isHydrated) {
|
|
31
|
+
const savedProject = loadProject();
|
|
32
|
+
if (savedProject) {
|
|
33
|
+
setProject(savedProject);
|
|
34
|
+
}
|
|
35
|
+
setIsHydrated(true);
|
|
36
|
+
}
|
|
37
|
+
}, [isHydrated]);
|
|
38
|
+
|
|
39
|
+
// Auto-save timer refs
|
|
40
|
+
const saveTimerRef = useRef<NodeJS.Timeout | null>(null);
|
|
41
|
+
const lastSaveRef = useRef<string>("");
|
|
42
|
+
|
|
43
|
+
// ✅ FIXED: Auto-save only after hydration
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
// Skip if running on server OR not hydrated yet
|
|
46
|
+
if (typeof window === "undefined" || !isHydrated) return;
|
|
47
|
+
|
|
48
|
+
// Serialize project for comparison
|
|
49
|
+
const projectSnapshot = JSON.stringify(project);
|
|
50
|
+
|
|
51
|
+
// Only save if project actually changed
|
|
52
|
+
if (projectSnapshot !== lastSaveRef.current) {
|
|
53
|
+
// Clear existing timer
|
|
54
|
+
if (saveTimerRef.current) {
|
|
55
|
+
clearTimeout(saveTimerRef.current);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Set new timer (debounce for 2 seconds)
|
|
59
|
+
saveTimerRef.current = setTimeout(() => {
|
|
60
|
+
saveProject(project);
|
|
61
|
+
lastSaveRef.current = projectSnapshot;
|
|
62
|
+
console.log("Project auto-saved");
|
|
63
|
+
}, 2000);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Cleanup on unmount
|
|
67
|
+
return () => {
|
|
68
|
+
if (saveTimerRef.current) {
|
|
69
|
+
clearTimeout(saveTimerRef.current);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}, [project, isHydrated]);
|
|
73
|
+
|
|
74
|
+
// Create new file
|
|
75
|
+
const createNewFile = useCallback((path: string, content?: string) => {
|
|
76
|
+
try {
|
|
77
|
+
setProject((prev) => addFile(prev, { path, content }));
|
|
78
|
+
return true;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error("Failed to create file:", error);
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}, []);
|
|
84
|
+
|
|
85
|
+
// Create new folder
|
|
86
|
+
const createNewFolder = useCallback((path: string) => {
|
|
87
|
+
try {
|
|
88
|
+
setProject((prev) => addFolder(prev, { path }));
|
|
89
|
+
return true;
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error("Failed to create folder:", error);
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}, []);
|
|
95
|
+
|
|
96
|
+
// Delete file
|
|
97
|
+
const removeFile = useCallback((path: string) => {
|
|
98
|
+
try {
|
|
99
|
+
setProject((prev) => deleteFile(prev, path));
|
|
100
|
+
return true;
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.error("Failed to delete file:", error);
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}, []);
|
|
106
|
+
|
|
107
|
+
// Delete folder
|
|
108
|
+
const removeFolder = useCallback((path: string) => {
|
|
109
|
+
try {
|
|
110
|
+
setProject((prev) => deleteFolder(prev, path));
|
|
111
|
+
return true;
|
|
112
|
+
} catch (error) {
|
|
113
|
+
console.error("Failed to delete folder:", error);
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}, []);
|
|
117
|
+
|
|
118
|
+
// Rename file/folder
|
|
119
|
+
const rename = useCallback((oldPath: string, newPath: string) => {
|
|
120
|
+
try {
|
|
121
|
+
setProject((prev) => renameFile(prev, { oldPath, newPath }));
|
|
122
|
+
return true;
|
|
123
|
+
} catch (error) {
|
|
124
|
+
console.error("Failed to rename:", error);
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}, []);
|
|
128
|
+
|
|
129
|
+
// Update file content
|
|
130
|
+
const updateContent = useCallback((path: string, content: string) => {
|
|
131
|
+
setProject((prev) => updateFileContent(prev, path, content));
|
|
132
|
+
}, []);
|
|
133
|
+
|
|
134
|
+
// Set active file
|
|
135
|
+
const setActive = useCallback((path: string | null) => {
|
|
136
|
+
setProject((prev) => {
|
|
137
|
+
let updated = setActiveFile(prev, path);
|
|
138
|
+
|
|
139
|
+
if (path) {
|
|
140
|
+
updated = toggleFileOpen(updated, path, true);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return updated;
|
|
144
|
+
});
|
|
145
|
+
}, []);
|
|
146
|
+
|
|
147
|
+
// Close file (remove from tabs)
|
|
148
|
+
const closeFile = useCallback((path: string) => {
|
|
149
|
+
setProject((prev) => {
|
|
150
|
+
let updated = toggleFileOpen(prev, path, false);
|
|
151
|
+
|
|
152
|
+
if (prev.activeFilePath === path) {
|
|
153
|
+
updated = setActiveFile(updated, null);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return updated;
|
|
157
|
+
});
|
|
158
|
+
}, []);
|
|
159
|
+
|
|
160
|
+
// Toggle folder expansion
|
|
161
|
+
const toggleFolder = useCallback((path: string, expanded: boolean) => {
|
|
162
|
+
setProject((prev) => ({
|
|
163
|
+
...prev,
|
|
164
|
+
structure: updateFolderExpansion(prev.structure, path, expanded),
|
|
165
|
+
}));
|
|
166
|
+
}, []);
|
|
167
|
+
|
|
168
|
+
// Duplicate file
|
|
169
|
+
const duplicateFile = useCallback((path: string) => {
|
|
170
|
+
try {
|
|
171
|
+
setProject((prev) => {
|
|
172
|
+
const file = getFileByPath(prev, path);
|
|
173
|
+
if (!file) {
|
|
174
|
+
console.error("File not found:", path);
|
|
175
|
+
return prev;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const pathParts = path.split("/");
|
|
179
|
+
const fileName = pathParts.pop()!;
|
|
180
|
+
const fileDir = pathParts.join("/");
|
|
181
|
+
|
|
182
|
+
const nameParts = fileName.split(".");
|
|
183
|
+
const ext = nameParts.length > 1 ? nameParts.pop() : "";
|
|
184
|
+
const baseName = nameParts.join(".");
|
|
185
|
+
|
|
186
|
+
let counter = 1;
|
|
187
|
+
let newName = ext ? `${baseName}_copy.${ext}` : `${baseName}_copy`;
|
|
188
|
+
let newPath = fileDir ? `${fileDir}/${newName}` : newName;
|
|
189
|
+
|
|
190
|
+
while (getFileByPath(prev, newPath)) {
|
|
191
|
+
counter++;
|
|
192
|
+
newName = ext
|
|
193
|
+
? `${baseName}_copy${counter}.${ext}`
|
|
194
|
+
: `${baseName}_copy${counter}`;
|
|
195
|
+
newPath = fileDir ? `${fileDir}/${newName}` : newName;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return addFile(prev, {
|
|
199
|
+
path: newPath,
|
|
200
|
+
content: file.content,
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
return true;
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.error("Failed to duplicate file:", error);
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
}, []);
|
|
210
|
+
|
|
211
|
+
// Get current file content
|
|
212
|
+
const getCurrentFile = useCallback(() => {
|
|
213
|
+
if (!project.activeFilePath) return null;
|
|
214
|
+
return getFileByPath(project, project.activeFilePath);
|
|
215
|
+
}, [project]);
|
|
216
|
+
|
|
217
|
+
// Get all open files
|
|
218
|
+
const getOpenFiles = useCallback(() => {
|
|
219
|
+
return project.files.filter((f) => f.isOpen);
|
|
220
|
+
}, [project.files]);
|
|
221
|
+
|
|
222
|
+
// Manual save function
|
|
223
|
+
const manualSave = useCallback(() => {
|
|
224
|
+
saveProject(project);
|
|
225
|
+
console.log("Project manually saved");
|
|
226
|
+
}, [project]);
|
|
227
|
+
|
|
228
|
+
// Reset to new project
|
|
229
|
+
const resetProject = useCallback(() => {
|
|
230
|
+
const newProject = createProject(initialName);
|
|
231
|
+
setProject(newProject);
|
|
232
|
+
saveProject(newProject);
|
|
233
|
+
}, [initialName]);
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
project,
|
|
237
|
+
setProject,
|
|
238
|
+
createNewFile,
|
|
239
|
+
createNewFolder,
|
|
240
|
+
removeFile,
|
|
241
|
+
removeFolder,
|
|
242
|
+
rename,
|
|
243
|
+
updateContent,
|
|
244
|
+
setActive,
|
|
245
|
+
closeFile,
|
|
246
|
+
toggleFolder,
|
|
247
|
+
duplicateFile,
|
|
248
|
+
getCurrentFile,
|
|
249
|
+
getOpenFiles,
|
|
250
|
+
manualSave,
|
|
251
|
+
resetProject,
|
|
252
|
+
isHydrated, // ✅ NEW: Export for debugging
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Helper to update folder expansion in tree
|
|
257
|
+
function updateFolderExpansion(
|
|
258
|
+
structure: FileNode[],
|
|
259
|
+
path: string,
|
|
260
|
+
expanded: boolean
|
|
261
|
+
): FileNode[] {
|
|
262
|
+
return structure.map((node) => {
|
|
263
|
+
if (node.path === path && node.type === "folder") {
|
|
264
|
+
return { ...node, expanded };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (node.type === "folder" && node.children) {
|
|
268
|
+
return {
|
|
269
|
+
...node,
|
|
270
|
+
children: updateFolderExpansion(node.children, path, expanded),
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return node;
|
|
275
|
+
});
|
|
276
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
|
|
5
|
+
export function useResponsive() {
|
|
6
|
+
const [isMobile, setIsMobile] = useState(false);
|
|
7
|
+
const [isTablet, setIsTablet] = useState(false);
|
|
8
|
+
const [isDesktop, setIsDesktop] = useState(false);
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
const checkScreenSize = () => {
|
|
12
|
+
const width = window.innerWidth;
|
|
13
|
+
setIsMobile(width < 768);
|
|
14
|
+
setIsTablet(width >= 768 && width < 1024);
|
|
15
|
+
setIsDesktop(width >= 1024);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Initial check
|
|
19
|
+
checkScreenSize();
|
|
20
|
+
|
|
21
|
+
// Add event listener
|
|
22
|
+
window.addEventListener('resize', checkScreenSize);
|
|
23
|
+
|
|
24
|
+
// Cleanup
|
|
25
|
+
return () => window.removeEventListener('resize', checkScreenSize);
|
|
26
|
+
}, []);
|
|
27
|
+
|
|
28
|
+
return { isMobile, isTablet, isDesktop };
|
|
29
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export interface ParsedFunction {
|
|
2
|
+
name: string;
|
|
3
|
+
type: "function";
|
|
4
|
+
stateMutability: "view" | "pure" | "nonpayable" | "payable";
|
|
5
|
+
inputs: Array<{
|
|
6
|
+
name: string;
|
|
7
|
+
type: string;
|
|
8
|
+
internalType?: string;
|
|
9
|
+
}>;
|
|
10
|
+
outputs: Array<{
|
|
11
|
+
name: string;
|
|
12
|
+
type: string;
|
|
13
|
+
internalType?: string;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function parseABI(abiString: string): ParsedFunction[] {
|
|
18
|
+
try {
|
|
19
|
+
const abi = JSON.parse(abiString);
|
|
20
|
+
return abi.filter(
|
|
21
|
+
(item: any) => item.type === "function"
|
|
22
|
+
) as ParsedFunction[];
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error("Failed to parse ABI:", error);
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function isReadFunction(func: ParsedFunction): boolean {
|
|
30
|
+
return func.stateMutability === "view" || func.stateMutability === "pure";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function isWriteFunction(func: ParsedFunction): boolean {
|
|
34
|
+
return (
|
|
35
|
+
func.stateMutability === "nonpayable" || func.stateMutability === "payable"
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function groupFunctionsByType(functions: ParsedFunction[]): {
|
|
40
|
+
read: ParsedFunction[];
|
|
41
|
+
write: ParsedFunction[];
|
|
42
|
+
} {
|
|
43
|
+
return {
|
|
44
|
+
read: functions.filter(isReadFunction),
|
|
45
|
+
write: functions.filter(isWriteFunction),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function formatFunctionSignature(func: ParsedFunction): string {
|
|
50
|
+
const params = func.inputs
|
|
51
|
+
.map((input) => `${input.type} ${input.name || ""}`)
|
|
52
|
+
.join(", ");
|
|
53
|
+
const returns =
|
|
54
|
+
func.outputs.length > 0
|
|
55
|
+
? ` returns (${func.outputs.map((output) => output.type).join(", ")})`
|
|
56
|
+
: "";
|
|
57
|
+
return `${func.name}(${params})${returns}`;
|
|
58
|
+
}
|