@vira-ui/cli 1.0.1 → 1.0.2
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 +965 -0
- package/dist/index.js +1221 -34
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,965 @@
|
|
|
1
|
+
# @vira-ui/cli
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
**Vira CLI - Генератор проектов и кода для Vira Framework**
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@vira-ui/cli)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://www.typescriptlang.org/)
|
|
10
|
+
|
|
11
|
+
**Создавайте проекты, генерируйте компоненты, сервисы и backend-код одной командой.**
|
|
12
|
+
|
|
13
|
+
[📖 Quickstart: Создаём CRM за 10 минут](QUICKSTART.md) • [🚀 Production-Ready](PRODUCTION.md) • [Установка](#-установка) • [Быстрый старт](#-быстрый-старт) • [Команды](#-команды) • [Примеры](#-примеры)
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 🎯 Что это?
|
|
20
|
+
|
|
21
|
+
**Vira CLI** — это мощный инструмент командной строки для быстрого создания проектов и генерации кода в экосистеме Vira Framework. Он автоматизирует рутинные задачи и помогает начать разработку за секунды.
|
|
22
|
+
|
|
23
|
+
### Основные возможности
|
|
24
|
+
|
|
25
|
+
- ✅ **Создание проектов** — Frontend, Fullstack, Kanban reference app
|
|
26
|
+
- ✅ **Генерация компонентов** — React компоненты, сервисы, страницы, модели
|
|
27
|
+
- ✅ **Backend scaffolding** — Go handlers, models, migrations, event handlers
|
|
28
|
+
- ✅ **Синхронизация типов** — Автоматическая синхронизация TypeScript типов из Go структур
|
|
29
|
+
- ✅ **VRP Protocol** — Валидация и генерация документации протокола
|
|
30
|
+
- ✅ **Docker & DevOps** — Готовая инфраструктура для разработки и продакшена
|
|
31
|
+
|
|
32
|
+
> **Примечание:** Некоторые функции находятся в экспериментальной стадии в альфа-версиях.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 📦 Установка
|
|
37
|
+
|
|
38
|
+
### Глобальная установка
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Глобальная установка
|
|
42
|
+
npm install -g @vira-ui/cli
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Использование через npx (рекомендуется)
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npx @vira-ui/cli create my-app
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 🚀 Быстрый старт
|
|
54
|
+
|
|
55
|
+
> 💡 **Новый?** Начните с [📖 Quickstart гайда](QUICKSTART.md) — создайте полноценную CRM страницу за 10 минут!
|
|
56
|
+
|
|
57
|
+
### 1. Создание проекта
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Интерактивный выбор шаблона
|
|
61
|
+
npx vira create my-app
|
|
62
|
+
|
|
63
|
+
# Или с указанием шаблона
|
|
64
|
+
npx vira create my-app --template frontend
|
|
65
|
+
npx vira create my-app --template fullstack
|
|
66
|
+
npx vira create my-app --template kanban
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 2. Генерация компонента
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
cd my-app
|
|
73
|
+
npx vira generate component Button
|
|
74
|
+
npx vira generate service User
|
|
75
|
+
npx vira generate page Dashboard
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 3. Запуск проекта
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
cd my-app
|
|
82
|
+
npm install
|
|
83
|
+
npm run dev
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Готово!** Ваш проект запущен и готов к разработке.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## 📚 Команды
|
|
91
|
+
|
|
92
|
+
### `vira create <name>` — Создание проекта
|
|
93
|
+
|
|
94
|
+
Создаёт новый проект Vira с выбранным шаблоном.
|
|
95
|
+
|
|
96
|
+
**Опции:**
|
|
97
|
+
- `-t, --template <template>` — Тип шаблона: `frontend`, `fullstack`, `kanban`
|
|
98
|
+
|
|
99
|
+
**Примеры:**
|
|
100
|
+
```bash
|
|
101
|
+
# Интерактивный выбор
|
|
102
|
+
vira create my-app
|
|
103
|
+
|
|
104
|
+
# Frontend проект (React + Vite + Vira UI)
|
|
105
|
+
vira create my-app --template frontend
|
|
106
|
+
|
|
107
|
+
# Fullstack проект (Frontend + Go Backend + Docker)
|
|
108
|
+
vira create my-app --template fullstack
|
|
109
|
+
|
|
110
|
+
# Kanban reference app (демонстрация VRP)
|
|
111
|
+
vira create my-app --template kanban
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### `vira init` — Инициализация проекта
|
|
115
|
+
|
|
116
|
+
Инициализирует проект Vira в текущей директории. Полезно для инициализации существующего проекта.
|
|
117
|
+
|
|
118
|
+
**Опции:**
|
|
119
|
+
- `-t, --template <template>` — Тип шаблона: `frontend`, `fullstack`, `kanban`
|
|
120
|
+
|
|
121
|
+
**Примеры:**
|
|
122
|
+
```bash
|
|
123
|
+
# Интерактивный выбор шаблона
|
|
124
|
+
cd my-existing-project
|
|
125
|
+
vira init
|
|
126
|
+
|
|
127
|
+
# С указанием шаблона
|
|
128
|
+
vira init --template frontend
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Что создаётся:**
|
|
132
|
+
|
|
133
|
+
#### Frontend Template
|
|
134
|
+
```
|
|
135
|
+
my-app/
|
|
136
|
+
├── src/
|
|
137
|
+
│ ├── components/ # React компоненты
|
|
138
|
+
│ ├── services/ # Сервисы (DI)
|
|
139
|
+
│ ├── pages/ # Страницы
|
|
140
|
+
│ ├── models/ # Модели с валидацией
|
|
141
|
+
│ ├── hooks/ # Custom hooks
|
|
142
|
+
│ ├── utils/ # Утилиты
|
|
143
|
+
│ ├── App.tsx # Главный компонент
|
|
144
|
+
│ └── main.tsx # Точка входа
|
|
145
|
+
├── package.json # Зависимости
|
|
146
|
+
├── tsconfig.json # TypeScript конфигурация
|
|
147
|
+
├── vite.config.ts # Vite конфигурация
|
|
148
|
+
└── index.html # HTML шаблон
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
#### Fullstack Template
|
|
152
|
+
```
|
|
153
|
+
my-app/
|
|
154
|
+
├── frontend/ # React приложение
|
|
155
|
+
├── ui/ # Vira UI пакет/шоукейсы
|
|
156
|
+
├── backend/ # Go API
|
|
157
|
+
│ ├── cmd/api/ # Точка входа
|
|
158
|
+
│ ├── internal/
|
|
159
|
+
│ │ ├── handlers/ # HTTP handlers
|
|
160
|
+
│ │ ├── models/ # Go модели
|
|
161
|
+
│ │ ├── events/ # Event handlers
|
|
162
|
+
│ │ ├── db/ # Database
|
|
163
|
+
│ │ ├── cache/ # Redis
|
|
164
|
+
│ │ └── config/ # Конфигурация
|
|
165
|
+
│ ├── migrations/ # SQL миграции
|
|
166
|
+
│ └── queries/ # SQLC queries
|
|
167
|
+
├── deploy/ # Docker & DevOps
|
|
168
|
+
│ ├── docker-compose.dev.yml
|
|
169
|
+
│ └── docker-compose.prod.yml
|
|
170
|
+
└── migrations/ # Общие миграции
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
#### Kanban Template
|
|
174
|
+
```
|
|
175
|
+
my-app/
|
|
176
|
+
├── src/
|
|
177
|
+
│ ├── components/
|
|
178
|
+
│ │ ├── KanbanBoard.tsx
|
|
179
|
+
│ │ ├── KanbanColumn.tsx
|
|
180
|
+
│ │ └── KanbanCard.tsx
|
|
181
|
+
│ ├── services/
|
|
182
|
+
│ │ └── kanban.ts # VRP сервис
|
|
183
|
+
│ └── models/
|
|
184
|
+
│ └── kanban.ts # Типы
|
|
185
|
+
└── ...
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
### `vira generate <type> <name>` — Генерация кода
|
|
191
|
+
|
|
192
|
+
Генерирует файлы для компонентов, сервисов, страниц, моделей и роутов.
|
|
193
|
+
|
|
194
|
+
**Алиас:** `vira g`
|
|
195
|
+
|
|
196
|
+
**Типы:**
|
|
197
|
+
- `component` / `comp` — React компонент
|
|
198
|
+
- `service` — Сервис (DI)
|
|
199
|
+
- `page` — Страница
|
|
200
|
+
- `model` — Модель с валидацией
|
|
201
|
+
- `route` — Роут
|
|
202
|
+
- `test` — Тест для компонента, сервиса или страницы
|
|
203
|
+
|
|
204
|
+
**Опции:**
|
|
205
|
+
- `-d, --dir <directory>` — Директория для вывода (по умолчанию: `src`)
|
|
206
|
+
- `-i, --interactive` — Интерактивный режим (для компонентов и сервисов - выбор props, VRP, UI)
|
|
207
|
+
- `--vrp` — Явно использовать Vira Reactive Protocol (VRP)
|
|
208
|
+
- `--no-vrp` — Явно не использовать VRP
|
|
209
|
+
|
|
210
|
+
**Примеры:**
|
|
211
|
+
```bash
|
|
212
|
+
vira generate component Button
|
|
213
|
+
vira g comp UserCard
|
|
214
|
+
|
|
215
|
+
# Интерактивная генерация компонента с выбором props
|
|
216
|
+
vira generate component Button --interactive
|
|
217
|
+
|
|
218
|
+
# Явное использование VRP (без интерактивного режима)
|
|
219
|
+
vira generate component Button --vrp
|
|
220
|
+
|
|
221
|
+
# Явное указание не использовать VRP
|
|
222
|
+
vira generate component Button --no-vrp
|
|
223
|
+
|
|
224
|
+
# Комбинация: интерактивный режим с принудительным VRP
|
|
225
|
+
vira generate component Button --interactive --vrp
|
|
226
|
+
|
|
227
|
+
# Генерация сервиса
|
|
228
|
+
vira generate service User
|
|
229
|
+
vira g service Product
|
|
230
|
+
|
|
231
|
+
# Генерация страницы
|
|
232
|
+
vira generate page Dashboard
|
|
233
|
+
vira g page Profile
|
|
234
|
+
|
|
235
|
+
# Генерация модели
|
|
236
|
+
vira generate model User
|
|
237
|
+
vira g model Product
|
|
238
|
+
|
|
239
|
+
# Генерация роута
|
|
240
|
+
vira generate route users
|
|
241
|
+
vira g route products
|
|
242
|
+
|
|
243
|
+
# Генерация теста
|
|
244
|
+
vira generate test Button
|
|
245
|
+
vira g test UserService
|
|
246
|
+
|
|
247
|
+
# С указанием директории
|
|
248
|
+
vira generate component Button --dir src/components
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Сгенерированные файлы:**
|
|
252
|
+
|
|
253
|
+
#### Component
|
|
254
|
+
```tsx
|
|
255
|
+
// src/components/Button.tsx
|
|
256
|
+
import { createElement } from '@vira-ui/core';
|
|
257
|
+
import type { ViraComponentProps } from '@vira-ui/core';
|
|
258
|
+
|
|
259
|
+
export interface ButtonProps extends ViraComponentProps {
|
|
260
|
+
// Add your props here
|
|
261
|
+
// При использовании --interactive здесь будут автоматически добавлены props
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export function Button(props: ButtonProps) {
|
|
265
|
+
return createElement('div', { className: 'button' },
|
|
266
|
+
// Add your content here
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Интерактивная генерация компонента:**
|
|
272
|
+
```bash
|
|
273
|
+
vira generate component Button --interactive
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Интерактивный режим позволяет:
|
|
277
|
+
- ✅ Выбрать использование **Vira Reactive Protocol (VRP)** для state management
|
|
278
|
+
- ✅ Настроить VRP channel и state type
|
|
279
|
+
- ✅ Интерактивно добавить props с выбором типов
|
|
280
|
+
- ✅ Выбрать использование **Vira UI** компонентов (@vira-ui/ui)
|
|
281
|
+
- ✅ Автоматически сгенерировать правильную структуру компонента
|
|
282
|
+
|
|
283
|
+
**Пример интерактивной генерации с VRP:**
|
|
284
|
+
```bash
|
|
285
|
+
vira generate component TaskCard --interactive
|
|
286
|
+
# → Использовать VRP? Yes
|
|
287
|
+
# → Channel: task:123
|
|
288
|
+
# → State type: TaskState
|
|
289
|
+
# → Использовать Vira UI? Yes
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Результат будет включать:
|
|
293
|
+
- `useViraState` hook для синхронизации состояния
|
|
294
|
+
- Интерфейс состояния (`TaskState`)
|
|
295
|
+
- Интеграцию с Vira UI компонентами
|
|
296
|
+
- Готовую структуру для работы с VRP
|
|
297
|
+
|
|
298
|
+
> **Примечание:** `createElement` и некоторые экспериментальные функции могут изменяться в будущих версиях.
|
|
299
|
+
|
|
300
|
+
#### Service
|
|
301
|
+
```tsx
|
|
302
|
+
// src/services/UserService.ts
|
|
303
|
+
import { createViraService, signal } from '@vira-ui/core';
|
|
304
|
+
|
|
305
|
+
export const UserService = createViraService('user', () => {
|
|
306
|
+
const data = signal([]);
|
|
307
|
+
const loading = signal(false);
|
|
308
|
+
const error = signal<string | null>(null);
|
|
309
|
+
|
|
310
|
+
const fetch = async () => {
|
|
311
|
+
loading.set(true);
|
|
312
|
+
try {
|
|
313
|
+
// Add your logic here
|
|
314
|
+
// const result = await api.get('/user');
|
|
315
|
+
// data.set(result);
|
|
316
|
+
} catch (e) {
|
|
317
|
+
error.set(e instanceof Error ? e.message : 'Unknown error');
|
|
318
|
+
} finally {
|
|
319
|
+
loading.set(false);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
return {
|
|
324
|
+
data,
|
|
325
|
+
loading,
|
|
326
|
+
error,
|
|
327
|
+
fetch,
|
|
328
|
+
};
|
|
329
|
+
});
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**VRP-based Service (при интерактивной генерации с выбором VRP):**
|
|
333
|
+
```tsx
|
|
334
|
+
// src/services/UserService.ts
|
|
335
|
+
import { createService, useService } from '@vira-ui/core';
|
|
336
|
+
import { useViraState } from '@vira-ui/react';
|
|
337
|
+
|
|
338
|
+
export interface UserState {
|
|
339
|
+
id?: string;
|
|
340
|
+
// Add your state fields here
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Business logic service
|
|
344
|
+
createService('user', () => ({
|
|
345
|
+
processData(data: UserState | null): any {
|
|
346
|
+
// Add processing logic
|
|
347
|
+
return data;
|
|
348
|
+
},
|
|
349
|
+
}));
|
|
350
|
+
|
|
351
|
+
// VRP hook
|
|
352
|
+
export function useUser(id?: string) {
|
|
353
|
+
const channel = id ? `user:${id}` : 'user';
|
|
354
|
+
const { data, sendEvent, sendUpdate, sendDiff } = useViraState<UserState>(channel, null);
|
|
355
|
+
const userService = useService('user');
|
|
356
|
+
|
|
357
|
+
return {
|
|
358
|
+
data,
|
|
359
|
+
update(updates: Partial<UserState>) {
|
|
360
|
+
sendDiff(updates);
|
|
361
|
+
},
|
|
362
|
+
sendEvent(eventName: string, payload: any) {
|
|
363
|
+
sendEvent(eventName, payload);
|
|
364
|
+
},
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
#### Page
|
|
370
|
+
```tsx
|
|
371
|
+
// src/pages/DashboardPage.tsx
|
|
372
|
+
import { createElement } from '@vira-ui/core';
|
|
373
|
+
|
|
374
|
+
export function DashboardPage() {
|
|
375
|
+
return createElement('div', { className: 'dashboard-page' },
|
|
376
|
+
createElement('h1', null, 'Dashboard'),
|
|
377
|
+
// Add your content here
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
#### Model
|
|
383
|
+
```tsx
|
|
384
|
+
// src/models/User.ts
|
|
385
|
+
import { defineModel } from '@vira-ui/core';
|
|
386
|
+
|
|
387
|
+
export const UserModel = defineModel({
|
|
388
|
+
// Add your fields here
|
|
389
|
+
id: {
|
|
390
|
+
type: 'string',
|
|
391
|
+
required: true,
|
|
392
|
+
},
|
|
393
|
+
});
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
#### Route
|
|
397
|
+
```tsx
|
|
398
|
+
// src/routes/users.ts
|
|
399
|
+
import { reactiveRoute } from '@vira-ui/core';
|
|
400
|
+
import { UsersPage } from '../pages/UsersPage';
|
|
401
|
+
|
|
402
|
+
export const usersRoute = reactiveRoute({
|
|
403
|
+
path: '/users',
|
|
404
|
+
component: UsersPage,
|
|
405
|
+
});
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
#### Test
|
|
409
|
+
```tsx
|
|
410
|
+
// src/components/Button.test.tsx
|
|
411
|
+
import React from 'react';
|
|
412
|
+
import { render } from '@testing-library/react';
|
|
413
|
+
import { Button } from './Button';
|
|
414
|
+
import type { ButtonProps } from './Button';
|
|
415
|
+
|
|
416
|
+
describe('Button', () => {
|
|
417
|
+
it('renders correctly', () => {
|
|
418
|
+
const props: ButtonProps = {
|
|
419
|
+
// Add test props here
|
|
420
|
+
};
|
|
421
|
+
const { container } = render(React.createElement(Button, props));
|
|
422
|
+
expect(container).toBeTruthy();
|
|
423
|
+
});
|
|
424
|
+
});
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
### `vira make <type> <name>` — Backend scaffolding (Go)
|
|
430
|
+
|
|
431
|
+
Генерирует Go-код для backend разработки.
|
|
432
|
+
|
|
433
|
+
**Типы:**
|
|
434
|
+
- `handler` — HTTP handler
|
|
435
|
+
- `model` — Go модель (struct)
|
|
436
|
+
- `migration` — SQL миграция (up/down)
|
|
437
|
+
- `event` — Event handler
|
|
438
|
+
- `crud` — CRUD handlers (List, Get, Create, Update, Delete)
|
|
439
|
+
|
|
440
|
+
**Опции:**
|
|
441
|
+
- `-d, --dir <directory>` — Целевая директория
|
|
442
|
+
- `-m, --model <model>` — Имя модели (для crud)
|
|
443
|
+
|
|
444
|
+
**Примеры:**
|
|
445
|
+
|
|
446
|
+
```bash
|
|
447
|
+
# Генерация HTTP handler
|
|
448
|
+
vira make handler user
|
|
449
|
+
# Создаёт: backend/internal/handlers/user.go
|
|
450
|
+
|
|
451
|
+
# Генерация модели
|
|
452
|
+
vira make model User
|
|
453
|
+
# Создаёт: backend/internal/models/User.go
|
|
454
|
+
|
|
455
|
+
# Генерация миграции
|
|
456
|
+
vira make migration create-users
|
|
457
|
+
# Создаёт: migrations/20240101120000_create-users.up.sql
|
|
458
|
+
# migrations/20240101120000_create-users.down.sql
|
|
459
|
+
|
|
460
|
+
# Генерация event handler
|
|
461
|
+
vira make event user.created
|
|
462
|
+
# Создаёт: backend/internal/events/user_created.go
|
|
463
|
+
# backend/internal/events/registry_user_created.go
|
|
464
|
+
|
|
465
|
+
# Генерация CRUD handlers
|
|
466
|
+
vira make crud user
|
|
467
|
+
# Создаёт: backend/internal/handlers/user_crud.go
|
|
468
|
+
# (ListUser, GetUser, CreateUser, UpdateUser, DeleteUser)
|
|
469
|
+
|
|
470
|
+
vira make crud product --model Product
|
|
471
|
+
# Создаёт CRUD handlers с указанной моделью
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
**Сгенерированные файлы:**
|
|
475
|
+
|
|
476
|
+
#### Handler
|
|
477
|
+
```go
|
|
478
|
+
// backend/internal/handlers/user.go
|
|
479
|
+
package handlers
|
|
480
|
+
|
|
481
|
+
import (
|
|
482
|
+
"encoding/json"
|
|
483
|
+
"net/http"
|
|
484
|
+
)
|
|
485
|
+
|
|
486
|
+
type UserResponse struct {
|
|
487
|
+
Message string `json:"message"`
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// User handles GET /user
|
|
491
|
+
func User(w http.ResponseWriter, r *http.Request) {
|
|
492
|
+
w.Header().Set("Content-Type", "application/json")
|
|
493
|
+
_ = json.NewEncoder(w).Encode(UserResponse{
|
|
494
|
+
Message: "User handler ok",
|
|
495
|
+
})
|
|
496
|
+
}
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
#### Model
|
|
500
|
+
```go
|
|
501
|
+
// backend/internal/models/User.go
|
|
502
|
+
package models
|
|
503
|
+
|
|
504
|
+
import "time"
|
|
505
|
+
|
|
506
|
+
type User struct {
|
|
507
|
+
ID string `db:"id"`
|
|
508
|
+
CreatedAt time.Time `db:"created_at"`
|
|
509
|
+
UpdatedAt time.Time `db:"updated_at"`
|
|
510
|
+
}
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
#### Migration
|
|
514
|
+
```sql
|
|
515
|
+
-- migrations/20240101120000_create-users.up.sql
|
|
516
|
+
-- +goose Up
|
|
517
|
+
-- TODO: add migration SQL here
|
|
518
|
+
|
|
519
|
+
-- migrations/20240101120000_create-users.down.sql
|
|
520
|
+
-- +goose Down
|
|
521
|
+
-- TODO: rollback SQL here
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
#### Event Handler
|
|
525
|
+
```go
|
|
526
|
+
// backend/internal/events/user_created.go
|
|
527
|
+
package events
|
|
528
|
+
|
|
529
|
+
import (
|
|
530
|
+
"context"
|
|
531
|
+
"encoding/json"
|
|
532
|
+
"github.com/gorilla/websocket"
|
|
533
|
+
)
|
|
534
|
+
|
|
535
|
+
// UserCreated handles event: user.created
|
|
536
|
+
func UserCreated(ctx context.Context, hub EventEmitter, conn *websocket.Conn, msg WSMessage) {
|
|
537
|
+
var payload map[string]any
|
|
538
|
+
if len(msg.Data) > 0 {
|
|
539
|
+
_ = json.Unmarshal(msg.Data, &payload)
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// TODO: implement domain logic here
|
|
543
|
+
// Example: hub.Emit(ChannelCustom("demo", "echo"), payload)
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
func init() {
|
|
547
|
+
Register("user.created", UserCreated)
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// backend/internal/events/registry_user_created.go
|
|
551
|
+
package events
|
|
552
|
+
|
|
553
|
+
func init() {
|
|
554
|
+
Register("user.created", UserCreated)
|
|
555
|
+
}
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
#### CRUD Handler
|
|
559
|
+
```go
|
|
560
|
+
// backend/internal/handlers/user_crud.go
|
|
561
|
+
package handlers
|
|
562
|
+
|
|
563
|
+
import (
|
|
564
|
+
"encoding/json"
|
|
565
|
+
"net/http"
|
|
566
|
+
"github.com/gorilla/mux"
|
|
567
|
+
)
|
|
568
|
+
|
|
569
|
+
// ListUser handles GET /user
|
|
570
|
+
func ListUser(w http.ResponseWriter, r *http.Request) {
|
|
571
|
+
// Implementation
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// GetUser handles GET /user/{id}
|
|
575
|
+
func GetUser(w http.ResponseWriter, r *http.Request) {
|
|
576
|
+
// Implementation
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// CreateUser handles POST /user
|
|
580
|
+
func CreateUser(w http.ResponseWriter, r *http.Request) {
|
|
581
|
+
// Implementation
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// UpdateUser handles PUT /user/{id}
|
|
585
|
+
func UpdateUser(w http.ResponseWriter, r *http.Request) {
|
|
586
|
+
// Implementation
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// DeleteUser handles DELETE /user/{id}
|
|
590
|
+
func DeleteUser(w http.ResponseWriter, r *http.Request) {
|
|
591
|
+
// Implementation
|
|
592
|
+
}
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
---
|
|
596
|
+
|
|
597
|
+
### `vira sync` — Синхронизация типов
|
|
598
|
+
|
|
599
|
+
Синхронизирует TypeScript типы из Go структур.
|
|
600
|
+
|
|
601
|
+
**Опции:**
|
|
602
|
+
- `--types` — Синхронизировать TypeScript типы (по умолчанию: `true`)
|
|
603
|
+
- `--backend <path>` — Путь к Go файлу (по умолчанию: `backend/internal/types/types.go`)
|
|
604
|
+
- `--frontend <path>` — Путь для TypeScript типов (по умолчанию: `frontend/src/vira-types.ts`)
|
|
605
|
+
- `--ui <path>` — Путь для TypeScript типов UI (по умолчанию: `ui/src/vira-types.ts`)
|
|
606
|
+
- `-w, --watch` — Watch mode: автоматическая синхронизация при изменениях (в разработке)
|
|
607
|
+
|
|
608
|
+
**Пример:**
|
|
609
|
+
```bash
|
|
610
|
+
vira sync --types
|
|
611
|
+
|
|
612
|
+
# С указанием путей
|
|
613
|
+
vira sync --backend backend/internal/types/types.go \
|
|
614
|
+
--frontend frontend/src/types/vira.ts \
|
|
615
|
+
--ui ui/src/types/vira.ts
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
**Что делает:**
|
|
619
|
+
1. Парсит Go структуры
|
|
620
|
+
2. Конвертирует Go типы в TypeScript
|
|
621
|
+
3. Генерирует TypeScript файлы с типами
|
|
622
|
+
4. Создаёт helper функции для каналов VRP
|
|
623
|
+
|
|
624
|
+
**Пример Go структуры:**
|
|
625
|
+
|
|
626
|
+
```go
|
|
627
|
+
// backend/internal/types/types.go
|
|
628
|
+
package types
|
|
629
|
+
|
|
630
|
+
type User struct {
|
|
631
|
+
ID string `json:"id"`
|
|
632
|
+
Name string `json:"name"`
|
|
633
|
+
Email string `json:"email"`
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
type Task struct {
|
|
637
|
+
ID string `json:"id"`
|
|
638
|
+
Title string `json:"title"`
|
|
639
|
+
Completed bool `json:"completed"`
|
|
640
|
+
}
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
**Сгенерированный TypeScript:**
|
|
644
|
+
|
|
645
|
+
```typescript
|
|
646
|
+
// frontend/src/vira-types.ts
|
|
647
|
+
// Auto-generated by vira sync --types. Do not edit manually.
|
|
648
|
+
|
|
649
|
+
export type ViraMessageType =
|
|
650
|
+
| 'handshake' | 'ack' | 'sub' | 'sub_ack' | 'unsub' | 'unsub_ack'
|
|
651
|
+
| 'update' | 'event' | 'diff' | 'ping' | 'pong' | 'error';
|
|
652
|
+
|
|
653
|
+
export enum ViraChannelEnum {
|
|
654
|
+
User = 'user',
|
|
655
|
+
Task = 'task',
|
|
656
|
+
Notifications = 'notifications',
|
|
657
|
+
Demo = 'demo',
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
export type ViraChannel =
|
|
661
|
+
| `${ViraChannelEnum.User}:${string}`
|
|
662
|
+
| `${ViraChannelEnum.Task}:${string}`
|
|
663
|
+
| `${ViraChannelEnum.Notifications}:${string}`
|
|
664
|
+
| ViraChannelEnum.Demo
|
|
665
|
+
| string;
|
|
666
|
+
|
|
667
|
+
export interface ViraDataMap {
|
|
668
|
+
User: User;
|
|
669
|
+
Task: Task;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
export type ViraAnyData = ViraDataMap[keyof ViraDataMap];
|
|
673
|
+
|
|
674
|
+
export interface User {
|
|
675
|
+
id: string;
|
|
676
|
+
name: string;
|
|
677
|
+
email: string;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
export interface Task {
|
|
681
|
+
id: string;
|
|
682
|
+
title: string;
|
|
683
|
+
completed: boolean;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// ... helper functions для каналов
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
---
|
|
690
|
+
|
|
691
|
+
### `vira proto` — VRP Protocol утилиты
|
|
692
|
+
|
|
693
|
+
Работа с Vira Reactive Protocol (VRP).
|
|
694
|
+
|
|
695
|
+
> **Примечание:** Некоторые функции VRP находятся в экспериментальной стадии в альфа-версиях.
|
|
696
|
+
|
|
697
|
+
**Подкоманды:**
|
|
698
|
+
|
|
699
|
+
#### `vira proto validate`
|
|
700
|
+
|
|
701
|
+
Валидирует схему VRP протокола и проверяет типы.
|
|
702
|
+
|
|
703
|
+
**Опции:**
|
|
704
|
+
- `--file <path>` — Путь к Go файлу с типами (по умолчанию: `backend/internal/types/types.go`)
|
|
705
|
+
|
|
706
|
+
**Примеры:**
|
|
707
|
+
```bash
|
|
708
|
+
# Валидация с файлом по умолчанию
|
|
709
|
+
vira proto validate
|
|
710
|
+
|
|
711
|
+
# Валидация с указанным файлом
|
|
712
|
+
vira proto validate --file backend/internal/types/models.go
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
**Что проверяется:**
|
|
716
|
+
- Наличие и корректность Go структур
|
|
717
|
+
- Соответствие структур требованиям VRP
|
|
718
|
+
- Наличие необходимых полей для каналов
|
|
719
|
+
|
|
720
|
+
#### `vira proto generate`
|
|
721
|
+
|
|
722
|
+
Генерирует документацию по каналам VRP и схемы протокола.
|
|
723
|
+
|
|
724
|
+
**Опции:**
|
|
725
|
+
- `--file <path>` — Путь к Go файлу с типами (по умолчанию: `backend/internal/types/types.go`)
|
|
726
|
+
- `--output <path>` — Директория для вывода (по умолчанию: `docs`)
|
|
727
|
+
|
|
728
|
+
**Примеры:**
|
|
729
|
+
```bash
|
|
730
|
+
# Генерация документации
|
|
731
|
+
vira proto generate
|
|
732
|
+
|
|
733
|
+
# С указанием путей
|
|
734
|
+
vira proto generate --file backend/internal/types/types.go --output docs/vrp
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
**Что генерируется:**
|
|
738
|
+
- `VRP_CHANNELS.md` — Документация по всем доступным каналам
|
|
739
|
+
- Описание типов данных для каждого канала
|
|
740
|
+
- Примеры использования с `useViraState`
|
|
741
|
+
|
|
742
|
+
---
|
|
743
|
+
|
|
744
|
+
### `vira doc` — Генерация документации
|
|
745
|
+
|
|
746
|
+
Генерирует документацию CLI команд в `docs/cli.md`.
|
|
747
|
+
|
|
748
|
+
```bash
|
|
749
|
+
vira doc
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
### `vira validate` — Валидация проекта
|
|
753
|
+
|
|
754
|
+
Проверяет структуру проекта и наличие необходимых файлов.
|
|
755
|
+
|
|
756
|
+
```bash
|
|
757
|
+
vira validate
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
**Что проверяется:**
|
|
761
|
+
- Наличие обязательных файлов (`package.json`, `vite.config.ts`, и т.д.)
|
|
762
|
+
- Структура директорий
|
|
763
|
+
- Конфигурационные файлы
|
|
764
|
+
|
|
765
|
+
---
|
|
766
|
+
|
|
767
|
+
## 🎨 Примеры
|
|
768
|
+
|
|
769
|
+
### Создание Fullstack проекта
|
|
770
|
+
|
|
771
|
+
```bash
|
|
772
|
+
# Создание проекта
|
|
773
|
+
vira create my-crm --template fullstack
|
|
774
|
+
|
|
775
|
+
cd my-crm
|
|
776
|
+
|
|
777
|
+
# Frontend: генерация компонентов
|
|
778
|
+
cd frontend
|
|
779
|
+
vira generate component ClientCard
|
|
780
|
+
vira generate service Client
|
|
781
|
+
vira generate page Clients
|
|
782
|
+
|
|
783
|
+
# Backend: генерация handlers
|
|
784
|
+
cd ../backend
|
|
785
|
+
vira make handler client
|
|
786
|
+
vira make model Client
|
|
787
|
+
vira make migration create-clients
|
|
788
|
+
|
|
789
|
+
# Синхронизация типов
|
|
790
|
+
cd ..
|
|
791
|
+
vira sync --types
|
|
792
|
+
|
|
793
|
+
# Запуск
|
|
794
|
+
cd frontend && npm install && npm run dev
|
|
795
|
+
cd ../backend && go mod tidy && go run ./cmd/api
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
### Синхронизация типов
|
|
799
|
+
|
|
800
|
+
```bash
|
|
801
|
+
# Создание Kanban reference app
|
|
802
|
+
vira create kanban-app --template kanban
|
|
803
|
+
|
|
804
|
+
cd kanban-app
|
|
805
|
+
|
|
806
|
+
# Генерация дополнительных компонентов
|
|
807
|
+
vira generate component TaskCard
|
|
808
|
+
vira generate service Task
|
|
809
|
+
|
|
810
|
+
# Backend: генерация event handlers
|
|
811
|
+
cd ../backend
|
|
812
|
+
vira make event kanban.card.create
|
|
813
|
+
vira make event kanban.card.move
|
|
814
|
+
vira make event kanban.card.delete
|
|
815
|
+
|
|
816
|
+
# Запуск
|
|
817
|
+
cd .. && npm install && npm run dev
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
### Пример 3: Работа с миграциями
|
|
821
|
+
|
|
822
|
+
```bash
|
|
823
|
+
# Создание миграции
|
|
824
|
+
vira make migration create-users
|
|
825
|
+
|
|
826
|
+
# Редактирование миграции
|
|
827
|
+
# migrations/20240101120000_create-users.up.sql
|
|
828
|
+
CREATE TABLE users (
|
|
829
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
830
|
+
name VARCHAR(255) NOT NULL,
|
|
831
|
+
email VARCHAR(255) UNIQUE NOT NULL,
|
|
832
|
+
created_at TIMESTAMP DEFAULT NOW()
|
|
833
|
+
);
|
|
834
|
+
|
|
835
|
+
# migrations/20240101120000_create-users.down.sql
|
|
836
|
+
DROP TABLE IF EXISTS users;
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
### Пример 4: Синхронизация типов
|
|
840
|
+
|
|
841
|
+
```bash
|
|
842
|
+
# 1. Определяем Go структуры
|
|
843
|
+
# backend/internal/types/types.go
|
|
844
|
+
type Product struct {
|
|
845
|
+
ID string `json:"id"`
|
|
846
|
+
Name string `json:"name"`
|
|
847
|
+
Price int64 `json:"price"`
|
|
848
|
+
}
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
# 2. Синхронизируем типы
|
|
852
|
+
vira sync --types
|
|
853
|
+
```
|
|
854
|
+
|
|
855
|
+
# 3. Используем в TypeScript
|
|
856
|
+
# frontend/src/components/ProductCard.tsx
|
|
857
|
+
import type { Product } from '../vira-types';
|
|
858
|
+
|
|
859
|
+
export function ProductCard({ product }: { product: Product }) {
|
|
860
|
+
return <div>{product.name} - ${product.price}</div>;
|
|
861
|
+
}
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
---
|
|
865
|
+
|
|
866
|
+
## ❓ FAQ
|
|
867
|
+
|
|
868
|
+
**Q: Можно ли использовать CLI без глобальной установки?**
|
|
869
|
+
A: Да! Используйте `npx @vira-ui/cli`.
|
|
870
|
+
|
|
871
|
+
**Q: Можно ли использовать CLI в существующем проекте?**
|
|
872
|
+
A: Да! Команды `generate` и `make` работают в любом проекте.
|
|
873
|
+
|
|
874
|
+
**Q: Как синхронизировать типы из нескольких Go файлов?**
|
|
875
|
+
A: Объедините структуры в один файл или используйте несколько вызовов `vira sync` с разными путями.
|
|
876
|
+
|
|
877
|
+
**Q: Как работает синхронизация типов?**
|
|
878
|
+
A: CLI парсит Go структуры, конвертирует типы в TypeScript и генерирует файлы с типами и helper функциями.
|
|
879
|
+
|
|
880
|
+
**Q: Поддерживаются ли другие языки backend?**
|
|
881
|
+
A: Сейчас поддерживается только Go. Поддержка других языков планируется в будущих версиях.
|
|
882
|
+
|
|
883
|
+
---
|
|
884
|
+
|
|
885
|
+
## 🔧 Разработка CLI
|
|
886
|
+
|
|
887
|
+
```bash
|
|
888
|
+
# Клонирование и установка
|
|
889
|
+
git clone https://github.com/skrolikov/vira-cli.git
|
|
890
|
+
cd vira-cli
|
|
891
|
+
npm install
|
|
892
|
+
|
|
893
|
+
# Сборка
|
|
894
|
+
npm run build
|
|
895
|
+
|
|
896
|
+
# Локальное использование
|
|
897
|
+
npm link
|
|
898
|
+
vira create test-app
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
## ✨ Что нового в v1.0.1
|
|
902
|
+
|
|
903
|
+
### Улучшенная генерация компонентов
|
|
904
|
+
- ✅ **Интерактивный режим** с опцией использования VRP
|
|
905
|
+
- ✅ **Интеграция с Vira UI** компонентами
|
|
906
|
+
- ✅ **Автоматическая генерация** VRP-enabled компонентов
|
|
907
|
+
- ✅ **Умный выбор props** с интерактивным добавлением типов
|
|
908
|
+
|
|
909
|
+
### Улучшенная генерация сервисов
|
|
910
|
+
- ✅ **Поддержка VRP** для сервисов
|
|
911
|
+
- ✅ **Генерация hooks** с `useViraState`
|
|
912
|
+
- ✅ **Интеграция с DI container**
|
|
913
|
+
|
|
914
|
+
### VRP Protocol утилиты
|
|
915
|
+
- ✅ **Реальная валидация** Go структур
|
|
916
|
+
- ✅ **Генерация документации** по каналам
|
|
917
|
+
- ✅ **Автоматическое определение** доступных каналов
|
|
918
|
+
|
|
919
|
+
### Новые команды
|
|
920
|
+
- ✅ `vira init` — инициализация проекта в существующей директории
|
|
921
|
+
- ✅ `vira generate test` — генерация тестов
|
|
922
|
+
- ✅ `vira make crud` — генерация CRUD handlers
|
|
923
|
+
- ✅ `vira validate` — валидация структуры проекта
|
|
924
|
+
|
|
925
|
+
## 🛣️ Roadmap
|
|
926
|
+
|
|
927
|
+
### v1.1 (В разработке)
|
|
928
|
+
- [ ] Watch mode для `vira sync`
|
|
929
|
+
- [ ] Поддержка других шаблонов (Vue, Svelte)
|
|
930
|
+
- [ ] Генерация Storybook историй
|
|
931
|
+
- [ ] Плагины для расширения функциональности
|
|
932
|
+
|
|
933
|
+
### v1.2 (Планируется)
|
|
934
|
+
- [ ] Шаблоны для микросервисов
|
|
935
|
+
- [ ] Интеграция с CI/CD
|
|
936
|
+
- [ ] Генерация OpenAPI спецификаций
|
|
937
|
+
- [ ] Автоматическая генерация событий из схем
|
|
938
|
+
---
|
|
939
|
+
|
|
940
|
+
## 📄 License
|
|
941
|
+
|
|
942
|
+
MIT
|
|
943
|
+
|
|
944
|
+
---
|
|
945
|
+
|
|
946
|
+
## 🤝 Contributing
|
|
947
|
+
|
|
948
|
+
Мы приветствуем вклад! Пожалуйста, прочитайте [CONTRIBUTING.md](../../CONTRIBUTING.md) для деталей.
|
|
949
|
+
|
|
950
|
+
---
|
|
951
|
+
|
|
952
|
+
## 📞 Support
|
|
953
|
+
|
|
954
|
+
- **GitHub Issues**: [Создать issue](https://github.com/skrolikov/vira-cli/issues)
|
|
955
|
+
- **Discussions**: [Обсуждения](https://github.com/skrolikov/vira-cli/discussions)
|
|
956
|
+
|
|
957
|
+
---
|
|
958
|
+
|
|
959
|
+
<div align="center">
|
|
960
|
+
|
|
961
|
+
**Сделано с ❤️ командой Vira**
|
|
962
|
+
|
|
963
|
+
[GitHub](https://github.com/skrolikov/vira-cli) • [Документация](https://vira.dev/cli) • [Примеры](https://vira.dev/examples)
|
|
964
|
+
|
|
965
|
+
</div>
|