autoicd-js 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md 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
  );
@@ -115,25 +114,15 @@ const results = await autoicd.codes.search("heart failure", { limit: 5 });
115
114
 
116
115
  ### ICD-10 Code Details
117
116
 
118
- Get full details for any ICD-10-CM code — descriptions, billable status, and indexed terms.
117
+ Get full details for any ICD-10-CM code — descriptions, billable status, synonyms, hierarchy, and chapter classification.
119
118
 
120
119
  ```ts
121
120
  const detail = await autoicd.codes.get("E11.9");
122
121
  console.log(detail.code); // "E11.9"
123
122
  console.log(detail.long_description); // "Type 2 diabetes mellitus without complications"
124
123
  console.log(detail.is_billable); // true
125
- ```
126
-
127
- ### ICD-10 Code Terms & Synonyms
128
-
129
- Retrieve all indexed terms and synonyms for a code — includes SNOMED CT mappings and clinical variants.
130
-
131
- ```ts
132
- const terms = await autoicd.codes.terms("E11.9");
133
- terms.forEach((t) => console.log(t.term, `(${t.term_type})`));
134
- // "Type 2 diabetes mellitus without complications" (long_desc)
135
- // "adult onset diabetes" (synonym)
136
- // ...
124
+ console.log(detail.synonyms.snomed); // ["Diabetes mellitus type 2", ...]
125
+ console.log(detail.chapter?.title); // "Endocrine, Nutritional and Metabolic Diseases"
137
126
  ```
138
127
 
139
128
  ### PHI De-identification
