Skip to content

chore: build with tsdown#46

Merged
Nr9 merged 3 commits intomainfrom
chore/tsdown
Sep 5, 2025
Merged

chore: build with tsdown#46
Nr9 merged 3 commits intomainfrom
chore/tsdown

Conversation

@Nr9
Copy link
Copy Markdown

@Nr9 Nr9 commented Sep 5, 2025

Summary by CodeRabbit

  • Chores

    • Added a publish-time lint step (publint) to CI and package scripts; runs after build.
    • Migrated build tooling from Rollup to tsdown and removed legacy Rollup dev dependencies/configs.
    • Added per-package tsdown build configurations.
  • Packaging

    • Improved TypeScript type resolution with separate import/require type entries for ESM and CJS consumers.
    • Excluded tsdown config files from published packages.

@Nr9 Nr9 requested a review from a team as a code owner September 5, 2025 00:10
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Sep 5, 2025

Walkthrough

Replaces per-package Rollup builds with tsdown configs, updates package type exports to separate ESM/CJS declaration paths, removes Rollup deps/configs, adds publint and lint:publint scripts and CI publint step, adds tsdown config files and ignores them from published packages, and tweaks a Firestore import split.

Changes

Cohort / File(s) Summary
CI workflow update
\.github/workflows/pull-request.yml
Adds a new publint step to the lint job that runs pnpm lint:publint after the existing prettier step.
Root package & dev tooling
package.json
Adds script lint:publint (nx run-many --target lint:publint), removes Rollup-related devDependencies (rollup, @rollup/plugin-typescript, rollup-plugin-dts), and adds publint and tsdown devDependencies.
Package package.json migrations
react-firestore: packages/react-firestore/package.json · react-kitchen-sink: packages/react-kitchen-sink/package.json · rxjs-firebase: packages/rxjs-firebase/package.json · zustand-firestore: packages/zustand-firestore/package.json
Switches build script to tsdown, adds lint:publint script (pnpm build && publint), changes top-level types to ./lib/index.d.mts, and changes exports["."].types to an object with import: "./lib/index.d.mts" and require: "./lib/index.d.cts".
Removed Rollup configs
packages/*/rollup.config.js (react-firestore, react-kitchen-sink, rxjs-firebase, zustand-firestore)
Removes per-package Rollup configuration files (both JS build and DTS/type-build configs).
New tsdown configs
packages/react-firestore/tsdown.config.mjs, packages/react-kitchen-sink/tsdown.config.mjs, packages/rxjs-firebase/tsdown.config.mjs, packages/zustand-firestore/tsdown.config.mjs
Adds tsdown configuration modules exporting defineConfig({ outDir: 'lib', platform: 'browser', format: ['esm','cjs'], target: 'es2020', fixedExtension: true }).
.npmignore updates
packages/react-firestore/.npmignore, packages/react-kitchen-sink/.npmignore, packages/rxjs-firebase/.npmignore, packages/zustand-firestore/.npmignore
Adds tsdown.config.json to each package's .npmignore to exclude tsdown config from published artifacts.
Minor import change
packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts
Splits Firestore imports: DocumentData and QueryDocumentSnapshot imported from @firebase/firestore, and GeoPoint/Timestamp from firebase/firestore (import statements reorganized).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Dev as Developer
  participant CI as CI
  participant Repo as Repo scripts
  participant PKG as Package build (tsdown)
  participant Publint as publint

  Dev->>CI: Open PR / push
  CI->>Repo: run lint job
  Repo->>CI: run prettier step
  CI->>Repo: run publint step (pnpm lint:publint)
  Repo->>PKG: pnpm build (tsdown) invoked by lint:publint
  PKG-->>Repo: emit CJS/ESM + `.d.cts`/`.d.mts`
  Repo->>Publint: run publint on outputs
  Publint-->>CI: return results (pass/fail)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • fpbouchard

Poem

I hop through build files, light and spry,
Rollup folded, tsdown I try.
Types split neatly, ESM and CJS too,
publint hums softly — checks pass through. 🥕

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/tsdown

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/react-kitchen-sink/tsdown.config.mjs (1)

5-7: Confirm intent: platform: 'browser' + format: ['esm','cjs'] makes only ESM browser-targeted; CJS will target Node.

In tsdown, CJS format is always built for Node regardless of platform. Keep both if you need a Node CJS artifact; otherwise consider emitting ESM only for this package.

Optional tweak:

-  format: ['esm', 'cjs'],
+  format: ['esm'],

Reference: CJS platform is forced to node; formats list and usage. (tsdown.dev)

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1b6a716 and fe5ea3a.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • .github/workflows/pull-request.yml (1 hunks)
  • package.json (2 hunks)
  • packages/react-firestore/.npmignore (1 hunks)
  • packages/react-firestore/package.json (2 hunks)
  • packages/react-kitchen-sink/.npmignore (1 hunks)
  • packages/react-kitchen-sink/package.json (1 hunks)
  • packages/react-kitchen-sink/tsdown.config.mjs (1 hunks)
  • packages/rxjs-firebase/.npmignore (1 hunks)
  • packages/rxjs-firebase/package.json (2 hunks)
  • packages/zustand-firestore/.npmignore (1 hunks)
  • packages/zustand-firestore/package.json (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (10)
  • packages/react-kitchen-sink/.npmignore
  • packages/rxjs-firebase/.npmignore
  • packages/react-firestore/.npmignore
  • package.json
  • .github/workflows/pull-request.yml
  • packages/zustand-firestore/package.json
  • packages/zustand-firestore/.npmignore
  • packages/react-kitchen-sink/package.json
  • packages/rxjs-firebase/package.json
  • packages/react-firestore/package.json
🧰 Additional context used
🪛 ESLint
packages/react-kitchen-sink/tsdown.config.mjs

[error] 1-1: Unable to resolve path to module 'tsdown'.

(import-x/no-unresolved)

🔇 Additional comments (1)
packages/react-kitchen-sink/tsdown.config.mjs (1)

4-9: Config options look valid; fixedExtension: true is appropriate for .mjs/.cjs outputs.

fixedExtension is a supported option and forces .mjs/.cjs extensions; target: 'es2020', outDir, and format are standard config fields. LGTM.

Refs: option definitions for fixedExtension, outDir, target, and format. (tsdown.dev)

Comment thread packages/react-kitchen-sink/tsdown.config.mjs
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts (1)

15-16: Don’t treat all objects as plain objects; this breaks DocumentReference and other Firestore classes.

value instanceof Object will match Firestore classes (e.g., DocumentReference, Bytes) and strip them via Object.entries(...), returning an empty or mangled object. Use a plain-object guard.

Apply:

-    case value instanceof Object:
-      return Object.fromEntries(Object.entries(value).map(([key, v]) => [key, handleFirestoreDataTypes(v)])) as T
+    case value !== null && typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype:
+      return Object.fromEntries(
+        Object.entries(value).map(([key, v]) => [key, handleFirestoreDataTypes(v)])
+      ) as T
🧹 Nitpick comments (1)
packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts (1)

11-14: Type-safety of array mapping could be improved (optional).

The casts to T[keyof T] and as T are broad. If you keep this utility generic, prefer widening to unknown[] internally and narrowing at the call site, or introduce a constrained generic for arrays.

Example:

-    case Array.isArray(value):
-      return value.map((v) => handleFirestoreDataTypes(v) as T[keyof T]) as T
+    case Array.isArray(value):
+      return (value as unknown[]).map((v) => handleFirestoreDataTypes(v)) as unknown as T
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fe5ea3a and d982b06.

📒 Files selected for processing (1)
  • packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Ensure all new code conforms to the project's ESLint and Prettier rules

Files:

  • packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts
🧠 Learnings (3)
📚 Learning: 2025-08-16T16:32:15.795Z
Learnt from: CR
PR: valian-ca/react-firebase#0
File: packages/react-firestore/GEMINI.md:0-0
Timestamp: 2025-08-16T16:32:15.795Z
Learning: Applies to packages/react-firestore/**/*.{ts,tsx} : Write all new code in TypeScript

