diff --git a/README.md b/README.md index 026e5ce..cd169d3 100644 --- a/README.md +++ b/README.md @@ -238,6 +238,17 @@ The module enable / disable hooks were always mutations, so nothing changes in y The gateway still answers the old `GET` on these paths for now (it logs a deprecation warning) and will drop it after gateway 0.2, so upgrade the core SDK before then. The scheduler switch moved to `PUT` earlier (core SDK 4.6.0). The code module (`hub.code`) has no hooks in this package yet; call `useNorbix().hub.code.enableCode(...)` directly. +### Bulk record writes (core SDK 4.11.0) + +`useUpdateManyRecordsMutation` / `useDeleteManyRecordsMutation` (Hub) and `useUpdateManyMutation` / `useDeleteManyMutation` (Api) take a new optional `allRecords` argument. An empty filter (`{}`, or no filter on update) matches the whole collection and the gateway refuses it with `CM-ERRORS-DATABASE-037` unless you pass `allRecords: true`: + +```ts +const [deleteMany] = useDeleteManyRecordsMutation(); +await deleteMany({ collectionName: 'orders', filter: '{}', allRecords: true }); +``` + +Other gateway rules that now show up as errors from these hooks: an update body with `$` operators (`$inc`, `$set`, …) is refused with `CM-ERRORS-DATABASE-035` (send the plain fields to set); a broken insert or replace document answers `CM-ERRORS-DATABASE-036`; soft-deleted records are "not found" for update, replace and change-owner, and a bulk update skips them. A caller with only own-record rights may now use the bulk hooks; they touch only that caller's records. + ### Schemas per environment `useGetDatabaseSchemasQuery` returns only the schemas of the environment the request targets: the `env` argument, or else the client's environment (`norbix.setEnvironment(...)`, sent as the `norbix-env` header), or `PROD` when neither is set. Each row carries `env`. The schema list settings (`useGetDatabaseSchemaListSettingsQuery` / `useUpdateDatabaseSchemaListSettingsMutation`) are stored per environment too. diff --git a/docs/tasks/database-last-wave.md b/docs/tasks/database-last-wave.md new file mode 100644 index 0000000..28a0153 --- /dev/null +++ b/docs/tasks/database-last-wave.md @@ -0,0 +1,39 @@ +# Database last wave — react-redux on @norbix.ai/ts 4.11.0 + +## Goal + +Move `@norbix.ai/react-redux` onto `@norbix.ai/ts` 4.11.0, the core SDK release that follows the last gateway Database wave. + +Not in scope: new hooks (4.11.0 adds no SDK method), the follow-up aggregate field `JoinedCollections` (not in any SDK yet). + +## Plan + +1. chore(deps): require @norbix.ai/ts 4.11.0 — done, `package.json`, `package-lock.json` +2. test(database): `allRecords` reaches the wire for update many / delete many — done, `tests/database.test.ts` +3. docs(readme): bulk record writes, `allRecords` and the new database errors — done, `README.md` +4. chore(hooks): regenerate hooks — dropped: no hook generator exists in this repo, and 4.11.0 has the same method list as 4.10.0 (compared the `.d.ts` method names of both npm packages), so no hook is added or removed. The hook-per-SDK-method guards (`has one hook per hub.database method …`, `reaches every api.database method …`) pass. + +## Changes + +| file | what changed | plan step # | +| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | +| `package.json`, `package-lock.json` | `@norbix.ai/ts` peer `>=4.11.0`, dev `^4.11.0` | 1 | +| `tests/database.test.ts` | two real-SDK tests: `updateManyRecords` sends `PUT …/orders/many` with `allRecords: true`; `deleteManyRecords` sends `DELETE …/orders/many` with `allRecords` | 2 | +| `README.md` | "Bulk record writes (core SDK 4.11.0)" section | 3 | + +## Findings + +- What 4.11.0 changes for this package: types only. New `allRecords?: boolean` on the update-many / delete-many requests (Hub and Api); `TaxonomyListProjection.dependencyRefs` (a `TaxonomyRef { id, name? }` list) replaces `dependencyNames`; trigger rows carry `env`; `RenameDatabaseSchemaRequest.renameUniqueName` removed. No hook or test here used the removed fields. Left as is. +- `npx prettier --check .` reports 20 files with style issues that are already on `main` (docs, examples, `tests/provider.test.tsx`). Not touched here; left open. + +## Rejected / moved out + +- None. + +## Needs you + +- Nothing. + +## Open questions + +- None. diff --git a/package-lock.json b/package-lock.json index a13eec4..aaaefad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@commitlint/cli": "^21.2.2", "@commitlint/config-conventional": "^21.2.2", "@eslint/js": "^10.0.1", - "@norbix.ai/ts": "^4.10.0", + "@norbix.ai/ts": "^4.11.0", "@reduxjs/toolkit": "^2.12.0", "@semantic-release/commit-analyzer": "^13.0.1", "@semantic-release/github": "^12.0.9", @@ -45,7 +45,7 @@ "node": ">=18" }, "peerDependencies": { - "@norbix.ai/ts": ">=4.10.0", + "@norbix.ai/ts": ">=4.11.0", "@reduxjs/toolkit": ">=2.0.0", "react": ">=18.0.0", "react-redux": ">=9.0.0" @@ -1490,9 +1490,9 @@ } }, "node_modules/@norbix.ai/ts": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@norbix.ai/ts/-/ts-4.10.0.tgz", - "integrity": "sha512-yGKbR9nwbt7jEB06Qdzg0HzEXqwzKsfU9h+wB4c03Il8qFH/7Gi2zkcMLCmSATcenho809MjZLuo4DPGXiH+aA==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@norbix.ai/ts/-/ts-4.11.0.tgz", + "integrity": "sha512-Amrs58kmKBnegPCNdrYtiHaCwRnx9hN+JHS+qneLRAzmQuJ86evMDohn13qs+YwBgvvhOkwEb76opcs31y3Isg==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 2c5e9e6..31e28e9 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "prepublishOnly": "npm run build" }, "peerDependencies": { - "@norbix.ai/ts": ">=4.10.0", + "@norbix.ai/ts": ">=4.11.0", "@reduxjs/toolkit": ">=2.0.0", "react": ">=18.0.0", "react-redux": ">=9.0.0" @@ -68,7 +68,7 @@ "@commitlint/cli": "^21.2.2", "@commitlint/config-conventional": "^21.2.2", "@eslint/js": "^10.0.1", - "@norbix.ai/ts": "^4.10.0", + "@norbix.ai/ts": "^4.11.0", "@reduxjs/toolkit": "^2.12.0", "@semantic-release/commit-analyzer": "^13.0.1", "@semantic-release/github": "^12.0.9", diff --git a/tests/database.test.ts b/tests/database.test.ts index f2235bf..bba1304 100644 --- a/tests/database.test.ts +++ b/tests/database.test.ts @@ -341,6 +341,40 @@ describe('hub records through the real SDK (fake fetch)', () => { expect(out.data?.result).toBe('r2'); }); + it('updateManyRecords sends PUT /many with allRecords for an empty filter', async () => { + const { seen, result } = run( + 'updateManyRecords', + { collectionName: 'orders', filter: '{}', update: '{"status":"archived"}', allRecords: true }, + 200, + { result: { matchedCount: 3, modifiedCount: 3 } }, + ); + + const out = (await result) as { error?: unknown }; + + expect(out.error).toBeUndefined(); + expect(seen[0].method).toBe('PUT'); + expect(seen[0].url).toBe('https://hub.norbix.io/v2/database/collections/orders/many'); + expect(seen[0].body).toMatchObject({ filter: '{}', allRecords: true }); + }); + + it('deleteManyRecords sends DELETE /many with allRecords for an empty filter', async () => { + const { seen, result } = run( + 'deleteManyRecords', + { collectionName: 'orders', filter: '{}', allRecords: true }, + 200, + { result: { deletedCount: 3 } }, + ); + + const out = (await result) as { error?: unknown }; + + expect(out.error).toBeUndefined(); + expect(seen[0].method).toBe('DELETE'); + const url = new globalThis.URL(seen[0].url); + expect(url.pathname).toBe('/v2/database/collections/orders/many'); + const sent = { ...Object.fromEntries(url.searchParams), ...(seen[0].body as object) }; + expect(String(sent.allRecords)).toBe('true'); + }); + it('a gateway error ResponseStatus comes back as the usual serialized error', async () => { const { result } = run('findRecords', { collectionName: 'orders' }, 403, { responseStatus: { errorCode: 'Forbidden', message: 'Missing permission database:read' },