@ankimcp/anki-mcp-server 0.13.0-tunnel.1 → 0.13.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 (133) hide show
  1. package/README.md +53 -5
  2. package/bin/ankimcp.js +17 -10
  3. package/dist/anki-config.service.d.ts +11 -0
  4. package/dist/anki-config.service.js +46 -0
  5. package/dist/anki-config.service.js.map +1 -0
  6. package/dist/app.module.d.ts +2 -4
  7. package/dist/app.module.js +11 -98
  8. package/dist/app.module.js.map +1 -1
  9. package/dist/bootstrap.d.ts +1 -6
  10. package/dist/bootstrap.js +2 -7
  11. package/dist/bootstrap.js.map +1 -1
  12. package/dist/cli.d.ts +1 -4
  13. package/dist/cli.js +18 -23
  14. package/dist/cli.js.map +1 -1
  15. package/dist/http/guards/origin-validation.guard.d.ts +0 -1
  16. package/dist/http/guards/origin-validation.guard.js +3 -5
  17. package/dist/http/guards/origin-validation.guard.js.map +1 -1
  18. package/dist/main-http.js +10 -19
  19. package/dist/main-http.js.map +1 -1
  20. package/dist/main-stdio.js +31 -7
  21. package/dist/main-stdio.js.map +1 -1
  22. package/dist/mcp/clients/anki-connect.client.d.ts +5 -0
  23. package/dist/mcp/clients/anki-connect.client.js +35 -1
  24. package/dist/mcp/clients/anki-connect.client.js.map +1 -1
  25. package/dist/mcp/config/anki-config.interface.d.ts +1 -0
  26. package/dist/mcp/config/anki-config.interface.js.map +1 -1
  27. package/dist/mcp/primitives/essential/index.d.ts +4 -9
  28. package/dist/mcp/primitives/essential/index.js +7 -21
  29. package/dist/mcp/primitives/essential/index.js.map +1 -1
  30. package/dist/mcp/primitives/essential/tools/add-note.tool.js +22 -9
  31. package/dist/mcp/primitives/essential/tools/add-note.tool.js.map +1 -1
  32. package/dist/mcp/primitives/essential/tools/deckActions/actions/changeDeck.action.d.ts +12 -0
  33. package/dist/mcp/primitives/essential/tools/deckActions/actions/changeDeck.action.js +24 -0
  34. package/dist/mcp/primitives/essential/tools/deckActions/actions/changeDeck.action.js.map +1 -0
  35. package/dist/mcp/primitives/essential/tools/deckActions/actions/createDeck.action.d.ts +15 -0
  36. package/dist/mcp/primitives/essential/tools/deckActions/actions/createDeck.action.js +44 -0
  37. package/dist/mcp/primitives/essential/tools/deckActions/actions/createDeck.action.js.map +1 -0
  38. package/dist/mcp/primitives/essential/tools/{deck-stats/deck-stats.types.d.ts → deckActions/actions/deckStats.action.d.ts} +5 -2
  39. package/dist/mcp/primitives/essential/tools/deckActions/actions/deckStats.action.js +78 -0
  40. package/dist/mcp/primitives/essential/tools/deckActions/actions/deckStats.action.js.map +1 -0
  41. package/dist/mcp/primitives/essential/tools/deckActions/actions/listDecks.action.d.ts +18 -0
  42. package/dist/mcp/primitives/essential/tools/deckActions/actions/listDecks.action.js +63 -0
  43. package/dist/mcp/primitives/essential/tools/deckActions/actions/listDecks.action.js.map +1 -0
  44. package/dist/mcp/primitives/essential/tools/{deck-stats/deck-stats.tool.d.ts → deckActions/deckActions.tool.d.ts} +8 -4
  45. package/dist/mcp/primitives/essential/tools/deckActions/deckActions.tool.js +138 -0
  46. package/dist/mcp/primitives/essential/tools/deckActions/deckActions.tool.js.map +1 -0
  47. package/dist/mcp/primitives/essential/tools/deckActions/index.d.ts +5 -0
  48. package/dist/mcp/primitives/essential/tools/deckActions/index.js +6 -0
  49. package/dist/mcp/primitives/essential/tools/deckActions/index.js.map +1 -0
  50. package/dist/mcp/primitives/gui/index.d.ts +0 -1
  51. package/dist/mcp/primitives/gui/index.js +1 -8
  52. package/dist/mcp/primitives/gui/index.js.map +1 -1
  53. package/dist/services/ngrok.service.d.ts +0 -1
  54. package/dist/services/ngrok.service.js +3 -5
  55. package/dist/services/ngrok.service.js.map +1 -1
  56. package/dist/test-fixtures/mock-data.d.ts +0 -8
  57. package/dist/test-fixtures/mock-data.js +0 -8
  58. package/dist/test-fixtures/mock-data.js.map +1 -1
  59. package/dist/tsconfig.build.tsbuildinfo +1 -1
  60. package/package.json +24 -27
  61. package/dist/app-config.service.d.ts +0 -21
  62. package/dist/app-config.service.js +0 -76
  63. package/dist/app-config.service.js.map +0 -1
  64. package/dist/cli/__tests__/cli-output.manual.d.ts +0 -2
  65. package/dist/cli/__tests__/cli-output.manual.js +0 -13
  66. package/dist/cli/__tests__/cli-output.manual.js.map +0 -1
  67. package/dist/cli/cli-output.d.ts +0 -20
  68. package/dist/cli/cli-output.js +0 -69
  69. package/dist/cli/cli-output.js.map +0 -1
  70. package/dist/cli/index.d.ts +0 -1
  71. package/dist/cli/index.js +0 -18
  72. package/dist/cli/index.js.map +0 -1
  73. package/dist/config/config.factory.d.ts +0 -12
  74. package/dist/config/config.factory.js +0 -29
  75. package/dist/config/config.factory.js.map +0 -1
  76. package/dist/config/config.schema.d.ts +0 -32
  77. package/dist/config/config.schema.js +0 -48
  78. package/dist/config/config.schema.js.map +0 -1
  79. package/dist/config/index.d.ts +0 -3
  80. package/dist/config/index.js +0 -11
  81. package/dist/config/index.js.map +0 -1
  82. package/dist/main-tunnel.d.ts +0 -1
  83. package/dist/main-tunnel.js +0 -26
  84. package/dist/main-tunnel.js.map +0 -1
  85. package/dist/mcp/primitives/essential/tools/create-deck.tool.d.ts +0 -105
  86. package/dist/mcp/primitives/essential/tools/create-deck.tool.js +0 -121
  87. package/dist/mcp/primitives/essential/tools/create-deck.tool.js.map +0 -1
  88. package/dist/mcp/primitives/essential/tools/deck-stats/deck-stats.tool.js +0 -165
  89. package/dist/mcp/primitives/essential/tools/deck-stats/deck-stats.tool.js.map +0 -1
  90. package/dist/mcp/primitives/essential/tools/deck-stats/deck-stats.types.js +0 -3
  91. package/dist/mcp/primitives/essential/tools/deck-stats/deck-stats.types.js.map +0 -1
  92. package/dist/mcp/primitives/essential/tools/deck-stats/index.d.ts +0 -2
  93. package/dist/mcp/primitives/essential/tools/deck-stats/index.js +0 -6
  94. package/dist/mcp/primitives/essential/tools/deck-stats/index.js.map +0 -1
  95. package/dist/mcp/primitives/essential/tools/list-decks.tool.d.ts +0 -105
  96. package/dist/mcp/primitives/essential/tools/list-decks.tool.js +0 -117
  97. package/dist/mcp/primitives/essential/tools/list-decks.tool.js.map +0 -1
  98. package/dist/tunnel/commands/index.d.ts +0 -3
  99. package/dist/tunnel/commands/index.js +0 -10
  100. package/dist/tunnel/commands/index.js.map +0 -1
  101. package/dist/tunnel/commands/login.command.d.ts +0 -1
  102. package/dist/tunnel/commands/login.command.js +0 -108
  103. package/dist/tunnel/commands/login.command.js.map +0 -1
  104. package/dist/tunnel/commands/logout.command.d.ts +0 -1
  105. package/dist/tunnel/commands/logout.command.js +0 -26
  106. package/dist/tunnel/commands/logout.command.js.map +0 -1
  107. package/dist/tunnel/commands/tunnel.command.d.ts +0 -1
  108. package/dist/tunnel/commands/tunnel.command.js +0 -183
  109. package/dist/tunnel/commands/tunnel.command.js.map +0 -1
  110. package/dist/tunnel/credentials.service.d.ts +0 -23
  111. package/dist/tunnel/credentials.service.js +0 -152
  112. package/dist/tunnel/credentials.service.js.map +0 -1
  113. package/dist/tunnel/device-flow.service.d.ts +0 -46
  114. package/dist/tunnel/device-flow.service.js +0 -237
  115. package/dist/tunnel/device-flow.service.js.map +0 -1
  116. package/dist/tunnel/in-memory.transport.d.ts +0 -14
  117. package/dist/tunnel/in-memory.transport.js +0 -63
  118. package/dist/tunnel/in-memory.transport.js.map +0 -1
  119. package/dist/tunnel/index.d.ts +0 -6
  120. package/dist/tunnel/index.js +0 -31
  121. package/dist/tunnel/index.js.map +0 -1
  122. package/dist/tunnel/tunnel-mcp.service.d.ts +0 -15
  123. package/dist/tunnel/tunnel-mcp.service.js +0 -100
  124. package/dist/tunnel/tunnel-mcp.service.js.map +0 -1
  125. package/dist/tunnel/tunnel.client.d.ts +0 -60
  126. package/dist/tunnel/tunnel.client.js +0 -381
  127. package/dist/tunnel/tunnel.client.js.map +0 -1
  128. package/dist/tunnel/tunnel.protocol.d.ts +0 -67
  129. package/dist/tunnel/tunnel.protocol.js +0 -25
  130. package/dist/tunnel/tunnel.protocol.js.map +0 -1
  131. package/dist/version.d.ts +0 -2
  132. package/dist/version.js +0 -21
  133. package/dist/version.js.map +0 -1
