@vira-ui/cli 0.3.2-alpha → 0.4.0-alpha

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.
Files changed (42) hide show
  1. package/dist/go/appYaml.js +34 -0
  2. package/dist/go/backendEnvExample.js +21 -0
  3. package/dist/go/backendReadme.js +18 -0
  4. package/dist/go/channelHelpers.js +29 -0
  5. package/dist/go/configGo.js +262 -0
  6. package/dist/go/dbGo.js +47 -0
  7. package/dist/go/dbYaml.js +11 -0
  8. package/dist/go/dockerCompose.js +38 -0
  9. package/dist/go/dockerComposeProd.js +54 -0
  10. package/dist/go/dockerfile.js +19 -0
  11. package/dist/go/eventHandlerTemplate.js +34 -0
  12. package/dist/go/eventsAPI.js +414 -0
  13. package/dist/go/goMod.js +20 -0
  14. package/dist/go/kafkaGo.js +71 -0
  15. package/dist/go/kafkaYaml.js +10 -0
  16. package/dist/go/kanbanHandlers.js +221 -0
  17. package/dist/go/mainGo.js +527 -0
  18. package/dist/go/readme.js +14 -0
  19. package/dist/go/redisGo.js +35 -0
  20. package/dist/go/redisYaml.js +8 -0
  21. package/dist/go/registryGo.js +47 -0
  22. package/dist/go/sqlcYaml.js +17 -0
  23. package/dist/go/stateStore.js +119 -0
  24. package/dist/go/typesGo.js +15 -0
  25. package/dist/go/useViraState.js +160 -0
  26. package/dist/go/useViraStream.js +167 -0
  27. package/dist/index.js +608 -200
  28. package/dist/react/appTsx.js +52 -0
  29. package/dist/react/envExample.js +7 -0
  30. package/dist/react/envLocal.js +5 -0
  31. package/dist/react/indexCss.js +22 -0
  32. package/dist/react/indexHtml.js +16 -0
  33. package/dist/react/kanbanAppTsx.js +34 -0
  34. package/dist/react/kanbanBoard.js +63 -0
  35. package/dist/react/kanbanCard.js +65 -0
  36. package/dist/react/kanbanColumn.js +67 -0
  37. package/dist/react/kanbanModels.js +37 -0
  38. package/dist/react/kanbanService.js +119 -0
  39. package/dist/react/mainTsx.js +16 -0
  40. package/dist/react/tsconfig.js +25 -0
  41. package/dist/react/viteConfig.js +31 -0
  42. package/package.json +3 -4
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.appTsx = void 0;
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
+ }
52
+ `;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.envExample = void 0;
4
+ exports.envExample = `# Frontend environment example
5
+ VITE_API_URL=http://localhost:8080
6
+ VITE_AUTH_TOKEN=
7
+ `;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.envLocal = void 0;
4
+ exports.envLocal = `VITE_API_URL=http://localhost:8080
5
+ `;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.indexCss = void 0;
4
+ // src/index.css
5
+ exports.indexCss = `* {
6
+ margin: 0;
7
+ padding: 0;
8
+ box-sizing: border-box;
9
+ }
10
+
11
+ body {
12
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
13
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
14
+ sans-serif;
15
+ -webkit-font-smoothing: antialiased;
16
+ -moz-osx-font-smoothing: grayscale;
17
+ }
18
+
19
+ #root {
20
+ min-height: 100vh;
21
+ }
22
+ `;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.indexHtml = void 0;
4
+ exports.indexHtml = `<!DOCTYPE html>
5
+ <html lang="en">
6
+ <head>
7
+ <meta charset="UTF-8" />
8
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
9
+ <title>Vira App</title>
10
+ </head>
11
+ <body>
12
+ <div id="root"></div>
13
+ <script type="module" src="/src/main.tsx"></script>
14
+ </body>
15
+ </html>
16
+ `;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.kanbanAppTsx = void 0;
4
+ // src/App.tsx - Kanban reference app (VRP + Vira UI/Core standards)
5
+ exports.kanbanAppTsx = `import { ViraProvider } from '@vira-ui/ui';
6
+ import { Box } from '@vira-ui/ui';
7
+ import { KanbanBoard } from './components/KanbanBoard';
8
+ import './index.css';
9
+
10
+ /**
11
+ * Kanban Reference App - Demonstrates Vira Framework standards:
12
+ *
13
+ * ✅ Uses @vira-ui/ui components (Card, Button, Flex, Box, Input, etc.)
14
+ * ✅ Uses @vira-ui/core services (createService/useService)
15
+ * ✅ Uses VRP for state (useViraState hook)
16
+ * ✅ Declarative style (no inline styles, no manual state management)
17
+ * ✅ Server-authoritative state (client is terminal)
18
+ * ✅ Auto-binding ready (action/model props)
19
+ *
20
+ * This is THE standard for Vira apps.
21
+ */
22
+
23
+ export function App() {
24
+ const boardId = 'demo-board';
25
+
26
+ return (
27
+ <ViraProvider hideDataDesign={false} theme="default">
28
+ <Box design={{ height: '100vh', background: '#fafafa' }}>
29
+ <KanbanBoard boardId={boardId} />
30
+ </Box>
31
+ </ViraProvider>
32
+ );
33
+ }
34
+ `;
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.kanbanBoard = void 0;
4
+ // src/components/KanbanBoard.tsx
5
+ exports.kanbanBoard = `import { Container, Flex, Input, Text, Box } from '@vira-ui/ui';
6
+ import { useKanbanBoard } from '../services/kanban';
7
+ import { KanbanColumn } from './KanbanColumn';
8
+
9
+ interface KanbanBoardProps {
10
+ boardId: string;
11
+ }
12
+
13
+ export function KanbanBoard({ boardId }: KanbanBoardProps) {
14
+ const board = useKanbanBoard(boardId);
15
+
16
+ if (!board.board) {
17
+ return (
18
+ <Box design={{ padding: 10, textAlign: 'center', color: '#999' }}>
19
+ <Text>Loading board...</Text>
20
+ </Box>
21
+ );
22
+ }
23
+
24
+ return (
25
+ <Container design={{ padding: 6, height: '100vh', display: 'flex', flexDirection: 'column' }}>
26
+ <Box design={{ marginBottom: 6 }}>
27
+ <Input
28
+ model={\`kanban.\${boardId}.title\`}
29
+ value={board.board.title}
30
+ onChange={(e) => board.updateBoardTitle(e.target.value)}
31
+ design={{
32
+ fontSize: '24px',
33
+ fontWeight: 'bold',
34
+ border: 'none',
35
+ borderBottom: '2px solid transparent',
36
+ padding: 1,
37
+ }}
38
+ onFocus={(e) => {
39
+ e.target.style.borderBottomColor = '#007bff';
40
+ }}
41
+ onBlur={(e) => {
42
+ e.target.style.borderBottomColor = 'transparent';
43
+ }}
44
+ />
45
+ </Box>
46
+ <Flex
47
+ gap={4}
48
+ design={{
49
+ overflowX: 'auto',
50
+ flex: 1,
51
+ paddingBottom: 4,
52
+ }}
53
+ >
54
+ {board.board.columns
55
+ .sort((a, b) => a.order - b.order)
56
+ .map(column => (
57
+ <KanbanColumn key={column.id} column={column} boardId={boardId} />
58
+ ))}
59
+ </Flex>
60
+ </Container>
61
+ );
62
+ }
63
+ `;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.kanbanCard = void 0;
4
+ // src/components/KanbanCard.tsx
5
+ exports.kanbanCard = `import { Card, Flex, Box, Text, Tag, Button } from '@vira-ui/ui';
6
+ import { useKanbanBoard } from '../services/kanban';
7
+ import { KanbanCard as CardType } from '../models/kanban';
8
+
9
+ interface KanbanCardProps {
10
+ card: CardType;
11
+ boardId: string;
12
+ }
13
+
14
+ export function KanbanCard({ card, boardId }: KanbanCardProps) {
15
+ const board = useKanbanBoard(boardId);
16
+
17
+ return (
18
+ <Card
19
+ design={{
20
+ marginBottom: 2,
21
+ cursor: 'pointer',
22
+ padding: 3,
23
+ }}
24
+ onClick={() => {
25
+ // Open card details (future: modal)
26
+ }}
27
+ >
28
+ <Text design={{ fontWeight: 600, fontSize: '14px', marginBottom: 1 }}>
29
+ {card.title}
30
+ </Text>
31
+ {card.description && (
32
+ <Text design={{ fontSize: '12px', color: '#666', marginBottom: 2 }}>
33
+ {card.description}
34
+ </Text>
35
+ )}
36
+ <Flex justify="space-between" align="center">
37
+ <Flex gap={1}>
38
+ {card.assignee && (
39
+ <Text design={{ fontSize: '11px', color: '#888' }}>@{card.assignee}</Text>
40
+ )}
41
+ {card.tags && card.tags.length > 0 && (
42
+ <Flex gap={1}>
43
+ {card.tags.map(tag => (
44
+ <Tag key={tag} design={{ fontSize: '10px' }}>
45
+ {tag}
46
+ </Tag>
47
+ ))}
48
+ </Flex>
49
+ )}
50
+ </Flex>
51
+ <Button
52
+ preset="ghost"
53
+ design={{ padding: 1, minWidth: 'auto' }}
54
+ onClick={(e) => {
55
+ e.stopPropagation();
56
+ board.deleteCard(card.id);
57
+ }}
58
+ >
59
+ ×
60
+ </Button>
61
+ </Flex>
62
+ </Card>
63
+ );
64
+ }
65
+ `;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.kanbanColumn = void 0;
4
+ // src/components/KanbanColumn.tsx
5
+ exports.kanbanColumn = `import { Box, Flex, Text, Button, ScrollArea } from '@vira-ui/ui';
6
+ import { useKanbanBoard } from '../services/kanban';
7
+ import { KanbanColumn as ColumnType } from '../models/kanban';
8
+ import { KanbanCard } from './KanbanCard';
9
+
10
+ interface KanbanColumnProps {
11
+ column: ColumnType;
12
+ boardId: string;
13
+ }
14
+
15
+ export function KanbanColumn({ column, boardId }: KanbanColumnProps) {
16
+ const board = useKanbanBoard(boardId);
17
+ const cards = board.getColumnCards(column.id);
18
+
19
+ const handleAddCard = () => {
20
+ const title = prompt('Card title:');
21
+ if (title) {
22
+ board.createCard(column.id, title);
23
+ }
24
+ };
25
+
26
+ return (
27
+ <Box
28
+ design={{
29
+ background: '#f5f5f5',
30
+ borderRadius: 2,
31
+ padding: 4,
32
+ minWidth: '280px',
33
+ maxHeight: 'calc(100vh - 100px)',
34
+ display: 'flex',
35
+ flexDirection: 'column',
36
+ }}
37
+ >
38
+ <Text design={{ fontWeight: 600, fontSize: '16px', marginBottom: 4 }}>
39
+ {column.title}
40
+ </Text>
41
+ <ScrollArea
42
+ design={{
43
+ flex: 1,
44
+ marginBottom: 3,
45
+ }}
46
+ >
47
+ <Flex direction="column" gap={2}>
48
+ {cards.map(card => (
49
+ <KanbanCard key={card.id} card={card} boardId={boardId} />
50
+ ))}
51
+ </Flex>
52
+ </ScrollArea>
53
+ <Button
54
+ preset="ghost"
55
+ design={{
56
+ width: '100%',
57
+ border: '1px dashed #ccc',
58
+ padding: 2,
59
+ }}
60
+ onClick={handleAddCard}
61
+ >
62
+ + Add card
63
+ </Button>
64
+ </Box>
65
+ );
66
+ }
67
+ `;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.kanbanModels = void 0;
4
+ // src/models/kanban.ts
5
+ exports.kanbanModels = `// Kanban data models (shared with backend)
6
+
7
+ export interface KanbanCard {
8
+ id: string;
9
+ title: string;
10
+ description?: string;
11
+ columnId: string;
12
+ order: number;
13
+ assignee?: string;
14
+ tags?: string[];
15
+ createdAt: number;
16
+ updatedAt: number;
17
+ }
18
+
19
+ export interface KanbanColumn {
20
+ id: string;
21
+ title: string;
22
+ order: number;
23
+ cardIds: string[]; // ordered list
24
+ }
25
+
26
+ export interface KanbanBoard {
27
+ id: string;
28
+ title: string;
29
+ columns: KanbanColumn[];
30
+ cards: Record<string, KanbanCard>; // cardId -> Card
31
+ createdAt: number;
32
+ updatedAt: number;
33
+ }
34
+
35
+ // VRP Channel types
36
+ export type KanbanChannel = \`kanban:\${string}\`;
37
+ `;
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.kanbanService = void 0;
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
+ }
119
+ `;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mainTsx = void 0;
4
+ exports.mainTsx = `import React from 'react';
5
+ import ReactDOM from 'react-dom/client';
6
+ import { ViraProvider } from '@vira-ui/ui';
7
+ import { App } from './App';
8
+
9
+ ReactDOM.createRoot(document.getElementById("root")!).render(
10
+ <React.StrictMode>
11
+ <ViraProvider hideDataDesign={false} theme="default">
12
+ <App />
13
+ </ViraProvider>
14
+ </React.StrictMode>
15
+ );
16
+ `;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tsconfig = void 0;
4
+ // tsconfig.json
5
+ exports.tsconfig = {
6
+ compilerOptions: {
7
+ target: "ES2020",
8
+ module: "ESNext",
9
+ lib: ["ES2020", "DOM", "DOM.Iterable"],
10
+ jsx: "react-jsx",
11
+ moduleResolution: "bundler",
12
+ resolveJsonModule: true,
13
+ allowJs: true,
14
+ strict: true,
15
+ noEmit: true,
16
+ esModuleInterop: true,
17
+ skipLibCheck: true,
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
+ },
24
+ include: ["src"],
25
+ };
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.viteConfig = void 0;
4
+ exports.viteConfig = `import { defineConfig, loadEnv } from 'vite';
5
+ import react from '@vitejs/plugin-react';
6
+
7
+ export default defineConfig(({ mode }) => {
8
+ const env = loadEnv(mode, process.cwd(), '');
9
+ const API_URL = env.VITE_API_URL || 'http://localhost:8080';
10
+
11
+ return {
12
+ plugins: [react()],
13
+ server: {
14
+ proxy: {
15
+ '/api': {
16
+ target: API_URL,
17
+ changeOrigin: true,
18
+ },
19
+ '/ws': {
20
+ target: API_URL,
21
+ ws: true,
22
+ changeOrigin: true,
23
+ },
24
+ },
25
+ },
26
+ optimizeDeps: {
27
+ exclude: ['lucide-react'],
28
+ },
29
+ };
30
+ });
31
+ `;
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@vira-ui/cli",
3
- "version": "0.3.2-alpha",
3
+ "version": "0.4.0-alpha",
4
4
  "description": "CLI tool for ViraJS project generation",
5
5
  "author": "Vira Team",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "https://github.com/vira-ui/vira-ui"
9
+ "url": "git+https://github.com/skrolikov/vira-cli.git"
10
10
  },
11
11
  "keywords": [
12
12
  "vira",
@@ -18,7 +18,7 @@
18
18
  "ui"
19
19
  ],
20
20
  "bin": {
21
- "vira": "./dist/index.js"
21
+ "vira": "dist/index.js"
22
22
  },
23
23
  "main": "dist/index.js",
24
24
  "files": [
@@ -43,4 +43,3 @@
43
43
  "typescript": "^5.3.0"
44
44
  }
45
45
  }
46
-