@wervt/nuxt 0.2.13 → 0.2.14

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/README.md CHANGED
@@ -20,6 +20,7 @@ export default defineNuxtConfig({
20
20
  - `useWervtUser()`: the signed-in wervt user, on the server and in the app.
21
21
  - `useValidatedBody()` / `useValidatedQuery()` / `useValidatedParams()`: valibot validation.
22
22
  - `useWervtTrack()`: custom events for wervt's cookieless analytics (page views are counted automatically).
23
+ - `wervt: { feedback: { key } }` and `useWervtFeedback()`: the kontor feedback widget, reports go into a kontor project's triage.
23
24
  - `defineTool()` (server): tools in `server/tools/` that browser agents call through WebMCP, and
24
25
  MCP clients (Claude Code, Cursor, …) at `/mcp`, signed in through wervt's OAuth login.
25
26
  - `nuxt dev` starts against the local wervt stack (Postgres, Electric) and a dev user.
package/dist/module.d.ts CHANGED
@@ -30,6 +30,28 @@ export interface ModuleOptions {
30
30
  * counted by the runtime either way.
31
31
  */
32
32
  analytics?: boolean;
33
+ /**
34
+ * The kontor feedback widget: a "Feedback" button that reports issues into a kontor project's
35
+ * triage, as the signed-in wervt user when the app's URL is an allowed origin of the key.
36
+ * With `true`, the key comes from `wervt env <app> --set NUXT_PUBLIC_WERVT_FEEDBACK_KEY=pk_…`
37
+ * (it can override a configured key the same way).
38
+ */
39
+ feedback?: FeedbackOptions | boolean;
40
+ }
41
+ export interface FeedbackOptions {
42
+ /** Public intake key of the kontor project (Project settings → Intake keys). */
43
+ key?: string;
44
+ /** The kontor instance. Defaults to https://kontor.wervt.app. */
45
+ url?: string;
46
+ /** Widget language. Defaults to the browser's. */
47
+ lang?: 'de' | 'en';
48
+ /** `none` hides the floating button; open the form with `useWervtFeedback().open()`. */
49
+ position?: 'bottom-right' | 'bottom-left' | 'none';
50
+ label?: string;
51
+ /** Accent color (any CSS color). */
52
+ color?: string;
53
+ /** Also load it in `nuxt dev`. Off by default: localhost usually isn't an allowed origin. */
54
+ dev?: boolean;
33
55
  }
34
56
  export interface McpOptions {
35
57
  /** Server name clients show. Defaults to the app name. */
package/dist/module.js CHANGED
@@ -265,6 +265,24 @@ var module_default = defineNuxtModule({
265
265
  mode: "client"
266
266
  });
267
267
  }
268
+ const feedbackOptions = options.feedback === true ? {} : options.feedback;
269
+ if (feedbackOptions && (feedbackOptions.dev || !nuxt.options.dev)) {
270
+ const { dev: _, ...feedback } = feedbackOptions;
271
+ const config = nuxt.options.runtimeConfig.public;
272
+ config.wervt = {
273
+ ...config.wervt,
274
+ feedback: {
275
+ key: "",
276
+ url: "https://kontor.wervt.app",
277
+ ...feedback,
278
+ app: await resolveAppName(nuxt.options.rootDir, options.app)
279
+ }
280
+ };
281
+ addPlugin({
282
+ src: resolver.resolve("./runtime/app/plugins/feedback.client"),
283
+ mode: "client"
284
+ });
285
+ }
268
286
  nuxt.options.build.transpile.push(resolver.resolve("./runtime"));
269
287
  addImports([
270
288
  {
@@ -290,6 +308,10 @@ var module_default = defineNuxtModule({
290
308
  {
291
309
  name: "useWervtUpdate",
292
310
  from: resolver.resolve("./runtime/app/useWervtUpdate")
311
+ },
312
+ {
313
+ name: "useWervtFeedback",
314
+ from: resolver.resolve("./runtime/app/useWervtFeedback")
293
315
  }
294
316
  ]);
295
317
  }
@@ -0,0 +1,4 @@
1
+ //#region src/runtime/app/plugins/feedback.client.d.ts
2
+ declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
3
+ //#endregion
4
+ export { _default as default };
@@ -0,0 +1,32 @@
1
+ import { pendingFeedbackContext } from "../useWervtFeedback.js";
2
+ import { defineNuxtPlugin, onNuxtReady, useRuntimeConfig } from "#app";
3
+ //#region src/runtime/app/plugins/feedback.client.ts
4
+ var feedback_client_default = defineNuxtPlugin({
5
+ name: "wervt:feedback",
6
+ setup() {
7
+ const config = useRuntimeConfig();
8
+ const feedback = config.public.wervt?.feedback;
9
+ if (!feedback?.key) return;
10
+ onNuxtReady(() => {
11
+ const script = document.createElement("script");
12
+ script.src = `${feedback.url.replace(/\/$/, "")}/widget.js`;
13
+ script.async = true;
14
+ script.dataset.key = feedback.key;
15
+ for (const name of [
16
+ "lang",
17
+ "position",
18
+ "label",
19
+ "color"
20
+ ]) if (feedback[name]) script.dataset[name] = feedback[name];
21
+ script.dataset.context = JSON.stringify({
22
+ app: feedback.app,
23
+ release: config.app.buildId,
24
+ ...pendingFeedbackContext
25
+ });
26
+ script.addEventListener("load", () => window.kontor?.setContext(pendingFeedbackContext));
27
+ document.head.appendChild(script);
28
+ });
29
+ }
30
+ });
31
+ //#endregion
32
+ export { feedback_client_default as default };
@@ -0,0 +1,24 @@
1
+ //#region src/runtime/app/useWervtFeedback.d.ts
2
+ interface KontorWidget {
3
+ open(): void;
4
+ close(): void;
5
+ setContext(values: Record<string, unknown>): void;
6
+ }
7
+ declare global {
8
+ interface Window {
9
+ kontor?: KontorWidget;
10
+ }
11
+ }
12
+ export declare const pendingFeedbackContext: Record<string, unknown>;
13
+ /**
14
+ * Controls the feedback widget (`wervt: { feedback: { key } }`): open it from your own button,
15
+ * or add context to every report, e.g. what the user was looking at.
16
+ *
17
+ * @example useWervtFeedback().setContext({ room: room.id })
18
+ */
19
+ export declare function useWervtFeedback(): {
20
+ open: () => void | undefined;
21
+ close: () => void | undefined;
22
+ setContext(values: Record<string, unknown>): void;
23
+ };
24
+ //#endregion
@@ -0,0 +1,21 @@
1
+ //#region src/runtime/app/useWervtFeedback.ts
2
+ const pendingFeedbackContext = {};
3
+ /**
4
+ * Controls the feedback widget (`wervt: { feedback: { key } }`): open it from your own button,
5
+ * or add context to every report, e.g. what the user was looking at.
6
+ *
7
+ * @example useWervtFeedback().setContext({ room: room.id })
8
+ */
9
+ function useWervtFeedback() {
10
+ const widget = () => import.meta.client ? window.kontor : void 0;
11
+ return {
12
+ open: () => widget()?.open(),
13
+ close: () => widget()?.close(),
14
+ setContext(values) {
15
+ Object.assign(pendingFeedbackContext, values);
16
+ widget()?.setContext(values);
17
+ }
18
+ };
19
+ }
20
+ //#endregion
21
+ export { pendingFeedbackContext, useWervtFeedback };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wervt/nuxt",
3
- "version": "0.2.13",
3
+ "version": "0.2.14",
4
4
  "description": "Nuxt module for apps hosted on wervt: database, live data, MCP and runtime setup.",
5
5
  "keywords": [
6
6
  "drizzle",