syncsnap 1.0.0 → 1.0.2
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/README.md +1 -1
- package/dist/chunk-SUNHYVAG.js +99 -0
- package/dist/chunk-SUNHYVAG.js.map +1 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +5 -82
- package/dist/index.js.map +1 -1
- package/dist/next.js +79 -30
- package/dist/next.js.map +1 -1
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// src/client.ts
|
|
2
|
+
var SYNCSNAP_API_BASE_URL = "https://api.syncsnap.xyz/api";
|
|
3
|
+
var SyncsnapRateLimitError = class _SyncsnapRateLimitError extends Error {
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.statusCode = 429;
|
|
7
|
+
this.name = "SyncsnapRateLimitError";
|
|
8
|
+
Object.setPrototypeOf(this, _SyncsnapRateLimitError.prototype);
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
var SyncsnapServer = class {
|
|
12
|
+
constructor(apiVersion = "v1") {
|
|
13
|
+
this.baseUrl = `${SYNCSNAP_API_BASE_URL}/${apiVersion}`;
|
|
14
|
+
this.token = process.env.SYNCSNAP_TOKEN;
|
|
15
|
+
this.fetcher = fetch;
|
|
16
|
+
}
|
|
17
|
+
authHeaders() {
|
|
18
|
+
return {
|
|
19
|
+
"Content-Type": "application/json",
|
|
20
|
+
"X-API-KEY": this.token
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
async requestJson(url, init) {
|
|
24
|
+
const res = await this.fetcher(url, init);
|
|
25
|
+
const data = await res.json().catch(() => ({}));
|
|
26
|
+
if (!res.ok) {
|
|
27
|
+
const message = typeof data === "object" && data && "error" in data && data.error ? String(data.error) : `Syncsnap request failed (${res.status})`;
|
|
28
|
+
if (res.status === 429) {
|
|
29
|
+
throw new SyncsnapRateLimitError(message);
|
|
30
|
+
}
|
|
31
|
+
throw new Error(message);
|
|
32
|
+
}
|
|
33
|
+
return data;
|
|
34
|
+
}
|
|
35
|
+
async createJob() {
|
|
36
|
+
const url = `${this.baseUrl}/jobs`;
|
|
37
|
+
return this.requestJson(url, {
|
|
38
|
+
method: "POST",
|
|
39
|
+
headers: this.authHeaders()
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
async getJob(jobId) {
|
|
43
|
+
const url = `${this.baseUrl}/jobs/${encodeURIComponent(jobId)}`;
|
|
44
|
+
return this.requestJson(url, {
|
|
45
|
+
method: "GET",
|
|
46
|
+
headers: this.authHeaders()
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async getUploadUrl(jobId, options) {
|
|
50
|
+
const url = `${this.baseUrl}/jobs/${encodeURIComponent(
|
|
51
|
+
jobId
|
|
52
|
+
)}/presigned-upload-url`;
|
|
53
|
+
return this.requestJson(url, {
|
|
54
|
+
method: "POST",
|
|
55
|
+
headers: this.authHeaders(),
|
|
56
|
+
body: JSON.stringify({
|
|
57
|
+
file_name: options.fileName,
|
|
58
|
+
expiration: options.expirationMinutes
|
|
59
|
+
})
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async getDownloadUrl(jobId, options) {
|
|
63
|
+
const url = `${this.baseUrl}/jobs/${encodeURIComponent(
|
|
64
|
+
jobId
|
|
65
|
+
)}/presigned-download-url`;
|
|
66
|
+
return this.requestJson(url, {
|
|
67
|
+
method: "POST",
|
|
68
|
+
headers: this.authHeaders(),
|
|
69
|
+
body: JSON.stringify({
|
|
70
|
+
expiration: options?.expirationMinutes
|
|
71
|
+
})
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async waitForJobCompletion(jobId, options = {}) {
|
|
75
|
+
const intervalMs = options.intervalMs ?? 2e3;
|
|
76
|
+
const timeoutMs = options.timeoutMs ?? 12e4;
|
|
77
|
+
const startedAt = Date.now();
|
|
78
|
+
while (true) {
|
|
79
|
+
if (options.signal?.aborted) {
|
|
80
|
+
throw new Error("Polling aborted");
|
|
81
|
+
}
|
|
82
|
+
if (Date.now() - startedAt > timeoutMs) {
|
|
83
|
+
throw new Error("Polling timed out");
|
|
84
|
+
}
|
|
85
|
+
const job = await this.getJob(jobId);
|
|
86
|
+
options.onPoll?.(job);
|
|
87
|
+
if (job.status === "completed" || job.status === "failed") {
|
|
88
|
+
return job;
|
|
89
|
+
}
|
|
90
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export {
|
|
96
|
+
SyncsnapRateLimitError,
|
|
97
|
+
SyncsnapServer
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=chunk-SUNHYVAG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client.ts"],"sourcesContent":["import type {\n CreateJobResponse,\n Job,\n PresignedUrlResponse,\n WaitForJobOptions,\n} from './types';\n\nconst SYNCSNAP_API_BASE_URL = 'https://api.syncsnap.xyz/api';\n\n/** Thrown when the Syncsnap API returns 429 Too Many Requests (rate limit exceeded). */\nexport class SyncsnapRateLimitError extends Error {\n readonly statusCode = 429;\n\n constructor(message: string) {\n super(message);\n this.name = 'SyncsnapRateLimitError';\n Object.setPrototypeOf(this, SyncsnapRateLimitError.prototype);\n }\n}\n\nexport class SyncsnapServer {\n private readonly baseUrl: string;\n private readonly token: string;\n private readonly fetcher: typeof fetch;\n\n constructor(apiVersion: string = 'v1') {\n this.baseUrl = `${SYNCSNAP_API_BASE_URL}/${apiVersion}`;\n this.token = process.env.SYNCSNAP_TOKEN!;\n this.fetcher = fetch;\n }\n\n private authHeaders(): HeadersInit {\n return {\n 'Content-Type': 'application/json',\n 'X-API-KEY': this.token,\n };\n }\n\n private async requestJson<T>(url: string, init?: RequestInit): Promise<T> {\n const res = await this.fetcher(url, init);\n const data = (await res.json().catch(() => ({}))) as T & {\n error?: string;\n };\n\n if (!res.ok) {\n const message =\n typeof data === 'object' && data && 'error' in data && data.error\n ? String(data.error)\n : `Syncsnap request failed (${res.status})`;\n if (res.status === 429) {\n throw new SyncsnapRateLimitError(message);\n }\n throw new Error(message);\n }\n\n return data as T;\n }\n\n async createJob(): Promise<CreateJobResponse> {\n const url = `${this.baseUrl}/jobs`;\n return this.requestJson<CreateJobResponse>(url, {\n method: 'POST',\n headers: this.authHeaders(),\n });\n }\n\n async getJob(jobId: string): Promise<Job> {\n const url = `${this.baseUrl}/jobs/${encodeURIComponent(jobId)}`;\n return this.requestJson<Job>(url, {\n method: 'GET',\n headers: this.authHeaders(),\n });\n }\n\n async getUploadUrl(\n jobId: string,\n options: { fileName: string; expirationMinutes?: number }\n ): Promise<PresignedUrlResponse> {\n const url = `${this.baseUrl}/jobs/${encodeURIComponent(\n jobId\n )}/presigned-upload-url`;\n return this.requestJson<PresignedUrlResponse>(url, {\n method: 'POST',\n headers: this.authHeaders(),\n body: JSON.stringify({\n file_name: options.fileName,\n expiration: options.expirationMinutes,\n }),\n });\n }\n\n async getDownloadUrl(\n jobId: string,\n options?: { expirationMinutes?: number }\n ): Promise<PresignedUrlResponse> {\n const url = `${this.baseUrl}/jobs/${encodeURIComponent(\n jobId\n )}/presigned-download-url`;\n return this.requestJson<PresignedUrlResponse>(url, {\n method: 'POST',\n headers: this.authHeaders(),\n body: JSON.stringify({\n expiration: options?.expirationMinutes,\n }),\n });\n }\n\n async waitForJobCompletion(\n jobId: string,\n options: WaitForJobOptions = {}\n ): Promise<Job> {\n const intervalMs = options.intervalMs ?? 2000;\n const timeoutMs = options.timeoutMs ?? 120000;\n const startedAt = Date.now();\n\n while (true) {\n if (options.signal?.aborted) {\n throw new Error('Polling aborted');\n }\n if (Date.now() - startedAt > timeoutMs) {\n throw new Error('Polling timed out');\n }\n\n const job = await this.getJob(jobId);\n options.onPoll?.(job);\n\n if (job.status === 'completed' || job.status === 'failed') {\n return job;\n }\n\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -38,6 +38,11 @@ interface WaitCompletionResponse<T = unknown> {
|
|
|
38
38
|
result?: T;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/** Thrown when the Syncsnap API returns 429 Too Many Requests (rate limit exceeded). */
|
|
42
|
+
declare class SyncsnapRateLimitError extends Error {
|
|
43
|
+
readonly statusCode = 429;
|
|
44
|
+
constructor(message: string);
|
|
45
|
+
}
|
|
41
46
|
declare class SyncsnapServer {
|
|
42
47
|
private readonly baseUrl;
|
|
43
48
|
private readonly token;
|
|
@@ -57,4 +62,4 @@ declare class SyncsnapServer {
|
|
|
57
62
|
waitForJobCompletion(jobId: string, options?: WaitForJobOptions): Promise<Job>;
|
|
58
63
|
}
|
|
59
64
|
|
|
60
|
-
export { type CreateJobResponse, type DownloadUrlResponse, type Job, type JobStatus, type PresignedUrlResponse, SyncsnapServer, type WaitCompletionResponse, type WaitForJobOptions };
|
|
65
|
+
export { type CreateJobResponse, type DownloadUrlResponse, type Job, type JobStatus, type PresignedUrlResponse, SyncsnapRateLimitError, SyncsnapServer, type WaitCompletionResponse, type WaitForJobOptions };
|
package/dist/index.js
CHANGED
|
@@ -1,86 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
this.baseUrl = `${SYNCSNAP_API_BASE_URL}/${apiVersion}`;
|
|
6
|
-
this.token = process.env.SYNCSNAP_TOKEN;
|
|
7
|
-
this.fetcher = fetch;
|
|
8
|
-
}
|
|
9
|
-
authHeaders() {
|
|
10
|
-
return {
|
|
11
|
-
"Content-Type": "application/json",
|
|
12
|
-
"X-API-KEY": this.token
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
async requestJson(url, init) {
|
|
16
|
-
const res = await this.fetcher(url, init);
|
|
17
|
-
const data = await res.json().catch(() => ({}));
|
|
18
|
-
if (!res.ok) {
|
|
19
|
-
const message = typeof data === "object" && data && "error" in data && data.error ? String(data.error) : `Syncsnap request failed (${res.status})`;
|
|
20
|
-
throw new Error(message);
|
|
21
|
-
}
|
|
22
|
-
return data;
|
|
23
|
-
}
|
|
24
|
-
async createJob() {
|
|
25
|
-
const url = `${this.baseUrl}/jobs`;
|
|
26
|
-
return this.requestJson(url, {
|
|
27
|
-
method: "POST",
|
|
28
|
-
headers: this.authHeaders()
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
async getJob(jobId) {
|
|
32
|
-
const url = `${this.baseUrl}/jobs/${encodeURIComponent(jobId)}`;
|
|
33
|
-
return this.requestJson(url, {
|
|
34
|
-
method: "GET",
|
|
35
|
-
headers: this.authHeaders()
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
async getUploadUrl(jobId, options) {
|
|
39
|
-
const url = `${this.baseUrl}/jobs/${encodeURIComponent(
|
|
40
|
-
jobId
|
|
41
|
-
)}/presigned-upload-url`;
|
|
42
|
-
return this.requestJson(url, {
|
|
43
|
-
method: "POST",
|
|
44
|
-
headers: this.authHeaders(),
|
|
45
|
-
body: JSON.stringify({
|
|
46
|
-
file_name: options.fileName,
|
|
47
|
-
expiration: options.expirationMinutes
|
|
48
|
-
})
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
async getDownloadUrl(jobId, options) {
|
|
52
|
-
const url = `${this.baseUrl}/jobs/${encodeURIComponent(
|
|
53
|
-
jobId
|
|
54
|
-
)}/presigned-download-url`;
|
|
55
|
-
return this.requestJson(url, {
|
|
56
|
-
method: "POST",
|
|
57
|
-
headers: this.authHeaders(),
|
|
58
|
-
body: JSON.stringify({
|
|
59
|
-
expiration: options?.expirationMinutes
|
|
60
|
-
})
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
async waitForJobCompletion(jobId, options = {}) {
|
|
64
|
-
const intervalMs = options.intervalMs ?? 2e3;
|
|
65
|
-
const timeoutMs = options.timeoutMs ?? 12e4;
|
|
66
|
-
const startedAt = Date.now();
|
|
67
|
-
while (true) {
|
|
68
|
-
if (options.signal?.aborted) {
|
|
69
|
-
throw new Error("Polling aborted");
|
|
70
|
-
}
|
|
71
|
-
if (Date.now() - startedAt > timeoutMs) {
|
|
72
|
-
throw new Error("Polling timed out");
|
|
73
|
-
}
|
|
74
|
-
const job = await this.getJob(jobId);
|
|
75
|
-
options.onPoll?.(job);
|
|
76
|
-
if (job.status === "completed" || job.status === "failed") {
|
|
77
|
-
return job;
|
|
78
|
-
}
|
|
79
|
-
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
SyncsnapRateLimitError,
|
|
3
|
+
SyncsnapServer
|
|
4
|
+
} from "./chunk-SUNHYVAG.js";
|
|
83
5
|
export {
|
|
6
|
+
SyncsnapRateLimitError,
|
|
84
7
|
SyncsnapServer
|
|
85
8
|
};
|
|
86
9
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/next.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SyncsnapRateLimitError
|
|
3
|
+
} from "./chunk-SUNHYVAG.js";
|
|
4
|
+
|
|
1
5
|
// src/next/route-handlers.ts
|
|
2
6
|
function json(data, init) {
|
|
3
7
|
return new Response(JSON.stringify(data), {
|
|
@@ -45,8 +49,15 @@ function getCatchAllPath(params) {
|
|
|
45
49
|
}
|
|
46
50
|
function createJobHandler(client) {
|
|
47
51
|
return async function POST() {
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
try {
|
|
53
|
+
const job = await client.createJob();
|
|
54
|
+
return json(job);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
if (err instanceof SyncsnapRateLimitError) {
|
|
57
|
+
return json({ error: err.message }, { status: 429 });
|
|
58
|
+
}
|
|
59
|
+
throw err;
|
|
60
|
+
}
|
|
50
61
|
};
|
|
51
62
|
}
|
|
52
63
|
function getJobHandler(client) {
|
|
@@ -55,8 +66,15 @@ function getJobHandler(client) {
|
|
|
55
66
|
if (!resolved?.id) {
|
|
56
67
|
return json({ error: "Job id is required" }, { status: 400 });
|
|
57
68
|
}
|
|
58
|
-
|
|
59
|
-
|
|
69
|
+
try {
|
|
70
|
+
const job = await client.getJob(resolved.id);
|
|
71
|
+
return json(job);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
if (err instanceof SyncsnapRateLimitError) {
|
|
74
|
+
return json({ error: err.message }, { status: 429 });
|
|
75
|
+
}
|
|
76
|
+
throw err;
|
|
77
|
+
}
|
|
60
78
|
};
|
|
61
79
|
}
|
|
62
80
|
function getDownloadUrlHandler(client) {
|
|
@@ -65,12 +83,19 @@ function getDownloadUrlHandler(client) {
|
|
|
65
83
|
if (!resolved?.id) {
|
|
66
84
|
return json({ error: "Job id is required" }, { status: 400 });
|
|
67
85
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
86
|
+
try {
|
|
87
|
+
const expirationMinutes = parseExpiration(request.url);
|
|
88
|
+
const response = await client.getDownloadUrl(
|
|
89
|
+
resolved.id,
|
|
90
|
+
{ expirationMinutes }
|
|
91
|
+
);
|
|
92
|
+
return json(response);
|
|
93
|
+
} catch (err) {
|
|
94
|
+
if (err instanceof SyncsnapRateLimitError) {
|
|
95
|
+
return json({ error: err.message }, { status: 429 });
|
|
96
|
+
}
|
|
97
|
+
throw err;
|
|
98
|
+
}
|
|
74
99
|
};
|
|
75
100
|
}
|
|
76
101
|
function createRouteHandler(options) {
|
|
@@ -80,30 +105,44 @@ function createRouteHandler(options) {
|
|
|
80
105
|
const resolved = await resolveParams(context.params);
|
|
81
106
|
const segments = getCatchAllPath(resolved);
|
|
82
107
|
if (segments.length === 2 && segments[0] === "job") {
|
|
83
|
-
|
|
84
|
-
|
|
108
|
+
try {
|
|
109
|
+
const job = await client.getJob(segments[1]);
|
|
110
|
+
return json(job);
|
|
111
|
+
} catch (err) {
|
|
112
|
+
if (err instanceof SyncsnapRateLimitError) {
|
|
113
|
+
return json({ error: err.message }, { status: 429 });
|
|
114
|
+
}
|
|
115
|
+
throw err;
|
|
116
|
+
}
|
|
85
117
|
}
|
|
86
118
|
if (segments.length === 3 && segments[0] === "job" && segments[2] === "download") {
|
|
87
119
|
const jobId = segments[1];
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const expirationMinutes = parseExpiration(request.url);
|
|
93
|
-
const presigned = await client.getDownloadUrl(
|
|
94
|
-
jobId,
|
|
95
|
-
{
|
|
96
|
-
expirationMinutes
|
|
120
|
+
try {
|
|
121
|
+
const job = await client.getJob(jobId);
|
|
122
|
+
if (job.status !== "completed") {
|
|
123
|
+
return json({ error: "Job is not completed" }, { status: 400 });
|
|
97
124
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
125
|
+
const expirationMinutes = parseExpiration(request.url);
|
|
126
|
+
const presigned = await client.getDownloadUrl(
|
|
127
|
+
jobId,
|
|
128
|
+
{
|
|
129
|
+
expirationMinutes
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
const response = { ...presigned };
|
|
133
|
+
if (onCompletedCallback) {
|
|
134
|
+
const payload = await onCompletedCallback(job, presigned);
|
|
135
|
+
if (payload !== void 0) {
|
|
136
|
+
response.completedPayload = payload;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return json(response);
|
|
140
|
+
} catch (err) {
|
|
141
|
+
if (err instanceof SyncsnapRateLimitError) {
|
|
142
|
+
return json({ error: err.message }, { status: 429 });
|
|
104
143
|
}
|
|
144
|
+
throw err;
|
|
105
145
|
}
|
|
106
|
-
return json(response);
|
|
107
146
|
}
|
|
108
147
|
if (segments.length === 3 && segments[0] === "job" && segments[2] === "wait") {
|
|
109
148
|
const jobId = segments[1];
|
|
@@ -128,6 +167,9 @@ function createRouteHandler(options) {
|
|
|
128
167
|
}
|
|
129
168
|
return json(body);
|
|
130
169
|
} catch (err) {
|
|
170
|
+
if (err instanceof SyncsnapRateLimitError) {
|
|
171
|
+
return json({ error: err.message }, { status: 429 });
|
|
172
|
+
}
|
|
131
173
|
const message = err instanceof Error ? err.message : "Wait failed";
|
|
132
174
|
const isTimeout = message.includes("timed out") || message.includes("Polling timed out");
|
|
133
175
|
return json({ error: message }, { status: isTimeout ? 408 : 500 });
|
|
@@ -139,8 +181,15 @@ function createRouteHandler(options) {
|
|
|
139
181
|
const resolved = await resolveParams(context.params);
|
|
140
182
|
const segments = getCatchAllPath(resolved);
|
|
141
183
|
if (segments.length === 1 && segments[0] === "job") {
|
|
142
|
-
|
|
143
|
-
|
|
184
|
+
try {
|
|
185
|
+
const job = await client.createJob();
|
|
186
|
+
return json(job);
|
|
187
|
+
} catch (err) {
|
|
188
|
+
if (err instanceof SyncsnapRateLimitError) {
|
|
189
|
+
return json({ error: err.message }, { status: 429 });
|
|
190
|
+
}
|
|
191
|
+
throw err;
|
|
192
|
+
}
|
|
144
193
|
}
|
|
145
194
|
return json({ error: "Not found" }, { status: 404 });
|
|
146
195
|
}
|
package/dist/next.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/next/route-handlers.ts"],"sourcesContent":["import type { SyncsnapServer } from '../client';\nimport type {\n DownloadUrlResponse,\n Job,\n PresignedUrlResponse,\n WaitCompletionResponse,\n} from '../types';\n\ntype NextParams = { params: { id: string } | Promise<{ id: string }> };\ntype CatchAllParams = {\n params?:\n | Record<string, string | string[] | undefined>\n | Promise<Record<string, string | string[] | undefined>>;\n};\n\nfunction json(data: unknown, init?: ResponseInit): Response {\n return new Response(JSON.stringify(data), {\n ...init,\n headers: {\n 'Content-Type': 'application/json',\n ...(init?.headers ?? {}),\n },\n });\n}\n\nfunction parseExpiration(url: string): number | undefined {\n const { searchParams } = new URL(url);\n const raw = searchParams.get('expiration');\n if (!raw) return undefined;\n const value = Number(raw);\n return Number.isFinite(value) && value > 0 ? value : undefined;\n}\n\nfunction parseWaitOptions(url: string): {\n timeoutMs?: number;\n intervalMs?: number;\n} {\n const { searchParams } = new URL(url);\n const timeoutMs = parseOptionalPositiveNumber(searchParams.get('timeoutMs'));\n const intervalMs = parseOptionalPositiveNumber(\n searchParams.get('intervalMs')\n );\n return { timeoutMs, intervalMs };\n}\n\nfunction parseOptionalPositiveNumber(value: string | null): number | undefined {\n if (value == null) return undefined;\n const n = Number(value);\n return Number.isFinite(n) && n > 0 ? n : undefined;\n}\n\nasync function resolveParams<T>(\n params?: T | Promise<T>\n): Promise<T | undefined> {\n if (!params) return undefined;\n if (typeof (params as Promise<T>).then === 'function') {\n return await (params as Promise<T>);\n }\n return params as T;\n}\n\nfunction getCatchAllPath(\n params?: Record<string, string | string[] | undefined>\n): string[] {\n if (!params) return [];\n for (const value of Object.values(params)) {\n if (Array.isArray(value)) return value;\n if (typeof value === 'string' && value.length > 0) return [value];\n }\n return [];\n}\n\nexport function createJobHandler(client: SyncsnapServer) {\n return async function POST(): Promise<Response> {\n const job = await client.createJob();\n return json(job);\n };\n}\n\nexport function getJobHandler(client: SyncsnapServer) {\n return async function GET(\n _request: Request,\n context: NextParams\n ): Promise<Response> {\n const resolved = await resolveParams(context.params);\n if (!resolved?.id) {\n return json({ error: 'Job id is required' }, { status: 400 });\n }\n const job = await client.getJob(resolved.id);\n return json(job);\n };\n}\n\nexport function getDownloadUrlHandler(client: SyncsnapServer) {\n return async function GET(\n request: Request,\n context: NextParams\n ): Promise<Response> {\n const resolved = await resolveParams(context.params);\n if (!resolved?.id) {\n return json({ error: 'Job id is required' }, { status: 400 });\n }\n const expirationMinutes = parseExpiration(request.url);\n const response: PresignedUrlResponse = await client.getDownloadUrl(\n resolved.id,\n { expirationMinutes }\n );\n return json(response);\n };\n}\n\nexport interface CreateRouteHandlerOptions {\n client: SyncsnapServer;\n /**\n * Called when a job completes (after server-side polling). Receives the job and, when\n * status is \"completed\", the presigned download URL. Whatever this returns is sent to\n * the client and passed to `useSyncsnapJob`'s `onCompleted(job, result)`.\n */\n onCompleted?: (\n job: Job,\n presigned?: PresignedUrlResponse\n ) => unknown | Promise<unknown>;\n}\n\nexport function createRouteHandler(options: CreateRouteHandlerOptions) {\n const { client, onCompleted: onCompletedCallback } = options;\n\n return {\n GET: async (\n request: Request,\n context: CatchAllParams\n ): Promise<Response> => {\n const resolved = await resolveParams(context.params);\n const segments = getCatchAllPath(resolved);\n if (segments.length === 2 && segments[0] === 'job') {\n const job = await client.getJob(segments[1]);\n return json(job);\n }\n\n if (\n segments.length === 3 &&\n segments[0] === 'job' &&\n segments[2] === 'download'\n ) {\n const jobId = segments[1];\n const job = await client.getJob(jobId);\n if (job.status !== 'completed') {\n return json({ error: 'Job is not completed' }, { status: 400 });\n }\n const expirationMinutes = parseExpiration(request.url);\n const presigned: PresignedUrlResponse = await client.getDownloadUrl(\n jobId,\n {\n expirationMinutes,\n }\n );\n const response: DownloadUrlResponse = { ...presigned };\n if (onCompletedCallback) {\n const payload = await onCompletedCallback(job, presigned);\n if (payload !== undefined) {\n response.completedPayload = payload;\n }\n }\n return json(response);\n }\n\n if (\n segments.length === 3 &&\n segments[0] === 'job' &&\n segments[2] === 'wait'\n ) {\n const jobId = segments[1];\n const { timeoutMs, intervalMs } = parseWaitOptions(request.url);\n try {\n const job = await client.waitForJobCompletion(jobId, {\n timeoutMs,\n intervalMs,\n });\n const body: WaitCompletionResponse = { job };\n if (job.status === 'completed') {\n const presigned: PresignedUrlResponse =\n await client.getDownloadUrl(jobId);\n const result = onCompletedCallback\n ? await onCompletedCallback(job, presigned)\n : presigned;\n if (result !== undefined) {\n body.result = result;\n }\n } else if (onCompletedCallback) {\n const result = await onCompletedCallback(job);\n if (result !== undefined) {\n body.result = result;\n }\n }\n return json(body);\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Wait failed';\n const isTimeout =\n message.includes('timed out') ||\n message.includes('Polling timed out');\n return json({ error: message }, { status: isTimeout ? 408 : 500 });\n }\n }\n\n return json({ error: 'Not found' }, { status: 404 });\n },\n POST: async (\n _request: Request,\n context: CatchAllParams\n ): Promise<Response> => {\n const resolved = await resolveParams(context.params);\n const segments = getCatchAllPath(resolved);\n if (segments.length === 1 && segments[0] === 'job') {\n const job = await client.createJob();\n return json(job);\n }\n\n return json({ error: 'Not found' }, { status: 404 });\n },\n };\n}\n\nexport type { Job };\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/next/route-handlers.ts"],"sourcesContent":["import type { SyncsnapServer } from '../client';\nimport { SyncsnapRateLimitError } from '../client';\nimport type {\n DownloadUrlResponse,\n Job,\n PresignedUrlResponse,\n WaitCompletionResponse,\n} from '../types';\n\ntype NextParams = { params: { id: string } | Promise<{ id: string }> };\ntype CatchAllParams = {\n params?:\n | Record<string, string | string[] | undefined>\n | Promise<Record<string, string | string[] | undefined>>;\n};\n\nfunction json(data: unknown, init?: ResponseInit): Response {\n return new Response(JSON.stringify(data), {\n ...init,\n headers: {\n 'Content-Type': 'application/json',\n ...(init?.headers ?? {}),\n },\n });\n}\n\nfunction parseExpiration(url: string): number | undefined {\n const { searchParams } = new URL(url);\n const raw = searchParams.get('expiration');\n if (!raw) return undefined;\n const value = Number(raw);\n return Number.isFinite(value) && value > 0 ? value : undefined;\n}\n\nfunction parseWaitOptions(url: string): {\n timeoutMs?: number;\n intervalMs?: number;\n} {\n const { searchParams } = new URL(url);\n const timeoutMs = parseOptionalPositiveNumber(searchParams.get('timeoutMs'));\n const intervalMs = parseOptionalPositiveNumber(\n searchParams.get('intervalMs')\n );\n return { timeoutMs, intervalMs };\n}\n\nfunction parseOptionalPositiveNumber(value: string | null): number | undefined {\n if (value == null) return undefined;\n const n = Number(value);\n return Number.isFinite(n) && n > 0 ? n : undefined;\n}\n\nasync function resolveParams<T>(\n params?: T | Promise<T>\n): Promise<T | undefined> {\n if (!params) return undefined;\n if (typeof (params as Promise<T>).then === 'function') {\n return await (params as Promise<T>);\n }\n return params as T;\n}\n\nfunction getCatchAllPath(\n params?: Record<string, string | string[] | undefined>\n): string[] {\n if (!params) return [];\n for (const value of Object.values(params)) {\n if (Array.isArray(value)) return value;\n if (typeof value === 'string' && value.length > 0) return [value];\n }\n return [];\n}\n\nexport function createJobHandler(client: SyncsnapServer) {\n return async function POST(): Promise<Response> {\n try {\n const job = await client.createJob();\n return json(job);\n } catch (err) {\n if (err instanceof SyncsnapRateLimitError) {\n return json({ error: err.message }, { status: 429 });\n }\n throw err;\n }\n };\n}\n\nexport function getJobHandler(client: SyncsnapServer) {\n return async function GET(\n _request: Request,\n context: NextParams\n ): Promise<Response> {\n const resolved = await resolveParams(context.params);\n if (!resolved?.id) {\n return json({ error: 'Job id is required' }, { status: 400 });\n }\n try {\n const job = await client.getJob(resolved.id);\n return json(job);\n } catch (err) {\n if (err instanceof SyncsnapRateLimitError) {\n return json({ error: err.message }, { status: 429 });\n }\n throw err;\n }\n };\n}\n\nexport function getDownloadUrlHandler(client: SyncsnapServer) {\n return async function GET(\n request: Request,\n context: NextParams\n ): Promise<Response> {\n const resolved = await resolveParams(context.params);\n if (!resolved?.id) {\n return json({ error: 'Job id is required' }, { status: 400 });\n }\n try {\n const expirationMinutes = parseExpiration(request.url);\n const response: PresignedUrlResponse = await client.getDownloadUrl(\n resolved.id,\n { expirationMinutes }\n );\n return json(response);\n } catch (err) {\n if (err instanceof SyncsnapRateLimitError) {\n return json({ error: err.message }, { status: 429 });\n }\n throw err;\n }\n };\n}\n\nexport interface CreateRouteHandlerOptions {\n client: SyncsnapServer;\n /**\n * Called when a job completes (after server-side polling). Receives the job and, when\n * status is \"completed\", the presigned download URL. Whatever this returns is sent to\n * the client and passed to `useSyncsnapJob`'s `onCompleted(job, result)`.\n */\n onCompleted?: (\n job: Job,\n presigned?: PresignedUrlResponse\n ) => unknown | Promise<unknown>;\n}\n\nexport function createRouteHandler(options: CreateRouteHandlerOptions) {\n const { client, onCompleted: onCompletedCallback } = options;\n\n return {\n GET: async (\n request: Request,\n context: CatchAllParams\n ): Promise<Response> => {\n const resolved = await resolveParams(context.params);\n const segments = getCatchAllPath(resolved);\n if (segments.length === 2 && segments[0] === 'job') {\n try {\n const job = await client.getJob(segments[1]);\n return json(job);\n } catch (err) {\n if (err instanceof SyncsnapRateLimitError) {\n return json({ error: err.message }, { status: 429 });\n }\n throw err;\n }\n }\n\n if (\n segments.length === 3 &&\n segments[0] === 'job' &&\n segments[2] === 'download'\n ) {\n const jobId = segments[1];\n try {\n const job = await client.getJob(jobId);\n if (job.status !== 'completed') {\n return json({ error: 'Job is not completed' }, { status: 400 });\n }\n const expirationMinutes = parseExpiration(request.url);\n const presigned: PresignedUrlResponse = await client.getDownloadUrl(\n jobId,\n {\n expirationMinutes,\n }\n );\n const response: DownloadUrlResponse = { ...presigned };\n if (onCompletedCallback) {\n const payload = await onCompletedCallback(job, presigned);\n if (payload !== undefined) {\n response.completedPayload = payload;\n }\n }\n return json(response);\n } catch (err) {\n if (err instanceof SyncsnapRateLimitError) {\n return json({ error: err.message }, { status: 429 });\n }\n throw err;\n }\n }\n\n if (\n segments.length === 3 &&\n segments[0] === 'job' &&\n segments[2] === 'wait'\n ) {\n const jobId = segments[1];\n const { timeoutMs, intervalMs } = parseWaitOptions(request.url);\n try {\n const job = await client.waitForJobCompletion(jobId, {\n timeoutMs,\n intervalMs,\n });\n const body: WaitCompletionResponse = { job };\n if (job.status === 'completed') {\n const presigned: PresignedUrlResponse =\n await client.getDownloadUrl(jobId);\n const result = onCompletedCallback\n ? await onCompletedCallback(job, presigned)\n : presigned;\n if (result !== undefined) {\n body.result = result;\n }\n } else if (onCompletedCallback) {\n const result = await onCompletedCallback(job);\n if (result !== undefined) {\n body.result = result;\n }\n }\n return json(body);\n } catch (err) {\n if (err instanceof SyncsnapRateLimitError) {\n return json({ error: err.message }, { status: 429 });\n }\n const message = err instanceof Error ? err.message : 'Wait failed';\n const isTimeout =\n message.includes('timed out') ||\n message.includes('Polling timed out');\n return json({ error: message }, { status: isTimeout ? 408 : 500 });\n }\n }\n\n return json({ error: 'Not found' }, { status: 404 });\n },\n POST: async (\n _request: Request,\n context: CatchAllParams\n ): Promise<Response> => {\n const resolved = await resolveParams(context.params);\n const segments = getCatchAllPath(resolved);\n if (segments.length === 1 && segments[0] === 'job') {\n try {\n const job = await client.createJob();\n return json(job);\n } catch (err) {\n if (err instanceof SyncsnapRateLimitError) {\n return json({ error: err.message }, { status: 429 });\n }\n throw err;\n }\n }\n\n return json({ error: 'Not found' }, { status: 404 });\n },\n };\n}\n\nexport type { Job };\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "syncsnap",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Syncsnap server SDK for Node/Next.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,12 +21,12 @@
|
|
|
21
21
|
],
|
|
22
22
|
"repository": {
|
|
23
23
|
"type": "git",
|
|
24
|
-
"url": "https://github.com/
|
|
24
|
+
"url": "https://github.com/syncsnapxyz/packages.git",
|
|
25
25
|
"directory": "syncsnap"
|
|
26
26
|
},
|
|
27
|
-
"homepage": "https://github.com/
|
|
27
|
+
"homepage": "https://github.com/syncsnapxyz/packages/syncsnap#readme",
|
|
28
28
|
"bugs": {
|
|
29
|
-
"url": "https://github.com/
|
|
29
|
+
"url": "https://github.com/syncsnapxyz/packages/syncsnap/issues"
|
|
30
30
|
},
|
|
31
31
|
"keywords": [
|
|
32
32
|
"syncsnap",
|
|
@@ -49,7 +49,8 @@
|
|
|
49
49
|
"format": "prettier --write .",
|
|
50
50
|
"format:check": "prettier --check .",
|
|
51
51
|
"build": "tsup src/index.ts src/next.ts --dts --format esm --out-dir dist --clean --sourcemap",
|
|
52
|
-
"publish": "npm publish --
|
|
52
|
+
"publish": "npm publish --access public",
|
|
53
|
+
"publish:ci": "npm publish --provenance --access public",
|
|
53
54
|
"link": "npm run build && npm link",
|
|
54
55
|
"prepublishOnly": "npm run build",
|
|
55
56
|
"test": "vitest run",
|