@pikku/kysely 0.12.6 → 0.12.8

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.
@@ -38,9 +38,9 @@ export class KyselyChannelStore extends ChannelStore {
38
38
  await this.db
39
39
  .insertInto('channels')
40
40
  .values({
41
- channel_id: channelId,
42
- channel_name: channelName,
43
- opening_data: JSON.stringify(openingData || {}),
41
+ channelId: channelId,
42
+ channelName: channelName,
43
+ openingData: JSON.stringify(openingData || {}),
44
44
  })
45
45
  .execute();
46
46
  }
@@ -50,30 +50,30 @@ export class KyselyChannelStore extends ChannelStore {
50
50
  }
51
51
  await this.db
52
52
  .deleteFrom('channels')
53
- .where('channel_id', 'in', channelIds)
53
+ .where('channelId', 'in', channelIds)
54
54
  .execute();
55
55
  }
56
56
  async setUserSession(channelId, session) {
57
57
  await this.db
58
58
  .updateTable('channels')
59
- .set({ user_session: session ? JSON.stringify(session) : null })
60
- .where('channel_id', '=', channelId)
59
+ .set({ userSession: session ? JSON.stringify(session) : null })
60
+ .where('channelId', '=', channelId)
61
61
  .execute();
62
62
  }
63
63
  async getChannelAndSession(channelId) {
64
64
  const row = await this.db
65
65
  .selectFrom('channels')
66
- .select(['channel_id', 'channel_name', 'opening_data', 'user_session'])
67
- .where('channel_id', '=', channelId)
66
+ .select(['channelId', 'channelName', 'openingData', 'userSession'])
67
+ .where('channelId', '=', channelId)
68
68
  .executeTakeFirst();
69
69
  if (!row) {
70
70
  throw new Error(`Channel not found: ${channelId}`);
71
71
  }
72
72
  return {
73
- channelId: row.channel_id,
74
- channelName: row.channel_name,
75
- openingData: parseJson(row.opening_data) ?? {},
76
- session: (parseJson(row.user_session) ?? {}),
73
+ channelId: row.channelId,
74
+ channelName: row.channelName,
75
+ openingData: parseJson(row.openingData) ?? {},
76
+ session: (parseJson(row.userSession) ?? {}),
77
77
  };
78
78
  }
79
79
  async close() { }
@@ -26,5 +26,7 @@ export declare class KyselyCredentialService implements CredentialService {
26
26
  delete(name: string, userId?: string): Promise<void>;
27
27
  has(name: string, userId?: string): Promise<boolean>;
28
28
  getAll(userId: string): Promise<Record<string, unknown>>;
29
+ getUsersWithCredential(name: string): Promise<string[]>;
30
+ getAllUsers(): Promise<string[]>;
29
31
  rotateKEK(): Promise<number>;
30
32
  }
@@ -50,13 +50,13 @@ export class KyselyCredentialService {
50
50
  if (action === 'read' && !this.auditReads)
51
51
  return;
52
52
  await this.db
53
- .insertInto('credentials_audit')
53
+ .insertInto('credentialsAudit')
54
54
  .values({
55
55
  id: crypto.randomUUID(),
56
- credential_name: name,
57
- user_id: userId ?? null,
56
+ credentialName: name,
57
+ userId: userId ?? null,
58
58
  action,
59
- performed_at: new Date().toISOString(),
59
+ performedAt: new Date().toISOString(),
60
60
  })
61
61
  .execute();
62
62
  }
@@ -69,20 +69,20 @@ export class KyselyCredentialService {
69
69
  }
70
70
  whereUserId(qb, userId) {
71
71
  return userId
72
- ? qb.where('user_id', '=', userId)
73
- : qb.where('user_id', 'is', null);
72
+ ? qb.where('userId', '=', userId)
73
+ : qb.where('userId', 'is', null);
74
74
  }
