lawspec 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/API-MIGRATION.md +180 -3
  2. package/GO.md +144 -0
  3. package/HASKELL.md +171 -0
  4. package/JAVA.md +113 -0
  5. package/KOTLIN.md +214 -0
  6. package/LANGUAGE.md +240 -12
  7. package/NATIVE-BINDINGS.md +1046 -0
  8. package/PRIMITIVES.md +1 -1
  9. package/PYTHON.md +152 -0
  10. package/README.md +86 -23
  11. package/REFINEMENTS.md +289 -3
  12. package/RELEASE-0.10.md +60 -0
  13. package/RELEASE-0.9.md +61 -0
  14. package/RUST.md +115 -1
  15. package/WEB.md +144 -0
  16. package/api.mjs +28 -2
  17. package/bin/lawspec.mjs +23 -7
  18. package/build.json +199 -37
  19. package/core.wasm +0 -0
  20. package/examples/native-payments/go/example/payments/domain.go +38 -0
  21. package/examples/native-payments/go/example/payments/native_generators_test.go +13 -0
  22. package/examples/native-payments/go/lawspec.json +136 -0
  23. package/examples/native-payments/haskell/lawspec.json +149 -0
  24. package/examples/native-payments/haskell/src/PaymentsDomain.hs +21 -0
  25. package/examples/native-payments/haskell/test/PaymentGenerators.hs +12 -0
  26. package/examples/native-payments/java/lawspec.json +165 -0
  27. package/examples/native-payments/java/src/main/java/domain/PaymentsDomain.java +32 -0
  28. package/examples/native-payments/java/src/test/java/domain/PaymentGenerators.java +16 -0
  29. package/examples/native-payments/javascript/lawspec.json +149 -0
  30. package/examples/native-payments/javascript/src/payments_domain.mjs +44 -0
  31. package/examples/native-payments/javascript/test/lawspec_generators.mjs +6 -0
  32. package/examples/native-payments/kotlin/lawspec.json +165 -0
  33. package/examples/native-payments/kotlin/src/main/kotlin/domain/PaymentsDomain.kt +17 -0
  34. package/examples/native-payments/kotlin/src/test/kotlin/domain/PaymentGenerators.kt +12 -0
  35. package/examples/native-payments/python/lawspec.json +149 -0
  36. package/examples/native-payments/python/src/payments_domain.py +60 -0
  37. package/examples/native-payments/python/tests/lawspec_generators.py +15 -0
  38. package/examples/native-payments/rust/lawspec.json +167 -0
  39. package/examples/native-payments/rust/src/domain.rs +37 -0
  40. package/examples/native-payments/rust/src/lib.rs +2 -0
  41. package/examples/native-payments/rust/tests/support/lawspec_generators.rs +11 -0
  42. package/examples/native-payments/typescript/lawspec.json +149 -0
  43. package/examples/native-payments/typescript/src/payments_domain.ts +42 -0
  44. package/examples/native-payments/typescript/test/lawspec_generators.ts +8 -0
  45. package/examples/specs/collections.lawspec +67 -0
  46. package/examples/specs/data_types.lawspec +66 -0
  47. package/examples/specs/finite_data.lawspec +37 -0
  48. package/examples/specs/list_contracts.lawspec +136 -0
  49. package/examples/specs/list_refinements.lawspec +51 -0
  50. package/examples/specs/matching.lawspec +49 -0
  51. package/examples/specs/payments.lawspec +76 -0
  52. package/examples/specs/recursive_refinements.lawspec +41 -0
  53. package/examples/specs/refined_definitions.lawspec +44 -0
  54. package/examples/specs/sum_refinements.lawspec +49 -0
  55. package/examples/specs/total_functions.lawspec +101 -0
  56. package/examples-command.mjs +11 -1
  57. package/files.mjs +16 -7
  58. package/index.d.ts +297 -27
  59. package/native-examples.mjs +81 -0
  60. package/package.json +2 -2
  61. package/templates.mjs +107 -17
@@ -0,0 +1,136 @@
1
+ {
2
+ "version": 1,
3
+ "sources": [
4
+ "laws"
5
+ ],
6
+ "machineBits": 64,
7
+ "targets": [
8
+ {
9
+ "language": "go",
10
+ "root": ".",
11
+ "nativeBindings": {
12
+ "types": [
13
+ {
14
+ "type": "example.payments::type::Currency",
15
+ "native": [
16
+ "CurrencyCode"
17
+ ],
18
+ "constructors": [
19
+ {
20
+ "constructor": "USD",
21
+ "native": [
22
+ "Dollars"
23
+ ],
24
+ "style": "unit",
25
+ "fields": []
26
+ },
27
+ {
28
+ "constructor": "EUR",
29
+ "native": [
30
+ "Euros"
31
+ ],
32
+ "style": "unit",
33
+ "fields": []
34
+ },
35
+ {
36
+ "constructor": "GBP",
37
+ "native": [
38
+ "Pounds"
39
+ ],
40
+ "style": "unit",
41
+ "fields": []
42
+ }
43
+ ]
44
+ },
45
+ {
46
+ "type": "example.payments::type::Money",
47
+ "native": [
48
+ "Price"
49
+ ],
50
+ "constructors": [
51
+ {
52
+ "constructor": "Money",
53
+ "native": [
54
+ "Price"
55
+ ],
56
+ "style": "record",
57
+ "fields": [
58
+ {
59
+ "field": "amount",
60
+ "native": "Major"
61
+ },
62
+ {
63
+ "field": "currency",
64
+ "native": "Unit"
65
+ }
66
+ ]
67
+ }
68
+ ]
69
+ },
70
+ {
71
+ "type": "example.payments::type::Payment",
72
+ "native": [
73
+ "PaymentStatus"
74
+ ],
75
+ "constructors": [
76
+ {
77
+ "constructor": "Paid",
78
+ "native": [
79
+ "Settled"
80
+ ],
81
+ "style": "variant",
82
+ "fields": [
83
+ {
84
+ "field": "value",
85
+ "native": "Price"
86
+ }
87
+ ]
88
+ },
89
+ {
90
+ "constructor": "Declined",
91
+ "native": [
92
+ "Rejected"
93
+ ],
94
+ "style": "variant",
95
+ "fields": [
96
+ {
97
+ "field": "reason",
98
+ "native": "Explanation"
99
+ }
100
+ ]
101
+ }
102
+ ]
103
+ }
104
+ ],
105
+ "functions": [
106
+ {
107
+ "declaration": "example.payments::addFee",
108
+ "native": [
109
+ "AddFee"
110
+ ]
111
+ },
112
+ {
113
+ "declaration": "example.payments::roundTrip",
114
+ "native": [
115
+ "Restore"
116
+ ]
117
+ },
118
+ {
119
+ "declaration": "example.payments::archive",
120
+ "native": [
121
+ "Store"
122
+ ]
123
+ }
124
+ ],
125
+ "generators": [
126
+ {
127
+ "type": "example.payments::type::Money",
128
+ "factory": [
129
+ "NativePrices"
130
+ ]
131
+ }
132
+ ]
133
+ }
134
+ }
135
+ ]
136
+ }
@@ -0,0 +1,149 @@
1
+ {
2
+ "version": 1,
3
+ "sources": [
4
+ "laws"
5
+ ],
6
+ "machineBits": 64,
7
+ "targets": [
8
+ {
9
+ "language": "haskell",
10
+ "root": ".",
11
+ "nativeBindings": {
12
+ "types": [
13
+ {
14
+ "type": "example.payments::type::Currency",
15
+ "native": [
16
+ "PaymentsDomain",
17
+ "CurrencyCode"
18
+ ],
19
+ "constructors": [
20
+ {
21
+ "constructor": "USD",
22
+ "native": [
23
+ "PaymentsDomain",
24
+ "Dollars"
25
+ ],
26
+ "style": "unit",
27
+ "fields": []
28
+ },
29
+ {
30
+ "constructor": "EUR",
31
+ "native": [
32
+ "PaymentsDomain",
33
+ "Euros"
34
+ ],
35
+ "style": "unit",
36
+ "fields": []
37
+ },
38
+ {
39
+ "constructor": "GBP",
40
+ "native": [
41
+ "PaymentsDomain",
42
+ "Pounds"
43
+ ],
44
+ "style": "unit",
45
+ "fields": []
46
+ }
47
+ ]
48
+ },
49
+ {
50
+ "type": "example.payments::type::Money",
51
+ "native": [
52
+ "PaymentsDomain",
53
+ "Price"
54
+ ],
55
+ "constructors": [
56
+ {
57
+ "constructor": "Money",
58
+ "native": [
59
+ "PaymentsDomain",
60
+ "Price"
61
+ ],
62
+ "style": "record",
63
+ "fields": [
64
+ {
65
+ "field": "amount",
66
+ "native": "major"
67
+ },
68
+ {
69
+ "field": "currency",
70
+ "native": "unit"
71
+ }
72
+ ]
73
+ }
74
+ ]
75
+ },
76
+ {
77
+ "type": "example.payments::type::Payment",
78
+ "native": [
79
+ "PaymentsDomain",
80
+ "PaymentStatus"
81
+ ],
82
+ "constructors": [
83
+ {
84
+ "constructor": "Paid",
85
+ "native": [
86
+ "PaymentsDomain",
87
+ "Settled"
88
+ ],
89
+ "style": "variant",
90
+ "fields": [
91
+ {
92
+ "field": "value",
93
+ "native": "price"
94
+ }
95
+ ]
96
+ },
97
+ {
98
+ "constructor": "Declined",
99
+ "native": [
100
+ "PaymentsDomain",
101
+ "Rejected"
102
+ ],
103
+ "style": "variant",
104
+ "fields": [
105
+ {
106
+ "field": "reason",
107
+ "native": "explanation"
108
+ }
109
+ ]
110
+ }
111
+ ]
112
+ }
113
+ ],
114
+ "functions": [
115
+ {
116
+ "declaration": "example.payments::addFee",
117
+ "native": [
118
+ "PaymentsDomain",
119
+ "addFee"
120
+ ]
121
+ },
122
+ {
123
+ "declaration": "example.payments::roundTrip",
124
+ "native": [
125
+ "PaymentsDomain",
126
+ "restore"
127
+ ]
128
+ },
129
+ {
130
+ "declaration": "example.payments::archive",
131
+ "native": [
132
+ "PaymentsDomain",
133
+ "store"
134
+ ]
135
+ }
136
+ ],
137
+ "generators": [
138
+ {
139
+ "type": "example.payments::type::Money",
140
+ "factory": [
141
+ "PaymentGenerators",
142
+ "prices"
143
+ ]
144
+ }
145
+ ]
146
+ }
147
+ }
148
+ ]
149
+ }
@@ -0,0 +1,21 @@
1
+ module PaymentsDomain where
2
+
3
+ import Data.Ratio ((%))
4
+ import Data.Text (Text)
5
+ import LawSpecRuntime (Decimal(..))
6
+
7
+ data CurrencyCode = Dollars | Euros | Pounds deriving (Eq, Show)
8
+ -- Deliberately reverse the logical field order.
9
+ data Price = Price { unit :: CurrencyCode, major :: Decimal } deriving (Eq, Show)
10
+ data PaymentStatus = Settled { price :: Price } | Rejected { explanation :: Text }
11
+ deriving (Eq, Show)
12
+
13
+ addFee :: Price -> Price
14
+ addFee value = case major value of
15
+ Decimal amount -> value { major = Decimal (amount + 1 % 5) }
16
+
17
+ restore :: PaymentStatus -> PaymentStatus
18
+ restore value = value
19
+
20
+ store :: [Maybe PaymentStatus] -> [Maybe PaymentStatus]
21
+ store values = values
@@ -0,0 +1,12 @@
1
+ module PaymentGenerators where
2
+
3
+ import Data.Ratio ((%))
4
+ import Hedgehog (Gen)
5
+ import qualified Hedgehog.Gen as Gen
6
+ import qualified Hedgehog.Range as Range
7
+ import LawSpecRuntime (Decimal(..))
8
+ import PaymentsDomain
9
+
10
+ prices :: Gen Price
11
+ prices = (\cents -> Price Euros (Decimal (cents % 100))) <$>
12
+ Gen.integral (Range.linear 100 200)
@@ -0,0 +1,165 @@
1
+ {
2
+ "version": 1,
3
+ "sources": [
4
+ "laws"
5
+ ],
6
+ "machineBits": 64,
7
+ "targets": [
8
+ {
9
+ "language": "java",
10
+ "root": ".",
11
+ "nativeBindings": {
12
+ "types": [
13
+ {
14
+ "type": "example.payments::type::Currency",
15
+ "native": [
16
+ "domain",
17
+ "PaymentsDomain",
18
+ "CurrencyCode"
19
+ ],
20
+ "constructors": [
21
+ {
22
+ "constructor": "USD",
23
+ "native": [
24
+ "domain",
25
+ "PaymentsDomain",
26
+ "CurrencyCode",
27
+ "Dollars"
28
+ ],
29
+ "style": "unit",
30
+ "fields": []
31
+ },
32
+ {
33
+ "constructor": "EUR",
34
+ "native": [
35
+ "domain",
36
+ "PaymentsDomain",
37
+ "CurrencyCode",
38
+ "Euros"
39
+ ],
40
+ "style": "unit",
41
+ "fields": []
42
+ },
43
+ {
44
+ "constructor": "GBP",
45
+ "native": [
46
+ "domain",
47
+ "PaymentsDomain",
48
+ "CurrencyCode",
49
+ "Pounds"
50
+ ],
51
+ "style": "unit",
52
+ "fields": []
53
+ }
54
+ ]
55
+ },
56
+ {
57
+ "type": "example.payments::type::Money",
58
+ "native": [
59
+ "domain",
60
+ "PaymentsDomain",
61
+ "Price"
62
+ ],
63
+ "constructors": [
64
+ {
65
+ "constructor": "Money",
66
+ "native": [
67
+ "domain",
68
+ "PaymentsDomain",
69
+ "Price"
70
+ ],
71
+ "style": "record",
72
+ "fields": [
73
+ {
74
+ "field": "amount",
75
+ "native": "major"
76
+ },
77
+ {
78
+ "field": "currency",
79
+ "native": "unit"
80
+ }
81
+ ]
82
+ }
83
+ ]
84
+ },
85
+ {
86
+ "type": "example.payments::type::Payment",
87
+ "native": [
88
+ "domain",
89
+ "PaymentsDomain",
90
+ "PaymentStatus"
91
+ ],
92
+ "constructors": [
93
+ {
94
+ "constructor": "Paid",
95
+ "native": [
96
+ "domain",
97
+ "PaymentsDomain",
98
+ "Settled"
99
+ ],
100
+ "style": "variant",
101
+ "fields": [
102
+ {
103
+ "field": "value",
104
+ "native": "price"
105
+ }
106
+ ]
107
+ },
108
+ {
109
+ "constructor": "Declined",
110
+ "native": [
111
+ "domain",
112
+ "PaymentsDomain",
113
+ "Rejected"
114
+ ],
115
+ "style": "variant",
116
+ "fields": [
117
+ {
118
+ "field": "reason",
119
+ "native": "explanation"
120
+ }
121
+ ]
122
+ }
123
+ ]
124
+ }
125
+ ],
126
+ "functions": [
127
+ {
128
+ "declaration": "example.payments::addFee",
129
+ "native": [
130
+ "domain",
131
+ "PaymentsDomain",
132
+ "apply_fee"
133
+ ]
134
+ },
135
+ {
136
+ "declaration": "example.payments::roundTrip",
137
+ "native": [
138
+ "domain",
139
+ "PaymentsDomain",
140
+ "restore"
141
+ ]
142
+ },
143
+ {
144
+ "declaration": "example.payments::archive",
145
+ "native": [
146
+ "domain",
147
+ "PaymentsDomain",
148
+ "store"
149
+ ]
150
+ }
151
+ ],
152
+ "generators": [
153
+ {
154
+ "type": "example.payments::type::Money",
155
+ "factory": [
156
+ "domain",
157
+ "PaymentGenerators",
158
+ "prices"
159
+ ]
160
+ }
161
+ ]
162
+ }
163
+ }
164
+ ]
165
+ }
@@ -0,0 +1,32 @@
1
+ package domain;
2
+
3
+ import java.math.BigDecimal;
4
+ import java.util.List;
5
+ import lawspec.runtime.LawSpecRuntime.Maybe;
6
+
7
+ /** Application types, independent of generated LawSpec domain declarations. */
8
+ public final class PaymentsDomain {
9
+ private PaymentsDomain() {}
10
+
11
+ public enum CurrencyCode { Dollars, Euros, Pounds }
12
+
13
+ public record Price(BigDecimal major, CurrencyCode unit) {}
14
+
15
+ public sealed interface PaymentStatus permits Settled, Rejected {}
16
+
17
+ public record Settled(Price price) implements PaymentStatus {}
18
+
19
+ public record Rejected(String explanation) implements PaymentStatus {}
20
+
21
+ public static Price apply_fee(Price price) {
22
+ return new Price(price.major().add(new BigDecimal("0.2")), price.unit());
23
+ }
24
+
25
+ public static PaymentStatus restore(PaymentStatus payment) {
26
+ return payment;
27
+ }
28
+
29
+ public static List<Maybe<PaymentStatus>> store(List<Maybe<PaymentStatus>> payments) {
30
+ return payments;
31
+ }
32
+ }
@@ -0,0 +1,16 @@
1
+ package domain;
2
+
3
+ import java.math.BigDecimal;
4
+ import java.math.BigInteger;
5
+ import org.jetbrains.jetCheck.Generator;
6
+
7
+ public final class PaymentGenerators {
8
+ private PaymentGenerators() {}
9
+
10
+ public static Generator<PaymentsDomain.Price> prices() {
11
+ return Generator.integers(100, 200)
12
+ .map(cents -> new PaymentsDomain.Price(
13
+ new BigDecimal(BigInteger.valueOf(cents), 2),
14
+ PaymentsDomain.CurrencyCode.Euros));
15
+ }
16
+ }
@@ -0,0 +1,149 @@
1
+ {
2
+ "version": 1,
3
+ "sources": [
4
+ "laws"
5
+ ],
6
+ "machineBits": 64,
7
+ "targets": [
8
+ {
9
+ "language": "javascript",
10
+ "root": ".",
11
+ "nativeBindings": {
12
+ "types": [
13
+ {
14
+ "type": "example.payments::type::Currency",
15
+ "native": [
16
+ "payments_domain",
17
+ "CurrencyCode"
18
+ ],
19
+ "constructors": [
20
+ {
21
+ "constructor": "USD",
22
+ "native": [
23
+ "payments_domain",
24
+ "Dollars"
25
+ ],
26
+ "style": "unit",
27
+ "fields": []
28
+ },
29
+ {
30
+ "constructor": "EUR",
31
+ "native": [
32
+ "payments_domain",
33
+ "Euros"
34
+ ],
35
+ "style": "unit",
36
+ "fields": []
37
+ },
38
+ {
39
+ "constructor": "GBP",
40
+ "native": [
41
+ "payments_domain",
42
+ "Pounds"
43
+ ],
44
+ "style": "unit",
45
+ "fields": []
46
+ }
47
+ ]
48
+ },
49
+ {
50
+ "type": "example.payments::type::Money",
51
+ "native": [
52
+ "payments_domain",
53
+ "Price"
54
+ ],
55
+ "constructors": [
56
+ {
57
+ "constructor": "Money",
58
+ "native": [
59
+ "payments_domain",
60
+ "Price"
61
+ ],
62
+ "style": "record",
63
+ "fields": [
64
+ {
65
+ "field": "amount",
66
+ "native": "major"
67
+ },
68
+ {
69
+ "field": "currency",
70
+ "native": "unit"
71
+ }
72
+ ]
73
+ }
74
+ ]
75
+ },
76
+ {
77
+ "type": "example.payments::type::Payment",
78
+ "native": [
79
+ "payments_domain",
80
+ "PaymentStatus"
81
+ ],
82
+ "constructors": [
83
+ {
84
+ "constructor": "Paid",
85
+ "native": [
86
+ "payments_domain",
87
+ "Settled"
88
+ ],
89
+ "style": "variant",
90
+ "fields": [
91
+ {
92
+ "field": "value",
93
+ "native": "price"
94
+ }
95
+ ]
96
+ },
97
+ {
98
+ "constructor": "Declined",
99
+ "native": [
100
+ "payments_domain",
101
+ "Rejected"
102
+ ],
103
+ "style": "variant",
104
+ "fields": [
105
+ {
106
+ "field": "reason",
107
+ "native": "explanation"
108
+ }
109
+ ]
110
+ }
111
+ ]
112
+ }
113
+ ],
114
+ "functions": [
115
+ {
116
+ "declaration": "example.payments::addFee",
117
+ "native": [
118
+ "payments_domain",
119
+ "apply_fee"
120
+ ]
121
+ },
122
+ {
123
+ "declaration": "example.payments::roundTrip",
124
+ "native": [
125
+ "payments_domain",
126
+ "restore"
127
+ ]
128
+ },
129
+ {
130
+ "declaration": "example.payments::archive",
131
+ "native": [
132
+ "payments_domain",
133
+ "store"
134
+ ]
135
+ }
136
+ ],
137
+ "generators": [
138
+ {
139
+ "type": "example.payments::type::Money",
140
+ "factory": [
141
+ "lawspec_generators",
142
+ "prices"
143
+ ]
144
+ }
145
+ ]
146
+ }
147
+ }
148
+ ]
149
+ }