runtime-resolver 0.1.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/235.js +89 -0
- package/969.js +27407 -0
- package/LICENSE +21 -0
- package/README.md +119 -0
- package/bin/runtime-resolver.js +289 -0
- package/index.d.ts +430 -0
- package/index.js +20 -0
- package/package.json +66 -0
- package/tsdoc-metadata.json +11 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 C. Spencer Beggs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# runtime-resolver
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/runtime-resolver)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
Resolve semver-compatible versions of Node.js, Bun, and Deno runtimes. Fetches available versions from GitHub with automatic offline fallback via a build-time cache.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- Resolve matching versions for Node.js, Bun, and Deno with a single call
|
|
11
|
+
- Filter Node.js results by release phase (current, active-lts, maintenance-lts)
|
|
12
|
+
- Control version granularity with increment levels (latest, minor, patch) for all runtimes
|
|
13
|
+
- Resolve a single version from a semver range with `resolveVersion`
|
|
14
|
+
- Control data freshness with `freshness` option (`"auto"`, `"api"`, or `"cache"`)
|
|
15
|
+
- Track data provenance with the `source` field (`"api"` or `"cache"`)
|
|
16
|
+
- Input validation with typed `InvalidInputError` for all resolvers
|
|
17
|
+
- Offline fallback using bundled version data when GitHub is unreachable
|
|
18
|
+
- CLI with structured JSON output for CI/CD pipelines
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install runtime-resolver
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { resolveNode, resolveBun, resolveDeno } from "runtime-resolver";
|
|
30
|
+
|
|
31
|
+
const node = await resolveNode({ semverRange: ">=20" });
|
|
32
|
+
console.log(node.latest); // e.g. "22.14.0"
|
|
33
|
+
console.log(node.source); // "api" or "cache"
|
|
34
|
+
console.log(node.default); // latest LTS version
|
|
35
|
+
|
|
36
|
+
const bun = await resolveBun({ semverRange: ">=1.1", increments: "minor" });
|
|
37
|
+
const deno = await resolveDeno({ semverRange: ">=2", increments: "minor" });
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Set a `GITHUB_TOKEN` or `GITHUB_PERSONAL_ACCESS_TOKEN` environment variable
|
|
41
|
+
for authenticated requests. Without one, the resolver falls back to cached data.
|
|
42
|
+
|
|
43
|
+
### CLI
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx runtime-resolver --node ">=22" --bun "^1" --deno ">=2" --pretty
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Output is structured JSON with a `$schema` reference for editor auto-complete. Print the full schema with `--schema`:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npx runtime-resolver --schema
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
#### Useful `jq` recipes
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Get the latest resolved Node.js version
|
|
59
|
+
npx runtime-resolver --node ">=22" | jq -r '.results.node.latest'
|
|
60
|
+
|
|
61
|
+
# List all matching versions as plain lines
|
|
62
|
+
npx runtime-resolver --deno ">=2" | jq -r '.results.deno.versions[]'
|
|
63
|
+
|
|
64
|
+
# Exit non-zero when any runtime fails to resolve
|
|
65
|
+
npx runtime-resolver --node ">=22" --bun "^1" | jq -e '.ok'
|
|
66
|
+
|
|
67
|
+
# Extract only the LTS version for Node.js
|
|
68
|
+
npx runtime-resolver --node ">=20" --node-phases active-lts | jq -r '.results.node.lts'
|
|
69
|
+
|
|
70
|
+
# Build a comma-separated matrix for GitHub Actions
|
|
71
|
+
npx runtime-resolver --node ">=20" --increments minor \
|
|
72
|
+
| jq -r '[.results.node.versions[]] | join(",")'
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Effect API
|
|
76
|
+
|
|
77
|
+
Power users can compose resolvers with custom layers and typed error handling instead of the Promise wrappers.
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import { Effect, Layer } from "effect";
|
|
81
|
+
import {
|
|
82
|
+
NodeResolver,
|
|
83
|
+
NodeResolverLive,
|
|
84
|
+
GitHubClientLive,
|
|
85
|
+
GitHubTokenAuth,
|
|
86
|
+
VersionCacheLive,
|
|
87
|
+
} from "runtime-resolver";
|
|
88
|
+
|
|
89
|
+
const program = Effect.gen(function* () {
|
|
90
|
+
const resolver = yield* NodeResolver;
|
|
91
|
+
return yield* resolver.resolve({
|
|
92
|
+
semverRange: ">=22",
|
|
93
|
+
phases: ["active-lts"],
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const layer = NodeResolverLive.pipe(
|
|
98
|
+
Layer.provide(Layer.merge(
|
|
99
|
+
GitHubClientLive.pipe(Layer.provide(GitHubTokenAuth)),
|
|
100
|
+
VersionCacheLive,
|
|
101
|
+
)),
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
Effect.runPromise(program.pipe(Effect.provide(layer)));
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
All services (`NodeResolver`, `BunResolver`, `DenoResolver`, `GitHubClient`,
|
|
108
|
+
`VersionCache`), live layers, auth layers (`GitHubTokenAuth`, `GitHubAppAuth`,
|
|
109
|
+
`GitHubAutoAuth`), and typed errors (`AuthenticationError`, `NetworkError`,
|
|
110
|
+
`RateLimitError`, `VersionNotFoundError`, etc.) are exported from the package
|
|
111
|
+
root.
|
|
112
|
+
|
|
113
|
+
## Documentation
|
|
114
|
+
|
|
115
|
+
For configuration, API reference, and advanced usage, see [docs](./docs/).
|
|
116
|
+
|
|
117
|
+
## License
|
|
118
|
+
|
|
119
|
+
[MIT](./LICENSE)
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command, Options } from "@effect/cli";
|
|
3
|
+
import { NodeContext, NodeRuntime } from "@effect/platform-node";
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import { BunResolver, Console, NodeResolverLive, Layer, GitHubAppAuth, GitHubAutoAuth, BunResolverLive, DenoResolverLive, GitHubClientLive, Cause, Effect, GitHubTokenAuthFromToken, VersionCacheLive, Option, NodeResolver, DenoResolver } from "../969.js";
|
|
6
|
+
const GitHubLayer = GitHubClientLive.pipe(Layer.provide(GitHubAutoAuth));
|
|
7
|
+
const SharedLayer = Layer.merge(GitHubLayer, VersionCacheLive);
|
|
8
|
+
const NodeLayer = NodeResolverLive.pipe(Layer.provide(SharedLayer));
|
|
9
|
+
const BunLayer = BunResolverLive.pipe(Layer.provide(SharedLayer));
|
|
10
|
+
const DenoLayer = DenoResolverLive.pipe(Layer.provide(SharedLayer));
|
|
11
|
+
const SCHEMA_URL = "https://raw.githubusercontent.com/spencerbeggs/runtime-resolver/main/runtime-resolver.schema.json";
|
|
12
|
+
const nodeOption = Options.text("node").pipe(Options.optional);
|
|
13
|
+
const bunOption = Options.text("bun").pipe(Options.optional);
|
|
14
|
+
const denoOption = Options.text("deno").pipe(Options.optional);
|
|
15
|
+
const nodePhasesOption = Options.text("node-phases").pipe(Options.optional);
|
|
16
|
+
const incrementsOption = Options.text("increments").pipe(Options.optional);
|
|
17
|
+
const nodeDefaultOption = Options.text("node-default").pipe(Options.optional);
|
|
18
|
+
const bunDefaultOption = Options.text("bun-default").pipe(Options.optional);
|
|
19
|
+
const denoDefaultOption = Options.text("deno-default").pipe(Options.optional);
|
|
20
|
+
const freshnessOption = Options.text("freshness").pipe(Options.optional);
|
|
21
|
+
const nodeDateOption = Options.text("node-date").pipe(Options.optional);
|
|
22
|
+
const prettyOption = Options.boolean("pretty").pipe(Options.withDefault(false));
|
|
23
|
+
const schemaOption = Options.boolean("schema").pipe(Options.withDefault(false));
|
|
24
|
+
const tokenOption = Options.text("token").pipe(Options.optional);
|
|
25
|
+
const appIdOption = Options.text("app-id").pipe(Options.optional);
|
|
26
|
+
const appPrivateKeyOption = Options.text("app-private-key").pipe(Options.optional);
|
|
27
|
+
const appInstallationIdOption = Options.text("app-installation-id").pipe(Options.optional);
|
|
28
|
+
const VALID_PHASES = [
|
|
29
|
+
"current",
|
|
30
|
+
"active-lts",
|
|
31
|
+
"maintenance-lts",
|
|
32
|
+
"end-of-life"
|
|
33
|
+
];
|
|
34
|
+
const VALID_INCREMENTS = [
|
|
35
|
+
"latest",
|
|
36
|
+
"minor",
|
|
37
|
+
"patch"
|
|
38
|
+
];
|
|
39
|
+
const VALID_FRESHNESS = [
|
|
40
|
+
"auto",
|
|
41
|
+
"api",
|
|
42
|
+
"cache"
|
|
43
|
+
];
|
|
44
|
+
const validatePhases = (raw)=>{
|
|
45
|
+
const phases = raw.split(",").map((s)=>s.trim());
|
|
46
|
+
for (const p of phases)if (!VALID_PHASES.includes(p)) throw new Error(`Invalid phase: "${p}". Valid values: ${VALID_PHASES.join(", ")}`);
|
|
47
|
+
return phases;
|
|
48
|
+
};
|
|
49
|
+
const validateIncrements = (raw)=>{
|
|
50
|
+
if (!VALID_INCREMENTS.includes(raw)) throw new Error(`Invalid increments value: "${raw}". Valid values: ${VALID_INCREMENTS.join(", ")}`);
|
|
51
|
+
return raw;
|
|
52
|
+
};
|
|
53
|
+
const validateFreshness = (raw)=>{
|
|
54
|
+
if (!VALID_FRESHNESS.includes(raw)) throw new Error(`Invalid freshness value: "${raw}". Valid values: ${VALID_FRESHNESS.join(", ")}`);
|
|
55
|
+
return raw;
|
|
56
|
+
};
|
|
57
|
+
const serializeError = (error)=>{
|
|
58
|
+
if (error && "object" == typeof error && "_tag" in error && "message" in error) {
|
|
59
|
+
const { _tag, message, ...rest } = error;
|
|
60
|
+
return {
|
|
61
|
+
_tag,
|
|
62
|
+
message,
|
|
63
|
+
...rest
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
_tag: "UnknownError",
|
|
68
|
+
message: error instanceof Error ? error.message : String(error)
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
const toSuccess = (name, result)=>[
|
|
72
|
+
name,
|
|
73
|
+
{
|
|
74
|
+
ok: true,
|
|
75
|
+
source: result.source,
|
|
76
|
+
versions: [
|
|
77
|
+
...result.versions
|
|
78
|
+
],
|
|
79
|
+
latest: result.latest,
|
|
80
|
+
...void 0 !== result.lts ? {
|
|
81
|
+
lts: result.lts
|
|
82
|
+
} : {},
|
|
83
|
+
...void 0 !== result.default ? {
|
|
84
|
+
default: result.default
|
|
85
|
+
} : {}
|
|
86
|
+
}
|
|
87
|
+
];
|
|
88
|
+
const toError = (name, error)=>[
|
|
89
|
+
name,
|
|
90
|
+
{
|
|
91
|
+
ok: false,
|
|
92
|
+
error: serializeError(error)
|
|
93
|
+
}
|
|
94
|
+
];
|
|
95
|
+
const resolveNode = (semverRange, phases, increments, defaultVersion, date, freshness, authOverride)=>Effect.gen(function*() {
|
|
96
|
+
const resolver = yield* NodeResolver;
|
|
97
|
+
const result = yield* resolver.resolve({
|
|
98
|
+
semverRange,
|
|
99
|
+
...phases ? {
|
|
100
|
+
phases
|
|
101
|
+
} : {},
|
|
102
|
+
...increments ? {
|
|
103
|
+
increments
|
|
104
|
+
} : {},
|
|
105
|
+
...defaultVersion ? {
|
|
106
|
+
defaultVersion
|
|
107
|
+
} : {},
|
|
108
|
+
...date ? {
|
|
109
|
+
date
|
|
110
|
+
} : {},
|
|
111
|
+
...freshness ? {
|
|
112
|
+
freshness
|
|
113
|
+
} : {}
|
|
114
|
+
});
|
|
115
|
+
return toSuccess("node", result);
|
|
116
|
+
}).pipe(Effect.provide(authOverride ? NodeResolverLive.pipe(Layer.provide(Layer.merge(GitHubClientLive.pipe(Layer.provide(authOverride)), VersionCacheLive))) : NodeLayer), Effect.catchAll((error)=>Effect.succeed(toError("node", error))));
|
|
117
|
+
const resolveBun = (semverRange, increments, defaultVersion, freshness, authOverride)=>Effect.gen(function*() {
|
|
118
|
+
const resolver = yield* BunResolver;
|
|
119
|
+
const result = yield* resolver.resolve({
|
|
120
|
+
semverRange,
|
|
121
|
+
...increments ? {
|
|
122
|
+
increments
|
|
123
|
+
} : {},
|
|
124
|
+
...defaultVersion ? {
|
|
125
|
+
defaultVersion
|
|
126
|
+
} : {},
|
|
127
|
+
...freshness ? {
|
|
128
|
+
freshness
|
|
129
|
+
} : {}
|
|
130
|
+
});
|
|
131
|
+
return toSuccess("bun", result);
|
|
132
|
+
}).pipe(Effect.provide(authOverride ? BunResolverLive.pipe(Layer.provide(Layer.merge(GitHubClientLive.pipe(Layer.provide(authOverride)), VersionCacheLive))) : BunLayer), Effect.catchAll((error)=>Effect.succeed(toError("bun", error))));
|
|
133
|
+
const resolveDeno = (semverRange, increments, defaultVersion, freshness, authOverride)=>Effect.gen(function*() {
|
|
134
|
+
const resolver = yield* DenoResolver;
|
|
135
|
+
const result = yield* resolver.resolve({
|
|
136
|
+
semverRange,
|
|
137
|
+
...increments ? {
|
|
138
|
+
increments
|
|
139
|
+
} : {},
|
|
140
|
+
...defaultVersion ? {
|
|
141
|
+
defaultVersion
|
|
142
|
+
} : {},
|
|
143
|
+
...freshness ? {
|
|
144
|
+
freshness
|
|
145
|
+
} : {}
|
|
146
|
+
});
|
|
147
|
+
return toSuccess("deno", result);
|
|
148
|
+
}).pipe(Effect.provide(authOverride ? DenoResolverLive.pipe(Layer.provide(Layer.merge(GitHubClientLive.pipe(Layer.provide(authOverride)), VersionCacheLive))) : DenoLayer), Effect.catchAll((error)=>Effect.succeed(toError("deno", error))));
|
|
149
|
+
const formatResponse = (ok, results, pretty)=>{
|
|
150
|
+
const response = {
|
|
151
|
+
$schema: SCHEMA_URL,
|
|
152
|
+
ok,
|
|
153
|
+
results
|
|
154
|
+
};
|
|
155
|
+
return JSON.stringify(response, null, pretty ? 2 : void 0);
|
|
156
|
+
};
|
|
157
|
+
const resolveHandler = (args)=>Effect.gen(function*() {
|
|
158
|
+
if (args.schema) {
|
|
159
|
+
const resolveFlags = [
|
|
160
|
+
args.node,
|
|
161
|
+
args.bun,
|
|
162
|
+
args.deno,
|
|
163
|
+
args.nodePhases,
|
|
164
|
+
args.increments,
|
|
165
|
+
args.freshness,
|
|
166
|
+
args.nodeDefault,
|
|
167
|
+
args.bunDefault,
|
|
168
|
+
args.denoDefault,
|
|
169
|
+
args.nodeDate,
|
|
170
|
+
args.token,
|
|
171
|
+
args.appId,
|
|
172
|
+
args.appPrivateKey,
|
|
173
|
+
args.appInstallationId
|
|
174
|
+
];
|
|
175
|
+
const hasResolveFlags = resolveFlags.some((f)=>Option.isSome(f));
|
|
176
|
+
if (hasResolveFlags) return void (yield* Console.error("Error: --schema cannot be combined with resolve flags (--node, --bun, --deno, etc.)"));
|
|
177
|
+
const { cliJsonSchema } = yield* Effect.promise(()=>import("../235.js").then((mod)=>({
|
|
178
|
+
cliJsonSchema: mod.cliJsonSchema
|
|
179
|
+
})));
|
|
180
|
+
yield* Console.log(JSON.stringify(cliJsonSchema, null, 2));
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const hasToken = Option.isSome(args.token);
|
|
184
|
+
const hasAppId = Option.isSome(args.appId);
|
|
185
|
+
const hasAppPrivateKey = Option.isSome(args.appPrivateKey);
|
|
186
|
+
const hasAppInstallationId = Option.isSome(args.appInstallationId);
|
|
187
|
+
if (hasToken && (hasAppId || hasAppPrivateKey)) return void (yield* Console.error("Error: --token and --app-id/--app-private-key are mutually exclusive"));
|
|
188
|
+
if (hasAppId !== hasAppPrivateKey) return void (yield* Console.error("Error: --app-id and --app-private-key must both be provided"));
|
|
189
|
+
if (hasAppInstallationId && !hasAppId) return void (yield* Console.error("Error: --app-installation-id requires --app-id and --app-private-key"));
|
|
190
|
+
let resolvedPrivateKey;
|
|
191
|
+
if (hasAppPrivateKey) {
|
|
192
|
+
const keyValue = args.appPrivateKey.value;
|
|
193
|
+
if (keyValue.startsWith("@")) {
|
|
194
|
+
const filePath = keyValue.slice(1);
|
|
195
|
+
try {
|
|
196
|
+
resolvedPrivateKey = readFileSync(filePath, "utf-8");
|
|
197
|
+
} catch {
|
|
198
|
+
yield* Console.error(`Error: Cannot read private key file: ${filePath}`);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
} else resolvedPrivateKey = keyValue;
|
|
202
|
+
}
|
|
203
|
+
let authLayerOverride;
|
|
204
|
+
if (hasToken) authLayerOverride = GitHubTokenAuthFromToken(args.token.value);
|
|
205
|
+
else if (hasAppId && resolvedPrivateKey) authLayerOverride = GitHubAppAuth({
|
|
206
|
+
appId: args.appId.value,
|
|
207
|
+
privateKey: resolvedPrivateKey,
|
|
208
|
+
...hasAppInstallationId ? {
|
|
209
|
+
installationId: Number(args.appInstallationId.value)
|
|
210
|
+
} : {}
|
|
211
|
+
});
|
|
212
|
+
const hasNode = Option.isSome(args.node);
|
|
213
|
+
const hasBun = Option.isSome(args.bun);
|
|
214
|
+
const hasDeno = Option.isSome(args.deno);
|
|
215
|
+
if (!hasNode && !hasBun && !hasDeno) return void (yield* Console.error("No runtime specified. Use --node, --bun, or --deno to resolve versions.\nRun with --help for usage information."));
|
|
216
|
+
let validatedPhases;
|
|
217
|
+
if (Option.isSome(args.nodePhases)) try {
|
|
218
|
+
validatedPhases = validatePhases(args.nodePhases.value);
|
|
219
|
+
} catch (e) {
|
|
220
|
+
yield* Console.error(e.message);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
let validatedIncrements;
|
|
224
|
+
if (Option.isSome(args.increments)) try {
|
|
225
|
+
validatedIncrements = validateIncrements(args.increments.value);
|
|
226
|
+
} catch (e) {
|
|
227
|
+
yield* Console.error(e.message);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
let validatedFreshness;
|
|
231
|
+
if (Option.isSome(args.freshness)) try {
|
|
232
|
+
validatedFreshness = validateFreshness(args.freshness.value);
|
|
233
|
+
} catch (e) {
|
|
234
|
+
yield* Console.error(e.message);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
let nodeDate;
|
|
238
|
+
if (Option.isSome(args.nodeDate)) {
|
|
239
|
+
nodeDate = new Date(args.nodeDate.value);
|
|
240
|
+
if (Number.isNaN(nodeDate.getTime())) return void (yield* Console.error(`Invalid date: "${args.nodeDate.value}". Use ISO 8601 format (e.g. 2024-01-15).`));
|
|
241
|
+
}
|
|
242
|
+
const tasks = [];
|
|
243
|
+
if (hasNode) {
|
|
244
|
+
const nodeDefaultVersion = Option.isSome(args.nodeDefault) ? args.nodeDefault.value : void 0;
|
|
245
|
+
tasks.push(resolveNode(args.node.value, validatedPhases, validatedIncrements, nodeDefaultVersion, nodeDate, validatedFreshness, authLayerOverride));
|
|
246
|
+
}
|
|
247
|
+
if (hasBun) {
|
|
248
|
+
const bunDefaultVersion = Option.isSome(args.bunDefault) ? args.bunDefault.value : void 0;
|
|
249
|
+
tasks.push(resolveBun(args.bun.value, validatedIncrements, bunDefaultVersion, validatedFreshness, authLayerOverride));
|
|
250
|
+
}
|
|
251
|
+
if (hasDeno) {
|
|
252
|
+
const denoDefaultVersion = Option.isSome(args.denoDefault) ? args.denoDefault.value : void 0;
|
|
253
|
+
tasks.push(resolveDeno(args.deno.value, validatedIncrements, denoDefaultVersion, validatedFreshness, authLayerOverride));
|
|
254
|
+
}
|
|
255
|
+
const entries = yield* Effect.all(tasks, {
|
|
256
|
+
concurrency: "unbounded"
|
|
257
|
+
});
|
|
258
|
+
const results = Object.fromEntries(entries);
|
|
259
|
+
const hasError = Object.values(results).some((r)=>!r.ok);
|
|
260
|
+
yield* Console.log(formatResponse(!hasError, results, args.pretty));
|
|
261
|
+
});
|
|
262
|
+
const rootCommand = Command.make("runtime-resolver", {
|
|
263
|
+
node: nodeOption,
|
|
264
|
+
bun: bunOption,
|
|
265
|
+
deno: denoOption,
|
|
266
|
+
nodePhases: nodePhasesOption,
|
|
267
|
+
increments: incrementsOption,
|
|
268
|
+
freshness: freshnessOption,
|
|
269
|
+
nodeDefault: nodeDefaultOption,
|
|
270
|
+
bunDefault: bunDefaultOption,
|
|
271
|
+
denoDefault: denoDefaultOption,
|
|
272
|
+
nodeDate: nodeDateOption,
|
|
273
|
+
pretty: prettyOption,
|
|
274
|
+
schema: schemaOption,
|
|
275
|
+
token: tokenOption,
|
|
276
|
+
appId: appIdOption,
|
|
277
|
+
appPrivateKey: appPrivateKeyOption,
|
|
278
|
+
appInstallationId: appInstallationIdOption
|
|
279
|
+
}, resolveHandler);
|
|
280
|
+
const cli = Command.run(rootCommand, {
|
|
281
|
+
name: "runtime-resolver",
|
|
282
|
+
version: "0.1.0"
|
|
283
|
+
});
|
|
284
|
+
const main = Effect.suspend(()=>cli(process.argv)).pipe(Effect.provide(NodeContext.layer), Effect.catchAllCause((cause)=>{
|
|
285
|
+
const defects = Cause.defects(cause);
|
|
286
|
+
if (defects.length > 0) return Console.error(Cause.pretty(cause)).pipe(Effect.andThen(Effect.failCause(cause)));
|
|
287
|
+
return Effect.failCause(cause);
|
|
288
|
+
}));
|
|
289
|
+
NodeRuntime.runMain(main);
|