befly 3.76.1 → 3.76.2

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 (149) hide show
  1. package/Befly.js +159 -0
  2. package/README.md +50 -11
  3. package/apis/admin/delete.js +1 -3
  4. package/apis/admin/select.js +2 -7
  5. package/apis/admin/update.js +1 -5
  6. package/apis/api/select.js +2 -7
  7. package/apis/auth/login.js +16 -20
  8. package/apis/dict/delete.js +1 -1
  9. package/apis/dict/detail.js +1 -3
  10. package/apis/dict/select.js +1 -2
  11. package/apis/dict/update.js +1 -1
  12. package/apis/dictType/delete.js +1 -1
  13. package/apis/dictType/detail.js +1 -1
  14. package/apis/dictType/insert.js +1 -1
  15. package/apis/dictType/select.js +2 -7
  16. package/apis/dictType/update.js +2 -2
  17. package/apis/email/config.js +4 -7
  18. package/apis/email/logList.js +2 -7
  19. package/apis/email/send.js +1 -2
  20. package/apis/email/verify.js +1 -3
  21. package/apis/loginLog/select.js +2 -7
  22. package/apis/menu/select.js +2 -7
  23. package/apis/operateLog/select.js +2 -7
  24. package/apis/role/apiSave.js +2 -2
  25. package/apis/role/menuSave.js +2 -2
  26. package/apis/role/select.js +2 -7
  27. package/apis/source/imageList.js +2 -5
  28. package/apis/tongJi/dailyReport.js +12 -13
  29. package/apis/tongJi/dailyReportSelect.js +1 -2
  30. package/apis/tongJi/dailyStats.js +1 -1
  31. package/apis/tongJi/dailyStatsDistribution.js +2 -2
  32. package/apis/tongJi/errorList.js +1 -2
  33. package/apis/tongJi/errorReport.js +1 -2
  34. package/apis/tongJi/projectDelete.js +1 -3
  35. package/apis/tongJi/projectSelect.js +2 -4
  36. package/apis/tongJi/projectUpdate.js +2 -2
  37. package/apis/upload/file.js +7 -5
  38. package/checks/api.js +43 -66
  39. package/checks/config.js +17 -12
  40. package/checks/corns.js +28 -46
  41. package/checks/field.js +18 -0
  42. package/checks/items.js +16 -60
  43. package/checks/menu.js +28 -39
  44. package/checks/table.js +106 -26
  45. package/checks/validation.js +13 -0
  46. package/configs/beflyConfig.json +6 -6
  47. package/configs/constConfig.js +2 -63
  48. package/exports.js +2 -0
  49. package/hooks/auth.js +11 -7
  50. package/hooks/parser.js +55 -59
  51. package/hooks/permission.js +1 -0
  52. package/hooks/rateLimit.js +25 -62
  53. package/hooks/validator.js +43 -31
  54. package/index.js +43 -344
  55. package/{lib → libs}/cacheHelper.js +3 -8
  56. package/libs/cron.js +60 -0
  57. package/libs/logger/index.js +1 -0
  58. package/libs/logger/logger.js +245 -0
  59. package/libs/logger/sanitize.js +115 -0
  60. package/{lib → libs/mysql}/dbHelper.js +100 -73
  61. package/{lib → libs/mysql}/dbParse.js +16 -9
  62. package/{lib → libs/mysql}/dbUtil.js +15 -32
  63. package/libs/mysql/error.js +29 -0
  64. package/libs/mysql/index.js +6 -0
  65. package/libs/mysql/is.js +29 -0
  66. package/libs/mysql/mysql.js +43 -0
  67. package/libs/mysql/sql/identifier.js +85 -0
  68. package/libs/mysql/sql/index.js +2 -0
  69. package/{lib → libs/mysql/sql}/sqlBuilder.js +2 -3
  70. package/libs/mysql/util.js +44 -0
  71. package/libs/redis/index.js +2 -0
  72. package/libs/redis/redis.js +204 -0
  73. package/libs/redis/redisError.js +8 -0
  74. package/libs/tableModel.js +72 -0
  75. package/libs/tool.js +33 -0
  76. package/libs/validator/compiler.js +248 -0
  77. package/libs/validator/index.js +10 -0
  78. package/libs/validator/parser.js +173 -0
  79. package/libs/validator/util.js +5 -0
  80. package/package.json +10 -8
  81. package/paths.js +2 -3
  82. package/plugins/cache.js +2 -1
  83. package/plugins/email.js +4 -4
  84. package/plugins/mysql.js +5 -15
  85. package/plugins/redis.js +4 -12
  86. package/router/api.js +14 -10
  87. package/router/root.js +14 -0
  88. package/router/static.js +3 -3
  89. package/schemas/api.json +99 -0
  90. package/schemas/config.json +255 -0
  91. package/schemas/corn.json +39 -0
  92. package/schemas/item.json +43 -0
  93. package/schemas/menu.json +44 -0
  94. package/schemas/table.json +80 -0
  95. package/scripts/syncDb/apply.js +87 -0
  96. package/scripts/syncDb/ddl.js +43 -0
  97. package/scripts/syncDb/index.js +175 -30
  98. package/scripts/syncDb/model.js +60 -0
  99. package/scripts/syncDb/plan.js +160 -0
  100. package/scripts/syncDb/preflight.js +98 -0
  101. package/scripts/syncDb/report.js +177 -162
  102. package/scripts/syncDb/snapshot.js +118 -0
  103. package/tables/admin.json +51 -53
  104. package/tables/api.json +28 -39
  105. package/tables/dailyReport.json +85 -73
  106. package/tables/dict.json +27 -39
  107. package/tables/dictType.json +20 -34
  108. package/tables/emailLog.json +49 -47
  109. package/tables/errorReport.json +86 -60
  110. package/tables/file.json +47 -50
  111. package/tables/loginLog.json +68 -55
  112. package/tables/menu.json +20 -34
  113. package/tables/operateLog.json +53 -47
  114. package/tables/project.json +18 -30
  115. package/tables/role.json +33 -37
  116. package/utils/cors.js +37 -41
  117. package/utils/deepMerge.js +3 -1
  118. package/utils/error.js +1 -56
  119. package/utils/id.js +44 -0
  120. package/utils/is.js +6 -243
  121. package/utils/response.js +12 -1
  122. package/utils/scanFiles.js +13 -4
  123. package/utils/scanSources.js +58 -20
  124. package/utils/util.js +11 -163
  125. package/apis/_apis.js +0 -20
  126. package/apis/auth/sendSmsCode.js +0 -24
  127. package/configs/regexpAlias.json +0 -55
  128. package/lib/connect.js +0 -119
  129. package/lib/logger.js +0 -430
  130. package/lib/redisHelper.js +0 -399
  131. package/lib/validator.js +0 -274
  132. package/lib/xmlParse.js +0 -149
  133. package/plugins/config.js +0 -13
  134. package/plugins/cron.js +0 -115
  135. package/plugins/logger.js +0 -17
  136. package/plugins/tool.js +0 -131
  137. package/plugins/xmlParse.js +0 -10
  138. package/schemas/config.js +0 -67
  139. package/scripts/syncDb/context.js +0 -120
  140. package/scripts/syncDb/diff.js +0 -279
  141. package/scripts/syncDb/transform.js +0 -113
  142. package/sql/befly.sql +0 -271
  143. package/utils/email.js +0 -3
  144. package/utils/fieldClear.js +0 -22
  145. package/utils/formatValidationIssues.js +0 -28
  146. package/utils/getClientIp.js +0 -47
  147. package/utils/loggerUtils.js +0 -196
  148. package/utils/regexpUtil.js +0 -52
  149. /package/{lib → libs}/smtpText.js +0 -0
