@djangocfg/ext-newsletter 1.0.8 → 1.0.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/dist/config.cjs +2 -2
- package/dist/config.js +2 -2
- package/dist/hooks.cjs +52 -17
- package/dist/hooks.js +49 -14
- package/dist/index.cjs +47 -12
- package/dist/index.d.cts +40 -17
- package/dist/index.d.ts +40 -17
- package/dist/index.js +48 -13
- package/package.json +5 -5
- package/src/api/generated/ext_newsletter/CLAUDE.md +1 -8
- package/src/api/generated/ext_newsletter/_utils/schemas/BulkEmailRequest.schema.ts +1 -1
- package/src/api/generated/ext_newsletter/_utils/schemas/NewsletterCampaign.schema.ts +1 -1
- package/src/api/generated/ext_newsletter/_utils/schemas/NewsletterCampaignRequest.schema.ts +1 -1
- package/src/api/generated/ext_newsletter/_utils/schemas/PatchedNewsletterCampaignRequest.schema.ts +1 -1
- package/src/api/generated/ext_newsletter/api-instance.ts +61 -13
- package/src/api/generated/ext_newsletter/client.ts +23 -2
- package/src/api/generated/ext_newsletter/http.ts +8 -2
- package/src/api/generated/ext_newsletter/index.ts +3 -1
- package/src/api/index.ts +6 -1
- package/src/components/Hero/index.tsx +1 -1
package/dist/config.cjs
CHANGED
|
@@ -27,7 +27,7 @@ var import_ext_base = require("@djangocfg/ext-base");
|
|
|
27
27
|
// package.json
|
|
28
28
|
var package_default = {
|
|
29
29
|
name: "@djangocfg/ext-newsletter",
|
|
30
|
-
version: "1.0.
|
|
30
|
+
version: "1.0.10",
|
|
31
31
|
description: "Newsletter and subscription management extension for DjangoCFG",
|
|
32
32
|
keywords: [
|
|
33
33
|
"django",
|
|
@@ -88,7 +88,7 @@ var package_default = {
|
|
|
88
88
|
peerDependencies: {
|
|
89
89
|
"@djangocfg/api": "workspace:*",
|
|
90
90
|
"@djangocfg/ext-base": "workspace:*",
|
|
91
|
-
"@djangocfg/ui-
|
|
91
|
+
"@djangocfg/ui-core": "workspace:*",
|
|
92
92
|
consola: "^3.4.2",
|
|
93
93
|
"lucide-react": "^0.545.0",
|
|
94
94
|
next: "^15.5.7",
|
package/dist/config.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createExtensionConfig } from "@djangocfg/ext-base";
|
|
|
4
4
|
// package.json
|
|
5
5
|
var package_default = {
|
|
6
6
|
name: "@djangocfg/ext-newsletter",
|
|
7
|
-
version: "1.0.
|
|
7
|
+
version: "1.0.10",
|
|
8
8
|
description: "Newsletter and subscription management extension for DjangoCFG",
|
|
9
9
|
keywords: [
|
|
10
10
|
"django",
|
|
@@ -65,7 +65,7 @@ var package_default = {
|
|
|
65
65
|
peerDependencies: {
|
|
66
66
|
"@djangocfg/api": "workspace:*",
|
|
67
67
|
"@djangocfg/ext-base": "workspace:*",
|
|
68
|
-
"@djangocfg/ui-
|
|
68
|
+
"@djangocfg/ui-core": "workspace:*",
|
|
69
69
|
consola: "^3.4.2",
|
|
70
70
|
"lucide-react": "^0.545.0",
|
|
71
71
|
next: "^15.5.7",
|
package/dist/hooks.cjs
CHANGED
|
@@ -10,7 +10,7 @@ var react = require('react');
|
|
|
10
10
|
var hooks = require('@djangocfg/ext-base/hooks');
|
|
11
11
|
var jsxRuntime = require('react/jsx-runtime');
|
|
12
12
|
var lucideReact = require('lucide-react');
|
|
13
|
-
var
|
|
13
|
+
var uiCore = require('@djangocfg/ui-core');
|
|
14
14
|
|
|
15
15
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
16
|
|
|
@@ -278,7 +278,7 @@ var models_exports7 = {};
|
|
|
278
278
|
// src/api/generated/ext_newsletter/http.ts
|
|
279
279
|
var FetchAdapter = class {
|
|
280
280
|
async request(request) {
|
|
281
|
-
const { method, url, headers, body, params, formData } = request;
|
|
281
|
+
const { method, url, headers, body, params, formData, binaryBody } = request;
|
|
282
282
|
let finalUrl = url;
|
|
283
283
|
if (params) {
|
|
284
284
|
const searchParams = new URLSearchParams();
|
|
@@ -296,6 +296,9 @@ var FetchAdapter = class {
|
|
|
296
296
|
let requestBody;
|
|
297
297
|
if (formData) {
|
|
298
298
|
requestBody = formData;
|
|
299
|
+
} else if (binaryBody) {
|
|
300
|
+
finalHeaders["Content-Type"] = "application/octet-stream";
|
|
301
|
+
requestBody = binaryBody;
|
|
299
302
|
} else if (body) {
|
|
300
303
|
finalHeaders["Content-Type"] = "application/json";
|
|
301
304
|
requestBody = JSON.stringify(body);
|
|
@@ -620,6 +623,7 @@ var APIClient = class {
|
|
|
620
623
|
httpClient;
|
|
621
624
|
logger = null;
|
|
622
625
|
retryConfig = null;
|
|
626
|
+
tokenGetter = null;
|
|
623
627
|
// Sub-clients
|
|
624
628
|
ext_newsletter_bulk_email;
|
|
625
629
|
ext_newsletter_campaigns;
|
|
@@ -631,6 +635,7 @@ var APIClient = class {
|
|
|
631
635
|
constructor(baseUrl, options) {
|
|
632
636
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
633
637
|
this.httpClient = options?.httpClient || new FetchAdapter();
|
|
638
|
+
this.tokenGetter = options?.tokenGetter || null;
|
|
634
639
|
if (options?.loggerConfig !== void 0) {
|
|
635
640
|
this.logger = new APILogger(options.loggerConfig);
|
|
636
641
|
}
|
|
@@ -659,6 +664,19 @@ var APIClient = class {
|
|
|
659
664
|
}
|
|
660
665
|
return null;
|
|
661
666
|
}
|
|
667
|
+
/**
|
|
668
|
+
* Get the base URL for building streaming/download URLs.
|
|
669
|
+
*/
|
|
670
|
+
getBaseUrl() {
|
|
671
|
+
return this.baseUrl;
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Get JWT token for URL authentication (used in streaming endpoints).
|
|
675
|
+
* Returns null if no token getter is configured or no token is available.
|
|
676
|
+
*/
|
|
677
|
+
getToken() {
|
|
678
|
+
return this.tokenGetter ? this.tokenGetter() : null;
|
|
679
|
+
}
|
|
662
680
|
/**
|
|
663
681
|
* Make HTTP request with Django CSRF and session handling.
|
|
664
682
|
* Automatically retries on network errors and 5xx server errors.
|
|
@@ -689,7 +707,7 @@ var APIClient = class {
|
|
|
689
707
|
const headers = {
|
|
690
708
|
...options?.headers || {}
|
|
691
709
|
};
|
|
692
|
-
if (!options?.formData && !headers["Content-Type"]) {
|
|
710
|
+
if (!options?.formData && !options?.binaryBody && !headers["Content-Type"]) {
|
|
693
711
|
headers["Content-Type"] = "application/json";
|
|
694
712
|
}
|
|
695
713
|
if (this.logger) {
|
|
@@ -708,7 +726,8 @@ var APIClient = class {
|
|
|
708
726
|
headers,
|
|
709
727
|
params: options?.params,
|
|
710
728
|
body: options?.body,
|
|
711
|
-
formData: options?.formData
|
|
729
|
+
formData: options?.formData,
|
|
730
|
+
binaryBody: options?.binaryBody
|
|
712
731
|
});
|
|
713
732
|
const duration = Date.now() - startTime;
|
|
714
733
|
if (response.status >= 400) {
|
|
@@ -989,7 +1008,7 @@ var BulkEmailRequestSchema = zod.z.object({
|
|
|
989
1008
|
main_text: zod.z.string().min(1),
|
|
990
1009
|
main_html_content: zod.z.string().optional(),
|
|
991
1010
|
button_text: zod.z.string().max(100).optional(),
|
|
992
|
-
button_url: zod.z.url().optional(),
|
|
1011
|
+
button_url: zod.z.union([zod.z.url(), zod.z.literal("")]).optional(),
|
|
993
1012
|
secondary_text: zod.z.string().optional()
|
|
994
1013
|
});
|
|
995
1014
|
var BulkEmailResponseSchema = zod.z.object({
|
|
@@ -1036,7 +1055,7 @@ var NewsletterCampaignSchema = zod.z.object({
|
|
|
1036
1055
|
main_text: zod.z.string(),
|
|
1037
1056
|
main_html_content: zod.z.string().optional(),
|
|
1038
1057
|
button_text: zod.z.string().max(100).optional(),
|
|
1039
|
-
button_url: zod.z.url().optional(),
|
|
1058
|
+
button_url: zod.z.union([zod.z.url(), zod.z.literal("")]).optional(),
|
|
1040
1059
|
secondary_text: zod.z.string().optional(),
|
|
1041
1060
|
status: zod.z.nativeEnum(NewsletterCampaignStatus),
|
|
1042
1061
|
created_at: zod.z.iso.datetime(),
|
|
@@ -1050,7 +1069,7 @@ var NewsletterCampaignRequestSchema = zod.z.object({
|
|
|
1050
1069
|
main_text: zod.z.string().min(1),
|
|
1051
1070
|
main_html_content: zod.z.string().optional(),
|
|
1052
1071
|
button_text: zod.z.string().max(100).optional(),
|
|
1053
|
-
button_url: zod.z.url().optional(),
|
|
1072
|
+
button_url: zod.z.union([zod.z.url(), zod.z.literal("")]).optional(),
|
|
1054
1073
|
secondary_text: zod.z.string().optional()
|
|
1055
1074
|
});
|
|
1056
1075
|
var NewsletterSubscriptionSchema = zod.z.object({
|
|
@@ -1115,7 +1134,7 @@ var PatchedNewsletterCampaignRequestSchema = zod.z.object({
|
|
|
1115
1134
|
main_text: zod.z.string().min(1).optional(),
|
|
1116
1135
|
main_html_content: zod.z.string().optional(),
|
|
1117
1136
|
button_text: zod.z.string().max(100).optional(),
|
|
1118
|
-
button_url: zod.z.url().optional(),
|
|
1137
|
+
button_url: zod.z.union([zod.z.url(), zod.z.literal("")]).optional(),
|
|
1119
1138
|
secondary_text: zod.z.string().optional()
|
|
1120
1139
|
});
|
|
1121
1140
|
var PatchedUnsubscribeRequestSchema = zod.z.object({
|
|
@@ -1225,15 +1244,28 @@ __export(fetchers_exports, {
|
|
|
1225
1244
|
|
|
1226
1245
|
// src/api/generated/ext_newsletter/api-instance.ts
|
|
1227
1246
|
var globalAPI = null;
|
|
1247
|
+
var autoConfigAttempted = false;
|
|
1248
|
+
function tryAutoConfigureFromEnv() {
|
|
1249
|
+
if (autoConfigAttempted) return;
|
|
1250
|
+
autoConfigAttempted = true;
|
|
1251
|
+
if (globalAPI) return;
|
|
1252
|
+
if (typeof process === "undefined" || !process.env) return;
|
|
1253
|
+
const baseUrl = process.env.NEXT_PUBLIC_API_URL || process.env.VITE_API_URL || process.env.REACT_APP_API_URL || process.env.API_URL;
|
|
1254
|
+
if (baseUrl) {
|
|
1255
|
+
globalAPI = new API(baseUrl);
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1228
1258
|
function getAPIInstance() {
|
|
1259
|
+
tryAutoConfigureFromEnv();
|
|
1229
1260
|
if (!globalAPI) {
|
|
1230
1261
|
throw new Error(
|
|
1231
|
-
'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" })'
|
|
1262
|
+
'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'
|
|
1232
1263
|
);
|
|
1233
1264
|
}
|
|
1234
1265
|
return globalAPI;
|
|
1235
1266
|
}
|
|
1236
1267
|
function isAPIConfigured() {
|
|
1268
|
+
tryAutoConfigureFromEnv();
|
|
1237
1269
|
return globalAPI !== null;
|
|
1238
1270
|
}
|
|
1239
1271
|
function configureAPI(config) {
|
|
@@ -1969,7 +2001,8 @@ var API = class {
|
|
|
1969
2001
|
this._loadTokensFromStorage();
|
|
1970
2002
|
this._client = new APIClient(this.baseUrl, {
|
|
1971
2003
|
retryConfig: this.options?.retryConfig,
|
|
1972
|
-
loggerConfig: this.options?.loggerConfig
|
|
2004
|
+
loggerConfig: this.options?.loggerConfig,
|
|
2005
|
+
tokenGetter: () => this.getToken()
|
|
1973
2006
|
});
|
|
1974
2007
|
this._injectAuthHeader();
|
|
1975
2008
|
this.ext_newsletter_bulk_email = this._client.ext_newsletter_bulk_email;
|
|
@@ -1987,7 +2020,8 @@ var API = class {
|
|
|
1987
2020
|
_reinitClients() {
|
|
1988
2021
|
this._client = new APIClient(this.baseUrl, {
|
|
1989
2022
|
retryConfig: this.options?.retryConfig,
|
|
1990
|
-
loggerConfig: this.options?.loggerConfig
|
|
2023
|
+
loggerConfig: this.options?.loggerConfig,
|
|
2024
|
+
tokenGetter: () => this.getToken()
|
|
1991
2025
|
});
|
|
1992
2026
|
this._injectAuthHeader();
|
|
1993
2027
|
this.ext_newsletter_bulk_email = this._client.ext_newsletter_bulk_email;
|
|
@@ -2084,12 +2118,13 @@ var API = class {
|
|
|
2084
2118
|
return "./schema.json";
|
|
2085
2119
|
}
|
|
2086
2120
|
};
|
|
2121
|
+
api.initializeExtensionAPI(configureAPI);
|
|
2087
2122
|
var apiNewsletter = api.createExtensionAPI(API);
|
|
2088
2123
|
|
|
2089
2124
|
// package.json
|
|
2090
2125
|
var package_default = {
|
|
2091
2126
|
name: "@djangocfg/ext-newsletter",
|
|
2092
|
-
version: "1.0.
|
|
2127
|
+
version: "1.0.10",
|
|
2093
2128
|
description: "Newsletter and subscription management extension for DjangoCFG",
|
|
2094
2129
|
keywords: [
|
|
2095
2130
|
"django",
|
|
@@ -2150,7 +2185,7 @@ var package_default = {
|
|
|
2150
2185
|
peerDependencies: {
|
|
2151
2186
|
"@djangocfg/api": "workspace:*",
|
|
2152
2187
|
"@djangocfg/ext-base": "workspace:*",
|
|
2153
|
-
"@djangocfg/ui-
|
|
2188
|
+
"@djangocfg/ui-core": "workspace:*",
|
|
2154
2189
|
consola: "^3.4.2",
|
|
2155
2190
|
"lucide-react": "^0.545.0",
|
|
2156
2191
|
next: "^15.5.7",
|
|
@@ -2490,7 +2525,7 @@ function Hero({
|
|
|
2490
2525
|
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg sm:text-xl text-muted-foreground mb-8 max-w-2xl mx-auto", children: description }),
|
|
2491
2526
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col sm:flex-row gap-4 justify-center items-center mb-12", children: [
|
|
2492
2527
|
primaryAction && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2493
|
-
|
|
2528
|
+
uiCore.Button,
|
|
2494
2529
|
{
|
|
2495
2530
|
size: "lg",
|
|
2496
2531
|
onClick: primaryAction.onClick,
|
|
@@ -2499,7 +2534,7 @@ function Hero({
|
|
|
2499
2534
|
}
|
|
2500
2535
|
),
|
|
2501
2536
|
secondaryAction && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2502
|
-
|
|
2537
|
+
uiCore.Button,
|
|
2503
2538
|
{
|
|
2504
2539
|
size: "lg",
|
|
2505
2540
|
variant: "outline",
|
|
@@ -2515,7 +2550,7 @@ function Hero({
|
|
|
2515
2550
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1", children: [
|
|
2516
2551
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Mail, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-5 w-5 text-muted-foreground" }),
|
|
2517
2552
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2518
|
-
|
|
2553
|
+
uiCore.Input,
|
|
2519
2554
|
{
|
|
2520
2555
|
type: "email",
|
|
2521
2556
|
placeholder: newsletterPlaceholder,
|
|
@@ -2528,7 +2563,7 @@ function Hero({
|
|
|
2528
2563
|
)
|
|
2529
2564
|
] }),
|
|
2530
2565
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2531
|
-
|
|
2566
|
+
uiCore.Button,
|
|
2532
2567
|
{
|
|
2533
2568
|
type: "submit",
|
|
2534
2569
|
disabled: isLoading || !email,
|
package/dist/hooks.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
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
|
import useSWR, { useSWRConfig } from 'swr';
|
|
7
7
|
import { createContext, useContext, useState } from 'react';
|
|
8
8
|
import { ExtensionProvider } from '@djangocfg/ext-base/hooks';
|
|
9
9
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
10
10
|
import { Mail, Loader2, CheckCircle2, AlertCircle } from 'lucide-react';
|
|
11
|
-
import { Button, Input } from '@djangocfg/ui-
|
|
11
|
+
import { Button, Input } from '@djangocfg/ui-core';
|
|
12
12
|
|
|
13
13
|
var __defProp = Object.defineProperty;
|
|
14
14
|
var __export = (target, all) => {
|
|
@@ -271,7 +271,7 @@ var models_exports7 = {};
|
|
|
271
271
|
// src/api/generated/ext_newsletter/http.ts
|
|
272
272
|
var FetchAdapter = class {
|
|
273
273
|
async request(request) {
|
|
274
|
-
const { method, url, headers, body, params, formData } = request;
|
|
274
|
+
const { method, url, headers, body, params, formData, binaryBody } = request;
|
|
275
275
|
let finalUrl = url;
|
|
276
276
|
if (params) {
|
|
277
277
|
const searchParams = new URLSearchParams();
|
|
@@ -289,6 +289,9 @@ var FetchAdapter = class {
|
|
|
289
289
|
let requestBody;
|
|
290
290
|
if (formData) {
|
|
291
291
|
requestBody = formData;
|
|
292
|
+
} else if (binaryBody) {
|
|
293
|
+
finalHeaders["Content-Type"] = "application/octet-stream";
|
|
294
|
+
requestBody = binaryBody;
|
|
292
295
|
} else if (body) {
|
|
293
296
|
finalHeaders["Content-Type"] = "application/json";
|
|
294
297
|
requestBody = JSON.stringify(body);
|
|
@@ -613,6 +616,7 @@ var APIClient = class {
|
|
|
613
616
|
httpClient;
|
|
614
617
|
logger = null;
|
|
615
618
|
retryConfig = null;
|
|
619
|
+
tokenGetter = null;
|
|
616
620
|
// Sub-clients
|
|
617
621
|
ext_newsletter_bulk_email;
|
|
618
622
|
ext_newsletter_campaigns;
|
|
@@ -624,6 +628,7 @@ var APIClient = class {
|
|
|
624
628
|
constructor(baseUrl, options) {
|
|
625
629
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
626
630
|
this.httpClient = options?.httpClient || new FetchAdapter();
|
|
631
|
+
this.tokenGetter = options?.tokenGetter || null;
|
|
627
632
|
if (options?.loggerConfig !== void 0) {
|
|
628
633
|
this.logger = new APILogger(options.loggerConfig);
|
|
629
634
|
}
|
|
@@ -652,6 +657,19 @@ var APIClient = class {
|
|
|
652
657
|
}
|
|
653
658
|
return null;
|
|
654
659
|
}
|
|
660
|
+
/**
|
|
661
|
+
* Get the base URL for building streaming/download URLs.
|
|
662
|
+
*/
|
|
663
|
+
getBaseUrl() {
|
|
664
|
+
return this.baseUrl;
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Get JWT token for URL authentication (used in streaming endpoints).
|
|
668
|
+
* Returns null if no token getter is configured or no token is available.
|
|
669
|
+
*/
|
|
670
|
+
getToken() {
|
|
671
|
+
return this.tokenGetter ? this.tokenGetter() : null;
|
|
672
|
+
}
|
|
655
673
|
/**
|
|
656
674
|
* Make HTTP request with Django CSRF and session handling.
|
|
657
675
|
* Automatically retries on network errors and 5xx server errors.
|
|
@@ -682,7 +700,7 @@ var APIClient = class {
|
|
|
682
700
|
const headers = {
|
|
683
701
|
...options?.headers || {}
|
|
684
702
|
};
|
|
685
|
-
if (!options?.formData && !headers["Content-Type"]) {
|
|
703
|
+
if (!options?.formData && !options?.binaryBody && !headers["Content-Type"]) {
|
|
686
704
|
headers["Content-Type"] = "application/json";
|
|
687
705
|
}
|
|
688
706
|
if (this.logger) {
|
|
@@ -701,7 +719,8 @@ var APIClient = class {
|
|
|
701
719
|
headers,
|
|
702
720
|
params: options?.params,
|
|
703
721
|
body: options?.body,
|
|
704
|
-
formData: options?.formData
|
|
722
|
+
formData: options?.formData,
|
|
723
|
+
binaryBody: options?.binaryBody
|
|
705
724
|
});
|
|
706
725
|
const duration = Date.now() - startTime;
|
|
707
726
|
if (response.status >= 400) {
|
|
@@ -982,7 +1001,7 @@ var BulkEmailRequestSchema = z.object({
|
|
|
982
1001
|
main_text: z.string().min(1),
|
|
983
1002
|
main_html_content: z.string().optional(),
|
|
984
1003
|
button_text: z.string().max(100).optional(),
|
|
985
|
-
button_url: z.url().optional(),
|
|
1004
|
+
button_url: z.union([z.url(), z.literal("")]).optional(),
|
|
986
1005
|
secondary_text: z.string().optional()
|
|
987
1006
|
});
|
|
988
1007
|
var BulkEmailResponseSchema = z.object({
|
|
@@ -1029,7 +1048,7 @@ var NewsletterCampaignSchema = z.object({
|
|
|
1029
1048
|
main_text: z.string(),
|
|
1030
1049
|
main_html_content: z.string().optional(),
|
|
1031
1050
|
button_text: z.string().max(100).optional(),
|
|
1032
|
-
button_url: z.url().optional(),
|
|
1051
|
+
button_url: z.union([z.url(), z.literal("")]).optional(),
|
|
1033
1052
|
secondary_text: z.string().optional(),
|
|
1034
1053
|
status: z.nativeEnum(NewsletterCampaignStatus),
|
|
1035
1054
|
created_at: z.iso.datetime(),
|
|
@@ -1043,7 +1062,7 @@ var NewsletterCampaignRequestSchema = z.object({
|
|
|
1043
1062
|
main_text: z.string().min(1),
|
|
1044
1063
|
main_html_content: z.string().optional(),
|
|
1045
1064
|
button_text: z.string().max(100).optional(),
|
|
1046
|
-
button_url: z.url().optional(),
|
|
1065
|
+
button_url: z.union([z.url(), z.literal("")]).optional(),
|
|
1047
1066
|
secondary_text: z.string().optional()
|
|
1048
1067
|
});
|
|
1049
1068
|
var NewsletterSubscriptionSchema = z.object({
|
|
@@ -1108,7 +1127,7 @@ var PatchedNewsletterCampaignRequestSchema = z.object({
|
|
|
1108
1127
|
main_text: z.string().min(1).optional(),
|
|
1109
1128
|
main_html_content: z.string().optional(),
|
|
1110
1129
|
button_text: z.string().max(100).optional(),
|
|
1111
|
-
button_url: z.url().optional(),
|
|
1130
|
+
button_url: z.union([z.url(), z.literal("")]).optional(),
|
|
1112
1131
|
secondary_text: z.string().optional()
|
|
1113
1132
|
});
|
|
1114
1133
|
var PatchedUnsubscribeRequestSchema = z.object({
|
|
@@ -1218,15 +1237,28 @@ __export(fetchers_exports, {
|
|
|
1218
1237
|
|
|
1219
1238
|
// src/api/generated/ext_newsletter/api-instance.ts
|
|
1220
1239
|
var globalAPI = null;
|
|
1240
|
+
var autoConfigAttempted = false;
|
|
1241
|
+
function tryAutoConfigureFromEnv() {
|
|
1242
|
+
if (autoConfigAttempted) return;
|
|
1243
|
+
autoConfigAttempted = true;
|
|
1244
|
+
if (globalAPI) return;
|
|
1245
|
+
if (typeof process === "undefined" || !process.env) return;
|
|
1246
|
+
const baseUrl = process.env.NEXT_PUBLIC_API_URL || process.env.VITE_API_URL || process.env.REACT_APP_API_URL || process.env.API_URL;
|
|
1247
|
+
if (baseUrl) {
|
|
1248
|
+
globalAPI = new API(baseUrl);
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1221
1251
|
function getAPIInstance() {
|
|
1252
|
+
tryAutoConfigureFromEnv();
|
|
1222
1253
|
if (!globalAPI) {
|
|
1223
1254
|
throw new Error(
|
|
1224
|
-
'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" })'
|
|
1255
|
+
'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'
|
|
1225
1256
|
);
|
|
1226
1257
|
}
|
|
1227
1258
|
return globalAPI;
|
|
1228
1259
|
}
|
|
1229
1260
|
function isAPIConfigured() {
|
|
1261
|
+
tryAutoConfigureFromEnv();
|
|
1230
1262
|
return globalAPI !== null;
|
|
1231
1263
|
}
|
|
1232
1264
|
function configureAPI(config) {
|
|
@@ -1962,7 +1994,8 @@ var API = class {
|
|
|
1962
1994
|
this._loadTokensFromStorage();
|
|
1963
1995
|
this._client = new APIClient(this.baseUrl, {
|
|
1964
1996
|
retryConfig: this.options?.retryConfig,
|
|
1965
|
-
loggerConfig: this.options?.loggerConfig
|
|
1997
|
+
loggerConfig: this.options?.loggerConfig,
|
|
1998
|
+
tokenGetter: () => this.getToken()
|
|
1966
1999
|
});
|
|
1967
2000
|
this._injectAuthHeader();
|
|
1968
2001
|
this.ext_newsletter_bulk_email = this._client.ext_newsletter_bulk_email;
|
|
@@ -1980,7 +2013,8 @@ var API = class {
|
|
|
1980
2013
|
_reinitClients() {
|
|
1981
2014
|
this._client = new APIClient(this.baseUrl, {
|
|
1982
2015
|
retryConfig: this.options?.retryConfig,
|
|
1983
|
-
loggerConfig: this.options?.loggerConfig
|
|
2016
|
+
loggerConfig: this.options?.loggerConfig,
|
|
2017
|
+
tokenGetter: () => this.getToken()
|
|
1984
2018
|
});
|
|
1985
2019
|
this._injectAuthHeader();
|
|
1986
2020
|
this.ext_newsletter_bulk_email = this._client.ext_newsletter_bulk_email;
|
|
@@ -2077,12 +2111,13 @@ var API = class {
|
|
|
2077
2111
|
return "./schema.json";
|
|
2078
2112
|
}
|
|
2079
2113
|
};
|
|
2114
|
+
initializeExtensionAPI(configureAPI);
|
|
2080
2115
|
var apiNewsletter = createExtensionAPI(API);
|
|
2081
2116
|
|
|
2082
2117
|
// package.json
|
|
2083
2118
|
var package_default = {
|
|
2084
2119
|
name: "@djangocfg/ext-newsletter",
|
|
2085
|
-
version: "1.0.
|
|
2120
|
+
version: "1.0.10",
|
|
2086
2121
|
description: "Newsletter and subscription management extension for DjangoCFG",
|
|
2087
2122
|
keywords: [
|
|
2088
2123
|
"django",
|
|
@@ -2143,7 +2178,7 @@ var package_default = {
|
|
|
2143
2178
|
peerDependencies: {
|
|
2144
2179
|
"@djangocfg/api": "workspace:*",
|
|
2145
2180
|
"@djangocfg/ext-base": "workspace:*",
|
|
2146
|
-
"@djangocfg/ui-
|
|
2181
|
+
"@djangocfg/ui-core": "workspace:*",
|
|
2147
2182
|
consola: "^3.4.2",
|
|
2148
2183
|
"lucide-react": "^0.545.0",
|
|
2149
2184
|
next: "^15.5.7",
|
package/dist/index.cjs
CHANGED
|
@@ -271,7 +271,7 @@ var models_exports7 = {};
|
|
|
271
271
|
// src/api/generated/ext_newsletter/http.ts
|
|
272
272
|
var FetchAdapter = class {
|
|
273
273
|
async request(request) {
|
|
274
|
-
const { method, url, headers, body, params, formData } = request;
|
|
274
|
+
const { method, url, headers, body, params, formData, binaryBody } = request;
|
|
275
275
|
let finalUrl = url;
|
|
276
276
|
if (params) {
|
|
277
277
|
const searchParams = new URLSearchParams();
|
|
@@ -289,6 +289,9 @@ var FetchAdapter = class {
|
|
|
289
289
|
let requestBody;
|
|
290
290
|
if (formData) {
|
|
291
291
|
requestBody = formData;
|
|
292
|
+
} else if (binaryBody) {
|
|
293
|
+
finalHeaders["Content-Type"] = "application/octet-stream";
|
|
294
|
+
requestBody = binaryBody;
|
|
292
295
|
} else if (body) {
|
|
293
296
|
finalHeaders["Content-Type"] = "application/json";
|
|
294
297
|
requestBody = JSON.stringify(body);
|
|
@@ -613,6 +616,7 @@ var APIClient = class {
|
|
|
613
616
|
httpClient;
|
|
614
617
|
logger = null;
|
|
615
618
|
retryConfig = null;
|
|
619
|
+
tokenGetter = null;
|
|
616
620
|
// Sub-clients
|
|
617
621
|
ext_newsletter_bulk_email;
|
|
618
622
|
ext_newsletter_campaigns;
|
|
@@ -624,6 +628,7 @@ var APIClient = class {
|
|
|
624
628
|
constructor(baseUrl, options) {
|
|
625
629
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
626
630
|
this.httpClient = options?.httpClient || new FetchAdapter();
|
|
631
|
+
this.tokenGetter = options?.tokenGetter || null;
|
|
627
632
|
if (options?.loggerConfig !== void 0) {
|
|
628
633
|
this.logger = new APILogger(options.loggerConfig);
|
|
629
634
|
}
|
|
@@ -652,6 +657,19 @@ var APIClient = class {
|
|
|
652
657
|
}
|
|
653
658
|
return null;
|
|
654
659
|
}
|
|
660
|
+
/**
|
|
661
|
+
* Get the base URL for building streaming/download URLs.
|
|
662
|
+
*/
|
|
663
|
+
getBaseUrl() {
|
|
664
|
+
return this.baseUrl;
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Get JWT token for URL authentication (used in streaming endpoints).
|
|
668
|
+
* Returns null if no token getter is configured or no token is available.
|
|
669
|
+
*/
|
|
670
|
+
getToken() {
|
|
671
|
+
return this.tokenGetter ? this.tokenGetter() : null;
|
|
672
|
+
}
|
|
655
673
|
/**
|
|
656
674
|
* Make HTTP request with Django CSRF and session handling.
|
|
657
675
|
* Automatically retries on network errors and 5xx server errors.
|
|
@@ -682,7 +700,7 @@ var APIClient = class {
|
|
|
682
700
|
const headers = {
|
|
683
701
|
...options?.headers || {}
|
|
684
702
|
};
|
|
685
|
-
if (!options?.formData && !headers["Content-Type"]) {
|
|
703
|
+
if (!options?.formData && !options?.binaryBody && !headers["Content-Type"]) {
|
|
686
704
|
headers["Content-Type"] = "application/json";
|
|
687
705
|
}
|
|
688
706
|
if (this.logger) {
|
|
@@ -701,7 +719,8 @@ var APIClient = class {
|
|
|
701
719
|
headers,
|
|
702
720
|
params: options?.params,
|
|
703
721
|
body: options?.body,
|
|
704
|
-
formData: options?.formData
|
|
722
|
+
formData: options?.formData,
|
|
723
|
+
binaryBody: options?.binaryBody
|
|
705
724
|
});
|
|
706
725
|
const duration = Date.now() - startTime;
|
|
707
726
|
if (response.status >= 400) {
|
|
@@ -982,7 +1001,7 @@ var BulkEmailRequestSchema = zod.z.object({
|
|
|
982
1001
|
main_text: zod.z.string().min(1),
|
|
983
1002
|
main_html_content: zod.z.string().optional(),
|
|
984
1003
|
button_text: zod.z.string().max(100).optional(),
|
|
985
|
-
button_url: zod.z.url().optional(),
|
|
1004
|
+
button_url: zod.z.union([zod.z.url(), zod.z.literal("")]).optional(),
|
|
986
1005
|
secondary_text: zod.z.string().optional()
|
|
987
1006
|
});
|
|
988
1007
|
var BulkEmailResponseSchema = zod.z.object({
|
|
@@ -1029,7 +1048,7 @@ var NewsletterCampaignSchema = zod.z.object({
|
|
|
1029
1048
|
main_text: zod.z.string(),
|
|
1030
1049
|
main_html_content: zod.z.string().optional(),
|
|
1031
1050
|
button_text: zod.z.string().max(100).optional(),
|
|
1032
|
-
button_url: zod.z.url().optional(),
|
|
1051
|
+
button_url: zod.z.union([zod.z.url(), zod.z.literal("")]).optional(),
|
|
1033
1052
|
secondary_text: zod.z.string().optional(),
|
|
1034
1053
|
status: zod.z.nativeEnum(NewsletterCampaignStatus),
|
|
1035
1054
|
created_at: zod.z.iso.datetime(),
|
|
@@ -1043,7 +1062,7 @@ var NewsletterCampaignRequestSchema = zod.z.object({
|
|
|
1043
1062
|
main_text: zod.z.string().min(1),
|
|
1044
1063
|
main_html_content: zod.z.string().optional(),
|
|
1045
1064
|
button_text: zod.z.string().max(100).optional(),
|
|
1046
|
-
button_url: zod.z.url().optional(),
|
|
1065
|
+
button_url: zod.z.union([zod.z.url(), zod.z.literal("")]).optional(),
|
|
1047
1066
|
secondary_text: zod.z.string().optional()
|
|
1048
1067
|
});
|
|
1049
1068
|
var NewsletterSubscriptionSchema = zod.z.object({
|
|
@@ -1108,7 +1127,7 @@ var PatchedNewsletterCampaignRequestSchema = zod.z.object({
|
|
|
1108
1127
|
main_text: zod.z.string().min(1).optional(),
|
|
1109
1128
|
main_html_content: zod.z.string().optional(),
|
|
1110
1129
|
button_text: zod.z.string().max(100).optional(),
|
|
1111
|
-
button_url: zod.z.url().optional(),
|
|
1130
|
+
button_url: zod.z.union([zod.z.url(), zod.z.literal("")]).optional(),
|
|
1112
1131
|
secondary_text: zod.z.string().optional()
|
|
1113
1132
|
});
|
|
1114
1133
|
var PatchedUnsubscribeRequestSchema = zod.z.object({
|
|
@@ -1218,15 +1237,28 @@ __export(fetchers_exports, {
|
|
|
1218
1237
|
|
|
1219
1238
|
// src/api/generated/ext_newsletter/api-instance.ts
|
|
1220
1239
|
var globalAPI = null;
|
|
1240
|
+
var autoConfigAttempted = false;
|
|
1241
|
+
function tryAutoConfigureFromEnv() {
|
|
1242
|
+
if (autoConfigAttempted) return;
|
|
1243
|
+
autoConfigAttempted = true;
|
|
1244
|
+
if (globalAPI) return;
|
|
1245
|
+
if (typeof process === "undefined" || !process.env) return;
|
|
1246
|
+
const baseUrl = process.env.NEXT_PUBLIC_API_URL || process.env.VITE_API_URL || process.env.REACT_APP_API_URL || process.env.API_URL;
|
|
1247
|
+
if (baseUrl) {
|
|
1248
|
+
globalAPI = new API(baseUrl);
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1221
1251
|
function getAPIInstance() {
|
|
1252
|
+
tryAutoConfigureFromEnv();
|
|
1222
1253
|
if (!globalAPI) {
|
|
1223
1254
|
throw new Error(
|
|
1224
|
-
'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" })'
|
|
1255
|
+
'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'
|
|
1225
1256
|
);
|
|
1226
1257
|
}
|
|
1227
1258
|
return globalAPI;
|
|
1228
1259
|
}
|
|
1229
1260
|
function isAPIConfigured() {
|
|
1261
|
+
tryAutoConfigureFromEnv();
|
|
1230
1262
|
return globalAPI !== null;
|
|
1231
1263
|
}
|
|
1232
1264
|
function configureAPI(config) {
|
|
@@ -1962,7 +1994,8 @@ var API = class {
|
|
|
1962
1994
|
this._loadTokensFromStorage();
|
|
1963
1995
|
this._client = new APIClient(this.baseUrl, {
|
|
1964
1996
|
retryConfig: this.options?.retryConfig,
|
|
1965
|
-
loggerConfig: this.options?.loggerConfig
|
|
1997
|
+
loggerConfig: this.options?.loggerConfig,
|
|
1998
|
+
tokenGetter: () => this.getToken()
|
|
1966
1999
|
});
|
|
1967
2000
|
this._injectAuthHeader();
|
|
1968
2001
|
this.ext_newsletter_bulk_email = this._client.ext_newsletter_bulk_email;
|
|
@@ -1980,7 +2013,8 @@ var API = class {
|
|
|
1980
2013
|
_reinitClients() {
|
|
1981
2014
|
this._client = new APIClient(this.baseUrl, {
|
|
1982
2015
|
retryConfig: this.options?.retryConfig,
|
|
1983
|
-
loggerConfig: this.options?.loggerConfig
|
|
2016
|
+
loggerConfig: this.options?.loggerConfig,
|
|
2017
|
+
tokenGetter: () => this.getToken()
|
|
1984
2018
|
});
|
|
1985
2019
|
this._injectAuthHeader();
|
|
1986
2020
|
this.ext_newsletter_bulk_email = this._client.ext_newsletter_bulk_email;
|
|
@@ -2077,12 +2111,13 @@ var API = class {
|
|
|
2077
2111
|
return "./schema.json";
|
|
2078
2112
|
}
|
|
2079
2113
|
};
|
|
2114
|
+
api.initializeExtensionAPI(configureAPI);
|
|
2080
2115
|
var apiNewsletter = api.createExtensionAPI(API);
|
|
2081
2116
|
|
|
2082
2117
|
// package.json
|
|
2083
2118
|
var package_default = {
|
|
2084
2119
|
name: "@djangocfg/ext-newsletter",
|
|
2085
|
-
version: "1.0.
|
|
2120
|
+
version: "1.0.10",
|
|
2086
2121
|
description: "Newsletter and subscription management extension for DjangoCFG",
|
|
2087
2122
|
keywords: [
|
|
2088
2123
|
"django",
|
|
@@ -2143,7 +2178,7 @@ var package_default = {
|
|
|
2143
2178
|
peerDependencies: {
|
|
2144
2179
|
"@djangocfg/api": "workspace:*",
|
|
2145
2180
|
"@djangocfg/ext-base": "workspace:*",
|
|
2146
|
-
"@djangocfg/ui-
|
|
2181
|
+
"@djangocfg/ui-core": "workspace:*",
|
|
2147
2182
|
consola: "^3.4.2",
|
|
2148
2183
|
"lucide-react": "^0.545.0",
|
|
2149
2184
|
next: "^15.5.7",
|