effect-app 4.0.0-beta.7 → 4.0.0-beta.70

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 (138) hide show
  1. package/CHANGELOG.md +307 -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 +54 -18
  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 +81 -44
  38. package/dist/Schema/ext.d.ts.map +1 -1
  39. package/dist/Schema/ext.js +76 -36
  40. package/dist/Schema/moreStrings.d.ts +4 -4
  41. package/dist/Schema/moreStrings.d.ts.map +1 -1
  42. package/dist/Schema/moreStrings.js +10 -5
  43. package/dist/Schema/numbers.d.ts +8 -8
  44. package/dist/Schema/numbers.js +2 -2
  45. package/dist/Schema/phoneNumber.d.ts.map +1 -1
  46. package/dist/Schema/phoneNumber.js +8 -3
  47. package/dist/Schema/strings.d.ts +4 -4
  48. package/dist/Schema/strings.d.ts.map +1 -1
  49. package/dist/Schema.d.ts +22 -55
  50. package/dist/Schema.d.ts.map +1 -1
  51. package/dist/Schema.js +43 -64
  52. package/dist/client/apiClientFactory.d.ts +3 -3
  53. package/dist/client/apiClientFactory.d.ts.map +1 -1
  54. package/dist/client/apiClientFactory.js +14 -15
  55. package/dist/client/errors.d.ts +16 -8
  56. package/dist/client/errors.d.ts.map +1 -1
  57. package/dist/client/errors.js +35 -10
  58. package/dist/client/makeClient.d.ts +13 -12
  59. package/dist/client/makeClient.d.ts.map +1 -1
  60. package/dist/client/makeClient.js +5 -2
  61. package/dist/http/Request.d.ts.map +1 -1
  62. package/dist/http/Request.js +5 -5
  63. package/dist/ids.d.ts +1 -1
  64. package/dist/ids.d.ts.map +1 -1
  65. package/dist/ids.js +1 -1
  66. package/dist/index.d.ts +3 -8
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +4 -9
  69. package/dist/middleware.d.ts +2 -2
  70. package/dist/middleware.d.ts.map +1 -1
  71. package/dist/middleware.js +3 -3
  72. package/dist/rpc/MiddlewareMaker.d.ts +4 -3
  73. package/dist/rpc/MiddlewareMaker.d.ts.map +1 -1
  74. package/dist/rpc/MiddlewareMaker.js +7 -6
  75. package/dist/rpc/RpcContextMap.d.ts +2 -2
  76. package/dist/rpc/RpcContextMap.d.ts.map +1 -1
  77. package/dist/rpc/RpcContextMap.js +4 -4
  78. package/dist/rpc/RpcMiddleware.d.ts +4 -3
  79. package/dist/rpc/RpcMiddleware.d.ts.map +1 -1
  80. package/dist/rpc/RpcMiddleware.js +1 -1
  81. package/dist/utils/gen.d.ts +1 -1
  82. package/dist/utils/gen.d.ts.map +1 -1
  83. package/dist/utils/logger.d.ts +2 -2
  84. package/dist/utils/logger.d.ts.map +1 -1
  85. package/dist/utils/logger.js +3 -3
  86. package/dist/utils.d.ts +18 -0
  87. package/dist/utils.d.ts.map +1 -1
  88. package/dist/utils.js +24 -5
  89. package/package.json +29 -17
  90. package/src/Config/SecretURL.ts +1 -1
  91. package/src/Config.ts +14 -0
  92. package/src/ConfigProvider.ts +48 -0
  93. package/src/{ServiceMap.ts → Context.ts} +57 -64
  94. package/src/Effect.ts +11 -9
  95. package/src/Layer.ts +5 -4
  96. package/src/Pure.ts +17 -18
  97. package/src/Schema/Class.ts +114 -16
  98. package/src/Schema/SpecialJsonSchema.ts +69 -0
  99. package/src/Schema/SpecialOpenApi.ts +130 -0
  100. package/src/Schema/brand.ts +13 -7
  101. package/src/Schema/email.ts +10 -2
  102. package/src/Schema/ext.ts +150 -59
  103. package/src/Schema/moreStrings.ts +14 -6
  104. package/src/Schema/numbers.ts +2 -2
  105. package/src/Schema/phoneNumber.ts +8 -1
  106. package/src/Schema.ts +79 -103
  107. package/src/client/apiClientFactory.ts +18 -18
  108. package/src/client/errors.ts +46 -12
  109. package/src/client/makeClient.ts +32 -12
  110. package/src/http/Request.ts +7 -4
  111. package/src/ids.ts +1 -1
  112. package/src/index.ts +3 -11
  113. package/src/middleware.ts +2 -2
  114. package/src/rpc/MiddlewareMaker.ts +8 -7
  115. package/src/rpc/RpcContextMap.ts +6 -5
  116. package/src/rpc/RpcMiddleware.ts +5 -4
  117. package/src/utils/gen.ts +1 -1
  118. package/src/utils/logger.ts +2 -2
  119. package/src/utils.ts +26 -4
  120. package/test/dist/moreStrings.test.d.ts.map +1 -0
  121. package/test/dist/rpc.test.d.ts.map +1 -1
  122. package/test/dist/secretURL.test.d.ts.map +1 -0
  123. package/test/dist/special.test.d.ts.map +1 -0
  124. package/test/moreStrings.test.ts +17 -0
  125. package/test/rpc.test.ts +26 -5
  126. package/test/schema.test.ts +396 -3
  127. package/test/secretURL.test.ts +157 -0
  128. package/test/special.test.ts +732 -0
  129. package/test/utils.test.ts +1 -1
  130. package/tsconfig.base.json +0 -1
  131. package/tsconfig.json +0 -1
  132. package/dist/ServiceMap.d.ts +0 -44
  133. package/dist/ServiceMap.d.ts.map +0 -1
  134. package/dist/ServiceMap.js +0 -91
  135. package/dist/Struct.d.ts +0 -44
  136. package/dist/Struct.d.ts.map +0 -1
  137. package/dist/Struct.js +0 -29
  138. package/src/Struct.ts +0 -54
