Skip to content

Commit

Permalink
feat: migrate cli to fetch
Browse files Browse the repository at this point in the history
  • Loading branch information
loks0n committed Dec 27, 2023
1 parent 21743f4 commit 40083d9
Show file tree
Hide file tree
Showing 7 changed files with 322 additions and 258 deletions.
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 40083d9

Please sign in to comment.