bytex-sdk 1.9.0 → 1.9.5

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 +62 -45
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -25,7 +25,7 @@ export class BytexCloud {
25
25
  this._listeners = {};
26
26
  }
27
27
 
28
- // ... (Login, Upload, Download methods remain same as v1.8.1)
28
+ // --- CORE METHODS ---
29
29
  async login(email, password) {
30
30
  const { data, error } = await this.supabase.auth.signInWithPassword({ email, password });
31
31
  if (error) throw new Error(error.message);
@@ -37,85 +37,102 @@ export class BytexCloud {
37
37
  const fd = new FormData();
38
38
  fd.append('file', data instanceof Blob ? data : new Blob([data]), name);
39
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}`);
40
41
  return await res.json();
41
42
  }
42
43
 
43
44
  async downloadData(name) {
44
45
  this._requireKey();
45
- const url = `${this.workerUrl}?action=view&key=${this.apiKey}&file=${encodeURIComponent(name.endsWith('.btx') ? name : name + '.stream.btx')}&_cb=${Date.now()}`;
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()}`;
46
48
  const { data: { session } } = await this.supabase.auth.getSession();
47
49
  const res = await fetch(url, { headers: { 'Authorization': `Bearer ${session?.access_token || ''}` } });
50
+ if (!res.ok) throw new Error(`Download Failed: ${res.status}`);
48
51
  const text = await res.text();
49
52
  try { return JSON.parse(text); } catch (e) { return text.split('\n').filter(Boolean).map(line => JSON.parse(line)); }
50
53
  }
51
54
 
55
+ 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;
65
+ }
66
+
52
67
  /**
53
- * ByteX X-RAY v2.0 (The Surgeon)
54
- * Advanced diagnostics & code implementation audit.
68
+ * ByteX X-RAY v2.1 (The Professional)
69
+ * Detailed diagnostic for Upload, Delete, and Streaming capabilities.
55
70
  */
56
71
  async xray() {
57
- console.log('[ByteX X-RAY] 🔍 Initiating Deep Code Surgery...');
72
+ console.log('[ByteX X-RAY] 🔍 Running professional system diagnostics...');
58
73
  const report = {
59
74
  timestamp: new Date().toISOString(),
60
- sdk_version: '1.9.0',
75
+ sdk_version: '1.9.5',
61
76
  health_score: 100,
62
- diagnostics: {},
77
+ checks: {},
63
78
  advice: []
64
79
  };
65
80
 
66
- // 1. Implementation Audit (Code Surgery)
67
- report.diagnostics.implementation = { status: 'OK' };
68
- if (!this.config.storage && typeof navigator !== 'undefined' && /React|Expo/i.test(navigator.userAgent || '')) {
69
- report.diagnostics.implementation = { status: 'WARN', issue: 'Missing Storage Engine' };
70
- report.advice.push('React Native detected but no storage engine (AsyncStorage) provided. Sessions will not persist.');
71
- report.health_score -= 20;
72
- }
81
+ // 1. Auth & Session Integrity
82
+ 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.');
73
85
 
74
- // 2. API Key Diagnostic
86
+ // 2. Upload/Write Permission Check
75
87
  try {
76
88
  this._requireKey();
77
- report.diagnostics.api_key = { status: 'OK', prefix: this.apiKey.substring(0, 8) };
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.');
78
94
  } catch (e) {
79
- report.diagnostics.api_key = { status: 'CRITICAL', issue: 'Missing Key' };
80
- report.advice.push('No API Key found. Call setApiKey() or pass it in constructor.');
81
- report.health_score -= 40;
95
+ report.checks.upload_capability = 'ERROR';
96
+ report.advice.push(`Upload Check Failed: ${e.message}`);
82
97
  }
83
98
 
84
- // 3. Worker Connectivity & Speed Probe
85
- const start = Date.now();
99
+ // 3. Delete/Management Permission Check
86
100
  try {
87
- const res = await fetch(`${this.workerUrl}?action=list&key=${this.apiKey}`);
88
- const latency = Date.now() - start;
89
- report.diagnostics.connectivity = {
90
- status: res.ok ? 'ONLINE' : 'DEGRADED',
91
- latency_ms: latency
92
- };
93
- if (latency > 500) {
94
- report.advice.push('High latency detected. This may cause delays in audio/video streaming.');
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.');
95
109
  }
96
110
  } catch (e) {
97
- report.diagnostics.connectivity = { status: 'OFFLINE', issue: 'Unreachable' };
98
- report.advice.push('ByteX Cloud is unreachable. Check your internet or firewall settings.');
99
- report.health_score -= 30;
111
+ report.checks.delete_capability = 'UNSUPPORTED';
100
112
  }
101
113
 
102
- // 4. Quota Check
114
+ // 4. Streaming & Range Support
103
115
  try {
104
- const qRes = await fetch(`${this.workerUrl}?action=quota&key=${this.apiKey}`);
105
- if (qRes.ok) {
106
- const quota = await qRes.json();
107
- report.diagnostics.storage = quota;
108
- if (quota.percentage > 90) {
109
- report.advice.push('Storage is almost full. Delete unused files to avoid upload errors.');
110
- report.health_score -= 10;
111
- }
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.');
112
122
  }
113
- } catch (e) { /* skip if quota fails */ }
123
+ } catch (e) { report.checks.streaming = 'UNKNOWN'; }
124
+
125
+ // 5. Code Implementation Audit
126
+ 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.');
129
+ }
114
130
 
115
- report.final_status = report.health_score > 80 ? 'HEALTHY' : (report.health_score > 50 ? 'WARNING' : 'CRITICAL');
131
+ const issues = report.advice.length;
132
+ report.final_status = issues === 0 ? 'HEALTHY' : (issues < 3 ? 'WARNING' : 'CRITICAL');
133
+
116
134
  return report;
117
135
  }
118
136
 
119
- _requireKey() { if (!this.apiKey) throw new Error('API Key required!'); }
120
- _emit(event, data) { if (this._listeners[event]) this._listeners[event].forEach(cb => cb(data)); }
137
+ _requireKey() { if (!this.apiKey) throw new Error('API Key required! Use setApiKey().'); }
121
138
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bytex-sdk",
3
- "version": "1.9.0",
3
+ "version": "1.9.5",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {