ballerina-core 1.0.48 → 1.0.49

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/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.48",
5
+ "version": "1.0.49",
6
6
  "main": "main.ts",
7
7
  "dependencies": {
8
8
  "immutable": "^5.0.0-beta.5",
@@ -0,0 +1,136 @@
1
+ import { List } from "immutable";
2
+ import { BasicFun, BasicFun2, Fun } from "../../../fun/state";
3
+ import { Value } from "../../../value/state";
4
+
5
+ export type ValueOrErrors<v, e> = (
6
+ | (Value<v> & { kind: "value" })
7
+ | { errors: List<e>; kind: "errors" }
8
+ ) & {
9
+ map: <a, b, e>(
10
+ this: ValueOrErrors<a, e>,
11
+ f: BasicFun<a, b>
12
+ ) => ValueOrErrors<b, e>;
13
+ mapErrors: <a, e, e2>(
14
+ this: ValueOrErrors<a, e>,
15
+ f: BasicFun<List<e>, List<e2>>
16
+ ) => ValueOrErrors<a, e2>;
17
+ flatten: <a, e>(
18
+ this: ValueOrErrors<ValueOrErrors<a, e>, e>
19
+ ) => ValueOrErrors<a, e>;
20
+ then: <a, b, e>(
21
+ this: ValueOrErrors<a, e>,
22
+ k: BasicFun<a, ValueOrErrors<b, e>>
23
+ ) => ValueOrErrors<b, e>;
24
+ };
25
+
26
+ const operations = {
27
+ map: function <a, b, e>(
28
+ this: ValueOrErrors<a, e>,
29
+ f: BasicFun<a, b>
30
+ ): ValueOrErrors<b, e> {
31
+ if (this.kind == "errors") {
32
+ return this;
33
+ }
34
+ return ValueOrErrors.Default.return(f(this.value));
35
+ },
36
+ mapErrors: function <a, e, e2>(
37
+ this: ValueOrErrors<a, e>,
38
+ f: BasicFun<List<e>, List<e2>>
39
+ ): ValueOrErrors<a, e2> {
40
+ if (this.kind == "errors") {
41
+ return ValueOrErrors.Default.throw(f(this.errors));
42
+ }
43
+ return this;
44
+ },
45
+ flatten: function <a, e>(
46
+ this: ValueOrErrors<ValueOrErrors<a, e>, e>
47
+ ): ValueOrErrors<a, e> {
48
+ if (this.kind == "errors") {
49
+ return this;
50
+ } else if (this.value.kind == "errors") {
51
+ return ValueOrErrors.Default.throw(this.value.errors);
52
+ } else {
53
+ return this.value;
54
+ }
55
+ },
56
+ then: function <a, b, e>(
57
+ this: ValueOrErrors<a, e>,
58
+ k: BasicFun<a, ValueOrErrors<b, e>>
59
+ ): ValueOrErrors<b, e> {
60
+ return this.map(k).flatten();
61
+ },
62
+ };
63
+
64
+ export const ValueOrErrors = {
65
+ Default: {
66
+ return: <v, e>(_: v): ValueOrErrors<v, e> => ({
67
+ ...Value.Default(_),
68
+ kind: "value",
69
+ ...operations,
70
+ }),
71
+ throw: <v, e>(_: List<e>): ValueOrErrors<v, e> => ({
72
+ errors: _,
73
+ kind: "errors",
74
+ ...operations,
75
+ }),
76
+ },
77
+ Operations: {
78
+ return: <v, e>(_: v): ValueOrErrors<v, e> =>
79
+ ValueOrErrors.Default.return(_),
80
+ throw: <v, e>(_: e): ValueOrErrors<v, e> =>
81
+ ValueOrErrors.Default.throw(List([_])),
82
+ map: <a, b, e>(
83
+ f: BasicFun<a, b>
84
+ ): Fun<ValueOrErrors<a, e>, ValueOrErrors<b, e>> =>
85
+ Fun((_) =>
86
+ _.kind == "errors" ? _ : ValueOrErrors.Default.return(f(_.value))
87
+ ),
88
+ mapErrors: <a, e, e2>(
89
+ f: BasicFun<List<e>, List<e2>>
90
+ ): BasicFun<ValueOrErrors<a, e>, ValueOrErrors<a, e2>> =>
91
+ Fun((_) =>
92
+ _.kind == "errors" ? ValueOrErrors.Default.throw(f(_.errors)) : _
93
+ ),
94
+ flatten: <a, e>(): Fun<
95
+ ValueOrErrors<ValueOrErrors<a, e>, e>,
96
+ ValueOrErrors<a, e>
97
+ > =>
98
+ Fun((_) => {
99
+ if (_.kind == "errors") {
100
+ return _;
101
+ } else if (_.value.kind == "errors") {
102
+ return ValueOrErrors.Default.throw(_.value.errors);
103
+ } else {
104
+ return _.value;
105
+ }
106
+ }),
107
+ then: <a, b, e>(
108
+ k: BasicFun<a, ValueOrErrors<b, e>>
109
+ ): Fun<ValueOrErrors<a, e>, ValueOrErrors<b, e>> =>
110
+ Fun((_: ValueOrErrors<a, e>) =>
111
+ ValueOrErrors.Operations.flatten<b, e>()(
112
+ ValueOrErrors.Operations.map<a, ValueOrErrors<b, e>, e>(k)(_)
113
+ )
114
+ ),
115
+ fold: <v, e, c>(
116
+ l: BasicFun<v, c>,
117
+ r: BasicFun<List<e>, c>
118
+ ): Fun<ValueOrErrors<v, e>, c> =>
119
+ Fun((_) => (_.kind == "value" ? l(_.value) : r(_.errors))),
120
+ all: <v, e>(_: List<ValueOrErrors<v, e>>): ValueOrErrors<List<v>, e> =>
121
+ _.reduce(
122
+ (reduction, value) =>
123
+ ValueOrErrors.Operations.fold<v, e, ValueOrErrors<List<v>, e>>(
124
+ (v: v) =>
125
+ reduction.kind == "errors"
126
+ ? reduction
127
+ : reduction.map((_) => _.concat(v)),
128
+ (es: List<e>) =>
129
+ reduction.kind == "errors"
130
+ ? reduction.mapErrors((_) => _.concat(es))
131
+ : ValueOrErrors.Default.throw(es)
132
+ )(value),
133
+ ValueOrErrors.Default.return(List<v>())
134
+ ),
135
+ },
136
+ };
@@ -2,7 +2,8 @@ import { Map, List, Set, OrderedMap } from "immutable"
2
2
  import { CollectionReference } from "../../../collection/domains/reference/state";
3
3
  import { CollectionSelection } from "../../../collection/domains/selection/state";
4
4
  import { BasicFun } from "../../../../../fun/state";
5
- import { InjectedPrimitives, Maybe, replaceKeyword, replaceKeywords, revertKeyword, Type, TypeDefinition, TypeName, Unit } from "../../../../../../main";
5
+ import { InjectedPrimitives, Maybe, replaceKeyword, replaceKeywords, revertKeyword, Type, TypeDefinition, TypeName, Unit, Value } from "../../../../../../main";
6
+ import { ValueOrErrors } from "../../../../../collections/domains/valueOrErrors/state";
6
7
 
7
8
  export const PrimitiveTypes =
8
9
  ["string",
@@ -233,74 +234,105 @@ export const fromAPIRawValue = <T>(t: Type, types: Map<TypeName, TypeDefinition>
233
234
  return obj
234
235
  }
235
236
 
236
- export const toAPIRawValue = <T>(t: Type, types: Map<TypeName, TypeDefinition>, builtIns: BuiltIns, converters: BuiltInApiConverters, isKeywordsReverted: boolean = false, injectedPrimitives?: InjectedPrimitives<T>) => (raw: any, formState: any) : any => {
237
+ export const toAPIRawValue = <T>(t: Type, types: Map<TypeName, TypeDefinition>, builtIns: BuiltIns, converters: BuiltInApiConverters, isKeywordsReverted: boolean = false, injectedPrimitives?: InjectedPrimitives<T>) => (raw: any, formState: any) : ValueOrErrors<any, string> => {
237
238
  const obj = !isKeywordsReverted ? replaceKeywords(raw, "to api") : raw
238
239
  if (t.kind == "primitive") {
239
- return converters[t.value].toAPIRawValue([obj, formState.modifiedByUser] as never)
240
+ return ValueOrErrors.Operations.return(converters[t.value].toAPIRawValue([obj, formState.modifiedByUser] as never))
240
241
  } else if (t.kind == "application") { // application here means "generic type application"
241
242
  if (t.value == "SingleSelection" && t.args.length == 1) {
242
- let result = converters[t.value].toAPIRawValue([obj, formState.modifiedByUser])
243
- if (result != undefined && typeof result == "object"){
244
- result = toAPIRawValue({ kind:"lookup", name:t.args[0] }, types, builtIns, converters, true, injectedPrimitives)(result, formState)
245
- }
246
- return result
243
+ const result = converters[t.value].toAPIRawValue([obj, formState.modifiedByUser])
244
+ if(typeof result != "object") return ValueOrErrors.Operations.return(result)
245
+
246
+ return toAPIRawValue({ kind:"lookup", name:t.args[0] }, types, builtIns, converters, true, injectedPrimitives)(result, formState)
247
247
  }
248
248
  if ((t.value == "Multiselection" || t.value == "MultiSelection") && t.args.length == 1) {
249
- // alert(`MultiSelect ${JSON.stringify(t)} ${JSON.stringify(obj)}`)
250
- let result = converters["MultiSelection"].toAPIRawValue([obj, formState.modifiedByUser])
251
- // alert(`MultiSelect result1 = ${JSON.stringify(result)}`)
252
- // alert(`${JSON.stringify(t.args[0])}`)
253
- result = result.map((_:any) =>
254
- typeof _ == "object" ? toAPIRawValue({ kind:"lookup", name: t.args[0] }, types, builtIns, converters, true, injectedPrimitives)(_, formState) : _)
255
- // alert(`MultiSelect result2 = ${JSON.stringify(result)}`)
256
- return result
249
+ const result = converters["MultiSelection"].toAPIRawValue([obj, formState.modifiedByUser])
250
+
251
+ return ValueOrErrors.Operations.all(List<ValueOrErrors<any, string>>(result.map((_:any) =>
252
+ typeof _ == "object" ? toAPIRawValue({ kind:"lookup", name: t.args[0] }, types, builtIns, converters, true, injectedPrimitives)(_, formState) : ValueOrErrors.Operations.return(_))))
257
253
  }
258
254
  if (t.value == "List" && t.args.length == 1) {
259
255
  const converterResult = converters[t.value].toAPIRawValue([obj, formState.modifiedByUser])
260
256
  const isPrimitive = PrimitiveTypes.some(_ => _ == t.args[0]) || injectedPrimitives?.injectedPrimitives.has(t.args[0] as keyof T)
261
- return converterResult.map((item: any, index: number) =>
257
+ return ValueOrErrors.Operations.all(List<ValueOrErrors<any, string>>(converterResult.map((item: any, index: number) =>
262
258
  toAPIRawValue(
263
259
  isPrimitive ?
264
260
  { kind:"primitive", value:t.args[0] as PrimitiveType }
265
261
  : { kind:"lookup", name:t.args[0] },
266
262
  types, builtIns, converters, true, injectedPrimitives)(item,
267
263
  formState.elementFormStates.get(index)
268
- ))
264
+ ))))
269
265
  }
270
266
  if (t.value == "Map" && t.args.length == 2) {
271
267
  const converterResult = converters[t.value].toAPIRawValue([obj, formState.modifiedByUser])
268
+ const isKeyPrimitive = PrimitiveTypes.some(_ => _ == t.args[0]) || injectedPrimitives?.injectedPrimitives.has(t.args[0] as keyof T)
272
269
  const isValuePrimitive = PrimitiveTypes.some(_ => _ == t.args[1]) || injectedPrimitives?.injectedPrimitives.has(t.args[1] as keyof T)
273
270
  let t_args = t.args.map(parseTypeIShouldBePartOfFormValidation)
274
- return (converterResult as List<[any, any]>).reduce((acc: Record<any, any>, [k, v]: [any, any], index: number) => {
275
- if(typeof k != "string" && typeof k != "number") {
276
- throw new Error(`key ${k} is not a valid javascript object key (string, number), it is ${typeof k} check field converters.`)
277
- }
278
- const value = toAPIRawValue(
279
- typeof t_args[1] == "string" ?
280
- isValuePrimitive ?
281
- { kind: "primitive", value: t_args[1] as PrimitiveType }
282
- : { kind: "lookup", name: t_args[1] }
271
+
272
+ const parsedMap: ValueOrErrors<{key: ValueOrErrors<any, any>, value: ValueOrErrors<any, any>}, any>[] = converterResult.map((keyValue: any, index: number) => {
273
+ const key = toAPIRawValue(
274
+ typeof t_args[0] == "string" ?
275
+ isKeyPrimitive ?
276
+ { kind: "primitive", value: t_args[0] as PrimitiveType }
277
+ : { kind: "lookup", name: t_args[0] }
283
278
  :
284
- t_args[1],
285
- types, builtIns, converters, true, injectedPrimitives)(v, formState.elementFormStates.get(index).ValueFormState);
286
- acc[k] = value;
287
- return acc;
288
- }, {} as Record<any, any>
279
+ t_args[0],
280
+ types, builtIns, converters, true, injectedPrimitives)(keyValue[0], formState.elementFormStates.get(index).KeyFormState
281
+ )
282
+
283
+ if(key.kind == "value" && (key.value == undefined || key.value == null)) {
284
+ return ValueOrErrors.Operations.throw([`A mapped key is undefined for type ${JSON.stringify(t.args[0])}`])
285
+ } else if ( key.kind == "errors"){
286
+ return key
287
+ }
288
+
289
+ const value = toAPIRawValue(
290
+ typeof t_args[1] == "string" ?
291
+ isValuePrimitive ?
292
+ { kind: "primitive", value: t_args[1] as PrimitiveType }
293
+ : { kind: "lookup", name: t_args[1] }
294
+ :
295
+ t_args[1],
296
+ types, builtIns, converters, true, injectedPrimitives)(keyValue[1], formState.elementFormStates.get(index).ValueFormState)
297
+
298
+ if(value.kind == "errors") return value
299
+
300
+ return ValueOrErrors.Operations.return({key, value})
301
+ }
289
302
  )
290
- }
291
303
 
304
+ if(parsedMap.length > 0 && parsedMap.some((_: ValueOrErrors<any, any>) => _.kind == "errors")) {
305
+ return ValueOrErrors.Operations.all(List(parsedMap))
306
+ }
307
+ // TODO this needs improvement
308
+ const allKeysStringified = parsedMap.map((_) => _.kind == "value" ? JSON.stringify((_.value.key as any).value) : "")
309
+ const allKeysUnique = Set(allKeysStringified).size == allKeysStringified.length
310
+
311
+ if(allKeysStringified.length > 0 && !allKeysUnique) {
312
+ return ValueOrErrors.Operations.throw(`Keys in the map are not unique: ${JSON.stringify(allKeysStringified)}`)
313
+ }
314
+
315
+ // return ValueOrErrors.Operations.return(parsedMap.map(_ => _.flatten()))
316
+ return ValueOrErrors.Operations.return(parsedMap.map(_ => (_ as any).map(({key, value}: {key: any, value: any}) => ({key: key.value, value: value.value}))).map((_: any) => _.value))
317
+
318
+ }
292
319
  } else { // t.kind == lookup: we are dealing with a record/object or extended type
293
- let result: any = { ...obj }
294
320
  const tDef = types.get(t.name)!
295
321
  if("extends" in tDef && tDef.extends.length == 1) {
296
- return converters[(tDef.extends[0] as keyof BuiltInApiConverters)].toAPIRawValue([obj, formState.modifiedByUser] as never)
297
- }
298
- tDef.fields.forEach((fieldType, fieldName) => {
322
+ return ValueOrErrors.Operations.return(converters[(tDef.extends[0] as keyof BuiltInApiConverters)].toAPIRawValue([obj, formState.modifiedByUser] as never))
323
+ }
324
+ const convertedMap = tDef.fields.mapEntries(([fieldName, fieldType] ) => {
299
325
  const revertedFieldName = revertKeyword(fieldName)
300
326
  const fieldValue = obj[revertedFieldName]
301
- result[revertedFieldName] = toAPIRawValue(fieldType, types, builtIns, converters, true, injectedPrimitives)(fieldValue, formState[fieldName])
327
+ const converted = toAPIRawValue(fieldType, types, builtIns, converters, true, injectedPrimitives)(fieldValue, formState[fieldName])
328
+ return [revertedFieldName, converted]
302
329
  })
303
- return result
330
+ if(convertedMap.some((valueOrError) => valueOrError.kind == "errors")) {
331
+ const propertiesWithErrors = convertedMap.filter((valueOrError) => valueOrError.kind == "errors")
332
+ const namedErrors = propertiesWithErrors.map((value, key) => value.mapErrors(_ => _.map((_: string) => `${key}: ${_}`)))
333
+ return ValueOrErrors.Operations.all(List<ValueOrErrors<any, string>>(namedErrors.valueSeq().toList()))
334
+ }
335
+ return ValueOrErrors.Operations.return(convertedMap.map(valueOrError => valueOrError.kind == "value" ? valueOrError.value : valueOrError.errors).toJS())
304
336
  }
305
- return defaultValue(types, builtIns, injectedPrimitives)(t.value)
337
+ return ValueOrErrors.Operations.return(defaultValue(types, builtIns, injectedPrimitives)(t.value))
306
338
  }
@@ -16,6 +16,7 @@ import { SearchableInfiniteStreamForm } from "../primitives/domains/searchable-i
16
16
  import { StringForm } from "../primitives/domains/string/template";
17
17
  import { FormLabel } from "../singleton/domains/form-label/state";
18
18
  import { Form } from "../singleton/template";
19
+ import { ValueOrErrors } from "../../../collections/domains/valueOrErrors/state";
19
20
 
20
21
  const parseOptions = (leafPredicates: any, options: any) => {
21
22
  const result = options.map((_: any) => ([_[0].id, [_[0], (_[1] as BoolExpr<any>).eval<any>(leafPredicates)]]));
@@ -483,13 +484,12 @@ export const parseForms =
483
484
  const initialState = parsedForm.initialFormState
484
485
  const api = {
485
486
  get: (id: string) => entityApis.get(launcher.api)(id).then((raw: any) => {
486
- // alert(JSON.stringify(raw))
487
- // alert(JSON.stringify(parsedForm.formDef.type))
488
- const parsed = fromAPIRawValue({ kind: "lookup", name: parsedForm.formDef.type }, formsConfig.types, builtIns, apiConverters, false, injectedPrimitives)(raw)
489
- return parsed
487
+ return fromAPIRawValue({ kind: "lookup", name: parsedForm.formDef.type }, formsConfig.types, builtIns, apiConverters, false, injectedPrimitives)(raw)
490
488
  }),
491
- update: (id: Guid, value: any, formState: any) =>
492
- entityApis.update(launcher.api)(id, toAPIRawValue({ kind: "lookup", name: parsedForm.formDef.type }, formsConfig.types, builtIns, apiConverters, false, injectedPrimitives)(value, formState))
489
+ update: (id: Guid, value: any, formState: any) => {
490
+ const raw = toAPIRawValue({ kind: "lookup", name: parsedForm.formDef.type }, formsConfig.types, builtIns, apiConverters, false, injectedPrimitives)(value, formState)
491
+ return raw.kind == "errors" ? Promise.reject(raw.errors) : entityApis.update(launcher.api)(id, raw.value)
492
+ }
493
493
  }
494
494
  parsedLaunchers.edit = parsedLaunchers.edit.set(
495
495
  launcherName,
@@ -513,12 +513,8 @@ export const parseForms =
513
513
  const initialState = parsedForm.initialFormState
514
514
  const api = {
515
515
  create: ([value, formState]: [any, any]) => {
516
- // alert(`type = ${JSON.stringify(parsedForm.formDef.type)}`)
517
- // alert(`value = ${JSON.stringify(value)}`)
518
- console.log("value", JSON.stringify(value))
519
516
  const raw = toAPIRawValue({ kind: "lookup", name: parsedForm.formDef.type }, formsConfig.types, builtIns, apiConverters, false, injectedPrimitives)(value, formState)
520
- // alert(`raw = ${JSON.stringify(raw.interests)}`)
521
- return entityApis.create(launcher.api)(raw)
517
+ return raw.kind == "errors" ? Promise.reject(raw.errors) : entityApis.create(launcher.api)(raw.value)
522
518
  },
523
519
  default: (_: Unit) => entityApis.default(launcher.api)(unit)
524
520
  .then((raw: any) => {