@pikku/core 0.12.92 → 0.12.93

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.
Files changed (99) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/dist/errors/error-handler.d.ts +11 -0
  3. package/dist/errors/error-handler.js +8 -0
  4. package/dist/errors/serialized-error.d.ts +3 -0
  5. package/dist/function/function-runner.d.ts +1 -1
  6. package/dist/function/function-runner.js +3 -3
  7. package/dist/function/functions.types.d.ts +33 -21
  8. package/dist/middleware/auth-apikey.d.ts +7 -0
  9. package/dist/middleware/auth-apikey.js +6 -0
  10. package/dist/middleware/auth-bearer.d.ts +3 -0
  11. package/dist/middleware/auth-bearer.js +2 -0
  12. package/dist/middleware/auth-cookie.d.ts +9 -0
  13. package/dist/middleware/auth-cookie.js +6 -4
  14. package/dist/middleware/cors.d.ts +8 -0
  15. package/dist/middleware/cors.js +2 -0
  16. package/dist/middleware/middleware-factories.d.ts +14 -0
  17. package/dist/middleware/middleware-factories.js +14 -0
  18. package/dist/services/local-secrets.js +1 -1
  19. package/dist/services/personas-service.d.ts +4 -0
  20. package/dist/services/personas-service.js +4 -0
  21. package/dist/services/secret-service.d.ts +0 -1
  22. package/dist/testing/service-tests/secret-service-tests.js +1 -1
  23. package/dist/types/core.types.d.ts +5 -0
  24. package/dist/wirings/addon/wire-addon.d.ts +17 -15
  25. package/dist/wirings/addon/wire-addon.js +6 -0
  26. package/dist/wirings/addon/wire-remote-addon.d.ts +4 -0
  27. package/dist/wirings/addon/wire-remote-addon.js +4 -0
  28. package/dist/wirings/agent/agent-prepare.js +2 -2
  29. package/dist/wirings/agent/agent.types.d.ts +31 -27
  30. package/dist/wirings/agent-scorer/agent-scorer.d.ts +4 -0
  31. package/dist/wirings/agent-scorer/agent-scorer.js +4 -0
  32. package/dist/wirings/channel/channel.types.d.ts +11 -0
  33. package/dist/wirings/cli/cli.types.d.ts +43 -1
  34. package/dist/wirings/cli/define-cli-commands.d.ts +6 -1
  35. package/dist/wirings/cli/define-cli-commands.js +6 -1
  36. package/dist/wirings/credential/credential.types.d.ts +7 -0
  37. package/dist/wirings/gateway/gateway.types.d.ts +23 -0
  38. package/dist/wirings/http/http.types.d.ts +51 -37
  39. package/dist/wirings/mcp/mcp.types.d.ts +27 -0
  40. package/dist/wirings/queue/queue.types.d.ts +6 -0
  41. package/dist/wirings/scheduler/scheduler.types.d.ts +5 -0
  42. package/dist/wirings/secret/secret.types.d.ts +9 -14
  43. package/dist/wirings/secret/secret.types.js +7 -0
  44. package/dist/wirings/trigger/trigger.types.d.ts +4 -1
  45. package/dist/wirings/variable/variable.types.d.ts +14 -13
  46. package/dist/wirings/variable/variable.types.js +7 -0
  47. package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +7 -0
  48. package/dist/wirings/workflow/scenario-cookie-jar.d.ts +6 -0
  49. package/dist/wirings/workflow/scenario-cookie-jar.js +6 -0
  50. package/dist/wirings/workflow/scenario-poll.d.ts +6 -0
  51. package/dist/wirings/workflow/scenario-poll.js +6 -0
  52. package/dist/wirings/workflow/scenario-step-guards.d.ts +6 -0
  53. package/dist/wirings/workflow/scenario-step-guards.js +6 -0
  54. package/dist/wirings/workflow/workflow-errors.d.ts +4 -0
  55. package/dist/wirings/workflow/workflow-errors.js +4 -0
  56. package/package.json +1 -1
  57. package/src/app-leaf-surface.test.ts +2 -2
  58. package/src/errors/error-handler.ts +11 -0
  59. package/src/errors/serialized-error.ts +3 -0
  60. package/src/function/function-runner.ts +4 -4
  61. package/src/function/functions.types.ts +33 -21
  62. package/src/middleware/auth-apikey.ts +7 -0
  63. package/src/middleware/auth-bearer.ts +3 -0
  64. package/src/middleware/auth-cookie.ts +9 -4
  65. package/src/middleware/cors.ts +8 -0
  66. package/src/middleware/middleware-factories.ts +14 -0
  67. package/src/services/local-secrets.test.ts +2 -2
  68. package/src/services/local-secrets.ts +1 -1
  69. package/src/services/personas-service.ts +4 -0
  70. package/src/services/secret-service.ts +0 -1
  71. package/src/testing/service-tests/secret-service-tests.ts +1 -1
  72. package/src/types/core.types.ts +5 -0
  73. package/src/wirings/addon/addon-auth-tags.test.ts +4 -4
  74. package/src/wirings/addon/wire-addon.ts +17 -15
  75. package/src/wirings/addon/wire-remote-addon.ts +4 -0
  76. package/src/wirings/agent/agent-authorization.test.ts +7 -3
  77. package/src/wirings/agent/agent-prepare.ts +2 -2
  78. package/src/wirings/agent/agent.types.ts +31 -27
  79. package/src/wirings/agent-scorer/agent-scorer.ts +4 -0
  80. package/src/wirings/channel/channel.types.ts +11 -0
  81. package/src/wirings/cli/cli.types.ts +44 -1
  82. package/src/wirings/cli/define-cli-commands.ts +6 -1
  83. package/src/wirings/credential/credential.types.ts +7 -0
  84. package/src/wirings/gateway/gateway-authorization.test.ts +3 -3
  85. package/src/wirings/gateway/gateway.types.ts +23 -0
  86. package/src/wirings/http/http-runner-addon-ref.test.ts +1 -1
  87. package/src/wirings/http/http.types.ts +94 -69
  88. package/src/wirings/mcp/mcp.types.ts +27 -0
  89. package/src/wirings/queue/queue.types.ts +6 -0
  90. package/src/wirings/scheduler/scheduler.types.ts +5 -0
  91. package/src/wirings/secret/secret.types.ts +9 -14
  92. package/src/wirings/trigger/trigger.types.ts +4 -1
  93. package/src/wirings/variable/variable.types.ts +14 -13
  94. package/src/wirings/workflow/graph/wire-workflow-graph.ts +7 -0
  95. package/src/wirings/workflow/scenario-cookie-jar.ts +6 -0
  96. package/src/wirings/workflow/scenario-poll.ts +6 -0
  97. package/src/wirings/workflow/scenario-step-guards.ts +6 -0
  98. package/src/wirings/workflow/workflow-errors.ts +4 -0
  99. package/tsconfig.tsbuildinfo +1 -1
