@reventlessdev/reventless-core 3.0.0-alpha.148 → 3.0.0-alpha.150
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/CHANGELOG.md +14 -0
- package/package.json +6 -6
- package/src/components/Api/Api_Naming.res +38 -10
- package/src/components/Api/Api_Naming.res.mjs +21 -3
- package/src/components/Api/SuryToJsonSchema.res +5 -0
- package/src/components/Api/SuryToJsonSchema.res.mjs +4 -0
- package/src/plugin/lifecycle/PluginsReadModelSpec.res +3 -1
- package/src/plugin/lifecycle/PluginsReadModelSpec.res.mjs +1 -0
- package/tests/api/SuryToJsonSchemaTest.res +20 -0
- package/tests/api/SuryToJsonSchemaTest.res.mjs +51 -0
- package/tests/plugin/StateViewSlice/PsAnnotatedView.res.mjs +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# 3.0.0-alpha.150 (2026-07-10)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **reventless-ppx:** add [@group](https://github.com/group)By state-field annotation → x-reventless-group-by ([9e7a7b2](https://github.com/ReventlessDev/reventless-core/commit/9e7a7b29e54fb4eda1c6a145c0e7b6dcf26940ee))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# 3.0.0-alpha.149 (2026-07-09)
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* **reventless-core:** DCB StateChangeSlice mutations use ${plugin}_${command}, not ${plugin}_${slice}_${command} ([c5874d2](https://github.com/ReventlessDev/reventless-core/commit/c5874d27ad63e6af5c639c8b6c6f8596fd7f682b))
|
|
18
|
+
|
|
19
|
+
|
|
6
20
|
# 3.0.0-alpha.148 (2026-07-09)
|
|
7
21
|
|
|
8
22
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reventlessdev/reventless-core",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.150",
|
|
4
4
|
"description": "Core package for Reventless framework",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"jest": {
|
|
@@ -29,21 +29,21 @@
|
|
|
29
29
|
"sury": "11.0.0-alpha.4",
|
|
30
30
|
"uuid": "^13.0.0",
|
|
31
31
|
"@reventlessdev/rescript-effect": "0.1.0-alpha.25",
|
|
32
|
-
"@reventlessdev/rescript-hash-object": "1.2.0-alpha.10",
|
|
33
32
|
"@reventlessdev/rescript-fast-csv": "1.2.0-alpha.11",
|
|
33
|
+
"@reventlessdev/rescript-hash-object": "1.2.0-alpha.10",
|
|
34
34
|
"@reventlessdev/rescript-jest": "1.0.0-alpha.6",
|
|
35
35
|
"@reventlessdev/rescript-node-streams": "1.1.0-alpha.10",
|
|
36
36
|
"@reventlessdev/rescript-pulumi-pulumi": "2.3.0-alpha.14",
|
|
37
|
+
"@reventlessdev/rescript-ssh2": "1.1.0-alpha.11",
|
|
37
38
|
"@reventlessdev/rescript-uuid": "1.1.0-alpha.14",
|
|
38
|
-
"@reventlessdev/reventless-infra": "3.0.0-alpha.
|
|
39
|
+
"@reventlessdev/reventless-infra": "3.0.0-alpha.92",
|
|
39
40
|
"@reventlessdev/reventless-interop": "3.0.0-alpha.24",
|
|
40
|
-
"@reventlessdev/
|
|
41
|
-
"@reventlessdev/reventless-spec": "3.0.0-alpha.69"
|
|
41
|
+
"@reventlessdev/reventless-spec": "3.0.0-alpha.70"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"rescript": "^12.3.0",
|
|
45
45
|
"sury-ppx": "11.0.0-alpha.2",
|
|
46
|
-
"@reventlessdev/reventless-ppx": "1.0.0-alpha.
|
|
46
|
+
"@reventlessdev/reventless-ppx": "1.0.0-alpha.52"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"rescript": "^12.3.0"
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
open ReventlessInfra.Api
|
|
2
|
-
|
|
3
1
|
type queryNames = {
|
|
4
2
|
singleFieldName: string,
|
|
5
3
|
listFieldName: string,
|
|
@@ -41,13 +39,43 @@ let aggregateMutationField = (~plugin: string, ~aggregate: string, ~command: str
|
|
|
41
39
|
|
|
42
40
|
let sliceMutationField = (~plugin: string, ~slice: string) => `${plugin}_${slice}`
|
|
43
41
|
|
|
42
|
+
// DCB StateChangeSlice per-command mutation field. Unlike aggregates — where multiple
|
|
43
|
+
// aggregates coexist under a plugin so the aggregate name must namespace the command —
|
|
44
|
+
// a DCB slice's command constructor already names the operation, and callers/plans
|
|
45
|
+
// treat the mutation as `${plugin}_${command}`. Doubling in the slice name
|
|
46
|
+
// (`${plugin}_${slice}_${command}`) both renames the primary command out from under
|
|
47
|
+
// existing callers and overflows AppSync's 50-char subscription-field cap once the
|
|
48
|
+
// `on` prefix is added.
|
|
49
|
+
let dcbCommandMutationField = (~plugin: string, ~command: string) => `${plugin}_${command}`
|
|
50
|
+
|
|
51
|
+
// AppSync hard limit: subscription field names may be at most 50 chars. Each mutation
|
|
52
|
+
// field `f` produces a `@aws_subscribe` subscription `on${f}` (see
|
|
53
|
+
// Plugin_SubscriptionSchema.sourceCFields), so the real cap on a mutation field is 48.
|
|
54
|
+
// Fail at build with an actionable message rather than letting AppSync reject the
|
|
55
|
+
// schema push at deploy time with an opaque 500.
|
|
56
|
+
let appSyncSubscriptionMaxLen = 50
|
|
57
|
+
|
|
58
|
+
let assertSubscriptionNameFits = (~fieldName: string) => {
|
|
59
|
+
let subscriptionName = `on${fieldName}`
|
|
60
|
+
if subscriptionName->String.length > appSyncSubscriptionMaxLen {
|
|
61
|
+
JsError.throwWithMessage(
|
|
62
|
+
`Generated subscription field \`${subscriptionName}\` is ${subscriptionName
|
|
63
|
+
->String.length
|
|
64
|
+
->Int.toString} chars, over AppSync's ${appSyncSubscriptionMaxLen->Int.toString}-char limit. ` ++
|
|
65
|
+
`Shorten the plugin, slice, or command name behind mutation field \`${fieldName}\`.`,
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
fieldName
|
|
69
|
+
}
|
|
70
|
+
|
|
44
71
|
// DCB StateChangeSlice mutation fields — one per API-exposed command constructor,
|
|
45
72
|
// mirroring the aggregate path (which emits one field per constructor). A slice whose
|
|
46
73
|
// command union has a single API-exposed constructor keeps the byte-identical
|
|
47
|
-
// `Plugin_Slice` name (no schema churn); a multi-command slice
|
|
48
|
-
// `
|
|
49
|
-
//
|
|
50
|
-
// out.
|
|
74
|
+
// `Plugin_Slice` name (no schema churn); a multi-command slice names each mutation
|
|
75
|
+
// `${plugin}_${command}` — the constructor already names the operation, and callers/plans
|
|
76
|
+
// expect that shape (not aggregate-style `${plugin}_${slice}_${command}`). @noApi
|
|
77
|
+
// variants are filtered out. Every emitted name is guarded against the 50-char AppSync
|
|
78
|
+
// subscription cap at build time. Returns [(fieldName, constructorName)] in declaration order.
|
|
51
79
|
let sliceMutationFields = (
|
|
52
80
|
~plugin: string,
|
|
53
81
|
~slice: string,
|
|
@@ -57,10 +85,10 @@ let sliceMutationFields = (
|
|
|
57
85
|
let filtered = ApiNoApiHelpers.filterNoApiVariants(allNames, commandSchema)
|
|
58
86
|
switch filtered {
|
|
59
87
|
| [] => []
|
|
60
|
-
| [single] => [(sliceMutationField(~plugin, ~slice), single)]
|
|
88
|
+
| [single] => [(assertSubscriptionNameFits(~fieldName=sliceMutationField(~plugin, ~slice)), single)]
|
|
61
89
|
| _ =>
|
|
62
90
|
filtered->Array.map(ctor => (
|
|
63
|
-
|
|
91
|
+
assertSubscriptionNameFits(~fieldName=dcbCommandMutationField(~plugin, ~command=ctor)),
|
|
64
92
|
ctor,
|
|
65
93
|
))
|
|
66
94
|
}
|
|
@@ -68,7 +96,7 @@ let sliceMutationFields = (
|
|
|
68
96
|
|
|
69
97
|
// The mutation field name for a single command constructor of a DCB StateChangeSlice,
|
|
70
98
|
// consistent with `sliceMutationFields`: single-command slices resolve every variant
|
|
71
|
-
// to the slice name, multi-command slices to the
|
|
99
|
+
// to the slice name, multi-command slices to the per-constructor `${plugin}_${command}`.
|
|
72
100
|
let sliceMutationFieldFor = (
|
|
73
101
|
~plugin: string,
|
|
74
102
|
~slice: string,
|
|
@@ -78,7 +106,7 @@ let sliceMutationFieldFor = (
|
|
|
78
106
|
if sliceMutationFields(~plugin, ~slice, ~commandSchema)->Array.length <= 1 {
|
|
79
107
|
sliceMutationField(~plugin, ~slice)
|
|
80
108
|
} else {
|
|
81
|
-
|
|
109
|
+
dcbCommandMutationField(~plugin, ~command=variant)
|
|
82
110
|
}
|
|
83
111
|
|
|
84
112
|
// Pluralize via the singular stem so already-plural names normalise correctly:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
+
import * as Stdlib_JsError from "@rescript/runtime/lib/es6/Stdlib_JsError.js";
|
|
3
4
|
import * as DcbTag$Reventless from "@reventlessdev/reventless-spec/src/components/DcbTag.res.mjs";
|
|
4
5
|
import * as ApiNoApiHelpers$ReventlessCore from "./ApiNoApiHelpers.res.mjs";
|
|
5
6
|
|
|
@@ -41,6 +42,18 @@ function sliceMutationField(plugin, slice) {
|
|
|
41
42
|
return plugin + `_` + slice;
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
function dcbCommandMutationField(plugin, command) {
|
|
46
|
+
return plugin + `_` + command;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function assertSubscriptionNameFits(fieldName) {
|
|
50
|
+
let subscriptionName = `on` + fieldName;
|
|
51
|
+
if (subscriptionName.length > 50) {
|
|
52
|
+
Stdlib_JsError.throwWithMessage(`Generated subscription field \`` + subscriptionName + `\` is ` + subscriptionName.length.toString() + ` chars, over AppSync's ` + (50).toString() + `-char limit. ` + (`Shorten the plugin, slice, or command name behind mutation field \`` + fieldName + `\`.`));
|
|
53
|
+
}
|
|
54
|
+
return fieldName;
|
|
55
|
+
}
|
|
56
|
+
|
|
44
57
|
function sliceMutationFields(plugin, slice, commandSchema) {
|
|
45
58
|
let allNames = DcbTag$Reventless.extractAllVariantNames(commandSchema);
|
|
46
59
|
let filtered = ApiNoApiHelpers$ReventlessCore.filterNoApiVariants(allNames, commandSchema);
|
|
@@ -48,7 +61,7 @@ function sliceMutationFields(plugin, slice, commandSchema) {
|
|
|
48
61
|
if (len !== 1) {
|
|
49
62
|
if (len !== 0) {
|
|
50
63
|
return filtered.map(ctor => [
|
|
51
|
-
|
|
64
|
+
assertSubscriptionNameFits(dcbCommandMutationField(plugin, ctor)),
|
|
52
65
|
ctor
|
|
53
66
|
]);
|
|
54
67
|
} else {
|
|
@@ -57,7 +70,7 @@ function sliceMutationFields(plugin, slice, commandSchema) {
|
|
|
57
70
|
}
|
|
58
71
|
let single = filtered[0];
|
|
59
72
|
return [[
|
|
60
|
-
sliceMutationField(plugin, slice),
|
|
73
|
+
assertSubscriptionNameFits(sliceMutationField(plugin, slice)),
|
|
61
74
|
single
|
|
62
75
|
]];
|
|
63
76
|
}
|
|
@@ -66,7 +79,7 @@ function sliceMutationFieldFor(plugin, slice, commandSchema, variant) {
|
|
|
66
79
|
if (sliceMutationFields(plugin, slice, commandSchema).length <= 1) {
|
|
67
80
|
return sliceMutationField(plugin, slice);
|
|
68
81
|
} else {
|
|
69
|
-
return
|
|
82
|
+
return dcbCommandMutationField(plugin, variant);
|
|
70
83
|
}
|
|
71
84
|
}
|
|
72
85
|
|
|
@@ -119,12 +132,17 @@ function adminField(name) {
|
|
|
119
132
|
return `Platform_` + name;
|
|
120
133
|
}
|
|
121
134
|
|
|
135
|
+
let appSyncSubscriptionMaxLen = 50;
|
|
136
|
+
|
|
122
137
|
export {
|
|
123
138
|
pluralize,
|
|
124
139
|
singularize,
|
|
125
140
|
stripViewSuffix,
|
|
126
141
|
aggregateMutationField,
|
|
127
142
|
sliceMutationField,
|
|
143
|
+
dcbCommandMutationField,
|
|
144
|
+
appSyncSubscriptionMaxLen,
|
|
145
|
+
assertSubscriptionNameFits,
|
|
128
146
|
sliceMutationFields,
|
|
129
147
|
sliceMutationFieldFor,
|
|
130
148
|
canonicalPlural,
|
|
@@ -44,6 +44,11 @@ let mergeAnnotations = (
|
|
|
44
44
|
if spec.summary->Array.includes(fieldName) {
|
|
45
45
|
obj->Dict.set("x-reventless-summary", JSON.Encode.bool(true))
|
|
46
46
|
}
|
|
47
|
+
switch spec.groupBy {
|
|
48
|
+
| Some(name) if name === fieldName =>
|
|
49
|
+
obj->Dict.set("x-reventless-group-by", JSON.Encode.bool(true))
|
|
50
|
+
| _ => ()
|
|
51
|
+
}
|
|
47
52
|
switch spec.drillTargets->Array.find(((field, _)) => field === fieldName) {
|
|
48
53
|
| Some((_, sliceName)) =>
|
|
49
54
|
obj->Dict.set("x-reventless-drillTarget", JSON.Encode.string(sliceName))
|
|
@@ -41,6 +41,10 @@ function mergeAnnotations(fieldSchema, fieldName, spec) {
|
|
|
41
41
|
if (spec.summary.includes(fieldName)) {
|
|
42
42
|
obj["x-reventless-summary"] = true;
|
|
43
43
|
}
|
|
44
|
+
let name = spec.groupBy;
|
|
45
|
+
if (name !== undefined && name === fieldName) {
|
|
46
|
+
obj["x-reventless-group-by"] = true;
|
|
47
|
+
}
|
|
44
48
|
let match$1 = spec.drillTargets.find(param => param[0] === fieldName);
|
|
45
49
|
if (match$1 !== undefined) {
|
|
46
50
|
obj["x-reventless-drillTarget"] = match$1[1];
|
|
@@ -42,7 +42,9 @@ type state = {
|
|
|
42
42
|
// @scan opts the field into server-side equality filtering so the connection gains
|
|
43
43
|
// a `kindEq` filter — the panel split (main list vs System/Infrastructure) pages
|
|
44
44
|
// correctly server-side rather than filtering a page client-side.
|
|
45
|
-
@
|
|
45
|
+
// @groupBy tags this field as the list view's section key (emitted as
|
|
46
|
+
// `x-reventless-group-by`); AutoUI sections the admin Plugins view by kind.
|
|
47
|
+
@scan @groupBy kind: Reventless.Plugin.pluginKind,
|
|
46
48
|
// Other versions of this name that are currently **Connected** — excludes this
|
|
47
49
|
// row's own `version` (whose status is the `status` field above). Lets the
|
|
48
50
|
// projection recompute which version is current (highest Connected) during a
|
|
@@ -30,6 +30,7 @@ let emptySpec: Reventless.StateAnnotations.stateAnnotationSpec = {
|
|
|
30
30
|
scan: [],
|
|
31
31
|
scanSort: [],
|
|
32
32
|
status: None,
|
|
33
|
+
groupBy: None,
|
|
33
34
|
visibility: None,
|
|
34
35
|
}
|
|
35
36
|
|
|
@@ -305,6 +306,25 @@ describe("SuryToJsonSchema:", () => {
|
|
|
305
306
|
))->toEqual((Some(true), None))
|
|
306
307
|
})
|
|
307
308
|
|
|
309
|
+
testSync("emits x-reventless-group-by on the field named by groupBy", () => {
|
|
310
|
+
let schema = S.schema(s =>
|
|
311
|
+
{
|
|
312
|
+
"id": s.matches(S.string),
|
|
313
|
+
"kind": s.matches(S.string),
|
|
314
|
+
}
|
|
315
|
+
)->S.castToUnknown
|
|
316
|
+
let schema' = schema->withSpec({...emptySpec, groupBy: Some("kind")})
|
|
317
|
+
let json = SuryToJsonSchema.deriveObjectSchema(schema')
|
|
318
|
+
let kindSchema = getPropertyOf(json, "kind")
|
|
319
|
+
let idSchema = getPropertyOf(json, "id")
|
|
320
|
+
expect((
|
|
321
|
+
kindSchema
|
|
322
|
+
->Option.flatMap(s => getProperty(s, "x-reventless-group-by"))
|
|
323
|
+
->Option.flatMap(JSON.Decode.bool),
|
|
324
|
+
idSchema->Option.flatMap(s => getProperty(s, "x-reventless-group-by")),
|
|
325
|
+
))->toEqual((Some(true), None))
|
|
326
|
+
})
|
|
327
|
+
|
|
308
328
|
testSync("emits x-reventless-collapsed on field listed in collapsed", () => {
|
|
309
329
|
let schema = S.schema(s =>
|
|
310
330
|
{
|
|
@@ -64,6 +64,7 @@ let emptySpec = {
|
|
|
64
64
|
scan: emptySpec_scan,
|
|
65
65
|
scanSort: emptySpec_scanSort,
|
|
66
66
|
status: undefined,
|
|
67
|
+
groupBy: undefined,
|
|
67
68
|
visibility: undefined
|
|
68
69
|
};
|
|
69
70
|
|
|
@@ -100,6 +101,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
100
101
|
scan: emptySpec_scan,
|
|
101
102
|
scanSort: emptySpec_scanSort,
|
|
102
103
|
status: undefined,
|
|
104
|
+
groupBy: undefined,
|
|
103
105
|
visibility: undefined
|
|
104
106
|
});
|
|
105
107
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -129,6 +131,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
129
131
|
scan: emptySpec_scan,
|
|
130
132
|
scanSort: emptySpec_scanSort,
|
|
131
133
|
status: undefined,
|
|
134
|
+
groupBy: undefined,
|
|
132
135
|
visibility: undefined
|
|
133
136
|
});
|
|
134
137
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -161,6 +164,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
161
164
|
scan: emptySpec_scan,
|
|
162
165
|
scanSort: emptySpec_scanSort,
|
|
163
166
|
status: undefined,
|
|
167
|
+
groupBy: undefined,
|
|
164
168
|
visibility: undefined
|
|
165
169
|
});
|
|
166
170
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -189,6 +193,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
189
193
|
scan: emptySpec_scan,
|
|
190
194
|
scanSort: emptySpec_scanSort,
|
|
191
195
|
status: undefined,
|
|
196
|
+
groupBy: undefined,
|
|
192
197
|
visibility: undefined
|
|
193
198
|
});
|
|
194
199
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -217,6 +222,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
217
222
|
scan: emptySpec_scan,
|
|
218
223
|
scanSort: emptySpec_scanSort,
|
|
219
224
|
status: undefined,
|
|
225
|
+
groupBy: undefined,
|
|
220
226
|
visibility: undefined
|
|
221
227
|
});
|
|
222
228
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -242,6 +248,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
242
248
|
scan: emptySpec_scan,
|
|
243
249
|
scanSort: emptySpec_scanSort,
|
|
244
250
|
status: undefined,
|
|
251
|
+
groupBy: undefined,
|
|
245
252
|
visibility: undefined
|
|
246
253
|
});
|
|
247
254
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -267,6 +274,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
267
274
|
scan: emptySpec_scan,
|
|
268
275
|
scanSort: emptySpec_scanSort,
|
|
269
276
|
status: undefined,
|
|
277
|
+
groupBy: undefined,
|
|
270
278
|
visibility: undefined
|
|
271
279
|
});
|
|
272
280
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -299,6 +307,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
299
307
|
scan: emptySpec_scan,
|
|
300
308
|
scanSort: emptySpec_scanSort,
|
|
301
309
|
status: undefined,
|
|
310
|
+
groupBy: undefined,
|
|
302
311
|
visibility: undefined
|
|
303
312
|
});
|
|
304
313
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -334,6 +343,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
334
343
|
scan: emptySpec_scan,
|
|
335
344
|
scanSort: emptySpec_scanSort,
|
|
336
345
|
status: undefined,
|
|
346
|
+
groupBy: undefined,
|
|
337
347
|
visibility: undefined
|
|
338
348
|
});
|
|
339
349
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -372,6 +382,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
372
382
|
scan: emptySpec_scan,
|
|
373
383
|
scanSort: emptySpec_scanSort,
|
|
374
384
|
status: undefined,
|
|
385
|
+
groupBy: undefined,
|
|
375
386
|
visibility: undefined
|
|
376
387
|
});
|
|
377
388
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -400,6 +411,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
400
411
|
scan: emptySpec_scan,
|
|
401
412
|
scanSort: emptySpec_scanSort,
|
|
402
413
|
status: undefined,
|
|
414
|
+
groupBy: undefined,
|
|
403
415
|
visibility: undefined
|
|
404
416
|
});
|
|
405
417
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -425,6 +437,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
425
437
|
scan: ["status"],
|
|
426
438
|
scanSort: emptySpec_scanSort,
|
|
427
439
|
status: undefined,
|
|
440
|
+
groupBy: undefined,
|
|
428
441
|
visibility: undefined
|
|
429
442
|
});
|
|
430
443
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -457,6 +470,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
457
470
|
scan: emptySpec_scan,
|
|
458
471
|
scanSort: ["name"],
|
|
459
472
|
status: undefined,
|
|
473
|
+
groupBy: undefined,
|
|
460
474
|
visibility: undefined
|
|
461
475
|
});
|
|
462
476
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -470,6 +484,39 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
470
484
|
undefined
|
|
471
485
|
]);
|
|
472
486
|
});
|
|
487
|
+
globalThis.test("emits x-reventless-group-by on the field named by groupBy", () => {
|
|
488
|
+
let schema = S.schema(s => ({
|
|
489
|
+
id: s.m(S.string),
|
|
490
|
+
kind: s.m(S.string)
|
|
491
|
+
}));
|
|
492
|
+
let schema$p = withSpec(schema, {
|
|
493
|
+
ids: emptySpec_ids,
|
|
494
|
+
compositeIds: emptySpec_compositeIds,
|
|
495
|
+
subIds: emptySpec_subIds,
|
|
496
|
+
compositeSubIds: emptySpec_compositeSubIds,
|
|
497
|
+
indexes: emptySpec_indexes,
|
|
498
|
+
hidden: emptySpec_hidden,
|
|
499
|
+
summary: emptySpec_summary,
|
|
500
|
+
drillTargets: emptySpec_drillTargets,
|
|
501
|
+
drillTargetKeys: emptySpec_drillTargetKeys,
|
|
502
|
+
collapsed: emptySpec_collapsed,
|
|
503
|
+
scan: emptySpec_scan,
|
|
504
|
+
scanSort: emptySpec_scanSort,
|
|
505
|
+
status: undefined,
|
|
506
|
+
groupBy: "kind",
|
|
507
|
+
visibility: undefined
|
|
508
|
+
});
|
|
509
|
+
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
510
|
+
let kindSchema = getPropertyOf(json, "kind");
|
|
511
|
+
let idSchema = getPropertyOf(json, "id");
|
|
512
|
+
globalThis.expect([
|
|
513
|
+
Stdlib_Option.flatMap(Stdlib_Option.flatMap(kindSchema, s => getProperty(s, "x-reventless-group-by")), Stdlib_JSON.Decode.bool),
|
|
514
|
+
Stdlib_Option.flatMap(idSchema, s => getProperty(s, "x-reventless-group-by"))
|
|
515
|
+
]).toEqual([
|
|
516
|
+
true,
|
|
517
|
+
undefined
|
|
518
|
+
]);
|
|
519
|
+
});
|
|
473
520
|
globalThis.test("emits x-reventless-collapsed on field listed in collapsed", () => {
|
|
474
521
|
let schema = S.schema(s => ({
|
|
475
522
|
id: s.m(S.string),
|
|
@@ -489,6 +536,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
489
536
|
scan: emptySpec_scan,
|
|
490
537
|
scanSort: emptySpec_scanSort,
|
|
491
538
|
status: undefined,
|
|
539
|
+
groupBy: undefined,
|
|
492
540
|
visibility: undefined
|
|
493
541
|
});
|
|
494
542
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -520,6 +568,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
520
568
|
scan: emptySpec_scan,
|
|
521
569
|
scanSort: emptySpec_scanSort,
|
|
522
570
|
status: undefined,
|
|
571
|
+
groupBy: undefined,
|
|
523
572
|
visibility: "Internal"
|
|
524
573
|
});
|
|
525
574
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -543,6 +592,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
543
592
|
scan: emptySpec_scan,
|
|
544
593
|
scanSort: emptySpec_scanSort,
|
|
545
594
|
status: undefined,
|
|
595
|
+
groupBy: undefined,
|
|
546
596
|
visibility: undefined
|
|
547
597
|
});
|
|
548
598
|
let json = SuryToJsonSchema$ReventlessCore.deriveObjectSchema(schema$p);
|
|
@@ -606,6 +656,7 @@ globalThis.describe("SuryToJsonSchema:", () => {
|
|
|
606
656
|
scan: emptySpec_scan,
|
|
607
657
|
scanSort: emptySpec_scanSort,
|
|
608
658
|
status: undefined,
|
|
659
|
+
groupBy: undefined,
|
|
609
660
|
visibility: undefined
|
|
610
661
|
});
|
|
611
662
|
let native = S.toJSONSchema(schema$p);
|