package/router/api.js CHANGED
@@ -3,20 +3,19 @@
3
3
  * 处理 /api/* 路径的请求
4
4
  */
5
5
 
6
- import picomatch from "picomatch";
6
+ import { Logger } from "#befly/libs/logger/index.js";
7
7
 
8
- import { Logger } from "../lib/logger.js";
9
8
  // 相对导入
10
9
  import { setCorsOptions } from "../utils/cors.js";
11
10
  import { createError } from "../utils/error.js";
12
- import { getClientIp } from "../utils/getClientIp.js";
11
+ import { isNonEmptyString } from "../utils/is.js";
13
12
  import { ErrorResponse, FinalResponse } from "../utils/response.js";
14
13
  import { genShortId } from "../utils/util.js";
15
14
 
16
15
  function createExcludeApisLogMatchers(excludeApisLog) {
17
16
  return excludeApisLog.map((pattern) => {
18
17
  try {
19
- return picomatch(pattern);
18
+ return new Bun.Glob(pattern);
20
19
  } catch (error) {
21
20
  throw createError(`excludeApisLog glob 无效: ${pattern}`, { cause: error, code: "validation", subsystem: "config", operation: "excludeApisLog" });
22
21
  }
@@ -53,7 +52,8 @@ export function apiHandler(apis, hooks, context) {
53
52
  // 只用接口路径做存在性判断与匹配:不要把 method 拼进 key
54
53
  // 说明:apisMap 的 key 来源于 scanFiles/loadApis 生成的 path(例如 /api/core/xxx)
55
54
 
56
- const clientIp = getClientIp(req, server);
55
+ const forwardedFor = context.config.trustProxy ? req.headers.get("x-forwarded-for") : "";
56
+ const clientIp = isNonEmptyString(forwardedFor) ? forwardedFor.split(",")[0].trim() : server?.requestIP(req)?.address?.trim() || "unknown";
57
57
 
58
58
  const apiData = apis[url.pathname];
59
59
  if (!apiData) {
@@ -63,6 +63,7 @@ export function apiHandler(apis, hooks, context) {
63
63
  msg: "接口不存在"
64
64
  },
65
65
  {
66
+ status: 404,
66
67
  headers: corsHeaders
67
68
  }
68
69
  );
@@ -88,18 +89,20 @@ export function apiHandler(apis, hooks, context) {
88
89
  apiAuth: apiData.auth,
89
90
  apiFields: apiData.fields,
90
91
  apiRequired: apiData.required,
92
+ apiConstraints: apiData.constraints,
91
93
  apiFile: apiData.filePath
92
94
  };
93
95
 
94
- if (ctx.apiMethod !== "ALL" && ctx.method !== ctx.apiMethod) {
96
+ const allowedMethods = apiData.method === "ALL" ? ["GET", "POST"] : [apiData.method];
97
+ if (!allowedMethods.includes(ctx.method)) {
95
98
  return ErrorResponse(
96
99
  ctx,
97
- `请求方法不允许,请使用 ${ctx.apiMethod}`,
100
+ `请求方法不允许,请使用 ${allowedMethods.join(" 或 ")}`,
98
101
  1,
99
102
  null,
100
103
  {
101
104
  method: ctx.method,
102
- allowMethod: ctx.apiMethod,
105
+ allowMethod: allowedMethods,
103
106
  apiPath: ctx.apiPath
104
107
  },
105
108
  "method"
@@ -136,7 +139,7 @@ export function apiHandler(apis, hooks, context) {
136
139
  logData["body"] = ctx.body;
137
140
  }
138
141
 
139
- const shouldSkipRequestLog = excludeApisLogMatchers.some((isMatch) => isMatch(ctx.apiPath));
142
+ const shouldSkipRequestLog = excludeApisLogMatchers.some((matcher) => matcher.match(ctx.apiPath));
140
143
 
141
144
  if (!shouldSkipRequestLog) {
142
145
  Logger.info("请求", logData);
@@ -176,7 +179,8 @@ export function apiHandler(apis, hooks, context) {
176
179
  code: 1,
177
180
  msg: "内部服务错误"
178
181
  };
179
- return FinalResponse(ctx);
182
+ const response = FinalResponse(ctx);
183
+ return new Response(response.body, { status: 500, headers: response.headers });
180
184
  }
181
185
  };
182
186
  }
package/router/root.js ADDED
@@ -0,0 +1,14 @@
1
+ import { formatYmdHms } from "../utils/datetime.js";
2
+
3
+ export function rootHandler(config) {
4
+ return () =>
5
+ Response.json({
6
+ code: 0,
7
+ msg: "success",
8
+ data: {
9
+ name: config.appName,
10
+ mode: config.runMode,
11
+ time: formatYmdHms(Date.now())
12
+ }
13
+ });
14
+ }
package/router/static.js CHANGED
@@ -3,10 +3,10 @@
3
3
  * 处理 /* 路径的静态文件请求
4
4
  */
5
5
 
6
- // 外部依赖
7
- import { basename, extname, isAbsolute, normalize, relative, resolve } from "pathe";
6
+ import { basename, extname, isAbsolute, normalize, relative, resolve } from "node:path";
7
+
8
+ import { Logger } from "#befly/libs/logger/index.js";
8
9
 
9
- import { Logger } from "../lib/logger.js";
10
10
  // 相对导入
11
11
  import { getAppPublicDir } from "../paths.js";
12
12
  import { setCorsOptions } from "../utils/cors.js";
@@ -0,0 +1,99 @@
1
+ {
2
+ "paramType": "array",
3
+ "items": {
4
+ "paramType": "object",
5
+ "fields": {
6
+ "source": {
7
+ "paramType": "string",
8
+ "enum": ["core", "app"]
9
+ },
10
+ "filePath": {
11
+ "paramType": "string",
12
+ "minValue": 1
13
+ },
14
+ "relativePath": {
15
+ "paramType": "string",
16
+ "minValue": 1
17
+ },
18
+ "fileName": {
19
+ "paramType": "string",
20
+ "minValue": 1
21
+ },
22
+ "apiPath": {
23
+ "paramType": "string",
24
+ "minValue": 1,
25
+ "pattern": "^/api/[a-z][a-zA-Z0-9]*(?:/[a-z][a-zA-Z0-9]*)*$"
26
+ },
27
+ "name": {
28
+ "paramType": "string",
29
+ "minValue": 1,
30
+ "maxValue": 100
31
+ },
32
+ "handler": {
33
+ "paramType": "function"
34
+ },
35
+ "method": {
36
+ "paramType": "string",
37
+ "enum": ["GET", "POST", "ALL"]
38
+ },
39
+ "body": {
40
+ "paramType": "string",
41
+ "enum": ["none", "raw"]
42
+ },
43
+ "auth": {
44
+ "anyOf": [
45
+ {
46
+ "paramType": "boolean"
47
+ },
48
+ {
49
+ "paramType": "array",
50
+ "minItem": 1,
51
+ "items": {
52
+ "paramType": "string",
53
+ "minValue": 1
54
+ }
55
+ }
56
+ ]
57
+ },
58
+ "fields": {
59
+ "paramType": "record",
60
+ "keys": {
61
+ "paramType": "string",
62
+ "minValue": 1,
63
+ "pattern": "^[a-z][a-zA-Z0-9]*$"
64
+ },
65
+ "values": {
66
+ "paramType": "object",
67
+ "extra": true
68
+ }
69
+ },
70
+ "required": {
71
+ "paramType": "array",
72
+ "unique": true,
73
+ "items": {
74
+ "paramType": "string",
75
+ "minValue": 1,
76
+ "pattern": "^[a-z][a-zA-Z0-9]*$"
77
+ }
78
+ },
79
+ "constraints": {
80
+ "paramType": "array",
81
+ "minItem": 1,
82
+ "items": {
83
+ "paramType": "object",
84
+ "extra": true
85
+ },
86
+ "optional": true
87
+ },
88
+ "category": {
89
+ "paramType": "string",
90
+ "enum": ["select", "insert", "delete", "update", "other"],
91
+ "paramDefault": "other"
92
+ },
93
+ "type": {
94
+ "paramType": "string",
95
+ "minValue": 1
96
+ }
97
+ }
98
+ }
99
+ }
@@ -0,0 +1,255 @@
1
+ {
2
+ "paramType": "object",
3
+ "fields": {
4
+ "appName": {
5
+ "paramType": "string"
6
+ },
7
+ "appPort": {
8
+ "paramType": "integer",
9
+ "minValue": 1,
10
+ "maxValue": 65535
11
+ },
12
+ "appHost": {
13
+ "paramType": "string"
14
+ },
15
+ "apiHost": {
16
+ "paramType": "string"
17
+ },
18
+ "devEmail": {
19
+ "paramType": "string",
20
+ "pattern": "^(|[^\\s@]+@[^\\s@]+\\.[^\\s@]+)$"
21
+ },
22
+ "devPassword": {
23
+ "paramType": "string",
24
+ "minValue": 6
25
+ },
26
+ "trustProxy": {
27
+ "paramType": "boolean"
28
+ },
29
+ "bodyLimit": {
30
+ "paramType": "integer",
31
+ "minValue": 1
32
+ },
33
+ "tz": {
34
+ "paramType": "string"
35
+ },
36
+ "excludeApisLog": {
37
+ "paramType": "array",
38
+ "items": {
39
+ "paramType": "string"
40
+ }
41
+ },
42
+ "upload": {
43
+ "paramType": "object",
44
+ "fields": {
45
+ "maxSize": {
46
+ "paramType": "integer",
47
+ "minValue": 1
48
+ },
49
+ "publicDir": {
50
+ "paramType": "string",
51
+ "minValue": 1
52
+ },
53
+ "publicHost": {
54
+ "paramType": "string"
55
+ },
56
+ "allowedExtensions": {
57
+ "paramType": "string",
58
+ "pattern": "^\\.[a-z0-9]+(?:,\\.[a-z0-9]+)*$"
59
+ },
60
+ "allowedMimeTypes": {
61
+ "paramType": "string",
62
+ "pattern": "^[a-z0-9][a-z0-9.+-]*\\/[a-z0-9][a-z0-9.+-]*(?:,[a-z0-9][a-z0-9.+-]*\\/[a-z0-9][a-z0-9.+-]*)*$"
63
+ },
64
+ "forceDownloadExtensions": {
65
+ "paramType": "string",
66
+ "pattern": "^(|\\.[a-z0-9]+(?:,\\.[a-z0-9]+)*)$"
67
+ }
68
+ }
69
+ },
70
+ "logger": {
71
+ "paramType": "object",
72
+ "fields": {
73
+ "debug": {
74
+ "paramType": "boolean"
75
+ },
76
+ "excludeFields": {
77
+ "paramType": "array",
78
+ "items": {
79
+ "paramType": "string"
80
+ }
81
+ }
82
+ }
83
+ },
84
+ "mysql": {
85
+ "paramType": "object",
86
+ "fields": {
87
+ "hostname": {
88
+ "paramType": "string"
89
+ },
90
+ "port": {
91
+ "paramType": "integer",
92
+ "minValue": 1,
93
+ "maxValue": 65535
94
+ },
95
+ "username": {
96
+ "paramType": "string"
97
+ },
98
+ "password": {
99
+ "paramType": "string"
100
+ },
101
+ "database": {
102
+ "paramType": "string"
103
+ },
104
+ "beflyMode": {
105
+ "paramType": "string",
106
+ "enum": ["manual", "auto"],
107
+ "optional": true
108
+ },
109
+ "idleTimeout": {
110
+ "paramType": "number",
111
+ "minValue": 1,
112
+ "optional": true
113
+ },
114
+ "maxLifetime": {
115
+ "paramType": "number",
116
+ "minValue": 0,
117
+ "optional": true
118
+ },
119
+ "connectionTimeout": {
120
+ "paramType": "number",
121
+ "minValue": 1,
122
+ "optional": true
123
+ },
124
+ "queryTimeout": {
125
+ "paramType": "number",
126
+ "minValue": 1,
127
+ "optional": true
128
+ },
129
+ "max": {
130
+ "paramType": "number",
131
+ "minValue": 1
132
+ }
133
+ }
134
+ },
135
+ "redis": {
136
+ "paramType": "object",
137
+ "fields": {
138
+ "hostname": {
139
+ "paramType": "string"
140
+ },
141
+ "port": {
142
+ "paramType": "integer",
143
+ "minValue": 1,
144
+ "maxValue": 65535
145
+ },
146
+ "username": {
147
+ "paramType": "string"
148
+ },
149
+ "password": {
150
+ "paramType": "string"
151
+ },
152
+ "db": {
153
+ "paramType": "integer",
154
+ "minValue": 0,
155
+ "maxValue": 16
156
+ },
157
+ "prefix": {
158
+ "paramType": "string",
159
+ "pattern": "^[^:]*$"
160
+ }
161
+ }
162
+ },
163
+ "session": {
164
+ "paramType": "object",
165
+ "fields": {
166
+ "expireDays": {
167
+ "paramType": "integer",
168
+ "minValue": 1
169
+ }
170
+ }
171
+ },
172
+ "email": {
173
+ "paramType": "object",
174
+ "optional": true,
175
+ "fields": {
176
+ "host": {
177
+ "paramType": "string"
178
+ },
179
+ "port": {
180
+ "paramType": "integer",
181
+ "minValue": 1,
182
+ "maxValue": 65535
183
+ },
184
+ "secure": {
185
+ "paramType": "boolean"
186
+ },
187
+ "user": {
188
+ "paramType": "string"
189
+ },
190
+ "pass": {
191
+ "paramType": "string"
192
+ },
193
+ "label": {
194
+ "paramType": "string",
195
+ "optional": true
196
+ }
197
+ }
198
+ },
199
+ "cors": {
200
+ "paramType": "object",
201
+ "fields": {
202
+ "origins": {
203
+ "paramType": "array",
204
+ "optional": true,
205
+ "minItem": 1,
206
+ "items": {
207
+ "paramType": "string",
208
+ "minValue": 1
209
+ }
210
+ },
211
+ "allowedHeaders": {
212
+ "paramType": "string"
213
+ },
214
+ "exposedHeaders": {
215
+ "paramType": "string"
216
+ },
217
+ "maxAge": {
218
+ "paramType": "integer",
219
+ "minValue": 0
220
+ },
221
+ "credentials": {
222
+ "paramType": "boolean"
223
+ }
224
+ }
225
+ },
226
+ "rateLimit": {
227
+ "paramType": "object",
228
+ "fields": {
229
+ "enable": {
230
+ "paramType": "boolean"
231
+ },
232
+ "failOpen": {
233
+ "paramType": "boolean"
234
+ },
235
+ "defaultLimit": {
236
+ "paramType": "integer",
237
+ "minValue": 1
238
+ },
239
+ "defaultWindow": {
240
+ "paramType": "integer",
241
+ "minValue": 1
242
+ },
243
+ "key": {
244
+ "paramType": "string"
245
+ },
246
+ "skipRoutes": {
247
+ "paramType": "array",
248
+ "items": {
249
+ "paramType": "string"
250
+ }
251
+ }
252
+ }
253
+ }
254
+ }
255
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "paramType": "array",
3
+ "items": {
4
+ "paramType": "object",
5
+ "fields": {
6
+ "source": {
7
+ "paramType": "string",
8
+ "enum": ["core", "app"]
9
+ },
10
+ "filePath": {
11
+ "paramType": "string",
12
+ "minValue": 1
13
+ },
14
+ "relativePath": {
15
+ "paramType": "string",
16
+ "minValue": 1
17
+ },
18
+ "fileName": {
19
+ "paramType": "string",
20
+ "minValue": 1
21
+ },
22
+ "apiPath": {
23
+ "paramType": "string",
24
+ "minValue": 1
25
+ },
26
+ "schedule": {
27
+ "paramType": "string",
28
+ "minValue": 1
29
+ },
30
+ "handler": {
31
+ "paramType": "function"
32
+ },
33
+ "type": {
34
+ "paramType": "string",
35
+ "minValue": 1
36
+ }
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "paramType": "array",
3
+ "uniqueBy": "order",
4
+ "items": {
5
+ "paramType": "object",
6
+ "fields": {
7
+ "name": {
8
+ "paramType": "string",
9
+ "minValue": 1
10
+ },
11
+ "source": {
12
+ "paramType": "string",
13
+ "enum": ["core", "app"]
14
+ },
15
+ "filePath": {
16
+ "paramType": "string",
17
+ "minValue": 1
18
+ },
19
+ "relativePath": {
20
+ "paramType": "string",
21
+ "minValue": 1
22
+ },
23
+ "fileName": {
24
+ "paramType": "string",
25
+ "minValue": 1
26
+ },
27
+ "apiPath": {
28
+ "paramType": "string",
29
+ "minValue": 1
30
+ },
31
+ "handler": {
32
+ "paramType": "function"
33
+ },
34
+ "order": {
35
+ "paramType": "number"
36
+ },
37
+ "type": {
38
+ "paramType": "string",
39
+ "minValue": 1
40
+ }
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "paramType": "array",
3
+ "items": {
4
+ "paramType": "object",
5
+ "fields": {
6
+ "path": {
7
+ "paramType": "string",
8
+ "pattern": "^/(?:core(?:/[a-z][a-z0-9]*(?:-[a-z0-9]+)*)*|(?:[a-z][a-z0-9]*(?:-[a-z0-9]+)*(?:/[a-z][a-z0-9]*(?:-[a-z0-9]+)*)*)?)$"
9
+ },
10
+ "name": {
11
+ "paramType": "string",
12
+ "minValue": 1
13
+ },
14
+ "sort": {
15
+ "paramType": "number"
16
+ },
17
+ "children": {
18
+ "paramType": "array",
19
+ "optional": true,
20
+ "items": {
21
+ "paramType": "object",
22
+ "fields": {
23
+ "path": {
24
+ "paramType": "string",
25
+ "pattern": "^/[a-z][a-z0-9]*(?:-[a-z0-9]+)*$"
26
+ },
27
+ "name": {
28
+ "paramType": "string",
29
+ "minValue": 1
30
+ },
31
+ "sort": {
32
+ "paramType": "number"
33
+ },
34
+ "children": {
35
+ "paramType": "array",
36
+ "maxItem": 0,
37
+ "optional": true
38
+ }
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,80 @@
1
+ {
2
+ "paramType": "record",
3
+ "keys": {
4
+ "paramType": "string",
5
+ "minValue": 1,
6
+ "pattern": "^[a-z][a-zA-Z0-9]*$"
7
+ },
8
+ "values": {
9
+ "paramType": "object",
10
+ "fields": {
11
+ "name": {
12
+ "paramType": "string",
13
+ "minValue": 1
14
+ },
15
+ "source": {
16
+ "paramType": "string",
17
+ "enum": ["core", "app"]
18
+ },
19
+ "fileName": {
20
+ "paramType": "string",
21
+ "minValue": 1,
22
+ "pattern": "^[a-z][a-zA-Z0-9]*$"
23
+ },
24
+ "codeName": {
25
+ "paramType": "string",
26
+ "minValue": 1,
27
+ "pattern": "^[a-z][a-zA-Z0-9]*$"
28
+ },
29
+ "dbName": {
30
+ "paramType": "string",
31
+ "minValue": 1,
32
+ "pattern": "^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$"
33
+ },
34
+ "primary": {
35
+ "paramType": "string",
36
+ "minValue": 1,
37
+ "pattern": "^[a-z][a-zA-Z0-9]*$"
38
+ },
39
+ "indexes": {
40
+ "paramType": "record",
41
+ "keys": {
42
+ "paramType": "string",
43
+ "minValue": 1,
44
+ "pattern": "^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$"
45
+ },
46
+ "values": {
47
+ "paramType": "object",
48
+ "fields": {
49
+ "fields": {
50
+ "paramType": "array",
51
+ "minItem": 1,
52
+ "unique": true,
53
+ "items": {
54
+ "paramType": "string",
55
+ "minValue": 1,
56
+ "pattern": "^[a-z][a-zA-Z0-9]*$"
57
+ }
58
+ },
59
+ "type": {
60
+ "enum": ["index", "unique"],
61
+ "paramType": "string"
62
+ }
63
+ }
64
+ }
65
+ },
66
+ "fields": {
67
+ "paramType": "record",
68
+ "keys": {
69
+ "paramType": "string",
70
+ "minValue": 1,
71
+ "pattern": "^[a-z][a-zA-Z0-9]*$"
72
+ },
73
+ "values": {
74
+ "paramType": "object",
75
+ "extra": true
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }