jat-feedback 3.2.0 → 3.3.0
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/dist/jat-feedback.js +41 -41
- package/dist/jat-feedback.mjs +1875 -1807
- package/package.json +1 -1
- package/supabase/functions/jat-webhook/index.ts +15 -11
- package/supabase/migrations/3.3.0_realtime_voice.sql +78 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jat-feedback",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "Embeddable feedback widget for bug reports and feature requests. Captures screenshots, console logs, and user context as a web component.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/jat-feedback.js",
|
|
@@ -82,10 +82,8 @@ interface WebhookPayload {
|
|
|
82
82
|
|
|
83
83
|
// Tables and the columns that JAT is allowed to update.
|
|
84
84
|
// Add more tables here if you want JAT to sync status for other record types.
|
|
85
|
-
// "feedback_reports" kept as alias for backward compat with pre-v3 callers.
|
|
86
85
|
const TABLE_CONFIG: Record<string, { statusCol: string; taskIdCol: string }> = {
|
|
87
86
|
project_tasks: { statusCol: "status", taskIdCol: "jat_task_id" },
|
|
88
|
-
feedback_reports: { statusCol: "status", taskIdCol: "jat_task_id" },
|
|
89
87
|
}
|
|
90
88
|
|
|
91
89
|
Deno.serve(async (req) => {
|
|
@@ -139,8 +137,14 @@ Deno.serve(async (req) => {
|
|
|
139
137
|
)
|
|
140
138
|
}
|
|
141
139
|
|
|
142
|
-
//
|
|
143
|
-
|
|
140
|
+
// Skip transient voice-pipeline statuses — only sync when the task
|
|
141
|
+
// has a meaningful status that JAT should know about.
|
|
142
|
+
if (data.status === "transcribing" || data.status === "failed") {
|
|
143
|
+
return new Response(
|
|
144
|
+
JSON.stringify({ skipped: true, reason: `Status "${data.status}" is transient, not synced to JAT` }),
|
|
145
|
+
{ status: 200, headers: { "Content-Type": "application/json" } },
|
|
146
|
+
)
|
|
147
|
+
}
|
|
144
148
|
|
|
145
149
|
// Build the update object from the payload fields
|
|
146
150
|
const update: Record<string, unknown> = {}
|
|
@@ -162,14 +166,14 @@ Deno.serve(async (req) => {
|
|
|
162
166
|
|
|
163
167
|
const supabase = createClient(supabaseUrl, supabaseServiceKey)
|
|
164
168
|
const result = await supabase
|
|
165
|
-
.from(
|
|
169
|
+
.from(reference_table)
|
|
166
170
|
.update(update)
|
|
167
171
|
.eq("id", reference_id)
|
|
168
172
|
.select("id")
|
|
169
173
|
|
|
170
174
|
if (result.error) {
|
|
171
175
|
console.error(`JAT webhook failed: ${result.error.message}`, {
|
|
172
|
-
table:
|
|
176
|
+
table: reference_table,
|
|
173
177
|
reference_id,
|
|
174
178
|
update,
|
|
175
179
|
})
|
|
@@ -180,11 +184,11 @@ Deno.serve(async (req) => {
|
|
|
180
184
|
}
|
|
181
185
|
|
|
182
186
|
if (!result.data || result.data.length === 0) {
|
|
183
|
-
console.warn(`JAT webhook: no rows matched ${
|
|
187
|
+
console.warn(`JAT webhook: no rows matched ${reference_table}[${reference_id}]`, update)
|
|
184
188
|
return new Response(
|
|
185
189
|
JSON.stringify({
|
|
186
|
-
error: `No rows matched: ${
|
|
187
|
-
table:
|
|
190
|
+
error: `No rows matched: ${reference_table} id=${reference_id}`,
|
|
191
|
+
table: reference_table,
|
|
188
192
|
id: reference_id,
|
|
189
193
|
rowsAffected: 0,
|
|
190
194
|
}),
|
|
@@ -192,12 +196,12 @@ Deno.serve(async (req) => {
|
|
|
192
196
|
)
|
|
193
197
|
}
|
|
194
198
|
|
|
195
|
-
console.log(`JAT webhook: ${event} → ${
|
|
199
|
+
console.log(`JAT webhook: ${event} → ${reference_table}[${reference_id}] (${result.data.length} row(s))`, update)
|
|
196
200
|
|
|
197
201
|
return new Response(
|
|
198
202
|
JSON.stringify({
|
|
199
203
|
success: true,
|
|
200
|
-
table:
|
|
204
|
+
table: reference_table,
|
|
201
205
|
id: reference_id,
|
|
202
206
|
updated: update,
|
|
203
207
|
rowsAffected: result.data.length,
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
-- jat-feedback v3.3.0 — Realtime + voice transcription support
|
|
2
|
+
--
|
|
3
|
+
-- Enables Supabase Realtime on project_tasks (REPLICA IDENTITY FULL),
|
|
4
|
+
-- adds audio_url column for voice recordings, expands status CHECK
|
|
5
|
+
-- to include 'transcribing' and 'failed', and creates a private
|
|
6
|
+
-- Storage bucket for voice audio files.
|
|
7
|
+
--
|
|
8
|
+
-- This is an additive migration (nullable column + new bucket + constraint update).
|
|
9
|
+
-- Safe for 3.x — no existing data affected.
|
|
10
|
+
--
|
|
11
|
+
-- Apply to each consuming project:
|
|
12
|
+
-- cp node_modules/jat-feedback/supabase/migrations/3.3.0_realtime_voice.sql \
|
|
13
|
+
-- supabase/migrations/$(date +%Y%m%d%H%M%S)_feedback_3_3_0.sql
|
|
14
|
+
-- supabase db push
|
|
15
|
+
--
|
|
16
|
+
-- After applying, enable Realtime for project_tasks in the Supabase dashboard:
|
|
17
|
+
-- Database → Replication → supabase_realtime → toggle project_tasks ON
|
|
18
|
+
|
|
19
|
+
-- ============================================================================
|
|
20
|
+
-- 1. Enable Realtime (REPLICA IDENTITY FULL for complete row data in changes)
|
|
21
|
+
-- ============================================================================
|
|
22
|
+
|
|
23
|
+
ALTER TABLE project_tasks REPLICA IDENTITY FULL;
|
|
24
|
+
|
|
25
|
+
-- ============================================================================
|
|
26
|
+
-- 2. Add audio_url column (voice recording path in Storage)
|
|
27
|
+
-- ============================================================================
|
|
28
|
+
|
|
29
|
+
-- Separate from recording_url (which stores rrweb session replay data).
|
|
30
|
+
-- audio_url points to raw voice audio files in the voice-recordings bucket.
|
|
31
|
+
ALTER TABLE project_tasks ADD COLUMN IF NOT EXISTS audio_url TEXT;
|
|
32
|
+
|
|
33
|
+
-- ============================================================================
|
|
34
|
+
-- 3. Expand status CHECK constraint to include voice transcription states
|
|
35
|
+
-- ============================================================================
|
|
36
|
+
|
|
37
|
+
-- Drop the existing constraint (inherited from 1.0.0_feedback_reports.sql)
|
|
38
|
+
-- and recreate with additional values for the voice pipeline.
|
|
39
|
+
ALTER TABLE project_tasks DROP CONSTRAINT IF EXISTS feedback_reports_status_check;
|
|
40
|
+
|
|
41
|
+
ALTER TABLE project_tasks ADD CONSTRAINT project_tasks_status_check
|
|
42
|
+
CHECK (status IN (
|
|
43
|
+
'submitted',
|
|
44
|
+
'in_progress',
|
|
45
|
+
'completed',
|
|
46
|
+
'accepted',
|
|
47
|
+
'rejected',
|
|
48
|
+
'wontfix',
|
|
49
|
+
'closed',
|
|
50
|
+
'transcribing',
|
|
51
|
+
'failed'
|
|
52
|
+
));
|
|
53
|
+
|
|
54
|
+
-- ============================================================================
|
|
55
|
+
-- 4. Storage bucket for voice recordings (private)
|
|
56
|
+
-- ============================================================================
|
|
57
|
+
|
|
58
|
+
INSERT INTO storage.buckets (id, name, public)
|
|
59
|
+
VALUES ('voice-recordings', 'voice-recordings', false)
|
|
60
|
+
ON CONFLICT (id) DO NOTHING;
|
|
61
|
+
|
|
62
|
+
-- RLS: service role can read and write
|
|
63
|
+
CREATE POLICY "Service role can manage voice recordings"
|
|
64
|
+
ON storage.objects FOR ALL TO service_role
|
|
65
|
+
USING (bucket_id = 'voice-recordings')
|
|
66
|
+
WITH CHECK (bucket_id = 'voice-recordings');
|
|
67
|
+
|
|
68
|
+
-- RLS: authenticated users can upload voice recordings
|
|
69
|
+
CREATE POLICY "Authenticated users can upload voice recordings"
|
|
70
|
+
ON storage.objects FOR INSERT TO authenticated
|
|
71
|
+
WITH CHECK (bucket_id = 'voice-recordings');
|
|
72
|
+
|
|
73
|
+
-- RLS: authenticated users can read own voice recordings
|
|
74
|
+
CREATE POLICY "Authenticated users can read voice recordings"
|
|
75
|
+
ON storage.objects FOR SELECT TO authenticated
|
|
76
|
+
USING (bucket_id = 'voice-recordings');
|
|
77
|
+
|
|
78
|
+
-- Anon role is blocked by default (no policy = no access)
|