From 265bf4baefab0af05b085c861163c5bd2ff16d1b Mon Sep 17 00:00:00 2001 From: XueYuSky Date: Thu, 14 May 2026 10:53:13 +0800 Subject: [PATCH 1/8] feat(db): add clearAll collection helper --- .changeset/clear-all-db-adapter.md | 5 +++++ packages/db/src/db-client.ts | 15 +++++++++++++++ tests/unit/db.test.ts | 24 ++++++++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 .changeset/clear-all-db-adapter.md diff --git a/.changeset/clear-all-db-adapter.md b/.changeset/clear-all-db-adapter.md new file mode 100644 index 00000000..5f8db005 --- /dev/null +++ b/.changeset/clear-all-db-adapter.md @@ -0,0 +1,5 @@ +--- +"zerithdb-db": patch +--- + +Add a `clearAll()` helper to remove every document from a collection. diff --git a/packages/db/src/db-client.ts b/packages/db/src/db-client.ts index 2e3ef051..9d247dfb 100644 --- a/packages/db/src/db-client.ts +++ b/packages/db/src/db-client.ts @@ -152,6 +152,21 @@ export class CollectionClient = Record { + try { + await this.table.clear(); + } catch (err) { + throw new ZerithDBError( + ErrorCode.DB_DELETE_FAILED, + `Failed to clear collection "${this.collectionName}"`, + { cause: err } + ); + } + } + /** * Count documents matching a filter. */ diff --git a/tests/unit/db.test.ts b/tests/unit/db.test.ts index 7ca10ee2..d392aa3a 100644 --- a/tests/unit/db.test.ts +++ b/tests/unit/db.test.ts @@ -142,6 +142,30 @@ describe("DbClient — CollectionClient", () => { }); }); + describe("clearAll()", () => { + it("should remove every document in the collection", async () => { + const col = db.collection<{ done: boolean }>("tasks"); + await col.insertMany([{ done: true }, { done: false }, { done: true }]); + + await col.clearAll(); + + expect(await col.find({})).toHaveLength(0); + expect(await col.count()).toBe(0); + }); + + it("should not clear other collections", async () => { + const tasks = db.collection<{ done: boolean }>("tasks"); + const notes = db.collection<{ text: string }>("notes"); + await tasks.insertMany([{ done: true }, { done: false }]); + await notes.insert({ text: "keep me" }); + + await tasks.clearAll(); + + expect(await tasks.count()).toBe(0); + expect(await notes.count()).toBe(1); + }); + }); + describe("count()", () => { it("should return correct document count", async () => { const col = db.collection<{ x: number }>("counts"); From 82e285b93a48d9fa13ff2576d6dc614b66886cbf Mon Sep 17 00:00:00 2001 From: arpittkhandelwal Date: Thu, 14 May 2026 19:23:37 +0530 Subject: [PATCH 2/8] feat: add PR welcome bot workflow --- .github/workflows/pr-welcome.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/pr-welcome.yml diff --git a/.github/workflows/pr-welcome.yml b/.github/workflows/pr-welcome.yml new file mode 100644 index 00000000..8e698a7d --- /dev/null +++ b/.github/workflows/pr-welcome.yml @@ -0,0 +1,30 @@ +name: PR Welcome Bot + +on: + pull_request_target: + types: [opened] + +jobs: + welcome-comment: + name: Post Welcome Comment + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Welcome Comment + uses: actions/github-script@v7 + with: + script: | + const creator = context.payload.pull_request.user.login; + const message = `### 👋 Hello @${creator}! + +Our reviewers will be checking your PR shortly. In the meantime, please join our Discord server to connect with the team and other contributors: + +🚀 **Join Discord:** https://discord.gg/mwCayEMK4h`; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + body: message + }); From 4bc897b90e8e3aa28da48bd43af8d23715662b89 Mon Sep 17 00:00:00 2001 From: arpittkhandelwal Date: Thu, 14 May 2026 19:23:37 +0530 Subject: [PATCH 3/8] fix: add issues: write permission for welcome bot --- .github/workflows/pr-welcome.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr-welcome.yml b/.github/workflows/pr-welcome.yml index 8e698a7d..7585bcb3 100644 --- a/.github/workflows/pr-welcome.yml +++ b/.github/workflows/pr-welcome.yml @@ -10,6 +10,7 @@ jobs: runs-on: ubuntu-latest permissions: pull-requests: write + issues: write steps: - name: Welcome Comment uses: actions/github-script@v7 From b5d77383d660a1248a5761e530c0c18f41419c74 Mon Sep 17 00:00:00 2001 From: arpittkhandelwal Date: Thu, 14 May 2026 19:30:26 +0530 Subject: [PATCH 4/8] fix: resolve YAML syntax error in welcome bot --- .github/workflows/pr-welcome.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-welcome.yml b/.github/workflows/pr-welcome.yml index 7585bcb3..8c8aa46e 100644 --- a/.github/workflows/pr-welcome.yml +++ b/.github/workflows/pr-welcome.yml @@ -17,12 +17,12 @@ jobs: with: script: | const creator = context.payload.pull_request.user.login; - const message = `### 👋 Hello @${creator}! + const message = `### 👋 Hello @${creator}! Our reviewers will be checking your PR shortly. In the meantime, please join our Discord server to connect with the team and other contributors: 🚀 **Join Discord:** https://discord.gg/mwCayEMK4h`; - + await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, From c447c11368475123bf7d42955c858694208878cd Mon Sep 17 00:00:00 2001 From: arpittkhandelwal Date: Thu, 14 May 2026 19:35:36 +0530 Subject: [PATCH 5/8] fix: remove emojis and simplify string to fix YAML syntax error --- .github/workflows/pr-welcome.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/pr-welcome.yml b/.github/workflows/pr-welcome.yml index 8c8aa46e..f6d10534 100644 --- a/.github/workflows/pr-welcome.yml +++ b/.github/workflows/pr-welcome.yml @@ -17,11 +17,7 @@ jobs: with: script: | const creator = context.payload.pull_request.user.login; - const message = `### 👋 Hello @${creator}! - -Our reviewers will be checking your PR shortly. In the meantime, please join our Discord server to connect with the team and other contributors: - -🚀 **Join Discord:** https://discord.gg/mwCayEMK4h`; + const message = "### Hello @" + creator + "!\n\nOur reviewers will be checking your PR shortly. In the meantime, please join our Discord server to connect with the team and other contributors:\n\n**Join Discord:** https://discord.gg/mwCayEMK4h"; await github.rest.issues.createComment({ owner: context.repo.owner, From 68107958e85c0a0956c2cd5cc9f57cb93d087dd5 Mon Sep 17 00:00:00 2001 From: arpittkhandelwal Date: Thu, 14 May 2026 19:36:14 +0530 Subject: [PATCH 6/8] chore: test commit for welcome bot --- bot-test.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 bot-test.txt diff --git a/bot-test.txt b/bot-test.txt new file mode 100644 index 00000000..e69de29b From 5403a47738af6248b528f48f57ce4edc110729a3 Mon Sep 17 00:00:00 2001 From: Arpit Khandelwal <71580150+arpittkhandelwal@users.noreply.github.com> Date: Thu, 14 May 2026 23:48:37 +0530 Subject: [PATCH 7/8] Delete .github/ISSUE_TEMPLATE/bug_report.yml --- .github/ISSUE_TEMPLATE/bug_report.yml | 38 --------------------------- 1 file changed, 38 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml deleted file mode 100644 index 16c679fd..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ /dev/null @@ -1,38 +0,0 @@ ---- -name: "🐛 Bug Report" -about: "Something isn't working as expected" -labels: ["bug", "needs-investigation"] ---- - -## Description - - - -## Steps to Reproduce - -1. -2. -3. - -## Expected Behavior - - - -## Actual Behavior - - - -## Environment - -- ZerithDB version: -- Browser + version: -- OS: -- Package(s) affected: `@zerithdb/` - -## Reproduction - - - -## Additional Context - - From 5d51df4116aec5f04c92f0c30127f2dfd4a21c80 Mon Sep 17 00:00:00 2001 From: Gowtham sree charan reddy Date: Fri, 29 May 2026 15:19:38 +0530 Subject: [PATCH 8/8] fix(db): support $unset operator in update operations --- .changeset/support-unset-operator.md | 5 ++++ packages/db/src/db-client.ts | 39 ++++++++++++++++++---------- tests/unit/db.test.ts | 15 ++++++++++- 3 files changed, 44 insertions(+), 15 deletions(-) create mode 100644 .changeset/support-unset-operator.md diff --git a/.changeset/support-unset-operator.md b/.changeset/support-unset-operator.md new file mode 100644 index 00000000..42f4febb --- /dev/null +++ b/.changeset/support-unset-operator.md @@ -0,0 +1,5 @@ +--- +"zerithdb-db": patch +--- + +Add complete support for the `$unset` operator in database update operations to allow deleting fields from documents. diff --git a/packages/db/src/db-client.ts b/packages/db/src/db-client.ts index 9d247dfb..2529cedd 100644 --- a/packages/db/src/db-client.ts +++ b/packages/db/src/db-client.ts @@ -15,10 +15,14 @@ import { ZerithDBError, ErrorCode } from "zerithdb-core"; */ export class CollectionClient = Record> { constructor( - private readonly table: Table>, + private readonly db: Dexie, private readonly collectionName: string ) {} + private get table(): Table> { + return this.db.table(this.collectionName) as Table>; + } + /** * Insert a new document into the collection. * Automatically assigns `_id`, `_createdAt`, and `_updatedAt`. @@ -117,11 +121,21 @@ export class CollectionClient = Record ({ - ...doc, - ...(spec.$set ?? {}), - _updatedAt: now, - })) + matches.map((doc) => { + const newDoc = { ...doc }; + if (spec.$set) { + Object.assign(newDoc, spec.$set); + } + if (spec.$unset) { + for (const key of Object.keys(spec.$unset)) { + delete (newDoc as Record)[key]; + } + } + return { + ...newDoc, + _updatedAt: now, + }; + }) ); return matches.length; @@ -200,6 +214,7 @@ export class CollectionClient = Record(); + private readonly currentSchema: Record = {}; constructor(appId: string) { super(`zerithdb_${appId}`); @@ -209,12 +224,8 @@ class ZerithDBDexie extends Dexie { if (!this.tableMap.has(name)) { // Dexie requires version upgrade to add tables — we use a dynamic schema pattern const version = (this.verno ?? 0) + 1; - const existingTableNames = this.tableMap.keys(); - const schema: Record = { [name]: "_id, _createdAt, _updatedAt" }; - for (const existingName of existingTableNames) { - schema[existingName] = "_id, _createdAt, _updatedAt"; - } - this.version(version).stores(schema); + this.currentSchema[name] = "_id, _createdAt, _updatedAt"; + this.version(version).stores(this.currentSchema); this.tableMap.set(name, this.table(name)); } // biome-ignore lint: map guarantees this is defined @@ -237,8 +248,8 @@ export class DbClient { collection>(name: string): CollectionClient { if (!this.collections.has(name)) { - const table = this.dexie.ensureCollection(name); - this.collections.set(name, new CollectionClient(table as Table>, name)); + this.dexie.ensureCollection(name); + this.collections.set(name, new CollectionClient(this.dexie, name)); } return this.collections.get(name) as CollectionClient; } diff --git a/tests/unit/db.test.ts b/tests/unit/db.test.ts index d392aa3a..e15247ac 100644 --- a/tests/unit/db.test.ts +++ b/tests/unit/db.test.ts @@ -4,13 +4,14 @@ import { DbClient } from "../../packages/db/src/db-client.js"; import type { ZerithDBConfig } from "../../packages/core/src/index.js"; const testConfig: ZerithDBConfig = { - appId: "test-db-" + Math.random().toString(36).slice(2), + appId: "test-db", }; describe("DbClient — CollectionClient", () => { let db: DbClient; beforeEach(() => { + testConfig.appId = "test-db-" + Math.random().toString(36).slice(2); db = new DbClient(testConfig); }); @@ -129,6 +130,18 @@ describe("DbClient — CollectionClient", () => { const after = (await col.findById(id))?._updatedAt ?? 0; expect(after).toBeGreaterThanOrEqual(before); }); + + it("should support $unset operator to remove fields", async () => { + const col = db.collection<{ text: string; category?: string }>("unset_test"); + const { id } = await col.insert({ text: "do homework", category: "school" }); + + const count = await col.update({ _id: id } as never, { $unset: { category: true } }); + expect(count).toBe(1); + + const doc = await col.findById(id); + expect(doc?.text).toBe("do homework"); + expect(doc?.category).toBeUndefined(); + }); }); describe("delete()", () => {