@effect-app/vue 1.20.8 → 1.21.1

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.
@@ -0,0 +1,499 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { flow, pipe, tuple } from "@effect-app/core/Function"
3
+ import { type MutationResult, Result, useSafeMutation } from "@effect-app/vue"
4
+ import * as Sentry from "@sentry/browser"
5
+ import { type MaybeRefOrGetter, type Pausable, useIntervalFn, type UseIntervalFnOptions } from "@vueuse/core"
6
+ import type { Either } from "effect-app"
7
+ import { Array, Cause, Effect, Match, Option, Runtime, S } from "effect-app"
8
+ import { type ApiConfig, type SupportedErrors } from "effect-app/client"
9
+ import type { HttpClient } from "effect-app/http"
10
+ import { Failure, Success } from "effect-app/Operations"
11
+ import { computed, type ComputedRef } from "vue"
12
+ import type { MakeIntlReturn } from "./makeIntl.js"
13
+
14
+ /**
15
+ * Use this after handling an error yourself, still continueing on the Error track, but the error will not be reported.
16
+ */
17
+ export class SuppressErrors extends Cause.YieldableError {
18
+ readonly _tag = "SuppressErrors"
19
+ }
20
+
21
+ type ResErrors = S.ParseResult.ParseError | SupportedErrors | SuppressErrors
22
+
23
+ export function pauseWhileProcessing(
24
+ iv: Pausable,
25
+ pmf: () => Promise<unknown>
26
+ ) {
27
+ return Promise
28
+ .resolve(iv.pause())
29
+ .then(() => pmf())
30
+ .finally(() => iv.resume())
31
+ }
32
+
33
+ export function useIntervalPauseWhileProcessing(
34
+ pmf: () => Promise<unknown>,
35
+ interval?: MaybeRefOrGetter<number>,
36
+ options?: Omit<UseIntervalFnOptions, "immediateCallback">
37
+ ) {
38
+ const iv = useIntervalFn(
39
+ () => pauseWhileProcessing(iv, pmf),
40
+ interval,
41
+ options ? { ...options, immediateCallback: false } : options
42
+ )
43
+ return {
44
+ isActive: iv.isActive
45
+ }
46
+ }
47
+
48
+ interface Opts<A> {
49
+ suppressErrorToast?: boolean
50
+ suppressSuccessToast?: boolean
51
+ successToast?: (a: A) => any
52
+ }
53
+ export const useSafeMutationWithState = <I, E, A>(self: {
54
+ handler: (i: I) => Effect<A, E, ApiConfig | HttpClient.HttpClient>
55
+ name: string
56
+ }) => {
57
+ const [a, b] = useSafeMutation(self)
58
+
59
+ return tuple(
60
+ computed(() => mutationResultToVue(a.value)),
61
+ b
62
+ )
63
+ }
64
+
65
+ export const withSuccess: {
66
+ <I, E extends ResErrors, A, X>(
67
+ self: {
68
+ handler: (i: I) => Effect<A, E, ApiConfig | HttpClient.HttpClient>
69
+ name: string
70
+ },
71
+ onSuccess: (a: A, i: I) => Promise<X>
72
+ ): {
73
+ handler: (i: I) => Effect<X, E, ApiConfig | HttpClient.HttpClient>
74
+ name: string
75
+ }
76
+ <E extends ResErrors, A, X>(
77
+ self: {
78
+ handler: Effect<A, E, ApiConfig | HttpClient.HttpClient>
79
+ name: string
80
+ },
81
+ onSuccess: (_: A) => Promise<X>
82
+ ): {
83
+ handler: Effect<X, E, ApiConfig | HttpClient.HttpClient>
84
+ name: string
85
+ }
86
+ } = (self: any, onSuccess: any): any => ({
87
+ ...self,
88
+ handler: typeof self.handler === "function"
89
+ ? (i: any) =>
90
+ pipe(
91
+ (
92
+ self.handler as (
93
+ i: any
94
+ ) => Effect<any, any, ApiConfig | HttpClient.HttpClient>
95
+ )(i),
96
+ Effect.flatMap((_) => Effect.promise(() => onSuccess(_, i)))
97
+ )
98
+ : Effect.flatMap(self.handler, (_) => Effect.promise(() => onSuccess(_)))
99
+ })
100
+
101
+ export const withSuccessE: {
102
+ <I, E extends ResErrors, A, E2, X>(
103
+ self: {
104
+ handler: (i: I) => Effect<A, E, ApiConfig | HttpClient.HttpClient>
105
+ name: string
106
+ },
107
+ onSuccessE: (_: A, i: I) => Effect<X, E2>
108
+ ): {
109
+ handler: (i: I) => Effect<X, E | E2, ApiConfig | HttpClient.HttpClient>
110
+ name: string
111
+ }
112
+ <E extends ResErrors, A, E2, X>(
113
+ self: {
114
+ handler: Effect<A, E, ApiConfig | HttpClient.HttpClient>
115
+ name: string
116
+ },
117
+ onSuccessE: (_: A) => Effect<X, E2>
118
+ ): {
119
+ handler: Effect<X, E | E2, ApiConfig | HttpClient.HttpClient>
120
+ name: string
121
+ }
122
+ } = (self: any, onSuccessE: any): any => {
123
+ return {
124
+ ...self,
125
+ handler: typeof self.handler === "function"
126
+ ? (i: any) =>
127
+ pipe(
128
+ self.handler(i),
129
+ Effect.flatMap((_) => onSuccessE(_, i))
130
+ )
131
+ : Effect.flatMap(self.handler, (_) => onSuccessE(_))
132
+ }
133
+ }
134
+
135
+ interface Res<A, E> {
136
+ readonly loading: boolean
137
+ readonly data: A | undefined
138
+ readonly error: E | undefined
139
+ }
140
+
141
+ type WithAction<A> = A & {
142
+ action: string
143
+ }
144
+
145
+ // computed() takes a getter function and returns a readonly reactive ref
146
+ // object for the returned value from the getter.
147
+ type Resp<I, E, A> = readonly [
148
+ ComputedRef<Res<A, E>>,
149
+ WithAction<(I: I) => Promise<void>>
150
+ ]
151
+
152
+ type ActResp<E, A> = readonly [
153
+ ComputedRef<Res<A, E>>,
154
+ WithAction<() => Promise<void>>
155
+ ]
156
+ function mutationResultToVue<A, E>(
157
+ mutationResult: MutationResult<A, E>
158
+ ): Res<A, E> {
159
+ switch (mutationResult._tag) {
160
+ case "Loading": {
161
+ return { loading: true, data: undefined, error: undefined }
162
+ }
163
+ case "Success": {
164
+ return {
165
+ loading: false,
166
+ data: mutationResult.data,
167
+ error: undefined
168
+ }
169
+ }
170
+ case "Error": {
171
+ return {
172
+ loading: false,
173
+ data: undefined,
174
+ error: mutationResult.error
175
+ }
176
+ }
177
+ case "Initial": {
178
+ return { loading: false, data: undefined, error: undefined }
179
+ }
180
+ }
181
+ }
182
+
183
+ const messages: Record<string, string | undefined> = {}
184
+
185
+ export const makeClient = <Locale extends string>(
186
+ makeUseIntl: MakeIntlReturn<Locale>,
187
+ useToast: () => {
188
+ error: (message: string) => void
189
+ warning: (message: string) => void
190
+ success: (message: string) => void
191
+ }
192
+ ) => {
193
+ const { useIntl } = makeUseIntl
194
+ const toast = useToast()
195
+ const { intl } = useIntl()
196
+ /**
197
+ * Pass a function that returns a Promise.
198
+ * Returns an execution function which reports errors as Toast.
199
+ */
200
+ function handleRequestWithToast<
201
+ E extends ResErrors,
202
+ A,
203
+ Args extends unknown[]
204
+ >(
205
+ f: (...args: Args) => Promise<Either<A, E>>,
206
+ action: string,
207
+ options: Opts<A> = { suppressErrorToast: false }
208
+ ) {
209
+ const message = messages[action] ?? action
210
+ const warnMessage = intl.value.formatMessage(
211
+ { id: "handle.with_warnings" },
212
+ { action: message }
213
+ )
214
+ const successMessage = intl.value.formatMessage(
215
+ { id: "handle.success" },
216
+ { action: message }
217
+ )
218
+ const errorMessage = intl.value.formatMessage(
219
+ { id: "handle.with_errors" },
220
+ { action: message }
221
+ )
222
+ return Object.assign(
223
+ flow(f, (p) =>
224
+ p.then(
225
+ (r) =>
226
+ r._tag === "Right"
227
+ ? S.is(Failure)(r.right)
228
+ ? Promise
229
+ .resolve(
230
+ toast.warning(
231
+ warnMessage + r.right.message
232
+ ? "\n" + r.right.message
233
+ : ""
234
+ )
235
+ )
236
+ .then((_) => {})
237
+ : Promise
238
+ .resolve(
239
+ toast.success(
240
+ successMessage
241
+ + (S.is(Success)(r.right) && r.right.message
242
+ ? "\n" + r.right.message
243
+ : "")
244
+ )
245
+ )
246
+ .then((_) => {})
247
+ : r.left._tag === "SuppressErrors"
248
+ ? Promise.resolve(void 0)
249
+ : Promise
250
+ .resolve(
251
+ !options.suppressErrorToast
252
+ && toast.error(`${errorMessage}:\n` + renderError(r.left))
253
+ )
254
+ .then((_) => {
255
+ console.warn(r.left, r.left.toString())
256
+ }),
257
+ (err) => {
258
+ if (
259
+ Cause.isInterruptedException(err)
260
+ || (Runtime.isFiberFailure(err)
261
+ && Cause.isInterruptedOnly(err[Runtime.FiberFailureCauseId]))
262
+ ) {
263
+ return
264
+ }
265
+ const extra = {
266
+ action,
267
+ message: `Unexpected Error trying to ${action}`
268
+ }
269
+ Sentry.captureException(err, {
270
+ extra
271
+ })
272
+ console.error(err, extra)
273
+
274
+ return toast.error(
275
+ intl.value.formatMessage(
276
+ { id: "handle.unexpected_error" },
277
+ {
278
+ action: message,
279
+ error: JSON.stringify(err, undefined, 2)
280
+ }
281
+ )
282
+ )
283
+ }
284
+ )),
285
+ { action }
286
+ )
287
+ }
288
+
289
+ function renderError(e: ResErrors): string {
290
+ return Match.value(e).pipe(
291
+ Match.tags({
292
+ // HttpErrorRequest: e =>
293
+ // intl.value.formatMessage(
294
+ // { id: "handle.request_error" },
295
+ // { error: `${e.error}` },
296
+ // ),
297
+ // HttpErrorResponse: e =>
298
+ // e.response.status >= 500 ||
299
+ // e.response.body._tag !== "Some" ||
300
+ // !e.response.body.value
301
+ // ? intl.value.formatMessage(
302
+ // { id: "handle.error_response" },
303
+ // {
304
+ // error: `${
305
+ // e.response.body._tag === "Some" && e.response.body.value
306
+ // ? parseError(e.response.body.value)
307
+ // : "Unknown"
308
+ // } (${e.response.status})`,
309
+ // },
310
+ // )
311
+ // : intl.value.formatMessage(
312
+ // { id: "handle.unexpected_error" },
313
+ // {
314
+ // error:
315
+ // JSON.stringify(e.response.body, undefined, 2) +
316
+ // "( " +
317
+ // e.response.status +
318
+ // ")",
319
+ // },
320
+ // ),
321
+ // ResponseError: e =>
322
+ // intl.value.formatMessage(
323
+ // { id: "handle.response_error" },
324
+ // { error: `${e.error}` },
325
+ // ),
326
+ ParseError: (e) => {
327
+ console.warn(e.toString())
328
+ return intl.value.formatMessage({ id: "validation.failed" })
329
+ }
330
+ }),
331
+ Match.orElse((e) =>
332
+ intl.value.formatMessage(
333
+ { id: "handle.unexpected_error" },
334
+ {
335
+ error: `${e.message ?? e._tag ?? e}`
336
+ }
337
+ )
338
+ )
339
+ )
340
+ }
341
+
342
+ /**
343
+ * Pass a function that returns an Effect, e.g from a client action, give it a name, and optionally pass an onSuccess callback.
344
+ * Returns a tuple with state ref and execution function which reports errors as Toast.
345
+ */
346
+ const useAndHandleMutation: {
347
+ <I, E extends ResErrors, A>(
348
+ self: {
349
+ handler: (i: I) => Effect<A, E, ApiConfig | HttpClient.HttpClient>
350
+ name: string
351
+ },
352
+ action: string,
353
+ options?: Opts<A>
354
+ ): Resp<I, E, A>
355
+ <E extends ResErrors, A>(
356
+ self: {
357
+ handler: Effect<A, E, ApiConfig | HttpClient.HttpClient>
358
+ name: string
359
+ },
360
+ action: string,
361
+ options?: Opts<A>
362
+ ): ActResp<E, A>
363
+ } = (self: any, action: any, options: any) => {
364
+ const [a, b] = useSafeMutation({
365
+ handler: Effect.isEffect(self.handler)
366
+ ? (pipe(
367
+ self.handler,
368
+ Effect.withSpan("mutation", { attributes: { action } })
369
+ ) as any)
370
+ : (...args: any[]) =>
371
+ pipe(
372
+ self.handler(...args),
373
+ Effect.withSpan("mutation", { attributes: { action } })
374
+ ),
375
+ name: self.name
376
+ })
377
+
378
+ return tuple(
379
+ computed(() => mutationResultToVue(a.value)),
380
+ handleRequestWithToast(b as any, action, options)
381
+ )
382
+ }
383
+
384
+ function makeUseAndHandleMutation(onSuccess: () => Promise<void>) {
385
+ return ((self: any, action: any, options: any) => {
386
+ return useAndHandleMutation(
387
+ {
388
+ handler: (typeof self.handler === "function"
389
+ ? (i: any) => Effect.tap(self.handler(i), () => Effect.promise(onSuccess))
390
+ : Effect.tap(self.handler, () => Effect.promise(onSuccess))) as any,
391
+ name: self.name
392
+ },
393
+ action,
394
+ options
395
+ )
396
+ }) as {
397
+ <I, E extends ResErrors, A>(
398
+ self: {
399
+ handler: (i: I) => Effect<A, E, ApiConfig | HttpClient.HttpClient>
400
+ name: string
401
+ },
402
+ action: string,
403
+ options?: Opts<A>
404
+ ): Resp<I, E, A>
405
+ <E extends ResErrors, A>(
406
+ self: {
407
+ handler: Effect<A, E, ApiConfig | HttpClient.HttpClient>
408
+ name: string
409
+ },
410
+ action: string,
411
+ options?: Opts<A>
412
+ ): ActResp<E, A>
413
+ }
414
+ }
415
+
416
+ return {
417
+ useAndHandleMutation,
418
+ makeUseAndHandleMutation,
419
+ handleRequestWithToast
420
+ }
421
+ }
422
+
423
+ export const mapHandler: {
424
+ <I, E, R, A, E2, A2, R2>(
425
+ self: {
426
+ handler: (i: I) => Effect<A, E, R>
427
+ name: string
428
+ mapPath: (i: I) => string
429
+ },
430
+ map: (i: I) => (handler: Effect<A, E, R>) => Effect<A2, E2, R2>
431
+ ): {
432
+ handler: (i: I) => Effect<A2, E2, R2>
433
+ name: string
434
+ mapPath: (i: I) => string
435
+ }
436
+ <E, A, R, E2, A2, R2>(
437
+ self: {
438
+ handler: Effect<A, E, R>
439
+ name: string
440
+ mapPath: string
441
+ },
442
+ map: (handler: Effect<A, E, R>) => Effect<A2, E2, R2>
443
+ ): {
444
+ handler: Effect<A2, E2, R2>
445
+ name: string
446
+ mapPath: string
447
+ }
448
+ } = (self: any, map: any): any => ({
449
+ ...self,
450
+ handler: typeof self.handler === "function"
451
+ ? (i: any) => map(i)((self.handler as (i: any) => Effect<any, any, any>)(i))
452
+ : map(self.handler)
453
+ })
454
+
455
+ export function composeQueries<
456
+ R extends Record<string, Result.Result<any, any>>
457
+ >(
458
+ results: R,
459
+ renderPreviousOnFailure?: boolean
460
+ ): Result.Result<
461
+ {
462
+ [Property in keyof R]: R[Property] extends Result.Result<infer A, any> ? A
463
+ : never
464
+ },
465
+ {
466
+ [Property in keyof R]: R[Property] extends Result.Result<any, infer E> ? E
467
+ : never
468
+ }[keyof R]
469
+ > {
470
+ const values = renderPreviousOnFailure
471
+ ? Object.values(results).map(orPrevious)
472
+ : Object.values(results)
473
+ const error = values.find(Result.isFailure)
474
+ if (error) {
475
+ return error
476
+ }
477
+ const initial = Array.findFirst(values, (x) => x._tag === "Initial" ? Option.some(x) : Option.none())
478
+ if (initial.value !== undefined) {
479
+ return initial.value
480
+ }
481
+ const loading = Array.findFirst(values, (x) => Result.isInitial(x) && x.waiting ? Option.some(x) : Option.none())
482
+ if (loading.value !== undefined) {
483
+ return loading.value
484
+ }
485
+
486
+ const isRefreshing = values.some((x) => x.waiting)
487
+
488
+ const r = Object.entries(results).reduce((prev, [key, value]) => {
489
+ prev[key] = Result.value(value).value
490
+ return prev
491
+ }, {} as any)
492
+ return Result.success(r, isRefreshing)
493
+ }
494
+
495
+ function orPrevious<E, A>(result: Result.Result<A, E>) {
496
+ return Result.isFailure(result) && Option.isSome(result.previousValue)
497
+ ? Result.success(result.previousValue.value, result.waiting)
498
+ : result
499
+ }
@@ -0,0 +1,9 @@
1
+ import { inject, type InjectionKey, provide } from "vue"
2
+
3
+ export const makeContext = <T>(def: T) => {
4
+ const key = Symbol() as InjectionKey<T>
5
+ return {
6
+ use: () => inject(key, def),
7
+ provide: (locale: T) => provide(key, locale)
8
+ }
9
+ }
@@ -0,0 +1,60 @@
1
+ /* eslint-disable @typescript-eslint/no-empty-object-type */
2
+ import { createIntl, createIntlCache, type IntlShape } from "@formatjs/intl"
3
+ import { typedKeysOf } from "effect-app/utils"
4
+ import type { FormatXMLElementFn, PrimitiveType } from "intl-messageformat"
5
+ import type { Ref } from "vue"
6
+ import { computed, ref, watch } from "vue"
7
+ import { translate } from "./form.js"
8
+ import { makeContext } from "./makeContext.js"
9
+
10
+ export interface MakeIntlReturn<Locale extends string> extends ReturnType<typeof makeIntl<Locale>> {}
11
+
12
+ export const makeIntl = <Locale extends string>(
13
+ messages: Record<Locale, Record<string, string>>,
14
+ defaultLocale: NoInfer<Locale>
15
+ ) => {
16
+ const intlCache = createIntlCache()
17
+
18
+ const intls = typedKeysOf(messages).reduce(
19
+ (acc, cur) => {
20
+ acc[cur] = createIntl<Locale>(
21
+ {
22
+ defaultLocale,
23
+ locale: cur,
24
+ messages: messages[cur]
25
+ },
26
+ intlCache
27
+ )
28
+ return acc
29
+ },
30
+ {} as Record<Locale, IntlShape<Locale>>
31
+ )
32
+
33
+ const LocaleContext = makeContext(ref<Locale>(defaultLocale) as Ref<Locale>)
34
+
35
+ const useIntl = () => {
36
+ const locale = LocaleContext.use()
37
+
38
+ const trans = (
39
+ id: keyof (typeof messages)[Locale],
40
+ values?: Record<
41
+ string,
42
+ PrimitiveType | FormatXMLElementFn<string, string>
43
+ >
44
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
45
+ ) => intls[locale.value].formatMessage({ id: id as any }, values)
46
+
47
+ const intl = computed(() => intls[locale.value])
48
+ watch(
49
+ locale,
50
+ (locale) => {
51
+ const intl = intls[locale]
52
+ translate.value = intl.formatMessage
53
+ },
54
+ { immediate: true }
55
+ )
56
+
57
+ return { locale, trans, intl }
58
+ }
59
+ return { useIntl, LocaleContext }
60
+ }
@@ -0,0 +1,37 @@
1
+ // packages/vue/vitest.config.ts
2
+ import { defineConfig } from "file:///Users/patrickroza/pj/effect-app/libs/node_modules/.pnpm/vite@5.2.6_@types+node@20.11.30/node_modules/vite/dist/node/index.js";
3
+
4
+ // vite.config.base.ts
5
+ import path from "path";
6
+ import fs from "fs";
7
+ var __vite_injected_original_dirname = "/Users/patrickroza/pj/effect-app/libs";
8
+ function makeConfig(dirName) {
9
+ const prefix = path.resolve(__vite_injected_original_dirname, "packages");
10
+ const packages = fs.readdirSync(prefix).map((f) => prefix + "/" + f).filter((f) => fs.lstatSync(f).isDirectory());
11
+ const cfg = {
12
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
13
+ //plugins: [autoImport],
14
+ test: {
15
+ include: ["./test/**/*.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
16
+ reporters: "verbose",
17
+ globals: true
18
+ },
19
+ resolve: {
20
+ alias: packages.reduce((acc, cur) => {
21
+ acc[JSON.parse(fs.readFileSync(cur + "/package.json", "utf-8")).name] = path.resolve(cur, cur.endsWith("core") ? "dist" : "src");
22
+ return acc;
23
+ }, {})
24
+ // "@effect-app/core/Prelude": path.join(__dirname, "packages/core/src/Prelude.code.ts")
25
+ }
26
+ };
27
+ console.log(cfg);
28
+ return cfg;
29
+ }
30
+
31
+ // packages/vue/vitest.config.ts
32
+ var __vite_injected_original_dirname2 = "/Users/patrickroza/pj/effect-app/libs/packages/vue";
33
+ var vitest_config_default = defineConfig(makeConfig(__vite_injected_original_dirname2));
34
+ export {
35
+ vitest_config_default as default
36
+ };
37
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsicGFja2FnZXMvdnVlL3ZpdGVzdC5jb25maWcudHMiLCAidml0ZS5jb25maWcuYmFzZS50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIi9Vc2Vycy9wYXRyaWNrcm96YS9wai9lZmZlY3QtYXBwL2xpYnMvcGFja2FnZXMvdnVlXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCIvVXNlcnMvcGF0cmlja3JvemEvcGovZWZmZWN0LWFwcC9saWJzL3BhY2thZ2VzL3Z1ZS92aXRlc3QuY29uZmlnLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9Vc2Vycy9wYXRyaWNrcm96YS9wai9lZmZlY3QtYXBwL2xpYnMvcGFja2FnZXMvdnVlL3ZpdGVzdC5jb25maWcudHNcIjsvLy8gPHJlZmVyZW5jZSB0eXBlcz1cInZpdGVzdFwiIC8+XG5pbXBvcnQgeyBkZWZpbmVDb25maWcgfSBmcm9tIFwidml0ZVwiXG5pbXBvcnQgbWFrZUNvbmZpZyBmcm9tIFwiLi4vLi4vdml0ZS5jb25maWcuYmFzZVwiXG5cbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZyhtYWtlQ29uZmlnKF9fZGlybmFtZSkpXG4iLCAiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIi9Vc2Vycy9wYXRyaWNrcm96YS9wai9lZmZlY3QtYXBwL2xpYnNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9Vc2Vycy9wYXRyaWNrcm96YS9wai9lZmZlY3QtYXBwL2xpYnMvdml0ZS5jb25maWcuYmFzZS50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vVXNlcnMvcGF0cmlja3JvemEvcGovZWZmZWN0LWFwcC9saWJzL3ZpdGUuY29uZmlnLmJhc2UudHNcIjsvLy8gPHJlZmVyZW5jZSB0eXBlcz1cInZpdGVzdFwiIC8+XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiXG5pbXBvcnQgZnMgZnJvbSBcImZzXCJcbmltcG9ydCBBdXRvSW1wb3J0IGZyb20gXCJ1bnBsdWdpbi1hdXRvLWltcG9ydC92aXRlXCJcbmltcG9ydCB7IGRlZmluZUNvbmZpZyB9IGZyb20gXCJ2aXRlc3QvY29uZmlnXCJcblxuLy8gY29uc3QgYXV0b0ltcG9ydCA9IEF1dG9JbXBvcnQoe1xuLy8gICBkdHM6IFwiLi90ZXN0L2F1dG8taW1wb3J0cy5kLnRzXCIsXG4vLyAgIC8vIGluY2x1ZGU6IFtcbi8vICAgLy8gICAvXFwudGVzdFxcLlt0al1zeD8kLyAvLyAudHMsIC50c3gsIC5qcywgLmpzeFxuLy8gICAvLyBdLFxuLy8gICBpbXBvcnRzOiBbXG4vLyAgICAgXCJ2aXRlc3RcIlxuLy8gICBdXG4vLyB9KVxuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBtYWtlQ29uZmlnKGRpck5hbWU/OiBzdHJpbmcpIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgXCJwYWNrYWdlc1wiKVxuICBjb25zdCBwYWNrYWdlcyA9IGZzLnJlYWRkaXJTeW5jKHByZWZpeCkubWFwKGYgPT4gcHJlZml4ICsgXCIvXCIgKyBmKS5maWx0ZXIoZiA9PiBmcy5sc3RhdFN5bmMoZikuaXNEaXJlY3RvcnkoKSApXG4gIGNvbnN0IGNmZyA9IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlc1xuICAgIC8vcGx1Z2luczogW2F1dG9JbXBvcnRdLFxuICAgIHRlc3Q6IHtcbiAgICAgIGluY2x1ZGU6ICBbXCIuL3Rlc3QvKiovKi50ZXN0LntqcyxtanMsY2pzLHRzLG10cyxjdHMsanN4LHRzeH1cIl0sXG4gICAgICByZXBvcnRlcnM6IFwidmVyYm9zZVwiLFxuICAgICAgZ2xvYmFsczogdHJ1ZVxuICAgIH0sXG4gICAgcmVzb2x2ZToge1xuICAgICAgYWxpYXM6IHBhY2thZ2VzLnJlZHVjZSgoYWNjLCBjdXIpID0+IHsgLy8gd29ya2Fyb3VuZCBmb3IgL1ByZWx1ZGUgaXNzdWVcbiAgICAgIGFjY1tKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhjdXIgKyBcIi9wYWNrYWdlLmpzb25cIiwgXCJ1dGYtOFwiKSkubmFtZV0gPSBwYXRoLnJlc29sdmUoY3VyLCBjdXIuZW5kc1dpdGgoXCJjb3JlXCIpID8gXCJkaXN0XCIgOiBcInNyY1wiKVxuICAgICAgcmV0dXJuIGFjY1xuICAgIH0sIHsgfSkgLy8gXCJAZWZmZWN0LWFwcC9jb3JlL1ByZWx1ZGVcIjogcGF0aC5qb2luKF9fZGlybmFtZSwgXCJwYWNrYWdlcy9jb3JlL3NyYy9QcmVsdWRlLmNvZGUudHNcIilcbiAgfVxuICB9XG4gIGNvbnNvbGUubG9nKGNmZylcbiAgcmV0dXJuIGNmZ1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUNBLFNBQVMsb0JBQW9COzs7QUNBN0IsT0FBTyxVQUFVO0FBQ2pCLE9BQU8sUUFBUTtBQUZmLElBQU0sbUNBQW1DO0FBZ0IxQixTQUFSLFdBQTRCLFNBQWtCO0FBQ25ELFFBQU0sU0FBUyxLQUFLLFFBQVEsa0NBQVcsVUFBVTtBQUNqRCxRQUFNLFdBQVcsR0FBRyxZQUFZLE1BQU0sRUFBRSxJQUFJLE9BQUssU0FBUyxNQUFNLENBQUMsRUFBRSxPQUFPLE9BQUssR0FBRyxVQUFVLENBQUMsRUFBRSxZQUFZLENBQUU7QUFDN0csUUFBTSxNQUFNO0FBQUE7QUFBQTtBQUFBLElBR1YsTUFBTTtBQUFBLE1BQ0osU0FBVSxDQUFDLGtEQUFrRDtBQUFBLE1BQzdELFdBQVc7QUFBQSxNQUNYLFNBQVM7QUFBQSxJQUNYO0FBQUEsSUFDQSxTQUFTO0FBQUEsTUFDUCxPQUFPLFNBQVMsT0FBTyxDQUFDLEtBQUssUUFBUTtBQUNyQyxZQUFJLEtBQUssTUFBTSxHQUFHLGFBQWEsTUFBTSxpQkFBaUIsT0FBTyxDQUFDLEVBQUUsSUFBSSxJQUFJLEtBQUssUUFBUSxLQUFLLElBQUksU0FBUyxNQUFNLElBQUksU0FBUyxLQUFLO0FBQy9ILGVBQU87QUFBQSxNQUNULEdBQUcsQ0FBRSxDQUFDO0FBQUE7QUFBQSxJQUNSO0FBQUEsRUFDQTtBQUNBLFVBQVEsSUFBSSxHQUFHO0FBQ2YsU0FBTztBQUNUOzs7QURwQ0EsSUFBTUEsb0NBQW1DO0FBSXpDLElBQU8sd0JBQVEsYUFBYSxXQUFXQyxpQ0FBUyxDQUFDOyIsCiAgIm5hbWVzIjogWyJfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSIsICJfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSJdCn0K
@@ -0,0 +1,37 @@
1
+ // packages/vue/vitest.config.ts
2
+ import { defineConfig } from "file:///Users/patrickroza/pj/effect-app/libs/node_modules/.pnpm/vite@5.2.6_@types+node@20.11.30/node_modules/vite/dist/node/index.js";
3
+
4
+ // vite.config.base.ts
5
+ import path from "path";
6
+ import fs from "fs";
7
+ var __vite_injected_original_dirname = "/Users/patrickroza/pj/effect-app/libs";
8
+ function makeConfig(dirName) {
9
+ const prefix = path.resolve(__vite_injected_original_dirname, "packages");
10
+ const packages = fs.readdirSync(prefix).map((f) => prefix + "/" + f).filter((f) => fs.lstatSync(f).isDirectory());
11
+ const cfg = {
12
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
13
+ //plugins: [autoImport],
14
+ test: {
15
+ include: ["./test/**/*.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
16
+ reporters: "verbose",
17
+ globals: true
18
+ },
19
+ resolve: {
20
+ alias: packages.reduce((acc, cur) => {
21
+ acc[JSON.parse(fs.readFileSync(cur + "/package.json", "utf-8")).name] = path.resolve(cur, cur.endsWith("core") ? "dist" : "src");
22
+ return acc;
23
+ }, {})
24
+ // "@effect-app/core/Prelude": path.join(__dirname, "packages/core/src/Prelude.code.ts")
25
+ }
26
+ };
27
+ console.log(cfg);
28
+ return cfg;
29
+ }
30
+
31
+ // packages/vue/vitest.config.ts
32
+ var __vite_injected_original_dirname2 = "/Users/patrickroza/pj/effect-app/libs/packages/vue";
33
+ var vitest_config_default = defineConfig(makeConfig(__vite_injected_original_dirname2));
34
+ export {
35
+ vitest_config_default as default
36
+ };
37
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsicGFja2FnZXMvdnVlL3ZpdGVzdC5jb25maWcudHMiLCAidml0ZS5jb25maWcuYmFzZS50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIi9Vc2Vycy9wYXRyaWNrcm96YS9wai9lZmZlY3QtYXBwL2xpYnMvcGFja2FnZXMvdnVlXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCIvVXNlcnMvcGF0cmlja3JvemEvcGovZWZmZWN0LWFwcC9saWJzL3BhY2thZ2VzL3Z1ZS92aXRlc3QuY29uZmlnLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9Vc2Vycy9wYXRyaWNrcm96YS9wai9lZmZlY3QtYXBwL2xpYnMvcGFja2FnZXMvdnVlL3ZpdGVzdC5jb25maWcudHNcIjsvLy8gPHJlZmVyZW5jZSB0eXBlcz1cInZpdGVzdFwiIC8+XG5pbXBvcnQgeyBkZWZpbmVDb25maWcgfSBmcm9tIFwidml0ZVwiXG5pbXBvcnQgbWFrZUNvbmZpZyBmcm9tIFwiLi4vLi4vdml0ZS5jb25maWcuYmFzZVwiXG5cbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZyhtYWtlQ29uZmlnKF9fZGlybmFtZSkpXG4iLCAiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIi9Vc2Vycy9wYXRyaWNrcm96YS9wai9lZmZlY3QtYXBwL2xpYnNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9Vc2Vycy9wYXRyaWNrcm96YS9wai9lZmZlY3QtYXBwL2xpYnMvdml0ZS5jb25maWcuYmFzZS50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vVXNlcnMvcGF0cmlja3JvemEvcGovZWZmZWN0LWFwcC9saWJzL3ZpdGUuY29uZmlnLmJhc2UudHNcIjsvLy8gPHJlZmVyZW5jZSB0eXBlcz1cInZpdGVzdFwiIC8+XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiXG5pbXBvcnQgZnMgZnJvbSBcImZzXCJcbmltcG9ydCBBdXRvSW1wb3J0IGZyb20gXCJ1bnBsdWdpbi1hdXRvLWltcG9ydC92aXRlXCJcbmltcG9ydCB7IGRlZmluZUNvbmZpZyB9IGZyb20gXCJ2aXRlc3QvY29uZmlnXCJcblxuLy8gY29uc3QgYXV0b0ltcG9ydCA9IEF1dG9JbXBvcnQoe1xuLy8gICBkdHM6IFwiLi90ZXN0L2F1dG8taW1wb3J0cy5kLnRzXCIsXG4vLyAgIC8vIGluY2x1ZGU6IFtcbi8vICAgLy8gICAvXFwudGVzdFxcLlt0al1zeD8kLyAvLyAudHMsIC50c3gsIC5qcywgLmpzeFxuLy8gICAvLyBdLFxuLy8gICBpbXBvcnRzOiBbXG4vLyAgICAgXCJ2aXRlc3RcIlxuLy8gICBdXG4vLyB9KVxuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBtYWtlQ29uZmlnKGRpck5hbWU/OiBzdHJpbmcpIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0aC5yZXNvbHZlKF9fZGlybmFtZSwgXCJwYWNrYWdlc1wiKVxuICBjb25zdCBwYWNrYWdlcyA9IGZzLnJlYWRkaXJTeW5jKHByZWZpeCkubWFwKGYgPT4gcHJlZml4ICsgXCIvXCIgKyBmKS5maWx0ZXIoZiA9PiBmcy5sc3RhdFN5bmMoZikuaXNEaXJlY3RvcnkoKSApXG4gIGNvbnN0IGNmZyA9IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlc1xuICAgIC8vcGx1Z2luczogW2F1dG9JbXBvcnRdLFxuICAgIHRlc3Q6IHtcbiAgICAgIGluY2x1ZGU6ICBbXCIuL3Rlc3QvKiovKi50ZXN0LntqcyxtanMsY2pzLHRzLG10cyxjdHMsanN4LHRzeH1cIl0sXG4gICAgICByZXBvcnRlcnM6IFwidmVyYm9zZVwiLFxuICAgICAgZ2xvYmFsczogdHJ1ZVxuICAgIH0sXG4gICAgcmVzb2x2ZToge1xuICAgICAgYWxpYXM6IHBhY2thZ2VzLnJlZHVjZSgoYWNjLCBjdXIpID0+IHsgLy8gd29ya2Fyb3VuZCBmb3IgL1ByZWx1ZGUgaXNzdWVcbiAgICAgIGFjY1tKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhjdXIgKyBcIi9wYWNrYWdlLmpzb25cIiwgXCJ1dGYtOFwiKSkubmFtZV0gPSBwYXRoLnJlc29sdmUoY3VyLCBjdXIuZW5kc1dpdGgoXCJjb3JlXCIpID8gXCJkaXN0XCIgOiBcInNyY1wiKVxuICAgICAgcmV0dXJuIGFjY1xuICAgIH0sIHsgfSkgLy8gXCJAZWZmZWN0LWFwcC9jb3JlL1ByZWx1ZGVcIjogcGF0aC5qb2luKF9fZGlybmFtZSwgXCJwYWNrYWdlcy9jb3JlL3NyYy9QcmVsdWRlLmNvZGUudHNcIilcbiAgfVxuICB9XG4gIGNvbnNvbGUubG9nKGNmZylcbiAgcmV0dXJuIGNmZ1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUNBLFNBQVMsb0JBQW9COzs7QUNBN0IsT0FBTyxVQUFVO0FBQ2pCLE9BQU8sUUFBUTtBQUZmLElBQU0sbUNBQW1DO0FBZ0IxQixTQUFSLFdBQTRCLFNBQWtCO0FBQ25ELFFBQU0sU0FBUyxLQUFLLFFBQVEsa0NBQVcsVUFBVTtBQUNqRCxRQUFNLFdBQVcsR0FBRyxZQUFZLE1BQU0sRUFBRSxJQUFJLE9BQUssU0FBUyxNQUFNLENBQUMsRUFBRSxPQUFPLE9BQUssR0FBRyxVQUFVLENBQUMsRUFBRSxZQUFZLENBQUU7QUFDN0csUUFBTSxNQUFNO0FBQUE7QUFBQTtBQUFBLElBR1YsTUFBTTtBQUFBLE1BQ0osU0FBVSxDQUFDLGtEQUFrRDtBQUFBLE1BQzdELFdBQVc7QUFBQSxNQUNYLFNBQVM7QUFBQSxJQUNYO0FBQUEsSUFDQSxTQUFTO0FBQUEsTUFDUCxPQUFPLFNBQVMsT0FBTyxDQUFDLEtBQUssUUFBUTtBQUNyQyxZQUFJLEtBQUssTUFBTSxHQUFHLGFBQWEsTUFBTSxpQkFBaUIsT0FBTyxDQUFDLEVBQUUsSUFBSSxJQUFJLEtBQUssUUFBUSxLQUFLLElBQUksU0FBUyxNQUFNLElBQUksU0FBUyxLQUFLO0FBQy9ILGVBQU87QUFBQSxNQUNULEdBQUcsQ0FBRSxDQUFDO0FBQUE7QUFBQSxJQUNSO0FBQUEsRUFDQTtBQUNBLFVBQVEsSUFBSSxHQUFHO0FBQ2YsU0FBTztBQUNUOzs7QURwQ0EsSUFBTUEsb0NBQW1DO0FBSXpDLElBQU8sd0JBQVEsYUFBYSxXQUFXQyxpQ0FBUyxDQUFDOyIsCiAgIm5hbWVzIjogWyJfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSIsICJfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSJdCn0K