effect-app 4.0.0-beta.25 → 4.0.0-beta.251

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 (365) hide show
  1. package/CHANGELOG.md +1137 -0
  2. package/dist/Array.d.ts +3 -2
  3. package/dist/Array.d.ts.map +1 -1
  4. package/dist/Array.js +4 -4
  5. package/dist/Chunk.d.ts +1 -1
  6. package/dist/Chunk.d.ts.map +1 -1
  7. package/dist/Config/SecretURL.d.ts +4 -2
  8. package/dist/Config/SecretURL.d.ts.map +1 -1
  9. package/dist/Config/SecretURL.js +3 -6
  10. package/dist/Config/internal/configSecretURL.d.ts +1 -1
  11. package/dist/Config/internal/configSecretURL.d.ts.map +1 -1
  12. package/dist/Config/internal/configSecretURL.js +2 -2
  13. package/dist/Config.d.ts +7 -0
  14. package/dist/Config.d.ts.map +1 -0
  15. package/dist/Config.js +6 -0
  16. package/dist/ConfigProvider.d.ts +39 -0
  17. package/dist/ConfigProvider.d.ts.map +1 -0
  18. package/dist/ConfigProvider.js +42 -0
  19. package/dist/Context.d.ts +42 -0
  20. package/dist/Context.d.ts.map +1 -0
  21. package/dist/Context.js +67 -0
  22. package/dist/Effect.d.ts +13 -12
  23. package/dist/Effect.d.ts.map +1 -1
  24. package/dist/Effect.js +5 -8
  25. package/dist/Emailer.d.ts +51 -0
  26. package/dist/Emailer.d.ts.map +1 -0
  27. package/dist/Emailer.js +7 -0
  28. package/dist/Function.d.ts +1 -1
  29. package/dist/Function.d.ts.map +1 -1
  30. package/dist/Inputify.type.d.ts +1 -1
  31. package/dist/Layer.d.ts +11 -7
  32. package/dist/Layer.d.ts.map +1 -1
  33. package/dist/Layer.js +3 -2
  34. package/dist/Model/Repository/Registry.d.ts +21 -0
  35. package/dist/Model/Repository/Registry.d.ts.map +1 -0
  36. package/dist/Model/Repository/Registry.js +18 -0
  37. package/dist/Model/Repository/ext.d.ts +60 -0
  38. package/dist/Model/Repository/ext.d.ts.map +1 -0
  39. package/dist/Model/Repository/ext.js +122 -0
  40. package/dist/Model/Repository/internal/internal.d.ts +62 -0
  41. package/dist/Model/Repository/internal/internal.d.ts.map +1 -0
  42. package/dist/Model/Repository/internal/internal.js +397 -0
  43. package/dist/Model/Repository/legacy.d.ts +21 -0
  44. package/dist/Model/Repository/legacy.d.ts.map +1 -0
  45. package/dist/Model/Repository/legacy.js +2 -0
  46. package/dist/Model/Repository/makeRepo.d.ts +53 -0
  47. package/dist/Model/Repository/makeRepo.d.ts.map +1 -0
  48. package/dist/Model/Repository/makeRepo.js +27 -0
  49. package/dist/Model/Repository/service.d.ts +97 -0
  50. package/dist/Model/Repository/service.d.ts.map +1 -0
  51. package/dist/Model/Repository/service.js +2 -0
  52. package/dist/Model/Repository/validation.d.ts +71 -0
  53. package/dist/Model/Repository/validation.d.ts.map +1 -0
  54. package/dist/Model/Repository/validation.js +32 -0
  55. package/dist/Model/Repository.d.ts +7 -0
  56. package/dist/Model/Repository.d.ts.map +1 -0
  57. package/dist/Model/Repository.js +7 -0
  58. package/dist/Model/dsl.d.ts +33 -0
  59. package/dist/Model/dsl.d.ts.map +1 -0
  60. package/dist/Model/dsl.js +43 -0
  61. package/dist/Model/filter/filterApi.d.ts +30 -0
  62. package/dist/Model/filter/filterApi.d.ts.map +1 -0
  63. package/dist/Model/filter/filterApi.js +2 -0
  64. package/dist/Model/filter/types/errors.d.ts +29 -0
  65. package/dist/Model/filter/types/errors.d.ts.map +1 -0
  66. package/dist/Model/filter/types/errors.js +2 -0
  67. package/dist/Model/filter/types/fields.d.ts +15 -0
  68. package/dist/Model/filter/types/fields.d.ts.map +1 -0
  69. package/dist/Model/filter/types/fields.js +2 -0
  70. package/dist/Model/filter/types/path/common.d.ts +316 -0
  71. package/dist/Model/filter/types/path/common.d.ts.map +1 -0
  72. package/dist/Model/filter/types/path/common.js +2 -0
  73. package/dist/Model/filter/types/path/eager.d.ts +95 -0
  74. package/dist/Model/filter/types/path/eager.d.ts.map +1 -0
  75. package/dist/Model/filter/types/path/eager.js +31 -0
  76. package/dist/Model/filter/types/path/index.d.ts +4 -0
  77. package/dist/Model/filter/types/path/index.d.ts.map +1 -0
  78. package/dist/Model/filter/types/path/index.js +3 -0
  79. package/dist/Model/filter/types/utils.d.ts +79 -0
  80. package/dist/Model/filter/types/utils.d.ts.map +1 -0
  81. package/dist/Model/filter/types/utils.js +2 -0
  82. package/dist/Model/filter/types/validator.d.ts +30 -0
  83. package/dist/Model/filter/types/validator.d.ts.map +1 -0
  84. package/dist/Model/filter/types/validator.js +2 -0
  85. package/dist/Model/filter/types.d.ts +5 -0
  86. package/dist/Model/filter/types.d.ts.map +1 -0
  87. package/dist/Model/filter/types.js +7 -0
  88. package/dist/Model/query/dsl.d.ts +446 -0
  89. package/dist/Model/query/dsl.d.ts.map +1 -0
  90. package/dist/Model/query/dsl.js +342 -0
  91. package/dist/Model/query/new-kid-interpreter.d.ts +136 -0
  92. package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -0
  93. package/dist/Model/query/new-kid-interpreter.js +336 -0
  94. package/dist/Model/query.d.ts +15 -0
  95. package/dist/Model/query.d.ts.map +1 -0
  96. package/dist/Model/query.js +3 -0
  97. package/dist/Model.d.ts +5 -0
  98. package/dist/Model.d.ts.map +1 -0
  99. package/dist/Model.js +5 -0
  100. package/dist/NonEmptySet.d.ts +4 -2
  101. package/dist/NonEmptySet.d.ts.map +1 -1
  102. package/dist/NonEmptySet.js +2 -2
  103. package/dist/Option.d.ts +2 -1
  104. package/dist/Option.d.ts.map +1 -1
  105. package/dist/Option.js +3 -1
  106. package/dist/Pure.d.ts +8 -6
  107. package/dist/Pure.d.ts.map +1 -1
  108. package/dist/Pure.js +17 -14
  109. package/dist/QueueMaker.d.ts +13 -0
  110. package/dist/QueueMaker.d.ts.map +1 -0
  111. package/dist/QueueMaker.js +4 -0
  112. package/dist/RequestContext.d.ts +103 -0
  113. package/dist/RequestContext.d.ts.map +1 -0
  114. package/dist/RequestContext.js +49 -0
  115. package/dist/Schema/Class.d.ts +66 -20
  116. package/dist/Schema/Class.d.ts.map +1 -1
  117. package/dist/Schema/Class.js +192 -23
  118. package/dist/Schema/FastCheck.d.ts +1 -1
  119. package/dist/Schema/FastCheck.d.ts.map +1 -1
  120. package/dist/Schema/Methods.d.ts +1 -1
  121. package/dist/Schema/SchemaParser.d.ts +5 -0
  122. package/dist/Schema/SchemaParser.d.ts.map +1 -0
  123. package/dist/Schema/SchemaParser.js +6 -0
  124. package/dist/Schema/SpecialJsonSchema.d.ts +34 -0
  125. package/dist/Schema/SpecialJsonSchema.d.ts.map +1 -0
  126. package/dist/Schema/SpecialJsonSchema.js +118 -0
  127. package/dist/Schema/SpecialOpenApi.d.ts +32 -0
  128. package/dist/Schema/SpecialOpenApi.d.ts.map +1 -0
  129. package/dist/Schema/SpecialOpenApi.js +123 -0
  130. package/dist/Schema/brand.d.ts +5 -3
  131. package/dist/Schema/brand.d.ts.map +1 -1
  132. package/dist/Schema/brand.js +3 -1
  133. package/dist/Schema/email.d.ts +1 -1
  134. package/dist/Schema/email.d.ts.map +1 -1
  135. package/dist/Schema/email.js +7 -4
  136. package/dist/Schema/ext.d.ts +339 -56
  137. package/dist/Schema/ext.d.ts.map +1 -1
  138. package/dist/Schema/ext.js +358 -53
  139. package/dist/Schema/moreStrings.d.ts +108 -26
  140. package/dist/Schema/moreStrings.d.ts.map +1 -1
  141. package/dist/Schema/moreStrings.js +45 -16
  142. package/dist/Schema/numbers.d.ts +55 -15
  143. package/dist/Schema/numbers.d.ts.map +1 -1
  144. package/dist/Schema/numbers.js +60 -12
  145. package/dist/Schema/phoneNumber.d.ts +1 -1
  146. package/dist/Schema/phoneNumber.d.ts.map +1 -1
  147. package/dist/Schema/phoneNumber.js +6 -3
  148. package/dist/Schema/schema.d.ts +1 -1
  149. package/dist/Schema/strings.d.ts +5 -5
  150. package/dist/Schema/strings.d.ts.map +1 -1
  151. package/dist/Schema/strings.js +1 -5
  152. package/dist/Schema.d.ts +214 -8
  153. package/dist/Schema.d.ts.map +1 -1
  154. package/dist/Schema.js +190 -11
  155. package/dist/Set.d.ts +5 -2
  156. package/dist/Set.d.ts.map +1 -1
  157. package/dist/Set.js +3 -2
  158. package/dist/Store.d.ts +170 -0
  159. package/dist/Store.d.ts.map +1 -0
  160. package/dist/Store.js +121 -0
  161. package/dist/TypeTest.d.ts +1 -1
  162. package/dist/Types.d.ts +1 -1
  163. package/dist/Widen.type.d.ts +1 -1
  164. package/dist/_ext/Array.d.ts +2 -2
  165. package/dist/_ext/Array.d.ts.map +1 -1
  166. package/dist/_ext/Array.js +4 -2
  167. package/dist/_ext/date.d.ts +1 -1
  168. package/dist/_ext/misc.d.ts +5 -2
  169. package/dist/_ext/misc.d.ts.map +1 -1
  170. package/dist/_ext/misc.js +4 -2
  171. package/dist/_ext/ord.ext.d.ts +3 -2
  172. package/dist/_ext/ord.ext.d.ts.map +1 -1
  173. package/dist/_ext/ord.ext.js +2 -2
  174. package/dist/builtin.d.ts +1 -1
  175. package/dist/builtin.d.ts.map +1 -1
  176. package/dist/client/InvalidationKeys.d.ts +29 -0
  177. package/dist/client/InvalidationKeys.d.ts.map +1 -0
  178. package/dist/client/InvalidationKeys.js +33 -0
  179. package/dist/client/apiClientFactory.d.ts +20 -32
  180. package/dist/client/apiClientFactory.d.ts.map +1 -1
  181. package/dist/client/apiClientFactory.js +104 -34
  182. package/dist/client/clientFor.d.ts +53 -19
  183. package/dist/client/clientFor.d.ts.map +1 -1
  184. package/dist/client/clientFor.js +9 -1
  185. package/dist/client/errors.d.ts +49 -25
  186. package/dist/client/errors.d.ts.map +1 -1
  187. package/dist/client/errors.js +43 -17
  188. package/dist/client/makeClient.d.ts +495 -33
  189. package/dist/client/makeClient.d.ts.map +1 -1
  190. package/dist/client/makeClient.js +66 -24
  191. package/dist/client.d.ts +6 -5
  192. package/dist/client.d.ts.map +1 -1
  193. package/dist/client.js +2 -1
  194. package/dist/faker.d.ts +1 -1
  195. package/dist/faker.d.ts.map +1 -1
  196. package/dist/http/Request.d.ts +2 -2
  197. package/dist/http/Request.d.ts.map +1 -1
  198. package/dist/http/Request.js +2 -2
  199. package/dist/http/internal/lib.d.ts +1 -1
  200. package/dist/http.d.ts +1 -1
  201. package/dist/ids.d.ts +40 -12
  202. package/dist/ids.d.ts.map +1 -1
  203. package/dist/ids.js +25 -3
  204. package/dist/index.d.ts +7 -8
  205. package/dist/index.d.ts.map +1 -1
  206. package/dist/index.js +8 -8
  207. package/dist/logger.d.ts +1 -1
  208. package/dist/middleware.d.ts +14 -8
  209. package/dist/middleware.d.ts.map +1 -1
  210. package/dist/middleware.js +14 -8
  211. package/dist/rpc/Invalidation.d.ts +420 -0
  212. package/dist/rpc/Invalidation.d.ts.map +1 -0
  213. package/dist/rpc/Invalidation.js +168 -0
  214. package/dist/rpc/MiddlewareMaker.d.ts +12 -8
  215. package/dist/rpc/MiddlewareMaker.d.ts.map +1 -1
  216. package/dist/rpc/MiddlewareMaker.js +59 -38
  217. package/dist/rpc/RpcContextMap.d.ts +4 -4
  218. package/dist/rpc/RpcContextMap.d.ts.map +1 -1
  219. package/dist/rpc/RpcContextMap.js +4 -4
  220. package/dist/rpc/RpcMiddleware.d.ts +15 -11
  221. package/dist/rpc/RpcMiddleware.d.ts.map +1 -1
  222. package/dist/rpc/RpcMiddleware.js +1 -1
  223. package/dist/rpc.d.ts +2 -2
  224. package/dist/rpc.d.ts.map +1 -1
  225. package/dist/rpc.js +2 -2
  226. package/dist/runtime.d.ts +19 -0
  227. package/dist/runtime.d.ts.map +1 -0
  228. package/dist/runtime.js +40 -0
  229. package/dist/setupRequest.d.ts +19 -0
  230. package/dist/setupRequest.d.ts.map +1 -0
  231. package/dist/setupRequest.js +69 -0
  232. package/dist/toast.d.ts +51 -0
  233. package/dist/toast.d.ts.map +1 -0
  234. package/dist/toast.js +34 -0
  235. package/dist/transform.d.ts +2 -2
  236. package/dist/transform.d.ts.map +1 -1
  237. package/dist/transform.js +4 -5
  238. package/dist/utils/effectify.d.ts +2 -2
  239. package/dist/utils/effectify.d.ts.map +1 -1
  240. package/dist/utils/effectify.js +2 -2
  241. package/dist/utils/extend.d.ts +1 -1
  242. package/dist/utils/extend.d.ts.map +1 -1
  243. package/dist/utils/gen.d.ts +5 -5
  244. package/dist/utils/gen.d.ts.map +1 -1
  245. package/dist/utils/logLevel.d.ts +3 -3
  246. package/dist/utils/logLevel.d.ts.map +1 -1
  247. package/dist/utils/logger.d.ts +5 -4
  248. package/dist/utils/logger.d.ts.map +1 -1
  249. package/dist/utils/logger.js +4 -4
  250. package/dist/utils.d.ts +40 -45
  251. package/dist/utils.d.ts.map +1 -1
  252. package/dist/utils.js +19 -27
  253. package/dist/validation/validators.d.ts +1 -1
  254. package/dist/validation/validators.d.ts.map +1 -1
  255. package/dist/validation.d.ts +1 -1
  256. package/dist/validation.d.ts.map +1 -1
  257. package/dist/withToast.d.ts +30 -0
  258. package/dist/withToast.d.ts.map +1 -0
  259. package/dist/withToast.js +64 -0
  260. package/package.json +162 -24
  261. package/src/Array.ts +3 -3
  262. package/src/Config/SecretURL.ts +5 -2
  263. package/src/Config/internal/configSecretURL.ts +1 -1
  264. package/src/Config.ts +14 -0
  265. package/src/ConfigProvider.ts +48 -0
  266. package/src/{ServiceMap.ts → Context.ts} +56 -63
  267. package/src/Effect.ts +12 -14
  268. package/src/Emailer.ts +51 -0
  269. package/src/Layer.ts +10 -6
  270. package/src/Model/Repository/Registry.ts +34 -0
  271. package/src/Model/Repository/ext.ts +375 -0
  272. package/src/Model/Repository/internal/internal.ts +691 -0
  273. package/src/Model/Repository/legacy.ts +29 -0
  274. package/src/Model/Repository/makeRepo.ts +144 -0
  275. package/src/Model/Repository/service.ts +639 -0
  276. package/src/Model/Repository/validation.ts +31 -0
  277. package/src/Model/Repository.ts +6 -0
  278. package/src/Model/dsl.ts +129 -0
  279. package/src/Model/filter/filterApi.ts +60 -0
  280. package/src/Model/filter/types/errors.ts +47 -0
  281. package/src/Model/filter/types/fields.ts +50 -0
  282. package/src/Model/filter/types/path/common.ts +404 -0
  283. package/src/Model/filter/types/path/eager.ts +297 -0
  284. package/src/Model/filter/types/path/index.ts +4 -0
  285. package/src/Model/filter/types/utils.ts +128 -0
  286. package/src/Model/filter/types/validator.ts +46 -0
  287. package/src/Model/filter/types.ts +6 -0
  288. package/src/Model/query/dsl.ts +2546 -0
  289. package/src/Model/query/new-kid-interpreter.ts +484 -0
  290. package/src/Model/query.ts +13 -0
  291. package/src/Model.ts +4 -0
  292. package/src/NonEmptySet.ts +3 -1
  293. package/src/Option.ts +2 -0
  294. package/src/Pure.ts +21 -19
  295. package/src/QueueMaker.ts +19 -0
  296. package/src/RequestContext.ts +62 -0
  297. package/src/Schema/Class.ts +274 -64
  298. package/src/Schema/SchemaParser.ts +12 -0
  299. package/src/Schema/SpecialJsonSchema.ts +139 -0
  300. package/src/Schema/SpecialOpenApi.ts +130 -0
  301. package/src/Schema/brand.ts +22 -2
  302. package/src/Schema/email.ts +7 -2
  303. package/src/Schema/ext.ts +443 -88
  304. package/src/Schema/moreStrings.ts +93 -37
  305. package/src/Schema/numbers.ts +64 -16
  306. package/src/Schema/phoneNumber.ts +5 -1
  307. package/src/Schema/strings.ts +4 -8
  308. package/src/Schema.ts +374 -10
  309. package/src/Set.ts +5 -1
  310. package/src/Store.ts +277 -0
  311. package/src/_ext/Array.ts +3 -1
  312. package/src/_ext/misc.ts +4 -1
  313. package/src/_ext/ord.ext.ts +2 -1
  314. package/src/client/InvalidationKeys.ts +50 -0
  315. package/src/client/apiClientFactory.ts +230 -131
  316. package/src/client/clientFor.ts +102 -31
  317. package/src/client/errors.ts +52 -26
  318. package/src/client/makeClient.ts +592 -71
  319. package/src/client.ts +5 -4
  320. package/src/http/Request.ts +1 -1
  321. package/src/ids.ts +25 -3
  322. package/src/index.ts +7 -10
  323. package/src/middleware.ts +13 -9
  324. package/src/rpc/Invalidation.ts +261 -0
  325. package/src/rpc/MiddlewareMaker.ts +83 -75
  326. package/src/rpc/README.md +2 -2
  327. package/src/rpc/RpcContextMap.ts +6 -5
  328. package/src/rpc/RpcMiddleware.ts +18 -12
  329. package/src/rpc.ts +1 -1
  330. package/src/runtime.ts +56 -0
  331. package/src/setupRequest.ts +134 -0
  332. package/src/toast.ts +54 -0
  333. package/src/transform.ts +3 -3
  334. package/src/utils/effectify.ts +1 -1
  335. package/src/utils/gen.ts +8 -8
  336. package/src/utils/logLevel.ts +1 -1
  337. package/src/utils/logger.ts +4 -3
  338. package/src/utils.ts +62 -139
  339. package/src/withToast.ts +133 -0
  340. package/test/dist/rpc-dynamic-middleware.test.d.ts.map +1 -0
  341. package/test/dist/rpc.test.d.ts.map +1 -1
  342. package/test/dist/secretURL.test.d.ts.map +1 -0
  343. package/test/dist/special.test.d.ts.map +1 -0
  344. package/test/dist/stream-error.types.d.ts +2 -0
  345. package/test/dist/stream-error.types.d.ts.map +1 -0
  346. package/test/dist/stream-error.types.js +27 -0
  347. package/test/moreStrings.test.ts +1 -1
  348. package/test/rpc.test.ts +46 -6
  349. package/test/schema.test.ts +459 -30
  350. package/test/secretURL.test.ts +160 -0
  351. package/test/special.test.ts +1026 -0
  352. package/test/utils.test.ts +7 -7
  353. package/tsconfig.base.json +6 -5
  354. package/tsconfig.json +2 -1
  355. package/tsconfig.json.bak +2 -2
  356. package/tsconfig.src.json +29 -29
  357. package/tsconfig.test.json +2 -2
  358. package/dist/Operations.d.ts +0 -123
  359. package/dist/Operations.d.ts.map +0 -1
  360. package/dist/Operations.js +0 -29
  361. package/dist/ServiceMap.d.ts +0 -44
  362. package/dist/ServiceMap.d.ts.map +0 -1
  363. package/dist/ServiceMap.js +0 -91
  364. package/eslint.config.mjs +0 -26
  365. package/src/Operations.ts +0 -55
