Skip to content

Commit 32ab736

Browse files
Merge pull request #847 from appwrite/feat-pull-function
Feat pull function
2 parents 634679a + 283a063 commit 32ab736

File tree

5 files changed

+129
-19
lines changed

5 files changed

+129
-19
lines changed

templates/cli/base/params.twig

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,10 @@
7575
{% endif %}
7676
{% endfor %}
7777
{% if method.type == 'location' %}
78-
payload['project'] = localConfig.getProject().projectId
79-
payload['key'] = globalConfig.getKey();
80-
const queryParams = new URLSearchParams(payload);
81-
apiPath = `${globalConfig.getEndpoint()}${apiPath}?${queryParams.toString()}`;
78+
if (!overrideForCli) {
79+
payload['project'] = localConfig.getProject().projectId
80+
payload['key'] = globalConfig.getKey();
81+
const queryParams = new URLSearchParams(payload);
82+
apiPath = `${globalConfig.getEndpoint()}${apiPath}?${queryParams.toString()}`;
83+
}
8284
{% endif %}

templates/cli/base/requests/api.twig

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@
99
{% endfor %}
1010
}, payload{% if method.type == 'location' %}, 'arraybuffer'{% endif %});
1111

12-
{% if method.type == 'location' %}
13-
fs.writeFileSync(destination, response);
12+
{%~ if method.type == 'location' %}
13+
if (overrideForCli) {
14+
response = Buffer.from(response);
15+
}
1416

15-
{% endif %}
17+
fs.writeFileSync(destination, response);
18+
{%~ endif %}
1619
if (parseOutput) {
1720
parse(response)
1821
success()
1922
}
20-
21-
return response;
23+
24+
return response;

