foldkit 0.43.2 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/index.d.ts +2 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +2 -1
  4. package/dist/test/apps/counter.d.ts +38 -0
  5. package/dist/test/apps/counter.d.ts.map +1 -0
  6. package/dist/test/apps/counter.js +25 -0
  7. package/dist/test/apps/formChild.d.ts +69 -0
  8. package/dist/test/apps/formChild.d.ts.map +1 -0
  9. package/dist/test/apps/formChild.js +84 -0
  10. package/dist/test/apps/keypress.d.ts +23 -0
  11. package/dist/test/apps/keypress.d.ts.map +1 -0
  12. package/dist/test/apps/keypress.js +39 -0
  13. package/dist/test/apps/login.d.ts +46 -0
  14. package/dist/test/apps/login.d.ts.map +1 -0
  15. package/dist/test/apps/login.js +83 -0
  16. package/dist/test/apps/logoutButton.d.ts +17 -0
  17. package/dist/test/apps/logoutButton.d.ts.map +1 -0
  18. package/dist/test/apps/logoutButton.js +22 -0
  19. package/dist/test/internal.d.ts +25 -0
  20. package/dist/test/internal.d.ts.map +1 -0
  21. package/dist/test/internal.js +39 -0
  22. package/dist/test/matchers.d.ts +94 -0
  23. package/dist/test/matchers.d.ts.map +1 -0
  24. package/dist/test/matchers.js +283 -0
  25. package/dist/test/public.d.ts +2 -2
  26. package/dist/test/public.d.ts.map +1 -1
  27. package/dist/test/public.js +2 -1
  28. package/dist/test/query.d.ts +88 -0
  29. package/dist/test/query.d.ts.map +1 -0
  30. package/dist/test/query.js +227 -0
  31. package/dist/test/scene.d.ts +106 -0
  32. package/dist/test/scene.d.ts.map +1 -0
  33. package/dist/test/scene.js +373 -0
  34. package/dist/test/{index.d.ts → story.d.ts} +13 -17
  35. package/dist/test/story.d.ts.map +1 -0
  36. package/dist/test/{index.js → story.js} +8 -36
  37. package/dist/test/vitest-setup.d.ts +19 -0
  38. package/dist/test/vitest-setup.d.ts.map +1 -0
  39. package/dist/test/vitest-setup.js +3 -0
  40. package/dist/ui/input/index.d.ts +0 -2
  41. package/dist/ui/input/index.d.ts.map +1 -1
  42. package/dist/ui/input/index.js +2 -5
  43. package/dist/ui/input/public.d.ts +1 -1
  44. package/dist/ui/input/public.d.ts.map +1 -1
  45. package/dist/ui/input/public.js +1 -1
  46. package/dist/ui/select/index.d.ts +0 -2
  47. package/dist/ui/select/index.d.ts.map +1 -1
  48. package/dist/ui/select/index.js +2 -5
  49. package/dist/ui/select/public.d.ts +1 -1
  50. package/dist/ui/select/public.d.ts.map +1 -1
  51. package/dist/ui/select/public.js +1 -1
  52. package/dist/ui/textarea/index.d.ts +0 -2
  53. package/dist/ui/textarea/index.d.ts.map +1 -1
  54. package/dist/ui/textarea/index.js +2 -5
  55. package/dist/ui/textarea/public.d.ts +1 -1
  56. package/dist/ui/textarea/public.d.ts.map +1 -1
  57. package/dist/ui/textarea/public.js +1 -1
  58. package/package.json +5 -5
  59. package/dist/test/index.d.ts.map +0 -1
package/dist/index.d.ts CHANGED
@@ -10,7 +10,8 @@ export * as Schema from './schema/public';
10
10
  export * as Struct from './struct/public';
11
11
  export * as Subscription from './subscription/public';
12
12
  export * as Task from './task/public';
13
- export * as Test from './test/public';
13
+ export * as Scene from './test/scene';
14
+ export * as Story from './test/story';
14
15
  export * as Ui from './ui';
15
16
  export * as Url from './url/public';
16
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,eAAe,MAAM,0BAA0B,CAAA;AAC3D,OAAO,KAAK,eAAe,MAAM,0BAA0B,CAAA;AAC3D,OAAO,KAAK,IAAI,MAAM,eAAe,CAAA;AACrC,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,UAAU,MAAM,qBAAqB,CAAA;AACjD,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAA;AACvC,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAA;AACzC,OAAO,KAAK,YAAY,MAAM,uBAAuB,CAAA;AACrD,OAAO,KAAK,IAAI,MAAM,eAAe,CAAA;AACrC,OAAO,KAAK,IAAI,MAAM,eAAe,CAAA;AACrC,OAAO,KAAK,EAAE,MAAM,MAAM,CAAA;AAC1B,OAAO,KAAK,GAAG,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,eAAe,MAAM,0BAA0B,CAAA;AAC3D,OAAO,KAAK,eAAe,MAAM,0BAA0B,CAAA;AAC3D,OAAO,KAAK,IAAI,MAAM,eAAe,CAAA;AACrC,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,UAAU,MAAM,qBAAqB,CAAA;AACjD,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAA;AACvC,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,iBAAiB,CAAA;AACzC,OAAO,KAAK,YAAY,MAAM,uBAAuB,CAAA;AACrD,OAAO,KAAK,IAAI,MAAM,eAAe,CAAA;AACrC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,EAAE,MAAM,MAAM,CAAA;AAC1B,OAAO,KAAK,GAAG,MAAM,cAAc,CAAA"}
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ export * as Schema from './schema/public';
10
10
  export * as Struct from './struct/public';
11
11
  export * as Subscription from './subscription/public';
12
12
  export * as Task from './task/public';
13
- export * as Test from './test/public';
13
+ export * as Scene from './test/scene';
14
+ export * as Story from './test/story';
14
15
  export * as Ui from './ui';
15
16
  export * as Url from './url/public';
@@ -0,0 +1,38 @@
1
+ import { Effect, Schema as S } from 'effect';
2
+ import * as Command from '../../command';
3
+ export declare const Model: S.Struct<{
4
+ count: typeof S.Number;
5
+ }>;
6
+ export type Model = typeof Model.Type;
7
+ export declare const ClickedIncrement: import("../../schema").CallableTaggedStruct<"ClickedIncrement", {}>;
8
+ export declare const ClickedDecrement: import("../../schema").CallableTaggedStruct<"ClickedDecrement", {}>;
9
+ export declare const ClickedFetch: import("../../schema").CallableTaggedStruct<"ClickedFetch", {}>;
10
+ export declare const SucceededFetchCount: import("../../schema").CallableTaggedStruct<"SucceededFetchCount", {
11
+ count: typeof S.Number;
12
+ }>;
13
+ export declare const FailedFetchCount: import("../../schema").CallableTaggedStruct<"FailedFetchCount", {
14
+ error: typeof S.String;
15
+ }>;
16
+ export declare const Message: S.Union<[import("../../schema").CallableTaggedStruct<"ClickedIncrement", {}>, import("../../schema").CallableTaggedStruct<"ClickedDecrement", {}>, import("../../schema").CallableTaggedStruct<"ClickedFetch", {}>, import("../../schema").CallableTaggedStruct<"SucceededFetchCount", {
17
+ count: typeof S.Number;
18
+ }>, import("../../schema").CallableTaggedStruct<"FailedFetchCount", {
19
+ error: typeof S.String;
20
+ }>]>;
21
+ export type Message = typeof Message.Type;
22
+ export declare const FetchCount: Command.CommandDefinition<"FetchCount", {
23
+ readonly _tag: "SucceededFetchCount";
24
+ readonly count: number;
25
+ } | {
26
+ readonly _tag: "FailedFetchCount";
27
+ readonly error: string;
28
+ }>;
29
+ export declare const fetchCount: Readonly<{
30
+ name: "FetchCount";
31
+ effect: Effect.Effect<{
32
+ readonly _tag: "SucceededFetchCount";
33
+ readonly count: number;
34
+ }, never, never>;
35
+ }>;
36
+ export declare const initialModel: Model;
37
+ export declare const update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<Command.Command<Message>>];
38
+ //# sourceMappingURL=counter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"counter.d.ts","sourceRoot":"","sources":["../../../src/test/apps/counter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAc,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAExD,OAAO,KAAK,OAAO,MAAM,eAAe,CAAA;AAKxC,eAAO,MAAM,KAAK;;EAAgC,CAAA;AAClD,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,eAAO,MAAM,gBAAgB,qEAAwB,CAAA;AACrD,eAAO,MAAM,gBAAgB,qEAAwB,CAAA;AACrD,eAAO,MAAM,YAAY,iEAAoB,CAAA;AAC7C,eAAO,MAAM,mBAAmB;;EAAgD,CAAA;AAChF,eAAO,MAAM,gBAAgB;;EAA6C,CAAA;AAE1E,eAAO,MAAM,OAAO;;;;IAMnB,CAAA;AACD,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAIzC,eAAO,MAAM,UAAU;;;;;;EAItB,CAAA;AAED,eAAO,MAAM,UAAU;;;;;;EAEtB,CAAA;AAID,eAAO,MAAM,YAAY,EAAE,KAAoB,CAAA;AAI/C,eAAO,MAAM,MAAM,GACjB,OAAO,KAAK,EACZ,SAAS,OAAO,KACf,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAYxD,CAAA"}
@@ -0,0 +1,25 @@
1
+ import { Effect, Match as M, Schema as S } from 'effect';
2
+ import * as Command from '../../command';
3
+ import { m } from '../../message';
4
+ // MODEL
5
+ export const Model = S.Struct({ count: S.Number });
6
+ // MESSAGE
7
+ export const ClickedIncrement = m('ClickedIncrement');
8
+ export const ClickedDecrement = m('ClickedDecrement');
9
+ export const ClickedFetch = m('ClickedFetch');
10
+ export const SucceededFetchCount = m('SucceededFetchCount', { count: S.Number });
11
+ export const FailedFetchCount = m('FailedFetchCount', { error: S.String });
12
+ export const Message = S.Union(ClickedIncrement, ClickedDecrement, ClickedFetch, SucceededFetchCount, FailedFetchCount);
13
+ // COMMAND
14
+ export const FetchCount = Command.define('FetchCount', SucceededFetchCount, FailedFetchCount);
15
+ export const fetchCount = FetchCount(Effect.sync(() => SucceededFetchCount({ count: 0 })));
16
+ // INIT
17
+ export const initialModel = { count: 0 };
18
+ // UPDATE
19
+ export const update = (model, message) => M.value(message).pipe(M.withReturnType(), M.tagsExhaustive({
20
+ ClickedIncrement: () => [{ count: model.count + 1 }, []],
21
+ ClickedDecrement: () => [{ count: model.count - 1 }, []],
22
+ ClickedFetch: () => [model, [fetchCount]],
23
+ SucceededFetchCount: ({ count }) => [{ count }, []],
24
+ FailedFetchCount: () => [model, []],
25
+ }));
@@ -0,0 +1,69 @@
1
+ import { Effect, Option, Schema as S } from 'effect';
2
+ import * as Command from '../../command';
3
+ export declare const ChildModel: S.Struct<{
4
+ status: S.Literal<["Idle", "Submitting", "Submitted"]>;
5
+ }>;
6
+ export type ChildModel = typeof ChildModel.Type;
7
+ export declare const SubmittedForm: import("../../schema").CallableTaggedStruct<"SubmittedForm", {}>;
8
+ export declare const SucceededSubmit: import("../../schema").CallableTaggedStruct<"SucceededSubmit", {
9
+ id: typeof S.String;
10
+ }>;
11
+ export declare const CancelledForm: import("../../schema").CallableTaggedStruct<"CancelledForm", {}>;
12
+ export declare const CompletedReset: import("../../schema").CallableTaggedStruct<"CompletedReset", {}>;
13
+ export declare const ChildMessage: S.Union<[import("../../schema").CallableTaggedStruct<"SubmittedForm", {}>, import("../../schema").CallableTaggedStruct<"SucceededSubmit", {
14
+ id: typeof S.String;
15
+ }>, import("../../schema").CallableTaggedStruct<"CancelledForm", {}>, import("../../schema").CallableTaggedStruct<"CompletedReset", {}>]>;
16
+ export type ChildMessage = typeof ChildMessage.Type;
17
+ export declare const RequestedSave: import("../../schema").CallableTaggedStruct<"RequestedSave", {
18
+ id: typeof S.String;
19
+ }>;
20
+ export declare const RequestedCancel: import("../../schema").CallableTaggedStruct<"RequestedCancel", {}>;
21
+ export declare const ChildOutMessage: S.Union<[import("../../schema").CallableTaggedStruct<"RequestedSave", {
22
+ id: typeof S.String;
23
+ }>, import("../../schema").CallableTaggedStruct<"RequestedCancel", {}>]>;
24
+ export type ChildOutMessage = typeof ChildOutMessage.Type;
25
+ export declare const SubmitForm: Command.CommandDefinition<"SubmitForm", {
26
+ readonly _tag: "SucceededSubmit";
27
+ readonly id: string;
28
+ }>;
29
+ export declare const submitForm: Readonly<{
30
+ name: "SubmitForm";
31
+ effect: Effect.Effect<{
32
+ readonly _tag: "SucceededSubmit";
33
+ readonly id: string;
34
+ }, never, never>;
35
+ }>;
36
+ export declare const ResetForm: Command.CommandDefinition<"ResetForm", {
37
+ readonly _tag: "CompletedReset";
38
+ }>;
39
+ export declare const resetForm: Readonly<{
40
+ name: "ResetForm";
41
+ effect: Effect.Effect<{
42
+ readonly _tag: "CompletedReset";
43
+ }, never, never>;
44
+ }>;
45
+ export declare const initialChildModel: ChildModel;
46
+ export declare const childUpdate: (_model: ChildModel, message: ChildMessage) => readonly [ChildModel, ReadonlyArray<Command.Command<ChildMessage>>, Option.Option<ChildOutMessage>];
47
+ export declare const ParentModel: S.Struct<{
48
+ child: S.Struct<{
49
+ status: S.Literal<["Idle", "Submitting", "Submitted"]>;
50
+ }>;
51
+ savedIds: S.Array$<typeof S.String>;
52
+ cancelled: typeof S.Boolean;
53
+ }>;
54
+ export type ParentModel = typeof ParentModel.Type;
55
+ export declare const GotChildMessage: import("../../schema").CallableTaggedStruct<"GotChildMessage", {
56
+ message: S.Union<[import("../../schema").CallableTaggedStruct<"SubmittedForm", {}>, import("../../schema").CallableTaggedStruct<"SucceededSubmit", {
57
+ id: typeof S.String;
58
+ }>, import("../../schema").CallableTaggedStruct<"CancelledForm", {}>, import("../../schema").CallableTaggedStruct<"CompletedReset", {}>]>;
59
+ }>;
60
+ export declare const CompletedParentReset: import("../../schema").CallableTaggedStruct<"CompletedParentReset", {}>;
61
+ export declare const ParentMessage: S.Union<[import("../../schema").CallableTaggedStruct<"GotChildMessage", {
62
+ message: S.Union<[import("../../schema").CallableTaggedStruct<"SubmittedForm", {}>, import("../../schema").CallableTaggedStruct<"SucceededSubmit", {
63
+ id: typeof S.String;
64
+ }>, import("../../schema").CallableTaggedStruct<"CancelledForm", {}>, import("../../schema").CallableTaggedStruct<"CompletedReset", {}>]>;
65
+ }>, import("../../schema").CallableTaggedStruct<"CompletedParentReset", {}>]>;
66
+ export type ParentMessage = typeof ParentMessage.Type;
67
+ export declare const initialParentModel: ParentModel;
68
+ export declare const parentUpdate: (parentModel: ParentModel, message: ParentMessage) => readonly [ParentModel, ReadonlyArray<Command.Command<ChildMessage>>];
69
+ //# sourceMappingURL=formChild.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formChild.d.ts","sourceRoot":"","sources":["../../../src/test/apps/formChild.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAc,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAEhE,OAAO,KAAK,OAAO,MAAM,eAAe,CAAA;AAKxC,eAAO,MAAM,UAAU;;EAErB,CAAA;AACF,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA;AAI/C,eAAO,MAAM,aAAa,kEAAqB,CAAA;AAC/C,eAAO,MAAM,eAAe;;EAAyC,CAAA;AACrE,eAAO,MAAM,aAAa,kEAAqB,CAAA;AAC/C,eAAO,MAAM,cAAc,mEAAsB,CAAA;AAEjD,eAAO,MAAM,YAAY;;yIAKxB,CAAA;AACD,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA;AAInD,eAAO,MAAM,aAAa;;EAAuC,CAAA;AACjE,eAAO,MAAM,eAAe,oEAAuB,CAAA;AAEnD,eAAO,MAAM,eAAe;;wEAA0C,CAAA;AACtE,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAA;AAIzD,eAAO,MAAM,UAAU;;;EAAgD,CAAA;AACvE,eAAO,MAAM,UAAU;;;;;;EAEtB,CAAA;AAED,eAAO,MAAM,SAAS;;EAA8C,CAAA;AACpE,eAAO,MAAM,SAAS;;;;;EAAiD,CAAA;AAIvE,eAAO,MAAM,iBAAiB,EAAE,UAA+B,CAAA;AAI/D,eAAO,MAAM,WAAW,GACtB,QAAQ,UAAU,EAClB,SAAS,YAAY,KACpB,SAAS,CACV,UAAU,EACV,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,EAC5C,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CA4B7B,CAAA;AAIH,eAAO,MAAM,WAAW;;;;;;EAItB,CAAA;AACF,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;AAIjD,eAAO,MAAM,eAAe;;;;EAE1B,CAAA;AACF,eAAO,MAAM,oBAAoB,yEAA4B,CAAA;AAE7D,eAAO,MAAM,aAAa;;;;6EAAiD,CAAA;AAC3E,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;AAIrD,eAAO,MAAM,kBAAkB,EAAE,WAIhC,CAAA;AAID,eAAO,MAAM,YAAY,GACvB,aAAa,WAAW,EACxB,SAAS,aAAa,KACrB,SAAS,CAAC,WAAW,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAkCnE,CAAA"}
@@ -0,0 +1,84 @@
1
+ import { Effect, Match as M, Option, Schema as S } from 'effect';
2
+ import * as Command from '../../command';
3
+ import { m } from '../../message';
4
+ // CHILD MODEL
5
+ export const ChildModel = S.Struct({
6
+ status: S.Literal('Idle', 'Submitting', 'Submitted'),
7
+ });
8
+ // CHILD MESSAGE
9
+ export const SubmittedForm = m('SubmittedForm');
10
+ export const SucceededSubmit = m('SucceededSubmit', { id: S.String });
11
+ export const CancelledForm = m('CancelledForm');
12
+ export const CompletedReset = m('CompletedReset');
13
+ export const ChildMessage = S.Union(SubmittedForm, SucceededSubmit, CancelledForm, CompletedReset);
14
+ // CHILD OUT MESSAGE
15
+ export const RequestedSave = m('RequestedSave', { id: S.String });
16
+ export const RequestedCancel = m('RequestedCancel');
17
+ export const ChildOutMessage = S.Union(RequestedSave, RequestedCancel);
18
+ // CHILD COMMAND
19
+ export const SubmitForm = Command.define('SubmitForm', SucceededSubmit);
20
+ export const submitForm = SubmitForm(Effect.sync(() => SucceededSubmit({ id: 'abc' })));
21
+ export const ResetForm = Command.define('ResetForm', CompletedReset);
22
+ export const resetForm = ResetForm(Effect.sync(() => CompletedReset()));
23
+ // CHILD INIT
24
+ export const initialChildModel = { status: 'Idle' };
25
+ // CHILD UPDATE
26
+ export const childUpdate = (_model, message) => M.value(message).pipe(M.withReturnType(), M.tagsExhaustive({
27
+ SubmittedForm: () => [
28
+ { status: 'Submitting' },
29
+ [submitForm],
30
+ Option.none(),
31
+ ],
32
+ SucceededSubmit: ({ id }) => [
33
+ { status: 'Submitted' },
34
+ [resetForm],
35
+ Option.some(RequestedSave({ id })),
36
+ ],
37
+ CancelledForm: () => [
38
+ { status: 'Idle' },
39
+ [],
40
+ Option.some(RequestedCancel()),
41
+ ],
42
+ CompletedReset: () => [{ status: 'Idle' }, [], Option.none()],
43
+ }));
44
+ // PARENT MODEL
45
+ export const ParentModel = S.Struct({
46
+ child: ChildModel,
47
+ savedIds: S.Array(S.String),
48
+ cancelled: S.Boolean,
49
+ });
50
+ // PARENT MESSAGE
51
+ export const GotChildMessage = m('GotChildMessage', {
52
+ message: ChildMessage,
53
+ });
54
+ export const CompletedParentReset = m('CompletedParentReset');
55
+ export const ParentMessage = S.Union(GotChildMessage, CompletedParentReset);
56
+ // PARENT INIT
57
+ export const initialParentModel = {
58
+ child: { status: 'Idle' },
59
+ savedIds: [],
60
+ cancelled: false,
61
+ };
62
+ // PARENT UPDATE
63
+ export const parentUpdate = (parentModel, message) => M.value(message).pipe(M.withReturnType(), M.tagsExhaustive({
64
+ GotChildMessage: ({ message: childMessage }) => {
65
+ const [nextChild, commands, maybeOutMessage] = childUpdate(parentModel.child, childMessage);
66
+ const nextParent = Option.match(maybeOutMessage, {
67
+ onNone: () => ({ ...parentModel, child: nextChild }),
68
+ onSome: outMessage => M.value(outMessage).pipe(M.withReturnType(), M.tagsExhaustive({
69
+ RequestedSave: ({ id }) => ({
70
+ ...parentModel,
71
+ child: nextChild,
72
+ savedIds: [...parentModel.savedIds, id],
73
+ }),
74
+ RequestedCancel: () => ({
75
+ ...parentModel,
76
+ child: nextChild,
77
+ cancelled: true,
78
+ }),
79
+ })),
80
+ });
81
+ return [nextParent, commands];
82
+ },
83
+ CompletedParentReset: () => [parentModel, []],
84
+ }));
@@ -0,0 +1,23 @@
1
+ import { Schema as S } from 'effect';
2
+ import type { Html } from '../../html';
3
+ export declare const Model: S.Struct<{
4
+ lastKey: typeof S.String;
5
+ isShifted: typeof S.Boolean;
6
+ }>;
7
+ export type Model = typeof Model.Type;
8
+ export declare const PressedKey: import("../../schema").CallableTaggedStruct<"PressedKey", {
9
+ key: typeof S.String;
10
+ }>;
11
+ export declare const PressedShiftKey: import("../../schema").CallableTaggedStruct<"PressedShiftKey", {
12
+ key: typeof S.String;
13
+ }>;
14
+ export declare const Message: S.Union<[import("../../schema").CallableTaggedStruct<"PressedKey", {
15
+ key: typeof S.String;
16
+ }>, import("../../schema").CallableTaggedStruct<"PressedShiftKey", {
17
+ key: typeof S.String;
18
+ }>]>;
19
+ export type Message = typeof Message.Type;
20
+ export declare const initialModel: Model;
21
+ export declare const update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<never>];
22
+ export declare const view: (model: Model) => Html;
23
+ //# sourceMappingURL=keypress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keypress.d.ts","sourceRoot":"","sources":["../../../src/test/apps/keypress.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAEhD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAMtC,eAAO,MAAM,KAAK;;;EAGhB,CAAA;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,eAAO,MAAM,UAAU;;EAAqC,CAAA;AAC5D,eAAO,MAAM,eAAe;;EAA0C,CAAA;AAEtE,eAAO,MAAM,OAAO;;;;IAAuC,CAAA;AAC3D,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAIzC,eAAO,MAAM,YAAY,EAAE,KAG1B,CAAA;AAID,eAAO,MAAM,MAAM,GACjB,OAAO,KAAK,EACZ,SAAS,OAAO,KACf,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,CAarC,CAAA;AAMH,eAAO,MAAM,IAAI,GAAI,OAAO,KAAK,KAAG,IAiBjC,CAAA"}
@@ -0,0 +1,39 @@
1
+ import { Match as M, Schema as S } from 'effect';
2
+ import { html } from '../../html';
3
+ import { m } from '../../message';
4
+ // MODEL
5
+ export const Model = S.Struct({
6
+ lastKey: S.String,
7
+ isShifted: S.Boolean,
8
+ });
9
+ // MESSAGE
10
+ export const PressedKey = m('PressedKey', { key: S.String });
11
+ export const PressedShiftKey = m('PressedShiftKey', { key: S.String });
12
+ export const Message = S.Union(PressedKey, PressedShiftKey);
13
+ // INIT
14
+ export const initialModel = {
15
+ lastKey: '',
16
+ isShifted: false,
17
+ };
18
+ // UPDATE
19
+ export const update = (model, message) => M.value(message).pipe(M.withReturnType(), M.tagsExhaustive({
20
+ PressedKey: ({ key }) => [
21
+ { ...model, lastKey: key, isShifted: false },
22
+ [],
23
+ ],
24
+ PressedShiftKey: ({ key }) => [
25
+ { ...model, lastKey: key, isShifted: true },
26
+ [],
27
+ ],
28
+ }));
29
+ // VIEW
30
+ const { div, span, Id, Class, AriaLabel, Role, OnKeyDown } = html();
31
+ export const view = (model) => div([
32
+ Id('key-app'),
33
+ Role('application'),
34
+ AriaLabel('Key press area'),
35
+ OnKeyDown((key, modifiers) => modifiers.shiftKey ? PressedShiftKey({ key }) : PressedKey({ key })),
36
+ ], [
37
+ span([Class('last-key'), AriaLabel('Last key')], [model.lastKey]),
38
+ span([Class('shifted'), AriaLabel('Shift pressed')], [model.isShifted ? 'true' : 'false']),
39
+ ]);
@@ -0,0 +1,46 @@
1
+ import { Schema as S } from 'effect';
2
+ import * as Command from '../../command';
3
+ import { type Html } from '../../html';
4
+ export declare const Model: S.Struct<{
5
+ email: typeof S.String;
6
+ password: typeof S.String;
7
+ status: S.Literal<["Idle", "Submitting", "LoggedIn", "Error"]>;
8
+ username: typeof S.String;
9
+ error: typeof S.String;
10
+ }>;
11
+ export type Model = typeof Model.Type;
12
+ export declare const UpdatedEmail: import("../../schema").CallableTaggedStruct<"UpdatedEmail", {
13
+ value: typeof S.String;
14
+ }>;
15
+ export declare const UpdatedPassword: import("../../schema").CallableTaggedStruct<"UpdatedPassword", {
16
+ value: typeof S.String;
17
+ }>;
18
+ export declare const SubmittedLogin: import("../../schema").CallableTaggedStruct<"SubmittedLogin", {}>;
19
+ export declare const SucceededAuthenticate: import("../../schema").CallableTaggedStruct<"SucceededAuthenticate", {
20
+ username: typeof S.String;
21
+ }>;
22
+ export declare const FailedAuthenticate: import("../../schema").CallableTaggedStruct<"FailedAuthenticate", {
23
+ error: typeof S.String;
24
+ }>;
25
+ export declare const ClickedLogout: import("../../schema").CallableTaggedStruct<"ClickedLogout", {}>;
26
+ export declare const Message: S.Union<[import("../../schema").CallableTaggedStruct<"UpdatedEmail", {
27
+ value: typeof S.String;
28
+ }>, import("../../schema").CallableTaggedStruct<"UpdatedPassword", {
29
+ value: typeof S.String;
30
+ }>, import("../../schema").CallableTaggedStruct<"SubmittedLogin", {}>, import("../../schema").CallableTaggedStruct<"SucceededAuthenticate", {
31
+ username: typeof S.String;
32
+ }>, import("../../schema").CallableTaggedStruct<"FailedAuthenticate", {
33
+ error: typeof S.String;
34
+ }>, import("../../schema").CallableTaggedStruct<"ClickedLogout", {}>]>;
35
+ export type Message = typeof Message.Type;
36
+ export declare const Authenticate: Command.CommandDefinition<"Authenticate", {
37
+ readonly _tag: "SucceededAuthenticate";
38
+ readonly username: string;
39
+ } | {
40
+ readonly _tag: "FailedAuthenticate";
41
+ readonly error: string;
42
+ }>;
43
+ export declare const initialModel: Model;
44
+ export declare const update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<Command.Command<Message>>];
45
+ export declare const view: (model: Model) => Html;
46
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/test/apps/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAExD,OAAO,KAAK,OAAO,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,KAAK,IAAI,EAAQ,MAAM,YAAY,CAAA;AAK5C,eAAO,MAAM,KAAK;;;;;;EAMhB,CAAA;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,eAAO,MAAM,YAAY;;EAAyC,CAAA;AAClE,eAAO,MAAM,eAAe;;EAA4C,CAAA;AACxE,eAAO,MAAM,cAAc,mEAAsB,CAAA;AACjD,eAAO,MAAM,qBAAqB;;EAEhC,CAAA;AACF,eAAO,MAAM,kBAAkB;;EAA+C,CAAA;AAC9E,eAAO,MAAM,aAAa,kEAAqB,CAAA;AAE/C,eAAO,MAAM,OAAO;;;;;;;;sEAOnB,CAAA;AACD,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAIzC,eAAO,MAAM,YAAY;;;;;;EAIxB,CAAA;AAQD,eAAO,MAAM,YAAY,EAAE,KAM1B,CAAA;AAID,eAAO,MAAM,MAAM,GACjB,OAAO,KAAK,EACZ,SAAS,OAAO,KACf,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAyBxD,CAAA;AA2BH,eAAO,MAAM,IAAI,GAAI,OAAO,KAAK,KAAG,IAkEjC,CAAA"}
@@ -0,0 +1,83 @@
1
+ import { Effect, Match as M, Schema as S } from 'effect';
2
+ import * as Command from '../../command';
3
+ import { html } from '../../html';
4
+ import { m } from '../../message';
5
+ // MODEL
6
+ export const Model = S.Struct({
7
+ email: S.String,
8
+ password: S.String,
9
+ status: S.Literal('Idle', 'Submitting', 'LoggedIn', 'Error'),
10
+ username: S.String,
11
+ error: S.String,
12
+ });
13
+ // MESSAGE
14
+ export const UpdatedEmail = m('UpdatedEmail', { value: S.String });
15
+ export const UpdatedPassword = m('UpdatedPassword', { value: S.String });
16
+ export const SubmittedLogin = m('SubmittedLogin');
17
+ export const SucceededAuthenticate = m('SucceededAuthenticate', {
18
+ username: S.String,
19
+ });
20
+ export const FailedAuthenticate = m('FailedAuthenticate', { error: S.String });
21
+ export const ClickedLogout = m('ClickedLogout');
22
+ export const Message = S.Union(UpdatedEmail, UpdatedPassword, SubmittedLogin, SucceededAuthenticate, FailedAuthenticate, ClickedLogout);
23
+ // COMMAND
24
+ export const Authenticate = Command.define('Authenticate', SucceededAuthenticate, FailedAuthenticate);
25
+ const authenticate = Authenticate(Effect.sync(() => SucceededAuthenticate({ username: 'alice' })));
26
+ // INIT
27
+ export const initialModel = {
28
+ email: '',
29
+ password: '',
30
+ status: 'Idle',
31
+ username: '',
32
+ error: '',
33
+ };
34
+ // UPDATE
35
+ export const update = (model, message) => M.value(message).pipe(M.withReturnType(), M.tagsExhaustive({
36
+ UpdatedEmail: ({ value }) => [{ ...model, email: value }, []],
37
+ UpdatedPassword: ({ value }) => [{ ...model, password: value }, []],
38
+ SubmittedLogin: () => [
39
+ { ...model, status: 'Submitting' },
40
+ [authenticate],
41
+ ],
42
+ SucceededAuthenticate: ({ username }) => [
43
+ { ...model, status: 'LoggedIn', username },
44
+ [],
45
+ ],
46
+ FailedAuthenticate: ({ error }) => [
47
+ { ...model, status: 'Error', error },
48
+ [],
49
+ ],
50
+ ClickedLogout: () => [
51
+ { ...model, status: 'Idle', username: '', email: '', password: '' },
52
+ [],
53
+ ],
54
+ }));
55
+ // VIEW
56
+ const { div, form, input, button, span, label, p, OnInput, OnSubmit, OnClick, Id, For, Class, Type, Value, Placeholder, Role, AriaExpanded, AriaLabel, Disabled, } = html();
57
+ export const view = (model) => div([Id('app')], [
58
+ M.value(model.status).pipe(M.withReturnType(), M.when('Submitting', () => form([Class('login-form'), Disabled(true)], [button([Type('submit'), Disabled(true)], ['Signing in...'])])), M.when('LoggedIn', () => div([Class('logged-in'), Role('region'), AriaLabel('User session')], [
59
+ span([Class('greeting'), Role('status')], [`Welcome, ${model.username}!`]),
60
+ button([OnClick(ClickedLogout()), Role('button'), AriaExpanded(false)], ['Log out']),
61
+ ])), M.when('Error', () => div([], [
62
+ p([Class('error'), Role('alert')], [model.error]),
63
+ button([OnClick(SubmittedLogin()), Class('retry')], ['Retry']),
64
+ ])), M.when('Idle', () => form([OnSubmit(SubmittedLogin()), Class('login-form')], [
65
+ label([For('email'), Class('sr-only')], ['Email']),
66
+ input([
67
+ Id('email'),
68
+ Type('email'),
69
+ Placeholder('Email'),
70
+ Value(model.email),
71
+ OnInput(value => UpdatedEmail({ value })),
72
+ ]),
73
+ label([For('password'), Class('sr-only')], ['Password']),
74
+ input([
75
+ Id('password'),
76
+ Type('password'),
77
+ Placeholder('Password'),
78
+ Value(model.password),
79
+ OnInput(value => UpdatedPassword({ value })),
80
+ ]),
81
+ button([Type('submit'), Class('primary'), Disabled(false)], ['Sign in']),
82
+ ])), M.exhaustive),
83
+ ]);
@@ -0,0 +1,17 @@
1
+ import { Option, Schema as S } from 'effect';
2
+ import type { Html } from '../../html';
3
+ export declare const Model: S.Struct<{
4
+ label: typeof S.String;
5
+ }>;
6
+ export type Model = typeof Model.Type;
7
+ export declare const ClickedLogout: import("../../schema").CallableTaggedStruct<"ClickedLogout", {}>;
8
+ export declare const CompletedAction: import("../../schema").CallableTaggedStruct<"CompletedAction", {}>;
9
+ export declare const Message: S.Union<[import("../../schema").CallableTaggedStruct<"ClickedLogout", {}>, import("../../schema").CallableTaggedStruct<"CompletedAction", {}>]>;
10
+ export type Message = typeof Message.Type;
11
+ export declare const RequestedLogout: import("../../schema").CallableTaggedStruct<"RequestedLogout", {}>;
12
+ export declare const OutMessage: import("../../schema").CallableTaggedStruct<"RequestedLogout", {}>;
13
+ export type OutMessage = typeof OutMessage.Type;
14
+ export declare const initialModel: Model;
15
+ export declare const update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<never>, Option.Option<OutMessage>];
16
+ export declare const view: (model: Model) => Html;
17
+ //# sourceMappingURL=logoutButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logoutButton.d.ts","sourceRoot":"","sources":["../../../src/test/apps/logoutButton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAExD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAMtC,eAAO,MAAM,KAAK;;EAAgC,CAAA;AAClD,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,eAAO,MAAM,aAAa,kEAAqB,CAAA;AAC/C,eAAO,MAAM,eAAe,oEAAuB,CAAA;AAEnD,eAAO,MAAM,OAAO,iJAA0C,CAAA;AAC9D,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAIzC,eAAO,MAAM,eAAe,oEAAuB,CAAA;AAEnD,eAAO,MAAM,UAAU,oEAA2B,CAAA;AAClD,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA;AAI/C,eAAO,MAAM,YAAY,EAAE,KAA4B,CAAA;AAIvD,eAAO,MAAM,MAAM,GACjB,OAAO,KAAK,EACZ,SAAS,OAAO,KACf,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAShE,CAAA;AAMH,eAAO,MAAM,IAAI,GAAI,OAAO,KAAK,KAAG,IAC0C,CAAA"}
@@ -0,0 +1,22 @@
1
+ import { Match as M, Option, Schema as S } from 'effect';
2
+ import { html } from '../../html';
3
+ import { m } from '../../message';
4
+ // MODEL
5
+ export const Model = S.Struct({ label: S.String });
6
+ // MESSAGE
7
+ export const ClickedLogout = m('ClickedLogout');
8
+ export const CompletedAction = m('CompletedAction');
9
+ export const Message = S.Union(ClickedLogout, CompletedAction);
10
+ // OUT MESSAGE
11
+ export const RequestedLogout = m('RequestedLogout');
12
+ export const OutMessage = S.Union(RequestedLogout);
13
+ // INIT
14
+ export const initialModel = { label: 'Log out' };
15
+ // UPDATE
16
+ export const update = (model, message) => M.value(message).pipe(M.withReturnType(), M.tagsExhaustive({
17
+ ClickedLogout: () => [model, [], Option.some(RequestedLogout())],
18
+ CompletedAction: () => [model, [], Option.none()],
19
+ }));
20
+ // VIEW
21
+ const { div, button, OnClick, Role } = html();
22
+ export const view = (model) => div([], [button([OnClick(ClickedLogout()), Role('button')], [model.label])]);
@@ -0,0 +1,25 @@
1
+ import type { CommandDefinition } from '../command';
2
+ /** A Command in a test simulation, identified by name. */
3
+ export type AnyCommand = Readonly<{
4
+ name: string;
5
+ }>;
6
+ type UpdateResult<Model, OutMessage> = readonly [Model, ReadonlyArray<AnyCommand>] | readonly [Model, ReadonlyArray<AnyCommand>, OutMessage];
7
+ /** A Command definition paired with the result Message to resolve it with. */
8
+ export type ResolverPair<Name extends string = string, ResultMessage = unknown> = readonly [CommandDefinition<Name, ResultMessage>, ResultMessage];
9
+ /** Base shape of an internal simulation — shared between Story and Scene. */
10
+ export type BaseInternal<Model, Message, OutMessage = undefined> = Readonly<{
11
+ model: Model;
12
+ message: Message | undefined;
13
+ commands: ReadonlyArray<AnyCommand>;
14
+ outMessage: OutMessage;
15
+ updateFn: (model: Model, message: Message) => UpdateResult<Model, OutMessage>;
16
+ resolvers: Record<string, Message>;
17
+ }>;
18
+ /** Resolves a single command by name and feeds its result through update. */
19
+ export declare const resolveByName: <Model, Message>(internal: BaseInternal<Model, Message, unknown>, commandName: string, resolverMessage: Message) => BaseInternal<Model, Message, unknown> | undefined;
20
+ /** Throws when trying to send a message with unresolved Commands. */
21
+ export declare const assertNoUnresolvedCommands: (commands: ReadonlyArray<AnyCommand>, context: string) => void;
22
+ /** Throws when Commands remain at the end of a test. */
23
+ export declare const assertAllCommandsResolved: (commands: ReadonlyArray<AnyCommand>) => void;
24
+ export {};
25
+ //# sourceMappingURL=internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/test/internal.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEnD,0DAA0D;AAC1D,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAEnD,KAAK,YAAY,CAAC,KAAK,EAAE,UAAU,IAC/B,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC,GAC3C,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,CAAA;AAE3D,8EAA8E;AAC9E,MAAM,MAAM,YAAY,CACtB,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,aAAa,GAAG,OAAO,IACrB,SAAS,CAAC,iBAAiB,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE,aAAa,CAAC,CAAA;AAEpE,6EAA6E;AAC7E,MAAM,MAAM,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,GAAG,SAAS,IAAI,QAAQ,CAAC;IAC1E,KAAK,EAAE,KAAK,CAAA;IACZ,OAAO,EAAE,OAAO,GAAG,SAAS,CAAA;IAC5B,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,CAAA;IACnC,UAAU,EAAE,UAAU,CAAA;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,KAAK,YAAY,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;IAC7E,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC,CAAC,CAAA;AAEF,6EAA6E;AAC7E,eAAO,MAAM,aAAa,GAAI,KAAK,EAAE,OAAO,EAC1C,UAAU,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAC/C,aAAa,MAAM,EACnB,iBAAiB,OAAO,KACvB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,SAyBxC,CAAA;AAEH,qEAAqE;AACrE,eAAO,MAAM,0BAA0B,GACrC,UAAU,aAAa,CAAC,UAAU,CAAC,EACnC,SAAS,MAAM,KACd,IAcF,CAAA;AAED,wDAAwD;AACxD,eAAO,MAAM,yBAAyB,GACpC,UAAU,aAAa,CAAC,UAAU,CAAC,KAClC,IAcF,CAAA"}
@@ -0,0 +1,39 @@
1
+ import { Array, Option, pipe } from 'effect';
2
+ /** Resolves a single command by name and feeds its result through update. */
3
+ export const resolveByName = (internal, commandName, resolverMessage) => pipe(internal.commands, Array.findFirstIndex(({ name }) => name === commandName), Option.match({
4
+ onNone: () => undefined,
5
+ onSome: commandIndex => {
6
+ const remainingCommands = Array.remove(internal.commands, commandIndex);
7
+ const [nextModel, newCommands, ...rest] = internal.updateFn(internal.model, resolverMessage);
8
+ const outMessage = Array.isNonEmptyArray(rest)
9
+ ? rest[0]
10
+ : internal.outMessage;
11
+ return {
12
+ ...internal,
13
+ model: nextModel,
14
+ message: resolverMessage,
15
+ commands: Array.appendAll(remainingCommands, newCommands),
16
+ outMessage,
17
+ };
18
+ },
19
+ }));
20
+ /** Throws when trying to send a message with unresolved Commands. */
21
+ export const assertNoUnresolvedCommands = (commands, context) => {
22
+ if (Array.isNonEmptyReadonlyArray(commands)) {
23
+ const names = pipe(commands, Array.map(({ name }) => ` ${name}`), Array.join('\n'));
24
+ throw new Error(`I found unresolved Commands ${context}:\n\n${names}\n\n` +
25
+ 'Resolve all Commands before sending the next Message.\n' +
26
+ 'Use resolve(Definition, ResultMessage) for each one,\n' +
27
+ 'or resolveAll([...pairs]) to resolve them all at once.');
28
+ }
29
+ };
30
+ /** Throws when Commands remain at the end of a test. */
31
+ export const assertAllCommandsResolved = (commands) => {
32
+ if (Array.isNonEmptyReadonlyArray(commands)) {
33
+ const names = pipe(commands, Array.map(({ name }) => ` ${name}`), Array.join('\n'));
34
+ throw new Error(`I found Commands without resolvers:\n\n${names}\n\n` +
35
+ 'Every Command produced by update needs to be resolved.\n' +
36
+ 'Use resolve(Definition, ResultMessage) for each one,\n' +
37
+ 'or resolveAll([...pairs]) to resolve them all at once.');
38
+ }
39
+ };