@vira-ui/cli 1.1.2 → 1.2.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/README.md +454 -1029
- package/dist/go/appYaml.js +30 -30
- package/dist/go/backendEnvExample.js +17 -17
- package/dist/go/backendReadme.js +14 -14
- package/dist/go/channelHelpers.js +25 -25
- package/dist/go/configGo.js +258 -258
- package/dist/go/dbGo.js +43 -43
- package/dist/go/dbYaml.js +7 -7
- package/dist/go/dockerCompose.js +48 -48
- package/dist/go/dockerComposeProd.js +78 -78
- package/dist/go/dockerfile.js +15 -15
- package/dist/go/eventHandlerTemplate.js +22 -22
- package/dist/go/eventsAPI.js +411 -411
- package/dist/go/goMod.js +16 -16
- package/dist/go/kafkaGo.js +67 -67
- package/dist/go/kafkaYaml.js +6 -6
- package/dist/go/kanbanHandlers.js +216 -216
- package/dist/go/mainGo.js +558 -558
- package/dist/go/readme.js +27 -27
- package/dist/go/redisGo.js +31 -31
- package/dist/go/redisYaml.js +4 -4
- package/dist/go/registryGo.js +38 -38
- package/dist/go/sqlcYaml.js +13 -13
- package/dist/go/stateStore.js +115 -115
- package/dist/go/typesGo.js +11 -11
- package/dist/index.js +472 -24
- package/dist/react/envExample.js +3 -3
- package/dist/react/envLocal.js +1 -1
- package/dist/react/indexCss.js +17 -17
- package/dist/react/indexHtml.js +12 -12
- package/dist/react/kanbanAppTsx.js +29 -29
- package/dist/react/kanbanBoard.js +58 -58
- package/dist/react/kanbanCard.js +60 -60
- package/dist/react/kanbanColumn.js +62 -62
- package/dist/react/kanbanModels.js +32 -32
- package/dist/react/mainTsx.js +12 -12
- package/dist/react/viteConfig.js +27 -27
- package/package.json +47 -45
- package/dist/go/useViraState.js +0 -160
- package/dist/go/useViraStream.js +0 -167
package/dist/go/readme.js
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.readme = void 0;
|
|
4
|
-
exports.readme = `# Vira Engine Monorepo (scaffold)
|
|
5
|
-
|
|
6
|
-
Структура:
|
|
7
|
-
- frontend/ — Vite + Vira UI приложение
|
|
8
|
-
- backend/ — Go API (стаб)
|
|
9
|
-
- ui/ — Vira UI пакет/шоукейсы (vite)
|
|
10
|
-
- cli/ — CLI расширения/плагины
|
|
11
|
-
- plugins/ — интеграции
|
|
12
|
-
- migrations/ — SQL/Go миграции
|
|
13
|
-
- deploy/ — docker-compose/devops артефакты
|
|
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):
|
|
4
|
+
exports.readme = `# Vira Engine Monorepo (scaffold)
|
|
5
|
+
|
|
6
|
+
Структура:
|
|
7
|
+
- frontend/ — Vite + Vira UI приложение
|
|
8
|
+
- backend/ — Go API (стаб)
|
|
9
|
+
- ui/ — Vira UI пакет/шоукейсы (vite)
|
|
10
|
+
- cli/ — CLI расширения/плагины
|
|
11
|
+
- plugins/ — интеграции
|
|
12
|
+
- migrations/ — SQL/Go миграции
|
|
13
|
+
- deploy/ — docker-compose/devops артефакты
|
|
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
31
|
cd ../deploy && docker compose -f docker-compose.dev.yml up`;
|
package/dist/go/redisGo.js
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.redisGo = void 0;
|
|
4
|
-
exports.redisGo = `package cache
|
|
5
|
-
|
|
6
|
-
import (
|
|
7
|
-
"context"
|
|
8
|
-
"fmt"
|
|
9
|
-
"time"
|
|
10
|
-
|
|
11
|
-
"github.com/redis/go-redis/v9"
|
|
12
|
-
"github.com/rs/zerolog"
|
|
13
|
-
|
|
14
|
-
"vira-engine-backend/internal/config"
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
func NewRedisClient(ctx context.Context, cfg config.Config, logger zerolog.Logger) (*redis.Client, error) {
|
|
18
|
-
addr := fmt.Sprintf("%s:%d", cfg.Redis.Host, cfg.Redis.Port)
|
|
19
|
-
client := redis.NewClient(&redis.Options{
|
|
20
|
-
Addr: addr,
|
|
21
|
-
Password: cfg.Redis.Password,
|
|
22
|
-
DB: cfg.Redis.DB,
|
|
23
|
-
ReadTimeout: 3 * time.Second,
|
|
24
|
-
WriteTimeout: 3 * time.Second,
|
|
25
|
-
DialTimeout: 3 * time.Second,
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
if _, err := client.Ping(ctx).Result(); err != nil {
|
|
29
|
-
return nil, fmt.Errorf("ping redis: %w", err)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
logger.Info().Str("redis.addr", addr).Int("redis.db", cfg.Redis.DB).Msg("redis ready")
|
|
33
|
-
return client, nil
|
|
34
|
-
}
|
|
4
|
+
exports.redisGo = `package cache
|
|
5
|
+
|
|
6
|
+
import (
|
|
7
|
+
"context"
|
|
8
|
+
"fmt"
|
|
9
|
+
"time"
|
|
10
|
+
|
|
11
|
+
"github.com/redis/go-redis/v9"
|
|
12
|
+
"github.com/rs/zerolog"
|
|
13
|
+
|
|
14
|
+
"vira-engine-backend/internal/config"
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
func NewRedisClient(ctx context.Context, cfg config.Config, logger zerolog.Logger) (*redis.Client, error) {
|
|
18
|
+
addr := fmt.Sprintf("%s:%d", cfg.Redis.Host, cfg.Redis.Port)
|
|
19
|
+
client := redis.NewClient(&redis.Options{
|
|
20
|
+
Addr: addr,
|
|
21
|
+
Password: cfg.Redis.Password,
|
|
22
|
+
DB: cfg.Redis.DB,
|
|
23
|
+
ReadTimeout: 3 * time.Second,
|
|
24
|
+
WriteTimeout: 3 * time.Second,
|
|
25
|
+
DialTimeout: 3 * time.Second,
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
if _, err := client.Ping(ctx).Result(); err != nil {
|
|
29
|
+
return nil, fmt.Errorf("ping redis: %w", err)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
logger.Info().Str("redis.addr", addr).Int("redis.db", cfg.Redis.DB).Msg("redis ready")
|
|
33
|
+
return client, nil
|
|
34
|
+
}
|
|
35
35
|
`;
|
package/dist/go/redisYaml.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.redisYaml = void 0;
|
|
4
|
-
exports.redisYaml = `host: localhost
|
|
5
|
-
port: 6379
|
|
6
|
-
db: 0
|
|
7
|
-
password: ""
|
|
4
|
+
exports.redisYaml = `host: localhost
|
|
5
|
+
port: 6379
|
|
6
|
+
db: 0
|
|
7
|
+
password: ""
|
|
8
8
|
`;
|
package/dist/go/registryGo.js
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.registryGo = void 0;
|
|
4
|
-
exports.registryGo = `package events
|
|
5
|
-
|
|
6
|
-
// Registry holds all registered event handlers.
|
|
7
|
-
var Registry = make(map[string]EventHandler)
|
|
8
|
-
|
|
9
|
-
// Register registers an event handler by name.
|
|
10
|
-
func Register(name string, handler EventHandler) {
|
|
11
|
-
Registry[name] = handler
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// RegisterAll registers multiple handlers at once.
|
|
15
|
-
func RegisterAll(handlers map[string]EventHandler) {
|
|
16
|
-
for name, handler := range handlers {
|
|
17
|
-
Registry[name] = handler
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Get returns a handler by name.
|
|
22
|
-
func Get(name string) (EventHandler, bool) {
|
|
23
|
-
handler, ok := Registry[name]
|
|
24
|
-
return handler, ok
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Apply registers all handlers from Registry into a Hub.
|
|
28
|
-
func (h *Hub) ApplyRegistry() {
|
|
29
|
-
h.mu.Lock()
|
|
30
|
-
defer h.mu.Unlock()
|
|
31
|
-
for name, handler := range Registry {
|
|
32
|
-
h.events[name] = handler
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Example handler registration (auto-generated by CLI):
|
|
37
|
-
// func init() {
|
|
38
|
-
// Register("demo.echo", handleDemoEvent)
|
|
39
|
-
// Register("task.update", handleTaskUpdate)
|
|
40
|
-
// Register("user.setStatus", handleUserStatus)
|
|
41
|
-
// }
|
|
4
|
+
exports.registryGo = `package events
|
|
5
|
+
|
|
6
|
+
// Registry holds all registered event handlers.
|
|
7
|
+
var Registry = make(map[string]EventHandler)
|
|
8
|
+
|
|
9
|
+
// Register registers an event handler by name.
|
|
10
|
+
func Register(name string, handler EventHandler) {
|
|
11
|
+
Registry[name] = handler
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// RegisterAll registers multiple handlers at once.
|
|
15
|
+
func RegisterAll(handlers map[string]EventHandler) {
|
|
16
|
+
for name, handler := range handlers {
|
|
17
|
+
Registry[name] = handler
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Get returns a handler by name.
|
|
22
|
+
func Get(name string) (EventHandler, bool) {
|
|
23
|
+
handler, ok := Registry[name]
|
|
24
|
+
return handler, ok
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Apply registers all handlers from Registry into a Hub.
|
|
28
|
+
func (h *Hub) ApplyRegistry() {
|
|
29
|
+
h.mu.Lock()
|
|
30
|
+
defer h.mu.Unlock()
|
|
31
|
+
for name, handler := range Registry {
|
|
32
|
+
h.events[name] = handler
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Example handler registration (auto-generated by CLI):
|
|
37
|
+
// func init() {
|
|
38
|
+
// Register("demo.echo", handleDemoEvent)
|
|
39
|
+
// Register("task.update", handleTaskUpdate)
|
|
40
|
+
// Register("user.setStatus", handleUserStatus)
|
|
41
|
+
// }
|
|
42
42
|
`;
|
package/dist/go/sqlcYaml.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.sqlcYaml = void 0;
|
|
4
|
-
exports.sqlcYaml = `version: "2"
|
|
5
|
-
sql:
|
|
6
|
-
- engine: "postgresql"
|
|
7
|
-
schema: "migrations"
|
|
8
|
-
queries: "queries"
|
|
9
|
-
gen:
|
|
10
|
-
go:
|
|
11
|
-
package: "gen"
|
|
12
|
-
out: "internal/db/gen"
|
|
13
|
-
sql_package: "pgx/v5"
|
|
14
|
-
emit_interface: true
|
|
15
|
-
emit_db_tags: true
|
|
16
|
-
emit_empty_slices: true
|
|
4
|
+
exports.sqlcYaml = `version: "2"
|
|
5
|
+
sql:
|
|
6
|
+
- engine: "postgresql"
|
|
7
|
+
schema: "migrations"
|
|
8
|
+
queries: "queries"
|
|
9
|
+
gen:
|
|
10
|
+
go:
|
|
11
|
+
package: "gen"
|
|
12
|
+
out: "internal/db/gen"
|
|
13
|
+
sql_package: "pgx/v5"
|
|
14
|
+
emit_interface: true
|
|
15
|
+
emit_db_tags: true
|
|
16
|
+
emit_empty_slices: true
|
|
17
17
|
`;
|
package/dist/go/stateStore.js
CHANGED
|
@@ -1,119 +1,119 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.stateStore = void 0;
|
|
4
|
-
exports.stateStore = `package events
|
|
5
|
-
|
|
6
|
-
import (
|
|
7
|
-
"context"
|
|
8
|
-
"encoding/json"
|
|
9
|
-
"fmt"
|
|
10
|
-
"time"
|
|
11
|
-
|
|
12
|
-
"github.com/redis/go-redis/v9"
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
// StateStore abstracts persist/replay of channel state.
|
|
16
|
-
type StateStore interface {
|
|
17
|
-
SaveSnapshot(ctx context.Context, channel string, snapshot StateSnapshot, ttlSec int) error
|
|
18
|
-
LoadSnapshot(ctx context.Context, channel string) (StateSnapshot, bool, error)
|
|
19
|
-
AppendHistory(ctx context.Context, channel string, snapshot StateSnapshot, maxLen int, ttlSec int) error
|
|
20
|
-
LoadHistory(ctx context.Context, channel string, fromVersion int64) ([]StateSnapshot, error)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// MemoryStore fallback (no-op persist)
|
|
24
|
-
type MemoryStore struct{}
|
|
25
|
-
|
|
26
|
-
func (MemoryStore) SaveSnapshot(ctx context.Context, channel string, snapshot StateSnapshot, ttlSec int) error { return nil }
|
|
27
|
-
func (MemoryStore) LoadSnapshot(ctx context.Context, channel string) (StateSnapshot, bool, error) {
|
|
28
|
-
return StateSnapshot{}, false, nil
|
|
29
|
-
}
|
|
30
|
-
func (MemoryStore) AppendHistory(ctx context.Context, channel string, snapshot StateSnapshot, maxLen int, ttlSec int) error {
|
|
31
|
-
return nil
|
|
32
|
-
}
|
|
33
|
-
func (MemoryStore) LoadHistory(ctx context.Context, channel string, fromVersion int64) ([]StateSnapshot, error) {
|
|
34
|
-
return nil, nil
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// RedisStore persists snapshots/history into Redis.
|
|
38
|
-
type RedisStore struct {
|
|
39
|
-
client *redis.Client
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
func NewRedisStore(client *redis.Client) *RedisStore {
|
|
43
|
-
return &RedisStore{client: client}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Keys:
|
|
47
|
-
// snapshot:<channel> -> json StateSnapshot
|
|
48
|
-
// history:<channel> -> list of json StateSnapshot (trimmed)
|
|
49
|
-
|
|
50
|
-
func snapshotKey(ch string) string { return fmt.Sprintf("snapshot:%s", ch) }
|
|
51
|
-
func historyKey(ch string) string { return fmt.Sprintf("history:%s", ch) }
|
|
52
|
-
|
|
53
|
-
func (s *RedisStore) SaveSnapshot(ctx context.Context, channel string, snapshot StateSnapshot, ttlSec int) error {
|
|
54
|
-
raw, err := json.Marshal(snapshot)
|
|
55
|
-
if err != nil {
|
|
56
|
-
return err
|
|
57
|
-
}
|
|
58
|
-
key := snapshotKey(channel)
|
|
59
|
-
if err := s.client.Set(ctx, key, raw, time.Duration(ttlSec)*time.Second).Err(); err != nil {
|
|
60
|
-
return err
|
|
61
|
-
}
|
|
62
|
-
return nil
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
func (s *RedisStore) LoadSnapshot(ctx context.Context, channel string) (StateSnapshot, bool, error) {
|
|
66
|
-
key := snapshotKey(channel)
|
|
67
|
-
val, err := s.client.Get(ctx, key).Bytes()
|
|
68
|
-
if err == redis.Nil {
|
|
69
|
-
return StateSnapshot{}, false, nil
|
|
70
|
-
}
|
|
71
|
-
if err != nil {
|
|
72
|
-
return StateSnapshot{}, false, err
|
|
73
|
-
}
|
|
74
|
-
var snap StateSnapshot
|
|
75
|
-
if err := json.Unmarshal(val, &snap); err != nil {
|
|
76
|
-
return StateSnapshot{}, false, err
|
|
77
|
-
}
|
|
78
|
-
return snap, true, nil
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
func (s *RedisStore) AppendHistory(ctx context.Context, channel string, snapshot StateSnapshot, maxLen int, ttlSec int) error {
|
|
82
|
-
raw, err := json.Marshal(snapshot)
|
|
83
|
-
if err != nil {
|
|
84
|
-
return err
|
|
85
|
-
}
|
|
86
|
-
key := historyKey(channel)
|
|
87
|
-
pipe := s.client.Pipeline()
|
|
88
|
-
pipe.RPush(ctx, key, raw)
|
|
89
|
-
if maxLen > 0 {
|
|
90
|
-
pipe.LTrim(ctx, key, int64(-maxLen), int64(-1))
|
|
91
|
-
}
|
|
92
|
-
if ttlSec > 0 {
|
|
93
|
-
pipe.Expire(ctx, key, time.Duration(ttlSec)*time.Second)
|
|
94
|
-
}
|
|
95
|
-
_, err = pipe.Exec(ctx)
|
|
96
|
-
return err
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
func (s *RedisStore) LoadHistory(ctx context.Context, channel string, fromVersion int64) ([]StateSnapshot, error) {
|
|
100
|
-
key := historyKey(channel)
|
|
101
|
-
items, err := s.client.LRange(ctx, key, 0, -1).Result()
|
|
102
|
-
if err == redis.Nil {
|
|
103
|
-
return nil, nil
|
|
104
|
-
}
|
|
105
|
-
if err != nil {
|
|
106
|
-
return nil, err
|
|
107
|
-
}
|
|
108
|
-
var out []StateSnapshot
|
|
109
|
-
for _, item := range items {
|
|
110
|
-
var snap StateSnapshot
|
|
111
|
-
if err := json.Unmarshal([]byte(item), &snap); err == nil {
|
|
112
|
-
if snap.VersionNo > fromVersion {
|
|
113
|
-
out = append(out, snap)
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return out, nil
|
|
118
|
-
}
|
|
4
|
+
exports.stateStore = `package events
|
|
5
|
+
|
|
6
|
+
import (
|
|
7
|
+
"context"
|
|
8
|
+
"encoding/json"
|
|
9
|
+
"fmt"
|
|
10
|
+
"time"
|
|
11
|
+
|
|
12
|
+
"github.com/redis/go-redis/v9"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
// StateStore abstracts persist/replay of channel state.
|
|
16
|
+
type StateStore interface {
|
|
17
|
+
SaveSnapshot(ctx context.Context, channel string, snapshot StateSnapshot, ttlSec int) error
|
|
18
|
+
LoadSnapshot(ctx context.Context, channel string) (StateSnapshot, bool, error)
|
|
19
|
+
AppendHistory(ctx context.Context, channel string, snapshot StateSnapshot, maxLen int, ttlSec int) error
|
|
20
|
+
LoadHistory(ctx context.Context, channel string, fromVersion int64) ([]StateSnapshot, error)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// MemoryStore fallback (no-op persist)
|
|
24
|
+
type MemoryStore struct{}
|
|
25
|
+
|
|
26
|
+
func (MemoryStore) SaveSnapshot(ctx context.Context, channel string, snapshot StateSnapshot, ttlSec int) error { return nil }
|
|
27
|
+
func (MemoryStore) LoadSnapshot(ctx context.Context, channel string) (StateSnapshot, bool, error) {
|
|
28
|
+
return StateSnapshot{}, false, nil
|
|
29
|
+
}
|
|
30
|
+
func (MemoryStore) AppendHistory(ctx context.Context, channel string, snapshot StateSnapshot, maxLen int, ttlSec int) error {
|
|
31
|
+
return nil
|
|
32
|
+
}
|
|
33
|
+
func (MemoryStore) LoadHistory(ctx context.Context, channel string, fromVersion int64) ([]StateSnapshot, error) {
|
|
34
|
+
return nil, nil
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// RedisStore persists snapshots/history into Redis.
|
|
38
|
+
type RedisStore struct {
|
|
39
|
+
client *redis.Client
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
func NewRedisStore(client *redis.Client) *RedisStore {
|
|
43
|
+
return &RedisStore{client: client}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Keys:
|
|
47
|
+
// snapshot:<channel> -> json StateSnapshot
|
|
48
|
+
// history:<channel> -> list of json StateSnapshot (trimmed)
|
|
49
|
+
|
|
50
|
+
func snapshotKey(ch string) string { return fmt.Sprintf("snapshot:%s", ch) }
|
|
51
|
+
func historyKey(ch string) string { return fmt.Sprintf("history:%s", ch) }
|
|
52
|
+
|
|
53
|
+
func (s *RedisStore) SaveSnapshot(ctx context.Context, channel string, snapshot StateSnapshot, ttlSec int) error {
|
|
54
|
+
raw, err := json.Marshal(snapshot)
|
|
55
|
+
if err != nil {
|
|
56
|
+
return err
|
|
57
|
+
}
|
|
58
|
+
key := snapshotKey(channel)
|
|
59
|
+
if err := s.client.Set(ctx, key, raw, time.Duration(ttlSec)*time.Second).Err(); err != nil {
|
|
60
|
+
return err
|
|
61
|
+
}
|
|
62
|
+
return nil
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
func (s *RedisStore) LoadSnapshot(ctx context.Context, channel string) (StateSnapshot, bool, error) {
|
|
66
|
+
key := snapshotKey(channel)
|
|
67
|
+
val, err := s.client.Get(ctx, key).Bytes()
|
|
68
|
+
if err == redis.Nil {
|
|
69
|
+
return StateSnapshot{}, false, nil
|
|
70
|
+
}
|
|
71
|
+
if err != nil {
|
|
72
|
+
return StateSnapshot{}, false, err
|
|
73
|
+
}
|
|
74
|
+
var snap StateSnapshot
|
|
75
|
+
if err := json.Unmarshal(val, &snap); err != nil {
|
|
76
|
+
return StateSnapshot{}, false, err
|
|
77
|
+
}
|
|
78
|
+
return snap, true, nil
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
func (s *RedisStore) AppendHistory(ctx context.Context, channel string, snapshot StateSnapshot, maxLen int, ttlSec int) error {
|
|
82
|
+
raw, err := json.Marshal(snapshot)
|
|
83
|
+
if err != nil {
|
|
84
|
+
return err
|
|
85
|
+
}
|
|
86
|
+
key := historyKey(channel)
|
|
87
|
+
pipe := s.client.Pipeline()
|
|
88
|
+
pipe.RPush(ctx, key, raw)
|
|
89
|
+
if maxLen > 0 {
|
|
90
|
+
pipe.LTrim(ctx, key, int64(-maxLen), int64(-1))
|
|
91
|
+
}
|
|
92
|
+
if ttlSec > 0 {
|
|
93
|
+
pipe.Expire(ctx, key, time.Duration(ttlSec)*time.Second)
|
|
94
|
+
}
|
|
95
|
+
_, err = pipe.Exec(ctx)
|
|
96
|
+
return err
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
func (s *RedisStore) LoadHistory(ctx context.Context, channel string, fromVersion int64) ([]StateSnapshot, error) {
|
|
100
|
+
key := historyKey(channel)
|
|
101
|
+
items, err := s.client.LRange(ctx, key, 0, -1).Result()
|
|
102
|
+
if err == redis.Nil {
|
|
103
|
+
return nil, nil
|
|
104
|
+
}
|
|
105
|
+
if err != nil {
|
|
106
|
+
return nil, err
|
|
107
|
+
}
|
|
108
|
+
var out []StateSnapshot
|
|
109
|
+
for _, item := range items {
|
|
110
|
+
var snap StateSnapshot
|
|
111
|
+
if err := json.Unmarshal([]byte(item), &snap); err == nil {
|
|
112
|
+
if snap.VersionNo > fromVersion {
|
|
113
|
+
out = append(out, snap)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return out, nil
|
|
118
|
+
}
|
|
119
119
|
`;
|
package/dist/go/typesGo.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.typesGo = void 0;
|
|
4
|
-
exports.typesGo = `package types
|
|
5
|
-
|
|
6
|
-
import "time"
|
|
7
|
-
|
|
8
|
-
// Example shared model; extend with your domain structs.
|
|
9
|
-
type User struct {
|
|
10
|
-
ID int \`json:"id"\`
|
|
11
|
-
Username string \`json:"username"\`
|
|
12
|
-
Role string \`json:"role"\`
|
|
13
|
-
UpdatedAt time.Time \`json:"updated_at"\`
|
|
14
|
-
}
|
|
4
|
+
exports.typesGo = `package types
|
|
5
|
+
|
|
6
|
+
import "time"
|
|
7
|
+
|
|
8
|
+
// Example shared model; extend with your domain structs.
|
|
9
|
+
type User struct {
|
|
10
|
+
ID int \`json:"id"\`
|
|
11
|
+
Username string \`json:"username"\`
|
|
12
|
+
Role string \`json:"role"\`
|
|
13
|
+
UpdatedAt time.Time \`json:"updated_at"\`
|
|
14
|
+
}
|
|
15
15
|
`;
|