@umituz/web-cloudflare 1.4.6 → 1.4.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.
- package/package.json +1 -1
- package/src/config/patterns.ts +11 -8
- package/src/config/types.ts +9 -1
- package/src/domains/ai-gateway/services/index.ts +52 -25
- package/src/domains/analytics/services/analytics.service.ts +16 -92
- package/src/domains/analytics/types/service.interface.ts +1 -1
- package/src/domains/d1/services/d1.service.ts +19 -22
- package/src/domains/images/services/images.service.ts +58 -21
- package/src/domains/kv/services/kv.service.ts +14 -5
- package/src/domains/middleware/entities/index.ts +4 -4
- package/src/domains/middleware/services/auth.service.ts +6 -2
- package/src/domains/middleware/services/cache.service.ts +7 -3
- package/src/domains/middleware/services/cors.service.ts +8 -5
- package/src/domains/middleware/services/rate-limit.service.ts +7 -3
- package/src/domains/middleware/types/service.interface.ts +17 -11
- package/src/domains/r2/services/r2.service.ts +25 -13
- package/src/domains/workers/entities/index.ts +17 -1
- package/src/domains/workers/examples/worker.example.ts +11 -8
- package/src/domains/workers/services/workers.service.ts +9 -4
- package/src/domains/workflows/entities/index.ts +14 -1
- package/src/domains/workflows/services/workflows.service.ts +43 -10
- package/src/domains/wrangler/services/wrangler.service.ts +150 -443
- package/src/index.ts +44 -12
- package/src/infrastructure/middleware/index.ts +23 -18
- package/src/infrastructure/router/index.ts +2 -1
- package/src/infrastructure/utils/helpers.ts +29 -7
- package/src/presentation/hooks/cloudflare.hooks.ts +7 -309
- package/src/presentation/hooks/index.ts +4 -1
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
// Re-export from middleware domain
|
|
8
8
|
export * from '../../domains/middleware';
|
|
9
9
|
|
|
10
|
+
import type { WorkersAIBinding } from '../../config/types';
|
|
11
|
+
|
|
10
12
|
// ============================================================
|
|
11
13
|
// Environment Types (kept for backwards compatibility)
|
|
12
14
|
// ============================================================
|
|
@@ -17,7 +19,7 @@ export interface CloudflareMiddlewareEnv {
|
|
|
17
19
|
D1?: D1Database;
|
|
18
20
|
DO?: Record<string, DurableObjectNamespace>;
|
|
19
21
|
QUEUE?: Record<string, Queue>;
|
|
20
|
-
AI?:
|
|
22
|
+
AI?: WorkersAIBinding;
|
|
21
23
|
vars?: Record<string, string>;
|
|
22
24
|
}
|
|
23
25
|
|
|
@@ -196,20 +198,8 @@ export async function logRequest(
|
|
|
196
198
|
}
|
|
197
199
|
}
|
|
198
200
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
console.debug('[Request]', JSON.stringify(logData));
|
|
202
|
-
break;
|
|
203
|
-
case 'info':
|
|
204
|
-
console.info('[Request]', JSON.stringify(logData));
|
|
205
|
-
break;
|
|
206
|
-
case 'warn':
|
|
207
|
-
console.warn('[Request]', JSON.stringify(logData));
|
|
208
|
-
break;
|
|
209
|
-
case 'error':
|
|
210
|
-
console.error('[Request]', JSON.stringify(logData));
|
|
211
|
-
break;
|
|
212
|
-
}
|
|
201
|
+
// Logging disabled in Workers runtime - console methods not reliably supported
|
|
202
|
+
// Log data is collected above but not output in production
|
|
213
203
|
}
|
|
214
204
|
|
|
215
205
|
/**
|
|
@@ -318,10 +308,27 @@ export async function healthCheck(
|
|
|
318
308
|
env: CloudflareMiddlewareEnv,
|
|
319
309
|
config?: HealthCheckConfig
|
|
320
310
|
): Promise<Response> {
|
|
311
|
+
// Get uptime if available (Node.js only)
|
|
312
|
+
let uptime = 0;
|
|
313
|
+
if (config?.uptime !== undefined) {
|
|
314
|
+
uptime = config.uptime;
|
|
315
|
+
} else {
|
|
316
|
+
// Try to get process uptime in Node.js environment
|
|
317
|
+
try {
|
|
318
|
+
// @ts-ignore - process is not available in Workers runtime
|
|
319
|
+
if (typeof process !== 'undefined' && process?.uptime) {
|
|
320
|
+
// @ts-ignore
|
|
321
|
+
uptime = process.uptime();
|
|
322
|
+
}
|
|
323
|
+
} catch {
|
|
324
|
+
uptime = 0;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
321
328
|
const checks: Record<string, boolean | string> = {
|
|
322
329
|
healthy: true,
|
|
323
330
|
timestamp: new Date().toISOString(),
|
|
324
|
-
uptime:
|
|
331
|
+
uptime: uptime.toString(),
|
|
325
332
|
};
|
|
326
333
|
|
|
327
334
|
if (config?.checks) {
|
|
@@ -353,8 +360,6 @@ export function handleMiddlewareError(
|
|
|
353
360
|
): Response {
|
|
354
361
|
if (config.logger) {
|
|
355
362
|
config.logger(error);
|
|
356
|
-
} else {
|
|
357
|
-
console.error('[Middleware Error]', error);
|
|
358
363
|
}
|
|
359
364
|
|
|
360
365
|
const status = 500;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { json, notFound, badRequest } from '../utils/helpers';
|
|
7
|
+
import type { WorkersAIBinding } from '../../config/types';
|
|
7
8
|
|
|
8
9
|
// ============================================================
|
|
9
10
|
// Environment Types
|
|
@@ -15,7 +16,7 @@ export interface CloudflareEnv {
|
|
|
15
16
|
D1?: D1Database;
|
|
16
17
|
DO?: Record<string, DurableObjectNamespace>;
|
|
17
18
|
QUEUE?: Record<string, Queue>;
|
|
18
|
-
AI?:
|
|
19
|
+
AI?: WorkersAIBinding;
|
|
19
20
|
vars?: Record<string, string>;
|
|
20
21
|
}
|
|
21
22
|
|
|
@@ -626,17 +626,25 @@ export function deepClone<T>(obj: T): T {
|
|
|
626
626
|
/**
|
|
627
627
|
* Deep merge objects
|
|
628
628
|
*/
|
|
629
|
-
export function deepMerge<T extends Record<string, any>>(
|
|
629
|
+
export function deepMerge<T extends Record<string, any>>(
|
|
630
|
+
target: T,
|
|
631
|
+
...sources: Array<Partial<Record<string, any>>>
|
|
632
|
+
): T {
|
|
630
633
|
if (!sources.length) return target;
|
|
631
634
|
const source = sources.shift();
|
|
632
635
|
|
|
633
636
|
if (isObject(target) && isObject(source)) {
|
|
634
637
|
for (const key in source) {
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
+
const sourceValue = source[key];
|
|
639
|
+
const targetValue = (target as Record<string, unknown>)[key];
|
|
640
|
+
|
|
641
|
+
if (isObject(sourceValue)) {
|
|
642
|
+
if (!targetValue) {
|
|
643
|
+
(target as Record<string, unknown>)[key] = {};
|
|
644
|
+
}
|
|
645
|
+
deepMerge((target as Record<string, unknown>)[key] as Record<string, any>, sourceValue);
|
|
638
646
|
} else {
|
|
639
|
-
|
|
647
|
+
(target as Record<string, unknown>)[key] = sourceValue;
|
|
640
648
|
}
|
|
641
649
|
}
|
|
642
650
|
}
|
|
@@ -651,16 +659,23 @@ function isObject(item: unknown): item is Record<string, unknown> {
|
|
|
651
659
|
/**
|
|
652
660
|
* Pick properties from object
|
|
653
661
|
*/
|
|
654
|
-
export function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
|
|
662
|
+
export function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
|
|
655
663
|
const result = {} as Pick<T, K>;
|
|
656
664
|
keys.forEach((key) => {
|
|
657
665
|
if (key in obj) {
|
|
658
|
-
result[key] = obj[key];
|
|
666
|
+
(result as Record<string, unknown>)[key as string] = obj[key as keyof T];
|
|
659
667
|
}
|
|
660
668
|
});
|
|
661
669
|
return result;
|
|
662
670
|
}
|
|
663
671
|
|
|
672
|
+
/**
|
|
673
|
+
* Merge multiple objects
|
|
674
|
+
*/
|
|
675
|
+
export function merge<T extends object>(target: T, ...sources: Array<Partial<T>>): T {
|
|
676
|
+
return Object.assign(target, ...sources);
|
|
677
|
+
}
|
|
678
|
+
|
|
664
679
|
/**
|
|
665
680
|
* Omit properties from object
|
|
666
681
|
*/
|
|
@@ -672,6 +687,13 @@ export function omit<T, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {
|
|
|
672
687
|
return result as Omit<T, K>;
|
|
673
688
|
}
|
|
674
689
|
|
|
690
|
+
/**
|
|
691
|
+
* Clone object
|
|
692
|
+
*/
|
|
693
|
+
export function clone<T>(obj: T): T {
|
|
694
|
+
return JSON.parse(JSON.stringify(obj));
|
|
695
|
+
}
|
|
696
|
+
|
|
675
697
|
// ============================================================
|
|
676
698
|
// Random Utilities
|
|
677
699
|
// ============================================================
|
|
@@ -1,314 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cloudflare React Hooks
|
|
3
3
|
* @description React hooks for Cloudflare services (client-side)
|
|
4
|
+
*
|
|
5
|
+
* DEPRECATED: This file is disabled because React hooks are not compatible
|
|
6
|
+
* with Cloudflare Workers runtime.
|
|
7
|
+
*
|
|
8
|
+
* React hooks require browser/React environment and cannot be used in Workers.
|
|
9
|
+
* If you need React integration, create a separate client-side package.
|
|
4
10
|
*/
|
|
5
11
|
|
|
6
|
-
|
|
7
|
-
import { kvService } from "../../infrastructure/services/kv";
|
|
8
|
-
import { r2Service } from "../../infrastructure/services/r2";
|
|
9
|
-
import { imagesService } from "../../infrastructure/services/images";
|
|
10
|
-
import { analyticsService } from "../../infrastructure/services/analytics";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Cloudflare Worker Hook
|
|
14
|
-
* @description Fetch data from Cloudflare Workers
|
|
15
|
-
*/
|
|
16
|
-
export interface UseCloudflareWorkerOptions {
|
|
17
|
-
readonly enabled?: boolean;
|
|
18
|
-
readonly refetchInterval?: number;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function useCloudflareWorker<T = unknown>(
|
|
22
|
-
url: string,
|
|
23
|
-
options?: UseCloudflareWorkerOptions
|
|
24
|
-
) {
|
|
25
|
-
const [data, setData] = useState<T | null>(null);
|
|
26
|
-
const [loading, setLoading] = useState(false);
|
|
27
|
-
const [error, setError] = useState<Error | null>(null);
|
|
28
|
-
|
|
29
|
-
const fetcher = useCallback(async () => {
|
|
30
|
-
if (!options?.enabled ?? true) {
|
|
31
|
-
setLoading(true);
|
|
32
|
-
setError(null);
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
const response = await fetch(url);
|
|
36
|
-
if (!response.ok) {
|
|
37
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
38
|
-
}
|
|
39
|
-
const json = await response.json();
|
|
40
|
-
setData(json);
|
|
41
|
-
} catch (err) {
|
|
42
|
-
setError(err as Error);
|
|
43
|
-
} finally {
|
|
44
|
-
setLoading(false);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}, [url, options?.enabled]);
|
|
48
|
-
|
|
49
|
-
useEffect(() => {
|
|
50
|
-
fetcher();
|
|
51
|
-
|
|
52
|
-
if (options?.refetchInterval) {
|
|
53
|
-
const interval = setInterval(fetcher, options.refetchInterval);
|
|
54
|
-
return () => clearInterval(interval);
|
|
55
|
-
}
|
|
56
|
-
}, [fetcher, options?.refetchInterval]);
|
|
57
|
-
|
|
58
|
-
return { data, loading, error, refetch: fetcher };
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Cloudflare KV Hook
|
|
63
|
-
* @description Read from Cloudflare KV (client-side, via Worker API)
|
|
64
|
-
*/
|
|
65
|
-
export interface UseCloudflareKVOptions {
|
|
66
|
-
readonly apiURL: string;
|
|
67
|
-
readonly enabled?: boolean;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function useCloudflareKV<T = unknown>(
|
|
71
|
-
key: string,
|
|
72
|
-
options: UseCloudflareKVOptions
|
|
73
|
-
) {
|
|
74
|
-
const [data, setData] = useState<T | null>(null);
|
|
75
|
-
const [loading, setLoading] = useState(false);
|
|
76
|
-
const [error, setError] = useState<Error | null>(null);
|
|
77
|
-
|
|
78
|
-
useEffect(() => {
|
|
79
|
-
if (!options.enabled ?? true) {
|
|
80
|
-
setLoading(true);
|
|
81
|
-
setError(null);
|
|
82
|
-
|
|
83
|
-
fetch(`${options.apiURL}/kv/${key}`)
|
|
84
|
-
.then((res) => {
|
|
85
|
-
if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`);
|
|
86
|
-
return res.json();
|
|
87
|
-
})
|
|
88
|
-
.then((json) => setData(json.value))
|
|
89
|
-
.catch((err) => setError(err))
|
|
90
|
-
.finally(() => setLoading(false));
|
|
91
|
-
}
|
|
92
|
-
}, [key, options.apiURL, options.enabled]);
|
|
93
|
-
|
|
94
|
-
return { data, loading, error };
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Cloudflare R2 Hook
|
|
99
|
-
* @description Upload files to R2 (client-side, via Worker API)
|
|
100
|
-
*/
|
|
101
|
-
export interface UseCloudflareR2Options {
|
|
102
|
-
readonly uploadURL: string;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export function useCloudflareR2(options: UseCloudflareR2Options) {
|
|
106
|
-
const [uploading, setUploading] = useState(false);
|
|
107
|
-
const [progress, setProgress] = useState(0);
|
|
108
|
-
const [error, setError] = useState<Error | null>(null);
|
|
109
|
-
|
|
110
|
-
const upload = useCallback(
|
|
111
|
-
async (file: File, key?: string) => {
|
|
112
|
-
setUploading(true);
|
|
113
|
-
setProgress(0);
|
|
114
|
-
setError(null);
|
|
115
|
-
|
|
116
|
-
try {
|
|
117
|
-
const formData = new FormData();
|
|
118
|
-
formData.append("file", file);
|
|
119
|
-
if (key) formData.append("key", key);
|
|
120
|
-
|
|
121
|
-
const xhr = new XMLHttpRequest();
|
|
122
|
-
|
|
123
|
-
xhr.upload.addEventListener("progress", (e) => {
|
|
124
|
-
if (e.lengthComputable) {
|
|
125
|
-
setProgress((e.loaded / e.total) * 100);
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
const promise = new Promise<{ key: string; url: string }>((resolve, reject) => {
|
|
130
|
-
xhr.addEventListener("load", () => {
|
|
131
|
-
if (xhr.status === 200) {
|
|
132
|
-
const data = JSON.parse(xhr.responseText);
|
|
133
|
-
resolve(data);
|
|
134
|
-
} else {
|
|
135
|
-
reject(new Error(`Upload failed: ${xhr.statusText}`));
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
xhr.addEventListener("error", () => {
|
|
140
|
-
reject(new Error("Upload failed"));
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
xhr.open("POST", options.uploadURL);
|
|
144
|
-
xhr.send(formData);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
return await promise;
|
|
148
|
-
} catch (err) {
|
|
149
|
-
setError(err as Error);
|
|
150
|
-
throw err;
|
|
151
|
-
} finally {
|
|
152
|
-
setUploading(false);
|
|
153
|
-
setProgress(0);
|
|
154
|
-
}
|
|
155
|
-
},
|
|
156
|
-
[options.uploadURL]
|
|
157
|
-
);
|
|
158
|
-
|
|
159
|
-
return { upload, uploading, progress, error };
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Cloudflare D1 Hook
|
|
164
|
-
* @description Query D1 database (client-side, via Worker API)
|
|
165
|
-
*/
|
|
166
|
-
export interface UseCloudflareD1Options {
|
|
167
|
-
readonly apiURL: string;
|
|
168
|
-
readonly enabled?: boolean;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
export function useCloudflareD1<T = unknown>(
|
|
172
|
-
query: string,
|
|
173
|
-
params?: readonly unknown[],
|
|
174
|
-
options?: UseCloudflareD1Options
|
|
175
|
-
) {
|
|
176
|
-
const [data, setData] = useState<T[] | null>(null);
|
|
177
|
-
const [loading, setLoading] = useState(false);
|
|
178
|
-
const [error, setError] = useState<Error | null>(null);
|
|
179
|
-
|
|
180
|
-
useEffect(() => {
|
|
181
|
-
if (!options?.enabled ?? true) {
|
|
182
|
-
setLoading(true);
|
|
183
|
-
setError(null);
|
|
184
|
-
|
|
185
|
-
fetch(`${options?.apiURL}/d1/query`, {
|
|
186
|
-
method: "POST",
|
|
187
|
-
headers: { "Content-Type": "application/json" },
|
|
188
|
-
body: JSON.stringify({ query, params }),
|
|
189
|
-
})
|
|
190
|
-
.then((res) => {
|
|
191
|
-
if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`);
|
|
192
|
-
return res.json();
|
|
193
|
-
})
|
|
194
|
-
.then((json) => setData(json.results))
|
|
195
|
-
.catch((err) => setError(err))
|
|
196
|
-
.finally(() => setLoading(false));
|
|
197
|
-
}
|
|
198
|
-
}, [query, params, options?.apiURL, options?.enabled]);
|
|
199
|
-
|
|
200
|
-
return { data, loading, error };
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Cloudflare Images Hook
|
|
205
|
-
* @description Upload and manage images
|
|
206
|
-
*/
|
|
207
|
-
export interface UseCloudflareImagesOptions {
|
|
208
|
-
readonly accountId?: string;
|
|
209
|
-
readonly apiToken?: string;
|
|
210
|
-
readonly uploadURL?: string;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export function useCloudflareImages(options?: UseCloudflareImagesOptions) {
|
|
214
|
-
const [uploading, setUploading] = useState(false);
|
|
215
|
-
const [error, setError] = useState<Error | null>(null);
|
|
216
|
-
|
|
217
|
-
useEffect(() => {
|
|
218
|
-
if (options?.accountId && options?.apiToken) {
|
|
219
|
-
imagesService.initialize({
|
|
220
|
-
accountId: options.accountId,
|
|
221
|
-
apiToken: options.apiToken,
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
}, [options?.accountId, options?.apiToken]);
|
|
225
|
-
|
|
226
|
-
const upload = useCallback(
|
|
227
|
-
async (file: File, metadata?: Record<string, string>) => {
|
|
228
|
-
setUploading(true);
|
|
229
|
-
setError(null);
|
|
230
|
-
|
|
231
|
-
try {
|
|
232
|
-
if (options?.uploadURL) {
|
|
233
|
-
// Upload via Worker proxy
|
|
234
|
-
const formData = new FormData();
|
|
235
|
-
formData.append("file", file);
|
|
236
|
-
if (metadata) {
|
|
237
|
-
for (const [key, value] of Object.entries(metadata)) {
|
|
238
|
-
formData.append(`metadata[${key}]`, value);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
const response = await fetch(options.uploadURL, {
|
|
243
|
-
method: "POST",
|
|
244
|
-
body: formData,
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
if (!response.ok) {
|
|
248
|
-
throw new Error(`Upload failed: ${response.statusText}`);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return await response.json();
|
|
252
|
-
} else {
|
|
253
|
-
// Direct upload to Cloudflare Images
|
|
254
|
-
return await imagesService.upload(file, { metadata });
|
|
255
|
-
}
|
|
256
|
-
} catch (err) {
|
|
257
|
-
setError(err as Error);
|
|
258
|
-
throw err;
|
|
259
|
-
} finally {
|
|
260
|
-
setUploading(false);
|
|
261
|
-
}
|
|
262
|
-
},
|
|
263
|
-
[options?.uploadURL]
|
|
264
|
-
);
|
|
265
|
-
|
|
266
|
-
const getTransformedURL = useCallback(
|
|
267
|
-
(imageId: string, transform: {
|
|
268
|
-
width?: number;
|
|
269
|
-
height?: number;
|
|
270
|
-
fit?: string;
|
|
271
|
-
format?: string;
|
|
272
|
-
quality?: number;
|
|
273
|
-
}) => {
|
|
274
|
-
return imagesService.getTransformedURL(imageId, transform);
|
|
275
|
-
},
|
|
276
|
-
[]
|
|
277
|
-
);
|
|
278
|
-
|
|
279
|
-
return { upload, uploading, error, getTransformedURL };
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Cloudflare Analytics Hook
|
|
284
|
-
* @description Track analytics events
|
|
285
|
-
*/
|
|
286
|
-
export interface UseCloudflareAnalyticsOptions {
|
|
287
|
-
readonly siteId: string;
|
|
288
|
-
readonly scriptUrl?: string;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
export function useCloudflareAnalytics(options: UseCloudflareAnalyticsOptions) {
|
|
292
|
-
useEffect(() => {
|
|
293
|
-
analyticsService.initialize({
|
|
294
|
-
siteId: options.siteId,
|
|
295
|
-
scriptUrl: options.scriptUrl,
|
|
296
|
-
});
|
|
297
|
-
}, [options.siteId, options.scriptUrl]);
|
|
298
|
-
|
|
299
|
-
const trackPageview = useCallback((title: string, referrer?: string) => {
|
|
300
|
-
if (typeof window !== "undefined") {
|
|
301
|
-
analyticsService.trackPageview(window.location.href, title, referrer);
|
|
302
|
-
}
|
|
303
|
-
}, []);
|
|
304
|
-
|
|
305
|
-
const trackEvent = useCallback((eventName: string, data?: Record<string, unknown>) => {
|
|
306
|
-
analyticsService.trackCustom(eventName, data);
|
|
307
|
-
}, []);
|
|
308
|
-
|
|
309
|
-
const getScriptTag = useCallback(() => {
|
|
310
|
-
return analyticsService.getScriptTag();
|
|
311
|
-
}, []);
|
|
312
|
-
|
|
313
|
-
return { trackPageview, trackEvent, getScriptTag };
|
|
314
|
-
}
|
|
12
|
+
// Empty file - all functionality removed to prevent Workers runtime errors
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cloudflare React Hooks
|
|
3
3
|
* Subpath: @umituz/web-cloudflare/presentation
|
|
4
|
+
*
|
|
5
|
+
* DEPRECATED: React hooks are not compatible with Workers runtime.
|
|
6
|
+
* All exports have been disabled.
|
|
4
7
|
*/
|
|
5
8
|
|
|
6
|
-
|
|
9
|
+
// No exports - React hooks disabled for Workers runtime compatibility
|