@effect-app/vue 4.0.0-beta.17 → 4.0.0-beta.171

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 (96) hide show
  1. package/CHANGELOG.md +1098 -0
  2. package/dist/commander.d.ts +370 -0
  3. package/dist/commander.d.ts.map +1 -0
  4. package/dist/commander.js +591 -0
  5. package/dist/confirm.d.ts +19 -0
  6. package/dist/confirm.d.ts.map +1 -0
  7. package/dist/confirm.js +24 -0
  8. package/dist/errorReporter.d.ts +4 -4
  9. package/dist/errorReporter.d.ts.map +1 -1
  10. package/dist/errorReporter.js +12 -18
  11. package/dist/form.d.ts +13 -4
  12. package/dist/form.d.ts.map +1 -1
  13. package/dist/form.js +41 -12
  14. package/dist/index.d.ts +1 -1
  15. package/dist/intl.d.ts +15 -0
  16. package/dist/intl.d.ts.map +1 -0
  17. package/dist/intl.js +9 -0
  18. package/dist/lib.d.ts +8 -9
  19. package/dist/lib.d.ts.map +1 -1
  20. package/dist/lib.js +34 -7
  21. package/dist/makeClient.d.ts +120 -277
  22. package/dist/makeClient.d.ts.map +1 -1
  23. package/dist/makeClient.js +155 -359
  24. package/dist/makeContext.d.ts +1 -1
  25. package/dist/makeContext.d.ts.map +1 -1
  26. package/dist/makeIntl.d.ts +1 -1
  27. package/dist/makeIntl.d.ts.map +1 -1
  28. package/dist/makeUseCommand.d.ts +8 -0
  29. package/dist/makeUseCommand.d.ts.map +1 -0
  30. package/dist/makeUseCommand.js +13 -0
  31. package/dist/mutate.d.ts +4 -4
  32. package/dist/mutate.d.ts.map +1 -1
  33. package/dist/mutate.js +7 -7
  34. package/dist/query.d.ts +11 -15
  35. package/dist/query.d.ts.map +1 -1
  36. package/dist/query.js +19 -27
  37. package/dist/routeParams.d.ts +1 -1
  38. package/dist/runtime.d.ts +5 -2
  39. package/dist/runtime.d.ts.map +1 -1
  40. package/dist/runtime.js +27 -17
  41. package/dist/toast.d.ts +46 -0
  42. package/dist/toast.d.ts.map +1 -0
  43. package/dist/toast.js +32 -0
  44. package/dist/withToast.d.ts +26 -0
  45. package/dist/withToast.d.ts.map +1 -0
  46. package/dist/withToast.js +49 -0
  47. package/eslint.config.mjs +2 -2
  48. package/package.json +48 -48
  49. package/src/{experimental/commander.ts → commander.ts} +930 -255
  50. package/src/{experimental/confirm.ts → confirm.ts} +10 -14
  51. package/src/errorReporter.ts +60 -72
  52. package/src/form.ts +55 -16
  53. package/src/intl.ts +12 -0
  54. package/src/lib.ts +50 -13
  55. package/src/makeClient.ts +454 -1023
  56. package/src/{experimental/makeUseCommand.ts → makeUseCommand.ts} +3 -3
  57. package/src/mutate.ts +40 -32
  58. package/src/query.ts +39 -50
  59. package/src/runtime.ts +39 -18
  60. package/src/{experimental/toast.ts → toast.ts} +11 -25
  61. package/src/{experimental/withToast.ts → withToast.ts} +15 -6
  62. package/test/Mutation.test.ts +130 -10
  63. package/test/dist/form.test.d.ts.map +1 -1
  64. package/test/dist/lib.test.d.ts.map +1 -0
  65. package/test/dist/stubs.d.ts +2162 -118
  66. package/test/dist/stubs.d.ts.map +1 -1
  67. package/test/dist/stubs.js +80 -23
  68. package/test/form-validation-errors.test.ts +23 -19
  69. package/test/form.test.ts +20 -2
  70. package/test/lib.test.ts +240 -0
  71. package/test/makeClient.test.ts +217 -38
  72. package/test/stubs.ts +117 -40
  73. package/tsconfig.json +0 -1
  74. package/tsconfig.json.bak +2 -2
  75. package/tsconfig.src.json +34 -34
  76. package/tsconfig.test.json +2 -2
  77. package/vitest.config.ts +5 -5
  78. package/dist/experimental/commander.d.ts +0 -359
  79. package/dist/experimental/commander.d.ts.map +0 -1
  80. package/dist/experimental/commander.js +0 -557
  81. package/dist/experimental/confirm.d.ts +0 -19
  82. package/dist/experimental/confirm.d.ts.map +0 -1
  83. package/dist/experimental/confirm.js +0 -28
  84. package/dist/experimental/intl.d.ts +0 -16
  85. package/dist/experimental/intl.d.ts.map +0 -1
  86. package/dist/experimental/intl.js +0 -5
  87. package/dist/experimental/makeUseCommand.d.ts +0 -8
  88. package/dist/experimental/makeUseCommand.d.ts.map +0 -1
  89. package/dist/experimental/makeUseCommand.js +0 -13
  90. package/dist/experimental/toast.d.ts +0 -47
  91. package/dist/experimental/toast.d.ts.map +0 -1
  92. package/dist/experimental/toast.js +0 -41
  93. package/dist/experimental/withToast.d.ts +0 -25
  94. package/dist/experimental/withToast.d.ts.map +0 -1
  95. package/dist/experimental/withToast.js +0 -45
  96. package/src/experimental/intl.ts +0 -9
