@blindfold/sdk 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Blindfold
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -4,7 +4,11 @@ The official JavaScript/TypeScript SDK for Blindfold - The Privacy API for AI.
4
4
 
5
5
  Securely tokenize, mask, redact, and encrypt sensitive data (PII) before sending it to LLMs or third-party services.
6
6
 
7
- ## Installation
7
+ ## How to use it
8
+
9
+ ### 1. Install SDK
10
+
11
+ Javascript/ Typescript
8
12
 
9
13
  ```bash
10
14
  npm install @blindfold/sdk
@@ -14,7 +18,21 @@ yarn add @blindfold/sdk
14
18
  pnpm add @blindfold/sdk
15
19
  ```
16
20
 
17
- ## Usage
21
+ Python SDK
22
+
23
+ ```bash
24
+ pip install blindfold-sdk
25
+ ```
26
+
27
+ ### 2. Get Blindfold API key
28
+
29
+ 1. Sign up to Blindfold here.
30
+ 1. Sign up to Blindfold [here](https://www.blindfold.dev/).
31
+ 3. Get your API key [here](https://app.blindfold.dev/api-keys).
32
+ 3. Set environment variable with your API key
33
+ ```
34
+ BLINDFOLD_API_KEY=sk-***
35
+ ```
18
36
 
19
37
  ### Initialization
20
38
 
@@ -30,38 +48,46 @@ const client = new Blindfold({
30
48
 
31
49
  ### Tokenize (Reversible)
32
50
 
33
- Replace sensitive data with reversible tokens (e.g., `<PERSON_1>`).
51
+ Replace sensitive data with reversible tokens (e.g., `<Person_1>`).
34
52
 
35
53
  ```typescript
36
54
  const response = await client.tokenize(
37
55
  "Contact John Doe at john@example.com",
38
56
  {
57
+ // Optional: Use a pre-configured policy
58
+ policy: 'gdpr_eu', // or 'hipaa_us', 'basic'
39
59
  // Optional: Filter specific entities
40
- entities: ['PERSON', 'EMAIL_ADDRESS'],
60
+ entities: ['person', 'email address'],
41
61
  // Optional: Set confidence threshold
42
62
  score_threshold: 0.4
43
63
  }
44
64
  );
45
65
 
46
- console.log(response.text);
47
- // "Contact <PERSON_1> at <EMAIL_ADDRESS_1>"
66
+ console.log(response.text);
67
+ // "Contact <Person_1> at <Email Address_1>"
48
68
 
49
69
  console.log(response.mapping);
50
- // { "<PERSON_1>": "John Doe", "<EMAIL_ADDRESS_1>": "john@example.com" }
70
+ // { "<Person_1>": "John Doe", "<Email Address_1>": "john@example.com" }
51
71
  ```
52
72
 
53
73
  ### Detokenize
54
74
 
55
75
  Restore original values from tokens.
56
76
 
77
+ **⚡ Note:** Detokenization is performed **client-side** for better performance, security, and offline support. No API call is made.
78
+
57
79
  ```typescript
58
- const original = await client.detokenize(
59
- "AI response for <PERSON_1>",
80
+ // No await needed - runs locally!
81
+ const original = client.detokenize(
82
+ "AI response for <Person_1>",
60
83
  response.mapping
61
84
  );
62
85
 
63
86
  console.log(original.text);
64
87
  // "AI response for John Doe"
88
+
89
+ console.log(original.replacements_made);
90
+ // 1
65
91
  ```
66
92
 
67
93
  ### Mask
@@ -90,7 +116,7 @@ Permanently remove sensitive data.
90
116
  const response = await client.redact(
91
117
  "My password is secret123",
92
118
  {
93
- entities: ['PASSWORD'] // If supported
119
+ entities: ['person', 'email address']
94
120
  }
95
121
  );
96
122
  ```
@@ -143,17 +169,19 @@ const response = await client.encrypt(
143
169
  ### Entity Types
144
170
 
145
171
  Common supported entities:
146
- - `PERSON`
147
- - `EMAIL_ADDRESS`
148
- - `PHONE_NUMBER`
149
- - `CREDIT_CARD`
150
- - `IP_ADDRESS`
151
- - `LOCATION`
152
- - `DATE_TIME`
153
- - `URL`
154
- - `IBAN_CODE`
155
- - `US_SSN`
156
- - `MEDICAL_LICENSE`
172
+ - `person`
173
+ - `email address`
174
+ - `phone number`
175
+ - `credit card number`
176
+ - `ip address`
177
+ - `address`
178
+ - `date of birth`
179
+ - `organization`
180
+ - `iban`
181
+ - `social security number`
182
+ - `medical condition`
183
+ - `passport number`
184
+ - `driver's license number`
157
185
 
158
186
  ### Error Handling
159
187
 
package/dist/index.d.mts CHANGED
@@ -17,12 +17,34 @@ interface TokenizeConfig {
17
17
  entities?: string[];
18
18
  /** Minimum confidence score for entity detection (0.0-1.0) */
19
19
  score_threshold?: number;
20
+ /** Policy name to use for detection configuration (e.g., 'gdpr_eu', 'hipaa_us', 'basic') */
21
+ policy?: string;
22
+ }
23
+ /**
24
+ * Configuration options for detection (no text transformation)
25
+ */
26
+ interface DetectConfig {
27
+ /** List of entities to detect */
28
+ entities?: string[];
29
+ /** Minimum confidence score for entity detection (0.0-1.0) */
30
+ score_threshold?: number;
31
+ /** Policy name to use for detection configuration (e.g., 'gdpr_eu', 'hipaa_us', 'basic') */
32
+ policy?: string;
33
+ }
34
+ /**
35
+ * Response from detect endpoint
36
+ */
37
+ interface DetectResponse {
38
+ /** List of detected entities */
39
+ detected_entities: DetectedEntity[];
40
+ /** Count of detected entities */
41
+ entities_count: number;
20
42
  }
21
43
  /**
22
44
  * Detected entity information
23
45
  */
24
46
  interface DetectedEntity {
25
- /** Entity type (e.g., PERSON, EMAIL_ADDRESS) */
47
+ /** Entity type (e.g., "person", "email address", "phone number") */
26
48
  entity_type: string;
27
49
  /** Original text of the entity */
28
50
  text: string;
@@ -65,6 +87,8 @@ interface RedactConfig {
65
87
  entities?: string[];
66
88
  /** Minimum confidence score for entity detection (0.0-1.0) */
67
89
  score_threshold?: number;
90
+ /** Policy name to use for detection configuration (e.g., 'gdpr_eu', 'hipaa_us', 'basic') */
91
+ policy?: string;
68
92
  }
69
93
  /**
70
94
  * Response from redact endpoint
@@ -91,6 +115,8 @@ interface MaskConfig {
91
115
  entities?: string[];
92
116
  /** Minimum confidence score for entity detection (0.0-1.0) */
93
117
  score_threshold?: number;
118
+ /** Policy name to use for detection configuration (e.g., 'gdpr_eu', 'hipaa_us', 'basic') */
119
+ policy?: string;
94
120
  }
95
121
  /**
96
122
  * Response from mask endpoint
@@ -113,6 +139,8 @@ interface SynthesizeConfig {
113
139
  entities?: string[];
114
140
  /** Minimum confidence score for entity detection (0.0-1.0) */
115
141
  score_threshold?: number;
142
+ /** Policy name to use for detection configuration (e.g., 'gdpr_eu', 'hipaa_us', 'basic') */
143
+ policy?: string;
116
144
  }
117
145
  /**
118
146
  * Response from synthesis endpoint
@@ -139,6 +167,8 @@ interface HashConfig {
139
167
  entities?: string[];
140
168
  /** Minimum confidence score for entity detection (0.0-1.0) */
141
169
  score_threshold?: number;
170
+ /** Policy name to use for detection configuration (e.g., 'gdpr_eu', 'hipaa_us', 'basic') */
171
+ policy?: string;
142
172
  }
143
173
  /**
144
174
  * Response from hash endpoint
@@ -161,6 +191,8 @@ interface EncryptConfig {
161
191
  entities?: string[];
162
192
  /** Minimum confidence score for entity detection (0.0-1.0) */
163
193
  score_threshold?: number;
194
+ /** Policy name to use for detection configuration (e.g., 'gdpr_eu', 'hipaa_us', 'basic') */
195
+ policy?: string;
164
196
  }
165
197
  /**
166
198
  * Response from encrypt endpoint
@@ -204,13 +236,28 @@ declare class Blindfold {
204
236
  * @returns Promise with tokenized text and mapping
205
237
  */
206
238
  tokenize(text: string, config?: TokenizeConfig): Promise<TokenizeResponse>;
239
+ /**
240
+ * Detect PII in text without modifying it
241
+ *
242
+ * Returns only the detected entities with their types, positions,
243
+ * and confidence scores. The original text is not transformed.
244
+ *
245
+ * @param text - Text to analyze for PII
246
+ * @param config - Optional configuration (entities, score_threshold, policy)
247
+ * @returns Promise with detected entities
248
+ */
249
+ detect(text: string, config?: DetectConfig): Promise<DetectResponse>;
207
250
  /**
208
251
  * Detokenize text by replacing tokens with original values
252
+ *
253
+ * This method performs detokenization CLIENT-SIDE for better performance,
254
+ * security, and to work offline. No API call is made.
255
+ *
209
256
  * @param text - Tokenized text
210
257
  * @param mapping - Token mapping from tokenize response
211
- * @returns Promise with original text
258
+ * @returns DetokenizeResponse with original text
212
259
  */
213
- detokenize(text: string, mapping: Record<string, string>): Promise<DetokenizeResponse>;
260
+ detokenize(text: string, mapping: Record<string, string>): DetokenizeResponse;
214
261
  /**
215
262
  * Redact (permanently remove) sensitive information from text
216
263
  *
@@ -272,8 +319,8 @@ declare class AuthenticationError extends BlindfoldError {
272
319
  */
273
320
  declare class APIError extends BlindfoldError {
274
321
  statusCode: number;
275
- responseBody?: any;
276
- constructor(message: string, statusCode: number, responseBody?: any);
322
+ responseBody?: unknown;
323
+ constructor(message: string, statusCode: number, responseBody?: unknown);
277
324
  }
278
325
  /**
279
326
  * Error thrown when network request fails
@@ -282,4 +329,4 @@ declare class NetworkError extends BlindfoldError {
282
329
  constructor(message?: string);
283
330
  }
284
331
 
285
- export { APIError, type APIErrorResponse, AuthenticationError, Blindfold, type BlindfoldConfig, BlindfoldError, type DetectedEntity, type DetokenizeResponse, NetworkError, type TokenizeConfig, type TokenizeResponse };
332
+ export { APIError, type APIErrorResponse, AuthenticationError, Blindfold, type BlindfoldConfig, BlindfoldError, type DetectConfig, type DetectResponse, type DetectedEntity, type DetokenizeResponse, NetworkError, type TokenizeConfig, type TokenizeResponse };
package/dist/index.d.ts CHANGED
@@ -17,12 +17,34 @@ interface TokenizeConfig {
17
17
  entities?: string[];
18
18
  /** Minimum confidence score for entity detection (0.0-1.0) */
19
19
  score_threshold?: number;
20
+ /** Policy name to use for detection configuration (e.g., 'gdpr_eu', 'hipaa_us', 'basic') */
21
+ policy?: string;
22
+ }
23
+ /**
24
+ * Configuration options for detection (no text transformation)
25
+ */
26
+ interface DetectConfig {
27
+ /** List of entities to detect */
28
+ entities?: string[];
29
+ /** Minimum confidence score for entity detection (0.0-1.0) */
30
+ score_threshold?: number;
31
+ /** Policy name to use for detection configuration (e.g., 'gdpr_eu', 'hipaa_us', 'basic') */
32
+ policy?: string;
33
+ }
34
+ /**
35
+ * Response from detect endpoint
36
+ */
37
+ interface DetectResponse {
38
+ /** List of detected entities */
39
+ detected_entities: DetectedEntity[];
40
+ /** Count of detected entities */
41
+ entities_count: number;
20
42
  }
