@lenne.tech/nest-server 12.1.0 → 12.2.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.
- package/.claude/rules/architecture.md +1 -0
- package/.claude/rules/better-auth.md +18 -6
- package/.claude/rules/configurable-features.md +5 -4
- package/.claude/rules/package-management.md +16 -1
- package/.claude/rules/persistence.md +26 -0
- package/.claude/rules/testing.md +102 -28
- package/CLAUDE.md +3 -2
- package/FRAMEWORK-API.md +17 -2
- package/README.md +24 -3
- package/dist/core/common/helpers/file.helper.js +3 -4
- package/dist/core/common/helpers/file.helper.js.map +1 -1
- package/dist/core/common/helpers/graphql-ws-connection.helper.js.map +1 -1
- package/dist/core/common/interfaces/server-options.interface.d.ts +41 -0
- package/dist/core/common/interfaces/service-options.interface.d.ts +3 -0
- package/dist/core/common/persistence/core-persistence.module.js +12 -2
- package/dist/core/common/persistence/core-persistence.module.js.map +1 -1
- package/dist/core/common/persistence/data-source.runtime.js +14 -19
- package/dist/core/common/persistence/data-source.runtime.js.map +1 -1
- package/dist/core/common/persistence/data-store.interface.d.ts +24 -9
- package/dist/core/common/persistence/id-format.d.ts +2 -0
- package/dist/core/common/persistence/id-format.js +14 -0
- package/dist/core/common/persistence/id-format.js.map +1 -1
- package/dist/core/common/persistence/model-descriptor.interface.d.ts +6 -0
- package/dist/core/common/persistence/model-metadata.registry.d.ts +2 -1
- package/dist/core/common/persistence/model-metadata.registry.js +20 -2
- package/dist/core/common/persistence/model-metadata.registry.js.map +1 -1
- package/dist/core/common/persistence/mongo/sync-schema.plugin.d.ts +18 -0
- package/dist/core/common/persistence/mongo/sync-schema.plugin.js +368 -0
- package/dist/core/common/persistence/mongo/sync-schema.plugin.js.map +1 -0
- package/dist/core/common/persistence/mongoose-data-store.d.ts +19 -9
- package/dist/core/common/persistence/mongoose-data-store.js +107 -31
- package/dist/core/common/persistence/mongoose-data-store.js.map +1 -1
- package/dist/core/common/persistence/persisted-model.decorator.d.ts +3 -0
- package/dist/core/common/persistence/persisted-model.decorator.js +9 -0
- package/dist/core/common/persistence/persisted-model.decorator.js.map +1 -1
- package/dist/core/common/persistence/persistence-runtime.registry.d.ts +5 -1
- package/dist/core/common/persistence/persistence-runtime.registry.js.map +1 -1
- package/dist/core/common/persistence/policies/sync.policy.d.ts +17 -0
- package/dist/core/common/persistence/policies/sync.policy.js +77 -0
- package/dist/core/common/persistence/policies/sync.policy.js.map +1 -0
- package/dist/core/common/persistence/sql/mysql/mysql-data-store.d.ts +12 -8
- package/dist/core/common/persistence/sql/mysql/mysql-data-store.js +82 -29
- package/dist/core/common/persistence/sql/mysql/mysql-data-store.js.map +1 -1
- package/dist/core/common/persistence/sql/mysql/mysql-schema.compiler.d.ts +10 -0
- package/dist/core/common/persistence/sql/mysql/mysql-schema.compiler.js +61 -4
- package/dist/core/common/persistence/sql/mysql/mysql-schema.compiler.js.map +1 -1
- package/dist/core/common/persistence/sql/mysql/mysql-schema.migrator.d.ts +2 -0
- package/dist/core/common/persistence/sql/mysql/mysql-schema.migrator.js +145 -4
- package/dist/core/common/persistence/sql/mysql/mysql-schema.migrator.js.map +1 -1
- package/dist/core/common/persistence/sql/postgres/postgres-schema.compiler.d.ts +10 -0
- package/dist/core/common/persistence/sql/postgres/postgres-schema.compiler.js +41 -2
- package/dist/core/common/persistence/sql/postgres/postgres-schema.compiler.js.map +1 -1
- package/dist/core/common/persistence/sql/postgres/postgres-schema.migrator.js +98 -10
- package/dist/core/common/persistence/sql/postgres/postgres-schema.migrator.js.map +1 -1
- package/dist/core/common/persistence/sql/sql-data-store.d.ts +38 -14
- package/dist/core/common/persistence/sql/sql-data-store.js +212 -38
- package/dist/core/common/persistence/sql/sql-data-store.js.map +1 -1
- package/dist/core/common/persistence/sql/sql-dialect.d.ts +2 -0
- package/dist/core/common/persistence/sql/sql-dialect.js +14 -2
- package/dist/core/common/persistence/sql/sql-dialect.js.map +1 -1
- package/dist/core/common/persistence/sql/sql-errors.d.ts +2 -1
- package/dist/core/common/persistence/sql/sql-errors.js +3 -1
- package/dist/core/common/persistence/sql/sql-errors.js.map +1 -1
- package/dist/core/common/persistence/sync-access.registry.d.ts +17 -0
- package/dist/core/common/persistence/sync-access.registry.js +8 -0
- package/dist/core/common/persistence/sync-access.registry.js.map +1 -0
- package/dist/core/common/persistence/sync-model.d.ts +29 -0
- package/dist/core/common/persistence/sync-model.js +138 -0
- package/dist/core/common/persistence/sync-model.js.map +1 -0
- package/dist/core/common/services/core-cron-jobs.service.d.ts +27 -0
- package/dist/core/common/services/core-cron-jobs.service.js +269 -13
- package/dist/core/common/services/core-cron-jobs.service.js.map +1 -1
- package/dist/core/common/services/core-redis-pubsub.js +5 -5
- package/dist/core/common/services/core-redis-pubsub.js.map +1 -1
- package/dist/core/common/services/core-redis.service.d.ts +6 -0
- package/dist/core/common/services/core-redis.service.js +57 -0
- package/dist/core/common/services/core-redis.service.js.map +1 -1
- package/dist/core/common/services/crud.service.d.ts +13 -1
- package/dist/core/common/services/crud.service.js +174 -16
- package/dist/core/common/services/crud.service.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth-sql.helper.d.ts +1 -0
- package/dist/core/modules/better-auth/better-auth-sql.helper.js +41 -14
- package/dist/core/modules/better-auth/better-auth-sql.helper.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth-sql.store.d.ts +4 -7
- package/dist/core/modules/better-auth/core-better-auth-sql.store.js +23 -16
- package/dist/core/modules/better-auth/core-better-auth-sql.store.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth-user.mapper.d.ts +12 -2
- package/dist/core/modules/better-auth/core-better-auth-user.mapper.js +82 -5
- package/dist/core/modules/better-auth/core-better-auth-user.mapper.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.module.js +1 -1
- package/dist/core/modules/better-auth/core-better-auth.module.js.map +1 -1
- package/dist/core/modules/error-code/error-codes.d.ts +54 -0
- package/dist/core/modules/error-code/error-codes.js +48 -0
- package/dist/core/modules/error-code/error-codes.js.map +1 -1
- package/dist/core/modules/hub/hub-buffer.js +3 -4
- package/dist/core/modules/hub/hub-buffer.js.map +1 -1
- package/dist/core/modules/migrate/index.js.map +1 -1
- package/dist/core/modules/migrate/migration-runner.d.ts +6 -0
- package/dist/core/modules/migrate/migration-runner.js +28 -2
- package/dist/core/modules/migrate/migration-runner.js.map +1 -1
- package/dist/core/modules/migrate/mongo-state-store.d.ts +0 -1
- package/dist/core/modules/migrate/mongo-state-store.js +0 -5
- package/dist/core/modules/migrate/mongo-state-store.js.map +1 -1
- package/dist/core/modules/migrate/sql-migration.helper.d.ts +15 -1
- package/dist/core/modules/migrate/sql-migration.helper.js +90 -5
- package/dist/core/modules/migrate/sql-migration.helper.js.map +1 -1
- package/dist/core/modules/sync/core-sync-base.controller.d.ts +7 -0
- package/dist/core/modules/sync/core-sync-base.controller.js +44 -0
- package/dist/core/modules/sync/core-sync-base.controller.js.map +1 -0
- package/dist/core/modules/sync/core-sync-cursor.d.ts +19 -0
- package/dist/core/modules/sync/core-sync-cursor.js +77 -0
- package/dist/core/modules/sync/core-sync-cursor.js.map +1 -0
- package/dist/core/modules/sync/core-sync-hints.controller.d.ts +4 -0
- package/dist/core/modules/sync/core-sync-hints.controller.js +55 -0
- package/dist/core/modules/sync/core-sync-hints.controller.js.map +1 -0
- package/dist/core/modules/sync/core-sync-hints.service.d.ts +28 -0
- package/dist/core/modules/sync/core-sync-hints.service.js +155 -0
- package/dist/core/modules/sync/core-sync-hints.service.js.map +1 -0
- package/dist/core/modules/sync/core-sync-infrastructure.models.d.ts +2 -0
- package/dist/core/modules/sync/core-sync-infrastructure.models.js +17 -0
- package/dist/core/modules/sync/core-sync-infrastructure.models.js.map +1 -0
- package/dist/core/modules/sync/core-sync-mutation.store.d.ts +43 -0
- package/dist/core/modules/sync/core-sync-mutation.store.js +88 -0
- package/dist/core/modules/sync/core-sync-mutation.store.js.map +1 -0
- package/dist/core/modules/sync/core-sync-state.store.d.ts +18 -0
- package/dist/core/modules/sync/core-sync-state.store.js +64 -0
- package/dist/core/modules/sync/core-sync-state.store.js.map +1 -0
- package/dist/core/modules/sync/core-sync.constants.d.ts +28 -0
- package/dist/core/modules/sync/core-sync.constants.js +23 -0
- package/dist/core/modules/sync/core-sync.constants.js.map +1 -0
- package/dist/core/modules/sync/core-sync.controller.d.ts +8 -0
- package/dist/core/modules/sync/core-sync.controller.js +79 -0
- package/dist/core/modules/sync/core-sync.controller.js.map +1 -0
- package/dist/core/modules/sync/core-sync.decorators.d.ts +12 -0
- package/dist/core/modules/sync/core-sync.decorators.js +28 -0
- package/dist/core/modules/sync/core-sync.decorators.js.map +1 -0
- package/dist/core/modules/sync/core-sync.module.d.ts +16 -0
- package/dist/core/modules/sync/core-sync.module.js +50 -0
- package/dist/core/modules/sync/core-sync.module.js.map +1 -0
- package/dist/core/modules/sync/core-sync.resolver.d.ts +9 -0
- package/dist/core/modules/sync/core-sync.resolver.js +46 -0
- package/dist/core/modules/sync/core-sync.resolver.js.map +1 -0
- package/dist/core/modules/sync/core-sync.service.d.ts +142 -0
- package/dist/core/modules/sync/core-sync.service.js +1208 -0
- package/dist/core/modules/sync/core-sync.service.js.map +1 -0
- package/dist/core/modules/sync/interfaces/core-sync.interfaces.d.ts +56 -0
- package/dist/core/modules/sync/interfaces/core-sync.interfaces.js +2 -0
- package/dist/core/modules/sync/interfaces/core-sync.interfaces.js.map +1 -0
- package/dist/core/modules/sync/models/core-sync-hint.model.d.ts +4 -0
- package/dist/core/modules/sync/models/core-sync-hint.model.js +30 -0
- package/dist/core/modules/sync/models/core-sync-hint.model.js.map +1 -0
- package/dist/core/modules/tenant/core-tenant.guard.js +8 -3
- package/dist/core/modules/tenant/core-tenant.guard.js.map +1 -1
- package/dist/core.module.js +14 -0
- package/dist/core.module.js.map +1 -1
- package/dist/index.d.ts +16 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/server/modules/error-code/error-codes.d.ts +6 -0
- package/dist/server/modules/sync-note/inputs/sync-note-create.input.d.ts +4 -0
- package/dist/server/modules/sync-note/inputs/sync-note-create.input.js +27 -0
- package/dist/server/modules/sync-note/inputs/sync-note-create.input.js.map +1 -0
- package/dist/server/modules/sync-note/inputs/sync-note.input.d.ts +6 -0
- package/dist/server/modules/sync-note/inputs/sync-note.input.js +37 -0
- package/dist/server/modules/sync-note/inputs/sync-note.input.js.map +1 -0
- package/dist/server/modules/sync-note/sync-note.model.d.ts +10 -0
- package/dist/server/modules/sync-note/sync-note.model.js +73 -0
- package/dist/server/modules/sync-note/sync-note.model.js.map +1 -0
- package/dist/server/modules/sync-note/sync-note.module.d.ts +2 -0
- package/dist/server/modules/sync-note/sync-note.module.js +21 -0
- package/dist/server/modules/sync-note/sync-note.module.js.map +1 -0
- package/dist/server/modules/sync-note/sync-note.service.d.ts +10 -0
- package/dist/server/modules/sync-note/sync-note.service.js +35 -0
- package/dist/server/modules/sync-note/sync-note.service.js.map +1 -0
- package/docs/REQUEST-LIFECYCLE.md +3 -2
- package/docs/choosing-a-database.md +7 -4
- package/docs/offline-sync-protocol.md +410 -0
- package/docs/security-overrides.md +14 -0
- package/migration-guides/12.0.x-to-12.1.x.md +9 -4
- package/migration-guides/12.1.0-to-12.1.1.md +125 -0
- package/migration-guides/12.1.x-to-12.2.x.md +154 -0
- package/package.json +10 -8
- package/src/core/common/helpers/file.helper.ts +7 -5
- package/src/core/common/helpers/graphql-ws-connection.helper.ts +3 -2
- package/src/core/common/interfaces/cron-job-config.interface.ts +7 -2
- package/src/core/common/interfaces/server-options.interface.ts +149 -0
- package/src/core/common/interfaces/service-options.interface.ts +15 -0
- package/src/core/common/persistence/core-persistence.module.ts +21 -2
- package/src/core/common/persistence/data-source.runtime.ts +22 -23
- package/src/core/common/persistence/data-store.interface.ts +65 -12
- package/src/core/common/persistence/id-format.ts +26 -0
- package/src/core/common/persistence/model-descriptor.interface.ts +12 -0
- package/src/core/common/persistence/model-metadata.registry.ts +31 -2
- package/src/core/common/persistence/mongo/sync-schema.plugin.ts +508 -0
- package/src/core/common/persistence/mongoose-data-store.ts +171 -35
- package/src/core/common/persistence/persisted-model.decorator.ts +26 -0
- package/src/core/common/persistence/persistence-runtime.registry.ts +16 -5
- package/src/core/common/persistence/policies/sync.policy.ts +121 -0
- package/src/core/common/persistence/sql/mysql/mysql-data-store.ts +108 -30
- package/src/core/common/persistence/sql/mysql/mysql-schema.compiler.ts +107 -4
- package/src/core/common/persistence/sql/mysql/mysql-schema.migrator.ts +194 -3
- package/src/core/common/persistence/sql/postgres/postgres-schema.compiler.ts +74 -2
- package/src/core/common/persistence/sql/postgres/postgres-schema.migrator.ts +139 -7
- package/src/core/common/persistence/sql/sql-data-store.ts +325 -44
- package/src/core/common/persistence/sql/sql-dialect.ts +38 -1
- package/src/core/common/persistence/sql/sql-errors.ts +5 -1
- package/src/core/common/persistence/sql/sql-executor.interface.ts +4 -1
- package/src/core/common/persistence/sync-access.registry.ts +50 -0
- package/src/core/common/persistence/sync-model.ts +270 -0
- package/src/core/common/services/core-cron-jobs.service.ts +441 -27
- package/src/core/common/services/core-redis-pubsub.ts +8 -6
- package/src/core/common/services/core-redis.service.ts +99 -0
- package/src/core/common/services/crud.service.ts +257 -19
- package/src/core/modules/better-auth/README.md +25 -1
- package/src/core/modules/better-auth/better-auth-sql.helper.ts +56 -24
- package/src/core/modules/better-auth/better-auth.config.ts +4 -3
- package/src/core/modules/better-auth/core-better-auth-sql.store.ts +28 -21
- package/src/core/modules/better-auth/core-better-auth-user.mapper.ts +122 -6
- package/src/core/modules/better-auth/core-better-auth.module.ts +2 -2
- package/src/core/modules/error-code/error-codes.ts +59 -0
- package/src/core/modules/hub/README.md +5 -2
- package/src/core/modules/hub/hub-buffer.ts +13 -7
- package/src/core/modules/migrate/README.md +20 -11
- package/src/core/modules/migrate/index.ts +1 -0
- package/src/core/modules/migrate/migration-runner.ts +68 -3
- package/src/core/modules/migrate/mongo-state-store.ts +7 -30
- package/src/core/modules/migrate/sql-migration.helper.ts +141 -7
- package/src/core/modules/sync/INTEGRATION-CHECKLIST.md +95 -0
- package/src/core/modules/sync/README.md +188 -0
- package/src/core/modules/sync/SECURITY.md +65 -0
- package/src/core/modules/sync/core-sync-base.controller.ts +43 -0
- package/src/core/modules/sync/core-sync-cursor.ts +117 -0
- package/src/core/modules/sync/core-sync-hints.controller.ts +52 -0
- package/src/core/modules/sync/core-sync-hints.service.ts +178 -0
- package/src/core/modules/sync/core-sync-infrastructure.models.ts +40 -0
- package/src/core/modules/sync/core-sync-mutation.store.ts +146 -0
- package/src/core/modules/sync/core-sync-state.store.ts +89 -0
- package/src/core/modules/sync/core-sync.constants.ts +51 -0
- package/src/core/modules/sync/core-sync.controller.ts +68 -0
- package/src/core/modules/sync/core-sync.decorators.ts +84 -0
- package/src/core/modules/sync/core-sync.module.ts +75 -0
- package/src/core/modules/sync/core-sync.resolver.ts +35 -0
- package/src/core/modules/sync/core-sync.service.ts +1728 -0
- package/src/core/modules/sync/interfaces/core-sync.interfaces.ts +85 -0
- package/src/core/modules/sync/models/core-sync-hint.model.ts +18 -0
- package/src/core/modules/tenant/README.md +1 -0
- package/src/core/modules/tenant/core-tenant.guard.ts +16 -3
- package/src/core.module.ts +25 -0
- package/src/index.ts +21 -0
- package/src/server/modules/sync-note/inputs/sync-note-create.input.ts +14 -0
- package/src/server/modules/sync-note/inputs/sync-note.input.ts +23 -0
- package/src/server/modules/sync-note/sync-note.model.ts +77 -0
- package/src/server/modules/sync-note/sync-note.module.ts +16 -0
- package/src/server/modules/sync-note/sync-note.service.ts +25 -0
|
@@ -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
|
|
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
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
|
121
|
-
distinct(field: string, where?: Where<T
|
|
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(
|
|
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
|
|
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
|
|
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(
|
|
78
|
-
|
|
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
|
}
|