Applied to files:

  • packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts
📚 Learning: 2025-08-16T16:32:15.795Z
Learnt from: CR
PR: valian-ca/react-firebase#0
File: packages/react-firestore/GEMINI.md:0-0
Timestamp: 2025-08-16T16:32:15.795Z
Learning: Applies to packages/react-firestore/**/*.{ts,tsx} : Ensure all code conforms to the project’s ESLint rules

Applied to files:

  • packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts
📚 Learning: 2025-08-16T16:32:27.169Z
Learnt from: CR
PR: valian-ca/react-firebase#0
File: packages/rxjs-firebase/GEMINI.md:0-0
Timestamp: 2025-08-16T16:32:27.169Z
Learning: Applies to packages/rxjs-firebase/**/*.ts : Implement library code in TypeScript

Applied to files:

  • packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts
🪛 ESLint
packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts

[error] 1-1: Filename is not in kebab case. Rename it to firestore-data-converter.ts.

(unicorn/filename-case)


[error] 1-1: Unable to resolve path to module '@firebase/firestore'.

(import-x/no-unresolved)

🔇 Additional comments (2)
packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts (2)

1-1: Rename file to kebab-case to satisfy ESLint (unicorn/filename-case).

Current: firestoreDataConverter.ts. Expected: firestore-data-converter.ts.

