@consilioweb/payload-support 5.0.0 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +249 -22
- package/dist/components/RichTextEditor/index.js +1 -1
- package/dist/components/TicketConversation/RewriteDropdown.js +1 -1
- package/dist/components/TicketConversation/components/AISummaryPanel.js +3 -0
- package/dist/components/TicketConversation/components/ActionPanels.js +13 -8
- package/dist/components/TicketConversation/components/ClientHistory.js +1 -0
- package/dist/components/TicketConversation/components/CodeBlock.js +1 -0
- package/dist/components/TicketConversation/components/CodeBlockInserter.js +1 -1
- package/dist/components/TicketConversation/components/QuickActions.js +10 -8
- package/dist/components/TicketConversation/components/TicketHeader.js +2 -0
- package/dist/components/TicketConversation/components/TimeTrackingPanel.js +15 -9
- package/dist/components/TicketConversation/index.d.ts +10 -0
- package/dist/components/TicketConversation/index.js +25 -7
- package/dist/index.cjs +306 -60
- package/dist/index.d.cts +107 -38
- package/dist/index.d.ts +107 -38
- package/dist/index.js +300 -59
- package/dist/styles/BillingView.module.scss +11 -11
- package/dist/styles/ChatView.module.scss +7 -7
- package/dist/styles/CommandPalette.module.scss +1 -1
- package/dist/styles/CrmView.module.scss +9 -9
- package/dist/styles/EmailTracking.module.scss +6 -6
- package/dist/styles/ImportConversation.module.scss +5 -5
- package/dist/styles/Logs.module.scss +5 -5
- package/dist/styles/NewTicket.module.scss +2 -2
- package/dist/styles/PendingEmails.module.scss +13 -13
- package/dist/styles/SupportDashboard.module.scss +24 -8
- package/dist/styles/TicketDetail.module.scss +20 -20
- package/dist/styles/TicketInbox.module.scss +6 -6
- package/dist/styles/TicketingSettings.module.scss +10 -10
- package/dist/styles/TimeDashboard.module.scss +6 -6
- package/dist/styles/_tokens.scss +3 -1
- package/dist/utils/db.js +20 -0
- package/dist/utils/readSettings.js +150 -0
- package/dist/views/BillingView/client.js +15 -8
- package/dist/views/ChatView/client.js +2 -0
- package/dist/views/CrmView/client.js +2 -0
- package/dist/views/EmailTrackingView/client.js +23 -11
- package/dist/views/ImportConversationView/client.js +1 -0
- package/dist/views/LogsView/client.js +1 -1
- package/dist/views/NewTicketView/client.js +20 -13
- package/dist/views/PendingEmailsView/client.js +9 -3
- package/dist/views/SupportDashboardView/client.js +17 -19
- package/dist/views/TicketDetailView/client.js +23 -11
- package/dist/views/TicketInboxView/client.js +52 -26
- package/dist/views/TicketingSettingsView/TicketingSettings.module.scss +7 -7
- package/dist/views/TicketingSettingsView/client.js +44 -26
- package/dist/views/TimeDashboardView/client.js +10 -7
- package/dist/views/shared/ErrorBoundary.d.ts +36 -1
- package/dist/views/shared/ErrorBoundary.js +59 -28
- package/dist/views/shared/adminTokens.d.ts +15 -5
- package/dist/views/shared/adminTokens.js +23 -7
- package/dist/views/shared/icons.d.ts +49 -0
- package/dist/views/shared/icons.js +92 -0
- package/dist/views/shared/locales/en.json +15 -1
- package/dist/views/shared/locales/fr.json +15 -1
- package/package.json +9 -4
- package/scripts/copy-subpath-types.mjs +103 -0
- package/scripts/uninstall-data.mjs +178 -0
- package/scripts/uninstall.mjs +184 -0
- package/scripts/verify-dist-imports.mjs +84 -0
- package/src/collections/Tickets.ts +7 -0
- package/src/collections/TimeEntries.ts +11 -3
- package/src/components/RichTextEditor/index.tsx +1 -1
- package/src/components/TicketConversation/RewriteDropdown.tsx +1 -1
- package/src/components/TicketConversation/components/AISummaryPanel.tsx +3 -0
- package/src/components/TicketConversation/components/ActionPanels.tsx +13 -8
- package/src/components/TicketConversation/components/ClientHistory.tsx +1 -0
- package/src/components/TicketConversation/components/CodeBlock.tsx +1 -0
- package/src/components/TicketConversation/components/CodeBlockInserter.tsx +1 -1
- package/src/components/TicketConversation/components/QuickActions.tsx +10 -8
- package/src/components/TicketConversation/components/TicketHeader.tsx +2 -0
- package/src/components/TicketConversation/components/TimeTrackingPanel.tsx +17 -9
- package/src/components/TicketConversation/index.tsx +41 -7
- package/src/endpoints/delete-account.ts +191 -47
- package/src/endpoints/export-data.ts +104 -4
- package/src/endpoints/purge-logs.ts +6 -15
- package/src/index.ts +2 -0
- package/src/plugin.ts +51 -1
- package/src/portal/LiveChat.tsx +1 -1
- package/src/portal/auth/profile/page.tsx +3 -2
- package/src/portal/icons.tsx +91 -0
- package/src/styles/BillingView.module.scss +11 -11
- package/src/styles/ChatView.module.scss +7 -7
- package/src/styles/CommandPalette.module.scss +1 -1
- package/src/styles/CrmView.module.scss +9 -9
- package/src/styles/EmailTracking.module.scss +6 -6
- package/src/styles/ImportConversation.module.scss +5 -5
- package/src/styles/Logs.module.scss +5 -5
- package/src/styles/NewTicket.module.scss +2 -2
- package/src/styles/PendingEmails.module.scss +13 -13
- package/src/styles/SupportDashboard.module.scss +24 -8
- package/src/styles/TicketDetail.module.scss +20 -20
- package/src/styles/TicketInbox.module.scss +6 -6
- package/src/styles/TicketingSettings.module.scss +10 -10
- package/src/styles/TimeDashboard.module.scss +6 -6
- package/src/styles/_tokens.scss +3 -1
- package/src/types.ts +20 -0
- package/src/utils/retention.ts +111 -0
- package/src/utils/slugs.ts +15 -0
- package/src/views/BillingView/client.tsx +17 -8
- package/src/views/ChatView/client.tsx +2 -0
- package/src/views/CrmView/client.tsx +2 -0
- package/src/views/EmailTrackingView/client.tsx +18 -7
- package/src/views/ImportConversationView/client.tsx +1 -0
- package/src/views/LogsView/client.tsx +1 -1
- package/src/views/NewTicketView/client.tsx +22 -13
- package/src/views/PendingEmailsView/client.tsx +9 -3
- package/src/views/SupportDashboardView/client.tsx +11 -5
- package/src/views/TicketDetailView/client.tsx +25 -11
- package/src/views/TicketInboxView/client.tsx +47 -7
- package/src/views/TicketingSettingsView/TicketingSettings.module.scss +7 -7
- package/src/views/TicketingSettingsView/client.tsx +201 -144
- package/src/views/TimeDashboardView/client.tsx +10 -7
- package/src/views/shared/ErrorBoundary.tsx +95 -31
- package/src/views/shared/adminTokens.ts +28 -11
- package/src/views/shared/icons.tsx +146 -0
- package/src/views/shared/locales/en.json +15 -1
- package/src/views/shared/locales/fr.json +15 -1
- package/src/types/lucide-react.d.ts +0 -42
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
function createIcon(displayName, nodes) {
|
|
5
|
+
const Icon = ({ size = 24, strokeWidth = 2, ...rest }) => /* @__PURE__ */ jsx(
|
|
6
|
+
"svg",
|
|
7
|
+
{
|
|
8
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
9
|
+
width: size,
|
|
10
|
+
height: size,
|
|
11
|
+
viewBox: "0 0 24 24",
|
|
12
|
+
fill: "none",
|
|
13
|
+
stroke: "currentColor",
|
|
14
|
+
strokeWidth,
|
|
15
|
+
strokeLinecap: "round",
|
|
16
|
+
strokeLinejoin: "round",
|
|
17
|
+
"aria-hidden": "true",
|
|
18
|
+
...rest,
|
|
19
|
+
children: nodes.map(([tag, attrs], index) => React.createElement(tag, { key: index, ...attrs }))
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
Icon.displayName = displayName;
|
|
23
|
+
return Icon;
|
|
24
|
+
}
|
|
25
|
+
const Bot = createIcon("Bot", [
|
|
26
|
+
["path", { d: "M12 8V4H8" }],
|
|
27
|
+
["rect", { width: "16", height: "12", x: "4", y: "8", rx: "2" }],
|
|
28
|
+
["path", { d: "M2 14h2" }],
|
|
29
|
+
["path", { d: "M20 14h2" }],
|
|
30
|
+
["path", { d: "M15 13v2" }],
|
|
31
|
+
["path", { d: "M9 13v2" }]
|
|
32
|
+
]);
|
|
33
|
+
const ChevronDown = createIcon("ChevronDown", [
|
|
34
|
+
["path", { d: "m6 9 6 6 6-6" }]
|
|
35
|
+
]);
|
|
36
|
+
const ChevronUp = createIcon("ChevronUp", [
|
|
37
|
+
["path", { d: "m18 15-6-6-6 6" }]
|
|
38
|
+
]);
|
|
39
|
+
const Clock = createIcon("Clock", [
|
|
40
|
+
["circle", { cx: "12", cy: "12", r: "10" }],
|
|
41
|
+
["path", { d: "M12 6v6l4 2" }]
|
|
42
|
+
]);
|
|
43
|
+
const FileSignature = createIcon("FileSignature", [
|
|
44
|
+
["path", { d: "M14.364 13.634a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506l4.013-4.009a1 1 0 0 0-3.004-3.004z" }],
|
|
45
|
+
["path", { d: "M14.487 7.858A1 1 0 0 1 14 7V2" }],
|
|
46
|
+
["path", { d: "M20 19.645V20a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l2.516 2.516" }],
|
|
47
|
+
["path", { d: "M8 18h1" }]
|
|
48
|
+
]);
|
|
49
|
+
const Globe = createIcon("Globe", [
|
|
50
|
+
["circle", { cx: "12", cy: "12", r: "10" }],
|
|
51
|
+
["path", { d: "M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20" }],
|
|
52
|
+
["path", { d: "M2 12h20" }]
|
|
53
|
+
]);
|
|
54
|
+
const Inbox = createIcon("Inbox", [
|
|
55
|
+
["polyline", { points: "22 12 16 12 14 15 10 15 8 12 2 12" }],
|
|
56
|
+
["path", { d: "M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" }]
|
|
57
|
+
]);
|
|
58
|
+
const Link2 = createIcon("Link2", [
|
|
59
|
+
["path", { d: "M9 17H7A5 5 0 0 1 7 7h2" }],
|
|
60
|
+
["path", { d: "M15 7h2a5 5 0 1 1 0 10h-2" }],
|
|
61
|
+
["line", { x1: "8", x2: "16", y1: "12", y2: "12" }]
|
|
62
|
+
]);
|
|
63
|
+
const Mail = createIcon("Mail", [
|
|
64
|
+
["path", { d: "m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7" }],
|
|
65
|
+
["rect", { x: "2", y: "4", width: "20", height: "16", rx: "2" }]
|
|
66
|
+
]);
|
|
67
|
+
const Paperclip = createIcon("Paperclip", [
|
|
68
|
+
["path", { d: "m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551" }]
|
|
69
|
+
]);
|
|
70
|
+
const Plus = createIcon("Plus", [
|
|
71
|
+
["path", { d: "M5 12h14" }],
|
|
72
|
+
["path", { d: "M12 5v14" }]
|
|
73
|
+
]);
|
|
74
|
+
const Search = createIcon("Search", [
|
|
75
|
+
["path", { d: "m21 21-4.34-4.34" }],
|
|
76
|
+
["circle", { cx: "11", cy: "11", r: "8" }]
|
|
77
|
+
]);
|
|
78
|
+
const Settings = createIcon("Settings", [
|
|
79
|
+
["path", { d: "M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" }],
|
|
80
|
+
["circle", { cx: "12", cy: "12", r: "3" }]
|
|
81
|
+
]);
|
|
82
|
+
const Timer = createIcon("Timer", [
|
|
83
|
+
["line", { x1: "10", x2: "14", y1: "2", y2: "2" }],
|
|
84
|
+
["line", { x1: "12", x2: "15", y1: "14", y2: "11" }],
|
|
85
|
+
["circle", { cx: "12", cy: "14", r: "8" }]
|
|
86
|
+
]);
|
|
87
|
+
const X = createIcon("X", [
|
|
88
|
+
["path", { d: "M18 6 6 18" }],
|
|
89
|
+
["path", { d: "m6 6 12 12" }]
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
export { Bot, ChevronDown, ChevronUp, Clock, FileSignature, Globe, Inbox, Link2, Mail, Paperclip, Plus, Search, Settings, Timer, X };
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
+
"errorBoundary": {
|
|
3
|
+
"title": "Something went wrong",
|
|
4
|
+
"description": "This section could not be displayed. The technical details were logged to the browser console.",
|
|
5
|
+
"retry": "Retry"
|
|
6
|
+
},
|
|
2
7
|
"common": {
|
|
3
8
|
"loading": "Loading...",
|
|
4
9
|
"cancel": "Cancel",
|
|
@@ -144,6 +149,7 @@
|
|
|
144
149
|
"title": "CRM Clients",
|
|
145
150
|
"subtitle": "Client management and history",
|
|
146
151
|
"searchPlaceholder": "Search a client...",
|
|
152
|
+
"searchLabel": "Search a client",
|
|
147
153
|
"noClientFound": "No client found",
|
|
148
154
|
"selectClient": "Select a client to see their details",
|
|
149
155
|
"editButton": "Edit",
|
|
@@ -316,6 +322,8 @@
|
|
|
316
322
|
"resolved": "Resolved",
|
|
317
323
|
"slaBreach": "SLA breached"
|
|
318
324
|
},
|
|
325
|
+
"searchLabel": "Search a ticket",
|
|
326
|
+
"sortLabel": "Sort the tickets",
|
|
319
327
|
"sort": {
|
|
320
328
|
"newest": "Most recent",
|
|
321
329
|
"oldest": "Oldest first",
|
|
@@ -324,6 +332,7 @@
|
|
|
324
332
|
},
|
|
325
333
|
"selected": "{{count}} selected",
|
|
326
334
|
"selectedPlural": "{{count}} selected",
|
|
335
|
+
"tabsLabel": "Inbox filters",
|
|
327
336
|
"closeAction": "Close",
|
|
328
337
|
"reopenAction": "Reopen",
|
|
329
338
|
"moreActions": "More actions...",
|
|
@@ -344,6 +353,7 @@
|
|
|
344
353
|
"emailTracking": {
|
|
345
354
|
"title": "Email tracking",
|
|
346
355
|
"searchPlaceholder": "Search by recipient or subject...",
|
|
356
|
+
"searchLabel": "Search an email",
|
|
347
357
|
"noLogs": "No logs found for this period",
|
|
348
358
|
"tabs": {
|
|
349
359
|
"all": "All",
|
|
@@ -366,7 +376,8 @@
|
|
|
366
376
|
"action": "Action",
|
|
367
377
|
"time": "Time"
|
|
368
378
|
},
|
|
369
|
-
"errorLabel": "Error"
|
|
379
|
+
"errorLabel": "Error",
|
|
380
|
+
"toggleError": "Show the error detail"
|
|
370
381
|
},
|
|
371
382
|
"logs": {
|
|
372
383
|
"title": "Email Logs",
|
|
@@ -530,8 +541,11 @@
|
|
|
530
541
|
"messageDeletedToast": "Message deleted",
|
|
531
542
|
"split": {
|
|
532
543
|
"subjectPlaceholder": "New ticket subject...",
|
|
544
|
+
"subjectLabel": "Subject of the new ticket",
|
|
533
545
|
"createBtn": "Create ticket"
|
|
534
546
|
},
|
|
547
|
+
"sendAs": "Send as",
|
|
548
|
+
"manualMinutes": "Minutes to add",
|
|
535
549
|
"editMessage": "Edit",
|
|
536
550
|
"editMessageLabel": "Edit message",
|
|
537
551
|
"uploadItem": "Attachment {{name}}",
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
+
"errorBoundary": {
|
|
3
|
+
"title": "Une erreur est survenue",
|
|
4
|
+
"description": "Cette section n'a pas pu s'afficher. Le detail technique est consigne dans la console du navigateur.",
|
|
5
|
+
"retry": "Reessayer"
|
|
6
|
+
},
|
|
2
7
|
"common": {
|
|
3
8
|
"loading": "Chargement...",
|
|
4
9
|
"cancel": "Annuler",
|
|
@@ -144,6 +149,7 @@
|
|
|
144
149
|
"title": "CRM Clients",
|
|
145
150
|
"subtitle": "Gestion des clients et historique",
|
|
146
151
|
"searchPlaceholder": "Rechercher un client...",
|
|
152
|
+
"searchLabel": "Rechercher un client",
|
|
147
153
|
"noClientFound": "Aucun client trouvé",
|
|
148
154
|
"selectClient": "Sélectionnez un client pour voir ses détails",
|
|
149
155
|
"editButton": "Modifier",
|
|
@@ -316,6 +322,8 @@
|
|
|
316
322
|
"resolved": "Résolus",
|
|
317
323
|
"slaBreach": "SLA dépassé"
|
|
318
324
|
},
|
|
325
|
+
"searchLabel": "Rechercher un ticket",
|
|
326
|
+
"sortLabel": "Trier les tickets",
|
|
319
327
|
"sort": {
|
|
320
328
|
"newest": "Plus récent",
|
|
321
329
|
"oldest": "Plus ancien",
|
|
@@ -324,6 +332,7 @@
|
|
|
324
332
|
},
|
|
325
333
|
"selected": "{{count}} sélectionné",
|
|
326
334
|
"selectedPlural": "{{count}} sélectionnés",
|
|
335
|
+
"tabsLabel": "Filtres de la boite de reception",
|
|
327
336
|
"closeAction": "Fermer",
|
|
328
337
|
"reopenAction": "Rouvrir",
|
|
329
338
|
"moreActions": "Plus d'actions...",
|
|
@@ -344,6 +353,7 @@
|
|
|
344
353
|
"emailTracking": {
|
|
345
354
|
"title": "Suivi des emails",
|
|
346
355
|
"searchPlaceholder": "Rechercher par destinataire ou sujet...",
|
|
356
|
+
"searchLabel": "Rechercher un email",
|
|
347
357
|
"noLogs": "Aucun log trouvé pour cette période",
|
|
348
358
|
"tabs": {
|
|
349
359
|
"all": "Tous",
|
|
@@ -366,7 +376,8 @@
|
|
|
366
376
|
"action": "Action",
|
|
367
377
|
"time": "Temps"
|
|
368
378
|
},
|
|
369
|
-
"errorLabel": "Erreur"
|
|
379
|
+
"errorLabel": "Erreur",
|
|
380
|
+
"toggleError": "Afficher le detail de l'erreur"
|
|
370
381
|
},
|
|
371
382
|
"logs": {
|
|
372
383
|
"title": "Logs Email",
|
|
@@ -530,8 +541,11 @@
|
|
|
530
541
|
"messageDeletedToast": "Message supprimé",
|
|
531
542
|
"split": {
|
|
532
543
|
"subjectPlaceholder": "Sujet du nouveau ticket...",
|
|
544
|
+
"subjectLabel": "Sujet du nouveau ticket",
|
|
533
545
|
"createBtn": "Créer le ticket"
|
|
534
546
|
},
|
|
547
|
+
"sendAs": "Envoyer en tant que",
|
|
548
|
+
"manualMinutes": "Minutes a ajouter",
|
|
535
549
|
"editMessage": "Éditer",
|
|
536
550
|
"editMessageLabel": "Éditer le message",
|
|
537
551
|
"uploadItem": "PJ {{name}}",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@consilioweb/payload-support",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.1",
|
|
4
4
|
"description": "Payload CMS plugin — professional support & ticketing system with AI, SLA, time tracking, live chat, and more",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -40,14 +40,20 @@
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
|
+
"bin": {
|
|
44
|
+
"support-uninstall": "./scripts/uninstall.mjs"
|
|
45
|
+
},
|
|
43
46
|
"files": [
|
|
44
47
|
"dist",
|
|
45
48
|
"src",
|
|
46
49
|
"!src/__tests__",
|
|
47
50
|
"!src/**/*.test.ts",
|
|
48
51
|
"!src/**/*.test.tsx",
|
|
52
|
+
"scripts/uninstall.mjs",
|
|
53
|
+
"scripts/uninstall-data.mjs",
|
|
49
54
|
"README.md",
|
|
50
|
-
"LICENSE"
|
|
55
|
+
"LICENSE",
|
|
56
|
+
"scripts"
|
|
51
57
|
],
|
|
52
58
|
"keywords": [
|
|
53
59
|
"payload",
|
|
@@ -86,7 +92,6 @@
|
|
|
86
92
|
"license": "MIT",
|
|
87
93
|
"peerDependencies": {
|
|
88
94
|
"@payloadcms/next": "^3.79.1",
|
|
89
|
-
"lucide-react": ">=0.300.0",
|
|
90
95
|
"next": "^15.2.9 || ^16.0.0",
|
|
91
96
|
"payload": "^3.79.1",
|
|
92
97
|
"react": "^19.0.0",
|
|
@@ -133,7 +138,7 @@
|
|
|
133
138
|
}
|
|
134
139
|
},
|
|
135
140
|
"scripts": {
|
|
136
|
-
"build": "tsup && tsc -p tsconfig.types.json && node scripts/copy-subpath-types.mjs",
|
|
141
|
+
"build": "tsup && tsc -p tsconfig.types.json && node scripts/copy-subpath-types.mjs && node scripts/verify-dist-imports.mjs",
|
|
137
142
|
"typecheck": "tsc --noEmit",
|
|
138
143
|
"test": "vitest run",
|
|
139
144
|
"test:watch": "vitest",
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copies the declarations emitted by `tsc -p tsconfig.types.json` into dist/,
|
|
3
|
+
* then rewrites their relative import specifiers so they carry an explicit
|
|
4
|
+
* `.js` extension.
|
|
5
|
+
*
|
|
6
|
+
* Why a separate pass: the `bundle: false` tsup entry that emits dist/views/**
|
|
7
|
+
* and dist/components/** cannot generate declarations — turning `dts: true` on
|
|
8
|
+
* for ~100 entries makes rollup-plugin-dts run for well over ten minutes without
|
|
9
|
+
* finishing. Without them, `dist/views.d.ts` re-exports 13 views from paths that
|
|
10
|
+
* carry no declaration (TS7016 under noImplicitAny) and the publicly documented
|
|
11
|
+
* `./components/TicketConversation` subpath has no types at all.
|
|
12
|
+
*
|
|
13
|
+
* Why the extension rewrite: the sources are compiled with
|
|
14
|
+
* `moduleResolution: bundler`, so both tsc and tsup emit extensionless relative
|
|
15
|
+
* specifiers (`from './client'`, `from '../../utils/features'`). A consumer on
|
|
16
|
+
* `moduleResolution: node16 | nodenext` — the recommended setting for an ESM
|
|
17
|
+
* package — then gets `TS2835: Relative import paths need explicit file
|
|
18
|
+
* extensions`, and with the default `skipLibCheck: true` that error is swallowed
|
|
19
|
+
* and every export silently degrades to `any`. tsup's `onSuccess` already does
|
|
20
|
+
* this for the emitted `.js`; this does the same for the `.d.ts` (the copied ones
|
|
21
|
+
* *and* the `dist/views.d.ts` barrel produced by tsup's dts pass).
|
|
22
|
+
*
|
|
23
|
+
* `utils` is copied too: the emitted view declarations reference
|
|
24
|
+
* `../../utils/features`, whose JS is already emitted by the same tsup pass.
|
|
25
|
+
*/
|
|
26
|
+
import { cpSync, existsSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs'
|
|
27
|
+
import { dirname, join, resolve } from 'node:path'
|
|
28
|
+
|
|
29
|
+
const OUT = '.types-out'
|
|
30
|
+
const SUBPATHS = ['views', 'components', 'utils']
|
|
31
|
+
|
|
32
|
+
if (!existsSync(OUT)) {
|
|
33
|
+
console.error(`[build] "${OUT}" is missing — run \`tsc -p tsconfig.types.json\` before this script.`)
|
|
34
|
+
process.exit(1)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
for (const dir of SUBPATHS) {
|
|
38
|
+
const from = `${OUT}/${dir}`
|
|
39
|
+
if (existsSync(from)) cpSync(from, `dist/${dir}`, { recursive: true })
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
rmSync(OUT, { recursive: true, force: true })
|
|
43
|
+
console.log('✓ Copied subpath declarations into dist/')
|
|
44
|
+
|
|
45
|
+
// ─── Explicit .js extensions on relative specifiers ──────────────────────────
|
|
46
|
+
|
|
47
|
+
const HAS_EXTENSION = /\.(js|jsx|mjs|cjs|css|scss|json)$/
|
|
48
|
+
const RELATIVE_SPECIFIER = /((?:from|import)\s*['"])(\.\.?\/[^'"]+?)(['"])/g
|
|
49
|
+
|
|
50
|
+
const errors = []
|
|
51
|
+
|
|
52
|
+
/** Resolve an extensionless specifier against the emitted declarations. */
|
|
53
|
+
function withExtension(fromFile, specifier) {
|
|
54
|
+
const base = resolve(dirname(fromFile), specifier)
|
|
55
|
+
if (existsSync(`${base}.d.ts`)) return `${specifier}.js`
|
|
56
|
+
if (existsSync(join(base, 'index.d.ts'))) return `${specifier}/index.js`
|
|
57
|
+
return null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function rewrite(file) {
|
|
61
|
+
const content = readFileSync(file, 'utf-8')
|
|
62
|
+
const fixed = content.replace(RELATIVE_SPECIFIER, (match, prefix, specifier, suffix) => {
|
|
63
|
+
if (HAS_EXTENSION.test(specifier)) return match
|
|
64
|
+
const resolved = withExtension(file, specifier)
|
|
65
|
+
if (!resolved) {
|
|
66
|
+
errors.push(`${file}: cannot resolve "${specifier}" to an emitted declaration`)
|
|
67
|
+
return match
|
|
68
|
+
}
|
|
69
|
+
return `${prefix}${resolved}${suffix}`
|
|
70
|
+
})
|
|
71
|
+
if (fixed !== content) writeFileSync(file, fixed)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function walkDts(dir) {
|
|
75
|
+
if (!existsSync(dir)) return
|
|
76
|
+
for (const entry of readdirSync(dir)) {
|
|
77
|
+
const path = join(dir, entry)
|
|
78
|
+
if (statSync(path).isDirectory()) {
|
|
79
|
+
walkDts(path)
|
|
80
|
+
continue
|
|
81
|
+
}
|
|
82
|
+
if (path.endsWith('.d.ts')) rewrite(path)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// The `./views` barrel is emitted by tsup's dts pass, not by the tsc pass above,
|
|
87
|
+
// but it has the exact same extensionless specifiers — and it is the entry point
|
|
88
|
+
// consumers actually import, so it matters most.
|
|
89
|
+
const VIEWS_BARREL = 'dist/views.d.ts'
|
|
90
|
+
if (!existsSync(VIEWS_BARREL)) {
|
|
91
|
+
console.error(`[build] "${VIEWS_BARREL}" is missing — did the tsup views barrel entry run?`)
|
|
92
|
+
process.exit(1)
|
|
93
|
+
}
|
|
94
|
+
rewrite(VIEWS_BARREL)
|
|
95
|
+
for (const dir of SUBPATHS) walkDts(`dist/${dir}`)
|
|
96
|
+
|
|
97
|
+
if (errors.length > 0) {
|
|
98
|
+
console.error('[build] unresolved relative specifiers in emitted declarations:')
|
|
99
|
+
for (const error of errors) console.error(` - ${error}`)
|
|
100
|
+
process.exit(1)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
console.log('✓ Added explicit .js extensions to relative specifiers in dist/**/*.d.ts')
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Data half of `support-uninstall`. It is NOT meant to be run directly: it is
|
|
5
|
+
* spawned by `scripts/uninstall.mjs` through `payload run`, which is what puts
|
|
6
|
+
* the TypeScript loader and the environment in place so the host's
|
|
7
|
+
* `payload.config.ts` can be imported.
|
|
8
|
+
*
|
|
9
|
+
* Everything here goes through the Payload local API rather than a `sqlite3`
|
|
10
|
+
* binary. The plugin accepts custom collection slugs and runs on SQLite,
|
|
11
|
+
* PostgreSQL and MongoDB; raw SQL against hardcoded table names would only
|
|
12
|
+
* work on one of the three, and silently do nothing on the other two.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { getPayload } from 'payload'
|
|
16
|
+
import { findConfig } from 'payload/node'
|
|
17
|
+
import { pathToFileURL } from 'node:url'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Deletion order matters: a child row whose `ticket` / `client` relationship is
|
|
21
|
+
* `required` blocks the delete of its parent (NOT NULL on the foreign key).
|
|
22
|
+
*
|
|
23
|
+
* These are the DEFAULT slugs. They are duplicated from `src/utils/slugs.ts`
|
|
24
|
+
* on purpose — importing `dist/index.js` here would pull pdfkit, web-push and
|
|
25
|
+
* sanitize-html into a script that only deletes rows. `src/__tests__/
|
|
26
|
+
* uninstallScript.test.ts` fails if the two lists ever drift apart.
|
|
27
|
+
*/
|
|
28
|
+
const ORDERED_SLUGS = [
|
|
29
|
+
// 1. Rows pointing at a ticket.
|
|
30
|
+
'ticket-collaborators',
|
|
31
|
+
'ticket-feedback',
|
|
32
|
+
'satisfaction-surveys',
|
|
33
|
+
'ticket-activity-log',
|
|
34
|
+
'ticket-messages',
|
|
35
|
+
'time-entries',
|
|
36
|
+
// 2. The tickets themselves.
|
|
37
|
+
'tickets',
|
|
38
|
+
// 3. Rows pointing at a client, or at nothing.
|
|
39
|
+
'chat-messages',
|
|
40
|
+
'pending-emails',
|
|
41
|
+
'client-summaries',
|
|
42
|
+
'notification-queue',
|
|
43
|
+
'push-subscriptions',
|
|
44
|
+
'canned-responses',
|
|
45
|
+
'knowledge-base',
|
|
46
|
+
'macros',
|
|
47
|
+
'automation-rules',
|
|
48
|
+
'ticket-statuses',
|
|
49
|
+
'webhook-endpoints',
|
|
50
|
+
'sla-policies',
|
|
51
|
+
'support-teams',
|
|
52
|
+
'auth-logs',
|
|
53
|
+
'email-logs',
|
|
54
|
+
'support-counters',
|
|
55
|
+
'support-rate-limits',
|
|
56
|
+
// 4. The portal accounts.
|
|
57
|
+
'support-clients',
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
/** `payload-preferences` keys the plugin writes. */
|
|
61
|
+
const PREFERENCE_KEYS = {
|
|
62
|
+
exact: ['support-settings', 'support-round-robin'],
|
|
63
|
+
prefix: ['support-user-prefs'],
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function parseArgs(argv) {
|
|
67
|
+
const confirm = argv.includes('--confirm')
|
|
68
|
+
const keepData = argv.includes('--keep-data')
|
|
69
|
+
const extra = argv.find((a) => a.startsWith('--extra-slugs='))
|
|
70
|
+
return {
|
|
71
|
+
confirm,
|
|
72
|
+
keepData,
|
|
73
|
+
extraSlugs: extra ? extra.slice('--extra-slugs='.length).split(',').map((s) => s.trim()).filter(Boolean) : [],
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function main() {
|
|
78
|
+
const { confirm, keepData, extraSlugs } = parseArgs(process.argv.slice(2))
|
|
79
|
+
|
|
80
|
+
const configPath = findConfig()
|
|
81
|
+
const imported = await import(pathToFileURL(configPath).toString())
|
|
82
|
+
const config = await (imported.default ?? imported)
|
|
83
|
+
const payload = await getPayload({ config })
|
|
84
|
+
|
|
85
|
+
const candidates = [...ORDERED_SLUGS, ...extraSlugs]
|
|
86
|
+
const present = candidates.filter((slug) => Boolean(payload.collections?.[slug]))
|
|
87
|
+
const absent = candidates.filter((slug) => !payload.collections?.[slug])
|
|
88
|
+
|
|
89
|
+
console.log('')
|
|
90
|
+
console.log(` Config: ${configPath}`)
|
|
91
|
+
console.log(` Mode: ${confirm ? 'DELETE' : 'DRY RUN (nothing is written)'}`)
|
|
92
|
+
console.log('')
|
|
93
|
+
|
|
94
|
+
if (!keepData) {
|
|
95
|
+
console.log(' Collections found in this app:')
|
|
96
|
+
for (const slug of present) {
|
|
97
|
+
const { totalDocs } = await payload.count({ collection: slug, overrideAccess: true })
|
|
98
|
+
console.log(` ${String(totalDocs).padStart(7)} ${slug}`)
|
|
99
|
+
}
|
|
100
|
+
if (present.length === 0) {
|
|
101
|
+
console.log(' (none — nothing of this plugin is registered in this config)')
|
|
102
|
+
}
|
|
103
|
+
if (absent.length > 0) {
|
|
104
|
+
console.log('')
|
|
105
|
+
console.log(` Not registered here, skipped: ${absent.join(', ')}`)
|
|
106
|
+
console.log(' If you renamed any of them through `collectionSlugs`, re-run with')
|
|
107
|
+
console.log(' --extra-slugs=your-slug,another-slug — this script cannot guess them.')
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
console.log(' --keep-data: no collection row will be deleted.')
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
console.log('')
|
|
114
|
+
console.log(' payload-preferences keys:')
|
|
115
|
+
for (const key of PREFERENCE_KEYS.exact) console.log(` ${key}`)
|
|
116
|
+
for (const key of PREFERENCE_KEYS.prefix) console.log(` ${key}* (one row per agent)`)
|
|
117
|
+
|
|
118
|
+
if (!confirm) {
|
|
119
|
+
console.log('')
|
|
120
|
+
console.log(' Nothing was deleted. Re-run with --confirm to apply.')
|
|
121
|
+
console.log('')
|
|
122
|
+
process.exit(0)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (!keepData) {
|
|
126
|
+
console.log('')
|
|
127
|
+
for (const slug of present) {
|
|
128
|
+
const result = await payload.delete({
|
|
129
|
+
collection: slug,
|
|
130
|
+
where: { id: { exists: true } },
|
|
131
|
+
overrideAccess: true,
|
|
132
|
+
})
|
|
133
|
+
const deleted = Array.isArray(result?.docs) ? result.docs.length : 0
|
|
134
|
+
const failed = Array.isArray(result?.errors) ? result.errors.length : 0
|
|
135
|
+
console.log(` deleted ${String(deleted).padStart(7)} ${slug}${failed ? ` (${failed} failed)` : ''}`)
|
|
136
|
+
if (failed) {
|
|
137
|
+
console.log(` ${JSON.stringify(result.errors.slice(0, 3))}`)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
console.log('')
|
|
143
|
+
for (const key of PREFERENCE_KEYS.exact) {
|
|
144
|
+
const result = await payload.delete({
|
|
145
|
+
collection: 'payload-preferences',
|
|
146
|
+
where: { key: { equals: key } },
|
|
147
|
+
overrideAccess: true,
|
|
148
|
+
})
|
|
149
|
+
console.log(` deleted ${String(result?.docs?.length ?? 0).padStart(7)} payload-preferences/${key}`)
|
|
150
|
+
}
|
|
151
|
+
for (const key of PREFERENCE_KEYS.prefix) {
|
|
152
|
+
const result = await payload.delete({
|
|
153
|
+
collection: 'payload-preferences',
|
|
154
|
+
where: { key: { like: key } },
|
|
155
|
+
overrideAccess: true,
|
|
156
|
+
})
|
|
157
|
+
console.log(` deleted ${String(result?.docs?.length ?? 0).padStart(7)} payload-preferences/${key}*`)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
console.log('')
|
|
161
|
+
console.log(' Left untouched, on purpose:')
|
|
162
|
+
console.log(' - your `media` collection. Attachments uploaded through the support')
|
|
163
|
+
console.log(' desk are ordinary uploads once their messages are gone, and this')
|
|
164
|
+
console.log(' script has no way to tell them apart from the rest of your media.')
|
|
165
|
+
console.log(' Review them yourself before deleting anything there.')
|
|
166
|
+
console.log(' - the tables. Rows are gone; run `payload migrate:create` and apply')
|
|
167
|
+
console.log(' the migration to drop the now-unused tables.')
|
|
168
|
+
console.log('')
|
|
169
|
+
|
|
170
|
+
process.exit(0)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
main().catch((err) => {
|
|
174
|
+
console.error('')
|
|
175
|
+
console.error(' Uninstall failed:', err)
|
|
176
|
+
console.error('')
|
|
177
|
+
process.exit(1)
|
|
178
|
+
})
|