templates/cli/lib/commands/command.js.twig

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const {{ service.name | caseLower }} = new Command("{{ service.name | caseLower
4545
{% for parameter in method.parameters.all %}
4646
* @property {{ "{" }}{{ parameter | typeName }}{{ "}" }} {{ parameter.name | caseCamel | escapeKeyword }} {{ parameter.description | replace({'`':'\''}) | replace({'\n':' '}) | replace({'\n \n':' '}) }}
4747
{% endfor %}
48+
* @property {boolean} overrideForCli
4849
* @property {boolean} parseOutput
4950
* @property {libClient | undefined} sdk
5051
{% if 'multipart/form-data' in method.consumes %}
@@ -58,8 +59,21 @@ const {{ service.name | caseLower }} = new Command("{{ service.name | caseLower
5859
/**
5960
* @param {{ "{" }}{{ service.name | caseUcfirst }}{{ method.name | caseUcfirst }}RequestParams{{ "}" }} params
6061
*/
61-
const {{ service.name | caseLower }}{{ method.name | caseUcfirst }} = async ({ {% for parameter in method.parameters.all %}{{ parameter.name | caseCamel | escapeKeyword }}, {% endfor %}parseOutput = true, sdk = undefined{% if 'multipart/form-data' in method.consumes %}, onProgress = () => {}{% endif %}{% if method.type == 'location' %}, destination{% endif %}}) => {
62-
let client = !sdk ? await {% if service.name == "projects" %}sdkForConsole(){% else %}sdkForProject(){% endif %} : sdk;
62+
{%~ block decleration -%}
63+
const {{ service.name | caseLower }}{{ method.name | caseUcfirst }} = async ({
64+
{%- for parameter in method.parameters.all -%}
65+
{{ parameter.name | caseCamel | escapeKeyword }},
66+
{%- endfor -%}
67+
68+
{%- block baseParams -%}parseOutput = true, overrideForCli = false, sdk = undefined {%- endblock -%}
69+
70+
{%- if 'multipart/form-data' in method.consumes -%},onProgress = () => {}{%- endif -%}
71+
72+
{%- if method.type == 'location' -%}, destination{%- endif -%}
73+
}) => {
74+
{%~ endblock %}
75+
let client = !sdk ? await {% if service.name == "projects" %}sdkForConsole(){% else %}sdkForProject(){% endif %} :
76+
sdk;
6377
let apiPath = '{{ method.path }}'{% for parameter in method.parameters.path %}.replace('{{ '{' }}{{ parameter.name | caseCamel }}{{ '}' }}', {{ parameter.name | caseCamel | escapeKeyword }}){% endfor %};
6478
{{ include ('cli/base/params.twig') }}
6579
{% if 'multipart/form-data' in method.consumes %}
@@ -90,4 +104,4 @@ module.exports = {
90104
{{ service.name | caseLower }}{{ method.name | caseUcfirst }}{% if not loop.last %},{% endif %}
91105

92106
{% endfor %}
93-
};
107+
};

templates/cli/lib/commands/pull.js.twig

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1+
const fs = require("fs");
2+
const tar = require("tar");
13
const { Command } = require("commander");
24
const inquirer = require("inquirer");
35
const { messagingCreateTopic, messagingListTopics } = require("./messaging");
46
const { teamsCreate, teamsList } = require("./teams");
57
const { projectsCreate } = require("./projects");
8+
const { functionsList, functionsDownloadDeployment } = require("./functions");
69
const { databasesGet, databasesListCollections, databasesList } = require("./databases");
710
const { storageListBuckets } = require("./storage");
811
const { sdkForConsole } = require("../sdks");
912
const { localConfig } = require("../config");
1013
const { paginate } = require("../paginate");
11-
const { questionsPullProject, questionsPullCollection } = require("../questions");
14+
const { questionsPullProject, questionsPullCollection, questionsPullFunctions } = require("../questions");
1215
const { success, log, actionRunner, commandDescriptions } = require("../parser");
1316

1417
const pull = new Command("pull")
@@ -28,6 +31,64 @@ const pullProject = async () => {
2831
success();
2932
}
3033

34+
const pullFunctions = async ({ all, yes } = {}) => {
35+
let functions = [];
36+
let questions = questionsPullFunctions;
37+
38+
const localFunctions = localConfig.getFunctions();
39+
40+
if (all) {
41+
questions = yes ? [] : questionsPullFunctions[1];
42+
functions = (await paginate(functionsList, { parseOutput: false }, 100, 'functions')).functions;
43+
}
44+
45+
const answers = await inquirer.prompt(questions);
46+
47+
const overridingLocalChanges = yes ?? answers.override.toLowerCase() === "yes";
48+
const selectedFunctions = functions.length === 0 ? answers.functions : functions;
49+
50+
for (let func of selectedFunctions) {
51+
const functionExistLocally = localFunctions.find((localFunc) => localFunc['$id'] === func['$id']) !== undefined;
52+
53+
if (!overridingLocalChanges && functionExistLocally) {
54+
log(`Skipping locally found implementation of ${func['name']}`)
55+
continue;
56+
}
57+
if (functionExistLocally) {
58+
localConfig.updateFunction(func['$id'], func);
59+
} else {
60+
func['path'] = `functions/${func['$id']}`;
61+
localConfig.addFunction(func);
62+
}
63+
64+
const localFunction = localFunctions.find((localFunc) => localFunc['$id'] === func['$id']);
65+
66+
if (localFunction['deployment'] === '') {
67+
continue
68+
}
69+
70+
const compressedFileName = `${+new Date()}.tar.gz`
71+
72+
await functionsDownloadDeployment({
73+
functionId: func['$id'],
74+
deploymentId: func['deployment'],
75+
destination: compressedFileName,
76+
overrideForCli: true,
77+
parseOutput: false
78+
})
79+
80+
tar.extract({
81+
sync: true,
82+
cwd: localFunction['path'],
83+
file: compressedFileName,
84+
strict: false,
85+
});
86+
87+
fs.rmSync(compressedFileName);
88+
success(`Pulled ${func['name']} code and definition`)
89+
}
90+
}
91+
3192
const pullCollection = async ({ all, databaseId } = {}) => {
3293
const databaseIds = [];
3394

@@ -117,14 +178,21 @@ const pullMessagingTopic = async () => {
117178

118179
pull
119180
.command("project")
120-
.description("Pulling your {{ spec.title|caseUcfirst }} project")
181+
.description("Pulling your Appwrite project")
121182
.action(actionRunner(pullProject));
122183

184+
pull
185+
.command("function")
186+
.description(`Pulling your Appwrite functions`)
187+
.option(`--yes`, `Flag to confirm all warnings`)
188+
.option(`--all`, `Flag to pull all functions`)
189+
.action(actionRunner(pullFunctions));
190+
123191
pull
124192
.command("collection")
125-
.description("Pulling your {{ spec.title|caseUcfirst }} collections")
193+
.description("Pulling your Appwrite collections")
126194
.option(`--databaseId <databaseId>`, `Database ID`)
127-
.option(`--all`, `Flag to pullialize all databases`)
195+
.option(`--all`, `Flag to pull all databases`)
128196
.action(actionRunner(pullCollection))
129197

130198
pull

templates/cli/lib/questions.js.twig

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
const { localConfig } = require('./config');
22
const { projectsList } = require('./commands/projects');
33
const { teamsList } = require('./commands/teams');
4-
const { functionsListRuntimes } = require('./commands/functions');
4+
const { functionsListRuntimes, functionsList } = require('./commands/functions');
55
const { accountListMfaFactors } = require("./commands/account");
66
const { sdkForConsole } = require("./sdks");
77
const { validateRequired } = require("./validations");
88
const { paginate } = require('./paginate');
9-
9+
const chalk = require('chalk');
1010
const { databasesList } = require('./commands/databases');
1111
const JSONbig = require("json-bigint")({ storeAsString: false });
1212

@@ -200,6 +200,29 @@ const questionsPullProject = [
200200
}
201201
];
202202

203+
const questionsPullFunctions = [
204+
{
205+
type: "checkbox",
206+
name: "functions",
207+
message: "Which functions would you like to pull?",
208+
choices: async () => {
209+
const { functions } = await paginate(functionsList, { parseOutput: false }, 100, 'functions');
210+
211+
return functions.map(func => {
212+
return {
213+
name: `${func.name} (${func.$id})`,
214+
value: func
215+
}
216+
});
217+
}
218+
},
219+
{
220+
type: "input",
221+
name: "override",
222+
message: `Are you sure you want to override local functions code and definition? ${chalk.red('All local changes will be lost!')} Type "YES" to confirm.`
223+
}
224+
];
225+
203226
const questionsCreateFunction = [
204227
{
205228
type: "input",
@@ -316,7 +339,6 @@ const questionsCreateMessagingTopic = [
316339
}
317340
];
318341

319-
320342
const questionsPullCollection = [
321343
{
322344
type: "checkbox",
@@ -585,6 +607,7 @@ module.exports = {
585607
questionsCreateCollection,
586608
questionsCreateMessagingTopic,
587609
questionsPullProject,
610+
questionsPullFunctions,
588611
questionsLogin,
589612
questionsPullCollection,
590613
questionsPushResources,

0 commit comments

Comments
 (0)