@tthr/vue 0.0.30 → 0.0.32

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.js ADDED
@@ -0,0 +1,133 @@
1
+ /**
2
+ * @tthr/vue/nuxt - Tether Nuxt Module
3
+ *
4
+ * Automatically configures Tether for Nuxt applications.
5
+ * All API calls are proxied through Nuxt server routes to keep API keys secure.
6
+ *
7
+ * Usage in nuxt.config.ts:
8
+ * ```ts
9
+ * export default defineNuxtConfig({
10
+ * modules: ['@tthr/vue/nuxt'],
11
+ * tether: {
12
+ * projectId: 'your-project-id',
13
+ * url: 'https://api.tether.strands.gg', // optional
14
+ * },
15
+ * })
16
+ * ```
17
+ *
18
+ * Environment variables (in .env):
19
+ * - TETHER_API_KEY: Your project's API key (required, kept server-side)
20
+ */
21
+ import { defineNuxtModule, addPlugin, createResolver, addImports, addComponent, addServerHandler, addServerImports } from '@nuxt/kit';
22
+ export default defineNuxtModule({
23
+ meta: {
24
+ name: '@tthr/vue',
25
+ configKey: 'tether',
26
+ compatibility: {
27
+ nuxt: '>=3.0.0',
28
+ },
29
+ },
30
+ defaults: {
31
+ projectId: undefined,
32
+ url: undefined,
33
+ },
34
+ setup(options, nuxt) {
35
+ const resolver = createResolver(import.meta.url);
36
+ // Get values from options or env vars (build-time defaults)
37
+ // These can be overridden at runtime via NUXT_TETHER_* and NUXT_PUBLIC_TETHER_* env vars
38
+ const apiKey = process.env.TETHER_API_KEY || '';
39
+ const url = options.url || process.env.TETHER_URL || 'https://tether-api.strands.gg';
40
+ const projectId = options.projectId || process.env.TETHER_PROJECT_ID || '';
41
+ // Calculate WebSocket URL from HTTP URL
42
+ const wsUrl = url.replace(/^https:/, 'wss:').replace(/^http:/, 'ws:');
43
+ // Server-side config (includes API key - never exposed to client)
44
+ // Can be overridden at runtime via:
45
+ // - NUXT_TETHER_API_KEY
46
+ // - NUXT_TETHER_URL
47
+ // - NUXT_TETHER_PROJECT_ID
48
+ nuxt.options.runtimeConfig.tether = {
49
+ apiKey,
50
+ url,
51
+ projectId,
52
+ };
53
+ // Public config (safe for client - no secrets)
54
+ // Can be overridden at runtime via:
55
+ // - NUXT_PUBLIC_TETHER_PROJECT_ID
56
+ // - NUXT_PUBLIC_TETHER_WS_URL
57
+ nuxt.options.runtimeConfig.public.tether = {
58
+ projectId,
59
+ wsUrl,
60
+ };
61
+ // Add server API routes for proxying Tether requests
62
+ addServerHandler({
63
+ route: '/api/_tether/query',
64
+ method: 'post',
65
+ handler: resolver.resolve('./runtime/server/query.post.js'),
66
+ });
67
+ addServerHandler({
68
+ route: '/api/_tether/mutation',
69
+ method: 'post',
70
+ handler: resolver.resolve('./runtime/server/mutation.post.js'),
71
+ });
72
+ // Add the client plugin for WebSocket subscriptions only
73
+ addPlugin({
74
+ src: resolver.resolve('./runtime/plugin.client'),
75
+ mode: 'client',
76
+ });
77
+ // Auto-import composables so users don't need explicit imports
78
+ addImports([
79
+ {
80
+ name: 'useQuery',
81
+ from: resolver.resolve('./runtime/composables'),
82
+ },
83
+ {
84
+ name: 'useMutation',
85
+ from: resolver.resolve('./runtime/composables'),
86
+ },
87
+ {
88
+ name: 'useTetherSubscription',
89
+ from: resolver.resolve('./runtime/composables'),
90
+ },
91
+ ]);
92
+ // Auto-import components
93
+ addComponent({
94
+ name: 'TetherWelcome',
95
+ filePath: resolver.resolve('./runtime/components/TetherWelcome.vue'),
96
+ });
97
+ // Auto-import server utilities (available in server/ directory)
98
+ // Use .js extensions to ensure the pre-built files are used
99
+ addServerImports([
100
+ {
101
+ name: 'useTetherServer',
102
+ from: resolver.resolve('./runtime/server/utils/tether.js'),
103
+ },
104
+ {
105
+ name: 'registerCronHandler',
106
+ from: resolver.resolve('./runtime/server/plugins/cron.js'),
107
+ },
108
+ {
109
+ name: 'unregisterCronHandler',
110
+ from: resolver.resolve('./runtime/server/plugins/cron.js'),
111
+ },
112
+ {
113
+ name: 'getCronHandlers',
114
+ from: resolver.resolve('./runtime/server/plugins/cron.js'),
115
+ },
116
+ ]);
117
+ // Ensure the runtime files are transpiled
118
+ nuxt.options.build.transpile = nuxt.options.build.transpile || [];
119
+ nuxt.options.build.transpile.push('@tthr/vue');
120
+ // Add Nitro plugin for cron WebSocket connection
121
+ // This auto-connects to Tether when the server starts
122
+ // Use .js extension to ensure the pre-built file is used
123
+ nuxt.hook('nitro:config', (nitroConfig) => {
124
+ nitroConfig.plugins = nitroConfig.plugins || [];
125
+ nitroConfig.plugins.push(resolver.resolve('./runtime/server/plugins/cron.js'));
126
+ // Ensure Nitro inlines and transpiles the plugin from node_modules
127
+ nitroConfig.externals = nitroConfig.externals || {};
128
+ nitroConfig.externals.inline = nitroConfig.externals.inline || [];
129
+ nitroConfig.externals.inline.push('@tthr/vue');
130
+ });
131
+ },
132
+ });
133
+ //# sourceMappingURL=module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.js","sourceRoot":"","sources":["module.ts"],"names":[],"mappings":"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"}
package/nuxt/module.ts CHANGED
@@ -114,30 +114,41 @@ export default defineNuxtModule<TetherModuleOptions>({
114
114
  });
