vicket 0.1.0 → 1.0.0
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.ts +101 -0
- package/dist/index.js +141 -0
- package/dist/next.d.ts +10 -0
- package/dist/next.js +39 -0
- package/dist/nuxt.d.ts +6 -0
- package/dist/nuxt.js +66 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.js +41 -0
- package/dist/sveltekit.d.ts +21 -0
- package/dist/sveltekit.js +54 -0
- package/package.json +18 -3
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
type TemplateOption = {
|
|
2
|
+
id: string;
|
|
3
|
+
label: string;
|
|
4
|
+
value: string;
|
|
5
|
+
};
|
|
6
|
+
type TemplateQuestion = {
|
|
7
|
+
id: string;
|
|
8
|
+
label: string;
|
|
9
|
+
type: "TEXT" | "TEXTAREA" | "SELECT" | "CHECKBOX" | "DATE" | "FILE";
|
|
10
|
+
required: boolean;
|
|
11
|
+
order: number;
|
|
12
|
+
options?: TemplateOption[];
|
|
13
|
+
};
|
|
14
|
+
type Template = {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
questions: TemplateQuestion[];
|
|
19
|
+
};
|
|
20
|
+
type Article = {
|
|
21
|
+
id: string;
|
|
22
|
+
title: string;
|
|
23
|
+
slug: string;
|
|
24
|
+
content: string;
|
|
25
|
+
};
|
|
26
|
+
type Faq = {
|
|
27
|
+
id: string;
|
|
28
|
+
question: string;
|
|
29
|
+
answer: string;
|
|
30
|
+
};
|
|
31
|
+
type SupportInitResponse = {
|
|
32
|
+
success: boolean;
|
|
33
|
+
data?: {
|
|
34
|
+
website?: {
|
|
35
|
+
name?: string;
|
|
36
|
+
};
|
|
37
|
+
templates: Template[];
|
|
38
|
+
articles?: Article[];
|
|
39
|
+
faqs?: Faq[];
|
|
40
|
+
};
|
|
41
|
+
error?: string;
|
|
42
|
+
};
|
|
43
|
+
type FormValues = {
|
|
44
|
+
email: string;
|
|
45
|
+
title: string;
|
|
46
|
+
answers: Record<string, unknown>;
|
|
47
|
+
};
|
|
48
|
+
type Attachment = {
|
|
49
|
+
id: string;
|
|
50
|
+
original_filename: string;
|
|
51
|
+
url: string;
|
|
52
|
+
};
|
|
53
|
+
type Message = {
|
|
54
|
+
id: string;
|
|
55
|
+
content: string;
|
|
56
|
+
author_type: "reporter" | "user" | "system";
|
|
57
|
+
created_at: string;
|
|
58
|
+
attachments?: Attachment[];
|
|
59
|
+
};
|
|
60
|
+
type TicketAnswer = {
|
|
61
|
+
id: string;
|
|
62
|
+
question_label: string;
|
|
63
|
+
answer: string;
|
|
64
|
+
attachments?: Attachment[];
|
|
65
|
+
};
|
|
66
|
+
type TicketThread = {
|
|
67
|
+
id: string;
|
|
68
|
+
title: string;
|
|
69
|
+
status?: {
|
|
70
|
+
label: string;
|
|
71
|
+
};
|
|
72
|
+
priority?: {
|
|
73
|
+
label: string;
|
|
74
|
+
};
|
|
75
|
+
messages: Message[];
|
|
76
|
+
answers?: TicketAnswer[];
|
|
77
|
+
};
|
|
78
|
+
declare const AUTHOR_LABELS: Record<string, string>;
|
|
79
|
+
declare const initialFormValues: FormValues;
|
|
80
|
+
declare function cn(...classes: (string | boolean | undefined | null)[]): string;
|
|
81
|
+
declare function stripHtml(html: string): string;
|
|
82
|
+
declare function sanitizeHtml(html: string): string;
|
|
83
|
+
declare function formatDate(iso: string): string;
|
|
84
|
+
declare function isFileAnswer(answer: string): boolean;
|
|
85
|
+
declare function formatAnswerText(value: string): string;
|
|
86
|
+
declare function fetchInit(): Promise<NonNullable<SupportInitResponse["data"]>>;
|
|
87
|
+
declare function createTicket(body: {
|
|
88
|
+
email: string;
|
|
89
|
+
title: string;
|
|
90
|
+
templateId: string;
|
|
91
|
+
answers: Record<string, unknown>;
|
|
92
|
+
hasFiles: boolean;
|
|
93
|
+
fileQuestionIds: string[];
|
|
94
|
+
}): Promise<{
|
|
95
|
+
emailLimitReached?: boolean;
|
|
96
|
+
warning?: string;
|
|
97
|
+
}>;
|
|
98
|
+
declare function fetchThread(token: string): Promise<TicketThread>;
|
|
99
|
+
declare function sendReply(token: string, content: string, files: File[]): Promise<void>;
|
|
100
|
+
|
|
101
|
+
export { AUTHOR_LABELS, type Article, type Attachment, type Faq, type FormValues, type Message, type SupportInitResponse, type Template, type TemplateOption, type TemplateQuestion, type TicketAnswer, type TicketThread, cn, createTicket, fetchInit, fetchThread, formatAnswerText, formatDate, initialFormValues, isFileAnswer, sanitizeHtml, sendReply, stripHtml };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var PROXY_BASE = "/api/vicket";
|
|
3
|
+
var AUTHOR_LABELS = {
|
|
4
|
+
reporter: "You",
|
|
5
|
+
user: "Support",
|
|
6
|
+
system: "System"
|
|
7
|
+
};
|
|
8
|
+
var initialFormValues = { email: "", title: "", answers: {} };
|
|
9
|
+
function cn(...classes) {
|
|
10
|
+
return classes.filter(Boolean).join(" ");
|
|
11
|
+
}
|
|
12
|
+
function stripHtml(html) {
|
|
13
|
+
return html.replace(/<[^>]*>/g, "");
|
|
14
|
+
}
|
|
15
|
+
function sanitizeHtml(html) {
|
|
16
|
+
return html.replace(/<script[\s>][\s\S]*?<\/script>/gi, "").replace(/<iframe[\s>][\s\S]*?<\/iframe>/gi, "").replace(/on\w+\s*=\s*"[^"]*"/gi, "").replace(/on\w+\s*=\s*'[^']*'/gi, "").replace(/on\w+\s*=\s*[^\s>]*/gi, "").replace(/javascript\s*:/gi, "");
|
|
17
|
+
}
|
|
18
|
+
function formatDate(iso) {
|
|
19
|
+
try {
|
|
20
|
+
return new Intl.DateTimeFormat("en", {
|
|
21
|
+
month: "short",
|
|
22
|
+
day: "numeric",
|
|
23
|
+
hour: "numeric",
|
|
24
|
+
minute: "2-digit"
|
|
25
|
+
}).format(new Date(iso));
|
|
26
|
+
} catch {
|
|
27
|
+
return iso;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function isFileAnswer(answer) {
|
|
31
|
+
return answer?.includes("__isFile:true") || answer?.includes("map[__isFile");
|
|
32
|
+
}
|
|
33
|
+
function formatAnswerText(value) {
|
|
34
|
+
if (!value) return "";
|
|
35
|
+
const trimmed = value.trim();
|
|
36
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
37
|
+
const rawItems = trimmed.slice(1, -1).trim();
|
|
38
|
+
return rawItems.length > 0 ? rawItems.split(/\s+/).join(", ") : "";
|
|
39
|
+
}
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
async function fetchInit() {
|
|
43
|
+
const response = await fetch(`${PROXY_BASE}/init`, {
|
|
44
|
+
method: "GET",
|
|
45
|
+
cache: "no-store",
|
|
46
|
+
headers: { "Content-Type": "application/json" }
|
|
47
|
+
});
|
|
48
|
+
const payload = await response.json();
|
|
49
|
+
if (!response.ok || !payload?.success || !payload?.data) {
|
|
50
|
+
throw new Error(payload?.error || "Failed to load support data.");
|
|
51
|
+
}
|
|
52
|
+
return payload.data;
|
|
53
|
+
}
|
|
54
|
+
async function createTicket(body) {
|
|
55
|
+
const payload = {
|
|
56
|
+
email: body.email,
|
|
57
|
+
title: body.title,
|
|
58
|
+
templateId: body.templateId,
|
|
59
|
+
answers: { ...body.answers }
|
|
60
|
+
};
|
|
61
|
+
let response;
|
|
62
|
+
if (body.hasFiles) {
|
|
63
|
+
const formData = new FormData();
|
|
64
|
+
const normalizedAnswers = {};
|
|
65
|
+
for (const [questionId, answer] of Object.entries(payload.answers)) {
|
|
66
|
+
if (answer instanceof File) {
|
|
67
|
+
formData.append(`files[${questionId}]`, answer);
|
|
68
|
+
normalizedAnswers[questionId] = "__isFile:true";
|
|
69
|
+
} else {
|
|
70
|
+
normalizedAnswers[questionId] = answer;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
formData.append("data", JSON.stringify({ ...payload, answers: normalizedAnswers }));
|
|
74
|
+
response = await fetch(`${PROXY_BASE}/tickets`, { method: "POST", body: formData });
|
|
75
|
+
} else {
|
|
76
|
+
response = await fetch(`${PROXY_BASE}/tickets`, {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: { "Content-Type": "application/json" },
|
|
79
|
+
body: JSON.stringify(payload)
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const responsePayload = await response.json();
|
|
83
|
+
if (!response.ok || !responsePayload?.success) {
|
|
84
|
+
throw new Error(responsePayload?.error || "Failed to create ticket.");
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
emailLimitReached: responsePayload.data?.email_limit_reached ?? false,
|
|
88
|
+
warning: responsePayload.data?.warning
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
async function fetchThread(token) {
|
|
92
|
+
const response = await fetch(
|
|
93
|
+
`${PROXY_BASE}/ticket?token=${encodeURIComponent(token)}`,
|
|
94
|
+
{ method: "GET", cache: "no-store", headers: { "Content-Type": "application/json" } }
|
|
95
|
+
);
|
|
96
|
+
const payload = await response.json();
|
|
97
|
+
if (!response.ok || !payload?.success || !payload?.data) {
|
|
98
|
+
if (payload?.error_code === "ticket-link-expired") {
|
|
99
|
+
throw new Error("This link has expired. A new secure link has been sent to your email.");
|
|
100
|
+
}
|
|
101
|
+
throw new Error(payload?.error || "Failed to load ticket.");
|
|
102
|
+
}
|
|
103
|
+
return payload.data;
|
|
104
|
+
}
|
|
105
|
+
async function sendReply(token, content, files) {
|
|
106
|
+
const url = `${PROXY_BASE}/ticket/messages?token=${encodeURIComponent(token)}`;
|
|
107
|
+
let response;
|
|
108
|
+
if (files.length > 0) {
|
|
109
|
+
const formData = new FormData();
|
|
110
|
+
formData.append("data", JSON.stringify({ content }));
|
|
111
|
+
for (const file of files) formData.append("files", file);
|
|
112
|
+
response = await fetch(url, { method: "POST", body: formData });
|
|
113
|
+
} else {
|
|
114
|
+
response = await fetch(url, {
|
|
115
|
+
method: "POST",
|
|
116
|
+
headers: { "Content-Type": "application/json" },
|
|
117
|
+
body: JSON.stringify({ content })
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
const payload = await response.json();
|
|
121
|
+
if (!response.ok || !payload?.success) {
|
|
122
|
+
if (payload?.error_code === "ticket-link-expired") {
|
|
123
|
+
throw new Error("This link has expired. A new secure link has been sent to your email.");
|
|
124
|
+
}
|
|
125
|
+
throw new Error(payload?.error || "Failed to send reply.");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
export {
|
|
129
|
+
AUTHOR_LABELS,
|
|
130
|
+
cn,
|
|
131
|
+
createTicket,
|
|
132
|
+
fetchInit,
|
|
133
|
+
fetchThread,
|
|
134
|
+
formatAnswerText,
|
|
135
|
+
formatDate,
|
|
136
|
+
initialFormValues,
|
|
137
|
+
isFileAnswer,
|
|
138
|
+
sanitizeHtml,
|
|
139
|
+
sendReply,
|
|
140
|
+
stripHtml
|
|
141
|
+
};
|
package/dist/next.d.ts
ADDED
package/dist/next.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// src/next.ts
|
|
2
|
+
function createVicketProxy(options) {
|
|
3
|
+
return async function proxy(req, context) {
|
|
4
|
+
const apiUrl = (options?.apiUrl || process.env.VICKET_API_URL || "https://api.vicket.app/api/v1").replace(/\/+$/, "");
|
|
5
|
+
const apiKey = options?.apiKey || process.env.VICKET_API_KEY || "";
|
|
6
|
+
if (!apiKey) {
|
|
7
|
+
return Response.json(
|
|
8
|
+
{ error: "Missing VICKET_API_KEY server environment variable." },
|
|
9
|
+
{ status: 500 }
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
const { path } = await context.params;
|
|
13
|
+
const subpath = path.join("/");
|
|
14
|
+
const url = new URL(`${apiUrl}/public/support/${subpath}`);
|
|
15
|
+
const reqUrl = new URL(req.url);
|
|
16
|
+
reqUrl.searchParams.forEach((value, key) => url.searchParams.set(key, value));
|
|
17
|
+
const headers = { "X-Api-Key": apiKey };
|
|
18
|
+
const contentType = req.headers.get("content-type") || "";
|
|
19
|
+
let body = null;
|
|
20
|
+
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
21
|
+
if (contentType.includes("multipart/form-data")) {
|
|
22
|
+
body = await req.blob();
|
|
23
|
+
headers["Content-Type"] = contentType;
|
|
24
|
+
} else {
|
|
25
|
+
body = await req.text();
|
|
26
|
+
headers["Content-Type"] = contentType || "application/json";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const upstream = await fetch(url.toString(), { method: req.method, headers, body });
|
|
30
|
+
const responseBody = await upstream.arrayBuffer();
|
|
31
|
+
return new Response(responseBody, {
|
|
32
|
+
status: upstream.status,
|
|
33
|
+
headers: { "Content-Type": upstream.headers.get("Content-Type") || "application/json" }
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
createVicketProxy
|
|
39
|
+
};
|
package/dist/nuxt.d.ts
ADDED
package/dist/nuxt.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// src/nuxt.ts
|
|
2
|
+
function createVicketProxy(options) {
|
|
3
|
+
return async (event) => {
|
|
4
|
+
const h3 = await Function('return import("h3")')();
|
|
5
|
+
const { getQuery, readBody, readMultipartFormData, getMethod, createError } = h3;
|
|
6
|
+
const apiUrl = (options?.apiUrl || process.env.VICKET_API_URL || "https://api.vicket.app/api/v1").replace(/\/+$/, "");
|
|
7
|
+
const apiKey = options?.apiKey || process.env.VICKET_API_KEY || "";
|
|
8
|
+
if (!apiKey) {
|
|
9
|
+
throw createError({
|
|
10
|
+
statusCode: 500,
|
|
11
|
+
statusMessage: "Missing VICKET_API_KEY environment variable."
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
const path = event.context.params?.path || "";
|
|
15
|
+
const method = getMethod(event);
|
|
16
|
+
const query = getQuery(event);
|
|
17
|
+
const queryString = new URLSearchParams(
|
|
18
|
+
Object.entries(query).reduce((acc, [k, v]) => {
|
|
19
|
+
if (v !== void 0 && v !== null) acc[k] = String(v);
|
|
20
|
+
return acc;
|
|
21
|
+
}, {})
|
|
22
|
+
).toString();
|
|
23
|
+
const targetUrl = `${apiUrl}/public/support/${path}${queryString ? `?${queryString}` : ""}`;
|
|
24
|
+
const contentType = event.node.req.headers["content-type"] || "";
|
|
25
|
+
const isMultipart = contentType.includes("multipart/form-data");
|
|
26
|
+
let fetchOptions;
|
|
27
|
+
if (method === "GET" || method === "HEAD") {
|
|
28
|
+
fetchOptions = {
|
|
29
|
+
method,
|
|
30
|
+
headers: { "X-Api-Key": apiKey, "Content-Type": "application/json" }
|
|
31
|
+
};
|
|
32
|
+
} else if (isMultipart) {
|
|
33
|
+
const parts = await readMultipartFormData(event);
|
|
34
|
+
const formData = new FormData();
|
|
35
|
+
if (parts) {
|
|
36
|
+
for (const part of parts) {
|
|
37
|
+
if (part.filename) {
|
|
38
|
+
const blob = new Blob([part.data], { type: part.type || "application/octet-stream" });
|
|
39
|
+
formData.append(part.name || "file", blob, part.filename);
|
|
40
|
+
} else {
|
|
41
|
+
formData.append(part.name || "field", part.data.toString("utf-8"));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
fetchOptions = {
|
|
46
|
+
method,
|
|
47
|
+
headers: { "X-Api-Key": apiKey },
|
|
48
|
+
body: formData
|
|
49
|
+
};
|
|
50
|
+
} else {
|
|
51
|
+
const body = await readBody(event);
|
|
52
|
+
fetchOptions = {
|
|
53
|
+
method,
|
|
54
|
+
headers: { "X-Api-Key": apiKey, "Content-Type": "application/json" },
|
|
55
|
+
body: body ? JSON.stringify(body) : void 0
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const response = await fetch(targetUrl, fetchOptions);
|
|
59
|
+
const data = await response.json();
|
|
60
|
+
event.node.res.statusCode = response.status;
|
|
61
|
+
return data;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
createVicketProxy
|
|
66
|
+
};
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SupportInitResponse, TicketThread } from './index.js';
|
|
2
|
+
|
|
3
|
+
declare function createServerClient(options?: {
|
|
4
|
+
apiUrl?: string;
|
|
5
|
+
apiKey?: string;
|
|
6
|
+
}): {
|
|
7
|
+
fetchInit: () => Promise<NonNullable<SupportInitResponse["data"]>>;
|
|
8
|
+
fetchThread: (token: string) => Promise<TicketThread>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export { createServerClient };
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// src/server.ts
|
|
2
|
+
function createServerClient(options) {
|
|
3
|
+
const apiUrl = (options?.apiUrl || process.env.VICKET_API_URL || "https://api.vicket.app/api/v1").replace(/\/+$/, "");
|
|
4
|
+
const apiKey = options?.apiKey || process.env.VICKET_API_KEY || "";
|
|
5
|
+
async function fetchInit() {
|
|
6
|
+
if (!apiKey) throw new Error("Missing VICKET_API_KEY.");
|
|
7
|
+
const res = await fetch(`${apiUrl}/public/support/init`, {
|
|
8
|
+
method: "GET",
|
|
9
|
+
cache: "no-store",
|
|
10
|
+
headers: { "X-Api-Key": apiKey, "Content-Type": "application/json" }
|
|
11
|
+
});
|
|
12
|
+
const payload = await res.json();
|
|
13
|
+
if (!res.ok || !payload?.success || !payload?.data) {
|
|
14
|
+
throw new Error(payload?.error || "Failed to load support data.");
|
|
15
|
+
}
|
|
16
|
+
return payload.data;
|
|
17
|
+
}
|
|
18
|
+
async function fetchThread(token) {
|
|
19
|
+
if (!apiKey) throw new Error("Missing VICKET_API_KEY.");
|
|
20
|
+
const res = await fetch(
|
|
21
|
+
`${apiUrl}/public/support/ticket?token=${encodeURIComponent(token)}`,
|
|
22
|
+
{
|
|
23
|
+
method: "GET",
|
|
24
|
+
cache: "no-store",
|
|
25
|
+
headers: { "X-Api-Key": apiKey, "Content-Type": "application/json" }
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
const payload = await res.json();
|
|
29
|
+
if (!res.ok || !payload?.success || !payload?.data) {
|
|
30
|
+
if (payload?.error_code === "ticket-link-expired") {
|
|
31
|
+
throw new Error("This link has expired. A new secure link has been sent to your email.");
|
|
32
|
+
}
|
|
33
|
+
throw new Error(payload?.error || "Failed to load ticket.");
|
|
34
|
+
}
|
|
35
|
+
return payload.data;
|
|
36
|
+
}
|
|
37
|
+
return { fetchInit, fetchThread };
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
createServerClient
|
|
41
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
declare function createVicketProxy(options?: {
|
|
2
|
+
apiUrl?: string;
|
|
3
|
+
apiKey?: string;
|
|
4
|
+
}): {
|
|
5
|
+
GET: ({ params, url }: {
|
|
6
|
+
params: {
|
|
7
|
+
path: string;
|
|
8
|
+
};
|
|
9
|
+
url: URL;
|
|
10
|
+
request: Request;
|
|
11
|
+
}) => Promise<Response>;
|
|
12
|
+
POST: ({ params, url, request }: {
|
|
13
|
+
params: {
|
|
14
|
+
path: string;
|
|
15
|
+
};
|
|
16
|
+
url: URL;
|
|
17
|
+
request: Request;
|
|
18
|
+
}) => Promise<Response>;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { createVicketProxy };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// src/sveltekit.ts
|
|
2
|
+
function createVicketProxy(options) {
|
|
3
|
+
const getConfig = () => {
|
|
4
|
+
const apiUrl = (options?.apiUrl || process.env.VICKET_API_URL || "https://api.vicket.app/api/v1").replace(/\/+$/, "");
|
|
5
|
+
const apiKey = options?.apiKey || process.env.VICKET_API_KEY || "";
|
|
6
|
+
return { apiUrl, apiKey };
|
|
7
|
+
};
|
|
8
|
+
async function handle(request, params, url) {
|
|
9
|
+
const { apiUrl, apiKey } = getConfig();
|
|
10
|
+
if (!apiKey) {
|
|
11
|
+
return Response.json(
|
|
12
|
+
{ success: false, error: "Missing VICKET_API_KEY." },
|
|
13
|
+
{ status: 500 }
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
const path = params.path || "";
|
|
17
|
+
const query = url.searchParams.toString();
|
|
18
|
+
const target = `${apiUrl}/public/support/${path}${query ? `?${query}` : ""}`;
|
|
19
|
+
const contentType = request.headers.get("Content-Type") || "";
|
|
20
|
+
const isFormData = contentType.includes("multipart/form-data");
|
|
21
|
+
let upstream;
|
|
22
|
+
if (request.method === "GET" || request.method === "HEAD") {
|
|
23
|
+
upstream = await fetch(target, {
|
|
24
|
+
method: request.method,
|
|
25
|
+
headers: { "X-Api-Key": apiKey, "Content-Type": "application/json" }
|
|
26
|
+
});
|
|
27
|
+
} else if (isFormData) {
|
|
28
|
+
const formData = await request.formData();
|
|
29
|
+
upstream = await fetch(target, {
|
|
30
|
+
method: request.method,
|
|
31
|
+
headers: { "X-Api-Key": apiKey },
|
|
32
|
+
body: formData
|
|
33
|
+
});
|
|
34
|
+
} else {
|
|
35
|
+
const body = await request.text();
|
|
36
|
+
upstream = await fetch(target, {
|
|
37
|
+
method: request.method,
|
|
38
|
+
headers: { "X-Api-Key": apiKey, "Content-Type": "application/json" },
|
|
39
|
+
body
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
const responseBody = await upstream.text();
|
|
43
|
+
return new Response(responseBody, {
|
|
44
|
+
status: upstream.status,
|
|
45
|
+
headers: { "Content-Type": upstream.headers.get("Content-Type") || "application/json" }
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const GET = ({ params, url }) => handle(new Request(url), params, url);
|
|
49
|
+
const POST = ({ params, url, request }) => handle(request, params, url);
|
|
50
|
+
return { GET, POST };
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
createVicketProxy
|
|
54
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vicket",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Vicket support widget SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -15,23 +15,38 @@
|
|
|
15
15
|
"./next": {
|
|
16
16
|
"import": "./dist/next.js",
|
|
17
17
|
"types": "./dist/next.d.ts"
|
|
18
|
+
},
|
|
19
|
+
"./nuxt": {
|
|
20
|
+
"import": "./dist/nuxt.js",
|
|
21
|
+
"types": "./dist/nuxt.d.ts"
|
|
22
|
+
},
|
|
23
|
+
"./sveltekit": {
|
|
24
|
+
"import": "./dist/sveltekit.js",
|
|
25
|
+
"types": "./dist/sveltekit.d.ts"
|
|
18
26
|
}
|
|
19
27
|
},
|
|
20
|
-
"files": [
|
|
28
|
+
"files": [
|
|
29
|
+
"dist"
|
|
30
|
+
],
|
|
21
31
|
"scripts": {
|
|
22
32
|
"build": "tsup",
|
|
23
33
|
"dev": "tsup --watch"
|
|
24
34
|
},
|
|
25
35
|
"devDependencies": {
|
|
36
|
+
"@types/node": "^22.0.0",
|
|
26
37
|
"tsup": "^8.0.0",
|
|
27
38
|
"typescript": "^5.9.0"
|
|
28
39
|
},
|
|
29
40
|
"peerDependencies": {
|
|
30
|
-
"next": ">=14.0.0"
|
|
41
|
+
"next": ">=14.0.0",
|
|
42
|
+
"h3": ">=1.0.0"
|
|
31
43
|
},
|
|
32
44
|
"peerDependenciesMeta": {
|
|
33
45
|
"next": {
|
|
34
46
|
"optional": true
|
|
47
|
+
},
|
|
48
|
+
"h3": {
|
|
49
|
+
"optional": true
|
|
35
50
|
}
|
|
36
51
|
}
|
|
37
52
|
}
|