### Install Dependencies with pnpm (Bash) Source: https://www.zapstudio.dev/local-ts This command installs the necessary project dependencies using the pnpm package manager. Ensure pnpm is installed globally before running this command. ```bash pnpm install ``` -------------------------------- ### Install @zap-studio/fetch Package Source: https://www.zapstudio.dev/packages/fetch Instructions for installing the @zap-studio/fetch package using pnpm or npm. ```bash pnpm add @zap-studio/fetch # or npm install @zap-studio/fetch ``` -------------------------------- ### Tauri Bundle Configuration (JSON) Source: https://www.zapstudio.dev/llms-full A minimal example of the `bundle` configuration within `tauri.conf.json`. It enables bundling, sets the targets to 'all' platforms, and specifies a unique bundle identifier. This configuration determines the types of installers and bundles produced. ```json { "bundle": { "active": true, "targets": "all", "identifier": "com.yourcompany.yourapp" } } ``` -------------------------------- ### Real-World Examples: Multiple API Clients Source: https://www.zapstudio.dev/llms-full Demonstrates how to create and use multiple, independently configured API clients for different services. ```APIDOC ## Real-World Examples ### Multiple API Clients Create separate clients for different APIs in your application: ```typescript import { z } from "zod"; import { createFetch } from "@zap-studio/fetch"; // GitHub API client const github = createFetch({ baseURL: "https://api.github.com", headers: { Authorization: `token ${process.env.GITHUB_TOKEN}`, Accept: "application/vnd.github.v3+json", }, }); // Stripe API client const stripe = createFetch({ baseURL: "https://api.stripe.com/v1", headers: { Authorization: `Bearer ${process.env.STRIPE_SECRET_KEY}`, }, }); // Internal API client const internal = createFetch({ baseURL: process.env.API_URL, headers: { "X-Internal-Key": process.env.INTERNAL_API_KEY, }, }); // Schemas const RepoSchema = z.object({ id: z.number(), name: z.string(), full_name: z.string(), private: z.boolean(), }); const CustomerSchema = z.object({ id: z.string(), email: z.string(), name: z.string().nullable(), }); // Usage const repo = await github.api.get("/repos/owner/repo", RepoSchema); const customer = await stripe.api.get("/customers/cus_123", CustomerSchema); ``` ``` -------------------------------- ### API Request Examples Source: https://www.zapstudio.dev/llms-full Illustrates various use cases for the $fetch function, including POST requests with JSON bodies, GET requests with query parameters, and handling non-JSON responses. ```APIDOC ## API Request Examples ### POST with JSON body ```typescript const user = await $fetch("https://api.example.com/users", UserSchema, { method: "POST", body: { name: "John Doe", email: "john@example.com", }, }); ``` ### GET with query parameters ```typescript const url = new URL("https://api.example.com/users"); url.searchParams.set("page", "1"); url.searchParams.set("limit", "10"); const users = await $fetch(url.toString(), UsersSchema); ``` ### Handling non-JSON responses ```typescript const response = await $fetch("https://api.example.com/file.pdf"); if (response.ok) { const blob = await response.blob(); // Handle the binary data } ``` ### Custom headers ```typescript const user = await $fetch("https://api.example.com/users/1", UserSchema, { headers: { Authorization: "Bearer token", "Accept-Language": "en-US", "X-Request-ID": crypto.randomUUID(), }, }); ``` ``` -------------------------------- ### GET /products Source: https://www.zapstudio.dev/llms-full Fetches a list of products, supporting query parameters for search and pagination. ```APIDOC ## GET /products ### Description Fetches a list of products. Supports query parameters for searching and pagination. ### Method GET ### Endpoint https://api.example.com/products ### Parameters #### Query Parameters - **q** (string) - Required - The search query for products. - **page** (integer) - Optional - The page number to retrieve. Defaults to 1. - **limit** (integer) - Optional - The number of products per page. Defaults to 20. ### Response #### Success Response (200) - **products** (array) - An array of product objects. - **id** (string) - The unique identifier of the product. - **name** (string) - The name of the product. - **price** (number) - The price of the product. - **total** (number) - The total number of products found. - **page** (number) - The current page number. - **perPage** (number) - The number of products per page. #### Response Example ```json { "products": [ { "id": "prod_123", "name": "Laptop", "price": 1200 } ], "total": 50, "page": 2, "perPage": 20 } ``` ``` -------------------------------- ### Run Local.ts Development Server (Bash) Source: https://www.zapstudio.dev/local-ts This command starts the Local.ts development server using the Tauri CLI. It enables hot-reloading for a faster development cycle. ```bash pnpm tauri dev ``` -------------------------------- ### Remove System Tray Setup from Tauri lib.rs (Rust) Source: https://www.zapstudio.dev/llms-full Demonstrates how to remove the system tray setup call from `src-tauri/src/lib.rs` when disabling the system tray feature. ```diff - plugins::system_tray::setup(app, &pool)?; ``` -------------------------------- ### Install @zap-studio/permit Package Source: https://www.zapstudio.dev/packages/permit Provides instructions for installing the @zap-studio/permit package using pnpm or npm package managers. ```bash pnpm add @zap-studio/permit # or npm install @zap-studio/permit ``` -------------------------------- ### Install @zap-studio/webhooks Package Source: https://www.zapstudio.dev/llms-full Installs the @zap-studio/webhooks library using either pnpm or npm package managers. This is the first step to integrating webhook handling into your TypeScript application. ```bash pnpm add @zap-studio/webhooks # or npm install @zap-studio/webhooks ``` -------------------------------- ### Clone Local.ts Repository (Bash) Source: https://www.zapstudio.dev/local-ts This snippet shows how to clone the Local.ts repository using Git. It's the first step to starting a new project with the Local.ts starter kit. ```bash git clone https://github.com/zap-studio/local.ts.git my-app cd my-app ``` -------------------------------- ### Install Cargo Tarpaulin Source: https://www.zapstudio.dev/llms-full Installs the `cargo-tarpaulin` tool, which is used for generating code coverage reports for Rust projects. ```bash cargo install cargo-tarpaulin ``` -------------------------------- ### Configuring Tauri Logging Plugin Builder Source: https://www.zapstudio.dev/llms-full Provides an example of how to configure the Tauri logging plugin builder in Rust. This includes setting up log targets, timezone strategy, and max file size for log rotation. ```rust use tauri_plugin_log::{Target, TargetKind, TimezoneStrategy}; pub fn build() -> tauri_plugin_log::Builder { tauri_plugin_log::Builder::new() .targets([ Target::new(TargetKind::Stdout), Target::new(TargetKind::Webview), Target::new(TargetKind::LogDir { file_name: Some("logs".to_string()), }), ]) .timezone_strategy(TimezoneStrategy::UseLocal) .max_file_size(50_000) } ``` -------------------------------- ### TypeScript Example: Creating a Policy with 'and' Combinator Source: https://www.zapstudio.dev/llms-full Demonstrates creating a policy rule for editing a published post using the `and` condition combinator. It requires the user to be authenticated, the owner, and the post to be published. ```typescript import { createPolicy, when, and } from "@zap-studio/permit"; // User must be authenticated AND be the owner AND post must be published const canEditPublishedPost = and( (ctx) => ctx.user !== null, (ctx, _, post) => ctx.user?.id === post.authorId, (_, __, post) => post.status === "published" ); const policy = createPolicy({ resources, actions, rules: { post: { edit: when(canEditPublishedPost), }, }, }); ``` -------------------------------- ### TypeScript Example: Creating a Policy with 'or' Combinator Source: https://www.zapstudio.dev/llms-full Demonstrates creating a policy rule for reading a document using the `or` condition combinator. Access is granted if the user is the owner, an admin, or explicitly shared. ```typescript import { createPolicy, when, or } from "@zap-studio/permit"; // User can access if they're the owner OR an admin OR explicitly shared const canAccess = or( (ctx, _, doc) => ctx.user?.id === doc.ownerId, (ctx) => ctx.user?.role === "admin", (ctx, _, doc) => doc.sharedWith.includes(ctx.user?.id ?? "") ); const policy = createPolicy({ resources, actions, rules: { document: { read: when(canAccess), }, }, }); ``` -------------------------------- ### Installation of @zap-studio/validation Source: https://www.zapstudio.dev/packages/validation Installs the @zap-studio/validation package using pnpm or npm. This is the first step to integrate the validation utilities into your project. ```bash pnpm add @zap-studio/validation # or npm install @zap-studio/validation ``` -------------------------------- ### Blog API Client (TypeScript) Source: https://www.zapstudio.dev/llms-full This example shows how to create a reusable API client for a blog using the Zapstudio Fetch library and Zod for schema validation. It defines schemas for posts and comments, then creates an API instance with a base URL and authentication headers. The client exposes functions for fetching, creating, updating, and deleting posts, as well as adding comments. ```typescript import { z } from "zod"; import { createFetch } from "@zap-studio/fetch"; // Schemas const PostSchema = z.object({ id: z.string(), title: z.string(), content: z.string(), authorId: z.string(), published: z.boolean(), createdAt: z.string(), updatedAt: z.string(), }); const PostListSchema = z.object({ posts: z.array(PostSchema), total: z.number(), hasMore: z.boolean(), }); const CommentSchema = z.object({ id: z.string(), postId: z.string(), authorId: z.string(), content: z.string(), createdAt: z.string(), }); // Create API client const { api } = createFetch({ baseURL: "https://api.myblog.com/v1", headers: { Authorization: `Bearer ${getAuthToken()}`, }, }); // Blog API functions export const blogApi = { // Get all posts async getPosts(page = 1, limit = 10) { return api.get("/posts", PostListSchema, { searchParams: { page: String(page), limit: String(limit) }, }); }, // Get single post async getPost(id: string) { return api.get(`/posts/${id}`, PostSchema); }, // Create post async createPost(data: { title: string; content: string }) { return api.post("/posts", PostSchema, { body: data }); }, // Update post async updatePost(id: string, data: Partial<{ title: string; content: string; published: boolean }> ) { return api.patch(`/posts/${id}`, PostSchema, { body: data }); }, // Delete post async deletePost(id: string) { return api.delete(`/posts/${id}`, z.object({ success: z.boolean() })); }, // Add comment async addComment(postId: string, content: string) { return api.post(`/posts/${postId}/comments`, CommentSchema, { body: { content }, }); }, }; // Usage const { posts, hasMore } = await blogApi.getPosts(); const newPost = await blogApi.createPost({ title: "My First Post", content: "Hello, world!", }); await blogApi.updatePost(newPost.id, { published: true }); ``` -------------------------------- ### TypeScript: Exclusion Rules Example with permit Source: https://www.zapstudio.dev/llms-full Demonstrates how to use 'not', 'and', and 'when' from '@zap-studio/permit' to define exclusion rules for content interactions, such as preventing users from interacting with their own content or archived posts. ```typescript import { createPolicy, when, not, and } from "@zap-studio/permit"; // Cannot interact with your own content const isNotOwner = not((ctx, _, resource) => ctx.user?.id === resource.authorId); // Content is not archived const isNotArchived = not((_, __, resource) => resource.status === "archived"); const policy = createPolicy({ resources, actions, rules: { post: { // Can like any post except your own like: when(isNotOwner), // Can comment on posts that aren't archived comment: when(isNotArchived), // Can report posts that: you don't own AND aren't already reported by you report: when( and( isNotOwner, (ctx, _, post) => !post.reportedBy.includes(ctx.user?.id ?? "") ) ), }, }, }); ``` -------------------------------- ### Turborepo Remote Caching Setup Source: https://www.zapstudio.dev/llms-full Commands to log in and link your Turborepo client for remote caching. This enables sharing build caches across team members and CI runners. ```bash turbo login turbo link ``` -------------------------------- ### GET Request with Query Parameters using $fetch Source: https://www.zapstudio.dev/llms-full Illustrates making a GET request with query parameters using $fetch. It shows constructing a URL with search parameters and then passing the URL string and a UsersSchema to $fetch for data retrieval and validation. ```typescript const url = new URL("https://api.example.com/users"); url.searchParams.set("page", "1"); url.searchParams.set("limit", "10"); const users = await $fetch(url.toString(), UsersSchema); ``` -------------------------------- ### Runtime Validation Example with @zap-studio/fetch Source: https://www.zapstudio.dev/llms-full Contrasts the previous example by showing how @zap-studio/fetch with runtime validation prevents type mismatches. If the API response does not conform to the UserSchema, a ValidationError is thrown immediately, preventing potential bugs. ```typescript // With validation const user = await api.get("/api/users/1", UserSchema); // If the API returns { id: "123" }, you get a ValidationError // instead of silent type mismatch ``` -------------------------------- ### Creating Multiple API Clients with TypeScript Source: https://www.zapstudio.dev/llms-full Provides an example of creating distinct API clients using createFetch for different services (GitHub, Stripe, internal API). This allows for tailored configurations like base URLs and authentication headers for each client. ```typescript import { z } from "zod"; import { createFetch } from "@zap-studio/fetch"; // GitHub API client const github = createFetch({ baseURL: "https://api.github.com", headers: { Authorization: `token ${process.env.GITHUB_TOKEN}`, Accept: "application/vnd.github.v3+json", }, }); // Stripe API client const stripe = createFetch({ baseURL: "https://api.stripe.com/v1", headers: { Authorization: `Bearer ${process.env.STRIPE_SECRET_KEY}`, }, }); // Internal API client const internal = createFetch({ baseURL: process.env.API_URL, headers: { "X-Internal-Key": process.env.INTERNAL_API_KEY, }, }); // Schemas const RepoSchema = z.object({ id: z.number(), name: z.string(), full_name: z.string(), private: z.boolean(), }); const CustomerSchema = z.object({ id: z.string(), email: z.string(), name: z.string().nullable(), }); // Usage const repo = await github.api.get("/repos/owner/repo", RepoSchema); const customer = await stripe.api.get("/customers/cus_123", CustomerSchema); ``` -------------------------------- ### Blog Post Authorization Example (TypeScript) Source: https://www.zapstudio.dev/llms-full Demonstrates checking if a user can edit a blog post based on ownership. It sets up a context and post object, then uses a policy.can() function to determine editability. Returns a boolean indicating permission. ```typescript const context: AppContext = { user: { id: "user-123", role: "user", permissions: [], organizationId: "org-1" }, timestamp: new Date(), }; const post = { id: "post-456", authorId: "user-123", // Same as context.user.id (so user is the author) title: "My First Post", visibility: "public" as const, createdAt: new Date(), }; // The user is the author, so this returns true according to the policy const canEdit = policy.can(context, "write", "post", post); console.log(canEdit); // true // A different user trying to edit const otherContext: AppContext = { user: { id: "user-789", role: "user", permissions: [], organizationId: "org-1" }, timestamp: new Date(), }; const canOtherEdit = policy.can(otherContext, "write", "post", post); console.log(canOtherEdit); // false ``` -------------------------------- ### Handle Tauri Tray Icon Click Events (Rust) Source: https://www.zapstudio.dev/llms-full Defines the behavior when the system tray icon is clicked in Tauri. This example shows how to display and focus the main window on a left-click. ```rust .on_tray_icon_event(|tray, event| { if let TrayIconEvent::Click { button: MouseButton::Left, button_state: MouseButtonState::Up, .. } = event { let app = tray.app_handle(); if let Some(window) = app.get_webview_window("main") { let _ = window.show(); let _ = window.set_focus(); } } }) ``` -------------------------------- ### Using Valibot Schema with @zap-studio/fetch Source: https://www.zapstudio.dev/llms-full Illustrates the integration of Valibot, a schema validation library, with the @zap-studio/fetch package. This example defines a Valibot schema for user data and uses it for fetching and validating user information. ```typescript import * as v from "valibot"; import { api } from "@zap-studio/fetch"; const UserSchema = v.object({ id: v.number(), name: v.string(), email: v.pipe(v.string(), v.email()), createdAt: v.pipe(v.string(), v.isoTimestamp()), }); const user = await api.get("/users/1", UserSchema); ``` -------------------------------- ### Runtime Validation with Standard Schema Source: https://www.zapstudio.dev/llms-full Explains the importance of runtime validation using Standard Schema to prevent type mismatches and ensure data integrity, showcasing examples with Zod, Valibot, and ArkType. ```APIDOC # Validation `@zap-studio/fetch` utilizes [Standard Schema](https://standardschema.dev/) for runtime validation, ensuring compatibility with various schema libraries. ## Why Validation Matters APIs can change, leading to data that doesn't match TypeScript types. Runtime validation catches these discrepancies, preventing subtle bugs. ### Example without validation: ```typescript // Without validation const user = await fetch("/api/users/1").then((r) => r.json()) as User; // If API returns { id: "123" }, user.id is a string, causing unexpected behavior. user.id + 1; // Results in "1231" ``` ### Example with validation: ```typescript // With validation const user = await api.get("/api/users/1", UserSchema); // If API returns { id: "123" }, a ValidationError is thrown. ``` ## Supported Schema Libraries Any library implementing Standard Schema v1 is supported, including: * [Zod](https://zod.dev/) * [Valibot](https://valibot.dev/) * [ArkType](https://arktype.io/) * [TypeBox](https://github.com/sinclairzx81/typebox) ## Using Different Schema Libraries ### Zod Example ```typescript import { z } from "zod"; import { api } from "@zap-studio/fetch"; const UserSchema = z.object({ id: z.number(), name: z.string(), email: z.string().email(), createdAt: z.string().datetime(), }); const user = await api.get("/users/1", UserSchema); ``` ### Valibot Example ```typescript import * as v from "valibot"; import { api } from "@zap-studio/fetch"; const UserSchema = v.object({ id: v.number(), name: v.string(), email: v.pipe(v.string(), v.email()), createdAt: v.pipe(v.string(), v.isoTimestamp()), }); const user = await api.get("/users/1", UserSchema); ``` ### ArkType Example ```typescript import { type } from "arktype"; import { api } from "@zap-studio/fetch"; const UserSchema = type({ id: "number", name: "string", email: "email", createdAt: "string", }); const user = await api.get("/users/1", UserSchema); ``` ## The `standardValidate` Helper Use `standardValidate` for standalone validation: ```typescript import { standardValidate } from "@zap-studio/fetch/validator"; import { z } from "zod"; const UserSchema = z.object({ id: z.number(), name: z.string(), }); // Throwing validation (default) const user = await standardValidate(UserSchema, data, true); // Returns validated data or throws ValidationError // Non-throwing validation const result = await standardValidate(UserSchema, data, false); // Returns { value: T } or { issues: Issue[] } if (result.issues) { console.error("Validation failed:", result.issues); } else { console.log("Valid user:", result.value); } ``` ``` -------------------------------- ### Unsafe Fetch vs. @zap-studio/fetch TypeScript Example Source: https://www.zapstudio.dev/packages/fetch Demonstrates the difference between unsafe type assertions in standard fetch requests and the type-safe, validated approach provided by @zap-studio/fetch. ```typescript const response = await fetch("/api/users/1"); const data = await response.json(); const user = data as User; // 😱 Unsafe type assertion // If the API returns { name: "John" } instead of { id: 1, name: "John" }, // your app breaks at runtime with no warning ``` ```typescript import { api } from "@zap-studio/fetch"; const user = await api.get("/api/users/1", UserSchema); // ✨ Typed, validated, and safe! // If the API response doesn't match UserSchema, you get a clear error ``` -------------------------------- ### Basic RBAC Policy Creation Source: https://www.zapstudio.dev/llms-full This TypeScript example demonstrates creating a comprehensive RBAC policy using `createPolicy` from `@zap-studio/permit`. It defines resources, actions, and rules based on roles and context, including conditions for reading, writing, deleting, and publishing posts, as well as managing user profiles. It uses helper functions like `when`, `or`, and `hasRole` for defining access logic. ```typescript import { z } from "zod"; import { createPolicy, when, hasRole, or } from "@zap-studio/permit"; import type { Resources, Actions } from "@zap-studio/permit/types"; const resources = { post: z.object({ id: z.string(), authorId: z.string(), status: z.enum(["draft", "published", "archived"]), }), user: z.object({ id: z.string(), email: z.string(), }), } satisfies Resources; const actions = { post: ["read", "write", "delete", "publish"], user: ["read", "update", "delete", "ban"], } as const satisfies Actions; type Role = "guest" | "user" | "moderator" | "admin"; type AppContext = { user: { id: string } | null; role: Role; }; const policy = createPolicy({ resources, actions, rules: { post: { // Guests can read published posts read: when((ctx, _, post) => post.status === "published" || ctx.role === "user" ), // Users can write their own posts write: when((ctx, _, post) => ctx.role === "user" && ctx.user?.id === post.authorId ), // Moderators and admins can delete any post delete: when( or( hasRole("moderator"), hasRole("admin") ) ), // Only admins can publish publish: when(hasRole("admin")), }, user: { // Users can read their own profile, admins can read any read: when( or( (ctx, _, user) => ctx.user?.id === user.id, hasRole("admin") ) ), // Users can update their own profile update: when((ctx, _, user) => ctx.user?.id === user.id), // Only admins can delete users delete: when(hasRole("admin")), // Moderators and admins can ban users ban: when( or( hasRole("moderator"), hasRole("admin") ) ), }, }, }); ``` -------------------------------- ### Combine Permit Policies with AND and OR Logic (TypeScript) Source: https://www.zapstudio.dev/llms-full This example demonstrates how to combine multiple policies using both `mergePolicies` (AND logic, requiring all policies to permit) and `mergePoliciesAny` (OR logic, requiring at least one policy to permit). It illustrates creating separate access and security layers, then merging them into a final policy. ```typescript import { mergePolicies, mergePoliciesAny } from "@zap-studio/permit"; // Access layer: multiple paths to access const accessPolicy = mergePoliciesAny(ownerPolicy, sharedPolicy, publicPolicy); // Security layer: must pass all security checks const securityPolicy = mergePolicies(auditPolicy, compliancePolicy, ratePolicy); // Final policy: must have access AND pass security const finalPolicy = mergePolicies(accessPolicy, securityPolicy); ``` -------------------------------- ### Turborepo CI Cache Validation Source: https://www.zapstudio.dev/llms-full Example YAML snippet for a CI pipeline step that validates the monorepo using Turborepo. It installs dependencies and runs validation tasks. ```yaml # Your CI pipeline benefits from Turborepo's cache - name: Install dependencies run: pnpm install --frozen-lockfile - name: Validate run: pnpm turbo run validate ``` -------------------------------- ### Create Tauri Menu Items and Build Menu (Rust) Source: https://www.zapstudio.dev/llms-full Demonstrates how to create menu items (show, hide, quit) and build a menu for the Tauri system tray using Rust. Requires the 'tauri::menu' module. ```rust use tauri::menu::{Menu, MenuItem}; pub fn setup(app: &App, pool: &DbPool) -> Result<(), Box> { // Create menu items let show_i = MenuItem::with_id(app, "show", "Show", true, None::<&str>)?; let hide_i = MenuItem::with_id(app, "hide", "Hide", true, None::<&str>)?; let quit_i = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?; // Build the menu let menu = Menu::with_items(app, &[&show_i, &hide_i, &quit_i])?; // ... rest of setup } ``` -------------------------------- ### Custom Headers in $fetch Request Source: https://www.zapstudio.dev/llms-full Demonstrates how to include custom headers in an HTTP request made with $fetch. This example shows setting an Authorization token, Accept-Language, and a custom X-Request-ID header for a GET request. ```typescript const user = await $fetch("https://api.example.com/users/1", UserSchema, { headers: { Authorization: "Bearer token", "Accept-Language": "en-US", "X-Request-ID": crypto.randomUUID(), }, }); ``` -------------------------------- ### Run and Configure Vitest for Testing Source: https://www.zapstudio.dev/llms-full Illustrates how to run tests using Vitest, a Vite-native test runner. Includes commands for running tests once, in watch mode, generating coverage reports, and opening the UI runner. Also shows basic Vitest configuration for coverage reporters. ```bash # Run tests once turbo test # Watch mode for development turbo test:watch # Generate coverage report turbo test:coverage # Open the UI test runner turbo test:ui ``` ```typescript export default defineConfig({ // ... other config test: { coverage: { provider: "v8", reporter: ["text", "html"] }, }, }); ``` ```typescript import { describe, it, expect } from "vitest"; describe("myFunction", () => { it("should return the correct value", () => { expect(myFunction(2)).toBe(4); }); }); ``` -------------------------------- ### Initialize Theme Store and Listen for Changes (TypeScript) Source: https://www.zapstudio.dev/llms-full Initializes the theme store by applying the theme from settings and then sets up a listener for system theme changes. When the OS preference for color scheme changes and the application theme is set to 'system', it reapplies the theme to the DOM and updates the store's resolved theme. This utilizes Zustand's `create` and `useSettings` hook. ```typescript export const useTheme = create((set) => ({ // ... initialize: () => { const settings = useSettings.getState().settings; if (settings) { const resolved = applyThemeToDOM(settings.theme); set({ theme: settings.theme, resolvedTheme: resolved }); } const handleChange = () => { const currentTheme = useTheme.getState().theme; if (currentTheme === "system") { const resolved = applyThemeToDOM("system"); set({ resolvedTheme: resolved }); } }; // Listen for system theme changes const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); mediaQuery.addEventListener("change", handleChange); }, })); ``` -------------------------------- ### Make Type-Safe API GET Request Source: https://www.zapstudio.dev/packages/fetch How to perform a type-safe GET request using the api object from @zap-studio/fetch, providing the URL and the defined schema for validation. ```typescript import { api } from "@zap-studio/fetch"; // Fetch a single user - fully typed and validated const user = await api.get("https://api.example.com/users/1", UserSchema); console.log(user.name); // TypeScript knows this is a string console.log(user.createdAt); // TypeScript knows this is a Date ``` -------------------------------- ### POST /users Source: https://www.zapstudio.dev/llms-full Creates a new user resource on the server. ```APIDOC ## POST /users ### Description Creates a new user resource on the server. The request body is automatically JSON-stringified. ### Method POST ### Endpoint https://api.example.com/users ### Parameters #### Request Body - **name** (string) - Required - The name of the user. - **email** (string) - Required - The email address of the user. - **password** (string) - Required - The password for the user. ### Response #### Success Response (200) - **id** (string) - The unique identifier of the newly created user. - **name** (string) - The name of the user. - **email** (string) - The email address of the user. - **createdAt** (string) - The timestamp when the user was created. #### Response Example ```json { "id": "user_abc", "name": "John Doe", "email": "john.doe@example.com", "createdAt": "2023-10-27T10:00:00Z" } ``` ``` -------------------------------- ### Factory Options Source: https://www.zapstudio.dev/llms-full Configuration options available when creating a fetch client instance. ```APIDOC ## Factory Options | Option | Type | Default | Description | |---|---|---|---| | `baseURL` | `string` | `""` | Base URL prepended to relative paths only | | `headers` | `HeadersInit` | - | Default headers included in all requests | | `searchParams` | `URLSearchParams | Record` | - | Default query params included in all requests | | `throwOnFetchError` | `boolean` | `true` | Throw `FetchError` on non-2xx responses | | `throwOnValidationError` | `boolean` | `true` | Throw `ValidationError` on schema validation failures | ``` -------------------------------- ### Tailwind CSS Dark Mode Styling (CSS) Source: https://www.zapstudio.dev/llms-full Demonstrates styling for dark mode using Tailwind CSS. The first example shows direct CSS rules for a '.card' element, where a white background is set for light mode and a dark background for elements with the '.dark' class. The second example uses Tailwind's utility classes `bg-white` and `dark:bg-gray-900` for the same effect. ```css .card { background: white; } .dark .card { background: #1a1a1a; } ``` ```html
Content
``` -------------------------------- ### Importing Lucide React Icons Source: https://www.zapstudio.dev/llms-full Demonstrates how to import various icons from the Lucide React library for use in your application. This allows for flexible icon selection and consistent styling. ```typescript import { FileText, Calendar, Mail, Bell } from "lucide-react"; ``` -------------------------------- ### Format and Lint Code with Ultracite Source: https://www.zapstudio.dev/llms-full These bash commands demonstrate how to use Ultracite, a zero-configuration linter and formatter, to fix code issues and check for quality problems. It leverages oxlint and oxfmt for fast performance. ```bash # Format and fix all issues pnpm dlx ultracite fix # Check for issues without fixing pnpm dlx ultracite check # Diagnose setup issues pnpm dlx ultracite doctor ``` -------------------------------- ### TypeScript Creating and Throwing PolicyError Source: https://www.zapstudio.dev/llms-full Provides examples of how to instantiate and throw PolicyError for various authorization-related scenarios, such as unauthorized access, invalid configurations, or missing context. ```typescript import { PolicyError } from "@zap-studio/permit/errors"; // Throw when an authorization check fails throw new PolicyError("User is not authorized to delete this resource"); // Throw for invalid policy configuration throw new PolicyError("Unknown resource type: 'invalid'"); // Throw for missing context throw new PolicyError("User context is required for this action"); ``` -------------------------------- ### Define API Response Schema with Zod Source: https://www.zapstudio.dev/packages/fetch Example of defining a TypeScript schema for API responses using the Zod library, which can then be used with @zap-studio/fetch for validation. ```typescript import { z } from "zod"; // Define the user schema const UserSchema = z.object({ id: z.number(), name: z.string(), email: z.string().email(), role: z.enum(["admin", "user", "guest"]), createdAt: z.string().transform((s) => new Date(s)), }); type User = z.infer; ``` -------------------------------- ### Logging from Rust with the log Crate Source: https://www.zapstudio.dev/llms-full Demonstrates how to use the standard Rust `log` macros for emitting log messages. These messages can be filtered by level and sent to configured targets. ```rust log::info!("Application started"); log::debug!("Processing user: {}", user_id); log::warn!("Deprecated API called"); log::error!("Failed to save settings: {}", error); ``` -------------------------------- ### Handle Tauri Menu Events (Rust) Source: https://www.zapstudio.dev/llms-full Shows how to handle menu events triggered by clicking on system tray menu items in Tauri. It includes actions for 'show', 'hide', 'quit', and a placeholder for custom actions. ```rust .on_menu_event(|app, event| match event.id.as_ref() { "show" => { if let Some(window) = app.get_webview_window("main") { let _ = window.show(); let _ = window.set_focus(); } } "hide" => { if let Some(window) = app.get_webview_window("main") { let _ = window.hide(); } } "quit" => { app.exit(0); } "my_custom_action" => { // Handle your custom action } _ => {} }) ``` -------------------------------- ### Read Theme State Using useTheme Hook (TypeScript) Source: https://www.zapstudio.dev/llms-full Example of using the `useTheme` hook from '@/stores/theme' to access the user's theme preference and the currently resolved theme in a React component. ```typescript import { useTheme } from "@/stores/theme"; function ThemeIndicator() { // The user's preference: "light" | "dark" | "system" const theme = useTheme((state) => state.theme); // The actual applied theme: "light" | "dark" const resolvedTheme = useTheme((state) => state.resolvedTheme); return (

