@reventlessdev/reventless-spec 3.0.0-alpha.143 → 3.0.0-alpha.144

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.
@@ -62,77 +62,78 @@ let readPackageField = (packageJson: JSON.t, field: string, fallback: string) =>
62
62
  ->Option.flatMap(JSON.Decode.string)
63
63
  ->Option.getOr(fallback)
64
64
 
65
- let main = async () => {
66
- let argv = NodeProcess.argv->Array.slice(~start=2, ~end=NodeProcess.argv->Array.length)
67
- let flag = key =>
68
- switch argv->Array.indexOf("--" ++ key) {
69
- | -1 => None
70
- | i => argv->Array.get(i + 1)
65
+ type args = {traitPackage: string, out: string}
66
+
67
+ let parseArgs = (argv: array<string>): result<args, string> =>
68
+ CliArgs.parse(~strings=["out"], argv)
69
+ ->Result.flatMap(a => a->CliArgs.atMost(1))
70
+ ->Result.flatMap(a =>
71
+ switch (a->CliArgs.positionals->Array.get(0), a->CliArgs.string("out")) {
72
+ | (None | Some(""), _) => Error("<trait-package> is required.")
73
+ | (Some(_), None) => Error("--out is required.")
74
+ | (Some(traitPackage), Some(out)) => Ok({traitPackage, out})
71
75
  }
76
+ )
77
+
78
+ let cli: CliArgs.cli<args> = {bin: "trait-manifest", usage, parse: parseArgs}
79
+
80
+ let main = () =>
81
+ CliArgs.run(cli, async ({traitPackage, out}) => {
82
+ let base = moduleBase(traitPackage)
72
83
 
73
- switch (argv->Array.get(0), flag("out")) {
74
- | (None, _) | (Some(""), _) | (Some("--help"), _) | (Some("-h"), _) => {
75
- Console.log(usage)
76
- NodeProcess.exit(argv->Array.length == 0 ? 1 : 0)
84
+ let packageJson = switch resolveFrom(`${traitPackage}/package.json`) {
85
+ | None =>
86
+ fail(
87
+ `${traitPackage} is not installed here. A manifest is derived from the trait, so ` ++ `the trait has to be resolvable.`,
88
+ )
89
+ JSON.Encode.null
90
+ | Some(path) => NodeFs.readFileSync(path)->JSON.parseOrThrow
77
91
  }
78
- | (Some(_), None) => fail("--out is required.\n\n" ++ usage)
79
- | (Some(traitPackage), Some(out)) => {
80
- let base = moduleBase(traitPackage)
81
-
82
- let packageJson = switch resolveFrom(`${traitPackage}/package.json`) {
83
- | None =>
84
- fail(
85
- `${traitPackage} is not installed here. A manifest is derived from the trait, so ` ++ `the trait has to be resolvable.`,
86
- )
87
- JSON.Encode.null
88
- | Some(path) => NodeFs.readFileSync(path)->JSON.parseOrThrow
89
- }
90
-
91
- // The trait's entry module, for what it needs. Absent is refused rather
92
- // than defaulted to `[]`: "needs nothing" and "nobody said" are different
93
- // claims, and a listing that could not tell them apart would quietly
94
- // publish the second as the first.
95
- let traitModule: traitExports = switch resolveFrom(`${traitPackage}/src/${base}.res.mjs`) {
96
- | None =>
97
- fail(
98
- `${traitPackage} exports no ${base} module, so its capability needs cannot be read.\n` ++
99
- ` A trait states them as a value — an empty array if it brokers nothing — because ` ++ `an unstated need fails silently at run time.`,
100
- )
101
- %raw(`undefined`)
102
- | Some(path) => await dynImport(NodeUrl.pathToFileURL(path)["href"])
103
- }
104
-
105
- // The emitter is optional: a trait whose graft is all patches has nothing
106
- // to write, and says so here rather than by failing when someone tries.
107
- let scaffold: option<scaffoldExports> = switch resolveFrom(
108
- `${traitPackage}/src/${base}_Scaffold.res.mjs`,
109
- ) {
110
- | None => None
111
- | Some(path) => Some(await dynImport(NodeUrl.pathToFileURL(path)["href"]))
112
- }
113
-
114
- let manifest: TraitManifest.t = {
115
- trait: readPackageField(packageJson, "name", traitPackage),
116
- version: readPackageField(packageJson, "version", "0.0.0"),
117
- description: readPackageField(packageJson, "description", ""),
118
- license: readPackageField(packageJson, "license", ""),
119
- capabilities: traitModule.capabilityNeeds->Array.map(CapabilityNeed.toString),
120
- config: switch scaffold {
121
- | Some({configSchema}) => TraitManifest.configFieldsOf(configSchema)
122
- | None => []
123
- },
124
- scaffolded: scaffold->Option.isSome,
125
- }
126
-
127
- NodeFs.writeFileSync(out, manifest->TraitManifest.render)
128
- Console.log(
129
- `trait-manifest: ${manifest.trait}@${manifest.version} — ` ++
130
- `${manifest.capabilities->Array.length->Int.toString} capabilit(ies), ` ++
131
- `${manifest.config->Array.length->Int.toString} config field(s)`,
92
+
93
+ // The trait's entry module, for what it needs. Absent is refused rather
94
+ // than defaulted to `[]`: "needs nothing" and "nobody said" are different
95
+ // claims, and a listing that could not tell them apart would quietly
96
+ // publish the second as the first.
97
+ let traitModule: traitExports = switch resolveFrom(`${traitPackage}/src/${base}.res.mjs`) {
98
+ | None =>
99
+ fail(
100
+ `${traitPackage} exports no ${base} module, so its capability needs cannot be read.\n` ++
101
+ ` A trait states them as a value — an empty array if it brokers nothing — because ` ++ `an unstated need fails silently at run time.`,
132
102
  )
133
- Console.log(`Wrote: ${out}`)
103
+ %raw(`undefined`)
104
+ | Some(path) => await dynImport(NodeUrl.pathToFileURL(path)["href"])
105
+ }
106
+
107
+ // The emitter is optional: a trait whose graft is all patches has nothing
108
+ // to write, and says so here rather than by failing when someone tries.
109
+ let scaffold: option<scaffoldExports> = switch resolveFrom(
110
+ `${traitPackage}/src/${base}_Scaffold.res.mjs`,
111
+ ) {
112
+ | None => None
113
+ | Some(path) => Some(await dynImport(NodeUrl.pathToFileURL(path)["href"]))
114
+ }
115
+
116
+ let manifest: TraitManifest.t = {
117
+ trait: readPackageField(packageJson, "name", traitPackage),
118
+ version: readPackageField(packageJson, "version", "0.0.0"),
119
+ description: readPackageField(packageJson, "description", ""),
120
+ license: readPackageField(packageJson, "license", ""),
121
+ capabilities: traitModule.capabilityNeeds->Array.map(CapabilityNeed.toString),
122
+ config: switch scaffold {
123
+ | Some({configSchema}) => TraitManifest.configFieldsOf(configSchema)
124
+ | None => []
125
+ },
126
+ scaffolded: scaffold->Option.isSome,
134
127
  }
135
- }
136
- }
137
128
 
138
- main()->Promise.ignore
129
+ NodeFs.writeFileSync(out, manifest->TraitManifest.render)
130
+ Console.log(
131
+ `trait-manifest: ${manifest.trait}@${manifest.version} — ` ++
132
+ `${manifest.capabilities->Array.length->Int.toString} capabilit(ies), ` ++
133
+ `${manifest.config->Array.length->Int.toString} config field(s)`,
134
+ )
135
+ Console.log(`Wrote: ${out}`)
136
+ })
137
+
138
+ // No top-level call: `../../run-trait-manifest.mjs` invokes [main], so a test
139
+ // can import this module.
@@ -6,6 +6,8 @@ import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
6
6
  import * as Nodemodule from "node:module";
7
7
  import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
8
8
  import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
9
+ import * as Stdlib_Result from "@rescript/runtime/lib/es6/Stdlib_Result.js";
10
+ import * as CliArgs$Reventless from "../CliArgs.res.mjs";
9
11
  import * as TraitManifest$Reventless from "../components/TraitManifest.res.mjs";
10
12
  import * as CapabilityNeed$Reventless from "../semantic/CapabilityNeed.res.mjs";
11
13
 
@@ -39,60 +41,72 @@ function readPackageField(packageJson, field, fallback) {
39
41
  return Stdlib_Option.getOr(Stdlib_Option.flatMap(Stdlib_Option.flatMap(Stdlib_JSON.Decode.object(packageJson), o => o[field]), Stdlib_JSON.Decode.string), fallback);
40
42
  }
41
43
 
42
- async function main() {
43
- let argv = process.argv.slice(2, process.argv.length);
44
- let flag = key => {
45
- let i = argv.indexOf("--" + key);
46
- if (i !== -1) {
47
- return argv[i + 1 | 0];
48
- }
49
- };
50
- let match = argv[0];
51
- let match$1 = flag("out");
52
- if (match !== undefined) {
53
- switch (match) {
54
- case "" :
55
- case "--help" :
56
- case "-h" :
57
- break;
58
- default:
59
- if (match$1 === undefined) {
60
- return fail("--out is required.\n\n" + usage);
61
- }
62
- let base = moduleBase(match);
63
- let path = resolveFrom(match + `/package.json`);
64
- let packageJson = path !== undefined ? JSON.parse(Nodefs.readFileSync(path, "utf8")) : (fail(match + ` is not installed here. A manifest is derived from the trait, so the trait has to be resolvable.`), null);
65
- let path$1 = resolveFrom(match + `/src/` + base + `.res.mjs`);
66
- let traitModule = path$1 !== undefined ? await import(Nodeurl.pathToFileURL(path$1).href) : (fail(match + ` exports no ` + base + ` module, so its capability needs cannot be read.\n A trait states them as a value — an empty array if it brokers nothing — because an unstated need fails silently at run time.`), undefined);
67
- let path$2 = resolveFrom(match + `/src/` + base + `_Scaffold.res.mjs`);
68
- let scaffold = path$2 !== undefined ? await import(Nodeurl.pathToFileURL(path$2).href) : undefined;
69
- let manifest_trait = readPackageField(packageJson, "name", match);
70
- let manifest_version = readPackageField(packageJson, "version", "0.0.0");
71
- let manifest_description = readPackageField(packageJson, "description", "");
72
- let manifest_license = readPackageField(packageJson, "license", "");
73
- let manifest_capabilities = traitModule.capabilityNeeds.map(CapabilityNeed$Reventless.toString);
74
- let manifest_config = scaffold !== undefined ? TraitManifest$Reventless.configFieldsOf(scaffold.configSchema) : [];
75
- let manifest_scaffolded = Stdlib_Option.isSome(scaffold);
76
- let manifest = {
77
- trait: manifest_trait,
78
- version: manifest_version,
79
- description: manifest_description,
80
- license: manifest_license,
81
- capabilities: manifest_capabilities,
82
- config: manifest_config,
83
- scaffolded: manifest_scaffolded
44
+ function parseArgs(argv) {
45
+ return Stdlib_Result.flatMap(Stdlib_Result.flatMap(CliArgs$Reventless.parse(["out"], undefined, undefined, undefined, argv), a => CliArgs$Reventless.atMost(a, 1)), a => {
46
+ let match = CliArgs$Reventless.positionals(a)[0];
47
+ let match$1 = CliArgs$Reventless.string(a, "out");
48
+ if (match !== undefined && match !== "") {
49
+ if (match$1 !== undefined) {
50
+ return {
51
+ TAG: "Ok",
52
+ _0: {
53
+ traitPackage: match,
54
+ out: match$1
55
+ }
56
+ };
57
+ } else {
58
+ return {
59
+ TAG: "Error",
60
+ _0: "--out is required."
84
61
  };
85
- Nodefs.writeFileSync(match$1, TraitManifest$Reventless.render(manifest), "utf8");
86
- console.log(`trait-manifest: ` + manifest_trait + `@` + manifest_version + ` — ` + (manifest_capabilities.length.toString() + ` capabilit(ies), `) + (manifest_config.length.toString() + ` config field(s)`));
87
- console.log(`Wrote: ` + match$1);
88
- return;
62
+ }
63
+ } else {
64
+ return {
65
+ TAG: "Error",
66
+ _0: "<trait-package> is required."
67
+ };
89
68
  }
90
- }
91
- console.log(usage);
92
- process.exit(argv.length === 0 ? 1 : 0);
69
+ });
93
70
  }
94
71
 
95
- main();
72
+ let cli = {
73
+ bin: "trait-manifest",
74
+ usage: usage,
75
+ parse: parseArgs
76
+ };
77
+
78
+ function main() {
79
+ return CliArgs$Reventless.run(cli, undefined, undefined, async param => {
80
+ let out = param.out;
81
+ let traitPackage = param.traitPackage;
82
+ let base = moduleBase(traitPackage);
83
+ let path = resolveFrom(traitPackage + `/package.json`);
84
+ let packageJson = path !== undefined ? JSON.parse(Nodefs.readFileSync(path, "utf8")) : (fail(traitPackage + ` is not installed here. A manifest is derived from the trait, so the trait has to be resolvable.`), null);
85
+ let path$1 = resolveFrom(traitPackage + `/src/` + base + `.res.mjs`);
86
+ let traitModule = path$1 !== undefined ? await import(Nodeurl.pathToFileURL(path$1).href) : (fail(traitPackage + ` exports no ` + base + ` module, so its capability needs cannot be read.\n A trait states them as a value — an empty array if it brokers nothing — because an unstated need fails silently at run time.`), undefined);
87
+ let path$2 = resolveFrom(traitPackage + `/src/` + base + `_Scaffold.res.mjs`);
88
+ let scaffold = path$2 !== undefined ? await import(Nodeurl.pathToFileURL(path$2).href) : undefined;
89
+ let manifest_trait = readPackageField(packageJson, "name", traitPackage);
90
+ let manifest_version = readPackageField(packageJson, "version", "0.0.0");
91
+ let manifest_description = readPackageField(packageJson, "description", "");
92
+ let manifest_license = readPackageField(packageJson, "license", "");
93
+ let manifest_capabilities = traitModule.capabilityNeeds.map(CapabilityNeed$Reventless.toString);
94
+ let manifest_config = scaffold !== undefined ? TraitManifest$Reventless.configFieldsOf(scaffold.configSchema) : [];
95
+ let manifest_scaffolded = Stdlib_Option.isSome(scaffold);
96
+ let manifest = {
97
+ trait: manifest_trait,
98
+ version: manifest_version,
99
+ description: manifest_description,
100
+ license: manifest_license,
101
+ capabilities: manifest_capabilities,
102
+ config: manifest_config,
103
+ scaffolded: manifest_scaffolded
104
+ };
105
+ Nodefs.writeFileSync(out, TraitManifest$Reventless.render(manifest), "utf8");
106
+ console.log(`trait-manifest: ` + manifest_trait + `@` + manifest_version + ` — ` + (manifest_capabilities.length.toString() + ` capabilit(ies), `) + (manifest_config.length.toString() + ` config field(s)`));
107
+ console.log(`Wrote: ` + out);
108
+ });
109
+ }
96
110
 
97
111
  export {
98
112
  fail,
@@ -100,6 +114,8 @@ export {
100
114
  moduleBase,
101
115
  resolveFrom,
102
116
  readPackageField,
117
+ parseArgs,
118
+ cli,
103
119
  main,
104
120
  }
105
- /* Not a pure module */
121
+ /* node:fs Not a pure module */