@pikku/core 0.12.2 → 0.12.4

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 (282) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/crypto-utils.d.ts +10 -0
  3. package/dist/crypto-utils.js +62 -0
  4. package/dist/function/function-runner.js +4 -4
  5. package/dist/function/functions.types.d.ts +26 -1
  6. package/dist/function/functions.types.js +16 -0
  7. package/dist/handle-error.d.ts +1 -1
  8. package/dist/handle-error.js +7 -3
  9. package/dist/index.d.ts +14 -2
  10. package/dist/index.js +1 -1
  11. package/dist/pikku-state.js +3 -1
  12. package/dist/schema.js +1 -1
  13. package/dist/services/in-memory-workflow-service.d.ts +22 -3
  14. package/dist/services/in-memory-workflow-service.js +77 -1
  15. package/dist/services/workflow-service.d.ts +8 -2
  16. package/dist/testing/index.d.ts +2 -0
  17. package/dist/testing/index.js +1 -0
  18. package/dist/testing/service-tests.d.ts +31 -0
  19. package/dist/testing/service-tests.js +598 -0
  20. package/dist/types/core.types.d.ts +9 -1
  21. package/dist/types/state.types.d.ts +4 -2
  22. package/dist/utils/hash.d.ts +2 -0
  23. package/dist/utils/hash.js +23 -0
  24. package/dist/wirings/ai-agent/agent-dynamic-workflow.d.ts +6 -0
  25. package/dist/wirings/ai-agent/agent-dynamic-workflow.js +348 -0
  26. package/dist/wirings/ai-agent/ai-agent-memory.d.ts +1 -1
  27. package/dist/wirings/ai-agent/ai-agent-memory.js +6 -5
  28. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +10 -7
  29. package/dist/wirings/ai-agent/ai-agent-prepare.js +127 -47
  30. package/dist/wirings/ai-agent/ai-agent-runner.d.ts +4 -0
  31. package/dist/wirings/ai-agent/ai-agent-runner.js +381 -27
  32. package/dist/wirings/ai-agent/ai-agent-stream.d.ts +7 -2
  33. package/dist/wirings/ai-agent/ai-agent-stream.js +109 -46
  34. package/dist/wirings/ai-agent/ai-agent.types.d.ts +22 -1
  35. package/dist/wirings/ai-agent/index.d.ts +1 -2
  36. package/dist/wirings/ai-agent/index.js +1 -2
  37. package/dist/wirings/channel/channel-handler.js +5 -1
  38. package/dist/wirings/channel/channel.types.d.ts +1 -7
  39. package/dist/wirings/channel/local/local-channel-handler.d.ts +1 -1
  40. package/dist/wirings/channel/local/local-channel-handler.js +5 -3
  41. package/dist/wirings/channel/local/local-channel-runner.js +14 -4
  42. package/dist/wirings/channel/serverless/serverless-channel-runner.js +4 -1
  43. package/dist/wirings/cli/cli-runner.js +10 -2
  44. package/dist/wirings/cli/cli.types.d.ts +1 -0
  45. package/dist/wirings/http/http-routes.js +0 -1
  46. package/dist/wirings/http/http-runner.d.ts +1 -1
  47. package/dist/wirings/http/http-runner.js +25 -3
  48. package/dist/wirings/http/http.types.d.ts +3 -11
  49. package/dist/wirings/http/index.d.ts +2 -1
  50. package/dist/wirings/http/index.js +1 -0
  51. package/dist/wirings/http/pikku-fetch-http-request.d.ts +1 -0
  52. package/dist/wirings/http/pikku-fetch-http-request.js +3 -0
  53. package/dist/wirings/http/pikku-fetch-http-response.d.ts +1 -0
  54. package/dist/wirings/http/pikku-fetch-http-response.js +4 -4
  55. package/dist/wirings/http/web-request.d.ts +12 -0
  56. package/dist/wirings/http/web-request.js +85 -0
  57. package/dist/wirings/mcp/mcp-endpoint-registry.js +1 -1
  58. package/dist/wirings/mcp/mcp-runner.js +13 -1
  59. package/dist/wirings/rpc/rpc-runner.d.ts +30 -6
  60. package/dist/wirings/rpc/rpc-runner.js +36 -14
  61. package/dist/wirings/rpc/rpc-types.d.ts +6 -1
  62. package/dist/wirings/rpc/wire-addon.d.ts +1 -0
  63. package/dist/wirings/rpc/wire-addon.js +1 -1
  64. package/dist/wirings/scheduler/scheduler-runner.js +1 -0
  65. package/dist/wirings/workflow/graph/graph-validation.d.ts +3 -0
  66. package/dist/wirings/workflow/graph/graph-validation.js +175 -0
  67. package/dist/wirings/workflow/graph/index.d.ts +1 -0
  68. package/dist/wirings/workflow/graph/index.js +1 -0
  69. package/dist/wirings/workflow/index.d.ts +1 -1
  70. package/dist/wirings/workflow/pikku-workflow-service.d.ts +8 -2
  71. package/dist/wirings/workflow/pikku-workflow-service.js +1 -2
  72. package/dist/wirings/workflow/workflow.types.d.ts +10 -1
  73. package/lcov.info +18891 -0
  74. package/package.json +4 -2
  75. package/dist/wirings/ai-agent/ai-agent-assistant-ui.d.ts +0 -5
  76. package/dist/wirings/ai-agent/ai-agent-assistant-ui.js +0 -168
  77. package/src/crypto-utils.test.ts +0 -116
  78. package/src/crypto-utils.ts +0 -99
  79. package/src/errors/error-handler.ts +0 -62
  80. package/src/errors/error.test.ts +0 -195
  81. package/src/errors/errors.ts +0 -374
  82. package/src/errors/index.ts +0 -2
  83. package/src/factory-functions.test.ts +0 -109
  84. package/src/function/function-runner.test.ts +0 -536
  85. package/src/function/function-runner.ts +0 -365
  86. package/src/function/functions.types.ts +0 -267
  87. package/src/function/index.ts +0 -5
  88. package/src/handle-error.test.ts +0 -361
  89. package/src/handle-error.ts +0 -65
  90. package/src/index.ts +0 -104
  91. package/src/internal.ts +0 -6
  92. package/src/middleware/auth-apikey.test.ts +0 -363
  93. package/src/middleware/auth-apikey.ts +0 -47
  94. package/src/middleware/auth-bearer.test.ts +0 -450
  95. package/src/middleware/auth-bearer.ts +0 -72
  96. package/src/middleware/auth-cookie.test.ts +0 -528
  97. package/src/middleware/auth-cookie.ts +0 -80
  98. package/src/middleware/cors.test.ts +0 -424
  99. package/src/middleware/cors.ts +0 -104
  100. package/src/middleware/index.ts +0 -5
  101. package/src/middleware/remote-auth.test.ts +0 -488
  102. package/src/middleware/remote-auth.ts +0 -68
  103. package/src/middleware/timeout.ts +0 -15
  104. package/src/middleware-runner.test.ts +0 -418
  105. package/src/middleware-runner.ts +0 -234
  106. package/src/permissions.test.ts +0 -434
  107. package/src/permissions.ts +0 -319
  108. package/src/pikku-request.ts +0 -23
  109. package/src/pikku-response.ts +0 -5
  110. package/src/pikku-state.test.ts +0 -224
  111. package/src/pikku-state.ts +0 -214
  112. package/src/run-tests-script.test.ts +0 -49
  113. package/src/schema.test.ts +0 -249
  114. package/src/schema.ts +0 -151
  115. package/src/services/ai-agent-runner-service.ts +0 -41
  116. package/src/services/ai-run-state-service.ts +0 -20
  117. package/src/services/ai-storage-service.ts +0 -39
  118. package/src/services/content-service.ts +0 -76
  119. package/src/services/deployment-service.ts +0 -22
  120. package/src/services/gateway-service.ts +0 -20
  121. package/src/services/gopass-secrets.ts +0 -98
  122. package/src/services/in-memory-ai-run-state-service.ts +0 -73
  123. package/src/services/in-memory-trigger-service.ts +0 -64
  124. package/src/services/in-memory-workflow-service.test.ts +0 -351
  125. package/src/services/in-memory-workflow-service.ts +0 -395
  126. package/src/services/index.ts +0 -56
  127. package/src/services/jwt-service.ts +0 -30
  128. package/src/services/local-content.ts +0 -120
  129. package/src/services/local-gateway-service.ts +0 -62
  130. package/src/services/local-secrets.test.ts +0 -80
  131. package/src/services/local-secrets.ts +0 -94
  132. package/src/services/local-variables.test.ts +0 -61
  133. package/src/services/local-variables.ts +0 -39
  134. package/src/services/logger-console.test.ts +0 -118
  135. package/src/services/logger-console.ts +0 -98
  136. package/src/services/logger.ts +0 -57
  137. package/src/services/scheduler-service.ts +0 -86
  138. package/src/services/schema-service.ts +0 -33
  139. package/src/services/scoped-secret-service.test.ts +0 -74
  140. package/src/services/scoped-secret-service.ts +0 -41
  141. package/src/services/secret-service.ts +0 -38
  142. package/src/services/trigger-service.ts +0 -17
  143. package/src/services/typed-secret-service.test.ts +0 -93
  144. package/src/services/typed-secret-service.ts +0 -70
  145. package/src/services/typed-variables-service.test.ts +0 -73
  146. package/src/services/typed-variables-service.ts +0 -81
  147. package/src/services/user-session-service.test.ts +0 -113
  148. package/src/services/user-session-service.ts +0 -86
  149. package/src/services/variables-service.ts +0 -11
  150. package/src/services/workflow-service.ts +0 -84
  151. package/src/time-utils.test.ts +0 -56
  152. package/src/time-utils.ts +0 -107
  153. package/src/types/core.types.ts +0 -470
  154. package/src/types/state.types.ts +0 -186
  155. package/src/utils.test.ts +0 -350
  156. package/src/utils.ts +0 -129
  157. package/src/version.test.ts +0 -80
  158. package/src/version.ts +0 -25
  159. package/src/wirings/ai-agent/ai-agent-assistant-ui.test.ts +0 -363
  160. package/src/wirings/ai-agent/ai-agent-assistant-ui.ts +0 -238
  161. package/src/wirings/ai-agent/ai-agent-helpers.test.ts +0 -152
  162. package/src/wirings/ai-agent/ai-agent-helpers.ts +0 -76
  163. package/src/wirings/ai-agent/ai-agent-memory.ts +0 -309
  164. package/src/wirings/ai-agent/ai-agent-model-config.test.ts +0 -115
  165. package/src/wirings/ai-agent/ai-agent-model-config.ts +0 -43
  166. package/src/wirings/ai-agent/ai-agent-prepare.ts +0 -522
  167. package/src/wirings/ai-agent/ai-agent-registry.test.ts +0 -37
  168. package/src/wirings/ai-agent/ai-agent-registry.ts +0 -82
  169. package/src/wirings/ai-agent/ai-agent-runner.test.ts +0 -317
  170. package/src/wirings/ai-agent/ai-agent-runner.ts +0 -251
  171. package/src/wirings/ai-agent/ai-agent-stream.test.ts +0 -652
  172. package/src/wirings/ai-agent/ai-agent-stream.ts +0 -1060
  173. package/src/wirings/ai-agent/ai-agent.types.ts +0 -360
  174. package/src/wirings/ai-agent/index.ts +0 -41
  175. package/src/wirings/channel/channel-common.ts +0 -90
  176. package/src/wirings/channel/channel-handler.ts +0 -241
  177. package/src/wirings/channel/channel-middleware-runner.ts +0 -120
  178. package/src/wirings/channel/channel-runner.ts +0 -166
  179. package/src/wirings/channel/channel-store.ts +0 -29
  180. package/src/wirings/channel/channel.types.ts +0 -178
  181. package/src/wirings/channel/define-channel-routes.ts +0 -25
  182. package/src/wirings/channel/eventhub-service.ts +0 -34
  183. package/src/wirings/channel/eventhub-store.ts +0 -13
  184. package/src/wirings/channel/index.ts +0 -24
  185. package/src/wirings/channel/local/index.ts +0 -3
  186. package/src/wirings/channel/local/local-channel-handler.ts +0 -79
  187. package/src/wirings/channel/local/local-channel-runner.test.ts +0 -215
  188. package/src/wirings/channel/local/local-channel-runner.ts +0 -200
  189. package/src/wirings/channel/local/local-eventhub-service.test.ts +0 -95
  190. package/src/wirings/channel/local/local-eventhub-service.ts +0 -101
  191. package/src/wirings/channel/log-channels.ts +0 -20
  192. package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +0 -54
  193. package/src/wirings/channel/pikku-abstract-channel-handler.ts +0 -45
  194. package/src/wirings/channel/serverless/index.ts +0 -5
  195. package/src/wirings/channel/serverless/serverless-channel-runner.ts +0 -286
  196. package/src/wirings/cli/channel/cli-channel-runner.ts +0 -136
  197. package/src/wirings/cli/channel/index.ts +0 -1
  198. package/src/wirings/cli/cli-runner.test.ts +0 -403
  199. package/src/wirings/cli/cli-runner.ts +0 -519
  200. package/src/wirings/cli/cli.types.ts +0 -357
  201. package/src/wirings/cli/command-parser.test.ts +0 -445
  202. package/src/wirings/cli/command-parser.ts +0 -504
  203. package/src/wirings/cli/define-cli-commands.ts +0 -24
  204. package/src/wirings/cli/index.ts +0 -19
  205. package/src/wirings/gateway/gateway-runner.test.ts +0 -474
  206. package/src/wirings/gateway/gateway-runner.ts +0 -411
  207. package/src/wirings/gateway/gateway.types.ts +0 -149
  208. package/src/wirings/gateway/index.ts +0 -13
  209. package/src/wirings/http/http-routes.test.ts +0 -322
  210. package/src/wirings/http/http-routes.ts +0 -198
  211. package/src/wirings/http/http-runner.test.ts +0 -144
  212. package/src/wirings/http/http-runner.ts +0 -563
  213. package/src/wirings/http/http.types.ts +0 -378
  214. package/src/wirings/http/index.ts +0 -25
  215. package/src/wirings/http/log-http-routes.ts +0 -22
  216. package/src/wirings/http/pikku-fetch-http-request.test.ts +0 -237
  217. package/src/wirings/http/pikku-fetch-http-request.ts +0 -166
  218. package/src/wirings/http/pikku-fetch-http-response.test.ts +0 -82
  219. package/src/wirings/http/pikku-fetch-http-response.ts +0 -147
  220. package/src/wirings/http/routers/http-router.ts +0 -13
  221. package/src/wirings/http/routers/path-to-regex.test.ts +0 -319
  222. package/src/wirings/http/routers/path-to-regex.ts +0 -126
  223. package/src/wirings/mcp/index.ts +0 -27
  224. package/src/wirings/mcp/mcp-endpoint-registry.test.ts +0 -389
  225. package/src/wirings/mcp/mcp-endpoint-registry.ts +0 -159
  226. package/src/wirings/mcp/mcp-runner.ts +0 -305
  227. package/src/wirings/mcp/mcp.types.ts +0 -216
  228. package/src/wirings/node/index.ts +0 -2
  229. package/src/wirings/node/node.types.ts +0 -23
  230. package/src/wirings/oauth2/index.ts +0 -3
  231. package/src/wirings/oauth2/oauth2-client.test.ts +0 -929
  232. package/src/wirings/oauth2/oauth2-client.ts +0 -335
  233. package/src/wirings/oauth2/oauth2.types.ts +0 -69
  234. package/src/wirings/oauth2/wire-oauth2-credential.ts +0 -23
  235. package/src/wirings/queue/index.ts +0 -31
  236. package/src/wirings/queue/queue-runner.test.ts +0 -710
  237. package/src/wirings/queue/queue-runner.ts +0 -192
  238. package/src/wirings/queue/queue.types.ts +0 -189
  239. package/src/wirings/queue/register-queue-helper.ts +0 -60
  240. package/src/wirings/queue/validate-worker-config.test.ts +0 -108
  241. package/src/wirings/queue/validate-worker-config.ts +0 -116
  242. package/src/wirings/rpc/index.ts +0 -4
  243. package/src/wirings/rpc/rpc-runner.ts +0 -439
  244. package/src/wirings/rpc/rpc-types.ts +0 -51
  245. package/src/wirings/rpc/wire-addon.ts +0 -20
  246. package/src/wirings/scheduler/index.ts +0 -11
  247. package/src/wirings/scheduler/log-schedulers.ts +0 -20
  248. package/src/wirings/scheduler/scheduler-runner.test.ts +0 -660
  249. package/src/wirings/scheduler/scheduler-runner.ts +0 -132
  250. package/src/wirings/scheduler/scheduler.types.ts +0 -53
  251. package/src/wirings/secret/index.ts +0 -9
  252. package/src/wirings/secret/secret.types.ts +0 -32
  253. package/src/wirings/secret/validate-secret-definitions.test.ts +0 -140
  254. package/src/wirings/secret/validate-secret-definitions.ts +0 -82
  255. package/src/wirings/trigger/index.ts +0 -10
  256. package/src/wirings/trigger/pikku-trigger-service.ts +0 -112
  257. package/src/wirings/trigger/trigger-runner.test.ts +0 -79
  258. package/src/wirings/trigger/trigger-runner.ts +0 -135
  259. package/src/wirings/trigger/trigger.types.ts +0 -178
  260. package/src/wirings/variable/index.ts +0 -8
  261. package/src/wirings/variable/validate-variable-definitions.test.ts +0 -91
  262. package/src/wirings/variable/validate-variable-definitions.ts +0 -69
  263. package/src/wirings/variable/variable.types.ts +0 -22
  264. package/src/wirings/workflow/dsl/index.ts +0 -31
  265. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +0 -320
  266. package/src/wirings/workflow/dsl/workflow-runner.ts +0 -28
  267. package/src/wirings/workflow/graph/graph-node.ts +0 -222
  268. package/src/wirings/workflow/graph/graph-runner.test.ts +0 -487
  269. package/src/wirings/workflow/graph/graph-runner.ts +0 -816
  270. package/src/wirings/workflow/graph/index.ts +0 -14
  271. package/src/wirings/workflow/graph/template.test.ts +0 -49
  272. package/src/wirings/workflow/graph/template.ts +0 -42
  273. package/src/wirings/workflow/graph/wire-workflow-graph.ts +0 -29
  274. package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -104
  275. package/src/wirings/workflow/index.ts +0 -81
  276. package/src/wirings/workflow/pikku-workflow-service.test.ts +0 -200
  277. package/src/wirings/workflow/pikku-workflow-service.ts +0 -1165
  278. package/src/wirings/workflow/workflow-helpers.test.ts +0 -129
  279. package/src/wirings/workflow/workflow-helpers.ts +0 -79
  280. package/src/wirings/workflow/workflow.types.ts +0 -266
  281. package/tsconfig.json +0 -14
  282. package/tsconfig.tsbuildinfo +0 -1
@@ -1,166 +0,0 @@
1
- import { parse as parseQuery } from 'picoquery'
2
- import { parse as parseCookie } from 'cookie'
3
- import type { HTTPMethod, PikkuHTTPRequest, PikkuQuery } from './http.types.js'
4
- import { UnprocessableContentError } from '../../errors/errors.js'
5
-
6
- /**
7
- * Abstract class representing a pikku request.
8
- * @template In - The type of the request body.
9
- * @group RequestResponse
10
- */
11
- export class PikkuFetchHTTPRequest<In = unknown>
12
- implements PikkuHTTPRequest<In>
13
- {
14
- #cookies: Partial<Record<string, string>> | undefined
15
- #params: Partial<Record<string, string | string[]>> = {}
16
- #url: URL
17
-
18
- constructor(private request: Request) {
19
- this.#url = new URL(request.url)
20
- }
21
-
22
- public method(): HTTPMethod {
23
- return this.request.method.toLowerCase() as HTTPMethod
24
- }
25
-
26
- public path(): string {
27
- return this.#url.pathname
28
- }
29
-
30
- /**
31
- * Retrieves the request body.
32
- * @returns A promise that resolves to the request body.
33
- */
34
- public json(): Promise<In> {
35
- return this.request.json()
36
- }
37
-
38
- /**
39
- * Retrieves the raw request body as a Buffer.
40
- * @returns A promise that resolves to the raw request body.
41
- */
42
- public arrayBuffer(): Promise<ArrayBuffer> {
43
- return this.request.arrayBuffer()
44
- }
45
-
46
- /**
47
- * Retrieves the value of a specific header.
48
- * @param headerName - The name of the header to retrieve.
49
- * @returns The value of the header, or undefined if the header is not found.
50
- */
51
- public header(headerName: string): string | null {
52
- return this.request.headers.get(headerName.toLowerCase())
53
- }
54
-
55
- /**
56
- * Retrieves the cookies from the request.
57
- * @returns An object containing the cookies.
58
- */
59
- public cookie(cookieName: string): string | null {
60
- if (this.#cookies?.[cookieName]) {
61
- return this.#cookies[cookieName]
62
- }
63
- const cookieHeader = this.header('cookie')
64
- this.#cookies = cookieHeader ? parseCookie(cookieHeader) : {}
65
- return this.#cookies[cookieName] || null
66
- }
67
-
68
- /**
69
- * Retrieves the request parameters.
70
- * @returns An object containing the request parameters.
71
- */
72
- public params(): Partial<Record<string, string | string[]>> {
73
- return this.#params
74
- }
75
-
76
- /**
77
- * Sets the request parameters.
78
- * @param params - An object containing the request parameters to set.
79
- */
80
- public setParams(
81
- params: Record<string, string | string[] | undefined>
82
- ): void {
83
- this.#params = params
84
- }
85
-
86
- /**
87
- * Retrieves the query parameters from the request.
88
- * @returns An object containing the query parameters.
89
- */
90
- public query(): PikkuQuery {
91
- return parseQuery(this.#url.searchParams.toString()) as PikkuQuery
92
- }
93
-
94
- /**
95
- * Retrieves the combined data from the request, including parameters, query, and body.
96
- * @returns A promise that resolves to an object containing the combined data.
97
- */
98
- public async data(): Promise<In> {
99
- const body = await this.body()
100
- const parts = [this.params(), this.query(), body]
101
- const merged: Record<string, unknown> = {}
102
- for (const part of parts) {
103
- for (const [key, value] of Object.entries(part)) {
104
- if (key in merged && !valuesAreEquivalent(merged[key], value)) {
105
- throw new UnprocessableContentError(
106
- `Conflicting values for key "${key}": "${merged[key]}" vs "${value}"`
107
- )
108
- }
109
- merged[key] ??= value
110
- }
111
- }
112
- return merged as In
113
- }
114
-
115
- private async body(): Promise<any> {
116
- const noBodyMethods: HTTPMethod[] = ['get', 'head', 'options', 'delete']
117
- if (noBodyMethods.includes(this.method())) {
118
- return {}
119
- }
120
-
121
- let body: any = {}
122
- const contentType = this.header('content-type') || ''
123
- try {
124
- if (contentType.includes('application/json')) {
125
- const parsed = await this.json()
126
- body =
127
- typeof parsed === 'object' &&
128
- parsed !== null &&
129
- !Array.isArray(parsed)
130
- ? parsed
131
- : { data: parsed }
132
- } else if (contentType.includes('text/')) {
133
- const text = await this.request.text()
134
- body = { data: text }
135
- } else if (contentType.includes('application/octet-stream')) {
136
- const buffer = await this.request.arrayBuffer()
137
- body = { data: buffer }
138
- } else if (contentType === 'application/x-www-form-urlencoded') {
139
- const text = await this.request.text()
140
- body = Object.fromEntries(new URLSearchParams(text))
141
- } else {
142
- throw new UnprocessableContentError(
143
- `Unsupported content type ${contentType}`
144
- )
145
- }
146
- } catch (e) {
147
- throw new UnprocessableContentError(`Error parsing body: ${e}`)
148
- }
149
- return body
150
- }
151
- }
152
-
153
- function valuesAreEquivalent(a: unknown, b: unknown): boolean {
154
- return coerce(a) === coerce(b)
155
- }
156
-
157
- function coerce(value: unknown): string | number | boolean {
158
- if (typeof value === 'boolean' || typeof value === 'number') return value
159
- if (typeof value === 'string') {
160
- if (value === 'true') return true
161
- if (value === 'false') return false
162
- const num = Number(value)
163
- return isNaN(num) ? value : num
164
- }
165
- return value as any
166
- }
@@ -1,82 +0,0 @@
1
- import { describe, test } from 'node:test'
2
- import assert from 'assert'
3
- import { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js' // Adjust path if needed
4
-
5
- describe('PikkuFetchHTTPResponse', () => {
6
- test('sets status code', () => {
7
- const res = new PikkuFetchHTTPResponse().status(404).toResponse()
8
- assert.strictEqual(res.status, 404)
9
- })
10
-
11
- test('sets headers', async () => {
12
- const res = new PikkuFetchHTTPResponse()
13
- .header('X-Test', 'value')
14
- .header('X-Multi', ['a', 'b'])
15
- .toResponse()
16
-
17
- assert.strictEqual(res.headers.get('X-Test'), 'value')
18
- const multi = res.headers.get('X-Multi')?.split(', ')
19
- assert.deepEqual(multi, ['a', 'b'])
20
- })
21
-
22
- test('sets cookies', () => {
23
- const res = new PikkuFetchHTTPResponse()
24
- .cookie('token', 'abc123', { httpOnly: true, path: '/' })
25
- .cookie('other', 'val', { maxAge: 3600 })
26
- .toResponse()
27
-
28
- const setCookieHeader = res.headers.get('Set-Cookie')
29
- assert.ok(setCookieHeader)
30
-
31
- const cookies = setCookieHeader!.split(', ')
32
- assert.ok(cookies.some((c) => c.startsWith('token=abc123')))
33
- assert.ok(cookies.some((c) => c.startsWith('other=val')))
34
- })
35
-
36
- test('json sets correct content type and body', async () => {
37
- const res = new PikkuFetchHTTPResponse()
38
- .json({ hello: 'world' })
39
- .toResponse()
40
-
41
- assert.strictEqual(res.headers.get('Content-Type'), 'application/json')
42
- const body = await res.json()
43
- assert.deepEqual(body, { hello: 'world' })
44
- })
45
-
46
- test('text sets correct content type and body', async () => {
47
- const res = new PikkuFetchHTTPResponse().text('hello').toResponse()
48
-
49
- assert.strictEqual(res.headers.get('Content-Type'), 'text/plain')
50
- const text = await res.text()
51
- assert.strictEqual(text, 'hello')
52
- })
53
-
54
- test('html sets correct content type and body', async () => {
55
- const res = new PikkuFetchHTTPResponse().html('<p>hi</p>').toResponse()
56
-
57
- assert.strictEqual(res.headers.get('Content-Type'), 'text/html')
58
- const text = await res.text()
59
- assert.strictEqual(text, '<p>hi</p>')
60
- })
61
-
62
- test('arrayBuffer sets correct content type', async () => {
63
- const buffer = new Uint8Array([1, 2, 3]).buffer
64
- const res = new PikkuFetchHTTPResponse().arrayBuffer(buffer).toResponse()
65
-
66
- assert.strictEqual(
67
- res.headers.get('Content-Type'),
68
- 'application/octet-stream'
69
- )
70
- const body = await res.arrayBuffer()
71
- assert.deepEqual(new Uint8Array(body), new Uint8Array([1, 2, 3]))
72
- })
73
-
74
- test('redirect sets Location header and status', () => {
75
- const res = new PikkuFetchHTTPResponse()
76
- .redirect('/login', 301)
77
- .toResponse()
78
-
79
- assert.strictEqual(res.status, 301)
80
- assert.strictEqual(res.headers.get('Location'), '/login')
81
- })
82
- })
@@ -1,147 +0,0 @@
1
- import type { PikkuHTTPResponse } from './http.types.js'
2
- import type { SerializeOptions as CookieSerializeOptions } from 'cookie'
3
- import { serialize as serializeCookie } from 'cookie'
4
-
5
- export class PikkuFetchHTTPResponse implements PikkuHTTPResponse {
6
- #statusCode: number = 200
7
- #headers = new Headers()
8
- #cookies = new Map<string, { value: string; flags: CookieSerializeOptions }>()
9
-
10
- #body: BodyInit | null = null
11
- #responseMode: 'stream' | null = null
12
- #send: ((data: string) => void) | null = null
13
- #close: (() => void) | null = null
14
-
15
- public setMode(mode: 'stream') {
16
- this.#responseMode = 'stream'
17
- if (mode === 'stream') {
18
- this.#body = this.createStream()
19
- }
20
- }
21
-
22
- public status(code: number): this {
23
- this.#statusCode = code
24
- return this
25
- }
26
-
27
- public cookie(
28
- name: string,
29
- value: string,
30
- flags: CookieSerializeOptions
31
- ): this {
32
- this.#cookies.set(name, { value, flags })
33
- return this
34
- }
35
-
36
- public header(name: string, value: string | string[]): this {
37
- this.#headers.delete(name)
38
- if (Array.isArray(value)) {
39
- value.forEach((v) => this.#headers.append(name, v))
40
- } else {
41
- this.#headers.set(name, value)
42
- }
43
- return this
44
- }
45
-
46
- public arrayBuffer(data: XMLHttpRequestBodyInit): this {
47
- if (this.#responseMode === 'stream') {
48
- this.#send!(data as string)
49
- } else {
50
- this.#body = data
51
- this.header('Content-Type', 'application/octet-stream')
52
- }
53
- return this
54
- }
55
-
56
- public json(data: unknown): this {
57
- if (this.#responseMode === 'stream') {
58
- this.#send!(JSON.stringify(data))
59
- } else {
60
- this.#body = JSON.stringify(data)
61
- this.header('Content-Type', 'application/json')
62
- }
63
- return this
64
- }
65
-
66
- public text(content: string): this {
67
- if (this.#responseMode === 'stream') {
68
- this.#send!(content)
69
- } else {
70
- this.#body = content
71
- this.header('Content-Type', 'text/plain')
72
- }
73
- return this
74
- }
75
-
76
- public html(content: string): this {
77
- if (this.#responseMode === 'stream') {
78
- this.#send!(content)
79
- } else {
80
- this.#body = content
81
- this.header('Content-Type', 'text/html')
82
- }
83
- return this
84
- }
85
-
86
- // public body(body: BodyInit): this {
87
- // this.#body = body
88
- // return this
89
- // }
90
-
91
- public redirect(location: string, status: number = 302): this {
92
- if (
93
- !location.startsWith('/') &&
94
- !location.startsWith('https://') &&
95
- !location.startsWith('http://')
96
- ) {
97
- throw new Error(
98
- 'Invalid redirect location: must be a relative path or absolute URL'
99
- )
100
- }
101
- this.#statusCode = status
102
- this.header('Location', location)
103
- return this
104
- }
105
-
106
- public close(): this {
107
- if (this.#close) {
108
- this.#close()
109
- }
110
- return this
111
- }
112
-
113
- public toResponse(args?: Record<string, any>): Response {
114
- const cookieHeader = Array.from(this.#cookies.entries()).map(
115
- ([name, { value, flags }]) => serializeCookie(name, value, flags)
116
- )
117
- // Multiple Set-Cookie headers must be appended separately, not joined with commas
118
- // per HTTP specification (RFC 6265)
119
- cookieHeader.forEach((cookie) => this.#headers.append('Set-Cookie', cookie))
120
- return new Response(this.#body, {
121
- ...args,
122
- status: this.#statusCode,
123
- headers: this.#headers,
124
- })
125
- }
126
-
127
- private createStream(): ReadableStream<Uint8Array> {
128
- const encoder = new TextEncoder()
129
- return new ReadableStream({
130
- start: (controller) => {
131
- const send = (data: string) => {
132
- controller.enqueue(encoder.encode(`data: ${data}\n\n`))
133
- }
134
-
135
- const close = () => {
136
- controller.close()
137
- }
138
-
139
- this.#send = send
140
- this.#close = close
141
-
142
- // Force initial flush
143
- controller.enqueue(encoder.encode(':\n\n'))
144
- },
145
- })
146
- }
147
- }
@@ -1,13 +0,0 @@
1
- import type { HTTPMethod } from '../http.types.js'
2
- import { PathToRegexRouter } from './path-to-regex.js'
3
-
4
- export type MatchResult = {
5
- route: string
6
- params: Record<string, any>
7
- } | null
8
-
9
- export interface Router {
10
- match(method: HTTPMethod, path: string): MatchResult
11
- }
12
-
13
- export const httpRouter = new PathToRegexRouter()