@pikku/cli 0.12.25 → 0.12.27

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.
Files changed (122) hide show
  1. package/console-app/assets/index-BERGDBO9.js +228 -0
  2. package/console-app/assets/{index-C52h1B_L.css → index-CQ29NRyR.css} +1 -1
  3. package/console-app/index.html +2 -2
  4. package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
  5. package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
  6. package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
  7. package/dist/.pikku/cli/pikku-cli-channel.js +6 -1
  8. package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
  9. package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
  10. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
  11. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +9 -0
  12. package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
  13. package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
  14. package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
  15. package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
  16. package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
  17. package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
  18. package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
  19. package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
  20. package/dist/.pikku/function/pikku-functions-meta.gen.json +140 -125
  21. package/dist/.pikku/function/pikku-functions.gen.js +3 -1
  22. package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
  23. package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
  24. package/dist/.pikku/http/pikku-http-wirings-meta.gen.js +1 -1
  25. package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +1 -1
  26. package/dist/.pikku/http/pikku-http-wirings.gen.js +1 -1
  27. package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
  28. package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
  29. package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
  30. package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
  31. package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
  32. package/dist/.pikku/pikku-meta-service.gen.js +1 -1
  33. package/dist/.pikku/pikku-services.gen.d.ts +1 -1
  34. package/dist/.pikku/pikku-types.gen.d.ts +1 -1
  35. package/dist/.pikku/pikku-types.gen.js +1 -1
  36. package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
  37. package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
  38. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
  39. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
  40. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
  41. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
  42. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +11 -10
  43. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
  44. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
  45. package/dist/.pikku/schemas/register.gen.js +11 -9
  46. package/dist/.pikku/schemas/schemas/DbAuditInput.schema.json +1 -0
  47. package/dist/.pikku/schemas/schemas/PikkuTestsCoverageInput.schema.json +1 -1
  48. package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
  49. package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
  50. package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
  51. package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
  52. package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
  53. package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
  54. package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
  55. package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
  56. package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
  57. package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
  58. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
  59. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
  60. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
  61. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
  62. package/dist/bin/pikku-bin.mjs +2 -2
  63. package/dist/src/cli.wiring.js +8 -0
  64. package/dist/src/fabric/functions/validate-core.js +6 -6
  65. package/dist/src/fabric/functions/validate.function.js +1 -1
  66. package/dist/src/functions/commands/db-audit.d.ts +1 -0
  67. package/dist/src/functions/commands/db-audit.js +67 -0
  68. package/dist/src/functions/commands/db-migrate.js +5 -8
  69. package/dist/src/functions/commands/db-reset.js +9 -8
  70. package/dist/src/functions/commands/db-seed.js +9 -8
  71. package/dist/src/functions/commands/db-shared.d.ts +2 -4
  72. package/dist/src/functions/commands/db-shared.js +15 -5
  73. package/dist/src/functions/commands/dev.js +14 -8
  74. package/dist/src/functions/commands/new-addon.js +2 -2
  75. package/dist/src/functions/commands/tests-coverage.d.ts +3 -0
  76. package/dist/src/functions/commands/tests-coverage.js +34 -0
  77. package/dist/src/functions/db/annotation-parser.d.ts +31 -0
  78. package/dist/src/functions/db/annotation-parser.js +93 -0
  79. package/dist/src/functions/db/db-codegen.d.ts +24 -0
  80. package/dist/src/functions/db/db-codegen.js +276 -0
  81. package/dist/src/functions/db/db-introspector.d.ts +15 -0
  82. package/dist/src/functions/db/db-introspector.js +1 -0
  83. package/dist/src/functions/db/db-migrator.d.ts +32 -0
  84. package/dist/src/functions/db/db-migrator.js +65 -0
  85. package/dist/src/functions/db/local-db.d.ts +26 -32
  86. package/dist/src/functions/db/local-db.js +100 -53
  87. package/dist/src/functions/db/postgres/postgres-introspector.d.ts +10 -0
  88. package/dist/src/functions/db/postgres/postgres-introspector.js +54 -0
  89. package/dist/src/functions/db/postgres/postgres-migrator.d.ts +9 -0
  90. package/dist/src/functions/db/postgres/postgres-migrator.js +32 -0
  91. package/dist/src/functions/db/sqlite/sqlite-introspector.d.ts +9 -0
  92. package/dist/src/functions/db/sqlite/sqlite-introspector.js +35 -0
  93. package/dist/src/functions/db/sqlite/sqlite-migrator.d.ts +10 -0
  94. package/dist/src/functions/db/sqlite/sqlite-migrator.js +36 -0
  95. package/dist/src/functions/validate/workspace-validate.js +7 -3
  96. package/dist/src/functions/wirings/ai-agent/serialize-public-agent.js +2 -1
  97. package/dist/src/functions/wirings/console/serialize-console-functions.js +4 -4
  98. package/dist/src/functions/wirings/functions/serialize-addon-types.js +1 -1
  99. package/dist/src/scaffold/rpc-remote.gen.js +1 -1
  100. package/dist/src/services.js +2 -0
  101. package/dist/tsconfig.tsbuildinfo +1 -1
  102. package/package.json +6 -4
  103. package/skills/pikku-middleware/SKILL.md +283 -0
  104. package/skills/pikku-permissions/SKILL.md +165 -0
  105. package/skills/pikku-security/SKILL.md +38 -177
  106. package/skills/pikku-tag-middleware/SKILL.md +13 -0
  107. package/skills/pikku-testing/SKILL.md +208 -0
  108. package/console-app/assets/index-D4DgafuS.js +0 -232
  109. package/dist/src/functions/db/sql-migrator.d.ts +0 -26
  110. package/dist/src/functions/db/sql-migrator.js +0 -104
  111. package/dist/src/functions/db/sqlite-codegen.d.ts +0 -45
  112. package/dist/src/functions/db/sqlite-codegen.js +0 -294
  113. /package/dist/src/functions/db/{seed.d.ts → sqlite/seed.d.ts} +0 -0
  114. /package/dist/src/functions/db/{seed.js → sqlite/seed.js} +0 -0
  115. /package/dist/src/functions/db/{sqlite-kysely.d.ts → sqlite/sqlite-kysely.d.ts} +0 -0
  116. /package/dist/src/functions/db/{sqlite-kysely.js → sqlite/sqlite-kysely.js} +0 -0
  117. /package/dist/src/functions/db/{sqlite-runtime-bun.d.ts → sqlite/sqlite-runtime-bun.d.ts} +0 -0
  118. /package/dist/src/functions/db/{sqlite-runtime-bun.js → sqlite/sqlite-runtime-bun.js} +0 -0
  119. /package/dist/src/functions/db/{sqlite-runtime-node.d.ts → sqlite/sqlite-runtime-node.d.ts} +0 -0
  120. /package/dist/src/functions/db/{sqlite-runtime-node.js → sqlite/sqlite-runtime-node.js} +0 -0
  121. /package/dist/src/functions/db/{sqlite-runtime.d.ts → sqlite/sqlite-runtime.d.ts} +0 -0
  122. /package/dist/src/functions/db/{sqlite-runtime.js → sqlite/sqlite-runtime.js} +0 -0
