@shivaedev/test-story 0.2.0 → 0.2.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.
- package/CHANGELOG.md +6 -0
- package/README.md +3 -1
- package/dist/server/internal/hookInference.d.ts +28 -0
- package/dist/server/internal/hookInference.d.ts.map +1 -0
- package/dist/server/internal/hookInference.js +2 -0
- package/dist/server/internal/hookInference.js.map +1 -0
- package/dist/server/internal/hooked.d.ts +4 -1
- package/dist/server/internal/hooked.d.ts.map +1 -1
- package/dist/server/internal/hooked.js +3 -0
- package/dist/server/internal/hooked.js.map +1 -1
- package/dist/server/internal/seed.d.ts +3 -3
- package/dist/server/internal/seed.d.ts.map +1 -1
- package/dist/server/internal/seed.js.map +1 -1
- package/dist/server/storyKit.d.ts +10 -11
- package/dist/server/storyKit.d.ts.map +1 -1
- package/dist/server/storyKit.js.map +1 -1
- package/package.json +3 -3
- package/src/server/internal/hookInference.ts +46 -0
- package/src/server/internal/hooked.ts +11 -3
- package/src/server/internal/seed.ts +3 -3
- package/src/server/storyKit.ts +31 -28
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.1 - 2026-10-16
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Let `create`, stage `after` hooks and traits return an Effect directly, with inferred engine types, checked service requirements and the story's Scope, alongside generators and synchronous functions.
|
|
8
|
+
|
|
3
9
|
## 0.2.0 - 2026-10-13
|
|
4
10
|
|
|
5
11
|
### Breaking
|
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ An application has an **engine**: the real thing a test drives, such as a bakery
|
|
|
47
47
|
|
|
48
48
|
Every story belongs to a **genre**, the kind of engine it runs. The kit names each of its tests after its genre, such as `Bakery Story: steps until the condition holds`, so a report shows which engine a test runs and one run can pick the bakery's stories and leave the others.
|
|
49
49
|
|
|
50
|
-
The package runs on Effect and Vitest, but an engine needs neither: every hook, trait and test body may be a plain function.
|
|
50
|
+
The package runs on Effect and Vitest, but an engine needs neither: every hook, trait and test body may be a plain function. Use a generator function to yield Effects when a hook needs a service or fails with a typed error; the kit runs it, so no definition needs `Effect.gen`. Creation, stage `after` hooks and traits may also be plain functions that return an Effect directly. The kit runs that Effect in the story's Scope, with the services from its layer.
|
|
51
51
|
|
|
52
52
|
The work splits into three layers, and each is written by a different hand at a different time:
|
|
53
53
|
|
|
@@ -209,6 +209,8 @@ A spec starts a story, acts through verbs and checks what a user would see. When
|
|
|
209
209
|
|
|
210
210
|
### Running the engine
|
|
211
211
|
|
|
212
|
+
Hooks and steps that wait for real workers can use `withLive(Effect.sleep(...))` or `withLive(eventually(...))` from `@shivaedev/effect-test/withLive.ts` and `@shivaedev/effect-test/eventually.ts`. Both work under the kit's live clock and a story's TestClock override. The wrapped work uses live time without advancing the story's virtual time; outside it, the selected clock still applies. Unwrapped `eventually` uses the active clock and advances TestClock between attempts.
|
|
213
|
+
|
|
212
214
|
`story.runUntil(condition, { maxSteps })` returns an Effect that asks three questions before every step:
|
|
213
215
|
|
|
214
216
|
1. `run.failed` returns a sentence: it dies with it, even when the condition also holds.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Effect, Layer, Scope } from "effect";
|
|
2
|
+
import type { AnyEffect, Hook, HookEffects, HookValue, ServicesOf } from "#internal/hooked.ts";
|
|
3
|
+
import type { StoryKitDefinition } from "#storyKit.ts";
|
|
4
|
+
export type AfterResults<TStage extends string> = {
|
|
5
|
+
readonly [TKey in TStage]?: Generator<AnyEffect, void, never> | Effect.Effect<void, unknown, unknown> | void;
|
|
6
|
+
};
|
|
7
|
+
type LayerFor<THooks, TProvided> = [Exclude<ServicesOf<THooks>, Scope.Scope>] extends [TProvided] ? unknown : {
|
|
8
|
+
readonly layer: Layer.Layer<Exclude<ServicesOf<THooks>, Scope.Scope>, unknown, never>;
|
|
9
|
+
};
|
|
10
|
+
export type InferredDefinition<TCreate extends () => unknown, TStage extends string, TVerbs, TProvided, TAfter extends AfterResults<TStage>, TStep extends AnyEffect, TFailed extends AnyEffect, TDiagnose extends AnyEffect> = Omit<StoryKitDefinition<HookValue<ReturnType<TCreate>>, TStage, TVerbs, TProvided, never, Record<never, never>, TStep, TFailed, TDiagnose>, "create" | "after"> & {
|
|
11
|
+
readonly create: TCreate;
|
|
12
|
+
readonly after?: {
|
|
13
|
+
readonly [TKey in keyof TAfter]: (engine: HookValue<ReturnType<TCreate>>) => TAfter[TKey];
|
|
14
|
+
};
|
|
15
|
+
} & LayerFor<HookEffects<ReturnType<TCreate> | TAfter[keyof TAfter]> | TStep | TFailed | TDiagnose, TProvided>;
|
|
16
|
+
type AfterEffects<TAfter> = {
|
|
17
|
+
readonly [TKey in keyof TAfter]-?: AnyEffect extends TAfter[TKey] ? never : TAfter[TKey];
|
|
18
|
+
}[keyof TAfter];
|
|
19
|
+
export type LegacyDefinition<TEngine, TStage extends string, TVerbs, TProvided, TCreate extends AnyEffect, TAfter extends {
|
|
20
|
+
readonly [TKey in TStage]?: AnyEffect;
|
|
21
|
+
}, TStep extends AnyEffect, TFailed extends AnyEffect, TDiagnose extends AnyEffect> = Omit<StoryKitDefinition<TEngine, TStage, TVerbs, TProvided, TCreate, TAfter, TStep, TFailed, TDiagnose>, "create" | "after"> & {
|
|
22
|
+
readonly create: Hook<[], TCreate, TEngine> & (TEngine extends AnyEffect ? never : unknown);
|
|
23
|
+
readonly after?: {
|
|
24
|
+
readonly [TKey in keyof TAfter]: Hook<[engine: TEngine], TAfter[TKey] & AnyEffect, void>;
|
|
25
|
+
};
|
|
26
|
+
} & LayerFor<TCreate | AfterEffects<TAfter> | TStep | TFailed | TDiagnose, TProvided>;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=hookInference.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hookInference.d.ts","sourceRoot":"","sources":["../../../src/server/internal/hookInference.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hookInference.js","sourceRoot":"","sources":["../../../src/server/internal/hookInference.ts"],"names":[],"mappings":""}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
2
|
export type AnyEffect = Effect.Effect<unknown, unknown, unknown>;
|
|
3
3
|
export type Hook<TArguments extends readonly unknown[], TEffect extends AnyEffect, A> = (...input: TArguments) => Generator<TEffect, A, never> | A;
|
|
4
|
+
export type EffectHook<TArguments extends readonly unknown[], TEffect extends AnyEffect, A> = (...input: TArguments) => Generator<TEffect, A, never> | (TEffect & Effect.Effect<A, ErrorOf<TEffect>, ServicesOf<TEffect>>) | A;
|
|
5
|
+
export type HookValue<T> = T extends Generator<AnyEffect, infer A, never> ? A : T extends Effect.Effect<infer A, unknown, unknown> ? A : T;
|
|
6
|
+
export type HookEffects<T> = T extends Generator<infer TEffect, unknown, never> ? Extract<TEffect, AnyEffect> : T extends AnyEffect ? T : never;
|
|
4
7
|
export type ErrorOf<TEffect> = [TEffect] extends [never] ? never : [TEffect] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E : never;
|
|
5
8
|
export type ServicesOf<TEffect> = [TEffect] extends [never] ? never : [TEffect] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R : never;
|
|
6
|
-
export declare function hooked<TEffect extends AnyEffect, A>(call:
|
|
9
|
+
export declare function hooked<TEffect extends AnyEffect, A>(call: EffectHook<[], TEffect, A>): Effect.Effect<A, ErrorOf<TEffect>, ServicesOf<TEffect>>;
|
|
7
10
|
//# sourceMappingURL=hooked.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooked.d.ts","sourceRoot":"","sources":["../../../src/server/internal/hooked.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAEjE,MAAM,MAAM,IAAI,CAAC,UAAU,SAAS,SAAS,OAAO,EAAE,EAAE,OAAO,SAAS,SAAS,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,EAAE,UAAU,KAAK,SAAS,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;AAEnJ,MAAM,MAAM,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAE9I,MAAM,MAAM,UAAU,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAMjJ,wBAAgB,MAAM,CAAC,OAAO,SAAS,SAAS,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"hooked.d.ts","sourceRoot":"","sources":["../../../src/server/internal/hooked.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAEjE,MAAM,MAAM,IAAI,CAAC,UAAU,SAAS,SAAS,OAAO,EAAE,EAAE,OAAO,SAAS,SAAS,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,EAAE,UAAU,KAAK,SAAS,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;AAEnJ,MAAM,MAAM,UAAU,CAAC,UAAU,SAAS,SAAS,OAAO,EAAE,EAAE,OAAO,SAAS,SAAS,EAAE,CAAC,IAAI,CAC7F,GAAG,KAAK,EAAE,UAAU,KAChB,SAAS,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAE5G,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC3I,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,MAAM,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,GAAG,CAAC,SAAS,SAAS,GAAG,CAAC,GAAG,KAAK,CAAC;AAEhJ,MAAM,MAAM,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAE9I,MAAM,MAAM,UAAU,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAMjJ,wBAAgB,MAAM,CAAC,OAAO,SAAS,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAQ9I"}
|
|
@@ -5,6 +5,9 @@ function isGenerator(value) {
|
|
|
5
5
|
export function hooked(call) {
|
|
6
6
|
return Effect.suspend(() => {
|
|
7
7
|
const result = call();
|
|
8
|
+
if (Effect.isEffect(result)) {
|
|
9
|
+
return result;
|
|
10
|
+
}
|
|
8
11
|
return isGenerator(result) ? Effect.gen(() => result) : Effect.succeed(result);
|
|
9
12
|
});
|
|
10
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooked.js","sourceRoot":"","sources":["../../../src/server/internal/hooked.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"hooked.js","sourceRoot":"","sources":["../../../src/server/internal/hooked.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAiBhC,SAAS,WAAW,CAAa,KAAuC;IACvE,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,CAAC,QAAQ,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC;AACvI,CAAC;AAED,MAAM,UAAU,MAAM,CAA+B,IAAgC;IACpF,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE;QAC1B,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC;QACtB,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,OAAO,MAAM,CAAC;QACf,CAAC;QACD,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Effect, type Scope } from "effect";
|
|
2
2
|
import type { AnyTestLayer } from "@shivaedev/effect-test/any-test-layer.ts";
|
|
3
3
|
import type { EffectClock } from "@shivaedev/effect-test/types.ts";
|
|
4
|
-
import { type AnyEffect, type Hook } from "#internal/hooked.ts";
|
|
4
|
+
import { type AnyEffect, type EffectHook, type Hook } from "#internal/hooked.ts";
|
|
5
5
|
import { type Narration } from "#internal/narration.ts";
|
|
6
6
|
import type { LooseRunHooks } from "#internal/runUntil.ts";
|
|
7
7
|
import type { Parts } from "#internal/traits.ts";
|
|
@@ -14,10 +14,10 @@ export interface LooseStory {
|
|
|
14
14
|
readonly tell: (line: string) => void;
|
|
15
15
|
}
|
|
16
16
|
export interface LooseDefinition {
|
|
17
|
-
readonly after?: Readonly<Partial<Record<string,
|
|
17
|
+
readonly after?: Readonly<Partial<Record<string, EffectHook<[engine: unknown], AnyEffect, void>>>>;
|
|
18
18
|
readonly around?: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, unknown, R | Scope.Scope>;
|
|
19
19
|
readonly clock?: EffectClock;
|
|
20
|
-
readonly create:
|
|
20
|
+
readonly create: EffectHook<[], AnyEffect, unknown>;
|
|
21
21
|
readonly inspect?: (engine: unknown) => unknown;
|
|
22
22
|
readonly layer?: AnyTestLayer;
|
|
23
23
|
readonly name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../../../src/server/internal/seed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0CAA0C,CAAC;AAC7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAEnE,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,IAAI,EAAU,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../../../src/server/internal/seed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0CAA0C,CAAC;AAC7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAEnE,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,IAAI,EAAU,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,wBAAwB,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAEnG,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5I,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACnG,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1G,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IACpD,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,KAAK,MAAM,CAAC;CAC/D;AAED,eAAO,MAAM,IAAI,6IAuBf,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seed.js","sourceRoot":"","sources":["../../../src/server/internal/seed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAc,MAAM,QAAQ,CAAC;AAGnD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,
|
|
1
|
+
{"version":3,"file":"seed.js","sourceRoot":"","sources":["../../../src/server/internal/seed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAc,MAAM,QAAQ,CAAC;AAGnD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAA8C,MAAM,EAAE,MAAM,qBAAqB,CAAC;AACzF,OAAO,EAAkB,SAAS,EAAE,MAAM,wBAAwB,CAAC;AA2BnE,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,UAA2B,EAAE,MAAe,EAAE,SAAoB,EAAE,KAA4B;IAChJ,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC5B,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;QACvC,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAC7C,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;gBAC1B,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CACnD,MAAM,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,EAAE;oBAC3B,IAAI,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;wBACpC,OAAO,MAAM,CAAC,SAAS,CAAC;oBACzB,CAAC;oBACD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBACnC,SAAS,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;oBAC7C,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;gBAChE,CAAC,CAAC,CACF,CAAC;YACH,CAAC;QACF,CAAC;QACD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACzB,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QACpC,CAAC;IACF,CAAC;AACF,CAAC,CAAC,CAAC"}
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import type { TestContext } from "@effect/vitest";
|
|
2
2
|
import type { Effect, Layer, Scope } from "effect";
|
|
3
3
|
import type { EffectClock, EffectTestOptions } from "@shivaedev/effect-test/types.ts";
|
|
4
|
-
import { type AnyEffect, type ErrorOf, type Hook, type ServicesOf } from "#internal/hooked.ts";
|
|
4
|
+
import { type AnyEffect, type EffectHook, type ErrorOf, type Hook, type HookValue, type ServicesOf } from "#internal/hooked.ts";
|
|
5
|
+
import type { AfterResults, InferredDefinition, LegacyDefinition } from "#internal/hookInference.ts";
|
|
5
6
|
import { type Parts } from "#internal/traits.ts";
|
|
6
7
|
export type Trait<TEngine, TStage extends string, R = never> = Parts<TStage, (engine: TEngine) => Effect.Effect<void, unknown, R>>;
|
|
7
8
|
type TraitServices<TTrait> = TTrait extends Parts<string, (engine: never) => Effect.Effect<void, unknown, infer R>> ? R : never;
|
|
8
9
|
type Needs<TProvided> = Effect.Effect<unknown, unknown, TProvided>;
|
|
9
|
-
type AfterEffects<TAfter> = {
|
|
10
|
-
readonly [TKey in keyof TAfter]-?: AnyEffect extends TAfter[TKey] ? never : TAfter[TKey];
|
|
11
|
-
}[keyof TAfter];
|
|
12
|
-
type LayerFor<THooks, TProvided> = [Exclude<ServicesOf<THooks>, Scope.Scope>] extends [TProvided] ? unknown : {
|
|
13
|
-
readonly layer: Layer.Layer<Exclude<ServicesOf<THooks>, Scope.Scope>, unknown, never>;
|
|
14
|
-
};
|
|
15
10
|
export interface RunUntilOptions {
|
|
16
11
|
readonly maxSteps?: number | undefined;
|
|
17
12
|
}
|
|
@@ -31,11 +26,11 @@ export interface StoryKitDefinition<TEngine, TStage extends string, TVerbs, TPro
|
|
|
31
26
|
readonly [TKey in TStage]?: AnyEffect;
|
|
32
27
|
}, TStep extends AnyEffect, TFailed extends AnyEffect, TDiagnose extends AnyEffect> {
|
|
33
28
|
readonly after?: {
|
|
34
|
-
readonly [TKey in keyof TAfter]:
|
|
29
|
+
readonly [TKey in keyof TAfter]: EffectHook<[engine: TEngine], TAfter[TKey] & AnyEffect, void>;
|
|
35
30
|
};
|
|
36
31
|
readonly around?: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, unknown, R | NoInfer<TProvided> | Scope.Scope>;
|
|
37
32
|
readonly clock?: EffectClock;
|
|
38
|
-
readonly create:
|
|
33
|
+
readonly create: EffectHook<[], TCreate, TEngine>;
|
|
39
34
|
readonly inspect?: (engine: TEngine) => unknown;
|
|
40
35
|
readonly layer?: Layer.Layer<TProvided, unknown, never>;
|
|
41
36
|
readonly name: string;
|
|
@@ -57,11 +52,15 @@ export interface StoryIt<TEngine, TStage extends string, TVerbs, TRun extends An
|
|
|
57
52
|
}
|
|
58
53
|
export interface StoryKit<TEngine, TStage extends string, TVerbs, TRun extends AnyEffect, TProvided> {
|
|
59
54
|
readonly it: StoryIt<TEngine, TStage, TVerbs, TRun, TProvided>;
|
|
60
|
-
readonly trait:
|
|
55
|
+
readonly trait: {
|
|
56
|
+
<TEffect extends AnyEffect = never>(stage: TStage, line: string, apply: Hook<[engine: TEngine], TEffect, void>): Trait<TEngine, TStage, ServicesOf<TEffect>>;
|
|
57
|
+
<E, R>(stage: TStage, line: string, apply: (engine: TEngine) => Effect.Effect<void, E, R>): Trait<TEngine, TStage, R>;
|
|
58
|
+
};
|
|
61
59
|
readonly traits: <const TGiven extends readonly Trait<TEngine, TStage, unknown>[]>(...given: TGiven) => Trait<TEngine, TStage, TraitServices<TGiven[number]>>;
|
|
62
60
|
}
|
|
61
|
+
export declare function storyKit<TCreate extends () => unknown, const TStage extends string, TVerbs extends object, TProvided = never, TAfter extends AfterResults<TStage> = Record<never, never>, TStep extends AnyEffect = never, TFailed extends AnyEffect = never, TDiagnose extends AnyEffect = never>(definition: InferredDefinition<TCreate, TStage, TVerbs, TProvided, TAfter, TStep, TFailed, TDiagnose>): StoryKit<HookValue<ReturnType<TCreate>>, TStage, TVerbs, TStep | TFailed | TDiagnose, TProvided>;
|
|
63
62
|
export declare function storyKit<TEngine, const TStage extends string, TVerbs extends object, TProvided = never, TCreate extends AnyEffect = never, TAfter extends {
|
|
64
63
|
readonly [TKey in TStage]?: AnyEffect;
|
|
65
|
-
} = Record<never, never>, TStep extends AnyEffect = never, TFailed extends AnyEffect = never, TDiagnose extends AnyEffect = never>(definition:
|
|
64
|
+
} = Record<never, never>, TStep extends AnyEffect = never, TFailed extends AnyEffect = never, TDiagnose extends AnyEffect = never>(definition: LegacyDefinition<TEngine, TStage, TVerbs, TProvided, TCreate, TAfter, TStep, TFailed, TDiagnose>): StoryKit<TEngine, TStage, TVerbs, TStep | TFailed | TDiagnose, TProvided>;
|
|
66
65
|
export {};
|
|
67
66
|
//# sourceMappingURL=storyKit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storyKit.d.ts","sourceRoot":"","sources":["../../src/server/storyKit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACtF,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,OAAO,EAAE,KAAK,IAAI,EAAU,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"storyKit.d.ts","sourceRoot":"","sources":["../../src/server/storyKit.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storyKit.js","sourceRoot":"","sources":["../../src/server/storyKit.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"storyKit.js","sourceRoot":"","sources":["../../src/server/storyKit.ts"],"names":[],"mappings":"AAGA,OAAO,EAA4E,MAAM,EAAmB,MAAM,qBAAqB,CAAC;AAGxI,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAc,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAsHhE,MAAM,UAAU,QAAQ,CAAC,UAA2B;IACnD,OAAO;QACN,EAAE,EAAE,OAAO,CAAC,UAAU,CAAC;QACvB,KAAK,EAAE,CAAC,KAAa,EAAE,IAAY,EAAE,KAAqD,EAAE,EAAE,CAC7F,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,MAAe,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QACrE,MAAM;KACN,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/test-story",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Tests that read like stories over the real engine: a story kit per engine with its own it, traits per feature, and a failure that prints the story, where it stopped and the engine's state",
|
|
5
5
|
"homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/test-story#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -43,11 +43,11 @@
|
|
|
43
43
|
"README.md"
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@shivaedev/effect-test": "0.
|
|
46
|
+
"@shivaedev/effect-test": "0.5.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@effect/vitest": "4.0.4",
|
|
50
|
-
"@shivaedev/quality": "0.
|
|
50
|
+
"@shivaedev/quality": "0.21.1",
|
|
51
51
|
"@types/node": "24.19.1",
|
|
52
52
|
"@typescript/native": "npm:typescript@7.0.2",
|
|
53
53
|
"effect": "4.0.4",
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Effect, Layer, Scope } from "effect";
|
|
2
|
+
import type { AnyEffect, Hook, HookEffects, HookValue, ServicesOf } from "#internal/hooked.ts";
|
|
3
|
+
import type { StoryKitDefinition } from "#storyKit.ts";
|
|
4
|
+
|
|
5
|
+
export type AfterResults<TStage extends string> = {
|
|
6
|
+
readonly [TKey in TStage]?: Generator<AnyEffect, void, never> | Effect.Effect<void, unknown, unknown> | void;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
type LayerFor<THooks, TProvided> = [Exclude<ServicesOf<THooks>, Scope.Scope>] extends [TProvided]
|
|
10
|
+
? unknown
|
|
11
|
+
: { readonly layer: Layer.Layer<Exclude<ServicesOf<THooks>, Scope.Scope>, unknown, never> };
|
|
12
|
+
|
|
13
|
+
export type InferredDefinition<
|
|
14
|
+
TCreate extends () => unknown,
|
|
15
|
+
TStage extends string,
|
|
16
|
+
TVerbs,
|
|
17
|
+
TProvided,
|
|
18
|
+
TAfter extends AfterResults<TStage>,
|
|
19
|
+
TStep extends AnyEffect,
|
|
20
|
+
TFailed extends AnyEffect,
|
|
21
|
+
TDiagnose extends AnyEffect,
|
|
22
|
+
> = Omit<
|
|
23
|
+
StoryKitDefinition<HookValue<ReturnType<TCreate>>, TStage, TVerbs, TProvided, never, Record<never, never>, TStep, TFailed, TDiagnose>,
|
|
24
|
+
"create" | "after"
|
|
25
|
+
> & {
|
|
26
|
+
readonly create: TCreate;
|
|
27
|
+
readonly after?: { readonly [TKey in keyof TAfter]: (engine: HookValue<ReturnType<TCreate>>) => TAfter[TKey] };
|
|
28
|
+
} & LayerFor<HookEffects<ReturnType<TCreate> | TAfter[keyof TAfter]> | TStep | TFailed | TDiagnose, TProvided>;
|
|
29
|
+
|
|
30
|
+
// A synchronous after hook has no effect to infer, so TypeScript leaves it at the AnyEffect constraint.
|
|
31
|
+
type AfterEffects<TAfter> = { readonly [TKey in keyof TAfter]-?: AnyEffect extends TAfter[TKey] ? never : TAfter[TKey] }[keyof TAfter];
|
|
32
|
+
|
|
33
|
+
export type LegacyDefinition<
|
|
34
|
+
TEngine,
|
|
35
|
+
TStage extends string,
|
|
36
|
+
TVerbs,
|
|
37
|
+
TProvided,
|
|
38
|
+
TCreate extends AnyEffect,
|
|
39
|
+
TAfter extends { readonly [TKey in TStage]?: AnyEffect },
|
|
40
|
+
TStep extends AnyEffect,
|
|
41
|
+
TFailed extends AnyEffect,
|
|
42
|
+
TDiagnose extends AnyEffect,
|
|
43
|
+
> = Omit<StoryKitDefinition<TEngine, TStage, TVerbs, TProvided, TCreate, TAfter, TStep, TFailed, TDiagnose>, "create" | "after"> & {
|
|
44
|
+
readonly create: Hook<[], TCreate, TEngine> & (TEngine extends AnyEffect ? never : unknown);
|
|
45
|
+
readonly after?: { readonly [TKey in keyof TAfter]: Hook<[engine: TEngine], TAfter[TKey] & AnyEffect, void> };
|
|
46
|
+
} & LayerFor<TCreate | AfterEffects<TAfter> | TStep | TFailed | TDiagnose, TProvided>;
|
|
@@ -4,6 +4,13 @@ export type AnyEffect = Effect.Effect<unknown, unknown, unknown>;
|
|
|
4
4
|
|
|
5
5
|
export type Hook<TArguments extends readonly unknown[], TEffect extends AnyEffect, A> = (...input: TArguments) => Generator<TEffect, A, never> | A;
|
|
6
6
|
|
|
7
|
+
export type EffectHook<TArguments extends readonly unknown[], TEffect extends AnyEffect, A> = (
|
|
8
|
+
...input: TArguments
|
|
9
|
+
) => Generator<TEffect, A, never> | (TEffect & Effect.Effect<A, ErrorOf<TEffect>, ServicesOf<TEffect>>) | A;
|
|
10
|
+
|
|
11
|
+
export type HookValue<T> = T extends Generator<AnyEffect, infer A, never> ? A : T extends Effect.Effect<infer A, unknown, unknown> ? A : T;
|
|
12
|
+
export type HookEffects<T> = T extends Generator<infer TEffect, unknown, never> ? Extract<TEffect, AnyEffect> : T extends AnyEffect ? T : never;
|
|
13
|
+
|
|
7
14
|
export type ErrorOf<TEffect> = [TEffect] extends [never] ? never : [TEffect] extends [Effect.Effect<infer _A, infer E, infer _R>] ? E : never;
|
|
8
15
|
|
|
9
16
|
export type ServicesOf<TEffect> = [TEffect] extends [never] ? never : [TEffect] extends [Effect.Effect<infer _A, infer _E, infer R>] ? R : never;
|
|
@@ -12,11 +19,12 @@ function isGenerator<TEffect, A>(value: Generator<TEffect, A, never> | A): value
|
|
|
12
19
|
return typeof value === "object" && value !== null && Symbol.iterator in value && "next" in value && typeof value.next === "function";
|
|
13
20
|
}
|
|
14
21
|
|
|
15
|
-
export function hooked<TEffect extends AnyEffect, A>(
|
|
16
|
-
call: () => Generator<TEffect, A, never> | A,
|
|
17
|
-
): Effect.Effect<A, ErrorOf<TEffect>, ServicesOf<TEffect>> {
|
|
22
|
+
export function hooked<TEffect extends AnyEffect, A>(call: EffectHook<[], TEffect, A>): Effect.Effect<A, ErrorOf<TEffect>, ServicesOf<TEffect>> {
|
|
18
23
|
return Effect.suspend(() => {
|
|
19
24
|
const result = call();
|
|
25
|
+
if (Effect.isEffect(result)) {
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
20
28
|
return isGenerator(result) ? Effect.gen(() => result) : Effect.succeed(result);
|
|
21
29
|
});
|
|
22
30
|
}
|
|
@@ -2,7 +2,7 @@ import { Cause, Effect, type Scope } from "effect";
|
|
|
2
2
|
import type { AnyTestLayer } from "@shivaedev/effect-test/any-test-layer.ts";
|
|
3
3
|
import type { EffectClock } from "@shivaedev/effect-test/types.ts";
|
|
4
4
|
import { refusal } from "#internal/errors.ts";
|
|
5
|
-
import { type AnyEffect, type Hook, hooked } from "#internal/hooked.ts";
|
|
5
|
+
import { type AnyEffect, type EffectHook, type Hook, hooked } from "#internal/hooked.ts";
|
|
6
6
|
import { type Narration, tellGiven } from "#internal/narration.ts";
|
|
7
7
|
import type { LooseRunHooks } from "#internal/runUntil.ts";
|
|
8
8
|
import type { Parts } from "#internal/traits.ts";
|
|
@@ -18,10 +18,10 @@ export interface LooseStory {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export interface LooseDefinition {
|
|
21
|
-
readonly after?: Readonly<Partial<Record<string,
|
|
21
|
+
readonly after?: Readonly<Partial<Record<string, EffectHook<[engine: unknown], AnyEffect, void>>>>;
|
|
22
22
|
readonly around?: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, unknown, R | Scope.Scope>;
|
|
23
23
|
readonly clock?: EffectClock;
|
|
24
|
-
readonly create:
|
|
24
|
+
readonly create: EffectHook<[], AnyEffect, unknown>;
|
|
25
25
|
readonly inspect?: (engine: unknown) => unknown;
|
|
26
26
|
readonly layer?: AnyTestLayer;
|
|
27
27
|
readonly name: string;
|
package/src/server/storyKit.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { TestContext } from "@effect/vitest";
|
|
2
2
|
import type { Effect, Layer, Scope } from "effect";
|
|
3
3
|
import type { EffectClock, EffectTestOptions } from "@shivaedev/effect-test/types.ts";
|
|
4
|
-
import { type AnyEffect, type ErrorOf, type Hook, hooked, type ServicesOf } from "#internal/hooked.ts";
|
|
5
|
-
import type {
|
|
6
|
-
import
|
|
4
|
+
import { type AnyEffect, type EffectHook, type ErrorOf, type Hook, type HookValue, hooked, type ServicesOf } from "#internal/hooked.ts";
|
|
5
|
+
import type { AfterResults, InferredDefinition, LegacyDefinition } from "#internal/hookInference.ts";
|
|
6
|
+
import type { LooseDefinition } from "#internal/seed.ts";
|
|
7
|
+
import { storyIt } from "#internal/storyIt.ts";
|
|
7
8
|
import { type Parts, trait, traits } from "#internal/traits.ts";
|
|
8
9
|
|
|
9
10
|
export type Trait<TEngine, TStage extends string, R = never> = Parts<TStage, (engine: TEngine) => Effect.Effect<void, unknown, R>>;
|
|
@@ -12,13 +13,6 @@ type TraitServices<TTrait> = TTrait extends Parts<string, (engine: never) => Eff
|
|
|
12
13
|
|
|
13
14
|
type Needs<TProvided> = Effect.Effect<unknown, unknown, TProvided>;
|
|
14
15
|
|
|
15
|
-
// A plain after hook yields nothing to infer, so TypeScript leaves its effect at the AnyEffect constraint.
|
|
16
|
-
type AfterEffects<TAfter> = { readonly [TKey in keyof TAfter]-?: AnyEffect extends TAfter[TKey] ? never : TAfter[TKey] }[keyof TAfter];
|
|
17
|
-
|
|
18
|
-
type LayerFor<THooks, TProvided> = [Exclude<ServicesOf<THooks>, Scope.Scope>] extends [TProvided]
|
|
19
|
-
? unknown
|
|
20
|
-
: { readonly layer: Layer.Layer<Exclude<ServicesOf<THooks>, Scope.Scope>, unknown, never> };
|
|
21
|
-
|
|
22
16
|
export interface RunUntilOptions {
|
|
23
17
|
readonly maxSteps?: number | undefined;
|
|
24
18
|
}
|
|
@@ -51,10 +45,10 @@ export interface StoryKitDefinition<
|
|
|
51
45
|
TFailed extends AnyEffect,
|
|
52
46
|
TDiagnose extends AnyEffect,
|
|
53
47
|
> {
|
|
54
|
-
readonly after?: { readonly [TKey in keyof TAfter]:
|
|
48
|
+
readonly after?: { readonly [TKey in keyof TAfter]: EffectHook<[engine: TEngine], TAfter[TKey] & AnyEffect, void> };
|
|
55
49
|
readonly around?: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, unknown, R | NoInfer<TProvided> | Scope.Scope>;
|
|
56
50
|
readonly clock?: EffectClock;
|
|
57
|
-
readonly create:
|
|
51
|
+
readonly create: EffectHook<[], TCreate, TEngine>;
|
|
58
52
|
readonly inspect?: (engine: TEngine) => unknown;
|
|
59
53
|
readonly layer?: Layer.Layer<TProvided, unknown, never>;
|
|
60
54
|
readonly name: string;
|
|
@@ -90,23 +84,32 @@ export interface StoryIt<TEngine, TStage extends string, TVerbs, TRun extends An
|
|
|
90
84
|
|
|
91
85
|
export interface StoryKit<TEngine, TStage extends string, TVerbs, TRun extends AnyEffect, TProvided> {
|
|
92
86
|
readonly it: StoryIt<TEngine, TStage, TVerbs, TRun, TProvided>;
|
|
93
|
-
readonly trait:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
87
|
+
readonly trait: {
|
|
88
|
+
<TEffect extends AnyEffect = never>(
|
|
89
|
+
stage: TStage,
|
|
90
|
+
line: string,
|
|
91
|
+
apply: Hook<[engine: TEngine], TEffect, void>,
|
|
92
|
+
): Trait<TEngine, TStage, ServicesOf<TEffect>>;
|
|
93
|
+
<E, R>(stage: TStage, line: string, apply: (engine: TEngine) => Effect.Effect<void, E, R>): Trait<TEngine, TStage, R>;
|
|
94
|
+
};
|
|
98
95
|
readonly traits: <const TGiven extends readonly Trait<TEngine, TStage, unknown>[]>(
|
|
99
96
|
...given: TGiven
|
|
100
97
|
) => Trait<TEngine, TStage, TraitServices<TGiven[number]>>;
|
|
101
98
|
}
|
|
102
99
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
100
|
+
export function storyKit<
|
|
101
|
+
TCreate extends () => unknown,
|
|
102
|
+
const TStage extends string,
|
|
103
|
+
TVerbs extends object,
|
|
104
|
+
TProvided = never,
|
|
105
|
+
TAfter extends AfterResults<TStage> = Record<never, never>,
|
|
106
|
+
TStep extends AnyEffect = never,
|
|
107
|
+
TFailed extends AnyEffect = never,
|
|
108
|
+
TDiagnose extends AnyEffect = never,
|
|
109
|
+
>(
|
|
110
|
+
definition: InferredDefinition<TCreate, TStage, TVerbs, TProvided, TAfter, TStep, TFailed, TDiagnose>,
|
|
111
|
+
): StoryKit<HookValue<ReturnType<TCreate>>, TStage, TVerbs, TStep | TFailed | TDiagnose, TProvided>;
|
|
112
|
+
// Keep explicit engine and effect type arguments accepted by existing kits.
|
|
110
113
|
export function storyKit<
|
|
111
114
|
TEngine,
|
|
112
115
|
const TStage extends string,
|
|
@@ -118,13 +121,13 @@ export function storyKit<
|
|
|
118
121
|
TFailed extends AnyEffect = never,
|
|
119
122
|
TDiagnose extends AnyEffect = never,
|
|
120
123
|
>(
|
|
121
|
-
definition:
|
|
122
|
-
LayerFor<TCreate | AfterEffects<TAfter> | TStep | TFailed | TDiagnose, TProvided>,
|
|
124
|
+
definition: LegacyDefinition<TEngine, TStage, TVerbs, TProvided, TCreate, TAfter, TStep, TFailed, TDiagnose>,
|
|
123
125
|
): StoryKit<TEngine, TStage, TVerbs, TStep | TFailed | TDiagnose, TProvided>;
|
|
124
|
-
export function storyKit(definition: LooseDefinition):
|
|
126
|
+
export function storyKit(definition: LooseDefinition): unknown {
|
|
125
127
|
return {
|
|
126
128
|
it: storyIt(definition),
|
|
127
|
-
trait: (stage, line, apply
|
|
129
|
+
trait: (stage: string, line: string, apply: EffectHook<[engine: unknown], AnyEffect, void>) =>
|
|
130
|
+
trait(stage, line, (engine: unknown) => hooked(() => apply(engine))),
|
|
128
131
|
traits,
|
|
129
132
|
};
|
|
130
133
|
}
|