@credo-ts/drizzle-storage 0.6.0-pr-2324-20250708122805 → 0.6.0-pr-2324-20250709075226

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 (184) hide show
  1. package/cli/drizzle.config.ts +1 -1
  2. package/cli-build/drizzle.config.js +1 -1
  3. package/cli-build/drizzle.config.js.map +1 -1
  4. package/package.json +18 -17
  5. package/src/DrizzleDatabase.ts +29 -0
  6. package/src/DrizzleRecord.ts +73 -0
  7. package/src/DrizzleStorageModule.ts +112 -0
  8. package/src/DrizzleStorageModuleConfig.ts +48 -0
  9. package/src/action-menu/action-menu/DrizzleDidcommActionMenuRecordAdapter.ts +46 -0
  10. package/src/action-menu/action-menu/index.ts +10 -0
  11. package/src/action-menu/action-menu/postgres.ts +31 -0
  12. package/src/action-menu/action-menu/sqlite.ts +34 -0
  13. package/src/action-menu/bundle.ts +18 -0
  14. package/src/action-menu/postgres.ts +1 -0
  15. package/src/action-menu/sqlite.ts +1 -0
  16. package/src/adapter/BaseDrizzleRecordAdapter.ts +319 -0
  17. package/src/adapter/__tests__/queryToDrizzlePostgres.drizzle.e2e.test.ts +330 -0
  18. package/src/adapter/__tests__/queryToDrizzleSqlite.test.ts +324 -0
  19. package/src/adapter/index.ts +6 -0
  20. package/src/adapter/queryToDrizzlePostgres.ts +217 -0
  21. package/src/adapter/queryToDrizzleSqlite.ts +213 -0
  22. package/src/anoncreds/bundle.ts +34 -0
  23. package/src/anoncreds/credential/DrizzleAnonCredsCredentialRecordAdapter.ts +93 -0
  24. package/src/anoncreds/credential/index.ts +10 -0
  25. package/src/anoncreds/credential/postgres.ts +27 -0
  26. package/src/anoncreds/credential/sqlite.ts +27 -0
  27. package/src/anoncreds/credential-definition/DrizzleAnonCredsCredentialDefinitionRecordAdapter.ts +72 -0
  28. package/src/anoncreds/credential-definition/index.ts +10 -0
  29. package/src/anoncreds/credential-definition/postgres.ts +23 -0
  30. package/src/anoncreds/credential-definition/sqlite.ts +23 -0
  31. package/src/anoncreds/credential-definition-private/DrizzleAnonCredsCredentialDefinitionPrivateRecordAdapter.ts +48 -0
  32. package/src/anoncreds/credential-definition-private/index.ts +10 -0
  33. package/src/anoncreds/credential-definition-private/postgres.ts +14 -0
  34. package/src/anoncreds/credential-definition-private/sqlite.ts +14 -0
  35. package/src/anoncreds/key-correctness-proof/DrizzleAnonCredsKeyCorrectnessProofRecordAdapter.ts +46 -0
  36. package/src/anoncreds/key-correctness-proof/index.ts +10 -0
  37. package/src/anoncreds/key-correctness-proof/postgres.ts +13 -0
  38. package/src/anoncreds/key-correctness-proof/sqlite.ts +14 -0
  39. package/src/anoncreds/link-secret/DrizzleAnonCredsLinkSecretRecordAdapter.ts +45 -0
  40. package/src/anoncreds/link-secret/index.ts +10 -0
  41. package/src/anoncreds/link-secret/postgres.ts +18 -0
  42. package/src/anoncreds/link-secret/sqlite.ts +18 -0
  43. package/src/anoncreds/postgres.ts +8 -0
  44. package/src/anoncreds/revocation-registry-definition/DrizzleAnonCredsRevocationRegistryDefinitionRecordAdapter.ts +52 -0
  45. package/src/anoncreds/revocation-registry-definition/index.ts +10 -0
  46. package/src/anoncreds/revocation-registry-definition/postgres.ts +18 -0
  47. package/src/anoncreds/revocation-registry-definition/sqlite.ts +20 -0
  48. package/src/anoncreds/revocation-registry-definition-private/DrizzleAnonCredsRevocationRegistryDefinitionPrivateRecordAdapter.ts +53 -0
  49. package/src/anoncreds/revocation-registry-definition-private/index.ts +10 -0
  50. package/src/anoncreds/revocation-registry-definition-private/postgres.ts +22 -0
  51. package/src/anoncreds/revocation-registry-definition-private/sqlite.ts +18 -0
  52. package/src/anoncreds/schema/DrizzleAnonCredsSchemaRecordAdapter.ts +54 -0
  53. package/src/anoncreds/schema/__tests__/schema.drizzle.e2e.test.ts +70 -0
  54. package/src/anoncreds/schema/index.ts +10 -0
  55. package/src/anoncreds/schema/postgres.ts +22 -0
  56. package/src/anoncreds/schema/sqlite.ts +22 -0
  57. package/src/anoncreds/sqlite.ts +8 -0
  58. package/src/applyReactNativeMigrations.ts +24 -0
  59. package/src/combineSchemas.ts +44 -0
  60. package/src/core/bundle.ts +33 -0
  61. package/src/core/context/index.ts +8 -0
  62. package/src/core/context/postgres.ts +5 -0
  63. package/src/core/context/sqlite.ts +5 -0
  64. package/src/core/did/DrizzleDidRecordAdapter.ts +71 -0
  65. package/src/core/did/index.ts +10 -0
  66. package/src/core/did/postgres.ts +28 -0
  67. package/src/core/did/sqlite.ts +26 -0
  68. package/src/core/genericRecord/DrizzleGenericRecordAdapter.ts +36 -0
  69. package/src/core/genericRecord/index.ts +10 -0
  70. package/src/core/genericRecord/postgres.ts +12 -0
  71. package/src/core/genericRecord/sqlite.ts +12 -0
  72. package/src/core/mdoc/DrizzleMdocRecordAdapter.ts +44 -0
  73. package/src/core/mdoc/index.ts +10 -0
  74. package/src/core/mdoc/postgres.ts +15 -0
  75. package/src/core/mdoc/sqlite.ts +15 -0
  76. package/src/core/postgres.ts +8 -0
  77. package/src/core/sdJwtVc/DrizzleSdJwtVcRecordAdapter.ts +46 -0
  78. package/src/core/sdJwtVc/index.ts +10 -0
  79. package/src/core/sdJwtVc/postgres.ts +17 -0
  80. package/src/core/sdJwtVc/sqlite.ts +17 -0
  81. package/src/core/singleContextLruCache/DrizzleSingleContextLruCacheRecordAdapter.ts +43 -0
  82. package/src/core/singleContextLruCache/index.ts +10 -0
  83. package/src/core/singleContextLruCache/postgres.ts +12 -0
  84. package/src/core/singleContextLruCache/sqlite.ts +13 -0
  85. package/src/core/sqlite.ts +8 -0
  86. package/src/core/storageVersion/DrizzleStorageVersionRecordAdapter.ts +36 -0
  87. package/src/core/storageVersion/index.ts +10 -0
  88. package/src/core/storageVersion/postgres.ts +13 -0
  89. package/src/core/storageVersion/sqlite.ts +13 -0
  90. package/src/core/w3cCredential/DrizzleW3cCredentialRecordAdapter.ts +95 -0
  91. package/src/core/w3cCredential/index.ts +10 -0
  92. package/src/core/w3cCredential/postgres.ts +31 -0
  93. package/src/core/w3cCredential/sqlite.ts +29 -0
  94. package/src/didcomm/basic-message/DrizzleDidcommBasicMessageRecordAdapter.ts +54 -0
  95. package/src/didcomm/basic-message/index.ts +10 -0
  96. package/src/didcomm/basic-message/postgres.ts +30 -0
  97. package/src/didcomm/basic-message/sqlite.ts +29 -0
  98. package/src/didcomm/bundle.ts +34 -0
  99. package/src/didcomm/connection/DrizzleDidcommConnectionRecordAdapter.ts +70 -0
  100. package/src/didcomm/connection/index.ts +10 -0
  101. package/src/didcomm/connection/postgres.ts +55 -0
  102. package/src/didcomm/connection/sqlite.ts +39 -0
  103. package/src/didcomm/credential-exchange/DrizzleDidcommCredentialExchangeRecordAdapter.ts +64 -0
  104. package/src/didcomm/credential-exchange/__tests__/credentialExchange.drizzle.e2e.test.ts +104 -0
  105. package/src/didcomm/credential-exchange/index.ts +10 -0
  106. package/src/didcomm/credential-exchange/postgres.ts +45 -0
  107. package/src/didcomm/credential-exchange/sqlite.ts +39 -0
  108. package/src/didcomm/didcomm-message/DrizzleDidcommMessageRecordAdapter.ts +75 -0
  109. package/src/didcomm/didcomm-message/index.ts +10 -0
  110. package/src/didcomm/didcomm-message/postgres.ts +27 -0
  111. package/src/didcomm/didcomm-message/sqlite.ts +26 -0
  112. package/src/didcomm/mediation/DrizzleDidcommMediationRecordAdapter.ts +51 -0
  113. package/src/didcomm/mediation/index.ts +10 -0
  114. package/src/didcomm/mediation/postgres.ts +33 -0
  115. package/src/didcomm/mediation/sqlite.ts +31 -0
  116. package/src/didcomm/mediator-routing/DrizzleDidcommMediatorRoutingRecordAdapter.ts +49 -0
  117. package/src/didcomm/mediator-routing/index.ts +10 -0
  118. package/src/didcomm/mediator-routing/postgres.ts +14 -0
  119. package/src/didcomm/mediator-routing/sqlite.ts +17 -0
  120. package/src/didcomm/out-of-band/DrizzleDidcommOutOfBandRecordAdapter.ts +85 -0
  121. package/src/didcomm/out-of-band/__tests__/outOfBand.drizzle.e2e.test.ts +88 -0
  122. package/src/didcomm/out-of-band/index.ts +10 -0
  123. package/src/didcomm/out-of-band/postgres.ts +46 -0
  124. package/src/didcomm/out-of-band/sqlite.ts +46 -0
  125. package/src/didcomm/postgres.ts +8 -0
  126. package/src/didcomm/proof-exchange/DrizzleDidcommProofExchangeRecordAdapter.ts +51 -0
  127. package/src/didcomm/proof-exchange/index.ts +10 -0
  128. package/src/didcomm/proof-exchange/postgres.ts +33 -0
  129. package/src/didcomm/proof-exchange/sqlite.ts +29 -0
  130. package/src/didcomm/sqlite.ts +8 -0
  131. package/src/drpc/bundle.ts +18 -0
  132. package/src/drpc/drpc/DrizzleDidcommDrpcRecordAdapter.ts +44 -0
  133. package/src/drpc/drpc/index.ts +10 -0
  134. package/src/drpc/drpc/postgres.ts +31 -0
  135. package/src/drpc/drpc/sqlite.ts +29 -0
  136. package/src/drpc/postgres.ts +1 -0
  137. package/src/drpc/sqlite.ts +1 -0
  138. package/src/error/CredoDrizzleColumnDoesNotExistError.ts +21 -0
  139. package/src/error/CredoDrizzleStorageError.ts +7 -0
  140. package/src/error/index.ts +2 -0
  141. package/src/index.ts +29 -0
  142. package/src/openid4vc/bundle.ts +26 -0
  143. package/src/openid4vc/openid4vc-issuance-session/DrizzleOpenId4VcIssuanceSessionRecordAdapter.ts +90 -0
  144. package/src/openid4vc/openid4vc-issuance-session/index.ts +10 -0
  145. package/src/openid4vc/openid4vc-issuance-session/postgres.ts +54 -0
  146. package/src/openid4vc/openid4vc-issuance-session/sqlite.ts +54 -0
  147. package/src/openid4vc/openid4vc-issuer/DrizzleOpenid4vcIssuerRecordAdapter.ts +50 -0
  148. package/src/openid4vc/openid4vc-issuer/index.ts +10 -0
  149. package/src/openid4vc/openid4vc-issuer/postgres.ts +31 -0
  150. package/src/openid4vc/openid4vc-issuer/sqlite.ts +40 -0
  151. package/src/openid4vc/openid4vc-verification-session/DrizzleOpenId4VcVerificationSessionRecordAdapter.ts +62 -0
  152. package/src/openid4vc/openid4vc-verification-session/index.ts +10 -0
  153. package/src/openid4vc/openid4vc-verification-session/postgres.ts +46 -0
  154. package/src/openid4vc/openid4vc-verification-session/sqlite.ts +40 -0
  155. package/src/openid4vc/openid4vc-verifier/DrizzleOpenid4vcVerifierRecordAdapter.ts +43 -0
  156. package/src/openid4vc/openid4vc-verifier/index.ts +10 -0
  157. package/src/openid4vc/openid4vc-verifier/postgres.ts +14 -0
  158. package/src/openid4vc/openid4vc-verifier/sqlite.ts +19 -0
  159. package/src/openid4vc/postgres.ts +4 -0
  160. package/src/openid4vc/sqlite.ts +4 -0
  161. package/src/postgres/baseRecord.ts +44 -0
  162. package/src/postgres/index.ts +1 -0
  163. package/src/question-answer/bundle.ts +18 -0
  164. package/src/question-answer/postgres.ts +1 -0
  165. package/src/question-answer/question-answer/DrizzleDidcommQuestionAnswerRecordAdapter.ts +52 -0
  166. package/src/question-answer/question-answer/index.ts +10 -0
  167. package/src/question-answer/question-answer/postgres.ts +34 -0
  168. package/src/question-answer/question-answer/sqlite.ts +32 -0
  169. package/src/question-answer/sqlite.ts +1 -0
  170. package/src/sqlite/baseRecord.ts +38 -0
  171. package/src/sqlite/index.ts +1 -0
  172. package/src/storage/DrizzleStorageService.ts +87 -0
  173. package/src/storage/index.ts +1 -0
  174. package/src/tenants/bundle.ts +19 -0
  175. package/src/tenants/postgres.ts +2 -0
  176. package/src/tenants/sqlite.ts +2 -0
  177. package/src/tenants/tenant/DrizzleTenantRecordAdapter.ts +45 -0
  178. package/src/tenants/tenant/index.ts +10 -0
  179. package/src/tenants/tenant/postgres.ts +16 -0
  180. package/src/tenants/tenant/sqlite.ts +16 -0
  181. package/src/tenants/tenant-routing/DrizzleTenantRoutingRecordAdapter.ts +44 -0
  182. package/src/tenants/tenant-routing/index.ts +10 -0
  183. package/src/tenants/tenant-routing/postgres.ts +20 -0
  184. package/src/tenants/tenant-routing/sqlite.ts +20 -0
@@ -0,0 +1,319 @@
1
+ /**
2
+ * Adapter between a specific Record class and the record Type
3
+ */
4
+
5
+ import { AgentContext, BaseRecord, CredoError, Query, QueryOptions, RecordNotFoundError } from '@credo-ts/core'
6
+ import { Simplify, and, eq } from 'drizzle-orm'
7
+ import { PgTable, pgTable } from 'drizzle-orm/pg-core'
8
+ import { SQLiteTable as _SQLiteTable, sqliteTable } from 'drizzle-orm/sqlite-core'
9
+ import { DrizzleDatabase, isDrizzlePostgresDatabase, isDrizzleSqliteDatabase } from '../DrizzleDatabase'
10
+ import { CredoDrizzleStorageError } from '../error'
11
+ import { getPostgresBaseRecordTable } from '../postgres'
12
+ import { getSqliteBaseRecordTable } from '../sqlite'
13
+ import { DrizzleCustomTagKeyMapping, queryToDrizzlePostgres } from './queryToDrizzlePostgres'
14
+ import { queryToDrizzleSqlite } from './queryToDrizzleSqlite'
15
+
16
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
17
+ export type AnyDrizzleAdapter = BaseDrizzleRecordAdapter<any, any, any, any, any>
18
+
19
+ export type DrizzleAdapterValues<Table extends _SQLiteTable> = Simplify<
20
+ Omit<
21
+ { [Key in keyof Table['$inferInsert']]: Table['$inferInsert'][Key] },
22
+ Exclude<keyof ReturnType<typeof getSqliteBaseRecordTable>, 'customTags'>
23
+ >
24
+ >
25
+
26
+ export type DrizzleAdapterRecordValues<Table extends _SQLiteTable> = Simplify<
27
+ Omit<{ [Key in keyof Table['$inferInsert']]: Table['$inferInsert'][Key] }, 'contextCorrelationId'>
28
+ >
29
+
30
+ export abstract class BaseDrizzleRecordAdapter<
31
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
32
+ CredoRecord extends BaseRecord<any, any, any>,
33
+ PostgresTable extends ReturnType<typeof pgTable<string, ReturnType<typeof getPostgresBaseRecordTable>>>,
34
+ PostgresSchema extends Record<string, unknown>,
35
+ SQLiteTable extends ReturnType<typeof sqliteTable<string, ReturnType<typeof getSqliteBaseRecordTable>>>,
36
+ SQLiteSchema extends Record<string, unknown>,
37
+ > {
38
+ public recordType: CredoRecord['type']
39
+
40
+ public table: {
41
+ postgres: PostgresTable
42
+ sqlite: SQLiteTable
43
+ }
44
+
45
+ /**
46
+ * Allows overriding top level tags (as used by Credo record classes)
47
+ * to the database structure. For example mapping from the tag `presentationAuthSession`
48
+ * to the nested database json structure `presentation.authSession`.
49
+ */
50
+ public tagKeyMapping?: DrizzleCustomTagKeyMapping
51
+
52
+ public constructor(
53
+ public database: DrizzleDatabase<PostgresSchema, SQLiteSchema>,
54
+ table: {
55
+ postgres: PostgresTable
56
+ sqlite: SQLiteTable
57
+ },
58
+ recordType: CredoRecord['type']
59
+ ) {
60
+ this.table = table
61
+ this.recordType = recordType
62
+ }
63
+
64
+ public abstract getValues(record: CredoRecord): DrizzleAdapterValues<SQLiteTable>
65
+ public getValuesWithBase(agentContext: AgentContext, record: CredoRecord) {
66
+ return {
67
+ ...this.getValues(record),
68
+
69
+ // Always store based on context correlation id
70
+ contextCorrelationId: agentContext.contextCorrelationId,
71
+
72
+ id: record.id,
73
+ metadata: record.metadata.data,
74
+ createdAt: record.createdAt,
75
+ updatedAt: record.updatedAt,
76
+ }
77
+ }
78
+
79
+ private _toRecord(values: DrizzleAdapterRecordValues<SQLiteTable>): CredoRecord {
80
+ const filteredValues = Object.fromEntries(
81
+ Object.entries(values).filter(([_key, value]) => value !== null)
82
+ ) as DrizzleAdapterRecordValues<SQLiteTable>
83
+
84
+ return this.toRecord(filteredValues)
85
+ }
86
+
87
+ public abstract toRecord(values: DrizzleAdapterRecordValues<SQLiteTable>): CredoRecord
88
+
89
+ public async query(agentContext: AgentContext, query?: Query<CredoRecord>, queryOptions?: QueryOptions) {
90
+ if (isDrizzlePostgresDatabase(this.database)) {
91
+ let queryResult = this.database.select().from(this.table.postgres as PgTable)
92
+
93
+ if (query) {
94
+ queryResult = queryResult.where(
95
+ and(
96
+ // Always filter based on context correlation id
97
+ eq(this.table.postgres.contextCorrelationId, agentContext.contextCorrelationId),
98
+ queryToDrizzlePostgres(query ?? {}, this.table.postgres, this.tagKeyMapping)
99
+ )
100
+ ) as typeof queryResult
101
+ }
102
+
103
+ if (queryOptions?.limit !== undefined) {
104
+ queryResult = queryResult.limit(queryOptions.limit) as typeof queryResult
105
+ }
106
+
107
+ if (queryOptions?.offset !== undefined) {
108
+ queryResult = queryResult.offset(queryOptions.offset ?? 0) as typeof queryResult
109
+ }
110
+
111
+ const result = await queryResult
112
+ return result.map(({ contextCorrelationId, ...item }) =>
113
+ this._toRecord(item as DrizzleAdapterRecordValues<SQLiteTable>)
114
+ )
115
+ }
116
+
117
+ if (isDrizzleSqliteDatabase(this.database)) {
118
+ let queryResult = this.database.select().from(this.table.sqlite as SQLiteTable)
119
+
120
+ if (query) {
121
+ queryResult = queryResult.where(
122
+ and(
123
+ // Always filter based on context correlation id
124
+ eq(this.table.sqlite.contextCorrelationId, agentContext.contextCorrelationId),
125
+ queryToDrizzleSqlite(query ?? {}, this.table.sqlite, this.tagKeyMapping)
126
+ )
127
+ ) as unknown as typeof queryResult
128
+ }
129
+
130
+ if (queryOptions?.limit !== undefined) {
131
+ queryResult = queryResult.limit(queryOptions.limit) as unknown as typeof queryResult
132
+ }
133
+
134
+ if (queryOptions?.offset !== undefined) {
135
+ queryResult = queryResult.offset(queryOptions.offset ?? 0) as unknown as typeof queryResult
136
+ }
137
+
138
+ const result = await queryResult
139
+ return result.map(({ contextCorrelationId, ...item }) =>
140
+ this._toRecord(item as DrizzleAdapterRecordValues<SQLiteTable>)
141
+ )
142
+ }
143
+
144
+ throw new CredoError('Unsupported database type')
145
+ }
146
+
147
+ public async getById(agentContext: AgentContext, id: string) {
148
+ if (isDrizzlePostgresDatabase(this.database)) {
149
+ const [result] = await this.database
150
+ .select()
151
+ .from(this.table.postgres as PgTable)
152
+ .where(
153
+ and(
154
+ eq(this.table.postgres.id, id),
155
+ eq(this.table.postgres.contextCorrelationId, agentContext.contextCorrelationId)
156
+ )
157
+ )
158
+ .limit(1)
159
+
160
+ if (!result) {
161
+ throw new RecordNotFoundError(`record with id ${id} not found.`, {
162
+ recordType: this.recordType,
163
+ })
164
+ }
165
+
166
+ const { contextCorrelationId, ...item } = result
167
+ return this._toRecord(item as DrizzleAdapterRecordValues<SQLiteTable>)
168
+ }
169
+
170
+ if (isDrizzleSqliteDatabase(this.database)) {
171
+ const [result] = await this.database
172
+ .select()
173
+ .from(this.table.sqlite)
174
+ .where(
175
+ and(
176
+ eq(this.table.sqlite.id, id),
177
+ eq(this.table.sqlite.contextCorrelationId, agentContext.contextCorrelationId)
178
+ )
179
+ )
180
+ .limit(1)
181
+
182
+ if (!result) {
183
+ throw new RecordNotFoundError(`record with id ${id} not found.`, {
184
+ recordType: this.recordType,
185
+ })
186
+ }
187
+
188
+ const { contextCorrelationId, ...item } = result
189
+ return this._toRecord(item as DrizzleAdapterRecordValues<SQLiteTable>)
190
+ }
191
+
192
+ throw new CredoError('Unsupported database type')
193
+ }
194
+
195
+ public async insert(agentContext: AgentContext, record: CredoRecord) {
196
+ if (isDrizzlePostgresDatabase(this.database)) {
197
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
198
+ await this.database.insert(this.table.postgres).values(this.getValuesWithBase(agentContext, record) as any)
199
+ return
200
+ }
201
+
202
+ if (isDrizzleSqliteDatabase(this.database)) {
203
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
204
+ await this.database.insert(this.table.sqlite).values(this.getValuesWithBase(agentContext, record) as any)
205
+ return
206
+ }
207
+
208
+ throw new CredoError('Unsupported database type')
209
+ }
210
+
211
+ public async update(agentContext: AgentContext, record: CredoRecord) {
212
+ // Although id should always be set, if for some reason it is not set it can be quite impactful
213
+ if (!record.id) {
214
+ throw new CredoDrizzleStorageError(`Record of type ${record.type}' is missing 'id' column.`)
215
+ }
216
+
217
+ if (isDrizzlePostgresDatabase(this.database)) {
218
+ const updated = await this.database
219
+ .update(this.table.postgres)
220
+ // biome-ignore lint/suspicious/noExplicitAny: generics really don't play well here
221
+ .set(this.getValuesWithBase(agentContext, record) as any)
222
+ .where(
223
+ and(
224
+ eq(this.table.postgres.id, record.id),
225
+ eq(this.table.postgres.contextCorrelationId, agentContext.contextCorrelationId)
226
+ )
227
+ )
228
+ .returning({ id: this.table.postgres.id })
229
+
230
+ if (updated.length === 0) {
231
+ throw new RecordNotFoundError(`record with id ${record.id} not found.`, {
232
+ recordType: this.recordType,
233
+ })
234
+ }
235
+
236
+ return
237
+ }
238
+
239
+ if (isDrizzleSqliteDatabase(this.database)) {
240
+ const updated = await this.database
241
+ .update(this.table.sqlite)
242
+ // biome-ignore lint/suspicious/noExplicitAny: generics really don't play well here
243
+ .set(this.getValuesWithBase(agentContext, record) as any)
244
+ .where(
245
+ and(
246
+ eq(this.table.sqlite.id, record.id),
247
+ eq(this.table.sqlite.contextCorrelationId, agentContext.contextCorrelationId)
248
+ )
249
+ )
250
+ .returning({
251
+ id: this.table.sqlite.id,
252
+ })
253
+
254
+ if (updated.length === 0) {
255
+ throw new RecordNotFoundError(`record with id ${record.id} not found.`, {
256
+ recordType: this.recordType,
257
+ })
258
+ }
259
+
260
+ return
261
+ }
262
+
263
+ throw new CredoError('Unsupported database type')
264
+ }
265
+
266
+ public async delete(agentContext: AgentContext, id: string) {
267
+ // Although id should always be set, if for some reason it is not set it can be quite impactful
268
+ if (!id) {
269
+ throw new CredoDrizzleStorageError(`Missing required 'id' for delete.`)
270
+ }
271
+
272
+ if (isDrizzlePostgresDatabase(this.database)) {
273
+ const deleted = await this.database
274
+ .delete(this.table.postgres)
275
+ .where(
276
+ and(
277
+ eq(this.table.postgres.id, id),
278
+ eq(this.table.postgres.contextCorrelationId, agentContext.contextCorrelationId)
279
+ )
280
+ )
281
+ .returning({
282
+ id: this.table.postgres.id,
283
+ })
284
+
285
+ if (deleted.length === 0) {
286
+ throw new RecordNotFoundError(`record with id ${id} not found.`, {
287
+ recordType: this.recordType,
288
+ })
289
+ }
290
+
291
+ return
292
+ }
293
+
294
+ if (isDrizzleSqliteDatabase(this.database)) {
295
+ const deleted = await this.database
296
+ .delete(this.table.postgres)
297
+ .where(
298
+ and(
299
+ eq(this.table.sqlite.id, id),
300
+ eq(this.table.sqlite.contextCorrelationId, agentContext.contextCorrelationId)
301
+ )
302
+ )
303
+ .returning({
304
+ id: this.table.sqlite.id,
305
+ })
306
+
307
+ if (deleted.length === 0) {
308
+ throw new RecordNotFoundError(`record with id ${id} not found.`, {
309
+ recordType: this.recordType,
310
+ })
311
+ }
312
+
313
+ return
314
+ }
315
+
316
+ // @ts-expect-error
317
+ throw new CredoError(`Unsupported database type '${database.type}'`)
318
+ }
319
+ }
@@ -0,0 +1,330 @@
1
+ import { ConnectionRecord, DidExchangeRole, DidExchangeState } from '@credo-ts/didcomm'
2
+ import { pushSchema } from 'drizzle-kit/api'
3
+ import { DrizzlePostgresTestDatabase, createDrizzlePostgresTestDatabase } from '../../../tests/testDatabase'
4
+ import * as coreContextSchema from '../../core/context/postgres'
5
+ import * as didcommConnectionSchema from '../../didcomm/connection/postgres'
6
+ import { queryToDrizzlePostgres } from '../queryToDrizzlePostgres'
7
+
8
+ const { didcommConnection } = didcommConnectionSchema
9
+ const { context } = coreContextSchema
10
+
11
+ describe('queryToDrizzlePostgres', () => {
12
+ let postgresDatabase: DrizzlePostgresTestDatabase
13
+
14
+ beforeAll(async () => {
15
+ postgresDatabase = await createDrizzlePostgresTestDatabase()
16
+
17
+ const { apply } = await pushSchema(
18
+ { ...didcommConnectionSchema, ...coreContextSchema },
19
+ // @ts-ignore
20
+ postgresDatabase.drizzle
21
+ )
22
+ await apply()
23
+
24
+ await postgresDatabase.drizzle.insert(context).values({
25
+ contextCorrelationId: 'b2fc0867-d0d1-4182-ade7-813b695d43c2',
26
+ })
27
+ await postgresDatabase.drizzle.insert(didcommConnection).values({
28
+ createdAt: new Date(),
29
+ updatedAt: new Date(),
30
+ contextCorrelationId: 'b2fc0867-d0d1-4182-ade7-813b695d43c2',
31
+ id: 'db0ddc8f-5339-431b-9675-749f8a2ac92f',
32
+ role: DidExchangeRole.Requester,
33
+ state: DidExchangeState.Abandoned,
34
+ connectionTypes: ['one', 'three', 'four'],
35
+ invitationDid: 'some string',
36
+ customTags: {
37
+ myCustomTag: ['First', 'Second'],
38
+ anotherCustomTag: true,
39
+ },
40
+ })
41
+ })
42
+
43
+ afterAll(async () => {
44
+ await postgresDatabase.teardown()
45
+ })
46
+
47
+ test('should correctly query column', async () => {
48
+ expect(
49
+ await postgresDatabase.drizzle
50
+ .select()
51
+ .from(didcommConnection)
52
+ .where(
53
+ queryToDrizzlePostgres<ConnectionRecord>(
54
+ {
55
+ invitationDid: 'some string',
56
+ },
57
+ didcommConnection
58
+ )
59
+ )
60
+ ).toHaveLength(1)
61
+
62
+ expect(
63
+ await postgresDatabase.drizzle
64
+ .select()
65
+ .from(didcommConnection)
66
+ .where(
67
+ queryToDrizzlePostgres<ConnectionRecord>(
68
+ {
69
+ invitationDid: 'some other string',
70
+ },
71
+ didcommConnection
72
+ )
73
+ )
74
+ ).toHaveLength(0)
75
+ })
76
+
77
+ test('should correctly query array value column', async () => {
78
+ expect(
79
+ await postgresDatabase.drizzle
80
+ .select()
81
+ .from(didcommConnection)
82
+ .where(
83
+ queryToDrizzlePostgres<ConnectionRecord>(
84
+ {
85
+ connectionTypes: ['one', 'three'],
86
+ invitationDid: 'some string',
87
+ },
88
+ didcommConnection
89
+ )
90
+ )
91
+ ).toHaveLength(1)
92
+
93
+ expect(
94
+ await postgresDatabase.drizzle
95
+ .select()
96
+ .from(didcommConnection)
97
+ .where(
98
+ queryToDrizzlePostgres<ConnectionRecord>(
99
+ {
100
+ connectionTypes: ['one', 'two', 'five'],
101
+ invitationDid: 'some string',
102
+ },
103
+ didcommConnection
104
+ )
105
+ )
106
+ ).toHaveLength(0)
107
+
108
+ expect(
109
+ await postgresDatabase.drizzle
110
+ .select()
111
+ .from(didcommConnection)
112
+ .where(
113
+ queryToDrizzlePostgres<ConnectionRecord>(
114
+ {
115
+ connectionTypes: ['one'],
116
+ invitationDid: 'some string',
117
+ },
118
+ didcommConnection
119
+ )
120
+ )
121
+ ).toHaveLength(1)
122
+ })
123
+
124
+ test('should correctly query custom tag column value', async () => {
125
+ expect(
126
+ await postgresDatabase.drizzle
127
+ .select()
128
+ .from(didcommConnection)
129
+ .where(
130
+ queryToDrizzlePostgres<ConnectionRecord>(
131
+ {
132
+ anotherCustomTag: true,
133
+ invitationDid: 'some string',
134
+ },
135
+ didcommConnection
136
+ )
137
+ )
138
+ ).toHaveLength(1)
139
+
140
+ expect(
141
+ await postgresDatabase.drizzle
142
+ .select()
143
+ .from(didcommConnection)
144
+ .where(
145
+ queryToDrizzlePostgres<ConnectionRecord>(
146
+ {
147
+ anotherCustomTag: false,
148
+ invitationDid: 'some string',
149
+ },
150
+ didcommConnection
151
+ )
152
+ )
153
+ ).toHaveLength(0)
154
+ })
155
+
156
+ test('should correctly query custom tag column array value', async () => {
157
+ expect(
158
+ await postgresDatabase.drizzle
159
+ .select()
160
+ .from(didcommConnection)
161
+ .where(
162
+ queryToDrizzlePostgres<ConnectionRecord>(
163
+ {
164
+ myCustomTag: ['First', 'Second'],
165
+ invitationDid: 'some string',
166
+ },
167
+ didcommConnection
168
+ )
169
+ )
170
+ ).toHaveLength(1)
171
+
172
+ expect(
173
+ await postgresDatabase.drizzle
174
+ .select()
175
+ .from(didcommConnection)
176
+ .where(
177
+ queryToDrizzlePostgres<ConnectionRecord>(
178
+ {
179
+ myCustomTag: ['Third'],
180
+ invitationDid: 'some string',
181
+ },
182
+ didcommConnection
183
+ )
184
+ )
185
+ ).toHaveLength(0)
186
+
187
+ expect(
188
+ await postgresDatabase.drizzle
189
+ .select()
190
+ .from(didcommConnection)
191
+ .where(
192
+ queryToDrizzlePostgres<ConnectionRecord>(
193
+ {
194
+ myCustomTag: ['First'],
195
+ invitationDid: 'some string',
196
+ },
197
+ didcommConnection
198
+ )
199
+ )
200
+ ).toHaveLength(1)
201
+ })
202
+
203
+ test('should correctly query with and/or', async () => {
204
+ expect(
205
+ await postgresDatabase.drizzle
206
+ .select()
207
+ .from(didcommConnection)
208
+ .where(
209
+ queryToDrizzlePostgres<ConnectionRecord>(
210
+ {
211
+ connectionTypes: ['one'],
212
+ $or: [
213
+ {
214
+ connectionTypes: ['two'],
215
+ },
216
+ {
217
+ connectionTypes: ['three'],
218
+ },
219
+ ],
220
+ $and: [
221
+ {
222
+ connectionTypes: ['four'],
223
+ },
224
+ ],
225
+ },
226
+ didcommConnection
227
+ )
228
+ )
229
+ ).toHaveLength(1)
230
+
231
+ expect(
232
+ await postgresDatabase.drizzle
233
+ .select()
234
+ .from(didcommConnection)
235
+ .where(
236
+ queryToDrizzlePostgres<ConnectionRecord>(
237
+ {
238
+ connectionTypes: ['one'],
239
+ $or: [
240
+ {
241
+ connectionTypes: ['two'],
242
+ },
243
+ {
244
+ connectionTypes: ['three'],
245
+ },
246
+ ],
247
+ $and: [
248
+ {
249
+ connectionTypes: ['four'],
250
+ },
251
+ {
252
+ connectionTypes: ['two'],
253
+ },
254
+ ],
255
+ },
256
+ didcommConnection
257
+ )
258
+ )
259
+ ).toHaveLength(0)
260
+ })
261
+
262
+ test('should correctly query with not', async () => {
263
+ expect(
264
+ await postgresDatabase.drizzle
265
+ .select()
266
+ .from(didcommConnection)
267
+ .where(
268
+ queryToDrizzlePostgres<ConnectionRecord>(
269
+ {
270
+ connectionTypes: ['one'],
271
+ $not: {
272
+ $and: [
273
+ {
274
+ connectionTypes: ['two'],
275
+ },
276
+ {
277
+ connectionTypes: ['five'],
278
+ },
279
+ ],
280
+ $or: [
281
+ {
282
+ connectionTypes: ['two'],
283
+ },
284
+ {
285
+ connectionTypes: ['three'],
286
+ },
287
+ ],
288
+ },
289
+ },
290
+ didcommConnection
291
+ )
292
+ )
293
+ ).toHaveLength(1)
294
+
295
+ expect(
296
+ await postgresDatabase.drizzle
297
+ .select()
298
+ .from(didcommConnection)
299
+ .where(
300
+ queryToDrizzlePostgres<ConnectionRecord>(
301
+ {
302
+ connectionTypes: ['one'],
303
+ $not: {
304
+ $and: [
305
+ {
306
+ connectionTypes: ['two'],
307
+ },
308
+ {
309
+ connectionTypes: ['five'],
310
+ },
311
+ {
312
+ connectionTypes: ['three'],
313
+ },
314
+ ],
315
+ $or: [
316
+ {
317
+ connectionTypes: ['two'],
318
+ },
319
+ {
320
+ connectionTypes: ['three'],
321
+ },
322
+ ],
323
+ },
324
+ },
325
+ didcommConnection
326
+ )
327
+ )
328
+ ).toHaveLength(0)
329
+ })
330
+ })