fluxmail 0.3.0 → 0.4.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/README.md +15 -55
- package/dist/accounts/gmailConnection.d.ts +5 -1
- package/dist/accounts/gmailConnection.d.ts.map +1 -1
- package/dist/accounts/gmailConnection.js +14 -2
- package/dist/accounts/gmailConnection.js.map +1 -1
- package/dist/accounts/googleAuth.js +1 -1
- package/dist/accounts/googleAuth.js.map +1 -1
- package/dist/accounts/microsoftAuth.d.ts +21 -0
- package/dist/accounts/microsoftAuth.d.ts.map +1 -0
- package/dist/accounts/microsoftAuth.js +220 -0
- package/dist/accounts/microsoftAuth.js.map +1 -0
- package/dist/accounts/registry.d.ts +21 -8
- package/dist/accounts/registry.d.ts.map +1 -1
- package/dist/accounts/registry.js +190 -24
- package/dist/accounts/registry.js.map +1 -1
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +857 -647
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +102 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +114 -14
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +7 -1
- package/dist/context.js.map +1 -1
- package/dist/http/admin.d.ts +21 -0
- package/dist/http/admin.d.ts.map +1 -0
- package/dist/http/admin.js +618 -0
- package/dist/http/admin.js.map +1 -0
- package/dist/http/app.d.ts +2 -0
- package/dist/http/app.d.ts.map +1 -1
- package/dist/http/app.js +322 -42
- package/dist/http/app.js.map +1 -1
- package/dist/http/rest.d.ts +28 -0
- package/dist/http/rest.d.ts.map +1 -0
- package/dist/http/rest.js +1130 -0
- package/dist/http/rest.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/licensing/refresher.d.ts +23 -7
- package/dist/licensing/refresher.d.ts.map +1 -1
- package/dist/licensing/refresher.js +93 -37
- package/dist/licensing/refresher.js.map +1 -1
- package/dist/mcp/buildServer.d.ts.map +1 -1
- package/dist/mcp/buildServer.js +1 -1
- package/dist/mcp/buildServer.js.map +1 -1
- package/dist/permissions.d.ts +15 -4
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +61 -12
- package/dist/permissions.js.map +1 -1
- package/dist/service/emailService.d.ts +15 -8
- package/dist/service/emailService.d.ts.map +1 -1
- package/dist/service/emailService.js +42 -17
- package/dist/service/emailService.js.map +1 -1
- package/dist/storage/adminAudit.d.ts +14 -0
- package/dist/storage/adminAudit.d.ts.map +1 -0
- package/dist/storage/adminAudit.js +32 -0
- package/dist/storage/adminAudit.js.map +1 -0
- package/dist/storage/apiKeys.d.ts +25 -7
- package/dist/storage/apiKeys.d.ts.map +1 -1
- package/dist/storage/apiKeys.js +104 -12
- package/dist/storage/apiKeys.js.map +1 -1
- package/dist/storage/db.d.ts +486 -0
- package/dist/storage/db.d.ts.map +1 -1
- package/dist/storage/db.js +171 -8
- package/dist/storage/db.js.map +1 -1
- package/dist/storage/gmailConnectionGrants.d.ts +9 -0
- package/dist/storage/gmailConnectionGrants.d.ts.map +1 -1
- package/dist/storage/gmailConnectionGrants.js +30 -7
- package/dist/storage/gmailConnectionGrants.js.map +1 -1
- package/dist/storage/members.d.ts +7 -4
- package/dist/storage/members.d.ts.map +1 -1
- package/dist/storage/members.js +34 -8
- package/dist/storage/members.js.map +1 -1
- package/dist/storage/restIdempotency.d.ts +28 -0
- package/dist/storage/restIdempotency.d.ts.map +1 -0
- package/dist/storage/restIdempotency.js +47 -0
- package/dist/storage/restIdempotency.js.map +1 -0
- package/package.json +7 -5
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Fluxmail
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Fluxmail is a self-hosted email server for Gmail, Microsoft 365, Outlook.com, and IMAP/SMTP mailboxes. It supports MCP clients and a versioned REST API for scripts and applications.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -8,65 +8,25 @@ Fluxmail requires Node.js 20.20.x, or Node.js 22.22 or later.
|
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npm install -g fluxmail
|
|
11
|
+
fluxmail members add --name "Your name" --email you@example.com
|
|
11
12
|
```
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
Then follow the [quickstart](https://fluxmail.ai/docs/quickstart) to connect a mailbox, choose who can use it, and configure your MCP client.
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
npx fluxmail
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Connect Gmail
|
|
20
|
-
|
|
21
|
-
Create a Google Cloud OAuth client with the Gmail API enabled, then save its credentials:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
fluxmail config set GOOGLE_CLIENT_ID <your-client-id>.apps.googleusercontent.com
|
|
25
|
-
fluxmail config set GOOGLE_CLIENT_SECRET <your-client-secret>
|
|
26
|
-
fluxmail accounts add gmail
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
For a local installation, the last command starts Google's consent flow in your browser.
|
|
30
|
-
|
|
31
|
-
For Docker or a remote server, set `FLUXMAIL_PUBLIC_URL` to the server's public HTTPS address and register `<FLUXMAIL_PUBLIC_URL>/auth/google/callback` as an authorized redirect URI in Google Cloud. Run the command on the server, then open the printed URL in your local browser:
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
docker compose exec fluxmail fluxmail accounts add gmail
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Open the printed link, then select Continue with Google. The link expires after 10 minutes and works once. Fluxmail selects the flow from `FLUXMAIL_PUBLIC_URL`; `--local` and `--hosted` override that selection when needed.
|
|
38
|
-
|
|
39
|
-
## Connect IMAP
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
fluxmail accounts add imap \
|
|
43
|
-
--email you@example.com \
|
|
44
|
-
--imap-host imap.example.com \
|
|
45
|
-
--smtp-host smtp.example.com
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Fluxmail prompts for the password and stores it encrypted. Use `--imap-password-env <name>` for Docker or scripted setup.
|
|
49
|
-
|
|
50
|
-
## Connect an MCP client
|
|
51
|
-
|
|
52
|
-
For example, with Claude Code:
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
claude mcp add fluxmail -- fluxmail stdio
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Or with Codex CLI:
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
codex mcp add fluxmail -- fluxmail stdio
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
To have your MCP client run Fluxmail without a global installation, replace `fluxmail stdio` with `npx -y fluxmail@latest stdio`. Replace `@latest` with an exact version to keep the client on that version.
|
|
16
|
+
## Documentation
|
|
65
17
|
|
|
66
|
-
|
|
18
|
+
- [Overview](https://fluxmail.ai/docs/overview)
|
|
19
|
+
- [Tools](https://fluxmail.ai/docs/tools)
|
|
20
|
+
- [REST API](https://fluxmail.ai/docs/rest-api)
|
|
21
|
+
- [Permissions](https://fluxmail.ai/docs/permissions)
|
|
22
|
+
- [Configuration](https://fluxmail.ai/docs/configuration)
|
|
23
|
+
- [CLI reference](https://fluxmail.ai/docs/cli)
|
|
24
|
+
- [Gmail setup](https://fluxmail.ai/docs/connect-gmail-to-mcp)
|
|
25
|
+
- [Outlook setup](https://fluxmail.ai/docs/connect-outlook-to-mcp)
|
|
26
|
+
- [IMAP setup](https://fluxmail.ai/docs/connect-an-imap-mailbox)
|
|
67
27
|
|
|
68
|
-
|
|
28
|
+
Fluxmail supports stdio for local MCP clients. Its HTTP server provides Streamable HTTP MCP and REST for local, Docker, and remote deployments. Use an exact package version instead of `@latest` when you need a reproducible installation.
|
|
69
29
|
|
|
70
30
|
## License
|
|
71
31
|
|
|
72
|
-
See the [repository](https://github.com/churichard/fluxmail-mcp) for
|
|
32
|
+
Fluxmail is proprietary, source-available software. Production use is limited to your Fluxmail entitlement. See the [repository license](https://github.com/churichard/fluxmail-mcp/blob/main/LICENSE.md) for the full terms.
|
|
@@ -2,7 +2,7 @@ import type { FluxmailConfig } from '../config.js';
|
|
|
2
2
|
import type { FluxmailDb } from '../storage/db.js';
|
|
3
3
|
import { type GmailConnectionIntent } from '../storage/gmailConnectionGrants.js';
|
|
4
4
|
export type GmailConnectionMode = 'local' | 'hosted';
|
|
5
|
-
export declare function validateAccountConnectionFlags(provider: 'gmail' | 'imap', options: {
|
|
5
|
+
export declare function validateAccountConnectionFlags(provider: 'gmail' | 'outlook' | 'imap', options: {
|
|
6
6
|
local?: boolean;
|
|
7
7
|
hosted?: boolean;
|
|
8
8
|
}): void;
|
|
@@ -14,4 +14,8 @@ export declare function prepareHostedGmailConnection(db: FluxmailDb, config: Flu
|
|
|
14
14
|
connectionUrl: string;
|
|
15
15
|
expiresAt: number;
|
|
16
16
|
};
|
|
17
|
+
export declare function prepareHostedOutlookConnection(db: FluxmailDb, config: FluxmailConfig, intent: GmailConnectionIntent): {
|
|
18
|
+
connectionUrl: string;
|
|
19
|
+
expiresAt: number;
|
|
20
|
+
};
|
|
17
21
|
//# sourceMappingURL=gmailConnection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gmailConnection.d.ts","sourceRoot":"","sources":["../../src/accounts/gmailConnection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,
|
|
1
|
+
{"version":3,"file":"gmailConnection.d.ts","sourceRoot":"","sources":["../../src/accounts/gmailConnection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,qCAAqC,CAAC;AAI7C,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,QAAQ,CAAC;AAOrD,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,EACtC,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7C,IAAI,CAIN;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7C,mBAAmB,CAUrB;AAED,wBAAgB,4BAA4B,CAC1C,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,qBAAqB,GAC5B;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAO9C;AAED,wBAAgB,8BAA8B,CAC5C,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,qBAAqB,GAC5B;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAa9C"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { EmailError } from '@fluxmail/core';
|
|
2
|
-
import { createGmailConnectionGrant } from '../storage/gmailConnectionGrants.js';
|
|
2
|
+
import { createGmailConnectionGrant, createOutlookConnectionGrant, } from '../storage/gmailConnectionGrants.js';
|
|
3
3
|
import { requireGoogleConfig } from './googleAuth.js';
|
|
4
|
+
import { requireMicrosoftConfig } from './microsoftAuth.js';
|
|
4
5
|
function isLoopbackPublicUrl(publicUrl) {
|
|
5
6
|
const hostname = new URL(publicUrl).hostname;
|
|
6
7
|
return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]';
|
|
7
8
|
}
|
|
8
9
|
export function validateAccountConnectionFlags(provider, options) {
|
|
9
10
|
if (provider === 'imap' && (options.local || options.hosted)) {
|
|
10
|
-
throw new EmailError('invalid_request', '--local and --hosted are only available for
|
|
11
|
+
throw new EmailError('invalid_request', '--local and --hosted are only available for OAuth accounts.');
|
|
11
12
|
}
|
|
12
13
|
}
|
|
13
14
|
export function selectGmailConnectionMode(config, options) {
|
|
@@ -29,4 +30,15 @@ export function prepareHostedGmailConnection(db, config, intent) {
|
|
|
29
30
|
expiresAt,
|
|
30
31
|
};
|
|
31
32
|
}
|
|
33
|
+
export function prepareHostedOutlookConnection(db, config, intent) {
|
|
34
|
+
const microsoft = requireMicrosoftConfig(config);
|
|
35
|
+
if (!microsoft.clientSecret) {
|
|
36
|
+
throw new EmailError('invalid_request', 'MICROSOFT_CLIENT_SECRET is required for hosted Outlook connections. Add a Web redirect URI and client secret to the Entra app.');
|
|
37
|
+
}
|
|
38
|
+
const { token, expiresAt } = createOutlookConnectionGrant(db, intent);
|
|
39
|
+
return {
|
|
40
|
+
connectionUrl: `${config.publicUrl}/auth/microsoft/connect?token=${encodeURIComponent(token)}`,
|
|
41
|
+
expiresAt,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
32
44
|
//# sourceMappingURL=gmailConnection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gmailConnection.js","sourceRoot":"","sources":["../../src/accounts/gmailConnection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5C,OAAO,
|
|
1
|
+
{"version":3,"file":"gmailConnection.js","sourceRoot":"","sources":["../../src/accounts/gmailConnection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5C,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,GAE7B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAI5D,SAAS,mBAAmB,CAAC,SAAiB;IAC5C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC;IAC7C,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,OAAO,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC5C,QAAsC,EACtC,OAA8C;IAE9C,IAAI,QAAQ,KAAK,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,UAAU,CAAC,iBAAiB,EAAE,6DAA6D,CAAC,CAAC;IACzG,CAAC;AACH,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,MAAsB,EACtB,OAA8C;IAE9C,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACpC,MAAM,IAAI,UAAU,CAAC,iBAAiB,EAAE,+CAA+C,CAAC,CAAC;IAC3F,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAClD,MAAM,IAAI,UAAU,CAAC,iBAAiB,EAAE,kDAAkD,CAAC,CAAC;IAC9F,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,mBAAmB,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC/G,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,OAAO,CAAC;AACd,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,EAAc,EACd,MAAsB,EACtB,MAA6B;IAE7B,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,0BAA0B,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACpE,OAAO;QACL,aAAa,EAAE,GAAG,MAAM,CAAC,SAAS,8BAA8B,kBAAkB,CAAC,KAAK,CAAC,EAAE;QAC3F,SAAS;KACV,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC5C,EAAc,EACd,MAAsB,EACtB,MAA6B;IAE7B,MAAM,SAAS,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IACjD,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC;QAC5B,MAAM,IAAI,UAAU,CAClB,iBAAiB,EACjB,gIAAgI,CACjI,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,4BAA4B,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACtE,OAAO;QACL,aAAa,EAAE,GAAG,MAAM,CAAC,SAAS,iCAAiC,kBAAkB,CAAC,KAAK,CAAC,EAAE;QAC9F,SAAS;KACV,CAAC;AACJ,CAAC"}
|
|
@@ -51,7 +51,7 @@ function oauthListenerError(err, port) {
|
|
|
51
51
|
return err;
|
|
52
52
|
return new Error(`OAuth callback port ${port} is already in use.\n\n` +
|
|
53
53
|
'If Fluxmail is already running with Docker Compose, connect the account inside the container:\n\n' +
|
|
54
|
-
' docker compose exec fluxmail fluxmail accounts add gmail
|
|
54
|
+
' docker compose exec fluxmail fluxmail accounts add gmail --owner <member>\n\n' +
|
|
55
55
|
`Otherwise, stop the process using port ${port} and try again.`, { cause: err });
|
|
56
56
|
}
|
|
57
57
|
function escapeHtml(value) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"googleAuth.js","sourceRoot":"","sources":["../../src/accounts/googleAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAoB,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5C;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,0BAA0B,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;AAEvF,MAAM,UAAU,mBAAmB,CAAC,MAAsB;IACxD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,UAAU,CAClB,iBAAiB,EACjB,kGAAkG;YAChG,iEAAiE,CACpE,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAsB,EAAE,WAAmB;IAC3E,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC/D,OAAO,IAAI,YAAY,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAoB,EAAE,KAAa;IAC9D,OAAO,MAAM,CAAC,eAAe,CAAC;QAC5B,WAAW,EAAE,SAAS;QACtB,MAAM,EAAE,SAAS;QACjB,KAAK,EAAE,YAAY;QACnB,KAAK;KACN,CAAC,CAAC;AACL,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAoB,EACpB,MAAmB;IAEnB,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC;IAChC,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,UAAU,CAAC,sBAAsB,EAAE,mCAAmC,CAAC,CAAC;IAChG,IAAI,CAAC,MAAM,CAAC,SAAS;QAAE,MAAM,IAAI,UAAU,CAAC,sBAAsB,EAAE,sCAAsC,CAAC,CAAC;IAC5G,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IACnF,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACnC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,UAAU,CAAC,sBAAsB,EAAE,+BAA+B,CAAC,CAAC;IAC3F,IAAI,CAAC,MAAM,CAAC,KAAK;QAAE,MAAM,IAAI,UAAU,CAAC,sBAAsB,EAAE,oCAAoC,CAAC,CAAC;IACtG,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAC3B,MAAM,IAAI,UAAU,CAAC,sBAAsB,EAAE,iDAAiD,CAAC,CAAC;IAClG,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACvF,CAAC;AAQD,SAAS,kBAAkB,CAAC,GAAU,EAAE,IAAY;IAClD,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;IACjD,IAAI,IAAI,KAAK,YAAY;QAAE,OAAO,GAAG,CAAC;IAEtC,OAAO,IAAI,KAAK,CACd,uBAAuB,IAAI,yBAAyB;QAClD,mGAAmG;QACnG,
|
|
1
|
+
{"version":3,"file":"googleAuth.js","sourceRoot":"","sources":["../../src/accounts/googleAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { FluxmailConfig } from '../config.js';
|
|
2
|
+
export declare const MICROSOFT_SCOPES: string[];
|
|
3
|
+
export interface MicrosoftCredentials {
|
|
4
|
+
accessToken: string;
|
|
5
|
+
refreshToken: string;
|
|
6
|
+
expiresAt: number;
|
|
7
|
+
scope?: string;
|
|
8
|
+
/** Hosted callbacks use a confidential client; loopback callbacks use PKCE only. */
|
|
9
|
+
clientAuth?: 'public' | 'confidential';
|
|
10
|
+
}
|
|
11
|
+
export interface MicrosoftOAuthResult {
|
|
12
|
+
email: string;
|
|
13
|
+
displayName?: string;
|
|
14
|
+
credentials: MicrosoftCredentials;
|
|
15
|
+
}
|
|
16
|
+
export declare function requireMicrosoftConfig(config: FluxmailConfig): NonNullable<FluxmailConfig['microsoft']>;
|
|
17
|
+
export declare function buildMicrosoftAuthUrl(config: FluxmailConfig, redirectUri: string, state: string, verifier: string): string;
|
|
18
|
+
export declare function refreshMicrosoftCredentials(config: FluxmailConfig, credentials: MicrosoftCredentials): Promise<MicrosoftCredentials>;
|
|
19
|
+
export declare function exchangeMicrosoftCode(config: FluxmailConfig, code: string, redirectUri: string, verifier: string, clientAuth?: 'public' | 'confidential'): Promise<MicrosoftOAuthResult>;
|
|
20
|
+
export declare function runMicrosoftLoopbackFlow<T = MicrosoftOAuthResult>(config: FluxmailConfig, onAuthUrl: (url: string) => void, onAuthorized?: (result: MicrosoftOAuthResult) => T | Promise<T>): Promise<T>;
|
|
21
|
+
//# sourceMappingURL=microsoftAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"microsoftAuth.d.ts","sourceRoot":"","sources":["../../src/accounts/microsoftAuth.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,eAAO,MAAM,gBAAgB,UAQ5B,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,UAAU,CAAC,EAAE,QAAQ,GAAG,cAAc,CAAC;CACxC;AAWD,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,oBAAoB,CAAC;CACnC;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,cAAc,GAAG,WAAW,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAQvG;AAWD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,MAAM,CAeR;AAoDD,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,cAAc,EACtB,WAAW,EAAE,oBAAoB,GAChC,OAAO,CAAC,oBAAoB,CAAC,CAa/B;AA+CD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,UAAU,GAAE,QAAQ,GAAG,cAAyB,GAC/C,OAAO,CAAC,oBAAoB,CAAC,CAgB/B;AAkCD,wBAAsB,wBAAwB,CAAC,CAAC,GAAG,oBAAoB,EACrE,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAChC,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAC9D,OAAO,CAAC,CAAC,CAAC,CA2DZ"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
2
|
+
import { createServer } from 'node:http';
|
|
3
|
+
import { EmailError } from '@fluxmail/core';
|
|
4
|
+
export const MICROSOFT_SCOPES = [
|
|
5
|
+
'openid',
|
|
6
|
+
'profile',
|
|
7
|
+
'email',
|
|
8
|
+
'offline_access',
|
|
9
|
+
'User.Read',
|
|
10
|
+
'Mail.ReadWrite',
|
|
11
|
+
'Mail.Send',
|
|
12
|
+
];
|
|
13
|
+
export function requireMicrosoftConfig(config) {
|
|
14
|
+
if (!config.microsoft) {
|
|
15
|
+
throw new EmailError('invalid_request', 'MICROSOFT_CLIENT_ID is not set. Register an app in Microsoft Entra, then set its application client ID. See https://fluxmail.ai/docs/connect-outlook-to-mcp.');
|
|
16
|
+
}
|
|
17
|
+
return config.microsoft;
|
|
18
|
+
}
|
|
19
|
+
function tenantEndpoint(config, path) {
|
|
20
|
+
const { tenantId } = requireMicrosoftConfig(config);
|
|
21
|
+
return `https://login.microsoftonline.com/${encodeURIComponent(tenantId)}/oauth2/v2.0/${path}`;
|
|
22
|
+
}
|
|
23
|
+
function codeChallenge(verifier) {
|
|
24
|
+
return createHash('sha256').update(verifier).digest('base64url');
|
|
25
|
+
}
|
|
26
|
+
export function buildMicrosoftAuthUrl(config, redirectUri, state, verifier) {
|
|
27
|
+
const { clientId } = requireMicrosoftConfig(config);
|
|
28
|
+
const url = new URL(tenantEndpoint(config, 'authorize'));
|
|
29
|
+
url.search = new URLSearchParams({
|
|
30
|
+
client_id: clientId,
|
|
31
|
+
response_type: 'code',
|
|
32
|
+
redirect_uri: redirectUri,
|
|
33
|
+
response_mode: 'query',
|
|
34
|
+
scope: MICROSOFT_SCOPES.join(' '),
|
|
35
|
+
state,
|
|
36
|
+
code_challenge: codeChallenge(verifier),
|
|
37
|
+
code_challenge_method: 'S256',
|
|
38
|
+
prompt: 'select_account',
|
|
39
|
+
}).toString();
|
|
40
|
+
return url.toString();
|
|
41
|
+
}
|
|
42
|
+
async function tokenRequest(config, params, clientAuth) {
|
|
43
|
+
const microsoft = requireMicrosoftConfig(config);
|
|
44
|
+
if (clientAuth === 'confidential' && !microsoft.clientSecret) {
|
|
45
|
+
throw new EmailError('invalid_request', 'MICROSOFT_CLIENT_SECRET is required for hosted Outlook connections.');
|
|
46
|
+
}
|
|
47
|
+
const body = new URLSearchParams({
|
|
48
|
+
client_id: microsoft.clientId,
|
|
49
|
+
...params,
|
|
50
|
+
...(clientAuth === 'confidential' ? { client_secret: microsoft.clientSecret } : {}),
|
|
51
|
+
});
|
|
52
|
+
const response = await fetch(tenantEndpoint(config, 'token'), {
|
|
53
|
+
method: 'POST',
|
|
54
|
+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
|
|
55
|
+
body,
|
|
56
|
+
});
|
|
57
|
+
const payload = (await response.json());
|
|
58
|
+
if (!response.ok || payload.error) {
|
|
59
|
+
const detail = payload.error_description ?? payload.error ?? `HTTP ${response.status}`;
|
|
60
|
+
const code = /invalid_grant/i.test(payload.error ?? '') ? 'auth_expired' : 'provider_unavailable';
|
|
61
|
+
throw new EmailError(code, `Microsoft OAuth failed: ${detail}`);
|
|
62
|
+
}
|
|
63
|
+
return payload;
|
|
64
|
+
}
|
|
65
|
+
function credentialsFromToken(payload, clientAuth, previousRefreshToken) {
|
|
66
|
+
if (!payload.access_token)
|
|
67
|
+
throw new EmailError('provider_unavailable', 'Microsoft did not return an access token');
|
|
68
|
+
const refreshToken = payload.refresh_token ?? previousRefreshToken;
|
|
69
|
+
if (!refreshToken) {
|
|
70
|
+
throw new EmailError('invalid_request', 'Microsoft did not return a refresh token. Confirm offline_access consent and try again.');
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
accessToken: payload.access_token,
|
|
74
|
+
refreshToken,
|
|
75
|
+
expiresAt: Date.now() + Math.max(payload.expires_in ?? 3_600, 60) * 1_000,
|
|
76
|
+
clientAuth,
|
|
77
|
+
...(payload.scope ? { scope: payload.scope } : {}),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export async function refreshMicrosoftCredentials(config, credentials) {
|
|
81
|
+
const clientAuth = credentials.clientAuth ?? (requireMicrosoftConfig(config).clientSecret ? 'confidential' : 'public');
|
|
82
|
+
const payload = await tokenRequest(config, {
|
|
83
|
+
grant_type: 'refresh_token',
|
|
84
|
+
refresh_token: credentials.refreshToken,
|
|
85
|
+
scope: MICROSOFT_SCOPES.join(' '),
|
|
86
|
+
}, clientAuth);
|
|
87
|
+
return credentialsFromToken(payload, clientAuth, credentials.refreshToken);
|
|
88
|
+
}
|
|
89
|
+
async function microsoftIdentity(accessToken) {
|
|
90
|
+
const response = await fetch('https://graph.microsoft.com/v1.0/me?$select=mail,userPrincipalName,displayName', {
|
|
91
|
+
headers: { authorization: `Bearer ${accessToken}`, accept: 'application/json' },
|
|
92
|
+
});
|
|
93
|
+
const payload = (await response.json());
|
|
94
|
+
if (!response.ok) {
|
|
95
|
+
throw new EmailError(response.status === 401 ? 'auth_expired' : 'provider_unavailable', `Microsoft Graph could not read the signed-in account: ${payload.error?.message ?? `HTTP ${response.status}`}`);
|
|
96
|
+
}
|
|
97
|
+
const email = payload.mail?.trim() || payload.userPrincipalName?.trim();
|
|
98
|
+
if (!email)
|
|
99
|
+
throw new EmailError('provider_unavailable', 'Microsoft Graph returned no mailbox address');
|
|
100
|
+
const displayName = payload.displayName?.trim();
|
|
101
|
+
return { email, ...(displayName ? { displayName } : {}) };
|
|
102
|
+
}
|
|
103
|
+
async function verifyMicrosoftMailbox(accessToken) {
|
|
104
|
+
const response = await fetch('https://graph.microsoft.com/v1.0/me/mailFolders/inbox?$select=id', {
|
|
105
|
+
headers: { authorization: `Bearer ${accessToken}`, accept: 'application/json' },
|
|
106
|
+
});
|
|
107
|
+
let payload = {};
|
|
108
|
+
try {
|
|
109
|
+
payload = (await response.json());
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Microsoft Graph can return an empty or non-JSON gateway response.
|
|
113
|
+
}
|
|
114
|
+
if (!response.ok) {
|
|
115
|
+
const code = response.status === 401 ? 'auth_expired' : response.status === 403 ? 'permission_denied' : 'provider_unavailable';
|
|
116
|
+
throw new EmailError(code, `Microsoft Graph could not access this account's mailbox: ${payload.error?.message ?? `HTTP ${response.status}`}`);
|
|
117
|
+
}
|
|
118
|
+
if (!payload.id) {
|
|
119
|
+
throw new EmailError('provider_unavailable', "Microsoft Graph could not access this account's mailbox");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export async function exchangeMicrosoftCode(config, code, redirectUri, verifier, clientAuth = 'public') {
|
|
123
|
+
const payload = await tokenRequest(config, {
|
|
124
|
+
grant_type: 'authorization_code',
|
|
125
|
+
code,
|
|
126
|
+
redirect_uri: redirectUri,
|
|
127
|
+
code_verifier: verifier,
|
|
128
|
+
scope: MICROSOFT_SCOPES.join(' '),
|
|
129
|
+
}, clientAuth);
|
|
130
|
+
const credentials = credentialsFromToken(payload, clientAuth);
|
|
131
|
+
const identity = await microsoftIdentity(credentials.accessToken);
|
|
132
|
+
await verifyMicrosoftMailbox(credentials.accessToken);
|
|
133
|
+
return { ...identity, credentials };
|
|
134
|
+
}
|
|
135
|
+
function escapeHtml(value) {
|
|
136
|
+
return value.replace(/[&<>"']/g, (char) => {
|
|
137
|
+
const entities = {
|
|
138
|
+
'&': '&',
|
|
139
|
+
'<': '<',
|
|
140
|
+
'>': '>',
|
|
141
|
+
'"': '"',
|
|
142
|
+
"'": ''',
|
|
143
|
+
};
|
|
144
|
+
return entities[char];
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
function callbackPage(title, message) {
|
|
148
|
+
return ('<html><body style="font-family: sans-serif">' +
|
|
149
|
+
`<h2>${escapeHtml(title)}</h2><p>${escapeHtml(message)}</p>` +
|
|
150
|
+
'<p>You can close this tab and return to the terminal.</p></body></html>');
|
|
151
|
+
}
|
|
152
|
+
function listenerError(error, port) {
|
|
153
|
+
if (error.code !== 'EADDRINUSE')
|
|
154
|
+
return error;
|
|
155
|
+
return new Error(`OAuth callback port ${port} is already in use.\n\n` +
|
|
156
|
+
'If Fluxmail is running with Docker Compose, connect the account inside the container:\n\n' +
|
|
157
|
+
' docker compose exec fluxmail fluxmail accounts add outlook --owner <member>\n\n' +
|
|
158
|
+
`Otherwise, stop the process using port ${port} and try again.`, { cause: error });
|
|
159
|
+
}
|
|
160
|
+
export async function runMicrosoftLoopbackFlow(config, onAuthUrl, onAuthorized) {
|
|
161
|
+
requireMicrosoftConfig(config);
|
|
162
|
+
const redirectUri = `http://localhost:${config.oauthPort}/oauth/microsoft/callback`;
|
|
163
|
+
const state = randomBytes(16).toString('hex');
|
|
164
|
+
const verifier = randomBytes(48).toString('base64url');
|
|
165
|
+
return new Promise((resolve, reject) => {
|
|
166
|
+
const server = createServer(async (request, response) => {
|
|
167
|
+
const finish = (settle) => {
|
|
168
|
+
response.once('close', () => {
|
|
169
|
+
server.close();
|
|
170
|
+
server.closeAllConnections();
|
|
171
|
+
settle();
|
|
172
|
+
});
|
|
173
|
+
};
|
|
174
|
+
try {
|
|
175
|
+
const url = new URL(request.url ?? '/', redirectUri);
|
|
176
|
+
if (url.pathname !== '/oauth/microsoft/callback') {
|
|
177
|
+
response.writeHead(404).end('Not found');
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (url.searchParams.get('state') !== state) {
|
|
181
|
+
response.writeHead(400).end('State mismatch. Restart the flow.');
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const oauthError = url.searchParams.get('error');
|
|
185
|
+
if (oauthError) {
|
|
186
|
+
const description = url.searchParams.get('error_description') ?? oauthError;
|
|
187
|
+
finish(() => reject(new EmailError('invalid_request', `Microsoft OAuth error: ${description}`)));
|
|
188
|
+
response.writeHead(400).end(`Microsoft returned an error: ${description}. You can close this tab.`);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const code = url.searchParams.get('code');
|
|
192
|
+
if (!code) {
|
|
193
|
+
response.writeHead(400).end('Missing code parameter.');
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const result = await exchangeMicrosoftCode(config, code, redirectUri, verifier);
|
|
197
|
+
const accepted = onAuthorized ? await onAuthorized(result) : result;
|
|
198
|
+
finish(() => resolve(accepted));
|
|
199
|
+
response
|
|
200
|
+
.writeHead(200, { 'content-type': 'text/html; charset=utf-8' })
|
|
201
|
+
.end(callbackPage(`${result.email} is connected to Fluxmail`, 'The account is ready to use.'));
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
finish(() => reject(error));
|
|
205
|
+
const expected = error instanceof EmailError;
|
|
206
|
+
const message = expected
|
|
207
|
+
? error.message
|
|
208
|
+
: 'Fluxmail could not finish connecting this account. Check the terminal for details.';
|
|
209
|
+
response
|
|
210
|
+
.writeHead(expected ? 400 : 500, { 'content-type': 'text/html; charset=utf-8' })
|
|
211
|
+
.end(callbackPage('Fluxmail could not connect this account', message));
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
server.on('error', (error) => reject(listenerError(error, config.oauthPort)));
|
|
215
|
+
server.listen(config.oauthPort, config.oauthHost, () => {
|
|
216
|
+
onAuthUrl(buildMicrosoftAuthUrl(config, redirectUri, state, verifier));
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=microsoftAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"microsoftAuth.js","sourceRoot":"","sources":["../../src/accounts/microsoftAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { type Credentials } from 'google-auth-library';
|
|
2
|
-
import { type Account, type EmailProvider } from '@fluxmail/core';
|
|
3
|
-
import { type ImapCredentials } from '@fluxmail/provider-imap';
|
|
2
|
+
import { type Account, type AccountSharingMode, type EmailProvider } from '@fluxmail/core';
|
|
3
|
+
import { type FolderWarning, type ImapCredentials } from '@fluxmail/provider-imap';
|
|
4
4
|
import type { FluxmailConfig } from '../config.js';
|
|
5
5
|
import { type FluxmailDb } from '../storage/db.js';
|
|
6
|
+
import { type MicrosoftCredentials } from './microsoftAuth.js';
|
|
7
|
+
export interface AccountAccessInput {
|
|
8
|
+
sharingMode: AccountSharingMode;
|
|
9
|
+
sharedMemberIds?: readonly string[];
|
|
10
|
+
}
|
|
6
11
|
export declare class AccountRegistry {
|
|
7
12
|
private readonly db;
|
|
8
13
|
private readonly config;
|
|
@@ -11,6 +16,10 @@ export declare class AccountRegistry {
|
|
|
11
16
|
private evictProvider;
|
|
12
17
|
listAccounts(): Account[];
|
|
13
18
|
getAccount(accountId: string): Account;
|
|
19
|
+
/** Resolve an account by canonical id or mailbox address. Email matching is case-insensitive. */
|
|
20
|
+
findAccount(ref: string): Account;
|
|
21
|
+
private normalizeAccess;
|
|
22
|
+
private writeAccess;
|
|
14
23
|
/** Fail before OAuth when a new account would exceed the current plan. */
|
|
15
24
|
assertCanAddAccount(): void;
|
|
16
25
|
/** Resolve an account id, defaulting to the sole account when only one exists. */
|
|
@@ -22,15 +31,19 @@ export declare class AccountRegistry {
|
|
|
22
31
|
private saveTokens;
|
|
23
32
|
private writeTokens;
|
|
24
33
|
private buildGmailProvider;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
34
|
+
private buildOutlookProvider;
|
|
35
|
+
addGmailAccount(email: string, tokens: Credentials, displayName?: string, memberId?: string, access?: AccountAccessInput): Account;
|
|
36
|
+
addOutlookAccount(email: string, credentials: MicrosoftCredentials, displayName?: string, memberId?: string, reauthorizeId?: string, access?: AccountAccessInput): Account;
|
|
37
|
+
testImapCredentials(email: string, credentials: ImapCredentials, displayName?: string, timeoutMs?: number): Promise<FolderWarning[]>;
|
|
38
|
+
testImapFolderOverrides(email: string, credentials: ImapCredentials, displayName?: string, timeoutMs?: number): Promise<FolderWarning[]>;
|
|
39
|
+
private testImapSetup;
|
|
40
|
+
addImapAccount(email: string, credentials: ImapCredentials, displayName?: string, memberId?: string, reauthorizeId?: string, access?: AccountAccessInput): Account;
|
|
30
41
|
loadImapCredentials(accountId: string): ImapCredentials;
|
|
31
42
|
saveImapCredentials(accountId: string, credentials: ImapCredentials): void;
|
|
32
|
-
/**
|
|
43
|
+
/** Deprecated storage alias for assignAccountOwner. */
|
|
33
44
|
assignAccountMember(accountId: string, memberId: string | null): Account;
|
|
45
|
+
assignAccountOwner(accountId: string, memberId: string): Account;
|
|
46
|
+
setAccountAccess(accountId: string, access: AccountAccessInput): Account;
|
|
34
47
|
removeAccount(accountId: string): void;
|
|
35
48
|
markStatus(accountId: string, status: Account['status']): void;
|
|
36
49
|
}
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/accounts/registry.ts"],"names":[],"mappings":"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"}
|