@one-source/api-mcp 1.0.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 (167) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +147 -0
  3. package/dist/analytics.d.ts +53 -0
  4. package/dist/analytics.d.ts.map +1 -0
  5. package/dist/analytics.fix-verification.test.d.ts +11 -0
  6. package/dist/analytics.fix-verification.test.d.ts.map +1 -0
  7. package/dist/analytics.fix-verification.test.js +146 -0
  8. package/dist/analytics.fix-verification.test.js.map +1 -0
  9. package/dist/analytics.js +126 -0
  10. package/dist/analytics.js.map +1 -0
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +144 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/client.d.ts +52 -0
  16. package/dist/client.d.ts.map +1 -0
  17. package/dist/client.js +126 -0
  18. package/dist/client.js.map +1 -0
  19. package/dist/create-server.d.ts +28 -0
  20. package/dist/create-server.d.ts.map +1 -0
  21. package/dist/create-server.js +133 -0
  22. package/dist/create-server.js.map +1 -0
  23. package/dist/tools/chain/contract-code.d.ts +6 -0
  24. package/dist/tools/chain/contract-code.d.ts.map +1 -0
  25. package/dist/tools/chain/contract-code.js +19 -0
  26. package/dist/tools/chain/contract-code.js.map +1 -0
  27. package/dist/tools/chain/ens-resolve.d.ts +3 -0
  28. package/dist/tools/chain/ens-resolve.d.ts.map +1 -0
  29. package/dist/tools/chain/ens-resolve.js +25 -0
  30. package/dist/tools/chain/ens-resolve.js.map +1 -0
  31. package/dist/tools/chain/estimate-gas.d.ts +6 -0
  32. package/dist/tools/chain/estimate-gas.d.ts.map +1 -0
  33. package/dist/tools/chain/estimate-gas.js +31 -0
  34. package/dist/tools/chain/estimate-gas.js.map +1 -0
  35. package/dist/tools/chain/network-info.d.ts +6 -0
  36. package/dist/tools/chain/network-info.d.ts.map +1 -0
  37. package/dist/tools/chain/network-info.js +18 -0
  38. package/dist/tools/chain/network-info.js.map +1 -0
  39. package/dist/tools/chain/nonce.d.ts +6 -0
  40. package/dist/tools/chain/nonce.d.ts.map +1 -0
  41. package/dist/tools/chain/nonce.js +19 -0
  42. package/dist/tools/chain/nonce.js.map +1 -0
  43. package/dist/tools/chain/pending-block.d.ts +6 -0
  44. package/dist/tools/chain/pending-block.d.ts.map +1 -0
  45. package/dist/tools/chain/pending-block.js +18 -0
  46. package/dist/tools/chain/pending-block.js.map +1 -0
  47. package/dist/tools/chain/proxy-detect.d.ts +6 -0
  48. package/dist/tools/chain/proxy-detect.d.ts.map +1 -0
  49. package/dist/tools/chain/proxy-detect.js +19 -0
  50. package/dist/tools/chain/proxy-detect.js.map +1 -0
  51. package/dist/tools/chain/simulate-call.d.ts +6 -0
  52. package/dist/tools/chain/simulate-call.d.ts.map +1 -0
  53. package/dist/tools/chain/simulate-call.js +33 -0
  54. package/dist/tools/chain/simulate-call.js.map +1 -0
  55. package/dist/tools/chain/storage-read.d.ts +3 -0
  56. package/dist/tools/chain/storage-read.d.ts.map +1 -0
  57. package/dist/tools/chain/storage-read.js +22 -0
  58. package/dist/tools/chain/storage-read.js.map +1 -0
  59. package/dist/tools/chain/tx-receipt.d.ts +6 -0
  60. package/dist/tools/chain/tx-receipt.d.ts.map +1 -0
  61. package/dist/tools/chain/tx-receipt.js +18 -0
  62. package/dist/tools/chain/tx-receipt.js.map +1 -0
  63. package/dist/tools/index.d.ts +7 -0
  64. package/dist/tools/index.d.ts.map +1 -0
  65. package/dist/tools/index.js +77 -0
  66. package/dist/tools/index.js.map +1 -0
  67. package/dist/tools/indexed/address-txs.d.ts +6 -0
  68. package/dist/tools/indexed/address-txs.d.ts.map +1 -0
  69. package/dist/tools/indexed/address-txs.js +25 -0
  70. package/dist/tools/indexed/address-txs.js.map +1 -0
  71. package/dist/tools/indexed/block.d.ts +3 -0
  72. package/dist/tools/indexed/block.d.ts.map +1 -0
  73. package/dist/tools/indexed/block.js +23 -0
  74. package/dist/tools/indexed/block.js.map +1 -0
  75. package/dist/tools/indexed/contract-info.d.ts +6 -0
  76. package/dist/tools/indexed/contract-info.d.ts.map +1 -0
  77. package/dist/tools/indexed/contract-info.js +18 -0
  78. package/dist/tools/indexed/contract-info.js.map +1 -0
  79. package/dist/tools/indexed/erc1155-balance.d.ts +6 -0
  80. package/dist/tools/indexed/erc1155-balance.d.ts.map +1 -0
  81. package/dist/tools/indexed/erc1155-balance.js +24 -0
  82. package/dist/tools/indexed/erc1155-balance.js.map +1 -0
  83. package/dist/tools/indexed/erc20-balance.d.ts +6 -0
  84. package/dist/tools/indexed/erc20-balance.d.ts.map +1 -0
  85. package/dist/tools/indexed/erc20-balance.js +22 -0
  86. package/dist/tools/indexed/erc20-balance.js.map +1 -0
  87. package/dist/tools/indexed/erc20-transfers.d.ts +6 -0
  88. package/dist/tools/indexed/erc20-transfers.d.ts.map +1 -0
  89. package/dist/tools/indexed/erc20-transfers.js +24 -0
  90. package/dist/tools/indexed/erc20-transfers.js.map +1 -0
  91. package/dist/tools/indexed/events.d.ts +3 -0
  92. package/dist/tools/indexed/events.d.ts.map +1 -0
  93. package/dist/tools/indexed/events.js +32 -0
  94. package/dist/tools/indexed/events.js.map +1 -0
  95. package/dist/tools/indexed/nft-media.d.ts +6 -0
  96. package/dist/tools/indexed/nft-media.d.ts.map +1 -0
  97. package/dist/tools/indexed/nft-media.js +22 -0
  98. package/dist/tools/indexed/nft-media.js.map +1 -0
  99. package/dist/tools/indexed/nft-metadata.d.ts +6 -0
  100. package/dist/tools/indexed/nft-metadata.d.ts.map +1 -0
  101. package/dist/tools/indexed/nft-metadata.js +22 -0
  102. package/dist/tools/indexed/nft-metadata.js.map +1 -0
  103. package/dist/tools/indexed/nft-owner.d.ts +6 -0
  104. package/dist/tools/indexed/nft-owner.d.ts.map +1 -0
  105. package/dist/tools/indexed/nft-owner.js +22 -0
  106. package/dist/tools/indexed/nft-owner.js.map +1 -0
  107. package/dist/tools/indexed/tx-details.d.ts +6 -0
  108. package/dist/tools/indexed/tx-details.d.ts.map +1 -0
  109. package/dist/tools/indexed/tx-details.js +19 -0
  110. package/dist/tools/indexed/tx-details.js.map +1 -0
  111. package/dist/tools/indexed/wallet-nfts.d.ts +6 -0
  112. package/dist/tools/indexed/wallet-nfts.d.ts.map +1 -0
  113. package/dist/tools/indexed/wallet-nfts.js +22 -0
  114. package/dist/tools/indexed/wallet-nfts.js.map +1 -0
  115. package/dist/tools/live/allowance.d.ts +6 -0
  116. package/dist/tools/live/allowance.d.ts.map +1 -0
  117. package/dist/tools/live/allowance.js +24 -0
  118. package/dist/tools/live/allowance.js.map +1 -0
  119. package/dist/tools/live/contract-info.d.ts +6 -0
  120. package/dist/tools/live/contract-info.d.ts.map +1 -0
  121. package/dist/tools/live/contract-info.js +19 -0
  122. package/dist/tools/live/contract-info.js.map +1 -0
  123. package/dist/tools/live/erc1155-balance.d.ts +6 -0
  124. package/dist/tools/live/erc1155-balance.d.ts.map +1 -0
  125. package/dist/tools/live/erc1155-balance.js +24 -0
  126. package/dist/tools/live/erc1155-balance.js.map +1 -0
  127. package/dist/tools/live/erc20-balance.d.ts +6 -0
  128. package/dist/tools/live/erc20-balance.d.ts.map +1 -0
  129. package/dist/tools/live/erc20-balance.js +22 -0
  130. package/dist/tools/live/erc20-balance.js.map +1 -0
  131. package/dist/tools/live/erc20-transfers.d.ts +3 -0
  132. package/dist/tools/live/erc20-transfers.d.ts.map +1 -0
  133. package/dist/tools/live/erc20-transfers.js +26 -0
  134. package/dist/tools/live/erc20-transfers.js.map +1 -0
  135. package/dist/tools/live/erc721-tokens.d.ts +6 -0
  136. package/dist/tools/live/erc721-tokens.d.ts.map +1 -0
  137. package/dist/tools/live/erc721-tokens.js +22 -0
  138. package/dist/tools/live/erc721-tokens.js.map +1 -0
  139. package/dist/tools/live/events.d.ts +3 -0
  140. package/dist/tools/live/events.d.ts.map +1 -0
  141. package/dist/tools/live/events.js +26 -0
  142. package/dist/tools/live/events.js.map +1 -0
  143. package/dist/tools/live/multi-balance.d.ts +3 -0
  144. package/dist/tools/live/multi-balance.d.ts.map +1 -0
  145. package/dist/tools/live/multi-balance.js +26 -0
  146. package/dist/tools/live/multi-balance.js.map +1 -0
  147. package/dist/tools/live/nft-metadata.d.ts +6 -0
  148. package/dist/tools/live/nft-metadata.d.ts.map +1 -0
  149. package/dist/tools/live/nft-metadata.js +22 -0
  150. package/dist/tools/live/nft-metadata.js.map +1 -0
  151. package/dist/tools/live/nft-owner.d.ts +6 -0
  152. package/dist/tools/live/nft-owner.d.ts.map +1 -0
  153. package/dist/tools/live/nft-owner.js +22 -0
  154. package/dist/tools/live/nft-owner.js.map +1 -0
  155. package/dist/tools/live/total-supply.d.ts +6 -0
  156. package/dist/tools/live/total-supply.d.ts.map +1 -0
  157. package/dist/tools/live/total-supply.js +20 -0
  158. package/dist/tools/live/total-supply.js.map +1 -0
  159. package/dist/tools/live/tx-details.d.ts +6 -0
  160. package/dist/tools/live/tx-details.d.ts.map +1 -0
  161. package/dist/tools/live/tx-details.js +19 -0
  162. package/dist/tools/live/tx-details.js.map +1 -0
  163. package/dist/types.d.ts +74 -0
  164. package/dist/types.d.ts.map +1 -0
  165. package/dist/types.js +86 -0
  166. package/dist/types.js.map +1 -0
  167. package/package.json +64 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 BlockParty
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,147 @@
1
+ # onesource-api-mcp
2
+
3
+ MCP server for OneSource blockchain data. 34 named tools for balances, NFTs, transactions, events, and live chain queries via x402 micropayments.
4
+
5
+ ```
6
+ npx onesource-api-mcp
7
+ ```
8
+
9
+ ## Install
10
+
11
+ ```sh
12
+ # Claude Code
13
+ claude mcp add onesource-api -- npx onesource-api-mcp
14
+
15
+ # Claude Desktop / Cursor — add to MCP config:
16
+ {
17
+ "mcpServers": {
18
+ "onesource-api": {
19
+ "command": "npx",
20
+ "args": ["-y", "onesource-api-mcp"]
21
+ }
22
+ }
23
+ }
24
+ ```
25
+
26
+ ## Tools (34)
27
+
28
+ ### Indexed Data (12 tools) — OpenSearch, cheaper, slight sync delay
29
+
30
+ | Tool | Description |
31
+ |------|-------------|
32
+ | `1s_address_txs` | Address transaction history |
33
+ | `1s_block` | Block details by number |
34
+ | `1s_contract_info` | Contract metadata |
35
+ | `1s_erc1155_balance` | ERC1155 token balance |
36
+ | `1s_erc20_balance` | ERC20 token balance |
37
+ | `1s_erc20_transfers` | ERC20 transfer history |
38
+ | `1s_events` | Event log search |
39
+ | `1s_nft_media` | NFT processed media URLs |
40
+ | `1s_nft_metadata` | NFT metadata and traits |
41
+ | `1s_nft_owner` | NFT current owner |
42
+ | `1s_tx_details` | Transaction with decoded events |
43
+ | `1s_wallet_nfts` | Wallet NFT portfolio |
44
+
45
+ ### Live Chain Data (12 tools) — Direct RPC, real-time
46
+
47
+ | Tool | Description |
48
+ |------|-------------|
49
+ | `1s_allowance_live` | ERC20 allowance check |
50
+ | `1s_contract_info_live` | Contract type detection via ERC165 |
51
+ | `1s_erc1155_balance_live` | ERC1155 balance via RPC |
52
+ | `1s_erc20_balance_live` | ERC20 balance via balanceOf |
53
+ | `1s_erc20_transfers_live` | ERC20 Transfer logs via eth_getLogs |
54
+ | `1s_erc721_tokens_live` | ERC721 token enumeration |
55
+ | `1s_events_live` | Event logs via eth_getLogs |
56
+ | `1s_multi_balance_live` | ETH + multiple ERC20 balances |
57
+ | `1s_nft_metadata_live` | NFT metadata via tokenURI |
58
+ | `1s_nft_owner_live` | NFT owner via ownerOf |
59
+ | `1s_total_supply_live` | Token total supply |
60
+ | `1s_tx_details_live` | Transaction + receipt via RPC |
61
+
62
+ ### Chain Utilities (10 tools) — RPC only
63
+
64
+ | Tool | Description |
65
+ |------|-------------|
66
+ | `1s_contract_code` | Contract bytecode |
67
+ | `1s_ens_resolve` | ENS name/address resolution |
68
+ | `1s_estimate_gas` | Gas estimation |
69
+ | `1s_network_info` | Chain ID, block number, gas price |
70
+ | `1s_nonce` | Transaction count |
71
+ | `1s_pending_block` | Pending block from mempool |
72
+ | `1s_proxy_detect` | Proxy contract detection |
73
+ | `1s_simulate_call` | Simulate eth_call |
74
+ | `1s_storage_read` | Read storage slot |
75
+ | `1s_tx_receipt` | Transaction receipt |
76
+
77
+ ## Networks
78
+
79
+ All tools accept an optional `network` parameter:
80
+
81
+ | Network | Description |
82
+ |---------|-------------|
83
+ | `ethereum` | Ethereum mainnet (default) |
84
+ | `sepolia` | Ethereum Sepolia testnet |
85
+ | `avax` | Avalanche C-Chain |
86
+
87
+ ## Payment (x402)
88
+
89
+ Endpoints are priced in USDC on Base via [x402](https://github.com/coinbase/x402). When the backend has payments enabled, tool calls return a 402 with payment details. Agents using [`@x402/fetch`](https://www.npmjs.com/package/@x402/fetch) handle this automatically.
90
+
91
+ ## Configuration
92
+
93
+ | Variable | Default | Description |
94
+ |----------|---------|-------------|
95
+ | `ONESOURCE_BASE_URL` | `https://skills.onesource.io` | Skills API endpoint |
96
+ | `ONESOURCE_ANALYTICS` | `true` | Set `false` to disable analytics |
97
+ | `ONESOURCE_ANALYTICS_URL` | — | Dashboard endpoint for event ingestion |
98
+ | `ONESOURCE_ANALYTICS_KEY` | — | API key for the analytics dashboard |
99
+
100
+ ## Transport Modes
101
+
102
+ ```sh
103
+ # stdio (default — for MCP clients)
104
+ npx onesource-api-mcp
105
+
106
+ # HTTP (for testing or remote access)
107
+ npx onesource-api-mcp --http
108
+ npx onesource-api-mcp --http --port=8080
109
+ ```
110
+
111
+ HTTP mode binds to `127.0.0.1` by default.
112
+
113
+ ## Adding a New Tool
114
+
115
+ When a new SKILL.md is added to `skills/OneSource*/`, a corresponding MCP tool file needs to be created here.
116
+
117
+ **Step 1:** Create the SKILL.md in the skills repo (see the skills README for format).
118
+
119
+ **Step 2:** Scaffold the tool file:
120
+
121
+ ```sh
122
+ cd mcp/
123
+ npm run new-tool
124
+ ```
125
+
126
+ This prompts for:
127
+ - **Tool name** — `1s_` prefix, snake_case (e.g. `1s_token_info`)
128
+ - **Category** — `indexed` (OpenSearch), `live` (RPC with indexed counterpart), or `chain` (RPC-only utility)
129
+ - **Description** — one-liner for the tool
130
+ - **Endpoint** — REST API path (e.g. `/api/chain/my-endpoint`)
131
+ - **Method** — GET or POST
132
+
133
+ It generates a tool file in `src/tools/{category}/` with TODO markers.
134
+
135
+ **Step 3:** Edit the generated file — fill in the Zod schema parameters and handler logic. Use the shared params from `src/types.ts` (`addressParam`, `txHashParam`, `tokenIdParam`, `hexDataParam`, `networkParam`, `limitParam`, `blockNumberParam`).
136
+
137
+ **Step 4:** Build:
138
+
139
+ ```sh
140
+ npm run build
141
+ ```
142
+
143
+ This auto-regenerates the tool index and compiles. The new tool is immediately available in the MCP server.
144
+
145
+ ## License
146
+
147
+ MIT
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Analytics instrumentation for the MCP server.
3
+ *
4
+ * Three modes (selected via env vars):
5
+ * - NoopAnalytics: ONESOURCE_ANALYTICS=false
6
+ * - StderrAnalytics: default (structured JSON to stderr)
7
+ * - DashboardAnalytics: ONESOURCE_ANALYTICS_URL is set (POSTs to dashboard)
8
+ */
9
+ export interface ToolCallEvent {
10
+ type: 'tool_call';
11
+ service: string;
12
+ tool: string;
13
+ category: 'indexed' | 'live' | 'chain';
14
+ timestamp: string;
15
+ duration_ms: number;
16
+ success: boolean;
17
+ error_category?: string;
18
+ network?: string;
19
+ input_params: string[];
20
+ response_size: number;
21
+ version: string;
22
+ auth_method: 'x402' | 'none';
23
+ client_name?: string;
24
+ client_version?: string;
25
+ session_id?: string;
26
+ transport?: 'stdio' | 'http';
27
+ }
28
+ export interface HttpCallEvent {
29
+ type: 'http_call';
30
+ service: string;
31
+ tool: string;
32
+ http_status: number;
33
+ backend_latency_ms: number;
34
+ x402_required: boolean;
35
+ timestamp: string;
36
+ session_id?: string;
37
+ }
38
+ export interface ServiceEvent {
39
+ type: 'service_start' | 'service_stop' | 'service_error';
40
+ service: string;
41
+ timestamp: string;
42
+ version: string;
43
+ details?: string;
44
+ }
45
+ export interface Analytics {
46
+ trackTool(event: ToolCallEvent): void;
47
+ trackHttp(event: HttpCallEvent): void;
48
+ trackService(event: ServiceEvent): void;
49
+ flush(): Promise<void>;
50
+ stop(): void;
51
+ }
52
+ export declare function createAnalytics(): Analytics;
53
+ //# sourceMappingURL=analytics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,eAAe,GAAG,cAAc,GAAG,eAAe,CAAC;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACtC,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACtC,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IACxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,IAAI,CAAC;CACd;AAkHD,wBAAgB,eAAe,IAAI,SAAS,CAY3C"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Verification tests for DashboardAnalytics bug fixes:
3
+ *
4
+ * 1. Event preservation — events are restored to the buffer when flush fails,
5
+ * so they can be retried on the next flush.
6
+ *
7
+ * 2. Flush timeout — flush() aborts after 3s via AbortSignal.timeout,
8
+ * so shutdown never hangs indefinitely.
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=analytics.fix-verification.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.fix-verification.test.d.ts","sourceRoot":"","sources":["../src/analytics.fix-verification.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Verification tests for DashboardAnalytics bug fixes:
3
+ *
4
+ * 1. Event preservation — events are restored to the buffer when flush fails,
5
+ * so they can be retried on the next flush.
6
+ *
7
+ * 2. Flush timeout — flush() aborts after 3s via AbortSignal.timeout,
8
+ * so shutdown never hangs indefinitely.
9
+ */
10
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
11
+ import { createAnalytics } from './analytics.js';
12
+ // ---------------------------------------------------------------------------
13
+ // Helpers
14
+ // ---------------------------------------------------------------------------
15
+ function makeToolEvent(overrides = {}) {
16
+ return {
17
+ type: 'tool_call',
18
+ service: 'mcp',
19
+ tool: 'test-tool',
20
+ category: 'indexed',
21
+ timestamp: new Date().toISOString(),
22
+ duration_ms: 50,
23
+ success: true,
24
+ input_params: [],
25
+ response_size: 128,
26
+ version: '1.0.0',
27
+ auth_method: 'none',
28
+ ...overrides,
29
+ };
30
+ }
31
+ // Drain the microtask queue — works regardless of timer mode.
32
+ const drainMicrotasks = async () => {
33
+ for (let i = 0; i < 5; i++)
34
+ await Promise.resolve();
35
+ };
36
+ // ---------------------------------------------------------------------------
37
+ // Setup: point createAnalytics() at DashboardAnalytics via env vars
38
+ // ---------------------------------------------------------------------------
39
+ beforeEach(() => {
40
+ process.env.ONESOURCE_ANALYTICS_URL = 'http://analytics.test';
41
+ process.env.ONESOURCE_ANALYTICS_KEY = 'test-key';
42
+ vi.spyOn(global, 'fetch');
43
+ });
44
+ afterEach(() => {
45
+ delete process.env.ONESOURCE_ANALYTICS_URL;
46
+ delete process.env.ONESOURCE_ANALYTICS_KEY;
47
+ vi.restoreAllMocks();
48
+ });
49
+ // ---------------------------------------------------------------------------
50
+ // Fix 1: Events preserved on network failure
51
+ // ---------------------------------------------------------------------------
52
+ describe('Event preservation on network failure', () => {
53
+ it('events are restored to buffer on failure and retried on next flush', async () => {
54
+ vi.mocked(global.fetch).mockRejectedValue(new Error('Network failure'));
55
+ const analytics = createAnalytics();
56
+ for (let i = 0; i < 10; i++) {
57
+ analytics.trackTool(makeToolEvent());
58
+ }
59
+ // Let the auto-triggered flush run: splice(0) removes events, fetch rejects,
60
+ // catch restores them to the buffer via unshift.
61
+ await drainMicrotasks();
62
+ expect(global.fetch).toHaveBeenCalledOnce();
63
+ // Network is healthy again
64
+ vi.mocked(global.fetch).mockResolvedValue(new Response(JSON.stringify({ ok: true }), { status: 200 }));
65
+ // Manually flush — the 10 events were preserved and are now sent
66
+ await analytics.flush();
67
+ // fetch called twice — once failed, once succeeded with the restored events
68
+ expect(global.fetch).toHaveBeenCalledTimes(2);
69
+ });
70
+ it('flush-in-progress guard prevents concurrent flushes, events preserved on failure', async () => {
71
+ let rejectFetch;
72
+ vi.mocked(global.fetch).mockImplementation(() => {
73
+ return new Promise((_, reject) => { rejectFetch = reject; });
74
+ });
75
+ const analytics = createAnalytics();
76
+ // First batch of 10 → triggers flush
77
+ for (let i = 0; i < 10; i++) {
78
+ analytics.trackTool(makeToolEvent());
79
+ }
80
+ await drainMicrotasks();
81
+ expect(global.fetch).toHaveBeenCalledOnce();
82
+ // Second batch of 10 arrives while flush is in-flight
83
+ // The flush-in-progress guard means these stay in the buffer —
84
+ // no second concurrent fetch fires
85
+ for (let i = 0; i < 10; i++) {
86
+ analytics.trackTool(makeToolEvent());
87
+ }
88
+ await drainMicrotasks();
89
+ // Still only 1 fetch — guard prevented a concurrent flush
90
+ expect(global.fetch).toHaveBeenCalledOnce();
91
+ // Fail the in-flight request — first 10 events restored via unshift
92
+ rejectFetch(new Error('timeout'));
93
+ await drainMicrotasks();
94
+ // Restore healthy network
95
+ vi.mocked(global.fetch).mockResolvedValue(new Response(JSON.stringify({ ok: true }), { status: 200 }));
96
+ // Flush now sends all 20 events (10 restored + 10 buffered)
97
+ await analytics.flush();
98
+ // 2 calls total — one failed, one succeeded with all 20 events
99
+ expect(global.fetch).toHaveBeenCalledTimes(2);
100
+ });
101
+ });
102
+ // ---------------------------------------------------------------------------
103
+ // Fix 2: Flush timeout prevents shutdown hang
104
+ // ---------------------------------------------------------------------------
105
+ describe('Flush timeout prevents shutdown hang', () => {
106
+ it('flush() resolves within timeout even when fetch hangs', async () => {
107
+ // Mock fetch that respects AbortSignal — hangs until aborted
108
+ vi.mocked(global.fetch).mockImplementation((_url, init) => {
109
+ return new Promise((_, reject) => {
110
+ const signal = init?.signal;
111
+ if (signal) {
112
+ signal.addEventListener('abort', () => reject(signal.reason));
113
+ }
114
+ });
115
+ });
116
+ const analytics = createAnalytics();
117
+ analytics.trackTool(makeToolEvent());
118
+ let flushCompleted = false;
119
+ await Promise.race([
120
+ analytics.flush().then(() => { flushCompleted = true; }),
121
+ // 4s deadline — longer than the 3s AbortSignal.timeout in flush()
122
+ new Promise((resolve) => setTimeout(resolve, 4_000)),
123
+ ]);
124
+ // flush completed because AbortSignal.timeout aborted the hung fetch
125
+ expect(flushCompleted).toBe(true);
126
+ }, 10_000);
127
+ it('a single buffered event does not hang the process on shutdown', async () => {
128
+ vi.mocked(global.fetch).mockImplementation((_url, init) => {
129
+ return new Promise((_, reject) => {
130
+ const signal = init?.signal;
131
+ if (signal) {
132
+ signal.addEventListener('abort', () => reject(signal.reason));
133
+ }
134
+ });
135
+ });
136
+ const analytics = createAnalytics();
137
+ analytics.trackTool(makeToolEvent());
138
+ const result = await Promise.race([
139
+ analytics.flush().then(() => 'completed'),
140
+ new Promise((resolve) => setTimeout(() => resolve('timed-out'), 4_000)),
141
+ ]);
142
+ // flush completes (via abort timeout) rather than hanging
143
+ expect(result).toBe('completed');
144
+ }, 10_000);
145
+ });
146
+ //# sourceMappingURL=analytics.fix-verification.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.fix-verification.test.js","sourceRoot":"","sources":["../src/analytics.fix-verification.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGjD,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,aAAa,CAAC,YAAoC,EAAE;IAC3D,OAAO;QACL,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,SAAS;QACnB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,WAAW,EAAE,EAAE;QACf,OAAO,EAAE,IAAI;QACb,YAAY,EAAE,EAAE;QAChB,aAAa,EAAE,GAAG;QAClB,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,MAAM;QACnB,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,8DAA8D;AAC9D,MAAM,eAAe,GAAG,KAAK,IAAI,EAAE;IACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;QAAE,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;AACtD,CAAC,CAAC;AAEF,8EAA8E;AAC9E,oEAAoE;AACpE,8EAA8E;AAE9E,UAAU,CAAC,GAAG,EAAE;IACd,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,uBAAuB,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,UAAU,CAAC;IACjD,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC5B,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,GAAG,EAAE;IACb,OAAO,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IAC3C,OAAO,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IAC3C,EAAE,CAAC,eAAe,EAAE,CAAC;AACvB,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,6CAA6C;AAC7C,8EAA8E;AAE9E,QAAQ,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACrD,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAClF,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAExE,MAAM,SAAS,GAAG,eAAe,EAAE,CAAC;QAEpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,SAAS,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAC;QACvC,CAAC;QAED,6EAA6E;QAC7E,iDAAiD;QACjD,MAAM,eAAe,EAAE,CAAC;QAExB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,oBAAoB,EAAE,CAAC;QAE5C,2BAA2B;QAC3B,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,iBAAiB,CACvC,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAC5D,CAAC;QAEF,iEAAiE;QACjE,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;QAExB,4EAA4E;QAC5E,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kFAAkF,EAAE,KAAK,IAAI,EAAE;QAChG,IAAI,WAAgC,CAAC;QAErC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE;YAC9C,OAAO,IAAI,OAAO,CAAW,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,eAAe,EAAE,CAAC;QAEpC,qCAAqC;QACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,SAAS,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,eAAe,EAAE,CAAC;QACxB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,oBAAoB,EAAE,CAAC;QAE5C,sDAAsD;QACtD,+DAA+D;QAC/D,mCAAmC;QACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,SAAS,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,eAAe,EAAE,CAAC;QACxB,0DAA0D;QAC1D,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,oBAAoB,EAAE,CAAC;QAE5C,oEAAoE;QACpE,WAAW,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QAClC,MAAM,eAAe,EAAE,CAAC;QAExB,0BAA0B;QAC1B,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,iBAAiB,CACvC,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAC5D,CAAC;QAEF,4DAA4D;QAC5D,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;QAExB,+DAA+D;QAC/D,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,8CAA8C;AAC9C,8EAA8E;AAE9E,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACpD,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,6DAA6D;QAC7D,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,kBAAkB,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;YACxD,OAAO,IAAI,OAAO,CAAW,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;gBACzC,MAAM,MAAM,GAAI,IAAoB,EAAE,MAAM,CAAC;gBAC7C,IAAI,MAAM,EAAE,CAAC;oBACX,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;gBAChE,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,eAAe,EAAE,CAAC;QACpC,SAAS,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAC;QAErC,IAAI,cAAc,GAAG,KAAK,CAAC;QAE3B,MAAM,OAAO,CAAC,IAAI,CAAC;YACjB,SAAS,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACxD,kEAAkE;YAClE,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;SAC3D,CAAC,CAAC;QAEH,qEAAqE;QACrE,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,EAAE,MAAM,CAAC,CAAC;IAEX,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,kBAAkB,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;YACxD,OAAO,IAAI,OAAO,CAAW,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;gBACzC,MAAM,MAAM,GAAI,IAAoB,EAAE,MAAM,CAAC;gBAC7C,IAAI,MAAM,EAAE,CAAC;oBACX,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;gBAChE,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,eAAe,EAAE,CAAC;QACpC,SAAS,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAC;QAErC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAChC,SAAS,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC;YACzC,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC,CAAC;SAChF,CAAC,CAAC;QAEH,0DAA0D;QAC1D,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACnC,CAAC,EAAE,MAAM,CAAC,CAAC;AACb,CAAC,CAAC,CAAC"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Analytics instrumentation for the MCP server.
3
+ *
4
+ * Three modes (selected via env vars):
5
+ * - NoopAnalytics: ONESOURCE_ANALYTICS=false
6
+ * - StderrAnalytics: default (structured JSON to stderr)
7
+ * - DashboardAnalytics: ONESOURCE_ANALYTICS_URL is set (POSTs to dashboard)
8
+ */
9
+ // --- Implementations ---
10
+ class NoopAnalytics {
11
+ trackTool() { }
12
+ trackHttp() { }
13
+ trackService() { }
14
+ stop() { }
15
+ async flush() { }
16
+ }
17
+ class StderrAnalytics {
18
+ trackTool(event) {
19
+ console.error(JSON.stringify(event));
20
+ }
21
+ trackHttp(event) {
22
+ console.error(JSON.stringify(event));
23
+ }
24
+ trackService(event) {
25
+ console.error(JSON.stringify(event));
26
+ }
27
+ stop() { }
28
+ async flush() { }
29
+ }
30
+ class DashboardAnalytics {
31
+ static FLUSH_TIMEOUT_MS = 3_000;
32
+ static MAX_BUFFER = 1_000;
33
+ buffer = [];
34
+ flushPromise = null;
35
+ timer = null;
36
+ endpoint;
37
+ apiKey;
38
+ constructor(endpoint, apiKey) {
39
+ const parsed = new URL(endpoint);
40
+ if (!['https:', 'http:'].includes(parsed.protocol)) {
41
+ throw new Error('ONESOURCE_ANALYTICS_URL must use http or https');
42
+ }
43
+ this.endpoint = endpoint.replace(/\/+$/, '');
44
+ this.apiKey = apiKey;
45
+ // Auto-flush every 30 seconds
46
+ this.timer = setInterval(() => { void this.flush(); }, 30_000);
47
+ // Don't keep the process alive just for the flush timer
48
+ if (this.timer.unref)
49
+ this.timer.unref();
50
+ }
51
+ stop() {
52
+ if (this.timer) {
53
+ clearInterval(this.timer);
54
+ this.timer = null;
55
+ }
56
+ }
57
+ trackTool(event) {
58
+ this.buffer.push(event);
59
+ if (this.buffer.length >= 10)
60
+ void this.flush();
61
+ }
62
+ trackHttp(event) {
63
+ this.buffer.push(event);
64
+ if (this.buffer.length >= 10)
65
+ void this.flush();
66
+ }
67
+ trackService(event) {
68
+ this.buffer.push(event);
69
+ }
70
+ async flush() {
71
+ // If a flush is already in-flight, await it instead of racing
72
+ if (this.flushPromise)
73
+ return this.flushPromise;
74
+ if (this.buffer.length === 0)
75
+ return;
76
+ this.flushPromise = this.doFlush();
77
+ try {
78
+ await this.flushPromise;
79
+ }
80
+ finally {
81
+ this.flushPromise = null;
82
+ }
83
+ }
84
+ async doFlush() {
85
+ const events = this.buffer.splice(0);
86
+ try {
87
+ const res = await fetch(`${this.endpoint}/api/events`, {
88
+ method: 'POST',
89
+ headers: {
90
+ 'Content-Type': 'application/json',
91
+ 'Authorization': `Bearer ${this.apiKey}`,
92
+ 'x-402-receipt': this.apiKey,
93
+ },
94
+ body: JSON.stringify({ events }),
95
+ signal: AbortSignal.timeout(DashboardAnalytics.FLUSH_TIMEOUT_MS),
96
+ });
97
+ if (!res.ok) {
98
+ console.error(`[analytics] flush failed: HTTP ${res.status}`);
99
+ this.buffer = events.concat(this.buffer);
100
+ }
101
+ }
102
+ catch {
103
+ console.error(`[analytics] flush failed: ${events.length} events queued for retry`);
104
+ this.buffer = events.concat(this.buffer);
105
+ }
106
+ // Cap buffer to prevent unbounded growth — drop oldest first
107
+ if (this.buffer.length > DashboardAnalytics.MAX_BUFFER) {
108
+ const dropped = this.buffer.length - DashboardAnalytics.MAX_BUFFER;
109
+ this.buffer.splice(0, dropped);
110
+ console.error(`[analytics] buffer full: dropped ${dropped} oldest events`);
111
+ }
112
+ }
113
+ }
114
+ // --- Factory ---
115
+ export function createAnalytics() {
116
+ if (process.env.ONESOURCE_ANALYTICS === 'false') {
117
+ return new NoopAnalytics();
118
+ }
119
+ const url = process.env.ONESOURCE_ANALYTICS_URL?.trim();
120
+ const key = process.env.X402_ANALYTICS_KEY?.trim();
121
+ if (url && key) {
122
+ return new DashboardAnalytics(url, key);
123
+ }
124
+ return new StderrAnalytics();
125
+ }
126
+ //# sourceMappingURL=analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAoKA,OAAO,EAAE,CAAC"}