# Contributing to MetonaSqlark Thanks for your interest in contributing! This document outlines the development workflow and conventions. ## Prerequisites - Node.js >= 16.0.0 - npm >= 8.0.0 ## Setup ```bash git clone https://git.metona.cn/MetonaTeam/MetonaSqlark.git cd MetonaSqlark npm install ``` ## Development ```bash # Start dev server with hot reload (port 3001) npm run dev # Run tests in watch mode npm run test:watch # Type check npm run typecheck # Lint npm run lint npm run lint:fix # Format npm run format ``` ## Project Structure ``` src/ ├── index.ts # Entry point, global API (MetonaSqlark + MeSqlark) ├── core.ts # MetonaSqlark main class ├── constants.ts # Types, defaults, enums, errors ├── utils.ts # Utility functions ├── engine/ # Storage engines │ ├── interface.ts # IStorageEngine interface │ ├── memory.ts # MemoryEngine (Map-based) │ ├── indexeddb.ts # IndexedDBEngine (browser persistence) │ └── opfs.ts # OPFSEngine (Origin Private File System) ├── hybrid/ # HybridEngine (write-through) ├── table/ # Table management & Schema validation ├── query/ # Query system │ ├── ast.ts # SQL AST type definitions │ ├── builder.ts # Chainable QueryBuilder API │ ├── compiler.ts # AST → QueryPlan compiler │ ├── executor.ts # QueryExecutor with JOIN/GROUP BY support │ └── where-matcher.ts # Unified WHERE matching logic ├── sql/ # SQL parser │ ├── tokens.ts # Token types & keywords │ ├── lexer.ts # Tokenizer │ └── parser.ts # Recursive descent parser ├── transaction/ # Transaction manager ├── plugin/ # Plugin system (14 lifecycle hooks) └── integrations/ # React & Vue hooks tests/ # Test suite (264+ test cases, 15 test suites) site/ # Documentation site (index / docs / demo) ``` ## Code Conventions ### TypeScript - **Strict mode** is enabled — all code must pass `tsc --noEmit`. - Export types explicitly. Avoid `any` where possible. - Use `interface` for object shapes, `type` for unions/primitives. ### Style - Run `npm run format` before committing (uses Prettier). - Follow existing comment patterns: JSDoc `/** */` for public APIs, `//` for inline notes. - Keep functions focused and under ~60 lines where practical. ### Testing - **Every new feature must include tests.** - Test files mirror source structure: `src/foo.ts` → `tests/foo.test.ts`. - Use descriptive test names: `('does X when Y')`. - Run the full suite before submitting: `npm test`. ### Commits - Use conventional commit messages: - `feat: add SQL GROUP BY support` - `fix: JOIN with multiple ON conditions` - `docs: update API reference` - `test: add edge case coverage` - `chore: optimize rollup dev build` ## Architecture MetonaSqlark follows a layered architecture: ``` ┌──────────────────────────────────────────────────┐ │ MetonaSqlark / MeSqlark (Public API) │ ├──────────────────────────────────────────────────┤ │ SQL Parser │ QueryBuilder │ Transaction │ Plugin │ │ (Lexer→AST) │ (.select…) │ Manager │ System │ ├──────────────────────────────────────────────────┤ │ QueryExecutor (AST → Results) │ │ JOIN · GROUP BY · HAVING · DISTINCT · Agg │ ├──────────────────────────────────────────────────┤ │ IStorageEngine (Interface) │ ├─────────┬──────────┬──────────┬──────────────────┤ │ Memory │ IndexedDB │ OPFS │ Hybrid │ │ Engine │ Engine │ Engine │ Engine │ └─────────┴──────────┴──────────┴──────────────────┘ ``` ### Key Design Decisions 1. **AST as Universal Intermediate Representation**: Both SQL strings and Query Builder produce the same AST, ensuring consistent behavior regardless of API used. 2. **Write-Through Hybrid Strategy**: When using `mode: 'hybrid'`, all writes go to both memory and disk simultaneously. Reads always hit memory for maximum speed. 3. **Plugin Hook Pipeline**: 14 lifecycle hooks allow intercepting database operations without modifying core code. 4. **Hand-Written SQL Parser**: No dependencies on parser generators — a recursive-descent parser keeps the bundle size minimal. ## Building ```bash # Production build (all formats) npm run build # Output in dist/ # ├── metona-sqlark.js UMD # ├── metona-sqlark.min.js UMD minified (~42KB / ~10KB gzip) # ├── metona-sqlark.esm.js ES Module # ├── metona-sqlark.cjs.js CommonJS # └── metona-sqlark.d.ts TypeScript declarations ``` ## Plugin Development Plugins follow a simple convention: ```typescript import type { MetonaPlugin } from '@metona-team/metona-sqlark'; const myPlugin: MetonaPlugin = { name: 'myPlugin', version: '1.0.0', description: 'Description of my plugin', priority: 50, // higher = executed first install(db) { // Use db.on() to subscribe to hooks db.on('beforeInsert', async (rows) => { // Validate or transform data }); db.on('afterQuery', async (sql, result) => { // Log or cache query results }); }, destroy() { // Clean up event listeners, timers, etc. }, }; // Register in config const db = await MetonaSqlark.create({ name: 'my-app', plugins: [myPlugin], }); ``` ### Available Lifecycle Hooks | Hook | Trigger | Parameters | |------|---------|------------| | `beforeCreateTable` | Before table creation | schema | | `afterCreateTable` | After table creation | schema | | `beforeDropTable` | Before table drop | tableName | | `afterDropTable` | After table drop | tableName | | `beforeInsert` | Before row insert | rows[] | | `afterInsert` | After row insert | rows[] | | `beforeUpdate` | Before row update | query, updates | | `afterUpdate` | After row update | query, updates, count | | `beforeDelete` | Before row delete | query | | `afterDelete` | After row delete | query, count | | `beforeQuery` | Before SQL query | sql | | `afterQuery` | After SQL query | sql, result | | `beforeTransaction` | Before transaction | - | | `afterTransaction` | After transaction | - | ## Releasing 1. Update version in `package.json` and `src/constants.ts` (`VERSION` constant). 2. Update `CHANGELOG.md`. 3. Run full test suite: `npm test`. 4. Build: `npm run build`. 5. Publish: `npm publish`. ## Questions? Open an issue at [git.metona.cn/MetonaTeam/MetonaSqlark/issues](https://git.metona.cn/MetonaTeam/MetonaSqlark/issues).