Preference: {theme}

Applied: {resolvedTheme}

); } ``` -------------------------------- ### Run Tests with Turborepo Source: https://www.zapstudio.dev/llms-full Executes test suites for both frontend and backend codebases using the Turborepo CLI. This command is crucial for verifying code functionality. ```bash turbo test ``` -------------------------------- ### Logging to Separate Files by Level Source: https://www.zapstudio.dev/llms-full Explains how to configure the logging system to write logs to different files based on their log level. This allows for better organization and analysis of log data. ```rust .targets([ Target::new(TargetKind::Stdout), Target::new(TargetKind::LogDir { file_name: Some("errors".to_string()) }) .filter(|metadata| metadata.level() == log::Level::Error), Target::new(TargetKind::LogDir { file_name: Some("all".to_string()) }), ]) ``` -------------------------------- ### Handle Fetch and Validation Errors Source: https://www.zapstudio.dev/packages/fetch Example of using a try-catch block to gracefully handle potential FetchError (HTTP errors) and ValidationError (schema mismatches) when making API requests with @zap-studio/fetch. ```typescript import { FetchError, ValidationError } from "@zap-studio/fetch/errors"; try { const user = await api.get("https://api.example.com/users/1", UserSchema); console.log(`Hello, ${user.name}!`); } catch (error) { if (error instanceof FetchError) { // HTTP error (404, 500, etc.) console.error(`API error: ${error.status}`); } else if (error instanceof ValidationError) { // Response didn't match schema console.error("Invalid API response:", error.issues); } } ``` -------------------------------- ### Add New Setting: Database Migration (Bash) Source: https://www.zapstudio.dev/llms-full Provides the bash commands to generate and run a new database migration for adding a setting. This involves creating migration files and executing them using `diesel`. ```bash cd src-tauri diesel migration generate add_my_setting -- Inside migrations/_add_my_setting/up.sql -- ALTER TABLE settings ADD COLUMN my_setting INTEGER NOT NULL DEFAULT 0; -- Inside migrations/_add_my_setting/down.sql -- ALTER TABLE settings DROP COLUMN my_setting; diesel migration run ``` -------------------------------- ### Standalone Data Validation with standardValidate (Throwing) Source: https://www.zapstudio.dev/llms-full Demonstrates the usage of the `standardValidate` helper function for standalone data validation. This example shows the default behavior where the function throws a `ValidationError` if the provided data does not match the schema. ```typescript import { standardValidate } from "@zap-studio/fetch/validator"; import { z } from "zod"; const UserSchema = z.object({ id: z.number(), name: z.string(), }); // Throwing validation (default) const user = await standardValidate(UserSchema, data, true); // Returns validated data or throws ValidationError ``` -------------------------------- ### Using ArkType Schema with @zap-studio/fetch Source: https://www.zapstudio.dev/llms-full Shows how to use the ArkType schema validation library with the @zap-studio/fetch package. The example defines an ArkType schema that mirrors TypeScript syntax for validating user data fetched from an API. ```typescript import { type } from "arktype"; import { api } from "@zap-studio/fetch"; const UserSchema = type({ id: "number", name: "string", email: "email", createdAt: "string", }); const user = await api.get("/users/1", UserSchema); ``` -------------------------------- ### Initialize Connection Pool (Rust) Source: https://www.zapstudio.dev/llms-full Shows the initialization of a database connection pool using the `r2d2` crate in Rust. The pool is configured with a maximum size of 10 connections, suitable for most desktop applications, and is typically set up during application startup. ```rust let pool = r2d2::Pool::builder() .max_size(10) .build(manager)?; ``` -------------------------------- ### Create Reusable Fetch Instances with createFetch in TypeScript Source: https://www.zapstudio.dev/llms-full Shows how to use the createFetch utility to instantiate pre-configured fetch clients. This pattern is useful for setting base URLs and default headers, promoting code reuse and consistency in API requests. ```typescript import { z } from "zod"; import { createFetch } from "@zap-studio/fetch"; const { $fetch, api } = createFetch({ baseURL: "https://api.example.com", headers: { Authorization: "Bearer your-token", "X-API-Key": "your-api-key", }, }); const UserSchema = z.object({ id: z.number(), name: z.string(), }); // Use relative paths - baseURL is prepended automatically const user = await api.get("/users/1", UserSchema); // POST with auto-stringified body const newUser = await api.post("/users", UserSchema, { body: { name: "John Doe" }, }); ``` -------------------------------- ### Build Tauri Application for Production (Bash) Source: https://www.zapstudio.dev/llms-full Command to build production-ready bundles for a Tauri application. This command is part of a build system (like `turbo`) and produces platform-specific artifacts in the `src-tauri/target/release/bundle/` directory. ```bash turbo tauri -- build ``` -------------------------------- ### Composing Zod Schemas for Complex Structures (TypeScript) Source: https://www.zapstudio.dev/llms-full Illustrates how to build complex Zod schemas by composing simpler ones. This example shows creating nested schemas for `AddressSchema`, `UserSchema`, and `OrderSchema`, utilizing `optional()` for fields that may not be present. ```typescript const AddressSchema = z.object({ street: z.string(), city: z.string(), country: z.string(), }); const UserSchema = z.object({ id: z.string(), name: z.string(), address: AddressSchema.optional(), }); const OrderSchema = z.object({ id: z.string(), user: UserSchema, shippingAddress: AddressSchema, billingAddress: AddressSchema.optional(), }); ``` -------------------------------- ### Centralized Authorization Logic with Zap Studio Permit Source: https://www.zapstudio.dev/llms-full Demonstrates how to centralize authorization logic using Zap Studio Permit's declarative policy. This approach makes authorization rules clear, reusable, and type-safe, improving maintainability. ```typescript import { createPolicy, when, or, hasRole } from "@zap-studio/permit"; // ✨ Centralized, declarative authorization const policy = createPolicy({ resources, actions, rules: { post: { delete: when( or( hasRole("admin"), (ctx, _, post) => ctx.user.id === post.authorId ) ), }, }, }); // Clean route handler app.delete("/posts/:id", async (req, res) => { const post = await getPost(req.params.id); if (!policy.can(req.context, "delete", "post", post)) { return res.status(403).json({ error: "Forbidden" }); } await deletePost(post.id); res.json({ success: true }); }); ``` -------------------------------- ### Zap Studio Fetch API Methods Source: https://www.zapstudio.dev/llms-full The `api` object from `@zap-studio/fetch` provides type-safe methods for common HTTP verbs (GET, POST, PUT, PATCH, DELETE). All methods require a schema for validation and return fully typed, validated data. ```APIDOC ## API Methods - @zap-studio/fetch ### Overview The `api` object provides convenient methods for common HTTP verbs. All methods require a schema for validation and return fully typed, validated data. | Method | Use Case | | ------ | -------- | | `api.get()` | Retrieve data | | `api.post()` | Create new resources | | `api.put()` | Replace entire resources | | `api.patch()` | Partially update resources | | `api.delete()` | Remove resources | All methods automatically: * Set `Content-Type: application/json` for request bodies * JSON-stringify objects passed as `body` * Validate responses against your schema * Provide full TypeScript type inference ### `api.get()` Retrieves data from the server. Use for fetching resources. ```typescript api.get(url, schema, options?) ``` #### Example: Fetching a User Profile ```typescript import { z } from "zod"; import { api } from "@zap-studio/fetch"; const UserProfileSchema = z.object({ id: z.string(), name: z.string(), email: z.string().email(), avatar: z.string().url().nullable(), bio: z.string().optional(), joinedAt: z.string(), }); async function getUserProfile(userId: string) { const profile = await api.get( `https://api.example.com/users/${userId}`, UserProfileSchema ); return profile; // Type: { id: string; name: string; email: string; avatar: string | null; bio?: string; joinedAt: string } } ``` ### `api.post()` Creates new resources on the server. ```typescript api.post(url, schema, data, options?) ``` ### `api.put()` Replaces entire resources on the server. ```typescript api.put(url, schema, data, options?) ``` ### `api.patch()` Partially updates resources on the server. ```typescript api.patch(url, schema, data, options?) ``` ### `api.delete()` Removes resources from the server. ```typescript api.delete(url, schema, options?) ``` ``` -------------------------------- ### Configure Default Window Size (JSON) Source: https://www.zapstudio.dev/llms-full Sets the default dimensions for the application window on its first launch. This configuration is defined in `src-tauri/tauri.conf.json` and is used before any user-specific state is saved. ```json { "windows": [{ "title": "Local.ts", "label": "main", "visible": false, "width": 1280, "height": 720, "center": true }] } ```