@koolbase/react-native 12.3.0 → 12.5.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/dist/cjs/index.d.ts +11 -0
- package/dist/cjs/index.js +17 -3
- package/dist/cjs/use-collection.d.ts +12 -0
- package/dist/cjs/use-collection.js +39 -0
- package/dist/esm/index.d.ts +11 -0
- package/dist/esm/index.js +17 -3
- package/dist/esm/use-collection.d.ts +12 -0
- package/dist/esm/use-collection.js +36 -0
- package/package.json +4 -3
package/dist/cjs/index.d.ts
CHANGED
|
@@ -18,3 +18,14 @@ export declare const Koolbase: {
|
|
|
18
18
|
checkVersion(currentVersion: string): VersionCheckResult;
|
|
19
19
|
};
|
|
20
20
|
export { SecureAuthStorage } from './auth-storage.js';
|
|
21
|
+
export type { UseCollectionResult } from './use-collection.js';
|
|
22
|
+
/**
|
|
23
|
+
* A collection as React state: loading, loaded or error, with refresh and
|
|
24
|
+
* loadMore. Equality filters only for now: `where: { field: value }`.
|
|
25
|
+
* Use it after Koolbase.initialize() (in an exported app, inside KoolbaseRoot).
|
|
26
|
+
*
|
|
27
|
+
* ```tsx
|
|
28
|
+
* const songs = useCollection('songs', { where: { genre: 'jazz' }, orderBy: 'title' });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare const useCollection: (collection: string, query?: import("@koolbase/core").CollectionQuery) => import("./use-collection.js").UseCollectionResult;
|
package/dist/cjs/index.js
CHANGED
|
@@ -20,12 +20,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
20
20
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
21
|
};
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
-
exports.SecureAuthStorage = exports.Koolbase = exports.reactNativePlatform = void 0;
|
|
23
|
+
exports.useCollection = exports.SecureAuthStorage = exports.Koolbase = exports.reactNativePlatform = void 0;
|
|
24
24
|
__exportStar(require("@koolbase/core"), exports);
|
|
25
25
|
var platform_js_1 = require("./platform.js");
|
|
26
26
|
Object.defineProperty(exports, "reactNativePlatform", { enumerable: true, get: function () { return platform_js_1.reactNativePlatform; } });
|
|
27
27
|
const core_1 = require("@koolbase/core");
|
|
28
28
|
const platform_js_2 = require("./platform.js");
|
|
29
|
+
const use_collection_js_1 = require("./use-collection.js");
|
|
29
30
|
let _auth = null;
|
|
30
31
|
let _db = null;
|
|
31
32
|
let _storage = null;
|
|
@@ -34,6 +35,8 @@ let _realtime = null;
|
|
|
34
35
|
let _functions = null;
|
|
35
36
|
let _flags = null;
|
|
36
37
|
let _analytics = null;
|
|
38
|
+
// While analytics is off, calls are harmless no-ops rather than a crash.
|
|
39
|
+
const analyticsOff = (0, core_1.disabledAnalytics)();
|
|
37
40
|
let _messaging = null;
|
|
38
41
|
let _initialized = false;
|
|
39
42
|
// The in-flight initialize, so overlapping callers await the same one.
|
|
@@ -75,7 +78,8 @@ exports.Koolbase = {
|
|
|
75
78
|
const deviceId = await (0, core_1.getOrCreateDeviceId)();
|
|
76
79
|
_flags = new core_1.KoolbaseFlags(config, deviceId);
|
|
77
80
|
// Initialize analytics
|
|
78
|
-
|
|
81
|
+
// Opt-in: nothing is sent unless the app asks for it.
|
|
82
|
+
if (config.analyticsEnabled === true) {
|
|
79
83
|
_analytics = new core_1.KoolbaseAnalytics(config, () => _auth?.currentUser?.id ?? null);
|
|
80
84
|
await _analytics.init(config.appVersion);
|
|
81
85
|
}
|
|
@@ -137,7 +141,7 @@ exports.Koolbase = {
|
|
|
137
141
|
},
|
|
138
142
|
get analytics() {
|
|
139
143
|
ensureInitialized();
|
|
140
|
-
return _analytics;
|
|
144
|
+
return _analytics ?? analyticsOff;
|
|
141
145
|
},
|
|
142
146
|
get messaging() {
|
|
143
147
|
ensureInitialized();
|
|
@@ -150,3 +154,13 @@ exports.Koolbase = {
|
|
|
150
154
|
};
|
|
151
155
|
var auth_storage_js_1 = require("./auth-storage.js");
|
|
152
156
|
Object.defineProperty(exports, "SecureAuthStorage", { enumerable: true, get: function () { return auth_storage_js_1.SecureAuthStorage; } });
|
|
157
|
+
/**
|
|
158
|
+
* A collection as React state: loading, loaded or error, with refresh and
|
|
159
|
+
* loadMore. Equality filters only for now: `where: { field: value }`.
|
|
160
|
+
* Use it after Koolbase.initialize() (in an exported app, inside KoolbaseRoot).
|
|
161
|
+
*
|
|
162
|
+
* ```tsx
|
|
163
|
+
* const songs = useCollection('songs', { where: { genre: 'jazz' }, orderBy: 'title' });
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
exports.useCollection = (0, use_collection_js_1.createUseCollection)(() => exports.Koolbase.db);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type CollectionQuery, type CollectionState, type KoolbaseDatabase } from '@koolbase/core';
|
|
2
|
+
export interface UseCollectionResult extends CollectionState {
|
|
3
|
+
/** Page one again, from the server. What is shown stays while it runs, and stays if it fails. */
|
|
4
|
+
refresh: () => Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* The next page, appended, while hasMore. If rows are added or removed on
|
|
7
|
+
* the server between pages, one can be skipped until refresh(); none is
|
|
8
|
+
* ever shown twice.
|
|
9
|
+
*/
|
|
10
|
+
loadMore: () => Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare function createUseCollection(getDb: () => Pick<KoolbaseDatabase, 'query'>): (collection: string, query?: CollectionQuery) => UseCollectionResult;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// useCollection: a Koolbase collection as React state.
|
|
3
|
+
//
|
|
4
|
+
// A thin wrapper. Everything about getting the records right lives in
|
|
5
|
+
// @koolbase/core's KoolbaseCollectionController, which is tested there; this
|
|
6
|
+
// file only ties one controller's lifetime to a component's.
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.createUseCollection = createUseCollection;
|
|
9
|
+
const react_1 = require("react");
|
|
10
|
+
const core_1 = require("@koolbase/core");
|
|
11
|
+
const noop = () => { };
|
|
12
|
+
const done = () => Promise.resolve();
|
|
13
|
+
function createUseCollection(getDb) {
|
|
14
|
+
return function useCollection(collection, query = {}) {
|
|
15
|
+
// The query as a value: an inline `where` object is a new object every
|
|
16
|
+
// render, and must not start a new fetch every render.
|
|
17
|
+
const key = (0, core_1.collectionQueryKey)(collection, query);
|
|
18
|
+
const [current, setCurrent] = (0, react_1.useState)(null);
|
|
19
|
+
(0, react_1.useEffect)(() => {
|
|
20
|
+
// Created here, not during render. Under React strict mode an effect
|
|
21
|
+
// runs, cleans up and runs again; each run gets its own controller, so
|
|
22
|
+
// the one left running is never one that was already disposed.
|
|
23
|
+
const controller = new core_1.KoolbaseCollectionController(getDb(), collection, query);
|
|
24
|
+
setCurrent({ key, controller });
|
|
25
|
+
void controller.load();
|
|
26
|
+
return () => controller.dispose();
|
|
27
|
+
// Depends on key alone: key is collection + query, as a value.
|
|
28
|
+
}, [key]);
|
|
29
|
+
// A controller from the previous key reads as a fresh load, never as
|
|
30
|
+
// the previous query's records.
|
|
31
|
+
const controller = current?.key === key ? current.controller : null;
|
|
32
|
+
const subscribe = (0, react_1.useCallback)((onChange) => (controller ? controller.subscribe(onChange) : noop), [controller]);
|
|
33
|
+
const getSnapshot = (0, react_1.useCallback)(() => (controller ? controller.getState() : core_1.initialCollectionState), [controller]);
|
|
34
|
+
const state = (0, react_1.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
35
|
+
const refresh = (0, react_1.useCallback)(() => (controller ? controller.refresh() : done()), [controller]);
|
|
36
|
+
const loadMore = (0, react_1.useCallback)(() => (controller ? controller.loadMore() : done()), [controller]);
|
|
37
|
+
return { ...state, refresh, loadMore };
|
|
38
|
+
};
|
|
39
|
+
}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -18,3 +18,14 @@ export declare const Koolbase: {
|
|
|
18
18
|
checkVersion(currentVersion: string): VersionCheckResult;
|
|
19
19
|
};
|
|
20
20
|
export { SecureAuthStorage } from './auth-storage.js';
|
|
21
|
+
export type { UseCollectionResult } from './use-collection.js';
|
|
22
|
+
/**
|
|
23
|
+
* A collection as React state: loading, loaded or error, with refresh and
|
|
24
|
+
* loadMore. Equality filters only for now: `where: { field: value }`.
|
|
25
|
+
* Use it after Koolbase.initialize() (in an exported app, inside KoolbaseRoot).
|
|
26
|
+
*
|
|
27
|
+
* ```tsx
|
|
28
|
+
* const songs = useCollection('songs', { where: { genre: 'jazz' }, orderBy: 'title' });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare const useCollection: (collection: string, query?: import("@koolbase/core").CollectionQuery) => import("./use-collection.js").UseCollectionResult;
|
package/dist/esm/index.js
CHANGED
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
// React Native platform adapter and keychain-backed session storage.
|
|
7
7
|
export * from '@koolbase/core';
|
|
8
8
|
export { reactNativePlatform } from './platform.js';
|
|
9
|
-
import { KoolbaseAuth, KoolbaseDatabase, KoolbaseFiscal, KoolbaseStorage, KoolbaseRealtime, KoolbaseFunctions, KoolbaseFlags, KoolbaseAnalytics, KoolbaseMessaging, getOrCreateDeviceId, setPlatform, } from '@koolbase/core';
|
|
9
|
+
import { KoolbaseAuth, KoolbaseDatabase, KoolbaseFiscal, KoolbaseStorage, KoolbaseRealtime, KoolbaseFunctions, KoolbaseFlags, KoolbaseAnalytics, disabledAnalytics, KoolbaseMessaging, getOrCreateDeviceId, setPlatform, } from '@koolbase/core';
|
|
10
10
|
import { reactNativePlatform } from './platform.js';
|
|
11
|
+
import { createUseCollection } from './use-collection.js';
|
|
11
12
|
let _auth = null;
|
|
12
13
|
let _db = null;
|
|
13
14
|
let _storage = null;
|
|
@@ -16,6 +17,8 @@ let _realtime = null;
|
|
|
16
17
|
let _functions = null;
|
|
17
18
|
let _flags = null;
|
|
18
19
|
let _analytics = null;
|
|
20
|
+
// While analytics is off, calls are harmless no-ops rather than a crash.
|
|
21
|
+
const analyticsOff = disabledAnalytics();
|
|
19
22
|
let _messaging = null;
|
|
20
23
|
let _initialized = false;
|
|
21
24
|
// The in-flight initialize, so overlapping callers await the same one.
|
|
@@ -57,7 +60,8 @@ export const Koolbase = {
|
|
|
57
60
|
const deviceId = await getOrCreateDeviceId();
|
|
58
61
|
_flags = new KoolbaseFlags(config, deviceId);
|
|
59
62
|
// Initialize analytics
|
|
60
|
-
|
|
63
|
+
// Opt-in: nothing is sent unless the app asks for it.
|
|
64
|
+
if (config.analyticsEnabled === true) {
|
|
61
65
|
_analytics = new KoolbaseAnalytics(config, () => _auth?.currentUser?.id ?? null);
|
|
62
66
|
await _analytics.init(config.appVersion);
|
|
63
67
|
}
|
|
@@ -119,7 +123,7 @@ export const Koolbase = {
|
|
|
119
123
|
},
|
|
120
124
|
get analytics() {
|
|
121
125
|
ensureInitialized();
|
|
122
|
-
return _analytics;
|
|
126
|
+
return _analytics ?? analyticsOff;
|
|
123
127
|
},
|
|
124
128
|
get messaging() {
|
|
125
129
|
ensureInitialized();
|
|
@@ -131,3 +135,13 @@ export const Koolbase = {
|
|
|
131
135
|
},
|
|
132
136
|
};
|
|
133
137
|
export { SecureAuthStorage } from './auth-storage.js';
|
|
138
|
+
/**
|
|
139
|
+
* A collection as React state: loading, loaded or error, with refresh and
|
|
140
|
+
* loadMore. Equality filters only for now: `where: { field: value }`.
|
|
141
|
+
* Use it after Koolbase.initialize() (in an exported app, inside KoolbaseRoot).
|
|
142
|
+
*
|
|
143
|
+
* ```tsx
|
|
144
|
+
* const songs = useCollection('songs', { where: { genre: 'jazz' }, orderBy: 'title' });
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
export const useCollection = createUseCollection(() => Koolbase.db);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type CollectionQuery, type CollectionState, type KoolbaseDatabase } from '@koolbase/core';
|
|
2
|
+
export interface UseCollectionResult extends CollectionState {
|
|
3
|
+
/** Page one again, from the server. What is shown stays while it runs, and stays if it fails. */
|
|
4
|
+
refresh: () => Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* The next page, appended, while hasMore. If rows are added or removed on
|
|
7
|
+
* the server between pages, one can be skipped until refresh(); none is
|
|
8
|
+
* ever shown twice.
|
|
9
|
+
*/
|
|
10
|
+
loadMore: () => Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare function createUseCollection(getDb: () => Pick<KoolbaseDatabase, 'query'>): (collection: string, query?: CollectionQuery) => UseCollectionResult;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// useCollection: a Koolbase collection as React state.
|
|
2
|
+
//
|
|
3
|
+
// A thin wrapper. Everything about getting the records right lives in
|
|
4
|
+
// @koolbase/core's KoolbaseCollectionController, which is tested there; this
|
|
5
|
+
// file only ties one controller's lifetime to a component's.
|
|
6
|
+
import { useCallback, useEffect, useState, useSyncExternalStore } from 'react';
|
|
7
|
+
import { KoolbaseCollectionController, collectionQueryKey, initialCollectionState, } from '@koolbase/core';
|
|
8
|
+
const noop = () => { };
|
|
9
|
+
const done = () => Promise.resolve();
|
|
10
|
+
export function createUseCollection(getDb) {
|
|
11
|
+
return function useCollection(collection, query = {}) {
|
|
12
|
+
// The query as a value: an inline `where` object is a new object every
|
|
13
|
+
// render, and must not start a new fetch every render.
|
|
14
|
+
const key = collectionQueryKey(collection, query);
|
|
15
|
+
const [current, setCurrent] = useState(null);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
// Created here, not during render. Under React strict mode an effect
|
|
18
|
+
// runs, cleans up and runs again; each run gets its own controller, so
|
|
19
|
+
// the one left running is never one that was already disposed.
|
|
20
|
+
const controller = new KoolbaseCollectionController(getDb(), collection, query);
|
|
21
|
+
setCurrent({ key, controller });
|
|
22
|
+
void controller.load();
|
|
23
|
+
return () => controller.dispose();
|
|
24
|
+
// Depends on key alone: key is collection + query, as a value.
|
|
25
|
+
}, [key]);
|
|
26
|
+
// A controller from the previous key reads as a fresh load, never as
|
|
27
|
+
// the previous query's records.
|
|
28
|
+
const controller = current?.key === key ? current.controller : null;
|
|
29
|
+
const subscribe = useCallback((onChange) => (controller ? controller.subscribe(onChange) : noop), [controller]);
|
|
30
|
+
const getSnapshot = useCallback(() => (controller ? controller.getState() : initialCollectionState), [controller]);
|
|
31
|
+
const state = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
32
|
+
const refresh = useCallback(() => (controller ? controller.refresh() : done()), [controller]);
|
|
33
|
+
const loadMore = useCallback(() => (controller ? controller.loadMore() : done()), [controller]);
|
|
34
|
+
return { ...state, refresh, loadMore };
|
|
35
|
+
};
|
|
36
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@koolbase/react-native",
|
|
3
|
-
"version": "12.
|
|
4
|
-
"description": "React Native SDK for Koolbase
|
|
3
|
+
"version": "12.5.0",
|
|
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",
|
|
7
7
|
"files": [
|
|
@@ -24,11 +24,12 @@
|
|
|
24
24
|
"url": "https://github.com/koolbase/koolbase-react-native"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@koolbase/core": "12.
|
|
27
|
+
"@koolbase/core": "12.5.0"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"@react-native-async-storage/async-storage": "^3.0.2",
|
|
31
31
|
"@react-native-community/netinfo": "^12.0.1",
|
|
32
|
+
"react": ">=18.0.0",
|
|
32
33
|
"react-native": ">=0.70.0",
|
|
33
34
|
"react-native-keychain": ">=8.0.0"
|
|
34
35
|
},
|