dashcam 1.0.1-beta.23 → 1.0.1-beta.24

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/lib/auth.js CHANGED
@@ -18,7 +18,7 @@ const auth = {
18
18
  });
19
19
 
20
20
  // Exchange API key for token
21
- const { token } = await got.post('https://api.testdriver.ai/auth/exchange-api-key', {
21
+ const { token } = await got.post('https://testdriver-api.onrender.com/auth/exchange-api-key', {
22
22
  json: { apiKey },
23
23
  timeout: 30000 // 30 second timeout
24
24
  }).json();
@@ -34,7 +34,7 @@ const auth = {
34
34
 
35
35
  // Get user info to verify the token works
36
36
  logger.debug('Fetching user information to validate token...');
37
- const user = await got.get('https://api.testdriver.ai/api/v1/whoami', {
37
+ const user = await got.get('https://testdriver-api.onrender.com/api/v1/whoami', {
38
38
  headers: {
39
39
  Authorization: `Bearer ${token}`
40
40
  },
@@ -105,7 +105,7 @@ const auth = {
105
105
  const token = await this.getToken();
106
106
 
107
107
  try {
108
- const response = await got.get('https://api.testdriver.ai/api/v1/projects', {
108
+ const response = await got.get('https://testdriver-api.onrender.com/api/v1/projects', {
109
109
  headers: {
110
110
  Authorization: `Bearer ${token}`
111
111
  },
@@ -160,7 +160,7 @@ const auth = {
160
160
  requestBody.project = replayData.project;
161
161
  }
162
162
 
163
- const response = await got.post('https://api.testdriver.ai/api/v1/replay/upload', {
163
+ const response = await got.post('https://testdriver-api.onrender.com/api/v1/replay/upload', {
164
164
  headers: {
165
165
  Authorization: `Bearer ${token}`
166
166
  },
@@ -188,7 +188,7 @@ const auth = {
188
188
  const token = await this.getToken();
189
189
 
190
190
  try {
191
- const response = await got.post('https://api.testdriver.ai/api/v1/logs', {
191
+ const response = await got.post('https://testdriver-api.onrender.com/api/v1/logs', {
192
192
  headers: {
193
193
  Authorization: `Bearer ${token}`
194
194
  },
package/lib/config.js CHANGED
@@ -17,7 +17,7 @@ export const auth0Config = {
17
17
  export const apiEndpoints = {
18
18
  development: process.env.API_ENDPOINT || 'http://localhost:3000',
19
19
  staging: 'https://replayable-api-staging.herokuapp.com',
20
- production: 'https://api.testdriver.ai'
20
+ production: 'https://testdriver-api.onrender.com'
21
21
  };
22
22
 
23
23
  export const API_ENDPOINT = apiEndpoints[ENV];
@@ -47,6 +47,63 @@ const findLinuxIcon = async (appName) => {
47
47
  return null;
48
48
  };
49
49
 
50
+ /**
51
+ * Calculate string similarity (Levenshtein distance based)
52
+ * Returns a value between 0 (no match) and 1 (perfect match)
53
+ */
54
+ const calculateSimilarity = (str1, str2) => {
55
+ const s1 = str1.toLowerCase();
56
+ const s2 = str2.toLowerCase();
57
+
58
+ // Exact match
59
+ if (s1 === s2) return 1.0;
60
+
61
+ // Check if one contains the other
62
+ if (s1.includes(s2) || s2.includes(s1)) {
63
+ return 0.8;
64
+ }
65
+
66
+ // Simple Levenshtein-based similarity
67
+ const longer = s1.length > s2.length ? s1 : s2;
68
+ const shorter = s1.length > s2.length ? s2 : s1;
69
+
70
+ if (longer.length === 0) return 1.0;
71
+
72
+ const editDistance = levenshteinDistance(s1, s2);
73
+ return (longer.length - editDistance) / longer.length;
74
+ };
75
+
76
+ /**
77
+ * Calculate Levenshtein distance between two strings
78
+ */
79
+ const levenshteinDistance = (str1, str2) => {
80
+ const matrix = [];
81
+
82
+ for (let i = 0; i <= str2.length; i++) {
83
+ matrix[i] = [i];
84
+ }
85
+
86
+ for (let j = 0; j <= str1.length; j++) {
87
+ matrix[0][j] = j;
88
+ }
89
+
90
+ for (let i = 1; i <= str2.length; i++) {
91
+ for (let j = 1; j <= str1.length; j++) {
92
+ if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
93
+ matrix[i][j] = matrix[i - 1][j - 1];
94
+ } else {
95
+ matrix[i][j] = Math.min(
96
+ matrix[i - 1][j - 1] + 1, // substitution
97
+ matrix[i][j - 1] + 1, // insertion
98
+ matrix[i - 1][j] + 1 // deletion
99
+ );
100
+ }
101
+ }
102
+ }
103
+
104
+ return matrix[str2.length][str1.length];
105
+ };
106
+
50
107
  /**
51
108
  * Find .desktop file for an application
52
109
  */
@@ -61,11 +118,12 @@ const findDesktopFile = async (appName) => {
61
118
  for (const dir of desktopDirs) {
62
119
  const desktopFile = path.join(dir, `${appName}.desktop`);
63
120
  if (fs.existsSync(desktopFile)) {
121
+ logger.debug("Found desktop file (exact match)", { appName, desktopFile });
64
122
  return desktopFile;
65
123
  }
66
124
  }
67
125
 
68
- // Try case-insensitive search
126
+ // Try case-insensitive exact match
69
127
  for (const dir of desktopDirs) {
70
128
  try {
71
129
  if (!fs.existsSync(dir)) continue;
@@ -75,6 +133,7 @@ const findDesktopFile = async (appName) => {
75
133
  (f) => f.toLowerCase() === `${appName.toLowerCase()}.desktop`
76
134
  );
77
135
  if (match) {
136
+ logger.debug("Found desktop file (case-insensitive)", { appName, match });
78
137
  return path.join(dir, match);
79
138
  }
80
139
  } catch (error) {
@@ -82,6 +141,40 @@ const findDesktopFile = async (appName) => {
82
141
  }
83
142
  }
84
143
 
144
+ // Try fuzzy matching - find best match based on string similarity
145
+ let bestMatch = null;
146
+ let bestScore = 0.6; // Minimum similarity threshold
147
+
148
+ for (const dir of desktopDirs) {
149
+ try {
150
+ if (!fs.existsSync(dir)) continue;
151
+
152
+ const files = fs.readdirSync(dir).filter(f => f.endsWith('.desktop'));
153
+
154
+ for (const file of files) {
155
+ const baseName = file.replace('.desktop', '');
156
+ const similarity = calculateSimilarity(appName, baseName);
157
+
158
+ if (similarity > bestScore) {
159
+ bestScore = similarity;
160
+ bestMatch = path.join(dir, file);
161
+ }
162
+ }
163
+ } catch (error) {
164
+ logger.debug("Error in fuzzy desktop file search", { dir, error: error.message });
165
+ }
166
+ }
167
+
168
+ if (bestMatch) {
169
+ logger.debug("Found desktop file (fuzzy match)", {
170
+ appName,
171
+ desktopFile: bestMatch,
172
+ similarity: bestScore.toFixed(2)
173
+ });
174
+ return bestMatch;
175
+ }
176
+
177
+ logger.debug("No desktop file found", { appName });
85
178
  return null;
86
179
  };
87
180
 
package/lib/uploader.js CHANGED
@@ -255,7 +255,7 @@ export async function upload(filePath, metadata = {}) {
255
255
 
256
256
  let newReplay;
257
257
  try {
258
- newReplay = await got.post('https://api.testdriver.ai/api/v1/replay', {
258
+ newReplay = await got.post('https://testdriver-api.onrender.com/api/v1/replay', {
259
259
  headers: {
260
260
  Authorization: `Bearer ${token}`
261
261
  },
@@ -430,7 +430,7 @@ export async function upload(filePath, metadata = {}) {
430
430
 
431
431
  // Publish the replay (like the desktop app does)
432
432
  logger.debug('Publishing replay...');
433
- await got.post('https://api.testdriver.ai/api/v1/replay/publish', {
433
+ await got.post('https://testdriver-api.onrender.com/api/v1/replay/publish', {
434
434
  headers: {
435
435
  Authorization: `Bearer ${token}`
436
436
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dashcam",
3
- "version": "1.0.1-beta.23",
3
+ "version": "1.0.1-beta.24",
4
4
  "description": "Minimal CLI version of Dashcam desktop app",
5
5
  "main": "bin/index.js",
6
6
  "bin": {