@vv0rkz/js-template 1.3.0 → 1.4.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/bin/init.js CHANGED
@@ -2,29 +2,83 @@
2
2
  import { fileURLToPath } from 'url'
3
3
  import { dirname, join } from 'path'
4
4
  import { copyFileSync, mkdirSync, existsSync, readFileSync, writeFileSync, readdirSync, statSync } from 'fs'
5
- import { execSync } from 'child_process'
5
+ import { execSync, spawnSync } from 'child_process'
6
+ import * as readline from 'readline'
6
7
 
7
8
  const __dirname = dirname(fileURLToPath(import.meta.url))
8
9
  const templateDir = join(__dirname, '../templates')
9
10
  const targetDir = process.cwd()
11
+ const toolsDir = join(__dirname, '../tools-gh')
10
12
 
11
13
  console.log('⚡ JS Template by @vv0rkz — Инициализация проекта\n')
12
14
 
13
- // 1. Копирование конфигов
14
- console.log('📋 Копирование конфигов...')
15
+ // Функция для интерактивного вопроса
16
+ function askQuestion(query) {
17
+ const rl = readline.createInterface({
18
+ input: process.stdin,
19
+ output: process.stdout,
20
+ })
21
+
22
+ return new Promise((resolve) =>
23
+ rl.question(query, (ans) => {
24
+ rl.close()
25
+ resolve(ans)
26
+ })
27
+ )
28
+ }
29
+
30
+ // 0. Проверка git репозитория
31
+ console.log('🔍 Проверка git...')
32
+ const hasGit = existsSync(join(targetDir, '.git'))
33
+
34
+ if (!hasGit) {
35
+ console.log(' ⚠️ Git репозиторий не найден')
36
+ const answer = await askQuestion(' ❓ Инициализировать git репозиторий? (Y/n): ')
37
+
38
+ if (answer.toLowerCase() !== 'n' && answer.toLowerCase() !== 'no') {
39
+ try {
40
+ execSync('git init', { stdio: 'inherit', cwd: targetDir })
41
+ console.log(' ✅ Git репозиторий создан')
42
+ } catch (error) {
43
+ console.log(' ❌ Ошибка создания git репозитория')
44
+ console.log(' Создай вручную: git init')
45
+ }
46
+ } else {
47
+ console.log(' ⏭️ Git пропущен')
48
+ console.log(' ⚠️ Без git некоторые функции могут не работать (husky, gh)')
49
+ }
50
+ } else {
51
+ console.log(' ✅ Git репозиторий найден')
52
+ }
53
+
54
+ // 1. Копирование конфигов с интерактивной перезаписью
55
+ console.log('\n📋 Копирование конфигов...')
15
56
  const filesToCopy = ['.gitignore', 'changelog.config.js', 'commitlint.config.js']
16
57
 
17
- filesToCopy.forEach((file) => {
58
+ for (const file of filesToCopy) {
18
59
  const src = join(templateDir, file)
19
60
  const dest = join(targetDir, file)
20
61
 
62
+ if (!existsSync(src)) {
63
+ console.log(` ⚠️ ${file} не найден в template (пропускаем)`)
64
+ continue
65
+ }
66
+
21
67
  if (existsSync(dest)) {
22
- console.log(` ⚠️ ${file} уже существует, пропускаем`)
68
+ // Файл существует - спрашиваем что делать
69
+ const answer = await askQuestion(` ❓ ${file} уже существует. Перезаписать? (y/N): `)
70
+
71
+ if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
72
+ copyFileSync(src, dest)
73
+ console.log(` ✅ ${file} (перезаписан)`)
74
+ } else {
75
+ console.log(` ⏭️ ${file} (пропущен)`)
76
+ }
23
77
  } else {
24
78
  copyFileSync(src, dest)
25
79
  console.log(` ✅ ${file}`)
26
80
  }
27
- })
81
+ }
28
82
 
29
83
  // 2. Копирование .husky
30
84
  console.log('\n🐶 Настройка husky хуков...')
@@ -33,7 +87,6 @@ if (!existsSync(huskyDir)) {
33
87
  mkdirSync(huskyDir, { recursive: true })
34
88
  }
35
89
 
36
- // Копирование всей папки .husky
37
90
  const huskyTemplateDir = join(templateDir, '.husky')
