ballerina-core 1.0.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 (118) hide show
  1. package/main.ts +149 -0
  2. package/package.json +20 -0
  3. package/src/apiResultStatus/state.ts +7 -0
  4. package/src/async/domains/mirroring/domains/collection/coroutines/synchronizers.ts +334 -0
  5. package/src/async/domains/mirroring/domains/collection/state.ts +137 -0
  6. package/src/async/domains/mirroring/domains/entity/domains/loaded-collection/state.ts +24 -0
  7. package/src/async/domains/mirroring/domains/entity/domains/loaded-collection-entity/state.ts +27 -0
  8. package/src/async/domains/mirroring/domains/entity/domains/loaded-entities/state.ts +12 -0
  9. package/src/async/domains/mirroring/domains/entity/domains/loaded-entity/state.ts +29 -0
  10. package/src/async/domains/mirroring/domains/entity/state.ts +22 -0
  11. package/src/async/domains/mirroring/domains/singleton/coroutines/synchronizers.ts +216 -0
  12. package/src/async/domains/mirroring/domains/singleton/state.ts +57 -0
  13. package/src/async/domains/mirroring/domains/synchronization-result/state.ts +2 -0
  14. package/src/async/domains/mirroring/domains/synchronized-entities/state.ts +23 -0
  15. package/src/async/domains/promise/state.ts +13 -0
  16. package/src/async/domains/synchronized/coroutines/synchronize.ts +62 -0
  17. package/src/async/domains/synchronized/state.ts +20 -0
  18. package/src/async/state.ts +144 -0
  19. package/src/baseEntity/domains/identifiable/state.ts +29 -0
  20. package/src/collections/domains/array/state.ts +16 -0
  21. package/src/collections/domains/immutable/domains/list/state.ts +20 -0
  22. package/src/collections/domains/immutable/domains/map/state.ts +33 -0
  23. package/src/collections/domains/immutable/domains/orderedMap/state.ts +117 -0
  24. package/src/collections/domains/immutable/domains/ordereredSet/state.ts +19 -0
  25. package/src/collections/domains/immutable/domains/set/state.ts +15 -0
  26. package/src/collections/domains/maybe/state.ts +20 -0
  27. package/src/collections/domains/product/state.ts +47 -0
  28. package/src/collections/domains/sum/state.ts +82 -0
  29. package/src/coroutines/builder.tsx +66 -0
  30. package/src/coroutines/state.ts +574 -0
  31. package/src/coroutines/template.tsx +119 -0
  32. package/src/debounced/coroutines/debounce.ts +118 -0
  33. package/src/debounced/state.ts +61 -0
  34. package/src/diagnostics/domains/message-box/state.ts +4 -0
  35. package/src/foreignMutations/state.ts +4 -0
  36. package/src/forms/domains/attachments/views/attachments-view.tsx +22 -0
  37. package/src/forms/domains/collection/domains/reference/state.ts +18 -0
  38. package/src/forms/domains/collection/domains/selection/state.ts +5 -0
  39. package/src/forms/domains/launcher/domains/create/coroutines/runner.ts +60 -0
  40. package/src/forms/domains/launcher/domains/create/state.ts +71 -0
  41. package/src/forms/domains/launcher/domains/create/template.tsx +66 -0
  42. package/src/forms/domains/launcher/domains/edit/coroutines/runner.ts +47 -0
  43. package/src/forms/domains/launcher/domains/edit/state.ts +55 -0
  44. package/src/forms/domains/launcher/domains/edit/template.tsx +39 -0
  45. package/src/forms/domains/parser/domains/validator/state.ts +423 -0
  46. package/src/forms/domains/parser/state.tsx +311 -0
  47. package/src/forms/domains/primitives/domains/boolean/state.ts +13 -0
  48. package/src/forms/domains/primitives/domains/boolean/template.tsx +24 -0
  49. package/src/forms/domains/primitives/domains/date/state.ts +23 -0
  50. package/src/forms/domains/primitives/domains/date/template.tsx +31 -0
  51. package/src/forms/domains/primitives/domains/enum/state.ts +27 -0
  52. package/src/forms/domains/primitives/domains/enum/template.tsx +52 -0
  53. package/src/forms/domains/primitives/domains/enum-multiselect/state.ts +18 -0
  54. package/src/forms/domains/primitives/domains/enum-multiselect/template.tsx +56 -0
  55. package/src/forms/domains/primitives/domains/number/state.ts +8 -0
  56. package/src/forms/domains/primitives/domains/number/template.tsx +26 -0
  57. package/src/forms/domains/primitives/domains/searchable-infinite-stream/state.ts +55 -0
  58. package/src/forms/domains/primitives/domains/searchable-infinite-stream/template.tsx +114 -0
  59. package/src/forms/domains/primitives/domains/searchable-infinite-stream-multiselect/state.ts +27 -0
  60. package/src/forms/domains/primitives/domains/searchable-infinite-stream-multiselect/template.tsx +119 -0
  61. package/src/forms/domains/primitives/domains/string/state.ts +12 -0
  62. package/src/forms/domains/primitives/domains/string/template.tsx +24 -0
  63. package/src/forms/domains/singleton/domains/descriptors/entity/state.ts +9 -0
  64. package/src/forms/domains/singleton/domains/descriptors/field/domains/base/state.ts +5 -0
  65. package/src/forms/domains/singleton/domains/descriptors/field/domains/boolean/state.ts +6 -0
  66. package/src/forms/domains/singleton/domains/descriptors/field/domains/custom/state.ts +21 -0
  67. package/src/forms/domains/singleton/domains/descriptors/field/domains/date/state.ts +6 -0
  68. package/src/forms/domains/singleton/domains/descriptors/field/domains/enum/state.ts +7 -0
  69. package/src/forms/domains/singleton/domains/descriptors/field/domains/infinite-enum/state.ts +8 -0
  70. package/src/forms/domains/singleton/domains/descriptors/field/domains/number/state.ts +7 -0
  71. package/src/forms/domains/singleton/domains/descriptors/field/domains/string/state.ts +7 -0
  72. package/src/forms/domains/singleton/domains/descriptors/field/state.ts +16 -0
  73. package/src/forms/domains/singleton/domains/descriptors/form/state.ts +13 -0
  74. package/src/forms/domains/singleton/domains/form-label/state.ts +2 -0
  75. package/src/forms/domains/singleton/state.ts +87 -0
  76. package/src/forms/domains/singleton/template.tsx +92 -0
  77. package/src/forms/domains/singleton/views/field-views.ts +23 -0
  78. package/src/forms/domains/singleton/views/simple-inputs/base.ts +5 -0
  79. package/src/forms/domains/singleton/views/simple-inputs/boolean.tsx +4 -0
  80. package/src/forms/domains/singleton/views/simple-inputs/date.tsx +4 -0
  81. package/src/forms/domains/singleton/views/simple-inputs/number.tsx +4 -0
  82. package/src/forms/domains/singleton/views/simple-inputs/string.tsx +4 -0
  83. package/src/fun/domains/curry/state.ts +6 -0
  84. package/src/fun/domains/id/state.ts +2 -0
  85. package/src/fun/domains/predicate/domains/bool-expr.ts +98 -0
  86. package/src/fun/domains/predicate/state.ts +29 -0
  87. package/src/fun/domains/simpleCallback/state.ts +3 -0
  88. package/src/fun/domains/uncurry/state.ts +5 -0
  89. package/src/fun/domains/unit/state.ts +3 -0
  90. package/src/fun/domains/updater/domains/caseUpdater/state.ts +44 -0
  91. package/src/fun/domains/updater/domains/mapUpdater/state.ts +36 -0
  92. package/src/fun/domains/updater/domains/maybeUpdater/state.ts +45 -0
  93. package/src/fun/domains/updater/domains/orderedMapUpdater/state.ts +26 -0
  94. package/src/fun/domains/updater/domains/orderedSetUpdater/state.ts +23 -0
  95. package/src/fun/domains/updater/domains/replaceWith/state.ts +3 -0
  96. package/src/fun/domains/updater/domains/simpleUpdater/domains/baseSimpleUpdater/state.ts +18 -0
  97. package/src/fun/domains/updater/domains/simpleUpdater/state.ts +72 -0
  98. package/src/fun/domains/updater/state.ts +86 -0
  99. package/src/fun/state.ts +33 -0
  100. package/src/infinite-data-stream/coroutines/builder.ts +8 -0
  101. package/src/infinite-data-stream/coroutines/infiniteLoader.ts +51 -0
  102. package/src/infinite-data-stream/coroutines/runner.ts +12 -0
  103. package/src/infinite-data-stream/state.ts +175 -0
  104. package/src/infinite-data-stream/template.tsx +16 -0
  105. package/src/math/domains/DOMRect/state.ts +12 -0
  106. package/src/math/domains/number/state.ts +9 -0
  107. package/src/math/domains/rect/state.ts +22 -0
  108. package/src/math/domains/rgba/state.ts +87 -0
  109. package/src/math/domains/size2/state.ts +14 -0
  110. package/src/math/domains/vector2/state.ts +16 -0
  111. package/src/queue/state.ts +42 -0
  112. package/src/state/domains/repository/state.ts +14 -0
  113. package/src/template/state.tsx +198 -0
  114. package/src/validation/state.ts +2 -0
  115. package/src/value/domains/mutable-value/state.ts +13 -0
  116. package/src/value/state.ts +12 -0
  117. package/src/visibility/state.ts +3 -0
  118. package/tsconfig.json +22 -0
