@techfinityedge/koolbase-react-native 1.6.1
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 +282 -0
- package/dist/analytics.d.ts +26 -0
- package/dist/analytics.js +138 -0
- package/dist/apple-auth.d.ts +22 -0
- package/dist/apple-auth.js +74 -0
- package/dist/auth.d.ts +24 -0
- package/dist/auth.js +85 -0
- package/dist/cache-store.d.ts +11 -0
- package/dist/cache-store.js +136 -0
- package/dist/code-push.d.ts +51 -0
- package/dist/code-push.js +234 -0
- package/dist/database.d.ts +15 -0
- package/dist/database.js +161 -0
- package/dist/flags.d.ts +15 -0
- package/dist/flags.js +76 -0
- package/dist/functions.d.ts +7 -0
- package/dist/functions.js +64 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +165 -0
- package/dist/logic-engine.d.ts +17 -0
- package/dist/logic-engine.js +193 -0
- package/dist/messaging.d.ts +20 -0
- package/dist/messaging.js +58 -0
- package/dist/realtime.d.ts +11 -0
- package/dist/realtime.js +52 -0
- package/dist/storage.d.ts +12 -0
- package/dist/storage.js +62 -0
- package/dist/sync-engine.d.ts +15 -0
- package/dist/sync-engine.js +83 -0
- package/dist/types.d.ts +122 -0
- package/dist/types.js +9 -0
- package/package.json +43 -0
package/dist/flags.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KoolbaseFlags = void 0;
|
|
4
|
+
class KoolbaseFlags {
|
|
5
|
+
constructor(config, deviceId) {
|
|
6
|
+
this.payload = null;
|
|
7
|
+
this.config = config;
|
|
8
|
+
this.deviceId = deviceId;
|
|
9
|
+
}
|
|
10
|
+
async fetch(appVersion, platform) {
|
|
11
|
+
try {
|
|
12
|
+
const res = await fetch(`${this.config.baseUrl}/v1/bootstrap?public_key=${this.config.publicKey}&device_id=${this.deviceId}&app_version=${appVersion}&platform=${platform}`);
|
|
13
|
+
if (res.ok) {
|
|
14
|
+
this.payload = await res.json();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
catch (_) { }
|
|
18
|
+
}
|
|
19
|
+
isEnabled(key) {
|
|
20
|
+
const flag = this.payload?.flags[key];
|
|
21
|
+
if (!flag || !flag.enabled || flag.kill_switch)
|
|
22
|
+
return false;
|
|
23
|
+
const bucket = this.stableHash(`${this.deviceId}:${key}`) % 100;
|
|
24
|
+
return bucket < flag.rollout_percentage;
|
|
25
|
+
}
|
|
26
|
+
getString(key, fallback = '') {
|
|
27
|
+
const val = this.payload?.config[key];
|
|
28
|
+
return val !== undefined ? String(val) : fallback;
|
|
29
|
+
}
|
|
30
|
+
getNumber(key, fallback = 0) {
|
|
31
|
+
const val = this.payload?.config[key];
|
|
32
|
+
return typeof val === 'number' ? val : Number(val) || fallback;
|
|
33
|
+
}
|
|
34
|
+
getBool(key, fallback = false) {
|
|
35
|
+
const val = this.payload?.config[key];
|
|
36
|
+
if (typeof val === 'boolean')
|
|
37
|
+
return val;
|
|
38
|
+
return val === 'true' ? true : fallback;
|
|
39
|
+
}
|
|
40
|
+
checkVersion(currentVersion) {
|
|
41
|
+
const policy = this.payload?.version;
|
|
42
|
+
if (!policy?.min_version) {
|
|
43
|
+
return { status: 'up_to_date', message: '', latestVersion: '' };
|
|
44
|
+
}
|
|
45
|
+
const current = this.parseVersion(currentVersion);
|
|
46
|
+
const min = this.parseVersion(policy.min_version);
|
|
47
|
+
const latest = this.parseVersion(policy.latest_version);
|
|
48
|
+
if (current < min) {
|
|
49
|
+
return {
|
|
50
|
+
status: 'force_update',
|
|
51
|
+
message: policy.update_message,
|
|
52
|
+
latestVersion: policy.latest_version,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (policy.latest_version && current < latest) {
|
|
56
|
+
return {
|
|
57
|
+
status: policy.force_update ? 'force_update' : 'soft_update',
|
|
58
|
+
message: policy.update_message,
|
|
59
|
+
latestVersion: policy.latest_version,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return { status: 'up_to_date', message: '', latestVersion: policy.latest_version };
|
|
63
|
+
}
|
|
64
|
+
parseVersion(v) {
|
|
65
|
+
const parts = v.split('.').map(Number);
|
|
66
|
+
return (parts[0] ?? 0) * 10000 + (parts[1] ?? 0) * 100 + (parts[2] ?? 0);
|
|
67
|
+
}
|
|
68
|
+
stableHash(s) {
|
|
69
|
+
let hash = 0;
|
|
70
|
+
for (let i = 0; i < s.length; i++) {
|
|
71
|
+
hash = (Math.imul(31, hash) + s.charCodeAt(i)) | 0;
|
|
72
|
+
}
|
|
73
|
+
return Math.abs(hash);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.KoolbaseFlags = KoolbaseFlags;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { KoolbaseConfig, FunctionInvokeResult, DeployOptions, DeployResult } from './types';
|
|
2
|
+
export declare class KoolbaseFunctions {
|
|
3
|
+
private config;
|
|
4
|
+
constructor(config: KoolbaseConfig);
|
|
5
|
+
deploy(options: DeployOptions): Promise<DeployResult>;
|
|
6
|
+
invoke(name: string, body?: Record<string, unknown>): Promise<FunctionInvokeResult>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KoolbaseFunctions = void 0;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
class KoolbaseFunctions {
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.config = config;
|
|
8
|
+
}
|
|
9
|
+
// ─── Deploy ────────────────────────────────────────────────────────────────
|
|
10
|
+
async deploy(options) {
|
|
11
|
+
const runtime = options.runtime ?? types_1.FunctionRuntime.Deno;
|
|
12
|
+
const res = await fetch(`${this.config.baseUrl}/v1/sdk/functions/deploy`, {
|
|
13
|
+
method: 'POST',
|
|
14
|
+
headers: {
|
|
15
|
+
'Content-Type': 'application/json',
|
|
16
|
+
'x-api-key': this.config.publicKey,
|
|
17
|
+
},
|
|
18
|
+
body: JSON.stringify({
|
|
19
|
+
name: options.name,
|
|
20
|
+
code: options.code,
|
|
21
|
+
runtime,
|
|
22
|
+
timeout_ms: options.timeoutMs ?? 10000,
|
|
23
|
+
}),
|
|
24
|
+
});
|
|
25
|
+
const data = await res.json().catch(() => null);
|
|
26
|
+
if (!res.ok) {
|
|
27
|
+
throw new Error(data?.error ??
|
|
28
|
+
'Function deploy failed');
|
|
29
|
+
}
|
|
30
|
+
const d = data;
|
|
31
|
+
return {
|
|
32
|
+
id: d.id,
|
|
33
|
+
name: d.name,
|
|
34
|
+
runtime: d.runtime,
|
|
35
|
+
version: d.version,
|
|
36
|
+
isActive: d.is_active,
|
|
37
|
+
timeoutMs: d.timeout_ms,
|
|
38
|
+
lastDeployedAt: d.last_deployed_at,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
// ─── Invoke ────────────────────────────────────────────────────────────────
|
|
42
|
+
async invoke(name, body) {
|
|
43
|
+
const res = await fetch(`${this.config.baseUrl}/v1/sdk/functions/${name}`, {
|
|
44
|
+
method: 'POST',
|
|
45
|
+
headers: {
|
|
46
|
+
'Content-Type': 'application/json',
|
|
47
|
+
'x-api-key': this.config.publicKey,
|
|
48
|
+
},
|
|
49
|
+
body: JSON.stringify({ body: body ?? {} }),
|
|
50
|
+
});
|
|
51
|
+
const data = await res.json().catch(() => null);
|
|
52
|
+
const success = res.status >= 200 && res.status < 300;
|
|
53
|
+
if (!success) {
|
|
54
|
+
throw new Error(data?.error ??
|
|
55
|
+
'Function invocation failed');
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
statusCode: res.status,
|
|
59
|
+
data: data,
|
|
60
|
+
success,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.KoolbaseFunctions = KoolbaseFunctions;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { KoolbaseAuth } from './auth';
|
|
2
|
+
import { KoolbaseCodePush } from './code-push';
|
|
3
|
+
import { KoolbaseAnalytics } from './analytics';
|
|
4
|
+
import { KoolbaseMessaging } from './messaging';
|
|
5
|
+
export { KoolbaseMessaging } from './messaging';
|
|
6
|
+
export { KoolbaseAppleAuth } from './apple-auth';
|
|
7
|
+
export type { RegisterTokenOptions, SendOptions } from './messaging';
|
|
8
|
+
import { FlowResult } from './logic-engine';
|
|
9
|
+
export { KoolbaseAnalytics } from './analytics';
|
|
10
|
+
export type { FlowResult } from './logic-engine';
|
|
11
|
+
export { KoolbaseCodePush } from './code-push';
|
|
12
|
+
export type { BundleManifest, BundlePayload } from './code-push';
|
|
13
|
+
import { KoolbaseDatabase } from './database';
|
|
14
|
+
import { KoolbaseFlags } from './flags';
|
|
15
|
+
import { KoolbaseFunctions } from './functions';
|
|
16
|
+
import { KoolbaseRealtime } from './realtime';
|
|
17
|
+
import { KoolbaseStorage } from './storage';
|
|
18
|
+
import { KoolbaseConfig, VersionCheckResult } from './types';
|
|
19
|
+
export * from './types';
|
|
20
|
+
export { KoolbaseAuth, KoolbaseDatabase, KoolbaseFlags, KoolbaseFunctions, KoolbaseRealtime, KoolbaseStorage };
|
|
21
|
+
export declare const Koolbase: {
|
|
22
|
+
initialize(config: KoolbaseConfig): Promise<void>;
|
|
23
|
+
readonly auth: KoolbaseAuth;
|
|
24
|
+
readonly db: KoolbaseDatabase;
|
|
25
|
+
readonly storage: KoolbaseStorage;
|
|
26
|
+
readonly realtime: KoolbaseRealtime;
|
|
27
|
+
readonly functions: KoolbaseFunctions;
|
|
28
|
+
isEnabled(key: string): boolean;
|
|
29
|
+
configString(key: string, fallback?: string): string;
|
|
30
|
+
configNumber(key: string, fallback?: number): number;
|
|
31
|
+
configBool(key: string, fallback?: boolean): boolean;
|
|
32
|
+
readonly codePush: KoolbaseCodePush;
|
|
33
|
+
readonly analytics: KoolbaseAnalytics;
|
|
34
|
+
executeFlow(flowId: string, context?: Record<string, unknown>): FlowResult;
|
|
35
|
+
readonly messaging: KoolbaseMessaging;
|
|
36
|
+
checkVersion(currentVersion: string): VersionCheckResult;
|
|
37
|
+
};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.Koolbase = exports.KoolbaseStorage = exports.KoolbaseRealtime = exports.KoolbaseFunctions = exports.KoolbaseFlags = exports.KoolbaseDatabase = exports.KoolbaseAuth = exports.KoolbaseCodePush = exports.KoolbaseAnalytics = exports.KoolbaseAppleAuth = exports.KoolbaseMessaging = void 0;
|
|
21
|
+
const async_storage_1 = __importDefault(require("@react-native-async-storage/async-storage"));
|
|
22
|
+
const auth_1 = require("./auth");
|
|
23
|
+
Object.defineProperty(exports, "KoolbaseAuth", { enumerable: true, get: function () { return auth_1.KoolbaseAuth; } });
|
|
24
|
+
const code_push_1 = require("./code-push");
|
|
25
|
+
const analytics_1 = require("./analytics");
|
|
26
|
+
const messaging_1 = require("./messaging");
|
|
27
|
+
var messaging_2 = require("./messaging");
|
|
28
|
+
Object.defineProperty(exports, "KoolbaseMessaging", { enumerable: true, get: function () { return messaging_2.KoolbaseMessaging; } });
|
|
29
|
+
var apple_auth_1 = require("./apple-auth");
|
|
30
|
+
Object.defineProperty(exports, "KoolbaseAppleAuth", { enumerable: true, get: function () { return apple_auth_1.KoolbaseAppleAuth; } });
|
|
31
|
+
const logic_engine_1 = require("./logic-engine");
|
|
32
|
+
var analytics_2 = require("./analytics");
|
|
33
|
+
Object.defineProperty(exports, "KoolbaseAnalytics", { enumerable: true, get: function () { return analytics_2.KoolbaseAnalytics; } });
|
|
34
|
+
var code_push_2 = require("./code-push");
|
|
35
|
+
Object.defineProperty(exports, "KoolbaseCodePush", { enumerable: true, get: function () { return code_push_2.KoolbaseCodePush; } });
|
|
36
|
+
const database_1 = require("./database");
|
|
37
|
+
Object.defineProperty(exports, "KoolbaseDatabase", { enumerable: true, get: function () { return database_1.KoolbaseDatabase; } });
|
|
38
|
+
const flags_1 = require("./flags");
|
|
39
|
+
Object.defineProperty(exports, "KoolbaseFlags", { enumerable: true, get: function () { return flags_1.KoolbaseFlags; } });
|
|
40
|
+
const functions_1 = require("./functions");
|
|
41
|
+
Object.defineProperty(exports, "KoolbaseFunctions", { enumerable: true, get: function () { return functions_1.KoolbaseFunctions; } });
|
|
42
|
+
const realtime_1 = require("./realtime");
|
|
43
|
+
Object.defineProperty(exports, "KoolbaseRealtime", { enumerable: true, get: function () { return realtime_1.KoolbaseRealtime; } });
|
|
44
|
+
const storage_1 = require("./storage");
|
|
45
|
+
Object.defineProperty(exports, "KoolbaseStorage", { enumerable: true, get: function () { return storage_1.KoolbaseStorage; } });
|
|
46
|
+
__exportStar(require("./types"), exports);
|
|
47
|
+
let _auth = null;
|
|
48
|
+
let _db = null;
|
|
49
|
+
let _storage = null;
|
|
50
|
+
let _realtime = null;
|
|
51
|
+
let _functions = null;
|
|
52
|
+
let _flags = null;
|
|
53
|
+
let _codePush = null;
|
|
54
|
+
let _analytics = null;
|
|
55
|
+
let _messaging = null;
|
|
56
|
+
const _logicEngine = new logic_engine_1.KoolbaseLogicEngine();
|
|
57
|
+
let _initialized = false;
|
|
58
|
+
function ensureInitialized() {
|
|
59
|
+
if (!_initialized) {
|
|
60
|
+
throw new Error('Koolbase not initialized. Call Koolbase.initialize() first.');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.Koolbase = {
|
|
64
|
+
async initialize(config) {
|
|
65
|
+
if (_initialized)
|
|
66
|
+
return;
|
|
67
|
+
_auth = new auth_1.KoolbaseAuth(config);
|
|
68
|
+
_db = new database_1.KoolbaseDatabase(config, () => _auth?.currentUser?.id ?? null);
|
|
69
|
+
_storage = new storage_1.KoolbaseStorage(config, () => _auth?.accessToken ?? null);
|
|
70
|
+
_realtime = new realtime_1.KoolbaseRealtime(config);
|
|
71
|
+
_functions = new functions_1.KoolbaseFunctions(config);
|
|
72
|
+
_flags = new flags_1.KoolbaseFlags(config, 'rn-device');
|
|
73
|
+
_codePush = new code_push_1.KoolbaseCodePush(config, config.codePushChannel ?? 'stable');
|
|
74
|
+
// Initialize code push — loads cached bundle then checks in background
|
|
75
|
+
await _codePush.init({
|
|
76
|
+
appVersion: '1.0.0', // override with your app version
|
|
77
|
+
platform: 'react-native',
|
|
78
|
+
deviceId: 'rn-device',
|
|
79
|
+
});
|
|
80
|
+
// Initialize analytics
|
|
81
|
+
if (config.analyticsEnabled !== false) {
|
|
82
|
+
_analytics = new analytics_1.KoolbaseAnalytics(config);
|
|
83
|
+
await _analytics.init(config.appVersion);
|
|
84
|
+
}
|
|
85
|
+
// Initialize messaging
|
|
86
|
+
if (config.messagingEnabled !== false) {
|
|
87
|
+
_messaging = new messaging_1.KoolbaseMessaging(config);
|
|
88
|
+
const storedDeviceId = await async_storage_1.default.getItem('koolbase:device_id');
|
|
89
|
+
_messaging.setDeviceId(storedDeviceId ?? 'rn-device');
|
|
90
|
+
}
|
|
91
|
+
_initialized = true;
|
|
92
|
+
},
|
|
93
|
+
get auth() {
|
|
94
|
+
ensureInitialized();
|
|
95
|
+
return _auth;
|
|
96
|
+
},
|
|
97
|
+
get db() {
|
|
98
|
+
ensureInitialized();
|
|
99
|
+
return _db;
|
|
100
|
+
},
|
|
101
|
+
get storage() {
|
|
102
|
+
ensureInitialized();
|
|
103
|
+
return _storage;
|
|
104
|
+
},
|
|
105
|
+
get realtime() {
|
|
106
|
+
ensureInitialized();
|
|
107
|
+
return _realtime;
|
|
108
|
+
},
|
|
109
|
+
get functions() {
|
|
110
|
+
ensureInitialized();
|
|
111
|
+
return _functions;
|
|
112
|
+
},
|
|
113
|
+
isEnabled(key) {
|
|
114
|
+
ensureInitialized();
|
|
115
|
+
// Bundle flag wins over remote flag
|
|
116
|
+
const bundleFlag = _codePush?.getBundleFlag(key);
|
|
117
|
+
if (bundleFlag !== undefined)
|
|
118
|
+
return bundleFlag;
|
|
119
|
+
return _flags.isEnabled(key);
|
|
120
|
+
},
|
|
121
|
+
configString(key, fallback = '') {
|
|
122
|
+
ensureInitialized();
|
|
123
|
+
const bundleVal = _codePush?.getBundleConfig(key);
|
|
124
|
+
if (bundleVal !== undefined)
|
|
125
|
+
return String(bundleVal);
|
|
126
|
+
return _flags.getString(key, fallback);
|
|
127
|
+
},
|
|
128
|
+
configNumber(key, fallback = 0) {
|
|
129
|
+
ensureInitialized();
|
|
130
|
+
const bundleVal = _codePush?.getBundleConfig(key);
|
|
131
|
+
if (bundleVal !== undefined)
|
|
132
|
+
return typeof bundleVal === 'number' ? bundleVal : Number(bundleVal) || fallback;
|
|
133
|
+
return _flags.getNumber(key, fallback);
|
|
134
|
+
},
|
|
135
|
+
configBool(key, fallback = false) {
|
|
136
|
+
ensureInitialized();
|
|
137
|
+
const bundleVal = _codePush?.getBundleConfig(key);
|
|
138
|
+
if (bundleVal !== undefined)
|
|
139
|
+
return typeof bundleVal === 'boolean' ? bundleVal : bundleVal === 'true';
|
|
140
|
+
return _flags.getBool(key, fallback);
|
|
141
|
+
},
|
|
142
|
+
get codePush() {
|
|
143
|
+
ensureInitialized();
|
|
144
|
+
return _codePush;
|
|
145
|
+
},
|
|
146
|
+
get analytics() {
|
|
147
|
+
ensureInitialized();
|
|
148
|
+
return _analytics;
|
|
149
|
+
},
|
|
150
|
+
executeFlow(flowId, context) {
|
|
151
|
+
ensureInitialized();
|
|
152
|
+
const manifest = _codePush?.manifest;
|
|
153
|
+
if (!manifest)
|
|
154
|
+
return { hasEvent: false, args: {}, completed: true };
|
|
155
|
+
return _logicEngine.execute(flowId, manifest.payload.flows ?? {}, context ?? {}, manifest.payload.config ?? {}, manifest.payload.flags ?? {});
|
|
156
|
+
},
|
|
157
|
+
get messaging() {
|
|
158
|
+
ensureInitialized();
|
|
159
|
+
return _messaging;
|
|
160
|
+
},
|
|
161
|
+
checkVersion(currentVersion) {
|
|
162
|
+
ensureInitialized();
|
|
163
|
+
return _flags.checkVersion(currentVersion);
|
|
164
|
+
},
|
|
165
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface FlowResult {
|
|
2
|
+
hasEvent: boolean;
|
|
3
|
+
eventName?: string;
|
|
4
|
+
args: Record<string, unknown>;
|
|
5
|
+
completed: boolean;
|
|
6
|
+
error?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class KoolbaseLogicEngine {
|
|
9
|
+
execute(flowId: string, flows: Record<string, unknown>, context: Record<string, unknown>, config: Record<string, unknown>, flags: Record<string, boolean>): FlowResult;
|
|
10
|
+
private evalNode;
|
|
11
|
+
private evalIf;
|
|
12
|
+
private evalSequence;
|
|
13
|
+
private evalCondition;
|
|
14
|
+
private resolve;
|
|
15
|
+
private getNested;
|
|
16
|
+
private setNested;
|
|
17
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ─── Logic Engine ────────────────────────────────────────────────────────
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.KoolbaseLogicEngine = void 0;
|
|
5
|
+
class KoolbaseLogicEngine {
|
|
6
|
+
// ─── Public API ───────────────────────────────────────────────────────────
|
|
7
|
+
execute(flowId, flows, context, config, flags) {
|
|
8
|
+
try {
|
|
9
|
+
const flowJson = flows[flowId];
|
|
10
|
+
if (!flowJson) {
|
|
11
|
+
return { hasEvent: false, args: {}, completed: true };
|
|
12
|
+
}
|
|
13
|
+
const ctx = {
|
|
14
|
+
context: { ...context },
|
|
15
|
+
config,
|
|
16
|
+
flags,
|
|
17
|
+
};
|
|
18
|
+
return this.evalNode(flowJson, ctx);
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
return {
|
|
22
|
+
hasEvent: false,
|
|
23
|
+
args: {},
|
|
24
|
+
completed: false,
|
|
25
|
+
error: String(e),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// ─── Node evaluation ──────────────────────────────────────────────────────
|
|
30
|
+
evalNode(node, ctx) {
|
|
31
|
+
switch (node.type) {
|
|
32
|
+
case 'if':
|
|
33
|
+
return this.evalIf(node, ctx);
|
|
34
|
+
case 'sequence':
|
|
35
|
+
return this.evalSequence(node, ctx);
|
|
36
|
+
case 'event':
|
|
37
|
+
return { hasEvent: true, eventName: node.name, args: node.args ?? {}, completed: true };
|
|
38
|
+
case 'set':
|
|
39
|
+
this.setNested(ctx.context, node.key, node.value);
|
|
40
|
+
return { hasEvent: false, args: {}, completed: true };
|
|
41
|
+
default:
|
|
42
|
+
return { hasEvent: false, args: {}, completed: true };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
evalIf(node, ctx) {
|
|
46
|
+
const result = this.evalCondition(node.condition, ctx);
|
|
47
|
+
if (result)
|
|
48
|
+
return this.evalNode(node.then, ctx);
|
|
49
|
+
if (node.else)
|
|
50
|
+
return this.evalNode(node.else, ctx);
|
|
51
|
+
return { hasEvent: false, args: {}, completed: true };
|
|
52
|
+
}
|
|
53
|
+
evalSequence(node, ctx) {
|
|
54
|
+
for (const step of node.steps) {
|
|
55
|
+
const result = this.evalNode(step, ctx);
|
|
56
|
+
if (result.hasEvent)
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
return { hasEvent: false, args: {}, completed: true };
|
|
60
|
+
}
|
|
61
|
+
// ─── Condition evaluation ─────────────────────────────────────────────────
|
|
62
|
+
evalCondition(condition, ctx) {
|
|
63
|
+
switch (condition.op) {
|
|
64
|
+
case 'eq': {
|
|
65
|
+
const left = condition.left ? this.resolve(condition.left.from, ctx) : undefined;
|
|
66
|
+
return String(left) === String(condition.right);
|
|
67
|
+
}
|
|
68
|
+
case 'neq': {
|
|
69
|
+
const left = condition.left ? this.resolve(condition.left.from, ctx) : undefined;
|
|
70
|
+
return String(left) !== String(condition.right);
|
|
71
|
+
}
|
|
72
|
+
case 'gt': {
|
|
73
|
+
const left = Number(condition.left ? this.resolve(condition.left.from, ctx) : undefined);
|
|
74
|
+
const right = Number(condition.right);
|
|
75
|
+
return !isNaN(left) && !isNaN(right) && left > right;
|
|
76
|
+
}
|
|
77
|
+
case 'lt': {
|
|
78
|
+
const left = Number(condition.left ? this.resolve(condition.left.from, ctx) : undefined);
|
|
79
|
+
const right = Number(condition.right);
|
|
80
|
+
return !isNaN(left) && !isNaN(right) && left < right;
|
|
81
|
+
}
|
|
82
|
+
case 'and':
|
|
83
|
+
return (condition.conditions ?? []).every((c) => this.evalCondition(c, ctx));
|
|
84
|
+
case 'or':
|
|
85
|
+
return (condition.conditions ?? []).some((c) => this.evalCondition(c, ctx));
|
|
86
|
+
case 'exists': {
|
|
87
|
+
const val = condition.value ? this.resolve(condition.value.from, ctx) : undefined;
|
|
88
|
+
return val !== null && val !== undefined;
|
|
89
|
+
}
|
|
90
|
+
case 'not_exists': {
|
|
91
|
+
const val = condition.value ? this.resolve(condition.value.from, ctx) : undefined;
|
|
92
|
+
return val === null || val === undefined;
|
|
93
|
+
}
|
|
94
|
+
case 'gte': {
|
|
95
|
+
const left = Number(condition.left ? this.resolve(condition.left.from, ctx) : undefined);
|
|
96
|
+
const right = Number(condition.right);
|
|
97
|
+
return !isNaN(left) && !isNaN(right) && left >= right;
|
|
98
|
+
}
|
|
99
|
+
case 'lte': {
|
|
100
|
+
const left = Number(condition.left ? this.resolve(condition.left.from, ctx) : undefined);
|
|
101
|
+
const right = Number(condition.right);
|
|
102
|
+
return !isNaN(left) && !isNaN(right) && left <= right;
|
|
103
|
+
}
|
|
104
|
+
case 'contains': {
|
|
105
|
+
const left = condition.left ? this.resolve(condition.left.from, ctx) : undefined;
|
|
106
|
+
const right = condition.right;
|
|
107
|
+
if (typeof left === 'string' && typeof right === 'string')
|
|
108
|
+
return left.includes(right);
|
|
109
|
+
if (Array.isArray(left))
|
|
110
|
+
return left.includes(right);
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
case 'starts_with': {
|
|
114
|
+
const left = condition.left ? this.resolve(condition.left.from, ctx) : undefined;
|
|
115
|
+
const right = String(condition.right ?? '');
|
|
116
|
+
return typeof left === 'string' && left.startsWith(right);
|
|
117
|
+
}
|
|
118
|
+
case 'ends_with': {
|
|
119
|
+
const left = condition.left ? this.resolve(condition.left.from, ctx) : undefined;
|
|
120
|
+
const right = String(condition.right ?? '');
|
|
121
|
+
return typeof left === 'string' && left.endsWith(right);
|
|
122
|
+
}
|
|
123
|
+
case 'in_list': {
|
|
124
|
+
const left = condition.left ? this.resolve(condition.left.from, ctx) : undefined;
|
|
125
|
+
const list = condition.right;
|
|
126
|
+
if (!Array.isArray(list))
|
|
127
|
+
return false;
|
|
128
|
+
return list.some((item) => String(item) === String(left));
|
|
129
|
+
}
|
|
130
|
+
case 'not_in_list': {
|
|
131
|
+
const left = condition.left ? this.resolve(condition.left.from, ctx) : undefined;
|
|
132
|
+
const list = condition.right;
|
|
133
|
+
if (!Array.isArray(list))
|
|
134
|
+
return true;
|
|
135
|
+
return !list.some((item) => String(item) === String(left));
|
|
136
|
+
}
|
|
137
|
+
case 'between': {
|
|
138
|
+
const left = Number(condition.left ? this.resolve(condition.left.from, ctx) : undefined);
|
|
139
|
+
const range = condition.right;
|
|
140
|
+
if (!Array.isArray(range) || range.length < 2)
|
|
141
|
+
return false;
|
|
142
|
+
const min = Number(range[0]);
|
|
143
|
+
const max = Number(range[1]);
|
|
144
|
+
return !isNaN(left) && !isNaN(min) && !isNaN(max) && left >= min && left <= max;
|
|
145
|
+
}
|
|
146
|
+
case 'is_true': {
|
|
147
|
+
const left = condition.left ? this.resolve(condition.left.from, ctx) : undefined;
|
|
148
|
+
return left === true || left === 'true';
|
|
149
|
+
}
|
|
150
|
+
case 'is_false': {
|
|
151
|
+
const left = condition.left ? this.resolve(condition.left.from, ctx) : undefined;
|
|
152
|
+
return left === false || left === 'false';
|
|
153
|
+
}
|
|
154
|
+
default:
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// ─── Data resolution ──────────────────────────────────────────────────────
|
|
159
|
+
resolve(from, ctx) {
|
|
160
|
+
const dotIdx = from.indexOf('.');
|
|
161
|
+
if (dotIdx === -1)
|
|
162
|
+
return undefined;
|
|
163
|
+
const source = from.substring(0, dotIdx);
|
|
164
|
+
const key = from.substring(dotIdx + 1);
|
|
165
|
+
switch (source) {
|
|
166
|
+
case 'context': return this.getNested(ctx.context, key);
|
|
167
|
+
case 'config': return this.getNested(ctx.config, key);
|
|
168
|
+
case 'flags': return ctx.flags[key];
|
|
169
|
+
default: return undefined;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
getNested(obj, key) {
|
|
173
|
+
const parts = key.split('.');
|
|
174
|
+
let current = obj;
|
|
175
|
+
for (const part of parts) {
|
|
176
|
+
if (current == null || typeof current !== 'object')
|
|
177
|
+
return undefined;
|
|
178
|
+
current = current[part];
|
|
179
|
+
}
|
|
180
|
+
return current;
|
|
181
|
+
}
|
|
182
|
+
setNested(obj, key, value) {
|
|
183
|
+
const parts = key.split('.');
|
|
184
|
+
let current = obj;
|
|
185
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
186
|
+
if (!(parts[i] in current))
|
|
187
|
+
current[parts[i]] = {};
|
|
188
|
+
current = current[parts[i]];
|
|
189
|
+
}
|
|
190
|
+
current[parts[parts.length - 1]] = value;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
exports.KoolbaseLogicEngine = KoolbaseLogicEngine;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { KoolbaseConfig } from './types';
|
|
2
|
+
export interface RegisterTokenOptions {
|
|
3
|
+
token: string;
|
|
4
|
+
platform: 'android' | 'ios';
|
|
5
|
+
userId?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface SendOptions {
|
|
8
|
+
to: string;
|
|
9
|
+
title: string;
|
|
10
|
+
body: string;
|
|
11
|
+
data?: Record<string, unknown>;
|
|
12
|
+
}
|
|
13
|
+
export declare class KoolbaseMessaging {
|
|
14
|
+
private config;
|
|
15
|
+
private deviceId;
|
|
16
|
+
constructor(config: KoolbaseConfig);
|
|
17
|
+
setDeviceId(deviceId: string): void;
|
|
18
|
+
registerToken(options: RegisterTokenOptions): Promise<boolean>;
|
|
19
|
+
send(options: SendOptions): Promise<boolean>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KoolbaseMessaging = void 0;
|
|
4
|
+
// ─── KoolbaseMessaging ────────────────────────────────────────────────────────
|
|
5
|
+
class KoolbaseMessaging {
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.deviceId = '';
|
|
8
|
+
this.config = config;
|
|
9
|
+
}
|
|
10
|
+
setDeviceId(deviceId) {
|
|
11
|
+
this.deviceId = deviceId;
|
|
12
|
+
}
|
|
13
|
+
// ─── Register token ───────────────────────────────────────────────────────
|
|
14
|
+
async registerToken(options) {
|
|
15
|
+
try {
|
|
16
|
+
const response = await fetch(`${this.config.baseUrl}/v1/messaging/register`, {
|
|
17
|
+
method: 'POST',
|
|
18
|
+
headers: {
|
|
19
|
+
'Content-Type': 'application/json',
|
|
20
|
+
'x-api-key': this.config.publicKey,
|
|
21
|
+
},
|
|
22
|
+
body: JSON.stringify({
|
|
23
|
+
device_id: this.deviceId,
|
|
24
|
+
token: options.token,
|
|
25
|
+
platform: options.platform,
|
|
26
|
+
...(options.userId && { user_id: options.userId }),
|
|
27
|
+
}),
|
|
28
|
+
});
|
|
29
|
+
return response.ok;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// ─── Send notification ────────────────────────────────────────────────────
|
|
36
|
+
async send(options) {
|
|
37
|
+
try {
|
|
38
|
+
const response = await fetch(`${this.config.baseUrl}/v1/messaging/send`, {
|
|
39
|
+
method: 'POST',
|
|
40
|
+
headers: {
|
|
41
|
+
'Content-Type': 'application/json',
|
|
42
|
+
'x-api-key': this.config.publicKey,
|
|
43
|
+
},
|
|
44
|
+
body: JSON.stringify({
|
|
45
|
+
token: options.to,
|
|
46
|
+
title: options.title,
|
|
47
|
+
body: options.body,
|
|
48
|
+
data: options.data ?? {},
|
|
49
|
+
}),
|
|
50
|
+
});
|
|
51
|
+
return response.ok;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.KoolbaseMessaging = KoolbaseMessaging;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { KoolbaseConfig, RealtimeCallback } from './types';
|
|
2
|
+
export declare class KoolbaseRealtime {
|
|
3
|
+
private config;
|
|
4
|
+
private ws;
|
|
5
|
+
private listeners;
|
|
6
|
+
private reconnectTimer;
|
|
7
|
+
constructor(config: KoolbaseConfig);
|
|
8
|
+
subscribe(collection: string, callback: RealtimeCallback): () => void;
|
|
9
|
+
private connect;
|
|
10
|
+
disconnect(): void;
|
|
11
|
+
}
|