@sonamu-kit/tasks 0.2.0 → 0.3.0

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 (215) hide show
  1. package/.oxlintrc.json +3 -0
  2. package/AGENTS.md +21 -0
  3. package/dist/backend.d.ts +126 -107
  4. package/dist/backend.d.ts.map +1 -1
  5. package/dist/backend.js +4 -1
  6. package/dist/backend.js.map +1 -1
  7. package/dist/client.d.ts +145 -132
  8. package/dist/client.d.ts.map +1 -1
  9. package/dist/client.js +219 -213
  10. package/dist/client.js.map +1 -1
  11. package/dist/config.d.ts +15 -8
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/config.js +22 -17
  14. package/dist/config.js.map +1 -1
  15. package/dist/core/duration.d.ts +5 -4
  16. package/dist/core/duration.d.ts.map +1 -1
  17. package/dist/core/duration.js +54 -59
  18. package/dist/core/duration.js.map +1 -1
  19. package/dist/core/error.d.ts +10 -7
  20. package/dist/core/error.d.ts.map +1 -1
  21. package/dist/core/error.js +21 -21
  22. package/dist/core/error.js.map +1 -1
  23. package/dist/core/json.d.ts +8 -3
  24. package/dist/core/json.d.ts.map +1 -1
  25. package/dist/core/result.d.ts +10 -14
  26. package/dist/core/result.d.ts.map +1 -1
  27. package/dist/core/result.js +21 -16
  28. package/dist/core/result.js.map +1 -1
  29. package/dist/core/retry.d.ts +37 -31
  30. package/dist/core/retry.d.ts.map +1 -1
  31. package/dist/core/retry.js +44 -51
  32. package/dist/core/retry.js.map +1 -1
  33. package/dist/core/schema.d.ts +57 -53
  34. package/dist/core/schema.d.ts.map +1 -1
  35. package/dist/core/step.d.ts +28 -78
  36. package/dist/core/step.d.ts.map +1 -1
  37. package/dist/core/step.js +53 -63
  38. package/dist/core/step.js.map +1 -1
  39. package/dist/core/workflow.d.ts +33 -61
  40. package/dist/core/workflow.d.ts.map +1 -1
  41. package/dist/core/workflow.js +31 -41
  42. package/dist/core/workflow.js.map +1 -1
  43. package/dist/database/backend.d.ts +53 -46
  44. package/dist/database/backend.d.ts.map +1 -1
  45. package/dist/database/backend.js +544 -577
  46. package/dist/database/backend.js.map +1 -1
  47. package/dist/database/base.js +48 -25
  48. package/dist/database/base.js.map +1 -1
  49. package/dist/database/migrations/20251212000000_0_init.d.ts +10 -0
  50. package/dist/database/migrations/20251212000000_0_init.d.ts.map +1 -0
  51. package/dist/database/migrations/20251212000000_0_init.js +8 -4
  52. package/dist/database/migrations/20251212000000_0_init.js.map +1 -1
  53. package/dist/database/migrations/20251212000000_1_tables.d.ts +10 -0
  54. package/dist/database/migrations/20251212000000_1_tables.d.ts.map +1 -0
  55. package/dist/database/migrations/20251212000000_1_tables.js +81 -83
  56. package/dist/database/migrations/20251212000000_1_tables.js.map +1 -1
  57. package/dist/database/migrations/20251212000000_2_fk.d.ts +10 -0
  58. package/dist/database/migrations/20251212000000_2_fk.d.ts.map +1 -0
  59. package/dist/database/migrations/20251212000000_2_fk.js +20 -43
  60. package/dist/database/migrations/20251212000000_2_fk.js.map +1 -1
  61. package/dist/database/migrations/20251212000000_3_indexes.d.ts +10 -0
  62. package/dist/database/migrations/20251212000000_3_indexes.d.ts.map +1 -0
  63. package/dist/database/migrations/20251212000000_3_indexes.js +88 -102
  64. package/dist/database/migrations/20251212000000_3_indexes.js.map +1 -1
  65. package/dist/database/pubsub.d.ts +7 -16
  66. package/dist/database/pubsub.d.ts.map +1 -1
  67. package/dist/database/pubsub.js +75 -73
  68. package/dist/database/pubsub.js.map +1 -1
  69. package/dist/execution.d.ts +20 -59
  70. package/dist/execution.d.ts.map +1 -1
  71. package/dist/execution.js +175 -188
  72. package/dist/execution.js.map +1 -1
  73. package/dist/index.d.ts +5 -8
  74. package/dist/index.js +5 -5
  75. package/dist/internal.d.ts +12 -13
  76. package/dist/internal.js +4 -4
  77. package/dist/registry.d.ts +33 -27
  78. package/dist/registry.d.ts.map +1 -1
  79. package/dist/registry.js +58 -49
  80. package/dist/registry.js.map +1 -1
  81. package/dist/worker.d.ts +57 -50
  82. package/dist/worker.d.ts.map +1 -1
  83. package/dist/worker.js +194 -199
  84. package/dist/worker.js.map +1 -1
  85. package/dist/workflow.d.ts +26 -30
  86. package/dist/workflow.d.ts.map +1 -1
  87. package/dist/workflow.js +20 -15
  88. package/dist/workflow.js.map +1 -1
  89. package/nodemon.json +1 -1
  90. package/package.json +17 -19
  91. package/src/backend.ts +25 -9
  92. package/src/chaos.test.ts +3 -1
  93. package/src/client.test.ts +2 -0
  94. package/src/client.ts +30 -8
  95. package/src/config.test.ts +1 -0
  96. package/src/config.ts +3 -2
  97. package/src/core/duration.test.ts +2 -1
  98. package/src/core/duration.ts +1 -1
  99. package/src/core/error.test.ts +1 -0
  100. package/src/core/error.ts +1 -1
  101. package/src/core/result.test.ts +1 -0
  102. package/src/core/retry.test.ts +3 -2
  103. package/src/core/retry.ts +1 -1
  104. package/src/core/schema.ts +2 -2
  105. package/src/core/step.test.ts +2 -1
  106. package/src/core/step.ts +4 -3
  107. package/src/core/workflow.test.ts +2 -1
  108. package/src/core/workflow.ts +4 -3
  109. package/src/database/backend.test.ts +1 -0
  110. package/src/database/backend.testsuite.ts +44 -40
  111. package/src/database/backend.ts +207 -25
  112. package/src/database/base.test.ts +41 -0
  113. package/src/database/base.ts +51 -2
  114. package/src/database/migrations/20251212000000_0_init.ts +2 -1
  115. package/src/database/migrations/20251212000000_1_tables.ts +2 -1
  116. package/src/database/migrations/20251212000000_2_fk.ts +2 -1
  117. package/src/database/migrations/20251212000000_3_indexes.ts +2 -1
  118. package/src/database/pubsub.test.ts +6 -3
  119. package/src/database/pubsub.ts +55 -33
  120. package/src/execution.test.ts +2 -0
  121. package/src/execution.ts +49 -10
  122. package/src/internal.ts +15 -15
  123. package/src/practices/01-remote-workflow.ts +1 -0
  124. package/src/registry.test.ts +1 -0
  125. package/src/registry.ts +1 -1
  126. package/src/testing/connection.ts +3 -1
  127. package/src/worker.test.ts +2 -0
  128. package/src/worker.ts +30 -9
  129. package/src/workflow.test.ts +1 -0
  130. package/src/workflow.ts +3 -3
  131. package/templates/openworkflow.config.ts +2 -1
  132. package/tsdown.config.ts +31 -0
  133. package/.swcrc +0 -17
  134. package/dist/chaos.test.d.ts +0 -2
  135. package/dist/chaos.test.d.ts.map +0 -1
  136. package/dist/chaos.test.js +0 -92
  137. package/dist/chaos.test.js.map +0 -1
  138. package/dist/client.test.d.ts +0 -2
  139. package/dist/client.test.d.ts.map +0 -1
  140. package/dist/client.test.js +0 -340
  141. package/dist/client.test.js.map +0 -1
  142. package/dist/config.test.d.ts +0 -2
  143. package/dist/config.test.d.ts.map +0 -1
  144. package/dist/config.test.js +0 -24
  145. package/dist/config.test.js.map +0 -1
  146. package/dist/core/duration.test.d.ts +0 -2
  147. package/dist/core/duration.test.d.ts.map +0 -1
  148. package/dist/core/duration.test.js +0 -265
  149. package/dist/core/duration.test.js.map +0 -1
  150. package/dist/core/error.test.d.ts +0 -2
  151. package/dist/core/error.test.d.ts.map +0 -1
  152. package/dist/core/error.test.js +0 -63
  153. package/dist/core/error.test.js.map +0 -1
  154. package/dist/core/json.js +0 -3
  155. package/dist/core/json.js.map +0 -1
  156. package/dist/core/result.test.d.ts +0 -2
  157. package/dist/core/result.test.d.ts.map +0 -1
  158. package/dist/core/result.test.js +0 -19
  159. package/dist/core/result.test.js.map +0 -1
  160. package/dist/core/retry.test.d.ts +0 -2
  161. package/dist/core/retry.test.d.ts.map +0 -1
  162. package/dist/core/retry.test.js +0 -198
  163. package/dist/core/retry.test.js.map +0 -1
  164. package/dist/core/schema.js +0 -4
  165. package/dist/core/schema.js.map +0 -1
  166. package/dist/core/step.test.d.ts +0 -2
  167. package/dist/core/step.test.d.ts.map +0 -1
  168. package/dist/core/step.test.js +0 -356
  169. package/dist/core/step.test.js.map +0 -1
  170. package/dist/core/workflow.test.d.ts +0 -2
  171. package/dist/core/workflow.test.d.ts.map +0 -1
  172. package/dist/core/workflow.test.js +0 -172
  173. package/dist/core/workflow.test.js.map +0 -1
  174. package/dist/database/backend.test.d.ts +0 -2
  175. package/dist/database/backend.test.d.ts.map +0 -1
  176. package/dist/database/backend.test.js +0 -19
  177. package/dist/database/backend.test.js.map +0 -1
  178. package/dist/database/backend.testsuite.d.ts +0 -20
  179. package/dist/database/backend.testsuite.d.ts.map +0 -1
  180. package/dist/database/backend.testsuite.js +0 -1280
  181. package/dist/database/backend.testsuite.js.map +0 -1
  182. package/dist/database/base.d.ts +0 -12
  183. package/dist/database/base.d.ts.map +0 -1
  184. package/dist/database/pubsub.test.d.ts +0 -2
  185. package/dist/database/pubsub.test.d.ts.map +0 -1
  186. package/dist/database/pubsub.test.js +0 -86
  187. package/dist/database/pubsub.test.js.map +0 -1
  188. package/dist/execution.test.d.ts +0 -2
  189. package/dist/execution.test.d.ts.map +0 -1
  190. package/dist/execution.test.js +0 -662
  191. package/dist/execution.test.js.map +0 -1
  192. package/dist/index.d.ts.map +0 -1
  193. package/dist/index.js.map +0 -1
  194. package/dist/internal.d.ts.map +0 -1
  195. package/dist/internal.js.map +0 -1
  196. package/dist/practices/01-remote-workflow.d.ts +0 -2
  197. package/dist/practices/01-remote-workflow.d.ts.map +0 -1
  198. package/dist/practices/01-remote-workflow.js +0 -70
  199. package/dist/practices/01-remote-workflow.js.map +0 -1
  200. package/dist/registry.test.d.ts +0 -2
  201. package/dist/registry.test.d.ts.map +0 -1
  202. package/dist/registry.test.js +0 -95
  203. package/dist/registry.test.js.map +0 -1
  204. package/dist/testing/connection.d.ts +0 -7
  205. package/dist/testing/connection.d.ts.map +0 -1
  206. package/dist/testing/connection.js +0 -39
  207. package/dist/testing/connection.js.map +0 -1
  208. package/dist/worker.test.d.ts +0 -2
  209. package/dist/worker.test.d.ts.map +0 -1
  210. package/dist/worker.test.js +0 -1164
  211. package/dist/worker.test.js.map +0 -1
  212. package/dist/workflow.test.d.ts +0 -2
  213. package/dist/workflow.test.d.ts.map +0 -1
  214. package/dist/workflow.test.js +0 -73
  215. package/dist/workflow.test.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/core/retry.test.ts"],"sourcesContent":["import { describe, expect, test } from \"vitest\";\nimport type { SerializedError } from \"./error\";\nimport type { DynamicRetryPolicy, StaticRetryPolicy } from \"./retry\";\nimport {\n calculateRetryDelayMs,\n DEFAULT_RETRY_POLICY,\n isDynamicRetryPolicy,\n isStaticRetryPolicy,\n mergeRetryPolicy,\n serializeRetryPolicy,\n shouldRetry,\n shouldRetryByPolicy,\n} from \"./retry\";\n\ndescribe(\"calculateRetryDelayMs\", () => {\n test(\"calculates exponential backoff correctly\", () => {\n expect(calculateRetryDelayMs(1)).toBe(1000);\n expect(calculateRetryDelayMs(2)).toBe(2000);\n expect(calculateRetryDelayMs(3)).toBe(4000);\n expect(calculateRetryDelayMs(4)).toBe(8000);\n expect(calculateRetryDelayMs(5)).toBe(16_000);\n expect(calculateRetryDelayMs(6)).toBe(32_000);\n // attempt 7: 1s * 2^6 = 64s = 64000ms, capped at 60000ms (max)\n expect(calculateRetryDelayMs(7)).toBe(60_000);\n });\n\n test(\"caps delay at maximum interval\", () => {\n const { maximumIntervalMs } = DEFAULT_RETRY_POLICY;\n\n // attempt 7: 1s * 2^6 = 64s = 64000ms, capped at 60000ms (max)\n expect(calculateRetryDelayMs(7)).toBe(maximumIntervalMs);\n\n // attempts 10 & 100: should still be capped\n expect(calculateRetryDelayMs(10)).toBe(maximumIntervalMs);\n expect(calculateRetryDelayMs(100)).toBe(maximumIntervalMs);\n });\n\n test(\"handles edge cases\", () => {\n // attempt 0: 1s * 2^-1 = 0.5s = 500ms\n expect(calculateRetryDelayMs(0)).toBe(500);\n expect(calculateRetryDelayMs(Infinity)).toBe(60_000);\n });\n});\n\ndescribe(\"shouldRetry\", () => {\n test(\"returns false when attempt reaches maxAttempts\", () => {\n // 기본 정책: maxAttempts = 5\n expect(shouldRetry(DEFAULT_RETRY_POLICY, 1)).toBe(true);\n expect(shouldRetry(DEFAULT_RETRY_POLICY, 4)).toBe(true);\n expect(shouldRetry(DEFAULT_RETRY_POLICY, 5)).toBe(false);\n expect(shouldRetry(DEFAULT_RETRY_POLICY, 10)).toBe(false);\n });\n});\n\ndescribe(\"shouldRetryByPolicy\", () => {\n test(\"respects maxAttempts from policy\", () => {\n expect(shouldRetryByPolicy({ maxAttempts: 3 }, 1)).toBe(true);\n expect(shouldRetryByPolicy({ maxAttempts: 3 }, 2)).toBe(true);\n expect(shouldRetryByPolicy({ maxAttempts: 3 }, 3)).toBe(false);\n expect(shouldRetryByPolicy({ maxAttempts: 3 }, 4)).toBe(false);\n });\n\n test(\"uses default maxAttempts when not specified\", () => {\n expect(shouldRetryByPolicy({}, 1)).toBe(true);\n expect(shouldRetryByPolicy({}, 4)).toBe(true);\n expect(shouldRetryByPolicy({}, 5)).toBe(false);\n });\n});\n\ndescribe(\"isDynamicRetryPolicy\", () => {\n test(\"returns true for policy with shouldRetry function\", () => {\n const dynamicPolicy: DynamicRetryPolicy = {\n maxAttempts: 3,\n shouldRetry: () => ({ shouldRetry: true, delayMs: 1000 }),\n };\n expect(isDynamicRetryPolicy(dynamicPolicy)).toBe(true);\n });\n\n test(\"returns false for static policy without shouldRetry\", () => {\n const staticPolicy: StaticRetryPolicy = {\n maxAttempts: 5,\n initialIntervalMs: 1000,\n };\n expect(isDynamicRetryPolicy(staticPolicy)).toBe(false);\n });\n\n test(\"returns false for empty policy\", () => {\n expect(isDynamicRetryPolicy({})).toBe(false);\n });\n});\n\ndescribe(\"isStaticRetryPolicy\", () => {\n test(\"returns true for static policy without shouldRetry\", () => {\n const staticPolicy: StaticRetryPolicy = {\n maxAttempts: 5,\n initialIntervalMs: 1000,\n };\n expect(isStaticRetryPolicy(staticPolicy)).toBe(true);\n });\n\n test(\"returns true for empty policy\", () => {\n expect(isStaticRetryPolicy({})).toBe(true);\n });\n\n test(\"returns false for dynamic policy\", () => {\n const dynamicPolicy: DynamicRetryPolicy = {\n maxAttempts: 3,\n shouldRetry: () => ({ shouldRetry: true, delayMs: 1000 }),\n };\n expect(isStaticRetryPolicy(dynamicPolicy)).toBe(false);\n });\n});\n\ndescribe(\"mergeRetryPolicy\", () => {\n test(\"returns default values when policy is undefined\", () => {\n const merged = mergeRetryPolicy(undefined);\n expect(merged.maxAttempts).toBe(5);\n expect(merged.initialIntervalMs).toBe(1000);\n expect(merged.backoffCoefficient).toBe(2);\n expect(merged.maximumIntervalMs).toBe(60_000);\n });\n\n test(\"uses provided values and fills missing with defaults for static policy\", () => {\n const merged = mergeRetryPolicy({ maxAttempts: 10, initialIntervalMs: 500 });\n expect(merged.maxAttempts).toBe(10);\n expect(merged.initialIntervalMs).toBe(500);\n expect(merged.backoffCoefficient).toBe(2);\n expect(merged.maximumIntervalMs).toBe(60_000);\n });\n\n test(\"returns only maxAttempts and shouldRetry for dynamic policy\", () => {\n const customFn = (_error: SerializedError, _attempt: number) => ({\n shouldRetry: false,\n delayMs: 5000,\n });\n const dynamicPolicy: DynamicRetryPolicy = {\n maxAttempts: 3,\n shouldRetry: customFn,\n };\n const merged = mergeRetryPolicy(dynamicPolicy);\n\n expect(merged.maxAttempts).toBe(3);\n expect(merged.shouldRetry).toBe(customFn);\n // 동적 정책에서는 backoff 필드들이 없어야 합니다.\n expect(\"initialIntervalMs\" in merged).toBe(false);\n expect(\"backoffCoefficient\" in merged).toBe(false);\n expect(\"maximumIntervalMs\" in merged).toBe(false);\n });\n\n test(\"uses default maxAttempts for dynamic policy when not specified\", () => {\n const customFn = () => ({ shouldRetry: true, delayMs: 1000 });\n const dynamicPolicy: DynamicRetryPolicy = {\n shouldRetry: customFn,\n };\n const merged = mergeRetryPolicy(dynamicPolicy);\n\n expect(merged.maxAttempts).toBe(5); // 기본값\n expect(merged.shouldRetry).toBe(customFn);\n });\n});\n\ndescribe(\"serializeRetryPolicy\", () => {\n test(\"returns empty object with hasDynamicPolicy=false for undefined\", () => {\n const serialized = serializeRetryPolicy(undefined);\n expect(serialized.hasDynamicPolicy).toBe(false);\n expect(serialized.maxAttempts).toBeUndefined();\n });\n\n test(\"serializes static fields for static policy\", () => {\n const serialized = serializeRetryPolicy({\n maxAttempts: 10,\n initialIntervalMs: 2000,\n });\n expect(serialized.maxAttempts).toBe(10);\n expect(serialized.initialIntervalMs).toBe(2000);\n expect(serialized.hasDynamicPolicy).toBe(false);\n expect(\"shouldRetry\" in serialized).toBe(false);\n });\n\n test(\"excludes backoff fields for dynamic policy\", () => {\n const dynamicPolicy: DynamicRetryPolicy = {\n maxAttempts: 3,\n shouldRetry: () => ({ shouldRetry: true, delayMs: 1000 }),\n };\n const serialized = serializeRetryPolicy(dynamicPolicy);\n\n expect(serialized.maxAttempts).toBe(3);\n expect(serialized.hasDynamicPolicy).toBe(true);\n // 동적 정책에서는 backoff 필드들이 없어야 합니다.\n expect(serialized.initialIntervalMs).toBeUndefined();\n expect(serialized.backoffCoefficient).toBeUndefined();\n expect(serialized.maximumIntervalMs).toBeUndefined();\n });\n\n test(\"includes backoff fields for static policy\", () => {\n const staticPolicy: StaticRetryPolicy = {\n maxAttempts: 5,\n initialIntervalMs: 2000,\n backoffCoefficient: 3,\n maximumIntervalMs: 30000,\n };\n const serialized = serializeRetryPolicy(staticPolicy);\n\n expect(serialized.maxAttempts).toBe(5);\n expect(serialized.initialIntervalMs).toBe(2000);\n expect(serialized.backoffCoefficient).toBe(3);\n expect(serialized.maximumIntervalMs).toBe(30000);\n expect(serialized.hasDynamicPolicy).toBe(false);\n });\n});\n"],"names":["describe","expect","test","calculateRetryDelayMs","DEFAULT_RETRY_POLICY","isDynamicRetryPolicy","isStaticRetryPolicy","mergeRetryPolicy","serializeRetryPolicy","shouldRetry","shouldRetryByPolicy","toBe","maximumIntervalMs","Infinity","maxAttempts","dynamicPolicy","delayMs","staticPolicy","initialIntervalMs","merged","undefined","backoffCoefficient","customFn","_error","_attempt","serialized","hasDynamicPolicy","toBeUndefined"],"mappings":"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"}
