@koolbase/react-native 9.1.0 → 10.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.
- package/CHANGELOG.md +1342 -0
- package/README.md +462 -511
- package/dist/{auth-storage.d.ts → cjs/auth-storage.d.ts} +1 -1
- package/dist/cjs/index.d.ts +19 -0
- package/dist/cjs/index.js +125 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/platform.d.ts +2 -0
- package/dist/cjs/platform.js +43 -0
- package/dist/esm/auth-storage.d.ts +26 -0
- package/dist/esm/auth-storage.js +100 -0
- package/dist/esm/index.d.ts +19 -0
- package/dist/esm/index.js +106 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/platform.d.ts +2 -0
- package/dist/esm/platform.js +37 -0
- package/package.json +30 -24
- package/dist/analytics.d.ts +0 -24
- package/dist/analytics.js +0 -114
- package/dist/apple-auth.d.ts +0 -22
- package/dist/apple-auth.js +0 -74
- package/dist/auth-errors.d.ts +0 -117
- package/dist/auth-errors.js +0 -250
- package/dist/auth.d.ts +0 -199
- package/dist/auth.js +0 -794
- package/dist/cache-store.d.ts +0 -11
- package/dist/cache-store.js +0 -136
- package/dist/code-push.d.ts +0 -59
- package/dist/code-push.js +0 -255
- package/dist/database-errors.d.ts +0 -95
- package/dist/database-errors.js +0 -173
- package/dist/database.d.ts +0 -208
- package/dist/database.js +0 -508
- package/dist/device-id.d.ts +0 -1
- package/dist/device-id.js +0 -60
- package/dist/device-metadata.d.ts +0 -36
- package/dist/device-metadata.js +0 -102
- package/dist/flags.d.ts +0 -15
- package/dist/flags.js +0 -76
- package/dist/functions.d.ts +0 -8
- package/dist/functions.js +0 -70
- package/dist/index.d.ts +0 -45
- package/dist/index.js +0 -193
- package/dist/logic-engine.d.ts +0 -17
- package/dist/logic-engine.js +0 -193
- package/dist/messaging.d.ts +0 -13
- package/dist/messaging.js +0 -36
- package/dist/realtime.d.ts +0 -19
- package/dist/realtime.js +0 -148
- package/dist/record.d.ts +0 -2
- package/dist/record.js +0 -20
- package/dist/storage-errors.d.ts +0 -163
- package/dist/storage-errors.js +0 -249
- package/dist/storage.d.ts +0 -184
- package/dist/storage.js +0 -438
- package/dist/sync-engine.d.ts +0 -16
- package/dist/sync-engine.js +0 -86
- package/dist/types.d.ts +0 -470
- package/dist/types.js +0 -40
- /package/dist/{auth-storage.js → cjs/auth-storage.js} +0 -0
package/dist/cache-store.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { KoolbaseRecord, PendingWrite, QueryResult } from './types';
|
|
2
|
-
export declare function hashQuery(collection: string, options: Record<string, unknown>): string;
|
|
3
|
-
export declare function getCached(userId: string, collection: string, queryHash: string): Promise<QueryResult | null>;
|
|
4
|
-
export declare function setCached(userId: string, collection: string, queryHash: string, result: QueryResult): Promise<void>;
|
|
5
|
-
export declare function invalidateCache(userId: string, collection: string): Promise<void>;
|
|
6
|
-
export declare function clearUserCache(userId: string): Promise<void>;
|
|
7
|
-
export declare function getWriteQueue(userId: string): Promise<PendingWrite[]>;
|
|
8
|
-
export declare function addToWriteQueue(userId: string, write: Omit<PendingWrite, 'retries' | 'createdAt'>): Promise<void>;
|
|
9
|
-
export declare function removeFromWriteQueue(userId: string, writeId: string): Promise<void>;
|
|
10
|
-
export declare function incrementWriteRetry(userId: string, writeId: string): Promise<void>;
|
|
11
|
-
export declare function optimisticallyInsert(userId: string, collection: string, record: KoolbaseRecord): Promise<void>;
|
package/dist/cache-store.js
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.hashQuery = hashQuery;
|
|
7
|
-
exports.getCached = getCached;
|
|
8
|
-
exports.setCached = setCached;
|
|
9
|
-
exports.invalidateCache = invalidateCache;
|
|
10
|
-
exports.clearUserCache = clearUserCache;
|
|
11
|
-
exports.getWriteQueue = getWriteQueue;
|
|
12
|
-
exports.addToWriteQueue = addToWriteQueue;
|
|
13
|
-
exports.removeFromWriteQueue = removeFromWriteQueue;
|
|
14
|
-
exports.incrementWriteRetry = incrementWriteRetry;
|
|
15
|
-
exports.optimisticallyInsert = optimisticallyInsert;
|
|
16
|
-
const async_storage_1 = __importDefault(require("@react-native-async-storage/async-storage"));
|
|
17
|
-
const CACHE_VERSION = 'v1';
|
|
18
|
-
function cacheKey(userId, collection, queryHash) {
|
|
19
|
-
return `koolbase:${CACHE_VERSION}:${userId}:${collection}:${queryHash}`;
|
|
20
|
-
}
|
|
21
|
-
function writeQueueKey(userId) {
|
|
22
|
-
return `koolbase:${CACHE_VERSION}:${userId}:write_queue`;
|
|
23
|
-
}
|
|
24
|
-
function hashQuery(collection, options) {
|
|
25
|
-
return `${collection}:${JSON.stringify(options)}`;
|
|
26
|
-
}
|
|
27
|
-
// ─── Cache ──────────────────────────────────────────────────────────────────
|
|
28
|
-
async function getCached(userId, collection, queryHash) {
|
|
29
|
-
try {
|
|
30
|
-
const raw = await async_storage_1.default.getItem(cacheKey(userId, collection, queryHash));
|
|
31
|
-
if (!raw)
|
|
32
|
-
return null;
|
|
33
|
-
return JSON.parse(raw);
|
|
34
|
-
}
|
|
35
|
-
catch {
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
async function setCached(userId, collection, queryHash, result) {
|
|
40
|
-
try {
|
|
41
|
-
await async_storage_1.default.setItem(cacheKey(userId, collection, queryHash), JSON.stringify(result));
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
// ignore storage errors
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
async function invalidateCache(userId, collection) {
|
|
48
|
-
try {
|
|
49
|
-
const keys = await async_storage_1.default.getAllKeys();
|
|
50
|
-
const prefix = `koolbase:${CACHE_VERSION}:${userId}:${collection}:`;
|
|
51
|
-
const toDelete = keys.filter(k => k.startsWith(prefix));
|
|
52
|
-
for (const key of toDelete) {
|
|
53
|
-
await async_storage_1.default.removeItem(key);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
catch {
|
|
57
|
-
// ignore
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
async function clearUserCache(userId) {
|
|
61
|
-
try {
|
|
62
|
-
const keys = await async_storage_1.default.getAllKeys();
|
|
63
|
-
const prefix = `koolbase:${CACHE_VERSION}:${userId}:`;
|
|
64
|
-
const toDelete = keys.filter(k => k.startsWith(prefix));
|
|
65
|
-
for (const key of toDelete) {
|
|
66
|
-
await async_storage_1.default.removeItem(key);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
catch {
|
|
70
|
-
// ignore
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
// ─── Write Queue ────────────────────────────────────────────────────────────
|
|
74
|
-
async function getWriteQueue(userId) {
|
|
75
|
-
try {
|
|
76
|
-
const raw = await async_storage_1.default.getItem(writeQueueKey(userId));
|
|
77
|
-
if (!raw)
|
|
78
|
-
return [];
|
|
79
|
-
return JSON.parse(raw);
|
|
80
|
-
}
|
|
81
|
-
catch {
|
|
82
|
-
return [];
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
async function addToWriteQueue(userId, write) {
|
|
86
|
-
try {
|
|
87
|
-
const queue = await getWriteQueue(userId);
|
|
88
|
-
queue.push({ ...write, retries: 0, createdAt: new Date().toISOString() });
|
|
89
|
-
await async_storage_1.default.setItem(writeQueueKey(userId), JSON.stringify(queue));
|
|
90
|
-
}
|
|
91
|
-
catch {
|
|
92
|
-
// ignore
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
async function removeFromWriteQueue(userId, writeId) {
|
|
96
|
-
try {
|
|
97
|
-
const queue = await getWriteQueue(userId);
|
|
98
|
-
const updated = queue.filter(w => w.id !== writeId);
|
|
99
|
-
await async_storage_1.default.setItem(writeQueueKey(userId), JSON.stringify(updated));
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
// ignore
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
async function incrementWriteRetry(userId, writeId) {
|
|
106
|
-
try {
|
|
107
|
-
const queue = await getWriteQueue(userId);
|
|
108
|
-
const updated = queue.map(w => w.id === writeId ? { ...w, retries: w.retries + 1 } : w);
|
|
109
|
-
// Drop writes that have exceeded 3 retries
|
|
110
|
-
const filtered = updated.filter(w => w.retries <= 3);
|
|
111
|
-
await async_storage_1.default.setItem(writeQueueKey(userId), JSON.stringify(filtered));
|
|
112
|
-
}
|
|
113
|
-
catch {
|
|
114
|
-
// ignore
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
// ─── Optimistic cache update ─────────────────────────────────────────────────
|
|
118
|
-
async function optimisticallyInsert(userId, collection, record) {
|
|
119
|
-
try {
|
|
120
|
-
const keys = await async_storage_1.default.getAllKeys();
|
|
121
|
-
const prefix = `koolbase:${CACHE_VERSION}:${userId}:${collection}:`;
|
|
122
|
-
const collectionKeys = keys.filter(k => k.startsWith(prefix));
|
|
123
|
-
for (const key of collectionKeys) {
|
|
124
|
-
const raw = await async_storage_1.default.getItem(key);
|
|
125
|
-
if (!raw)
|
|
126
|
-
continue;
|
|
127
|
-
const cached = JSON.parse(raw);
|
|
128
|
-
cached.records = [record, ...cached.records];
|
|
129
|
-
cached.total = cached.total + 1;
|
|
130
|
-
await async_storage_1.default.setItem(key, JSON.stringify(cached));
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
catch {
|
|
134
|
-
// ignore
|
|
135
|
-
}
|
|
136
|
-
}
|
package/dist/code-push.d.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { KoolbaseConfig } from './types';
|
|
2
|
-
export interface BundlePayload {
|
|
3
|
-
config: Record<string, unknown>;
|
|
4
|
-
flags: Record<string, boolean>;
|
|
5
|
-
directives: Record<string, unknown>;
|
|
6
|
-
assets: {
|
|
7
|
-
images: string[];
|
|
8
|
-
json: string[];
|
|
9
|
-
fonts: string[];
|
|
10
|
-
};
|
|
11
|
-
screens?: Record<string, string>;
|
|
12
|
-
flows?: Record<string, unknown>;
|
|
13
|
-
}
|
|
14
|
-
export interface BundleManifest {
|
|
15
|
-
bundle_id: string;
|
|
16
|
-
app_id: string;
|
|
17
|
-
version: number;
|
|
18
|
-
base_app_version: string;
|
|
19
|
-
max_app_version: string;
|
|
20
|
-
platform: string;
|
|
21
|
-
channel: string;
|
|
22
|
-
checksum: string;
|
|
23
|
-
signature: string;
|
|
24
|
-
size_bytes: number;
|
|
25
|
-
payload: BundlePayload;
|
|
26
|
-
mandatory?: boolean;
|
|
27
|
-
}
|
|
28
|
-
export declare class KoolbaseCodePush {
|
|
29
|
-
private config;
|
|
30
|
-
private channel;
|
|
31
|
-
private activeManifest;
|
|
32
|
-
private mandatoryPending;
|
|
33
|
-
constructor(config: KoolbaseConfig, channel?: string);
|
|
34
|
-
init(options: {
|
|
35
|
-
appVersion: string;
|
|
36
|
-
platform: string;
|
|
37
|
-
deviceId: string;
|
|
38
|
-
}): Promise<void>;
|
|
39
|
-
private promotePendingIfAvailable;
|
|
40
|
-
private loadActive;
|
|
41
|
-
private checkInBackground;
|
|
42
|
-
private download;
|
|
43
|
-
private handleRollback;
|
|
44
|
-
get hasActiveBundle(): boolean;
|
|
45
|
-
/**
|
|
46
|
-
* True when a mandatory bundle has been staged this session and is awaiting
|
|
47
|
-
* application (it activates on the next cold launch). Gate your UI on this to
|
|
48
|
-
* prompt the user to restart so the required update takes effect.
|
|
49
|
-
*/
|
|
50
|
-
get hasMandatoryUpdate(): boolean;
|
|
51
|
-
get manifest(): BundleManifest | null;
|
|
52
|
-
getBundleConfig(key: string): unknown | undefined;
|
|
53
|
-
getBundleFlag(key: string): boolean | undefined;
|
|
54
|
-
getBundleDirective(key: string): unknown | undefined;
|
|
55
|
-
private directiveHandlers;
|
|
56
|
-
onDirective(key: string, handler: (value: unknown) => void): void;
|
|
57
|
-
applyDirectives(): void;
|
|
58
|
-
clearBundle(): Promise<void>;
|
|
59
|
-
}
|
package/dist/code-push.js
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.KoolbaseCodePush = void 0;
|
|
40
|
-
const async_storage_1 = __importDefault(require("@react-native-async-storage/async-storage"));
|
|
41
|
-
const STORAGE_KEY_ACTIVE = 'koolbase:codepush:active';
|
|
42
|
-
const STORAGE_KEY_PENDING = 'koolbase:codepush:pending';
|
|
43
|
-
// ─── Pure JS sha256 for checksum verification ────────────────────────────────
|
|
44
|
-
async function sha256Hex(data) {
|
|
45
|
-
// Use SubtleCrypto if available (modern RN / Hermes)
|
|
46
|
-
if (typeof crypto !== 'undefined' && crypto.subtle) {
|
|
47
|
-
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
|
48
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
49
|
-
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
|
50
|
-
}
|
|
51
|
-
// Fallback — skip verification (dev only)
|
|
52
|
-
return '';
|
|
53
|
-
}
|
|
54
|
-
// ─── Zip manifest extraction ─────────────────────────────────────────────────
|
|
55
|
-
async function extractManifestFromZip(data) {
|
|
56
|
-
try {
|
|
57
|
-
// Dynamically import JSZip — must be installed as a dependency
|
|
58
|
-
const JSZip = (await Promise.resolve().then(() => __importStar(require('jszip')))).default;
|
|
59
|
-
const zip = await JSZip.loadAsync(data);
|
|
60
|
-
const manifestFile = zip.file('manifest.json');
|
|
61
|
-
if (!manifestFile)
|
|
62
|
-
return null;
|
|
63
|
-
const json = await manifestFile.async('string');
|
|
64
|
-
return JSON.parse(json);
|
|
65
|
-
}
|
|
66
|
-
catch (e) {
|
|
67
|
-
console.warn('[KoolbaseCodePush] manifest extraction failed:', e);
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
// ─── KoolbaseCodePush ────────────────────────────────────────────────────────
|
|
72
|
-
class KoolbaseCodePush {
|
|
73
|
-
constructor(config, channel = 'stable') {
|
|
74
|
-
this.activeManifest = null;
|
|
75
|
-
this.mandatoryPending = false;
|
|
76
|
-
// ─── Directive handling ──────────────────────────────────────────────────
|
|
77
|
-
this.directiveHandlers = new Map();
|
|
78
|
-
this.config = config;
|
|
79
|
-
this.channel = channel;
|
|
80
|
-
}
|
|
81
|
-
// Called inside Koolbase.initialize() — loads cached bundle then checks in background
|
|
82
|
-
async init(options) {
|
|
83
|
-
// Step 1 — promote pending → active if available
|
|
84
|
-
await this.promotePendingIfAvailable();
|
|
85
|
-
// Step 2 — load active manifest into memory
|
|
86
|
-
this.activeManifest = await this.loadActive();
|
|
87
|
-
if (this.activeManifest) {
|
|
88
|
-
console.log(`[KoolbaseCodePush] bundle v${this.activeManifest.version} active`);
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
console.log('[KoolbaseCodePush] no active bundle — using app defaults');
|
|
92
|
-
}
|
|
93
|
-
// Step 3 — check for updates in background (non-blocking)
|
|
94
|
-
this.checkInBackground(options);
|
|
95
|
-
}
|
|
96
|
-
async promotePendingIfAvailable() {
|
|
97
|
-
try {
|
|
98
|
-
const pending = await async_storage_1.default.getItem(STORAGE_KEY_PENDING);
|
|
99
|
-
if (!pending)
|
|
100
|
-
return;
|
|
101
|
-
// Archive current active → just overwrite, we keep one version
|
|
102
|
-
await async_storage_1.default.setItem(STORAGE_KEY_ACTIVE, pending);
|
|
103
|
-
await async_storage_1.default.removeItem(STORAGE_KEY_PENDING);
|
|
104
|
-
console.log('[KoolbaseCodePush] promoted pending bundle to active');
|
|
105
|
-
}
|
|
106
|
-
catch (e) {
|
|
107
|
-
console.warn('[KoolbaseCodePush] promotion failed:', e);
|
|
108
|
-
// One re-check will be triggered naturally by background check
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
async loadActive() {
|
|
112
|
-
try {
|
|
113
|
-
const stored = await async_storage_1.default.getItem(STORAGE_KEY_ACTIVE);
|
|
114
|
-
if (!stored)
|
|
115
|
-
return null;
|
|
116
|
-
return JSON.parse(stored);
|
|
117
|
-
}
|
|
118
|
-
catch {
|
|
119
|
-
return null;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
checkInBackground(options) {
|
|
123
|
-
// Fire and forget
|
|
124
|
-
(async () => {
|
|
125
|
-
try {
|
|
126
|
-
const currentVersion = this.activeManifest?.version ?? 0;
|
|
127
|
-
const res = await fetch(`${this.config.baseUrl}/v1/code-push/check` +
|
|
128
|
-
`?app_version=${options.appVersion}` +
|
|
129
|
-
`&platform=${options.platform}` +
|
|
130
|
-
`&channel=${this.channel}` +
|
|
131
|
-
`&device_id=${options.deviceId}` +
|
|
132
|
-
`¤t_bundle=${currentVersion}`, { headers: { 'x-api-key': this.config.publicKey } });
|
|
133
|
-
if (!res.ok)
|
|
134
|
-
return;
|
|
135
|
-
const body = await res.json();
|
|
136
|
-
switch (body.status) {
|
|
137
|
-
case 'update_available':
|
|
138
|
-
await this.download(body.bundle);
|
|
139
|
-
break;
|
|
140
|
-
case 'rollback':
|
|
141
|
-
await this.handleRollback(body.revert_to ?? '0');
|
|
142
|
-
break;
|
|
143
|
-
case 'no_update':
|
|
144
|
-
console.log('[KoolbaseCodePush] no update available');
|
|
145
|
-
break;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
catch (e) {
|
|
149
|
-
// Server unreachable — continue silently
|
|
150
|
-
console.log('[KoolbaseCodePush] check failed silently:', e);
|
|
151
|
-
}
|
|
152
|
-
})();
|
|
153
|
-
}
|
|
154
|
-
async download(ref) {
|
|
155
|
-
try {
|
|
156
|
-
console.log(`[KoolbaseCodePush] downloading bundle v${ref.version}...`);
|
|
157
|
-
const res = await fetch(ref.download_url);
|
|
158
|
-
if (!res.ok) {
|
|
159
|
-
console.warn('[KoolbaseCodePush] download failed:', res.status);
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
const data = await res.arrayBuffer();
|
|
163
|
-
console.log(`[KoolbaseCodePush] downloaded ${data.byteLength} bytes`);
|
|
164
|
-
// Verify checksum
|
|
165
|
-
if (ref.checksum !== 'placeholder' && ref.checksum !== 'pending') {
|
|
166
|
-
const actual = `sha256:${await sha256Hex(data)}`;
|
|
167
|
-
if (actual !== ref.checksum && actual !== 'sha256:') {
|
|
168
|
-
console.warn('[KoolbaseCodePush] checksum mismatch — bundle rejected');
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
console.log('[KoolbaseCodePush] checksum verified');
|
|
172
|
-
}
|
|
173
|
-
else {
|
|
174
|
-
console.log('[KoolbaseCodePush] checksum skipped (dev mode)');
|
|
175
|
-
}
|
|
176
|
-
// Extract manifest
|
|
177
|
-
const manifest = await extractManifestFromZip(data);
|
|
178
|
-
if (!manifest) {
|
|
179
|
-
console.warn('[KoolbaseCodePush] manifest extraction failed');
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
// Carry the mandatory flag from the check response onto the staged manifest
|
|
183
|
-
manifest.mandatory = ref.mandatory;
|
|
184
|
-
// Store as pending — activates on next launch
|
|
185
|
-
await async_storage_1.default.setItem(STORAGE_KEY_PENDING, JSON.stringify(manifest));
|
|
186
|
-
console.log(`[KoolbaseCodePush] bundle v${manifest.version} ready for next launch`);
|
|
187
|
-
if (ref.mandatory) {
|
|
188
|
-
this.mandatoryPending = true;
|
|
189
|
-
console.log('[KoolbaseCodePush] staged bundle is mandatory — notifying app');
|
|
190
|
-
try {
|
|
191
|
-
this.config.onMandatoryUpdate?.({ version: manifest.version, bundleId: manifest.bundle_id });
|
|
192
|
-
}
|
|
193
|
-
catch (cbErr) {
|
|
194
|
-
console.warn('[KoolbaseCodePush] onMandatoryUpdate handler threw:', cbErr);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
catch (e) {
|
|
199
|
-
console.warn('[KoolbaseCodePush] download error:', e);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
async handleRollback(revertTo) {
|
|
203
|
-
console.log(`[KoolbaseCodePush] rollback to v${revertTo}`);
|
|
204
|
-
await async_storage_1.default.removeItem(STORAGE_KEY_ACTIVE);
|
|
205
|
-
await async_storage_1.default.removeItem(STORAGE_KEY_PENDING);
|
|
206
|
-
this.activeManifest = null;
|
|
207
|
-
console.log('[KoolbaseCodePush] reverted to app defaults');
|
|
208
|
-
}
|
|
209
|
-
// ─── Public accessors ────────────────────────────────────────────────────
|
|
210
|
-
get hasActiveBundle() {
|
|
211
|
-
return this.activeManifest !== null;
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* True when a mandatory bundle has been staged this session and is awaiting
|
|
215
|
-
* application (it activates on the next cold launch). Gate your UI on this to
|
|
216
|
-
* prompt the user to restart so the required update takes effect.
|
|
217
|
-
*/
|
|
218
|
-
get hasMandatoryUpdate() {
|
|
219
|
-
return this.mandatoryPending;
|
|
220
|
-
}
|
|
221
|
-
get manifest() {
|
|
222
|
-
return this.activeManifest;
|
|
223
|
-
}
|
|
224
|
-
getBundleConfig(key) {
|
|
225
|
-
return this.activeManifest?.payload.config[key];
|
|
226
|
-
}
|
|
227
|
-
getBundleFlag(key) {
|
|
228
|
-
return this.activeManifest?.payload.flags[key];
|
|
229
|
-
}
|
|
230
|
-
getBundleDirective(key) {
|
|
231
|
-
return this.activeManifest?.payload.directives[key];
|
|
232
|
-
}
|
|
233
|
-
onDirective(key, handler) {
|
|
234
|
-
this.directiveHandlers.set(key, handler);
|
|
235
|
-
}
|
|
236
|
-
applyDirectives() {
|
|
237
|
-
if (!this.activeManifest?.payload.directives)
|
|
238
|
-
return;
|
|
239
|
-
for (const [key, value] of Object.entries(this.activeManifest.payload.directives)) {
|
|
240
|
-
const handler = this.directiveHandlers.get(key);
|
|
241
|
-
if (handler) {
|
|
242
|
-
console.log(`[KoolbaseCodePush] directive: ${key} = ${value}`);
|
|
243
|
-
handler(value);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
// ─── Cache management ────────────────────────────────────────────────────
|
|
248
|
-
async clearBundle() {
|
|
249
|
-
await async_storage_1.default.removeItem(STORAGE_KEY_ACTIVE);
|
|
250
|
-
await async_storage_1.default.removeItem(STORAGE_KEY_PENDING);
|
|
251
|
-
this.activeManifest = null;
|
|
252
|
-
console.log('[KoolbaseCodePush] bundle cache cleared');
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
exports.KoolbaseCodePush = KoolbaseCodePush;
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Base class for errors surfaced by the Koolbase data layer (database reads
|
|
3
|
-
* and writes). Every data error carries a `message` and, when the server
|
|
4
|
-
* provides one, its stable `code` (e.g. `not_found`, `validation_error`,
|
|
5
|
-
* `unique_violation`).
|
|
6
|
-
*
|
|
7
|
-
* Catch this to handle any data-layer failure generically, or catch a
|
|
8
|
-
* specific subclass to branch on the kind of failure.
|
|
9
|
-
*/
|
|
10
|
-
export declare class KoolbaseDataError extends Error {
|
|
11
|
-
code?: string;
|
|
12
|
-
constructor(message: string, code?: string);
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Thrown when a write is rejected because the value would violate a
|
|
16
|
-
* collection's unique constraint — the server responds with 409 Conflict.
|
|
17
|
-
* Catch it to handle duplicates, e.g. an email or username already in use.
|
|
18
|
-
*
|
|
19
|
-
* `field` names the field that collided, when the server reports it
|
|
20
|
-
* (`details.field`) — useful when a collection has more than one unique
|
|
21
|
-
* constraint and you need to know which value clashed.
|
|
22
|
-
*
|
|
23
|
-
* Surfaced by `insert`, `update`, and `upsert` whenever the server is
|
|
24
|
-
* reachable and rejects the write with a 409. These writes are online-first:
|
|
25
|
-
* a server-side conflict throws immediately. Only a genuine network failure
|
|
26
|
-
* falls back to the offline queue, where a conflict that surfaces at sync
|
|
27
|
-
* time is handled by the sync engine rather than thrown here.
|
|
28
|
-
*
|
|
29
|
-
* @example
|
|
30
|
-
* try {
|
|
31
|
-
* await koolbase.db.upsert('users', { email }, { name });
|
|
32
|
-
* } catch (e) {
|
|
33
|
-
* if (e instanceof KoolbaseConflictError) {
|
|
34
|
-
* showError(`That ${e.field ?? 'value'} is already registered.`);
|
|
35
|
-
* }
|
|
36
|
-
* }
|
|
37
|
-
*/
|
|
38
|
-
export declare class KoolbaseConflictError extends KoolbaseDataError {
|
|
39
|
-
field?: string;
|
|
40
|
-
constructor(message?: string, field?: string);
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Thrown when the requested record or collection does not exist — the server
|
|
44
|
-
* responds with 404 and code `not_found` / `record_not_found` /
|
|
45
|
-
* `collection_not_found`.
|
|
46
|
-
*/
|
|
47
|
-
export declare class KoolbaseNotFoundError extends KoolbaseDataError {
|
|
48
|
-
constructor(message?: string);
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Thrown when the request is rejected as invalid — the server responds with
|
|
52
|
-
* 400 and code `validation_error`.
|
|
53
|
-
*/
|
|
54
|
-
export declare class KoolbaseValidationError extends KoolbaseDataError {
|
|
55
|
-
constructor(message?: string);
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Thrown when the caller is authenticated but not allowed to perform the
|
|
59
|
-
* operation — the server responds with 403 and code `permission_denied`
|
|
60
|
-
* (typically a collection access rule rejecting the read/write).
|
|
61
|
-
*/
|
|
62
|
-
export declare class KoolbasePermissionError extends KoolbaseDataError {
|
|
63
|
-
constructor(message?: string);
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Thrown when the server is rate-limiting the caller — 429 with code
|
|
67
|
-
* `rate_limit`. Back off and retry after a short delay.
|
|
68
|
-
*/
|
|
69
|
-
export declare class KoolbaseRateLimitError extends KoolbaseDataError {
|
|
70
|
-
constructor(message?: string);
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Thrown when the supplied vector's length does not match the dimension
|
|
74
|
-
* declared on the collection's vector field — the server responds with
|
|
75
|
-
* 400 and code `vector_dimension_mismatch`. The message includes both
|
|
76
|
-
* the expected and actual dimensions so you can surface a precise error.
|
|
77
|
-
*
|
|
78
|
-
* @example
|
|
79
|
-
* try {
|
|
80
|
-
* await koolbase.db.setVector(id, 'embedding', [0.1, 0.2]); // 2 dims
|
|
81
|
-
* } catch (e) {
|
|
82
|
-
* if (e instanceof KoolbaseVectorDimensionMismatchError) {
|
|
83
|
-
* showError(e.message); // "expected 1536, got 2"
|
|
84
|
-
* }
|
|
85
|
-
* }
|
|
86
|
-
*/
|
|
87
|
-
export declare class KoolbaseVectorDimensionMismatchError extends KoolbaseDataError {
|
|
88
|
-
constructor(message?: string);
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Maps a non-2xx data-layer response to a typed {@link KoolbaseDataError},
|
|
92
|
-
* preferring the server's stable `code` and falling back to the HTTP status
|
|
93
|
-
* for older or uncoded responses. Always returns an error to throw.
|
|
94
|
-
*/
|
|
95
|
-
export declare function koolbaseDataError(status: number, body: any, fallbackMessage?: string): KoolbaseDataError;
|