@pikku/cli 0.12.28 → 0.12.30

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 (76) hide show
  1. package/console-app/assets/{index-Ca6xJwNm.js → index-BkiCv5R3.js} +110 -110
  2. package/console-app/index.html +1 -1
  3. package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
  4. package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
  5. package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
  6. package/dist/.pikku/cli/pikku-cli-channel.js +1 -1
  7. package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
  8. package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
  9. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
  10. package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
  11. package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
  12. package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
  13. package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
  14. package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
  15. package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
  16. package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
  17. package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
  18. package/dist/.pikku/function/pikku-functions-meta.gen.json +118 -118
  19. package/dist/.pikku/function/pikku-functions.gen.js +3 -1
  20. package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
  21. package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
  22. package/dist/.pikku/http/pikku-http-wirings-meta.gen.js +1 -1
  23. package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +1 -1
  24. package/dist/.pikku/http/pikku-http-wirings.gen.js +1 -1
  25. package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
  26. package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
  27. package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
  28. package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
  29. package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
  30. package/dist/.pikku/pikku-meta-service.gen.js +1 -1
  31. package/dist/.pikku/pikku-services.gen.d.ts +1 -1
  32. package/dist/.pikku/pikku-types.gen.d.ts +1 -1
  33. package/dist/.pikku/pikku-types.gen.js +1 -1
  34. package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
  35. package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
  36. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
  37. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.json +4 -0
  38. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
  39. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
  40. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
  41. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +9 -9
  42. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
  43. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
  44. package/dist/.pikku/schemas/register.gen.js +7 -7
  45. package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
  46. package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
  47. package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
  48. package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
  49. package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
  50. package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
  51. package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
  52. package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
  53. package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
  54. package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
  55. package/dist/.pikku/workflow/meta/allWorkflow.gen.json +8 -2
  56. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
  57. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
  58. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
  59. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
  60. package/dist/bin/pikku-bin.mjs +2 -2
  61. package/dist/src/fabric/functions/validate-core.js +65 -0
  62. package/dist/src/functions/commands/dev.js +9 -17
  63. package/dist/src/functions/db/db-codegen.d.ts +1 -0
  64. package/dist/src/functions/db/db-codegen.js +45 -0
  65. package/dist/src/functions/db/db-introspector.d.ts +12 -0
  66. package/dist/src/functions/db/local-db.d.ts +8 -0
  67. package/dist/src/functions/db/local-db.js +17 -0
  68. package/dist/src/functions/db/postgres/postgres-introspector.d.ts +3 -1
  69. package/dist/src/functions/db/postgres/postgres-introspector.js +43 -0
  70. package/dist/src/functions/db/sqlite/sqlite-introspector.d.ts +3 -1
  71. package/dist/src/functions/db/sqlite/sqlite-introspector.js +14 -0
  72. package/dist/src/functions/db/sqlite/sqlite-runtime-node.js +16 -3
  73. package/dist/src/functions/wirings/auth/serialize-auth-gen.js +4 -2
  74. package/dist/src/scaffold/rpc-remote.gen.js +1 -1
  75. package/package.json +2 -2
  76. package/skills/pikku-workflow/SKILL.md +22 -0
@@ -60,6 +60,49 @@ export class PostgresIntrospector {
60
60
  generated: r.is_generated === 'ALWAYS',
61
61
  }));
62
62
  }
