@vira-ui/cli 1.0.0 → 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/eventsAPI.js +5 -0
- package/dist/react/appTsx.js +61 -47
- package/dist/react/kanbanService.js +95 -94
- package/package.json +1 -1
package/dist/go/eventsAPI.js
CHANGED
|
@@ -16,6 +16,11 @@ import (
|
|
|
16
16
|
// VRP_VERSION is the current protocol version.
|
|
17
17
|
const VRP_VERSION = "0.1"
|
|
18
18
|
|
|
19
|
+
// ProtocolVersion returns the current VRP version.
|
|
20
|
+
func ProtocolVersion() string {
|
|
21
|
+
return VRP_VERSION
|
|
22
|
+
}
|
|
23
|
+
|
|
19
24
|
// WSMessage matches protocol message schema.
|
|
20
25
|
type WSMessage struct {
|
|
21
26
|
Type string \`json:"type"\`
|
package/dist/react/appTsx.js
CHANGED
|
@@ -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 {
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
</
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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,98 +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, useService
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return
|
|
19
|
-
|
|
20
|
-
.
|
|
21
|
-
.
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
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
|
+
}
|
|
99
100
|
`;
|