@fayz-ai/plugin-forms 0.2.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/data/supabase.d.ts.map +1 -1
- package/dist/data/tables.d.ts +7 -0
- package/dist/data/tables.d.ts.map +1 -0
- package/dist/index.cjs +27 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -19
- package/dist/index.js.map +1 -1
- package/dist/migrations/index.d.ts +8 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +10 -4
- package/src/data/supabase.ts +20 -19
- package/src/data/tables.ts +7 -0
- package/src/index.ts +2 -1
- package/src/migrations/000_plg_rename.sql +21 -0
- package/src/migrations/001_frm_base.sql +92 -56
- package/src/migrations/002_document_archetype.sql +130 -42
- package/src/migrations/index.ts +433 -0
- package/src/types.ts +4 -4
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const MIGRATION_000_PLG_RENAME = "-- 000_plg_rename.sql \u2014 rename legacy forms tables to plg_forms_* for pools\n-- provisioned before the industry-pool rename. Guarded: fires only when the legacy\n-- name exists and the target does not, so fresh pools skip every branch.\n-- The core `documents` archetype table is NOT renamed \u2014 it stays public.documents.\nDO $$\nBEGIN\n IF to_regclass('public.frm_documents') IS NOT NULL AND to_regclass('public.plg_forms_documents') IS NULL THEN\n ALTER TABLE public.frm_documents RENAME TO plg_forms_documents;\n END IF;\n IF to_regclass('public.frm_templates') IS NOT NULL AND to_regclass('public.plg_forms_templates') IS NULL THEN\n ALTER TABLE public.frm_templates RENAME TO plg_forms_templates;\n END IF;\n IF to_regclass('public.frm_document_files') IS NOT NULL AND to_regclass('public.plg_forms_document_files') IS NULL THEN\n ALTER TABLE public.frm_document_files RENAME TO plg_forms_document_files;\n END IF;\n -- frm_categories: registry-declared (form-template categories); no base-table\n -- DDL ships in this plugin, but rename in place if a pool created one.\n IF to_regclass('public.frm_categories') IS NOT NULL AND to_regclass('public.plg_forms_categories') IS NULL THEN\n ALTER TABLE public.frm_categories RENAME TO plg_forms_categories;\n END IF;\nEND $$;\n";
|
|
2
|
+
export declare const MIGRATION_001_FRM_BASE = "-- ============================================================\n-- Custom Forms Plugin \u2014 Base Tables\n-- ============================================================\n\n-- plg_forms_templates: form template definitions (versioned)\nCREATE TABLE IF NOT EXISTS public.plg_forms_templates (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n name text NOT NULL,\n description text,\n category text NOT NULL DEFAULT 'general',\n version integer NOT NULL DEFAULT 1,\n is_current boolean NOT NULL DEFAULT true,\n parent_id uuid REFERENCES public.plg_forms_templates(id),\n schema jsonb NOT NULL DEFAULT '{\"fields\":[],\"layout\":{\"columns\":12}}',\n specialty text,\n tags text[] DEFAULT '{}',\n metadata jsonb DEFAULT '{}',\n is_active boolean NOT NULL DEFAULT true,\n is_deleted boolean NOT NULL DEFAULT false,\n created_by uuid,\n updated_by uuid,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now()\n);\n\nALTER TABLE public.plg_forms_templates ENABLE ROW LEVEL SECURITY;\n\nCREATE INDEX IF NOT EXISTS idx_plg_forms_templates_tenant\n ON public.plg_forms_templates(tenant_id);\nCREATE INDEX IF NOT EXISTS idx_plg_forms_templates_parent\n ON public.plg_forms_templates(parent_id);\nCREATE INDEX IF NOT EXISTS idx_plg_forms_templates_category\n ON public.plg_forms_templates(tenant_id, category);\nCREATE INDEX IF NOT EXISTS idx_plg_forms_templates_current\n ON public.plg_forms_templates(tenant_id, is_current, is_active)\n WHERE is_current = true AND is_active = true AND is_deleted = false;\n\nDROP POLICY IF EXISTS \"plg_forms_templates_select\" ON public.plg_forms_templates;\nCREATE POLICY \"plg_forms_templates_select\" ON public.plg_forms_templates\n FOR SELECT TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"plg_forms_templates_insert\" ON public.plg_forms_templates;\nCREATE POLICY \"plg_forms_templates_insert\" ON public.plg_forms_templates\n FOR INSERT TO authenticated\n WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"plg_forms_templates_update\" ON public.plg_forms_templates;\nCREATE POLICY \"plg_forms_templates_update\" ON public.plg_forms_templates\n FOR UPDATE TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"plg_forms_templates_delete\" ON public.plg_forms_templates;\nCREATE POLICY \"plg_forms_templates_delete\" ON public.plg_forms_templates\n FOR DELETE TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\n\n-- plg_forms_documents: filled form instances\nCREATE TABLE IF NOT EXISTS public.plg_forms_documents (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n template_id uuid NOT NULL REFERENCES public.plg_forms_templates(id),\n person_id uuid REFERENCES public.people(id) ON DELETE SET NULL,\n title text,\n data jsonb NOT NULL DEFAULT '{}',\n status text NOT NULL DEFAULT 'draft',\n signed_at timestamptz,\n signed_by uuid,\n notes text,\n metadata jsonb DEFAULT '{}',\n is_deleted boolean NOT NULL DEFAULT false,\n created_by uuid,\n updated_by uuid,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now()\n);\n\nALTER TABLE public.plg_forms_documents ENABLE ROW LEVEL SECURITY;\n\nCREATE INDEX IF NOT EXISTS idx_plg_forms_documents_tenant\n ON public.plg_forms_documents(tenant_id);\n-- person_id/status only exist in the pre-archetype shape this file creates;\n-- converted pools (salon) already carry the archetype extension shape\n-- (document_id PK, no person_id) \u2014 002 owns that shape, so guard these.\nDO $$\nBEGIN\n IF EXISTS (\n SELECT 1 FROM information_schema.columns\n WHERE table_schema = 'public' AND table_name = 'plg_forms_documents'\n AND column_name = 'person_id'\n ) THEN\n EXECUTE 'CREATE INDEX IF NOT EXISTS idx_plg_forms_documents_person\n ON public.plg_forms_documents(person_id)';\n EXECUTE 'CREATE INDEX IF NOT EXISTS idx_plg_forms_documents_status\n ON public.plg_forms_documents(tenant_id, status)';\n END IF;\nEND $$;\nCREATE INDEX IF NOT EXISTS idx_plg_forms_documents_template\n ON public.plg_forms_documents(template_id);\n\nDROP POLICY IF EXISTS \"plg_forms_documents_select\" ON public.plg_forms_documents;\nCREATE POLICY \"plg_forms_documents_select\" ON public.plg_forms_documents\n FOR SELECT TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"plg_forms_documents_insert\" ON public.plg_forms_documents;\nCREATE POLICY \"plg_forms_documents_insert\" ON public.plg_forms_documents\n FOR INSERT TO authenticated\n WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"plg_forms_documents_update\" ON public.plg_forms_documents;\nCREATE POLICY \"plg_forms_documents_update\" ON public.plg_forms_documents\n FOR UPDATE TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"plg_forms_documents_delete\" ON public.plg_forms_documents;\nCREATE POLICY \"plg_forms_documents_delete\" ON public.plg_forms_documents\n FOR DELETE TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\n\n-- plg_forms_document_files: file attachments for image/gallery/drawing fields\nCREATE TABLE IF NOT EXISTS public.plg_forms_document_files (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n document_id uuid NOT NULL REFERENCES public.plg_forms_documents(id) ON DELETE CASCADE,\n field_key text NOT NULL,\n file_url text NOT NULL,\n file_name text,\n file_size integer,\n mime_type text,\n sort_order integer DEFAULT 0,\n metadata jsonb DEFAULT '{}',\n created_at timestamptz NOT NULL DEFAULT now()\n);\n\nALTER TABLE public.plg_forms_document_files ENABLE ROW LEVEL SECURITY;\n\nCREATE INDEX IF NOT EXISTS idx_plg_forms_document_files_document\n ON public.plg_forms_document_files(document_id);\n\nDROP POLICY IF EXISTS \"plg_forms_document_files_select\" ON public.plg_forms_document_files;\nCREATE POLICY \"plg_forms_document_files_select\" ON public.plg_forms_document_files\n FOR SELECT TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"plg_forms_document_files_insert\" ON public.plg_forms_document_files;\nCREATE POLICY \"plg_forms_document_files_insert\" ON public.plg_forms_document_files\n FOR INSERT TO authenticated\n WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"plg_forms_document_files_update\" ON public.plg_forms_document_files;\nCREATE POLICY \"plg_forms_document_files_update\" ON public.plg_forms_document_files\n FOR UPDATE TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"plg_forms_document_files_delete\" ON public.plg_forms_document_files;\nCREATE POLICY \"plg_forms_document_files_delete\" ON public.plg_forms_document_files\n FOR DELETE TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\n\n-- View: pre-archetype read model (needs person_id; archetype pools get\n-- v_documents from 002 instead, which also drops this view when migrating).\nDO $$\nBEGIN\n IF EXISTS (\n SELECT 1 FROM information_schema.columns\n WHERE table_schema = 'public' AND table_name = 'plg_forms_documents'\n AND column_name = 'person_id'\n ) THEN\n EXECUTE $v$\n CREATE OR REPLACE VIEW public.v_frm_documents AS\n SELECT\n d.*,\n t.name AS template_name,\n t.category AS template_category,\n p.name AS person_name\n FROM public.plg_forms_documents d\n LEFT JOIN public.plg_forms_templates t ON t.id = d.template_id\n LEFT JOIN public.people p ON p.id = d.person_id\n $v$;\n END IF;\nEND $$;\n";
|
|
3
|
+
export declare const MIGRATION_002_DOCUMENT_ARCHETYPE = "-- ============================================================\n-- Document Archetype \u2014 public.documents\n-- A document is any record associated with a person (or standalone):\n-- forms, images, attachments, prescriptions, contracts, etc.\n-- The `kind` column discriminates the type.\n--\n-- DATA SAFETY (converted pools): plg_forms_documents may already hold REAL\n-- rows in its PRE-archetype shape (its own `id` PK, no `document_id` column \u2014\n-- see 001_frm_base.sql). This migration MIGRATES those rows into the new\n-- document archetype instead of dropping them:\n-- * pre-archetype + rows -> copy each legacy row into public.documents\n-- (reusing its id) + into the new extension\n-- table, migrate its files, then drop legacy.\n-- * pre-archetype + empty -> plain drop + create (fresh shape).\n-- * already new shape -> no-op.\n-- ============================================================\n\nCREATE TABLE IF NOT EXISTS public.documents (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n kind text NOT NULL DEFAULT 'attachment',\n -- kind: 'form', 'image', 'attachment', 'prescription', 'contract', etc.\n person_id uuid REFERENCES public.people(id) ON DELETE SET NULL,\n title text,\n description text,\n status text NOT NULL DEFAULT 'draft',\n -- status: 'draft', 'completed', 'signed', 'archived'\n file_url text,\n file_name text,\n file_size integer,\n mime_type text,\n tags text[] DEFAULT '{}',\n notes text,\n is_active boolean NOT NULL DEFAULT true,\n metadata jsonb DEFAULT '{}',\n created_by uuid,\n updated_by uuid,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now()\n);\n\nALTER TABLE public.documents ENABLE ROW LEVEL SECURITY;\n\nCREATE INDEX IF NOT EXISTS idx_documents_tenant ON public.documents(tenant_id, kind);\nCREATE INDEX IF NOT EXISTS idx_documents_person ON public.documents(person_id);\nCREATE INDEX IF NOT EXISTS idx_documents_status ON public.documents(tenant_id, status);\n\nDROP POLICY IF EXISTS \"documents_select\" ON public.documents;\nCREATE POLICY \"documents_select\" ON public.documents\n FOR SELECT TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"documents_insert\" ON public.documents;\nCREATE POLICY \"documents_insert\" ON public.documents\n FOR INSERT TO authenticated\n WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"documents_update\" ON public.documents;\nCREATE POLICY \"documents_update\" ON public.documents\n FOR UPDATE TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"documents_delete\" ON public.documents;\nCREATE POLICY \"documents_delete\" ON public.documents\n FOR DELETE TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\n\n-- ============================================================\n-- Reconcile plg_forms_documents / plg_forms_document_files with the archetype.\n-- ============================================================\n\n-- Step 1: if a PRE-archetype plg_forms_documents is present (no document_id\n-- column), rename it (and its files table + dependent view) out of the way so\n-- the new archetype-shaped tables can be created and \u2014 when it holds rows \u2014\n-- its data copied across. Fully guarded, so already-migrated pools skip this.\nDO $$\nBEGIN\n IF to_regclass('public.plg_forms_documents') IS NOT NULL\n AND NOT EXISTS (\n SELECT 1 FROM information_schema.columns\n WHERE table_schema = 'public'\n AND table_name = 'plg_forms_documents'\n AND column_name = 'document_id'\n ) THEN\n DROP VIEW IF EXISTS public.v_frm_documents;\n ALTER TABLE public.plg_forms_documents RENAME TO plg_forms_documents_legacy;\n IF to_regclass('public.plg_forms_document_files') IS NOT NULL THEN\n ALTER TABLE public.plg_forms_document_files RENAME TO plg_forms_document_files_legacy;\n END IF;\n END IF;\nEND $$;\n\n-- Step 2: create the new archetype-shaped extension tables. IF NOT EXISTS makes\n-- this a no-op on pools already migrated to the new shape; after Step 1 the\n-- names are free on pre-archetype pools.\n\n-- plg_forms_documents: extension table for form-type documents\nCREATE TABLE IF NOT EXISTS public.plg_forms_documents (\n document_id uuid PRIMARY KEY REFERENCES public.documents(id) ON DELETE CASCADE,\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n template_id uuid NOT NULL REFERENCES public.plg_forms_templates(id),\n data jsonb NOT NULL DEFAULT '{}',\n signed_at timestamptz,\n signed_by uuid,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now()\n);\n\nALTER TABLE public.plg_forms_documents ENABLE ROW LEVEL SECURITY;\n\nCREATE INDEX IF NOT EXISTS idx_plg_forms_documents_template ON public.plg_forms_documents(template_id);\n\nDROP POLICY IF EXISTS \"plg_forms_documents_select\" ON public.plg_forms_documents;\nCREATE POLICY \"plg_forms_documents_select\" ON public.plg_forms_documents\n FOR SELECT TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"plg_forms_documents_insert\" ON public.plg_forms_documents;\nCREATE POLICY \"plg_forms_documents_insert\" ON public.plg_forms_documents\n FOR INSERT TO authenticated\n WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"plg_forms_documents_update\" ON public.plg_forms_documents;\nCREATE POLICY \"plg_forms_documents_update\" ON public.plg_forms_documents\n FOR UPDATE TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"plg_forms_documents_delete\" ON public.plg_forms_documents;\nCREATE POLICY \"plg_forms_documents_delete\" ON public.plg_forms_documents\n FOR DELETE TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\n\n-- plg_forms_document_files: file attachments for form fields\nCREATE TABLE IF NOT EXISTS public.plg_forms_document_files (\n id uuid PRIMARY KEY DEFAULT gen_random_uuid(),\n tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,\n document_id uuid NOT NULL REFERENCES public.documents(id) ON DELETE CASCADE,\n field_key text NOT NULL,\n file_url text NOT NULL,\n file_name text,\n file_size integer,\n mime_type text,\n sort_order integer DEFAULT 0,\n metadata jsonb DEFAULT '{}',\n created_at timestamptz NOT NULL DEFAULT now()\n);\n\nALTER TABLE public.plg_forms_document_files ENABLE ROW LEVEL SECURITY;\n\nCREATE INDEX IF NOT EXISTS idx_plg_forms_document_files_document ON public.plg_forms_document_files(document_id);\n\nDROP POLICY IF EXISTS \"plg_forms_document_files_select\" ON public.plg_forms_document_files;\nCREATE POLICY \"plg_forms_document_files_select\" ON public.plg_forms_document_files\n FOR SELECT TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"plg_forms_document_files_insert\" ON public.plg_forms_document_files;\nCREATE POLICY \"plg_forms_document_files_insert\" ON public.plg_forms_document_files\n FOR INSERT TO authenticated\n WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"plg_forms_document_files_update\" ON public.plg_forms_document_files;\nCREATE POLICY \"plg_forms_document_files_update\" ON public.plg_forms_document_files\n FOR UPDATE TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\nDROP POLICY IF EXISTS \"plg_forms_document_files_delete\" ON public.plg_forms_document_files;\nCREATE POLICY \"plg_forms_document_files_delete\" ON public.plg_forms_document_files\n FOR DELETE TO authenticated\n USING (tenant_id IN (SELECT public.user_tenant_ids()));\n\n-- Step 3: if legacy rows exist, migrate them, then drop the quarantined legacy\n-- tables. Reusing each legacy id as the documents.id keeps every legacy file's\n-- document_id FK valid after the copy. ON CONFLICT DO NOTHING makes a partial\n-- re-run safe.\nDO $$\nBEGIN\n IF to_regclass('public.plg_forms_documents_legacy') IS NOT NULL THEN\n -- 3a. base document (one per legacy form document; is_active mirrors NOT is_deleted)\n INSERT INTO public.documents (\n id, tenant_id, kind, person_id, title, status, notes, metadata,\n is_active, created_by, updated_by, created_at, updated_at\n )\n SELECT\n id, tenant_id, 'form', person_id, title, status, notes, metadata,\n NOT COALESCE(is_deleted, false), created_by, updated_by, created_at, updated_at\n FROM public.plg_forms_documents_legacy\n ON CONFLICT (id) DO NOTHING;\n\n -- 3b. form extension row (keyed by the reused document id)\n INSERT INTO public.plg_forms_documents (\n document_id, tenant_id, template_id, data, signed_at, signed_by, created_at, updated_at\n )\n SELECT\n id, tenant_id, template_id, data, signed_at, signed_by, created_at, updated_at\n FROM public.plg_forms_documents_legacy\n ON CONFLICT (document_id) DO NOTHING;\n\n -- 3c. file attachments (document_id already points at the reused id)\n IF to_regclass('public.plg_forms_document_files_legacy') IS NOT NULL THEN\n INSERT INTO public.plg_forms_document_files (\n id, tenant_id, document_id, field_key, file_url, file_name,\n file_size, mime_type, sort_order, metadata, created_at\n )\n SELECT\n id, tenant_id, document_id, field_key, file_url, file_name,\n file_size, mime_type, sort_order, metadata, created_at\n FROM public.plg_forms_document_files_legacy\n ON CONFLICT (id) DO NOTHING;\n END IF;\n END IF;\n\n -- Drop legacy remnants now that any data has been copied across.\n DROP TABLE IF EXISTS public.plg_forms_document_files_legacy;\n DROP TABLE IF EXISTS public.plg_forms_documents_legacy;\nEND $$;\n\n-- View: all documents for a person with form data joined when applicable\nCREATE OR REPLACE VIEW public.v_documents AS\nSELECT\n d.*,\n f.template_id,\n f.data AS form_data,\n f.signed_at,\n f.signed_by,\n t.name AS template_name,\n t.category AS template_category,\n p.name AS person_name\nFROM public.documents d\nLEFT JOIN public.plg_forms_documents f ON f.document_id = d.id\nLEFT JOIN public.plg_forms_templates t ON t.id = f.template_id\nLEFT JOIN public.people p ON p.id = d.person_id;\n";
|
|
4
|
+
export declare const MIGRATIONS: Array<{
|
|
5
|
+
id: string;
|
|
6
|
+
sql: string;
|
|
7
|
+
}>;
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,wBAAwB,iyCAqBpC,CAAA;AAED,eAAO,MAAM,sBAAsB,y1PA8KlC,CAAA;AAED,eAAO,MAAM,gCAAgC,0xUA+N5C,CAAA;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAIzD,CAAA"}
|
package/dist/types.d.ts
CHANGED
|
@@ -69,7 +69,7 @@ export interface FormDocument {
|
|
|
69
69
|
updatedBy?: string;
|
|
70
70
|
createdAt: string;
|
|
71
71
|
updatedAt: string;
|
|
72
|
-
/** Document kind from
|
|
72
|
+
/** Document kind from public.documents */
|
|
73
73
|
kind?: string;
|
|
74
74
|
/** File URL for image/attachment documents */
|
|
75
75
|
fileUrl?: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fayz-ai/plugin-forms",
|
|
3
|
-
"
|
|
3
|
+
"fayz": {
|
|
4
|
+
"status": "beta"
|
|
5
|
+
},
|
|
6
|
+
"version": "0.8.0",
|
|
4
7
|
"description": "Fayz SDK — plugin-forms plugin",
|
|
5
8
|
"type": "module",
|
|
6
9
|
"main": "./dist/index.cjs",
|
|
@@ -29,9 +32,9 @@
|
|
|
29
32
|
"@dnd-kit/utilities": "^3.2.2",
|
|
30
33
|
"lucide-react": "^0.400.0",
|
|
31
34
|
"zustand": "^4.5.0",
|
|
32
|
-
"@fayz-ai/
|
|
33
|
-
"@fayz-ai/
|
|
34
|
-
"@fayz-ai/
|
|
35
|
+
"@fayz-ai/core": "^0.8.0",
|
|
36
|
+
"@fayz-ai/saas": "^0.8.0",
|
|
37
|
+
"@fayz-ai/ui": "^0.8.0"
|
|
35
38
|
},
|
|
36
39
|
"devDependencies": {
|
|
37
40
|
"@types/react": "^18.3.0",
|
|
@@ -46,6 +49,9 @@
|
|
|
46
49
|
"fayz-plugin",
|
|
47
50
|
"fayz-sdk"
|
|
48
51
|
],
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
},
|
|
49
55
|
"scripts": {
|
|
50
56
|
"build": "tsup && tsc --emitDeclarationOnly --declaration --declarationMap --noEmit false",
|
|
51
57
|
"dev": "tsup --watch",
|
package/src/data/supabase.ts
CHANGED
|
@@ -13,6 +13,7 @@ import type {
|
|
|
13
13
|
UpdateDocumentInput,
|
|
14
14
|
} from '../types'
|
|
15
15
|
import { getSupabaseClientOptional, getActiveTenantId } from '@fayz-ai/core'
|
|
16
|
+
import { T } from './tables'
|
|
16
17
|
|
|
17
18
|
function getTenantId(): string {
|
|
18
19
|
// Local override wins; else use the app's active tenant so writes pass RLS.
|
|
@@ -102,7 +103,7 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
102
103
|
async getTemplates(query: TemplateQuery): Promise<PaginatedResult<FormTemplate>> {
|
|
103
104
|
const db = getClient()
|
|
104
105
|
let qb = db
|
|
105
|
-
.from(
|
|
106
|
+
.from(T.templates)
|
|
106
107
|
.select('*', { count: 'exact' })
|
|
107
108
|
.eq('tenant_id', getTenantId())
|
|
108
109
|
.eq('is_current', true)
|
|
@@ -125,7 +126,7 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
125
126
|
async getTemplateById(id: string): Promise<FormTemplate | null> {
|
|
126
127
|
const db = getClient()
|
|
127
128
|
const { data, error } = await db
|
|
128
|
-
.from(
|
|
129
|
+
.from(T.templates)
|
|
129
130
|
.select('*')
|
|
130
131
|
.eq('id', id)
|
|
131
132
|
.eq('is_deleted', false)
|
|
@@ -138,7 +139,7 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
138
139
|
const db = getClient()
|
|
139
140
|
const tenantId = getTenantId()
|
|
140
141
|
const { data, error } = await db
|
|
141
|
-
.from(
|
|
142
|
+
.from(T.templates)
|
|
142
143
|
.insert({
|
|
143
144
|
tenant_id: tenantId,
|
|
144
145
|
name: input.name,
|
|
@@ -160,7 +161,7 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
160
161
|
const tenantId = getTenantId()
|
|
161
162
|
|
|
162
163
|
const { count } = await db
|
|
163
|
-
.from(
|
|
164
|
+
.from(T.documents)
|
|
164
165
|
.select('document_id', { count: 'exact', head: true })
|
|
165
166
|
.eq('template_id', id)
|
|
166
167
|
|
|
@@ -171,7 +172,7 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
171
172
|
if (!existing) throw new Error('Template not found')
|
|
172
173
|
|
|
173
174
|
const { data: newRow, error: insertError } = await db
|
|
174
|
-
.from(
|
|
175
|
+
.from(T.templates)
|
|
175
176
|
.insert({
|
|
176
177
|
tenant_id: tenantId,
|
|
177
178
|
name: input.name ?? existing.name,
|
|
@@ -191,7 +192,7 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
191
192
|
if (insertError) throw new Error(insertError.message)
|
|
192
193
|
|
|
193
194
|
await db
|
|
194
|
-
.from(
|
|
195
|
+
.from(T.templates)
|
|
195
196
|
.update({ is_current: false, updated_at: new Date().toISOString() })
|
|
196
197
|
.eq('id', id)
|
|
197
198
|
|
|
@@ -209,7 +210,7 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
209
210
|
if (input.isActive !== undefined) updates.is_active = input.isActive
|
|
210
211
|
|
|
211
212
|
const { data, error } = await db
|
|
212
|
-
.from(
|
|
213
|
+
.from(T.templates)
|
|
213
214
|
.update(updates)
|
|
214
215
|
.eq('id', id)
|
|
215
216
|
.select()
|
|
@@ -221,13 +222,13 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
221
222
|
async deleteTemplate(id: string): Promise<void> {
|
|
222
223
|
const db = getClient()
|
|
223
224
|
const { error } = await db
|
|
224
|
-
.from(
|
|
225
|
+
.from(T.templates)
|
|
225
226
|
.update({ is_deleted: true, updated_at: new Date().toISOString() })
|
|
226
227
|
.eq('id', id)
|
|
227
228
|
if (error) throw new Error(error.message)
|
|
228
229
|
},
|
|
229
230
|
|
|
230
|
-
// ── Documents (
|
|
231
|
+
// ── Documents (public.documents + plg_forms_documents extension) ──
|
|
231
232
|
|
|
232
233
|
async getDocuments(query: DocumentQuery): Promise<PaginatedResult<FormDocument>> {
|
|
233
234
|
const db = getClient()
|
|
@@ -272,9 +273,9 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
272
273
|
const tenantId = getTenantId()
|
|
273
274
|
const isForm = !!input.templateId
|
|
274
275
|
|
|
275
|
-
// Step 1: Insert into
|
|
276
|
+
// Step 1: Insert into public.documents
|
|
276
277
|
const { data: coreDoc, error: coreError } = await getClient()
|
|
277
|
-
.from('
|
|
278
|
+
.from('documents')
|
|
278
279
|
.insert({
|
|
279
280
|
tenant_id: tenantId,
|
|
280
281
|
kind: input.kind ?? (isForm ? 'form' : 'attachment'),
|
|
@@ -295,7 +296,7 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
295
296
|
if (isForm && input.templateId) {
|
|
296
297
|
const db = getClient()
|
|
297
298
|
const { error: extError } = await db
|
|
298
|
-
.from(
|
|
299
|
+
.from(T.documents)
|
|
299
300
|
.insert({
|
|
300
301
|
document_id: coreDoc.id,
|
|
301
302
|
tenant_id: tenantId,
|
|
@@ -304,7 +305,7 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
304
305
|
})
|
|
305
306
|
if (extError) {
|
|
306
307
|
// Rollback core insert
|
|
307
|
-
await getClient().from('
|
|
308
|
+
await getClient().from('documents').delete().eq('id', coreDoc.id)
|
|
308
309
|
throw new Error(extError.message)
|
|
309
310
|
}
|
|
310
311
|
}
|
|
@@ -324,7 +325,7 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
324
325
|
if (input.notes !== undefined) coreUpdates.notes = input.notes
|
|
325
326
|
|
|
326
327
|
const { error: coreError } = await getClient()
|
|
327
|
-
.from('
|
|
328
|
+
.from('documents')
|
|
328
329
|
.update(coreUpdates)
|
|
329
330
|
.eq('id', id)
|
|
330
331
|
if (coreError) throw new Error(coreError.message)
|
|
@@ -333,7 +334,7 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
333
334
|
if (input.data !== undefined) {
|
|
334
335
|
const db = getClient()
|
|
335
336
|
await db
|
|
336
|
-
.from(
|
|
337
|
+
.from(T.documents)
|
|
337
338
|
.update({ data: input.data, updated_at: now })
|
|
338
339
|
.eq('document_id', id)
|
|
339
340
|
}
|
|
@@ -344,7 +345,7 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
344
345
|
|
|
345
346
|
async deleteDocument(id: string): Promise<void> {
|
|
346
347
|
const { error } = await getClient()
|
|
347
|
-
.from('
|
|
348
|
+
.from('documents')
|
|
348
349
|
.update({ is_active: false, updated_at: new Date().toISOString() })
|
|
349
350
|
.eq('id', id)
|
|
350
351
|
if (error) throw new Error(error.message)
|
|
@@ -355,7 +356,7 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
355
356
|
async getDocumentFiles(documentId: string): Promise<DocumentFile[]> {
|
|
356
357
|
const db = getClient()
|
|
357
358
|
const { data, error } = await db
|
|
358
|
-
.from(
|
|
359
|
+
.from(T.documentFiles)
|
|
359
360
|
.select('*')
|
|
360
361
|
.eq('document_id', documentId)
|
|
361
362
|
.order('sort_order')
|
|
@@ -377,7 +378,7 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
377
378
|
const { data: urlData } = db.storage.from('documents').getPublicUrl(storagePath)
|
|
378
379
|
|
|
379
380
|
const { data, error } = await db
|
|
380
|
-
.from(
|
|
381
|
+
.from(T.documentFiles)
|
|
381
382
|
.insert({
|
|
382
383
|
tenant_id: tenantId,
|
|
383
384
|
document_id: documentId,
|
|
@@ -396,7 +397,7 @@ export function createSupabaseFormsProvider(): CustomFormsDataProvider {
|
|
|
396
397
|
async deleteFile(fileId: string): Promise<void> {
|
|
397
398
|
const db = getClient()
|
|
398
399
|
const { error } = await db
|
|
399
|
-
.from(
|
|
400
|
+
.from(T.documentFiles)
|
|
400
401
|
.delete()
|
|
401
402
|
.eq('id', fileId)
|
|
402
403
|
if (error) throw new Error(error.message)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Central physical-table-name registry for plugin-forms. `documents` stays core.
|
|
2
|
+
export const T = {
|
|
3
|
+
documents: 'plg_forms_documents',
|
|
4
|
+
templates: 'plg_forms_templates',
|
|
5
|
+
documentFiles: 'plg_forms_document_files',
|
|
6
|
+
categories: 'plg_forms_categories',
|
|
7
|
+
} as const
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import type { PluginManifest } from '@fayz-ai/core'
|
|
3
3
|
import type { CustomFormsDataProvider } from './data/types'
|
|
4
|
+
import { T } from './data/tables'
|
|
4
5
|
import { createMockFormsProvider } from './data/mock'
|
|
5
6
|
import { createSupabaseFormsProvider } from './data/supabase'
|
|
6
7
|
import { createSafeDataProvider, registerTranslations } from '@fayz-ai/core'
|
|
@@ -82,7 +83,7 @@ export function createCustomFormsPlugin(options?: CustomFormsPluginOptions): Plu
|
|
|
82
83
|
{ key: 'isActive', label: 'Active', type: 'boolean' as const, showInTable: true, defaultValue: true, inlineToggle: true },
|
|
83
84
|
],
|
|
84
85
|
data: {
|
|
85
|
-
table:
|
|
86
|
+
table: T.categories,
|
|
86
87
|
tenantScoped: true,
|
|
87
88
|
},
|
|
88
89
|
},
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
-- 000_plg_rename.sql — rename legacy forms tables to plg_forms_* for pools
|
|
2
|
+
-- provisioned before the industry-pool rename. Guarded: fires only when the legacy
|
|
3
|
+
-- name exists and the target does not, so fresh pools skip every branch.
|
|
4
|
+
-- The core `documents` archetype table is NOT renamed — it stays public.documents.
|
|
5
|
+
DO $$
|
|
6
|
+
BEGIN
|
|
7
|
+
IF to_regclass('public.frm_documents') IS NOT NULL AND to_regclass('public.plg_forms_documents') IS NULL THEN
|
|
8
|
+
ALTER TABLE public.frm_documents RENAME TO plg_forms_documents;
|
|
9
|
+
END IF;
|
|
10
|
+
IF to_regclass('public.frm_templates') IS NOT NULL AND to_regclass('public.plg_forms_templates') IS NULL THEN
|
|
11
|
+
ALTER TABLE public.frm_templates RENAME TO plg_forms_templates;
|
|
12
|
+
END IF;
|
|
13
|
+
IF to_regclass('public.frm_document_files') IS NOT NULL AND to_regclass('public.plg_forms_document_files') IS NULL THEN
|
|
14
|
+
ALTER TABLE public.frm_document_files RENAME TO plg_forms_document_files;
|
|
15
|
+
END IF;
|
|
16
|
+
-- frm_categories: registry-declared (form-template categories); no base-table
|
|
17
|
+
-- DDL ships in this plugin, but rename in place if a pool created one.
|
|
18
|
+
IF to_regclass('public.frm_categories') IS NOT NULL AND to_regclass('public.plg_forms_categories') IS NULL THEN
|
|
19
|
+
ALTER TABLE public.frm_categories RENAME TO plg_forms_categories;
|
|
20
|
+
END IF;
|
|
21
|
+
END $$;
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
-- Custom Forms Plugin — Base Tables
|
|
3
3
|
-- ============================================================
|
|
4
4
|
|
|
5
|
-
--
|
|
6
|
-
CREATE TABLE IF NOT EXISTS public.
|
|
5
|
+
-- plg_forms_templates: form template definitions (versioned)
|
|
6
|
+
CREATE TABLE IF NOT EXISTS public.plg_forms_templates (
|
|
7
7
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
8
|
-
tenant_id uuid NOT NULL REFERENCES
|
|
8
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
9
9
|
name text NOT NULL,
|
|
10
10
|
description text,
|
|
11
11
|
category text NOT NULL DEFAULT 'general',
|
|
12
12
|
version integer NOT NULL DEFAULT 1,
|
|
13
13
|
is_current boolean NOT NULL DEFAULT true,
|
|
14
|
-
parent_id uuid REFERENCES public.
|
|
14
|
+
parent_id uuid REFERENCES public.plg_forms_templates(id),
|
|
15
15
|
schema jsonb NOT NULL DEFAULT '{"fields":[],"layout":{"columns":12}}',
|
|
16
16
|
specialty text,
|
|
17
17
|
tags text[] DEFAULT '{}',
|
|
@@ -24,37 +24,41 @@ CREATE TABLE IF NOT EXISTS public.frm_templates (
|
|
|
24
24
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
25
25
|
);
|
|
26
26
|
|
|
27
|
-
ALTER TABLE public.
|
|
27
|
+
ALTER TABLE public.plg_forms_templates ENABLE ROW LEVEL SECURITY;
|
|
28
28
|
|
|
29
|
-
CREATE INDEX IF NOT EXISTS
|
|
30
|
-
ON public.
|
|
31
|
-
CREATE INDEX IF NOT EXISTS
|
|
32
|
-
ON public.
|
|
33
|
-
CREATE INDEX IF NOT EXISTS
|
|
34
|
-
ON public.
|
|
35
|
-
CREATE INDEX IF NOT EXISTS
|
|
36
|
-
ON public.
|
|
29
|
+
CREATE INDEX IF NOT EXISTS idx_plg_forms_templates_tenant
|
|
30
|
+
ON public.plg_forms_templates(tenant_id);
|
|
31
|
+
CREATE INDEX IF NOT EXISTS idx_plg_forms_templates_parent
|
|
32
|
+
ON public.plg_forms_templates(parent_id);
|
|
33
|
+
CREATE INDEX IF NOT EXISTS idx_plg_forms_templates_category
|
|
34
|
+
ON public.plg_forms_templates(tenant_id, category);
|
|
35
|
+
CREATE INDEX IF NOT EXISTS idx_plg_forms_templates_current
|
|
36
|
+
ON public.plg_forms_templates(tenant_id, is_current, is_active)
|
|
37
37
|
WHERE is_current = true AND is_active = true AND is_deleted = false;
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
DROP POLICY IF EXISTS "plg_forms_templates_select" ON public.plg_forms_templates;
|
|
40
|
+
CREATE POLICY "plg_forms_templates_select" ON public.plg_forms_templates
|
|
40
41
|
FOR SELECT TO authenticated
|
|
41
42
|
USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
42
|
-
|
|
43
|
+
DROP POLICY IF EXISTS "plg_forms_templates_insert" ON public.plg_forms_templates;
|
|
44
|
+
CREATE POLICY "plg_forms_templates_insert" ON public.plg_forms_templates
|
|
43
45
|
FOR INSERT TO authenticated
|
|
44
46
|
WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
45
|
-
|
|
47
|
+
DROP POLICY IF EXISTS "plg_forms_templates_update" ON public.plg_forms_templates;
|
|
48
|
+
CREATE POLICY "plg_forms_templates_update" ON public.plg_forms_templates
|
|
46
49
|
FOR UPDATE TO authenticated
|
|
47
50
|
USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
48
|
-
|
|
51
|
+
DROP POLICY IF EXISTS "plg_forms_templates_delete" ON public.plg_forms_templates;
|
|
52
|
+
CREATE POLICY "plg_forms_templates_delete" ON public.plg_forms_templates
|
|
49
53
|
FOR DELETE TO authenticated
|
|
50
54
|
USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
51
55
|
|
|
52
|
-
--
|
|
53
|
-
CREATE TABLE IF NOT EXISTS public.
|
|
56
|
+
-- plg_forms_documents: filled form instances
|
|
57
|
+
CREATE TABLE IF NOT EXISTS public.plg_forms_documents (
|
|
54
58
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
55
|
-
tenant_id uuid NOT NULL REFERENCES
|
|
56
|
-
template_id uuid NOT NULL REFERENCES public.
|
|
57
|
-
person_id uuid REFERENCES
|
|
59
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
60
|
+
template_id uuid NOT NULL REFERENCES public.plg_forms_templates(id),
|
|
61
|
+
person_id uuid REFERENCES public.people(id) ON DELETE SET NULL,
|
|
58
62
|
title text,
|
|
59
63
|
data jsonb NOT NULL DEFAULT '{}',
|
|
60
64
|
status text NOT NULL DEFAULT 'draft',
|
|
@@ -69,35 +73,51 @@ CREATE TABLE IF NOT EXISTS public.frm_documents (
|
|
|
69
73
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
70
74
|
);
|
|
71
75
|
|
|
72
|
-
ALTER TABLE public.
|
|
76
|
+
ALTER TABLE public.plg_forms_documents ENABLE ROW LEVEL SECURITY;
|
|
73
77
|
|
|
74
|
-
CREATE INDEX IF NOT EXISTS
|
|
75
|
-
ON public.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
CREATE INDEX IF NOT EXISTS idx_plg_forms_documents_tenant
|
|
79
|
+
ON public.plg_forms_documents(tenant_id);
|
|
80
|
+
-- person_id/status only exist in the pre-archetype shape this file creates;
|
|
81
|
+
-- converted pools (salon) already carry the archetype extension shape
|
|
82
|
+
-- (document_id PK, no person_id) — 002 owns that shape, so guard these.
|
|
83
|
+
DO $$
|
|
84
|
+
BEGIN
|
|
85
|
+
IF EXISTS (
|
|
86
|
+
SELECT 1 FROM information_schema.columns
|
|
87
|
+
WHERE table_schema = 'public' AND table_name = 'plg_forms_documents'
|
|
88
|
+
AND column_name = 'person_id'
|
|
89
|
+
) THEN
|
|
90
|
+
EXECUTE 'CREATE INDEX IF NOT EXISTS idx_plg_forms_documents_person
|
|
91
|
+
ON public.plg_forms_documents(person_id)';
|
|
92
|
+
EXECUTE 'CREATE INDEX IF NOT EXISTS idx_plg_forms_documents_status
|
|
93
|
+
ON public.plg_forms_documents(tenant_id, status)';
|
|
94
|
+
END IF;
|
|
95
|
+
END $$;
|
|
96
|
+
CREATE INDEX IF NOT EXISTS idx_plg_forms_documents_template
|
|
97
|
+
ON public.plg_forms_documents(template_id);
|
|
82
98
|
|
|
83
|
-
|
|
99
|
+
DROP POLICY IF EXISTS "plg_forms_documents_select" ON public.plg_forms_documents;
|
|
100
|
+
CREATE POLICY "plg_forms_documents_select" ON public.plg_forms_documents
|
|
84
101
|
FOR SELECT TO authenticated
|
|
85
102
|
USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
86
|
-
|
|
103
|
+
DROP POLICY IF EXISTS "plg_forms_documents_insert" ON public.plg_forms_documents;
|
|
104
|
+
CREATE POLICY "plg_forms_documents_insert" ON public.plg_forms_documents
|
|
87
105
|
FOR INSERT TO authenticated
|
|
88
106
|
WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
89
|
-
|
|
107
|
+
DROP POLICY IF EXISTS "plg_forms_documents_update" ON public.plg_forms_documents;
|
|
108
|
+
CREATE POLICY "plg_forms_documents_update" ON public.plg_forms_documents
|
|
90
109
|
FOR UPDATE TO authenticated
|
|
91
110
|
USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
92
|
-
|
|
111
|
+
DROP POLICY IF EXISTS "plg_forms_documents_delete" ON public.plg_forms_documents;
|
|
112
|
+
CREATE POLICY "plg_forms_documents_delete" ON public.plg_forms_documents
|
|
93
113
|
FOR DELETE TO authenticated
|
|
94
114
|
USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
95
115
|
|
|
96
|
-
--
|
|
97
|
-
CREATE TABLE IF NOT EXISTS public.
|
|
116
|
+
-- plg_forms_document_files: file attachments for image/gallery/drawing fields
|
|
117
|
+
CREATE TABLE IF NOT EXISTS public.plg_forms_document_files (
|
|
98
118
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
99
|
-
tenant_id uuid NOT NULL REFERENCES
|
|
100
|
-
document_id uuid NOT NULL REFERENCES public.
|
|
119
|
+
tenant_id uuid NOT NULL REFERENCES public.tenants(id) ON DELETE CASCADE,
|
|
120
|
+
document_id uuid NOT NULL REFERENCES public.plg_forms_documents(id) ON DELETE CASCADE,
|
|
101
121
|
field_key text NOT NULL,
|
|
102
122
|
file_url text NOT NULL,
|
|
103
123
|
file_name text,
|
|
@@ -108,31 +128,47 @@ CREATE TABLE IF NOT EXISTS public.frm_document_files (
|
|
|
108
128
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
109
129
|
);
|
|
110
130
|
|
|
111
|
-
ALTER TABLE public.
|
|
131
|
+
ALTER TABLE public.plg_forms_document_files ENABLE ROW LEVEL SECURITY;
|
|
112
132
|
|
|
113
|
-
CREATE INDEX IF NOT EXISTS
|
|
114
|
-
ON public.
|
|
133
|
+
CREATE INDEX IF NOT EXISTS idx_plg_forms_document_files_document
|
|
134
|
+
ON public.plg_forms_document_files(document_id);
|
|
115
135
|
|
|
116
|
-
|
|
136
|
+
DROP POLICY IF EXISTS "plg_forms_document_files_select" ON public.plg_forms_document_files;
|
|
137
|
+
CREATE POLICY "plg_forms_document_files_select" ON public.plg_forms_document_files
|
|
117
138
|
FOR SELECT TO authenticated
|
|
118
139
|
USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
119
|
-
|
|
140
|
+
DROP POLICY IF EXISTS "plg_forms_document_files_insert" ON public.plg_forms_document_files;
|
|
141
|
+
CREATE POLICY "plg_forms_document_files_insert" ON public.plg_forms_document_files
|
|
120
142
|
FOR INSERT TO authenticated
|
|
121
143
|
WITH CHECK (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
122
|
-
|
|
144
|
+
DROP POLICY IF EXISTS "plg_forms_document_files_update" ON public.plg_forms_document_files;
|
|
145
|
+
CREATE POLICY "plg_forms_document_files_update" ON public.plg_forms_document_files
|
|
123
146
|
FOR UPDATE TO authenticated
|
|
124
147
|
USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
125
|
-
|
|
148
|
+
DROP POLICY IF EXISTS "plg_forms_document_files_delete" ON public.plg_forms_document_files;
|
|
149
|
+
CREATE POLICY "plg_forms_document_files_delete" ON public.plg_forms_document_files
|
|
126
150
|
FOR DELETE TO authenticated
|
|
127
151
|
USING (tenant_id IN (SELECT public.user_tenant_ids()));
|
|
128
152
|
|
|
129
|
-
-- View:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
153
|
+
-- View: pre-archetype read model (needs person_id; archetype pools get
|
|
154
|
+
-- v_documents from 002 instead, which also drops this view when migrating).
|
|
155
|
+
DO $$
|
|
156
|
+
BEGIN
|
|
157
|
+
IF EXISTS (
|
|
158
|
+
SELECT 1 FROM information_schema.columns
|
|
159
|
+
WHERE table_schema = 'public' AND table_name = 'plg_forms_documents'
|
|
160
|
+
AND column_name = 'person_id'
|
|
161
|
+
) THEN
|
|
162
|
+
EXECUTE $v$
|
|
163
|
+
CREATE OR REPLACE VIEW public.v_frm_documents AS
|
|
164
|
+
SELECT
|
|
165
|
+
d.*,
|
|
166
|
+
t.name AS template_name,
|
|
167
|
+
t.category AS template_category,
|
|
168
|
+
p.name AS person_name
|
|
169
|
+
FROM public.plg_forms_documents d
|
|
170
|
+
LEFT JOIN public.plg_forms_templates t ON t.id = d.template_id
|
|
171
|
+
LEFT JOIN public.people p ON p.id = d.person_id
|
|
172
|
+
$v$;
|
|
173
|
+
END IF;
|
|
174
|
+
END $$;
|