realtimex-crm 0.9.2 → 0.9.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "realtimex-crm",
3
- "version": "0.9.2",
3
+ "version": "0.9.10",
4
4
  "description": "RealTimeX CRM - A full-featured CRM built with React, shadcn-admin-kit, and Supabase. Fork of Atomic CRM with RealTimeX App SDK integration.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -39,13 +39,13 @@ export const TagsListEdit = () => {
39
39
  const [update] = useUpdate<Contact>();
40
40
 
41
41
  const unselectedTags =
42
- allTags && record && allTags.filter((tag) => !record.tags.includes(tag.id));
42
+ allTags && record && allTags.filter((tag) => !(record.tags ?? []).includes(tag.id));
43
43
 
44
44
  const handleTagAdd = (id: Identifier) => {
45
45
  if (!record) {
46
46
  throw new Error("No contact record found");
47
47
  }
48
- const tags = [...record.tags, id];
48
+ const tags = [...(record.tags ?? []), id];
49
49
  update("contacts", {
50
50
  id: record.id,
51
51
  data: { tags },
@@ -57,7 +57,7 @@ export const TagsListEdit = () => {
57
57
  if (!record) {
58
58
  throw new Error("No contact record found");
59
59
  }
60
- const tags = record.tags.filter((tagId) => tagId !== id);
60
+ const tags = (record.tags ?? []).filter((tagId) => tagId !== id);
61
61
  await update("contacts", {
62
62
  id: record.id,
63
63
  data: { tags },
@@ -83,7 +83,7 @@ export const TagsListEdit = () => {
83
83
  "contacts",
84
84
  {
85
85
  id: record.id,
86
- data: { tags: [...record.tags, tag.id] },
86
+ data: { tags: [...(record.tags ?? []), tag.id] },
87
87
  previousData: record,
88
88
  },
89
89
  {
@@ -0,0 +1,27 @@
1
+ -- Function to enqueue webhook events
2
+ create or replace function enqueue_webhook_event(
3
+ p_event_type text,
4
+ p_payload jsonb
5
+ ) returns void
6
+ language plpgsql
7
+ security definer
8
+ set search_path = public
9
+ as $$
10
+ begin
11
+ -- Find all active webhooks that listen to this event
12
+ insert into public.webhook_queue (webhook_id, event_type, payload, next_retry_at)
13
+ select
14
+ id,
15
+ p_event_type,
16
+ p_payload,
17
+ now()
18
+ from public.webhooks
19
+ where is_active = true
20
+ and p_event_type = any(events);
21
+ end;
22
+ $$;
23
+
24
+ -- Grant execute permissions on webhook functions
25
+ grant execute on function enqueue_webhook_event(text, jsonb) to authenticated;
26
+ grant execute on function enqueue_webhook_event(text, jsonb) to service_role;
27
+ grant execute on function enqueue_webhook_event(text, jsonb) to anon;
@@ -0,0 +1,164 @@
1
+ -- Explicitly define function in public schema
2
+ create or replace function public.enqueue_webhook_event(
3
+ p_event_type text,
4
+ p_payload jsonb
5
+ ) returns void
6
+ language plpgsql
7
+ security definer
8
+ set search_path = public
9
+ as $$
10
+ begin
11
+ -- Find all active webhooks that listen to this event
12
+ insert into public.webhook_queue (webhook_id, event_type, payload, next_retry_at)
13
+ select
14
+ id,
15
+ p_event_type,
16
+ p_payload,
17
+ now()
18
+ from public.webhooks
19
+ where is_active = true
20
+ and p_event_type = any(events);
21
+ end;
22
+ $$;
23
+
24
+ -- Grant execute permissions
25
+ grant execute on function public.enqueue_webhook_event(text, jsonb) to authenticated;
26
+ grant execute on function public.enqueue_webhook_event(text, jsonb) to service_role;
27
+ grant execute on function public.enqueue_webhook_event(text, jsonb) to anon;
28
+
29
+ -- Update triggers to use fully qualified name
30
+
31
+ -- Trigger function for contact CRUD events
32
+ create or replace function public.trigger_contact_webhooks()
33
+ returns trigger
34
+ language plpgsql
35
+ security definer
36
+ set search_path = public
37
+ as $$
38
+ declare
39
+ event_type text;
40
+ payload jsonb;
41
+ begin
42
+ if (TG_OP = 'INSERT') then
43
+ event_type := 'contact.created';
44
+ payload := to_jsonb(NEW);
45
+ elsif (TG_OP = 'UPDATE') then
46
+ event_type := 'contact.updated';
47
+ payload := jsonb_build_object('old', to_jsonb(OLD), 'new', to_jsonb(NEW));
48
+ elsif (TG_OP = 'DELETE') then
49
+ event_type := 'contact.deleted';
50
+ payload := to_jsonb(OLD);
51
+ end if;
52
+
53
+ perform public.enqueue_webhook_event(event_type, payload);
54
+
55
+ if (TG_OP = 'DELETE') then
56
+ return OLD;
57
+ else
58
+ return NEW;
59
+ end if;
60
+ end;
61
+ $$;
62
+
63
+ -- Trigger function for company CRUD events
64
+ create or replace function public.trigger_company_webhooks()
65
+ returns trigger
66
+ language plpgsql
67
+ security definer
68
+ set search_path = public
69
+ as $$
70
+ declare
71
+ event_type text;
72
+ payload jsonb;
73
+ begin
74
+ if (TG_OP = 'INSERT') then
75
+ event_type := 'company.created';
76
+ payload := to_jsonb(NEW);
77
+ elsif (TG_OP = 'UPDATE') then
78
+ event_type := 'company.updated';
79
+ payload := jsonb_build_object('old', to_jsonb(OLD), 'new', to_jsonb(NEW));
80
+ elsif (TG_OP = 'DELETE') then
81
+ event_type := 'company.deleted';
82
+ payload := to_jsonb(OLD);
83
+ end if;
84
+
85
+ perform public.enqueue_webhook_event(event_type, payload);
86
+
87
+ if (TG_OP = 'DELETE') then
88
+ return OLD;
89
+ else
90
+ return NEW;
91
+ end if;
92
+ end;
93
+ $$;
94
+
95
+ -- Trigger function for deal CRUD and stage change events
96
+ create or replace function public.trigger_deal_webhooks()
97
+ returns trigger
98
+ language plpgsql
99
+ security definer
100
+ set search_path = public
101
+ as $$
102
+ declare
103
+ event_type text;
104
+ payload jsonb;
105
+ begin
106
+ if (TG_OP = 'INSERT') then
107
+ event_type := 'deal.created';
108
+ payload := to_jsonb(NEW);
109
+ perform public.enqueue_webhook_event(event_type, payload);
110
+ elsif (TG_OP = 'UPDATE') then
111
+ -- Check for stage changes
112
+ if (OLD.stage <> NEW.stage) then
113
+ event_type := 'deal.stage_changed';
114
+ payload := jsonb_build_object(
115
+ 'deal_id', NEW.id,
116
+ 'old_stage', OLD.stage,
117
+ 'new_stage', NEW.stage,
118
+ 'deal', to_jsonb(NEW)
119
+ );
120
+ perform public.enqueue_webhook_event(event_type, payload);
121
+
122
+ -- Check for won/lost
123
+ if (NEW.stage = 'won') then
124
+ perform public.enqueue_webhook_event('deal.won', to_jsonb(NEW));
125
+ elsif (NEW.stage = 'lost') then
126
+ perform public.enqueue_webhook_event('deal.lost', to_jsonb(NEW));
127
+ end if;
128
+ end if;
129
+
130
+ event_type := 'deal.updated';
131
+ payload := jsonb_build_object('old', to_jsonb(OLD), 'new', to_jsonb(NEW));
132
+ perform public.enqueue_webhook_event(event_type, payload);
133
+ elsif (TG_OP = 'DELETE') then
134
+ event_type := 'deal.deleted';
135
+ payload := to_jsonb(OLD);
136
+ perform public.enqueue_webhook_event(event_type, payload);
137
+ end if;
138
+
139
+ if (TG_OP = 'DELETE') then
140
+ return OLD;
141
+ else
142
+ return NEW;
143
+ end if;
144
+ end;
145
+ $$;
146
+
147
+ -- Trigger function for task completion
148
+ create or replace function public.trigger_task_webhooks()
149
+ returns trigger
150
+ language plpgsql
151
+ security definer
152
+ set search_path = public
153
+ as $$
154
+ begin
155
+ if (TG_OP = 'UPDATE' and OLD.done_date is null and NEW.done_date is not null) then
156
+ perform public.enqueue_webhook_event('task.completed', to_jsonb(NEW));
157
+ end if;
158
+
159
+ return NEW;
160
+ end;
161
+ $$;
162
+
163
+ -- Reload schema cache
164
+ NOTIFY pgrst, 'reload schema';