Skip to content

Commit e77db07

Browse files
authored
Merge branch 'main' into treeview-build-fix
2 parents 7ab9364 + 0f7f862 commit e77db07

File tree

13 files changed

+1913
-350
lines changed

13 files changed

+1913
-350
lines changed

.github/workflows/nodejs.yml

+24-24
Original file line numberDiff line numberDiff line change
@@ -60,31 +60,31 @@ jobs:
6060
###########################
6161
## Sonatype SCA Scanning ##
6262
###########################
63-
- name: Sonatype Lifecycle SCA Scan
64-
if: github.repository_owner == 'finos'
65-
id: evaluate
66-
uses: sonatype/actions/evaluate@v1
67-
with:
68-
iq-server-url: ${{ env.SonatypeUrl }}
69-
username: ${{ secrets.SONATYPE_SCANNER_USERNAME }}
70-
password: ${{ secrets.SONATYPE_SCANNER_PASSWORD }}
71-
application-id: ${{ env.SonatypeAppId }}
72-
stage: "build"
73-
scan-targets: ${{ env.SonatypeScanTarget }}
74-
module-exclude: ${{ env.ExcludeDirectory }}
63+
# - name: Sonatype Lifecycle SCA Scan
64+
# if: github.repository_owner == 'finos'
65+
# id: evaluate
66+
# uses: sonatype/actions/evaluate@v1
67+
# with:
68+
# iq-server-url: ${{ env.SonatypeUrl }}
69+
# username: ${{ secrets.SONATYPE_SCANNER_USERNAME }}
70+
# password: ${{ secrets.SONATYPE_SCANNER_PASSWORD }}
71+
# application-id: ${{ env.SonatypeAppId }}
72+
# stage: "build"
73+
# scan-targets: ${{ env.SonatypeScanTarget }}
74+
# module-exclude: ${{ env.ExcludeDirectory }}
7575

76-
- name: Save Sonatype SBOM
77-
uses: sonatype/actions/fetch-sbom@v1
78-
if: always() && steps.evaluate.outputs.scan-id
79-
with:
80-
iq-server-url: ${{ env.SonatypeUrl }}
81-
username: ${{ secrets.SONATYPE_SCANNER_USERNAME }}
82-
password: ${{ secrets.SONATYPE_SCANNER_PASSWORD }}
83-
application-id: ${{ env.SonatypeAppId }}
84-
scan-id: ${{ steps.evaluate.outputs.scan-id }}
85-
sbom-standard: spdx
86-
sbom-version: 2.3
87-
artifact-name: ${{ env.SonatypeAppId }}-bom
76+
# - name: Save Sonatype SBOM
77+
# uses: sonatype/actions/fetch-sbom@v1
78+
# if: always() && steps.evaluate.outputs.scan-id
79+
# with:
80+
# iq-server-url: ${{ env.SonatypeUrl }}
81+
# username: ${{ secrets.SONATYPE_SCANNER_USERNAME }}
82+
# password: ${{ secrets.SONATYPE_SCANNER_PASSWORD }}
83+
# application-id: ${{ env.SonatypeAppId }}
84+
# scan-id: ${{ steps.evaluate.outputs.scan-id }}
85+
# sbom-standard: spdx
86+
# sbom-version: 2.3
87+
# artifact-name: ${{ env.SonatypeAppId }}-bom
8888

8989
# CVE scanning
9090
# cvescan:

morphir-ts/src/exports/sdk.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export { default as Dict } from "../sdk/dict";
22
export { default as Set } from "../sdk/set";
3-
export { default as List } from "../sdk/list";
3+
export { default as List } from "../sdk/list";
4+
export * as Maybe from "../sdk/maybe";

