@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.
- package/console-app/assets/{index-Ca6xJwNm.js → index-BkiCv5R3.js} +110 -110
- package/console-app/index.html +1 -1
- package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-channel.js +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
- package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.json +118 -118
- package/dist/.pikku/function/pikku-functions.gen.js +3 -1
- package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
- package/dist/.pikku/http/pikku-http-wirings-meta.gen.js +1 -1
- package/dist/.pikku/http/pikku-http-wirings.gen.d.ts +1 -1
- package/dist/.pikku/http/pikku-http-wirings.gen.js +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
- package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
- package/dist/.pikku/pikku-meta-service.gen.js +1 -1
- package/dist/.pikku/pikku-services.gen.d.ts +1 -1
- package/dist/.pikku/pikku-types.gen.d.ts +1 -1
- package/dist/.pikku/pikku-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.json +4 -0
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +9 -9
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
- package/dist/.pikku/schemas/register.gen.js +7 -7
- package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
- package/dist/.pikku/workflow/meta/allWorkflow.gen.json +8 -2
- package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
- package/dist/bin/pikku-bin.mjs +2 -2
- package/dist/src/fabric/functions/validate-core.js +65 -0
- package/dist/src/functions/commands/dev.js +9 -17
- package/dist/src/functions/db/db-codegen.d.ts +1 -0
- package/dist/src/functions/db/db-codegen.js +45 -0
- package/dist/src/functions/db/db-introspector.d.ts +12 -0
- package/dist/src/functions/db/local-db.d.ts +8 -0
- package/dist/src/functions/db/local-db.js +17 -0
- package/dist/src/functions/db/postgres/postgres-introspector.d.ts +3 -1
- package/dist/src/functions/db/postgres/postgres-introspector.js +43 -0
- package/dist/src/functions/db/sqlite/sqlite-introspector.d.ts +3 -1
- package/dist/src/functions/db/sqlite/sqlite-introspector.js +14 -0
- package/dist/src/functions/db/sqlite/sqlite-runtime-node.js +16 -3
- package/dist/src/functions/wirings/auth/serialize-auth-gen.js +4 -2
- package/dist/src/scaffold/rpc-remote.gen.js +1 -1
- package/package.json +2 -2
- 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
|
-
|
|
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:
|
|
49
|
+
lines.push(` schema: AuthSecretSchema,`);
|
|
48
50
|
lines.push(`})`);
|
|
49
51
|
lines.push('');
|
|
50
52
|
// wireSecret for each provider
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pikku/cli",
|
|
3
|
-
"version": "0.12.
|
|
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.
|
|
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
|