naystack 1.1.13-beta.3 → 1.1.13
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/client/index.cjs.js +26 -0
- package/dist/client/index.d.mts +1 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.esm.js +25 -0
- package/dist/file/client.cjs.js +51 -0
- package/dist/file/client.d.mts +13 -0
- package/dist/file/client.d.ts +13 -0
- package/dist/file/client.esm.js +26 -0
- package/dist/file/index.cjs.js +195 -0
- package/dist/file/index.d.mts +3 -0
- package/dist/file/index.d.ts +3 -0
- package/dist/file/index.esm.js +172 -0
- package/dist/file/put.cjs.js +157 -0
- package/dist/file/put.d.mts +11 -0
- package/dist/file/put.d.ts +11 -0
- package/dist/file/put.esm.js +136 -0
- package/dist/file/setup.cjs.js +195 -0
- package/dist/file/setup.d.mts +34 -0
- package/dist/file/setup.d.ts +34 -0
- package/dist/file/setup.esm.js +172 -0
- package/dist/file/utils.cjs.js +104 -0
- package/dist/file/utils.d.mts +13 -0
- package/dist/file/utils.d.ts +13 -0
- package/dist/file/utils.esm.js +78 -0
- package/dist/graphql/utils.d.mts +3 -2
- package/dist/graphql/utils.d.ts +3 -2
- package/package.json +8 -1
package/dist/client/index.cjs.js
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/client/index.ts
|
|
21
21
|
var client_exports = {};
|
|
22
22
|
__export(client_exports, {
|
|
23
|
+
getHandleImageUpload: () => getHandleImageUpload,
|
|
23
24
|
getInstagramAuthorizationURLSetup: () => getInstagramAuthorizationURLSetup,
|
|
24
25
|
setupSEO: () => setupSEO,
|
|
25
26
|
useBreakpoint: () => useBreakpoint,
|
|
@@ -30,6 +31,30 @@ module.exports = __toCommonJS(client_exports);
|
|
|
30
31
|
// src/auth/instagram/client.ts
|
|
31
32
|
var getInstagramAuthorizationURLSetup = (clientId, redirectURL) => (token) => `https://www.instagram.com/oauth/authorize?client_id=${clientId}&response_type=code&enable_fb_login=0&force_authentication=1&scope=instagram_business_basic&state=${token}&redirect_uri=${redirectURL}`;
|
|
32
33
|
|
|
34
|
+
// src/file/client.ts
|
|
35
|
+
var getHandleImageUpload = (route) => ({
|
|
36
|
+
file,
|
|
37
|
+
type,
|
|
38
|
+
token,
|
|
39
|
+
data,
|
|
40
|
+
sync
|
|
41
|
+
}) => {
|
|
42
|
+
const formData = new FormData();
|
|
43
|
+
formData.append("type", type);
|
|
44
|
+
if (file) formData.append("file", file);
|
|
45
|
+
if (sync) formData.append("sync", sync.toString());
|
|
46
|
+
if (data) formData.append("data", JSON.stringify(data));
|
|
47
|
+
return fetch(route, {
|
|
48
|
+
method: "PUT",
|
|
49
|
+
body: formData,
|
|
50
|
+
headers: {
|
|
51
|
+
Authorization: `Bearer ${token}`
|
|
52
|
+
}
|
|
53
|
+
}).then(
|
|
54
|
+
async (res) => await res.json() || null
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
33
58
|
// src/client/hooks.ts
|
|
34
59
|
var import_react = require("react");
|
|
35
60
|
function useVisibility(onVisible) {
|
|
@@ -100,6 +125,7 @@ var setupSEO = (SEO) => (title, description, image) => ({
|
|
|
100
125
|
});
|
|
101
126
|
// Annotate the CommonJS export names for ESM import in node:
|
|
102
127
|
0 && (module.exports = {
|
|
128
|
+
getHandleImageUpload,
|
|
103
129
|
getInstagramAuthorizationURLSetup,
|
|
104
130
|
setupSEO,
|
|
105
131
|
useBreakpoint,
|
package/dist/client/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { getInstagramAuthorizationURLSetup } from '../auth/instagram/client.mjs';
|
|
2
|
+
export { ImageUploadResponseType, getHandleImageUpload } from '../file/client.mjs';
|
|
2
3
|
export { useBreakpoint, useVisibility } from './hooks.mjs';
|
|
3
4
|
export { setupSEO } from './seo.mjs';
|
|
4
5
|
import 'react';
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { getInstagramAuthorizationURLSetup } from '../auth/instagram/client.js';
|
|
2
|
+
export { ImageUploadResponseType, getHandleImageUpload } from '../file/client.js';
|
|
2
3
|
export { useBreakpoint, useVisibility } from './hooks.js';
|
|
3
4
|
export { setupSEO } from './seo.js';
|
|
4
5
|
import 'react';
|
package/dist/client/index.esm.js
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
// src/auth/instagram/client.ts
|
|
2
2
|
var getInstagramAuthorizationURLSetup = (clientId, redirectURL) => (token) => `https://www.instagram.com/oauth/authorize?client_id=${clientId}&response_type=code&enable_fb_login=0&force_authentication=1&scope=instagram_business_basic&state=${token}&redirect_uri=${redirectURL}`;
|
|
3
3
|
|
|
4
|
+
// src/file/client.ts
|
|
5
|
+
var getHandleImageUpload = (route) => ({
|
|
6
|
+
file,
|
|
7
|
+
type,
|
|
8
|
+
token,
|
|
9
|
+
data,
|
|
10
|
+
sync
|
|
11
|
+
}) => {
|
|
12
|
+
const formData = new FormData();
|
|
13
|
+
formData.append("type", type);
|
|
14
|
+
if (file) formData.append("file", file);
|
|
15
|
+
if (sync) formData.append("sync", sync.toString());
|
|
16
|
+
if (data) formData.append("data", JSON.stringify(data));
|
|
17
|
+
return fetch(route, {
|
|
18
|
+
method: "PUT",
|
|
19
|
+
body: formData,
|
|
20
|
+
headers: {
|
|
21
|
+
Authorization: `Bearer ${token}`
|
|
22
|
+
}
|
|
23
|
+
}).then(
|
|
24
|
+
async (res) => await res.json() || null
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
4
28
|
// src/client/hooks.ts
|
|
5
29
|
import { useEffect, useRef, useState } from "react";
|
|
6
30
|
function useVisibility(onVisible) {
|
|
@@ -70,6 +94,7 @@ var setupSEO = (SEO) => (title, description, image) => ({
|
|
|
70
94
|
publisher: SEO.siteName
|
|
71
95
|
});
|
|
72
96
|
export {
|
|
97
|
+
getHandleImageUpload,
|
|
73
98
|
getInstagramAuthorizationURLSetup,
|
|
74
99
|
setupSEO,
|
|
75
100
|
useBreakpoint,
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/file/client.ts
|
|
21
|
+
var client_exports = {};
|
|
22
|
+
__export(client_exports, {
|
|
23
|
+
getHandleImageUpload: () => getHandleImageUpload
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(client_exports);
|
|
26
|
+
var getHandleImageUpload = (route) => ({
|
|
27
|
+
file,
|
|
28
|
+
type,
|
|
29
|
+
token,
|
|
30
|
+
data,
|
|
31
|
+
sync
|
|
32
|
+
}) => {
|
|
33
|
+
const formData = new FormData();
|
|
34
|
+
formData.append("type", type);
|
|
35
|
+
if (file) formData.append("file", file);
|
|
36
|
+
if (sync) formData.append("sync", sync.toString());
|
|
37
|
+
if (data) formData.append("data", JSON.stringify(data));
|
|
38
|
+
return fetch(route, {
|
|
39
|
+
method: "PUT",
|
|
40
|
+
body: formData,
|
|
41
|
+
headers: {
|
|
42
|
+
Authorization: `Bearer ${token}`
|
|
43
|
+
}
|
|
44
|
+
}).then(
|
|
45
|
+
async (res) => await res.json() || null
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
49
|
+
0 && (module.exports = {
|
|
50
|
+
getHandleImageUpload
|
|
51
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare const getHandleImageUpload: (route: string) => ({ file, type, token, data, sync, }: {
|
|
2
|
+
file?: File | Blob;
|
|
3
|
+
token: string;
|
|
4
|
+
type: string;
|
|
5
|
+
sync?: boolean;
|
|
6
|
+
data?: object;
|
|
7
|
+
}) => Promise<ImageUploadResponseType>;
|
|
8
|
+
interface ImageUploadResponseType {
|
|
9
|
+
url?: string;
|
|
10
|
+
response?: object;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { type ImageUploadResponseType, getHandleImageUpload };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
declare const getHandleImageUpload: (route: string) => ({ file, type, token, data, sync, }: {
|
|
2
|
+
file?: File | Blob;
|
|
3
|
+
token: string;
|
|
4
|
+
type: string;
|
|
5
|
+
sync?: boolean;
|
|
6
|
+
data?: object;
|
|
7
|
+
}) => Promise<ImageUploadResponseType>;
|
|
8
|
+
interface ImageUploadResponseType {
|
|
9
|
+
url?: string;
|
|
10
|
+
response?: object;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { type ImageUploadResponseType, getHandleImageUpload };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// src/file/client.ts
|
|
2
|
+
var getHandleImageUpload = (route) => ({
|
|
3
|
+
file,
|
|
4
|
+
type,
|
|
5
|
+
token,
|
|
6
|
+
data,
|
|
7
|
+
sync
|
|
8
|
+
}) => {
|
|
9
|
+
const formData = new FormData();
|
|
10
|
+
formData.append("type", type);
|
|
11
|
+
if (file) formData.append("file", file);
|
|
12
|
+
if (sync) formData.append("sync", sync.toString());
|
|
13
|
+
if (data) formData.append("data", JSON.stringify(data));
|
|
14
|
+
return fetch(route, {
|
|
15
|
+
method: "PUT",
|
|
16
|
+
body: formData,
|
|
17
|
+
headers: {
|
|
18
|
+
Authorization: `Bearer ${token}`
|
|
19
|
+
}
|
|
20
|
+
}).then(
|
|
21
|
+
async (res) => await res.json() || null
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
export {
|
|
25
|
+
getHandleImageUpload
|
|
26
|
+
};
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/file/index.ts
|
|
21
|
+
var file_exports = {};
|
|
22
|
+
__export(file_exports, {
|
|
23
|
+
setupFileUpload: () => setupFileUpload
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(file_exports);
|
|
26
|
+
|
|
27
|
+
// src/file/put.ts
|
|
28
|
+
var import_functions2 = require("@vercel/functions");
|
|
29
|
+
var import_server3 = require("next/server");
|
|
30
|
+
var import_uuid = require("uuid");
|
|
31
|
+
|
|
32
|
+
// src/auth/email/utils.ts
|
|
33
|
+
var import_jsonwebtoken2 = require("jsonwebtoken");
|
|
34
|
+
|
|
35
|
+
// src/auth/email/token.ts
|
|
36
|
+
var import_bcryptjs = require("bcryptjs");
|
|
37
|
+
var import_jsonwebtoken = require("jsonwebtoken");
|
|
38
|
+
var import_server = require("next/server");
|
|
39
|
+
function getUserIdFromRefreshToken(refreshKey, refreshToken) {
|
|
40
|
+
if (refreshToken)
|
|
41
|
+
try {
|
|
42
|
+
const decoded = (0, import_jsonwebtoken.verify)(refreshToken, refreshKey);
|
|
43
|
+
if (typeof decoded !== "string" && typeof decoded.id === "number")
|
|
44
|
+
return decoded.id;
|
|
45
|
+
} catch (e) {
|
|
46
|
+
if (!(e instanceof import_jsonwebtoken.JsonWebTokenError)) console.error(e, "errors");
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/auth/utils/errors.ts
|
|
53
|
+
var import_server2 = require("next/server");
|
|
54
|
+
|
|
55
|
+
// src/auth/email/utils.ts
|
|
56
|
+
var getUserContext = (refreshKey, signingKey, req) => {
|
|
57
|
+
const bearer = req.headers.get("authorization");
|
|
58
|
+
if (!bearer) {
|
|
59
|
+
const refresh = req.cookies.get("refresh")?.value;
|
|
60
|
+
const userId = getUserIdFromRefreshToken(refreshKey, refresh);
|
|
61
|
+
if (userId) return { refreshUserID: userId };
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const token = bearer.slice(7);
|
|
65
|
+
try {
|
|
66
|
+
const res = (0, import_jsonwebtoken2.verify)(token, signingKey);
|
|
67
|
+
if (typeof res === "string") {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
accessUserId: res.id
|
|
72
|
+
};
|
|
73
|
+
} catch {
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// src/file/utils.ts
|
|
79
|
+
var import_node_crypto = require("crypto");
|
|
80
|
+
var import_client_s3 = require("@aws-sdk/client-s3");
|
|
81
|
+
var import_s3_request_presigner = require("@aws-sdk/s3-request-presigner");
|
|
82
|
+
var import_functions = require("@vercel/functions");
|
|
83
|
+
var getS3Client = (options) => new import_client_s3.S3Client({
|
|
84
|
+
region: options.region,
|
|
85
|
+
credentials: {
|
|
86
|
+
accessKeyId: options.awsKey,
|
|
87
|
+
secretAccessKey: options.awsSecret
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
var getURLPrefix = (options) => `https://${options.bucket}.s3.${options.region}.amazonaws.com/`;
|
|
91
|
+
function getHash(keys) {
|
|
92
|
+
return (0, import_node_crypto.createHash)("sha256").update(keys.join("/")).digest("hex");
|
|
93
|
+
}
|
|
94
|
+
var getUploadFileURL = (client, Bucket) => (keys, isPublic) => {
|
|
95
|
+
const command = new import_client_s3.PutObjectCommand({
|
|
96
|
+
Bucket,
|
|
97
|
+
Key: getHash(keys),
|
|
98
|
+
ACL: isPublic ? "public-read" : void 0
|
|
99
|
+
});
|
|
100
|
+
return (0, import_s3_request_presigner.getSignedUrl)(client, command, { expiresIn: 300 });
|
|
101
|
+
};
|
|
102
|
+
var getFileURL = (options) => (keys) => {
|
|
103
|
+
if (typeof keys === "string") return `${getURLPrefix(options)}${keys}`;
|
|
104
|
+
return `${getURLPrefix(options)}${getHash(keys)}`;
|
|
105
|
+
};
|
|
106
|
+
var uploadImage = (client, options) => async (url, key, blob) => {
|
|
107
|
+
const photoBlob = blob || await fetch(url).then((file) => file.blob());
|
|
108
|
+
if (photoBlob) {
|
|
109
|
+
(0, import_functions.waitUntil)(uploadFile(client, options.bucket)(photoBlob, getHash(key)));
|
|
110
|
+
return getFileURL(options)(key);
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
};
|
|
114
|
+
var deleteImage = (client, options) => async (url) => {
|
|
115
|
+
const key = url.split(getURLPrefix(options))[1];
|
|
116
|
+
if (key) {
|
|
117
|
+
try {
|
|
118
|
+
await client.send(
|
|
119
|
+
new import_client_s3.DeleteObjectCommand({
|
|
120
|
+
Bucket: options.bucket,
|
|
121
|
+
Key: key
|
|
122
|
+
})
|
|
123
|
+
);
|
|
124
|
+
return true;
|
|
125
|
+
} catch (e) {
|
|
126
|
+
console.error("ERROR", url, e);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return false;
|
|
130
|
+
};
|
|
131
|
+
var uploadFile = (client, Bucket) => async (file, key) => {
|
|
132
|
+
const fileBuffer = await file.arrayBuffer();
|
|
133
|
+
return client.send(
|
|
134
|
+
new import_client_s3.PutObjectCommand({
|
|
135
|
+
Bucket,
|
|
136
|
+
Key: key,
|
|
137
|
+
ACL: "public-read",
|
|
138
|
+
Body: Buffer.from(fileBuffer),
|
|
139
|
+
ContentType: file.type,
|
|
140
|
+
ContentLength: file.size
|
|
141
|
+
})
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// src/file/put.ts
|
|
146
|
+
var getFileUploadPutRoute = (options, client) => async (req) => {
|
|
147
|
+
const ctx = getUserContext(options.refreshKey, options.signingKey, req);
|
|
148
|
+
if (!ctx?.accessUserId)
|
|
149
|
+
return import_server3.NextResponse.json({ error: "unauthorized" }, { status: 401 });
|
|
150
|
+
const formData = await req.formData();
|
|
151
|
+
const type = formData.get("type");
|
|
152
|
+
const sync = Boolean(formData.get("sync"));
|
|
153
|
+
const file = formData.get("file");
|
|
154
|
+
const data = formData.get("data");
|
|
155
|
+
const imageKey = (0, import_uuid.v4)();
|
|
156
|
+
const url = file ? getFileURL(options)(imageKey) : null;
|
|
157
|
+
const handleKeyProcessing = async () => {
|
|
158
|
+
if (file) await uploadFile(client, options.bucket)(file, imageKey);
|
|
159
|
+
if (!type || !ctx.accessUserId) return;
|
|
160
|
+
const { deleteURL, response } = await options.processFile({
|
|
161
|
+
url,
|
|
162
|
+
type,
|
|
163
|
+
userId: ctx.accessUserId,
|
|
164
|
+
data: typeof data === "string" ? JSON.parse(data) : void 0
|
|
165
|
+
});
|
|
166
|
+
if (deleteURL) await deleteImage(client, options)(deleteURL);
|
|
167
|
+
return response;
|
|
168
|
+
};
|
|
169
|
+
if (!sync) {
|
|
170
|
+
(0, import_functions2.waitUntil)(handleKeyProcessing());
|
|
171
|
+
return import_server3.NextResponse.json({ url });
|
|
172
|
+
} else {
|
|
173
|
+
return import_server3.NextResponse.json({
|
|
174
|
+
url,
|
|
175
|
+
response: await handleKeyProcessing()
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// src/file/setup.ts
|
|
181
|
+
function setupFileUpload(options) {
|
|
182
|
+
const client = getS3Client(options);
|
|
183
|
+
return {
|
|
184
|
+
PUT: getFileUploadPutRoute(options, client),
|
|
185
|
+
getUploadFileURL: getUploadFileURL(client, options.bucket),
|
|
186
|
+
uploadImage: uploadImage(client, options),
|
|
187
|
+
deleteImage: deleteImage(client, options),
|
|
188
|
+
getFileURL: getFileURL(options),
|
|
189
|
+
uploadFile: uploadFile(client, options.bucket)
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
193
|
+
0 && (module.exports = {
|
|
194
|
+
setupFileUpload
|
|
195
|
+
});
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// src/file/put.ts
|
|
2
|
+
import { waitUntil as waitUntil2 } from "@vercel/functions";
|
|
3
|
+
import { NextResponse as NextResponse3 } from "next/server";
|
|
4
|
+
import { v4 } from "uuid";
|
|
5
|
+
|
|
6
|
+
// src/auth/email/utils.ts
|
|
7
|
+
import { verify as verify2 } from "jsonwebtoken";
|
|
8
|
+
|
|
9
|
+
// src/auth/email/token.ts
|
|
10
|
+
import { compare } from "bcryptjs";
|
|
11
|
+
import { JsonWebTokenError, sign, verify } from "jsonwebtoken";
|
|
12
|
+
import { NextResponse } from "next/server";
|
|
13
|
+
function getUserIdFromRefreshToken(refreshKey, refreshToken) {
|
|
14
|
+
if (refreshToken)
|
|
15
|
+
try {
|
|
16
|
+
const decoded = verify(refreshToken, refreshKey);
|
|
17
|
+
if (typeof decoded !== "string" && typeof decoded.id === "number")
|
|
18
|
+
return decoded.id;
|
|
19
|
+
} catch (e) {
|
|
20
|
+
if (!(e instanceof JsonWebTokenError)) console.error(e, "errors");
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/auth/utils/errors.ts
|
|
27
|
+
import { NextResponse as NextResponse2 } from "next/server";
|
|
28
|
+
|
|
29
|
+
// src/auth/email/utils.ts
|
|
30
|
+
var getUserContext = (refreshKey, signingKey, req) => {
|
|
31
|
+
const bearer = req.headers.get("authorization");
|
|
32
|
+
if (!bearer) {
|
|
33
|
+
const refresh = req.cookies.get("refresh")?.value;
|
|
34
|
+
const userId = getUserIdFromRefreshToken(refreshKey, refresh);
|
|
35
|
+
if (userId) return { refreshUserID: userId };
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const token = bearer.slice(7);
|
|
39
|
+
try {
|
|
40
|
+
const res = verify2(token, signingKey);
|
|
41
|
+
if (typeof res === "string") {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
accessUserId: res.id
|
|
46
|
+
};
|
|
47
|
+
} catch {
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// src/file/utils.ts
|
|
53
|
+
import { createHash } from "crypto";
|
|
54
|
+
import {
|
|
55
|
+
DeleteObjectCommand,
|
|
56
|
+
PutObjectCommand,
|
|
57
|
+
S3Client
|
|
58
|
+
} from "@aws-sdk/client-s3";
|
|
59
|
+
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
|
|
60
|
+
import { waitUntil } from "@vercel/functions";
|
|
61
|
+
var getS3Client = (options) => new S3Client({
|
|
62
|
+
region: options.region,
|
|
63
|
+
credentials: {
|
|
64
|
+
accessKeyId: options.awsKey,
|
|
65
|
+
secretAccessKey: options.awsSecret
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
var getURLPrefix = (options) => `https://${options.bucket}.s3.${options.region}.amazonaws.com/`;
|
|
69
|
+
function getHash(keys) {
|
|
70
|
+
return createHash("sha256").update(keys.join("/")).digest("hex");
|
|
71
|
+
}
|
|
72
|
+
var getUploadFileURL = (client, Bucket) => (keys, isPublic) => {
|
|
73
|
+
const command = new PutObjectCommand({
|
|
74
|
+
Bucket,
|
|
75
|
+
Key: getHash(keys),
|
|
76
|
+
ACL: isPublic ? "public-read" : void 0
|
|
77
|
+
});
|
|
78
|
+
return getSignedUrl(client, command, { expiresIn: 300 });
|
|
79
|
+
};
|
|
80
|
+
var getFileURL = (options) => (keys) => {
|
|
81
|
+
if (typeof keys === "string") return `${getURLPrefix(options)}${keys}`;
|
|
82
|
+
return `${getURLPrefix(options)}${getHash(keys)}`;
|
|
83
|
+
};
|
|
84
|
+
var uploadImage = (client, options) => async (url, key, blob) => {
|
|
85
|
+
const photoBlob = blob || await fetch(url).then((file) => file.blob());
|
|
86
|
+
if (photoBlob) {
|
|
87
|
+
waitUntil(uploadFile(client, options.bucket)(photoBlob, getHash(key)));
|
|
88
|
+
return getFileURL(options)(key);
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
};
|
|
92
|
+
var deleteImage = (client, options) => async (url) => {
|
|
93
|
+
const key = url.split(getURLPrefix(options))[1];
|
|
94
|
+
if (key) {
|
|
95
|
+
try {
|
|
96
|
+
await client.send(
|
|
97
|
+
new DeleteObjectCommand({
|
|
98
|
+
Bucket: options.bucket,
|
|
99
|
+
Key: key
|
|
100
|
+
})
|
|
101
|
+
);
|
|
102
|
+
return true;
|
|
103
|
+
} catch (e) {
|
|
104
|
+
console.error("ERROR", url, e);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
};
|
|
109
|
+
var uploadFile = (client, Bucket) => async (file, key) => {
|
|
110
|
+
const fileBuffer = await file.arrayBuffer();
|
|
111
|
+
return client.send(
|
|
112
|
+
new PutObjectCommand({
|
|
113
|
+
Bucket,
|
|
114
|
+
Key: key,
|
|
115
|
+
ACL: "public-read",
|
|
116
|
+
Body: Buffer.from(fileBuffer),
|
|
117
|
+
ContentType: file.type,
|
|
118
|
+
ContentLength: file.size
|
|
119
|
+
})
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// src/file/put.ts
|
|
124
|
+
var getFileUploadPutRoute = (options, client) => async (req) => {
|
|
125
|
+
const ctx = getUserContext(options.refreshKey, options.signingKey, req);
|
|
126
|
+
if (!ctx?.accessUserId)
|
|
127
|
+
return NextResponse3.json({ error: "unauthorized" }, { status: 401 });
|
|
128
|
+
const formData = await req.formData();
|
|
129
|
+
const type = formData.get("type");
|
|
130
|
+
const sync = Boolean(formData.get("sync"));
|
|
131
|
+
const file = formData.get("file");
|
|
132
|
+
const data = formData.get("data");
|
|
133
|
+
const imageKey = v4();
|
|
134
|
+
const url = file ? getFileURL(options)(imageKey) : null;
|
|
135
|
+
const handleKeyProcessing = async () => {
|
|
136
|
+
if (file) await uploadFile(client, options.bucket)(file, imageKey);
|
|
137
|
+
if (!type || !ctx.accessUserId) return;
|
|
138
|
+
const { deleteURL, response } = await options.processFile({
|
|
139
|
+
url,
|
|
140
|
+
type,
|
|
141
|
+
userId: ctx.accessUserId,
|
|
142
|
+
data: typeof data === "string" ? JSON.parse(data) : void 0
|
|
143
|
+
});
|
|
144
|
+
if (deleteURL) await deleteImage(client, options)(deleteURL);
|
|
145
|
+
return response;
|
|
146
|
+
};
|
|
147
|
+
if (!sync) {
|
|
148
|
+
waitUntil2(handleKeyProcessing());
|
|
149
|
+
return NextResponse3.json({ url });
|
|
150
|
+
} else {
|
|
151
|
+
return NextResponse3.json({
|
|
152
|
+
url,
|
|
153
|
+
response: await handleKeyProcessing()
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// src/file/setup.ts
|
|
159
|
+
function setupFileUpload(options) {
|
|
160
|
+
const client = getS3Client(options);
|
|
161
|
+
return {
|
|
162
|
+
PUT: getFileUploadPutRoute(options, client),
|
|
163
|
+
getUploadFileURL: getUploadFileURL(client, options.bucket),
|
|
164
|
+
uploadImage: uploadImage(client, options),
|
|
165
|
+
deleteImage: deleteImage(client, options),
|
|
166
|
+
getFileURL: getFileURL(options),
|
|
167
|
+
uploadFile: uploadFile(client, options.bucket)
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
export {
|
|
171
|
+
setupFileUpload
|
|
172
|
+
};
|