21
43
  /**
22
44
  * Detected entity information
23
45
  */
24
46
  interface DetectedEntity {
25
- /** Entity type (e.g., PERSON, EMAIL_ADDRESS) */
47
+ /** Entity type (e.g., "person", "email address", "phone number") */
26
48
  entity_type: string;
27
49
  /** Original text of the entity */
28
50
  text: string;
@@ -65,6 +87,8 @@ interface RedactConfig {
65
87
  entities?: string[];
66
88
  /** Minimum confidence score for entity detection (0.0-1.0) */
67
89
  score_threshold?: number;
90
+ /** Policy name to use for detection configuration (e.g., 'gdpr_eu', 'hipaa_us', 'basic') */
91
+ policy?: string;
68
92
  }
69
93
  /**
70
94
  * Response from redact endpoint
@@ -91,6 +115,8 @@ interface MaskConfig {
91
115
  entities?: string[];
92
116
  /** Minimum confidence score for entity detection (0.0-1.0) */
93
117
  score_threshold?: number;
118
+ /** Policy name to use for detection configuration (e.g., 'gdpr_eu', 'hipaa_us', 'basic') */
119
+ policy?: string;
94
120
  }
95
121
  /**
96
122
  * Response from mask endpoint
@@ -113,6 +139,8 @@ interface SynthesizeConfig {
113
139
  entities?: string[];
114
140
  /** Minimum confidence score for entity detection (0.0-1.0) */
115
141
  score_threshold?: number;
142
+ /** Policy name to use for detection configuration (e.g., 'gdpr_eu', 'hipaa_us', 'basic') */
143
+ policy?: string;
116
144
  }
117
145
  /**
118
146
  * Response from synthesis endpoint
@@ -139,6 +167,8 @@ interface HashConfig {
139
167
  entities?: string[];
140
168
  /** Minimum confidence score for entity detection (0.0-1.0) */
141
169
  score_threshold?: number;
170
+ /** Policy name to use for detection configuration (e.g., 'gdpr_eu', 'hipaa_us', 'basic') */
171
+ policy?: string;
142
172
  }
143
173
  /**
144
174
  * Response from hash endpoint
@@ -161,6 +191,8 @@ interface EncryptConfig {
161
191
  entities?: string[];
162
192
  /** Minimum confidence score for entity detection (0.0-1.0) */
163
193
  score_threshold?: number;
194
+ /** Policy name to use for detection configuration (e.g., 'gdpr_eu', 'hipaa_us', 'basic') */
195
+ policy?: string;
164
196
  }
165
197
  /**
166
198
  * Response from encrypt endpoint
@@ -204,13 +236,28 @@ declare class Blindfold {
204
236
  * @returns Promise with tokenized text and mapping
205
237
  */
206
238
  tokenize(text: string, config?: TokenizeConfig): Promise<TokenizeResponse>;
239
+ /**
240
+ * Detect PII in text without modifying it
241
+ *
242
+ * Returns only the detected entities with their types, positions,
243
+ * and confidence scores. The original text is not transformed.
244
+ *
245
+ * @param text - Text to analyze for PII
246
+ * @param config - Optional configuration (entities, score_threshold, policy)
247
+ * @returns Promise with detected entities
248
+ */
249
+ detect(text: string, config?: DetectConfig): Promise<DetectResponse>;
207
250
  /**
208
251
  * Detokenize text by replacing tokens with original values
252
+ *
253
+ * This method performs detokenization CLIENT-SIDE for better performance,
254
+ * security, and to work offline. No API call is made.
255
+ *
209
256
  * @param text - Tokenized text
210
257
  * @param mapping - Token mapping from tokenize response
211
- * @returns Promise with original text
258
+ * @returns DetokenizeResponse with original text
212
259
  */
213
- detokenize(text: string, mapping: Record<string, string>): Promise<DetokenizeResponse>;
260
+ detokenize(text: string, mapping: Record<string, string>): DetokenizeResponse;
214
261
  /**
215
262
  * Redact (permanently remove) sensitive information from text
216
263
  *
@@ -272,8 +319,8 @@ declare class AuthenticationError extends BlindfoldError {
272
319
  */
273
320
  declare class APIError extends BlindfoldError {
274
321
  statusCode: number;
275
- responseBody?: any;
276
- constructor(message: string, statusCode: number, responseBody?: any);
322
+ responseBody?: unknown;
323
+ constructor(message: string, statusCode: number, responseBody?: unknown);
277
324
  }
278
325
  /**
279
326
  * Error thrown when network request fails
@@ -282,4 +329,4 @@ declare class NetworkError extends BlindfoldError {
282
329
  constructor(message?: string);
283
330
  }
284
331
 
285
- export { APIError, type APIErrorResponse, AuthenticationError, Blindfold, type BlindfoldConfig, BlindfoldError, type DetectedEntity, type DetokenizeResponse, NetworkError, type TokenizeConfig, type TokenizeResponse };
332
+ export { APIError, type APIErrorResponse, AuthenticationError, Blindfold, type BlindfoldConfig, BlindfoldError, type DetectConfig, type DetectResponse, type DetectedEntity, type DetokenizeResponse, NetworkError, type TokenizeConfig, type TokenizeResponse };
package/dist/index.js CHANGED
@@ -63,9 +63,7 @@ var Blindfold = class {
63
63
  body: body ? JSON.stringify(body) : void 0
64
64
  });
65
65
  if (response.status === 401 || response.status === 403) {
66
- throw new AuthenticationError(
67
- "Authentication failed. Please check your API key."
68
- );
66
+ throw new AuthenticationError("Authentication failed. Please check your API key.");
69
67
  }
70
68
  if (!response.ok) {
71
69
  let errorMessage = `API request failed with status ${response.status}`;
@@ -89,9 +87,7 @@ var Blindfold = class {
89
87
  "Network request failed. Please check your connection and the API URL."
90
88
  );
91
89
  }
92
- throw new NetworkError(
93
- error instanceof Error ? error.message : "Unknown error occurred"
94
- );
90
+ throw new NetworkError(error instanceof Error ? error.message : "Unknown error occurred");
95
91
  }
96
92
  }
97
93
  /**
@@ -106,17 +102,49 @@ var Blindfold = class {
106
102
  ...config
107
103
  });
108
104
  }
105
+ /**
106
+ * Detect PII in text without modifying it
107
+ *
108
+ * Returns only the detected entities with their types, positions,
109
+ * and confidence scores. The original text is not transformed.
110
+ *
111
+ * @param text - Text to analyze for PII
112
+ * @param config - Optional configuration (entities, score_threshold, policy)
113
+ * @returns Promise with detected entities
114
+ */
115
+ async detect(text, config) {
116
+ return this.request("/detect", "POST", {
117
+ text,
118
+ ...config
119
+ });
120
+ }
109
121
  /**
110
122
  * Detokenize text by replacing tokens with original values
123
+ *
124
+ * This method performs detokenization CLIENT-SIDE for better performance,
125
+ * security, and to work offline. No API call is made.
126
+ *
111
127
  * @param text - Tokenized text
112
128
  * @param mapping - Token mapping from tokenize response
113
- * @returns Promise with original text
129
+ * @returns DetokenizeResponse with original text
114
130
  */
115
- async detokenize(text, mapping) {
116
- return this.request("/detokenize", "POST", {
117
- text,
118
- mapping
119
- });
131
+ detokenize(text, mapping) {
132
+ let result = text;
133
+ let replacements = 0;
134
+ const sortedTokens = Object.keys(mapping).sort((a, b) => b.length - a.length);
135
+ for (const token of sortedTokens) {
136
+ const originalValue = mapping[token];
137
+ const regex = new RegExp(token.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g");
138
+ const matches = result.match(regex);
139
+ if (matches) {
140
+ result = result.replace(regex, originalValue);
141
+ replacements += matches.length;
142
+ }
143
+ }
144
+ return {
145
+ text: result,
146
+ replacements_made: replacements
147
+ };
120
148
  }
121
149
  /**
122
150
  * Redact (permanently remove) sensitive information from text
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Base error class for Blindfold SDK\n */\nexport class BlindfoldError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'BlindfoldError'\n Object.setPrototypeOf(this, BlindfoldError.prototype)\n }\n}\n\n/**\n * Error thrown when authentication fails\n */\nexport class AuthenticationError extends BlindfoldError {\n constructor(message: string = 'Authentication failed. Please check your API key.') {\n super(message)\n this.name = 'AuthenticationError'\n Object.setPrototypeOf(this, AuthenticationError.prototype)\n }\n}\n\n/**\n * Error thrown when API request fails\n */\nexport class APIError extends BlindfoldError {\n statusCode: number\n responseBody?: any\n\n constructor(message: string, statusCode: number, responseBody?: any) {\n super(message)\n this.name = 'APIError'\n this.statusCode = statusCode\n this.responseBody = responseBody\n Object.setPrototypeOf(this, APIError.prototype)\n }\n}\n\n/**\n * Error thrown when network request fails\n */\nexport class NetworkError extends BlindfoldError {\n constructor(message: string = 'Network request failed. Please check your connection.') {\n super(message)\n this.name = 'NetworkError'\n Object.setPrototypeOf(this, NetworkError.prototype)\n }\n}\n","import type {\n BlindfoldConfig,\n TokenizeConfig,\n TokenizeResponse,\n DetokenizeResponse,\n RedactConfig,\n RedactResponse,\n MaskConfig,\n MaskResponse,\n SynthesizeConfig,\n SynthesizeResponse,\n HashConfig,\n HashResponse,\n EncryptConfig,\n EncryptResponse,\n APIErrorResponse,\n} from './types'\nimport { AuthenticationError, APIError, NetworkError } from './errors'\n\nconst DEFAULT_BASE_URL = 'https://api.blindfold.dev/api/public/v1'\n\n/**\n * Blindfold client for tokenization and detokenization\n */\nexport class Blindfold {\n private apiKey: string\n private baseUrl: string\n private userId?: string\n\n /**\n * Create a new Blindfold client\n * @param config - Configuration options\n */\n constructor(config: BlindfoldConfig) {\n this.apiKey = config.apiKey\n this.baseUrl = config.baseUrl || DEFAULT_BASE_URL\n this.userId = config.userId\n }\n\n /**\n * Make an authenticated request to the API\n */\n private async request<T>(\n endpoint: string,\n method: string,\n body?: any\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-API-Key': this.apiKey,\n }\n\n if (this.userId) {\n headers['X-Blindfold-User-Id'] = this.userId\n }\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n })\n\n // Handle authentication errors\n if (response.status === 401 || response.status === 403) {\n throw new AuthenticationError(\n 'Authentication failed. Please check your API key.'\n )\n }\n\n // Handle other error responses\n if (!response.ok) {\n let errorMessage = `API request failed with status ${response.status}`\n let responseBody: any\n\n try {\n responseBody = await response.json()\n const errorData = responseBody as APIErrorResponse\n errorMessage = errorData.detail || errorData.message || errorMessage\n } catch {\n // If we can't parse the error response, use the status text\n errorMessage = `${errorMessage}: ${response.statusText}`\n }\n\n throw new APIError(errorMessage, response.status, responseBody)\n }\n\n return (await response.json()) as T\n } catch (error) {\n // Re-throw our custom errors\n if (\n error instanceof AuthenticationError ||\n error instanceof APIError\n ) {\n throw error\n }\n\n // Handle network errors\n if (error instanceof TypeError && error.message.includes('fetch')) {\n throw new NetworkError(\n 'Network request failed. Please check your connection and the API URL.'\n )\n }\n\n // Handle other errors\n throw new NetworkError(\n error instanceof Error ? error.message : 'Unknown error occurred'\n )\n }\n }\n\n /**\n * Tokenize text by replacing sensitive information with tokens\n * @param text - Text to tokenize\n * @param config - Optional configuration\n * @returns Promise with tokenized text and mapping\n */\n async tokenize(\n text: string,\n config?: TokenizeConfig\n ): Promise<TokenizeResponse> {\n return this.request<TokenizeResponse>('/tokenize', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Detokenize text by replacing tokens with original values\n * @param text - Tokenized text\n * @param mapping - Token mapping from tokenize response\n * @returns Promise with original text\n */\n async detokenize(\n text: string,\n mapping: Record<string, string>\n ): Promise<DetokenizeResponse> {\n return this.request<DetokenizeResponse>('/detokenize', 'POST', {\n text,\n mapping,\n })\n }\n\n /**\n * Redact (permanently remove) sensitive information from text\n *\n * WARNING: Redaction is irreversible - original data cannot be restored!\n *\n * @param text - Text to redact\n * @param config - Optional configuration (masking_char, entities)\n * @returns Promise with redacted text and detected entities\n */\n async redact(\n text: string,\n config?: RedactConfig\n ): Promise<RedactResponse> {\n return this.request<RedactResponse>('/redact', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Mask (partially hide) sensitive information from text\n *\n * @param text - Text to mask\n * @param config - Optional configuration (chars_to_show, from_end, masking_char, entities)\n * @returns Promise with masked text and detected entities\n */\n async mask(\n text: string,\n config?: MaskConfig\n ): Promise<MaskResponse> {\n return this.request<MaskResponse>('/mask', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Synthesize (replace real data with synthetic fake data)\n *\n * @param text - Text to synthesize\n * @param config - Optional configuration (language, entities)\n * @returns Promise with synthetic text and detected entities\n */\n async synthesize(\n text: string,\n config?: SynthesizeConfig\n ): Promise<SynthesizeResponse> {\n return this.request<SynthesizeResponse>('/synthesize', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Hash (replace with deterministic hash values)\n *\n * @param text - Text to hash\n * @param config - Optional configuration (hash_type, hash_prefix, hash_length, entities)\n * @returns Promise with hashed text and detected entities\n */\n async hash(\n text: string,\n config?: HashConfig\n ): Promise<HashResponse> {\n return this.request<HashResponse>('/hash', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Encrypt (reversibly protect) sensitive data in text using AES encryption\n *\n * @param text - Text to encrypt\n * @param config - Optional configuration (encryption_key, entities)\n * @returns Promise with encrypted text and detected entities\n */\n async encrypt(\n text: string,\n config?: EncryptConfig\n ): Promise<EncryptResponse> {\n return this.request<EncryptResponse>('/encrypt', 'POST', {\n text,\n ...config,\n })\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/client.ts"],"names":[],"mappings":";;;AAGO,IAAM,cAAA,GAAN,MAAM,eAAA,SAAuB,KAAA,CAAM;AAAA,EACxC,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,eAAA,CAAe,SAAS,CAAA;AAAA,EACtD;AACF;AAKO,IAAM,mBAAA,GAAN,MAAM,oBAAA,SAA4B,cAAA,CAAe;AAAA,EACtD,WAAA,CAAY,UAAkB,mDAAA,EAAqD;AACjF,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,oBAAA,CAAoB,SAAS,CAAA;AAAA,EAC3D;AACF;AAKO,IAAM,QAAA,GAAN,MAAM,SAAA,SAAiB,cAAA,CAAe;AAAA,EAI3C,WAAA,CAAY,OAAA,EAAiB,UAAA,EAAoB,YAAA,EAAwB;AACvE,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,UAAA;AACZ,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAClB,IAAA,IAAA,CAAK,YAAA,GAAe,YAAA;AACpB,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,SAAA,CAAS,SAAS,CAAA;AAAA,EAChD;AACF;AAKO,IAAM,YAAA,GAAN,MAAM,aAAA,SAAqB,cAAA,CAAe;AAAA,EAC/C,WAAA,CAAY,UAAkB,uDAAA,EAAyD;AACrF,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,aAAA,CAAa,SAAS,CAAA;AAAA,EACpD;AACF;;;AC1BA,IAAM,gBAAA,GAAmB,yCAAA;AAKlB,IAAM,YAAN,MAAgB;AAAA;AAAA;AAAA;AAAA;AAAA,EASrB,YAAY,MAAA,EAAyB;AACnC,IAAA,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AACrB,IAAA,IAAA,CAAK,OAAA,GAAU,OAAO,OAAA,IAAW,gBAAA;AACjC,IAAA,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,OAAA,CACZ,QAAA,EACA,MAAA,EACA,IAAA,EACY;AACZ,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,IAAA,CAAK,OAAO,GAAG,QAAQ,CAAA,CAAA;AAEtC,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,cAAA,EAAgB,kBAAA;AAAA,MAChB,aAAa,IAAA,CAAK;AAAA,KACpB;AAEA,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA,OAAA,CAAQ,qBAAqB,IAAI,IAAA,CAAK,MAAA;AAAA,IACxC;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,QAChC,MAAA;AAAA,QACA,OAAA;AAAA,QACA,IAAA,EAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,GAAI,KAAA;AAAA,OACrC,CAAA;AAGD,MAAA,IAAI,QAAA,CAAS,MAAA,KAAW,GAAA,IAAO,QAAA,CAAS,WAAW,GAAA,EAAK;AACtD,QAAA,MAAM,IAAI,oBAAoB,mDAAmD,CAAA;AAAA,MACnF;AAGA,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,IAAI,YAAA,GAAe,CAAA,+BAAA,EAAkC,QAAA,CAAS,MAAM,CAAA,CAAA;AACpE,QAAA,IAAI,YAAA;AAEJ,QAAA,IAAI;AACF,UAAA,YAAA,GAAe,MAAM,SAAS,IAAA,EAAK;AACnC,UAAA,MAAM,SAAA,GAAY,YAAA;AAClB,UAAA,YAAA,GAAe,SAAA,CAAU,MAAA,IAAU,SAAA,CAAU,OAAA,IAAW,YAAA;AAAA,QAC1D,CAAA,CAAA,MAAQ;AAEN,UAAA,YAAA,GAAe,CAAA,EAAG,YAAY,CAAA,EAAA,EAAK,QAAA,CAAS,UAAU,CAAA,CAAA;AAAA,QACxD;AAEA,QAAA,MAAM,IAAI,QAAA,CAAS,YAAA,EAAc,QAAA,CAAS,QAAQ,YAAY,CAAA;AAAA,MAChE;AAEA,MAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,IAC9B,SAAS,KAAA,EAAO;AAEd,MAAA,IAAI,KAAA,YAAiB,mBAAA,IAAuB,KAAA,YAAiB,QAAA,EAAU;AACrE,QAAA,MAAM,KAAA;AAAA,MACR;AAGA,MAAA,IAAI,iBAAiB,SAAA,IAAa,KAAA,CAAM,OAAA,CAAQ,QAAA,CAAS,OAAO,CAAA,EAAG;AACjE,QAAA,MAAM,IAAI,YAAA;AAAA,UACR;AAAA,SACF;AAAA,MACF;AAGA,MAAA,MAAM,IAAI,YAAA,CAAa,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,UAAU,wBAAwB,CAAA;AAAA,IAC1F;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QAAA,CAAS,IAAA,EAAc,MAAA,EAAoD;AAC/E,IAAA,OAAO,IAAA,CAAK,OAAA,CAA0B,WAAA,EAAa,MAAA,EAAQ;AAAA,MACzD,IAAA;AAAA,MACA,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,MAAA,CAAO,IAAA,EAAc,MAAA,EAAgD;AACzE,IAAA,OAAO,IAAA,CAAK,OAAA,CAAwB,SAAA,EAAW,MAAA,EAAQ;AAAA,MACrD,IAAA;AAAA,MACA,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,UAAA,CAAW,MAAc,OAAA,EAAqD;AAC5E,IAAA,IAAI,MAAA,GAAS,IAAA;AACb,IAAA,IAAI,YAAA,GAAe,CAAA;AAGnB,IAAA,MAAM,YAAA,GAAe,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,MAAA,GAAS,CAAA,CAAE,MAAM,CAAA;AAE5E,IAAA,KAAA,MAAW,SAAS,YAAA,EAAc;AAChC,MAAA,MAAM,aAAA,GAAgB,QAAQ,KAAK,CAAA;AACnC,MAAA,MAAM,KAAA,GAAQ,IAAI,MAAA,CAAO,KAAA,CAAM,QAAQ,qBAAA,EAAuB,MAAM,GAAG,GAAG,CAAA;AAC1E,MAAA,MAAM,OAAA,GAAU,MAAA,CAAO,KAAA,CAAM,KAAK,CAAA;AAElC,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,MAAA,GAAS,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,aAAa,CAAA;AAC5C,QAAA,YAAA,IAAgB,OAAA,CAAQ,MAAA;AAAA,MAC1B;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,MAAA;AAAA,MACN,iBAAA,EAAmB;AAAA,KACrB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,MAAA,CAAO,IAAA,EAAc,MAAA,EAAgD;AACzE,IAAA,OAAO,IAAA,CAAK,OAAA,CAAwB,SAAA,EAAW,MAAA,EAAQ;AAAA,MACrD,IAAA;AAAA,MACA,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IAAA,CAAK,IAAA,EAAc,MAAA,EAA4C;AACnE,IAAA,OAAO,IAAA,CAAK,OAAA,CAAsB,OAAA,EAAS,MAAA,EAAQ;AAAA,MACjD,IAAA;AAAA,MACA,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,UAAA,CAAW,IAAA,EAAc,MAAA,EAAwD;AACrF,IAAA,OAAO,IAAA,CAAK,OAAA,CAA4B,aAAA,EAAe,MAAA,EAAQ;AAAA,MAC7D,IAAA;AAAA,MACA,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IAAA,CAAK,IAAA,EAAc,MAAA,EAA4C;AACnE,IAAA,OAAO,IAAA,CAAK,OAAA,CAAsB,OAAA,EAAS,MAAA,EAAQ;AAAA,MACjD,IAAA;AAAA,MACA,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OAAA,CAAQ,IAAA,EAAc,MAAA,EAAkD;AAC5E,IAAA,OAAO,IAAA,CAAK,OAAA,CAAyB,UAAA,EAAY,MAAA,EAAQ;AAAA,MACvD,IAAA;AAAA,MACA,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AACF","file":"index.js","sourcesContent":["/**\n * Base error class for Blindfold SDK\n */\nexport class BlindfoldError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'BlindfoldError'\n Object.setPrototypeOf(this, BlindfoldError.prototype)\n }\n}\n\n/**\n * Error thrown when authentication fails\n */\nexport class AuthenticationError extends BlindfoldError {\n constructor(message: string = 'Authentication failed. Please check your API key.') {\n super(message)\n this.name = 'AuthenticationError'\n Object.setPrototypeOf(this, AuthenticationError.prototype)\n }\n}\n\n/**\n * Error thrown when API request fails\n */\nexport class APIError extends BlindfoldError {\n statusCode: number\n responseBody?: unknown\n\n constructor(message: string, statusCode: number, responseBody?: unknown) {\n super(message)\n this.name = 'APIError'\n this.statusCode = statusCode\n this.responseBody = responseBody\n Object.setPrototypeOf(this, APIError.prototype)\n }\n}\n\n/**\n * Error thrown when network request fails\n */\nexport class NetworkError extends BlindfoldError {\n constructor(message: string = 'Network request failed. Please check your connection.') {\n super(message)\n this.name = 'NetworkError'\n Object.setPrototypeOf(this, NetworkError.prototype)\n }\n}\n","import type {\n BlindfoldConfig,\n DetectConfig,\n DetectResponse,\n TokenizeConfig,\n TokenizeResponse,\n DetokenizeResponse,\n RedactConfig,\n RedactResponse,\n MaskConfig,\n MaskResponse,\n SynthesizeConfig,\n SynthesizeResponse,\n HashConfig,\n HashResponse,\n EncryptConfig,\n EncryptResponse,\n APIErrorResponse,\n} from './types'\nimport { AuthenticationError, APIError, NetworkError } from './errors'\n\nconst DEFAULT_BASE_URL = 'https://api.blindfold.dev/api/public/v1'\n\n/**\n * Blindfold client for tokenization and detokenization\n */\nexport class Blindfold {\n private apiKey: string\n private baseUrl: string\n private userId?: string\n\n /**\n * Create a new Blindfold client\n * @param config - Configuration options\n */\n constructor(config: BlindfoldConfig) {\n this.apiKey = config.apiKey\n this.baseUrl = config.baseUrl || DEFAULT_BASE_URL\n this.userId = config.userId\n }\n\n /**\n * Make an authenticated request to the API\n */\n private async request<T>(\n endpoint: string,\n method: string,\n body?: Record<string, unknown>\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-API-Key': this.apiKey,\n }\n\n if (this.userId) {\n headers['X-Blindfold-User-Id'] = this.userId\n }\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n })\n\n // Handle authentication errors\n if (response.status === 401 || response.status === 403) {\n throw new AuthenticationError('Authentication failed. Please check your API key.')\n }\n\n // Handle other error responses\n if (!response.ok) {\n let errorMessage = `API request failed with status ${response.status}`\n let responseBody: unknown\n\n try {\n responseBody = await response.json()\n const errorData = responseBody as APIErrorResponse\n errorMessage = errorData.detail || errorData.message || errorMessage\n } catch {\n // If we can't parse the error response, use the status text\n errorMessage = `${errorMessage}: ${response.statusText}`\n }\n\n throw new APIError(errorMessage, response.status, responseBody)\n }\n\n return (await response.json()) as T\n } catch (error) {\n // Re-throw our custom errors\n if (error instanceof AuthenticationError || error instanceof APIError) {\n throw error\n }\n\n // Handle network errors\n if (error instanceof TypeError && error.message.includes('fetch')) {\n throw new NetworkError(\n 'Network request failed. Please check your connection and the API URL.'\n )\n }\n\n // Handle other errors\n throw new NetworkError(error instanceof Error ? error.message : 'Unknown error occurred')\n }\n }\n\n /**\n * Tokenize text by replacing sensitive information with tokens\n * @param text - Text to tokenize\n * @param config - Optional configuration\n * @returns Promise with tokenized text and mapping\n */\n async tokenize(text: string, config?: TokenizeConfig): Promise<TokenizeResponse> {\n return this.request<TokenizeResponse>('/tokenize', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Detect PII in text without modifying it\n *\n * Returns only the detected entities with their types, positions,\n * and confidence scores. The original text is not transformed.\n *\n * @param text - Text to analyze for PII\n * @param config - Optional configuration (entities, score_threshold, policy)\n * @returns Promise with detected entities\n */\n async detect(text: string, config?: DetectConfig): Promise<DetectResponse> {\n return this.request<DetectResponse>('/detect', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Detokenize text by replacing tokens with original values\n *\n * This method performs detokenization CLIENT-SIDE for better performance,\n * security, and to work offline. No API call is made.\n *\n * @param text - Tokenized text\n * @param mapping - Token mapping from tokenize response\n * @returns DetokenizeResponse with original text\n */\n detokenize(text: string, mapping: Record<string, string>): DetokenizeResponse {\n let result = text\n let replacements = 0\n\n // Sort tokens by length (longest first) to avoid partial replacements\n const sortedTokens = Object.keys(mapping).sort((a, b) => b.length - a.length)\n\n for (const token of sortedTokens) {\n const originalValue = mapping[token]\n const regex = new RegExp(token.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g')\n const matches = result.match(regex)\n\n if (matches) {\n result = result.replace(regex, originalValue)\n replacements += matches.length\n }\n }\n\n return {\n text: result,\n replacements_made: replacements,\n }\n }\n\n /**\n * Redact (permanently remove) sensitive information from text\n *\n * WARNING: Redaction is irreversible - original data cannot be restored!\n *\n * @param text - Text to redact\n * @param config - Optional configuration (masking_char, entities)\n * @returns Promise with redacted text and detected entities\n */\n async redact(text: string, config?: RedactConfig): Promise<RedactResponse> {\n return this.request<RedactResponse>('/redact', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Mask (partially hide) sensitive information from text\n *\n * @param text - Text to mask\n * @param config - Optional configuration (chars_to_show, from_end, masking_char, entities)\n * @returns Promise with masked text and detected entities\n */\n async mask(text: string, config?: MaskConfig): Promise<MaskResponse> {\n return this.request<MaskResponse>('/mask', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Synthesize (replace real data with synthetic fake data)\n *\n * @param text - Text to synthesize\n * @param config - Optional configuration (language, entities)\n * @returns Promise with synthetic text and detected entities\n */\n async synthesize(text: string, config?: SynthesizeConfig): Promise<SynthesizeResponse> {\n return this.request<SynthesizeResponse>('/synthesize', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Hash (replace with deterministic hash values)\n *\n * @param text - Text to hash\n * @param config - Optional configuration (hash_type, hash_prefix, hash_length, entities)\n * @returns Promise with hashed text and detected entities\n */\n async hash(text: string, config?: HashConfig): Promise<HashResponse> {\n return this.request<HashResponse>('/hash', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Encrypt (reversibly protect) sensitive data in text using AES encryption\n *\n * @param text - Text to encrypt\n * @param config - Optional configuration (encryption_key, entities)\n * @returns Promise with encrypted text and detected entities\n */\n async encrypt(text: string, config?: EncryptConfig): Promise<EncryptResponse> {\n return this.request<EncryptResponse>('/encrypt', 'POST', {\n text,\n ...config,\n })\n }\n}\n"]}
package/dist/index.mjs CHANGED
@@ -61,9 +61,7 @@ var Blindfold = class {
61
61
  body: body ? JSON.stringify(body) : void 0
62
62
  });
63
63
  if (response.status === 401 || response.status === 403) {
64
- throw new AuthenticationError(
65
- "Authentication failed. Please check your API key."
66
- );
64
+ throw new AuthenticationError("Authentication failed. Please check your API key.");
67
65
  }
68
66
  if (!response.ok) {
69
67
  let errorMessage = `API request failed with status ${response.status}`;
@@ -87,9 +85,7 @@ var Blindfold = class {
87
85
  "Network request failed. Please check your connection and the API URL."
88
86
  );
89
87
  }
90
- throw new NetworkError(
91
- error instanceof Error ? error.message : "Unknown error occurred"
92
- );
88
+ throw new NetworkError(error instanceof Error ? error.message : "Unknown error occurred");
93
89
  }
94
90
  }
95
91
  /**
@@ -104,17 +100,49 @@ var Blindfold = class {
104
100
  ...config
105
101
  });
106
102
  }
103
+ /**
104
+ * Detect PII in text without modifying it
105
+ *
106
+ * Returns only the detected entities with their types, positions,
107
+ * and confidence scores. The original text is not transformed.
108
+ *
109
+ * @param text - Text to analyze for PII
110
+ * @param config - Optional configuration (entities, score_threshold, policy)
111
+ * @returns Promise with detected entities
112
+ */
113
+ async detect(text, config) {
114
+ return this.request("/detect", "POST", {
115
+ text,
116
+ ...config
117
+ });
118
+ }
107
119
  /**
108
120
  * Detokenize text by replacing tokens with original values
121
+ *
122
+ * This method performs detokenization CLIENT-SIDE for better performance,
123
+ * security, and to work offline. No API call is made.
124
+ *
109
125
  * @param text - Tokenized text
110
126
  * @param mapping - Token mapping from tokenize response
111
- * @returns Promise with original text
127
+ * @returns DetokenizeResponse with original text
112
128
  */
