|
| 1 | +import type * as Brand from "../Brand.js" |
1 | 2 | import * as Chunk from "../Chunk.js" |
2 | 3 | import type * as Config from "../Config.js" |
3 | 4 | import * as ConfigError from "../ConfigError.js" |
@@ -192,6 +193,33 @@ export const url = (name?: string): Config.Config<URL> => { |
192 | 193 | return name === undefined ? config : nested(config, name) |
193 | 194 | } |
194 | 195 |
|
| 196 | +/** @internal */ |
| 197 | +export const port = (name?: string): Config.Config<number> => { |
| 198 | + const config = primitive( |
| 199 | + "a network port property", |
| 200 | + (text) => { |
| 201 | + const result = Number(text) |
| 202 | + |
| 203 | + if ( |
| 204 | + Number.isNaN(result) || |
| 205 | + result.toString() !== text.toString() || |
| 206 | + !Number.isInteger(result) || |
| 207 | + result < 1 || |
| 208 | + result > 65535 |
| 209 | + ) { |
| 210 | + return Either.left( |
| 211 | + configError.InvalidData( |
| 212 | + [], |
| 213 | + `Expected a network port value but received ${text}` |
| 214 | + ) |
| 215 | + ) |
| 216 | + } |
| 217 | + return Either.right(result) |
| 218 | + } |
| 219 | + ) |
| 220 | + return name === undefined ? config : nested(config, name) |
| 221 | +} |
| 222 | + |
195 | 223 | /** @internal */ |
196 | 224 | export const array = <A>(config: Config.Config<A>, name?: string): Config.Config<Array<A>> => { |
197 | 225 | return pipe(chunk(config, name), map(Chunk.toArray)) |
@@ -444,6 +472,33 @@ export const redacted = <A>( |
444 | 472 | return map(config, redacted_.make) |
445 | 473 | } |
446 | 474 |
|
| 475 | +/** @internal */ |
| 476 | +export const branded: { |
| 477 | + <A, B extends Brand.Branded<A, any>>( |
| 478 | + constructor: Brand.Brand.Constructor<B> |
| 479 | + ): (config: Config.Config<A>) => Config.Config<B> |
| 480 | + <B extends Brand.Branded<string, any>>( |
| 481 | + name: string | undefined, |
| 482 | + constructor: Brand.Brand.Constructor<B> |
| 483 | + ): Config.Config<B> |
| 484 | + <A, B extends Brand.Branded<A, any>>( |
| 485 | + config: Config.Config<A>, |
| 486 | + constructor: Brand.Brand.Constructor<B> |
| 487 | + ): Config.Config<B> |
| 488 | +} = dual(2, <A, B extends Brand.Brand.Constructor<any>>( |
| 489 | + nameOrConfig: Config.Config<NoInfer<A>> | string | undefined, |
| 490 | + constructor: B |
| 491 | +) => { |
| 492 | + const config: Config.Config<string | A> = isConfig(nameOrConfig) ? nameOrConfig : string(nameOrConfig) |
| 493 | + |
| 494 | + return mapOrFail(config, (a) => |
| 495 | + constructor.either(a).pipe( |
| 496 | + Either.mapLeft((brandErrors) => |
| 497 | + configError.InvalidData([], brandErrors.map((brandError) => brandError.message).join("\n")) |
| 498 | + ) |
| 499 | + )) |
| 500 | +}) |
| 501 | + |
447 | 502 | /** @internal */ |
448 | 503 | export const hashSet = <A>(config: Config.Config<A>, name?: string): Config.Config<HashSet.HashSet<A>> => { |
449 | 504 | const newConfig = map(chunk(config), HashSet.fromIterable) |
|
0 commit comments