Skip to content

Commit

Permalink
Merge pull request #771 from appwrite/feat-replace-axios
Browse files Browse the repository at this point in the history
Replace Axios with Undici
  • Loading branch information
christyjacob4 authored Feb 14, 2024
2 parents 196595b + 7361d91 commit 8d308f7
Show file tree
Hide file tree
Showing 11 changed files with 373 additions and 272 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
fail-fast: false
matrix:
php-version: ['8.1']
sdk: [Android11Java8, Android11Java11, Android12Java8, Android12Java11, CLINode14, CLINode16, DartBeta, DartStable, Deno1193, Deno1303, DotNet60, DotNet70, FlutterStable, FlutterBeta, Go112, Go118, KotlinJava8, KotlinJava11, KotlinJava17, Node12, Node14, Node16, PHP74, PHP80, Python38, Python39, Python310, Ruby27, Ruby30, Ruby31, AppleSwift55, Swift55, WebChromium, WebNode]
sdk: [Android11Java8, Android11Java11, Android12Java8, Android12Java11, CLINode16, CLINode18, DartBeta, DartStable, Deno1193, Deno1303, DotNet60, DotNet70, FlutterStable, FlutterBeta, Go112, Go118, KotlinJava8, KotlinJava11, KotlinJava17, Node12, Node14, Node16, PHP74, PHP80, Python38, Python39, Python310, Ruby27, Ruby30, Ruby31, AppleSwift55, Swift55, WebChromium, WebNode]

steps:
- name: Checkout repository
Expand Down
12 changes: 12 additions & 0 deletions mock-server/app/http.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@
'buffer_output_size' => $payloadSize,
]);

// Version Route for CLI
App::get('/v1/health/version')
->desc('Get version')
->groups(['api', 'health'])
->label('scope', 'public')
->label('sdk.response.code', Response::STATUS_CODE_OK)
->label('sdk.response.type', Response::CONTENT_TYPE_JSON)
->inject('response')
->action(function (UtopiaSwooleResponse $response) {
$response->json([ 'version' => '1.0.0' ]);
});

// Mock Routes
App::get('/v1/mock/tests/foo')
->desc('Get Foo')
Expand Down
27 changes: 27 additions & 0 deletions src/SDK/Language/CLI.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,33 @@ public function getFiles(): array
];
}

/**
* @param array $parameter
* @param array $nestedTypes
* @return string
*/
public function getTypeName(array $parameter, array $spec = []): string
{
if (isset($parameter['enumName'])) {
return \ucfirst($parameter['enumName']);
}
if (!empty($parameter['enumValues'])) {
return \ucfirst($parameter['name']);
}
return match ($parameter['type']) {
self::TYPE_INTEGER,
self::TYPE_NUMBER => 'number',
self::TYPE_STRING => 'string',
self::TYPE_FILE => 'string',
self::TYPE_BOOLEAN => 'boolean',
self::TYPE_OBJECT => 'object',
self::TYPE_ARRAY => (!empty(($parameter['array'] ?? [])['type']) && !\is_array($parameter['array']['type']))
? $this->getTypeName($parameter['array']) . '[]'
: 'string[]',
default => $parameter['type'],
};
}

