fluxmail 0.1.0 → 0.2.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.
Files changed (54) hide show
  1. package/README.md +56 -0
  2. package/dist/accounts/googleAuth.js +7 -3
  3. package/dist/accounts/googleAuth.js.map +1 -1
  4. package/dist/accounts/registry.d.ts +11 -2
  5. package/dist/accounts/registry.d.ts.map +1 -1
  6. package/dist/accounts/registry.js +121 -28
  7. package/dist/accounts/registry.js.map +1 -1
  8. package/dist/cli.js +207 -12
  9. package/dist/cli.js.map +1 -1
  10. package/dist/config.d.ts +1 -1
  11. package/dist/config.d.ts.map +1 -1
  12. package/dist/config.js +13 -12
  13. package/dist/config.js.map +1 -1
  14. package/dist/http/app.d.ts.map +1 -1
  15. package/dist/http/app.js +12 -4
  16. package/dist/http/app.js.map +1 -1
  17. package/dist/index.d.ts +3 -3
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -3
  20. package/dist/index.js.map +1 -1
  21. package/dist/licensing/activation.d.ts.map +1 -1
  22. package/dist/licensing/activation.js.map +1 -1
  23. package/dist/licensing/entitlements.d.ts.map +1 -1
  24. package/dist/licensing/entitlements.js.map +1 -1
  25. package/dist/licensing/lease.d.ts.map +1 -1
  26. package/dist/licensing/lease.js.map +1 -1
  27. package/dist/mcp/buildServer.d.ts.map +1 -1
  28. package/dist/mcp/buildServer.js +40 -20
  29. package/dist/mcp/buildServer.js.map +1 -1
  30. package/dist/scheduler/sendScheduler.d.ts.map +1 -1
  31. package/dist/scheduler/sendScheduler.js +1 -3
  32. package/dist/scheduler/sendScheduler.js.map +1 -1
  33. package/dist/service/emailService.d.ts +1 -0
  34. package/dist/service/emailService.d.ts.map +1 -1
  35. package/dist/service/emailService.js +11 -6
  36. package/dist/service/emailService.js.map +1 -1
  37. package/dist/storage/apiKeys.d.ts.map +1 -1
  38. package/dist/storage/apiKeys.js +8 -2
  39. package/dist/storage/apiKeys.js.map +1 -1
  40. package/dist/storage/db.d.ts +312 -0
  41. package/dist/storage/db.d.ts.map +1 -1
  42. package/dist/storage/db.js +68 -0
  43. package/dist/storage/db.js.map +1 -1
  44. package/dist/storage/imapState.d.ts +15 -0
  45. package/dist/storage/imapState.d.ts.map +1 -0
  46. package/dist/storage/imapState.js +89 -0
  47. package/dist/storage/imapState.js.map +1 -0
  48. package/dist/storage/members.d.ts.map +1 -1
  49. package/dist/storage/members.js.map +1 -1
  50. package/dist/storage/scheduledSends.d.ts.map +1 -1
  51. package/dist/storage/scheduledSends.js.map +1 -1
  52. package/dist/version.d.ts.map +1 -1
  53. package/dist/version.js.map +1 -1
  54. package/package.json +17 -6
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # Fluxmail
2
+
3
+ Fluxmail is a self-hosted MCP server that connects AI agents to Gmail and IMAP/SMTP mailboxes. It gives MCP clients a consistent set of tools to read, search, draft, send, and organize email.
4
+
5
+ ## Install
6
+
7
+ Fluxmail requires Node.js 20 or later.
8
+
9
+ ```bash
10
+ npm install -g fluxmail
11
+ ```
12
+
13
+ ## Connect Gmail
14
+
15
+ Create a Google Cloud OAuth client with the Gmail API enabled, then save its credentials:
16
+
17
+ ```bash
18
+ fluxmail config set GOOGLE_CLIENT_ID <your-client-id>.apps.googleusercontent.com
19
+ fluxmail config set GOOGLE_CLIENT_SECRET <your-client-secret>
20
+ fluxmail accounts add gmail
21
+ ```
22
+
23
+ The last command opens Google's consent flow in your browser.
24
+
25
+ ## Connect IMAP
26
+
27
+ ```bash
28
+ fluxmail accounts add imap \
29
+ --email you@example.com \
30
+ --imap-host imap.example.com \
31
+ --smtp-host smtp.example.com
32
+ ```
33
+
34
+ Fluxmail prompts for the password and stores it encrypted. Use `--imap-password-env <name>` for Docker or scripted setup.
35
+
36
+ ## Connect an MCP client
37
+
38
+ Configure your client to launch `fluxmail stdio`. For example, with Claude Code:
39
+
40
+ ```bash
41
+ claude mcp add fluxmail -- fluxmail stdio
42
+ ```
43
+
44
+ Or with Codex CLI:
45
+
46
+ ```bash
47
+ codex mcp add fluxmail -- fluxmail stdio
48
+ ```
49
+
50
+ Fluxmail also supports Streamable HTTP for Docker and remote deployments.
51
+
52
+ See the [setup guide](https://fluxmail.ai/docs/quickstart) for Google OAuth configuration, Docker deployment, supported MCP clients, environment variables, and the complete tool list.
53
+
54
+ ## License
55
+
56
+ See the [repository](https://github.com/churichard/fluxmail-mcp) for license terms.
@@ -74,7 +74,7 @@ function callbackPage(title, message) {
74
74
  export async function exchangeCode(client, code) {
75
75
  const { tokens } = await client.getToken(code);
76
76
  if (!tokens.refresh_token) {
77
- throw new EmailError('invalid_request', 'Google did not return a refresh token. Remove Fluxmail from the account\'s third-party access ' +
77
+ throw new EmailError('invalid_request', "Google did not return a refresh token. Remove Fluxmail from the account's third-party access " +
78
78
  '(myaccount.google.com/permissions) and try again.');
79
79
  }
80
80
  return { ...(await identityFromIdToken(client, tokens)), tokens };
@@ -123,7 +123,9 @@ export async function runLoopbackFlow(config, onAuthUrl, onAuthorized) {
123
123
  const result = await exchangeCode(client, code);
124
124
  const accepted = onAuthorized ? await onAuthorized(result) : result;
125
125
  finish(() => resolve(accepted));
126
- res.writeHead(200, { 'content-type': 'text/html; charset=utf-8' }).end(callbackPage(`${result.email} is connected to Fluxmail`, 'The account is ready to use.'));
126
+ res
127
+ .writeHead(200, { 'content-type': 'text/html; charset=utf-8' })
128
+ .end(callbackPage(`${result.email} is connected to Fluxmail`, 'The account is ready to use.'));
127
129
  }
128
130
  catch (err) {
129
131
  finish(() => reject(err));
@@ -131,7 +133,9 @@ export async function runLoopbackFlow(config, onAuthUrl, onAuthorized) {
131
133
  const message = expected
132
134
  ? err.message
133
135
  : 'Fluxmail could not finish connecting this account. Check the terminal for details.';
134
- res.writeHead(expected ? 400 : 500, { 'content-type': 'text/html; charset=utf-8' }).end(callbackPage('Fluxmail could not connect this account', message));
136
+ res
137
+ .writeHead(expected ? 400 : 500, { 'content-type': 'text/html; charset=utf-8' })
138
+ .end(callbackPage('Fluxmail could not connect this account', message));
135
139
  }
136
140
  });
137
141
  server.on('error', (err) => reject(oauthListenerError(err, config.oauthPort)));
@@ -1 +1 @@
1
- {"version":3,"file":"googleAuth.js","sourceRoot":"","sources":["../../src/accounts/googleAuth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"googleAuth.js","sourceRoot":"","sources":["../../src/accounts/googleAuth.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { type Credentials } from 'google-auth-library';
2
2
  import { type Account, type EmailProvider } from '@fluxmail/core';
3
+ import { type ImapCredentials } from '@fluxmail/provider-imap';
3
4
  import type { FluxmailConfig } from '../config.js';
4
5
  import { type FluxmailDb } from '../storage/db.js';
5
6
  export declare class AccountRegistry {
@@ -7,6 +8,7 @@ export declare class AccountRegistry {
7
8
  private readonly config;
8
9
  private readonly providers;
9
10
  constructor(db: FluxmailDb, config: FluxmailConfig);
11
+ private evictProvider;
10
12
  listAccounts(): Account[];
11
13
  getAccount(accountId: string): Account;
12
14
  /** Fail before OAuth when a new account would exceed the current plan. */
@@ -14,12 +16,19 @@ export declare class AccountRegistry {
14
16
  /** Resolve an account id, defaulting to the sole account when only one exists. */
15
17
  resolveAccountId(accountId?: string): string;
16
18
  getProvider(accountId: string): EmailProvider;
17
- private loadTokenRow;
19
+ private loadCredentialRow;
18
20
  private loadTokens;
19
- private writeTokens;
21
+ private writeCredentials;
20
22
  private saveTokens;
23
+ private writeTokens;
21
24
  private buildGmailProvider;
22
25
  addGmailAccount(email: string, tokens: Credentials, displayName?: string, memberId?: string): Account;
26
+ testImapCredentials(email: string, credentials: ImapCredentials, displayName?: string): Promise<Array<{
27
+ message: string;
28
+ }>>;
29
+ addImapAccount(email: string, credentials: ImapCredentials, displayName?: string, memberId?: string, reauthorizeId?: string): Account;
30
+ loadImapCredentials(accountId: string): ImapCredentials;
31
+ saveImapCredentials(accountId: string, credentials: ImapCredentials): void;
23
32
  /** Assign a mailbox to a member, or make it shared again (memberId = null). */
24
33
  assignAccountMember(accountId: string, memberId: string | null): Account;
25
34
  removeAccount(accountId: string): void;
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/accounts/registry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAc,KAAK,OAAO,EAAE,KAAK,aAAa,EAAiB,MAAM,gBAAgB,CAAC;AAE7F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAyB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAM1E,qBAAa,eAAe;IAOxB,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPzB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAGtB;gBAGe,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,cAAc;IAGzC,YAAY,IAAI,OAAO,EAAE;IAgBzB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAMtC,0EAA0E;IAC1E,mBAAmB,IAAI,IAAI;IAkB3B,kFAAkF;IAClF,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM;IAoB5C,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa;IAiB7C,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,WAAW;IAiBnB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,kBAAkB;IAyB1B,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO;IAuCrG,+EAA+E;IAC/E,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;IAOxE,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAMtC,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;CAG/D"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/accounts/registry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAc,KAAK,OAAO,EAAE,KAAK,aAAa,EAAiB,MAAM,gBAAgB,CAAC;AAE7F,OAAO,EAAmC,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAChG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAA6C,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAO9F,qBAAa,eAAe;IAIxB,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJzB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgF;gBAGvF,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,cAAc;IAGzC,OAAO,CAAC,aAAa;IAMrB,YAAY,IAAI,OAAO,EAAE;IAgBzB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAMtC,0EAA0E;IAC1E,mBAAmB,IAAI,IAAI;IAc3B,kFAAkF;IAClF,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM;IAoB5C,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa;IAyB7C,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,kBAAkB;IAyB1B,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO;IAuC/F,mBAAmB,CACvB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,eAAe,EAC5B,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAgBtC,cAAc,CACZ,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,eAAe,EAC5B,WAAW,CAAC,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO;IAwCV,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe;IAQvD,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,eAAe,GAAG,IAAI;IAM1E,+EAA+E;IAC/E,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;IAOxE,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAMtC,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;CAG/D"}
@@ -3,11 +3,13 @@ import { eq } from 'drizzle-orm';
3
3
  import { OAuth2Client } from 'google-auth-library';
4
4
  import { EmailError } from '@fluxmail/core';
5
5
  import { GmailProvider, GMAIL_CAPABILITIES } from '@fluxmail/provider-gmail';
6
- import { accounts, oauthTokens } from '../storage/db.js';
6
+ import { ImapProvider, IMAP_CAPABILITIES } from '@fluxmail/provider-imap';
7
+ import { accountCredentials, accounts, oauthTokens } from '../storage/db.js';
7
8
  import { decryptString, encryptString } from '../storage/crypto.js';
8
9
  import { assertAccountLimit, getEntitlements } from '../licensing/entitlements.js';
9
10
  import { getMember } from '../storage/members.js';
10
11
  import { requireGoogleConfig } from './googleAuth.js';
12
+ import { SqliteImapStateStore } from '../storage/imapState.js';
11
13
  export class AccountRegistry {
12
14
  db;
13
15
  config;
@@ -16,6 +18,11 @@ export class AccountRegistry {
16
18
  this.db = db;
17
19
  this.config = config;
18
20
  }
21
+ evictProvider(accountId) {
22
+ const cached = this.providers.get(accountId)?.provider;
23
+ this.providers.delete(accountId);
24
+ void cached?.close?.();
25
+ }
19
26
  listAccounts() {
20
27
  return this.db
21
28
  .select()
@@ -27,7 +34,7 @@ export class AccountRegistry {
27
34
  email: row.email,
28
35
  ...(row.displayName ? { displayName: row.displayName } : {}),
29
36
  status: row.status,
30
- capabilities: GMAIL_CAPABILITIES,
37
+ capabilities: row.provider === 'imap' ? IMAP_CAPABILITIES : GMAIL_CAPABILITIES,
31
38
  ...(row.memberId ? { memberId: row.memberId } : {}),
32
39
  }));
33
40
  }
@@ -47,8 +54,7 @@ export class AccountRegistry {
47
54
  if (!(err instanceof EmailError))
48
55
  throw err;
49
56
  const reconnect = existing.length === 1
50
- ? `To reconnect ${existing[0].email}, rerun this command with ` +
51
- `"--reauthorize ${existing[0].id}".`
57
+ ? `To reconnect ${existing[0].email}, rerun this command with ` + `"--reauthorize ${existing[0].id}".`
52
58
  : 'To reconnect an existing account, rerun this command with "--reauthorize <account-id>".';
53
59
  throw new EmailError(err.code, `${err.message} ${reconnect}`);
54
60
  }
@@ -59,7 +65,7 @@ export class AccountRegistry {
59
65
  return this.getAccount(accountId).id;
60
66
  const all = this.listAccounts();
61
67
  if (all.length === 0) {
62
- throw new EmailError('invalid_request', 'No email accounts are connected yet. Run "fluxmail accounts add gmail" to connect one.');
68
+ throw new EmailError('invalid_request', 'No email accounts are connected yet. Run "fluxmail accounts add gmail" or "fluxmail accounts add imap".');
63
69
  }
64
70
  if (all.length > 1) {
65
71
  throw new EmailError('invalid_request', `Multiple accounts are connected; specify accountId. Available: ${all
@@ -70,36 +76,44 @@ export class AccountRegistry {
70
76
  }
71
77
  getProvider(accountId) {
72
78
  const account = this.getAccount(accountId);
73
- if (account.provider !== 'gmail') {
74
- throw new EmailError('unsupported_capability', `Provider "${account.provider}" is not supported yet`);
75
- }
76
- const tokenRow = this.loadTokenRow(accountId);
79
+ const credentialRow = this.loadCredentialRow(accountId);
77
80
  const cached = this.providers.get(accountId);
78
- if (cached?.encryptedTokens === tokenRow.encryptedTokens)
81
+ if (cached?.encryptedCredentials === credentialRow.encryptedCredentials)
79
82
  return cached.provider;
80
- const stored = JSON.parse(decryptString(this.config.encryptionKey, tokenRow.encryptedTokens));
81
- const provider = this.buildGmailProvider(accountId, account.email, stored, account.displayName);
82
- this.providers.set(accountId, { provider, encryptedTokens: tokenRow.encryptedTokens });
83
+ const stored = JSON.parse(decryptString(this.config.encryptionKey, credentialRow.encryptedCredentials));
84
+ const provider = account.provider === 'gmail'
85
+ ? this.buildGmailProvider(accountId, account.email, stored, account.displayName)
86
+ : account.provider === 'imap'
87
+ ? new ImapProvider({
88
+ accountId,
89
+ email: account.email,
90
+ ...(account.displayName ? { displayName: account.displayName } : {}),
91
+ credentials: stored,
92
+ store: new SqliteImapStateStore(this.db, accountId),
93
+ })
94
+ : undefined;
95
+ if (!provider)
96
+ throw new EmailError('unsupported_capability', `Provider "${account.provider}" is not supported yet`);
97
+ this.providers.set(accountId, { provider, encryptedCredentials: credentialRow.encryptedCredentials });
83
98
  return provider;
84
99
  }
85
- loadTokenRow(accountId) {
86
- const row = this.db.select().from(oauthTokens).where(eq(oauthTokens.accountId, accountId)).get();
100
+ loadCredentialRow(accountId) {
101
+ const row = this.db.select().from(accountCredentials).where(eq(accountCredentials.accountId, accountId)).get();
87
102
  if (!row)
88
103
  throw new EmailError('auth_expired', `No stored credentials for account ${accountId}`);
89
104
  return row;
90
105
  }
91
106
  loadTokens(accountId) {
92
- const row = this.loadTokenRow(accountId);
93
- return JSON.parse(decryptString(this.config.encryptionKey, row.encryptedTokens));
107
+ const row = this.loadCredentialRow(accountId);
108
+ return JSON.parse(decryptString(this.config.encryptionKey, row.encryptedCredentials));
94
109
  }
95
- writeTokens(db, accountId, tokens) {
96
- const encrypted = encryptString(this.config.encryptionKey, JSON.stringify(tokens));
97
- db
98
- .insert(oauthTokens)
99
- .values({ accountId, encryptedTokens: encrypted, updatedAt: Date.now() })
110
+ writeCredentials(db, accountId, credentials) {
111
+ const encrypted = encryptString(this.config.encryptionKey, JSON.stringify(credentials));
112
+ db.insert(accountCredentials)
113
+ .values({ accountId, encryptedCredentials: encrypted, updatedAt: Date.now() })
100
114
  .onConflictDoUpdate({
101
- target: oauthTokens.accountId,
102
- set: { encryptedTokens: encrypted, updatedAt: Date.now() },
115
+ target: accountCredentials.accountId,
116
+ set: { encryptedCredentials: encrypted, updatedAt: Date.now() },
103
117
  })
104
118
  .run();
105
119
  return encrypted;
@@ -107,6 +121,18 @@ export class AccountRegistry {
107
121
  saveTokens(accountId, tokens) {
108
122
  return this.writeTokens(this.db, accountId, tokens);
109
123
  }
124
+ writeTokens(db, accountId, tokens) {
125
+ const encrypted = this.writeCredentials(db, accountId, tokens);
126
+ const updatedAt = Date.now();
127
+ db.insert(oauthTokens)
128
+ .values({ accountId, encryptedTokens: encrypted, updatedAt })
129
+ .onConflictDoUpdate({
130
+ target: oauthTokens.accountId,
131
+ set: { encryptedTokens: encrypted, updatedAt },
132
+ })
133
+ .run();
134
+ return encrypted;
135
+ }
110
136
  buildGmailProvider(accountId, email, stored, displayName) {
111
137
  const { clientId, clientSecret } = requireGoogleConfig(this.config);
112
138
  const auth = new OAuth2Client({ clientId, clientSecret });
@@ -120,10 +146,10 @@ export class AccountRegistry {
120
146
  // google-auth-library refreshes access tokens transparently; persist them so
121
147
  // restarts don't need a refresh round-trip (and rotated refresh tokens survive).
122
148
  auth.on('tokens', (fresh) => {
123
- const encryptedTokens = this.saveTokens(accountId, { ...this.loadTokens(accountId), ...fresh });
149
+ const encryptedCredentials = this.saveTokens(accountId, { ...this.loadTokens(accountId), ...fresh });
124
150
  const cached = this.providers.get(accountId);
125
151
  if (cached?.provider === provider)
126
- cached.encryptedTokens = encryptedTokens;
152
+ cached.encryptedCredentials = encryptedCredentials;
127
153
  });
128
154
  return provider;
129
155
  }
@@ -143,7 +169,7 @@ export class AccountRegistry {
143
169
  .where(eq(accounts.id, duplicate.id))
144
170
  .run();
145
171
  });
146
- this.providers.delete(duplicate.id);
172
+ this.evictProvider(duplicate.id);
147
173
  return this.getAccount(duplicate.id);
148
174
  }
149
175
  const id = `acct_${randomBytes(6).toString('hex')}`;
@@ -165,6 +191,73 @@ export class AccountRegistry {
165
191
  });
166
192
  return this.getAccount(id);
167
193
  }
194
+ async testImapCredentials(email, credentials, displayName) {
195
+ const provider = new ImapProvider({
196
+ accountId: 'imap_setup',
197
+ email,
198
+ ...(displayName ? { displayName } : {}),
199
+ credentials,
200
+ store: new SqliteImapStateStore(this.db, 'imap_setup'),
201
+ });
202
+ try {
203
+ await provider.testConnection();
204
+ return await provider.getFolderWarnings();
205
+ }
206
+ finally {
207
+ await provider.close();
208
+ }
209
+ }
210
+ addImapAccount(email, credentials, displayName, memberId, reauthorizeId) {
211
+ if (memberId)
212
+ getMember(this.db, memberId);
213
+ const existingRows = this.db.select().from(accounts).all();
214
+ const duplicate = reauthorizeId
215
+ ? existingRows.find((row) => row.id === reauthorizeId)
216
+ : existingRows.find((row) => row.provider === 'imap' && row.email === email);
217
+ if (duplicate) {
218
+ if (duplicate.provider !== 'imap' || duplicate.email !== email) {
219
+ throw new EmailError('invalid_request', `Account ${duplicate.id} does not match IMAP mailbox ${email}.`);
220
+ }
221
+ this.db.transaction((tx) => {
222
+ this.writeCredentials(tx, duplicate.id, credentials);
223
+ tx.update(accounts)
224
+ .set({ status: 'active', ...(displayName ? { displayName } : {}) })
225
+ .where(eq(accounts.id, duplicate.id))
226
+ .run();
227
+ });
228
+ this.evictProvider(duplicate.id);
229
+ return this.getAccount(duplicate.id);
230
+ }
231
+ const id = `acct_${randomBytes(6).toString('hex')}`;
232
+ this.db.transaction((tx) => {
233
+ assertAccountLimit(tx.select().from(accounts).all().length, getEntitlements(tx));
234
+ tx.insert(accounts)
235
+ .values({
236
+ id,
237
+ provider: 'imap',
238
+ email,
239
+ displayName: displayName ?? null,
240
+ status: 'active',
241
+ createdAt: Date.now(),
242
+ memberId: memberId ?? null,
243
+ })
244
+ .run();
245
+ this.writeCredentials(tx, id, credentials);
246
+ });
247
+ return this.getAccount(id);
248
+ }
249
+ loadImapCredentials(accountId) {
250
+ const account = this.getAccount(accountId);
251
+ if (account.provider !== 'imap')
252
+ throw new EmailError('invalid_request', `Account ${accountId} is not an IMAP account.`);
253
+ const row = this.loadCredentialRow(accountId);
254
+ return JSON.parse(decryptString(this.config.encryptionKey, row.encryptedCredentials));
255
+ }
256
+ saveImapCredentials(accountId, credentials) {
257
+ this.loadImapCredentials(accountId);
258
+ this.writeCredentials(this.db, accountId, credentials);
259
+ this.evictProvider(accountId);
260
+ }
168
261
  /** Assign a mailbox to a member, or make it shared again (memberId = null). */
169
262
  assignAccountMember(accountId, memberId) {
170
263
  this.getAccount(accountId);
@@ -176,7 +269,7 @@ export class AccountRegistry {
176
269
  removeAccount(accountId) {
177
270
  this.getAccount(accountId);
178
271
  this.db.delete(accounts).where(eq(accounts.id, accountId)).run();
179
- this.providers.delete(accountId);
272
+ this.evictProvider(accountId);
180
273
  }
181
274
  markStatus(accountId, status) {
182
275
  this.db.update(accounts).set({ status }).where(eq(accounts.id, accountId)).run();
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/accounts/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/accounts/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,YAAY,EAAoB,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,UAAU,EAAmD,MAAM,gBAAgB,CAAC;AAC7F,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAwB,MAAM,yBAAyB,CAAC;AAEhG,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,WAAW,EAAmB,MAAM,kBAAkB,CAAC;AAC9F,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACnF,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,MAAM,OAAO,eAAe;IAIP;IACA;IAJF,SAAS,GAAG,IAAI,GAAG,EAAqE,CAAC;IAE1G,YACmB,EAAc,EACd,MAAsB;QADtB,OAAE,GAAF,EAAE,CAAY;QACd,WAAM,GAAN,MAAM,CAAgB;IACtC,CAAC;IAEI,aAAa,CAAC,SAAiB;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,QAA2D,CAAC;QAC1G,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACjC,KAAK,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;IACzB,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,EAAE;aACX,MAAM,EAAE;aACR,IAAI,CAAC,QAAQ,CAAC;aACd,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACb,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,QAAQ,EAAE,GAAG,CAAC,QAAoB;YAClC,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5D,MAAM,EAAE,GAAG,CAAC,MAA2B;YACvC,YAAY,EAAE,GAAG,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,kBAAkB;YAC9E,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpD,CAAC,CAAC,CAAC;IACR,CAAC;IAED,UAAU,CAAC,SAAiB;QAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;QACpE,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,UAAU,CAAC,WAAW,EAAE,uBAAuB,SAAS,GAAG,CAAC,CAAC;QACrF,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,0EAA0E;IAC1E,mBAAmB;QACjB,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACrC,IAAI,CAAC;YACH,kBAAkB,CAAC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,CAAC,GAAG,YAAY,UAAU,CAAC;gBAAE,MAAM,GAAG,CAAC;YAC5C,MAAM,SAAS,GACb,QAAQ,CAAC,MAAM,KAAK,CAAC;gBACnB,CAAC,CAAC,gBAAgB,QAAQ,CAAC,CAAC,CAAE,CAAC,KAAK,4BAA4B,GAAG,kBAAkB,QAAQ,CAAC,CAAC,CAAE,CAAC,EAAE,IAAI;gBACxG,CAAC,CAAC,yFAAyF,CAAC;YAChG,MAAM,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,OAAO,IAAI,SAAS,EAAE,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IAED,kFAAkF;IAClF,gBAAgB,CAAC,SAAkB;QACjC,IAAI,SAAS;YAAE,OAAO,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAChC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,UAAU,CAClB,iBAAiB,EACjB,yGAAyG,CAC1G,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnB,MAAM,IAAI,UAAU,CAClB,iBAAiB,EACjB,kEAAkE,GAAG;iBAClE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC;iBAClC,IAAI,CAAC,IAAI,CAAC,EAAE,CAChB,CAAC;QACJ,CAAC;QACD,OAAO,GAAG,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;IACpB,CAAC;IAED,WAAW,CAAC,SAAiB;QAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QACxD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC7C,IAAI,MAAM,EAAE,oBAAoB,KAAK,aAAa,CAAC,oBAAoB;YAAE,OAAO,MAAM,CAAC,QAAQ,CAAC;QAEhG,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAY,CAAC;QACnH,MAAM,QAAQ,GACZ,OAAO,CAAC,QAAQ,KAAK,OAAO;YAC1B,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,EAAE,MAAqB,EAAE,OAAO,CAAC,WAAW,CAAC;YAC/F,CAAC,CAAC,OAAO,CAAC,QAAQ,KAAK,MAAM;gBAC3B,CAAC,CAAC,IAAI,YAAY,CAAC;oBACf,SAAS;oBACT,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACpE,WAAW,EAAE,MAAyB;oBACtC,KAAK,EAAE,IAAI,oBAAoB,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC;iBACpD,CAAC;gBACJ,CAAC,CAAC,SAAS,CAAC;QAClB,IAAI,CAAC,QAAQ;YACX,MAAM,IAAI,UAAU,CAAC,wBAAwB,EAAE,aAAa,OAAO,CAAC,QAAQ,wBAAwB,CAAC,CAAC;QACxG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,oBAAoB,EAAE,aAAa,CAAC,oBAAoB,EAAE,CAAC,CAAC;QACtG,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEO,iBAAiB,CAAC,SAAiB;QACzC,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;QAC/G,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,UAAU,CAAC,cAAc,EAAE,qCAAqC,SAAS,EAAE,CAAC,CAAC;QACjG,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,UAAU,CAAC,SAAiB;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,GAAG,CAAC,oBAAoB,CAAC,CAAgB,CAAC;IACvG,CAAC;IAEO,gBAAgB,CAAC,EAA8B,EAAE,SAAiB,EAAE,WAAoB;QAC9F,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC;QACxF,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC;aAC1B,MAAM,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;aAC7E,kBAAkB,CAAC;YAClB,MAAM,EAAE,kBAAkB,CAAC,SAAS;YACpC,GAAG,EAAE,EAAE,oBAAoB,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE;SAChE,CAAC;aACD,GAAG,EAAE,CAAC;QACT,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,UAAU,CAAC,SAAiB,EAAE,MAAmB;QACvD,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IACtD,CAAC;IAEO,WAAW,CAAC,EAA8B,EAAE,SAAiB,EAAE,MAAmB;QACxF,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC;aACnB,MAAM,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;aAC5D,kBAAkB,CAAC;YAClB,MAAM,EAAE,WAAW,CAAC,SAAS;YAC7B,GAAG,EAAE,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,EAAE;SAC/C,CAAC;aACD,GAAG,EAAE,CAAC;QACT,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,kBAAkB,CACxB,SAAiB,EACjB,KAAa,EACb,MAAmB,EACnB,WAAoB;QAEpB,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,IAAI,YAAY,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC;QAC1D,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,aAAa,CAAC;YACjC,SAAS;YACT,KAAK;YACL,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvC,IAAI;SACL,CAAC,CAAC;QACH,6EAA6E;QAC7E,iFAAiF;QACjF,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,MAAM,oBAAoB,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;YACrG,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC7C,IAAI,MAAM,EAAE,QAAQ,KAAK,QAAQ;gBAAE,MAAM,CAAC,oBAAoB,GAAG,oBAAoB,CAAC;QACxF,CAAC,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,eAAe,CAAC,KAAa,EAAE,MAAmB,EAAE,WAAoB,EAAE,QAAiB;QACzF,4EAA4E;QAC5E,IAAI,QAAQ;YAAE,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC;QACvD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;QACpF,IAAI,SAAS,EAAE,CAAC;YACd,qEAAqE;YACrE,oEAAoE;YACpE,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE;gBACzB,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;gBAC3C,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;qBAChB,GAAG,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;qBAClE,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;qBACpC,GAAG,EAAE,CAAC;YACX,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YACjC,OAAO,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,EAAE,GAAG,QAAQ,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE;YACzB,MAAM,YAAY,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC;YAC7D,kBAAkB,CAAC,YAAY,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC;YACtD,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;iBAChB,MAAM,CAAC;gBACN,EAAE;gBACF,QAAQ,EAAE,OAAO;gBACjB,KAAK;gBACL,WAAW,EAAE,WAAW,IAAI,IAAI;gBAChC,MAAM,EAAE,QAAQ;gBAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,QAAQ,EAAE,QAAQ,IAAI,IAAI;aAC3B,CAAC;iBACD,GAAG,EAAE,CAAC;YACT,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,mBAAmB,CACvB,KAAa,EACb,WAA4B,EAC5B,WAAoB;QAEpB,MAAM,QAAQ,GAAG,IAAI,YAAY,CAAC;YAChC,SAAS,EAAE,YAAY;YACvB,KAAK;YACL,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvC,WAAW;YACX,KAAK,EAAE,IAAI,oBAAoB,CAAC,IAAI,CAAC,EAAE,EAAE,YAAY,CAAC;SACvD,CAAC,CAAC;QACH,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,cAAc,EAAE,CAAC;YAChC,OAAO,MAAM,QAAQ,CAAC,iBAAiB,EAAE,CAAC;QAC5C,CAAC;gBAAS,CAAC;YACT,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;QACzB,CAAC;IACH,CAAC;IAED,cAAc,CACZ,KAAa,EACb,WAA4B,EAC5B,WAAoB,EACpB,QAAiB,EACjB,aAAsB;QAEtB,IAAI,QAAQ;YAAE,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC;QAC3D,MAAM,SAAS,GAAG,aAAa;YAC7B,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,aAAa,CAAC;YACtD,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,IAAI,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;QAC/E,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,SAAS,CAAC,QAAQ,KAAK,MAAM,IAAI,SAAS,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;gBAC/D,MAAM,IAAI,UAAU,CAAC,iBAAiB,EAAE,WAAW,SAAS,CAAC,EAAE,gCAAgC,KAAK,GAAG,CAAC,CAAC;YAC3G,CAAC;YACD,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE;gBACzB,IAAI,CAAC,gBAAgB,CAAC,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;gBACrD,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;qBAChB,GAAG,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;qBAClE,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;qBACpC,GAAG,EAAE,CAAC;YACX,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YACjC,OAAO,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,EAAE,GAAG,QAAQ,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE;YACzB,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC;YACjF,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;iBAChB,MAAM,CAAC;gBACN,EAAE;gBACF,QAAQ,EAAE,MAAM;gBAChB,KAAK;gBACL,WAAW,EAAE,WAAW,IAAI,IAAI;gBAChC,MAAM,EAAE,QAAQ;gBAChB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,QAAQ,EAAE,QAAQ,IAAI,IAAI;aAC3B,CAAC;iBACD,GAAG,EAAE,CAAC;YACT,IAAI,CAAC,gBAAgB,CAAC,EAAE,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC;IAED,mBAAmB,CAAC,SAAiB;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,OAAO,CAAC,QAAQ,KAAK,MAAM;YAC7B,MAAM,IAAI,UAAU,CAAC,iBAAiB,EAAE,WAAW,SAAS,0BAA0B,CAAC,CAAC;QAC1F,MAAM,GAAG,GAAG,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,GAAG,CAAC,oBAAoB,CAAC,CAAoB,CAAC;IAC3G,CAAC;IAED,mBAAmB,CAAC,SAAiB,EAAE,WAA4B;QACjE,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;QACpC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;QACvD,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC;IAED,+EAA+E;IAC/E,mBAAmB,CAAC,SAAiB,EAAE,QAAuB;QAC5D,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAC3B,IAAI,QAAQ;YAAE,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;QACnF,OAAO,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAED,aAAa,CAAC,SAAiB;QAC7B,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAC3B,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;QACjE,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC;IAED,UAAU,CAAC,SAAiB,EAAE,MAAyB;QACrD,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IACnF,CAAC;CACF"}