functype 0.9.0 → 0.9.1
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/dist/{Either-C-PDWX2U.d.ts → Either-BHep7I0d.d.ts} +7 -2
- package/dist/{Serializable-D9GKEo30.d.ts → Serializable-BbKuhDDL.d.ts} +14 -3
- package/dist/branded/index.d.ts +4 -6
- package/dist/branded/index.mjs +1 -1
- package/dist/chunk-GHBOC52G.mjs +43 -0
- package/dist/chunk-GHBOC52G.mjs.map +1 -0
- package/dist/chunk-R2TQJN3P.mjs +2 -0
- package/dist/chunk-R2TQJN3P.mjs.map +1 -0
- package/dist/either/index.d.ts +2 -2
- package/dist/either/index.mjs +1 -1
- package/dist/fpromise/index.d.ts +2 -2
- package/dist/fpromise/index.mjs +1 -1
- package/dist/index.d.ts +28 -20
- package/dist/index.mjs +1 -1
- package/dist/list/index.d.ts +2 -2
- package/dist/list/index.mjs +1 -1
- package/dist/map/index.d.ts +2 -2
- package/dist/map/index.mjs +1 -1
- package/dist/option/index.d.ts +2 -2
- package/dist/option/index.mjs +1 -1
- package/dist/set/index.d.ts +2 -2
- package/dist/set/index.mjs +1 -1
- package/dist/try/index.d.ts +2 -2
- package/dist/try/index.mjs +1 -1
- package/dist/tuple/index.d.ts +1 -1
- package/package.json +3 -3
- package/readme/BUNDLE_OPTIMIZATION.md +74 -0
- package/readme/FPromise-Assessment.md +43 -0
- package/readme/HKT.md +110 -0
- package/readme/ROADMAP.md +113 -0
- package/readme/TASK-TODO.md +33 -0
- package/readme/TUPLE-EXAMPLES.md +76 -0
- package/readme/TaskMigration.md +129 -0
- package/readme/ai-guide.md +406 -0
- package/readme/examples.md +2093 -0
- package/readme/quick-reference.md +514 -0
- package/readme/task-error-handling.md +283 -0
- package/readme/tasks.md +203 -0
- package/readme/type-index.md +238 -0
- package/dist/chunk-4EYCKDDF.mjs +0 -43
- package/dist/chunk-4EYCKDDF.mjs.map +0 -1
- package/dist/chunk-V6LFV5LW.mjs +0 -2
- package/dist/chunk-V6LFV5LW.mjs.map +0 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function e(r,n){let d=n,t={unbrand(){return n},unwrap(){return n},toString(){return String(n)}};return typeof n=="number"&&Object.assign(t,{valueOf(){return n}}),Object.assign(d,t)}function a(r){return r.unbrand()}function s(r,n){return r!=null}function o(r){return n=>e(r,n)}var i=r=>n=>e(r,n),K=r=>n=>e(r,n),B=r=>n=>e(r,n);export{e as a,a as b,s as c,o as d,i as e,K as f,B as g};//# sourceMappingURL=chunk-R2TQJN3P.mjs.map
|
|
2
|
+
//# sourceMappingURL=chunk-R2TQJN3P.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/branded/Brand.ts"],"names":["Brand","brand","value","branded","methods","unbrand","hasBrand","createBrander","BrandedString","BrandedNumber","BrandedBoolean"],"mappings":"AAsBO,SAASA,CAAAA,CAA2BC,EAAUC,CAAAA,CAAuB,CAC1E,IAAMC,CAAAA,CAAUD,CAAAA,CACVE,EAAU,CACd,OAAA,EAAa,CACX,OAAOF,CACT,EACA,MAAA,EAAY,CACV,OAAOA,CACT,CAAA,CACA,QAAA,EAAmB,CACjB,OAAO,MAAA,CAAOA,CAAK,CACrB,CACF,EAGA,OAAI,OAAOA,GAAU,QAAA,EACnB,MAAA,CAAO,OAAOE,CAAAA,CAAS,CACrB,SAAkB,CAChB,OAAOF,CACT,CACF,CAAC,EAGI,MAAA,CAAO,MAAA,CAAOC,CAAAA,CAASC,CAAO,CACvC,CAOO,SAASC,CAAAA,CAAWF,CAAAA,CAA8B,CACvD,OAAOA,CAAAA,CAAQ,SACjB,CAaO,SAASG,CAAAA,CAA8BJ,CAAAA,CAAgBD,EAAgC,CAG5F,OAAOC,GAAU,IACnB,CAOO,SAASK,CAAAA,CAAmCN,CAAAA,CAAU,CAC3D,OAAQC,CAAAA,EAA0BF,CAAAA,CAAMC,EAAOC,CAAK,CACtD,CAQO,IAAMM,CAAAA,CACQP,GAClBC,CAAAA,EACCF,CAAAA,CAAMC,CAAAA,CAAOC,CAAK,CAAA,CAETO,CAAAA,CACQR,GAClBC,CAAAA,EACCF,CAAAA,CAAMC,EAAOC,CAAK,CAAA,CAETQ,EACQT,CAAAA,EAClBC,CAAAA,EACCF,CAAAA,CAAMC,CAAAA,CAAOC,CAAK","file":"chunk-R2TQJN3P.mjs","sourcesContent":["// The brand symbol type with instance methods\nexport type Brand<K extends string, T> = T & {\n readonly __brand: K\n readonly unbrand: () => T\n readonly unwrap: () => T\n}\n\n// Utility type to extract the underlying type from a branded type\nexport type Unbrand<T> = T extends Brand<string, infer U> ? U : never\n\n// Utility type to extract the brand from a branded type\nexport type ExtractBrand<T> = T extends Brand<infer K, unknown> ? K : never\n\n/**\n * Brand is a utility for creating nominal typing in TypeScript.\n * It allows for creating distinct types that are structurally identical\n * but considered different by TypeScript's type system.\n *\n * @param brand - The brand name\n * @param value - The value to brand\n * @returns The branded value with unbrand/unwrap methods\n */\nexport function Brand<K extends string, T>(brand: K, value: T): Brand<K, T> {\n const branded = value as Brand<K, T>\n const methods = {\n unbrand(): T {\n return value\n },\n unwrap(): T {\n return value\n },\n toString(): string {\n return String(value)\n },\n }\n\n // Add valueOf for numeric types to support numeric operations\n if (typeof value === \"number\") {\n Object.assign(methods, {\n valueOf(): number {\n return value as number\n },\n })\n }\n\n return Object.assign(branded, methods)\n}\n\n/**\n * Helper to remove a brand from a value\n * @param branded - The branded value\n * @returns The original value without the brand\n */\nexport function unbrand<T>(branded: Brand<string, T>): T {\n return branded.unbrand()\n}\n\n/**\n * Type guard for checking if a value has a specific brand\n * @param value - The value to check\n * @param brand - The brand to check for\n * @returns True if the value has the specified brand\n *\n * Note: Since brands are phantom types that exist only at compile time,\n * this function can only provide a runtime approximation. It always returns true\n * for non-null values, as we have no way to actually check the brand at runtime.\n * This function is primarily for API consistency and documentation purposes.\n */\nexport function hasBrand<K extends string, T>(value: unknown, brand: K): value is Brand<K, T> {\n // In a phantom type system, we can't actually check the brand at runtime\n // We can only verify the value exists\n return value !== null && value !== undefined\n}\n\n/**\n * Create a branded type constructor for a specific brand\n * @param brand - The brand name\n * @returns A function that brands values with the specified brand\n */\nexport function createBrander<K extends string, T>(brand: K) {\n return (value: T): Brand<K, T> => Brand(brand, value)\n}\n\n// Common branded primitive types\nexport type BrandedString<K extends string> = Brand<K, string>\nexport type BrandedNumber<K extends string> = Brand<K, number>\nexport type BrandedBoolean<K extends string> = Brand<K, boolean>\n\n// Factory for common primitive branded types\nexport const BrandedString =\n <K extends string>(brand: K) =>\n (value: string): BrandedString<K> =>\n Brand(brand, value)\n\nexport const BrandedNumber =\n <K extends string>(brand: K) =>\n (value: number): BrandedNumber<K> =>\n Brand(brand, value)\n\nexport const BrandedBoolean =\n <K extends string>(brand: K) =>\n (value: boolean): BrandedBoolean<K> =>\n Brand(brand, value)\n"]}
|
package/dist/either/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { E as Either, c as Left, R as Right, b as TestEither, f as TypeCheckLeft, e as TypeCheckRight, d as isLeft, i as isRight, t as tryCatch, g as tryCatchAsync } from '../Either-
|
|
2
|
-
import '../Serializable-
|
|
1
|
+
export { E as Either, c as Left, R as Right, b as TestEither, f as TypeCheckLeft, e as TypeCheckRight, d as isLeft, i as isRight, t as tryCatch, g as tryCatchAsync } from '../Either-BHep7I0d.js';
|
|
2
|
+
import '../Serializable-BbKuhDDL.js';
|
package/dist/either/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{
|
|
1
|
+
export{o as Either,h as Left,g as Right,m as TypeCheckLeft,l as TypeCheckRight,j as isLeft,i as isRight,k as tryCatch,n as tryCatchAsync}from'../chunk-GHBOC52G.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-R2TQJN3P.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/fpromise/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { E as Either } from '../Either-
|
|
2
|
-
import { T as Type } from '../Serializable-
|
|
1
|
+
import { E as Either } from '../Either-BHep7I0d.js';
|
|
2
|
+
import { T as Type } from '../Serializable-BbKuhDDL.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Error context information that provides additional metadata about errors.
|
package/dist/fpromise/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{
|
|
1
|
+
export{I as FPromise,H as FPromiseCompanion}from'../chunk-GHBOC52G.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-R2TQJN3P.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Brand } from './branded/index.js';
|
|
2
2
|
export { BrandedBoolean, BrandedNumber, BrandedString, ExtractBrand, Unbrand, createBrander, hasBrand, unbrand } from './branded/index.js';
|
|
3
|
-
import { O as Option, E as Either, L as List, F as FunctypeBase, a as Extractable, T as Traversable, M as Matchable } from './Either-
|
|
4
|
-
export { A as Applicative,
|
|
5
|
-
import { T as Type, a as Typeable, F as Foldable, P as Pipe, S as Serializable } from './Serializable-
|
|
6
|
-
export {
|
|
3
|
+
import { O as Option, E as Either, L as List, F as FunctypeBase, a as Extractable, T as Traversable, M as Matchable } from './Either-BHep7I0d.js';
|
|
4
|
+
export { A as Applicative, q as AsyncMonad, C as Collection, o as CollectionOps, p as ContainerOps, r as Functor, j as Functype, k as FunctypeCollection, c as Left, l as MatchableUtils, s as Monad, N as None, m as OptionConstructor, R as Right, n as Set, S as Some, b as TestEither, f as TypeCheckLeft, e as TypeCheckRight, h as isExtractable, d as isLeft, i as isRight, t as tryCatch, g as tryCatchAsync } from './Either-BHep7I0d.js';
|
|
5
|
+
import { T as Type, a as Typeable, F as Foldable, P as Pipe, S as Serializable } from './Serializable-BbKuhDDL.js';
|
|
6
|
+
export { b as SerializationMethods } from './Serializable-BbKuhDDL.js';
|
|
7
7
|
import { FPromise } from './fpromise/index.js';
|
|
8
8
|
export { ErrorContext, FPromiseCompanion } from './fpromise/index.js';
|
|
9
9
|
import { Try } from './try/index.js';
|
|
@@ -11,13 +11,6 @@ export { TypeNames } from './try/index.js';
|
|
|
11
11
|
export { Map, SafeTraversable } from './map/index.js';
|
|
12
12
|
export { Tuple } from './tuple/index.js';
|
|
13
13
|
|
|
14
|
-
/**
|
|
15
|
-
* A brand with runtime validation
|
|
16
|
-
* @example
|
|
17
|
-
* const Age = ValidatedBrand("Age", (n: number) => n >= 0 && n <= 150)
|
|
18
|
-
* const myAge = Age.of(25) // Option<Brand<"Age", number>>
|
|
19
|
-
* const invalid = Age.of(-5) // None
|
|
20
|
-
*/
|
|
21
14
|
type ValidatedBrand<K extends string, T> = {
|
|
22
15
|
readonly brand: K;
|
|
23
16
|
readonly validate: (value: T) => boolean;
|
|
@@ -144,6 +137,7 @@ declare function PatternString(brand: string, pattern: RegExp): ValidatedBrand<s
|
|
|
144
137
|
*/
|
|
145
138
|
declare function Companion<ObjectF extends object, CompanionF extends object>(object: ObjectF, companion: CompanionF): ObjectF & CompanionF;
|
|
146
139
|
|
|
140
|
+
/** @internal */
|
|
147
141
|
type LazyCondChain<T> = {
|
|
148
142
|
when: (condition: () => boolean, value: () => T) => LazyCondChain<T>;
|
|
149
143
|
elseWhen: (condition: () => boolean, value: () => T) => LazyCondChain<T>;
|
|
@@ -277,12 +271,16 @@ declare const Cond: (<T extends Type>() => Cond<T>) & {
|
|
|
277
271
|
|
|
278
272
|
/**
|
|
279
273
|
* Type-level utilities for exhaustiveness checking
|
|
274
|
+
* @internal
|
|
280
275
|
*/
|
|
281
276
|
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
|
277
|
+
/** @internal */
|
|
282
278
|
type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;
|
|
279
|
+
/** @internal */
|
|
283
280
|
type RequireExhaustive<T, Cases> = IsUnion<T> extends true ? (keyof Cases extends T ? (T extends keyof Cases ? Cases : never) : never) : Cases;
|
|
284
281
|
/**
|
|
285
282
|
* Pattern types for nested matching
|
|
283
|
+
* @internal
|
|
286
284
|
*/
|
|
287
285
|
type Pattern<T> = T | {
|
|
288
286
|
[K in keyof T]?: Pattern<T[K]>;
|
|
@@ -291,6 +289,7 @@ type Pattern<T> = T | {
|
|
|
291
289
|
};
|
|
292
290
|
/**
|
|
293
291
|
* Extract result from pattern
|
|
292
|
+
* @internal
|
|
294
293
|
*/
|
|
295
294
|
type PatternResult<T, R> = R | ((matched: T) => R);
|
|
296
295
|
/**
|
|
@@ -529,6 +528,9 @@ declare function Base<T>(type: string, body: T): T & {
|
|
|
529
528
|
* The identifier name for Throwable type
|
|
530
529
|
*/
|
|
531
530
|
declare const NAME: "Throwable";
|
|
531
|
+
/**
|
|
532
|
+
* @internal
|
|
533
|
+
*/
|
|
532
534
|
type ThrowableType = Error & Typeable<typeof NAME> & {
|
|
533
535
|
readonly data?: unknown;
|
|
534
536
|
readonly cause?: Error;
|
|
@@ -1222,13 +1224,20 @@ type EitherKind<E> = <A>(a: A) => Either<E, A>;
|
|
|
1222
1224
|
type TryKind = <A>(a: A) => Try<A>;
|
|
1223
1225
|
/**
|
|
1224
1226
|
* Generic container types for type-safe operations
|
|
1227
|
+
* @internal
|
|
1225
1228
|
*/
|
|
1226
1229
|
type Mappable<T> = {
|
|
1227
1230
|
map<U>(f: (value: T) => U): unknown;
|
|
1228
1231
|
};
|
|
1232
|
+
/**
|
|
1233
|
+
* @internal
|
|
1234
|
+
*/
|
|
1229
1235
|
type Flattenable = {
|
|
1230
1236
|
flatten(): unknown;
|
|
1231
1237
|
};
|
|
1238
|
+
/**
|
|
1239
|
+
* @internal
|
|
1240
|
+
*/
|
|
1232
1241
|
type FlatMappable<T> = {
|
|
1233
1242
|
flatMap<U>(f: (value: T) => unknown): unknown;
|
|
1234
1243
|
};
|
|
@@ -1603,7 +1612,7 @@ type ValuableParams<Tag extends string, T, V> = {
|
|
|
1603
1612
|
value: V;
|
|
1604
1613
|
};
|
|
1605
1614
|
/**
|
|
1606
|
-
* Creates a Valuable wrapper that adds value extraction capabilities
|
|
1615
|
+
* Represents a type that can extract its inner value. Creates a Valuable wrapper that adds value extraction capabilities.
|
|
1607
1616
|
* @param params - Configuration parameters
|
|
1608
1617
|
* @module Valuable
|
|
1609
1618
|
* @category Utilities
|
|
@@ -1615,13 +1624,12 @@ declare function Valuable<Tag extends string, V, T = object>(params: ValuablePar
|
|
|
1615
1624
|
};
|
|
1616
1625
|
_tag: Tag;
|
|
1617
1626
|
};
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
type Valuable<Tag extends string, V, T = object> = ReturnType<typeof Valuable<Tag, V, T>>;
|
|
1627
|
+
type Valuable<Tag extends string, V, T = object> = Typeable<Tag, T> & {
|
|
1628
|
+
toValue: () => {
|
|
1629
|
+
_tag: Tag;
|
|
1630
|
+
value: V;
|
|
1631
|
+
};
|
|
1632
|
+
};
|
|
1625
1633
|
|
|
1626
1634
|
/**
|
|
1627
1635
|
* Stack data structure - Last In, First Out (LIFO)
|
|
@@ -1725,4 +1733,4 @@ declare const Stack: (<A extends Type>(values?: A[]) => Stack<A>) & {
|
|
|
1725
1733
|
fromBinary: <A>(binary: string) => Stack<A>;
|
|
1726
1734
|
};
|
|
1727
1735
|
|
|
1728
|
-
export { type Async, Base, BoundedNumber, BoundedString, Brand, type CancellationToken, type CancellationTokenSource, Companion, Cond, ESMap, type ESMapType, Either, type EitherKind, EmailAddress, type ErrorChainElement, type ErrorCode, type ErrorFormatterOptions, type ErrorMessage, type ErrorStatus, type ErrorWithTaskInfo, FPromise, type FieldValidation, Foldable, FoldableUtils, type FormValidation, FunctypeBase, HKT, ISO8601Date, Identity, IntegerNumber, type Kind, Lazy, LazyList, Lazy as LazyType, List, type ListKind, Match, Matchable, NAME, NonEmptyString, NonNegativeNumber, Option, type OptionKind, ParseError, PatternString, Pipe, PositiveInteger, PositiveNumber, Ref, Ref as RefType, Serializable, Stack, type Sync, type TaggedThrowable, Task, type TaskErrorInfo, TaskException, type TaskInfo, type TaskParams, TaskResult, Throwable, type ThrowableType, Traversable, Try, type TryKind, Type,
|
|
1736
|
+
export { type Async, Base, BoundedNumber, BoundedString, Brand, type CancellationToken, type CancellationTokenSource, Companion, Cond, ESMap, type ESMapType, Either, type EitherKind, EmailAddress, type ErrorChainElement, type ErrorCode, type ErrorFormatterOptions, type ErrorMessage, type ErrorStatus, type ErrorWithTaskInfo, Extractable, FPromise, type FieldValidation, Foldable, FoldableUtils, type FormValidation, FunctypeBase, HKT, ISO8601Date, Identity, IntegerNumber, type Kind, Lazy, LazyList, Lazy as LazyType, List, type ListKind, Match, Matchable, NAME, NonEmptyString, NonNegativeNumber, Option, type OptionKind, ParseError, PatternString, Pipe, PositiveInteger, PositiveNumber, Ref, Ref as RefType, Serializable, Stack, type Sync, type TaggedThrowable, Task, type TaskErrorInfo, TaskException, type TaskInfo, type TaskParams, TaskResult, Throwable, type ThrowableType, Traversable, Try, type TryKind, Type, TypedError, type TypedErrorContext, UUID, type UniversalContainer, UrlString, ValidatedBrand, Validation, type ValidationRule, type Validator, Valuable, type ValuableParams, createCancellationTokenSource, createErrorSerializer, formatError, formatStackTrace, isTaggedThrowable, safeStringify };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{
|
|
1
|
+
export{E as Base,z as BoundedNumber,A as BoundedString,C as Cond,aa as ESMap,o as Either,v as EmailAddress,I as FPromise,H as FPromiseCompanion,X as FoldableUtils,Z as HKT,y as ISO8601Date,_ as Identity,s as IntegerNumber,$ as Lazy,U as LazyList,h as Left,f as List,ba as Map,D as Match,ca as MatchableUtils,F as NAME,u as NonEmptyString,r as NonNegativeNumber,b as None,d as Option,c as OptionConstructor,S as ParseError,B as PatternString,t as PositiveInteger,q as PositiveNumber,da as Ref,g as Right,e as Set,a as Some,fa as Stack,N as Task,K as TaskException,L as TaskResult,G as Throwable,Y as Try,m as TypeCheckLeft,l as TypeCheckRight,T as TypedError,x as UUID,w as UrlString,p as ValidatedBrand,V as Validation,ea as Valuable,M as createCancellationTokenSource,R as createErrorSerializer,Q as formatError,P as formatStackTrace,W as isExtractable,j as isLeft,i as isRight,J as isTaggedThrowable,O as safeStringify,k as tryCatch,n as tryCatchAsync}from'./chunk-GHBOC52G.mjs';export{a as Companion,b as Tuple}from'./chunk-BQJB6CCW.mjs';export{a as Brand,g as BrandedBoolean,f as BrandedNumber,e as BrandedString,d as createBrander,c as hasBrand,b as unbrand}from'./chunk-R2TQJN3P.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/list/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { L as List } from '../Either-
|
|
2
|
-
import '../Serializable-
|
|
1
|
+
export { L as List } from '../Either-BHep7I0d.js';
|
|
2
|
+
import '../Serializable-BbKuhDDL.js';
|
package/dist/list/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{
|
|
1
|
+
export{f as List}from'../chunk-GHBOC52G.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-R2TQJN3P.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/map/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as Traversable, C as Collection, O as Option } from '../Either-
|
|
2
|
-
import { a as Typeable, S as Serializable, P as Pipe, F as Foldable, T as Type } from '../Serializable-
|
|
1
|
+
import { T as Traversable, C as Collection, O as Option } from '../Either-BHep7I0d.js';
|
|
2
|
+
import { a as Typeable, S as Serializable, P as Pipe, F as Foldable, T as Type } from '../Serializable-BbKuhDDL.js';
|
|
3
3
|
import { Tuple } from '../tuple/index.js';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/map/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{
|
|
1
|
+
export{ba as Map}from'../chunk-GHBOC52G.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-R2TQJN3P.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/option/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { N as None, O as Option,
|
|
2
|
-
import '../Serializable-
|
|
1
|
+
export { N as None, O as Option, m as OptionConstructor, S as Some } from '../Either-BHep7I0d.js';
|
|
2
|
+
import '../Serializable-BbKuhDDL.js';
|
package/dist/option/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{b as None,d as Option,c as OptionConstructor,a as Some}from'../chunk-
|
|
1
|
+
export{b as None,d as Option,c as OptionConstructor,a as Some}from'../chunk-GHBOC52G.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-R2TQJN3P.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/set/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
2
|
-
import '../Serializable-
|
|
1
|
+
export { n as Set } from '../Either-BHep7I0d.js';
|
|
2
|
+
import '../Serializable-BbKuhDDL.js';
|
package/dist/set/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{e as Set}from'../chunk-
|
|
1
|
+
export{e as Set}from'../chunk-GHBOC52G.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-R2TQJN3P.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/try/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as FunctypeBase, a as Extractable, E as Either } from '../Either-
|
|
2
|
-
import { P as Pipe, T as Type } from '../Serializable-
|
|
1
|
+
import { F as FunctypeBase, a as Extractable, E as Either } from '../Either-BHep7I0d.js';
|
|
2
|
+
import { P as Pipe, T as Type } from '../Serializable-BbKuhDDL.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Possible types of Try instances
|
package/dist/try/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export{
|
|
1
|
+
export{Y as Try}from'../chunk-GHBOC52G.mjs';import'../chunk-BQJB6CCW.mjs';import'../chunk-R2TQJN3P.mjs';//# sourceMappingURL=index.mjs.map
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/tuple/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { T as Type, F as Foldable, P as Pipe, S as Serializable, a as Typeable } from '../Serializable-
|
|
1
|
+
import { T as Type, F as Foldable, P as Pipe, S as Serializable, a as Typeable } from '../Serializable-BbKuhDDL.js';
|
|
2
2
|
|
|
3
3
|
interface Tuple<T extends Type[]> extends Foldable<T[number]>, Pipe<Tuple<T>>, Serializable<Tuple<T>>, Typeable<"Tuple"> {
|
|
4
4
|
get<K extends number>(index: K): T[K];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "functype",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A smallish functional library for TypeScript",
|
|
6
6
|
"author": "jordan.burke@gmail.com",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"@typescript-eslint/parser": "^8.38.0",
|
|
21
21
|
"@vitest/coverage-v8": "^3.2.4",
|
|
22
22
|
"@vitest/ui": "^3.2.4",
|
|
23
|
-
"cross-env": "^
|
|
23
|
+
"cross-env": "^10.0.0",
|
|
24
24
|
"eslint": "^9.32.0",
|
|
25
25
|
"eslint-config-prettier": "^10.1.8",
|
|
26
26
|
"eslint-plugin-functional": "^9.0.2",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"rimraf": "^6.0.1",
|
|
34
34
|
"ts-node": "^10.9.2",
|
|
35
35
|
"tsup": "^8.5.0",
|
|
36
|
-
"typedoc": "^0.28.
|
|
36
|
+
"typedoc": "^0.28.8",
|
|
37
37
|
"typescript": "5.8.3",
|
|
38
38
|
"vitest": "^3.2.4"
|
|
39
39
|
},
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Bundle Size Optimization Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Functype is designed with tree-shaking in mind, allowing you to optimize your application's bundle size by only including the specific modules you need.
|
|
6
|
+
|
|
7
|
+
## Import Strategies
|
|
8
|
+
|
|
9
|
+
### Strategy 1: Selective Module Imports (Recommended)
|
|
10
|
+
|
|
11
|
+
Import only the specific modules you need to reduce bundle size significantly.
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { Option } from "functype/option"
|
|
15
|
+
import { Either } from "functype/either"
|
|
16
|
+
|
|
17
|
+
// Usage
|
|
18
|
+
const option = Option.some(42)
|
|
19
|
+
const either = Either.right("value")
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Strategy 2: Direct Constructor Imports (Smallest Bundle)
|
|
23
|
+
|
|
24
|
+
For the most aggressive tree-shaking, import only the specific constructors and functions you need.
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { some, none } from "functype/option"
|
|
28
|
+
import { right } from "functype/either"
|
|
29
|
+
|
|
30
|
+
// Usage
|
|
31
|
+
const option = some(42)
|
|
32
|
+
const none_value = none()
|
|
33
|
+
const either = right("value")
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Bundle Size Comparison
|
|
37
|
+
|
|
38
|
+
| Import Strategy | Approximate Bundle Size | Best For |
|
|
39
|
+
| --------------- | ------------------------ | -------------------------- |
|
|
40
|
+
| Selective | 200-500 bytes per module | Most applications |
|
|
41
|
+
| Direct | <200 bytes per feature | Size-critical applications |
|
|
42
|
+
|
|
43
|
+
## Common Module Sizes
|
|
44
|
+
|
|
45
|
+
| Module | Approximate Size (minified) | Gzipped Size |
|
|
46
|
+
| -------- | --------------------------- | ------------ |
|
|
47
|
+
| Option | ~200 bytes | ~140 bytes |
|
|
48
|
+
| Either | ~290 bytes | ~190 bytes |
|
|
49
|
+
| List | ~170 bytes | ~125 bytes |
|
|
50
|
+
| Try | ~170 bytes | ~125 bytes |
|
|
51
|
+
| Tuple | ~120 bytes | ~100 bytes |
|
|
52
|
+
| FPromise | ~200 bytes | ~140 bytes |
|
|
53
|
+
|
|
54
|
+
## Additional Tips
|
|
55
|
+
|
|
56
|
+
1. **Import Analysis**: Use tools like [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) or [rollup-plugin-visualizer](https://github.com/btd/rollup-plugin-visualizer) to analyze your bundle and identify opportunities for optimization.
|
|
57
|
+
|
|
58
|
+
2. **Dynamic Imports**: Consider using dynamic imports for rarely used functionality:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
// Only load when needed
|
|
62
|
+
const useRareFeature = async () => {
|
|
63
|
+
const { someLargeUtility } = await import("functype/some-large-module")
|
|
64
|
+
return someLargeUtility()
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
3. **Development vs Production**: During development, you might prefer the convenience of importing everything. In production builds, switch to selective imports.
|
|
69
|
+
|
|
70
|
+
4. **Peer Dependencies**: Functype has minimal dependencies, and the only external dependency (`safe-stable-stringify`) is quite small.
|
|
71
|
+
|
|
72
|
+
## Need Help?
|
|
73
|
+
|
|
74
|
+
If you need assistance with optimizing your bundle size further, please open an issue on our GitHub repository.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# FPromise Implementation Assessment
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This document provides an assessment of whether the FPromise implementation is ready to replace the old main branch version, with particular focus on potential impacts to implementing libraries outside this one.
|
|
6
|
+
|
|
7
|
+
## Strengths of the FPromise Implementation
|
|
8
|
+
|
|
9
|
+
1. **Comprehensive Error Handling**: FPromise provides rich error handling capabilities including `mapError`, `tapError`, `recover`, `recoverWith`, `recoverWithF`, `filterError`, and `logError`.
|
|
10
|
+
|
|
11
|
+
2. **Either Integration**: FPromise has built-in conversion to/from Either with `toEither()` and `fromEither()`, which aligns well with the functional programming approach used in the Task implementation.
|
|
12
|
+
|
|
13
|
+
3. **Promise Compatibility**: FPromise implements the PromiseLike interface, ensuring compatibility with async/await and standard Promise chains.
|
|
14
|
+
|
|
15
|
+
4. **Extensive Test Coverage**: The test suite is comprehensive, covering basic functionality, error handling, recovery mechanisms, and real-world scenarios.
|
|
16
|
+
|
|
17
|
+
5. **Retry Mechanisms**: The implementation includes multiple retry strategies (basic retry, retry with backoff, and retry with options).
|
|
18
|
+
|
|
19
|
+
## Potential Compatibility Issues
|
|
20
|
+
|
|
21
|
+
1. **Import Path Differences**: The Task.ts file imports from `"'core/throwable/Throwable"'` and `"'either/Either"'` with unusual quotes, while the actual imports should use `@/` prefix. This might cause issues if external libraries rely on these specific import paths.
|
|
22
|
+
|
|
23
|
+
2. **Type Compatibility**: The Task implementation uses `Either<Throwable, T>` for error handling, while FPromise uses a more generic approach. Libraries expecting specific Either structures might need adjustments.
|
|
24
|
+
|
|
25
|
+
3. **API Surface Changes**: External libraries that directly interact with the Promise implementation might need to adapt to the new methods and patterns provided by FPromise.
|
|
26
|
+
|
|
27
|
+
## Recommendation
|
|
28
|
+
|
|
29
|
+
The FPromise implementation is technically sound and provides significant improvements, but to avoid breaking implementing libraries outside this one:
|
|
30
|
+
|
|
31
|
+
1. **Gradual Migration**: Consider a phased approach where both implementations coexist temporarily.
|
|
32
|
+
|
|
33
|
+
2. **Version Bumping**: This change warrants a major version bump to signal potential breaking changes.
|
|
34
|
+
|
|
35
|
+
3. **Documentation**: Provide clear migration guides for dependent libraries.
|
|
36
|
+
|
|
37
|
+
4. **Import Path Fixes**: Ensure import paths are consistent and follow the project's conventions.
|
|
38
|
+
|
|
39
|
+
5. **Compatibility Layer**: Consider providing a thin compatibility layer for libraries that can't immediately migrate to the new API.
|
|
40
|
+
|
|
41
|
+
## Conclusion
|
|
42
|
+
|
|
43
|
+
The FPromise implementation appears ready to replace the old main branch version from a technical perspective, but careful migration planning is necessary to minimize disruption to implementing libraries.
|
package/readme/HKT.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Higher-Kinded Types (HKT)
|
|
2
|
+
|
|
3
|
+
Higher-kinded types allow for writing generic code that works across different container types like `Option`, `List`, `Either`, and `Try`. This is a powerful abstraction that lets you create algorithms that work with any type that supports certain operations, without having to rewrite them for each specific type.
|
|
4
|
+
|
|
5
|
+
## Introduction
|
|
6
|
+
|
|
7
|
+
In functional programming, many operations like `map`, `flatMap`, or `sequence` follow similar patterns across different data structures. The HKT module provides a unified way to work with these operations for any supporting container type.
|
|
8
|
+
|
|
9
|
+
## Key Concepts
|
|
10
|
+
|
|
11
|
+
1. **Kind**: A type-level function representing a higher-kinded type relationship
|
|
12
|
+
2. **Container Types**: Data structures that contain values (Option, List, Either, etc.)
|
|
13
|
+
3. **Type Constructor**: A function that takes a type and returns a new type
|
|
14
|
+
|
|
15
|
+
## Basic Operations
|
|
16
|
+
|
|
17
|
+
### Map
|
|
18
|
+
|
|
19
|
+
Apply a function to a value inside a container:
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { Option, HKT } from "functype"
|
|
23
|
+
|
|
24
|
+
const option = Option(42)
|
|
25
|
+
const doubled = HKT.map(option, (x) => x * 2) // Option(84)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### FlatMap
|
|
29
|
+
|
|
30
|
+
Apply a function that returns a container to a value inside a container, then flatten the result:
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
const option = Option(42)
|
|
34
|
+
const result = HKT.flatMap(option, (x) => Option(x * 2)) // Option(84)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Flatten
|
|
38
|
+
|
|
39
|
+
Flatten a nested container:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
const nestedOption = Option(Option(42))
|
|
43
|
+
const flattened = HKT.flatten(nestedOption) // Option(42)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Advanced Operations
|
|
47
|
+
|
|
48
|
+
### Sequence
|
|
49
|
+
|
|
50
|
+
Transform a container of containers into a container of container (e.g., `Option<List<A>>` to `List<Option<A>>`):
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
const optionOfList = Option(List([1, 2, 3]))
|
|
54
|
+
const listOfOptions = HKT.sequence(optionOfList)
|
|
55
|
+
// List([Option(1), Option(2), Option(3)])
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Traverse
|
|
59
|
+
|
|
60
|
+
Transform each element in a container using a function that returns another container type, then sequence the results:
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
const list = List([1, 2, 3])
|
|
64
|
+
const result = HKT.traverse(list, (x) => Option(x * 2))
|
|
65
|
+
// Option(List([2, 4, 6]))
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Applicative (ap)
|
|
69
|
+
|
|
70
|
+
Apply a function inside a container to a value inside another container:
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
const optionFn = Option((x: number) => x * 2)
|
|
74
|
+
const optionValue = Option(21)
|
|
75
|
+
const result = HKT.ap(optionFn, optionValue) // Option(42)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Supported Container Types
|
|
79
|
+
|
|
80
|
+
The HKT module currently supports the following container types:
|
|
81
|
+
|
|
82
|
+
- `Option<A>`
|
|
83
|
+
- `List<A>`
|
|
84
|
+
- `Either<E, A>`
|
|
85
|
+
- `Try<A>`
|
|
86
|
+
|
|
87
|
+
## Creating Generic Algorithms
|
|
88
|
+
|
|
89
|
+
The power of HKT is in creating algorithms that work with any container type:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
// A function that works with any container implementing map
|
|
93
|
+
function increment<F extends (a: number) => any>(container: Kind<F, number>): Kind<F, number> {
|
|
94
|
+
return HKT.map(container, (x) => x + 1)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Works with any container
|
|
98
|
+
increment(Option(41)) // Option(42)
|
|
99
|
+
increment(List([1, 2, 3])) // List([2, 3, 4])
|
|
100
|
+
increment(Right<string, number>(41)) // Right(42)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Implementing Your Own Container Types
|
|
104
|
+
|
|
105
|
+
To make your custom container types work with HKT, you need to:
|
|
106
|
+
|
|
107
|
+
1. Implement the appropriate methods (`map`, `flatMap`, etc.)
|
|
108
|
+
2. Add type checking in the HKT functions
|
|
109
|
+
|
|
110
|
+
This allows seamless integration with the rest of the functional programming ecosystem.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Functype Roadmap (2025-2026)
|
|
2
|
+
|
|
3
|
+
This roadmap outlines the planned development path for the Functype library, focusing on expanding functionality, improving performance, ensuring API consistency, and enhancing TypeScript integration.
|
|
4
|
+
|
|
5
|
+
## Q2 2025: Core Functional Data Types
|
|
6
|
+
|
|
7
|
+
### Lazy Evaluation
|
|
8
|
+
|
|
9
|
+
- [ ] Implement `LazyList` / `Stream` for efficient processing of potentially infinite sequences
|
|
10
|
+
- [ ] Add common operations: `map`, `filter`, `take`, `drop`, etc.
|
|
11
|
+
- [ ] Implement memoization for evaluated values
|
|
12
|
+
|
|
13
|
+
### Validation Type
|
|
14
|
+
|
|
15
|
+
- [ ] Create `Validation` data type for applicative validation
|
|
16
|
+
- [ ] Support collecting multiple errors (unlike Either which short-circuits)
|
|
17
|
+
- [ ] Add utilities for combining validation results
|
|
18
|
+
|
|
19
|
+
### Performance Foundation
|
|
20
|
+
|
|
21
|
+
- [ ] Add memoization utilities for expensive function calls
|
|
22
|
+
- [ ] Implement a basic benchmarking suite for measuring performance
|
|
23
|
+
- [ ] Standardize performance metrics across data structures
|
|
24
|
+
|
|
25
|
+
## Q3 2025: Advanced Functional Patterns & Optimizations
|
|
26
|
+
|
|
27
|
+
### Type Classes
|
|
28
|
+
|
|
29
|
+
- [x] Implement `Foldable` typeclass with fold, foldLeft, and foldRight methods
|
|
30
|
+
- [x] Implement `Matchable` typeclass for pattern matching
|
|
31
|
+
- [ ] Implement proper `Functor` and `Monad` typeclasses
|
|
32
|
+
- [ ] Add `Applicative` typeclass
|
|
33
|
+
- [ ] Support `Traversable` with comprehensive HKT
|
|
34
|
+
|
|
35
|
+
### Monad Implementations
|
|
36
|
+
|
|
37
|
+
- [ ] Implement `Reader` monad for dependency injection
|
|
38
|
+
- [ ] Add `State` monad for managing state transformations
|
|
39
|
+
- [ ] Create `IO` monad for pure handling of side effects
|
|
40
|
+
- [ ] Add comprehensive documentation and examples
|
|
41
|
+
|
|
42
|
+
### Performance Improvements
|
|
43
|
+
|
|
44
|
+
- [ ] Implement structural sharing for immutable collections
|
|
45
|
+
- [ ] Optimize recursive operations for large data structures
|
|
46
|
+
- [ ] Add performance comparison against other FP libraries
|
|
47
|
+
|
|
48
|
+
### Lenses & Optics
|
|
49
|
+
|
|
50
|
+
- [ ] Implement lens abstraction for immutable updates
|
|
51
|
+
- [ ] Add prism implementation for optional data
|
|
52
|
+
- [ ] Create utilities for composing lenses and prisms
|
|
53
|
+
|
|
54
|
+
## Q4 2025: TypeScript Enhancements & API Consistency
|
|
55
|
+
|
|
56
|
+
### TypeScript Integration
|
|
57
|
+
|
|
58
|
+
- [x] Add support for higher-kinded types
|
|
59
|
+
- [ ] Remove `any` from HKT
|
|
60
|
+
- [x] Implement branded/nominal types for stronger type safety
|
|
61
|
+
- [ ] Add type-level utilities using newer TypeScript features
|
|
62
|
+
- [ ] Leverage const type parameters and tuple manipulation
|
|
63
|
+
|
|
64
|
+
### API Normalization
|
|
65
|
+
|
|
66
|
+
- [ ] Review and standardize API across all modules
|
|
67
|
+
- [ ] Ensure consistent implementation of the Scala-inspired pattern
|
|
68
|
+
- [ ] Standardize import patterns (@imports throughout)
|
|
69
|
+
- [ ] Create migration guides for API changes
|
|
70
|
+
|
|
71
|
+
## Q1 2026: Testing, Documentation & Community Support
|
|
72
|
+
|
|
73
|
+
### Testing Expansion
|
|
74
|
+
|
|
75
|
+
- [ ] Add test coverage metrics and set coverage goals
|
|
76
|
+
- [ ] Expand property-based testing across all modules
|
|
77
|
+
- [ ] Create interoperability tests with popular libraries
|
|
78
|
+
- [ ] Add more specialized test cases for error handling
|
|
79
|
+
|
|
80
|
+
### Documentation & Examples
|
|
81
|
+
|
|
82
|
+
- [ ] Add comprehensive documentation for all modules
|
|
83
|
+
- [ ] Create step-by-step migration guides from imperative to functional
|
|
84
|
+
- [ ] Add real-world examples showcasing practical applications
|
|
85
|
+
- [ ] Create tutorial sections for beginners
|
|
86
|
+
|
|
87
|
+
### Community Engagement
|
|
88
|
+
|
|
89
|
+
- [ ] Create contribution guidelines and templates
|
|
90
|
+
- [ ] Set up automated issue/PR handling
|
|
91
|
+
- [ ] Establish regular release schedule
|
|
92
|
+
- [ ] Add community forum/discussion platform
|
|
93
|
+
|
|
94
|
+
## Ongoing Priorities
|
|
95
|
+
|
|
96
|
+
### Compatibility
|
|
97
|
+
|
|
98
|
+
- [ ] Ensure compatibility with Node.js LTS versions
|
|
99
|
+
- [ ] Maintain browser compatibility
|
|
100
|
+
- [ ] Support for Deno and other runtimes
|
|
101
|
+
- [ ] Test with various bundlers (webpack, esbuild, etc.)
|
|
102
|
+
|
|
103
|
+
### Bundle Size
|
|
104
|
+
|
|
105
|
+
- [x] Optimize tree-shaking
|
|
106
|
+
- [x] Provide guidance on importing only needed modules
|
|
107
|
+
- [x] Add bundle size monitoring to CI/CD
|
|
108
|
+
|
|
109
|
+
### Community Feedback
|
|
110
|
+
|
|
111
|
+
- [ ] Regular review of GitHub issues and feature requests
|
|
112
|
+
- [ ] Prioritization based on community needs
|
|
113
|
+
- [ ] Transparent development process
|