package/README.md CHANGED
@@ -41,8 +41,11 @@ For comprehensive guides, real-world examples, and step-by-step tutorials on usi
41
41
  - `rate_card` - Rate card performance
42
42
 
43
43
  ### Deck Management
44
- - `list_decks` - Show available decks
45
- - `createDeck` - Create new decks
44
+ - `deckActions` - Unified deck operations:
45
+ - `listDecks` - List all decks with optional statistics
46
+ - `createDeck` - Create new decks (max 2 levels: "Parent::Child")
47
+ - `deckStats` - Get comprehensive deck statistics
48
+ - `changeDeck` - Move cards to a different deck
46
49
 
47
50
  ### Note Management
48
51
  - `addNote` - Create new notes
@@ -216,6 +219,7 @@ Options:
216
219
  -h, --host <host> Host to bind to (HTTP mode, default: 127.0.0.1)
217
220
  -a, --anki-connect <url> AnkiConnect URL (default: http://localhost:8765)
218
221
  --ngrok Start ngrok tunnel (requires global ngrok installation)
222
+ --read-only Run in read-only mode (blocks all write operations)
219
223
  --help Show help message
220
224
 
221
225
  Usage with npx (no installation needed):
@@ -223,6 +227,7 @@ Usage with npx (no installation needed):
223
227
  npx @ankimcp/anki-mcp-server --port 8080 # Custom port
224
228
  npx @ankimcp/anki-mcp-server --stdio # STDIO mode
225
229
  npx @ankimcp/anki-mcp-server --ngrok # HTTP mode with ngrok tunnel
230
+ npx @ankimcp/anki-mcp-server --read-only # Read-only mode
226
231
 
227
232
  Usage with global installation:
228
233
  npm install -g @ankimcp/anki-mcp-server # Install once
@@ -230,6 +235,46 @@ Usage with global installation:
230
235
  ankimcp --port 8080 # Custom port
231
236
  ankimcp --stdio # STDIO mode
232
237
  ankimcp --ngrok # HTTP mode with ngrok tunnel
238
+ ankimcp --read-only # Read-only mode
239
+ ```
240
+
241
+ **Read-Only Mode:**
242
+
243
+ The `--read-only` flag prevents any modifications to your Anki collection. When enabled:
244
+ - All read operations work normally (browsing decks, viewing cards, searching notes)
245
+ - Review operations are allowed (sync, answerCards, suspend/unsuspend)
246
+ - Content modifications are blocked (addNote, deleteNotes, createDeck, updateNoteFields, etc.)
247
+ - Useful for safely exploring Anki data without risk of accidental changes
248
+
249
+ ```bash
250
+ # HTTP mode with read-only
251
+ ankimcp --read-only
252
+
253
+ # STDIO mode with read-only
254
+ ankimcp --stdio --read-only
255
+
256
+ # Can combine with other flags
257
+ ankimcp --ngrok --read-only
258
+ ```
259
+
260
+ You can also enable read-only mode via environment variable:
261
+ ```bash
262
+ READ_ONLY=true ankimcp
263
+ ```
264
+
265
+ Or in MCP client configuration:
266
+ ```json
267
+ {
268
+ "mcpServers": {
269
+ "anki-mcp": {
270
+ "command": "npx",
271
+ "args": ["-y", "@ankimcp/anki-mcp-server", "--stdio", "--read-only"],
272
+ "env": {
273
+ "ANKI_CONNECT_URL": "http://localhost:8765"
274
+ }
275
+ }
276
+ }
277
+ }
233
278
  ```
234
279
 
235
280
  **Using with ngrok:**
@@ -321,6 +366,7 @@ For more details, see the [official MCP documentation](https://modelcontextproto
321
366
  | `ANKI_CONNECT_API_VERSION` | API version | `6` |
322
367
  | `ANKI_CONNECT_API_KEY` | API key if configured in AnkiConnect | - |
323
368
  | `ANKI_CONNECT_TIMEOUT` | Request timeout in ms | `5000` |
369
+ | `READ_ONLY` | Enable read-only mode (`true` or `1`) | `false` |
324
370
 
325
371
  ## Usage Examples
326
372
 
@@ -398,14 +444,16 @@ If you see an error like:
398
444
  Error [ERR_REQUIRE_ESM]: require() of ES Module not supported
399
445
  ```
400
446
 
401
- This means your Node.js version is too old. The server requires **Node.js 20.19.0 or later**.
447
+ This means your Node.js version is not supported. The server requires **Node.js 20.19.0+ or 22.12.0+**.
448
+
449
+ > **Note:** Node.js 21.x is not supported. The `require(esm)` feature was added in Node 22 and backported to Node 20.17+, but was never available in Node 21. See [#16](https://github.com/ankimcp/anki-mcp-server/issues/16) for details.
402
450
 
403
451
  **Check your version:**
404
452
  ```bash
405
453
  node --version
406
454
  ```
407
455
 
408
- **Solution:** Update Node.js to version 20.19.0 or later. You can download it from [nodejs.org](https://nodejs.org/) or use a version manager like [nvm](https://github.com/nvm-sh/nvm).
456
+ **Solution:** Update Node.js to version 20.19.0+ or 22.12.0+. You can download it from [nodejs.org](https://nodejs.org/) or use a version manager like [nvm](https://github.com/nvm-sh/nvm).
409
457
 
410
458
  ## Development
411
459
 
@@ -798,4 +846,4 @@ For complete license terms, see the [LICENSE](LICENSE) file.
798
846
 
799
847
  - **Model Context Protocol (MCP)** is an open standard by Anthropic. The MCP logo is from the official [MCP documentation repository](https://github.com/modelcontextprotocol/docs) and is used under the MIT License. For more information about MCP, visit [https://modelcontextprotocol.io](https://modelcontextprotocol.io).
800
848
 
801
- - This is an independent project that bridges Anki and MCP technologies. All trademarks, service marks, trade names, product names, and logos are the property of their respective owners.
849
+ - This is an independent project that bridges Anki and MCP technologies. All trademarks, service marks, trade names, product names, and logos are the property of their respective owners.
package/bin/ankimcp.js CHANGED
@@ -1,20 +1,27 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // Determine mode based on CLI flags
3
+ // Runtime Node.js version check (require(esm) needs Node 20.19+ or 22.12+)
4
+ const [major, minor] = process.versions.node.split('.').map(Number);
5
+ if (
6
+ (major < 20) ||
7
+ (major === 21) ||
8
+ (major === 20 && minor < 19) ||
9
+ (major === 22 && minor < 12)
10
+ ) {
11
+ console.error(
12
+ `Error: Node.js ${process.versions.node} is not supported.\n` +
13
+ 'This package requires Node.js 20.19.0+ or 22.12.0+ (Node 21.x is not supported).\n' +
14
+ 'Download: https://nodejs.org/'
15
+ );
16
+ process.exit(1);
17
+ }
18
+
19
+ // Check if --stdio flag is present
4
20
  const isStdioMode = process.argv.includes('--stdio');
5
- const isTunnelMode = process.argv.some(arg =>
6
- arg === '--tunnel' ||
7
- arg.startsWith('--tunnel=') ||
8
- arg === '--login' ||
9
- arg === '--logout'
10
- );
11
21
 
12
22
  if (isStdioMode) {
13
23
  // STDIO mode - for MCP clients like Cursor, Cline, Zed, etc.
14
24
  require('../dist/main-stdio.js');
15
- } else if (isTunnelMode) {
16
- // Tunnel mode - for remote MCP access via tunnel service
17
- require('../dist/main-tunnel.js');
18
25
  } else {
19
26
  // HTTP mode (default) - for web-based AI assistants
20
27
  require('../dist/main-http.js');
@@ -0,0 +1,11 @@
1
+ import { ConfigService } from "@nestjs/config";
2
+ import { IAnkiConfig } from "./mcp/config/anki-config.interface";
3
+ export declare class AnkiConfigService implements IAnkiConfig {
4
+ private configService;
5
+ constructor(configService: ConfigService);
6
+ get ankiConnectUrl(): string;
7
+ get ankiConnectApiVersion(): number;
8
+ get ankiConnectApiKey(): string | undefined;
9
+ get ankiConnectTimeout(): number;
10
+ get readOnly(): boolean;
11
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.AnkiConfigService = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ const config_1 = require("@nestjs/config");
15
+ const mcpb_workarounds_1 = require("./mcp/utils/mcpb-workarounds");
16
+ let AnkiConfigService = class AnkiConfigService {
17
+ configService;
18
+ constructor(configService) {
19
+ this.configService = configService;
20
+ }
21
+ get ankiConnectUrl() {
22
+ return this.configService.get("ANKI_CONNECT_URL", "http://localhost:8765");
23
+ }
24
+ get ankiConnectApiVersion() {
25
+ const version = this.configService.get("ANKI_CONNECT_API_VERSION", "6");
26
+ return parseInt(version, 10);
27
+ }
28
+ get ankiConnectApiKey() {
29
+ const apiKey = this.configService.get("ANKI_CONNECT_API_KEY");
30
+ return (0, mcpb_workarounds_1.sanitizeMcpbConfigValue)(apiKey);
31
+ }
32
+ get ankiConnectTimeout() {
33
+ const timeout = this.configService.get("ANKI_CONNECT_TIMEOUT", "5000");
34
+ return parseInt(timeout, 10);
35
+ }
36
+ get readOnly() {
37
+ const readOnly = this.configService.get("READ_ONLY", "false");
38
+ return readOnly === "true" || readOnly === "1";
39
+ }
40
+ };
41
+ exports.AnkiConfigService = AnkiConfigService;
42
+ exports.AnkiConfigService = AnkiConfigService = __decorate([
43
+ (0, common_1.Injectable)(),
44
+ __metadata("design:paramtypes", [config_1.ConfigService])
45
+ ], AnkiConfigService);
46
+ //# sourceMappingURL=anki-config.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anki-config.service.js","sourceRoot":"","sources":["../src/anki-config.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,2CAA+C;AAE/C,mEAAuE;AAMhE,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IACR;IAApB,YAAoB,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IAAG,CAAC;IAEpD,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAC3B,kBAAkB,EAClB,uBAAuB,CACxB,CAAC;IACJ,CAAC;IAED,IAAI,qBAAqB;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CACpC,0BAA0B,EAC1B,GAAG,CACJ,CAAC;QACF,OAAO,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,iBAAiB;QACnB,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,sBAAsB,CAAC,CAAC;QACtE,OAAO,IAAA,0CAAuB,EAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,kBAAkB;QACpB,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CACpC,sBAAsB,EACtB,MAAM,CACP,CAAC;QACF,OAAO,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,QAAQ;QACV,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAS,WAAW,EAAE,OAAO,CAAC,CAAC;QACtE,OAAO,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,GAAG,CAAC;IACjD,CAAC;CACF,CAAA;AAnCY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,mBAAU,GAAE;qCAEwB,sBAAa;GADrC,iBAAiB,CAmC7B"}
@@ -1,7 +1,5 @@
1
1
  import { DynamicModule } from "@nestjs/common";
2
- import { ConfigInput, CliOverrides } from "@/config";
3
2
  export declare class AppModule {
4
- static forStdio(configInput: ConfigInput): DynamicModule;
5
- static forHttp(configInput: ConfigInput): DynamicModule;
6
- static forTunnel(cliOverrides?: CliOverrides): DynamicModule;
3
+ static forStdio(): DynamicModule;
4
+ static forHttp(): DynamicModule;
7
5
  }
@@ -13,19 +13,16 @@ const config_1 = require("@nestjs/config");
13
13
  const mcp_nest_1 = require("@rekog/mcp-nest");
14
14
  const essential_1 = require("./mcp/primitives/essential");
15
15
  const gui_1 = require("./mcp/primitives/gui");
16
- const app_config_service_1 = require("./app-config.service");
17
- const config_2 = require("./config");
18
- const tunnel_mcp_service_1 = require("./tunnel/tunnel-mcp.service");
16
+ const anki_config_service_1 = require("./anki-config.service");
19
17
  let AppModule = AppModule_1 = class AppModule {
20
- static forStdio(configInput) {
21
- const validatedConfig = config_2.configSchema.parse((0, config_2.transformEnvToConfig)(configInput));
18
+ static forStdio() {
22
19
  return {
23
20
  module: AppModule_1,
24
21
  imports: [
25
22
  config_1.ConfigModule.forRoot({
26
23
  isGlobal: true,
27
24
  cache: true,
28
- load: [() => validatedConfig],
25
+ envFilePath: [".env.local", ".env"],
29
26
  }),
30
27
  mcp_nest_1.McpModule.forRoot({
31
28
  name: process.env.MCP_SERVER_NAME || "anki-mcp-server",
@@ -35,45 +32,27 @@ let AppModule = AppModule_1 = class AppModule {
35
32
  essential_1.McpPrimitivesAnkiEssentialModule.forRoot({
36
33
  ankiConfigProvider: {
37
34
  provide: essential_1.ANKI_CONFIG,
38
- useClass: app_config_service_1.AppConfigService,
39
- },
40
- appConfigProvider: {
41
- provide: config_2.APP_CONFIG,
42
- useValue: validatedConfig,
35
+ useClass: anki_config_service_1.AnkiConfigService,
43
36
  },
44
37
  }),
45
38
  gui_1.McpPrimitivesAnkiGuiModule.forRoot({
46
39
  ankiConfigProvider: {
47
40
  provide: essential_1.ANKI_CONFIG,
48
- useClass: app_config_service_1.AppConfigService,
49
- },
50
- appConfigProvider: {
51
- provide: config_2.APP_CONFIG,
52
- useValue: validatedConfig,
41
+ useClass: anki_config_service_1.AnkiConfigService,
53
42
  },
54
43
  }),
55
44
  ],
56
- providers: [
57
- {
58
- provide: config_2.APP_CONFIG,
59
- useValue: validatedConfig,
60
- },
61
- app_config_service_1.AppConfigService,
62
- ...essential_1.ESSENTIAL_MCP_TOOLS,
63
- ...gui_1.GUI_MCP_TOOLS,
64
- ],
65
- exports: [config_2.APP_CONFIG, app_config_service_1.AppConfigService],
45
+ providers: [anki_config_service_1.AnkiConfigService, ...essential_1.ESSENTIAL_MCP_TOOLS, ...gui_1.GUI_MCP_TOOLS],
66
46
  };
67
47
  }
68
- static forHttp(configInput) {
69
- const validatedConfig = config_2.configSchema.parse((0, config_2.transformEnvToConfig)(configInput));
48
+ static forHttp() {
70
49
  return {
71
50
  module: AppModule_1,
72
51
  imports: [
73
52
  config_1.ConfigModule.forRoot({
74
53
  isGlobal: true,
75
54
  cache: true,
76
- load: [() => validatedConfig],
55
+ envFilePath: [".env.local", ".env"],
77
56
  }),
78
57
  mcp_nest_1.McpModule.forRoot({
79
58
  name: process.env.MCP_SERVER_NAME || "anki-mcp-server",
@@ -84,83 +63,17 @@ let AppModule = AppModule_1 = class AppModule {
84
63
  essential_1.McpPrimitivesAnkiEssentialModule.forRoot({
85
64
  ankiConfigProvider: {
86
65
  provide: essential_1.ANKI_CONFIG,
87
- useClass: app_config_service_1.AppConfigService,
88
- },
89
- appConfigProvider: {
90
- provide: config_2.APP_CONFIG,
91
- useValue: validatedConfig,
66
+ useClass: anki_config_service_1.AnkiConfigService,
92
67
  },
93
68
  }),
94
69
  gui_1.McpPrimitivesAnkiGuiModule.forRoot({
95
70
  ankiConfigProvider: {
96
71
  provide: essential_1.ANKI_CONFIG,
97
- useClass: app_config_service_1.AppConfigService,
98
- },
99
- appConfigProvider: {
100
- provide: config_2.APP_CONFIG,
101
- useValue: validatedConfig,
72
+ useClass: anki_config_service_1.AnkiConfigService,
102
73
  },
103
74
  }),
104
75
  ],
105
- providers: [
106
- {
107
- provide: config_2.APP_CONFIG,
108
- useValue: validatedConfig,
109
- },
110
- app_config_service_1.AppConfigService,
111
- ...essential_1.ESSENTIAL_MCP_TOOLS,
112
- ...gui_1.GUI_MCP_TOOLS,
113
- ],
114
- exports: [config_2.APP_CONFIG, app_config_service_1.AppConfigService],
115
- };
116
- }
117
- static forTunnel(cliOverrides) {
118
- const validatedConfig = (0, config_2.loadValidatedConfig)(cliOverrides);
119
- return {
120
- module: AppModule_1,
121
- imports: [
122
- config_1.ConfigModule.forRoot({
123
- isGlobal: true,
124
- cache: true,
125
- load: [() => validatedConfig],
126
- }),
127
- mcp_nest_1.McpModule.forRoot({
128
- name: process.env.MCP_SERVER_NAME || "anki-mcp-server",
129
- version: process.env.MCP_SERVER_VERSION || "1.0.0",
130
- transport: [],
131
- }),
132
- essential_1.McpPrimitivesAnkiEssentialModule.forRoot({
133
- ankiConfigProvider: {
134
- provide: essential_1.ANKI_CONFIG,
135
- useClass: app_config_service_1.AppConfigService,
136
- },
137
- appConfigProvider: {
138
- provide: config_2.APP_CONFIG,
139
- useValue: validatedConfig,
140
- },
141
- }),
142
- gui_1.McpPrimitivesAnkiGuiModule.forRoot({
143
- ankiConfigProvider: {
144
- provide: essential_1.ANKI_CONFIG,
145
- useClass: app_config_service_1.AppConfigService,
146
- },
147
- appConfigProvider: {
148
- provide: config_2.APP_CONFIG,
149
- useValue: validatedConfig,
150
- },
151
- }),
152
- ],
153
- providers: [
154
- {
155
- provide: config_2.APP_CONFIG,
156
- useValue: validatedConfig,
157
- },
158
- app_config_service_1.AppConfigService,
159
- tunnel_mcp_service_1.TunnelMcpService,
160
- ...essential_1.ESSENTIAL_MCP_TOOLS,
161
- ...gui_1.GUI_MCP_TOOLS,
162
- ],
163
- exports: [config_2.APP_CONFIG, app_config_service_1.AppConfigService, tunnel_mcp_service_1.TunnelMcpService],
76
+ providers: [anki_config_service_1.AnkiConfigService, ...essential_1.ESSENTIAL_MCP_TOOLS, ...gui_1.GUI_MCP_TOOLS],
164
77
  };
165
78
  }
166
79
  };
@@ -1 +1 @@
1
- {"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAuD;AACvD,2CAA8C;AAC9C,8CAA8D;AAC9D,0DAIoC;AACpC,8CAG8B;AAC9B,+DAA0D;AAGnD,IAAM,SAAS,iBAAf,MAAM,SAAS;IAIpB,MAAM,CAAC,QAAQ;QACb,OAAO;YACL,MAAM,EAAE,WAAS;YACjB,OAAO,EAAE;gBAEP,qBAAY,CAAC,OAAO,CAAC;oBACnB,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,IAAI;oBACX,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC;iBACpC,CAAC;gBAGF,oBAAS,CAAC,OAAO,CAAC;oBAChB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,iBAAiB;oBACtD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO;oBAClD,SAAS,EAAE,2BAAgB,CAAC,KAAK;iBAClC,CAAC;gBAGF,4CAAgC,CAAC,OAAO,CAAC;oBACvC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;gBAGF,gCAA0B,CAAC,OAAO,CAAC;oBACjC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;aACH;YAED,SAAS,EAAE,CAAC,uCAAiB,EAAE,GAAG,+BAAmB,EAAE,GAAG,mBAAa,CAAC;SACzE,CAAC;IACJ,CAAC;IAKD,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,MAAM,EAAE,WAAS;YACjB,OAAO,EAAE;gBAEP,qBAAY,CAAC,OAAO,CAAC;oBACnB,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,IAAI;oBACX,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC;iBACpC,CAAC;gBAGF,oBAAS,CAAC,OAAO,CAAC;oBAChB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,iBAAiB;oBACtD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO;oBAClD,SAAS,EAAE,2BAAgB,CAAC,eAAe;oBAC3C,WAAW,EAAE,GAAG;iBACjB,CAAC;gBAGF,4CAAgC,CAAC,OAAO,CAAC;oBACvC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;gBAGF,gCAA0B,CAAC,OAAO,CAAC;oBACjC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;aACH;YAED,SAAS,EAAE,CAAC,uCAAiB,EAAE,GAAG,+BAAmB,EAAE,GAAG,mBAAa,CAAC;SACzE,CAAC;IACJ,CAAC;CACF,CAAA;AArFY,8BAAS;oBAAT,SAAS;IADrB,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,SAAS,CAqFrB"}
@@ -1,8 +1,3 @@
1
1
  import { LoggerService } from "@nestjs/common";
2
- export declare const LOG_DESTINATION: {
3
- readonly STDOUT: 1;
4
- readonly STDERR: 2;
5
- };
6
- export type LogDestination = (typeof LOG_DESTINATION)[keyof typeof LOG_DESTINATION];
7
- export declare function createPinoLogger(destination: LogDestination, logLevel?: string): import("pino").Logger<never, boolean>;
2
+ export declare function createPinoLogger(destination: 1 | 2): import("pino").Logger<never, boolean>;
8
3
  export declare function createLoggerService(pinoLogger: any): LoggerService;
package/dist/bootstrap.js CHANGED
@@ -1,16 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LOG_DESTINATION = void 0;
4
3
  exports.createPinoLogger = createPinoLogger;
5
4
  exports.createLoggerService = createLoggerService;
6
5
  const pino_1 = require("pino");
7
- exports.LOG_DESTINATION = {
8
- STDOUT: 1,
9
- STDERR: 2,
10
- };
11
- function createPinoLogger(destination, logLevel = "info") {
6
+ function createPinoLogger(destination) {
12
7
  return (0, pino_1.pino)({
13
- level: logLevel,
8
+ level: process.env.LOG_LEVEL || "info",
14
9
  transport: {
15
10
  target: "pino-pretty",
16
11
  options: {
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":";;;AAuBA,4CAgBC;AAQD,kDAkBC;AAhED,+BAA4B;AAKf,QAAA,eAAe,GAAG;IAE7B,MAAM,EAAE,CAAC;IAET,MAAM,EAAE,CAAC;CACD,CAAC;AAYX,SAAgB,gBAAgB,CAC9B,WAA2B,EAC3B,WAAmB,MAAM;IAEzB,OAAO,IAAA,WAAI,EAAC;QACV,KAAK,EAAE,QAAQ;QACf,SAAS,EAAE;YACT,MAAM,EAAE,aAAa;YACrB,OAAO,EAAE;gBACP,WAAW;gBACX,QAAQ,EAAE,IAAI;gBACd,aAAa,EAAE,YAAY;gBAC3B,MAAM,EAAE,cAAc;aACvB;SACF;KACF,CAAC,CAAC;AACL,CAAC;AAQD,SAAgB,mBAAmB,CAAC,UAAe;IACjD,OAAO;QACL,GAAG,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YACtC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,KAAK,EAAE,CAAC,OAAY,EAAE,KAAc,EAAE,OAAgB,EAAE,EAAE;YACxD,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YACvC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,KAAK,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YACxC,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YAC1C,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":";;AASA,4CAaC;AAQD,kDAkBC;AA/CD,+BAA4B;AAQ5B,SAAgB,gBAAgB,CAAC,WAAkB;IACjD,OAAO,IAAA,WAAI,EAAC;QACV,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;QACtC,SAAS,EAAE;YACT,MAAM,EAAE,aAAa;YACrB,OAAO,EAAE;gBACP,WAAW;gBACX,QAAQ,EAAE,IAAI;gBACd,aAAa,EAAE,YAAY;gBAC3B,MAAM,EAAE,cAAc;aACvB;SACF;KACF,CAAC,CAAC;AACL,CAAC;AAQD,SAAgB,mBAAmB,CAAC,UAAe;IACjD,OAAO;QACL,GAAG,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YACtC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,KAAK,EAAE,CAAC,OAAY,EAAE,KAAc,EAAE,OAAgB,EAAE,EAAE;YACxD,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YACvC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACxC,CAAC;QACD,KAAK,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YACxC,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,EAAE,CAAC,OAAY,EAAE,OAAgB,EAAE,EAAE;YAC1C,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACzC,CAAC;KACF,CAAC;AACJ,CAAC"}
package/dist/cli.d.ts CHANGED
@@ -3,10 +3,7 @@ export interface CliOptions {
3
3
  host: string;
4
4
  ankiConnect: string;
5
5
  ngrok: boolean;
6
- login: string | boolean;
7
- logout: boolean;
8
- tunnel: string | boolean;
9
- debug: boolean;
6
+ readOnly: boolean;
10
7
  }
11
8
  export declare function checkForUpdates(): void;
12
9
  export declare function parseCliArgs(): CliOptions;
package/dist/cli.js CHANGED
@@ -10,8 +10,6 @@ const commander_1 = require("commander");
10
10
  const fs_1 = require("fs");
11
11
  const path_1 = require("path");
12
12
  const update_notifier_1 = __importDefault(require("update-notifier"));
13
- const cli_output_1 = require("./cli/cli-output");
14
- const version_1 = require("./version");
15
13
  function getPackageJson() {
16
14
  try {
17
15
  return JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, "../package.json"), "utf-8"));
@@ -20,6 +18,9 @@ function getPackageJson() {
20
18
  return { version: "0.0.0", name: "ankimcp" };
21
19
  }
22
20
  }
21
+ function getVersion() {
22
+ return getPackageJson().version;
23
+ }
23
24
  function checkForUpdates() {
24
25
  (0, update_notifier_1.default)({ pkg: getPackageJson() }).notify();
25
26
  }
@@ -28,16 +29,13 @@ function parseCliArgs() {
28
29
  program
29
30
  .name("ankimcp")
30
31
  .description("AnkiMCP Server - Model Context Protocol server for Anki")
31
- .version((0, version_1.getVersion)())
32
+ .version(getVersion())
32
33
  .option("--stdio", "Run in STDIO mode (for MCP clients like Cursor, Cline, Zed)")
33
34
  .option("-p, --port <number>", "Port to listen on (HTTP mode)", "3000")
34
35
  .option("-h, --host <address>", "Host to bind to (HTTP mode)", "127.0.0.1")
35
36
  .option("-a, --anki-connect <url>", "AnkiConnect URL", "http://localhost:8765")
36
37
  .option("--ngrok", "Start ngrok tunnel (requires global ngrok installation)")
37
- .option("--login [url]", "Authenticate with tunnel service")
38
- .option("--logout", "Clear tunnel credentials")
39
- .option("--tunnel [url]", "Connect to tunnel server (default: ws://localhost:3004/tunnel)")
40
- .option("-d, --debug", "Enable debug logging (shows stack traces)")
38
+ .option("--read-only", "Run in read-only mode (blocks all write operations)")
41
39
  .addHelpText("after", `
42
40
  Transport Modes:
43
41
  HTTP Mode (default): For web-based AI assistants (ChatGPT, Claude.ai)
@@ -67,18 +65,15 @@ Examples - STDIO Mode:
67
65
  }
68
66
  }
69
67
 
68
+ Examples - Read-Only Mode:
69
+ $ ankimcp --read-only # HTTP mode, read-only
70
+ $ ankimcp --stdio --read-only # STDIO mode, read-only
71
+
70
72
  Ngrok Setup (one-time):
71
73
  1. Install: npm install -g ngrok
72
74
  2. Get auth token from: https://dashboard.ngrok.com/get-started/your-authtoken
73
75
  3. Setup: ngrok config add-authtoken <your-token>
74
76
  4. Run: ankimcp --ngrok
75
-
76
- Tunnel Mode:
77
- $ ankimcp --login # Login to default tunnel service
78
- $ ankimcp --login wss://custom.server.com/tunnel # Login to custom server
79
- $ ankimcp --logout # Clear saved credentials
80
- $ ankimcp --tunnel # Connect to localhost:3004
81
- $ ankimcp --tunnel wss://tunnel.ankimcp.ai/tunnel # Production tunnel
82
77
  `);
83
78
  program.parse();
84
79
  const options = program.opts();
@@ -87,30 +82,30 @@ Tunnel Mode:
87
82
  host: options.host,
88
83
  ankiConnect: options.ankiConnect,
89
84
  ngrok: options.ngrok || false,
90
- login: options.login ?? false,
91
- logout: options.logout || false,
92
- tunnel: options.tunnel ?? false,
93
- debug: options.debug || false,
85
+ readOnly: options.readOnly || false,
94
86
  };
95
87
  }
96
88
  function displayStartupBanner(options, ngrokUrl) {
97
- const version = (0, version_1.getVersion)();
89
+ const version = getVersion();
98
90
  const title = `AnkiMCP HTTP Server v${version}`;
99
91
  const padding = Math.floor((64 - title.length) / 2);
100
92
  const paddedTitle = " ".repeat(padding) + title + " ".repeat(64 - padding - title.length);
101
- cli_output_1.cli.info(`
93
+ const readOnlyWarning = options.readOnly
94
+ ? "\n\n** READ-ONLY MODE ENABLED **\nContent modifications (addNote, deleteNotes, createDeck, etc.) are blocked.\nReview operations (sync, answerCards, suspend) remain available."
95
+ : "";
96
+ console.log(`
102
97
  ╔════════════════════════════════════════════════════════════════╗
103
98
  ║${paddedTitle}║
104
- ╚════════════════════════════════════════════════════════════════╝
99
+ ╚════════════════════════════════════════════════════════════════╝${readOnlyWarning}
105
100
 
106
101
  🚀 Server running on: http://${options.host}:${options.port}
107
- 🔌 AnkiConnect URL: ${options.ankiConnect}${ngrokUrl ? `\n🌐 Ngrok tunnel: ${ngrokUrl}` : ""}
102
+ 🔌 AnkiConnect URL: ${options.ankiConnect}${ngrokUrl ? `\n🌐 Ngrok tunnel: ${ngrokUrl}` : ""}${options.readOnly ? "\n🔒 Mode: Read-only" : ""}
108
103
 
109
104
  Configuration:
110
105
  • Port: ${options.port} (override: --port 8080)
111
106
  • Host: ${options.host} (override: --host 0.0.0.0)
112
107
  • AnkiConnect: ${options.ankiConnect}
113
- (override: --anki-connect http://localhost:8765)${ngrokUrl ? `\n • Ngrok tunnel: ${ngrokUrl}\n • Ngrok dashboard: http://localhost:4040` : ""}
108
+ (override: --anki-connect http://localhost:8765)${options.readOnly ? "\n • Read-only: Yes (write operations blocked)" : ""}${ngrokUrl ? `\n • Ngrok tunnel: ${ngrokUrl}\n • Ngrok dashboard: http://localhost:4040` : ""}
114
109
  ${!ngrokUrl
115
110
  ? `
116
111
  Usage with ngrok:
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  import { CanActivate, ExecutionContext } from "@nestjs/common";
2
2
  export declare class OriginValidationGuard implements CanActivate {
3
- private readonly logger;
4
3
  private readonly allowedOrigins;
5
4
  constructor();
6
5
  canActivate(context: ExecutionContext): boolean;
@@ -8,12 +8,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
10
  };
11
- var OriginValidationGuard_1;
12
11
  Object.defineProperty(exports, "__esModule", { value: true });
13
12
  exports.OriginValidationGuard = void 0;
14
13
  const common_1 = require("@nestjs/common");
15
- let OriginValidationGuard = OriginValidationGuard_1 = class OriginValidationGuard {
16
- logger = new common_1.Logger(OriginValidationGuard_1.name);
14
+ let OriginValidationGuard = class OriginValidationGuard {
17
15
  allowedOrigins;
18
16
  constructor() {
19
17
  const defaultOrigins = "http://localhost:*,http://127.0.0.1:*,https://localhost:*,https://127.0.0.1:*";
@@ -28,7 +26,7 @@ let OriginValidationGuard = OriginValidationGuard_1 = class OriginValidationGuar
28
26
  }
29
27
  const isAllowed = this.allowedOrigins.some((allowedOrigin) => this.matchesPattern(origin, allowedOrigin));
30
28
  if (!isAllowed) {
31
- this.logger.warn(`Rejected request from unauthorized origin: ${origin}`);
29
+ console.warn(`[OriginValidationGuard] Rejected request from unauthorized origin: ${origin}`);
32
30
  }
33
31
  return isAllowed;
34
32
  }
@@ -47,7 +45,7 @@ let OriginValidationGuard = OriginValidationGuard_1 = class OriginValidationGuar
47
45
  }
48
46
  };
49
47
  exports.OriginValidationGuard = OriginValidationGuard;
50
- exports.OriginValidationGuard = OriginValidationGuard = OriginValidationGuard_1 = __decorate([
48
+ exports.OriginValidationGuard = OriginValidationGuard = __decorate([
51
49
  (0, common_1.Injectable)(),
52
50
  __metadata("design:paramtypes", [])
53
51
  ], OriginValidationGuard);
@@ -1 +1 @@
1
- {"version":3,"file":"origin-validation.guard.js","sourceRoot":"","sources":["../../../src/http/guards/origin-validation.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAKwB;AAiBjB,IAAM,qBAAqB,6BAA3B,MAAM,qBAAqB;IACf,MAAM,GAAG,IAAI,eAAM,CAAC,uBAAqB,CAAC,IAAI,CAAC,CAAC;IAChD,cAAc,CAAW;IAE1C;QACE,MAAM,cAAc,GAClB,+EAA+E,CAAC;QAClF,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,cAAc,CAAC;QACjE,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,WAAW,CAAC,OAAyB;QACnC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAW,CAAC;QAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QAGjE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QAGD,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,EAAE,CAC3D,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC,CAC3C,CAAC;QAEF,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,8CAA8C,MAAM,EAAE,CAAC,CAAC;QAC3E,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IASO,cAAc,CAAC,MAAc,EAAE,OAAe;QAEpD,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAGD,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,YAAY,GAAG,OAAO;iBACzB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;iBACrB,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YACxB,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,YAAY,GAAG,CAAC,CAAC;YAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF,CAAA;AAxDY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,mBAAU,GAAE;;GACA,qBAAqB,CAwDjC"}
1
+ {"version":3,"file":"origin-validation.guard.js","sourceRoot":"","sources":["../../../src/http/guards/origin-validation.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA2E;AAiBpE,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IACf,cAAc,CAAW;IAE1C;QACE,MAAM,cAAc,GAClB,+EAA+E,CAAC;QAClF,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,cAAc,CAAC;QACjE,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,WAAW,CAAC,OAAyB;QACnC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAW,CAAC;QAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QAGjE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QAGD,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,EAAE,CAC3D,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC,CAC3C,CAAC;QAEF,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CACV,sEAAsE,MAAM,EAAE,CAC/E,CAAC;QACJ,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IASO,cAAc,CAAC,MAAc,EAAE,OAAe;QAEpD,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAGD,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,YAAY,GAAG,OAAO;iBACzB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;iBACrB,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YACxB,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,YAAY,GAAG,CAAC,CAAC;YAC9C,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF,CAAA;AAzDY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,mBAAU,GAAE;;GACA,qBAAqB,CAyDjC"}