115
115
 
116
116
  // Auto-import server utilities (available in server/ directory)
117
+ // Use .js extensions to ensure the pre-built files are used
117
118
  addServerImports([
118
119
  {
119
120
  name: 'useTetherServer',
120
- from: resolver.resolve('./runtime/server/utils/tether'),
121
+ from: resolver.resolve('./runtime/server/utils/tether.js'),
121
122
  },
122
123
  {
123
124
  name: 'registerCronHandler',
124
- from: resolver.resolve('./runtime/server/plugins/cron'),
125
+ from: resolver.resolve('./runtime/server/plugins/cron.js'),
125
126
  },
126
127
  {
127
128
  name: 'unregisterCronHandler',
128
- from: resolver.resolve('./runtime/server/plugins/cron'),
129
+ from: resolver.resolve('./runtime/server/plugins/cron.js'),
129
130
  },
130
131
  {
131
132
  name: 'getCronHandlers',
132
- from: resolver.resolve('./runtime/server/plugins/cron'),
133
+ from: resolver.resolve('./runtime/server/plugins/cron.js'),
133
134
  },
134
135
  ]);
135
136
 
137
+ // Ensure the runtime files are transpiled
138
+ nuxt.options.build.transpile = nuxt.options.build.transpile || [];
139
+ nuxt.options.build.transpile.push('@tthr/vue');
140
+
136
141
  // Add Nitro plugin for cron WebSocket connection
137
142
  // This auto-connects to Tether when the server starts
143
+ // Use .js extension to ensure the pre-built file is used
138
144
  nuxt.hook('nitro:config', (nitroConfig) => {
139
145
  nitroConfig.plugins = nitroConfig.plugins || [];
140
- nitroConfig.plugins.push(resolver.resolve('./runtime/server/plugins/cron'));
146
+ nitroConfig.plugins.push(resolver.resolve('./runtime/server/plugins/cron.js'));
147
+
148
+ // Ensure Nitro inlines and transpiles the plugin from node_modules
149
+ nitroConfig.externals = nitroConfig.externals || {};
150
+ nitroConfig.externals.inline = nitroConfig.externals.inline || [];
151
+ nitroConfig.externals.inline.push('@tthr/vue');
141
152
  });
142
153
  },
143
154
  });
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Nuxt composables for Tether
3
+ *
4
+ * These are auto-imported when using the Tether Nuxt module.
5
+ * Queries and mutations are executed server-side to keep API keys secure.
6
+ * WebSocket subscriptions run client-side for realtime updates.
7
+ */
8
+ import { type Ref } from 'vue';
9
+ /**
10
+ * Query state returned by useQuery
11
+ */
12
+ export interface QueryState<T> {
13
+ data: Ref<T | undefined>;
14
+ error: Ref<Error | null>;
15
+ isLoading: Ref<boolean>;
16
+ refetch: () => Promise<void>;
17
+ /** Update data directly (used for hot-swapping from WebSocket) */
18
+ setData: (newData: T) => void;
19
+ }
20
+ /**
21
+ * Query function reference
22
+ */
23
+ export interface QueryFunction<TArgs = void, TResult = unknown> {
24
+ _name: string;
25
+ _args?: TArgs;
26
+ _result?: TResult;
27
+ }
28
+ /**
29
+ * Reactive query composable with auto-refresh on subscription updates
30
+ *
31
+ * @example
32
+ * ```vue
33
+ * <script setup>
34
+ * const { data: posts, isLoading } = useQuery(api.posts.list);
35
+ * </script>
36
+ * ```
37
+ */
38
+ export declare function useQuery<TArgs, TResult>(query: QueryFunction<TArgs, TResult> | string, args?: TArgs): QueryState<TResult>;
39
+ /**
40
+ * Mutation state returned by useMutation
41
+ */
42
+ export interface MutationState<TArgs, TResult> {
43
+ data: Ref<TResult | undefined>;
44
+ error: Ref<Error | null>;
45
+ isPending: Ref<boolean>;
46
+ mutate: (args: TArgs) => Promise<TResult>;
47
+ reset: () => void;
48
+ }
49
+ /**
50
+ * Mutation function reference
51
+ */
52
+ export interface MutationFunction<TArgs = void, TResult = unknown> {
53
+ _name: string;
54
+ _args?: TArgs;
55
+ _result?: TResult;
56
+ }
57
+ /**
58
+ * Mutation composable
59
+ *
60
+ * @example
61
+ * ```vue
62
+ * <script setup>
63
+ * const { mutate: createPost, isPending } = useMutation(api.posts.create);
64
+ *
65
+ * async function handleSubmit() {
66
+ * await createPost({ title: 'Hello', content: '...' });
67
+ * }
68
+ * </script>
69
+ * ```
70
+ */
71
+ export declare function useMutation<TArgs, TResult>(mutation: MutationFunction<TArgs, TResult> | string): MutationState<TArgs, TResult>;
72
+ /**
73
+ * WebSocket subscription composable for realtime updates
74
+ * This runs client-side only and calls refetch when updates are received
75
+ *
76
+ * @example
77
+ * ```vue
78
+ * <script setup>
79
+ * const { data: posts, refetch } = useQuery('posts.list');
80
+ * useTetherSubscription('posts.list', {}, refetch);
81
+ * </script>
82
+ * ```
83
+ */
84
+ export declare function useTetherSubscription(queryName: string, args: Record<string, unknown> | undefined, onUpdate: (data?: unknown) => void): {
85
+ isConnected: Ref<boolean>;
86
+ };
87
+ //# sourceMappingURL=composables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composables.d.ts","sourceRoot":"","sources":["composables.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAA+B,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IACzB,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IACzB,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACxB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,kEAAkE;IAClE,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,IAAI,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,GAAG,OAAO;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EACrC,KAAK,EAAE,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,MAAM,EAC7C,IAAI,CAAC,EAAE,KAAK,GACX,UAAU,CAAC,OAAO,CAAC,CAiDrB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,KAAK,EAAE,OAAO;IAC3C,IAAI,EAAE,GAAG,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;IAC/B,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IACzB,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACxB,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1C,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,GAAG,OAAO;IAC/D,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EACxC,QAAQ,EAAE,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,MAAM,GAClD,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CA0C/B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EACzC,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,GACjC;IAAE,WAAW,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;CAAE,CA4J/B"}
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Nuxt composables for Tether
3
+ *
4
+ * These are auto-imported when using the Tether Nuxt module.
5
+ * Queries and mutations are executed server-side to keep API keys secure.
6
+ * WebSocket subscriptions run client-side for realtime updates.
7
+ */
8
+ import { ref, onMounted, onUnmounted } from 'vue';
9
+ /**
10
+ * Reactive query composable with auto-refresh on subscription updates
11
+ *
12
+ * @example
13
+ * ```vue
14
+ * <script setup>
15
+ * const { data: posts, isLoading } = useQuery(api.posts.list);
16
+ * </script>
17
+ * ```
18
+ */
19
+ export function useQuery(query, args) {
20
+ const queryName = typeof query === 'string' ? query : query._name;
21
+ const data = ref();
22
+ const error = ref(null);
23
+ const isLoading = ref(true);
24
+ const fetchData = async () => {
25
+ try {
26
+ isLoading.value = true;
27
+ error.value = null;
28
+ const response = await $fetch('/api/_tether/query', {
29
+ method: 'POST',
30
+ body: {
31
+ function: queryName,
32
+ args,
33
+ },
34
+ });
35
+ data.value = response.data;
36
+ }
37
+ catch (e) {
38
+ error.value = e instanceof Error ? e : new Error(String(e));
39
+ }
40
+ finally {
41
+ isLoading.value = false;
42
+ }
43
+ };
44
+ // Fetch on mount (client-side)
45
+ onMounted(() => {
46
+ fetchData();
47
+ });
48
+ // Also fetch immediately for SSR
49
+ if (import.meta.server) {
50
+ fetchData();
51
+ }
52
+ // Direct data setter for hot-swapping from WebSocket
53
+ const setData = (newData) => {
54
+ data.value = newData;
55
+ };
56
+ return {
57
+ data: data,
58
+ error,
59
+ isLoading,
60
+ refetch: fetchData,
61
+ setData,
62
+ };
63
+ }
64
+ /**
65
+ * Mutation composable
66
+ *
67
+ * @example
68
+ * ```vue
69
+ * <script setup>
70
+ * const { mutate: createPost, isPending } = useMutation(api.posts.create);
71
+ *
72
+ * async function handleSubmit() {
73
+ * await createPost({ title: 'Hello', content: '...' });
74
+ * }
75
+ * </script>
76
+ * ```
77
+ */
78
+ export function useMutation(mutation) {
79
+ const mutationName = typeof mutation === 'string' ? mutation : mutation._name;
80
+ const data = ref();
81
+ const error = ref(null);
82
+ const isPending = ref(false);
83
+ const mutate = async (args) => {
84
+ try {
85
+ isPending.value = true;
86
+ error.value = null;
87
+ const response = await $fetch('/api/_tether/mutation', {
88
+ method: 'POST',
89
+ body: {
90
+ function: mutationName,
91
+ args,
92
+ },
93
+ });
94
+ data.value = response.data;
95
+ return response.data;
96
+ }
97
+ catch (e) {
98
+ error.value = e instanceof Error ? e : new Error(String(e));
99
+ throw e;
100
+ }
101
+ finally {
102
+ isPending.value = false;
103
+ }
104
+ };
105
+ const reset = () => {
106
+ data.value = undefined;
107
+ error.value = null;
108
+ isPending.value = false;
109
+ };
110
+ return {
111
+ data: data,
112
+ error,
113
+ isPending,
114
+ mutate,
115
+ reset,
116
+ };
117
+ }
118
+ /**
119
+ * WebSocket subscription composable for realtime updates
120
+ * This runs client-side only and calls refetch when updates are received
121
+ *
122
+ * @example
123
+ * ```vue
124
+ * <script setup>
125
+ * const { data: posts, refetch } = useQuery('posts.list');
126
+ * useTetherSubscription('posts.list', {}, refetch);
127
+ * </script>
128
+ * ```
129
+ */
130
+ export function useTetherSubscription(queryName, args, onUpdate) {
131
+ const isConnected = ref(false);
132
+ if (import.meta.client) {
133
+ let ws = null;
134
+ let reconnectTimeout = null;
135
+ let heartbeatInterval = null;
136
+ let heartbeatTimeout = null;
137
+ let awaitingPong = false;
138
+ let isConnecting = false;
139
+ let isMounted = false;
140
+ // Heartbeat configuration
141
+ const HEARTBEAT_INTERVAL = 25000; // 25 seconds (well under server's 90s timeout)
142
+ const HEARTBEAT_TIMEOUT = 15000; // 15 seconds to receive pong (generous for slow networks)
143
+ // Generate a unique subscription ID
144
+ const subscriptionId = `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
145
+ const startHeartbeat = () => {
146
+ stopHeartbeat();
147
+ heartbeatInterval = setInterval(() => {
148
+ if (ws?.readyState === WebSocket.OPEN) {
149
+ awaitingPong = true;
150
+ ws.send(JSON.stringify({ type: 'ping' }));
151
+ heartbeatTimeout = setTimeout(() => {
152
+ if (awaitingPong && isMounted) {
153
+ console.warn('[Tether] Heartbeat timeout - forcing reconnect');
154
+ ws?.close();
155
+ }
156
+ }, HEARTBEAT_TIMEOUT);
157
+ }
158
+ }, HEARTBEAT_INTERVAL);
159
+ };
160
+ const stopHeartbeat = () => {
161
+ if (heartbeatInterval) {
162
+ clearInterval(heartbeatInterval);
163
+ heartbeatInterval = null;
164
+ }
165
+ if (heartbeatTimeout) {
166
+ clearTimeout(heartbeatTimeout);
167
+ heartbeatTimeout = null;
168
+ }
169
+ awaitingPong = false;
170
+ };
171
+ const connect = () => {
172
+ // Don't connect if unmounted or already connecting/connected
173
+ if (!isMounted)
174
+ return;
175
+ if (isConnecting)
176
+ return;
177
+ if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) {
178
+ return;
179
+ }
180
+ // Get config from window (set by plugin)
181
+ const config = window.__TETHER_CONFIG__;
182
+ if (!config?.wsUrl || !config?.projectId) {
183
+ console.warn('[Tether] WebSocket config not available');
184
+ return;
185
+ }
186
+ isConnecting = true;
187
+ const wsUrl = `${config.wsUrl}/ws/${config.projectId}`;
188
+ ws = new WebSocket(wsUrl);
189
+ ws.onopen = () => {
190
+ isConnecting = false;
191
+ // Wait for connected message before subscribing
192
+ };
193
+ ws.onmessage = (event) => {
194
+ try {
195
+ const message = JSON.parse(event.data);
196
+ if (message.type === 'connected') {
197
+ isConnected.value = true;
198
+ startHeartbeat();
199
+ // Subscribe to the query with our ID
200
+ ws?.send(JSON.stringify({
201
+ type: 'subscribe',
202
+ id: subscriptionId,
203
+ query: queryName,
204
+ args,
205
+ }));
206
+ }
207
+ else if (message.type === 'data' && message.id === subscriptionId) {
208
+ // Call onUpdate with the fresh data
209
+ onUpdate(message.data);
210
+ }
211
+ else if (message.type === 'pong') {
212
+ // Heartbeat acknowledged
213
+ awaitingPong = false;
214
+ if (heartbeatTimeout) {
215
+ clearTimeout(heartbeatTimeout);
216
+ heartbeatTimeout = null;
217
+ }
218
+ }
219
+ }
220
+ catch {
221
+ // Ignore parse errors
222
+ }
223
+ };
224
+ ws.onclose = () => {
225
+ isConnected.value = false;
226
+ isConnecting = false;
227
+ stopHeartbeat();
228
+ // Only reconnect if still mounted
229
+ if (isMounted) {
230
+ reconnectTimeout = setTimeout(connect, 3000);
231
+ }
232
+ };
233
+ ws.onerror = () => {
234
+ isConnecting = false;
235
+ ws?.close();
236
+ };
237
+ };
238
+ // Handle page visibility changes - reconnect when tab becomes visible
239
+ const handleVisibilityChange = () => {
240
+ if (!isMounted)
241
+ return;
242
+ if (document.visibilityState === 'visible') {
243
+ // Tab became visible - check connection health
244
+ if (!ws || ws.readyState === WebSocket.CLOSED) {
245
+ // Clear any pending reconnect and connect immediately
246
+ if (reconnectTimeout) {
247
+ clearTimeout(reconnectTimeout);
248
+ reconnectTimeout = null;
249
+ }
250
+ connect();
251
+ }
252
+ }
253
+ };
254
+ onMounted(() => {
255
+ isMounted = true;
256
+ connect();
257
+ document.addEventListener('visibilitychange', handleVisibilityChange);
258
+ });
259
+ onUnmounted(() => {
260
+ isMounted = false;
261
+ document.removeEventListener('visibilitychange', handleVisibilityChange);
262
+ stopHeartbeat();
263
+ if (reconnectTimeout) {
264
+ clearTimeout(reconnectTimeout);
265
+ reconnectTimeout = null;
266
+ }
267
+ if (ws) {
268
+ ws.close();
269
+ ws = null;
270
+ }
271
+ });
272
+ }
273
+ return { isConnected };
274
+ }
275
+ //# sourceMappingURL=composables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composables.js","sourceRoot":"","sources":["composables.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Client-side Tether plugin
3
+ *
4
+ * Sets up the WebSocket configuration for realtime subscriptions.
5
+ * This only exposes the project ID and WebSocket URL - no secrets.
6
+ */
7
+ declare global {
8
+ interface Window {
9
+ __TETHER_CONFIG__?: {
10
+ projectId: string;
11
+ wsUrl: string;
12
+ };
13
+ }
14
+ }
15
+ declare const _default: any;
16
+ export default _default;
17
+ //# sourceMappingURL=plugin.client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.client.d.ts","sourceRoot":"","sources":["plugin.client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,iBAAiB,CAAC,EAAE;YAClB,SAAS,EAAE,MAAM,CAAC;YAClB,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;KACH;CACF;;AAED,wBAeG"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Client-side Tether plugin
3
+ *
4
+ * Sets up the WebSocket configuration for realtime subscriptions.
5
+ * This only exposes the project ID and WebSocket URL - no secrets.
6
+ */
7
+ import { defineNuxtPlugin, useRuntimeConfig } from '#imports';
8
+ export default defineNuxtPlugin(() => {
9
+ const config = useRuntimeConfig();
10
+ // Make config available for WebSocket connections
11
+ // This is safe - no secrets are exposed
12
+ const tetherConfig = {
13
+ projectId: config.public.tether?.projectId || '',
14
+ wsUrl: config.public.tether?.wsUrl || '',
15
+ };
16
+ window.__TETHER_CONFIG__ = tetherConfig;
17
+ if (!tetherConfig.wsUrl || !tetherConfig.projectId) {
18
+ console.warn('[Tether] Config incomplete - WebSocket subscriptions will not work');
19
+ }
20
+ });
21
+ //# sourceMappingURL=plugin.client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.client.js","sourceRoot":"","sources":["plugin.client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAW9D,eAAe,gBAAgB,CAAC,GAAG,EAAE;IACnC,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAElC,kDAAkD;IAClD,wCAAwC;IACxC,MAAM,YAAY,GAAG;QACnB,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,IAAI,EAAE;QAChD,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;KACzC,CAAC;IAEF,MAAM,CAAC,iBAAiB,GAAG,YAAY,CAAC;IAExC,IAAI,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAC;IACrF,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Nuxt server plugin for Tether cron execution
3
+ *
4
+ * This plugin automatically connects to Tether via WebSocket as a server connection
5
+ * to receive cron triggers. When a cron is due, Tether sends a trigger message,
6
+ * this plugin executes the function, and reports the result back.
7
+ *
8
+ * The connection is secured with the API key and only server connections
9
+ * (identified by ?type=server) receive cron triggers.
10
+ */
11
+ /**
12
+ * Register a cron handler for a specific function
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * // In your Nuxt server setup
17
+ * import { registerCronHandler } from '#imports';
18
+ *
19
+ * registerCronHandler('reports.generate', async (args) => {
20
+ * // Your function logic here
21
+ * return { generated: true };
22
+ * });
23
+ * ```
24
+ */
25
+ export declare function registerCronHandler(functionName: string, handler: (args: unknown) => Promise<unknown>): void;
26
+ /**
27
+ * Unregister a cron handler
28
+ */
29
+ export declare function unregisterCronHandler(functionName: string): void;
30
+ /**
31
+ * Get all registered cron handlers
32
+ */
33
+ export declare function getCronHandlers(): string[];
34
+ declare const _default: any;
35
+ export default _default;
36
+ //# sourceMappingURL=cron.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["cron.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAsBH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAC3C,IAAI,CAGN;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAEhE;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C;;AAqPD,wBA+BG"}
@@ -0,0 +1,268 @@
1
+ /**
2
+ * Nuxt server plugin for Tether cron execution
3
+ *
4
+ * This plugin automatically connects to Tether via WebSocket as a server connection
5
+ * to receive cron triggers. When a cron is due, Tether sends a trigger message,
6
+ * this plugin executes the function, and reports the result back.
7
+ *
8
+ * The connection is secured with the API key and only server connections
9
+ * (identified by ?type=server) receive cron triggers.
10
+ */
11
+ import { defineNitroPlugin } from 'nitropack/runtime';
12
+ import { useRuntimeConfig } from '#imports';
13
+ // Store for registered cron handlers
14
+ const cronHandlers = new Map();
15
+ // WebSocket connection state
16
+ let ws = null;
17
+ let connectionId = null;
18
+ let reconnectAttempts = 0;
19
+ let heartbeatTimer = null;
20
+ let heartbeatTimeoutTimer = null;
21
+ let awaitingPong = false;
22
+ let shouldReconnect = true;
23
+ const MAX_RECONNECT_ATTEMPTS = 10;
24
+ const HEARTBEAT_INTERVAL = 30000;
25
+ const HEARTBEAT_TIMEOUT = 10000;
26
+ const RECONNECT_DELAY = 1000;
27
+ /**
28
+ * Register a cron handler for a specific function
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * // In your Nuxt server setup
33
+ * import { registerCronHandler } from '#imports';
34
+ *
35
+ * registerCronHandler('reports.generate', async (args) => {
36
+ * // Your function logic here
37
+ * return { generated: true };
38
+ * });
39
+ * ```
40
+ */
41
+ export function registerCronHandler(functionName, handler) {
42
+ cronHandlers.set(functionName, handler);
43
+ console.log(`[Tether Cron] Registered handler for: ${functionName}`);
44
+ }
45
+ /**
46
+ * Unregister a cron handler
47
+ */
48
+ export function unregisterCronHandler(functionName) {
49
+ cronHandlers.delete(functionName);
50
+ }
51
+ /**
52
+ * Get all registered cron handlers
53
+ */
54
+ export function getCronHandlers() {
55
+ return Array.from(cronHandlers.keys());
56
+ }
57
+ function getWsUrl(config) {
58
+ const base = config.url
59
+ .replace('https://', 'wss://')
60
+ .replace('http://', 'ws://')
61
+ .replace(/\/$/, '');
62
+ const env = config.environment;
63
+ let wsPath;
64
+ if (env && env !== 'production') {
65
+ wsPath = `${base}/ws/${config.projectId}/${env}`;
66
+ }
67
+ else {
68
+ wsPath = `${base}/ws/${config.projectId}`;
69
+ }
70
+ // Add type=server to identify as server connection and token for auth
71
+ return `${wsPath}?type=server&token=${encodeURIComponent(config.apiKey)}`;
72
+ }
73
+ async function reportExecution(config, trigger, result, durationMs) {
74
+ const base = config.url.replace(/\/$/, '');
75
+ const env = config.environment;
76
+ let apiPath;
77
+ if (env && env !== 'production') {
78
+ apiPath = `${base}/api/v1/projects/${config.projectId}/env/${env}`;
79
+ }
80
+ else {
81
+ apiPath = `${base}/api/v1/projects/${config.projectId}`;
82
+ }
83
+ const url = `${apiPath}/crons/${trigger.cronId}/executions`;
84
+ try {
85
+ const response = await fetch(url, {
86
+ method: 'POST',
87
+ headers: {
88
+ 'Content-Type': 'application/json',
89
+ 'Authorization': `Bearer ${config.apiKey}`,
90
+ },
91
+ body: JSON.stringify({
92
+ executionId: trigger.executionId,
93
+ success: result.success,
94
+ errorMessage: result.error,
95
+ result: result.result,
96
+ durationMs,
97
+ }),
98
+ });
99
+ if (!response.ok) {
100
+ console.error(`[Tether Cron] Failed to report execution: ${response.status} ${response.statusText}`);
101
+ }
102
+ else {
103
+ console.log(`[Tether Cron] Reported execution ${trigger.executionId}: ${result.success ? 'success' : 'failed'}`);
104
+ }
105
+ }
106
+ catch (error) {
107
+ console.error('[Tether Cron] Failed to report execution:', error);
108
+ }
109
+ }
110
+ async function handleCronTrigger(config, trigger) {
111
+ console.log(`[Tether Cron] Received trigger for ${trigger.functionName} (execution: ${trigger.executionId})`);
112
+ const startTime = Date.now();
113
+ const handler = cronHandlers.get(trigger.functionName);
114
+ if (!handler) {
115
+ console.warn(`[Tether Cron] No handler registered for: ${trigger.functionName}`);
116
+ const durationMs = Date.now() - startTime;
117
+ await reportExecution(config, trigger, {
118
+ success: false,
119
+ error: `No handler registered for function: ${trigger.functionName}`,
120
+ }, durationMs);
121
+ return;
122
+ }
123
+ try {
124
+ const result = await handler(trigger.args);
125
+ const durationMs = Date.now() - startTime;
126
+ await reportExecution(config, trigger, {
127
+ success: true,
128
+ result,
129
+ }, durationMs);
130
+ }
131
+ catch (error) {
132
+ const durationMs = Date.now() - startTime;
133
+ const errorMessage = error instanceof Error ? error.message : String(error);
134
+ console.error(`[Tether Cron] Handler error for ${trigger.functionName}:`, errorMessage);
135
+ await reportExecution(config, trigger, {
136
+ success: false,
137
+ error: errorMessage,
138
+ }, durationMs);
139
+ }
140
+ }
141
+ function startHeartbeat() {
142
+ stopHeartbeat();
143
+ heartbeatTimer = setInterval(() => {
144
+ if (ws?.readyState === WebSocket.OPEN) {
145
+ awaitingPong = true;
146
+ ws.send(JSON.stringify({ type: 'ping' }));
147
+ heartbeatTimeoutTimer = setTimeout(() => {
148
+ if (awaitingPong) {
149
+ console.warn('[Tether Cron] Heartbeat timeout - forcing reconnect');
150
+ ws?.close();
151
+ }
152
+ }, HEARTBEAT_TIMEOUT);
153
+ }
154
+ }, HEARTBEAT_INTERVAL);
155
+ }
156
+ function stopHeartbeat() {
157
+ if (heartbeatTimer) {
158
+ clearInterval(heartbeatTimer);
159
+ heartbeatTimer = null;
160
+ }
161
+ if (heartbeatTimeoutTimer) {
162
+ clearTimeout(heartbeatTimeoutTimer);
163
+ heartbeatTimeoutTimer = null;
164
+ }
165
+ awaitingPong = false;
166
+ }
167
+ function connect(config) {
168
+ if (ws?.readyState === WebSocket.OPEN || ws?.readyState === WebSocket.CONNECTING) {
169
+ return;
170
+ }
171
+ try {
172
+ const url = getWsUrl(config);
173
+ // Use ws package for Node.js
174
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
175
+ const WebSocketImpl = typeof WebSocket !== 'undefined' ? WebSocket : require('ws');
176
+ ws = new WebSocketImpl(url);
177
+ ws.onopen = () => {
178
+ reconnectAttempts = 0;
179
+ console.log('[Tether Cron] WebSocket connected');
180
+ };
181
+ ws.onmessage = async (event) => {
182
+ const data = typeof event.data === 'string' ? event.data : event.data.toString();
183
+ try {
184
+ const message = JSON.parse(data);
185
+ switch (message.type) {
186
+ case 'connected':
187
+ connectionId = message.connection_id ?? null;
188
+ startHeartbeat();
189
+ console.log(`[Tether Cron] Connected with ID: ${connectionId}`);
190
+ break;
191
+ case 'cron_trigger':
192
+ await handleCronTrigger(config, message);
193
+ break;
194
+ case 'pong':
195
+ awaitingPong = false;
196
+ if (heartbeatTimeoutTimer) {
197
+ clearTimeout(heartbeatTimeoutTimer);
198
+ heartbeatTimeoutTimer = null;
199
+ }
200
+ break;
201
+ case 'error':
202
+ console.error('[Tether Cron] Server error:', message.error);
203
+ break;
204
+ }
205
+ }
206
+ catch (e) {
207
+ console.error('[Tether Cron] Failed to parse message:', e);
208
+ }
209
+ };
210
+ ws.onerror = (error) => {
211
+ const err = error instanceof Error ? error : new Error('WebSocket error');
212
+ console.error('[Tether Cron] WebSocket error:', err.message);
213
+ };
214
+ ws.onclose = () => {
215
+ connectionId = null;
216
+ stopHeartbeat();
217
+ console.log('[Tether Cron] WebSocket disconnected');
218
+ handleReconnect(config);
219
+ };
220
+ }
221
+ catch (error) {
222
+ console.error('[Tether Cron] Failed to connect:', error);
223
+ handleReconnect(config);
224
+ }
225
+ }
226
+ function handleReconnect(config) {
227
+ if (!shouldReconnect) {
228
+ return;
229
+ }
230
+ if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
231
+ console.error('[Tether Cron] Max reconnection attempts reached');
232
+ return;
233
+ }
234
+ reconnectAttempts++;
235
+ const delay = Math.min(RECONNECT_DELAY * Math.pow(2, reconnectAttempts - 1), 30000);
236
+ console.log(`[Tether Cron] Reconnecting in ${delay}ms (attempt ${reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})`);
237
+ setTimeout(() => {
238
+ connect(config);
239
+ }, delay);
240
+ }
241
+ export default defineNitroPlugin((nitro) => {
242
+ // Get config from runtime config
243
+ const config = useRuntimeConfig();
244
+ const apiKey = config.tether?.apiKey || process.env.TETHER_API_KEY;
245
+ const url = config.tether?.url || process.env.TETHER_URL || 'https://tether-api.strands.gg';
246
+ const projectId = config.tether?.projectId || process.env.TETHER_PROJECT_ID;
247
+ // Only connect if we have all required config
248
+ if (!apiKey || !projectId) {
249
+ console.log('[Tether Cron] Missing config (apiKey or projectId) - cron connection disabled');
250
+ return;
251
+ }
252
+ console.log('[Tether Cron] Initialising cron connection...');
253
+ // Connect on next tick to allow handlers to be registered first
254
+ process.nextTick(() => {
255
+ connect({ url, projectId, apiKey });
256
+ });
257
+ // Clean up on shutdown
258
+ nitro.hooks.hook('close', () => {
259
+ shouldReconnect = false;
260
+ stopHeartbeat();
261
+ if (ws) {
262
+ ws.close();
263
+ ws = null;
264
+ }
265
+ console.log('[Tether Cron] Connection closed');
266
+ });
267
+ });
268
+ //# sourceMappingURL=cron.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron.js","sourceRoot":"","sources":["cron.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tthr/vue",
3
- "version": "0.0.30",
3
+ "version": "0.0.32",
4
4
  "description": "Tether Vue/Nuxt SDK",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",