@pikku/kysely 0.12.7 → 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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  ## 0.12.0
2
2
 
3
+ ## 0.12.8
4
+
5
+ ### Patch Changes
6
+
7
+ - f85c234: Add unified credential system with per-user OAuth and AI agent pre-flight checks
8
+
9
+ - Unified CredentialService with lazy loading per user via pikkuUserId
10
+ - wire.getCredential() for typed single credential lookup
11
+ - MissingCredentialError with structured payload for client-side connect flows
12
+ - Console UI: Global/Users credential tabs, per-user OAuth connect/revoke
13
+ - AI agent pre-flight check: detects missing OAuth credentials from addon metadata, shows "Connect your accounts" prompt before chat
14
+ - CLI codegen: generates credentialsMeta per addon package for runtime lookup
15
+ - Vercel AI runner: catches MissingCredentialError as runtime fallback
16
+
17
+ - Updated dependencies [f85c234]
18
+ - Updated dependencies [88d3100]
19
+ - @pikku/core@0.12.14
20
+
3
21
  ## 0.12.7
4
22
 
5
23
  ### Patch Changes
@@ -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
  }
@@ -160,6 +160,24 @@ 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');
@@ -105,7 +105,7 @@ export interface AIRunTable {
105
105
  resourceId: string;
106
106
  status: Generated<'running' | 'suspended' | 'completed' | 'failed'>;
107
107
  errorMessage: string | null;
108
- suspendReason: 'approval' | 'rpc-missing' | null;
108
+ suspendReason: 'approval' | 'credential' | 'rpc-missing' | null;
109
109
  missingRpcs: string | null;
110
110
  usageInputTokens: Generated<number>;
111
111
  usageOutputTokens: Generated<number>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/kysely",
3
- "version": "0.12.7",
3
+ "version": "0.12.8",
4
4
  "author": "yasser.fadl@gmail.com",
5
5
  "license": "MIT",
6
6
  "module": "dist/src/index.js",
@@ -20,7 +20,7 @@
20
20
  "prepublishOnly": "yarn build"
21
21
  },
22
22
  "peerDependencies": {
23
- "@pikku/core": "^0.12.10"
23
+ "@pikku/core": "^0.12.14"
24
24
  },
25
25
  "dependencies": {
26
26
  "kysely": "^0.28.12"
@@ -216,6 +216,28 @@ export class KyselyCredentialService implements CredentialService {
216
216
  return result
217
217
  }
218
218
 
219
+ async getUsersWithCredential(name: string): Promise<string[]> {
220
+ const rows = await this.db
221
+ .selectFrom('credentials')
222
+ .select('userId')
223
+ .where('name', '=', name)
224
+ .where('userId', 'is not', null)
225
+ .execute()
226
+
227
+ return rows.map((row) => row.userId!).filter(Boolean)
228
+ }
229
+
230
+ async getAllUsers(): Promise<string[]> {
231
+ const rows = await this.db
232
+ .selectFrom('credentials')
233
+ .select('userId')
234
+ .distinct()
235
+ .where('userId', 'is not', null)
236
+ .execute()
237
+
238
+ return rows.map((row) => row.userId!).filter(Boolean)
239
+ }
240
+
219
241
  async rotateKEK(): Promise<number> {
220
242
  if (!this.previousKey) {
221
243
  throw new Error('No previousKey configured — nothing to rotate from')
@@ -120,7 +120,7 @@ export interface AIRunTable {
120
120
  resourceId: string
121
121
  status: Generated<'running' | 'suspended' | 'completed' | 'failed'>
122
122
  errorMessage: string | null
123
- suspendReason: 'approval' | 'rpc-missing' | null
123
+ suspendReason: 'approval' | 'credential' | 'rpc-missing' | null
124
124
  missingRpcs: string | null
125
125
  usageInputTokens: Generated<number>
126
126
  usageOutputTokens: Generated<number>