@pikku/cli 0.12.127 → 0.12.128
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/CHANGELOG.md +92 -0
- package/dist/.pikku/addon/index.d.ts +1 -1
- package/dist/.pikku/addon/index.js +1 -1
- package/dist/.pikku/addon/pikku-addon-types.gen.d.ts +1 -1
- package/dist/.pikku/addon/pikku-addon-types.gen.js +1 -1
- package/dist/.pikku/agent/index.d.ts +1 -1
- package/dist/.pikku/agent/index.js +1 -1
- package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
- package/dist/.pikku/agent/pikku-model-aliases.gen.js +1 -1
- package/dist/.pikku/auth/index.d.ts +1 -1
- package/dist/.pikku/auth/index.js +1 -1
- package/dist/.pikku/auth/pikku-auth-types.gen.d.ts +1 -1
- package/dist/.pikku/auth/pikku-auth-types.gen.js +1 -1
- package/dist/.pikku/channel/index.d.ts +1 -1
- package/dist/.pikku/channel/index.js +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/index.d.ts +1 -1
- package/dist/.pikku/cli/index.js +1 -1
- package/dist/.pikku/cli/pikku-cli-channel.js +11 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -1
- 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-contracts-meta.gen.json +21 -0
- 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 +37 -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/error/index.d.ts +1 -1
- package/dist/.pikku/error/index.js +1 -1
- package/dist/.pikku/error/pikku-error-types.gen.d.ts +1 -1
- package/dist/.pikku/error/pikku-error-types.gen.js +1 -1
- package/dist/.pikku/function/index.d.ts +1 -1
- package/dist/.pikku/function/index.js +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 +42 -6
- package/dist/.pikku/function/pikku-functions.gen.js +1 -1
- package/dist/.pikku/gateway/index.d.ts +1 -1
- package/dist/.pikku/gateway/index.js +1 -1
- package/dist/.pikku/gateway/pikku-gateway-types.gen.d.ts +1 -1
- package/dist/.pikku/gateway/pikku-gateway-types.gen.js +1 -1
- package/dist/.pikku/http/index.d.ts +1 -1
- package/dist/.pikku/http/index.js +1 -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/index.d.ts +1 -1
- package/dist/.pikku/mcp/index.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/middleware/index.d.ts +1 -1
- package/dist/.pikku/middleware/index.js +1 -1
- package/dist/.pikku/middleware/pikku-middleware-types.gen.d.ts +1 -1
- package/dist/.pikku/middleware/pikku-middleware-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-services.gen.d.ts +1 -1
- package/dist/.pikku/queue/index.d.ts +1 -1
- package/dist/.pikku/queue/index.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 +2 -0
- package/dist/.pikku/scenarios/index.d.ts +1 -1
- package/dist/.pikku/scenarios/index.js +1 -1
- package/dist/.pikku/scenarios/pikku-personas.gen.js +1 -1
- 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-types.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/index.d.ts +1 -1
- package/dist/.pikku/scheduler/index.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 +7 -1
- package/dist/.pikku/schemas/schemas/FabricSecretsDeleteInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricSecretsDeleteOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuDistInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/PikkuNewAddonInput.schema.json +1 -1
- package/dist/.pikku/scopes/index.d.ts +1 -1
- package/dist/.pikku/scopes/index.js +1 -1
- package/dist/.pikku/scopes/pikku-personas.gen.js +1 -1
- package/dist/.pikku/scopes/pikku-roles.gen.d.ts +1 -1
- package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +1 -1
- package/dist/.pikku/scopes/pikku-scope-types.gen.js +1 -1
- package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
- package/dist/.pikku/secrets/index.d.ts +1 -1
- package/dist/.pikku/secrets/index.js +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/services/pikku-meta-service.gen.d.ts +1 -1
- package/dist/.pikku/services/pikku-meta-service.gen.js +1 -1
- package/dist/.pikku/setup/index.d.ts +1 -1
- package/dist/.pikku/setup/index.js +1 -1
- package/dist/.pikku/setup/pikku-setup-types.gen.d.ts +1 -1
- package/dist/.pikku/setup/pikku-setup-types.gen.js +1 -1
- package/dist/.pikku/trigger/index.d.ts +1 -1
- package/dist/.pikku/trigger/index.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/index.d.ts +1 -1
- package/dist/.pikku/variables/index.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/index.d.ts +1 -1
- package/dist/.pikku/workflow/index.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 +16 -1
- package/dist/src/fabric/fabric-commands.d.ts +25 -0
- package/dist/src/fabric/fabric-commands.js +13 -0
- package/dist/src/fabric/functions/secrets-delete.function.d.ts +36 -0
- package/dist/src/fabric/functions/secrets-delete.function.js +51 -0
- package/dist/src/functions/commands/dev.js +2 -1
- package/dist/src/functions/commands/dist.d.ts +28 -0
- package/dist/src/functions/commands/dist.js +58 -0
- package/dist/src/functions/commands/new-addon.d.ts +30 -0
- package/dist/src/functions/commands/new-addon.js +81 -3
- package/dist/src/functions/commands/persona-sync.d.ts +5 -4
- package/dist/src/functions/commands/persona-sync.js +6 -5
- package/dist/src/functions/commands/persona.js +6 -2
- package/dist/src/functions/validate/auth-plugin-checks.js +3 -2
- package/dist/src/functions/validate/persona-checks.js +2 -1
- package/dist/src/utils/persona-credentials.d.ts +0 -2
- package/dist/src/utils/persona-credentials.js +1 -8
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/snippets.json +1 -1
- package/surface.json +1292 -4907
|
@@ -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.128
|
|
3
3
|
*/
|
|
4
4
|
import { WorkflowCancelledException } from '@pikku/core/workflow';
|
|
5
5
|
import type { PikkuWorkflowGraphConfig, PikkuWorkflowGraphResult } from '@pikku/core/workflow';
|
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.128') {
|
|
15
|
+
process.stderr.write(`\n Update available 0.12.128 → ${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
|
@@ -12,6 +12,7 @@ import { pikkuCLICommand, wireCLI } from '../.pikku/cli/pikku-cli-types.gen.js';
|
|
|
12
12
|
import { fabricCommands } from './fabric/fabric-commands.js';
|
|
13
13
|
import { all } from './functions/commands/all.js';
|
|
14
14
|
import { bootstrap } from './functions/commands/bootstrap.js';
|
|
15
|
+
import { pikkuDist } from './functions/commands/dist.js';
|
|
15
16
|
import { watch } from './functions/commands/watch.js';
|
|
16
17
|
import { login, logout, whoami } from './functions/commands/login.js';
|
|
17
18
|
import { dev } from './functions/commands/dev.js';
|
|
@@ -231,6 +232,16 @@ wireCLI({
|
|
|
231
232
|
func: bootstrap,
|
|
232
233
|
description: 'Generate only type files (setup phase only)',
|
|
233
234
|
}),
|
|
235
|
+
dist: pikkuCLICommand({
|
|
236
|
+
func: pikkuDist,
|
|
237
|
+
description: "Copy the generated files tsc cannot emit — the .gen.json meta, and hand-authored .d.ts — into the build output. Run it after tsc, as a package's build script",
|
|
238
|
+
options: {
|
|
239
|
+
distDir: {
|
|
240
|
+
description: "Where to copy to. Defaults to the tsconfig's compilerOptions.outDir",
|
|
241
|
+
type: 'string',
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
}),
|
|
234
245
|
audit: pikkuCLICommand({
|
|
235
246
|
func: pikkuAudit,
|
|
236
247
|
description: 'Audit dependencies for security advisories (always) and available updates (--outdated); writes .pikku/audit.json',
|
|
@@ -635,7 +646,7 @@ wireCLI({
|
|
|
635
646
|
}),
|
|
636
647
|
sync: pikkuCLICommand({
|
|
637
648
|
func: personaSync,
|
|
638
|
-
description: "Report which personas an environment will provision, with which roles, and why any of them were skipped. The provisioning itself happens in the deployment —
|
|
649
|
+
description: "Report which personas an environment will provision, with which roles, and why any of them were skipped. The provisioning itself happens in the deployment — pass the generated personas to pikkuFabric from '@pikku/better-auth' — because the CLI has no connection to a deployed environment's database.",
|
|
639
650
|
parameters: '<environment>',
|
|
640
651
|
}),
|
|
641
652
|
list: pikkuCLICommand({
|
|
@@ -829,6 +840,10 @@ wireCLI({
|
|
|
829
840
|
description: 'Convert snake_case property names to camelCase in generated Zod schemas',
|
|
830
841
|
default: false,
|
|
831
842
|
},
|
|
843
|
+
build: {
|
|
844
|
+
description: 'Install and build the generated addon (an unbuilt addon exports a dist/ that does not exist yet, so every ref() into it is dead at runtime)',
|
|
845
|
+
default: true,
|
|
846
|
+
},
|
|
832
847
|
},
|
|
833
848
|
}),
|
|
834
849
|
},
|
|
@@ -611,6 +611,31 @@ export declare const fabricCommands: {
|
|
|
611
611
|
updatedAt: string;
|
|
612
612
|
}[];
|
|
613
613
|
}, "rpc" | "session", import("../../.pikku/function/pikku-function-types.gen.js").WiredServices>, undefined, undefined>, import("../../.pikku/middleware/pikku-middleware-types.gen.js").PikkuMiddleware, (services: import("../../types/application-types.js").SingletonServices, data: any, session?: import("../../types/application-types.js").UserSession | undefined) => void | Promise<void>, string>;
|
|
614
|
+
delete: import("@pikku/core/cli").CoreCLICommandConfig<import("../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionConfig<{
|
|
615
|
+
name: string;
|
|
616
|
+
branch?: string | undefined;
|
|
617
|
+
force?: boolean | undefined;
|
|
618
|
+
}, {
|
|
619
|
+
name: string;
|
|
620
|
+
runId: string | null;
|
|
621
|
+
deploymentId: string | null;
|
|
622
|
+
}, "rpc" | "session", import("../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionSessionless<{
|
|
623
|
+
name: string;
|
|
624
|
+
branch?: string | undefined;
|
|
625
|
+
force?: boolean | undefined;
|
|
626
|
+
}, {
|
|
627
|
+
name: string;
|
|
628
|
+
runId: string | null;
|
|
629
|
+
deploymentId: string | null;
|
|
630
|
+
}, "rpc" | "session", import("../../.pikku/function/pikku-function-types.gen.js").WiredServices, unknown> | import("../../.pikku/function/pikku-function-types.gen.js").PikkuFunction<{
|
|
631
|
+
name: string;
|
|
632
|
+
branch?: string | undefined;
|
|
633
|
+
force?: boolean | undefined;
|
|
634
|
+
}, {
|
|
635
|
+
name: string;
|
|
636
|
+
runId: string | null;
|
|
637
|
+
deploymentId: string | null;
|
|
638
|
+
}, "rpc" | "session", import("../../.pikku/function/pikku-function-types.gen.js").WiredServices>, undefined, undefined>, import("../../.pikku/middleware/pikku-middleware-types.gen.js").PikkuMiddleware, (services: import("../../types/application-types.js").SingletonServices, data: any, session?: import("../../types/application-types.js").UserSession | undefined) => void | Promise<void>, string>;
|
|
614
639
|
rotate: import("@pikku/core/cli").CoreCLICommandConfig<import("../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionConfig<{
|
|
615
640
|
branch?: string | undefined;
|
|
616
641
|
force?: boolean | undefined;
|
|
@@ -32,6 +32,7 @@ import { FabricDbSchema, renderDbSchema, } from './functions/db-schema.function.
|
|
|
32
32
|
import { FabricRollback } from './functions/rollback.function.js';
|
|
33
33
|
import { FabricSecretsSet } from './functions/secrets-set.function.js';
|
|
34
34
|
import { FabricSecretsList } from './functions/secrets-list.function.js';
|
|
35
|
+
import { FabricSecretsDelete } from './functions/secrets-delete.function.js';
|
|
35
36
|
import { FabricSecretsRotate } from './functions/secrets-rotate.function.js';
|
|
36
37
|
import { FabricVariablesSet } from './functions/variables-set.function.js';
|
|
37
38
|
import { FabricVariablesGet } from './functions/variables-get.function.js';
|
|
@@ -254,6 +255,18 @@ export const fabricCommands = defineCLICommands({
|
|
|
254
255
|
json: { description: 'Machine-readable output', default: false },
|
|
255
256
|
},
|
|
256
257
|
}),
|
|
258
|
+
delete: pikkuCLICommand({
|
|
259
|
+
parameters: '<name>',
|
|
260
|
+
func: FabricSecretsDelete,
|
|
261
|
+
description: 'Delete a single stage-scoped secret',
|
|
262
|
+
options: {
|
|
263
|
+
branch: { description: 'Target branch', short: 'b' },
|
|
264
|
+
force: {
|
|
265
|
+
description: 'Delete without confirmation',
|
|
266
|
+
default: false,
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
}),
|
|
257
270
|
rotate: pikkuCLICommand({
|
|
258
271
|
func: FabricSecretsRotate,
|
|
259
272
|
description: "Retire a stage's sealing key (secrets must be set again)",
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const FabricSecretsDeleteInput: z.ZodObject<{
|
|
3
|
+
name: z.ZodString;
|
|
4
|
+
branch: z.ZodOptional<z.ZodString>;
|
|
5
|
+
force: z.ZodOptional<z.ZodBoolean>;
|
|
6
|
+
}, z.core.$strip>;
|
|
7
|
+
export declare const FabricSecretsDeleteOutput: z.ZodObject<{
|
|
8
|
+
name: z.ZodString;
|
|
9
|
+
runId: z.ZodNullable<z.ZodString>;
|
|
10
|
+
deploymentId: z.ZodNullable<z.ZodString>;
|
|
11
|
+
}, z.core.$strip>;
|
|
12
|
+
export declare const FabricSecretsDelete: import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionConfig<{
|
|
13
|
+
name: string;
|
|
14
|
+
branch?: string | undefined;
|
|
15
|
+
force?: boolean | undefined;
|
|
16
|
+
}, {
|
|
17
|
+
name: string;
|
|
18
|
+
runId: string | null;
|
|
19
|
+
deploymentId: string | null;
|
|
20
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunctionSessionless<{
|
|
21
|
+
name: string;
|
|
22
|
+
branch?: string | undefined;
|
|
23
|
+
force?: boolean | undefined;
|
|
24
|
+
}, {
|
|
25
|
+
name: string;
|
|
26
|
+
runId: string | null;
|
|
27
|
+
deploymentId: string | null;
|
|
28
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices, unknown> | import("../../../.pikku/function/pikku-function-types.gen.js").PikkuFunction<{
|
|
29
|
+
name: string;
|
|
30
|
+
branch?: string | undefined;
|
|
31
|
+
force?: boolean | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
name: string;
|
|
34
|
+
runId: string | null;
|
|
35
|
+
deploymentId: string | null;
|
|
36
|
+
}, "rpc" | "session", import("../../../.pikku/function/pikku-function-types.gen.js").WiredServices>, undefined, undefined>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { pikkuSessionlessFunc } from '../../../.pikku/function/index.js';
|
|
3
|
+
import { resolveApiContext } from '../lib/config.js';
|
|
4
|
+
import { getFabricRPC } from '../lib/http.js';
|
|
5
|
+
import { promptConfirm } from '../lib/prompt.js';
|
|
6
|
+
import { resolveStage } from '../lib/stage.js';
|
|
7
|
+
export const FabricSecretsDeleteInput = z.object({
|
|
8
|
+
name: z.string(),
|
|
9
|
+
branch: z.string().optional(),
|
|
10
|
+
force: z.boolean().optional(),
|
|
11
|
+
});
|
|
12
|
+
export const FabricSecretsDeleteOutput = z.object({
|
|
13
|
+
name: z.string(),
|
|
14
|
+
runId: z.string().nullable(),
|
|
15
|
+
deploymentId: z.string().nullable(),
|
|
16
|
+
});
|
|
17
|
+
export const FabricSecretsDelete = pikkuSessionlessFunc({
|
|
18
|
+
description: 'Remove a single stage-scoped secret. Unlike `secrets rotate`, the rest of the stage keeps its sealing key and its other secrets.',
|
|
19
|
+
input: FabricSecretsDeleteInput,
|
|
20
|
+
output: FabricSecretsDeleteOutput,
|
|
21
|
+
func: async (_services, { name, branch: requested, force }) => {
|
|
22
|
+
const ctx = await resolveApiContext();
|
|
23
|
+
if (!ctx.token)
|
|
24
|
+
throw new Error('Not logged in. Run `pikku fabric login` first.');
|
|
25
|
+
if (!ctx.projectId)
|
|
26
|
+
throw new Error('No fabric project linked. Run `pikku fabric link` first.');
|
|
27
|
+
// Resolved before the prompt so the confirmation names the stage that
|
|
28
|
+
// would actually lose the secret, not an argument that may be absent.
|
|
29
|
+
const rpc = getFabricRPC({ apiUrl: ctx.apiUrl, token: ctx.token });
|
|
30
|
+
const { stageId, branch } = await resolveStage(rpc, ctx.projectId, requested);
|
|
31
|
+
if (!force) {
|
|
32
|
+
if (!process.stdin.isTTY) {
|
|
33
|
+
throw new Error(`Refusing to delete ${name} from ${branch} without confirmation — re-run with --force to delete non-interactively.`);
|
|
34
|
+
}
|
|
35
|
+
// Fabric cannot read the sealed value back, so this is not recoverable
|
|
36
|
+
// by re-reading it — the plaintext has to be supplied again.
|
|
37
|
+
if (!(await promptConfirm(`Delete ${name} from ${branch}? It cannot be recovered — the value must be set again.`))) {
|
|
38
|
+
throw new Error('Delete aborted.');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const result = await rpc.invoke('deleteStageSecret', { stageId, name });
|
|
42
|
+
console.log(`[fabric] deleted ${result.name} from ${branch}`);
|
|
43
|
+
if (result.runId) {
|
|
44
|
+
console.log(`[fabric] republishing the stage as run ${result.runId} — units serve the old value until it lands`);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.log('[fabric] deploy the stage to stop its units serving the old value');
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
},
|
|
51
|
+
});
|
|
@@ -4,7 +4,7 @@ import { pikkuSessionlessFunc } from '#pikku/function';
|
|
|
4
4
|
import chokidar from 'chokidar';
|
|
5
5
|
import { pikkuDevReloader, reloadGeneratedMeta, reconcileAddonRegistry, } from '@pikku/core/dev';
|
|
6
6
|
import { InMemoryQueueService, QueueWebhookService } from '@pikku/core/services';
|
|
7
|
-
import { ConsoleLogger, LocalEmailService, spy, InMemoryAgentRunStateService, } from '@pikku/core/services';
|
|
7
|
+
import { ConsoleLogger, LocalEmailService, LocalCredentialService, spy, InMemoryAgentRunStateService, } from '@pikku/core/services';
|
|
8
8
|
import { InMemoryTriggerService } from '@pikku/core/services';
|
|
9
9
|
import { InMemoryWorkflowService } from '@pikku/core/services';
|
|
10
10
|
import { KyselyAgentStorageService, KyselyAgentRunStateService, KyselyAgentRunService, } from '@pikku/kysely';
|
|
@@ -230,6 +230,7 @@ export const dev = pikkuSessionlessFunc({
|
|
|
230
230
|
workflowService,
|
|
231
231
|
workflowRunService: workflowService,
|
|
232
232
|
triggerService: new InMemoryTriggerService(),
|
|
233
|
+
credentialService: new LocalCredentialService(),
|
|
233
234
|
agentStorage,
|
|
234
235
|
agentRunState,
|
|
235
236
|
agentRunService,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Carry into the build output the files `tsc` compiles around but never emits.
|
|
3
|
+
*
|
|
4
|
+
* `tsc` turns the generated `.ts` under the pikku out dir into JavaScript, so
|
|
5
|
+
* that half arrives on its own. Two kinds of file do not:
|
|
6
|
+
*
|
|
7
|
+
* - the `*.gen.json` meta pikku writes beside them. `resolveJsonModule` lets
|
|
8
|
+
* TypeScript *read* a json, it never copies one to `outDir`, and the meta is
|
|
9
|
+
* read off disk at runtime — `MetaService` opens it by path — so a package
|
|
10
|
+
* that ships only tsc's output answers every meta lookup with nothing.
|
|
11
|
+
* - a hand-authored `.d.ts` such as `types/application-types.d.ts`. A
|
|
12
|
+
* declaration file is an input, and `declaration: true` does not re-emit it.
|
|
13
|
+
*
|
|
14
|
+
* Packages used to do this with `cp -r .pikku types dist/`, which also dumped
|
|
15
|
+
* every `.ts` source into the published output and needed a POSIX shell.
|
|
16
|
+
*/
|
|
17
|
+
export type DistCopy = {
|
|
18
|
+
from: string;
|
|
19
|
+
to: string;
|
|
20
|
+
};
|
|
21
|
+
export declare const planDistCopies: (rootDir: string, distDir: string, files: string[]) => DistCopy[];
|
|
22
|
+
export declare const pikkuDist: import("#pikku/function").PikkuFunctionConfig<{
|
|
23
|
+
distDir?: string;
|
|
24
|
+
}, void, "rpc" | "session", import("#pikku/function").PikkuFunctionSessionless<{
|
|
25
|
+
distDir?: string;
|
|
26
|
+
}, void, "rpc" | "session", import("#pikku/function").WiredServices, unknown> | import("#pikku/function").PikkuFunction<{
|
|
27
|
+
distDir?: string;
|
|
28
|
+
}, void, "rpc" | "session", import("#pikku/function").WiredServices>, undefined, undefined>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { cp, mkdir, readdir } from 'node:fs/promises';
|
|
3
|
+
import { dirname, join, relative, resolve } from 'node:path';
|
|
4
|
+
import ts from 'typescript';
|
|
5
|
+
import { pikkuSessionlessFunc } from '#pikku/function';
|
|
6
|
+
/**
|
|
7
|
+
* `tsc` compiles a `.ts` and emits it. Everything else it either reads without
|
|
8
|
+
* emitting — a `.d.ts` is an input, `declaration: true` does not re-emit one —
|
|
9
|
+
* or ignores entirely, like the generated json.
|
|
10
|
+
*/
|
|
11
|
+
const tscEmitsIt = (file) => file.endsWith('.ts') && !file.endsWith('.d.ts');
|
|
12
|
+
const walk = async (dir) => {
|
|
13
|
+
if (!existsSync(dir)) {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
17
|
+
const files = await Promise.all(entries.map(async (entry) => {
|
|
18
|
+
const path = join(dir, entry.name);
|
|
19
|
+
return entry.isDirectory() ? walk(path) : [path];
|
|
20
|
+
}));
|
|
21
|
+
return files.flat();
|
|
22
|
+
};
|
|
23
|
+
export const planDistCopies = (rootDir, distDir, files) => {
|
|
24
|
+
return files
|
|
25
|
+
.filter((file) => !tscEmitsIt(file))
|
|
26
|
+
.map((from) => ({
|
|
27
|
+
from,
|
|
28
|
+
to: join(distDir, relative(rootDir, from)),
|
|
29
|
+
}));
|
|
30
|
+
};
|
|
31
|
+
const readTsOutDir = (tsconfig) => {
|
|
32
|
+
const parsed = ts.getParsedCommandLineOfConfigFile(tsconfig, {}, {
|
|
33
|
+
...ts.sys,
|
|
34
|
+
onUnRecoverableConfigFileDiagnostic: () => { },
|
|
35
|
+
});
|
|
36
|
+
return parsed?.options.outDir;
|
|
37
|
+
};
|
|
38
|
+
export const pikkuDist = pikkuSessionlessFunc({
|
|
39
|
+
func: async ({ logger, config }, data) => {
|
|
40
|
+
const { rootDir, outDir, srcDirectories, tsconfig } = config;
|
|
41
|
+
const distDir = data.distDir
|
|
42
|
+
? resolve(rootDir, data.distDir)
|
|
43
|
+
: readTsOutDir(resolve(rootDir, tsconfig));
|
|
44
|
+
if (!distDir) {
|
|
45
|
+
logger.error(`${tsconfig} sets no compilerOptions.outDir, so there is nowhere to copy to. Set one, or pass --dist-dir.`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
const copies = planDistCopies(rootDir, distDir, [
|
|
49
|
+
...(await walk(outDir)),
|
|
50
|
+
...(await Promise.all(srcDirectories.map((dir) => walk(resolve(rootDir, dir))))).flat(),
|
|
51
|
+
]);
|
|
52
|
+
for (const { from, to } of copies) {
|
|
53
|
+
await mkdir(dirname(to), { recursive: true });
|
|
54
|
+
await cp(from, to);
|
|
55
|
+
}
|
|
56
|
+
logger.info(`Copied ${copies.length} generated file(s) into ${relative(rootDir, distDir) || distDir}`);
|
|
57
|
+
},
|
|
58
|
+
});
|
|
@@ -28,6 +28,33 @@ export declare function getAddonFiles(vars: AddonVars, flags: {
|
|
|
28
28
|
delegated?: boolean;
|
|
29
29
|
}): Record<string, string>;
|
|
30
30
|
export declare function getTestFiles(vars: AddonVars): Record<string, string>;
|
|
31
|
+
/**
|
|
32
|
+
* Does `root`'s `workspaces` field cover `dir`?
|
|
33
|
+
*
|
|
34
|
+
* Declaring workspaces is not enough — a root with `packages/*` does not own an
|
|
35
|
+
* addon written to `addons/crm`, and yarn, npm and pnpm all skip a nested
|
|
36
|
+
* package they were never told about.
|
|
37
|
+
*/
|
|
38
|
+
export declare function workspaceCovers(root: string, dir: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* An addon that has not been built is dead at runtime.
|
|
41
|
+
*
|
|
42
|
+
* The generated package exports `./dist/...` — that is what an installed
|
|
43
|
+
* consumer resolves, and what the app's own `pikku-bootstrap.gen.ts` imports.
|
|
44
|
+
* Until `build` has run, every `ref('<addon>:...')` resolves to nothing and the
|
|
45
|
+
* app fails at boot with PKU340 plus an ERR_MODULE_NOT_FOUND on a dist path
|
|
46
|
+
* nobody wrote. Nothing about the generated files shows the problem, so the
|
|
47
|
+
* generator finishes the job: install at the root that owns the lockfile, then
|
|
48
|
+
* run the addon's own `build` script (whose `prebuild` is `pikku all`).
|
|
49
|
+
*/
|
|
50
|
+
export type AddonBuildRunner = (command: string, args: string[], cwd: string) => {
|
|
51
|
+
status: number | null;
|
|
52
|
+
error?: Error;
|
|
53
|
+
};
|
|
54
|
+
export declare const buildGeneratedAddon: (addonDir: string, logger: {
|
|
55
|
+
info: (message: string) => void;
|
|
56
|
+
error: (message: string) => void;
|
|
57
|
+
}, run?: AddonBuildRunner) => boolean;
|
|
31
58
|
export declare const pikkuNewAddon: import("#pikku/function").PikkuFunctionConfig<{
|
|
32
59
|
name: string;
|
|
33
60
|
displayName?: string;
|
|
@@ -43,6 +70,7 @@ export declare const pikkuNewAddon: import("#pikku/function").PikkuFunctionConfi
|
|
|
43
70
|
authConfig?: string;
|
|
44
71
|
mcp?: boolean;
|
|
45
72
|
camelCase?: boolean;
|
|
73
|
+
build?: boolean;
|
|
46
74
|
}, void, "rpc" | "session", import("#pikku/function").PikkuFunctionSessionless<{
|
|
47
75
|
name: string;
|
|
48
76
|
displayName?: string;
|
|
@@ -58,6 +86,7 @@ export declare const pikkuNewAddon: import("#pikku/function").PikkuFunctionConfi
|
|
|
58
86
|
authConfig?: string;
|
|
59
87
|
mcp?: boolean;
|
|
60
88
|
camelCase?: boolean;
|
|
89
|
+
build?: boolean;
|
|
61
90
|
}, void, "rpc" | "session", import("#pikku/function").WiredServices, unknown> | import("#pikku/function").PikkuFunction<{
|
|
62
91
|
name: string;
|
|
63
92
|
displayName?: string;
|
|
@@ -73,4 +102,5 @@ export declare const pikkuNewAddon: import("#pikku/function").PikkuFunctionConfi
|
|
|
73
102
|
authConfig?: string;
|
|
74
103
|
mcp?: boolean;
|
|
75
104
|
camelCase?: boolean;
|
|
105
|
+
build?: boolean;
|
|
76
106
|
}, void, "rpc" | "session", import("#pikku/function").WiredServices>, undefined, undefined>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'fs';
|
|
2
|
-
import { dirname, join } from 'path';
|
|
2
|
+
import { dirname, join, relative as relativePath, sep } from 'path';
|
|
3
3
|
import { mkdir, writeFile } from 'fs/promises';
|
|
4
|
+
import { spawnSync } from 'node:child_process';
|
|
5
|
+
import { findInstallRoot } from './update.js';
|
|
4
6
|
import { createEmptyManifest, saveManifest, } from '../../utils/contract-versions.js';
|
|
5
7
|
import { pikkuSessionlessFunc } from '#pikku/function';
|
|
6
8
|
import { parseOpenAPISpec, computeContractHash, generateAddonFromOpenAPI, loadAuthConfig, } from '@pikku/openapi-parser';
|
|
@@ -159,7 +161,7 @@ export function getAddonFiles(vars, flags) {
|
|
|
159
161
|
scripts: {
|
|
160
162
|
prepublishOnly: 'yarn build',
|
|
161
163
|
prebuild: 'pikku all',
|
|
162
|
-
build: 'tsc &&
|
|
164
|
+
build: 'tsc && pikku dist',
|
|
163
165
|
pikku: 'pikku all',
|
|
164
166
|
},
|
|
165
167
|
peerDependencies: {
|
|
@@ -851,8 +853,81 @@ async function writeFiles(baseDir, files) {
|
|
|
851
853
|
}
|
|
852
854
|
return written;
|
|
853
855
|
}
|
|
856
|
+
/**
|
|
857
|
+
* Does `root`'s `workspaces` field cover `dir`?
|
|
858
|
+
*
|
|
859
|
+
* Declaring workspaces is not enough — a root with `packages/*` does not own an
|
|
860
|
+
* addon written to `addons/crm`, and yarn, npm and pnpm all skip a nested
|
|
861
|
+
* package they were never told about.
|
|
862
|
+
*/
|
|
863
|
+
export function workspaceCovers(root, dir) {
|
|
864
|
+
const relative = relativePath(root, dir).split(sep).join('/');
|
|
865
|
+
if (relative === '' || relative.startsWith('..')) {
|
|
866
|
+
return false;
|
|
867
|
+
}
|
|
868
|
+
let patterns;
|
|
869
|
+
try {
|
|
870
|
+
const manifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'));
|
|
871
|
+
patterns = Array.isArray(manifest.workspaces)
|
|
872
|
+
? manifest.workspaces
|
|
873
|
+
: manifest.workspaces?.packages;
|
|
874
|
+
}
|
|
875
|
+
catch {
|
|
876
|
+
return false;
|
|
877
|
+
}
|
|
878
|
+
if (!Array.isArray(patterns)) {
|
|
879
|
+
return false;
|
|
880
|
+
}
|
|
881
|
+
return patterns.some((pattern) => {
|
|
882
|
+
if (typeof pattern !== 'string') {
|
|
883
|
+
return false;
|
|
884
|
+
}
|
|
885
|
+
const source = pattern
|
|
886
|
+
.split('/')
|
|
887
|
+
.map((segment) => segment === '**'
|
|
888
|
+
? '.*'
|
|
889
|
+
: segment.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '[^/]*'))
|
|
890
|
+
.join('/');
|
|
891
|
+
return new RegExp(`^${source}$`).test(relative);
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
const spawnAddonBuildStep = (command, args, cwd) => {
|
|
895
|
+
const { status, error } = spawnSync(command, args, {
|
|
896
|
+
cwd,
|
|
897
|
+
stdio: 'inherit',
|
|
898
|
+
shell: process.platform === 'win32',
|
|
899
|
+
});
|
|
900
|
+
return { status, error };
|
|
901
|
+
};
|
|
902
|
+
export const buildGeneratedAddon = (addonDir, logger, run = spawnAddonBuildStep) => {
|
|
903
|
+
const { dir: installDir, packageManager } = findInstallRoot(addonDir);
|
|
904
|
+
if (packageManager === 'unknown') {
|
|
905
|
+
logger.error(`Could not tell which package manager owns ${addonDir} — the addon is generated but NOT built. Run install, then the addon's build script, in ${addonDir} before using it.`);
|
|
906
|
+
return false;
|
|
907
|
+
}
|
|
908
|
+
// A root install only reaches the addon when the root's workspace patterns
|
|
909
|
+
// cover it. A root that owns the lockfile but not this package installs
|
|
910
|
+
// nothing for it, so its devDependencies — `@pikku/cli` and `typescript`,
|
|
911
|
+
// which the build script needs — would never arrive.
|
|
912
|
+
const installIn = workspaceCovers(installDir, addonDir)
|
|
913
|
+
? installDir
|
|
914
|
+
: addonDir;
|
|
915
|
+
const steps = [
|
|
916
|
+
[installIn, ['install']],
|
|
917
|
+
[addonDir, ['run', 'build']],
|
|
918
|
+
];
|
|
919
|
+
for (const [cwd, args] of steps) {
|
|
920
|
+
logger.info(`${packageManager} ${args.join(' ')} (${cwd})`);
|
|
921
|
+
const result = run(packageManager, args, cwd);
|
|
922
|
+
if (result.status !== 0) {
|
|
923
|
+
logger.error(`${packageManager} ${args.join(' ')} failed in ${cwd}: ${result.error?.message ?? `exit ${result.status}`}`);
|
|
924
|
+
return false;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
return true;
|
|
928
|
+
};
|
|
854
929
|
export const pikkuNewAddon = pikkuSessionlessFunc({
|
|
855
|
-
func: async ({ logger, config }, { name, displayName, description, category = 'General', dir, secret = false, variable = false, oauth = false, credential, test = true, openapi, authConfig, mcp = false, camelCase = false, }) => {
|
|
930
|
+
func: async ({ logger, config }, { name, displayName, description, category = 'General', dir, secret = false, variable = false, oauth = false, credential, test = true, openapi, authConfig, mcp = false, camelCase = false, build = true, }) => {
|
|
856
931
|
name = sanitizeAddonName(name);
|
|
857
932
|
if (!/^[a-z][a-z0-9_-]*$/.test(name)) {
|
|
858
933
|
logger.error(`Invalid addon name "${name}": must start with a lowercase letter and contain only lowercase alphanumerics, hyphens, and underscores`);
|
|
@@ -949,6 +1024,9 @@ export const pikkuNewAddon = pikkuSessionlessFunc({
|
|
|
949
1024
|
for (const f of written) {
|
|
950
1025
|
logger.debug({ message: ` ${f}`, type: 'success' });
|
|
951
1026
|
}
|
|
1027
|
+
if (build && !buildGeneratedAddon(addonDir, logger)) {
|
|
1028
|
+
process.exit(1);
|
|
1029
|
+
}
|
|
952
1030
|
console.log(addonDir);
|
|
953
1031
|
},
|
|
954
1032
|
});
|
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
* config and write through it, which provisioned a local stage correctly and
|
|
10
10
|
* silently provisioned the wrong database for every other environment.
|
|
11
11
|
*
|
|
12
|
-
* So the deployment provisions itself: an app
|
|
13
|
-
* `@pikku/better-auth
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
* So the deployment provisions itself: an app hands its personas to
|
|
13
|
+
* `pikkuFabric` from `@pikku/better-auth`, and the plugin creates a missing one
|
|
14
|
+
* on the operator handshake that asks for it, where the database connection and
|
|
15
|
+
* better-auth's own adapter are both already open. What is left here is the
|
|
16
|
+
* half that needs no database — the
|
|
16
17
|
* declaration, and the environment rule applied to it — which is what tells you
|
|
17
18
|
* before a deploy whether the accounts you expect will appear.
|
|
18
19
|
*/
|
|
@@ -12,10 +12,11 @@ import { resolvePersonas } from '../../utils/resolve-personas.js';
|
|
|
12
12
|
* config and write through it, which provisioned a local stage correctly and
|
|
13
13
|
* silently provisioned the wrong database for every other environment.
|
|
14
14
|
*
|
|
15
|
-
* So the deployment provisions itself: an app
|
|
16
|
-
* `@pikku/better-auth
|
|
17
|
-
*
|
|
18
|
-
*
|
|
15
|
+
* So the deployment provisions itself: an app hands its personas to
|
|
16
|
+
* `pikkuFabric` from `@pikku/better-auth`, and the plugin creates a missing one
|
|
17
|
+
* on the operator handshake that asks for it, where the database connection and
|
|
18
|
+
* better-auth's own adapter are both already open. What is left here is the
|
|
19
|
+
* half that needs no database — the
|
|
19
20
|
* declaration, and the environment rule applied to it — which is what tells you
|
|
20
21
|
* before a deploy whether the accounts you expect will appear.
|
|
21
22
|
*/
|
|
@@ -65,6 +66,6 @@ export const personaSync = pikkuSessionlessFunc({
|
|
|
65
66
|
for (const refusal of skipped) {
|
|
66
67
|
logger.info(` skipped: ${refusal}`);
|
|
67
68
|
}
|
|
68
|
-
logger.info(" Provisioning runs in the deployment:
|
|
69
|
+
logger.info(" Provisioning runs in the deployment: pass `personas: { personas: personaConfigs, environments: personaEnvironments }` from the generated personas file to `pikkuFabric` from '@pikku/better-auth'.");
|
|
69
70
|
},
|
|
70
71
|
});
|
|
@@ -4,6 +4,7 @@ import { pikkuSessionlessFunc } from '#pikku/function';
|
|
|
4
4
|
import { createHttpPersonas, deriveActorSecret, personaEnvironmentRefusal, roleMismatchMessage, verifyPersonaRoles, } from '@pikku/core/persona';
|
|
5
5
|
import { personaVirtualUserTarget, runVirtualUser, catalogueClassification, DISPOSITIONS, prepareVirtualUserRun, } from '@pikku/core/virtual-user';
|
|
6
6
|
import { getSingletonServices, setSingletonServices } from '@pikku/core/state';
|
|
7
|
+
import { PikkuError } from '@pikku/core/errors';
|
|
7
8
|
import { resolvePersonas } from '../../utils/resolve-personas.js';
|
|
8
9
|
import { ACTOR_SECRET_VARIABLE, PERSONA_SECRETS_VARIABLE, resolvePersonaCredentials, } from '../../utils/persona-credentials.js';
|
|
9
10
|
import { resolveEnvironment } from './environment.js';
|
|
@@ -108,7 +109,7 @@ export const personaRun = pikkuSessionlessFunc({
|
|
|
108
109
|
agentsMeta: state.agents?.agentsMeta ?? {},
|
|
109
110
|
});
|
|
110
111
|
if (catalogue.length === 0) {
|
|
111
|
-
throw new
|
|
112
|
+
throw new PikkuError('This project exposes no RPCs, so there is nothing for a virtual user to do.');
|
|
112
113
|
}
|
|
113
114
|
const signedIn = createHttpPersonas({
|
|
114
115
|
apiUrl: env.apiUrl,
|
|
@@ -132,7 +133,10 @@ export const personaRun = pikkuSessionlessFunc({
|
|
|
132
133
|
else {
|
|
133
134
|
const message = roleMismatchMessage(verifyPersonaRoles(personaId, persona.roles, actual));
|
|
134
135
|
if (message) {
|
|
135
|
-
|
|
136
|
+
// A refusal, not a crash: `PikkuError` is what tells the CLI to print
|
|
137
|
+
// the message on its own, since the seed drift it names is the whole
|
|
138
|
+
// finding and the frames underneath it are noise.
|
|
139
|
+
throw new PikkuError(message);
|
|
136
140
|
}
|
|
137
141
|
}
|
|
138
142
|
}
|