@norbix.ai/react-redux 0.1.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -0
- package/dist/index.cjs +52 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -12
- package/dist/index.d.ts +31 -12
- package/dist/index.js +52 -6
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -150,6 +150,7 @@ A *curated* set of hooks for the most common endpoints. Every hook is end-to-end
|
|
|
150
150
|
| `useGetApiKeysQuery` | `api.apikeys.getApiKeys` | provides `ApiKey/LIST` |
|
|
151
151
|
| `useRegenerateApiKeysMutation` | `api.apikeys.regenerateApiKeys` | invalidates `ApiKey/LIST` |
|
|
152
152
|
| `useGetPublicFileQuery` | `api.files.getPublicFile` | provides `Files/PUBLIC:<publicId>` |
|
|
153
|
+
| `useTestFilesIntegrationApiMutation` | `api.files.testFilesIntegration` | invalidates `Files` + `FilesIntegrations` |
|
|
153
154
|
|
|
154
155
|
### Hub surface — `norbix.hub.*`
|
|
155
156
|
|
|
@@ -213,6 +214,31 @@ on the page. `useGetPublicFileQuery` caches under its own
|
|
|
213
214
|
making a file private again invalidates `Files`, a different tag, so call
|
|
214
215
|
`refetch()` if a stale entry would matter to you.
|
|
215
216
|
|
|
217
|
+
## Testing a files integration
|
|
218
|
+
|
|
219
|
+
Two hooks run the same live probe against a files integration — upload a
|
|
220
|
+
small file, read it, list the folder, delete the file — and answer one item
|
|
221
|
+
per step (`UploadFile`, `GetFile`, `GetAllFiles`, `DeleteFile`) with `result`
|
|
222
|
+
`OK`, `FAILED` or `NOT_TESTED`:
|
|
223
|
+
|
|
224
|
+
| Hook | Wraps | Route | Use it from |
|
|
225
|
+
|---|---|---|---|
|
|
226
|
+
| `useTestFilesIntegrationApiMutation` | `api.files.testFilesIntegration` | `POST /{version}/files/{filesIntegrationId}/test` | your app, with an API key or a user session (needs `files:create`) |
|
|
227
|
+
| `useTestFilesIntegrationMutation` | `hub.files.testFilesIntegration` | `POST /{version}/files/integrations/test` | a dashboard, signed in to the Hub |
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
const [testIntegration, { data, isLoading }] = useTestFilesIntegrationApiMutation();
|
|
231
|
+
|
|
232
|
+
await testIntegration({ filesIntegrationId: 'nbin_1' });
|
|
233
|
+
const failed = data?.items?.filter((i) => i.result !== 'OK');
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
The API one carries the `Api` suffix because both live in one endpoint map
|
|
237
|
+
(like `useDeleteFileApiMutation`). It invalidates `Files` — the probe writes to
|
|
238
|
+
the storage, and a failed delete step leaves its file behind — and
|
|
239
|
+
`FilesIntegrations`, because the gateway records the last test result on the
|
|
240
|
+
integration.
|
|
241
|
+
|
|
216
242
|
## Working with terms
|
|
217
243
|
|
|
218
244
|
A **taxonomy** is a named tree of **terms** (labels). A term can have one parent (a clean hierarchy) or several parents (the same item under many categories). There is one read hook per scenario — pick the one that matches what you want:
|
|
@@ -782,6 +808,37 @@ If your app currently calls Norbix via `fetchBaseQuery({ baseUrl })` + a custom
|
|
|
782
808
|
4. **Remove** the custom error interceptor — `createNorbixBaseQuery` already maps `NorbixError` to `SerializedNorbixError` with `code`, `status`, `message`, `fieldErrors`. Consume those in your error UI instead.
|
|
783
809
|
5. **Keep** the same tag taxonomy — the package exports the full set (`Account`, `Projects`, `Regions`, `MembershipUsers`, `DatabaseSchemas`, ... 59 in total), so existing `providesTags` keep working.
|
|
784
810
|
|
|
811
|
+
## Errors
|
|
812
|
+
|
|
813
|
+
A failed call lands in the Redux state as a plain `SerializedNorbixError`:
|
|
814
|
+
|
|
815
|
+
```ts
|
|
816
|
+
const { error } = useGetFileInfoQuery({ filesIntegrationId, path });
|
|
817
|
+
if (error) {
|
|
818
|
+
// httpStatus / errorCode / errors are the names every Norbix SDK uses.
|
|
819
|
+
// status / code / fieldErrors are the same values, kept for older code.
|
|
820
|
+
console.log(error.httpStatus, error.errorCode, error.message);
|
|
821
|
+
error.errors.forEach((e) => console.log(e.errorCode, e.fieldName, e.message));
|
|
822
|
+
}
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
The message and the error code are the gateway's own. `@norbix.ai/ts` reads
|
|
826
|
+
them out of `responseStatus.errors[]`, where the gateway puts them, and this
|
|
827
|
+
package copies them into the store unchanged — it does not parse bodies
|
|
828
|
+
itself.
|
|
829
|
+
|
|
830
|
+
### Breaking change — a refused call now lands as an error
|
|
831
|
+
|
|
832
|
+
The gateway answers a business refusal (an unknown id, a rule that says no)
|
|
833
|
+
with **HTTP 200** and `responseStatus.isSuccess = false`. Until now such an
|
|
834
|
+
answer arrived as `{ data }` and your components rendered it as a success.
|
|
835
|
+
With the fixed `@norbix.ai/ts` it arrives as `{ error }` with `httpStatus` 200
|
|
836
|
+
and the gateway's message and error code.
|
|
837
|
+
|
|
838
|
+
If a component checked `data.responseStatus.isSuccess` itself, read `error`
|
|
839
|
+
instead. This needs `@norbix.ai/ts` **2.0.0 or newer** — the version that
|
|
840
|
+
carries the fix.
|
|
841
|
+
|
|
785
842
|
## How it works under the hood
|
|
786
843
|
|
|
787
844
|
`createNorbixApi(getClient)` returns an RTK Query API. Its `baseQuery` is a thin wrapper that calls a closure you pass at endpoint definition time:
|
package/dist/index.cjs
CHANGED
|
@@ -10,18 +10,27 @@ var jsxRuntime = require('react/jsx-runtime');
|
|
|
10
10
|
function serializeNorbixError(err) {
|
|
11
11
|
if (err && typeof err === "object") {
|
|
12
12
|
const e = err;
|
|
13
|
+
const status = typeof e.status === "number" ? e.status : typeof e.httpStatus === "number" ? e.httpStatus : 0;
|
|
14
|
+
const code = e.code ?? e.errorCode;
|
|
15
|
+
const list = Array.isArray(e.fieldErrors) ? e.fieldErrors : Array.isArray(e.errors) ? e.errors : [];
|
|
13
16
|
return {
|
|
14
|
-
status
|
|
15
|
-
|
|
17
|
+
status,
|
|
18
|
+
httpStatus: status,
|
|
19
|
+
code,
|
|
20
|
+
errorCode: code,
|
|
16
21
|
message: e.message ?? "Unknown Norbix error",
|
|
17
|
-
fieldErrors:
|
|
22
|
+
fieldErrors: list,
|
|
23
|
+
errors: list,
|
|
18
24
|
url: e.url
|
|
19
25
|
};
|
|
20
26
|
}
|
|
27
|
+
const message = typeof err === "string" ? err : "Unknown Norbix error";
|
|
21
28
|
return {
|
|
22
29
|
status: 0,
|
|
23
|
-
|
|
24
|
-
|
|
30
|
+
httpStatus: 0,
|
|
31
|
+
message,
|
|
32
|
+
fieldErrors: [],
|
|
33
|
+
errors: []
|
|
25
34
|
};
|
|
26
35
|
}
|
|
27
36
|
|
|
@@ -38,9 +47,12 @@ function createNorbixBaseQuery(getClient) {
|
|
|
38
47
|
return {
|
|
39
48
|
error: {
|
|
40
49
|
status: 0,
|
|
50
|
+
httpStatus: 0,
|
|
41
51
|
code: "NORBIX_NO_CLIENT",
|
|
52
|
+
errorCode: "NORBIX_NO_CLIENT",
|
|
42
53
|
message: "No Norbix client available. Did you forget <NorbixProvider>?",
|
|
43
|
-
fieldErrors: []
|
|
54
|
+
fieldErrors: [],
|
|
55
|
+
errors: []
|
|
44
56
|
}
|
|
45
57
|
};
|
|
46
58
|
}
|
|
@@ -276,6 +288,36 @@ var apiFiles = (b) => ({
|
|
|
276
288
|
providesTags: (_res, _err, arg) => [
|
|
277
289
|
{ type: "Files", id: `PUBLIC:${arg?.publicId ?? "unknown"}` }
|
|
278
290
|
]
|
|
291
|
+
}),
|
|
292
|
+
/**
|
|
293
|
+
* Runs a live probe against a files integration with the caller's own API
|
|
294
|
+
* key or session: uploads a small file, reads it, lists the folder and
|
|
295
|
+
* deletes the file again. Answers one item per step (`UploadFile`,
|
|
296
|
+
* `GetFile`, `GetAllFiles`, `DeleteFile`) with `result` `OK`, `FAILED` or
|
|
297
|
+
* `NOT_TESTED`, plus the step's `errors`. Needs the `files:create`
|
|
298
|
+
* permission, because the probe writes to the storage.
|
|
299
|
+
*
|
|
300
|
+
* Wraps `api.files.testFilesIntegration`
|
|
301
|
+
* (`POST /{version}/files/{filesIntegrationId}/test`). This is NOT the
|
|
302
|
+
* dashboard endpoint `hub.files.testFilesIntegration`
|
|
303
|
+
* (`POST /{version}/files/integrations/test`), whose hook is
|
|
304
|
+
* `useTestFilesIntegrationMutation`. Both live in one flat endpoint map,
|
|
305
|
+
* so this one carries the `Api` suffix — the same way `deleteFileApi` and
|
|
306
|
+
* `downloadFileApi` do — otherwise the Hub one, spread later, would
|
|
307
|
+
* silently replace it. Hook: `useTestFilesIntegrationApiMutation`.
|
|
308
|
+
*
|
|
309
|
+
* A mutation, like every other write in this file, so its answer is never
|
|
310
|
+
* served from cache. It invalidates:
|
|
311
|
+
* - `Files`, like its write neighbours: the probe uploads and deletes a
|
|
312
|
+
* real file in the storage `listFiles` reads, and if the delete step
|
|
313
|
+
* fails the probe file stays behind;
|
|
314
|
+
* - `FilesIntegrations`: the gateway records the outcome on the
|
|
315
|
+
* integration (last test time, success, errors), which
|
|
316
|
+
* `getFilesIntegration(s)` return.
|
|
317
|
+
*/
|
|
318
|
+
testFilesIntegrationApi: b.mutation({
|
|
319
|
+
query: (args) => (norbix) => norbix.api.files.testFilesIntegration(args),
|
|
320
|
+
invalidatesTags: ["Files", "FilesIntegrations"]
|
|
279
321
|
})
|
|
280
322
|
});
|
|
281
323
|
|
|
@@ -1589,6 +1631,10 @@ var hubNotifications = (b) => ({
|
|
|
1589
1631
|
query: (args) => (norbix) => norbix.hub.notifications.getPushCampaignStatistics(args),
|
|
1590
1632
|
providesTags: ["PushCampaigns"]
|
|
1591
1633
|
}),
|
|
1634
|
+
previewPushNotification: b.query({
|
|
1635
|
+
query: (args) => (norbix) => norbix.hub.notifications.previewPushNotification(args),
|
|
1636
|
+
providesTags: ["Push"]
|
|
1637
|
+
}),
|
|
1592
1638
|
getPushCampaignMessage: b.query({
|
|
1593
1639
|
query: (args) => (norbix) => norbix.hub.notifications.getPushCampaignMessage(args),
|
|
1594
1640
|
providesTags: ["PushCampaigns"]
|