@djangocfg/ext-support 1.0.6 → 1.0.8

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.
Files changed (39) hide show
  1. package/dist/config.cjs +4 -1
  2. package/dist/config.js +4 -1
  3. package/dist/hooks.cjs +79 -89
  4. package/dist/hooks.js +78 -89
  5. package/dist/index.cjs +79 -89
  6. package/dist/index.d.cts +0 -97
  7. package/dist/index.d.ts +0 -97
  8. package/dist/index.js +78 -89
  9. package/package.json +10 -7
  10. package/src/api/generated/ext_support/CLAUDE.md +80 -0
  11. package/src/api/generated/ext_support/_utils/fetchers/ext_support__support.ts +1 -8
  12. package/src/api/generated/ext_support/_utils/fetchers/index.ts +1 -8
  13. package/src/api/generated/ext_support/_utils/hooks/ext_support__support.ts +1 -8
  14. package/src/api/generated/ext_support/_utils/hooks/index.ts +1 -8
  15. package/src/api/generated/ext_support/_utils/schemas/index.ts +1 -8
  16. package/src/api/generated/ext_support/api-instance.ts +1 -8
  17. package/src/api/generated/ext_support/enums.ts +1 -8
  18. package/src/api/generated/ext_support/errors.ts +1 -8
  19. package/src/api/generated/ext_support/ext_support__support/index.ts +1 -8
  20. package/src/api/generated/ext_support/ext_support__support/models.ts +1 -8
  21. package/src/api/generated/ext_support/http.ts +1 -8
  22. package/src/api/generated/ext_support/index.ts +1 -8
  23. package/src/api/generated/ext_support/logger.ts +1 -8
  24. package/src/api/generated/ext_support/retry.ts +1 -8
  25. package/src/api/generated/ext_support/storage.ts +1 -8
  26. package/src/api/generated/ext_support/validation-events.ts +1 -8
  27. package/src/api/index.ts +2 -1
  28. package/src/config.ts +1 -0
  29. package/src/contexts/SupportContext.tsx +9 -13
  30. package/src/contexts/SupportExtensionProvider.tsx +1 -0
  31. package/src/layouts/SupportLayout/SupportLayout.tsx +5 -13
  32. package/src/layouts/SupportLayout/components/CreateTicketDialog.tsx +8 -18
  33. package/src/layouts/SupportLayout/components/MessageInput.tsx +5 -10
  34. package/src/layouts/SupportLayout/components/MessageList.tsx +25 -22
  35. package/src/layouts/SupportLayout/components/TicketCard.tsx +10 -10
  36. package/src/layouts/SupportLayout/components/TicketList.tsx +6 -4
  37. package/src/layouts/SupportLayout/context/SupportLayoutContext.tsx +9 -2
  38. package/src/layouts/SupportLayout/hooks/useInfiniteMessages.ts +2 -0
  39. package/src/layouts/SupportLayout/hooks/useInfiniteTickets.ts +2 -0
package/dist/index.js CHANGED
@@ -2,13 +2,15 @@ import { createConsola, consola } from 'consola';
2
2
  import pRetry, { AbortError } from 'p-retry';
3
3
  import { z } from 'zod';
4
4
  import { createExtensionAPI } from '@djangocfg/ext-base/api';
5
+ import { ArrowLeft, LifeBuoy, Plus, MessageSquare, Loader2, Send, Headphones, User, Clock } from 'lucide-react';
5
6
  import React7, { createContext, useState, useCallback, useEffect, useContext, useRef } from 'react';
7
+ import { Button, ResizablePanelGroup, ResizablePanel, ResizableHandle, Skeleton, ScrollArea, useToast, Textarea, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Form, FormField, FormItem, FormLabel, FormControl, Input, FormMessage, Avatar, AvatarImage, AvatarFallback, Card, CardContent, Badge } from '@djangocfg/ui-nextjs';
6
8
  import useSWR, { useSWRConfig } from 'swr';
7
9
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
+ import moment2 from 'moment';
11
+ import { cn } from '@djangocfg/ui-core/lib';
8
12
  import { useAuth } from '@djangocfg/api/auth';
9
13
  import useSWRInfinite from 'swr/infinite';
10
- import { Button, ResizablePanelGroup, ResizablePanel, ResizableHandle, Skeleton, ScrollArea, useToast, Textarea, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Form, FormField, FormItem, FormLabel, FormControl, Input, FormMessage, Avatar, AvatarImage, AvatarFallback, Card, CardContent, cn, Badge } from '@djangocfg/ui-nextjs';
11
- import { ArrowLeft, LifeBuoy, Plus, MessageSquare, Loader2, Send, Headphones, User, Clock } from 'lucide-react';
12
14
  import { useForm } from 'react-hook-form';
13
15
  import { zodResolver } from '@hookform/resolvers/zod';
14
16
  import { createExtensionConfig } from '@djangocfg/ext-base';
@@ -1775,6 +1777,67 @@ function useSupportContext() {
1775
1777
  }
1776
1778
  return context;
1777
1779
  }
1780
+ var getStatusBadgeVariant = (status) => {
1781
+ switch (status) {
1782
+ case "open":
1783
+ return "default";
1784
+ case "waiting_for_user":
1785
+ return "secondary";
1786
+ case "waiting_for_admin":
1787
+ return "outline";
1788
+ case "resolved":
1789
+ return "outline";
1790
+ case "closed":
1791
+ return "secondary";
1792
+ default:
1793
+ return "default";
1794
+ }
1795
+ };
1796
+ var formatRelativeTime = (date) => {
1797
+ if (!date) return "N/A";
1798
+ const m = moment2.utc(date).local();
1799
+ const now = moment2();
1800
+ const diffInSeconds = now.diff(m, "seconds");
1801
+ if (diffInSeconds < 60) return "Just now";
1802
+ if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
1803
+ if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
1804
+ if (diffInSeconds < 604800) return `${Math.floor(diffInSeconds / 86400)}d ago`;
1805
+ return m.format("MMM D, YYYY");
1806
+ };
1807
+ var TicketCard = ({ ticket, isSelected, onClick }) => {
1808
+ return /* @__PURE__ */ jsx(
1809
+ Card,
1810
+ {
1811
+ className: cn(
1812
+ "cursor-pointer transition-all duration-200 ease-out",
1813
+ "hover:bg-accent/50 hover:shadow-md hover:scale-[1.02]",
1814
+ "active:scale-[0.98]",
1815
+ isSelected && "bg-accent border-primary shadow-sm"
1816
+ ),
1817
+ onClick,
1818
+ children: /* @__PURE__ */ jsxs(CardContent, { className: "p-4", children: [
1819
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-2", children: [
1820
+ /* @__PURE__ */ jsx("h3", { className: "font-semibold text-sm line-clamp-2 flex-1", children: ticket.subject }),
1821
+ (ticket.unanswered_messages_count || 0) > 0 && /* @__PURE__ */ jsx(
1822
+ Badge,
1823
+ {
1824
+ variant: "destructive",
1825
+ className: "ml-2 shrink-0 animate-pulse",
1826
+ children: ticket.unanswered_messages_count
1827
+ }
1828
+ )
1829
+ ] }),
1830
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1831
+ /* @__PURE__ */ jsx(Badge, { variant: getStatusBadgeVariant(ticket.status || "open"), className: "text-xs", children: ticket.status || "open" }),
1832
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
1833
+ /* @__PURE__ */ jsx(Clock, { className: "h-3 w-3" }),
1834
+ /* @__PURE__ */ jsx("span", { children: formatRelativeTime(ticket.created_at) })
1835
+ ] })
1836
+ ] }) })
1837
+ ] })
1838
+ }
1839
+ );
1840
+ };
1778
1841
 
