hola-server 2.0.1 → 3.0.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.
Files changed (242) hide show
  1. package/README.md +318 -132
  2. package/dist/config/index.d.ts +46 -0
  3. package/dist/config/index.d.ts.map +1 -0
  4. package/dist/config/index.js +55 -0
  5. package/dist/config/index.js.map +1 -0
  6. package/dist/core/array.d.ts +27 -0
  7. package/dist/core/array.d.ts.map +1 -0
  8. package/dist/core/array.js +66 -0
  9. package/dist/core/array.js.map +1 -0
  10. package/dist/core/bash.d.ts +51 -0
  11. package/dist/core/bash.d.ts.map +1 -0
  12. package/dist/core/bash.js +161 -0
  13. package/dist/core/bash.js.map +1 -0
  14. package/dist/core/chart.d.ts +11 -0
  15. package/dist/core/chart.d.ts.map +1 -0
  16. package/dist/core/chart.js +35 -0
  17. package/dist/core/chart.js.map +1 -0
  18. package/dist/core/date.d.ts +11 -0
  19. package/dist/core/date.d.ts.map +1 -0
  20. package/dist/core/date.js +18 -0
  21. package/dist/core/date.js.map +1 -0
  22. package/dist/core/encrypt.d.ts +18 -0
  23. package/dist/core/encrypt.d.ts.map +1 -0
  24. package/dist/core/encrypt.js +50 -0
  25. package/dist/core/encrypt.js.map +1 -0
  26. package/dist/core/file.d.ts +22 -0
  27. package/dist/core/file.d.ts.map +1 -0
  28. package/dist/core/file.js +21 -0
  29. package/dist/core/file.js.map +1 -0
  30. package/dist/core/lhs.d.ts +17 -0
  31. package/dist/core/lhs.d.ts.map +1 -0
  32. package/dist/core/lhs.js +30 -0
  33. package/dist/core/lhs.js.map +1 -0
  34. package/dist/core/meta.d.ts +200 -0
  35. package/dist/core/meta.d.ts.map +1 -0
  36. package/dist/core/meta.js +336 -0
  37. package/dist/core/meta.js.map +1 -0
  38. package/dist/core/number.d.ts +37 -0
  39. package/dist/core/number.d.ts.map +1 -0
  40. package/dist/core/number.js +99 -0
  41. package/dist/core/number.js.map +1 -0
  42. package/dist/core/obj.d.ts +9 -0
  43. package/dist/core/obj.d.ts.map +1 -0
  44. package/dist/core/obj.js +15 -0
  45. package/dist/core/obj.js.map +1 -0
  46. package/dist/core/random.d.ts +7 -0
  47. package/dist/core/random.d.ts.map +1 -0
  48. package/dist/core/random.js +7 -0
  49. package/dist/core/random.js.map +1 -0
  50. package/dist/core/role.d.ts +42 -0
  51. package/dist/core/role.d.ts.map +1 -0
  52. package/dist/core/role.js +81 -0
  53. package/dist/core/role.js.map +1 -0
  54. package/dist/core/thread.d.ts +7 -0
  55. package/dist/core/thread.d.ts.map +1 -0
  56. package/dist/core/thread.js +7 -0
  57. package/dist/core/thread.js.map +1 -0
  58. package/dist/core/type.d.ts +46 -0
  59. package/dist/core/type.d.ts.map +1 -0
  60. package/dist/core/type.js +281 -0
  61. package/dist/core/type.js.map +1 -0
  62. package/dist/core/url.d.ts +20 -0
  63. package/dist/core/url.d.ts.map +1 -0
  64. package/dist/core/url.js +24 -0
  65. package/dist/core/url.js.map +1 -0
  66. package/dist/core/validate.d.ts +11 -0
  67. package/dist/core/validate.d.ts.map +1 -0
  68. package/dist/core/validate.js +19 -0
  69. package/dist/core/validate.js.map +1 -0
  70. package/dist/db/db.d.ts +72 -0
  71. package/dist/db/db.d.ts.map +1 -0
  72. package/dist/db/db.js +225 -0
  73. package/dist/db/db.js.map +1 -0
  74. package/dist/db/entity.d.ts +77 -0
  75. package/dist/db/entity.d.ts.map +1 -0
  76. package/dist/db/entity.js +671 -0
  77. package/dist/db/entity.js.map +1 -0
  78. package/dist/db/gridfs.d.ts +29 -0
  79. package/dist/db/gridfs.d.ts.map +1 -0
  80. package/dist/db/gridfs.js +125 -0
  81. package/dist/db/gridfs.js.map +1 -0
  82. package/dist/db/index.d.ts +8 -0
  83. package/dist/db/index.d.ts.map +1 -0
  84. package/dist/db/index.js +8 -0
  85. package/dist/db/index.js.map +1 -0
  86. package/dist/errors/auth.d.ts +15 -0
  87. package/dist/errors/auth.d.ts.map +1 -0
  88. package/dist/errors/auth.js +21 -0
  89. package/dist/errors/auth.js.map +1 -0
  90. package/dist/errors/http.d.ts +15 -0
  91. package/dist/errors/http.d.ts.map +1 -0
  92. package/dist/errors/http.js +21 -0
  93. package/dist/errors/http.js.map +1 -0
  94. package/dist/errors/index.d.ts +18 -0
  95. package/dist/errors/index.d.ts.map +1 -0
  96. package/dist/errors/index.js +18 -0
  97. package/dist/errors/index.js.map +1 -0
  98. package/dist/errors/validation.d.ts +11 -0
  99. package/dist/errors/validation.d.ts.map +1 -0
  100. package/dist/errors/validation.js +15 -0
  101. package/dist/errors/validation.js.map +1 -0
  102. package/dist/http/code.d.ts +21 -0
  103. package/dist/http/code.d.ts.map +1 -0
  104. package/dist/http/code.js +27 -0
  105. package/dist/http/code.js.map +1 -0
  106. package/dist/index.d.ts +57 -0
  107. package/dist/index.d.ts.map +1 -0
  108. package/dist/index.js +61 -0
  109. package/dist/index.js.map +1 -0
  110. package/dist/meta/index.d.ts +9 -0
  111. package/dist/meta/index.d.ts.map +1 -0
  112. package/dist/meta/index.js +11 -0
  113. package/dist/meta/index.js.map +1 -0
  114. package/dist/meta/router.d.ts +26 -0
  115. package/dist/meta/router.d.ts.map +1 -0
  116. package/dist/meta/router.js +258 -0
  117. package/dist/meta/router.js.map +1 -0
  118. package/dist/meta/schema.d.ts +41 -0
  119. package/dist/meta/schema.d.ts.map +1 -0
  120. package/dist/meta/schema.js +69 -0
  121. package/dist/meta/schema.js.map +1 -0
  122. package/dist/plugins/auth.d.ts +248 -0
  123. package/dist/plugins/auth.d.ts.map +1 -0
  124. package/dist/plugins/auth.js +121 -0
  125. package/dist/plugins/auth.js.map +1 -0
  126. package/dist/plugins/body.d.ts +47 -0
  127. package/dist/plugins/body.d.ts.map +1 -0
  128. package/dist/plugins/body.js +36 -0
  129. package/dist/plugins/body.js.map +1 -0
  130. package/dist/plugins/cors.d.ts +62 -0
  131. package/dist/plugins/cors.d.ts.map +1 -0
  132. package/dist/plugins/cors.js +17 -0
  133. package/dist/plugins/cors.js.map +1 -0
  134. package/dist/plugins/error.d.ts +51 -0
  135. package/dist/plugins/error.d.ts.map +1 -0
  136. package/dist/plugins/error.js +51 -0
  137. package/dist/plugins/error.js.map +1 -0
  138. package/dist/plugins/index.d.ts +9 -0
  139. package/dist/plugins/index.d.ts.map +1 -0
  140. package/dist/plugins/index.js +9 -0
  141. package/dist/plugins/index.js.map +1 -0
  142. package/dist/setting.d.ts +66 -0
  143. package/dist/setting.d.ts.map +1 -0
  144. package/dist/setting.js +27 -0
  145. package/dist/setting.js.map +1 -0
  146. package/dist/tool/gen_i18n.d.ts +10 -0
  147. package/dist/tool/gen_i18n.d.ts.map +1 -0
  148. package/{tool → dist/tool}/gen_i18n.js +9 -22
  149. package/dist/tool/gen_i18n.js.map +1 -0
  150. package/dist/tool/vector_store.d.ts +72 -0
  151. package/dist/tool/vector_store.d.ts.map +1 -0
  152. package/dist/tool/vector_store.js +203 -0
  153. package/dist/tool/vector_store.js.map +1 -0
  154. package/package.json +37 -22
  155. package/core/array.js +0 -124
  156. package/core/bash.js +0 -294
  157. package/core/chart.js +0 -46
  158. package/core/cron.js +0 -21
  159. package/core/date.js +0 -26
  160. package/core/encrypt.js +0 -26
  161. package/core/file.js +0 -51
  162. package/core/lhs.js +0 -53
  163. package/core/meta.js +0 -283
  164. package/core/msg.js +0 -24
  165. package/core/number.js +0 -181
  166. package/core/obj.js +0 -25
  167. package/core/random.js +0 -12
  168. package/core/role.js +0 -108
  169. package/core/thread.js +0 -13
  170. package/core/type.js +0 -368
  171. package/core/url.js +0 -30
  172. package/core/validate.js +0 -35
  173. package/db/db.js +0 -446
  174. package/db/entity.js +0 -920
  175. package/db/gridfs.js +0 -175
  176. package/design/add_default_field_attr.md +0 -56
  177. package/http/code.js +0 -18
  178. package/http/context.js +0 -31
  179. package/http/cors.js +0 -32
  180. package/http/error.js +0 -39
  181. package/http/express.js +0 -104
  182. package/http/params.js +0 -85
  183. package/http/router.js +0 -83
  184. package/http/session.js +0 -73
  185. package/index.js +0 -112
  186. package/router/clone.js +0 -65
  187. package/router/create.js +0 -54
  188. package/router/delete.js +0 -49
  189. package/router/read.js +0 -191
  190. package/router/update.js +0 -89
  191. package/setting.js +0 -67
  192. package/skills/array.md +0 -155
  193. package/skills/bash.md +0 -91
  194. package/skills/chart.md +0 -54
  195. package/skills/code.md +0 -422
  196. package/skills/context.md +0 -177
  197. package/skills/date.md +0 -58
  198. package/skills/express.md +0 -255
  199. package/skills/file.md +0 -60
  200. package/skills/lhs.md +0 -54
  201. package/skills/meta.md +0 -1023
  202. package/skills/msg.md +0 -30
  203. package/skills/number.md +0 -88
  204. package/skills/obj.md +0 -36
  205. package/skills/params.md +0 -206
  206. package/skills/random.md +0 -22
  207. package/skills/role.md +0 -59
  208. package/skills/session.md +0 -281
  209. package/skills/storage.md +0 -743
  210. package/skills/thread.md +0 -22
  211. package/skills/type.md +0 -547
  212. package/skills/url.md +0 -34
  213. package/skills/validate.md +0 -48
  214. package/test/cleanup/close-db.js +0 -5
  215. package/test/core/array.js +0 -226
  216. package/test/core/chart.js +0 -51
  217. package/test/core/date.js +0 -37
  218. package/test/core/encrypt.js +0 -14
  219. package/test/core/file.js +0 -59
  220. package/test/core/lhs.js +0 -44
  221. package/test/core/meta.js +0 -594
  222. package/test/core/number.js +0 -172
  223. package/test/core/obj.js +0 -47
  224. package/test/core/random.js +0 -24
  225. package/test/core/thread.js +0 -20
  226. package/test/core/type.js +0 -216
  227. package/test/core/validate.js +0 -67
  228. package/test/db/db-ops.js +0 -99
  229. package/test/db/db.js +0 -72
  230. package/test/db/pipe_test.txt +0 -0
  231. package/test/db/test_case_design.md +0 -528
  232. package/test/db/test_db_class.js +0 -613
  233. package/test/db/test_entity_class.js +0 -414
  234. package/test/db/test_gridfs_class.js +0 -234
  235. package/test/entity/create.js +0 -442
  236. package/test/entity/delete-mixed.js +0 -156
  237. package/test/entity/delete.js +0 -480
  238. package/test/entity/read.js +0 -285
  239. package/test/entity/ref-filter.js +0 -63
  240. package/test/entity/update.js +0 -252
  241. package/test/router/role.js +0 -15
  242. package/tool/test.json +0 -25
package/dist/index.js ADDED
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Hola Server - Main entry point and public API.
3
+ *
4
+ * @module hola-server
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { plugins, errors, db, meta, config } from 'hola-server';
9
+ *
10
+ * const app = new Elysia()
11
+ * .use(plugins.holaCors({ origin: ['http://localhost:5173'] }))
12
+ * .use(plugins.holaBody({ limit: '10mb' }))
13
+ * .use(plugins.holaAuth({ secret: 'your-secret' }))
14
+ * .use(plugins.holaError())
15
+ * .use(userRouter)
16
+ * .onStart(async () => {
17
+ * await db.get_db();
18
+ * meta.validate_all_metas();
19
+ * })
20
+ * .listen(3000);
21
+ * ```
22
+ */
23
+ // Namespaced exports
24
+ export * as plugins from "./plugins/index.js";
25
+ export * as errors from "./errors/index.js";
26
+ export * as db from "./db/index.js";
27
+ export * as meta from "./meta/index.js";
28
+ export * as config from "./config/index.js";
29
+ // Commonly used items at top level for convenience
30
+ export { EntityMeta, init_router, validate_all_metas, register_schema_type } from "./meta/index.js";
31
+ export { Entity } from "./db/entity.js";
32
+ export { get_db, init_db, close_db } from "./db/db.js";
33
+ // Core Type System
34
+ export { register_type, get_type, convert_type, convert_update_type, int_enum_type } from "./core/type.js";
35
+ export { get_entity_meta, get_all_metas, DELETE_MODE } from "./core/meta.js";
36
+ // Core Role System
37
+ export { is_root_role, is_root_user, check_user_role, get_user_role_right, get_session_user, validate_meta_role } from "./core/role.js";
38
+ // Core Utilities
39
+ export { url } from "./core/url.js";
40
+ export * as array from "./core/array.js";
41
+ export * as bash from "./core/bash.js";
42
+ export * as chart from "./core/chart.js";
43
+ export * as date from "./core/date.js";
44
+ export * as file from "./core/file.js";
45
+ export * as lhs from "./core/lhs.js";
46
+ export * as number from "./core/number.js";
47
+ export * as obj from "./core/obj.js";
48
+ export * as random from "./core/random.js";
49
+ export * as thread from "./core/thread.js";
50
+ export * as validate from "./core/validate.js";
51
+ export { encrypt_pwd, md5, encrypt_secret, decrypt_secret } from "./core/encrypt.js";
52
+ // HTTP utilities
53
+ export * as code from "./http/code.js";
54
+ // Settings
55
+ export { init_settings, get_settings } from "./setting.js";
56
+ // OID utilities
57
+ export { oid_query, oid_queries } from "./db/db.js";
58
+ // Tools
59
+ export { gen_i18n } from "./tool/gen_i18n.js";
60
+ export { VectorStore, getVectorStore, initVectorStore } from "./tool/vector_store.js";
61
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,qBAAqB;AACrB,OAAO,KAAK,OAAO,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,eAAe,CAAC;AACpC,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAE5C,mDAAmD;AACnD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAIpG,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEvD,mBAAmB;AACnB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE3G,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7E,mBAAmB;AACnB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAExI,iBAAiB;AACjB,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACpC,OAAO,KAAK,KAAK,MAAM,iBAAiB,CAAC;AACzC,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,KAAK,KAAK,MAAM,iBAAiB,CAAC;AACzC,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACvC,OAAO,KAAK,GAAG,MAAM,eAAe,CAAC;AACrC,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAC3C,OAAO,KAAK,GAAG,MAAM,eAAe,CAAC;AACrC,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAC3C,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAC3C,OAAO,KAAK,QAAQ,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAErF,iBAAiB;AACjB,OAAO,KAAK,IAAI,MAAM,gBAAgB,CAAC;AAEvC,WAAW;AACX,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG3D,gBAAgB;AAChB,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEpD,QAAQ;AACR,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Meta module index - exports EntityMeta, router, and schema utilities.
3
+ * @module meta
4
+ */
5
+ export { EntityMeta, get_entity_meta, get_all_metas, validate_all_metas, DELETE_MODE } from '../core/meta.js';
6
+ export type { MetaDefinition, FieldDefinition, AnyCallback, FieldValue, QueryValue } from '../core/meta.js';
7
+ export { init_router } from './router.js';
8
+ export { meta_to_schema, meta_to_openapi, register_schema_type } from './schema.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/meta/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACH,UAAU,EACV,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,WAAW,EACd,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACR,cAAc,EACd,eAAe,EACf,WAAW,EACX,UAAU,EACV,UAAU,EACb,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Meta module index - exports EntityMeta, router, and schema utilities.
3
+ * @module meta
4
+ */
5
+ // EntityMeta and related types
6
+ export { EntityMeta, get_entity_meta, get_all_metas, validate_all_metas, DELETE_MODE } from '../core/meta.js';
7
+ // Router initialization
8
+ export { init_router } from './router.js';
9
+ // Schema generation
10
+ export { meta_to_schema, meta_to_openapi, register_schema_type } from './schema.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/meta/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,+BAA+B;AAC/B,OAAO,EACH,UAAU,EACV,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,WAAW,EACd,MAAM,iBAAiB,CAAC;AAUzB,wBAAwB;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,oBAAoB;AACpB,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * RESTful router initialization for EntityMeta.
3
+ * @module meta/router
4
+ */
5
+ import { Elysia } from "elysia";
6
+ import { MetaDefinition } from "../core/meta.js";
7
+ /**
8
+ * Create RESTful router for an entity.
9
+ *
10
+ * Routes:
11
+ * - GET / Simple list with optional params (attr_names, sort_by, desc, page, limit)
12
+ * - POST /list List entities with full query options
13
+ * - GET /:id Get single entity
14
+ * - POST / Create entity
15
+ * - PUT /:id Update entity
16
+ * - DELETE /:id Delete entity
17
+ * - GET /meta Get field metadata and permission mode
18
+ * - GET /ref Get reference labels
19
+ * - POST /:id/clone Clone entity
20
+ *
21
+ * @param definition Meta definition for the entity
22
+ */
23
+ export declare const init_router: (definition: MetaDefinition) => Elysia<any>;
24
+ /** Re-export validate_all_metas for convenience. */
25
+ export { validate_all_metas } from "../core/meta.js";
26
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/meta/router.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAc,cAAc,EAAiD,MAAM,iBAAiB,CAAC;AA8E5G;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,WAAW,GAAI,YAAY,cAAc,KAAG,MAAM,CAAC,GAAG,CAyNlE,CAAC;AAEF,oDAAoD;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,258 @@
1
+ /**
2
+ * RESTful router initialization for EntityMeta.
3
+ * @module meta/router
4
+ */
5
+ import { Elysia } from "elysia";
6
+ import { EntityMeta, filter_fields_by_role } from "../core/meta.js";
7
+ import { meta_to_schema } from "./schema.js";
8
+ import { Entity } from "../db/entity.js";
9
+ import { NotFoundError, NoRightsError } from "../errors/index.js";
10
+ import { SUCCESS } from "../http/code.js";
11
+ import { get_settings } from "../setting.js";
12
+ import { has_value } from "../core/validate.js";
13
+ /** Check if user has read rights for meta. */
14
+ const check_read_rights = (user, meta) => {
15
+ if (!meta.readable)
16
+ throw new NoRightsError("entity not readable");
17
+ const settings = get_settings();
18
+ if (settings.server.check_user && !user)
19
+ throw new NoRightsError("no user found");
20
+ // Check role-based permission if roles are defined
21
+ if (meta.roles && user) {
22
+ const mode = meta.get_role_mode(user.role);
23
+ if (!mode.includes("r"))
24
+ throw new NoRightsError("role has no read rights");
25
+ }
26
+ };
27
+ /** Check if user has create rights for meta. */
28
+ const check_create_rights = (user, meta) => {
29
+ if (!meta.creatable)
30
+ throw new NoRightsError("entity not creatable");
31
+ const settings = get_settings();
32
+ if (settings.server.check_user && !user)
33
+ throw new NoRightsError("no user found");
34
+ // Check role-based permission if roles are defined
35
+ if (meta.roles && user) {
36
+ const mode = meta.get_role_mode(user.role);
37
+ if (!mode.includes("c"))
38
+ throw new NoRightsError("role has no create rights");
39
+ }
40
+ };
41
+ /** Check if user has update rights for meta. */
42
+ const check_update_rights = (user, meta) => {
43
+ if (!meta.updatable)
44
+ throw new NoRightsError("entity not updatable");
45
+ const settings = get_settings();
46
+ if (settings.server.check_user && !user)
47
+ throw new NoRightsError("no user found");
48
+ // Check role-based permission if roles are defined
49
+ if (meta.roles && user) {
50
+ const mode = meta.get_role_mode(user.role);
51
+ if (!mode.includes("u"))
52
+ throw new NoRightsError("role has no update rights");
53
+ }
54
+ };
55
+ /** Check if user has delete rights for meta. */
56
+ const check_delete_rights = (user, meta) => {
57
+ if (!meta.deleteable)
58
+ throw new NoRightsError("entity not deleteable");
59
+ const settings = get_settings();
60
+ if (settings.server.check_user && !user)
61
+ throw new NoRightsError("no user found");
62
+ // Check role-based permission if roles are defined
63
+ if (meta.roles && user) {
64
+ const mode = meta.get_role_mode(user.role);
65
+ if (!mode.includes("d"))
66
+ throw new NoRightsError("role has no delete rights");
67
+ }
68
+ };
69
+ /** Check if user has clone rights for meta. */
70
+ const check_clone_rights = (user, meta) => {
71
+ if (!meta.cloneable)
72
+ throw new NoRightsError("entity not cloneable");
73
+ const settings = get_settings();
74
+ if (settings.server.check_user && !user)
75
+ throw new NoRightsError("no user found");
76
+ // Check role-based permission if roles are defined (clone requires create permission)
77
+ if (meta.roles && user) {
78
+ const mode = meta.get_role_mode(user.role);
79
+ if (!mode.includes("o"))
80
+ throw new NoRightsError("role has no clone rights");
81
+ }
82
+ };
83
+ /**
84
+ * Create RESTful router for an entity.
85
+ *
86
+ * Routes:
87
+ * - GET / Simple list with optional params (attr_names, sort_by, desc, page, limit)
88
+ * - POST /list List entities with full query options
89
+ * - GET /:id Get single entity
90
+ * - POST / Create entity
91
+ * - PUT /:id Update entity
92
+ * - DELETE /:id Delete entity
93
+ * - GET /meta Get field metadata and permission mode
94
+ * - GET /ref Get reference labels
95
+ * - POST /:id/clone Clone entity
96
+ *
97
+ * @param definition Meta definition for the entity
98
+ */
99
+ export const init_router = (definition) => {
100
+ const meta = new EntityMeta(definition);
101
+ const entity = new Entity(meta.collection);
102
+ const schema = meta_to_schema(meta);
103
+ const router = new Elysia({ prefix: `/${meta.collection}` });
104
+ // POST /list - List entities
105
+ if (meta.readable) {
106
+ router.post("/list", async ({ user, body }) => {
107
+ check_read_rights(user, meta);
108
+ const body_data = body;
109
+ const filter = {};
110
+ // Apply user field filter if defined
111
+ if (meta.user_field && user?.sub) {
112
+ filter[meta.user_field] = user.sub;
113
+ }
114
+ const user_role = user?.role || "*";
115
+ const result = await entity.list_entity(body_data, filter, body_data, user_role);
116
+ return { ...result };
117
+ }, { body: schema.query });
118
+ }
119
+ // GET / - Simple list with optional parameters and sensible defaults
120
+ if (meta.readable) {
121
+ router.get("/", async ({ user, query }) => {
122
+ check_read_rights(user, meta);
123
+ const settings = get_settings();
124
+ const query_data = query;
125
+ const filter = {};
126
+ // Apply user field filter if defined
127
+ if (meta.user_field && user?.sub) {
128
+ filter[meta.user_field] = user.sub;
129
+ }
130
+ // Provide sensible defaults for optional parameters
131
+ const list_field_names = meta.list_fields.map((f) => f.name).join(",");
132
+ const primary_key = meta.primary_keys?.[0] || "_id";
133
+ const default_limit = settings.server.threshold.default_list_limit || 100;
134
+ const params = {
135
+ attr_names: query_data.attr_names || list_field_names,
136
+ sort_by: query_data.sort_by || primary_key,
137
+ desc: query_data.desc || "true",
138
+ page: Number(query_data.page) || 1,
139
+ limit: Number(query_data.limit) || default_limit,
140
+ };
141
+ const user_role = user?.role || "*";
142
+ const result = await entity.list_entity(params, filter, query_data, user_role);
143
+ return { ...result };
144
+ });
145
+ }
146
+ // GET /meta - Get field metadata and mode
147
+ if (meta.readable) {
148
+ router.get("/meta", async ({ user }) => {
149
+ check_read_rights(user, meta);
150
+ // Get mode based on user's role
151
+ const role_mode = meta.get_role_mode(user?.role);
152
+ // Filter to fields visible in at least one UI context
153
+ const user_role = user?.role || "*";
154
+ const visible_fields = filter_fields_by_role(meta.client_fields, user_role).filter((f) => f.create !== false || f.update !== false || f.search !== false || f.list !== false);
155
+ return { code: SUCCESS, data: { mode: role_mode, fields: visible_fields } };
156
+ });
157
+ }
158
+ // GET /ref - Get reference labels
159
+ if (meta.readable && meta.ref_label) {
160
+ router.get("/ref", async ({ user, query }) => {
161
+ check_read_rights(user, meta);
162
+ const list = await entity.get_filtered_ref_labels(query.ref_by_entity || "", query.query, user?.sub);
163
+ const items = list.map((obj) => ({ title: obj[meta.ref_label], value: String(obj._id) }));
164
+ return { code: SUCCESS, data: items };
165
+ }, { query: schema.ref_query });
166
+ }
167
+ // GET /:id - Get single entity
168
+ if (meta.readable) {
169
+ router.get("/:id", async ({ user, params }) => {
170
+ check_read_rights(user, meta);
171
+ const user_role = user?.role || "*";
172
+ const list_field_names = meta.list_fields.map((f) => f.name).join(",");
173
+ const result = await entity.read_entity(params.id, list_field_names, user_role);
174
+ if (!result.data)
175
+ throw new NotFoundError();
176
+ return { code: SUCCESS, data: result.data };
177
+ }, { params: schema.id_param });
178
+ }
179
+ // GET /:id/property - Get specific properties
180
+ if (meta.readable) {
181
+ router.get("/:id/property", async ({ user, params, query }) => {
182
+ check_read_rights(user, meta);
183
+ const user_role = user?.role || "*";
184
+ const attr_names = query.fields || "*";
185
+ const result = await entity.read_property(params.id, attr_names, user_role);
186
+ if (!result.data)
187
+ throw new NotFoundError();
188
+ return { code: SUCCESS, data: result.data };
189
+ }, { params: schema.id_param, query: schema.property_query });
190
+ }
191
+ // POST / - Create entity
192
+ // Note: No Elysia schema validation here - Entity layer handles validation after before_hook
193
+ // This allows hooks to set default values for required fields
194
+ if (meta.creatable) {
195
+ router.post("/", async ({ user, body }) => {
196
+ check_create_rights(user, meta);
197
+ const data = body;
198
+ // Apply default values for create operation
199
+ for (const field of meta.create_fields) {
200
+ if (!has_value(data[field.name]) && field.default !== undefined) {
201
+ data[field.name] = field.default;
202
+ }
203
+ }
204
+ // Set user field if defined
205
+ if (meta.user_field && user?.sub) {
206
+ data[meta.user_field] = user.sub;
207
+ }
208
+ // Pass user context for hooks to access
209
+ data._user = user;
210
+ const user_role = user?.role || "*";
211
+ const result = await entity.create_entity(data, user_role);
212
+ return result;
213
+ });
214
+ }
215
+ // PUT /:id - Update entity
216
+ if (meta.updatable) {
217
+ router.put("/:id", async ({ user, params, body }) => {
218
+ check_update_rights(user, meta);
219
+ const data = body;
220
+ const user_role = user?.role || "*";
221
+ const result = await entity.update_entity(params.id, data, user_role);
222
+ return result;
223
+ }, { params: schema.id_param, body: schema.update });
224
+ }
225
+ // DELETE /:id - Delete entity
226
+ if (meta.deleteable) {
227
+ router.delete("/:id", async ({ user, params }) => {
228
+ check_delete_rights(user, meta);
229
+ const result = await entity.delete_entity([params.id]);
230
+ return result;
231
+ }, { params: schema.id_param });
232
+ }
233
+ // POST /:id/clone - Clone entity
234
+ // Note: No Elysia body schema validation here - Entity layer handles validation after before_hook
235
+ if (meta.cloneable) {
236
+ router.post("/:id/clone", async ({ user, params, body }) => {
237
+ check_clone_rights(user, meta);
238
+ const data = body;
239
+ // Set user field if defined (cloned entity belongs to the cloning user)
240
+ if (meta.user_field && user?.sub) {
241
+ data[meta.user_field] = user.sub;
242
+ }
243
+ // Pass user context for hooks to access
244
+ data._user = user;
245
+ const user_role = user?.role || "*";
246
+ const result = await entity.clone_entity(params.id, data, user_role);
247
+ return result;
248
+ }, { params: schema.id_param });
249
+ }
250
+ // Custom route callback
251
+ if (definition.route) {
252
+ definition.route(router, meta);
253
+ }
254
+ return router;
255
+ };
256
+ /** Re-export validate_all_metas for convenience. */
257
+ export { validate_all_metas } from "../core/meta.js";
258
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/meta/router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * TypeBox schema generation from EntityMeta.
3
+ * @module meta/schema
4
+ */
5
+ import { TSchema } from "elysia";
6
+ import type { EntityMeta } from "../core/meta.js";
7
+ /** Register a custom schema type mapping. */
8
+ export declare const register_schema_type: (name: string, schema_fn: () => TSchema) => void;
9
+ /** Generate TypeBox schemas from EntityMeta (lazy evaluation for custom types). */
10
+ export declare const meta_to_schema: (meta: EntityMeta) => {
11
+ readonly create: TSchema;
12
+ readonly update: TSchema;
13
+ query: import("@sinclair/typebox").TObject<{
14
+ page: import("@sinclair/typebox").TNumber;
15
+ limit: import("@sinclair/typebox").TNumber;
16
+ sort_by: import("@sinclair/typebox").TString;
17
+ desc: import("@sinclair/typebox").TString;
18
+ attr_names: import("@sinclair/typebox").TString;
19
+ search: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
20
+ }>;
21
+ ref_query: import("@sinclair/typebox").TObject<{
22
+ ref_by_entity: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
23
+ query: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
24
+ }>;
25
+ property_query: import("@sinclair/typebox").TObject<{
26
+ fields: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
27
+ }>;
28
+ id_param: import("@sinclair/typebox").TObject<{
29
+ id: import("@sinclair/typebox").TString;
30
+ }>;
31
+ };
32
+ /** Generate OpenAPI-compatible schema documentation from EntityMeta. */
33
+ export declare const meta_to_openapi: (meta: EntityMeta) => {
34
+ collection: string;
35
+ fields: {
36
+ name: string;
37
+ type: string;
38
+ required: boolean;
39
+ }[];
40
+ };
41
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/meta/schema.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAK,OAAO,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,iBAAiB,CAAC;AAKnE,6CAA6C;AAC7C,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,EAAE,WAAW,MAAM,OAAO,KAAG,IAE7E,CAAC;AAsCF,mFAAmF;AACnF,eAAO,MAAM,cAAc,GAAI,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;CAyB9C,CAAC;AAEF,wEAAwE;AACxE,eAAO,MAAM,eAAe,GAAI,MAAM,UAAU;;;;;;;CAA0J,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * TypeBox schema generation from EntityMeta.
3
+ * @module meta/schema
4
+ */
5
+ import { t } from "elysia";
6
+ /** Custom schema type registry for project-specific types. */
7
+ const custom_schema_types = {};
8
+ /** Register a custom schema type mapping. */
9
+ export const register_schema_type = (name, schema_fn) => {
10
+ custom_schema_types[name] = schema_fn;
11
+ };
12
+ /** Get schema for a field type (checks custom types first, then built-in, then defaults to string). */
13
+ const get_schema_for_type = (type_name) => {
14
+ const type_map = { string: () => t.String(), text: () => t.String(), number: () => t.Numeric(), int: () => t.Numeric(), float: () => t.Numeric(), boolean: () => t.Boolean(), date: () => t.String({ format: "date-time" }), datetime: () => t.String({ format: "date-time" }), array: () => t.Array(t.Unknown()), object: () => t.Object({}), file: () => t.Any(), json: () => t.Any() };
15
+ // Check custom types first, then built-in types, then default to string
16
+ const schema_fn = custom_schema_types[type_name] ?? type_map[type_name];
17
+ return schema_fn?.() ?? t.String();
18
+ };
19
+ /** Map field type to TypeBox schema. */
20
+ const field_to_schema = (field) => {
21
+ const base = get_schema_for_type(field.type ?? "string");
22
+ return field.required ? base : t.Optional(base);
23
+ };
24
+ /** Build create schema for entity. */
25
+ const build_create_schema = (meta) => {
26
+ const create_fields = {};
27
+ // Exclude user_field from request validation - it's auto-populated from session
28
+ const user_field = meta.user_field;
29
+ for (const field of meta.create_fields) {
30
+ if (field.name === user_field)
31
+ continue;
32
+ create_fields[field.name] = field_to_schema(field);
33
+ }
34
+ return t.Object(create_fields);
35
+ };
36
+ /** Build update schema for entity. */
37
+ const build_update_schema = (meta) => {
38
+ const update_fields = {};
39
+ for (const field of meta.update_fields) {
40
+ update_fields[field.name] = t.Optional(field_to_schema(field));
41
+ }
42
+ return t.Object(update_fields);
43
+ };
44
+ /** Generate TypeBox schemas from EntityMeta (lazy evaluation for custom types). */
45
+ export const meta_to_schema = (meta) => {
46
+ // Query schema for list operations - allows additional properties for entity-specific search fields
47
+ const query_schema = t.Object({ page: t.Number({ minimum: 1 }), limit: t.Number({ minimum: 1, maximum: 1000 }), sort_by: t.String(), desc: t.String(), attr_names: t.String(), search: t.Optional(t.String()) }, { additionalProperties: true });
48
+ // Ref query schema for reference labels lookup
49
+ const ref_query_schema = t.Object({ ref_by_entity: t.Optional(t.String()), query: t.Optional(t.String()) });
50
+ // Property query schema for reading specific fields
51
+ const property_query_schema = t.Object({ fields: t.Optional(t.String()) });
52
+ const id_param = t.Object({ id: t.String() });
53
+ // Use getters for lazy evaluation - custom types are resolved when schema is accessed
54
+ return {
55
+ get create() {
56
+ return build_create_schema(meta);
57
+ },
58
+ get update() {
59
+ return build_update_schema(meta);
60
+ },
61
+ query: query_schema,
62
+ ref_query: ref_query_schema,
63
+ property_query: property_query_schema,
64
+ id_param,
65
+ };
66
+ };
67
+ /** Generate OpenAPI-compatible schema documentation from EntityMeta. */
68
+ export const meta_to_openapi = (meta) => ({ collection: meta.collection, fields: meta.client_fields.map((f) => ({ name: f.name, type: f.type ?? "string", required: f.required ?? false })) });
69
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/meta/schema.ts"],"names":[],"mappings":"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"}