@@ -223,7 +212,6 @@ Full REST API documentation at [autoicdapi.com/docs](https://autoicdapi.com/docs
223
212
  | `autoicd.anonymize(text)` | De-identify PHI/PII in clinical text |
224
213
  | `autoicd.codes.search(query, options?)` | Search ICD-10-CM codes by description |
225
214
  | `autoicd.codes.get(code)` | Get details for an ICD-10-CM code |
226
- | `autoicd.codes.terms(code)` | Get indexed terms/synonyms for a code |
227
215
 
228
216
  ---
229
217
 
@@ -239,7 +227,6 @@ import type {
239
227
  CodeOptions,
240
228
  CodeDetail,
241
229
  CodeSearchResponse,
242
- CodeTermInfo,
243
230
  AnonymizeResponse,
244
231
  PIIEntity,
245
232
  RateLimit,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autoicd-js",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
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.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/dist/index.d.mts DELETED
@@ -1,240 +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 CodeTermInfo {
112
- /** The term text that was embedded. */
113
- term: string;
114
- /** Origin of this term (e.g., `"long_desc"`, `"synonym"`). */
115
- term_type: string;
116
- }
117
- interface PIIEntity {
118
- /** Original PII text. */
119
- text: string;
120
- /** Character offset start. */
121
- start: number;
122
- /** Character offset end. */
123
- end: number;
124
- /** PII category (NAME, DATE, SSN, PHONE, EMAIL, ADDRESS, MRN, AGE). */
125
- label: string;
126
- /** Replacement token (e.g., `"[NAME]"`). */
127
- replacement: string;
128
- }
129
- interface AnonymizeResponse {
130
- /** The input text that was processed. */
131
- original_text: string;
132
- /** Text with PII replaced by type labels. */
133
- anonymized_text: string;
134
- /** Number of PII entities detected. */
135
- pii_count: number;
136
- /** Detected PII spans with original offsets. */
137
- pii_entities: PIIEntity[];
138
- }
139
- interface RateLimit {
140
- /** Total requests allowed in the current period. */
141
- limit: number;
142
- /** Requests remaining. */
143
- remaining: number;
144
- /** UTC timestamp when the limit resets. */
145
- resetAt: Date;
146
- }
147
-
148
- declare class AutoICD {
149
- private readonly apiKey;
150
- private readonly baseURL;
151
- private readonly timeout;
152
- private readonly _fetch;
153
- /** Rate limit info from the most recent API response. */
154
- lastRateLimit: RateLimit | null;
155
- /** Sub-resource for ICD-10 code lookup. */
156
- readonly codes: Codes;
157
- constructor(options: AutoICDOptions);
158
- /**
159
- * Code clinical text to ICD-10-CM diagnoses.
160
- *
161
- * @example
162
- * ```ts
163
- * const result = await autoicd.code("Patient has type 2 diabetes");
164
- * for (const entity of result.entities) {
165
- * console.log(entity.entity_text, entity.codes[0]?.code);
166
- * }
167
- * ```
168
- */
169
- code(text: string, options?: CodeOptions): Promise<CodingResponse>;
170
- /**
171
- * Anonymize PHI/PII in clinical text.
172
- *
173
- * @example
174
- * ```ts
175
- * const result = await autoicd.anonymize("John Smith, DOB 01/15/1980, has COPD");
176
- * console.log(result.anonymized_text);
177
- * // "[NAME], DOB [DATE], has COPD"
178
- * ```
179
- */
180
- anonymize(text: string): Promise<AnonymizeResponse>;
181
- /** @internal */
182
- get<T>(path: string): Promise<T>;
183
- /** @internal */
184
- post<T>(path: string, body: Record<string, unknown>): Promise<T>;
185
- private request;
186
- }
187
- declare class Codes {
188
- private readonly client;
189
- constructor(client: AutoICD);
190
- /**
191
- * Search ICD-10 codes by description.
192
- *
193
- * @example
194
- * ```ts
195
- * const results = await autoicd.codes.search("diabetes mellitus");
196
- * ```
197
- */
198
- search(query: string, options?: SearchOptions): Promise<CodeSearchResponse>;
199
- /**
200
- * Get comprehensive details for a single ICD-10 code, including synonyms,
201
- * hierarchy (parent/children), chapter, and SNOMED CT / UMLS cross-references.
202
- *
203
- * @example
204
- * ```ts
205
- * const detail = await autoicd.codes.get("E11.9");
206
- * console.log(detail.long_description);
207
- * console.log(detail.synonyms.snomed); // SNOMED CT synonyms
208
- * console.log(detail.chapter?.title); // "Endocrine, Nutritional and Metabolic Diseases"
209
- * console.log(detail.children.length); // child codes
210
- * ```
211
- */
212
- get(code: string): Promise<CodeDetailFull>;
213
- /**
214
- * Get all indexed terms/synonyms for an ICD-10 code.
215
- *
216
- * @example
217
- * ```ts
218
- * const terms = await autoicd.codes.terms("E11.9");
219
- * terms.forEach(t => console.log(t.term, t.term_type));
220
- * ```
221
- */
222
- terms(code: string): Promise<CodeTermInfo[]>;
223
- }
224
-
225
- declare class AutoICDError extends Error {
226
- readonly status: number;
227
- constructor(status: number, message: string);
228
- }
229
- declare class AuthenticationError extends AutoICDError {
230
- constructor(message?: string);
231
- }
232
- declare class RateLimitError extends AutoICDError {
233
- readonly rateLimit: RateLimit;
234
- constructor(message: string, rateLimit: RateLimit);
235
- }
236
- declare class NotFoundError extends AutoICDError {
237
- constructor(message?: string);
238
- }
239
-
240
- export { type AnonymizeResponse, AuthenticationError, AutoICD, AutoICDError, type AutoICDOptions, type ChapterInfo, type CodeDetail, type CodeDetailFull, type CodeMatch, type CodeOptions, type CodeSearchResponse, type CodeTermInfo, type CodingEntity, type CodingResponse, NotFoundError, type PIIEntity, type RateLimit, RateLimitError, type SearchOptions };
package/dist/index.d.ts DELETED
@@ -1,240 +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 CodeTermInfo {
112
- /** The term text that was embedded. */
113
- term: string;
114
- /** Origin of this term (e.g., `"long_desc"`, `"synonym"`). */
115
- term_type: string;
116
- }
117
- interface PIIEntity {
118
- /** Original PII text. */
119
- text: string;
120
- /** Character offset start. */
121
- start: number;
122
- /** Character offset end. */
123
- end: number;
124
- /** PII category (NAME, DATE, SSN, PHONE, EMAIL, ADDRESS, MRN, AGE). */
125
- label: string;
126
- /** Replacement token (e.g., `"[NAME]"`). */
127
- replacement: string;
128
- }
129
- interface AnonymizeResponse {
130
- /** The input text that was processed. */
131
- original_text: string;
132
- /** Text with PII replaced by type labels. */
133
- anonymized_text: string;
134
- /** Number of PII entities detected. */
135
- pii_count: number;
136
- /** Detected PII spans with original offsets. */
137
- pii_entities: PIIEntity[];
138
- }
139
- interface RateLimit {
140
- /** Total requests allowed in the current period. */
141
- limit: number;
142
- /** Requests remaining. */
143
- remaining: number;
144
- /** UTC timestamp when the limit resets. */
145
- resetAt: Date;
146
- }
147
-
148
- declare class AutoICD {
149
- private readonly apiKey;
150
- private readonly baseURL;
151
- private readonly timeout;
152
- private readonly _fetch;
153
- /** Rate limit info from the most recent API response. */
154
- lastRateLimit: RateLimit | null;
155
- /** Sub-resource for ICD-10 code lookup. */
156
- readonly codes: Codes;
157
- constructor(options: AutoICDOptions);
158
- /**
159
- * Code clinical text to ICD-10-CM diagnoses.
160
- *
161
- * @example
162
- * ```ts
163
- * const result = await autoicd.code("Patient has type 2 diabetes");
164
- * for (const entity of result.entities) {
165
- * console.log(entity.entity_text, entity.codes[0]?.code);
166
- * }
167
- * ```
168
- */
169
- code(text: string, options?: CodeOptions): Promise<CodingResponse>;
170
- /**
171
- * Anonymize PHI/PII in clinical text.
172
- *
173
- * @example
174
- * ```ts
175
- * const result = await autoicd.anonymize("John Smith, DOB 01/15/1980, has COPD");
176
- * console.log(result.anonymized_text);
177
- * // "[NAME], DOB [DATE], has COPD"
178
- * ```
179
- */
180
- anonymize(text: string): Promise<AnonymizeResponse>;
181
- /** @internal */
182
- get<T>(path: string): Promise<T>;
183
- /** @internal */
184
- post<T>(path: string, body: Record<string, unknown>): Promise<T>;
185
- private request;
186
- }
187
- declare class Codes {
188
- private readonly client;
189
- constructor(client: AutoICD);
190
- /**
191
- * Search ICD-10 codes by description.
192
- *
193
- * @example
194
- * ```ts
195
- * const results = await autoicd.codes.search("diabetes mellitus");
196
- * ```
197
- */
198
- search(query: string, options?: SearchOptions): Promise<CodeSearchResponse>;
199
- /**
200
- * Get comprehensive details for a single ICD-10 code, including synonyms,
201
- * hierarchy (parent/children), chapter, and SNOMED CT / UMLS cross-references.
202
- *
203
- * @example
204
- * ```ts
205
- * const detail = await autoicd.codes.get("E11.9");
206
- * console.log(detail.long_description);
207
- * console.log(detail.synonyms.snomed); // SNOMED CT synonyms
208
- * console.log(detail.chapter?.title); // "Endocrine, Nutritional and Metabolic Diseases"
209
- * console.log(detail.children.length); // child codes
210
- * ```
211
- */
212
- get(code: string): Promise<CodeDetailFull>;
213
- /**
214
- * Get all indexed terms/synonyms for an ICD-10 code.
215
- *
216
- * @example
217
- * ```ts
218
- * const terms = await autoicd.codes.terms("E11.9");
219
- * terms.forEach(t => console.log(t.term, t.term_type));
220
- * ```
221
- */
222
- terms(code: string): Promise<CodeTermInfo[]>;
223
- }
224
-
225
- declare class AutoICDError extends Error {
226
- readonly status: number;
227
- constructor(status: number, message: string);
228
- }
229
- declare class AuthenticationError extends AutoICDError {
230
- constructor(message?: string);
231
- }
232
- declare class RateLimitError extends AutoICDError {
233
- readonly rateLimit: RateLimit;
234
- constructor(message: string, rateLimit: RateLimit);
235
- }
236
- declare class NotFoundError extends AutoICDError {
237
- constructor(message?: string);
238
- }
239
-
240
- export { type AnonymizeResponse, AuthenticationError, AutoICD, AutoICDError, type AutoICDOptions, type ChapterInfo, type CodeDetail, type CodeDetailFull, type CodeMatch, type CodeOptions, type CodeSearchResponse, type CodeTermInfo, type CodingEntity, type CodingResponse, NotFoundError, type PIIEntity, type RateLimit, RateLimitError, type SearchOptions };
package/dist/index.js DELETED
@@ -1,241 +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
- * Get all indexed terms/synonyms for an ICD-10 code.
209
- *
210
- * @example
211
- * ```ts
212
- * const terms = await autoicd.codes.terms("E11.9");
213
- * terms.forEach(t => console.log(t.term, t.term_type));
214
- * ```
215
- */
216
- async terms(code) {
217
- return this.client.get(
218
- `/api/v1/codes/${encodeURIComponent(code)}/terms`
219
- );
220
- }
221
- };
222
- function parseRateLimit(headers) {
223
- const limit = headers.get("X-RateLimit-Limit");
224
- const remaining = headers.get("X-RateLimit-Remaining");
225
- const reset = headers.get("X-RateLimit-Reset");
226
- if (!limit || !remaining || !reset) return null;
227
- return {
228
- limit: parseInt(limit, 10),
229
- remaining: parseInt(remaining, 10),
230
- resetAt: new Date(reset)
231
- };
232
- }
233
- // Annotate the CommonJS export names for ESM import in node:
234
- 0 && (module.exports = {
235
- AuthenticationError,
236
- AutoICD,
237
- AutoICDError,
238
- NotFoundError,
239
- RateLimitError
240
- });
241
- //# 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 CodeTermInfo,\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 CodeTermInfo,\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 * Get all indexed terms/synonyms for an ICD-10 code.\n *\n * @example\n * ```ts\n * const terms = await autoicd.codes.terms(\"E11.9\");\n * terms.forEach(t => console.log(t.term, t.term_type));\n * ```\n */\n async terms(code: string): Promise<CodeTermInfo[]> {\n return this.client.get<CodeTermInfo[]>(\n `/api/v1/codes/${encodeURIComponent(code)}/terms`\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,210 +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
- * Get all indexed terms/synonyms for an ICD-10 code.
179
- *
180
- * @example
181
- * ```ts
182
- * const terms = await autoicd.codes.terms("E11.9");
183
- * terms.forEach(t => console.log(t.term, t.term_type));
184
- * ```
185
- */
186
- async terms(code) {
187
- return this.client.get(
188
- `/api/v1/codes/${encodeURIComponent(code)}/terms`
189
- );
190
- }
191
- };
192
- function parseRateLimit(headers) {
193
- const limit = headers.get("X-RateLimit-Limit");
194
- const remaining = headers.get("X-RateLimit-Remaining");
195
- const reset = headers.get("X-RateLimit-Reset");
196
- if (!limit || !remaining || !reset) return null;
197
- return {
198
- limit: parseInt(limit, 10),
199
- remaining: parseInt(remaining, 10),
200
- resetAt: new Date(reset)
201
- };
202
- }
203
- export {
204
- AuthenticationError,
205
- AutoICD,
206
- AutoICDError,
207
- NotFoundError,
208
- RateLimitError
209
- };
210
- //# 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 CodeTermInfo,\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 * Get all indexed terms/synonyms for an ICD-10 code.\n *\n * @example\n * ```ts\n * const terms = await autoicd.codes.terms(\"E11.9\");\n * terms.forEach(t => console.log(t.term, t.term_type));\n * ```\n */\n async terms(code: string): Promise<CodeTermInfo[]> {\n return this.client.get<CodeTermInfo[]>(\n `/api/v1/codes/${encodeURIComponent(code)}/terms`\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":[]}