@@ -1,95 +1,274 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { type Effect } from "effect-app"
3
- import { Something, useClient, useExperimental } from "./stubs.js"
4
-
5
- it.skip("works2", () => {
6
- const { legacy } = useClient()
7
- const n = legacy.useQuery({
8
- Request: null as any,
9
- handler: null as any as (a: string) => Effect.Effect<number>,
10
- id: "id"
2
+ import { S } from "effect-app"
3
+ import { configureInvalidation, makeQueryKey } from "effect-app/client"
4
+ import * as Exit from "effect/Exit"
5
+ import { Something, SomethingElse, SomethingElseReq, SomethingReq, useClient, useExperimental } from "./stubs.js"
6
+
7
+ const somethingInvalidationResources = {
8
+ Something: {
9
+ GetSomething2: Something.GetSomething2,
10
+ GetSomething2WithDependencies: Something.GetSomething2WithDependencies,
11
+ GetSomething3: Something.GetSomething3,
12
+ GetSomething4: Something.GetSomething4
13
+ }
14
+ }
15
+
16
+ it("TaggedRequestFor .moduleName and request .id / .moduleName", () => {
17
+ expectTypeOf(SomethingReq.moduleName).toEqualTypeOf<"Something">()
18
+ expectTypeOf(SomethingElseReq.moduleName).toEqualTypeOf<"SomethingElse">()
19
+
20
+ expectTypeOf(Something.GetSomething2.moduleName).toEqualTypeOf<"Something">()
21
+ expectTypeOf(Something.GetSomething2.id).toEqualTypeOf<"Something.GetSomething2">()
22
+ expectTypeOf(Something.GetSomething2.type).toEqualTypeOf<"query">()
23
+ expectTypeOf(Something.DoSomething.type).toEqualTypeOf<"command">()
24
+
25
+ expectTypeOf(SomethingElse.GetSomething2.moduleName).toEqualTypeOf<"SomethingElse">()
26
+ expectTypeOf(SomethingElse.GetSomething2.id).toEqualTypeOf<"SomethingElse.GetSomething2">()
27
+
28
+ const invalidates = configureInvalidation<{
29
+ Something: typeof Something
30
+ SomethingElse: typeof SomethingElse
31
+ }>()((queryKey, { Something, SomethingElse }) => [
32
+ { filters: { queryKey } },
33
+ { filters: { queryKey: makeQueryKey(Something.GetSomething2) } },
34
+ { filters: { queryKey: makeQueryKey(SomethingElse.GetSomething2) } }
35
+ ])
36
+
37
+ expectTypeOf(invalidates.invalidatesQueries).toBeFunction()
38
+ configureInvalidation<{ Something: typeof Something }>()((_queryKey, { Something }) => {
39
+ // @ts-expect-error commands are intentionally excluded from configured resources
40
+ void Something.DoSomething
41
+ return []
11
42
  })
12
43
 
13
- const [, z] = n("a")
44
+ const { clientFor } = useClient()
45
+ const client = clientFor(
46
+ Something,
47
+ undefined,
48
+ somethingInvalidationResources
49
+ )
50
+
51
+ // only queries, no commands, and no commands who require resources; shouldn't require invalidation resources args!
52
+ clientFor({ GetSomething: Something.GetSomething2 })
53
+
54
+ // @ts-expect-error invalidation resources should be required when any command configures them
55
+ clientFor(Something)
56
+
57
+ // @ts-expect-error invalidation resources for this module reject extra top-level resources
58
+ clientFor(Something, undefined, { ...somethingInvalidationResources, SomethingElse })
59
+
60
+ const doSomethingInvalidation = client.DoSomething.Request.config["invalidatesQueries"]
61
+ if (doSomethingInvalidation) {
62
+ const entries = doSomethingInvalidation(
63
+ ["$Something"],
64
+ somethingInvalidationResources,
65
+ { id: "abc" },
66
+ Exit.succeed(123)
67
+ )
68
+ expect(Array.isArray(entries)).toBe(true)
69
+ }
70
+
71
+ const SomethingCommand = SomethingReq.Command
72
+
73
+ class TypeInferenceWithSuccess extends SomethingCommand<TypeInferenceWithSuccess>()("TypeInferenceWithSuccess", {
74
+ id: S.String
75
+ }, {
76
+ success: S.FiniteFromString
77
+ }, (_queryKey, _resources, input, result) => {
78
+ expectTypeOf(input).toEqualTypeOf<{ readonly id: string }>()
79
+ expectTypeOf(result).toEqualTypeOf<Exit.Exit<number, never>>()
80
+ return []
81
+ }) {}
82
+ void TypeInferenceWithSuccess
83
+
84
+ class TypeInferenceWithoutSuccess extends SomethingCommand<TypeInferenceWithoutSuccess>()(
85
+ "TypeInferenceWithoutSuccess",
86
+ {
87
+ id: S.String
88
+ },
89
+ {},
90
+ (_queryKey, _resources, input, result) => {
91
+ expectTypeOf(input).toEqualTypeOf<{ readonly id: string }>()
92
+ expectTypeOf(result).toEqualTypeOf<Exit.Exit<void, never>>()
93
+ return []
94
+ }
95
+ ) {}
96
+ void TypeInferenceWithoutSuccess
97
+
98
+ type MixedResources = {
99
+ Something: typeof Something
100
+ Misc: {
101
+ value: number
102
+ GetSomething2: typeof Something.GetSomething2
103
+ }
104
+ }
105
+
106
+ class TypeInferenceResourceFiltering extends SomethingCommand<
107
+ TypeInferenceResourceFiltering,
108
+ MixedResources
109
+ >()("TypeInferenceResourceFiltering", {
110
+ id: S.String
111
+ }, {
112
+ success: S.FiniteFromString
113
+ }, (_queryKey, resources, _input, _result) => {
114
+ expectTypeOf(resources.Something.GetSomething2).toEqualTypeOf<typeof Something.GetSomething2>()
115
+ expectTypeOf(resources.Misc.GetSomething2).toEqualTypeOf<typeof Something.GetSomething2>()
116
+
117
+ // @ts-expect-error commands must be filtered from invalidation resources
118
+ void resources.Something.DoSomething
119
+ // @ts-expect-error non-query values must be filtered from invalidation resources
120
+ void resources.Misc.value
121
+
122
+ return []
123
+ }) {}
124
+ void TypeInferenceResourceFiltering
125
+
126
+ type WithSuccessInvalidation = NonNullable<typeof TypeInferenceWithSuccess.config.invalidatesQueries> // @ts-expect-error input should be required when command payload is non-empty
127
+ ;((_queryKey, _resources) => []) satisfies WithSuccessInvalidation
128
+ })
129
+
130
+ it.skip("query type tests", () => {
131
+ const { clientFor } = useClient()
132
+ const client = clientFor(
133
+ Something,
134
+ () => ({
135
+ GetSomething2WithDependencies: (queryKey) => [
136
+ { filters: { queryKey } },
137
+ {
138
+ filters: {
139
+ queryKey: makeQueryKey(
140
+ SomethingElse
141
+ .GetSomething2
142
+ )
143
+ }
144
+ }
145
+ ]
146
+ }),
147
+ somethingInvalidationResources
148
+ )
149
+
150
+ const q = client.GetSomething2.query
151
+
152
+ const [, z] = q({ id: "a" })
14
153
  const valz = z.value
15
154
  expectTypeOf(valz).toEqualTypeOf<number | undefined>()
16
155
 
17
- const [, a] = n("a", { placeholderData: () => 123 })
156
+ const [, a] = q({ id: "a" }, { placeholderData: () => 123 })
18
157
  const val1 = a.value
19
158
  expectTypeOf(val1).toEqualTypeOf<number>()
20
159
 
21
- const [, bbbb] = n("a", { select: (data) => data.toString() })
160
+ const [, bbbb] = q({ id: "a" }, { select: (data) => data.toString() })
22
161
  const val = bbbb.value
23
162
  expectTypeOf(val).toEqualTypeOf<string | undefined>()
24
163
 
25
- const [, ccc] = n("a", { placeholderData: () => 123, select: (data) => data.toString() })
164
+ const [, ccc] = q({ id: "a" }, { placeholderData: () => 123, select: (data) => data.toString() })
26
165
  const val2 = ccc.value
27
166
  expectTypeOf(val2).toEqualTypeOf<string>()
28
167
 
29
- const [, ddd] = n("a", { initialData: 123, select: (data) => data.toString() })
168
+ const [, ddd] = q({ id: "a" }, { initialData: 123, select: (data) => data.toString() })
30
169
  const val3 = ddd.value
31
170
  expectTypeOf(val3).toEqualTypeOf<string>()
32
171
 
33
- const [, eee] = n("a", { initialData: 123, placeholderData: () => 123, select: (data) => data.toString() })
172
+ const [, eee] = q({ id: "a" }, { initialData: 123, placeholderData: () => 123, select: (data) => data.toString() })
34
173
  const val4 = eee.value
35
174
  expectTypeOf(val4).toEqualTypeOf<string>()
36
175
  })
37
176
 
38
177
  it.skip("works", () => {
39
- const { clientFor, legacy } = useClient()
40
- const client = clientFor(Something)
178
+ const { clientFor } = useClient()
179
+ const client = clientFor(Something, undefined, somethingInvalidationResources)
41
180
  const Command = useExperimental()
42
181
 
43
182
  // just for jsdoc / type testing.
44
- const a0 = client.GetSomething2(null as any)
45
- const a00 = client.GetSomething2.mutate(null as any)
183
+ const a0 = client.GetSomething2.request(null as any)
184
+ const a00 = client.DoSomething.mutate(null as any)
46
185
  const a = client.GetSomething2.suspense(null as any)
47
186
  const b = client.GetSomething2.query(null as any)
48
187
 
49
- const c0 = legacy.useSafeMutation(null as any)
50
- const c = legacy.useQuery(null as any)
51
- const d = legacy.useSuspenseQuery(null as any)
188
+ const de = client.GetSomething3.handler(null as any)
189
+ const de2 = client.GetSomething3.handler({ id: null })
52
190
 
191
+ // @ts-expect-error not callable as it requires no input
192
+ const de3 = client.GetSomething4.handler(null as any)
193
+ void client.GetSomething4.handler
194
+
195
+ // @ts-expect-error query requests no longer expose command helpers
53
196
  const e = client.GetSomething2.wrap(null as any)
197
+ // @ts-expect-error query requests no longer expose command helpers
54
198
  const f = client.GetSomething2.fn(null as any)
55
199
 
56
- // @ts-expect-error dependencies required that are not provided
57
- const e0 = client.GetSomething2WithDependencies.wrap().handle // not available as we require dependencies not provided by the runtime
58
- // @ts-expect-error dependencies required that are not provided
59
- const e000 = Command.wrap(client.GetSomething2WithDependencies)().handle // not available as we require dependencies not provided by the runtime
60
- const e00 = client.GetSomething2WithDependencies.wrap((_) => _ as Effect.Effect<number, never, never>).handle(
61
- null as any
62
- )
63
- const e0000 =
64
- Command.wrap(client.GetSomething2WithDependencies)((_) => _ as Effect.Effect<number, never, never>).handle
200
+ // @ts-expect-error query requests no longer expose command helpers
201
+ const e0 = client.GetSomething2WithDependencies.wrap
202
+ // @ts-expect-error query request does not match Command.wrap mutation signature
203
+ const e000 = Command.wrap(client.GetSomething2WithDependencies)
204
+ const e00 = client.GetSomething2WithDependencies.request(null as any)
65
205
  // @ts-expect-error dependencies required that are not provided
66
206
  const e1 = client.GetSomething2WithDependencies.suspense(null as any)
67
207
  // @ts-expect-error dependencies required that are not provided
68
208
  const e2 = client.GetSomething2WithDependencies.query(null as any)
209
+ // @ts-expect-error query requests no longer expose command helpers
69
210
  const f0 = client.GetSomething2WithDependencies.fn(null as any)
70
211
 
71
- const g = client.GetSomething2.mutate.wrap(null as any)
72
- const h = client.GetSomething2.mutate.fn(null as any)
212
+ const g0 = client.DoSomething.wrap(null as any)
213
+ const g = client.DoSomething.mutate.wrap(null as any)
214
+ const g1 = client.DoSomething.mutate.project(S.String)
215
+ const g2 = g1(null as any)
216
+ const g3 = g1.wrap(null as any)
217
+ const g4 = client.helpers.doSomethingMutation.project(S.String)
218
+ const g5 = g4(null as any)
219
+ const g6 = g4.wrap(null as any)
220
+ // @ts-expect-error mutate no longer exposes fn, use client.DoSomething.fn
221
+ const h = client.DoSomething.mutate.fn(null as any)
222
+
223
+ // projection
224
+ // GetSomething2 uses FiniteFromString, that means Codec is String -> Number
225
+ // when we project that to S.String, it should work as the encoded shapes are identical
226
+ // aka, when we project, we skip decoding with the original codec, and instead use the provided one
227
+ // we have to make sure the Encoded shape of the provided projection schema matches the Encoded Shape of the original codec.
228
+ const projected = client.GetSomething2.project(S.String)
229
+ // @ts-expect-error encoded type mismatch: original encodes to string, S.Number encodes to number
230
+ client.GetSomething2.project(S.Number)
231
+ const p0 = projected.request(null as any)
232
+
233
+ // struct example: success schema encodes to { a: string | null }
234
+ // good: projection schema also expects { a: string | null } on the encoded side
235
+ const projectedStruct = client.GetStructNullable.project(S.Struct({ a: S.NullOr(S.String) }))
236
+ // bad: { a: S.String } has encoded type { a: string } — does not accept null
237
+ // @ts-expect-error encoded type mismatch: original encodes to { a: string | null }, projection expects { a: string }
238
+ client.GetStructNullable.project(S.Struct({ a: S.String }))
239
+
240
+ const p00 = projected.query(null as any)
241
+ const p = projected.suspense(null as any)
73
242
 
74
243
  expect(true).toBe(true)
75
244
  console.log({
76
245
  a,
77
246
  a0,
78
247
  a00,
79
- c0,
80
248
  b,
81
- c,
82
- d,
83
249
  e,
250
+ de,
251
+ de2,
252
+ de3,
84
253
  e0,
85
254
  e00,
86
255
  e000,
87
- e0000,
88
256
  e1,
89
257
  e2,
90
258
  f,
91
259
  f0,
260
+ g0,
92
261
  g,
93
- h
262
+ g1,
263
+ g2,
264
+ g3,
265
+ g4,
266
+ g5,
267
+ g6,
268
+ h,
269
+ p0,
270
+ p00,
271
+ p,
272
+ projectedStruct
94
273
  })
95
274
  })
package/test/stubs.ts CHANGED
@@ -4,15 +4,16 @@ import * as Intl from "@formatjs/intl"
4
4
  import { Effect, Layer, ManagedRuntime, Option, S } from "effect-app"
5
5
  import { ApiClientFactory, makeRpcClient } from "effect-app/client"
6
6
  import { RpcContextMap } from "effect-app/rpc"
7
+ import * as Exit from "effect/Exit"
7
8
  import * as FetchHttpClient from "effect/unstable/http/FetchHttpClient"
8
9
  import { ref } from "vue"
9
- import { Commander } from "../src/experimental/commander.js"
10
- import { I18n } from "../src/experimental/intl.js"
11
- import { makeUseCommand } from "../src/experimental/makeUseCommand.js"
12
- import * as Toast from "../src/experimental/toast.js"
13
- import { WithToast } from "../src/experimental/withToast.js"
14
- import { LegacyMutation, makeClient } from "../src/makeClient.js"
10
+ import { Commander } from "../src/commander.js"
11
+ import { I18n } from "../src/intl.js"
12
+ import { makeClient } from "../src/makeClient.js"
15
13
  import { type MakeIntlReturn } from "../src/makeIntl.js"
14
+ import { makeUseCommand } from "../src/makeUseCommand.js"
15
+ import * as Toast from "../src/toast.js"
16
+ import { WithToast } from "../src/withToast.js"
16
17
 
17
18
  const fakeToastLayer = (toasts: any[] = []) =>
18
19
  Layer.effect(
@@ -26,33 +27,34 @@ const fakeToastLayer = (toasts: any[] = []) =>
26
27
  toasts.splice(idx, 1)
27
28
  }
28
29
  }
29
- const fakeToast = (message: string, options?: Toast.ToastOpts) => {
30
- const id = options?.id ?? Math.random().toString(36).substring(2, 15)
31
- console.log(`Toast [${id}]: ${message}`, options)
30
+ const fakeToast =
31
+ (type: "error" | "warning" | "success" | "info") => (message: string, options?: Toast.ToastOpts) => {
32
+ const id = options?.id ?? Math.random().toString(36).substring(2, 15)
33
+ console.log(`Toast [${type}][${id}]: ${message}`, options)
32
34
 
33
- options = { ...options, id }
34
- const idx = toasts.findIndex((_) => _.id === id)
35
- if (idx > -1) {
36
- const toast = toasts[idx]
37
- clearTimeout(toast.timeoutId)
38
- Object.assign(toast, { message, options })
39
- toast.timeoutId = setTimeout(() => {
40
- toasts.splice(idx, 1)
41
- }, options?.timeout ?? 3000)
42
- } else {
43
- const toast: any = { id, message, options }
44
- toast.timeoutId = setTimeout(() => {
45
- toasts.splice(idx, 1)
46
- }, options?.timeout ?? 3000)
47
- toasts.push(toast)
35
+ options = { ...options, id }
36
+ const idx = toasts.findIndex((_) => _.id === id)
37
+ if (idx > -1) {
38
+ const toast = toasts[idx]
39
+ clearTimeout(toast.timeoutId)
40
+ Object.assign(toast, { type, message, options })
41
+ toast.timeoutId = setTimeout(() => {
42
+ toasts.splice(idx, 1)
43
+ }, options?.timeout ?? 3000)
44
+ } else {
45
+ const toast: any = { id, type, message, options }
46
+ toast.timeoutId = setTimeout(() => {
47
+ toasts.splice(idx, 1)
48
+ }, options?.timeout ?? 3000)
49
+ toasts.push(toast)
50
+ }
51
+ return id
48
52
  }
49
- return id
50
- }
51
53
  return Toast.Toast.of(Toast.wrap({
52
- error: fakeToast,
53
- warning: fakeToast,
54
- success: fakeToast,
55
- info: fakeToast,
54
+ error: fakeToast("error"),
55
+ warning: fakeToast("warning"),
56
+ success: fakeToast("success"),
57
+ info: fakeToast("info"),
56
58
  dismiss
57
59
  })) as any
58
60
  })
@@ -92,20 +94,96 @@ export const useExperimental = (
92
94
  }
93
95
 
94
96
  export class RequestContextMap extends RpcContextMap.makeMap({}) {}
95
- export const { TaggedRequest: Req } = makeRpcClient(RequestContextMap)
96
- export class GetSomething2 extends Req<GetSomething2>()("GetSomething2", {
97
+ export const { TaggedRequestFor } = makeRpcClient(RequestContextMap)
98
+
99
+ export const SomethingReq = TaggedRequestFor("Something")
100
+ const SomethingQuery = SomethingReq.Query
101
+ const SomethingCommand = SomethingReq.Command
102
+
103
+ class SomethingGetSomething2 extends SomethingQuery<SomethingGetSomething2>()("GetSomething2", {
97
104
  id: S.String
98
- }, { success: S.NumberFromString }) {}
105
+ }, { success: S.FiniteFromString }) {}
106
+
107
+ class SomethingGetSomething3 extends SomethingQuery<SomethingGetSomething3>()("GetSomething3", {
108
+ id: S.NullOr(S.String).withDefault
109
+ }, { success: S.FiniteFromString }) {}
110
+
111
+ class SomethingGetSomething4
112
+ extends SomethingQuery<SomethingGetSomething4>()("GetSomething4", {}, { success: S.FiniteFromString })
113
+ {}
114
+
115
+ class SomethingGetSomething2WithDependencies
116
+ extends SomethingQuery<SomethingGetSomething2WithDependencies>()("GetSomething2", {
117
+ id: S.String
118
+ }, {
119
+ // this is intentilally fake, to simulate a codec that requires a dependency
120
+ success: S.FiniteFromString as S.Codec<number, string, "dep-a">,
121
+ error: S.String
122
+ })
123
+ {}
124
+
125
+ type SomethingInvalidationResources = {
126
+ GetSomething2: typeof SomethingGetSomething2
127
+ GetSomething2WithDependencies: typeof SomethingGetSomething2WithDependencies
128
+ GetSomething3: typeof SomethingGetSomething3
129
+ }
99
130
 
100
- export class GetSomething2WithDependencies extends Req<GetSomething2WithDependencies>()("GetSomething2", {
131
+ class SomethingDoSomething extends SomethingCommand<
132
+ SomethingDoSomething,
133
+ { Something: SomethingInvalidationResources }
134
+ >()("DoSomething", {
101
135
  id: S.String
102
136
  }, {
103
- // this is intentilally fake, to simulate a codec that requires a dependency
104
- success: S.NumberFromString as S.Codec<number, string, "dep-a">,
105
- error: S.String
137
+ success: S.FiniteFromString
138
+ }, (queryKey, { Something }, input, output) => {
139
+ return [
140
+ { filters: { queryKey } },
141
+ {
142
+ filters: {
143
+ queryKey: [
144
+ Something["GetSomething2"].id,
145
+ input.id,
146
+ Exit.isSuccess(output) ? output.value.toString() : "failed"
147
+ ]
148
+ }
149
+ }
150
+ ]
151
+ }) {}
152
+
153
+ // success schema has encoded shape { a: string | null } — used to test projection constraints
154
+ class SomethingGetStructNullable extends SomethingQuery<SomethingGetStructNullable>()("GetStructNullable", {}, {
155
+ success: S.Struct({ a: S.NullOr(S.String) })
106
156
  }) {}
107
157
 
108
- export const Something = { GetSomething2, GetSomething2WithDependencies, meta: { moduleName: "Something" as const } }
158
+ export const Something = {
159
+ GetSomething2: SomethingGetSomething2,
160
+ GetSomething2WithDependencies: SomethingGetSomething2WithDependencies,
161
+ GetSomething3: SomethingGetSomething3,
162
+ GetSomething4: SomethingGetSomething4,
163
+ DoSomething: SomethingDoSomething,
164
+ GetStructNullable: SomethingGetStructNullable
165
+ }
166
+
167
+ export const SomethingElseReq = TaggedRequestFor("SomethingElse")
168
+ const SomethingElseQuery = SomethingElseReq.Query
169
+
170
+ class SomethingElseGetSomething2 extends SomethingElseQuery<SomethingElseGetSomething2>()("GetSomething2", {
171
+ id: S.String
172
+ }, { success: S.FiniteFromString }) {}
173
+
174
+ class SomethingElseGetSomething2WithDependencies
175
+ extends SomethingElseQuery<SomethingElseGetSomething2WithDependencies>()("GetSomething2", {
176
+ id: S.String
177
+ }, {
178
+ success: S.FiniteFromString as S.Codec<number, string, "dep-a">,
179
+ error: S.String
180
+ })
181
+ {}
182
+
183
+ export const SomethingElse = {
184
+ GetSomething2: SomethingElseGetSomething2,
185
+ GetSomething2WithDependencies: SomethingElseGetSomething2WithDependencies
186
+ }
109
187
 
110
188
  export const useClient = (
111
189
  options?: { messages?: Record<string, string> | Record<string, MessageFormatElement[]>; toasts: any[] }
@@ -117,8 +195,7 @@ export const useClient = (
117
195
  const api = ApiClientFactory.layer({ url: "bogus", headers: Option.none() }).pipe(
118
196
  Layer.provide(FetchHttpClient.layer)
119
197
  )
120
- const lm = LegacyMutation.Default.pipe(Layer.provide([FakeIntlLayer, FakeToastLayer]))
121
- const layers = Layer.mergeAll(CommanderLayer, WithToastLayer, FakeToastLayer, FakeIntlLayer, api, lm)
198
+ const layers = Layer.mergeAll(CommanderLayer, WithToastLayer, FakeToastLayer, FakeIntlLayer, api)
122
199
 
123
200
  const clientFor_ = ApiClientFactory.makeFor(Layer.empty)
124
201
  return makeClient(() => ManagedRuntime.make(layers), clientFor_, Layer.empty)
package/tsconfig.json CHANGED
@@ -32,7 +32,6 @@
32
32
  "outDir": "build/dist",
33
33
  "resolveJsonModule": true,
34
34
  "moduleResolution": "Node16",
35
- "downlevelIteration": true,
36
35
  "noErrorTruncation": true,
37
36
  "forceConsistentCasingInFileNames": true,
38
37
  "types": [
package/tsconfig.json.bak CHANGED
@@ -8,5 +8,5 @@
8
8
  {
9
9
  "path": "./tsconfig.test.json"
10
10
  }
11
- ],
12
- }
11
+ ]
12
+ }
package/tsconfig.src.json CHANGED
@@ -1,36 +1,36 @@
1
1
  {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "lib": [
5
- "esnext",
6
- "DOM"
7
- ],
8
- "tsBuildInfoFile": "./dist/.tsbuildinfo",
9
- "esModuleInterop": true,
10
- "rootDir": "./src",
11
- // keep in here, cause madge can't detect it from extended tsconfig
12
- "moduleResolution": "Node16",
13
- "outDir": "./dist"
14
- },
15
- "include": [
16
- "./src/**/*.ts"
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "lib": [
5
+ "esnext",
6
+ "DOM"
17
7
  ],
18
- "exclude": [
19
- "./dist",
20
- "*.test.ts",
21
- "node_modules",
22
- "build",
23
- "lib",
24
- "dist",
25
- "**/*.d.ts.map",
26
- ".git",
27
- ".data",
28
- "**/.*",
29
- "**/*.tmp"
30
- ],
31
- "references": [
32
- {
33
- "path": "../effect-app"
34
- }
35
- ]
36
- }
8
+ "tsBuildInfoFile": "./dist/.tsbuildinfo",
9
+ "esModuleInterop": true,
10
+ "rootDir": "./src",
11
+ // keep in here, cause madge can't detect it from extended tsconfig
12
+ "moduleResolution": "Node16",
13
+ "outDir": "./dist"
14
+ },
15
+ "include": [
16
+ "./src/**/*.ts"
17
+ ],
18
+ "exclude": [
19
+ "./dist",
20
+ "*.test.ts",
21
+ "node_modules",
22
+ "build",
23
+ "lib",
24
+ "dist",
25
+ "**/*.d.ts.map",
26
+ ".git",
27
+ ".data",
28
+ "**/.*",
29
+ "**/*.tmp"
30
+ ],
31
+ "references": [
32
+ {
33
+ "path": "../effect-app"
34
+ }
35
+ ]
36
+ }
@@ -28,6 +28,6 @@
28
28
  "references": [
29
29
  {
30
30
  "path": "./tsconfig.src.json"
31
- },
31
+ }
32
32
  ]
