effect 2.0.0-next.60 → 2.0.0-next.62

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.
Files changed (78) hide show
  1. package/dist/cjs/BigDecimal.js +19 -5
  2. package/dist/cjs/BigDecimal.js.map +1 -1
  3. package/dist/cjs/ConfigProvider.js +8 -1
  4. package/dist/cjs/ConfigProvider.js.map +1 -1
  5. package/dist/cjs/Effect.js +7 -2
  6. package/dist/cjs/Effect.js.map +1 -1
  7. package/dist/cjs/Layer.js +8 -1
  8. package/dist/cjs/Layer.js.map +1 -1
  9. package/dist/cjs/ReadonlyRecord.js +28 -1
  10. package/dist/cjs/ReadonlyRecord.js.map +1 -1
  11. package/dist/cjs/internal/configProvider.js +103 -32
  12. package/dist/cjs/internal/configProvider.js.map +1 -1
  13. package/dist/cjs/internal/core-effect.js +47 -38
  14. package/dist/cjs/internal/core-effect.js.map +1 -1
  15. package/dist/cjs/internal/effect/circular.js +2 -3
  16. package/dist/cjs/internal/effect/circular.js.map +1 -1
  17. package/dist/cjs/internal/fiberRuntime.js +4 -4
  18. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  19. package/dist/cjs/internal/layer.js +3 -1
  20. package/dist/cjs/internal/layer.js.map +1 -1
  21. package/dist/cjs/internal/matcher.js +13 -16
  22. package/dist/cjs/internal/matcher.js.map +1 -1
  23. package/dist/cjs/internal/metric.js +2 -2
  24. package/dist/cjs/internal/metric.js.map +1 -1
  25. package/dist/cjs/internal/version.js +1 -1
  26. package/dist/dts/BigDecimal.d.ts +2 -2
  27. package/dist/dts/BigDecimal.d.ts.map +1 -1
  28. package/dist/dts/ConfigProvider.d.ts +28 -0
  29. package/dist/dts/ConfigProvider.d.ts.map +1 -1
  30. package/dist/dts/Effect.d.ts +12 -7
  31. package/dist/dts/Effect.d.ts.map +1 -1
  32. package/dist/dts/Layer.d.ts +7 -0
  33. package/dist/dts/Layer.d.ts.map +1 -1
  34. package/dist/dts/Match.d.ts +15 -27
  35. package/dist/dts/Match.d.ts.map +1 -1
  36. package/dist/dts/ReadonlyRecord.d.ts +26 -0
  37. package/dist/dts/ReadonlyRecord.d.ts.map +1 -1
  38. package/dist/dts/internal/version.d.ts +1 -1
  39. package/dist/esm/BigDecimal.js +17 -4
  40. package/dist/esm/BigDecimal.js.map +1 -1
  41. package/dist/esm/ConfigProvider.js +7 -0
  42. package/dist/esm/ConfigProvider.js.map +1 -1
  43. package/dist/esm/Effect.js +5 -0
  44. package/dist/esm/Effect.js.map +1 -1
  45. package/dist/esm/Layer.js +7 -0
  46. package/dist/esm/Layer.js.map +1 -1
  47. package/dist/esm/ReadonlyRecord.js +26 -0
  48. package/dist/esm/ReadonlyRecord.js.map +1 -1
  49. package/dist/esm/internal/configProvider.js +101 -31
  50. package/dist/esm/internal/configProvider.js.map +1 -1
  51. package/dist/esm/internal/core-effect.js +43 -35
  52. package/dist/esm/internal/core-effect.js.map +1 -1
  53. package/dist/esm/internal/effect/circular.js +2 -3
  54. package/dist/esm/internal/effect/circular.js.map +1 -1
  55. package/dist/esm/internal/fiberRuntime.js +4 -4
  56. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  57. package/dist/esm/internal/layer.js +2 -0
  58. package/dist/esm/internal/layer.js.map +1 -1
  59. package/dist/esm/internal/matcher.js +13 -16
  60. package/dist/esm/internal/matcher.js.map +1 -1
  61. package/dist/esm/internal/metric.js +2 -2
  62. package/dist/esm/internal/metric.js.map +1 -1
  63. package/dist/esm/internal/version.js +1 -1
  64. package/package.json +1 -1
  65. package/src/BigDecimal.ts +19 -4
  66. package/src/ConfigProvider.ts +32 -0
  67. package/src/Effect.ts +18 -7
  68. package/src/Layer.ts +8 -0
  69. package/src/Match.ts +37 -75
  70. package/src/ReadonlyRecord.ts +28 -0
  71. package/src/internal/configProvider.ts +133 -33
  72. package/src/internal/core-effect.ts +74 -72
  73. package/src/internal/effect/circular.ts +7 -5
  74. package/src/internal/fiberRuntime.ts +4 -4
  75. package/src/internal/layer.ts +3 -0
  76. package/src/internal/matcher.ts +16 -16
  77. package/src/internal/metric.ts +2 -2
  78. package/src/internal/version.ts +1 -1
