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.
@@ -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(args),
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());
@@ -148,6 +148,8 @@ export type StorageClient = {
148
148
  path: string;
149
149
  contentType?: string;
150
150
  expiresIn?: number;
151
+ base64Body?: string;
152
+ body?: string | File;
151
153
  }) => Promise<StorageSignedUrlResponse>;
152
154
  download: (args: {
153
155
  path: string;
@@ -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 expiresIn =
41
- typeof body.expiresIn === "number" && body.expiresIn > 0
42
- ? Math.floor(body.expiresIn)
43
- : undefined;
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
- const url = await ctx.storage.put({
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
- expiresIn: expiresIn ?? 300,
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
- const url = await ctx.storage.signedUrl({
79
- path,
80
- method: "GET",
81
- expiresIn,
82
- downloadAsAttachment: true,
83
- fileName,
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
- const url = await ctx.storage.signedUrl({
110
- path,
111
- method: "GET",
112
- expiresIn,
113
- downloadAsAttachment: false,
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 = {