33
- }
33
+ }
package/vitest.config.ts CHANGED
@@ -1,18 +1,18 @@
1
1
  /// <reference types="vitest" />
2
+ import vue from "@vitejs/plugin-vue"
2
3
  import { defineConfig } from "vitest/config"
3
- import vue from '@vitejs/plugin-vue'
4
4
  import makeConfig from "../../vite.config.base"
5
5
 
6
6
  export default defineConfig({
7
7
  ...makeConfig(__dirname),
8
8
  plugins: [vue()],
9
9
  test: {
10
- environment: 'jsdom',
11
- include: ['src/**/*.test.{ts,tsx}', '**/test/**/*.test.{ts,tsx}', '**/__tests__/**/*.test.{ts,tsx}'],
12
- exclude: ['node_modules/**', 'dist/**'],
10
+ environment: "jsdom",
11
+ include: ["src/**/*.test.{ts,tsx}", "**/test/**/*.test.{ts,tsx}", "**/__tests__/**/*.test.{ts,tsx}"],
12
+ exclude: ["node_modules/**", "dist/**"],
13
13
  globals: true
14
14
  },
15
15
  optimizeDeps: {
16
- exclude: ['**/__tests__/**', '**/test/**', '**/*.test.*']
16
+ exclude: ["**/__tests__/**", "**/test/**", "**/*.test.*"]
17
17
  }
18
18
  })