113
- async detokenize(text, mapping) {
114
- return this.request("/detokenize", "POST", {
115
- text,
116
- mapping
117
- });
129
+ detokenize(text, mapping) {
130
+ let result = text;
131
+ let replacements = 0;
132
+ const sortedTokens = Object.keys(mapping).sort((a, b) => b.length - a.length);
133
+ for (const token of sortedTokens) {
134
+ const originalValue = mapping[token];
135
+ const regex = new RegExp(token.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g");
136
+ const matches = result.match(regex);
137
+ if (matches) {
138
+ result = result.replace(regex, originalValue);
139
+ replacements += matches.length;
140
+ }
141
+ }
142
+ return {
143
+ text: result,
144
+ replacements_made: replacements
145
+ };
118
146
  }
119
147
  /**
120
148
  * Redact (permanently remove) sensitive information from text
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Base error class for Blindfold SDK\n */\nexport class BlindfoldError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'BlindfoldError'\n Object.setPrototypeOf(this, BlindfoldError.prototype)\n }\n}\n\n/**\n * Error thrown when authentication fails\n */\nexport class AuthenticationError extends BlindfoldError {\n constructor(message: string = 'Authentication failed. Please check your API key.') {\n super(message)\n this.name = 'AuthenticationError'\n Object.setPrototypeOf(this, AuthenticationError.prototype)\n }\n}\n\n/**\n * Error thrown when API request fails\n */\nexport class APIError extends BlindfoldError {\n statusCode: number\n responseBody?: any\n\n constructor(message: string, statusCode: number, responseBody?: any) {\n super(message)\n this.name = 'APIError'\n this.statusCode = statusCode\n this.responseBody = responseBody\n Object.setPrototypeOf(this, APIError.prototype)\n }\n}\n\n/**\n * Error thrown when network request fails\n */\nexport class NetworkError extends BlindfoldError {\n constructor(message: string = 'Network request failed. Please check your connection.') {\n super(message)\n this.name = 'NetworkError'\n Object.setPrototypeOf(this, NetworkError.prototype)\n }\n}\n","import type {\n BlindfoldConfig,\n TokenizeConfig,\n TokenizeResponse,\n DetokenizeResponse,\n RedactConfig,\n RedactResponse,\n MaskConfig,\n MaskResponse,\n SynthesizeConfig,\n SynthesizeResponse,\n HashConfig,\n HashResponse,\n EncryptConfig,\n EncryptResponse,\n APIErrorResponse,\n} from './types'\nimport { AuthenticationError, APIError, NetworkError } from './errors'\n\nconst DEFAULT_BASE_URL = 'https://api.blindfold.dev/api/public/v1'\n\n/**\n * Blindfold client for tokenization and detokenization\n */\nexport class Blindfold {\n private apiKey: string\n private baseUrl: string\n private userId?: string\n\n /**\n * Create a new Blindfold client\n * @param config - Configuration options\n */\n constructor(config: BlindfoldConfig) {\n this.apiKey = config.apiKey\n this.baseUrl = config.baseUrl || DEFAULT_BASE_URL\n this.userId = config.userId\n }\n\n /**\n * Make an authenticated request to the API\n */\n private async request<T>(\n endpoint: string,\n method: string,\n body?: any\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-API-Key': this.apiKey,\n }\n\n if (this.userId) {\n headers['X-Blindfold-User-Id'] = this.userId\n }\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n })\n\n // Handle authentication errors\n if (response.status === 401 || response.status === 403) {\n throw new AuthenticationError(\n 'Authentication failed. Please check your API key.'\n )\n }\n\n // Handle other error responses\n if (!response.ok) {\n let errorMessage = `API request failed with status ${response.status}`\n let responseBody: any\n\n try {\n responseBody = await response.json()\n const errorData = responseBody as APIErrorResponse\n errorMessage = errorData.detail || errorData.message || errorMessage\n } catch {\n // If we can't parse the error response, use the status text\n errorMessage = `${errorMessage}: ${response.statusText}`\n }\n\n throw new APIError(errorMessage, response.status, responseBody)\n }\n\n return (await response.json()) as T\n } catch (error) {\n // Re-throw our custom errors\n if (\n error instanceof AuthenticationError ||\n error instanceof APIError\n ) {\n throw error\n }\n\n // Handle network errors\n if (error instanceof TypeError && error.message.includes('fetch')) {\n throw new NetworkError(\n 'Network request failed. Please check your connection and the API URL.'\n )\n }\n\n // Handle other errors\n throw new NetworkError(\n error instanceof Error ? error.message : 'Unknown error occurred'\n )\n }\n }\n\n /**\n * Tokenize text by replacing sensitive information with tokens\n * @param text - Text to tokenize\n * @param config - Optional configuration\n * @returns Promise with tokenized text and mapping\n */\n async tokenize(\n text: string,\n config?: TokenizeConfig\n ): Promise<TokenizeResponse> {\n return this.request<TokenizeResponse>('/tokenize', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Detokenize text by replacing tokens with original values\n * @param text - Tokenized text\n * @param mapping - Token mapping from tokenize response\n * @returns Promise with original text\n */\n async detokenize(\n text: string,\n mapping: Record<string, string>\n ): Promise<DetokenizeResponse> {\n return this.request<DetokenizeResponse>('/detokenize', 'POST', {\n text,\n mapping,\n })\n }\n\n /**\n * Redact (permanently remove) sensitive information from text\n *\n * WARNING: Redaction is irreversible - original data cannot be restored!\n *\n * @param text - Text to redact\n * @param config - Optional configuration (masking_char, entities)\n * @returns Promise with redacted text and detected entities\n */\n async redact(\n text: string,\n config?: RedactConfig\n ): Promise<RedactResponse> {\n return this.request<RedactResponse>('/redact', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Mask (partially hide) sensitive information from text\n *\n * @param text - Text to mask\n * @param config - Optional configuration (chars_to_show, from_end, masking_char, entities)\n * @returns Promise with masked text and detected entities\n */\n async mask(\n text: string,\n config?: MaskConfig\n ): Promise<MaskResponse> {\n return this.request<MaskResponse>('/mask', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Synthesize (replace real data with synthetic fake data)\n *\n * @param text - Text to synthesize\n * @param config - Optional configuration (language, entities)\n * @returns Promise with synthetic text and detected entities\n */\n async synthesize(\n text: string,\n config?: SynthesizeConfig\n ): Promise<SynthesizeResponse> {\n return this.request<SynthesizeResponse>('/synthesize', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Hash (replace with deterministic hash values)\n *\n * @param text - Text to hash\n * @param config - Optional configuration (hash_type, hash_prefix, hash_length, entities)\n * @returns Promise with hashed text and detected entities\n */\n async hash(\n text: string,\n config?: HashConfig\n ): Promise<HashResponse> {\n return this.request<HashResponse>('/hash', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Encrypt (reversibly protect) sensitive data in text using AES encryption\n *\n * @param text - Text to encrypt\n * @param config - Optional configuration (encryption_key, entities)\n * @returns Promise with encrypted text and detected entities\n */\n async encrypt(\n text: string,\n config?: EncryptConfig\n ): Promise<EncryptResponse> {\n return this.request<EncryptResponse>('/encrypt', 'POST', {\n text,\n ...config,\n })\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Base error class for Blindfold SDK\n */\nexport class BlindfoldError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'BlindfoldError'\n Object.setPrototypeOf(this, BlindfoldError.prototype)\n }\n}\n\n/**\n * Error thrown when authentication fails\n */\nexport class AuthenticationError extends BlindfoldError {\n constructor(message: string = 'Authentication failed. Please check your API key.') {\n super(message)\n this.name = 'AuthenticationError'\n Object.setPrototypeOf(this, AuthenticationError.prototype)\n }\n}\n\n/**\n * Error thrown when API request fails\n */\nexport class APIError extends BlindfoldError {\n statusCode: number\n responseBody?: unknown\n\n constructor(message: string, statusCode: number, responseBody?: unknown) {\n super(message)\n this.name = 'APIError'\n this.statusCode = statusCode\n this.responseBody = responseBody\n Object.setPrototypeOf(this, APIError.prototype)\n }\n}\n\n/**\n * Error thrown when network request fails\n */\nexport class NetworkError extends BlindfoldError {\n constructor(message: string = 'Network request failed. Please check your connection.') {\n super(message)\n this.name = 'NetworkError'\n Object.setPrototypeOf(this, NetworkError.prototype)\n }\n}\n","import type {\n BlindfoldConfig,\n DetectConfig,\n DetectResponse,\n TokenizeConfig,\n TokenizeResponse,\n DetokenizeResponse,\n RedactConfig,\n RedactResponse,\n MaskConfig,\n MaskResponse,\n SynthesizeConfig,\n SynthesizeResponse,\n HashConfig,\n HashResponse,\n EncryptConfig,\n EncryptResponse,\n APIErrorResponse,\n} from './types'\nimport { AuthenticationError, APIError, NetworkError } from './errors'\n\nconst DEFAULT_BASE_URL = 'https://api.blindfold.dev/api/public/v1'\n\n/**\n * Blindfold client for tokenization and detokenization\n */\nexport class Blindfold {\n private apiKey: string\n private baseUrl: string\n private userId?: string\n\n /**\n * Create a new Blindfold client\n * @param config - Configuration options\n */\n constructor(config: BlindfoldConfig) {\n this.apiKey = config.apiKey\n this.baseUrl = config.baseUrl || DEFAULT_BASE_URL\n this.userId = config.userId\n }\n\n /**\n * Make an authenticated request to the API\n */\n private async request<T>(\n endpoint: string,\n method: string,\n body?: Record<string, unknown>\n ): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-API-Key': this.apiKey,\n }\n\n if (this.userId) {\n headers['X-Blindfold-User-Id'] = this.userId\n }\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n })\n\n // Handle authentication errors\n if (response.status === 401 || response.status === 403) {\n throw new AuthenticationError('Authentication failed. Please check your API key.')\n }\n\n // Handle other error responses\n if (!response.ok) {\n let errorMessage = `API request failed with status ${response.status}`\n let responseBody: unknown\n\n try {\n responseBody = await response.json()\n const errorData = responseBody as APIErrorResponse\n errorMessage = errorData.detail || errorData.message || errorMessage\n } catch {\n // If we can't parse the error response, use the status text\n errorMessage = `${errorMessage}: ${response.statusText}`\n }\n\n throw new APIError(errorMessage, response.status, responseBody)\n }\n\n return (await response.json()) as T\n } catch (error) {\n // Re-throw our custom errors\n if (error instanceof AuthenticationError || error instanceof APIError) {\n throw error\n }\n\n // Handle network errors\n if (error instanceof TypeError && error.message.includes('fetch')) {\n throw new NetworkError(\n 'Network request failed. Please check your connection and the API URL.'\n )\n }\n\n // Handle other errors\n throw new NetworkError(error instanceof Error ? error.message : 'Unknown error occurred')\n }\n }\n\n /**\n * Tokenize text by replacing sensitive information with tokens\n * @param text - Text to tokenize\n * @param config - Optional configuration\n * @returns Promise with tokenized text and mapping\n */\n async tokenize(text: string, config?: TokenizeConfig): Promise<TokenizeResponse> {\n return this.request<TokenizeResponse>('/tokenize', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Detect PII in text without modifying it\n *\n * Returns only the detected entities with their types, positions,\n * and confidence scores. The original text is not transformed.\n *\n * @param text - Text to analyze for PII\n * @param config - Optional configuration (entities, score_threshold, policy)\n * @returns Promise with detected entities\n */\n async detect(text: string, config?: DetectConfig): Promise<DetectResponse> {\n return this.request<DetectResponse>('/detect', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Detokenize text by replacing tokens with original values\n *\n * This method performs detokenization CLIENT-SIDE for better performance,\n * security, and to work offline. No API call is made.\n *\n * @param text - Tokenized text\n * @param mapping - Token mapping from tokenize response\n * @returns DetokenizeResponse with original text\n */\n detokenize(text: string, mapping: Record<string, string>): DetokenizeResponse {\n let result = text\n let replacements = 0\n\n // Sort tokens by length (longest first) to avoid partial replacements\n const sortedTokens = Object.keys(mapping).sort((a, b) => b.length - a.length)\n\n for (const token of sortedTokens) {\n const originalValue = mapping[token]\n const regex = new RegExp(token.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g')\n const matches = result.match(regex)\n\n if (matches) {\n result = result.replace(regex, originalValue)\n replacements += matches.length\n }\n }\n\n return {\n text: result,\n replacements_made: replacements,\n }\n }\n\n /**\n * Redact (permanently remove) sensitive information from text\n *\n * WARNING: Redaction is irreversible - original data cannot be restored!\n *\n * @param text - Text to redact\n * @param config - Optional configuration (masking_char, entities)\n * @returns Promise with redacted text and detected entities\n */\n async redact(text: string, config?: RedactConfig): Promise<RedactResponse> {\n return this.request<RedactResponse>('/redact', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Mask (partially hide) sensitive information from text\n *\n * @param text - Text to mask\n * @param config - Optional configuration (chars_to_show, from_end, masking_char, entities)\n * @returns Promise with masked text and detected entities\n */\n async mask(text: string, config?: MaskConfig): Promise<MaskResponse> {\n return this.request<MaskResponse>('/mask', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Synthesize (replace real data with synthetic fake data)\n *\n * @param text - Text to synthesize\n * @param config - Optional configuration (language, entities)\n * @returns Promise with synthetic text and detected entities\n */\n async synthesize(text: string, config?: SynthesizeConfig): Promise<SynthesizeResponse> {\n return this.request<SynthesizeResponse>('/synthesize', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Hash (replace with deterministic hash values)\n *\n * @param text - Text to hash\n * @param config - Optional configuration (hash_type, hash_prefix, hash_length, entities)\n * @returns Promise with hashed text and detected entities\n */\n async hash(text: string, config?: HashConfig): Promise<HashResponse> {\n return this.request<HashResponse>('/hash', 'POST', {\n text,\n ...config,\n })\n }\n\n /**\n * Encrypt (reversibly protect) sensitive data in text using AES encryption\n *\n * @param text - Text to encrypt\n * @param config - Optional configuration (encryption_key, entities)\n * @returns Promise with encrypted text and detected entities\n */\n async encrypt(text: string, config?: EncryptConfig): Promise<EncryptResponse> {\n return this.request<EncryptResponse>('/encrypt', 'POST', {\n text,\n ...config,\n })\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blindfold/sdk",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "JavaScript/TypeScript SDK for Blindfold Gateway",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -13,24 +13,61 @@
13
13
  }
