bytex-sdk 1.9.5 → 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.
Files changed (2) hide show
  1. package/index.js +68 -82
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -25,114 +25,100 @@ export class BytexCloud {
25
25
  this._listeners = {};
26
26
  }
27
27
 
28
- // --- CORE METHODS ---
28
+ // --- AUTO X-RAY WRAPPER ---
29
+ async _execute(fn, actionName) {
30
+ try {
31
+ return await fn();
32
+ } catch (e) {
33
+ console.warn(`[ByteX SDK] Error in ${actionName}. Running Auto X-RAY...`);
34
+ const diagnostic = await this.xray();
35
+ const advice = diagnostic.advice.length > 0 ? `\n[X-RAY Advice]: ${diagnostic.advice.join(' ')}` : '';
36
+ throw new Error(`${actionName} failed: ${e.message}${advice}`);
37
+ }
38
+ }
39
+
40
+ // --- CORE METHODS (ENHANCED WITH AUTO X-RAY) ---
29
41
  async login(email, password) {
30
- const { data, error } = await this.supabase.auth.signInWithPassword({ email, password });
31
- if (error) throw new Error(error.message);
32
- return data.user;
42
+ return this._execute(async () => {
43
+ const { data, error } = await this.supabase.auth.signInWithPassword({ email, password });
44
+ if (error) throw error;
45
+ return data.user;
46
+ }, 'Login');
33
47
  }
34
48
 
35
49
  async upload(name, data) {
36
- this._requireKey();
37
- const fd = new FormData();
38
- fd.append('file', data instanceof Blob ? data : new Blob([data]), name);
39
- const res = await fetch(`${this.workerUrl}?action=upload&key=${this.apiKey}`, { method: 'POST', body: fd });
40
- if (!res.ok) throw new Error(`Upload Failed: ${res.statusText}`);
41
- return await res.json();
50
+ return this._execute(async () => {
51
+ this._requireKey();
52
+ const fd = new FormData();
53
+ fd.append('file', data instanceof Blob ? data : new Blob([data]), name);
54
+ const res = await fetch(`${this.workerUrl}?action=upload&key=${this.apiKey}`, { method: 'POST', body: fd });
55
+ if (!res.ok) throw new Error(await res.text() || res.statusText);
56
+ return await res.json();
57
+ }, 'Upload');
42
58
  }
43
59
 
44
60
  async downloadData(name) {
45
- this._requireKey();
46
- const streamName = name.endsWith('.stream.btx') ? name : `${name}.stream.btx`;
47
- const url = `${this.workerUrl}?action=view&key=${this.apiKey}&file=${encodeURIComponent(streamName)}&_cb=${Date.now()}`;
48
- const { data: { session } } = await this.supabase.auth.getSession();
49
- const res = await fetch(url, { headers: { 'Authorization': `Bearer ${session?.access_token || ''}` } });
50
- if (!res.ok) throw new Error(`Download Failed: ${res.status}`);
51
- const text = await res.text();
52
- try { return JSON.parse(text); } catch (e) { return text.split('\n').filter(Boolean).map(line => JSON.parse(line)); }
61
+ return this._execute(async () => {
62
+ this._requireKey();
63
+ const streamName = name.endsWith('.btx') ? name : `${name}.stream.btx`;
64
+ const url = `${this.workerUrl}?action=view&key=${this.apiKey}&file=${encodeURIComponent(streamName)}&_cb=${Date.now()}`;
65
+ const { data: { session } } = await this.supabase.auth.getSession();
66
+ const res = await fetch(url, { headers: { 'Authorization': `Bearer ${session?.access_token || ''}` } });
67
+ if (!res.ok) throw new Error(`Status ${res.status}`);
68
+ const text = await res.text();
69
+ try { return JSON.parse(text); } catch (e) { return text.split('\n').filter(Boolean).map(line => JSON.parse(line)); }
70
+ }, 'Download');
53
71
  }
54
72
 
55
73
  async delete(name) {
56
- this._requireKey();
57
- const streamName = name.endsWith('.stream.btx') ? name : `${name}.stream.btx`;
58
- const { data: { session } } = await this.supabase.auth.getSession();
59
- const res = await fetch(`${this.workerUrl}?action=delete&key=${this.apiKey}&file=${encodeURIComponent(streamName)}`, {
60
- method: 'DELETE',
61
- headers: { 'Authorization': `Bearer ${session?.access_token || ''}` }
62
- });
63
- if (!res.ok) throw new Error(`Delete Failed: ${res.status}`);
64
- return true;
74
+ return this._execute(async () => {
75
+ this._requireKey();
76
+ const streamName = name.endsWith('.btx') ? name : `${name}.stream.btx`;
77
+ const { data: { session } } = await this.supabase.auth.getSession();
78
+ const res = await fetch(`${this.workerUrl}?action=delete&key=${this.apiKey}&file=${encodeURIComponent(streamName)}`, {
79
+ method: 'DELETE',
80
+ headers: { 'Authorization': `Bearer ${session?.access_token || ''}` }
81
+ });
82
+ if (!res.ok) throw new Error(`Status ${res.status}`);
83
+ return true;
84
+ }, 'Delete');
65
85
  }
66
86
 
