@vira-ui/cli 0.4.1-alpha → 1.0.1

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/dist/go/readme.js CHANGED
@@ -11,4 +11,21 @@ exports.readme = `# Vira Engine Monorepo (scaffold)
11
11
  - plugins/ — интеграции
12
12
  - migrations/ — SQL/Go миграции
13
13
  - deploy/ — docker-compose/devops артефакты
14
- `;
14
+
15
+ Next steps:
16
+ cd my-vira-app/frontend
17
+ npm install
18
+ npm run dev
19
+
20
+ UI package:
21
+ cd ../ui
22
+ npm install
23
+ npm run dev
24
+
25
+ Backend stub:
26
+ cd ../backend
27
+ go mod tidy
28
+ go run ./cmd/api
29
+
30
+ Dev stack (DB/Redis/Kafka):
31
+ cd ../deploy && docker compose -f docker-compose.dev.yml up`;
@@ -3,11 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.registryGo = void 0;
4
4
  exports.registryGo = `package events
5
5
 
6
- import (
7
- "context"
8
- "github.com/gorilla/websocket"
9
- )
10
-
11
6
  // Registry holds all registered event handlers.
12
7
  var Registry = make(map[string]EventHandler)
13
8
 
package/dist/index.js CHANGED
@@ -65,8 +65,6 @@ const dbGo_1 = require("./go/dbGo");
65
65
  const configGo_1 = require("./go/configGo");
66
66
  const mainGo_1 = require("./go/mainGo");
67
67
  const goMod_1 = require("./go/goMod");
68
- const useViraState_1 = require("./go/useViraState");
69
- const useViraStream_1 = require("./go/useViraStream");
70
68
  const channelHelpers_1 = require("./go/channelHelpers");
71
69
  const eventsAPI_1 = require("./go/eventsAPI");
72
70
  const eventHandlerTemplate_1 = require("./go/eventHandlerTemplate");
@@ -301,13 +299,11 @@ async function createFullstackProject(projectPath) {
301
299
  const frontendPath = path.join(projectPath, "frontend");
302
300
  const backendPath = path.join(projectPath, "backend");
303
301
  const uiPath = path.join(projectPath, "ui");
304
- const cliPath = path.join(projectPath, "cli");
305
302
  const pluginsPath = path.join(projectPath, "plugins");
306
303
  const migrationsPath = path.join(projectPath, "migrations");
307
304
  const deployPath = path.join(projectPath, "deploy");
308
305
  await fs.ensureDir(projectPath);
309
306
  await fs.ensureDir(uiPath);
310
- await fs.ensureDir(cliPath);
311
307
  await fs.ensureDir(pluginsPath);
312
308
  await fs.ensureDir(migrationsPath);
313
309
  await fs.ensureDir(deployPath);
@@ -363,12 +359,12 @@ async function createFrontendProject(projectPath) {
363
359
  preview: "vite preview",
364
360
  },
365
361
  dependencies: {
366
- "@vira-ui/core": "^0.3.0-alpha",
367
- "@vira-ui/ui": "^0.3.0-alpha",
362
+ "@vira-ui/core": "^1.0.0",
363
+ "@vira-ui/ui": "^1.0.0",
368
364
  "lucide-react": "^0.400.0",
369
365
  },
370
366
  devDependencies: {
371
- "@vira-ui/babel-plugin": "^0.3.0-alpha",
367
+ "@vira-ui/babel-plugin": "^1.0.0",
372
368
  "@vitejs/plugin-react": "^4.2.0",
373
369
  "@types/node": "^20.10.0",
374
370
  "@types/react": "^18.2.0",
@@ -388,8 +384,8 @@ async function createFrontendProject(projectPath) {
388
384
  await fs.writeFile(path.join(projectPath, "src", "index.css"), indexCss_1.indexCss);
389
385
  await fs.writeFile(path.join(projectPath, "src", "main.tsx"), mainTsx_1.mainTsx);
390
386
  await fs.writeFile(path.join(projectPath, "src", "App.tsx"), appTsx_1.appTsx);
391
- await fs.writeFile(path.join(projectPath, "src", "hooks", "useViraStream.ts"), useViraStream_1.useViraStream);
392
- await fs.writeFile(path.join(projectPath, "src", "hooks", "useViraState.ts"), useViraState_1.useViraState);
387
+ // VRP hooks are now provided by @vira-ui/core
388
+ // No need to generate useViraState/useViraStream files
393
389
  }
394
390
  /**
395
391
  * Бекенд-заготовка (Go) для последующего расширения (Kafka/Redis/PG)
@@ -2,51 +2,65 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.appTsx = void 0;
4
4
  // src/App.tsx
5
- exports.appTsx = `import { useState } from 'react';
6
- import { Container, Heading, Text, Button, Stack, Code } from '@vira-ui/ui';
7
- import { useViraState } from './hooks/useViraState';
8
- import './index.css';
9
-
10
- export function App() {
11
- const { data, sendEvent, sendUpdate, sendDiff } = useViraState<any>('demo');
12
- const [counter, setCounter] = useState(0);
13
-
14
- const bump = () => {
15
- const next = counter + 1;
16
- setCounter(next);
17
- sendUpdate({ counter: next });
18
- };
19
-
20
- const echo = () => {
21
- sendEvent('demo.echo', { message: 'hello from client', at: Date.now(), counter });
22
- };
23
-
24
- const patch = () => {
25
- sendDiff({ patched: true, ts: Date.now() });
26
- };
27
-
28
- return (
29
- <Container design={{ padding: 8, maxWidth: '900px', margin: '0 auto' }}>
30
- <Stack space={3}>
31
- <Heading design={{ fontSize: '2rem', fontWeight: 'bold' }}>Vira Engine demo</Heading>
32
- <Text color="#555">
33
- WebSocket demo channel <Code>demo</Code>. Uses handshake/session, versioned updates/diffs.
34
- </Text>
35
- <Stack direction="row" space={2}>
36
- <Button preset="primary" onClick={bump}>
37
- sendUpdate (counter)
38
- </Button>
39
- <Button preset="secondary" onClick={patch}>
40
- sendDiff (patch)
41
- </Button>
42
- <Button preset="ghost" onClick={echo}>
43
- sendEvent (demo.echo)
44
- </Button>
45
- </Stack>
46
- <Heading design={{ fontSize: '1.1rem' }}>State:</Heading>
47
- <Code block>{JSON.stringify(data ?? {}, null, 2)}</Code>
48
- </Stack>
49
- </Container>
50
- );
51
- }
5
+ exports.appTsx = `import { Container, Heading, Text, Button, Stack, Code } from '@vira-ui/ui';
6
+ import { useViraState } from '@vira-ui/react';
7
+ import './index.css';
8
+
9
+ interface DemoState {
10
+ counter: number;
11
+ patched?: boolean;
12
+ ts?: number;
13
+ message?: string;
14
+ at?: number;
15
+ }
16
+
17
+ export function App() {
18
+ const { data, sendEvent, sendUpdate, sendDiff } = useViraState<DemoState>('demo', {
19
+ enableMsgId: true,
20
+ });
21
+
22
+ // Use server state instead of local counter
23
+ const currentCounter = data?.counter ?? 0;
24
+
25
+ const bump = () => {
26
+ // Send diff with increment - server will handle versioning
27
+ sendDiff({ counter: currentCounter + 1 });
28
+ };
29
+
30
+ const echo = () => {
31
+ sendEvent('demo.echo', {
32
+ message: 'hello from client',
33
+ at: Date.now(),
34
+ counter: currentCounter,
35
+ });
36
+ };
37
+
38
+ const patch = () => {
39
+ sendDiff({ patched: true, ts: Date.now() });
40
+ };
41
+
42
+ return (
43
+ <Container design={{ padding: 8, maxWidth: '900px', margin: '0 auto' }}>
44
+ <Stack space={3}>
45
+ <Heading design={{ fontSize: '2rem', fontWeight: 'bold' }}>Vira Engine demo</Heading>
46
+ <Text color="#555">
47
+ WebSocket demo channel <Code>demo</Code>. Uses handshake/session, versioned updates/diffs.
48
+ </Text>
49
+ <Stack direction="row" space={2}>
50
+ <Button preset="primary" onClick={bump}>
51
+ sendDiff (counter + 1)
52
+ </Button>
53
+ <Button preset="secondary" onClick={patch}>
54
+ sendDiff (patch)
55
+ </Button>
56
+ <Button preset="ghost" onClick={echo}>
57
+ sendEvent (demo.echo)
58
+ </Button>
59
+ </Stack>
60
+ <Heading design={{ fontSize: '1.1rem' }}>State:</Heading>
61
+ <Code block>{JSON.stringify(data ?? {}, null, 2)}</Code>
62
+ </Stack>
63
+ </Container>
64
+ );
65
+ }
52
66
  `;
@@ -2,118 +2,99 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.kanbanService = void 0;
4
4
  // src/services/kanban.ts
5
- exports.kanbanService = `// Kanban service using Vira Core DI container + VRP
6
- // This demonstrates the Vira standard: services for business logic, hooks for React state
7
-
8
- import { createService } from '@vira-ui/core';
9
- import { useViraState } from '../hooks/useViraState';
10
- import type { KanbanBoard, KanbanCard, KanbanChannel } from '../models/kanban';
11
-
12
- // Create kanban service (singleton via DI container)
13
- // Service holds business logic, not React state
14
- createService('kanban', () => ({
15
- // Helper: get cards for a column (pure function)
16
- getColumnCards(board: KanbanBoard | null, columnId: string): KanbanCard[] {
17
- if (!board) return [];
18
- const column = board.columns.find(col => col.id === columnId);
19
- if (!column) return [];
20
- return column.cardIds
21
- .map(id => board.cards[id])
22
- .filter((card): card is KanbanCard => card !== undefined)
23
- .sort((a, b) => a.order - b.order);
24
- },
25
- }));
26
-
27
- import { createService, useService } from '@vira-ui/core';
28
- import { useViraState } from '../hooks/useViraState';
29
- import type { KanbanBoard, KanbanCard, KanbanChannel } from '../models/kanban';
30
-
31
- // Create kanban service (singleton via DI container)
32
- // Service holds pure business logic helpers
33
- createService('kanban', () => ({
34
- getColumnCards(board: KanbanBoard | null, columnId: string): KanbanCard[] {
35
- if (!board) return [];
36
- const column = board.columns.find(col => col.id === columnId);
37
- if (!column) return [];
38
- return column.cardIds
39
- .map(id => board.cards[id])
40
- .filter((card): card is KanbanCard => card !== undefined)
41
- .sort((a, b) => a.order - b.order);
42
- },
43
- }));
44
-
45
- // Hook for board operations (combines service + VRP state)
46
- export function useKanbanBoard(boardId: string) {
47
- const channel: KanbanChannel = \`kanban:\${boardId}\`;
48
- const { data: board, sendEvent, sendUpdate, sendDiff } = useViraState<KanbanBoard>(channel, null);
49
- const kanbanService = useService<{ getColumnCards: (board: KanbanBoard | null, columnId: string) => KanbanCard[] }>('kanban');
50
-
51
- return {
52
- board,
53
- // Card operations
54
- createCard(columnId: string, title: string, description?: string) {
55
- sendEvent('kanban.card.create', {
56
- boardId,
57
- columnId,
58
- title,
59
- description,
60
- at: Date.now(),
61
- });
62
- },
63
- updateCard(cardId: string, updates: Partial<Pick<KanbanCard, 'title' | 'description' | 'assignee' | 'tags'>>) {
64
- sendDiff({
65
- cards: {
66
- [cardId]: updates,
67
- },
68
- updatedAt: Date.now(),
69
- });
70
- },
71
- moveCard(cardId: string, fromColumnId: string, toColumnId: string, newOrder: number) {
72
- sendEvent('kanban.card.move', {
73
- boardId,
74
- cardId,
75
- fromColumnId,
76
- toColumnId,
77
- newOrder,
78
- at: Date.now(),
79
- });
80
- },
81
- deleteCard(cardId: string) {
82
- sendEvent('kanban.card.delete', {
83
- boardId,
84
- cardId,
85
- at: Date.now(),
86
- });
87
- },
88
- // Column operations
89
- createColumn(title: string, order: number) {
90
- sendEvent('kanban.column.create', {
91
- boardId,
92
- title,
93
- order,
94
- at: Date.now(),
95
- });
96
- },
97
- updateColumn(columnId: string, title: string) {
98
- if (!board) return;
99
- sendDiff({
100
- columns: board.columns.map(col =>
101
- col.id === columnId ? { ...col, title } : col
102
- ),
103
- updatedAt: Date.now(),
104
- });
105
- },
106
- // Board operations
107
- updateBoardTitle(title: string) {
108
- sendDiff({
109
- title,
110
- updatedAt: Date.now(),
111
- });
112
- },
113
- // Helper: get cards for a column (uses service)
114
- getColumnCards(columnId: string): KanbanCard[] {
115
- return kanbanService.getColumnCards(board, columnId);
116
- },
117
- };
118
- }
5
+ exports.kanbanService = `// Kanban service using Vira Core DI container + VRP
6
+ // This demonstrates the Vira standard: services for business logic, hooks for React state
7
+
8
+ import { createService, useService } from '@vira-ui/core';
9
+ import { useViraState } from '@vira-ui/react';
10
+ import type { KanbanBoard, KanbanCard, KanbanChannel } from '../models/kanban';
11
+
12
+ // Create kanban service (singleton via DI container)
13
+ // Service holds pure business logic helpers
14
+ createService('kanban', () => ({
15
+ getColumnCards(board: KanbanBoard | null, columnId: string): KanbanCard[] {
16
+ if (!board) return [];
17
+ const column = board.columns.find(col => col.id === columnId);
18
+ if (!column) return [];
19
+ return column.cardIds
20
+ .map(id => board.cards[id])
21
+ .filter((card): card is KanbanCard => card !== undefined)
22
+ .sort((a, b) => a.order - b.order);
23
+ },
24
+ }));
25
+
26
+ // Hook for board operations (combines service + VRP state)
27
+ export function useKanbanBoard(boardId: string) {
28
+ const channel: KanbanChannel = \`kanban:\${boardId}\`;
29
+ const { data: board, sendEvent, sendUpdate, sendDiff } = useViraState<KanbanBoard>(channel, null);
30
+ const kanbanService = useService<{ getColumnCards: (board: KanbanBoard | null, columnId: string) => KanbanCard[] }>('kanban');
31
+
32
+ return {
33
+ board,
34
+ // Card operations
35
+ createCard(columnId: string, title: string, description?: string) {
36
+ sendEvent('kanban.card.create', {
37
+ boardId,
38
+ columnId,
39
+ title,
40
+ description,
41
+ at: Date.now(),
42
+ });
43
+ },
44
+ updateCard(cardId: string, updates: Partial<Pick<KanbanCard, 'title' | 'description' | 'assignee' | 'tags'>>) {
45
+ sendDiff({
46
+ cards: {
47
+ [cardId]: updates,
48
+ },
49
+ updatedAt: Date.now(),
50
+ });
51
+ },
52
+ moveCard(cardId: string, fromColumnId: string, toColumnId: string, newOrder: number) {
53
+ sendEvent('kanban.card.move', {
54
+ boardId,
55
+ cardId,
56
+ fromColumnId,
57
+ toColumnId,
58
+ newOrder,
59
+ at: Date.now(),
60
+ });
61
+ },
62
+ deleteCard(cardId: string) {
63
+ sendEvent('kanban.card.delete', {
64
+ boardId,
65
+ cardId,
66
+ at: Date.now(),
67
+ });
68
+ },
69
+ // Column operations
70
+ createColumn(title: string, order: number) {
71
+ sendEvent('kanban.column.create', {
72
+ boardId,
73
+ title,
74
+ order,
75
+ at: Date.now(),
76
+ });
77
+ },
78
+ updateColumn(columnId: string, title: string) {
79
+ if (!board) return;
80
+ sendDiff({
81
+ columns: board.columns.map(col =>
82
+ col.id === columnId ? { ...col, title } : col
83
+ ),
84
+ updatedAt: Date.now(),
85
+ });
86
+ },
87
+ // Board operations
88
+ updateBoardTitle(title: string) {
89
+ sendDiff({
90
+ title,
91
+ updatedAt: Date.now(),
92
+ });
93
+ },
94
+ // Helper: get cards for a column (uses service)
95
+ getColumnCards(columnId: string): KanbanCard[] {
96
+ return kanbanService.getColumnCards(board, columnId);
97
+ },
98
+ };
99
+ }
119
100
  `;
@@ -16,10 +16,6 @@ exports.tsconfig = {
16
16
  esModuleInterop: true,
17
17
  skipLibCheck: true,
18
18
  forceConsistentCasingInFileNames: true,
19
- paths: {
20
- "@vira-ui/ui": ["./node_modules/@vira-ui/ui/src"],
21
- "@vira-ui/core": ["./node_modules/@vira-ui/core/src"],
22
- },
23
19
  },
24
20
  include: ["src"],
25
21
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vira-ui/cli",
3
- "version": "0.4.1-alpha",
3
+ "version": "1.0.1",
4
4
  "description": "CLI tool for ViraJS project generation",
5
5
  "author": "Vira Team",
6
6
  "license": "MIT",