@guillaume-docquier/tools-ts 4.0.1 → 4.2.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/README.md CHANGED
@@ -44,6 +44,26 @@ duplicating min/max checks across call sites.
44
44
  | ------- | ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
45
45
  | `Range` | Helpers for creating, validating, comparing, and testing ranges. | You need finite integer or float intervals with inclusive minimums and configurable maximums. |
46
46
 
47
+ ### Sorting
48
+
49
+ Use this tool when code needs shared ordering helpers.
50
+
51
+ | Export | What it is | Use it when |
52
+ | ------ | ---------------------------------------------- | --------------------------------------------------------------------------------------- |
53
+ | `Sort` | Comparator helpers for common sort operations. | You want a shared sorting utility instead of rewriting compare callbacks at call sites. |
54
+
55
+ ### Randomness
56
+
57
+ Use these tools when code needs injectable randomness or deterministic
58
+ pseudo-random sequences.
59
+
60
+ | Export | What it is | Use it when |
61
+ | ---------------- | -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
62
+ | `Rng` | Type for the RNG facade returned by `createRng`. | A function accepts or stores the package RNG abstraction. |
63
+ | `createRng` | Builds an RNG facade from a generator that returns values in [0, 1). | You need range-aware random numbers, shuffling, or draws backed by injectable randomness. |
64
+ | `Generator` | Type for raw generators that return values in [0, 1). | You accept or provide the primitive random source used to construct an `Rng`. |
65
+ | `mulberry32Prng` | Deterministic seeded pseudo-random generator factory. | Tests, simulations, or generation code need repeatable pseudo-random sequences. |
66
+
47
67
  ### Utility Types
48
68
 
49
69
  These exports are type-only helpers for common TypeScript modeling problems.
@@ -81,12 +101,13 @@ consistent context, scopes, formatting, and redaction.
81
101
  Use these small utilities to keep common asynchronous and callback patterns
82
102
  consistent.
83
103
 
84
- | Export | What it is | Use it when |
85
- | ----------------- | ----------------------------- | ------------------------------------------------------------------------------- |
86
- | `setTimeoutAsync` | Promise-based timeout helper. | You want `await`-friendly delays that work in browser and Node environments. |
87
- | `debounce` | Creates a debounced callback. | A repeated event should trigger work only after calls have settled for a delay. |
88
- | `noop` | Synchronous no-op function. | You need a safe default callback that intentionally does nothing. |
89
- | `asyncNoop` | Asynchronous no-op function. | You need a safe default async callback or hook that resolves immediately. |
104
+ | Export | What it is | Use it when |
105
+ | ----------------- | ------------------------------------------ | ------------------------------------------------------------------------------- |
106
+ | `setTimeoutAsync` | Promise-based timeout helper. | You want `await`-friendly delays that work in browser and Node environments. |
107
+ | `debounce` | Creates a debounced callback. | A repeated event should trigger work only after calls have settled for a delay. |
108
+ | `noop` | Synchronous no-op function. | You need a safe default callback that intentionally does nothing. |
109
+ | `asyncNoop` | Asynchronous no-op function. | You need a safe default async callback or hook that resolves immediately. |
110
+ | `omit` | Runtime equivalent of `Omit<TType, TKey>`. | You need to remove keys from an object. |
90
111
 
91
112
  ### Measurement
92
113
 
package/dist/Sort.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export declare const Sort: {
2
+ /**
3
+ * Sorts numbers by ascending values
4
+ */
5
+ byAscending: (a: number, b: number) => number;
6
+ };
package/dist/Sort.js ADDED
@@ -0,0 +1,9 @@
1
+ export const Sort = {
2
+ /**
3
+ * Sorts numbers by ascending values
4
+ */
5
+ byAscending: (a, b) => {
6
+ return a - b;
7
+ },
8
+ };
9
+ //# sourceMappingURL=Sort.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Sort.js","sourceRoot":"","sources":["../src/Sort.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB;;OAEG;IACH,WAAW,EAAE,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE;QAC5C,OAAO,CAAC,GAAG,CAAC,CAAA;IACd,CAAC;CACF,CAAA"}
@@ -6,6 +6,7 @@ export { isNodeJSError } from "./errors/isNodeJSError.js";
6
6
  export { getEnumKey } from "./getEnumKey.js";
