@pikku/kysely 0.12.18 → 0.13.0
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 +15 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/kysely-audit-service.d.ts +19 -0
- package/dist/src/kysely-audit-service.js +55 -0
- package/dist/src/kysely-workflow-service.js +5 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/index.ts +1 -0
- package/src/kysely-audit-service.ts +62 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
## 0.13.0
|
|
2
|
+
|
|
3
|
+
### Minor Changes
|
|
4
|
+
|
|
5
|
+
- 241e6cf: Add `KyselyAuditService` — a durable `AuditService` that persists AuditEvents to an `audit` table via Kysely (the companion sink to `createAuditedKysely`). Its column mapping matches Fabric's platform audit-queue consumer, so a locally-run project and a deployed stage produce identical rows. Use it as the local/dev audit sink so audit events persist and are queryable without the platform queue.
|
|
6
|
+
|
|
7
|
+
### Patch Changes
|
|
8
|
+
|
|
9
|
+
- 41ce2cb: Upgrade to TypeScript 6 and raise the minimum Node.js version to 22.
|
|
10
|
+
|
|
11
|
+
All packages now build against `typescript@^6.0.3` and declare `engines.node >= 22`. Internal tooling (`ts-json-schema-generator`, `zod-to-ts`) was bumped to TypeScript 6-compatible releases.
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [41ce2cb]
|
|
14
|
+
- @pikku/core@0.12.44
|
|
15
|
+
|
|
1
16
|
## 0.12.18
|
|
2
17
|
|
|
3
18
|
### Patch Changes
|
package/dist/src/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export { KyselyCredentialService } from './kysely-credential-service.js';
|
|
|
13
13
|
export type { KyselyCredentialServiceConfig } from './kysely-credential-service.js';
|
|
14
14
|
export { KyselySessionStore } from './kysely-session-store.js';
|
|
15
15
|
export { createAuditedKysely, type CreateAuditedKyselyOptions, } from './create-audited-kysely.js';
|
|
16
|
+
export { KyselyAuditService } from './kysely-audit-service.js';
|
|
16
17
|
export { SerializePlugin, SqliteSerializePlugin, BaseSerializePlugin, defaultSerializer, defaultDeserializer, maybeJson, skipTransform, dateRegex, type Serializer, type Deserializer, type SerializePluginOptions, } from './serialize-plugin.js';
|
|
17
18
|
export type { KyselyPikkuDB } from './kysely-tables.js';
|
|
18
19
|
export type { WorkflowRunService } from '@pikku/core/workflow';
|
package/dist/src/index.js
CHANGED
|
@@ -11,4 +11,5 @@ export { KyselySecretService } from './kysely-secret-service.js';
|
|
|
11
11
|
export { KyselyCredentialService } from './kysely-credential-service.js';
|
|
12
12
|
export { KyselySessionStore } from './kysely-session-store.js';
|
|
13
13
|
export { createAuditedKysely, } from './create-audited-kysely.js';
|
|
14
|
+
export { KyselyAuditService } from './kysely-audit-service.js';
|
|
14
15
|
export { SerializePlugin, SqliteSerializePlugin, BaseSerializePlugin, defaultSerializer, defaultDeserializer, maybeJson, skipTransform, dateRegex, } from './serialize-plugin.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AuditEvent, AuditEventBatch, AuditService } from '@pikku/core';
|
|
2
|
+
import type { Kysely } from 'kysely';
|
|
3
|
+
/**
|
|
4
|
+
* Durable {@link AuditService} that persists AuditEvents to an `audit` table
|
|
5
|
+
* via Kysely — the companion sink to {@link createAuditedKysely}.
|
|
6
|
+
*
|
|
7
|
+
* The column mapping matches a platform audit-queue consumer, so a locally-run
|
|
8
|
+
* project and a deployed stage write identical rows (the read side relies only
|
|
9
|
+
* on `type`, `occurred_at`, `actor_user_id`, and the `data` JSON that holds
|
|
10
|
+
* `metadata`). The `audit` table is an optional per-project migration (not in
|
|
11
|
+
* the generated schema), so rows are inserted untyped; all columns are TEXT on
|
|
12
|
+
* every engine and ON CONFLICT DO NOTHING keeps writes idempotent on retries.
|
|
13
|
+
*/
|
|
14
|
+
export declare class KyselyAuditService implements AuditService {
|
|
15
|
+
private db;
|
|
16
|
+
constructor(db: Kysely<any>);
|
|
17
|
+
audit(event: AuditEvent): Promise<void>;
|
|
18
|
+
write(batch: AuditEventBatch): Promise<void>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const jsonOrNull = (v) => v != null ? JSON.stringify(v) : null;
|
|
2
|
+
// No global `crypto` is guaranteed across every runtime, and audit_id is the
|
|
3
|
+
// PK — any collision is dropped by ON CONFLICT DO NOTHING.
|
|
4
|
+
const fallbackId = () => `evt_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`;
|
|
5
|
+
/**
|
|
6
|
+
* Durable {@link AuditService} that persists AuditEvents to an `audit` table
|
|
7
|
+
* via Kysely — the companion sink to {@link createAuditedKysely}.
|
|
8
|
+
*
|
|
9
|
+
* The column mapping matches a platform audit-queue consumer, so a locally-run
|
|
10
|
+
* project and a deployed stage write identical rows (the read side relies only
|
|
11
|
+
* on `type`, `occurred_at`, `actor_user_id`, and the `data` JSON that holds
|
|
12
|
+
* `metadata`). The `audit` table is an optional per-project migration (not in
|
|
13
|
+
* the generated schema), so rows are inserted untyped; all columns are TEXT on
|
|
14
|
+
* every engine and ON CONFLICT DO NOTHING keeps writes idempotent on retries.
|
|
15
|
+
*/
|
|
16
|
+
export class KyselyAuditService {
|
|
17
|
+
db;
|
|
18
|
+
constructor(db) {
|
|
19
|
+
this.db = db;
|
|
20
|
+
}
|
|
21
|
+
async audit(event) {
|
|
22
|
+
await this.write([event]);
|
|
23
|
+
}
|
|
24
|
+
async write(batch) {
|
|
25
|
+
if (!batch.length)
|
|
26
|
+
return;
|
|
27
|
+
const rows = batch.map((e) => {
|
|
28
|
+
const metadata = e.metadata;
|
|
29
|
+
return {
|
|
30
|
+
audit_id: e.eventId ?? e.queryId ?? fallbackId(),
|
|
31
|
+
occurred_at: e.occurredAt ?? new Date().toISOString(),
|
|
32
|
+
type: e.type ?? 'unknown',
|
|
33
|
+
source: e.source ?? 'auto',
|
|
34
|
+
outcome: e.outcome ?? null,
|
|
35
|
+
function_id: e.functionId ?? null,
|
|
36
|
+
wire_type: e.wireType ?? null,
|
|
37
|
+
trace_id: e.traceId ?? null,
|
|
38
|
+
transaction_id: e.transactionId ?? null,
|
|
39
|
+
query_id: e.queryId ?? null,
|
|
40
|
+
actor_user_id: e.actor?.userId ?? null,
|
|
41
|
+
actor_org_id: e.actor?.orgId ?? null,
|
|
42
|
+
tables: jsonOrNull(metadata?.tables),
|
|
43
|
+
changed_cols: jsonOrNull(metadata?.changedColumns),
|
|
44
|
+
event: e.eventId ?? null,
|
|
45
|
+
old: null,
|
|
46
|
+
data: jsonOrNull(e.metadata),
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
await this.db
|
|
50
|
+
.insertInto('audit')
|
|
51
|
+
.values(rows)
|
|
52
|
+
.onConflict((oc) => oc.doNothing())
|
|
53
|
+
.execute();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -308,7 +308,11 @@ export class KyselyWorkflowService extends PikkuWorkflowService {
|
|
|
308
308
|
if (latestHistory) {
|
|
309
309
|
await this.db
|
|
310
310
|
.updateTable('workflowStepHistory')
|
|
311
|
-
.set({
|
|
311
|
+
.set({
|
|
312
|
+
status: 'succeeded',
|
|
313
|
+
result: resultJson,
|
|
314
|
+
succeededAt: new Date(),
|
|
315
|
+
})
|
|
312
316
|
.where('historyId', '=', latestHistory.historyId)
|
|
313
317
|
.execute();
|
|
314
318
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/create-audited-kysely.ts","../src/index.ts","../src/kysely-ai-agent-run-service.ts","../src/kysely-ai-run-state-service.ts","../src/kysely-ai-storage-service.ts","../src/kysely-channel-store.ts","../src/kysely-credential-service.ts","../src/kysely-deployment-service.ts","../src/kysely-eventhub-store.ts","../src/kysely-json.ts","../src/kysely-secret-service.ts","../src/kysely-session-store.ts","../src/kysely-tables.ts","../src/kysely-workflow-mirror.ts","../src/kysely-workflow-run-service.ts","../src/kysely-workflow-service.ts","../src/serialize-plugin.ts","../bin/pikku-kysely-pure.ts"],"version":"
|
|
1
|
+
{"root":["../src/create-audited-kysely.ts","../src/index.ts","../src/kysely-ai-agent-run-service.ts","../src/kysely-ai-run-state-service.ts","../src/kysely-ai-storage-service.ts","../src/kysely-audit-service.ts","../src/kysely-channel-store.ts","../src/kysely-credential-service.ts","../src/kysely-deployment-service.ts","../src/kysely-eventhub-store.ts","../src/kysely-json.ts","../src/kysely-secret-service.ts","../src/kysely-session-store.ts","../src/kysely-tables.ts","../src/kysely-workflow-mirror.ts","../src/kysely-workflow-run-service.ts","../src/kysely-workflow-service.ts","../src/serialize-plugin.ts","../bin/pikku-kysely-pure.ts"],"version":"6.0.3"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikku/kysely",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
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.
|
|
23
|
+
"@pikku/core": "^0.12.44"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"kysely": "^0.29.0"
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"kysely-codegen": "^0.20.0",
|
|
32
32
|
"kysely-postgres-js": "^3.0.0",
|
|
33
33
|
"postgres": "^3.4.8",
|
|
34
|
-
"typescript": "^
|
|
34
|
+
"typescript": "^6.0.3"
|
|
35
35
|
},
|
|
36
36
|
"exports": {
|
|
37
37
|
".": "./dist/src/index.js"
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { AuditEvent, AuditEventBatch, AuditService } from '@pikku/core'
|
|
2
|
+
import type { Kysely } from 'kysely'
|
|
3
|
+
|
|
4
|
+
const jsonOrNull = (v: unknown): string | null =>
|
|
5
|
+
v != null ? JSON.stringify(v) : null
|
|
6
|
+
|
|
7
|
+
// No global `crypto` is guaranteed across every runtime, and audit_id is the
|
|
8
|
+
// PK — any collision is dropped by ON CONFLICT DO NOTHING.
|
|
9
|
+
const fallbackId = (): string =>
|
|
10
|
+
`evt_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 10)}`
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Durable {@link AuditService} that persists AuditEvents to an `audit` table
|
|
14
|
+
* via Kysely — the companion sink to {@link createAuditedKysely}.
|
|
15
|
+
*
|
|
16
|
+
* The column mapping matches a platform audit-queue consumer, so a locally-run
|
|
17
|
+
* project and a deployed stage write identical rows (the read side relies only
|
|
18
|
+
* on `type`, `occurred_at`, `actor_user_id`, and the `data` JSON that holds
|
|
19
|
+
* `metadata`). The `audit` table is an optional per-project migration (not in
|
|
20
|
+
* the generated schema), so rows are inserted untyped; all columns are TEXT on
|
|
21
|
+
* every engine and ON CONFLICT DO NOTHING keeps writes idempotent on retries.
|
|
22
|
+
*/
|
|
23
|
+
export class KyselyAuditService implements AuditService {
|
|
24
|
+
constructor(private db: Kysely<any>) {}
|
|
25
|
+
|
|
26
|
+
async audit(event: AuditEvent): Promise<void> {
|
|
27
|
+
await this.write([event])
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async write(batch: AuditEventBatch): Promise<void> {
|
|
31
|
+
if (!batch.length) return
|
|
32
|
+
const rows = batch.map((e) => {
|
|
33
|
+
const metadata = e.metadata as
|
|
34
|
+
| { tables?: unknown; changedColumns?: unknown }
|
|
35
|
+
| undefined
|
|
36
|
+
return {
|
|
37
|
+
audit_id: e.eventId ?? e.queryId ?? fallbackId(),
|
|
38
|
+
occurred_at: e.occurredAt ?? new Date().toISOString(),
|
|
39
|
+
type: e.type ?? 'unknown',
|
|
40
|
+
source: e.source ?? 'auto',
|
|
41
|
+
outcome: e.outcome ?? null,
|
|
42
|
+
function_id: e.functionId ?? null,
|
|
43
|
+
wire_type: e.wireType ?? null,
|
|
44
|
+
trace_id: e.traceId ?? null,
|
|
45
|
+
transaction_id: e.transactionId ?? null,
|
|
46
|
+
query_id: e.queryId ?? null,
|
|
47
|
+
actor_user_id: e.actor?.userId ?? null,
|
|
48
|
+
actor_org_id: e.actor?.orgId ?? null,
|
|
49
|
+
tables: jsonOrNull(metadata?.tables),
|
|
50
|
+
changed_cols: jsonOrNull(metadata?.changedColumns),
|
|
51
|
+
event: e.eventId ?? null,
|
|
52
|
+
old: null,
|
|
53
|
+
data: jsonOrNull(e.metadata),
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
await (this.db as any)
|
|
57
|
+
.insertInto('audit')
|
|
58
|
+
.values(rows)
|
|
59
|
+
.onConflict((oc: any) => oc.doNothing())
|
|
60
|
+
.execute()
|
|
61
|
+
}
|
|
62
|
+
}
|