If you want, I can generate a small script to rename and update imports across the repo.


22-24: If dual App/Db model types are required, avoid internal typings.

Should you need both App and Db model typing, model it without @firebase/* by accepting QueryDocumentSnapshot<App> and letting the converter be generic over App, keeping Db types internal to your withConverter usage. This prevents tight coupling to Firebase internals.

Do you actually consume the second generic elsewhere? If yes, I can propose a public-API-compliant typing for that flow.

Comment thread packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts (3)

23-25: Align with public QueryDocumentSnapshot<T> and return the converted type.

Public API uses a single generic. Returning FirestoreToJs<T> makes the conversion explicit and improves DX. Also resolves publint complaints.

-export const firestoreDataConverter = <AppModelType = DocumentData, DbModelType extends DocumentData = DocumentData>(
-  snapshot: QueryDocumentSnapshot<AppModelType, DbModelType>,
-) => handleFirestoreDataTypes(snapshot.data())
+export const firestoreDataConverter = <T extends DocumentData = DocumentData>(
+  snapshot: QueryDocumentSnapshot<T>,
+) => handleFirestoreDataTypes(snapshot.data()) as FirestoreToJs<T>

1-2: Use public Firebase entrypoint; drop @firebase internals and unify imports.

Importing from @firebase/firestore reaches into private APIs and triggers import-x/no-unresolved. Use the public firebase/firestore for both types and values. This also aligns with publint and tsdown expectations.

Apply:

-import { type DocumentData, type QueryDocumentSnapshot } from '@firebase/firestore'
-import { GeoPoint, Timestamp } from 'firebase/firestore'
+import type { DocumentData, QueryDocumentSnapshot } from 'firebase/firestore'
+import { GeoPoint, Timestamp } from 'firebase/firestore'

2-2: Refactor all @firebase/firestore imports and update ESLint config

  • Replace every internal import from @firebase/firestore with the public firebase/firestore entrypoint across the repo.
  • In your ESLint settings, add a TypeScript resolver under settings.import/resolver and adjust the import-x/extensions rule to ignore package imports so that firebase/firestore isn’t flagged for missing extensions.
🧹 Nitpick comments (1)
packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts (1)

4-21: Type soundness: function returns T but converts Timestamp to Date.

The current signature lies to the type system and leaks any-like casts. Model the deep conversion with a mapped conditional type and adjust the return type.

Add above the function:

type FirestoreToJs<T> =
  T extends Timestamp ? Date :
  T extends GeoPoint ? GeoPoint :
  T extends Array<infer U> ? Array<FirestoreToJs<U>> :
  T extends object ? { [K in keyof T]: FirestoreToJs<T[K]> } :
  T

Then change the function as follows:

-const handleFirestoreDataTypes = <T>(value: T): T => {
+const handleFirestoreDataTypes = <T>(value: T): FirestoreToJs<T> => {
   switch (true) {
     case value instanceof Date:
-      return value
+      return value as unknown as FirestoreToJs<T>
     case value instanceof GeoPoint:
-      return value
+      return value as unknown as FirestoreToJs<T>
     case value instanceof Timestamp:
-      return value.toDate() as T
+      return value.toDate() as unknown as FirestoreToJs<T>
     case typeof value === 'string':
-      return value
+      return value as unknown as FirestoreToJs<T>
     case Array.isArray(value):
-      return value.map((v) => handleFirestoreDataTypes(v) as T[keyof T]) as T
-    case value instanceof Object:
-      return Object.fromEntries(Object.entries(value).map(([key, v]) => [key, handleFirestoreDataTypes(v)])) as T
+      return (value as unknown as Array<unknown>)
+        .map((v) => handleFirestoreDataTypes(v)) as unknown as FirestoreToJs<T>
+    case value !== null && typeof value === 'object':
+      return Object.fromEntries(
+        Object.entries(value as Record<string, unknown>)
+          .map(([key, v]) => [key, handleFirestoreDataTypes(v)]),
+      ) as unknown as FirestoreToJs<T>
     default:
-      return value
+      return value as unknown as FirestoreToJs<T>
   }
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d982b06 and 05978e5.

📒 Files selected for processing (1)
  • packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (GEMINI.md)

Ensure all new code conforms to the project's ESLint and Prettier rules

Files:

  • packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
PR: valian-ca/react-firebase#0
File: packages/react-firestore/GEMINI.md:0-0
Timestamp: 2025-08-16T16:32:15.795Z
Learning: Applies to packages/react-firestore/**/*.{ts,tsx} : Ensure all code conforms to the project’s ESLint rules
📚 Learning: 2025-08-16T16:32:15.795Z
Learnt from: CR
PR: valian-ca/react-firebase#0
File: packages/react-firestore/GEMINI.md:0-0
Timestamp: 2025-08-16T16:32:15.795Z
Learning: Applies to packages/react-firestore/**/*.{ts,tsx} : Write all new code in TypeScript

