@lenne.tech/nest-server 12.1.1 → 12.3.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 (317) hide show
  1. package/.claude/rules/architecture.md +1 -0
  2. package/.claude/rules/better-auth.md +31 -4
  3. package/.claude/rules/configurable-features.md +8 -6
  4. package/.claude/rules/package-management.md +29 -2
  5. package/.claude/rules/persistence.md +27 -1
  6. package/.claude/rules/testing.md +80 -15
  7. package/.claude/rules/versioning.md +13 -2
  8. package/CLAUDE.md +7 -1
  9. package/FRAMEWORK-API.md +20 -4
  10. package/README.md +20 -2
  11. package/dist/config.env.js +2 -2
  12. package/dist/config.env.js.map +1 -1
  13. package/dist/core/common/helpers/graphql-ws-connection.helper.d.ts +4 -0
  14. package/dist/core/common/helpers/graphql-ws-connection.helper.js +17 -3
  15. package/dist/core/common/helpers/graphql-ws-connection.helper.js.map +1 -1
  16. package/dist/core/common/interfaces/server-options.interface.d.ts +49 -0
  17. package/dist/core/common/interfaces/service-options.interface.d.ts +3 -0
  18. package/dist/core/common/persistence/core-persistence.module.js +12 -2
  19. package/dist/core/common/persistence/core-persistence.module.js.map +1 -1
  20. package/dist/core/common/persistence/data-source.runtime.js +4 -2
  21. package/dist/core/common/persistence/data-source.runtime.js.map +1 -1
  22. package/dist/core/common/persistence/data-store.interface.d.ts +24 -9
  23. package/dist/core/common/persistence/id-format.d.ts +2 -0
  24. package/dist/core/common/persistence/id-format.js +14 -0
  25. package/dist/core/common/persistence/id-format.js.map +1 -1
  26. package/dist/core/common/persistence/model-descriptor.interface.d.ts +6 -0
  27. package/dist/core/common/persistence/model-metadata.registry.d.ts +2 -1
  28. package/dist/core/common/persistence/model-metadata.registry.js +20 -2
  29. package/dist/core/common/persistence/model-metadata.registry.js.map +1 -1
  30. package/dist/core/common/persistence/mongo/sync-schema.plugin.d.ts +18 -0
  31. package/dist/core/common/persistence/mongo/sync-schema.plugin.js +368 -0
  32. package/dist/core/common/persistence/mongo/sync-schema.plugin.js.map +1 -0
  33. package/dist/core/common/persistence/mongoose-data-store.d.ts +19 -9
  34. package/dist/core/common/persistence/mongoose-data-store.js +107 -31
  35. package/dist/core/common/persistence/mongoose-data-store.js.map +1 -1
  36. package/dist/core/common/persistence/persisted-model.decorator.d.ts +3 -0
  37. package/dist/core/common/persistence/persisted-model.decorator.js +9 -0
  38. package/dist/core/common/persistence/persisted-model.decorator.js.map +1 -1
  39. package/dist/core/common/persistence/policies/sync.policy.d.ts +17 -0
  40. package/dist/core/common/persistence/policies/sync.policy.js +77 -0
  41. package/dist/core/common/persistence/policies/sync.policy.js.map +1 -0
  42. package/dist/core/common/persistence/sql/mysql/mysql-data-store.d.ts +12 -8
  43. package/dist/core/common/persistence/sql/mysql/mysql-data-store.js +82 -29
  44. package/dist/core/common/persistence/sql/mysql/mysql-data-store.js.map +1 -1
  45. package/dist/core/common/persistence/sql/mysql/mysql-schema.compiler.d.ts +10 -0
  46. package/dist/core/common/persistence/sql/mysql/mysql-schema.compiler.js +61 -4
  47. package/dist/core/common/persistence/sql/mysql/mysql-schema.compiler.js.map +1 -1
  48. package/dist/core/common/persistence/sql/mysql/mysql-schema.migrator.js +101 -4
  49. package/dist/core/common/persistence/sql/mysql/mysql-schema.migrator.js.map +1 -1
  50. package/dist/core/common/persistence/sql/postgres/postgres-schema.compiler.d.ts +10 -0
  51. package/dist/core/common/persistence/sql/postgres/postgres-schema.compiler.js +41 -2
  52. package/dist/core/common/persistence/sql/postgres/postgres-schema.compiler.js.map +1 -1
  53. package/dist/core/common/persistence/sql/postgres/postgres-schema.migrator.js +98 -10
  54. package/dist/core/common/persistence/sql/postgres/postgres-schema.migrator.js.map +1 -1
  55. package/dist/core/common/persistence/sql/sql-data-store.d.ts +38 -14
  56. package/dist/core/common/persistence/sql/sql-data-store.js +212 -38
  57. package/dist/core/common/persistence/sql/sql-data-store.js.map +1 -1
  58. package/dist/core/common/persistence/sql/sql-errors.d.ts +2 -1
  59. package/dist/core/common/persistence/sql/sql-errors.js +3 -1
  60. package/dist/core/common/persistence/sql/sql-errors.js.map +1 -1
  61. package/dist/core/common/persistence/sync-access.registry.d.ts +17 -0
  62. package/dist/core/common/persistence/sync-access.registry.js +8 -0
  63. package/dist/core/common/persistence/sync-access.registry.js.map +1 -0
  64. package/dist/core/common/persistence/sync-model.d.ts +29 -0
  65. package/dist/core/common/persistence/sync-model.js +138 -0
  66. package/dist/core/common/persistence/sync-model.js.map +1 -0
  67. package/dist/core/common/services/crud.service.d.ts +13 -1
  68. package/dist/core/common/services/crud.service.js +174 -16
  69. package/dist/core/common/services/crud.service.js.map +1 -1
  70. package/dist/core/modules/ai/core-ai-mcp.controller.d.ts +3 -0
  71. package/dist/core/modules/ai/core-ai-mcp.controller.js +29 -0
  72. package/dist/core/modules/ai/core-ai-mcp.controller.js.map +1 -1
  73. package/dist/core/modules/ai/core-ai.constants.d.ts +2 -0
  74. package/dist/core/modules/ai/core-ai.constants.js +2 -0
  75. package/dist/core/modules/ai/core-ai.constants.js.map +1 -1
  76. package/dist/core/modules/ai/core-ai.controller.d.ts +6 -0
  77. package/dist/core/modules/ai/core-ai.controller.js +31 -1
  78. package/dist/core/modules/ai/core-ai.controller.js.map +1 -1
  79. package/dist/core/modules/ai/core-ai.module.d.ts +2 -0
  80. package/dist/core/modules/ai/core-ai.module.js +8 -1
  81. package/dist/core/modules/ai/core-ai.module.js.map +1 -1
  82. package/dist/core/modules/ai/core-ai.resolver.d.ts +6 -0
  83. package/dist/core/modules/ai/core-ai.resolver.js +32 -0
  84. package/dist/core/modules/ai/core-ai.resolver.js.map +1 -1
  85. package/dist/core/modules/ai/helpers/ai-mcp-oauth-consent.helper.d.ts +65 -1
  86. package/dist/core/modules/ai/helpers/ai-mcp-oauth-consent.helper.js +6 -3
  87. package/dist/core/modules/ai/helpers/ai-mcp-oauth-consent.helper.js.map +1 -1
  88. package/dist/core/modules/ai/helpers/ai-mcp-oauth.helper.js +48 -1
  89. package/dist/core/modules/ai/helpers/ai-mcp-oauth.helper.js.map +1 -1
  90. package/dist/core/modules/ai/helpers/ai-tool-authorization.helper.d.ts +9 -0
  91. package/dist/core/modules/ai/helpers/ai-tool-authorization.helper.js +54 -0
  92. package/dist/core/modules/ai/helpers/ai-tool-authorization.helper.js.map +1 -0
  93. package/dist/core/modules/ai/index.d.ts +7 -0
  94. package/dist/core/modules/ai/index.js +6 -0
  95. package/dist/core/modules/ai/index.js.map +1 -1
  96. package/dist/core/modules/ai/inputs/core-ai-settings.input.d.ts +3 -0
  97. package/dist/core/modules/ai/inputs/core-ai-settings.input.js +31 -0
  98. package/dist/core/modules/ai/inputs/core-ai-settings.input.js.map +1 -0
  99. package/dist/core/modules/ai/interfaces/ai-tool.interface.d.ts +2 -0
  100. package/dist/core/modules/ai/models/core-ai-settings.model.d.ts +4 -0
  101. package/dist/core/modules/ai/models/core-ai-settings.model.js +30 -0
  102. package/dist/core/modules/ai/models/core-ai-settings.model.js.map +1 -0
  103. package/dist/core/modules/ai/models/core-ai-user-setting.model.d.ts +8 -0
  104. package/dist/core/modules/ai/models/core-ai-user-setting.model.js +45 -0
  105. package/dist/core/modules/ai/models/core-ai-user-setting.model.js.map +1 -0
  106. package/dist/core/modules/ai/services/core-ai-conversation.service.d.ts +4 -1
  107. package/dist/core/modules/ai/services/core-ai-conversation.service.js +16 -4
  108. package/dist/core/modules/ai/services/core-ai-conversation.service.js.map +1 -1
  109. package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.js +6 -6
  110. package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.js.map +1 -1
  111. package/dist/core/modules/ai/services/core-ai-mcp.service.d.ts +27 -2
  112. package/dist/core/modules/ai/services/core-ai-mcp.service.js +118 -11
  113. package/dist/core/modules/ai/services/core-ai-mcp.service.js.map +1 -1
  114. package/dist/core/modules/ai/services/core-ai-prompt-builder.service.js +9 -6
  115. package/dist/core/modules/ai/services/core-ai-prompt-builder.service.js.map +1 -1
  116. package/dist/core/modules/ai/services/core-ai-user-setting.service.d.ts +17 -0
  117. package/dist/core/modules/ai/services/core-ai-user-setting.service.js +72 -0
  118. package/dist/core/modules/ai/services/core-ai-user-setting.service.js.map +1 -0
  119. package/dist/core/modules/ai/services/core-ai.service.d.ts +8 -3
  120. package/dist/core/modules/ai/services/core-ai.service.js +68 -29
  121. package/dist/core/modules/ai/services/core-ai.service.js.map +1 -1
  122. package/dist/core/modules/better-auth/better-auth.config.js +3 -1
  123. package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
  124. package/dist/core/modules/better-auth/core-better-auth-email-verification.service.js +2 -2
  125. package/dist/core/modules/better-auth/core-better-auth-email-verification.service.js.map +1 -1
  126. package/dist/core/modules/better-auth/core-better-auth-path-guard.middleware.d.ts +8 -0
  127. package/dist/core/modules/better-auth/core-better-auth-path-guard.middleware.js +64 -0
  128. package/dist/core/modules/better-auth/core-better-auth-path-guard.middleware.js.map +1 -0
  129. package/dist/core/modules/better-auth/core-better-auth-rate-limit.middleware.js +2 -1
  130. package/dist/core/modules/better-auth/core-better-auth-rate-limit.middleware.js.map +1 -1
  131. package/dist/core/modules/better-auth/core-better-auth-rate-limiter.service.d.ts +1 -1
  132. package/dist/core/modules/better-auth/core-better-auth-rate-limiter.service.js +5 -3
  133. package/dist/core/modules/better-auth/core-better-auth-rate-limiter.service.js.map +1 -1
  134. package/dist/core/modules/better-auth/core-better-auth.module.js +2 -0
  135. package/dist/core/modules/better-auth/core-better-auth.module.js.map +1 -1
  136. package/dist/core/modules/better-auth/index.d.ts +1 -0
  137. package/dist/core/modules/better-auth/index.js +1 -0
  138. package/dist/core/modules/better-auth/index.js.map +1 -1
  139. package/dist/core/modules/error-code/error-codes.d.ts +72 -0
  140. package/dist/core/modules/error-code/error-codes.js +64 -0
  141. package/dist/core/modules/error-code/error-codes.js.map +1 -1
  142. package/dist/core/modules/migrate/sql-migration.helper.d.ts +15 -1
  143. package/dist/core/modules/migrate/sql-migration.helper.js +90 -5
  144. package/dist/core/modules/migrate/sql-migration.helper.js.map +1 -1
  145. package/dist/core/modules/sync/core-sync-base.controller.d.ts +7 -0
  146. package/dist/core/modules/sync/core-sync-base.controller.js +44 -0
  147. package/dist/core/modules/sync/core-sync-base.controller.js.map +1 -0
  148. package/dist/core/modules/sync/core-sync-cursor.d.ts +19 -0
  149. package/dist/core/modules/sync/core-sync-cursor.js +77 -0
  150. package/dist/core/modules/sync/core-sync-cursor.js.map +1 -0
  151. package/dist/core/modules/sync/core-sync-hints.controller.d.ts +4 -0
  152. package/dist/core/modules/sync/core-sync-hints.controller.js +55 -0
  153. package/dist/core/modules/sync/core-sync-hints.controller.js.map +1 -0
  154. package/dist/core/modules/sync/core-sync-hints.service.d.ts +28 -0
  155. package/dist/core/modules/sync/core-sync-hints.service.js +155 -0
  156. package/dist/core/modules/sync/core-sync-hints.service.js.map +1 -0
  157. package/dist/core/modules/sync/core-sync-infrastructure.models.d.ts +2 -0
  158. package/dist/core/modules/sync/core-sync-infrastructure.models.js +17 -0
  159. package/dist/core/modules/sync/core-sync-infrastructure.models.js.map +1 -0
  160. package/dist/core/modules/sync/core-sync-mutation.store.d.ts +43 -0
  161. package/dist/core/modules/sync/core-sync-mutation.store.js +88 -0
  162. package/dist/core/modules/sync/core-sync-mutation.store.js.map +1 -0
  163. package/dist/core/modules/sync/core-sync-state.store.d.ts +18 -0
  164. package/dist/core/modules/sync/core-sync-state.store.js +64 -0
  165. package/dist/core/modules/sync/core-sync-state.store.js.map +1 -0
  166. package/dist/core/modules/sync/core-sync.constants.d.ts +28 -0
  167. package/dist/core/modules/sync/core-sync.constants.js +23 -0
  168. package/dist/core/modules/sync/core-sync.constants.js.map +1 -0
  169. package/dist/core/modules/sync/core-sync.controller.d.ts +8 -0
  170. package/dist/core/modules/sync/core-sync.controller.js +79 -0
  171. package/dist/core/modules/sync/core-sync.controller.js.map +1 -0
  172. package/dist/core/modules/sync/core-sync.decorators.d.ts +12 -0
  173. package/dist/core/modules/sync/core-sync.decorators.js +28 -0
  174. package/dist/core/modules/sync/core-sync.decorators.js.map +1 -0
  175. package/dist/core/modules/sync/core-sync.module.d.ts +16 -0
  176. package/dist/core/modules/sync/core-sync.module.js +50 -0
  177. package/dist/core/modules/sync/core-sync.module.js.map +1 -0
  178. package/dist/core/modules/sync/core-sync.resolver.d.ts +9 -0
  179. package/dist/core/modules/sync/core-sync.resolver.js +46 -0
  180. package/dist/core/modules/sync/core-sync.resolver.js.map +1 -0
  181. package/dist/core/modules/sync/core-sync.service.d.ts +143 -0
  182. package/dist/core/modules/sync/core-sync.service.js +1237 -0
  183. package/dist/core/modules/sync/core-sync.service.js.map +1 -0
  184. package/dist/core/modules/sync/interfaces/core-sync.interfaces.d.ts +56 -0
  185. package/dist/core/modules/sync/interfaces/core-sync.interfaces.js +2 -0
  186. package/dist/core/modules/sync/interfaces/core-sync.interfaces.js.map +1 -0
  187. package/dist/core/modules/sync/models/core-sync-hint.model.d.ts +4 -0
  188. package/dist/core/modules/sync/models/core-sync-hint.model.js +30 -0
  189. package/dist/core/modules/sync/models/core-sync-hint.model.js.map +1 -0
  190. package/dist/core/modules/tenant/core-tenant.guard.js +14 -0
  191. package/dist/core/modules/tenant/core-tenant.guard.js.map +1 -1
  192. package/dist/core/modules/tenant/core-tenant.service.d.ts +21 -1
  193. package/dist/core/modules/tenant/core-tenant.service.js +153 -1
  194. package/dist/core/modules/tenant/core-tenant.service.js.map +1 -1
  195. package/dist/core.module.js +14 -0
  196. package/dist/core.module.js.map +1 -1
  197. package/dist/index.d.ts +16 -0
  198. package/dist/index.js +16 -0
  199. package/dist/index.js.map +1 -1
  200. package/dist/server/modules/error-code/error-codes.d.ts +8 -0
  201. package/dist/server/modules/sync-note/inputs/sync-note-create.input.d.ts +4 -0
  202. package/dist/server/modules/sync-note/inputs/sync-note-create.input.js +27 -0
  203. package/dist/server/modules/sync-note/inputs/sync-note-create.input.js.map +1 -0
  204. package/dist/server/modules/sync-note/inputs/sync-note.input.d.ts +6 -0
  205. package/dist/server/modules/sync-note/inputs/sync-note.input.js +37 -0
  206. package/dist/server/modules/sync-note/inputs/sync-note.input.js.map +1 -0
  207. package/dist/server/modules/sync-note/sync-note.model.d.ts +10 -0
  208. package/dist/server/modules/sync-note/sync-note.model.js +73 -0
  209. package/dist/server/modules/sync-note/sync-note.model.js.map +1 -0
  210. package/dist/server/modules/sync-note/sync-note.module.d.ts +2 -0
  211. package/dist/server/modules/sync-note/sync-note.module.js +21 -0
  212. package/dist/server/modules/sync-note/sync-note.module.js.map +1 -0
  213. package/dist/server/modules/sync-note/sync-note.service.d.ts +10 -0
  214. package/dist/server/modules/sync-note/sync-note.service.js +35 -0
  215. package/dist/server/modules/sync-note/sync-note.service.js.map +1 -0
  216. package/dist/test/test.helper.d.ts +1 -0
  217. package/dist/test/test.helper.js +9 -2
  218. package/dist/test/test.helper.js.map +1 -1
  219. package/docs/REQUEST-LIFECYCLE.md +4 -2
  220. package/docs/error-codes.md +14 -0
  221. package/docs/offline-sync-protocol.md +111 -68
  222. package/docs/security-overrides.md +14 -0
  223. package/migration-guides/12.0.x-to-12.1.x.md +0 -1
  224. package/migration-guides/12.1.x-to-12.2.x.md +154 -0
  225. package/migration-guides/12.2.x-to-12.3.x.md +440 -0
  226. package/package.json +23 -21
  227. package/src/config.env.ts +6 -2
  228. package/src/core/common/helpers/graphql-ws-connection.helper.ts +32 -4
  229. package/src/core/common/interfaces/server-options.interface.ts +229 -8
  230. package/src/core/common/interfaces/service-options.interface.ts +15 -0
  231. package/src/core/common/persistence/core-persistence.module.ts +21 -2
  232. package/src/core/common/persistence/data-source.runtime.ts +5 -2
  233. package/src/core/common/persistence/data-store.interface.ts +65 -12
  234. package/src/core/common/persistence/id-format.ts +26 -0
  235. package/src/core/common/persistence/model-descriptor.interface.ts +12 -0
  236. package/src/core/common/persistence/model-metadata.registry.ts +31 -2
  237. package/src/core/common/persistence/mongo/sync-schema.plugin.ts +508 -0
  238. package/src/core/common/persistence/mongoose-data-store.ts +171 -35
  239. package/src/core/common/persistence/persisted-model.decorator.ts +26 -0
  240. package/src/core/common/persistence/policies/sync.policy.ts +121 -0
  241. package/src/core/common/persistence/sql/mysql/mysql-data-store.ts +108 -30
  242. package/src/core/common/persistence/sql/mysql/mysql-schema.compiler.ts +107 -4
  243. package/src/core/common/persistence/sql/mysql/mysql-schema.migrator.ts +129 -3
  244. package/src/core/common/persistence/sql/postgres/postgres-schema.compiler.ts +74 -2
  245. package/src/core/common/persistence/sql/postgres/postgres-schema.migrator.ts +139 -7
  246. package/src/core/common/persistence/sql/sql-data-store.ts +325 -44
  247. package/src/core/common/persistence/sql/sql-errors.ts +5 -1
  248. package/src/core/common/persistence/sync-access.registry.ts +50 -0
  249. package/src/core/common/persistence/sync-model.ts +270 -0
  250. package/src/core/common/services/crud.service.ts +257 -19
  251. package/src/core/modules/ai/INTEGRATION-CHECKLIST.md +36 -15
  252. package/src/core/modules/ai/README.md +163 -25
  253. package/src/core/modules/ai/core-ai-mcp.controller.ts +48 -1
  254. package/src/core/modules/ai/core-ai.constants.ts +6 -0
  255. package/src/core/modules/ai/core-ai.controller.ts +36 -1
  256. package/src/core/modules/ai/core-ai.module.ts +12 -0
  257. package/src/core/modules/ai/core-ai.resolver.ts +36 -0
  258. package/src/core/modules/ai/helpers/ai-mcp-oauth-consent.helper.ts +35 -4
  259. package/src/core/modules/ai/helpers/ai-mcp-oauth.helper.ts +68 -1
  260. package/src/core/modules/ai/helpers/ai-tool-authorization.helper.ts +99 -0
  261. package/src/core/modules/ai/index.ts +18 -0
  262. package/src/core/modules/ai/inputs/core-ai-settings.input.ts +24 -0
  263. package/src/core/modules/ai/interfaces/ai-hook.interface.ts +1 -1
  264. package/src/core/modules/ai/interfaces/ai-tool.interface.ts +38 -26
  265. package/src/core/modules/ai/models/core-ai-mode.model.ts +1 -1
  266. package/src/core/modules/ai/models/core-ai-settings.model.ts +23 -0
  267. package/src/core/modules/ai/models/core-ai-tool-policy.model.ts +1 -1
  268. package/src/core/modules/ai/models/core-ai-user-setting.model.ts +46 -0
  269. package/src/core/modules/ai/services/core-ai-conversation.service.ts +31 -6
  270. package/src/core/modules/ai/services/core-ai-mcp-oauth.service.ts +12 -9
  271. package/src/core/modules/ai/services/core-ai-mcp.service.ts +206 -13
  272. package/src/core/modules/ai/services/core-ai-prompt-builder.service.ts +13 -6
  273. package/src/core/modules/ai/services/core-ai-user-setting.service.ts +85 -0
  274. package/src/core/modules/ai/services/core-ai.service.ts +134 -35
  275. package/src/core/modules/api-token/README.md +4 -2
  276. package/src/core/modules/better-auth/CUSTOMIZATION.md +1 -1
  277. package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +7 -0
  278. package/src/core/modules/better-auth/README.md +32 -1
  279. package/src/core/modules/better-auth/better-auth.config.ts +12 -1
  280. package/src/core/modules/better-auth/core-better-auth-email-verification.service.ts +5 -2
  281. package/src/core/modules/better-auth/core-better-auth-path-guard.middleware.ts +85 -0
  282. package/src/core/modules/better-auth/core-better-auth-rate-limit.middleware.ts +5 -2
  283. package/src/core/modules/better-auth/core-better-auth-rate-limiter.service.ts +14 -7
  284. package/src/core/modules/better-auth/core-better-auth.module.ts +12 -2
  285. package/src/core/modules/better-auth/index.ts +1 -0
  286. package/src/core/modules/error-code/error-codes.ts +77 -0
  287. package/src/core/modules/migrate/sql-migration.helper.ts +141 -7
  288. package/src/core/modules/sync/INTEGRATION-CHECKLIST.md +95 -0
  289. package/src/core/modules/sync/README.md +198 -0
  290. package/src/core/modules/sync/SECURITY.md +65 -0
  291. package/src/core/modules/sync/core-sync-base.controller.ts +43 -0
  292. package/src/core/modules/sync/core-sync-cursor.ts +117 -0
  293. package/src/core/modules/sync/core-sync-hints.controller.ts +52 -0
  294. package/src/core/modules/sync/core-sync-hints.service.ts +178 -0
  295. package/src/core/modules/sync/core-sync-infrastructure.models.ts +40 -0
  296. package/src/core/modules/sync/core-sync-mutation.store.ts +146 -0
  297. package/src/core/modules/sync/core-sync-state.store.ts +89 -0
  298. package/src/core/modules/sync/core-sync.constants.ts +51 -0
  299. package/src/core/modules/sync/core-sync.controller.ts +68 -0
  300. package/src/core/modules/sync/core-sync.decorators.ts +84 -0
  301. package/src/core/modules/sync/core-sync.module.ts +75 -0
  302. package/src/core/modules/sync/core-sync.resolver.ts +35 -0
  303. package/src/core/modules/sync/core-sync.service.ts +1773 -0
  304. package/src/core/modules/sync/interfaces/core-sync.interfaces.ts +85 -0
  305. package/src/core/modules/sync/models/core-sync-hint.model.ts +18 -0
  306. package/src/core/modules/tenant/INTEGRATION-CHECKLIST.md +12 -1
  307. package/src/core/modules/tenant/README.md +49 -3
  308. package/src/core/modules/tenant/core-tenant.guard.ts +26 -2
  309. package/src/core/modules/tenant/core-tenant.service.ts +287 -2
  310. package/src/core.module.ts +25 -0
  311. package/src/index.ts +21 -0
  312. package/src/server/modules/sync-note/inputs/sync-note-create.input.ts +14 -0
  313. package/src/server/modules/sync-note/inputs/sync-note.input.ts +23 -0
  314. package/src/server/modules/sync-note/sync-note.model.ts +77 -0
  315. package/src/server/modules/sync-note/sync-note.module.ts +16 -0
  316. package/src/server/modules/sync-note/sync-note.service.ts +25 -0
  317. package/src/test/test.helper.ts +17 -3
