@djangocfg/ext-newsletter 1.0.9 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -607,6 +607,8 @@ interface HttpRequest {
607
607
  params?: Record<string, any>;
608
608
  /** FormData for file uploads (multipart/form-data) */
609
609
  formData?: FormData;
610
+ /** Binary data for octet-stream uploads */
611
+ binaryBody?: Blob | ArrayBuffer;
610
612
  }
611
613
  interface HttpResponse<T = any> {
612
614
  data: T;
@@ -859,6 +861,7 @@ declare class APIClient {
859
861
  private httpClient;
860
862
  private logger;
861
863
  private retryConfig;
864
+ private tokenGetter;
862
865
  ext_newsletter_bulk_email: ExtNewsletterBulkEmail;
863
866
  ext_newsletter_campaigns: ExtNewsletterCampaigns;
864
867
  ext_newsletter_logs: ExtNewsletterLogs;
@@ -870,6 +873,7 @@ declare class APIClient {
870
873
  httpClient?: HttpClientAdapter;
871
874
  loggerConfig?: Partial<LoggerConfig>;
872
875
  retryConfig?: RetryConfig;
876
+ tokenGetter?: () => string | null;
873
877
  });
874
878
  /**
875
879
  * Get CSRF token from cookies (for SessionAuthentication).
@@ -877,6 +881,15 @@ declare class APIClient {
877
881
  * Returns null if cookie doesn't exist (JWT-only auth).
878
882
  */
879
883
  getCsrfToken(): string | null;
884
+ /**
885
+ * Get the base URL for building streaming/download URLs.
886
+ */
887
+ getBaseUrl(): string;
888
+ /**
889
+ * Get JWT token for URL authentication (used in streaming endpoints).
890
+ * Returns null if no token getter is configured or no token is available.
891
+ */
892
+ getToken(): string | null;
880
893
  /**
881
894
  * Make HTTP request with Django CSRF and session handling.
882
895
  * Automatically retries on network errors and 5xx server errors.
@@ -885,6 +898,7 @@ declare class APIClient {
885
898
  params?: Record<string, any>;
886
899
  body?: any;
887
900
  formData?: FormData;
901
+ binaryBody?: Blob | ArrayBuffer;
888
902
  headers?: Record<string, string>;
889
903
  }): Promise<T>;
890
904
  /**
@@ -966,7 +980,7 @@ declare const BulkEmailRequestSchema: z.ZodObject<{
966
980
  main_text: z.ZodString;
967
981
  main_html_content: z.ZodOptional<z.ZodString>;
968
982
  button_text: z.ZodOptional<z.ZodString>;
969
- button_url: z.ZodOptional<z.ZodURL>;
983
+ button_url: z.ZodOptional<z.ZodUnion<readonly [z.ZodURL, z.ZodLiteral<"">]>>;
970
984
  secondary_text: z.ZodOptional<z.ZodString>;
971
985
  }, z.core.$strip>;
972
986
  /**
@@ -1088,7 +1102,7 @@ declare const NewsletterCampaignSchema: z.ZodObject<{
1088
1102
  main_text: z.ZodString;
1089
1103
  main_html_content: z.ZodOptional<z.ZodString>;
1090
1104
  button_text: z.ZodOptional<z.ZodString>;
1091
- button_url: z.ZodOptional<z.ZodURL>;
1105
+ button_url: z.ZodOptional<z.ZodUnion<readonly [z.ZodURL, z.ZodLiteral<"">]>>;
1092
1106
  secondary_text: z.ZodOptional<z.ZodString>;
1093
1107
  status: z.ZodEnum<typeof NewsletterCampaignStatus>;
1094
1108
  created_at: z.ZodISODateTime;
@@ -1117,7 +1131,7 @@ declare const NewsletterCampaignRequestSchema: z.ZodObject<{
1117
1131
  main_text: z.ZodString;
1118
1132
  main_html_content: z.ZodOptional<z.ZodString>;
1119
1133
  button_text: z.ZodOptional<z.ZodString>;
1120
- button_url: z.ZodOptional<z.ZodURL>;
1134
+ button_url: z.ZodOptional<z.ZodUnion<readonly [z.ZodURL, z.ZodLiteral<"">]>>;
1121
1135
  secondary_text: z.ZodOptional<z.ZodString>;
1122
1136
  }, z.core.$strip>;
1123
1137
  /**
@@ -1198,7 +1212,7 @@ declare const PaginatedNewsletterCampaignListSchema: z.ZodObject<{
1198
1212
  main_text: z.ZodString;
1199
1213
  main_html_content: z.ZodOptional<z.ZodString>;
1200
1214
  button_text: z.ZodOptional<z.ZodString>;
1201
- button_url: z.ZodOptional<z.ZodURL>;
1215
+ button_url: z.ZodOptional<z.ZodUnion<readonly [z.ZodURL, z.ZodLiteral<"">]>>;
1202
1216
  secondary_text: z.ZodOptional<z.ZodString>;
1203
1217
  status: z.ZodEnum<typeof NewsletterCampaignStatus>;
1204
1218
  created_at: z.ZodISODateTime;
@@ -1291,7 +1305,7 @@ declare const PatchedNewsletterCampaignRequestSchema: z.ZodObject<{
1291
1305
  main_text: z.ZodOptional<z.ZodString>;
1292
1306
  main_html_content: z.ZodOptional<z.ZodString>;
1293
1307
  button_text: z.ZodOptional<z.ZodString>;
1294
- button_url: z.ZodOptional<z.ZodURL>;
1308
+ button_url: z.ZodOptional<z.ZodUnion<readonly [z.ZodURL, z.ZodLiteral<"">]>>;
1295
1309
  secondary_text: z.ZodOptional<z.ZodString>;
1296
1310
  }, z.core.$strip>;
1297
1311
  /**
@@ -1796,30 +1810,38 @@ declare namespace index {
1796
1810
  }
1797
1811
 
1798
1812
  /**
1799
- * Global API Instance - Singleton configuration
1813
+ * Global API Instance - Singleton configuration with auto-configuration support
1800
1814
  *
1801
- * This module provides a global API instance that can be configured once
1802
- * and used throughout your application.
1815
+ * This module provides a global API instance that auto-configures from
1816
+ * environment variables or can be configured manually.
1803
1817
  *
1804
- * Usage:
1818
+ * AUTO-CONFIGURATION (recommended):
1819
+ * Set one of these environment variables and the API will auto-configure:
1820
+ * - NEXT_PUBLIC_API_URL (Next.js)
1821
+ * - VITE_API_URL (Vite)
1822
+ * - REACT_APP_API_URL (Create React App)
1823
+ * - API_URL (generic)
1824
+ *
1825
+ * Then just use fetchers and hooks directly:
1826
+ * ```typescript
1827
+ * import { getUsers } from './_utils/fetchers'
1828
+ * const users = await getUsers({ page: 1 })
1829
+ * ```
1830
+ *
1831
+ * MANUAL CONFIGURATION:
1805
1832
  * ```typescript
1806
- * // Configure once (e.g., in your app entry point)
1807
1833
  * import { configureAPI } from './api-instance'
1808
1834
  *
1809
1835
  * configureAPI({
1810
1836
  * baseUrl: 'https://api.example.com',
1811
1837
  * token: 'your-jwt-token'
1812
1838
  * })
1813
- *
1814
- * // Then use fetchers and hooks anywhere without configuration
1815
- * import { getUsers } from './fetchers'
1816
- * const users = await getUsers({ page: 1 })
1817
1839
  * ```
1818
1840
  *
1819
1841
  * For SSR or multiple instances:
1820
1842
  * ```typescript
1821
1843
  * import { API } from './index'
1822
- * import { getUsers } from './fetchers'
1844
+ * import { getUsers } from './_utils/fetchers'
1823
1845
  *
1824
1846
  * const api = new API('https://api.example.com')
1825
1847
  * const users = await getUsers({ page: 1 }, api)
@@ -1828,11 +1850,12 @@ declare namespace index {
1828
1850
 
1829
1851
  /**
1830
1852
  * Get the global API instance
1831
- * @throws Error if API is not configured
1853
+ * Auto-configures from environment variables on first call if not manually configured.
1854
+ * @throws Error if API is not configured and no env variable is set
1832
1855
  */
1833
1856
  declare function getAPIInstance(): API;
1834
1857
  /**
1835
- * Check if API is configured
1858
+ * Check if API is configured (or can be auto-configured)
1836
1859
  */
1837
1860
  declare function isAPIConfigured(): boolean;
1838
1861
  /**
package/dist/index.d.ts CHANGED
@@ -607,6 +607,8 @@ interface HttpRequest {
607
607
  params?: Record<string, any>;
608
608
  /** FormData for file uploads (multipart/form-data) */
609
609
  formData?: FormData;
610
+ /** Binary data for octet-stream uploads */
611
+ binaryBody?: Blob | ArrayBuffer;
610
612
  }