63
+ async getForeignKeys(table) {
64
+ const dotIdx = table.indexOf('.');
65
+ const schema = dotIdx >= 0 ? table.slice(0, dotIdx) : 'public';
66
+ const tableName = dotIdx >= 0 ? table.slice(dotIdx + 1) : table;
67
+ const result = await this.client.query(`SELECT kcu.column_name,
68
+ kcu2.table_schema AS foreign_table_schema,
69
+ kcu2.table_name AS foreign_table_name,
70
+ kcu2.column_name AS foreign_column_name
71
+ FROM information_schema.referential_constraints rc
72
+ JOIN information_schema.key_column_usage kcu
73
+ ON kcu.constraint_catalog = rc.constraint_catalog
74
+ AND kcu.constraint_schema = rc.constraint_schema
75
+ AND kcu.constraint_name = rc.constraint_name
76
+ JOIN information_schema.key_column_usage kcu2
77
+ ON kcu2.constraint_catalog = rc.unique_constraint_catalog
78
+ AND kcu2.constraint_schema = rc.unique_constraint_schema
79
+ AND kcu2.constraint_name = rc.unique_constraint_name
80
+ AND kcu2.ordinal_position = kcu.ordinal_position
81
+ WHERE kcu.table_schema = $2 AND kcu.table_name = $1
82
+ ORDER BY kcu.ordinal_position`, [tableName, schema]);
83
+ return result.rows.map((r) => ({
84
+ column: r.column_name,
85
+ foreignTable: r.foreign_table_schema === 'public'
86
+ ? r.foreign_table_name
87
+ : `${r.foreign_table_schema}.${r.foreign_table_name}`,
88
+ foreignColumn: r.foreign_column_name,
89
+ }));
90
+ }
91
+ async listEnums() {
92
+ const result = await this.client.query(`SELECT t.typname AS enum_name,
93
+ t.typnamespace::regnamespace::text AS schema_name,
94
+ json_agg(e.enumlabel ORDER BY e.enumsortorder) AS values
95
+ FROM pg_type t
96
+ JOIN pg_enum e ON e.enumtypid = t.oid
97
+ WHERE t.typtype = 'e'
98
+ GROUP BY t.typname, t.typnamespace
99
+ ORDER BY schema_name, enum_name`);
100
+ return result.rows.map((r) => ({
101
+ name: r.enum_name,
102
+ schema: r.schema_name,
103
+ values: r.values,
104
+ }));
105
+ }
63
106
  async close() {
64
107
  await this.client.end();
65
108
  }
@@ -1,9 +1,11 @@
1
- import type { DbIntrospector, ColumnInfo } from '../db-introspector.js';
1
+ import type { DbIntrospector, ColumnInfo, ForeignKeyInfo, EnumInfo } from '../db-introspector.js';
2
2
  import type { SyncSqliteDatabase } from './sqlite-runtime.js';
3
3
  export declare class SqliteIntrospector implements DbIntrospector {
4
4
  private readonly db;
5
5
  constructor(db: SyncSqliteDatabase);
6
6
  listTables(): Promise<string[]>;
7
7
  getColumns(table: string): Promise<ColumnInfo[]>;
8
+ getForeignKeys(table: string): Promise<ForeignKeyInfo[]>;
9
+ listEnums(): Promise<EnumInfo[]>;
8
10
  close(): Promise<void>;
9
11
  }
@@ -29,6 +29,20 @@ export class SqliteIntrospector {
29
29
  generated: c.hidden === 2 || c.hidden === 3,
30
30
  }));
31
31
  }
32
+ async getForeignKeys(table) {
33
+ const escaped = `"${table.replace(/"/g, '""')}"`;
34
+ const rows = this.db
35
+ .prepare(`PRAGMA foreign_key_list(${escaped})`)
36
+ .all();
37
+ return rows.map((r) => ({
38
+ column: r.from,
39
+ foreignTable: r.table,
40
+ foreignColumn: r.to,
41
+ }));
42
+ }
43
+ async listEnums() {
44
+ return [];
45
+ }
32
46
  async close() {
33
47
  this.db.close();
34
48
  }
