ballerina-core 1.0.11 → 1.0.14

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 CHANGED
@@ -95,6 +95,8 @@ export * from "./src/forms/domains/parser/state"
95
95
  export * from "./src/forms/domains/parser/template"
96
96
  export * from "./src/forms/domains/parser/coroutines/runner"
97
97
  export * from "./src/forms/domains/parser/domains/validator/state"
98
+ export * from "./src/forms/domains/parser/domains/built-ins/state"
99
+ export * from "./src/forms/domains/parser/domains/types/state"
98
100
  export * from "./src/forms/domains/launcher/domains/edit/state"
99
101
  export * from "./src/forms/domains/launcher/domains/edit/template"
100
102
  export * from "./src/forms/domains/launcher/domains/edit/coroutines/runner"
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.11",
5
+ "version": "1.0.14",
6
6
  "main": "main.ts",
7
7
  "dependencies": {
8
8
  "immutable": "^5.0.0-beta.5",
@@ -243,10 +243,10 @@ export const Coroutine = {
243
243
  return CoroutineStep.Result(nextState, step.result);
244
244
  else {
245
245
  if (step.excludeOthers) {
246
- console.log(
247
- `exclude others detected, killing ${ps.length - 1
248
- } other coroutines`
249
- );
246
+ // console.log(
247
+ // `exclude others detected, killing ${ps.length - 1
248
+ // } other coroutines`
249
+ // );
250
250
  return CoroutineStep.MapState(
251
251
  step.next([context, deltaT]),
252
252
  ((_) => thenMaybe(nextState, _) || id)
@@ -1,9 +1,37 @@
1
- import { FormValidationError } from "../../../parser/domains/validator/state"
1
+ import { merge } from 'immutable'
2
+
3
+ const INITIAL_CONFIG = {
4
+ types: {},
5
+ forms: {},
6
+ apis: {
7
+ enumOptions: {},
8
+ searchableStreams: {},
9
+ entities: {},
10
+ },
11
+ mappings: {},
12
+ launchers: {}
13
+ }
2
14
 
3
15
  export const FormsConfigMerger = {
4
16
  Default:{
5
- merge:(formsConfigs:any, errors:Array<FormValidationError>) : [any, Array<FormValidationError>] => {
6
- return null!
17
+ merge: (formsConfigs: any): any => {
18
+ if (!formsConfigs || formsConfigs.length === 0) {
19
+ return {...INITIAL_CONFIG};
20
+ }
21
+
22
+ return formsConfigs.reduce((acc: any, current: any) => {
23
+ return {
24
+ types: merge(acc.types, current.types),
25
+ forms: merge(acc.forms, current.forms),
26
+ apis: {
27
+ enumOptions: merge(acc.apis.enumOptions, current.apis.enumOptions),
28
+ searchableStreams: merge(acc.apis.searchableStreams, current.apis.searchableStreams),
29
+ entities: merge(acc.apis.entities, current.apis.entities),
30
+ },
31
+ mappings: merge(acc.mappings, current.mappings),
32
+ launchers: merge(acc.launchers, current.launchers),
33
+ }
34
+ }, {...INITIAL_CONFIG})
7
35
  }
8
36
  }
9
37
  }
@@ -1,6 +1,6 @@
1
- import { AsyncState, FormsConfig, Sum, Synchronize, Unit } from "../../../../../main"
1
+ import { AsyncState, builtInsFromFieldViews, FormsConfig, Sum, Synchronize, Unit } from "../../../../../main"
2
2
  import { CoTypedFactory } from "../../../../coroutines/builder"
3
- import { builtInsFromFieldViews, FormParsingResult, FormsParserContext, FormsParserState, parseForms } from "../state"
3
+ import { FormParsingResult, FormsParserContext, FormsParserState, parseForms } from "../state"
4
4
 
5
5
  export const LoadValidateAndParseFormsConfig = () => {
6
6
  const Co = CoTypedFactory<FormsParserContext, FormsParserState>()
@@ -9,12 +9,13 @@ export const LoadValidateAndParseFormsConfig = () => {
9
9
  Co.GetState().then(current =>
10
10
  Synchronize<Unit, FormParsingResult>(async() => {
11
11
  const formsConfig = await current.getFormsConfig()
12
- const builtIns = builtInsFromFieldViews(current.fieldViews)
12
+ const builtIns = builtInsFromFieldViews(current.fieldViews, current.fieldTypeConverters)
13
13
  const validationResult = FormsConfig.Default.validateAndParseAPIResponse(builtIns)(formsConfig)
14
14
  if (validationResult.kind == "r")
15
15
  return Sum.Default.right(validationResult.value)
16
16
  return parseForms(
17
17
  builtIns,
18
+ current.fieldTypeConverters,
18
19
  current.containerFormView,
19
20
  current.nestedContainerFormView,
20
21
  current.fieldViews,
@@ -0,0 +1,203 @@
1
+ import { Map, List, Set, OrderedMap } from "immutable"
2
+ import { CollectionReference } from "../../../collection/domains/reference/state";
3
+ import { CollectionSelection } from "../../../collection/domains/selection/state";
4
+ import { BasicFun } from "../../../../../fun/state";
5
+ import { Option, Sum } from "../../../../../collections/domains/sum/state"
6
+ import { Type, TypeDefinition, TypeName } from "../../../../../../main";
7
+
8
+ export const PrimitiveTypes =
9
+ ["string",
10
+ "number",
11
+ "boolean",
12
+ "maybeBoolean",
13
+ "Date",
14
+ "CollectionReference"] as const
15
+ export type PrimitiveType = (typeof PrimitiveTypes)[number]
16
+
17
+ export const GenericTypes = [
18
+ "SingleSelection",
19
+ "MultiSelection",
20
+ "List"] as const
21
+ export type GenericType = (typeof GenericTypes)[number]
22
+
23
+ export type ApiConverter<T> = { fromAPIRawValue: BasicFun<any, T>, toAPIRawValue: BasicFun<T, any> }
24
+ export type ApiConverters = {
25
+ "string": ApiConverter<string>
26
+ "number": ApiConverter<number>
27
+ "boolean": ApiConverter<boolean>
28
+ "maybeBoolean": ApiConverter<boolean | undefined>
29
+ "Date": ApiConverter<Date>
30
+ "CollectionReference": ApiConverter<CollectionReference>
31
+ "SingleSelection": ApiConverter<CollectionSelection<any>>
32
+ "MultiSelection": ApiConverter<OrderedMap<string, any>>
33
+ "List": ApiConverter<List<any>>
34
+ }
35
+
36
+ export type PrimitiveBuiltIn = { renderers: Set<keyof BuiltIns["renderers"]>, apiConverters: ApiConverter<any>, defaultValue: any }
37
+ export type GenericBuiltIn = { defaultValue: any, apiConverters: ApiConverter<any> }
38
+ export type BuiltIns = {
39
+ primitives: Map<string, PrimitiveBuiltIn>;
40
+ generics: Map<string, GenericBuiltIn>;
41
+ renderers: {
42
+ boolean: Set<string>;
43
+ maybeBoolean: Set<string>;
44
+ number: Set<string>;
45
+ string: Set<string>;
46
+ date: Set<string>;
47
+ enumSingleSelection: Set<string>;
48
+ enumMultiSelection: Set<string>;
49
+ streamSingleSelection: Set<string>;
50
+ streamMultiSelection: Set<string>;
51
+ list: Set<string>;
52
+ };
53
+ };
54
+
55
+ export const builtInsFromFieldViews = (fieldViews: any, fieldTypeConverters: ApiConverters): BuiltIns => {
56
+ let builtins: BuiltIns = {
57
+ "primitives": Map<string, PrimitiveBuiltIn>([
58
+ ["string", { renderers: Set(["string"]), apiConverters: fieldTypeConverters["string"], defaultValue: "" }] as [string, PrimitiveBuiltIn],
59
+ ["number", { renderers: Set(["number"]), apiConverters: fieldTypeConverters["number"], defaultValue: 0 }] as [string, PrimitiveBuiltIn],
60
+ ["boolean", { renderers: Set(["boolean"]), apiConverters: fieldTypeConverters["boolean"], defaultValue: false }],
61
+ ["maybeBoolean", { renderers: Set(["maybeBoolean"]), apiConverters: fieldTypeConverters["maybeBoolean"], defaultValue: undefined }] as [string, PrimitiveBuiltIn],
62
+ ["date", { renderers: Set(["date"]), apiConverters: fieldTypeConverters["Date"], defaultValue: new Date(Date.now()) }] as [string, PrimitiveBuiltIn],
63
+ ["Date", { renderers: Set(["date"]), apiConverters: fieldTypeConverters["Date"], defaultValue: new Date(Date.now()) }] as [string, PrimitiveBuiltIn],
64
+ ["CollectionReference", { renderers: Set(["enumSingleSelection", "enumMultiSelection", "streamSingleSelection", "streamMultiSelection"]), apiConverters: fieldTypeConverters["CollectionReference"], defaultValue: CollectionReference.Default("", "") }] as [string, PrimitiveBuiltIn]
65
+ ]),
66
+ "generics": Map([
67
+ ["SingleSelection", { apiConverters: fieldTypeConverters["SingleSelection"], defaultValue: CollectionSelection().Default.right("no selection") }] as [string, GenericBuiltIn],
68
+ ["Multiselection", { apiConverters: fieldTypeConverters["SingleSelection"], defaultValue: Map() }] as [string, GenericBuiltIn],
69
+ ["List", { apiConverters: fieldTypeConverters["SingleSelection"], defaultValue: [] }] as [string, GenericBuiltIn]
70
+ ]),
71
+ "renderers": {
72
+ "boolean": Set(),
73
+ "maybeBoolean": Set(),
74
+ "date": Set(),
75
+ "enumMultiSelection": Set(),
76
+ "enumSingleSelection": Set(),
77
+ "streamMultiSelection": Set(),
78
+ "streamSingleSelection": Set(),
79
+ "number": Set(),
80
+ "string": Set(),
81
+ "list": Set(),
82
+ }
83
+ }
84
+ Object.keys(builtins.renderers).forEach((_categoryName) => {
85
+ const categoryName = _categoryName as keyof BuiltIns["renderers"]
86
+ if (categoryName in fieldViews) {
87
+ Object.keys(fieldViews[categoryName]).forEach(viewName => {
88
+ builtins.renderers[categoryName] = builtins.renderers[categoryName].add(viewName)
89
+ })
90
+ }
91
+ })
92
+ return builtins
93
+ }
94
+
95
+
96
+ export const defaultValue = (types:Map<TypeName, TypeDefinition>, builtIns:BuiltIns) => (t: TypeName): any => {
97
+ let primitive = builtIns.primitives.get(t)
98
+ if (primitive != undefined) {
99
+ return primitive.defaultValue
100
+ } else {
101
+ let generic = builtIns.generics.get(t)
102
+ if (generic != undefined) {
103
+ return generic.defaultValue
104
+ } else {
105
+ let custom = types.get(t)
106
+ if (custom != undefined) {
107
+ let res = {} as any
108
+ custom.fields.forEach((field, fieldName) => {
109
+ res[fieldName] = defaultValue(types, builtIns)(field.kind == "primitive" ? field.value : field.kind == "lookup" ? field.name : field.value)
110
+ }
111
+ )
112
+ return res
113
+ } else {
114
+ throw `cannot find type ${t} when resolving defaultValue`
115
+ }
116
+ }
117
+ }
118
+ }
119
+
120
+ export const fromAPIRawValue = (t:Type, types:Map<TypeName, TypeDefinition>, builtIns:BuiltIns, converters:ApiConverters) => (raw:any) : any => {
121
+ // alert(JSON.stringify(t))
122
+ if (raw == undefined) {
123
+ console.warn(`instantiating default value for type ${JSON.stringify(t)}: the value was undefined so something is missing from the API response`)
124
+ return defaultValue(types, builtIns)(t.kind == "primitive" ? t.value : t.kind == "lookup" ? t.name : t.value)
125
+ }
126
+
127
+ if (t.kind == "primitive") {
128
+ return converters[t.value].fromAPIRawValue(raw)
129
+ } else if (t.kind == "application") { // application here means "generic type application"
130
+ if (t.value == "SingleSelection" && t.args.length == 1) {
131
+ let result = converters[t.value].fromAPIRawValue(raw)
132
+ result = CollectionSelection().Updaters.left(
133
+ fromAPIRawValue({ kind:"lookup", name:t.args[0] }, types, builtIns, converters))(result)
134
+ return result
135
+ }
136
+ if ((t.value == "Multiselection" || t.value == "MultiSelection") && t.args.length == 1) {
137
+ let result = converters["MultiSelection"].fromAPIRawValue(raw)
138
+ result = result.map(fromAPIRawValue({ kind:"lookup", name:t.args[0] }, types, builtIns, converters))
139
+ return result
140
+ }
141
+ if (t.value == "List" && t.args.length == 1) {
142
+ let result = converters[t.value].fromAPIRawValue(raw)
143
+ result = result.map(fromAPIRawValue(
144
+ PrimitiveTypes.some(_ => _ == t.args[0]) ?
145
+ { kind:"primitive", value:t.args[0] as PrimitiveType }
146
+ : { kind:"lookup", name:t.args[0] }
147
+ , types, builtIns, converters))
148
+ return result
149
+ }
150
+ } else { // t.kind == lookup: we are dealing with a record/object
151
+ let result:any = {...raw}
152
+ const tDef = types.get(t.name)!
153
+ tDef.fields.forEach((fieldType, fieldName) => {
154
+ const fieldValue = raw[fieldName]
155
+ result[fieldName] = fromAPIRawValue(fieldType, types, builtIns, converters)(fieldValue)
156
+ })
157
+ return result
158
+ }
159
+ console.error(`unsupported type ${JSON.stringify(t)}, returning the raw value right away`)
160
+ return raw
161
+ }
162
+
163
+
164
+ export const toAPIRawValue = (t:Type, types:Map<TypeName, TypeDefinition>, builtIns:BuiltIns, converters:ApiConverters) => (raw:any) : any => {
165
+ if (t.kind == "primitive") {
166
+ return converters[t.value].toAPIRawValue(raw as never)
167
+ } else if (t.kind == "application") { // application here means "generic type application"
168
+ if (t.value == "SingleSelection" && t.args.length == 1) {
169
+ let result = converters[t.value].toAPIRawValue(raw)
170
+ if (result != undefined)
171
+ result = toAPIRawValue({ kind:"lookup", name:t.args[0] }, types, builtIns, converters)(result)
172
+ return result
173
+ }
174
+ if ((t.value == "Multiselection" || t.value == "MultiSelection") && t.args.length == 1) {
175
+ // alert(`MultiSelect ${JSON.stringify(t)} ${JSON.stringify(raw)}`)
176
+ let result = converters["MultiSelection"].toAPIRawValue(raw)
177
+ // alert(`MultiSelect result1 = ${JSON.stringify(result)}`)
178
+ // alert(`${JSON.stringify(t.args[0])}`)
179
+ result = result.map(toAPIRawValue({ kind:"lookup", name:t.args[0] }, types, builtIns, converters))
180
+ // alert(`MultiSelect result2 = ${JSON.stringify(result)}`)
181
+ return result
182
+ }
183
+ if (t.value == "List" && t.args.length == 1) {
184
+ let result = converters[t.value].toAPIRawValue(raw)
185
+ result = result.map(toAPIRawValue(
186
+ PrimitiveTypes.some(_ => _ == t.args[0]) ?
187
+ { kind:"primitive", value:t.args[0] as PrimitiveType }
188
+ : { kind:"lookup", name:t.args[0] },
189
+ // { kind:"lookup", name:t.args[0] },
190
+ types, builtIns, converters))
191
+ return result
192
+ }
193
+ } else { // t.kind == lookup: we are dealing with a record/object
194
+ let result:any = {...raw}
195
+ const tDef = types.get(t.name)!
196
+ tDef.fields.forEach((fieldType, fieldName) => {
197
+ const fieldValue = raw[fieldName]
198
+ result[fieldName] = toAPIRawValue(fieldType, types, builtIns, converters)(fieldValue)
199
+ })
200
+ return result
201
+ }
202
+ return defaultValue(types, builtIns)(t.value)
203
+ }
@@ -0,0 +1,31 @@
1
+ import { OrderedMap } from "immutable";
2
+
3
+ export type FieldName = string;
4
+ export type TypeName = string;
5
+ export type TypeDefinition = {
6
+ extends: Array<TypeName>;
7
+ name: TypeName;
8
+ fields: OrderedMap<FieldName, Type>;
9
+ };
10
+ export type Type = {
11
+ kind: "lookup"; name: TypeName;
12
+ } | {
13
+ kind: "primitive"; value: "string" | "number" | "maybeBoolean" | "boolean" | "Date" | "CollectionReference";
14
+ } | {
15
+ kind: "application"; value: TypeName; args: Array<TypeName>;
16
+ };
17
+ export const Type = {
18
+ Default: {
19
+ lookup: (name: TypeName): Type => ({ kind: "lookup", name })
20
+ },
21
+ Operations: {
22
+ Equals: (fst: Type, snd: Type): boolean =>
23
+ fst.kind == "lookup" && snd.kind == "lookup" ? fst.name == snd.name :
24
+ fst.kind == "primitive" && snd.kind == "primitive" ? fst.value == snd.value :
25
+ fst.kind == "application" && snd.kind == "application" ?
26
+ fst.value == snd.value &&
27
+ fst.args.length == snd.args.length &&
28
+ fst.args.every((v, i) => v == snd.args[i]) :
29
+ false
30
+ }
31
+ }
@@ -1,35 +1,6 @@
1
1
  import { Set, Map, OrderedMap } from "immutable";
2
- import { BoolExpr, FormsConfigMerger, MappingPaths, Sum } from "../../../../../../main";
2
+ import { BoolExpr, BuiltIns, FieldName, FormsConfigMerger, MappingPaths, Sum, Type, TypeDefinition, TypeName } from "../../../../../../main";
3
3
 
4
- export type FieldName = string;
5
- export type TypeName = string;
6
- export type TypeDefinition = {
7
- extends: Array<TypeName>;
8
- name: TypeName;
9
- fields: OrderedMap<FieldName, Type>;
10
- };
11
- export type Type = {
12
- kind: "lookup"; name: TypeName;
13
- } | {
14
- kind: "primitive"; value: "string" | "number" | "maybeBoolean" | "boolean" | "Date" | "CollectionReference";
15
- } | {
16
- kind: "application"; value: TypeName; args: Array<TypeName>;
17
- };
18
- export const Type = {
19
- Default: {
20
- lookup: (name: TypeName): Type => ({ kind: "lookup", name })
21
- },
22
- Operations: {
23
- Equals: (fst: Type, snd: Type): boolean =>
24
- fst.kind == "lookup" && snd.kind == "lookup" ? fst.name == snd.name :
25
- fst.kind == "primitive" && snd.kind == "primitive" ? fst.value == snd.value :
26
- fst.kind == "application" && snd.kind == "application" ?
27
- fst.value == snd.value &&
28
- fst.args.length == snd.args.length &&
29
- fst.args.every((v, i) => v == snd.args[i]) :
30
- false
31
- }
32
- }
33
4
  export type FieldConfig = {
34
5
  renderer: string;
35
6
  label: string
@@ -91,37 +62,12 @@ export type FormsConfig = {
91
62
  };
92
63
  export type FormValidationError = string;
93
64
 
94
- export type PrimitiveBuiltIn = { renderers: Set<keyof BuiltIns["renderers"]>, defaultValue: any }
95
- export type GenericBuiltIn = { defaultValue: any }
96
- export type BuiltIns = {
97
- primitives: Map<string, PrimitiveBuiltIn>;
98
- generics: Map<string, GenericBuiltIn>;
99
- renderers: {
100
- BooleanViews: Set<string>;
101
- MaybeBooleanViews: Set<string>;
102
- NumberViews: Set<string>;
103
- StringViews: Set<string>;
104
- DateViews: Set<string>;
105
- EnumViews: Set<string>;
106
- EnumMultiselectViews: Set<string>;
107
- InfiniteStreamViews: Set<string>;
108
- InfiniteStreamMultiselectViews: Set<string>;
109
- ListViews: Set<string>;
110
- };
111
- };
112
-
113
65
  export type FormValidationResult = Sum<FormsConfig, Array<FormValidationError>>
114
66
  export const FormsConfig = {
115
67
  Default: {
116
- validateAndParseAPIResponse: (builtIns: BuiltIns) => (formsConfig: any): FormValidationResult => {
68
+ validateAndParseAPIResponse: (builtIns: BuiltIns) => (fc: any): FormValidationResult => {
117
69
  let errors: Array<FormValidationError> = [];
118
- if (Array.isArray(formsConfig)) {
119
- alert("formsConfig is an array!")
120
- const merged = FormsConfigMerger.Default.merge(formsConfig, errors)
121
- formsConfig = merged[0]
122
- errors = merged[0]
123
- }
124
-
70
+ const formsConfig = Array.isArray(fc) ? FormsConfigMerger.Default.merge(fc) : fc;
125
71
  let types: Map<TypeName, TypeDefinition> = Map();
126
72
  if ("types" in formsConfig == false) {
127
73
  errors.push("the formsConfig does not contain a 'types' field");
@@ -346,57 +292,59 @@ export const FormsConfig = {
346
292
  if (fieldTypeDef.value == "maybeBoolean") {
347
293
  // alert(JSON.stringify(fieldConfig["renderer"]))
348
294
  // alert(JSON.stringify(builtIns.renderers.MaybeBooleanViews))
349
- if (!builtIns.renderers.MaybeBooleanViews.has(fieldConfig["renderer"]))
295
+ if (!builtIns.renderers.maybeBoolean.has(fieldConfig["renderer"]))
350
296
  errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
351
297
  } else if (fieldTypeDef.value == "boolean") {
352
- if (!builtIns.renderers.BooleanViews.has(fieldConfig["renderer"]))
298
+ if (!builtIns.renderers.boolean.has(fieldConfig["renderer"]))
353
299
  errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
354
300
  } else if (fieldTypeDef.value == "number") {
355
- if (!builtIns.renderers.NumberViews.has(fieldConfig["renderer"]))
301
+ if (!builtIns.renderers.number.has(fieldConfig["renderer"]))
356
302
  errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
357
303
  } else if (fieldTypeDef.value == "string") {
358
- if (!builtIns.renderers.StringViews.has(fieldConfig["renderer"]))
304
+ if (!builtIns.renderers.string.has(fieldConfig["renderer"]))
359
305
  errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
360
306
  } else if (fieldTypeDef.value == "Date") {
361
- if (!builtIns.renderers.DateViews.has(fieldConfig["renderer"]))
307
+ if (!builtIns.renderers.date.has(fieldConfig["renderer"])) {
308
+ alert(JSON.stringify(builtIns.renderers))
362
309
  errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
363
- } else {
310
+ }
311
+ } else {
364
312
  errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
365
313
  }
366
314
  } else if (fieldTypeDef?.kind == "application") {
367
315
  if (fieldTypeDef?.value == "SingleSelection") {
368
- if (!builtIns.renderers.EnumViews.has(fieldConfig["renderer"]) &&
369
- !builtIns.renderers.InfiniteStreamViews.has(fieldConfig["renderer"]))
316
+ if (!builtIns.renderers.enumSingleSelection.has(fieldConfig["renderer"]) &&
317
+ !builtIns.renderers.streamSingleSelection.has(fieldConfig["renderer"]))
370
318
  errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
371
319
  } else if (fieldTypeDef?.value == "Multiselection") {
372
- if (!builtIns.renderers.EnumMultiselectViews.has(fieldConfig["renderer"]) &&
373
- !builtIns.renderers.InfiniteStreamMultiselectViews.has(fieldConfig["renderer"]))
320
+ if (!builtIns.renderers.enumMultiSelection.has(fieldConfig["renderer"]) &&
321
+ !builtIns.renderers.streamMultiSelection.has(fieldConfig["renderer"]))
374
322
  errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
375
323
  } else if (fieldTypeDef?.value == "List") {
376
- if (!builtIns.renderers.ListViews.has(fieldConfig["renderer"]))
324
+ if (!builtIns.renderers.list.has(fieldConfig["renderer"]))
377
325
  errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
378
326
  }
379
327
  if (fieldTypeDef.args.length < 1)
380
328
  errors.push(`field ${fieldName} of form ${formName} should have one type argument}`);
381
329
  else if (
382
- (builtIns.renderers.ListViews.has(fieldConfig["renderer"])) && "elementRenderer" in fieldConfig != true)
330
+ (builtIns.renderers.list.has(fieldConfig["renderer"])) && "elementRenderer" in fieldConfig != true)
383
331
  errors.push(`field ${fieldName} of form ${formName} is missing the 'elementRenderer' property`);
384
332
  else if (
385
- (builtIns.renderers.EnumMultiselectViews.has(fieldConfig["renderer"]) ||
386
- builtIns.renderers.EnumViews.has(fieldConfig["renderer"])) && "options" in fieldConfig != true)
333
+ (builtIns.renderers.enumMultiSelection.has(fieldConfig["renderer"]) ||
334
+ builtIns.renderers.enumSingleSelection.has(fieldConfig["renderer"])) && "options" in fieldConfig != true)
387
335
  errors.push(`field ${fieldName} of form ${formName} is missing the 'options' property`);
388
336
  else if (
389
- (builtIns.renderers.InfiniteStreamViews.has(fieldConfig["renderer"]) ||
390
- builtIns.renderers.InfiniteStreamMultiselectViews.has(fieldConfig["renderer"])) && "stream" in fieldConfig != true)
337
+ (builtIns.renderers.streamSingleSelection.has(fieldConfig["renderer"]) ||
338
+ builtIns.renderers.streamMultiSelection.has(fieldConfig["renderer"])) && "stream" in fieldConfig != true)
391
339
  errors.push(`field ${fieldName} of form ${formName} is missing the 'stream' property`);
392
- else if ((builtIns.renderers.EnumMultiselectViews.has(fieldConfig["renderer"]) ||
393
- builtIns.renderers.EnumViews.has(fieldConfig["renderer"])) && (enums.get(fieldConfig["options"])) != fieldTypeDef.args[0]) {
340
+ else if ((builtIns.renderers.enumMultiSelection.has(fieldConfig["renderer"]) ||
341
+ builtIns.renderers.enumSingleSelection.has(fieldConfig["renderer"])) && (enums.get(fieldConfig["options"])) != fieldTypeDef.args[0]) {
394
342
  if (enums.has(fieldConfig["options"]))
395
343
  errors.push(`field ${fieldName} of form ${formName} references an enum api with type ${enums.get(fieldConfig["options"])} when ${fieldTypeDef.args[0]} was expected`);
396
344
  else
397
345
  errors.push(`field ${fieldName} of form ${formName} references a non-existing enum api`);
398
- } else if ((builtIns.renderers.InfiniteStreamMultiselectViews.has(fieldConfig["renderer"]) ||
399
- builtIns.renderers.InfiniteStreamViews.has(fieldConfig["renderer"])) && (streams.get(fieldConfig["stream"])) != fieldTypeDef.args[0]) {
346
+ } else if ((builtIns.renderers.streamMultiSelection.has(fieldConfig["renderer"]) ||
347
+ builtIns.renderers.streamSingleSelection.has(fieldConfig["renderer"])) && (streams.get(fieldConfig["stream"])) != fieldTypeDef.args[0]) {
400
348
  if (streams.has(fieldConfig["stream"]))
401
349
  errors.push(`field ${fieldName} of form ${formName} references an api with type ${streams.get(fieldConfig["stream"])} when ${fieldTypeDef.args[0]} was expected`);
402
350
  else
@@ -415,7 +363,7 @@ export const FormsConfig = {
415
363
  Object.keys(configFormDef["fields"]).forEach(fieldName => {
416
364
  const fieldConfig = configFormDef["fields"][fieldName]
417
365
  const fieldTypeDef = formTypeDef?.fields.get(fieldName);
418
- if (fieldTypeDef && fieldTypeDef.kind == "application" && fieldTypeDef.value == "List" && (builtIns.renderers.ListViews.has(fieldConfig["renderer"]))) {
366
+ if (fieldTypeDef && fieldTypeDef.kind == "application" && fieldTypeDef.value == "List" && (builtIns.renderers.list.has(fieldConfig["renderer"]))) {
419
367
  let elementRenderer = fieldConfig["elementRenderer"]
420
368
  let elementType = fieldTypeDef.args[0]
421
369
  const rendererHasType = (elementRenderer: string, elementType: string): Array<string> => {
@@ -570,8 +518,8 @@ export const FormsConfig = {
570
518
  })
571
519
 
572
520
  if (errors.length > 0) {
573
- console.log("parsing errors")
574
- console.log(errors)
521
+ console.error("parsing errors")
522
+ console.error(errors)
575
523
  return Sum.Default.right(errors);
576
524
  }
577
525
 
@@ -1,5 +1,5 @@
1
1
  import { Collection, Map, OrderedMap, OrderedSet, Set } from "immutable";
2
- import { BoolExpr, Unit, PromiseRepo, Guid, LeafPredicatesEvaluators, Predicate, FormsConfig, BuiltIns, FormDef, Sum, BasicFun, Template, unit, EditFormState, EditFormTemplate, ApiErrors, CreateFormTemplate, EntityFormTemplate, SharedFormState, CreateFormState, Entity, EditFormContext, CreateFormContext, MappedEntityFormTemplate, Mapping, FormValidationResult, Synchronized, simpleUpdater, PrimitiveBuiltIn, GenericBuiltIn, TypeName, ListFieldState, ListForm, TypeDefinition } from "../../../../main";
2
+ import { BoolExpr, Unit, PromiseRepo, Guid, LeafPredicatesEvaluators, Predicate, FormsConfig, BuiltIns, FormDef, Sum, BasicFun, Template, unit, EditFormState, EditFormTemplate, ApiErrors, CreateFormTemplate, EntityFormTemplate, SharedFormState, CreateFormState, Entity, EditFormContext, CreateFormContext, MappedEntityFormTemplate, Mapping, FormValidationResult, Synchronized, simpleUpdater, PrimitiveType, GenericType, ApiConverter, TypeName, ListFieldState, ListForm, TypeDefinition, ApiConverters, defaultValue, fromAPIRawValue, toAPIRawValue } from "../../../../main";
3
3
  import { Value } from "../../../value/state";
4
4
  import { CollectionReference } from "../collection/domains/reference/state";
5
5
  import { CollectionSelection } from "../collection/domains/selection/state";
@@ -26,43 +26,43 @@ const parseOptions = (leafPredicates: any, options: any) => {
26
26
  export const FieldView = //<Context, FieldViews extends DefaultFieldViews, EnumFieldConfigs extends {}, EnumSources extends {}>() => <ViewType extends keyof FieldViews, ViewName extends keyof FieldViews[ViewType]>
27
27
  (fieldViews: any, viewType: any, viewName: any, fieldName: string, label: string, enumFieldConfigs: any, enumSources: any, leafPredicates: any): any => // FieldView<Context, FieldViews, ViewType, ViewName> =>
28
28
  {
29
- if (viewType == "MaybeBooleanViews")
29
+ if (viewType == "maybeBoolean")
30
30
  return MaybeBooleanForm<any & FormLabel, Unit>(_ => PromiseRepo.Default.mock(() => []))
31
31
  .withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
32
32
  .mapContext<any & SharedFormState & Value<boolean>>(_ => ({ ..._, label: label })) as any
33
- if (viewType == "BooleanViews")
33
+ if (viewType == "boolean")
34
34
  return BooleanForm<any & FormLabel, Unit>(_ => PromiseRepo.Default.mock(() => []))
35
35
  .withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
36
36
  .mapContext<any & SharedFormState & Value<boolean>>(_ => ({ ..._, label: label })) as any
37
- if (viewType == "DateViews")
37
+ if (viewType == "date")
38
38
  return DateForm<any & FormLabel, Unit>(_ => PromiseRepo.Default.mock(() => []))
39
39
  .withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
40
40
  .mapContext<any & DateFormState & Value<Date>>(_ => ({ ..._, label: label })) as any
41
- if (viewType == "NumberViews")
41
+ if (viewType == "number")
42
42
  return NumberForm<any & FormLabel, Unit>(_ => PromiseRepo.Default.mock(() => []))
43
43
  .withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
44
44
  .mapContext<any & SharedFormState & Value<number>>(_ => ({ ..._, label: label })) as any
45
- if (viewType == "StringViews")
45
+ if (viewType == "string")
46
46
  return StringForm<any & FormLabel, Unit>(_ => PromiseRepo.Default.mock(() => []))
47
47
  .withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
48
48
  .mapContext<any & SharedFormState & Value<string>>(_ => ({ ..._, label: label })) as any
49
- if (viewType == "EnumViews")
49
+ if (viewType == "enumSingleSelection")
50
50
  return EnumForm<any & FormLabel & BaseEnumContext<any, CollectionReference>, Unit, CollectionReference>(_ => PromiseRepo.Default.mock(() => []))
51
51
  .withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
52
52
  .mapContext<any & EnumFormState<any & BaseEnumContext<any, CollectionReference>, CollectionReference> & Value<CollectionSelection<CollectionReference>>>(_ => ({
53
53
  ..._, label: label, getOptions: () => ((enumFieldConfigs as any)((enumSources as any)[fieldName]) as Promise<any>).then(options => parseOptions(leafPredicates, options))
54
54
  })) as any
55
- if (viewType == "EnumMultiselectViews")
55
+ if (viewType == "enumMultiSelection")
56
56
  return EnumMultiselectForm<any & FormLabel & BaseEnumContext<any, CollectionReference>, Unit, CollectionReference>(_ => PromiseRepo.Default.mock(() => []))
57
57
  .withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
58
58
  .mapContext<any & EnumFormState<any & BaseEnumContext<any, CollectionReference>, CollectionReference> & Value<OrderedMap<Guid, CollectionReference>>>(_ => ({
59
59
  ..._, label: label, getOptions: () => ((enumFieldConfigs as any)((enumSources as any)[fieldName]) as Promise<any>).then(options => parseOptions(leafPredicates, options))
60
60
  })) as any
61
- if (viewType == "InfiniteStreamViews")
61
+ if (viewType == "streamSingleSelection")
62
62
  return SearchableInfiniteStreamForm<CollectionReference, any & FormLabel, Unit>(_ => PromiseRepo.Default.mock(() => []))
63
63
  .withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
64
64
  .mapContext<any & SearchableInfiniteStreamState<CollectionReference> & Value<CollectionSelection<CollectionReference>>>(_ => ({ ..._, label: label })) as any
65
- if (viewType == "InfiniteStreamMultiselectViews")
65
+ if (viewType == "streamMultiSelection")
66
66
  return InfiniteMultiselectDropdownForm<CollectionReference, any & FormLabel, Unit>(_ => PromiseRepo.Default.mock(() => []))
67
67
  .withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
68
68
  .mapContext<any & FormLabel & SharedFormState & SearchableInfiniteStreamState<CollectionReference> & Value<OrderedMap<Guid, CollectionReference>>>(_ => ({ ..._, label: label })) as any
@@ -71,19 +71,19 @@ export const FieldView = //<Context, FieldViews extends DefaultFieldViews, EnumF
71
71
 
72
72
  export const FieldFormState = //<Context, FieldViews extends DefaultFieldViews, InfiniteStreamSources extends {}, InfiniteStreamConfigs extends {}>() => <ViewType extends keyof FieldViews, ViewName extends keyof FieldViews[ViewType]>
73
73
  (fieldViews: any, viewType: any, viewName: any, fieldName: string, InfiniteStreamSources: any, infiniteStreamConfigs: any): any => {
74
- if (viewType == "MaybeBooleanViews" || viewType == "BooleanViews" || viewType == "NumberViews" || viewType == "StringViews")
74
+ if (viewType == "maybeBoolean" || viewType == "boolean" || viewType == "number" || viewType == "string")
75
75
  return SharedFormState.Default();
76
- if (viewType == "DateViews")
76
+ if (viewType == "date")
77
77
  return DateFormState.Default("");
78
- if (viewType == "EnumViews" || viewType == "EnumMultiselectViews")
78
+ if (viewType == "enumSingleSelection" || viewType == "enumMultiSelection")
79
79
  return ({ ...EnumFormState<any, any>().Default(), ...SharedFormState.Default() });
80
- if (viewType == "InfiniteStreamViews" || viewType == "InfiniteStreamMultiselectViews") {
80
+ if (viewType == "streamSingleSelection" || viewType == "streamMultiSelection") {
81
81
  return ({
82
82
  ...SearchableInfiniteStreamState<any>().Default("", (InfiniteStreamSources as any)((infiniteStreamConfigs as any)[fieldName])
83
83
  ), ...SharedFormState.Default()
84
84
  });
85
85
  }
86
- if (viewType == "ListViews")
86
+ if (viewType == "list")
87
87
  return ListFieldState<any, any>().Default(Map())
88
88
  return `error: the view for ${viewType as string}::${viewName as string} cannot be found when creating the corresponding field form state`;
89
89
  };
@@ -91,10 +91,13 @@ export const FieldFormState = //<Context, FieldViews extends DefaultFieldViews,
91
91
  export type ParsedForm = {
92
92
  initialFormState: any,
93
93
  formConfig: any,
94
+ formName: string,
95
+ formDef: FormDef,
94
96
  visibleFields: any,
95
97
  disabledFields: any,
96
98
  }
97
99
  export const ParseForm = (
100
+ formName: string,
98
101
  formDef: FormDef,
99
102
  containerFormView: any,
100
103
  nestedContainerFormView: any,
@@ -146,8 +149,6 @@ export const ParseForm = (
146
149
  }
147
150
  });
148
151
  const formConfig: any = {};
149
- console.log(fieldsViewsConfig)
150
- console.log(Object.keys(fieldsViewsConfig))
151
152
  Object.keys(fieldsViewsConfig).forEach(fieldName => {
152
153
  const label = formDef.fields.get(fieldName)!.label
153
154
  const viewName = (fieldsViewsConfig as any)[fieldName];
@@ -156,7 +157,7 @@ export const ParseForm = (
156
157
  formConfig[fieldName] = otherForm.form.withView(nestedContainerFormView).mapContext<any>(_ => ({ ..._, label: label }))
157
158
  } else {
158
159
  const viewType = fieldNameToViewCategory(fieldName) as any
159
- if (viewType == "ListViews") {
160
+ if (viewType == "list") {
160
161
  const elementRendererName = formFieldElementRenderers[fieldName]
161
162
  const field = type.fields.get(fieldName)!
162
163
  const initialElementValue = defaultValue(field.kind == "primitive" ? field.value : field.kind == "lookup" ? field.name : field.args[0])
@@ -188,7 +189,7 @@ export const ParseForm = (
188
189
  if (typeof formConfig[fieldName] == "string") {
189
190
  debugger
190
191
  const err = formConfig[fieldName]
191
- console.log(`error processing field ${fieldName}`, err)
192
+ console.error(`error processing field ${fieldName}`, err)
192
193
  formConfig[fieldName] = (props: any) => <>Error: field {fieldName} with {viewName} could not be instantiated</>
193
194
  throw err
194
195
  }
@@ -203,6 +204,8 @@ export const ParseForm = (
203
204
 
204
205
  return ({
205
206
  initialFormState,
207
+ formName,
208
+ formDef,
206
209
  formConfig,
207
210
  visibleFields,
208
211
  disabledFields,
@@ -215,44 +218,6 @@ export const parseVisibleFields = (
215
218
  visibleFields.map(([fieldName, boolExpr]) => ([fieldName, boolExpr.eval<any>(leafPredicates)]) as any)
216
219
  );
217
220
 
218
- export const builtInsFromFieldViews = (fieldViews: any): BuiltIns => {
219
- let builtins: BuiltIns = {
220
- "primitives": Map([
221
- ["string", { renderers: Set(["StringViews"]), defaultValue: "" }] as [string, PrimitiveBuiltIn],
222
- ["number", { renderers: Set(["NumberViews"]), defaultValue: 0 }],
223
- ["boolean", { renderers: Set(["BooleanViews"]), defaultValue: false }],
224
- ["maybeBoolean", { renderers: Set(["MaybeBooleanViews"]), defaultValue: undefined }],
225
- ["Date", { renderers: Set(["DateViews"]), defaultValue: new Date(Date.now()) }],
226
- ["CollectionReference", { renderers: Set(["EnumViews"]), defaultValue: CollectionReference.Default("", "") }]]),
227
- "generics": Map([
228
- ["SingleSelection", { defaultValue: CollectionSelection().Default.right("no selection") }] as [string, GenericBuiltIn],
229
- ["Multiselection", { defaultValue: Map() }],
230
- ["List", { defaultValue: [] }]
231
- ]),
232
- "renderers": {
233
- "BooleanViews": Set(),
234
- "MaybeBooleanViews": Set(),
235
- "DateViews": Set(),
236
- "EnumMultiselectViews": Set(),
237
- "EnumViews": Set(),
238
- "InfiniteStreamMultiselectViews": Set(),
239
- "InfiniteStreamViews": Set(),
240
- "NumberViews": Set(),
241
- "StringViews": Set(),
242
- "ListViews": Set(),
243
- }
244
- }
245
- Object.keys(builtins.renderers).forEach((_categoryName) => {
246
- const categoryName = _categoryName as keyof BuiltIns["renderers"]
247
- if (categoryName in fieldViews) {
248
- Object.keys(fieldViews[categoryName]).forEach(viewName => {
249
- builtins.renderers[categoryName] = builtins.renderers[categoryName].add(viewName)
250
- })
251
- }
252
- })
253
- return builtins
254
- }
255
-
256
221
  export type EditLauncherContext<Entity, FormState, ExtraContext> =
257
222
  Omit<
258
223
  EditFormContext<Entity, FormState> &
@@ -307,10 +272,13 @@ export type EntityApis = {
307
272
  get: BasicFun<EntityName, BasicFun<Guid, Promise<any>>>
308
273
  }
309
274
  export type EnumName = string
275
+
276
+
310
277
  export type EnumOptionsSources = BasicFun<EnumName, Promise<Array<[CollectionReference, BoolExpr<Unit>]>>>
311
278
  export const parseForms =
312
279
  <LeafPredicates,>(
313
280
  builtIns: BuiltIns,
281
+ apiConverters: ApiConverters,
314
282
  containerFormView: any,
315
283
  nestedContainerFormView: any,
316
284
  fieldViews: any,
@@ -324,31 +292,6 @@ export const parseForms =
324
292
  let seen = Set<string>()
325
293
  let formProcessingOrder = OrderedSet<string>()
326
294
 
327
- const defaultValue = (t: TypeName): any => {
328
- let primitive = builtIns.primitives.get(t)
329
- if (primitive != undefined) {
330
- return primitive.defaultValue
331
- } else {
332
- let generic = builtIns.generics.get(t)
333
- if (generic != undefined) {
334
- return generic.defaultValue
335
- } else {
336
- let custom = formsConfig.types.get(t)
337
- if (custom != undefined) {
338
- let res = {} as any
339
- custom.fields.forEach((field, fieldName) => {
340
- res[fieldName] = defaultValue(field.kind == "primitive" ? field.value : field.kind == "lookup" ? field.name : field.value)
341
- }
342
- )
343
- return res
344
- } else {
345
- errors.push(`cannot find type ${t} when resolving defaultValue`)
346
- return undefined
347
- }
348
- }
349
- }
350
- }
351
-
352
295
  let parsedLaunchers: ParsedLaunchers = {
353
296
  create: Map(),
354
297
  edit: Map(),
@@ -384,6 +327,7 @@ export const parseForms =
384
327
 
385
328
  try {
386
329
  const parsedForm = ParseForm(
330
+ formName,
387
331
  formConfig,
388
332
  containerFormView,
389
333
  nestedContainerFormView,
@@ -398,7 +342,7 @@ export const parseForms =
398
342
  leafPredicates,
399
343
  formFieldVisibilities,
400
344
  formFieldDisabled,
401
- defaultValue,
345
+ defaultValue(formsConfig.types, builtIns),
402
346
  formConfig.typeDef,
403
347
  )
404
348
  const formBuilder = Form<any, any, any, any>().Default<any>()
@@ -422,8 +366,13 @@ export const parseForms =
422
366
  const form = parsedForm.form
423
367
  const initialState = parsedForm.initialFormState
424
368
  const api = {
425
- get: entityApis.get(launcher.api),
426
- update: entityApis.update(launcher.api)
369
+ get: (id:string) => entityApis.get(launcher.api)(id).then((raw: any) => {
370
+ // alert(JSON.stringify(raw))
371
+ // alert(JSON.stringify(parsedForm.formDef.type))
372
+ const parsed = fromAPIRawValue({ kind: "lookup", name: parsedForm.formDef.type }, formsConfig.types, builtIns, apiConverters)(raw)
373
+ return parsed
374
+ }),
375
+ update: (value:any) => entityApis.update(launcher.api)(toAPIRawValue({ kind: "lookup", name: parsedForm.formDef.type }, formsConfig.types, builtIns, apiConverters)(value))
427
376
  }
428
377
  parsedLaunchers.edit = parsedLaunchers.edit.set(
429
378
  launcherName,
@@ -444,8 +393,18 @@ export const parseForms =
444
393
  const form = parsedForm.form
445
394
  const initialState = parsedForm.initialFormState
446
395
  const api = {
447
- create: entityApis.create(launcher.api),
448
- default: entityApis.default(launcher.api)
396
+ create: (value:any) => {
397
+ // alert(`type = ${JSON.stringify(parsedForm.formDef.type)}`)
398
+ // alert(`value = ${JSON.stringify(value)}`)
399
+ const raw = toAPIRawValue({ kind: "lookup", name: parsedForm.formDef.type }, formsConfig.types, builtIns, apiConverters)(value)
400
+ alert(`raw = ${JSON.stringify(raw.interests)}`)
401
+ return entityApis.create(launcher.api)(raw)
402
+ },
403
+ default: (_: Unit) => entityApis.default(launcher.api)(unit)
404
+ .then((raw: any) => {
405
+ const parsed = fromAPIRawValue({ kind: "lookup", name: parsedForm.formDef.type }, formsConfig.types, builtIns, apiConverters)(raw)
406
+ return parsed
407
+ })
449
408
  }
450
409
  parsedLaunchers.create = parsedLaunchers.create.set(
451
410
  launcherName,
@@ -502,6 +461,7 @@ export type FormsParserContext = {
502
461
  containerFormView: any,
503
462
  nestedContainerFormView: any,
504
463
  fieldViews: any,
464
+ fieldTypeConverters: ApiConverters,
505
465
  infiniteStreamSources: InfiniteStreamSources,
506
466
  enumOptionsSources: EnumOptionsSources,
507
467
  entityApis: EntityApis,
@@ -35,10 +35,10 @@ const X = {
35
35
  }
36
36
  }
37
37
 
38
- const visitor =
39
- X.Updaters.y.l(LeftValue.Updaters.value(_ => _ + 1)).then(
40
- X.Updaters.y.r(RightValue.Updaters.value(_ => !_))
41
- )
38
+ // const visitor =
39
+ // X.Updaters.y.l(LeftValue.Updaters.value(_ => _ + 1)).then(
40
+ // X.Updaters.y.r(RightValue.Updaters.value(_ => !_))
41
+ // )
42
42
 
43
43
 
44
- console.log(visitor)
44
+ // console.log(visitor)