@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
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PersonaDefinitions } from '@pikku/core/persona';
|
|
2
|
+
export interface SerializePersonasOptions {
|
|
3
|
+
definitions: PersonaDefinitions;
|
|
4
|
+
/** Relative import path to the generated roles file. */
|
|
5
|
+
rolesImportPath: string;
|
|
6
|
+
/** Keys of `environments` in pikku.config.json. */
|
|
7
|
+
environmentNames: string[];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Generates the `PersonaId` union and a `definePersonas` whose `roles` are
|
|
11
|
+
* checked against the declared system roles.
|
|
12
|
+
*
|
|
13
|
+
* The wrapper is why this is generated rather than re-exported: `roles` typed
|
|
14
|
+
* as `string[]` would let a persona name a role nobody declared, and the
|
|
15
|
+
* failure — a scatter of 403s in a run days later — looks nothing like the
|
|
16
|
+
* mistake. Typed as `SystemRoleName[]`, it is a red squiggle in the editor.
|
|
17
|
+
*/
|
|
18
|
+
export declare const serializePersonasTypes: ({ definitions, rolesImportPath, environmentNames, }: SerializePersonasOptions) => string;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const quote = (value) => `'${value.replace(/'/g, "\\'")}'`;
|
|
2
|
+
/**
|
|
3
|
+
* Generates the `PersonaId` union and a `definePersonas` whose `roles` are
|
|
4
|
+
* checked against the declared system roles.
|
|
5
|
+
*
|
|
6
|
+
* The wrapper is why this is generated rather than re-exported: `roles` typed
|
|
7
|
+
* as `string[]` would let a persona name a role nobody declared, and the
|
|
8
|
+
* failure — a scatter of 403s in a run days later — looks nothing like the
|
|
9
|
+
* mistake. Typed as `SystemRoleName[]`, it is a red squiggle in the editor.
|
|
10
|
+
*/
|
|
11
|
+
export const serializePersonasTypes = ({ definitions, rolesImportPath, environmentNames, }) => {
|
|
12
|
+
const ids = [...new Set(definitions.map((d) => d.id))].sort();
|
|
13
|
+
const environmentUnion = environmentNames.length > 0
|
|
14
|
+
? `\n${[...environmentNames].sort().map((name) => ` | ${quote(name)}`).join('\n')}`
|
|
15
|
+
: ' never';
|
|
16
|
+
const union = ids.length > 0
|
|
17
|
+
? `\n${ids.map((id) => ` | ${quote(id)}`).join('\n')}`
|
|
18
|
+
: ' never';
|
|
19
|
+
const runnable = definitions
|
|
20
|
+
.filter((d) => d.runnable)
|
|
21
|
+
.map((d) => d.id)
|
|
22
|
+
.sort();
|
|
23
|
+
const runnableUnion = runnable.length > 0
|
|
24
|
+
? `\n${runnable.map((id) => ` | ${quote(id)}`).join('\n')}`
|
|
25
|
+
: ' never';
|
|
26
|
+
return `/**
|
|
27
|
+
* This file was generated by the @pikku/cli
|
|
28
|
+
*/
|
|
29
|
+
import { definePersonas as definePersonasCore } from '@pikku/core/persona'
|
|
30
|
+
import type { CorePersona, PersonaMeta, PersonasMeta } from '@pikku/core/persona'
|
|
31
|
+
import type { SystemRoleName } from '${rolesImportPath}'
|
|
32
|
+
import definitions from './pikku-personas-meta.gen.json' with { type: 'json' }
|
|
33
|
+
|
|
34
|
+
/** Every declared persona. */
|
|
35
|
+
export type PersonaId =${union}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The personas a virtual user can actually be.
|
|
39
|
+
*
|
|
40
|
+
* Excludes anyone whose only login is a provider account — driving a consent
|
|
41
|
+
* screen needs a human — and anyone declared \`runnable: false\`, who exists to
|
|
42
|
+
* be acted upon rather than to act.
|
|
43
|
+
*/
|
|
44
|
+
export type RunnablePersonaId =${runnableUnion}
|
|
45
|
+
|
|
46
|
+
/** Every environment configured in pikku.config.json. */
|
|
47
|
+
export type EnvironmentName =${environmentUnion}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A persona whose roles are checked against \`defineSystemRole\` and whose
|
|
51
|
+
* environments are checked against the config.
|
|
52
|
+
*
|
|
53
|
+
* Omitting \`environments\` means every environment except the ones flagged
|
|
54
|
+
* \`production: true\`. Naming a production one additionally requires
|
|
55
|
+
* \`disposition: 'accountable'\`, which the type cannot express and \`pikku\`
|
|
56
|
+
* refuses at build time.
|
|
57
|
+
*/
|
|
58
|
+
export type TypedPersona = Omit<CorePersona, 'roles' | 'environments'> & {
|
|
59
|
+
roles?: SystemRoleName[]
|
|
60
|
+
environments?: EnvironmentName[]
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Declare the people who use this application.
|
|
65
|
+
*
|
|
66
|
+
* A persona while running is a virtual user; there is no second declaration.
|
|
67
|
+
*/
|
|
68
|
+
export const definePersonas = (personas: Record<string, TypedPersona>): void =>
|
|
69
|
+
definePersonasCore(personas)
|
|
70
|
+
|
|
71
|
+
/** Declared personas, keyed by id. Read by the console and \`pikku persona\`. */
|
|
72
|
+
export const PERSONAS: PersonasMeta = definitions as unknown as PersonasMeta
|
|
73
|
+
|
|
74
|
+
export const PERSONA_LIST: PersonaMeta[] = Object.values(PERSONAS)
|
|
75
|
+
`;
|
|
76
|
+
};
|
|
@@ -4,6 +4,7 @@ import { writeFileInDir } from '../../../utils/file-writer.js';
|
|
|
4
4
|
import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
|
|
5
5
|
import { removeLegacyScaffoldFile } from '../../../utils/remove-legacy-scaffold-file.js';
|
|
6
6
|
import { serializeEventsScaffold } from './serialize-events-scaffold.js';
|
|
7
|
+
import { resolveScaffoldFeature } from '../../../utils/resolve-scaffold-feature.js';
|
|
7
8
|
export const pikkuEventsScaffold = pikkuSessionlessFunc({
|
|
8
9
|
func: async ({ logger, config }) => {
|
|
9
10
|
if (!config.scaffold?.events ||
|
|
@@ -15,7 +16,7 @@ export const pikkuEventsScaffold = pikkuSessionlessFunc({
|
|
|
15
16
|
});
|
|
16
17
|
return false;
|
|
17
18
|
}
|
|
18
|
-
const authRequired = config.scaffold.events
|
|
19
|
+
const authRequired = resolveScaffoldFeature('events', config.scaffold.events).auth;
|
|
19
20
|
const pikkuTypesImportPath = getFileImportRelativePath(config.eventsChannelFile, config.typesDeclarationFile, config.packageMappings);
|
|
20
21
|
const { schemas, functions } = serializeEventsScaffold(authRequired, pikkuTypesImportPath);
|
|
21
22
|
await writeFileInDir(logger, config.eventsSchemasFile, schemas);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const pikkuRoles: 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,33 @@
|
|
|
1
|
+
import { pikkuSessionlessFunc } from '#pikku';
|
|
2
|
+
import { writeFileInDir } from '../../../utils/file-writer.js';
|
|
3
|
+
import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
|
|
4
|
+
import { serializeRolesTypes } from './serialize-roles-types.js';
|
|
5
|
+
import { validateAndBuildSystemRoleDefinitionsMeta } from '@pikku/core/role';
|
|
6
|
+
export const pikkuRoles = pikkuSessionlessFunc({
|
|
7
|
+
func: async ({ logger, config, getInspectorState }, data) => {
|
|
8
|
+
const { rolesFile, rolesMetaJsonFile } = config;
|
|
9
|
+
if (!rolesFile) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
// Same cold-start reasoning as Scopes: on a bare .pikku this runs before
|
|
13
|
+
// pikku-types.gen.ts exists, so it takes the zero state. The file only has
|
|
14
|
+
// to exist so personas can import SystemRoleName; the real Roles step
|
|
15
|
+
// regenerates it with the declarations once setup has run.
|
|
16
|
+
const bootstrap = data?.bootstrap ?? false;
|
|
17
|
+
const state = await getInspectorState(false, bootstrap, bootstrap);
|
|
18
|
+
const content = serializeRolesTypes({
|
|
19
|
+
definitions: state.systemRoles.definitions,
|
|
20
|
+
});
|
|
21
|
+
await writeFileInDir(logger, rolesFile, content);
|
|
22
|
+
if (rolesMetaJsonFile) {
|
|
23
|
+
const meta = validateAndBuildSystemRoleDefinitionsMeta(state.systemRoles.definitions);
|
|
24
|
+
await writeFileInDir(logger, rolesMetaJsonFile, JSON.stringify(meta, null, 2));
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
middleware: [
|
|
28
|
+
logCommandInfoAndTime({
|
|
29
|
+
commandStart: 'Creating PikkuRoles types',
|
|
30
|
+
commandEnd: 'Created PikkuRoles types',
|
|
31
|
+
}),
|
|
32
|
+
],
|
|
33
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SystemRoleDefinitions } from '@pikku/core/role';
|
|
2
|
+
export interface SerializeRolesOptions {
|
|
3
|
+
definitions: SystemRoleDefinitions;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Generates the `SystemRoleName` union and role metadata from
|
|
7
|
+
* `defineSystemRole` declarations.
|
|
8
|
+
*
|
|
9
|
+
* The union is what makes a persona's `roles: ['buyer']` checkable. Custom
|
|
10
|
+
* roles are deliberately absent: an admin can delete one from the console, so
|
|
11
|
+
* a persona pinned to it would silently stop testing what it claims to — the
|
|
12
|
+
* failure would be a scatter of 403s rather than a build error.
|
|
13
|
+
*/
|
|
14
|
+
export declare const serializeRolesTypes: ({ definitions }: SerializeRolesOptions) => string;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const quote = (value) => `'${value.replace(/'/g, "\\'")}'`;
|
|
2
|
+
/**
|
|
3
|
+
* Generates the `SystemRoleName` union and role metadata from
|
|
4
|
+
* `defineSystemRole` declarations.
|
|
5
|
+
*
|
|
6
|
+
* The union is what makes a persona's `roles: ['buyer']` checkable. Custom
|
|
7
|
+
* roles are deliberately absent: an admin can delete one from the console, so
|
|
8
|
+
* a persona pinned to it would silently stop testing what it claims to — the
|
|
9
|
+
* failure would be a scatter of 403s rather than a build error.
|
|
10
|
+
*/
|
|
11
|
+
export const serializeRolesTypes = ({ definitions }) => {
|
|
12
|
+
const names = [...new Set(definitions.map((d) => d.name))].sort();
|
|
13
|
+
const union = names.length > 0
|
|
14
|
+
? `\n${names.map((name) => ` | ${quote(name)}`).join('\n')}`
|
|
15
|
+
: ' never';
|
|
16
|
+
return `/**
|
|
17
|
+
* This file was generated by the @pikku/cli
|
|
18
|
+
*/
|
|
19
|
+
import type { SystemRole, SystemRoleDefinitionsMeta } from '@pikku/core/role'
|
|
20
|
+
import { flattenSystemRoleDefinitions } from '@pikku/core/role'
|
|
21
|
+
import definitions from './pikku-roles-meta.gen.json' with { type: 'json' }
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Every role that ships with this application.
|
|
25
|
+
*
|
|
26
|
+
* Roles an admin composes in the console are not here and cannot be: they do
|
|
27
|
+
* not exist at build time, and can be deleted after it.
|
|
28
|
+
*/
|
|
29
|
+
export type SystemRoleName =${union}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The declared role set, for a ScopeService to sync into its store.
|
|
33
|
+
*
|
|
34
|
+
* Derived from the metadata sidecar rather than inlined, so the import above
|
|
35
|
+
* forces tsc to emit the .json alongside this file — an addon publishes only
|
|
36
|
+
* its compiled output, and a host reads that .json to merge the addon's roles
|
|
37
|
+
* into its own union.
|
|
38
|
+
*
|
|
39
|
+
* Additive on removal: a deleted declaration leaves an inert row rather than
|
|
40
|
+
* revoking everyone's grant on deploy. Use \`pikku roles prune\` to remove them.
|
|
41
|
+
*/
|
|
42
|
+
export const SYSTEM_ROLES: SystemRole[] = flattenSystemRoleDefinitions(
|
|
43
|
+
Object.values(definitions as SystemRoleDefinitionsMeta)
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
/** Declared roles, keyed by name. Rendered by the console when granting. */
|
|
47
|
+
export const SYSTEM_ROLES_META: Record<string, SystemRole> = Object.fromEntries(
|
|
48
|
+
SYSTEM_ROLES.map((role) => [role.name, role])
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
/** Whether a role name is declared in code, and therefore not editable. */
|
|
52
|
+
export const isSystemRole = (name: string): boolean =>
|
|
53
|
+
Object.prototype.hasOwnProperty.call(SYSTEM_ROLES_META, name)
|
|
54
|
+
`;
|
|
55
|
+
};
|
|
@@ -4,6 +4,7 @@ import { writeFileInDir } from '../../../utils/file-writer.js';
|
|
|
4
4
|
import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
|
|
5
5
|
import { removeLegacyScaffoldFile } from '../../../utils/remove-legacy-scaffold-file.js';
|
|
6
6
|
import { serializePublicRPC } from './serialize-public-rpc.js';
|
|
7
|
+
import { resolveScaffoldFeature } from '../../../utils/resolve-scaffold-feature.js';
|
|
7
8
|
export const pikkuPublicRPC = pikkuSessionlessFunc({
|
|
8
9
|
func: async ({ logger, config, variables }) => {
|
|
9
10
|
const deployCodegenFlag = await variables.get('PIKKU_DEPLOY_CODEGEN');
|
|
@@ -12,7 +13,7 @@ export const pikkuPublicRPC = pikkuSessionlessFunc({
|
|
|
12
13
|
}
|
|
13
14
|
if (config.scaffold?.rpc && config.publicRpcSchemasFile) {
|
|
14
15
|
const pathToPikkuTypes = getFileImportRelativePath(config.publicRpcFile, config.typesDeclarationFile, config.packageMappings);
|
|
15
|
-
const { schemas, functions } = serializePublicRPC(pathToPikkuTypes, config.scaffold.rpc
|
|
16
|
+
const { schemas, functions } = serializePublicRPC(pathToPikkuTypes, resolveScaffoldFeature('rpc', config.scaffold.rpc).auth, config.globalHTTPPrefix || '');
|
|
16
17
|
await writeFileInDir(logger, config.publicRpcSchemasFile, schemas);
|
|
17
18
|
await writeFileInDir(logger, config.publicRpcFile, functions);
|
|
18
19
|
await removeLegacyScaffoldFile(config.publicRpcFile);
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* scenario runner can reach it over `/rpc/<name>` exactly as before.
|
|
4
4
|
*
|
|
5
5
|
* They are registered sessionless: `auth` decides whether a session is
|
|
6
|
-
* *required*, and a sessioned function would demand one regardless of the flag
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* *required*, and a sessioned function would demand one regardless of the flag.
|
|
7
|
+
* `scaffold.scenarios: true` therefore requires a session; `{ auth: false }` is
|
|
8
|
+
* what opens them.
|
|
9
9
|
*/
|
|
10
10
|
export declare const registerScenarioInstrumentation: (requireAuth: boolean) => void;
|
|
@@ -79,9 +79,9 @@ const instrumentation = {
|
|
|
79
79
|
* scenario runner can reach it over `/rpc/<name>` exactly as before.
|
|
80
80
|
*
|
|
81
81
|
* They are registered sessionless: `auth` decides whether a session is
|
|
82
|
-
* *required*, and a sessioned function would demand one regardless of the flag
|
|
83
|
-
*
|
|
84
|
-
*
|
|
82
|
+
* *required*, and a sessioned function would demand one regardless of the flag.
|
|
83
|
+
* `scaffold.scenarios: true` therefore requires a session; `{ auth: false }` is
|
|
84
|
+
* what opens them.
|
|
85
85
|
*/
|
|
86
86
|
export const registerScenarioInstrumentation = (requireAuth) => {
|
|
87
87
|
const meta = pikkuState(null, 'function', 'meta');
|
|
@@ -3,7 +3,7 @@ export interface SerializeScopesOptions {
|
|
|
3
3
|
definitions: ScopeDefinitions;
|
|
4
4
|
}
|
|
5
5
|
/**
|
|
6
|
-
* Generates the `ScopeId` union and scope metadata from `
|
|
6
|
+
* Generates the `ScopeId` union and scope metadata from `defineScope`
|
|
7
7
|
* declarations.
|
|
8
8
|
*
|
|
9
9
|
* The union carries every declared node plus a wildcard form for each node that
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { flattenScopeDefinitions } from '@pikku/core/scope';
|
|
2
2
|
const quote = (value) => `'${value.replace(/'/g, "\\'")}'`;
|
|
3
3
|
/**
|
|
4
|
-
* Generates the `ScopeId` union and scope metadata from `
|
|
4
|
+
* Generates the `ScopeId` union and scope metadata from `defineScope`
|
|
5
5
|
* declarations.
|
|
6
6
|
*
|
|
7
7
|
* The union carries every declared node plus a wildcard form for each node that
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { validateAndBuildSecretDefinitionsMeta } from '@pikku/core/secret';
|
|
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 serializeSecretsTypes = ({ definitions, schemaLookup, secretsFile, packageMappings, }) => {
|
|
4
11
|
const secrets = validateAndBuildSecretDefinitionsMeta(definitions, schemaLookup);
|
|
5
12
|
const credentialEntries = Object.entries(secrets);
|
|
@@ -13,8 +20,8 @@ export const serializeSecretsTypes = ({ definitions, schemaLookup, secretsFile,
|
|
|
13
20
|
needsOAuth2Types = true;
|
|
14
21
|
mapEntries.push(` '${meta.secretId}': OAuth2AppCredential`);
|
|
15
22
|
mapEntries.push(` '${meta.oauth2.tokenSecretId}': OAuth2Token`);
|
|
16
|
-
metaEntries.push(` '${meta.secretId}': { name: '${name}', displayName:
|
|
17
|
-
metaEntries.push(` '${meta.oauth2.tokenSecretId}': { name: '${name}_tokens', displayName:
|
|
23
|
+
metaEntries.push(` '${meta.secretId}': { name: '${name}', displayName: ${literal(meta.displayName)}, oauth2: { tokenSecretId: '${meta.oauth2.tokenSecretId}' } }`);
|
|
24
|
+
metaEntries.push(` '${meta.oauth2.tokenSecretId}': { name: '${name}_tokens', displayName: ${literal(`${meta.displayName} Tokens`)} }`);
|
|
18
25
|
}
|
|
19
26
|
else if (meta.schema && typeof meta.schema === 'string') {
|
|
20
27
|
const schemaRef = schemaLookup.get(meta.schema);
|
|
@@ -25,7 +32,7 @@ export const serializeSecretsTypes = ({ definitions, schemaLookup, secretsFile,
|
|
|
25
32
|
}
|
|
26
33
|
schemaImports.get(schemaRef.sourceFile).add(schemaRef.variableName);
|
|
27
34
|
mapEntries.push(` '${meta.secretId}': z.infer<typeof ${schemaRef.variableName}>`);
|
|
28
|
-
metaEntries.push(` '${meta.secretId}': { name: '${name}', displayName:
|
|
35
|
+
metaEntries.push(` '${meta.secretId}': { name: '${name}', displayName: ${literal(meta.displayName)} }`);
|
|
29
36
|
}
|
|
30
37
|
}
|
|
31
38
|
}
|
|
@@ -3,6 +3,7 @@ import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
|
|
|
3
3
|
import { writeFileInDir } from '../../../utils/file-writer.js';
|
|
4
4
|
import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
|
|
5
5
|
import { serializeUserAdminFunctions } from './serialize-user-admin-functions.js';
|
|
6
|
+
import { resolveScaffoldFeature } from '../../../utils/resolve-scaffold-feature.js';
|
|
6
7
|
export const pikkuUserAdminFunctions = pikkuSessionlessFunc({
|
|
7
8
|
func: async ({ logger, config, getInspectorState }) => {
|
|
8
9
|
if (!config.scaffold?.userAdmin ||
|
|
@@ -35,7 +36,7 @@ export const pikkuUserAdminFunctions = pikkuSessionlessFunc({
|
|
|
35
36
|
`Then re-run codegen. Or remove "scaffold.userAdmin" from pikku.config.json.`);
|
|
36
37
|
}
|
|
37
38
|
const pathToPikkuTypes = getFileImportRelativePath(config.userAdminFunctionsFile, config.typesDeclarationFile, config.packageMappings);
|
|
38
|
-
const { schemas, functions } = serializeUserAdminFunctions(pathToPikkuTypes, config.scaffold.userAdmin
|
|
39
|
+
const { schemas, functions } = serializeUserAdminFunctions(pathToPikkuTypes, resolveScaffoldFeature('userAdmin', config.scaffold.userAdmin).auth);
|
|
39
40
|
await writeFileInDir(logger, config.userAdminSchemasFile, schemas);
|
|
40
41
|
await writeFileInDir(logger, config.userAdminFunctionsFile, functions);
|
|
41
42
|
return true;
|
|
@@ -86,7 +86,7 @@ export const Success = z.object({
|
|
|
86
86
|
* Auto-generated user management functions
|
|
87
87
|
* Do not edit manually - regenerate with 'npx pikku'
|
|
88
88
|
*/
|
|
89
|
-
import { pikkuFunc,
|
|
89
|
+
import { pikkuFunc, defineScope } from '${pathToPikkuTypes}'
|
|
90
90
|
import { callAdminApi } from '@pikku/better-auth'
|
|
91
91
|
import {
|
|
92
92
|
CreateUserInput,
|
|
@@ -103,7 +103,7 @@ import {
|
|
|
103
103
|
// this is the whole \`admin\` tree — not just the leaves gated below. It must stay
|
|
104
104
|
// byte-identical to ADMIN_SCOPE_TREE in @pikku/better-auth and to the copy in
|
|
105
105
|
// @pikku/addon-console, or codegen fails with conflicting declarations.
|
|
106
|
-
|
|
106
|
+
defineScope({
|
|
107
107
|
admin: {
|
|
108
108
|
displayName: 'Administration',
|
|
109
109
|
description: 'Capabilities that act on the application as a whole',
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { validateAndBuildVariableDefinitionsMeta } from '@pikku/core/variable';
|
|
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 serializeVariablesTypes = ({ definitions, schemaLookup, variablesFile, packageMappings, }) => {
|
|
4
11
|
const variables = validateAndBuildVariableDefinitionsMeta(definitions, schemaLookup);
|
|
5
12
|
const variableEntries = Object.entries(variables);
|
|
@@ -17,7 +24,7 @@ export const serializeVariablesTypes = ({ definitions, schemaLookup, variablesFi
|
|
|
17
24
|
}
|
|
18
25
|
schemaImports.get(schemaRef.sourceFile).add(schemaRef.variableName);
|
|
19
26
|
mapEntries.push(` '${meta.variableId}': z.infer<typeof ${schemaRef.variableName}>`);
|
|
20
|
-
metaEntries.push(` '${meta.variableId}': { name: '${name}', displayName:
|
|
27
|
+
metaEntries.push(` '${meta.variableId}': { name: '${name}', displayName: ${literal(meta.displayName)} }`);
|
|
21
28
|
}
|
|
22
29
|
}
|
|
23
30
|
}
|
|
@@ -4,13 +4,14 @@ import { writeFileInDir } from '../../../utils/file-writer.js';
|
|
|
4
4
|
import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
|
|
5
5
|
import { removeLegacyScaffoldFile } from '../../../utils/remove-legacy-scaffold-file.js';
|
|
6
6
|
import { serializeWorkflowRoutes } from './serialize-workflow-routes.js';
|
|
7
|
+
import { resolveScaffoldFeature } from '../../../utils/resolve-scaffold-feature.js';
|
|
7
8
|
export const pikkuWorkflowRoutes = pikkuSessionlessFunc({
|
|
8
9
|
func: async ({ logger, config }) => {
|
|
9
10
|
if (config.scaffold?.workflow &&
|
|
10
11
|
config.workflowRoutesFile &&
|
|
11
12
|
config.workflowRoutesSchemasFile) {
|
|
12
13
|
const pathToPikkuTypes = getFileImportRelativePath(config.workflowRoutesFile, config.typesDeclarationFile, config.packageMappings);
|
|
13
|
-
const { schemas, functions } = serializeWorkflowRoutes(pathToPikkuTypes, config.scaffold?.workflow
|
|
14
|
+
const { schemas, functions } = serializeWorkflowRoutes(pathToPikkuTypes, resolveScaffoldFeature('workflow', config.scaffold?.workflow).auth);
|
|
14
15
|
await writeFileInDir(logger, config.workflowRoutesSchemasFile, schemas);
|
|
15
16
|
await writeFileInDir(logger, config.workflowRoutesFile, functions);
|
|
16
17
|
await removeLegacyScaffoldFile(config.workflowRoutesFile);
|
|
@@ -3,8 +3,8 @@ import { ErrorCode } from '@pikku/inspector';
|
|
|
3
3
|
import { writeFileInDir } from '../../../utils/file-writer.js';
|
|
4
4
|
import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
|
|
5
5
|
import { serializeWorkflowTypes } from './serialize-workflow-types.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { serializePersonas } from './serialize-personas.js';
|
|
7
|
+
import { resolvePersonas } from '../../../utils/resolve-personas.js';
|
|
8
8
|
import { serializeWorkflowRegistration } from './serialize-workflow-registration.js';
|
|
9
9
|
import { serializeWorkflowMap } from './serialize-workflow-map.js';
|
|
10
10
|
import { serializeScenarioStepMap } from './serialize-scenario-step-map.js';
|
|
@@ -89,21 +89,21 @@ export const pikkuWorkflow = pikkuSessionlessFunc({
|
|
|
89
89
|
const agentMapImportPath = getFileImportRelativePath(workflowTypesFile, config.agentMapDeclarationFile, packageMappings);
|
|
90
90
|
const scopesImportPath = getFileImportRelativePath(workflowTypesFile, config.scopesFile, packageMappings);
|
|
91
91
|
const scenarioStepMapImportPath = getFileImportRelativePath(workflowTypesFile, config.scenarioStepMapDeclarationFile, packageMappings);
|
|
92
|
-
const
|
|
93
|
-
await writeFileInDir(logger, workflowTypesFile, serializeWorkflowTypes(functionTypesImportPath, rpcMapImportPath, workflowMapImportPath, agentMapImportPath, scopesImportPath, scenarioStepMapImportPath,
|
|
92
|
+
const personasImportPath = getFileImportRelativePath(workflowTypesFile, config.personasWiringFile, packageMappings);
|
|
93
|
+
await writeFileInDir(logger, workflowTypesFile, serializeWorkflowTypes(functionTypesImportPath, rpcMapImportPath, workflowMapImportPath, agentMapImportPath, scopesImportPath, scenarioStepMapImportPath, personasImportPath));
|
|
94
94
|
// Rides the workflow command rather than getting its own codegen node, so
|
|
95
95
|
// it can't drift out of the two hand-maintained ordering lists.
|
|
96
96
|
await writeFileInDir(logger, config.scenarioStepMapDeclarationFile, serializeScenarioStepMap(logger, config.scenarioStepMapDeclarationFile, packageMappings, typesMap, functionState.meta));
|
|
97
|
-
// Written even
|
|
98
|
-
// resolvable import for the generated function types.
|
|
99
|
-
const
|
|
97
|
+
// Written even when nobody declared a persona, so `TypedPersonas` is always
|
|
98
|
+
// a resolvable import for the generated function types.
|
|
99
|
+
const personas = resolvePersonas(visitState.personas.definitions, config.scenarios?.emailDomain);
|
|
100
100
|
{
|
|
101
|
-
const agentMapImportPath = getFileImportRelativePath(config.
|
|
102
|
-
const exposedRpcMapImportPath = getFileImportRelativePath(config.
|
|
103
|
-
await writeFileInDir(logger, config.
|
|
104
|
-
// Fixed path
|
|
105
|
-
//
|
|
106
|
-
await writeFileInDir(logger, join(config.outDir, 'workflow', '
|
|
101
|
+
const agentMapImportPath = getFileImportRelativePath(config.personasWiringFile, config.agentMapDeclarationFile, packageMappings);
|
|
102
|
+
const exposedRpcMapImportPath = getFileImportRelativePath(config.personasWiringFile, config.rpcMapDeclarationFile, packageMappings);
|
|
103
|
+
await writeFileInDir(logger, config.personasWiringFile, serializePersonas(personas, agentMapImportPath, exposedRpcMapImportPath));
|
|
104
|
+
// Fixed path getPersonasMeta() reads; kept out of workflow/meta, which
|
|
105
|
+
// getWorkflowMeta() globs as workflows.
|
|
106
|
+
await writeFileInDir(logger, join(config.outDir, 'workflow', 'personas.gen.json'), JSON.stringify(personas, null, 2));
|
|
107
107
|
}
|
|
108
108
|
// Fixed path getFeaturesMeta() reads. Written even when empty so the
|
|
109
109
|
// console can tell "no features declared" from "meta not generated yet".
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ResolvedPersona } from '@pikku/core/services';
|
|
2
|
+
/**
|
|
3
|
+
* The runtime half of `definePersonas()`.
|
|
4
|
+
*
|
|
5
|
+
* Generated rather than re-exported because the addresses are computed: nobody
|
|
6
|
+
* writes one down, and a seed, a scenario run and a virtual-user run all have
|
|
7
|
+
* to arrive at the same one. Baking them here is what makes that a single fact
|
|
8
|
+
* rather than three implementations of the same rule.
|
|
9
|
+
*/
|
|
10
|
+
export declare const serializePersonas: (personas: Record<string, ResolvedPersona>, agentMapImportPath: string, rpcMapImportPath: string) => string;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The runtime half of `definePersonas()`.
|
|
3
|
+
*
|
|
4
|
+
* Generated rather than re-exported because the addresses are computed: nobody
|
|
5
|
+
* writes one down, and a seed, a scenario run and a virtual-user run all have
|
|
6
|
+
* to arrive at the same one. Baking them here is what makes that a single fact
|
|
7
|
+
* rather than three implementations of the same rule.
|
|
8
|
+
*/
|
|
9
|
+
export const serializePersonas = (personas, agentMapImportPath, rpcMapImportPath) => {
|
|
10
|
+
return `/** Personas declared with definePersonas() */
|
|
11
|
+
import { createHttpPersonas } from '@pikku/core/persona'
|
|
12
|
+
import type {
|
|
13
|
+
HttpPersonasConfig,
|
|
14
|
+
ScenarioPersona,
|
|
15
|
+
ResolvedPersona,
|
|
16
|
+
} from '@pikku/core/services'
|
|
17
|
+
import type { AgentMap } from '${agentMapImportPath}'
|
|
18
|
+
import type { FlattenedRPCMap } from '${rpcMapImportPath}'
|
|
19
|
+
|
|
20
|
+
export const personaConfigs = ${JSON.stringify(personas, null, 2)} as const satisfies Record<string, ResolvedPersona>
|
|
21
|
+
|
|
22
|
+
export type PersonaName = keyof typeof personaConfigs
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The same personas as a list, widened to \`ResolvedPersona\`. Iterating
|
|
26
|
+
* \`personaConfigs\` directly yields the literal type of each entry, on which an
|
|
27
|
+
* optional field a persona did not declare does not exist — so a seed reading
|
|
28
|
+
* \`roles\` off every persona needs this instead.
|
|
29
|
+
*/
|
|
30
|
+
export const personaList: ResolvedPersona[] = Object.values(personaConfigs)
|
|
31
|
+
|
|
32
|
+
export type AgentName = keyof AgentMap & string
|
|
33
|
+
export type TypedPersonas = Record<
|
|
34
|
+
PersonaName,
|
|
35
|
+
ScenarioPersona<AgentName, FlattenedRPCMap>
|
|
36
|
+
>
|
|
37
|
+
|
|
38
|
+
export const createPersonas = (
|
|
39
|
+
options: Omit<HttpPersonasConfig, 'personas'>
|
|
40
|
+
): TypedPersonas =>
|
|
41
|
+
createHttpPersonas({
|
|
42
|
+
...options,
|
|
43
|
+
personas: personaConfigs,
|
|
44
|
+
}) as TypedPersonas
|
|
45
|
+
`;
|
|
46
|
+
};
|
|
@@ -9,10 +9,19 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { serializeImportMap } from '../../../utils/serialize-import-map.js';
|
|
11
11
|
import { generateCustomTypes } from '@pikku/inspector';
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* All three step wrappers. A scenario calls a platform or addon step by name
|
|
14
|
+
* exactly as it calls a persona one — who acts changes what the step may do, not
|
|
15
|
+
* how it is referenced — so all three belong in the map.
|
|
16
|
+
*/
|
|
17
|
+
const SCENARIO_STEP_WRAPPERS = new Set([
|
|
18
|
+
'pikkuScenarioStep',
|
|
19
|
+
'pikkuPlatformScenarioStep',
|
|
20
|
+
'pikkuAddonScenarioStep',
|
|
21
|
+
]);
|
|
13
22
|
export const serializeScenarioStepMap = (logger, relativeToPath, packageMappings, typesMap, functionsMeta) => {
|
|
14
23
|
const requiredTypes = new Set();
|
|
15
|
-
const steps = Object.entries(functionsMeta).filter(([, meta]) => meta.funcWrapper
|
|
24
|
+
const steps = Object.entries(functionsMeta).filter(([, meta]) => !!meta.funcWrapper && SCENARIO_STEP_WRAPPERS.has(meta.funcWrapper));
|
|
16
25
|
const resolveType = (name) => {
|
|
17
26
|
if (!name) {
|
|
18
27
|
return 'void';
|