@social-mail/social-mail-web-server 1.5.52 → 1.5.53

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.
Files changed (49) hide show
  1. package/dist/server/model/SocialMailContext.d.ts +2 -0
  2. package/dist/server/model/SocialMailContext.d.ts.map +1 -1
  3. package/dist/server/model/SocialMailContext.js +2 -0
  4. package/dist/server/model/SocialMailContext.js.map +1 -1
  5. package/dist/server/model/SocialMailContextEvents.d.ts.map +1 -1
  6. package/dist/server/model/SocialMailContextEvents.js +3 -0
  7. package/dist/server/model/SocialMailContextEvents.js.map +1 -1
  8. package/dist/server/model/entities/EmailAddressName.d.ts +3 -1
  9. package/dist/server/model/entities/EmailAddressName.d.ts.map +1 -1
  10. package/dist/server/model/entities/EmailAddressName.js +4 -4
  11. package/dist/server/model/entities/EmailAddressName.js.map +1 -1
  12. package/dist/server/model/entities/NameToken.d.ts +27 -0
  13. package/dist/server/model/entities/NameToken.d.ts.map +1 -0
  14. package/dist/server/model/entities/NameToken.js +63 -0
  15. package/dist/server/model/entities/NameToken.js.map +1 -0
  16. package/dist/server/model/entities/Tag.d.ts +0 -2
  17. package/dist/server/model/entities/Tag.d.ts.map +1 -1
  18. package/dist/server/model/entities/Tag.js.map +1 -1
  19. package/dist/server/model/events/NameTokenEvents.d.ts +7 -0
  20. package/dist/server/model/events/NameTokenEvents.d.ts.map +1 -0
  21. package/dist/server/model/events/NameTokenEvents.js +10 -0
  22. package/dist/server/model/events/NameTokenEvents.js.map +1 -0
  23. package/dist/server/services/EmailAddressService.d.ts.map +1 -1
  24. package/dist/server/services/EmailAddressService.js +5 -3
  25. package/dist/server/services/EmailAddressService.js.map +1 -1
  26. package/dist/server/services/name-tokens/NameTokenService.d.ts +7 -0
  27. package/dist/server/services/name-tokens/NameTokenService.d.ts.map +1 -0
  28. package/dist/server/services/name-tokens/NameTokenService.js +105 -0
  29. package/dist/server/services/name-tokens/NameTokenService.js.map +1 -0
  30. package/dist/server/workflows/repair/tags/RepairEmailNameTagsWorkflow.d.ts +7 -3
  31. package/dist/server/workflows/repair/tags/RepairEmailNameTagsWorkflow.d.ts.map +1 -1
  32. package/dist/server/workflows/repair/tags/RepairEmailNameTagsWorkflow.js +12 -13
  33. package/dist/server/workflows/repair/tags/RepairEmailNameTagsWorkflow.js.map +1 -1
  34. package/dist/tsconfig.tsbuildinfo +1 -1
  35. package/package.json +1 -1
  36. package/src/server/model/SocialMailContext.ts +3 -0
  37. package/src/server/model/SocialMailContextEvents.ts +3 -0
  38. package/src/server/model/entities/EmailAddressName.ts +5 -3
  39. package/src/server/model/entities/NameToken.ts +54 -0
  40. package/src/server/model/entities/Tag.ts +0 -2
  41. package/src/server/model/events/NameTokenEvents.ts +15 -0
  42. package/src/server/services/EmailAddressService.ts +5 -3
  43. package/src/server/services/name-tokens/NameTokenService.ts +43 -0
  44. package/src/server/workflows/repair/tags/RepairEmailNameTagsWorkflow.ts +14 -12
  45. package/dist/server/workflows/email-address/UpdateEmailAddressNameWorkflow.d.ts +0 -11
  46. package/dist/server/workflows/email-address/UpdateEmailAddressNameWorkflow.d.ts.map +0 -1
  47. package/dist/server/workflows/email-address/UpdateEmailAddressNameWorkflow.js +0 -44
  48. package/dist/server/workflows/email-address/UpdateEmailAddressNameWorkflow.js.map +0 -1
  49. package/src/server/workflows/email-address/UpdateEmailAddressNameWorkflow.ts +0 -30
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@social-mail/social-mail-web-server",
3
- "version": "1.5.52",
3
+ "version": "1.5.53",
4
4
  "description": "## Phase 1",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -46,6 +46,7 @@ import VerificationToken, { VerificationTokenAddress } from "./entities/Verifica
