@tthr/vue 0.0.80 → 0.0.82

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/nuxt/module.ts CHANGED
@@ -110,6 +110,14 @@ export default defineNuxtModule<TetherModuleOptions>({
110
110
  name: 'useTetherSubscription',
111
111
  from: resolver.resolve('./runtime/composables'),
112
112
  },
113
+ {
114
+ name: '$query',
115
+ from: resolver.resolve('./runtime/composables'),
116
+ },
117
+ {
118
+ name: '$mutation',
119
+ from: resolver.resolve('./runtime/composables'),
120
+ },
113
121
  ]);
114
122
 
115
123
  // Auto-import components
@@ -16,6 +16,12 @@ export interface QueryState<T> {
16
16
  isConnected: Ref<boolean>;
17
17
  refetch: () => Promise<void>;
18
18
  }
19
+ /**
20
+ * Thenable query state — can be awaited or destructured directly.
21
+ * When awaited, resolves after the initial fetch completes (data is populated).
22
+ * When destructured without await, data starts as undefined and populates reactively.
23
+ */
24
+ export type AsyncQueryState<T> = QueryState<T> & PromiseLike<QueryState<T>>;
19
25
  /**
20
26
  * Query function reference
21
27
  */
@@ -31,15 +37,33 @@ export interface QueryFunction<TArgs = void, TResult = unknown> {
31
37
  * Data is fetched on the server and hydrated on the client.
32
38
  * Automatically subscribes to WebSocket updates for realtime sync.
33
39
  *
40
+ * Can be used with or without await:
41
+ *
34
42
  * @example
35
43
  * ```vue
36
44
  * <script setup>
37
- * // That's it! Data automatically updates when it changes anywhere
45
+ * // Reactive data fills in asynchronously, updates in realtime
38
46
  * const { data: posts, isLoading, isConnected } = useQuery(api.posts.list);
47
+ *
48
+ * // Awaited — data is populated when the promise resolves, still updates in realtime
49
+ * const { data: posts } = await useQuery(api.posts.list);
39
50
  * </script>
40
51
  * ```
41
52
  */
42
- export declare function useQuery<TArgs, TResult>(query: QueryFunction<TArgs, TResult> | string, args?: TArgs): QueryState<TResult>;
53
+ export declare function useQuery<TArgs, TResult>(query: QueryFunction<TArgs, TResult> | string, args?: TArgs): AsyncQueryState<TResult>;
54
+ /**
55
+ * Execute a query and return raw data directly.
56
+ *
57
+ * Unlike useQuery, this does NOT set up reactive state or WebSocket subscriptions.
58
+ * Use this in event handlers, utilities, or anywhere you need a one-shot data fetch.
59
+ * Proxies through the Nuxt server route to keep API keys secure.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * const messages = await $query(api.messages.listByChannel, { channelId });
64
+ * ```
65
+ */
66
+ export declare function $query<TArgs, TResult>(query: QueryFunction<TArgs, TResult> | string, args?: TArgs): Promise<TResult>;
43
67
  /**
44
68
  * Mutation state returned by useMutation
45
69
  */
@@ -74,6 +98,19 @@ export interface MutationFunction<TArgs = void, TResult = unknown> {
74
98
  * ```
75
99
  */
76
100
  export declare function useMutation<TArgs, TResult>(mutation: MutationFunction<TArgs, TResult> | string): MutationState<TArgs, TResult>;
101
+ /**
102
+ * Execute a mutation and return the result directly.
103
+ *
104
+ * Unlike useMutation, this does NOT set up reactive state.
105
+ * Use this in event handlers, utilities, or anywhere you need a one-shot mutation.
106
+ * Proxies through the Nuxt server route to keep API keys secure.
107
+ *
108
+ * @example
109
+ * ```ts
110
+ * const post = await $mutation(api.posts.create, { title: 'Hello' });
111
+ * ```
112
+ */
113
+ export declare function $mutation<TArgs, TResult>(mutation: MutationFunction<TArgs, TResult> | string, args?: TArgs): Promise<TResult>;
77
114
  /**
78
115
  * Subscription handler options
79
116
  */
@@ -103,4 +140,3 @@ export interface SubscriptionHandlers {
103
140
  export declare function useTetherSubscription(queryName: string, args: Record<string, unknown> | undefined, handlers: SubscriptionHandlers | ((data?: unknown) => void)): {
104
141
  isConnected: Ref<boolean>;
105
142
  };
106
- //# sourceMappingURL=composables.d.ts.map
@@ -218,10 +218,12 @@ function createDatabaseProxy(apiKey, url, projectId) {
218
218
  const whereObj = options.where;
219
219
  // Support both _id (standard) and id (legacy) in where clause
220
220
  const id = whereObj?._id ?? whereObj?.id;
221
- if (!id) {
222
- throw new Error('Delete requires an _id in the where clause');
221
+ if (id) {
222
+ const result = await makeMutation('delete', { id });
223
+ return result?.rowsAffected ?? 0;
223
224
  }
224
- const result = await makeMutation('delete', { id });
225
+ // Compound where clause use deleteMany
226
+ const result = await makeMutation('deleteMany', { where: whereObj });
225
227
  return result?.rowsAffected ?? 0;
226
228
  },
227
229
  deleteById: async (id) => {
@@ -218,10 +218,12 @@ function createDatabaseProxy(apiKey, url, projectId) {
218
218
  const whereObj = options.where;
219
219
  // Support both _id (standard) and id (legacy) in where clause
220
220
  const id = whereObj?._id ?? whereObj?.id;
221
- if (!id) {
222
- throw new Error('Delete requires an _id in the where clause');
221
+ if (id) {
222
+ const result = await makeMutation('delete', { id });
223
+ return result?.rowsAffected ?? 0;
223
224
  }
224
- const result = await makeMutation('delete', { id });
225
+ // Compound where clause use deleteMany
226
+ const result = await makeMutation('deleteMany', { where: whereObj });
225
227
  return result?.rowsAffected ?? 0;
226
228
  },
227
229
  deleteById: async (id) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tthr/vue",
3
- "version": "0.0.80",
3
+ "version": "0.0.82",
4
4
  "description": "Tether Vue/Nuxt SDK",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",