@railway-ts/pipelines 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/README.md +811 -0
- package/dist/composition/index.cjs +72 -0
- package/dist/composition/index.cjs.map +1 -0
- package/dist/composition/index.d.cts +286 -0
- package/dist/composition/index.d.ts +286 -0
- package/dist/composition/index.mjs +65 -0
- package/dist/composition/index.mjs.map +1 -0
- package/dist/index-BdfKTZ7O.d.cts +799 -0
- package/dist/index-BdfKTZ7O.d.ts +799 -0
- package/dist/index.cjs +1074 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.mjs +969 -0
- package/dist/index.mjs.map +1 -0
- package/dist/option/index.cjs +111 -0
- package/dist/option/index.cjs.map +1 -0
- package/dist/option/index.d.cts +1 -0
- package/dist/option/index.d.ts +1 -0
- package/dist/option/index.mjs +93 -0
- package/dist/option/index.mjs.map +1 -0
- package/dist/result/index.cjs +178 -0
- package/dist/result/index.cjs.map +1 -0
- package/dist/result/index.d.cts +1 -0
- package/dist/result/index.d.ts +1 -0
- package/dist/result/index.mjs +152 -0
- package/dist/result/index.mjs.map +1 -0
- package/dist/schema/index.cjs +794 -0
- package/dist/schema/index.cjs.map +1 -0
- package/dist/schema/index.d.cts +1867 -0
- package/dist/schema/index.d.ts +1867 -0
- package/dist/schema/index.mjs +735 -0
- package/dist/schema/index.mjs.map +1 -0
- package/examples/complete-pipelines/async-launch.ts +128 -0
- package/examples/complete-pipelines/async.ts +119 -0
- package/examples/complete-pipelines/hill-clohessy-wiltshire.ts +218 -0
- package/examples/complete-pipelines/hohmann-transfer.ts +159 -0
- package/examples/composition/advanced-composition.ts +32 -0
- package/examples/composition/curry-basics.ts +24 -0
- package/examples/composition/tupled-basics.ts +26 -0
- package/examples/index.ts +47 -0
- package/examples/interop/interop-examples.ts +110 -0
- package/examples/option/option-examples.ts +63 -0
- package/examples/result/result-examples.ts +110 -0
- package/examples/schema/basic.ts +78 -0
- package/examples/schema/union.ts +301 -0
- package/package.json +100 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// src/option/option.ts
|
|
2
|
+
var OPTION_BRAND = Symbol("OPTION_BRAND");
|
|
3
|
+
function some(value) {
|
|
4
|
+
return {
|
|
5
|
+
some: true,
|
|
6
|
+
value,
|
|
7
|
+
[OPTION_BRAND]: "some"
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function none() {
|
|
11
|
+
return {
|
|
12
|
+
some: false,
|
|
13
|
+
[OPTION_BRAND]: "none"
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// src/result/result.ts
|
|
18
|
+
var RESULT_BRAND = Symbol("RESULT_BRAND");
|
|
19
|
+
function ok(value) {
|
|
20
|
+
return {
|
|
21
|
+
ok: true,
|
|
22
|
+
value,
|
|
23
|
+
[RESULT_BRAND]: "ok"
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function err(error) {
|
|
27
|
+
return { ok: false, error, [RESULT_BRAND]: "error" };
|
|
28
|
+
}
|
|
29
|
+
function isOk(result) {
|
|
30
|
+
return result.ok;
|
|
31
|
+
}
|
|
32
|
+
function isErr(result) {
|
|
33
|
+
return !result.ok;
|
|
34
|
+
}
|
|
35
|
+
function map(result, fn) {
|
|
36
|
+
return result.ok ? ok(fn(result.value)) : result;
|
|
37
|
+
}
|
|
38
|
+
function mapErr(result, fn) {
|
|
39
|
+
return result.ok ? result : err(fn(result.error));
|
|
40
|
+
}
|
|
41
|
+
function flatMap(result, fn) {
|
|
42
|
+
return result.ok ? fn(result.value) : result;
|
|
43
|
+
}
|
|
44
|
+
function bimap(result, okFn, errFn) {
|
|
45
|
+
return result.ok ? ok(okFn(result.value)) : err(errFn(result.error));
|
|
46
|
+
}
|
|
47
|
+
function filter(result, predicate, error) {
|
|
48
|
+
return result.ok && predicate(result.value) ? result : err(error);
|
|
49
|
+
}
|
|
50
|
+
function unwrap(result, errorMsg) {
|
|
51
|
+
if (result.ok) {
|
|
52
|
+
return result.value;
|
|
53
|
+
} else {
|
|
54
|
+
throw new Error(errorMsg || `Cannot unwrap an error Result: ${String(result.error)}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function unwrapOr(result, defaultValue) {
|
|
58
|
+
return result.ok ? result.value : defaultValue;
|
|
59
|
+
}
|
|
60
|
+
function unwrapOrElse(result, defaultFn) {
|
|
61
|
+
return result.ok ? result.value : defaultFn();
|
|
62
|
+
}
|
|
63
|
+
function combine(results) {
|
|
64
|
+
const values = [];
|
|
65
|
+
for (const result of results) {
|
|
66
|
+
if (!result.ok) return result;
|
|
67
|
+
values.push(result.value);
|
|
68
|
+
}
|
|
69
|
+
return ok(values);
|
|
70
|
+
}
|
|
71
|
+
function combineAll(results) {
|
|
72
|
+
const errors = [];
|
|
73
|
+
const values = [];
|
|
74
|
+
for (const result of results) {
|
|
75
|
+
if (result.ok) {
|
|
76
|
+
values.push(result.value);
|
|
77
|
+
} else {
|
|
78
|
+
errors.push(result.error);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return errors.length > 0 ? err(errors) : ok(values);
|
|
82
|
+
}
|
|
83
|
+
function match(result, patterns) {
|
|
84
|
+
if (isOk(result)) {
|
|
85
|
+
const okFn = patterns.ok;
|
|
86
|
+
return okFn(result.value);
|
|
87
|
+
} else {
|
|
88
|
+
const errFn = patterns.err;
|
|
89
|
+
return errFn(result.error);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function tap(result, fn) {
|
|
93
|
+
if (isOk(result)) {
|
|
94
|
+
const callback = fn;
|
|
95
|
+
callback(result.value);
|
|
96
|
+
}
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
function tapErr(result, fn) {
|
|
100
|
+
if (isErr(result)) {
|
|
101
|
+
const callback = fn;
|
|
102
|
+
callback(result.error);
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
function mapToOption(result) {
|
|
107
|
+
return result.ok ? some(result.value) : none();
|
|
108
|
+
}
|
|
109
|
+
function fromTry(f) {
|
|
110
|
+
try {
|
|
111
|
+
return ok(f());
|
|
112
|
+
} catch (error) {
|
|
113
|
+
return err(error instanceof Error ? error.message : String(error));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function fromTryWithError(f) {
|
|
117
|
+
try {
|
|
118
|
+
return ok(f());
|
|
119
|
+
} catch (error) {
|
|
120
|
+
return err(error instanceof Error ? error : new Error(String(error)));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function fromPromise(promise) {
|
|
124
|
+
try {
|
|
125
|
+
const value = await promise;
|
|
126
|
+
return ok(value);
|
|
127
|
+
} catch (error) {
|
|
128
|
+
return err(error instanceof Error ? error.message : String(error));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async function fromPromiseWithError(promise, errorFn = (error) => error) {
|
|
132
|
+
try {
|
|
133
|
+
const value = await promise;
|
|
134
|
+
return ok(value);
|
|
135
|
+
} catch (error) {
|
|
136
|
+
return err(errorFn(error));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function toPromise(result) {
|
|
140
|
+
return result.ok ? Promise.resolve(result.value) : Promise.reject(result.error);
|
|
141
|
+
}
|
|
142
|
+
async function andThen(input, fn) {
|
|
143
|
+
const settled = await input;
|
|
144
|
+
if (settled.ok) {
|
|
145
|
+
return await fn(settled.value);
|
|
146
|
+
}
|
|
147
|
+
return err(settled.error);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export { RESULT_BRAND, andThen, bimap, combine, combineAll, err, filter, flatMap, fromPromise, fromPromiseWithError, fromTry, fromTryWithError, isErr, isOk, map, mapErr, mapToOption, match, ok, tap, tapErr, toPromise, unwrap, unwrapOr, unwrapOrElse };
|
|
151
|
+
//# sourceMappingURL=index.mjs.map
|
|
152
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/option/option.ts","../../src/result/result.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { type Result, ok, err } from '@/result';\n\n/**\n * Symbol used to identify Option objects.\n *\n * @internal\n */\nexport const OPTION_BRAND = Symbol('OPTION_BRAND');\n\n/**\n * Represents an Option type.\n *\n * @example\n * const some: Option<number> = some(123);\n * const none: Option<number> = none();\n *\n * @param T - The type of the value contained in the Some variant\n * @returns An Option containing a value or nothing\n */\nexport type Option<T> =\n | {\n readonly some: true;\n readonly value: T;\n readonly [OPTION_BRAND]: 'some';\n }\n | {\n readonly some: false;\n readonly [OPTION_BRAND]: 'none';\n };\n\n/**\n * Creates an Option containing a value.\n *\n * @param value - The value to contain\n * @returns An Option containing the value\n */\nexport function some<T>(value: T): Option<T> {\n return {\n some: true,\n value,\n [OPTION_BRAND]: 'some',\n };\n}\n\n/**\n * Creates an Option containing nothing.\n *\n * @example\n * const some: Option<number> = some(123);\n * const none: Option<number> = none();\n *\n * @returns An Option containing nothing\n */\nexport function none(): Option<never>;\nexport function none<T>(): Option<T>;\nexport function none<T>(): Option<T> {\n return {\n some: false,\n [OPTION_BRAND]: 'none',\n };\n}\n\n/**\n * Type guard that checks if an Option is a Some variant containing a value.\n *\n * @example\n * const option: Option<number> = some(123);\n * if (isSome(option)) {\n * // TypeScript knows option.value exists here\n * console.log(option.value);\n * }\n *\n * @param option - The option to check\n * @returns A type predicate indicating if the option is a Some variant\n */\nexport function isSome<T>(option: Option<T>): option is {\n readonly some: true;\n readonly value: T;\n readonly [OPTION_BRAND]: 'some';\n} {\n return option.some;\n}\n\n/**\n * Type guard that checks if an Option is a None variant containing no value.\n *\n * @example\n * const option: Option<number> = none();\n * if (isNone(option)) {\n * // TypeScript knows this option has no value\n * // Attempting to access option.value would be a type error\n * }\n *\n * @param option - The option to check\n * @returns A type predicate indicating if the option is a None variant\n */\nexport function isNone<T>(option: Option<T>): option is {\n readonly some: false;\n readonly [OPTION_BRAND]: 'none';\n} {\n return !option.some;\n}\n\n/**\n * Maps the value inside an Option using a transformation function.\n *\n * @example\n * const option: Option<number> = some(123);\n * const transformed: Option<string> = map(option, (value) => value.toString());\n *\n * @param option - The Option to transform\n * @param fn - The function to apply to the contained value\n * @returns A new Option containing the transformed value, or none if the input was none\n */\nexport function map<T, U>(option: Option<T>, fn: (value: T) => U): Option<U> {\n return option.some ? some(fn(option.value)) : none();\n}\n\n/**\n * Maps the value inside an Option using a transformation function that returns an Option.\n *\n * @example\n * const option: Option<number> = some(123);\n * const transformed: Option<string> = flatMap(option, (value) => some(value.toString()));\n *\n * @param option - The Option to transform\n * @param fn - The function to apply to the contained value, returning an Option\n * @returns The Option returned by the transformation function, or none if the input was none\n */\nexport function flatMap<T, U>(option: Option<T>, fn: (value: T) => Option<U>): Option<U> {\n return option.some ? fn(option.value) : none();\n}\n\n/**\n * Maps both the Some and None branches of an Option using separate transformation functions.\n * This is similar to combining a match with flatMap: it lets you decide the resulting Option in both cases.\n *\n * @example\n * const o1 = some(123);\n * const r1 = bimap(o1, (n) => some(n.toString()), () => none()); // some(\"123\")\n *\n * const o2 = none<number>();\n * const r2 = bimap(o2, (n) => some(n.toString()), () => some('fallback')); // some(\"fallback\")\n *\n * @param option - The Option to transform\n * @param someFn - The function to apply if the Option is Some, returning a new Option\n * @param noneFn - The function to apply if the Option is None, returning a new Option\n * @returns The Option returned by the appropriate transformation function\n */\nexport function bimap<T, U>(option: Option<T>, someFn: (value: T) => Option<U>, noneFn: () => Option<U>): Option<U> {\n return option.some ? someFn(option.value) : noneFn();\n}\n\n/**\n * Filters an Option based on a predicate function.\n *\n * @example\n * const option: Option<number> = some(123);\n * const filtered: Option<number> = filter(option, value => value > 100); // still Some(123)\n * const filtered2: Option<number> = filter(option, value => value < 100); // None\n *\n * @param option - The Option to filter\n * @param predicate - A function that determines if the value should be kept\n * @returns The original Option if it contains a value that satisfies the predicate, otherwise None\n */\nexport function filter<T>(option: Option<T>, predicate: (value: T) => boolean): Option<T> {\n return option.some && predicate(option.value) ? option : none();\n}\n\n/**\n * Unwraps the value inside an Option, throwing an error if the Option is none.\n *\n * @remarks\n * This function is intended for prototyping only and should not be used in production.\n * In production code, prefer using pattern matching or `unwrapOr` to handle both Some and None cases safely.\n *\n * @example\n * const option: Option<number> = some(123);\n * const value: number = unwrap(option);\n *\n * @param option - The Option to unwrap\n * @param [errorMsg] - Optional custom error message to throw when the Option is none\n * @returns The contained value\n */\nexport function unwrap<T>(option: Option<T>, errorMsg?: string): T {\n if (option.some) {\n return option.value;\n } else {\n throw new Error(errorMsg || 'Cannot unwrap a none Option');\n }\n}\n\n/**\n * Unwraps the value inside an Option, providing a default value if the Option is none.\n *\n * @example\n * const option: Option<number> = none();\n * const value: number = unwrapOr(option, 123);\n *\n * @param option - The Option to unwrap\n * @param defaultValue - The value to return if the Option is none\n * @returns The contained value, or the default value if the Option is none\n */\nexport function unwrapOr<T>(option: Option<T>, defaultValue: T): T {\n return option.some ? option.value : defaultValue;\n}\n\n/**\n * Unwraps the value inside an Option, calling a function to generate a default value if the Option is none.\n * Unlike unwrapOr, this only computes the default when needed.\n *\n * @example\n * const option: Option<number> = none();\n * const value = unwrapOrElse(option, () => expensiveComputation());\n *\n * @param option - The Option to unwrap\n * @param defaultFn - A function that returns a default value if the Option is none\n * @returns The contained value, or the result of calling defaultFn if the Option is none\n */\nexport function unwrapOrElse<T>(option: Option<T>, defaultFn: () => T): T {\n return option.some ? option.value : defaultFn();\n}\n\n/**\n * Creates an Option from a nullable value.\n *\n * @example\n * const option = fromNullable(123); // some(123)\n * const option = fromNullable(null); // none()\n *\n * @param value - The value to wrap in the Some variant\n * @returns An Option containing the value (Some) if the value is not null or undefined, or None if the value is null or undefined\n */\nexport const fromNullable = <T>(value: T | null | undefined): Option<T> => {\n return value === null || value === undefined ? none() : some(value);\n};\n\n/**\n * Combines an array of Options into a single Option containing an array of values.\n * Returns None if any Option in the array is None.\n *\n * @example\n * const options = [some(1), some(2), some(3)];\n * const combined = combine(options); // some([1, 2, 3])\n *\n * const withNone = [some(1), none(), some(3)];\n * const result = combine(withNone); // none()\n *\n * @param options - An array of Options to combine\n * @returns An Option containing an array of all values if all inputs are Some, or None if any input is None\n */\n\n// Tuple-preserving overloads\nexport function combine<T1>(options: readonly [Option<T1>]): Option<[T1]>;\nexport function combine<T1, T2>(options: readonly [Option<T1>, Option<T2>]): Option<[T1, T2]>;\nexport function combine<T1, T2, T3>(options: readonly [Option<T1>, Option<T2>, Option<T3>]): Option<[T1, T2, T3]>;\nexport function combine<T1, T2, T3, T4>(\n options: readonly [Option<T1>, Option<T2>, Option<T3>, Option<T4>],\n): Option<[T1, T2, T3, T4]>;\nexport function combine<T1, T2, T3, T4, T5>(\n options: readonly [Option<T1>, Option<T2>, Option<T3>, Option<T4>, Option<T5>],\n): Option<[T1, T2, T3, T4, T5]>;\nexport function combine<T1, T2, T3, T4, T5, T6>(\n options: readonly [Option<T1>, Option<T2>, Option<T3>, Option<T4>, Option<T5>, Option<T6>],\n): Option<[T1, T2, T3, T4, T5, T6]>;\nexport function combine<T1, T2, T3, T4, T5, T6, T7>(\n options: readonly [Option<T1>, Option<T2>, Option<T3>, Option<T4>, Option<T5>, Option<T6>, Option<T7>],\n): Option<[T1, T2, T3, T4, T5, T6, T7]>;\nexport function combine<T1, T2, T3, T4, T5, T6, T7, T8>(\n options: readonly [Option<T1>, Option<T2>, Option<T3>, Option<T4>, Option<T5>, Option<T6>, Option<T7>, Option<T8>],\n): Option<[T1, T2, T3, T4, T5, T6, T7, T8]>;\nexport function combine<T1, T2, T3, T4, T5, T6, T7, T8, T9>(\n options: readonly [\n Option<T1>,\n Option<T2>,\n Option<T3>,\n Option<T4>,\n Option<T5>,\n Option<T6>,\n Option<T7>,\n Option<T8>,\n Option<T9>,\n ],\n): Option<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>;\nexport function combine<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(\n options: readonly [\n Option<T1>,\n Option<T2>,\n Option<T3>,\n Option<T4>,\n Option<T5>,\n Option<T6>,\n Option<T7>,\n Option<T8>,\n Option<T9>,\n Option<T10>,\n ],\n): Option<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>;\nexport function combine<T>(options: readonly Option<T>[]): Option<T[]>;\n\nexport function combine<T>(options: readonly Option<T>[]): Option<T[]> {\n const values: T[] = [];\n\n for (const option of options) {\n if (!option.some) return none();\n values.push(option.value);\n }\n\n return some(values);\n}\n\n/**\n * Pattern matches on an Option to handle both Some and None cases.\n *\n * @example\n * const option = some(42);\n * const result = match(option, {\n * some: (value) => `Got value: ${value}`,\n * none: () => \"Got nothing\"\n * }); // \"Got value: 42\"\n *\n * const empty = none<number>();\n * const result2 = match(empty, {\n * some: (value) => `Got value: ${value}`,\n * none: () => \"Got nothing\"\n * }); // \"Got nothing\"\n *\n * @param option - The Option to match against\n * @param patterns - An object containing handler functions for Some and None cases\n * @returns The result of calling the appropriate handler function\n */\nexport function match<T, R>(\n option: Option<T>,\n patterns: {\n some: (value: T) => R;\n none: () => R;\n },\n): R {\n if (isSome(option)) {\n const someFn = patterns.some;\n return someFn(option.value);\n } else {\n const noneFn = patterns.none;\n return noneFn();\n }\n}\n\n/**\n * Executes a callback with the value if the Option is Some, without changing the Option.\n * Useful for side effects like logging while maintaining a processing chain.\n *\n * @example\n * const result = pipe(\n * some(123),\n * opt => map(opt, x => x * 2),\n * opt => tap(opt, x => console.log(`Value: ${x}`)), // Logs but doesn't change the Option\n * opt => filter(opt, x => x > 200)\n * );\n *\n * @param option - The Option to tap into\n * @param fn - The function to execute with the value if Some\n * @returns The original Option unchanged\n */\nexport function tap<T>(option: Option<T>, fn: (value: T) => void): Option<T> {\n if (isSome(option)) {\n const callback = fn;\n callback(option.value);\n }\n return option;\n}\n\n/**\n * Converts an Option to a Result.\n * If the Option is Some, returns an Ok variant with the value.\n * If the Option is None, returns an Err variant with the provided error.\n *\n * @example\n * const result = mapToResult(some(123), 'Some error message');\n * if (isOk(result)) {\n * console.log('Value:', result.value);\n * } else {\n * console.error('Error:', result.error);\n * }\n *\n * @param option - The Option to convert\n * @param error - The error to return if the Option is None\n * @returns A Result containing either the value (Ok) or the error (Err)\n */\nexport function mapToResult<T, E>(option: Option<T>, error: E): Result<T, E> {\n return option.some ? ok(option.value) : err(error);\n}\n","import { none, some, type Option } from '@/option';\n\n/**\n * Symbol used to identify Result objects.\n *\n * @internal\n */\nexport const RESULT_BRAND = Symbol('RESULT_BRAND');\n\n/**\n * Represents a Result type.\n *\n * @example\n * const result: Result<number, string> = ok(123);\n * const error: Result<number, string> = error(\"An error occurred\");\n *\n * @param T - The type of the value contained in the Ok variant\n * @param E - The type of the error contained in the Error variant\n * @returns A Result containing a value or an error\n */\nexport type Result<T, E> =\n | {\n readonly ok: true;\n readonly value: T;\n readonly [RESULT_BRAND]: 'ok';\n }\n | {\n readonly ok: false;\n readonly error: E;\n readonly [RESULT_BRAND]: 'error';\n };\n\n/**\n * Creates a Result containing a value.\n *\n * @example\n * const result: Result<number, string> = ok(123);\n *\n * @param value - The value to contain\n * @returns A Result containing the value\n */\nexport function ok<T, E = never>(value: T): Result<T, E> {\n return {\n ok: true,\n value,\n [RESULT_BRAND]: 'ok',\n };\n}\n\n/**\n * Creates a Result containing an error.\n *\n * @example\n * const error: Result<number, string> = err(\"An error occurred\");\n *\n * @param error - The error to contain\n * @returns A Result containing the error\n */\nexport function err<E>(error: E): Result<never, E> {\n return { ok: false, error, [RESULT_BRAND]: 'error' };\n}\n\n/**\n * Type guard that checks if a Result is an Ok variant containing a value.\n *\n * @example\n * const result: Result<number, string> = ok(123);\n * if (isOk(result)) {\n * // TypeScript knows result.value exists here\n * console.log(result.value);\n * }\n *\n * @param result - The result to check\n * @returns A type predicate indicating if the result is an Ok variant\n */\nexport function isOk<T, E>(\n result: Result<T, E>,\n): result is {\n readonly ok: true;\n readonly value: T;\n readonly [RESULT_BRAND]: 'ok';\n} {\n return result.ok;\n}\n\n/**\n * Type guard that checks if a Result is an Error variant.\n *\n * @example\n * const result: Result<number, string> = err(\"error\");\n * if (isErr(result)) {\n * // TypeScript knows result.error exists here\n * console.log(result.error);\n * }\n *\n * @param result - The result to check\n * @returns A type predicate indicating if the result is an Error variant\n */\nexport function isErr<T, E>(\n result: Result<T, E>,\n): result is {\n readonly ok: false;\n readonly error: E;\n readonly [RESULT_BRAND]: 'error';\n} {\n return !result.ok;\n}\n\n/**\n * Maps the value inside a Result using a transformation function.\n *\n * @example\n * const result: Result<number, string> = ok(123);\n * const transformed: Result<string, string> = map(result, (value) => value.toString());\n *\n * @param result - The Result to transform\n * @param fn - The function to apply to the contained value\n * @returns A new Result containing the transformed value, or the original error if the input was an error\n */\nexport function map<T, E, U>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> {\n return result.ok ? ok(fn(result.value)) : result;\n}\n\n/**\n * Maps the error inside a Result using a transformation function.\n *\n * @example\n * const result: Result<number, string> = err(\"error\");\n * const transformed: Result<number, Error> = mapErr(result, (err) => new Error(err));\n *\n * @param result - The Result to transform\n * @param fn - The function to apply to the contained error\n * @returns A new Result containing the transformed error, or the original value if the input was ok\n */\nexport function mapErr<T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F> {\n return result.ok ? result : err(fn(result.error));\n}\n\n/**\n * Maps the value inside a Result using a transformation function that returns a Result.\n *\n * @example\n * const result: Result<number, string> = ok(123);\n * const transformed: Result<string, string> = flatMap(result, (value) => ok(value.toString()));\n *\n * @param result - The Result to transform\n * @param fn - The function to apply to the contained value, returning a Result\n * @returns The Result returned by the transformation function, or the original error if the input was an error\n */\nexport function flatMap<T, E, U>(result: Result<T, E>, fn: (value: T) => Result<U, E>): Result<U, E> {\n return result.ok ? fn(result.value) : result;\n}\n\n/**\n * Maps both the value and error of a Result using separate transformation functions.\n * This is equivalent to chaining map and mapErr, but more concise.\n *\n * @example\n * const result: Result<number, string> = ok(123);\n * const transformed = bimap(\n * result,\n * (value) => value.toString(),\n * (error) => new Error(error)\n * ); // ok(\"123\")\n *\n * const error: Result<number, string> = err(\"failed\");\n * const transformed2 = bimap(\n * error,\n * (value) => value.toString(),\n * (error) => new Error(error)\n * ); // err(Error(\"failed\"))\n *\n * @param result - The Result to transform\n * @param okFn - The function to apply to the contained value if Ok\n * @param errFn - The function to apply to the contained error if Err\n * @returns A new Result with both branches transformed\n */\nexport function bimap<T, E, U, F>(result: Result<T, E>, okFn: (value: T) => U, errFn: (error: E) => F): Result<U, F> {\n return result.ok ? ok(okFn(result.value)) : err(errFn(result.error));\n}\n\n/**\n * Filters a Result based on a predicate function.\n *\n * @example\n * const result: Result<number, string> = ok(123);\n * const filtered: Result<number, string> = filter(result, value => value > 100, \"Value too small\"); // still Ok(123)\n * const filtered2: Result<number, string> = filter(result, value => value > 200, \"Value too small\"); // Err(\"Value too small\")\n *\n * @param result - The Result to filter\n * @param predicate - A function that determines if the value should be kept\n * @param error - The error to return if the predicate fails\n * @returns The original Result if it contains a value that satisfies the predicate, otherwise an Error\n */\nexport function filter<T, E>(result: Result<T, E>, predicate: (value: T) => boolean, error: E): Result<T, E> {\n return result.ok && predicate(result.value) ? result : err(error);\n}\n\n/**\n * Unwraps the value inside a Result, throwing an error if the Result is an error.\n *\n * @remarks\n * This function is intended for prototyping only and should not be used in production.\n * In production code, prefer using pattern matching or `unwrapOr` to handle both Ok and Error cases safely.\n *\n * @example\n * const result: Result<number, string> = ok(123);\n * const value: number = unwrap(result);\n *\n * // With custom error message\n * try {\n * const badResult: Result<number, string> = err(\"Invalid data\");\n * unwrap(badResult, \"Custom error message\");\n * } catch (error) {\n * // Error will contain \"Custom error message\" instead of the default\n * }\n *\n * @param result - The Result to unwrap\n * @param errorMsg - Optional custom error message to use if Result is an error\n * @returns The contained value\n * @throws If the Result is an error\n */\nexport function unwrap<T, E>(result: Result<T, E>, errorMsg?: string): T {\n if (result.ok) {\n return result.value;\n } else {\n throw new Error(errorMsg || `Cannot unwrap an error Result: ${String(result.error)}`);\n }\n}\n\n/**\n * Unwraps the value inside a Result, providing a default value if the Result is an error.\n *\n * @example\n * const result: Result<number, string> = err(\"error\");\n * const value: number = unwrapOr(result, 123);\n *\n * @param result - The Result to unwrap\n * @param defaultValue - The value to return if the Result is an error\n * @returns The contained value, or the default value if the Result is an error\n */\nexport function unwrapOr<T, E>(result: Result<T, E>, defaultValue: T): T {\n return result.ok ? result.value : defaultValue;\n}\n\n/**\n * Unwraps the value inside a Result, calling a function to generate a default value if the Result is an error.\n * Unlike unwrapOr, this only computes the default when needed.\n *\n * @example\n * const result: Result<number, string> = err(\"error\");\n * const value = unwrapOrElse(result, () => expensiveComputation());\n *\n * @param result - The Result to unwrap\n * @param defaultFn - A function that returns a default value if the Result is an error\n * @returns The contained value, or the result of calling defaultFn if the Result is an error\n */\nexport function unwrapOrElse<T, E>(result: Result<T, E>, defaultFn: () => T): T {\n return result.ok ? result.value : defaultFn();\n}\n\n/**\n * Combines an array of Results into a single Result containing an array of values.\n * Returns an Error if any Result in the array is an Error, using the first encountered error.\n * If an empty array is provided, returns `ok([])` (an Ok containing an empty array).\n *\n * @example\n * const results = [ok(1), ok(2), ok(3)];\n * const combined = combine(results); // ok([1, 2, 3])\n *\n * const withError = [ok(1), err(\"error\"), ok(3)];\n * const result = combine(withError); // err(\"error\")\n *\n * const emptyResults = [];\n * const emptyResult = combine(emptyResults); // ok([])\n *\n * @param results - An array of Results to combine\n * @returns A Result containing an array of all values if all inputs are Ok, or the first Error if any input is an Error\n */\n\n// Tuple-preserving overloads with error type unions\nexport function combine<T1, E1>(results: readonly [Result<T1, E1>]): Result<[T1], E1>;\nexport function combine<T1, E1, T2, E2>(results: readonly [Result<T1, E1>, Result<T2, E2>]): Result<[T1, T2], E1 | E2>;\nexport function combine<T1, E1, T2, E2, T3, E3>(\n results: readonly [Result<T1, E1>, Result<T2, E2>, Result<T3, E3>],\n): Result<[T1, T2, T3], E1 | E2 | E3>;\nexport function combine<T1, E1, T2, E2, T3, E3, T4, E4>(\n results: readonly [Result<T1, E1>, Result<T2, E2>, Result<T3, E3>, Result<T4, E4>],\n): Result<[T1, T2, T3, T4], E1 | E2 | E3 | E4>;\nexport function combine<T1, E1, T2, E2, T3, E3, T4, E4, T5, E5>(\n results: readonly [Result<T1, E1>, Result<T2, E2>, Result<T3, E3>, Result<T4, E4>, Result<T5, E5>],\n): Result<[T1, T2, T3, T4, T5], E1 | E2 | E3 | E4 | E5>;\nexport function combine<T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6>(\n results: readonly [Result<T1, E1>, Result<T2, E2>, Result<T3, E3>, Result<T4, E4>, Result<T5, E5>, Result<T6, E6>],\n): Result<[T1, T2, T3, T4, T5, T6], E1 | E2 | E3 | E4 | E5 | E6>;\nexport function combine<T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7>(\n results: readonly [\n Result<T1, E1>,\n Result<T2, E2>,\n Result<T3, E3>,\n Result<T4, E4>,\n Result<T5, E5>,\n Result<T6, E6>,\n Result<T7, E7>,\n ],\n): Result<[T1, T2, T3, T4, T5, T6, T7], E1 | E2 | E3 | E4 | E5 | E6 | E7>;\nexport function combine<T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7, T8, E8>(\n results: readonly [\n Result<T1, E1>,\n Result<T2, E2>,\n Result<T3, E3>,\n Result<T4, E4>,\n Result<T5, E5>,\n Result<T6, E6>,\n Result<T7, E7>,\n Result<T8, E8>,\n ],\n): Result<[T1, T2, T3, T4, T5, T6, T7, T8], E1 | E2 | E3 | E4 | E5 | E6 | E7 | E8>;\nexport function combine<T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7, T8, E8, T9, E9>(\n results: readonly [\n Result<T1, E1>,\n Result<T2, E2>,\n Result<T3, E3>,\n Result<T4, E4>,\n Result<T5, E5>,\n Result<T6, E6>,\n Result<T7, E7>,\n Result<T8, E8>,\n Result<T9, E9>,\n ],\n): Result<[T1, T2, T3, T4, T5, T6, T7, T8, T9], E1 | E2 | E3 | E4 | E5 | E6 | E7 | E8 | E9>;\nexport function combine<T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7, T8, E8, T9, E9, T10, E10>(\n results: readonly [\n Result<T1, E1>,\n Result<T2, E2>,\n Result<T3, E3>,\n Result<T4, E4>,\n Result<T5, E5>,\n Result<T6, E6>,\n Result<T7, E7>,\n Result<T8, E8>,\n Result<T9, E9>,\n Result<T10, E10>,\n ],\n): Result<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10], E1 | E2 | E3 | E4 | E5 | E6 | E7 | E8 | E9 | E10>;\nexport function combine<T, E>(results: readonly Result<T, E>[]): Result<T[], E>;\nexport function combine<T, E>(results: readonly Result<T, E>[]): Result<T[], E> {\n const values: T[] = [];\n\n for (const result of results) {\n if (!result.ok) return result;\n values.push(result.value);\n }\n\n return ok(values);\n}\n\n/**\n * Combines an array of Results into a single Result containing an array of values.\n * Unlike combine, this collects all errors instead of returning just the first one.\n * If all Results are Ok, returns an Ok containing an array of all values.\n * If any Results are Error, returns an Error containing an array of all errors.\n *\n * @example\n * const results = [ok(1), ok(2), ok(3)];\n * const combined = combineAll(results); // ok([1, 2, 3])\n *\n * const withErrors = [ok(1), err(\"error1\"), ok(3), err(\"error2\")];\n * const result = combineAll(withErrors); // err([\"error1\", \"error2\"])\n *\n * const emptyResults = [];\n * const emptyResult = combineAll(emptyResults); // ok([])\n *\n * @param results - An array of Results to combine\n * @returns A Result containing an array of all values if all inputs are Ok, or an array of all errors if any input is an Error\n */\n\n// Tuple-preserving overloads with error arrays\nexport function combineAll<T1, E1>(results: readonly [Result<T1, E1>]): Result<[T1], E1[]>;\nexport function combineAll<T1, E1, T2, E2>(\n results: readonly [Result<T1, E1>, Result<T2, E2>],\n): Result<[T1, T2], (E1 | E2)[]>;\nexport function combineAll<T1, E1, T2, E2, T3, E3>(\n results: readonly [Result<T1, E1>, Result<T2, E2>, Result<T3, E3>],\n): Result<[T1, T2, T3], (E1 | E2 | E3)[]>;\nexport function combineAll<T1, E1, T2, E2, T3, E3, T4, E4>(\n results: readonly [Result<T1, E1>, Result<T2, E2>, Result<T3, E3>, Result<T4, E4>],\n): Result<[T1, T2, T3, T4], (E1 | E2 | E3 | E4)[]>;\nexport function combineAll<T1, E1, T2, E2, T3, E3, T4, E4, T5, E5>(\n results: readonly [Result<T1, E1>, Result<T2, E2>, Result<T3, E3>, Result<T4, E4>, Result<T5, E5>],\n): Result<[T1, T2, T3, T4, T5], (E1 | E2 | E3 | E4 | E5)[]>;\nexport function combineAll<T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6>(\n results: readonly [Result<T1, E1>, Result<T2, E2>, Result<T3, E3>, Result<T4, E4>, Result<T5, E5>, Result<T6, E6>],\n): Result<[T1, T2, T3, T4, T5, T6], (E1 | E2 | E3 | E4 | E5 | E6)[]>;\nexport function combineAll<T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7>(\n results: readonly [\n Result<T1, E1>,\n Result<T2, E2>,\n Result<T3, E3>,\n Result<T4, E4>,\n Result<T5, E5>,\n Result<T6, E6>,\n Result<T7, E7>,\n ],\n): Result<[T1, T2, T3, T4, T5, T6, T7], (E1 | E2 | E3 | E4 | E5 | E6 | E7)[]>;\nexport function combineAll<T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7, T8, E8>(\n results: readonly [\n Result<T1, E1>,\n Result<T2, E2>,\n Result<T3, E3>,\n Result<T4, E4>,\n Result<T5, E5>,\n Result<T6, E6>,\n Result<T7, E7>,\n Result<T8, E8>,\n ],\n): Result<[T1, T2, T3, T4, T5, T6, T7, T8], (E1 | E2 | E3 | E4 | E5 | E6 | E7 | E8)[]>;\nexport function combineAll<T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7, T8, E8, T9, E9>(\n results: readonly [\n Result<T1, E1>,\n Result<T2, E2>,\n Result<T3, E3>,\n Result<T4, E4>,\n Result<T5, E5>,\n Result<T6, E6>,\n Result<T7, E7>,\n Result<T8, E8>,\n Result<T9, E9>,\n ],\n): Result<[T1, T2, T3, T4, T5, T6, T7, T8, T9], (E1 | E2 | E3 | E4 | E5 | E6 | E7 | E8 | E9)[]>;\nexport function combineAll<T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6, T7, E7, T8, E8, T9, E9, T10, E10>(\n results: readonly [\n Result<T1, E1>,\n Result<T2, E2>,\n Result<T3, E3>,\n Result<T4, E4>,\n Result<T5, E5>,\n Result<T6, E6>,\n Result<T7, E7>,\n Result<T8, E8>,\n Result<T9, E9>,\n Result<T10, E10>,\n ],\n): Result<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10], (E1 | E2 | E3 | E4 | E5 | E6 | E7 | E8 | E9 | E10)[]>;\nexport function combineAll<T, E>(results: readonly Result<T, E>[]): Result<T[], E[]>;\nexport function combineAll<T, E>(results: readonly Result<T, E>[]): Result<T[], E[]> {\n const errors: E[] = [];\n const values: T[] = [];\n\n for (const result of results) {\n if (result.ok) {\n values.push(result.value);\n } else {\n errors.push(result.error);\n }\n }\n\n return errors.length > 0 ? err(errors) : ok(values);\n}\n\n/**\n * Pattern matches on a Result to handle both Ok and Error cases.\n *\n * @example\n * const result = ok(42);\n * const message = match(result, {\n * ok: (value) => `Got value: ${value}`,\n * err: (error) => `Got error: ${error}`\n * }); // \"Got value: 42\"\n *\n * @param result - The Result to match against\n * @param patterns - An object containing handler functions for Ok and Error cases\n * @returns The result of calling the appropriate handler function\n */\nexport function match<T, E, R>(\n result: Result<T, E>,\n patterns: {\n ok: (value: T) => R;\n err: (error: E) => R;\n },\n): R {\n if (isOk(result)) {\n const okFn = patterns.ok;\n return okFn(result.value);\n } else {\n const errFn = patterns.err;\n return errFn(result.error);\n }\n}\n\n/**\n * Executes a callback with the value if the Result is Ok, without changing the Result.\n * Useful for side effects like logging while maintaining a processing chain.\n *\n * @example\n * const finalResult = pipe(\n * ok(123),\n * r => map(r, x => x * 2),\n * r => tap(r, x => console.log(`Value: ${x}`)), // Logs but doesn't change the Result\n * r => filter(r, x => x > 200, \"Value too small\")\n * );\n *\n * @param result - The Result to tap into\n * @param fn - The function to execute with the value if Ok\n * @returns The original Result unchanged\n */\nexport function tap<T, E>(result: Result<T, E>, fn: (value: T) => void): Result<T, E> {\n if (isOk(result)) {\n const callback = fn;\n callback(result.value);\n }\n return result;\n}\n\n/**\n * Executes a callback with the error if the Result is an Error, without changing the Result.\n * Useful for side effects like logging while maintaining a processing chain.\n *\n * @example\n * const finalResult = pipe(\n * err(\"something went wrong\"),\n * r => tapErr(r, e => console.error(`Error: ${e}`)), // Logs but doesn't change the Result\n * r => mapErr(r, e => new Error(e))\n * );\n *\n * @param result - The Result to tap into\n * @param fn - The function to execute with the error if Error\n * @returns The original Result unchanged\n */\nexport function tapErr<T, E>(result: Result<T, E>, fn: (error: E) => void): Result<T, E> {\n if (isErr(result)) {\n const callback = fn;\n callback(result.error);\n }\n return result;\n}\n\n/**\n * Converts a Result to an Option.\n * If the Result is Ok, returns a Some variant with the value.\n * If the Result is an Error, returns a None variant.\n *\n * @example\n * import { some, none } from \"@/option\";\n *\n * const option1 = mapToOption(ok(123)); // some(123)\n * const option2 = mapToOption(err(\"error\")); // none()\n *\n * @param result - The Result to convert\n * @returns An Option containing the value if Ok, or None if Error\n */\nexport function mapToOption<T, E>(result: Result<T, E>): Option<T> {\n return result.ok ? some(result.value) : none();\n}\n\n/**\n * Safely executes a function that might throw and converts the result into a Result type.\n * If the function executes successfully, returns an Ok variant with the return value.\n * If the function throws an error, returns an Error variant containing the error message as a string.\n *\n * @example\n * const parseJson = (str: string) => fromTry(() => JSON.parse(str));\n *\n * const validResult = parseJson('{\"name\":\"John\"}'); // ok({ name: 'John' })\n * const invalidResult = parseJson('invalid json'); // err(\"Unexpected token...\")\n *\n * @param f - The function to execute\n * @returns A Result containing either the function's return value or the error message\n */\nexport function fromTry<T>(f: () => T): Result<T, string> {\n try {\n return ok(f());\n } catch (error) {\n return err(error instanceof Error ? error.message : String(error));\n }\n}\n\n/**\n * Safely executes a function that might throw and converts the result into a Result type.\n * Unlike fromTry, this preserves the full Error object instead of just the message.\n * Use this when you need access to error stack traces or custom error properties.\n *\n * @example\n * const result = fromTryWithError(() => JSON.parse('invalid'));\n * if (isErr(result)) {\n * console.log(result.error.stack); // Access to full stack trace\n * }\n *\n * @param f - The function to execute\n * @returns A Result containing either the function's return value or the full Error object\n */\nexport function fromTryWithError<T>(f: () => T): Result<T, Error> {\n try {\n return ok(f());\n } catch (error) {\n return err(error instanceof Error ? error : new Error(String(error)));\n }\n}\n\n/**\n * Converts a Promise to a Result, capturing any errors that occur during promise resolution.\n * Returns error messages as strings for simplicity.\n *\n * @example\n * const result = await fromPromise(fetch('https://api.example.com/data'));\n * if (isErr(result)) {\n * console.log(result.error); // Error message as string\n * }\n *\n * @param promise - The Promise to convert\n * @returns A Promise that resolves to a Result with string error messages\n */\nexport async function fromPromise<T>(promise: Promise<T>): Promise<Result<T, string>> {\n try {\n const value = await promise;\n return ok(value);\n } catch (error) {\n return err(error instanceof Error ? error.message : String(error));\n }\n}\n\n/**\n * Converts a Promise to a Result, preserving the full error object or custom error type.\n * Use this when you need access to error stack traces, custom properties, or specific error types.\n *\n * @example\n * // With default error handling (preserves full error)\n * const result = await fromPromiseWithError(fetch('https://api.example.com/data'));\n *\n * @example\n * // With specific error type and transformer\n * type ApiError = { code: number; message: string };\n *\n * const result = await fromPromiseWithError<Response, ApiError>(\n * fetch('https://api.example.com/data'),\n * (error) => ({\n * code: error instanceof Error ? 500 : 400,\n * message: error instanceof Error ? error.message : String(error)\n * })\n * );\n *\n * @param promise - The Promise to convert\n * @param errorFn - Optional function to transform caught errors to the expected error type\n * @returns A Promise that resolves to a Result\n */\nexport async function fromPromiseWithError<T, E = unknown>(\n promise: Promise<T>,\n errorFn: (error: unknown) => E = (error) => error as unknown as E,\n): Promise<Result<T, E>> {\n try {\n const value = await promise;\n return ok(value);\n } catch (error) {\n return err(errorFn(error));\n }\n}\n\n/**\n * Converts a Result to a Promise.\n *\n * @example\n * const result = ok(123);\n * const promise = toPromise(result);\n * const value = await promise; // 123\n *\n * @param result - The Result to convert\n * @returns A Promise that resolves to the value if Ok, or rejects with the error if Error\n */\nexport function toPromise<T, E>(result: Result<T, E>): Promise<T> {\n return result.ok ? Promise.resolve(result.value) : Promise.reject(result.error);\n}\n\n/**\n * Chains an asynchronous operation that returns a Result.\n *\n * @remarks\n * This function is the async counterpart to {@link flatMap}. It accepts either\n * a `Result` or a `Promise<Result>` and a step function that may be synchronous\n * or asynchronous, but must return a `Result` (or `Promise<Result>`). If the\n * input is an Ok, the step is invoked and awaited; if the input is an Err, the\n * same error is returned and the step is not called.\n *\n * This design keeps your core pipeline synchronous in structure while enabling\n * async effects at the boundaries (e.g., database, HTTP) without nested flows.\n *\n * @example\n * // Using with a Result input and async step\n * const r1 = await andThen(ok(2 as const), async (n) => ok(n * 3)); // Ok(6)\n *\n * @example\n * // Using with a Promise<Result> input (e.g., previous async step)\n * const r2 = await andThen(fromPromise(Promise.resolve(2)), async (n) => ok(n * 3)); // Ok(6)\n *\n * @example\n * // Skips step on Err\n * const r3 = await andThen(err<number, string>(\"boom\"), async (n) => ok(n * 3)); // Err(\"boom\")\n *\n * @param input - A Result or Promise<Result> to chain from\n * @param fn - A function invoked when input is Ok; may be sync or async but returns a Result\n * @returns A Promise that resolves to a Result of the chained operation\n */\nexport function andThen<T, E, U>(\n input: Result<T, E>,\n fn: (value: T) => Result<U, E> | Promise<Result<U, E>>,\n): Promise<Result<U, E>>;\nexport function andThen<T, E, U>(\n input: Promise<Result<T, E>>,\n fn: (value: T) => Result<U, E> | Promise<Result<U, E>>,\n): Promise<Result<U, E>>;\nexport async function andThen<T, E, U>(\n input: Result<T, E> | Promise<Result<T, E>>,\n fn: (value: T) => Result<U, E> | Promise<Result<U, E>>,\n): Promise<Result<U, E>> {\n const settled = await input;\n if (settled.ok) {\n return await fn(settled.value);\n }\n return err(settled.error);\n}\n"]}
|