@effect-app/infra 2.93.0 → 3.0.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 (63) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/Emailer/service.d.ts +1 -1
  3. package/dist/MainFiberSet.d.ts +1 -1
  4. package/dist/Operations.d.ts +1 -1
  5. package/dist/RequestFiberSet.d.ts +1 -1
  6. package/dist/Store/service.d.ts +2 -2
  7. package/dist/adapters/SQL/Model.d.ts +6 -6
  8. package/dist/adapters/ServiceBus.d.ts +2 -2
  9. package/dist/adapters/ServiceBus.d.ts.map +1 -1
  10. package/dist/adapters/ServiceBus.js +13 -10
  11. package/dist/adapters/memQueue.d.ts +1 -1
  12. package/dist/api/ContextProvider.d.ts +3 -3
  13. package/dist/api/ContextProvider.d.ts.map +1 -1
  14. package/dist/api/ContextProvider.js +1 -1
  15. package/dist/api/routing/middleware/RouterMiddleware.d.ts +6 -6
  16. package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
  17. package/dist/api/routing/middleware/RpcMiddleware.d.ts +4 -15
  18. package/dist/api/routing/middleware/RpcMiddleware.d.ts.map +1 -1
  19. package/dist/api/routing/middleware/RpcMiddleware.js +3 -4
  20. package/dist/api/routing/middleware/RpcMiddlewareX.d.ts +18 -0
  21. package/dist/api/routing/middleware/RpcMiddlewareX.d.ts.map +1 -0
  22. package/dist/api/routing/middleware/RpcMiddlewareX.js +16 -0
  23. package/dist/api/routing/middleware/generic-middleware.d.ts +22 -8
  24. package/dist/api/routing/middleware/generic-middleware.d.ts.map +1 -1
  25. package/dist/api/routing/middleware/generic-middleware.js +59 -62
  26. package/dist/api/routing/middleware/middleware-api.d.ts +51 -32
  27. package/dist/api/routing/middleware/middleware-api.d.ts.map +1 -1
  28. package/dist/api/routing/middleware/middleware-api.js +54 -24
  29. package/dist/api/routing/middleware/middleware-native.d.ts +23 -0
  30. package/dist/api/routing/middleware/middleware-native.d.ts.map +1 -0
  31. package/dist/api/routing/middleware/middleware-native.js +19 -0
  32. package/dist/api/routing/middleware/middleware.d.ts +7 -27
  33. package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
  34. package/dist/api/routing/middleware/middleware.js +73 -88
  35. package/dist/api/routing/middleware.d.ts +1 -0
  36. package/dist/api/routing/middleware.d.ts.map +1 -1
  37. package/dist/api/routing/middleware.js +2 -1
  38. package/dist/api/routing.d.ts +1 -4
  39. package/dist/api/routing.d.ts.map +1 -1
  40. package/dist/api/routing.js +8 -8
  41. package/package.json +11 -3
  42. package/src/adapters/ServiceBus.ts +7 -5
  43. package/src/api/ContextProvider.ts +9 -7
  44. package/src/api/routing/middleware/RouterMiddleware.ts +9 -8
  45. package/src/api/routing/middleware/RpcMiddleware.ts +4 -51
  46. package/src/api/routing/middleware/RpcMiddlewareX.ts +70 -0
  47. package/src/api/routing/middleware/generic-middleware.ts +142 -107
  48. package/src/api/routing/middleware/middleware-api.ts +239 -61
  49. package/src/api/routing/middleware/middleware-native.ts +23 -0
  50. package/src/api/routing/middleware/middleware.ts +37 -40
  51. package/src/api/routing/middleware.ts +1 -0
  52. package/src/api/routing.ts +7 -13
  53. package/test/contextProvider.test.ts +4 -4
  54. package/test/controller.test.ts +41 -16
  55. package/test/dist/controller.test.d.ts.map +1 -1
  56. package/test/dist/fixtures.d.ts +48 -32
  57. package/test/dist/fixtures.d.ts.map +1 -1
  58. package/test/dist/fixtures.js +76 -47
  59. package/test/dist/requires.test.d.ts.map +1 -1
  60. package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -0
  61. package/test/fixtures.ts +71 -17
  62. package/test/requires.test.ts +15 -50
  63. package/test/rpc-multi-middleware.test.ts +134 -0
