-
Notifications
You must be signed in to change notification settings - Fork 44
[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 1 commit
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,60 @@ | ||
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: any; | ||
|
||
constructor(data: any) { | ||
vermakhushboo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
this.data = data; | ||
} | ||
|
||
// converts JSON to binary data (Buffer) | ||
static async fromJson(json: object): Promise<NewPayload> { | ||
vermakhushboo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
const jsonString = JSON.stringify(json); | ||
const encoder = new TextEncoder(); | ||
const buffer = encoder.encode(jsonString); | ||
return new NewPayload(buffer); | ||
} | ||
|
||
// converts file to binary data (Buffer) | ||
static fromPath(path: string): NewPayload { | ||
const realPath = realpathSync(path); | ||
const contents = readFileSync(realPath); | ||
return new NewPayload(new Uint8Array(contents)); | ||
} | ||
|
||
// converts text to binary data (Buffer) | ||
static async fromPlainText(text: string): Promise<NewPayload> { | ||
vermakhushboo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
const arrayBytes = new TextEncoder().encode(text); | ||
return new NewPayload(arrayBytes); | ||
} | ||
|
||
async fromBinary(): Promise<NewPayload> { | ||
return new NewPayload(this.data); | ||
} | ||
vermakhushboo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
// converts binary data (Buffer) to JSON | ||
async toJson(): Promise<any> { | ||
|
||
const decoder = new TextDecoder(); | ||
const jsonString = decoder.decode(this.data); | ||
return JSON.parse(jsonString); | ||
} | ||
|
||
// convert binary data (Buffer) to file | ||
async toFile(fileName: string): Promise<File> { | ||
|
||
const blob = new Blob([this.data]); | ||
return new File([blob], fileName); | ||
|
||
} | ||
|
||
// converts binary data (Buffer) to text | ||
async toPlainText(): Promise<string> { | ||
const decoder = new TextDecoder(); | ||
return decoder.decode(this.data); | ||
} | ||
|
||
toBinary(): Uint8Array { | ||
vermakhushboo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
return Uint8Array.from(this.data); | ||
vermakhushboo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
|
||
public getData(): any { | ||
|
||
return this.data; | ||
} | ||
} |
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; | ||
|
@@ -32,6 +35,16 @@ class AppwriteException extends Error { | |
} | ||
} | ||
|
||
function getBoundary(str: string): string { | ||
vermakhushboo marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
const lines = str.replaceAll("\r\n", "\n").split("\n").reverse(); | ||
for (const line of lines) { | ||
if (line !== "") { | ||
return line.slice(0, -2).slice(2); | ||
} | ||
} | ||
return ""; | ||
} | ||
|
||
function getUserAgent() { | ||
let ua = 'AppwriteNodeJSSDK/13.0.0'; | ||
|
||
|
@@ -331,7 +344,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 = getBoundary(body.toString()); | ||
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.
Outdated
Show resolved
Hide resolved
|
||
data = { | ||
...partsObject, | ||
|
||
responseBody: new NewPayload(partsObject.responseBody) | ||
|
||
} | ||
} | ||
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; | ||
|
||
} | ||
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.