This letter is best viewed on Desktop.
Welcome to my first letter.
This is a test to check for different markdown features, and to see if they work as expected.
Link List of items:
Bold Text
italic bold
Some italic text
function add(a: number, b: number): number { return a + b; } console.log(add(2, 3));
Some long code example
let add a b = a + b let () = print_endline (string_of_int (add 2 3))
Check out this interactive 3D planet component built with Three.js:
Pretty cool, right? You can drag to rotate and scroll to zoom!
func add(a: Int, b: Int) -> Int { return a + b } print(add(a: 2, b: 3))
func add(a int, b int) int { return a + b } fmt.Println(add(2, 3))
CREATE TABLE IF NOT EXISTS numbers ( id SERIAL PRIMARY KEY, value INTEGER ); INSERT INTO numbers (value) VALUES (2), (3); SELECT add(2, 3);
namespace math { int add(int a, int b) { return a + b; } } // namespace math #include <iostream> int main() { std::cout << math::add(2, 3) << std::endl; return 0; }
#include <stdio.h> int add(int a, int b) { return a + b; } int main() { printf("%d\n", add(2, 3)); return 0; }
This demonstrates a custom Shiki theme created to match a specific dark color scheme.
I've created a custom Shiki theme that accurately recreates the beautiful "Bore" Vim theme colors. This theme features a true black background (#0e0e0e
) with carefully chosen colors for different code elements.
The custom theme uses these precise colors from the Bore Vim theme:
#0e0e0e
)#cacadd
)#6cbeff
)#ecc48d
)#74778c
)#ffffff
)#7fdbca
)#FD98B9
)#7fdbca
)Let's also see how it looks with TypeScript:
import { CheckCircle, Loader, PauseCircle } from "lucide-react"; import Link from "next/link"; export interface Links { label: string; url: string; } export type PossibleStatuses = "In Progress" | "Completed" | "On Hiatus" | ""; interface CardProps { title: string; description: string; status: PossibleStatuses; links: Links[]; } export default function Card({ title, description, status, links }: CardProps) { const getIconForStatus = (status?: PossibleStatuses) => { switch (status) { case "In Progress": return <Loader />; case "Completed": return <CheckCircle className="text-green-500" />; case "On Hiatus": return <PauseCircle className="text-yellow-500" />; default: return null; } }; return ( <div className="mx-auto bg-[#101010] border border-neutral-700 rounded-2xl p-8 md:p-6"> <div className="flex items-start justify-between mb-6"> <h1 className="text-4xl md:text-xl font-semibold text-white leading-tight"> {title} </h1> {getIconForStatus(status)} </div> </div> ); }
And here's some Go code showing similar patterns to your screenshot:
// CompactionLevels returns a full list of compaction levels include L0. func (c *Config) CompactionLevels() litestream.CompactionLevels { levels := litestream.CompactionLevels{ {Level: 0}, } for i, lvl := range c.Levels { levels = append(levels, &litestream.CompactionLevel{ Level: i + 1, Interval: lvl.Interval, }) } return levels } // DefaultConfigPath returns the default configuration file path. // DBConfig returns database configuration by path. func (c *Config) DBConfig(path string) *DBConfig { for _, dbConfig := range c.DBs { if dbConfig.Path == path { return dbConfig } } return nil }
And here's some JavaScript with modern syntax:
// Modern JavaScript with async/await const fetchUserData = async (userId) => { try { const response = await fetch(`/api/users/${userId}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const userData = await response.json(); return userData; } catch (error) { console.error("Failed to fetch user data:", error); return null; } }; // Using array methods and destructuring const processUsers = (users) => { return users .filter(({ active }) => active) .map(({ id, name, email }) => ({ id, displayName: name.toUpperCase(), contact: email || "No email provided", })) .sort((a, b) => a.displayName.localeCompare(b.displayName)); };
#include "git-compat-util.h" #include "config.h" #include "repo-settings.h" #include "repository.h" #include "midx.h" #include "pack-objects.h" #include "setup.h" static void repo_cfg_bool(struct repository *r, const char *key, int *dest, int def) { if (repo_config_get_bool(r, key, dest)) *dest = def; } static void repo_cfg_int(struct repository *r, const char *key, int *dest, int def) { if (repo_config_get_int(r, key, dest)) *dest = def; } static void repo_cfg_ulong(struct repository *r, const char *key, unsigned long *dest, unsigned long def) { if (repo_config_get_ulong(r, key, dest)) *dest = def; } void prepare_repo_settings(struct repository *r) { int experimental; int value; const char *strval; int manyfiles; int read_changed_paths; unsigned long ulongval; if (!r->gitdir) BUG("Cannot add settings for uninitialized repository"); if (r->settings.initialized) return; repo_settings_clear(r); r->settings.initialized++; /* Booleans config or default, cascades to other settings */ repo_cfg_bool(r, "feature.manyfiles", &manyfiles, 0); repo_cfg_bool(r, "feature.experimental", &experimental, 0); /* Defaults modified by feature.* */ if (experimental) { r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_SKIPPING; r->settings.pack_use_bitmap_boundary_traversal = 1; r->settings.pack_use_multi_pack_reuse = 1; r->settings.pack_use_path_walk = 1; } if (manyfiles) { r->settings.index_version = 4; r->settings.index_skip_hash = 1; r->settings.core_untracked_cache = UNTRACKED_CACHE_WRITE; r->settings.pack_use_path_walk = 1; } /* Commit graph config or default, does not cascade (simple) */ repo_cfg_bool(r, "core.commitgraph", &r->settings.core_commit_graph, 1); repo_cfg_int(r, "commitgraph.generationversion", &r->settings.commit_graph_generation_version, 2); repo_cfg_bool(r, "commitgraph.readchangedpaths", &read_changed_paths, 1); repo_cfg_int(r, "commitgraph.changedpathsversion", &r->settings.commit_graph_changed_paths_version, read_changed_paths ? -1 : 0); repo_cfg_bool(r, "gc.writecommitgraph", &r->settings.gc_write_commit_graph, 1); repo_cfg_bool(r, "fetch.writecommitgraph", &r->settings.fetch_write_commit_graph, 0); /* Boolean config or default, does not cascade (simple) */ repo_cfg_bool(r, "pack.usesparse", &r->settings.pack_use_sparse, 1); repo_cfg_bool(r, "pack.usepathwalk", &r->settings.pack_use_path_walk, 0); repo_cfg_bool(r, "core.multipackindex", &r->settings.core_multi_pack_index, 1); repo_cfg_bool(r, "index.sparse", &r->settings.sparse_index, 0); repo_cfg_bool(r, "index.skiphash", &r->settings.index_skip_hash, r->settings.index_skip_hash); repo_cfg_bool(r, "pack.readreverseindex", &r->settings.pack_read_reverse_index, 1); repo_cfg_bool(r, "pack.usebitmapboundarytraversal", &r->settings.pack_use_bitmap_boundary_traversal, r->settings.pack_use_bitmap_boundary_traversal); repo_cfg_bool(r, "core.usereplacerefs", &r->settings.read_replace_refs, 1); /* * The GIT_TEST_MULTI_PACK_INDEX variable is special in that * either it *or* the config sets * r->settings.core_multi_pack_index if true. We don't take * the environment variable if it exists (even if false) over * any config, as in most other cases. */ if (git_env_bool(GIT_TEST_MULTI_PACK_INDEX, 0)) r->settings.core_multi_pack_index = 1; /* * Non-boolean config */ if (!repo_config_get_int(r, "index.version", &value)) r->settings.index_version = value; if (!repo_config_get_string_tmp(r, "core.untrackedcache", &strval)) { int v = git_parse_maybe_bool(strval); /* * If it's set to "keep", or some other non-boolean * value then "v < 0". Then we do nothing and keep it * at the default of UNTRACKED_CACHE_KEEP. */ if (v >= 0) r->settings.core_untracked_cache = v ? UNTRACKED_CACHE_WRITE : UNTRACKED_CACHE_REMOVE; } if (!repo_config_get_string_tmp(r, "fetch.negotiationalgorithm", &strval)) { int fetch_default = r->settings.fetch_negotiation_algorithm; if (!strcasecmp(strval, "skipping")) r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_SKIPPING; else if (!strcasecmp(strval, "noop")) r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_NOOP; else if (!strcasecmp(strval, "consecutive")) r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_CONSECUTIVE; else if (!strcasecmp(strval, "default")) r->settings.fetch_negotiation_algorithm = fetch_default; else die("unknown fetch negotiation algorithm '%s'", strval); } /* * This setting guards all index reads to require a full index * over a sparse index. After suitable guards are placed in the * codebase around uses of the index, this setting will be * removed. */ r->settings.command_requires_full_index = 1; if (!repo_config_get_ulong(r, "core.deltabasecachelimit", &ulongval)) r->settings.delta_base_cache_limit = ulongval; if (!repo_config_get_ulong(r, "core.packedgitwindowsize", &ulongval)) { int pgsz_x2 = getpagesize() * 2; /* This value must be multiple of (pagesize * 2) */ ulongval /= pgsz_x2; if (ulongval < 1) ulongval = 1; r->settings.packed_git_window_size = ulongval * pgsz_x2; } if (!repo_config_get_ulong(r, "core.packedgitlimit", &ulongval)) r->settings.packed_git_limit = ulongval; } void repo_settings_clear(struct repository *r) { struct repo_settings empty = REPO_SETTINGS_INIT; FREE_AND_NULL(r->settings.fsmonitor); FREE_AND_NULL(r->settings.hooks_path); r->settings = empty; } unsigned long repo_settings_get_big_file_threshold(struct repository *repo) { if (!repo->settings.big_file_threshold) repo_cfg_ulong(repo, "core.bigfilethreshold", &repo->settings.big_file_threshold, 512 * 1024 * 1024); return repo->settings.big_file_threshold; } void repo_settings_set_big_file_threshold(struct repository *repo, unsigned long value) { repo->settings.big_file_threshold = value; } enum log_refs_config repo_settings_get_log_all_ref_updates(struct repository *repo) { const char *value; if (!repo_config_get_string_tmp(repo, "core.logallrefupdates", &value)) { if (value && !strcasecmp(value, "always")) return LOG_REFS_ALWAYS; else if (git_config_bool("core.logallrefupdates", value)) return LOG_REFS_NORMAL; else return LOG_REFS_NONE; } return LOG_REFS_UNSET; } int repo_settings_get_warn_ambiguous_refs(struct repository *repo) { prepare_repo_settings(repo); if (repo->settings.warn_ambiguous_refs < 0) repo_cfg_bool(repo, "core.warnambiguousrefs", &repo->settings.warn_ambiguous_refs, 1); return repo->settings.warn_ambiguous_refs; } const char *repo_settings_get_hooks_path(struct repository *repo) { if (!repo->settings.hooks_path) repo_config_get_pathname(repo, "core.hookspath", &repo->settings.hooks_path); return repo->settings.hooks_path; } int repo_settings_get_shared_repository(struct repository *repo) { if (!repo->settings.shared_repository_initialized) { const char *var = "core.sharedrepository"; const char *value; if (!repo_config_get_value(repo, var, &value)) repo->settings.shared_repository = git_config_perm(var, value); else repo->settings.shared_repository = PERM_UMASK; repo->settings.shared_repository_initialized = 1; } return repo->settings.shared_repository; } void repo_settings_set_shared_repository(struct repository *repo, int value) { repo->settings.shared_repository = value; repo->settings.shared_repository_initialized = 1; } void repo_settings_reset_shared_repository(struct repository *repo) { repo->settings.shared_repository_initialized = 0; }``` ```cpp class QmlObjectListModel : public QAbstractListModel { Q_OBJECT QML_ELEMENT QML_UNCREATABLE("") public: QmlObjectListModel(QObject* parent = nullptr); ~QmlObjectListModel() override; Q_PROPERTY(int count READ count NOTIFY countChanged) /// Returns true if any of the items in the list are dirty. Requires each object to have /// a dirty property and dirtyChanged signal. Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) Q_INVOKABLE QObject* get(int index); const QObject *get(int index) const; // Property accessors int count () const; bool dirty () const { return _dirty; } void setDirty (bool dirty); void append (QObject* object); void append (QList<QObject*> objects); QObjectList swapObjectList (const QObjectList& newlist); void clear (); QObject* removeAt (int i); QObject* removeOne (const QObject* object) { return removeAt(indexOf(object)); } void insert (int i, QObject* object); void insert (int i, QList<QObject*> objects); bool contains (const QObject* object) { return _objectList.indexOf(object) != -1; } int indexOf (const QObject* object) { return _objectList.indexOf(object); } /// Moves an item to a new position void move(int from, int to); QObject* operator[] (int i); const QObject* operator[] (int i) const; template<class T> T value (int index) const { return qobject_cast<T>(_objectList[index]); } QList<QObject*>* objectList () { return &_objectList; } /// Calls deleteLater on all items and this itself. void deleteListAndContents (); /// Clears the list and calls deleteLater on each entry void clearAndDeleteContents (); /// These methods handling nesting a begin/end pairs. Such that only the outermost /// beginResetModel/endResetModel pair will emit modelReset. void beginResetModel (); void endResetModel (); signals: void countChanged (int count); void dirtyChanged (bool dirtyChanged); private slots: void _childDirtyChanged (bool dirty); private: void _signalCountChangedIfNotNested(); // Overrides from QAbstractListModel int rowCount (const QModelIndex & parent = QModelIndex()) const override; QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const override; bool insertRows (int position, int rows, const QModelIndex &index = QModelIndex()) override; bool removeRows (int position, int rows, const QModelIndex &index = QModelIndex()) override; bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; QHash<int, QByteArray> roleNames(void) const override; private: QList<QObject*> _objectList; bool _dirty; bool _skipDirtyFirstItem; uint _resetModelNestingCount = 0; static constexpr int ObjectRole = Qt::UserRole; static constexpr int TextRole = Qt::UserRole + 1; };
/** * @since 4.0.0 */ import * as Arr from "../collections/Array.ts" import * as MutableHashMap from "../collections/MutableHashMap.ts" import * as Option from "../data/Option.ts" import type { Predicate } from "../data/Predicate.ts" import * as Deferred from "../Deferred.ts" import type * as Effect from "../Effect.ts" import type * as Exit from "../Exit.ts" import * as Fiber from "../Fiber.ts" import { dual, identity } from "../Function.ts" import type { Pipeable } from "../interfaces/Pipeable.ts" import * as core from "../internal/core.ts" import { PipeInspectableProto } from "../internal/core.ts" import * as effect from "../internal/effect.ts" import * as Scope from "../Scope.ts" import * as ServiceMap from "../ServiceMap.ts" import * as Duration from "../time/Duration.ts" /** * @since 4.0.0 * @category Type Identifiers */ export const TypeId: TypeId = "~effect/caching/ScopedCache" /** * @since 4.0.0 * @category Type Identifiers */ export type TypeId = "~effect/caching/ScopedCache" /** * @since 4.0.0 * @category Models */ export interface ScopedCache<in out Key, in out A, in out E = never, out R = never> extends Pipeable { readonly [TypeId]: TypeId state: State<Key, A, E> readonly capacity: number readonly lookup: (key: Key) => Effect.Effect<A, E, R | Scope.Scope> readonly timeToLive: (exit: Exit.Exit<A, E>, key: Key) => Duration.Duration } /** * @since 4.0.0 * @category Models */ export type State<K, A, E> = { readonly _tag: "Open" readonly map: MutableHashMap.MutableHashMap<K, Entry<A, E>> } | { readonly _tag: "Closed" } /** * Represents a cache entry containing a deferred value and optional expiration time. * This is used internally by the cache implementation to track cached values and their lifetimes. * * @since 4.0.0 * @category Models */ export interface Entry<A, E> { expiresAt: number | undefined readonly deferred: Deferred.Deferred<A, E> readonly scope: Scope.Scope.Closeable } /** * @since 4.0.0 * @category Constructors */ export const makeWith = < Key, A, E = never, R = never, ServiceMode extends "lookup" | "construction" = never >(options: { readonly lookup: (key: Key) => Effect.Effect<A, E, R | Scope.Scope> readonly capacity: number readonly timeToLive?: ((exit: Exit.Exit<A, E>, key: Key) => Duration.DurationInput) | undefined readonly requireServicesAt?: ServiceMode | undefined }): Effect.Effect< ScopedCache<Key, A, E, "lookup" extends ServiceMode ? Exclude<R, Scope.Scope> : never>, never, ("lookup" extends ServiceMode ? never : R) | Scope.Scope > => effect.servicesWith((services: ServiceMap.ServiceMap<any>) => { const scope = ServiceMap.unsafeGet(services, Scope.Scope) const self = Object.create(Proto) self.lookup = (key: Key): Effect.Effect<A, E> => effect.updateServices( options.lookup(key), (input) => ServiceMap.merge(services, input) ) const map = MutableHashMap.empty<Key, Entry<A, E>>() self.state = { _tag: "Open", map } self.capacity = options.capacity self.timeToLive = options.timeToLive ? (exit: Exit.Exit<A, E>, key: Key) => Duration.decode(options.timeToLive!(exit, key)) : defaultTimeToLive return effect.as( Scope.addFinalizer( scope, core.withFiber((fiber) => { self.state = { _tag: "Closed" } return invalidateAllImpl(fiber, map) }) ), self ) }) /** * @since 4.0.0 * @category Constructors */ export const make = < Key, A, E = never, R = never, ServiceMode extends "lookup" | "construction" = never >( options: { readonly lookup: (key: Key) => Effect.Effect<A, E, R | Scope.Scope> readonly capacity: number readonly timeToLive?: Duration.DurationInput | undefined readonly requireServicesAt?: ServiceMode | undefined } ): Effect.Effect< ScopedCache<Key, A, E, "lookup" extends ServiceMode ? Exclude<R, Scope.Scope> : never>, never, ("lookup" extends ServiceMode ? never : R) | Scope.Scope > => makeWith<Key, A, E, R, ServiceMode>({ ...options, timeToLive: options.timeToLive ? () => options.timeToLive! : defaultTimeToLive }) const Proto = { ...PipeInspectableProto, [TypeId]: TypeId, toJSON(this: ScopedCache<any, any, any>) { return { _id: "ScopedCache", capacity: this.capacity, state: this.state } } } const defaultTimeToLive = <A, E>(_: Exit.Exit<A, E>, _key: unknown): Duration.Duration => Duration.infinity /** * @since 4.0.0 * @category Combinators */ export const get: { <Key, A>(key: Key): <E, R>(self: ScopedCache<Key, A, E, R>) => Effect.Effect<A, E, R> <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect.Effect<A, E, R> } = dual( 2, <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect.Effect<A, E, R> => effect.uninterruptibleMask((restore) => core.withFiber((fiber) => { const state = self.state if (state._tag === "Closed") { return effect.interrupt } const oentry = MutableHashMap.get(state.map, key) if (Option.isSome(oentry) && !hasExpired(oentry.value, fiber)) { // Move the entry to the end of the map to keep it fresh MutableHashMap.remove(state.map, key) MutableHashMap.set(state.map, key, oentry.value) return restore(Deferred.await(oentry.value.deferred)) } const scope = Scope.unsafeMake() const deferred = Deferred.unsafeMake<A, E>() const entry: Entry<A, E> = { expiresAt: undefined, deferred, scope } MutableHashMap.set(state.map, key, entry) return checkCapacity(fiber, state.map, self.capacity).pipe( Option.isSome(oentry) ? effect.flatMap(() => oentry.value.scope.close(effect.exitVoid)) : identity, effect.flatMap(() => Scope.provide(restore(self.lookup(key)), scope)), effect.onExit((exit) => { Deferred.unsafeDone(deferred, exit) const ttl = self.timeToLive(exit, key) if (Duration.isFinite(ttl)) { entry.expiresAt = fiber.getRef(effect.ClockRef).unsafeCurrentTimeMillis() + Duration.toMillis(ttl) } return effect.void }) ) }) ) ) const hasExpired = <A, E>(entry: Entry<A, E>, fiber: Fiber.Fiber<unknown, unknown>): boolean => { if (entry.expiresAt === undefined) { return false } return fiber.getRef(effect.ClockRef).unsafeCurrentTimeMillis() >= entry.expiresAt } const checkCapacity = <K, A, E>( parent: Fiber.Fiber<unknown, unknown>, map: MutableHashMap.MutableHashMap<K, Entry<A, E>>, capacity: number ): Effect.Effect<void> => { let diff = MutableHashMap.size(map) - capacity if (diff <= 0) return effect.void // MutableHashMap has insertion order, so we can remove the oldest entries const fibers = Arr.empty<Fiber.Fiber<unknown, unknown>>() for (const [key, entry] of map) { MutableHashMap.remove(map, key) fibers.push(effect.unsafeFork(parent as any, entry.scope.close(effect.exitVoid), true)) diff-- if (diff === 0) break } return effect.fiberAwaitAll(fibers) } /** * @since 4.0.0 * @category Combinators */ export const getOption: { <Key, A>(key: Key): <E, R>(self: ScopedCache<Key, A, E, R>) => Effect.Effect<Option.Option<A>, E> <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect.Effect<Option.Option<A>, E> } = dual( 2, <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect.Effect<Option.Option<A>, E> => effect.uninterruptibleMask((restore) => core.withFiber((fiber) => effect.flatMap( getOptionImpl(self, key, fiber), (oentry) => Option.isSome(oentry) ? effect.asSome(restore(Deferred.await(oentry.value.deferred))) : effect.succeedNone ) ) ) ) const getOptionImpl = <Key, A, E, R>( self: ScopedCache<Key, A, E, R>, key: Key, fiber: Fiber.Fiber<any, any>, isRead = true ): Effect.Effect<Option.Option<Entry<A, E>>> => { if (self.state._tag === "Closed") { return effect.interrupt } const state = self.state const oentry = MutableHashMap.get(state.map, key) if (Option.isNone(oentry)) { return effect.succeedNone } else if (hasExpired(oentry.value, fiber)) { MutableHashMap.remove(state.map, key) return effect.as( oentry.value.scope.close(effect.exitVoid), Option.none() ) } else if (isRead) { MutableHashMap.remove(state.map, key) MutableHashMap.set(state.map, key, oentry.value) } return effect.succeedSome(oentry.value) } /** * Retrieves the value associated with the specified key from the cache, only if * it contains a resolved successful value. * * @since 4.0.0 * @category Combinators */ export const getSuccess: { <Key, A, R>(key: Key): <E>(self: ScopedCache<Key, A, E, R>) => Effect.Effect<Option.Option<A>> <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect.Effect<Option.Option<A>> } = dual( 2, <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect.Effect<Option.Option<A>> => effect.uninterruptible( core.withFiber((fiber) => effect.map( getOptionImpl(self, key, fiber), (o) => o.pipe( Option.flatMapNullishOr((entry) => entry.deferred.effect as Exit.Exit<A, E>), Option.flatMap((exit) => effect.exitIsSuccess(exit) ? Option.some(exit.value) : Option.none()) ) ) ) ) ) /** * Sets the value associated with the specified key in the cache. This will * overwrite any existing value for that key, skipping the lookup function. * * @since 4.0.0 * @category Combinators */ export const set: { <Key, A>(key: Key, value: A): <E, R>(self: ScopedCache<Key, A, E, R>) => Effect.Effect<void> <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key, value: A): Effect.Effect<void> } = dual( 3, <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key, value: A): Effect.Effect<void> => effect.uninterruptible( core.withFiber((fiber) => { if (self.state._tag === "Closed") { return effect.interrupt } const oentry = MutableHashMap.get(self.state.map, key) const state = self.state const exit = core.exitSucceed(value) const deferred = Deferred.unsafeMake<A, E>() Deferred.unsafeDone(deferred, exit) const ttl = self.timeToLive(exit, key) MutableHashMap.set(state.map, key, { scope: Scope.unsafeMake(), deferred, expiresAt: Duration.isFinite(ttl) ? fiber.getRef(effect.ClockRef).unsafeCurrentTimeMillis() + Duration.toMillis(ttl) : undefined }) const check = checkCapacity(fiber, state.map, self.capacity) return Option.isSome(oentry) ? effect.flatMap(oentry.value.scope.close(effect.exitVoid), () => check) : check }) ) ) /** * Checks if the cache contains an entry for the specified key. * * @since 4.0.0 * @category Combinators */ export const has: { <Key, A>(key: Key): <E, R>(self: ScopedCache<Key, A, E, R>) => Effect.Effect<boolean> <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect.Effect<boolean> } = dual( 2, <Key, A, E>(self: ScopedCache<Key, A, E>, key: Key): Effect.Effect<boolean> => effect.uninterruptible( core.withFiber((fiber) => effect.map(getOptionImpl(self, key, fiber, false), Option.isSome)) ) ) /** * Invalidates the entry associated with the specified key in the cache. * * @since 4.0.0 * @category Combinators */ export const invalidate: { <Key, A>(key: Key): <E, R>(self: ScopedCache<Key, A, E, R>) => Effect.Effect<void> <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect.Effect<void> } = dual(2, <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect.Effect<void> => effect.uninterruptible( effect.suspend(() => { if (self.state._tag === "Closed") { return effect.interrupt } const oentry = MutableHashMap.get(self.state.map, key) if (Option.isNone(oentry)) { return effect.void } MutableHashMap.remove(self.state.map, key) return oentry.value.scope.close(effect.exitVoid) }) )) /** * Conditionally invalidates the entry associated with the specified key in the cache * if the predicate returns true for the cached value. * * @since 4.0.0 * @category Combinators */ export const invalidateWhen: { <Key, A>(key: Key, f: Predicate<A>): <E, R>(self: ScopedCache<Key, A, E, R>) => Effect.Effect<boolean> <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key, f: Predicate<A>): Effect.Effect<boolean> } = dual( 3, <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key, f: Predicate<A>): Effect.Effect<boolean> => effect.uninterruptibleMask((restore) => core.withFiber((fiber) => effect.flatMap(getOptionImpl(self, key, fiber, false), (oentry) => { if (Option.isNone(oentry)) { return effect.succeed(false) } return restore(Deferred.await(oentry.value.deferred)).pipe( effect.flatMap((value) => { if (self.state._tag === "Closed") { return effect.succeed(false) } else if (f(value)) { MutableHashMap.remove(self.state.map, key) return effect.as(oentry.value.scope.close(effect.exitVoid), true) } return effect.succeed(false) }), effect.catch_(() => effect.succeed(false)) ) }) ) ) ) /** * Forces a refresh of the value associated with the specified key in the cache. * * It will always invoke the lookup function to construct a new value, * overwriting any existing value for that key. * * @since 4.0.0 * @category Combinators */ export const refresh: { <Key, A>(key: Key): <E, R>(self: ScopedCache<Key, A, E, R>) => Effect.Effect<A, E, R> <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect.Effect<A, E, R> } = dual( 2, <Key, A, E, R>(self: ScopedCache<Key, A, E, R>, key: Key): Effect.Effect<A, E, R> => effect.uninterruptibleMask(effect.fnUntraced(function*(restore) { if (self.state._tag === "Closed") return yield* effect.interrupt const fiber = Fiber.getCurrent()! const scope = Scope.unsafeMake() const deferred = Deferred.unsafeMake<A, E>() const entry: Entry<A, E> = { scope, expiresAt: undefined, deferred } const newEntry = !MutableHashMap.has(self.state.map, key) if (newEntry) { MutableHashMap.set(self.state.map, key, entry) yield* checkCapacity(fiber, self.state.map, self.capacity) } const exit = yield* effect.exit(restore(Scope.provide(self.lookup(key), scope))) Deferred.unsafeDone(deferred, exit) // @ts-ignore async gap if (self.state._tag === "Closed") { if (!newEntry) { yield* scope.close(effect.exitVoid) } return yield* effect.interrupt } const ttl = self.timeToLive(exit, key) entry.expiresAt = Duration.isFinite(ttl) ? fiber.getRef(effect.ClockRef).unsafeCurrentTimeMillis() + Duration.toMillis(ttl) : undefined if (!newEntry) { const oentry = MutableHashMap.get(self.state.map, key) MutableHashMap.set(self.state.map, key, entry) if (Option.isSome(oentry)) { yield* oentry.value.scope.close(effect.exitVoid) } } return yield* exit })) ) /** * Invalidates all entries in the cache. * * @since 4.0.0 * @category Combinators */ export const invalidateAll = <Key, A, E, R>(self: ScopedCache<Key, A, E, R>): Effect.Effect<void> => core.withFiber((parent) => { if (self.state._tag === "Closed") { return effect.interrupt } return invalidateAllImpl(parent, self.state.map) }) const invalidateAllImpl = <Key, A, E>( parent: Fiber.Fiber<unknown, unknown>, map: MutableHashMap.MutableHashMap<Key, Entry<A, E>> ): Effect.Effect<void> => { const fibers = Arr.empty<Fiber.Fiber<unknown, unknown>>() for (const [, entry] of map) { fibers.push(effect.unsafeFork(parent as any, entry.scope.close(effect.exitVoid), true, true)) } MutableHashMap.clear(map) return effect.fiberAwaitAll(fibers) } /** * Retrieves the approximate number of entries in the cache. * * Note that expired entries are counted until they are accessed and removed. * The size reflects the current number of entries stored, not the number * of valid entries. * * @since 4.0.0 * @category Combinators */ export const size = <Key, A, E, R>(self: ScopedCache<Key, A, E, R>): Effect.Effect<number> => effect.sync(() => self.state._tag === "Closed" ? 0 : MutableHashMap.size(self.state.map)) /** * Retrieves all active keys from the cache, automatically filtering out expired entries. * * @since 4.0.0 * @category Combinators */ export const keys = <Key, A, E, R>(self: ScopedCache<Key, A, E, R>): Effect.Effect<Array<Key>> => core.withFiber((fiber) => { if (self.state._tag === "Closed") return effect.succeed([]) const state = self.state const now = fiber.getRef(effect.ClockRef).unsafeCurrentTimeMillis() const fibers = Arr.empty<Fiber.Fiber<unknown, unknown>>() const keys = Arr.filterMap(state.map, ([key, entry]) => { if (entry.expiresAt === undefined || entry.expiresAt > now) { return Option.some(key) } MutableHashMap.remove(state.map, key) fibers.push(effect.unsafeFork(fiber, entry.scope.close(effect.exitVoid), true, true)) return Option.none() }) return fibers.length === 0 ? effect.succeed(keys) : effect.as(effect.fiberAwaitAll(fibers), keys) }) /** * Retrieves all successfully cached values from the cache, excluding failed * lookups and expired entries. * * @since 4.0.0 * @category Combinators */ export const values = <Key, A, E, R>(self: ScopedCache<Key, A, E, R>): Effect.Effect<Array<A>> => effect.map(entries(self), Arr.map(([, value]) => value)) /** * Retrieves all key-value pairs from the cache as an iterable. This function * only returns entries with successfully resolved values, filtering out any * failed lookups or expired entries. * * @since 4.0.0 * @category Combinators */ export const entries = <Key, A, E, R>(self: ScopedCache<Key, A, E, R>): Effect.Effect<Array<[Key, A]>> => core.withFiber((fiber) => { if (self.state._tag === "Closed") return effect.succeed([]) const state = self.state const now = fiber.getRef(effect.ClockRef).unsafeCurrentTimeMillis() const fibers = Arr.empty<Fiber.Fiber<unknown, unknown>>() const arr = Arr.filterMap(state.map, ([key, entry]) => { if (entry.expiresAt === undefined || entry.expiresAt > now) { const exit = entry.deferred.effect return !core.isExit(exit) || effect.exitIsFailure(exit) ? Option.none() : Option.some([key, exit.value as A] as [Key, A]) } MutableHashMap.remove(state.map, key) fibers.push(effect.unsafeFork(fiber, entry.scope.close(effect.exitVoid), true, true)) return Option.none() }) return fibers.length === 0 ? effect.succeed(arr) : effect.as(effect.fiberAwaitAll(fibers), arr) })
© 2025 Ethan Morgan. All rights reserved.