effect-app 4.0.0-beta.8 → 4.0.0-beta.82

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 (142) hide show
  1. package/CHANGELOG.md +354 -0
  2. package/dist/Config/SecretURL.js +2 -2
  3. package/dist/Config.d.ts +7 -0
  4. package/dist/Config.d.ts.map +1 -0
  5. package/dist/Config.js +6 -0
  6. package/dist/ConfigProvider.d.ts +39 -0
  7. package/dist/ConfigProvider.d.ts.map +1 -0
  8. package/dist/ConfigProvider.js +42 -0
  9. package/dist/Context.d.ts +40 -0
  10. package/dist/Context.d.ts.map +1 -0
  11. package/dist/Context.js +66 -0
  12. package/dist/Effect.d.ts +8 -7
  13. package/dist/Effect.d.ts.map +1 -1
  14. package/dist/Effect.js +3 -2
  15. package/dist/Layer.d.ts +5 -4
  16. package/dist/Layer.d.ts.map +1 -1
  17. package/dist/Layer.js +1 -1
  18. package/dist/Operations.d.ts +62 -25
  19. package/dist/Operations.d.ts.map +1 -1
  20. package/dist/Pure.d.ts +2 -2
  21. package/dist/Pure.d.ts.map +1 -1
  22. package/dist/Pure.js +13 -13
  23. package/dist/Schema/Class.d.ts +39 -1
  24. package/dist/Schema/Class.d.ts.map +1 -1
  25. package/dist/Schema/Class.js +89 -12
  26. package/dist/Schema/SpecialJsonSchema.d.ts +21 -0
  27. package/dist/Schema/SpecialJsonSchema.d.ts.map +1 -0
  28. package/dist/Schema/SpecialJsonSchema.js +59 -0
  29. package/dist/Schema/SpecialOpenApi.d.ts +32 -0
  30. package/dist/Schema/SpecialOpenApi.d.ts.map +1 -0
  31. package/dist/Schema/SpecialOpenApi.js +123 -0
  32. package/dist/Schema/brand.d.ts +8 -5
  33. package/dist/Schema/brand.d.ts.map +1 -1
  34. package/dist/Schema/brand.js +1 -1
  35. package/dist/Schema/email.d.ts.map +1 -1
  36. package/dist/Schema/email.js +9 -4
  37. package/dist/Schema/ext.d.ts +103 -46
  38. package/dist/Schema/ext.d.ts.map +1 -1
  39. package/dist/Schema/ext.js +110 -51
  40. package/dist/Schema/moreStrings.d.ts +19 -7
  41. package/dist/Schema/moreStrings.d.ts.map +1 -1
  42. package/dist/Schema/moreStrings.js +14 -9
  43. package/dist/Schema/numbers.d.ts +11 -11
  44. package/dist/Schema/numbers.d.ts.map +1 -1
  45. package/dist/Schema/numbers.js +10 -9
  46. package/dist/Schema/phoneNumber.d.ts.map +1 -1
  47. package/dist/Schema/phoneNumber.js +8 -3
  48. package/dist/Schema/strings.d.ts +4 -4
  49. package/dist/Schema/strings.d.ts.map +1 -1
  50. package/dist/Schema.d.ts +22 -55
  51. package/dist/Schema.d.ts.map +1 -1
  52. package/dist/Schema.js +43 -64
  53. package/dist/client/apiClientFactory.d.ts +11 -28
  54. package/dist/client/apiClientFactory.d.ts.map +1 -1
  55. package/dist/client/apiClientFactory.js +18 -19
  56. package/dist/client/clientFor.d.ts +6 -5
  57. package/dist/client/clientFor.d.ts.map +1 -1
  58. package/dist/client/errors.d.ts +18 -9
  59. package/dist/client/errors.d.ts.map +1 -1
  60. package/dist/client/errors.js +35 -10
  61. package/dist/client/makeClient.d.ts +21 -16
  62. package/dist/client/makeClient.d.ts.map +1 -1
  63. package/dist/client/makeClient.js +32 -23
  64. package/dist/http/Request.d.ts.map +1 -1
  65. package/dist/http/Request.js +5 -5
  66. package/dist/ids.d.ts +3 -3
  67. package/dist/ids.d.ts.map +1 -1
  68. package/dist/ids.js +3 -2
  69. package/dist/index.d.ts +3 -8
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +4 -9
  72. package/dist/middleware.d.ts +2 -2
  73. package/dist/middleware.d.ts.map +1 -1
  74. package/dist/middleware.js +3 -3
  75. package/dist/rpc/MiddlewareMaker.d.ts +4 -3
  76. package/dist/rpc/MiddlewareMaker.d.ts.map +1 -1
  77. package/dist/rpc/MiddlewareMaker.js +7 -6
  78. package/dist/rpc/RpcContextMap.d.ts +2 -2
  79. package/dist/rpc/RpcContextMap.d.ts.map +1 -1
  80. package/dist/rpc/RpcContextMap.js +4 -4
  81. package/dist/rpc/RpcMiddleware.d.ts +4 -3
  82. package/dist/rpc/RpcMiddleware.d.ts.map +1 -1
  83. package/dist/rpc/RpcMiddleware.js +1 -1
  84. package/dist/utils/gen.d.ts +1 -1
  85. package/dist/utils/gen.d.ts.map +1 -1
  86. package/dist/utils/logger.d.ts +2 -2
  87. package/dist/utils/logger.d.ts.map +1 -1
  88. package/dist/utils/logger.js +3 -3
  89. package/dist/utils.d.ts +18 -0
  90. package/dist/utils.d.ts.map +1 -1
  91. package/dist/utils.js +24 -5
  92. package/package.json +29 -17
  93. package/src/Config/SecretURL.ts +1 -1
  94. package/src/Config.ts +14 -0
  95. package/src/ConfigProvider.ts +48 -0
  96. package/src/{ServiceMap.ts → Context.ts} +57 -64
  97. package/src/Effect.ts +11 -9
  98. package/src/Layer.ts +5 -4
  99. package/src/Pure.ts +17 -18
  100. package/src/Schema/Class.ts +114 -16
  101. package/src/Schema/SpecialJsonSchema.ts +69 -0
  102. package/src/Schema/SpecialOpenApi.ts +130 -0
  103. package/src/Schema/brand.ts +13 -7
  104. package/src/Schema/email.ts +10 -2
  105. package/src/Schema/ext.ts +185 -82
  106. package/src/Schema/moreStrings.ts +21 -11
  107. package/src/Schema/numbers.ts +9 -8
  108. package/src/Schema/phoneNumber.ts +8 -1
  109. package/src/Schema.ts +79 -103
  110. package/src/client/apiClientFactory.ts +31 -35
  111. package/src/client/clientFor.ts +6 -1
  112. package/src/client/errors.ts +46 -12
  113. package/src/client/makeClient.ts +122 -62
  114. package/src/http/Request.ts +7 -4
  115. package/src/ids.ts +3 -2
  116. package/src/index.ts +3 -11
  117. package/src/middleware.ts +2 -2
  118. package/src/rpc/MiddlewareMaker.ts +8 -7
  119. package/src/rpc/RpcContextMap.ts +6 -5
  120. package/src/rpc/RpcMiddleware.ts +5 -4
  121. package/src/utils/gen.ts +1 -1
  122. package/src/utils/logger.ts +2 -2
  123. package/src/utils.ts +26 -4
  124. package/test/dist/moreStrings.test.d.ts.map +1 -0
  125. package/test/dist/rpc.test.d.ts.map +1 -1
  126. package/test/dist/secretURL.test.d.ts.map +1 -0
  127. package/test/dist/special.test.d.ts.map +1 -0
  128. package/test/moreStrings.test.ts +17 -0
  129. package/test/rpc.test.ts +28 -6
  130. package/test/schema.test.ts +397 -4
  131. package/test/secretURL.test.ts +157 -0
  132. package/test/special.test.ts +732 -0
  133. package/test/utils.test.ts +2 -2
  134. package/tsconfig.base.json +0 -1
  135. package/tsconfig.json +0 -1
  136. package/dist/ServiceMap.d.ts +0 -44
  137. package/dist/ServiceMap.d.ts.map +0 -1
  138. package/dist/ServiceMap.js +0 -91
  139. package/dist/Struct.d.ts +0 -44
  140. package/dist/Struct.d.ts.map +0 -1
  141. package/dist/Struct.js +0 -29
  142. package/src/Struct.ts +0 -54
