@pikku/core 0.12.3 → 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 (218) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/services/in-memory-workflow-service.d.ts +15 -2
  3. package/dist/services/in-memory-workflow-service.js +49 -0
  4. package/lcov.info +18891 -0
  5. package/package.json +1 -1
  6. package/src/crypto-utils.test.ts +0 -214
  7. package/src/crypto-utils.ts +0 -213
  8. package/src/errors/error-handler.ts +0 -62
  9. package/src/errors/error.test.ts +0 -195
  10. package/src/errors/errors.ts +0 -374
  11. package/src/errors/index.ts +0 -2
  12. package/src/factory-functions.test.ts +0 -109
  13. package/src/function/function-runner.test.ts +0 -536
  14. package/src/function/function-runner.ts +0 -365
  15. package/src/function/functions.types.ts +0 -304
  16. package/src/function/index.ts +0 -5
  17. package/src/handle-error.test.ts +0 -424
  18. package/src/handle-error.ts +0 -69
  19. package/src/index.ts +0 -118
  20. package/src/internal.ts +0 -6
  21. package/src/middleware/auth-apikey.test.ts +0 -363
  22. package/src/middleware/auth-apikey.ts +0 -47
  23. package/src/middleware/auth-bearer.test.ts +0 -450
  24. package/src/middleware/auth-bearer.ts +0 -72
  25. package/src/middleware/auth-cookie.test.ts +0 -528
  26. package/src/middleware/auth-cookie.ts +0 -80
  27. package/src/middleware/cors.test.ts +0 -424
  28. package/src/middleware/cors.ts +0 -104
  29. package/src/middleware/index.ts +0 -5
  30. package/src/middleware/remote-auth.test.ts +0 -488
  31. package/src/middleware/remote-auth.ts +0 -68
  32. package/src/middleware/timeout.ts +0 -15
  33. package/src/middleware-runner.test.ts +0 -418
  34. package/src/middleware-runner.ts +0 -234
  35. package/src/permissions.test.ts +0 -434
  36. package/src/permissions.ts +0 -319
  37. package/src/pikku-request.ts +0 -23
  38. package/src/pikku-response.ts +0 -5
  39. package/src/pikku-state.test.ts +0 -224
  40. package/src/pikku-state.ts +0 -216
  41. package/src/run-tests-script.test.ts +0 -49
  42. package/src/schema.test.ts +0 -249
  43. package/src/schema.ts +0 -151
  44. package/src/services/ai-agent-runner-service.ts +0 -41
  45. package/src/services/ai-run-state-service.ts +0 -20
  46. package/src/services/ai-storage-service.ts +0 -39
  47. package/src/services/content-service.ts +0 -76
  48. package/src/services/deployment-service.ts +0 -22
  49. package/src/services/gateway-service.ts +0 -20
  50. package/src/services/gopass-secrets.ts +0 -98
  51. package/src/services/in-memory-ai-run-state-service.ts +0 -73
  52. package/src/services/in-memory-trigger-service.ts +0 -64
  53. package/src/services/in-memory-workflow-service.test.ts +0 -351
  54. package/src/services/in-memory-workflow-service.ts +0 -438
  55. package/src/services/index.ts +0 -56
  56. package/src/services/jwt-service.ts +0 -30
  57. package/src/services/local-content.ts +0 -120
  58. package/src/services/local-gateway-service.ts +0 -62
  59. package/src/services/local-secrets.test.ts +0 -80
  60. package/src/services/local-secrets.ts +0 -94
  61. package/src/services/local-variables.test.ts +0 -61
  62. package/src/services/local-variables.ts +0 -39
  63. package/src/services/logger-console.test.ts +0 -118
  64. package/src/services/logger-console.ts +0 -98
  65. package/src/services/logger.ts +0 -57
  66. package/src/services/scheduler-service.ts +0 -86
  67. package/src/services/schema-service.ts +0 -33
  68. package/src/services/scoped-secret-service.test.ts +0 -74
  69. package/src/services/scoped-secret-service.ts +0 -41
  70. package/src/services/secret-service.ts +0 -38
  71. package/src/services/trigger-service.ts +0 -17
  72. package/src/services/typed-secret-service.test.ts +0 -93
  73. package/src/services/typed-secret-service.ts +0 -70
  74. package/src/services/typed-variables-service.test.ts +0 -73
  75. package/src/services/typed-variables-service.ts +0 -81
  76. package/src/services/user-session-service.test.ts +0 -113
  77. package/src/services/user-session-service.ts +0 -86
  78. package/src/services/variables-service.ts +0 -11
  79. package/src/services/workflow-service.ts +0 -95
  80. package/src/testing/index.ts +0 -2
  81. package/src/testing/service-tests.ts +0 -873
  82. package/src/time-utils.test.ts +0 -56
  83. package/src/time-utils.ts +0 -107
  84. package/src/types/core.types.ts +0 -478
  85. package/src/types/state.types.ts +0 -188
  86. package/src/utils/hash.test.ts +0 -68
  87. package/src/utils/hash.ts +0 -26
  88. package/src/utils.test.ts +0 -350
  89. package/src/utils.ts +0 -129
  90. package/src/version.test.ts +0 -80
  91. package/src/version.ts +0 -25
  92. package/src/wirings/ai-agent/agent-dynamic-workflow.ts +0 -469
  93. package/src/wirings/ai-agent/ai-agent-helpers.test.ts +0 -152
  94. package/src/wirings/ai-agent/ai-agent-helpers.ts +0 -76
  95. package/src/wirings/ai-agent/ai-agent-memory.ts +0 -310
  96. package/src/wirings/ai-agent/ai-agent-model-config.test.ts +0 -115
  97. package/src/wirings/ai-agent/ai-agent-model-config.ts +0 -43
  98. package/src/wirings/ai-agent/ai-agent-prepare.ts +0 -636
  99. package/src/wirings/ai-agent/ai-agent-registry.test.ts +0 -37
  100. package/src/wirings/ai-agent/ai-agent-registry.ts +0 -82
  101. package/src/wirings/ai-agent/ai-agent-runner.test.ts +0 -319
  102. package/src/wirings/ai-agent/ai-agent-runner.ts +0 -773
  103. package/src/wirings/ai-agent/ai-agent-stream.test.ts +0 -859
  104. package/src/wirings/ai-agent/ai-agent-stream.ts +0 -1153
  105. package/src/wirings/ai-agent/ai-agent.types.ts +0 -382
  106. package/src/wirings/ai-agent/index.ts +0 -37
  107. package/src/wirings/channel/channel-common.ts +0 -90
  108. package/src/wirings/channel/channel-handler.ts +0 -250
  109. package/src/wirings/channel/channel-middleware-runner.ts +0 -120
  110. package/src/wirings/channel/channel-runner.ts +0 -166
  111. package/src/wirings/channel/channel-store.ts +0 -29
  112. package/src/wirings/channel/channel.types.ts +0 -172
  113. package/src/wirings/channel/define-channel-routes.ts +0 -25
  114. package/src/wirings/channel/eventhub-service.ts +0 -34
  115. package/src/wirings/channel/eventhub-store.ts +0 -13
  116. package/src/wirings/channel/index.ts +0 -24
  117. package/src/wirings/channel/local/index.ts +0 -3
  118. package/src/wirings/channel/local/local-channel-handler.ts +0 -81
  119. package/src/wirings/channel/local/local-channel-runner.test.ts +0 -215
  120. package/src/wirings/channel/local/local-channel-runner.ts +0 -210
  121. package/src/wirings/channel/local/local-eventhub-service.test.ts +0 -95
  122. package/src/wirings/channel/local/local-eventhub-service.ts +0 -101
  123. package/src/wirings/channel/log-channels.ts +0 -20
  124. package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +0 -54
  125. package/src/wirings/channel/pikku-abstract-channel-handler.ts +0 -45
  126. package/src/wirings/channel/serverless/index.ts +0 -5
  127. package/src/wirings/channel/serverless/serverless-channel-runner.ts +0 -289
  128. package/src/wirings/cli/channel/cli-channel-runner.ts +0 -136
  129. package/src/wirings/cli/channel/index.ts +0 -1
  130. package/src/wirings/cli/cli-runner.test.ts +0 -403
  131. package/src/wirings/cli/cli-runner.ts +0 -529
  132. package/src/wirings/cli/cli.types.ts +0 -358
  133. package/src/wirings/cli/command-parser.test.ts +0 -445
  134. package/src/wirings/cli/command-parser.ts +0 -504
  135. package/src/wirings/cli/define-cli-commands.ts +0 -24
  136. package/src/wirings/cli/index.ts +0 -19
  137. package/src/wirings/gateway/gateway-runner.test.ts +0 -474
  138. package/src/wirings/gateway/gateway-runner.ts +0 -411
  139. package/src/wirings/gateway/gateway.types.ts +0 -149
  140. package/src/wirings/gateway/index.ts +0 -13
  141. package/src/wirings/http/http-routes.test.ts +0 -322
  142. package/src/wirings/http/http-routes.ts +0 -197
  143. package/src/wirings/http/http-runner.test.ts +0 -144
  144. package/src/wirings/http/http-runner.ts +0 -588
  145. package/src/wirings/http/http.types.ts +0 -369
  146. package/src/wirings/http/index.ts +0 -28
  147. package/src/wirings/http/log-http-routes.ts +0 -22
  148. package/src/wirings/http/pikku-fetch-http-request.test.ts +0 -237
  149. package/src/wirings/http/pikku-fetch-http-request.ts +0 -170
  150. package/src/wirings/http/pikku-fetch-http-response.test.ts +0 -82
  151. package/src/wirings/http/pikku-fetch-http-response.ts +0 -147
  152. package/src/wirings/http/routers/http-router.ts +0 -13
  153. package/src/wirings/http/routers/path-to-regex.test.ts +0 -319
  154. package/src/wirings/http/routers/path-to-regex.ts +0 -126
  155. package/src/wirings/http/web-request.test.ts +0 -236
  156. package/src/wirings/http/web-request.ts +0 -104
  157. package/src/wirings/mcp/index.ts +0 -27
  158. package/src/wirings/mcp/mcp-endpoint-registry.test.ts +0 -389
  159. package/src/wirings/mcp/mcp-endpoint-registry.ts +0 -159
  160. package/src/wirings/mcp/mcp-runner.ts +0 -323
  161. package/src/wirings/mcp/mcp.types.ts +0 -216
  162. package/src/wirings/node/index.ts +0 -2
  163. package/src/wirings/node/node.types.ts +0 -23
  164. package/src/wirings/oauth2/index.ts +0 -3
  165. package/src/wirings/oauth2/oauth2-client.test.ts +0 -929
  166. package/src/wirings/oauth2/oauth2-client.ts +0 -335
  167. package/src/wirings/oauth2/oauth2.types.ts +0 -69
  168. package/src/wirings/oauth2/wire-oauth2-credential.ts +0 -23
  169. package/src/wirings/queue/index.ts +0 -31
  170. package/src/wirings/queue/queue-runner.test.ts +0 -710
  171. package/src/wirings/queue/queue-runner.ts +0 -192
  172. package/src/wirings/queue/queue.types.ts +0 -189
  173. package/src/wirings/queue/register-queue-helper.ts +0 -60
  174. package/src/wirings/queue/validate-worker-config.test.ts +0 -108
  175. package/src/wirings/queue/validate-worker-config.ts +0 -116
  176. package/src/wirings/rpc/index.ts +0 -4
  177. package/src/wirings/rpc/rpc-runner.ts +0 -460
  178. package/src/wirings/rpc/rpc-types.ts +0 -56
  179. package/src/wirings/rpc/wire-addon.ts +0 -21
  180. package/src/wirings/scheduler/index.ts +0 -11
  181. package/src/wirings/scheduler/log-schedulers.ts +0 -20
  182. package/src/wirings/scheduler/scheduler-runner.test.ts +0 -660
  183. package/src/wirings/scheduler/scheduler-runner.ts +0 -133
  184. package/src/wirings/scheduler/scheduler.types.ts +0 -53
  185. package/src/wirings/secret/index.ts +0 -9
  186. package/src/wirings/secret/secret.types.ts +0 -32
  187. package/src/wirings/secret/validate-secret-definitions.test.ts +0 -140
  188. package/src/wirings/secret/validate-secret-definitions.ts +0 -82
  189. package/src/wirings/trigger/index.ts +0 -10
  190. package/src/wirings/trigger/pikku-trigger-service.ts +0 -112
  191. package/src/wirings/trigger/trigger-runner.test.ts +0 -79
  192. package/src/wirings/trigger/trigger-runner.ts +0 -135
  193. package/src/wirings/trigger/trigger.types.ts +0 -178
  194. package/src/wirings/variable/index.ts +0 -8
  195. package/src/wirings/variable/validate-variable-definitions.test.ts +0 -91
  196. package/src/wirings/variable/validate-variable-definitions.ts +0 -69
  197. package/src/wirings/variable/variable.types.ts +0 -22
  198. package/src/wirings/workflow/dsl/index.ts +0 -31
  199. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +0 -320
  200. package/src/wirings/workflow/dsl/workflow-runner.ts +0 -28
  201. package/src/wirings/workflow/graph/graph-node.ts +0 -222
  202. package/src/wirings/workflow/graph/graph-runner.test.ts +0 -487
  203. package/src/wirings/workflow/graph/graph-runner.ts +0 -816
  204. package/src/wirings/workflow/graph/graph-validation.test.ts +0 -170
  205. package/src/wirings/workflow/graph/graph-validation.ts +0 -237
  206. package/src/wirings/workflow/graph/index.ts +0 -19
  207. package/src/wirings/workflow/graph/template.test.ts +0 -49
  208. package/src/wirings/workflow/graph/template.ts +0 -42
  209. package/src/wirings/workflow/graph/wire-workflow-graph.ts +0 -29
  210. package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -104
  211. package/src/wirings/workflow/index.ts +0 -82
  212. package/src/wirings/workflow/pikku-workflow-service.test.ts +0 -200
  213. package/src/wirings/workflow/pikku-workflow-service.ts +0 -1176
  214. package/src/wirings/workflow/workflow-helpers.test.ts +0 -129
  215. package/src/wirings/workflow/workflow-helpers.ts +0 -79
  216. package/src/wirings/workflow/workflow.types.ts +0 -274
  217. package/tsconfig.json +0 -14
  218. package/tsconfig.tsbuildinfo +0 -1