7
7
  export type * from "./utility-types.js";
8
8
  export { asArray } from "./asArray.js";
9
+ export { omit } from "./omit.js";
9
10
  export { Assert } from "./Assert.js";
10
11
  export { Result, type Success, type Failure } from "./Result.js";
11
12
  export { Measure } from "./Measure.js";
@@ -23,3 +24,6 @@ export type { LogContext } from "./logging/log-context/LogContext.js";
23
24
  export type { LoggerContext } from "./logging/log-context/LoggerContext.js";
24
25
  export type { LogContextProvider } from "./logging/log-context/LogContextProvider.js";
25
26
  export { debounce } from "./debounce.js";
27
+ export { Sort } from "./Sort.js";
28
+ export { createRng, type Rng, type Generator } from "./rng/rng.js";
29
+ export { mulberry32Prng } from "./rng/mulberry32prng.js";
@@ -5,6 +5,7 @@ export { NotImplementedError } from "./errors/NotImplementedError.js";
5
5
  export { isNodeJSError } from "./errors/isNodeJSError.js";
6
6
  export { getEnumKey } from "./getEnumKey.js";
7
7
  export { asArray } from "./asArray.js";
8
+ export { omit } from "./omit.js";
8
9
  export { Assert } from "./Assert.js";
9
10
  export { Result } from "./Result.js";
10
11
  export { Measure } from "./Measure.js";
@@ -18,4 +19,7 @@ export { jsonLineFormatter } from "./logging/formatter/jsonLineFormatter.js";
18
19
  export { prettyConsoleFormatter } from "./logging/formatter/prettyConsoleFormatter.js";
19
20
  export { createConsoleLogSink } from "./logging/sink/ConsoleLogSink.js";
20
21
  export { debounce } from "./debounce.js";
22
+ export { Sort } from "./Sort.js";
23
+ export { createRng } from "./rng/rng.js";
24
+ export { mulberry32Prng } from "./rng/mulberry32prng.js";
21
25
  //# sourceMappingURL=entry.tools-ts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"entry.tools-ts.js","sourceRoot":"","sources":["../src/entry.tools-ts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAA;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAI5C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,MAAM,EAA8B,MAAM,aAAa,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAA;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,+CAA+C,CAAA;AAEtF,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAA;AAKvE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"entry.tools-ts.js","sourceRoot":"","sources":["../src/entry.tools-ts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAA;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAI5C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,MAAM,EAA8B,MAAM,aAAa,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAA;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,+CAA+C,CAAA;AAEtF,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAA;AAKvE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,SAAS,EAA4B,MAAM,cAAc,CAAA;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA"}
package/dist/noop.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Does nothing.
3
- * Usually used a default parameter for optional callbacks.
3
+ * Usually used as a default parameter for optional callbacks.
4
4
  */
5
5
  export declare function noop(): void;
6
6
  /**
7
7
  * Asynchronously does nothing.
8
- * Usually used a default parameter for async optional callbacks.
8
+ * Usually used as a default parameter for async optional callbacks.
9
9
  */
10
10
  export declare function asyncNoop(): Promise<void>;
package/dist/noop.js CHANGED
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * Does nothing.
3
- * Usually used a default parameter for optional callbacks.
3
+ * Usually used as a default parameter for optional callbacks.
4
4
  */
5
5
  export function noop() { }
6
6
  /**
7
7
  * Asynchronously does nothing.
8
- * Usually used a default parameter for async optional callbacks.
8
+ * Usually used as a default parameter for async optional callbacks.
9
9
  */
10
10
  export async function asyncNoop() { }
11
11
  //# sourceMappingURL=noop.js.map
