ballerina-core 1.0.28 → 1.0.31

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 (27) hide show
  1. package/main.ts +2 -0
  2. package/package.json +1 -1
  3. package/src/async/domains/mirroring/domains/entity/domains/loaded-collection-entity/state.ts +2 -1
  4. package/src/async/domains/mirroring/domains/entity/domains/loaded-entity/state.ts +2 -1
  5. package/src/debounced/coroutines/debounce.ts +72 -36
  6. package/src/debounced/state.ts +5 -4
  7. package/src/forms/domains/launcher/domains/edit/coroutines/runner.ts +2 -2
  8. package/src/forms/domains/launcher/domains/edit/state.ts +10 -11
  9. package/src/forms/domains/launcher/domains/edit/template.tsx +30 -6
  10. package/src/forms/domains/launcher/state.ts +1 -1
  11. package/src/forms/domains/launcher/template.tsx +1 -2
  12. package/src/forms/domains/parser/domains/built-ins/state.ts +111 -33
  13. package/src/forms/domains/parser/domains/types/state.ts +17 -5
  14. package/src/forms/domains/parser/domains/validator/state.ts +121 -70
  15. package/src/forms/domains/parser/state.tsx +101 -34
  16. package/src/forms/domains/primitives/domains/boolean/template.tsx +4 -4
  17. package/src/forms/domains/primitives/domains/date/template.tsx +2 -2
  18. package/src/forms/domains/primitives/domains/enum/template.tsx +2 -2
  19. package/src/forms/domains/primitives/domains/enum-multiselect/template.tsx +2 -2
  20. package/src/forms/domains/primitives/domains/list/template.tsx +3 -3
  21. package/src/forms/domains/primitives/domains/map/state.ts +55 -0
  22. package/src/forms/domains/primitives/domains/map/template.tsx +114 -0
  23. package/src/forms/domains/primitives/domains/number/template.tsx +2 -2
  24. package/src/forms/domains/primitives/domains/searchable-infinite-stream/template.tsx +2 -2
  25. package/src/forms/domains/primitives/domains/searchable-infinite-stream-multiselect/template.tsx +2 -2
  26. package/src/forms/domains/primitives/domains/string/template.tsx +2 -2
  27. package/src/forms/domains/singleton/template.tsx +6 -5
package/main.ts CHANGED
@@ -91,6 +91,8 @@ export * from "./src/forms/domains/primitives/domains/searchable-infinite-stream
91
91
  export * from "./src/forms/domains/primitives/domains/searchable-infinite-stream-multiselect/template"
92
92
  export * from "./src/forms/domains/primitives/domains/list/state"
93
93
  export * from "./src/forms/domains/primitives/domains/list/template"
94
+ export * from "./src/forms/domains/primitives/domains/map/state"
95
+ export * from "./src/forms/domains/primitives/domains/map/template"
94
96
  export * from "./src/forms/domains/singleton/domains/mapping/state"
95
97
  export * from "./src/forms/domains/singleton/domains/mapping/template"
96
98
  export * from "./src/forms/domains/parser/state"
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "ballerina-core",
3
3
  "author": "Dr. Giuseppe Maggiore",
4
4
  "private": false,
5
- "version": "1.0.28",
5
+ "version": "1.0.31",
6
6
  "main": "main.ts",
