@robsun/create-keystone-app 0.2.15 → 0.4.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.
Files changed (96) hide show
  1. package/README.md +46 -44
  2. package/dist/create-keystone-app.js +347 -10
  3. package/dist/create-module.js +1217 -1187
  4. package/package.json +1 -1
  5. package/template/.claude/skills/keystone-implement/SKILL.md +113 -0
  6. package/template/.claude/skills/keystone-implement/references/CHECKLIST.md +91 -0
  7. package/template/.claude/skills/keystone-implement/references/PATTERNS.md +1088 -0
  8. package/template/.claude/skills/keystone-implement/references/SCHEMA.md +135 -0
  9. package/template/.claude/skills/keystone-implement/references/TESTING.md +231 -0
  10. package/template/.claude/skills/keystone-requirements/SKILL.md +296 -0
  11. package/template/.claude/skills/keystone-requirements/references/CONFIRM_TEMPLATE.md +170 -0
  12. package/template/.claude/skills/keystone-requirements/references/SCHEMA.md +135 -0
  13. package/template/.eslintrc.js +3 -0
  14. package/template/.github/workflows/ci.yml +30 -0
  15. package/template/.github/workflows/release.yml +32 -0
  16. package/template/.golangci.yml +11 -0
  17. package/template/README.md +82 -81
  18. package/template/apps/server/README.md +8 -0
  19. package/template/apps/server/cmd/server/main.go +27 -185
  20. package/template/apps/server/config.example.yaml +31 -1
  21. package/template/apps/server/config.yaml +31 -1
  22. package/template/apps/server/go.mod +61 -19
  23. package/template/apps/server/go.sum +185 -32
  24. package/template/apps/server/internal/frontend/embed.go +3 -8
  25. package/template/apps/server/internal/modules/example/README.md +18 -0
  26. package/template/apps/server/internal/modules/example/api/handler/handler_test.go +9 -0
  27. package/template/apps/server/internal/modules/example/api/handler/item_handler.go +468 -165
  28. package/template/apps/server/internal/modules/example/bootstrap/seeds/item.go +217 -8
  29. package/template/apps/server/internal/modules/example/domain/models/item.go +40 -7
  30. package/template/apps/server/internal/modules/example/domain/service/approval_callback.go +68 -0
  31. package/template/apps/server/internal/modules/example/domain/service/approval_schema.go +41 -0
  32. package/template/apps/server/internal/modules/example/domain/service/errors.go +20 -22
  33. package/template/apps/server/internal/modules/example/domain/service/item_service.go +267 -7
  34. package/template/apps/server/internal/modules/example/domain/service/item_service_test.go +281 -0
  35. package/template/apps/server/internal/modules/example/i18n/keys.go +32 -20
  36. package/template/apps/server/internal/modules/example/i18n/locales/en-US.json +30 -18
  37. package/template/apps/server/internal/modules/example/i18n/locales/zh-CN.json +30 -18
  38. package/template/apps/server/internal/modules/example/infra/exporter/item_exporter.go +119 -0
  39. package/template/apps/server/internal/modules/example/infra/importer/item_importer.go +77 -0
  40. package/template/apps/server/internal/modules/example/infra/repository/item_repository.go +99 -49
  41. package/template/apps/server/internal/modules/example/module.go +171 -97
  42. package/template/apps/server/internal/modules/example/tests/integration_test.go +7 -0
  43. package/template/apps/server/internal/modules/manifest.go +7 -7
  44. package/template/apps/web/README.md +4 -2
  45. package/template/apps/web/package.json +1 -1
  46. package/template/apps/web/src/app.config.ts +8 -6
  47. package/template/apps/web/src/index.css +7 -3
  48. package/template/apps/web/src/main.tsx +2 -5
  49. package/template/apps/web/src/modules/example/help/en-US/faq.md +27 -0
  50. package/template/apps/web/src/modules/example/help/en-US/items.md +30 -0
  51. package/template/apps/web/src/modules/example/help/en-US/overview.md +31 -0
  52. package/template/apps/web/src/modules/example/help/zh-CN/faq.md +27 -0
  53. package/template/apps/web/src/modules/example/help/zh-CN/items.md +31 -0
  54. package/template/apps/web/src/modules/example/help/zh-CN/overview.md +32 -0
  55. package/template/apps/web/src/modules/example/locales/en-US/example.json +99 -32
  56. package/template/apps/web/src/modules/example/locales/zh-CN/example.json +85 -18
  57. package/template/apps/web/src/modules/example/pages/ExampleItemsPage.tsx +840 -237
  58. package/template/apps/web/src/modules/example/services/exampleItems.ts +79 -8
  59. package/template/apps/web/src/modules/example/types.ts +14 -1
  60. package/template/apps/web/src/modules/index.ts +1 -0
  61. package/template/apps/web/vite.config.ts +9 -3
  62. package/template/docs/CONVENTIONS.md +17 -17
  63. package/template/package.json +4 -5
  64. package/template/pnpm-lock.yaml +76 -5
  65. package/template/scripts/build.bat +15 -3
  66. package/template/scripts/build.sh +9 -3
  67. package/template/scripts/check-help.js +249 -0
  68. package/template/scripts/compress-assets.js +89 -0
  69. package/template/scripts/test.bat +23 -0
  70. package/template/scripts/test.sh +16 -0
  71. package/template/.claude/skills/keystone-dev/SKILL.md +0 -90
  72. package/template/.claude/skills/keystone-dev/references/ADVANCED_PATTERNS.md +0 -716
  73. package/template/.claude/skills/keystone-dev/references/APPROVAL.md +0 -121
  74. package/template/.claude/skills/keystone-dev/references/CAPABILITIES.md +0 -261
  75. package/template/.claude/skills/keystone-dev/references/CHECKLIST.md +0 -285
  76. package/template/.claude/skills/keystone-dev/references/GOTCHAS.md +0 -390
  77. package/template/.claude/skills/keystone-dev/references/PATTERNS.md +0 -605
  78. package/template/.claude/skills/keystone-dev/references/TEMPLATES.md +0 -2710
  79. package/template/.claude/skills/keystone-dev/references/TESTING.md +0 -44
  80. package/template/.codex/skills/keystone-dev/SKILL.md +0 -90
  81. package/template/.codex/skills/keystone-dev/references/ADVANCED_PATTERNS.md +0 -716
  82. package/template/.codex/skills/keystone-dev/references/APPROVAL.md +0 -121
  83. package/template/.codex/skills/keystone-dev/references/CAPABILITIES.md +0 -261
  84. package/template/.codex/skills/keystone-dev/references/CHECKLIST.md +0 -285
  85. package/template/.codex/skills/keystone-dev/references/GOTCHAS.md +0 -390
  86. package/template/.codex/skills/keystone-dev/references/PATTERNS.md +0 -605
  87. package/template/.codex/skills/keystone-dev/references/TEMPLATES.md +0 -2710
  88. package/template/.codex/skills/keystone-dev/references/TESTING.md +0 -44
  89. package/template/apps/server/internal/app/routes/module_routes.go +0 -16
  90. package/template/apps/server/internal/app/routes/routes.go +0 -226
  91. package/template/apps/server/internal/app/startup/startup.go +0 -74
  92. package/template/apps/server/internal/frontend/handler.go +0 -122
  93. package/template/apps/server/internal/modules/registry.go +0 -145
  94. package/template/apps/web/src/modules/example/help/faq.md +0 -23
  95. package/template/apps/web/src/modules/example/help/items.md +0 -26
  96. package/template/apps/web/src/modules/example/help/overview.md +0 -25