@@ -54,6 +54,11 @@ export interface FindOptions {
54
54
  * Not combinable with `select`, as MongoDB does not combine them either.
55
55
  */
56
56
  exclude?: readonly string[];
57
+ /**
58
+ * Read tombstones too (a synchronized model's deleted records, `deletedAt` set). Every read of such a model leaves
59
+ * them out unless asked — only the sync module asks. No effect on other models.
60
+ */
61
+ includeTombstones?: boolean;
57
62
  /** Field names to return; the id is always returned */
58
63
  select?: readonly string[];
59
64
  skip?: number;
@@ -61,7 +66,15 @@ export interface FindOptions {
61
66
  sort?: Record<string, -1 | 1>;
62
67
  }
63
68
 
69
+ /** Options of a read that has no paging (`count`, `distinct`, `findById`) */
70
+ export interface ReadOptions {
71
+ /** See `FindOptions.includeTombstones` */
72
+ includeTombstones?: boolean;
73
+ }
74
+
64
75
  export interface UpdateOptions {
76
+ /** Match tombstones too (a synchronized model's deleted records) — see `FindOptions.includeTombstones` */
77
+ includeTombstones?: boolean;
65
78
  /**
66
79
  * `false` leaves the update time (`updatedAt`) as it is — for bookkeeping writes such as a last-used stamp, which
67
80
  * must not read as a change of the record (Mongoose's `timestamps: false`). @default true
@@ -69,6 +82,17 @@ export interface UpdateOptions {
69
82
  timestamps?: boolean;
70
83
  }
71
84
 
85
+ export interface DeleteOptions {
86
+ /**
87
+ * Remove the record for good. A synchronized model's delete otherwise leaves a tombstone (`deletedAt` set, the
88
+ * content cleared, the version incremented), which is how clients learn of it; a hard delete is the tombstone purge's
89
+ * (with `includeTombstones`). No effect on other models, whose delete always removes.
90
+ */
91
+ hardDelete?: boolean;
92
+ /** Match tombstones too — see `FindOptions.includeTombstones` */
93
+ includeTombstones?: boolean;
94
+ }
95
+
72
96
  export interface PushOptions {
73
97
  /** Insert position (MongoDB `$position`) */
74
98
  position?: number;
@@ -99,28 +123,57 @@ export interface StoreCapabilities {
99
123
  textSearch: boolean;
100
124
  /** Multi-statement transactions */
101
125
  transactions: boolean;
102
- /** Format of generated ids */
103
- idType: 'objectId';
126
+ /** Format of the model's ids — `uuidv7` only for a synchronized model that declares it */
127
+ idType: 'objectId' | 'uuidv7';
128
+ /**
129
+ * How a synchronized model orders its changes (offline-sync plan §3.4): `seq` — the commit-ordered `syncSeq` (SQL);
130
+ * `clock` — the server clock `syncAt`, read with a window (MongoDB). Absent for a model that is not synchronized.
131
+ */
132
+ changeOrder?: 'clock' | 'seq';
133
+ }
134
+
135
+ /** The database's clock as a pull over `changeOrder: 'clock'` reads it (offline-sync plan §3.4) */
136
+ export interface ChangeClock {
137
+ /** The database server's current time */
138
+ now: Date;
139
+ /**
140
+ * The window W: how long a write may take from its stamp until it is visible. A pull run starts this far below the
141
+ * previous run's start, so a change stamped before that start but committed after it is not passed.
142
+ */
143
+ windowMs: number;
104
144
  }
105
145
 
106
146
  export interface DataStore<T = Record<string, any>> {
107
147
  readonly capabilities: StoreCapabilities;
148
+ /**
149
+ * The database's clock and the window W of a synchronized model whose change order is the clock
150
+ * (`capabilities.changeOrder === 'clock'`); absent on every other store. What the sync module reads instead of
151
+ * asking for the driver.
152
+ */
153
+ changeClock?(): Promise<ChangeClock>;
108
154
  /** The database behind the store (`mongodb`, `postgres`, …) */
109
155
  readonly driver: string;
110
156
  readonly modelName: string;
111
157
 
112
- count(where?: Where<T>): Promise<number>;
113
- deleteById(id: string): Promise<null | StoredRecord<T>>;
114
- /** Remove every record matching `where`; returns how many were removed. */
115
- deleteMany(where: Where<T>): Promise<number>;
158
+ count(where?: Where<T>, options?: ReadOptions): Promise<number>;
159
+ /**
160
+ * Remove the record and return it as it was; `null` when there is none. On a synchronized model: turn it into a
161
+ * tombstone instead, unless `hardDelete` (see `DeleteOptions`).
162
+ */
163
+ deleteById(id: string, options?: DeleteOptions): Promise<null | StoredRecord<T>>;
164
+ /** Remove every record matching `where`; returns how many were removed (tombstoned on a synchronized model). */
165
+ deleteMany(where: Where<T>, options?: DeleteOptions): Promise<number>;
116
166
  /**
117
167
  * Remove the first record matching `where`, atomically (MongoDB's `findOneAndDelete`), and return it; `null` when
118
- * nothing matches.
168
+ * nothing matches (tombstoned on a synchronized model).
119
169
  */
120
- deleteOne(where: Where<T>): Promise<null | StoredRecord<T>>;
121
- distinct(field: string, where?: Where<T>): Promise<unknown[]>;
170
+ deleteOne(where: Where<T>, options?: DeleteOptions): Promise<null | StoredRecord<T>>;
171
+ distinct(field: string, where?: Where<T>, options?: ReadOptions): Promise<unknown[]>;
122
172
  find(where?: Where<T>, options?: FindOptions): Promise<StoredRecord<T>[]>;
123
- findById(id: string, options?: Pick<FindOptions, 'exclude' | 'select'>): Promise<null | StoredRecord<T>>;
173
+ findById(
174
+ id: string,
175
+ options?: Pick<FindOptions, 'exclude' | 'includeTombstones' | 'select'>,
176
+ ): Promise<null | StoredRecord<T>>;
124
177
  findOne(where: Where<T>, options?: Omit<FindOptions, 'limit' | 'skip'>): Promise<null | StoredRecord<T>>;
125
178
  insert(record: Partial<T>): Promise<StoredRecord<T>>;
126
179
  /**
@@ -145,11 +198,11 @@ export interface DataStore<T = Record<string, any>> {
145
198
  /** Apply `update` to the record and return it as stored afterwards; `null` when there is none. */
146
199
  updateById(id: string, update: DataStoreUpdate<T>, options?: UpdateOptions): Promise<null | StoredRecord<T>>;
147
200
  /** Apply `update` to every record matching `where`; returns how many records matched. */
148
- updateMany(where: Where<T>, update: DataStoreUpdate<T>): Promise<number>;
201
+ updateMany(where: Where<T>, update: DataStoreUpdate<T>, options?: UpdateOptions): Promise<number>;
149
202
  /**
150
203
  * Apply `update` to the first record matching `where`, atomically: the record still matches when it is changed, and
151
204
  * concurrent callers never change the same record on the strength of one match (MongoDB's `findOneAndUpdate`).
152
205
  * Returns the record as stored afterwards; `null` when nothing matches.
153
206
  */
154
- updateOne(where: Where<T>, update: DataStoreUpdate<T>): Promise<null | StoredRecord<T>>;
207
+ updateOne(where: Where<T>, update: DataStoreUpdate<T>, options?: UpdateOptions): Promise<null | StoredRecord<T>>;
155
208
  }
@@ -41,3 +41,29 @@ export function generateId(): string {
41
41
  bytes.writeUIntBE(counter, 9, 3);
42
42
  return bytes.toString('hex');
43
43
  }
44
+
45
+ /**
46
+ * A uuidv7 as the framework stores it (plan §3.5): lowercase, hyphenated, version nibble `7`, variant `8`–`b`. The id
47
+ * format a synchronized model may choose instead of the ObjectId (`@PersistedModel({ sync: { idFormat: 'uuidv7' } })`).
48
+ */
49
+ const UUID_V7 = /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
50
+
51
+ /** Whether a value is a uuidv7 in the stored form — lowercase only, so one id has exactly one spelling */
52
+ export function isUuidV7(value: unknown): value is string {
53
+ return typeof value === 'string' && UUID_V7.test(value);
54
+ }
55
+
56
+ /**
57
+ * A new uuidv7 (RFC 9562): 48 bits of milliseconds, then 74 random bits — sortable by creation time like an ObjectId,
58
+ * but with nothing after the timestamp that one observed id would let anybody predict.
59
+ */
60
+ export function generateUuidV7(): string {
61
+ const bytes = randomBytes(16);
62
+ const millis = Date.now();
63
+ bytes.writeUIntBE(Math.floor(millis / 0x10000), 0, 4);
64
+ bytes.writeUInt16BE(millis % 0x10000, 4);
65
+ bytes[6] = (bytes[6] & 0x0f) | 0x70;
66
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
67
+ const hex = bytes.toString('hex');
68
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
69
+ }
@@ -77,12 +77,24 @@ export interface IndexDescriptor {
77
77
  options: Record<string, unknown>;
78
78
  }
79
79
 
80
+ /** The id format of a synchronized model: one per model, never mixed (offline-sync plan §3.5) */
81
+ export type SyncIdFormat = 'objectId' | 'uuidv7';
82
+
83
+ /** How a model is synchronized to offline clients — see `sync-model.ts` */
84
+ export interface SyncDescriptor {
85
+ idFormat: SyncIdFormat;
86
+ /** User-id fields a tombstone keeps besides `tenantId` */
87
+ scope: readonly string[];
88
+ }
89
+
80
90
  export interface ModelDescriptor {
81
91
  /** Explicit collection / table name, when the model declares one */
82
92
  collection?: string;
83
93
  fields: Record<string, FieldDescriptor>;
84
94
  indexes: IndexDescriptor[];
85
95
  name: string;
96
+ /** Present when the model is synchronized (`@PersistedModel({ sync })`); absent for every other model */
97
+ sync?: SyncDescriptor;
86
98
  /** Whether the model carries a `tenantId` — the same criterion the tenant plugin uses */
87
99
  tenantScoped: boolean;
88
100
  /** `createdAt` / `updatedAt` maintenance: `true`, `false`, or the configured field names */
@@ -2,6 +2,7 @@ import type { FieldDescriptor, FieldKind, IndexDescriptor, ModelDescriptor } fro
2
2
  import { declaredSchemaView } from './mongo/declared-schema.view.js';
3
3
  import { type DeclaredSchema, isDeclaredSchema } from './mongo/model-declarations.js';
4
4
  import { SchemaFactory } from './mongo/mongoose-compat.js';
5
+ import { type SyncDescriptor, withSyncDescriptor } from './sync-model.js';
5
6
 
6
7
  /**
7
8
  * Registry of database-neutral model descriptors.
@@ -70,12 +71,40 @@ export function describeModelClass(modelClass: abstract new (...args: any[]) =>
70
71
  return descriptor;
71
72
  }
72
73
 
74
+ /**
75
+ * The descriptor of a schema as it was declared, per schema object and model name. A synchronized model's Mongoose
76
+ * schema gains its system paths and partial indexes once it is registered (`mongo/sync-schema.plugin.ts`); a second
77
+ * registration of the same schema must describe what was declared, not what the plugin added.
78
+ */
79
+ const declaredDescriptors = new WeakMap<object, Map<string, ModelDescriptor>>();
80
+
73
81
  /**
74
82
  * Register the schema a model is persisted with, under its model name. A later registration under
75
83
  * the same name replaces the earlier one — the last `forFeature` wins, as it does in Mongoose.
84
+ *
85
+ * `sync` makes it the descriptor of a synchronized model (`sync-model.ts`).
76
86
  */
77
- export function registerModelSchema(name: string, schema: DeclaredSchema | SchemaLike): ModelDescriptor {
78
- const descriptor = describeSchema(name, schema);
87
+ export function registerModelSchema(
88
+ name: string,
89
+ schema: DeclaredSchema | SchemaLike,
90
+ sync?: SyncDescriptor,
91
+ ): ModelDescriptor {
92
+ let descriptor: ModelDescriptor;
93
+ if (sync) {
94
+ let byName = declaredDescriptors.get(schema);
95
+ if (!byName) {
96
+ byName = new Map();
97
+ declaredDescriptors.set(schema, byName);
98
+ }
99
+ let declared = byName.get(name);
100
+ if (!declared) {
101
+ declared = describeSchema(name, schema);
102
+ byName.set(name, declared);
103
+ }
104
+ descriptor = withSyncDescriptor(declared, sync);
105
+ } else {
106
+ descriptor = describeSchema(name, schema);
107
+ }
79
108
  descriptorsByName.set(name, descriptor);
80
109
  return descriptor;
81
110
  }