14
14
  },
15
15
  "files": [
16
- "dist"
16
+ "dist",
17
+ "README.md"
17
18
  ],
18
19
  "scripts": {
19
20
  "build": "tsup",
20
21
  "dev": "tsup --watch",
21
- "type-check": "tsc --noEmit"
22
+ "type-check": "tsc --noEmit",
23
+ "test": "jest",
24
+ "test:watch": "jest --watch",
25
+ "test:coverage": "jest --coverage",
26
+ "lint": "eslint src tests --ext .ts",
27
+ "lint:fix": "eslint src tests --ext .ts --fix",
28
+ "format": "prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"",
29
+ "format:check": "prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"",
30
+ "clean": "rm -rf dist",
31
+ "prepublishOnly": "npm run clean && npm run build && npm run test",
32
+ "validate": "npm run type-check && npm run lint && npm run test"
22
33
  },
23
34
  "keywords": [
24
35
  "blindfold",
25
36
  "tokenization",
26
37
  "pii",
27
- "security"
38
+ "security",
39
+ "privacy",
40
+ "gdpr",
41
+ "hipaa",
42
+ "llm",
43
+ "ai"
28
44
  ],
29
- "author": "",
45
+ "author": "Blindfold Team",
30
46
  "license": "MIT",
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/blindfold-dev/blindfold-github.git",
50
+ "directory": "packages/js-sdk"
51
+ },
52
+ "bugs": {
53
+ "url": "https://github.com/blindfold-dev/blindfold-github/issues"
54
+ },
55
+ "homepage": "https://blindfold.dev",
31
56
  "devDependencies": {
57
+ "@types/jest": "^29.5.11",
32
58
  "@types/node": "^20.10.0",
59
+ "@typescript-eslint/eslint-plugin": "^6.18.0",
60
+ "@typescript-eslint/parser": "^6.18.0",
61
+ "eslint": "^8.56.0",
62
+ "eslint-config-prettier": "^9.1.0",
63
+ "eslint-plugin-prettier": "^5.1.2",
64
+ "jest": "^29.7.0",
65
+ "prettier": "^3.1.1",
66
+ "ts-jest": "^29.1.1",
33
67
  "tsup": "^8.0.1",
34
68
  "typescript": "^5.3.3"
69
+ },
70
+ "engines": {
71
+ "node": ">=16.0.0"
35
72
  }
36
73
  }