Repository navigation
feat: comprehensive project improvements across 10 areas - #3
Merged
Merged
Conversation
…ng tests - Fix silent batch commit errors: failed batches now report errors and adjust stats - Add CLI validation bounds: batch-size (1-500), parallel (1-20), rate-limit (>=0), max-depth (0-100), retries (0-10), limit (>=0) - Consolidate duplicated query building into shared buildQueryWithFilters helper - Consolidate subcollection filtering into shared getFilteredSubcollections helper - Refactor config merging with resolve() helper to reduce repetitive null coalescing - Improve state file error messages for corrupted JSON and missing version fields - Fix Firebase app cleanup on interactive mode connection errors - Add config file extension warning for unrecognized formats - Webhook sendWebhook now returns boolean to indicate success/failure - Refactor conflict detection with local comparison helper - Add FirebaseError interface to strengthen TypeScript types - Add missing tests for credentials, display, and generator modules - Add validator tests for new numeric bounds - Add CHANGELOG.md and .editorconfig https://claude.ai/code/session_01Mfs7sviD8epMkLVBRVDNiE
…tion improvements - Block HTTP webhooks by default, require --allow-http-webhook flag - Validate transform file extensions (.ts, .js, .mjs, .mts only) - Validate rename collection mappings as valid Firestore IDs - Make transform errors visible to user with warn() output - Handle orphaned state collections in resume mode with warnings - Optimize integrity verification: skip re-fetch in non-merge mode - Document --limit root-level-only behavior in CLI help - Document FSCOPY_SKIP_CREDENTIALS_CHECK env var in README - Add transform file examples (anonymize, add-metadata, filter-and-reshape) - Add --allow-http-webhook to config options tables https://claude.ai/code/session_01Mfs7sviD8epMkLVBRVDNiE
Add ~27 integration tests running against the Firestore emulator to validate real API behavior (pagination, subcollections, batch writes, count aggregation). - Create integration test suite in src/__tests__/integration/ with helpers - Add transfer, clear, count, and end-to-end integration tests - Configure Firebase emulator (firebase.json) and npm scripts - Handle emulator credentials in firebase/index.ts (skip ADC when emulator) - Add CI workflow job for integration tests with emulator - Add firebase-tools as devDependency https://claude.ai/code/session_01Mfs7sviD8epMkLVBRVDNiE
- Replace console.* with stderr writes in credentials.ts, state/index.ts, config/parser.ts to avoid bypassing --quiet/--json/--log modes - Add paginated clearing in clearCollection() to avoid loading entire collections into memory on large datasets - Add rename collision detection (multiple sources -> same dest) - Add idPrefix/idSuffix validation (reject "/" in paths) - Add webhook retry with exponential backoff on 5xx/network errors - Add webhook payload size validation (2MB limit) - Centralize magic numbers in constants.ts (batch limits, timeouts, etc.) - Add error handling in cleanupFirebase() to prevent masking errors - Create parent directory for log files if it doesn't exist - Validate transform function on live runs, not just dry-run - Protect doc.data() calls against corrupted documents https://claude.ai/code/session_01Mfs7sviD8epMkLVBRVDNiE
…flict detection - Replace broken conflict detection (double getAll comparing identical data) with chunked FieldPath.documentId() 'in' queries using .select() - Use .count() aggregation for progress bar counting (1 read vs N per collection) - Add lazy subcollection counting during transfer instead of upfront full scan - Paginate deleteOrphanDocuments and countWithSubcollections to bound memory - Add .select() to clearCollection queries to reduce bandwidth - Add graceful shutdown (SIGINT/SIGTERM) with state flush for --resume - Guard against double Firebase initialization (prevents app leaks) - Remove dead code (isDocCompleted/markDocCompleted) replaced by CompletedDocsCache - Move maxDepthWarningsShown from module-level to TransferContext - Add format:check step to CI pipeline
- Add 19 critical-path tests for transferCollection with full Firestore mocks - Preserve partial stats on transfer error instead of returning empty stats - Fix WhereFilter type to include null, remove unsafe type casts - Remove duplicate clearOrphanSubcollections function in clear.ts - Bump all deps: eslint 10, yargs 18, firebase-tools 15, firebase-admin 13.7 - Add ESLint no-floating-promises rule, fix preserve-caught-error violations - CI: add security audit, coverage step, tag/version verification in release - Replace webhook payload double-cast with clean spread operator
There was a problem hiding this comment.
Pull request overview
This PR delivers a broad set of reliability, safety, and CI improvements for the Firestore copy tool, with emphasis on critical-path test coverage, safer config/type handling, and more resilient operational behavior (webhooks, state/resume, pagination).
Changes:
- Adds extensive unit + integration coverage for
transferCollection, plus new integration test harness for the Firestore emulator. - Refactors transfer/count/clear helpers for deduplication and performance (pagination, shared query/subcollection helpers), and improves state/resume + shutdown behavior.
- Tightens validation and safety (config bounds, transform file extension validation, webhook HTTPS-by-default with retry/size limits), and updates CI workflows + dependencies.
Reviewed changes
Copilot reviewed 54 out of 55 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/webhook/index.ts | Adds webhook constants, payload sizing, retries, timeout, and HTTPS validation behavior updates. |
| src/utils/progress.ts | Adds ability to dynamically increase progress bar total. |
| src/utils/output.ts | Ensures log file parent directory exists before writing. |
| src/utils/index.ts | Re-exports FirebaseError type from errors utilities. |
| src/utils/errors.ts | Introduces FirebaseError interface and uses it for formatting/logging. |
| src/utils/credentials.ts | Routes credential-missing output to stderr via a single message write. |
| src/types.ts | Extends WhereFilter.value to include null; adds allowHttpWebhook to config/args. |
| src/transform/loader.ts | Validates transform file extensions; improves error chaining via cause. |
| src/transfer/transfer.ts | Refactors query/subcollection helpers; adds subcollection counting for progress; changes conflict detection; improves batch failure accounting; optimizes integrity verification logic. |
| src/transfer/index.ts | Exports new helper utilities (getFilteredSubcollections, buildQueryWithFilters). |
| src/transfer/helpers.ts | Adds shared getFilteredSubcollections + buildQueryWithFilters helpers. |
| src/transfer/count.ts | Refactors subcollection counting to paginate and reuse shared query helper. |
| src/transfer/clear.ts | Refactors clearing and orphan deletion to use pagination and shared subcollection filtering helper. |
| src/state/index.ts | Adds stderr warning helper; improves state loading diagnostics; adds resume validation warnings; changes validation return type. |
| src/orchestrator.ts | Preserves partial stats on failure; adds signal handling for graceful shutdown; adjusts progress-counting approach; threads new context state. |
| src/interactive.ts | Ensures Firebase app cleanup on interactive connection failures. |
| src/firebase/index.ts | Avoids credentials when using emulator; adds initialization guard; makes cleanup resilient; improves error chaining. |
| src/constants.ts | Adds bounds constants and webhook/clear constants (timeouts, payload size, paging size). |
| src/config/validator.ts | Adds numeric bounds validation and rename mapping validation (ID validity + collisions). |
| src/config/parser.ts | Adds config-extension warning; makes warnings go to stderr; removes unsafe casts; refactors merge logic via resolve(). |
| src/config/defaults.ts | Adds allowHttpWebhook default. |
| src/cli.ts | Updates --limit description; adds --allow-http-webhook flag; passes allow-http into webhook validator. |
| src/tests/webhook.test.ts | Updates tests for new webhook URL validation behavior. |
| src/tests/validator.test.ts | Adds coverage for new config bounds validation + defaults updates. |
| src/tests/transfer.test.ts | Updates test config scaffolding for new config field. |
| src/tests/transfer-critical.test.ts | Adds critical-path transferCollection tests (new file). |
| src/tests/state.test.ts | Updates for new resume validation return type and warnings behavior. |
| src/tests/orchestrator.test.ts | Updates test config scaffolding for new config field. |
| src/tests/loader.test.ts | Adds tests for transform extension validation errors. |
| src/tests/interactive.test.ts | Updates test config scaffolding for new config field. |
| src/tests/integration/transfer.integration.test.ts | Adds Firestore-emulator integration tests for transfer behavior (new file). |
| src/tests/integration/helpers.ts | Adds emulator test helpers (app lifecycle, seed/query utilities, config/context creation) (new file). |
| src/tests/integration/end-to-end.integration.test.ts | Adds end-to-end integration tests for orchestrator pipeline (new file). |
| src/tests/integration/count.integration.test.ts | Adds integration tests for counting behavior (new file). |
| src/tests/integration/clear.integration.test.ts | Adds integration tests for clear + delete-missing behavior (new file). |
| src/tests/generator.test.ts | Adds tests for config generator behavior (new file). |
| src/tests/firebase.test.ts | Ensures Firebase cleanup between tests for deterministic initialization. |
| src/tests/display.test.ts | Adds tests for config/summary/json output formatting (new file). |
| src/tests/credentials.test.ts | Adds tests for credential path detection logic (new file). |
| src/tests/count.test.ts | Updates test config scaffolding and formatting cleanup. |
| src/tests/conflicts.test.ts | Updates test config scaffolding for new config field. |
| src/tests/clear.test.ts | Updates test config scaffolding for new config field. |
| package.json | Updates scripts (unit/integration split), adds emulator script, bumps dependencies/devDependencies. |
| firebase.json | Adds Firestore emulator configuration (new file). |
| examples/transforms/filter-and-reshape.ts | Adds example transform (filter/reshape) (new file). |
| examples/transforms/anonymize.ts | Adds example transform (anonymization) (new file). |
| examples/transforms/add-metadata.ts | Adds example transform (metadata injection) (new file). |
| eslint.config.js | Enables @typescript-eslint/no-floating-promises. |
| README.md | Documents new CLI flag and clarifies limit semantics; documents env vars and extension validation. |
| CLAUDE.md | Updates CLI option documentation table. |
| CHANGELOG.md | Adds initial changelog with release notes for 1.5.0 (new file). |
| .github/workflows/release.yml | Adds tag/version verification; fixes Bun test invocation. |
| .github/workflows/ci.yml | Adds audit/format/coverage steps and separate integration-test job. |
| .editorconfig | Adds repository-wide editor defaults (new file). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…lure generateConfigFile() sets process.exitCode = 1 when file already exists. This leaked into the test runner, causing exit code 1 despite all tests passing. Reset exitCode after the test assertion.
- Separate rootCount/subCount in count.ts so --limit only considers root documents, preventing subcollection counts from prematurely stopping pagination - Use continue-on-error instead of suppressing audit output in CI
test:coverage was running all test files including integration tests that require the Firestore emulator, causing CI failure.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
transferCollectioncovering transforms with errors, conflict detection, batch commit failures, resume mode, subcollections + maxDepth, dry run, integrity verification, pagination, rate limiter, and skipped docsnulltoWhereFilter.valuetype, remove unsafeas unknown ascasts in parser and webhookclearOrphanSubcollectionsfunction, reuseclearDocSubcollections@typescript-eslint/no-floating-promisesrule, fixpreserve-caught-errorviolations from ESLint 10bun test→bun run testTest plan
fscopy --help)