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.
- package/main.ts +149 -0
- package/package.json +20 -0
- package/src/apiResultStatus/state.ts +7 -0
- package/src/async/domains/mirroring/domains/collection/coroutines/synchronizers.ts +334 -0
- package/src/async/domains/mirroring/domains/collection/state.ts +137 -0
- package/src/async/domains/mirroring/domains/entity/domains/loaded-collection/state.ts +24 -0
- package/src/async/domains/mirroring/domains/entity/domains/loaded-collection-entity/state.ts +27 -0
- package/src/async/domains/mirroring/domains/entity/domains/loaded-entities/state.ts +12 -0
- package/src/async/domains/mirroring/domains/entity/domains/loaded-entity/state.ts +29 -0
- package/src/async/domains/mirroring/domains/entity/state.ts +22 -0
- package/src/async/domains/mirroring/domains/singleton/coroutines/synchronizers.ts +216 -0
- package/src/async/domains/mirroring/domains/singleton/state.ts +57 -0
- package/src/async/domains/mirroring/domains/synchronization-result/state.ts +2 -0
- package/src/async/domains/mirroring/domains/synchronized-entities/state.ts +23 -0
- package/src/async/domains/promise/state.ts +13 -0
- package/src/async/domains/synchronized/coroutines/synchronize.ts +62 -0
- package/src/async/domains/synchronized/state.ts +20 -0
- package/src/async/state.ts +144 -0
- package/src/baseEntity/domains/identifiable/state.ts +29 -0
- package/src/collections/domains/array/state.ts +16 -0
- package/src/collections/domains/immutable/domains/list/state.ts +20 -0
- package/src/collections/domains/immutable/domains/map/state.ts +33 -0
- package/src/collections/domains/immutable/domains/orderedMap/state.ts +117 -0
- package/src/collections/domains/immutable/domains/ordereredSet/state.ts +19 -0
- package/src/collections/domains/immutable/domains/set/state.ts +15 -0
- package/src/collections/domains/maybe/state.ts +20 -0
- package/src/collections/domains/product/state.ts +47 -0
- package/src/collections/domains/sum/state.ts +82 -0
- package/src/coroutines/builder.tsx +66 -0
- package/src/coroutines/state.ts +574 -0
- package/src/coroutines/template.tsx +119 -0
- package/src/debounced/coroutines/debounce.ts +118 -0
- package/src/debounced/state.ts +61 -0
- package/src/diagnostics/domains/message-box/state.ts +4 -0
- package/src/foreignMutations/state.ts +4 -0
- package/src/forms/domains/attachments/views/attachments-view.tsx +22 -0
- package/src/forms/domains/collection/domains/reference/state.ts +18 -0
- package/src/forms/domains/collection/domains/selection/state.ts +5 -0
- package/src/forms/domains/launcher/domains/create/coroutines/runner.ts +60 -0
- package/src/forms/domains/launcher/domains/create/state.ts +71 -0
- package/src/forms/domains/launcher/domains/create/template.tsx +66 -0
- package/src/forms/domains/launcher/domains/edit/coroutines/runner.ts +47 -0
- package/src/forms/domains/launcher/domains/edit/state.ts +55 -0
- package/src/forms/domains/launcher/domains/edit/template.tsx +39 -0
- package/src/forms/domains/parser/domains/validator/state.ts +423 -0
- package/src/forms/domains/parser/state.tsx +311 -0
- package/src/forms/domains/primitives/domains/boolean/state.ts +13 -0
- package/src/forms/domains/primitives/domains/boolean/template.tsx +24 -0
- package/src/forms/domains/primitives/domains/date/state.ts +23 -0
- package/src/forms/domains/primitives/domains/date/template.tsx +31 -0
- package/src/forms/domains/primitives/domains/enum/state.ts +27 -0
- package/src/forms/domains/primitives/domains/enum/template.tsx +52 -0
- package/src/forms/domains/primitives/domains/enum-multiselect/state.ts +18 -0
- package/src/forms/domains/primitives/domains/enum-multiselect/template.tsx +56 -0
- package/src/forms/domains/primitives/domains/number/state.ts +8 -0
- package/src/forms/domains/primitives/domains/number/template.tsx +26 -0
- package/src/forms/domains/primitives/domains/searchable-infinite-stream/state.ts +55 -0
- package/src/forms/domains/primitives/domains/searchable-infinite-stream/template.tsx +114 -0
- package/src/forms/domains/primitives/domains/searchable-infinite-stream-multiselect/state.ts +27 -0
- package/src/forms/domains/primitives/domains/searchable-infinite-stream-multiselect/template.tsx +119 -0
- package/src/forms/domains/primitives/domains/string/state.ts +12 -0
- package/src/forms/domains/primitives/domains/string/template.tsx +24 -0
- package/src/forms/domains/singleton/domains/descriptors/entity/state.ts +9 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/base/state.ts +5 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/boolean/state.ts +6 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/custom/state.ts +21 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/date/state.ts +6 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/enum/state.ts +7 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/infinite-enum/state.ts +8 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/number/state.ts +7 -0
- package/src/forms/domains/singleton/domains/descriptors/field/domains/string/state.ts +7 -0
- package/src/forms/domains/singleton/domains/descriptors/field/state.ts +16 -0
- package/src/forms/domains/singleton/domains/descriptors/form/state.ts +13 -0
- package/src/forms/domains/singleton/domains/form-label/state.ts +2 -0
- package/src/forms/domains/singleton/state.ts +87 -0
- package/src/forms/domains/singleton/template.tsx +92 -0
- package/src/forms/domains/singleton/views/field-views.ts +23 -0
- package/src/forms/domains/singleton/views/simple-inputs/base.ts +5 -0
- package/src/forms/domains/singleton/views/simple-inputs/boolean.tsx +4 -0
- package/src/forms/domains/singleton/views/simple-inputs/date.tsx +4 -0
- package/src/forms/domains/singleton/views/simple-inputs/number.tsx +4 -0
- package/src/forms/domains/singleton/views/simple-inputs/string.tsx +4 -0
- package/src/fun/domains/curry/state.ts +6 -0
- package/src/fun/domains/id/state.ts +2 -0
- package/src/fun/domains/predicate/domains/bool-expr.ts +98 -0
- package/src/fun/domains/predicate/state.ts +29 -0
- package/src/fun/domains/simpleCallback/state.ts +3 -0
- package/src/fun/domains/uncurry/state.ts +5 -0
- package/src/fun/domains/unit/state.ts +3 -0
- package/src/fun/domains/updater/domains/caseUpdater/state.ts +44 -0
- package/src/fun/domains/updater/domains/mapUpdater/state.ts +36 -0
- package/src/fun/domains/updater/domains/maybeUpdater/state.ts +45 -0
- package/src/fun/domains/updater/domains/orderedMapUpdater/state.ts +26 -0
- package/src/fun/domains/updater/domains/orderedSetUpdater/state.ts +23 -0
- package/src/fun/domains/updater/domains/replaceWith/state.ts +3 -0
- package/src/fun/domains/updater/domains/simpleUpdater/domains/baseSimpleUpdater/state.ts +18 -0
- package/src/fun/domains/updater/domains/simpleUpdater/state.ts +72 -0
- package/src/fun/domains/updater/state.ts +86 -0
- package/src/fun/state.ts +33 -0
- package/src/infinite-data-stream/coroutines/builder.ts +8 -0
- package/src/infinite-data-stream/coroutines/infiniteLoader.ts +51 -0
- package/src/infinite-data-stream/coroutines/runner.ts +12 -0
- package/src/infinite-data-stream/state.ts +175 -0
- package/src/infinite-data-stream/template.tsx +16 -0
- package/src/math/domains/DOMRect/state.ts +12 -0
- package/src/math/domains/number/state.ts +9 -0
- package/src/math/domains/rect/state.ts +22 -0
- package/src/math/domains/rgba/state.ts +87 -0
- package/src/math/domains/size2/state.ts +14 -0
- package/src/math/domains/vector2/state.ts +16 -0
- package/src/queue/state.ts +42 -0
- package/src/state/domains/repository/state.ts +14 -0
- package/src/template/state.tsx +198 -0
- package/src/validation/state.ts +2 -0
- package/src/value/domains/mutable-value/state.ts +13 -0
- package/src/value/state.ts +12 -0
- package/src/visibility/state.ts +3 -0
- 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,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,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,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
|
+
}
|