@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
|
@@ -96,24 +96,28 @@
|
|
|
96
96
|
"pikkuAIAgent": "pikkuAIAgent",
|
|
97
97
|
"pikkuPublicAgent": "pikkuPublicAgent",
|
|
98
98
|
"pikkuAuth": "pikkuAuth",
|
|
99
|
+
"pikkuChannels": "pikkuChannels",
|
|
100
|
+
"pikkuChannelTypes": "pikkuChannelTypes",
|
|
101
|
+
"pikkuChannelsMap": "pikkuChannelsMap",
|
|
102
|
+
"pikkuCommandChannels": "pikkuCommandChannels",
|
|
99
103
|
"pikkuCLIEntry": "pikkuCLIEntry",
|
|
100
104
|
"pikkuCLI": "pikkuCLI",
|
|
101
105
|
"pikkuConsoleFunctions": "pikkuConsoleFunctions",
|
|
102
106
|
"pikkuNodeTypes": "pikkuNodeTypes",
|
|
103
107
|
"pikkuNodesMeta": "pikkuNodesMeta",
|
|
104
108
|
"pikkuCredentials": "pikkuCredentials",
|
|
105
|
-
"pikkuGateway": "pikkuGateway",
|
|
106
109
|
"pikkuFunctionTypesSplit": "pikkuFunctionTypesSplit",
|
|
107
110
|
"pikkuFunctionTypes": "pikkuFunctionTypes",
|
|
108
111
|
"pikkuFunctions": "pikkuFunctions",
|
|
109
112
|
"pikkuServices": "pikkuServices",
|
|
110
|
-
"
|
|
111
|
-
"pikkuMCPTypes": "pikkuMCPTypes",
|
|
112
|
-
"pikkuMCP": "pikkuMCP",
|
|
113
|
+
"pikkuGateway": "pikkuGateway",
|
|
113
114
|
"pikkuHTTPMap": "pikkuHTTPMap",
|
|
114
115
|
"pikkuCommandHTTP": "pikkuCommandHTTP",
|
|
115
116
|
"pikkuHTTPTypes": "pikkuHTTPTypes",
|
|
116
117
|
"pikkuHTTP": "pikkuHTTP",
|
|
118
|
+
"pikkuMCPJSON": "pikkuMCPJSON",
|
|
119
|
+
"pikkuMCPTypes": "pikkuMCPTypes",
|
|
120
|
+
"pikkuMCP": "pikkuMCP",
|
|
117
121
|
"pikkuMiddleware": "pikkuMiddleware",
|
|
118
122
|
"pikkuSecretDefinitionTypes": "pikkuSecretDefinitionTypes",
|
|
119
123
|
"pikkuVariableDefinitionTypes": "pikkuVariableDefinitionTypes",
|
|
@@ -136,9 +140,5 @@
|
|
|
136
140
|
"pikkuTriggerTypes": "pikkuTriggerTypes",
|
|
137
141
|
"pikkuTrigger": "pikkuTrigger",
|
|
138
142
|
"pikkuVariables": "pikkuVariables",
|
|
139
|
-
"pikkuWorkflowRoutes": "pikkuWorkflowRoutes"
|
|
140
|
-
"pikkuChannels": "pikkuChannels",
|
|
141
|
-
"pikkuChannelTypes": "pikkuChannelTypes",
|
|
142
|
-
"pikkuChannelsMap": "pikkuChannelsMap",
|
|
143
|
-
"pikkuCommandChannels": "pikkuCommandChannels"
|
|
143
|
+
"pikkuWorkflowRoutes": "pikkuWorkflowRoutes"
|
|
144
144
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* This file was generated by @pikku/cli@0.12.
|
|
2
|
+
* This file was generated by @pikku/cli@0.12.30
|
|
3
3
|
*/
|
|
4
4
|
import { addSchema } from '@pikku/core/schema';
|
|
5
5
|
import * as PikkuSchemasOutput from './schemas/PikkuSchemasOutput.schema.json' with { type: 'json' };
|
|
@@ -192,20 +192,20 @@ import * as PikkuCLIEntryOutput from './schemas/PikkuCLIEntryOutput.schema.json'
|
|
|
192
192
|
addSchema('PikkuCLIEntryOutput', PikkuCLIEntryOutput);
|
|
193
193
|
import * as PikkuCLIOutput from './schemas/PikkuCLIOutput.schema.json' with { type: 'json' };
|
|
194
194
|
addSchema('PikkuCLIOutput', PikkuCLIOutput);
|
|
195
|
-
import * as PikkuGatewayOutput from './schemas/PikkuGatewayOutput.schema.json' with { type: 'json' };
|
|
196
|
-
addSchema('PikkuGatewayOutput', PikkuGatewayOutput);
|
|
197
195
|
import * as PikkuFunctionTypesSplitInput from './schemas/PikkuFunctionTypesSplitInput.schema.json' with { type: 'json' };
|
|
198
196
|
addSchema('PikkuFunctionTypesSplitInput', PikkuFunctionTypesSplitInput);
|
|
199
197
|
import * as PikkuFunctionsOutput from './schemas/PikkuFunctionsOutput.schema.json' with { type: 'json' };
|
|
200
198
|
addSchema('PikkuFunctionsOutput', PikkuFunctionsOutput);
|
|
199
|
+
import * as PikkuGatewayOutput from './schemas/PikkuGatewayOutput.schema.json' with { type: 'json' };
|
|
200
|
+
addSchema('PikkuGatewayOutput', PikkuGatewayOutput);
|
|
201
201
|
import * as PikkuCommandHTTPOutput from './schemas/PikkuCommandHTTPOutput.schema.json' with { type: 'json' };
|
|
202
202
|
addSchema('PikkuCommandHTTPOutput', PikkuCommandHTTPOutput);
|
|
203
203
|
import * as PikkuHTTPOutput from './schemas/PikkuHTTPOutput.schema.json' with { type: 'json' };
|
|
204
204
|
addSchema('PikkuHTTPOutput', PikkuHTTPOutput);
|
|
205
|
-
import * as PikkuMCPOutput from './schemas/PikkuMCPOutput.schema.json' with { type: 'json' };
|
|
206
|
-
addSchema('PikkuMCPOutput', PikkuMCPOutput);
|
|
207
205
|
import * as PikkuMiddlewareOutput from './schemas/PikkuMiddlewareOutput.schema.json' with { type: 'json' };
|
|
208
206
|
addSchema('PikkuMiddlewareOutput', PikkuMiddlewareOutput);
|
|
207
|
+
import * as PikkuMCPOutput from './schemas/PikkuMCPOutput.schema.json' with { type: 'json' };
|
|
208
|
+
addSchema('PikkuMCPOutput', PikkuMCPOutput);
|
|
209
209
|
import * as PikkuPackageOutput from './schemas/PikkuPackageOutput.schema.json' with { type: 'json' };
|
|
210
210
|
addSchema('PikkuPackageOutput', PikkuPackageOutput);
|
|
211
211
|
import * as PikkuPermissionsOutput from './schemas/PikkuPermissionsOutput.schema.json' with { type: 'json' };
|
|
@@ -222,13 +222,13 @@ import * as PikkuTriggerTypesInput from './schemas/PikkuTriggerTypesInput.schema
|
|
|
222
222
|
addSchema('PikkuTriggerTypesInput', PikkuTriggerTypesInput);
|
|
223
223
|
import * as PikkuTriggerOutput from './schemas/PikkuTriggerOutput.schema.json' with { type: 'json' };
|
|
224
224
|
addSchema('PikkuTriggerOutput', PikkuTriggerOutput);
|
|
225
|
-
import * as PikkuWorkflowRoutesOutput from './schemas/PikkuWorkflowRoutesOutput.schema.json' with { type: 'json' };
|
|
226
|
-
addSchema('PikkuWorkflowRoutesOutput', PikkuWorkflowRoutesOutput);
|
|
227
225
|
import * as PikkuPublicRPCOutput from './schemas/PikkuPublicRPCOutput.schema.json' with { type: 'json' };
|
|
228
226
|
addSchema('PikkuPublicRPCOutput', PikkuPublicRPCOutput);
|
|
229
227
|
import * as PikkuRemoteRPCOutput from './schemas/PikkuRemoteRPCOutput.schema.json' with { type: 'json' };
|
|
230
228
|
addSchema('PikkuRemoteRPCOutput', PikkuRemoteRPCOutput);
|
|
231
229
|
import * as PikkuRPCOutput from './schemas/PikkuRPCOutput.schema.json' with { type: 'json' };
|
|
232
230
|
addSchema('PikkuRPCOutput', PikkuRPCOutput);
|
|
231
|
+
import * as PikkuWorkflowRoutesOutput from './schemas/PikkuWorkflowRoutesOutput.schema.json' with { type: 'json' };
|
|
232
|
+
addSchema('PikkuWorkflowRoutesOutput', PikkuWorkflowRoutesOutput);
|
|
233
233
|
import * as PikkuCLIConfig from './schemas/PikkuCLIConfig.schema.json' with { type: 'json' };
|
|
234
234
|
addSchema('PikkuCLIConfig', PikkuCLIConfig);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* This file was generated by @pikku/cli@0.12.
|
|
2
|
+
* This file was generated by @pikku/cli@0.12.30
|
|
3
3
|
*/
|
|
4
4
|
export { wireVariable } from '@pikku/core/variable';
|
|
5
5
|
export type { CoreVariable, VariableDefinitionMeta, VariableDefinitionsMeta } from '@pikku/core/variable';
|
|
@@ -225,9 +225,15 @@
|
|
|
225
225
|
"Events scaffold": {
|
|
226
226
|
"nodeId": "Events scaffold",
|
|
227
227
|
"rpcName": "pikkuEventsScaffold",
|
|
228
|
-
"next": "
|
|
228
|
+
"next": "Emails",
|
|
229
229
|
"stepHash": "b5a547ac59ef"
|
|
230
230
|
},
|
|
231
|
+
"Emails": {
|
|
232
|
+
"nodeId": "Emails",
|
|
233
|
+
"rpcName": "pikkuEmails",
|
|
234
|
+
"next": "Secret definition types",
|
|
235
|
+
"stepHash": "bb8361cb96cf"
|
|
236
|
+
},
|
|
231
237
|
"Secret definition types": {
|
|
232
238
|
"nodeId": "Secret definition types",
|
|
233
239
|
"rpcName": "pikkuSecretDefinitionTypes",
|
|
@@ -521,5 +527,5 @@
|
|
|
521
527
|
"entryNodeIds": [
|
|
522
528
|
"Bootstrap inspect"
|
|
523
529
|
],
|
|
524
|
-
"graphHash": "
|
|
530
|
+
"graphHash": "359c0b7178dc"
|
|
525
531
|
}
|
package/dist/bin/pikku-bin.mjs
CHANGED
|
@@ -11,8 +11,8 @@ async function checkForUpdate() {
|
|
|
11
11
|
})
|
|
12
12
|
if (!res.ok) return
|
|
13
13
|
const { version: latest } = await res.json()
|
|
14
|
-
if (latest !== '0.12.
|
|
15
|
-
process.stderr.write(`\n Update available 0.12.
|
|
14
|
+
if (latest !== '0.12.30') {
|
|
15
|
+
process.stderr.write(`\n Update available 0.12.30 → ${latest}\n brew upgrade pikku or npm install -g @pikku/cli\n\n`)
|
|
16
16
|
}
|
|
17
17
|
} catch {}
|
|
18
18
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
2
|
import { readdir } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
+
import { readFile } from 'node:fs/promises';
|
|
4
5
|
import { z } from 'zod';
|
|
5
6
|
import { added, changed, dim, removed } from '../lib/output.js';
|
|
6
7
|
import { WorkspaceValidateOutput, readJsonSafe, readTextSafe, runWorkspaceValidate, } from '../../functions/validate/workspace-validate.js';
|
|
@@ -31,6 +32,53 @@ export async function runFabricValidate(startDir = process.cwd()) {
|
|
|
31
32
|
const info = (id, message, path, fixHint) => {
|
|
32
33
|
findings.push({ id, severity: 'info', message, path, fixHint });
|
|
33
34
|
};
|
|
35
|
+
// These dirs are generated/runtime artefacts; committing them bloats PRs and causes stale issues
|
|
36
|
+
const gitignorePath = join(root, '.gitignore');
|
|
37
|
+
const REQUIRED_GITIGNORE_ENTRIES = [
|
|
38
|
+
{
|
|
39
|
+
name: '.pikku',
|
|
40
|
+
patterns: ['.pikku', '.pikku/', '/.pikku', '/.pikku/'],
|
|
41
|
+
reason: 'generated codegen artifacts will pollute commits and PRs',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: '.pikku-runtime',
|
|
45
|
+
patterns: [
|
|
46
|
+
'.pikku-runtime',
|
|
47
|
+
'.pikku-runtime/',
|
|
48
|
+
'/.pikku-runtime',
|
|
49
|
+
'/.pikku-runtime/',
|
|
50
|
+
],
|
|
51
|
+
reason: 'runtime state directory should not be committed',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: '.opencode',
|
|
55
|
+
patterns: ['.opencode', '.opencode/', '/.opencode', '/.opencode/'],
|
|
56
|
+
reason: 'OpenCode session data should not be committed',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: '*.gen.ts',
|
|
60
|
+
patterns: ['*.gen.ts', '**/*.gen.ts'],
|
|
61
|
+
reason: 'generated TypeScript files (by pikku and TanStack Start) should not be committed — they are regenerated at build time',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: '*.gen.js',
|
|
65
|
+
patterns: ['*.gen.js', '**/*.gen.js'],
|
|
66
|
+
reason: 'generated JavaScript files (by pikku and TanStack Start) should not be committed — they are regenerated at build time',
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
try {
|
|
70
|
+
const gitignoreText = await readFile(gitignorePath, 'utf8');
|
|
71
|
+
const lines = gitignoreText.split('\n').map((l) => l.trim());
|
|
72
|
+
for (const entry of REQUIRED_GITIGNORE_ENTRIES) {
|
|
73
|
+
const covered = lines.some((l) => entry.patterns.includes(l));
|
|
74
|
+
if (!covered) {
|
|
75
|
+
w(`${entry.name.replace(/[^a-z0-9]/gi, '-')}-not-gitignored`, `${entry.name} is not listed in .gitignore — ${entry.reason}`, gitignorePath, `Add "${entry.name}" to .gitignore`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
w('gitignore-missing', '.gitignore not found at project root — generated artifacts (.pikku, .pikku-runtime, .opencode) may be committed accidentally', gitignorePath, 'Create .gitignore and add ".pikku", ".pikku-runtime", and ".opencode" to it');
|
|
81
|
+
}
|
|
34
82
|
const fabricConfigPath = join(root, 'fabric.config.json');
|
|
35
83
|
const fabricConfig = await readJsonSafe(fabricConfigPath);
|
|
36
84
|
if (!fabricConfig) {
|
|
@@ -69,6 +117,12 @@ export async function runFabricValidate(startDir = process.cwd()) {
|
|
|
69
117
|
if (fnAllDeps['@pikku/kysely-postgres']) {
|
|
70
118
|
e('fn-pkg-postgres-dep', '@pikku/kysely-postgres is in packages/functions dependencies — Fabric uses SQLite/libSQL (Turso), not PostgreSQL', fnPkgPath, 'Remove @pikku/kysely-postgres and use @pikku/kysely-sqlite with LibsqlWebDialect instead');
|
|
71
119
|
}
|
|
120
|
+
if (!fnPkg.dependencies?.['@pikku/schema-cfworker']) {
|
|
121
|
+
e('missing-schema-cfworker', '@pikku/schema-cfworker is not in dependencies — every Cloudflare worker entry requires it', fnPkgPath, 'Run `yarn add @pikku/schema-cfworker` in packages/functions — must be in dependencies, not devDependencies');
|
|
122
|
+
}
|
|
123
|
+
if (!fnPkg.dependencies?.['@pikku/kysely']) {
|
|
124
|
+
e('missing-pikku-kysely', '@pikku/kysely is not in dependencies — every Cloudflare worker entry requires it (KyselySecretService)', fnPkgPath, 'Run `yarn add @pikku/kysely` in packages/functions — must be in dependencies, not devDependencies');
|
|
125
|
+
}
|
|
72
126
|
}
|
|
73
127
|
const servicesPath = join(fnDir, 'src', 'services.ts');
|
|
74
128
|
const servicesText = await readTextSafe(servicesPath);
|
|
@@ -90,6 +144,17 @@ export async function runFabricValidate(startDir = process.cwd()) {
|
|
|
90
144
|
e('missing-kysely-sqlite', 'services.ts imports @pikku/kysely-sqlite but it is not in root package.json', rootPkgPath, 'Add "@pikku/kysely-sqlite": "file:./vendor/pikku-kysely-sqlite.tgz" to dependencies');
|
|
91
145
|
}
|
|
92
146
|
}
|
|
147
|
+
// agent units — require explicit deps rather than CI injection
|
|
148
|
+
const agentMetaPath = join(fnDir, '.pikku', 'agent', 'pikku-agent-wirings-meta.gen.json');
|
|
149
|
+
const agentMeta = await readJsonSafe(agentMetaPath);
|
|
150
|
+
if (agentMeta && Object.keys(agentMeta.agentsMeta ?? {}).length > 0) {
|
|
151
|
+
if (!fnPkg?.dependencies?.['@pikku/ai-vercel']) {
|
|
152
|
+
e('missing-ai-vercel', 'Project declares agent units but @pikku/ai-vercel is not in dependencies', fnPkgPath, 'Run `yarn add @pikku/ai-vercel` in packages/functions — must be in dependencies, not devDependencies');
|
|
153
|
+
}
|
|
154
|
+
if (!fnPkg?.dependencies?.['@ai-sdk/openai-compatible']) {
|
|
155
|
+
e('missing-ai-sdk-openai-compatible', 'Project declares agent units but @ai-sdk/openai-compatible is not in dependencies', fnPkgPath, 'Run `yarn add @ai-sdk/openai-compatible` in packages/functions — must be in dependencies, not devDependencies');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
93
158
|
// db/sqlite/ — presence, numbering and SQL dialect
|
|
94
159
|
const migrationsDir = join(fnDir, 'db', 'sqlite');
|
|
95
160
|
if (!existsSync(migrationsDir)) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { existsSync } from 'fs';
|
|
2
1
|
import { join, resolve } from 'path';
|
|
3
2
|
import { pikkuSessionlessFunc } from '#pikku';
|
|
4
3
|
import chokidar from 'chokidar';
|
|
@@ -14,11 +13,11 @@ import { pikkuWebsocketHandler } from '@pikku/ws';
|
|
|
14
13
|
import { PikkuNodeHTTPServer } from '@pikku/node-http-server';
|
|
15
14
|
import { WebSocketServer } from 'ws';
|
|
16
15
|
import { InMemorySchedulerService } from '@pikku/schedule';
|
|
17
|
-
import { resolveDb, createKysely } from '../db/local-db.js';
|
|
16
|
+
import { resolveDb, createKysely, parseDatabaseUrl, } from '../db/local-db.js';
|
|
18
17
|
import { loadUserBootstrap, loadUserModule } from './load-user-project.js';
|
|
19
18
|
export const dev = pikkuSessionlessFunc({
|
|
20
19
|
remote: true,
|
|
21
|
-
func: async ({ logger, config, getInspectorState }, { port, watch, hmr }, { rpc }) => {
|
|
20
|
+
func: async ({ logger, config, getInspectorState, variables }, { port, watch, hmr }, { rpc }) => {
|
|
22
21
|
const resolvedPort = parseInt(port || '3000', 10);
|
|
23
22
|
const hostname = 'localhost';
|
|
24
23
|
const enableWatch = watch !== false;
|
|
@@ -40,8 +39,6 @@ export const dev = pikkuSessionlessFunc({
|
|
|
40
39
|
const commandWorkflowRegistrations = new Map(pikkuState(null, 'workflows', 'registrations'));
|
|
41
40
|
const workflowService = new InMemoryWorkflowService();
|
|
42
41
|
const pikkuDir = resolve(config.rootDir, config.outDir);
|
|
43
|
-
const bootstrapExists = existsSync(resolve(pikkuDir, 'pikku-bootstrap.gen.ts')) ||
|
|
44
|
-
existsSync(resolve(pikkuDir, 'pikku-bootstrap.gen.js'));
|
|
45
42
|
const runAll = async () => {
|
|
46
43
|
await workflowService.runToCompletion('allWorkflow', {}, rpc);
|
|
47
44
|
};
|
|
@@ -97,9 +94,6 @@ export const dev = pikkuSessionlessFunc({
|
|
|
97
94
|
pikkuState(null, 'workflows', 'registrations', previousWorkflowRegistrations);
|
|
98
95
|
}
|
|
99
96
|
};
|
|
100
|
-
if (bootstrapExists) {
|
|
101
|
-
await loadUserBootstrap(pikkuDir);
|
|
102
|
-
}
|
|
103
97
|
await runAllWithCommandState();
|
|
104
98
|
const inspectorState = await getInspectorState(true);
|
|
105
99
|
const { pikkuConfigFactory, singletonServicesFactory } = inspectorState.filesAndMethods;
|
|
@@ -107,21 +101,19 @@ export const dev = pikkuSessionlessFunc({
|
|
|
107
101
|
logger.error('createConfig and createSingletonServices must be defined in your project');
|
|
108
102
|
return;
|
|
109
103
|
}
|
|
110
|
-
|
|
111
|
-
await loadUserBootstrap(pikkuDir);
|
|
112
|
-
}
|
|
104
|
+
await loadUserBootstrap(pikkuDir);
|
|
113
105
|
workflowService.rewireQueueWorkers();
|
|
114
106
|
const configModule = await loadUserModule(pikkuConfigFactory.file);
|
|
115
107
|
const servicesModule = await loadUserModule(singletonServicesFactory.file);
|
|
116
108
|
const userCreateConfig = configModule[pikkuConfigFactory.variable];
|
|
117
109
|
const userCreateSingletonServices = servicesModule[singletonServicesFactory.variable];
|
|
118
110
|
const userConfig = await userCreateConfig();
|
|
119
|
-
const
|
|
120
|
-
const
|
|
121
|
-
?
|
|
122
|
-
: userConfig
|
|
123
|
-
|
|
124
|
-
|
|
111
|
+
const envDatabaseUrl = await variables.get('DATABASE_URL');
|
|
112
|
+
const effectiveDbConfig = envDatabaseUrl
|
|
113
|
+
? parseDatabaseUrl(envDatabaseUrl)
|
|
114
|
+
: userConfig;
|
|
115
|
+
const resolvedDb = resolveDb(effectiveDbConfig, config.rootDir, config.outDir, config.runtimeDir);
|
|
116
|
+
const resolvedLocalDb = resolvedDb?.dialect === 'sqlite' ? resolvedDb : undefined;
|
|
125
117
|
const kysely = resolvedLocalDb
|
|
126
118
|
? await createKysely(resolvedLocalDb)
|
|
127
119
|
: undefined;
|
|
@@ -308,11 +308,43 @@ export async function generateSchemaTypes(introspector, options) {
|
|
|
308
308
|
const classificationMapBody = options.classificationMapFile
|
|
309
309
|
? emitClassificationMap(tables)
|
|
310
310
|
: null;
|
|
311
|
+
// ── pikku-db-schema.gen.json ─────────────────────────────────────────────────
|
|
312
|
+
let schemaJsonBody = null;
|
|
313
|
+
if (options.schemaJsonFile) {
|
|
314
|
+
const [fkResults, enums] = await Promise.all([
|
|
315
|
+
Promise.all(tableNames.map((name) => introspector.getForeignKeys(name))),
|
|
316
|
+
introspector.listEnums(),
|
|
317
|
+
]);
|
|
318
|
+
const fkMap = new Map(tableNames.map((name, i) => [name, fkResults[i]]));
|
|
319
|
+
const jsonTables = tables.map((t) => ({
|
|
320
|
+
name: t.name,
|
|
321
|
+
columns: t.columns.map((c) => {
|
|
322
|
+
const fk = fkMap.get(t.name)?.find((f) => f.column === c.name);
|
|
323
|
+
return {
|
|
324
|
+
name: c.name,
|
|
325
|
+
type: c.type,
|
|
326
|
+
nullable: !c.notNull && !c.pk,
|
|
327
|
+
isPrimaryKey: c.pk,
|
|
328
|
+
...(fk
|
|
329
|
+
? {
|
|
330
|
+
foreignKey: {
|
|
331
|
+
table: fk.foreignTable,
|
|
332
|
+
column: fk.foreignColumn,
|
|
333
|
+
},
|
|
334
|
+
}
|
|
335
|
+
: {}),
|
|
336
|
+
};
|
|
337
|
+
}),
|
|
338
|
+
}));
|
|
339
|
+
schemaJsonBody =
|
|
340
|
+
JSON.stringify({ tables: jsonTables, enums }, null, 2) + '\n';
|
|
341
|
+
}
|
|
311
342
|
// ── write files ───────────────────────────────────────────────────────────────
|
|
312
343
|
let existingSchema = null;
|
|
313
344
|
let existingCoercion = null;
|
|
314
345
|
let existingManifest = null;
|
|
315
346
|
let existingClassificationMap = null;
|
|
347
|
+
let existingSchemaJson = null;
|
|
316
348
|
try {
|
|
317
349
|
existingSchema = readFileSync(options.outFile, 'utf8');
|
|
318
350
|
}
|
|
@@ -341,11 +373,20 @@ export async function generateSchemaTypes(introspector, options) {
|
|
|
341
373
|
/* ok */
|
|
342
374
|
}
|
|
343
375
|
}
|
|
376
|
+
if (options.schemaJsonFile) {
|
|
377
|
+
try {
|
|
378
|
+
existingSchemaJson = readFileSync(options.schemaJsonFile, 'utf8');
|
|
379
|
+
}
|
|
380
|
+
catch {
|
|
381
|
+
/* ok */
|
|
382
|
+
}
|
|
383
|
+
}
|
|
344
384
|
const schemaChanged = existingSchema !== schemaBody;
|
|
345
385
|
const coercionChanged = existingCoercion !== coercionBody;
|
|
346
386
|
const manifestChanged = manifestBody !== null && existingManifest !== manifestBody;
|
|
347
387
|
const classificationMapChanged = classificationMapBody !== null &&
|
|
348
388
|
existingClassificationMap !== classificationMapBody;
|
|
389
|
+
const schemaJsonChanged = schemaJsonBody !== null && existingSchemaJson !== schemaJsonBody;
|
|
349
390
|
if (schemaChanged) {
|
|
350
391
|
mkdirSync(dirname(options.outFile), { recursive: true });
|
|
351
392
|
writeFileSync(options.outFile, schemaBody, 'utf8');
|
|
@@ -364,6 +405,10 @@ export async function generateSchemaTypes(introspector, options) {
|
|
|
364
405
|
mkdirSync(dirname(options.classificationMapFile), { recursive: true });
|
|
365
406
|
writeFileSync(options.classificationMapFile, classificationMapBody, 'utf8');
|
|
366
407
|
}
|
|
408
|
+
if (schemaJsonChanged && options.schemaJsonFile && schemaJsonBody) {
|
|
409
|
+
mkdirSync(dirname(options.schemaJsonFile), { recursive: true });
|
|
410
|
+
writeFileSync(options.schemaJsonFile, schemaJsonBody, 'utf8');
|
|
411
|
+
}
|
|
367
412
|
return {
|
|
368
413
|
outFile: options.outFile,
|
|
369
414
|
coercionFile: options.coercionFile,
|
|
@@ -8,8 +8,20 @@ export interface ColumnInfo {
|
|
|
8
8
|
/** True for virtual or stored generated columns — these are read-only and never inserted. */
|
|
9
9
|
generated?: boolean;
|
|
10
10
|
}
|
|
11
|
+
export interface ForeignKeyInfo {
|
|
12
|
+
column: string;
|
|
13
|
+
foreignTable: string;
|
|
14
|
+
foreignColumn: string;
|
|
15
|
+
}
|
|
16
|
+
export interface EnumInfo {
|
|
17
|
+
name: string;
|
|
18
|
+
schema: string;
|
|
19
|
+
values: string[];
|
|
20
|
+
}
|
|
11
21
|
export interface DbIntrospector {
|
|
12
22
|
listTables(): Promise<string[]>;
|
|
13
23
|
getColumns(table: string): Promise<ColumnInfo[]>;
|
|
24
|
+
getForeignKeys(table: string): Promise<ForeignKeyInfo[]>;
|
|
25
|
+
listEnums(): Promise<EnumInfo[]>;
|
|
14
26
|
close(): Promise<void>;
|
|
15
27
|
}
|
|
@@ -11,6 +11,7 @@ interface ResolvedDbBase {
|
|
|
11
11
|
coercionFile: string;
|
|
12
12
|
manifestFile: string;
|
|
13
13
|
classificationMapFile: string;
|
|
14
|
+
schemaJsonFile: string;
|
|
14
15
|
classificationsFile: string;
|
|
15
16
|
classificationsGenJsonFile: string;
|
|
16
17
|
zodFile: string;
|
|
@@ -27,6 +28,13 @@ export interface ResolvedPostgresDb extends ResolvedDbBase {
|
|
|
27
28
|
connectionString: string;
|
|
28
29
|
}
|
|
29
30
|
export type ResolvedDb = ResolvedSqliteDb | ResolvedPostgresDb;
|
|
31
|
+
/**
|
|
32
|
+
* Parse a DATABASE_URL string into the subset of UserConfigShape that resolveDb understands.
|
|
33
|
+
* - postgres(ql):// → { postgresUrl }
|
|
34
|
+
* - libsql:// or http(s):// → {} (remote, not handled by the CLI layer)
|
|
35
|
+
* - anything else → { sqliteDb } (local file path)
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseDatabaseUrl(url: string): Pick<UserConfigShape, 'sqliteDb' | 'postgresUrl'>;
|
|
30
38
|
/**
|
|
31
39
|
* Resolve a UserConfigShape into an absolute-path descriptor.
|
|
32
40
|
* Returns null when neither sqliteDb nor postgresUrl is configured.
|
|
@@ -15,6 +15,19 @@ import { seed as runSeed } from './sqlite/seed.js';
|
|
|
15
15
|
import { PostgresMigrationExecutor } from './postgres/postgres-migrator.js';
|
|
16
16
|
import { PostgresIntrospector } from './postgres/postgres-introspector.js';
|
|
17
17
|
// ─── Resolution ───────────────────────────────────────────────────────────────
|
|
18
|
+
/**
|
|
19
|
+
* Parse a DATABASE_URL string into the subset of UserConfigShape that resolveDb understands.
|
|
20
|
+
* - postgres(ql):// → { postgresUrl }
|
|
21
|
+
* - libsql:// or http(s):// → {} (remote, not handled by the CLI layer)
|
|
22
|
+
* - anything else → { sqliteDb } (local file path)
|
|
23
|
+
*/
|
|
24
|
+
export function parseDatabaseUrl(url) {
|
|
25
|
+
if (/^postgres(ql)?:\/\//.test(url))
|
|
26
|
+
return { postgresUrl: url };
|
|
27
|
+
if (/^(libsql|https?):\/\//.test(url))
|
|
28
|
+
return {};
|
|
29
|
+
return { sqliteDb: url };
|
|
30
|
+
}
|
|
18
31
|
/**
|
|
19
32
|
* Resolve a UserConfigShape into an absolute-path descriptor.
|
|
20
33
|
* Returns null when neither sqliteDb nor postgresUrl is configured.
|
|
@@ -27,6 +40,7 @@ export function resolveDb(userConfig, rootDir, outDir, runtimeDir) {
|
|
|
27
40
|
coercionFile: join(outDir, 'db', 'coercion.gen.ts'),
|
|
28
41
|
manifestFile: join(outDir, 'db', 'classification.gen.ts'),
|
|
29
42
|
classificationMapFile: join(outDir, 'db', 'classification-map.gen.d.ts'),
|
|
43
|
+
schemaJsonFile: join(outDir, 'db', 'pikku-db-schema.gen.json'),
|
|
30
44
|
classificationsFile: join(rootDir, 'db', 'annotations.ts'),
|
|
31
45
|
classificationsGenJsonFile: join(outDir, 'db', 'annotations.gen.json'),
|
|
32
46
|
zodFile: join(outDir, 'db', 'zod.gen.ts'),
|
|
@@ -82,6 +96,7 @@ export async function migrateAndCodegen(resolved) {
|
|
|
82
96
|
coercionFile: resolved.coercionFile,
|
|
83
97
|
manifestFile: resolved.manifestFile,
|
|
84
98
|
classificationMapFile: resolved.classificationMapFile,
|
|
99
|
+
schemaJsonFile: resolved.schemaJsonFile,
|
|
85
100
|
camelCase: resolved.camelCase,
|
|
86
101
|
rootDir: resolved.rootDir,
|
|
87
102
|
migrationsDir: resolved.migrationsDir,
|
|
@@ -107,7 +122,9 @@ export async function migrateAndCodegen(resolved) {
|
|
|
107
122
|
coercionFile: resolved.coercionFile,
|
|
108
123
|
manifestFile: resolved.manifestFile,
|
|
109
124
|
classificationMapFile: resolved.classificationMapFile,
|
|
125
|
+
schemaJsonFile: resolved.schemaJsonFile,
|
|
110
126
|
camelCase: resolved.camelCase,
|
|
127
|
+
rootDir: resolved.rootDir,
|
|
111
128
|
migrationsDir: resolved.migrationsDir,
|
|
112
129
|
});
|
|
113
130
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DbIntrospector, ColumnInfo } from '../db-introspector.js';
|
|
1
|
+
import type { DbIntrospector, ColumnInfo, ForeignKeyInfo, EnumInfo } from '../db-introspector.js';
|
|
2
2
|
interface QueryClient {
|
|
3
3
|
query<T = unknown>(sql: string, params?: unknown[]): Promise<{
|
|
4
4
|
rows: T[];
|
|
@@ -11,6 +11,8 @@ export declare class PostgresIntrospector implements DbIntrospector {
|
|
|
11
11
|
connect(): Promise<void>;
|
|
12
12
|
listTables(): Promise<string[]>;
|
|
13
13
|
getColumns(table: string): Promise<ColumnInfo[]>;
|
|
14
|
+
getForeignKeys(table: string): Promise<ForeignKeyInfo[]>;
|
|
15
|
+
listEnums(): Promise<EnumInfo[]>;
|
|
14
16
|
close(): Promise<void>;
|
|
15
17
|
}
|
|
16
18
|
export {};
|