611
613
  interface HttpResponse<T = any> {
612
614
  data: T;
@@ -859,6 +861,7 @@ declare class APIClient {
859
861
  private httpClient;
860
862
  private logger;
861
863
  private retryConfig;
864
+ private tokenGetter;
862
865
  ext_newsletter_bulk_email: ExtNewsletterBulkEmail;
863
866
  ext_newsletter_campaigns: ExtNewsletterCampaigns;
864
867
  ext_newsletter_logs: ExtNewsletterLogs;
@@ -870,6 +873,7 @@ declare class APIClient {
870
873
  httpClient?: HttpClientAdapter;
871
874
  loggerConfig?: Partial<LoggerConfig>;
872
875
  retryConfig?: RetryConfig;
876
+ tokenGetter?: () => string | null;
873
877
  });
874
878
  /**
875
879
  * Get CSRF token from cookies (for SessionAuthentication).
@@ -877,6 +881,15 @@ declare class APIClient {
877
881
  * Returns null if cookie doesn't exist (JWT-only auth).
878
882
  */
879
883
  getCsrfToken(): string | null;
884
+ /**
885
+ * Get the base URL for building streaming/download URLs.
886
+ */
887
+ getBaseUrl(): string;
888
+ /**
889
+ * Get JWT token for URL authentication (used in streaming endpoints).
890
+ * Returns null if no token getter is configured or no token is available.
891
+ */
892
+ getToken(): string | null;
880
893
  /**
881
894
  * Make HTTP request with Django CSRF and session handling.
882
895
  * Automatically retries on network errors and 5xx server errors.
@@ -885,6 +898,7 @@ declare class APIClient {
885
898
  params?: Record<string, any>;
886
899
  body?: any;
887
900
  formData?: FormData;
901
+ binaryBody?: Blob | ArrayBuffer;
888
902
  headers?: Record<string, string>;
889
903
  }): Promise<T>;
890
904
  /**
@@ -966,7 +980,7 @@ declare const BulkEmailRequestSchema: z.ZodObject<{
966
980
  main_text: z.ZodString;
967
981
  main_html_content: z.ZodOptional<z.ZodString>;
968
982
  button_text: z.ZodOptional<z.ZodString>;
969
- button_url: z.ZodOptional<z.ZodURL>;
983
+ button_url: z.ZodOptional<z.ZodUnion<readonly [z.ZodURL, z.ZodLiteral<"">]>>;
970
984
  secondary_text: z.ZodOptional<z.ZodString>;
971
985
  }, z.core.$strip>;
972
986
  /**
@@ -1088,7 +1102,7 @@ declare const NewsletterCampaignSchema: z.ZodObject<{
1088
1102
  main_text: z.ZodString;
1089
1103
  main_html_content: z.ZodOptional<z.ZodString>;
1090
1104
  button_text: z.ZodOptional<z.ZodString>;
1091
- button_url: z.ZodOptional<z.ZodURL>;
1105
+ button_url: z.ZodOptional<z.ZodUnion<readonly [z.ZodURL, z.ZodLiteral<"">]>>;
1092
1106
  secondary_text: z.ZodOptional<z.ZodString>;
1093
1107
  status: z.ZodEnum<typeof NewsletterCampaignStatus>;
1094
1108
  created_at: z.ZodISODateTime;
@@ -1117,7 +1131,7 @@ declare const NewsletterCampaignRequestSchema: z.ZodObject<{
1117
1131
  main_text: z.ZodString;
1118
1132
  main_html_content: z.ZodOptional<z.ZodString>;
1119
1133
  button_text: z.ZodOptional<z.ZodString>;
1120
- button_url: z.ZodOptional<z.ZodURL>;
1134
+ button_url: z.ZodOptional<z.ZodUnion<readonly [z.ZodURL, z.ZodLiteral<"">]>>;
1121
1135
  secondary_text: z.ZodOptional<z.ZodString>;
1122
1136
  }, z.core.$strip>;
1123
1137
  /**
@@ -1198,7 +1212,7 @@ declare const PaginatedNewsletterCampaignListSchema: z.ZodObject<{
1198
1212
  main_text: z.ZodString;
1199
1213
  main_html_content: z.ZodOptional<z.ZodString>;
1200
1214
  button_text: z.ZodOptional<z.ZodString>;
1201
- button_url: z.ZodOptional<z.ZodURL>;
1215
+ button_url: z.ZodOptional<z.ZodUnion<readonly [z.ZodURL, z.ZodLiteral<"">]>>;
1202
1216
  secondary_text: z.ZodOptional<z.ZodString>;
1203
1217
  status: z.ZodEnum<typeof NewsletterCampaignStatus>;
1204
1218
  created_at: z.ZodISODateTime;
@@ -1291,7 +1305,7 @@ declare const PatchedNewsletterCampaignRequestSchema: z.ZodObject<{
1291
1305
  main_text: z.ZodOptional<z.ZodString>;
1292
1306
  main_html_content: z.ZodOptional<z.ZodString>;
1293
1307
  button_text: z.ZodOptional<z.ZodString>;
1294
- button_url: z.ZodOptional<z.ZodURL>;
1308
+ button_url: z.ZodOptional<z.ZodUnion<readonly [z.ZodURL, z.ZodLiteral<"">]>>;
1295
1309
  secondary_text: z.ZodOptional<z.ZodString>;
1296
1310
  }, z.core.$strip>;
1297
1311
  /**
@@ -1796,30 +1810,38 @@ declare namespace index {
1796
1810
  }
1797
1811
 
1798
1812
  /**
1799
- * Global API Instance - Singleton configuration
1813
+ * Global API Instance - Singleton configuration with auto-configuration support
1800
1814
  *
1801
- * This module provides a global API instance that can be configured once
1802
- * and used throughout your application.
1815
+ * This module provides a global API instance that auto-configures from
1816
+ * environment variables or can be configured manually.
1803
1817
  *
1804
- * Usage:
1818
+ * AUTO-CONFIGURATION (recommended):
1819
+ * Set one of these environment variables and the API will auto-configure:
1820
+ * - NEXT_PUBLIC_API_URL (Next.js)
1821
+ * - VITE_API_URL (Vite)
1822
+ * - REACT_APP_API_URL (Create React App)
1823
+ * - API_URL (generic)
1824
+ *
1825
+ * Then just use fetchers and hooks directly:
1826
+ * ```typescript
1827
+ * import { getUsers } from './_utils/fetchers'
1828
+ * const users = await getUsers({ page: 1 })
1829
+ * ```
1830
+ *
1831
+ * MANUAL CONFIGURATION:
1805
1832
  * ```typescript
1806
- * // Configure once (e.g., in your app entry point)
1807
1833
  * import { configureAPI } from './api-instance'
1808
1834
  *
1809
1835
  * configureAPI({
1810
1836
  * baseUrl: 'https://api.example.com',
1811
1837
  * token: 'your-jwt-token'
1812
1838
  * })
1813
- *
1814
- * // Then use fetchers and hooks anywhere without configuration
1815
- * import { getUsers } from './fetchers'
1816
- * const users = await getUsers({ page: 1 })
1817
1839
  * ```
1818
1840
  *
1819
1841
  * For SSR or multiple instances:
1820
1842
  * ```typescript
1821
1843
  * import { API } from './index'
1822
- * import { getUsers } from './fetchers'
1844
+ * import { getUsers } from './_utils/fetchers'
1823
1845
  *
1824
1846
  * const api = new API('https://api.example.com')
1825
1847
  * const users = await getUsers({ page: 1 }, api)
@@ -1828,11 +1850,12 @@ declare namespace index {
1828
1850
 
1829
1851
  /**
1830
1852
  * Get the global API instance
1831
- * @throws Error if API is not configured
1853
+ * Auto-configures from environment variables on first call if not manually configured.
1854
+ * @throws Error if API is not configured and no env variable is set
1832
1855
  */
1833
1856
  declare function getAPIInstance(): API;
1834
1857
  /**
1835
- * Check if API is configured
1858
+ * Check if API is configured (or can be auto-configured)
1836
1859
  */
1837
1860
  declare function isAPIConfigured(): boolean;
1838
1861
  /**
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createConsola, consola } from 'consola';
2
2
  import pRetry, { AbortError } from 'p-retry';
3
3
  import { z } from 'zod';
4
- import { createExtensionAPI } from '@djangocfg/ext-base/api';
4
+ import { initializeExtensionAPI, createExtensionAPI } from '@djangocfg/ext-base/api';
5
5
  import { createExtensionConfig } from '@djangocfg/ext-base';
6
6
 
7
7
  var __defProp = Object.defineProperty;
@@ -265,7 +265,7 @@ var models_exports7 = {};
265
265
  // src/api/generated/ext_newsletter/http.ts
266
266
  var FetchAdapter = class {
267
267
  async request(request) {
268
- const { method, url, headers, body, params, formData } = request;
268
+ const { method, url, headers, body, params, formData, binaryBody } = request;
269
269
  let finalUrl = url;
270
270
  if (params) {
271
271
  const searchParams = new URLSearchParams();
@@ -283,6 +283,9 @@ var FetchAdapter = class {
283
283
  let requestBody;
284
284
  if (formData) {
285
285
  requestBody = formData;
286
+ } else if (binaryBody) {
287
+ finalHeaders["Content-Type"] = "application/octet-stream";
288
+ requestBody = binaryBody;
286
289
  } else if (body) {
287
290
  finalHeaders["Content-Type"] = "application/json";
288
291
  requestBody = JSON.stringify(body);
@@ -607,6 +610,7 @@ var APIClient = class {
607
610
  httpClient;
608
611
  logger = null;
609
612
  retryConfig = null;
613
+ tokenGetter = null;
610
614
  // Sub-clients
611
615
  ext_newsletter_bulk_email;
612
616
  ext_newsletter_campaigns;
@@ -618,6 +622,7 @@ var APIClient = class {
618
622
  constructor(baseUrl, options) {
619
623
  this.baseUrl = baseUrl.replace(/\/$/, "");
620
624
  this.httpClient = options?.httpClient || new FetchAdapter();
625
+ this.tokenGetter = options?.tokenGetter || null;
621
626
  if (options?.loggerConfig !== void 0) {
622
627
  this.logger = new APILogger(options.loggerConfig);
623
628
  }
@@ -646,6 +651,19 @@ var APIClient = class {
646
651
  }
647
652
  return null;
648
653
  }
654
+ /**
655
+ * Get the base URL for building streaming/download URLs.
656
+ */
657
+ getBaseUrl() {
658
+ return this.baseUrl;
659
+ }
660
+ /**
661
+ * Get JWT token for URL authentication (used in streaming endpoints).
662
+ * Returns null if no token getter is configured or no token is available.
663
+ */
664
+ getToken() {
665
+ return this.tokenGetter ? this.tokenGetter() : null;
666
+ }
649
667
  /**
650
668
  * Make HTTP request with Django CSRF and session handling.
651
669
  * Automatically retries on network errors and 5xx server errors.
@@ -676,7 +694,7 @@ var APIClient = class {
676
694
  const headers = {
677
695
  ...options?.headers || {}
678
696
  };
679
- if (!options?.formData && !headers["Content-Type"]) {
697
+ if (!options?.formData && !options?.binaryBody && !headers["Content-Type"]) {
680
698
  headers["Content-Type"] = "application/json";
681
699
  }
682
700
  if (this.logger) {
@@ -695,7 +713,8 @@ var APIClient = class {
695
713
  headers,
696
714
  params: options?.params,
697
715
  body: options?.body,
698
- formData: options?.formData
716
+ formData: options?.formData,
717
+ binaryBody: options?.binaryBody
699
718
  });
700
719
  const duration = Date.now() - startTime;
701
720
  if (response.status >= 400) {
@@ -976,7 +995,7 @@ var BulkEmailRequestSchema = z.object({
976
995
  main_text: z.string().min(1),
977
996
  main_html_content: z.string().optional(),
978
997
  button_text: z.string().max(100).optional(),
979
- button_url: z.url().optional(),
998
+ button_url: z.union([z.url(), z.literal("")]).optional(),
980
999
  secondary_text: z.string().optional()
981
1000
  });
982
1001
  var BulkEmailResponseSchema = z.object({
@@ -1023,7 +1042,7 @@ var NewsletterCampaignSchema = z.object({
1023
1042
  main_text: z.string(),
1024
1043
  main_html_content: z.string().optional(),
1025
1044
  button_text: z.string().max(100).optional(),
1026
- button_url: z.url().optional(),
1045
+ button_url: z.union([z.url(), z.literal("")]).optional(),
1027
1046
  secondary_text: z.string().optional(),
1028
1047
  status: z.nativeEnum(NewsletterCampaignStatus),
1029
1048
  created_at: z.iso.datetime(),
@@ -1037,7 +1056,7 @@ var NewsletterCampaignRequestSchema = z.object({
1037
1056
  main_text: z.string().min(1),
1038
1057
  main_html_content: z.string().optional(),
1039
1058
  button_text: z.string().max(100).optional(),
1040
- button_url: z.url().optional(),
1059
+ button_url: z.union([z.url(), z.literal("")]).optional(),
1041
1060
  secondary_text: z.string().optional()
1042
1061
  });
1043
1062
  var NewsletterSubscriptionSchema = z.object({
@@ -1102,7 +1121,7 @@ var PatchedNewsletterCampaignRequestSchema = z.object({
1102
1121
  main_text: z.string().min(1).optional(),
1103
1122
  main_html_content: z.string().optional(),
1104
1123
  button_text: z.string().max(100).optional(),
1105
- button_url: z.url().optional(),
1124
+ button_url: z.union([z.url(), z.literal("")]).optional(),
1106
1125
  secondary_text: z.string().optional()
1107
1126
  });
1108
1127
  var PatchedUnsubscribeRequestSchema = z.object({
@@ -1212,15 +1231,28 @@ __export(fetchers_exports, {
1212
1231
 
1213
1232
  // src/api/generated/ext_newsletter/api-instance.ts
1214
1233
  var globalAPI = null;
1234
+ var autoConfigAttempted = false;
1235
+ function tryAutoConfigureFromEnv() {
1236
+ if (autoConfigAttempted) return;
1237
+ autoConfigAttempted = true;
1238
+ if (globalAPI) return;
1239
+ if (typeof process === "undefined" || !process.env) return;
1240
+ const baseUrl = process.env.NEXT_PUBLIC_API_URL || process.env.VITE_API_URL || process.env.REACT_APP_API_URL || process.env.API_URL;
1241
+ if (baseUrl) {
1242
+ globalAPI = new API(baseUrl);
1243
+ }
1244
+ }
1215
1245
  function getAPIInstance() {
1246
+ tryAutoConfigureFromEnv();
1216
1247
  if (!globalAPI) {
1217
1248
  throw new Error(
1218
- 'API not configured. Call configureAPI() with your base URL before using fetchers or hooks.\n\nExample:\n import { configureAPI } from "./api-instance"\n configureAPI({ baseUrl: "https://api.example.com" })'
1249
+ 'API not configured. Call configureAPI() with your base URL before using fetchers or hooks.\n\nExample:\n import { configureAPI } from "./api-instance"\n configureAPI({ baseUrl: "https://api.example.com" })\n\nOr set environment variable: NEXT_PUBLIC_API_URL, VITE_API_URL, or REACT_APP_API_URL'
1219
1250
  );
1220
1251
  }
1221
1252
  return globalAPI;
1222
1253
  }
1223
1254
  function isAPIConfigured() {
1255
+ tryAutoConfigureFromEnv();
1224
1256
  return globalAPI !== null;
1225
1257
  }
1226
1258
  function configureAPI(config) {
@@ -1956,7 +1988,8 @@ var API = class {
1956
1988
  this._loadTokensFromStorage();
1957
1989
  this._client = new APIClient(this.baseUrl, {
1958
1990
  retryConfig: this.options?.retryConfig,
1959
- loggerConfig: this.options?.loggerConfig
1991
+ loggerConfig: this.options?.loggerConfig,
1992
+ tokenGetter: () => this.getToken()
1960
1993
  });
1961
1994
  this._injectAuthHeader();
1962
1995
  this.ext_newsletter_bulk_email = this._client.ext_newsletter_bulk_email;
@@ -1974,7 +2007,8 @@ var API = class {
1974
2007
  _reinitClients() {
1975
2008
  this._client = new APIClient(this.baseUrl, {
1976
2009
  retryConfig: this.options?.retryConfig,
1977
- loggerConfig: this.options?.loggerConfig
2010
+ loggerConfig: this.options?.loggerConfig,
2011
+ tokenGetter: () => this.getToken()
1978
2012
  });
1979
2013
  this._injectAuthHeader();
1980
2014
  this.ext_newsletter_bulk_email = this._client.ext_newsletter_bulk_email;
@@ -2071,12 +2105,13 @@ var API = class {
2071
2105
  return "./schema.json";
2072
2106
  }
2073
2107
  };
2108
+ initializeExtensionAPI(configureAPI);
2074
2109
  var apiNewsletter = createExtensionAPI(API);
2075
2110
 
2076
2111
  // package.json
2077
2112
  var package_default = {
2078
2113
  name: "@djangocfg/ext-newsletter",
2079
- version: "1.0.9",
2114
+ version: "1.0.11",
2080
2115
  description: "Newsletter and subscription management extension for DjangoCFG",
2081
2116
  keywords: [
2082
2117
  "django",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/ext-newsletter",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "Newsletter and subscription management extension for DjangoCFG",
5
5
  "keywords": [
6
6
  "django",
@@ -59,9 +59,9 @@
59
59
  "check": "tsc --noEmit"
60
60
  },
61
61
  "peerDependencies": {
62
- "@djangocfg/api": "^2.1.104",
62
+ "@djangocfg/api": "^2.1.107",
63
63
  "@djangocfg/ext-base": "^1.0.8",
64
- "@djangocfg/ui-core": "^2.1.104",
64
+ "@djangocfg/ui-core": "^2.1.107",
65
65
  "consola": "^3.4.2",
66
66
  "lucide-react": "^0.545.0",
67
67
  "next": "^15.5.7",
@@ -72,9 +72,9 @@
72
72
  "zod": "^4.1.13"
73
73
  },
74
74
  "devDependencies": {
75
- "@djangocfg/api": "^2.1.104",
75
+ "@djangocfg/api": "^2.1.107",
76
76
  "@djangocfg/ext-base": "^1.0.8",
77
- "@djangocfg/typescript-config": "^2.1.104",
77
+ "@djangocfg/typescript-config": "^2.1.107",
78
78
  "@types/node": "^24.7.2",
79
79
  "@types/react": "^19.0.0",
80
80
  "consola": "^3.4.2",
@@ -60,12 +60,5 @@ openapi_client = OpenAPIClientConfig(
60
60
  )
61
61
  ```
62
62
 
63
- **Copy to Next.js** (if `nextjs_admin` configured):
64
- ```python
65
- nextjs_admin = NextJsAdminConfig(
66
- project_path="../frontend/apps/...",
67
- api_output_path="app/_lib/api/generated",
68
- )
69
- ```
70
-
71
63
  @see https://djangocfg.com/docs/features/api-generation
64
+
@@ -16,7 +16,7 @@ export const BulkEmailRequestSchema = z.object({
16
16
  main_text: z.string().min(1),
17
17
  main_html_content: z.string().optional(),
18
18
  button_text: z.string().max(100).optional(),
19
- button_url: z.url().optional(),
19
+ button_url: z.union([z.url(), z.literal('')]).optional(),
20
20
  secondary_text: z.string().optional(),
21
21
  })
22
22
 
@@ -19,7 +19,7 @@ export const NewsletterCampaignSchema = z.object({
19
19
  main_text: z.string(),
20
20
  main_html_content: z.string().optional(),
21
21
  button_text: z.string().max(100).optional(),
22
- button_url: z.url().optional(),
22
+ button_url: z.union([z.url(), z.literal('')]).optional(),
23
23
  secondary_text: z.string().optional(),
24
24
  status: z.nativeEnum(Enums.NewsletterCampaignStatus),
25
25
  created_at: z.iso.datetime(),
@@ -16,7 +16,7 @@ export const NewsletterCampaignRequestSchema = z.object({
16
16
  main_text: z.string().min(1),
17
17
  main_html_content: z.string().optional(),
18
18
  button_text: z.string().max(100).optional(),
19
- button_url: z.url().optional(),
19
+ button_url: z.union([z.url(), z.literal('')]).optional(),
20
20
  secondary_text: z.string().optional(),
21
21
  })
22
22
 
@@ -16,7 +16,7 @@ export const PatchedNewsletterCampaignRequestSchema = z.object({
16
16
  main_text: z.string().min(1).optional(),
17
17
  main_html_content: z.string().optional(),
18
18
  button_text: z.string().max(100).optional(),
19
- button_url: z.url().optional(),
19
+ button_url: z.union([z.url(), z.literal('')]).optional(),
20
20
  secondary_text: z.string().optional(),
21
21
  })
22
22