-
Notifications
You must be signed in to change notification settings - Fork 41
[Test PR] SDK Multipart support #93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I dont see type change.. like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have added There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { realpathSync, readFileSync } from "fs"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we import |
||
export class NewPayload { | ||
vermakhushboo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
private data: Buffer; | ||
|
||
constructor(data: Buffer) { | ||
this.data = data; | ||
} | ||
|
||
public getData(): Buffer { | ||
return this.data; | ||
} | ||
|
||
public static fromBuffer(buffer: Buffer): Buffer { | ||
return Buffer.from(buffer); | ||
} | ||
vermakhushboo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
public toBuffer(): Buffer { | ||
vermakhushboo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return this.data; | ||
} | ||
|
||
public static fromString(string: string): Buffer { | ||
return Buffer.from(string); | ||
} | ||
|
||
public toString(encoding: BufferEncoding = "utf8"): string { | ||
return this.data.toString(encoding); | ||
} | ||
|
||
public static fromJSON(json: object): Buffer { | ||
return Buffer.from(JSON.stringify(json)); | ||
} | ||
|
||
public toJSON(): object { | ||
return JSON.parse(this.data.toString()); | ||
} | ||
|
||
public static fromPath(path: string): Buffer { | ||
vermakhushboo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const realPath = realpathSync(path); | ||
const contents = readFileSync(realPath); | ||
return Buffer.from(contents); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Manually QA fromFile and fromPath. Upload a picture to Storage service. Then see the picture in Appwrite Console. Does it know it's PNG? Can you preview it? If not, we need to fix it. |
||
} | ||
|
||
public toFile(fileName: string): File { | ||
vermakhushboo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const blob = new Blob([this.data]); | ||
return new File([blob], fileName); | ||
vermakhushboo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
import { fetch, FormData, File } from 'node-fetch-native-with-agent'; | ||
import { createAgent } from 'node-fetch-native-with-agent/agent'; | ||
import { Models } from './models'; | ||
import { NewPayload } from './NewPayload'; | ||
import * as multipart from 'parse-multipart-data'; | ||
const { buffer } = require('node:stream/consumers'); | ||
|
||
type Payload = { | ||
[key: string]: any; | ||
|
@@ -331,7 +334,22 @@ class Client { | |
data = await response.json(); | ||
} else if (responseType === 'arrayBuffer') { | ||
data = await response.arrayBuffer(); | ||
} else { | ||
} else if (response.headers.get('content-type')?.includes('multipart/form-data')) { | ||
const body = await buffer(response.body); | ||
const boundary = multipart.getBoundary(response.headers.get('content-type') || ''); | ||
const parts = multipart.parse(body, boundary); | ||
const partsObject = parts.reduce<{ [key: string]: Buffer }>((acc, part) => { | ||
if (part.name) { | ||
acc[part.name] = part.data; | ||
} | ||
return acc; | ||
}, {}); | ||
vermakhushboo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
data = { | ||
...partsObject, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think everything in multipart response is string. Try createExecution, and print it. See what is type of |
||
responseBody: new NewPayload(partsObject.responseBody) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ResponseBody can be empty. in which case it would probably be.. empty string? in which case, it might not fit the buffer type? Just thinking out lit. its something to test - to make async execution (that doesn't have body) and see if all works fine |
||
} | ||
} | ||
else { | ||
data = { | ||
message: await response.text() | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,3 +33,5 @@ export { ImageGravity } from './enums/image-gravity'; | |
export { ImageFormat } from './enums/image-format'; | ||
export { PasswordHash } from './enums/password-hash'; | ||
export { MessagingProviderType } from './enums/messaging-provider-type'; | ||
export { NewPayload } from './NewPayload'; | ||
export { InputFile } from './inputFile'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should remove all mention of InputFile. It should no longer exist. With that, we also need to update existing endpoints that used to need it. they all should now use payload class |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ import { AppwriteException, Client, type Payload, UploadProgress } from '../clie | |
import type { Models } from '../models'; | ||
import { Runtime } from '../enums/runtime'; | ||
import { ExecutionMethod } from '../enums/execution-method'; | ||
import { NewPayload } from '../NewPayload'; | ||
|
||
export class Functions { | ||
client: Client; | ||
|
@@ -624,22 +625,22 @@ Use the "command" param to set the entrypoint used to execute your cod | |
* Trigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously. | ||
* | ||
* @param {string} functionId | ||
* @param {string} body | ||
* @param {NewPayload} body | ||
* @param {boolean} async | ||
* @param {string} xpath | ||
* @param {ExecutionMethod} method | ||
* @param {object} headers | ||
* @throws {AppwriteException} | ||
* @returns {Promise<Models.Execution>} | ||
*/ | ||
async createExecution(functionId: string, body?: string, async?: boolean, xpath?: string, method?: ExecutionMethod, headers?: object): Promise<Models.Execution> { | ||
async createExecution(functionId: string, body?: NewPayload, async?: boolean, xpath?: string, method?: ExecutionMethod, headers?: object): Promise<Models.Execution> { | ||
if (typeof functionId === 'undefined') { | ||
throw new AppwriteException('Missing required parameter: "functionId"'); | ||
} | ||
const apiPath = '/functions/{functionId}/executions'.replace('{functionId}', functionId); | ||
const payload: Payload = {}; | ||
if (typeof body !== 'undefined') { | ||
payload['body'] = body; | ||
payload['body'] = body ? body.getData : body; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, I dont understand the check. It doesn't make sense, right? |
||
} | ||
if (typeof async !== 'undefined') { | ||
payload['async'] = async; | ||
|
@@ -656,7 +657,8 @@ Use the "command" param to set the entrypoint used to execute your cod | |
const uri = new URL(this.client.config.endpoint + apiPath); | ||
|
||
const apiHeaders: { [header: string]: string } = { | ||
'content-type': 'application/json', | ||
'content-type': 'multipart/form-data', | ||
'accept': 'multipart/form-data', | ||
} | ||
|
||
return await this.client.call( | ||
|
Uh oh!
There was an error while loading. Please reload this page.