@credo-ts/drizzle-storage 0.6.0-pr-2324-20250708122805 → 0.6.0-pr-2324-20250708123651
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/package.json +15 -14
- package/src/DrizzleDatabase.ts +29 -0
- package/src/DrizzleRecord.ts +73 -0
- package/src/DrizzleStorageModule.ts +112 -0
- package/src/DrizzleStorageModuleConfig.ts +48 -0
- package/src/action-menu/action-menu/DrizzleDidcommActionMenuRecordAdapter.ts +46 -0
- package/src/action-menu/action-menu/index.ts +10 -0
- package/src/action-menu/action-menu/postgres.ts +31 -0
- package/src/action-menu/action-menu/sqlite.ts +34 -0
- package/src/action-menu/bundle.ts +18 -0
- package/src/action-menu/postgres.ts +1 -0
- package/src/action-menu/sqlite.ts +1 -0
- package/src/adapter/BaseDrizzleRecordAdapter.ts +319 -0
- package/src/adapter/__tests__/queryToDrizzlePostgres.test.ts +328 -0
- package/src/adapter/__tests__/queryToDrizzleSqlite.test.ts +324 -0
- package/src/adapter/index.ts +6 -0
- package/src/adapter/queryToDrizzlePostgres.ts +217 -0
- package/src/adapter/queryToDrizzleSqlite.ts +213 -0
- package/src/anoncreds/bundle.ts +34 -0
- package/src/anoncreds/credential/DrizzleAnonCredsCredentialRecordAdapter.ts +93 -0
- package/src/anoncreds/credential/index.ts +10 -0
- package/src/anoncreds/credential/postgres.ts +27 -0
- package/src/anoncreds/credential/sqlite.ts +27 -0
- package/src/anoncreds/credential-definition/DrizzleAnonCredsCredentialDefinitionRecordAdapter.ts +72 -0
- package/src/anoncreds/credential-definition/index.ts +10 -0
- package/src/anoncreds/credential-definition/postgres.ts +23 -0
- package/src/anoncreds/credential-definition/sqlite.ts +23 -0
- package/src/anoncreds/credential-definition-private/DrizzleAnonCredsCredentialDefinitionPrivateRecordAdapter.ts +48 -0
- package/src/anoncreds/credential-definition-private/index.ts +10 -0
- package/src/anoncreds/credential-definition-private/postgres.ts +14 -0
- package/src/anoncreds/credential-definition-private/sqlite.ts +14 -0
- package/src/anoncreds/key-correctness-proof/DrizzleAnonCredsKeyCorrectnessProofRecordAdapter.ts +46 -0
- package/src/anoncreds/key-correctness-proof/index.ts +10 -0
- package/src/anoncreds/key-correctness-proof/postgres.ts +13 -0
- package/src/anoncreds/key-correctness-proof/sqlite.ts +14 -0
- package/src/anoncreds/link-secret/DrizzleAnonCredsLinkSecretRecordAdapter.ts +45 -0
- package/src/anoncreds/link-secret/index.ts +10 -0
- package/src/anoncreds/link-secret/postgres.ts +18 -0
- package/src/anoncreds/link-secret/sqlite.ts +18 -0
- package/src/anoncreds/postgres.ts +8 -0
- package/src/anoncreds/revocation-registry-definition/DrizzleAnonCredsRevocationRegistryDefinitionRecordAdapter.ts +52 -0
- package/src/anoncreds/revocation-registry-definition/index.ts +10 -0
- package/src/anoncreds/revocation-registry-definition/postgres.ts +18 -0
- package/src/anoncreds/revocation-registry-definition/sqlite.ts +20 -0
- package/src/anoncreds/revocation-registry-definition-private/DrizzleAnonCredsRevocationRegistryDefinitionPrivateRecordAdapter.ts +53 -0
- package/src/anoncreds/revocation-registry-definition-private/index.ts +10 -0
- package/src/anoncreds/revocation-registry-definition-private/postgres.ts +22 -0
- package/src/anoncreds/revocation-registry-definition-private/sqlite.ts +18 -0
- package/src/anoncreds/schema/DrizzleAnonCredsSchemaRecordAdapter.ts +54 -0
- package/src/anoncreds/schema/__tests__/schema.test.ts +66 -0
- package/src/anoncreds/schema/index.ts +10 -0
- package/src/anoncreds/schema/postgres.ts +22 -0
- package/src/anoncreds/schema/sqlite.ts +22 -0
- package/src/anoncreds/sqlite.ts +8 -0
- package/src/applyReactNativeMigrations.ts +24 -0
- package/src/combineSchemas.ts +44 -0
- package/src/core/bundle.ts +33 -0
- package/src/core/context/index.ts +8 -0
- package/src/core/context/postgres.ts +5 -0
- package/src/core/context/sqlite.ts +5 -0
- package/src/core/did/DrizzleDidRecordAdapter.ts +71 -0
- package/src/core/did/index.ts +10 -0
- package/src/core/did/postgres.ts +28 -0
- package/src/core/did/sqlite.ts +26 -0
- package/src/core/genericRecord/DrizzleGenericRecordAdapter.ts +36 -0
- package/src/core/genericRecord/index.ts +10 -0
- package/src/core/genericRecord/postgres.ts +12 -0
- package/src/core/genericRecord/sqlite.ts +12 -0
- package/src/core/mdoc/DrizzleMdocRecordAdapter.ts +44 -0
- package/src/core/mdoc/index.ts +10 -0
- package/src/core/mdoc/postgres.ts +15 -0
- package/src/core/mdoc/sqlite.ts +15 -0
- package/src/core/postgres.ts +8 -0
- package/src/core/sdJwtVc/DrizzleSdJwtVcRecordAdapter.ts +46 -0
- package/src/core/sdJwtVc/index.ts +10 -0
- package/src/core/sdJwtVc/postgres.ts +17 -0
- package/src/core/sdJwtVc/sqlite.ts +17 -0
- package/src/core/singleContextLruCache/DrizzleSingleContextLruCacheRecordAdapter.ts +43 -0
- package/src/core/singleContextLruCache/index.ts +10 -0
- package/src/core/singleContextLruCache/postgres.ts +12 -0
- package/src/core/singleContextLruCache/sqlite.ts +13 -0
- package/src/core/sqlite.ts +8 -0
- package/src/core/storageVersion/DrizzleStorageVersionRecordAdapter.ts +36 -0
- package/src/core/storageVersion/index.ts +10 -0
- package/src/core/storageVersion/postgres.ts +13 -0
- package/src/core/storageVersion/sqlite.ts +13 -0
- package/src/core/w3cCredential/DrizzleW3cCredentialRecordAdapter.ts +95 -0
- package/src/core/w3cCredential/index.ts +10 -0
- package/src/core/w3cCredential/postgres.ts +31 -0
- package/src/core/w3cCredential/sqlite.ts +29 -0
- package/src/didcomm/basic-message/DrizzleDidcommBasicMessageRecordAdapter.ts +54 -0
- package/src/didcomm/basic-message/index.ts +10 -0
- package/src/didcomm/basic-message/postgres.ts +30 -0
- package/src/didcomm/basic-message/sqlite.ts +29 -0
- package/src/didcomm/bundle.ts +34 -0
- package/src/didcomm/connection/DrizzleDidcommConnectionRecordAdapter.ts +70 -0
- package/src/didcomm/connection/index.ts +10 -0
- package/src/didcomm/connection/postgres.ts +55 -0
- package/src/didcomm/connection/sqlite.ts +39 -0
- package/src/didcomm/credential-exchange/DrizzleDidcommCredentialExchangeRecordAdapter.ts +64 -0
- package/src/didcomm/credential-exchange/__tests__/credentialExchange.test.ts +97 -0
- package/src/didcomm/credential-exchange/index.ts +10 -0
- package/src/didcomm/credential-exchange/postgres.ts +45 -0
- package/src/didcomm/credential-exchange/sqlite.ts +39 -0
- package/src/didcomm/didcomm-message/DrizzleDidcommMessageRecordAdapter.ts +75 -0
- package/src/didcomm/didcomm-message/index.ts +10 -0
- package/src/didcomm/didcomm-message/postgres.ts +27 -0
- package/src/didcomm/didcomm-message/sqlite.ts +26 -0
- package/src/didcomm/mediation/DrizzleDidcommMediationRecordAdapter.ts +51 -0
- package/src/didcomm/mediation/index.ts +10 -0
- package/src/didcomm/mediation/postgres.ts +33 -0
- package/src/didcomm/mediation/sqlite.ts +31 -0
- package/src/didcomm/mediator-routing/DrizzleDidcommMediatorRoutingRecordAdapter.ts +49 -0
- package/src/didcomm/mediator-routing/index.ts +10 -0
- package/src/didcomm/mediator-routing/postgres.ts +14 -0
- package/src/didcomm/mediator-routing/sqlite.ts +17 -0
- package/src/didcomm/out-of-band/DrizzleDidcommOutOfBandRecordAdapter.ts +85 -0
- package/src/didcomm/out-of-band/__tests__/outOfBand.test.ts +84 -0
- package/src/didcomm/out-of-band/index.ts +10 -0
- package/src/didcomm/out-of-band/postgres.ts +46 -0
- package/src/didcomm/out-of-band/sqlite.ts +46 -0
- package/src/didcomm/postgres.ts +8 -0
- package/src/didcomm/proof-exchange/DrizzleDidcommProofExchangeRecordAdapter.ts +51 -0
- package/src/didcomm/proof-exchange/index.ts +10 -0
- package/src/didcomm/proof-exchange/postgres.ts +33 -0
- package/src/didcomm/proof-exchange/sqlite.ts +29 -0
- package/src/didcomm/sqlite.ts +8 -0
- package/src/drpc/bundle.ts +18 -0
- package/src/drpc/drpc/DrizzleDidcommDrpcRecordAdapter.ts +44 -0
- package/src/drpc/drpc/index.ts +10 -0
- package/src/drpc/drpc/postgres.ts +31 -0
- package/src/drpc/drpc/sqlite.ts +29 -0
- package/src/drpc/postgres.ts +1 -0
- package/src/drpc/sqlite.ts +1 -0
- package/src/error/CredoDrizzleColumnDoesNotExistError.ts +21 -0
- package/src/error/CredoDrizzleStorageError.ts +7 -0
- package/src/error/index.ts +2 -0
- package/src/index.ts +29 -0
- package/src/openid4vc/bundle.ts +26 -0
- package/src/openid4vc/openid4vc-issuance-session/DrizzleOpenId4VcIssuanceSessionRecordAdapter.ts +90 -0
- package/src/openid4vc/openid4vc-issuance-session/index.ts +10 -0
- package/src/openid4vc/openid4vc-issuance-session/postgres.ts +54 -0
- package/src/openid4vc/openid4vc-issuance-session/sqlite.ts +54 -0
- package/src/openid4vc/openid4vc-issuer/DrizzleOpenid4vcIssuerRecordAdapter.ts +50 -0
- package/src/openid4vc/openid4vc-issuer/index.ts +10 -0
- package/src/openid4vc/openid4vc-issuer/postgres.ts +31 -0
- package/src/openid4vc/openid4vc-issuer/sqlite.ts +40 -0
- package/src/openid4vc/openid4vc-verification-session/DrizzleOpenId4VcVerificationSessionRecordAdapter.ts +62 -0
- package/src/openid4vc/openid4vc-verification-session/index.ts +10 -0
- package/src/openid4vc/openid4vc-verification-session/postgres.ts +46 -0
- package/src/openid4vc/openid4vc-verification-session/sqlite.ts +40 -0
- package/src/openid4vc/openid4vc-verifier/DrizzleOpenid4vcVerifierRecordAdapter.ts +43 -0
- package/src/openid4vc/openid4vc-verifier/index.ts +10 -0
- package/src/openid4vc/openid4vc-verifier/postgres.ts +14 -0
- package/src/openid4vc/openid4vc-verifier/sqlite.ts +19 -0
- package/src/openid4vc/postgres.ts +4 -0
- package/src/openid4vc/sqlite.ts +4 -0
- package/src/postgres/baseRecord.ts +44 -0
- package/src/postgres/index.ts +1 -0
- package/src/question-answer/bundle.ts +18 -0
- package/src/question-answer/postgres.ts +1 -0
- package/src/question-answer/question-answer/DrizzleDidcommQuestionAnswerRecordAdapter.ts +52 -0
- package/src/question-answer/question-answer/index.ts +10 -0
- package/src/question-answer/question-answer/postgres.ts +34 -0
- package/src/question-answer/question-answer/sqlite.ts +32 -0
- package/src/question-answer/sqlite.ts +1 -0
- package/src/sqlite/baseRecord.ts +38 -0
- package/src/sqlite/index.ts +1 -0
- package/src/storage/DrizzleStorageService.ts +87 -0
- package/src/storage/index.ts +1 -0
- package/src/tenants/bundle.ts +19 -0
- package/src/tenants/postgres.ts +2 -0
- package/src/tenants/sqlite.ts +2 -0
- package/src/tenants/tenant/DrizzleTenantRecordAdapter.ts +45 -0
- package/src/tenants/tenant/index.ts +10 -0
- package/src/tenants/tenant/postgres.ts +16 -0
- package/src/tenants/tenant/sqlite.ts +16 -0
- package/src/tenants/tenant-routing/DrizzleTenantRoutingRecordAdapter.ts +44 -0
- package/src/tenants/tenant-routing/index.ts +10 -0
- package/src/tenants/tenant-routing/postgres.ts +20 -0
- 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,328 @@
|
|
|
1
|
+
import { ConnectionRecord, DidExchangeRole, DidExchangeState } from '@credo-ts/didcomm'
|
|
2
|
+
import { pushSchema } from 'drizzle-kit/api'
|
|
3
|
+
import { PgDatabase } from 'drizzle-orm/pg-core'
|
|
4
|
+
import { drizzle } from 'drizzle-orm/pglite'
|
|
5
|
+
import { DrizzlePostgresDatabase } from '../../DrizzleDatabase'
|
|
6
|
+
import * as coreContextSchema from '../../core/context/postgres'
|
|
7
|
+
import * as didcommConnectionSchema from '../../didcomm/connection/postgres'
|
|
8
|
+
import { queryToDrizzlePostgres } from '../queryToDrizzlePostgres'
|
|
9
|
+
|
|
10
|
+
const { didcommConnection } = didcommConnectionSchema
|
|
11
|
+
const { context } = coreContextSchema
|
|
12
|
+
|
|
13
|
+
const db = drizzle('memory://', {
|
|
14
|
+
schema: { ...didcommConnectionSchema, ...coreContextSchema },
|
|
15
|
+
}) as unknown as DrizzlePostgresDatabase<typeof didcommConnectionSchema>
|
|
16
|
+
|
|
17
|
+
describe('queryToDrizzlePostgres', () => {
|
|
18
|
+
beforeAll(async () => {
|
|
19
|
+
const { apply } = await pushSchema(
|
|
20
|
+
{ ...didcommConnectionSchema, ...coreContextSchema },
|
|
21
|
+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
22
|
+
db as unknown as PgDatabase<any>
|
|
23
|
+
)
|
|
24
|
+
await apply()
|
|
25
|
+
|
|
26
|
+
await db.insert(context).values({
|
|
27
|
+
contextCorrelationId: 'b2fc0867-d0d1-4182-ade7-813b695d43c2',
|
|
28
|
+
})
|
|
29
|
+
await db.insert(didcommConnection).values({
|
|
30
|
+
createdAt: new Date(),
|
|
31
|
+
updatedAt: new Date(),
|
|
32
|
+
contextCorrelationId: 'b2fc0867-d0d1-4182-ade7-813b695d43c2',
|
|
33
|
+
id: 'db0ddc8f-5339-431b-9675-749f8a2ac92f',
|
|
34
|
+
role: DidExchangeRole.Requester,
|
|
35
|
+
state: DidExchangeState.Abandoned,
|
|
36
|
+
connectionTypes: ['one', 'three', 'four'],
|
|
37
|
+
invitationDid: 'some string',
|
|
38
|
+
customTags: {
|
|
39
|
+
myCustomTag: ['First', 'Second'],
|
|
40
|
+
anotherCustomTag: true,
|
|
41
|
+
},
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test('should correctly query column', async () => {
|
|
46
|
+
expect(
|
|
47
|
+
await db
|
|
48
|
+
.select()
|
|
49
|
+
.from(didcommConnection)
|
|
50
|
+
.where(
|
|
51
|
+
queryToDrizzlePostgres<ConnectionRecord>(
|
|
52
|
+
{
|
|
53
|
+
invitationDid: 'some string',
|
|
54
|
+
},
|
|
55
|
+
didcommConnection
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
).toHaveLength(1)
|
|
59
|
+
|
|
60
|
+
expect(
|
|
61
|
+
await db
|
|
62
|
+
.select()
|
|
63
|
+
.from(didcommConnection)
|
|
64
|
+
.where(
|
|
65
|
+
queryToDrizzlePostgres<ConnectionRecord>(
|
|
66
|
+
{
|
|
67
|
+
invitationDid: 'some other string',
|
|
68
|
+
},
|
|
69
|
+
didcommConnection
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
).toHaveLength(0)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
test('should correctly query array value column', async () => {
|
|
76
|
+
expect(
|
|
77
|
+
await db
|
|
78
|
+
.select()
|
|
79
|
+
.from(didcommConnection)
|
|
80
|
+
.where(
|
|
81
|
+
queryToDrizzlePostgres<ConnectionRecord>(
|
|
82
|
+
{
|
|
83
|
+
connectionTypes: ['one', 'three'],
|
|
84
|
+
invitationDid: 'some string',
|
|
85
|
+
},
|
|
86
|
+
didcommConnection
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
).toHaveLength(1)
|
|
90
|
+
|
|
91
|
+
expect(
|
|
92
|
+
await db
|
|
93
|
+
.select()
|
|
94
|
+
.from(didcommConnection)
|
|
95
|
+
.where(
|
|
96
|
+
queryToDrizzlePostgres<ConnectionRecord>(
|
|
97
|
+
{
|
|
98
|
+
connectionTypes: ['one', 'two', 'five'],
|
|
99
|
+
invitationDid: 'some string',
|
|
100
|
+
},
|
|
101
|
+
didcommConnection
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
).toHaveLength(0)
|
|
105
|
+
|
|
106
|
+
expect(
|
|
107
|
+
await db
|
|
108
|
+
.select()
|
|
109
|
+
.from(didcommConnection)
|
|
110
|
+
.where(
|
|
111
|
+
queryToDrizzlePostgres<ConnectionRecord>(
|
|
112
|
+
{
|
|
113
|
+
connectionTypes: ['one'],
|
|
114
|
+
invitationDid: 'some string',
|
|
115
|
+
},
|
|
116
|
+
didcommConnection
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
).toHaveLength(1)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
test('should correctly query custom tag column value', async () => {
|
|
123
|
+
expect(
|
|
124
|
+
await db
|
|
125
|
+
.select()
|
|
126
|
+
.from(didcommConnection)
|
|
127
|
+
.where(
|
|
128
|
+
queryToDrizzlePostgres<ConnectionRecord>(
|
|
129
|
+
{
|
|
130
|
+
anotherCustomTag: true,
|
|
131
|
+
invitationDid: 'some string',
|
|
132
|
+
},
|
|
133
|
+
didcommConnection
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
).toHaveLength(1)
|
|
137
|
+
|
|
138
|
+
expect(
|
|
139
|
+
await db
|
|
140
|
+
.select()
|
|
141
|
+
.from(didcommConnection)
|
|
142
|
+
.where(
|
|
143
|
+
queryToDrizzlePostgres<ConnectionRecord>(
|
|
144
|
+
{
|
|
145
|
+
anotherCustomTag: false,
|
|
146
|
+
invitationDid: 'some string',
|
|
147
|
+
},
|
|
148
|
+
didcommConnection
|
|
149
|
+
)
|
|
150
|
+
)
|
|
151
|
+
).toHaveLength(0)
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
test('should correctly query custom tag column array value', async () => {
|
|
155
|
+
expect(
|
|
156
|
+
await db
|
|
157
|
+
.select()
|
|
158
|
+
.from(didcommConnection)
|
|
159
|
+
.where(
|
|
160
|
+
queryToDrizzlePostgres<ConnectionRecord>(
|
|
161
|
+
{
|
|
162
|
+
myCustomTag: ['First', 'Second'],
|
|
163
|
+
invitationDid: 'some string',
|
|
164
|
+
},
|
|
165
|
+
didcommConnection
|
|
166
|
+
)
|
|
167
|
+
)
|
|
168
|
+
).toHaveLength(1)
|
|
169
|
+
|
|
170
|
+
expect(
|
|
171
|
+
await db
|
|
172
|
+
.select()
|
|
173
|
+
.from(didcommConnection)
|
|
174
|
+
.where(
|
|
175
|
+
queryToDrizzlePostgres<ConnectionRecord>(
|
|
176
|
+
{
|
|
177
|
+
myCustomTag: ['Third'],
|
|
178
|
+
invitationDid: 'some string',
|
|
179
|
+
},
|
|
180
|
+
didcommConnection
|
|
181
|
+
)
|
|
182
|
+
)
|
|
183
|
+
).toHaveLength(0)
|
|
184
|
+
|
|
185
|
+
expect(
|
|
186
|
+
await db
|
|
187
|
+
.select()
|
|
188
|
+
.from(didcommConnection)
|
|
189
|
+
.where(
|
|
190
|
+
queryToDrizzlePostgres<ConnectionRecord>(
|
|
191
|
+
{
|
|
192
|
+
myCustomTag: ['First'],
|
|
193
|
+
invitationDid: 'some string',
|
|
194
|
+
},
|
|
195
|
+
didcommConnection
|
|
196
|
+
)
|
|
197
|
+
)
|
|
198
|
+
).toHaveLength(1)
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
test('should correctly query with and/or', async () => {
|
|
202
|
+
expect(
|
|
203
|
+
await db
|
|
204
|
+
.select()
|
|
205
|
+
.from(didcommConnection)
|
|
206
|
+
.where(
|
|
207
|
+
queryToDrizzlePostgres<ConnectionRecord>(
|
|
208
|
+
{
|
|
209
|
+
connectionTypes: ['one'],
|
|
210
|
+
$or: [
|
|
211
|
+
{
|
|
212
|
+
connectionTypes: ['two'],
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
connectionTypes: ['three'],
|
|
216
|
+
},
|
|
217
|
+
],
|
|
218
|
+
$and: [
|
|
219
|
+
{
|
|
220
|
+
connectionTypes: ['four'],
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
},
|
|
224
|
+
didcommConnection
|
|
225
|
+
)
|
|
226
|
+
)
|
|
227
|
+
).toHaveLength(1)
|
|
228
|
+
|
|
229
|
+
expect(
|
|
230
|
+
await db
|
|
231
|
+
.select()
|
|
232
|
+
.from(didcommConnection)
|
|
233
|
+
.where(
|
|
234
|
+
queryToDrizzlePostgres<ConnectionRecord>(
|
|
235
|
+
{
|
|
236
|
+
connectionTypes: ['one'],
|
|
237
|
+
$or: [
|
|
238
|
+
{
|
|
239
|
+
connectionTypes: ['two'],
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
connectionTypes: ['three'],
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
$and: [
|
|
246
|
+
{
|
|
247
|
+
connectionTypes: ['four'],
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
connectionTypes: ['two'],
|
|
251
|
+
},
|
|
252
|
+
],
|
|
253
|
+
},
|
|
254
|
+
didcommConnection
|
|
255
|
+
)
|
|
256
|
+
)
|
|
257
|
+
).toHaveLength(0)
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
test('should correctly query with not', async () => {
|
|
261
|
+
expect(
|
|
262
|
+
await db
|
|
263
|
+
.select()
|
|
264
|
+
.from(didcommConnection)
|
|
265
|
+
.where(
|
|
266
|
+
queryToDrizzlePostgres<ConnectionRecord>(
|
|
267
|
+
{
|
|
268
|
+
connectionTypes: ['one'],
|
|
269
|
+
$not: {
|
|
270
|
+
$and: [
|
|
271
|
+
{
|
|
272
|
+
connectionTypes: ['two'],
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
connectionTypes: ['five'],
|
|
276
|
+
},
|
|
277
|
+
],
|
|
278
|
+
$or: [
|
|
279
|
+
{
|
|
280
|
+
connectionTypes: ['two'],
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
connectionTypes: ['three'],
|
|
284
|
+
},
|
|
285
|
+
],
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
didcommConnection
|
|
289
|
+
)
|
|
290
|
+
)
|
|
291
|
+
).toHaveLength(1)
|
|
292
|
+
|
|
293
|
+
expect(
|
|
294
|
+
await db
|
|
295
|
+
.select()
|
|
296
|
+
.from(didcommConnection)
|
|
297
|
+
.where(
|
|
298
|
+
queryToDrizzlePostgres<ConnectionRecord>(
|
|
299
|
+
{
|
|
300
|
+
connectionTypes: ['one'],
|
|
301
|
+
$not: {
|
|
302
|
+
$and: [
|
|
303
|
+
{
|
|
304
|
+
connectionTypes: ['two'],
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
connectionTypes: ['five'],
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
connectionTypes: ['three'],
|
|
311
|
+
},
|
|
312
|
+
],
|
|
313
|
+
$or: [
|
|
314
|
+
{
|
|
315
|
+
connectionTypes: ['two'],
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
connectionTypes: ['three'],
|
|
319
|
+
},
|
|
320
|
+
],
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
didcommConnection
|
|
324
|
+
)
|
|
325
|
+
)
|
|
326
|
+
).toHaveLength(0)
|
|
327
|
+
})
|
|
328
|
+
})
|