package/src/Match.ts CHANGED
@@ -613,27 +613,27 @@ export declare namespace Types {
613
613
  type SafeRefinementP<A> = A extends never ? never
614
614
  : A extends SafeRefinement<infer S, infer _> ? S
615
615
  : A extends Function ? A
616
- : A extends Record<string, any> ? DrainOuterGeneric<{ [K in keyof A]: SafeRefinementP<A[K]> }>
616
+ : A extends Record<string, any> ? { [K in keyof A]: SafeRefinementP<A[K]> }
617
617
  : A
618
618
 
619
619
  type SafeRefinementR<A> = A extends never ? never
620
620
  : A extends SafeRefinement<infer _, infer R> ? R
621
621
  : A extends Function ? A
622
- : A extends Record<string, any> ? DrainOuterGeneric<{ [K in keyof A]: SafeRefinementR<A[K]> }>
622
+ : A extends Record<string, any> ? { [K in keyof A]: SafeRefinementR<A[K]> }
623
623
  : A
624
624
 
625
625
  type ResolvePred<A> = A extends never ? never
626
626
  : A extends Predicate.Refinement<any, infer P> ? P
627
627
  : A extends Predicate.Predicate<infer P> ? P
628
628
  : A extends SafeRefinement<any> ? A
629
- : A extends Record<string, any> ? DrainOuterGeneric<{ [K in keyof A]: ResolvePred<A[K]> }>
629
+ : A extends Record<string, any> ? { [K in keyof A]: ResolvePred<A[K]> }
630
630
  : A
631
631
 
632
632
  type ToSafeRefinement<A> = A extends never ? never
633
633
  : A extends Predicate.Refinement<any, infer P> ? SafeRefinement<P, P>
634
634
  : A extends Predicate.Predicate<infer P> ? SafeRefinement<P, never>
635
635
  : A extends SafeRefinement<any> ? A
636
- : A extends Record<string, any> ? DrainOuterGeneric<{ [K in keyof A]: ToSafeRefinement<A[K]> }>
636
+ : A extends Record<string, any> ? { [K in keyof A]: ToSafeRefinement<A[K]> }
637
637
  : NonLiteralsTo<A, never>
638
638
 
639
639
  type NonLiteralsTo<A, T> = [A] extends [string | number | boolean | bigint] ? [string] extends [A] ? T
@@ -643,16 +643,12 @@ export declare namespace Types {
643
643
  : A
644
644
  : A
645
645
 
646
- type DrainOuterGeneric<T> = [T] extends [unknown] ? T : never
647
-
648
646
  /**
649
647
  * @since 1.0.0
650
648
  */
651
649
  export type PatternBase<A> = A extends ReadonlyArray<infer _T> ? ReadonlyArray<any> | PatternPrimitive<A>
652
650
  : A extends Record<string, any> ? Partial<
653
- DrainOuterGeneric<
654
- { [K in keyof A]: PatternPrimitive<A[K] & {}> | PatternBase<A[K] & {}> }
655
- >
651
+ { [K in keyof A]: PatternPrimitive<A[K] & {}> | PatternBase<A[K] & {}> }
656
652
  >
657
653
  : never
658
654
 
@@ -718,33 +714,6 @@ export declare namespace Types {
718
714
  export type ExtractMatch<I, P> = [ExtractAndNarrow<I, P>] extends [infer EI] ? EI
719
715
  : never
720
716
 
721
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
722
- type IntersectOf<U extends unknown> = (
723
- U extends unknown ? (k: U) => void : never
724
- ) extends (k: infer I) => void ? I
725
- : never
726
-
727
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
728
- type Last<U extends any> = IntersectOf<
729
- U extends unknown ? (x: U) => void : never
730
- > extends (x: infer P) => void ? P
731
- : never
732
-
733
- type _ListOf<U, LN extends Array<any> = [], LastU = Last<U>> = {
734
- 0: _ListOf<Exclude<U, LastU>, [LastU, ...LN]>
735
- 1: LN
736
- }[[U] extends [never] ? 1 : 0]
737
-
738
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
739
- type ListOf<U extends any> = _ListOf<U> extends infer X ? X extends Array<any> ? X
740
- : []
741
- : never
742
-
743
- type IsUnion<T, U extends T = T> = (
744
- T extends any ? (U extends T ? false : true) : never
745
- ) extends false ? false
746
- : true
747
-
748
717
  type Replace<A, B> = A extends Function ? A
749
718
  : A extends Record<string | number, any> ? { [K in keyof A]: K extends keyof B ? Replace<A[K], B[K]> : A[K] }
750
719
  : [B] extends [A] ? B
@@ -767,46 +736,39 @@ export declare namespace Types {
767
736
 
768
737
  type Simplify<A> = { [K in keyof A]: A[K] } & {}
769
738
 
770
- type ExtractAndNarrow<I, P> =
739
+ type ExtractAndNarrow<Input, P> =
771
740
  // unknown is a wildcard pattern
772
- unknown extends P ? I
773
- : IsUnion<I> extends true ? ListOf<I> extends infer L ? L extends Array<any> ? Exclude<
774
- DrainOuterGeneric<
775
- { [K in keyof L]: ExtractAndNarrow<L[K], P> }
776
- >[number],
777
- Fail
778
- >
779
- : never
780
- : never
781
- : I extends ReadonlyArray<any> ? P extends ReadonlyArray<any> ? DrainOuterGeneric<
782
- {
783
- readonly [K in keyof I]: K extends keyof P ? ExtractAndNarrow<I[K], P[K]>
784
- : I[K]
785
- }
786
- > extends infer R ? Fail extends R[keyof R] ? never
787
- : R
788
- : never
789
- : never
790
- : IsPlainObject<I> extends true ? string extends keyof I ? I extends P ? I
791
- : never
792
- : symbol extends keyof I ? I extends P ? I
793
- : never
794
- : Simplify<
795
- DrainOuterGeneric<
796
- {
797
- [RK in Extract<keyof I, keyof P>]-?: ExtractAndNarrow<I[RK], P[RK]>
798
- }
799
- > & Omit<I, keyof P>
800
- > extends infer R ? [keyof P] extends [keyof RemoveFails<R>] ? R
801
- : never
802
- : never
803
- : MaybeReplace<I, P> extends infer R ? [I] extends [R] ? I
804
- : R
805
- : never
806
-
807
- type RemoveFails<A> = {
808
- [K in keyof A & {}]: A[K] extends Fail ? never : K
809
- }[keyof A] extends infer K ? [K] extends [keyof A] ? { [RK in K]: A[RK] }
741
+ unknown extends P ? Input
742
+ : Input extends infer I ? Exclude<
743
+ I extends ReadonlyArray<any> ? P extends ReadonlyArray<any> ? {
744
+ readonly [K in keyof I]: K extends keyof P ? ExtractAndNarrow<I[K], P[K]>
745
+ : I[K]
746
+ } extends infer R ? Fail extends R[keyof R] ? never
747
+ : R
748
+ : never
749
+ : never
750
+ : IsPlainObject<I> extends true ? string extends keyof I ? I extends P ? I
751
+ : never
752
+ : symbol extends keyof I ? I extends P ? I
753
+ : never
754
+ : Simplify<
755
+ & { [RK in Extract<keyof I, keyof P>]-?: ExtractAndNarrow<I[RK], P[RK]> }
756
+ & Omit<I, keyof P>
757
+ > extends infer R ? [keyof P] extends [keyof RemoveFails<R>] ? R
758
+ : never
759
+ : never
760
+ : MaybeReplace<I, P> extends infer R ? [I] extends [R] ? I
761
+ : R
762
+ : never,
763
+ Fail
764
+ > :
765
+ never
766
+
767
+ type RemoveFails<A> = NonFailKeys<A> extends infer K ? [K] extends [keyof A] ? { [RK in K]: A[RK] }
810
768
  : {}
811
769
  : {}
770
+
771
+ type NonFailKeys<A> = keyof A & {} extends infer K ? K extends keyof A ? A[K] extends Fail ? never : K
772
+ : never :
773
+ never
812
774
  }
@@ -117,6 +117,34 @@ export const fromIterable: <V>(entries: Iterable<readonly [string, V]>) => Recor
117
117
  identity
118
118
  )
119
119
 
120
+ /**
121
+ * Creates a new record from an iterable, utilizing the provided function to determine the key for each element.
122
+ *
123
+ * @param items - An iterable containing elements.
124
+ * @param f - A function that extracts the key for each element.
125
+ *
126
+ * @example
127
+ * import { fromIterableBy } from "effect/ReadonlyRecord"
128
+ *
129
+ * const users = [
130
+ * { id: "2", name: "name2" },
131
+ * { id: "1", name: "name1" }
132
+ * ]
133
+ *
134
+ * assert.deepStrictEqual(
135
+ * fromIterableBy(users, user => user.id),
136
+ * {
137
+ * "2": { id: "2", name: "name2" },
138
+ * "1": { id: "1", name: "name1" }
139
+ * }
140
+ * )
141
+ *
142
+ * @category constructors
143
+ * @since 2.0.0
144
+ */
145
+ export const fromIterableBy = <A>(items: Iterable<A>, f: (a: A) => string): Record<string, A> =>
146
+ fromIterableWith(items, (a) => [f(a), a])
147
+
120
148
  /**
121
149
  * Builds a record from an iterable of key-value pairs.
122
150
  *
@@ -12,7 +12,7 @@ import * as HashSet from "../HashSet.js"
12
12
  import * as number from "../Number.js"
13
13
  import * as Option from "../Option.js"
14
14
  import { pipeArguments } from "../Pipeable.js"
15
- import * as RA from "../ReadonlyArray.js"
15
+ import * as ReadonlyArray from "../ReadonlyArray.js"
16
16
  import type * as _config from "./config.js"
17
17
  import * as configError from "./configError.js"
18
18
  import * as pathPatch from "./configProvider/pathPatch.js"
@@ -20,6 +20,8 @@ import * as core from "./core.js"
20
20
  import * as OpCodes from "./opCodes/config.js"
21
21
  import * as StringUtils from "./string-utils.js"
22
22
 
23
+ type KeyComponent = ConfigProvider.ConfigProvider.KeyComponent
24
+
23
25
  const concat = <A, B>(l: ReadonlyArray<A>, r: ReadonlyArray<B>): ReadonlyArray<A | B> => [...l, ...r]
24
26
 
25
27
  /** @internal */
@@ -81,12 +83,12 @@ export const makeFlat = (
81
83
  export const fromFlat = (flat: ConfigProvider.ConfigProvider.Flat): ConfigProvider.ConfigProvider =>
82
84
  make({
83
85
  load: (config) =>
84
- core.flatMap(fromFlatLoop(flat, RA.empty(), config, false), (chunk) =>
85
- Option.match(RA.head(chunk), {
86
+ core.flatMap(fromFlatLoop(flat, ReadonlyArray.empty(), config, false), (chunk) =>
87
+ Option.match(ReadonlyArray.head(chunk), {
86
88
  onNone: () =>
87
89
  core.fail(
88
90
  configError.MissingData(
89
- RA.empty(),
91
+ ReadonlyArray.empty(),
90
92
  `Expected a single value having structure: ${config}`
91
93
  )
92
94
  ),
@@ -100,7 +102,7 @@ export const fromEnv = (
100
102
  config: Partial<ConfigProvider.ConfigProvider.FromEnvConfig> = {}
101
103
  ): ConfigProvider.ConfigProvider => {
102
104
  const { pathDelim, seqDelim } = Object.assign({}, { pathDelim: "_", seqDelim: "," }, config)
103
- const makePathString = (path: ReadonlyArray<string>): string => pipe(path, RA.join(pathDelim))
105
+ const makePathString = (path: ReadonlyArray<string>): string => pipe(path, ReadonlyArray.join(pathDelim))
104
106
  const unmakePathString = (pathString: string): ReadonlyArray<string> => pathString.split(pathDelim)
105
107
 
106
108
  const getEnv = () =>
@@ -130,7 +132,7 @@ export const fromEnv = (
130
132
  const keyPaths = Array.from(keys).map((value) => unmakePathString(value.toUpperCase()))
131
133
  const filteredKeyPaths = keyPaths.filter((keyPath) => {
132
134
  for (let i = 0; i < path.length; i++) {
133
- const pathComponent = pipe(path, RA.unsafeGet(i))
135
+ const pathComponent = pipe(path, ReadonlyArray.unsafeGet(i))
134
136
  const currentElement = keyPath[i]
135
137
  if (currentElement === undefined || pathComponent !== currentElement) {
136
138
  return false
@@ -150,7 +152,7 @@ export const fromMap = (
150
152
  config: Partial<ConfigProvider.ConfigProvider.FromMapConfig> = {}
151
153
  ): ConfigProvider.ConfigProvider => {
152
154
  const { pathDelim, seqDelim } = Object.assign({ seqDelim: ",", pathDelim: "." }, config)
153
- const makePathString = (path: ReadonlyArray<string>): string => pipe(path, RA.join(pathDelim))
155
+ const makePathString = (path: ReadonlyArray<string>): string => pipe(path, ReadonlyArray.join(pathDelim))
154
156
  const unmakePathString = (pathString: string): ReadonlyArray<string> => pathString.split(pathDelim)
155
157
  const mapWithIndexSplit = splitIndexInKeys(
156
158
  map,
@@ -179,7 +181,7 @@ export const fromMap = (
179
181
  const keyPaths = Array.from(mapWithIndexSplit.keys()).map(unmakePathString)
180
182
  const filteredKeyPaths = keyPaths.filter((keyPath) => {
181
183
  for (let i = 0; i < path.length; i++) {
182
- const pathComponent = pipe(path, RA.unsafeGet(i))
184
+ const pathComponent = pipe(path, ReadonlyArray.unsafeGet(i))
183
185
  const currentElement = keyPath[i]
184
186
  if (currentElement === undefined || pathComponent !== currentElement) {
185
187
  return false
@@ -199,14 +201,14 @@ const extend = <A, B>(
199
201
  left: ReadonlyArray<A>,
200
202
  right: ReadonlyArray<B>
201
203
  ): [ReadonlyArray<A>, ReadonlyArray<B>] => {
202
- const leftPad = RA.unfold(
204
+ const leftPad = ReadonlyArray.unfold(
203
205
  left.length,
204
206
  (index) =>
205
207
  index >= right.length ?
206
208
  Option.none() :
207
209
  Option.some([leftDef(index), index + 1])
208
210
  )
209
- const rightPad = RA.unfold(
211
+ const rightPad = ReadonlyArray.unfold(
210
212
  right.length,
211
213
  (index) =>
212
214
  index >= left.length ?
@@ -240,7 +242,7 @@ const fromFlatLoop = <A>(
240
242
  const op = config as _config.ConfigPrimitive
241
243
  switch (op._tag) {
242
244
  case OpCodes.OP_CONSTANT: {
243
- return core.succeed(RA.of(op.value)) as Effect.Effect<
245
+ return core.succeed(ReadonlyArray.of(op.value)) as Effect.Effect<
244
246
  never,
245
247
  ConfigError.ConfigError,
246
248
  ReadonlyArray<A>
@@ -298,7 +300,7 @@ const fromFlatLoop = <A>(
298
300
  return core.suspend(() =>
299
301
  fromFlatLoop(
300
302
  flat,
301
- concat(prefix, RA.of(op.name)),
303
+ concat(prefix, ReadonlyArray.of(op.name)),
302
304
  op.config,
303
305
  split
304
306
  )
@@ -312,7 +314,7 @@ const fromFlatLoop = <A>(
312
314
  flat.load(prefix, op, split),
313
315
  core.flatMap((values) => {
314
316
  if (values.length === 0) {
315
- const name = pipe(RA.last(prefix), Option.getOrElse(() => "<n/a>"))
317
+ const name = pipe(ReadonlyArray.last(prefix), Option.getOrElse(() => "<n/a>"))
316
318
  return core.fail(configError.MissingData([], `Expected ${op.description} with name ${name}`))
317
319
  }
318
320
  return core.succeed(values)
@@ -331,20 +333,20 @@ const fromFlatLoop = <A>(
331
333
  core.flatMap((indices) => {
332
334
  if (indices.length === 0) {
333
335
  return core.suspend(() =>
334
- core.map(fromFlatLoop(flat, patchedPrefix, op.config, true), RA.of)
336
+ core.map(fromFlatLoop(flat, patchedPrefix, op.config, true), ReadonlyArray.of)
335
337
  ) as unknown as Effect.Effect<never, ConfigError.ConfigError, ReadonlyArray<A>>
336
338
  }
337
339
  return pipe(
338
340
  core.forEachSequential(
339
341
  indices,
340
- (index) => fromFlatLoop(flat, RA.append(prefix, `[${index}]`), op.config, true)
342
+ (index) => fromFlatLoop(flat, ReadonlyArray.append(prefix, `[${index}]`), op.config, true)
341
343
  ),
342
344
  core.map((chunkChunk) => {
343
- const flattened = RA.flatten(chunkChunk)
345
+ const flattened = ReadonlyArray.flatten(chunkChunk)
344
346
  if (flattened.length === 0) {
345
- return RA.of(RA.empty<A>())
347
+ return ReadonlyArray.of(ReadonlyArray.empty<A>())
346
348
  }
347
- return RA.of(flattened)
349
+ return ReadonlyArray.of(flattened)
348
350
  })
349
351
  ) as unknown as Effect.Effect<never, ConfigError.ConfigError, ReadonlyArray<A>>
350
352
  })
@@ -365,19 +367,21 @@ const fromFlatLoop = <A>(
365
367
  core.forEachSequential((key) =>
366
368
  fromFlatLoop(
367
369
  flat,
368
- concat(prefix, RA.of(key)),
370
+ concat(prefix, ReadonlyArray.of(key)),
369
371
  op.valueConfig,
370
372
  split
371
373
  )
372
374
  ),
373
375
  core.map((values) => {
374
376
  if (values.length === 0) {
375
- return RA.of(HashMap.empty())
377
+ return ReadonlyArray.of(HashMap.empty())
376
378
  }
377
379
  const matrix = values.map((x) => Array.from(x))
378
380
  return pipe(
379
381
  transpose(matrix),
380
- RA.map((values) => HashMap.fromIterable(RA.zip(RA.fromIterable(keys), values)))
382
+ ReadonlyArray.map((values) =>
383
+ HashMap.fromIterable(ReadonlyArray.zip(ReadonlyArray.fromIterable(keys), values))
384
+ )
381
385
  )
382
386
  })
383
387
  )
@@ -407,17 +411,17 @@ const fromFlatLoop = <A>(
407
411
  return core.fail(right.left)
408
412
  }
409
413
  if (Either.isRight(left) && Either.isRight(right)) {
410
- const path = pipe(prefix, RA.join("."))
414
+ const path = pipe(prefix, ReadonlyArray.join("."))
411
415
  const fail = fromFlatLoopFail(prefix, path)
412
416
  const [lefts, rights] = extend(
413
417
  fail,
414
418
  fail,
415
- pipe(left.right, RA.map(Either.right)),
416
- pipe(right.right, RA.map(Either.right))
419
+ pipe(left.right, ReadonlyArray.map(Either.right)),
420
+ pipe(right.right, ReadonlyArray.map(Either.right))
417
421
  )
418
422
  return pipe(
419
423
  lefts,
420
- RA.zip(rights),
424
+ ReadonlyArray.zip(rights),
421
425
  core.forEachSequential(([left, right]) =>
422
426
  pipe(
423
427
  core.zip(left, right),
@@ -590,8 +594,8 @@ export const within = dual<
590
594
  f: (self: ConfigProvider.ConfigProvider) => ConfigProvider.ConfigProvider
591
595
  ) => ConfigProvider.ConfigProvider
592
596
  >(3, (self, path, f) => {
593
- const unnest = RA.reduce(path, self, (provider, name) => unnested(provider, name))
594
- const nest = RA.reduceRight(path, f(unnest), (provider, name) => nested(provider, name))
597
+ const unnest = ReadonlyArray.reduce(path, self, (provider, name) => unnested(provider, name))
598
+ const nest = ReadonlyArray.reduceRight(path, f(unnest), (provider, name) => nested(provider, name))
595
599
  return orElse(nest, () => self)
596
600
  })
597
601
 
@@ -612,7 +616,7 @@ const parsePrimitive = <A>(
612
616
  primitive.parse(text),
613
617
  core.mapBoth({
614
618
  onFailure: configError.prefixed(path),
615
- onSuccess: RA.of
619
+ onSuccess: ReadonlyArray.of
616
620
  })
617
621
  )
618
622
  }
@@ -635,8 +639,8 @@ const indicesFrom = (quotedIndices: HashSet.HashSet<string>): Effect.Effect<neve
635
639
  pipe(
636
640
  core.forEachSequential(quotedIndices, parseQuotedIndex),
637
641
  core.mapBoth({
638
- onFailure: () => RA.empty<number>(),
639
- onSuccess: RA.sort(number.Order)
642
+ onFailure: () => ReadonlyArray.empty<number>(),
643
+ onSuccess: ReadonlyArray.sort(number.Order)
640
644
  }),
641
645
  core.either,
642
646
  core.map(Either.merge)
@@ -668,10 +672,10 @@ const splitIndexInKeys = (
668
672
  for (const [pathString, value] of map) {
669
673
  const keyWithIndex = pipe(
670
674
  unmakePathString(pathString),
671
- RA.flatMap((key) =>
675
+ ReadonlyArray.flatMap((key) =>
672
676
  Option.match(splitIndexFrom(key), {
673
- onNone: () => RA.of(key),
674
- onSome: ([key, index]) => RA.make(key, `[${index}]`)
677
+ onNone: () => ReadonlyArray.of(key),
678
+ onSome: ([key, index]) => ReadonlyArray.make(key, `[${index}]`)
675
679
  })
676
680
  )
677
681
  )
@@ -705,3 +709,99 @@ const parseInteger = (str: string): Option.Option<number> => {
705
709
  Option.none() :
706
710
  Option.some(parsedIndex)
707
711
  }
712
+
713
+ const keyName = (name: string): KeyComponent => ({
714
+ _tag: "KeyName",
715
+ name
716
+ })
717
+
718
+ const keyIndex = (index: number): KeyComponent => ({
719
+ _tag: "KeyIndex",
720
+ index
721
+ })
722
+
723
+ interface JsonMap {
724
+ [member: string]: string | number | boolean | null | JsonArray | JsonMap
725
+ }
726
+ interface JsonArray extends Array<string | number | boolean | null | JsonArray | JsonMap> {}
727
+
728
+ /** @internal */
729
+ export const fromJson = (json: unknown): ConfigProvider.ConfigProvider => {
730
+ const hiddenDelimiter = "\ufeff"
731
+ const indexedEntries = ReadonlyArray.map(
732
+ getIndexedEntries(json as JsonMap),
733
+ ([key, value]): [string, string] => [configPathToString(key).join(hiddenDelimiter), value]
734
+ )
735
+ return fromMap(new Map(indexedEntries), {
736
+ pathDelim: hiddenDelimiter,
737
+ seqDelim: hiddenDelimiter
738
+ })
739
+ }
740
+
741
+ const configPathToString = (path: ReadonlyArray<KeyComponent>): ReadonlyArray<string> => {
742
+ const output: Array<string> = []
743
+ let i = 0
744
+ while (i < path.length) {
745
+ const component = path[i]
746
+ if (component._tag === "KeyName") {
747
+ if (i + 1 < path.length) {
748
+ const nextComponent = path[i + 1]
749
+ if (nextComponent._tag === "KeyIndex") {
750
+ output.push(`${component.name}[${nextComponent.index}]`)
751
+ i += 2
752
+ } else {
753
+ output.push(component.name)
754
+ i += 1
755
+ }
756
+ } else {
757
+ output.push(component.name)
758
+ i += 1
759
+ }
760
+ }
761
+ }
762
+ return output
763
+ }
764
+
765
+ const getIndexedEntries = (
766
+ config: JsonMap
767
+ ): ReadonlyArray<[path: ReadonlyArray<KeyComponent>, value: string]> => {
768
+ const loopAny = (
769
+ path: ReadonlyArray<KeyComponent>,
770
+ value: string | number | boolean | JsonMap | JsonArray | null
771
+ ): ReadonlyArray<[path: ReadonlyArray<KeyComponent>, value: string]> => {
772
+ if (typeof value === "string") {
773
+ return ReadonlyArray.make([path, value] as [ReadonlyArray<KeyComponent>, string])
774
+ }
775
+ if (typeof value === "number" || typeof value === "boolean") {
776
+ return ReadonlyArray.make([path, String(value)] as [ReadonlyArray<KeyComponent>, string])
777
+ }
778
+ if (Array.isArray(value)) {
779
+ return loopArray(path, value)
780
+ }
781
+ if (typeof value === "object" && value !== null) {
782
+ return loopObject(path, value)
783
+ }
784
+ return ReadonlyArray.empty<[ReadonlyArray<KeyComponent>, string]>()
785
+ }
786
+ const loopArray = (
787
+ path: ReadonlyArray<KeyComponent>,
788
+ values: JsonArray
789
+ ): ReadonlyArray<[path: ReadonlyArray<KeyComponent>, value: string]> =>
790
+ ReadonlyArray.match(values, {
791
+ onEmpty: () => ReadonlyArray.make([path, "<nil>"] as [ReadonlyArray<KeyComponent>, string]),
792
+ onNonEmpty: ReadonlyArray.flatMap((value, index) => loopAny(ReadonlyArray.append(path, keyIndex(index)), value))
793
+ })
794
+ const loopObject = (
795
+ path: ReadonlyArray<KeyComponent>,
796
+ value: JsonMap
797
+ ): ReadonlyArray<[path: ReadonlyArray<KeyComponent>, value: string]> =>
798
+ Object.entries(value).flatMap(([key, value]) => {
799
+ const newPath = ReadonlyArray.append(path, keyName(key))
800
+ const result = loopAny(newPath, value)
801
+ if (ReadonlyArray.isEmptyReadonlyArray(result)) {
802
+ return ReadonlyArray.make([newPath, ""] as [ReadonlyArray<KeyComponent>, string])
803
+ }
804
+ return result
805
+ })
806
+ return loopObject(ReadonlyArray.empty(), config)
807
+ }