@@ -1,5 +1,4 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import * as Config from "effect/Config"
3
2
  import { flow } from "effect/Function"
4
3
  import * as Layer from "effect/Layer"
5
4
  import * as ManagedRuntime from "effect/ManagedRuntime"
@@ -7,11 +6,12 @@ import * as Predicate from "effect/Predicate"
7
6
  import * as Schema from "effect/Schema"
8
7
  import * as Struct from "effect/Struct"
9
8
  import { Rpc, RpcClient, RpcGroup, RpcSerialization } from "effect/unstable/rpc"
9
+ import * as Config from "../Config.js"
10
+ import * as Context from "../Context.js"
10
11
  import * as Effect from "../Effect.js"
11
12
  import { HttpClient, HttpClientRequest } from "../http.js"
12
13
  import * as Option from "../Option.js"
13
14
  import type * as S from "../Schema.js"
14
- import * as ServiceMap from "../ServiceMap.js"
15
15
  import { typedKeysOf, typedValuesOf } from "../utils.js"
16
16
  import type { Client, ClientForOptions, Requests, RequestsAny } from "./clientFor.js"
17
17
 
@@ -40,7 +40,7 @@ export type Req = S.Top & {
40
40
  readonly "~decodingServices"?: unknown
41
41
  }
42
42
 
