@tthr/vue 0.0.23 → 0.0.25
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.
|
@@ -217,7 +217,7 @@ useTetherSubscription('comments.list', undefined, (data) => {
|
|
|
217
217
|
if (!grouped[comment.postId]) {
|
|
218
218
|
grouped[comment.postId] = [];
|
|
219
219
|
}
|
|
220
|
-
grouped[comment.postId]
|
|
220
|
+
grouped[comment.postId]!.push(comment);
|
|
221
221
|
}
|
|
222
222
|
postComments.value = grouped;
|
|
223
223
|
}
|
|
@@ -251,11 +251,8 @@ async function handleCreateComment(postId: string) {
|
|
|
251
251
|
|
|
252
252
|
try {
|
|
253
253
|
await createComment.mutate({
|
|
254
|
-
id: crypto.randomUUID(),
|
|
255
254
|
postId,
|
|
256
255
|
content: newCommentText.value.trim(),
|
|
257
|
-
authorId: 'demo-user',
|
|
258
|
-
createdAt: new Date().toISOString(),
|
|
259
256
|
});
|
|
260
257
|
newCommentText.value = '';
|
|
261
258
|
// Refresh comments for this post
|
|
@@ -298,12 +295,8 @@ async function handleCreatePost() {
|
|
|
298
295
|
|
|
299
296
|
try {
|
|
300
297
|
await createPost.mutate({
|
|
301
|
-
id: crypto.randomUUID(),
|
|
302
298
|
title: newPostTitle.value.trim(),
|
|
303
299
|
content: '',
|
|
304
|
-
authorId: 'demo-user',
|
|
305
|
-
createdAt: new Date().toISOString(),
|
|
306
|
-
updatedAt: new Date().toISOString(),
|
|
307
300
|
});
|
|
308
301
|
newPostTitle.value = '';
|
|
309
302
|
await posts.refetch();
|
|
@@ -21,12 +21,18 @@ async function loadFunctionRegistry() {
|
|
|
21
21
|
try {
|
|
22
22
|
// Try to import the user's functions index
|
|
23
23
|
// This path is relative to the Nuxt app's server runtime
|
|
24
|
-
|
|
24
|
+
console.log('[Tether] Loading custom functions from ~~/tether/functions/index.ts');
|
|
25
|
+
const functions = await import('~~/tether/functions/index.ts').catch((err) => {
|
|
26
|
+
console.warn('[Tether] Failed to import functions:', err.message);
|
|
27
|
+
return null;
|
|
28
|
+
});
|
|
25
29
|
|
|
26
30
|
if (functions) {
|
|
31
|
+
console.log('[Tether] Loaded function modules:', Object.keys(functions));
|
|
27
32
|
functionRegistry = functions;
|
|
28
33
|
} else {
|
|
29
34
|
// No custom functions found - that's OK, we'll proxy everything
|
|
35
|
+
console.log('[Tether] No custom functions found, will proxy all requests');
|
|
30
36
|
functionRegistry = {};
|
|
31
37
|
}
|
|
32
38
|
} catch (error) {
|
|
@@ -234,10 +240,12 @@ export default defineEventHandler(async (event) => {
|
|
|
234
240
|
|
|
235
241
|
// Try to find a custom function
|
|
236
242
|
const customFn = lookupFunction(body.function);
|
|
243
|
+
console.log(`[Tether] Mutation: ${body.function}, custom function found: ${!!customFn}`);
|
|
237
244
|
|
|
238
245
|
if (customFn) {
|
|
239
246
|
// Execute locally with database proxy
|
|
240
247
|
try {
|
|
248
|
+
console.log(`[Tether] Executing custom mutation: ${body.function}`);
|
|
241
249
|
const db = createDatabaseProxy(apiKey, url, projectId);
|
|
242
250
|
|
|
243
251
|
// Create auth context - try to get user identity from request
|
|
@@ -247,24 +255,29 @@ export default defineEventHandler(async (event) => {
|
|
|
247
255
|
const authHeader = getHeader(event, 'authorization');
|
|
248
256
|
const strandsToken = getHeader(event, 'x-strands-token');
|
|
249
257
|
|
|
250
|
-
// If using Strands auth,
|
|
258
|
+
// If using Strands auth, validate the token via Tether server
|
|
251
259
|
if (strandsToken || authHeader?.startsWith('Bearer ')) {
|
|
252
260
|
const token = strandsToken || authHeader?.replace('Bearer ', '');
|
|
253
261
|
if (token) {
|
|
254
262
|
try {
|
|
255
|
-
//
|
|
256
|
-
const authResponse = await fetch(
|
|
257
|
-
|
|
263
|
+
// Validate token via Tether server (which checks if Strands Auth is enabled)
|
|
264
|
+
const authResponse = await fetch(`${url}/api/v1/projects/${projectId}/auth/validate`, {
|
|
265
|
+
method: 'POST',
|
|
266
|
+
headers: { 'Content-Type': 'application/json' },
|
|
267
|
+
body: JSON.stringify({ accessToken: token }),
|
|
258
268
|
});
|
|
259
269
|
if (authResponse.ok) {
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
270
|
+
const authData = await authResponse.json();
|
|
271
|
+
if (authData.valid) {
|
|
272
|
+
userIdentity = {
|
|
273
|
+
subject: authData.userId,
|
|
274
|
+
email: authData.email,
|
|
275
|
+
name: authData.name,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
266
278
|
}
|
|
267
|
-
} catch {
|
|
279
|
+
} catch (authError) {
|
|
280
|
+
console.warn('[Tether] Auth validation failed:', authError.message);
|
|
268
281
|
// Auth validation failed - continue without identity
|
|
269
282
|
}
|
|
270
283
|
}
|
|
@@ -291,9 +304,11 @@ export default defineEventHandler(async (event) => {
|
|
|
291
304
|
|
|
292
305
|
return { data: result };
|
|
293
306
|
} catch (error) {
|
|
307
|
+
console.error(`[Tether] Mutation ${body.function} failed:`, error);
|
|
294
308
|
throw createError({
|
|
295
309
|
statusCode: 500,
|
|
296
310
|
message: error.message || 'Mutation execution failed',
|
|
311
|
+
data: { function: body.function, error: String(error) },
|
|
297
312
|
});
|
|
298
313
|
}
|
|
299
314
|
}
|
|
@@ -255,24 +255,29 @@ export default defineEventHandler(async (event) => {
|
|
|
255
255
|
const authHeader = getHeader(event, 'authorization');
|
|
256
256
|
const strandsToken = getHeader(event, 'x-strands-token');
|
|
257
257
|
|
|
258
|
-
// If using Strands auth,
|
|
258
|
+
// If using Strands auth, validate the token via Tether server
|
|
259
259
|
if (strandsToken || authHeader?.startsWith('Bearer ')) {
|
|
260
260
|
const token = strandsToken || authHeader?.replace('Bearer ', '');
|
|
261
261
|
if (token) {
|
|
262
262
|
try {
|
|
263
|
-
//
|
|
264
|
-
const authResponse = await fetch(
|
|
265
|
-
|
|
263
|
+
// Validate token via Tether server (which checks if Strands Auth is enabled)
|
|
264
|
+
const authResponse = await fetch(`${url}/api/v1/projects/${projectId}/auth/validate`, {
|
|
265
|
+
method: 'POST',
|
|
266
|
+
headers: { 'Content-Type': 'application/json' },
|
|
267
|
+
body: JSON.stringify({ accessToken: token }),
|
|
266
268
|
});
|
|
267
269
|
if (authResponse.ok) {
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
270
|
+
const authData = await authResponse.json();
|
|
271
|
+
if (authData.valid) {
|
|
272
|
+
userIdentity = {
|
|
273
|
+
subject: authData.userId,
|
|
274
|
+
email: authData.email,
|
|
275
|
+
name: authData.name,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
274
278
|
}
|
|
275
|
-
} catch {
|
|
279
|
+
} catch (authError) {
|
|
280
|
+
console.warn('[Tether] Auth validation failed:', authError.message);
|
|
276
281
|
// Auth validation failed - continue without identity
|
|
277
282
|
}
|
|
278
283
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tthr/vue",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.25",
|
|
4
4
|
"description": "Tether Vue/Nuxt SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,11 +22,6 @@
|
|
|
22
22
|
"dist",
|
|
23
23
|
"nuxt"
|
|
24
24
|
],
|
|
25
|
-
"scripts": {
|
|
26
|
-
"build": "tsc",
|
|
27
|
-
"dev": "tsc --watch",
|
|
28
|
-
"typecheck": "tsc --noEmit"
|
|
29
|
-
},
|
|
30
25
|
"dependencies": {
|
|
31
26
|
"@nuxt/kit": "^3.14.0",
|
|
32
27
|
"@tthr/client": "latest",
|
|
@@ -37,5 +32,10 @@
|
|
|
37
32
|
},
|
|
38
33
|
"peerDependencies": {
|
|
39
34
|
"vue": "^3.0.0"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc",
|
|
38
|
+
"dev": "tsc --watch",
|
|
39
|
+
"typecheck": "tsc --noEmit"
|
|
40
40
|
}
|
|
41
|
-
}
|
|
41
|
+
}
|