38
91
  if (existsSync(huskyTemplateDir)) {
39
92
  const copyDir = (src, dest) => {
@@ -56,9 +109,11 @@ if (existsSync(huskyTemplateDir)) {
56
109
 
57
110
  copyDir(huskyTemplateDir, huskyDir)
58
111
  console.log(' ✅ Хуки скопированы')
112
+ } else {
113
+ console.log(' ⚠️ .husky не найден в template')
59
114
  }
60
115
 
61
- // 3. НЕ копируем tools-gh — они остаются в node_modules
116
+ // 3. НЕ копируем tools-gh
62
117
  console.log('\n🔧 GitHub скрипты...')
63
118
  console.log(' ✅ Используются из @vv0rkz/js-template (не копируются)')
64
119
 
@@ -68,7 +123,6 @@ const packageJsonPath = join(targetDir, 'package.json')
68
123
  if (existsSync(packageJsonPath)) {
69
124
  const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'))
70
125
 
71
- // Добавляем только минимум скриптов
72
126
  packageJson.scripts = {
73
127
  ...packageJson.scripts,
74
128
  prepare: 'husky',
@@ -76,11 +130,10 @@ if (existsSync(packageJsonPath)) {
76
130
  _: 'jst',
77
131
  }
78
132
 
79
- // Добавляем зависимость
80
133
  if (!packageJson.devDependencies) {
81
134
  packageJson.devDependencies = {}
82
135
  }
83
- packageJson.devDependencies['@vv0rkz/js-template'] = '^1.0.0'
136
+ packageJson.devDependencies['@vv0rkz/js-template'] = '^1.4.0'
84
137
 
85
138
  writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2))
86
139
  console.log(' ✅ Скрипты добавлены')
@@ -107,6 +160,7 @@ try {
107
160
  } catch (error) {
108
161
  console.log(' ⚠️ Husky уже инициализирован')
109
162
  }
163
+
110
164
  // 7. Настройка GitHub labels
111
165
  console.log('\n🏷️ Настройка GitHub labels...')
112
166
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vv0rkz/js-template",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Reusable setup for JS projects with husky, changelog, gh tools",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,70 @@
1
+ # {{PROJECT_NAME}}
2
+
3
+ {{PROJECT_DESCRIPTION}}
4
+
5
+ <!-- AUTOGENERATED_SECTION START -->
6
+ <!-- AUTOGENERATED_SECTION END -->
7
+
8
+ ## 🛠️ Для разработчиков
9
+
10
+ ### 📋 Workflow разработки
11
+
12
+ ```bash
13
+ [ Придумал фичу / Нашёл баг ]
14
+
15
+ [ Создание задачи ] → npm run _ create-task/create-bug
16
+
17
+ [ Разработка в ветке vX.Y.Z-description ]
18
+
19
+ [ Коммиты с валидацией ] → feat/fix: #номер описание
20
+
21
+ [ Добавление демо ] → docs/vX.Y.Z.gif
22
+
23
+ [ Релиз ] → npm run _ release
24
+
25
+ [ Авто-обновление CHANGELOG, README ]
26
+ ```
27
+
28
+ **🚀 Пример (калькулятор):**
29
+
30
+ ```bash
31
+ # 1) Создание задачи
32
+ npm run _ create-task "Нормализация чисел: 0123 → 123"
33
+ # → Создаётся issue #9
34
+
35
+ # 2) Создание ветки в формате vX.Y.Z-description
36
+ git checkout -b v2.3.0-normalize-numbers
37
+
38
+ # 3) Коммиты в формате feat: #N (где #N номер созданного issue)
39
+ git commit -m "feat: #9 добавлена нормализация чисел"
40
+
41
+ # 4) Релиз
42
+ npm run _ release
43
+ # ✅ Создаётся:
44
+ # - CHANGELOG.md с фичей #9
45
+ # - Git tag v2.3.0
46
+ # - README обновляется автономно
47
+ 📋 Бэклог задач:
48
+
49
+ Открытые задачи (tasks)
50
+
51
+ Активные баги (bugs)
52
+
53
+ Все issues
54
+
55
+ 🔧 Workflow
56
+ Проект использует @vv0rkz/js-template для автоматизации:
57
+
58
+ ✅ Git hooks (husky) — проверка коммитов
59
+
60
+ ✅ Changelog генерация (changelogen)
61
+
62
+ ✅ GitHub issues integration
63
+
64
+ ✅ Автоматическое обновление версий
65
+
66
+ 📄 Лицензия
67
+ {{LICENSE}} © {{AUTHOR}}
68
+
69
+ Создано с помощью @vv0rkz/js-template
70
+ ```
@@ -11,6 +11,8 @@ if (!title) {
11
11
  }
12
12
 
13
13
  try {
14
+ console.log('🐛 Создаю баг...')
15
+
14
16
  // Создаем issue в GitHub
15
17
  execSync(`gh issue create --title "Bug: ${title}" --body "Баг обнаружен" --label "bug" --assignee "@me"`, {
16
18
  stdio: 'inherit',
@@ -18,9 +20,34 @@ try {
18
20
 
19
21
  console.log('🐛 Баг зарегистрирован!')
20
22
  } catch (error) {
21
- console.error('❌ Ошибка создания бага:', error.message)
22
- console.log('\n💡 Убедись что:')
23
- console.log(' 1. Установлен GitHub CLI: gh --version')
24
- console.log(' 2. Выполнена авторизация: gh auth login')
25
- process.exit(1)
23
+ // Если ошибка с label - создаём его автоматически
24
+ if (error.message.includes("'bug' not found") || error.stderr?.includes("'bug' not found")) {
25
+ console.log("\n⚠️ Label 'bug' не найден. Создаю автоматически...")
26
+
27
+ try {
28
+ // Создаём label
29
+ execSync('gh label create bug --color "D73A4A" --description "Баг который нужно исправить"', { stdio: 'ignore' })
30
+ console.log("✅ Label 'bug' создан")
31
+
32
+ // Пытаемся создать баг ещё раз
33
+ console.log('🐛 Создаю баг...')
34
+ execSync(`gh issue create --title "Bug: ${title}" --body "Баг обнаружен" --label "bug" --assignee "@me"`, {
35
+ stdio: 'inherit',
36
+ })
37
+
38
+ console.log('🐛 Баг зарегистрирован!')
39
+ } catch (retryError) {
40
+ console.error('❌ Ошибка создания бага:', retryError.message)
41
+ console.log('\n💡 Попробуй:')
42
+ console.log(' npm run _ setup-labels')
43
+ process.exit(1)
44
+ }
45
+ } else {
46
+ console.error('❌ Ошибка создания бага:', error.message)
47
+ console.log('\n💡 Убедись что:')
48
+ console.log(' 1. Установлен GitHub CLI: gh --version')
49
+ console.log(' 2. Выполнена авторизация: gh auth login')
50
+ console.log(' 3. Создан репозиторий на GitHub')
51
+ process.exit(1)
52
+ }
26
53
  }
@@ -12,15 +12,42 @@ if (!title) {
12
12
 
13
13
  try {
14
14
  console.log('📝 Создаю задачу...')
15
+
16
+ // Пытаемся создать задачу с label
15
17
  execSync(`gh issue create --title "Task: ${title}" --body "Задача: ${title}" --label "task"`, {
16
18
  stdio: 'inherit',
17
19
  })
18
20
 
19
21
  console.log('✅ Задача создана! Используй номер в коммитах: feat: #номер описание')
20
22
  } catch (error) {
21
- console.error('❌ Ошибка создания задачи:', error.message)
22
- console.log('\n💡 Убедись что:')
23
- console.log(' 1. Установлен GitHub CLI: gh --version')
24
- console.log(' 2. Выполнена авторизация: gh auth login')
25
- process.exit(1)
23
+ // Если ошибка с label - создаём его автоматически
24
+ if (error.message.includes("'task' not found") || error.stderr?.includes("'task' not found")) {
25
+ console.log("\n⚠️ Label 'task' не найден. Создаю автоматически...")
26
+
27
+ try {
28
+ // Создаём label
29
+ execSync('gh label create task --color "0E8A16" --description "Задача для реализации"', { stdio: 'ignore' })
30
+ console.log("✅ Label 'task' создан")
31
+
32
+ // Пытаемся создать задачу ещё раз
33
+ console.log('📝 Создаю задачу...')
34
+ execSync(`gh issue create --title "Task: ${title}" --body "Задача: ${title}" --label "task"`, {
35
+ stdio: 'inherit',
36
+ })
37
+
38
+ console.log('✅ Задача создана!')
39
+ } catch (retryError) {
40
+ console.error('❌ Ошибка создания задачи:', retryError.message)
41
+ console.log('\n💡 Попробуй:')
42
+ console.log(' npm run _ setup-labels')
43
+ process.exit(1)
44
+ }
45
+ } else {
46
+ console.error('❌ Ошибка создания задачи:', error.message)
47
+ console.log('\n💡 Убедись что:')
48
+ console.log(' 1. Установлен GitHub CLI: gh --version')
49
+ console.log(' 2. Выполнена авторизация: gh auth login')
50
+ console.log(' 3. Создан репозиторий на GitHub')
51
+ process.exit(1)
52
+ }
26
53
  }
@@ -1,61 +1,97 @@
1
1
  #!/usr/bin/env node
2
2
  import { readFileSync, writeFileSync, existsSync } from 'fs'
3
+ import { fileURLToPath } from 'url'
4
+ import { dirname, join } from 'path'
5
+ import * as readline from 'readline'
6
+
7
+ const __dirname = dirname(fileURLToPath(import.meta.url))
8
+ const templateDir = join(__dirname, '../templates')
3
9
 
4
10
  console.log('📝 Генерация стартового README.md...')
5
11
 
12
+ // Функция для интерактивного вопроса
13
+ function askQuestion(query) {
14
+ const rl = readline.createInterface({
15
+ input: process.stdin,
16
+ output: process.stdout,
17
+ })
18
+
19
+ return new Promise((resolve) =>
20
+ rl.question(query, (ans) => {
21
+ rl.close()
22
+ resolve(ans)
23
+ })
24
+ )
25
+ }
26
+
27
+ // Проверяем существование README
28
+ if (existsSync('README.md')) {
29
+ const answer = await askQuestion('⚠️ README.md уже существует. Перезаписать? (y/N): ')
30
+
31
+ if (answer.toLowerCase() !== 'y' && answer.toLowerCase() !== 'yes') {
32
+ console.log('⏭️ Создание README отменено')
33
+ process.exit(0)
34
+ }
35
+
36
+ console.log('✅ README.md будет перезаписан\n')
37
+ }
38
+
6
39
  // Читаем package.json
7
40
  const packageJson = JSON.parse(readFileSync('package.json', 'utf8'))
8
41
 
9
- const projectName = packageJson.name
42
+ const projectName = packageJson.name || 'Project'
10
43
  const description = packageJson.description || 'Описание проекта'
11
44
  const author = packageJson.author || 'vv0rkz'
12
45
  const license = packageJson.license || 'MIT'
13
- const repoUrl = packageJson.repository?.url?.replace('git+', '').replace('.git', '') || ''
14
-
15
- // Минималистичный шаблон README
16
- const readmeTemplate = `# ${projectName}
17
46
 
18
- ${description}
19
-
20
- ## 🚀 Быстрый старт
47
+ // Получаем URL репозитория
48
+ let repoUrl = ''
49
+ if (packageJson.repository?.url) {
50
+ repoUrl = packageJson.repository.url.replace('git+', '').replace('.git', '')
51
+ } else {
52
+ repoUrl = `https://github.com/${author}/${projectName}`
53
+ }
21
54
 
22
- \`\`\`bash
23
- # Установка зависимостей
24
- npm install
55
+ // Читаем шаблон
56
+ const templatePath = join(templateDir, 'README.md')
57
+ let readmeContent = ''
25
58
 
26
- # Запуск
27
- npm run dev
28
- \`\`\`
59
+ if (existsSync(templatePath)) {
60
+ readmeContent = readFileSync(templatePath, 'utf8')
29
61
 
30
- ## 📋 Команды
62
+ // Подставляем значения
63
+ readmeContent = readmeContent
64
+ .replace(/\{\{PROJECT_NAME\}\}/g, projectName)
65
+ .replace(/\{\{PROJECT_DESCRIPTION\}\}/g, description)
66
+ .replace(/\{\{REPO_URL\}\}/g, repoUrl)
67
+ .replace(/\{\{AUTHOR\}\}/g, author)
68
+ .replace(/\{\{LICENSE\}\}/g, license)
31
69
 
32
- \`\`\`bash
33
- npm run dev # Разработка
34
- npm run _ tasks # Задачи
35
- npm run _ release # Релиз
36
- \`\`\`
70
+ console.log('✅ README.md создан из шаблона!')
71
+ } else {
72
+ // Fallback если шаблона нет
73
+ readmeContent = `# ${projectName}
37
74
 
38
- > Проект использует [@vv0rkz/js-template](https://github.com/vv0rkz/js-template) для автоматизации workflow (husky hooks, changelog, GitHub tasks)
75
+ ${description}
39
76
 
40
77
  <!-- AUTOGENERATED_SECTION START -->
41
78
  <!-- AUTOGENERATED_SECTION END -->
42
79
 
80
+ ## 🔧 Workflow
81
+
82
+ Проект использует [@vv0rkz/js-template](https://github.com/vv0rkz/js-template)
83
+
43
84
  ## 📄 Лицензия
44
85
 
45
- ${license} © ${author}
86
+ ${license} © [${author}](${repoUrl})
46
87
  `
47
-
48
- // Проверяем существование README
49
- if (existsSync('README.md')) {
50
- console.log('⚠️ README.md уже существует')
51
- console.log('💡 Удали файл или переименуй, чтобы создать новый')
52
- process.exit(1)
88
+ console.log('✅ README.md создан (fallback)!')
53
89
  }
54
90
 
55
- // Сохраняем README
56
- writeFileSync('README.md', readmeTemplate)
57
- console.log('✅ README.md создан!')
91
+ // Сохраняем
92
+ writeFileSync('README.md', readmeContent)
93
+
58
94
  console.log('\n📝 Теперь:')
59
- console.log(' 1. Отредактируй описание и добавь детали')
95
+ console.log(' 1. Отредактируй README.md под свой проект')
60
96
  console.log(' 2. Добавь скриншоты/демо')
61
97
  console.log(' 3. npm run _ update-readme — для обновления истории версий')