@sphereon/ssi-sdk.data-store 0.36.1-feature.fides.fixes.111 → 0.36.1-feature.fides.fixes.117

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sphereon/ssi-sdk.data-store",
3
- "version": "0.36.1-feature.fides.fixes.111+275075fd",
3
+ "version": "0.36.1-feature.fides.fixes.117+9acc9ac1",
4
4
  "source": "src/index.ts",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -28,12 +28,12 @@
28
28
  "dependencies": {
29
29
  "@sphereon/kmp-mdoc-core": "0.2.0-SNAPSHOT.26",
30
30
  "@sphereon/pex": "5.0.0-unstable.28",
31
- "@sphereon/ssi-sdk-ext.did-utils": "0.36.1-feature.fides.fixes.111+275075fd",
32
- "@sphereon/ssi-sdk-ext.identifier-resolution": "0.36.1-feature.fides.fixes.111+275075fd",
33
- "@sphereon/ssi-sdk.agent-config": "0.36.1-feature.fides.fixes.111+275075fd",
34
- "@sphereon/ssi-sdk.core": "0.36.1-feature.fides.fixes.111+275075fd",
35
- "@sphereon/ssi-sdk.data-store-types": "0.36.1-feature.fides.fixes.111+275075fd",
36
- "@sphereon/ssi-types": "0.36.1-feature.fides.fixes.111+275075fd",
31
+ "@sphereon/ssi-sdk-ext.did-utils": "0.36.1-feature.fides.fixes.117+9acc9ac1",
32
+ "@sphereon/ssi-sdk-ext.identifier-resolution": "0.36.1-feature.fides.fixes.117+9acc9ac1",
33
+ "@sphereon/ssi-sdk.agent-config": "0.36.1-feature.fides.fixes.117+9acc9ac1",
34
+ "@sphereon/ssi-sdk.core": "0.36.1-feature.fides.fixes.117+9acc9ac1",
35
+ "@sphereon/ssi-sdk.data-store-types": "0.36.1-feature.fides.fixes.117+9acc9ac1",
36
+ "@sphereon/ssi-types": "0.36.1-feature.fides.fixes.117+9acc9ac1",
37
37
  "@veramo/core": "4.2.0",
38
38
  "@veramo/utils": "4.2.0",
39
39
  "blakejs": "^1.2.1",
@@ -66,5 +66,5 @@
66
66
  "PostgreSQL",
67
67
  "Contact Store"
68
68
  ],
69
- "gitHead": "275075fdc7753426df398e771e7ecdf28b7d1e3b"
69
+ "gitHead": "9acc9ac1a855c5327269e9c76e7028987057c777"
70
70
  }
