create-fs-structure 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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ ```text
2
+ MIT License
3
+
4
+ Copyright (c) 2025 Maxim Bulavchikov
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # Create Structure
2
+
3
+ CLI tool to create directory and file structure from a text scheme.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ # Install globally
9
+ npm install -g create-structure
10
+
11
+ # Or use with npx
12
+ npx create-structure scheme.txt ./my-project
13
+ ```
14
+
15
+ ## Usage
16
+ ```bash
17
+ # Create structure from scheme.ts (or .txt) in current directory
18
+ create-structure
19
+
20
+ # Specify scheme file and target directory
21
+ create-structure ./my-scheme.txt ./my-project
22
+
23
+ # Dry run (show what would be created)
24
+ create-structure --dry-run scheme.txt ./my-project
25
+
26
+ # Show help
27
+ create-structure --help
28
+ ```
29
+
30
+ ## Scheme Format
31
+ ```bash
32
+ # Create a text (.ts or .txt) file with your desired structure:
33
+
34
+ text
35
+ ├── components/
36
+ │ ├── Button/
37
+ │ │ ├── Button.tsx
38
+ │ │ └── index.ts
39
+ │ └── Header.tsx
40
+ ├── utils/
41
+ │ └── helpers.ts
42
+ └── package.json
43
+ ```
package/bin/cli.cjs ADDED
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env node
2
+ const { createStructureFromScheme, parseLine } = require('../lib/createStructure.cjs');
3
+ const { existsSync, statSync, readFileSync } = require('fs');
4
+ const { join, resolve } = require('path');
5
+
6
+ // Функция для вывода справки
7
+ function showHelp() {
8
+ console.log(`
9
+ Использование: node create-structure.js [ПУТЬ_К_СХЕМЕ] [ЦЕЛЕВАЯ_ПАПКА]
10
+
11
+ Аргументы:
12
+ ПУТЬ_К_СХЕМЕ Путь к файлу схемы (по умолчанию: ./scheme.ts)
13
+ ЦЕЛЕВАЯ_ПАПКА Путь к папке для создания структуры (по умолчанию: текущая папка)
14
+
15
+ Особенности:
16
+ - Если файл уже существует, он не будет перезаписан
17
+ - Если папка уже существует, скрипт продолжит работу внутри нее
18
+ - Несуществующие родительские папки будут созданы автоматически
19
+ - Файлы получают базовое содержимое в зависимости от расширения
20
+
21
+ Примеры:
22
+ node create-structure.js # Использует scheme.ts и создает в текущей папке
23
+ node create-structure.js ./my-scheme.txt # Использует my-scheme.txt в текущей папке
24
+ node create-structure.js scheme.ts ./my-app # Использует scheme.ts, создает в ./my-app
25
+ node create-structure.js ../scheme.txt ../proj # Использует схему на уровень выше
26
+
27
+ Поддерживаемые форматы схемы:
28
+ ├── components/ # Папка
29
+ │ ├── Button.tsx # Файл
30
+ └── utils/ # Папка
31
+ `);
32
+ }
33
+
34
+ function dryRun(schemeFile, targetDir) {
35
+ console.log(`📄 Схема: ${schemeFile}`);
36
+ console.log(`📁 Целевая папка: ${resolve(targetDir)}`);
37
+
38
+ if (!existsSync(schemeFile)) {
39
+ console.error(`❌ Файл схемы не найден: ${schemeFile}`);
40
+ process.exit(1);
41
+ }
42
+
43
+ const content = readFileSync(schemeFile, "utf8");
44
+ const lines = content.split("\n");
45
+
46
+ console.log("\n📋 Планируемые действия:");
47
+
48
+ const pathStack = [targetDir];
49
+ let minLevel = Infinity;
50
+ const parsedLines = [];
51
+
52
+ // Парсим все строки
53
+ for (const line of lines) {
54
+ if (!line.trim()) continue;
55
+ const parsed = parseLine(line);
56
+ if (!parsed) continue;
57
+ if (parsed.level < minLevel) minLevel = parsed.level;
58
+ parsedLines.push(parsed);
59
+ }
60
+
61
+ // Симулируем создание
62
+ for (const parsed of parsedLines) {
63
+ const normalizedLevel = parsed.level - minLevel;
64
+ while (pathStack.length > normalizedLevel + 1) {
65
+ pathStack.pop();
66
+ }
67
+
68
+ const currentPath = pathStack.slice(1).join("/");
69
+ const fullPath = join(targetDir, currentPath, parsed.name);
70
+
71
+ if (existsSync(fullPath)) {
72
+ const stats = statSync(fullPath);
73
+ const type = stats.isDirectory() ? "папка" : "файл";
74
+ console.log(
75
+ ` ⏭️ Будет пропущен (уже существует): ${fullPath} (${type})`
76
+ );
77
+ } else {
78
+ const type = parsed.isDir ? "папка" : "файл";
79
+ console.log(` ✅ Будет создан: ${fullPath} (${type})`);
80
+ }
81
+
82
+ if (parsed.isDir) {
83
+ pathStack.push(parsed.name);
84
+ }
85
+ }
86
+
87
+ console.log(
88
+ "\n🔍 Проверка завершена. Для создания файлов запустите без флага --dry-run"
89
+ );
90
+ }
91
+
92
+ function main() {
93
+ const args = process.argv.slice(2);
94
+
95
+ if (args.includes("--help") || args.includes("-h")) {
96
+ showHelp();
97
+ return;
98
+ }
99
+
100
+ if (args.includes("--version") || args.includes("-v")) {
101
+ console.log("create-structure v1.0.0");
102
+ return;
103
+ }
104
+
105
+ const dryRunFlag = args.includes("--dry-run");
106
+ if (dryRunFlag) {
107
+ console.log("🔍 Режим проверки (dry run) - файлы не будут созданы");
108
+ }
109
+
110
+ const filteredArgs = args.filter(
111
+ (arg) => !arg.startsWith("--") && !arg.startsWith("-")
112
+ );
113
+
114
+ let schemeFile = "scheme.ts";
115
+ let targetDir = ".";
116
+
117
+ if (filteredArgs.length === 1) {
118
+ const arg = filteredArgs[0];
119
+ if (existsSync(arg) && statSync(arg).isFile()) {
120
+ schemeFile = arg;
121
+ } else {
122
+ targetDir = arg;
123
+ }
124
+ } else if (filteredArgs.length >= 2) {
125
+ schemeFile = filteredArgs[0];
126
+ targetDir = filteredArgs[1];
127
+ }
128
+
129
+ if (dryRunFlag) {
130
+ dryRun(schemeFile, targetDir);
131
+ return;
132
+ }
133
+
134
+ // Запускаем создание структуры
135
+ createStructureFromScheme(schemeFile, targetDir);
136
+ }
137
+
138
+ // Запуск
139
+ main();
package/bin/index.cjs ADDED
@@ -0,0 +1,4 @@
1
+ export {
2
+ createStructureFromScheme,
3
+ parseLine,
4
+ } from "../lib/createStructure.cjs";
@@ -0,0 +1,4 @@
1
+ {
2
+ "type": "module",
3
+ "main": "./cli.js"
4
+ }
@@ -0,0 +1,154 @@
1
+ const { existsSync, mkdirSync, readFileSync, writeFileSync, statSync } = require('fs');
2
+ const { join, dirname, extname, basename, resolve } = require('path');
3
+
4
+ function parseLine(line) {
5
+ // Удаляем символы дерева, оставляем только отступы
6
+ let indent = 0;
7
+
8
+ // Считаем отступы до первого не-дерева символа
9
+ for (let i = 0; i < line.length; i++) {
10
+ const char = line[i];
11
+ if (
12
+ char === " " ||
13
+ char === "│" ||
14
+ char === "├" ||
15
+ char === "└" ||
16
+ char === "─"
17
+ ) {
18
+ indent++;
19
+ } else {
20
+ break;
21
+ }
22
+ }
23
+
24
+ // Каждые 4 символа = 1 уровень
25
+ const level = Math.floor(indent / 4);
26
+
27
+ // Получаем чистую строку
28
+ const clean = line.slice(indent).trim();
29
+ if (!clean) return null;
30
+
31
+ const isDir = clean.endsWith("/");
32
+ const name = isDir ? clean.slice(0, -1) : clean;
33
+
34
+ return { level, isDir, name };
35
+ }
36
+
37
+ function createStructureFromScheme(schemeFile, targetDir = ".") {
38
+ try {
39
+ if (!existsSync(schemeFile)) {
40
+ throw new Error(`Файл схемы не найден: ${schemeFile}`);
41
+ }
42
+
43
+ const content = readFileSync(schemeFile, "utf8");
44
+ const lines = content.split("\n");
45
+
46
+ const pathStack = [targetDir];
47
+ let createdCount = 0;
48
+ let skippedCount = 0;
49
+
50
+ console.log(`📄 Чтение схемы из: ${schemeFile}`);
51
+ console.log(`📁 Создание структуры в: ${resolve(targetDir)}\n`);
52
+
53
+ // Сначала найдем минимальный отступ, чтобы нормализовать уровни
54
+ let minLevel = Infinity;
55
+ const parsedLines = [];
56
+
57
+ for (const line of lines) {
58
+ if (!line.trim()) continue;
59
+
60
+ // Парсим строку
61
+ const parsed = parseLine(line);
62
+ if (!parsed) continue;
63
+
64
+ // Запоминаем минимальный уровень
65
+ if (parsed.level < minLevel) {
66
+ minLevel = parsed.level;
67
+ }
68
+
69
+ parsedLines.push(parsed);
70
+ }
71
+
72
+ // Обрабатываем каждую строку
73
+ for (const parsed of parsedLines) {
74
+ // Нормализуем уровень (вычитаем минимальный)
75
+ const normalizedLevel = parsed.level - minLevel;
76
+
77
+ // Обновляем стек пути - это КРИТИЧЕСКИ важная часть!
78
+ while (pathStack.length > normalizedLevel + 1) {
79
+ pathStack.pop();
80
+ }
81
+
82
+ // Строим полный путь
83
+ const currentPath = pathStack.slice(1).join("/");
84
+ const fullPath = join(targetDir, currentPath, parsed.name);
85
+
86
+ // Создаем элемент
87
+ if (parsed.isDir) {
88
+ try {
89
+ if (existsSync(fullPath)) {
90
+ console.log(`✓ Папка уже существует: ${fullPath}`);
91
+ skippedCount++;
92
+ } else {
93
+ mkdirSync(fullPath, { recursive: true });
94
+ console.log(`✓ Создана новая папка: ${fullPath}`);
95
+ createdCount++;
96
+ }
97
+ // Добавляем папку в стек для следующего уровня
98
+ pathStack.push(parsed.name);
99
+ } catch (err) {
100
+ console.error(`✗ Ошибка создания папки ${fullPath}:`, err.message);
101
+ }
102
+ } else {
103
+ try {
104
+ // Создаем родительскую папку если нужно
105
+ const parentDir = dirname(fullPath);
106
+ if (!existsSync(parentDir)) {
107
+ mkdirSync(parentDir, { recursive: true });
108
+ console.log(`✓ Создана родительская папка: ${parentDir}`);
109
+ createdCount++;
110
+ }
111
+
112
+ // Проверяем существование файла
113
+ if (existsSync(fullPath)) {
114
+ console.log(`✓ Файл уже существует: ${fullPath}`);
115
+ skippedCount++;
116
+ continue;
117
+ }
118
+
119
+ // Создаем файл с базовым содержимым
120
+ const ext = extname(parsed.name);
121
+ let content = "";
122
+
123
+ if (ext === ".tsx" || ext === ".ts") {
124
+ const componentName = basename(parsed.name, ext);
125
+ content = `// ${parsed.name}\n// Auto-generated\n\nexport const ${componentName} = () => {\n return (\n <div>\n {/* Content */}\n </div>\n );\n}\n`;
126
+ } else if (ext === ".css") {
127
+ content = `/* ${parsed.name} */\n/* Auto-generated */\n\n.container {\n /* Styles */\n}\n`;
128
+ } else {
129
+ content = `// ${parsed.name}\n// Auto-generated\n`;
130
+ }
131
+
132
+ writeFileSync(fullPath, content);
133
+ console.log(`✓ Создан новый файл: ${fullPath}`);
134
+ createdCount++;
135
+ } catch (err) {
136
+ console.error(`✗ Ошибка создания файла ${fullPath}:`, err.message);
137
+ }
138
+ }
139
+ }
140
+
141
+ console.log(`\n📊 Результат:`);
142
+ console.log(` ✅ Создано новых элементов: ${createdCount}`);
143
+ console.log(` ⏭️ Пропущено существующих: ${skippedCount}`);
144
+ console.log(`\n🎉 Структура успешно создана в ${resolve(targetDir)}`);
145
+ } catch (error) {
146
+ console.error("❌ Ошибка:", error.message);
147
+ process.exit(1);
148
+ }
149
+ }
150
+
151
+ module.exports = {
152
+ parseLine,
153
+ createStructureFromScheme
154
+ };
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "create-fs-structure",
3
+ "version": "1.0.0",
4
+ "description": "CLI tool to create directory and file structure from a text scheme",
5
+ "main": "bin/index.js",
6
+ "type": "commonjs",
7
+ "bin": {
8
+ "create-structure": "./bin/cli.cjs"
9
+ },
10
+ "scripts": {
11
+ "test": "echo \"Error: no test specified\" && exit 1"
12
+ },
13
+ "keywords": [
14
+ "scaffolding",
15
+ "generator",
16
+ "cli",
17
+ "structure",
18
+ "filesystem"
19
+ ],
20
+ "author": "Your Name <your.email@example.com>",
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/your-username/create-structure.git"
25
+ },
26
+ "bugs": {
27
+ "url": "https://github.com/your-username/create-structure/issues"
28
+ },
29
+ "homepage": "https://github.com/your-username/create-structure#readme",
30
+ "engines": {
31
+ "node": ">=14.0.0"
32
+ },
33
+ "dependencies": {},
34
+ "devDependencies": {}
35
+ }