@@ -1,74 +0,0 @@
1
- import { describe, test } from 'node:test'
2
- import assert from 'node:assert'
3
- import { ScopedSecretService } from './scoped-secret-service.js'
4
-
5
- const createMockSecrets = () => ({
6
- getSecret: async (key: string) => `value-of-${key}`,
7
- getSecretJSON: async (key: string) => ({ key }),
8
- hasSecret: async () => true,
9
- setSecretJSON: async () => {},
10
- deleteSecret: async () => {},
11
- })
12
-
13
- describe('ScopedSecretService', () => {
14
- test('should allow access to allowed keys', async () => {
15
- const mock = createMockSecrets()
16
- const scoped = new ScopedSecretService(mock, new Set(['KEY1', 'KEY2']))
17
- const result = await scoped.getSecret('KEY1')
18
- assert.strictEqual(result, 'value-of-KEY1')
19
- })
20
-
21
- test('should deny access to non-allowed keys', async () => {
22
- const mock = createMockSecrets()
23
- const scoped = new ScopedSecretService(mock, new Set(['KEY1']))
24
- await assert.rejects(() => scoped.getSecret('KEY2'), {
25
- message: 'Access denied to secret key: KEY2',
26
- })
27
- })
28
-
29
- test('should allow getSecretJSON for allowed keys', async () => {
30
- const mock = createMockSecrets()
31
- const scoped = new ScopedSecretService(mock, new Set(['KEY1']))
32
- const result = await scoped.getSecretJSON('KEY1')
33
- assert.deepStrictEqual(result, { key: 'KEY1' })
34
- })
35
-
36
- test('should deny getSecretJSON for non-allowed keys', async () => {
37
- const mock = createMockSecrets()
38
- const scoped = new ScopedSecretService(mock, new Set(['KEY1']))
39
- await assert.rejects(() => scoped.getSecretJSON('FORBIDDEN'), {
40
- message: 'Access denied to secret key: FORBIDDEN',
41
- })
42
- })
43
-
44
- test('should allow hasSecret for allowed keys', async () => {
45
- const mock = createMockSecrets()
46
- const scoped = new ScopedSecretService(mock, new Set(['KEY1']))
47
- const result = await scoped.hasSecret('KEY1')
48
- assert.strictEqual(result, true)
49
- })
50
-
51
- test('should deny hasSecret for non-allowed keys', async () => {
52
- const mock = createMockSecrets()
53
- const scoped = new ScopedSecretService(mock, new Set(['KEY1']))
54
- await assert.rejects(() => scoped.hasSecret('KEY2'), {
55
- message: 'Access denied to secret key: KEY2',
56
- })
57
- })
58
-
59
- test('should always throw on setSecretJSON', async () => {
60
- const mock = createMockSecrets()
61
- const scoped = new ScopedSecretService(mock, new Set(['KEY1']))
62
- await assert.rejects(() => scoped.setSecretJSON('KEY1', 'val'), {
63
- message: 'setSecretJSON is not allowed in scoped secret service',
64
- })
65
- })
66
-
67
- test('should always throw on deleteSecret', async () => {
68
- const mock = createMockSecrets()
69
- const scoped = new ScopedSecretService(mock, new Set(['KEY1']))
70
- await assert.rejects(() => scoped.deleteSecret('KEY1'), {
71
- message: 'deleteSecret is not allowed in scoped secret service',
72
- })
73
- })
74
- })
@@ -1,41 +0,0 @@
1
- import type { SecretService } from './secret-service.js'
2
-
3
- /**
4
- * A read-only wrapper around SecretService that restricts access
5
- * to only a defined set of allowed secret keys.
6
- */
7
- export class ScopedSecretService implements SecretService {
8
- constructor(
9
- private secrets: SecretService,
10
- private allowedKeys: Set<string>
11
- ) {}
12
-
13
- private assertAllowed(key: string): void {
14
- if (!this.allowedKeys.has(key)) {
15
- throw new Error(`Access denied to secret key: ${key}`)
16
- }
17
- }
18
-
19
- async getSecret(key: string): Promise<string> {
20
- this.assertAllowed(key)
21
- return this.secrets.getSecret(key)
22
- }
23
-
24
- async getSecretJSON<T = {}>(key: string): Promise<T> {
25
- this.assertAllowed(key)
26
- return this.secrets.getSecretJSON<T>(key)
27
- }
28
-
29
- async hasSecret(key: string): Promise<boolean> {
30
- this.assertAllowed(key)
31
- return this.secrets.hasSecret(key)
32
- }
33
-
34
- async setSecretJSON(_key: string, _value: unknown): Promise<void> {
35
- throw new Error('setSecretJSON is not allowed in scoped secret service')
36
- }
37
-
38
- async deleteSecret(_key: string): Promise<void> {
39
- throw new Error('deleteSecret is not allowed in scoped secret service')
40
- }
41
- }
@@ -1,38 +0,0 @@
1
- /**
2
- * Interface for retrieving and managing secrets.
3
- */
4
- export interface SecretService {
5
- /**
6
- * Retrieves a secret by key and parses it as JSON.
7
- * @param key - The key of the secret to retrieve.
8
- * @returns A promise that resolves to the parsed secret value.
9
- * @throws If the secret is not found.
10
- */
11
- getSecretJSON<Return = {}>(key: string): Promise<Return>
12
- /**
13
- * Retrieves a secret by key as a string.
14
- * @param key - The key of the secret to retrieve.
15
- * @returns A promise that resolves to the secret value.
16
- * @throws If the secret is not found.
17
- */
18
- getSecret(key: string): Promise<string>
19
- /**
20
- * Checks if a secret exists without throwing.
21
- * @param key - The key of the secret to check.
22
- * @returns A promise that resolves to true if the secret exists, false otherwise.
23
- */
24
- hasSecret(key: string): Promise<boolean>
25
- /**
26
- * Stores a JSON value as a secret.
27
- * @param key - The key to store the secret under.
28
- * @param value - The JSON value to store.
29
- * @returns A promise that resolves when the secret is stored.
30
- */
31
- setSecretJSON(key: string, value: unknown): Promise<void>
32
- /**
33
- * Deletes a secret by key.
34
- * @param key - The key of the secret to delete.
35
- * @returns A promise that resolves when the secret is deleted.
36
- */
37
- deleteSecret(key: string): Promise<void>
38
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * Abstract TriggerService interface.
3
- *
4
- * Implementations manage trigger subscriptions — listening to external events
5
- * and dispatching to RPC targets or workflow starts.
6
- */
7
- export interface TriggerService {
8
- /**
9
- * Start all triggers
10
- */
11
- start(): Promise<void>
12
-
13
- /**
14
- * Stop all triggers
15
- */
16
- stop(): Promise<void>
17
- }
@@ -1,93 +0,0 @@
1
- import { describe, test } from 'node:test'
2
- import assert from 'node:assert'
3
- import { TypedSecretService } from './typed-secret-service.js'
4
-
5
- const createMockSecrets = (store: Map<string, string> = new Map()) => ({
6
- getSecret: async (key: string) => {
7
- const val = store.get(key)
8
- if (!val) throw new Error(`Not found: ${key}`)
9
- return val
10
- },
11
- getSecretJSON: async (key: string) => {
12
- const val = store.get(key)
13
- if (!val) throw new Error(`Not found: ${key}`)
14
- return JSON.parse(val)
15
- },
16
- hasSecret: async (key: string) => store.has(key),
17
- setSecretJSON: async (key: string, value: unknown) => {
18
- store.set(key, JSON.stringify(value))
19
- },
20
- deleteSecret: async (key: string) => {
21
- store.delete(key)
22
- },
23
- })
24
-
25
- describe('TypedSecretService', () => {
26
- test('should delegate getSecret to underlying service', async () => {
27
- const store = new Map([['API_KEY', 'sk-123']])
28
- const service = new TypedSecretService(createMockSecrets(store), {})
29
- const result = await service.getSecret('API_KEY')
30
- assert.strictEqual(result, 'sk-123')
31
- })
32
-
33
- test('should delegate getSecretJSON to underlying service', async () => {
34
- const store = new Map([['CONFIG', '{"port":3000}']])
35
- const service = new TypedSecretService(createMockSecrets(store), {})
36
- const result = await service.getSecretJSON('CONFIG')
37
- assert.deepStrictEqual(result, { port: 3000 })
38
- })
39
-
40
- test('should delegate hasSecret to underlying service', async () => {
41
- const store = new Map([['EXISTS', 'val']])
42
- const service = new TypedSecretService(createMockSecrets(store), {})
43
- assert.strictEqual(await service.hasSecret('EXISTS'), true)
44
- assert.strictEqual(await service.hasSecret('MISSING'), false)
45
- })
46
-
47
- test('should delegate setSecretJSON to underlying service', async () => {
48
- const store = new Map<string, string>()
49
- const service = new TypedSecretService(createMockSecrets(store), {})
50
- await service.setSecretJSON('NEW_KEY', { data: 'val' })
51
- assert.strictEqual(store.get('NEW_KEY'), '{"data":"val"}')
52
- })
53
-
54
- test('should delegate deleteSecret to underlying service', async () => {
55
- const store = new Map([['KEY', 'val']])
56
- const service = new TypedSecretService(createMockSecrets(store), {})
57
- await service.deleteSecret('KEY')
58
- assert.strictEqual(store.has('KEY'), false)
59
- })
60
-
61
- test('should get all status for credentials', async () => {
62
- const store = new Map([['STRIPE_KEY', 'sk-123']])
63
- const meta = {
64
- STRIPE_KEY: { name: 'stripe', displayName: 'Stripe' },
65
- GITHUB_TOKEN: {
66
- name: 'github',
67
- displayName: 'GitHub',
68
- oauth2: { tokenSecretId: 'GH_TOKEN' },
69
- },
70
- }
71
- const service = new TypedSecretService(createMockSecrets(store), meta)
72
- const status = await service.getAllStatus()
73
- assert.strictEqual(status.length, 2)
74
- const stripeStatus = status.find((s) => s.secretId === 'STRIPE_KEY')!
75
- assert.strictEqual(stripeStatus.isConfigured, true)
76
- assert.strictEqual(stripeStatus.displayName, 'Stripe')
77
- const ghStatus = status.find((s) => s.secretId === 'GITHUB_TOKEN')!
78
- assert.strictEqual(ghStatus.isConfigured, false)
79
- assert.deepStrictEqual(ghStatus.oauth2, { tokenSecretId: 'GH_TOKEN' })
80
- })
81
-
82
- test('should get missing credentials', async () => {
83
- const store = new Map([['STRIPE_KEY', 'sk-123']])
84
- const meta = {
85
- STRIPE_KEY: { name: 'stripe', displayName: 'Stripe' },
86
- GITHUB_TOKEN: { name: 'github', displayName: 'GitHub' },
87
- }
88
- const service = new TypedSecretService(createMockSecrets(store), meta)
89
- const missing = await service.getMissing()
90
- assert.strictEqual(missing.length, 1)
91
- assert.strictEqual(missing[0].secretId, 'GITHUB_TOKEN')
92
- })
93
- })
@@ -1,70 +0,0 @@
1
- import type { SecretService } from './secret-service.js'
2
-
3
- export interface CredentialStatus {
4
- secretId: string
5
- name: string
6
- displayName: string
7
- isConfigured: boolean
8
- oauth2?: { tokenSecretId: string }
9
- }
10
-
11
- export type CredentialMeta = {
12
- name: string
13
- displayName: string
14
- oauth2?: { tokenSecretId: string }
15
- }
16
-
17
- export class TypedSecretService<TMap = Record<string, unknown>>
18
- implements SecretService
19
- {
20
- constructor(
21
- private secrets: SecretService,
22
- private credentialsMeta: Record<string, CredentialMeta>
23
- ) {}
24
-
25
- async getSecretJSON<K extends keyof TMap & string>(key: K): Promise<TMap[K]>
26
- async getSecretJSON<T = unknown>(key: string): Promise<T>
27
- async getSecretJSON(key: string): Promise<unknown> {
28
- return this.secrets.getSecretJSON(key)
29
- }
30
-
31
- async getSecret(key: string): Promise<string> {
32
- return this.secrets.getSecret(key)
33
- }
34
-
35
- async hasSecret(key: string): Promise<boolean> {
36
- return this.secrets.hasSecret(key)
37
- }
38
-
39
- async setSecretJSON<K extends string>(
40
- key: K,
41
- value: K extends keyof TMap ? TMap[K] : unknown
42
- ): Promise<void> {
43
- return this.secrets.setSecretJSON(key, value)
44
- }
45
-
46
- async deleteSecret(key: string): Promise<void> {
47
- return this.secrets.deleteSecret(key)
48
- }
49
-
50
- async getAllStatus(): Promise<CredentialStatus[]> {
51
- const results: CredentialStatus[] = []
52
-
53
- for (const [secretId, meta] of Object.entries(this.credentialsMeta)) {
54
- results.push({
55
- secretId,
56
- name: meta.name,
57
- displayName: meta.displayName,
58
- isConfigured: await this.secrets.hasSecret(secretId),
59
- oauth2: meta.oauth2,
60
- })
61
- }
62
-
63
- return results
64
- }
65
-
66
- async getMissing(): Promise<CredentialStatus[]> {
67
- const all = await this.getAllStatus()
68
- return all.filter((c) => !c.isConfigured)
69
- }
70
- }
@@ -1,73 +0,0 @@
1
- import { describe, test } from 'node:test'
2
- import assert from 'node:assert'
3
- import { TypedVariablesService } from './typed-variables-service.js'
4
- import { LocalVariablesService } from './local-variables.js'
5
-
6
- describe('TypedVariablesService', () => {
7
- const createService = (vars: Record<string, string | undefined> = {}) => {
8
- const underlying = new LocalVariablesService(vars)
9
- const meta = {
10
- DB_URL: { name: 'DB_URL', displayName: 'Database URL' },
11
- API_KEY: { name: 'API_KEY', displayName: 'API Key' },
12
- }
13
- return new TypedVariablesService(underlying, meta)
14
- }
15
-
16
- test('should delegate get to underlying service', () => {
17
- const service = createService({ DB_URL: 'postgres://...' })
18
- assert.strictEqual(service.get('DB_URL'), 'postgres://...')
19
- })
20
-
21
- test('should delegate set to underlying service', () => {
22
- const service = createService()
23
- service.set('DB_URL', 'new-value')
24
- assert.strictEqual(service.get('DB_URL'), 'new-value')
25
- })
26
-
27
- test('should delegate has to underlying service', () => {
28
- const service = createService({ DB_URL: 'val' })
29
- assert.strictEqual(service.has('DB_URL'), true)
30
- assert.strictEqual(service.has('MISSING'), false)
31
- })
32
-
33
- test('should delegate delete to underlying service', () => {
34
- const service = createService({ DB_URL: 'val' })
35
- service.delete('DB_URL')
36
- assert.strictEqual(service.has('DB_URL'), false)
37
- })
38
-
39
- test('should delegate getJSON to underlying service', () => {
40
- const service = createService({ DATA: '{"key":"val"}' })
41
- assert.deepStrictEqual(service.getJSON('DATA'), { key: 'val' })
42
- })
43
-
44
- test('should delegate setJSON to underlying service', () => {
45
- const service = createService()
46
- service.setJSON('DATA', { key: 'val' })
47
- assert.strictEqual(service.get('DATA'), '{"key":"val"}')
48
- })
49
-
50
- test('should get all status for configured variables', async () => {
51
- const service = createService({ DB_URL: 'postgres://...' })
52
- const status = await service.getAllStatus()
53
- assert.strictEqual(status.length, 2)
54
- const dbStatus = status.find((s) => s.variableId === 'DB_URL')!
55
- assert.strictEqual(dbStatus.isConfigured, true)
56
- assert.strictEqual(dbStatus.displayName, 'Database URL')
57
- const apiStatus = status.find((s) => s.variableId === 'API_KEY')!
58
- assert.strictEqual(apiStatus.isConfigured, false)
59
- })
60
-
61
- test('should get missing variables', async () => {
62
- const service = createService({ DB_URL: 'val' })
63
- const missing = await service.getMissing()
64
- assert.strictEqual(missing.length, 1)
65
- assert.strictEqual(missing[0].variableId, 'API_KEY')
66
- })
67
-
68
- test('should return empty missing when all configured', async () => {
69
- const service = createService({ DB_URL: 'val', API_KEY: 'key' })
70
- const missing = await service.getMissing()
71
- assert.strictEqual(missing.length, 0)
72
- })
73
- })
@@ -1,81 +0,0 @@
1
- import type { VariablesService } from './variables-service.js'
2
-
3
- export interface VariableStatus {
4
- variableId: string
5
- name: string
6
- displayName: string
7
- isConfigured: boolean
8
- }
9
-
10
- export type VariableMeta = {
11
- name: string
12
- displayName: string
13
- }
14
-
15
- export class TypedVariablesService<TMap = Record<string, unknown>>
16
- implements VariablesService
17
- {
18
- constructor(
19
- private variables: VariablesService,
20
- private variablesMeta: Record<string, VariableMeta>
21
- ) {}
22
-
23
- get(
24
- name: keyof TMap & string
25
- ): Promise<string | undefined> | string | undefined
26
- get(name: string): Promise<string | undefined> | string | undefined
27
- get(name: string): Promise<string | undefined> | string | undefined {
28
- return this.variables.get(name)
29
- }
30
-
31
- getJSON<K extends keyof TMap & string>(
32
- name: K
33
- ): Promise<TMap[K] | undefined> | TMap[K] | undefined
34
- getJSON<T = unknown>(name: string): Promise<T | undefined> | T | undefined
35
- getJSON(name: string): Promise<unknown> | unknown {
36
- return this.variables.getJSON(name)
37
- }
38
-
39
- getAll():
40
- | Promise<Record<string, string | undefined>>
41
- | Record<string, string | undefined> {
42
- return this.variables.getAll()
43
- }
44
-
45
- set(name: string, value: string): Promise<void> | void {
46
- return this.variables.set(name, value)
47
- }
48
-
49
- setJSON(name: string, value: unknown): Promise<void> | void {
50
- return this.variables.setJSON(name, value)
51
- }
52
-
53
- has(name: string): Promise<boolean> | boolean {
54
- return this.variables.has(name)
55
- }
56
-
57
- delete(name: string): Promise<void> | void {
58
- return this.variables.delete(name)
59
- }
60
-
61
- async getAllStatus(): Promise<VariableStatus[]> {
62
- const results: VariableStatus[] = []
63
- const all = await this.variables.getAll()
64
-
65
- for (const [variableId, meta] of Object.entries(this.variablesMeta)) {
66
- results.push({
67
- variableId,
68
- name: meta.name,
69
- displayName: meta.displayName,
70
- isConfigured: all[variableId] !== undefined,
71
- })
72
- }
73
-
74
- return results
75
- }
76
-
77
- async getMissing(): Promise<VariableStatus[]> {
78
- const all = await this.getAllStatus()
79
- return all.filter((v) => !v.isConfigured)
80
- }
81
- }
@@ -1,113 +0,0 @@
1
- import { describe, test } from 'node:test'
2
- import assert from 'node:assert'
3
- import {
4
- PikkuSessionService,
5
- createMiddlewareSessionWireProps,
6
- createFunctionSessionWireProps,
7
- } from './user-session-service.js'
8
-
9
- describe('PikkuSessionService', () => {
10
- test('should set and get session', () => {
11
- const service = new PikkuSessionService()
12
- service.setInitial({ userId: 'user-1' })
13
- const session = service.get()
14
- assert.deepStrictEqual(session, { userId: 'user-1' })
15
- })
16
-
17
- test('should return undefined when no session set', () => {
18
- const service = new PikkuSessionService()
19
- assert.strictEqual(service.get(), undefined)
20
- })
21
-
22
- test('should mark sessionChanged when set is called', () => {
23
- const service = new PikkuSessionService()
24
- assert.strictEqual(service.sessionChanged, false)
25
- service.set({ userId: 'user-1' })
26
- assert.strictEqual(service.sessionChanged, true)
27
- })
28
-
29
- test('should clear session', () => {
30
- const service = new PikkuSessionService()
31
- service.setInitial({ userId: 'user-1' })
32
- service.clear()
33
- assert.strictEqual(service.get(), undefined)
34
- assert.strictEqual(service.sessionChanged, true)
35
- })
36
-
37
- test('should freeze initial session', () => {
38
- const service = new PikkuSessionService()
39
- service.setInitial({ userId: 'user-1' })
40
- const frozen = service.freezeInitial()
41
- assert.deepStrictEqual(frozen, { userId: 'user-1' })
42
- })
43
-
44
- test('should only freeze initial once', () => {
45
- const service = new PikkuSessionService()
46
- service.setInitial({ userId: 'user-1' })
47
- service.freezeInitial()
48
- service.set({ userId: 'user-2' })
49
- const frozen2 = service.freezeInitial()
50
- assert.deepStrictEqual(frozen2, { userId: 'user-1' })
51
- })
52
-
53
- test('should throw when channelStore provided without channelId', () => {
54
- assert.throws(() => new PikkuSessionService({} as any), {
55
- message: 'Channel ID is required when using channel store',
56
- })
57
- })
58
-
59
- test('should use channelStore when provided', async () => {
60
- let storedSession: any
61
- const store = {
62
- setUserSession: (id: string, session: any) => {
63
- storedSession = session
64
- },
65
- getChannelAndSession: (id: string) => ({ session: { userId: 'stored' } }),
66
- }
67
- const service = new PikkuSessionService(store as any, 'ch-1')
68
- service.set({ userId: 'new' })
69
- assert.deepStrictEqual(storedSession, { userId: 'new' })
70
-
71
- const session = service.get()
72
- assert.deepStrictEqual(session, { userId: 'stored' })
73
- })
74
- })
75
-
76
- describe('createMiddlewareSessionWireProps', () => {
77
- test('should return session wire props', () => {
78
- const service = new PikkuSessionService()
79
- service.setInitial({ userId: 'user-1' })
80
- const props = createMiddlewareSessionWireProps(service)
81
- assert.ok('session' in props)
82
- assert.ok('setSession' in props)
83
- assert.ok('getSession' in props)
84
- assert.ok('hasSessionChanged' in props)
85
- })
86
-
87
- test('setSession should call setInitial', () => {
88
- const service = new PikkuSessionService()
89
- const props = createMiddlewareSessionWireProps(service)
90
- props.setSession({ userId: 'user-2' })
91
- assert.deepStrictEqual(service.get(), { userId: 'user-2' })
92
- })
93
- })
94
-
95
- describe('createFunctionSessionWireProps', () => {
96
- test('should return function session wire props', () => {
97
- const service = new PikkuSessionService()
98
- service.setInitial({ userId: 'user-1' })
99
- const props = createFunctionSessionWireProps(service)
100
- assert.ok('session' in props)
101
- assert.ok('setSession' in props)
102
- assert.ok('clearSession' in props)
103
- assert.ok('getSession' in props)
104
- assert.ok('hasSessionChanged' in props)
105
- })
106
-
107
- test('session should be frozen initial', () => {
108
- const service = new PikkuSessionService()
109
- service.setInitial({ userId: 'user-1' })
110
- const props = createFunctionSessionWireProps(service)
111
- assert.deepStrictEqual(props.session, { userId: 'user-1' })
112
- })
113
- })
@@ -1,86 +0,0 @@
1
- import type { ChannelStore } from '../wirings/channel/channel-store.js'
2
- import type { CoreUserSession } from '../types/core.types.js'
3
-
4
- export interface SessionService<UserSession extends CoreUserSession> {
5
- sessionChanged: boolean
6
- initial: UserSession | undefined
7
- setInitial(session: UserSession): void
8
- freezeInitial(): UserSession | undefined
9
- set(session: UserSession): Promise<void> | void
10
- clear(): Promise<void> | void
11
- get(): Promise<UserSession> | UserSession | undefined
12
- }
13
-
14
- export class PikkuSessionService<UserSession extends CoreUserSession>
15
- implements SessionService<UserSession>
16
- {
17
- public sessionChanged = false
18
- public initial: UserSession | undefined
19
- private session: UserSession | undefined
20
- constructor(
21
- private channelStore?: ChannelStore<unknown, unknown, UserSession>,
22
- private channelId?: string
23
- ) {
24
- if (channelStore && !channelId) {
25
- throw new Error('Channel ID is required when using channel store')
26
- }
27
- }
28
-
29
- public setInitial(session: UserSession) {
30
- this.session = session
31
- }
32
-
33
- public freezeInitial() {
34
- if (this.initial === undefined) {
35
- this.initial = this.session
36
- }
37
- return this.initial
38
- }
39
-
40
- public set(session: UserSession) {
41
- this.sessionChanged = true
42
- this.session = session
43
- return this.channelStore?.setUserSession(this.channelId!, session)
44
- }
45
-
46
- public clear() {
47
- this.sessionChanged = true
48
- this.session = undefined
49
- return this.channelStore?.setUserSession(this.channelId!, null)
50
- }
51
-
52
- public get(): Promise<UserSession> | UserSession | undefined {
53
- if (this.channelStore) {
54
- const channel = this.channelStore.getChannelAndSession(this.channelId!)
55
- if (channel instanceof Promise) {
56
- return channel.then(({ session }) => session)
57
- } else {
58
- return channel.session
59
- }
60
- }
61
- return this.session
62
- }
63
- }
64
-
65
- export function createMiddlewareSessionWireProps<
66
- UserSession extends CoreUserSession,
67
- >(session: SessionService<UserSession>) {
68
- return {
69
- session: session.get() as UserSession | undefined,
70
- setSession: (s: UserSession) => session.setInitial(s),
71
- getSession: () => session.get(),
72
- hasSessionChanged: () => session.sessionChanged,
73
- }
74
- }
75
-
76
- export function createFunctionSessionWireProps<
77
- UserSession extends CoreUserSession,
78
- >(session: SessionService<UserSession>) {
79
- return {
80
- session: session.freezeInitial(),
81
- setSession: (s: UserSession) => session.set(s),
82
- clearSession: () => session.clear(),
83
- getSession: () => session.get(),
84
- hasSessionChanged: () => session.sessionChanged,
85
- }
86
- }