@@ -109,7 +109,10 @@ export class ContactStore extends AbstractContactStore {
109
109
  const initialResult = await partyRepository.find({ select: ['id'], where: filterConditions })
110
110
 
111
111
  // Fetch the complete entities based on the initial result IDs
112
- const result = await partyRepository.find({ where: { id: In(initialResult.map((party) => party.id)) } })
112
+ const result = await partyRepository.find({
113
+ where: { id: In(initialResult.map((party) => party.id)) },
114
+ relations: ['contact'], // Explicit load prevents eager loading issues
115
+ })
113
116
  debug(`getParties() resulted in ${result.length} parties`)
114
117
  return result
115
118
  .filter((party) => {
@@ -62,7 +62,9 @@ export class CredentialBrandingEntity extends BaseEntity {
62
62
  @BeforeInsert()
63
63
  @BeforeUpdate()
64
64
  setState(): void {
65
- this.state = this.computeState()
65
+ if (this.localeBranding && Array.isArray(this.localeBranding)) {
66
+ this.state = this.computeState()
67
+ }
66
68
  }
67
69
 
68
70
  @BeforeInsert()
@@ -94,20 +94,48 @@ export class IssuanceBrandingStore extends AbstractIssuanceBrandingStore {
94
94
  }
95
95
 
96
96
  debug('Getting credential branding', args)
97
- const result: Array<CredentialBrandingEntity> = await (await this.dbConnection).getRepository(CredentialBrandingEntity).find({
98
- ...(filter && { where: filter }),
99
- })
97
+ const repository: Repository<CredentialBrandingEntity> = (await this.dbConnection).getRepository(CredentialBrandingEntity)
98
+
99
+ if (knownStates && Object.keys(knownStates).length > 0) {
100
+ // First do a lightweight query selecting only id and state to determine which records are "dirty"
101
+ const stateQuery = repository
102
+ .createQueryBuilder('branding')
103
+ .select(['branding.id', 'branding.state'])
104
+ if (filter) {
105
+ stateQuery.where(filter)
106
+ }
107
+ const stateResults: Array<{ id: string; state: string }> = await stateQuery.getRawMany().then((rows) =>
108
+ rows.map((row) => ({
109
+ id: row.branding_id,
110
+ state: row.branding_state,
111
+ })),
112
+ )
100
113
 
101
- const credentialBranding: Array<ICredentialBranding> = result.map((branding: CredentialBrandingEntity) => credentialBrandingFrom(branding))
114
+ // Filter to find dirty record ids (new or changed state)
115
+ const dirtyIds: Array<string> = stateResults
116
+ .filter((result) => {
117
+ const knownState: string | undefined = knownStates[result.id]
118
+ return !knownState || knownState !== result.state
119
+ })
120
+ .map((result) => result.id)
121
+
122
+ if (dirtyIds.length === 0) {
123
+ return []
124
+ }
125
+
126
+ // Only fetch full data for dirty records
127
+ const result: Array<CredentialBrandingEntity> = await repository.find({
128
+ where: { id: In(dirtyIds) },
129
+ })
102
130
 
103
- if (!knownStates) {
104
- return credentialBranding
131
+ return result.map((branding: CredentialBrandingEntity) => credentialBrandingFrom(branding))
105
132
  }
106
133
 
107
- return credentialBranding.filter((branding: ICredentialBranding) => {
108
- const knownState: string | undefined = knownStates[branding.id]
109
- return !knownState || knownState !== branding.state
134
+ const result: Array<CredentialBrandingEntity> = await repository.find({
135
+ ...(filter && { where: filter }),
110
136
  })
137
+
138
+ return result.map((branding: CredentialBrandingEntity) => credentialBrandingFrom(branding))
111
139
  }
112
140
 
113
141
  public removeCredentialBranding = async (args: IRemoveCredentialBrandingArgs): Promise<void> => {
@@ -4,11 +4,17 @@ export class AddBrandingStateSqlite1766000000000 implements MigrationInterface {
4
4
  name = 'AddBrandingState1766000000000'
5
5
 
6
6
  public async up(queryRunner: QueryRunner): Promise<void> {
7
+ // Add state column with empty string default for existing records
8
+ // Note: Existing records will have state='', which won't match computed hashes.
9
+ // This makes the knownStates optimization ineffective until records are naturally updated.
7
10
  await queryRunner.query(`ALTER TABLE "CredentialBranding" ADD COLUMN "state" varchar(255) NOT NULL DEFAULT ''`)
8
11
  await queryRunner.query(`ALTER TABLE "BaseLocaleBranding" ADD COLUMN "state" varchar(255) NOT NULL DEFAULT ''`)
9
12
  }
10
13
 
11
14
  public async down(queryRunner: QueryRunner): Promise<void> {
15
+ // Disable foreign key constraints during migration to avoid issues with DROP TABLE operations
16
+ await queryRunner.query(`PRAGMA foreign_keys = OFF`)
17
+
12
18
  // Recreate CredentialBranding without the state column
13
19
  await queryRunner.query(`
14
20
  CREATE TABLE "CredentialBranding_old"
@@ -67,8 +73,15 @@ export class AddBrandingStateSqlite1766000000000 implements MigrationInterface {
67
73
  `)
68
74
  await queryRunner.query(`DROP TABLE "BaseLocaleBranding"`)
69
75
  await queryRunner.query(`ALTER TABLE "BaseLocaleBranding_old" RENAME TO "BaseLocaleBranding"`)
70
- await queryRunner.query(`CREATE UNIQUE INDEX "IDX_CredentialLocaleBrandingEntity_credentialBranding_locale" ON "BaseLocaleBranding" ("credentialBrandingId", "locale")`)
71
- await queryRunner.query(`CREATE UNIQUE INDEX "IDX_IssuerLocaleBrandingEntity_issuerBranding_locale" ON "BaseLocaleBranding" ("issuerBrandingId", "locale")`)
76
+ await queryRunner.query(
77
+ `CREATE UNIQUE INDEX "IDX_CredentialLocaleBrandingEntity_credentialBranding_locale" ON "BaseLocaleBranding" ("credentialBrandingId", "locale")`,
78
+ )
79
+ await queryRunner.query(
80
+ `CREATE UNIQUE INDEX "IDX_IssuerLocaleBrandingEntity_issuerBranding_locale" ON "BaseLocaleBranding" ("issuerBrandingId", "locale")`,
81
+ )
72
82
  await queryRunner.query(`CREATE INDEX "IDX_BaseLocaleBranding_type" ON "BaseLocaleBranding" ("type")`)
83
+
84
+ // Re-enable foreign key constraints
85
+ await queryRunner.query(`PRAGMA foreign_keys = ON`)
73
86
  }
74
87
  }