@@ -0,0 +1,157 @@
1
+ import { Chunk, Config, ConfigProvider, Effect } from "effect"
2
+ import { describe, expect, test } from "vitest"
3
+ import { fromChunk, fromString, isSecretURL, make, secretURL, unsafeWipe, value } from "../src/Config/SecretURL.js"
4
+
5
+ const testUrls = [
6
+ "https://example.com/path?key=secret123",
7
+ "http://user:password@host.com:8080/resource",
8
+ "postgres://admin:p4ssw0rd@db.internal:5432/mydb",
9
+ "redis://default:token@cache.example.com:6379",
10
+ "mongodb+srv://user:pass@cluster.mongodb.net/db",
11
+ "https://api.example.com/v2/endpoint?token=abc&format=json"
12
+ ]
13
+
14
+ describe("SecretURL", () => {
15
+ describe("fromString / value roundtrip", () => {
16
+ test.each(testUrls)("preserves %s", (url) => {
17
+ const secret = fromString(url)
18
+ expect(value(secret)).toBe(url)
19
+ })
20
+ })
21
+
22
+ describe("make / value roundtrip", () => {
23
+ test.each(testUrls)("preserves %s via byte array", (url) => {
24
+ const bytes = url.split("").map((c) => c.charCodeAt(0))
25
+ const secret = make(bytes)
26
+ expect(value(secret)).toBe(url)
27
+ })
28
+ })
29
+
30
+ describe("fromChunk / value roundtrip", () => {
31
+ test.each(testUrls)("preserves %s via Chunk", (url) => {
32
+ const chunk = Chunk.fromIterable(url.split(""))
33
+ const secret = fromChunk(chunk)
34
+ expect(value(secret)).toBe(url)
35
+ })
36
+ })
37
+
38
+ describe("toString", () => {
39
+ test("redacts the URL, showing only protocol", () => {
40
+ const secret = fromString("https://example.com/secret")
41
+ expect(String(secret)).toBe("SecretURL(https://<redacted>)")
42
+ })
43
+
44
+ test("shows http protocol", () => {
45
+ const secret = fromString("http://example.com")
46
+ expect(String(secret)).toBe("SecretURL(http://<redacted>)")
47
+ })
48
+
49
+ test("shows unknown for non-URL strings", () => {
50
+ const secret = fromString("not-a-url")
51
+ expect(String(secret)).toBe("SecretURL(unknown://<redacted>)")
52
+ })
53
+ })
54
+
55
+ describe("toJSON", () => {
56
+ test("returns tag and protocol only", () => {
57
+ const secret = fromString("https://example.com/secret")
58
+ expect(JSON.parse(JSON.stringify(secret))).toEqual({ _tag: "SecretURL", protocol: "https" })
59
+ })
60
+
61
+ test("returns unknown protocol for non-URL", () => {
62
+ const secret = fromString("not-a-url")
63
+ expect(JSON.parse(JSON.stringify(secret))).toEqual({ _tag: "SecretURL", protocol: "unknown" })
64
+ })
65
+ })
66
+
67
+ describe("isSecretURL", () => {
68
+ test("returns true for SecretURL", () => {
69
+ const secret = fromString("https://example.com")
70
+ expect(isSecretURL(secret)).toBe(true)
71
+ })
72
+
73
+ test("returns false for plain string", () => {
74
+ expect(isSecretURL("https://example.com")).toBe(false)
75
+ })
76
+
77
+ test("returns false for plain object", () => {
78
+ expect(isSecretURL({ raw: [1, 2, 3] })).toBe(false)
79
+ })
80
+ })
81
+
82
+ describe("unsafeWipe", () => {
83
+ test("zeroes out raw bytes", () => {
84
+ const secret = fromString("https://example.com")
85
+ unsafeWipe(secret)
86
+ expect(value(secret)).toBe("\0".repeat("https://example.com".length))
87
+ })
88
+ })
89
+
90
+ describe("non-URL strings", () => {
91
+ const nonUrls = [
92
+ "just-a-secret-token",
93
+ "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.abc",
94
+ "sk-1234567890abcdef",
95
+ "some random string with spaces and symbols!@#$%"
96
+ ]
97
+
98
+ test.each(nonUrls)("preserves non-URL value: %s", (input) => {
99
+ const secret = fromString(input)
100
+ expect(value(secret)).toBe(input)
101
+ expect(String(secret)).toBe("SecretURL(unknown://<redacted>)")
102
+ expect(JSON.parse(JSON.stringify(secret))).toEqual({ _tag: "SecretURL", protocol: "unknown" })
103
+ })
104
+ })
105
+
106
+ describe("special characters", () => {
107
+ test("preserves URLs with encoded characters", () => {
108
+ const url = "https://example.com/path?q=hello%20world&name=%C3%A9"
109
+ expect(value(fromString(url))).toBe(url)
110
+ })
111
+
112
+ test("preserves URLs with unicode", () => {
113
+ const url = "https://example.com/café"
114
+ expect(value(fromString(url))).toBe(url)
115
+ })
116
+
117
+ test("preserves URLs with special query params", () => {
118
+ const url = "https://example.com?a=1&b=2&c=foo+bar"
119
+ expect(value(fromString(url))).toBe(url)
120
+ })
121
+ })
122
+
123
+ describe("secretURL config", () => {
124
+ const run = <A>(config: Config.Config<A>, provider: ConfigProvider.ConfigProvider) =>
125
+ Effect.runSync(config.parse(provider))
126
+
127
+ test("reads from env-style ConfigProvider (QUEUE_URL)", () => {
128
+ const url = "https://sqs.us-east-1.amazonaws.com/123456789/my-queue"
129
+ const provider = ConfigProvider.fromEnv({ env: { QUEUE_URL: url } })
130
+ const result = run(secretURL("QUEUE_URL"), provider)
131
+ expect(value(result)).toBe(url)
132
+ expect(String(result)).toBe("SecretURL(https://<redacted>)")
133
+ })
134
+
135
+ test("reads from fromUnknown with nested config ({ queue: { url } })", () => {
136
+ const url = "redis://default:token@cache.example.com:6379"
137
+ const provider = ConfigProvider.fromUnknown({ queue: { url } })
138
+ const config = secretURL("url").pipe(Config.nested("queue"))
139
+ const result = run(config, provider)
140
+ expect(value(result)).toBe(url)
141
+ expect(String(result)).toBe("SecretURL(redis://<redacted>)")
142
+ })
143
+
144
+ test("reads non-URL secret from env", () => {
145
+ const token = "sk-1234567890abcdef"
146
+ const provider = ConfigProvider.fromEnv({ env: { API_KEY: token } })
147
+ const result = run(secretURL("API_KEY"), provider)
148
+ expect(value(result)).toBe(token)
149
+ expect(String(result)).toBe("SecretURL(unknown://<redacted>)")
150
+ })
151
+
152
+ test("rejects empty string", () => {
153
+ const provider = ConfigProvider.fromEnv({ env: { QUEUE_URL: "" } })
154
+ expect(() => run(secretURL("QUEUE_URL"), provider)).toThrow()
155
+ })
156
+ })
157
+ })