@@ -48,15 +48,19 @@ export type HTTPHeadersSchema = StandardSchemaV1<
48
48
  >
49
49
 
50
50
  export type HTTPRouteBaseConfig = {
51
+ /** How the body is serialised. Defaults to JSON; `xml` is for routes a caller you do not control insists on. */
51
52
  contentType?: 'xml' | 'json'
53
+ /** Seconds before the request is abandoned. Work that can outlast a request should be dispatched instead, not given a longer timeout. */
52
54
  timeout?: number
55
+ /** Filters this route in and out of a build — see the `tags` option on `pikku all`. It has no effect at runtime. */
53
56
  tags?: string[]
57
+ /** A schema the request headers are validated against, so a missing or malformed header fails before the function body runs. */
54
58
  headers?: HTTPHeadersSchema
55
59
  }
56
60
 
57
61
  export type CoreHTTPFunction = HTTPRouteBaseConfig & {
58
62
  route: string
59
- eventChannel?: false
63
+ /** Sends the returned value as-is rather than JSON-encoding it, for a route whose body is binary or already serialised. */
60
64
  returnsJSON?: false
61
65
  }
62
66
 
@@ -70,100 +74,121 @@ export type PikkuQuery<T = Record<string, string | undefined>> = Record<
70
74
  string | T | null | Array<T | null>
71
75
  >
72
76
 