@@ -1,48 +1,42 @@
1
1
  import type { Kysely } from 'kysely';
2
- import { type MigrateResult } from './sql-migrator.js';
3
- import { type CodegenResult } from './sqlite-codegen.js';
2
+ import { type MigrateResult } from './db-migrator.js';
3
+ import { type CodegenResult } from './db-codegen.js';
4
4
  import { type ZodCodegenResult } from './zod-codegen.js';
5
- import { type SeedResult } from './seed.js';
6
- export type DevDbConfig = true | {
7
- file?: string;
8
- };
9
- export interface ResolvedLocalDb {
10
- dbFile: string;
11
- runtimeDir: string;
5
+ import { type SeedResult } from './sqlite/seed.js';
6
+ import type { UserConfigShape } from '../commands/db-shared.js';
7
+ interface ResolvedDbBase {
12
8
  migrationsDir: string;
13
9
  seedFile: string;
14
10
  schemaFile: string;
15
11
  coercionFile: string;
12
+ manifestFile: string;
16
13
  zodFile: string;
17
14
  camelCase: boolean;
18
15
  }
16
+ export interface ResolvedSqliteDb extends ResolvedDbBase {
17
+ dialect: 'sqlite';
18
+ dbFile: string;
19
+ runtimeDir: string;
20
+ }
21
+ export interface ResolvedPostgresDb extends ResolvedDbBase {
22
+ dialect: 'postgres';
23
+ connectionString: string;
24
+ }
25
+ export type ResolvedDb = ResolvedSqliteDb | ResolvedPostgresDb;
19
26
  /**
20
- * Resolve a DevDbConfig into absolute paths.
21
- * - dbFile lives under runtimeDir (default: <rootDir>/.pikku-runtime)
22
- * - schema/coercion/zod are generated into outDir/db
23
- * - migrations and seed are authored source under rootDir/db
27
+ * Resolve a UserConfigShape into an absolute-path descriptor.
28
+ * Returns null when neither sqliteDb nor postgresUrl is configured.
24
29
  */
25
- export declare function resolveLocalDb(config: DevDbConfig | undefined, rootDir: string, outDir: string, runtimeDir?: string): ResolvedLocalDb | null;
30
+ export declare function resolveDb(userConfig: UserConfigShape, rootDir: string, outDir: string, runtimeDir?: string): ResolvedDb | null;
31
+ /** @deprecated Use resolveDb(userConfig, ...) instead. */
32
+ export declare function resolveLocalDb(sqliteDb: string | undefined, rootDir: string, outDir: string, runtimeDir?: string): ResolvedSqliteDb | null;
26
33
  export interface MigrateAndCodegenOutcome {
27
34
  migrate: MigrateResult;
28
35
  codegen: CodegenResult;
29
36
  zod: ZodCodegenResult;
30
37
  }
31
- /**
32
- * Run the migrate routine (open tracking-table → drift-check → apply →
33
- * codegen close). Used by both `pikku db migrate` and `pikku dev` boot.
34
- */
35
- export declare function migrateAndCodegen(resolved: ResolvedLocalDb): Promise<MigrateAndCodegenOutcome>;
36
- export declare function seed(resolved: ResolvedLocalDb): Promise<SeedResult>;
37
- /**
38
- * Delete the dev DB file. Refuses if NODE_ENV is 'production' or the
39
- * resolved file lives outside the project root (defensive against
40
- * misconfigured absolute paths).
41
- */
42
- export declare function reset(resolved: ResolvedLocalDb, rootDir: string): void;
43
- /**
44
- * Construct the user-facing Kysely instance for the dev DB. Used by
45
- * `pikku dev` to populate inMemoryServices.kysely.
46
- * Wires the coercion plugin when db/coercion.gen.ts exists.
47
- */
48
- export declare function createKysely<DB>(resolved: ResolvedLocalDb): Promise<Kysely<DB>>;
38
+ export declare function migrateAndCodegen(resolved: ResolvedDb): Promise<MigrateAndCodegenOutcome>;
39
+ export declare function seed(resolved: ResolvedSqliteDb): Promise<SeedResult>;
40
+ export declare function reset(resolved: ResolvedSqliteDb, rootDir: string): void;
41
+ export declare function createKysely<DB>(resolved: ResolvedSqliteDb): Promise<Kysely<DB>>;
42
+ export {};
@@ -1,65 +1,122 @@
1
1
  import { existsSync, mkdirSync, rmSync } from 'node:fs';
2
2
  import { resolve, isAbsolute, relative, dirname, join } from 'node:path';
3
- import { migrate } from './sql-migrator.js';
4
- import { generateSchemaTypes } from './sqlite-codegen.js';
3
+ import { migrate } from './db-migrator.js';
4
+ import { generateSchemaTypes } from './db-codegen.js';
5
5
  import { generateZodTypes } from './zod-codegen.js';
6
- import { seed as runSeed } from './seed.js';
7
6
  import { createCoercionPlugin } from './coercion-plugin.js';
8
- import { createSqliteKysely } from './sqlite-kysely.js';
9
- import { loadSqliteRuntime } from './sqlite-runtime.js';
7
+ import { SqliteMigrationExecutor } from './sqlite/sqlite-migrator.js';
8
+ import { SqliteIntrospector } from './sqlite/sqlite-introspector.js';
9
+ import { createSqliteKysely } from './sqlite/sqlite-kysely.js';
10
+ import { loadSqliteRuntime } from './sqlite/sqlite-runtime.js';
11
+ import { seed as runSeed } from './sqlite/seed.js';
12
+ import { PostgresMigrationExecutor } from './postgres/postgres-migrator.js';
13
+ import { PostgresIntrospector } from './postgres/postgres-introspector.js';
14
+ // ─── Resolution ───────────────────────────────────────────────────────────────
10
15
  /**
11
- * Resolve a DevDbConfig into absolute paths.
12
- * - dbFile lives under runtimeDir (default: <rootDir>/.pikku-runtime)
13
- * - schema/coercion/zod are generated into outDir/db
14
- * - migrations and seed are authored source under rootDir/db
16
+ * Resolve a UserConfigShape into an absolute-path descriptor.
17
+ * Returns null when neither sqliteDb nor postgresUrl is configured.
15
18
  */
16
- export function resolveLocalDb(config, rootDir, outDir, runtimeDir) {
17
- if (!config)
18
- return null;
19
- const file = config === true ? undefined : config.file;
20
- const resolvedRuntimeDir = runtimeDir ?? join(rootDir, '.pikku-runtime');
21
- return {
22
- dbFile: file
23
- ? resolveAgainst(rootDir, file)
24
- : join(resolvedRuntimeDir, 'dev.db'),
25
- runtimeDir: resolvedRuntimeDir,
26
- migrationsDir: resolveAgainst(rootDir, 'db/migrations'),
27
- seedFile: resolveAgainst(rootDir, 'db/seed.sql'),
19
+ export function resolveDb(userConfig, rootDir, outDir, runtimeDir) {
20
+ const base = (sub, seedFileName) => ({
21
+ migrationsDir: resolveAgainst(rootDir, sub),
22
+ seedFile: resolveAgainst(rootDir, seedFileName),
28
23
  schemaFile: join(outDir, 'db', 'schema.d.ts'),
29
24
  coercionFile: join(outDir, 'db', 'coercion.gen.ts'),
25
+ manifestFile: join(outDir, 'db', 'classification.gen.ts'),
30
26
  zodFile: join(outDir, 'db', 'zod.gen.ts'),
31
27
  camelCase: true,
32
- };
28
+ });
29
+ if (userConfig.postgresUrl && userConfig.sqliteDb) {
30
+ throw new Error('Both postgresUrl and sqliteDb are set. Configure exactly one database dialect.');
31
+ }
32
+ if (userConfig.postgresUrl) {
33
+ return {
34
+ dialect: 'postgres',
35
+ connectionString: userConfig.postgresUrl,
36
+ ...base('db/postgres', 'db/postgres-seed.sql'),
37
+ };
38
+ }
39
+ if (userConfig.sqliteDb) {
40
+ const resolvedRuntimeDir = runtimeDir
41
+ ? resolveAgainst(rootDir, runtimeDir)
42
+ : join(rootDir, '.pikku-runtime');
43
+ return {
44
+ dialect: 'sqlite',
45
+ dbFile: resolveAgainst(rootDir, userConfig.sqliteDb),
46
+ runtimeDir: resolvedRuntimeDir,
47
+ ...base('db/sqlite', 'db/sqlite-seed.sql'),
48
+ };
49
+ }
50
+ return null;
51
+ }
52
+ /** @deprecated Use resolveDb(userConfig, ...) instead. */
53
+ export function resolveLocalDb(sqliteDb, rootDir, outDir, runtimeDir) {
54
+ if (!sqliteDb)
55
+ return null;
56
+ const result = resolveDb({ sqliteDb }, rootDir, outDir, runtimeDir);
57
+ return result;
33
58
  }
34
59
  function resolveAgainst(root, p) {
35
60
  return isAbsolute(p) ? p : resolve(root, p);
36
61
  }
37
- /**
38
- * Run the migrate routine (open → tracking-table → drift-check → apply →
39
- * codegen → close). Used by both `pikku db migrate` and `pikku dev` boot.
40
- */
41
62
  export async function migrateAndCodegen(resolved) {
42
- mkdirSync(dirname(resolved.dbFile), { recursive: true });
43
- const runtime = await loadSqliteRuntime();
44
- const db = runtime.open(resolved.dbFile);
63
+ if (resolved.dialect === 'sqlite') {
64
+ mkdirSync(dirname(resolved.dbFile), { recursive: true });
65
+ const runtime = await loadSqliteRuntime();
66
+ const db = runtime.open(resolved.dbFile);
67
+ try {
68
+ const executor = new SqliteMigrationExecutor(db);
69
+ const migrateResult = await migrate(executor, resolved.migrationsDir);
70
+ const introspector = new SqliteIntrospector(db);
71
+ const codegenResult = await generateSchemaTypes(introspector, {
72
+ outFile: resolved.schemaFile,
73
+ coercionFile: resolved.coercionFile,
74
+ manifestFile: resolved.manifestFile,
75
+ camelCase: resolved.camelCase,
76
+ migrationsDir: resolved.migrationsDir,
77
+ });
78
+ const zodResult = generateZodTypes({
79
+ schemaFile: resolved.schemaFile,
80
+ outFile: resolved.zodFile,
81
+ });
82
+ return { migrate: migrateResult, codegen: codegenResult, zod: zodResult };
83
+ }
84
+ finally {
85
+ db.close();
86
+ }
87
+ }
88
+ // Postgres
89
+ const introspector = new PostgresIntrospector(resolved.connectionString);
90
+ await introspector.connect();
45
91
  try {
46
- const migrateResult = migrate(db, resolved.migrationsDir);
47
- const codegenResult = generateSchemaTypes(db, {
48
- outFile: resolved.schemaFile,
49
- coercionFile: resolved.coercionFile,
50
- camelCase: resolved.camelCase,
51
- migrationsDir: resolved.migrationsDir,
52
- });
53
- const zodResult = generateZodTypes({
54
- schemaFile: resolved.schemaFile,
55
- outFile: resolved.zodFile,
56
- });
57
- return { migrate: migrateResult, codegen: codegenResult, zod: zodResult };
92
+ const { Client } = await import('pg');
93
+ const client = new Client({ connectionString: resolved.connectionString });
94
+ await client.connect();
95
+ try {
96
+ const executor = new PostgresMigrationExecutor(client);
97
+ const migrateResult = await migrate(executor, resolved.migrationsDir);
98
+ const codegenResult = await generateSchemaTypes(introspector, {
99
+ outFile: resolved.schemaFile,
100
+ coercionFile: resolved.coercionFile,
101
+ manifestFile: resolved.manifestFile,
102
+ camelCase: resolved.camelCase,
103
+ migrationsDir: resolved.migrationsDir,
104
+ });
105
+ const zodResult = generateZodTypes({
106
+ schemaFile: resolved.schemaFile,
107
+ outFile: resolved.zodFile,
108
+ });
109
+ return { migrate: migrateResult, codegen: codegenResult, zod: zodResult };
110
+ }
111
+ finally {
112
+ await client.end();
113
+ }
58
114
  }
59
115
  finally {
60
- db.close();
116
+ await introspector.close();
61
117
  }
62
118
  }
119
+ // ─── SQLite-only operations ───────────────────────────────────────────────────
63
120
  export async function seed(resolved) {
64
121
  const runtime = await loadSqliteRuntime();
65
122
  const db = runtime.open(resolved.dbFile);
@@ -70,28 +127,18 @@ export async function seed(resolved) {
70
127
  db.close();
71
128
  }
72
129
  }
73
- /**
74
- * Delete the dev DB file. Refuses if NODE_ENV is 'production' or the
75
- * resolved file lives outside the project root (defensive against
76
- * misconfigured absolute paths).
77
- */
78
130
  export function reset(resolved, rootDir) {
79
131
  if (process.env.NODE_ENV === 'production') {
80
132
  throw new Error(`pikku db reset refused: NODE_ENV=production. This command only runs in dev.`);
81
133
  }
82
134
  const rel = relative(resolved.runtimeDir, resolved.dbFile);
83
135
  if (rel.startsWith('..') || isAbsolute(rel)) {
84
- throw new Error(`pikku db reset refused: resolved DB file (${resolved.dbFile}) is outside the runtime directory (${resolved.runtimeDir}). Override dev.db.file or set runtimeDir correctly.`);
136
+ throw new Error(`pikku db reset refused: resolved DB file (${resolved.dbFile}) is outside the runtime directory (${resolved.runtimeDir}). Override sqliteDb or set runtimeDir correctly.`);
85
137
  }
86
138
  if (existsSync(resolved.dbFile)) {
87
139
  rmSync(resolved.dbFile);
88
140
  }
89
141
  }
90
- /**
91
- * Construct the user-facing Kysely instance for the dev DB. Used by
92
- * `pikku dev` to populate inMemoryServices.kysely.
93
- * Wires the coercion plugin when db/coercion.gen.ts exists.
94
- */
95
142
  export async function createKysely(resolved) {
96
143
  mkdirSync(dirname(resolved.dbFile), { recursive: true });
97
144
  const runtime = await loadSqliteRuntime();
@@ -0,0 +1,10 @@
1
+ import { Client } from 'pg';
2
+ import type { DbIntrospector, ColumnInfo } from '../db-introspector.js';
3
+ export declare class PostgresIntrospector implements DbIntrospector {
4
+ private client;
5
+ constructor(connectionStringOrClient: string | Client);
6
+ connect(): Promise<void>;
7
+ listTables(): Promise<string[]>;
8
+ getColumns(table: string): Promise<ColumnInfo[]>;
9
+ close(): Promise<void>;
10
+ }
@@ -0,0 +1,54 @@
1
+ import { Client } from 'pg';
2
+ export class PostgresIntrospector {
3
+ client;
4
+ constructor(connectionStringOrClient) {
5
+ this.client =
6
+ typeof connectionStringOrClient === 'string'
7
+ ? new Client({ connectionString: connectionStringOrClient })
8
+ : connectionStringOrClient;
9
+ }
10
+ async connect() {
11
+ await this.client.connect();
12
+ }
13
+ async listTables() {
14
+ const result = await this.client.query(`SELECT table_name
15
+ FROM information_schema.tables
16
+ WHERE table_schema = 'public' AND table_type = 'BASE TABLE'
17
+ ORDER BY table_name`);
18
+ return result.rows.map((r) => r.table_name);
19
+ }
20
+ async getColumns(table) {
21
+ const result = await this.client.query(`SELECT
22
+ c.column_name,
23
+ c.data_type,
24
+ c.is_nullable,
25
+ c.column_default,
26
+ c.is_generated,
27
+ EXISTS(
28
+ SELECT 1
29
+ FROM information_schema.table_constraints tc
30
+ JOIN information_schema.key_column_usage kcu
31
+ ON tc.constraint_name = kcu.constraint_name
32
+ AND tc.table_schema = kcu.table_schema
33
+ AND tc.table_name = kcu.table_name
34
+ WHERE tc.constraint_type = 'PRIMARY KEY'
35
+ AND tc.table_schema = 'public'
36
+ AND tc.table_name = $1
37
+ AND kcu.column_name = c.column_name
38
+ ) AS is_pk
39
+ FROM information_schema.columns c
40
+ WHERE c.table_schema = 'public' AND c.table_name = $1
41
+ ORDER BY c.ordinal_position`, [table]);
42
+ return result.rows.map((r) => ({
43
+ name: r.column_name,
44
+ type: r.data_type,
45
+ notNull: r.is_nullable === 'NO',
46
+ pk: Boolean(r.is_pk),
47
+ defaultValue: r.column_default,
48
+ generated: r.is_generated === 'ALWAYS',
49
+ }));
50
+ }
51
+ async close() {
52
+ await this.client.end();
53
+ }
54
+ }
@@ -0,0 +1,9 @@
1
+ import type { Client } from 'pg';
2
+ import type { MigrationExecutor, AppliedMigration } from '../db-migrator.js';
3
+ export declare class PostgresMigrationExecutor implements MigrationExecutor {
4
+ private readonly client;
5
+ constructor(client: Client);
6
+ ensureTrackingTable(): Promise<void>;
7
+ getApplied(): Promise<AppliedMigration[]>;
8
+ runMigration(sql: string, name: string, hash: string): Promise<void>;
9
+ }
@@ -0,0 +1,32 @@
1
+ const TRACKING_TABLE = 'sql_migrations';
2
+ export class PostgresMigrationExecutor {
3
+ client;
4
+ constructor(client) {
5
+ this.client = client;
6
+ }
7
+ async ensureTrackingTable() {
8
+ await this.client.query(`
9
+ CREATE TABLE IF NOT EXISTS ${TRACKING_TABLE} (
10
+ name TEXT PRIMARY KEY,
11
+ hash TEXT NOT NULL,
12
+ applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
13
+ )
14
+ `);
15
+ }
16
+ async getApplied() {
17
+ const { rows } = await this.client.query(`SELECT name, hash, applied_at FROM ${TRACKING_TABLE} ORDER BY name`);
18
+ return rows;
19
+ }
20
+ async runMigration(sql, name, hash) {
21
+ await this.client.query('BEGIN');
22
+ try {
23
+ await this.client.query(sql);
24
+ await this.client.query(`INSERT INTO ${TRACKING_TABLE} (name, hash) VALUES ($1, $2)`, [name, hash]);
25
+ await this.client.query('COMMIT');
26
+ }
27
+ catch (err) {
28
+ await this.client.query('ROLLBACK');
29
+ throw err;
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,9 @@
1
+ import type { DbIntrospector, ColumnInfo } from '../db-introspector.js';
2
+ import type { SyncSqliteDatabase } from './sqlite-runtime.js';
3
+ export declare class SqliteIntrospector implements DbIntrospector {
4
+ private readonly db;
5
+ constructor(db: SyncSqliteDatabase);
6
+ listTables(): Promise<string[]>;
7
+ getColumns(table: string): Promise<ColumnInfo[]>;
8
+ close(): Promise<void>;
9
+ }
@@ -0,0 +1,35 @@
1
+ const SKIP_TABLES = new Set(['sqlite_sequence', 'sql_migrations']);
2
+ export class SqliteIntrospector {
3
+ db;
4
+ constructor(db) {
5
+ this.db = db;
6
+ }
7
+ async listTables() {
8
+ const rows = this.db
9
+ .prepare(`SELECT name FROM sqlite_master
10
+ WHERE type = 'table'
11
+ AND name NOT LIKE 'sqlite\\_%' ESCAPE '\\'
12
+ ORDER BY name`)
13
+ .all();
14
+ return rows.map((r) => r.name).filter((n) => !SKIP_TABLES.has(n));
15
+ }
16
+ async getColumns(table) {
17
+ const escaped = `"${table.replace(/"/g, '""')}"`;
18
+ const rows = this.db
19
+ .prepare(`PRAGMA table_xinfo(${escaped})`)
20
+ .all();
21
+ return rows
22
+ .filter((c) => c.hidden !== 1)
23
+ .map((c) => ({
24
+ name: c.name,
25
+ type: c.type,
26
+ notNull: Boolean(c.notnull),
27
+ pk: c.pk > 0,
28
+ defaultValue: c.dflt_value != null ? String(c.dflt_value) : null,
29
+ generated: c.hidden === 2 || c.hidden === 3,
30
+ }));
31
+ }
32
+ async close() {
33
+ this.db.close();
34
+ }
35
+ }
@@ -0,0 +1,10 @@
1
+ import type { MigrationExecutor, AppliedMigration } from '../db-migrator.js';
2
+ import type { SyncSqliteDatabase } from './sqlite-runtime.js';
3
+ export declare class SqliteMigrationExecutor implements MigrationExecutor {
4
+ private readonly db;
5
+ constructor(db: SyncSqliteDatabase);
6
+ ensureTrackingTable(): Promise<void>;
7
+ getApplied(): Promise<AppliedMigration[]>;
8
+ runMigration(sql: string, name: string, hash: string): Promise<void>;
9
+ }
10
+ export declare function dropTrackingTable(db: SyncSqliteDatabase): void;
@@ -0,0 +1,36 @@
1
+ const TRACKING_TABLE = 'sql_migrations';
2
+ export class SqliteMigrationExecutor {
3
+ db;
4
+ constructor(db) {
5
+ this.db = db;
6
+ }
7
+ async ensureTrackingTable() {
8
+ this.db.exec(`CREATE TABLE IF NOT EXISTS ${TRACKING_TABLE} (
9
+ name TEXT PRIMARY KEY,
10
+ hash TEXT NOT NULL,
11
+ applied_at TEXT NOT NULL DEFAULT (datetime('now'))
12
+ )`);
13
+ }
14
+ async getApplied() {
15
+ return this.db
16
+ .prepare(`SELECT name, hash, applied_at FROM ${TRACKING_TABLE} ORDER BY name`)
17
+ .all();
18
+ }
19
+ async runMigration(sql, name, hash) {
20
+ this.db.exec('BEGIN');
21
+ try {
22
+ this.db.exec(sql);
23
+ this.db
24
+ .prepare(`INSERT INTO ${TRACKING_TABLE} (name, hash) VALUES (?, ?)`)
25
+ .run(name, hash);
26
+ this.db.exec('COMMIT');
27
+ }
28
+ catch (err) {
29
+ this.db.exec('ROLLBACK');
30
+ throw err;
31
+ }
32
+ }
33
+ }
34
+ export function dropTrackingTable(db) {
35
+ db.exec(`DROP TABLE IF EXISTS ${TRACKING_TABLE}`);
36
+ }
@@ -96,7 +96,6 @@ export async function runWorkspaceValidate(startDir = process.cwd()) {
96
96
  info('pikku-config-no-client-files', 'pikku.config.json missing "clientFiles" — no generated SDK or React Query hooks', pikkuConfigPath, 'Add clientFiles.rpcMapDeclarationFile and clientFiles.reactQueryFile pointing to packages/functions-sdk/src/pikku/');
97
97
  }
98
98
  }
99
- const hasConfiguredDevDb = Boolean(pikkuConfig?.dev?.db);
100
99
  const rootPkgPath = join(root, 'package.json');
101
100
  const rootPkg = await readJsonSafe(rootPkgPath);
102
101
  if (!rootPkg) {
@@ -143,8 +142,13 @@ export async function runWorkspaceValidate(startDir = process.cwd()) {
143
142
  if (!servicesText) {
144
143
  w('services-missing', 'packages/functions/src/services.ts not found', servicesPath, 'Create services.ts and export your service factory for the workspace');
145
144
  }
146
- const migrationsDir = join(fnDir, 'db', 'migrations');
147
145
  const authEnabled = await hasAuthSessionMiddleware(fnDir);
146
+ const configText = await readTextSafe(join(fnDir, 'src', 'config.ts'));
147
+ const hasConfiguredDevDb = /sqliteDb/.test(configText ?? '');
148
+ const hasPostgresUrl = /postgresUrl/.test(configText ?? '');
149
+ const migrationsDir = hasPostgresUrl
150
+ ? join(fnDir, 'db', 'postgres')
151
+ : join(fnDir, 'db', 'sqlite');
148
152
  let createsAppUser = false;
149
153
  let createsAuthVerificationToken = false;
150
154
  if (existsSync(migrationsDir)) {
@@ -178,7 +182,7 @@ export async function runWorkspaceValidate(startDir = process.cwd()) {
178
182
  }
179
183
  }
180
184
  if (authEnabled && !hasConfiguredDevDb) {
181
- e('auth-dev-db-missing', 'Auth middleware is registered, but pikku.config.json is missing dev.db so local auth schema validation and db migrate cannot run', pikkuConfigPath, 'Add dev.db to pikku.config.json so `pikku db migrate` can create and validate the local auth schema');
185
+ e('auth-dev-db-missing', 'Auth middleware is registered, but createConfig is missing sqliteDb so local auth schema validation and db migrate cannot run', pikkuConfigPath, 'Add sqliteDb to createConfig so `pikku db migrate` can create and validate the local auth schema');
182
186
  }
183
187
  if (authEnabled && !createsAppUser) {
184
188
  e('auth-schema-missing-app-user', 'Auth middleware is registered, but no SQL migration creates the app_user table', migrationsDir, 'Add a migration that creates app_user before enabling auth');
@@ -19,7 +19,7 @@ export const agentCaller = pikkuSessionlessFunc<
19
19
  })
20
20
 
21
21
  export const agentStreamCaller = pikkuSessionlessFunc<
22
- { agentName: string; message: string; threadId: string; resourceId: string },
22
+ { agentName: string; message: string; threadId: string; resourceId: string; context?: string },
23
23
  void
24
24
  >({
25
25
  tags: ['pikku'],
@@ -29,6 +29,7 @@ export const agentStreamCaller = pikkuSessionlessFunc<
29
29
  message: data.message,
30
30
  threadId: data.threadId,
31
31
  resourceId: data.resourceId,
32
+ ...(data.context ? { context: data.context } : {}),
32
33
  })
33
34
  },
34
35
  })
@@ -12,7 +12,7 @@ export const pikkuConsoleSetSecret = pikkuSessionlessFunc<{
12
12
  expose: true,
13
13
  auth: false,
14
14
  func: async ({ secrets }, { secretId, value }) => {
15
- await secrets.setSecretJSON(secretId, value)
15
+ await secrets.setSecret(secretId, value)
16
16
  return { success: true }
17
17
  },
18
18
  })
@@ -31,7 +31,7 @@ export const pikkuConsoleGetVariable = pikkuSessionlessFunc<
31
31
  return { exists: false, value: null }
32
32
  }
33
33
  try {
34
- const value = await variables.getJSON(variableId)
34
+ const value = await variables.get(variableId)
35
35
  return { exists: true, value }
36
36
  } catch {
37
37
  const value = await variables.get(variableId)
@@ -52,7 +52,7 @@ export const pikkuConsoleSetVariable = pikkuSessionlessFunc<
52
52
  if (typeof value === 'string') {
53
53
  await variables.set(variableId, value)
54
54
  } else {
55
- await variables.setJSON(variableId, value)
55
+ await variables.set(variableId, value)
56
56
  }
57
57
  return { success: true }
58
58
  },
@@ -85,7 +85,7 @@ export const pikkuConsoleGetSecret = pikkuSessionlessFunc<
85
85
  if (!exists) {
86
86
  return { exists: false, value: null }
87
87
  }
88
- const value = await secrets.getSecretJSON(secretId)
88
+ const value = await secrets.getSecret(secretId)
89
89
  return { exists: true, value }
90
90
  },