@@ -5,49 +5,9 @@ import { Context, Effect, Either, Layer, S } from "effect-app"
5
5
  import { NotLoggedInError, UnauthorizedError } from "effect-app/client"
6
6
  import { HttpHeaders } from "effect-app/http"
7
7
  import { makeMiddleware, Middleware } from "../src/api/routing.js"
8
- import { AllowAnonymous, RequestContextMap, RequireRoles, Some, SomeElse, SomeService, Test } from "./fixtures.js"
8
+ import { AllowAnonymous, AllowAnonymousLive, RequestContextMap, RequireRoles, RequireRolesLive, Some, SomeElseMiddleware, SomeElseMiddlewareLive, SomeMiddleware, SomeMiddlewareLive, SomeMiddlewareWrap, SomeService, Test, TestLive } from "./fixtures.js"
9
9
 
10
- export class SomeMiddleware extends Middleware.Tag<SomeMiddleware>()("SomeMiddleware", {
11
- provides: Some
12
- })({
13
- effect: Effect.gen(function*() {
14
- // yield* Effect.context<"test-dep">()
15
- return () =>
16
- Effect.gen(function*() {
17
- return new Some({ a: 1 })
18
- })
19
- })
20
- }) {
21
- }
22
-
23
- // functionally equivalent to the one above
24
- export class SomeMiddlewareWrap extends Middleware.Tag<SomeMiddlewareWrap>()("SomeMiddlewareWrap", {
25
- provides: Some,
26
- wrap: true
27
- })({
28
- effect: Effect.gen(function*() {
29
- // yield* Effect.context<"test-dep">()
30
- return ({ next }) => next.pipe(Effect.provideService(Some, new Some({ a: 1 })))
31
- })
32
- }) {
33
- }
34
-
35
- export class SomeElseMiddleware extends Middleware.Tag<SomeElseMiddleware>()("SomeElseMiddleware", {
36
- provides: SomeElse,
37
- wrap: true
38
- })({
39
- effect: Effect.gen(function*() {
40
- // yield* Effect.context<"test-dep">()
41
- return ({ next }) =>
42
- Effect.gen(function*() {
43
- // yield* Effect.context<"test-dep2">()
44
- return yield* next.pipe(Effect.provideService(SomeElse, new SomeElse({ b: 2 })))
45
- })
46
- })
47
- }) {
48
- }
49
-
50
- export class RequiresSomeMiddleware extends Middleware.Tag<RequiresSomeMiddleware>()("RequiresSomeMiddleware", {
10
+ export class RequiresSomeMiddleware extends Middleware.TagService<RequiresSomeMiddleware>()("RequiresSomeMiddleware", {
51
11
  requires: [Some],
52
12
  wrap: true
53
13
  })({
@@ -79,7 +39,7 @@ const _middlewareSideways = makeMiddleware(RequestContextMap)
79
39
  const _middlewareSidewaysFully = makeMiddleware(RequestContextMap)
80
40
  .middleware(RequiresSomeMiddleware, SomeMiddleware, RequireRoles, AllowAnonymous, Test, SomeElseMiddleware)
81
41
 
82
- const _middleware3Bis = makeMiddleware(RequestContextMap)
42
+ export const _middleware3Bis = makeMiddleware(RequestContextMap)
83
43
  .middleware(RequiresSomeMiddleware)
84
44
  .middleware(SomeMiddlewareWrap)
85
45
  .middleware(RequireRoles)
@@ -88,11 +48,7 @@ const _middleware3Bis = makeMiddleware(RequestContextMap)
88
48
 
89
49
  expectTypeOf(_middlewareSideways).toEqualTypeOf<typeof middleware3>()
90
50
  expectTypeOf(_middlewareSidewaysFully).toEqualTypeOf<typeof _middlewareSideways>()
91
- // expectTypeOf(_middleware3Bis).toEqualTypeOf<typeof middleware3>() // is not the same because SomeMiddlewareWrap is not SomeMiddleware
92
-
93
- type Default = typeof middleware3["Default"]
94
- type LayerContext = Layer.Layer.Context<Default>
95
- expectTypeOf({} as LayerContext).toEqualTypeOf<SomeService>()
51
+ expectTypeOf(_middleware3Bis).not.toEqualTypeOf<typeof middleware3>() // is not the same because SomeMiddlewareWrap is not SomeMiddleware
96
52
 
97
53
  class TestRequest extends S.TaggedRequest<Test>("Test")("Test", {
98
54
  payload: {},
@@ -112,7 +68,16 @@ const testSuite = (_mw: typeof middleware3) =>
112
68
  rpc: { ...Rpc.fromTaggedRequest(TestRequest), annotations: Context.make(_mw.requestContext, {}) },
113
69
  next: Effect.void as unknown as Effect<SuccessValue, never, any>
114
70
  }
115
- const layer = _mw.Default.pipe(Layer.provide(SomeService.toLayer()))
71
+ const layer = _mw.layer.pipe(
72
+ Layer.provide([
73
+ RequiresSomeMiddleware.Default,
74
+ SomeMiddlewareLive,
75
+ RequireRolesLive.pipe(Layer.provide(SomeService.toLayer())),
76
+ AllowAnonymousLive,
77
+ TestLive,
78
+ SomeElseMiddlewareLive
79
+ ])
80
+ )
116
81
  yield* Effect
117
82
  .gen(function*() {
118
83
  const mw = yield* _mw
@@ -194,6 +159,6 @@ const testSuite = (_mw: typeof middleware3) =>
194
159
  })
195
160
 
196
161
  testSuite(middleware3)
197
- testSuite(_middleware3Bis)
162
+ // testSuite(_middleware3Bis)
198
163
  testSuite(_middlewareSideways)
199
164
  testSuite(_middlewareSidewaysFully)
@@ -0,0 +1,134 @@
1
+ import { FetchHttpClient } from "@effect/platform"
2
+ import { NodeHttpServer } from "@effect/platform-node"
3
+ import { RpcClient, RpcGroup, RpcSerialization, RpcServer, RpcTest } from "@effect/rpc"
4
+ import { expect, expectTypeOf, it } from "@effect/vitest"
5
+ import { Console, Effect, Either, Layer } from "effect"
6
+ import { S } from "effect-app"
7
+ import { NotLoggedInError } from "effect-app/client"
8
+ import { HttpLayerRouter } from "effect-app/http"
9
+ import { createServer } from "http"
10
+ import { DefaultGenericMiddlewaresLive, makeMiddleware, middlewareGroup } from "../src/api/routing.js"
11
+ import { DefaultGenericMiddlewares } from "../src/api/routing/middleware/middleware-native.js"
12
+ import { AllowAnonymous, AllowAnonymousLive, RequestContextMap, RequireRoles, RequireRolesLive, Some, SomeElseMiddleware, SomeElseMiddlewareLive, SomeMiddlewareWrap, SomeMiddlewareWrapLive, SomeService, Test, TestLive, UserProfile } from "./fixtures.js"
13
+
14
+ const middleware = makeMiddleware(RequestContextMap)
15
+ .middleware(RequireRoles)
16
+ .middleware(AllowAnonymous, Test)
17
+ .middleware(SomeElseMiddleware, SomeMiddlewareWrap)
18
+ .middleware(...DefaultGenericMiddlewares)
19
+
20
+ const UserRpcs = middlewareGroup(middleware)(RpcGroup
21
+ .make(
22
+ middleware.rpc("getUser", {
23
+ success: S.Literal("awesome")
24
+ }),
25
+ middleware.rpc("doSomething", {
26
+ success: S.Literal("also-awesome"),
27
+ config: { allowAnonymous: true }
28
+ })
29
+ ))
30
+
31
+ const impl = Effect
32
+ .gen(function*() {
33
+ const impl = UserRpcs
34
+ .toLayerDynamic({
35
+ getUser: Effect.fn(function*(_payload, _headers) {
36
+ yield* Some
37
+ yield* UserProfile // we only access it while protected by allowAnonymous: false
38
+ return "awesome" as const
39
+ }),
40
+ doSomething: Effect.fn(function*() {
41
+ console.log(yield* Effect.serviceOption(UserProfile)) // we access it optionally, while allowAnonymous: true
42
+ return "also-awesome" as const
43
+ })
44
+ })
45
+ return impl
46
+ })
47
+ .pipe(Layer.unwrapEffect)
48
+
49
+ expectTypeOf<Layer.Layer.Context<typeof impl>>().toEqualTypeOf<never>()
50
+
51
+ const UserRpcsBad = middlewareGroup(middleware)(RpcGroup
52
+ .make(
53
+ middleware.rpc("doSomethingElse", {
54
+ success: S.Literal("also-awesome2"),
55
+ config: { allowAnonymous: true }
56
+ })
57
+ ))
58
+ export const badImpl = Effect
59
+ .gen(function*() {
60
+ const impl = UserRpcsBad
61
+ .toLayerDynamic({
62
+ doSomethingElse: Effect.fn(function*() {
63
+ console.log(yield* UserProfile) // bad boy! allowAnonymous: false, so `UserProfile` must fall through to the Layer R.
64
+ return "also-awesome2" as const
65
+ })
66
+ })
67
+ return impl
68
+ })
69
+ .pipe(Layer.unwrapEffect)
70
+
71
+ expectTypeOf<Layer.Layer.Context<typeof badImpl>>().toEqualTypeOf<UserProfile>()
72
+
73
+ const middlwareLayer = middleware
74
+ .layer
75
+ .pipe(
76
+ Layer.provide([
77
+ DefaultGenericMiddlewaresLive,
78
+ SomeElseMiddlewareLive,
79
+ SomeMiddlewareWrapLive,
80
+ TestLive,
81
+ RequireRolesLive.pipe(Layer.provide(SomeService.toLayer())),
82
+ AllowAnonymousLive
83
+ ])
84
+ )
85
+
86
+ export const RpcTestLayer = Layer
87
+ .mergeAll(
88
+ impl,
89
+ middlwareLayer
90
+ )
91
+
92
+ export const RpcRealLayer = Layer
93
+ .mergeAll(
94
+ HttpLayerRouter
95
+ .serve(
96
+ RpcServer
97
+ .layerHttpRouter({ group: UserRpcs, path: "/rpc", protocol: "http" })
98
+ .pipe(Layer.provide(impl))
99
+ .pipe(Layer.provide(middlwareLayer))
100
+ )
101
+ .pipe(Layer.provide(NodeHttpServer.layer(() => createServer(), { port: 5918 }))),
102
+ RpcClient
103
+ .layerProtocolHttp({ url: "http://localhost:5918/rpc" })
104
+ .pipe(
105
+ Layer.provide(FetchHttpClient.layer)
106
+ )
107
+ )
108
+ .pipe(Layer.provide(RpcSerialization.layerJson))
109
+
110
+ it.scopedLive(
111
+ "require login",
112
+ Effect.fnUntraced(
113
+ function*() {
114
+ const userClient = yield* RpcTest.makeClient(UserRpcs) // RpcTest.makeClient(UserRpcs) // RpcClient.make(UserRpcs)
115
+
116
+ const user = yield* Effect.either(userClient.getUser().pipe(Effect.onExit((_) => Console.dir(_, { depth: 10 }))))
117
+ expect(user).toStrictEqual(Either.left(new NotLoggedInError("Not logged in")))
118
+ },
119
+ Effect.provide(RpcTestLayer)
120
+ )
121
+ )
122
+
123
+ it.scopedLive(
124
+ "allow anonymous, optional UserProfile",
125
+ Effect.fnUntraced(
126
+ function*() {
127
+ const userClient = yield* RpcTest.makeClient(UserRpcs) // RpcTest.makeClient(UserRpcs) // RpcClient.make(UserRpcs)
128
+
129
+ const user = yield* userClient.doSomething().pipe(Effect.onExit((_) => Console.dir(_, { depth: 10 })))
130
+ expect(user).toBe("also-awesome")
131
+ },
132
+ Effect.provide(RpcTestLayer)
133
+ )
134
+ )