package/dist/omit.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Returns the given record with omitted keys.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * const record = { a: 1, b: 2, c: 3 }
7
+ * const omitted = omit(record, "b", "c")
8
+ *
9
+ * console.log(record) // { a: 1, b: 2, c: 3 }
10
+ * console.log(omitted) // { a: 1 }
11
+ * ```
12
+ */
13
+ export declare function omit<TRecord extends Record<string, unknown>, TKey extends keyof TRecord>(record: Readonly<TRecord>, ...keys: TKey[]): Omit<TRecord, TKey>;
package/dist/omit.js ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Returns the given record with omitted keys.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * const record = { a: 1, b: 2, c: 3 }
7
+ * const omitted = omit(record, "b", "c")
8
+ *
9
+ * console.log(record) // { a: 1, b: 2, c: 3 }
10
+ * console.log(omitted) // { a: 1 }
11
+ * ```
12
+ */
13
+ export function omit(record, ...keys) {
14
+ const result = { ...record };
15
+ for (const key of keys) {
16
+ delete result[key];
17
+ }
18
+ return result;
19
+ }
20
+ //# sourceMappingURL=omit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"omit.js","sourceRoot":"","sources":["../src/omit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,IAAI,CAClB,MAAyB,EACzB,GAAG,IAAY;IAEf,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,CAAA;IAE5B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Generator } from "./rng.js";
2
+ /**
3
+ * Creates a deterministic pseudo-random number generator based on a 32-bit integer seed using the mulberry32 algorithm.
4
+ *
5
+ * It generates floats in the range [0, 1)
6
+ */
7
+ export declare function mulberry32Prng(seed: number): Generator;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Creates a deterministic pseudo-random number generator based on a 32-bit integer seed using the mulberry32 algorithm.
3
+ *
4
+ * It generates floats in the range [0, 1)
5
+ */
6
+ export function mulberry32Prng(seed) {
7
+ let state = seed >>> 0;
8
+ return () => {
9
+ state += 0x6d2b79f5;
10
+ let next = state;
11
+ next = Math.imul(next ^ (next >>> 15), next | 1);
12
+ next ^= next + Math.imul(next ^ (next >>> 7), next | 61);
13
+ return ((next ^ (next >>> 14)) >>> 0) / 4_294_967_296;
14
+ };
15
+ }
16
+ //# sourceMappingURL=mulberry32prng.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mulberry32prng.js","sourceRoot":"","sources":["../../src/rng/mulberry32prng.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,KAAK,GAAG,IAAI,KAAK,CAAC,CAAA;IAEtB,OAAO,GAAG,EAAE;QACV,KAAK,IAAI,UAAU,CAAA;QAEnB,IAAI,IAAI,GAAG,KAAK,CAAA;QAChB,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAA;QAChD,IAAI,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,IAAI,GAAG,EAAE,CAAC,CAAA;QAExD,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,aAAa,CAAA;IACvD,CAAC,CAAA;AACH,CAAC"}
@@ -0,0 +1,37 @@
1
+ import type { Range } from "../Range.js";
2
+ /**
3
+ * A generator that returns numbers in the range [0, 1)
4
+ */
5
+ export type Generator = () => number;
6
+ export type Rng = {
7
+ /**
8
+ * Generates a random number based on the given Range.
9
+ * It will output an int given an int Range, or a float given a float Range.
10
+ */
11
+ random: (range: Range) => number;
12
+ /**
13
+ * Generates a float in the float Range.
14
+ * When no range is provided, returns a float in the range [0, 1).
15
+ */
16
+ float: (range?: Range<"float">) => number;
17
+ /**
18
+ * Generates an int in the int Range.
19
+ */
20
+ int: (range: Range<"integer">) => number;
21
+ /**
22
+ * Shuffles an array in place.
23
+ */
24
+ shuffle: <T>(values: T[]) => T[];
25
+ /**
26
+ * Draws a number of elements without modifying the original array.
27
+ */
28
+ draw: <T>(values: T[], count: number) => {
29
+ drawn: T[];
30
+ remaining: T[];
31
+ };
32
+ };
33
+ /**
34
+ * Creates a random number generator based on your generator of choice.
35
+ * @param generator The generator that returns numbers in the range [0, 1)
36
+ */
37
+ export declare function createRng(generator: Generator): Rng;
@@ -0,0 +1,58 @@
1
+ const intBoundsOffset = {
2
+ inclusive: 1,
3
+ exclusive: 0,
4
+ };
5
+ /**
6
+ * Creates a random number generator based on your generator of choice.
7
+ * @param generator The generator that returns numbers in the range [0, 1)
8
+ */
9
+ export function createRng(generator) {
10
+ function random(range) {
11
+ switch (range.numericType) {
12
+ case "float":
13
+ // The fact we have to cast like this sucks a little bit, we'll see if we have to do this often or not.
14
+ return float(range);
15
+ case "integer":
16
+ // The fact we have to cast like this sucks a little bit, we'll see if we have to do this often or not.
17
+ return int(range);
18
+ }
19
+ }
20
+ function float(range) {
21
+ if (range === undefined) {
22
+ return generator();
23
+ }
24
+ // Because of floating point errors, this is inclusive when min > 1, but that's statistically insignificant.
25
+ return range.min + generator() * (range.max - range.min);
26
+ }
27
+ function int(range) {
28
+ // We +1 the max because float is exclusive of the max, but for int we want the range to be inclusive.
29
+ // We floor before the addition, because the addition can lose precision and generate numbers that are out of bounds when float ~= 1.
30
+ // We don't use Math.floor(float(rangeWithMaxPlus1)) for the same reason
31
+ return range.min + Math.floor(float() * (range.max + intBoundsOffset[range.maxBoundType] - range.min));
32
+ }
33
+ /**
34
+ * Fisher-Yates shuffle in place.
35
+ */
36
+ function shuffle(values) {
37
+ for (let i = values.length - 1; i > 0; i--) {
38
+ const j = Math.floor(generator() * (i + 1));
39
+ [values[i], values[j]] = [values[j], values[i]];
40
+ }
41
+ return values;
42
+ }
43
+ function draw(values, count) {
44
+ const shuffled = shuffle(values.slice());
45
+ return {
46
+ drawn: shuffled,
47
+ remaining: shuffled.splice(count),
48
+ };
49
+ }
50
+ return {
51
+ random,
52
+ float,
53
+ int,
54
+ shuffle,
55
+ draw,
56
+ };
57
+ }
58
+ //# sourceMappingURL=rng.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rng.js","sourceRoot":"","sources":["../../src/rng/rng.ts"],"names":[],"mappings":"AAoCA,MAAM,eAAe,GAAG;IACtB,SAAS,EAAE,CAAC;IACZ,SAAS,EAAE,CAAC;CAC4C,CAAA;AAE1D;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,SAAoB;IAC5C,SAAS,MAAM,CAAC,KAAY;QAC1B,QAAQ,KAAK,CAAC,WAAW,EAAE,CAAC;YAC1B,KAAK,OAAO;gBACV,uGAAuG;gBACvG,OAAO,KAAK,CAAC,KAAwC,CAAC,CAAA;YACxD,KAAK,SAAS;gBACZ,uGAAuG;gBACvG,OAAO,GAAG,CAAC,KAAwC,CAAC,CAAA;QACxD,CAAC;IACH,CAAC;IAED,SAAS,KAAK,CAAC,KAAsB;QACnC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,SAAS,EAAE,CAAA;QACpB,CAAC;QAED,4GAA4G;QAC5G,OAAO,KAAK,CAAC,GAAG,GAAG,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;IAC1D,CAAC;IAED,SAAS,GAAG,CAAC,KAAuB;QAClC,sGAAsG;QACtG,qIAAqI;QACrI,wEAAwE;QACxE,OAAO,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,eAAe,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAA;IACxG,CAAC;IAED;;OAEG;IACH,SAAS,OAAO,CAAI,MAA0B;QAC5C,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAC1C;YAAA,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,MAAM,CAAC,CAAC,CAAM,CAAC,CAAA;QAC5D,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC;IAED,SAAS,IAAI,CAAI,MAAkC,EAAE,KAAa;QAChE,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAA;QAExC,OAAO;YACL,KAAK,EAAE,QAAQ;YACf,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC;SAClC,CAAA;IACH,CAAC;IAED,OAAO;QACL,MAAM;QACN,KAAK;QACL,GAAG;QACH,OAAO;QACP,IAAI;KACL,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guillaume-docquier/tools-ts",
3
- "version": "4.0.1",
3
+ "version": "4.2.0",
4
4
  "description": "My personal collection of typescript tools",
5
5
  "homepage": "https://github.com/Guillaume-Docquier/tools-ts",
6
6
  "repository": {