46
46
  import MailboxFolder from "./entities/MailboxFolder.js";
47
47
  import HostedZone, { HostedZoneRecord, HostedZoneUser } from "./entities/HostedZone.js";
48
48
  import EmailAddressName from "./entities/EmailAddressName.js";
49
+ import NameToken from "./entities/NameToken.js";
49
50
 
50
51
  @RegisterScoped
51
52
  export default class SocialMailContext extends EntityContext {
@@ -124,6 +125,8 @@ export default class SocialMailContext extends EntityContext {
124
125
 
125
126
  public mailboxSyncTargets = this.model.register(MailboxSyncTarget);
126
127
 
128
+ public nameTokens = this.model.register(NameToken);
129
+
127
130
  public channelConfigs = this.model.register(ChannelConfig);
128
131
 
129
132
  public subscriberEmails = this.model.register(SubscriberEmail);
@@ -99,6 +99,8 @@ import HostedZone, { HostedZoneRecord, HostedZoneUser } from "./entities/HostedZ
99
99
  import HostedZoneEvents, { HostedZoneRecordEvents, HostedZoneUserEvents } from "./events/HostedZoneEvents.js";
100
100
  import EmailAddressName from "./entities/EmailAddressName.js";
101
101
  import EmailAddressNameEvents from "./events/EmailAddressNameEvents.js";
102
+ import NameToken from "./entities/NameToken.js";
103
+ import NameTokenEvents from "./events/NameTokenEvents.js";
102
104
 
103
105
  @RegisterSingleton
104
106
  export default class SocialMailContextEvents extends ContextEvents {
@@ -141,6 +143,7 @@ export default class SocialMailContextEvents extends ContextEvents {
141
143
  this.register(MailboxContactEmail, MailboxContactEmailEvents);
142
144
  this.register(MailboxContactTag, MailboxContactTagEvents);
143
145
  this.register(MailboxEmail, MailboxEmailEvents);
146
+ this.register(NameToken, NameTokenEvents);
144
147
  this.register(Store, StoreEvents);
145
148
  this.register(StoreUser, StoreUserEvents);
146
149
  this.register(StoreItem, StoreItemEvents);
@@ -3,6 +3,7 @@ import Table from "@entity-access/entity-access/dist/decorators/Table.js";
3
3
  import { RelateTo } from "@entity-access/entity-access/dist/decorators/Relate.js";
4
4
  import EmailAddress from "./EmailAddress.js";
5
5
  import Tag from "./Tag.js";
6
+ import NameToken from "./NameToken.js";
6
7
 
7
8
  /**
8
9
  * This table exists as an index of all historical name tokens used in the email address.
@@ -19,11 +20,11 @@ import Tag from "./Tag.js";
19
20
  export default class EmailAddressName {
20
21
 
21
22
  @Column({ dataType: "BigInt", key: true })
22
- @RelateTo(Tag, {
23
- property: (x) => x.tag,
23
+ @RelateTo(NameToken, {
24
+ property: (x) => x.nameToken,
24
25
  inverseProperty: (x) => x.emailAddressNames
25
26
  })
26
- tagID: number;
27
+ nameTokenID: number;
27
28
 
28
29
  @Column({ dataType: "BigInt", key: true })
29
30
  @RelateTo(EmailAddress, {
@@ -34,4 +35,5 @@ export default class EmailAddressName {
34
35
 
35
36
  tag: Tag;
36
37
  emailAddress: EmailAddress;
38
+ nameToken: NameToken;
37
39
  }
@@ -0,0 +1,54 @@
1
+ import CheckConstraint from "@entity-access/entity-access/dist/decorators/CheckConstraint.js";
2
+ import Column from "@entity-access/entity-access/dist/decorators/Column.js";
3
+ import Index from "@entity-access/entity-access/dist/decorators/Index.js";
4
+ import Table from "@entity-access/entity-access/dist/decorators/Table.js";
5
+ import Sql from "@entity-access/entity-access/dist/sql/Sql.js";
6
+ import type EmailAddressName from "./EmailAddressName.js";
7
+
8
+ /**
9
+ * Since set of names will intersect with set of tags very rarely.
10
+ * We want to break names by spaces and save tokens with and without numbers.
11
+ * We will save username @ domain.com separately for faster search.
12
+ *
13
+ * Why not store full text in EmailAddressName itself?
14
+ * Since one name will be linked with many addresses. It will require less
15
+ * storage and faster access compared to inbuilt FTS.
16
+ *
17
+ * And This is the most importat part for Auto Complete.
18
+ *
19
+ * Why store suggest column?
20
+ * In dropdown we will only display suggestion if the name token has more than
21
+ * 2 chars.
22
+ *
23
+ * So why store less than 2 chars?
24
+ * User should be able to search `akash.in` by searching for 'in' in the search bar
25
+ * ignoring auto complete.
26
+ */
27
+
28
+ @Table("NameTokens")
29
+ @Index({
30
+ name: "UX_NameTokens_Unique",
31
+ unique: true,
32
+ columns: [
33
+ { name: (x) => x.word, descending: false },
34
+ ]
35
+ })
36
+ @Index({
37
+ name: "IX_NameTokens_Suggest",
38
+ columns: [ { name: (x) => x.word, descending: false }],
39
+ filter: (x) => x.suggest === true
40
+ })
41
+ export default class NameToken {
42
+
43
+ @Column({ dataType: "BigInt", key: true, generated: "identity"})
44
+ public nameTokenID: number;
45
+
46
+ @Column({ dataType: "Char", length: 400 })
47
+ public word: string;
48
+
49
+ @Column({ dataType:"Boolean", computed: (x) => Sql.text.length(x.word) > 2})
50
+ public suggest: boolean;
51
+
52
+ emailAddressNames: EmailAddressName[];
53
+
54
+ }
@@ -10,7 +10,6 @@ import type MailboxContactTag from "./MailboxContactTag.js";
10
10
  import type EmailTag from "./EmailTag.js";
11
11
  import type { StoreItemFolderTag, StoreItemTag, StoreTag } from "./Store.js";
12
12
  import type MailboxFolder from "./MailboxFolder.js";
13
- import type EmailAddressName from "./EmailAddressName.js";
14
13
 
15
14
  /**
16
15
  * The reason tags table exists in form of string,bigint pair is, we need
@@ -84,5 +83,4 @@ export default class Tag {
84
83
  storeTags: StoreTag[];
85
84
  storeItemFolderTags: StoreItemFolderTag[];
86
85
  mailboxFolders: MailboxFolder[];
87
- emailAddressNames: EmailAddressName[];
88
86
  }
@@ -0,0 +1,15 @@
1
+ import { IEntityQuery } from "@entity-access/entity-access/dist/model/IFilterWithParameter.js";
2
+ import NameToken from "../entities/NameToken.js";
3
+ import AuthenticatedEvents from "./AuthenticatedEvents.js";
4
+
5
+
6
+ export default class NameTokenEvents extends AuthenticatedEvents<NameToken> {
7
+
8
+ filter(query: IEntityQuery<NameToken>): IEntityQuery<NameToken> {
9
+ if (this.verify) {
10
+ this.sessionUser.ensureLoggedIn();
11
+ }
12
+ return query.limit(20);
13
+ }
14
+
15
+ }
@@ -6,7 +6,7 @@ import EntityAccessError from "@entity-access/entity-access/dist/common/EntityAc
6
6
  import { cacheFor } from "../../common/cacheFor.js";
7
7
  import Domain from "../model/entities/Domain.js";
8
8
  import WorkflowContext from "@entity-access/entity-access/dist/workflows/WorkflowContext.js";
9
- import UpdateEmailAddressNameWorkflow from "../workflows/email-address/UpdateEmailAddressNameWorkflow.js";
9
+ import RepairEmailNameTagsWorkflow from "../workflows/repair/tags/RepairEmailNameTagsWorkflow.js";
10
10
 
11
11
 
12
12
  @RegisterSingleton
@@ -157,7 +157,7 @@ export default class EmailAddressService {
157
157
  return await this.getId(emailAddress + "@empty", name);
158
158
  }
159
159
 
160
- const [ e, domainName ] = tokens;
160
+ const [ username, domainName ] = tokens;
161
161
 
162
162
  using scope = globalServices.createScope();
163
163
  const db = scope.resolve(SocialMailContext);
@@ -189,7 +189,9 @@ export default class EmailAddressService {
189
189
  if (name && ea.name !== name) {
190
190
  // schedule for names tag
191
191
  const wc = ServiceProvider.resolve(this, WorkflowContext);
192
- await wc.queue(UpdateEmailAddressNameWorkflow, { id: ea.emailAddressID, name });
192
+ await wc.queue(RepairEmailNameTagsWorkflow, { id: ea.emailAddressID, name });
193
+ // we should try to save username as well but without stripping numbers
194
+ await wc.queue(RepairEmailNameTagsWorkflow, { id: ea.emailAddressID, name:username, includeNumbers: true });
193
195
  }
194
196
  if(!hasMailbox && ((name && ea.name !== name) || ea.domainID !== domainID)) {
195
197
  ea.name = name;
@@ -0,0 +1,43 @@
1
+ import { RegisterSingleton, ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
2
+ import SocialMailContext from "../../model/SocialMailContext.js";
3
+
4
+ @RegisterSingleton
5
+ export default class NameTokenService {
6
+
7
+ async updateName(name: string, { emailAddressID }, includeNumbers = false) {
8
+ name = name?.trim();
9
+ if (!name) {
10
+ return [];
11
+ }
12
+ name = name.toLowerCase();
13
+ const ids = [];
14
+
15
+ const regex = includeNumbers
16
+ ? /[^\p{L}\d]+/igmu
17
+ : /[^\p{L}]+/igmu;
18
+
19
+ const tokens = name.split(regex);
20
+ using scope = ServiceProvider.createScope(this);
21
+ const db = scope.resolve(SocialMailContext);
22
+ for (const token of tokens) {
23
+ if (!token) {
24
+ continue;
25
+ }
26
+ if (token.length < 2) {
27
+ continue;
28
+ }
29
+ const nameTokenID = await this.getOrSaveToken(db, token);
30
+ if (emailAddressID) {
31
+ // save tokens..
32
+ await db.emailAddressNames.statements.selectOrInsert({ emailAddressID, nameTokenID }, { emailAddressID, nameTokenID });
33
+ }
34
+ ids.push(nameTokenID);
35
+ }
36
+ return ids;
37
+ }
38
+
39
+ private async getOrSaveToken(db: SocialMailContext, word: string) {
40
+ const w = await db.nameTokens.statements.selectOrInsert({ word }, { word });
41
+ return w.nameTokenID;
42
+ }
43
+ }
@@ -4,8 +4,9 @@ import Inject from "@entity-access/entity-access/dist/di/di.js";
4
4
  import Hashtags from "../../../../common/Hashtags.js";
5
5
  import TagService from "../../../services/tags/TagService.js";
6
6
  import { Email } from "../../../model/entities/Email.js";
7
+ import NameTokenService from "../../../services/name-tokens/NameTokenService.js";
7
8
 
8
- export default class RepairEmailNameTagsWorkflow extends Workflow {
9
+ export default class RepairEmailNameTagsWorkflow extends Workflow<{ id: number, name: string, includeNumbers?: boolean }> {
9
10
 
10
11
  static taskGroup = "batch";
11
12
 
@@ -20,9 +21,15 @@ export default class RepairEmailNameTagsWorkflow extends Workflow {
20
21
  async fixEmailTags(
21
22
  start: number,
22
23
  @Inject db?: SocialMailContext,
23
- @Inject ts?: TagService
24
+ @Inject nts?: NameTokenService
24
25
  ) {
25
26
 
27
+ if (typeof this.input === "object" && this.input?.id) {
28
+ const ea = await db.emailAddresses.statements.select({}, { emailAddressID: this.input.id });
29
+ await nts.updateName(this.input.name, ea, this.input.includeNumbers);
30
+ return 0;
31
+ }
32
+
26
33
  for(let i = 0;i< 100;i++) {
27
34
  const emails = await db.emailAddresses.where({ start }, (p) => (x) => x.emailAddressID > p.start)
28
35
  .orderBy(void 0, (p) => (x) => x.emailAddressID)
@@ -33,20 +40,15 @@ export default class RepairEmailNameTagsWorkflow extends Workflow {
33
40
  return 0;
34
41
  }
35
42
 
36
- for (const { emailAddressID, name } of emails) {
43
+ for (const { emailAddressID, name, emailAddress } of emails) {
37
44
  start = emailAddressID;
38
45
  if (!name) {
39
46
  continue;
40
47
  }
41
- // fix tag...
42
- const tokens = name.split(/[^\p{L}]+/igmu);
43
- for (const token of tokens) {
44
- if (!token) {
45
- continue;
46
- }
47
- const tagID = await ts.getSystemTagID(token);
48
- await db.emailAddressNames.statements.selectOrInsert({ tagID, emailAddressID },{ tagID, emailAddressID });
49
- }
48
+ await nts.updateName(name, { emailAddressID });
49
+ const [username ] = emailAddress.split("@", 2);
50
+ await nts.updateName(username, { emailAddressID }, true);
51
+
50
52
  }
51
53
  db.changeSet.clear();
52
54
  }
@@ -1,11 +0,0 @@
1
- import Workflow from "@entity-access/entity-access/dist/workflows/Workflow.js";
2
- import SocialMailContext from "../../model/SocialMailContext.js";
3
- import TagService from "../../services/tags/TagService.js";
4
- export default class UpdateEmailAddressNameWorkflow extends Workflow<{
5
- id: number;
6
- name: string;
7
- }> {
8
- run(): Promise<number>;
9
- update(db?: SocialMailContext, ts?: TagService): Promise<void>;
10
- }
11
- //# sourceMappingURL=UpdateEmailAddressNameWorkflow.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"UpdateEmailAddressNameWorkflow.d.ts","sourceRoot":"","sources":["../../../../src/server/workflows/email-address/UpdateEmailAddressNameWorkflow.ts"],"names":[],"mappings":"AACA,OAAO,QAA4B,MAAM,yDAAyD,CAAC;AACnG,OAAO,iBAAiB,MAAM,kCAAkC,CAAC;AACjE,OAAO,UAAU,MAAM,mCAAmC,CAAC;AAE3D,MAAM,CAAC,OAAO,OAAO,8BAA+B,SAAQ,QAAQ,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;IAExF,GAAG;IAMH,MAAM,CACA,EAAE,CAAC,EAAE,iBAAiB,EACtB,EAAE,CAAC,EAAE,UAAU;CAc9B"}
@@ -1,44 +0,0 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
6
- };
7
- var __metadata = (this && this.__metadata) || function (k, v) {
8
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
- };
10
- var __param = (this && this.__param) || function (paramIndex, decorator) {
11
- return function (target, key) { decorator(target, key, paramIndex); }
12
- };
13
- import Inject from "@entity-access/entity-access/dist/di/di.js";
14
- import Workflow, { UniqueActivity } from "@entity-access/entity-access/dist/workflows/Workflow.js";
15
- import SocialMailContext from "../../model/SocialMailContext.js";
16
- import TagService from "../../services/tags/TagService.js";
17
- export default class UpdateEmailAddressNameWorkflow extends Workflow {
18
- async run() {
19
- await this.update();
20
- return 1;
21
- }
22
- async update(db, ts) {
23
- const { id: emailAddressID } = this.input;
24
- // split tags...
25
- const tokens = this.input.name.split(/[^\p{L}]+/igmu);
26
- for (const token of tokens) {
27
- if (!token) {
28
- continue;
29
- }
30
- const tagID = await ts.getSystemTagID(token);
31
- await db.emailAddressNames.statements.selectOrInsert({ tagID, emailAddressID }, { tagID, emailAddressID });
32
- }
33
- }
34
- }
35
- __decorate([
36
- UniqueActivity,
37
- __param(0, Inject),
38
- __param(1, Inject),
39
- __metadata("design:type", Function),
40
- __metadata("design:paramtypes", [SocialMailContext,
41
- TagService]),
42
- __metadata("design:returntype", Promise)
43
- ], UpdateEmailAddressNameWorkflow.prototype, "update", null);
44
- //# sourceMappingURL=UpdateEmailAddressNameWorkflow.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"UpdateEmailAddressNameWorkflow.js","sourceRoot":"","sources":["../../../../src/server/workflows/email-address/UpdateEmailAddressNameWorkflow.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,MAAM,MAAM,4CAA4C,CAAC;AAChE,OAAO,QAAQ,EAAE,EAAE,cAAc,EAAE,MAAM,yDAAyD,CAAC;AACnG,OAAO,iBAAiB,MAAM,kCAAkC,CAAC;AACjE,OAAO,UAAU,MAAM,mCAAmC,CAAC;AAE3D,MAAM,CAAC,OAAO,OAAO,8BAA+B,SAAQ,QAAsC;IAE9F,KAAK,CAAC,GAAG;QACL,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACpB,OAAO,CAAC,CAAC;IACb,CAAC;IAGK,AAAN,KAAK,CAAC,MAAM,CACA,EAAsB,EACtB,EAAe;QAEvB,MAAM,EAAE,EAAE,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QAC1C,gBAAgB;QAChB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACtD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACzB,IAAI,CAAC,KAAK,EAAE,CAAC;gBACT,SAAS;YACb,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAC7C,MAAM,EAAE,CAAC,iBAAiB,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,EAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;QAC9G,CAAC;IACL,CAAC;CAEJ;AAhBS;IADL,cAAc;IAEV,WAAA,MAAM,CAAA;IACN,WAAA,MAAM,CAAA;;qCADM,iBAAiB;QACjB,UAAU;;4DAY1B"}
@@ -1,30 +0,0 @@
1
- import Inject from "@entity-access/entity-access/dist/di/di.js";
2
- import Workflow, { UniqueActivity } from "@entity-access/entity-access/dist/workflows/Workflow.js";
3
- import SocialMailContext from "../../model/SocialMailContext.js";
4
- import TagService from "../../services/tags/TagService.js";
5
-
6
- export default class UpdateEmailAddressNameWorkflow extends Workflow<{ id: number, name: string }> {
7
-
8
- async run() {
9
- await this.update();
10
- return 1;
11
- }
12
-
13
- @UniqueActivity
14
- async update(
15
- @Inject db?: SocialMailContext,
16
- @Inject ts?: TagService
17
- ) {
18
- const { id: emailAddressID } = this.input;
19
- // split tags...
20
- const tokens = this.input.name.split(/[^\p{L}]+/igmu);
21
- for (const token of tokens) {
22
- if (!token) {
23
- continue;
24
- }
25
- const tagID = await ts.getSystemTagID(token);
26
- await db.emailAddressNames.statements.selectOrInsert({ tagID, emailAddressID },{ tagID, emailAddressID });
27
- }
28
- }
29
-
30
- }