/**
* @param array $param
* @return string
Expand Down
79 changes: 79 additions & 0 deletions templates/cli/base/params.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
let payload = {};
{% for parameter in method.parameters.query %}
if (typeof {{ parameter.name | caseCamel | escapeKeyword }} !== 'undefined') {
payload['{{ parameter.name }}'] = {{ parameter.name | caseCamel | escapeKeyword }};
}
{% endfor %}
{% for parameter in method.parameters.body %}
{% if parameter.type == 'file' %}
{% if method.packaging %}
const folderPath = fs.realpathSync({{ parameter.name | caseCamel | escapeKeyword }});
if (!fs.lstatSync(folderPath).isDirectory()) {
throw new Error('The path is not a directory.');
}

const ignorer = ignore();

const func = localConfig.getFunction(functionId);

if (func.ignore) {
ignorer.add(func.ignore);
log('Ignoring files using configuration from appwrite.json');
} else if (fs.existsSync(pathLib.join({{ parameter.name | caseCamel | escapeKeyword }}, '.gitignore'))) {
ignorer.add(fs.readFileSync(pathLib.join({{ parameter.name | caseCamel | escapeKeyword }}, '.gitignore')).toString());
log('Ignoring files in .gitignore');
}

const files = getAllFiles({{ parameter.name | caseCamel | escapeKeyword }}).map((file) => pathLib.relative({{ parameter.name | caseCamel | escapeKeyword }}, file)).filter((file) => !ignorer.ignores(file));

await tar
.create({
gzip: true,
sync: true,
cwd: folderPath,
file: 'code.tar.gz'
}, files);

{% endif %}
const filePath = fs.realpathSync({{ parameter.name | caseCamel | escapeKeyword }});
const nodeStream = fs.createReadStream(filePath);
const stream = convertReadStreamToReadableStream(nodeStream);

if (typeof filePath !== 'undefined') {
{{ parameter.name | caseCamel | escapeKeyword }} = { type: 'file', stream, filename: pathLib.basename(filePath), size: fs.statSync(filePath).size };
payload['{{ parameter.name }}'] = {{ parameter.name | caseCamel | escapeKeyword }}
}
{% elseif parameter.type == 'boolean' %}
if (typeof {{ parameter.name | caseCamel | escapeKeyword }} !== 'undefined') {
payload['{{ parameter.name }}'] = {{ parameter.name | caseCamel | escapeKeyword }};
}
{% elseif parameter.type == 'number' %}
if (typeof {{ parameter.name | caseCamel | escapeKeyword }} !== 'undefined') {
payload['{{ parameter.name }}'] = {{ parameter.name | caseCamel | escapeKeyword }};
}
{% elseif parameter.type == 'string' %}
if (typeof {{ parameter.name | caseCamel | escapeKeyword }} !== 'undefined') {
payload['{{ parameter.name }}'] = {{ parameter.name | caseCamel | escapeKeyword }};
}
{% elseif parameter.type == 'object' %}
if (typeof {{ parameter.name | caseCamel | escapeKeyword }} !== 'undefined') {
payload['{{ parameter.name }}'] = JSON.parse({{ parameter.name | caseCamel | escapeKeyword}});
}
{% elseif parameter.type == 'array' %}
{{ parameter.name | caseCamel | escapeKeyword}} = {{ parameter.name | caseCamel | escapeKeyword}} === true ? [] : {{ parameter.name | caseCamel | escapeKeyword}};
if (typeof {{ parameter.name | caseCamel | escapeKeyword }} !== 'undefined') {
payload['{{ parameter.name }}'] = {{ parameter.name | caseCamel | escapeKeyword}};
}
{% else %}
if (typeof {{ parameter.name | caseCamel | escapeKeyword }} !== 'undefined') {
payload['{{ parameter.name }}'] = {{ parameter.name | caseCamel | escapeKeyword}}{% if method.consumes[0] == "multipart/form-data" %}.toString(){% endif %};
}
{% endif %}
{% endfor %}

{% if method.type == 'location' %}
payload['project'] = localConfig.getProject().projectId
payload['key'] = globalConfig.getKey();
const queryParams = new URLSearchParams(payload);
apiPath = `${globalConfig.getEndpoint()}${apiPath}?${queryParams.toString()}`;
{% endif %}
21 changes: 21 additions & 0 deletions templates/cli/base/requests/api.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
let response = undefined;

response = await client.call('{{ method.method | caseLower }}', apiPath, {
{% for parameter in method.parameters.header %}
'{{ parameter.name }}': ${{ parameter.name | caseCamel | escapeKeyword }},
{% endfor %}
{% for key, header in method.headers %}
'{{ key }}': '{{ header }}',
{% endfor %}
}, payload{% if method.type == 'location' %}, 'arraybuffer'{% endif %});

{% if method.type == 'location' %}
fs.writeFileSync(destination, response);
{% endif %}

if (parseOutput) {
parse(response)
success()
}

return response;
116 changes: 116 additions & 0 deletions templates/cli/base/requests/file.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
{% for parameter in method.parameters.all %}
{% if parameter.type == 'file' %}

const size = {{ parameter.name | caseCamel | escapeKeyword }}.size;

const apiHeaders = {
{% for parameter in method.parameters.header %}
'{{ parameter.name }}': ${{ parameter.name | caseCamel | escapeKeyword }},
{% endfor %}
{% for key, header in method.headers %}
'{{ key }}': '{{ header }}',
{% endfor %}
};

let id = undefined;
let response = undefined;

let chunksUploaded = 0;
{% for parameter in method.parameters.all %}
{% if parameter.isUploadID %}

if({{ parameter.name | caseCamel | escapeKeyword }} != 'unique()') {
try {
response = await client.call('get', apiPath + '/' + {{ parameter.name }}, apiHeaders);
chunksUploaded = response.chunksUploaded;
} catch(e) {
}
}
{% endif %}
{% endfor %}

let currentChunk = 1;
let currentPosition = 0;
let uploadableChunk = new Uint8Array(client.CHUNK_SIZE);

const uploadChunk = async (lastUpload = false) => {
if(currentChunk <= chunksUploaded) {
return;
}

const start = ((currentChunk - 1) * client.CHUNK_SIZE);
let end = start + currentPosition - 1;

if(!lastUpload || currentChunk !== 1) {
apiHeaders['content-range'] = 'bytes ' + start + '-' + end + '/' + size;
}

let uploadableChunkTrimmed;

if(currentPosition + 1 >= client.CHUNK_SIZE) {
uploadableChunkTrimmed = uploadableChunk;
} else {
uploadableChunkTrimmed = new Uint8Array(currentPosition);
for(let i = 0; i <= currentPosition; i++) {
uploadableChunkTrimmed[i] = uploadableChunk[i];
}
}

if (id) {
apiHeaders['x-{{spec.title | caseLower }}-id'] = id;
}

payload['{{ parameter.name }}'] = { type: 'file', file: new File([uploadableChunkTrimmed], {{ parameter.name | caseCamel | escapeKeyword }}.filename), filename: {{ parameter.name | caseCamel | escapeKeyword }}.filename };

response = await client.call('{{ method.method | caseLower }}', apiPath, apiHeaders, payload{% if method.type == 'location' %}, 'arraybuffer'{% endif %});

if (!id) {
id = response['$id'];
}

if (onProgress !== null) {
onProgress({
$id: response['$id'],
progress: Math.min((currentChunk) * client.CHUNK_SIZE, size) / size * 100,
sizeUploaded: end+1,
chunksTotal: response['chunksTotal'],
chunksUploaded: response['chunksUploaded']
});
}

uploadableChunk = new Uint8Array(client.CHUNK_SIZE);
currentChunk++;
currentPosition = 0;
}

for await (const chunk of {{ parameter.name | caseCamel | escapeKeyword }}.stream) {
for(const b of chunk) {
uploadableChunk[currentPosition] = b;

currentPosition++;
if(currentPosition >= client.CHUNK_SIZE) {
await uploadChunk();
currentPosition = 0;
}
}
}

if (currentPosition > 0) { // Check if there's any remaining data for the last chunk
await uploadChunk(true);
}

{% if method.packaging %}
fs.unlinkSync(filePath);
{% endif %}
{% if method.type == 'location' %}
fs.writeFileSync(destination, response);
{% endif %}

if (parseOutput) {
parse(response)
success()
}

return response;
{% endif %}
{% endfor %}
Loading

0 comments on commit 8d308f7

Please sign in to comment.