joopjs 2.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 +678 -0
- package/README.md +583 -0
- package/dist/a11y.service-C-DQQfgO.d.mts +143 -0
- package/dist/a11y.service-CauEJrJe.d.ts +143 -0
- package/dist/adapters-B6slG6hQ.d.mts +84 -0
- package/dist/adapters-B6slG6hQ.d.ts +84 -0
- package/dist/aes.service-CkoupAww.d.mts +95 -0
- package/dist/aes.service-CkoupAww.d.ts +95 -0
- package/dist/ai/index.d.mts +99 -0
- package/dist/ai/index.d.ts +99 -0
- package/dist/ai/index.js +307 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/index.mjs +304 -0
- package/dist/ai/index.mjs.map +1 -0
- package/dist/analytics/index.d.mts +42 -0
- package/dist/analytics/index.d.ts +42 -0
- package/dist/analytics/index.js +139 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics/index.mjs +136 -0
- package/dist/analytics/index.mjs.map +1 -0
- package/dist/angular/index.d.mts +148 -0
- package/dist/angular/index.d.ts +148 -0
- package/dist/angular/index.js +122 -0
- package/dist/angular/index.js.map +1 -0
- package/dist/angular/index.mjs +101 -0
- package/dist/angular/index.mjs.map +1 -0
- package/dist/api/index.d.mts +128 -0
- package/dist/api/index.d.ts +128 -0
- package/dist/api/index.js +1358 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/index.mjs +1332 -0
- package/dist/api/index.mjs.map +1 -0
- package/dist/auth/index.d.mts +105 -0
- package/dist/auth/index.d.ts +105 -0
- package/dist/auth/index.js +989 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +979 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/auth.service-DNVB-L4U.d.mts +16 -0
- package/dist/auth.service-PjUUSUIt.d.ts +16 -0
- package/dist/banking/index.d.mts +1530 -0
- package/dist/banking/index.d.ts +1530 -0
- package/dist/banking/index.js +4739 -0
- package/dist/banking/index.js.map +1 -0
- package/dist/banking/index.mjs +4661 -0
- package/dist/banking/index.mjs.map +1 -0
- package/dist/cache/index.d.mts +40 -0
- package/dist/cache/index.d.ts +40 -0
- package/dist/cache/index.js +174 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/index.mjs +172 -0
- package/dist/cache/index.mjs.map +1 -0
- package/dist/client-profile.service-BuPeXVp5.d.mts +28 -0
- package/dist/client-profile.service-D5bRRYQp.d.ts +28 -0
- package/dist/config.models-Cqg04fAQ.d.mts +84 -0
- package/dist/config.models-Cqg04fAQ.d.ts +84 -0
- package/dist/config.service-CrCvI-JS.d.ts +31 -0
- package/dist/config.service-Cz4QQLlf.d.mts +31 -0
- package/dist/core/index.d.mts +4 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.js +631 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/index.mjs +619 -0
- package/dist/core/index.mjs.map +1 -0
- package/dist/crypto-utils-DriNhLdx.d.mts +30 -0
- package/dist/crypto-utils-DriNhLdx.d.ts +30 -0
- package/dist/data-storage.service-DT6xaTxE.d.ts +51 -0
- package/dist/data-storage.service-LvhGRCmw.d.mts +51 -0
- package/dist/deeplink/index.d.mts +39 -0
- package/dist/deeplink/index.d.ts +39 -0
- package/dist/deeplink/index.js +268 -0
- package/dist/deeplink/index.js.map +1 -0
- package/dist/deeplink/index.mjs +265 -0
- package/dist/deeplink/index.mjs.map +1 -0
- package/dist/deeplink.service-Ctd5u243.d.mts +35 -0
- package/dist/deeplink.service-uUuTnY9_.d.ts +35 -0
- package/dist/dev/index.d.mts +20 -0
- package/dist/dev/index.d.ts +20 -0
- package/dist/dev/index.js +51 -0
- package/dist/dev/index.js.map +1 -0
- package/dist/dev/index.mjs +49 -0
- package/dist/dev/index.mjs.map +1 -0
- package/dist/device/index.d.mts +108 -0
- package/dist/device/index.d.ts +108 -0
- package/dist/device/index.js +960 -0
- package/dist/device/index.js.map +1 -0
- package/dist/device/index.mjs +951 -0
- package/dist/device/index.mjs.map +1 -0
- package/dist/differential-privacy-BcAv1G80.d.mts +210 -0
- package/dist/differential-privacy-C8mAUjZr.d.ts +210 -0
- package/dist/encryption/index.d.mts +75 -0
- package/dist/encryption/index.d.ts +75 -0
- package/dist/encryption/index.js +605 -0
- package/dist/encryption/index.js.map +1 -0
- package/dist/encryption/index.mjs +598 -0
- package/dist/encryption/index.mjs.map +1 -0
- package/dist/form-validator-3tkmzr_o.d.mts +72 -0
- package/dist/form-validator-3tkmzr_o.d.ts +72 -0
- package/dist/forms/index.d.mts +59 -0
- package/dist/forms/index.d.ts +59 -0
- package/dist/forms/index.js +446 -0
- package/dist/forms/index.js.map +1 -0
- package/dist/forms/index.mjs +442 -0
- package/dist/forms/index.mjs.map +1 -0
- package/dist/i18n/index.d.mts +37 -0
- package/dist/i18n/index.d.ts +37 -0
- package/dist/i18n/index.js +147 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/index.mjs +145 -0
- package/dist/i18n/index.mjs.map +1 -0
- package/dist/idempotency.service-_6LqhivP.d.mts +372 -0
- package/dist/idempotency.service-eOKoISRD.d.ts +372 -0
- package/dist/index-B_ksKpS1.d.mts +202 -0
- package/dist/index-CqDKWTUP.d.mts +28 -0
- package/dist/index-CqDKWTUP.d.ts +28 -0
- package/dist/index-DFqEoX_l.d.ts +202 -0
- package/dist/index-Dz0gOur2.d.mts +36 -0
- package/dist/index-Dz0gOur2.d.ts +36 -0
- package/dist/index.d.mts +1336 -0
- package/dist/index.d.ts +1336 -0
- package/dist/index.js +19464 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +19155 -0
- package/dist/index.mjs.map +1 -0
- package/dist/india/index.d.mts +75 -0
- package/dist/india/index.d.ts +75 -0
- package/dist/india/index.js +325 -0
- package/dist/india/index.js.map +1 -0
- package/dist/india/index.mjs +303 -0
- package/dist/india/index.mjs.map +1 -0
- package/dist/joop-Bx7Iwj5p.d.mts +155 -0
- package/dist/joop-CA3DMeOO.d.ts +155 -0
- package/dist/native-bridge/index.d.mts +27 -0
- package/dist/native-bridge/index.d.ts +27 -0
- package/dist/native-bridge/index.js +98 -0
- package/dist/native-bridge/index.js.map +1 -0
- package/dist/native-bridge/index.mjs +96 -0
- package/dist/native-bridge/index.mjs.map +1 -0
- package/dist/network/index.d.mts +85 -0
- package/dist/network/index.d.ts +85 -0
- package/dist/network/index.js +454 -0
- package/dist/network/index.js.map +1 -0
- package/dist/network/index.mjs +451 -0
- package/dist/network/index.mjs.map +1 -0
- package/dist/network-monitor-BIwPSXme.d.mts +179 -0
- package/dist/network-monitor-Bqp2hvZr.d.ts +179 -0
- package/dist/notification.service-Dm4fvfZf.d.mts +25 -0
- package/dist/notification.service-tEMKatWJ.d.ts +25 -0
- package/dist/observability/index.d.mts +179 -0
- package/dist/observability/index.d.ts +179 -0
- package/dist/observability/index.js +559 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/index.mjs +552 -0
- package/dist/observability/index.mjs.map +1 -0
- package/dist/oidc-client-DIJcClmB.d.mts +190 -0
- package/dist/oidc-client-DxhyE59t.d.ts +190 -0
- package/dist/platform/index.d.mts +73 -0
- package/dist/platform/index.d.ts +73 -0
- package/dist/platform/index.js +127 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/index.mjs +125 -0
- package/dist/platform/index.mjs.map +1 -0
- package/dist/pwa/index.d.mts +31 -0
- package/dist/pwa/index.d.ts +31 -0
- package/dist/pwa/index.js +247 -0
- package/dist/pwa/index.js.map +1 -0
- package/dist/pwa/index.mjs +244 -0
- package/dist/pwa/index.mjs.map +1 -0
- package/dist/react/index.d.mts +133 -0
- package/dist/react/index.d.ts +133 -0
- package/dist/react/index.js +632 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +630 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/router/index.d.mts +39 -0
- package/dist/router/index.d.ts +39 -0
- package/dist/router/index.js +168 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/index.mjs +166 -0
- package/dist/router/index.mjs.map +1 -0
- package/dist/security/index.d.mts +206 -0
- package/dist/security/index.d.ts +206 -0
- package/dist/security/index.js +1297 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/index.mjs +1285 -0
- package/dist/security/index.mjs.map +1 -0
- package/dist/session/index.d.mts +115 -0
- package/dist/session/index.d.ts +115 -0
- package/dist/session/index.js +297 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/index.mjs +292 -0
- package/dist/session/index.mjs.map +1 -0
- package/dist/state/index.d.mts +43 -0
- package/dist/state/index.d.ts +43 -0
- package/dist/state/index.js +156 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/index.mjs +152 -0
- package/dist/state/index.mjs.map +1 -0
- package/dist/statement-parser-BHQtXwCM.d.ts +260 -0
- package/dist/statement-parser-C2qNmb49.d.mts +260 -0
- package/dist/storage/index.d.mts +40 -0
- package/dist/storage/index.d.ts +40 -0
- package/dist/storage/index.js +256 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/index.mjs +252 -0
- package/dist/storage/index.mjs.map +1 -0
- package/dist/sync/index.d.mts +69 -0
- package/dist/sync/index.d.ts +69 -0
- package/dist/sync/index.js +330 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/index.mjs +323 -0
- package/dist/sync/index.mjs.map +1 -0
- package/dist/sync-engine-DCIMRG5s.d.ts +61 -0
- package/dist/sync-engine-DZqyKHkK.d.mts +61 -0
- package/dist/theme/index.d.mts +53 -0
- package/dist/theme/index.d.ts +53 -0
- package/dist/theme/index.js +169 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/index.mjs +167 -0
- package/dist/theme/index.mjs.map +1 -0
- package/dist/ui/index.d.mts +66 -0
- package/dist/ui/index.d.ts +66 -0
- package/dist/ui/index.js +811 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/index.mjs +803 -0
- package/dist/ui/index.mjs.map +1 -0
- package/dist/utilities/index.d.mts +199 -0
- package/dist/utilities/index.d.ts +199 -0
- package/dist/utilities/index.js +1991 -0
- package/dist/utilities/index.js.map +1 -0
- package/dist/utilities/index.mjs +1923 -0
- package/dist/utilities/index.mjs.map +1 -0
- package/dist/validation/index.d.mts +60 -0
- package/dist/validation/index.d.ts +60 -0
- package/dist/validation/index.js +460 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/index.mjs +455 -0
- package/dist/validation/index.mjs.map +1 -0
- package/dist/vue/index.d.mts +135 -0
- package/dist/vue/index.d.ts +135 -0
- package/dist/vue/index.js +621 -0
- package/dist/vue/index.js.map +1 -0
- package/dist/vue/index.mjs +619 -0
- package/dist/vue/index.mjs.map +1 -0
- package/dist/watermark.service-Detur5tq.d.ts +235 -0
- package/dist/watermark.service-QNegMeQZ.d.mts +235 -0
- package/dist/workers/index.d.mts +42 -0
- package/dist/workers/index.d.ts +42 -0
- package/dist/workers/index.js +359 -0
- package/dist/workers/index.js.map +1 -0
- package/dist/workers/index.mjs +356 -0
- package/dist/workers/index.mjs.map +1 -0
- package/dist/workflow/index.d.mts +99 -0
- package/dist/workflow/index.d.ts +99 -0
- package/dist/workflow/index.js +282 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow/index.mjs +279 -0
- package/dist/workflow/index.mjs.map +1 -0
- package/package.json +226 -0
|
@@ -0,0 +1,630 @@
|
|
|
1
|
+
// src/events/index.ts
|
|
2
|
+
var JoopSubject = class {
|
|
3
|
+
_listeners = [];
|
|
4
|
+
subscribe(listener) {
|
|
5
|
+
this._listeners.push(listener);
|
|
6
|
+
return () => {
|
|
7
|
+
this._listeners = this._listeners.filter((l) => l !== listener);
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
next(value) {
|
|
11
|
+
for (const listener of this._listeners) {
|
|
12
|
+
listener(value);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
asObservable() {
|
|
16
|
+
return new JoopObservable((listener) => this.subscribe(listener));
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
var JoopBehaviorSubject = class extends JoopSubject {
|
|
20
|
+
_value;
|
|
21
|
+
constructor(initialValue) {
|
|
22
|
+
super();
|
|
23
|
+
this._value = initialValue;
|
|
24
|
+
}
|
|
25
|
+
getValue() {
|
|
26
|
+
return this._value;
|
|
27
|
+
}
|
|
28
|
+
next(value) {
|
|
29
|
+
this._value = value;
|
|
30
|
+
super.next(value);
|
|
31
|
+
}
|
|
32
|
+
subscribe(listener) {
|
|
33
|
+
listener(this._value);
|
|
34
|
+
return super.subscribe(listener);
|
|
35
|
+
}
|
|
36
|
+
asObservable() {
|
|
37
|
+
return new JoopObservable((listener) => this.subscribe(listener));
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var JoopObservable = class {
|
|
41
|
+
constructor(_subscribeFn) {
|
|
42
|
+
this._subscribeFn = _subscribeFn;
|
|
43
|
+
}
|
|
44
|
+
_subscribeFn;
|
|
45
|
+
subscribe(listener) {
|
|
46
|
+
return this._subscribeFn(listener);
|
|
47
|
+
}
|
|
48
|
+
/** Returns the current value without subscribing (only meaningful for BehaviorSubject-backed observables). */
|
|
49
|
+
getOnce() {
|
|
50
|
+
let result;
|
|
51
|
+
const unsub = this.subscribe((v) => {
|
|
52
|
+
result = v;
|
|
53
|
+
});
|
|
54
|
+
unsub();
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// src/platform/platform.ts
|
|
60
|
+
var _webStorage = (store) => ({
|
|
61
|
+
getItem: (k) => store.getItem(k),
|
|
62
|
+
setItem: (k, v) => store.setItem(k, v),
|
|
63
|
+
removeItem: (k) => store.removeItem(k),
|
|
64
|
+
clear: () => store.clear()
|
|
65
|
+
});
|
|
66
|
+
var _MemStorageImpl = class {
|
|
67
|
+
_m = /* @__PURE__ */ new Map();
|
|
68
|
+
getItem(k) {
|
|
69
|
+
return this._m.get(k) ?? null;
|
|
70
|
+
}
|
|
71
|
+
setItem(k, v) {
|
|
72
|
+
this._m.set(k, v);
|
|
73
|
+
}
|
|
74
|
+
removeItem(k) {
|
|
75
|
+
this._m.delete(k);
|
|
76
|
+
}
|
|
77
|
+
clear() {
|
|
78
|
+
this._m.clear();
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
function _detect() {
|
|
82
|
+
if (typeof navigator !== "undefined" && navigator.product === "ReactNative") return "react-native";
|
|
83
|
+
const _proc = globalThis["process"];
|
|
84
|
+
if (typeof window === "undefined" && _proc?.versions?.node) return "node";
|
|
85
|
+
if (typeof window !== "undefined") return "web";
|
|
86
|
+
return "unknown";
|
|
87
|
+
}
|
|
88
|
+
var JoopPlatform = class {
|
|
89
|
+
static _type = _detect();
|
|
90
|
+
static _adapter = {};
|
|
91
|
+
static _memStorage = null;
|
|
92
|
+
/**
|
|
93
|
+
* Call once at app startup to configure adapters for your platform.
|
|
94
|
+
*
|
|
95
|
+
* Web (default — no call needed):
|
|
96
|
+
* JoopPlatform.init();
|
|
97
|
+
*
|
|
98
|
+
* React Native with react-native-mmkv:
|
|
99
|
+
* import { MMKV } from 'react-native-mmkv';
|
|
100
|
+
* const mmkv = new MMKV();
|
|
101
|
+
* JoopPlatform.init({ adapter: { storage: mmkv } });
|
|
102
|
+
*
|
|
103
|
+
* React Native with custom compression (fflate):
|
|
104
|
+
* import { gzip, ungzip } from 'fflate';
|
|
105
|
+
* JoopPlatform.init({
|
|
106
|
+
* adapter: {
|
|
107
|
+
* compression: {
|
|
108
|
+
* compress: (d, fmt) => new Promise((res, rej) => gzip(d, (e, r) => e ? rej(e) : res(r))),
|
|
109
|
+
* decompress: (d, fmt) => new Promise((res, rej) => ungzip(d, (e, r) => e ? rej(e) : res(r))),
|
|
110
|
+
* },
|
|
111
|
+
* },
|
|
112
|
+
* });
|
|
113
|
+
*/
|
|
114
|
+
static init(config = {}) {
|
|
115
|
+
if (config.platform) this._type = config.platform;
|
|
116
|
+
this._adapter = { ...this._adapter, ...config.adapter ?? {} };
|
|
117
|
+
}
|
|
118
|
+
/** Current detected or overridden platform type */
|
|
119
|
+
static get type() {
|
|
120
|
+
return this._type;
|
|
121
|
+
}
|
|
122
|
+
static is(type) {
|
|
123
|
+
return this._type === type;
|
|
124
|
+
}
|
|
125
|
+
static isMobile() {
|
|
126
|
+
return this._type === "react-native";
|
|
127
|
+
}
|
|
128
|
+
static isWeb() {
|
|
129
|
+
return this._type === "web";
|
|
130
|
+
}
|
|
131
|
+
static isNode() {
|
|
132
|
+
return this._type === "node";
|
|
133
|
+
}
|
|
134
|
+
/** Raw adapter config registered via init() */
|
|
135
|
+
static getAdapter() {
|
|
136
|
+
return this._adapter;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Returns the best available storage adapter:
|
|
140
|
+
* 1. Custom adapter registered via init()
|
|
141
|
+
* 2. localStorage (web)
|
|
142
|
+
* 3. In-memory fallback (Node / RN without adapter)
|
|
143
|
+
*/
|
|
144
|
+
static getStorage() {
|
|
145
|
+
if (this._adapter.storage) return this._adapter.storage;
|
|
146
|
+
if (typeof localStorage !== "undefined") return _webStorage(localStorage);
|
|
147
|
+
if (!this._memStorage) this._memStorage = new _MemStorageImpl();
|
|
148
|
+
return this._memStorage;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Returns the best available session-scoped storage:
|
|
152
|
+
* 1. Custom adapter registered via init()
|
|
153
|
+
* 2. sessionStorage (web)
|
|
154
|
+
* 3. Shared in-memory fallback
|
|
155
|
+
*/
|
|
156
|
+
static getSessionStorage() {
|
|
157
|
+
if (this._adapter.storage) return this._adapter.storage;
|
|
158
|
+
if (typeof sessionStorage !== "undefined") return _webStorage(sessionStorage);
|
|
159
|
+
if (!this._memStorage) this._memStorage = new _MemStorageImpl();
|
|
160
|
+
return this._memStorage;
|
|
161
|
+
}
|
|
162
|
+
/** What APIs are available in the current environment */
|
|
163
|
+
static capabilities() {
|
|
164
|
+
return {
|
|
165
|
+
compression: typeof CompressionStream !== "undefined" || !!this._adapter.compression,
|
|
166
|
+
workers: typeof Worker !== "undefined" || !!this._adapter.worker,
|
|
167
|
+
cryptoSubtle: !!(typeof globalThis !== "undefined" && globalThis.crypto?.subtle),
|
|
168
|
+
persistentStorage: typeof localStorage !== "undefined" || !!this._adapter.storage,
|
|
169
|
+
dom: typeof document !== "undefined",
|
|
170
|
+
serviceWorker: typeof navigator !== "undefined" && "serviceWorker" in navigator
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/** Reset to auto-detected defaults — useful between tests */
|
|
174
|
+
static _reset() {
|
|
175
|
+
this._type = _detect();
|
|
176
|
+
this._adapter = {};
|
|
177
|
+
this._memStorage = null;
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// src/device/network-monitor.ts
|
|
182
|
+
var JoopNetworkMonitor = class {
|
|
183
|
+
_adapter;
|
|
184
|
+
_state$;
|
|
185
|
+
_cleanup = [];
|
|
186
|
+
constructor(config = {}) {
|
|
187
|
+
this._adapter = config.adapter ?? JoopPlatform.getAdapter().network ?? null;
|
|
188
|
+
this._state$ = new JoopBehaviorSubject(this._read());
|
|
189
|
+
this._init();
|
|
190
|
+
}
|
|
191
|
+
_init() {
|
|
192
|
+
if (this._adapter) {
|
|
193
|
+
this._state$.next(this._adapter.getState());
|
|
194
|
+
const unsub = this._adapter.onChange((s) => this._state$.next(s));
|
|
195
|
+
this._cleanup.push(unsub);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (typeof window === "undefined") return;
|
|
199
|
+
const refresh = () => this._state$.next(this._read());
|
|
200
|
+
window.addEventListener("online", refresh);
|
|
201
|
+
window.addEventListener("offline", refresh);
|
|
202
|
+
const conn = navigator.connection;
|
|
203
|
+
if (conn) {
|
|
204
|
+
conn.addEventListener("change", refresh);
|
|
205
|
+
this._cleanup.push(() => conn.removeEventListener("change", refresh));
|
|
206
|
+
}
|
|
207
|
+
this._cleanup.push(
|
|
208
|
+
() => window.removeEventListener("online", refresh),
|
|
209
|
+
() => window.removeEventListener("offline", refresh)
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
_read() {
|
|
213
|
+
if (this._adapter) return this._adapter.getState();
|
|
214
|
+
if (typeof navigator === "undefined") return { online: false, type: "unknown" };
|
|
215
|
+
const online = navigator.onLine;
|
|
216
|
+
if (!online) return { online: false, type: "offline" };
|
|
217
|
+
const conn = navigator.connection;
|
|
218
|
+
const type = conn ? _mapType(conn.type) : "unknown";
|
|
219
|
+
return {
|
|
220
|
+
online,
|
|
221
|
+
type,
|
|
222
|
+
effectiveType: conn?.effectiveType,
|
|
223
|
+
downlink: conn?.downlink,
|
|
224
|
+
rtt: conn?.rtt,
|
|
225
|
+
saveData: conn?.saveData,
|
|
226
|
+
metered: conn?.metered ?? type === "cellular"
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
getState() {
|
|
230
|
+
return this._state$.getValue();
|
|
231
|
+
}
|
|
232
|
+
state$() {
|
|
233
|
+
return this._state$.asObservable();
|
|
234
|
+
}
|
|
235
|
+
isOnline() {
|
|
236
|
+
return this.getState().online;
|
|
237
|
+
}
|
|
238
|
+
isMetered() {
|
|
239
|
+
return this.getState().metered ?? this.getState().type === "cellular";
|
|
240
|
+
}
|
|
241
|
+
/** Call fn when connectivity is regained. */
|
|
242
|
+
onOnline(fn) {
|
|
243
|
+
let prev = this.getState().online;
|
|
244
|
+
return this._state$.subscribe((s) => {
|
|
245
|
+
if (s.online && !prev) fn();
|
|
246
|
+
prev = s.online;
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
/** Call fn when connectivity is lost. */
|
|
250
|
+
onOffline(fn) {
|
|
251
|
+
let prev = this.getState().online;
|
|
252
|
+
return this._state$.subscribe((s) => {
|
|
253
|
+
if (!s.online && prev) fn();
|
|
254
|
+
prev = s.online;
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
/** Call fn when the connection type changes (e.g. wifi → cellular). */
|
|
258
|
+
onTypeChange(fn) {
|
|
259
|
+
let prev = this.getState().type;
|
|
260
|
+
return this._state$.subscribe((s) => {
|
|
261
|
+
if (s.type !== prev) {
|
|
262
|
+
fn(s.type);
|
|
263
|
+
prev = s.type;
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
destroy() {
|
|
268
|
+
for (const fn of this._cleanup) fn();
|
|
269
|
+
this._cleanup = [];
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
function _mapType(raw) {
|
|
273
|
+
if (!raw) return "unknown";
|
|
274
|
+
if (raw === "wifi" || raw === "wimax") return "wifi";
|
|
275
|
+
if (raw === "cellular" || raw === "2g" || raw === "3g" || raw === "4g" || raw === "5g") return "cellular";
|
|
276
|
+
if (raw === "ethernet") return "ethernet";
|
|
277
|
+
if (raw === "none" || raw === "offline") return "offline";
|
|
278
|
+
return "unknown";
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// src/device/app-lifecycle.ts
|
|
282
|
+
var JoopAppLifecycle = class {
|
|
283
|
+
_state$ = new JoopBehaviorSubject("unknown");
|
|
284
|
+
_cleanup = [];
|
|
285
|
+
_adapter;
|
|
286
|
+
constructor(config = {}) {
|
|
287
|
+
this._adapter = config.adapter ?? JoopPlatform.getAdapter().lifecycle ?? null;
|
|
288
|
+
this._init();
|
|
289
|
+
}
|
|
290
|
+
_init() {
|
|
291
|
+
if (this._adapter) {
|
|
292
|
+
this._state$.next(this._adapter.getState());
|
|
293
|
+
const unsub = this._adapter.onChange((s) => this._state$.next(s));
|
|
294
|
+
this._cleanup.push(unsub);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (typeof document === "undefined") {
|
|
298
|
+
this._state$.next("unknown");
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
this._state$.next(document.hidden ? "background" : "active");
|
|
302
|
+
const onVisibility = () => this._state$.next(document.hidden ? "background" : "active");
|
|
303
|
+
const onFocus = () => this._state$.next("active");
|
|
304
|
+
const onBlur = () => this._state$.next("background");
|
|
305
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
306
|
+
window.addEventListener("focus", onFocus);
|
|
307
|
+
window.addEventListener("blur", onBlur);
|
|
308
|
+
this._cleanup.push(
|
|
309
|
+
() => document.removeEventListener("visibilitychange", onVisibility),
|
|
310
|
+
() => window.removeEventListener("focus", onFocus),
|
|
311
|
+
() => window.removeEventListener("blur", onBlur)
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
getState() {
|
|
315
|
+
return this._state$.getValue();
|
|
316
|
+
}
|
|
317
|
+
state$() {
|
|
318
|
+
return this._state$.asObservable();
|
|
319
|
+
}
|
|
320
|
+
isActive() {
|
|
321
|
+
return this.getState() === "active";
|
|
322
|
+
}
|
|
323
|
+
/** Call fn each time the app comes to the foreground (background → active). */
|
|
324
|
+
onForeground(fn) {
|
|
325
|
+
let prev = this.getState();
|
|
326
|
+
return this._state$.subscribe((s) => {
|
|
327
|
+
if (s === "active" && prev !== "active") fn();
|
|
328
|
+
prev = s;
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
/** Call fn each time the app goes to the background (active → background). */
|
|
332
|
+
onBackground(fn) {
|
|
333
|
+
let prev = this.getState();
|
|
334
|
+
return this._state$.subscribe((s) => {
|
|
335
|
+
if (s === "background" && prev !== "background") fn();
|
|
336
|
+
prev = s;
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
destroy() {
|
|
340
|
+
for (const fn of this._cleanup) fn();
|
|
341
|
+
this._cleanup = [];
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
// src/device/key-vault.ts
|
|
346
|
+
var JoopKeyVault = class {
|
|
347
|
+
_prefix;
|
|
348
|
+
_encKey;
|
|
349
|
+
_adapter;
|
|
350
|
+
_cryptoKey = null;
|
|
351
|
+
constructor(config = {}) {
|
|
352
|
+
this._prefix = config.prefix ?? "joop_vault_";
|
|
353
|
+
this._encKey = config.encryptionKey;
|
|
354
|
+
this._adapter = config.adapter ?? JoopPlatform.getAdapter().keyVault ?? null;
|
|
355
|
+
}
|
|
356
|
+
/** Store a secret. On web: AES-GCM encrypted if `encryptionKey` was provided. */
|
|
357
|
+
async set(key, value) {
|
|
358
|
+
if (this._adapter) return this._adapter.set(key, value);
|
|
359
|
+
const stored = this._encKey ? await _encrypt(value, await this._key()) : btoa(unescape(encodeURIComponent(value)));
|
|
360
|
+
JoopPlatform.getStorage().setItem(this._prefix + key, stored);
|
|
361
|
+
}
|
|
362
|
+
/** Retrieve a secret, or null if not found. */
|
|
363
|
+
async get(key) {
|
|
364
|
+
if (this._adapter) return this._adapter.get(key);
|
|
365
|
+
const raw = JoopPlatform.getStorage().getItem(this._prefix + key);
|
|
366
|
+
if (!raw) return null;
|
|
367
|
+
try {
|
|
368
|
+
return this._encKey ? await _decrypt(raw, await this._key()) : decodeURIComponent(escape(atob(raw)));
|
|
369
|
+
} catch {
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
async remove(key) {
|
|
374
|
+
if (this._adapter) return this._adapter.remove(key);
|
|
375
|
+
JoopPlatform.getStorage().removeItem(this._prefix + key);
|
|
376
|
+
}
|
|
377
|
+
async clear() {
|
|
378
|
+
if (this._adapter) return this._adapter.clear();
|
|
379
|
+
JoopPlatform.getStorage().clear?.();
|
|
380
|
+
}
|
|
381
|
+
async has(key) {
|
|
382
|
+
return await this.get(key) !== null;
|
|
383
|
+
}
|
|
384
|
+
/** Rotate the encryption key: re-encrypts all known entries with a new key. */
|
|
385
|
+
async rotateKey(newEncryptionKey, keys) {
|
|
386
|
+
if (this._adapter) throw new Error("rotateKey not supported with native adapter");
|
|
387
|
+
const values = await Promise.all(keys.map((k) => this.get(k)));
|
|
388
|
+
this._encKey = newEncryptionKey;
|
|
389
|
+
this._cryptoKey = null;
|
|
390
|
+
for (let i = 0; i < keys.length; i++) {
|
|
391
|
+
if (values[i] !== null) await this.set(keys[i], values[i]);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
async _key() {
|
|
395
|
+
if (!this._cryptoKey) this._cryptoKey = await _deriveKey(this._encKey);
|
|
396
|
+
return this._cryptoKey;
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
var _SALT = new Uint8Array([
|
|
400
|
+
106,
|
|
401
|
+
111,
|
|
402
|
+
111,
|
|
403
|
+
112,
|
|
404
|
+
45,
|
|
405
|
+
118,
|
|
406
|
+
97,
|
|
407
|
+
117,
|
|
408
|
+
108,
|
|
409
|
+
116,
|
|
410
|
+
45,
|
|
411
|
+
118,
|
|
412
|
+
49,
|
|
413
|
+
0,
|
|
414
|
+
0,
|
|
415
|
+
0
|
|
416
|
+
]);
|
|
417
|
+
async function _deriveKey(password) {
|
|
418
|
+
const km = await crypto.subtle.importKey(
|
|
419
|
+
"raw",
|
|
420
|
+
new TextEncoder().encode(password),
|
|
421
|
+
{ name: "PBKDF2" },
|
|
422
|
+
false,
|
|
423
|
+
["deriveKey"]
|
|
424
|
+
);
|
|
425
|
+
return crypto.subtle.deriveKey(
|
|
426
|
+
{ name: "PBKDF2", salt: _SALT, iterations: 1e5, hash: "SHA-256" },
|
|
427
|
+
km,
|
|
428
|
+
{ name: "AES-GCM", length: 256 },
|
|
429
|
+
false,
|
|
430
|
+
["encrypt", "decrypt"]
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
async function _encrypt(value, key) {
|
|
434
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
435
|
+
const encrypted = await crypto.subtle.encrypt(
|
|
436
|
+
{ name: "AES-GCM", iv },
|
|
437
|
+
key,
|
|
438
|
+
new TextEncoder().encode(value)
|
|
439
|
+
);
|
|
440
|
+
const combined = new Uint8Array(12 + encrypted.byteLength);
|
|
441
|
+
combined.set(iv);
|
|
442
|
+
combined.set(new Uint8Array(encrypted), 12);
|
|
443
|
+
return btoa(String.fromCharCode(...combined));
|
|
444
|
+
}
|
|
445
|
+
async function _decrypt(encoded, key) {
|
|
446
|
+
const combined = Uint8Array.from(atob(encoded), (c) => c.charCodeAt(0));
|
|
447
|
+
const iv = combined.slice(0, 12);
|
|
448
|
+
const data = combined.slice(12);
|
|
449
|
+
const decrypted = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, data);
|
|
450
|
+
return new TextDecoder().decode(decrypted);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// src/react/index.ts
|
|
454
|
+
function createJoopReact(react) {
|
|
455
|
+
const {
|
|
456
|
+
useState,
|
|
457
|
+
useEffect,
|
|
458
|
+
useCallback,
|
|
459
|
+
useMemo,
|
|
460
|
+
useRef,
|
|
461
|
+
createContext,
|
|
462
|
+
useContext,
|
|
463
|
+
createElement
|
|
464
|
+
} = react;
|
|
465
|
+
const JoopCtx = createContext(null);
|
|
466
|
+
function JoopProvider(props) {
|
|
467
|
+
return createElement(
|
|
468
|
+
JoopCtx.Provider,
|
|
469
|
+
{ value: props.joop },
|
|
470
|
+
props.children
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
function useJoop() {
|
|
474
|
+
const joop = useContext(JoopCtx);
|
|
475
|
+
if (!joop) throw new Error("[joopjs] useJoop must be called inside <JoopProvider>");
|
|
476
|
+
return joop;
|
|
477
|
+
}
|
|
478
|
+
function useJoopNetworkMonitor() {
|
|
479
|
+
const ref = useRef();
|
|
480
|
+
if (!ref.current) ref.current = new JoopNetworkMonitor();
|
|
481
|
+
const monitor = ref.current;
|
|
482
|
+
const [state, setState] = useState(() => monitor.getState());
|
|
483
|
+
useEffect(() => {
|
|
484
|
+
const unsub = monitor.state$().subscribe((s) => setState({ ...s }));
|
|
485
|
+
return () => {
|
|
486
|
+
unsub();
|
|
487
|
+
monitor.destroy();
|
|
488
|
+
};
|
|
489
|
+
}, []);
|
|
490
|
+
return { ...state, monitor };
|
|
491
|
+
}
|
|
492
|
+
function useJoopAppLifecycle() {
|
|
493
|
+
const ref = useRef();
|
|
494
|
+
if (!ref.current) ref.current = new JoopAppLifecycle();
|
|
495
|
+
const lc = ref.current;
|
|
496
|
+
const [state, setState] = useState(() => lc.getState());
|
|
497
|
+
useEffect(() => {
|
|
498
|
+
const unsub = lc.state$().subscribe((s) => setState(s));
|
|
499
|
+
return () => {
|
|
500
|
+
unsub();
|
|
501
|
+
lc.destroy();
|
|
502
|
+
};
|
|
503
|
+
}, []);
|
|
504
|
+
return { state, isActive: state === "active" };
|
|
505
|
+
}
|
|
506
|
+
function useJoopKeyVault(key, vaultConfig) {
|
|
507
|
+
const vaultRef = useRef();
|
|
508
|
+
if (!vaultRef.current) vaultRef.current = new JoopKeyVault(vaultConfig);
|
|
509
|
+
const vault = vaultRef.current;
|
|
510
|
+
const [value, setValue] = useState(null);
|
|
511
|
+
const [loading, setLoading] = useState(true);
|
|
512
|
+
const refresh = useCallback(async () => {
|
|
513
|
+
setLoading(true);
|
|
514
|
+
setValue(await vault.get(key));
|
|
515
|
+
setLoading(false);
|
|
516
|
+
}, [key]);
|
|
517
|
+
useEffect(() => {
|
|
518
|
+
refresh();
|
|
519
|
+
}, [key]);
|
|
520
|
+
const set = useCallback(async (v) => {
|
|
521
|
+
await vault.set(key, v);
|
|
522
|
+
setValue(v);
|
|
523
|
+
}, [key]);
|
|
524
|
+
const remove = useCallback(async () => {
|
|
525
|
+
await vault.remove(key);
|
|
526
|
+
setValue(null);
|
|
527
|
+
}, [key]);
|
|
528
|
+
return { value, loading, set, remove, refresh };
|
|
529
|
+
}
|
|
530
|
+
function useJoopAuth() {
|
|
531
|
+
const joop = useJoop();
|
|
532
|
+
const [isLoggedIn, setLoggedIn] = useState(() => joop.auth.isLoggedIn());
|
|
533
|
+
useEffect(() => {
|
|
534
|
+
const unsub = joop.auth.isLoggedIn$().subscribe((v) => setLoggedIn(v));
|
|
535
|
+
return () => unsub();
|
|
536
|
+
}, []);
|
|
537
|
+
const login = useCallback(() => joop.auth.setLoggedIn(true), []);
|
|
538
|
+
const logout = useCallback(() => joop.auth.logout(), []);
|
|
539
|
+
return { isLoggedIn, user: null, login, logout };
|
|
540
|
+
}
|
|
541
|
+
function useJoopTheme() {
|
|
542
|
+
const joop = useJoop();
|
|
543
|
+
const [active, setActive] = useState(() => joop.theme.getActiveName());
|
|
544
|
+
const themes = useMemo(() => joop.theme.getMapped(), []);
|
|
545
|
+
useEffect(() => {
|
|
546
|
+
const unsub = joop.theme.active$().subscribe((name) => setActive(name));
|
|
547
|
+
return () => unsub();
|
|
548
|
+
}, []);
|
|
549
|
+
const setTheme = useCallback((nameOrId) => {
|
|
550
|
+
joop.theme.apply(nameOrId);
|
|
551
|
+
}, []);
|
|
552
|
+
return { active, themes, setTheme };
|
|
553
|
+
}
|
|
554
|
+
function useJoopI18n() {
|
|
555
|
+
const joop = useJoop();
|
|
556
|
+
const [language, setLang] = useState(() => joop.i18n.getDetails().code);
|
|
557
|
+
const [direction, setDir] = useState(() => joop.i18n.getDirection());
|
|
558
|
+
useEffect(() => {
|
|
559
|
+
const unsub = joop.i18n.language$().subscribe((lang) => {
|
|
560
|
+
setLang(lang);
|
|
561
|
+
setDir(joop.i18n.getDirection());
|
|
562
|
+
});
|
|
563
|
+
return () => unsub();
|
|
564
|
+
}, []);
|
|
565
|
+
const t = useCallback(
|
|
566
|
+
(key, params) => joop.i18n.t(key, params),
|
|
567
|
+
[language]
|
|
568
|
+
);
|
|
569
|
+
const setLanguage = useCallback((lang) => joop.i18n.setLanguage(lang), []);
|
|
570
|
+
return { language, direction, t, setLanguage };
|
|
571
|
+
}
|
|
572
|
+
function useJoopLoader() {
|
|
573
|
+
const joop = useJoop();
|
|
574
|
+
const [isLoading, setLoading] = useState(() => joop.loader.isLoading());
|
|
575
|
+
useEffect(() => {
|
|
576
|
+
const unsub = joop.loader.isLoading$().subscribe((v) => setLoading(v));
|
|
577
|
+
return () => unsub();
|
|
578
|
+
}, []);
|
|
579
|
+
const show = useCallback(() => joop.loader.show(), []);
|
|
580
|
+
const hide = useCallback(() => joop.loader.hide(), []);
|
|
581
|
+
return { isLoading, show, hide };
|
|
582
|
+
}
|
|
583
|
+
function useJoopConfig(key) {
|
|
584
|
+
const joop = useJoop();
|
|
585
|
+
return useMemo(() => joop.config.get(key), [key]);
|
|
586
|
+
}
|
|
587
|
+
function useJoopFeatureFlag(flagKey, context) {
|
|
588
|
+
const joop = useJoop();
|
|
589
|
+
const enabled = useMemo(
|
|
590
|
+
() => joop.featureFlags.isEnabled(flagKey, context),
|
|
591
|
+
[flagKey]
|
|
592
|
+
);
|
|
593
|
+
const variant = useMemo(
|
|
594
|
+
() => joop.featureFlags.getVariant(flagKey, context),
|
|
595
|
+
[flagKey]
|
|
596
|
+
);
|
|
597
|
+
return { enabled, variant };
|
|
598
|
+
}
|
|
599
|
+
function useJoopStore(selector) {
|
|
600
|
+
const joop = useJoop();
|
|
601
|
+
const store = joop.store;
|
|
602
|
+
const [value, setValue] = useState(() => selector(store.getState()));
|
|
603
|
+
useEffect(() => {
|
|
604
|
+
const unsub = store.subscribe((s) => {
|
|
605
|
+
setValue(selector(s));
|
|
606
|
+
});
|
|
607
|
+
return () => unsub();
|
|
608
|
+
}, []);
|
|
609
|
+
return value;
|
|
610
|
+
}
|
|
611
|
+
return {
|
|
612
|
+
JoopProvider,
|
|
613
|
+
JoopCtx,
|
|
614
|
+
useJoop,
|
|
615
|
+
useJoopNetworkMonitor,
|
|
616
|
+
useJoopAppLifecycle,
|
|
617
|
+
useJoopKeyVault,
|
|
618
|
+
useJoopAuth,
|
|
619
|
+
useJoopTheme,
|
|
620
|
+
useJoopI18n,
|
|
621
|
+
useJoopLoader,
|
|
622
|
+
useJoopConfig,
|
|
623
|
+
useJoopFeatureFlag,
|
|
624
|
+
useJoopStore
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
export { createJoopReact };
|
|
629
|
+
//# sourceMappingURL=index.mjs.map
|
|
630
|
+
//# sourceMappingURL=index.mjs.map
|