appwrite-cli 13.0.0-rc.4 → 13.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 +12 -0
- package/README.md +2 -2
- package/dist/bundle.cjs +17258 -2711
- package/dist/lib/client.js +1 -1
- package/dist/lib/client.js.map +1 -1
- package/dist/lib/commands/config.d.ts +12 -12
- package/dist/lib/commands/config.d.ts.map +1 -1
- package/dist/lib/commands/config.js +15 -6
- package/dist/lib/commands/config.js.map +1 -1
- package/dist/lib/commands/pull.d.ts.map +1 -1
- package/dist/lib/commands/pull.js +53 -16
- package/dist/lib/commands/pull.js.map +1 -1
- package/dist/lib/commands/push.d.ts +1 -1
- package/dist/lib/commands/push.d.ts.map +1 -1
- package/dist/lib/commands/push.js +88 -12
- package/dist/lib/commands/push.js.map +1 -1
- package/dist/lib/commands/schema.js +1 -1
- package/dist/lib/commands/schema.js.map +1 -1
- package/dist/lib/commands/utils/attributes.d.ts.map +1 -1
- package/dist/lib/commands/utils/attributes.js +7 -2
- package/dist/lib/commands/utils/attributes.js.map +1 -1
- package/dist/lib/commands/utils/pools.js +2 -2
- package/dist/lib/commands/utils/pools.js.map +1 -1
- package/dist/lib/config.d.ts +1 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +41 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/constants.d.ts +1 -1
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +1 -1
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/questions.d.ts +2 -0
- package/dist/lib/questions.d.ts.map +1 -1
- package/dist/lib/questions.js +14 -0
- package/dist/lib/questions.js.map +1 -1
- package/dist/package.json +1 -1
- package/install.ps1 +2 -2
- package/install.sh +1 -1
- package/lib/client.ts +1 -1
- package/lib/commands/config.ts +20 -6
- package/lib/commands/pull.ts +81 -16
- package/lib/commands/push.ts +117 -12
- package/lib/commands/schema.ts +1 -1
- package/lib/commands/utils/attributes.ts +15 -9
- package/lib/commands/utils/pools.ts +2 -2
- package/lib/config.ts +47 -1
- package/lib/constants.ts +1 -1
- package/lib/questions.ts +16 -0
- package/package.json +1 -1
- package/scoop/appwrite.config.json +3 -3
package/install.sh
CHANGED
|
@@ -96,7 +96,7 @@ printSuccess() {
|
|
|
96
96
|
downloadBinary() {
|
|
97
97
|
echo "[2/4] Downloading executable for $OS ($ARCH) ..."
|
|
98
98
|
|
|
99
|
-
GITHUB_LATEST_VERSION="13.0.0
|
|
99
|
+
GITHUB_LATEST_VERSION="13.0.0"
|
|
100
100
|
GITHUB_FILE="appwrite-cli-${OS}-${ARCH}"
|
|
101
101
|
GITHUB_URL="https://github.com/$GITHUB_REPOSITORY_NAME/releases/download/$GITHUB_LATEST_VERSION/$GITHUB_FILE"
|
|
102
102
|
|
package/lib/client.ts
CHANGED
package/lib/commands/config.ts
CHANGED
|
@@ -127,10 +127,10 @@ const SettingsSchema = z
|
|
|
127
127
|
.optional(),
|
|
128
128
|
security: z
|
|
129
129
|
.object({
|
|
130
|
-
duration: z.number().optional(),
|
|
131
|
-
limit: z.number().optional(),
|
|
132
|
-
sessionsLimit: z.number().optional(),
|
|
133
|
-
passwordHistory: z.number().optional(),
|
|
130
|
+
duration: z.union([z.number(), z.bigint()]).optional(),
|
|
131
|
+
limit: z.union([z.number(), z.bigint()]).optional(),
|
|
132
|
+
sessionsLimit: z.union([z.number(), z.bigint()]).optional(),
|
|
133
|
+
passwordHistory: z.union([z.number(), z.bigint()]).optional(),
|
|
134
134
|
passwordDictionary: z.boolean().optional(),
|
|
135
135
|
personalDataCheck: z.boolean().optional(),
|
|
136
136
|
sessionAlerts: z.boolean().optional(),
|
|
@@ -155,7 +155,7 @@ const SiteSchema = z
|
|
|
155
155
|
name: z.string(),
|
|
156
156
|
enabled: z.boolean().optional(),
|
|
157
157
|
logging: z.boolean().optional(),
|
|
158
|
-
timeout: z.number().optional(),
|
|
158
|
+
timeout: z.union([z.number(), z.bigint()]).optional(),
|
|
159
159
|
framework: z.string().optional(),
|
|
160
160
|
buildRuntime: z.string().optional(),
|
|
161
161
|
adapter: z.string().optional(),
|
|
@@ -182,7 +182,7 @@ const FunctionSchema = z
|
|
|
182
182
|
scopes: z.array(z.string()).optional(),
|
|
183
183
|
events: z.array(z.string()).optional(),
|
|
184
184
|
schedule: z.string().optional(),
|
|
185
|
-
timeout: z.number().optional(),
|
|
185
|
+
timeout: z.union([z.number(), z.bigint()]).optional(),
|
|
186
186
|
entrypoint: z.string().optional(),
|
|
187
187
|
commands: z.string().optional(),
|
|
188
188
|
vars: z.record(z.string(), z.string()).optional(),
|
|
@@ -256,6 +256,20 @@ const AttributeSchema = AttributeSchemaBase.refine(
|
|
|
256
256
|
message: "When 'required' is true, 'default' must be null",
|
|
257
257
|
path: ["default"],
|
|
258
258
|
},
|
|
259
|
+
).refine(
|
|
260
|
+
(data) => {
|
|
261
|
+
if (
|
|
262
|
+
data.type === "string" &&
|
|
263
|
+
(data.size === undefined || data.size === null)
|
|
264
|
+
) {
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
return true;
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
message: "When 'type' is 'string', 'size' must be defined",
|
|
271
|
+
path: ["size"],
|
|
272
|
+
},
|
|
259
273
|
);
|
|
260
274
|
|
|
261
275
|
const IndexSchema = z
|
package/lib/commands/pull.ts
CHANGED
|
@@ -41,6 +41,7 @@ import { createSettingsObject } from "../utils.js";
|
|
|
41
41
|
import { ProjectNotInitializedError } from "./errors.js";
|
|
42
42
|
import type { SettingsType, FunctionType, SiteType } from "./config.js";
|
|
43
43
|
import { downloadDeploymentCode } from "./utils/deployment.js";
|
|
44
|
+
import { getConfirmation } from "./utils/change-approval.js";
|
|
44
45
|
|
|
45
46
|
export interface PullOptions {
|
|
46
47
|
all?: boolean;
|
|
@@ -804,53 +805,117 @@ const pullCollection = async (): Promise<void> => {
|
|
|
804
805
|
const pullInstance = await createPullInstance();
|
|
805
806
|
const { databases, collections } = await pullInstance.pullCollections();
|
|
806
807
|
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
808
|
+
const localCollections = localConfig.getCollections();
|
|
809
|
+
const remoteCollectionIds = new Set(collections.map((c: any) => c.$id));
|
|
810
|
+
const collectionsToRemove = localCollections.filter(
|
|
811
|
+
(c: any) => !remoteCollectionIds.has(c.$id),
|
|
812
|
+
);
|
|
810
813
|
|
|
811
|
-
|
|
812
|
-
|
|
814
|
+
if (collectionsToRemove.length > 0) {
|
|
815
|
+
warn(
|
|
816
|
+
`The following collections exist locally but not remotely and will be removed: ${collectionsToRemove.map((c: any) => c.name || c.$id).join(", ")}`,
|
|
817
|
+
);
|
|
818
|
+
if ((await getConfirmation()) !== true) {
|
|
819
|
+
log("Pull cancelled.");
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
813
822
|
}
|
|
823
|
+
|
|
824
|
+
localConfig.set("databases", databases);
|
|
825
|
+
localConfig.set("collections", collections);
|
|
814
826
|
};
|
|
815
827
|
|
|
816
828
|
const pullTable = async (): Promise<void> => {
|
|
817
829
|
const pullInstance = await createPullInstance();
|
|
818
830
|
const { databases, tables } = await pullInstance.pullTables();
|
|
819
831
|
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
832
|
+
const localTables = localConfig.getTables();
|
|
833
|
+
const remoteTableIds = new Set(tables.map((t: any) => t.$id));
|
|
834
|
+
const tablesToRemove = localTables.filter(
|
|
835
|
+
(t: any) => !remoteTableIds.has(t.$id),
|
|
836
|
+
);
|
|
823
837
|
|
|
824
|
-
|
|
825
|
-
|
|
838
|
+
if (tablesToRemove.length > 0) {
|
|
839
|
+
warn(
|
|
840
|
+
`The following tables exist locally but not remotely and will be removed: ${tablesToRemove.map((t: any) => t.name || t.$id).join(", ")}`,
|
|
841
|
+
);
|
|
842
|
+
if ((await getConfirmation()) !== true) {
|
|
843
|
+
log("Pull cancelled.");
|
|
844
|
+
return;
|
|
845
|
+
}
|
|
826
846
|
}
|
|
847
|
+
|
|
848
|
+
localConfig.set("tablesDB", databases);
|
|
849
|
+
localConfig.set("tables", tables);
|
|
827
850
|
};
|
|
828
851
|
|
|
829
852
|
const pullBucket = async (): Promise<void> => {
|
|
830
853
|
const pullInstance = await createPullInstance();
|
|
831
854
|
const buckets = await pullInstance.pullBuckets();
|
|
832
855
|
|
|
833
|
-
|
|
834
|
-
|
|
856
|
+
const localBuckets = localConfig.getBuckets();
|
|
857
|
+
const remoteBucketIds = new Set(buckets.map((b: any) => b.$id));
|
|
858
|
+
const bucketsToRemove = localBuckets.filter(
|
|
859
|
+
(b: any) => !remoteBucketIds.has(b.$id),
|
|
860
|
+
);
|
|
861
|
+
|
|
862
|
+
if (bucketsToRemove.length > 0) {
|
|
863
|
+
warn(
|
|
864
|
+
`The following buckets exist locally but not remotely and will be removed: ${bucketsToRemove.map((b: any) => b.name || b.$id).join(", ")}`,
|
|
865
|
+
);
|
|
866
|
+
if ((await getConfirmation()) !== true) {
|
|
867
|
+
log("Pull cancelled.");
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
835
870
|
}
|
|
871
|
+
|
|
872
|
+
localConfig.set("buckets", buckets);
|
|
836
873
|
};
|
|
837
874
|
|
|
838
875
|
const pullTeam = async (): Promise<void> => {
|
|
839
876
|
const pullInstance = await createPullInstance();
|
|
840
877
|
const teams = await pullInstance.pullTeams();
|
|
841
878
|
|
|
842
|
-
|
|
843
|
-
|
|
879
|
+
const localTeams = localConfig.getTeams();
|
|
880
|
+
const remoteTeamIds = new Set(teams.map((t: any) => t.$id));
|
|
881
|
+
const teamsToRemove = localTeams.filter(
|
|
882
|
+
(t: any) => !remoteTeamIds.has(t.$id),
|
|
883
|
+
);
|
|
884
|
+
|
|
885
|
+
if (teamsToRemove.length > 0) {
|
|
886
|
+
warn(
|
|
887
|
+
`The following teams exist locally but not remotely and will be removed: ${teamsToRemove.map((t: any) => t.name || t.$id).join(", ")}`,
|
|
888
|
+
);
|
|
889
|
+
if ((await getConfirmation()) !== true) {
|
|
890
|
+
log("Pull cancelled.");
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
844
893
|
}
|
|
894
|
+
|
|
895
|
+
localConfig.set("teams", teams);
|
|
845
896
|
};
|
|
846
897
|
|
|
847
898
|
const pullMessagingTopic = async (): Promise<void> => {
|
|
848
899
|
const pullInstance = await createPullInstance();
|
|
849
900
|
const topics = await pullInstance.pullMessagingTopics();
|
|
850
901
|
|
|
851
|
-
|
|
852
|
-
|
|
902
|
+
const localTopics = localConfig.getMessagingTopics();
|
|
903
|
+
const remoteTopicIds = new Set(topics.map((t: any) => t.$id));
|
|
904
|
+
const topicsToRemove = localTopics.filter(
|
|
905
|
+
(t: any) => !remoteTopicIds.has(t.$id),
|
|
906
|
+
);
|
|
907
|
+
|
|
908
|
+
if (topicsToRemove.length > 0) {
|
|
909
|
+
warn(
|
|
910
|
+
`The following topics exist locally but not remotely and will be removed: ${topicsToRemove.map((t: any) => t.name || t.$id).join(", ")}`,
|
|
911
|
+
);
|
|
912
|
+
if ((await getConfirmation()) !== true) {
|
|
913
|
+
log("Pull cancelled.");
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
853
916
|
}
|
|
917
|
+
|
|
918
|
+
localConfig.set("topics", topics);
|
|
854
919
|
};
|
|
855
920
|
|
|
856
921
|
/** Commander.js exports */
|
package/lib/commands/push.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
2
3
|
import { parse as parseDotenv } from "dotenv";
|
|
3
4
|
import chalk from "chalk";
|
|
4
5
|
import inquirer from "inquirer";
|
|
@@ -16,7 +17,8 @@ import {
|
|
|
16
17
|
KeysCollection,
|
|
17
18
|
KeysTable,
|
|
18
19
|
} from "../config.js";
|
|
19
|
-
import type
|
|
20
|
+
import { ConfigSchema, type SettingsType, type ConfigType } from "./config.js";
|
|
21
|
+
import { parseWithBetterErrors } from "./utils/error-formatter.js";
|
|
20
22
|
import { createSettingsObject } from "../utils.js";
|
|
21
23
|
import { Spinner, SPINNER_DOTS } from "../spinner.js";
|
|
22
24
|
import { paginate } from "../paginate.js";
|
|
@@ -25,7 +27,9 @@ import {
|
|
|
25
27
|
questionsPushBuckets,
|
|
26
28
|
questionsPushTeams,
|
|
27
29
|
questionsPushFunctions,
|
|
30
|
+
questionsPushFunctionsCode,
|
|
28
31
|
questionsPushSites,
|
|
32
|
+
questionsPushSitesCode,
|
|
29
33
|
questionsGetEntrypoint,
|
|
30
34
|
questionsPushCollections,
|
|
31
35
|
questionsPushTables,
|
|
@@ -414,15 +418,15 @@ export class Push {
|
|
|
414
418
|
this.log("Applying auth security settings ...");
|
|
415
419
|
await projectsService.updateAuthDuration({
|
|
416
420
|
projectId,
|
|
417
|
-
duration: settings.auth.security.duration,
|
|
421
|
+
duration: Number(settings.auth.security.duration),
|
|
418
422
|
});
|
|
419
423
|
await projectsService.updateAuthLimit({
|
|
420
424
|
projectId,
|
|
421
|
-
limit: settings.auth.security.limit,
|
|
425
|
+
limit: Number(settings.auth.security.limit),
|
|
422
426
|
});
|
|
423
427
|
await projectsService.updateAuthSessionsLimit({
|
|
424
428
|
projectId,
|
|
425
|
-
limit: settings.auth.security.sessionsLimit,
|
|
429
|
+
limit: Number(settings.auth.security.sessionsLimit),
|
|
426
430
|
});
|
|
427
431
|
await projectsService.updateAuthPasswordDictionary({
|
|
428
432
|
projectId,
|
|
@@ -430,7 +434,7 @@ export class Push {
|
|
|
430
434
|
});
|
|
431
435
|
await projectsService.updateAuthPasswordHistory({
|
|
432
436
|
projectId,
|
|
433
|
-
limit: settings.auth.security.passwordHistory,
|
|
437
|
+
limit: Number(settings.auth.security.passwordHistory),
|
|
434
438
|
});
|
|
435
439
|
await projectsService.updatePersonalDataCheck({
|
|
436
440
|
projectId,
|
|
@@ -807,6 +811,29 @@ export class Push {
|
|
|
807
811
|
return;
|
|
808
812
|
}
|
|
809
813
|
|
|
814
|
+
if (!func.path) {
|
|
815
|
+
errors.push(
|
|
816
|
+
new Error(`Function '${func.name}' has no path configured`),
|
|
817
|
+
);
|
|
818
|
+
updaterRow.fail({
|
|
819
|
+
errorMessage: `No path configured for function`,
|
|
820
|
+
});
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
if (
|
|
825
|
+
!fs.existsSync(func.path) ||
|
|
826
|
+
fs.readdirSync(func.path).length === 0
|
|
827
|
+
) {
|
|
828
|
+
errors.push(
|
|
829
|
+
new Error(`Deployment not found or empty at path: ${func.path}`),
|
|
830
|
+
);
|
|
831
|
+
updaterRow.fail({
|
|
832
|
+
errorMessage: `path not found or empty: ${path.relative(process.cwd(), path.resolve(func.path))}`,
|
|
833
|
+
});
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
|
|
810
837
|
try {
|
|
811
838
|
updaterRow.update({ status: "Pushing" }).replaceSpinner(SPINNER_DOTS);
|
|
812
839
|
const functionsServiceDeploy = await getFunctionsService(
|
|
@@ -838,7 +865,7 @@ export class Push {
|
|
|
838
865
|
switch (e.code) {
|
|
839
866
|
case "ENOENT":
|
|
840
867
|
updaterRow.fail({
|
|
841
|
-
errorMessage:
|
|
868
|
+
errorMessage: `Deployment not found at path: ${path.resolve(func.path)}`,
|
|
842
869
|
});
|
|
843
870
|
break;
|
|
844
871
|
default:
|
|
@@ -1145,6 +1172,27 @@ export class Push {
|
|
|
1145
1172
|
return;
|
|
1146
1173
|
}
|
|
1147
1174
|
|
|
1175
|
+
if (!site.path) {
|
|
1176
|
+
errors.push(new Error(`Site '${site.name}' has no path configured`));
|
|
1177
|
+
updaterRow.fail({
|
|
1178
|
+
errorMessage: `No path configured for site`,
|
|
1179
|
+
});
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
if (
|
|
1184
|
+
!fs.existsSync(site.path) ||
|
|
1185
|
+
fs.readdirSync(site.path).length === 0
|
|
1186
|
+
) {
|
|
1187
|
+
errors.push(
|
|
1188
|
+
new Error(`Deployment not found or empty at path: ${site.path}`),
|
|
1189
|
+
);
|
|
1190
|
+
updaterRow.fail({
|
|
1191
|
+
errorMessage: `path not found or empty: ${path.relative(process.cwd(), path.resolve(site.path))}`,
|
|
1192
|
+
});
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1148
1196
|
try {
|
|
1149
1197
|
updaterRow.update({ status: "Pushing" }).replaceSpinner(SPINNER_DOTS);
|
|
1150
1198
|
const sitesServiceDeploy = await getSitesService(this.projectClient);
|
|
@@ -1174,7 +1222,7 @@ export class Push {
|
|
|
1174
1222
|
switch (e.code) {
|
|
1175
1223
|
case "ENOENT":
|
|
1176
1224
|
updaterRow.fail({
|
|
1177
|
-
errorMessage:
|
|
1225
|
+
errorMessage: `Deployment not found at path: ${path.resolve(site.path)}`,
|
|
1178
1226
|
});
|
|
1179
1227
|
break;
|
|
1180
1228
|
default:
|
|
@@ -1593,13 +1641,54 @@ const pushResources = async ({
|
|
|
1593
1641
|
if (cliConfig.all) {
|
|
1594
1642
|
checkDeployConditions(localConfig);
|
|
1595
1643
|
|
|
1644
|
+
const functions = localConfig.getFunctions();
|
|
1645
|
+
let allowFunctionsCodePush: boolean | null =
|
|
1646
|
+
cliConfig.force === true ? true : null;
|
|
1647
|
+
if (functions.length > 0 && allowFunctionsCodePush === null) {
|
|
1648
|
+
const codeAnswer = await inquirer.prompt(questionsPushFunctionsCode);
|
|
1649
|
+
allowFunctionsCodePush = codeAnswer.override;
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
const sites = localConfig.getSites();
|
|
1653
|
+
let allowSitesCodePush: boolean | null =
|
|
1654
|
+
cliConfig.force === true ? true : null;
|
|
1655
|
+
if (sites.length > 0 && allowSitesCodePush === null) {
|
|
1656
|
+
const codeAnswer = await inquirer.prompt(questionsPushSitesCode);
|
|
1657
|
+
allowSitesCodePush = codeAnswer.override;
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1596
1660
|
const pushInstance = await createPushInstance();
|
|
1597
|
-
const
|
|
1661
|
+
const project = localConfig.getProject();
|
|
1662
|
+
const config: ConfigType = {
|
|
1663
|
+
projectId: project.projectId ?? "",
|
|
1664
|
+
projectName: project.projectName,
|
|
1665
|
+
settings: project.projectSettings,
|
|
1666
|
+
functions,
|
|
1667
|
+
sites,
|
|
1668
|
+
collections: localConfig.getCollections(),
|
|
1669
|
+
databases: localConfig.getDatabases(),
|
|
1670
|
+
tables: localConfig.getTables(),
|
|
1671
|
+
tablesDB: localConfig.getTablesDBs(),
|
|
1672
|
+
buckets: localConfig.getBuckets(),
|
|
1673
|
+
teams: localConfig.getTeams(),
|
|
1674
|
+
topics: localConfig.getMessagingTopics(),
|
|
1675
|
+
};
|
|
1676
|
+
|
|
1677
|
+
parseWithBetterErrors<ConfigType>(
|
|
1678
|
+
ConfigSchema,
|
|
1679
|
+
config,
|
|
1680
|
+
"Configuration validation failed",
|
|
1681
|
+
config,
|
|
1682
|
+
);
|
|
1598
1683
|
|
|
1599
1684
|
await pushInstance.pushResources(config, {
|
|
1685
|
+
all: cliConfig.all,
|
|
1600
1686
|
skipDeprecated,
|
|
1601
|
-
functionOptions: {
|
|
1602
|
-
|
|
1687
|
+
functionOptions: {
|
|
1688
|
+
code: allowFunctionsCodePush === true,
|
|
1689
|
+
withVariables: false,
|
|
1690
|
+
},
|
|
1691
|
+
siteOptions: { code: allowSitesCodePush === true, withVariables: false },
|
|
1603
1692
|
});
|
|
1604
1693
|
} else {
|
|
1605
1694
|
const actions: Record<string, (options?: any) => Promise<void>> = {
|
|
@@ -1763,12 +1852,20 @@ const pushSite = async ({
|
|
|
1763
1852
|
return;
|
|
1764
1853
|
}
|
|
1765
1854
|
|
|
1855
|
+
let allowCodePush: boolean | null = cliConfig.force === true ? true : null;
|
|
1856
|
+
if (code !== false && allowCodePush === null) {
|
|
1857
|
+
const codeAnswer = await inquirer.prompt(questionsPushSitesCode);
|
|
1858
|
+
allowCodePush = codeAnswer.override;
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
const shouldPushCode = code !== false && allowCodePush === true;
|
|
1862
|
+
|
|
1766
1863
|
log("Pushing sites ...");
|
|
1767
1864
|
|
|
1768
1865
|
const pushInstance = await createPushInstance();
|
|
1769
1866
|
const result = await pushInstance.pushSites(sites, {
|
|
1770
1867
|
async: asyncDeploy,
|
|
1771
|
-
code,
|
|
1868
|
+
code: shouldPushCode,
|
|
1772
1869
|
withVariables,
|
|
1773
1870
|
});
|
|
1774
1871
|
|
|
@@ -1883,12 +1980,20 @@ const pushFunction = async ({
|
|
|
1883
1980
|
return;
|
|
1884
1981
|
}
|
|
1885
1982
|
|
|
1983
|
+
let allowCodePush: boolean | null = cliConfig.force === true ? true : null;
|
|
1984
|
+
if (code !== false && allowCodePush === null) {
|
|
1985
|
+
const codeAnswer = await inquirer.prompt(questionsPushFunctionsCode);
|
|
1986
|
+
allowCodePush = codeAnswer.override;
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
const shouldPushCode = code !== false && allowCodePush === true;
|
|
1990
|
+
|
|
1886
1991
|
log("Pushing functions ...");
|
|
1887
1992
|
|
|
1888
1993
|
const pushInstance = await createPushInstance();
|
|
1889
1994
|
const result = await pushInstance.pushFunctions(functions, {
|
|
1890
1995
|
async: asyncDeploy,
|
|
1891
|
-
code,
|
|
1996
|
+
code: shouldPushCode,
|
|
1892
1997
|
withVariables,
|
|
1893
1998
|
});
|
|
1894
1999
|
|
package/lib/commands/schema.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { getDatabasesService } from "../../services.js";
|
|
3
3
|
import { KeysAttributes } from "../../config.js";
|
|
4
|
-
import { log, success, cliConfig, drawTable } from "../../parser.js";
|
|
4
|
+
import { log, success, error, cliConfig, drawTable } from "../../parser.js";
|
|
5
5
|
import { Pools } from "./pools.js";
|
|
6
6
|
import inquirer from "inquirer";
|
|
7
7
|
|
|
@@ -591,15 +591,21 @@ export class Attributes {
|
|
|
591
591
|
|
|
592
592
|
if (changes.length > 0) {
|
|
593
593
|
changedAttributes = changes.map((change) => change.attribute);
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
594
|
+
try {
|
|
595
|
+
await Promise.all(
|
|
596
|
+
changedAttributes.map((changed) =>
|
|
597
|
+
this.updateAttribute(
|
|
598
|
+
collection["databaseId"],
|
|
599
|
+
collection["$id"],
|
|
600
|
+
changed,
|
|
601
|
+
),
|
|
600
602
|
),
|
|
601
|
-
)
|
|
602
|
-
)
|
|
603
|
+
);
|
|
604
|
+
} catch (err) {
|
|
605
|
+
error(
|
|
606
|
+
`Error updating attribute for ${collection["$id"]}: ${String(err)}`,
|
|
607
|
+
);
|
|
608
|
+
}
|
|
603
609
|
}
|
|
604
610
|
|
|
605
611
|
const deletingAttributes = deleting.map((change) => change.attribute);
|
|
@@ -44,7 +44,7 @@ export class Pools {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
if (this.pollMaxDebounces === this.POLL_DEFAULT_VALUE) {
|
|
47
|
-
let steps = Math.max(1, Math.ceil(total / this.STEP_SIZE));
|
|
47
|
+
let steps = Math.max(1, Math.ceil(Number(total) / this.STEP_SIZE));
|
|
48
48
|
if (steps > 1 && iteration === 1) {
|
|
49
49
|
this.pollMaxDebounces *= steps;
|
|
50
50
|
|
|
@@ -83,7 +83,7 @@ export class Pools {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
if (this.pollMaxDebounces === this.POLL_DEFAULT_VALUE) {
|
|
86
|
-
let steps = Math.max(1, Math.ceil(total / this.STEP_SIZE));
|
|
86
|
+
let steps = Math.max(1, Math.ceil(Number(total) / this.STEP_SIZE));
|
|
87
87
|
if (steps > 1 && iteration === 1) {
|
|
88
88
|
this.pollMaxDebounces *= steps;
|
|
89
89
|
|
package/lib/config.ts
CHANGED
|
@@ -24,7 +24,7 @@ import type {
|
|
|
24
24
|
import { createSettingsObject } from "./utils.js";
|
|
25
25
|
import { SDK_TITLE_LOWER } from "./constants.js";
|
|
26
26
|
|
|
27
|
-
const JSONBigInt = JSONbig({
|
|
27
|
+
const JSONBigInt = JSONbig({ useNativeBigInt: true });
|
|
28
28
|
|
|
29
29
|
const KeysVars = new Set(["key", "value"]);
|
|
30
30
|
const KeysSite = new Set([
|
|
@@ -159,6 +159,41 @@ const KeyIndexesColumns = new Set([
|
|
|
159
159
|
"orders",
|
|
160
160
|
]);
|
|
161
161
|
|
|
162
|
+
const CONFIG_KEY_ORDER = [
|
|
163
|
+
"projectId",
|
|
164
|
+
"projectName",
|
|
165
|
+
"endpoint",
|
|
166
|
+
"settings",
|
|
167
|
+
"functions",
|
|
168
|
+
"sites",
|
|
169
|
+
"databases",
|
|
170
|
+
"collections",
|
|
171
|
+
"tablesDB",
|
|
172
|
+
"tables",
|
|
173
|
+
"buckets",
|
|
174
|
+
"teams",
|
|
175
|
+
"topics",
|
|
176
|
+
"messages",
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
function orderConfigKeys<T extends Record<string, any>>(data: T): T {
|
|
180
|
+
const ordered: Record<string, any> = {};
|
|
181
|
+
|
|
182
|
+
for (const key of CONFIG_KEY_ORDER) {
|
|
183
|
+
if (key in data) {
|
|
184
|
+
ordered[key] = data[key];
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
for (const key of Object.keys(data)) {
|
|
189
|
+
if (!(key in ordered)) {
|
|
190
|
+
ordered[key] = data[key];
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return ordered as T;
|
|
195
|
+
}
|
|
196
|
+
|
|
162
197
|
function whitelistKeys<T = any>(
|
|
163
198
|
value: T,
|
|
164
199
|
keys: Set<string>,
|
|
@@ -326,6 +361,17 @@ class Local extends Config<ConfigType> {
|
|
|
326
361
|
this.configDirectoryPath = _path.dirname(absolutePath);
|
|
327
362
|
}
|
|
328
363
|
|
|
364
|
+
write(): void {
|
|
365
|
+
const dir = _path.dirname(this.path);
|
|
366
|
+
if (!fs.existsSync(dir)) {
|
|
367
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
368
|
+
}
|
|
369
|
+
const orderedData = orderConfigKeys(this.data);
|
|
370
|
+
fs.writeFileSync(this.path, JSONBigInt.stringify(orderedData, null, 4), {
|
|
371
|
+
mode: 0o600,
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
|
|
329
375
|
static findConfigFile(filename: string): string | null {
|
|
330
376
|
let currentPath = process.cwd();
|
|
331
377
|
|
package/lib/constants.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SDK
|
|
2
2
|
export const SDK_TITLE = 'Appwrite';
|
|
3
3
|
export const SDK_TITLE_LOWER = 'appwrite';
|
|
4
|
-
export const SDK_VERSION = '13.0.0
|
|
4
|
+
export const SDK_VERSION = '13.0.0';
|
|
5
5
|
export const SDK_NAME = 'Command Line';
|
|
6
6
|
export const SDK_PLATFORM = 'console';
|
|
7
7
|
export const SDK_LANGUAGE = 'cli';
|
package/lib/questions.ts
CHANGED
|
@@ -368,6 +368,14 @@ export const questionsPullFunctionsCode: Question[] = [
|
|
|
368
368
|
},
|
|
369
369
|
];
|
|
370
370
|
|
|
371
|
+
export const questionsPushFunctionsCode: Question[] = [
|
|
372
|
+
{
|
|
373
|
+
type: "confirm",
|
|
374
|
+
name: "override",
|
|
375
|
+
message: "Do you want to create a deployment for your functions?",
|
|
376
|
+
},
|
|
377
|
+
];
|
|
378
|
+
|
|
371
379
|
export const questionsPullSites: Question[] = [
|
|
372
380
|
{
|
|
373
381
|
type: "checkbox",
|
|
@@ -403,6 +411,14 @@ export const questionsPullSitesCode: Question[] = [
|
|
|
403
411
|
},
|
|
404
412
|
];
|
|
405
413
|
|
|
414
|
+
export const questionsPushSitesCode: Question[] = [
|
|
415
|
+
{
|
|
416
|
+
type: "confirm",
|
|
417
|
+
name: "override",
|
|
418
|
+
message: "Do you want to create a deployment for your sites?",
|
|
419
|
+
},
|
|
420
|
+
];
|
|
421
|
+
|
|
406
422
|
export const questionsCreateFunction: Question[] = [
|
|
407
423
|
{
|
|
408
424
|
type: "input",
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"type": "module",
|
|
4
4
|
"homepage": "https://appwrite.io/support",
|
|
5
5
|
"description": "Appwrite is an open-source self-hosted backend server that abstracts and simplifies complex and repetitive development tasks behind a very simple REST API",
|
|
6
|
-
"version": "13.0.0
|
|
6
|
+
"version": "13.0.0",
|
|
7
7
|
"license": "BSD-3-Clause",
|
|
8
8
|
"main": "dist/index.js",
|
|
9
9
|
"types": "dist/index.d.ts",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/ScoopInstaller/Scoop/master/schema.json",
|
|
3
|
-
"version": "13.0.0
|
|
3
|
+
"version": "13.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/13.0.0
|
|
9
|
+
"url": "https://github.com/appwrite/sdk-for-cli/releases/download/13.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/13.0.0
|
|
18
|
+
"url": "https://github.com/appwrite/sdk-for-cli/releases/download/13.0.0/appwrite-cli-win-arm64.exe",
|
|
19
19
|
"bin": [
|
|
20
20
|
[
|
|
21
21
|
"appwrite-cli-win-arm64.exe",
|