@pikku/cli 0.12.92 → 0.12.96
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-DDpIMCpy.js → index-CeQodYfg.js} +151 -149
- package/console-app/assets/{index-D0HG8q0B.css → index-CyYHTGWZ.css} +1 -1
- package/console-app/index.html +2 -2
- 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.d.ts +13 -15
- package/dist/.pikku/cli/pikku-cli-channel.js +72 -3
- package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +14 -4
- package/dist/.pikku/cli/pikku-cli-client.gen.js +20 -10
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.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-meta.gen.json +156 -2
- 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 +55 -20
- package/dist/.pikku/function/pikku-function-types.gen.js +27 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.json +176 -13
- package/dist/.pikku/function/pikku-functions.gen.js +11 -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/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-scenarios.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap-scenarios.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 +9 -0
- package/dist/.pikku/scenarios/pikku-scenario-functions-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-functions.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/schemas/register.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/schemas/register.gen.js +1 -1
- 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 +21 -3
- package/dist/.pikku/schemas/schemas/KnowledgeIndexInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/KnowledgeIndexOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/KnowledgeValidateInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/KnowledgeValidateOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PersonaRunInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PersonaSyncInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/PikkuPersonasInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuRolesInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/RolesAuditInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/RolesPruneInput.schema.json +1 -0
- package/dist/.pikku/scopes/pikku-personas-meta.gen.json +1 -0
- package/dist/.pikku/scopes/pikku-personas.gen.d.ts +36 -0
- package/dist/.pikku/scopes/pikku-personas.gen.js +17 -0
- package/dist/.pikku/scopes/pikku-roles-meta.gen.json +1 -0
- package/dist/.pikku/scopes/pikku-roles.gen.d.ts +30 -0
- package/dist/.pikku/scopes/pikku-roles.gen.js +18 -0
- package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +4 -2
- package/dist/.pikku/scopes/pikku-scope-types.gen.js +3 -2
- package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +2 -2
- package/dist/.pikku/secrets/pikku-secret-types.gen.js +2 -2
- 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 +2 -2
- package/dist/.pikku/variables/pikku-variable-types.gen.js +2 -2
- 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 +27 -3
- package/dist/.pikku/workflow/pikku-personas.gen.d.ts +15 -0
- package/dist/.pikku/workflow/pikku-personas.gen.js +17 -0
- package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +96 -19
- package/dist/.pikku/workflow/pikku-workflow-types.gen.js +22 -2
- 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/bin/pikku.js +0 -0
- package/dist/src/cli.wiring.js +124 -2
- package/dist/src/deploy/analyzer/analyzer.js +14 -0
- package/dist/src/deploy/analyzer/manifest.d.ts +11 -0
- package/dist/src/fabric/functions/validate.function.js +20 -11
- package/dist/src/functions/commands/bootstrap.js +3 -0
- package/dist/src/functions/commands/dev-ai-runner.d.ts +16 -4
- package/dist/src/functions/commands/dev-ai-runner.js +63 -29
- package/dist/src/functions/commands/dev.js +9 -4
- package/dist/src/functions/commands/enable.js +15 -19
- package/dist/src/functions/commands/{scenario-environment.d.ts → environment.d.ts} +9 -6
- package/dist/src/functions/commands/{scenario-environment.js → environment.js} +5 -4
- package/dist/src/functions/commands/knowledge-index.d.ts +30 -0
- package/dist/src/functions/commands/knowledge-index.js +11 -0
- package/dist/src/functions/commands/knowledge-validate.d.ts +33 -0
- package/dist/src/functions/commands/knowledge-validate.js +11 -0
- package/dist/src/functions/commands/new-addon.d.ts +18 -0
- package/dist/src/functions/commands/new-addon.js +52 -36
- package/dist/src/functions/commands/persona-sync.d.ts +33 -0
- package/dist/src/functions/commands/persona-sync.js +151 -0
- package/dist/src/functions/commands/persona.d.ts +58 -0
- package/dist/src/functions/commands/persona.js +217 -0
- package/dist/src/functions/commands/roles-audit.d.ts +1 -0
- package/dist/src/functions/commands/roles-audit.js +37 -0
- package/dist/src/functions/commands/roles-prune.d.ts +16 -0
- package/dist/src/functions/commands/roles-prune.js +52 -0
- package/dist/src/functions/commands/roles-shared.d.ts +40 -0
- package/dist/src/functions/commands/roles-shared.js +77 -0
- package/dist/src/functions/commands/scenario-browser.d.ts +3 -3
- package/dist/src/functions/commands/scenario-browser.js +1 -1
- package/dist/src/functions/commands/scenario-ladder.d.ts +44 -2
- package/dist/src/functions/commands/scenario-ladder.js +51 -2
- package/dist/src/functions/commands/scenario.d.ts +7 -0
- package/dist/src/functions/commands/scenario.js +79 -17
- package/dist/src/functions/commands/scopes-shared.d.ts +8 -0
- package/dist/src/functions/commands/scopes-shared.js +1 -1
- package/dist/src/functions/commands/serve.js +7 -3
- package/dist/src/functions/commands/virtual-user-formatter.d.ts +30 -0
- package/dist/src/functions/commands/virtual-user-formatter.js +65 -0
- package/dist/src/functions/db/local-db.js +38 -1
- package/dist/src/functions/knowledge/render.d.ts +3 -0
- package/dist/src/functions/knowledge/render.js +66 -0
- package/dist/src/functions/knowledge/schemas.d.ts +51 -0
- package/dist/src/functions/knowledge/schemas.js +25 -0
- package/dist/src/functions/validate/workspace-validate.js +1 -1
- package/dist/src/functions/wirings/ai-agent/pikku-command-public-agent.js +2 -1
- package/dist/src/functions/wirings/ai-agent/serialize-public-agent.js +1 -0
- package/dist/src/functions/wirings/auth/serialize-auth-gen.d.ts +2 -2
- package/dist/src/functions/wirings/auth/serialize-auth-gen.js +8 -8
- package/dist/src/functions/wirings/cli/serialize-channel-cli-client.d.ts +7 -3
- package/dist/src/functions/wirings/cli/serialize-channel-cli-client.js +32 -18
- package/dist/src/functions/wirings/cli/serialize-channel-cli.js +63 -6
- package/dist/src/functions/wirings/console/serialize-console-functions.js +4 -7
- package/dist/src/functions/wirings/credentials/serialize-credentials-types.js +8 -1
- package/dist/src/functions/wirings/functions/serialize-function-types.js +88 -28
- package/dist/src/functions/wirings/middleware/serialize-middleware-imports.js +25 -9
- package/dist/src/functions/wirings/package/serialize-package-types.js +5 -3
- package/dist/src/functions/wirings/personas/pikku-command-personas.d.ts +7 -0
- package/dist/src/functions/wirings/personas/pikku-command-personas.js +43 -0
- package/dist/src/functions/wirings/personas/serialize-personas-types.d.ts +18 -0
- package/dist/src/functions/wirings/personas/serialize-personas-types.js +76 -0
- package/dist/src/functions/wirings/realtime/pikku-command-events-scaffold.js +2 -1
- package/dist/src/functions/wirings/roles/pikku-command-roles.d.ts +7 -0
- package/dist/src/functions/wirings/roles/pikku-command-roles.js +33 -0
- package/dist/src/functions/wirings/roles/serialize-roles-types.d.ts +14 -0
- package/dist/src/functions/wirings/roles/serialize-roles-types.js +55 -0
- package/dist/src/functions/wirings/rpc/pikku-command-public-rpc.js +2 -1
- package/dist/src/functions/wirings/scenarios/register-scenario-instrumentation.d.ts +3 -3
- package/dist/src/functions/wirings/scenarios/register-scenario-instrumentation.js +3 -3
- package/dist/src/functions/wirings/scopes/serialize-scopes-types.d.ts +1 -1
- package/dist/src/functions/wirings/scopes/serialize-scopes-types.js +1 -1
- package/dist/src/functions/wirings/secrets/serialize-secrets-types.js +10 -3
- package/dist/src/functions/wirings/user-admin/pikku-command-user-admin-functions.js +2 -1
- package/dist/src/functions/wirings/user-admin/serialize-user-admin-functions.js +2 -2
- package/dist/src/functions/wirings/variables/serialize-variables-types.js +8 -1
- package/dist/src/functions/wirings/workflow/pikku-command-workflow-routes.js +2 -1
- package/dist/src/functions/wirings/workflow/pikku-command-workflow.js +13 -13
- package/dist/src/functions/wirings/workflow/serialize-personas.d.ts +10 -0
- package/dist/src/functions/wirings/workflow/serialize-personas.js +46 -0
- package/dist/src/functions/wirings/workflow/serialize-scenario-step-map.js +11 -2
- package/dist/src/functions/wirings/workflow/serialize-workflow-types.js +165 -29
- package/dist/src/functions/workflows/all.workflow.js +7 -1
- package/dist/src/server/content-signing-jwt.d.ts +13 -0
- package/dist/src/server/content-signing-jwt.js +51 -0
- package/dist/src/server/dev-server-runner.interface.d.ts +10 -2
- package/dist/src/server/node-server-runner.d.ts +2 -2
- package/dist/src/server/node-server-runner.js +2 -1
- package/dist/src/services.d.ts +3 -1
- package/dist/src/services.js +2 -1
- package/dist/src/utils/pikku-cli-config.js +45 -2
- package/dist/src/utils/resolve-personas.d.ts +32 -0
- package/dist/src/utils/resolve-personas.js +46 -0
- package/dist/src/utils/resolve-scaffold-feature.d.ts +19 -0
- package/dist/src/utils/resolve-scaffold-feature.js +49 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -13
- package/dist/.pikku/schemas/schemas/ScenarioRunInput.schema.json +0 -1
- package/dist/.pikku/workflow/pikku-scenario-actors.gen.d.ts +0 -19
- package/dist/.pikku/workflow/pikku-scenario-actors.gen.js +0 -17
- package/dist/src/functions/wirings/workflow/serialize-scenario-actors.d.ts +0 -2
- package/dist/src/functions/wirings/workflow/serialize-scenario-actors.js +0 -40
- package/dist/src/utils/resolve-scenario-actors.d.ts +0 -23
- package/dist/src/utils/resolve-scenario-actors.js +0 -74
|
@@ -5,7 +5,11 @@ import type { Config } from '../../../../types/application-types.js';
|
|
|
5
5
|
*/
|
|
6
6
|
export declare function collectRendererNames(programMeta: CLIProgramMeta): Set<string>;
|
|
7
7
|
/**
|
|
8
|
-
* Serializes a CLI-over-Channel client bootstrap file
|
|
9
|
-
*
|
|
8
|
+
* Serializes a CLI-over-Channel client bootstrap file.
|
|
9
|
+
*
|
|
10
|
+
* The client deliberately does NOT import the CLI bootstrap: loading the
|
|
11
|
+
* command tree here would bind the client's version to the server's, which is
|
|
12
|
+
* the coupling running commands remotely exists to remove. Renderers are the
|
|
13
|
+
* only local artefact, and they are optional.
|
|
10
14
|
*/
|
|
11
|
-
export declare function serializeChannelCLIClient(programName: string, programMeta: CLIProgramMeta, clientFile: string, config: Config,
|
|
15
|
+
export declare function serializeChannelCLIClient(programName: string, programMeta: CLIProgramMeta, clientFile: string, config: Config, _cliBootstrapPath: string, channelRoute?: string, renderersMeta?: Record<string, any>): string;
|
|
@@ -65,14 +65,16 @@ function buildRenderersMap(programMeta, renderersMeta) {
|
|
|
65
65
|
return `{\n${entries.join(',\n')}\n }`;
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
|
-
* Serializes a CLI-over-Channel client bootstrap file
|
|
69
|
-
*
|
|
68
|
+
* Serializes a CLI-over-Channel client bootstrap file.
|
|
69
|
+
*
|
|
70
|
+
* The client deliberately does NOT import the CLI bootstrap: loading the
|
|
71
|
+
* command tree here would bind the client's version to the server's, which is
|
|
72
|
+
* the coupling running commands remotely exists to remove. Renderers are the
|
|
73
|
+
* only local artefact, and they are optional.
|
|
70
74
|
*/
|
|
71
|
-
export function serializeChannelCLIClient(programName, programMeta, clientFile, config,
|
|
75
|
+
export function serializeChannelCLIClient(programName, programMeta, clientFile, config, _cliBootstrapPath, channelRoute, renderersMeta) {
|
|
72
76
|
const capitalizedName = programName.charAt(0).toUpperCase() + programName.slice(1).replace(/-/g, '');
|
|
73
77
|
const finalChannelRoute = channelRoute || `/cli/${programName}`;
|
|
74
|
-
// Get relative import path to CLI bootstrap (for metadata)
|
|
75
|
-
const bootstrapImportPath = getFileImportRelativePath(clientFile, cliBootstrapPath, config.packageMappings);
|
|
76
78
|
// Collect all unique renderer names from CLI metadata (populated by inspector)
|
|
77
79
|
const rendererNames = collectRendererNames(programMeta);
|
|
78
80
|
// Generate renderer imports from their source files
|
|
@@ -108,29 +110,40 @@ export function serializeChannelCLIClient(programName, programMeta, clientFile,
|
|
|
108
110
|
? `,\n defaultRenderer: ${defaultRendererBinding}`
|
|
109
111
|
: '';
|
|
110
112
|
return `
|
|
111
|
-
import {
|
|
113
|
+
import { executeRawCLIViaChannel } from '@pikku/core/cli/channel'
|
|
114
|
+
import type { Capabilities } from '@pikku/core/channel'
|
|
112
115
|
import { CorePikkuWebsocket } from '@pikku/websocket'
|
|
113
|
-
import '${bootstrapImportPath}'
|
|
114
116
|
${rendererImports}
|
|
115
117
|
/**
|
|
116
118
|
* ${capitalizedName} CLI Client (via WebSocket Channel)
|
|
117
|
-
*
|
|
119
|
+
*
|
|
120
|
+
* Forwards argv to the server untouched — the command tree is never parsed
|
|
121
|
+
* here, so this client stays valid as the server's commands change. Renderers
|
|
122
|
+
* are matched by the command id the server reports; anything it doesn't
|
|
123
|
+
* recognise falls back to JSON.
|
|
124
|
+
*
|
|
125
|
+
* \`capabilities\` are the functions this client agrees to run on the server's
|
|
126
|
+
* behalf (a git sha, a local path). It is an allowlist, not a convenience —
|
|
127
|
+
* nothing outside it is reachable from the server. A bare function is
|
|
128
|
+
* unclassified and so needs approval before every call; write
|
|
129
|
+
* \`{ execute, needsApproval: false }\` for one that may run unattended.
|
|
118
130
|
*/
|
|
119
131
|
export async function ${capitalizedName}CLIClient(
|
|
120
132
|
ws: WebSocket,
|
|
121
|
-
args?: string[]
|
|
122
|
-
|
|
133
|
+
args?: string[],
|
|
134
|
+
capabilities: Capabilities = {}
|
|
135
|
+
): Promise<number> {
|
|
123
136
|
// Create Pikku WebSocket wrapper
|
|
124
137
|
const pikkuWS = new CorePikkuWebsocket(ws)
|
|
125
138
|
|
|
126
139
|
// Register renderers for CLI commands
|
|
127
140
|
const renderers = ${renderersMap}
|
|
128
141
|
|
|
129
|
-
|
|
130
|
-
programName: '${programName}',
|
|
142
|
+
return executeRawCLIViaChannel({
|
|
131
143
|
pikkuWS,
|
|
132
144
|
args,
|
|
133
|
-
renderers
|
|
145
|
+
renderers,
|
|
146
|
+
capabilities${defaultRendererCode},
|
|
134
147
|
})
|
|
135
148
|
}
|
|
136
149
|
|
|
@@ -183,11 +196,12 @@ if (import.meta.url === \`file://\${process.argv[1]}\`) {
|
|
|
183
196
|
ws = new WebSocket(url)
|
|
184
197
|
}
|
|
185
198
|
|
|
186
|
-
${capitalizedName}CLIClient(ws, process.argv.slice(2))
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
199
|
+
${capitalizedName}CLIClient(ws, process.argv.slice(2))
|
|
200
|
+
.then((exitCode) => process.exit(exitCode))
|
|
201
|
+
.catch(error => {
|
|
202
|
+
console.error('Fatal channel CLI error:', error)
|
|
203
|
+
process.exit(1)
|
|
204
|
+
})
|
|
191
205
|
}
|
|
192
206
|
`;
|
|
193
207
|
}
|
|
@@ -60,7 +60,7 @@ export function serializeChannelCLI(programName, programMeta, channelFile, funct
|
|
|
60
60
|
import { wireChannel } from '${channelTypesPath}'
|
|
61
61
|
import { pikkuMiddleware${hasAddonFuncs ? ', ref' : ''}, pikkuSessionlessFunc } from '${functionTypesPath}'
|
|
62
62
|
import { generateCommandHelp } from '@pikku/core/cli'
|
|
63
|
-
import { handleRawCLI } from '@pikku/core/cli/channel'
|
|
63
|
+
import { handleRawCLI, type RawCLIFrame } from '@pikku/core/cli/channel'
|
|
64
64
|
import { pikkuState } from '@pikku/core/internal'
|
|
65
65
|
${imports}
|
|
66
66
|
|
|
@@ -97,22 +97,79 @@ export const cliHelp = pikkuSessionlessFunc<{ args?: string[] }, { help: string
|
|
|
97
97
|
},
|
|
98
98
|
})
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
/**
|
|
101
|
+
* Raw entry point: the client forwards argv untouched and this side owns
|
|
102
|
+
* parsing, so a client binary never carries the command tree and its version
|
|
103
|
+
* is free to drift from the server's.
|
|
104
|
+
*
|
|
105
|
+
* Progressive output is streamed on the same channel rather than returned,
|
|
106
|
+
* and the terminating control frame carries the exit code so the client
|
|
107
|
+
* process can exit non-zero.
|
|
108
|
+
*/
|
|
109
|
+
export const cliRaw = pikkuSessionlessFunc<{ args: string[] }, RawCLIFrame>({
|
|
101
110
|
auth: false,
|
|
102
|
-
func: async (services, data: { args: string[] }) => {
|
|
103
|
-
|
|
111
|
+
func: async (services, data: { args: string[] }, { channel, session }) => {
|
|
112
|
+
const { help, result, error, exitCode, commandId } = await handleRawCLI({
|
|
104
113
|
programName: '${programName}',
|
|
105
114
|
args: data.args,
|
|
106
115
|
singletonServices: services as any,
|
|
116
|
+
createWireServices: pikkuState(null, 'package', 'factories')?.createWireServices,
|
|
117
|
+
// The connection authenticated during its upgrade — commands run as it.
|
|
118
|
+
session,
|
|
119
|
+
// The socket the command arrived on, so \`channel.remote(...)\` inside a
|
|
120
|
+
// command reaches the client that invoked it.
|
|
121
|
+
transport: channel,
|
|
122
|
+
onOutput: (output, commandId) =>
|
|
123
|
+
channel?.send({ action: 'cli-output', commandId, data: output }),
|
|
107
124
|
})
|
|
125
|
+
|
|
126
|
+
// A failed parse carries both: the error says what was wrong, the help
|
|
127
|
+
// says what was available. The error goes last so it is the line still on
|
|
128
|
+
// screen after the help text has scrolled past.
|
|
129
|
+
if (help !== undefined) {
|
|
130
|
+
await channel?.send({ action: 'cli-help', help })
|
|
131
|
+
if (error !== undefined) {
|
|
132
|
+
await channel?.send({ action: 'cli-error', error })
|
|
133
|
+
}
|
|
134
|
+
} else if (error !== undefined) {
|
|
135
|
+
await channel?.send({ action: 'cli-error', error })
|
|
136
|
+
} else if (result !== undefined) {
|
|
137
|
+
await channel?.send({ action: 'cli-result', commandId, result })
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Returned rather than sent so the runtime tags it with the routing key,
|
|
141
|
+
// and so the terminal frame cannot be emitted before the ones above it.
|
|
142
|
+
return { action: 'cli-control', event: 'complete', exitCode }
|
|
108
143
|
},
|
|
109
144
|
})
|
|
110
145
|
|
|
146
|
+
${programMeta.auth === true
|
|
147
|
+
? `/**
|
|
148
|
+
* Refuses a connection that arrives without a session.
|
|
149
|
+
*
|
|
150
|
+
* A CLI authenticates once, when it connects — there is no later message that
|
|
151
|
+
* would establish a session, so a connection that starts anonymous can never
|
|
152
|
+
* run anything. Saying so immediately and hanging up gives the caller a
|
|
153
|
+
* non-zero exit instead of a socket that silently refuses every command.
|
|
154
|
+
*/
|
|
155
|
+
export const cliRequireSession = pikkuSessionlessFunc<void, RawCLIFrame | void>({
|
|
156
|
+
auth: false,
|
|
157
|
+
func: async (_services, _data, { channel, session }) => {
|
|
158
|
+
if (session) {
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
await channel?.send({ action: 'cli-error', error: 'Authentication required' })
|
|
162
|
+
await channel?.send({ action: 'cli-control', event: 'complete', exitCode: 1 })
|
|
163
|
+
await channel?.close()
|
|
164
|
+
},
|
|
165
|
+
})
|
|
166
|
+
`
|
|
167
|
+
: ''}
|
|
111
168
|
wireChannel({
|
|
112
169
|
name: '${finalChannelName}',
|
|
113
170
|
route: '${finalChannelRoute}',
|
|
114
|
-
auth:
|
|
115
|
-
onMessageWiring: {
|
|
171
|
+
auth: ${programMeta.auth === true},
|
|
172
|
+
${programMeta.auth === true ? ' onConnect: cliRequireSession,\n' : ''} onMessageWiring: {
|
|
116
173
|
command: {
|
|
117
174
|
'__help': {
|
|
118
175
|
func: cliHelp,
|
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
} from './console.schemas.gen.js'
|
|
41
41
|
|
|
42
42
|
export const pikkuConsoleSetSecret = pikkuFunc({
|
|
43
|
+
secretBroker: true,
|
|
43
44
|
tags: ['pikku'],
|
|
44
45
|
description: 'Set the value of a secret',
|
|
45
46
|
expose: true,
|
|
@@ -89,6 +90,7 @@ export const pikkuConsoleSetVariable = pikkuFunc({
|
|
|
89
90
|
})
|
|
90
91
|
|
|
91
92
|
export const pikkuConsoleHasSecret = pikkuFunc({
|
|
93
|
+
secretBroker: true,
|
|
92
94
|
tags: ['pikku'],
|
|
93
95
|
description: 'Check if a secret exists without reading its value',
|
|
94
96
|
expose: true,
|
|
@@ -101,6 +103,7 @@ export const pikkuConsoleHasSecret = pikkuFunc({
|
|
|
101
103
|
})
|
|
102
104
|
|
|
103
105
|
export const pikkuConsoleGetSecret = pikkuFunc({
|
|
106
|
+
secretBroker: true,
|
|
104
107
|
tags: ['pikku'],
|
|
105
108
|
description: 'Get the current value of a secret',
|
|
106
109
|
expose: true,
|
|
@@ -129,13 +132,7 @@ export const consoleRoutes = defineHTTPRoutes({
|
|
|
129
132
|
},
|
|
130
133
|
})
|
|
131
134
|
|
|
132
|
-
|
|
133
|
-
// gates the whole privileged surface (credential read/write, source editing,
|
|
134
|
-
// package install) with a single package-scoped global permission —
|
|
135
|
-
// addGlobalPermission([isAdmin], '@pikku/addon-console') — which is resolved in
|
|
136
|
-
// the addon's package namespace, so it applies to every one of its functions at
|
|
137
|
-
// once. Apps that don't register one are unaffected (no globals => allow).
|
|
138
|
-
wireAddon({ name: 'console', package: '@pikku/addon-console' })
|
|
135
|
+
wireAddon({ name: 'console', package: '@pikku/addon-console', scopes: ['admin'] })
|
|
139
136
|
wireHTTPRoutes({ basePath: '${globalHTTPPrefix}', routes: { console: consoleRoutes } })
|
|
140
137
|
`;
|
|
141
138
|
return { schemas, functions };
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { validateAndBuildCredentialDefinitionsMeta } from '@pikku/core/credential';
|
|
2
2
|
import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
|
|
3
|
+
/**
|
|
4
|
+
* A display name is the human-facing label a developer wrote, so an apostrophe
|
|
5
|
+
* in it is ordinary. `JSON.stringify` emits a valid, escaped TypeScript string
|
|
6
|
+
* literal; interpolating the raw text into a quoted one terminates the string
|
|
7
|
+
* and the generated file stops parsing.
|
|
8
|
+
*/
|
|
9
|
+
const literal = (value) => JSON.stringify(value);
|
|
3
10
|
export const serializeCredentialsTypes = ({ definitions, schemaLookup, credentialsFile, packageMappings, }) => {
|
|
4
11
|
const credentials = validateAndBuildCredentialDefinitionsMeta(definitions, schemaLookup);
|
|
5
12
|
const credentialEntries = Object.entries(credentials);
|
|
@@ -22,7 +29,7 @@ export const serializeCredentialsTypes = ({ definitions, schemaLookup, credentia
|
|
|
22
29
|
}
|
|
23
30
|
const metaParts = [
|
|
24
31
|
`name: '${name}'`,
|
|
25
|
-
`displayName:
|
|
32
|
+
`displayName: ${literal(meta.displayName)}`,
|
|
26
33
|
`type: '${meta.type}'`,
|
|
27
34
|
];
|
|
28
35
|
if (meta.oauth2) {
|
|
@@ -7,7 +7,7 @@ export const serializeFunctionTypes = (userSessionTypeImport, userSessionTypeNam
|
|
|
7
7
|
? nodeCategories.map((c) => `'${c}'`).join(' | ')
|
|
8
8
|
: 'string';
|
|
9
9
|
const workflowImport = workflowTypesImport ||
|
|
10
|
-
`import type { TypedWorkflow, TypedScenario,
|
|
10
|
+
`import type { TypedWorkflow, TypedScenario, TypedPersonas } from '../workflow/pikku-workflow-types.gen.js'`;
|
|
11
11
|
// Falls back to `string` when a project has no scopes codegen, so that
|
|
12
12
|
// `scopes` stays usable rather than resolving to an unbound type name.
|
|
13
13
|
const scopesImport = scopesTypeImport || `type ScopeId = string`;
|
|
@@ -15,7 +15,7 @@ export const serializeFunctionTypes = (userSessionTypeImport, userSessionTypeNam
|
|
|
15
15
|
* Core function, middleware, and permission types for all wirings
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import type { CorePikkuMiddleware, CorePermissionGroup, ListInput, ListOutput, PikkuWire, PickRequired } from '@pikku/core'
|
|
18
|
+
import type { CorePikkuMiddleware, CorePermissionGroup, ListInput, ListOutput, PikkuWire, PickRequired, SecretlessServices, SecretService } from '@pikku/core'
|
|
19
19
|
import type { CorePikkuFunctionConfig, CorePikkuAuth, CorePikkuAuthConfig, CorePikkuPermission } from '@pikku/core/function'
|
|
20
20
|
import { pikkuAuth as pikkuAuthCore } from '@pikku/core/function'
|
|
21
21
|
import {
|
|
@@ -51,7 +51,20 @@ ${configTypeImport.includes('Config type not found') ? 'export type Config = any
|
|
|
51
51
|
* why an \`if (!service)\` guard inside a function body is always dead code.
|
|
52
52
|
*/
|
|
53
53
|
export type WiredSingletonServices = RequiredSingletonServices & SingletonServices
|
|
54
|
-
export type WiredServices = RequiredSingletonServices & Services
|
|
54
|
+
export type WiredServices = SecretlessServices<RequiredSingletonServices & Services>
|
|
55
|
+
|
|
56
|
+
/** \`WiredSingletonServices\` without \`secrets\`, for auth gates. */
|
|
57
|
+
export type WiredAuthServices = SecretlessServices<WiredSingletonServices>
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* \`WiredServices\` with \`secrets\` restored, for the console's secret-admin
|
|
61
|
+
* functions. Reached by declaring \`secretBroker: true\` on a \`pikkuFunc\` config.
|
|
62
|
+
*
|
|
63
|
+
* Declaring it does not grant the service. The runner hands out the real
|
|
64
|
+
* \`SecretService\` only to the functions the inspector marks as secret brokers;
|
|
65
|
+
* every other function still receives the throwing accessor.
|
|
66
|
+
*/
|
|
67
|
+
export type WiredSecretBrokerServices = WiredServices & { secrets: SecretService }
|
|
55
68
|
|
|
56
69
|
/**
|
|
57
70
|
* Inline node configuration for function definitions.
|
|
@@ -70,7 +83,7 @@ export type NodeConfig = {
|
|
|
70
83
|
* @template In - The input type that the permission check will receive
|
|
71
84
|
* @template RequiredServices - The services required for this permission check
|
|
72
85
|
*/
|
|
73
|
-
export type PikkuPermission<In = unknown, RequiredServices extends Services = WiredServices> = CorePikkuPermission<In, RequiredServices, PikkuWire<In, never, false, Session>>
|
|
86
|
+
export type PikkuPermission<In = unknown, RequiredServices extends SecretlessServices<Services> = WiredServices> = CorePikkuPermission<In, RequiredServices, PikkuWire<In, never, false, Session>>
|
|
74
87
|
|
|
75
88
|
/**
|
|
76
89
|
* Type-safe middleware definition that can access your application's services and session.
|
|
@@ -83,7 +96,7 @@ export type PikkuMiddleware<RequiredServices extends SingletonServices = WiredSi
|
|
|
83
96
|
/**
|
|
84
97
|
* Configuration object for creating a permission with metadata
|
|
85
98
|
*/
|
|
86
|
-
export type PikkuPermissionConfig<In = unknown, RequiredServices extends Services = WiredServices> = {
|
|
99
|
+
export type PikkuPermissionConfig<In = unknown, RequiredServices extends SecretlessServices<Services> = WiredServices> = {
|
|
87
100
|
/** The permission function */
|
|
88
101
|
func: PikkuPermission<In, RequiredServices>
|
|
89
102
|
/** Optional human-readable name for the permission */
|
|
@@ -128,12 +141,12 @@ export const pikkuPermission = <In>(
|
|
|
128
141
|
*
|
|
129
142
|
* @template RequiredServices - The services required for this auth check
|
|
130
143
|
*/
|
|
131
|
-
export type PikkuAuth<RequiredServices extends SingletonServices =
|
|
144
|
+
export type PikkuAuth<RequiredServices extends SecretlessServices<SingletonServices> = WiredAuthServices> = CorePikkuAuth<RequiredServices, Session>
|
|
132
145
|
|
|
133
146
|
/**
|
|
134
147
|
* Configuration object for creating an auth permission with metadata
|
|
135
148
|
*/
|
|
136
|
-
export type PikkuAuthConfig<RequiredServices extends SingletonServices =
|
|
149
|
+
export type PikkuAuthConfig<RequiredServices extends SecretlessServices<SingletonServices> = WiredAuthServices> = CorePikkuAuthConfig<RequiredServices, Session>
|
|
137
150
|
|
|
138
151
|
/**
|
|
139
152
|
* Factory function for creating auth-only permissions with tree-shaking support.
|
|
@@ -155,7 +168,7 @@ export type PikkuAuthConfig<RequiredServices extends SingletonServices = WiredSi
|
|
|
155
168
|
* })
|
|
156
169
|
* \\\`\\\`\\\`
|
|
157
170
|
*/
|
|
158
|
-
export const pikkuAuth = <RequiredServices extends SingletonServices =
|
|
171
|
+
export const pikkuAuth = <RequiredServices extends SecretlessServices<SingletonServices> = WiredAuthServices>(
|
|
159
172
|
auth: PikkuAuth<RequiredServices> | PikkuAuthConfig<RequiredServices>
|
|
160
173
|
): PikkuPermission<any, any> => {
|
|
161
174
|
return pikkuAuthCore(auth as any) as any
|
|
@@ -257,7 +270,7 @@ export const pikkuPermissionFactory = <In = any>(
|
|
|
257
270
|
* @template In - The input type (same as the function it describes)
|
|
258
271
|
* @template RequiredServices - The services required for this description function
|
|
259
272
|
*/
|
|
260
|
-
export type PikkuApprovalDescription<In = unknown, RequiredServices extends Services = WiredServices> = (
|
|
273
|
+
export type PikkuApprovalDescription<In = unknown, RequiredServices extends SecretlessServices<Services> = WiredServices> = (
|
|
261
274
|
services: RequiredServices,
|
|
262
275
|
data: In
|
|
263
276
|
) => Promise<string>
|
|
@@ -275,7 +288,7 @@ export type PikkuApprovalDescription<In = unknown, RequiredServices extends Serv
|
|
|
275
288
|
* )
|
|
276
289
|
* \`\`\`
|
|
277
290
|
*/
|
|
278
|
-
export const pikkuApprovalDescription = <In = unknown, RequiredServices extends Services = WiredServices>(
|
|
291
|
+
export const pikkuApprovalDescription = <In = unknown, RequiredServices extends SecretlessServices<Services> = WiredServices>(
|
|
279
292
|
fn: PikkuApprovalDescription<In, RequiredServices>
|
|
280
293
|
): PikkuApprovalDescription<In, RequiredServices> => {
|
|
281
294
|
return fn
|
|
@@ -293,13 +306,13 @@ export type PikkuFunctionSessionless<
|
|
|
293
306
|
In = unknown,
|
|
294
307
|
Out = never,
|
|
295
308
|
RequiredWires extends keyof PikkuWire = never,
|
|
296
|
-
RequiredServices extends Services = WiredServices
|
|
309
|
+
RequiredServices extends SecretlessServices<Services> = WiredServices
|
|
297
310
|
> = CorePikkuFunctionSessionless<
|
|
298
311
|
In,
|
|
299
312
|
Out,
|
|
300
313
|
RequiredServices,
|
|
301
314
|
Session,
|
|
302
|
-
PickRequired<PikkuWire<In, Out, false, Session, TypedPikkuRPC, null, any, TypedWorkflow, unknown, TypedScenario,
|
|
315
|
+
PickRequired<PikkuWire<In, Out, false, Session, TypedPikkuRPC, null, any, TypedWorkflow, unknown, TypedScenario, TypedPersonas>, RequiredWires>
|
|
303
316
|
>
|
|
304
317
|
|
|
305
318
|
/**
|
|
@@ -314,13 +327,13 @@ export type PikkuFunction<
|
|
|
314
327
|
In = unknown,
|
|
315
328
|
Out = never,
|
|
316
329
|
RequiredWires extends keyof PikkuWire = 'session',
|
|
317
|
-
RequiredServices extends Services = WiredServices
|
|
330
|
+
RequiredServices extends SecretlessServices<Services> = WiredServices
|
|
318
331
|
> = CorePikkuFunction<
|
|
319
332
|
In,
|
|
320
333
|
Out,
|
|
321
334
|
RequiredServices,
|
|
322
335
|
Session,
|
|
323
|
-
PickRequired<PikkuWire<In, Out, true, Session, TypedPikkuRPC, null, any, TypedWorkflow, unknown, TypedScenario,
|
|
336
|
+
PickRequired<PikkuWire<In, Out, true, Session, TypedPikkuRPC, null, any, TypedWorkflow, unknown, TypedScenario, TypedPersonas>, RequiredWires>
|
|
324
337
|
>
|
|
325
338
|
|
|
326
339
|
/**
|
|
@@ -340,7 +353,7 @@ export type PikkuFunctionConfig<
|
|
|
340
353
|
In = unknown,
|
|
341
354
|
Out = unknown,
|
|
342
355
|
RequiredWires extends keyof PikkuWire = never,
|
|
343
|
-
PikkuFunc extends PikkuFunction<In, Out, RequiredWires> | PikkuFunctionSessionless<In, Out, RequiredWires> = PikkuFunction<In, Out, RequiredWires> | PikkuFunctionSessionless<In, Out, RequiredWires>,
|
|
356
|
+
PikkuFunc extends PikkuFunction<In, Out, RequiredWires, any> | PikkuFunctionSessionless<In, Out, RequiredWires, any> = PikkuFunction<In, Out, RequiredWires> | PikkuFunctionSessionless<In, Out, RequiredWires>,
|
|
344
357
|
InputSchema extends StandardSchemaV1 | undefined = undefined,
|
|
345
358
|
OutputSchema extends StandardSchemaV1 | undefined = undefined
|
|
346
359
|
> = CorePikkuFunctionConfig<PikkuFunc, PikkuPermission<In>, PikkuMiddleware, InputSchema, OutputSchema, ScopeId>
|
|
@@ -361,11 +374,12 @@ type SchemaInferred<S, Fallback = unknown> = S extends StandardSchemaV1
|
|
|
361
374
|
export type PikkuFunctionConfigWithSchema<
|
|
362
375
|
InputSchema extends StandardSchemaV1 | undefined = undefined,
|
|
363
376
|
OutputSchema extends StandardSchemaV1 | undefined = undefined,
|
|
364
|
-
RequiredWires extends keyof PikkuWire = never
|
|
377
|
+
RequiredWires extends keyof PikkuWire = never,
|
|
378
|
+
RequiredServices extends SecretlessServices<Services> = WiredServices
|
|
365
379
|
> = Omit<
|
|
366
380
|
CorePikkuFunctionConfig<
|
|
367
|
-
| PikkuFunction<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires>
|
|
368
|
-
| PikkuFunctionSessionless<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires>,
|
|
381
|
+
| PikkuFunction<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires, RequiredServices>
|
|
382
|
+
| PikkuFunctionSessionless<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires, RequiredServices>,
|
|
369
383
|
CorePikkuPermission<any>,
|
|
370
384
|
PikkuMiddleware,
|
|
371
385
|
undefined,
|
|
@@ -375,8 +389,8 @@ export type PikkuFunctionConfigWithSchema<
|
|
|
375
389
|
'func' | 'input' | 'output' | 'permissions' | 'approvalDescription'
|
|
376
390
|
> & {
|
|
377
391
|
func:
|
|
378
|
-
| PikkuFunction<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires>
|
|
379
|
-
| PikkuFunctionSessionless<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires>
|
|
392
|
+
| PikkuFunction<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires, RequiredServices>
|
|
393
|
+
| PikkuFunctionSessionless<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires, RequiredServices>
|
|
380
394
|
input?: InputSchema
|
|
381
395
|
output?: OutputSchema
|
|
382
396
|
permissions?: InputSchema extends StandardSchemaV1
|
|
@@ -413,6 +427,12 @@ export type PikkuFunctionConfigWithSchema<
|
|
|
413
427
|
* })
|
|
414
428
|
* \`\`\`
|
|
415
429
|
*/
|
|
430
|
+
export function pikkuFunc<
|
|
431
|
+
InputSchema extends StandardSchemaV1 | undefined = undefined,
|
|
432
|
+
OutputSchema extends StandardSchemaV1 | undefined = undefined
|
|
433
|
+
>(
|
|
434
|
+
config: PikkuFunctionConfigWithSchema<InputSchema, OutputSchema, 'session' | 'rpc', WiredSecretBrokerServices> & { secretBroker: true }
|
|
435
|
+
): PikkuFunctionConfig<InputSchema extends StandardSchemaV1 ? InferSchemaOutput<InputSchema> : unknown, OutputSchema extends StandardSchemaV1 ? InferSchemaOutput<OutputSchema> : unknown, 'session' | 'rpc'>
|
|
416
436
|
export function pikkuFunc<
|
|
417
437
|
InputSchema extends StandardSchemaV1 | undefined = undefined,
|
|
418
438
|
OutputSchema extends StandardSchemaV1 | undefined = undefined
|
|
@@ -464,17 +484,19 @@ export const pikkuListFunc = <
|
|
|
464
484
|
export type PikkuFunctionSessionlessConfigWithSchema<
|
|
465
485
|
InputSchema extends StandardSchemaV1 | undefined = undefined,
|
|
466
486
|
OutputSchema extends StandardSchemaV1 | undefined = undefined,
|
|
467
|
-
RequiredWires extends keyof PikkuWire = never
|
|
487
|
+
RequiredWires extends keyof PikkuWire = never,
|
|
488
|
+
RequiredServices extends SecretlessServices<Services> = WiredServices
|
|
468
489
|
> = Omit<
|
|
469
490
|
CorePikkuFunctionConfig<
|
|
470
|
-
PikkuFunctionSessionless<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires>
|
|
491
|
+
PikkuFunctionSessionless<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires, RequiredServices>
|
|
471
492
|
>,
|
|
472
493
|
'func' | 'input' | 'output' | 'permissions' | 'approvalDescription'
|
|
473
494
|
> & {
|
|
474
495
|
func: PikkuFunctionSessionless<
|
|
475
496
|
SchemaInferred<InputSchema>,
|
|
476
497
|
SchemaInferred<OutputSchema>,
|
|
477
|
-
RequiredWires
|
|
498
|
+
RequiredWires,
|
|
499
|
+
RequiredServices
|
|
478
500
|
>
|
|
479
501
|
input?: InputSchema
|
|
480
502
|
output?: OutputSchema
|
|
@@ -512,14 +534,15 @@ export type PikkuFunctionSessionlessConfigWithSchema<
|
|
|
512
534
|
*/
|
|
513
535
|
export function pikkuSessionlessFunc<
|
|
514
536
|
InputSchema extends StandardSchemaV1 | undefined = undefined,
|
|
515
|
-
OutputSchema extends StandardSchemaV1 | undefined = undefined
|
|
537
|
+
OutputSchema extends StandardSchemaV1 | undefined = undefined,
|
|
538
|
+
RequiredServices extends SecretlessServices<Services> = WiredServices
|
|
516
539
|
>(
|
|
517
|
-
config: PikkuFunctionSessionlessConfigWithSchema<InputSchema, OutputSchema, 'session' | 'rpc'>
|
|
540
|
+
config: PikkuFunctionSessionlessConfigWithSchema<InputSchema, OutputSchema, 'session' | 'rpc', RequiredServices>
|
|
518
541
|
): PikkuFunctionConfig<InputSchema extends StandardSchemaV1 ? InferSchemaOutput<InputSchema> : unknown, OutputSchema extends StandardSchemaV1 ? InferSchemaOutput<OutputSchema> : unknown, 'session' | 'rpc'>
|
|
519
|
-
export function pikkuSessionlessFunc<In, Out = unknown>(
|
|
542
|
+
export function pikkuSessionlessFunc<In, Out = unknown, RequiredServices extends SecretlessServices<Services> = WiredServices>(
|
|
520
543
|
func:
|
|
521
|
-
| PikkuFunctionSessionless<In, Out, 'session' | 'rpc'>
|
|
522
|
-
| PikkuFunctionConfig<In, Out, 'session' | 'rpc'
|
|
544
|
+
| PikkuFunctionSessionless<In, Out, 'session' | 'rpc', RequiredServices>
|
|
545
|
+
| PikkuFunctionConfig<In, Out, 'session' | 'rpc', PikkuFunctionSessionless<In, Out, 'session' | 'rpc', RequiredServices>>
|
|
523
546
|
): PikkuFunctionConfig<In, Out, 'session' | 'rpc'>
|
|
524
547
|
export function pikkuSessionlessFunc(func: any) {
|
|
525
548
|
return typeof func === 'function' ? { func } : func
|
|
@@ -584,6 +607,43 @@ export const ref = <Name extends keyof FlattenedRPCMap>(
|
|
|
584
607
|
>
|
|
585
608
|
}
|
|
586
609
|
|
|
610
|
+
/**
|
|
611
|
+
* Declares a capability the connected client answers, reachable from any
|
|
612
|
+
* \`wireChannel\` function as \`channel.remote(name, input)\`.
|
|
613
|
+
*
|
|
614
|
+
* There is no \`func\`: this side owns the contract, the client owns the body.
|
|
615
|
+
* The \`description\` is what a person is shown when asked to approve the call,
|
|
616
|
+
* so write it for them rather than for the caller.
|
|
617
|
+
*
|
|
618
|
+
* @example
|
|
619
|
+
* \`\`\`typescript
|
|
620
|
+
* export const localCheckoutOutput = z.object({ sha: z.string(), branch: z.string() })
|
|
621
|
+
*
|
|
622
|
+
* export const localCheckout = pikkuRemoteChannelFunc({
|
|
623
|
+
* description: 'Read the current commit and branch of your working tree',
|
|
624
|
+
* output: localCheckoutOutput,
|
|
625
|
+
* })
|
|
626
|
+
* \`\`\`
|
|
627
|
+
*/
|
|
628
|
+
export function pikkuRemoteChannelFunc<
|
|
629
|
+
InputSchema extends StandardSchemaV1 | undefined = undefined,
|
|
630
|
+
OutputSchema extends StandardSchemaV1 | undefined = undefined
|
|
631
|
+
>(
|
|
632
|
+
config: Omit<
|
|
633
|
+
PikkuFunctionSessionlessConfigWithSchema<InputSchema, OutputSchema, 'session' | 'rpc'>,
|
|
634
|
+
'func'
|
|
635
|
+
>
|
|
636
|
+
): PikkuFunctionConfig<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, 'session' | 'rpc'> {
|
|
637
|
+
return {
|
|
638
|
+
...config,
|
|
639
|
+
func: async (_services: any, _data: any, _wire: any) => {
|
|
640
|
+
throw new Error(
|
|
641
|
+
\`\${config.title ?? 'This'} is a remote channel capability and has no local implementation — reach it with channel.remote() on the channel whose client exposes it.\`
|
|
642
|
+
)
|
|
643
|
+
},
|
|
644
|
+
} as any
|
|
645
|
+
}
|
|
646
|
+
|
|
587
647
|
/**
|
|
588
648
|
* Creates a Pikku config factory.
|
|
589
649
|
* Use this to define your application's configuration factory.
|
|
@@ -2,16 +2,30 @@ import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
|
|
|
2
2
|
const collectFactories = (groupMap, outputPath, packageMappings) => {
|
|
3
3
|
const factories = new Map();
|
|
4
4
|
for (const [, groupMeta] of groupMap.entries()) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
for (const registration of registrationsOf(groupMeta)) {
|
|
6
|
+
if (registration.exportName && registration.isFactory) {
|
|
7
|
+
const filePath = getFileImportRelativePath(outputPath, registration.sourceFile, packageMappings);
|
|
8
|
+
factories.set(registration.exportName, {
|
|
9
|
+
exportName: registration.exportName,
|
|
10
|
+
filePath,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
11
13
|
}
|
|
12
14
|
}
|
|
13
15
|
return factories;
|
|
14
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* Every `add*Middleware` call recorded under one pattern or tag.
|
|
19
|
+
*
|
|
20
|
+
* A group is keyed by its pattern, and more than one file may register for the
|
|
21
|
+
* same one. Emitting only the primary registration meant the other file was
|
|
22
|
+
* never imported, so its middleware never registered — which for a session
|
|
23
|
+
* bridge or an auth gate fails open and fails silently.
|
|
24
|
+
*/
|
|
25
|
+
const registrationsOf = (groupMeta) => [
|
|
26
|
+
groupMeta,
|
|
27
|
+
...(groupMeta.additionalRegistrations ?? []),
|
|
28
|
+
];
|
|
15
29
|
export const serializeMiddlewareImports = (outputPath, middlewareState, httpState, packageMappings = {}, fullState) => {
|
|
16
30
|
const serializedImports = [];
|
|
17
31
|
const serializedFactoryCalls = [];
|
|
@@ -24,9 +38,11 @@ export const serializeMiddlewareImports = (outputPath, middlewareState, httpStat
|
|
|
24
38
|
const directImports = new Set();
|
|
25
39
|
const collectDirectImports = (groupMap) => {
|
|
26
40
|
for (const [, groupMeta] of groupMap.entries()) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
41
|
+
for (const registration of registrationsOf(groupMeta)) {
|
|
42
|
+
if (!registration.isFactory) {
|
|
43
|
+
const filePath = getFileImportRelativePath(outputPath, registration.sourceFile, packageMappings);
|
|
44
|
+
directImports.add(filePath);
|
|
45
|
+
}
|
|
30
46
|
}
|
|
31
47
|
}
|
|
32
48
|
};
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
export const serializeSecretDefinitionTypes = () => {
|
|
2
|
-
return `export {
|
|
2
|
+
return `export { defineSecret } from '@pikku/core/secret'
|
|
3
3
|
export type { CoreSecret, SecretDefinitionMeta, SecretDefinitionsMeta } from '@pikku/core/secret'
|
|
4
4
|
`;
|
|
5
5
|
};
|
|
6
6
|
export const serializeScopeDefinitionTypes = () => {
|
|
7
|
-
return `export {
|
|
7
|
+
return `export { defineScope } from '@pikku/core/scope'
|
|
8
8
|
export type { CoreScopes, CoreScopeNode, FlatScope, ScopeDefinitionMeta, ScopeDefinitionsMeta } from '@pikku/core/scope'
|
|
9
|
+
export { defineSystemRole } from '@pikku/core/role'
|
|
10
|
+
export type { CoreSystemRole, CoreSystemRoles, SystemRole, SystemRoleDefinitionMeta, SystemRoleDefinitionsMeta } from '@pikku/core/role'
|
|
9
11
|
`;
|
|
10
12
|
};
|
|
11
13
|
export const serializeVariableDefinitionTypes = () => {
|
|
12
|
-
return `export {
|
|
14
|
+
return `export { defineVariable } from '@pikku/core/variable'
|
|
13
15
|
export type { CoreVariable, VariableDefinitionMeta, VariableDefinitionsMeta } from '@pikku/core/variable'
|
|
14
16
|
`;
|
|
15
17
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const pikkuPersonas: import("#pikku").PikkuFunctionConfig<{
|
|
2
|
+
bootstrap?: boolean;
|
|
3
|
+
}, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<{
|
|
4
|
+
bootstrap?: boolean;
|
|
5
|
+
}, void, "rpc" | "session", import("#pikku").WiredServices> | import("#pikku").PikkuFunction<{
|
|
6
|
+
bootstrap?: boolean;
|
|
7
|
+
}, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { pikkuSessionlessFunc } from '#pikku';
|
|
2
|
+
import { writeFileInDir } from '../../../utils/file-writer.js';
|
|
3
|
+
import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
|
|
4
|
+
import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
|
|
5
|
+
import { serializePersonasTypes } from './serialize-personas-types.js';
|
|
6
|
+
import { personaEnvironmentErrors, validateAndBuildPersonasMeta, } from '@pikku/core/persona';
|
|
7
|
+
export const pikkuPersonas = pikkuSessionlessFunc({
|
|
8
|
+
func: async ({ logger, config, getInspectorState }, data) => {
|
|
9
|
+
const { personasFile, personasMetaJsonFile, rolesFile, packageMappings } = config;
|
|
10
|
+
if (!personasFile) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
// Same cold-start reasoning as Scopes and Roles: on a bare .pikku this
|
|
14
|
+
// runs before the app's own types exist, so it takes the zero state. The
|
|
15
|
+
// file only has to exist so a persona file can import definePersonas.
|
|
16
|
+
const bootstrap = data?.bootstrap ?? false;
|
|
17
|
+
const state = await getInspectorState(false, bootstrap, bootstrap);
|
|
18
|
+
const environments = config.environments ?? {};
|
|
19
|
+
// Before anything is written. A persona that may not run where it says it
|
|
20
|
+
// runs is a declaration to fix, not a file to generate — and generating
|
|
21
|
+
// it anyway would leave a `.pikku` that typechecks while lying.
|
|
22
|
+
const errors = state.personas.definitions.flatMap((persona) => personaEnvironmentErrors(persona.id, persona, environments));
|
|
23
|
+
if (errors.length) {
|
|
24
|
+
throw new Error(errors.join('\n'));
|
|
25
|
+
}
|
|
26
|
+
const content = serializePersonasTypes({
|
|
27
|
+
definitions: state.personas.definitions,
|
|
28
|
+
rolesImportPath: getFileImportRelativePath(personasFile, rolesFile, packageMappings),
|
|
29
|
+
environmentNames: Object.keys(environments),
|
|
30
|
+
});
|
|
31
|
+
await writeFileInDir(logger, personasFile, content);
|
|
32
|
+
if (personasMetaJsonFile) {
|
|
33
|
+
const meta = validateAndBuildPersonasMeta(state.personas.definitions);
|
|
34
|
+
await writeFileInDir(logger, personasMetaJsonFile, JSON.stringify(meta, null, 2));
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
middleware: [
|
|
38
|
+
logCommandInfoAndTime({
|
|
39
|
+
commandStart: 'Creating PikkuPersonas types',
|
|
40
|
+
commandEnd: 'Created PikkuPersonas types',
|
|
41
|
+
}),
|
|
42
|
+
],
|
|
43
|
+
});
|