@goplusvn/core 0.1.1 → 0.1.3

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 (223) hide show
  1. package/package.json +31 -175
  2. package/dist/audit/index.d.mts +0 -115
  3. package/dist/audit/index.d.ts +0 -115
  4. package/dist/audit/index.js +0 -204
  5. package/dist/audit/index.js.map +0 -1
  6. package/dist/audit/index.mjs +0 -200
  7. package/dist/audit/index.mjs.map +0 -1
  8. package/dist/auth/index.d.mts +0 -86
  9. package/dist/auth/index.d.ts +0 -86
  10. package/dist/auth/index.js +0 -210
  11. package/dist/auth/index.js.map +0 -1
  12. package/dist/auth/index.mjs +0 -198
  13. package/dist/auth/index.mjs.map +0 -1
  14. package/dist/button-1dWvP9Ib.d.mts +0 -30
  15. package/dist/button-1dWvP9Ib.d.ts +0 -30
  16. package/dist/calendar-2QzdEo1z.d.mts +0 -20
  17. package/dist/calendar-2QzdEo1z.d.ts +0 -20
  18. package/dist/code-generation/index.d.mts +0 -30
  19. package/dist/code-generation/index.d.ts +0 -30
  20. package/dist/code-generation/index.js +0 -31
  21. package/dist/code-generation/index.js.map +0 -1
  22. package/dist/code-generation/index.mjs +0 -28
  23. package/dist/code-generation/index.mjs.map +0 -1
  24. package/dist/configs/index.d.mts +0 -175
  25. package/dist/configs/index.d.ts +0 -175
  26. package/dist/configs/index.js +0 -254
  27. package/dist/configs/index.js.map +0 -1
  28. package/dist/configs/index.mjs +0 -233
  29. package/dist/configs/index.mjs.map +0 -1
  30. package/dist/crud/index.d.mts +0 -646
  31. package/dist/crud/index.d.ts +0 -646
  32. package/dist/crud/index.js +0 -11772
  33. package/dist/crud/index.js.map +0 -1
  34. package/dist/crud/index.mjs +0 -11665
  35. package/dist/crud/index.mjs.map +0 -1
  36. package/dist/crud/server.d.mts +0 -20
  37. package/dist/crud/server.d.ts +0 -20
  38. package/dist/crud/server.js +0 -123
  39. package/dist/crud/server.js.map +0 -1
  40. package/dist/crud/server.mjs +0 -120
  41. package/dist/crud/server.mjs.map +0 -1
  42. package/dist/data-table-skeleton-12NA8Mjx.d.mts +0 -39
  43. package/dist/data-table-skeleton-12NA8Mjx.d.ts +0 -39
  44. package/dist/dialog-bKfjZMTd.d.mts +0 -22
  45. package/dist/dialog-bKfjZMTd.d.ts +0 -22
  46. package/dist/dynamic-icon-DrGIiu2N.d.mts +0 -10
  47. package/dist/dynamic-icon-DrGIiu2N.d.ts +0 -10
  48. package/dist/home/index.d.mts +0 -269
  49. package/dist/home/index.d.ts +0 -269
  50. package/dist/home/index.js +0 -1678
  51. package/dist/home/index.js.map +0 -1
  52. package/dist/home/index.mjs +0 -1635
  53. package/dist/home/index.mjs.map +0 -1
  54. package/dist/hooks/index.d.mts +0 -7
  55. package/dist/hooks/index.d.ts +0 -7
  56. package/dist/hooks/index.js +0 -8316
  57. package/dist/hooks/index.js.map +0 -1
  58. package/dist/hooks/index.mjs +0 -8255
  59. package/dist/hooks/index.mjs.map +0 -1
  60. package/dist/index-50hpiPrV.d.ts +0 -116
  61. package/dist/index-B9zQVEVi.d.mts +0 -116
  62. package/dist/index.d.mts +0 -5
  63. package/dist/index.d.ts +0 -5
  64. package/dist/index.js +0 -123
  65. package/dist/index.js.map +0 -1
  66. package/dist/index.mjs +0 -118
  67. package/dist/index.mjs.map +0 -1
  68. package/dist/infrastructure/index.d.mts +0 -423
  69. package/dist/infrastructure/index.d.ts +0 -423
  70. package/dist/infrastructure/index.js +0 -633
  71. package/dist/infrastructure/index.js.map +0 -1
  72. package/dist/infrastructure/index.mjs +0 -619
  73. package/dist/infrastructure/index.mjs.map +0 -1
  74. package/dist/label-DWTEkNPo.d.ts +0 -226
  75. package/dist/label-LPpdcoBx.d.mts +0 -226
  76. package/dist/layout/index.d.mts +0 -48
  77. package/dist/layout/index.d.ts +0 -48
  78. package/dist/layout/index.js +0 -117
  79. package/dist/layout/index.js.map +0 -1
  80. package/dist/layout/index.mjs +0 -90
  81. package/dist/layout/index.mjs.map +0 -1
  82. package/dist/navigation/index.d.mts +0 -16
  83. package/dist/navigation/index.d.ts +0 -16
  84. package/dist/navigation/index.js +0 -53
  85. package/dist/navigation/index.js.map +0 -1
  86. package/dist/navigation/index.mjs +0 -50
  87. package/dist/navigation/index.mjs.map +0 -1
  88. package/dist/notification/index.d.mts +0 -105
  89. package/dist/notification/index.d.ts +0 -105
  90. package/dist/notification/index.js +0 -278
  91. package/dist/notification/index.js.map +0 -1
  92. package/dist/notification/index.mjs +0 -274
  93. package/dist/notification/index.mjs.map +0 -1
  94. package/dist/organization/index.d.mts +0 -99
  95. package/dist/organization/index.d.ts +0 -99
  96. package/dist/organization/index.js +0 -360
  97. package/dist/organization/index.js.map +0 -1
  98. package/dist/organization/index.mjs +0 -352
  99. package/dist/organization/index.mjs.map +0 -1
  100. package/dist/plugin/index.d.mts +0 -83
  101. package/dist/plugin/index.d.ts +0 -83
  102. package/dist/plugin/index.js +0 -86
  103. package/dist/plugin/index.js.map +0 -1
  104. package/dist/plugin/index.mjs +0 -84
  105. package/dist/plugin/index.mjs.map +0 -1
  106. package/dist/providers/index.d.mts +0 -25
  107. package/dist/providers/index.d.ts +0 -25
  108. package/dist/providers/index.js +0 -84
  109. package/dist/providers/index.js.map +0 -1
  110. package/dist/providers/index.mjs +0 -77
  111. package/dist/providers/index.mjs.map +0 -1
  112. package/dist/rbac/index.d.mts +0 -226
  113. package/dist/rbac/index.d.ts +0 -226
  114. package/dist/rbac/index.js +0 -4784
  115. package/dist/rbac/index.js.map +0 -1
  116. package/dist/rbac/index.mjs +0 -4722
  117. package/dist/rbac/index.mjs.map +0 -1
  118. package/dist/rbac/permissions.d.mts +0 -26
  119. package/dist/rbac/permissions.d.ts +0 -26
  120. package/dist/rbac/permissions.js +0 -94
  121. package/dist/rbac/permissions.js.map +0 -1
  122. package/dist/rbac/permissions.mjs +0 -90
  123. package/dist/rbac/permissions.mjs.map +0 -1
  124. package/dist/rbac/server.d.mts +0 -1
  125. package/dist/rbac/server.d.ts +0 -1
  126. package/dist/rbac/server.js +0 -128
  127. package/dist/rbac/server.js.map +0 -1
  128. package/dist/rbac/server.mjs +0 -124
  129. package/dist/rbac/server.mjs.map +0 -1
  130. package/dist/schemas/index.d.mts +0 -1257
  131. package/dist/schemas/index.d.ts +0 -1257
  132. package/dist/schemas/index.js +0 -572
  133. package/dist/schemas/index.js.map +0 -1
  134. package/dist/schemas/index.mjs +0 -523
  135. package/dist/schemas/index.mjs.map +0 -1
  136. package/dist/server-QuYCTa89.d.mts +0 -83
  137. package/dist/server-QuYCTa89.d.ts +0 -83
  138. package/dist/sonner-C74GlRDQ.d.mts +0 -71
  139. package/dist/sonner-C74GlRDQ.d.ts +0 -71
  140. package/dist/status-BOXZgIqX.d.mts +0 -12
  141. package/dist/status-BOXZgIqX.d.ts +0 -12
  142. package/dist/system/index.d.mts +0 -77
  143. package/dist/system/index.d.ts +0 -77
  144. package/dist/system/index.js +0 -102
  145. package/dist/system/index.js.map +0 -1
  146. package/dist/system/index.mjs +0 -100
  147. package/dist/system/index.mjs.map +0 -1
  148. package/dist/tabs-C6FfBwPY.d.mts +0 -18
  149. package/dist/tabs-C6FfBwPY.d.ts +0 -18
  150. package/dist/tenant-provider-B8eC_Wpb.d.mts +0 -27
  151. package/dist/tenant-provider-B8eC_Wpb.d.ts +0 -27
  152. package/dist/types/index.d.mts +0 -469
  153. package/dist/types/index.d.ts +0 -469
  154. package/dist/types/index.js +0 -25
  155. package/dist/types/index.js.map +0 -1
  156. package/dist/types/index.mjs +0 -21
  157. package/dist/types/index.mjs.map +0 -1
  158. package/dist/ui/auth.d.mts +0 -39
  159. package/dist/ui/auth.d.ts +0 -39
  160. package/dist/ui/auth.js +0 -4941
  161. package/dist/ui/auth.js.map +0 -1
  162. package/dist/ui/auth.mjs +0 -4896
  163. package/dist/ui/auth.mjs.map +0 -1
  164. package/dist/ui/crud.d.mts +0 -2
  165. package/dist/ui/crud.d.ts +0 -2
  166. package/dist/ui/crud.js +0 -4
  167. package/dist/ui/crud.js.map +0 -1
  168. package/dist/ui/crud.mjs +0 -3
  169. package/dist/ui/crud.mjs.map +0 -1
  170. package/dist/ui/data-display.d.mts +0 -596
  171. package/dist/ui/data-display.d.ts +0 -596
  172. package/dist/ui/data-display.js +0 -5307
  173. package/dist/ui/data-display.js.map +0 -1
  174. package/dist/ui/data-display.mjs +0 -5212
  175. package/dist/ui/data-display.mjs.map +0 -1
  176. package/dist/ui/feedback.d.mts +0 -55
  177. package/dist/ui/feedback.d.ts +0 -55
  178. package/dist/ui/feedback.js +0 -2608
  179. package/dist/ui/feedback.js.map +0 -1
  180. package/dist/ui/feedback.mjs +0 -2526
  181. package/dist/ui/feedback.mjs.map +0 -1
  182. package/dist/ui/forms.d.mts +0 -309
  183. package/dist/ui/forms.d.ts +0 -309
  184. package/dist/ui/forms.js +0 -4656
  185. package/dist/ui/forms.js.map +0 -1
  186. package/dist/ui/forms.mjs +0 -4571
  187. package/dist/ui/forms.mjs.map +0 -1
  188. package/dist/ui/index.d.mts +0 -331
  189. package/dist/ui/index.d.ts +0 -331
  190. package/dist/ui/index.js +0 -16953
  191. package/dist/ui/index.js.map +0 -1
  192. package/dist/ui/index.mjs +0 -16598
  193. package/dist/ui/index.mjs.map +0 -1
  194. package/dist/ui/primitives/client.d.mts +0 -61
  195. package/dist/ui/primitives/client.d.ts +0 -61
  196. package/dist/ui/primitives/client.js +0 -3408
  197. package/dist/ui/primitives/client.js.map +0 -1
  198. package/dist/ui/primitives/client.mjs +0 -3256
  199. package/dist/ui/primitives/client.mjs.map +0 -1
  200. package/dist/ui/primitives.d.mts +0 -113
  201. package/dist/ui/primitives.d.ts +0 -113
  202. package/dist/ui/primitives.js +0 -3356
  203. package/dist/ui/primitives.js.map +0 -1
  204. package/dist/ui/primitives.mjs +0 -3227
  205. package/dist/ui/primitives.mjs.map +0 -1
  206. package/dist/user/index.d.mts +0 -228
  207. package/dist/user/index.d.ts +0 -228
  208. package/dist/user/index.js +0 -4306
  209. package/dist/user/index.js.map +0 -1
  210. package/dist/user/index.mjs +0 -4260
  211. package/dist/user/index.mjs.map +0 -1
  212. package/dist/utils/index.d.mts +0 -205
  213. package/dist/utils/index.d.ts +0 -205
  214. package/dist/utils/index.js +0 -574
  215. package/dist/utils/index.js.map +0 -1
  216. package/dist/utils/index.mjs +0 -514
  217. package/dist/utils/index.mjs.map +0 -1
  218. package/dist/workflow/index.d.mts +0 -40
  219. package/dist/workflow/index.d.ts +0 -40
  220. package/dist/workflow/index.js +0 -3710
  221. package/dist/workflow/index.js.map +0 -1
  222. package/dist/workflow/index.mjs +0 -3677
  223. package/dist/workflow/index.mjs.map +0 -1