@@ -1,9 +1,22 @@
1
1
  class NodeSqliteStatement {
2
2
  stmt;
3
3
  reader;
4
- constructor(stmt) {
4
+ constructor(stmt, sql) {
5
5
  this.stmt = stmt;
6
- this.reader = Boolean(stmt.reader);
6
+ // node:sqlite StatementSync does not have a .reader property
7
+ // (that's a better-sqlite3 API). Fall back to SQL inspection when absent.
8
+ if (stmt.reader !== undefined) {
9
+ this.reader = Boolean(stmt.reader);
10
+ }
11
+ else {
12
+ const upper = sql.trimStart().toUpperCase();
13
+ this.reader =
14
+ upper.startsWith('SELECT') ||
15
+ upper.startsWith('WITH') ||
16
+ upper.startsWith('PRAGMA') ||
17
+ upper.startsWith('EXPLAIN') ||
18
+ upper.startsWith('VALUES');
19
+ }
7
20
  }
8
21
  all(...parameters) {
9
22
  return this.stmt.all(...parameters);
@@ -31,7 +44,7 @@ class NodeSqliteDatabase {
31
44
  this.db.exec(sql);
32
45
  }
33
46
  prepare(sql) {
34
- return new NodeSqliteStatement(this.db.prepare(sql));
47
+ return new NodeSqliteStatement(this.db.prepare(sql), sql);
35
48
  }
36
49
  close() {
37
50
  this.db.close();
@@ -33,18 +33,20 @@ export const serializeAuthGen = (providers) => {
33
33
  const def = PROVIDER_REGISTRY[name];
34
34
  const schemaName = providerSchemaName(name);
35
35
  const fieldLines = Object.entries(def.fields).map(([field, zodExpr]) => ` ${field}: ${zodExpr},`);
36
- lines.push(`const ${schemaName} = z.object({`);
36
+ lines.push(`export const ${schemaName} = z.object({`);
37
37
  lines.push(...fieldLines);
38
38
  lines.push(`})`);
39
39
  lines.push('');
40
40
  }
41
41
  // wireSecret for AUTH_SECRET
42
+ lines.push(`export const AuthSecretSchema = z.string()`);
43
+ lines.push('');
42
44
  lines.push(`wireSecret({`);
43
45
  lines.push(` name: 'authSecret',`);
44
46
  lines.push(` displayName: 'Auth Secret',`);
45
47
  lines.push(` description: 'JWT signing secret for Auth.js sessions',`);
46
48
  lines.push(` secretId: 'AUTH_SECRET',`);
47
- lines.push(` schema: z.string(),`);
49
+ lines.push(` schema: AuthSecretSchema,`);
48
50
  lines.push(`})`);
49
51
  lines.push('');
50
52
  // wireSecret for each provider
@@ -1,5 +1,5 @@
1
1
  /**
2
- * This file was generated by @pikku/cli@0.12.28
2
+ * This file was generated by @pikku/cli@0.12.30
3
3
  */
4
4
  /**
5
5
  * Auto-generated remote internal RPC queue worker and HTTP endpoint
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/cli",
3
- "version": "0.12.28",
3
+ "version": "0.12.30",
4
4
  "author": "yasser.fadl@gmail.com",
5
5
  "license": "BUSL-1.1",
6
6
  "imports": {
@@ -29,7 +29,7 @@
29
29
  "@pikku/core": "^0.12.27",
30
30
  "@pikku/deploy-cloudflare": "^0.12.3",
31
31
  "@pikku/fetch": "^0.12.2",
32
- "@pikku/inspector": "^0.12.14",
32
+ "@pikku/inspector": "^0.12.15",
33
33
  "@pikku/kysely": "^0.12.14",
34
34
  "@pikku/kysely-node-sqlite": "^0.12.1",
35
35
  "@pikku/node-http-server": "^0.12.1",
@@ -71,6 +71,28 @@ await workflow.sleep('Wait 5 minutes', '5min')
71
71
  await workflow.suspend('Awaiting approval')
72
72
  ```
73
73
 
74
+ ### Choosing the right wrapper
75
+
76
+ | Wrapper | When to use |
77
+ |---|---|
78
+ | `pikkuWorkflowFunc` | **Default.** Use for all new workflows. DSL mode — serialisable, replay-safe. |
79
+ | `pikkuWorkflowComplexFunc` | **Only with explicit user approval.** For workflows with patterns the DSL extractor cannot handle (e.g. dynamic inline functions). Not a general escape hatch — restructure first. |
80
+ | `pikkuWorkflowGraph` | **Only with explicit user approval.** For genuine DAGs where there is a cyclic dependency between nodes or a Node.js-only import DSL cannot express. |
81
+
82
+ **Conditional results** — the correct DSL pattern when a step only runs under some condition:
83
+
84
+ ```typescript
85
+ // ✅ Declare at top level, assign inside block
86
+ let result: { id: string } | null = null
87
+ if (input.createFoo) {
88
+ result = await workflow.do('Create foo', 'createFoo', { ... })
89
+ }
90
+ // Use result?.id downstream
91
+
92
+ // ❌ Do NOT declare const inside a block — DSL forbids block-scoped declarations
93
+ // ❌ Do NOT switch to pikkuWorkflowComplexFunc to avoid the restriction
94
+ ```
95
+
74
96
  ### `pikkuWorkflowGraph(config)` — DAG Workflows
75
97
 
76
98
  ```typescript