@tthr/vue 0.0.44 → 0.0.45
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 +140 -1
- package/nuxt/module.ts +141 -0
- package/package.json +1 -1
package/nuxt/module.js
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* Environment variables (in .env):
|
|
19
19
|
* - TETHER_API_KEY: Your project's API key (required, kept server-side)
|
|
20
20
|
*/
|
|
21
|
-
import { defineNuxtModule, addPlugin, createResolver, addImports, addComponent, addServerHandler, addServerImports } from '@nuxt/kit';
|
|
21
|
+
import { defineNuxtModule, addPlugin, createResolver, addImports, addComponent, addServerHandler, addServerImports, addTemplate } from '@nuxt/kit';
|
|
22
22
|
export default defineNuxtModule({
|
|
23
23
|
meta: {
|
|
24
24
|
name: '@tthr/vue',
|
|
@@ -131,5 +131,144 @@ export default defineNuxtModule({
|
|
|
131
131
|
nitroConfig.externals.inline = nitroConfig.externals.inline || [];
|
|
132
132
|
nitroConfig.externals.inline.push('@tthr/vue');
|
|
133
133
|
});
|
|
134
|
+
// Generate a server plugin to auto-register cron handlers from tether/functions
|
|
135
|
+
// This runs at build time and creates a plugin that imports user's functions
|
|
136
|
+
addTemplate({
|
|
137
|
+
filename: 'server/plugins/tether-functions.ts',
|
|
138
|
+
write: true,
|
|
139
|
+
getContents: () => `
|
|
140
|
+
/**
|
|
141
|
+
* Auto-generated plugin to register Tether functions as cron handlers
|
|
142
|
+
* This file is generated by @tthr/vue/nuxt module
|
|
143
|
+
*/
|
|
144
|
+
import { defineNitroPlugin } from 'nitropack/runtime';
|
|
145
|
+
import { registerCronHandler } from '@tthr/vue/nuxt/runtime/server/plugins/cron.js';
|
|
146
|
+
import { useTetherServer } from '@tthr/vue/nuxt/runtime/server/utils/tether.js';
|
|
147
|
+
|
|
148
|
+
// Import all functions from tether/functions
|
|
149
|
+
// @ts-ignore - user's functions may not exist yet
|
|
150
|
+
import * as tetherFunctions from '~/tether/functions';
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Create a simple logger for function execution
|
|
154
|
+
*/
|
|
155
|
+
function createLogger(functionName: string) {
|
|
156
|
+
const prefix = \`[Tether] \${functionName}\`;
|
|
157
|
+
return {
|
|
158
|
+
log: (msg: string, data?: unknown) => console.log(prefix, msg, data !== undefined ? data : ''),
|
|
159
|
+
info: (msg: string, data?: unknown) => console.log(prefix, msg, data !== undefined ? data : ''),
|
|
160
|
+
warn: (msg: string, data?: unknown) => console.warn(prefix, msg, data !== undefined ? data : ''),
|
|
161
|
+
error: (msg: string, data?: unknown) => console.error(prefix, msg, data !== undefined ? data : ''),
|
|
162
|
+
debug: (msg: string, data?: unknown) => console.debug(prefix, msg, data !== undefined ? data : ''),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Create the handler context for a function
|
|
168
|
+
*/
|
|
169
|
+
function createHandlerContext(functionName: string, args: unknown) {
|
|
170
|
+
const tether = useTetherServer(null as any);
|
|
171
|
+
const log = createLogger(functionName);
|
|
172
|
+
|
|
173
|
+
// Create db proxy that uses tether server client
|
|
174
|
+
// TODO: This is a placeholder - proper db operations need to be implemented
|
|
175
|
+
const db = new Proxy({}, {
|
|
176
|
+
get(_, tableName: string) {
|
|
177
|
+
return {
|
|
178
|
+
findMany: async (options?: any) => {
|
|
179
|
+
// Call Tether API for db operations
|
|
180
|
+
return tether.query(\`_db.\${tableName}.findMany\`, options);
|
|
181
|
+
},
|
|
182
|
+
findFirst: async (options?: any) => {
|
|
183
|
+
return tether.query(\`_db.\${tableName}.findFirst\`, options);
|
|
184
|
+
},
|
|
185
|
+
findUnique: async (options?: any) => {
|
|
186
|
+
return tether.query(\`_db.\${tableName}.findUnique\`, options);
|
|
187
|
+
},
|
|
188
|
+
findById: async (id: unknown) => {
|
|
189
|
+
return tether.query(\`_db.\${tableName}.findById\`, { id });
|
|
190
|
+
},
|
|
191
|
+
count: async (options?: any) => {
|
|
192
|
+
return tether.query(\`_db.\${tableName}.count\`, options);
|
|
193
|
+
},
|
|
194
|
+
create: async (options: any) => {
|
|
195
|
+
return tether.mutation(\`_db.\${tableName}.create\`, options);
|
|
196
|
+
},
|
|
197
|
+
insert: async (data: any) => {
|
|
198
|
+
return tether.mutation(\`_db.\${tableName}.insert\`, { data });
|
|
199
|
+
},
|
|
200
|
+
insertMany: async (data: any[]) => {
|
|
201
|
+
return tether.mutation(\`_db.\${tableName}.insertMany\`, { data });
|
|
202
|
+
},
|
|
203
|
+
update: async (options: any) => {
|
|
204
|
+
return tether.mutation(\`_db.\${tableName}.update\`, options);
|
|
205
|
+
},
|
|
206
|
+
upsert: async (options: any) => {
|
|
207
|
+
return tether.mutation(\`_db.\${tableName}.upsert\`, options);
|
|
208
|
+
},
|
|
209
|
+
delete: async (options: any) => {
|
|
210
|
+
return tether.mutation(\`_db.\${tableName}.delete\`, options);
|
|
211
|
+
},
|
|
212
|
+
deleteById: async (id: unknown) => {
|
|
213
|
+
return tether.mutation(\`_db.\${tableName}.deleteById\`, { id });
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// Create tether context for actions
|
|
220
|
+
const tetherContext = {
|
|
221
|
+
query: tether.query.bind(tether),
|
|
222
|
+
mutation: tether.mutation.bind(tether),
|
|
223
|
+
env: new Proxy({}, {
|
|
224
|
+
get(_, key: string) {
|
|
225
|
+
return process.env[key];
|
|
226
|
+
},
|
|
227
|
+
}),
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
args,
|
|
232
|
+
db,
|
|
233
|
+
ctx: { auth: { userId: null, claims: {} }, userId: null },
|
|
234
|
+
log,
|
|
235
|
+
tether: tetherContext,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export default defineNitroPlugin(() => {
|
|
240
|
+
console.log('[Tether] Auto-registering functions from tether/functions...');
|
|
241
|
+
|
|
242
|
+
// Iterate through all exported modules
|
|
243
|
+
for (const [moduleName, moduleExports] of Object.entries(tetherFunctions)) {
|
|
244
|
+
if (!moduleExports || typeof moduleExports !== 'object') continue;
|
|
245
|
+
|
|
246
|
+
// Iterate through all exports in each module
|
|
247
|
+
for (const [fnName, fnDef] of Object.entries(moduleExports as Record<string, any>)) {
|
|
248
|
+
// Check if it's a Tether function definition (has handler property)
|
|
249
|
+
if (!fnDef || typeof fnDef !== 'object' || typeof fnDef.handler !== 'function') continue;
|
|
250
|
+
|
|
251
|
+
const fullName = \`\${moduleName}.\${fnName}\`;
|
|
252
|
+
|
|
253
|
+
// Register the cron handler
|
|
254
|
+
registerCronHandler(fullName, async (args: unknown) => {
|
|
255
|
+
const context = createHandlerContext(fullName, args);
|
|
256
|
+
return fnDef.handler(context);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
console.log(\`[Tether] Registered handler: \${fullName}\`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
console.log('[Tether] Function registration complete');
|
|
264
|
+
});
|
|
265
|
+
`,
|
|
266
|
+
});
|
|
267
|
+
// Add the generated plugin to Nitro
|
|
268
|
+
nuxt.hook('nitro:config', (nitroConfig) => {
|
|
269
|
+
nitroConfig.plugins = nitroConfig.plugins || [];
|
|
270
|
+
// Add our generated plugin after the cron plugin
|
|
271
|
+
nitroConfig.plugins.push('#build/server/plugins/tether-functions');
|
|
272
|
+
});
|
|
134
273
|
},
|
|
135
274
|
});
|
package/nuxt/module.ts
CHANGED
|
@@ -155,5 +155,146 @@ export default defineNuxtModule<TetherModuleOptions>({
|
|
|
155
155
|
nitroConfig.externals.inline = nitroConfig.externals.inline || [];
|
|
156
156
|
nitroConfig.externals.inline.push('@tthr/vue');
|
|
157
157
|
});
|
|
158
|
+
|
|
159
|
+
// Generate a server plugin to auto-register cron handlers from tether/functions
|
|
160
|
+
// This runs at build time and creates a plugin that imports user's functions
|
|
161
|
+
addTemplate({
|
|
162
|
+
filename: 'server/plugins/tether-functions.ts',
|
|
163
|
+
write: true,
|
|
164
|
+
getContents: () => `
|
|
165
|
+
/**
|
|
166
|
+
* Auto-generated plugin to register Tether functions as cron handlers
|
|
167
|
+
* This file is generated by @tthr/vue/nuxt module
|
|
168
|
+
*/
|
|
169
|
+
import { defineNitroPlugin } from 'nitropack/runtime';
|
|
170
|
+
import { registerCronHandler } from '@tthr/vue/nuxt/runtime/server/plugins/cron.js';
|
|
171
|
+
import { useTetherServer } from '@tthr/vue/nuxt/runtime/server/utils/tether.js';
|
|
172
|
+
|
|
173
|
+
// Import all functions from tether/functions
|
|
174
|
+
// @ts-ignore - user's functions may not exist yet
|
|
175
|
+
import * as tetherFunctions from '~/tether/functions';
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Create a simple logger for function execution
|
|
179
|
+
*/
|
|
180
|
+
function createLogger(functionName: string) {
|
|
181
|
+
const prefix = \`[Tether] \${functionName}\`;
|
|
182
|
+
return {
|
|
183
|
+
log: (msg: string, data?: unknown) => console.log(prefix, msg, data !== undefined ? data : ''),
|
|
184
|
+
info: (msg: string, data?: unknown) => console.log(prefix, msg, data !== undefined ? data : ''),
|
|
185
|
+
warn: (msg: string, data?: unknown) => console.warn(prefix, msg, data !== undefined ? data : ''),
|
|
186
|
+
error: (msg: string, data?: unknown) => console.error(prefix, msg, data !== undefined ? data : ''),
|
|
187
|
+
debug: (msg: string, data?: unknown) => console.debug(prefix, msg, data !== undefined ? data : ''),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Create the handler context for a function
|
|
193
|
+
*/
|
|
194
|
+
function createHandlerContext(functionName: string, args: unknown) {
|
|
195
|
+
const tether = useTetherServer(null as any);
|
|
196
|
+
const log = createLogger(functionName);
|
|
197
|
+
|
|
198
|
+
// Create db proxy that uses tether server client
|
|
199
|
+
// TODO: This is a placeholder - proper db operations need to be implemented
|
|
200
|
+
const db = new Proxy({}, {
|
|
201
|
+
get(_, tableName: string) {
|
|
202
|
+
return {
|
|
203
|
+
findMany: async (options?: any) => {
|
|
204
|
+
// Call Tether API for db operations
|
|
205
|
+
return tether.query(\`_db.\${tableName}.findMany\`, options);
|
|
206
|
+
},
|
|
207
|
+
findFirst: async (options?: any) => {
|
|
208
|
+
return tether.query(\`_db.\${tableName}.findFirst\`, options);
|
|
209
|
+
},
|
|
210
|
+
findUnique: async (options?: any) => {
|
|
211
|
+
return tether.query(\`_db.\${tableName}.findUnique\`, options);
|
|
212
|
+
},
|
|
213
|
+
findById: async (id: unknown) => {
|
|
214
|
+
return tether.query(\`_db.\${tableName}.findById\`, { id });
|
|
215
|
+
},
|
|
216
|
+
count: async (options?: any) => {
|
|
217
|
+
return tether.query(\`_db.\${tableName}.count\`, options);
|
|
218
|
+
},
|
|
219
|
+
create: async (options: any) => {
|
|
220
|
+
return tether.mutation(\`_db.\${tableName}.create\`, options);
|
|
221
|
+
},
|
|
222
|
+
insert: async (data: any) => {
|
|
223
|
+
return tether.mutation(\`_db.\${tableName}.insert\`, { data });
|
|
224
|
+
},
|
|
225
|
+
insertMany: async (data: any[]) => {
|
|
226
|
+
return tether.mutation(\`_db.\${tableName}.insertMany\`, { data });
|
|
227
|
+
},
|
|
228
|
+
update: async (options: any) => {
|
|
229
|
+
return tether.mutation(\`_db.\${tableName}.update\`, options);
|
|
230
|
+
},
|
|
231
|
+
upsert: async (options: any) => {
|
|
232
|
+
return tether.mutation(\`_db.\${tableName}.upsert\`, options);
|
|
233
|
+
},
|
|
234
|
+
delete: async (options: any) => {
|
|
235
|
+
return tether.mutation(\`_db.\${tableName}.delete\`, options);
|
|
236
|
+
},
|
|
237
|
+
deleteById: async (id: unknown) => {
|
|
238
|
+
return tether.mutation(\`_db.\${tableName}.deleteById\`, { id });
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// Create tether context for actions
|
|
245
|
+
const tetherContext = {
|
|
246
|
+
query: tether.query.bind(tether),
|
|
247
|
+
mutation: tether.mutation.bind(tether),
|
|
248
|
+
env: new Proxy({}, {
|
|
249
|
+
get(_, key: string) {
|
|
250
|
+
return process.env[key];
|
|
251
|
+
},
|
|
252
|
+
}),
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
return {
|
|
256
|
+
args,
|
|
257
|
+
db,
|
|
258
|
+
ctx: { auth: { userId: null, claims: {} }, userId: null },
|
|
259
|
+
log,
|
|
260
|
+
tether: tetherContext,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export default defineNitroPlugin(() => {
|
|
265
|
+
console.log('[Tether] Auto-registering functions from tether/functions...');
|
|
266
|
+
|
|
267
|
+
// Iterate through all exported modules
|
|
268
|
+
for (const [moduleName, moduleExports] of Object.entries(tetherFunctions)) {
|
|
269
|
+
if (!moduleExports || typeof moduleExports !== 'object') continue;
|
|
270
|
+
|
|
271
|
+
// Iterate through all exports in each module
|
|
272
|
+
for (const [fnName, fnDef] of Object.entries(moduleExports as Record<string, any>)) {
|
|
273
|
+
// Check if it's a Tether function definition (has handler property)
|
|
274
|
+
if (!fnDef || typeof fnDef !== 'object' || typeof fnDef.handler !== 'function') continue;
|
|
275
|
+
|
|
276
|
+
const fullName = \`\${moduleName}.\${fnName}\`;
|
|
277
|
+
|
|
278
|
+
// Register the cron handler
|
|
279
|
+
registerCronHandler(fullName, async (args: unknown) => {
|
|
280
|
+
const context = createHandlerContext(fullName, args);
|
|
281
|
+
return fnDef.handler(context);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
console.log(\`[Tether] Registered handler: \${fullName}\`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
console.log('[Tether] Function registration complete');
|
|
289
|
+
});
|
|
290
|
+
`,
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// Add the generated plugin to Nitro
|
|
294
|
+
nuxt.hook('nitro:config' as any, (nitroConfig: any) => {
|
|
295
|
+
nitroConfig.plugins = nitroConfig.plugins || [];
|
|
296
|
+
// Add our generated plugin after the cron plugin
|
|
297
|
+
nitroConfig.plugins.push('#build/server/plugins/tether-functions');
|
|
298
|
+
});
|
|
158
299
|
},
|
|
159
300
|
});
|