1779
1842
  // src/layouts/SupportLayout/events.ts
1780
1843
  var SUPPORT_LAYOUT_EVENTS = {
@@ -2039,71 +2102,6 @@ function useSupportLayoutContext() {
2039
2102
  }
2040
2103
  return context;
2041
2104
  }
2042
- var getStatusBadgeVariant = (status) => {
2043
- switch (status) {
2044
- case "open":
2045
- return "default";
2046
- case "waiting_for_user":
2047
- return "secondary";
2048
- case "waiting_for_admin":
2049
- return "outline";
2050
- case "resolved":
2051
- return "outline";
2052
- case "closed":
2053
- return "secondary";
2054
- default:
2055
- return "default";
2056
- }
2057
- };
2058
- var formatRelativeTime = (date) => {
2059
- if (!date) return "N/A";
2060
- const now = /* @__PURE__ */ new Date();
2061
- const messageDate = new Date(date);
2062
- const diffInSeconds = Math.floor((now.getTime() - messageDate.getTime()) / 1e3);
2063
- if (diffInSeconds < 60) return "Just now";
2064
- if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
2065
- if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
2066
- if (diffInSeconds < 604800) return `${Math.floor(diffInSeconds / 86400)}d ago`;
2067
- return new Date(date).toLocaleDateString("en-US", {
2068
- year: "numeric",
2069
- month: "short",
2070
- day: "numeric"
2071
- });
2072
- };
2073
- var TicketCard = ({ ticket, isSelected, onClick }) => {
2074
- return /* @__PURE__ */ jsx(
2075
- Card,
2076
- {
2077
- className: cn(
2078
- "cursor-pointer transition-all duration-200 ease-out",
2079
- "hover:bg-accent/50 hover:shadow-md hover:scale-[1.02]",
2080
- "active:scale-[0.98]",
2081
- isSelected && "bg-accent border-primary shadow-sm"
2082
- ),
2083
- onClick,
2084
- children: /* @__PURE__ */ jsxs(CardContent, { className: "p-4", children: [
2085
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-2", children: [
2086
- /* @__PURE__ */ jsx("h3", { className: "font-semibold text-sm line-clamp-2 flex-1", children: ticket.subject }),
2087
- (ticket.unanswered_messages_count || 0) > 0 && /* @__PURE__ */ jsx(
2088
- Badge,
2089
- {
2090
- variant: "destructive",
2091
- className: "ml-2 shrink-0 animate-pulse",
2092
- children: ticket.unanswered_messages_count
2093
- }
2094
- )
2095
- ] }),
2096
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
2097
- /* @__PURE__ */ jsx(Badge, { variant: getStatusBadgeVariant(ticket.status || "open"), className: "text-xs", children: ticket.status || "open" }),
2098
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
2099
- /* @__PURE__ */ jsx(Clock, { className: "h-3 w-3" }),
2100
- /* @__PURE__ */ jsx("span", { children: formatRelativeTime(ticket.created_at) })
2101
- ] })
2102
- ] }) })
2103
- ] })
2104
- }
2105
- );
2106
- };
2107
2105
  var TicketList = () => {
2108
2106
  const { selectedTicket, selectTicket } = useSupportLayoutContext();
2109
2107
  const {
@@ -2209,28 +2207,23 @@ var TicketList = () => {
2209
2207
  };
2210
2208
  var formatTime = (date) => {
2211
2209
  if (!date) return "";
2212
- return new Date(date).toLocaleTimeString("en-US", {
2213
- hour: "2-digit",
2214
- minute: "2-digit"
2215
- });
2210
+ return moment2.utc(date).local().format("hh:mm A");
2216
2211
  };
2217
2212
  var formatDate = (date) => {
2218
2213
  if (!date) return "";
2219
- return new Date(date).toLocaleDateString("en-US", {
2220
- year: "numeric",
2221
- month: "short",
2222
- day: "numeric"
2223
- });
2214
+ return moment2.utc(date).local().format("MMM D, YYYY");
2224
2215
  };
2225
2216
  var MessageBubble = ({ message, isFromUser, currentUser }) => {
2226
2217
  const sender = message.sender;
2218
+ const senderInitial = sender?.display_username?.charAt(0)?.toUpperCase() || sender?.initials || "S";
2219
+ const userInitial = currentUser?.display_username?.charAt(0)?.toUpperCase() || currentUser?.email?.charAt(0)?.toUpperCase() || currentUser?.initials || null;
2227
2220
  return /* @__PURE__ */ jsxs(
2228
2221
  "div",
2229
2222
  {
2230
2223
  className: `flex gap-3 ${isFromUser ? "justify-end" : "justify-start"}
2231
2224
  animate-in fade-in slide-in-from-bottom-2 duration-300`,
2232
2225
  children: [
2233
- !isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: sender?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: sender.avatar, alt: sender.display_username || "Support" }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary text-primary-foreground", children: sender?.is_staff ? /* @__PURE__ */ jsx(Headphones, { className: "h-4 w-4" }) : sender?.display_username?.charAt(0)?.toUpperCase() || sender?.initials || "S" }) }),
2226
+ !isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: sender?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: sender.avatar, alt: sender.display_username || "Support" }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary text-primary-foreground", children: sender?.is_staff ? /* @__PURE__ */ jsx(Headphones, { className: "h-4 w-4" }) : senderInitial }) }),
2234
2227
  /* @__PURE__ */ jsxs("div", { className: `flex flex-col gap-1 flex-1 max-w-[80%] ${isFromUser ? "items-end" : "items-start"}`, children: [
2235
2228
  !isFromUser && sender && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground px-1", children: [
2236
2229
  sender.display_username || sender.email || "Support Team",
@@ -2245,7 +2238,7 @@ var MessageBubble = ({ message, isFromUser, currentUser }) => {
2245
2238
  ),
2246
2239
  /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground px-1", children: formatTime(message.created_at) })
2247
2240
  ] }),
2248
- isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: currentUser?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: currentUser.avatar, alt: currentUser.display_username || currentUser.email || "You" }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary/10 text-primary font-semibold", children: currentUser?.display_username?.charAt(0)?.toUpperCase() || currentUser?.email?.charAt(0)?.toUpperCase() || currentUser?.initials || /* @__PURE__ */ jsx(User, { className: "h-4 w-4" }) }) })
2241
+ isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: currentUser?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: currentUser.avatar, alt: currentUser.display_username || currentUser.email || "You" }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary/10 text-primary font-semibold", children: userInitial || /* @__PURE__ */ jsx(User, { className: "h-4 w-4" }) }) })
2249
2242
  ]
2250
2243
  }
