@social-mail/social-mail-web-server 1.7.537 → 1.7.539

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@social-mail/social-mail-web-server",
3
- "version": "1.7.537",
3
+ "version": "1.7.539",
4
4
  "description": "## Phase 1",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -5,7 +5,7 @@ export default async function seedUI(config: DBConfig) {
5
5
  await config.saveVersion(UIPackageConfig, {
6
6
  package: "@social-mail/social-mail-client",
7
7
  view: "dist/web/AppIndex",
8
- version: "1.8.108"
8
+ version: "1.8.111"
9
9
  });
10
10
 
11
11
  await config.saveVersion(WebComponentsPackageConfig, {
@@ -10,25 +10,30 @@ export default class FilePathService {
10
10
  db: SocialMailContext;
11
11
 
12
12
  async update(entity: AppFile) {
13
+ const { db } = this;
13
14
  const { parentID, isFolder } = entity;
15
+ let root = null;
14
16
  if (parentID) {
15
- await this.db.appFiles.where(entity, (p) => (x) => x.appFileID === p.appFileID)
16
- .update(void 0, (p) => (x) => ({ path: `${x.parent.path}${Sql.cast.asText(x.appFileID)}/` }));
17
-
17
+ const [ { path }] = await db.appFiles.where(entity, (p) => (x) => x.appFileID === p.appFileID)
18
+ .updateSelect(void 0, (p) => (x) => ({ path: `${x.parent.path}${Sql.cast.asText(x.appFileID)}/` }));
19
+ root = path + "%";
18
20
  } else if (isFolder) {
19
- await this.db.appFiles.where(entity, (p) => (x) => x.appFileID === p.appFileID)
20
- .update(void 0, (p) => (x) => ({ path: `${Sql.cast.asText(x.appFileID)}/` }));
21
+ const [{ path }] = await db.appFiles.where(entity, (p) => (x) => x.appFileID === p.appFileID)
22
+ .updateSelect(void 0, (p) => (x) => ({ path: `${Sql.cast.asText(x.appFileID)}/` }));
23
+ root = path + "%";
21
24
  }
22
25
 
23
- await this.db.appFiles.where(entity, (p) => (x) => x.parentID === p.appFileID)
24
- .update(void 0, (p) => (x) => ({ path: `${x.parent.path}${Sql.cast.asText(x.appFileID)}/` }));
25
-
26
- // do this for every folder
27
- const childFolders = await this.db.appFiles.where(entity, (p) => (x) => x.parentID === p.appFileID && x.isFolder === true)
28
- .toArray();
29
-
30
- for (const folder of childFolders) {
31
- await this.update(folder);
26
+ // following logic will recursively set all path correctly for every nested level
27
+ // this should run in a single transaction to avoid conflicts
28
+
29
+ for(;;) {
30
+ const n = await db.appFiles.where({ root }, (p) => (x) => !Sql.text.like(x.path, p.root) && Sql.text.like(x.parent.path, p.root))
31
+ .update(void 0, (p) => (x) => ({
32
+ path: `${x.parent.path}${x.appFileID}/`,
33
+ }));
34
+ if (!n) {
35
+ break;
36
+ }
32
37
  }
33
38
 
34
39
  }
@@ -7,82 +7,131 @@ import Sql from "@entity-access/entity-access/dist/sql/Sql.js";
7
7
  export default class DeleteFileWorkflow extends Workflow<{ fileID }> {
8
8
 
9
9
  path: string;
10
+ root: string;
10
11
 
11
12
  async run() {
12
13
 
14
+ // mark the file as deleted and remove from parent
15
+ this.root = await this.markDeleted();
16
+
13
17
  let start = 0;
14
18
  for(;;) {
15
19
 
16
- const r = await this.deleteChildren(start);
17
- start = r.start;
18
- if (!start) {
20
+ start = await this.deleteFiles(start, false);
21
+ if (!BigInt(start)) {
19
22
  break;
20
23
  }
21
- start = r.start;
22
- if (r.children?.length) {
23
- const all = r.children.map((x) => this.runChild(DeleteFileWorkflow, { fileID: x }));
24
- await this.all(all);
24
+ }
25
+
26
+ start = 0;
27
+ for(;;) {
28
+
29
+ start = await this.deleteFiles(start, true);
30
+ if (!BigInt(start)) {
31
+ break;
25
32
  }
26
33
  }
27
34
 
35
+
28
36
  await this.deleteFile();
29
37
 
30
38
  }
31
39
 
32
40
  @UniqueActivity
33
- async deleteFile(@Inject db?: SocialMailContext) {
34
- await db.websiteVersions.asQuery().delete(this.input, (p) => (x) => x.snapshotFolderID === p.fileID);
35
- const site = await db.websiteFolders.statements.select({}, { folderID: this.input.fileID });
36
- if (site) {
37
- if (site.currentTemplateID) {
38
- await db.websiteFolders.where(site, (p) => (x) => x.folderID === p.currentTemplateID && x.isTemplate === true)
39
- .update(this.input, (p) => (x) => ({ templateSites: Sql.math.max(0, x.templateSites -1) }));
41
+ async deleteFiles(
42
+ start,
43
+ isFolder,
44
+ @Inject db?: SocialMailContext) {
45
+ const { root } = this;
46
+ for (let index = 0; index < 100; index++) {
47
+
48
+ db.changeSet.clear();
49
+
50
+ const q = db.appFiles
51
+ .where({ start, root, isFolder }, (p) => (x) =>
52
+ Sql.text.like(x.path, p.root)
53
+ && x.isFolder === p.isFolder
54
+ && x.appFileID > p.start)
55
+ .orderBy(void 0, (p) => (x) => x.appFileID)
56
+ .limit(20);
57
+
58
+ if (isFolder) {
59
+ const n = await q.delete(void 0, (p) => (x) => x.isFolder === true);
60
+ if (!n) {
61
+ return 0;
62
+ }
63
+ continue;
64
+ }
65
+
66
+ const files = await db.appFiles
67
+ .where({ start, root, isFolder }, (p) => (x) =>
68
+ Sql.text.like(x.path, p.root)
69
+ && x.isFolder === p.isFolder
70
+ && x.appFileID > p.start)
71
+ .orderBy(void 0, (p) => (x) => x.appFileID)
72
+ .limit(20)
73
+ .toArray();
74
+
75
+ if (!files.length) {
76
+ return 0;
77
+ }
78
+
79
+ for (const { appFileID } of files) {
80
+ start = appFileID;
81
+ await db.fileContents.where({ appFileID }, (p) => (x) =>
82
+ x.appFiles.some((f) => f.appFileID === p.appFileID)
83
+ || x.versions.some((v) => v.fileID === p.appFileID))
84
+ .update(void 0, (p) => (x) => ({ deleted: true }));
85
+ await db.fileVersions.asQuery()
86
+ .delete({ appFileID }, (p) => (x) => x.fileID === p.appFileID);
87
+ await db.appFiles.statements.delete({ appFileID });
40
88
  }
41
- await db.websiteFolders.statements.delete({ folderID: site.folderID });
42
89
  }
43
- await db.appFiles.statements.delete({ appFileID: this.input.fileID});
90
+ return start;
44
91
  }
45
92
 
46
93
  @UniqueActivity
47
- async deleteChildren(
48
- start?: number,
49
- @Inject db?: SocialMailContext
50
- ) {
51
- const { fileID } = this.input;
52
- const files = await db.appFiles
53
- .where({ fileID , start }, (p) => (x) =>
54
- x.parentID === p.fileID
55
- && x.appFileID > p.start)
56
- .orderBy(void 0, (p) => (x) => x.appFileID)
57
- .limit(20)
58
- .toArray();
94
+ async markDeleted(@Inject db?: SocialMailContext) {
95
+ const { fileID: appFileID } = this.input;
59
96
 
60
- const children = [];
97
+ await using tx = await db.connection.createTransaction();
61
98
 
62
- if (files.length === 0) {
63
- return { start: 0, children };
64
- }
99
+ const now = Date.now();
65
100
 
66
- for (const { appFileID, isFolder } of files) {
67
- start = appFileID;
101
+ let root = `x-${now.toString(36)}/${appFileID}/`;
68
102
 
69
- if (isFolder) {
70
- children.push(appFileID);
71
- continue;
103
+ await db.appFiles.statements.update({ parentID: null, path: root, isDeleted: true }, { appFileID });
104
+
105
+ root += "%";
106
+
107
+ for(;;) {
108
+ const n = await db.appFiles.where({ root }, (p) => (x) => !Sql.text.like(x.path, p.root) && Sql.text.like(x.parent.path, p.root))
109
+ .update(void 0, (p) => (x) => ({
110
+ path: `${x.parent.path}${x.appFileID}/`,
111
+ isDeleted: true
112
+ }));
113
+ if (!n) {
114
+ break;
72
115
  }
116
+ }
73
117
 
74
- await db.fileContents.where({ appFileID }, (p) => (x) =>
75
- x.appFiles.some((f) => f.appFileID === p.appFileID)
76
- || x.versions.some((v) => v.fileID === p.appFileID))
77
- .update(void 0, (p) => (x) => ({ deleted: true }));
118
+ await tx.commit();
78
119
 
79
- await db.fileVersions.asQuery()
80
- .delete({ appFileID }, (p) => (x) => x.fileID === p.appFileID);
120
+ return root;
121
+ }
81
122
 
82
- await db.appFiles.statements.delete({ appFileID });
123
+ @UniqueActivity
124
+ async deleteFile(@Inject db?: SocialMailContext) {
125
+ await db.websiteVersions.asQuery().delete(this.input, (p) => (x) => x.snapshotFolderID === p.fileID);
126
+ const site = await db.websiteFolders.statements.select({}, { folderID: this.input.fileID });
127
+ if (site) {
128
+ if (site.currentTemplateID) {
129
+ await db.websiteFolders.where(site, (p) => (x) => x.folderID === p.currentTemplateID && x.isTemplate === true)
130
+ .update(this.input, (p) => (x) => ({ templateSites: Sql.math.max(0, x.templateSites -1) }));
131
+ }
132
+ await db.websiteFolders.statements.delete({ folderID: site.folderID });
83
133
  }
84
-
85
- return { start, children };
134
+ await db.appFiles.statements.delete({ appFileID: this.input.fileID});
86
135
  }
87
136
 
88
137