Applied to files:

  • packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts
📚 Learning: 2025-08-16T16:32:27.169Z
Learnt from: CR
PR: valian-ca/react-firebase#0
File: packages/rxjs-firebase/GEMINI.md:0-0
Timestamp: 2025-08-16T16:32:27.169Z
Learning: Applies to packages/rxjs-firebase/**/*.ts : Implement library code in TypeScript

Applied to files:

  • packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts
📚 Learning: 2025-08-16T16:32:15.795Z
Learnt from: CR
PR: valian-ca/react-firebase#0
File: packages/react-firestore/GEMINI.md:0-0
Timestamp: 2025-08-16T16:32:15.795Z
Learning: Applies to packages/react-firestore/**/*.{ts,tsx} : Ensure all code conforms to the project’s ESLint rules

Applied to files:

  • packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts
🪛 ESLint
packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts

[error] 1-1: Filename is not in kebab case. Rename it to firestore-data-converter.ts.

(unicorn/filename-case)


[error] 1-1: Unable to resolve path to module '@firebase/firestore'.

(import-x/no-unresolved)


[error] 2-2: Unable to resolve path to module 'firebase/firestore'.

(import-x/no-unresolved)


[error] 2-2: Missing file extension for "firebase/firestore"

(import-x/extensions)

Comment thread packages/react-kitchen-sink/src/schema/firestoreDataConverter.ts
@Nr9 Nr9 merged commit a39095e into main Sep 5, 2025
7 checks passed
@Nr9 Nr9 deleted the chore/tsdown branch September 5, 2025 01:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant