@fayz-ai/plugin-reputation 0.10.3 → 0.10.5
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/index.js +328 -105
- package/dist/index.js.map +1 -1
- package/dist/migrations/index.d.ts +1 -1
- package/dist/migrations/index.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -120,120 +120,343 @@ function ReputationHome() {
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
// src/migrations/index.ts
|
|
123
|
-
var
|
|
124
|
-
-- plugin-reputation
|
|
123
|
+
var MIGRATION_000_BASELINE = `-- ============================================================================
|
|
124
|
+
-- plugins/plugin-reputation/src/migrations/000_baseline.sql \u2014 what installing this provisions, as one file.
|
|
125
125
|
--
|
|
126
|
-
--
|
|
127
|
-
--
|
|
128
|
-
--
|
|
129
|
-
-- a product review \u2014 product_id IS NOT NULL (the storefront PDP)
|
|
130
|
-
-- One table, because they are the same row to a merchant: an author, a rating,
|
|
131
|
-
-- some words, and a reply. Prefix: plg_reputation_.
|
|
126
|
+
-- GENERATED by scripts/emit-unit-baselines.mjs (#338). Do not edit by hand:
|
|
127
|
+
-- change the schema, regenerate, and let scripts/check-chain-equivalence.mjs
|
|
128
|
+
-- prove the result still matches.
|
|
132
129
|
--
|
|
133
|
-
--
|
|
134
|
-
--
|
|
135
|
-
--
|
|
136
|
-
-- \xA74 v_public_product_ratings \u2014 anon-readable per-product aggregate
|
|
130
|
+
-- This replaced 1 migration files. They are kept, unapplied, in
|
|
131
|
+
-- migrations.archive/ \u2014 a year of decisions is worth reading even when it is no
|
|
132
|
+
-- longer worth replaying.
|
|
137
133
|
--
|
|
138
|
-
--
|
|
139
|
-
--
|
|
140
|
-
--
|
|
141
|
-
--
|
|
142
|
-
--
|
|
143
|
-
-- product_id deliberately has NO foreign key. plugin-shop owns plg_shop_products
|
|
144
|
-
-- and may not be installed in a given pool \u2014 a FK here would make this migration
|
|
145
|
-
-- fail on every non-commerce tenant. product_name/product_slug are a display
|
|
146
|
-
-- snapshot taken at write time so the homepage card can render and link without
|
|
147
|
-
-- this plugin ever reading another plugin's table.
|
|
134
|
+
-- Object order is fixed rather than dependency-sorted: schemas, types,
|
|
135
|
+
-- sequences, tables, defaults, functions, constraints, views, indexes, foreign
|
|
136
|
+
-- keys, triggers, row security, policies, grants. Dependencies BETWEEN units
|
|
137
|
+
-- are carried by the order packages/db/chain.json declares.
|
|
148
138
|
-- ============================================================================
|
|
149
139
|
|
|
150
|
-
--
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
140
|
+
-- A LANGUAGE sql function binds its body at CREATE time, and 570 functions
|
|
141
|
+
-- sorted by name are not sorted by who calls whom. This is what lets them load
|
|
142
|
+
-- in any order; every body is still compiled on first call, so a genuinely
|
|
143
|
+
-- broken reference surfaces then rather than never. Session-scoped.
|
|
144
|
+
SET check_function_bodies = false;
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
-- \u2500\u2500 default privileges: reset \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
149
|
+
-- Cleared BEFORE anything is created, so every object below gets the ACL the
|
|
150
|
+
-- dump describes rather than the image's defaults on top of it. Restored at
|
|
151
|
+
-- the end of this file.
|
|
152
|
+
|
|
153
|
+
DO $dp$ BEGIN
|
|
154
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;
|
|
155
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
156
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;
|
|
157
|
+
END $dp$;
|
|
158
|
+
|
|
159
|
+
DO $dp$ BEGIN
|
|
160
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;
|
|
161
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
162
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;
|
|
163
|
+
END $dp$;
|
|
164
|
+
|
|
165
|
+
DO $dp$ BEGIN
|
|
166
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;
|
|
167
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
168
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;
|
|
169
|
+
END $dp$;
|
|
170
|
+
|
|
171
|
+
DO $dp$ BEGIN
|
|
172
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;
|
|
173
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
174
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;
|
|
175
|
+
END $dp$;
|
|
176
|
+
|
|
177
|
+
DO $dp$ BEGIN
|
|
178
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;
|
|
179
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
180
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;
|
|
181
|
+
END $dp$;
|
|
182
|
+
|
|
183
|
+
DO $dp$ BEGIN
|
|
184
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;
|
|
185
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
186
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;
|
|
187
|
+
END $dp$;
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
-- \u2500\u2500 table \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
191
|
+
|
|
192
|
+
CREATE TABLE public.plg_reputation_reviews (
|
|
193
|
+
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
|
194
|
+
tenant_id uuid NOT NULL,
|
|
195
|
+
product_id uuid,
|
|
196
|
+
product_name text,
|
|
197
|
+
product_slug text,
|
|
198
|
+
order_id uuid,
|
|
199
|
+
author_name text NOT NULL,
|
|
200
|
+
author_avatar_url text,
|
|
201
|
+
rating numeric(2,1) NOT NULL,
|
|
202
|
+
title text,
|
|
203
|
+
body text DEFAULT ''::text NOT NULL,
|
|
204
|
+
source text DEFAULT 'Website'::text NOT NULL,
|
|
205
|
+
status text DEFAULT 'pending'::text NOT NULL,
|
|
206
|
+
verified boolean DEFAULT false NOT NULL,
|
|
207
|
+
reply_text text,
|
|
208
|
+
replied_at timestamp with time zone,
|
|
209
|
+
published_at timestamp with time zone,
|
|
210
|
+
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
211
|
+
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
212
|
+
CONSTRAINT plg_reputation_reviews_rating_check CHECK (((rating >= (1)::numeric) AND (rating <= (5)::numeric))),
|
|
213
|
+
CONSTRAINT plg_reputation_reviews_status_check CHECK ((status = ANY (ARRAY['pending'::text, 'approved'::text, 'rejected'::text])))
|
|
172
214
|
);
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
-- \u2500\u2500 constraint \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
218
|
+
|
|
219
|
+
ALTER TABLE ONLY public.plg_reputation_reviews
|
|
220
|
+
ADD CONSTRAINT plg_reputation_reviews_pkey PRIMARY KEY (id);
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
-- \u2500\u2500 view \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
224
|
+
|
|
225
|
+
CREATE VIEW public.v_public_product_ratings AS
|
|
226
|
+
SELECT tenant_id,
|
|
227
|
+
product_id,
|
|
228
|
+
(round(avg(rating), 1))::numeric(2,1) AS average,
|
|
229
|
+
(count(*))::integer AS count,
|
|
230
|
+
(count(*) FILTER (WHERE (round(rating) = (5)::numeric)))::integer AS star5,
|
|
231
|
+
(count(*) FILTER (WHERE (round(rating) = (4)::numeric)))::integer AS star4,
|
|
232
|
+
(count(*) FILTER (WHERE (round(rating) = (3)::numeric)))::integer AS star3,
|
|
233
|
+
(count(*) FILTER (WHERE (round(rating) = (2)::numeric)))::integer AS star2,
|
|
234
|
+
(count(*) FILTER (WHERE (round(rating) = (1)::numeric)))::integer AS star1
|
|
235
|
+
FROM public.plg_reputation_reviews r
|
|
236
|
+
WHERE ((status = 'approved'::text) AND (product_id IS NOT NULL))
|
|
237
|
+
GROUP BY tenant_id, product_id;
|
|
238
|
+
|
|
239
|
+
CREATE VIEW public.v_public_product_reviews AS
|
|
240
|
+
SELECT id,
|
|
241
|
+
tenant_id,
|
|
242
|
+
product_id,
|
|
243
|
+
product_name,
|
|
244
|
+
product_slug,
|
|
245
|
+
author_name,
|
|
246
|
+
author_avatar_url,
|
|
247
|
+
rating,
|
|
248
|
+
title,
|
|
249
|
+
body,
|
|
250
|
+
source,
|
|
251
|
+
verified,
|
|
252
|
+
reply_text,
|
|
253
|
+
replied_at,
|
|
254
|
+
COALESCE(published_at, created_at) AS published_at
|
|
255
|
+
FROM public.plg_reputation_reviews r
|
|
256
|
+
WHERE (status = 'approved'::text);
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
-- \u2500\u2500 index \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
260
|
+
|
|
261
|
+
CREATE INDEX idx_plg_reputation_reviews_order ON public.plg_reputation_reviews USING btree (order_id);
|
|
262
|
+
|
|
263
|
+
CREATE INDEX idx_plg_reputation_reviews_product ON public.plg_reputation_reviews USING btree (tenant_id, product_id, status);
|
|
264
|
+
|
|
265
|
+
CREATE INDEX idx_plg_reputation_reviews_recent ON public.plg_reputation_reviews USING btree (tenant_id, status, created_at DESC);
|
|
266
|
+
|
|
267
|
+
CREATE INDEX idx_plg_reputation_reviews_tenant ON public.plg_reputation_reviews USING btree (tenant_id);
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
-- \u2500\u2500 fk constraint \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
271
|
+
|
|
272
|
+
ALTER TABLE ONLY public.plg_reputation_reviews
|
|
273
|
+
ADD CONSTRAINT plg_reputation_reviews_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
-- \u2500\u2500 row security \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
277
|
+
|
|
173
278
|
ALTER TABLE public.plg_reputation_reviews ENABLE ROW LEVEL SECURITY;
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
CREATE POLICY
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
SELECT
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
GRANT
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
-- \u2500\u2500 policy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
282
|
+
|
|
283
|
+
CREATE POLICY plg_reputation_reviews_delete ON public.plg_reputation_reviews FOR DELETE TO authenticated USING ((tenant_id IN ( SELECT public.user_tenant_ids() AS user_tenant_ids)));
|
|
284
|
+
|
|
285
|
+
CREATE POLICY plg_reputation_reviews_insert ON public.plg_reputation_reviews FOR INSERT TO authenticated WITH CHECK ((tenant_id IN ( SELECT public.user_tenant_ids() AS user_tenant_ids)));
|
|
286
|
+
|
|
287
|
+
CREATE POLICY plg_reputation_reviews_select ON public.plg_reputation_reviews FOR SELECT TO authenticated USING ((tenant_id IN ( SELECT public.user_tenant_ids() AS user_tenant_ids)));
|
|
288
|
+
|
|
289
|
+
CREATE POLICY plg_reputation_reviews_update ON public.plg_reputation_reviews FOR UPDATE TO authenticated USING ((tenant_id IN ( SELECT public.user_tenant_ids() AS user_tenant_ids)));
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
-- \u2500\u2500 acl \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
293
|
+
|
|
294
|
+
GRANT MAINTAIN ON TABLE public.plg_reputation_reviews TO anon;
|
|
295
|
+
GRANT ALL ON TABLE public.plg_reputation_reviews TO authenticated;
|
|
296
|
+
GRANT ALL ON TABLE public.plg_reputation_reviews TO service_role;
|
|
297
|
+
|
|
298
|
+
GRANT SELECT,MAINTAIN ON TABLE public.v_public_product_ratings TO anon;
|
|
299
|
+
GRANT ALL ON TABLE public.v_public_product_ratings TO authenticated;
|
|
300
|
+
GRANT ALL ON TABLE public.v_public_product_ratings TO service_role;
|
|
301
|
+
|
|
302
|
+
GRANT SELECT,MAINTAIN ON TABLE public.v_public_product_reviews TO anon;
|
|
303
|
+
GRANT ALL ON TABLE public.v_public_product_reviews TO authenticated;
|
|
304
|
+
GRANT ALL ON TABLE public.v_public_product_reviews TO service_role;
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
-- \u2500\u2500 default privileges: restore \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
308
|
+
-- Put back, so the NEXT thing installed inherits what the chain had.
|
|
309
|
+
|
|
310
|
+
DO $dp$ BEGIN
|
|
311
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;
|
|
312
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
313
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;
|
|
314
|
+
END $dp$;
|
|
315
|
+
|
|
316
|
+
DO $dp$ BEGIN
|
|
317
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;
|
|
318
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
319
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;
|
|
320
|
+
END $dp$;
|
|
321
|
+
|
|
322
|
+
DO $dp$ BEGIN
|
|
323
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;
|
|
324
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
325
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;
|
|
326
|
+
END $dp$;
|
|
327
|
+
|
|
328
|
+
DO $dp$ BEGIN
|
|
329
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;
|
|
330
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
331
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;
|
|
332
|
+
END $dp$;
|
|
333
|
+
|
|
334
|
+
DO $dp$ BEGIN
|
|
335
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;
|
|
336
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
337
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;
|
|
338
|
+
END $dp$;
|
|
339
|
+
|
|
340
|
+
DO $dp$ BEGIN
|
|
341
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;
|
|
342
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
343
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;
|
|
344
|
+
END $dp$;
|
|
345
|
+
|
|
346
|
+
DO $dp$ BEGIN
|
|
347
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;
|
|
348
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
349
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;
|
|
350
|
+
END $dp$;
|
|
351
|
+
|
|
352
|
+
DO $dp$ BEGIN
|
|
353
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;
|
|
354
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
355
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;
|
|
356
|
+
END $dp$;
|
|
357
|
+
|
|
358
|
+
DO $dp$ BEGIN
|
|
359
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;
|
|
360
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
361
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;
|
|
362
|
+
END $dp$;
|
|
363
|
+
|
|
364
|
+
DO $dp$ BEGIN
|
|
365
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;
|
|
366
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
367
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;
|
|
368
|
+
END $dp$;
|
|
369
|
+
|
|
370
|
+
DO $dp$ BEGIN
|
|
371
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;
|
|
372
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
373
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;
|
|
374
|
+
END $dp$;
|
|
375
|
+
|
|
376
|
+
DO $dp$ BEGIN
|
|
377
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;
|
|
378
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
379
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;
|
|
380
|
+
END $dp$;
|
|
381
|
+
|
|
382
|
+
DO $dp$ BEGIN
|
|
383
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO anon$stmt$;
|
|
384
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
385
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO anon$stmt$;
|
|
386
|
+
END $dp$;
|
|
387
|
+
|
|
388
|
+
DO $dp$ BEGIN
|
|
389
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;
|
|
390
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
391
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;
|
|
392
|
+
END $dp$;
|
|
393
|
+
|
|
394
|
+
DO $dp$ BEGIN
|
|
395
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;
|
|
396
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
397
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;
|
|
398
|
+
END $dp$;
|
|
399
|
+
|
|
400
|
+
DO $dp$ BEGIN
|
|
401
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;
|
|
402
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
403
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;
|
|
404
|
+
END $dp$;
|
|
405
|
+
|
|
406
|
+
DO $dp$ BEGIN
|
|
407
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT MAINTAIN ON TABLES TO anon$stmt$;
|
|
408
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
409
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT MAINTAIN ON TABLES TO anon$stmt$;
|
|
410
|
+
END $dp$;
|
|
411
|
+
|
|
412
|
+
DO $dp$ BEGIN
|
|
413
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;
|
|
414
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
415
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;
|
|
416
|
+
END $dp$;
|
|
417
|
+
|
|
418
|
+
DO $dp$ BEGIN
|
|
419
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;
|
|
420
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
421
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;
|
|
422
|
+
END $dp$;
|
|
423
|
+
|
|
424
|
+
DO $dp$ BEGIN
|
|
425
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;
|
|
426
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
427
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;
|
|
428
|
+
END $dp$;
|
|
429
|
+
|
|
430
|
+
DO $dp$ BEGIN
|
|
431
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO anon$stmt$;
|
|
432
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
433
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO anon$stmt$;
|
|
434
|
+
END $dp$;
|
|
435
|
+
|
|
436
|
+
DO $dp$ BEGIN
|
|
437
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;
|
|
438
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
439
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;
|
|
440
|
+
END $dp$;
|
|
441
|
+
|
|
442
|
+
DO $dp$ BEGIN
|
|
443
|
+
EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;
|
|
444
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
445
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;
|
|
446
|
+
END $dp$;
|
|
447
|
+
|
|
448
|
+
DO $dp$ BEGIN
|
|
449
|
+
EXECUTE $stmt$--
|
|
450
|
+
-- PostgreSQL database dump complete
|
|
451
|
+
--$stmt$;
|
|
452
|
+
EXCEPTION WHEN insufficient_privilege OR undefined_object THEN
|
|
453
|
+
RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$--
|
|
454
|
+
-- PostgreSQL database dump complete
|
|
455
|
+
--$stmt$;
|
|
456
|
+
END $dp$;
|
|
234
457
|
`;
|
|
235
458
|
var MIGRATIONS = [
|
|
236
|
-
{ id: "
|
|
459
|
+
{ id: "000_baseline", sql: MIGRATION_000_BASELINE }
|
|
237
460
|
];
|
|
238
461
|
|
|
239
462
|
// src/index.ts
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/views/ReputationHome.tsx","../src/migrations/index.ts","../src/index.ts"],"names":["React"],"mappings":"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","file":"index.js","sourcesContent":["import React from 'react'\nimport { Star, Send, Check, X, Trash2 } from 'lucide-react'\nimport { Button, PageHeaderActions, DataTable } from '@fayz-ai/ui'\nimport { useReviewSummary } from '../hooks/useReviewSummary'\nimport { useManagedReviews } from '../hooks/useManagedReviews'\nimport type { Review, ReviewStatus } from '../types'\n\n// ---------------------------------------------------------------------------\n// The reputation backoffice.\n//\n// Was five hardcoded reviews and a hardcoded 4.8. It now reads whatever provider\n// the host installed — Supabase when there is a session, the seed otherwise —\n// and the feed is a moderation queue: only `approved` rows reach the storefront,\n// so this screen is the thing that decides what a shopper sees.\n// ---------------------------------------------------------------------------\n\nconst STATUS_TABS: Array<{ id: ReviewStatus | 'all'; label: string }> = [\n { id: 'pending', label: 'Pendentes' },\n { id: 'approved', label: 'Publicadas' },\n { id: 'rejected', label: 'Recusadas' },\n { id: 'all', label: 'Todas' },\n]\n\nfunction Stars({ rating, className }: { rating: number; className?: string }) {\n return (\n <div className={`flex items-center gap-0.5 ${className ?? ''}`}>\n {[1, 2, 3, 4, 5].map((i) => (\n <Star\n key={i}\n className={`h-4 w-4 ${i <= Math.round(rating) ? 'fill-amber-400 text-amber-400' : 'text-muted-foreground/30'}`}\n />\n ))}\n </div>\n )\n}\n\nexport function ReputationHome() {\n const [tab, setTab] = React.useState<ReviewStatus | 'all'>('pending')\n const { summary: loadedSummary } = useReviewSummary()\n // null until the first load resolves; an empty aggregate renders the same\n // \"—\" as a business with no reviews, which is the honest thing to show.\n const summary = loadedSummary ?? { average: 0, count: 0, distribution: [] }\n const { reviews, loading, canModerate, setStatus, remove } = useManagedReviews(\n tab === 'all' ? {} : { status: tab },\n )\n\n const distribution = summary.distribution ?? []\n const total = summary.count\n\n const columns = React.useMemo(\n () => [\n {\n id: 'author',\n header: 'Cliente',\n cell: ({ row }: { row: { original: Review } }) => (\n <div className=\"min-w-[9rem]\">\n <p className=\"font-medium text-foreground\">{row.original.author}</p>\n <p className=\"text-xs text-muted-foreground\">{row.original.date || '—'}</p>\n </div>\n ),\n },\n {\n id: 'rating',\n header: 'Nota',\n cell: ({ row }: { row: { original: Review } }) => <Stars rating={row.original.rating} />,\n },\n {\n id: 'product',\n header: 'Produto',\n cell: ({ row }: { row: { original: Review } }) => (\n <span className=\"text-sm text-muted-foreground\">\n {/* No product means it is about the business, not a gap in the data. */}\n {row.original.productName ?? <em className=\"opacity-70\">a loja</em>}\n </span>\n ),\n },\n {\n id: 'text',\n header: 'Avaliação',\n cell: ({ row }: { row: { original: Review } }) => (\n <div className=\"max-w-[28rem]\">\n {row.original.title && <p className=\"font-medium text-foreground\">{row.original.title}</p>}\n <p className=\"line-clamp-2 text-sm text-muted-foreground\">{row.original.text}</p>\n {row.original.replyText && (\n <p className=\"mt-1 line-clamp-1 border-l-2 border-border pl-2 text-xs text-muted-foreground\">\n Resposta: {row.original.replyText}\n </p>\n )}\n </div>\n ),\n },\n {\n id: 'actions',\n header: '',\n cell: ({ row }: { row: { original: Review } }) => {\n const r = row.original\n return (\n <div className=\"flex items-center justify-end gap-1\">\n {r.status !== 'approved' && (\n <Button size=\"sm\" variant=\"ghost\" title=\"Publicar\" onClick={() => void setStatus(r.id, 'approved')}>\n <Check className=\"h-4 w-4\" />\n </Button>\n )}\n {r.status !== 'rejected' && (\n <Button size=\"sm\" variant=\"ghost\" title=\"Recusar\" onClick={() => void setStatus(r.id, 'rejected')}>\n <X className=\"h-4 w-4\" />\n </Button>\n )}\n <Button size=\"sm\" variant=\"ghost\" title=\"Excluir\" onClick={() => void remove(r.id)}>\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n )\n },\n },\n ],\n [setStatus, remove],\n )\n\n return (\n <div className=\"mx-auto max-w-6xl p-6\">\n <PageHeaderActions>\n <Button>\n <Send className=\"mr-1.5 h-4 w-4\" /> Pedir avaliações\n </Button>\n </PageHeaderActions>\n\n <div className=\"mt-6 grid grid-cols-1 gap-4 lg:grid-cols-3\">\n <div className=\"rounded-card border border-border bg-card p-5 text-center\">\n <p className=\"text-4xl font-bold text-foreground\">\n {total === 0 ? '—' : summary.average.toFixed(1).replace('.', ',')}\n </p>\n <Stars rating={summary.average} className=\"mt-1 justify-center\" />\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {total} {total === 1 ? 'avaliação' : 'avaliações'}\n </p>\n </div>\n <div className=\"rounded-card border border-border bg-card p-5 lg:col-span-2\">\n <div className=\"space-y-1.5\">\n {distribution.map((d) => (\n <div key={d.stars} className=\"flex items-center gap-2 text-xs\">\n <span className=\"w-6 text-muted-foreground\">{d.stars}★</span>\n <div className=\"h-2 flex-1 overflow-hidden rounded-full bg-muted\">\n <div\n className=\"h-full rounded-full bg-amber-400\"\n style={{ width: `${total === 0 ? 0 : (d.count / total) * 100}%` }}\n />\n </div>\n <span className=\"w-8 text-right text-muted-foreground\">{d.count}</span>\n </div>\n ))}\n </div>\n </div>\n </div>\n\n <div className=\"mt-6 flex flex-wrap gap-1\">\n {STATUS_TABS.map((t) => (\n <Button key={t.id} size=\"sm\" variant={tab === t.id ? 'default' : 'ghost'} onClick={() => setTab(t.id)}>\n {t.label}\n </Button>\n ))}\n </div>\n\n <div className=\"mt-3\">\n <DataTable\n columns={columns}\n data={reviews}\n loading={loading}\n emptyMessage={\n canModerate\n ? 'Nenhuma avaliação aqui ainda.'\n : 'Este app está lendo avaliações públicas e não pode moderá-las.'\n }\n />\n </div>\n </div>\n )\n}\n","// AUTO-GENERATED from 001_product_reviews.sql — regenerate with scripts/embed-migrations.mjs\n// SQL files are the source of truth; this inline copy lets the manifest declare\n// migrations as data. Do not edit by hand — run the embed script instead.\n\nexport const MIGRATION_001_PRODUCT_REVIEWS = `-- ============================================================================\n-- plugin-reputation 001: product reviews + public (anon) read surface\n--\n-- The plugin shipped with a mock-only reputation home. This is its first real\n-- table, and it carries BOTH shapes of review the plugin talks about:\n-- a business review — product_id IS NULL (the Google/Facebook feed)\n-- a product review — product_id IS NOT NULL (the storefront PDP)\n-- One table, because they are the same row to a merchant: an author, a rating,\n-- some words, and a reply. Prefix: plg_reputation_.\n--\n-- §1 plg_reputation_reviews — the reviews themselves\n-- §2 RLS: authenticated tenant CRUD (the backoffice)\n-- §3 v_public_product_reviews — anon-readable, APPROVED only, whitelisted\n-- §4 v_public_product_ratings — anon-readable per-product aggregate\n--\n-- Anon-access design mirrors plugin-blog's: the storefront runs with the\n-- publishable key and no session, so canonical tenant RLS yields nothing. Anon\n-- read is granted ONLY through the column-whitelisted, approved-only views; the\n-- front provider filters them by tenant_id. Idempotent + safe to re-run.\n--\n-- product_id deliberately has NO foreign key. plugin-shop owns plg_shop_products\n-- and may not be installed in a given pool — a FK here would make this migration\n-- fail on every non-commerce tenant. product_name/product_slug are a display\n-- snapshot taken at write time so the homepage card can render and link without\n-- this plugin ever reading another plugin's table.\n-- ============================================================================\n\n-- §1 — reviews\nCREATE TABLE IF NOT EXISTS public.plg_reputation_reviews (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n product_id uuid,\n product_name text,\n product_slug text,\n order_id uuid,\n author_name text NOT NULL,\n author_avatar_url text,\n rating numeric(2,1) NOT NULL CHECK (rating >= 1 AND rating <= 5),\n title text,\n body text NOT NULL DEFAULT '',\n source text NOT NULL DEFAULT 'Website',\n status text NOT NULL DEFAULT 'pending'\n CHECK (status IN ('pending', 'approved', 'rejected')),\n verified boolean NOT NULL DEFAULT false,\n reply_text text,\n replied_at timestamptz,\n published_at timestamptz,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now()\n);\nALTER TABLE public.plg_reputation_reviews ENABLE ROW LEVEL SECURITY;\nCREATE INDEX IF NOT EXISTS idx_plg_reputation_reviews_tenant ON public.plg_reputation_reviews(tenant_id);\nCREATE INDEX IF NOT EXISTS idx_plg_reputation_reviews_product ON public.plg_reputation_reviews(tenant_id, product_id, status);\nCREATE INDEX IF NOT EXISTS idx_plg_reputation_reviews_recent ON public.plg_reputation_reviews(tenant_id, status, created_at DESC);\nCREATE INDEX IF NOT EXISTS idx_plg_reputation_reviews_order ON public.plg_reputation_reviews(order_id);\n\n-- §2 — RLS: authenticated tenant CRUD (the backoffice writes here)\nDROP POLICY IF EXISTS plg_reputation_reviews_select ON public.plg_reputation_reviews;\nDROP POLICY IF EXISTS plg_reputation_reviews_insert ON public.plg_reputation_reviews;\nDROP POLICY IF EXISTS plg_reputation_reviews_update ON public.plg_reputation_reviews;\nDROP POLICY IF EXISTS plg_reputation_reviews_delete ON public.plg_reputation_reviews;\nCREATE POLICY plg_reputation_reviews_select ON public.plg_reputation_reviews FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));\nCREATE POLICY plg_reputation_reviews_insert ON public.plg_reputation_reviews FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));\nCREATE POLICY plg_reputation_reviews_update ON public.plg_reputation_reviews FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));\nCREATE POLICY plg_reputation_reviews_delete ON public.plg_reputation_reviews FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));\n\n-- §3 — anon-readable review feed (owner-rights view = deliberate, whitelisted,\n-- APPROVED only). author_avatar_url and the reply are safe to show; e-mail and\n-- order_id are not, so they are simply absent from the projection.\nCREATE OR REPLACE VIEW public.v_public_product_reviews AS\nSELECT\n r.id,\n r.tenant_id,\n r.product_id,\n r.product_name,\n r.product_slug,\n r.author_name,\n r.author_avatar_url,\n r.rating,\n r.title,\n r.body,\n r.source,\n r.verified,\n r.reply_text,\n r.replied_at,\n COALESCE(r.published_at, r.created_at) AS published_at\nFROM public.plg_reputation_reviews r\nWHERE r.status = 'approved';\n\nGRANT SELECT ON public.v_public_product_reviews TO anon, authenticated, service_role;\n\n-- §4 — per-product aggregate. Exists so a PDP costs ONE row instead of every\n-- review, and so a catalogue page can fetch ratings for a whole grid with a\n-- single \\`product_id=in.(…)\\`. Business reviews (product_id IS NULL) are excluded\n-- on purpose: they are not about any product.\nCREATE OR REPLACE VIEW public.v_public_product_ratings AS\nSELECT\n r.tenant_id,\n r.product_id,\n ROUND(AVG(r.rating), 1)::numeric(2,1) AS average,\n COUNT(*)::int AS count,\n COUNT(*) FILTER (WHERE ROUND(r.rating) = 5)::int AS star5,\n COUNT(*) FILTER (WHERE ROUND(r.rating) = 4)::int AS star4,\n COUNT(*) FILTER (WHERE ROUND(r.rating) = 3)::int AS star3,\n COUNT(*) FILTER (WHERE ROUND(r.rating) = 2)::int AS star2,\n COUNT(*) FILTER (WHERE ROUND(r.rating) = 1)::int AS star1\nFROM public.plg_reputation_reviews r\nWHERE r.status = 'approved' AND r.product_id IS NOT NULL\nGROUP BY r.tenant_id, r.product_id;\n\nGRANT SELECT ON public.v_public_product_ratings TO anon, authenticated, service_role;\n`\n\nexport const MIGRATIONS: Array<{ id: string; sql: string }> = [\n { id: \"001_product_reviews\", sql: MIGRATION_001_PRODUCT_REVIEWS },\n]\n","import React from 'react'\nimport type { PluginManifest, PluginScope, VerticalId } from '@fayz-ai/core'\nimport { createSafeDataProvider } from '@fayz-ai/core'\nimport { ReputationHome } from './views/ReputationHome'\nimport { ReputationProvider } from './context'\nimport { createMockReputationProvider, type ReputationSeed } from './data/mock'\nimport { createSupabaseReputationProvider } from './data/supabase'\nimport type { ReputationDataProvider } from './data/types'\nimport { reputationRegistries } from './data/registries'\nimport { MIGRATIONS } from './migrations'\n\n// ---------------------------------------------------------------------------\n// @fayz-ai/plugin-reputation — reviews & reputation (GoHighLevel \"Reputation\").\n// Universal plugin. M1 ships a rich mock home; Google/Facebook review sync +\n// automated review requests (over connectors + automations) come later.\n//\n// The public/website surface (createReputationWebsite + hooks + ReviewsList)\n// lives in the lean './public' subpath so a marketing-site host imports it\n// WITHOUT pulling the admin view's @fayz-ai/ui graph.\n// ---------------------------------------------------------------------------\n\n/** Version + prose for each migration, kept beside the manifest that ships it. */\nconst MIGRATION_META: Record<string, { version: string; description: string }> = {\n '001_product_reviews': {\n version: '1.0.0',\n description: 'Reviews table (business + product), RLS, and the anon-readable review/rating views',\n },\n}\n\nexport interface ReputationPluginOptions {\n navPosition?: number\n navSection?: 'main' | 'secondary' | 'settings'\n navLabel?: string\n scope?: PluginScope\n verticalId?: VerticalId\n /** Inject a custom provider. Overrides the safe Supabase/mock resolver. */\n dataProvider?: ReputationDataProvider\n /** Reviews to run on until the tables are populated (or in a demo). */\n seed?: ReputationSeed\n /** Tenant to read. Defaults to the active session tenant, which is what the\n * backoffice normally wants — pass this only for a fixed single-tenant app. */\n tenantId?: string\n}\n\nexport function createReputationPlugin(options?: ReputationPluginOptions): PluginManifest {\n // The screen used to render five hardcoded reviews. It now reads a provider,\n // so the plugin has to supply one: Supabase when a client and tenant exist,\n // the seed otherwise. createSafeDataProvider makes that choice lazily, per\n // call, which is what lets a host boot before its session is resolved.\n const provider =\n options?.dataProvider ??\n createSafeDataProvider(\n () => createSupabaseReputationProvider({ tenantId: options?.tenantId }),\n () => createMockReputationProvider({ seed: options?.seed }),\n )\n\n const PageComponent: React.ComponentType<unknown> = () =>\n React.createElement(ReputationProvider, {\n value: { provider },\n children: React.createElement(ReputationHome),\n })\n PageComponent.displayName = 'ReputationHome'\n\n return {\n id: 'reputation',\n name: options?.navLabel ?? 'Reputation',\n icon: 'Award',\n version: '1.0.0',\n scope: options?.scope ?? 'universal',\n verticalId: options?.verticalId,\n defaultEnabled: true,\n dependencies: [],\n declaredFeatures: [{ id: 'reputation', label: 'Reputation', group: 'Retain' }],\n navigation: [\n {\n section: options?.navSection ?? 'main',\n position: options?.navPosition ?? 8,\n label: options?.navLabel ?? 'Reputation',\n route: '/reputation',\n icon: 'Award',\n permission: { feature: 'reputation', action: 'read' as const },\n },\n ],\n routes: [\n {\n path: '/reputation',\n component: PageComponent,\n permission: { feature: 'reputation', action: 'read' as const },\n },\n ],\n widgets: [],\n // How the review request reaches the customer — the two the Fayz plugin\n // page lists for Reputação.\n integrations: ['whatsapp', 'twilio'],\n // Owns the reviews table and the two anon-read views. The backoffice here\n // writes them; the storefront surface in './public' only reads. Declared on\n // this manifest and not on the website one so a host that installs both\n // does not register the same migration twice.\n migrations: [\n ...MIGRATIONS.map((m) => ({\n id: `reputation-${m.id}`,\n version: MIGRATION_META[m.id]?.version ?? '1.0.0',\n sql: m.sql,\n description: MIGRATION_META[m.id]?.description ?? m.id,\n })),\n ],\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/views/ReputationHome.tsx","../src/migrations/index.ts","../src/index.ts"],"names":["React"],"mappings":"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","file":"index.js","sourcesContent":["import React from 'react'\nimport { Star, Send, Check, X, Trash2 } from 'lucide-react'\nimport { Button, PageHeaderActions, DataTable } from '@fayz-ai/ui'\nimport { useReviewSummary } from '../hooks/useReviewSummary'\nimport { useManagedReviews } from '../hooks/useManagedReviews'\nimport type { Review, ReviewStatus } from '../types'\n\n// ---------------------------------------------------------------------------\n// The reputation backoffice.\n//\n// Was five hardcoded reviews and a hardcoded 4.8. It now reads whatever provider\n// the host installed — Supabase when there is a session, the seed otherwise —\n// and the feed is a moderation queue: only `approved` rows reach the storefront,\n// so this screen is the thing that decides what a shopper sees.\n// ---------------------------------------------------------------------------\n\nconst STATUS_TABS: Array<{ id: ReviewStatus | 'all'; label: string }> = [\n { id: 'pending', label: 'Pendentes' },\n { id: 'approved', label: 'Publicadas' },\n { id: 'rejected', label: 'Recusadas' },\n { id: 'all', label: 'Todas' },\n]\n\nfunction Stars({ rating, className }: { rating: number; className?: string }) {\n return (\n <div className={`flex items-center gap-0.5 ${className ?? ''}`}>\n {[1, 2, 3, 4, 5].map((i) => (\n <Star\n key={i}\n className={`h-4 w-4 ${i <= Math.round(rating) ? 'fill-amber-400 text-amber-400' : 'text-muted-foreground/30'}`}\n />\n ))}\n </div>\n )\n}\n\nexport function ReputationHome() {\n const [tab, setTab] = React.useState<ReviewStatus | 'all'>('pending')\n const { summary: loadedSummary } = useReviewSummary()\n // null until the first load resolves; an empty aggregate renders the same\n // \"—\" as a business with no reviews, which is the honest thing to show.\n const summary = loadedSummary ?? { average: 0, count: 0, distribution: [] }\n const { reviews, loading, canModerate, setStatus, remove } = useManagedReviews(\n tab === 'all' ? {} : { status: tab },\n )\n\n const distribution = summary.distribution ?? []\n const total = summary.count\n\n const columns = React.useMemo(\n () => [\n {\n id: 'author',\n header: 'Cliente',\n cell: ({ row }: { row: { original: Review } }) => (\n <div className=\"min-w-[9rem]\">\n <p className=\"font-medium text-foreground\">{row.original.author}</p>\n <p className=\"text-xs text-muted-foreground\">{row.original.date || '—'}</p>\n </div>\n ),\n },\n {\n id: 'rating',\n header: 'Nota',\n cell: ({ row }: { row: { original: Review } }) => <Stars rating={row.original.rating} />,\n },\n {\n id: 'product',\n header: 'Produto',\n cell: ({ row }: { row: { original: Review } }) => (\n <span className=\"text-sm text-muted-foreground\">\n {/* No product means it is about the business, not a gap in the data. */}\n {row.original.productName ?? <em className=\"opacity-70\">a loja</em>}\n </span>\n ),\n },\n {\n id: 'text',\n header: 'Avaliação',\n cell: ({ row }: { row: { original: Review } }) => (\n <div className=\"max-w-[28rem]\">\n {row.original.title && <p className=\"font-medium text-foreground\">{row.original.title}</p>}\n <p className=\"line-clamp-2 text-sm text-muted-foreground\">{row.original.text}</p>\n {row.original.replyText && (\n <p className=\"mt-1 line-clamp-1 border-l-2 border-border pl-2 text-xs text-muted-foreground\">\n Resposta: {row.original.replyText}\n </p>\n )}\n </div>\n ),\n },\n {\n id: 'actions',\n header: '',\n cell: ({ row }: { row: { original: Review } }) => {\n const r = row.original\n return (\n <div className=\"flex items-center justify-end gap-1\">\n {r.status !== 'approved' && (\n <Button size=\"sm\" variant=\"ghost\" title=\"Publicar\" onClick={() => void setStatus(r.id, 'approved')}>\n <Check className=\"h-4 w-4\" />\n </Button>\n )}\n {r.status !== 'rejected' && (\n <Button size=\"sm\" variant=\"ghost\" title=\"Recusar\" onClick={() => void setStatus(r.id, 'rejected')}>\n <X className=\"h-4 w-4\" />\n </Button>\n )}\n <Button size=\"sm\" variant=\"ghost\" title=\"Excluir\" onClick={() => void remove(r.id)}>\n <Trash2 className=\"h-4 w-4\" />\n </Button>\n </div>\n )\n },\n },\n ],\n [setStatus, remove],\n )\n\n return (\n <div className=\"mx-auto max-w-6xl p-6\">\n <PageHeaderActions>\n <Button>\n <Send className=\"mr-1.5 h-4 w-4\" /> Pedir avaliações\n </Button>\n </PageHeaderActions>\n\n <div className=\"mt-6 grid grid-cols-1 gap-4 lg:grid-cols-3\">\n <div className=\"rounded-card border border-border bg-card p-5 text-center\">\n <p className=\"text-4xl font-bold text-foreground\">\n {total === 0 ? '—' : summary.average.toFixed(1).replace('.', ',')}\n </p>\n <Stars rating={summary.average} className=\"mt-1 justify-center\" />\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {total} {total === 1 ? 'avaliação' : 'avaliações'}\n </p>\n </div>\n <div className=\"rounded-card border border-border bg-card p-5 lg:col-span-2\">\n <div className=\"space-y-1.5\">\n {distribution.map((d) => (\n <div key={d.stars} className=\"flex items-center gap-2 text-xs\">\n <span className=\"w-6 text-muted-foreground\">{d.stars}★</span>\n <div className=\"h-2 flex-1 overflow-hidden rounded-full bg-muted\">\n <div\n className=\"h-full rounded-full bg-amber-400\"\n style={{ width: `${total === 0 ? 0 : (d.count / total) * 100}%` }}\n />\n </div>\n <span className=\"w-8 text-right text-muted-foreground\">{d.count}</span>\n </div>\n ))}\n </div>\n </div>\n </div>\n\n <div className=\"mt-6 flex flex-wrap gap-1\">\n {STATUS_TABS.map((t) => (\n <Button key={t.id} size=\"sm\" variant={tab === t.id ? 'default' : 'ghost'} onClick={() => setTab(t.id)}>\n {t.label}\n </Button>\n ))}\n </div>\n\n <div className=\"mt-3\">\n <DataTable\n columns={columns}\n data={reviews}\n loading={loading}\n emptyMessage={\n canModerate\n ? 'Nenhuma avaliação aqui ainda.'\n : 'Este app está lendo avaliações públicas e não pode moderá-las.'\n }\n />\n </div>\n </div>\n )\n}\n","// AUTO-GENERATED from 000_baseline.sql — regenerate with scripts/embed-migrations.mjs\n// SQL files are the source of truth; this inline copy lets the manifest declare\n// migrations as data. Do not edit by hand — run the embed script instead.\n\nexport const MIGRATION_000_BASELINE = `-- ============================================================================\n-- plugins/plugin-reputation/src/migrations/000_baseline.sql — what installing this provisions, as one file.\n--\n-- GENERATED by scripts/emit-unit-baselines.mjs (#338). Do not edit by hand:\n-- change the schema, regenerate, and let scripts/check-chain-equivalence.mjs\n-- prove the result still matches.\n--\n-- This replaced 1 migration files. They are kept, unapplied, in\n-- migrations.archive/ — a year of decisions is worth reading even when it is no\n-- longer worth replaying.\n--\n-- Object order is fixed rather than dependency-sorted: schemas, types,\n-- sequences, tables, defaults, functions, constraints, views, indexes, foreign\n-- keys, triggers, row security, policies, grants. Dependencies BETWEEN units\n-- are carried by the order packages/db/chain.json declares.\n-- ============================================================================\n\n-- A LANGUAGE sql function binds its body at CREATE time, and 570 functions\n-- sorted by name are not sorted by who calls whom. This is what lets them load\n-- in any order; every body is still compiled on first call, so a genuinely\n-- broken reference surfaces then rather than never. Session-scoped.\nSET check_function_bodies = false;\n\n\n\n-- ── default privileges: reset ───────────────────────────────────────────\n-- Cleared BEFORE anything is created, so every object below gets the ACL the\n-- dump describes rather than the image's defaults on top of it. Restored at\n-- the end of this file.\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\n\n-- ── table ───────────────────────────────────────────────────────────────\n\nCREATE TABLE public.plg_reputation_reviews (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n product_id uuid,\n product_name text,\n product_slug text,\n order_id uuid,\n author_name text NOT NULL,\n author_avatar_url text,\n rating numeric(2,1) NOT NULL,\n title text,\n body text DEFAULT ''::text NOT NULL,\n source text DEFAULT 'Website'::text NOT NULL,\n status text DEFAULT 'pending'::text NOT NULL,\n verified boolean DEFAULT false NOT NULL,\n reply_text text,\n replied_at timestamp with time zone,\n published_at timestamp with time zone,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n CONSTRAINT plg_reputation_reviews_rating_check CHECK (((rating >= (1)::numeric) AND (rating <= (5)::numeric))),\n CONSTRAINT plg_reputation_reviews_status_check CHECK ((status = ANY (ARRAY['pending'::text, 'approved'::text, 'rejected'::text])))\n);\n\n\n-- ── constraint ──────────────────────────────────────────────────────────\n\nALTER TABLE ONLY public.plg_reputation_reviews\n ADD CONSTRAINT plg_reputation_reviews_pkey PRIMARY KEY (id);\n\n\n-- ── view ────────────────────────────────────────────────────────────────\n\nCREATE VIEW public.v_public_product_ratings AS\n SELECT tenant_id,\n product_id,\n (round(avg(rating), 1))::numeric(2,1) AS average,\n (count(*))::integer AS count,\n (count(*) FILTER (WHERE (round(rating) = (5)::numeric)))::integer AS star5,\n (count(*) FILTER (WHERE (round(rating) = (4)::numeric)))::integer AS star4,\n (count(*) FILTER (WHERE (round(rating) = (3)::numeric)))::integer AS star3,\n (count(*) FILTER (WHERE (round(rating) = (2)::numeric)))::integer AS star2,\n (count(*) FILTER (WHERE (round(rating) = (1)::numeric)))::integer AS star1\n FROM public.plg_reputation_reviews r\n WHERE ((status = 'approved'::text) AND (product_id IS NOT NULL))\n GROUP BY tenant_id, product_id;\n\nCREATE VIEW public.v_public_product_reviews AS\n SELECT id,\n tenant_id,\n product_id,\n product_name,\n product_slug,\n author_name,\n author_avatar_url,\n rating,\n title,\n body,\n source,\n verified,\n reply_text,\n replied_at,\n COALESCE(published_at, created_at) AS published_at\n FROM public.plg_reputation_reviews r\n WHERE (status = 'approved'::text);\n\n\n-- ── index ───────────────────────────────────────────────────────────────\n\nCREATE INDEX idx_plg_reputation_reviews_order ON public.plg_reputation_reviews USING btree (order_id);\n\nCREATE INDEX idx_plg_reputation_reviews_product ON public.plg_reputation_reviews USING btree (tenant_id, product_id, status);\n\nCREATE INDEX idx_plg_reputation_reviews_recent ON public.plg_reputation_reviews USING btree (tenant_id, status, created_at DESC);\n\nCREATE INDEX idx_plg_reputation_reviews_tenant ON public.plg_reputation_reviews USING btree (tenant_id);\n\n\n-- ── fk constraint ───────────────────────────────────────────────────────\n\nALTER TABLE ONLY public.plg_reputation_reviews\n ADD CONSTRAINT plg_reputation_reviews_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;\n\n\n-- ── row security ────────────────────────────────────────────────────────\n\nALTER TABLE public.plg_reputation_reviews ENABLE ROW LEVEL SECURITY;\n\n\n-- ── policy ──────────────────────────────────────────────────────────────\n\nCREATE POLICY plg_reputation_reviews_delete ON public.plg_reputation_reviews FOR DELETE TO authenticated USING ((tenant_id IN ( SELECT public.user_tenant_ids() AS user_tenant_ids)));\n\nCREATE POLICY plg_reputation_reviews_insert ON public.plg_reputation_reviews FOR INSERT TO authenticated WITH CHECK ((tenant_id IN ( SELECT public.user_tenant_ids() AS user_tenant_ids)));\n\nCREATE POLICY plg_reputation_reviews_select ON public.plg_reputation_reviews FOR SELECT TO authenticated USING ((tenant_id IN ( SELECT public.user_tenant_ids() AS user_tenant_ids)));\n\nCREATE POLICY plg_reputation_reviews_update ON public.plg_reputation_reviews FOR UPDATE TO authenticated USING ((tenant_id IN ( SELECT public.user_tenant_ids() AS user_tenant_ids)));\n\n\n-- ── acl ─────────────────────────────────────────────────────────────────\n\nGRANT MAINTAIN ON TABLE public.plg_reputation_reviews TO anon;\nGRANT ALL ON TABLE public.plg_reputation_reviews TO authenticated;\nGRANT ALL ON TABLE public.plg_reputation_reviews TO service_role;\n\nGRANT SELECT,MAINTAIN ON TABLE public.v_public_product_ratings TO anon;\nGRANT ALL ON TABLE public.v_public_product_ratings TO authenticated;\nGRANT ALL ON TABLE public.v_public_product_ratings TO service_role;\n\nGRANT SELECT,MAINTAIN ON TABLE public.v_public_product_reviews TO anon;\nGRANT ALL ON TABLE public.v_public_product_reviews TO authenticated;\nGRANT ALL ON TABLE public.v_public_product_reviews TO service_role;\n\n\n-- ── default privileges: restore ─────────────────────────────────────────\n-- Put back, so the NEXT thing installed inherits what the chain had.\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT MAINTAIN ON TABLES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT MAINTAIN ON TABLES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$--\n-- PostgreSQL database dump complete\n--$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set — %', $stmt$--\n-- PostgreSQL database dump complete\n--$stmt$;\nEND $dp$;\n`\n\nexport const MIGRATIONS: Array<{ id: string; sql: string }> = [\n { id: \"000_baseline\", sql: MIGRATION_000_BASELINE },\n]\n","import React from 'react'\nimport type { PluginManifest, PluginScope, VerticalId } from '@fayz-ai/core'\nimport { createSafeDataProvider } from '@fayz-ai/core'\nimport { ReputationHome } from './views/ReputationHome'\nimport { ReputationProvider } from './context'\nimport { createMockReputationProvider, type ReputationSeed } from './data/mock'\nimport { createSupabaseReputationProvider } from './data/supabase'\nimport type { ReputationDataProvider } from './data/types'\nimport { reputationRegistries } from './data/registries'\nimport { MIGRATIONS } from './migrations'\n\n// ---------------------------------------------------------------------------\n// @fayz-ai/plugin-reputation — reviews & reputation (GoHighLevel \"Reputation\").\n// Universal plugin. M1 ships a rich mock home; Google/Facebook review sync +\n// automated review requests (over connectors + automations) come later.\n//\n// The public/website surface (createReputationWebsite + hooks + ReviewsList)\n// lives in the lean './public' subpath so a marketing-site host imports it\n// WITHOUT pulling the admin view's @fayz-ai/ui graph.\n// ---------------------------------------------------------------------------\n\n/** Version + prose for each migration, kept beside the manifest that ships it. */\nconst MIGRATION_META: Record<string, { version: string; description: string }> = {\n '001_product_reviews': {\n version: '1.0.0',\n description: 'Reviews table (business + product), RLS, and the anon-readable review/rating views',\n },\n}\n\nexport interface ReputationPluginOptions {\n navPosition?: number\n navSection?: 'main' | 'secondary' | 'settings'\n navLabel?: string\n scope?: PluginScope\n verticalId?: VerticalId\n /** Inject a custom provider. Overrides the safe Supabase/mock resolver. */\n dataProvider?: ReputationDataProvider\n /** Reviews to run on until the tables are populated (or in a demo). */\n seed?: ReputationSeed\n /** Tenant to read. Defaults to the active session tenant, which is what the\n * backoffice normally wants — pass this only for a fixed single-tenant app. */\n tenantId?: string\n}\n\nexport function createReputationPlugin(options?: ReputationPluginOptions): PluginManifest {\n // The screen used to render five hardcoded reviews. It now reads a provider,\n // so the plugin has to supply one: Supabase when a client and tenant exist,\n // the seed otherwise. createSafeDataProvider makes that choice lazily, per\n // call, which is what lets a host boot before its session is resolved.\n const provider =\n options?.dataProvider ??\n createSafeDataProvider(\n () => createSupabaseReputationProvider({ tenantId: options?.tenantId }),\n () => createMockReputationProvider({ seed: options?.seed }),\n )\n\n const PageComponent: React.ComponentType<unknown> = () =>\n React.createElement(ReputationProvider, {\n value: { provider },\n children: React.createElement(ReputationHome),\n })\n PageComponent.displayName = 'ReputationHome'\n\n return {\n id: 'reputation',\n name: options?.navLabel ?? 'Reputation',\n icon: 'Award',\n version: '1.0.0',\n scope: options?.scope ?? 'universal',\n verticalId: options?.verticalId,\n defaultEnabled: true,\n dependencies: [],\n declaredFeatures: [{ id: 'reputation', label: 'Reputation', group: 'Retain' }],\n navigation: [\n {\n section: options?.navSection ?? 'main',\n position: options?.navPosition ?? 8,\n label: options?.navLabel ?? 'Reputation',\n route: '/reputation',\n icon: 'Award',\n permission: { feature: 'reputation', action: 'read' as const },\n },\n ],\n routes: [\n {\n path: '/reputation',\n component: PageComponent,\n permission: { feature: 'reputation', action: 'read' as const },\n },\n ],\n widgets: [],\n // How the review request reaches the customer — the two the Fayz plugin\n // page lists for Reputação.\n integrations: ['whatsapp', 'twilio'],\n // Owns the reviews table and the two anon-read views. The backoffice here\n // writes them; the storefront surface in './public' only reads. Declared on\n // this manifest and not on the website one so a host that installs both\n // does not register the same migration twice.\n migrations: [\n ...MIGRATIONS.map((m) => ({\n id: `reputation-${m.id}`,\n version: MIGRATION_META[m.id]?.version ?? '1.0.0',\n sql: m.sql,\n description: MIGRATION_META[m.id]?.description ?? m.id,\n })),\n ],\n }\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const MIGRATION_001_PRODUCT_REVIEWS = "-- ============================================================================\n-- plugin-reputation 001: product reviews + public (anon) read surface\n--\n-- The plugin shipped with a mock-only reputation home. This is its first real\n-- table, and it carries BOTH shapes of review the plugin talks about:\n-- a business review \u2014 product_id IS NULL (the Google/Facebook feed)\n-- a product review \u2014 product_id IS NOT NULL (the storefront PDP)\n-- One table, because they are the same row to a merchant: an author, a rating,\n-- some words, and a reply. Prefix: plg_reputation_.\n--\n-- \u00A71 plg_reputation_reviews \u2014 the reviews themselves\n-- \u00A72 RLS: authenticated tenant CRUD (the backoffice)\n-- \u00A73 v_public_product_reviews \u2014 anon-readable, APPROVED only, whitelisted\n-- \u00A74 v_public_product_ratings \u2014 anon-readable per-product aggregate\n--\n-- Anon-access design mirrors plugin-blog's: the storefront runs with the\n-- publishable key and no session, so canonical tenant RLS yields nothing. Anon\n-- read is granted ONLY through the column-whitelisted, approved-only views; the\n-- front provider filters them by tenant_id. Idempotent + safe to re-run.\n--\n-- product_id deliberately has NO foreign key. plugin-shop owns plg_shop_products\n-- and may not be installed in a given pool \u2014 a FK here would make this migration\n-- fail on every non-commerce tenant. product_name/product_slug are a display\n-- snapshot taken at write time so the homepage card can render and link without\n-- this plugin ever reading another plugin's table.\n-- ============================================================================\n\n-- \u00A71 \u2014 reviews\nCREATE TABLE IF NOT EXISTS public.plg_reputation_reviews (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n product_id uuid,\n product_name text,\n product_slug text,\n order_id uuid,\n author_name text NOT NULL,\n author_avatar_url text,\n rating numeric(2,1) NOT NULL CHECK (rating >= 1 AND rating <= 5),\n title text,\n body text NOT NULL DEFAULT '',\n source text NOT NULL DEFAULT 'Website',\n status text NOT NULL DEFAULT 'pending'\n CHECK (status IN ('pending', 'approved', 'rejected')),\n verified boolean NOT NULL DEFAULT false,\n reply_text text,\n replied_at timestamptz,\n published_at timestamptz,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now()\n);\nALTER TABLE public.plg_reputation_reviews ENABLE ROW LEVEL SECURITY;\nCREATE INDEX IF NOT EXISTS idx_plg_reputation_reviews_tenant ON public.plg_reputation_reviews(tenant_id);\nCREATE INDEX IF NOT EXISTS idx_plg_reputation_reviews_product ON public.plg_reputation_reviews(tenant_id, product_id, status);\nCREATE INDEX IF NOT EXISTS idx_plg_reputation_reviews_recent ON public.plg_reputation_reviews(tenant_id, status, created_at DESC);\nCREATE INDEX IF NOT EXISTS idx_plg_reputation_reviews_order ON public.plg_reputation_reviews(order_id);\n\n-- \u00A72 \u2014 RLS: authenticated tenant CRUD (the backoffice writes here)\nDROP POLICY IF EXISTS plg_reputation_reviews_select ON public.plg_reputation_reviews;\nDROP POLICY IF EXISTS plg_reputation_reviews_insert ON public.plg_reputation_reviews;\nDROP POLICY IF EXISTS plg_reputation_reviews_update ON public.plg_reputation_reviews;\nDROP POLICY IF EXISTS plg_reputation_reviews_delete ON public.plg_reputation_reviews;\nCREATE POLICY plg_reputation_reviews_select ON public.plg_reputation_reviews FOR SELECT TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));\nCREATE POLICY plg_reputation_reviews_insert ON public.plg_reputation_reviews FOR INSERT TO authenticated WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));\nCREATE POLICY plg_reputation_reviews_update ON public.plg_reputation_reviews FOR UPDATE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));\nCREATE POLICY plg_reputation_reviews_delete ON public.plg_reputation_reviews FOR DELETE TO authenticated USING (tenant_id IN (SELECT public.user_tenant_ids()));\n\n-- \u00A73 \u2014 anon-readable review feed (owner-rights view = deliberate, whitelisted,\n-- APPROVED only). author_avatar_url and the reply are safe to show; e-mail and\n-- order_id are not, so they are simply absent from the projection.\nCREATE OR REPLACE VIEW public.v_public_product_reviews AS\nSELECT\n r.id,\n r.tenant_id,\n r.product_id,\n r.product_name,\n r.product_slug,\n r.author_name,\n r.author_avatar_url,\n r.rating,\n r.title,\n r.body,\n r.source,\n r.verified,\n r.reply_text,\n r.replied_at,\n COALESCE(r.published_at, r.created_at) AS published_at\nFROM public.plg_reputation_reviews r\nWHERE r.status = 'approved';\n\nGRANT SELECT ON public.v_public_product_reviews TO anon, authenticated, service_role;\n\n-- \u00A74 \u2014 per-product aggregate. Exists so a PDP costs ONE row instead of every\n-- review, and so a catalogue page can fetch ratings for a whole grid with a\n-- single `product_id=in.(\u2026)`. Business reviews (product_id IS NULL) are excluded\n-- on purpose: they are not about any product.\nCREATE OR REPLACE VIEW public.v_public_product_ratings AS\nSELECT\n r.tenant_id,\n r.product_id,\n ROUND(AVG(r.rating), 1)::numeric(2,1) AS average,\n COUNT(*)::int AS count,\n COUNT(*) FILTER (WHERE ROUND(r.rating) = 5)::int AS star5,\n COUNT(*) FILTER (WHERE ROUND(r.rating) = 4)::int AS star4,\n COUNT(*) FILTER (WHERE ROUND(r.rating) = 3)::int AS star3,\n COUNT(*) FILTER (WHERE ROUND(r.rating) = 2)::int AS star2,\n COUNT(*) FILTER (WHERE ROUND(r.rating) = 1)::int AS star1\nFROM public.plg_reputation_reviews r\nWHERE r.status = 'approved' AND r.product_id IS NOT NULL\nGROUP BY r.tenant_id, r.product_id;\n\nGRANT SELECT ON public.v_public_product_ratings TO anon, authenticated, service_role;\n";
|
|
1
|
+
export declare const MIGRATION_000_BASELINE = "-- ============================================================================\n-- plugins/plugin-reputation/src/migrations/000_baseline.sql \u2014 what installing this provisions, as one file.\n--\n-- GENERATED by scripts/emit-unit-baselines.mjs (#338). Do not edit by hand:\n-- change the schema, regenerate, and let scripts/check-chain-equivalence.mjs\n-- prove the result still matches.\n--\n-- This replaced 1 migration files. They are kept, unapplied, in\n-- migrations.archive/ \u2014 a year of decisions is worth reading even when it is no\n-- longer worth replaying.\n--\n-- Object order is fixed rather than dependency-sorted: schemas, types,\n-- sequences, tables, defaults, functions, constraints, views, indexes, foreign\n-- keys, triggers, row security, policies, grants. Dependencies BETWEEN units\n-- are carried by the order packages/db/chain.json declares.\n-- ============================================================================\n\n-- A LANGUAGE sql function binds its body at CREATE time, and 570 functions\n-- sorted by name are not sorted by who calls whom. This is what lets them load\n-- in any order; every body is still compiled on first call, so a genuinely\n-- broken reference surfaces then rather than never. Session-scoped.\nSET check_function_bodies = false;\n\n\n\n-- \u2500\u2500 default privileges: reset \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n-- Cleared BEFORE anything is created, so every object below gets the ACL the\n-- dump describes rather than the image's defaults on top of it. Restored at\n-- the end of this file.\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON SEQUENCES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL ON TABLES FROM anon, authenticated, service_role, fayz_connector$stmt$;\nEND $dp$;\n\n\n-- \u2500\u2500 table \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nCREATE TABLE public.plg_reputation_reviews (\n id uuid DEFAULT gen_random_uuid() NOT NULL,\n tenant_id uuid NOT NULL,\n product_id uuid,\n product_name text,\n product_slug text,\n order_id uuid,\n author_name text NOT NULL,\n author_avatar_url text,\n rating numeric(2,1) NOT NULL,\n title text,\n body text DEFAULT ''::text NOT NULL,\n source text DEFAULT 'Website'::text NOT NULL,\n status text DEFAULT 'pending'::text NOT NULL,\n verified boolean DEFAULT false NOT NULL,\n reply_text text,\n replied_at timestamp with time zone,\n published_at timestamp with time zone,\n created_at timestamp with time zone DEFAULT now() NOT NULL,\n updated_at timestamp with time zone DEFAULT now() NOT NULL,\n CONSTRAINT plg_reputation_reviews_rating_check CHECK (((rating >= (1)::numeric) AND (rating <= (5)::numeric))),\n CONSTRAINT plg_reputation_reviews_status_check CHECK ((status = ANY (ARRAY['pending'::text, 'approved'::text, 'rejected'::text])))\n);\n\n\n-- \u2500\u2500 constraint \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nALTER TABLE ONLY public.plg_reputation_reviews\n ADD CONSTRAINT plg_reputation_reviews_pkey PRIMARY KEY (id);\n\n\n-- \u2500\u2500 view \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nCREATE VIEW public.v_public_product_ratings AS\n SELECT tenant_id,\n product_id,\n (round(avg(rating), 1))::numeric(2,1) AS average,\n (count(*))::integer AS count,\n (count(*) FILTER (WHERE (round(rating) = (5)::numeric)))::integer AS star5,\n (count(*) FILTER (WHERE (round(rating) = (4)::numeric)))::integer AS star4,\n (count(*) FILTER (WHERE (round(rating) = (3)::numeric)))::integer AS star3,\n (count(*) FILTER (WHERE (round(rating) = (2)::numeric)))::integer AS star2,\n (count(*) FILTER (WHERE (round(rating) = (1)::numeric)))::integer AS star1\n FROM public.plg_reputation_reviews r\n WHERE ((status = 'approved'::text) AND (product_id IS NOT NULL))\n GROUP BY tenant_id, product_id;\n\nCREATE VIEW public.v_public_product_reviews AS\n SELECT id,\n tenant_id,\n product_id,\n product_name,\n product_slug,\n author_name,\n author_avatar_url,\n rating,\n title,\n body,\n source,\n verified,\n reply_text,\n replied_at,\n COALESCE(published_at, created_at) AS published_at\n FROM public.plg_reputation_reviews r\n WHERE (status = 'approved'::text);\n\n\n-- \u2500\u2500 index \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nCREATE INDEX idx_plg_reputation_reviews_order ON public.plg_reputation_reviews USING btree (order_id);\n\nCREATE INDEX idx_plg_reputation_reviews_product ON public.plg_reputation_reviews USING btree (tenant_id, product_id, status);\n\nCREATE INDEX idx_plg_reputation_reviews_recent ON public.plg_reputation_reviews USING btree (tenant_id, status, created_at DESC);\n\nCREATE INDEX idx_plg_reputation_reviews_tenant ON public.plg_reputation_reviews USING btree (tenant_id);\n\n\n-- \u2500\u2500 fk constraint \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nALTER TABLE ONLY public.plg_reputation_reviews\n ADD CONSTRAINT plg_reputation_reviews_tenant_id_fkey FOREIGN KEY (tenant_id) REFERENCES public.tenants(id) ON DELETE CASCADE;\n\n\n-- \u2500\u2500 row security \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nALTER TABLE public.plg_reputation_reviews ENABLE ROW LEVEL SECURITY;\n\n\n-- \u2500\u2500 policy \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nCREATE POLICY plg_reputation_reviews_delete ON public.plg_reputation_reviews FOR DELETE TO authenticated USING ((tenant_id IN ( SELECT public.user_tenant_ids() AS user_tenant_ids)));\n\nCREATE POLICY plg_reputation_reviews_insert ON public.plg_reputation_reviews FOR INSERT TO authenticated WITH CHECK ((tenant_id IN ( SELECT public.user_tenant_ids() AS user_tenant_ids)));\n\nCREATE POLICY plg_reputation_reviews_select ON public.plg_reputation_reviews FOR SELECT TO authenticated USING ((tenant_id IN ( SELECT public.user_tenant_ids() AS user_tenant_ids)));\n\nCREATE POLICY plg_reputation_reviews_update ON public.plg_reputation_reviews FOR UPDATE TO authenticated USING ((tenant_id IN ( SELECT public.user_tenant_ids() AS user_tenant_ids)));\n\n\n-- \u2500\u2500 acl \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nGRANT MAINTAIN ON TABLE public.plg_reputation_reviews TO anon;\nGRANT ALL ON TABLE public.plg_reputation_reviews TO authenticated;\nGRANT ALL ON TABLE public.plg_reputation_reviews TO service_role;\n\nGRANT SELECT,MAINTAIN ON TABLE public.v_public_product_ratings TO anon;\nGRANT ALL ON TABLE public.v_public_product_ratings TO authenticated;\nGRANT ALL ON TABLE public.v_public_product_ratings TO service_role;\n\nGRANT SELECT,MAINTAIN ON TABLE public.v_public_product_reviews TO anon;\nGRANT ALL ON TABLE public.v_public_product_reviews TO authenticated;\nGRANT ALL ON TABLE public.v_public_product_reviews TO service_role;\n\n\n-- \u2500\u2500 default privileges: restore \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n-- Put back, so the NEXT thing installed inherits what the chain had.\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON SEQUENCES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON FUNCTIONS TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT MAINTAIN ON TABLES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT MAINTAIN ON TABLES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO postgres$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO anon$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO anon$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO authenticated$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT ALL ON TABLES TO service_role$stmt$;\nEND $dp$;\n\nDO $dp$ BEGIN\n EXECUTE $stmt$--\n-- PostgreSQL database dump complete\n--$stmt$;\nEXCEPTION WHEN insufficient_privilege OR undefined_object THEN\n RAISE NOTICE 'baseline: not ours to set \u2014 %', $stmt$--\n-- PostgreSQL database dump complete\n--$stmt$;\nEND $dp$;\n";
|
|
2
2
|
export declare const MIGRATIONS: Array<{
|
|
3
3
|
id: string;
|
|
4
4
|
sql: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,sBAAsB,sgqBA8UlC,CAAA;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAEzD,CAAA"}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"status": "preview",
|
|
5
5
|
"dependencies": []
|
|
6
6
|
},
|
|
7
|
-
"version": "0.10.
|
|
7
|
+
"version": "0.10.5",
|
|
8
8
|
"description": "[experimental] Fayz SDK — reviews & reputation management plugin",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"sideEffects": false,
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"lucide-react": ">=0.400.0 <1.0.0"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@fayz-ai/core": "^0.
|
|
34
|
-
"@fayz-ai/ui": "^0.
|
|
33
|
+
"@fayz-ai/core": "^0.21.0",
|
|
34
|
+
"@fayz-ai/ui": "^0.21.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/react": "^18.3.0",
|