@pikku/cli 0.12.25 → 0.12.26
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-D4DgafuS.js → index-Ba9K10XZ.js} +4 -4
- 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 +6 -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-meta.gen.json +9 -0
- 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 +116 -101
- 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.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 +10 -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 -5
- package/dist/.pikku/schemas/schemas/DbAuditInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuTestsCoverageInput.schema.json +1 -1
- 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/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/cli.wiring.js +8 -0
- package/dist/src/fabric/functions/validate.function.js +1 -1
- package/dist/src/functions/commands/db-audit.d.ts +1 -0
- package/dist/src/functions/commands/db-audit.js +67 -0
- package/dist/src/functions/commands/db-migrate.js +5 -8
- package/dist/src/functions/commands/db-reset.js +9 -8
- package/dist/src/functions/commands/db-seed.js +9 -8
- package/dist/src/functions/commands/db-shared.d.ts +2 -4
- package/dist/src/functions/commands/db-shared.js +15 -5
- package/dist/src/functions/commands/dev.js +14 -8
- package/dist/src/functions/commands/new-addon.js +2 -2
- package/dist/src/functions/commands/tests-coverage.d.ts +3 -0
- package/dist/src/functions/commands/tests-coverage.js +34 -0
- package/dist/src/functions/db/annotation-parser.d.ts +31 -0
- package/dist/src/functions/db/annotation-parser.js +93 -0
- package/dist/src/functions/db/db-codegen.d.ts +24 -0
- package/dist/src/functions/db/db-codegen.js +276 -0
- package/dist/src/functions/db/db-introspector.d.ts +15 -0
- package/dist/src/functions/db/db-introspector.js +1 -0
- package/dist/src/functions/db/db-migrator.d.ts +32 -0
- package/dist/src/functions/db/db-migrator.js +65 -0
- package/dist/src/functions/db/local-db.d.ts +27 -33
- package/dist/src/functions/db/local-db.js +100 -53
- package/dist/src/functions/db/postgres/postgres-introspector.d.ts +10 -0
- package/dist/src/functions/db/postgres/postgres-introspector.js +54 -0
- package/dist/src/functions/db/postgres/postgres-migrator.d.ts +9 -0
- package/dist/src/functions/db/postgres/postgres-migrator.js +32 -0
- package/dist/src/functions/db/sqlite/sqlite-introspector.d.ts +9 -0
- package/dist/src/functions/db/sqlite/sqlite-introspector.js +35 -0
- package/dist/src/functions/db/sqlite/sqlite-migrator.d.ts +10 -0
- package/dist/src/functions/db/sqlite/sqlite-migrator.js +36 -0
- package/dist/src/functions/validate/workspace-validate.js +3 -2
- package/dist/src/functions/wirings/ai-agent/serialize-public-agent.js +2 -1
- package/dist/src/functions/wirings/console/serialize-console-functions.js +4 -4
- package/dist/src/functions/wirings/functions/serialize-addon-types.js +1 -1
- package/dist/src/scaffold/rpc-remote.gen.js +1 -1
- package/dist/src/services.js +2 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -3
- package/skills/pikku-testing/SKILL.md +208 -0
- package/dist/src/functions/db/sql-migrator.d.ts +0 -26
- package/dist/src/functions/db/sql-migrator.js +0 -104
- package/dist/src/functions/db/sqlite-codegen.d.ts +0 -45
- package/dist/src/functions/db/sqlite-codegen.js +0 -294
- /package/dist/src/functions/db/{seed.d.ts → sqlite/seed.d.ts} +0 -0
- /package/dist/src/functions/db/{seed.js → sqlite/seed.js} +0 -0
- /package/dist/src/functions/db/{sqlite-kysely.d.ts → sqlite/sqlite-kysely.d.ts} +0 -0
- /package/dist/src/functions/db/{sqlite-kysely.js → sqlite/sqlite-kysely.js} +0 -0
- /package/dist/src/functions/db/{sqlite-runtime-bun.d.ts → sqlite/sqlite-runtime-bun.d.ts} +0 -0
- /package/dist/src/functions/db/{sqlite-runtime-bun.js → sqlite/sqlite-runtime-bun.js} +0 -0
- /package/dist/src/functions/db/{sqlite-runtime-node.d.ts → sqlite/sqlite-runtime-node.d.ts} +0 -0
- /package/dist/src/functions/db/{sqlite-runtime-node.js → sqlite/sqlite-runtime-node.js} +0 -0
- /package/dist/src/functions/db/{sqlite-runtime.d.ts → sqlite/sqlite-runtime.d.ts} +0 -0
- /package/dist/src/functions/db/{sqlite-runtime.js → sqlite/sqlite-runtime.js} +0 -0
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
"dbMigrate": "dbMigrate",
|
|
48
48
|
"dbSeed": "dbSeed",
|
|
49
49
|
"dbReset": "dbReset",
|
|
50
|
+
"dbAudit": "dbAudit",
|
|
50
51
|
"workspaceValidate": "workspaceValidate",
|
|
51
52
|
"pikkuVersionsInit": "pikkuVersionsInit",
|
|
52
53
|
"pikkuTestsInit": "pikkuTestsInit",
|
|
@@ -102,11 +103,11 @@
|
|
|
102
103
|
"pikkuNodeTypes": "pikkuNodeTypes",
|
|
103
104
|
"pikkuNodesMeta": "pikkuNodesMeta",
|
|
104
105
|
"pikkuCredentials": "pikkuCredentials",
|
|
105
|
-
"pikkuGateway": "pikkuGateway",
|
|
106
106
|
"pikkuFunctionTypesSplit": "pikkuFunctionTypesSplit",
|
|
107
107
|
"pikkuFunctionTypes": "pikkuFunctionTypes",
|
|
108
108
|
"pikkuFunctions": "pikkuFunctions",
|
|
109
109
|
"pikkuServices": "pikkuServices",
|
|
110
|
+
"pikkuGateway": "pikkuGateway",
|
|
110
111
|
"pikkuHTTPMap": "pikkuHTTPMap",
|
|
111
112
|
"pikkuCommandHTTP": "pikkuCommandHTTP",
|
|
112
113
|
"pikkuHTTPTypes": "pikkuHTTPTypes",
|
|
@@ -114,13 +115,16 @@
|
|
|
114
115
|
"pikkuMCPJSON": "pikkuMCPJSON",
|
|
115
116
|
"pikkuMCPTypes": "pikkuMCPTypes",
|
|
116
117
|
"pikkuMCP": "pikkuMCP",
|
|
117
|
-
"
|
|
118
|
-
"pikkuCLI": "pikkuCLI",
|
|
118
|
+
"pikkuMiddleware": "pikkuMiddleware",
|
|
119
119
|
"pikkuSecretDefinitionTypes": "pikkuSecretDefinitionTypes",
|
|
120
120
|
"pikkuVariableDefinitionTypes": "pikkuVariableDefinitionTypes",
|
|
121
121
|
"pikkuPackage": "pikkuPackage",
|
|
122
122
|
"pikkuPermissions": "pikkuPermissions",
|
|
123
|
-
"
|
|
123
|
+
"pikkuCommandQueueMap": "pikkuCommandQueueMap",
|
|
124
|
+
"pikkuQueueTypes": "pikkuQueueTypes",
|
|
125
|
+
"pikkuCommandQueue": "pikkuCommandQueue",
|
|
126
|
+
"pikkuQueueMap": "pikkuQueueMap",
|
|
127
|
+
"pikkuQueue": "pikkuQueue",
|
|
124
128
|
"pikkuEventsScaffold": "pikkuEventsScaffold",
|
|
125
129
|
"pikkuPublicRPC": "pikkuPublicRPC",
|
|
126
130
|
"pikkuRemoteRPC": "pikkuRemoteRPC",
|
|
@@ -134,9 +138,6 @@
|
|
|
134
138
|
"pikkuTrigger": "pikkuTrigger",
|
|
135
139
|
"pikkuVariables": "pikkuVariables",
|
|
136
140
|
"pikkuWorkflowRoutes": "pikkuWorkflowRoutes",
|
|
137
|
-
"
|
|
138
|
-
"
|
|
139
|
-
"pikkuCommandQueue": "pikkuCommandQueue",
|
|
140
|
-
"pikkuQueueMap": "pikkuQueueMap",
|
|
141
|
-
"pikkuQueue": "pikkuQueue"
|
|
141
|
+
"pikkuCLIEntry": "pikkuCLIEntry",
|
|
142
|
+
"pikkuCLI": "pikkuCLI"
|
|
142
143
|
}
|
|
@@ -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.26
|
|
3
3
|
*/
|
|
4
4
|
import { addSchema } from '@pikku/core/schema';
|
|
5
5
|
import * as PikkuSchemasOutput from './schemas/PikkuSchemasOutput.schema.json' with { type: 'json' };
|
|
@@ -106,6 +106,8 @@ import * as DbSeedInput from './schemas/DbSeedInput.schema.json' with { type: 'j
|
|
|
106
106
|
addSchema('DbSeedInput', DbSeedInput);
|
|
107
107
|
import * as DbResetInput from './schemas/DbResetInput.schema.json' with { type: 'json' };
|
|
108
108
|
addSchema('DbResetInput', DbResetInput);
|
|
109
|
+
import * as DbAuditInput from './schemas/DbAuditInput.schema.json' with { type: 'json' };
|
|
110
|
+
addSchema('DbAuditInput', DbAuditInput);
|
|
109
111
|
import * as WorkspaceValidateInput from './schemas/WorkspaceValidateInput.schema.json' with { type: 'json' };
|
|
110
112
|
addSchema('WorkspaceValidateInput', WorkspaceValidateInput);
|
|
111
113
|
import * as WorkspaceValidateOutput from './schemas/WorkspaceValidateOutput.schema.json' with { type: 'json' };
|
|
@@ -180,12 +182,12 @@ import * as PikkuAIAgentOutput from './schemas/PikkuAIAgentOutput.schema.json' w
|
|
|
180
182
|
addSchema('PikkuAIAgentOutput', PikkuAIAgentOutput);
|
|
181
183
|
import * as PikkuPublicAgentOutput from './schemas/PikkuPublicAgentOutput.schema.json' with { type: 'json' };
|
|
182
184
|
addSchema('PikkuPublicAgentOutput', PikkuPublicAgentOutput);
|
|
183
|
-
import * as PikkuCommandChannelsOutput from './schemas/PikkuCommandChannelsOutput.schema.json' with { type: 'json' };
|
|
184
|
-
addSchema('PikkuCommandChannelsOutput', PikkuCommandChannelsOutput);
|
|
185
185
|
import * as PikkuCLIEntryOutput from './schemas/PikkuCLIEntryOutput.schema.json' with { type: 'json' };
|
|
186
186
|
addSchema('PikkuCLIEntryOutput', PikkuCLIEntryOutput);
|
|
187
187
|
import * as PikkuCLIOutput from './schemas/PikkuCLIOutput.schema.json' with { type: 'json' };
|
|
188
188
|
addSchema('PikkuCLIOutput', PikkuCLIOutput);
|
|
189
|
+
import * as PikkuCommandChannelsOutput from './schemas/PikkuCommandChannelsOutput.schema.json' with { type: 'json' };
|
|
190
|
+
addSchema('PikkuCommandChannelsOutput', PikkuCommandChannelsOutput);
|
|
189
191
|
import * as PikkuConsoleFunctionsOutput from './schemas/PikkuConsoleFunctionsOutput.schema.json' with { type: 'json' };
|
|
190
192
|
addSchema('PikkuConsoleFunctionsOutput', PikkuConsoleFunctionsOutput);
|
|
191
193
|
import * as PikkuNodesMetaOutput from './schemas/PikkuNodesMetaOutput.schema.json' with { type: 'json' };
|
|
@@ -214,14 +216,14 @@ import * as PikkuQueueOutput from './schemas/PikkuQueueOutput.schema.json' with
|
|
|
214
216
|
addSchema('PikkuQueueOutput', PikkuQueueOutput);
|
|
215
217
|
import * as PikkuEventsScaffoldOutput from './schemas/PikkuEventsScaffoldOutput.schema.json' with { type: 'json' };
|
|
216
218
|
addSchema('PikkuEventsScaffoldOutput', PikkuEventsScaffoldOutput);
|
|
217
|
-
import * as PikkuSchedulerOutput from './schemas/PikkuSchedulerOutput.schema.json' with { type: 'json' };
|
|
218
|
-
addSchema('PikkuSchedulerOutput', PikkuSchedulerOutput);
|
|
219
219
|
import * as PikkuPublicRPCOutput from './schemas/PikkuPublicRPCOutput.schema.json' with { type: 'json' };
|
|
220
220
|
addSchema('PikkuPublicRPCOutput', PikkuPublicRPCOutput);
|
|
221
221
|
import * as PikkuRemoteRPCOutput from './schemas/PikkuRemoteRPCOutput.schema.json' with { type: 'json' };
|
|
222
222
|
addSchema('PikkuRemoteRPCOutput', PikkuRemoteRPCOutput);
|
|
223
223
|
import * as PikkuRPCOutput from './schemas/PikkuRPCOutput.schema.json' with { type: 'json' };
|
|
224
224
|
addSchema('PikkuRPCOutput', PikkuRPCOutput);
|
|
225
|
+
import * as PikkuSchedulerOutput from './schemas/PikkuSchedulerOutput.schema.json' with { type: 'json' };
|
|
226
|
+
addSchema('PikkuSchedulerOutput', PikkuSchedulerOutput);
|
|
225
227
|
import * as PikkuTriggerTypesInput from './schemas/PikkuTriggerTypesInput.schema.json' with { type: 'json' };
|
|
226
228
|
addSchema('PikkuTriggerTypesInput', PikkuTriggerTypesInput);
|
|
227
229
|
import * as PikkuTriggerOutput from './schemas/PikkuTriggerOutput.schema.json' with { type: 'json' };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "additionalProperties": false, "definitions": {} }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "noRun": { "type": "boolean" } }, "additionalProperties": false, "definitions": {} }
|
|
1
|
+
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "noRun": { "type": "boolean" }, "aiOut": { "type": "string" } }, "additionalProperties": false, "definitions": {} }
|
|
@@ -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.26
|
|
3
3
|
*/
|
|
4
4
|
export { wireVariable } from '@pikku/core/variable';
|
|
5
5
|
export type { CoreVariable, VariableDefinitionMeta, VariableDefinitionsMeta } from '@pikku/core/variable';
|
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.26') {
|
|
15
|
+
process.stderr.write(`\n Update available 0.12.26 → ${latest}\n brew upgrade pikku or npm install -g @pikku/cli\n\n`)
|
|
16
16
|
}
|
|
17
17
|
} catch {}
|
|
18
18
|
}
|
package/dist/src/cli.wiring.js
CHANGED
|
@@ -18,6 +18,7 @@ import { dev } from './functions/commands/dev.js';
|
|
|
18
18
|
import { dbMigrate } from './functions/commands/db-migrate.js';
|
|
19
19
|
import { dbSeed } from './functions/commands/db-seed.js';
|
|
20
20
|
import { dbReset } from './functions/commands/db-reset.js';
|
|
21
|
+
import { dbAudit } from './functions/commands/db-audit.js';
|
|
21
22
|
import { workspaceValidate, renderWorkspaceValidate, } from './functions/commands/workspace-validate.js';
|
|
22
23
|
import { pikkuVersionsInit } from './functions/commands/versions-init.js';
|
|
23
24
|
import { pikkuTestsInit } from './functions/commands/tests-init.js';
|
|
@@ -230,6 +231,10 @@ wireCLI({
|
|
|
230
231
|
func: dbReset,
|
|
231
232
|
description: 'Wipe and recreate the dev database (migrate + seed)',
|
|
232
233
|
}),
|
|
234
|
+
audit: pikkuCLICommand({
|
|
235
|
+
func: dbAudit,
|
|
236
|
+
description: 'Report column classifications from the manifest and flag columns with no anonymize strategy',
|
|
237
|
+
}),
|
|
233
238
|
},
|
|
234
239
|
},
|
|
235
240
|
workspace: {
|
|
@@ -460,6 +465,9 @@ wireCLI({
|
|
|
460
465
|
noRun: {
|
|
461
466
|
description: 'Skip running the suite and only re-analyse an existing coverage-final.json',
|
|
462
467
|
},
|
|
468
|
+
aiOut: {
|
|
469
|
+
description: 'Write an AI-ready coverage prompt to the given file path (use - for stdout)',
|
|
470
|
+
},
|
|
463
471
|
},
|
|
464
472
|
}),
|
|
465
473
|
},
|
|
@@ -256,7 +256,7 @@ export async function runValidate(startDir = process.cwd()) {
|
|
|
256
256
|
info('wirings-dir-missing', 'packages/functions/src/wirings/ not found', join(fnDir, 'src', 'wirings'), 'Create src/wirings/ for transport bindings: *.http.ts, *.queue.ts, *.schedule.ts, *.channel.ts, *.cli.ts');
|
|
257
257
|
}
|
|
258
258
|
if (!existsSync(join(fnDir, 'src', 'config.ts'))) {
|
|
259
|
-
info('config-missing', 'packages/functions/src/config.ts not found', join(fnDir, 'src', 'config.ts'),
|
|
259
|
+
info('config-missing', 'packages/functions/src/config.ts not found', join(fnDir, 'src', 'config.ts'), "Create src/config.ts: export const createConfig = pikkuConfig(async () => ({ sqliteDb: '.pikku-runtime/dev.db' }))");
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
262
|
// ── apps/ vs fabric.config.json frontends ─────────────────────────────
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const dbAudit: import("#pikku").PikkuFunctionConfig<{}, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<{}, void, "rpc" | "session", import("#pikku").Services> | import("#pikku").PikkuFunction<{}, void, "rpc" | "session", import("#pikku").Services>, undefined, undefined>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { pikkuSessionlessFunc } from '#pikku';
|
|
2
|
+
import { resolveDb } from '../db/local-db.js';
|
|
3
|
+
import { loadUserConfigForDb } from './db-shared.js';
|
|
4
|
+
export const dbAudit = pikkuSessionlessFunc({
|
|
5
|
+
remote: true,
|
|
6
|
+
func: async ({ logger, config }) => {
|
|
7
|
+
const userConfig = await loadUserConfigForDb({ config, logger });
|
|
8
|
+
if (!userConfig)
|
|
9
|
+
return;
|
|
10
|
+
const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir);
|
|
11
|
+
if (!resolved) {
|
|
12
|
+
logger.error('pikku db audit: no database configured — set sqliteDb or postgresUrl in your createConfig.');
|
|
13
|
+
throw new Error('no database configured');
|
|
14
|
+
}
|
|
15
|
+
let manifest;
|
|
16
|
+
try {
|
|
17
|
+
const mod = await import(resolved.manifestFile);
|
|
18
|
+
manifest = mod.classificationManifest;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
logger.error(`pikku db audit: classification manifest not found at ${resolved.manifestFile}.\n` +
|
|
22
|
+
` Run \`pikku db migrate\` to generate it.`);
|
|
23
|
+
throw new Error('classification manifest not found');
|
|
24
|
+
}
|
|
25
|
+
let publicCount = 0;
|
|
26
|
+
let privateCount = 0;
|
|
27
|
+
let secretCount = 0;
|
|
28
|
+
const noStrategyColumns = [];
|
|
29
|
+
const secretColumns = [];
|
|
30
|
+
logger.info('Classification audit:');
|
|
31
|
+
for (const [table, cols] of Object.entries(manifest.tables)) {
|
|
32
|
+
logger.info(` ${table}:`);
|
|
33
|
+
for (const [col, info] of Object.entries(cols)) {
|
|
34
|
+
const { classification, anonymize_strategy } = info;
|
|
35
|
+
const strategyLabel = anonymize_strategy ?? '(null → will be nulled on clone)';
|
|
36
|
+
if (classification === 'public') {
|
|
37
|
+
publicCount++;
|
|
38
|
+
logger.info(` ${col.padEnd(30)} public`);
|
|
39
|
+
}
|
|
40
|
+
else if (classification === 'secret') {
|
|
41
|
+
secretCount++;
|
|
42
|
+
secretColumns.push(`${table}.${col}`);
|
|
43
|
+
if (!anonymize_strategy)
|
|
44
|
+
noStrategyColumns.push(`${table}.${col}`);
|
|
45
|
+
logger.info(` ${col.padEnd(30)} secret ${strategyLabel}`);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
privateCount++;
|
|
49
|
+
if (!anonymize_strategy)
|
|
50
|
+
noStrategyColumns.push(`${table}.${col}`);
|
|
51
|
+
logger.info(` ${col.padEnd(30)} private ${strategyLabel}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const total = publicCount + privateCount + secretCount;
|
|
56
|
+
logger.info('');
|
|
57
|
+
logger.info(`Summary: ${total} columns total — ` +
|
|
58
|
+
`${publicCount} public, ${privateCount} private, ${secretCount} secret`);
|
|
59
|
+
if (secretColumns.length > 0) {
|
|
60
|
+
logger.info(`Secret columns (extra-sensitive): ${secretColumns.join(', ')}`);
|
|
61
|
+
}
|
|
62
|
+
if (noStrategyColumns.length > 0) {
|
|
63
|
+
logger.warn(`${noStrategyColumns.length} private/secret column(s) have no anonymize strategy ` +
|
|
64
|
+
`and will be NULLed on clone: ${noStrategyColumns.join(', ')}`);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
});
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
import { pikkuSessionlessFunc } from '#pikku';
|
|
2
|
-
import {
|
|
2
|
+
import { resolveDb, migrateAndCodegen } from '../db/local-db.js';
|
|
3
3
|
import { loadUserConfigForDb } from './db-shared.js';
|
|
4
4
|
export const dbMigrate = pikkuSessionlessFunc({
|
|
5
5
|
remote: true,
|
|
6
6
|
func: async ({ logger, config }) => {
|
|
7
|
-
const userConfig = await loadUserConfigForDb({
|
|
8
|
-
config,
|
|
9
|
-
logger,
|
|
10
|
-
});
|
|
7
|
+
const userConfig = await loadUserConfigForDb({ config, logger });
|
|
11
8
|
if (!userConfig)
|
|
12
9
|
return;
|
|
13
|
-
const resolved =
|
|
10
|
+
const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir);
|
|
14
11
|
if (!resolved) {
|
|
15
|
-
logger.error('pikku db migrate:
|
|
16
|
-
throw new Error('
|
|
12
|
+
logger.error('pikku db migrate: no database configured — set sqliteDb or postgresUrl in your createConfig.');
|
|
13
|
+
throw new Error('no database configured');
|
|
17
14
|
}
|
|
18
15
|
const { migrate, codegen, zod } = await migrateAndCodegen(resolved);
|
|
19
16
|
if (migrate.applied.length === 0) {
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { pikkuSessionlessFunc } from '#pikku';
|
|
2
|
-
import {
|
|
2
|
+
import { resolveDb, reset, migrateAndCodegen, seed } from '../db/local-db.js';
|
|
3
3
|
import { loadUserConfigForDb } from './db-shared.js';
|
|
4
4
|
export const dbReset = pikkuSessionlessFunc({
|
|
5
5
|
remote: true,
|
|
6
6
|
func: async ({ logger, config }) => {
|
|
7
|
-
const userConfig = await loadUserConfigForDb({
|
|
8
|
-
config,
|
|
9
|
-
logger,
|
|
10
|
-
});
|
|
7
|
+
const userConfig = await loadUserConfigForDb({ config, logger });
|
|
11
8
|
if (!userConfig)
|
|
12
9
|
return;
|
|
13
|
-
const resolved =
|
|
10
|
+
const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir);
|
|
14
11
|
if (!resolved) {
|
|
15
|
-
logger.error('pikku db reset:
|
|
16
|
-
throw new Error('
|
|
12
|
+
logger.error('pikku db reset: no database configured — set sqliteDb in your createConfig.');
|
|
13
|
+
throw new Error('no database configured');
|
|
14
|
+
}
|
|
15
|
+
if (resolved.dialect !== 'sqlite') {
|
|
16
|
+
logger.error('pikku db reset: reset is only supported for SQLite databases.');
|
|
17
|
+
throw new Error('reset not supported for postgres');
|
|
17
18
|
}
|
|
18
19
|
reset(resolved, config.rootDir);
|
|
19
20
|
logger.info(`db reset: removed ${resolved.dbFile}`);
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { pikkuSessionlessFunc } from '#pikku';
|
|
2
|
-
import {
|
|
2
|
+
import { resolveDb, seed } from '../db/local-db.js';
|
|
3
3
|
import { loadUserConfigForDb } from './db-shared.js';
|
|
4
4
|
export const dbSeed = pikkuSessionlessFunc({
|
|
5
5
|
remote: true,
|
|
6
6
|
func: async ({ logger, config }) => {
|
|
7
|
-
const userConfig = await loadUserConfigForDb({
|
|
8
|
-
config,
|
|
9
|
-
logger,
|
|
10
|
-
});
|
|
7
|
+
const userConfig = await loadUserConfigForDb({ config, logger });
|
|
11
8
|
if (!userConfig)
|
|
12
9
|
return;
|
|
13
|
-
const resolved =
|
|
10
|
+
const resolved = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir);
|
|
14
11
|
if (!resolved) {
|
|
15
|
-
logger.error('pikku db seed:
|
|
16
|
-
throw new Error('
|
|
12
|
+
logger.error('pikku db seed: no database configured — set sqliteDb in your createConfig.');
|
|
13
|
+
throw new Error('no database configured');
|
|
14
|
+
}
|
|
15
|
+
if (resolved.dialect !== 'sqlite') {
|
|
16
|
+
logger.error('pikku db seed: seed is only supported for SQLite databases.');
|
|
17
|
+
throw new Error('seed not supported for postgres');
|
|
17
18
|
}
|
|
18
19
|
const result = await seed(resolved);
|
|
19
20
|
if (!result.applied) {
|
|
@@ -18,12 +18,22 @@ function findUserConfigFactoryFile(rootDir, srcDirectories) {
|
|
|
18
18
|
}
|
|
19
19
|
export async function loadUserConfigForDb(options) {
|
|
20
20
|
const { config, logger } = options;
|
|
21
|
-
const
|
|
22
|
-
|
|
21
|
+
const hasSqliteDbAssets = existsSync(join(config.rootDir, 'db', 'sqlite'));
|
|
22
|
+
const hasPostgresDbAssets = existsSync(join(config.rootDir, 'db', 'postgres'));
|
|
23
|
+
const hasConventionalDbAssets = hasSqliteDbAssets || hasPostgresDbAssets;
|
|
24
|
+
const getFallbackConfig = () => {
|
|
25
|
+
if (hasSqliteDbAssets)
|
|
26
|
+
return { sqliteDb: '.pikku-runtime/dev.db' };
|
|
27
|
+
if (hasPostgresDbAssets) {
|
|
28
|
+
logger.error('Postgres assets detected but postgresUrl is not configured in createConfig.');
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
};
|
|
23
33
|
const configFactoryFile = findUserConfigFactoryFile(config.rootDir, config.srcDirectories);
|
|
24
34
|
if (!configFactoryFile) {
|
|
25
35
|
if (hasConventionalDbAssets) {
|
|
26
|
-
return
|
|
36
|
+
return getFallbackConfig();
|
|
27
37
|
}
|
|
28
38
|
logger.error('createConfig must be defined in your project');
|
|
29
39
|
return null;
|
|
@@ -35,7 +45,7 @@ export async function loadUserConfigForDb(options) {
|
|
|
35
45
|
catch (error) {
|
|
36
46
|
if (hasConventionalDbAssets) {
|
|
37
47
|
logger.warn(`Falling back to default local db config because '${configFactoryFile}' could not be loaded: ${error.message}`);
|
|
38
|
-
return
|
|
48
|
+
return getFallbackConfig();
|
|
39
49
|
}
|
|
40
50
|
throw error;
|
|
41
51
|
}
|
|
@@ -43,7 +53,7 @@ export async function loadUserConfigForDb(options) {
|
|
|
43
53
|
if (typeof userCreateConfig !== 'function') {
|
|
44
54
|
if (hasConventionalDbAssets) {
|
|
45
55
|
logger.warn(`Falling back to default local db config because '${configFactoryFile}' does not export createConfig`);
|
|
46
|
-
return
|
|
56
|
+
return getFallbackConfig();
|
|
47
57
|
}
|
|
48
58
|
logger.error(`Expected 'createConfig' in '${configFactoryFile}' to be a function`);
|
|
49
59
|
return null;
|
|
@@ -14,7 +14,7 @@ import { pikkuWebsocketHandler } from '@pikku/ws';
|
|
|
14
14
|
import { PikkuNodeHTTPServer } from '@pikku/node-http-server';
|
|
15
15
|
import { WebSocketServer } from 'ws';
|
|
16
16
|
import { InMemorySchedulerService } from '@pikku/schedule';
|
|
17
|
-
import {
|
|
17
|
+
import { resolveDb, createKysely } from '../db/local-db.js';
|
|
18
18
|
import { loadUserBootstrap, loadUserModule } from './load-user-project.js';
|
|
19
19
|
export const dev = pikkuSessionlessFunc({
|
|
20
20
|
remote: true,
|
|
@@ -116,19 +116,25 @@ export const dev = pikkuSessionlessFunc({
|
|
|
116
116
|
const userCreateConfig = configModule[pikkuConfigFactory.variable];
|
|
117
117
|
const userCreateSingletonServices = servicesModule[singletonServicesFactory.variable];
|
|
118
118
|
const userConfig = await userCreateConfig();
|
|
119
|
-
const
|
|
119
|
+
const resolvedDb = resolveDb(userConfig, config.rootDir, config.outDir, config.runtimeDir);
|
|
120
|
+
const resolvedLocalDb = resolvedDb?.dialect === 'sqlite'
|
|
121
|
+
? resolvedDb
|
|
122
|
+
: userConfig.sqliteDb
|
|
123
|
+
? resolveDb({ sqliteDb: userConfig.sqliteDb }, config.rootDir, config.outDir, config.runtimeDir)
|
|
124
|
+
: undefined;
|
|
120
125
|
const kysely = resolvedLocalDb
|
|
121
126
|
? await createKysely(resolvedLocalDb)
|
|
122
127
|
: undefined;
|
|
123
128
|
const resolvedRuntimeDir = config.runtimeDir ?? join(config.rootDir, '.pikku-runtime');
|
|
124
|
-
const localContentConfig = userConfig.
|
|
125
|
-
?.content
|
|
129
|
+
const localContentConfig = userConfig.content
|
|
126
130
|
? {
|
|
127
|
-
localFileUploadPath:
|
|
128
|
-
|
|
129
|
-
|
|
131
|
+
localFileUploadPath: userConfig.content.contentPath
|
|
132
|
+
? resolve(config.rootDir, userConfig.content.contentPath)
|
|
133
|
+
: join(resolvedRuntimeDir, 'content'),
|
|
134
|
+
uploadUrlPrefix: userConfig.content.uploadUrlPrefix ?? '/upload',
|
|
135
|
+
assetUrlPrefix: userConfig.content.assetUrlPrefix ?? '/assets',
|
|
130
136
|
server: `http://${hostname}:${resolvedPort}`,
|
|
131
|
-
|
|
137
|
+
sizeLimit: userConfig.content.sizeLimit,
|
|
132
138
|
}
|
|
133
139
|
: undefined;
|
|
134
140
|
const localContent = localContentConfig
|
|
@@ -219,7 +219,7 @@ export const createSingletonServices = pikkuAddonServices(async (
|
|
|
219
219
|
config,
|
|
220
220
|
{ secrets, variables }
|
|
221
221
|
) => {
|
|
222
|
-
const creds = await secrets.
|
|
222
|
+
const creds = await secrets.getSecret<${pascalName}Secrets>('${screamingName}_CREDENTIALS')
|
|
223
223
|
const ${camelName} = new ${pascalName}Service(creds, variables)
|
|
224
224
|
|
|
225
225
|
return { ${camelName} }
|
|
@@ -717,7 +717,7 @@ import { createSingletonServices } from './services.js'
|
|
|
717
717
|
test('${name} addon', async () => {
|
|
718
718
|
const secrets = new LocalSecretService()
|
|
719
719
|
// Set up secrets for the service
|
|
720
|
-
// await secrets.
|
|
720
|
+
// await secrets.setSecret('${screamingName}_CREDENTIALS', { ... })
|
|
721
721
|
|
|
722
722
|
const singletonServices = await createSingletonServices({}, { secrets })
|
|
723
723
|
const rpc = rpcService.getContextRPCService(singletonServices as any, {})
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
export declare const pikkuTestsCoverage: import("#pikku").PikkuFunctionConfig<{
|
|
2
2
|
noRun?: boolean;
|
|
3
|
+
aiOut?: string;
|
|
3
4
|
}, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<{
|
|
4
5
|
noRun?: boolean;
|
|
6
|
+
aiOut?: string;
|
|
5
7
|
}, void, "rpc" | "session", import("#pikku").Services> | import("#pikku").PikkuFunction<{
|
|
6
8
|
noRun?: boolean;
|
|
9
|
+
aiOut?: string;
|
|
7
10
|
}, void, "rpc" | "session", import("#pikku").Services>, undefined, undefined>;
|
|
@@ -92,6 +92,7 @@ function lineCoverage(fileCov, span) {
|
|
|
92
92
|
export const pikkuTestsCoverage = pikkuSessionlessFunc({
|
|
93
93
|
func: async ({ logger, config }, input) => {
|
|
94
94
|
const noRun = input?.noRun ?? false;
|
|
95
|
+
const aiOut = input?.aiOut ?? null;
|
|
95
96
|
const packageMappings = config.packageMappings ?? {};
|
|
96
97
|
const srcDirs = config.srcDirectories ?? [];
|
|
97
98
|
const functionsRelDir = Object.keys(packageMappings).find((key) => srcDirs.some((src) => src === key || src.startsWith(key + '/'))) ?? Object.keys(packageMappings)[0];
|
|
@@ -227,5 +228,38 @@ export const pikkuTestsCoverage = pikkuSessionlessFunc({
|
|
|
227
228
|
console.log(` ${summary.covered} covered · ${summary.partial} partial · ${summary.uncovered} uncovered · ${summary.unknown} unknown (overall ${(overallRatio * 100).toFixed(1)}%)`);
|
|
228
229
|
if (uncovered.length)
|
|
229
230
|
console.log(` uncovered: ${uncovered.map((f) => f.name).join(', ')}`);
|
|
231
|
+
if (aiOut !== null) {
|
|
232
|
+
const generatedAt = new Date().toISOString();
|
|
233
|
+
const pct = Math.round(overallRatio * 100);
|
|
234
|
+
const needWork = functions.filter((f) => f.status !== 'covered');
|
|
235
|
+
const lines = [
|
|
236
|
+
`Coverage report — generated ${generatedAt}.`,
|
|
237
|
+
`Overall: ${pct}% (${summary.covered}/${summary.total} functions fully covered)`,
|
|
238
|
+
'',
|
|
239
|
+
needWork.length === 0
|
|
240
|
+
? 'All functions are fully covered — nothing to do!'
|
|
241
|
+
: `Functions needing coverage (${needWork.length}):`,
|
|
242
|
+
...needWork.flatMap((fn) => {
|
|
243
|
+
const ratio = Math.round(fn.ratio * 100);
|
|
244
|
+
const missed = fn.missedLines.length > 0 ? fn.missedLines.join(', ') : 'none';
|
|
245
|
+
return [
|
|
246
|
+
`- ${fn.name} [${fn.status}, ${ratio}% covered, ${fn.coveredLines}/${fn.totalLines} lines]`,
|
|
247
|
+
` file: ${fn.sourceFile}`,
|
|
248
|
+
` missed lines: ${missed}`,
|
|
249
|
+
];
|
|
250
|
+
}),
|
|
251
|
+
];
|
|
252
|
+
if (needWork.length > 0) {
|
|
253
|
+
lines.push('', 'Write @pikku/cucumber Gherkin scenarios (no custom steps) in tests/tests/features/ to cover the missed lines above.', 'Use pikku meta to get versioned RPC names and function schemas before writing.', 'Run pikku tests coverage after writing to verify coverage improved.');
|
|
254
|
+
}
|
|
255
|
+
const prompt = lines.join('\n') + '\n';
|
|
256
|
+
if (aiOut === '-') {
|
|
257
|
+
process.stdout.write(prompt);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
writeFileSync(aiOut, prompt, 'utf-8');
|
|
261
|
+
console.log(`AI prompt → ${relative(config.rootDir, aiOut)}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
230
264
|
},
|
|
231
265
|
});
|