@koolbase/react-native 11.4.0 → 12.0.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.
Files changed (2) hide show
  1. package/CHANGELOG.md +122 -0
  2. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -7,6 +7,128 @@ adheres to [Semantic Versioning][semver].
7
7
  [kac]: https://keepachangelog.com/en/1.1.0/
8
8
  [semver]: https://semver.org/
9
9
 
10
+ ## 12.0.0
11
+
12
+ ### Breaking
13
+
14
+ - **Fourteen error classes now report the code the server actually sends.**
15
+
16
+ `error.code` is a public field, and on these fourteen classes it carried a
17
+ value the Koolbase API has never emitted. Catching by type has always
18
+ worked and is unaffected — no class, constructor or export has changed.
19
+ Only the string in `code` moves.
20
+
21
+ If you compare `error.code` against a literal, update these comparisons.
22
+ If you assert on `code` in tests, or build fixtures from these values, the
23
+ same applies.
24
+
25
+ | Class | Was | Now |
26
+ |---|---|---|
27
+ | `EmailAlreadyInUseError` | `email_taken` | `email_in_use` |
28
+ | `UserDisabledError` | `user_disabled` | `account_disabled` |
29
+ | `SessionExpiredError` | `session_expired` | `invalid_refresh_token` |
30
+ | `UnlockTokenInvalidError` | `unlock_token_invalid` | `invalid_unlock_token` |
31
+ | `OtpRateLimitError` | `otp_rate_limit` | `rate_limit` |
32
+ | `PhoneAlreadyInUseError` | `phone_taken` | `phone_in_use` |
33
+ | `SmsConfigMissingError` | `sms_config_missing` | `sms_not_configured` |
34
+ | `AppleNotConfiguredError` | `apple_not_configured` | `oauth_not_configured` |
35
+ | `InvalidAppleTokenError` | `invalid_apple_token` | `invalid_oauth_token` |
36
+ | `AppleEmailRequiredError` | `apple_email_required` | `oauth_email_required` |
37
+ | `GoogleEmailRequiredError` | `google_email_required` | `oauth_email_required` |
38
+ | `GoogleNotConfiguredError` | `google_not_configured` | `oauth_not_configured` |
39
+ | `InvalidGoogleTokenError` | `invalid_google_token` | `invalid_oauth_token` |
40
+
41
+ The Apple and Google pairs are the clearest case: the SDK split them by
42
+ provider while the server has always sent one unified code for both.
43
+
44
+ Why this was invisible: the mapping tests checked which class a server code
45
+ produces, never what code that class reports. Both directions are now
46
+ asserted, so a class cannot report a code the API does not send.
47
+
48
+ **Nothing that worked before breaks in behaviour.** A comparison against
49
+ the old value could never have matched a real response — but it can match a
50
+ mock, which is why this is a major release rather than a patch.
51
+
52
+ ### Added
53
+
54
+ - **Account settings.** A web application could not offer one: these existed
55
+ on the server and in the Flutter SDK, and not here.
56
+
57
+ - `auth.getCurrentUser()` — the signed-in user, fetched fresh rather than
58
+ from the cached session, and persisted so `currentUser` stops being
59
+ stale.
60
+ - `auth.updateProfile({ fullName?, avatarUrl? })` — only the fields given
61
+ are sent, so passing one leaves the other untouched.
62
+ - `auth.changePassword({ currentPassword, newPassword })` — the current
63
+ password is required: a stolen session should not be enough to lock the
64
+ real owner out. A wrong one throws `CurrentPasswordIncorrectError`.
65
+ - `auth.deleteAccount()` — deletes the caller only; there is no user id to
66
+ pass, which is the security property. It does **not** delete the
67
+ account's records in your collections. Subscribe a Function to
68
+ `auth.user.deleted` and clean up there.
69
+
70
+ - **Session management.** Three endpoints had been live on the server the
71
+ whole time and no SDK exposed any of them.
72
+
73
+ - `auth.listSessions()` — where the user is signed in. Each entry carries
74
+ the device label, IP, user agent and timestamps, and `isCurrent` marks
75
+ this device. Token hashes are never included.
76
+ - `auth.revokeSession(id)` — sign one out. Revoking the current session
77
+ ends this one too; the next request's 401 clears it locally. A UI that
78
+ knows a row is current should call `logout()` instead.
79
+ - `auth.revokeAllOtherSessions()` — sign out every other device, keeping
80
+ this one, and return how many ended. What "sign out my other devices"
81
+ means after a lost phone.
82
+
83
+ - **`auth.auditLog({ limit?, offset? })`** — the account's own security
84
+ history, for a "recent activity" screen: sign-ins, failures, lockouts,
85
+ password changes, verification. The server sanitizes each event against a
86
+ per-type field allowlist, so an entry carries what its type may say and
87
+ nothing more. Returns a page with the total across all pages.
88
+
89
+ - **`db.aggregate(request)`** — count and total over a whole collection.
90
+
91
+ Not a paged query you add up in the client: the server aggregates the
92
+ entire authorized set with the read rule applied inside the query. And
93
+ never a bare number — collections are schemaless, so a sum that quietly
94
+ skipped three malformed rows would be a wrong number that looks right.
95
+ Every result carries its `accounting`: how many records contributed to each
96
+ measure, how many were skipped, and why.
97
+
98
+ ```ts
99
+ const r = await Koolbase.db.aggregate({
100
+ collection: 'orders',
101
+ groupBy: { field: 'created_at', bucket: 'month', timezone: 'Africa/Accra' },
102
+ measures: [{ aggregate: 'sum', field: 'total', as: 'revenue' }],
103
+ })
104
+
105
+ if (r.accounting.revenue.skipped > 0) {
106
+ // some orders had a total that was not a number — say so
107
+ }
108
+ ```
109
+
110
+ A calendar bucket requires a timezone and the types enforce it: midnight
111
+ means nothing without one, and Accra and UTC disagree about which day a
112
+ 23:30 sale belongs to.
113
+
114
+ ### Changed
115
+
116
+ - **`x-koolbase-platform-version` falls back to `unknown`** rather than being
117
+ sent empty. The browser version is read from the user agent, which
118
+ recognises Chrome, Firefox, Safari and Edge — so Brave, Opera, Samsung
119
+ Internet and in-app webviews reported nothing. An empty header stored
120
+ against a session is indistinguishable from an SDK that never reported
121
+ itself; `unknown` says the SDK spoke and could not identify the host.
122
+
123
+ ### Fixed
124
+
125
+ - The six `x-koolbase-*` identity headers are now pinned by a test against
126
+ the set the API allows. They are sent on every request, and a browser
127
+ refuses a request whose preflight does not list them — which is how every
128
+ authenticated call from `@koolbase/js` came to be blocked on 18 September.
129
+ The API derives its CORS allowance from one declaration now, and this test
130
+ is the other end of that contract.
131
+
10
132
  ## 11.4.0
11
133
 
12
134
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koolbase/react-native",
3
- "version": "11.4.0",
3
+ "version": "12.0.0",
4
4
  "description": "React Native SDK for Koolbase \u2014 auth, database, storage, realtime, feature flags, and functions in one package.",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "types": "./dist/esm/index.d.ts",
@@ -24,7 +24,7 @@
24
24
  "url": "https://github.com/koolbase/koolbase-react-native"
25
25
  },
26
26
  "dependencies": {
27
- "@koolbase/core": "11.4.0"
27
+ "@koolbase/core": "12.0.0"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "@react-native-async-storage/async-storage": "^3.0.2",