@@ -1,4 +0,0 @@
1
- /** The Standard Schema interface. https://standardschema.dev */ // eslint-disable-next-line @typescript-eslint/no-namespace
2
- export { };
3
-
4
- //# sourceMappingURL=schema.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/core/schema.ts"],"sourcesContent":["/** The Standard Schema interface. https://standardschema.dev */\nexport interface StandardSchemaV1<Input = unknown, Output = Input> {\n /** The Standard Schema properties. */\n readonly \"~standard\": StandardSchemaV1.Props<Input, Output>;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport declare namespace StandardSchemaV1 {\n /** The Standard Schema properties interface. */\n // eslint-disable-next-line functional/no-mixed-types\n export interface Props<Input = unknown, Output = Input> {\n /** The version number of the standard. */\n readonly version: 1;\n /** The vendor name of the schema library. */\n readonly vendor: string;\n /** Validates unknown input values. */\n readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;\n /** Inferred types associated with the schema. */\n readonly types?: Types<Input, Output> | undefined;\n }\n\n /** The result interface of the validate function. */\n export type Result<Output> = SuccessResult<Output> | FailureResult;\n\n /** The result interface if validation succeeds. */\n export interface SuccessResult<Output> {\n /** The typed output value. */\n readonly value: Output;\n /** The non-existent issues. */\n readonly issues?: undefined;\n }\n\n /** The result interface if validation fails. */\n export interface FailureResult {\n /** The issues of failed validation. */\n readonly issues: readonly Issue[];\n }\n\n /** The issue interface of the failure output. */\n export interface Issue {\n /** The error message of the issue. */\n readonly message: string;\n /** The path of the issue, if any. */\n readonly path?: readonly (PropertyKey | PathSegment)[] | undefined;\n }\n\n /** The path segment interface of the issue. */\n export interface PathSegment {\n /** The key representing a path segment. */\n readonly key: PropertyKey;\n }\n\n /** The Standard Schema types interface. */\n export interface Types<Input = unknown, Output = Input> {\n /** The input type of the schema. */\n readonly input: Input;\n /** The output type of the schema. */\n readonly output: Output;\n }\n\n /** Infers the input type of a Standard Schema. */\n export type InferInput<Schema extends StandardSchemaV1> = NonNullable<\n Schema[\"~standard\"][\"types\"]\n >[\"input\"];\n\n /** Infers the output type of a Standard Schema. */\n export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<\n Schema[\"~standard\"][\"types\"]\n >[\"output\"];\n\n // eslint-disable-next-line unicorn/require-module-specifiers\n // biome-ignore lint/complexity/noUselessEmptyExport: needed for granular visibility control of TS namespace\n export {};\n}\n"],"names":[],"mappings":"AAAA,8DAA8D,GAM9D,2DAA2D;AAC3D,WAkEC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=step.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"step.test.d.ts","sourceRoot":"","sources":["../../src/core/step.test.ts"],"names":[],"mappings":""}
@@ -1,356 +0,0 @@
1
- import { describe, expect, test } from "vitest";
2
- import { ok } from "./result.js";
3
- import { addToStepAttemptCache, calculateSleepResumeAt, createSleepContext, createStepAttemptCacheFromAttempts, getCachedStepAttempt, hasCompletedStep, normalizeStepOutput } from "./step.js";
4
- describe("createStepAttemptCacheFromAttempts", ()=>{
5
- test("creates empty cache from empty array", ()=>{
6
- const cache = createStepAttemptCacheFromAttempts([]);
7
- expect(cache.size).toBe(0);
8
- });
9
- test("includes completed attempts in cache", ()=>{
10
- const attempt = createMockStepAttempt({
11
- stepName: "step-a",
12
- status: "completed",
13
- output: "result"
14
- });
15
- const cache = createStepAttemptCacheFromAttempts([
16
- attempt
17
- ]);
18
- expect(cache.size).toBe(1);
19
- expect(cache.get("step-a")).toBe(attempt);
20
- });
21
- test("includes succeeded attempts in cache (deprecated status)", ()=>{
22
- const attempt = createMockStepAttempt({
23
- stepName: "step-b",
24
- status: "succeeded",
25
- output: "result"
26
- });
27
- const cache = createStepAttemptCacheFromAttempts([
28
- attempt
29
- ]);
30
- expect(cache.size).toBe(1);
31
- expect(cache.get("step-b")).toBe(attempt);
32
- });
33
- test("excludes running attempts from cache", ()=>{
34
- const attempt = createMockStepAttempt({
35
- stepName: "step-c",
36
- status: "running"
37
- });
38
- const cache = createStepAttemptCacheFromAttempts([
39
- attempt
40
- ]);
41
- expect(cache.size).toBe(0);
42
- });
43
- test("excludes failed attempts from cache", ()=>{
44
- const attempt = createMockStepAttempt({
45
- stepName: "step-d",
46
- status: "failed",
47
- error: {
48
- message: "failed"
49
- }
50
- });
51
- const cache = createStepAttemptCacheFromAttempts([
52
- attempt
53
- ]);
54
- expect(cache.size).toBe(0);
55
- });
56
- test("filters mixed statuses correctly", ()=>{
57
- const attempts = [
58
- createMockStepAttempt({
59
- stepName: "completed-step",
60
- status: "completed"
61
- }),
62
- createMockStepAttempt({
63
- stepName: "running-step",
64
- status: "running"
65
- }),
66
- createMockStepAttempt({
67
- stepName: "failed-step",
68
- status: "failed"
69
- }),
70
- createMockStepAttempt({
71
- stepName: "succeeded-step",
72
- status: "succeeded"
73
- })
74
- ];
75
- const cache = createStepAttemptCacheFromAttempts(attempts);
76
- expect(cache.size).toBe(2);
77
- expect(cache.has("completed-step")).toBe(true);
78
- expect(cache.has("succeeded-step")).toBe(true);
79
- expect(cache.has("running-step")).toBe(false);
80
- expect(cache.has("failed-step")).toBe(false);
81
- });
82
- test("uses step name as cache key", ()=>{
83
- const attempt = createMockStepAttempt({
84
- stepName: "my-unique-step-name",
85
- status: "completed"
86
- });
87
- const cache = createStepAttemptCacheFromAttempts([
88
- attempt
89
- ]);
90
- expect(cache.get("my-unique-step-name")).toBe(attempt);
91
- expect(cache.get("other-name")).toBeUndefined();
92
- });
93
- });
94
- describe("getCachedStepAttempt", ()=>{
95
- test("returns cached attempt when present", ()=>{
96
- const attempt = createMockStepAttempt({
97
- stepName: "cached-step"
98
- });
99
- const cache = new Map([
100
- [
101
- "cached-step",
102
- attempt
103
- ]
104
- ]);
105
- const result = getCachedStepAttempt(cache, "cached-step");
106
- expect(result).toBe(attempt);
107
- });
108
- test("returns undefined when step not in cache", ()=>{
109
- const cache = new Map();
110
- const result = getCachedStepAttempt(cache, "missing-step");
111
- expect(result).toBeUndefined();
112
- });
113
- test("returns undefined for similar but different step names", ()=>{
114
- const attempt = createMockStepAttempt({
115
- stepName: "step-1"
116
- });
117
- const cache = new Map([
118
- [
119
- "step-1",
120
- attempt
121
- ]
122
- ]);
123
- expect(getCachedStepAttempt(cache, "step-2")).toBeUndefined();
124
- expect(getCachedStepAttempt(cache, "Step-1")).toBeUndefined();
125
- expect(getCachedStepAttempt(cache, "step-1 ")).toBeUndefined();
126
- });
127
- });
128
- describe("hasCompletedStep", ()=>{
129
- test("returns true when step is in cache", ()=>{
130
- const attempt = createMockStepAttempt({
131
- stepName: "step-x"
132
- });
133
- const cache = new Map([
134
- [
135
- "step-x",
136
- attempt
137
- ]
138
- ]);
139
- expect(hasCompletedStep(cache, "step-x")).toBe(true);
140
- });
141
- test("returns false when step is not in cache", ()=>{
142
- const cache = new Map();
143
- expect(hasCompletedStep(cache, "step-y")).toBe(false);
144
- });
145
- test("returns false for empty cache", ()=>{
146
- const cache = new Map();
147
- expect(hasCompletedStep(cache, "any-step")).toBe(false);
148
- });
149
- });
150
- describe("addToStepAttemptCache", ()=>{
151
- test("adds attempt to empty cache", ()=>{
152
- const cache = new Map();
153
- const attempt = createMockStepAttempt({
154
- stepName: "new-step"
155
- });
156
- const newCache = addToStepAttemptCache(cache, attempt);
157
- expect(newCache.size).toBe(1);
158
- expect(newCache.get("new-step")).toBe(attempt);
159
- });
160
- test("adds attempt to existing cache", ()=>{
161
- const existing = createMockStepAttempt({
162
- stepName: "existing-step"
163
- });
164
- const cache = new Map([
165
- [
166
- "existing-step",
167
- existing
168
- ]
169
- ]);
170
- const newAttempt = createMockStepAttempt({
171
- stepName: "new-step"
172
- });
173
- const newCache = addToStepAttemptCache(cache, newAttempt);
174
- expect(newCache.size).toBe(2);
175
- expect(newCache.get("existing-step")).toBe(existing);
176
- expect(newCache.get("new-step")).toBe(newAttempt);
177
- });
178
- test("does not mutate original cache (immutable)", ()=>{
179
- const existing = createMockStepAttempt({
180
- stepName: "existing-step"
181
- });
182
- const cache = new Map([
183
- [
184
- "existing-step",
185
- existing
186
- ]
187
- ]);
188
- const newAttempt = createMockStepAttempt({
189
- stepName: "new-step"
190
- });
191
- const newCache = addToStepAttemptCache(cache, newAttempt);
192
- expect(cache.size).toBe(1);
193
- expect(cache.has("new-step")).toBe(false);
194
- expect(newCache.size).toBe(2);
195
- });
196
- test("overwrites existing entry with same step name", ()=>{
197
- const original = createMockStepAttempt({
198
- stepName: "step",
199
- output: "original"
200
- });
201
- const cache = new Map([
202
- [
203
- "step",
204
- original
205
- ]
206
- ]);
207
- const replacement = createMockStepAttempt({
208
- stepName: "step",
209
- output: "replacement"
210
- });
211
- const newCache = addToStepAttemptCache(cache, replacement);
212
- expect(newCache.size).toBe(1);
213
- expect(newCache.get("step")?.output).toBe("replacement");
214
- });
215
- });
216
- describe("normalizeStepOutput", ()=>{
217
- test("passes through string values", ()=>{
218
- expect(normalizeStepOutput("hello")).toBe("hello");
219
- });
220
- test("passes through number values", ()=>{
221
- expect(normalizeStepOutput(42)).toBe(42);
222
- expect(normalizeStepOutput(3.14)).toBe(3.14);
223
- expect(normalizeStepOutput(0)).toBe(0);
224
- expect(normalizeStepOutput(-1)).toBe(-1);
225
- });
226
- test("passes through boolean values", ()=>{
227
- expect(normalizeStepOutput(true)).toBe(true);
228
- expect(normalizeStepOutput(false)).toBe(false);
229
- });
230
- test("passes through null", ()=>{
231
- expect(normalizeStepOutput(null)).toBeNull();
232
- });
233
- test("converts undefined to null", ()=>{
234
- // eslint-disable-next-line unicorn/no-useless-undefined
235
- expect(normalizeStepOutput(undefined)).toBeNull();
236
- });
237
- test("passes through object values", ()=>{
238
- const obj = {
239
- foo: "bar",
240
- nested: {
241
- baz: 123
242
- }
243
- };
244
- expect(normalizeStepOutput(obj)).toBe(obj);
245
- });
246
- test("passes through array values", ()=>{
247
- const arr = [
248
- 1,
249
- 2,
250
- 3
251
- ];
252
- expect(normalizeStepOutput(arr)).toBe(arr);
253
- });
254
- test("passes through empty object", ()=>{
255
- const obj = {};
256
- expect(normalizeStepOutput(obj)).toBe(obj);
257
- });
258
- test("passes through empty array", ()=>{
259
- const arr = [];
260
- expect(normalizeStepOutput(arr)).toBe(arr);
261
- });
262
- });
263
- describe("calculateSleepResumeAt", ()=>{
264
- test("calculates resume time from duration string", ()=>{
265
- const now = 1_000_000;
266
- const result = calculateSleepResumeAt("5s", now);
267
- expect(result).toEqual(ok(new Date(now + 5000)));
268
- });
269
- test("calculates resume time with milliseconds", ()=>{
270
- const now = 1_000_000;
271
- const result = calculateSleepResumeAt("500ms", now);
272
- expect(result).toEqual(ok(new Date(now + 500)));
273
- });
274
- test("calculates resume time with minutes", ()=>{
275
- const now = 1_000_000;
276
- const result = calculateSleepResumeAt("2m", now);
277
- expect(result).toEqual(ok(new Date(now + 2 * 60 * 1000)));
278
- });
279
- test("calculates resume time with hours", ()=>{
280
- const now = 1_000_000;
281
- const result = calculateSleepResumeAt("1h", now);
282
- expect(result).toEqual(ok(new Date(now + 60 * 60 * 1000)));
283
- });
284
- test("uses Date.now() when now is not provided", ()=>{
285
- const before = Date.now();
286
- const result = calculateSleepResumeAt("1s");
287
- const after = Date.now();
288
- expect(result.ok).toBe(true);
289
- if (result.ok) {
290
- const resumeTime = result.value.getTime();
291
- expect(resumeTime).toBeGreaterThanOrEqual(before + 1000);
292
- expect(resumeTime).toBeLessThanOrEqual(after + 1000);
293
- }
294
- });
295
- test("returns error for invalid duration", ()=>{
296
- // @ts-expect-error testing invalid input
297
- const result = calculateSleepResumeAt("invalid");
298
- expect(result.ok).toBe(false);
299
- if (!result.ok) {
300
- expect(result.error).toBeInstanceOf(Error);
301
- }
302
- });
303
- test("returns error for empty duration", ()=>{
304
- // @ts-expect-error testing invalid input
305
- const result = calculateSleepResumeAt("");
306
- expect(result.ok).toBe(false);
307
- });
308
- });
309
- describe("createSleepContext", ()=>{
310
- test("creates sleep context with ISO string timestamp", ()=>{
311
- const resumeAt = new Date("2025-06-15T10:30:00.000Z");
312
- const context = createSleepContext(resumeAt);
313
- expect(context).toEqual({
314
- kind: "sleep",
315
- resumeAt: "2025-06-15T10:30:00.000Z"
316
- });
317
- });
318
- test("preserves millisecond precision", ()=>{
319
- const resumeAt = new Date("2025-01-01T00:00:00.123Z");
320
- const context = createSleepContext(resumeAt);
321
- expect(context.resumeAt).toBe("2025-01-01T00:00:00.123Z");
322
- });
323
- test("always has kind set to sleep", ()=>{
324
- const resumeAt = new Date();
325
- const context = createSleepContext(resumeAt);
326
- expect(context.kind).toBe("sleep");
327
- });
328
- test("creates context from current date", ()=>{
329
- const now = new Date();
330
- const context = createSleepContext(now);
331
- expect(context.resumeAt).toBe(now.toISOString());
332
- });
333
- });
334
- function createMockStepAttempt(overrides = {}) {
335
- return {
336
- namespaceId: "default",
337
- id: "step-1",
338
- workflowRunId: "workflow-1",
339
- stepName: "test-step",
340
- kind: "function",
341
- status: "completed",
342
- config: {},
343
- context: null,
344
- output: null,
345
- error: null,
346
- childWorkflowRunNamespaceId: null,
347
- childWorkflowRunId: null,
348
- startedAt: new Date("2025-01-01T00:00:00Z"),
349
- finishedAt: new Date("2025-01-01T00:00:01Z"),
350
- createdAt: new Date("2025-01-01T00:00:00Z"),
351
- updatedAt: new Date("2025-01-01T00:00:01Z"),
352
- ...overrides
353
- };
354
- }
355
-
356
- //# sourceMappingURL=step.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/core/step.test.ts"],"sourcesContent":["import { describe, expect, test } from \"vitest\";\nimport { ok } from \"./result\";\nimport type { StepAttempt, StepAttemptCache } from \"./step\";\nimport {\n addToStepAttemptCache,\n calculateSleepResumeAt,\n createSleepContext,\n createStepAttemptCacheFromAttempts,\n getCachedStepAttempt,\n hasCompletedStep,\n normalizeStepOutput,\n} from \"./step\";\n\ndescribe(\"createStepAttemptCacheFromAttempts\", () => {\n test(\"creates empty cache from empty array\", () => {\n const cache = createStepAttemptCacheFromAttempts([]);\n\n expect(cache.size).toBe(0);\n });\n\n test(\"includes completed attempts in cache\", () => {\n const attempt = createMockStepAttempt({\n stepName: \"step-a\",\n status: \"completed\",\n output: \"result\",\n });\n const cache = createStepAttemptCacheFromAttempts([attempt]);\n\n expect(cache.size).toBe(1);\n expect(cache.get(\"step-a\")).toBe(attempt);\n });\n\n test(\"includes succeeded attempts in cache (deprecated status)\", () => {\n const attempt = createMockStepAttempt({\n stepName: \"step-b\",\n status: \"succeeded\",\n output: \"result\",\n });\n const cache = createStepAttemptCacheFromAttempts([attempt]);\n\n expect(cache.size).toBe(1);\n expect(cache.get(\"step-b\")).toBe(attempt);\n });\n\n test(\"excludes running attempts from cache\", () => {\n const attempt = createMockStepAttempt({\n stepName: \"step-c\",\n status: \"running\",\n });\n const cache = createStepAttemptCacheFromAttempts([attempt]);\n\n expect(cache.size).toBe(0);\n });\n\n test(\"excludes failed attempts from cache\", () => {\n const attempt = createMockStepAttempt({\n stepName: \"step-d\",\n status: \"failed\",\n error: { message: \"failed\" },\n });\n const cache = createStepAttemptCacheFromAttempts([attempt]);\n\n expect(cache.size).toBe(0);\n });\n\n test(\"filters mixed statuses correctly\", () => {\n const attempts = [\n createMockStepAttempt({\n stepName: \"completed-step\",\n status: \"completed\",\n }),\n createMockStepAttempt({ stepName: \"running-step\", status: \"running\" }),\n createMockStepAttempt({ stepName: \"failed-step\", status: \"failed\" }),\n createMockStepAttempt({\n stepName: \"succeeded-step\",\n status: \"succeeded\",\n }),\n ];\n const cache = createStepAttemptCacheFromAttempts(attempts);\n\n expect(cache.size).toBe(2);\n expect(cache.has(\"completed-step\")).toBe(true);\n expect(cache.has(\"succeeded-step\")).toBe(true);\n expect(cache.has(\"running-step\")).toBe(false);\n expect(cache.has(\"failed-step\")).toBe(false);\n });\n\n test(\"uses step name as cache key\", () => {\n const attempt = createMockStepAttempt({\n stepName: \"my-unique-step-name\",\n status: \"completed\",\n });\n const cache = createStepAttemptCacheFromAttempts([attempt]);\n\n expect(cache.get(\"my-unique-step-name\")).toBe(attempt);\n expect(cache.get(\"other-name\")).toBeUndefined();\n });\n});\n\ndescribe(\"getCachedStepAttempt\", () => {\n test(\"returns cached attempt when present\", () => {\n const attempt = createMockStepAttempt({ stepName: \"cached-step\" });\n const cache: StepAttemptCache = new Map([[\"cached-step\", attempt]]);\n\n const result = getCachedStepAttempt(cache, \"cached-step\");\n\n expect(result).toBe(attempt);\n });\n\n test(\"returns undefined when step not in cache\", () => {\n const cache: StepAttemptCache = new Map();\n\n const result = getCachedStepAttempt(cache, \"missing-step\");\n\n expect(result).toBeUndefined();\n });\n\n test(\"returns undefined for similar but different step names\", () => {\n const attempt = createMockStepAttempt({ stepName: \"step-1\" });\n const cache: StepAttemptCache = new Map([[\"step-1\", attempt]]);\n\n expect(getCachedStepAttempt(cache, \"step-2\")).toBeUndefined();\n expect(getCachedStepAttempt(cache, \"Step-1\")).toBeUndefined();\n expect(getCachedStepAttempt(cache, \"step-1 \")).toBeUndefined();\n });\n});\n\ndescribe(\"hasCompletedStep\", () => {\n test(\"returns true when step is in cache\", () => {\n const attempt = createMockStepAttempt({ stepName: \"step-x\" });\n const cache: StepAttemptCache = new Map([[\"step-x\", attempt]]);\n\n expect(hasCompletedStep(cache, \"step-x\")).toBe(true);\n });\n\n test(\"returns false when step is not in cache\", () => {\n const cache: StepAttemptCache = new Map();\n\n expect(hasCompletedStep(cache, \"step-y\")).toBe(false);\n });\n\n test(\"returns false for empty cache\", () => {\n const cache: StepAttemptCache = new Map();\n\n expect(hasCompletedStep(cache, \"any-step\")).toBe(false);\n });\n});\n\ndescribe(\"addToStepAttemptCache\", () => {\n test(\"adds attempt to empty cache\", () => {\n const cache: StepAttemptCache = new Map();\n const attempt = createMockStepAttempt({ stepName: \"new-step\" });\n\n const newCache = addToStepAttemptCache(cache, attempt);\n\n expect(newCache.size).toBe(1);\n expect(newCache.get(\"new-step\")).toBe(attempt);\n });\n\n test(\"adds attempt to existing cache\", () => {\n const existing = createMockStepAttempt({ stepName: \"existing-step\" });\n const cache: StepAttemptCache = new Map([[\"existing-step\", existing]]);\n const newAttempt = createMockStepAttempt({ stepName: \"new-step\" });\n\n const newCache = addToStepAttemptCache(cache, newAttempt);\n\n expect(newCache.size).toBe(2);\n expect(newCache.get(\"existing-step\")).toBe(existing);\n expect(newCache.get(\"new-step\")).toBe(newAttempt);\n });\n\n test(\"does not mutate original cache (immutable)\", () => {\n const existing = createMockStepAttempt({ stepName: \"existing-step\" });\n const cache: StepAttemptCache = new Map([[\"existing-step\", existing]]);\n const newAttempt = createMockStepAttempt({ stepName: \"new-step\" });\n\n const newCache = addToStepAttemptCache(cache, newAttempt);\n\n expect(cache.size).toBe(1);\n expect(cache.has(\"new-step\")).toBe(false);\n expect(newCache.size).toBe(2);\n });\n\n test(\"overwrites existing entry with same step name\", () => {\n const original = createMockStepAttempt({\n stepName: \"step\",\n output: \"original\",\n });\n const cache: StepAttemptCache = new Map([[\"step\", original]]);\n const replacement = createMockStepAttempt({\n stepName: \"step\",\n output: \"replacement\",\n });\n\n const newCache = addToStepAttemptCache(cache, replacement);\n\n expect(newCache.size).toBe(1);\n expect(newCache.get(\"step\")?.output).toBe(\"replacement\");\n });\n});\n\ndescribe(\"normalizeStepOutput\", () => {\n test(\"passes through string values\", () => {\n expect(normalizeStepOutput(\"hello\")).toBe(\"hello\");\n });\n\n test(\"passes through number values\", () => {\n expect(normalizeStepOutput(42)).toBe(42);\n expect(normalizeStepOutput(3.14)).toBe(3.14);\n expect(normalizeStepOutput(0)).toBe(0);\n expect(normalizeStepOutput(-1)).toBe(-1);\n });\n\n test(\"passes through boolean values\", () => {\n expect(normalizeStepOutput(true)).toBe(true);\n expect(normalizeStepOutput(false)).toBe(false);\n });\n\n test(\"passes through null\", () => {\n expect(normalizeStepOutput(null)).toBeNull();\n });\n\n test(\"converts undefined to null\", () => {\n // eslint-disable-next-line unicorn/no-useless-undefined\n expect(normalizeStepOutput(undefined)).toBeNull();\n });\n\n test(\"passes through object values\", () => {\n const obj = { foo: \"bar\", nested: { baz: 123 } };\n expect(normalizeStepOutput(obj)).toBe(obj);\n });\n\n test(\"passes through array values\", () => {\n const arr = [1, 2, 3];\n expect(normalizeStepOutput(arr)).toBe(arr);\n });\n\n test(\"passes through empty object\", () => {\n const obj = {};\n expect(normalizeStepOutput(obj)).toBe(obj);\n });\n\n test(\"passes through empty array\", () => {\n const arr: unknown[] = [];\n expect(normalizeStepOutput(arr)).toBe(arr);\n });\n});\n\ndescribe(\"calculateSleepResumeAt\", () => {\n test(\"calculates resume time from duration string\", () => {\n const now = 1_000_000;\n const result = calculateSleepResumeAt(\"5s\", now);\n\n expect(result).toEqual(ok(new Date(now + 5000)));\n });\n\n test(\"calculates resume time with milliseconds\", () => {\n const now = 1_000_000;\n const result = calculateSleepResumeAt(\"500ms\", now);\n\n expect(result).toEqual(ok(new Date(now + 500)));\n });\n\n test(\"calculates resume time with minutes\", () => {\n const now = 1_000_000;\n const result = calculateSleepResumeAt(\"2m\", now);\n\n expect(result).toEqual(ok(new Date(now + 2 * 60 * 1000)));\n });\n\n test(\"calculates resume time with hours\", () => {\n const now = 1_000_000;\n const result = calculateSleepResumeAt(\"1h\", now);\n\n expect(result).toEqual(ok(new Date(now + 60 * 60 * 1000)));\n });\n\n test(\"uses Date.now() when now is not provided\", () => {\n const before = Date.now();\n const result = calculateSleepResumeAt(\"1s\");\n const after = Date.now();\n\n expect(result.ok).toBe(true);\n if (result.ok) {\n const resumeTime = result.value.getTime();\n expect(resumeTime).toBeGreaterThanOrEqual(before + 1000);\n expect(resumeTime).toBeLessThanOrEqual(after + 1000);\n }\n });\n\n test(\"returns error for invalid duration\", () => {\n // @ts-expect-error testing invalid input\n const result = calculateSleepResumeAt(\"invalid\");\n\n expect(result.ok).toBe(false);\n if (!result.ok) {\n expect(result.error).toBeInstanceOf(Error);\n }\n });\n\n test(\"returns error for empty duration\", () => {\n // @ts-expect-error testing invalid input\n const result = calculateSleepResumeAt(\"\");\n\n expect(result.ok).toBe(false);\n });\n});\n\ndescribe(\"createSleepContext\", () => {\n test(\"creates sleep context with ISO string timestamp\", () => {\n const resumeAt = new Date(\"2025-06-15T10:30:00.000Z\");\n const context = createSleepContext(resumeAt);\n\n expect(context).toEqual({\n kind: \"sleep\",\n resumeAt: \"2025-06-15T10:30:00.000Z\",\n });\n });\n\n test(\"preserves millisecond precision\", () => {\n const resumeAt = new Date(\"2025-01-01T00:00:00.123Z\");\n const context = createSleepContext(resumeAt);\n\n expect(context.resumeAt).toBe(\"2025-01-01T00:00:00.123Z\");\n });\n\n test(\"always has kind set to sleep\", () => {\n const resumeAt = new Date();\n const context = createSleepContext(resumeAt);\n\n expect(context.kind).toBe(\"sleep\");\n });\n\n test(\"creates context from current date\", () => {\n const now = new Date();\n const context = createSleepContext(now);\n\n expect(context.resumeAt).toBe(now.toISOString());\n });\n});\n\nfunction createMockStepAttempt(overrides: Partial<StepAttempt> = {}): StepAttempt {\n return {\n namespaceId: \"default\",\n id: \"step-1\",\n workflowRunId: \"workflow-1\",\n stepName: \"test-step\",\n kind: \"function\",\n status: \"completed\",\n config: {},\n context: null,\n output: null,\n error: null,\n childWorkflowRunNamespaceId: null,\n childWorkflowRunId: null,\n startedAt: new Date(\"2025-01-01T00:00:00Z\"),\n finishedAt: new Date(\"2025-01-01T00:00:01Z\"),\n createdAt: new Date(\"2025-01-01T00:00:00Z\"),\n updatedAt: new Date(\"2025-01-01T00:00:01Z\"),\n ...overrides,\n };\n}\n"],"names":["describe","expect","test","ok","addToStepAttemptCache","calculateSleepResumeAt","createSleepContext","createStepAttemptCacheFromAttempts","getCachedStepAttempt","hasCompletedStep","normalizeStepOutput","cache","size","toBe","attempt","createMockStepAttempt","stepName","status","output","get","error","message","attempts","has","toBeUndefined","Map","result","newCache","existing","newAttempt","original","replacement","toBeNull","undefined","obj","foo","nested","baz","arr","now","toEqual","Date","before","after","resumeTime","value","getTime","toBeGreaterThanOrEqual","toBeLessThanOrEqual","toBeInstanceOf","Error","resumeAt","context","kind","toISOString","overrides","namespaceId","id","workflowRunId","config","childWorkflowRunNamespaceId","childWorkflowRunId","startedAt","finishedAt","createdAt","updatedAt"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=workflow.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"workflow.test.d.ts","sourceRoot":"","sources":["../../src/core/workflow.test.ts"],"names":[],"mappings":""}
@@ -1,172 +0,0 @@
1
- import { describe, expect, test } from "vitest";
2
- import { DEFAULT_WORKFLOW_RESULT_CONFIG, isTerminalStatus, validateInput } from "./workflow.js";
3
- describe("validateInput", ()=>{
4
- test("returns success with input when no schema provided (null)", async ()=>{
5
- const input = {
6
- name: "test",
7
- value: 42
8
- };
9
- const result = await validateInput(null, input);
10
- expect(result.success).toBe(true);
11
- if (result.success) {
12
- expect(result.value).toBe(input);
13
- }
14
- });
15
- test("returns success with input when no schema provided (undefined)", async ()=>{
16
- const input = "string input";
17
- const result = await validateInput(undefined, input);
18
- expect(result.success).toBe(true);
19
- if (result.success) {
20
- expect(result.value).toBe(input);
21
- }
22
- });
23
- test("validates input successfully against schema", async ()=>{
24
- const schema = createMockSchema({
25
- validate: (input)=>({
26
- value: input
27
- })
28
- });
29
- const input = {
30
- name: "test"
31
- };
32
- const result = await validateInput(schema, input);
33
- expect(result.success).toBe(true);
34
- if (result.success) {
35
- expect(result.value).toEqual({
36
- name: "test"
37
- });
38
- }
39
- });
40
- test("transforms input using schema", async ()=>{
41
- const schema = createMockSchema({
42
- validate: (input)=>({
43
- value: Number.parseInt(input, 10)
44
- })
45
- });
46
- const result = await validateInput(schema, "42");
47
- expect(result.success).toBe(true);
48
- if (result.success) {
49
- expect(result.value).toBe(42);
50
- }
51
- });
52
- test("returns failure with error message when validation fails", async ()=>{
53
- const schema = createMockSchema({
54
- validate: ()=>({
55
- issues: [
56
- {
57
- message: "Invalid input"
58
- }
59
- ]
60
- })
61
- });
62
- const result = await validateInput(schema, "bad input");
63
- expect(result.success).toBe(false);
64
- if (!result.success) {
65
- expect(result.error).toBe("Invalid input");
66
- }
67
- });
68
- test("combines multiple validation error messages", async ()=>{
69
- const schema = createMockSchema({
70
- validate: ()=>({
71
- issues: [
72
- {
73
- message: "Invalid email format"
74
- },
75
- {
76
- message: "Age must be positive"
77
- }
78
- ]
79
- })
80
- });
81
- const result = await validateInput(schema, {
82
- email: "invalid",
83
- age: -5
84
- });
85
- expect(result.success).toBe(false);
86
- if (!result.success) {
87
- expect(result.error).toBe("Invalid email format; Age must be positive");
88
- }
89
- });
90
- test("returns generic message when issues array is empty", async ()=>{
91
- const schema = createMockSchema({
92
- validate: ()=>({
93
- issues: []
94
- })
95
- });
96
- const result = await validateInput(schema, "test");
97
- expect(result.success).toBe(false);
98
- if (!result.success) {
99
- expect(result.error).toBe("Validation failed");
100
- }
101
- });
102
- test("handles async schema validation", async ()=>{
103
- const schema = createMockSchema({
104
- validate: async (input)=>{
105
- await new Promise((resolve)=>setTimeout(resolve, 1));
106
- return {
107
- value: input.toUpperCase()
108
- };
109
- }
110
- });
111
- const result = await validateInput(schema, "hello");
112
- expect(result.success).toBe(true);
113
- if (result.success) {
114
- expect(result.value).toBe("HELLO");
115
- }
116
- });
117
- test("handles undefined input when no schema", async ()=>{
118
- // eslint-disable-next-line unicorn/no-useless-undefined
119
- const result = await validateInput(null, undefined);
120
- expect(result.success).toBe(true);
121
- if (result.success) {
122
- expect(result.value).toBeUndefined();
123
- }
124
- });
125
- });
126
- describe("isTerminalStatus", ()=>{
127
- test("returns true for 'completed' status", ()=>{
128
- expect(isTerminalStatus("completed")).toBe(true);
129
- });
130
- test("returns true for 'succeeded' status (deprecated)", ()=>{
131
- expect(isTerminalStatus("succeeded")).toBe(true);
132
- });
133
- test("returns true for 'failed' status", ()=>{
134
- expect(isTerminalStatus("failed")).toBe(true);
135
- });
136
- test("returns true for 'canceled' status", ()=>{
137
- expect(isTerminalStatus("canceled")).toBe(true);
138
- });
139
- test("returns false for 'pending' status", ()=>{
140
- expect(isTerminalStatus("pending")).toBe(false);
141
- });
142
- test("returns false for 'running' status", ()=>{
143
- expect(isTerminalStatus("running")).toBe(false);
144
- });
145
- test("returns false for 'sleeping' status", ()=>{
146
- expect(isTerminalStatus("sleeping")).toBe(false);
147
- });
148
- test("returns false for unknown status strings", ()=>{
149
- expect(isTerminalStatus("unknown")).toBe(false);
150
- expect(isTerminalStatus("")).toBe(false);
151
- expect(isTerminalStatus("COMPLETED")).toBe(false);
152
- });
153
- });
154
- describe("DEFAULT_WORKFLOW_RESULT_CONFIG", ()=>{
155
- test("has expected poll interval", ()=>{
156
- expect(DEFAULT_WORKFLOW_RESULT_CONFIG.pollIntervalMs).toBe(1000);
157
- });
158
- test("has expected timeout (5 minutes)", ()=>{
159
- expect(DEFAULT_WORKFLOW_RESULT_CONFIG.timeoutMs).toBe(5 * 60 * 1000);
160
- });
161
- });
162
- function createMockSchema(options) {
163
- return {
164
- "~standard": {
165
- version: 1,
166
- vendor: "test",
167
- validate: options.validate
168
- }
169
- };
170
- }
171
-
172
- //# sourceMappingURL=workflow.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/core/workflow.test.ts"],"sourcesContent":["import { describe, expect, test } from \"vitest\";\nimport type { StandardSchemaV1 } from \"./schema\";\nimport { DEFAULT_WORKFLOW_RESULT_CONFIG, isTerminalStatus, validateInput } from \"./workflow\";\n\ndescribe(\"validateInput\", () => {\n test(\"returns success with input when no schema provided (null)\", async () => {\n const input = { name: \"test\", value: 42 };\n const result = await validateInput(null, input);\n\n expect(result.success).toBe(true);\n if (result.success) {\n expect(result.value).toBe(input);\n }\n });\n\n test(\"returns success with input when no schema provided (undefined)\", async () => {\n const input = \"string input\";\n const result = await validateInput(undefined, input);\n\n expect(result.success).toBe(true);\n if (result.success) {\n expect(result.value).toBe(input);\n }\n });\n\n test(\"validates input successfully against schema\", async () => {\n const schema = createMockSchema<{ name: string }>({\n validate: (input) => ({ value: input as { name: string } }),\n });\n const input = { name: \"test\" };\n\n const result = await validateInput(schema, input);\n\n expect(result.success).toBe(true);\n if (result.success) {\n expect(result.value).toEqual({ name: \"test\" });\n }\n });\n\n test(\"transforms input using schema\", async () => {\n const schema = createMockSchema<string, number>({\n validate: (input) => ({ value: Number.parseInt(input as string, 10) }),\n });\n\n const result = await validateInput(schema, \"42\");\n\n expect(result.success).toBe(true);\n if (result.success) {\n expect(result.value).toBe(42);\n }\n });\n\n test(\"returns failure with error message when validation fails\", async () => {\n const schema = createMockSchema<string>({\n validate: () => ({\n issues: [{ message: \"Invalid input\" }],\n }),\n });\n\n const result = await validateInput(schema, \"bad input\");\n\n expect(result.success).toBe(false);\n if (!result.success) {\n expect(result.error).toBe(\"Invalid input\");\n }\n });\n\n test(\"combines multiple validation error messages\", async () => {\n const schema = createMockSchema<{ email: string; age: number }>({\n validate: () => ({\n issues: [{ message: \"Invalid email format\" }, { message: \"Age must be positive\" }],\n }),\n });\n\n const result = await validateInput(schema, {\n email: \"invalid\",\n age: -5,\n });\n\n expect(result.success).toBe(false);\n if (!result.success) {\n expect(result.error).toBe(\"Invalid email format; Age must be positive\");\n }\n });\n\n test(\"returns generic message when issues array is empty\", async () => {\n const schema = createMockSchema<string>({\n validate: () => ({\n issues: [],\n }),\n });\n\n const result = await validateInput(schema, \"test\");\n\n expect(result.success).toBe(false);\n if (!result.success) {\n expect(result.error).toBe(\"Validation failed\");\n }\n });\n\n test(\"handles async schema validation\", async () => {\n const schema = createMockSchema<string>({\n validate: async (input) => {\n await new Promise((resolve) => setTimeout(resolve, 1));\n return { value: (input as string).toUpperCase() };\n },\n });\n\n const result = await validateInput(schema, \"hello\");\n\n expect(result.success).toBe(true);\n if (result.success) {\n expect(result.value).toBe(\"HELLO\");\n }\n });\n\n test(\"handles undefined input when no schema\", async () => {\n // eslint-disable-next-line unicorn/no-useless-undefined\n const result = await validateInput(null, undefined);\n\n expect(result.success).toBe(true);\n if (result.success) {\n expect(result.value).toBeUndefined();\n }\n });\n});\n\ndescribe(\"isTerminalStatus\", () => {\n test(\"returns true for 'completed' status\", () => {\n expect(isTerminalStatus(\"completed\")).toBe(true);\n });\n\n test(\"returns true for 'succeeded' status (deprecated)\", () => {\n expect(isTerminalStatus(\"succeeded\")).toBe(true);\n });\n\n test(\"returns true for 'failed' status\", () => {\n expect(isTerminalStatus(\"failed\")).toBe(true);\n });\n\n test(\"returns true for 'canceled' status\", () => {\n expect(isTerminalStatus(\"canceled\")).toBe(true);\n });\n\n test(\"returns false for 'pending' status\", () => {\n expect(isTerminalStatus(\"pending\")).toBe(false);\n });\n\n test(\"returns false for 'running' status\", () => {\n expect(isTerminalStatus(\"running\")).toBe(false);\n });\n\n test(\"returns false for 'sleeping' status\", () => {\n expect(isTerminalStatus(\"sleeping\")).toBe(false);\n });\n\n test(\"returns false for unknown status strings\", () => {\n expect(isTerminalStatus(\"unknown\")).toBe(false);\n expect(isTerminalStatus(\"\")).toBe(false);\n expect(isTerminalStatus(\"COMPLETED\")).toBe(false);\n });\n});\n\ndescribe(\"DEFAULT_WORKFLOW_RESULT_CONFIG\", () => {\n test(\"has expected poll interval\", () => {\n expect(DEFAULT_WORKFLOW_RESULT_CONFIG.pollIntervalMs).toBe(1000);\n });\n\n test(\"has expected timeout (5 minutes)\", () => {\n expect(DEFAULT_WORKFLOW_RESULT_CONFIG.timeoutMs).toBe(5 * 60 * 1000);\n });\n});\n\nfunction createMockSchema<I, O = I>(options: {\n validate: (input: unknown) => StandardSchemaV1.Result<O> | Promise<StandardSchemaV1.Result<O>>;\n}): StandardSchemaV1<I, O> {\n return {\n \"~standard\": {\n version: 1,\n vendor: \"test\",\n validate: options.validate,\n },\n };\n}\n"],"names":["describe","expect","test","DEFAULT_WORKFLOW_RESULT_CONFIG","isTerminalStatus","validateInput","input","name","value","result","success","toBe","undefined","schema","createMockSchema","validate","toEqual","Number","parseInt","issues","message","error","email","age","Promise","resolve","setTimeout","toUpperCase","toBeUndefined","pollIntervalMs","timeoutMs","options","version","vendor"],"mappings":"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"}