import { pretty, typedKeysOf } from "@effect-ts-app/core/utils" export function assertUnreachable(x: never): never { throw new Error("Unknown case " + x) } export type OptPromise any> = ( ...args: Parameters ) => Promise> | ReturnType export const typedValuesOf = (obj: Record) => Object.values(obj) as readonly T2[] export function access(t: Record) { return (key: T) => t[key] as T2 } export function todayAtUTCNoon() { const localDate = new Date() const utcDateAtNoon = Date.UTC( localDate.getFullYear(), localDate.getMonth(), localDate.getDate(), 12 ) return new Date(utcDateAtNoon) } function anyOp_$(self: T) { return { get subject() { return self } } } /** * @tsplus getter Object $$ * @tsplus getter number $$ * @tsplus getter bigint $$ * @tsplus getter boolean $$ * @tsplus getter regexp $$ * @tsplus getter string $$ */ export function anyOp$(self: T): AnyOps { return anyOp_$(self) } /** * @tsplus type Any.Ops * @tsplus type Object.Ops */ export interface AnyOps { subject: T } /** * @tsplus fluent effect/io/Effect debug */ export function Effect_debug(self: Effect, name: string) { return self.tap(a => { let r: string | A = a try { r = pretty(a) } catch { /* empty */ } return Effect.logDebug("print").logAnnotate(name, `${r}`) }) } /** * @tsplus fluent effect/io/Effect debugUnsafe */ export function Effect_debugUnsafe(self: Effect, name: string) { return self.tap(a => Effect(() => console.log(name, a))) } /** * @tsplus fluent Any.Ops debug * @tsplus fluent Object.Ops debug */ export function debug(a: AnyOps, name: string) { let r: string | A = a.subject try { r = pretty(a.subject) } catch { /* empty */ } return Effect.logDebug("print") .logAnnotate(name, `${r}`) .map(() => a.subject) } /** * @tsplus fluent Any.Ops debugUnsafe * @tsplus fluent Object.Ops debugUnsafe */ export function debugUnsafe(a: AnyOps, name: string) { console.log(name, a.subject) return a.subject } export function spread< // eslint-disable-next-line @typescript-eslint/no-explicit-any Props extends Record, // eslint-disable-next-line @typescript-eslint/no-explicit-any NewProps >(props: Props, fnc: (props: Props) => NewProps) { return fnc(props) } export function spreadS< // eslint-disable-next-line @typescript-eslint/no-explicit-any Props extends Record >(props: Props, fnc: (props: Props) => Props) { return fnc(props) } type Key = T extends Record ? TKey : never type Values = T extends { [s: string]: infer S } ? S : any function object_$(self: T) { return { get subject() { return self }, // TODO: move to extensions spread

(this: void, fnc: (t: T) => P) { return spread(self, fnc) }, spreadS(this: void, fnc: (t: T) => T) { return spreadS(self, fnc) }, } } type BasicObjectOps = ReturnType> /** * @tsplus getter Object $$ */ export function object$(self: T): ObjectOps { return object_$(self) } /** * @tsplus type Object.Ops */ export interface ObjectOps extends BasicObjectOps {} function entries(o: TT): [Key, Values][] { return Object.entries(o) as any } /** * @tsplus getter Object.Ops entries */ export function RecordEntries(o: ObjectOps) { return entries(o.subject) } /** * @tsplus getter Object.Ops keys */ export function RecordKeys(o: ObjectOps) { return typedKeysOf(o.subject) } /** * @tsplus getter Object.Ops values */ export function RecordValues(o: ObjectOps): Values[] { return Object.values(o.subject) } /** * @tsplus getter Any.Ops pretty */ export function AnyPretty(o: AnyOps) { return pretty(o.subject) } /** * @tsplus getter Object.Ops pretty */ export function RecordPretty(o: ObjectOps) { return pretty(o.subject) } export function makeAzureFriendly(path: string) { return path.replace(/\//g, "___SL@SH___") } export function undoAzureFriendly(path: T): T { return path.replace(/___SL@SH___/g, "/") as T } export function arrayMove( arrInput: readonly T[], oldIndex: number, newIndex: number ) { const arr: (T | undefined)[] = [...arrInput] while (oldIndex < 0) { oldIndex += arr.length } while (newIndex < 0) { newIndex += arr.length } if (newIndex >= arr.length) { let k = newIndex - arr.length + 1 while (k--) { arr.push(undefined) } } arr.splice(newIndex, 0, arr.splice(oldIndex, 1)[0]) return arr } export function arrayMoveDropUndefined( arrInput: readonly (T | undefined)[], oldIndex: number, newIndex: number ): T[] { return arrayMove(arrInput, oldIndex, newIndex).filter((x): x is T => x !== undefined) } export function arMoveElDropUndefined(el: T, newIndex: number) { return (arrInput: ReadonlyArray): Opt> => { const ar = [...arrInput] const index = ar.findIndex(x => x === el) if (index === -1) { return Opt.none } return Opt(arrayMoveDropUndefined(ar, index, newIndex)) } } export function setMoveElDropUndefined(el: T, newIndex: number) { return (arrInput: ReadonlySet): Opt> => [...arrInput]["|>"](arMoveElDropUndefined(el, newIndex)).map(ar => new Set(ar)) } export * from "@effect-ts-app/core/utils" export { default as get } from "lodash/get.js" export { default as omit } from "lodash/omit.js" export { default as pick } from "lodash/pick.js" export type DistributiveOmit = T extends any ? Omit : never type RemoveNonArray = T extends readonly any[] ? T : never export function isNativeTuple(a: A): a is RemoveNonArray { return Array.isArray(a) } export const LazySymbol = Symbol("lazy") interface Lazy { [LazySymbol]: Record } export function lazyGetter(creator: (target: T) => T2) { const key = Symbol(creator.name) const f = (target: T): T2 => { let lazy = (target as unknown as Lazy)[LazySymbol] if (!lazy) { lazy = {} Object.defineProperty(target, LazySymbol, { enumerable: false, value: lazy }) } else if (lazy[key]) { return lazy[key] } const value = creator(target) lazy[key] = value return value } Object.defineProperty(f, "name", { enumerable: false, value: `Lazy<${creator.name}>` }) return f } export function exhaustiveMatch() { return any>>(handlers: Out) => (t: T): ReturnType => handlers[t](t) } export function exhaustiveMatch_(t: T) { return any>>(handlers: Out): ReturnType => handlers[t](t) }