91
91
  })
@@ -52,7 +52,7 @@ export const pikkuAddonConfig = <ExistingServices extends Omit<Partial<Singleton
52
52
  * config,
53
53
  * { secrets }
54
54
  * ) => {
55
- * const creds = await secrets.getSecretJSON<GithubCredentials>('GITHUB_CREDENTIALS')
55
+ * const creds = await secrets.getSecret<GithubCredentials>('GITHUB_CREDENTIALS')
56
56
  * const github = new GithubService(creds)
57
57
  * return { github }
58
58
  * })
@@ -1,5 +1,5 @@
1
1
  /**
2
- * This file was generated by @pikku/cli@0.12.25
2
+ * This file was generated by @pikku/cli@0.12.27
3
3
  */
4
4
  /**
5
5
  * Auto-generated remote internal RPC queue worker and HTTP endpoint
@@ -1,5 +1,6 @@
1
1
  import { pikkuCLIRender } from '@pikku/core/cli';
2
2
  import { LocalVariablesService, LocalSecretService, LogLevel, InMemoryWorkflowService, } from '@pikku/core/services';
3
+ import { NoopAuditService } from '@pikku/core';
3
4
  import { CLILogger } from './services/cli-logger.service.js';
4
5
  import { getPikkuCLIConfig } from './utils/pikku-cli-config.js';
5
6
  import { inspect, serializeInspectorState, deserializeInspectorState, filterInspectorState, getInitialInspectorState, ErrorCode, } from '@pikku/inspector';
@@ -251,6 +252,7 @@ export const createSingletonServices = async (config) => {
251
252
  logger,
252
253
  variables,
253
254
  secrets: new LocalSecretService(variables),
255
+ audit: new NoopAuditService(),
254
256
  getInspectorState,
255
257
  workflowService,
256
258
  };