@shivaedev/effect-test 0.1.3 → 0.3.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.
- package/CHANGELOG.md +13 -0
- package/README.md +25 -2
- package/dist/it.d.ts +3 -0
- package/dist/it.d.ts.map +1 -0
- package/dist/it.js +31 -0
- package/dist/it.js.map +1 -0
- package/dist/types.d.ts +18 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -9
- package/src/it.ts +45 -0
- package/src/types.ts +25 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -3
- package/dist/index.js.map +0 -1
- package/src/index.ts +0 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0 - 2026-10-05
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `@shivaedev/effect-test/it.ts` exports `it`: the `it` of `@effect/vitest`, whose `effect` and `live` testers also take a generator function and run it with `Effect.gen`, so a test reads `it.effect("loads the item", function* () { … })`. They take a function that returns an Effect as well, as `@effect/vitest`'s testers do, so a file switches its import without rewriting other tests. Each tester supports `each`, `fails`, `only`, `runIf`, `skip` and `skipIf`, runs the body in a Scope, and types the yielded values, failures and requirements: a body that needs a service the test does not provide does not type-check. `effect` installs the test services, such as TestClock; `live` uses the live ones. The types are `EffectIt`, `EffectItTest` and `EffectItTester` in `@shivaedev/effect-test/types.ts`.
|
|
8
|
+
|
|
9
|
+
## 0.2.0 - 2026-10-04
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Breaking: no root entry and no module that re-exports another. `exports` maps one `"./*.ts"` pattern to every module (`src` under the `source` condition, `dist` otherwise), so you import the module that defines a name, and a bundler sees only the modules you use. Where each name now lives:
|
|
14
|
+
- `@shivaedev/effect-test`: `@shivaedev/effect-test/eventually.ts` (`EventuallyOptions`, `eventually`), `@shivaedev/effect-test/types.ts` (`EffectClock`, `EffectTest`, `EffectTester`, `EffectTestOptions`, `MakeEffectItOptions`, `MakeEffectItResult`), `@shivaedev/effect-test/vitest.ts` (`makeEffectIt`)
|
|
15
|
+
|
|
3
16
|
## 0.1.3 - 2026-10-04
|
|
4
17
|
|
|
5
18
|
### Changed
|
package/README.md
CHANGED
|
@@ -17,11 +17,34 @@ built for ShivaeDev applications and may change without a deprecation period.
|
|
|
17
17
|
pnpm add --save-dev @shivaedev/effect-test @effect/vitest effect vitest
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
+
## `it`
|
|
21
|
+
|
|
22
|
+
`@shivaedev/effect-test/it.ts` exports the `it` of `@effect/vitest`, whose `effect` and `live`
|
|
23
|
+
testers also take the generator itself and run it with `Effect.gen`:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { it } from "@shivaedev/effect-test/it.ts"
|
|
27
|
+
|
|
28
|
+
it.effect("starts at time zero", function* ({ task }) {
|
|
29
|
+
expect(yield* Clock.currentTimeMillis).toBe(0)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it.live("waits on the real clock", function* () {
|
|
33
|
+
yield* Effect.sleep("10 millis")
|
|
34
|
+
})
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The body receives the Vitest test context; destructure what it reads. `effect`
|
|
38
|
+
installs TestClock and the other test services, `live` keeps the live ones, and
|
|
39
|
+
each runs the body in a Scope. A function that returns an Effect works as well,
|
|
40
|
+
as with `@effect/vitest`. Each tester supports `each`, `fails`, `only`, `runIf`,
|
|
41
|
+
`skip` and `skipIf`; an `each` body receives the table case.
|
|
42
|
+
|
|
20
43
|
## `makeEffectIt`
|
|
21
44
|
|
|
22
45
|
```ts
|
|
23
46
|
import { Layer } from "effect"
|
|
24
|
-
import { makeEffectIt } from "@shivaedev/effect-test"
|
|
47
|
+
import { makeEffectIt } from "@shivaedev/effect-test/vitest.ts"
|
|
25
48
|
|
|
26
49
|
const { effectApp } = makeEffectIt({
|
|
27
50
|
layer: TestLive,
|
|
@@ -74,7 +97,7 @@ retrying under either clock. Use `Effect.try(() => expect(...))` when an
|
|
|
74
97
|
assertion failure is intentionally a retryable condition.
|
|
75
98
|
|
|
76
99
|
```ts
|
|
77
|
-
import { eventually } from "@shivaedev/effect-test"
|
|
100
|
+
import { eventually } from "@shivaedev/effect-test/eventually.ts"
|
|
78
101
|
|
|
79
102
|
effectApp("sees a delayed write", function* ({ db }) {
|
|
80
103
|
const row = yield* eventually(db.Job.where({ id }).first(), {
|
package/dist/it.d.ts
ADDED
package/dist/it.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"it.d.ts","sourceRoot":"","sources":["../src/it.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAgC,MAAM,YAAY,CAAC;AAsCzE,eAAO,MAAM,EAAE,EAAE,QAGf,CAAC"}
|
package/dist/it.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { it as effectIt } from "@effect/vitest";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
function effectOf(body) {
|
|
4
|
+
return (...args) => {
|
|
5
|
+
const result = body(...args);
|
|
6
|
+
return Effect.isEffect(result) ? result : Effect.gen(() => result);
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function bodyTest(register) {
|
|
10
|
+
return (name, body, options) => register(name, effectOf(body), options);
|
|
11
|
+
}
|
|
12
|
+
function bodyTester(register) {
|
|
13
|
+
return Object.assign(bodyTest(register), {
|
|
14
|
+
each: (cases) => (name, body, options) => register.each(cases)(name, effectOf(body), options),
|
|
15
|
+
fails: bodyTest(register.fails),
|
|
16
|
+
only: bodyTest(register.only),
|
|
17
|
+
runIf: (condition) => bodyTest(register.runIf(condition)),
|
|
18
|
+
skip: bodyTest(register.skip),
|
|
19
|
+
skipIf: (condition) => bodyTest(register.skipIf(condition)),
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
const testers = {};
|
|
23
|
+
const vitestTests = new Proxy(effectIt, {
|
|
24
|
+
get: (target, key, receiver) => (Object.hasOwn(testers, key) ? testers[key] : Reflect.get(target, key, receiver)),
|
|
25
|
+
set: (_target, key, value) => Reflect.set(testers, key, value),
|
|
26
|
+
});
|
|
27
|
+
export const it = Object.assign(vitestTests, {
|
|
28
|
+
effect: bodyTester(effectIt.effect),
|
|
29
|
+
live: bodyTester(effectIt.live),
|
|
30
|
+
});
|
|
31
|
+
//# sourceMappingURL=it.js.map
|
package/dist/it.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"it.js","sourceRoot":"","sources":["../src/it.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,IAAI,QAAQ,EAAmD,MAAM,gBAAgB,CAAC;AACjG,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAQhC,SAAS,QAAQ,CAAsC,IAAoB;IAC1E,OAAO,CAAC,GAAG,IAAW,EAAsC,EAAE;QAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QAC7B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;IACpE,CAAC,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAI,QAAwB;IAC5C,OAAO,CAAC,IAAY,EAAE,IAAqC,EAAE,OAA8B,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;AACzI,CAAC;AAED,SAAS,UAAU,CAAI,QAA0B;IAChD,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;QACxC,IAAI,EACH,CAAQ,KAAuB,EAAkC,EAAE,CACnE,CAAC,IAAY,EAAE,IAA4B,EAAE,OAA8B,EAAE,EAAE,CAC9E,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;QACrD,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC/B,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC7B,KAAK,EAAE,CAAC,SAAkB,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAClE,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC7B,MAAM,EAAE,CAAC,SAAkB,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;KACpE,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,GAAiC,EAAE,CAAC;AAEjD,MAAM,WAAW,GAAG,IAAI,KAAK,CAAU,QAAQ,EAAE;IAChD,GAAG,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;IACjH,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC;CAC9D,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,EAAE,GAAa,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE;IACtD,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC;IACnC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;CAC/B,CAAC,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { TestContext, TestOptions } from "@effect/vitest";
|
|
2
|
-
import type { Effect, Layer } from "effect";
|
|
2
|
+
import type { Effect, Layer, Scope } from "effect";
|
|
3
|
+
import type { TestAPI } from "vitest";
|
|
3
4
|
import type { AnyTestLayer } from "./any-test-layer.ts";
|
|
4
5
|
export type EffectClock = "test" | "live";
|
|
5
6
|
export type EffectTestOptions = TestOptions & {
|
|
@@ -23,4 +24,20 @@ export interface MakeEffectItOptions<Harness, TestLayer extends AnyTestLayer> {
|
|
|
23
24
|
export interface MakeEffectItResult<Harness, Provided> {
|
|
24
25
|
readonly effectApp: EffectTester<Harness, Provided>;
|
|
25
26
|
}
|
|
27
|
+
export interface EffectItTest<R, TArgs extends readonly unknown[] = [context: TestContext]> {
|
|
28
|
+
<TEffect extends Effect.Effect<unknown, unknown, R>, A>(name: string, body: (...args: TArgs) => Generator<TEffect, A, never>, options?: number | TestOptions): void;
|
|
29
|
+
<A, E>(name: string, body: (...args: TArgs) => Effect.Effect<A, E, R>, options?: number | TestOptions): void;
|
|
30
|
+
}
|
|
31
|
+
export interface EffectItTester<R> extends EffectItTest<R> {
|
|
32
|
+
readonly each: <TItem>(cases: readonly TItem[]) => EffectItTest<R, [item: TItem]>;
|
|
33
|
+
readonly fails: EffectItTest<R>;
|
|
34
|
+
readonly only: EffectItTest<R>;
|
|
35
|
+
readonly runIf: (condition: unknown) => EffectItTest<R>;
|
|
36
|
+
readonly skip: EffectItTest<R>;
|
|
37
|
+
readonly skipIf: (condition: unknown) => EffectItTest<R>;
|
|
38
|
+
}
|
|
39
|
+
export type EffectIt = TestAPI & {
|
|
40
|
+
readonly effect: EffectItTester<Scope.Scope>;
|
|
41
|
+
readonly live: EffectItTester<Scope.Scope>;
|
|
42
|
+
};
|
|
26
43
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/effect-test",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Generic Effect Vitest runner with worker-scoped Layers and TestClock",
|
|
5
5
|
"homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/effect-test#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"sideEffects": false,
|
|
16
16
|
"type": "module",
|
|
17
17
|
"imports": {
|
|
18
|
-
"#test/*": "./test/*",
|
|
18
|
+
"#test/*": "./src/test-support/*",
|
|
19
19
|
"#*.ts": {
|
|
20
20
|
"source": "./src/*.ts",
|
|
21
21
|
"types": "./dist/*.d.ts",
|
|
@@ -23,28 +23,31 @@
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"exports": {
|
|
26
|
-
"
|
|
27
|
-
"types": "./dist
|
|
28
|
-
"source": "./src
|
|
29
|
-
"import": "./dist
|
|
30
|
-
"default": "./dist
|
|
26
|
+
"./*.ts": {
|
|
27
|
+
"types": "./dist/*.d.ts",
|
|
28
|
+
"source": "./src/*.ts",
|
|
29
|
+
"import": "./dist/*.js",
|
|
30
|
+
"default": "./dist/*.js"
|
|
31
31
|
},
|
|
32
32
|
"./package.json": "./package.json"
|
|
33
33
|
},
|
|
34
34
|
"files": [
|
|
35
35
|
"dist",
|
|
36
36
|
"src",
|
|
37
|
+
"!src/**/*.test.ts",
|
|
38
|
+
"!src/**/*.spec.ts",
|
|
39
|
+
"!src/**/test-support",
|
|
37
40
|
"CHANGELOG.md",
|
|
38
41
|
"README.md"
|
|
39
42
|
],
|
|
40
43
|
"devDependencies": {
|
|
41
44
|
"@effect/vitest": "4.0.0-rc.112",
|
|
42
|
-
"@shivaedev/quality": "0.
|
|
45
|
+
"@shivaedev/quality": "0.14.0",
|
|
43
46
|
"@types/node": "24.10.1",
|
|
44
47
|
"@typescript/native": "npm:typescript@7.0.2",
|
|
45
48
|
"effect": "4.0.0-rc.112",
|
|
46
49
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
47
|
-
"vitest": "4.1.
|
|
50
|
+
"vitest": "4.1.11"
|
|
48
51
|
},
|
|
49
52
|
"peerDependencies": {
|
|
50
53
|
"@effect/vitest": "4.0.0-rc.112",
|
package/src/it.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { it as effectIt, type TestContext, type TestOptions, type Vitest } from "@effect/vitest";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import type { TestAPI } from "vitest";
|
|
4
|
+
import type { EffectIt, EffectItTest, EffectItTester } from "./types.ts";
|
|
5
|
+
|
|
6
|
+
type Body<TArgs extends readonly unknown[], R> = (
|
|
7
|
+
...args: TArgs
|
|
8
|
+
) => Effect.Effect<unknown, unknown, R> | Generator<Effect.Effect<unknown, unknown, R>, unknown, never>;
|
|
9
|
+
|
|
10
|
+
function effectOf<TArgs extends readonly unknown[], R>(body: Body<TArgs, R>) {
|
|
11
|
+
return (...args: TArgs): Effect.Effect<unknown, unknown, R> => {
|
|
12
|
+
const result = body(...args);
|
|
13
|
+
return Effect.isEffect(result) ? result : Effect.gen(() => result);
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function bodyTest<R>(register: Vitest.Test<R>): EffectItTest<R> {
|
|
18
|
+
return (name: string, body: Body<[context: TestContext], R>, options?: number | TestOptions) => register(name, effectOf(body), options);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function bodyTester<R>(register: Vitest.Tester<R>): EffectItTester<R> {
|
|
22
|
+
return Object.assign(bodyTest(register), {
|
|
23
|
+
each:
|
|
24
|
+
<TItem>(cases: readonly TItem[]): EffectItTest<R, [item: TItem]> =>
|
|
25
|
+
(name: string, body: Body<[item: TItem], R>, options?: number | TestOptions) =>
|
|
26
|
+
register.each(cases)(name, effectOf(body), options),
|
|
27
|
+
fails: bodyTest(register.fails),
|
|
28
|
+
only: bodyTest(register.only),
|
|
29
|
+
runIf: (condition: unknown) => bodyTest(register.runIf(condition)),
|
|
30
|
+
skip: bodyTest(register.skip),
|
|
31
|
+
skipIf: (condition: unknown) => bodyTest(register.skipIf(condition)),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const testers: Record<PropertyKey, unknown> = {};
|
|
36
|
+
|
|
37
|
+
const vitestTests = new Proxy<TestAPI>(effectIt, {
|
|
38
|
+
get: (target, key, receiver) => (Object.hasOwn(testers, key) ? testers[key] : Reflect.get(target, key, receiver)),
|
|
39
|
+
set: (_target, key, value) => Reflect.set(testers, key, value),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export const it: EffectIt = Object.assign(vitestTests, {
|
|
43
|
+
effect: bodyTester(effectIt.effect),
|
|
44
|
+
live: bodyTester(effectIt.live),
|
|
45
|
+
});
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { TestContext, TestOptions } from "@effect/vitest";
|
|
2
|
-
import type { Effect, Layer } from "effect";
|
|
2
|
+
import type { Effect, Layer, Scope } from "effect";
|
|
3
|
+
import type { TestAPI } from "vitest";
|
|
3
4
|
import type { AnyTestLayer } from "./any-test-layer.ts";
|
|
4
5
|
|
|
5
6
|
export type EffectClock = "test" | "live";
|
|
@@ -41,3 +42,26 @@ export interface MakeEffectItOptions<Harness, TestLayer extends AnyTestLayer> {
|
|
|
41
42
|
export interface MakeEffectItResult<Harness, Provided> {
|
|
42
43
|
readonly effectApp: EffectTester<Harness, Provided>;
|
|
43
44
|
}
|
|
45
|
+
|
|
46
|
+
export interface EffectItTest<R, TArgs extends readonly unknown[] = [context: TestContext]> {
|
|
47
|
+
<TEffect extends Effect.Effect<unknown, unknown, R>, A>(
|
|
48
|
+
name: string,
|
|
49
|
+
body: (...args: TArgs) => Generator<TEffect, A, never>,
|
|
50
|
+
options?: number | TestOptions,
|
|
51
|
+
): void;
|
|
52
|
+
<A, E>(name: string, body: (...args: TArgs) => Effect.Effect<A, E, R>, options?: number | TestOptions): void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface EffectItTester<R> extends EffectItTest<R> {
|
|
56
|
+
readonly each: <TItem>(cases: readonly TItem[]) => EffectItTest<R, [item: TItem]>;
|
|
57
|
+
readonly fails: EffectItTest<R>;
|
|
58
|
+
readonly only: EffectItTest<R>;
|
|
59
|
+
readonly runIf: (condition: unknown) => EffectItTest<R>;
|
|
60
|
+
readonly skip: EffectItTest<R>;
|
|
61
|
+
readonly skipIf: (condition: unknown) => EffectItTest<R>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export type EffectIt = TestAPI & {
|
|
65
|
+
readonly effect: EffectItTester<Scope.Scope>;
|
|
66
|
+
readonly live: EffectItTester<Scope.Scope>;
|
|
67
|
+
};
|
package/dist/index.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export { type EventuallyOptions, eventually } from "./eventually.ts";
|
|
2
|
-
export type { EffectClock, EffectTest, EffectTester, EffectTestOptions, MakeEffectItOptions, MakeEffectItResult, } from "./types.ts";
|
|
3
|
-
export { makeEffectIt } from "./vitest.ts";
|
|
4
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACrE,YAAY,EACX,WAAW,EACX,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
DELETED
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,UAAU,EAAE,MAAM,iBAAiB,CAAC;AASrE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
|
package/src/index.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export { type EventuallyOptions, eventually } from "./eventually.ts";
|
|
2
|
-
export type {
|
|
3
|
-
EffectClock,
|
|
4
|
-
EffectTest,
|
|
5
|
-
EffectTester,
|
|
6
|
-
EffectTestOptions,
|
|
7
|
-
MakeEffectItOptions,
|
|
8
|
-
MakeEffectItResult,
|
|
9
|
-
} from "./types.ts";
|
|
10
|
-
export { makeEffectIt } from "./vitest.ts";
|