@@ -1,352 +0,0 @@
1
- import { GitBranch } from 'lucide-react';
2
- import { z } from 'zod';
3
-
4
- // src/organization/branches.config.ts
5
-
6
- // src/configs/status.ts
7
- var STATUS_ACTIVE = "active";
8
- var STATUS_INACTIVE = "inactive";
9
- var STATUS_OPTIONS = [
10
- { label: "crud.common.options.active", value: STATUS_ACTIVE },
11
- { label: "crud.common.options.inactive", value: STATUS_INACTIVE }
12
- ];
13
-
14
- // src/organization/branches.config.ts
15
- var branchesConfig = {
16
- name: "branch",
17
- permissionResource: "branch",
18
- label: "Chi nh\xE1nh",
19
- pluralLabel: "Danh s\xE1ch chi nh\xE1nh",
20
- icon: GitBranch,
21
- description: "Qu\u1EA3n l\xFD danh s\xE1ch chi nh\xE1nh",
22
- apiEndpoint: "/api/branches",
23
- idField: "id",
24
- displayField: "name",
25
- fields: [
26
- {
27
- name: "id",
28
- label: "ID",
29
- type: "text",
30
- hideInForm: true,
31
- hideInTable: true
32
- },
33
- {
34
- name: "companyId",
35
- label: "C\xF4ng ty",
36
- type: "select",
37
- required: true,
38
- placeholder: "Ch\u1ECDn c\xF4ng ty",
39
- filterable: true,
40
- dataSource: {
41
- type: "api",
42
- endpoint: "/api/companies",
43
- labelField: "name",
44
- valueField: "id"
45
- }
46
- },
47
- {
48
- name: "code",
49
- label: "M\xE3 chi nh\xE1nh",
50
- type: "text",
51
- required: true,
52
- placeholder: "Nh\u1EADp m\xE3 chi nh\xE1nh",
53
- filterable: true
54
- },
55
- {
56
- name: "name",
57
- label: "T\xEAn chi nh\xE1nh",
58
- type: "text",
59
- required: true,
60
- placeholder: "Nh\u1EADp t\xEAn chi nh\xE1nh",
61
- filterable: true
62
- },
63
- {
64
- name: "address",
65
- label: "\u0110\u1ECBa ch\u1EC9",
66
- type: "textarea",
67
- required: false,
68
- placeholder: "Nh\u1EADp \u0111\u1ECBa ch\u1EC9",
69
- rows: 2
70
- },
71
- {
72
- name: "phone",
73
- label: "S\u1ED1 \u0111i\u1EC7n tho\u1EA1i",
74
- type: "text",
75
- required: false,
76
- placeholder: "Nh\u1EADp s\u1ED1 \u0111i\u1EC7n tho\u1EA1i"
77
- },
78
- {
79
- name: "email",
80
- label: "Email",
81
- type: "email",
82
- required: false,
83
- placeholder: "Nh\u1EADp email"
84
- },
85
- {
86
- name: "status",
87
- label: "Tr\u1EA1ng th\xE1i",
88
- type: "switch",
89
- required: true,
90
- defaultValue: "active",
91
- filterable: true,
92
- options: STATUS_OPTIONS
93
- },
94
- {
95
- name: "createdAt",
96
- label: "Ng\xE0y t\u1EA1o",
97
- type: "datetime",
98
- hideInForm: true,
99
- renderCell: (value) => {
100
- return new Date(value).toLocaleDateString("vi-VN");
101
- }
102
- },
103
- {
104
- name: "updatedAt",
105
- label: "Ng\xE0y c\u1EADp nh\u1EADt",
106
- type: "datetime",
107
- hideInForm: true,
108
- hideInTable: true
109
- }
110
- ],
111
- filters: [
112
- {
113
- name: "search",
114
- label: "T\xECm ki\u1EBFm",
115
- type: "text",
116
- field: "name",
117
- operator: "contains"
118
- },
119
- {
120
- name: "companyId",
121
- label: "C\xF4ng ty",
122
- type: "select",
123
- field: "companyId",
124
- operator: "eq",
125
- dataSource: {
126
- type: "api",
127
- endpoint: "/api/companies",
128
- labelField: "name",
129
- valueField: "id"
130
- }
131
- },
132
- {
133
- name: "status",
134
- label: "Tr\u1EA1ng th\xE1i",
135
- type: "checkbox",
136
- field: "status",
137
- operator: "in",
138
- options: [
139
- { label: "Ho\u1EA1t \u0111\u1ED9ng", value: "active" },
140
- { label: "Ng\u1EEBng ho\u1EA1t \u0111\u1ED9ng", value: "inactive" }
141
- ]
142
- }
143
- ],
144
- permissions: {
145
- create: true,
146
- read: true,
147
- update: true,
148
- delete: true,
149
- export: true,
150
- import: false
151
- },
152
- features: {
153
- search: true,
154
- bulkActions: true,
155
- export: true,
156
- import: false
157
- }
158
- };
159
- var branchSchema = z.object({
160
- companyId: z.string().min(1, "C\xF4ng ty l\xE0 b\u1EAFt bu\u1ED9c"),
161
- code: z.string().min(1, "M\xE3 chi nh\xE1nh l\xE0 b\u1EAFt bu\u1ED9c").max(50, "M\xE3 chi nh\xE1nh t\u1ED1i \u0111a 50 k\xFD t\u1EF1").trim(),
162
- name: z.string().min(1, "T\xEAn chi nh\xE1nh l\xE0 b\u1EAFt bu\u1ED9c").max(255, "T\xEAn chi nh\xE1nh t\u1ED1i \u0111a 255 k\xFD t\u1EF1").trim(),
163
- address: z.string().max(500, "\u0110\u1ECBa ch\u1EC9 t\u1ED1i \u0111a 500 k\xFD t\u1EF1").trim().optional().nullable(),
164
- phone: z.string().max(20, "S\u1ED1 \u0111i\u1EC7n tho\u1EA1i t\u1ED1i \u0111a 20 k\xFD t\u1EF1").trim().optional().nullable(),
165
- email: z.string().max(255, "Email t\u1ED1i \u0111a 255 k\xFD t\u1EF1").email("Email kh\xF4ng h\u1EE3p l\u1EC7").trim().optional().nullable().or(z.literal("")),
166
- status: z.enum(["active", "inactive"]).default("active")
167
- });
168
- var branchUpdateSchema = branchSchema.partial();
169
-
170
- // src/organization/branch-service.ts
171
- var BranchServiceError = class extends Error {
172
- constructor(message, status, options) {
173
- super(message);
174
- this.name = "BranchServiceError";
175
- this.status = status;
176
- this.field = options?.field;
177
- this.details = options?.details;
178
- }
179
- };
180
- var BRANCH_INCLUDE = {
181
- company: {
182
- select: { id: true, name: true }
183
- }
184
- };
185
- var ensureUserId = (userId) => {
186
- if (!userId) {
187
- throw new BranchServiceError("Unauthorized", 401);
188
- }
189
- };
190
- async function listBranches(db, params) {
191
- const page = Number(params.page || 1);
192
- const pageSize = Math.min(Number(params.pageSize || 10), 100);
193
- const skip = (page - 1) * pageSize;
194
- const search = params.search?.trim() || void 0;
195
- const companyId = params.companyId?.trim() || void 0;
196
- const status = params.status?.trim() || void 0;
197
- const where = {};
198
- if (search) {
199
- where.OR = [
200
- { name: { contains: search, mode: "insensitive" } },
201
- { code: { contains: search, mode: "insensitive" } },
202
- { email: { contains: search, mode: "insensitive" } }
203
- ];
204
- }
205
- if (companyId) {
206
- where.companyId = companyId;
207
- }
208
- if (status) {
209
- where.status = status;
210
- }
211
- const [total, data] = await Promise.all([
212
- db.branch.count({ where }),
213
- db.branch.findMany({
214
- where,
215
- orderBy: { name: "asc" },
216
- skip,
217
- take: pageSize,
218
- include: BRANCH_INCLUDE
219
- })
220
- ]);
221
- return {
222
- data,
223
- pagination: {
224
- page,
225
- pageSize,
226
- total,
227
- totalPages: Math.ceil(total / pageSize)
228
- }
229
- };
230
- }
231
- async function getBranchById(db, id) {
232
- const branch = await db.branch.findUnique({
233
- where: { id },
234
- include: BRANCH_INCLUDE
235
- });
236
- if (!branch) {
237
- throw new BranchServiceError("Chi nh\xE1nh kh\xF4ng t\u1ED3n t\u1EA1i", 404);
238
- }
239
- return branch;
240
- }
241
- async function createBranch(db, input, userId) {
242
- ensureUserId(userId);
243
- const result = branchSchema.safeParse(input);
244
- if (!result.success) {
245
- const errors = result.error.issues || [];
246
- const firstError = errors[0];
247
- throw new BranchServiceError(
248
- firstError?.message || "Validation error",
249
- 400,
250
- {
251
- field: firstError?.path?.join("."),
252
- details: errors
253
- }
254
- );
255
- }
256
- const validData = result.data;
257
- const existing = await db.branch.findUnique({
258
- where: { code: validData.code }
259
- });
260
- if (existing) {
261
- throw new BranchServiceError("M\xE3 chi nh\xE1nh \u0111\xE3 t\u1ED3n t\u1EA1i", 400, {
262
- field: "code"
263
- });
264
- }
265
- const company = await db.company.findUnique({
266
- where: { id: validData.companyId }
267
- });
268
- if (!company) {
269
- throw new BranchServiceError("C\xF4ng ty kh\xF4ng t\u1ED3n t\u1EA1i", 400, {
270
- field: "companyId"
271
- });
272
- }
273
- return db.branch.create({
274
- data: {
275
- id: crypto.randomUUID(),
276
- companyId: validData.companyId,
277
- code: validData.code,
278
- name: validData.name,
279
- address: validData.address,
280
- phone: validData.phone,
281
- email: validData.email,
282
- status: validData.status,
283
- createdBy: userId,
284
- updatedAt: /* @__PURE__ */ new Date(),
285
- updatedBy: userId
286
- },
287
- include: BRANCH_INCLUDE
288
- });
289
- }
290
- async function updateBranch(db, id, input, userId) {
291
- ensureUserId(userId);
292
- const result = branchUpdateSchema.safeParse(input);
293
- if (!result.success) {
294
- const errors = result.error.issues || [];
295
- const firstError = errors[0];
296
- throw new BranchServiceError(
297
- firstError?.message || "Validation error",
298
- 400,
299
- {
300
- field: firstError?.path?.join("."),
301
- details: errors
302
- }
303
- );
304
- }
305
- const validData = result.data;
306
- const existingBranch = await db.branch.findUnique({
307
- where: { id }
308
- });
309
- if (!existingBranch) {
310
- throw new BranchServiceError("Chi nh\xE1nh kh\xF4ng t\u1ED3n t\u1EA1i", 404);
311
- }
312
- if (validData.code && validData.code !== existingBranch.code) {
313
- const duplicate = await db.branch.findUnique({
314
- where: { code: validData.code }
315
- });
316
- if (duplicate) {
317
- throw new BranchServiceError("M\xE3 chi nh\xE1nh \u0111\xE3 t\u1ED3n t\u1EA1i", 400, {
318
- field: "code"
319
- });
320
- }
321
- }
322
- if (validData.companyId) {
323
- const company = await db.company.findUnique({
324
- where: { id: validData.companyId }
325
- });
326
- if (!company) {
327
- throw new BranchServiceError("C\xF4ng ty kh\xF4ng t\u1ED3n t\u1EA1i", 400, {
328
- field: "companyId"
329
- });
330
- }
331
- }
332
- return db.branch.update({
333
- where: { id },
334
- data: {
335
- ...validData,
336
- updatedAt: /* @__PURE__ */ new Date(),
337
- updatedBy: userId
338
- },
339
- include: BRANCH_INCLUDE
340
- });
341
- }
342
- async function deleteBranch(db, id) {
343
- const branch = await db.branch.findUnique({ where: { id } });
344
- if (!branch) {
345
- throw new BranchServiceError("Chi nh\xE1nh kh\xF4ng t\u1ED3n t\u1EA1i", 404);
346
- }
347
- return db.branch.delete({ where: { id } });
348
- }
349
-
350
- export { BranchServiceError, branchesConfig, createBranch, deleteBranch, getBranchById, listBranches, updateBranch };
351
- //# sourceMappingURL=index.mjs.map
352
- //# sourceMappingURL=index.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/configs/status.ts","../../src/organization/branches.config.ts","../../src/schemas/branch.schema.ts","../../src/organization/branch-service.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export const STATUS_ACTIVE = \"active\";\nexport const STATUS_INACTIVE = \"inactive\";\n\nexport const STATUS_VALUES = [STATUS_ACTIVE, STATUS_INACTIVE] as const;\n\nexport const STATUS_OPTIONS = [\n { label: \"crud.common.options.active\", value: STATUS_ACTIVE },\n { label: \"crud.common.options.inactive\", value: STATUS_INACTIVE },\n];\n\nexport const STATUS_COLORS: Record<\n string,\n \"success\" | \"warning\" | \"default\" | \"destructive\" | \"secondary\" | \"outline\"\n> = {\n [STATUS_ACTIVE]: \"success\",\n [STATUS_INACTIVE]: \"warning\",\n};\n\nexport function booleanToStatus(value: boolean): string {\n return value ? STATUS_ACTIVE : STATUS_INACTIVE;\n}\n\nexport function statusToBoolean(value: string): boolean {\n return value === STATUS_ACTIVE;\n}\n","import { GitBranch } from \"lucide-react\";\n\nimport type { EntityConfig } from \"../types\";\n\nimport { STATUS_OPTIONS } from \"../configs/status\";\n\nexport const branchesConfig: EntityConfig = {\n name: \"branch\",\n permissionResource: \"branch\",\n label: \"Chi nhánh\",\n pluralLabel: \"Danh sách chi nhánh\",\n icon: GitBranch,\n description: \"Quản lý danh sách chi nhánh\",\n apiEndpoint: \"/api/branches\",\n idField: \"id\",\n displayField: \"name\",\n\n fields: [\n {\n name: \"id\",\n label: \"ID\",\n type: \"text\",\n hideInForm: true,\n hideInTable: true,\n },\n {\n name: \"companyId\",\n label: \"Công ty\",\n type: \"select\",\n required: true,\n placeholder: \"Chọn công ty\",\n filterable: true,\n dataSource: {\n type: \"api\",\n endpoint: \"/api/companies\",\n labelField: \"name\",\n valueField: \"id\",\n },\n },\n {\n name: \"code\",\n label: \"Mã chi nhánh\",\n type: \"text\",\n required: true,\n placeholder: \"Nhập mã chi nhánh\",\n filterable: true,\n },\n {\n name: \"name\",\n label: \"Tên chi nhánh\",\n type: \"text\",\n required: true,\n placeholder: \"Nhập tên chi nhánh\",\n filterable: true,\n },\n {\n name: \"address\",\n label: \"Địa chỉ\",\n type: \"textarea\",\n required: false,\n placeholder: \"Nhập địa chỉ\",\n rows: 2,\n },\n {\n name: \"phone\",\n label: \"Số điện thoại\",\n type: \"text\",\n required: false,\n placeholder: \"Nhập số điện thoại\",\n },\n {\n name: \"email\",\n label: \"Email\",\n type: \"email\",\n required: false,\n placeholder: \"Nhập email\",\n },\n {\n name: \"status\",\n label: \"Trạng thái\",\n type: \"switch\",\n required: true,\n defaultValue: \"active\",\n filterable: true,\n options: STATUS_OPTIONS,\n },\n {\n name: \"createdAt\",\n label: \"Ngày tạo\",\n type: \"datetime\",\n hideInForm: true,\n renderCell: (value) => {\n return new Date(value as string).toLocaleDateString(\"vi-VN\");\n },\n },\n {\n name: \"updatedAt\",\n label: \"Ngày cập nhật\",\n type: \"datetime\",\n hideInForm: true,\n hideInTable: true,\n },\n ],\n\n filters: [\n {\n name: \"search\",\n label: \"Tìm kiếm\",\n type: \"text\",\n field: \"name\",\n operator: \"contains\",\n },\n {\n name: \"companyId\",\n label: \"Công ty\",\n type: \"select\",\n field: \"companyId\",\n operator: \"eq\",\n dataSource: {\n type: \"api\",\n endpoint: \"/api/companies\",\n labelField: \"name\",\n valueField: \"id\",\n },\n },\n {\n name: \"status\",\n label: \"Trạng thái\",\n type: \"checkbox\",\n field: \"status\",\n operator: \"in\",\n options: [\n { label: \"Hoạt động\", value: \"active\" },\n { label: \"Ngừng hoạt động\", value: \"inactive\" },\n ],\n },\n ],\n\n permissions: {\n create: true,\n read: true,\n update: true,\n delete: true,\n export: true,\n import: false,\n },\n\n features: {\n search: true,\n bulkActions: true,\n export: true,\n import: false,\n },\n};\n","import { z } from \"zod\";\n\n/**\n * Branch Validation Schema\n *\n * Validates branch form submissions on both client & server.\n */\n\nexport const branchSchema = z.object({\n companyId: z.string().min(1, \"Công ty là bắt buộc\"),\n\n code: z\n .string()\n .min(1, \"Mã chi nhánh là bắt buộc\")\n .max(50, \"Mã chi nhánh tối đa 50 ký tự\")\n .trim(),\n\n name: z\n .string()\n .min(1, \"Tên chi nhánh là bắt buộc\")\n .max(255, \"Tên chi nhánh tối đa 255 ký tự\")\n .trim(),\n\n address: z\n .string()\n .max(500, \"Địa chỉ tối đa 500 ký tự\")\n .trim()\n .optional()\n .nullable(),\n\n phone: z\n .string()\n .max(20, \"Số điện thoại tối đa 20 ký tự\")\n .trim()\n .optional()\n .nullable(),\n\n email: z\n .string()\n .max(255, \"Email tối đa 255 ký tự\")\n .email(\"Email không hợp lệ\")\n .trim()\n .optional()\n .nullable()\n .or(z.literal(\"\")),\n\n status: z.enum([\"active\", \"inactive\"]).default(\"active\"),\n});\n\nexport type BranchInput = z.infer<typeof branchSchema>;\n\nexport const branchUpdateSchema = branchSchema.partial();\n","import { branchSchema, branchUpdateSchema } from \"../schemas\";\n\nexport interface BranchRecord {\n id: string;\n companyId?: string;\n code: string;\n name: string;\n address?: string | null;\n phone?: string | null;\n email?: string | null;\n status?: string;\n company?: { id: string; name: string };\n}\n\nexport interface BranchDbClient {\n branch: {\n count: (args: { where?: Record<string, unknown> }) => Promise<number>;\n findMany: (args: {\n where?: Record<string, unknown>;\n orderBy?: Record<string, unknown>;\n skip?: number;\n take?: number;\n include?: Record<string, unknown>;\n }) => Promise<BranchRecord[]>;\n findUnique: (args: {\n where: { id?: string; code?: string };\n include?: Record<string, unknown>;\n }) => Promise<BranchRecord | null>;\n create: (args: {\n data: Record<string, unknown>;\n include?: Record<string, unknown>;\n }) => Promise<BranchRecord>;\n update: (args: {\n where: { id: string };\n data: Record<string, unknown>;\n include?: Record<string, unknown>;\n }) => Promise<BranchRecord>;\n delete: (args: { where: { id: string } }) => Promise<BranchRecord>;\n };\n company: {\n findUnique: (args: {\n where: { id: string };\n }) => Promise<{ id: string } | null>;\n };\n}\n\nexport interface BranchListParams {\n page?: number;\n pageSize?: number;\n search?: string | null;\n companyId?: string | null;\n status?: string | null;\n}\n\nexport interface BranchListResponse {\n data: BranchRecord[];\n pagination: {\n page: number;\n pageSize: number;\n total: number;\n totalPages: number;\n };\n}\n\nexport class BranchServiceError extends Error {\n status: number;\n field?: string;\n details?: unknown;\n\n constructor(\n message: string,\n status: number,\n options?: { field?: string; details?: unknown },\n ) {\n super(message);\n this.name = \"BranchServiceError\";\n this.status = status;\n this.field = options?.field;\n this.details = options?.details;\n }\n}\n\nconst BRANCH_INCLUDE = {\n company: {\n select: { id: true, name: true },\n },\n};\n\nconst ensureUserId = (userId?: string) => {\n if (!userId) {\n throw new BranchServiceError(\"Unauthorized\", 401);\n }\n};\n\nexport async function listBranches(\n db: BranchDbClient,\n params: BranchListParams,\n): Promise<BranchListResponse> {\n const page = Number(params.page || 1);\n const pageSize = Math.min(Number(params.pageSize || 10), 100);\n const skip = (page - 1) * pageSize;\n\n const search = params.search?.trim() || undefined;\n const companyId = params.companyId?.trim() || undefined;\n const status = params.status?.trim() || undefined;\n\n const where: Record<string, unknown> = {};\n\n if (search) {\n where.OR = [\n { name: { contains: search, mode: \"insensitive\" } },\n { code: { contains: search, mode: \"insensitive\" } },\n { email: { contains: search, mode: \"insensitive\" } },\n ];\n }\n\n if (companyId) {\n where.companyId = companyId;\n }\n\n if (status) {\n where.status = status;\n }\n\n // ⚡ Bolt: Run count and findMany concurrently to reduce latency\n const [total, data] = await Promise.all([\n db.branch.count({ where }),\n db.branch.findMany({\n where,\n orderBy: { name: \"asc\" },\n skip,\n take: pageSize,\n include: BRANCH_INCLUDE,\n }),\n ]);\n\n return {\n data,\n pagination: {\n page,\n pageSize,\n total,\n totalPages: Math.ceil(total / pageSize),\n },\n };\n}\n\nexport async function getBranchById(\n db: BranchDbClient,\n id: string,\n): Promise<BranchRecord> {\n const branch = await db.branch.findUnique({\n where: { id },\n include: BRANCH_INCLUDE,\n });\n\n if (!branch) {\n throw new BranchServiceError(\"Chi nhánh không tồn tại\", 404);\n }\n\n return branch;\n}\n\nexport async function createBranch(\n db: BranchDbClient,\n input: unknown,\n userId?: string,\n): Promise<BranchRecord> {\n ensureUserId(userId);\n\n const result = branchSchema.safeParse(input);\n if (!result.success) {\n const errors = result.error.issues || [];\n const firstError = errors[0];\n throw new BranchServiceError(\n firstError?.message || \"Validation error\",\n 400,\n {\n field: firstError?.path?.join(\".\"),\n details: errors,\n },\n );\n }\n\n const validData = result.data;\n\n const existing = await db.branch.findUnique({\n where: { code: validData.code },\n });\n\n if (existing) {\n throw new BranchServiceError(\"Mã chi nhánh đã tồn tại\", 400, {\n field: \"code\",\n });\n }\n\n const company = await db.company.findUnique({\n where: { id: validData.companyId },\n });\n\n if (!company) {\n throw new BranchServiceError(\"Công ty không tồn tại\", 400, {\n field: \"companyId\",\n });\n }\n\n return db.branch.create({\n data: {\n id: crypto.randomUUID(),\n companyId: validData.companyId,\n code: validData.code,\n name: validData.name,\n address: validData.address,\n phone: validData.phone,\n email: validData.email,\n status: validData.status,\n createdBy: userId,\n updatedAt: new Date(),\n updatedBy: userId,\n },\n include: BRANCH_INCLUDE,\n });\n}\n\nexport async function updateBranch(\n db: BranchDbClient,\n id: string,\n input: unknown,\n userId?: string,\n): Promise<BranchRecord> {\n ensureUserId(userId);\n\n const result = branchUpdateSchema.safeParse(input);\n if (!result.success) {\n const errors = result.error.issues || [];\n const firstError = errors[0];\n throw new BranchServiceError(\n firstError?.message || \"Validation error\",\n 400,\n {\n field: firstError?.path?.join(\".\"),\n details: errors,\n },\n );\n }\n\n const validData = result.data;\n const existingBranch = await db.branch.findUnique({\n where: { id },\n });\n\n if (!existingBranch) {\n throw new BranchServiceError(\"Chi nhánh không tồn tại\", 404);\n }\n\n if (validData.code && validData.code !== existingBranch.code) {\n const duplicate = await db.branch.findUnique({\n where: { code: validData.code },\n });\n if (duplicate) {\n throw new BranchServiceError(\"Mã chi nhánh đã tồn tại\", 400, {\n field: \"code\",\n });\n }\n }\n\n if (validData.companyId) {\n const company = await db.company.findUnique({\n where: { id: validData.companyId },\n });\n if (!company) {\n throw new BranchServiceError(\"Công ty không tồn tại\", 400, {\n field: \"companyId\",\n });\n }\n }\n\n return db.branch.update({\n where: { id },\n data: {\n ...validData,\n updatedAt: new Date(),\n updatedBy: userId,\n },\n include: BRANCH_INCLUDE,\n });\n}\n\nexport async function deleteBranch(\n db: BranchDbClient,\n id: string,\n): Promise<BranchRecord> {\n const branch = await db.branch.findUnique({ where: { id } });\n if (!branch) {\n throw new BranchServiceError(\"Chi nhánh không tồn tại\", 404);\n }\n\n return db.branch.delete({ where: { id } });\n}\n"]}
@@ -1,83 +0,0 @@
1
- import { NavigationType, EntityConfig } from '../types/index.mjs';
2
- import { ComponentType } from 'react';
3
- import 'lucide-react';
4
- import 'zod';
5
-
6
- /**
7
- * Route definition for /app/[appId]/[pageId]
8
- * Used when an app has custom pages beyond CRUD
9
- */
10
- interface RouteDefinition {
11
- pageId: string;
12
- label: string;
13
- path: string;
14
- component: ComponentType<Record<string, unknown>>;
15
- permission?: string;
16
- }
17
- /**
18
- * GoerpApp - Plugin/App descriptor
19
- * Maps to AppDefinition.appId in core-db
20
- */
21
- interface GoerpApp {
22
- /** Unique app identifier - maps to AppDefinition.appId */
23
- appId: string;
24
- /** Display name */
25
- name: string;
26
- /** Semantic version */
27
- version: string;
28
- /** Human-readable description */
29
- description?: string;
30
- /** Core system app (always enabled) */
31
- isCore?: boolean;
32
- /** Navigation items for sidebar */
33
- navigation: NavigationType[];
34
- /** Entity configs for CRUD (/crud/[entity]) */
35
- entityConfigs: Record<string, EntityConfig>;
36
- /** Custom routes for /app/[appId]/[pageId] */
37
- routes?: RouteDefinition[];
38
- }
39
-
40
- /**
41
- * AppsRegistry - Manages registration and lookup of GoerpApp
42
- * Host app registers installed apps; registry merges navigation and entity configs
43
- */
44
- declare class AppsRegistry {
45
- private apps;
46
- private appsById;
47
- /**
48
- * Register an app. Later registrations override earlier entity configs for same entity.
49
- */
50
- register(app: GoerpApp): void;
51
- /**
52
- * Register multiple apps in order
53
- */
54
- registerAll(apps: GoerpApp[]): void;
55
- /**
56
- * Get app by appId
57
- */
58
- getApp(appId: string): GoerpApp | undefined;
59
- /**
60
- * Get all registered apps
61
- */
62
- getAllApps(): GoerpApp[];
63
- /**
64
- * Get merged navigation from all apps (order: registration order)
65
- * Groups with same title have their items merged
66
- */
67
- getNavigation(): NavigationType[];
68
- /**
69
- * Get entity config for entity key.
70
- * Later-registered apps override earlier for same entity.
71
- */
72
- getEntityConfig(entity: string): EntityConfig | undefined;
73
- /**
74
- * Check if entity exists in any app
75
- */
76
- hasEntity(entity: string): boolean;
77
- /**
78
- * Clear all registrations (for testing)
79
- */
80
- clear(): void;
81
- }
82
-
83
- export { AppsRegistry, type GoerpApp, type RouteDefinition };
@@ -1,83 +0,0 @@
1
- import { NavigationType, EntityConfig } from '../types/index.js';
2
- import { ComponentType } from 'react';
3
- import 'lucide-react';
4
- import 'zod';
5
-
6
- /**
7
- * Route definition for /app/[appId]/[pageId]
8
- * Used when an app has custom pages beyond CRUD
9
- */
10
- interface RouteDefinition {
11
- pageId: string;
12
- label: string;
13
- path: string;
14
- component: ComponentType<Record<string, unknown>>;
15
- permission?: string;
16
- }
17
- /**
18
- * GoerpApp - Plugin/App descriptor
19
- * Maps to AppDefinition.appId in core-db
20
- */
21
- interface GoerpApp {
22
- /** Unique app identifier - maps to AppDefinition.appId */
23
- appId: string;
24
- /** Display name */
25
- name: string;
26
- /** Semantic version */
27
- version: string;
28
- /** Human-readable description */
29
- description?: string;
30
- /** Core system app (always enabled) */
31
- isCore?: boolean;
32
- /** Navigation items for sidebar */
33
- navigation: NavigationType[];
34
- /** Entity configs for CRUD (/crud/[entity]) */
35
- entityConfigs: Record<string, EntityConfig>;
36
- /** Custom routes for /app/[appId]/[pageId] */
37
- routes?: RouteDefinition[];
38
- }
39
-
40
- /**
41
- * AppsRegistry - Manages registration and lookup of GoerpApp
42
- * Host app registers installed apps; registry merges navigation and entity configs
43
- */
44
- declare class AppsRegistry {
45
- private apps;
46
- private appsById;
47
- /**
48
- * Register an app. Later registrations override earlier entity configs for same entity.
49
- */
50
- register(app: GoerpApp): void;
51
- /**
52
- * Register multiple apps in order
53
- */
54
- registerAll(apps: GoerpApp[]): void;
55
- /**
56
- * Get app by appId
57
- */
58
- getApp(appId: string): GoerpApp | undefined;
59
- /**
60
- * Get all registered apps
61
- */
62
- getAllApps(): GoerpApp[];
63
- /**
64
- * Get merged navigation from all apps (order: registration order)
65
- * Groups with same title have their items merged
66
- */
67
- getNavigation(): NavigationType[];
68
- /**
69
- * Get entity config for entity key.
70
- * Later-registered apps override earlier for same entity.
71
- */
72
- getEntityConfig(entity: string): EntityConfig | undefined;
73
- /**
74
- * Check if entity exists in any app
75
- */
76
- hasEntity(entity: string): boolean;
77
- /**
78
- * Clear all registrations (for testing)
79
- */
80
- clear(): void;
81
- }
82
-
83
- export { AppsRegistry, type GoerpApp, type RouteDefinition };
@@ -1,86 +0,0 @@
1
- 'use strict';
2
-
3
- // src/plugin/apps-registry.ts
4
- var AppsRegistry = class {
5
- constructor() {
6
- this.apps = [];
7
- this.appsById = /* @__PURE__ */ new Map();
8
- }
9
- /**
10
- * Register an app. Later registrations override earlier entity configs for same entity.
11
- */
12
- register(app) {
13
- if (this.appsById.has(app.appId)) {
14
- console.warn(`[AppsRegistry] App "${app.appId}" already registered. Replacing.`);
15
- }
16
- this.appsById.set(app.appId, app);
17
- this.apps = Array.from(this.appsById.values());
18
- }
19
- /**
20
- * Register multiple apps in order
21
- */
22
- registerAll(apps) {
23
- for (const app of apps) {
24
- this.register(app);
25
- }
26
- }
27
- /**
28
- * Get app by appId
29
- */
30
- getApp(appId) {
31
- return this.appsById.get(appId);
32
- }
33
- /**
34
- * Get all registered apps
35
- */
36
- getAllApps() {
37
- return [...this.apps];
38
- }
39
- /**
40
- * Get merged navigation from all apps (order: registration order)
41
- * Groups with same title have their items merged
42
- */
43
- getNavigation() {
44
- const byTitle = /* @__PURE__ */ new Map();
45
- for (const app of this.apps) {
46
- for (const group of app.navigation) {
47
- const existing = byTitle.get(group.title);
48
- const items = group.items ?? [];
49
- if (existing) {
50
- existing.items = [...existing.items ?? [], ...items];
51
- } else {
52
- byTitle.set(group.title, { ...group, items: [...items] });
53
- }
54
- }
55
- }
56
- return Array.from(byTitle.values());
57
- }
58
- /**
59
- * Get entity config for entity key.
60
- * Later-registered apps override earlier for same entity.
61
- */
62
- getEntityConfig(entity) {
63
- for (let i = this.apps.length - 1; i >= 0; i--) {
64
- const config = this.apps[i].entityConfigs[entity];
65
- if (config) return config;
66
- }
67
- return void 0;
68
- }
69
- /**
70
- * Check if entity exists in any app
71
- */
72
- hasEntity(entity) {
73
- return this.getEntityConfig(entity) !== void 0;
74
- }
75
- /**
76
- * Clear all registrations (for testing)
77
- */
78
- clear() {
79
- this.apps = [];
80
- this.appsById.clear();
81
- }
82
- };
83
-
84
- exports.AppsRegistry = AppsRegistry;
85
- //# sourceMappingURL=index.js.map
86
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/plugin/apps-registry.ts"],"names":[],"mappings":";;;AAWO,IAAM,eAAN,MAAmB;AAAA,EAAnB,WAAA,GAAA;AACL,IAAA,IAAA,CAAQ,OAAmB,EAAC;AAC5B,IAAA,IAAA,CAAQ,QAAA,uBAAe,GAAA,EAAsB;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAK7C,SAAS,GAAA,EAAqB;AAC5B,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,GAAA,CAAI,KAAK,CAAA,EAAG;AAChC,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,oBAAA,EAAuB,GAAA,CAAI,KAAK,CAAA,gCAAA,CAAkC,CAAA;AAAA,IACjF;AACA,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,GAAA,CAAI,KAAA,EAAO,GAAG,CAAA;AAChC,IAAA,IAAA,CAAK,OAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,IAAA,EAAwB;AAClC,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,IAAA,CAAK,SAAS,GAAG,CAAA;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,KAAA,EAAqC;AAC1C,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,KAAK,CAAA;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,GAAyB;AACvB,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,IAAI,CAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAA,GAAkC;AAChC,IAAA,MAAM,OAAA,uBAAc,GAAA,EAA4B;AAEhD,IAAA,KAAA,MAAW,GAAA,IAAO,KAAK,IAAA,EAAM;AAC3B,MAAA,KAAA,MAAW,KAAA,IAAS,IAAI,UAAA,EAAY;AAClC,QAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,KAAK,CAAA;AACxC,QAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,IAAS,EAAC;AAC9B,QAAA,IAAI,QAAA,EAAU;AACZ,UAAA,QAAA,CAAS,KAAA,GAAQ,CAAC,GAAI,QAAA,CAAS,SAAS,EAAC,EAAI,GAAG,KAAK,CAAA;AAAA,QACvD,CAAA,MAAO;AACL,UAAA,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,KAAA,EAAO,EAAE,GAAG,KAAA,EAAO,KAAA,EAAO,CAAC,GAAG,KAAK,CAAA,EAAG,CAAA;AAAA,QAC1D;AAAA,MACF;AAAA,IACF;AACA,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,CAAA;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,MAAA,EAA0C;AACxD,IAAA,KAAA,IAAS,IAAI,IAAA,CAAK,IAAA,CAAK,SAAS,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AAC9C,MAAA,MAAM,SAAS,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,CAAE,cAAc,MAAM,CAAA;AAChD,MAAA,IAAI,QAAQ,OAAO,MAAA;AAAA,IACrB;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,MAAA,EAAyB;AACjC,IAAA,OAAO,IAAA,CAAK,eAAA,CAAgB,MAAM,CAAA,KAAM,MAAA;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,OAAO,EAAC;AACb,IAAA,IAAA,CAAK,SAAS,KAAA,EAAM;AAAA,EACtB;AACF","file":"index.js","sourcesContent":["// @goerp/core/plugin\n// AppsRegistry - Central registry for GoerpApp instances\n\nimport type { EntityConfig, NavigationType } from \"../types\"\n\nimport type { GoerpApp } from \"./types\"\n\n/**\n * AppsRegistry - Manages registration and lookup of GoerpApp\n * Host app registers installed apps; registry merges navigation and entity configs\n */\nexport class AppsRegistry {\n private apps: GoerpApp[] = []\n private appsById = new Map<string, GoerpApp>()\n\n /**\n * Register an app. Later registrations override earlier entity configs for same entity.\n */\n register(app: GoerpApp): void {\n if (this.appsById.has(app.appId)) {\n console.warn(`[AppsRegistry] App \"${app.appId}\" already registered. Replacing.`)\n }\n this.appsById.set(app.appId, app)\n this.apps = Array.from(this.appsById.values())\n }\n\n /**\n * Register multiple apps in order\n */\n registerAll(apps: GoerpApp[]): void {\n for (const app of apps) {\n this.register(app)\n }\n }\n\n /**\n * Get app by appId\n */\n getApp(appId: string): GoerpApp | undefined {\n return this.appsById.get(appId)\n }\n\n /**\n * Get all registered apps\n */\n getAllApps(): GoerpApp[] {\n return [...this.apps]\n }\n\n /**\n * Get merged navigation from all apps (order: registration order)\n * Groups with same title have their items merged\n */\n getNavigation(): NavigationType[] {\n const byTitle = new Map<string, NavigationType>()\n\n for (const app of this.apps) {\n for (const group of app.navigation) {\n const existing = byTitle.get(group.title)\n const items = group.items ?? []\n if (existing) {\n existing.items = [...(existing.items ?? []), ...items]\n } else {\n byTitle.set(group.title, { ...group, items: [...items] })\n }\n }\n }\n return Array.from(byTitle.values())\n }\n\n /**\n * Get entity config for entity key.\n * Later-registered apps override earlier for same entity.\n */\n getEntityConfig(entity: string): EntityConfig | undefined {\n for (let i = this.apps.length - 1; i >= 0; i--) {\n const config = this.apps[i].entityConfigs[entity]\n if (config) return config\n }\n return undefined\n }\n\n /**\n * Check if entity exists in any app\n */\n hasEntity(entity: string): boolean {\n return this.getEntityConfig(entity) !== undefined\n }\n\n /**\n * Clear all registrations (for testing)\n */\n clear(): void {\n this.apps = []\n this.appsById.clear()\n }\n}\n"]}