scaffoldrite 2.0.4 → 2.0.6

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.
@@ -1,183 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseConstraints = parseConstraints;
4
- function splitArgs(line) {
5
- const args = [];
6
- let current = "";
7
- let inQuotes = false;
8
- for (let i = 0; i < line.length; i++) {
9
- const ch = line[i];
10
- if (ch === '"' || ch === "'") {
11
- inQuotes = !inQuotes;
12
- continue;
13
- }
14
- if (ch === " " && !inQuotes) {
15
- if (current.length > 0) {
16
- args.push(current);
17
- current = "";
18
- }
19
- continue;
20
- }
21
- current += ch;
22
- }
23
- if (current.length > 0)
24
- args.push(current);
25
- return args;
26
- }
27
- function parseConstraints(input) {
28
- const lines = input.split("\n");
29
- const constraints = [];
30
- for (let line of lines) {
31
- line = line.trim();
32
- if (!line)
33
- continue;
34
- if (line.startsWith("require ")) {
35
- const path = line.replace("require ", "").trim();
36
- constraints.push({ type: "require", path });
37
- continue;
38
- }
39
- if (line.startsWith("forbid ")) {
40
- const path = line.replace("forbid ", "").trim();
41
- constraints.push({ type: "forbid", path });
42
- continue;
43
- }
44
- if (line.startsWith("maxFilesByExtRecursive ")) {
45
- const parts = splitArgs(line);
46
- const ext = parts[1];
47
- const value = Number(parts[2]);
48
- const path = parts[3];
49
- constraints.push({ type: "maxFilesByExtRecursive", path, value, ext });
50
- continue;
51
- }
52
- if (line.startsWith("maxFilesRecursive ")) {
53
- const parts = splitArgs(line);
54
- const value = Number(parts[1]);
55
- const path = parts[2];
56
- constraints.push({ type: "maxFilesRecursive", path, value });
57
- continue;
58
- }
59
- if (line.startsWith("maxFilesByExt ")) {
60
- const parts = splitArgs(line);
61
- const ext = parts[1];
62
- const value = Number(parts[2]);
63
- const path = parts[3];
64
- constraints.push({ type: "maxFilesByExt", path, value, ext });
65
- continue;
66
- }
67
- if (line.startsWith("maxFiles ")) {
68
- const parts = splitArgs(line);
69
- const value = Number(parts[1]);
70
- const path = parts[2];
71
- constraints.push({ type: "maxFiles", path, value });
72
- continue;
73
- }
74
- if (line.startsWith("maxFoldersRecursive ")) {
75
- const parts = splitArgs(line);
76
- const value = Number(parts[1]);
77
- const path = parts[2];
78
- constraints.push({ type: "maxFoldersRecursive", path, value });
79
- continue;
80
- }
81
- if (line.startsWith("maxFolders ")) {
82
- const parts = splitArgs(line);
83
- const value = Number(parts[1]);
84
- const path = parts[2];
85
- constraints.push({ type: "maxFolders", path, value });
86
- continue;
87
- }
88
- if (line.startsWith("minFiles ")) {
89
- const parts = splitArgs(line);
90
- const value = Number(parts[1]);
91
- const path = parts[2];
92
- constraints.push({ type: "minFiles", path, value });
93
- continue;
94
- }
95
- if (line.startsWith("minFolders ")) {
96
- const parts = splitArgs(line);
97
- const value = Number(parts[1]);
98
- const path = parts[2];
99
- constraints.push({ type: "minFolders", path, value });
100
- continue;
101
- }
102
- // NEW RULES PARSING (WITH SCOPE)
103
- if (line.startsWith("eachFolderMustContain ")) {
104
- const parts = splitArgs(line);
105
- const scope = parts[1];
106
- if (scope !== "*" && scope !== "**") {
107
- throw new Error(`Invalid scope for eachFolderMustContain: ${scope}`);
108
- }
109
- const hasPath = parts.length === 4;
110
- const path = hasPath ? parts[2] : "";
111
- const value = hasPath ? parts[3] : parts[2];
112
- constraints.push({ type: "eachFolderMustContain", path, value, scope });
113
- continue;
114
- }
115
- if (line.startsWith("eachFolderMustContainFile ")) {
116
- const parts = splitArgs(line);
117
- const scope = parts[1];
118
- if (scope !== "*" && scope !== "**") {
119
- throw new Error(`Invalid scope for eachFolderMustContainFile: ${scope}`);
120
- }
121
- const hasPath = parts.length === 4;
122
- const path = hasPath ? parts[2] : "";
123
- const value = hasPath ? parts[3] : parts[2];
124
- constraints.push({ type: "eachFolderMustContainFile", path, value, scope });
125
- continue;
126
- }
127
- if (line.startsWith("eachFolderMustContainFolder ")) {
128
- const parts = splitArgs(line);
129
- const scope = parts[1];
130
- if (scope !== "*" && scope !== "**") {
131
- throw new Error(`Invalid scope for eachFolderMustContainFolder: ${scope}`);
132
- }
133
- const hasPath = parts.length === 4;
134
- const path = hasPath ? parts[2] : "";
135
- const value = hasPath ? parts[3] : parts[2];
136
- constraints.push({ type: "eachFolderMustContainFolder", path, value, scope });
137
- continue;
138
- }
139
- if (line.startsWith("eachFolderMustHaveExt ")) {
140
- const parts = splitArgs(line);
141
- const scope = parts[1];
142
- if (scope !== "*" && scope !== "**") {
143
- throw new Error(`Invalid scope for eachFolderMustHaveExt: ${scope}`);
144
- }
145
- const hasPath = parts.length === 4;
146
- const path = hasPath ? parts[2] : "";
147
- const ext = hasPath ? parts[3] : parts[2];
148
- constraints.push({ type: "eachFolderMustHaveExt", path, ext, scope });
149
- continue;
150
- }
151
- // EXISTING RULES
152
- if (line.startsWith("mustContain ")) {
153
- const parts = splitArgs(line);
154
- const path = parts[1];
155
- const value = parts[2];
156
- constraints.push({ type: "mustContain", path, value });
157
- continue;
158
- }
159
- if (line.startsWith("fileNameRegex ")) {
160
- const parts = splitArgs(line);
161
- const path = parts[1];
162
- const regex = parts[2];
163
- constraints.push({ type: "fileNameRegex", path, regex });
164
- continue;
165
- }
166
- if (line.startsWith("maxDepth ")) {
167
- const parts = splitArgs(line);
168
- const value = Number(parts[1]);
169
- const path = parts[2];
170
- constraints.push({ type: "maxDepth", path, value });
171
- continue;
172
- }
173
- if (line.startsWith("mustHaveFile ")) {
174
- const parts = splitArgs(line);
175
- const path = parts[1];
176
- const value = parts[2];
177
- constraints.push({ type: "mustHaveFile", path, value });
178
- continue;
179
- }
180
- throw new Error(`Unknown constraint: ${line}`);
181
- }
182
- return constraints;
183
- }
package/dist/fsToAst.js DELETED
@@ -1,47 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.buildASTFromFS = buildASTFromFS;
7
- const fs_1 = __importDefault(require("fs"));
8
- const path_1 = __importDefault(require("path"));
9
- function buildASTFromFS(dir, ignoreList = []) {
10
- if (!fs_1.default.existsSync(dir)) {
11
- throw new Error(`Directory does not exist: ${dir}`);
12
- }
13
- const root = {
14
- type: "folder",
15
- name: path_1.default.basename(dir),
16
- children: [],
17
- };
18
- function scan(folderPath, node) {
19
- const items = fs_1.default.readdirSync(folderPath);
20
- for (const item of items) {
21
- if (ignoreList.includes(item))
22
- continue;
23
- const itemPath = path_1.default.join(folderPath, item);
24
- if (itemPath.startsWith(path_1.default.join(dir, ".scaffoldrite/history")))
25
- continue;
26
- const stat = fs_1.default.statSync(itemPath);
27
- if (stat.isDirectory()) {
28
- const childFolder = {
29
- type: "folder",
30
- name: item,
31
- children: [],
32
- };
33
- node.children.push(childFolder);
34
- scan(itemPath, childFolder);
35
- }
36
- else {
37
- const childFile = {
38
- type: "file",
39
- name: item,
40
- };
41
- node.children.push(childFile);
42
- }
43
- }
44
- }
45
- scan(dir, root);
46
- return root;
47
- }
package/dist/generator.js DELETED
@@ -1,152 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.generateFS = generateFS;
7
- const promises_1 = __importDefault(require("fs/promises"));
8
- const path_1 = __importDefault(require("path"));
9
- const visitor_1 = require("./visitor");
10
- // Helper function to check if file exists
11
- async function fileExists(filePath) {
12
- try {
13
- await promises_1.default.access(filePath);
14
- return true;
15
- }
16
- catch {
17
- return false;
18
- }
19
- }
20
- async function generateFS(ast, outputDir, options) {
21
- const root = path_1.default.resolve(outputDir);
22
- const sourceRoot = process.cwd(); // Get source directory for copying
23
- const ignoreList = options?.ignoreList ?? [];
24
- const copyContents = options?.copyContents ?? false;
25
- // ✅ store type info
26
- const expected = new Map();
27
- const actual = new Set();
28
- const ops = [];
29
- /* Helper: check if path is ignored */
30
- const isIgnored = (p) => {
31
- const name = path_1.default.basename(p);
32
- return ignoreList.includes(name);
33
- };
34
- /* 1️⃣ EXPECTED */
35
- expected.set(root, { type: "folder" });
36
- // Track source paths for files when copyContents is enabled
37
- const fileSourcePaths = new Map();
38
- await (0, visitor_1.visit)(ast, {
39
- folder: async (_, nodePath) => {
40
- const fullPath = path_1.default.join(root, nodePath);
41
- if (!isIgnored(fullPath)) {
42
- expected.set(fullPath, { type: "folder" });
43
- }
44
- },
45
- file: async (_, nodePath) => {
46
- const fullPath = path_1.default.join(root, nodePath);
47
- if (!isIgnored(fullPath)) {
48
- // Store source path for potential copying
49
- const sourcePath = path_1.default.join(sourceRoot, nodePath);
50
- expected.set(fullPath, {
51
- type: "file",
52
- sourcePath: sourcePath
53
- });
54
- fileSourcePaths.set(fullPath, sourcePath);
55
- }
56
- },
57
- });
58
- /* 2️⃣ ACTUAL */
59
- async function scan(dir) {
60
- if (isIgnored(dir))
61
- return;
62
- actual.add(dir);
63
- const entries = await promises_1.default.readdir(dir, { withFileTypes: true });
64
- for (const e of entries) {
65
- const full = path_1.default.join(dir, e.name);
66
- if (isIgnored(full))
67
- continue;
68
- actual.add(full);
69
- if (e.isDirectory())
70
- await scan(full);
71
- }
72
- }
73
- try {
74
- await scan(root);
75
- }
76
- catch { }
77
- /* 3️⃣ PLAN ops (NO FS MUTATION) */
78
- for (const [p, info] of expected.entries()) {
79
- if (actual.has(p)) {
80
- ops.push({ type: "skip", path: p, count: 0 });
81
- }
82
- else {
83
- // Determine operation type
84
- let operationType = info.type;
85
- // Check if we should copy contents for this file
86
- if (info.type === "file" && copyContents && info.sourcePath) {
87
- const sourceExists = await fileExists(info.sourcePath);
88
- if (sourceExists) {
89
- operationType = "copy";
90
- }
91
- }
92
- ops.push({
93
- type: operationType,
94
- path: p,
95
- count: 0,
96
- });
97
- }
98
- }
99
- const extras = [...actual]
100
- .filter((p) => !expected.has(p))
101
- .filter((p) => !p.startsWith(path_1.default.join(root, ".scaffoldrite/history")))
102
- .sort((a, b) => b.length - a.length);
103
- for (const p of extras) {
104
- ops.push({ type: "delete", path: p, count: 0 });
105
- }
106
- /* 4️⃣ START */
107
- options?.onStart?.(ops.length);
108
- /* 5️⃣ APPLY */
109
- let count = 0;
110
- for (const op of ops) {
111
- count++;
112
- if (!options?.dryRun) {
113
- if (op.type === "folder") {
114
- await promises_1.default.mkdir(op.path, { recursive: true });
115
- }
116
- else if (op.type === "file") {
117
- await promises_1.default.mkdir(path_1.default.dirname(op.path), { recursive: true });
118
- await promises_1.default.writeFile(op.path, "");
119
- }
120
- else if (op.type === "copy") {
121
- // Get source path from expected map
122
- const info = expected.get(op.path);
123
- if (info?.sourcePath) {
124
- try {
125
- await promises_1.default.mkdir(path_1.default.dirname(op.path), { recursive: true });
126
- await promises_1.default.copyFile(info.sourcePath, op.path);
127
- }
128
- catch (error) {
129
- // If copy fails, fall back to empty file
130
- console.warn(`Warning: Could not copy ${info.sourcePath} to ${op.path}, creating empty file instead`);
131
- await promises_1.default.writeFile(op.path, "");
132
- }
133
- }
134
- else {
135
- // Fallback to empty file if no source path
136
- await promises_1.default.mkdir(path_1.default.dirname(op.path), { recursive: true });
137
- await promises_1.default.writeFile(op.path, "");
138
- }
139
- }
140
- else if (op.type === "delete") {
141
- // KEEP THE ORIGINAL DELETE LOGIC
142
- if (op.path.startsWith(path_1.default.join(root, ".scaffoldrite/history")))
143
- continue;
144
- await promises_1.default.rm(op.path, { recursive: true, force: true });
145
- }
146
- }
147
- options?.onProgress?.({
148
- ...op,
149
- count,
150
- });
151
- }
152
- }
package/dist/history.js DELETED
@@ -1,21 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ensureHistoryDir = ensureHistoryDir;
7
- exports.writeHistory = writeHistory;
8
- const utils_1 = require("./utils");
9
- const node_path_1 = __importDefault(require("node:path"));
10
- const fs_1 = __importDefault(require("fs"));
11
- const HISTORY_DIR = node_path_1.default.join(utils_1.SCAFFOLDRITE_DIR, "history");
12
- function ensureHistoryDir() {
13
- if (!fs_1.default.existsSync(HISTORY_DIR)) {
14
- fs_1.default.mkdirSync(HISTORY_DIR, { recursive: true });
15
- }
16
- }
17
- function writeHistory(entry) {
18
- ensureHistoryDir();
19
- const filename = `${entry.id}-${entry.command}.json`;
20
- fs_1.default.writeFileSync(node_path_1.default.join(HISTORY_DIR, filename), JSON.stringify(entry, null, 2));
21
- }
@@ -1,129 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ai = void 0;
7
- const child_process_1 = require("child_process");
8
- const data_1 = require("../../data");
9
- const path_1 = __importDefault(require("path"));
10
- const fs_1 = __importDefault(require("fs"));
11
- const generateStructure_1 = require("./generateStructure");
12
- // ─────────────────────────────────────────────
13
- // HELPER: readline wrapper
14
- // ─────────────────────────────────────────────
15
- function createAsk() {
16
- const rl = require("readline").createInterface({
17
- input: process.stdin,
18
- output: process.stdout,
19
- });
20
- const ask = (q) => new Promise((res) => rl.question(q, res));
21
- return { ask, close: () => rl.close() };
22
- }
23
- // ─────────────────────────────────────────────
24
- // HELPER: sanitize AI output for ScaffoldRite
25
- // ─────────────────────────────────────────────
26
- function sanitizeStructureSR(input) {
27
- return input
28
- .split("\n")
29
- .filter((line) => !line.match(/^\s*(STRUCTURE|FORMAT|SYNTAX|RULES)/i))
30
- .join("\n")
31
- .trim();
32
- }
33
- // ─────────────────────────────────────────────
34
- // MAIN AI FUNCTION
35
- // ─────────────────────────────────────────────
36
- const ai = async () => {
37
- try {
38
- // ─────────────────────────────────────────────
39
- // 1️⃣ INITIAL QUESTIONS
40
- // ─────────────────────────────────────────────
41
- let { ask, close } = createAsk();
42
- const projectName = await ask("Project name: ");
43
- const framework = await ask("Framework (react, vue, vanilla): ");
44
- const language = await ask("Language (js, ts): ");
45
- close(); // ❗ CLOSE BEFORE execSync
46
- // ─────────────────────────────────────────────
47
- // 2️⃣ CREATE VITE PROJECT
48
- // ─────────────────────────────────────────────
49
- let template = framework.toLowerCase();
50
- if (framework === "react" && language === "ts")
51
- template = "react-ts";
52
- if (framework === "vue" && language === "ts")
53
- template = "vue-ts";
54
- if (framework === "vanilla" && language === "ts")
55
- template = "vanilla-ts";
56
- (0, child_process_1.execSync)(`npx create-vite@latest "${projectName}" --template ${template} --no-rolldown --no-immediate`, {
57
- stdio: "inherit",
58
- shell: process.platform === "win32" ? "cmd.exe" : "/bin/sh",
59
- });
60
- const projectPath = path_1.default.resolve(process.cwd(), projectName);
61
- // ─────────────────────────────────────────────
62
- // 3️⃣ INIT SCAFFOLDRITE
63
- // ─────────────────────────────────────────────
64
- (0, child_process_1.execSync)("sr init --from-fs .", {
65
- cwd: projectPath,
66
- stdio: "inherit",
67
- shell: process.platform === "win32" ? "cmd.exe" : "/bin/sh",
68
- });
69
- // ─────────────────────────────────────────────
70
- // 4️⃣ ASK FOR AI ASSISTANCE
71
- // ─────────────────────────────────────────────
72
- ({ ask, close } = createAsk());
73
- const wantAI = await ask("\n🤖 Do you want AI assistance in scaffolding the structure of your app? (yes/no): ");
74
- if (wantAI.toLowerCase() === "yes") {
75
- while (true) {
76
- const description = await ask("\n📝 Describe your project or what you want to add/change:\n");
77
- const structurePath = path_1.default.join(projectPath, ".scaffoldrite", "structure.sr");
78
- const existingStructure = fs_1.default.readFileSync(structurePath, "utf-8");
79
- const result = await (0, generateStructure_1.generateStructure)({
80
- existingStructure,
81
- description,
82
- });
83
- // 🧠 CLARIFICATION MODE
84
- if (result.startsWith("CLARIFICATION_REQUIRED")) {
85
- console.log("\n🤖 I need clarification:\n");
86
- console.log(result);
87
- const confirm = await ask("\nIs this what you meant? (yes/no): ");
88
- if (confirm.toLowerCase() === "yes") {
89
- await ask("\n✏️ Please rephrase clearly what you want:\n");
90
- continue;
91
- }
92
- else {
93
- console.log("\n🔁 Okay, please describe what you want again.\n");
94
- continue;
95
- }
96
- }
97
- // ✅ STRUCTURE MODE
98
- const clean = sanitizeStructureSR(result);
99
- fs_1.default.writeFileSync(structurePath, clean);
100
- // Generate the project structure
101
- (0, child_process_1.execSync)("sr generate .", {
102
- cwd: projectPath,
103
- stdio: "inherit",
104
- });
105
- (0, child_process_1.execSync)("sr list --sr --with-icon", {
106
- cwd: projectPath,
107
- stdio: "inherit",
108
- });
109
- // Ask if satisfied
110
- ({ ask, close } = createAsk());
111
- const satisfied = await ask("\n✅ Are you satisfied with the structure? (yes/no): ");
112
- if (satisfied.toLowerCase() === "yes")
113
- break;
114
- }
115
- }
116
- close();
117
- // ─────────────────────────────────────────────
118
- // 5️⃣ FINISH
119
- // ─────────────────────────────────────────────
120
- console.log(data_1.theme.success(`\n🎉 Project ${projectName} is ready!\n`));
121
- console.log(data_1.theme.muted(` cd ${projectName}`));
122
- console.log(data_1.theme.muted(" npm install"));
123
- console.log(data_1.theme.muted(" npm run dev"));
124
- }
125
- catch (err) {
126
- console.error(data_1.theme.error(`❌ Failed: ${err.message}`));
127
- }
128
- };
129
- exports.ai = ai;
@@ -1,28 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.generateStructure = generateStructure;
7
- const node_fetch_1 = __importDefault(require("node-fetch"));
8
- async function generateStructure(params) {
9
- try {
10
- const response = await (0, node_fetch_1.default)("http://localhost:3000/generate-structure", {
11
- method: "POST",
12
- headers: { "Content-Type": "application/json" },
13
- body: JSON.stringify(params),
14
- });
15
- if (!response.ok) {
16
- const text = await response.text();
17
- throw new Error(`Backend error: ${text}`);
18
- }
19
- const data = await response.json();
20
- if (typeof data?.result !== "string") {
21
- throw new Error("Invalid backend response: result missing");
22
- }
23
- return data.result;
24
- }
25
- catch (err) {
26
- throw new Error(`Failed to generate structure: ${err.message}`);
27
- }
28
- }
@@ -1,75 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.generateStructureWithGroq = generateStructureWithGroq;
7
- const node_fetch_1 = __importDefault(require("node-fetch"));
8
- async function generateStructureWithGroq(params) {
9
- const { existingStructure, description } = params;
10
- const GROQ_API_KEY = process.env.GROQ_API_KEY;
11
- if (!GROQ_API_KEY) {
12
- console.error("❌ GROQ_API_KEY is missing.");
13
- console.error("➡️ Add it to your .env file:");
14
- console.error(" GROQ_API_KEY=your_key_here");
15
- process.exit(1);
16
- }
17
- const systemPrompt = `
18
- You are a frontend project structure generator for Scaffoldrite.
19
-
20
- STRICT RULES:
21
- - Output ONLY valid structure.sr syntax
22
- - DO NOT include markdown
23
- - DO NOT explain anything
24
- - DO NOT add comments
25
- - DO NOT wrap output in code blocks
26
- - Preserve all existing files and folders
27
- - Only ADD or EXTEND structure where necessary
28
- - NEVER delete existing entries
29
- - Frontend-only structure
30
- - Ignore backend, database, server, API implementation details
31
- - Backend mentions should be interpreted as frontend needs
32
- - Valid entities: folder, file
33
- - Maintain correct indentation
34
- `;
35
- const userPrompt = `
36
- EXISTING STRUCTURE:
37
- ${existingStructure}
38
-
39
- PROJECT DESCRIPTION:
40
- ${description}
41
-
42
- TASK:
43
- Update the existing structure to satisfy the description.
44
- `;
45
- const response = await (0, node_fetch_1.default)("https://api.groq.com/openai/v1/chat/completions", {
46
- method: "POST",
47
- headers: {
48
- "Authorization": `Bearer ${GROQ_API_KEY}`,
49
- "Content-Type": "application/json",
50
- },
51
- body: JSON.stringify({
52
- model: "llama-3.1-70b-versatile",
53
- temperature: 0.2,
54
- max_tokens: 1500,
55
- messages: [
56
- { role: "system", content: systemPrompt },
57
- { role: "user", content: userPrompt },
58
- ],
59
- }),
60
- });
61
- if (!response.ok) {
62
- const text = await response.text();
63
- throw new Error(`Groq API error: ${text}`);
64
- }
65
- const data = (await response.json());
66
- const output = data.choices?.[0]?.message?.content;
67
- if (!output || typeof output !== "string") {
68
- throw new Error("Groq returned empty structure");
69
- }
70
- // 🔒 Final safety check
71
- if (!output.includes("folder") && !output.includes("file")) {
72
- throw new Error("Invalid structure.sr output from Groq");
73
- }
74
- return output.trim();
75
- }
@@ -1,25 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.generateStructure = generateStructure;
7
- const node_fetch_1 = __importDefault(require("node-fetch"));
8
- async function generateStructure(params) {
9
- try {
10
- const response = await (0, node_fetch_1.default)("https://your-backend.com/generate-structure", {
11
- method: "POST",
12
- headers: { "Content-Type": "application/json" },
13
- body: JSON.stringify(params),
14
- });
15
- if (!response.ok) {
16
- const text = await response.text();
17
- throw new Error(`Backend error: ${text}`);
18
- }
19
- const data = await response.json();
20
- return data.structure;
21
- }
22
- catch (err) {
23
- throw new Error(`Failed to generate structure: ${err.message}`);
24
- }
25
- }
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });