@reventlessdev/reventless-spec 3.0.0-alpha.100
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 +931 -0
- package/LICENSE +202 -0
- package/README.md +109 -0
- package/package.json +49 -0
- package/rescript.json +32 -0
- package/run-generator.mjs +2 -0
- package/run-platform-generator.mjs +2 -0
- package/scripts/generate-currency.mjs +215 -0
- package/scripts/iso-4217-list-one.xml +1956 -0
- package/src/AnsiStyle.res +40 -0
- package/src/AnsiStyle.res.mjs +54 -0
- package/src/LogPrefix.res +192 -0
- package/src/LogPrefix.res.mjs +159 -0
- package/src/PackageVersion.res +67 -0
- package/src/PackageVersion.res.mjs +81 -0
- package/src/components/Aggregate.res +64 -0
- package/src/components/Aggregate.res.mjs +2 -0
- package/src/components/AutomationSlice.res +279 -0
- package/src/components/AutomationSlice.res.mjs +30 -0
- package/src/components/CapabilityManifest.res +74 -0
- package/src/components/CapabilityManifest.res.mjs +61 -0
- package/src/components/ComponentKind.res +99 -0
- package/src/components/ComponentKind.res.mjs +125 -0
- package/src/components/Counter.res +24 -0
- package/src/components/Counter.res.mjs +2 -0
- package/src/components/DcbDecode.res +118 -0
- package/src/components/DcbDecode.res.mjs +100 -0
- package/src/components/DcbScopeInference.res +244 -0
- package/src/components/DcbScopeInference.res.mjs +177 -0
- package/src/components/DcbTag.res +1335 -0
- package/src/components/DcbTag.res.mjs +898 -0
- package/src/components/DcbValidation.res +427 -0
- package/src/components/DcbValidation.res.mjs +423 -0
- package/src/components/DisplayName.res +40 -0
- package/src/components/DisplayName.res.mjs +26 -0
- package/src/components/ExtensionPoint.res +27 -0
- package/src/components/ExtensionPoint.res.mjs +2 -0
- package/src/components/InboundTranslationSlice.res +85 -0
- package/src/components/InboundTranslationSlice.res.mjs +2 -0
- package/src/components/OutboundTranslationSlice.res +153 -0
- package/src/components/OutboundTranslationSlice.res.mjs +2 -0
- package/src/components/Plugin.res +538 -0
- package/src/components/Plugin.res.mjs +264 -0
- package/src/components/PluginName.res +39 -0
- package/src/components/PluginName.res.mjs +45 -0
- package/src/components/ReadModel.res +199 -0
- package/src/components/ReadModel.res.mjs +18 -0
- package/src/components/Reference.res +55 -0
- package/src/components/Reference.res.mjs +50 -0
- package/src/components/Snapshot.res +26 -0
- package/src/components/Snapshot.res.mjs +2 -0
- package/src/components/StateAnnotations.res +97 -0
- package/src/components/StateAnnotations.res.mjs +15 -0
- package/src/components/StateChangeSlice.res +131 -0
- package/src/components/StateChangeSlice.res.mjs +2 -0
- package/src/components/StateViewSlice.res +123 -0
- package/src/components/StateViewSlice.res.mjs +2 -0
- package/src/components/Task.res +62 -0
- package/src/components/Task.res.mjs +2 -0
- package/src/generator/Codegen.res +842 -0
- package/src/generator/Codegen.res.mjs +565 -0
- package/src/generator/Config.res +106 -0
- package/src/generator/Config.res.mjs +69 -0
- package/src/generator/Discovery.res +230 -0
- package/src/generator/Discovery.res.mjs +198 -0
- package/src/generator/Generator_Node.res +14 -0
- package/src/generator/Generator_Node.res.mjs +18 -0
- package/src/generator/Pairing.res +460 -0
- package/src/generator/Pairing.res.mjs +415 -0
- package/src/generator/PlatformCodegen.res +207 -0
- package/src/generator/PlatformCodegen.res.mjs +154 -0
- package/src/generator/PlatformGenerator.res +126 -0
- package/src/generator/PlatformGenerator.res.mjs +114 -0
- package/src/generator/PlatformManifests.res +203 -0
- package/src/generator/PlatformManifests.res.mjs +212 -0
- package/src/generator/PluginGenerator.res +57 -0
- package/src/generator/PluginGenerator.res.mjs +73 -0
- package/src/semantic/Bytes.res +54 -0
- package/src/semantic/Bytes.res.mjs +38 -0
- package/src/semantic/Capabilities.res +43 -0
- package/src/semantic/Capabilities.res.mjs +17 -0
- package/src/semantic/Color.res +51 -0
- package/src/semantic/Color.res.mjs +29 -0
- package/src/semantic/Currency.res +598 -0
- package/src/semantic/Currency.res.mjs +743 -0
- package/src/semantic/DateRange.res +148 -0
- package/src/semantic/DateRange.res.mjs +74 -0
- package/src/semantic/Duration.res +53 -0
- package/src/semantic/Duration.res.mjs +26 -0
- package/src/semantic/Email.res +51 -0
- package/src/semantic/Email.res.mjs +31 -0
- package/src/semantic/GeoPoint.res +226 -0
- package/src/semantic/GeoPoint.res.mjs +190 -0
- package/src/semantic/Geocoding.res +127 -0
- package/src/semantic/Geocoding.res.mjs +36 -0
- package/src/semantic/Money.res +196 -0
- package/src/semantic/Money.res.mjs +138 -0
- package/src/semantic/Offload.res +294 -0
- package/src/semantic/Offload.res.mjs +191 -0
- package/src/semantic/Percent.res +53 -0
- package/src/semantic/Percent.res.mjs +33 -0
- package/src/semantic/Phone.res +55 -0
- package/src/semantic/Phone.res.mjs +29 -0
- package/src/semantic/Semantic.res +162 -0
- package/src/semantic/Semantic.res.mjs +95 -0
- package/src/semantic/StorageRef.res +164 -0
- package/src/semantic/StorageRef.res.mjs +111 -0
- package/src/semantic/Url.res +66 -0
- package/src/semantic/Url.res.mjs +48 -0
- package/src/types/Authorization.res +23 -0
- package/src/types/Authorization.res.mjs +33 -0
- package/src/types/Behavior.res +86 -0
- package/src/types/Behavior.res.mjs +2 -0
- package/src/types/DateTime.res +29 -0
- package/src/types/DateTime.res.mjs +16 -0
- package/src/types/EventMapping.res +100 -0
- package/src/types/EventMapping.res.mjs +15 -0
- package/src/types/Handler.res +30 -0
- package/src/types/Handler.res.mjs +2 -0
- package/src/types/Id.res +75 -0
- package/src/types/Id.res.mjs +37 -0
- package/src/types/Identity.res +46 -0
- package/src/types/Identity.res.mjs +51 -0
- package/src/types/Message.res +326 -0
- package/src/types/Message.res.mjs +186 -0
- package/src/types/Projection.res +220 -0
- package/src/types/Projection.res.mjs +44 -0
- package/src/types/QueryEngine.res +123 -0
- package/src/types/QueryEngine.res.mjs +12 -0
- package/src/types/ReadConsistency.res +38 -0
- package/src/types/ReadConsistency.res.mjs +29 -0
- package/src/types/Schedule.res +65 -0
- package/src/types/Schedule.res.mjs +68 -0
- package/src/types/SideEffect.res +45 -0
- package/src/types/SideEffect.res.mjs +2 -0
- package/src/types/StoredEvent.res +46 -0
- package/src/types/StoredEvent.res.mjs +32 -0
- package/src/types/Visibility.res +24 -0
- package/src/types/Visibility.res.mjs +25 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Nodefs from "node:fs";
|
|
4
|
+
import * as Nodepath from "node:path";
|
|
5
|
+
import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
|
|
6
|
+
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
7
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
8
|
+
|
|
9
|
+
function nodeFileSystem_exists(prim) {
|
|
10
|
+
return Nodefs.existsSync(prim);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function nodeFileSystem_readJson(path) {
|
|
14
|
+
try {
|
|
15
|
+
return JSON.parse(Nodefs.readFileSync(path, "utf8"));
|
|
16
|
+
} catch (exn) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let nodeFileSystem = {
|
|
22
|
+
exists: nodeFileSystem_exists,
|
|
23
|
+
readJson: nodeFileSystem_readJson
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function describeVia(via) {
|
|
27
|
+
if (typeof via !== "object") {
|
|
28
|
+
return "its own src/";
|
|
29
|
+
} else if (via.TAG === "Generated") {
|
|
30
|
+
return `its \`generate\` script's ` + via._0;
|
|
31
|
+
} else {
|
|
32
|
+
return `dependency ` + via._0;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function asObject(json) {
|
|
37
|
+
return Stdlib_JSON.Decode.object(json);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function packageJsonAt(fs, dir) {
|
|
41
|
+
return Stdlib_Option.flatMap(fs.readJson(Nodepath.join(dir, "package.json")), asObject);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function scriptsOf(pkg) {
|
|
45
|
+
return Stdlib_Option.mapOr(Stdlib_Option.flatMap(pkg["scripts"], asObject), [], scripts => Stdlib_Array.filterMap(Object.values(scripts), Stdlib_JSON.Decode.string));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function generatedSrcDir(pkg) {
|
|
49
|
+
return Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_Option.flatMap(pkg["scripts"], asObject), scripts => scripts["generate"]), Stdlib_JSON.Decode.string), script => {
|
|
50
|
+
let tokens = script.split(" ").filter(t => t !== "");
|
|
51
|
+
if (tokens.length !== 4) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
let match = tokens[0];
|
|
55
|
+
if (match !== "generate-plugin") {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
let match$1 = tokens[1];
|
|
59
|
+
if (match$1 === "--aws") {
|
|
60
|
+
return tokens[3];
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function emitsCapabilities(pkg) {
|
|
66
|
+
return scriptsOf(pkg).some(script => script.includes("emit-capabilities"));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function dependencyNames(pkg) {
|
|
70
|
+
let seen = {};
|
|
71
|
+
return [
|
|
72
|
+
"dependencies",
|
|
73
|
+
"devDependencies"
|
|
74
|
+
].flatMap(field => Stdlib_Option.mapOr(Stdlib_Option.flatMap(pkg[field], asObject), [], prim => Object.keys(prim))).filter(name => {
|
|
75
|
+
let match = seen[name];
|
|
76
|
+
if (match !== undefined) {
|
|
77
|
+
return false;
|
|
78
|
+
} else {
|
|
79
|
+
seen[name] = true;
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function resolvePackageDir(fs, fromDir, name) {
|
|
86
|
+
let _dir = fromDir;
|
|
87
|
+
while (true) {
|
|
88
|
+
let dir = _dir;
|
|
89
|
+
let candidate = Nodepath.join(dir, "node_modules", name);
|
|
90
|
+
if (fs.exists(Nodepath.join(candidate, "package.json"))) {
|
|
91
|
+
return candidate;
|
|
92
|
+
}
|
|
93
|
+
let parent = Nodepath.dirname(dir);
|
|
94
|
+
if (parent === dir) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
_dir = parent;
|
|
98
|
+
continue;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function fromDependencies(fs, pluginDir, pkg) {
|
|
103
|
+
let found = [];
|
|
104
|
+
let unbuilt = {
|
|
105
|
+
contents: undefined
|
|
106
|
+
};
|
|
107
|
+
dependencyNames(pkg).forEach(name => {
|
|
108
|
+
let packageDir = resolvePackageDir(fs, pluginDir, name);
|
|
109
|
+
if (packageDir === undefined) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
let candidate = Nodepath.join(packageDir, "src", "capabilities.json");
|
|
113
|
+
if (fs.exists(candidate)) {
|
|
114
|
+
found.push({
|
|
115
|
+
path: candidate,
|
|
116
|
+
via: {
|
|
117
|
+
TAG: "Dependency",
|
|
118
|
+
_0: name
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (!Stdlib_Option.mapOr(packageJsonAt(fs, packageDir), false, emitsCapabilities)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
let match = unbuilt.contents;
|
|
127
|
+
if (match !== undefined) {
|
|
128
|
+
return;
|
|
129
|
+
} else {
|
|
130
|
+
unbuilt.contents = {
|
|
131
|
+
evidence: `dependency ` + name + ` emits a capability manifest`,
|
|
132
|
+
expected: candidate
|
|
133
|
+
};
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
let match = unbuilt.contents;
|
|
138
|
+
if (match !== undefined) {
|
|
139
|
+
return {
|
|
140
|
+
TAG: "Unbuilt",
|
|
141
|
+
_0: {
|
|
142
|
+
evidence: match.evidence,
|
|
143
|
+
expected: match.expected
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
} else if (found.length !== 0) {
|
|
147
|
+
return {
|
|
148
|
+
TAG: "Manifests",
|
|
149
|
+
_0: found
|
|
150
|
+
};
|
|
151
|
+
} else {
|
|
152
|
+
return "NotAPlugin";
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function resolve(fsOpt, pluginDir) {
|
|
157
|
+
let fs = fsOpt !== undefined ? fsOpt : nodeFileSystem;
|
|
158
|
+
let direct = Nodepath.join(pluginDir, "src", "capabilities.json");
|
|
159
|
+
if (fs.exists(direct)) {
|
|
160
|
+
return {
|
|
161
|
+
TAG: "Manifests",
|
|
162
|
+
_0: [{
|
|
163
|
+
path: direct,
|
|
164
|
+
via: "Composition"
|
|
165
|
+
}]
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
let pkg = packageJsonAt(fs, pluginDir);
|
|
169
|
+
if (pkg === undefined) {
|
|
170
|
+
return "NotAPlugin";
|
|
171
|
+
}
|
|
172
|
+
let srcDir = generatedSrcDir(pkg);
|
|
173
|
+
if (srcDir === undefined) {
|
|
174
|
+
return fromDependencies(fs, pluginDir, pkg);
|
|
175
|
+
}
|
|
176
|
+
let expected = Nodepath.resolve(pluginDir, srcDir, "capabilities.json");
|
|
177
|
+
if (fs.exists(expected)) {
|
|
178
|
+
return {
|
|
179
|
+
TAG: "Manifests",
|
|
180
|
+
_0: [{
|
|
181
|
+
path: expected,
|
|
182
|
+
via: {
|
|
183
|
+
TAG: "Generated",
|
|
184
|
+
_0: srcDir
|
|
185
|
+
}
|
|
186
|
+
}]
|
|
187
|
+
};
|
|
188
|
+
} else {
|
|
189
|
+
return {
|
|
190
|
+
TAG: "Unbuilt",
|
|
191
|
+
_0: {
|
|
192
|
+
evidence: `its \`generate\` script composes ` + srcDir,
|
|
193
|
+
expected: expected
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export {
|
|
200
|
+
nodeFileSystem,
|
|
201
|
+
describeVia,
|
|
202
|
+
asObject,
|
|
203
|
+
packageJsonAt,
|
|
204
|
+
scriptsOf,
|
|
205
|
+
generatedSrcDir,
|
|
206
|
+
emitsCapabilities,
|
|
207
|
+
dependencyNames,
|
|
208
|
+
resolvePackageDir,
|
|
209
|
+
fromDependencies,
|
|
210
|
+
resolve,
|
|
211
|
+
}
|
|
212
|
+
/* node:fs Not a pure module */
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Entry point for the plugin generator.
|
|
2
|
+
// Usage: generate-plugin <srcDir>
|
|
3
|
+
// generate-plugin --aws <Namespace> <srcDir>
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
let () = {
|
|
7
|
+
let argv2 = NodeProcess.argv->Array.get(2)->Option.getOr("")
|
|
8
|
+
let argv3 = NodeProcess.argv->Array.get(3)->Option.getOr("")
|
|
9
|
+
let argv4 = NodeProcess.argv->Array.get(4)->Option.getOr("")
|
|
10
|
+
|
|
11
|
+
let (variant, srcDirArg) = if argv2 === "--aws" {
|
|
12
|
+
if argv3 !== "" && argv4 !== "" {
|
|
13
|
+
(Config.Aws({compositionNamespace: argv3}), argv4)
|
|
14
|
+
} else {
|
|
15
|
+
Console.error("Usage: generate-plugin --aws <Namespace> <srcDir>")
|
|
16
|
+
(Config.Composition, "")
|
|
17
|
+
}
|
|
18
|
+
} else {
|
|
19
|
+
(Config.Composition, argv2)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if srcDirArg === "" {
|
|
23
|
+
if argv2 !== "--aws" {
|
|
24
|
+
Console.error("Usage: generate-plugin <srcDir>")
|
|
25
|
+
Console.error(" generate-plugin --aws <Namespace> <srcDir>")
|
|
26
|
+
}
|
|
27
|
+
// Exit non-zero on a usage error so `prebuild` (and CI) actually fail
|
|
28
|
+
// instead of continuing green with no Plugin.res generated.
|
|
29
|
+
NodeProcess.exit(1)
|
|
30
|
+
} else {
|
|
31
|
+
// Resolve to absolute path (handles relative paths and trailing slashes)
|
|
32
|
+
let srcDir = NodePath.resolve([srcDirArg])
|
|
33
|
+
|
|
34
|
+
let config = {...Config.read(~srcDir), variant}
|
|
35
|
+
let discovered = Discovery.scan(~srcDir, ~exclude=config.exclude)
|
|
36
|
+
let resolved = Pairing.resolve(discovered, ~srcDir)
|
|
37
|
+
let source = Codegen.render(~config, ~resolved, ~discovered)
|
|
38
|
+
|
|
39
|
+
let outputDir = switch variant {
|
|
40
|
+
| Config.Composition => srcDir
|
|
41
|
+
| Config.Aws(_) => NodePath.join([NodeProcess.cwd(), "src"])
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let pluginPath = NodePath.join([outputDir, "Plugin.res"])
|
|
45
|
+
NodeFs.writeFileSync(pluginPath, source)
|
|
46
|
+
Console.log("Generated: " ++ pluginPath)
|
|
47
|
+
|
|
48
|
+
switch variant {
|
|
49
|
+
| Config.Composition => ()
|
|
50
|
+
| Config.Aws(_) =>
|
|
51
|
+
let mainSource = Codegen.renderMain(~config)
|
|
52
|
+
let mainPath = NodePath.join([outputDir, "Main.res"])
|
|
53
|
+
NodeFs.writeFileSync(mainPath, mainSource)
|
|
54
|
+
Console.log("Generated: " ++ mainPath)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Nodefs from "node:fs";
|
|
4
|
+
import * as Nodepath from "node:path";
|
|
5
|
+
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
6
|
+
import * as Config$Reventless from "./Config.res.mjs";
|
|
7
|
+
import * as Codegen$Reventless from "./Codegen.res.mjs";
|
|
8
|
+
import * as Pairing$Reventless from "./Pairing.res.mjs";
|
|
9
|
+
import * as Discovery$Reventless from "./Discovery.res.mjs";
|
|
10
|
+
|
|
11
|
+
let argv2 = Stdlib_Option.getOr(process.argv[2], "");
|
|
12
|
+
|
|
13
|
+
let argv3 = Stdlib_Option.getOr(process.argv[3], "");
|
|
14
|
+
|
|
15
|
+
let argv4 = Stdlib_Option.getOr(process.argv[4], "");
|
|
16
|
+
|
|
17
|
+
let match = argv2 === "--aws" ? (
|
|
18
|
+
argv3 !== "" && argv4 !== "" ? [
|
|
19
|
+
{
|
|
20
|
+
TAG: "Aws",
|
|
21
|
+
compositionNamespace: argv3
|
|
22
|
+
},
|
|
23
|
+
argv4
|
|
24
|
+
] : (console.error("Usage: generate-plugin --aws <Namespace> <srcDir>"), [
|
|
25
|
+
"Composition",
|
|
26
|
+
""
|
|
27
|
+
])
|
|
28
|
+
) : [
|
|
29
|
+
"Composition",
|
|
30
|
+
argv2
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
let srcDirArg = match[1];
|
|
34
|
+
|
|
35
|
+
let variant = match[0];
|
|
36
|
+
|
|
37
|
+
if (srcDirArg === "") {
|
|
38
|
+
if (argv2 !== "--aws") {
|
|
39
|
+
console.error("Usage: generate-plugin <srcDir>");
|
|
40
|
+
console.error(" generate-plugin --aws <Namespace> <srcDir>");
|
|
41
|
+
}
|
|
42
|
+
process.exit(1);
|
|
43
|
+
} else {
|
|
44
|
+
let srcDir = Nodepath.resolve(srcDirArg);
|
|
45
|
+
let init = Config$Reventless.read(srcDir);
|
|
46
|
+
let config_name = init.name;
|
|
47
|
+
let config_heartbeatInterval = init.heartbeatInterval;
|
|
48
|
+
let config_exclude = init.exclude;
|
|
49
|
+
let config_componentRuntime = init.componentRuntime;
|
|
50
|
+
let config = {
|
|
51
|
+
name: config_name,
|
|
52
|
+
heartbeatInterval: config_heartbeatInterval,
|
|
53
|
+
exclude: config_exclude,
|
|
54
|
+
componentRuntime: config_componentRuntime,
|
|
55
|
+
variant: variant
|
|
56
|
+
};
|
|
57
|
+
let discovered = Discovery$Reventless.scan(srcDir, config_exclude);
|
|
58
|
+
let resolved = Pairing$Reventless.resolve(discovered, srcDir);
|
|
59
|
+
let source = Codegen$Reventless.render(config, resolved, discovered);
|
|
60
|
+
let outputDir;
|
|
61
|
+
outputDir = typeof variant !== "object" ? srcDir : Nodepath.join(process.cwd(), "src");
|
|
62
|
+
let pluginPath = Nodepath.join(outputDir, "Plugin.res");
|
|
63
|
+
Nodefs.writeFileSync(pluginPath, source, "utf8");
|
|
64
|
+
console.log("Generated: " + pluginPath);
|
|
65
|
+
if (typeof variant === "object") {
|
|
66
|
+
let mainSource = Codegen$Reventless.renderMain(config);
|
|
67
|
+
let mainPath = Nodepath.join(outputDir, "Main.res");
|
|
68
|
+
Nodefs.writeFileSync(mainPath, mainSource, "utf8");
|
|
69
|
+
console.log("Generated: " + mainPath);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* argv2 Not a pure module */
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Marks a numeric field as a count of bytes.
|
|
3
|
+
|
|
4
|
+
## Why `float` and not `int`
|
|
5
|
+
|
|
6
|
+
A byte count is a whole number and cannot be negative, so `int` is the type it
|
|
7
|
+
wants to be. It is the wrong one here anyway: ReScript's `int` is int32, and
|
|
8
|
+
sury enforces that, so an `int` byte count silently caps at 2,147,483,647 — just
|
|
9
|
+
under 2 GiB. A type whose stated job is file sizes cannot stop at 2 GB.
|
|
10
|
+
|
|
11
|
+
`float` is a JS number, exact for every integer up to 2^53 — nine petabytes,
|
|
12
|
+
which is enough. The discreteness `int` would have given for free is recovered
|
|
13
|
+
by checking it: the grammar below rejects a fractional byte count, so the type
|
|
14
|
+
still means what `int` meant, minus the ceiling.
|
|
15
|
+
|
|
16
|
+
The wire is unaffected either way — both are JSON numbers — so this is a source
|
|
17
|
+
choice, not a format one. A field genuinely bounded below 2 GiB can still be
|
|
18
|
+
declared `int` and left unmarked; this type is for the ones that are not.
|
|
19
|
+
|
|
20
|
+
## The grammar
|
|
21
|
+
|
|
22
|
+
A finite, whole number, zero or greater. Zero is a real byte count — an empty
|
|
23
|
+
object — so it is accepted.
|
|
24
|
+
|
|
25
|
+
@example
|
|
26
|
+
```rescript
|
|
27
|
+
@schema type state = {
|
|
28
|
+
documentId: string,
|
|
29
|
+
size: @s.matches(Reventless.Bytes.schema) float,
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/** The count's representation. Transparent `float`; see the note above on why
|
|
35
|
+
it is not `int`. */
|
|
36
|
+
type t = float
|
|
37
|
+
|
|
38
|
+
external unsafe: float => t = "%identity"
|
|
39
|
+
external toFloat: t => float = "%identity"
|
|
40
|
+
|
|
41
|
+
/** Validate a number as a byte count, saying why when it is not one. */
|
|
42
|
+
let fromFloat = (raw: float): result<t, string> =>
|
|
43
|
+
if !Float.isFinite(raw) {
|
|
44
|
+
Error(`a byte count must be a finite number, got ${Float.toString(raw)}`)
|
|
45
|
+
} else if raw < 0.0 {
|
|
46
|
+
Error(`a byte count cannot be negative, got ${Float.toString(raw)}`)
|
|
47
|
+
} else if Math.floor(raw) !== raw {
|
|
48
|
+
Error(`a byte count is a whole number of bytes, got ${Float.toString(raw)}`)
|
|
49
|
+
} else {
|
|
50
|
+
Ok(raw)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** The sury schema for a byte-count field. Use with `@s.matches(Reventless.Bytes.schema)`. */
|
|
54
|
+
let schema: S.t<t> = S.float->Semantic.refined(~id=Semantic.Id.bytes, ~check=fromFloat)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as S from "sury/src/S.res.mjs";
|
|
4
|
+
import * as Semantic$Reventless from "./Semantic.res.mjs";
|
|
5
|
+
|
|
6
|
+
function fromFloat(raw) {
|
|
7
|
+
if (isFinite(raw)) {
|
|
8
|
+
if (raw < 0.0) {
|
|
9
|
+
return {
|
|
10
|
+
TAG: "Error",
|
|
11
|
+
_0: `a byte count cannot be negative, got ` + raw.toString()
|
|
12
|
+
};
|
|
13
|
+
} else if (Math.floor(raw) !== raw) {
|
|
14
|
+
return {
|
|
15
|
+
TAG: "Error",
|
|
16
|
+
_0: `a byte count is a whole number of bytes, got ` + raw.toString()
|
|
17
|
+
};
|
|
18
|
+
} else {
|
|
19
|
+
return {
|
|
20
|
+
TAG: "Ok",
|
|
21
|
+
_0: raw
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
} else {
|
|
25
|
+
return {
|
|
26
|
+
TAG: "Error",
|
|
27
|
+
_0: `a byte count must be a finite number, got ` + raw.toString()
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let schema = Semantic$Reventless.refined(S.float, Semantic$Reventless.Id.bytes, fromFloat);
|
|
33
|
+
|
|
34
|
+
export {
|
|
35
|
+
fromFloat,
|
|
36
|
+
schema,
|
|
37
|
+
}
|
|
38
|
+
/* schema Not a pure module */
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
The platform capabilities a slice's `translate` is handed.
|
|
3
|
+
|
|
4
|
+
A plugin is provider-agnostic: it depends on `reventless-spec`, never on
|
|
5
|
+
`reventless-aws`, so it cannot name Amazon Location — and it should not want to.
|
|
6
|
+
What it can do is receive a function that geocodes, and let whoever assembled the
|
|
7
|
+
runtime decide what is on the other end. The same capability a client reaches
|
|
8
|
+
through a GraphQL field, plugin code reaches through here; the object store
|
|
9
|
+
already works this way, with `Upload_Presign` on one side and an injected
|
|
10
|
+
`Offload.resolve(~fetch)` on the other.
|
|
11
|
+
|
|
12
|
+
Injected rather than looked up, and required rather than optional, because the
|
|
13
|
+
alternative is a slot filled at cold start that nothing enforces: ES modules
|
|
14
|
+
evaluate imports before the importing module's body, so "the entry point runs
|
|
15
|
+
first" is an assumption a bundling change can quietly break. A missing argument
|
|
16
|
+
does not compile; an unfilled slot fails on the first real address, in
|
|
17
|
+
production.
|
|
18
|
+
|
|
19
|
+
**A record, not a widening argument list.** Adding a capability later changes
|
|
20
|
+
this type, which breaks the handful of places that *construct* it — the
|
|
21
|
+
platforms, which is exactly where a new capability has to be wired anyway — and
|
|
22
|
+
leaves every `translate` reading `capabilities.geocode` untouched.
|
|
23
|
+
*/
|
|
24
|
+
type t = {
|
|
25
|
+
/** Turn an address into ranked candidates. See `Geocoding.search`. */
|
|
26
|
+
geocode: Geocoding.search,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
The capability set of a platform that provisions nothing.
|
|
31
|
+
|
|
32
|
+
Every capability here answers `Unavailable`, which is a *modelled* outcome:
|
|
33
|
+
`translate` maps it to `Error`, the item is retried and the sweep surfaces it.
|
|
34
|
+
That is the behaviour wanted for a deployment that simply has no geocoder — the
|
|
35
|
+
work stays queued and visible rather than being written off as a verdict on the
|
|
36
|
+
address, which is what `NoMatch` would mean.
|
|
37
|
+
|
|
38
|
+
Named so that a platform passing it is making a statement rather than filling in
|
|
39
|
+
a blank.
|
|
40
|
+
*/
|
|
41
|
+
let none: t = {
|
|
42
|
+
geocode: async (~text as _) => Error(Unavailable("no geocoder is configured for this platform")),
|
|
43
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
let none = {
|
|
5
|
+
geocode: async param => ({
|
|
6
|
+
TAG: "Error",
|
|
7
|
+
_0: {
|
|
8
|
+
TAG: "Unavailable",
|
|
9
|
+
_0: "no geocoder is configured for this platform"
|
|
10
|
+
}
|
|
11
|
+
})
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
none,
|
|
16
|
+
}
|
|
17
|
+
/* No side effect */
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Marks a `string` field as a colour, written as a hex triplet.
|
|
3
|
+
|
|
4
|
+
## Why hex only
|
|
5
|
+
|
|
6
|
+
A field carrying this semantic is rendered as a swatch by setting the value as a
|
|
7
|
+
CSS `background`. CSS accepts far more than a colour there — `url(…)`, gradients,
|
|
8
|
+
`var(…)` — so "any CSS colour" would make a colour field a way to write arbitrary
|
|
9
|
+
CSS into a log that cannot be edited afterwards. Hex is the form that is a
|
|
10
|
+
colour and nothing else, and it is what a colour picker emits anyway.
|
|
11
|
+
|
|
12
|
+
Named colours (`rebeccapurple`) and functional forms (`rgb(…)`, `oklch(…)`) are
|
|
13
|
+
rejected for the same reason, not because they are worse notation.
|
|
14
|
+
|
|
15
|
+
## The grammar
|
|
16
|
+
|
|
17
|
+
`#` then 3, 4, 6 or 8 hex digits — the shorthand, the shorthand with alpha, the
|
|
18
|
+
full triplet, and the triplet with alpha. Case is not significant.
|
|
19
|
+
|
|
20
|
+
@example
|
|
21
|
+
```rescript
|
|
22
|
+
@schema type command =
|
|
23
|
+
| SetLabelColour({
|
|
24
|
+
labelId: @s.matches(DcbTag.string) string,
|
|
25
|
+
colour: @s.matches(Reventless.Color.schema) string,
|
|
26
|
+
})
|
|
27
|
+
```
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/** The colour's representation. Transparent `string`; see `Email.t`. */
|
|
31
|
+
type t = string
|
|
32
|
+
|
|
33
|
+
external unsafe: string => t = "%identity"
|
|
34
|
+
external toString: t => string = "%identity"
|
|
35
|
+
|
|
36
|
+
let hex = /^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/
|
|
37
|
+
|
|
38
|
+
/** Validate a raw string as a hex colour, saying why when it is not one. */
|
|
39
|
+
let fromString = (raw: string): result<t, string> =>
|
|
40
|
+
if hex->RegExp.test(raw) {
|
|
41
|
+
Ok(raw)
|
|
42
|
+
} else {
|
|
43
|
+
Error(
|
|
44
|
+
`expected a hex colour such as "#1e90ff" or "#1e90ffcc", got ${Semantic.showString(
|
|
45
|
+
raw,
|
|
46
|
+
)}. Named colours and rgb()/oklch() forms are not accepted.`,
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** The sury schema for a colour field. Use with `@s.matches(Reventless.Color.schema)`. */
|
|
51
|
+
let schema: S.t<t> = S.string->Semantic.refined(~id=Semantic.Id.color, ~check=fromString)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as S from "sury/src/S.res.mjs";
|
|
4
|
+
import * as Semantic$Reventless from "./Semantic.res.mjs";
|
|
5
|
+
|
|
6
|
+
let hex = /^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
|
|
7
|
+
|
|
8
|
+
function fromString(raw) {
|
|
9
|
+
if (hex.test(raw)) {
|
|
10
|
+
return {
|
|
11
|
+
TAG: "Ok",
|
|
12
|
+
_0: raw
|
|
13
|
+
};
|
|
14
|
+
} else {
|
|
15
|
+
return {
|
|
16
|
+
TAG: "Error",
|
|
17
|
+
_0: `expected a hex colour such as "#1e90ff" or "#1e90ffcc", got ` + Semantic$Reventless.showString(raw) + `. Named colours and rgb()/oklch() forms are not accepted.`
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let schema = Semantic$Reventless.refined(S.string, Semantic$Reventless.Id.color, fromString);
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
hex,
|
|
26
|
+
fromString,
|
|
27
|
+
schema,
|
|
28
|
+
}
|
|
29
|
+
/* schema Not a pure module */
|