@pikku/core 0.12.50 → 0.12.52

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 (46) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/dist/index.d.ts +1 -1
  3. package/dist/services/http-scenario-actors.d.ts +67 -0
  4. package/dist/services/http-scenario-actors.js +193 -0
  5. package/dist/services/http-user-flow-actors.d.ts +20 -0
  6. package/dist/services/http-user-flow-actors.js +100 -0
  7. package/dist/services/index.d.ts +2 -2
  8. package/dist/services/index.js +1 -1
  9. package/dist/services/meta-service.d.ts +4 -4
  10. package/dist/services/meta-service.js +8 -8
  11. package/dist/services/scenario-actors-service.d.ts +39 -0
  12. package/dist/services/scenario-actors-service.js +1 -0
  13. package/dist/services/user-flow-actors-service.d.ts +11 -1
  14. package/dist/types/core.types.d.ts +48 -4
  15. package/dist/wirings/actor-flow/actor-flow.types.d.ts +68 -0
  16. package/dist/wirings/actor-flow/actor-flow.types.js +1 -0
  17. package/dist/wirings/actor-flow/index.d.ts +11 -0
  18. package/dist/wirings/actor-flow/index.js +1 -0
  19. package/dist/wirings/actor-flow/run-conversation.d.ts +36 -0
  20. package/dist/wirings/actor-flow/run-conversation.js +181 -0
  21. package/dist/wirings/http/http.types.d.ts +1 -0
  22. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +6 -6
  23. package/dist/wirings/workflow/pikku-workflow-service.d.ts +10 -2
  24. package/dist/wirings/workflow/pikku-workflow-service.js +42 -2
  25. package/dist/wirings/workflow/workflow.types.d.ts +6 -6
  26. package/package.json +2 -1
  27. package/run-tests.sh +4 -4
  28. package/src/index.ts +6 -0
  29. package/src/services/http-scenario-actors-converse.test.ts +222 -0
  30. package/src/services/{http-user-flow-actors.test.ts → http-scenario-actors.test.ts} +17 -7
  31. package/src/services/http-scenario-actors.ts +269 -0
  32. package/src/services/index.ts +8 -8
  33. package/src/services/meta-service.ts +9 -9
  34. package/src/services/{user-flow-actors-service.ts → scenario-actors-service.ts} +18 -4
  35. package/src/types/core.types.ts +53 -4
  36. package/src/wirings/actor-flow/actor-flow.types.ts +73 -0
  37. package/src/wirings/actor-flow/index.ts +22 -0
  38. package/src/wirings/actor-flow/run-conversation.test.ts +176 -0
  39. package/src/wirings/actor-flow/run-conversation.ts +285 -0
  40. package/src/wirings/http/http.types.ts +1 -0
  41. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +6 -6
  42. package/src/wirings/workflow/pikku-workflow-service.ts +50 -5
  43. package/src/wirings/workflow/{user-flow-step.test.ts → scenario-step.test.ts} +19 -14
  44. package/src/wirings/workflow/workflow.types.ts +6 -6
  45. package/tsconfig.tsbuildinfo +1 -1
  46. package/src/services/http-user-flow-actors.ts +0 -132
