@clubz/sdk 0.1.2

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.
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Types de messages supportés par le Bridge.
3
+ */
4
+ export type BridgeAction = 'VIBRATE' | 'NAVIGATE' | 'GET_USER' | 'STORAGE_SET' | 'STORAGE_GET';
5
+ export interface BridgeRequest<T = any> {
6
+ id: string;
7
+ action: BridgeAction;
8
+ payload?: T;
9
+ }
10
+ export interface BridgeResponse<T = any> {
11
+ id: string;
12
+ success: boolean;
13
+ data?: T;
14
+ error?: string;
15
+ }
16
+ export declare class BridgeProvider {
17
+ private isNative;
18
+ private pendingRequests;
19
+ constructor();
20
+ /**
21
+ * Envoie une commande au système hôte (Mobile ou Simulateur)
22
+ */
23
+ send<T = any>(action: BridgeAction, payload?: any): Promise<T>;
24
+ getUser(): Promise<{
25
+ id: string;
26
+ name: string;
27
+ }>;
28
+ vibrate(): Promise<void>;
29
+ navigate(route: string): Promise<void>;
30
+ private handleMessage;
31
+ private mockFallback;
32
+ private generateId;
33
+ }
34
+ export declare const bridge: BridgeProvider;
@@ -0,0 +1,155 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
+ return new (P || (P = Promise))(function (resolve, reject) {
15
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
19
+ });
20
+ };
21
+ var __generator = (this && this.__generator) || function (thisArg, body) {
22
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
23
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
24
+ function verb(n) { return function (v) { return step([n, v]); }; }
25
+ function step(op) {
26
+ if (f) throw new TypeError("Generator is already executing.");
27
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
28
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
29
+ if (y = 0, t) op = [op[0] & 2, t.value];
30
+ switch (op[0]) {
31
+ case 0: case 1: t = op; break;
32
+ case 4: _.label++; return { value: op[1], done: false };
33
+ case 5: _.label++; y = op[1]; op = [0]; continue;
34
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
35
+ default:
36
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
37
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
38
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
39
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
40
+ if (t[2]) _.ops.pop();
41
+ _.trys.pop(); continue;
42
+ }
43
+ op = body.call(thisArg, _);
44
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
45
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
+ }
47
+ };
48
+ var BridgeProvider = /** @class */ (function () {
49
+ function BridgeProvider() {
50
+ // Détection de l'environnement React Native WebView
51
+ this.isNative = typeof window !== 'undefined' &&
52
+ window.ReactNativeWebView &&
53
+ window.ReactNativeWebView.postMessage;
54
+ this.pendingRequests = new Map();
55
+ // Écoute des réponses (Native ou Simulateur)
56
+ if (typeof window !== 'undefined') {
57
+ window.addEventListener('message', this.handleMessage.bind(this));
58
+ }
59
+ }
60
+ /**
61
+ * Envoie une commande au système hôte (Mobile ou Simulateur)
62
+ */
63
+ BridgeProvider.prototype.send = function (action, payload) {
64
+ var _this = this;
65
+ var id = this.generateId();
66
+ return new Promise(function (resolve, reject) {
67
+ // 1. Stocker la promesse pour la résoudre quand la réponse arrive
68
+ _this.pendingRequests.set(id, { resolve: resolve, reject: reject });
69
+ var request = { id: id, action: action, payload: payload };
70
+ if (_this.isNative) {
71
+ // --- MODE NATIF ---
72
+ // Envoi vers iOS/Android via l'interface WebView
73
+ window.ReactNativeWebView.postMessage(JSON.stringify(request));
74
+ }
75
+ else {
76
+ // --- MODE SIMULATEUR (Web) ---
77
+ // Envoi vers le parent (le cadre du simulateur)
78
+ window.parent.postMessage(__assign(__assign({}, request), { source: 'clubz-widget' }), '*');
79
+ // Fallback local si pas dans le simulateur (ex: dev simple)
80
+ if (window === window.parent) {
81
+ _this.mockFallback(action, payload, id);
82
+ }
83
+ }
84
+ });
85
+ };
86
+ /* --- MÉTODES PUBLIQUES (facades) --- */
87
+ BridgeProvider.prototype.getUser = function () {
88
+ return __awaiter(this, void 0, void 0, function () {
89
+ return __generator(this, function (_a) {
90
+ return [2 /*return*/, this.send('GET_USER')];
91
+ });
92
+ });
93
+ };
94
+ BridgeProvider.prototype.vibrate = function () {
95
+ return __awaiter(this, void 0, void 0, function () {
96
+ return __generator(this, function (_a) {
97
+ return [2 /*return*/, this.send('VIBRATE')];
98
+ });
99
+ });
100
+ };
101
+ BridgeProvider.prototype.navigate = function (route) {
102
+ return __awaiter(this, void 0, void 0, function () {
103
+ return __generator(this, function (_a) {
104
+ return [2 /*return*/, this.send('NAVIGATE', { route: route })];
105
+ });
106
+ });
107
+ };
108
+ /* --- INTERNE --- */
109
+ BridgeProvider.prototype.handleMessage = function (event) {
110
+ try {
111
+ // On parse, attention ça peut être une string ou un objet
112
+ var message = typeof event.data === 'string'
113
+ ? JSON.parse(event.data)
114
+ : event.data;
115
+ // On vérifie si c'est une réponse à une de nos requêtes
116
+ if (message.id && this.pendingRequests.has(message.id)) {
117
+ var _a = this.pendingRequests.get(message.id), resolve = _a.resolve, reject = _a.reject;
118
+ if (message.success) {
119
+ resolve(message.data);
120
+ }
121
+ else {
122
+ reject(new Error(message.error || 'Bridge Error'));
123
+ }
124
+ this.pendingRequests.delete(message.id);
125
+ }
126
+ }
127
+ catch (e) {
128
+ // Ignorer les messages non-JSON ou étrangers
129
+ }
130
+ };
131
+ BridgeProvider.prototype.mockFallback = function (action, payload, id) {
132
+ console.log("[Bridge Dev] Action: ".concat(action), payload);
133
+ var mockResponses = {
134
+ 'GET_USER': { id: 'dev-123', name: 'Developer Mike' },
135
+ 'DEFAULT': null
136
+ };
137
+ // Simuler l'asynchronicité
138
+ setTimeout(function () {
139
+ var response = {
140
+ id: id,
141
+ success: true,
142
+ data: mockResponses[action] || mockResponses['DEFAULT']
143
+ };
144
+ // On poste le message à nous-même pour que handleMessage l'attrape
145
+ window.postMessage(response, '*');
146
+ }, 500);
147
+ };
148
+ BridgeProvider.prototype.generateId = function () {
149
+ return Math.random().toString(36).substr(2, 9);
150
+ };
151
+ return BridgeProvider;
152
+ }());
153
+ export { BridgeProvider };
154
+ // Instance singleton
155
+ export var bridge = new BridgeProvider();
@@ -0,0 +1 @@
1
+ export * from './bridge/BridgeProvider';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from './bridge/BridgeProvider';
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "@clubz/sdk",
3
+ "version": "0.1.2",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "scripts": {
7
+ "build": "tsc"
8
+ },
9
+ "description": "SDK for building Clubz Widgets",
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "devDependencies": {
14
+ "typescript": "^5.0.0"
15
+ }
16
+ }
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Types de messages supportés par le Bridge.
3
+ */
4
+ export type BridgeAction =
5
+ | 'VIBRATE'
6
+ | 'NAVIGATE'
7
+ | 'GET_USER'
8
+ | 'STORAGE_SET'
9
+ | 'STORAGE_GET';
10
+
11
+ export interface BridgeRequest<T = any> {
12
+ id: string; // ID unique pour corréler la réponse
13
+ action: BridgeAction;
14
+ payload?: T;
15
+ }
16
+
17
+ export interface BridgeResponse<T = any> {
18
+ id: string;
19
+ success: boolean;
20
+ data?: T;
21
+ error?: string;
22
+ }
23
+
24
+ export class BridgeProvider {
25
+ private isNative: boolean;
26
+ private pendingRequests: Map<string, { resolve: Function; reject: Function }>;
27
+
28
+ constructor() {
29
+ // Détection de l'environnement React Native WebView
30
+ this.isNative = typeof window !== 'undefined' &&
31
+ (window as any).ReactNativeWebView &&
32
+ (window as any).ReactNativeWebView.postMessage;
33
+
34
+ this.pendingRequests = new Map();
35
+
36
+ // Écoute des réponses (Native ou Simulateur)
37
+ if (typeof window !== 'undefined') {
38
+ window.addEventListener('message', this.handleMessage.bind(this));
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Envoie une commande au système hôte (Mobile ou Simulateur)
44
+ */
45
+ public send<T = any>(action: BridgeAction, payload?: any): Promise<T> {
46
+ const id = this.generateId();
47
+
48
+ return new Promise((resolve, reject) => {
49
+ // 1. Stocker la promesse pour la résoudre quand la réponse arrive
50
+ this.pendingRequests.set(id, { resolve, reject });
51
+
52
+ const request: BridgeRequest = { id, action, payload };
53
+
54
+ if (this.isNative) {
55
+ // --- MODE NATIF ---
56
+ // Envoi vers iOS/Android via l'interface WebView
57
+ (window as any).ReactNativeWebView.postMessage(JSON.stringify(request));
58
+ } else {
59
+ // --- MODE SIMULATEUR (Web) ---
60
+ // Envoi vers le parent (le cadre du simulateur)
61
+ window.parent.postMessage({ ...request, source: 'clubz-widget' }, '*');
62
+
63
+ // Fallback local si pas dans le simulateur (ex: dev simple)
64
+ if (window === window.parent) {
65
+ this.mockFallback(action, payload, id);
66
+ }
67
+ }
68
+ });
69
+ }
70
+
71
+ /* --- MÉTODES PUBLIQUES (facades) --- */
72
+
73
+ public async getUser() {
74
+ return this.send<{ id: string; name: string }>('GET_USER');
75
+ }
76
+
77
+ public async vibrate() {
78
+ return this.send<void>('VIBRATE');
79
+ }
80
+
81
+ public async navigate(route: string) {
82
+ return this.send<void>('NAVIGATE', { route });
83
+ }
84
+
85
+ /* --- INTERNE --- */
86
+
87
+ private handleMessage(event: MessageEvent) {
88
+ try {
89
+ // On parse, attention ça peut être une string ou un objet
90
+ const message: BridgeResponse = typeof event.data === 'string'
91
+ ? JSON.parse(event.data)
92
+ : event.data;
93
+
94
+ // On vérifie si c'est une réponse à une de nos requêtes
95
+ if (message.id && this.pendingRequests.has(message.id)) {
96
+ const { resolve, reject } = this.pendingRequests.get(message.id)!;
97
+
98
+ if (message.success) {
99
+ resolve(message.data);
100
+ } else {
101
+ reject(new Error(message.error || 'Bridge Error'));
102
+ }
103
+
104
+ this.pendingRequests.delete(message.id);
105
+ }
106
+ } catch (e) {
107
+ // Ignorer les messages non-JSON ou étrangers
108
+ }
109
+ }
110
+
111
+ private mockFallback(action: BridgeAction, payload: any, id: string) {
112
+ console.log(`[Bridge Dev] Action: ${action}`, payload);
113
+
114
+ const mockResponses: Record<string, any> = {
115
+ 'GET_USER': { id: 'dev-123', name: 'Developer Mike' },
116
+ 'DEFAULT': null
117
+ };
118
+
119
+ // Simuler l'asynchronicité
120
+ setTimeout(() => {
121
+ const response: BridgeResponse = {
122
+ id,
123
+ success: true,
124
+ data: mockResponses[action] || mockResponses['DEFAULT']
125
+ };
126
+
127
+ // On poste le message à nous-même pour que handleMessage l'attrape
128
+ window.postMessage(response, '*');
129
+ }, 500);
130
+ }
131
+
132
+ private generateId() {
133
+ return Math.random().toString(36).substr(2, 9);
134
+ }
135
+ }
136
+
137
+ // Instance singleton
138
+ export const bridge = new BridgeProvider();
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './bridge/BridgeProvider';
package/tsconfig.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es5",
4
+ "lib": [
5
+ "dom",
6
+ "dom.iterable",
7
+ "esnext"
8
+ ],
9
+ "allowJs": true,
10
+ "skipLibCheck": true,
11
+ "strict": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "noEmit": false,
14
+ "esModuleInterop": true,
15
+ "module": "esnext",
16
+ "moduleResolution": "node",
17
+ "resolveJsonModule": true,
18
+ "isolatedModules": true,
19
+ "jsx": "react-jsx",
20
+ "declaration": true,
21
+ "outDir": "./dist"
22
+ },
23
+ "include": [
24
+ "src"
25
+ ]
26
+ }