43
- class RequestName extends ServiceMap.Reference("RequestName", {
43
+ class RequestName extends Context.Reference("RequestName", {
44
44
  defaultValue: () => ({ requestName: "Unspecified", moduleName: "Error" })
45
45
  }) {}
46
46
 
@@ -50,17 +50,17 @@ export const HttpClientLayer = (config: ApiConfig) =>
50
50
  Effect
51
51
  .gen(function*() {
52
52
  const baseClient = yield* HttpClient.HttpClient
53
- const ctx = yield* RequestName
54
53
  const client = baseClient.pipe(
55
54
  HttpClient.mapRequest(HttpClientRequest.prependUrl(config.url + "/rpc")),
56
55
  HttpClient.mapRequest(
57
56
  HttpClientRequest.setHeaders(config.headers.pipe(Option.getOrElse(() => ({}))))
58
57
  ),
59
- HttpClient.mapRequest((req) =>
60
- flow(
61
- HttpClientRequest.appendUrlParam("action", ctx.requestName),
62
- HttpClientRequest.appendUrl("/" + ctx.moduleName)
63
- )(req)
58
+ HttpClient.mapRequestEffect((req) =>
59
+ Effect.map(RequestName.asEffect(), (ctx) =>
60
+ flow(
61
+ HttpClientRequest.appendUrlParam("action", ctx.requestName),
62
+ HttpClientRequest.appendUrl("/" + ctx.moduleName)
63
+ )(req))
64
64
  )
65
65
  )
66
66
  return client
@@ -76,7 +76,7 @@ export const HttpClientFromConfigLayer = Layer.unwrap(
76
76
 
77
77
  export const RpcSerializationLayer = (config: ApiConfig) =>
78
78
  Layer.mergeAll(
79
- RpcSerialization.layerJson,
79
+ RpcSerialization.layerNdjson,
80
80
  HttpClientLayer(config)
81
81
  )
82
82
 
@@ -139,7 +139,7 @@ const makeRpcTag = <M extends Requests>(resource: M) => {
139
139
 
140
140
  // Use Object.assign instead of class extension to avoid TS2509 with complex generic return types.
141
141
  // The first type arg is `any` because this is a dynamically created tag — its identity is the string key.
142
- const TheClient = ServiceMap.Opaque<
142
+ const TheClient = Context.Opaque<
143
143
  any,
144
144
  RpcClient.RpcClient<RpcGroup.Rpcs<typeof rpcs>>
145
145
  >()(`RpcClient.${meta.moduleName}`)
@@ -153,7 +153,7 @@ const makeRpcTag = <M extends Requests>(resource: M) => {
153
153
 
154
154
  const makeApiClientFactory = Effect
155
155
  .gen(function*() {
156
- const ctx = yield* Effect.services<RpcSerialization.RpcSerialization | HttpClient.HttpClient>()
156
+ const ctx = yield* Effect.context<RpcSerialization.RpcSerialization | HttpClient.HttpClient>()
157
157
  const makeClientFor = <M extends Requests>(
158
158
  resource: M,
159
159
  requestLevelLayers = Layer.empty,
@@ -176,7 +176,7 @@ const makeApiClientFactory = Effect
176
176
  url: "" // why not here set meta.moduleName as root?
177
177
  })
178
178
  .pipe(
179
- Layer.provideMerge(Layer.succeedServices(ctx))
179
+ Layer.provideMerge(Layer.succeedContext(ctx))
180
180
  )
181
181
  )
182
182
  )
@@ -185,7 +185,7 @@ const makeApiClientFactory = Effect
185
185
  const filtered = getFiltered(resource)
186
186
  return {
187
187
  mr,
188
- client: (typedKeysOf(filtered)
188
+ client: typedKeysOf(filtered)
189
189
  .reduce((prev, cur) => {
190
190
  const h = filtered[cur]!
191
191
 
@@ -212,7 +212,7 @@ const makeApiClientFactory = Effect
212
212
  // @ts-expect-error doc
213
213
  prev[cur] = Object.keys(fields).length === 0
214
214
  ? {
215
- handler: mr.servicesEffect.pipe(
215
+ handler: mr.contextEffect.pipe(
216
216
  Effect.flatMap((svcs) =>
217
217
  TheClient
218
218
  .use((client) => (client as any)[requestAttr]!(new Request()) as Effect.Effect<any, any, never>)
@@ -226,7 +226,7 @@ const makeApiClientFactory = Effect
226
226
  }
227
227
  : {
228
228
  handler: (req: any) =>
229
- mr.servicesEffect.pipe(
229
+ mr.contextEffect.pipe(
230
230
  Effect.flatMap((svcs) =>
231
231
  TheClient
232
232
  .use((client) =>
@@ -243,7 +243,7 @@ const makeApiClientFactory = Effect
243
243
  }
244
244
 
245
245
  return prev
246
- }, {} as Client<M, M["meta"]["moduleName"]>))
246
+ }, {} as Client<M, M["meta"]["moduleName"]>)
247
247
  }
248
248
  })
249
249
 
@@ -281,7 +281,7 @@ const makeApiClientFactory = Effect
281
281
  * Used to create clients for resource modules.
282
282
  */
283
283
  export class ApiClientFactory
284
- extends ServiceMap.Opaque<ApiClientFactory, Effect.Success<typeof makeApiClientFactory>>()("ApiClientFactory")
284
+ extends Context.Opaque<ApiClientFactory, Effect.Success<typeof makeApiClientFactory>>()("ApiClientFactory")
285
285
  {
286
286
  static readonly layer = (config: ApiConfig) =>
287
287
  ApiClientFactory.toLayer(makeApiClientFactory).pipe(Layer.provide(RpcSerializationLayer(config)))
@@ -1,5 +1,5 @@
1
1
  /** @effect-diagnostics overriddenSchemaConstructor:skip-file */
2
- import { TaggedError } from "effect-app/Schema"
2
+ import { TaggedErrorClass } from "effect-app/Schema"
3
3
  import * as Cause from "effect/Cause"
4
4
  import * as S from "../Schema.js"
5
5
 
@@ -21,7 +21,7 @@ export const tryToJson = (error: { toJSON(): unknown; toString(): string }) => {
21
21
 
22
22
  // eslint-disable-next-line unused-imports/no-unused-vars
23
23
  // @ts-expect-error type not used
24
- export class NotFoundError<ItemType = string> extends TaggedError<NotFoundError<ItemType>>()("NotFoundError", {
24
+ export class NotFoundError<ItemType = string> extends TaggedErrorClass<NotFoundError<ItemType>>()("NotFoundError", {
25
25
  type: S.String,
26
26
  id: S.Unknown
27
27
  }) {
@@ -34,28 +34,43 @@ export class NotFoundError<ItemType = string> extends TaggedError<NotFoundError<
34
34
  override get message() {
35
35
  return `Didn't find ${(this as any).type}#${JSON.stringify((this as any).id)}`
36
36
  }
37
+ override toString() {
38
+ return `NotFoundError: ${this.message}`
39
+ }
37
40
  }
38
41
 
39
42
  const messageFallback = (messageOrObject?: string | { message: string }) =>
40
43
  typeof messageOrObject === "object" ? messageOrObject : { message: messageOrObject ?? "" }
41
44
 
42
- export class InvalidStateError extends TaggedError<InvalidStateError>()("InvalidStateError", {
45
+ export class InvalidStateError extends TaggedErrorClass<InvalidStateError>()("InvalidStateError", {
43
46
  message: S.String
44
47
  }) {
45
48
  constructor(messageOrObject: string | { message: string; cause?: unknown }, disableValidation?: boolean) {
46
- super(typeof messageOrObject === "object" ? messageOrObject : { message: messageOrObject } as any, disableValidation as any)
49
+ super(
50
+ typeof messageOrObject === "object" ? messageOrObject : { message: messageOrObject } as any,
51
+ disableValidation as any
52
+ )
53
+ }
54
+ override toString() {
55
+ return `InvalidStateError: ${this.message}`
47
56
  }
48
57
  }
49
58
 
50
- export class ServiceUnavailableError extends TaggedError<ServiceUnavailableError>()("ServiceUnavailableError", {
59
+ export class ServiceUnavailableError extends TaggedErrorClass<ServiceUnavailableError>()("ServiceUnavailableError", {
51
60
  message: S.String
52
61
  }) {
53
62
  constructor(messageOrObject: string | { message: string; cause?: unknown }, disableValidation?: boolean) {
54
- super(typeof messageOrObject === "object" ? messageOrObject : { message: messageOrObject } as any, disableValidation as any)
63
+ super(
64
+ typeof messageOrObject === "object" ? messageOrObject : { message: messageOrObject } as any,
65
+ disableValidation as any
66
+ )
67
+ }
68
+ override toString() {
69
+ return `ServiceUnavailableError: ${this.message}`
55
70
  }
56
71
  }
57
72
 
58
- export class ValidationError extends TaggedError<ValidationError>()("ValidationError", {
73
+ export class ValidationError extends TaggedErrorClass<ValidationError>()("ValidationError", {
59
74
  errors: S.Array(S.Unknown)
60
75
  }) {
61
76
  constructor(
@@ -67,33 +82,45 @@ export class ValidationError extends TaggedError<ValidationError>()("ValidationE
67
82
  override get message() {
68
83
  return `Validation failed: ${(this as any).errors.map((e: any) => JSON.stringify(e, undefined, 2)).join(",\n")}`
69
84
  }
85
+ override toString() {
86
+ return `ValidationError: ${this.message}`
87
+ }
70
88
  }
71
89
 
72
- export class NotLoggedInError extends TaggedError<NotLoggedInError>()("NotLoggedInError", {
90
+ export class NotLoggedInError extends TaggedErrorClass<NotLoggedInError>()("NotLoggedInError", {
73
91
  message: S.String
74
92
  }) {
75
93
  constructor(messageOrObject?: string | { message: string; cause?: unknown }, disableValidation?: boolean) {
76
94
  super(messageFallback(messageOrObject) as any, disableValidation as any)
77
95
  }
96
+ override toString() {
97
+ return `NotLoggedInError: ${this.message}`
98
+ }
78
99
  }
79
100
 
80
101
  /**
81
102
  * The user carries a valid Userprofile, but there is a problem with the login none the less.
82
103
  */
83
- export class LoginError extends TaggedError<LoginError>()("NotLoggedInError", {
104
+ export class LoginError extends TaggedErrorClass<LoginError>()("NotLoggedInError", {
84
105
  message: S.String
85
106
  }) {
86
107
  constructor(messageOrObject?: string | { message: string; cause?: unknown }, disableValidation?: boolean) {
87
108
  super(messageFallback(messageOrObject) as any, disableValidation as any)
88
109
  }
110
+ override toString() {
111
+ return `LoginError: ${this.message}`
112
+ }
89
113
  }
90
114
 
91
- export class UnauthorizedError extends TaggedError<UnauthorizedError>()("UnauthorizedError", {
115
+ export class UnauthorizedError extends TaggedErrorClass<UnauthorizedError>()("UnauthorizedError", {
92
116
  message: S.String
93
117
  }) {
94
118
  constructor(messageOrObject?: string | { message: string; cause?: unknown }, disableValidation?: boolean) {
95
119
  super(messageFallback(messageOrObject) as any, disableValidation as any)
96
120
  }
121
+ override toString() {
122
+ return `UnauthorizedError: ${this.message}`
123
+ }
97
124
  }
98
125
 
99
126
  type OptimisticConcurrencyDetails = {
@@ -104,7 +131,7 @@ type OptimisticConcurrencyDetails = {
104
131
  readonly found?: string | undefined
105
132
  }
106
133
 
107
- export class OptimisticConcurrencyException extends TaggedError<OptimisticConcurrencyException>()(
134
+ export class OptimisticConcurrencyException extends TaggedErrorClass<OptimisticConcurrencyException>()(
108
135
  "OptimisticConcurrencyException",
109
136
  { message: S.String }
110
137
  ) {
@@ -116,11 +143,17 @@ export class OptimisticConcurrencyException extends TaggedError<OptimisticConcur
116
143
  | ({ message: string; cause?: unknown; raw?: unknown }),
117
144
  disableValidation?: boolean
118
145
  ) {
119
- super("message" in args ? args : { message: `Existing ${args.type} ${args.id} record changed` } as any, disableValidation as any)
146
+ super(
147
+ "message" in args ? args : { message: `Existing ${args.type} ${args.id} record changed` } as any,
148
+ disableValidation as any
149
+ )
120
150
  if (!("message" in args)) {
121
151
  this.details = args
122
152
  }
123
153
  }
154
+ override toString() {
155
+ return `OptimisticConcurrencyException: ${this.message}`
156
+ }
124
157
  }
125
158
 
126
159
  const MutationOnlyErrors = [
@@ -174,6 +207,7 @@ export class CauseException<E> extends Error {
174
207
  Error.stackTraceLimit = 0
175
208
  super()
176
209
  Error.stackTraceLimit = limit
210
+ this.cause = Cause.squash(originalCause)
177
211
  // v4: makeFiberFailure removed — use Cause.prettyErrors instead
178
212
  const errors = Cause.prettyErrors(originalCause)
179
213
  const first = errors[0]
@@ -1,4 +1,5 @@
1
- import { GetEffectError, type GetContextConfig, type RequestContextMapTagAny } from "../rpc/RpcContextMap.js"
1
+ import { SchemaTransformation } from "effect"
2
+ import { type GetContextConfig, type GetEffectError, type RequestContextMapTagAny } from "../rpc/RpcContextMap.js"
2
3
  import * as S from "../Schema.js"
3
4
  import { AST } from "../Schema.js"
4
5
 
@@ -8,33 +9,38 @@ const merge = (a: any, b: Array<any>) =>
8
9
  /**
9
10
  * Whatever the input, we will only decode or encode to void
10
11
  */
11
- const ForceVoid: S.Codec<void> = S.Void as any
12
+ export const ForceVoid = S
13
+ .declare((_: unknown): _ is unknown => true)
14
+ .pipe(
15
+ S.decodeTo(S.Any, SchemaTransformation.transform<unknown, unknown>({ decode: () => void 0, encode: () => void 0 }))
16
+ )
12
17
 
13
18
  type SchemaOrFields<T> = T extends S.Top ? T : T extends S.Struct.Fields ? S.Struct<T> : S.Void
14
19
 
15
20
  type TaggedRequestResult<
21
+ Self,
16
22
  Tag extends string,
17
23
  Payload extends S.Struct.Fields,
18
24
  Success extends S.Top,
19
25
  Error extends S.Top,
20
26
  Config = Record<string, never>
21
27
  > =
22
- & S.TaggedStruct<Tag, Payload>
28
+ & S.EnhancedClass<Self, S.TaggedStruct<Tag, Payload>, {}>
23
29
  & {
24
- new(...args: any[]): any
25
30
  readonly _tag: Tag
26
- readonly fields: { readonly _tag: S.tag<Tag> } & Payload
27
31
  readonly success: Success
28
32
  readonly error: Error
29
33
  readonly config: Config
34
+ // TODO: these two are wrong. Anything using this request's success/error, should however derive the Decoding/Encoding services from them..
30
35
  readonly "~decodingServices": S.Codec.DecodingServices<Success> | S.Codec.DecodingServices<Error>
36
+ readonly "~encodingServices": S.Codec.EncodingServices<Success> | S.Codec.EncodingServices<Error>
31
37
  }
32
38
 
33
39
  export const makeRpcClient = <
34
40
  RequestContextMap extends RequestContextMapTagAny,
35
41
  GeneralErrors extends S.Top = never
36
42
  >(rcs: RequestContextMap, generalErrors?: GeneralErrors) => {
37
- // Long way around ServiceMap/C extends etc to support actual jsdoc from passed in RequestConfig etc... (??)
43
+ // Long way around Context/C extends etc to support actual jsdoc from passed in RequestConfig etc... (??)
38
44
  type ServiceMap = {
39
45
  success: S.Top | S.Struct.Fields // SchemaOrFields will make a Schema type out of Struct.Fields
40
46
  error: S.Top | S.Struct.Fields // SchemaOrFields will make a Schema type out of Struct.Fields
@@ -47,31 +53,45 @@ export const makeRpcClient = <
47
53
  : [GeneralErrors] extends [never] ? GetEffectError<RequestContextMap["config"], C>
48
54
  : MergeError<GetEffectError<RequestContextMap["config"], C>>
49
55
 
50
- function TaggedRequest<_Self>(): {
56
+ function TaggedRequest<Self>(): {
51
57
  <Tag extends string, Payload extends S.Struct.Fields, C extends ServiceMap>(
52
58
  tag: Tag,
53
59
  fields: Payload,
54
60
  config: RequestConfig & C
55
- ): TaggedRequestResult<Tag, Payload, SchemaOrFields<C["success"]>, ErrorResult<C>, Omit<C, "success" | "error">>
61
+ ): TaggedRequestResult<
62
+ Self,
63
+ Tag,
64
+ Payload,
65
+ SchemaOrFields<C["success"]>,
66
+ ErrorResult<C>,
67
+ Omit<C, "success" | "error">
68
+ >
56
69
  <Tag extends string, Payload extends S.Struct.Fields, C extends Pick<ServiceMap, "success">>(
57
70
  tag: Tag,
58
71
  fields: Payload,
59
72
  config: RequestConfig & C
60
- ): TaggedRequestResult<Tag, Payload, SchemaOrFields<C["success"]>, ErrorResult<C>, Omit<C, "success" | "error">>
73
+ ): TaggedRequestResult<
74
+ Self,
75
+ Tag,
76
+ Payload,
77
+ SchemaOrFields<C["success"]>,
78
+ ErrorResult<C>,
79
+ Omit<C, "success" | "error">
80
+ >
61
81
  <Tag extends string, Payload extends S.Struct.Fields, C extends Pick<ServiceMap, "error">>(
62
82
  tag: Tag,
63
83
  fields: Payload,
64
84
  config: RequestConfig & C
65
- ): TaggedRequestResult<Tag, Payload, S.Codec<void>, ErrorResult<C>, Omit<C, "success" | "error">>
85
+ ): TaggedRequestResult<Self, Tag, Payload, typeof ForceVoid, ErrorResult<C>, Omit<C, "success" | "error">>
66
86
  <Tag extends string, Payload extends S.Struct.Fields, C extends Record<string, any>>(
67
87
  tag: Tag,
68
88
  fields: Payload,
69
89
  config: C & RequestConfig
70
- ): TaggedRequestResult<Tag, Payload, S.Codec<void>, ErrorResult<C>, Omit<C, "success" | "error">>
90
+ ): TaggedRequestResult<Self, Tag, Payload, typeof ForceVoid, ErrorResult<C>, Omit<C, "success" | "error">>
71
91
  <Tag extends string, Payload extends S.Struct.Fields>(
72
92
  tag: Tag,
73
93
  fields: Payload
74
- ): TaggedRequestResult<Tag, Payload, S.Codec<void>, ErrorResult<never>, Record<string, never>>
94
+ ): TaggedRequestResult<Self, Tag, Payload, typeof ForceVoid, ErrorResult<{}>, Record<string, never>>
75
95
  } {
76
96
  // TODO: filter errors based on config + take care of inversion
77
97
  const errorSchemas = Object.values(rcs.config).map((_) => _.error)
@@ -1,3 +1,4 @@
1
+ import { Option } from "effect"
1
2
  import type { HttpClientResponse } from "effect/unstable/http/HttpClientResponse"
2
3
  import * as Effect from "../Effect.js"
3
4
  import { HttpClient, HttpClientError, HttpClientRequest, HttpHeaders } from "./internal/lib.js"
@@ -24,16 +25,18 @@ export const demandJson = (client: HttpClient.HttpClient) =>
24
25
  .mapRequest(client, (_) => HttpClientRequest.acceptJson(_))
25
26
  .pipe(HttpClient.transform((r, request) =>
26
27
  Effect.tap(r, (response) =>
27
- HttpHeaders
28
- .get(response.headers, "Content-Type")
29
- ?.startsWith("application/json")
28
+ Option
29
+ .exists(
30
+ HttpHeaders.get(response.headers, "Content-Type"),
31
+ (_) => _.startsWith("application/json")
32
+ )
30
33
  ? Effect.void
31
34
  : Effect.fail(
32
35
  new HttpClientError.DecodeError({
33
36
  request,
34
37
  response,
35
38
  description: "not json response: "
36
- + HttpHeaders.get(response.headers, "Content-Type")
39
+ + Option.getOrElse(HttpHeaders.get(response.headers, "Content-Type"), () => "<missing>")
37
40
  })
38
41
  ))
39
42
  ))
package/src/ids.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { brandedStringId, NonEmptyString255, StringId, type StringIdBrand, withDefaultMake, Codec } from "effect-app/Schema"
1
+ import { brandedStringId, type Codec, NonEmptyString255, StringId, type StringIdBrand, withDefaultMake } from "effect-app/Schema"
2
2
  import type { B } from "effect-app/Schema/schema"
3
3
  import type { Simplify } from "effect/Types"
4
4
  import { S } from "./index.js"
package/src/index.ts CHANGED
@@ -1,29 +1,21 @@
1
1
  import "./builtin.js"
2
2
 
3
- import * as ServiceMap from "./ServiceMap.js"
4
-
5
3
  export * as Fnc from "./Function.js"
6
4
  export * as Utils from "./utils.js"
7
5
 
8
6
  export * as Array from "./Array.js"
7
+ export * as Config from "./Config.js"
8
+ export * as ConfigProvider from "./ConfigProvider.js"
9
+ export * as Context from "./Context.js"
9
10
  export * as Effect from "./Effect.js"
10
11
  export * as Layer from "./Layer.js"
11
12
  export * as NonEmptySet from "./NonEmptySet.js"
12
- export * as ServiceMap from "./ServiceMap.js"
13
13
  export * as Set from "./Set.js"
14
14
 
15
- export {
16
- /**
17
- * @deprecated use ServiceMap directly instead
18
- */
19
- ServiceMap as Context
20
- }
21
-
22
15
  export { type NonEmptyArray, type NonEmptyReadonlyArray } from "./Array.js"
23
16
 
24
17
  export * from "effect"
25
18
 
26
- export * as Struct from "./Struct.js"
27
19
  export type * as Types from "./Types.js"
28
20
 
29
21
  export * as SecretURL from "./Config/SecretURL.js"
package/src/middleware.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { ServiceMap } from "effect-app"
2
+ import { Context } from "effect-app"
3
3
  import { RpcX } from "./rpc.js"
4
4
 
5
- export class DevMode extends ServiceMap.Reference("DevMode", { defaultValue: () => false }) {}
5
+ export class DevMode extends Context.Reference("DevMode", { defaultValue: () => false }) {}
6
6
 
7
7
  export class RequestCacheMiddleware
8
8
  extends RpcX.RpcMiddleware.Tag<RequestCacheMiddleware>()("RequestCacheMiddleware")
@@ -1,10 +1,11 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { Effect, Layer, type Schema, Schema as S, type Scope, ServiceMap } from "effect"
2
+ import { Effect, Layer, type Schema, Schema as S, type Scope } from "effect"
3
3
  import { type NonEmptyArray, type NonEmptyReadonlyArray } from "effect/Array"
4
4
  import { type Simplify } from "effect/Types"
5
5
  import { Rpc, type RpcGroup, type RpcSchema } from "effect/unstable/rpc"
6
6
  import { type HandlersFrom } from "effect/unstable/rpc/RpcGroup"
7
7
  import { type RequestId } from "effect/unstable/rpc/RpcMessage"
8
+ import * as Context from "../Context.js"
8
9
  import { type HttpHeaders } from "../http.js"
9
10
  import { PreludeLogger } from "../logger.js"
10
11
  import { type TypeTestId } from "../TypeTest.js"
@@ -61,13 +62,13 @@ export interface MiddlewareMaker<
61
62
  }
62
63
  >
63
64
  {
64
- readonly layer: Layer.Layer<Self, never, ServiceMap.Service.Identifier<MiddlewareProviders[number]>>
65
+ readonly layer: Layer.Layer<Self, never, Context.Service.Identifier<MiddlewareProviders[number]>>
65
66
  readonly requestContext: RequestContextTag<RequestContextMap>
66
67
  readonly requestContextMap: RequestContextMap
67
68
  }
68
69
 
69
70
  export interface RequestContextTag<RequestContextMap extends Record<string, RpcContextMap.Any>>
70
- extends ServiceMap.Service<"RequestContextConfig", GetContextConfig<RequestContextMap>>
71
+ extends Context.Service<"RequestContextConfig", GetContextConfig<RequestContextMap>>
71
72
  {}
72
73
 
73
74
  export namespace MiddlewareMaker {
@@ -275,7 +276,7 @@ const middlewareMaker = <
275
276
  middlewares = middlewares.toReversed() as any
276
277
 
277
278
  return Effect.gen(function*() {
278
- const context = yield* Effect.services()
279
+ const context = yield* Effect.context()
279
280
 
280
281
  // returns a Effect/RpcMiddlewareV4 with Scope.Scope in requirements
281
282
  // v4: wrap middleware takes (effect, options) as two params instead of a single options bag
@@ -295,7 +296,7 @@ const middlewareMaker = <
295
296
  // inspired from Effect/RpcMiddleware
296
297
  for (const tag of middlewares) {
297
298
  // use the tag to get the middleware from context
298
- const middleware = ServiceMap.getUnsafe(context, tag)
299
+ const middleware = Context.getUnsafe(context, tag)
299
300
 
300
301
  // wrap the current handler, allowing the middleware to run before and after it
301
302
  handler = PreludeLogger.logDebug("Applying middleware wrap " + tag.key).pipe(
@@ -367,7 +368,7 @@ const makeMiddlewareBasic = <Self>() =>
367
368
  return Object.assign(MiddlewareMaker, {
368
369
  layer,
369
370
  // tag to be used to retrieve the RequestContextConfig from Rpc annotations
370
- requestContext: ServiceMap.Service<"RequestContextConfig", GetContextConfig<RequestContextMap>>(
371
+ requestContext: Context.Service<"RequestContextConfig", GetContextConfig<RequestContextMap>>(
371
372
  "RequestContextConfig"
372
373
  ),
373
374
  requestContextMap: rcm
@@ -380,7 +381,7 @@ export const Tag = <Self>() =>
380
381
  RequestContextMap extends RequestContextMapTagAny
381
382
  >(id: Id, rcm: RequestContextMap): MiddlewaresBuilder<Self, Id, RequestContextMap["config"]> => {
382
383
  let allMiddleware: MiddlewareMaker.Any[] = []
383
- const requestContext = ServiceMap.Service<"RequestContextConfig", GetContextConfig<RequestContextMap["config"]>>(
384
+ const requestContext = Context.Service<"RequestContextConfig", GetContextConfig<RequestContextMap["config"]>>(
384
385
  "RequestContextConfig"
385
386
  )
386
387
  const it = {
@@ -2,14 +2,15 @@
2
2
  /* eslint-disable @typescript-eslint/no-unsafe-return */
3
3
  /* eslint-disable @typescript-eslint/no-explicit-any */
4
4
 
5
- import { type Schema as S, ServiceMap } from "effect"
5
+ import { type Schema as S } from "effect"
6
6
  import { type AnyWithProps } from "effect/unstable/rpc/Rpc"
7
+ import * as Context from "../Context.js"
7
8
  import { type RpcDynamic } from "./RpcMiddleware.js"
8
9
 
9
10
  type Values<T extends Record<any, any>> = T[keyof T]
10
11
 
11
12
  /**
12
- * Middleware is inactivate by default, the Key is optional in route context, and the service is optionally provided as Effect ServiceMap.
13
+ * Middleware is inactivate by default, the Key is optional in route context, and the service is optionally provided as Effect Context.
13
14
  * Unless explicitly configured as `true`.
14
15
  */
15
16
  export type RpcContextMap<Service, E> = {
@@ -22,7 +23,7 @@ export type RpcContextMap<Service, E> = {
22
23
 
23
24
  export declare namespace RpcContextMap {
24
25
  /**
25
- * Middleware is active by default, and provides the Service at Key in route context, and the Service is provided as Effect ServiceMap.
26
+ * Middleware is active by default, and provides the Service at Key in route context, and the Service is provided as Effect Context.
26
27
  * Unless explicitly omitted.
27
28
  */
28
29
  export type Inverted<Service, E> = {
@@ -97,7 +98,7 @@ export type GetEffectError<RequestContextMap extends Record<string, RpcContextMa
97
98
  }
98
99
  >
99
100
 
100
- const tag = ServiceMap.Service("RequestContextConfig")
101
+ const tag = Context.Service("RequestContextConfig")
101
102
 
102
103
  export const makeMap = <const Config extends Record<string, RpcContextMap.Any>>(config: Config) => {
103
104
  const cls = class {
@@ -109,7 +110,7 @@ export const makeMap = <const Config extends Record<string, RpcContextMap.Any>>(
109
110
  return Object.assign(cls, {
110
111
  config, /** Retrieves RequestContextConfig out of the Rpc annotations */
111
112
  getConfig: (rpc: AnyWithProps): GetContextConfig<Config> => {
112
- return ServiceMap.getOrElse(rpc.annotations, tag as any, () => ({}))
113
+ return Context.getOrElse(rpc.annotations, tag as any, () => ({}))
113
114
  },
114
115
  /** Adapter used when setting the dynamic prop on a middleware implementation */
115
116
  get: <
@@ -1,10 +1,11 @@
1
1
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
2
2
  /* eslint-disable @typescript-eslint/no-unsafe-return */
3
3
  /* eslint-disable @typescript-eslint/no-explicit-any */
4
- import { type Effect, type Schema, type Schema as S, type Scope, type ServiceMap, type Stream } from "effect"
4
+ import { type Effect, type Schema, type Schema as S, type Scope, type Stream } from "effect"
5
5
  import { type NonEmptyReadonlyArray } from "effect/Array"
6
6
  import { type Rpc, RpcMiddleware } from "effect/unstable/rpc"
7
7
  import { type TypeId } from "effect/unstable/rpc/RpcMiddleware"
8
+ import type * as Context from "../Context.js"
8
9
  import { type GetEffectContext, type RpcContextMap } from "./RpcContextMap.js"
9
10
 
10
11
  export type RpcMiddlewareV4<Provides, E, Requires> = RpcMiddleware.RpcMiddleware<Provides, E, Requires>
@@ -102,8 +103,8 @@ export declare namespace TagClass {
102
103
  requires?: any
103
104
  provides?: any
104
105
  }
105
- > extends ServiceMap.Service<Self, Service> {
106
- new(_: never): ServiceMap.ServiceClass.Shape<Name, Service>
106
+ > extends Context.Service<Self, Service> {
107
+ new(_: never): Context.ServiceClass.Shape<Name, Service>
107
108
  readonly [TypeId]: TypeId
108
109
  readonly optional: Optional<Options>
109
110
  readonly error: FailureSchema<Options>
@@ -226,7 +227,7 @@ export type ExtractProvides<R extends Rpc.Any, Tag extends string> = R extends
226
227
  Rpc.Rpc<Tag, infer _Payload, infer _Success, infer _Error, infer _Middleware, infer _Requires> ? _Middleware extends {
227
228
  readonly provides: infer _P
228
229
  } ? [_P] extends [never] ? never
229
- : _P /*_P extends ServiceMap.Service<infer _I, infer _S> ? _I
230
+ : _P /*_P extends Context.Service<infer _I, infer _S> ? _I
230
231
  : never */
231
232
  : never
232
233
  : never
package/src/utils/gen.ts CHANGED
@@ -15,7 +15,7 @@ export namespace EffectGenUtils {
15
15
  : EG extends (..._: infer _3) => Generator<Yieldable<any, infer _, infer E, infer _R>, infer _A, infer _2> ? E
16
16
  : never
17
17
 
18
- export type ServiceMap<EG> = EG extends Effect<infer _A, infer _E, infer R> ? R
18
+ export type Context<EG> = EG extends Effect<infer _A, infer _E, infer R> ? R
19
19
  // there could be a case where the generator function does not yield anything, so we need to handle that
20
20
  : EG extends (..._: infer _3) => Generator<never, infer _A, infer _2> ? never
21
21
  // v4: generators can yield Yieldable (Effect, Service, etc.), all have asEffect()
@@ -2,11 +2,11 @@
2
2
  /* eslint-disable @typescript-eslint/no-explicit-any */
3
3
 
4
4
  import { Effect, type LogLevel } from "effect"
5
- import * as ServiceMap from "../ServiceMap.js"
5
+ import * as Context from "../Context.js"
6
6
 
7
7
  type Levels = "info" | "debug" | "warn" | "error"
8
8
 
9
- export class LogLevels extends ServiceMap.Reference("LogLevels", {
9
+ export class LogLevels extends Context.Reference("LogLevels", {
10
10
  defaultValue: () => new Map<string, Levels>()
11
11
  }) {}
12
12