73
- export type CoreHTTPFunctionWiring<
77
+ /**
78
+ * The keys every HTTP wiring takes, whatever it is wired to. The three that
79
+ * are not here — `method`, `auth` and `func` — are correlated rather than
80
+ * independent, and live in the unions below.
81
+ */
82
+ type HTTPWiringShared<
83
+ R extends string,
84
+ PikkuMiddleware extends CorePikkuMiddleware<any, any>,
85
+ > = CoreHTTPFunction & {
86
+ /**
87
+ * The path this wiring answers on. `:name` marks a parameter, and every
88
+ * parameter in the path must be a key of the function's input schema —
89
+ * a mismatch is a compile error rather than a 404 at runtime.
90
+ */
91
+ route: R
92
+ /** Wraps every request to this route: auth, tracing, rate limiting. Runs before the permissions on `func`. */
93
+ middleware?: PikkuMiddleware[]
94
+ }
95
+
96
+ /**
97
+ * `auth` decides which kind of function this route can point at, so the two
98
+ * travel together: a route that requires a session gets a function that is
99
+ * handed one, and an open route gets a sessionless function that has none to
100
+ * read. Splitting them would let a function ask for a session the route never
101
+ * establishes.
102
+ */
103
+ type HTTPWiringAuth<
74
104
  In,
75
105
  Out,
76
- R extends string,
77
- PikkuFunction extends CorePikkuFunction<In, Out, any, any, any> =
78
- CorePikkuFunction<In, Out>,
106
+ PikkuFunction extends CorePikkuFunction<In, Out, any, any, any>,
79
107
  PikkuFunctionSessionless extends CorePikkuFunctionSessionless<
80
108
  In,
81
109
  Out,
82
110
  any,
83
111
  any,
84
112
  any
85
- > = CorePikkuFunctionSessionless<In, Out>,
86
- PikkuPermission extends CorePikkuPermission<In, any, any> =
87
- CorePikkuPermission<In, any, any>,
88
- PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<
89
- any,
90
- any
91
113
  >,
114
+ PikkuPermission extends CorePikkuPermission<In, any, any>,
115
+ PikkuMiddleware extends CorePikkuMiddleware<any, any>,
92
116
  > =