7
7
  "dependencies": {
8
8
  "immutable": "^5.0.0-beta.5",
@@ -1,3 +1,4 @@
1
+ import { Sum } from "../../../../../../../../main";
1
2
  import { DebouncedStatus, DirtyStatus } from "../../../../../../../debounced/state";
2
3
  import { AsyncState } from "../../../../../../state";
3
4
  import { CollectionEntity } from "../../../collection/state";
@@ -7,7 +8,7 @@ export type LoadedCollectionEntity<E> = LoadedEntity<E> & {
7
8
  isRemoved:boolean;
8
9
  lastUpdated: number;
9
10
  dirty: DirtyStatus;
10
- status: DebouncedStatus;
11
+ status: Sum<DebouncedStatus, "debug off">;
11
12
  };
12
13
  export const LoadedCollectionEntity = {
13
14
  Default:{
@@ -1,3 +1,4 @@
1
+ import { Sum } from "../../../../../../../../main";
1
2
  import { DebouncedStatus, DirtyStatus } from "../../../../../../../debounced/state";
2
3
  import { AsyncState } from "../../../../../../state";
3
4
  import { Entity } from "../../state";
@@ -10,7 +11,7 @@ export type LoadedEntity<E> = {
10
11
  synchronizationErrors:Array<any>;
11
12
  lastUpdated: number;
12
13
  dirty: DirtyStatus;
13
- status: DebouncedStatus;
14
+ status: Sum<DebouncedStatus, "debug off">;
14
15
  };
15
16
  export const LoadedEntity = {
16
17
  Default:{
@@ -26,11 +26,18 @@ export const Debounce = <value, context = Unit>(
26
26
  Co.SetState(
27
27
  updaters.Core.dirty(replaceWith<DirtyStatus>("dirty but being processed"))
28
28
  ),
29
- Co.SetState(
30
- updaters.Core.status(
31
- replaceWith<DebouncedStatus>("just detected dirty, starting processing")
32
- )
33
- ),
29
+ Co.GetState().then((current) => {
30
+ if (current.status.kind == "l") {
31
+ return Co.SetState(
32
+ updaters.Core.status(
33
+ replaceWith<DebouncedStatus>(
34
+ "just detected dirty, starting processing"
35
+ )
36
+ )
37
+ );
38
+ }
39
+ else return Co.Do(() => {});
40
+ }),
34
41
  Co.Any([
35
42
  // shortcircuit the validation if it takes longer than the whole cycle in the presence of an underwater update of the field
36
43
  Co.Seq([
@@ -40,22 +47,36 @@ export const Debounce = <value, context = Unit>(
40
47
  Date.now() - current.lastUpdated <= debounceDurationInMs,
41
48
  Co.Wait(debounceDurationInMs / 5)
42
49
  ),
43
- Co.SetState(
44
- updaters.Core.status(
45
- replaceWith<DebouncedStatus>("processing shortcircuited")
46
- )
47
- ),
50
+ Co.GetState().then((current) => {
51
+ if (current.status.kind == "l") {
52
+ return Co.SetState(
53
+ updaters.Core.status(
54
+ replaceWith<DebouncedStatus>(
55
+ "processing shortcircuited"
56
+ )
57
+ )
58
+ );
59
+ }
60
+ else return Co.Do(() => {});
61
+ }),
48
62
  Co.Wait(debounceDurationInMs / 2),
49
63
  ]),
50
64
  k
51
65
  .embed((_: Debounced<value & context>) => _, updaters.Core.value)
52
66
  .then((apiResult) => {
53
67
  return Co.Seq([
54
- Co.SetState(
55
- updaters.Core.status(
56
- replaceWith<DebouncedStatus>("processing finished")
57
- )
58
- ),
68
+ Co.GetState().then((current) => {
69
+ if (current.status.kind == "l") {
70
+ return Co.SetState(
71
+ updaters.Core.status(
72
+ replaceWith<DebouncedStatus>(
73
+ "processing finished"
74
+ )
75
+ )
76
+ );
77
+ }
78
+ else return Co.Do(() => {});
79
+ }),
59
80
  // Co.Wait(250)
60
81
  ]).then(() => {
61
82
  return Co.GetState().then((current) => {
@@ -64,13 +85,18 @@ export const Debounce = <value, context = Unit>(
64
85
  // maybe a new change has already reset dirty, in that case we need to start all over again
65
86
  if (current.dirty == "dirty but being processed") {
66
87
  return Co.Seq([
67
- Co.SetState(
68
- updaters.Core.status(
69
- replaceWith<DebouncedStatus>(
70
- "state was still dirty but being processed, resetting to not dirty"
71
- )
72
- )
73
- ),
88
+ Co.GetState().then((current) => {
89
+ if (current.status.kind == "l") {
90
+ return Co.SetState(
91
+ updaters.Core.status(
92
+ replaceWith<DebouncedStatus>(
93
+ "state was still dirty but being processed, resetting to not dirty"
94
+ )
95
+ )
96
+ );
97
+ }
98
+ else return Co.Do(() => {});
99
+ }),
74
100
  // use UpdateState to make sure that we look up the state at the last possible moment to account for delays
75
101
  Co.UpdateState((state) =>
76
102
  state.dirty == "dirty but being processed"
@@ -82,13 +108,18 @@ export const Debounce = <value, context = Unit>(
82
108
  ]);
83
109
  } else {
84
110
  return Co.Seq([
85
- Co.SetState(
86
- updaters.Core.status(
87
- replaceWith<DebouncedStatus>(
88
- "state was changed underwater back to dirty, leaving the dirty flag alone"
89
- )
90
- )
91
- ),
111
+ Co.GetState().then((current) => {
112
+ if (current.status.kind == "l") {
113
+ return Co.SetState(
114
+ updaters.Core.status(
115
+ replaceWith<DebouncedStatus>(
116
+ "state was changed underwater back to dirty, leaving the dirty flag alone"
117
+ )
118
+ )
119
+ );
120
+ }
121
+ else return Co.Do(() => {});
122
+ }),
92
123
  Co.SetState(
93
124
  updaters.Core.dirty(replaceWith<DirtyStatus>("dirty"))
94
125
  ),
@@ -97,13 +128,18 @@ export const Debounce = <value, context = Unit>(
97
128
  }
98
129
  } else {
99
130
  return Co.Seq([
100
- Co.SetState(
101
- updaters.Core.status(
102
- replaceWith<DebouncedStatus>(
103
- "inner call failed with transient failure"
104
- )
105
- )
106
- ),
131
+ Co.GetState().then((current) => {
132
+ if (current.status.kind == "l") {
133
+ return Co.SetState(
134
+ updaters.Core.status(
135
+ replaceWith<DebouncedStatus>(
136
+ "inner call failed with transient failure"
137
+ )
138
+ )
139
+ );
140
+ }
141
+ else return Co.Do(() => {});
142
+ }),
107
143
  Co.SetState(
108
144
  updaters.Core.dirty(replaceWith<DirtyStatus>("dirty"))
109
145
  ),
@@ -1,3 +1,4 @@
1
+ import { Sum } from "../../main";
1
2
  import { replaceWith } from "../fun/domains/updater/domains/replaceWith/state";
2
3
  import { BasicUpdater, Updater } from "../fun/domains/updater/state";
3
4
 
@@ -7,19 +8,19 @@ export type DebouncedStatus = "waiting for dirty" | "just detected dirty, starti
7
8
  | "processing shortcircuited"
8
9
  | "state was changed underwater back to dirty, leaving the dirty flag alone"
9
10
  | "inner call failed with transient failure"
10
- export type Debounced<Value> = Value & { lastUpdated: number; dirty: DirtyStatus; status:DebouncedStatus };
11
+ export type Debounced<Value> = Value & { lastUpdated: number; dirty: DirtyStatus; status: Sum<DebouncedStatus, "debug off"> };
11
12
  export const Debounced = {
12
- Default: <v>(initialValue: v): Debounced<v> => ({
13
+ Default: <v>(initialValue: v, debug?: boolean): Debounced<v> => ({
13
14
  ...initialValue,
14
15
  lastUpdated: 0,
15
16
  dirty: "not dirty",
16
- status: "waiting for dirty"
17
+ status: debug ? Sum.Default.left("waiting for dirty") : Sum.Default.right("debug off")
17
18
  }),
18
19
  Updaters: {
19
20
  Core:{
20
21
  status: <v>(_: BasicUpdater<DebouncedStatus>): Updater<Debounced<v>> => Updater<Debounced<v>>(current => ({
21
22
  ...current,
22
- status: _(current.status),
23
+ status: current.status.kind == "l" ? Sum.Default.left(_(current.status.value)) : Sum.Default.right("debug off"),
23
24
  })),
24
25
  dirty: <v>(_: BasicUpdater<DirtyStatus>): Updater<Debounced<v>> => Updater<Debounced<v>>(current => ({
25
26
  ...current,
@@ -23,7 +23,7 @@ export const editFormRunner = <E, FS>() => {
23
23
 
24
24
  const init = Co.GetState().then((current) =>
25
25
  Synchronize<Unit, E>(
26
- () => current.api.get(),
26
+ () => current.api.get(current.entityId),
27
27
  (_) => "transient failure",
28
28
  5,
29
29
  50
@@ -46,7 +46,7 @@ export const editFormRunner = <E, FS>() => {
46
46
  5,
47
47
  50
48
48
  ),
49
- current.debounceRateMs ?? 15
49
+ 15
50
50
  ).embed(
51
51
  (_) => ({ ..._, ..._.apiRunner }),
52
52
  EditFormState<E, FS>().Updaters.Core.apiRunner
@@ -1,4 +1,4 @@
1
- import { ApiResponseChecker, AsyncState, BasicUpdater, Debounced, ForeignMutationsInput, id, SimpleCallback, simpleUpdater, Synchronized, Template, unit, Unit, Updater, Value } from "../../../../../../main"
1
+ import { ApiResponseChecker, AsyncState, BasicUpdater, Debounced, ForeignMutationsInput, Guid, id, SimpleCallback, simpleUpdater, Synchronized, Template, unit, Unit, Updater, Value } from "../../../../../../main"
2
2
  import { BasicFun } from "../../../../../fun/state"
3
3
 
4
4
  export type ApiErrors = Array<string>
@@ -6,11 +6,10 @@ export type ApiErrors = Array<string>
6
6
  export type EditFormContext<E,FS> = {
7
7
  entityId:string,
8
8
  api:{
9
- get:() => Promise<E>,
9
+ get:(id: Guid) => Promise<E>,
10
10
  update:BasicFun<E, Promise<ApiErrors>>
11
11
  },
12
- actualForm:Template<Value<E> & FS, FS, { onChange:SimpleCallback<BasicUpdater<E>> }>
13
- debounceRateMs?: number
12
+ actualForm:Template<Value<E> & FS, FS, { onChange:SimpleCallback<BasicUpdater<E>>}>
14
13
  }
15
14
 
16
15
  export type EditFormState<E,FS> = {
@@ -39,19 +38,19 @@ export const EditFormState = <E,FS>() => ({
39
38
  toChecked: () => ApiResponseChecker.Updaters.toChecked<EditFormState<E, FS>>(),
40
39
  toUnchecked: () => ApiResponseChecker.Updaters.toUnchecked<EditFormState<E, FS>>(),
41
40
  entity:(_:BasicUpdater<E>) : Updater<EditFormState<E,FS>> =>
42
- EditFormState<E,FS>().Updaters.Core.apiRunner(
43
- Debounced.Updaters.Template.value(
41
+ EditFormState<E,FS>().Updaters.Core.entity(
44
42
  Synchronized.Updaters.sync(
45
43
  AsyncState.Operations.map(
46
- id
44
+ _
47
45
  )
48
46
  )
49
- )
50
- ).then(
51
- EditFormState<E,FS>().Updaters.Core.entity(
47
+ ),
48
+ submit: () : Updater<EditFormState<E,FS>> =>
49
+ EditFormState<E,FS>().Updaters.Core.apiRunner(
50
+ Debounced.Updaters.Template.value(
52
51
  Synchronized.Updaters.sync(
53
52
  AsyncState.Operations.map(
54
- _
53
+ id
55
54
  )
56
55
  )
57
56
  )
@@ -1,19 +1,41 @@
1
- import { AsyncState, editFormRunner, replaceWith, unit } from "../../../../../../main";
1
+ import { AsyncState, editFormRunner, replaceWith, SimpleCallback, unit } from "../../../../../../main";
2
2
  import { Template } from "../../../../../template/state";
3
3
  import { EditFormContext, EditFormForeignMutationsExpected, EditFormState, EditFormWritableState } from "./state";
4
4
 
5
+ export type EditFormView<E, FS> =
6
+ Template<
7
+ EditFormContext<E, FS> & EditFormWritableState<E, FS>,
8
+ EditFormWritableState<E, FS>,
9
+ EditFormForeignMutationsExpected<E, FS> & { onSubmit: SimpleCallback<void> },
10
+ {
11
+ actualForm: JSX.Element | undefined
12
+ }>
5
13
  export type EditFormTemplate<E, FS> =
6
14
  Template<
7
15
  EditFormContext<E, FS> & EditFormWritableState<E, FS>,
8
16
  EditFormWritableState<E, FS>,
9
- EditFormForeignMutationsExpected<E, FS>>
17
+ EditFormForeignMutationsExpected<E, FS>,
18
+ EditFormView<E, FS>>
10
19
  export const EditFormTemplate = <E, FS>() : EditFormTemplate<E,FS> =>
11
20
  Template.Default<
12
21
  EditFormContext<E, FS> & EditFormWritableState<E, FS>,
13
22
  EditFormWritableState<E, FS>,
14
- EditFormForeignMutationsExpected<E, FS>>(props =>
23
+ EditFormForeignMutationsExpected<E, FS>,
24
+ EditFormView<E, FS>
25
+ >(props =>
15
26
  <>
16
- {
27
+ {
28
+ props.view({
29
+ ...props,
30
+ foreignMutations: {
31
+ ...props.foreignMutations,
32
+ onSubmit: () => {
33
+ props.setState(EditFormState<E, FS>().Updaters.Template.submit())
34
+ }
35
+ },
36
+ view: {
37
+ ...props.view,
38
+ actualForm:
17
39
  !AsyncState.Operations.hasValue(props.context.entity.sync) ? undefined :
18
40
  props.context.actualForm({
19
41
  context: {
@@ -28,11 +50,13 @@ export const EditFormTemplate = <E, FS>() : EditFormTemplate<E,FS> =>
28
50
  foreignMutations: {
29
51
  onChange: (e) => {
30
52
  props.setState(EditFormState<E, FS>().Updaters.Template.entity(e))
31
- }
53
+ },
32
54
  },
33
55
  view: unit
34
56
  })
35
- }
57
+ }
58
+ })
59
+ }
36
60
  </>
37
61
  ).any([
38
62
  editFormRunner<E, FS>().mapContextFromProps(props => ({
@@ -6,8 +6,8 @@ export type FormRef = {
6
6
  formName:string
7
7
  } & ({
8
8
  kind:"edit",
9
+ submitButtonWrapper:any
9
10
  entityId:Guid,
10
- debounceRateMs?:number
11
11
  apiHandlers?: {
12
12
  success?: (_: any) => void,
13
13
  error?: (_: any) => void,
@@ -25,7 +25,6 @@ export const FormRunnerTemplate =
25
25
  <props.context.form.value.form
26
26
  context={{
27
27
  ...props.context.form.value.formState,
28
- debounceRateMs: props.context.formRef.kind == "edit" ? props.context.formRef.debounceRateMs : undefined,
29
28
  entityId: props.context.formRef.kind == "edit" ? props.context.formRef.entityId : undefined,
30
29
  value: props.context.formRef.kind == "map" ? props.context.formRef.value : undefined,
31
30
  formState: props.context.formRef.kind == "map" ? props.context.form.value.formState : props.context.form.value.formState.formState,
@@ -35,7 +34,7 @@ export const FormRunnerTemplate =
35
34
  props.context.formRef.kind == "map" ? props.context.form.value.mapping.from(props.context.formRef.value) :
36
35
  props.context.form.value.formState?.entity.sync?.value,
37
36
  },
38
- submitButtonWrapper: props.context.formRef.kind == "create" ? props.context.formRef.submitButtonWrapper : undefined
37
+ submitButtonWrapper: (props.context.formRef.kind == "create" || props.context.formRef.kind == "edit" ) ? props.context.formRef.submitButtonWrapper : undefined
39
38
  }}
40
39
  setState={(_: BasicUpdater<any>) => props.setState(
41
40
  FormRunnerState.Updaters.form(
@@ -16,7 +16,8 @@ export type PrimitiveType = (typeof PrimitiveTypes)[number]
16
16
  export const GenericTypes = [
17
17
  "SingleSelection",
18
18
  "MultiSelection",
19
- "List"] as const
19
+ "List",
20
+ "Map"] as const
20
21
  export type GenericType = (typeof GenericTypes)[number]
21
22
 
22
23
  export type ApiConverter<T> = { fromAPIRawValue: BasicFun<any, T>, toAPIRawValue: BasicFun<T, any> }
@@ -30,6 +31,7 @@ export type ApiConverters = {
30
31
  "SingleSelection": ApiConverter<CollectionSelection<any>>
31
32
  "MultiSelection": ApiConverter<OrderedMap<string, any>>
32
33
  "List": ApiConverter<List<any>>
34
+ "Map": ApiConverter<List<[any, any]>>
33
35
  }
34
36
 
35
37
  export type PrimitiveBuiltIn = { renderers: Set<keyof BuiltIns["renderers"]>, apiConverters: ApiConverter<any>, defaultValue: any }
@@ -48,6 +50,7 @@ export type BuiltIns = {
48
50
  streamSingleSelection: Set<string>;
49
51
  streamMultiSelection: Set<string>;
50
52
  list: Set<string>;
53
+ map: Set<string>;
51
54
  };
52
55
  };
53
56
 
@@ -65,7 +68,8 @@ export const builtInsFromFieldViews = (fieldViews: any, fieldTypeConverters: Api
65
68
  "generics": Map([
66
69
  ["SingleSelection", { apiConverters: fieldTypeConverters["SingleSelection"], defaultValue: CollectionSelection().Default.right("no selection") }] as [string, GenericBuiltIn],
67
70
  ["Multiselection", { apiConverters: fieldTypeConverters["SingleSelection"], defaultValue: Map() }] as [string, GenericBuiltIn],
68
- ["List", { apiConverters: fieldTypeConverters["SingleSelection"], defaultValue: List() }] as [string, GenericBuiltIn]
71
+ ["List", { apiConverters: fieldTypeConverters["SingleSelection"], defaultValue: List() }] as [string, GenericBuiltIn],
72
+ ["Map", { apiConverters: fieldTypeConverters["SingleSelection"], defaultValue: List() }] as [string, GenericBuiltIn]
69
73
  ]),
70
74
  "renderers": {
71
75
  "boolean": Set(),
@@ -78,6 +82,7 @@ export const builtInsFromFieldViews = (fieldViews: any, fieldTypeConverters: Api
78
82
  "number": Set(),
79
83
  "string": Set(),
80
84
  "list": Set(),
85
+ "map": Set(),
81
86
  }
82
87
  }
83
88
  Object.keys(builtins.renderers).forEach((_categoryName) => {
@@ -92,31 +97,53 @@ export const builtInsFromFieldViews = (fieldViews: any, fieldTypeConverters: Api
92
97
  }
93
98
 
94
99
 
95
- export const defaultValue = (types:Map<TypeName, TypeDefinition>, builtIns:BuiltIns) => (t: TypeName): any => {
96
- let primitive = builtIns.primitives.get(t)
97
- if (primitive != undefined) {
98
- return primitive.defaultValue
99
- } else {
100
- let generic = builtIns.generics.get(t)
101
- if (generic != undefined) {
102
- return generic.defaultValue
100
+ export const defaultValue = (types: Map<TypeName, TypeDefinition>, builtIns: BuiltIns) => (t: TypeName | Type): any => {
101
+ if (typeof t == "string") {
102
+ let primitive = builtIns.primitives.get(t)
103
+ if (primitive != undefined) {
104
+ return primitive.defaultValue
103
105
  } else {
104
- let custom = types.get(t)
105
- if (custom != undefined) {
106
- let res = {} as any
107
- custom.fields.forEach((field, fieldName) => {
108
- res[fieldName] = defaultValue(types, builtIns)(field.kind == "primitive" ? field.value : field.kind == "lookup" ? field.name : field.value)
106
+ let generic = builtIns.generics.get(t)
107
+ if (generic != undefined) {
108
+ return generic.defaultValue
109
+ } else {
110
+ let custom = types.get(t)
111
+ if (custom != undefined) {
112
+ let res = {} as any
113
+ custom.fields.forEach((field, fieldName) => {
114
+ res[fieldName] = defaultValue(types, builtIns)(field.kind == "primitive" ? field.value : field.kind == "lookup" ? field.name : field.value)
115
+ }
116
+ )
117
+ return res
118
+ } else {
119
+ debugger
120
+ throw `cannot find type ${t} when resolving defaultValue`
109
121
  }
110
- )
122
+ }
123
+ }
124
+ } else {
125
+ if (t.kind == "application") {
126
+ const generic = builtIns.generics.get(t.value)
127
+ if (generic) {
128
+ const res = generic.defaultValue
111
129
  return res
112
- } else {
113
- throw `cannot find type ${t} when resolving defaultValue`
114
130
  }
115
131
  }
132
+ debugger
133
+ throw `cannot find type ${t} when resolving defaultValue`
134
+ }
135
+ }
136
+
137
+
138
+ const parseTypeIShouldBePartOfFormValidation = (t:any) : TypeName | Type => {
139
+ if (typeof t == "string") return t
140
+ if ("fun" in t && "args" in t && Array.isArray(t.args)) {
141
+ return { kind:"application", value:t.fun, args:t.args }
116
142
  }
143
+ return null!
117
144
  }
118
145
 
119
- export const fromAPIRawValue = (t:Type, types:Map<TypeName, TypeDefinition>, builtIns:BuiltIns, converters:ApiConverters, isKeywordsReplaced: boolean = false) => (raw:any) : any => {
146
+ export const fromAPIRawValue = (t: Type, types: Map<TypeName, TypeDefinition>, builtIns: BuiltIns, converters: ApiConverters, isKeywordsReplaced: boolean = false) => (raw: any): any => {
120
147
  // alert(JSON.stringify(t))
121
148
  if (raw == undefined) {
122
149
  console.warn(`instantiating default value for type ${JSON.stringify(t)}: the value was undefined so something is missing from the API response`)
@@ -131,25 +158,49 @@ export const fromAPIRawValue = (t:Type, types:Map<TypeName, TypeDefinition>, bui
131
158
  if (t.value == "SingleSelection" && t.args.length == 1) {
132
159
  let result = converters[t.value].fromAPIRawValue(obj)
133
160
  result = CollectionSelection().Updaters.left(
134
- fromAPIRawValue({ kind:"lookup", name:t.args[0] }, types, builtIns, converters, true))(result)
161
+ fromAPIRawValue({ kind: "lookup", name: t.args[0] }, types, builtIns, converters, true))(result)
135
162
  return result
136
163
  }
137
164
  if ((t.value == "Multiselection" || t.value == "MultiSelection") && t.args.length == 1) {
138
165
  let result = converters["MultiSelection"].fromAPIRawValue(obj)
139
- result = result.map(fromAPIRawValue({ kind:"lookup", name:t.args[0] }, types, builtIns, converters, true))
166
+ result = result.map(fromAPIRawValue({ kind: "lookup", name: t.args[0] }, types, builtIns, converters, true))
140
167
  return result
141
168
  }
142
169
  if (t.value == "List" && t.args.length == 1) {
143
170
  let result = converters[t.value].fromAPIRawValue(obj)
144
171
  result = result.map(fromAPIRawValue(
145
172
  PrimitiveTypes.some(_ => _ == t.args[0]) ?
146
- { kind:"primitive", value:t.args[0] as PrimitiveType }
147
- : { kind:"lookup", name:t.args[0] }
173
+ { kind: "primitive", value: t.args[0] as PrimitiveType }
174
+ : { kind: "lookup", name: t.args[0] }
148
175
  , types, builtIns, converters, true))
149
176
  return result
150
177
  }
178
+ if (t.value == "Map" && t.args.length == 2) {
179
+ let result = converters[t.value].fromAPIRawValue(obj)
180
+ let t_args = t.args.map(parseTypeIShouldBePartOfFormValidation)
181
+ result = result.map(keyValue => ([
182
+ fromAPIRawValue(
183
+ typeof t_args[0] == "string" ?
184
+ PrimitiveTypes.some(_ => _ == t_args[0]) ?
185
+ { kind: "primitive", value: t_args[0] as PrimitiveType }
186
+ : { kind: "lookup", name: t_args[0] }
187
+ :
188
+ t_args[0],
189
+ types, builtIns, converters, true)(keyValue[0]),
190
+ fromAPIRawValue(
191
+ typeof t_args[1] == "string" ?
192
+ PrimitiveTypes.some(_ => _ == t_args[1]) ?
193
+ { kind: "primitive", value: t_args[1] as PrimitiveType }
194
+ : { kind: "lookup", name: t_args[1] }
195
+ :
196
+ t_args[1],
197
+ types, builtIns, converters, true)(keyValue[1]),
198
+ ])
199
+ )
200
+ return result
201
+ }
151
202
  } else { // t.kind == lookup: we are dealing with a record/object
152
- let result:any = {...obj}
203
+ let result: any = { ...obj }
153
204
  const tDef = types.get(t.name)!
154
205
  tDef.fields.forEach((fieldType, fieldName) => {
155
206
  const replacedFieldName = replaceKeyword(fieldName)
@@ -163,8 +214,8 @@ export const fromAPIRawValue = (t:Type, types:Map<TypeName, TypeDefinition>, bui
163
214
  }
164
215
 
165
216
 
166
- export const toAPIRawValue = (t:Type, types:Map<TypeName, TypeDefinition>, builtIns:BuiltIns, converters:ApiConverters, isKeywordsReverted: boolean = false) => (raw:any) : any => {
167
-
217
+ export const toAPIRawValue = (t: Type, types: Map<TypeName, TypeDefinition>, builtIns: BuiltIns, converters: ApiConverters, isKeywordsReverted: boolean = false) => (raw: any): any => {
218
+
168
219
  const obj = !isKeywordsReverted ? replaceKeywords(raw, "to api") : raw
169
220
 
170
221
  if (t.kind == "primitive") {
@@ -173,7 +224,7 @@ export const toAPIRawValue = (t:Type, types:Map<TypeName, TypeDefinition>, built
173
224
  if (t.value == "SingleSelection" && t.args.length == 1) {
174
225
  let result = converters[t.value].toAPIRawValue(obj)
175
226
  if (result != undefined && typeof result == "object")
176
- result = toAPIRawValue({ kind:"lookup", name:t.args[0] }, types, builtIns, converters, true)(result)
227
+ result = toAPIRawValue({ kind: "lookup", name: t.args[0] }, types, builtIns, converters, true)(result)
177
228
  return result
178
229
  }
179
230
  if ((t.value == "Multiselection" || t.value == "MultiSelection") && t.args.length == 1) {
@@ -181,8 +232,8 @@ export const toAPIRawValue = (t:Type, types:Map<TypeName, TypeDefinition>, built
181
232
  let result = converters["MultiSelection"].toAPIRawValue(obj)
182
233
  // alert(`MultiSelect result1 = ${JSON.stringify(result)}`)
183
234
  // alert(`${JSON.stringify(t.args[0])}`)
184
- result = result.map((_:any) =>
185
- typeof _ == "object" ? toAPIRawValue({ kind:"lookup", name:t.args[0] }, types, builtIns, converters, true)(_) : _)
235
+ result = result.map((_: any) =>
236
+ typeof _ == "object" ? toAPIRawValue({ kind: "lookup", name: t.args[0] }, types, builtIns, converters, true)(_) : _)
186
237
  // alert(`MultiSelect result2 = ${JSON.stringify(result)}`)
187
238
  return result
188
239
  }
@@ -190,14 +241,41 @@ export const toAPIRawValue = (t:Type, types:Map<TypeName, TypeDefinition>, built
190
241
  let result = converters[t.value].toAPIRawValue(obj)
191
242
  result = result.map(toAPIRawValue(
192
243
  PrimitiveTypes.some(_ => _ == t.args[0]) ?
193
- { kind:"primitive", value:t.args[0] as PrimitiveType }
194
- : { kind:"lookup", name:t.args[0] },
244
+ { kind: "primitive", value: t.args[0] as PrimitiveType }
245
+ : { kind: "lookup", name: t.args[0] },
195
246
  // { kind:"lookup", name:t.args[0] },
196
247
  types, builtIns, converters, true))
197
248
  return result
198
249
  }
250
+ if (t.value == "Map" && t.args.length == 2) {
251
+ let result = converters[t.value].toAPIRawValue(obj)
252
+
253
+ let t_args = t.args.map(parseTypeIShouldBePartOfFormValidation)
254
+ result = result.map((keyValue: any) => ([
255
+ toAPIRawValue(
256
+ typeof t_args[0] == "string" ?
257
+ PrimitiveTypes.some(_ => _ == t_args[0]) ?
258
+ { kind: "primitive", value: t_args[0] as PrimitiveType }
259
+ : { kind: "lookup", name: t_args[0] }
260
+ :
261
+ t_args[0],
262
+ types, builtIns, converters, true)(keyValue[0]),
263
+ toAPIRawValue(
264
+ typeof t_args[1] == "string" ?
265
+ PrimitiveTypes.some(_ => _ == t_args[1]) ?
266
+ { kind: "primitive", value: t_args[1] as PrimitiveType }
267
+ : { kind: "lookup", name: t_args[1] }
268
+ :
269
+ t_args[1],
270
+ types, builtIns, converters, true)(keyValue[1]),
271
+ ])
272
+ )
273
+
274
+ return result
275
+ }
276
+
199
277
  } else { // t.kind == lookup: we are dealing with a record/object
200
- let result:any = {...obj}
278
+ let result: any = { ...obj }
201
279
  const tDef = types.get(t.name)!
202
280
  tDef.fields.forEach((fieldType, fieldName) => {
203
281
  const revertedFieldName = revertKeyword(fieldName)
@@ -206,5 +284,5 @@ export const toAPIRawValue = (t:Type, types:Map<TypeName, TypeDefinition>, built
206
284
  })
207
285
  return result
208
286
  }
209
- return defaultValue(types, builtIns)(t.value)
287
+ return defaultValue(types, builtIns)(t.value)
210
288
  }