wafir 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ GNU AFFERO GENERAL PUBLIC LICENSE
2
+ Version 3, 19 November 2007
3
+
4
+ Copyright (C) 2025 BPS
5
+
6
+ This program is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU Affero General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version. Enhancements to the program must be
10
+ published under the same License.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Affero General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Affero General Public License
18
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
package/README.md ADDED
@@ -0,0 +1,248 @@
1
+ # Wafir - The Web App Feedback and Issue Reporter
2
+
3
+ Wafir is a lightweight feedback and issue reporting tool that seamlessly connects input from users and testers to your GitHub-based development workflow. It captures user input, screenshots, console logs, and essential browser telemetry to accelerate debugging. See details at https://bps-consulting.github.io/wafir/.
4
+
5
+ ## What's in this Repo
6
+
7
+ This repository contains everything needed to build, use, and support Wafir. You don't need to clone the repo to use Wafir: simply get the widget code and add it to your web application as described in the [Quickstart Guide](QUICKSTART.md).
8
+
9
+ The repo includes source code for the following:
10
+
11
+ - **Wafir Widget** (packages/wafir): A web component built with Lit that you can embed in any web application to collect user feedback.
12
+ - **Bridge Service** (apps/bridge): A Fastify-based backend service that handles feedback submissions, file uploads, and GitHub integration. See the [wafir-infrastructure](https://github.com/bps-consulting/wafir-infrastructure) repo for deployment and infrastructure details.
13
+ - **Test Web Page** (packages/wafir/index.html): A simple HTML page to test the Wafir widget in isolation.
14
+ - **React Consumer** (internal/react-consumer): A sample React application demonstrating how to integrate the Wafir widget. {TODO: Update or remove if needed}
15
+ - **Framework Wrappers** (packages/react, packages/vue): Sample React and Vue wrappers demonstrating how to integrate the Wafir widget into popular frameworks.
16
+ - **Public Documentation Site** (apps/www): An Astro-based website for public documentation deployed on [GitHub Pages](https://bps-consulting.github.io/wafir/).
17
+ - **Configuration Examples** (examples/): Sample YAML files showing how to configure the Wafir widget.
18
+
19
+ ## 🚀 Tech Stack
20
+
21
+ ### Wafir (Widget)
22
+
23
+ <p align="left">
24
+ <img src="https://img.shields.io/badge/Lit-324FFF?style=for-the-badge&logo=lit&logoColor=white" alt="Lit" />
25
+ <img src="https://img.shields.io/badge/Vite-646CFF?style=for-the-badge&logo=vite&logoColor=white" alt="Vite" />
26
+ <img src="https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript&logoColor=white" alt="TypeScript" />
27
+ <img src="https://img.shields.io/badge/Nanostores-000000?style=for-the-badge&logo=nanostores&logoColor=white" alt="Nanostores" />
28
+ </p>
29
+
30
+ - **Lit**: Simple, fast Web Components.
31
+ - **Nanostores**: A tiny state manager for React, Preact, Vue, Svelte, and vanilla JS.
32
+ - **Modern Screenshot**: Accurate DOM-to-Canvas rendering for feedback context.
33
+ - **OpenAPI Fetch**: Type-safe API fetching.
34
+
35
+ ### Bridge (Backend/API)
36
+
37
+ <p align="left">
38
+ <img src="https://img.shields.io/badge/Fastify-000000?style=for-the-badge&logo=fastify&logoColor=white" alt="Fastify" />
39
+ <img src="https://img.shields.io/badge/Node.js-339933?style=for-the-badge&logo=nodedotjs&logoColor=white" alt="Node.js" />
40
+ <img src="https://img.shields.io/badge/Amazon_S3-569A31?style=for-the-badge&logo=amazons3&logoColor=white" alt="AWS S3" />
41
+ <img src="https://img.shields.io/badge/Octokit-24292E?style=for-the-badge&logo=github&logoColor=white" alt="Octokit" />
42
+ </p>
43
+
44
+ - **Fastify**: Fast and low overhead web framework for Node.js.
45
+ - **AWS S3**: Secure storage for screenshots and assets.
46
+ - **Octokit**: Integration with GitHub for automated issue creation.
47
+ - **Swagger/OpenAPI**: Automated API documentation.
48
+
49
+ ### Monorepo Tooling
50
+
51
+ <p align="left">
52
+ <img src="https://img.shields.io/badge/Turborepo-EF4444?style=for-the-badge&logo=turborepo&logoColor=white" alt="Turborepo" />
53
+ <img src="https://img.shields.io/badge/pnpm-F69220?style=for-the-badge&logo=pnpm&logoColor=white" alt="pnpm" />
54
+ </p>
55
+
56
+ ## 📂 Project Structure
57
+
58
+ - **`wafir/`**: The client-side widget built with Lit. It's designed to be embedded in any web application.
59
+ - **`bridge/`**: The backend server built with Fastify. It handles submissions, file uploads (to S3), and integrations (like GitHub).
60
+ - **`react-consumer/`**: A sample React application demonstrating how to integrate the Wafir widget.
61
+
62
+ ## 🛠️ Installation
63
+
64
+ This project is a monorepo managed by **pnpm** and **Turborepo**.
65
+
66
+ 1. **Clone the repository:**
67
+
68
+ ```bash
69
+ git clone https://github.com/BPS-Consulting/wafir.git
70
+ cd wafir
71
+ ```
72
+
73
+ 2. **Install dependencies:**
74
+ ```bash
75
+ pnpm install
76
+ ```
77
+
78
+ ## 🏃‍♂️ Running Locally
79
+
80
+ To start the development environment for all packages (Widget, Bridge, and Consumer):
81
+
82
+ ```bash
83
+ pnpm dev
84
+ ```
85
+
86
+ This command runs `turbo run dev`, which spins up:
87
+
88
+ - The **Wafir Widget** in watch mode.
89
+ - The **Bridge API** server.
90
+ - The **React Consumer** app to test the integration.
91
+
92
+ ## 🏗️ Building
93
+
94
+ To build all packages for production:
95
+
96
+ ```bash
97
+ pnpm build
98
+ ```
99
+
100
+ To build the browser version of the Wafir widget and copy it to the www site:
101
+
102
+ ```bash
103
+ cd packages/wafir && pnpm run build:browser
104
+ cd apps/www && pnpm run build
105
+ ```
106
+
107
+ ## 🔧 Configuration
108
+
109
+ ### Bridge Environment Variables
110
+
111
+ Create a `.env` file in the `bridge/` directory based on the usage requirements. You typically need:
112
+
113
+ - `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`: For S3 access.
114
+ - `GITHUB_TOKEN`: For GitHub issue creation integration.
115
+
116
+ ### Widget Configuration
117
+
118
+ The widget can be configured via attributes or JavaScript initialization. See the `wafir/` directory for specific implementation details.
119
+
120
+ ### CSS Customization
121
+
122
+ Wafir uses Shadow DOM for isolation but exposes CSS custom properties for theming. Set these on the `wafir-widget` element:
123
+
124
+ #### Reporter Variables
125
+
126
+ | Variable | Default | Description |
127
+ | --------------------------------- | ----------------------------- | ------------------- |
128
+ | `--wafir-font-family` | System fonts | Font stack |
129
+ | `--wafir-font-size` | `14px` | Base font size |
130
+ | `--wafir-text-color` | `#111827` | Primary text color |
131
+ | `--wafir-text-secondary` | `#6b7280` | Muted text color |
132
+ | `--wafir-primary-color` | `#2563eb` | Brand color |
133
+ | `--wafir-primary-hover` | `#1d4ed8` | Hover state |
134
+ | `--wafir-border-color` | `#e5e7eb` | Border color |
135
+ | `--wafir-button-size` | `48px` | Trigger button size |
136
+ | `--wafir-button-border-radius` | `50%` | Button shape |
137
+ | `--wafir-button-offset` | `20px` | Edge distance |
138
+ | `--wafir-button-icon-size` | `24px` | Icon size |
139
+ | `--wafir-button-shadow` | `0 4px 12px rgba(0,0,0,0.15)` | Button shadow |
140
+ | `--wafir-button-shadow-hover` | `0 6px 16px rgba(0,0,0,0.2)` | Hover shadow |
141
+ | `--wafir-tooltip-bg` | `#1f2937` | Tooltip background |
142
+ | `--wafir-backdrop-color` | `rgba(0,0,0,0.5)` | Modal backdrop |
143
+ | `--wafir-modal-bg` | `white` | Modal background |
144
+ | `--wafir-modal-border-radius` | `12px` | Modal corners |
145
+ | `--wafir-modal-max-width` | `800px` | Modal width |
146
+ | `--wafir-modal-padding` | `20px` | Modal spacing |
147
+ | `--wafir-modal-shadow` | `0 20px 60px rgba(0,0,0,0.3)` | Modal shadow |
148
+ | `--wafir-modal-title-font-size` | `18px` | Title size |
149
+ | `--wafir-modal-title-font-weight` | `600` | Title weight |
150
+ | `--wafir-modal-title-color` | `--wafir-text-color` | Title color |
151
+
152
+ #### Form Variables
153
+
154
+ | Variable | Default | Description |
155
+ | ------------------------------- | ------------- | ---------------- |
156
+ | `--wafir-form-text-color` | `#374151` | Form text |
157
+ | `--wafir-form-bg` | `transparent` | Form background |
158
+ | `--wafir-form-padding` | `20px` | Form padding |
159
+ | `--wafir-form-border-color` | `#d1d5db` | Input borders |
160
+ | `--wafir-form-border-radius` | `6px` | Input corners |
161
+ | `--wafir-form-input-padding` | `10px 12px` | Input spacing |
162
+ | `--wafir-form-input-color` | `#111827` | Input text |
163
+ | `--wafir-form-input-bg` | `#ffffff` | Input background |
164
+ | `--wafir-form-primary-color` | `#2563eb` | Submit button |
165
+ | `--wafir-form-primary-hover` | `#1d4ed8` | Submit hover |
166
+ | `--wafir-form-disabled-color` | `#9ca3af` | Disabled state |
167
+ | `--wafir-form-bg-secondary` | `#f3f4f6` | Secondary bg |
168
+ | `--wafir-form-bg-tertiary` | `#f9fafb` | Tertiary bg |
169
+ | `--wafir-form-text-secondary` | `#6b7280` | Secondary text |
170
+ | `--wafir-form-telemetry-bg` | `#f9fafb` | Telemetry bg |
171
+ | `--wafir-form-telemetry-border` | `#e5e7eb` | Telemetry border |
172
+ | `--wafir-form-logs-bg` | `#111827` | Logs background |
173
+ | `--wafir-form-logs-text` | `#f3f4f6` | Logs text |
174
+ | `--wafir-form-log-warn` | `#fde047` | Warning color |
175
+ | `--wafir-form-log-error` | `#f87171` | Error color |
176
+
177
+ #### Highlighter Variables
178
+
179
+ | Variable | Default | Description |
180
+ | ----------------------------------- | --------------------- | ------------ |
181
+ | `--wafir-highlighter-overlay-bg` | `rgba(0,0,0,0.1)` | Overlay bg |
182
+ | `--wafir-highlighter-primary-color` | `#2563eb` | Border color |
183
+ | `--wafir-highlighter-highlight-bg` | `rgba(37,99,235,0.1)` | Fill color |
184
+
185
+ #### Example
186
+
187
+ ```css
188
+ wafir-widget {
189
+ --wafir-primary-color: #6366f1;
190
+ --wafir-primary-hover: #818cf8;
191
+ --wafir-modal-bg: #ffffff;
192
+ --wafir-text-color: #1f2937;
193
+ --wafir-form-border-radius: 8px;
194
+ }
195
+ ```
196
+
197
+ ## 🤝 Contributing
198
+
199
+ 1. Fork the repo
200
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
201
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
202
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
203
+ 5. Open a Pull Request
204
+
205
+ ## Credits
206
+
207
+ - This project uses [normalize.css](https://github.com/necolas/normalize.css) v8.0.1 by [Nicolas Gallagher](https://github.com/necolas), licensed under the [MIT License](https://github.com/necolas/normalize.css/blob/master/LICENSE).
208
+
209
+ ## Distribution & Usage
210
+
211
+ ### 📦 Using via NPM (Module, ESM)
212
+
213
+ Install:
214
+
215
+ ```bash
216
+ npm install wafir
217
+ ```
218
+
219
+ Import and use in your project:
220
+
221
+ ```js
222
+ import { WafirWidget } from "wafir";
223
+ // Register/use wafir-widget as a custom element (see docs)
224
+ ```
225
+
226
+ - For module consumers, import from `wafir`, styles from `wafir/styles/widget.css`, etc.
227
+
228
+ ### 🌐 Using via CDN/IIFE (Browser Global)
229
+
230
+ Add to your HTML:
231
+
232
+ ```html
233
+ <script src="https://cdn.jsdelivr.net/npm/wafir/dist/browser/wafir.browser.js"></script>
234
+ ```
235
+
236
+ This exposes `Wafir` globally (e.g. `window.WafirWidget`).
237
+ Include styles from the CDN:
238
+
239
+ ```html
240
+ <link
241
+ rel="stylesheet"
242
+ href="https://cdn.jsdelivr.net/npm/wafir/dist/browser/styles/wafir-widget.css"
243
+ />
244
+ ```
245
+
246
+ - Use `<wafir-widget></wafir-widget>` in your HTML as documented.
247
+
248
+ See full docs at [GitHub Pages](https://bps-consulting.github.io/wafir/).
@@ -0,0 +1,104 @@
1
+ import type { paths } from ".";
2
+ export declare const setBridgeUrl: (url: string) => void;
3
+ export type WafirConfigBase = paths["/config"]["get"]["responses"][200]["content"]["application/json"];
4
+ export type WafirConfig = WafirConfigBase & {
5
+ /** GitHub App installation ID. Required for authenticating with the GitHub API. */
6
+ installationId: number;
7
+ storage: {
8
+ type: "issue" | "project" | "both";
9
+ /** GitHub repository owner (user or organization) */
10
+ owner: string;
11
+ /** GitHub repository name */
12
+ repo: string;
13
+ projectNumber?: number;
14
+ };
15
+ };
16
+ export type TabConfigApi = NonNullable<WafirConfig["tabs"]>[number];
17
+ export type FieldConfigApi = NonNullable<TabConfigApi["fields"]>[number];
18
+ export declare const checkBridgeHealth: (bridgeUrl?: string) => Promise<boolean>;
19
+ /**
20
+ * @deprecated The widget now fetches config directly from a user-hosted URL.
21
+ * This function is kept for backward compatibility but will be removed in a future version.
22
+ */
23
+ export declare const getWafirConfig: (installationId: number, owner: string, repo: string, bridgeUrl?: string) => Promise<{
24
+ title: string;
25
+ storage?: {
26
+ type: "issue" | "project" | "both";
27
+ owner?: string;
28
+ repo?: string;
29
+ projectNumber?: number;
30
+ };
31
+ telemetry?: {
32
+ screenshot: boolean;
33
+ browserInfo: boolean;
34
+ consoleLog: boolean;
35
+ };
36
+ tabs?: {
37
+ id: string;
38
+ label?: string;
39
+ icon?: "thumbsup" | "lightbulb" | "bug";
40
+ isFeedback: boolean;
41
+ fields?: {
42
+ type: "input" | "email" | "textarea" | "dropdown" | "checkboxes" | "markdown" | "rating";
43
+ id?: string;
44
+ attributes?: {
45
+ label?: string;
46
+ description?: string;
47
+ placeholder?: string;
48
+ value?: string;
49
+ render?: string;
50
+ multiple?: boolean;
51
+ options?: string[] | {
52
+ label: string;
53
+ required?: boolean;
54
+ }[];
55
+ ratingLabels?: string[];
56
+ };
57
+ validations?: {
58
+ required?: boolean;
59
+ };
60
+ }[];
61
+ }[];
62
+ issueTypes?: {
63
+ id?: number;
64
+ name?: string;
65
+ color?: string;
66
+ }[];
67
+ feedbackProject?: {
68
+ projectNumber?: number;
69
+ owner?: string;
70
+ ratingField: string;
71
+ };
72
+ }>;
73
+ export interface BrowserInfo {
74
+ url?: string;
75
+ userAgent?: string;
76
+ viewportWidth?: number;
77
+ viewportHeight?: number;
78
+ language?: string;
79
+ }
80
+ export interface ConsoleLogEntry {
81
+ type: string;
82
+ message: string;
83
+ timestamp: string;
84
+ }
85
+ export interface SubmitIssueParams {
86
+ /** URL to the authoritative config file - required for server-side validation */
87
+ configUrl: string;
88
+ installationId: number;
89
+ owner: string;
90
+ repo: string;
91
+ title: string;
92
+ /** The active tab ID for field validation */
93
+ tabId?: string;
94
+ labels?: string[];
95
+ screenshot?: Blob;
96
+ bridgeUrl?: string;
97
+ rating?: number;
98
+ submissionType?: "issue" | "feedback";
99
+ formFields?: Record<string, unknown>;
100
+ fieldOrder?: string[];
101
+ browserInfo?: BrowserInfo;
102
+ consoleLogs?: ConsoleLogEntry[];
103
+ }
104
+ export declare const submitIssue: (params: SubmitIssueParams) => Promise<undefined>;