93
- | (CoreHTTPFunction & {
94
- route: R
95
- method: HTTPMethod
117
+ | {
118
+ /** Whether reaching this route requires a session. Defaults to true — a route is closed unless it says otherwise. */
119
+ auth?: true
120
+ /** The function to run. It is handed the session this route required. */
96
121
  func: CorePikkuFunctionConfig<
97
122
  PikkuFunction,
98
123
  PikkuPermission,
99
124
  PikkuMiddleware
100
125
  >
101
- auth?: true
102
- middleware?: PikkuMiddleware[]
103
- sse?: undefined
104
- })
105
- | (CoreHTTPFunction & {
106
- route: R
107
- method: HTTPMethod
126
+ }
127
+ | {
128
+ /** Whether reaching this route requires a session. Defaults to true — a route is closed unless it says otherwise. */
129
+ auth?: false
130
+ /** On an open route there is no session, so this must be a sessionless function. */
108
131
  func: CorePikkuFunctionConfig<
109
132
  PikkuFunctionSessionless,
110
133
  PikkuPermission,
111
134
  PikkuMiddleware
112
135
  >
113
- auth?: false
114
- middleware?: PikkuMiddleware[]
136
+ }
137
+
138
+ /**
139
+ * `sse` and `query` are each valid on one method only, so the method carries
140
+ * them: streaming is a GET, and naming which input keys arrive in the query
141
+ * string is only a question on a POST, where the rest of the input is a body.
142
+ */
143
+ type HTTPWiringMethod<In> =
144
+ | {
145
+ /** The HTTP method. A route and method together address one wiring. */
146
+ method: HTTPMethod
115
147
  sse?: undefined
116
- })
117
- | (CoreHTTPFunction & {
118
- route: R
148
+ }
149
+ | {
150
+ /** The HTTP method. A route and method together address one wiring. */
119
151
  method: 'get'
120
- func: CorePikkuFunctionConfig<
121
- PikkuFunction,
122
- PikkuPermission,
123
- PikkuMiddleware
124
- >
125
- auth?: true
126
- middleware?: PikkuMiddleware[]
127
- sse?: boolean
128
- })
129
- | (CoreHTTPFunction & {
130
- route: R
131
- method: 'get'
132
- func: CorePikkuFunctionConfig<
133
- PikkuFunctionSessionless,
134
- PikkuPermission,
135
- PikkuMiddleware
136
- >
137
- auth?: false
138
- middleware?: PikkuMiddleware[]
152
+ /** Streams the response as server-sent events instead of returning it once. GET only. */
139
153
  sse?: boolean
140
- })
141
- | (CoreHTTPFunction & {
142
- route: R
154
+ }
155
+ | {
156
+ /** The HTTP method. A route and method together address one wiring. */
143
157
  method: 'post'
144
- func: CorePikkuFunctionConfig<
145
- PikkuFunction,
146
- PikkuPermission,
147
- PikkuMiddleware
148
- >
149
- auth?: true
150
- middleware?: PikkuMiddleware[]
158
+ /** Input keys that arrive in the query string rather than the body. POST only, where the body is the default home for input. */
151
159
  query?: Array<keyof In>
152
160
  sse?: undefined
153
- })
154
- | (CoreHTTPFunction & {
155
- route: R
156
- method: 'post'
157
- func: CorePikkuFunctionConfig<
158
- PikkuFunctionSessionless,
159
- PikkuPermission,
160
- PikkuMiddleware
161
- >
162
- auth?: false
163
- middleware?: PikkuMiddleware[]
164
- query?: Array<keyof In>
165
- sse?: undefined
166
- })
161
+ }
162
+
163
+ export type CoreHTTPFunctionWiring<
164
+ In,
165
+ Out,
166
+ R extends string,
167
+ PikkuFunction extends CorePikkuFunction<In, Out, any, any, any> =
168
+ CorePikkuFunction<In, Out>,
169
+ PikkuFunctionSessionless extends CorePikkuFunctionSessionless<
170
+ In,
171
+ Out,
172
+ any,
173
+ any,
174
+ any
175
+ > = CorePikkuFunctionSessionless<In, Out>,
176
+ PikkuPermission extends CorePikkuPermission<In, any, any> =
177
+ CorePikkuPermission<In, any, any>,
178
+ PikkuMiddleware extends CorePikkuMiddleware<any, any> = CorePikkuMiddleware<
179
+ any,
180
+ any
181
+ >,
182
+ > = HTTPWiringShared<R, PikkuMiddleware> &
183
+ HTTPWiringAuth<
184
+ In,
185
+ Out,
186
+ PikkuFunction,
187
+ PikkuFunctionSessionless,
188
+ PikkuPermission,
189
+ PikkuMiddleware
190
+ > &
191
+ HTTPWiringMethod<In>
167
192
 
