@pikku/core 0.12.82 → 0.12.83
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 +33 -0
- package/dist/services/index.d.ts +5 -6
- package/dist/services/index.js +2 -2
- package/dist/services/meta-service.d.ts +2 -1
- package/dist/types/core.types.d.ts +2 -1
- package/dist/types/state.types.d.ts +6 -1
- package/dist/wirings/ai-agent/ai-agent-prepare.js +2 -0
- package/dist/wirings/rpc/addon-runner.d.ts +4 -0
- package/dist/wirings/rpc/addon-runner.js +14 -2
- package/dist/wirings/rpc/rpc-runner.js +2 -0
- package/dist/wirings/rpc/rpc-types.d.ts +4 -0
- package/dist/wirings/rpc/wire-addon.d.ts +12 -0
- package/dist/wirings/rpc/wire-addon.js +4 -0
- package/dist/wirings/workflow/feature.d.ts +2 -1
- package/dist/wirings/workflow/index.d.ts +3 -14
- package/dist/wirings/workflow/index.js +0 -8
- package/dist/wirings/workflow/pikku-scenario-service.d.ts +10 -0
- package/dist/wirings/workflow/pikku-scenario-service.js +9 -0
- package/dist/wirings/workflow/scenario.types.d.ts +37 -0
- package/dist/wirings/workflow/scenario.types.js +1 -0
- package/dist/wirings/workflow/workflow.types.d.ts +2 -37
- package/package.json +1 -2
- package/src/public-surface.json +11 -24
- package/src/services/index.ts +4 -15
- package/src/services/meta-service.ts +2 -4
- package/src/types/core.types.ts +1 -1
- package/src/types/state.types.ts +5 -1
- package/src/wirings/ai-agent/ai-agent-prepare.ts +2 -0
- package/src/wirings/rpc/addon-runner.ts +31 -3
- package/src/wirings/rpc/addon-secrets.test.ts +130 -0
- package/src/wirings/rpc/rpc-runner.ts +2 -0
- package/src/wirings/rpc/rpc-types.ts +4 -0
- package/src/wirings/rpc/wire-addon.ts +16 -0
- package/src/wirings/workflow/feature.ts +2 -5
- package/src/wirings/workflow/index.ts +1 -49
- package/src/wirings/workflow/pikku-scenario-service.ts +21 -1
- package/src/wirings/workflow/scenario.types.ts +63 -0
- package/src/wirings/workflow/workflow.types.ts +1 -54
- package/tsconfig.tsbuildinfo +1 -1
package/src/types/state.types.ts
CHANGED
|
@@ -47,9 +47,9 @@ import type {
|
|
|
47
47
|
} from '../wirings/scheduler/scheduler.types.js'
|
|
48
48
|
import type {
|
|
49
49
|
CoreWorkflow,
|
|
50
|
-
CoreFeature,
|
|
51
50
|
WorkflowsRuntimeMeta,
|
|
52
51
|
} from '../wirings/workflow/workflow.types.js'
|
|
52
|
+
import type { CoreFeature } from '../wirings/workflow/scenario.types.js'
|
|
53
53
|
import type {
|
|
54
54
|
CoreTrigger,
|
|
55
55
|
CoreTriggerSource,
|
|
@@ -102,6 +102,10 @@ export interface PikkuPackageState {
|
|
|
102
102
|
variableOverrides?: Record<string, string>
|
|
103
103
|
/** Per-instance name-aliases: logical name the addon reads -> actual project credential name */
|
|
104
104
|
credentialOverrides?: Record<string, string>
|
|
105
|
+
/** Secrets the host lends this instance, named as the addon reads them */
|
|
106
|
+
secretGrants?: string[]
|
|
107
|
+
/** Credentials the host lends this instance, named as the addon reads them */
|
|
108
|
+
credentialGrants?: string[]
|
|
105
109
|
/** Why this instance gets the whole `SecretService` rather than one scoped to its declared secrets */
|
|
106
110
|
globalSecrets?: string
|
|
107
111
|
/** Why this instance gets the whole `CredentialService` rather than one scoped to its declared credentials */
|
|
@@ -565,6 +565,8 @@ export async function buildToolDefs(
|
|
|
565
565
|
variableOverrides: capturedAddonConfig?.variableOverrides,
|
|
566
566
|
credentialOverrides:
|
|
567
567
|
capturedAddonConfig?.credentialOverrides,
|
|
568
|
+
secretGrants: capturedAddonConfig?.secretGrants,
|
|
569
|
+
credentialGrants: capturedAddonConfig?.credentialGrants,
|
|
568
570
|
globalSecrets: capturedAddonConfig?.globalSecrets,
|
|
569
571
|
globalCredentials: capturedAddonConfig?.globalCredentials,
|
|
570
572
|
}
|
|
@@ -13,12 +13,32 @@ export type AddonInstance = {
|
|
|
13
13
|
secretOverrides?: Record<string, string>
|
|
14
14
|
variableOverrides?: Record<string, string>
|
|
15
15
|
credentialOverrides?: Record<string, string>
|
|
16
|
+
/** Set by the consuming app: secrets it lends this instance, as the addon names them. */
|
|
17
|
+
secretGrants?: string[]
|
|
18
|
+
/** Set by the consuming app: credentials it lends this instance, as the addon names them. */
|
|
19
|
+
credentialGrants?: string[]
|
|
16
20
|
/** Set by the consuming app to opt this instance out of secret scoping. */
|
|
17
21
|
globalSecrets?: string
|
|
18
22
|
/** Set by the consuming app to opt this instance out of credential scoping. */
|
|
19
23
|
globalCredentials?: string
|
|
20
24
|
}
|
|
21
25
|
|
|
26
|
+
/**
|
|
27
|
+
* What the addon declared, plus what the host lent it. Scoping runs outside the
|
|
28
|
+
* aliaser, so every name here is the one the addon reads — which is why an
|
|
29
|
+
* override's *key* grants, and its value does not.
|
|
30
|
+
*/
|
|
31
|
+
const allowedNames = (
|
|
32
|
+
declared: string[] | null | undefined,
|
|
33
|
+
grants: string[] | undefined,
|
|
34
|
+
overrides: Record<string, string> | undefined
|
|
35
|
+
): Set<string> =>
|
|
36
|
+
new Set([
|
|
37
|
+
...(declared ?? []),
|
|
38
|
+
...(grants ?? []),
|
|
39
|
+
...Object.keys(overrides ?? {}),
|
|
40
|
+
])
|
|
41
|
+
|
|
22
42
|
const aliasSecretService = (
|
|
23
43
|
secrets: SecretService,
|
|
24
44
|
overrides: Record<string, string>
|
|
@@ -142,7 +162,11 @@ export const getOrCreatePackageSingletonServices = async (
|
|
|
142
162
|
...existingServices,
|
|
143
163
|
secrets: new ScopedSecretService(
|
|
144
164
|
existingServices.secrets,
|
|
145
|
-
|
|
165
|
+
allowedNames(
|
|
166
|
+
pikkuState(packageName, 'package', 'declaredSecrets'),
|
|
167
|
+
addonInstance?.secretGrants,
|
|
168
|
+
addonInstance?.secretOverrides
|
|
169
|
+
)
|
|
146
170
|
),
|
|
147
171
|
}
|
|
148
172
|
}
|
|
@@ -151,10 +175,12 @@ export const getOrCreatePackageSingletonServices = async (
|
|
|
151
175
|
...existingServices,
|
|
152
176
|
credentialService: new ScopedCredentialService(
|
|
153
177
|
existingServices.credentialService,
|
|
154
|
-
|
|
178
|
+
allowedNames(
|
|
155
179
|
Object.keys(
|
|
156
180
|
pikkuState(packageName, 'package', 'credentialsMeta') ?? {}
|
|
157
|
-
)
|
|
181
|
+
),
|
|
182
|
+
addonInstance?.credentialGrants,
|
|
183
|
+
addonInstance?.credentialOverrides
|
|
158
184
|
)
|
|
159
185
|
),
|
|
160
186
|
}
|
|
@@ -202,6 +228,8 @@ export const addonInstanceForNamespace = (
|
|
|
202
228
|
secretOverrides: cfg.secretOverrides,
|
|
203
229
|
variableOverrides: cfg.variableOverrides,
|
|
204
230
|
credentialOverrides: cfg.credentialOverrides,
|
|
231
|
+
secretGrants: cfg.secretGrants,
|
|
232
|
+
credentialGrants: cfg.credentialGrants,
|
|
205
233
|
globalSecrets: cfg.globalSecrets,
|
|
206
234
|
globalCredentials: cfg.globalCredentials,
|
|
207
235
|
}
|
|
@@ -259,3 +259,133 @@ describe('addon credentials are scoped to what the addon declared', () => {
|
|
|
259
259
|
assert.deepEqual(await credentials.getAllUsers(), ['user-1'])
|
|
260
260
|
})
|
|
261
261
|
})
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* An addon whose secret names come off its input rather than its own source
|
|
265
|
+
* declares nothing, so the host lends it names it could not have derived.
|
|
266
|
+
*
|
|
267
|
+
* knowledge: decisions/security/decision-secretless-functions.md
|
|
268
|
+
*/
|
|
269
|
+
describe('the host grants an addon secrets it could not declare', () => {
|
|
270
|
+
beforeEach(() => {
|
|
271
|
+
resetPikkuState()
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
test('a granted secret is readable', async () => {
|
|
275
|
+
registerAddon([])
|
|
276
|
+
wireAddon({
|
|
277
|
+
name: 'example',
|
|
278
|
+
package: ADDON_PACKAGE,
|
|
279
|
+
secretGrants: ['STRIPE_KEY'],
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
const secrets = await secretsHandedToAddon('example')
|
|
283
|
+
assert.equal(await secrets.getSecret('STRIPE_KEY'), 'value-of-STRIPE_KEY')
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
test('a secret the host did not grant is still denied', async () => {
|
|
287
|
+
registerAddon([])
|
|
288
|
+
wireAddon({
|
|
289
|
+
name: 'example',
|
|
290
|
+
package: ADDON_PACKAGE,
|
|
291
|
+
secretGrants: ['STRIPE_KEY'],
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
const secrets = await secretsHandedToAddon('example')
|
|
295
|
+
await assert.rejects(() => secrets.getSecret('DATABASE_URL'), /denied/i)
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
test('a grant adds to what the addon declared rather than replacing it', async () => {
|
|
299
|
+
registerAddon(['ADDON_KEY'])
|
|
300
|
+
wireAddon({
|
|
301
|
+
name: 'example',
|
|
302
|
+
package: ADDON_PACKAGE,
|
|
303
|
+
secretGrants: ['STRIPE_KEY'],
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
const secrets = await secretsHandedToAddon('example')
|
|
307
|
+
assert.equal(await secrets.getSecret('ADDON_KEY'), 'value-of-ADDON_KEY')
|
|
308
|
+
assert.equal(await secrets.getSecret('STRIPE_KEY'), 'value-of-STRIPE_KEY')
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
test('an overridden secret is granted by the override itself', async () => {
|
|
312
|
+
registerAddon([])
|
|
313
|
+
wireAddon({
|
|
314
|
+
name: 'example',
|
|
315
|
+
package: ADDON_PACKAGE,
|
|
316
|
+
secretOverrides: { MAILGUN_KEY: 'PROD_EMAIL_KEY' },
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
const secrets = await secretsHandedToAddon('example')
|
|
320
|
+
assert.equal(
|
|
321
|
+
await secrets.getSecret('MAILGUN_KEY'),
|
|
322
|
+
'value-of-PROD_EMAIL_KEY'
|
|
323
|
+
)
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
test('a grant is checked before the override renames it', async () => {
|
|
327
|
+
registerAddon([])
|
|
328
|
+
wireAddon({
|
|
329
|
+
name: 'example',
|
|
330
|
+
package: ADDON_PACKAGE,
|
|
331
|
+
secretGrants: ['MAILGUN_KEY'],
|
|
332
|
+
secretOverrides: { MAILGUN_KEY: 'PROD_EMAIL_KEY' },
|
|
333
|
+
})
|
|
334
|
+
|
|
335
|
+
const secrets = await secretsHandedToAddon('example')
|
|
336
|
+
assert.equal(
|
|
337
|
+
await secrets.getSecret('MAILGUN_KEY'),
|
|
338
|
+
'value-of-PROD_EMAIL_KEY'
|
|
339
|
+
)
|
|
340
|
+
await assert.rejects(() => secrets.getSecret('PROD_EMAIL_KEY'), /denied/i)
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
test('a granted credential is readable', async () => {
|
|
344
|
+
registerAddon([], [])
|
|
345
|
+
wireAddon({
|
|
346
|
+
name: 'example',
|
|
347
|
+
package: ADDON_PACKAGE,
|
|
348
|
+
credentialGrants: ['stripe'],
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
const credentials = await credentialsHandedToAddon('example')
|
|
352
|
+
assert.equal(await credentials.get('stripe'), 'credential-of-stripe')
|
|
353
|
+
await assert.rejects(() => credentials.get('slack'), /denied/i)
|
|
354
|
+
})
|
|
355
|
+
|
|
356
|
+
test('a granted credential does not widen the rest of the service', async () => {
|
|
357
|
+
registerAddon([], [])
|
|
358
|
+
wireAddon({
|
|
359
|
+
name: 'example',
|
|
360
|
+
package: ADDON_PACKAGE,
|
|
361
|
+
credentialGrants: ['stripe'],
|
|
362
|
+
})
|
|
363
|
+
|
|
364
|
+
const credentials = await credentialsHandedToAddon('example')
|
|
365
|
+
await assert.rejects(() => credentials.getAllUsers(), /denied/i)
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
test('an addon without a singleton factory is granted too', async () => {
|
|
369
|
+
pikkuState(ADDON_PACKAGE, 'package', 'declaredSecrets', [])
|
|
370
|
+
wireAddon({
|
|
371
|
+
name: 'example',
|
|
372
|
+
package: ADDON_PACKAGE,
|
|
373
|
+
secretGrants: ['STRIPE_KEY'],
|
|
374
|
+
})
|
|
375
|
+
|
|
376
|
+
const services = await getOrCreatePackageSingletonServices(
|
|
377
|
+
ADDON_PACKAGE,
|
|
378
|
+
createParentServices(),
|
|
379
|
+
pikkuState(null, 'addons', 'packages').get('example') as never
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
assert.equal(
|
|
383
|
+
await services.secrets.getSecret('STRIPE_KEY'),
|
|
384
|
+
'value-of-STRIPE_KEY'
|
|
385
|
+
)
|
|
386
|
+
await assert.rejects(
|
|
387
|
+
() => services.secrets.getSecret('DATABASE_URL'),
|
|
388
|
+
/denied/i
|
|
389
|
+
)
|
|
390
|
+
})
|
|
391
|
+
})
|
|
@@ -284,6 +284,8 @@ export class ContextAwareRPCService {
|
|
|
284
284
|
secretOverrides: resolved.addonConfig?.secretOverrides,
|
|
285
285
|
variableOverrides: resolved.addonConfig?.variableOverrides,
|
|
286
286
|
credentialOverrides: resolved.addonConfig?.credentialOverrides,
|
|
287
|
+
secretGrants: resolved.addonConfig?.secretGrants,
|
|
288
|
+
credentialGrants: resolved.addonConfig?.credentialGrants,
|
|
287
289
|
globalSecrets: resolved.addonConfig?.globalSecrets,
|
|
288
290
|
globalCredentials: resolved.addonConfig?.globalCredentials,
|
|
289
291
|
},
|
|
@@ -67,6 +67,10 @@ export interface ResolvedFunction {
|
|
|
67
67
|
secretOverrides?: Record<string, string>
|
|
68
68
|
variableOverrides?: Record<string, string>
|
|
69
69
|
credentialOverrides?: Record<string, string>
|
|
70
|
+
/** Set by the consuming app: secrets it lends this instance, as the addon names them */
|
|
71
|
+
secretGrants?: string[]
|
|
72
|
+
/** Set by the consuming app: credentials it lends this instance, as the addon names them */
|
|
73
|
+
credentialGrants?: string[]
|
|
70
74
|
/** Set by the consuming app: hand this instance the unscoped `SecretService` */
|
|
71
75
|
globalSecrets?: string
|
|
72
76
|
/** Set by the consuming app: hand this instance the unscoped `CredentialService` */
|
|
@@ -14,6 +14,18 @@ export type WireAddonConfig = {
|
|
|
14
14
|
secretOverrides?: Record<string, string>
|
|
15
15
|
variableOverrides?: Record<string, string>
|
|
16
16
|
credentialOverrides?: Record<string, string>
|
|
17
|
+
/**
|
|
18
|
+
* Secrets this instance may read on top of the ones it declared, named as the
|
|
19
|
+
* addon reads them — the scope check runs before `secretOverrides` renames
|
|
20
|
+
* them, so an overridden secret is named here by its addon-side key. Listing
|
|
21
|
+
* one in `secretOverrides` grants it too.
|
|
22
|
+
*
|
|
23
|
+
* For an addon whose secret names come off its input rather than its own
|
|
24
|
+
* source, this is how the host lends names the addon could not declare.
|
|
25
|
+
*/
|
|
26
|
+
secretGrants?: string[]
|
|
27
|
+
/** Credentials this instance may read on top of the ones it declared. */
|
|
28
|
+
credentialGrants?: string[]
|
|
17
29
|
/**
|
|
18
30
|
* Hands this instance the whole `SecretService` instead of one scoped to the
|
|
19
31
|
* secrets it declared. The value is the reason, recorded in the deploy
|
|
@@ -45,6 +57,10 @@ export const wireAddon = (config: WireAddonConfig): void => {
|
|
|
45
57
|
...(config.credentialOverrides
|
|
46
58
|
? { credentialOverrides: config.credentialOverrides }
|
|
47
59
|
: {}),
|
|
60
|
+
...(config.secretGrants ? { secretGrants: config.secretGrants } : {}),
|
|
61
|
+
...(config.credentialGrants
|
|
62
|
+
? { credentialGrants: config.credentialGrants }
|
|
63
|
+
: {}),
|
|
48
64
|
...(config.globalSecrets ? { globalSecrets: config.globalSecrets } : {}),
|
|
49
65
|
...(config.globalCredentials
|
|
50
66
|
? { globalCredentials: config.globalCredentials }
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { pikkuState } from '../../pikku-state.js'
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
CoreWorkflow,
|
|
5
|
-
FeaturePlanEntry,
|
|
6
|
-
} from './workflow.types.js'
|
|
2
|
+
import type { CoreWorkflow } from './workflow.types.js'
|
|
3
|
+
import type { CoreFeature, FeaturePlanEntry } from './scenario.types.js'
|
|
7
4
|
|
|
8
5
|
export const addFeature = (
|
|
9
6
|
featureId: string,
|
|
@@ -28,13 +28,9 @@ export {
|
|
|
28
28
|
reconstructStateAt,
|
|
29
29
|
reconstructFinalState,
|
|
30
30
|
} from './run-timeline.js'
|
|
31
|
-
export type {
|
|
32
|
-
RunTimeline,
|
|
33
|
-
ReconstructedRunState,
|
|
34
|
-
} from './run-timeline.js'
|
|
31
|
+
export type { RunTimeline, ReconstructedRunState } from './run-timeline.js'
|
|
35
32
|
|
|
36
33
|
export { addWorkflow } from './dsl/workflow-runner.js'
|
|
37
|
-
export { addFeature, resolveFeatureScenarios } from './feature.js'
|
|
38
34
|
|
|
39
35
|
export { template, type TemplateString } from './graph/template.js'
|
|
40
36
|
export {
|
|
@@ -63,10 +59,6 @@ export type {
|
|
|
63
59
|
WorkflowRunService,
|
|
64
60
|
WorkflowRunMirror,
|
|
65
61
|
CoreWorkflow,
|
|
66
|
-
CoreFeature,
|
|
67
|
-
FeatureMeta,
|
|
68
|
-
FeaturesMeta,
|
|
69
|
-
FeaturePlanEntry,
|
|
70
62
|
PikkuWorkflow,
|
|
71
63
|
ContextVariable,
|
|
72
64
|
WorkflowContext,
|
|
@@ -97,47 +89,7 @@ export type {
|
|
|
97
89
|
SwitchStepMeta,
|
|
98
90
|
FilterStepMeta,
|
|
99
91
|
ArrayPredicateStepMeta,
|
|
100
|
-
ScenarioStepInvocation,
|
|
101
|
-
ScenarioStepMeta,
|
|
102
92
|
WorkflowStepMeta,
|
|
103
93
|
WorkflowStepWire,
|
|
104
94
|
PikkuWorkflowWire,
|
|
105
|
-
PikkuScenarioWire,
|
|
106
95
|
} from './workflow.types.js'
|
|
107
|
-
|
|
108
|
-
export type {
|
|
109
|
-
ScenarioStepPhase,
|
|
110
|
-
ScenarioStepKind,
|
|
111
|
-
ScenarioStepOptions,
|
|
112
|
-
PikkuScenarioStepWire,
|
|
113
|
-
ScenarioEnvironment,
|
|
114
|
-
ScenarioSurface,
|
|
115
|
-
ScenarioSurfaceResolution,
|
|
116
|
-
} from './scenario-step.types.js'
|
|
117
|
-
export { SCENARIO_SURFACES } from './scenario-step.types.js'
|
|
118
|
-
|
|
119
|
-
// Which of a step's bindings run: one for an action, every witness for a `then`
|
|
120
|
-
export { resolveScenarioSurfaces } from './scenario-surface.js'
|
|
121
|
-
|
|
122
|
-
export { requireActor, requireScenarioEnv } from './scenario-step-guards.js'
|
|
123
|
-
|
|
124
|
-
export { pollUntil, type PollOptions } from './scenario-poll.js'
|
|
125
|
-
|
|
126
|
-
export { createCookieJar } from './scenario-cookie-jar.js'
|
|
127
|
-
export type { ScenarioCookieJar } from './scenario-cookie-jar.js'
|
|
128
|
-
|
|
129
|
-
export type {
|
|
130
|
-
ScenarioHttpResponse,
|
|
131
|
-
ScenarioJsonRequest,
|
|
132
|
-
} from '../../services/personas-service.js'
|
|
133
|
-
// The readers themselves live on `@pikku/core/persona`; workflow is a production
|
|
134
|
-
// wiring and must not pull scenario runtime in behind it.
|
|
135
|
-
|
|
136
|
-
export type {
|
|
137
|
-
PikkuBrowserWire,
|
|
138
|
-
TestIdSelector,
|
|
139
|
-
ScenarioBrowserProvider,
|
|
140
|
-
ScenarioBrowserFailure,
|
|
141
|
-
} from './scenario-step.types.js'
|
|
142
|
-
|
|
143
|
-
export { composeStepProse, renderStepTemplate } from './scenario-prose.js'
|
|
@@ -27,10 +27,10 @@ import type {
|
|
|
27
27
|
} from './scenario-step.types.js'
|
|
28
28
|
import { resolveScenarioSurfaces, witnessesAgree } from './scenario-surface.js'
|
|
29
29
|
import type {
|
|
30
|
-
PikkuScenarioWire,
|
|
31
30
|
PikkuWorkflowWire,
|
|
32
31
|
WorkflowQueueOptions,
|
|
33
32
|
} from './workflow.types.js'
|
|
33
|
+
import type { PikkuScenarioWire } from './scenario.types.js'
|
|
34
34
|
import type {
|
|
35
35
|
WorkflowExpectEventuallyOptions,
|
|
36
36
|
WorkflowExpectErrorOptions,
|
|
@@ -38,6 +38,26 @@ import type {
|
|
|
38
38
|
WorkflowExpectServiceOptions,
|
|
39
39
|
} from './dsl/workflow-dsl.types.js'
|
|
40
40
|
|
|
41
|
+
export { addFeature, resolveFeatureScenarios } from './feature.js'
|
|
42
|
+
export type * from './scenario.types.js'
|
|
43
|
+
export { SCENARIO_SURFACES } from './scenario-step.types.js'
|
|
44
|
+
|
|
45
|
+
// Which of a step's bindings run: one for an action, every witness for a `then`
|
|
46
|
+
export { resolveScenarioSurfaces } from './scenario-surface.js'
|
|
47
|
+
|
|
48
|
+
export { pollUntil, type PollOptions } from './scenario-poll.js'
|
|
49
|
+
export { createCookieJar } from './scenario-cookie-jar.js'
|
|
50
|
+
export type { ScenarioCookieJar } from './scenario-cookie-jar.js'
|
|
51
|
+
export { composeStepProse, renderStepTemplate } from './scenario-prose.js'
|
|
52
|
+
|
|
53
|
+
export { requireActor, requireScenarioEnv } from './scenario-step-guards.js'
|
|
54
|
+
|
|
55
|
+
export type {
|
|
56
|
+
ScenarioHttpResponse,
|
|
57
|
+
ScenarioJsonRequest,
|
|
58
|
+
} from '../../services/personas-service.js'
|
|
59
|
+
// The readers themselves live on `@pikku/core/persona`
|
|
60
|
+
|
|
41
61
|
/**
|
|
42
62
|
* A workflow service with the scenario capability attached — the two lines
|
|
43
63
|
* `pikku scenario run` needs, in one call so no caller has to remember that the
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CorePikkuFunctionConfig,
|
|
3
|
+
CorePikkuFunctionHook,
|
|
4
|
+
} from '../../function/functions.types.js'
|
|
5
|
+
|
|
6
|
+
export type {
|
|
7
|
+
ScenarioStepInvocation,
|
|
8
|
+
ScenarioStepMeta,
|
|
9
|
+
PikkuScenarioWire,
|
|
10
|
+
} from './dsl/workflow-dsl.types.js'
|
|
11
|
+
|
|
12
|
+
export type {
|
|
13
|
+
ScenarioStepPhase,
|
|
14
|
+
ScenarioStepKind,
|
|
15
|
+
ScenarioStepOptions,
|
|
16
|
+
PikkuScenarioStepWire,
|
|
17
|
+
ScenarioEnvironment,
|
|
18
|
+
ScenarioSurface,
|
|
19
|
+
ScenarioSurfaceResolution,
|
|
20
|
+
PikkuBrowserWire,
|
|
21
|
+
TestIdSelector,
|
|
22
|
+
ScenarioBrowserProvider,
|
|
23
|
+
ScenarioBrowserFailure,
|
|
24
|
+
} from './scenario-step.types.js'
|
|
25
|
+
|
|
26
|
+
export type CoreFeatureScenario =
|
|
27
|
+
| CorePikkuFunctionConfig<any, any, any>
|
|
28
|
+
| { scenario: CorePikkuFunctionConfig<any, any, any>; data: unknown }
|
|
29
|
+
|
|
30
|
+
export type CoreFeature = {
|
|
31
|
+
name: string
|
|
32
|
+
description?: string
|
|
33
|
+
tags?: string[]
|
|
34
|
+
scenarios: readonly CoreFeatureScenario[]
|
|
35
|
+
before?: CorePikkuFunctionHook
|
|
36
|
+
after?: CorePikkuFunctionHook
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type FeatureMetaEntry = {
|
|
40
|
+
scenario: string
|
|
41
|
+
data?: unknown
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type FeatureMeta = {
|
|
45
|
+
id: string
|
|
46
|
+
name: string
|
|
47
|
+
description?: string
|
|
48
|
+
tags: string[]
|
|
49
|
+
entries: FeatureMetaEntry[]
|
|
50
|
+
unresolvedEntries: number
|
|
51
|
+
hasBefore: boolean
|
|
52
|
+
hasAfter: boolean
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type FeaturesMeta = Record<string, FeatureMeta>
|
|
56
|
+
|
|
57
|
+
export type FeaturePlanEntry = {
|
|
58
|
+
featureId: string
|
|
59
|
+
featureName: string
|
|
60
|
+
scenarioName: string
|
|
61
|
+
data?: unknown
|
|
62
|
+
tags: string[]
|
|
63
|
+
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import type { SerializedError, CommonWireMeta } from '../../types/core.types.js'
|
|
2
|
-
import type {
|
|
3
|
-
CorePikkuFunctionConfig,
|
|
4
|
-
CorePikkuFunctionHook,
|
|
5
|
-
} from '../../function/functions.types.js'
|
|
2
|
+
import type { CorePikkuFunctionConfig } from '../../function/functions.types.js'
|
|
6
3
|
import type { GroupConcurrencyConfig } from '../queue/queue.types.js'
|
|
7
4
|
|
|
8
5
|
export type { WorkflowService } from '../../services/workflow-service.js'
|
|
@@ -30,22 +27,11 @@ export type {
|
|
|
30
27
|
SwitchStepMeta,
|
|
31
28
|
FilterStepMeta,
|
|
32
29
|
ArrayPredicateStepMeta,
|
|
33
|
-
ScenarioStepInvocation,
|
|
34
|
-
ScenarioStepMeta,
|
|
35
30
|
WorkflowStepMeta,
|
|
36
31
|
WorkflowStepWire,
|
|
37
32
|
PikkuWorkflowWire,
|
|
38
|
-
PikkuScenarioWire,
|
|
39
33
|
} from './dsl/workflow-dsl.types.js'
|
|
40
34
|
|
|
41
|
-
export type {
|
|
42
|
-
ScenarioStepPhase,
|
|
43
|
-
ScenarioStepOptions,
|
|
44
|
-
PikkuScenarioStepWire,
|
|
45
|
-
PikkuBrowserWire,
|
|
46
|
-
ScenarioBrowserProvider,
|
|
47
|
-
} from './scenario-step.types.js'
|
|
48
|
-
|
|
49
35
|
import type { WorkflowStepMeta } from './dsl/workflow-dsl.types.js'
|
|
50
36
|
|
|
51
37
|
export interface WorkflowRunWire {
|
|
@@ -238,45 +224,6 @@ export type CoreWorkflow<
|
|
|
238
224
|
tags?: string[]
|
|
239
225
|
}
|
|
240
226
|
|
|
241
|
-
export type CoreFeatureScenario =
|
|
242
|
-
| CorePikkuFunctionConfig<any, any, any>
|
|
243
|
-
| { scenario: CorePikkuFunctionConfig<any, any, any>; data: unknown }
|
|
244
|
-
|
|
245
|
-
export type CoreFeature = {
|
|
246
|
-
name: string
|
|
247
|
-
description?: string
|
|
248
|
-
tags?: string[]
|
|
249
|
-
scenarios: readonly CoreFeatureScenario[]
|
|
250
|
-
before?: CorePikkuFunctionHook
|
|
251
|
-
after?: CorePikkuFunctionHook
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
export type FeatureMetaEntry = {
|
|
255
|
-
scenario: string
|
|
256
|
-
data?: unknown
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
export type FeatureMeta = {
|
|
260
|
-
id: string
|
|
261
|
-
name: string
|
|
262
|
-
description?: string
|
|
263
|
-
tags: string[]
|
|
264
|
-
entries: FeatureMetaEntry[]
|
|
265
|
-
unresolvedEntries: number
|
|
266
|
-
hasBefore: boolean
|
|
267
|
-
hasAfter: boolean
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
export type FeaturesMeta = Record<string, FeatureMeta>
|
|
271
|
-
|
|
272
|
-
export type FeaturePlanEntry = {
|
|
273
|
-
featureId: string
|
|
274
|
-
featureName: string
|
|
275
|
-
scenarioName: string
|
|
276
|
-
data?: unknown
|
|
277
|
-
tags: string[]
|
|
278
|
-
}
|
|
279
|
-
|
|
280
227
|
export interface PikkuWorkflow {
|
|
281
228
|
start: <I>(input: I) => Promise<{ runId: string }>
|
|
282
229
|
getRun: (runId: string) => Promise<WorkflowRun>
|