|
| 1 | +# Scope |
| 2 | + |
| 3 | +- This file applies to the entire repository: `remotestorage/remotestorage.js`. |
| 4 | +- Follow these instructions for all code changes, scripts, and tests. |
| 5 | + |
| 6 | +# Build, Lint, Test |
| 7 | + |
| 8 | +- Install dependencies: `npm ci` (CI) or `npm install` (local). |
| 9 | +- TypeScript compile: `tsc` or `tsc -w` for auto-compile on changes. |
| 10 | +- Development bundle/watch: `npm run dev`. |
| 11 | +- Production bundle: `npm run build:release` (webpack production). |
| 12 | +- Lint sources: `npm run lint` (verbose) or `npm run lint:quiet`. |
| 13 | +- Lint Mocha specs: `npm run lint:specs` or `npm run lint:specs:quiet`. |
| 14 | +- Full test suite: `npm test` (runs `tsc` and `scripts/test-all.sh`). |
| 15 | +- Mocha unit tests: `npm run test:mocha`. |
| 16 | +- Mocha watch: `npm run test:watch`. |
| 17 | +- Typedoc docs (CI release step): `typedoc` via `npm run version`. |
| 18 | + |
| 19 | +# Running a Single Test |
| 20 | + |
| 21 | +- Mocha (preferred for new tests): |
| 22 | + - Single file: `npm run test:mocha -- test/unit/<name>.test.mjs`. |
| 23 | + - Single test by grep: `npm run test:mocha -- --grep "pattern"`. |
| 24 | + - Watch a file: `npm run test:watch -- test/unit/<name>.test.mjs`. |
| 25 | +- Jaribu (legacy suites while being ported): |
| 26 | + - Single suite: `./node_modules/.bin/jaribu test/unit/<suite>-suite.js`. |
| 27 | + - Notes: Jaribu suites are older `.js` files like `test/unit/inmemorycaching-suite.js`. |
| 28 | + |
| 29 | +# Continuous Integration |
| 30 | + |
| 31 | +- GitHub Actions workflow: `.github/workflows/test-and-lint.yml`. |
| 32 | +- Matrix Node versions: `18`, `20`. |
| 33 | +- Steps: `npm ci`, `npm test` (Jaribu), `npm run test:mocha -- --exit`, lint tasks, `npm run build:release`. |
| 34 | + |
| 35 | +# Project Overview |
| 36 | + |
| 37 | +- Library entrypoints: TypeScript sources in `src/` compiled/bundled to `release/`. |
| 38 | +- Docs: VitePress in `docs/` with Typedoc-generated API pages. |
| 39 | +- Tests: Legacy Jaribu suites in `test/unit/*-suite.js`; Mocha/Chai specs in `test/unit/*.test.mjs`. |
| 40 | + |
| 41 | +# Languages and Tooling |
| 42 | + |
| 43 | +- TypeScript (target `es2015`, module `commonjs`), Mocha/Chai, Sinon, ESLint (`@typescript-eslint`), Webpack, Typedoc. |
| 44 | +- Formatting: esformatter is only used for `src/sync.js` via `npm run format` (legacy). Prefer ESLint autofix for TS files. |
| 45 | + |
| 46 | +# Code Style Guidelines |
| 47 | + |
| 48 | +## Imports |
| 49 | + |
| 50 | +- Use TypeScript ES module syntax: `import { Thing } from "./path";`. |
| 51 | +- Prefer named imports; default imports only when the module exports default. |
| 52 | +- Relative paths: keep them short and stable; avoid deep chained `../../..` where possible by reorganizing modules if needed. |
| 53 | +- Do not use `require` in TypeScript files (`.ts`). The ESLint config warns for `@typescript-eslint/no-var-requires`. |
| 54 | + |
| 55 | +## Formatting |
| 56 | + |
| 57 | +- Indentation: 2 spaces. ESLint enforces `indent: ["error", 2]`. |
| 58 | +- Curly braces required: `curly: 2`. |
| 59 | +- Semicolons required: `semi: 2`. |
| 60 | +- Arrow function spacing enforced: `arrow-spacing: 2`. |
| 61 | +- Block spacing enforced: `block-spacing: 2`. |
| 62 | +- No multi-line string literals using `\` concatenations: `no-multi-str: 2`. |
| 63 | +- Console: only `console.warn` and `console.error` allowed. `no-console` blocks other methods. |
| 64 | +- Bitwise operators not allowed: `no-bitwise: 2`. |
| 65 | +- Equality: always use strict `===`/`!==` (`eqeqeq: 2`). |
| 66 | + |
| 67 | +## Types |
| 68 | + |
| 69 | +- Avoid `any` wherever possible (`@typescript-eslint/no-explicit-any: 1`). Prefer precise interfaces and type aliases. |
| 70 | +- Prefer explicit return types on exported functions. |
| 71 | +- Avoid unused variables and parameters (`@typescript-eslint/no-unused-vars: 1`). |
| 72 | +- Avoid using variables before definition (`@typescript-eslint/no-use-before-define: 1`). |
| 73 | +- Allow empty interfaces only if necessary (`@typescript-eslint/no-empty-interface: 1`). |
| 74 | +- Shadowing is warned (`@typescript-eslint/no-shadow: "warn"`); refactor to avoid. |
| 75 | +- Globals: the ESLint config defines browser and node environments. Don’t introduce implicit globals. |
| 76 | + |
| 77 | +## Naming Conventions |
| 78 | + |
| 79 | +- Use `camelCase` for variables, parameters, and functions. |
| 80 | +- Use `PascalCase` for classes, types, and enums. |
| 81 | +- Constructors/new-cap: ESLint enforces capitalization for constructor-like identifiers; exceptions include `Authorize`, `Discover` in legacy code. |
| 82 | +- File names: prefer `kebab-case` or `lowercase` for `.ts` files; keep names descriptive and aligned with exported symbols. |
| 83 | +- Constants: UPPER_CASE only for true compile-time constants; otherwise use `camelCase`. |
| 84 | + |
| 85 | +## Error Handling |
| 86 | + |
| 87 | +- Do not use `debugger` (`no-debugger: 2`). |
| 88 | +- Fail fast on invalid inputs; validate arguments and throw specific errors. |
| 89 | +- Use domain-specific error classes where available (e.g., `UnauthorizedError` in `src/unauthorized-error.ts`, `SyncError` in `src/sync-error.ts`, `SchemaNotFoundError` in `src/schema-not-found-error.ts`). |
| 90 | +- Avoid swallowing errors; when catching, either handle or rethrow with context. |
| 91 | +- Logging: prefer `console.warn`/`console.error` and keep messages actionable. |
| 92 | + |
| 93 | +## Asynchrony and Side Effects |
| 94 | + |
| 95 | +- Prefer `async/await` over raw Promise chains for readability. |
| 96 | +- Make network/storage side effects explicit in function names and docs. |
| 97 | +- Avoid shared mutable state; encapsulate in classes/modules. |
| 98 | + |
| 99 | +# Testing Guidelines |
| 100 | + |
| 101 | +- New tests: write Mocha/Chai specs in `test/unit/*.test.mjs`. |
| 102 | +- Use `sinon` for stubs/mocks/spies as needed. |
| 103 | +- Keep tests deterministic; avoid relying on timers or external services. |
| 104 | +- For single-test debugging: use `--grep` or isolate a `describe.only`/`it.only` in local runs (revert before committing). |
| 105 | +- Lint specs with `npm run lint:specs`. |
| 106 | + |
| 107 | +# Documentation |
| 108 | + |
| 109 | +- Public APIs should have TSDoc comments; Typedoc generates docs. |
| 110 | +- Update `docs/` guides when changing behavior or adding features. |
| 111 | +- Docs are built with VitePress: `npm run docs:dev`, `npm run docs:build`, `npm run docs:preview`. |
| 112 | +- Follow contributing docs in `docs/contributing/` (GitHub flow, building, testing, release checklist). |
| 113 | + |
| 114 | +# Dependency Management |
| 115 | + |
| 116 | +- Use exact or caret versions as configured. Do not introduce unpinned unstable dependencies. |
| 117 | +- Keep `devDependencies` limited to tools needed for building/testing. |
| 118 | +- Mac OS postshrinkwrap step adjusts `package-lock.json` URLs to `https` (`postshrinkwrap` script). Do not remove. |
| 119 | + |
| 120 | +# Build Artifacts |
| 121 | + |
| 122 | +- Generated bundles go to `release/`. Do not commit local debug builds. |
| 123 | +- Types are emitted to `release/types`. The package `types` field points to `release/types/remotestorage.d.ts`. |
| 124 | + |
| 125 | +# Performance and Complexity |
| 126 | + |
| 127 | +- Keep cyclomatic complexity reasonable (`complexity: warn`). |
| 128 | +- Limit function size (`max-statements: ["warn", 15]`). Break up large functions. |
| 129 | + |
| 130 | +# Module Boundaries |
| 131 | + |
| 132 | +- Core domains include: access, caching, clients, discovery, sync, storage backends. |
| 133 | +- Place new code in the appropriate domain under `src/` with focused responsibilities. |
| 134 | + |
| 135 | +# Logging and Diagnostics |
| 136 | + |
| 137 | +- Use `src/log.ts` utilities if applicable; avoid ad-hoc logging scattered across modules. |
| 138 | + |
| 139 | +# Browser vs Node |
| 140 | + |
| 141 | +- Code runs in both environments. Guard usage of environment-specific APIs. |
| 142 | +- For Node-specific types, see `@types/node` dependency. |
| 143 | + |
| 144 | +# Security |
| 145 | + |
| 146 | +- Avoid `eval` and `Function` constructors (`no-eval: 2`, `no-new-func: 0 but discouraged`). |
| 147 | +- Validate external inputs and URLs; do not construct script URLs. |
| 148 | + |
| 149 | +# Release Process |
| 150 | + |
| 151 | +- `npm run preversion`: tests + lint + type build must pass. |
| 152 | +- `npm run version`: builds release bundle and regenerates docs; commits `release/` and `docs/api/`. |
| 153 | + |
| 154 | +# Cursor/Copilot Rules |
| 155 | + |
| 156 | +- Cursor: no `.cursor/rules/` or `.cursorrules` found in this repo. |
| 157 | +- Copilot: no `.github/copilot-instructions.md` present. |
| 158 | +- If such rules are added later, agents must incorporate them into edits and reviews. |
| 159 | + |
| 160 | +# Contributing |
| 161 | + |
| 162 | +- Read `docs/contributing/` for detailed guidelines. |
| 163 | +- Follow GitHub Flow: small PRs, clear descriptions, passing CI. |
| 164 | + |
| 165 | +# Contact and Help |
| 166 | + |
| 167 | +- Issues: https://github.com/remotestorage/remotestorage.js/issues |
| 168 | +- Docs: https://remotestorage.io/rs.js/docs/ |
| 169 | +- Community: https://community.remotestorage.io/ |
| 170 | +- remoteStorage protocol specification: https://datatracker.ietf.org/doc/draft-dejong-remotestorage/ |
| 171 | + |
| 172 | +# Agent Notes |
| 173 | + |
| 174 | +- Prefer small, targeted changes respecting existing structure. |
| 175 | +- Do not add license headers unless requested. |
| 176 | +- Do not commit unless explicitly asked; use local validation. |
| 177 | +- Reference files with full paths when communicating changes. |
| 178 | + |
| 179 | +# Assistant Config |
| 180 | + |
| 181 | +- Config file: `opencode.config.json` at repo root. |
| 182 | +- Approvals: `on_request` — assistant asks before sensitive actions. |
| 183 | +- Sandbox: `workspace_write` filesystem; `restricted` network. |
| 184 | +- Prompts: require an explicit user approval for `shell` commands unless the command is in the shell allowlist below. |
| 185 | +- Allowlist (shell): npm scripts `dev`, `build:dev`, `build:js`, `test`, `test:mocha`, `test:watch`, `lint`, `lint:quiet`, `lint:specs`, `lint:specs:quiet`, `format`; command `npm install`. |
| 186 | +- Behavior: Allowlisted shell commands bypass the extra approval prompt; all other shell commands require explicit user permission before tool use. |
| 187 | +- RESTRICTIONS: For ANY shell command not in the allowlist (including `git`, `gh`, `ls`, `rm`, etc.), you MUST explicitly ask the user for permission in the chat BEFORE using the tool. |
| 188 | +- GIT/GH POLICY: NEVER run `git commit`, `git push`, or `gh` commands without a direct, explicit request from the user. |
0 commit comments