@pikku/kysely 0.13.16 → 0.13.18
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 +135 -0
- package/bin/pikku-kysely-pure.ts +0 -0
- package/dist/src/coercion-plugin.d.ts +41 -0
- package/dist/src/coercion-plugin.js +150 -0
- package/dist/src/create-audited-kysely.d.ts +1 -1
- package/dist/src/index.d.ts +4 -3
- package/dist/src/index.js +1 -0
- package/dist/src/kysely-agent-run-scores.d.ts +1 -1
- package/dist/src/kysely-agent-run-service.d.ts +1 -2
- package/dist/src/kysely-agent-run-state-service.d.ts +2 -2
- package/dist/src/kysely-agent-storage-service.d.ts +2 -2
- package/dist/src/kysely-audit-service.d.ts +3 -3
- package/dist/src/kysely-channel-store.d.ts +1 -1
- package/dist/src/kysely-credential-service.js +1 -1
- package/dist/src/kysely-deployment-service.d.ts +3 -2
- package/dist/src/kysely-deployment-service.js +2 -2
- package/dist/src/kysely-eventhub-store.d.ts +1 -1
- package/dist/src/kysely-eventhub-store.js +1 -1
- package/dist/src/kysely-scope-service.d.ts +3 -3
- package/dist/src/kysely-secret-service.d.ts +1 -1
- package/dist/src/kysely-secret-service.js +2 -2
- package/dist/src/kysely-session-store.d.ts +1 -1
- package/dist/src/kysely-tables.d.ts +1 -1
- package/dist/src/kysely-virtual-user-run-store.d.ts +1 -1
- package/dist/src/kysely-webhook-service.d.ts +1 -1
- package/dist/src/kysely-webhook-service.js +1 -1
- package/dist/src/kysely-workflow-mirror.d.ts +2 -2
- package/dist/src/kysely-workflow-run-service.d.ts +1 -1
- package/dist/src/kysely-workflow-service.d.ts +2 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/src/coercion-plugin.test.ts +160 -0
- package/src/coercion-plugin.ts +187 -0
- package/src/create-audited-kysely.test.ts +1 -1
- package/src/create-audited-kysely.ts +1 -1
- package/src/index.ts +9 -6
- package/src/kysely-agent-run-scores.ts +1 -1
- package/src/kysely-agent-run-service.ts +3 -2
- package/src/kysely-agent-run-state-service.ts +3 -3
- package/src/kysely-agent-storage-service.ts +7 -7
- package/src/kysely-audit-service.test.ts +1 -1
- package/src/kysely-audit-service.ts +4 -8
- package/src/kysely-channel-store.ts +1 -1
- package/src/kysely-credential-service.ts +5 -5
- package/src/kysely-deployment-service.ts +5 -4
- package/src/kysely-eventhub-store.ts +1 -1
- package/src/kysely-scope-service.ts +3 -3
- package/src/kysely-secret-service.ts +7 -6
- package/src/kysely-services.test.ts +1 -1
- package/src/kysely-session-store.ts +1 -1
- package/src/kysely-tables.ts +1 -1
- package/src/kysely-virtual-user-run-store.ts +1 -1
- package/src/kysely-webhook-service.test.ts +1 -1
- package/src/kysely-webhook-service.ts +2 -2
- package/src/kysely-workflow-mirror.ts +2 -2
- package/src/kysely-workflow-run-service.ts +1 -1
- package/src/kysely-workflow-service.test.ts +0 -1
- package/src/kysely-workflow-service.ts +11 -2
- package/dist/src/kysely-ai-agent-run-service.d.ts +0 -22
- package/dist/src/kysely-ai-agent-run-service.js +0 -190
- package/dist/src/kysely-ai-run-scores.d.ts +0 -10
- package/dist/src/kysely-ai-run-scores.js +0 -34
- package/dist/src/kysely-ai-run-state-service.d.ts +0 -24
- package/dist/src/kysely-ai-run-state-service.js +0 -169
- package/dist/src/kysely-ai-storage-service.d.ts +0 -40
- package/dist/src/kysely-ai-storage-service.js +0 -530
- package/dist/src/schema/ai.schema.d.ts +0 -12
- package/dist/src/schema/ai.schema.js +0 -102
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { describe, test } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
import type { QueryResult, UnknownRow } from 'kysely'
|
|
4
|
+
import { createCoercionPlugin, type CoercionMap } from './coercion-plugin.js'
|
|
5
|
+
|
|
6
|
+
function selectFrom(...tables: string[]) {
|
|
7
|
+
return {
|
|
8
|
+
kind: 'SelectQueryNode',
|
|
9
|
+
from: {
|
|
10
|
+
kind: 'FromNode',
|
|
11
|
+
froms: tables.map((table) => ({
|
|
12
|
+
kind: 'TableNode',
|
|
13
|
+
table: {
|
|
14
|
+
kind: 'SchemableIdentifierNode',
|
|
15
|
+
identifier: { kind: 'IdentifierNode', name: table },
|
|
16
|
+
},
|
|
17
|
+
})),
|
|
18
|
+
},
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const runTransform = async (
|
|
23
|
+
map: CoercionMap,
|
|
24
|
+
rows: UnknownRow[],
|
|
25
|
+
node?: unknown
|
|
26
|
+
): Promise<UnknownRow[]> => {
|
|
27
|
+
const plugin = createCoercionPlugin({ map })
|
|
28
|
+
const queryId = {} as { queryId: string }
|
|
29
|
+
if (node !== undefined) {
|
|
30
|
+
plugin.transformQuery({ node, queryId } as any)
|
|
31
|
+
}
|
|
32
|
+
const result = { rows } as QueryResult<UnknownRow>
|
|
33
|
+
const out = await plugin.transformResult({ result, queryId } as any)
|
|
34
|
+
return out.rows as UnknownRow[]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe('createCoercionPlugin', () => {
|
|
38
|
+
test('transformQuery passes the node through untouched', () => {
|
|
39
|
+
const plugin = createCoercionPlugin({ map: {} })
|
|
40
|
+
const node = selectFrom('users') as any
|
|
41
|
+
assert.equal(
|
|
42
|
+
plugin.transformQuery({ node, queryId: { queryId: 'x' } } as any),
|
|
43
|
+
node
|
|
44
|
+
)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test('coerces date columns from ISO strings to Date', async () => {
|
|
48
|
+
const [row] = await runTransform({ users: { created_at: 'date' } }, [
|
|
49
|
+
{ created_at: '2026-06-26T00:00:00.000Z' },
|
|
50
|
+
])
|
|
51
|
+
assert.ok(row!.created_at instanceof Date)
|
|
52
|
+
assert.equal(
|
|
53
|
+
(row!.created_at as Date).toISOString(),
|
|
54
|
+
'2026-06-26T00:00:00.000Z'
|
|
55
|
+
)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('leaves unparseable date strings untouched', async () => {
|
|
59
|
+
const [row] = await runTransform({ users: { created_at: 'date' } }, [
|
|
60
|
+
{ created_at: 'not-a-date' },
|
|
61
|
+
])
|
|
62
|
+
assert.equal(row!.created_at, 'not-a-date')
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
test('coerces bool columns from 0/1 numbers and bigints', async () => {
|
|
66
|
+
const rows = await runTransform(
|
|
67
|
+
{ users: { is_active: 'bool', has_pets: 'bool' } },
|
|
68
|
+
[{ is_active: 1, has_pets: 0n }]
|
|
69
|
+
)
|
|
70
|
+
assert.equal(rows[0]!.is_active, true)
|
|
71
|
+
assert.equal(rows[0]!.has_pets, false)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
test('parses json columns and tolerates invalid json', async () => {
|
|
75
|
+
const rows = await runTransform(
|
|
76
|
+
{ users: { meta: 'json', broken: 'json' } },
|
|
77
|
+
[{ meta: '{"a":1}', broken: '{bad' }]
|
|
78
|
+
)
|
|
79
|
+
assert.deepEqual(rows[0]!.meta, { a: 1 })
|
|
80
|
+
assert.equal(rows[0]!.broken, '{bad')
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test('passes through null values and unmapped columns', async () => {
|
|
84
|
+
const rows = await runTransform({ users: { created_at: 'date' } }, [
|
|
85
|
+
{ created_at: null, name: 'leave me' },
|
|
86
|
+
])
|
|
87
|
+
assert.equal(rows[0]!.created_at, null)
|
|
88
|
+
assert.equal(rows[0]!.name, 'leave me')
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
test('matches both snake_case and camelCase column names', async () => {
|
|
92
|
+
const rows = await runTransform({ users: { created_at: 'date' } }, [
|
|
93
|
+
{ createdAt: '2026-06-26T00:00:00.000Z' },
|
|
94
|
+
])
|
|
95
|
+
assert.ok(rows[0]!.createdAt instanceof Date)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
test('leaves columns ambiguous across tables uncoerced', async () => {
|
|
99
|
+
const rows = await runTransform(
|
|
100
|
+
{ users: { value: 'json' }, events: { value: 'bool' } },
|
|
101
|
+
[{ value: '{"a":1}' }]
|
|
102
|
+
)
|
|
103
|
+
assert.equal(rows[0]!.value, '{"a":1}')
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
test('still coerces columns that agree across tables', async () => {
|
|
107
|
+
const rows = await runTransform(
|
|
108
|
+
{ users: { active: 'bool' }, events: { active: 'bool' } },
|
|
109
|
+
[{ active: 1 }]
|
|
110
|
+
)
|
|
111
|
+
assert.equal(rows[0]!.active, true)
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
test('uses table-qualified coercions when names collide', async () => {
|
|
115
|
+
const map: CoercionMap = {
|
|
116
|
+
users: { settings: 'json' },
|
|
117
|
+
posts: { settings: 'bool' },
|
|
118
|
+
}
|
|
119
|
+
const fromUsers = await runTransform(
|
|
120
|
+
map,
|
|
121
|
+
[{ settings: '{"theme":"dark"}' }],
|
|
122
|
+
selectFrom('users')
|
|
123
|
+
)
|
|
124
|
+
assert.deepEqual(fromUsers[0]!.settings, { theme: 'dark' })
|
|
125
|
+
|
|
126
|
+
const fromPosts = await runTransform(
|
|
127
|
+
map,
|
|
128
|
+
[{ settings: 1 }],
|
|
129
|
+
selectFrom('posts')
|
|
130
|
+
)
|
|
131
|
+
assert.equal(fromPosts[0]!.settings, true)
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
test('table-qualified lookup matches camelCase result columns too', async () => {
|
|
135
|
+
const rows = await runTransform(
|
|
136
|
+
{ users: { created_at: 'date' }, jobs: { created_at: 'json' } },
|
|
137
|
+
[{ createdAt: '2026-06-26T00:00:00.000Z' }],
|
|
138
|
+
selectFrom('users')
|
|
139
|
+
)
|
|
140
|
+
assert.ok(rows[0]!.createdAt instanceof Date)
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
test('a join whose tables disagree leaves the column uncoerced', async () => {
|
|
144
|
+
const rows = await runTransform(
|
|
145
|
+
{ users: { value: 'json' }, events: { value: 'bool' } },
|
|
146
|
+
[{ value: '{"a":1}' }],
|
|
147
|
+
selectFrom('users', 'events')
|
|
148
|
+
)
|
|
149
|
+
assert.equal(rows[0]!.value, '{"a":1}')
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
test('falls back to flat keys when the query names no known table', async () => {
|
|
153
|
+
const rows = await runTransform(
|
|
154
|
+
{ users: { created_at: 'date' } },
|
|
155
|
+
[{ createdAt: '2026-01-02T03:04:05.000Z' }],
|
|
156
|
+
selectFrom('unrelated')
|
|
157
|
+
)
|
|
158
|
+
assert.ok(rows[0]!.createdAt instanceof Date)
|
|
159
|
+
})
|
|
160
|
+
})
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import type { KyselyPlugin, RootOperationNode, UnknownRow } from 'kysely'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The kinds a column can be coerced *to* at runtime. This is the value type of
|
|
5
|
+
* the generated `CoercionMap`, so it is a public artifact contract — a kind may
|
|
6
|
+
* only appear here if `fromDb` below actually does something with it.
|
|
7
|
+
*
|
|
8
|
+
* `uuid` is deliberately absent: it is an annotation kind (it selects the `Uuid`
|
|
9
|
+
* TypeScript type in the generated schema) but not a coercion kind, and the
|
|
10
|
+
* codegen filters it out of `coercion.gen.ts` for exactly that reason — a UUID
|
|
11
|
+
* is a string in both Postgres and SQLite.
|
|
12
|
+
*/
|
|
13
|
+
export type ColumnKind = 'date' | 'bool' | 'json'
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Per-table column kind map. Keys are the table names queries are written
|
|
17
|
+
* against; inner keys are snake_case column names.
|
|
18
|
+
* Generated into `outDir/db/coercion.gen.ts` by `pikku db migrate` from the
|
|
19
|
+
* explicit `kind` entries in `db/annotations.ts`.
|
|
20
|
+
*/
|
|
21
|
+
export type CoercionMap = Record<string, Record<string, ColumnKind>>
|
|
22
|
+
|
|
23
|
+
export interface CreateCoercionPluginOptions {
|
|
24
|
+
map: CoercionMap
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function fromDb(value: unknown, kind: ColumnKind): unknown {
|
|
28
|
+
if (value == null) return value
|
|
29
|
+
switch (kind) {
|
|
30
|
+
case 'date':
|
|
31
|
+
if (typeof value === 'string') {
|
|
32
|
+
const d = new Date(value)
|
|
33
|
+
return Number.isNaN(d.getTime()) ? value : d
|
|
34
|
+
}
|
|
35
|
+
return value
|
|
36
|
+
case 'bool':
|
|
37
|
+
if (typeof value === 'number') return value !== 0
|
|
38
|
+
if (typeof value === 'bigint') return value !== 0n
|
|
39
|
+
return value
|
|
40
|
+
case 'json':
|
|
41
|
+
if (typeof value !== 'string') return value
|
|
42
|
+
try {
|
|
43
|
+
return JSON.parse(value)
|
|
44
|
+
} catch {
|
|
45
|
+
return value
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function snakeToCamel(name: string): string {
|
|
51
|
+
return name.replace(/_([a-z])/g, (_, c) => c.toUpperCase())
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface ResolvedMaps {
|
|
55
|
+
/** `table.column` → kind, for the exact per-query resolution. */
|
|
56
|
+
qualified: Record<string, ColumnKind>
|
|
57
|
+
/** `column` → kind, the fallback for when the query's tables say nothing. */
|
|
58
|
+
flat: Record<string, ColumnKind>
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Flatten the per-table map into a table-qualified lookup plus a bare
|
|
63
|
+
* column-name fallback. Both are indexed by BOTH snake_case and camelCase so
|
|
64
|
+
* they work regardless of CamelCasePlugin ordering in the plugin array.
|
|
65
|
+
*
|
|
66
|
+
* When two tables disagree on the kind for the same column name, the bare name
|
|
67
|
+
* is ambiguous (a joined/aliased query could carry either) and is dropped from
|
|
68
|
+
* the flat map rather than letting whichever table was processed last win. The
|
|
69
|
+
* qualified map still resolves it whenever the query names its tables.
|
|
70
|
+
*/
|
|
71
|
+
function buildMaps(map: CoercionMap): ResolvedMaps {
|
|
72
|
+
const qualified: Record<string, ColumnKind> = {}
|
|
73
|
+
const flat: Record<string, ColumnKind> = {}
|
|
74
|
+
const ambiguous = new Set<string>()
|
|
75
|
+
const assignFlat = (key: string, kind: ColumnKind) => {
|
|
76
|
+
const existing = flat[key]
|
|
77
|
+
if (existing !== undefined && existing !== kind) {
|
|
78
|
+
ambiguous.add(key)
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
flat[key] = kind
|
|
82
|
+
}
|
|
83
|
+
for (const [table, cols] of Object.entries(map)) {
|
|
84
|
+
for (const [col, kind] of Object.entries(cols)) {
|
|
85
|
+
const camel = snakeToCamel(col)
|
|
86
|
+
qualified[`${table}.${col}`] = kind
|
|
87
|
+
qualified[`${table}.${camel}`] = kind
|
|
88
|
+
assignFlat(col, kind)
|
|
89
|
+
assignFlat(camel, kind)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
for (const key of ambiguous) delete flat[key]
|
|
93
|
+
return { qualified, flat }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Collect every table named anywhere in the query's operation node, so a result
|
|
98
|
+
* column can be resolved against the tables the query actually touched instead
|
|
99
|
+
* of against every table in the schema.
|
|
100
|
+
*/
|
|
101
|
+
function collectQueryTables(node: unknown, out: Set<string>): void {
|
|
102
|
+
if (!node || typeof node !== 'object') return
|
|
103
|
+
|
|
104
|
+
const op = node as {
|
|
105
|
+
kind?: string
|
|
106
|
+
table?: { identifier?: { name?: string } }
|
|
107
|
+
}
|
|
108
|
+
if (op.kind === 'TableNode') {
|
|
109
|
+
const tableName = op.table?.identifier?.name
|
|
110
|
+
if (typeof tableName === 'string' && tableName.length > 0)
|
|
111
|
+
out.add(tableName)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
for (const value of Object.values(node)) {
|
|
115
|
+
if (Array.isArray(value)) {
|
|
116
|
+
for (const item of value) collectQueryTables(item, out)
|
|
117
|
+
} else {
|
|
118
|
+
collectQueryTables(value, out)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Resolve a result column's kind against the query's tables, falling back to
|
|
125
|
+
* the bare column name. Tables that disagree with each other are as ambiguous
|
|
126
|
+
* as two schema tables are, so they fall back too.
|
|
127
|
+
*/
|
|
128
|
+
function lookupKind(
|
|
129
|
+
maps: ResolvedMaps,
|
|
130
|
+
tables: readonly string[],
|
|
131
|
+
col: string
|
|
132
|
+
): ColumnKind | undefined {
|
|
133
|
+
let matchedKind: ColumnKind | undefined
|
|
134
|
+
for (const table of tables) {
|
|
135
|
+
const kind = maps.qualified[`${table}.${col}`]
|
|
136
|
+
if (!kind) continue
|
|
137
|
+
if (matchedKind && matchedKind !== kind) return maps.flat[col]
|
|
138
|
+
matchedKind = kind
|
|
139
|
+
}
|
|
140
|
+
return matchedKind ?? maps.flat[col]
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Convert values stored in a dialect's on-disk representation back into the
|
|
145
|
+
* logical types app code expects (Date / boolean / parsed JSON).
|
|
146
|
+
*
|
|
147
|
+
* SQLite is what makes this necessary — it stores dates as TEXT, booleans as
|
|
148
|
+
* INTEGER and JSON as TEXT — but the plugin is dialect-neutral: on Postgres the
|
|
149
|
+
* driver already returns Date/boolean/object, and every branch of `fromDb`
|
|
150
|
+
* passes a non-string, non-number value straight through. That is why it lives
|
|
151
|
+
* in `@pikku/kysely` next to `SerializePlugin` rather than in a SQLite package:
|
|
152
|
+
* the CLI installs it on its local Postgres database too.
|
|
153
|
+
*
|
|
154
|
+
* Write-side coercion (Date → ISO string, boolean → 0/1, object → JSON) is
|
|
155
|
+
* handled in the SQLite database adapters (always-on), so this plugin is
|
|
156
|
+
* read-only.
|
|
157
|
+
*
|
|
158
|
+
* Place AFTER CamelCasePlugin in the plugin array (or it handles both
|
|
159
|
+
* orderings via the dual-keyed maps).
|
|
160
|
+
*/
|
|
161
|
+
export function createCoercionPlugin(
|
|
162
|
+
options: CreateCoercionPluginOptions
|
|
163
|
+
): KyselyPlugin {
|
|
164
|
+
const maps = buildMaps(options.map)
|
|
165
|
+
const queryTables = new WeakMap<object, readonly string[]>()
|
|
166
|
+
return {
|
|
167
|
+
transformQuery(args) {
|
|
168
|
+
const tables = new Set<string>()
|
|
169
|
+
collectQueryTables(args.node as RootOperationNode, tables)
|
|
170
|
+
queryTables.set(args.queryId, [...tables])
|
|
171
|
+
return args.node
|
|
172
|
+
},
|
|
173
|
+
async transformResult(args) {
|
|
174
|
+
const tables = queryTables.get(args.queryId) ?? []
|
|
175
|
+
const out: UnknownRow[] = []
|
|
176
|
+
for (const row of args.result.rows as UnknownRow[]) {
|
|
177
|
+
const next: UnknownRow = { ...row }
|
|
178
|
+
for (const [col, val] of Object.entries(row)) {
|
|
179
|
+
const kind = lookupKind(maps, tables, col)
|
|
180
|
+
if (kind) next[col] = fromDb(val, kind)
|
|
181
|
+
}
|
|
182
|
+
out.push(next)
|
|
183
|
+
}
|
|
184
|
+
return { ...args.result, rows: out }
|
|
185
|
+
},
|
|
186
|
+
}
|
|
187
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -25,6 +25,12 @@ export {
|
|
|
25
25
|
type Serializer,
|
|
26
26
|
type Deserializer,
|
|
27
27
|
} from './serialize-plugin.js'
|
|
28
|
+
export {
|
|
29
|
+
createCoercionPlugin,
|
|
30
|
+
type ColumnKind,
|
|
31
|
+
type CoercionMap,
|
|
32
|
+
type CreateCoercionPluginOptions,
|
|
33
|
+
} from './coercion-plugin.js'
|
|
28
34
|
export {
|
|
29
35
|
auditSchema,
|
|
30
36
|
pikkuSchemas,
|
|
@@ -40,12 +46,9 @@ export {
|
|
|
40
46
|
} from './schema/index.js'
|
|
41
47
|
|
|
42
48
|
export type { KyselyPikkuDB } from './kysely-tables.js'
|
|
43
|
-
export type { WorkflowRunService } from '@pikku/core/
|
|
44
|
-
export type {
|
|
45
|
-
AgentRunService,
|
|
46
|
-
AgentRunRow,
|
|
47
|
-
} from '@pikku/core/ecosystem/agent'
|
|
49
|
+
export type { WorkflowRunService } from '@pikku/core/workflow'
|
|
50
|
+
export type { AgentRunService, AgentRunRow } from '@pikku/core/agent'
|
|
48
51
|
export type {
|
|
49
52
|
VirtualUserRunStore,
|
|
50
53
|
VirtualUserRunRecord,
|
|
51
|
-
} from '@pikku/core/
|
|
54
|
+
} from '@pikku/core/virtual-user'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Kysely } from 'kysely'
|
|
2
2
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
3
|
-
import type { SaveScoreInput } from '@pikku/core/services'
|
|
4
3
|
import type { AgentRunScore } from '@pikku/core/agent-scorer'
|
|
4
|
+
import type { SaveScoreInput } from '@pikku/core/services'
|
|
5
5
|
import { parseJson } from './kysely-json.js'
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { AgentThread, AgentMessage } from '@pikku/core/agent'
|
|
2
1
|
import type {
|
|
2
|
+
AgentThread,
|
|
3
|
+
AgentMessage,
|
|
3
4
|
AgentRunRow,
|
|
4
5
|
AgentRunService,
|
|
5
|
-
} from '@pikku/core/
|
|
6
|
+
} from '@pikku/core/agent'
|
|
6
7
|
import type { Kysely } from 'kysely'
|
|
7
8
|
import { sql } from 'kysely'
|
|
8
9
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { sql } from 'kysely'
|
|
2
2
|
import type { Kysely } from 'kysely'
|
|
3
3
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
4
|
+
import type { AgentRunState } from '@pikku/core/agent'
|
|
5
|
+
import type { AgentRunScore } from '@pikku/core/agent-scorer'
|
|
4
6
|
import type {
|
|
5
7
|
AgentRunStateService,
|
|
6
8
|
CreateRunInput,
|
|
7
9
|
SaveScoreInput,
|
|
8
10
|
} from '@pikku/core/services'
|
|
9
|
-
import type {
|
|
10
|
-
import type { PendingApproval } from '@pikku/core/ecosystem/agent'
|
|
11
|
-
import type { AgentRunScore } from '@pikku/core/agent-scorer'
|
|
11
|
+
import type { PendingApproval } from '@pikku/core/agent'
|
|
12
12
|
import { ensurePikkuSchema } from './schema/index.js'
|
|
13
13
|
import { agentSchema } from './schema/agent.schema.js'
|
|
14
14
|
import { getRunScores, saveRunScore } from './kysely-agent-run-scores.js'
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
AgentStorageService,
|
|
3
|
-
AgentRunStateService,
|
|
4
|
-
CreateRunInput,
|
|
5
|
-
SaveScoreInput,
|
|
6
|
-
} from '@pikku/core/services'
|
|
7
|
-
import type {
|
|
8
|
-
AgentThread,
|
|
9
2
|
AgentMessage,
|
|
10
3
|
AgentRunState,
|
|
4
|
+
AgentThread,
|
|
11
5
|
} from '@pikku/core/agent'
|
|
12
6
|
import type { AgentRunScore } from '@pikku/core/agent-scorer'
|
|
7
|
+
import type {
|
|
8
|
+
AgentRunStateService,
|
|
9
|
+
AgentStorageService,
|
|
10
|
+
CreateRunInput,
|
|
11
|
+
SaveScoreInput,
|
|
12
|
+
} from '@pikku/core/services'
|
|
13
13
|
import type { Kysely } from 'kysely'
|
|
14
14
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
15
15
|
import { parseJson } from './kysely-json.js'
|
|
@@ -2,7 +2,7 @@ import { describe, test, beforeEach } from 'node:test'
|
|
|
2
2
|
import assert from 'node:assert/strict'
|
|
3
3
|
import Database from 'better-sqlite3'
|
|
4
4
|
import { CamelCasePlugin, Kysely, SqliteDialect, sql } from 'kysely'
|
|
5
|
-
import type { AuditEvent } from '
|
|
5
|
+
import type { AuditEvent } from '@pikku/core/services'
|
|
6
6
|
|
|
7
7
|
import { KyselyAuditService } from './kysely-audit-service.js'
|
|
8
8
|
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import type { AuditService } from '@pikku/core'
|
|
2
|
-
import type {
|
|
3
|
-
AuditEvent,
|
|
4
|
-
AuditEventBatch,
|
|
5
|
-
} from '@pikku/core/ecosystem/services'
|
|
1
|
+
import type { AuditService } from '@pikku/core/services'
|
|
2
|
+
import type { AuditEvent, AuditEventBatch } from '@pikku/core/services'
|
|
6
3
|
import type {
|
|
7
4
|
AuditFacets,
|
|
8
5
|
AuditQuery,
|
|
9
6
|
AuditQueryResult,
|
|
10
|
-
} from '@pikku/core/
|
|
7
|
+
} from '@pikku/core/services'
|
|
11
8
|
import type { Kysely } from 'kysely'
|
|
12
9
|
import { ensurePikkuSchema } from './schema/index.js'
|
|
13
10
|
import { auditSchema } from './schema/audit.schema.js'
|
|
@@ -118,8 +115,7 @@ export class KyselyAuditService implements AuditService {
|
|
|
118
115
|
if (!batch.length) return
|
|
119
116
|
const rows = batch.map((e) => {
|
|
120
117
|
const metadata = e.metadata as
|
|
121
|
-
|
|
122
|
-
| undefined
|
|
118
|
+
{ tables?: unknown; changedColumns?: unknown } | undefined
|
|
123
119
|
return {
|
|
124
120
|
audit_id: e.eventId ?? e.queryId ?? fallbackId(),
|
|
125
121
|
occurred_at: e.occurredAt ?? new Date().toISOString(),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Channel } from '@pikku/core/channel'
|
|
2
1
|
import { ChannelStore } from '@pikku/core/channel'
|
|
2
|
+
import type { Channel } from '@pikku/core/channel'
|
|
3
3
|
import type { Kysely } from 'kysely'
|
|
4
4
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
5
5
|
import { parseJson } from './kysely-json.js'
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type { CredentialService } from '@pikku/core/services'
|
|
2
|
-
import type { Kysely } from 'kysely'
|
|
3
|
-
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
4
1
|
import {
|
|
5
2
|
deriveKEK,
|
|
6
|
-
generateKEKSalt,
|
|
7
|
-
envelopeEncrypt,
|
|
8
3
|
envelopeDecrypt,
|
|
4
|
+
envelopeEncrypt,
|
|
9
5
|
envelopeRewrap,
|
|
6
|
+
generateKEKSalt,
|
|
10
7
|
} from '@pikku/core/crypto-utils'
|
|
8
|
+
import type { CredentialService } from '@pikku/core/services'
|
|
9
|
+
import type { Kysely } from 'kysely'
|
|
10
|
+
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
11
11
|
import { ensurePikkuSchema } from './schema/index.js'
|
|
12
12
|
import { credentialSchema } from './schema/credential.schema.js'
|
|
13
13
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { buildRemoteHeaders } from '@pikku/core/
|
|
1
|
+
import { buildRemoteHeaders } from '@pikku/core/remote'
|
|
2
2
|
import type {
|
|
3
3
|
DeploymentService,
|
|
4
4
|
DeploymentServiceConfig,
|
|
5
5
|
DeploymentConfig,
|
|
6
|
-
} from '@pikku/core/
|
|
7
|
-
import type { JWTService
|
|
8
|
-
import {
|
|
6
|
+
} from '@pikku/core/services'
|
|
7
|
+
import type { JWTService } from '@pikku/core/services'
|
|
8
|
+
import type { SecretService } from '@pikku/core/services'
|
|
9
|
+
import { getAllFunctionNames } from '@pikku/core/function'
|
|
9
10
|
import type { Kysely } from 'kysely'
|
|
10
11
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
11
12
|
import { ensurePikkuSchema } from './schema/index.js'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ScopeService } from '@pikku/core/services'
|
|
2
|
-
import type { Role } from '@pikku/core/
|
|
3
|
-
import type { FlatScope } from '@pikku/core/
|
|
4
|
-
import type { SystemRole } from '@pikku/core/
|
|
2
|
+
import type { Role } from '@pikku/core/services'
|
|
3
|
+
import type { FlatScope } from '@pikku/core/scope'
|
|
4
|
+
import type { SystemRole } from '@pikku/core/role'
|
|
5
5
|
import {
|
|
6
6
|
SystemRoleImmutableError,
|
|
7
7
|
SystemRoleShadowedError,
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { createSecretValue, isSecretValue, type SecretValue } from '@pikku/core'
|
|
2
|
-
import type { SecretService, SecretValues } from '@pikku/core/services'
|
|
3
|
-
import type { Kysely } from 'kysely'
|
|
4
|
-
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
5
1
|
import {
|
|
6
2
|
deriveKEK,
|
|
7
|
-
generateKEKSalt,
|
|
8
|
-
envelopeEncrypt,
|
|
9
3
|
envelopeDecrypt,
|
|
4
|
+
envelopeEncrypt,
|
|
10
5
|
envelopeRewrap,
|
|
6
|
+
generateKEKSalt,
|
|
11
7
|
} from '@pikku/core/crypto-utils'
|
|
8
|
+
import { createSecretValue, isSecretValue } from '@pikku/core/classification'
|
|
9
|
+
import type { SecretService, SecretValues } from '@pikku/core/services'
|
|
10
|
+
import type { SecretValue } from '@pikku/core/classification'
|
|
11
|
+
import type { Kysely } from 'kysely'
|
|
12
|
+
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
12
13
|
import { ensurePikkuSchema } from './schema/index.js'
|
|
13
14
|
import { secretSchema } from './schema/secret.schema.js'
|
|
14
15
|
|
|
@@ -5,7 +5,7 @@ import { SerializePlugin } from './serialize-plugin.js'
|
|
|
5
5
|
import Database from 'better-sqlite3'
|
|
6
6
|
import { PostgresJSDialect } from 'kysely-postgres-js'
|
|
7
7
|
import postgres from 'postgres'
|
|
8
|
-
import { defineServiceTests } from '@pikku/core/
|
|
8
|
+
import { defineServiceTests } from '@pikku/core/testing'
|
|
9
9
|
|
|
10
10
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
11
11
|
import { KyselyChannelStore } from './kysely-channel-store.js'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { CoreUserSession } from '@pikku/core'
|
|
2
1
|
import type { SessionStore } from '@pikku/core/services'
|
|
2
|
+
import type { CoreUserSession } from '@pikku/core/types'
|
|
3
3
|
import type { Kysely } from 'kysely'
|
|
4
4
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
5
5
|
import { parseJson } from './kysely-json.js'
|
package/src/kysely-tables.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
VirtualUserRunRecord,
|
|
7
7
|
VirtualUserRunStart,
|
|
8
8
|
VirtualUserRunStore,
|
|
9
|
-
} from '@pikku/core/
|
|
9
|
+
} from '@pikku/core/virtual-user'
|
|
10
10
|
import type { KyselyPikkuDB, VirtualUserRunTable } from './kysely-tables.js'
|
|
11
11
|
import { parseJson } from './kysely-json.js'
|
|
12
12
|
import { ensurePikkuSchema } from './schema/index.js'
|
|
@@ -2,7 +2,7 @@ import { describe, test, beforeEach } from 'node:test'
|
|
|
2
2
|
import assert from 'node:assert/strict'
|
|
3
3
|
import { CamelCasePlugin, Kysely, SqliteDialect } from 'kysely'
|
|
4
4
|
import Database from 'better-sqlite3'
|
|
5
|
-
import { setSingletonServices } from '@pikku/core/
|
|
5
|
+
import { setSingletonServices } from '@pikku/core/state'
|
|
6
6
|
|
|
7
7
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
8
8
|
import { SerializePlugin } from './serialize-plugin.js'
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { QueueWebhookService } from '@pikku/core/services'
|
|
2
|
+
import type { QueueService } from '@pikku/core/queue'
|
|
2
3
|
import {
|
|
3
4
|
PIKKU_OUTGOING_WEBHOOK_QUEUE_NAME,
|
|
4
5
|
type SendWebhookInput,
|
|
@@ -6,8 +7,7 @@ import {
|
|
|
6
7
|
type WebhookAttemptResult,
|
|
7
8
|
type WebhookDeliveryRecord,
|
|
8
9
|
type WebhookDeliveryWithAttempts,
|
|
9
|
-
} from '@pikku/core/
|
|
10
|
-
import type { QueueService } from '@pikku/core/queue'
|
|
10
|
+
} from '@pikku/core/services'
|
|
11
11
|
import type { Kysely } from 'kysely'
|
|
12
12
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
13
13
|
import { ensurePikkuSchema } from './schema/index.js'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SerializedError } from '@pikku/core/
|
|
1
|
+
import type { SerializedError } from '@pikku/core/errors'
|
|
2
2
|
import type {
|
|
3
3
|
StepState,
|
|
4
4
|
WorkflowRunMirror,
|
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
WorkflowStatus,
|
|
7
7
|
WorkflowPlannedStep,
|
|
8
8
|
WorkflowVersionStatus,
|
|
9
|
-
} from '@pikku/core/
|
|
9
|
+
} from '@pikku/core/workflow'
|
|
10
10
|
import type { Kysely } from 'kysely'
|
|
11
11
|
import type { KyselyPikkuDB } from './kysely-tables.js'
|
|
12
12
|
import { ensurePikkuSchema } from './schema/index.js'
|