mcp-twake-mail 0.1.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/LICENSE +663 -0
- package/README.md +332 -0
- package/build/auth/index.d.ts +3 -0
- package/build/auth/index.js +4 -0
- package/build/auth/index.js.map +1 -0
- package/build/auth/oidc-flow.d.ts +47 -0
- package/build/auth/oidc-flow.js +146 -0
- package/build/auth/oidc-flow.js.map +1 -0
- package/build/auth/token-refresh.d.ts +56 -0
- package/build/auth/token-refresh.js +132 -0
- package/build/auth/token-refresh.js.map +1 -0
- package/build/auth/token-store.d.ts +33 -0
- package/build/auth/token-store.js +63 -0
- package/build/auth/token-store.js.map +1 -0
- package/build/cli/commands/auth.d.ts +5 -0
- package/build/cli/commands/auth.js +49 -0
- package/build/cli/commands/auth.js.map +1 -0
- package/build/cli/commands/check.d.ts +4 -0
- package/build/cli/commands/check.js +125 -0
- package/build/cli/commands/check.js.map +1 -0
- package/build/cli/commands/setup.d.ts +4 -0
- package/build/cli/commands/setup.js +172 -0
- package/build/cli/commands/setup.js.map +1 -0
- package/build/cli/index.d.ts +15 -0
- package/build/cli/index.js +56 -0
- package/build/cli/index.js.map +1 -0
- package/build/cli/prompts/setup-wizard.d.ts +38 -0
- package/build/cli/prompts/setup-wizard.js +121 -0
- package/build/cli/prompts/setup-wizard.js.map +1 -0
- package/build/config/__tests__/logger.test.d.ts +1 -0
- package/build/config/__tests__/logger.test.js +28 -0
- package/build/config/__tests__/logger.test.js.map +1 -0
- package/build/config/__tests__/schema.test.d.ts +1 -0
- package/build/config/__tests__/schema.test.js +101 -0
- package/build/config/__tests__/schema.test.js.map +1 -0
- package/build/config/logger.d.ts +3 -0
- package/build/config/logger.js +9 -0
- package/build/config/logger.js.map +1 -0
- package/build/config/schema.d.ts +28 -0
- package/build/config/schema.js +81 -0
- package/build/config/schema.js.map +1 -0
- package/build/errors.d.ts +34 -0
- package/build/errors.js +154 -0
- package/build/errors.js.map +1 -0
- package/build/errors.test.d.ts +1 -0
- package/build/errors.test.js +234 -0
- package/build/errors.test.js.map +1 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +12 -0
- package/build/index.js.map +1 -0
- package/build/jmap/client.d.ts +96 -0
- package/build/jmap/client.js +267 -0
- package/build/jmap/client.js.map +1 -0
- package/build/mcp/server.d.ts +24 -0
- package/build/mcp/server.js +68 -0
- package/build/mcp/server.js.map +1 -0
- package/build/mcp/tools/attachment.d.ts +30 -0
- package/build/mcp/tools/attachment.js +246 -0
- package/build/mcp/tools/attachment.js.map +1 -0
- package/build/mcp/tools/attachment.test.d.ts +1 -0
- package/build/mcp/tools/attachment.test.js +457 -0
- package/build/mcp/tools/attachment.test.js.map +1 -0
- package/build/mcp/tools/email-operations.d.ts +10 -0
- package/build/mcp/tools/email-operations.js +828 -0
- package/build/mcp/tools/email-operations.js.map +1 -0
- package/build/mcp/tools/email-operations.test.d.ts +1 -0
- package/build/mcp/tools/email-operations.test.js +453 -0
- package/build/mcp/tools/email-operations.test.js.map +1 -0
- package/build/mcp/tools/email-sending.d.ts +10 -0
- package/build/mcp/tools/email-sending.js +682 -0
- package/build/mcp/tools/email-sending.js.map +1 -0
- package/build/mcp/tools/email.d.ts +10 -0
- package/build/mcp/tools/email.js +365 -0
- package/build/mcp/tools/email.js.map +1 -0
- package/build/mcp/tools/email.test.d.ts +1 -0
- package/build/mcp/tools/email.test.js +332 -0
- package/build/mcp/tools/email.test.js.map +1 -0
- package/build/mcp/tools/index.d.ts +14 -0
- package/build/mcp/tools/index.js +29 -0
- package/build/mcp/tools/index.js.map +1 -0
- package/build/mcp/tools/mailbox.d.ts +10 -0
- package/build/mcp/tools/mailbox.js +195 -0
- package/build/mcp/tools/mailbox.js.map +1 -0
- package/build/mcp/tools/mailbox.test.d.ts +1 -0
- package/build/mcp/tools/mailbox.test.js +231 -0
- package/build/mcp/tools/mailbox.test.js.map +1 -0
- package/build/mcp/tools/thread.d.ts +10 -0
- package/build/mcp/tools/thread.js +282 -0
- package/build/mcp/tools/thread.js.map +1 -0
- package/build/mcp/tools/thread.test.d.ts +1 -0
- package/build/mcp/tools/thread.test.js +384 -0
- package/build/mcp/tools/thread.test.js.map +1 -0
- package/build/transformers/__tests__/email.test.d.ts +1 -0
- package/build/transformers/__tests__/email.test.js +438 -0
- package/build/transformers/__tests__/email.test.js.map +1 -0
- package/build/transformers/__tests__/mailbox.test.d.ts +1 -0
- package/build/transformers/__tests__/mailbox.test.js +222 -0
- package/build/transformers/__tests__/mailbox.test.js.map +1 -0
- package/build/transformers/email.d.ts +76 -0
- package/build/transformers/email.js +138 -0
- package/build/transformers/email.js.map +1 -0
- package/build/transformers/index.d.ts +5 -0
- package/build/transformers/index.js +6 -0
- package/build/transformers/index.js.map +1 -0
- package/build/transformers/mailbox.d.ts +43 -0
- package/build/transformers/mailbox.js +70 -0
- package/build/transformers/mailbox.js.map +1 -0
- package/build/types/dto.d.ts +91 -0
- package/build/types/dto.js +9 -0
- package/build/types/dto.js.map +1 -0
- package/build/types/jmap.d.ts +110 -0
- package/build/types/jmap.js +5 -0
- package/build/types/jmap.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI entry point using Commander.js.
|
|
3
|
+
* Routes between MCP server (default) and interactive commands.
|
|
4
|
+
*/
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import { startServer } from '../mcp/server.js';
|
|
7
|
+
// Read version from package.json at runtime to stay in sync
|
|
8
|
+
const VERSION = '0.1.0'; // Match package.json
|
|
9
|
+
/**
|
|
10
|
+
* Create and configure the CLI program.
|
|
11
|
+
* @returns Configured Commander program
|
|
12
|
+
*/
|
|
13
|
+
export function createCLI() {
|
|
14
|
+
const program = new Command();
|
|
15
|
+
program
|
|
16
|
+
.name('mcp-twake-mail')
|
|
17
|
+
.description('MCP server for JMAP mail operations via Twake Mail')
|
|
18
|
+
.version(VERSION);
|
|
19
|
+
// Default action: start MCP server (no subcommand)
|
|
20
|
+
program
|
|
21
|
+
.action(async () => {
|
|
22
|
+
await startServer();
|
|
23
|
+
});
|
|
24
|
+
// Setup wizard command
|
|
25
|
+
program
|
|
26
|
+
.command('setup')
|
|
27
|
+
.description('Interactive configuration wizard')
|
|
28
|
+
.action(async () => {
|
|
29
|
+
const { runSetup } = await import('./commands/setup.js');
|
|
30
|
+
await runSetup();
|
|
31
|
+
});
|
|
32
|
+
program
|
|
33
|
+
.command('auth')
|
|
34
|
+
.description('Re-run OIDC authentication')
|
|
35
|
+
.action(async () => {
|
|
36
|
+
const { runAuth } = await import('./commands/auth.js');
|
|
37
|
+
await runAuth();
|
|
38
|
+
});
|
|
39
|
+
program
|
|
40
|
+
.command('check')
|
|
41
|
+
.description('Verify configuration and test connection')
|
|
42
|
+
.action(async () => {
|
|
43
|
+
const { runCheck } = await import('./commands/check.js');
|
|
44
|
+
await runCheck();
|
|
45
|
+
});
|
|
46
|
+
return program;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Run the CLI program.
|
|
50
|
+
* Uses parseAsync for proper async action handling.
|
|
51
|
+
*/
|
|
52
|
+
export async function runCLI() {
|
|
53
|
+
const program = createCLI();
|
|
54
|
+
await program.parseAsync(process.argv);
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,4DAA4D;AAC5D,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,qBAAqB;AAE9C;;;GAGG;AACH,MAAM,UAAU,SAAS;IACvB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,gBAAgB,CAAC;SACtB,WAAW,CAAC,oDAAoD,CAAC;SACjE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,mDAAmD;IACnD,OAAO;SACJ,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,WAAW,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;IAEL,uBAAuB;IACvB,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,kCAAkC,CAAC;SAC/C,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;QACzD,MAAM,QAAQ,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,4BAA4B,CAAC;SACzC,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACvD,MAAM,OAAO,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,0CAA0C,CAAC;SACvD,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;QACzD,MAAM,QAAQ,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IAEL,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM;IAC1B,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAC5B,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Auth method choices for the wizard */
|
|
2
|
+
export type AuthMethod = 'oidc' | 'basic' | 'bearer';
|
|
3
|
+
/**
|
|
4
|
+
* Prompt for JMAP session URL with validation.
|
|
5
|
+
*/
|
|
6
|
+
export declare function promptJmapUrl(): Promise<string>;
|
|
7
|
+
/**
|
|
8
|
+
* Prompt for authentication method selection.
|
|
9
|
+
*/
|
|
10
|
+
export declare function promptAuthMethod(): Promise<AuthMethod>;
|
|
11
|
+
/**
|
|
12
|
+
* Prompt for Basic auth credentials.
|
|
13
|
+
*/
|
|
14
|
+
export declare function promptBasicAuth(): Promise<{
|
|
15
|
+
username: string;
|
|
16
|
+
password: string;
|
|
17
|
+
}>;
|
|
18
|
+
/**
|
|
19
|
+
* Prompt for Bearer token.
|
|
20
|
+
*/
|
|
21
|
+
export declare function promptBearerToken(): Promise<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Prompt for OIDC configuration.
|
|
24
|
+
*/
|
|
25
|
+
export declare function promptOidcAuth(): Promise<{
|
|
26
|
+
issuer: string;
|
|
27
|
+
clientId: string;
|
|
28
|
+
scope: string;
|
|
29
|
+
redirectUri: string;
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* Prompt to confirm writing config to file.
|
|
33
|
+
*/
|
|
34
|
+
export declare function promptWriteConfig(): Promise<boolean>;
|
|
35
|
+
/**
|
|
36
|
+
* Prompt for custom server name in Claude config.
|
|
37
|
+
*/
|
|
38
|
+
export declare function promptServerName(): Promise<string>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive prompts for setup wizard.
|
|
3
|
+
* Uses @inquirer/prompts for modern, TypeScript-first prompts.
|
|
4
|
+
*/
|
|
5
|
+
import { input, select, password, confirm } from '@inquirer/prompts';
|
|
6
|
+
/**
|
|
7
|
+
* Prompt for JMAP session URL with validation.
|
|
8
|
+
*/
|
|
9
|
+
export async function promptJmapUrl() {
|
|
10
|
+
return input({
|
|
11
|
+
message: 'JMAP Session URL:',
|
|
12
|
+
default: 'https://jmap.linagora.com/jmap/session',
|
|
13
|
+
validate: (value) => {
|
|
14
|
+
try {
|
|
15
|
+
new URL(value);
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return 'Please enter a valid URL';
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Prompt for authentication method selection.
|
|
26
|
+
*/
|
|
27
|
+
export async function promptAuthMethod() {
|
|
28
|
+
return select({
|
|
29
|
+
message: 'Authentication method:',
|
|
30
|
+
choices: [
|
|
31
|
+
{ value: 'oidc', name: 'OIDC (recommended for Twake Mail)' },
|
|
32
|
+
{ value: 'basic', name: 'Basic Auth (username/password)' },
|
|
33
|
+
{ value: 'bearer', name: 'Bearer Token' },
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Prompt for Basic auth credentials.
|
|
39
|
+
*/
|
|
40
|
+
export async function promptBasicAuth() {
|
|
41
|
+
const username = await input({
|
|
42
|
+
message: 'Username (email):',
|
|
43
|
+
validate: (value) => value.length > 0 || 'Username is required',
|
|
44
|
+
});
|
|
45
|
+
const pwd = await password({
|
|
46
|
+
message: 'Password:',
|
|
47
|
+
mask: '*',
|
|
48
|
+
});
|
|
49
|
+
return { username, password: pwd };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Prompt for Bearer token.
|
|
53
|
+
*/
|
|
54
|
+
export async function promptBearerToken() {
|
|
55
|
+
return password({
|
|
56
|
+
message: 'Bearer token:',
|
|
57
|
+
mask: '*',
|
|
58
|
+
validate: (value) => value.length > 0 || 'Token is required',
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Prompt for OIDC configuration.
|
|
63
|
+
*/
|
|
64
|
+
export async function promptOidcAuth() {
|
|
65
|
+
const issuer = await input({
|
|
66
|
+
message: 'OIDC Issuer URL:',
|
|
67
|
+
default: 'https://sso.linagora.com',
|
|
68
|
+
validate: (value) => {
|
|
69
|
+
try {
|
|
70
|
+
new URL(value);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return 'Please enter a valid URL';
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
const clientId = await input({
|
|
79
|
+
message: 'OAuth Client ID:',
|
|
80
|
+
default: 'twake-mail',
|
|
81
|
+
validate: (value) => value.length > 0 || 'Client ID is required',
|
|
82
|
+
});
|
|
83
|
+
const scope = await input({
|
|
84
|
+
message: 'OAuth Scopes:',
|
|
85
|
+
default: 'openid profile email offline_access',
|
|
86
|
+
});
|
|
87
|
+
const redirectUri = await input({
|
|
88
|
+
message: 'OAuth Redirect URI (registered with OIDC provider):',
|
|
89
|
+
default: 'http://localhost:3000/callback',
|
|
90
|
+
validate: (value) => {
|
|
91
|
+
try {
|
|
92
|
+
new URL(value);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return 'Please enter a valid URL';
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
return { issuer, clientId, scope, redirectUri };
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Prompt to confirm writing config to file.
|
|
104
|
+
*/
|
|
105
|
+
export async function promptWriteConfig() {
|
|
106
|
+
return confirm({
|
|
107
|
+
message: 'Write config to Claude Desktop config file?',
|
|
108
|
+
default: true,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Prompt for custom server name in Claude config.
|
|
113
|
+
*/
|
|
114
|
+
export async function promptServerName() {
|
|
115
|
+
return input({
|
|
116
|
+
message: 'Server name in Claude Desktop:',
|
|
117
|
+
default: 'twake-mail',
|
|
118
|
+
validate: (value) => /^[a-z0-9-]+$/.test(value) || 'Use lowercase letters, numbers, and hyphens only',
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=setup-wizard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-wizard.js","sourceRoot":"","sources":["../../../src/cli/prompts/setup-wizard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { createLogger } from '../logger.js';
|
|
3
|
+
describe('createLogger', () => {
|
|
4
|
+
it('should create a pino logger instance', () => {
|
|
5
|
+
const logger = createLogger('info');
|
|
6
|
+
// Verify it's a valid logger with expected methods
|
|
7
|
+
expect(logger).toHaveProperty('info');
|
|
8
|
+
expect(logger).toHaveProperty('error');
|
|
9
|
+
expect(logger).toHaveProperty('warn');
|
|
10
|
+
expect(logger).toHaveProperty('debug');
|
|
11
|
+
expect(logger).toHaveProperty('trace');
|
|
12
|
+
expect(logger).toHaveProperty('fatal');
|
|
13
|
+
});
|
|
14
|
+
it('should use the provided log level', () => {
|
|
15
|
+
const logger = createLogger('debug');
|
|
16
|
+
expect(logger.level).toBe('debug');
|
|
17
|
+
});
|
|
18
|
+
it('should default to info level', () => {
|
|
19
|
+
const logger = createLogger();
|
|
20
|
+
expect(logger.level).toBe('info');
|
|
21
|
+
});
|
|
22
|
+
it('should have mcp-twake-mail as name', () => {
|
|
23
|
+
const logger = createLogger();
|
|
24
|
+
// Pino logger has bindings for the name
|
|
25
|
+
expect(logger.bindings()).toHaveProperty('name', 'mcp-twake-mail');
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
//# sourceMappingURL=logger.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.test.js","sourceRoot":"","sources":["../../../src/config/__tests__/logger.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QAEpC,mDAAmD;QACnD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QAErC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAE9B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAE9B,wCAAwC;QACxC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,cAAc,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { loadConfig } from '../schema.js';
|
|
3
|
+
import { ZodError } from 'zod';
|
|
4
|
+
describe('loadConfig', () => {
|
|
5
|
+
const originalEnv = process.env;
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
process.env = { ...originalEnv };
|
|
8
|
+
});
|
|
9
|
+
it('should return Config type with valid env vars', () => {
|
|
10
|
+
process.env.JMAP_SESSION_URL = 'https://jmap.example.com/session';
|
|
11
|
+
process.env.JMAP_AUTH_METHOD = 'basic';
|
|
12
|
+
process.env.JMAP_USERNAME = 'test@example.com';
|
|
13
|
+
process.env.JMAP_PASSWORD = 'testpass';
|
|
14
|
+
const config = loadConfig();
|
|
15
|
+
expect(config).toHaveProperty('JMAP_SESSION_URL');
|
|
16
|
+
expect(config.JMAP_SESSION_URL).toBe('https://jmap.example.com/session');
|
|
17
|
+
expect(config.JMAP_USERNAME).toBe('test@example.com');
|
|
18
|
+
expect(config.JMAP_PASSWORD).toBe('testpass');
|
|
19
|
+
expect(config.LOG_LEVEL).toBe('info'); // default
|
|
20
|
+
});
|
|
21
|
+
it('should allow localhost with HTTP', () => {
|
|
22
|
+
process.env.JMAP_SESSION_URL = 'http://localhost:8080/session';
|
|
23
|
+
process.env.JMAP_USERNAME = 'test';
|
|
24
|
+
process.env.JMAP_PASSWORD = 'test';
|
|
25
|
+
const config = loadConfig();
|
|
26
|
+
expect(config.JMAP_SESSION_URL).toBe('http://localhost:8080/session');
|
|
27
|
+
});
|
|
28
|
+
it('should throw ZodError when JMAP_SESSION_URL is missing', () => {
|
|
29
|
+
delete process.env.JMAP_SESSION_URL;
|
|
30
|
+
process.env.JMAP_USERNAME = 'test';
|
|
31
|
+
process.env.JMAP_PASSWORD = 'test';
|
|
32
|
+
expect(() => loadConfig()).toThrow(ZodError);
|
|
33
|
+
});
|
|
34
|
+
it('should throw ZodError when using HTTP with non-localhost', () => {
|
|
35
|
+
process.env.JMAP_SESSION_URL = 'http://insecure.example.com/session';
|
|
36
|
+
process.env.JMAP_USERNAME = 'test';
|
|
37
|
+
process.env.JMAP_PASSWORD = 'test';
|
|
38
|
+
expect(() => loadConfig()).toThrow(ZodError);
|
|
39
|
+
});
|
|
40
|
+
it('should throw ZodError when basic auth missing username', () => {
|
|
41
|
+
process.env.JMAP_SESSION_URL = 'https://jmap.example.com/session';
|
|
42
|
+
process.env.JMAP_AUTH_METHOD = 'basic';
|
|
43
|
+
delete process.env.JMAP_USERNAME;
|
|
44
|
+
process.env.JMAP_PASSWORD = 'test';
|
|
45
|
+
expect(() => loadConfig()).toThrow(ZodError);
|
|
46
|
+
});
|
|
47
|
+
it('should throw ZodError when bearer auth missing token', () => {
|
|
48
|
+
process.env.JMAP_SESSION_URL = 'https://jmap.example.com/session';
|
|
49
|
+
process.env.JMAP_AUTH_METHOD = 'bearer';
|
|
50
|
+
delete process.env.JMAP_TOKEN;
|
|
51
|
+
expect(() => loadConfig()).toThrow(ZodError);
|
|
52
|
+
});
|
|
53
|
+
it('should throw ZodError when basic auth missing password', () => {
|
|
54
|
+
process.env.JMAP_SESSION_URL = 'https://jmap.example.com/session';
|
|
55
|
+
process.env.JMAP_AUTH_METHOD = 'basic';
|
|
56
|
+
process.env.JMAP_USERNAME = 'test@example.com';
|
|
57
|
+
delete process.env.JMAP_PASSWORD;
|
|
58
|
+
expect(() => loadConfig()).toThrow(ZodError);
|
|
59
|
+
});
|
|
60
|
+
it('should throw ZodError when oidc auth missing issuer', () => {
|
|
61
|
+
process.env.JMAP_SESSION_URL = 'https://jmap.example.com/session';
|
|
62
|
+
process.env.JMAP_AUTH_METHOD = 'oidc';
|
|
63
|
+
delete process.env.JMAP_OIDC_ISSUER;
|
|
64
|
+
process.env.JMAP_OIDC_CLIENT_ID = 'client-123';
|
|
65
|
+
expect(() => loadConfig()).toThrow(ZodError);
|
|
66
|
+
});
|
|
67
|
+
it('should throw ZodError when oidc auth missing client ID', () => {
|
|
68
|
+
process.env.JMAP_SESSION_URL = 'https://jmap.example.com/session';
|
|
69
|
+
process.env.JMAP_AUTH_METHOD = 'oidc';
|
|
70
|
+
process.env.JMAP_OIDC_ISSUER = 'https://auth.example.com';
|
|
71
|
+
delete process.env.JMAP_OIDC_CLIENT_ID;
|
|
72
|
+
expect(() => loadConfig()).toThrow(ZodError);
|
|
73
|
+
});
|
|
74
|
+
it('should allow valid oidc auth configuration', () => {
|
|
75
|
+
process.env.JMAP_SESSION_URL = 'https://jmap.example.com/session';
|
|
76
|
+
process.env.JMAP_AUTH_METHOD = 'oidc';
|
|
77
|
+
process.env.JMAP_OIDC_ISSUER = 'https://auth.example.com';
|
|
78
|
+
process.env.JMAP_OIDC_CLIENT_ID = 'client-123';
|
|
79
|
+
const config = loadConfig();
|
|
80
|
+
expect(config.JMAP_AUTH_METHOD).toBe('oidc');
|
|
81
|
+
expect(config.JMAP_OIDC_ISSUER).toBe('https://auth.example.com');
|
|
82
|
+
expect(config.JMAP_OIDC_CLIENT_ID).toBe('client-123');
|
|
83
|
+
expect(config.JMAP_OIDC_SCOPE).toBe('openid email offline_access'); // default
|
|
84
|
+
});
|
|
85
|
+
it('should allow bearer auth with valid token', () => {
|
|
86
|
+
process.env.JMAP_SESSION_URL = 'https://jmap.example.com/session';
|
|
87
|
+
process.env.JMAP_AUTH_METHOD = 'bearer';
|
|
88
|
+
process.env.JMAP_TOKEN = 'valid-bearer-token';
|
|
89
|
+
const config = loadConfig();
|
|
90
|
+
expect(config.JMAP_AUTH_METHOD).toBe('bearer');
|
|
91
|
+
expect(config.JMAP_TOKEN).toBe('valid-bearer-token');
|
|
92
|
+
});
|
|
93
|
+
it('should allow 127.0.0.1 with HTTP', () => {
|
|
94
|
+
process.env.JMAP_SESSION_URL = 'http://127.0.0.1:8080/session';
|
|
95
|
+
process.env.JMAP_USERNAME = 'test';
|
|
96
|
+
process.env.JMAP_PASSWORD = 'test';
|
|
97
|
+
const config = loadConfig();
|
|
98
|
+
expect(config.JMAP_SESSION_URL).toBe('http://127.0.0.1:8080/session');
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
//# sourceMappingURL=schema.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.test.js","sourceRoot":"","sources":["../../../src/config/__tests__/schema.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/config/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAIxB,MAAM,UAAU,YAAY,CAAC,QAAgB,MAAM;IACjD,OAAO,IAAI,CACT;QACE,IAAI,EAAE,gBAAgB;QACtB,KAAK;KACN,EACD,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,6CAA6C;KAClE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const envSchema: z.ZodObject<{
|
|
3
|
+
JMAP_SESSION_URL: z.ZodString;
|
|
4
|
+
JMAP_AUTH_METHOD: z.ZodDefault<z.ZodEnum<{
|
|
5
|
+
oidc: "oidc";
|
|
6
|
+
basic: "basic";
|
|
7
|
+
bearer: "bearer";
|
|
8
|
+
}>>;
|
|
9
|
+
JMAP_USERNAME: z.ZodOptional<z.ZodString>;
|
|
10
|
+
JMAP_PASSWORD: z.ZodOptional<z.ZodString>;
|
|
11
|
+
JMAP_TOKEN: z.ZodOptional<z.ZodString>;
|
|
12
|
+
JMAP_OIDC_ISSUER: z.ZodOptional<z.ZodString>;
|
|
13
|
+
JMAP_OIDC_CLIENT_ID: z.ZodOptional<z.ZodString>;
|
|
14
|
+
JMAP_OIDC_SCOPE: z.ZodDefault<z.ZodString>;
|
|
15
|
+
JMAP_OIDC_REDIRECT_URI: z.ZodDefault<z.ZodString>;
|
|
16
|
+
JMAP_OIDC_LOCAL_PORT: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
17
|
+
JMAP_REQUEST_TIMEOUT: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
18
|
+
LOG_LEVEL: z.ZodDefault<z.ZodEnum<{
|
|
19
|
+
error: "error";
|
|
20
|
+
fatal: "fatal";
|
|
21
|
+
warn: "warn";
|
|
22
|
+
info: "info";
|
|
23
|
+
debug: "debug";
|
|
24
|
+
trace: "trace";
|
|
25
|
+
}>>;
|
|
26
|
+
}, z.core.$strip>;
|
|
27
|
+
export type Config = z.infer<typeof envSchema>;
|
|
28
|
+
export declare function loadConfig(): Config;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const envSchema = z
|
|
3
|
+
.object({
|
|
4
|
+
JMAP_SESSION_URL: z
|
|
5
|
+
.string()
|
|
6
|
+
.url('JMAP_SESSION_URL must be a valid URL')
|
|
7
|
+
.refine((url) => {
|
|
8
|
+
const parsed = new URL(url);
|
|
9
|
+
return (parsed.protocol === 'https:' ||
|
|
10
|
+
parsed.hostname === 'localhost' ||
|
|
11
|
+
parsed.hostname === '127.0.0.1');
|
|
12
|
+
}, { message: 'URL must use HTTPS. Only localhost allowed over HTTP for development.' }),
|
|
13
|
+
JMAP_AUTH_METHOD: z.enum(['basic', 'bearer', 'oidc']).default('basic'),
|
|
14
|
+
JMAP_USERNAME: z.string().optional(),
|
|
15
|
+
JMAP_PASSWORD: z.string().optional(),
|
|
16
|
+
JMAP_TOKEN: z.string().optional(),
|
|
17
|
+
// OIDC configuration fields
|
|
18
|
+
JMAP_OIDC_ISSUER: z
|
|
19
|
+
.string()
|
|
20
|
+
.url('JMAP_OIDC_ISSUER must be a valid URL')
|
|
21
|
+
.optional(),
|
|
22
|
+
JMAP_OIDC_CLIENT_ID: z.string().optional(),
|
|
23
|
+
JMAP_OIDC_SCOPE: z.string().default('openid email offline_access'),
|
|
24
|
+
// Redirect URI for OIDC - must be registered with the provider
|
|
25
|
+
JMAP_OIDC_REDIRECT_URI: z.string().url().default('http://localhost:3000/callback'),
|
|
26
|
+
// Local port for OIDC callback server (useful when redirect URI is remote like ngrok)
|
|
27
|
+
JMAP_OIDC_LOCAL_PORT: z.coerce.number().optional(),
|
|
28
|
+
JMAP_REQUEST_TIMEOUT: z.coerce.number().default(30000),
|
|
29
|
+
LOG_LEVEL: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).default('info'),
|
|
30
|
+
})
|
|
31
|
+
.superRefine((data, ctx) => {
|
|
32
|
+
// Conditional validation: basic auth requires username+password
|
|
33
|
+
if (data.JMAP_AUTH_METHOD === 'basic') {
|
|
34
|
+
if (!data.JMAP_USERNAME) {
|
|
35
|
+
ctx.addIssue({
|
|
36
|
+
code: z.ZodIssueCode.custom,
|
|
37
|
+
path: ['JMAP_USERNAME'],
|
|
38
|
+
message: 'JMAP_USERNAME is required when using basic auth',
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (!data.JMAP_PASSWORD) {
|
|
42
|
+
ctx.addIssue({
|
|
43
|
+
code: z.ZodIssueCode.custom,
|
|
44
|
+
path: ['JMAP_PASSWORD'],
|
|
45
|
+
message: 'JMAP_PASSWORD is required when using basic auth',
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else if (data.JMAP_AUTH_METHOD === 'bearer') {
|
|
50
|
+
// Bearer auth requires a token
|
|
51
|
+
if (!data.JMAP_TOKEN) {
|
|
52
|
+
ctx.addIssue({
|
|
53
|
+
code: z.ZodIssueCode.custom,
|
|
54
|
+
path: ['JMAP_TOKEN'],
|
|
55
|
+
message: 'JMAP_TOKEN is required when using bearer auth',
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else if (data.JMAP_AUTH_METHOD === 'oidc') {
|
|
60
|
+
// OIDC requires issuer and client ID
|
|
61
|
+
if (!data.JMAP_OIDC_ISSUER) {
|
|
62
|
+
ctx.addIssue({
|
|
63
|
+
code: z.ZodIssueCode.custom,
|
|
64
|
+
path: ['JMAP_OIDC_ISSUER'],
|
|
65
|
+
message: 'JMAP_OIDC_ISSUER is required when using oidc auth',
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
if (!data.JMAP_OIDC_CLIENT_ID) {
|
|
69
|
+
ctx.addIssue({
|
|
70
|
+
code: z.ZodIssueCode.custom,
|
|
71
|
+
path: ['JMAP_OIDC_CLIENT_ID'],
|
|
72
|
+
message: 'JMAP_OIDC_CLIENT_ID is required when using oidc auth',
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
// Note: JMAP_TOKEN is NOT required for OIDC - tokens come from the OAuth flow
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
export function loadConfig() {
|
|
79
|
+
return envSchema.parse(process.env);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC;KACvB,MAAM,CAAC;IACN,gBAAgB,EAAE,CAAC;SAChB,MAAM,EAAE;SACR,GAAG,CAAC,sCAAsC,CAAC;SAC3C,MAAM,CACL,CAAC,GAAG,EAAE,EAAE;QACN,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,OAAO,CACL,MAAM,CAAC,QAAQ,KAAK,QAAQ;YAC5B,MAAM,CAAC,QAAQ,KAAK,WAAW;YAC/B,MAAM,CAAC,QAAQ,KAAK,WAAW,CAChC,CAAC;IACJ,CAAC,EACD,EAAE,OAAO,EAAE,uEAAuE,EAAE,CACrF;IACH,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACtE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,4BAA4B;IAC5B,gBAAgB,EAAE,CAAC;SAChB,MAAM,EAAE;SACR,GAAG,CAAC,sCAAsC,CAAC;SAC3C,QAAQ,EAAE;IACb,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,6BAA6B,CAAC;IAClE,+DAA+D;IAC/D,sBAAsB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,gCAAgC,CAAC;IAClF,sFAAsF;IACtF,oBAAoB,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClD,oBAAoB,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACtD,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;CACxF,CAAC;KACD,WAAW,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IACzB,gEAAgE;IAChE,IAAI,IAAI,CAAC,gBAAgB,KAAK,OAAO,EAAE,CAAC;QACtC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,GAAG,CAAC,QAAQ,CAAC;gBACX,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;gBAC3B,IAAI,EAAE,CAAC,eAAe,CAAC;gBACvB,OAAO,EAAE,iDAAiD;aAC3D,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,GAAG,CAAC,QAAQ,CAAC;gBACX,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;gBAC3B,IAAI,EAAE,CAAC,eAAe,CAAC;gBACvB,OAAO,EAAE,iDAAiD;aAC3D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;SAAM,IAAI,IAAI,CAAC,gBAAgB,KAAK,QAAQ,EAAE,CAAC;QAC9C,+BAA+B;QAC/B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,GAAG,CAAC,QAAQ,CAAC;gBACX,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;gBAC3B,IAAI,EAAE,CAAC,YAAY,CAAC;gBACpB,OAAO,EAAE,+CAA+C;aACzD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;SAAM,IAAI,IAAI,CAAC,gBAAgB,KAAK,MAAM,EAAE,CAAC;QAC5C,qCAAqC;QACrC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,GAAG,CAAC,QAAQ,CAAC;gBACX,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;gBAC3B,IAAI,EAAE,CAAC,kBAAkB,CAAC;gBAC1B,OAAO,EAAE,mDAAmD;aAC7D,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC9B,GAAG,CAAC,QAAQ,CAAC;gBACX,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;gBAC3B,IAAI,EAAE,CAAC,qBAAqB,CAAC;gBAC7B,OAAO,EAAE,sDAAsD;aAChE,CAAC,CAAC;QACL,CAAC;QACD,8EAA8E;IAChF,CAAC;AACH,CAAC,CAAC,CAAC;AAIL,MAAM,UAAU,UAAU;IACxB,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export declare class JMAPError extends Error {
|
|
2
|
+
type: string;
|
|
3
|
+
fix: string;
|
|
4
|
+
constructor(message: string, type: string, fix: string);
|
|
5
|
+
/**
|
|
6
|
+
* Create a JMAPError for HTTP-level errors (4xx, 5xx responses)
|
|
7
|
+
*/
|
|
8
|
+
static httpError(status: number, statusText: string): JMAPError;
|
|
9
|
+
/**
|
|
10
|
+
* Create a JMAPError for JMAP method-level errors
|
|
11
|
+
*/
|
|
12
|
+
static methodError(type: string, description?: string): JMAPError;
|
|
13
|
+
/**
|
|
14
|
+
* Create a JMAPError for timeout errors
|
|
15
|
+
*/
|
|
16
|
+
static timeout(operation: string): JMAPError;
|
|
17
|
+
/**
|
|
18
|
+
* Create a JMAPError for expired access token
|
|
19
|
+
*/
|
|
20
|
+
static tokenExpired(refreshAvailable: boolean): JMAPError;
|
|
21
|
+
/**
|
|
22
|
+
* Create a JMAPError for failed token refresh
|
|
23
|
+
*/
|
|
24
|
+
static refreshFailed(reason?: string): JMAPError;
|
|
25
|
+
/**
|
|
26
|
+
* Create a JMAPError for OIDC flow errors
|
|
27
|
+
*/
|
|
28
|
+
static oidcFlowError(stage: string, details?: string): JMAPError;
|
|
29
|
+
/**
|
|
30
|
+
* Create a JMAPError for missing stored tokens
|
|
31
|
+
*/
|
|
32
|
+
static noStoredTokens(): JMAPError;
|
|
33
|
+
}
|
|
34
|
+
export declare function formatStartupError(error: Error, sessionUrl?: string): string;
|