@@ -1,11 +1,27 @@
1
1
  package seeds
2
2
 
3
3
  import (
4
+ "context"
5
+ "encoding/json"
6
+ "errors"
4
7
  "log"
8
+ "time"
5
9
 
6
10
  "gorm.io/gorm"
7
11
 
8
- "__APP_NAME__/apps/server/internal/modules/example/domain/models"
12
+ approvalmodels "github.com/robsuncn/keystone/domain/approval/models"
13
+ approvalRepo "github.com/robsuncn/keystone/domain/approval/repository"
14
+ approvalSvc "github.com/robsuncn/keystone/domain/approval/service"
15
+ "github.com/robsuncn/keystone/domain/service"
16
+ "github.com/robsuncn/keystone/infra/repository"
17
+
18
+ examplemodels "__APP_NAME__/apps/server/internal/modules/example/domain/models"
19
+ exampleservice "__APP_NAME__/apps/server/internal/modules/example/domain/service"
20
+ )
21
+
22
+ const (
23
+ defaultTenantID = 1
24
+ defaultUserID = 1
9
25
  )
10
26
 
11
27
  func Seed(db *gorm.DB) error {
@@ -13,8 +29,13 @@ func Seed(db *gorm.DB) error {
13
29
  return nil
14
30
  }
15
31
 
32
+ flow, err := seedApprovalFlow(db)
33
+ if err != nil {
34
+ return err
35
+ }
36
+
16
37
  var count int64
17
- if err := db.Model(&models.ExampleItem{}).Count(&count).Error; err != nil {
38
+ if err := db.Model(&examplemodels.ExampleItem{}).Count(&count).Error; err != nil {
18
39
  return err
19
40
  }
20
41
  if count > 0 {
@@ -22,12 +43,200 @@ func Seed(db *gorm.DB) error {
22
43
  }
23
44
 
24
45
  log.Println("[example] Seeding initial data...")
25
- items := []models.ExampleItem{
26
- {Title: "First example item", Description: "A seeded record to explore CRUD.", Status: models.StatusActive},
27
- {Title: "Inactive example item", Description: "Use status to drive UI state.", Status: models.StatusInactive},
46
+ items := []examplemodels.ExampleItem{
47
+ {
48
+ Number: "EX-20240101-0001",
49
+ Title: "Launch Plan",
50
+ Description: "Sample record to demonstrate approval and import/export flows.",
51
+ Category: examplemodels.CategoryOperations,
52
+ Amount: 1200,
53
+ Status: examplemodels.StatusDraft,
54
+ },
55
+ {
56
+ Number: "EX-20240101-0002",
57
+ Title: "Budget Request",
58
+ Description: "Draft item with finance category.",
59
+ Category: examplemodels.CategoryFinance,
60
+ Amount: 5600,
61
+ Status: examplemodels.StatusDraft,
62
+ },
63
+ {
64
+ Number: "EX-20240101-0003",
65
+ Title: "Growth Campaign",
66
+ Description: "Draft item for marketing.",
67
+ Category: examplemodels.CategoryGrowth,
68
+ Amount: 3200,
69
+ Status: examplemodels.StatusDraft,
70
+ },
71
+ {
72
+ Number: "EX-20240101-0004",
73
+ Title: "Ops Checklist",
74
+ Description: "Draft item for operations runbook.",
75
+ Category: examplemodels.CategoryOperations,
76
+ Amount: 0,
77
+ Status: examplemodels.StatusDraft,
78
+ },
79
+ }
80
+ var userID uint = defaultUserID
81
+ for i := range items {
82
+ items[i].TenantID = defaultTenantID
83
+ items[i].CreatedBy = &userID
84
+ items[i].UpdatedBy = &userID
85
+ }
86
+ if err := db.Create(&items).Error; err != nil {
87
+ return err
88
+ }
89
+
90
+ if flow != nil && len(items) > 0 {
91
+ if err := seedPendingInstance(db, flow, &items[0]); err != nil {
92
+ log.Printf("[example] seed approval instance failed: %v", err)
93
+ }
94
+ }
95
+ return nil
96
+ }
97
+
98
+ func seedApprovalFlow(db *gorm.DB) (*approvalmodels.ApprovalFlow, error) {
99
+ ctx := context.Background()
100
+ flowRepo := approvalRepo.NewFlowRepository(db)
101
+ nodeRepo := approvalRepo.NewNodeRepository(db)
102
+
103
+ existing, err := flowRepo.FindByCode(ctx, defaultTenantID, "EXAMPLE_ITEM")
104
+ if err == nil && existing != nil {
105
+ return existing, nil
28
106
  }
29
- for i := range items {
30
- items[i].TenantID = 1
107
+ if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
108
+ return nil, err
109
+ }
110
+
111
+ flow := &approvalmodels.ApprovalFlow{
112
+ Code: "EXAMPLE_ITEM",
113
+ Name: "Example Item Approval",
114
+ Description: "Default approval flow for example items.",
115
+ BusinessType: approvalmodels.BusinessType(exampleservice.ApprovalBusinessType),
116
+ Priority: 0,
117
+ Enabled: true,
118
+ }
119
+ flow.TenantID = defaultTenantID
120
+ _ = flow.Publish(defaultUserID)
121
+
122
+ if err := flowRepo.Create(ctx, flow); err != nil {
123
+ return nil, err
31
124
  }
32
- return db.Create(&items).Error
125
+
126
+ conditions := approvalmodels.ConditionConfig{
127
+ Branches: []approvalmodels.ConditionBranch{
128
+ {
129
+ Name: "High Amount",
130
+ Expr: approvalmodels.SingleCondition{
131
+ Field: "amount",
132
+ Op: string(approvalmodels.OpGte),
133
+ Value: 3000,
134
+ },
135
+ Goto: "approve",
136
+ },
137
+ {
138
+ Name: "Finance Category",
139
+ Expr: approvalmodels.SingleCondition{
140
+ Field: "category",
141
+ Op: string(approvalmodels.OpEq),
142
+ Value: string(examplemodels.CategoryFinance),
143
+ },
144
+ Goto: "approve",
145
+ },
146
+ },
147
+ DefaultGoto: "end",
148
+ }
149
+ conditionPayload, err := json.Marshal(conditions)
150
+ if err != nil {
151
+ return nil, err
152
+ }
153
+
154
+ nodes := []approvalmodels.ApprovalFlowNode{
155
+ {
156
+ FlowID: flow.ID,
157
+ NodeID: "start",
158
+ NodeType: approvalmodels.NodeTypeStart,
159
+ Name: "Start",
160
+ NextNodeID: "condition",
161
+ Enabled: true,
162
+ },
163
+ {
164
+ FlowID: flow.ID,
165
+ NodeID: "condition",
166
+ NodeType: approvalmodels.NodeTypeCondition,
167
+ Name: "Condition Gate",
168
+ Conditions: conditionPayload,
169
+ Enabled: true,
170
+ },
171
+ {
172
+ FlowID: flow.ID,
173
+ NodeID: "approve",
174
+ NodeType: approvalmodels.NodeTypeApproval,
175
+ Name: "Manager Approval",
176
+ ApproverType: approvalmodels.ApproverTypeRole,
177
+ ApproverRole: "admin",
178
+ ActionType: approvalmodels.ActionTypeApprove,
179
+ RejectRequireReason: true,
180
+ OnApprove: "end",
181
+ OnReject: "end",
182
+ Enabled: true,
183
+ },
184
+ {
185
+ FlowID: flow.ID,
186
+ NodeID: "end",
187
+ NodeType: approvalmodels.NodeTypeEnd,
188
+ Name: "End",
189
+ Enabled: true,
190
+ },
191
+ }
192
+ for i := range nodes {
193
+ nodes[i].TenantID = defaultTenantID
194
+ if err := nodeRepo.Create(ctx, &nodes[i]); err != nil {
195
+ return nil, err
196
+ }
197
+ }
198
+ return flow, nil
199
+ }
200
+
201
+ func seedPendingInstance(db *gorm.DB, flow *approvalmodels.ApprovalFlow, item *examplemodels.ExampleItem) error {
202
+ if db == nil || flow == nil || item == nil {
203
+ return nil
204
+ }
205
+ userRepo := repository.NewUserRepository(db)
206
+ permRepo := repository.NewPermissionRepository(db)
207
+ permSvc := service.NewPermissionService(permRepo, userRepo)
208
+
209
+ flowRepo := approvalRepo.NewFlowRepository(db)
210
+ nodeRepo := approvalRepo.NewNodeRepository(db)
211
+ instanceRepo := approvalRepo.NewInstanceRepository(db)
212
+ recordRepo := approvalRepo.NewRecordRepository(db)
213
+ approvalService := approvalSvc.NewService(db, instanceRepo, flowRepo, nodeRepo, recordRepo, userRepo, permSvc, approvalSvc.DefaultCallbackRegistry)
214
+
215
+ contextMap := map[string]interface{}{
216
+ "number": item.Number,
217
+ "title": item.Title,
218
+ "amount": item.Amount,
219
+ "category": item.Category,
220
+ }
221
+ rawContext, _ := json.Marshal(contextMap)
222
+
223
+ instance, err := approvalService.CreateInstance(context.Background(), &approvalSvc.CreateInstanceRequest{
224
+ TenantID: item.TenantID,
225
+ BusinessType: approvalmodels.BusinessType(exampleservice.ApprovalBusinessType),
226
+ BusinessID: item.ID,
227
+ BusinessNumber: item.Number,
228
+ FlowID: flow.ID,
229
+ FlowCode: flow.Code,
230
+ Context: rawContext,
231
+ SubmitterID: defaultUserID,
232
+ })
233
+ if err != nil {
234
+ return err
235
+ }
236
+
237
+ item.Status = examplemodels.StatusPending
238
+ item.ApprovalInstanceID = &instance.ID
239
+ item.ApprovalStatus = instance.Status
240
+ item.UpdatedAt = time.Now().UTC()
241
+ return db.Save(item).Error
33
242
  }
@@ -1,17 +1,43 @@
1
1
  package models
2
2
 
3
- import "github.com/robsuncn/keystone/domain/models"
3
+ import (
4
+ "gorm.io/datatypes"
5
+
6
+ approval "github.com/robsuncn/keystone/domain/approval/models"
7
+ "github.com/robsuncn/keystone/domain/models"
8
+ )
4
9
 
5
10
  type ItemStatus string
6
11
 
7
12
  const (
8
- StatusActive ItemStatus = "active"
9
- StatusInactive ItemStatus = "inactive"
13
+ StatusDraft ItemStatus = "draft"
14
+ StatusPending ItemStatus = "pending"
15
+ StatusApproved ItemStatus = "approved"
16
+ StatusRejected ItemStatus = "rejected"
17
+ StatusCancelled ItemStatus = "cancelled"
10
18
  )
11
19
 
12
20
  func (s ItemStatus) IsValid() bool {
13
21
  switch s {
14
- case StatusActive, StatusInactive:
22
+ case StatusDraft, StatusPending, StatusApproved, StatusRejected, StatusCancelled:
23
+ return true
24
+ default:
25
+ return false
26
+ }
27
+ }
28
+
29
+ type ItemCategory string
30
+
31
+ const (
32
+ CategoryGeneral ItemCategory = "general"
33
+ CategoryOperations ItemCategory = "operations"
34
+ CategoryFinance ItemCategory = "finance"
35
+ CategoryGrowth ItemCategory = "growth"
36
+ )
37
+
38
+ func (c ItemCategory) IsValid() bool {
39
+ switch c {
40
+ case CategoryGeneral, CategoryOperations, CategoryFinance, CategoryGrowth:
15
41
  return true
16
42
  default:
17
43
  return false
@@ -20,9 +46,16 @@ func (s ItemStatus) IsValid() bool {
20
46
 
21
47
  type ExampleItem struct {
22
48
  models.BaseModel
23
- Title string `gorm:"size:200;not null" json:"title"`
24
- Description string `gorm:"size:1000" json:"description"`
25
- Status ItemStatus `gorm:"size:20;not null;default:'active'" json:"status"`
49
+ Number string `gorm:"size:50;not null;uniqueIndex" json:"number"`
50
+ Title string `gorm:"size:200;not null" json:"title"`
51
+ Description string `gorm:"size:1000" json:"description"`
52
+ Category ItemCategory `gorm:"size:30;not null;default:'general'" json:"category"`
53
+ Amount float64 `gorm:"type:decimal(18,2);not null;default:0" json:"amount"`
54
+ Status ItemStatus `gorm:"size:20;not null;default:'draft'" json:"status"`
55
+ ApprovalInstanceID *uint `gorm:"index" json:"approval_instance_id,omitempty"`
56
+ ApprovalStatus approval.InstanceStatus `gorm:"size:20" json:"approval_status,omitempty"`
57
+ RejectReason string `gorm:"size:500" json:"reject_reason,omitempty"`
58
+ Attachment datatypes.JSON `gorm:"type:json" json:"attachment,omitempty"`
26
59
  }
27
60
 
28
61
  func (ExampleItem) TableName() string {
@@ -0,0 +1,68 @@
1
+ package service
2
+
3
+ import (
4
+ "context"
5
+ "fmt"
6
+
7
+ approvalmodels "github.com/robsuncn/keystone/domain/approval/models"
8
+ coremodels "github.com/robsuncn/keystone/domain/models"
9
+
10
+ "__APP_NAME__/apps/server/internal/modules/example/domain/models"
11
+ )
12
+
13
+ type ApprovalCallback struct {
14
+ repo ItemRepository
15
+ notifier NotificationService
16
+ }
17
+
18
+ func NewApprovalCallback(repo ItemRepository, notifier NotificationService) *ApprovalCallback {
19
+ return &ApprovalCallback{repo: repo, notifier: notifier}
20
+ }
21
+
22
+ func (c *ApprovalCallback) OnApproved(ctx context.Context, tenantID, businessID, approverID uint) error {
23
+ item, err := c.repo.FindByID(tenantID, businessID)
24
+ if err != nil {
25
+ return err
26
+ }
27
+ item.Status = models.StatusApproved
28
+ item.ApprovalStatus = approvalmodels.InstanceStatusApproved
29
+ item.RejectReason = ""
30
+ if err := c.repo.Update(ctx, item); err != nil {
31
+ return err
32
+ }
33
+ c.notify(ctx, tenantID, item, "approved")
34
+ return nil
35
+ }
36
+
37
+ func (c *ApprovalCallback) OnRejected(ctx context.Context, tenantID, businessID, approverID uint, reason string) error {
38
+ item, err := c.repo.FindByID(tenantID, businessID)
39
+ if err != nil {
40
+ return err
41
+ }
42
+ item.Status = models.StatusRejected
43
+ item.ApprovalStatus = approvalmodels.InstanceStatusRejected
44
+ item.RejectReason = reason
45
+ if err := c.repo.Update(ctx, item); err != nil {
46
+ return err
47
+ }
48
+ c.notify(ctx, tenantID, item, "rejected")
49
+ return nil
50
+ }
51
+
52
+ func (c *ApprovalCallback) notify(ctx context.Context, tenantID uint, item *models.ExampleItem, action string) {
53
+ if c == nil || c.notifier == nil || item == nil {
54
+ return
55
+ }
56
+ if item.CreatedBy == nil || *item.CreatedBy == 0 {
57
+ return
58
+ }
59
+ notification := &coremodels.Notification{
60
+ BaseModel: coremodels.BaseModel{TenantID: tenantID},
61
+ UserID: *item.CreatedBy,
62
+ Title: fmt.Sprintf("Example item %s", action),
63
+ Content: fmt.Sprintf("%s (%s)", item.Title, item.Number),
64
+ Type: coremodels.NotificationTypeSuccess,
65
+ Read: false,
66
+ }
67
+ _ = c.notifier.Create(ctx, notification)
68
+ }
@@ -0,0 +1,41 @@
1
+ package service
2
+
3
+ import (
4
+ approvalmodels "github.com/robsuncn/keystone/domain/approval/models"
5
+ approvalsvc "github.com/robsuncn/keystone/domain/approval/service"
6
+
7
+ examplemodels "__APP_NAME__/apps/server/internal/modules/example/domain/models"
8
+ )
9
+
10
+ var exampleCategoryOptions = []approvalmodels.EnumOption{
11
+ {Label: "通用", Value: string(examplemodels.CategoryGeneral)},
12
+ {Label: "运营", Value: string(examplemodels.CategoryOperations)},
13
+ {Label: "财务", Value: string(examplemodels.CategoryFinance)},
14
+ {Label: "增长", Value: string(examplemodels.CategoryGrowth)},
15
+ }
16
+
17
+ func init() {
18
+ if _, exists := approvalsvc.GetSchema(string(ApprovalBusinessType)); exists {
19
+ return
20
+ }
21
+
22
+ err := approvalsvc.Register(approvalmodels.FormSchema{
23
+ Code: string(ApprovalBusinessType),
24
+ Name: "示例事项",
25
+ Description: "示例事项审批条件字段",
26
+ Fields: []approvalmodels.FieldDef{
27
+ {Name: "number", Label: "编号", Type: approvalmodels.FieldTypeString},
28
+ {Name: "title", Label: "标题", Type: approvalmodels.FieldTypeString},
29
+ {Name: "amount", Label: "金额", Type: approvalmodels.FieldTypeNumber},
30
+ {
31
+ Name: "category",
32
+ Label: "类别",
33
+ Type: approvalmodels.FieldTypeEnum,
34
+ Options: exampleCategoryOptions,
35
+ },
36
+ },
37
+ })
38
+ if err != nil {
39
+ panic(err)
40
+ }
41
+ }
@@ -1,22 +1,20 @@
1
- package service
2
-
3
- import "errors"
4
-
5
- var (
6
- ErrItemNotFound = errors.New("item not found")
7
- ErrTitleRequired = errors.New("title is required")
8
- ErrStatusInvalid = errors.New("status is invalid")
9
- )
10
-
11
- // I18n version (uncomment when using keystone with i18n support):
12
- //
13
- // import (
14
- // "github.com/robsuncn/keystone/infra/i18n"
15
- // examplei18n "your-app/apps/server/internal/modules/example/i18n"
16
- // )
17
- //
18
- // var (
19
- // ErrItemNotFound = &i18n.I18nError{Key: examplei18n.MsgItemNotFound}
20
- // ErrTitleRequired = &i18n.I18nError{Key: examplei18n.MsgTitleRequired}
21
- // ErrStatusInvalid = &i18n.I18nError{Key: examplei18n.MsgStatusInvalid}
22
- // )
1
+ package service
2
+
3
+ import (
4
+ "github.com/robsuncn/keystone/infra/i18n"
5
+
6
+ examplei18n "__APP_NAME__/apps/server/internal/modules/example/i18n"
7
+ )
8
+
9
+ var (
10
+ ErrItemNotFound = &i18n.I18nError{Key: examplei18n.MsgItemNotFound}
11
+ ErrTitleRequired = &i18n.I18nError{Key: examplei18n.MsgTitleRequired}
12
+ ErrStatusInvalid = &i18n.I18nError{Key: examplei18n.MsgStatusInvalid}
13
+ ErrCategoryInvalid = &i18n.I18nError{Key: examplei18n.MsgCategoryInvalid}
14
+ ErrAmountInvalid = &i18n.I18nError{Key: examplei18n.MsgAmountInvalid}
15
+ ErrItemLocked = &i18n.I18nError{Key: examplei18n.MsgItemLocked}
16
+ ErrSubmitterRequired = &i18n.I18nError{Key: examplei18n.MsgSubmitterRequired}
17
+ ErrApprovalNotReady = &i18n.I18nError{Key: examplei18n.MsgApprovalNotReady}
18
+ ErrApprovalNotPending = &i18n.I18nError{Key: examplei18n.MsgApprovalNotPending}
19
+ ErrApprovalInstanceNil = &i18n.I18nError{Key: examplei18n.MsgApprovalInstanceMissing}
20
+ )