autoicd-js 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -96,7 +96,6 @@ const result = await autoicd.code(
96
96
  "Patient presents with acute bronchitis and chest pain",
97
97
  {
98
98
  topK: 3, // Top 3 ICD-10 candidates per entity (default: 5)
99
- strategy: "merged", // "individual" or "merged" entity strategy
100
99
  includeNegated: false, // Exclude negated conditions from results
101
100
  }
102
101
  );
@@ -144,6 +143,31 @@ console.log(result.pii_entities); // [{ text: "John Smith", label: "NAME", ... }
144
143
 
145
144
  ---
146
145
 
146
+ ## Common ICD-10 Codes
147
+
148
+ The SDK can code any of the 74,000+ ICD-10-CM codes. Here are some of the most commonly coded conditions:
149
+
150
+ | Condition | ICD-10 Code | Description |
151
+ |-----------|-------------|-------------|
152
+ | [Hypertension](https://autoicdapi.com/icd10/condition/hypertension) | [I10](https://autoicdapi.com/icd10/I10) | Essential (primary) hypertension |
153
+ | [Type 2 Diabetes](https://autoicdapi.com/icd10/condition/diabetes) | [E11.9](https://autoicdapi.com/icd10/E11.9) | Type 2 diabetes mellitus without complications |
154
+ | [Depression](https://autoicdapi.com/icd10/condition/depression) | [F32.9](https://autoicdapi.com/icd10/F32.9) | Major depressive disorder, single episode, unspecified |
155
+ | [Anxiety](https://autoicdapi.com/icd10/condition/anxiety) | [F41.1](https://autoicdapi.com/icd10/F41.1) | Generalized anxiety disorder |
156
+ | [Low Back Pain](https://autoicdapi.com/icd10/condition/back-pain) | [M54.5](https://autoicdapi.com/icd10/M54.5) | Low back pain |
157
+ | [COPD](https://autoicdapi.com/icd10/condition/copd) | [J44.9](https://autoicdapi.com/icd10/J44.9) | Chronic obstructive pulmonary disease, unspecified |
158
+ | [Heart Failure](https://autoicdapi.com/icd10/condition/heart-failure) | [I50.9](https://autoicdapi.com/icd10/I50.9) | Heart failure, unspecified |
159
+ | [UTI](https://autoicdapi.com/icd10/condition/urinary-tract-infection) | [N39.0](https://autoicdapi.com/icd10/N39.0) | Urinary tract infection, site not specified |
160
+ | [Pneumonia](https://autoicdapi.com/icd10/condition/pneumonia) | [J18.9](https://autoicdapi.com/icd10/J18.9) | Pneumonia, unspecified organism |
161
+ | [Atrial Fibrillation](https://autoicdapi.com/icd10/condition/atrial-fibrillation) | [I48.91](https://autoicdapi.com/icd10/I48.91) | Unspecified atrial fibrillation |
162
+ | [Obesity](https://autoicdapi.com/icd10/condition/obesity) | [E66.01](https://autoicdapi.com/icd10/E66.01) | Morbid (severe) obesity due to excess calories |
163
+ | [GERD](https://autoicdapi.com/icd10/condition/gerd) | [K21.9](https://autoicdapi.com/icd10/K21.9) | Gastro-esophageal reflux disease without esophagitis |
164
+ | [Hypothyroidism](https://autoicdapi.com/icd10/condition/hypothyroidism) | [E03.9](https://autoicdapi.com/icd10/E03.9) | Hypothyroidism, unspecified |
165
+ | [CKD](https://autoicdapi.com/icd10/condition/chronic-kidney-disease) | [N18.9](https://autoicdapi.com/icd10/N18.9) | Chronic kidney disease, unspecified |
166
+
167
+ Browse all 74,000+ codes in the [ICD-10-CM Code Directory](https://autoicdapi.com/icd10) or find codes by [condition](https://autoicdapi.com/icd10/condition).
168
+
169
+ ---
170
+
147
171
  ## Use Cases
148
172
 
149
173
  - **EHR / EMR Integration** — Auto-code clinical notes as providers type, reducing manual coding burden
@@ -247,6 +271,11 @@ import type {
247
271
 
248
272
  - [AutoICD API](https://autoicdapi.com) — Homepage and API key management
249
273
  - [API Documentation](https://autoicdapi.com/docs) — Full REST API reference
274
+ - [ICD-10-CM Code Directory](https://autoicdapi.com/icd10) — Browse all 74,000+ diagnosis codes
275
+ - [ICD-10 Codes by Condition](https://autoicdapi.com/icd10/condition) — Find codes for common conditions
276
+ - [Python SDK](https://pypi.org/project/autoicd/) — `pip install autoicd`
277
+ - [MCP Server](https://www.npmjs.com/package/autoicd-mcp) — For Claude Desktop, Cursor, VS Code
278
+ - [SNOMED CT & UMLS Cross-References](https://autoicdapi.com/snomed-ct-umls) — Terminology mappings
250
279
  - [ICD-10-CM 2025 Code Set](https://www.cms.gov/medicare/coding-billing/icd-10-codes) — Official CMS reference
251
280
 
252
281
  ---
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "autoicd-js",
3
- "version": "0.3.0",
4
- "description": "ICD-10 medical coding SDK — convert clinical text to ICD-10-CM diagnosis codes with AI-powered NLP. Automated medical coding, PHI de-identification, and ICD-10 code search for EHR, billing, and health-tech apps.",
3
+ "version": "0.5.0",
4
+ "description": "ICD-10 & ICD-11 medical coding SDK — convert clinical text to ICD-10-CM and ICD-11 diagnosis codes with AI-powered NLP. Automated medical coding, PHI de-identification, code search, and ICD-10/ICD-11 crosswalk for EHR, billing, and health-tech apps.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
@@ -28,6 +28,10 @@
28
28
  "icd-10",
29
29
  "icd10",
30
30
  "icd-10-cm",
31
+ "icd-10-api",
32
+ "icd-10-lookup",
33
+ "icd-10-search",
34
+ "icd-10-code",
31
35
  "medical-coding",
32
36
  "medical-billing",
33
37
  "clinical-nlp",
@@ -42,6 +46,14 @@
42
46
  "hipaa",
43
47
  "medical-ai",
44
48
  "revenue-cycle-management",
49
+ "snomed-ct",
50
+ "umls",
51
+ "medical-coding-api",
52
+ "code-search",
53
+ "icd-11",
54
+ "icd11",
55
+ "icd-11-api",
56
+ "icd-10-icd-11-crosswalk",
45
57
  "autoicd",
46
58
  "autoicd-api"
47
59
  ],
package/dist/index.d.mts DELETED
@@ -1,224 +0,0 @@
1
- interface AutoICDOptions {
2
- /** API key (starts with `sk_`). */
3
- apiKey: string;
4
- /** Base URL. Defaults to `https://autoicdapi.com`. */
5
- baseURL?: string;
6
- /** Default timeout in milliseconds. Defaults to 30_000. */
7
- timeout?: number;
8
- /** Custom fetch implementation (for testing or non-standard runtimes). */
9
- fetch?: typeof globalThis.fetch;
10
- }
11
- interface CodeOptions {
12
- /** Number of top ICD-10 candidates per entity (1-25). Defaults to 5. */
13
- topK?: number;
14
- /** Include negated entities in results. Defaults to true. */
15
- includeNegated?: boolean;
16
- /** Matching strategy. Defaults to `"individual"`. */
17
- strategy?: "individual" | "merged";
18
- }
19
- interface CodeMatch {
20
- /** ICD-10-CM code (e.g., `"E11.21"`). */
21
- code: string;
22
- /** Official code description. */
23
- description: string;
24
- /** Cosine similarity score (0-1). */
25
- similarity: number;
26
- /** `"high"` if above high-confidence threshold, else `"moderate"`. */
27
- confidence: "high" | "moderate";
28
- /** The index term that produced this match. */
29
- matched_term: string;
30
- }
31
- interface CodingEntity {
32
- /** Entity text as extracted from the input. */
33
- entity_text: string;
34
- /** Character offset start in input text. */
35
- entity_start: number;
36
- /** Character offset end in input text. */
37
- entity_end: number;
38
- /** Whether this entity was negated in context. */
39
- negated: boolean;
40
- /** Entity refers to a past/resolved condition. */
41
- historical: boolean;
42
- /** Entity refers to a family member's condition. */
43
- family_history: boolean;
44
- /** Entity is hedged or uncertain. */
45
- uncertain: boolean;
46
- /** Severity modifier if detected (e.g., `"severe"`). */
47
- severity: string | null;
48
- /** Ranked ICD-10 code candidates. */
49
- codes: CodeMatch[];
50
- /** Source entity texts if this result was created by merging consecutive entities. */
51
- merged_from?: string[] | null;
52
- /** Original text before spell correction (null if no correction). */
53
- corrected_from?: string | null;
54
- }
55
- interface CodingResponse {
56
- /** The input text that was processed. */
57
- text: string;
58
- /** Coding provider used. */
59
- provider: string;
60
- /** Matching strategy used. */
61
- strategy: string;
62
- /** Total number of entities in results. */
63
- entity_count: number;
64
- /** Coding results per entity, sorted by position in text. */
65
- entities: CodingEntity[];
66
- }
67
- interface SearchOptions {
68
- /** Maximum number of results (1-100). Defaults to 20. */
69
- limit?: number;
70
- /** Number of results to skip (for pagination). Defaults to 0. */
71
- offset?: number;
72
- }
73
- interface CodeDetail {
74
- /** ICD-10-CM code. */
75
- code: string;
76
- /** Abbreviated description. */
77
- short_description: string;
78
- /** Full official description. */
79
- long_description: string;
80
- /** Whether this is a billable (leaf) code. */
81
- is_billable: boolean;
82
- }
83
- interface ChapterInfo {
84
- /** Chapter number (1-22). */
85
- number: number;
86
- /** Code range (e.g., `"E00-E89"`). */
87
- range: string;
88
- /** Chapter title. */
89
- title: string;
90
- }
91
- interface CodeDetailFull extends CodeDetail {
92
- /** Synonyms grouped by source: `"snomed"`, `"umls"`, `"icd10_augmented"`. */
93
- synonyms: Record<string, string[]>;
94
- /** Parent code in the ICD-10 hierarchy, or `null` for top-level categories. */
95
- parent: CodeDetail | null;
96
- /** Direct child codes in the ICD-10 hierarchy. */
97
- children: CodeDetail[];
98
- /** ICD-10-CM chapter this code belongs to. */
99
- chapter: ChapterInfo | null;
100
- /** Code block range (e.g., `"E08-E13"`). */
101
- block: string | null;
102
- }
103
- interface CodeSearchResponse {
104
- /** The search query that was used. */
105
- query: string;
106
- /** Number of results returned. */
107
- count: number;
108
- /** Matching ICD-10 codes. */
109
- codes: CodeDetail[];
110
- }
111
- interface PIIEntity {
112
- /** Original PII text. */
113
- text: string;
114
- /** Character offset start. */
115
- start: number;
116
- /** Character offset end. */
117
- end: number;
118
- /** PII category (NAME, DATE, SSN, PHONE, EMAIL, ADDRESS, MRN, AGE). */
119
- label: string;
120
- /** Replacement token (e.g., `"[NAME]"`). */
121
- replacement: string;
122
- }
123
- interface AnonymizeResponse {
124
- /** The input text that was processed. */
125
- original_text: string;
126
- /** Text with PII replaced by type labels. */
127
- anonymized_text: string;
128
- /** Number of PII entities detected. */
129
- pii_count: number;
130
- /** Detected PII spans with original offsets. */
131
- pii_entities: PIIEntity[];
132
- }
133
- interface RateLimit {
134
- /** Total requests allowed in the current period. */
135
- limit: number;
136
- /** Requests remaining. */
137
- remaining: number;
138
- /** UTC timestamp when the limit resets. */
139
- resetAt: Date;
140
- }
141
-
142
- declare class AutoICD {
143
- private readonly apiKey;
144
- private readonly baseURL;
145
- private readonly timeout;
146
- private readonly _fetch;
147
- /** Rate limit info from the most recent API response. */
148
- lastRateLimit: RateLimit | null;
149
- /** Sub-resource for ICD-10 code lookup. */
150
- readonly codes: Codes;
151
- constructor(options: AutoICDOptions);
152
- /**
153
- * Code clinical text to ICD-10-CM diagnoses.
154
- *
155
- * @example
156
- * ```ts
157
- * const result = await autoicd.code("Patient has type 2 diabetes");
158
- * for (const entity of result.entities) {
159
- * console.log(entity.entity_text, entity.codes[0]?.code);
160
- * }
161
- * ```
162
- */
163
- code(text: string, options?: CodeOptions): Promise<CodingResponse>;
164
- /**
165
- * Anonymize PHI/PII in clinical text.
166
- *
167
- * @example
168
- * ```ts
169
- * const result = await autoicd.anonymize("John Smith, DOB 01/15/1980, has COPD");
170
- * console.log(result.anonymized_text);
171
- * // "[NAME], DOB [DATE], has COPD"
172
- * ```
173
- */
174
- anonymize(text: string): Promise<AnonymizeResponse>;
175
- /** @internal */
176
- get<T>(path: string): Promise<T>;
177
- /** @internal */
178
- post<T>(path: string, body: Record<string, unknown>): Promise<T>;
179
- private request;
180
- }
181
- declare class Codes {
182
- private readonly client;
183
- constructor(client: AutoICD);
184
- /**
185
- * Search ICD-10 codes by description.
186
- *
187
- * @example
188
- * ```ts
189
- * const results = await autoicd.codes.search("diabetes mellitus");
190
- * ```
191
- */
192
- search(query: string, options?: SearchOptions): Promise<CodeSearchResponse>;
193
- /**
194
- * Get comprehensive details for a single ICD-10 code, including synonyms,
195
- * hierarchy (parent/children), chapter, and SNOMED CT / UMLS cross-references.
196
- *
197
- * @example
198
- * ```ts
199
- * const detail = await autoicd.codes.get("E11.9");
200
- * console.log(detail.long_description);
201
- * console.log(detail.synonyms.snomed); // SNOMED CT synonyms
202
- * console.log(detail.chapter?.title); // "Endocrine, Nutritional and Metabolic Diseases"
203
- * console.log(detail.children.length); // child codes
204
- * ```
205
- */
206
- get(code: string): Promise<CodeDetailFull>;
207
- }
208
-
209
- declare class AutoICDError extends Error {
210
- readonly status: number;
211
- constructor(status: number, message: string);
212
- }
213
- declare class AuthenticationError extends AutoICDError {
214
- constructor(message?: string);
215
- }
216
- declare class RateLimitError extends AutoICDError {
217
- readonly rateLimit: RateLimit;
218
- constructor(message: string, rateLimit: RateLimit);
219
- }
220
- declare class NotFoundError extends AutoICDError {
221
- constructor(message?: string);
222
- }
223
-
224
- export { type AnonymizeResponse, AuthenticationError, AutoICD, AutoICDError, type AutoICDOptions, type ChapterInfo, type CodeDetail, type CodeDetailFull, type CodeMatch, type CodeOptions, type CodeSearchResponse, type CodingEntity, type CodingResponse, NotFoundError, type PIIEntity, type RateLimit, RateLimitError, type SearchOptions };
package/dist/index.d.ts DELETED
@@ -1,224 +0,0 @@
1
- interface AutoICDOptions {
2
- /** API key (starts with `sk_`). */
3
- apiKey: string;
4
- /** Base URL. Defaults to `https://autoicdapi.com`. */
5
- baseURL?: string;
6
- /** Default timeout in milliseconds. Defaults to 30_000. */
7
- timeout?: number;
8
- /** Custom fetch implementation (for testing or non-standard runtimes). */
9
- fetch?: typeof globalThis.fetch;
10
- }
11
- interface CodeOptions {
12
- /** Number of top ICD-10 candidates per entity (1-25). Defaults to 5. */
13
- topK?: number;
14
- /** Include negated entities in results. Defaults to true. */
15
- includeNegated?: boolean;
16
- /** Matching strategy. Defaults to `"individual"`. */
17
- strategy?: "individual" | "merged";
18
- }
19
- interface CodeMatch {
20
- /** ICD-10-CM code (e.g., `"E11.21"`). */
21
- code: string;
22
- /** Official code description. */
23
- description: string;
24
- /** Cosine similarity score (0-1). */
25
- similarity: number;
26
- /** `"high"` if above high-confidence threshold, else `"moderate"`. */
27
- confidence: "high" | "moderate";
28
- /** The index term that produced this match. */
29
- matched_term: string;
30
- }
31
- interface CodingEntity {
32
- /** Entity text as extracted from the input. */
33
- entity_text: string;
34
- /** Character offset start in input text. */
35
- entity_start: number;
36
- /** Character offset end in input text. */
37
- entity_end: number;
38
- /** Whether this entity was negated in context. */
39
- negated: boolean;
40
- /** Entity refers to a past/resolved condition. */
41
- historical: boolean;
42
- /** Entity refers to a family member's condition. */
43
- family_history: boolean;
44
- /** Entity is hedged or uncertain. */
45
- uncertain: boolean;
46
- /** Severity modifier if detected (e.g., `"severe"`). */
47
- severity: string | null;
48
- /** Ranked ICD-10 code candidates. */
49
- codes: CodeMatch[];
50
- /** Source entity texts if this result was created by merging consecutive entities. */
51
- merged_from?: string[] | null;
52
- /** Original text before spell correction (null if no correction). */
53
- corrected_from?: string | null;
54
- }
55
- interface CodingResponse {
56
- /** The input text that was processed. */
57
- text: string;
58
- /** Coding provider used. */
59
- provider: string;
60
- /** Matching strategy used. */
61
- strategy: string;
62
- /** Total number of entities in results. */
63
- entity_count: number;
64
- /** Coding results per entity, sorted by position in text. */
65
- entities: CodingEntity[];
66
- }
67
- interface SearchOptions {
68
- /** Maximum number of results (1-100). Defaults to 20. */
69
- limit?: number;
70
- /** Number of results to skip (for pagination). Defaults to 0. */
71
- offset?: number;
72
- }
73
- interface CodeDetail {
74
- /** ICD-10-CM code. */
75
- code: string;
76
- /** Abbreviated description. */
77
- short_description: string;
78
- /** Full official description. */
79
- long_description: string;
80
- /** Whether this is a billable (leaf) code. */
81
- is_billable: boolean;
82
- }
83
- interface ChapterInfo {
84
- /** Chapter number (1-22). */
85
- number: number;
86
- /** Code range (e.g., `"E00-E89"`). */
87
- range: string;
88
- /** Chapter title. */
89
- title: string;
90
- }
91
- interface CodeDetailFull extends CodeDetail {
92
- /** Synonyms grouped by source: `"snomed"`, `"umls"`, `"icd10_augmented"`. */
93
- synonyms: Record<string, string[]>;
94
- /** Parent code in the ICD-10 hierarchy, or `null` for top-level categories. */
95
- parent: CodeDetail | null;
96
- /** Direct child codes in the ICD-10 hierarchy. */
97
- children: CodeDetail[];
98
- /** ICD-10-CM chapter this code belongs to. */
99
- chapter: ChapterInfo | null;
100
- /** Code block range (e.g., `"E08-E13"`). */
101
- block: string | null;
102
- }
103
- interface CodeSearchResponse {
104
- /** The search query that was used. */
105
- query: string;
106
- /** Number of results returned. */
107
- count: number;
108
- /** Matching ICD-10 codes. */
109
- codes: CodeDetail[];
110
- }
111
- interface PIIEntity {
112
- /** Original PII text. */
113
- text: string;
114
- /** Character offset start. */
115
- start: number;
116
- /** Character offset end. */
117
- end: number;
118
- /** PII category (NAME, DATE, SSN, PHONE, EMAIL, ADDRESS, MRN, AGE). */
119
- label: string;
120
- /** Replacement token (e.g., `"[NAME]"`). */
121
- replacement: string;
122
- }
123
- interface AnonymizeResponse {
124
- /** The input text that was processed. */
125
- original_text: string;
126
- /** Text with PII replaced by type labels. */
127
- anonymized_text: string;
128
- /** Number of PII entities detected. */
129
- pii_count: number;
130
- /** Detected PII spans with original offsets. */
131
- pii_entities: PIIEntity[];
132
- }
133
- interface RateLimit {
134
- /** Total requests allowed in the current period. */
135
- limit: number;
136
- /** Requests remaining. */
137
- remaining: number;
138
- /** UTC timestamp when the limit resets. */
139
- resetAt: Date;
140
- }
141
-
142
- declare class AutoICD {
143
- private readonly apiKey;
144
- private readonly baseURL;
145
- private readonly timeout;
146
- private readonly _fetch;
147
- /** Rate limit info from the most recent API response. */
148
- lastRateLimit: RateLimit | null;
149
- /** Sub-resource for ICD-10 code lookup. */
150
- readonly codes: Codes;
151
- constructor(options: AutoICDOptions);
152
- /**
153
- * Code clinical text to ICD-10-CM diagnoses.
154
- *
155
- * @example
156
- * ```ts
157
- * const result = await autoicd.code("Patient has type 2 diabetes");
158
- * for (const entity of result.entities) {
159
- * console.log(entity.entity_text, entity.codes[0]?.code);
160
- * }
161
- * ```
162
- */
163
- code(text: string, options?: CodeOptions): Promise<CodingResponse>;
164
- /**
165
- * Anonymize PHI/PII in clinical text.
166
- *
167
- * @example
168
- * ```ts
169
- * const result = await autoicd.anonymize("John Smith, DOB 01/15/1980, has COPD");
170
- * console.log(result.anonymized_text);
171
- * // "[NAME], DOB [DATE], has COPD"
172
- * ```
173
- */
174
- anonymize(text: string): Promise<AnonymizeResponse>;
175
- /** @internal */
176
- get<T>(path: string): Promise<T>;
177
- /** @internal */
178
- post<T>(path: string, body: Record<string, unknown>): Promise<T>;
179
- private request;
180
- }
181
- declare class Codes {
182
- private readonly client;
183
- constructor(client: AutoICD);
184
- /**
185
- * Search ICD-10 codes by description.
186
- *
187
- * @example
188
- * ```ts
189
- * const results = await autoicd.codes.search("diabetes mellitus");
190
- * ```
191
- */
192
- search(query: string, options?: SearchOptions): Promise<CodeSearchResponse>;
193
- /**
194
- * Get comprehensive details for a single ICD-10 code, including synonyms,
195
- * hierarchy (parent/children), chapter, and SNOMED CT / UMLS cross-references.
196
- *
197
- * @example
198
- * ```ts
199
- * const detail = await autoicd.codes.get("E11.9");
200
- * console.log(detail.long_description);
201
- * console.log(detail.synonyms.snomed); // SNOMED CT synonyms
202
- * console.log(detail.chapter?.title); // "Endocrine, Nutritional and Metabolic Diseases"
203
- * console.log(detail.children.length); // child codes
204
- * ```
205
- */
206
- get(code: string): Promise<CodeDetailFull>;
207
- }
208
-
209
- declare class AutoICDError extends Error {
210
- readonly status: number;
211
- constructor(status: number, message: string);
212
- }
213
- declare class AuthenticationError extends AutoICDError {
214
- constructor(message?: string);
215
- }
216
- declare class RateLimitError extends AutoICDError {
217
- readonly rateLimit: RateLimit;
218
- constructor(message: string, rateLimit: RateLimit);
219
- }
220
- declare class NotFoundError extends AutoICDError {
221
- constructor(message?: string);
222
- }
223
-
224
- export { type AnonymizeResponse, AuthenticationError, AutoICD, AutoICDError, type AutoICDOptions, type ChapterInfo, type CodeDetail, type CodeDetailFull, type CodeMatch, type CodeOptions, type CodeSearchResponse, type CodingEntity, type CodingResponse, NotFoundError, type PIIEntity, type RateLimit, RateLimitError, type SearchOptions };
package/dist/index.js DELETED
@@ -1,227 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- AuthenticationError: () => AuthenticationError,
24
- AutoICD: () => AutoICD,
25
- AutoICDError: () => AutoICDError,
26
- NotFoundError: () => NotFoundError,
27
- RateLimitError: () => RateLimitError
28
- });
29
- module.exports = __toCommonJS(index_exports);
30
-
31
- // src/errors.ts
32
- var AutoICDError = class extends Error {
33
- status;
34
- constructor(status, message) {
35
- super(message);
36
- this.name = "AutoICDError";
37
- this.status = status;
38
- }
39
- };
40
- var AuthenticationError = class extends AutoICDError {
41
- constructor(message = "Invalid API key") {
42
- super(401, message);
43
- this.name = "AuthenticationError";
44
- }
45
- };
46
- var RateLimitError = class extends AutoICDError {
47
- rateLimit;
48
- constructor(message, rateLimit) {
49
- super(429, message);
50
- this.name = "RateLimitError";
51
- this.rateLimit = rateLimit;
52
- }
53
- };
54
- var NotFoundError = class extends AutoICDError {
55
- constructor(message = "Resource not found") {
56
- super(404, message);
57
- this.name = "NotFoundError";
58
- }
59
- };
60
-
61
- // src/client.ts
62
- var DEFAULT_BASE_URL = "https://autoicdapi.com";
63
- var DEFAULT_TIMEOUT = 3e4;
64
- var AutoICD = class {
65
- apiKey;
66
- baseURL;
67
- timeout;
68
- _fetch;
69
- /** Rate limit info from the most recent API response. */
70
- lastRateLimit = null;
71
- /** Sub-resource for ICD-10 code lookup. */
72
- codes;
73
- constructor(options) {
74
- if (!options.apiKey) {
75
- throw new Error("apiKey is required");
76
- }
77
- this.apiKey = options.apiKey;
78
- this.baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
79
- this.timeout = options.timeout ?? DEFAULT_TIMEOUT;
80
- this._fetch = options.fetch ?? globalThis.fetch;
81
- this.codes = new Codes(this);
82
- }
83
- // ─── Public Methods ───
84
- /**
85
- * Code clinical text to ICD-10-CM diagnoses.
86
- *
87
- * @example
88
- * ```ts
89
- * const result = await autoicd.code("Patient has type 2 diabetes");
90
- * for (const entity of result.entities) {
91
- * console.log(entity.entity_text, entity.codes[0]?.code);
92
- * }
93
- * ```
94
- */
95
- async code(text, options) {
96
- return this.post("/api/v1/code", {
97
- text,
98
- top_k: options?.topK,
99
- include_negated: options?.includeNegated,
100
- strategy: options?.strategy
101
- });
102
- }
103
- /**
104
- * Anonymize PHI/PII in clinical text.
105
- *
106
- * @example
107
- * ```ts
108
- * const result = await autoicd.anonymize("John Smith, DOB 01/15/1980, has COPD");
109
- * console.log(result.anonymized_text);
110
- * // "[NAME], DOB [DATE], has COPD"
111
- * ```
112
- */
113
- async anonymize(text) {
114
- return this.post("/api/v1/anonymize", { text });
115
- }
116
- // ─── Internal HTTP ───
117
- /** @internal */
118
- async get(path) {
119
- return this.request("GET", path);
120
- }
121
- /** @internal */
122
- async post(path, body) {
123
- const clean = Object.fromEntries(
124
- Object.entries(body).filter(([, v]) => v !== void 0)
125
- );
126
- return this.request("POST", path, clean);
127
- }
128
- async request(method, path, body) {
129
- const url = `${this.baseURL}${path}`;
130
- const controller = new AbortController();
131
- const timer = setTimeout(() => controller.abort(), this.timeout);
132
- try {
133
- const res = await this._fetch(url, {
134
- method,
135
- headers: {
136
- Authorization: `Bearer ${this.apiKey}`,
137
- "Content-Type": "application/json",
138
- Accept: "application/json"
139
- },
140
- body: body ? JSON.stringify(body) : void 0,
141
- signal: controller.signal
142
- });
143
- this.lastRateLimit = parseRateLimit(res.headers);
144
- if (res.ok) {
145
- return await res.json();
146
- }
147
- const errorBody = await res.json().catch(() => null);
148
- const message = errorBody?.error ?? `HTTP ${res.status}`;
149
- if (res.status === 401) throw new AuthenticationError(message);
150
- if (res.status === 404) throw new NotFoundError(message);
151
- if (res.status === 429) {
152
- throw new RateLimitError(
153
- message,
154
- this.lastRateLimit ?? {
155
- limit: errorBody?.limit ?? 0,
156
- remaining: 0,
157
- resetAt: errorBody?.resetAt ? new Date(errorBody.resetAt) : /* @__PURE__ */ new Date()
158
- }
159
- );
160
- }
161
- throw new AutoICDError(res.status, message);
162
- } catch (err) {
163
- if (err instanceof AutoICDError) throw err;
164
- if (err instanceof DOMException && err.name === "AbortError") {
165
- throw new AutoICDError(0, `Request timed out after ${this.timeout}ms`);
166
- }
167
- throw err;
168
- } finally {
169
- clearTimeout(timer);
170
- }
171
- }
172
- };
173
- var Codes = class {
174
- constructor(client) {
175
- this.client = client;
176
- }
177
- /**
178
- * Search ICD-10 codes by description.
179
- *
180
- * @example
181
- * ```ts
182
- * const results = await autoicd.codes.search("diabetes mellitus");
183
- * ```
184
- */
185
- async search(query, options) {
186
- const params = new URLSearchParams({ q: query });
187
- if (options?.limit !== void 0) params.set("limit", String(options.limit));
188
- if (options?.offset !== void 0) params.set("offset", String(options.offset));
189
- return this.client.get(`/api/v1/codes/search?${params}`);
190
- }
191
- /**
192
- * Get comprehensive details for a single ICD-10 code, including synonyms,
193
- * hierarchy (parent/children), chapter, and SNOMED CT / UMLS cross-references.
194
- *
195
- * @example
196
- * ```ts
197
- * const detail = await autoicd.codes.get("E11.9");
198
- * console.log(detail.long_description);
199
- * console.log(detail.synonyms.snomed); // SNOMED CT synonyms
200
- * console.log(detail.chapter?.title); // "Endocrine, Nutritional and Metabolic Diseases"
201
- * console.log(detail.children.length); // child codes
202
- * ```
203
- */
204
- async get(code) {
205
- return this.client.get(`/api/v1/codes/${encodeURIComponent(code)}`);
206
- }
207
- };
208
- function parseRateLimit(headers) {
209
- const limit = headers.get("X-RateLimit-Limit");
210
- const remaining = headers.get("X-RateLimit-Remaining");
211
- const reset = headers.get("X-RateLimit-Reset");
212
- if (!limit || !remaining || !reset) return null;
213
- return {
214
- limit: parseInt(limit, 10),
215
- remaining: parseInt(remaining, 10),
216
- resetAt: new Date(reset)
217
- };
218
- }
219
- // Annotate the CommonJS export names for ESM import in node:
220
- 0 && (module.exports = {
221
- AuthenticationError,
222
- AutoICD,
223
- AutoICDError,
224
- NotFoundError,
225
- RateLimitError
226
- });
227
- //# sourceMappingURL=index.js.map
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["export { AutoICD } from \"./client.js\";\n\nexport type {\n AutoICDOptions,\n CodeOptions,\n CodeMatch,\n CodingEntity,\n CodingResponse,\n SearchOptions,\n CodeDetail,\n CodeDetailFull,\n ChapterInfo,\n CodeSearchResponse,\n PIIEntity,\n AnonymizeResponse,\n RateLimit,\n} from \"./types.js\";\n\nexport {\n AutoICDError,\n AuthenticationError,\n RateLimitError,\n NotFoundError,\n} from \"./errors.js\";\n","import type { RateLimit } from \"./types.js\";\n\nexport class AutoICDError extends Error {\n readonly status: number;\n\n constructor(status: number, message: string) {\n super(message);\n this.name = \"AutoICDError\";\n this.status = status;\n }\n}\n\nexport class AuthenticationError extends AutoICDError {\n constructor(message = \"Invalid API key\") {\n super(401, message);\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class RateLimitError extends AutoICDError {\n readonly rateLimit: RateLimit;\n\n constructor(message: string, rateLimit: RateLimit) {\n super(429, message);\n this.name = \"RateLimitError\";\n this.rateLimit = rateLimit;\n }\n}\n\nexport class NotFoundError extends AutoICDError {\n constructor(message = \"Resource not found\") {\n super(404, message);\n this.name = \"NotFoundError\";\n }\n}\n","import type {\n AutoICDOptions,\n CodeOptions,\n CodingResponse,\n SearchOptions,\n CodeSearchResponse,\n CodeDetail,\n CodeDetailFull,\n AnonymizeResponse,\n RateLimit,\n ErrorBody,\n} from \"./types.js\";\nimport {\n AutoICDError,\n AuthenticationError,\n RateLimitError,\n NotFoundError,\n} from \"./errors.js\";\n\nconst DEFAULT_BASE_URL = \"https://autoicdapi.com\";\nconst DEFAULT_TIMEOUT = 30_000;\n\nexport class AutoICD {\n private readonly apiKey: string;\n private readonly baseURL: string;\n private readonly timeout: number;\n private readonly _fetch: typeof globalThis.fetch;\n\n /** Rate limit info from the most recent API response. */\n lastRateLimit: RateLimit | null = null;\n\n /** Sub-resource for ICD-10 code lookup. */\n readonly codes: Codes;\n\n constructor(options: AutoICDOptions) {\n if (!options.apiKey) {\n throw new Error(\"apiKey is required\");\n }\n this.apiKey = options.apiKey;\n this.baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this._fetch = options.fetch ?? globalThis.fetch;\n this.codes = new Codes(this);\n }\n\n // ─── Public Methods ───\n\n /**\n * Code clinical text to ICD-10-CM diagnoses.\n *\n * @example\n * ```ts\n * const result = await autoicd.code(\"Patient has type 2 diabetes\");\n * for (const entity of result.entities) {\n * console.log(entity.entity_text, entity.codes[0]?.code);\n * }\n * ```\n */\n async code(text: string, options?: CodeOptions): Promise<CodingResponse> {\n return this.post<CodingResponse>(\"/api/v1/code\", {\n text,\n top_k: options?.topK,\n include_negated: options?.includeNegated,\n strategy: options?.strategy,\n });\n }\n\n /**\n * Anonymize PHI/PII in clinical text.\n *\n * @example\n * ```ts\n * const result = await autoicd.anonymize(\"John Smith, DOB 01/15/1980, has COPD\");\n * console.log(result.anonymized_text);\n * // \"[NAME], DOB [DATE], has COPD\"\n * ```\n */\n async anonymize(text: string): Promise<AnonymizeResponse> {\n return this.post<AnonymizeResponse>(\"/api/v1/anonymize\", { text });\n }\n\n // ─── Internal HTTP ───\n\n /** @internal */\n async get<T>(path: string): Promise<T> {\n return this.request<T>(\"GET\", path);\n }\n\n /** @internal */\n async post<T>(path: string, body: Record<string, unknown>): Promise<T> {\n // Strip undefined values so the API receives clean JSON\n const clean = Object.fromEntries(\n Object.entries(body).filter(([, v]) => v !== undefined)\n );\n return this.request<T>(\"POST\", path, clean);\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: Record<string, unknown>\n ): Promise<T> {\n const url = `${this.baseURL}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await this._fetch(url, {\n method,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n // Parse rate limit headers\n this.lastRateLimit = parseRateLimit(res.headers);\n\n if (res.ok) {\n return (await res.json()) as T;\n }\n\n // Error responses\n const errorBody = (await res.json().catch(() => null)) as ErrorBody | null;\n const message = errorBody?.error ?? `HTTP ${res.status}`;\n\n if (res.status === 401) throw new AuthenticationError(message);\n if (res.status === 404) throw new NotFoundError(message);\n if (res.status === 429) {\n throw new RateLimitError(\n message,\n this.lastRateLimit ?? {\n limit: errorBody?.limit ?? 0,\n remaining: 0,\n resetAt: errorBody?.resetAt ? new Date(errorBody.resetAt) : new Date(),\n }\n );\n }\n\n throw new AutoICDError(res.status, message);\n } catch (err) {\n if (err instanceof AutoICDError) throw err;\n if (err instanceof DOMException && err.name === \"AbortError\") {\n throw new AutoICDError(0, `Request timed out after ${this.timeout}ms`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n }\n}\n\n// ─── Codes Sub-resource ───\n\nclass Codes {\n constructor(private readonly client: AutoICD) {}\n\n /**\n * Search ICD-10 codes by description.\n *\n * @example\n * ```ts\n * const results = await autoicd.codes.search(\"diabetes mellitus\");\n * ```\n */\n async search(query: string, options?: SearchOptions): Promise<CodeSearchResponse> {\n const params = new URLSearchParams({ q: query });\n if (options?.limit !== undefined) params.set(\"limit\", String(options.limit));\n if (options?.offset !== undefined) params.set(\"offset\", String(options.offset));\n return this.client.get<CodeSearchResponse>(`/api/v1/codes/search?${params}`);\n }\n\n /**\n * Get comprehensive details for a single ICD-10 code, including synonyms,\n * hierarchy (parent/children), chapter, and SNOMED CT / UMLS cross-references.\n *\n * @example\n * ```ts\n * const detail = await autoicd.codes.get(\"E11.9\");\n * console.log(detail.long_description);\n * console.log(detail.synonyms.snomed); // SNOMED CT synonyms\n * console.log(detail.chapter?.title); // \"Endocrine, Nutritional and Metabolic Diseases\"\n * console.log(detail.children.length); // child codes\n * ```\n */\n async get(code: string): Promise<CodeDetailFull> {\n return this.client.get<CodeDetailFull>(`/api/v1/codes/${encodeURIComponent(code)}`);\n }\n\n}\n\n// ─── Helpers ───\n\nfunction parseRateLimit(headers: Headers): RateLimit | null {\n const limit = headers.get(\"X-RateLimit-Limit\");\n const remaining = headers.get(\"X-RateLimit-Remaining\");\n const reset = headers.get(\"X-RateLimit-Reset\");\n\n if (!limit || !remaining || !reset) return null;\n\n return {\n limit: parseInt(limit, 10),\n remaining: parseInt(remaining, 10),\n resetAt: new Date(reset),\n };\n}\n"],"mappings":"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","names":[]}
package/dist/index.mjs DELETED
@@ -1,196 +0,0 @@
1
- // src/errors.ts
2
- var AutoICDError = class extends Error {
3
- status;
4
- constructor(status, message) {
5
- super(message);
6
- this.name = "AutoICDError";
7
- this.status = status;
8
- }
9
- };
10
- var AuthenticationError = class extends AutoICDError {
11
- constructor(message = "Invalid API key") {
12
- super(401, message);
13
- this.name = "AuthenticationError";
14
- }
15
- };
16
- var RateLimitError = class extends AutoICDError {
17
- rateLimit;
18
- constructor(message, rateLimit) {
19
- super(429, message);
20
- this.name = "RateLimitError";
21
- this.rateLimit = rateLimit;
22
- }
23
- };
24
- var NotFoundError = class extends AutoICDError {
25
- constructor(message = "Resource not found") {
26
- super(404, message);
27
- this.name = "NotFoundError";
28
- }
29
- };
30
-
31
- // src/client.ts
32
- var DEFAULT_BASE_URL = "https://autoicdapi.com";
33
- var DEFAULT_TIMEOUT = 3e4;
34
- var AutoICD = class {
35
- apiKey;
36
- baseURL;
37
- timeout;
38
- _fetch;
39
- /** Rate limit info from the most recent API response. */
40
- lastRateLimit = null;
41
- /** Sub-resource for ICD-10 code lookup. */
42
- codes;
43
- constructor(options) {
44
- if (!options.apiKey) {
45
- throw new Error("apiKey is required");
46
- }
47
- this.apiKey = options.apiKey;
48
- this.baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
49
- this.timeout = options.timeout ?? DEFAULT_TIMEOUT;
50
- this._fetch = options.fetch ?? globalThis.fetch;
51
- this.codes = new Codes(this);
52
- }
53
- // ─── Public Methods ───
54
- /**
55
- * Code clinical text to ICD-10-CM diagnoses.
56
- *
57
- * @example
58
- * ```ts
59
- * const result = await autoicd.code("Patient has type 2 diabetes");
60
- * for (const entity of result.entities) {
61
- * console.log(entity.entity_text, entity.codes[0]?.code);
62
- * }
63
- * ```
64
- */
65
- async code(text, options) {
66
- return this.post("/api/v1/code", {
67
- text,
68
- top_k: options?.topK,
69
- include_negated: options?.includeNegated,
70
- strategy: options?.strategy
71
- });
72
- }
73
- /**
74
- * Anonymize PHI/PII in clinical text.
75
- *
76
- * @example
77
- * ```ts
78
- * const result = await autoicd.anonymize("John Smith, DOB 01/15/1980, has COPD");
79
- * console.log(result.anonymized_text);
80
- * // "[NAME], DOB [DATE], has COPD"
81
- * ```
82
- */
83
- async anonymize(text) {
84
- return this.post("/api/v1/anonymize", { text });
85
- }
86
- // ─── Internal HTTP ───
87
- /** @internal */
88
- async get(path) {
89
- return this.request("GET", path);
90
- }
91
- /** @internal */
92
- async post(path, body) {
93
- const clean = Object.fromEntries(
94
- Object.entries(body).filter(([, v]) => v !== void 0)
95
- );
96
- return this.request("POST", path, clean);
97
- }
98
- async request(method, path, body) {
99
- const url = `${this.baseURL}${path}`;
100
- const controller = new AbortController();
101
- const timer = setTimeout(() => controller.abort(), this.timeout);
102
- try {
103
- const res = await this._fetch(url, {
104
- method,
105
- headers: {
106
- Authorization: `Bearer ${this.apiKey}`,
107
- "Content-Type": "application/json",
108
- Accept: "application/json"
109
- },
110
- body: body ? JSON.stringify(body) : void 0,
111
- signal: controller.signal
112
- });
113
- this.lastRateLimit = parseRateLimit(res.headers);
114
- if (res.ok) {
115
- return await res.json();
116
- }
117
- const errorBody = await res.json().catch(() => null);
118
- const message = errorBody?.error ?? `HTTP ${res.status}`;
119
- if (res.status === 401) throw new AuthenticationError(message);
120
- if (res.status === 404) throw new NotFoundError(message);
121
- if (res.status === 429) {
122
- throw new RateLimitError(
123
- message,
124
- this.lastRateLimit ?? {
125
- limit: errorBody?.limit ?? 0,
126
- remaining: 0,
127
- resetAt: errorBody?.resetAt ? new Date(errorBody.resetAt) : /* @__PURE__ */ new Date()
128
- }
129
- );
130
- }
131
- throw new AutoICDError(res.status, message);
132
- } catch (err) {
133
- if (err instanceof AutoICDError) throw err;
134
- if (err instanceof DOMException && err.name === "AbortError") {
135
- throw new AutoICDError(0, `Request timed out after ${this.timeout}ms`);
136
- }
137
- throw err;
138
- } finally {
139
- clearTimeout(timer);
140
- }
141
- }
142
- };
143
- var Codes = class {
144
- constructor(client) {
145
- this.client = client;
146
- }
147
- /**
148
- * Search ICD-10 codes by description.
149
- *
150
- * @example
151
- * ```ts
152
- * const results = await autoicd.codes.search("diabetes mellitus");
153
- * ```
154
- */
155
- async search(query, options) {
156
- const params = new URLSearchParams({ q: query });
157
- if (options?.limit !== void 0) params.set("limit", String(options.limit));
158
- if (options?.offset !== void 0) params.set("offset", String(options.offset));
159
- return this.client.get(`/api/v1/codes/search?${params}`);
160
- }
161
- /**
162
- * Get comprehensive details for a single ICD-10 code, including synonyms,
163
- * hierarchy (parent/children), chapter, and SNOMED CT / UMLS cross-references.
164
- *
165
- * @example
166
- * ```ts
167
- * const detail = await autoicd.codes.get("E11.9");
168
- * console.log(detail.long_description);
169
- * console.log(detail.synonyms.snomed); // SNOMED CT synonyms
170
- * console.log(detail.chapter?.title); // "Endocrine, Nutritional and Metabolic Diseases"
171
- * console.log(detail.children.length); // child codes
172
- * ```
173
- */
174
- async get(code) {
175
- return this.client.get(`/api/v1/codes/${encodeURIComponent(code)}`);
176
- }
177
- };
178
- function parseRateLimit(headers) {
179
- const limit = headers.get("X-RateLimit-Limit");
180
- const remaining = headers.get("X-RateLimit-Remaining");
181
- const reset = headers.get("X-RateLimit-Reset");
182
- if (!limit || !remaining || !reset) return null;
183
- return {
184
- limit: parseInt(limit, 10),
185
- remaining: parseInt(remaining, 10),
186
- resetAt: new Date(reset)
187
- };
188
- }
189
- export {
190
- AuthenticationError,
191
- AutoICD,
192
- AutoICDError,
193
- NotFoundError,
194
- RateLimitError
195
- };
196
- //# sourceMappingURL=index.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/client.ts"],"sourcesContent":["import type { RateLimit } from \"./types.js\";\n\nexport class AutoICDError extends Error {\n readonly status: number;\n\n constructor(status: number, message: string) {\n super(message);\n this.name = \"AutoICDError\";\n this.status = status;\n }\n}\n\nexport class AuthenticationError extends AutoICDError {\n constructor(message = \"Invalid API key\") {\n super(401, message);\n this.name = \"AuthenticationError\";\n }\n}\n\nexport class RateLimitError extends AutoICDError {\n readonly rateLimit: RateLimit;\n\n constructor(message: string, rateLimit: RateLimit) {\n super(429, message);\n this.name = \"RateLimitError\";\n this.rateLimit = rateLimit;\n }\n}\n\nexport class NotFoundError extends AutoICDError {\n constructor(message = \"Resource not found\") {\n super(404, message);\n this.name = \"NotFoundError\";\n }\n}\n","import type {\n AutoICDOptions,\n CodeOptions,\n CodingResponse,\n SearchOptions,\n CodeSearchResponse,\n CodeDetail,\n CodeDetailFull,\n AnonymizeResponse,\n RateLimit,\n ErrorBody,\n} from \"./types.js\";\nimport {\n AutoICDError,\n AuthenticationError,\n RateLimitError,\n NotFoundError,\n} from \"./errors.js\";\n\nconst DEFAULT_BASE_URL = \"https://autoicdapi.com\";\nconst DEFAULT_TIMEOUT = 30_000;\n\nexport class AutoICD {\n private readonly apiKey: string;\n private readonly baseURL: string;\n private readonly timeout: number;\n private readonly _fetch: typeof globalThis.fetch;\n\n /** Rate limit info from the most recent API response. */\n lastRateLimit: RateLimit | null = null;\n\n /** Sub-resource for ICD-10 code lookup. */\n readonly codes: Codes;\n\n constructor(options: AutoICDOptions) {\n if (!options.apiKey) {\n throw new Error(\"apiKey is required\");\n }\n this.apiKey = options.apiKey;\n this.baseURL = (options.baseURL ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT;\n this._fetch = options.fetch ?? globalThis.fetch;\n this.codes = new Codes(this);\n }\n\n // ─── Public Methods ───\n\n /**\n * Code clinical text to ICD-10-CM diagnoses.\n *\n * @example\n * ```ts\n * const result = await autoicd.code(\"Patient has type 2 diabetes\");\n * for (const entity of result.entities) {\n * console.log(entity.entity_text, entity.codes[0]?.code);\n * }\n * ```\n */\n async code(text: string, options?: CodeOptions): Promise<CodingResponse> {\n return this.post<CodingResponse>(\"/api/v1/code\", {\n text,\n top_k: options?.topK,\n include_negated: options?.includeNegated,\n strategy: options?.strategy,\n });\n }\n\n /**\n * Anonymize PHI/PII in clinical text.\n *\n * @example\n * ```ts\n * const result = await autoicd.anonymize(\"John Smith, DOB 01/15/1980, has COPD\");\n * console.log(result.anonymized_text);\n * // \"[NAME], DOB [DATE], has COPD\"\n * ```\n */\n async anonymize(text: string): Promise<AnonymizeResponse> {\n return this.post<AnonymizeResponse>(\"/api/v1/anonymize\", { text });\n }\n\n // ─── Internal HTTP ───\n\n /** @internal */\n async get<T>(path: string): Promise<T> {\n return this.request<T>(\"GET\", path);\n }\n\n /** @internal */\n async post<T>(path: string, body: Record<string, unknown>): Promise<T> {\n // Strip undefined values so the API receives clean JSON\n const clean = Object.fromEntries(\n Object.entries(body).filter(([, v]) => v !== undefined)\n );\n return this.request<T>(\"POST\", path, clean);\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: Record<string, unknown>\n ): Promise<T> {\n const url = `${this.baseURL}${path}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await this._fetch(url, {\n method,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n // Parse rate limit headers\n this.lastRateLimit = parseRateLimit(res.headers);\n\n if (res.ok) {\n return (await res.json()) as T;\n }\n\n // Error responses\n const errorBody = (await res.json().catch(() => null)) as ErrorBody | null;\n const message = errorBody?.error ?? `HTTP ${res.status}`;\n\n if (res.status === 401) throw new AuthenticationError(message);\n if (res.status === 404) throw new NotFoundError(message);\n if (res.status === 429) {\n throw new RateLimitError(\n message,\n this.lastRateLimit ?? {\n limit: errorBody?.limit ?? 0,\n remaining: 0,\n resetAt: errorBody?.resetAt ? new Date(errorBody.resetAt) : new Date(),\n }\n );\n }\n\n throw new AutoICDError(res.status, message);\n } catch (err) {\n if (err instanceof AutoICDError) throw err;\n if (err instanceof DOMException && err.name === \"AbortError\") {\n throw new AutoICDError(0, `Request timed out after ${this.timeout}ms`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n }\n}\n\n// ─── Codes Sub-resource ───\n\nclass Codes {\n constructor(private readonly client: AutoICD) {}\n\n /**\n * Search ICD-10 codes by description.\n *\n * @example\n * ```ts\n * const results = await autoicd.codes.search(\"diabetes mellitus\");\n * ```\n */\n async search(query: string, options?: SearchOptions): Promise<CodeSearchResponse> {\n const params = new URLSearchParams({ q: query });\n if (options?.limit !== undefined) params.set(\"limit\", String(options.limit));\n if (options?.offset !== undefined) params.set(\"offset\", String(options.offset));\n return this.client.get<CodeSearchResponse>(`/api/v1/codes/search?${params}`);\n }\n\n /**\n * Get comprehensive details for a single ICD-10 code, including synonyms,\n * hierarchy (parent/children), chapter, and SNOMED CT / UMLS cross-references.\n *\n * @example\n * ```ts\n * const detail = await autoicd.codes.get(\"E11.9\");\n * console.log(detail.long_description);\n * console.log(detail.synonyms.snomed); // SNOMED CT synonyms\n * console.log(detail.chapter?.title); // \"Endocrine, Nutritional and Metabolic Diseases\"\n * console.log(detail.children.length); // child codes\n * ```\n */\n async get(code: string): Promise<CodeDetailFull> {\n return this.client.get<CodeDetailFull>(`/api/v1/codes/${encodeURIComponent(code)}`);\n }\n\n}\n\n// ─── Helpers ───\n\nfunction parseRateLimit(headers: Headers): RateLimit | null {\n const limit = headers.get(\"X-RateLimit-Limit\");\n const remaining = headers.get(\"X-RateLimit-Remaining\");\n const reset = headers.get(\"X-RateLimit-Reset\");\n\n if (!limit || !remaining || !reset) return null;\n\n return {\n limit: parseInt(limit, 10),\n remaining: parseInt(remaining, 10),\n resetAt: new Date(reset),\n };\n}\n"],"mappings":"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","names":[]}