@@ -0,0 +1,160 @@
1
+ import * as Chunk from "effect/Chunk"
2
+ import * as Config from "effect/Config"
3
+ import * as ConfigProvider from "effect/ConfigProvider"
4
+ import * as Effect from "effect/Effect"
5
+ import { describe, expect, test } from "vitest"
6
+ import { fromChunk, fromString, isSecretURL, make, secretURL, unsafeWipe, value } from "../src/Config/SecretURL.js"
7
+
8
+ const testUrls = [
9
+ "https://example.com/path?key=secret123",
10
+ "http://user:password@host.com:8080/resource",
11
+ "postgres://admin:p4ssw0rd@db.internal:5432/mydb",
12
+ "redis://default:token@cache.example.com:6379",
13
+ "mongodb+srv://user:pass@cluster.mongodb.net/db",
14
+ "https://api.example.com/v2/endpoint?token=abc&format=json"
15
+ ]
16
+
17
+ describe("SecretURL", () => {
18
+ describe("fromString / value roundtrip", () => {
19
+ test.each(testUrls)("preserves %s", (url) => {
20
+ const secret = fromString(url)
21
+ expect(value(secret)).toBe(url)
22
+ })
23
+ })
24
+
25
+ describe("make / value roundtrip", () => {
26
+ test.each(testUrls)("preserves %s via byte array", (url) => {
27
+ const bytes = url.split("").map((c) => c.charCodeAt(0))
28
+ const secret = make(bytes)
29
+ expect(value(secret)).toBe(url)
30
+ })
31
+ })
32
+
33
+ describe("fromChunk / value roundtrip", () => {
34
+ test.each(testUrls)("preserves %s via Chunk", (url) => {
35
+ const chunk = Chunk.fromIterable(url.split(""))
36
+ const secret = fromChunk(chunk)
37
+ expect(value(secret)).toBe(url)
38
+ })
39
+ })
40
+
41
+ describe("toString", () => {
42
+ test("redacts the URL, showing only protocol", () => {
43
+ const secret = fromString("https://example.com/secret")
44
+ expect(String(secret)).toBe("SecretURL(https://<redacted>)")
45
+ })
46
+
47
+ test("shows http protocol", () => {
48
+ const secret = fromString("http://example.com")
49
+ expect(String(secret)).toBe("SecretURL(http://<redacted>)")
50
+ })
51
+
52
+ test("shows unknown for non-URL strings", () => {
53
+ const secret = fromString("not-a-url")
54
+ expect(String(secret)).toBe("SecretURL(unknown://<redacted>)")
55
+ })
56
+ })
57
+
58
+ describe("toJSON", () => {
59
+ test("returns tag and protocol only", () => {
60
+ const secret = fromString("https://example.com/secret")
61
+ expect(JSON.parse(JSON.stringify(secret))).toEqual({ _tag: "SecretURL", protocol: "https" })
62
+ })
63
+
64
+ test("returns unknown protocol for non-URL", () => {
65
+ const secret = fromString("not-a-url")
66
+ expect(JSON.parse(JSON.stringify(secret))).toEqual({ _tag: "SecretURL", protocol: "unknown" })
67
+ })
68
+ })
69
+
70
+ describe("isSecretURL", () => {
71
+ test("returns true for SecretURL", () => {
72
+ const secret = fromString("https://example.com")
73
+ expect(isSecretURL(secret)).toBe(true)
74
+ })
75
+
76
+ test("returns false for plain string", () => {
77
+ expect(isSecretURL("https://example.com")).toBe(false)
78
+ })
79
+
80
+ test("returns false for plain object", () => {
81
+ expect(isSecretURL({ raw: [1, 2, 3] })).toBe(false)
82
+ })
83
+ })
84
+
85
+ describe("unsafeWipe", () => {
86
+ test("zeroes out raw bytes", () => {
87
+ const secret = fromString("https://example.com")
88
+ unsafeWipe(secret)
89
+ expect(value(secret)).toBe("\0".repeat("https://example.com".length))
90
+ })
91
+ })
92
+
93
+ describe("non-URL strings", () => {
94
+ const nonUrls = [
95
+ "just-a-secret-token",
96
+ "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.abc",
97
+ "sk-1234567890abcdef",
98
+ "some random string with spaces and symbols!@#$%"
99
+ ]
100
+
101
+ test.each(nonUrls)("preserves non-URL value: %s", (input) => {
102
+ const secret = fromString(input)
103
+ expect(value(secret)).toBe(input)
104
+ expect(String(secret)).toBe("SecretURL(unknown://<redacted>)")
105
+ expect(JSON.parse(JSON.stringify(secret))).toEqual({ _tag: "SecretURL", protocol: "unknown" })
106
+ })
107
+ })
108
+
109
+ describe("special characters", () => {
110
+ test("preserves URLs with encoded characters", () => {
111
+ const url = "https://example.com/path?q=hello%20world&name=%C3%A9"
112
+ expect(value(fromString(url))).toBe(url)
113
+ })
114
+
115
+ test("preserves URLs with unicode", () => {
116
+ const url = "https://example.com/café"
117
+ expect(value(fromString(url))).toBe(url)
118
+ })
119
+
120
+ test("preserves URLs with special query params", () => {
121
+ const url = "https://example.com?a=1&b=2&c=foo+bar"
122
+ expect(value(fromString(url))).toBe(url)
123
+ })
124
+ })
125
+
126
+ describe("secretURL config", () => {
127
+ const run = <A>(config: Config.Config<A>, provider: ConfigProvider.ConfigProvider) =>
128
+ Effect.runSync(config.parse(provider))
129
+
130
+ test("reads from env-style ConfigProvider (QUEUE_URL)", () => {
131
+ const url = "https://sqs.us-east-1.amazonaws.com/123456789/my-queue"
132
+ const provider = ConfigProvider.fromEnv({ env: { QUEUE_URL: url } })
133
+ const result = run(secretURL("QUEUE_URL"), provider)
134
+ expect(value(result)).toBe(url)
135
+ expect(String(result)).toBe("SecretURL(https://<redacted>)")
136
+ })
137
+
138
+ test("reads from fromUnknown with nested config ({ queue: { url } })", () => {
139
+ const url = "redis://default:token@cache.example.com:6379"
140
+ const provider = ConfigProvider.fromUnknown({ queue: { url } })
141
+ const config = secretURL("url").pipe(Config.nested("queue"))
142
+ const result = run(config, provider)
143
+ expect(value(result)).toBe(url)
144
+ expect(String(result)).toBe("SecretURL(redis://<redacted>)")
145
+ })
146
+
147
+ test("reads non-URL secret from env", () => {
148
+ const token = "sk-1234567890abcdef"
149
+ const provider = ConfigProvider.fromEnv({ env: { API_KEY: token } })
150
+ const result = run(secretURL("API_KEY"), provider)
151
+ expect(value(result)).toBe(token)
152
+ expect(String(result)).toBe("SecretURL(unknown://<redacted>)")
153
+ })
154
+
155
+ test("rejects empty string", () => {
156
+ const provider = ConfigProvider.fromEnv({ env: { QUEUE_URL: "" } })
157
+ expect(() => run(secretURL("QUEUE_URL"), provider)).toThrow()
158
+ })
159
+ })
160
+ })