### Install and Run the Todo App Source: https://github.com/logosdx/monorepo/blob/master/example/README.md Commands to install project dependencies and start the development servers for both the Hapi.js API and the Vite dev server. This allows for live development of the Vanilla JS and React UIs. ```bash pnpm install pnpm dev ``` -------------------------------- ### LogosDX React Quick Start Setup Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/react.md A comprehensive setup example demonstrating how to create engine instances for various LogosDX modules (Observer, Fetch, Storage, Localize, StateMachine) and then create corresponding context providers and hooks using the @logosdx/react bindings. It also shows how to compose these providers into a single wrapper. ```typescript // setup.ts — run once, types inferred from instances import { ObserverEngine } from '@logosdx/observer'; import { FetchEngine } from '@logosdx/fetch'; import { StorageAdapter, WebStorageDriver } from '@logosdx/storage'; import { LocaleManager } from '@logosdx/localize'; import { StateMachine } from '@logosdx/state-machine'; import { createObserverContext, createFetchContext, createStorageContext, createLocalizeContext, createStateMachineContext, composeProviders, } from '@logosdx/react'; // Create your engine instances const observer = new ObserverEngine(); const api = new FetchEngine({ baseUrl: 'https://api.example.com' }); const storage = new StorageAdapter({ driver: new WebStorageDriver(localStorage), prefix: 'myapp', }); const i18n = new LocaleManager({ current: 'en', fallback: 'en', locales }); const game = new StateMachine({ ... }); // Create context + hook pairs — rename freely export const [AppObserver, useAppObserver] = createObserverContext(observer); export const [ApiFetch, useApiFetch] = createFetchContext(api); export const [AppStorage, useAppStorage] = createStorageContext(storage); export const [AppLocale, useAppLocale] = createLocalizeContext(i18n); export const [GameProvider, useGame] = createStateMachineContext(game); // Compose into a single wrapper — no nesting required export const Providers = composeProviders( AppObserver, ApiFetch, AppStorage, AppLocale, GameProvider, ); ``` -------------------------------- ### Configuring and Using FetchEngine for API Requests Source: https://github.com/logosdx/monorepo/blob/master/docs/getting-started.md Illustrates the setup and usage of FetchEngine for making API calls. It includes defining base URLs, retry strategies, default headers, and managing state for authentication tokens. ```typescript import { FetchEngine } from '@logosdx/fetch'; import { attempt } from '@logosdx/utils' // Your Fetch instance can have a state from which you can make // decisions about the request. type ApiState = { authToken: string; userId: string; } // You can also define headers and query params // you will expect throughout your app. type ApiHeaders = { 'X-User-ID': string; } type ApiQueryParams = { page: string; } const api = new FetchEngine({ baseUrl: 'https://rainbow-loans.com', retry: { maxAttempts: 3, retryableStatusCodes: [501, 502, 503, 504] }, headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' } }); observer.on('user:login', ({ userId, token }) => { // Once you have a token, you can set the state of the // Fetch instance to use it in the next request. api.state.set({ authToken: token, userId }); }); observer.on('user:logout', () => { // When the user logs out, you can clear the state of the // Fetch instance to avoid using the token in the next request. api.state.set({ authToken: null, userId: null }); }); export const signIn = async (user: string, password: string) => { // Go-style error handling, with type safety. const [response, err] = await attempt(() => api.post('/signin', { user, password })); if (err) { observer.emit('user:login-failed', { userId: user, error: err }); throw err; } const { userId, token } = response.data; observer.emit('user:login', { userId: user, token, timestamp: Date.now() }); return user; } ``` -------------------------------- ### GET Request Example Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/fetch/requests.md Demonstrates how to retrieve data from a server using the GET method. It shows fetching a list of users and a specific user with query parameters. ```typescript const { data: users } = await api.get('/users'); const { data: user } = await api.get('/users/123', { params: { include: 'profile' } }); ``` -------------------------------- ### Install LogosDX Packages with npm, yarn, or pnpm Source: https://github.com/logosdx/monorepo/blob/master/docs/getting-started.md Install the necessary LogosDX packages for your project using your preferred package manager. This ensures you have the latest versions of observer, utils, and fetch modules available for use. ```bash npm install @logosdx/observer @logosdx/utils @logosdx/fetch # ...etc. ``` ```bash yarn add @logosdx/observer @logosdx/utils @logosdx/fetch # ...etc. ``` ```bash pnpm add @logosdx/observer @logosdx/utils @logosdx/fetch # ...etc. ``` -------------------------------- ### Quick start with FetchEngine for API requests in TypeScript Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/fetch/index.md This TypeScript example shows how to create an instance of FetchEngine and make a GET request to fetch user data. It utilizes the `attempt` utility for graceful error handling and demonstrates accessing response data, status, and headers. ```typescript import { FetchEngine } from '@logosdx/fetch' import { attempt } from '@logosdx/utils' // Create HTTP client const api = new FetchEngine({ baseUrl: 'https://api.example.com', defaultType: 'json', totalTimeout: 5000 }); // Make requests with error handling const [response, err] = await attempt(() => api.get('/users')); if (err) { console.error('Failed to fetch users:', err.message); return; } // Access response data and metadata console.log('Users:', response.data); console.log('Status:', response.status); console.log('Headers:', response.headers['content-type']); ``` -------------------------------- ### Quick Start with @logosdx/storage in TypeScript Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/storage/index.md This TypeScript example demonstrates the basic usage of @logosdx/storage. It shows how to initialize a StorageAdapter with a specific driver and prefix, perform set and get operations, subscribe to storage events, merge object properties, and clean up listeners. ```typescript import { StorageAdapter, LocalStorageDriver } from '@logosdx/storage' interface AppStorage { user: { id: string; name: string; email: string } settings: { theme: 'light' | 'dark'; notifications: boolean } cart: { id: string; quantity: number }[] } const storage = new StorageAdapter({ driver: new LocalStorageDriver(), prefix: 'myapp' }) // All operations are async await storage.set('user', { id: '123', name: 'Jane', email: 'jane@example.com' }) const user = await storage.get('user') // Subscribe to updates (returns cleanup function) const cleanup = storage.on('after-set', (event) => { console.log('Set:', event.key, event.value) }) // Merge object properties await storage.assign('settings', { notifications: false }) // Remove and clear await storage.rm(['user', 'settings']) await storage.clear() // Cleanup listener when done cleanup() ``` -------------------------------- ### Start Web UI Server Source: https://github.com/logosdx/monorepo/blob/master/tests/src/_memory-tests/README.md This command starts the web-based UI server for visualizing test results. It uses `pnpm tsx` to execute the server script. After starting, the UI can be accessed via a web browser. ```bash # Start the UI server pnpm tsx src/experiments/memory-tests/ui/server.ts # Open in browser open http://localhost:3456 ``` -------------------------------- ### Implementing Rate Limiting and Circuit Breaker with FetchEngine Source: https://github.com/logosdx/monorepo/blob/master/docs/getting-started.md Demonstrates how to enhance API requests using `composeFlow` from `@logosdx/utils` to add rate limiting and circuit breaker patterns to a FetchEngine instance. This example shows how to configure these features and handle their respective events. ```typescript import { composeFlow, attempt } from '@logosdx/utils'; const painPal = new FetchEngine({ baseUrl: 'https://painpal.com', retry: { maxAttempts: 3, retryableStatusCodes: [429, 501, 502, 503, 504] }, headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-API-Key': 'painpal-api-key' } }); const _makePayment = async (paymentToken: string, amount: number) => { const [response, err] = await attempt(() => api.post('/payments', { paymentToken, amount })); if (err) { observer.emit('payment:failed', { paymentToken, amount, error: err }); throw err; } observer.emit('payment:success', { paymentToken, amount, timestamp: Date.now() }); return response.data; } // This makePayment function is now rate-limited to 10 // calls per second, and has a circuit breaker that trips // after 3 failures. const makePayment = composeFlow( _makePayment, { circuitBreaker: { maxFailures: 3, resetAfter: 1000, onTripped: (error) => { console.log('PainPal is being sensitive again', error); } }, rateLimit: { maxCalls: 10, windowMs: 1000, onLimitReached: (error, nextAvailable, args) => { console.log('We might be over-doing it...', error); console.log('Try again at', nextAvailable); } }, } ); ``` -------------------------------- ### Installing Plugins at Runtime Source: https://github.com/logosdx/monorepo/blob/master/skills/logosdx/references/fetch.md Explains how to install a plugin dynamically to a running FetchEngine instance using the `engine.use(plugin)` method and how to uninstall it later. ```APIDOC ## Installing Plugins at Runtime ### Description This endpoint allows for the dynamic installation of plugins into an active `FetchEngine` instance. The `engine.use(plugin)` method accepts a plugin object and integrates it into the engine's hook system. It returns a cleanup function that can be called later to remove the plugin. ### Method `use` (Instance Method) ### Endpoint N/A (Instance Method) ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body - **plugin** (object) - Required - The plugin object to install. ### Request Example ```typescript // Assuming 'api' is an instance of FetchEngine and 'myPlugin' is a valid plugin object const cleanup = api.use(myPlugin); // To uninstall the plugin later: // cleanup(); ``` ### Response #### Success Response (200) - **cleanup** (function) - A function that, when called, uninstalls the plugin. #### Response Example N/A (Function return value) ``` -------------------------------- ### Multi-Package Manager Installation Commands Source: https://github.com/logosdx/monorepo/blob/master/docs/CLAUDE.md Provides installation commands for a package using npm, yarn, and pnpm, facilitating easy setup for users regardless of their preferred package manager. ```markdown ::: code-group ```bash [npm] npm install @logosdx/utils ``` ```bash [yarn] yarn add @logosdx/utils ``` ```bash [pnpm] pnpm add @logosdx/utils ``` ::: ``` -------------------------------- ### Managing FetchEngine configuration and state in TypeScript Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/fetch/index.md This TypeScript example illustrates how to use the manager objects (`headers`, `state`, `config`) exposed by a FetchEngine instance. It shows how to set and get headers, state values, and modify configuration like the base URL at runtime. ```typescript // Set headers api.headers.set('Authorization', 'Bearer token'); // Set state api.state.set('userId', '123'); // Change configuration api.config.set('baseUrl', 'https://new-api.example.com'); // Get current config const baseUrl = api.config.get('baseUrl'); ``` -------------------------------- ### Widget Lifecycle Example Source: https://github.com/logosdx/monorepo/blob/master/docs/public/llms-full.txt An example demonstrating how to initialize a chat widget, manage its lifecycle, and ensure proper cleanup using AbortController. ```APIDOC ## Widget Lifecycle Example ### Description Illustrates a common pattern for initializing complex UI widgets, integrating various utility functions from the library and ensuring all associated listeners and observers are cleaned up when the widget is no longer needed. ### Method This is a usage example, not a direct API method. ### Parameters None ### Request Example ```ts function initChatWidget(container: HTMLElement) { const controller = new AbortController(); const ui = $(container, { signal: controller.signal }); ui.class.add('chat-active'); ui.aria({ role: 'dialog', label: 'Customer support' }); ui.css({ '--chat-bg': '#fff' }); ui.on('click', handler); observe('[data-emoji]', initEmoji, { signal: controller.signal }); watchResize(container, relayout, { signal: controller.signal }); return () => controller.abort(); // single cleanup for everything } ``` ### Response #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Installing Built-in Plugins at Construction Time Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/fetch/plugins.md Demonstrates how to install multiple built-in FetchEngine plugins (retry, cache, dedupe, rate-limit) when initializing a new FetchEngine instance. Each plugin can be configured with specific options. ```typescript import { FetchEngine, retryPlugin, cachePlugin, dedupePlugin, rateLimitPlugin } from '@logosdx/fetch'; const api = new FetchEngine({ baseUrl: 'https://api.example.com', plugins: [ retryPlugin({ maxAttempts: 3, baseDelay: 1000 }), cachePlugin({ ttl: 60000, staleIn: 30000 }), dedupePlugin(true), rateLimitPlugin({ maxCalls: 100, windowMs: 60000 }), ] }); ``` -------------------------------- ### Install @logosdx/fetch using npm, yarn, or pnpm Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/fetch/index.md These commands show how to install the @logosdx/fetch package using different package managers. This is the first step to integrating the library into your project. ```bash npm install @logosdx/fetch ``` ```bash yarn add @logosdx/fetch ``` ```bash pnpm add @logosdx/fetch ``` -------------------------------- ### Install and Build Dependencies with pnpm Source: https://github.com/logosdx/monorepo/blob/master/CONTRIBUTING.md Commands to install project dependencies, build all packages, run tests, and enable watch mode for development using pnpm. ```bash pnpm install pnpm build pnpm test pnpm watch ``` -------------------------------- ### Start Web UI Server (Bash) Source: https://github.com/logosdx/monorepo/blob/master/tests/src/_memory-tests/CLAUDE.md Command to start the memory UI server using pnpm. This command launches a local development server that allows visualization of memory test results. ```bash pnpm memory:ui # Opens at http://localhost:3456 ``` -------------------------------- ### beforeRequest Hook Examples in TypeScript Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/fetch/hooks.md Provides practical examples of 'beforeRequest' hooks: adding authentication headers, short-circuiting requests with cached data, and conditional logging based on request method and body. ```typescript // Add auth header to every request api.hooks.add('beforeRequest', (url, opts, ctx) => { ctx.args(url, { ...opts, headers: { ...opts.headers, Authorization: `Bearer ${opts.state.token}` } }); }); // Short-circuit with a cached response api.hooks.add('beforeRequest', (url, opts, ctx) => { const cached = myCache.get(url.toString()); if (cached) { return ctx.returns(cached); } }); // Conditional logging api.hooks.add('beforeRequest', (url, opts, ctx) => { if (opts.method === 'POST') { console.log('POST to', url.pathname, opts.body); } }); ``` -------------------------------- ### Initial Load and SSE Connection Setup Source: https://github.com/logosdx/monorepo/blob/master/tests/src/_memory-tests/ui/index.html Executes initial setup functions when the script loads. It calls `loadFiles()` to populate the file list and `setupSSE()` to establish the Server-Sent Events connection for real-time updates. ```javascript // Initial load loadFiles(); // Start SSE connection setup setupSSE(); ``` -------------------------------- ### OPTIONS Request Example Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/fetch/requests.md Shows how to check server capabilities using the OPTIONS method. It demonstrates retrieving response headers. ```typescript const { headers } = await api.options('/users'); ``` -------------------------------- ### Core API Setup and Usage Source: https://github.com/logosdx/monorepo/blob/master/skills/logosdx/references/fetch.md Demonstrates how to set up and use the FetchEngine for making HTTP requests, including basic error handling with the attempt utility. ```APIDOC ## Core API Setup and Usage ### Description This section covers the fundamental setup of the `FetchEngine` and provides an example of making a GET request with error handling. ### Method N/A (Illustrative Setup) ### Endpoint N/A (Illustrative Setup) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```typescript import { FetchEngine, isFetchError } from '@logosdx/fetch'; import { attempt } from '@logosdx/utils'; // Basic setup const api = new FetchEngine({ baseUrl: 'https://api.example.com', defaultType: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData', headers: { Authorization: 'Bearer token' }, totalTimeout: 5000, // Total timeout for entire operation (including retries) attemptTimeout: 2000 // Per-attempt timeout (allows retries on timeout) }); // Error handling pattern const [response, err] = await attempt(() => api.get('/users/123')); if (err) { console.error('Request failed:', err.status, err.message); return; } const { data: user } = response; console.log('User:', user); console.log('Rate limit:', response.headers['x-rate-limit-remaining']); ``` ### Response #### Success Response (200) - **data** (any) - The parsed response body. - **headers** (object) - Response headers. - **status** (number) - HTTP status code. - **request** (Request) - The original request object. - **config** (FetchConfig) - The typed configuration used for the request. #### Response Example ```json { "data": { "id": 123, "name": "John Doe" }, "headers": { "x-rate-limit-remaining": "1000" }, "status": 200, "request": { ... }, "config": { ... } } ``` ``` -------------------------------- ### Initialize FetchEngine with Custom Configuration Source: https://github.com/logosdx/monorepo/blob/master/docs/public/llms-full.txt Demonstrates how to create a new instance of FetchEngine with specific configurations for base URL, default content type, headers, and various timeout settings. This setup is crucial for managing API interactions in production environments. ```typescript import { FetchEngine, FetchError, FetchEvent, FetchEventNames, FetchResponse, isFetchError } from '@logosdx/fetch'; import { attempt } from '@logosdx/utils'; // Basic setup const api = new FetchEngine({ baseUrl: 'https://api.example.com', defaultType: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData', headers: { Authorization: 'Bearer token' }, totalTimeout: 5000, // Total timeout for entire operation (including retries) attemptTimeout: 2000 // Per-attempt timeout (allows retries on timeout) }); ``` -------------------------------- ### Basic Setup and Error Handling with FetchEngine Source: https://github.com/logosdx/monorepo/blob/master/skills/logosdx/references/fetch.md Demonstrates how to initialize FetchEngine with custom configurations like baseUrl, defaultType, headers, and timeouts. It also shows a common error handling pattern using the `attempt` utility to gracefully manage API request failures. ```typescript import { FetchEngine, FetchError, FetchEvent, FetchEventNames, FetchResponse, isFetchError } from '@logosdx/fetch'; import { attempt } from '@logosdx/utils'; // Basic setup const api = new FetchEngine({ baseUrl: 'https://api.example.com', defaultType: 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData', headers: { Authorization: 'Bearer token' }, totalTimeout: 5000, // Total timeout for entire operation (including retries) attemptTimeout: 2000 // Per-attempt timeout (allows retries on timeout) }); // Error handling pattern const [response, err] = await attempt(() => api.get('/users/123')); if (err) { console.error('Request failed:', err.status, err.message); return; } const { data: user } = response; console.log('User:', user); console.log('Rate limit:', response.headers['x-rate-limit-remaining']); ``` -------------------------------- ### Cache Invalidation Example (TypeScript) Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/utils/performance.md Shows how to invalidate cache entries in SingleFlight based on a predicate function. This example invalidates all cache entries whose keys start with 'user:'. ```typescript // Invalidate by pattern await flight.invalidateCache(key => key.startsWith('user:')) ``` -------------------------------- ### POST Request Example Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/fetch/requests.md Illustrates creating a new resource on the server using the POST method. It includes sending a payload for user creation. ```typescript const { data: user } = await api.post('/users', { name: 'John Doe', email: 'john@example.com' }); ``` -------------------------------- ### afterRequest Hook Examples in TypeScript Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/fetch/hooks.md Showcases 'afterRequest' hooks for processing responses after a successful network call. Examples include caching successful GET responses and transforming response data before it's returned to the caller. ```typescript // Cache successful responses api.hooks.add('afterRequest', (response, url, opts, ctx) => { if (opts.method === 'GET' && response.status === 200) { myCache.set(url.toString(), response); } }); // Replace the response api.hooks.add('afterRequest', (response, url, opts, ctx) => { return ctx.returns({ ...response, data: transformData(response.data) }); }); ``` -------------------------------- ### FetchEngine Initialization with Plugins (TypeScript) Source: https://github.com/logosdx/monorepo/blob/master/packages/fetch/plan.md Demonstrates how to initialize FetchEngine with various plugins like cache, dedupe, retry, and rateLimit. It also shows how to optionally hook into plugin decisions and how to install/uninstall plugins at runtime. ```typescript import { FetchEngine, cachePlugin, dedupePlugin, retryPlugin, rateLimitPlugin } from '@logosdx/fetch'; const cache = cachePlugin({ ttl: 60_000, rules: [ { startsWith: '/static', ttl: 3_600_000 }, { startsWith: '/admin', enabled: false } ] }); const retry = retryPlugin({ count: 3, delay: 1000, rules: [ { startsWith: '/payments', enabled: false }, { startsWith: '/users', count: 5, delay: 500 } ] }); const dedupe = dedupePlugin({ enabled: true }); const rateLimit = rateLimitPlugin({ maxConcurrent: 10 }); // Hook into plugin decisions (optional) cache.hooks.add('shouldCache', (url, opts, ctx) => { if (url.pathname.includes('/live')) return ctx.returns(false); }); retry.hooks.add('shouldRetry', (error, attempt, opts, ctx) => { if (error.status === 401) return ctx.returns(false); }); // Pass plugins to engine const api = new FetchEngine({ baseUrl: '/api', plugins: [cache, dedupe, retry, rateLimit] }); // Or install at runtime const removeAuth = api.use(authPlugin(getToken)); removeAuth(); // uninstall later ``` -------------------------------- ### Set, Get, and Remove Data Attributes with @logosdx/dom Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/dom/styling.md Explains the usage of the `data` function from `@logosdx/dom` for setting, getting, and removing data attributes (via `dataset`) on elements. Examples include single/multiple attribute operations and chained calls. ```typescript import { data } from '@logosdx/dom'; data(el, { userId: '123', role: 'admin' }); // set via dataset data(el, 'userId'); // get → string | undefined data(el, ['userId', 'role']); // get → Record data.remove(el, 'userId'); // remove // Chained $('.card').data({ id: '1' }).data.remove('stale'); ``` -------------------------------- ### Distributed Caching with Custom Adapter (Redis Example - TypeScript) Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/utils/performance.md Implements a distributed caching strategy using a custom Redis adapter. This example shows how to create a `RedisCacheAdapter` that implements the `CacheAdapter` interface for `get` and `set` operations, enabling memoization across multiple servers. ```typescript import { MapCacheAdapter } from '@logosdx/utils' class RedisCacheAdapter implements CacheAdapter> { async get(key: string): Promise | undefined> { const data = await redis.get(key) return data ? JSON.parse(data) : undefined } async set(key: string, value: CacheItem, expiresAt: number): Promise { const ttl = Math.max(0, expiresAt - Date.now()) await redis.set(key, JSON.stringify(value), 'PX', ttl) } // ... implement other methods } const distributedCache = memoize(expensiveQuery, { adapter: new RedisCacheAdapter() }) ``` -------------------------------- ### FetchEngine Initialization with Different Plugin Configurations (TypeScript) Source: https://github.com/logosdx/monorepo/blob/master/packages/hooks/notes.md Illustrates various ways to initialize FetchEngine, from a minimal setup without plugins to a full suite of common plugins, and a custom mix tailored to specific needs. This highlights the flexibility in configuring the engine. ```typescript // Minimal — no plugins const bare = new FetchEngine({ baseUrl: '/api' }); // Full suite const full = new FetchEngine({ baseUrl: '/api', plugins: [cachePlugin(...), dedupePlugin(...), rateLimitPlugin(...)] }); // Custom mix const custom = new FetchEngine({ baseUrl: '/api', plugins: [rateLimitPlugin(...), authPlugin(...), loggingPlugin(...)] }); ``` -------------------------------- ### Non-Functional Load Test Example Source: https://github.com/logosdx/monorepo/blob/master/tests/CLAUDE.md An example of a non-functional test simulating concurrent requests to check system performance and resource management. This test verifies that the system can handle a high load without memory leaks. It assumes an `api` object with `get` and `cacheStats` methods. ```typescript it('should handle 100 concurrent requests', async () => { const promises = Array.from({ length: 100 }, () => api.get('/json')); const results = await Promise.all(promises); expect(api.cacheStats().inflightCount).to.equal(0); // No leaks }); ``` -------------------------------- ### FetchEngine Registration and Plugin Management (TypeScript) Source: https://github.com/logosdx/monorepo/blob/master/packages/hooks/notes.md Demonstrates how to construct a FetchEngine instance with plugins and how to dynamically add and remove plugins at runtime. The `use` method on FetchEngine is shown to facilitate plugin installation. ```typescript const api = new FetchEngine({ baseUrl: '/api', plugins: [cache, rateLimit, dedupe] }); const remove = api.use(loggingPlugin(logger)); remove(); // uninstall class FetchEngine { use(plugin: FetchPlugin) { return plugin.install(this); } } ``` -------------------------------- ### Advanced Event Handling with ObserverEngine using Regex Source: https://github.com/logosdx/monorepo/blob/master/docs/getting-started.md Shows how to use regular expressions with ObserverEngine's `on` method to listen for events matching a pattern. It also demonstrates how to unsubscribe from events. ```typescript const stopBeingNosy = observer.on(/^user:/, ({ event, data }) => { console.log(`🕵🏻‍♂️ ${data.userId} is doing something`, event, '👀'); }); observer.emit('user:login', { userId: 'alice', timestamp: Date.now() }); // 🕵🏻‍♂️ alice is doing something user:login 👀 observer.on('stop-being-nosy', () => stopBeingNosy()); ``` -------------------------------- ### Type-Safe Event Handling with ObserverEngine Source: https://github.com/logosdx/monorepo/blob/master/docs/getting-started.md Demonstrates how to define events with TypeScript interfaces and use ObserverEngine for type-safe event listening and emission. It covers basic event handling and emitting data payloads. ```typescript import { ObserverEngine } from '@logosdx/observer'; // Define your events like a civilized person interface AppEvents { 'user:login': { userId: string; token: string; timestamp: number }; 'user:logout': { userId: string }; 'user:login-failed': { userId: string; error: Error }; 'system:ready': void; } const observer = new ObserverEngine(); // Listen and emit with full type safety observer.on('user:login', ({ userId, timestamp }) => { console.log(`User ${userId} logged in at ${new Date(timestamp)}`); }); observer.emit('user:login', { userId: 'alice', token: 'alice-token', timestamp: Date.now() }); ``` -------------------------------- ### Installing a Plugin at Runtime Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/fetch/plugins.md Shows how to dynamically add a plugin to an existing FetchEngine instance using the `use` method. It also demonstrates how to remove the plugin's hooks later by calling the returned uninstall function. ```typescript const uninstall = api.use(myPlugin); // Later, remove the plugin's hooks uninstall(); ``` -------------------------------- ### Implement a custom RedisDriver Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/storage/drivers.md Shows a complete implementation of a custom `StorageDriver` using Redis as the backend. This example includes methods for `get`, `set`, `remove`, `keys`, and `clear` operations against a Redis instance. ```typescript import type { StorageDriver } from '@logosdx/storage' import Redis from 'ioredis' export class RedisDriver implements StorageDriver { #client: Redis constructor(redisUrl: string) { this.#client = new Redis(redisUrl) } async get(key: string) { const raw = await this.#client.get(key) return raw ?? null } async set(key: string, value: unknown) { await this.#client.set(key, String(value)) } async remove(key: string) { await this.#client.del(key) } async keys() { return this.#client.keys('*') } async clear() { const allKeys = await this.keys() if (allKeys.length > 0) { await this.#client.del(...allKeys) } } } // Usage const storage = new StorageAdapter({ driver: new RedisDriver('redis://localhost:6379'), prefix: 'sessions' }) ``` -------------------------------- ### Build the Todo App for Production Source: https://github.com/logosdx/monorepo/blob/master/example/README.md Command to build the project for production. This process generates separate bundles for the Vanilla JS and React UIs, optimized for deployment. ```bash pnpm build ``` -------------------------------- ### Install FetchEngine Plugin at Runtime (TypeScript) Source: https://github.com/logosdx/monorepo/blob/master/skills/logosdx/references/fetch.md Illustrates how to dynamically install a plugin onto an existing FetchEngine instance using the `api.use(plugin)` method. This method returns a cleanup function that can be called later to uninstall the plugin. ```typescript const cleanup = api.use(myPlugin); // Later: cleanup() to uninstall ``` -------------------------------- ### Implement Custom Storage Driver (Redis) Source: https://github.com/logosdx/monorepo/blob/master/skills/logosdx/references/storage.md You can implement a custom storage driver by adhering to the StorageDriver interface, which requires implementing five asynchronous methods: get, set, remove, keys, and clear. This example shows a RedisDriver implementation. ```typescript import type { StorageDriver } from '@logosdx/storage' // Implement 5 async methods class RedisDriver implements StorageDriver { #client: Redis constructor(redisUrl: string) { this.#client = new Redis(redisUrl) } async get(key: string) { const raw = await this.#client.get(key) return raw ?? null } async set(key: string, value: unknown) { await this.#client.set(key, String(value)) } async remove(key: string) { await this.#client.del(key) } async keys() { return this.#client.keys('*') } async clear() { const allKeys = await this.keys() if (allKeys.length > 0) { await this.#client.del(...allKeys) } } } const storage = new StorageAdapter({ driver: new RedisDriver('redis://localhost:6379'), prefix: 'sessions' }) ``` -------------------------------- ### Initialize StateMachine Instance Source: https://github.com/logosdx/monorepo/blob/master/skills/logosdx/references/state-machine.md Demonstrates how to instantiate a StateMachine with specific context and event types. It shows the basic structure of the machine configuration, including initial state, context, and transitions. Properties like `state` and `context` are accessible after initialization. ```typescript import { StateMachine } from '@logosdx/state-machine' const machine = new StateMachine({ initial: 'idle', context: { items: [], error: null }, transitions: { idle: { on: { FETCH: 'loading', ADD_ITEM: { target: 'idle', action: (ctx, data) => ({ ...ctx, items: [...ctx.items, data] }), }, }, }, loading: { on: { SUCCESS: { target: 'idle', action: (ctx, data) => ({ ...ctx, items: data.items }), }, FAILURE: { target: 'error', action: (ctx, data) => ({ ...ctx, error: data.message }), }, }, }, error: { on: { RETRY: 'loading', RESET: { target: 'idle', action: () => ({ items: [], error: null }), }, }, }, }, }) // Properties machine.state // 'idle' — current state name machine.context // { items: [], error: null } — cloned, safe to read ``` -------------------------------- ### Quick Start: Define and Use a State Machine in TypeScript Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/state-machine/index.md This TypeScript example illustrates the basic usage of @logosdx/state-machine. It defines a state machine for an order process with specific context, events, and transitions, including actions for updating context. ```typescript import { StateMachine } from '@logosdx/state-machine' interface OrderContext { items: string[] error: string | null } interface OrderEvents { ADD_ITEM: { name: string } SUBMIT: void SUCCESS: { orderId: string } FAILURE: { message: string } RETRY: void } const order = new StateMachine({ initial: 'draft', context: { items: [], error: null }, transitions: { draft: { on: { ADD_ITEM: { target: 'draft', action: (ctx, data) => ({ ...ctx, items: [...ctx.items, data.name], }), }, SUBMIT: 'submitting', }, }, submitting: { on: { SUCCESS: { target: 'confirmed', action: (ctx) => ({ ...ctx, error: null }), }, FAILURE: { target: 'error', action: (ctx, data) => ({ ...ctx, error: data.message }), }, }, }, error: { on: { RETRY: 'submitting' }, }, confirmed: { final: true }, }, }) order.send('ADD_ITEM', { name: 'Widget' }) order.send('SUBMIT') order.send('SUCCESS', { orderId: 'ORD-123' }) console.log(order.state) // 'confirmed' console.log(order.context) // { items: ['Widget'], error: null } ``` -------------------------------- ### Plugin Factories and Usage Source: https://github.com/logosdx/monorepo/blob/master/skills/logosdx/references/fetch.md Demonstrates how to create and configure various plugins (cache, dedupe, retry, rateLimit) and install them into a FetchEngine instance. Also shows how to access plugin methods directly. ```APIDOC ## Plugin Factories and Usage ### Description This section illustrates the creation and utilization of FetchEngine plugins. It covers initializing plugins like `cachePlugin`, `dedupePlugin`, `retryPlugin`, and `rateLimitPlugin` with their respective configurations and then integrating them into a `FetchEngine` instance. It also shows how to interact with plugin-specific methods after installation. ### Method N/A (Code Examples) ### Endpoint N/A (Code Examples) ### Parameters N/A (Code Examples) ### Request Example ```typescript import { cachePlugin, dedupePlugin, retryPlugin, rateLimitPlugin } from '@logosdx/fetch'; // Create plugins const cache = cachePlugin({ ttl: 300000, staleIn: 60000 }); const dedupe = dedupePlugin(true); const retry = retryPlugin({ maxAttempts: 3 }); const rateLimit = rateLimitPlugin({ maxCalls: 100, windowMs: 60000 }); // Use with FetchEngine const api = new FetchEngine({ baseUrl: 'https://api.example.com', plugins: [cache, dedupe, retry, rateLimit] }); // Access plugin methods directly cache.clearCache(); cache.stats(); // { cacheSize, inflightCount } dedupe.inflightCount(); ``` ### Response N/A (Code Examples) ### Response Example N/A (Code Examples) ``` -------------------------------- ### Accessing FetchResponse data and metadata in TypeScript Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/fetch/index.md This TypeScript example demonstrates how to interact with the `FetchResponse` object returned by FetchEngine methods. It shows destructuring just the data or accessing the full response object to get parsed data, status, headers, and configuration. ```typescript // Destructure just the data const { data: users } = await api.get('/users'); // Or access full response const response = await api.get('/users'); console.log(response.data); // Parsed data console.log(response.status); // HTTP status console.log(response.headers); // Response headers console.log(response.config); // Request configuration ``` -------------------------------- ### Include LogosDX Packages via CDN in Browser Source: https://github.com/logosdx/monorepo/blob/master/docs/getting-started.md Include LogosDX packages directly in your browser environment using CDN links. This method is suitable for quick integration or when a build process is not desired. It makes the LogosDX modules available globally. ```html ``` -------------------------------- ### Create and Use Scoped Interface in TypeScript Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/storage/api.md Demonstrates how to create a scoped interface using the scope() function and perform operations like setting, assigning, getting, and removing data for a specific key. This example highlights the asynchronous nature of these operations. ```typescript const userStorage = storage.scope('user') await userStorage.set({ id: '123', name: 'Charlie' }) await userStorage.assign({ email: 'charlie@example.com' }) const user = await userStorage.get() await userStorage.remove() ``` -------------------------------- ### Quick Start: Error Handling with attempt() in TypeScript Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/utils/index.md This TypeScript example showcases the 'attempt' utility from @logosdx/utils for handling asynchronous operations. It replaces traditional try-catch blocks with Go-style error tuples, returning either the result or an error object. ```typescript import { attempt } from '@logosdx/utils' // Replace try-catch with error tuples const [user, err] = await attempt(() => fetch('/api/users/123').then(r => r.json()) ) if (err) { console.error('Failed to fetch user:', err.message) return } console.log('User loaded:', user.name) ``` -------------------------------- ### Fetch Engine Plugin Lifecycle Example (TypeScript) Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/fetch/plugins.md Illustrates the plugin lifecycle management within the Fetch Engine. It shows how to initialize the engine with plugins and how to properly clean them up using `api.destroy()`. This ensures that all associated hooks are removed when the engine is no longer needed, preventing potential memory leaks. ```typescript const api = new FetchEngine({ baseUrl: 'https://api.example.com', plugins: [authPlugin(getToken), loggingPlugin()] }); // All plugin hooks are removed api.destroy(); ``` -------------------------------- ### VitePress Configuration Example Source: https://github.com/logosdx/monorepo/blob/master/docs/CLAUDE.md Illustrates a basic VitePress configuration file (`.vitepress/config.js`), setting up the site title, theme configuration, navigation, and sidebar. ```javascript // .vitepress/config.js export default { title: 'LogosDX', themeConfig: { logo: '/images/logo.svg', nav: [ { text: 'Home', link: '/' }, { text: 'API', link: 'https://typedoc.logosdx.dev' } ], sidebar: { '/': [ { text: 'Introduction', items: [...] }, { text: 'Packages', items: [...] } ] } } } ``` -------------------------------- ### Environment Detection Type Guards in TypeScript Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/utils/validation.md Provides utility functions to detect the runtime environment, such as browser, Node.js, or React Native. The `setupEnvironment` example illustrates conditional logic based on these environment checks, enabling environment-specific setup and initialization. ```typescript import { isBrowser, isNode, isReactNative } from '@logosdx/utils' const setupEnvironment = () => { if (isBrowser()) { // Browser-specific setup setupAnalytics() registerServiceWorker() } else if (isNode()) { // Node.js-specific setup setupLogging() connectToDatabase() } else if (isReactNative()) { // React Native-specific setup setupNativeModules() } } ``` -------------------------------- ### React UI Integration with State Machine (TypeScript/JSX) Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/state-machine/guide.md This example demonstrates a React component that consumes a state machine. It uses the `useStateMachine` hook to get the current state, context, and send function. A switch statement then renders different UI components based on the machine's current state. ```tsx function CheckoutPage() { const { state, selected: ctx, send } = useStateMachine(hub, 'checkout') switch (state) { case 'browsing': return send('ADD_ITEM', item)} onCheckout={() => send('CHECKOUT')} /> case 'checkingInventory': return case 'outOfStock': return send('BACK_TO_CART')} /> case 'loadingPaymentMethods': return case 'decidingPayment': return ctx.paymentMethods.length > 0 ? send('SELECT_PAYMENT', { method: m })} /> : send('ADD_PAYMENT_METHOD', { method: m })} /> case 'addingPaymentMethod': return send('ADD_PAYMENT_METHOD', { method: m })} onBack={() => send('BACK_TO_CART')} /> case 'readyToPay': return send('PAY')} onBack={() => send('BACK_TO_CART')} /> case 'processingPayment': return case 'paymentFailed': return send('RETRY')} onBack={() => send('BACK_TO_CART')} /> case 'success': return } } ``` -------------------------------- ### Token Bucket Configuration Example Source: https://github.com/logosdx/monorepo/blob/master/docs/packages/fetch/policies.md Configures the token bucket algorithm with a capacity of 10 calls and a window of 60000 milliseconds (1 minute), resulting in a refill rate of 1 token every 6 seconds. This setup limits requests to 10 per minute. ```typescript { maxCalls: 10, windowMs: 60000 // 60000ms / 10 = 6000ms per token } ``` -------------------------------- ### Basic HTTP Client with Retries and Error Handling - TypeScript Source: https://context7.com/logosdx/monorepo/llms.txt Demonstrates the basic usage of FetchEngine for making GET and POST requests. It includes configuration for automatic retries, timeouts, and comprehensive error handling using the `attempt` utility. The example shows how to access response data and headers, and how to cancel requests. ```typescript import { FetchEngine, isFetchError } from '@logosdx/fetch'; import { attempt } from '@logosdx/utils'; // Create instance const api = new FetchEngine({ baseUrl: 'https://api.example.com', defaultType: 'json', headers: { 'Authorization': 'Bearer token123' }, totalTimeout: 30000, // 30s max for entire request lifecycle attemptTimeout: 5000, // 5s per attempt (allows retries on timeout) retry: { maxAttempts: 3, baseDelay: 1000, useExponentialBackoff: true, retryableStatusCodes: [408, 429, 500, 502, 503, 504] } }); // GET request with error handling const [response, err] = await attempt(() => api.get('/users/123')); if (err) { if (isFetchError(err)) { console.error(`HTTP ${err.status}: ${err.message}`); console.log('Response data:', err.data); } return null; } console.log('User:', response.data); // { id: '123', name: 'Jane' } console.log('Rate limit:', response.headers['x-rate-limit-remaining']); // POST with payload const [created, createErr] = await attempt(() => api.post('/users', { name: 'John', email: 'john@example.com' }) ); // Request cancellation const request = api.get('/slow-endpoint'); setTimeout(() => request.abort('User cancelled'), 5000); ```