@@ -1,132 +0,0 @@
1
- import type {
2
- UserFlowActor,
3
- UserFlowActorConfig,
4
- UserFlowActors,
5
- } from './user-flow-actors-service.js'
6
-
7
- export interface HttpUserFlowActorsConfig {
8
- /**
9
- * Base API URL of the target app, INCLUDING the HTTP prefix — e.g.
10
- * `https://app.example.com/api` or `http://localhost:4000/api`. Actor
11
- * sign-in is reached at `${apiUrl}${signInPath}` and exposed RPCs at
12
- * `${apiUrl}${rpcPath}/:rpcName`.
13
- */
14
- apiUrl: string
15
- /**
16
- * The actor impersonation secret. Sign-in only ever works for user rows
17
- * flagged `actor: true` — knowing the secret never impersonates real users.
18
- */
19
- secret: string
20
- /** Actor name → config (usually from pikku.config.json's actor registry). */
21
- actors: Record<string, UserFlowActorConfig>
22
- /** Sign-in path under apiUrl. Default: the actor plugin's `/auth/sign-in/actor`. */
23
- signInPath?: string
24
- /** Exposed-RPC path prefix under apiUrl. Default `/rpc`. */
25
- rpcPath?: string
26
- }
27
-
28
- /**
29
- * Default HTTP-backed actor. Signs in lazily on first invoke via the Better
30
- * Auth actor plugin (`POST /auth/sign-in/actor` with `{ email, secret }` —
31
- * the plugin upserts the actor-flagged user row and mints a session whose
32
- * `actor` flag flows into audits/analytics). Holds the session cookies for
33
- * its lifetime; a 401 mid-run re-logs-in once (long health-check runs can
34
- * outlive a session).
35
- */
36
- export class HttpUserFlowActor implements UserFlowActor {
37
- private cookie: string | null = null
38
- private origin: string
39
-
40
- constructor(
41
- readonly name: string,
42
- private actorConfig: UserFlowActorConfig,
43
- private config: HttpUserFlowActorsConfig
44
- ) {
45
- this.origin = new URL(config.apiUrl).origin
46
- }
47
-
48
- get email(): string {
49
- return this.actorConfig.email
50
- }
51
-
52
- async invoke(rpcName: string, data: unknown): Promise<unknown> {
53
- const cookie = this.cookie ?? (await this.login())
54
- const res = await this.postRpc(rpcName, data, cookie)
55
- if (res.status === 401) {
56
- // Session expired mid-run — re-login once and retry.
57
- this.cookie = null
58
- return this.readRpcResponse(rpcName, await this.postRpc(rpcName, data, await this.login()))
59
- }
60
- return this.readRpcResponse(rpcName, res)
61
- }
62
-
63
- private async postRpc(rpcName: string, data: unknown, cookie: string) {
64
- const rpcPath = this.config.rpcPath ?? '/rpc'
65
- return fetch(`${this.config.apiUrl}${rpcPath}/${rpcName}`, {
66
- method: 'POST',
67
- headers: {
68
- 'content-type': 'application/json',
69
- origin: this.origin,
70
- cookie,
71
- },
72
- body: JSON.stringify({ data }),
73
- })
74
- }
75
-
76
- private async readRpcResponse(rpcName: string, res: Response) {
77
- if (!res.ok) {
78
- const body = (await res.text().catch(() => '')).slice(0, 300)
79
- throw new Error(
80
- `[user-flow] '${rpcName}' as '${this.name}' returned ${res.status}: ${body}`
81
- )
82
- }
83
- if (res.status === 204) return undefined
84
- const text = await res.text()
85
- return text ? JSON.parse(text) : undefined
86
- }
87
-
88
- private async login(): Promise<string> {
89
- const signInPath = this.config.signInPath ?? '/auth/sign-in/actor'
90
- const res = await fetch(`${this.config.apiUrl}${signInPath}`, {
91
- method: 'POST',
92
- headers: { 'content-type': 'application/json', origin: this.origin },
93
- body: JSON.stringify({
94
- email: this.actorConfig.email,
95
- name: this.actorConfig.name ?? this.name,
96
- secret: this.config.secret,
97
- }),
98
- })
99
- if (!res.ok) {
100
- const body = (await res.text().catch(() => '')).slice(0, 300)
101
- throw new Error(
102
- `[user-flow] actor sign-in failed for '${this.name}' (${res.status}): ${body}`
103
- )
104
- }
105
- const setCookies = res.headers.getSetCookie?.() ?? []
106
- const cookie = setCookies
107
- .map((c) => c.split(';')[0]!)
108
- .filter(Boolean)
109
- .join('; ')
110
- if (!cookie) {
111
- throw new Error(
112
- `[user-flow] actor sign-in for '${this.name}' returned no session cookie`
113
- )
114
- }
115
- this.cookie = cookie
116
- return cookie
117
- }
118
- }
119
-
120
- /**
121
- * Build the injected `actors` service from the config registry: actor name →
122
- * lazy HTTP actor. Wire the result as the `actors` singleton service.
123
- */
124
- export function createHttpUserFlowActors(
125
- config: HttpUserFlowActorsConfig
126
- ): UserFlowActors {
127
- const actors: UserFlowActors = {}
128
- for (const [name, actorConfig] of Object.entries(config.actors)) {
129
- actors[name] = new HttpUserFlowActor(name, actorConfig, config)
130
- }
131
- return actors
132
- }