lawspec 0.9.0 → 0.11.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 (46) hide show
  1. package/API-MIGRATION.md +78 -2
  2. package/HASKELL.md +1 -0
  3. package/KOTLIN.md +5 -0
  4. package/LANGUAGE.md +70 -11
  5. package/NATIVE-BINDINGS.md +1049 -0
  6. package/PRIMITIVES.md +1 -1
  7. package/README.md +86 -23
  8. package/REFINEMENTS.md +6 -1
  9. package/RELEASE-0.10.md +60 -0
  10. package/RELEASE-0.11.md +62 -0
  11. package/api.mjs +23 -3
  12. package/bin/lawspec.mjs +17 -4
  13. package/build.json +60 -38
  14. package/core.wasm +0 -0
  15. package/examples/native-payments/go/example/payments/domain.go +38 -0
  16. package/examples/native-payments/go/example/payments/native_generators_test.go +13 -0
  17. package/examples/native-payments/go/lawspec.json +136 -0
  18. package/examples/native-payments/haskell/lawspec.json +149 -0
  19. package/examples/native-payments/haskell/src/PaymentsDomain.hs +21 -0
  20. package/examples/native-payments/haskell/test/PaymentGenerators.hs +12 -0
  21. package/examples/native-payments/java/lawspec.json +165 -0
  22. package/examples/native-payments/java/src/main/java/domain/PaymentsDomain.java +32 -0
  23. package/examples/native-payments/java/src/test/java/domain/PaymentGenerators.java +16 -0
  24. package/examples/native-payments/javascript/lawspec.json +149 -0
  25. package/examples/native-payments/javascript/src/payments_domain.mjs +44 -0
  26. package/examples/native-payments/javascript/test/lawspec_generators.mjs +6 -0
  27. package/examples/native-payments/kotlin/lawspec.json +165 -0
  28. package/examples/native-payments/kotlin/src/main/kotlin/domain/PaymentsDomain.kt +17 -0
  29. package/examples/native-payments/kotlin/src/test/kotlin/domain/PaymentGenerators.kt +12 -0
  30. package/examples/native-payments/python/lawspec.json +149 -0
  31. package/examples/native-payments/python/src/payments_domain.py +60 -0
  32. package/examples/native-payments/python/tests/lawspec_generators.py +15 -0
  33. package/examples/native-payments/rust/lawspec.json +167 -0
  34. package/examples/native-payments/rust/src/domain.rs +37 -0
  35. package/examples/native-payments/rust/src/lib.rs +2 -0
  36. package/examples/native-payments/rust/tests/support/lawspec_generators.rs +11 -0
  37. package/examples/native-payments/typescript/lawspec.json +149 -0
  38. package/examples/native-payments/typescript/src/payments_domain.ts +42 -0
  39. package/examples/native-payments/typescript/test/lawspec_generators.ts +8 -0
  40. package/examples/specs/indexed_families.lawspec +59 -0
  41. package/examples/specs/payments.lawspec +76 -0
  42. package/examples-command.mjs +5 -0
  43. package/files.mjs +6 -6
  44. package/index.d.ts +53 -2
  45. package/native-examples.mjs +81 -0
  46. package/package.json +2 -2
@@ -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
+ }
@@ -0,0 +1,44 @@
1
+ // Application-owned domain types; no generated domain declarations.
2
+ import * as ls from './lawspec_runtime.mjs';
3
+ export class CurrencyCode {
4
+ }
5
+ export class Dollars extends CurrencyCode {
6
+ }
7
+ export class Euros extends CurrencyCode {
8
+ }
9
+ export class Pounds extends CurrencyCode {
10
+ }
11
+ export class Price {
12
+ major;
13
+ unit;
14
+ constructor({ unit, major }) {
15
+ this.unit = unit;
16
+ this.major = major;
17
+ }
18
+ }
19
+ export class PaymentStatus {
20
+ }
21
+ export class Settled extends PaymentStatus {
22
+ price;
23
+ constructor({ price }) {
24
+ super();
25
+ this.price = price;
26
+ }
27
+ }
28
+ export class Rejected extends PaymentStatus {
29
+ explanation;
30
+ constructor({ explanation }) {
31
+ super();
32
+ this.explanation = explanation;
33
+ }
34
+ }
35
+ export function apply_fee(price) {
36
+ const major = ls.binary('+', price.major, new ls.Decimal(2n, -1n), 'Decimal', 'Decimal');
37
+ return new Price({ major, unit: price.unit });
38
+ }
39
+ export function restore(payment) {
40
+ return payment;
41
+ }
42
+ export function store(payments) {
43
+ return payments;
44
+ }
@@ -0,0 +1,6 @@
1
+ import * as fc from 'fast-check';
2
+ import * as ls from '../src/lawspec_runtime.mjs';
3
+ import { Price, Euros } from '../src/payments_domain.mjs';
4
+ export function prices() {
5
+ return fc.integer({ min: 100, max: 200 }).map(cents => new Price({ major: new ls.Decimal(BigInt(cents), -2n), unit: new Euros() }));
6
+ }
@@ -0,0 +1,165 @@
1
+ {
2
+ "version": 1,
3
+ "sources": [
4
+ "laws"
5
+ ],
6
+ "machineBits": 64,
7
+ "targets": [
8
+ {
9
+ "language": "kotlin",
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,17 @@
1
+ package domain
2
+
3
+ import java.math.BigDecimal
4
+ import lawspec.runtime.LawSpecRuntime.Maybe
5
+
6
+ // Application-owned types; no generated LawSpec domain declarations.
7
+ object PaymentsDomain {
8
+ enum class CurrencyCode { Dollars, Euros, Pounds }
9
+ data class Price(val major: BigDecimal, val unit: CurrencyCode)
10
+ sealed interface PaymentStatus
11
+ data class Settled(val price: Price) : PaymentStatus
12
+ data class Rejected(val explanation: String) : PaymentStatus
13
+
14
+ fun apply_fee(price: Price) = Price(price.major + BigDecimal("0.2"), price.unit)
15
+ fun restore(payment: PaymentStatus) = payment
16
+ fun store(payments: List<Maybe<PaymentStatus>>) = payments
17
+ }
@@ -0,0 +1,12 @@
1
+ package domain
2
+
3
+ import io.kotest.property.Arb
4
+ import io.kotest.property.arbitrary.int
5
+ import io.kotest.property.arbitrary.map
6
+ import java.math.BigDecimal
7
+
8
+ object PaymentGenerators {
9
+ fun prices(): Arb<PaymentsDomain.Price> = Arb.int(100..200).map { cents ->
10
+ PaymentsDomain.Price(BigDecimal.valueOf(cents.toLong(), 2), PaymentsDomain.CurrencyCode.Euros)
11
+ }
12
+ }