|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +Vorm is an intuitive form engine for Vue 3 — dynamic, schema-driven, and fully validated. This is a **pnpm workspace** monorepo containing: |
| 8 | + |
| 9 | +- `vorm-vue` (packages/vorm): Core form engine library for Vue 3 |
| 10 | +- `vorm-nuxt` (packages/vorm-nuxt): Nuxt module integration |
| 11 | +- `playground` (packages/playground): Demo application for testing |
| 12 | +- `docs` (packages/docs): VitePress documentation site |
| 13 | + |
| 14 | +## Development Commands |
| 15 | + |
| 16 | +### Installation & Setup |
| 17 | +```bash |
| 18 | +pnpm install |
| 19 | +``` |
| 20 | + |
| 21 | +### Development |
| 22 | +```bash |
| 23 | +# Run playground (default dev command) |
| 24 | +pnpm dev |
| 25 | + |
| 26 | +# Run documentation site locally |
| 27 | +pnpm docs:dev |
| 28 | +``` |
| 29 | + |
| 30 | +### Building |
| 31 | +```bash |
| 32 | +# Build vorm-vue library |
| 33 | +pnpm --filter vorm-vue build |
| 34 | + |
| 35 | +# Build all packages |
| 36 | +pnpm -r build |
| 37 | +``` |
| 38 | + |
| 39 | +### Testing |
| 40 | +```bash |
| 41 | +# Run tests for vorm-vue |
| 42 | +pnpm --filter vorm-vue test |
| 43 | + |
| 44 | +# Run tests with coverage |
| 45 | +pnpm --filter vorm-vue test:cov |
| 46 | + |
| 47 | +# Run tests with UI |
| 48 | +pnpm --filter vorm-vue test:ui |
| 49 | + |
| 50 | +# Run tests for vorm-nuxt |
| 51 | +pnpm --filter vorm-nuxt test |
| 52 | + |
| 53 | +# Run type checking for vorm-nuxt |
| 54 | +pnpm --filter vorm-nuxt test:types |
| 55 | +``` |
| 56 | + |
| 57 | +### Versioning & Release (Changesets) |
| 58 | +```bash |
| 59 | +# Create a new changeset (when making changes) |
| 60 | +pnpm changeset |
| 61 | + |
| 62 | +# Apply version updates locally |
| 63 | +pnpm version:apply |
| 64 | + |
| 65 | +# Build and publish locally (for testing) |
| 66 | +pnpm release:local |
| 67 | +``` |
| 68 | + |
| 69 | +**Important**: The packages use **Changesets** for version management. `vorm-nuxt` is in the ignore list (`.changeset/config.json`), meaning it doesn't auto-bump via changesets. |
| 70 | + |
| 71 | +### Linting (vorm-nuxt) |
| 72 | +```bash |
| 73 | +pnpm --filter vorm-nuxt lint |
| 74 | +``` |
| 75 | + |
| 76 | +## Architecture |
| 77 | + |
| 78 | +### Core Library (vorm-vue) |
| 79 | + |
| 80 | +The library is structured around three key concepts: |
| 81 | + |
| 82 | +1. **Schema System** (`types/schemaTypes.ts`) |
| 83 | + - `VormSchema`: Array of field definitions that describe form structure |
| 84 | + - `VormFieldSchema`: Individual field configuration with type, validation, conditional visibility |
| 85 | + - Field types are strictly typed via `FieldValueTypeMap` (text, number, email, checkbox, select, etc.) |
| 86 | + - Supports nested fields, repeaters, and conditional fields via `showIf` |
| 87 | + |
| 88 | +2. **Validation Engine** (`core/validatorEngine.ts` + `core/validatorCompiler.ts`) |
| 89 | + - **Two-phase validation**: Compilation phase (schema → compiled validators) + execution phase (async validation) |
| 90 | + - Built-in validators: `required`, `minLength`, `maxLength`, `min`, `max`, `pattern`, `between`, `step`, `matchField` |
| 91 | + - Custom validators supported via `ValidationRule` interface |
| 92 | + - Validation modes: `onInput`, `onBlur`, `onSubmit` |
| 93 | + - Compiled validators are cached for performance |
| 94 | + |
| 95 | +3. **Context System** (`composables/useVorm.ts` + `core/vormContext.ts`) |
| 96 | + - `useVorm()`: Creates form context with reactive state (formData, errors, touched, dirty) |
| 97 | + - `VormContext`: Centralized form state injected via Vue's provide/inject |
| 98 | + - `VormContextKey`: InjectionKey for type-safe dependency injection |
| 99 | + - Context tracks: validation state, field options, dirty/touched state, initial values |
| 100 | + |
| 101 | +### Components |
| 102 | + |
| 103 | +- **VormProvider**: Root component that establishes form context via `useVorm()` |
| 104 | +- **AutoVorm**: Auto-generates form UI from schema (experimental/under development) |
| 105 | +- **VormSection**: Groups related fields with optional conditional rendering |
| 106 | +- **VormRepeater**: Dynamic array fields (add/remove field groups) |
| 107 | + |
| 108 | +All components use Vue 3 Composition API and TypeScript. |
| 109 | + |
| 110 | +### Nuxt Module (vorm-nuxt) |
| 111 | + |
| 112 | +- Auto-imports `useVorm`, `useVormContext`, and types when `autoImports: true` |
| 113 | +- Auto-registers all Vorm components when `components: true` |
| 114 | +- Transpiles `vorm-vue` for SSR compatibility |
| 115 | +- Plugin setup in `runtime/plugin` |
| 116 | + |
| 117 | +### Build Configuration |
| 118 | + |
| 119 | +- **vorm-vue**: Vite library mode with dual exports: |
| 120 | + - `./index.mjs`: Main library + built-in validators |
| 121 | + - `./components.mjs`: Components only |
| 122 | + - CSS bundled in `vorm-vue.css` |
| 123 | +- **Test setup**: Vitest with jsdom environment, coverage via v8 |
| 124 | +- **Type generation**: `vite-plugin-dts` with rollup types enabled |
| 125 | + |
| 126 | +## Release Workflow |
| 127 | + |
| 128 | +### GitHub Actions Workflows |
| 129 | + |
| 130 | +1. **version-pr.yml**: Triggered on changeset additions |
| 131 | + - Creates/updates version PR using `changesets/action` |
| 132 | + - Updates PR title with package versions |
| 133 | + |
| 134 | +2. **release-vorm-vue.yml**: Triggered when version PR is merged |
| 135 | + - Checks for absence of changesets (indicating release merge) |
| 136 | + - Builds vorm-vue |
| 137 | + - Publishes to npm with provenance |
| 138 | + - Creates GitHub release |
| 139 | + |
| 140 | +3. **release-vorm-nuxt.yml**: Separate release workflow for Nuxt module |
| 141 | + |
| 142 | +### GitLab CI (.gitlab-ci.yml) |
| 143 | + |
| 144 | +Used for documentation deployment: |
| 145 | +- Manual version tagging (patch/minor/major) |
| 146 | +- Docker image build for docs |
| 147 | +- Deploy to server (pulls `:latest` image) |
| 148 | + |
| 149 | +## Key Patterns |
| 150 | + |
| 151 | +### Path Helpers (`utils/pathHelpers.ts`) |
| 152 | +The library uses dot-notation paths (e.g., `user.address.city`) to access nested form data: |
| 153 | +- `getValueByPath(obj, path)`: Retrieve nested values |
| 154 | +- `setValueByPath(obj, path, value)`: Set nested values |
| 155 | + |
| 156 | +### Conditional Visibility |
| 157 | +Fields support `showIf` conditions: |
| 158 | +- Object comparison: `{ fieldName: expectedValue }` |
| 159 | +- Function: `(formData, path) => boolean` |
| 160 | +- Dependent field: `{ dependsOn: 'field', condition: (value, formData) => boolean }` |
| 161 | + |
| 162 | +### Validation Flow |
| 163 | +1. Schema compilation: `compileField()` creates `CompiledValidator` |
| 164 | +2. Field validation: `validateFieldByName()` uses compiled validators |
| 165 | +3. Async execution: `validateFieldAsync()` runs validation rules sequentially |
| 166 | +4. Error propagation: `affects` field in rules can propagate errors to other fields |
| 167 | + |
| 168 | +## Workspace Structure |
| 169 | + |
| 170 | +``` |
| 171 | +vorm/ |
| 172 | +├── packages/ |
| 173 | +│ ├── vorm/ # vorm-vue (main library) |
| 174 | +│ │ ├── src/ |
| 175 | +│ │ │ ├── core/ # Validation engine & context |
| 176 | +│ │ │ ├── composables/ # useVorm, useVormContext |
| 177 | +│ │ │ ├── components/ # VormProvider, AutoVorm, etc. |
| 178 | +│ │ │ ├── validation/ # Built-in validators |
| 179 | +│ │ │ ├── types/ # TypeScript definitions |
| 180 | +│ │ │ └── utils/ # Path helpers |
| 181 | +│ │ └── __tests__/ # Vitest tests |
| 182 | +│ ├── vorm-nuxt/ # Nuxt module |
| 183 | +│ ├── playground/ # Demo app (Vite + Vue + TailwindCSS) |
| 184 | +│ └── docs/ # VitePress documentation |
| 185 | +├── .changeset/ # Changesets configuration |
| 186 | +└── .github/workflows/ # Release automation |
| 187 | +``` |
0 commit comments