67
87
  /**
68
- * ByteX X-RAY v2.1 (The Professional)
69
- * Detailed diagnostic for Upload, Delete, and Streaming capabilities.
88
+ * ByteX X-RAY v2.5 (Self-Healing Diagnostic)
70
89
  */
71
90
  async xray() {
72
- console.log('[ByteX X-RAY] 🔍 Running professional system diagnostics...');
73
- const report = {
74
- timestamp: new Date().toISOString(),
75
- sdk_version: '1.9.5',
76
- health_score: 100,
77
- checks: {},
78
- advice: []
79
- };
80
-
81
- // 1. Auth & Session Integrity
91
+ const report = { timestamp: new Date().toISOString(), sdk_version: '2.0.0', checks: {}, advice: [] };
82
92
  const { data: { session } } = await this.supabase.auth.getSession();
83
- report.checks.auth = { status: session ? 'OK' : 'GUEST', user: session?.user?.email || 'unauthenticated' };
84
- if (!session) report.advice.push('User is not logged in. Most management operations (delete, protected view) will fail.');
85
-
86
- // 2. Upload/Write Permission Check
93
+
94
+ // 1. Connectivity Check
95
+ const start = Date.now();
87
96
  try {
88
- this._requireKey();
89
- const testFd = new FormData();
90
- testFd.append('file', new Blob(['test']), 'xray_probe.txt');
91
- const upRes = await fetch(`${this.workerUrl}?action=upload&key=${this.apiKey}&probe=true`, { method: 'POST', body: testFd });
92
- report.checks.upload_capability = upRes.ok ? 'OK' : 'RESTRICTED';
93
- if (!upRes.ok) report.advice.push('Upload restricted. Your API Key might be READ-ONLY or the server rejected the probe.');
97
+ const res = await fetch(`${this.workerUrl}?action=list&key=${this.apiKey}`);
98
+ report.checks.connectivity = res.ok ? 'OK' : 'ERROR';
99
+ report.latency = Date.now() - start;
94
100
  } catch (e) {
95
- report.checks.upload_capability = 'ERROR';
96
- report.advice.push(`Upload Check Failed: ${e.message}`);
101
+ report.checks.connectivity = 'OFFLINE';
102
+ report.advice.push('ByteX Cloud is unreachable. Check your internet.');
97
103
  }
98
104
 
99
- // 3. Delete/Management Permission Check
100
- try {
101
- const delRes = await fetch(`${this.workerUrl}?action=delete&key=${this.apiKey}&file=non_existent_probe`, {
102
- method: 'DELETE',
103
- headers: { 'Authorization': `Bearer ${session?.access_token || ''}` }
104
- });
105
- // 404 is actually GOOD here because it means the DELETE method was accepted by the worker
106
- report.checks.delete_capability = (delRes.status === 404 || delRes.ok) ? 'OK' : 'FORBIDDEN';
107
- if (delRes.status === 403 || delRes.status === 401) {
108
- report.advice.push('Delete forbidden. Ensure your session is valid and you have owner permissions.');
109
- }
110
- } catch (e) {
111
- report.checks.delete_capability = 'UNSUPPORTED';
112
- }
105
+ // 2. API Key Check
106
+ if (!this.apiKey) {
107
+ report.checks.api_key = 'MISSING';
108
+ report.advice.push('No API Key detected. Please provide an apiKey in the constructor.');
109
+ } else { report.checks.api_key = 'OK'; }
113
110
 
114
- // 4. Streaming & Range Support
115
- try {
116
- const streamRes = await fetch(`${this.workerUrl}?action=view&key=${this.apiKey}&file=probe`, {
117
- headers: { 'Range': 'bytes=0-1' }
118
- });
119
- report.checks.streaming = streamRes.headers.get('Accept-Ranges') ? 'OPTIMIZED' : 'STANDARD';
120
- if (report.checks.streaming === 'STANDARD') {
121
- report.advice.push('Server does not support partial content (Ranges). Large video seeking might be slow.');
122
- }
123
- } catch (e) { report.checks.streaming = 'UNKNOWN'; }
111
+ // 3. Auth Check
112
+ report.checks.auth = session ? 'AUTHENTICATED' : 'GUEST';
113
+ if (!session) report.advice.push('User is not logged in. Some operations may fail.');
124
114
 
125
- // 5. Code Implementation Audit
115
+ // 4. Platform Audit (Mobile/Web)
126
116
  if (!this.config.storage && typeof navigator !== 'undefined') {
127
- report.checks.implementation = 'INCOMPLETE';
128
- report.advice.push('React Native detected but "storage" engine is missing in constructor. Sessions will NOT persist across app restarts.');
117
+ report.advice.push('Storage engine (AsyncStorage) is missing. Sessions will not persist.');
129
118
  }
130
119
 
131
- const issues = report.advice.length;
132
- report.final_status = issues === 0 ? 'HEALTHY' : (issues < 3 ? 'WARNING' : 'CRITICAL');
133
-
134
120
  return report;
135
121
  }
136
122
 
137
- _requireKey() { if (!this.apiKey) throw new Error('API Key required! Use setApiKey().'); }
123
+ _requireKey() { if (!this.apiKey) throw new Error('API Key required!'); }
138
124
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bytex-sdk",
3
- "version": "1.9.5",
3
+ "version": "2.0.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {