lawspec 0.9.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.
- package/API-MIGRATION.md +78 -2
- package/LANGUAGE.md +10 -7
- package/NATIVE-BINDINGS.md +1046 -0
- package/PRIMITIVES.md +1 -1
- package/README.md +73 -23
- package/REFINEMENTS.md +1 -1
- package/RELEASE-0.10.md +60 -0
- package/api.mjs +23 -3
- package/bin/lawspec.mjs +17 -4
- package/build.json +56 -36
- package/core.wasm +0 -0
- package/examples/native-payments/go/example/payments/domain.go +38 -0
- package/examples/native-payments/go/example/payments/native_generators_test.go +13 -0
- package/examples/native-payments/go/lawspec.json +136 -0
- package/examples/native-payments/haskell/lawspec.json +149 -0
- package/examples/native-payments/haskell/src/PaymentsDomain.hs +21 -0
- package/examples/native-payments/haskell/test/PaymentGenerators.hs +12 -0
- package/examples/native-payments/java/lawspec.json +165 -0
- package/examples/native-payments/java/src/main/java/domain/PaymentsDomain.java +32 -0
- package/examples/native-payments/java/src/test/java/domain/PaymentGenerators.java +16 -0
- package/examples/native-payments/javascript/lawspec.json +149 -0
- package/examples/native-payments/javascript/src/payments_domain.mjs +44 -0
- package/examples/native-payments/javascript/test/lawspec_generators.mjs +6 -0
- package/examples/native-payments/kotlin/lawspec.json +165 -0
- package/examples/native-payments/kotlin/src/main/kotlin/domain/PaymentsDomain.kt +17 -0
- package/examples/native-payments/kotlin/src/test/kotlin/domain/PaymentGenerators.kt +12 -0
- package/examples/native-payments/python/lawspec.json +149 -0
- package/examples/native-payments/python/src/payments_domain.py +60 -0
- package/examples/native-payments/python/tests/lawspec_generators.py +15 -0
- package/examples/native-payments/rust/lawspec.json +167 -0
- package/examples/native-payments/rust/src/domain.rs +37 -0
- package/examples/native-payments/rust/src/lib.rs +2 -0
- package/examples/native-payments/rust/tests/support/lawspec_generators.rs +11 -0
- package/examples/native-payments/typescript/lawspec.json +149 -0
- package/examples/native-payments/typescript/src/payments_domain.ts +42 -0
- package/examples/native-payments/typescript/test/lawspec_generators.ts +8 -0
- package/examples/specs/payments.lawspec +76 -0
- package/examples-command.mjs +5 -0
- package/files.mjs +6 -6
- package/index.d.ts +53 -2
- package/native-examples.mjs +81 -0
- package/package.json +2 -2
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"sources": [
|
|
4
|
+
"laws"
|
|
5
|
+
],
|
|
6
|
+
"machineBits": 64,
|
|
7
|
+
"targets": [
|
|
8
|
+
{
|
|
9
|
+
"language": "rust",
|
|
10
|
+
"root": ".",
|
|
11
|
+
"nativeBindings": {
|
|
12
|
+
"rustCrate": "lawspec_example",
|
|
13
|
+
"types": [
|
|
14
|
+
{
|
|
15
|
+
"type": "example.payments::type::Currency",
|
|
16
|
+
"native": [
|
|
17
|
+
"crate",
|
|
18
|
+
"domain",
|
|
19
|
+
"CurrencyCode"
|
|
20
|
+
],
|
|
21
|
+
"constructors": [
|
|
22
|
+
{
|
|
23
|
+
"constructor": "USD",
|
|
24
|
+
"native": [
|
|
25
|
+
"crate",
|
|
26
|
+
"domain",
|
|
27
|
+
"CurrencyCode",
|
|
28
|
+
"Dollars"
|
|
29
|
+
],
|
|
30
|
+
"style": "unit",
|
|
31
|
+
"fields": []
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"constructor": "EUR",
|
|
35
|
+
"native": [
|
|
36
|
+
"crate",
|
|
37
|
+
"domain",
|
|
38
|
+
"CurrencyCode",
|
|
39
|
+
"Euros"
|
|
40
|
+
],
|
|
41
|
+
"style": "unit",
|
|
42
|
+
"fields": []
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"constructor": "GBP",
|
|
46
|
+
"native": [
|
|
47
|
+
"crate",
|
|
48
|
+
"domain",
|
|
49
|
+
"CurrencyCode",
|
|
50
|
+
"Pounds"
|
|
51
|
+
],
|
|
52
|
+
"style": "unit",
|
|
53
|
+
"fields": []
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"type": "example.payments::type::Money",
|
|
59
|
+
"native": [
|
|
60
|
+
"crate",
|
|
61
|
+
"domain",
|
|
62
|
+
"Price"
|
|
63
|
+
],
|
|
64
|
+
"constructors": [
|
|
65
|
+
{
|
|
66
|
+
"constructor": "Money",
|
|
67
|
+
"native": [
|
|
68
|
+
"crate",
|
|
69
|
+
"domain",
|
|
70
|
+
"Price"
|
|
71
|
+
],
|
|
72
|
+
"style": "record",
|
|
73
|
+
"fields": [
|
|
74
|
+
{
|
|
75
|
+
"field": "amount",
|
|
76
|
+
"native": "major"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"field": "currency",
|
|
80
|
+
"native": "unit"
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"type": "example.payments::type::Payment",
|
|
88
|
+
"native": [
|
|
89
|
+
"crate",
|
|
90
|
+
"domain",
|
|
91
|
+
"PaymentStatus"
|
|
92
|
+
],
|
|
93
|
+
"constructors": [
|
|
94
|
+
{
|
|
95
|
+
"constructor": "Paid",
|
|
96
|
+
"native": [
|
|
97
|
+
"crate",
|
|
98
|
+
"domain",
|
|
99
|
+
"PaymentStatus",
|
|
100
|
+
"Settled"
|
|
101
|
+
],
|
|
102
|
+
"style": "variant",
|
|
103
|
+
"fields": [
|
|
104
|
+
{
|
|
105
|
+
"field": "value",
|
|
106
|
+
"native": "price"
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"constructor": "Declined",
|
|
112
|
+
"native": [
|
|
113
|
+
"crate",
|
|
114
|
+
"domain",
|
|
115
|
+
"PaymentStatus",
|
|
116
|
+
"Rejected"
|
|
117
|
+
],
|
|
118
|
+
"style": "variant",
|
|
119
|
+
"fields": [
|
|
120
|
+
{
|
|
121
|
+
"field": "reason",
|
|
122
|
+
"native": "explanation"
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
"functions": [
|
|
130
|
+
{
|
|
131
|
+
"declaration": "example.payments::addFee",
|
|
132
|
+
"native": [
|
|
133
|
+
"crate",
|
|
134
|
+
"domain",
|
|
135
|
+
"apply_fee"
|
|
136
|
+
]
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"declaration": "example.payments::roundTrip",
|
|
140
|
+
"native": [
|
|
141
|
+
"crate",
|
|
142
|
+
"domain",
|
|
143
|
+
"restore"
|
|
144
|
+
]
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"declaration": "example.payments::archive",
|
|
148
|
+
"native": [
|
|
149
|
+
"crate",
|
|
150
|
+
"domain",
|
|
151
|
+
"store"
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
],
|
|
155
|
+
"generators": [
|
|
156
|
+
{
|
|
157
|
+
"type": "example.payments::type::Money",
|
|
158
|
+
"factory": [
|
|
159
|
+
"lawspec_generators",
|
|
160
|
+
"prices"
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
]
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
]
|
|
167
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Application-owned types: no dependency on generated lawspec_data types.
|
|
2
|
+
use crate::lawspec_runtime::Decimal;
|
|
3
|
+
|
|
4
|
+
#[derive(Clone, Debug)]
|
|
5
|
+
pub enum CurrencyCode {
|
|
6
|
+
Dollars,
|
|
7
|
+
Euros,
|
|
8
|
+
Pounds,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
#[derive(Clone, Debug)]
|
|
12
|
+
pub struct Price {
|
|
13
|
+
pub major: Decimal,
|
|
14
|
+
pub unit: CurrencyCode,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
#[derive(Clone, Debug)]
|
|
18
|
+
pub enum PaymentStatus {
|
|
19
|
+
Settled { price: Price },
|
|
20
|
+
Rejected { explanation: String },
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
pub fn apply_fee(mut price: Price) -> Price {
|
|
24
|
+
price.major = price
|
|
25
|
+
.major
|
|
26
|
+
.add(&Decimal::new(2.into(), (-1).into()))
|
|
27
|
+
.unwrap();
|
|
28
|
+
price
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
pub fn restore(payment: PaymentStatus) -> PaymentStatus {
|
|
32
|
+
payment
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
pub fn store(payments: Vec<Option<PaymentStatus>>) -> Vec<Option<PaymentStatus>> {
|
|
36
|
+
payments
|
|
37
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
use lawspec_example::domain::{CurrencyCode, Price};
|
|
2
|
+
use lawspec_example::lawspec_runtime::Decimal;
|
|
3
|
+
use proptest::prelude::*;
|
|
4
|
+
|
|
5
|
+
// The native range strategy retains its shrinker through this mapping.
|
|
6
|
+
pub fn prices() -> impl Strategy<Value = Price> {
|
|
7
|
+
(100i32..=200).prop_map(|cents| Price {
|
|
8
|
+
major: Decimal::new(cents.into(), (-2).into()),
|
|
9
|
+
unit: CurrencyCode::Euros,
|
|
10
|
+
})
|
|
11
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"sources": [
|
|
4
|
+
"laws"
|
|
5
|
+
],
|
|
6
|
+
"machineBits": 64,
|
|
7
|
+
"targets": [
|
|
8
|
+
{
|
|
9
|
+
"language": "typescript",
|
|
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,42 @@
|
|
|
1
|
+
// Application-owned domain types; no generated domain declarations.
|
|
2
|
+
import * as ls from './lawspec_runtime.js';
|
|
3
|
+
|
|
4
|
+
export class CurrencyCode {}
|
|
5
|
+
export class Dollars extends CurrencyCode {}
|
|
6
|
+
export class Euros extends CurrencyCode {}
|
|
7
|
+
export class Pounds extends CurrencyCode {}
|
|
8
|
+
|
|
9
|
+
export class Price {
|
|
10
|
+
major: ls.Decimal;
|
|
11
|
+
unit: CurrencyCode;
|
|
12
|
+
constructor({unit, major}: {unit: CurrencyCode; major: ls.Decimal}) {
|
|
13
|
+
this.unit = unit;
|
|
14
|
+
this.major = major;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export class PaymentStatus {}
|
|
18
|
+
export class Settled extends PaymentStatus {
|
|
19
|
+
price: Price;
|
|
20
|
+
constructor({price}: {price: Price}) {
|
|
21
|
+
super();
|
|
22
|
+
this.price = price;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export class Rejected extends PaymentStatus {
|
|
26
|
+
explanation: string;
|
|
27
|
+
constructor({explanation}: {explanation: string}) {
|
|
28
|
+
super();
|
|
29
|
+
this.explanation = explanation;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function apply_fee(price: Price): Price {
|
|
33
|
+
const major = ls.binary('+', price.major, new ls.Decimal(2n, -1n),
|
|
34
|
+
'Decimal', 'Decimal') as ls.Decimal;
|
|
35
|
+
return new Price({major, unit: price.unit});
|
|
36
|
+
}
|
|
37
|
+
export function restore<T>(payment: T): T {
|
|
38
|
+
return payment;
|
|
39
|
+
}
|
|
40
|
+
export function store<T>(payments: T[]): T[] {
|
|
41
|
+
return payments;
|
|
42
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as fc from 'fast-check';
|
|
2
|
+
import * as ls from '../src/lawspec_runtime.js';
|
|
3
|
+
import {Price, Euros} from '../src/payments_domain.js';
|
|
4
|
+
|
|
5
|
+
export function prices(): fc.Arbitrary<Price> {
|
|
6
|
+
return fc.integer({min:100, max:200}).map(cents =>
|
|
7
|
+
new Price({major:new ls.Decimal(BigInt(cents), -2n), unit:new Euros()}));
|
|
8
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
unit example.payments
|
|
2
|
+
|
|
3
|
+
-- The executable acceptance model for native domain bindings in 0.10.
|
|
4
|
+
-- Applications may call Money "Price", amount "major", and currency "unit";
|
|
5
|
+
-- those representation choices must not alter these laws.
|
|
6
|
+
type Currency is USD | EUR | GBP end
|
|
7
|
+
|
|
8
|
+
type Money is
|
|
9
|
+
Money amount :: Decimal currency :: Currency
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
type Payment is
|
|
13
|
+
Paid value :: Money
|
|
14
|
+
Declined reason :: Text
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
-- These are adapter functions supplied by the application.
|
|
18
|
+
addFee :: Money -> Money
|
|
19
|
+
roundTrip :: Payment -> Payment
|
|
20
|
+
archive :: List (Maybe Payment) -> List (Maybe Payment)
|
|
21
|
+
|
|
22
|
+
-- The model is exact, independent of host decimal rounding settings.
|
|
23
|
+
definition feeModel (money :: Money) :: Money is
|
|
24
|
+
match money with
|
|
25
|
+
| Money amount currency -> Money (amount + 0.2) currency
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
law `fees preserve currency and exact decimal value` is
|
|
30
|
+
definition is
|
|
31
|
+
`for all` (money :: Money) . addFee money = feeModel money
|
|
32
|
+
end
|
|
33
|
+
example `decimal tenths` is
|
|
34
|
+
money = Money 0.1 USD
|
|
35
|
+
expect addFee money = Money 0.3 USD
|
|
36
|
+
end
|
|
37
|
+
example `small amount is not rounded away` is
|
|
38
|
+
money = Money 0.000000000000000000000000000001 EUR
|
|
39
|
+
expect addFee money = Money 0.200000000000000000000000000001 EUR
|
|
40
|
+
end
|
|
41
|
+
example `beyond binary floating precision` is
|
|
42
|
+
money = Money 9007199254740993.1 GBP
|
|
43
|
+
expect addFee money = Money 9007199254740993.3 GBP
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
law `payment variants and payloads survive native conversion` is
|
|
48
|
+
definition is
|
|
49
|
+
`for all` (payment :: Payment) . roundTrip payment = payment
|
|
50
|
+
end
|
|
51
|
+
example `successful payment` is
|
|
52
|
+
payment = Paid (Money 12.34 EUR)
|
|
53
|
+
expect roundTrip payment = Paid (Money 12.34 EUR)
|
|
54
|
+
end
|
|
55
|
+
example `declined payment` is
|
|
56
|
+
payment = Declined "card declined"
|
|
57
|
+
expect roundTrip payment = Declined "card declined"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
law `archives preserve order duplicates and absence` is
|
|
62
|
+
definition is
|
|
63
|
+
`for all` (payments :: List (Maybe Payment)) . archive payments = payments
|
|
64
|
+
end
|
|
65
|
+
example `empty archive` is
|
|
66
|
+
payments = []
|
|
67
|
+
expect archive payments = []
|
|
68
|
+
end
|
|
69
|
+
example `missing is different from a declined payment` is
|
|
70
|
+
payments = [Nothing, Just (Declined ""), Just (Paid (Money 0.1 USD)),
|
|
71
|
+
Just (Paid (Money 0.1 USD))]
|
|
72
|
+
expect archive payments = [Nothing, Just (Declined ""),
|
|
73
|
+
Just (Paid (Money 0.1 USD)),
|
|
74
|
+
Just (Paid (Money 0.1 USD))]
|
|
75
|
+
end
|
|
76
|
+
end
|
package/examples-command.mjs
CHANGED
|
@@ -3,11 +3,16 @@ import path from "node:path";
|
|
|
3
3
|
import { createCompiler } from "./api.mjs";
|
|
4
4
|
import { targets } from "./templates.mjs";
|
|
5
5
|
import { safePath, planWrites, applyWrites } from "./files.mjs";
|
|
6
|
+
import { exportNativePayments } from "./native-examples.mjs";
|
|
6
7
|
|
|
7
8
|
export async function generateExamples(options) {
|
|
8
9
|
const selected = options.target ? [options.target] : targets;
|
|
9
10
|
if (selected.some((t) => !targets.includes(t)))
|
|
10
11
|
throw new Error(`Unknown target: ${options.target}`);
|
|
12
|
+
if (options.example !== undefined) {
|
|
13
|
+
if (options.example !== "payments") throw new Error(`Unknown example: ${options.example}`);
|
|
14
|
+
return exportNativePayments(options, selected);
|
|
15
|
+
}
|
|
11
16
|
const directory = new URL("./examples/specs/", import.meta.url);
|
|
12
17
|
const sources = await Promise.all(
|
|
13
18
|
(await readdir(directory))
|
package/files.mjs
CHANGED
|
@@ -63,8 +63,8 @@ export async function atomicWrite(file, content, exclusive = false) {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
export async function planWrites(root, artifacts) {
|
|
67
|
-
const manifestPath = await safePath(root,
|
|
66
|
+
export async function planWrites(root, artifacts, {manifest = ".lawspec/generated.json"} = {}) {
|
|
67
|
+
const manifestPath = await safePath(root, manifest);
|
|
68
68
|
const previousText = await readOptional(manifestPath);
|
|
69
69
|
const previous =
|
|
70
70
|
previousText === null
|
|
@@ -144,18 +144,18 @@ export async function planWrites(root, artifacts) {
|
|
|
144
144
|
throw new Error(`Refusing to remove edited generated file: ${relative}`);
|
|
145
145
|
changes.push({ action: "remove", file, relative, expected: old });
|
|
146
146
|
}
|
|
147
|
-
const
|
|
147
|
+
const manifestContent =
|
|
148
148
|
JSON.stringify(
|
|
149
149
|
{ version: 1, files: next, adapters: adapterHashes },
|
|
150
150
|
null,
|
|
151
151
|
2,
|
|
152
152
|
) + "\n";
|
|
153
|
-
if (
|
|
153
|
+
if (manifestContent !== previousText)
|
|
154
154
|
changes.push({
|
|
155
155
|
action: previousText === null ? "create" : "update",
|
|
156
156
|
file: manifestPath,
|
|
157
|
-
relative:
|
|
158
|
-
content:
|
|
157
|
+
relative: manifest,
|
|
158
|
+
content: manifestContent,
|
|
159
159
|
expected: previousText,
|
|
160
160
|
});
|
|
161
161
|
return { root, changes, preserved, adapterUpdates };
|
package/index.d.ts
CHANGED
|
@@ -162,11 +162,62 @@ export interface Refinement {
|
|
|
162
162
|
definition: string;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
export type NativeReference = string[];
|
|
166
|
+
|
|
167
|
+
export interface NativeFieldBinding {
|
|
168
|
+
field: string;
|
|
169
|
+
native: string;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export interface NativeConstructorBinding {
|
|
173
|
+
constructor: string;
|
|
174
|
+
native: NativeReference;
|
|
175
|
+
fields?: NativeFieldBinding[];
|
|
176
|
+
style: 'record' | 'variant' | 'unit';
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface NativeCodecBinding {
|
|
180
|
+
toNative: NativeReference;
|
|
181
|
+
fromNative: NativeReference;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export interface NativeTypeBinding {
|
|
185
|
+
type: string;
|
|
186
|
+
native: NativeReference;
|
|
187
|
+
constructors?: NativeConstructorBinding[];
|
|
188
|
+
codec?: NativeCodecBinding;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export interface NativeGeneratorBinding {
|
|
192
|
+
type: string;
|
|
193
|
+
factory: NativeReference;
|
|
194
|
+
stub?: boolean;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export interface NativeFunctionBinding {
|
|
198
|
+
declaration: string;
|
|
199
|
+
native: NativeReference;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export interface NativeGoImport {
|
|
203
|
+
alias: string;
|
|
204
|
+
path: string;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export interface NativeBindings {
|
|
208
|
+
types?: NativeTypeBinding[];
|
|
209
|
+
generators?: NativeGeneratorBinding[];
|
|
210
|
+
functions?: NativeFunctionBinding[];
|
|
211
|
+
rustCrate?: string;
|
|
212
|
+
goImports?: NativeGoImport[];
|
|
213
|
+
}
|
|
214
|
+
|
|
165
215
|
export interface CheckRequest {
|
|
166
216
|
sources: Source[];
|
|
167
|
-
schemaVersion?: 3;
|
|
217
|
+
schemaVersion?: 3 | 4;
|
|
168
218
|
machineBits?: 32 | 64;
|
|
169
219
|
generation?: Partial<Generation>;
|
|
220
|
+
nativeBindings?: NativeBindings;
|
|
170
221
|
}
|
|
171
222
|
|
|
172
223
|
export interface GenerationRequest extends CheckRequest {
|
|
@@ -177,7 +228,7 @@ export interface GenerationRequest extends CheckRequest {
|
|
|
177
228
|
}
|
|
178
229
|
|
|
179
230
|
export interface Result {
|
|
180
|
-
schemaVersion: 3;
|
|
231
|
+
schemaVersion: 3 | 4;
|
|
181
232
|
machineBits?: 32 | 64;
|
|
182
233
|
generation?: Generation;
|
|
183
234
|
units?: Unit[];
|