168
193
  export type HTTPFunctionMetaInputTypes = {
169
194
  params?: string
@@ -76,16 +76,27 @@ export type CoreMCPResource<
76
76
  PikkuPermission = CorePikkuPermission<any, any>,
77
77
  PikkuMiddleware = CorePikkuMiddleware<any>,
78
78
  > = {
79
+ /** How the client addresses this resource. `{name}` marks a parameter, and every parameter must be a key of the function's input schema. */
79
80
  uri: string
81
+ /** The name a human sees in a client's resource list. */
80
82
  title: string
83
+ /** What the resource holds, written for the model deciding whether to read it. */
81
84
  description: string
85
+ /** A one-line description for listings, where the full `description` is too long. */
82
86
  summary?: string
87
+ /** Names of error classes this may throw, so the client is told which failures are its own fault. */
83
88
  errors?: string[]
89
+ /** The media type of what the function returns, so the client knows whether it is text, JSON or an image. */
84
90
  mimeType?: string
91
+ /** Size in bytes, where it is known ahead of the read. A client uses it to decide whether to fetch at all. */
85
92
  size?: number
93
+ /** Whether the function returns the content in chunks rather than at once. */
86
94
  streaming?: boolean
95
+ /** The function to run. It is sessionless: an MCP client is not a logged-in user. */
87
96
  func: PikkuFunctionConfig
97
+ /** Filters this wiring in and out of a build — see the `tags` option on `pikku all`. It has no effect at runtime. */
88
98
  tags?: string[]
99
+ /** Wraps every call: tracing, rate limiting, whatever the transport does not do. */
89
100
  middleware?: PikkuMiddleware[]
90
101
  }
91
102
 
@@ -96,14 +107,23 @@ export type CoreMCPTool<
96
107
  PikkuPermission = CorePikkuPermission<any, any>,
97
108
  PikkuMiddleware = CorePikkuMiddleware<any>,
98
109
  > = {
110
+ /** How the model calls this tool. It is the tool's identity, so renaming it breaks any client that already knows it. */
99
111
  name: string
112
+ /** The name a human sees, where the calling `name` is not readable. */
100
113
  title?: string
114
+ /** What the tool does and when to reach for it. This is what the model decides on, so it earns more care than the rest of this object. */
101
115
  description?: string
116
+ /** A one-line description for listings, where the full `description` is too long. */
102
117
  summary?: string
118
+ /** Names of error classes this may throw, so the client is told which failures are its own fault. */
103
119
  errors?: string[]
120
+ /** The function to run. It is sessionless: an MCP client is not a logged-in user. */
104
121
  func: PikkuFunctionConfig
122
+ /** Filters this wiring in and out of a build — see the `tags` option on `pikku all`. It has no effect at runtime. */
105
123
  tags?: string[]
124
+ /** Whether the function returns its result in chunks rather than at once. */
106
125
  streaming?: boolean
126
+ /** Wraps every call: tracing, rate limiting, whatever the transport does not do. */
107
127
  middleware?: PikkuMiddleware[]
108
128
  }
109
129
 
@@ -114,12 +134,19 @@ export type CoreMCPPrompt<
114
134
  PikkuPermission = CorePikkuPermission<any, any>,
115
135
  PikkuMiddleware = CorePikkuMiddleware<any>,
116
136
  > = {
137
+ /** How the client asks for this prompt. */
117
138
  name: string
139
+ /** What the prompt is for, written for the human picking it out of a list. */
118
140
  description: string
141
+ /** A one-line description for listings, where the full `description` is too long. */
119
142
  summary?: string
143
+ /** Names of error classes this may throw, so the client is told which failures are its own fault. */
120
144
  errors?: string[]
145
+ /** The function to run. It is sessionless: an MCP client is not a logged-in user. */
121
146
  func: PikkuFunctionConfig
147
+ /** Filters this wiring in and out of a build — see the `tags` option on `pikku all`. It has no effect at runtime. */
122
148
  tags?: string[]
149
+ /** Wraps every call: tracing, rate limiting, whatever the transport does not do. */
123
150
  middleware?: PikkuMiddleware[]
124
151
  }
125
152
 
@@ -135,11 +135,17 @@ export type CoreQueueWorker<
135
135
  PikkuFunctionConfig extends CorePikkuFunctionConfig<any, any, any> =
136
136
  CorePikkuFunctionConfig<any, any, any>,
137
137
  > = {
138
+ /** The queue this worker consumes. Whoever enqueues a job names the same string, so it is the contract between producer and consumer. */
138
139
  name: string
140
+ /** The function to run per job. Its `input` schema is the job payload's schema — a job that does not match is rejected before the body runs. */
139
141
  func: PikkuFunctionConfig
142
+ /** Concurrency, retry and backoff, passed through to the queue service backing this worker. Defaults come from the service, not from here. */
140
143
  config?: PikkuWorkerConfig
144
+ /** Names of error classes that mean the job is bad rather than the run — thrown, they fail the job permanently instead of being retried. */
141
145
  errors?: string[]
146
+ /** Filters this worker in and out of a build — see the `tags` option on `pikku all`. It has no effect at runtime. */
142
147
  tags?: string[]
148
+ /** Wraps every job. There is no request to read from, so this is for tracing, locking and teardown rather than auth. */
143
149
  middleware?: PikkuFunctionConfig['middleware']
144
150
  }
145
151
 
@@ -21,10 +21,15 @@ export type CoreScheduledTask<
21
21
  >,
22
22
  PikkuMiddleware = CorePikkuMiddleware<any>,
23
23
  > = {
24
+ /** Unique across the project. It is how the task is addressed in logs, in `pikku meta`, and by a scheduler service asked to run it now. */
24
25
  name: string
26
+ /** A five-field cron expression: minute, hour, day of month, month, day of week. `0 9 * * 1` is 09:00 every Monday. Interpreted in the deployment's timezone, not the author's. */
25
27
  schedule: string
28
+ /** The function to run. It receives no session and no input: a scheduled task has no caller, so it must be sessionless. */
26
29
  func: PikkuFunctionConfig
30
+ /** Filters this task in and out of a build — see the `tags` option on `pikku all`. It has no effect at runtime. */
27
31
  tags?: string[]
32
+ /** Wraps every execution. There is no request to read from, so this is for tracing, locking and teardown rather than auth. */
28
33
  middleware?: PikkuMiddleware[]
29
34
  }
30
35
 
@@ -4,21 +4,9 @@ export type CoreSecret<T = unknown> = {
4
4
  description?: string
5
5
  secretId: string
6
6
  schema: T
7
- /**
8
- * A secret is REQUIRED by default because `getSecret` throws when the value is
9
- * missing — a deploy without it is a runtime failure waiting to happen, so the
10
- * deploy gate refuses it. Mark a secret `optional` when absence is a supported
11
- * state the app handles (a feature that simply stays off): the generated map
12
- * emits it as an optional property and `getSecret` resolves `undefined`
13
- * instead of throwing.
14
- */
7
+ /** Required by default: this says absence is a supported state, and `getSecret` resolves `undefined` rather than throwing. */
15
8
  optional?: boolean
16
- /**
17
- * Where a user goes to obtain this value — a provider's API-key page, a setup
18
- * guide, an internal runbook. Consoles and deploy UIs surface it beside a
19
- * missing value. The same field on every credential/variable definition means
20
- * the same thing.
21
- */
9
+ /** Where a user goes to obtain this value, surfaced beside a missing one. */
22
10
  docsUrl?: string
23
11
  /** Rotation cadence as a duration string, e.g. `'1d'`, `'30day'`, `'1w'`. */
24
12
  rotationPeriod?: string
@@ -64,4 +52,11 @@ export type SecretDefinitionsMeta = Record<string, SecretDefinitionMeta>
64
52
 
65
53
  export type SecretDefinitions = SecretDefinitionMeta[]
66
54
 
55
+ /**
56
+ * Declares a secret this project needs, with the shape of its value. The CLI
57
+ * collects every declaration into `CredentialsMap`, which is what makes
58
+ * `secrets.getSecret('NAME')` return the right type instead of `unknown`.
59
+ *
60
+ * @example snippet: secrets
61
+ */
67
62
  export const defineSecret = <T>(_config: CoreSecret<T>): void => {}
@@ -72,11 +72,14 @@ export const pikkuTriggerFunc = <
72
72
  }
73
73
 
74
74
  export interface CoreTrigger<PikkuFunctionConfig = any> {
75
+ /** What a `wireTriggerSource` points at to fire this trigger. It is the contract between the two, so both must spell it the same. */
75
76
  name: string
77
+ /** The function to run each time the trigger fires. */
76
78
  func: PikkuFunctionConfig
79
+ /** What firing this trigger means, for whoever is reading the wiring rather than writing it. */
77
80
  description?: string
81
+ /** Filters this trigger in and out of a build — see the `tags` option on `pikku all`. It has no effect at runtime. */
78
82
  tags?: string[]
79
- graph?: true
80
83
  }
81
84
 
82
85
  export interface TriggerInstance {
@@ -1,23 +1,17 @@
1
1
  export type CoreVariable<T = unknown> = {
2
+ /** How the variable is asked for in code. Generated into `VariablesMap`, so it is what `variables.get` autocompletes. */
2
3
  name: string
4
+ /** The name shown to whoever configures the deployment. */
3
5
  displayName: string
6
+ /** What the value does, for the person setting it rather than the one reading it. */
4
7
  description?: string
8
+ /** The environment variable this reads, which is the name that has to exist on the host. */
5
9
  variableId: string
10
+ /** The shape of the value. It arrives as a string, so this is also what parses it. */
6
11
  schema: T
7
- /**
8
- * A variable is REQUIRED by default, and marking it `optional` is how a
9
- * declaration says its absence is a supported state. Same flag, same
10
- * polarity and same meaning as `CoreSecret.optional` — one word to learn
11
- * rather than two with opposite senses.
12
- *
13
- * Defaulting to required rather than following `variables.get`'s
14
- * `T | undefined` return is deliberate. That signature describes what a
15
- * caller must HANDLE, not whether a deployment is correct without the value:
16
- * an undefined feature flag is fine, an undefined API base URL is an outage
17
- * that the type system cannot tell apart. Declaring the difference is the
18
- * point of the flag, and the safe default for an undeclared one is to ask.
19
- */
12
+ /** Required by default: this says the deployment is still correct without it. */
20
13
  optional?: boolean
14
+ /** Where to go to work out what to set this to. */
21
15
  docsUrl?: string
22
16
  }
23
17
 
@@ -36,4 +30,11 @@ export type VariableDefinitionsMeta = Record<string, VariableDefinitionMeta>
36
30
 
37
31
  export type VariableDefinitions = VariableDefinitionMeta[]
38
32
 
33
+ /**
34
+ * Declares an environment variable this project needs, with the shape of its
35
+ * value. The CLI collects every declaration into `VariablesMap`, which is what
36
+ * makes `variables.get('NAME')` return the right type instead of `unknown`.
37
+ *
38
+ * @example snippet: variables
39
+ */
39
40
  export const defineVariable = <T>(_config: CoreVariable<T>): void => {}
@@ -2,12 +2,19 @@ export interface PikkuWorkflowGraphConfig<
2
2
  FuncMap extends Record<string, string>,
3
3
  T,
4
4
  > {
5
+ /** Keeps the graph in the codebase but out of the build. */
5
6
  disabled?: true
7
+ /** Unique across the project. It is how the graph is started and how its runs are grouped. */
6
8
  name?: string
9
+ /** What the graph does, for whoever is reading it rather than editing it. */
7
10
  description?: string
11
+ /** Filters this graph in and out of a build — see the `tags` option on `pikku all`. It has no effect at runtime. */
8
12
  tags?: string[]
13
+ /** The graph's steps, keyed by node id, each naming a function. `pikku meta` lists the names available here. */
9
14
  nodes: FuncMap
15
+ /** Per-node settings — retries, timeouts, the edges between them. */
10
16
  config?: T
17
+ /** Free text carried onto the rendered graph, for a reader who needs the reasoning the shape cannot show. */
11
18
  notes?: string[]
12
19
  }
13
20
 
@@ -4,6 +4,12 @@ export interface ScenarioCookieJar {
4
4
  readonly empty: boolean
5
5
  }
6
6
 
7
+ /**
8
+ * A cookie store for a scenario run, so a step that signs in leaves the session
9
+ * cookie behind for the steps after it.
10
+ *
11
+ * @example snippet: scenarioCookieJar
12
+ */
7
13
  export const createCookieJar = (apiUrl: string): ScenarioCookieJar => {
8
14
  const jar = new Map<string, string>()
9
15
  const origin = new URL(apiUrl).origin
@@ -3,6 +3,12 @@ export interface PollOptions {
3
3
  intervalMs?: number
4
4
  }
5
5
 
6
+ /**
7
+ * Retries an assertion until it passes or the timeout runs out — for the
8
+ * eventually-consistent parts of a scenario (a queued job, a projection).
9
+ *
10
+ * @example snippet: scenarioPolling
11
+ */
6
12
  export const pollUntil = async <T>(
7
13
  attempt: () => Promise<T | undefined> | T | undefined,
8
14
  { timeoutMs = 15_000, intervalMs = 250 }: PollOptions = {}
@@ -3,6 +3,12 @@ import type {
3
3
  ScenarioEnvironment,
4
4
  } from './scenario-step.types.js'
5
5
 
6
+ /**
7
+ * The environment the current scenario run targets, or a throw explaining that
8
+ * the run carries none. Use it in a step that needs the target's URLs.
9
+ *
10
+ * @example snippet: scenarioHttpStep
11
+ */
6
12
  export const requireScenarioEnv = (
7
13
  scenarioStep: PikkuScenarioStepWire | undefined
8
14
  ): ScenarioEnvironment => {
@@ -15,6 +15,10 @@ export class WorkflowAsyncException extends Error {
15
15
  }
16
16
  }
17
17
 
18
+ /**
19
+ * Thrown inside a workflow step when the run has been cancelled, so the step
20
+ * stops rather than finishing work nobody wants.
21
+ */
18
22
  export class WorkflowCancelledException extends Error {
19
23
  constructor(
20
24
  public readonly runId: string,