75
75
  async get(name, userId) {
76
76
  let qb = this.db
77
77
  .selectFrom('credentials')
78
- .select(['ciphertext', 'wrapped_dek', 'key_version'])
78
+ .select(['ciphertext', 'wrappedDek', 'keyVersion'])
79
79
  .where('name', '=', name);
80
80
  qb = this.whereUserId(qb, userId);
81
81
  const row = await qb.executeTakeFirst();
82
82
  if (!row)
83
83
  return null;
84
- const kek = this.getKEK(row.key_version);
85
- const plaintext = await envelopeDecrypt(kek, row.ciphertext, row.wrapped_dek);
84
+ const kek = this.getKEK(row.keyVersion);
85
+ const plaintext = await envelopeDecrypt(kek, row.ciphertext, row.wrappedDek);
86
86
  await this.logAudit(name, userId, 'read');
87
87
  try {
88
88
  return JSON.parse(plaintext);
@@ -101,9 +101,9 @@ export class KyselyCredentialService {
101
101
  .updateTable('credentials')
102
102
  .set({
103
103
  ciphertext,
104
- wrapped_dek: wrappedDEK,
105
- key_version: this.keyVersion,
106
- updated_at: now,
104
+ wrappedDek: wrappedDEK,
105
+ keyVersion: this.keyVersion,
106
+ updatedAt: now,
107
107
  })
108
108
  .where('name', '=', name);
109
109
  qb = this.whereUserId(qb, userId);
@@ -114,12 +114,12 @@ export class KyselyCredentialService {
114
114
  .insertInto('credentials')
115
115
  .values({
116
116
  name,
117
- user_id: userId ?? null,
117
+ userId: userId ?? null,
118
118
  ciphertext,
119
- wrapped_dek: wrappedDEK,
120
- key_version: this.keyVersion,
121
- created_at: now,
122
- updated_at: now,
119
+ wrappedDek: wrappedDEK,
120
+ keyVersion: this.keyVersion,
121
+ createdAt: now,
122
+ updatedAt: now,
123
123
  })
124
124
  .execute();
125
125
  }
@@ -143,13 +143,13 @@ export class KyselyCredentialService {
143
143
  async getAll(userId) {
144
144
  const rows = await this.db
145
145
  .selectFrom('credentials')
146
- .select(['name', 'ciphertext', 'wrapped_dek', 'key_version'])
147
- .where('user_id', '=', userId)
146
+ .select(['name', 'ciphertext', 'wrappedDek', 'keyVersion'])
147
+ .where('userId', '=', userId)
148
148
  .execute();
149
149
  const result = {};
150
150
  for (const row of rows) {
151
- const kek = this.getKEK(row.key_version);
152
- const plaintext = await envelopeDecrypt(kek, row.ciphertext, row.wrapped_dek);
151
+ const kek = this.getKEK(row.keyVersion);
152
+ const plaintext = await envelopeDecrypt(kek, row.ciphertext, row.wrappedDek);
153
153
  try {
154
154
  result[row.name] = JSON.parse(plaintext);
155
155
  }
@@ -160,28 +160,46 @@ export class KyselyCredentialService {
160
160
  }
161
161
  return result;
162
162
  }
163
+ async getUsersWithCredential(name) {
164
+ const rows = await this.db
165
+ .selectFrom('credentials')
166
+ .select('userId')
167
+ .where('name', '=', name)
168
+ .where('userId', 'is not', null)
169
+ .execute();
170
+ return rows.map((row) => row.userId).filter(Boolean);
171
+ }
172
+ async getAllUsers() {
173
+ const rows = await this.db
174
+ .selectFrom('credentials')
175
+ .select('userId')
176
+ .distinct()
177
+ .where('userId', 'is not', null)
178
+ .execute();
179
+ return rows.map((row) => row.userId).filter(Boolean);
180
+ }
163
181
  async rotateKEK() {
164
182
  if (!this.previousKey) {
165
183
  throw new Error('No previousKey configured — nothing to rotate from');
166
184
  }
167
185
  const rows = await this.db
168
186
  .selectFrom('credentials')
169
- .select(['name', 'user_id', 'wrapped_dek'])
170
- .where('key_version', '<', this.keyVersion)
187
+ .select(['name', 'userId', 'wrappedDek'])
188
+ .where('keyVersion', '<', this.keyVersion)
171
189
  .execute();
172
190
  for (const row of rows) {
173
- const newWrappedDEK = await envelopeRewrap(this.previousKey, this.key, row.wrapped_dek);
191
+ const newWrappedDEK = await envelopeRewrap(this.previousKey, this.key, row.wrappedDek);
174
192
  let qb = this.db
175
193
  .updateTable('credentials')
176
194
  .set({
177
- wrapped_dek: newWrappedDEK,
178
- key_version: this.keyVersion,
179
- updated_at: new Date().toISOString(),
195
+ wrappedDek: newWrappedDEK,
196
+ keyVersion: this.keyVersion,
197
+ updatedAt: new Date().toISOString(),
180
198
  })
181
199
  .where('name', '=', row.name);
182
- qb = this.whereUserId(qb, row.user_id ?? undefined);
200
+ qb = this.whereUserId(qb, row.userId ?? undefined);
183
201
  await qb.execute();
184
- await this.logAudit(row.name, row.user_id ?? undefined, 'rotate');
202
+ await this.logAudit(row.name, row.userId ?? undefined, 'rotate');
185
203
  }
186
204
  return rows.length;
187
205
  }
@@ -54,27 +54,27 @@ export class KyselyDeploymentService {
54
54
  this.deploymentConfig = { ...config, functions };
55
55
  await this.db.transaction().execute(async (trx) => {
56
56
  await trx
57
- .insertInto('pikku_deployments')
57
+ .insertInto('pikkuDeployments')
58
58
  .values({
59
- deployment_id: config.deploymentId,
59
+ deploymentId: config.deploymentId,
60
60
  endpoint: config.endpoint,
61
- last_heartbeat: new Date(),
61
+ lastHeartbeat: new Date(),
62
62
  })
63
- .onConflict((oc) => oc.column('deployment_id').doUpdateSet({
63
+ .onConflict((oc) => oc.column('deploymentId').doUpdateSet({
64
64
  endpoint: config.endpoint,
65
- last_heartbeat: new Date(),
65
+ lastHeartbeat: new Date(),
66
66
  }))
67
67
  .execute();
68
68
  await trx
69
- .deleteFrom('pikku_deployment_functions')
70
- .where('deployment_id', '=', config.deploymentId)
69
+ .deleteFrom('pikkuDeploymentFunctions')
70
+ .where('deploymentId', '=', config.deploymentId)
71
71
  .execute();
72
72
  if (functions.length > 0) {
73
73
  await trx
74
- .insertInto('pikku_deployment_functions')
74
+ .insertInto('pikkuDeploymentFunctions')
75
75
  .values(functions.map((fn) => ({
76
- deployment_id: config.deploymentId,
77
- function_name: fn,
76
+ deploymentId: config.deploymentId,
77
+ functionName: fn,
78
78
  })))
79
79
  .execute();
80
80
  }
@@ -88,8 +88,8 @@ export class KyselyDeploymentService {
88
88
  }
89
89
  if (this.deploymentConfig) {
90
90
  await this.db
91
- .deleteFrom('pikku_deployments')
92
- .where('deployment_id', '=', this.deploymentConfig.deploymentId)
91
+ .deleteFrom('pikkuDeployments')
92
+ .where('deploymentId', '=', this.deploymentConfig.deploymentId)
93
93
  .execute();
94
94
  }
95
95
  }
@@ -97,15 +97,15 @@ export class KyselyDeploymentService {
97
97
  const ttlMs = this.heartbeatTtl;
98
98
  const cutoff = new Date(Date.now() - ttlMs);
99
99
  const result = await this.db
100
- .selectFrom('pikku_deployments as d')
101
- .innerJoin('pikku_deployment_functions as f', 'f.deployment_id', 'd.deployment_id')
102
- .select(['d.deployment_id', 'd.endpoint'])
103
- .where('f.function_name', '=', name)
104
- .where('d.last_heartbeat', '>', cutoff)
105
- .orderBy('d.last_heartbeat', 'desc')
100
+ .selectFrom('pikkuDeployments as d')
101
+ .innerJoin('pikkuDeploymentFunctions as f', 'f.deploymentId', 'd.deploymentId')
102
+ .select(['d.deploymentId', 'd.endpoint'])
103
+ .where('f.functionName', '=', name)
104
+ .where('d.lastHeartbeat', '>', cutoff)
105
+ .orderBy('d.lastHeartbeat', 'desc')
106
106
  .execute();
107
107
  return result.map((row) => ({
108
- deploymentId: row.deployment_id,
108
+ deploymentId: row.deploymentId,
109
109
  endpoint: row.endpoint,
110
110
  }));
111
111
  }
@@ -128,9 +128,9 @@ export class KyselyDeploymentService {
128
128
  return;
129
129
  try {
130
130
  await this.db
131
- .updateTable('pikku_deployments')
132
- .set({ last_heartbeat: new Date() })
133
- .where('deployment_id', '=', this.deploymentConfig.deploymentId)
131
+ .updateTable('pikkuDeployments')
132
+ .set({ lastHeartbeat: new Date() })
133
+ .where('deploymentId', '=', this.deploymentConfig.deploymentId)
134
134
  .execute();
135
135
  }
136
136
  catch {
@@ -14,18 +14,18 @@ export class KyselyEventHubStore extends EventHubStore {
14
14
  }
15
15
  async getChannelIdsForTopic(topic) {
16
16
  const result = await this.db
17
- .selectFrom('channel_subscriptions')
18
- .select('channel_id')
17
+ .selectFrom('channelSubscriptions')
18
+ .select('channelId')
19
19
  .where('topic', '=', topic)
20
20
  .execute();
21
- return result.map((row) => row.channel_id);
21
+ return result.map((row) => row.channelId);
22
22
  }
23
23
  async subscribe(topic, channelId) {
24
24
  try {
25
25
  await this.db
26
- .insertInto('channel_subscriptions')
27
- .values({ channel_id: channelId, topic: topic })
28
- .onConflict((oc) => oc.columns(['channel_id', 'topic']).doNothing())
26
+ .insertInto('channelSubscriptions')
27
+ .values({ channelId: channelId, topic: topic })
28
+ .onConflict((oc) => oc.columns(['channelId', 'topic']).doNothing())
29
29
  .execute();
30
30
  return true;
31
31
  }
@@ -35,8 +35,8 @@ export class KyselyEventHubStore extends EventHubStore {
35
35
  }
36
36
  async unsubscribe(topic, channelId) {
37
37
  const result = await this.db
38
- .deleteFrom('channel_subscriptions')
39
- .where('channel_id', '=', channelId)
38
+ .deleteFrom('channelSubscriptions')
39
+ .where('channelId', '=', channelId)
40
40
  .where('topic', '=', topic)
41
41
  .executeTakeFirst();
42
42
  return BigInt(result.numDeletedRows) > 0n;
@@ -47,12 +47,12 @@ export class KyselySecretService {
47
47
  if (action === 'read' && !this.auditReads)
48
48
  return;
49
49
  await this.db
50
- .insertInto('secrets_audit')
50
+ .insertInto('secretsAudit')
51
51
  .values({
52
52
  id: crypto.randomUUID(),
53
- secret_key: secretKey,
53
+ secretKey: secretKey,
54
54
  action,
55
- performed_at: new Date().toISOString(),
55
+ performedAt: new Date().toISOString(),
56
56
  })
57
57
  .execute();
58
58
  }
@@ -66,13 +66,13 @@ export class KyselySecretService {
66
66
  async getSecret(key) {
67
67
  const row = await this.db
68
68
  .selectFrom('secrets')
69
- .select(['ciphertext', 'wrapped_dek', 'key_version'])
69
+ .select(['ciphertext', 'wrappedDek', 'keyVersion'])
70
70
  .where('key', '=', key)
71
71
  .executeTakeFirst();
72
72
  if (!row)
73
73
  throw new Error('Requested secret not found');
74
- const kek = this.getKEK(row.key_version);
75
- const result = await envelopeDecrypt(kek, row.ciphertext, row.wrapped_dek);
74
+ const kek = this.getKEK(row.keyVersion);
75
+ const result = await envelopeDecrypt(kek, row.ciphertext, row.wrappedDek);
76
76
  await this.logAudit(key, 'read');
77
77
  return result;
78
78
  }
@@ -97,16 +97,16 @@ export class KyselySecretService {
97
97
  .values({
98
98
  key,
99
99
  ciphertext,
100
- wrapped_dek: wrappedDEK,
101
- key_version: this.keyVersion,
102
- created_at: now,
103
- updated_at: now,
100
+ wrappedDek: wrappedDEK,
101
+ keyVersion: this.keyVersion,
102
+ createdAt: now,
103
+ updatedAt: now,
104
104
  })
105
105
  .onConflict((oc) => oc.column('key').doUpdateSet({
106
106
  ciphertext,
107
- wrapped_dek: wrappedDEK,
108
- key_version: this.keyVersion,
109
- updated_at: now,
107
+ wrappedDek: wrappedDEK,
108
+ keyVersion: this.keyVersion,
109
+ updatedAt: now,
110
110
  }))
111
111
  .execute();
112
112
  await this.logAudit(key, 'write');
@@ -121,17 +121,17 @@ export class KyselySecretService {
121
121
  }
122
122
  const rows = await this.db
123
123
  .selectFrom('secrets')
124
- .select(['key', 'wrapped_dek'])
125
- .where('key_version', '<', this.keyVersion)
124
+ .select(['key', 'wrappedDek'])
125
+ .where('keyVersion', '<', this.keyVersion)
126
126
  .execute();
127
127
  for (const row of rows) {
128
- const newWrappedDEK = await envelopeRewrap(this.previousKey, this.key, row.wrapped_dek);
128
+ const newWrappedDEK = await envelopeRewrap(this.previousKey, this.key, row.wrappedDek);
129
129
  await this.db
130
130
  .updateTable('secrets')
131
131
  .set({
132
- wrapped_dek: newWrappedDEK,
133
- key_version: this.keyVersion,
134
- updated_at: new Date().toISOString(),
132
+ wrappedDek: newWrappedDEK,
133
+ keyVersion: this.keyVersion,
134
+ updatedAt: new Date().toISOString(),
135
135
  })
136
136
  .where('key', '=', row.key)
137
137
  .execute();