@@ -0,0 +1,92 @@
1
+ import { List, OrderedMap, OrderedSet } from "immutable"
2
+ import { BasicUpdater, id, BasicPredicate, SimpleCallback, Unit, Debounced, Synchronized, unit, replaceWith, CoTypedFactory, Debounce, Synchronize, BasicFun, EntityFormState, EntityFormContext, EntityFormForeignMutationsExpected, EntityFormTemplate, EntityFormView, FieldTemplates, FieldValidationWithPath, FormValidatorSynchronized, OnChange, SharedFormState } from "../../../../main"
3
+ import { Template, View } from "../../../template/state"
4
+ import { Value } from "../../../value/state"
5
+
6
+ export const Form = <Entity, FieldStates, Context, ForeignMutationsExpected>() => ({
7
+ Default: <Fields extends (keyof Entity) & (keyof FieldStates)>() => {
8
+ type State = EntityFormState<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>
9
+ type FieldTemplate<f extends Fields> = Template<Context & State[f] & Value<Entity[f]>, State[f], ForeignMutationsExpected & { onChange: OnChange<Entity[f]> }>
10
+ type EntityFormConfig = { [f in Fields]: FieldTemplate<f> }
11
+
12
+ return {
13
+ config: id<EntityFormConfig>,
14
+ template: (config: EntityFormConfig, validation:BasicFun<Entity, Promise<FieldValidationWithPath>>): EntityFormTemplate<Entity, Fields, FieldStates, Context, ForeignMutationsExpected> => {
15
+ const fieldTemplates: FieldTemplates<Entity, Fields, FieldStates, Context, ForeignMutationsExpected> = {} as FieldTemplates<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>
16
+ const setFieldTemplate = <field extends Fields>(field: field) => {
17
+ fieldTemplates[field] =
18
+ config[field]
19
+ .mapContext<EntityFormContext<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>>(_ =>
20
+ ({ ..._, value: _.value[field], ...(_[field]) }) as any)
21
+ .mapState<State>(_ => current => ({ ...current, [field]: _(current[field]) }))
22
+ .mapForeignMutationsFromProps<EntityFormForeignMutationsExpected<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>>(props =>
23
+ ({
24
+ ...props.foreignMutations,
25
+ onChange: (_: BasicUpdater<Entity[field]>, path) => {
26
+ props.setState(_ => ({ ..._,
27
+ modifiedByUser: true,
28
+ validation:Debounced.Updaters.Template.value<FormValidatorSynchronized>(Synchronized.Updaters.value(replaceWith(unit)))(_.validation),
29
+ [field]:({
30
+ ..._[field],
31
+ modifiedByUser:true,
32
+ validation:Debounced.Updaters.Template.value<FormValidatorSynchronized>(Synchronized.Updaters.value(replaceWith(unit)))(_[field].validation),
33
+ }) }))
34
+ setTimeout(() =>
35
+ props.foreignMutations.onChange((current: Entity): Entity => ({
36
+ ...current,
37
+ [field]: _(current[field])
38
+ }), path.push(field as string)),
39
+ 0)
40
+ }
41
+ }))
42
+ }
43
+ Object.keys(config).forEach((_) => {
44
+ const field = _ as Fields
45
+ setFieldTemplate(field)
46
+ })
47
+ return Template.Default<EntityFormContext<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>, State,
48
+ EntityFormForeignMutationsExpected<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>,
49
+ EntityFormView<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>>(props => {
50
+ let visibleFieldKeys: OrderedSet<Fields> = OrderedSet()
51
+ props.context.visibleFields.forEach((showField, field) => {
52
+ if (!showField(props.context)) return
53
+ visibleFieldKeys = visibleFieldKeys.add(field)
54
+ })
55
+ return <>
56
+ <props.view {...props}
57
+ VisibleFieldKeys={visibleFieldKeys}
58
+ EmbeddedFields={fieldTemplates}
59
+ />
60
+ </>
61
+ })
62
+ .any([
63
+ ValidateRunner<
64
+ EntityFormContext<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>,
65
+ State,
66
+ EntityFormForeignMutationsExpected<Entity, Fields, FieldStates, Context, ForeignMutationsExpected>,
67
+ Entity>(validation),
68
+ ])
69
+ }
70
+ }
71
+ }
72
+ })
73
+
74
+ export const ValidateRunner = <Context, FormState extends SharedFormState, ForeignMutationsExpected, Entity,>(
75
+ validation:BasicFun<Entity, Promise<FieldValidationWithPath>>,
76
+ ) => {
77
+ const Co = CoTypedFactory<Context & Value<Entity> & FormState, FormState>()
78
+ return Co.Template<ForeignMutationsExpected & { onChange: OnChange<Entity>; }>(
79
+ Co.Repeat(
80
+ Debounce<FormValidatorSynchronized, Value<Entity>>(
81
+ Synchronize<Unit, FieldValidationWithPath, Value<Entity>>(
82
+ _ => validation(_.value),
83
+ () => "transient failure", 3, 50
84
+ ), 50
85
+ ).embed(_ => ({..._.validation, value:_.value}), (_) => curr => ({...curr, validation:_(curr.validation)}))
86
+ ),
87
+ {
88
+ interval:15,
89
+ runFilter:props => Debounced.Operations.shouldCoroutineRun(props.context.validation)
90
+ }
91
+ )
92
+ }
@@ -0,0 +1,23 @@
1
+ import { FormInput } from "./simple-inputs/base";
2
+ import { SimpleBooleanInput } from "./simple-inputs/boolean";
3
+ import { SimpleDateInput } from "./simple-inputs/date";
4
+ import { SimpleNumberInput } from "./simple-inputs/number";
5
+ import { SimpleStringInput } from "./simple-inputs/string";
6
+
7
+
8
+ export type FieldViews = {
9
+ string: FormInput<string>;
10
+ number: FormInput<number>;
11
+ boolean: FormInput<boolean>;
12
+ date: FormInput<Date>;
13
+ };
14
+ export const FieldViews = {
15
+ Default: {
16
+ simple: (): FieldViews => ({
17
+ string: SimpleStringInput,
18
+ number: SimpleNumberInput,
19
+ boolean: SimpleBooleanInput,
20
+ date: SimpleDateInput,
21
+ })
22
+ }
23
+ };
@@ -0,0 +1,5 @@
1
+ import { SimpleCallback } from "../../../../../../main";
2
+ import { BasicFun } from "../../../../../fun/state";
3
+
4
+
5
+ export type FormInput<T> = BasicFun<{ value: T; onChange: SimpleCallback<T>; }, JSX.Element>;
@@ -0,0 +1,4 @@
1
+ import { FormInput } from "./base";
2
+
3
+
4
+ export const SimpleBooleanInput: FormInput<boolean> = props => <input type="checkbox" checked = { props.value } onChange = { e => props.onChange(e.currentTarget.checked) } />;
@@ -0,0 +1,4 @@
1
+ import { FormInput } from "./base";
2
+
3
+
4
+ export const SimpleDateInput: FormInput<Date> = props => <input type="date" value = { props.value.toDateString() } onChange = { e => props.onChange(new Date(Date.parse(e.currentTarget.value))) } />;
@@ -0,0 +1,4 @@
1
+ import { FormInput } from "./base";
2
+
3
+
4
+ export const SimpleNumberInput: FormInput<number> = props => <input type="number" value = { props.value } onChange = { e => props.onChange(parseInt(e.currentTarget.value)) } />;
@@ -0,0 +1,4 @@
1
+ import { FormInput } from "./base";
2
+
3
+
4
+ export const SimpleStringInput: FormInput<string> = props => <input value={ props.value } onChange = { e => props.onChange(e.currentTarget.value)}/>;
@@ -0,0 +1,6 @@
1
+ export const curry =
2
+ <A, B, C>(f: (a: A, b: B) => C) =>
3
+ (a: A) =>
4
+ (b: B): C =>
5
+ f(a, b);
6
+
@@ -0,0 +1,2 @@
1
+
2
+ export const id = <a>(_: a) => _;
@@ -0,0 +1,98 @@
1
+ import { BasicFun } from "../../../state"
2
+ import { Predicate } from "../state"
3
+
4
+ export type BoolExprSerializable<Leaf> =
5
+ {
6
+ kind: "leaf",
7
+ operation: keyof Leaf,
8
+ arguments: Leaf[keyof Leaf]
9
+ } |
10
+ {
11
+ kind: "true"
12
+ } | {
13
+ kind: "false"
14
+ } | {
15
+ kind: "and" | "or",
16
+ operands: [BoolExprSerializable<Leaf>, BoolExprSerializable<Leaf>]
17
+ } | {
18
+ kind: "not",
19
+ operand: BoolExprSerializable<Leaf>
20
+ }
21
+
22
+ export type LeafPredicatesEvaluators<Leaf, Context> = { [leaf in keyof Leaf]: BasicFun<Leaf[leaf], Predicate<Context>> }
23
+ export type BoolExpr<Leaf> =
24
+ ({
25
+ kind: "leaf",
26
+ operation: keyof Leaf,
27
+ arguments: Leaf[keyof Leaf]
28
+ } |
29
+ {
30
+ kind: "true"
31
+ } | {
32
+ kind: "false"
33
+ } | {
34
+ kind: "and" | "or",
35
+ operands: [BoolExpr<Leaf>, BoolExpr<Leaf>]
36
+ } | {
37
+ kind: "not",
38
+ operand: BoolExpr<Leaf>
39
+ }) & ({
40
+ not: () => BoolExpr<Leaf>,
41
+ and: BasicFun<BoolExpr<Leaf>, BoolExpr<Leaf>>,
42
+ or: BasicFun<BoolExpr<Leaf>, BoolExpr<Leaf>>,
43
+ eval: <Context>(evalLeaf: LeafPredicatesEvaluators<Leaf, Context>) => Predicate<Context>
44
+ })
45
+
46
+ export const BoolExpr = {
47
+ Default: Object.assign(<Leaf>(_: BoolExprSerializable<Leaf>): BoolExpr<Leaf> => {
48
+ return Object.assign(
49
+ _.kind == "and" || _.kind == "or" ?
50
+ ({ kind: _.kind, operands: [BoolExpr.Default(_.operands[0]), BoolExpr.Default(_.operands[1])] as [BoolExpr<Leaf>, BoolExpr<Leaf>] })
51
+ : _.kind == "not" ?
52
+ ({ kind: _.kind, operand: BoolExpr.Default(_.operand) })
53
+ : _.kind == "leaf" ?
54
+ ({ kind: _.kind, operation: _.operation, arguments: _.arguments })
55
+ : _.kind == "true" ?
56
+ ({ kind: _.kind })
57
+ :
58
+ ({ kind: _.kind }),
59
+ {
60
+ not: function (this: BoolExpr<Leaf>): BoolExpr<Leaf> {
61
+ return BoolExpr.Default({
62
+ kind: "not", operand: this
63
+ })
64
+ },
65
+ and: function (this: BoolExpr<Leaf>, other: BoolExpr<Leaf>): BoolExpr<Leaf> {
66
+ return BoolExpr.Default({
67
+ kind: "and", operands: [this, other]
68
+ })
69
+ },
70
+ or: function (this: BoolExpr<Leaf>, other: BoolExpr<Leaf>): BoolExpr<Leaf> {
71
+ return BoolExpr.Default({
72
+ kind: "or", operands: [this, other]
73
+ })
74
+ },
75
+ eval: function <Context>(this: BoolExpr<Leaf>, evalLeaf: { [leaf in keyof Leaf]: BasicFun<Leaf[leaf], Predicate<Context>> }): Predicate<Context> {
76
+ return this.kind == "not" ? this.operand.eval(evalLeaf).not()
77
+ : this.kind == "and" ? this.operands[0].eval(evalLeaf).and(this.operands[1].eval(evalLeaf))
78
+ : this.kind == "or" ? this.operands[0].eval(evalLeaf).or(this.operands[1].eval(evalLeaf))
79
+ : this.kind == "leaf" ? evalLeaf[this.operation](this.arguments)
80
+ : this.kind == "true" ? Predicate.True()
81
+ : Predicate.False()
82
+ },
83
+ })
84
+ },
85
+ {
86
+ true: <Leaf>(): BoolExpr<Leaf> => BoolExpr.Default({
87
+ kind: "true"
88
+ }),
89
+ false: <Leaf>(): BoolExpr<Leaf> => BoolExpr.Default({
90
+ kind: "false"
91
+ }),
92
+ leaf: <Leaf>() => <operation extends keyof Leaf>(operation: operation, args: Leaf[operation]): BoolExpr<Leaf> => BoolExpr.Default({
93
+ kind: "leaf",
94
+ operation,
95
+ arguments: args
96
+ }),
97
+ })
98
+ }
@@ -0,0 +1,29 @@
1
+ import { BasicFun, Fun } from "../../state"
2
+
3
+ export type BasicPredicate<c> = BasicFun<c, boolean>
4
+ export type Predicate<c> = Fun<c, boolean> & {
5
+ not:() => Predicate<c>,
6
+ and:(other:Predicate<c>) => Predicate<c>,
7
+ or:(other:Predicate<c>) => Predicate<c>,
8
+ }
9
+
10
+ export const Predicate = Object.assign(<c>(actual:BasicPredicate<c>) : Predicate<c> =>
11
+ Object.assign(
12
+ Fun(actual),
13
+ {
14
+ not:function(this:Predicate<c>) : Predicate<c> {
15
+ return Predicate(_ => !this(_))
16
+ },
17
+ and:function(this:Predicate<c>, other:Predicate<c>) : Predicate<c> {
18
+ return Predicate(_ => this(_) && other(_))
19
+ },
20
+ or:function(this:Predicate<c>, other:Predicate<c>) : Predicate<c> {
21
+ return Predicate(_ => this(_) || other(_))
22
+ }
23
+ }
24
+ ),
25
+ {
26
+ True:<c>() => Predicate<c>(_ => true),
27
+ False:<c>() => Predicate<c>(_ => false),
28
+ }
29
+ )
@@ -0,0 +1,3 @@
1
+ import { BasicFun } from "../../state";
2
+
3
+ export type SimpleCallback<E = void> = BasicFun<E, void>
@@ -0,0 +1,5 @@
1
+ export const uncurry =
2
+ <A, B, C>(f: (a: A) => (b: B) => C) =>
3
+ (a: A, b: B): C =>
4
+ f(a)(b);
5
+
@@ -0,0 +1,3 @@
1
+
2
+ export type Unit = {} // { kind:"unit" };
3
+ export const unit: Unit = {} // { kind:"unit" };
@@ -0,0 +1,44 @@
1
+ import { BasicFun } from "../../../../state";
2
+ import { BasicUpdater, Updater } from "../../state";
3
+
4
+ export type Kind<T> = T extends { kind:infer k } ? k : never
5
+
6
+ export type CaseUpdater<Entity, Field extends keyof Entity, CaseName extends Kind<Entity[Field]> & string> = {
7
+ [f in CaseName]: BasicFun<BasicUpdater<Entity[Field] & { kind: CaseName; }>, Updater<Entity>>;
8
+ };
9
+
10
+ export const caseUpdater = <Entity>() => <Field extends keyof Entity>(field:Field) => <CaseName extends Kind<Entity[Field]> & string>(caseName: CaseName):
11
+ CaseUpdater<Entity, Field, CaseName> => ({
12
+ [caseName]: (caseUpdater: BasicUpdater<Entity[Field]>): Updater<Entity & { [_ in Field]:{ kind:CaseName } }> => {
13
+ return Updater<Entity & { [_ in Field]:{ kind:CaseName } }>(currentEntity => (currentEntity[field].kind == caseName) ?
14
+ ({...currentEntity, [field]:caseUpdater(currentEntity as Entity[Field] & { kind: CaseName; }) })
15
+ : currentEntity
16
+ );
17
+ },
18
+ }) as CaseUpdater<Entity, Field, CaseName>;
19
+
20
+
21
+
22
+ import { LeftValue, RightValue, Sum } from "../../../../../collections/domains/sum/state";
23
+ type Y = Sum<number,boolean>
24
+ const Y = Sum<number,boolean>()
25
+ type X = {
26
+ y:Y
27
+ }
28
+ const X = {
29
+ Default:() : X => ({ y:Y.Default.left(10) }),
30
+ Updaters:{
31
+ y:{
32
+ ...caseUpdater<X>()("y")("l"),
33
+ ...caseUpdater<X>()("y")("r"),
34
+ }
35
+ }
36
+ }
37
+
38
+ const visitor =
39
+ X.Updaters.y.l(LeftValue.Updaters.value(_ => _ + 1)).then(
40
+ X.Updaters.y.r(RightValue.Updaters.value(_ => !_))
41
+ )
42
+
43
+
44
+ console.log(visitor)
@@ -0,0 +1,36 @@
1
+ import { BasicFun, Fun } from "../../../../state";
2
+ import { unit, Unit } from "../../../unit/state";
3
+ import { BasicUpdater, Updater } from "../../state";
4
+ import { Map } from "immutable";
5
+
6
+ export type MapUpdater<Entity, Field extends keyof Entity, DisplayName extends string> = Entity extends {
7
+ [_ in Field]: Map<infer key, infer value>;
8
+ } ? {
9
+ [f in DisplayName]: {
10
+ add: Fun<[key, value], Updater<Entity>>;
11
+ remove: Fun<key, Updater<Entity>>;
12
+ set: Fun<key, Fun<BasicUpdater<value>, Updater<Entity>>>;
13
+ upsert: Fun<[key, BasicFun<Unit, value>, BasicUpdater<value>], Updater<Entity>>;
14
+ };
15
+ } : "Error: mapUpdater has been invoked on a field which is not a map";
16
+
17
+
18
+ export const mapUpdater = <Entity>() => <Field extends keyof Entity, DisplayName extends string>(field: Field, displayName:DisplayName): MapUpdater<Entity, Field, DisplayName> => ({
19
+ [displayName]: {
20
+ add: Fun(([key, value]: [unknown, unknown]): Updater<Entity> => Updater(entity => ({ ...entity, [field]: (entity[field] as Map<unknown, unknown>).set(key, value) }) as Entity)),
21
+ remove: Fun((key: unknown): Updater<Entity> => Updater(entity => ({ ...entity, [field]: (entity[field] as Map<unknown, unknown>).remove(key) }) as Entity)),
22
+ set: Fun((key: unknown) => (Fun((fieldUpdater: BasicUpdater<unknown>): Updater<Entity> => Updater(entity => ({
23
+ ...entity, [field]: (entity[field] as Map<unknown, unknown>).has(key) == false ? entity[field] :
24
+ (entity[field] as Map<unknown, unknown>).set(key, fieldUpdater((entity[field] as Map<unknown, unknown>).get(key)!))
25
+ }) as Entity)
26
+ ))),
27
+ upsert: Fun(([key, fallback, fieldUpdater]: [unknown, BasicFun<Unit, unknown>, BasicUpdater<unknown>]) : Updater<Entity> => Updater(entity => ({
28
+ ...entity, [field]:
29
+ (entity[field] as Map<unknown, unknown>).set(key,
30
+ (entity[field] as Map<unknown, unknown>).has(key) ?
31
+ fieldUpdater((entity[field] as Map<unknown, unknown>).get(key)!)
32
+ : fieldUpdater(fallback(unit)))
33
+ }) as Entity)
34
+ ),
35
+ }
36
+ }) as MapUpdater<Entity, Field, DisplayName>;
@@ -0,0 +1,45 @@
1
+ import { Fun } from "../../../../state";
2
+ import { BasicUpdater, Updater } from "../../state";
3
+
4
+
5
+
6
+
7
+
8
+ export type MaybeUpdater<Entity, Field extends keyof Entity> = Entity extends {
9
+ [_ in Field]: infer value | undefined;
10
+ } ? Required<{
11
+ [f in Field]: Fun<BasicUpdater<value>, Updater<Entity>> & { both:Fun<BasicUpdater<value | undefined>, Updater<Entity>> };
12
+ }> : Entity extends {
13
+ [_ in Field]?: infer value;
14
+ } ? Required<{
15
+ [f in Field]: Fun<BasicUpdater<value>, Updater<Entity>> & { both:Fun<BasicUpdater<value | undefined>, Updater<Entity>> };
16
+ }> : "Error: maybeUpdater has been invoked on a field which cannot be undefined";
17
+
18
+ export const maybeUpdater = <Entity>() => <Field extends keyof Entity>(field: Field): MaybeUpdater<Entity, Field> => ({
19
+ [field]: Object.assign(Fun((fieldUpdater: BasicUpdater<Entity[Field]>): Updater<Entity> => {
20
+ return Updater(currentEntity => currentEntity[field] == undefined ? currentEntity :
21
+ ({ ...currentEntity, [field]: fieldUpdater(currentEntity[field]) }) as Entity
22
+ );
23
+ }), {
24
+ both:Fun((fieldUpdater: BasicUpdater<Entity[Field] | undefined>): Updater<Entity> => {
25
+ return Updater(currentEntity => ({ ...currentEntity, [field]: fieldUpdater(currentEntity[field]) }) as Entity
26
+ );
27
+ })
28
+ }),
29
+ }) as MaybeUpdater<Entity, Field>;
30
+
31
+
32
+ // // reference examples:
33
+ // type T = {
34
+ // x:number,
35
+ // y:string | undefined,
36
+ // z?:boolean
37
+ // }
38
+
39
+ // const T = {
40
+ // Updaters:{
41
+ // ...maybeUpdater<T>()("x"),
42
+ // ...maybeUpdater<T>()("y").y(...),
43
+ // ...maybeUpdater<T>()("z").z.both(...),
44
+ // }
45
+ // }
@@ -0,0 +1,26 @@
1
+ import { Fun } from "../../../../state";
2
+ import { BasicUpdater, Updater } from "../../state";
3
+ import { OrderedMap } from "immutable";
4
+
5
+ export type OrderedMapUpdater<Entity, Field extends keyof Entity, DisplayName extends string> = Entity extends {
6
+ [_ in Field]: OrderedMap<infer key, infer value>;
7
+ } ? {
8
+ [f in DisplayName]: {
9
+ add: Fun<[key, value], Updater<Entity>>;
10
+ remove: Fun<key, Updater<Entity>>;
11
+ set: Fun<key, Fun<BasicUpdater<value>, Updater<Entity>>>;
12
+ };
13
+ } : "Error: orderedMapUpdater has been invoked on a field which is not an OrderedMap";
14
+
15
+
16
+ export const orderedMapUpdater = <Entity>() => <Field extends keyof Entity, DisplayName extends string>(field: Field, displayName:DisplayName): OrderedMapUpdater<Entity, Field, DisplayName> => ({
17
+ [displayName]: {
18
+ add: Fun(([key, value]: [unknown, unknown]): Updater<Entity> => Updater(entity => ({ ...entity, [field]: (entity[field] as OrderedMap<unknown, unknown>).set(key, value) }) as Entity)),
19
+ remove: Fun((key: unknown): Updater<Entity> => Updater(entity => ({ ...entity, [field]: (entity[field] as OrderedMap<unknown, unknown>).remove(key) }) as Entity)),
20
+ set: Fun((key: unknown) => (Fun((fieldUpdater: BasicUpdater<unknown>): Updater<Entity> => Updater(entity => ({
21
+ ...entity, [field]: (entity[field] as OrderedMap<unknown, unknown>).has(key) == false ? entity[field] :
22
+ (entity[field] as OrderedMap<unknown, unknown>).set(key, fieldUpdater((entity[field] as OrderedMap<unknown, unknown>).get(key)!))
23
+ }) as Entity)
24
+ ))),
25
+ }
26
+ }) as OrderedMapUpdater<Entity, Field, DisplayName>;
@@ -0,0 +1,23 @@
1
+ import { Fun } from "../../../../state";
2
+ import { BasicUpdater, Updater } from "../../state";
3
+ import { OrderedSet } from "immutable";
4
+
5
+ export type OrderedSetUpdater<Entity, Field extends keyof Entity, DisplayName extends string> = Entity extends {
6
+ [_ in Field]: OrderedSet<infer value>;
7
+ } ? {
8
+ [f in DisplayName]: {
9
+ add: Fun<value, Updater<Entity>>;
10
+ remove: Fun<value, Updater<Entity>>;
11
+ };
12
+ } : "Error: orderedSetUpdater has been invoked on a filed which is not an OrderedSet";
13
+
14
+ export const orderedSetUpdater = <Entity>() => <Field extends keyof Entity, DisplayName extends string>(field: Field, displayName: DisplayName): OrderedSetUpdater<Entity, Field, DisplayName> => ({
15
+ [displayName]: {
16
+ add: Fun((value: unknown): Updater<Entity> =>
17
+ Updater(entity =>
18
+ ({ ...entity, [field]: (entity[field] as OrderedSet<unknown>).add(value) }) as Entity)),
19
+ remove: Fun((value: unknown): Updater<Entity> =>
20
+ Updater(entity =>
21
+ ({ ...entity, [field]: (entity[field] as OrderedSet<unknown>).remove(value) }) as Entity)),
22
+ }
23
+ }) as OrderedSetUpdater<Entity, Field, DisplayName>;
@@ -0,0 +1,3 @@
1
+ import { Updater } from "../../state";
2
+
3
+ export const replaceWith = <V>(v: V) => Updater((_: V) => v);
@@ -0,0 +1,18 @@
1
+ import { Fun } from "../../../../../../state";
2
+ import { BasicUpdater, Updater } from "../../../../state";
3
+
4
+
5
+
6
+ export type BaseWidening<c, p extends c> = Fun<BasicUpdater<c>, Updater<p>>;
7
+
8
+ export type BaseSimpleUpdater<BaseEntity, Entity extends BaseEntity, Name extends string> = Required<{
9
+ [_ in Name]: BaseWidening<BaseEntity, Entity>;
10
+ }>;
11
+ export const baseSimpleUpdater = <BaseEntity, Entity extends BaseEntity>() => <Name extends string>(name: Name): BaseSimpleUpdater<BaseEntity, Entity, Name> => ({
12
+ [name]: Fun((baseUpdater: BasicUpdater<BaseEntity>): Updater<Entity> => {
13
+ return Updater<Entity>(current => ({
14
+ ...current,
15
+ ...(baseUpdater(current)),
16
+ }));
17
+ }),
18
+ }) as BaseSimpleUpdater<BaseEntity, Entity, Name>;
@@ -0,0 +1,72 @@
1
+ import { Fun } from "../../../../state";
2
+ import { Unit } from "../../../unit/state";
3
+ import { BasicUpdater, Updater } from "../../state";
4
+
5
+ export type Widening<p, c extends keyof p> = Fun<BasicUpdater<p[c]>, Updater<p>>;
6
+
7
+ export type SimpleUpdater<Entity, Field extends keyof Entity> = Required<{
8
+ [f in Field]: Widening<Entity, Field>;
9
+ }>;
10
+ export const simpleUpdater = <Entity>() => <Field extends keyof Entity>(field: Field): SimpleUpdater<Entity, Field> => ({
11
+ [field]: Fun((fieldUpdater: BasicUpdater<Entity[Field]>): Updater<Entity> => {
12
+ return Updater<Entity>(currentEntity => ({ ...currentEntity, [field]: fieldUpdater(currentEntity[field]) }) as Entity
13
+ );
14
+ }),
15
+ }) as SimpleUpdater<Entity, Field>;
16
+
17
+
18
+ export type WidenedChildren<p, children> =
19
+ { [k in Exclude<keyof children, "Core" | "Template" | "Coroutine">]:
20
+ children[k] extends WideningWithChildren<infer child, infer nephew, infer nephews> ?
21
+ Fun<BasicUpdater<child[nephew]>, Updater<p>> & { children:WidenedChildren<p, nephews> }
22
+ : children[k] extends Widening<infer child, infer nephew> ? Fun<BasicUpdater<child[nephew]>, Updater<p>>
23
+ : "cannot invoke custom updaters through automated nesting"
24
+ } & (children extends { Core:Unit } ? {
25
+ Core:WidenedChildren<p, children["Core"]>
26
+ } : Unit) & (children extends { Template:Unit } ? {
27
+ Template:WidenedChildren<p, children["Template"]>
28
+ } : Unit) & (children extends { Coroutine:Unit } ? {
29
+ Coroutine:WidenedChildren<p, children["Coroutine"]>
30
+ } : Unit);
31
+
32
+ export type WideningWithChildren<p, c extends keyof p, children> =
33
+ Fun<BasicUpdater<p[c]>, Updater<p>> & { children:WidenedChildren<p, children> }
34
+
35
+ export type SimpleUpdaterWithChildren<Entity, Field extends keyof Entity, children> = {
36
+ [f in Field]: WideningWithChildren<Entity, Field, children>;
37
+ };
38
+ export const simpleUpdaterWithChildren = <Entity>() => <children>(children:children) => <Field extends keyof Entity>(field: Field): SimpleUpdaterWithChildren<Entity, Field, children> => ({
39
+ [field]: Object.assign(Fun((fieldUpdater: BasicUpdater<Entity[Field]>): Updater<Entity> => {
40
+ const basicUpdater:BasicUpdater<Entity> = currentEntity => ({ ...currentEntity, [field]: fieldUpdater(currentEntity[field]) })
41
+ return Updater<Entity>(basicUpdater);
42
+ }),
43
+ { children:widenChildren<Entity, Entity[Field], children>(simpleUpdater<Entity>()(field)[field], children, ) }
44
+ ),
45
+ }) as SimpleUpdaterWithChildren<Entity, Field, children>;
46
+
47
+
48
+ export const widenChildren = <p, child, children>(childToParent:Fun<BasicUpdater<child>, Updater<p>>, children:children) : WidenedChildren<p, children> => {
49
+ if (children == undefined) return {} as any
50
+ const result = {} as WidenedChildren<p, children>
51
+ Object.keys(children as any).forEach(key => {
52
+ if (key == "Core" || key == "Template" || key == "Coroutine") return
53
+ // Fun<BasicUpdater<child[key]>, Updater<child>>
54
+ const fieldOfChildUpdater = (children as any)[key] as any;
55
+ (result as any)[key] = Fun(_ => childToParent(fieldOfChildUpdater(_)))
56
+
57
+ if (Object.keys(fieldOfChildUpdater).includes("children")) {
58
+ (result as any)[key]["children"] = widenChildren<p, any, any>(childToParent, fieldOfChildUpdater["children"])
59
+ }
60
+ })
61
+
62
+ const updateBlock = (block:string) => {
63
+ if ((children as any)[block] != undefined) {
64
+ (result as any)[block] = widenChildren<p, any, any>(childToParent, (children as any)[block])
65
+ }
66
+ }
67
+ updateBlock("Core")
68
+ updateBlock("Template")
69
+ updateBlock("Coroutines")
70
+
71
+ return result
72
+ }