@axiom-lattice/pg-stores 1.0.21 → 1.0.23
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +17 -0
- package/dist/index.d.mts +126 -58
- package/dist/index.d.ts +126 -58
- package/dist/index.js +551 -135
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +544 -135
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +7 -0
- package/src/migrations/assistant_migrations.ts +4 -2
- package/src/migrations/assistant_pk_migration.ts +101 -0
- package/src/migrations/assistant_tenant_migration.ts +29 -0
- package/src/migrations/schedule_tenant_migration.ts +75 -0
- package/src/migrations/skill_pk_migration.ts +97 -0
- package/src/migrations/skill_tenant_migration.ts +55 -0
- package/src/migrations/thread_pk_migration.ts +99 -0
- package/src/migrations/thread_tenant_migration.ts +55 -0
- package/src/stores/PostgreSQLAssistantStore.ts +55 -22
- package/src/stores/PostgreSQLScheduleStorage.ts +16 -0
- package/src/stores/PostgreSQLSkillStore.ts +146 -103
- package/src/stores/PostgreSQLThreadStore.ts +40 -30
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* PostgreSQL implementation of SkillStore
|
|
2
|
+
* PostgreSQL implementation of SkillStore with tenant isolation
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { Pool, PoolConfig } from "pg";
|
|
@@ -10,35 +10,28 @@ import {
|
|
|
10
10
|
} from "@axiom-lattice/protocols";
|
|
11
11
|
import { MigrationManager } from "../migrations/migration";
|
|
12
12
|
import { createSkillsTable } from "../migrations/skill_migrations";
|
|
13
|
+
import { addSkillTenantId } from "../migrations/skill_tenant_migration";
|
|
14
|
+
import { changeSkillPrimaryKey } from "../migrations/skill_pk_migration";
|
|
13
15
|
|
|
14
|
-
/**
|
|
15
|
-
* PostgreSQL SkillStore options
|
|
16
|
-
*/
|
|
17
16
|
export interface PostgreSQLSkillStoreOptions {
|
|
18
|
-
/**
|
|
19
|
-
* PostgreSQL connection pool configuration
|
|
20
|
-
* Can be a connection string or PoolConfig object
|
|
21
|
-
*/
|
|
22
17
|
poolConfig: string | PoolConfig;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Whether to run migrations automatically on initialization
|
|
26
|
-
* @default true
|
|
27
|
-
*/
|
|
28
18
|
autoMigrate?: boolean;
|
|
29
19
|
}
|
|
30
20
|
|
|
31
21
|
/**
|
|
32
|
-
* PostgreSQL implementation of SkillStore
|
|
22
|
+
* PostgreSQL implementation of SkillStore with tenant isolation
|
|
23
|
+
*
|
|
24
|
+
* Features:
|
|
25
|
+
* - Multi-tenant isolation via tenant_id
|
|
33
26
|
*/
|
|
34
27
|
export class PostgreSQLSkillStore implements SkillStore {
|
|
35
28
|
private pool: Pool;
|
|
36
29
|
private migrationManager: MigrationManager;
|
|
37
30
|
private initialized: boolean = false;
|
|
38
31
|
private ownsPool: boolean = true;
|
|
32
|
+
private initPromise: Promise<void> | null = null;
|
|
39
33
|
|
|
40
34
|
constructor(options: PostgreSQLSkillStoreOptions) {
|
|
41
|
-
// Create Pool from config
|
|
42
35
|
if (typeof options.poolConfig === "string") {
|
|
43
36
|
this.pool = new Pool({ connectionString: options.poolConfig });
|
|
44
37
|
} else {
|
|
@@ -47,8 +40,9 @@ export class PostgreSQLSkillStore implements SkillStore {
|
|
|
47
40
|
|
|
48
41
|
this.migrationManager = new MigrationManager(this.pool);
|
|
49
42
|
this.migrationManager.register(createSkillsTable);
|
|
43
|
+
this.migrationManager.register(addSkillTenantId);
|
|
44
|
+
this.migrationManager.register(changeSkillPrimaryKey);
|
|
50
45
|
|
|
51
|
-
// Auto-migrate by default
|
|
52
46
|
if (options.autoMigrate !== false) {
|
|
53
47
|
this.initialize().catch((error) => {
|
|
54
48
|
console.error("Failed to initialize PostgreSQLSkillStore:", error);
|
|
@@ -57,31 +51,37 @@ export class PostgreSQLSkillStore implements SkillStore {
|
|
|
57
51
|
}
|
|
58
52
|
}
|
|
59
53
|
|
|
60
|
-
/**
|
|
61
|
-
* Dispose resources and close the connection pool
|
|
62
|
-
* Should be called when the store is no longer needed
|
|
63
|
-
*/
|
|
64
|
-
async dispose(): Promise<void> {
|
|
65
|
-
if (this.ownsPool && this.pool) {
|
|
66
|
-
await this.pool.end();
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
54
|
/**
|
|
71
55
|
* Initialize the store and run migrations
|
|
56
|
+
* Uses a promise-based lock to prevent concurrent initialization
|
|
72
57
|
*/
|
|
73
58
|
async initialize(): Promise<void> {
|
|
74
59
|
if (this.initialized) {
|
|
75
60
|
return;
|
|
76
61
|
}
|
|
77
62
|
|
|
78
|
-
|
|
79
|
-
|
|
63
|
+
if (this.initPromise) {
|
|
64
|
+
return this.initPromise;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this.initPromise = (async () => {
|
|
68
|
+
try {
|
|
69
|
+
await this.migrationManager.migrate();
|
|
70
|
+
this.initialized = true;
|
|
71
|
+
} finally {
|
|
72
|
+
this.initPromise = null;
|
|
73
|
+
}
|
|
74
|
+
})();
|
|
75
|
+
|
|
76
|
+
return this.initPromise;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async dispose(): Promise<void> {
|
|
80
|
+
if (this.ownsPool && this.pool) {
|
|
81
|
+
await this.pool.end();
|
|
82
|
+
}
|
|
80
83
|
}
|
|
81
84
|
|
|
82
|
-
/**
|
|
83
|
-
* Ensure store is initialized
|
|
84
|
-
*/
|
|
85
85
|
private async ensureInitialized(): Promise<void> {
|
|
86
86
|
if (!this.initialized) {
|
|
87
87
|
await this.initialize();
|
|
@@ -93,6 +93,7 @@ export class PostgreSQLSkillStore implements SkillStore {
|
|
|
93
93
|
*/
|
|
94
94
|
private mapRowToSkill(row: {
|
|
95
95
|
id: string;
|
|
96
|
+
tenant_id: string;
|
|
96
97
|
name: string;
|
|
97
98
|
description: string;
|
|
98
99
|
license: string | null;
|
|
@@ -105,28 +106,28 @@ export class PostgreSQLSkillStore implements SkillStore {
|
|
|
105
106
|
}): Skill {
|
|
106
107
|
return {
|
|
107
108
|
id: row.id,
|
|
109
|
+
tenantId: row.tenant_id,
|
|
108
110
|
name: row.name,
|
|
109
111
|
description: row.description,
|
|
110
112
|
license: row.license || undefined,
|
|
111
113
|
compatibility: row.compatibility || undefined,
|
|
112
114
|
metadata: row.metadata || {},
|
|
113
115
|
content: row.content || undefined,
|
|
114
|
-
subSkills: Array.isArray(row.sub_skills)
|
|
115
|
-
? row.sub_skills
|
|
116
|
-
: undefined,
|
|
116
|
+
subSkills: Array.isArray(row.sub_skills) ? row.sub_skills : undefined,
|
|
117
117
|
createdAt: row.created_at,
|
|
118
118
|
updatedAt: row.updated_at,
|
|
119
119
|
};
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
|
-
* Get all skills
|
|
123
|
+
* Get all skills for a tenant
|
|
124
124
|
*/
|
|
125
|
-
async getAllSkills(): Promise<Skill[]> {
|
|
125
|
+
async getAllSkills(tenantId: string): Promise<Skill[]> {
|
|
126
126
|
await this.ensureInitialized();
|
|
127
127
|
|
|
128
128
|
const result = await this.pool.query<{
|
|
129
129
|
id: string;
|
|
130
|
+
tenant_id: string;
|
|
130
131
|
name: string;
|
|
131
132
|
description: string;
|
|
132
133
|
license: string | null;
|
|
@@ -138,23 +139,26 @@ export class PostgreSQLSkillStore implements SkillStore {
|
|
|
138
139
|
updated_at: Date;
|
|
139
140
|
}>(
|
|
140
141
|
`
|
|
141
|
-
SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
142
|
+
SELECT id, tenant_id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
142
143
|
FROM lattice_skills
|
|
144
|
+
WHERE tenant_id = $1
|
|
143
145
|
ORDER BY created_at DESC
|
|
144
|
-
|
|
146
|
+
`,
|
|
147
|
+
[tenantId]
|
|
145
148
|
);
|
|
146
149
|
|
|
147
150
|
return result.rows.map(this.mapRowToSkill);
|
|
148
151
|
}
|
|
149
152
|
|
|
150
153
|
/**
|
|
151
|
-
* Get skill by ID
|
|
154
|
+
* Get skill by ID for a tenant
|
|
152
155
|
*/
|
|
153
|
-
async getSkillById(id: string): Promise<Skill | null> {
|
|
156
|
+
async getSkillById(tenantId: string, id: string): Promise<Skill | null> {
|
|
154
157
|
await this.ensureInitialized();
|
|
155
158
|
|
|
156
159
|
const result = await this.pool.query<{
|
|
157
160
|
id: string;
|
|
161
|
+
tenant_id: string;
|
|
158
162
|
name: string;
|
|
159
163
|
description: string;
|
|
160
164
|
license: string | null;
|
|
@@ -166,11 +170,11 @@ export class PostgreSQLSkillStore implements SkillStore {
|
|
|
166
170
|
updated_at: Date;
|
|
167
171
|
}>(
|
|
168
172
|
`
|
|
169
|
-
SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
173
|
+
SELECT id, tenant_id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
170
174
|
FROM lattice_skills
|
|
171
|
-
WHERE id = $
|
|
175
|
+
WHERE tenant_id = $1 AND id = $2
|
|
172
176
|
`,
|
|
173
|
-
[id]
|
|
177
|
+
[tenantId, id]
|
|
174
178
|
);
|
|
175
179
|
|
|
176
180
|
if (result.rows.length === 0) {
|
|
@@ -181,19 +185,23 @@ export class PostgreSQLSkillStore implements SkillStore {
|
|
|
181
185
|
}
|
|
182
186
|
|
|
183
187
|
/**
|
|
184
|
-
* Create a new skill
|
|
188
|
+
* Create a new skill for a tenant
|
|
185
189
|
*/
|
|
186
|
-
async createSkill(
|
|
190
|
+
async createSkill(
|
|
191
|
+
tenantId: string,
|
|
192
|
+
id: string,
|
|
193
|
+
data: CreateSkillRequest
|
|
194
|
+
): Promise<Skill> {
|
|
187
195
|
await this.ensureInitialized();
|
|
188
196
|
|
|
189
197
|
const now = new Date();
|
|
190
|
-
const metadata = data.metadata || {};
|
|
191
198
|
|
|
192
199
|
await this.pool.query(
|
|
193
200
|
`
|
|
194
|
-
INSERT INTO lattice_skills (id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at)
|
|
195
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
|
201
|
+
INSERT INTO lattice_skills (id, tenant_id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at)
|
|
202
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
|
196
203
|
ON CONFLICT (id) DO UPDATE SET
|
|
204
|
+
tenant_id = EXCLUDED.tenant_id,
|
|
197
205
|
name = EXCLUDED.name,
|
|
198
206
|
description = EXCLUDED.description,
|
|
199
207
|
license = EXCLUDED.license,
|
|
@@ -205,11 +213,12 @@ export class PostgreSQLSkillStore implements SkillStore {
|
|
|
205
213
|
`,
|
|
206
214
|
[
|
|
207
215
|
id,
|
|
216
|
+
tenantId,
|
|
208
217
|
data.name,
|
|
209
218
|
data.description,
|
|
210
219
|
data.license || null,
|
|
211
220
|
data.compatibility || null,
|
|
212
|
-
JSON.stringify(metadata),
|
|
221
|
+
JSON.stringify(data.metadata || {}),
|
|
213
222
|
data.content || null,
|
|
214
223
|
JSON.stringify(data.subSkills || []),
|
|
215
224
|
now,
|
|
@@ -217,116 +226,143 @@ export class PostgreSQLSkillStore implements SkillStore {
|
|
|
217
226
|
]
|
|
218
227
|
);
|
|
219
228
|
|
|
220
|
-
return
|
|
229
|
+
return {
|
|
230
|
+
id,
|
|
231
|
+
tenantId,
|
|
232
|
+
name: data.name,
|
|
233
|
+
description: data.description,
|
|
234
|
+
license: data.license,
|
|
235
|
+
compatibility: data.compatibility,
|
|
236
|
+
metadata: data.metadata || {},
|
|
237
|
+
content: data.content,
|
|
238
|
+
subSkills: data.subSkills,
|
|
239
|
+
createdAt: now,
|
|
240
|
+
updatedAt: now,
|
|
241
|
+
};
|
|
221
242
|
}
|
|
222
243
|
|
|
223
244
|
/**
|
|
224
|
-
* Update an existing skill
|
|
245
|
+
* Update an existing skill for a tenant
|
|
225
246
|
*/
|
|
226
247
|
async updateSkill(
|
|
248
|
+
tenantId: string,
|
|
227
249
|
id: string,
|
|
228
250
|
updates: Partial<CreateSkillRequest>
|
|
229
251
|
): Promise<Skill | null> {
|
|
230
252
|
await this.ensureInitialized();
|
|
231
253
|
|
|
254
|
+
// Get existing skill
|
|
255
|
+
const existing = await this.getSkillById(tenantId, id);
|
|
256
|
+
if (!existing) {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Build update query dynamically based on provided fields
|
|
232
261
|
const updateFields: string[] = [];
|
|
233
|
-
const
|
|
262
|
+
const updateValues: any[] = [];
|
|
234
263
|
let paramIndex = 1;
|
|
235
264
|
|
|
236
265
|
if (updates.name !== undefined) {
|
|
237
266
|
updateFields.push(`name = $${paramIndex++}`);
|
|
238
|
-
|
|
267
|
+
updateValues.push(updates.name);
|
|
239
268
|
}
|
|
240
269
|
|
|
241
270
|
if (updates.description !== undefined) {
|
|
242
271
|
updateFields.push(`description = $${paramIndex++}`);
|
|
243
|
-
|
|
272
|
+
updateValues.push(updates.description);
|
|
244
273
|
}
|
|
245
274
|
|
|
246
275
|
if (updates.license !== undefined) {
|
|
247
276
|
updateFields.push(`license = $${paramIndex++}`);
|
|
248
|
-
|
|
277
|
+
updateValues.push(updates.license || null);
|
|
249
278
|
}
|
|
250
279
|
|
|
251
280
|
if (updates.compatibility !== undefined) {
|
|
252
281
|
updateFields.push(`compatibility = $${paramIndex++}`);
|
|
253
|
-
|
|
282
|
+
updateValues.push(updates.compatibility || null);
|
|
254
283
|
}
|
|
255
284
|
|
|
256
285
|
if (updates.metadata !== undefined) {
|
|
257
286
|
updateFields.push(`metadata = $${paramIndex++}`);
|
|
258
|
-
|
|
287
|
+
updateValues.push(JSON.stringify(updates.metadata || {}));
|
|
259
288
|
}
|
|
260
289
|
|
|
261
290
|
if (updates.content !== undefined) {
|
|
262
291
|
updateFields.push(`content = $${paramIndex++}`);
|
|
263
|
-
|
|
292
|
+
updateValues.push(updates.content || null);
|
|
264
293
|
}
|
|
265
294
|
|
|
266
295
|
if (updates.subSkills !== undefined) {
|
|
267
296
|
updateFields.push(`sub_skills = $${paramIndex++}`);
|
|
268
|
-
|
|
297
|
+
updateValues.push(JSON.stringify(updates.subSkills || []));
|
|
269
298
|
}
|
|
270
299
|
|
|
271
300
|
if (updateFields.length === 0) {
|
|
272
|
-
|
|
301
|
+
// No fields to update
|
|
302
|
+
return existing;
|
|
273
303
|
}
|
|
274
304
|
|
|
305
|
+
// Always update updated_at
|
|
275
306
|
updateFields.push(`updated_at = $${paramIndex++}`);
|
|
276
|
-
|
|
277
|
-
|
|
307
|
+
updateValues.push(new Date());
|
|
308
|
+
|
|
309
|
+
// Add tenant_id and id for WHERE clause
|
|
310
|
+
updateValues.push(tenantId);
|
|
311
|
+
updateValues.push(id);
|
|
278
312
|
|
|
279
313
|
await this.pool.query(
|
|
280
314
|
`
|
|
281
315
|
UPDATE lattice_skills
|
|
282
316
|
SET ${updateFields.join(", ")}
|
|
283
|
-
WHERE id = $${paramIndex}
|
|
317
|
+
WHERE tenant_id = $${paramIndex++} AND id = $${paramIndex}
|
|
284
318
|
`,
|
|
285
|
-
|
|
319
|
+
updateValues
|
|
286
320
|
);
|
|
287
321
|
|
|
288
|
-
|
|
322
|
+
// Return updated skill
|
|
323
|
+
return await this.getSkillById(tenantId, id);
|
|
289
324
|
}
|
|
290
325
|
|
|
291
326
|
/**
|
|
292
|
-
* Delete a skill by ID
|
|
327
|
+
* Delete a skill by ID for a tenant
|
|
293
328
|
*/
|
|
294
|
-
async deleteSkill(id: string): Promise<boolean> {
|
|
329
|
+
async deleteSkill(tenantId: string, id: string): Promise<boolean> {
|
|
295
330
|
await this.ensureInitialized();
|
|
296
331
|
|
|
297
332
|
const result = await this.pool.query(
|
|
298
333
|
`
|
|
299
334
|
DELETE FROM lattice_skills
|
|
300
|
-
WHERE id = $
|
|
335
|
+
WHERE tenant_id = $1 AND id = $2
|
|
301
336
|
`,
|
|
302
|
-
[id]
|
|
337
|
+
[tenantId, id]
|
|
303
338
|
);
|
|
304
339
|
|
|
305
340
|
return result.rowCount !== null && result.rowCount > 0;
|
|
306
341
|
}
|
|
307
342
|
|
|
308
343
|
/**
|
|
309
|
-
* Check if skill exists
|
|
344
|
+
* Check if skill exists for a tenant
|
|
310
345
|
*/
|
|
311
|
-
async hasSkill(id: string): Promise<boolean> {
|
|
346
|
+
async hasSkill(tenantId: string, id: string): Promise<boolean> {
|
|
312
347
|
await this.ensureInitialized();
|
|
313
348
|
|
|
314
|
-
const result = await this.pool.query
|
|
349
|
+
const result = await this.pool.query(
|
|
315
350
|
`
|
|
316
|
-
SELECT
|
|
317
|
-
|
|
318
|
-
|
|
351
|
+
SELECT 1 FROM lattice_skills
|
|
352
|
+
WHERE tenant_id = $1 AND id = $2
|
|
353
|
+
LIMIT 1
|
|
319
354
|
`,
|
|
320
|
-
[id]
|
|
355
|
+
[tenantId, id]
|
|
321
356
|
);
|
|
322
357
|
|
|
323
|
-
return
|
|
358
|
+
return result.rows.length > 0;
|
|
324
359
|
}
|
|
325
360
|
|
|
326
361
|
/**
|
|
327
|
-
* Search skills by metadata
|
|
362
|
+
* Search skills by metadata within a tenant
|
|
328
363
|
*/
|
|
329
364
|
async searchByMetadata(
|
|
365
|
+
tenantId: string,
|
|
330
366
|
metadataKey: string,
|
|
331
367
|
metadataValue: string
|
|
332
368
|
): Promise<Skill[]> {
|
|
@@ -334,6 +370,7 @@ export class PostgreSQLSkillStore implements SkillStore {
|
|
|
334
370
|
|
|
335
371
|
const result = await this.pool.query<{
|
|
336
372
|
id: string;
|
|
373
|
+
tenant_id: string;
|
|
337
374
|
name: string;
|
|
338
375
|
description: string;
|
|
339
376
|
license: string | null;
|
|
@@ -345,25 +382,29 @@ export class PostgreSQLSkillStore implements SkillStore {
|
|
|
345
382
|
updated_at: Date;
|
|
346
383
|
}>(
|
|
347
384
|
`
|
|
348
|
-
SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
385
|
+
SELECT id, tenant_id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
349
386
|
FROM lattice_skills
|
|
350
|
-
WHERE
|
|
387
|
+
WHERE tenant_id = $1 AND metadata ->> $2 = $3
|
|
351
388
|
ORDER BY created_at DESC
|
|
352
389
|
`,
|
|
353
|
-
[metadataKey, metadataValue]
|
|
390
|
+
[tenantId, metadataKey, metadataValue]
|
|
354
391
|
);
|
|
355
392
|
|
|
356
393
|
return result.rows.map(this.mapRowToSkill);
|
|
357
394
|
}
|
|
358
395
|
|
|
359
396
|
/**
|
|
360
|
-
* Filter skills by compatibility
|
|
397
|
+
* Filter skills by compatibility within a tenant
|
|
361
398
|
*/
|
|
362
|
-
async filterByCompatibility(
|
|
399
|
+
async filterByCompatibility(
|
|
400
|
+
tenantId: string,
|
|
401
|
+
compatibility: string
|
|
402
|
+
): Promise<Skill[]> {
|
|
363
403
|
await this.ensureInitialized();
|
|
364
404
|
|
|
365
405
|
const result = await this.pool.query<{
|
|
366
406
|
id: string;
|
|
407
|
+
tenant_id: string;
|
|
367
408
|
name: string;
|
|
368
409
|
description: string;
|
|
369
410
|
license: string | null;
|
|
@@ -375,25 +416,29 @@ export class PostgreSQLSkillStore implements SkillStore {
|
|
|
375
416
|
updated_at: Date;
|
|
376
417
|
}>(
|
|
377
418
|
`
|
|
378
|
-
SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
419
|
+
SELECT id, tenant_id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
379
420
|
FROM lattice_skills
|
|
380
|
-
WHERE compatibility = $
|
|
421
|
+
WHERE tenant_id = $1 AND compatibility = $2
|
|
381
422
|
ORDER BY created_at DESC
|
|
382
423
|
`,
|
|
383
|
-
[compatibility]
|
|
424
|
+
[tenantId, compatibility]
|
|
384
425
|
);
|
|
385
426
|
|
|
386
427
|
return result.rows.map(this.mapRowToSkill);
|
|
387
428
|
}
|
|
388
429
|
|
|
389
430
|
/**
|
|
390
|
-
* Filter skills by license
|
|
431
|
+
* Filter skills by license within a tenant
|
|
391
432
|
*/
|
|
392
|
-
async filterByLicense(
|
|
433
|
+
async filterByLicense(
|
|
434
|
+
tenantId: string,
|
|
435
|
+
license: string
|
|
436
|
+
): Promise<Skill[]> {
|
|
393
437
|
await this.ensureInitialized();
|
|
394
438
|
|
|
395
439
|
const result = await this.pool.query<{
|
|
396
440
|
id: string;
|
|
441
|
+
tenant_id: string;
|
|
397
442
|
name: string;
|
|
398
443
|
description: string;
|
|
399
444
|
license: string | null;
|
|
@@ -405,32 +450,30 @@ export class PostgreSQLSkillStore implements SkillStore {
|
|
|
405
450
|
updated_at: Date;
|
|
406
451
|
}>(
|
|
407
452
|
`
|
|
408
|
-
SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
453
|
+
SELECT id, tenant_id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
409
454
|
FROM lattice_skills
|
|
410
|
-
WHERE license = $
|
|
455
|
+
WHERE tenant_id = $1 AND license = $2
|
|
411
456
|
ORDER BY created_at DESC
|
|
412
457
|
`,
|
|
413
|
-
[license]
|
|
458
|
+
[tenantId, license]
|
|
414
459
|
);
|
|
415
460
|
|
|
416
461
|
return result.rows.map(this.mapRowToSkill);
|
|
417
462
|
}
|
|
418
463
|
|
|
419
464
|
/**
|
|
420
|
-
* Get sub-skills of a parent skill
|
|
465
|
+
* Get sub-skills of a parent skill within a tenant
|
|
466
|
+
* Note: This searches for skills that have the parent skill name in their subSkills array
|
|
421
467
|
*/
|
|
422
|
-
async getSubSkills(
|
|
468
|
+
async getSubSkills(
|
|
469
|
+
tenantId: string,
|
|
470
|
+
parentSkillName: string
|
|
471
|
+
): Promise<Skill[]> {
|
|
423
472
|
await this.ensureInitialized();
|
|
424
473
|
|
|
425
|
-
const parentSkill = await this.getSkillById(parentSkillName);
|
|
426
|
-
if (!parentSkill || !parentSkill.subSkills || parentSkill.subSkills.length === 0) {
|
|
427
|
-
return [];
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
// Query all sub-skills in one query
|
|
431
|
-
const placeholders = parentSkill.subSkills.map((_, index) => `$${index + 1}`).join(", ");
|
|
432
474
|
const result = await this.pool.query<{
|
|
433
475
|
id: string;
|
|
476
|
+
tenant_id: string;
|
|
434
477
|
name: string;
|
|
435
478
|
description: string;
|
|
436
479
|
license: string | null;
|
|
@@ -442,12 +485,12 @@ export class PostgreSQLSkillStore implements SkillStore {
|
|
|
442
485
|
updated_at: Date;
|
|
443
486
|
}>(
|
|
444
487
|
`
|
|
445
|
-
SELECT id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
488
|
+
SELECT id, tenant_id, name, description, license, compatibility, metadata, content, sub_skills, created_at, updated_at
|
|
446
489
|
FROM lattice_skills
|
|
447
|
-
WHERE
|
|
490
|
+
WHERE tenant_id = $1 AND sub_skills @> to_jsonb($2::text)
|
|
448
491
|
ORDER BY created_at DESC
|
|
449
492
|
`,
|
|
450
|
-
|
|
493
|
+
[tenantId, JSON.stringify([parentSkillName])]
|
|
451
494
|
);
|
|
452
495
|
|
|
453
496
|
return result.rows.map(this.mapRowToSkill);
|