morphir-ts/src/sdk/maybe.ts

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
type Just<T> = {
2+
readonly kind: 'Just';
3+
readonly value: T;
4+
}
5+
6+
type Nothing = {
7+
readonly kind: 'Nothing';
8+
}
9+
10+
interface MaybeOps<T> {
11+
/**
12+
* Provide a default value, turning an optional value into a normal value.
13+
* @param defaultValue the default value to use if the Maybe is Nothing.
14+
* @return the value of the Maybe, or the default value if it is Nothing.
15+
* @example
16+
* ```ts
17+
* const maybeValue = Maybe.Just(42);
18+
* const result = maybeValue.withDefault(0); // result is 42
19+
* ...
20+
* const maybeValue = Maybe.Nothing<number>();
21+
* const result = maybeValue.withDefault(0); // result is 0
22+
* ```
23+
*/
24+
withDefault(defaultValue: T): T;
25+
/**
26+
* Transform a Maybe value with a given function
27+
* @param fn the function to apply to the value if it is Just.
28+
* @return a new Maybe value, which is Just if the original was Just, or Nothing if it was Nothing.
29+
* @example
30+
* ```ts
31+
* const maybeValue = Maybe.Just(42);
32+
* const result = maybeValue.map(x => x * 2); // result is Just(84)
33+
* ...
34+
* const maybeValue = Maybe.Nothing<number>();
35+
* const result = maybeValue.map(x => x * 2); // result is Nothing
36+
* ```
37+
*/
38+
map<U>(fn: (value: T) => U): Maybe<U>;
39+
/**
40+
* Chain together many computations that may fail.
41+
* @param fn the function to apply to the value if it is Just.
42+
* @return a new Maybe value, which is Just if the original was Just and the function returned Just, or Nothing if it was Nothing or the function returned Nothing.
43+
* @example
44+
* ```ts
45+
* const toInt = (x: string): Maybe<number> => {
46+
* const parsed = parseInt(x, 10);
47+
* return isNaN(parsed) ? Maybe.Nothing() : Maybe.Just(parsed);
48+
* };
49+
* const toValidMonth = (month: number): Maybe<number> => {
50+
* return month >= 1 && month <= 12 ? Maybe.Just(month) : Maybe.Nothing();
51+
* };
52+
* const parseMonth = (input: string): Maybe<number> => toInt(input).andThen(toValidMonth);
53+
*
54+
* const result1 = parseMonth("5"); // Just(5)
55+
* const result2 = parseMonth("13"); // Nothing
56+
* ```
57+
*/
58+
andThen<U>(fn: (value: T) => Maybe<U>): Maybe<U>;
59+
}
60+
61+
/**
62+
* Represent values that may or may not exist.
63+
* It can be useful if you have a record field that is only filled in sometimes.
64+
* Or if a function takes a value sometimes, but does not absolutely need it.
65+
*/
66+
export type Maybe<T> = (Just<T> | Nothing) & MaybeOps<T>;
67+
68+
function MaybeOps<T>(maybe: Just<T> | Nothing): MaybeOps<T> {
69+
return {
70+
withDefault(defaultValue: T): T {
71+
if (maybe.kind === 'Just') {
72+
return maybe.value;
73+
}
74+
return defaultValue;
75+
},
76+
77+
map<U>(fn: (value: T) => U): Maybe<U> {
78+
if (maybe.kind === 'Just') {
79+
return Just(fn(maybe.value));
80+
}
81+
return Nothing();
82+
},
83+
84+
andThen<U>(fn: (value: T) => Maybe<U>): Maybe<U> {
85+
if (maybe.kind === 'Just') {
86+
return fn(maybe.value);
87+
}
88+
return Nothing();
89+
}
90+
}
91+
}
92+
93+
/**
94+
* Create a Just value, which represents a value that exists.
95+
* @param value the value to wrap in a Just.
96+
* @return a new Just value.
97+
* @example
98+
* ```ts
99+
* const maybeValue = Maybe.Just(42); // maybeValue is Just(42)
100+
* ```
101+
*/
102+
export function Just<T>(value: T): Maybe<T> {
103+
const v: Just<T> = { kind: 'Just', value };
104+
return Object.assign(v, MaybeOps(v));
105+
}
106+
107+
/**
108+
* Create a Nothing value, which represents a value that does not exist.
109+
* @return a new Nothing value.
110+
* @example
111+
* ```ts
112+
* const maybeValue = Maybe.Nothing<number>(); // maybeValue is Nothing
113+
* ```
114+
*/
115+
export function Nothing<T>(): Maybe<T> {
116+
const v: Nothing = { kind: 'Nothing' };
117+
return Object.assign(v, MaybeOps<T>(v));
118+
}
119+
120+
/**
121+
* Create a Maybe value from a value that may be null or undefined.
122+
* If the value is null or undefined, a Nothing value is returned.
123+
* Otherwise, a Just value is returned.
124+
* @param value the value to wrap in a Maybe.
125+
* @return a new Maybe value.
126+
* @example
127+
* ```ts
128+
* const maybeValue = Maybe.Maybe(42); // maybeValue is Just(42)
129+
* ...
130+
* const maybeValue = Maybe.Maybe(null); // maybeValue is Nothing
131+
* ```
132+
*/
133+
export function Maybe<T>(value: T | null | undefined): Maybe<T> {
134+
if (value === null || value === undefined) {
135+
return Nothing<T>();
136+
}
137+
return Just(value);
138+
}

src/Morphir/IR/Decoration.elm

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module Morphir.IR.Decoration exposing
33
, getDecoratedNodeIds, getNodeIdsDecoratedWithValue, filterDecorations
44
)
55

6-
{-| Module to work with Decorations. A decoration is an additional piece of information added to your model that is not captured in the langauge
6+
{-| Module to work with Decorations. A decoration is an additional piece of information added to your model that is not captured in the language
77
88
@docs DecorationID, AllDecorationConfigAndData, DecorationData, DecorationConfigAndData
99
@docs getDecoratedNodeIds, getNodeIdsDecoratedWithValue, filterDecorations

src/Morphir/IR/Distribution.elm

+23-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module Morphir.IR.Distribution exposing
2-
( Distribution(..), library
2+
( Distribution(..), Component, library
33
, lookupModuleSpecification, lookupTypeSpecification, lookupValueSpecification, lookupBaseTypeName, lookupValueDefinition
44
, lookupPackageSpecification, lookupPackageName, typeSpecifications, lookupTypeConstructor
55
, resolveAliases, resolveType, resolveRecordConstructors
@@ -18,7 +18,7 @@ information:
1818
- The package definition which contains all the module definitions included in the library. The package definition
1919
contains implementations as well, even ones that are not exposed.
2020
21-
@docs Distribution, library
21+
@docs Distribution, Component, library
2222
2323
2424
# Lookups
@@ -39,10 +39,31 @@ import Morphir.IR.FQName exposing (FQName)
3939
import Morphir.IR.Module as Module exposing (ModuleName)
4040
import Morphir.IR.Name exposing (Name)
4141
import Morphir.IR.Package as Package exposing (PackageName, lookupModuleDefinition)
42+
import Morphir.IR.Path exposing (Path)
4243
import Morphir.IR.Type as Type exposing (Type)
4344
import Morphir.IR.Value as Value exposing (Value)
4445

4546

47+
{-| Type that represents a complete encapsulated and tree-shaken Component.
48+
A component is a superset of Library. It's similar to an application because it contains all the information needed
49+
to run the component. The fields of a component are:
50+
51+
- name: The name of the component
52+
- libraries: All the library dependencies with their implementation.
53+
- inputs: The inputs of the component as a dictionary of the unique input name and it's Morphir type.
54+
- states: The states of the component as a dictionary of the unique state name and it's Morphir type.
55+
- outputs: The outputs of the component as a dictionary of unique names and their values.
56+
57+
-}
58+
type alias Component =
59+
{ name : Path
60+
, libraries : Dict PackageName (Package.Definition () (Type ()))
61+
, inputs : Dict Name (Type ())
62+
, states : Dict Name (Type ())
63+
, outputs : Dict Name (Value () (Type ()))
64+
}
65+
66+
4667
{-| Type that represents a package distribution. Currently the only distribution type we provide is a `Library`.
4768
-}
4869
type Distribution

src/Morphir/IR/Distribution/Codec.elm

+61-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515
-}
1616

1717

18-
module Morphir.IR.Distribution.Codec exposing (encodeDistribution, decodeDistribution)
18+
module Morphir.IR.Distribution.Codec exposing
19+
( encodeDistribution, decodeDistribution
20+
, encodeComponent, decodeComponent
21+
)
1922

2023
{-| Codecs for types in the `Morphir.IR.Distribution` module.
2124
@@ -24,17 +27,24 @@ module Morphir.IR.Distribution.Codec exposing (encodeDistribution, decodeDistrib
2427
2528
@docs encodeDistribution, decodeDistribution
2629
30+
31+
# Component
32+
33+
@docs encodeComponent, decodeComponent
34+
2735
-}
2836

2937
import Dict
3038
import Json.Decode as Decode
3139
import Json.Encode as Encode
3240
import Morphir.Codec exposing (decodeUnit, encodeUnit)
33-
import Morphir.IR.Distribution exposing (Distribution(..))
41+
import Morphir.IR.Distribution exposing (Component, Distribution(..))
3442
import Morphir.IR.Distribution.CodecV1 as CodecV1
43+
import Morphir.IR.Name as Name
3544
import Morphir.IR.Package.Codec as PackageCodec
3645
import Morphir.IR.Path.Codec exposing (decodePath, encodePath)
3746
import Morphir.IR.Type.Codec exposing (decodeType, encodeType)
47+
import Morphir.IR.Value.Codec exposing (decodeValue, encodeValue)
3848

3949

4050
{-| Encode Distribution.
@@ -87,3 +97,52 @@ decodeDistribution =
8797
other ->
8898
Decode.fail <| "Unknown value type: " ++ other
8999
)
100+
101+
102+
{-| Encodes a Component.
103+
-}
104+
encodeComponent : Component -> Encode.Value
105+
encodeComponent component =
106+
Encode.object
107+
[ ( "name", encodePath component.name )
108+
, ( "libraries"
109+
, component.libraries
110+
|> Dict.toList
111+
|> Encode.list
112+
(\( packageName, packageDef ) ->
113+
Encode.list identity
114+
[ encodePath packageName
115+
, PackageCodec.encodeDefinition encodeUnit (encodeType encodeUnit) packageDef
116+
]
117+
)
118+
)
119+
, ( "inputs", Encode.dict Name.toCamelCase (encodeType encodeUnit) component.inputs )
120+
, ( "states", Encode.dict Name.toCamelCase (encodeType encodeUnit) component.states )
121+
, ( "outputs", Encode.dict Name.toCamelCase (encodeValue encodeUnit <| encodeType encodeUnit) component.outputs )
122+
]
123+
124+
125+
{-| Decodes a Component.
126+
-}
127+
decodeComponent : Decode.Decoder Component
128+
decodeComponent =
129+
let
130+
nameKeyValueDecoder valueDecoder =
131+
Decode.keyValuePairs valueDecoder
132+
|> Decode.map
133+
(List.map (Tuple.mapFirst Name.fromString)
134+
>> Dict.fromList
135+
)
136+
137+
libraryEntryDecoder =
138+
Decode.map2 Tuple.pair
139+
(Decode.index 0 decodePath)
140+
(Decode.index 1 (PackageCodec.decodeDefinition decodeUnit (decodeType decodeUnit)))
141+
in
142+
Decode.map5
143+
Component
144+
(Decode.field "name" decodePath)
145+
(Decode.field "libraries" <| (Decode.list libraryEntryDecoder |> Decode.map Dict.fromList))
146+
(Decode.field "inputs" <| nameKeyValueDecoder (decodeType decodeUnit))
147+
(Decode.field "states" <| nameKeyValueDecoder (decodeType decodeUnit))
148+
(Decode.field "outputs" <| nameKeyValueDecoder (decodeValue decodeUnit (decodeType decodeUnit)))

0 commit comments

Comments
 (0)