appwrite-cli 9.0.2 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +2 -2
- package/docs/examples/databases/create-line-attribute.md +5 -0
- package/docs/examples/databases/create-point-attribute.md +5 -0
- package/docs/examples/databases/create-polygon-attribute.md +5 -0
- package/docs/examples/databases/update-line-attribute.md +5 -0
- package/docs/examples/databases/update-point-attribute.md +5 -0
- package/docs/examples/databases/update-polygon-attribute.md +5 -0
- package/docs/examples/tablesdb/create-line-column.md +5 -0
- package/docs/examples/tablesdb/create-point-column.md +5 -0
- package/docs/examples/tablesdb/create-polygon-column.md +5 -0
- package/docs/examples/tablesdb/update-line-column.md +5 -0
- package/docs/examples/tablesdb/update-point-column.md +5 -0
- package/docs/examples/tablesdb/update-polygon-column.md +5 -0
- package/index.js +0 -2
- package/install.ps1 +2 -2
- package/install.sh +1 -1
- package/lib/client.js +2 -2
- package/lib/commands/databases.js +336 -0
- package/lib/commands/functions.js +2 -2
- package/lib/commands/generic.js +5 -5
- package/lib/commands/init.js +3 -1
- package/lib/commands/pull.js +24 -12
- package/lib/commands/push.js +27 -9
- package/lib/commands/tables-db.js +338 -2
- package/lib/commands/types.js +54 -15
- package/lib/config.js +57 -33
- package/lib/parser.js +5 -2
- package/lib/questions.js +6 -6
- package/lib/type-generation/languages/csharp.js +170 -0
- package/lib/type-generation/languages/javascript.js +2 -2
- package/lib/type-generation/languages/typescript.js +4 -2
- package/package.json +1 -1
- package/scoop/appwrite.config.json +3 -3
- package/docs/examples/avatars/get-browser.md +0 -2
- package/docs/examples/avatars/get-credit-card.md +0 -2
- package/docs/examples/avatars/get-favicon.md +0 -2
- package/docs/examples/avatars/get-flag.md +0 -2
- package/docs/examples/avatars/get-image.md +0 -2
- package/docs/examples/avatars/get-initials.md +0 -1
- package/docs/examples/avatars/get-qr.md +0 -2
- package/lib/commands/avatars.js +0 -484
package/lib/commands/types.js
CHANGED
|
@@ -12,6 +12,7 @@ const { Swift } = require("../type-generation/languages/swift");
|
|
|
12
12
|
const { Java } = require("../type-generation/languages/java");
|
|
13
13
|
const { Dart } = require("../type-generation/languages/dart");
|
|
14
14
|
const { JavaScript } = require("../type-generation/languages/javascript");
|
|
15
|
+
const { CSharp } = require("../type-generation/languages/csharp");
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* @param {string} language
|
|
@@ -33,6 +34,8 @@ function createLanguageMeta(language) {
|
|
|
33
34
|
return new Java();
|
|
34
35
|
case "dart":
|
|
35
36
|
return new Dart();
|
|
37
|
+
case "cs":
|
|
38
|
+
return new CSharp();
|
|
36
39
|
default:
|
|
37
40
|
throw new Error(`Language '${language}' is not supported`);
|
|
38
41
|
}
|
|
@@ -55,7 +58,7 @@ const typesLanguageOption = new Option(
|
|
|
55
58
|
"-l, --language <language>",
|
|
56
59
|
"The language of the types"
|
|
57
60
|
)
|
|
58
|
-
.choices(["auto", "ts", "js", "php", "kotlin", "swift", "java", "dart"])
|
|
61
|
+
.choices(["auto", "ts", "js", "php", "kotlin", "swift", "java", "dart", "cs"])
|
|
59
62
|
.default("auto");
|
|
60
63
|
|
|
61
64
|
const typesStrictOption = new Option(
|
|
@@ -97,22 +100,58 @@ const typesCommand = actionRunner(async (rawOutputDirectory, {language, strict})
|
|
|
97
100
|
fs.mkdirSync(outputDirectory, { recursive: true });
|
|
98
101
|
}
|
|
99
102
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
103
|
+
// Try tables first, fallback to collections
|
|
104
|
+
let tables = localConfig.getTables();
|
|
105
|
+
let collections = [];
|
|
106
|
+
let dataSource = 'tables';
|
|
107
|
+
|
|
108
|
+
if (tables.length === 0) {
|
|
109
|
+
collections = localConfig.getCollections();
|
|
110
|
+
dataSource = 'collections';
|
|
111
|
+
|
|
112
|
+
if (collections.length === 0) {
|
|
113
|
+
const configFileName = path.basename(localConfig.path);
|
|
114
|
+
throw new Error(`No tables or collections found in configuration. Make sure ${configFileName} exists and contains tables or collections.`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Use tables if available, otherwise use collections
|
|
119
|
+
let dataItems = tables.length > 0 ? tables : collections;
|
|
120
|
+
const itemType = tables.length > 0 ? 'tables' : 'collections';
|
|
121
|
+
|
|
122
|
+
// Normalize tables data: rename 'columns' to 'attributes' for template compatibility
|
|
123
|
+
if (tables.length > 0) {
|
|
124
|
+
dataItems = dataItems.map(table => {
|
|
125
|
+
const { columns, ...rest } = table;
|
|
126
|
+
return {
|
|
127
|
+
...rest,
|
|
128
|
+
attributes: (columns || []).map(column => {
|
|
129
|
+
if (column.relatedTable) {
|
|
130
|
+
const { relatedTable, ...columnRest } = column;
|
|
131
|
+
return {
|
|
132
|
+
...columnRest,
|
|
133
|
+
relatedCollection: relatedTable
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
return column;
|
|
137
|
+
})
|
|
138
|
+
};
|
|
139
|
+
});
|
|
104
140
|
}
|
|
105
141
|
|
|
106
|
-
log(`Found ${
|
|
142
|
+
log(`Found ${dataItems.length} ${itemType}: ${dataItems.map(c => c.name).join(", ")}`);
|
|
143
|
+
|
|
144
|
+
// Use columns if available, otherwise use attributes
|
|
145
|
+
const resourceType = tables.length > 0 ? 'columns' : 'attributes';
|
|
107
146
|
|
|
108
|
-
const totalAttributes =
|
|
109
|
-
log(`Found ${totalAttributes}
|
|
147
|
+
const totalAttributes = dataItems.reduce((count, item) => count + (item.attributes || []).length, 0);
|
|
148
|
+
log(`Found ${totalAttributes} ${resourceType} across all ${itemType}`);
|
|
110
149
|
|
|
111
150
|
const templater = ejs.compile(meta.getTemplate());
|
|
112
151
|
|
|
113
152
|
if (meta.isSingleFile()) {
|
|
114
153
|
const content = templater({
|
|
115
|
-
collections,
|
|
154
|
+
collections: dataItems,
|
|
116
155
|
strict,
|
|
117
156
|
...templateHelpers,
|
|
118
157
|
getType: meta.getType,
|
|
@@ -123,23 +162,23 @@ const typesCommand = actionRunner(async (rawOutputDirectory, {language, strict})
|
|
|
123
162
|
fs.writeFileSync(destination, content);
|
|
124
163
|
log(`Added types to ${destination}`);
|
|
125
164
|
} else {
|
|
126
|
-
for (const
|
|
165
|
+
for (const item of dataItems) {
|
|
127
166
|
const content = templater({
|
|
128
|
-
collections,
|
|
129
|
-
collection,
|
|
167
|
+
collections: dataItems,
|
|
168
|
+
collection: item,
|
|
130
169
|
strict,
|
|
131
170
|
...templateHelpers,
|
|
132
171
|
getType: meta.getType,
|
|
133
172
|
});
|
|
134
173
|
|
|
135
|
-
const destination = path.join(outputDirectory, meta.getFileName(
|
|
174
|
+
const destination = path.join(outputDirectory, meta.getFileName(item));
|
|
136
175
|
|
|
137
176
|
fs.writeFileSync(destination, content);
|
|
138
|
-
log(`Added types for ${
|
|
177
|
+
log(`Added types for ${item.name} to ${destination}`);
|
|
139
178
|
}
|
|
140
179
|
}
|
|
141
180
|
|
|
142
|
-
success(`Generated types for all the listed
|
|
181
|
+
success(`Generated types for all the listed ${itemType}`);
|
|
143
182
|
});
|
|
144
183
|
|
|
145
184
|
const types = new Command("types")
|
package/lib/config.js
CHANGED
|
@@ -55,7 +55,7 @@ const KeysColumns = new Set([
|
|
|
55
55
|
// enum
|
|
56
56
|
"elements",
|
|
57
57
|
// relationship
|
|
58
|
-
"
|
|
58
|
+
"relatedTable",
|
|
59
59
|
"relationType",
|
|
60
60
|
"twoWay",
|
|
61
61
|
"twoWayKey",
|
|
@@ -150,6 +150,47 @@ class Config {
|
|
|
150
150
|
toString() {
|
|
151
151
|
return JSONbig.stringify(this.data, null, 4);
|
|
152
152
|
}
|
|
153
|
+
|
|
154
|
+
_getDBEntities(entityType) {
|
|
155
|
+
if (!this.has(entityType)) {
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
158
|
+
return this.get(entityType);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
_getDBEntity(entityType, $id) {
|
|
162
|
+
if (!this.has(entityType)) {
|
|
163
|
+
return {};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
let entities = this.get(entityType);
|
|
167
|
+
for (let i = 0; i < entities.length; i++) {
|
|
168
|
+
if (entities[i]['$id'] == $id) {
|
|
169
|
+
return entities[i];
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return {};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
_addDBEntity(entityType, props, keysSet, nestedKeys = {}) {
|
|
177
|
+
props = whitelistKeys(props, keysSet, nestedKeys);
|
|
178
|
+
|
|
179
|
+
if (!this.has(entityType)) {
|
|
180
|
+
this.set(entityType, []);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
let entities = this.get(entityType);
|
|
184
|
+
for (let i = 0; i < entities.length; i++) {
|
|
185
|
+
if (entities[i]['$id'] == props['$id']) {
|
|
186
|
+
entities[i] = props;
|
|
187
|
+
this.set(entityType, entities);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
entities.push(props);
|
|
192
|
+
this.set(entityType, entities);
|
|
193
|
+
}
|
|
153
194
|
}
|
|
154
195
|
|
|
155
196
|
class Local extends Config {
|
|
@@ -464,45 +505,28 @@ class Local extends Config {
|
|
|
464
505
|
this.set("topics", topics);
|
|
465
506
|
}
|
|
466
507
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
return [];
|
|
470
|
-
}
|
|
471
|
-
return this.get("databases");
|
|
508
|
+
getTablesDBs() {
|
|
509
|
+
return this._getDBEntities("tablesDB");
|
|
472
510
|
}
|
|
473
511
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
512
|
+
getTablesDB($id) {
|
|
513
|
+
return this._getDBEntity("tablesDB", $id);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
addTablesDB(props) {
|
|
517
|
+
this._addDBEntity("tablesDB", props, KeysDatabase);
|
|
518
|
+
}
|
|
478
519
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
return databases[i];
|
|
483
|
-
}
|
|
484
|
-
}
|
|
520
|
+
getDatabases() {
|
|
521
|
+
return this._getDBEntities("databases");
|
|
522
|
+
}
|
|
485
523
|
|
|
486
|
-
|
|
524
|
+
getDatabase($id) {
|
|
525
|
+
return this._getDBEntity("databases", $id);
|
|
487
526
|
}
|
|
488
527
|
|
|
489
528
|
addDatabase(props) {
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
if (!this.has("databases")) {
|
|
493
|
-
this.set("databases", []);
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
let databases = this.get("databases");
|
|
497
|
-
for (let i = 0; i < databases.length; i++) {
|
|
498
|
-
if (databases[i]['$id'] == props['$id']) {
|
|
499
|
-
databases[i] = props;
|
|
500
|
-
this.set("databases", databases);
|
|
501
|
-
return;
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
databases.push(props);
|
|
505
|
-
this.set("databases", databases);
|
|
529
|
+
this._addDBEntity("databases", props, KeysDatabase);
|
|
506
530
|
}
|
|
507
531
|
|
|
508
532
|
getTeams() {
|
package/lib/parser.js
CHANGED
|
@@ -122,7 +122,7 @@ const parseError = (err) => {
|
|
|
122
122
|
} catch {
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
const version = '
|
|
125
|
+
const version = '10.0.0';
|
|
126
126
|
const stepsToReproduce = `Running \`appwrite ${cliConfig.reportData.data.args.join(' ')}\``;
|
|
127
127
|
const yourEnvironment = `CLI version: ${version}\nOperation System: ${os.type()}\nAppwrite version: ${appwriteVersion}\nIs Cloud: ${isCloud()}`;
|
|
128
128
|
|
|
@@ -205,7 +205,8 @@ const commandDescriptions = {
|
|
|
205
205
|
"account": `The account command allows you to authenticate and manage a user account.`,
|
|
206
206
|
"graphql": `The graphql command allows you to query and mutate any resource type on your Appwrite server.`,
|
|
207
207
|
"avatars": `The avatars command aims to help you complete everyday tasks related to your app image, icons, and avatars.`,
|
|
208
|
-
"databases": `The databases command allows you to create structured collections of documents and query and filter lists of documents.`,
|
|
208
|
+
"databases": `(Legacy) The databases command allows you to create structured collections of documents and query and filter lists of documents.`,
|
|
209
|
+
'tables-db': `The tables-db command allows you to create structured tables of columns and query and filter lists of rows.`,
|
|
209
210
|
"init": `The init command provides a convenient wrapper for creating and initializing projects, functions, collections, buckets, teams, and messaging-topics in Appwrite.`,
|
|
210
211
|
"push": `The push command provides a convenient wrapper for pushing your functions, collections, buckets, teams, and messaging-topics.`,
|
|
211
212
|
"run": `The run command allows you to run the project locally to allow easy development and quick debugging.`,
|
|
@@ -218,6 +219,8 @@ const commandDescriptions = {
|
|
|
218
219
|
"teams": `The teams command allows you to group users of your project to enable them to share read and write access to your project resources.`,
|
|
219
220
|
"update": `The update command allows you to update the Appwrite CLI to the latest version.`,
|
|
220
221
|
"users": `The users command allows you to manage your project users.`,
|
|
222
|
+
"projects": `The projects command allows you to manage your projects, add platforms, manage API keys, Dev Keys etc.`,
|
|
223
|
+
"project": `The project command allows you to manage project related resources like usage, variables, etc.`,
|
|
221
224
|
"client": `The client command allows you to configure your CLI`,
|
|
222
225
|
"login": `The login command allows you to authenticate and manage a user account.`,
|
|
223
226
|
"logout": `The logout command allows you to log out of your Appwrite account.`,
|
package/lib/questions.js
CHANGED
|
@@ -5,7 +5,7 @@ const { projectsList } = require('./commands/projects');
|
|
|
5
5
|
const { organizationsList } = require('./commands/organizations');
|
|
6
6
|
const { teamsList } = require('./commands/teams');
|
|
7
7
|
const { functionsListRuntimes, functionsListSpecifications, functionsList } = require('./commands/functions');
|
|
8
|
-
const {
|
|
8
|
+
const { accountListMFAFactors } = require("./commands/account");
|
|
9
9
|
const { sdkForConsole } = require("./sdks");
|
|
10
10
|
const { validateRequired } = require("./validations");
|
|
11
11
|
const { paginate } = require('./paginate');
|
|
@@ -259,7 +259,7 @@ const questionsPullResources = [
|
|
|
259
259
|
{ name: `Buckets ${chalk.blackBright(`(Storage)`)}`, value: 'buckets' },
|
|
260
260
|
{ name: `Teams ${chalk.blackBright(`(Auth)`)}`, value: 'teams' },
|
|
261
261
|
{ name: `Topics ${chalk.blackBright(`(Messaging)`)}`, value: 'messages' },
|
|
262
|
-
{ name: `Collections ${chalk.blackBright(`(
|
|
262
|
+
{ name: `Collections ${chalk.blackBright(`(Legacy Databases)`)}`, value: 'collections' }
|
|
263
263
|
]
|
|
264
264
|
}
|
|
265
265
|
]
|
|
@@ -671,7 +671,7 @@ const questionsPushResources = [
|
|
|
671
671
|
{ name: `Buckets ${chalk.blackBright(`(Storage)`)}`, value: 'buckets' },
|
|
672
672
|
{ name: `Teams ${chalk.blackBright(`(Auth)`)}`, value: 'teams' },
|
|
673
673
|
{ name: `Topics ${chalk.blackBright(`(Messaging)`)}`, value: 'messages' },
|
|
674
|
-
{ name: `Collections ${chalk.blackBright(`(
|
|
674
|
+
{ name: `Collections ${chalk.blackBright(`(Legacy Databases)`)}`, value: 'collections' }
|
|
675
675
|
]
|
|
676
676
|
}
|
|
677
677
|
];
|
|
@@ -877,7 +877,7 @@ const questionsListFactors = [
|
|
|
877
877
|
message: "Your account is protected by multi-factor authentication. Please choose one for verification.",
|
|
878
878
|
choices: async () => {
|
|
879
879
|
let client = await sdkForConsole(false);
|
|
880
|
-
const factors = await
|
|
880
|
+
const factors = await accountListMFAFactors({
|
|
881
881
|
sdk: client,
|
|
882
882
|
parseOutput: false
|
|
883
883
|
});
|
|
@@ -906,7 +906,7 @@ const questionsListFactors = [
|
|
|
906
906
|
}
|
|
907
907
|
];
|
|
908
908
|
|
|
909
|
-
const
|
|
909
|
+
const questionsMFAChallenge = [
|
|
910
910
|
{
|
|
911
911
|
type: "input",
|
|
912
912
|
name: "otp",
|
|
@@ -1019,7 +1019,7 @@ module.exports = {
|
|
|
1019
1019
|
questionsPushTeams,
|
|
1020
1020
|
questionsGetEntrypoint,
|
|
1021
1021
|
questionsListFactors,
|
|
1022
|
-
|
|
1022
|
+
questionsMFAChallenge,
|
|
1023
1023
|
questionsRunFunctions,
|
|
1024
1024
|
questionGetEndpoint,
|
|
1025
1025
|
questionsInitResources,
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/** @typedef {import('../attribute').Attribute} Attribute */
|
|
2
|
+
const { AttributeType } = require('../attribute');
|
|
3
|
+
const { LanguageMeta } = require("./language");
|
|
4
|
+
|
|
5
|
+
class CSharp extends LanguageMeta {
|
|
6
|
+
getType(attribute, collections) {
|
|
7
|
+
let type = "";
|
|
8
|
+
switch (attribute.type) {
|
|
9
|
+
case AttributeType.STRING:
|
|
10
|
+
case AttributeType.EMAIL:
|
|
11
|
+
case AttributeType.DATETIME:
|
|
12
|
+
type = "string";
|
|
13
|
+
if (attribute.format === AttributeType.ENUM) {
|
|
14
|
+
type = LanguageMeta.toPascalCase(attribute.key);
|
|
15
|
+
}
|
|
16
|
+
break;
|
|
17
|
+
case AttributeType.INTEGER:
|
|
18
|
+
type = "long";
|
|
19
|
+
break;
|
|
20
|
+
case AttributeType.FLOAT:
|
|
21
|
+
type = "double";
|
|
22
|
+
break;
|
|
23
|
+
case AttributeType.BOOLEAN:
|
|
24
|
+
type = "bool";
|
|
25
|
+
break;
|
|
26
|
+
case AttributeType.RELATIONSHIP:
|
|
27
|
+
const relatedCollection = collections.find(c => c.$id === attribute.relatedCollection);
|
|
28
|
+
if (!relatedCollection) {
|
|
29
|
+
throw new Error(`Related collection with ID '${attribute.relatedCollection}' not found.`);
|
|
30
|
+
}
|
|
31
|
+
type = LanguageMeta.toPascalCase(relatedCollection.name);
|
|
32
|
+
if ((attribute.relationType === 'oneToMany' && attribute.side === 'parent') || (attribute.relationType === 'manyToOne' && attribute.side === 'child') || attribute.relationType === 'manyToMany') {
|
|
33
|
+
type = `List<${type}>`;
|
|
34
|
+
}
|
|
35
|
+
break;
|
|
36
|
+
default:
|
|
37
|
+
throw new Error(`Unknown attribute type: ${attribute.type}`);
|
|
38
|
+
}
|
|
39
|
+
if (attribute.array) {
|
|
40
|
+
type = `List<${type}>`;
|
|
41
|
+
}
|
|
42
|
+
if (!attribute.required) {
|
|
43
|
+
type += "?";
|
|
44
|
+
}
|
|
45
|
+
return type;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
getTemplate() {
|
|
49
|
+
return `/// This file is auto-generated by the Appwrite CLI.
|
|
50
|
+
/// You can regenerate it by running \`appwrite ${process.argv.slice(2).join(' ')}\`.
|
|
51
|
+
|
|
52
|
+
#nullable enable
|
|
53
|
+
using System;
|
|
54
|
+
using System.Collections.Generic;
|
|
55
|
+
using System.Linq;
|
|
56
|
+
using System.Text.Json.Serialization;
|
|
57
|
+
|
|
58
|
+
namespace Appwrite.Models
|
|
59
|
+
{
|
|
60
|
+
<% for (const attribute of collection.attributes) { -%>
|
|
61
|
+
<% if (attribute.format === 'enum') { -%>
|
|
62
|
+
|
|
63
|
+
public enum <%- toPascalCase(attribute.key) %> {
|
|
64
|
+
<% for (const [index, element] of Object.entries(attribute.elements) ) { -%>
|
|
65
|
+
[JsonPropertyName("<%- element %>")]
|
|
66
|
+
<%- toPascalCase(element) %><% if (index < attribute.elements.length - 1) { %>,<% } %>
|
|
67
|
+
<% } -%>
|
|
68
|
+
}
|
|
69
|
+
<% } -%>
|
|
70
|
+
<% } %>
|
|
71
|
+
public class <%= toPascalCase(collection.name) %>
|
|
72
|
+
{
|
|
73
|
+
<% for (const [index, attribute] of Object.entries(collection.attributes)) { -%>
|
|
74
|
+
[JsonPropertyName("<%- attribute.key %>")]
|
|
75
|
+
public <%- getType(attribute, collections) %> <%= toPascalCase(attribute.key) %> { get; private set; }
|
|
76
|
+
|
|
77
|
+
<% } -%>
|
|
78
|
+
|
|
79
|
+
public <%= toPascalCase(collection.name) %>(
|
|
80
|
+
<% for (const [index, attribute] of Object.entries(collection.attributes)) { -%>
|
|
81
|
+
<%- getType(attribute, collections) %> <%= toCamelCase(attribute.key) %><% if (index < collection.attributes.length - 1) { %>,<% } %>
|
|
82
|
+
<% } -%>
|
|
83
|
+
)
|
|
84
|
+
{
|
|
85
|
+
<% for (const [index, attribute] of Object.entries(collection.attributes)) { -%>
|
|
86
|
+
<%= toPascalCase(attribute.key) %> = <%= toCamelCase(attribute.key) %>;
|
|
87
|
+
<% } -%>
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public static <%= toPascalCase(collection.name) %> From(Dictionary<string, object> map) => new <%= toPascalCase(collection.name) %>(
|
|
91
|
+
<% for (const [index, attribute] of Object.entries(collection.attributes)) { -%>
|
|
92
|
+
<%- toCamelCase(attribute.key) %>: <%
|
|
93
|
+
// ENUM
|
|
94
|
+
if (attribute.format === 'enum') {
|
|
95
|
+
if (attribute.array) {
|
|
96
|
+
-%>((IEnumerable<object>)map["<%- attribute.key %>"]).Select(e => Enum.Parse<Models.<%- toPascalCase(attribute.key) %>>(e.ToString()!, true)).ToList()<%
|
|
97
|
+
} else {
|
|
98
|
+
-%>Enum.Parse<Models.<%- toPascalCase(attribute.key) %>>(map["<%- attribute.key %>"].ToString()!, true)<%
|
|
99
|
+
}
|
|
100
|
+
// RELATIONSHIP
|
|
101
|
+
} else if (attribute.type === 'relationship') {
|
|
102
|
+
const relatedClass = toPascalCase(collections.find(c => c.$id === attribute.relatedCollection).name);
|
|
103
|
+
if ((attribute.relationType === 'oneToMany' && attribute.side === 'parent') || (attribute.relationType === 'manyToOne' && attribute.side === 'child') || attribute.relationType === 'manyToMany' || attribute.array) {
|
|
104
|
+
-%>((IEnumerable<object>)map["<%- attribute.key %>"]).Select(it => Models.<%- relatedClass %>.From((Dictionary<string, object>)it)).ToList()<%
|
|
105
|
+
} else {
|
|
106
|
+
-%>Models.<%- relatedClass %>.From((Dictionary<string, object>)map["<%- attribute.key %>"])<%
|
|
107
|
+
}
|
|
108
|
+
// ARRAY TYPES
|
|
109
|
+
} else if (attribute.array) {
|
|
110
|
+
if (attribute.type === 'string' || attribute.type === 'datetime' || attribute.type === 'email') {
|
|
111
|
+
-%>((IEnumerable<object>)map["<%- attribute.key %>"]).Select(x => x?.ToString())<%- attribute.required ? '.Where(x => x != null)' : '' %>.ToList()!<%
|
|
112
|
+
} else if (attribute.type === 'integer') {
|
|
113
|
+
-%>((IEnumerable<object>)map["<%- attribute.key %>"]).Select(x => <%- !attribute.required ? 'x == null ? (long?)null : ' : '' %>Convert.ToInt64(x)).ToList()<%
|
|
114
|
+
} else if (attribute.type === 'double') {
|
|
115
|
+
-%>((IEnumerable<object>)map["<%- attribute.key %>"]).Select(x => <%- !attribute.required ? 'x == null ? (double?)null : ' : '' %>Convert.ToDouble(x)).ToList()<%
|
|
116
|
+
} else if (attribute.type === 'boolean') {
|
|
117
|
+
-%>((IEnumerable<object>)map["<%- attribute.key %>"]).Select(x => <%- !attribute.required ? 'x == null ? (bool?)null : ' : '' %>(bool)x).ToList()<%
|
|
118
|
+
}
|
|
119
|
+
// SINGLE VALUE TYPES
|
|
120
|
+
} else if (attribute.type === 'integer') {
|
|
121
|
+
-%><%- !attribute.required ? 'map["' + attribute.key + '"] == null ? null : ' : '' %>Convert.ToInt64(map["<%- attribute.key %>"])<%
|
|
122
|
+
} else if (attribute.type === 'double') {
|
|
123
|
+
-%><%- !attribute.required ? 'map["' + attribute.key + '"] == null ? null : ' : '' %>Convert.ToDouble(map["<%- attribute.key %>"])<%
|
|
124
|
+
} else if (attribute.type === 'boolean') {
|
|
125
|
+
-%>(<%- getType(attribute, collections) %>)map["<%- attribute.key %>"]<%
|
|
126
|
+
} else if (attribute.type === 'string' || attribute.type === 'datetime' || attribute.type === 'email') {
|
|
127
|
+
-%>map["<%- attribute.key %>"]<%- !attribute.required ? '?' : '' %>.ToString()<%- attribute.required ? '!' : ''%><%
|
|
128
|
+
} else {
|
|
129
|
+
-%>default<%
|
|
130
|
+
}
|
|
131
|
+
-%><% if (index < collection.attributes.length - 1) { %>,<% } %>
|
|
132
|
+
<% } -%>
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
public Dictionary<string, object?> ToMap() => new Dictionary<string, object?>()
|
|
136
|
+
{
|
|
137
|
+
<% for (const [index, attribute] of Object.entries(collection.attributes)) { -%>
|
|
138
|
+
{ "<%- attribute.key %>", <%
|
|
139
|
+
// ENUM
|
|
140
|
+
if (attribute.format === 'enum') {
|
|
141
|
+
if (attribute.array) {
|
|
142
|
+
-%><%= toPascalCase(attribute.key) %>?.Select(e => e.ToString()).ToList()<%
|
|
143
|
+
} else {
|
|
144
|
+
-%><%= toPascalCase(attribute.key) %>?.ToString()<%
|
|
145
|
+
}
|
|
146
|
+
// RELATIONSHIP
|
|
147
|
+
} else if (attribute.type === 'relationship') {
|
|
148
|
+
if ((attribute.relationType === 'oneToMany' && attribute.side === 'parent') || (attribute.relationType === 'manyToOne' && attribute.side === 'child') || attribute.relationType === 'manyToMany' || attribute.array) {
|
|
149
|
+
-%><%= toPascalCase(attribute.key) %>?.Select(e => e.ToMap()).ToList()<%
|
|
150
|
+
} else {
|
|
151
|
+
-%><%= toPascalCase(attribute.key) %>?.ToMap()<%
|
|
152
|
+
}
|
|
153
|
+
// OTHER
|
|
154
|
+
} else {
|
|
155
|
+
-%><%= toPascalCase(attribute.key) %><%
|
|
156
|
+
}
|
|
157
|
+
-%> }<% if (index < collection.attributes.length - 1) { %>,<% } %>
|
|
158
|
+
<% } -%>
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
`;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
getFileName(collection) {
|
|
166
|
+
return LanguageMeta.toPascalCase(collection.name) + ".cs";
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
module.exports = { CSharp };
|
|
@@ -66,7 +66,7 @@ class JavaScript extends LanguageMeta {
|
|
|
66
66
|
|
|
67
67
|
getTemplate() {
|
|
68
68
|
return `/**
|
|
69
|
-
* @typedef {import('${this._getAppwriteDependency()}').Models.
|
|
69
|
+
* @typedef {import('${this._getAppwriteDependency()}').Models.Row} Row
|
|
70
70
|
*/
|
|
71
71
|
|
|
72
72
|
// This file is auto-generated by the Appwrite CLI.
|
|
@@ -83,7 +83,7 @@ class JavaScript extends LanguageMeta {
|
|
|
83
83
|
<% } -%>
|
|
84
84
|
<% } -%>
|
|
85
85
|
<% for (const [index, collection] of Object.entries(collections)) { %>/**
|
|
86
|
-
* @typedef {
|
|
86
|
+
* @typedef {Row & {
|
|
87
87
|
<% for (const attribute of collection.attributes) { -%>
|
|
88
88
|
* <%- strict ? toCamelCase(attribute.key) : attribute.key %>: <%- getType(attribute, collections) %>;
|
|
89
89
|
<% } -%>
|
|
@@ -88,9 +88,11 @@ export enum <%- toPascalCase(attribute.key) %> {
|
|
|
88
88
|
<% } -%>
|
|
89
89
|
<% } -%>
|
|
90
90
|
<% for (const [index, collection] of Object.entries(collections)) { -%>
|
|
91
|
-
export type <%- toPascalCase(collection.name) %> = Models.
|
|
91
|
+
export type <%- toPascalCase(collection.name) %> = Models.Row & {
|
|
92
92
|
<% for (const attribute of collection.attributes) { -%>
|
|
93
|
-
|
|
93
|
+
<% const propertyName = strict ? toCamelCase(attribute.key) : attribute.key; -%>
|
|
94
|
+
<% const isValidIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(propertyName); -%>
|
|
95
|
+
<% if (isValidIdentifier) { %><%- propertyName %><% } else { %>"<%- propertyName %>"<% } %>: <%- getType(attribute, collections) %>;
|
|
94
96
|
<% } -%>
|
|
95
97
|
}<% if (index < collections.length - 1) { %>
|
|
96
98
|
<% } %>
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "appwrite-cli",
|
|
3
3
|
"homepage": "https://appwrite.io/support",
|
|
4
4
|
"description": "Appwrite is an open-source self-hosted backend server that abstract and simplify complex and repetitive development tasks behind a very simple REST API",
|
|
5
|
-
"version": "
|
|
5
|
+
"version": "10.0.0",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"bin": {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/ScoopInstaller/Scoop/master/schema.json",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.0",
|
|
4
4
|
"description": "The Appwrite CLI is a command-line application that allows you to interact with Appwrite and perform server-side tasks using your terminal.",
|
|
5
5
|
"homepage": "https://github.com/appwrite/sdk-for-cli",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
7
7
|
"architecture": {
|
|
8
8
|
"64bit": {
|
|
9
|
-
"url": "https://github.com/appwrite/sdk-for-cli/releases/download/
|
|
9
|
+
"url": "https://github.com/appwrite/sdk-for-cli/releases/download/10.0.0/appwrite-cli-win-x64.exe",
|
|
10
10
|
"bin": [
|
|
11
11
|
[
|
|
12
12
|
"appwrite-cli-win-x64.exe",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
]
|
|
16
16
|
},
|
|
17
17
|
"arm64": {
|
|
18
|
-
"url": "https://github.com/appwrite/sdk-for-cli/releases/download/
|
|
18
|
+
"url": "https://github.com/appwrite/sdk-for-cli/releases/download/10.0.0/appwrite-cli-win-arm64.exe",
|
|
19
19
|
"bin": [
|
|
20
20
|
[
|
|
21
21
|
"appwrite-cli-win-arm64.exe",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
appwrite avatars get-initials
|