2251
2244
  );
@@ -2363,7 +2356,7 @@ var MessageList = () => {
2363
2356
  messages.map((message, index) => {
2364
2357
  const isFromUser = message.sender?.id && user?.id && String(message.sender.id) === String(user.id) || message.sender?.email && user?.email && message.sender.email === user.email || message.is_from_author && selectedTicket?.user && user?.id && String(selectedTicket.user) === String(user.id);
2365
2358
  const previousMessage = index > 0 ? messages[index - 1] : null;
2366
- const showDateSeparator = previousMessage && new Date(previousMessage.created_at || "").toDateString() !== new Date(message.created_at || "").toDateString();
2359
+ const showDateSeparator = previousMessage && moment2.utc(previousMessage.created_at || "").format("YYYY-MM-DD") !== moment2.utc(message.created_at || "").format("YYYY-MM-DD");
2367
2360
  return /* @__PURE__ */ jsxs(React7.Fragment, { children: [
2368
2361
  showDateSeparator && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 my-4", children: [
2369
2362
  /* @__PURE__ */ jsx("div", { className: "flex-1 h-px bg-border" }),
@@ -2400,17 +2393,10 @@ var MessageInput = () => {
2400
2393
  try {
2401
2394
  await sendMessage(message.trim());
2402
2395
  setMessage("");
2403
- toast({
2404
- title: "Success",
2405
- description: "Message sent successfully"
2406
- });
2396
+ toast.success("Message sent successfully");
2407
2397
  } catch (error) {
2408
2398
  supportLogger.error("Failed to send message:", error);
2409
- toast({
2410
- title: "Error",
2411
- description: "Failed to send message",
2412
- variant: "destructive"
2413
- });
2399
+ toast.error("Failed to send message");
2414
2400
  } finally {
2415
2401
  setIsSending(false);
2416
2402
  }
@@ -2631,7 +2617,7 @@ var SupportLayout = () => {
2631
2617
  // package.json
2632
2618
  var package_default = {
2633
2619
  name: "@djangocfg/ext-support",
2634
- version: "1.0.6",
2620
+ version: "1.0.8",
2635
2621
  description: "Support ticket system extension for DjangoCFG",
2636
2622
  keywords: [
2637
2623
  "django",
@@ -2692,9 +2678,11 @@ var package_default = {
2692
2678
  peerDependencies: {
2693
2679
  "@djangocfg/api": "workspace:*",
2694
2680
  "@djangocfg/ext-base": "workspace:*",
2681
+ "@djangocfg/ui-core": "workspace:*",
2695
2682
  "@djangocfg/ui-nextjs": "workspace:*",
2696
2683
  consola: "^3.4.2",
2697
2684
  "lucide-react": "^0.545.0",
2685
+ moment: "^2.30.1",
2698
2686
  next: "^15.5.7",
2699
2687
  "p-retry": "^7.0.0",
2700
2688
  react: "^18 || ^19",
@@ -2709,6 +2697,7 @@ var package_default = {
2709
2697
  "@types/node": "^24.7.2",
2710
2698
  "@types/react": "^19.0.0",
2711
2699
  consola: "^3.4.2",
2700
+ moment: "^2.30.1",
2712
2701
  "p-retry": "^7.0.0",
2713
2702
  swr: "^2.3.7",
2714
2703
  tsup: "^8.5.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/ext-support",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "Support ticket system extension for DjangoCFG",
5
5
  "keywords": [
6
6
  "django",
@@ -59,11 +59,13 @@
59
59
  "check": "tsc --noEmit"
60
60
  },
61
61
  "peerDependencies": {
62
- "@djangocfg/api": "^2.1.37",
63
- "@djangocfg/ext-base": "^1.0.6",
64
- "@djangocfg/ui-nextjs": "^2.1.37",
62
+ "@djangocfg/api": "^2.1.91",
63
+ "@djangocfg/ext-base": "^1.0.8",
64
+ "@djangocfg/ui-core": "^2.1.91",
65
+ "@djangocfg/ui-nextjs": "^2.1.91",
65
66
  "consola": "^3.4.2",
66
67
  "lucide-react": "^0.545.0",
68
+ "moment": "^2.30.1",
67
69
  "next": "^15.5.7",
68
70
  "p-retry": "^7.0.0",
69
71
  "react": "^18 || ^19",
@@ -72,12 +74,13 @@
72
74
  "zod": "^4.1.13"
73
75
  },
74
76
  "devDependencies": {
75
- "@djangocfg/api": "^2.1.37",
76
- "@djangocfg/ext-base": "^1.0.6",
77
- "@djangocfg/typescript-config": "^2.1.37",
77
+ "@djangocfg/api": "^2.1.91",
78
+ "@djangocfg/ext-base": "^1.0.8",
79
+ "@djangocfg/typescript-config": "^2.1.91",
78
80
  "@types/node": "^24.7.2",
79
81
  "@types/react": "^19.0.0",
80
82
  "consola": "^3.4.2",
83
+ "moment": "^2.30.1",
81
84
  "p-retry": "^7.0.0",
82
85
  "swr": "^2.3.7",
83
86
  "tsup": "^8.5.0",
@@ -0,0 +1,80 @@
1
+ # Django CFG API - Typescript Client
2
+
3
+ Auto-generated. **Do not edit manually.**
4
+
5
+ ```bash
6
+ python manage.py generate_client --groups ext_support --typescript
7
+ ```
8
+
9
+ ## Stats
10
+
11
+ | | |
12
+ |---|---|
13
+ | Version | 3.0.3 |
14
+ | Operations | 12 |
15
+ | Schemas | 11 |
16
+
17
+ ## Resources
18
+
19
+ - **support** (12 ops)
20
+
21
+ ## Operations
22
+
23
+ **support:**
24
+ - `POST` /cfg/support/tickets/ → `cfg_support_tickets_create`
25
+ - `DELETE` /cfg/support/tickets/{uuid}/ → `cfg_support_tickets_destroy`
26
+ - `GET` /cfg/support/tickets/ → `cfg_support_tickets_list`
27
+ - `POST` /cfg/support/tickets/{ticket_uuid}/messages/ → `cfg_support_tickets_messages_create`
28
+ - `DELETE` /cfg/support/tickets/{ticket_uuid}/messages/{uuid}/ → `cfg_support_tickets_messages_destroy`
29
+ - `GET` /cfg/support/tickets/{ticket_uuid}/messages/ → `cfg_support_tickets_messages_list`
30
+ - `PATCH` /cfg/support/tickets/{ticket_uuid}/messages/{uuid}/ → `cfg_support_tickets_messages_partial_update`
31
+ - `GET` /cfg/support/tickets/{ticket_uuid}/messages/{uuid}/ → `cfg_support_tickets_messages_retrieve`
32
+ - `PUT` /cfg/support/tickets/{ticket_uuid}/messages/{uuid}/ → `cfg_support_tickets_messages_update`
33
+ - `PATCH` /cfg/support/tickets/{uuid}/ → `cfg_support_tickets_partial_update`
34
+ - `GET` /cfg/support/tickets/{uuid}/ → `cfg_support_tickets_retrieve`
35
+ - `PUT` /cfg/support/tickets/{uuid}/ → `cfg_support_tickets_update`
36
+
37
+ ## Usage
38
+
39
+ ```typescript
40
+ import { APIClient } from './';
41
+
42
+ const client = new APIClient({ baseUrl, token });
43
+
44
+ await client.support.list();
45
+ await client.support.retrieve({ id: 1 });
46
+ await client.support.create({ ... });
47
+ ```
48
+
49
+ **SWR Hooks:**
50
+ ```typescript
51
+ import { useSupportList } from './hooks';
52
+ const { data, isLoading } = useSupportList();
53
+ ```
54
+
55
+ ## How It Works
56
+
57
+ ```
58
+ DRF ViewSets → drf-spectacular → OpenAPI → IR Parser → Generator → This Client
59
+ ```
60
+
61
+ **Configuration** (`api/config.py`):
62
+ ```python
63
+ openapi_client = OpenAPIClientConfig(
64
+ enabled=True,
65
+ groups=[OpenAPIGroupConfig(name="ext_support", apps=["..."])],
66
+ generate_zod_schemas=True, # → schemas.ts
67
+ generate_fetchers=True, # → fetchers.ts
68
+ generate_swr_hooks=True, # → hooks.ts
69
+ )
70
+ ```
71
+
72
+ **Copy to Next.js** (if `nextjs_admin` configured):
73
+ ```python
74
+ nextjs_admin = NextJsAdminConfig(
75
+ project_path="../frontend/apps/...",
76
+ api_output_path="app/_lib/api/generated",
77
+ )
78
+ ```
79
+
80
+ @see https://djangocfg.com/docs/features/api-generation
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Typed fetchers for Support
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Typed Fetchers - Universal API functions
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  'use client';
10
3
 
11
4
  /**
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  'use client';
10
3
 
11
4
  /**
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Zod Schemas - Runtime validation and type inference
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Global API Instance - Singleton configuration
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * * `open` - Open
11
4
  * * `waiting_for_user` - Waiting for User
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * API Error Classes
11
4
  *
@@ -1,10 +1,3 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  export * from "./client";
10
3
  export * as Models from "./models";
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  import * as Enums from "../enums";
10
3
 
11
4
  /**
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * HTTP Client Adapter Pattern
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Django CFG API - API Client with JWT Management
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * API Logger with Consola
11
4
  * Beautiful console logging for API requests and responses
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Retry Configuration and Utilities
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Storage adapters for cross-platform token storage.
11
4
  *
@@ -1,11 +1,4 @@
1
- /**
2
- * AUTO-GENERATED FILE - DO NOT EDIT
3
- *
4
- * This file is automatically generated by DjangoCFG.
5
- * Any manual changes will be lost when the code is regenerated.
6
- *
7
- * @see https://djangocfg.com/docs/features/modules/django-client/overview/
8
- */
1
+ // Auto-generated by DjangoCFG - see CLAUDE.md
9
2
  /**
10
3
  * Zod Validation Events - Browser CustomEvent integration
11
4
  *
package/src/api/index.ts CHANGED
@@ -1,9 +1,10 @@
1
+ import { createExtensionAPI } from '@djangocfg/ext-base/api';
2
+
1
3
  /**
2
4
  * Support Extension API
3
5
  *
4
6
  * Pre-configured API instance with shared authentication
5
7
  */
6
8
  import { API } from './generated/ext_support';
7
- import { createExtensionAPI } from '@djangocfg/ext-base/api';
8
9
 
9
10
  export const apiSupport = createExtensionAPI(API);
package/src/config.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import { createExtensionConfig } from '@djangocfg/ext-base';
6
+
6
7
  import packageJson from '../package.json';
7
8
 
8
9
  export const extensionConfig = createExtensionConfig(packageJson, {
@@ -1,20 +1,16 @@
1
1
  'use client';
2
2
 
3
- import React, { createContext, useContext, type ReactNode } from 'react';
3
+ import React, { createContext, ReactNode, useContext } from 'react';
4
+
4
5
  import {
5
- useSupportTicketsList,
6
- useSupportTicketsRetrieve,
7
- useCreateSupportTicketsCreate,
8
- useUpdateSupportTicketsUpdate,
9
- usePartialUpdateSupportTicketsPartialUpdate,
10
- useDeleteSupportTicketsDestroy,
11
- useSupportTicketsMessagesList,
12
- useSupportTicketsMessagesRetrieve,
13
- useCreateSupportTicketsMessagesCreate,
14
- useUpdateSupportTicketsMessagesUpdate,
15
- usePartialUpdateSupportTicketsMessagesPartialUpdate,
16
- useDeleteSupportTicketsMessagesDestroy,
6
+ useCreateSupportTicketsCreate, useCreateSupportTicketsMessagesCreate,
7
+ useDeleteSupportTicketsDestroy, useDeleteSupportTicketsMessagesDestroy,
8
+ usePartialUpdateSupportTicketsMessagesPartialUpdate,
9
+ usePartialUpdateSupportTicketsPartialUpdate, useSupportTicketsList,
10
+ useSupportTicketsMessagesList, useSupportTicketsMessagesRetrieve, useSupportTicketsRetrieve,
11
+ useUpdateSupportTicketsMessagesUpdate, useUpdateSupportTicketsUpdate
17
12
  } from '../api/generated/ext_support/_utils/hooks';
13
+
18
14
  import type {
19
15
  Ticket,
20
16
  TicketRequest,