appflare 0.2.26 → 0.2.27
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/cli/templates/core/client/storage.ts +26 -1
- package/cli/templates/core/client/types.ts +2 -0
- package/cli/templates/handlers/generators/context/storage-api.ts +0 -52
- package/cli/templates/handlers/generators/registration/modules/storage.ts +33 -37
- package/cli/templates/handlers/generators/types/context.ts +0 -1
- package/dist/cli/index.js +105 -135
- package/dist/cli/index.mjs +105 -135
- package/package.json +1 -1
|
@@ -67,6 +67,26 @@ export function createStorageClient(
|
|
|
67
67
|
): StorageClient {
|
|
68
68
|
return {
|
|
69
69
|
upload: async (args) => {
|
|
70
|
+
let base64BodyToSend: string | undefined;
|
|
71
|
+
|
|
72
|
+
if (args.body instanceof File) {
|
|
73
|
+
const buffer = await args.body.arrayBuffer();
|
|
74
|
+
const bytes = new Uint8Array(buffer);
|
|
75
|
+
let binary = "";
|
|
76
|
+
const chunkSize = 8192;
|
|
77
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
78
|
+
const chunk = bytes.subarray(i, i + chunkSize);
|
|
79
|
+
binary += String.fromCharCode(...chunk);
|
|
80
|
+
}
|
|
81
|
+
base64BodyToSend = btoa(binary);
|
|
82
|
+
} else if (typeof args.body === "string") {
|
|
83
|
+
base64BodyToSend = btoa(args.body);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (args.base64Body) {
|
|
87
|
+
base64BodyToSend = args.base64Body;
|
|
88
|
+
}
|
|
89
|
+
|
|
70
90
|
const headers = await createAuthorizedHeaders(
|
|
71
91
|
{
|
|
72
92
|
"content-type": "application/json",
|
|
@@ -77,7 +97,12 @@ export function createStorageClient(
|
|
|
77
97
|
const response = await request(\`\${endpoint}/storage/upload\`, {
|
|
78
98
|
method: "POST",
|
|
79
99
|
headers,
|
|
80
|
-
body: JSON.stringify(
|
|
100
|
+
body: JSON.stringify({
|
|
101
|
+
path: args.path,
|
|
102
|
+
contentType: args.contentType,
|
|
103
|
+
expiresIn: args.expiresIn,
|
|
104
|
+
base64Body: base64BodyToSend,
|
|
105
|
+
}),
|
|
81
106
|
});
|
|
82
107
|
if (!response.ok) {
|
|
83
108
|
throw new Error(await response.text());
|
|
@@ -32,28 +32,6 @@ function createStorageApi(
|
|
|
32
32
|
contentType: args.contentType,
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
if (args.returnSignedUrlOnly) {
|
|
36
|
-
const currentBucket = requireBucket();
|
|
37
|
-
if (typeof currentBucket.createPresignedUrl !== "function") {
|
|
38
|
-
throw new Error("R2 createPresignedUrl is unavailable for this runtime binding");
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const signedRequest = buildSignedRequest(
|
|
42
|
-
{
|
|
43
|
-
path,
|
|
44
|
-
method: "PUT",
|
|
45
|
-
contentType: args.contentType,
|
|
46
|
-
expiresIn: args.expiresIn,
|
|
47
|
-
},
|
|
48
|
-
path,
|
|
49
|
-
);
|
|
50
|
-
const signedUrl = await currentBucket.createPresignedUrl(signedRequest, {
|
|
51
|
-
expiresIn: args.expiresIn ?? 60 * 5,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
return signedUrl.toString();
|
|
55
|
-
}
|
|
56
|
-
|
|
57
35
|
return requireBucket().put(path, args.body, {
|
|
58
36
|
httpMetadata: {
|
|
59
37
|
...(args.httpMetadata ?? {}),
|
|
@@ -98,36 +76,6 @@ function createStorageApi(
|
|
|
98
76
|
include: args.include,
|
|
99
77
|
});
|
|
100
78
|
},
|
|
101
|
-
signedUrl: async (args) => {
|
|
102
|
-
const path = normalizeStoragePath(args.path);
|
|
103
|
-
const requestMethod = args.method ?? "GET";
|
|
104
|
-
const method: StorageMethod =
|
|
105
|
-
requestMethod === "PUT"
|
|
106
|
-
? "put"
|
|
107
|
-
: requestMethod === "DELETE"
|
|
108
|
-
? "delete"
|
|
109
|
-
: args.downloadAsAttachment === false
|
|
110
|
-
? "preview"
|
|
111
|
-
: "download";
|
|
112
|
-
|
|
113
|
-
await assertAuthorized({
|
|
114
|
-
path: "/" + path,
|
|
115
|
-
method,
|
|
116
|
-
contentType: args.contentType,
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
const currentBucket = requireBucket();
|
|
120
|
-
if (typeof currentBucket.createPresignedUrl !== "function") {
|
|
121
|
-
throw new Error("R2 createPresignedUrl is unavailable for this runtime binding");
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const signedRequest = buildSignedRequest(args, path);
|
|
125
|
-
const signedUrl = await currentBucket.createPresignedUrl(signedRequest, {
|
|
126
|
-
expiresIn: args.expiresIn ?? 60 * 5,
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
return signedUrl.toString();
|
|
130
|
-
},
|
|
131
79
|
};
|
|
132
80
|
}
|
|
133
81
|
`;
|
|
@@ -37,25 +37,34 @@ export function registerGeneratedStorageRoutes(
|
|
|
37
37
|
const path = toStoragePath(String(body.path ?? ""));
|
|
38
38
|
const contentType =
|
|
39
39
|
typeof body.contentType === "string" ? body.contentType : undefined;
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
const encodedBody = typeof body.body === "string" ? body.body : undefined;
|
|
41
|
+
const base64Body = typeof body.base64Body === "string" ? body.base64Body : undefined;
|
|
42
|
+
|
|
43
|
+
if (!base64Body && !encodedBody) {
|
|
44
|
+
return c.json(
|
|
45
|
+
{ message: "File content is required. Provide either 'body' or 'base64Body' field." },
|
|
46
|
+
400,
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const uploadBody = base64Body
|
|
51
|
+
? Uint8Array.from(atob(base64Body), (char) => char.charCodeAt(0))
|
|
52
|
+
: encodedBody
|
|
53
|
+
? Uint8Array.from(atob(encodedBody), (char) => char.charCodeAt(0))
|
|
54
|
+
: new Uint8Array();
|
|
44
55
|
|
|
45
|
-
|
|
56
|
+
await ctx.storage.put({
|
|
46
57
|
path,
|
|
47
|
-
body:
|
|
58
|
+
body: uploadBody,
|
|
48
59
|
contentType,
|
|
49
|
-
expiresIn,
|
|
50
|
-
returnSignedUrlOnly: true,
|
|
51
60
|
});
|
|
52
61
|
|
|
53
62
|
return c.json({
|
|
54
|
-
url,
|
|
63
|
+
url: null,
|
|
55
64
|
method: "PUT",
|
|
56
65
|
path,
|
|
57
66
|
contentType,
|
|
58
|
-
|
|
67
|
+
uploaded: true,
|
|
59
68
|
}, 200);
|
|
60
69
|
} catch (error) {
|
|
61
70
|
if (error instanceof AppflareHandledError) {
|
|
@@ -75,20 +84,13 @@ export function registerGeneratedStorageRoutes(
|
|
|
75
84
|
const path = readStoragePath(c);
|
|
76
85
|
const fileName = c.req.query("fileName") ?? undefined;
|
|
77
86
|
const expiresIn = parseExpiresIn(c.req.query("expiresIn"));
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return c.json({
|
|
87
|
-
url,
|
|
88
|
-
method: "GET",
|
|
89
|
-
path,
|
|
90
|
-
disposition: "attachment",
|
|
91
|
-
}, 200);
|
|
87
|
+
|
|
88
|
+
// For now, we'll return an error since signed URLs are not available
|
|
89
|
+
// In the future, we could implement direct file serving here
|
|
90
|
+
return c.json(
|
|
91
|
+
{ message: "Download via signed URL is not available in this runtime. Use direct file access instead." },
|
|
92
|
+
501,
|
|
93
|
+
);
|
|
92
94
|
} catch (error) {
|
|
93
95
|
if (error instanceof AppflareHandledError) {
|
|
94
96
|
return c.json(error.payload, error.status as any);
|
|
@@ -106,19 +108,13 @@ export function registerGeneratedStorageRoutes(
|
|
|
106
108
|
try {
|
|
107
109
|
const path = readStoragePath(c);
|
|
108
110
|
const expiresIn = parseExpiresIn(c.req.query("expiresIn"));
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return c.json({
|
|
117
|
-
url,
|
|
118
|
-
method: "GET",
|
|
119
|
-
path,
|
|
120
|
-
disposition: "inline",
|
|
121
|
-
}, 200);
|
|
111
|
+
|
|
112
|
+
// For now, we'll return an error since signed URLs are not available
|
|
113
|
+
// In the future, we could implement direct file serving here
|
|
114
|
+
return c.json(
|
|
115
|
+
{ message: "Preview via signed URL is not available in this runtime. Use direct file access instead." },
|
|
116
|
+
501,
|
|
117
|
+
);
|
|
122
118
|
} catch (error) {
|
|
123
119
|
if (error instanceof AppflareHandledError) {
|
|
124
120
|
return c.json(error.payload, error.status as any);
|
|
@@ -49,7 +49,6 @@ export type AppflareStorage = {
|
|
|
49
49
|
get: (args: StorageGetArgs) => Promise<unknown | null>;
|
|
50
50
|
delete: (args: StorageDeleteArgs) => Promise<void>;
|
|
51
51
|
list: (args?: StorageListArgs) => Promise<unknown>;
|
|
52
|
-
signedUrl: (args: StorageSignedUrlArgs) => Promise<string>;
|
|
53
52
|
};
|
|
54
53
|
|
|
55
54
|
export type AppflareContext = {
|