@easy-data/sdk 0.1.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.
@@ -0,0 +1,2 @@
1
+ "use strict";var a=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var h=Object.prototype.hasOwnProperty;var m=(o,e)=>{for(var t in e)a(o,t,{get:e[t],enumerable:!0})},l=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of T(e))!h.call(o,r)&&r!==t&&a(o,r,{get:()=>e[r],enumerable:!(n=E(e,r))||n.enumerable});return o};var _=o=>l(a({},"__esModule",{value:!0}),o);var u={};m(u,{fetchEphemeralToken:()=>i});module.exports=_(u);var p=class extends Error{constructor(t,n){super(t);this.code=n;this.name="EasydataError"}};var s=class extends p{statusCode;constructor(e,t){super(e,"NETWORK_ERROR"),this.name="EasydataNetworkError",this.statusCode=t}};var c="https://api.easydata.dev";async function i(o){let e=o.baseUrl??c,t=await fetch(`${e}/v1/tokens/ephemeral`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o.apiKey}`}});if(!t.ok)throw new s(`Failed to fetch ephemeral token: HTTP ${t.status}`,t.status);return await t.json()}0&&(module.exports={fetchEphemeralToken});
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/browser/index.ts","../../src/errors.ts","../../src/constants.ts","../../src/browser/token.ts"],"sourcesContent":["export { fetchEphemeralToken } from \"./token\";\nexport type { FetchTokenOptions } from \"./token\";\n","export class EasydataError extends Error {\n constructor(message: string, public readonly code?: string) {\n super(message);\n this.name = \"EasydataError\";\n }\n}\n\nexport class EasydataValidationError extends EasydataError {\n constructor(message: string) {\n super(message, \"VALIDATION_ERROR\");\n this.name = \"EasydataValidationError\";\n }\n}\n\nexport class EasydataNetworkError extends EasydataError {\n public readonly statusCode?: number;\n\n constructor(message: string, statusCode?: number) {\n super(message, \"NETWORK_ERROR\");\n this.name = \"EasydataNetworkError\";\n this.statusCode = statusCode;\n }\n}\n","export const DEFAULT_BASE_URL = \"https://api.easydata.dev\";\nexport const DEFAULT_BATCH_SIZE = 10;\nexport const DEFAULT_BATCH_INTERVAL_MS = 5000;\nexport const DEFAULT_TIMEOUT_MS = 30000;\nexport const DEFAULT_MAX_RETRIES = 3;\nexport const RETRY_BASE_DELAY_MS = 500;\nexport const SDK_VERSION = \"0.1.0\";\n","import type { EphemeralToken } from \"../types\";\nimport { EasydataNetworkError } from \"../errors\";\nimport { DEFAULT_BASE_URL } from \"../constants\";\n\nexport interface FetchTokenOptions {\n baseUrl?: string;\n apiKey: string;\n}\n\nexport async function fetchEphemeralToken(\n options: FetchTokenOptions\n): Promise<EphemeralToken> {\n const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n const response = await fetch(`${baseUrl}/v1/tokens/ephemeral`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${options.apiKey}`,\n },\n });\n\n if (!response.ok) {\n throw new EasydataNetworkError(\n `Failed to fetch ephemeral token: HTTP ${response.status}`,\n response.status\n );\n }\n\n return (await response.json()) as EphemeralToken;\n}\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,yBAAAE,IAAA,eAAAC,EAAAH,GCAO,IAAMI,EAAN,cAA4B,KAAM,CACvC,YAAYC,EAAiCC,EAAe,CAC1D,MAAMD,CAAO,EAD8B,UAAAC,EAE3C,KAAK,KAAO,eACd,CACF,EASO,IAAMC,EAAN,cAAmCC,CAAc,CACtC,WAEhB,YAAYC,EAAiBC,EAAqB,CAChD,MAAMD,EAAS,eAAe,EAC9B,KAAK,KAAO,uBACZ,KAAK,WAAaC,CACpB,CACF,ECtBO,IAAMC,EAAmB,2BCShC,eAAsBC,EACpBC,EACyB,CACzB,IAAMC,EAAUD,EAAQ,SAAWE,EAC7BC,EAAW,MAAM,MAAM,GAAGF,CAAO,uBAAwB,CAC7D,OAAQ,OACR,QAAS,CACP,eAAgB,mBAChB,cAAe,UAAUD,EAAQ,MAAM,EACzC,CACF,CAAC,EAED,GAAI,CAACG,EAAS,GACZ,MAAM,IAAIC,EACR,yCAAyCD,EAAS,MAAM,GACxDA,EAAS,MACX,EAGF,OAAQ,MAAMA,EAAS,KAAK,CAC9B","names":["browser_exports","__export","fetchEphemeralToken","__toCommonJS","EasydataError","message","code","EasydataNetworkError","EasydataError","message","statusCode","DEFAULT_BASE_URL","fetchEphemeralToken","options","baseUrl","DEFAULT_BASE_URL","response","EasydataNetworkError"]}
@@ -0,0 +1,9 @@
1
+ import { c as EphemeralToken } from '../types-BCRHQ6gc.cjs';
2
+
3
+ interface FetchTokenOptions {
4
+ baseUrl?: string;
5
+ apiKey: string;
6
+ }
7
+ declare function fetchEphemeralToken(options: FetchTokenOptions): Promise<EphemeralToken>;
8
+
9
+ export { type FetchTokenOptions, fetchEphemeralToken };
@@ -0,0 +1,9 @@
1
+ import { c as EphemeralToken } from '../types-BCRHQ6gc.js';
2
+
3
+ interface FetchTokenOptions {
4
+ baseUrl?: string;
5
+ apiKey: string;
6
+ }
7
+ declare function fetchEphemeralToken(options: FetchTokenOptions): Promise<EphemeralToken>;
8
+
9
+ export { type FetchTokenOptions, fetchEphemeralToken };
@@ -0,0 +1,2 @@
1
+ var s=class extends Error{constructor(e,p){super(e);this.code=p;this.name="EasydataError"}};var r=class extends s{statusCode;constructor(o,e){super(o,"NETWORK_ERROR"),this.name="EasydataNetworkError",this.statusCode=e}};var n="https://api.easydata.dev";async function a(t){let o=t.baseUrl??n,e=await fetch(`${o}/v1/tokens/ephemeral`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.apiKey}`}});if(!e.ok)throw new r(`Failed to fetch ephemeral token: HTTP ${e.status}`,e.status);return await e.json()}export{a as fetchEphemeralToken};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/errors.ts","../../src/constants.ts","../../src/browser/token.ts"],"sourcesContent":["export class EasydataError extends Error {\n constructor(message: string, public readonly code?: string) {\n super(message);\n this.name = \"EasydataError\";\n }\n}\n\nexport class EasydataValidationError extends EasydataError {\n constructor(message: string) {\n super(message, \"VALIDATION_ERROR\");\n this.name = \"EasydataValidationError\";\n }\n}\n\nexport class EasydataNetworkError extends EasydataError {\n public readonly statusCode?: number;\n\n constructor(message: string, statusCode?: number) {\n super(message, \"NETWORK_ERROR\");\n this.name = \"EasydataNetworkError\";\n this.statusCode = statusCode;\n }\n}\n","export const DEFAULT_BASE_URL = \"https://api.easydata.dev\";\nexport const DEFAULT_BATCH_SIZE = 10;\nexport const DEFAULT_BATCH_INTERVAL_MS = 5000;\nexport const DEFAULT_TIMEOUT_MS = 30000;\nexport const DEFAULT_MAX_RETRIES = 3;\nexport const RETRY_BASE_DELAY_MS = 500;\nexport const SDK_VERSION = \"0.1.0\";\n","import type { EphemeralToken } from \"../types\";\nimport { EasydataNetworkError } from \"../errors\";\nimport { DEFAULT_BASE_URL } from \"../constants\";\n\nexport interface FetchTokenOptions {\n baseUrl?: string;\n apiKey: string;\n}\n\nexport async function fetchEphemeralToken(\n options: FetchTokenOptions\n): Promise<EphemeralToken> {\n const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n const response = await fetch(`${baseUrl}/v1/tokens/ephemeral`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${options.apiKey}`,\n },\n });\n\n if (!response.ok) {\n throw new EasydataNetworkError(\n `Failed to fetch ephemeral token: HTTP ${response.status}`,\n response.status\n );\n }\n\n return (await response.json()) as EphemeralToken;\n}\n"],"mappings":"AAAO,IAAMA,EAAN,cAA4B,KAAM,CACvC,YAAYC,EAAiCC,EAAe,CAC1D,MAAMD,CAAO,EAD8B,UAAAC,EAE3C,KAAK,KAAO,eACd,CACF,EASO,IAAMC,EAAN,cAAmCC,CAAc,CACtC,WAEhB,YAAYC,EAAiBC,EAAqB,CAChD,MAAMD,EAAS,eAAe,EAC9B,KAAK,KAAO,uBACZ,KAAK,WAAaC,CACpB,CACF,ECtBO,IAAMC,EAAmB,2BCShC,eAAsBC,EACpBC,EACyB,CACzB,IAAMC,EAAUD,EAAQ,SAAWE,EAC7BC,EAAW,MAAM,MAAM,GAAGF,CAAO,uBAAwB,CAC7D,OAAQ,OACR,QAAS,CACP,eAAgB,mBAChB,cAAe,UAAUD,EAAQ,MAAM,EACzC,CACF,CAAC,EAED,GAAI,CAACG,EAAS,GACZ,MAAM,IAAIC,EACR,yCAAyCD,EAAS,MAAM,GACxDA,EAAS,MACX,EAGF,OAAQ,MAAMA,EAAS,KAAK,CAC9B","names":["EasydataError","message","code","EasydataNetworkError","EasydataError","message","statusCode","DEFAULT_BASE_URL","fetchEphemeralToken","options","baseUrl","DEFAULT_BASE_URL","response","EasydataNetworkError"]}
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var y=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var S=Object.prototype.hasOwnProperty;var B=(r,e)=>{for(var t in e)y(r,t,{get:e[t],enumerable:!0})},D=(r,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of P(e))!S.call(r,o)&&o!==t&&y(r,o,{get:()=>e[o],enumerable:!(s=x(e,o))||s.enumerable});return r};var M=r=>D(y({},"__esModule",{value:!0}),r);var F={};B(F,{DEFAULT_BASE_URL:()=>l,DEFAULT_BATCH_INTERVAL_MS:()=>h,DEFAULT_BATCH_SIZE:()=>d,DEFAULT_MAX_RETRIES:()=>E,DEFAULT_TIMEOUT_MS:()=>m,Easydata:()=>T,EasydataError:()=>p,EasydataNetworkError:()=>n,EasydataValidationError:()=>u,SDK_VERSION:()=>_,scrubEntry:()=>R,scrubText:()=>c});module.exports=M(F);var p=class extends Error{constructor(t,s){super(t);this.code=s;this.name="EasydataError"}},u=class extends p{constructor(e){super(e,"VALIDATION_ERROR"),this.name="EasydataValidationError"}},n=class extends p{statusCode;constructor(e,t){super(e,"NETWORK_ERROR"),this.name="EasydataNetworkError",this.statusCode=t}};var l="https://api.easydata.dev",d=10,h=5e3,m=3e4,E=3;var _="0.1.0";function w(r){return r>=500||r===429}function I(r){return new Promise(e=>setTimeout(e,r))}async function A(r,e,t){let s=`${t.baseUrl}${r}`,o;for(let a=0;a<t.maxRetries;a++){let C=new AbortController,b=setTimeout(()=>C.abort(),t.timeoutMs);try{let i=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.apiKey}`,"X-Easydata-SDK":"js/0.1.0"},body:JSON.stringify(e),signal:C.signal});if(clearTimeout(b),i.ok)return await i.json();if(!w(i.status)){let v=await i.text().catch(()=>"Unknown error");throw new n(`HTTP ${i.status}: ${v}`,i.status)}o=new n(`HTTP ${i.status}`,i.status)}catch(i){if(clearTimeout(b),i instanceof n&&!w(i.statusCode??0))throw i;i instanceof DOMException&&i.name==="AbortError"?o=new n("Request timed out"):i instanceof n?o=i:o=i instanceof Error?i:new Error(String(i))}a<t.maxRetries-1&&await I(500*Math.pow(2,a))}throw o??new n("Request failed after retries")}var f=class{queue=[];timer=null;options;_isShutdown=!1;constructor(e){this.options=e,this.startTimer()}get pending(){return this.queue.length}get isShutdown(){return this._isShutdown}enqueue(e){return this._isShutdown?Promise.reject(new Error("BatchQueue has been shut down")):new Promise((t,s)=>{this.queue.push({entry:e,resolve:t,reject:s}),this.queue.length>=this.options.size&&this.flush()})}async flush(){if(this.queue.length===0)return{results:[],accepted:0,rejected:0,failed:0};let e=this.queue.splice(0),t=e.map(s=>s.entry);try{let s=await this.options.onFlush(t);for(let o=0;o<e.length;o++){let a=s.results[o];a?e[o].resolve(a):e[o].resolve({id:"unknown",status:"failed",reason:"No result returned"})}return s}catch(s){let o=s instanceof Error?s:new Error(String(s));for(let a of e)a.reject(o);return{results:[],accepted:0,rejected:0,failed:e.length}}}async shutdown(){this._isShutdown=!0,this.stopTimer(),this.queue.length>0&&await this.flush()}startTimer(){this.options.intervalMs>0&&(this.timer=setInterval(()=>{this.queue.length>0&&this.flush()},this.options.intervalMs))}stopTimer(){this.timer!==null&&(clearInterval(this.timer),this.timer=null)}};var L=[{pattern:/\b\d{3}-\d{2}-\d{4}\b/g,replacement:"[REDACTED_SSN]"},{pattern:/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,replacement:"[REDACTED_EMAIL]"},{pattern:/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g,replacement:"[REDACTED_PHONE]"},{pattern:/\b(?:4\d{3}|5[1-5]\d{2}|3[47]\d{2}|6(?:011|5\d{2}))\d{8,12}\b/g,replacement:"[REDACTED_CC]"}];function c(r){let e=r;for(let{pattern:t,replacement:s}of L)t.lastIndex=0,e=e.replace(t,s);return e}function R(r){return{...r,userPrompt:c(r.userPrompt),aiResponse:c(r.aiResponse),userCorrection:c(r.userCorrection),...r.aiCorrectedResponse?{aiCorrectedResponse:c(r.aiCorrectedResponse)}:{},...r.aiInitialPrompt?{aiInitialPrompt:c(r.aiInitialPrompt)}:{}}}var g=class{constructor(e=!1){this.debug=e}info(e,...t){this.debug&&console.log(`[easydata] ${e}`,...t)}warn(e,...t){console.warn(`[easydata] ${e}`,...t)}error(e,...t){console.error(`[easydata] ${e}`,...t)}logBatchResult(e){let t=`${e.accepted} entries accepted ${e.rejected} entries rejected ${e.failed} entries failed`;e.failed>0?this.warn(t):this.info(t)}};var T=class r{config;batchQueue;logger;constructor(e){if(!e.apiKey)throw new u("apiKey is required");this.config={apiKey:e.apiKey,baseUrl:e.baseUrl??l,scrubPii:e.scrubPii??!0,timeoutMs:e.timeoutMs??3e4,maxRetries:e.maxRetries??3,debug:e.debug??!1},this.logger=new g(this.config.debug),this.batchQueue=new f({size:e.batch?.size??10,intervalMs:e.batch?.intervalMs??5e3,onFlush:t=>this.sendBatch(t)}),this.logger.info("Client initialized")}async captureCorrection(e){this.validateEntry(e);let t=this.config.scrubPii?R(e):e;return this.batchQueue.enqueue(t)}async captureCorrections(e){return Promise.all(e.map(t=>this.captureCorrection(t)))}async flush(){return this.batchQueue.flush()}async shutdown(){this.logger.info("Shutting down client"),await this.batchQueue.shutdown()}static createBrowserClient(e){return new r(e)}validateEntry(e){if(!e.userPrompt)throw new u("userPrompt is required");if(!e.aiResponse)throw new u("aiResponse is required");if(!e.userCorrection)throw new u("userCorrection is required")}toApiEntry(e){return{user_prompt:e.userPrompt,ai_response:e.aiResponse,user_correction:e.userCorrection,...e.aiCorrectedResponse&&{ai_corrected_response:e.aiCorrectedResponse},...e.aiInitialPrompt&&{system_prompt:e.aiInitialPrompt},...e.provider&&{provider:e.provider},...e.model&&{model:e.model},...e.domain&&{domain:e.domain},...e.metadata&&{metadata:e.metadata}}}async sendBatch(e){this.logger.info(`Sending batch of ${e.length} entries`);let t=e.map(o=>this.toApiEntry(o)),s=await A("/v1/corrections",{entries:t},{baseUrl:this.config.baseUrl,apiKey:this.config.apiKey,timeoutMs:this.config.timeoutMs,maxRetries:this.config.maxRetries});return this.logger.logBatchResult(s),s}};0&&(module.exports={DEFAULT_BASE_URL,DEFAULT_BATCH_INTERVAL_MS,DEFAULT_BATCH_SIZE,DEFAULT_MAX_RETRIES,DEFAULT_TIMEOUT_MS,Easydata,EasydataError,EasydataNetworkError,EasydataValidationError,SDK_VERSION,scrubEntry,scrubText});
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/constants.ts","../src/transport/http.ts","../src/transport/batch.ts","../src/pii/scrubber.ts","../src/logger.ts","../src/client.ts"],"sourcesContent":["export { Easydata } from \"./client\";\nexport {\n EasydataError,\n EasydataValidationError,\n EasydataNetworkError,\n} from \"./errors\";\nexport { scrubText, scrubEntry } from \"./pii/scrubber\";\nexport type {\n EasydataConfig,\n CorrectionEntry,\n CaptureResult,\n BatchResult,\n BatchConfig,\n Domain,\n EphemeralToken,\n} from \"./types\";\nexport {\n DEFAULT_BASE_URL,\n DEFAULT_BATCH_SIZE,\n DEFAULT_BATCH_INTERVAL_MS,\n DEFAULT_TIMEOUT_MS,\n DEFAULT_MAX_RETRIES,\n SDK_VERSION,\n} from \"./constants\";\n","export class EasydataError extends Error {\n constructor(message: string, public readonly code?: string) {\n super(message);\n this.name = \"EasydataError\";\n }\n}\n\nexport class EasydataValidationError extends EasydataError {\n constructor(message: string) {\n super(message, \"VALIDATION_ERROR\");\n this.name = \"EasydataValidationError\";\n }\n}\n\nexport class EasydataNetworkError extends EasydataError {\n public readonly statusCode?: number;\n\n constructor(message: string, statusCode?: number) {\n super(message, \"NETWORK_ERROR\");\n this.name = \"EasydataNetworkError\";\n this.statusCode = statusCode;\n }\n}\n","export const DEFAULT_BASE_URL = \"https://api.easydata.dev\";\nexport const DEFAULT_BATCH_SIZE = 10;\nexport const DEFAULT_BATCH_INTERVAL_MS = 5000;\nexport const DEFAULT_TIMEOUT_MS = 30000;\nexport const DEFAULT_MAX_RETRIES = 3;\nexport const RETRY_BASE_DELAY_MS = 500;\nexport const SDK_VERSION = \"0.1.0\";\n","import { EasydataNetworkError } from \"../errors\";\nimport { RETRY_BASE_DELAY_MS } from \"../constants\";\n\nexport interface HttpOptions {\n baseUrl: string;\n apiKey: string;\n timeoutMs: number;\n maxRetries: number;\n}\n\nfunction isRetryable(status: number): boolean {\n return status >= 500 || status === 429;\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function httpPost<T>(\n path: string,\n body: unknown,\n options: HttpOptions\n): Promise<T> {\n const url = `${options.baseUrl}${path}`;\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt < options.maxRetries; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), options.timeoutMs);\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${options.apiKey}`,\n \"X-Easydata-SDK\": \"js/0.1.0\",\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n clearTimeout(timer);\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n if (!isRetryable(response.status)) {\n const text = await response.text().catch(() => \"Unknown error\");\n throw new EasydataNetworkError(\n `HTTP ${response.status}: ${text}`,\n response.status\n );\n }\n\n lastError = new EasydataNetworkError(\n `HTTP ${response.status}`,\n response.status\n );\n } catch (err) {\n clearTimeout(timer);\n\n if (err instanceof EasydataNetworkError && !isRetryable(err.statusCode ?? 0)) {\n throw err;\n }\n\n if (err instanceof DOMException && err.name === \"AbortError\") {\n lastError = new EasydataNetworkError(\"Request timed out\");\n } else if (!(err instanceof EasydataNetworkError)) {\n lastError = err instanceof Error ? err : new Error(String(err));\n } else {\n lastError = err;\n }\n }\n\n if (attempt < options.maxRetries - 1) {\n await delay(RETRY_BASE_DELAY_MS * Math.pow(2, attempt));\n }\n }\n\n throw lastError ?? new EasydataNetworkError(\"Request failed after retries\");\n}\n","import type { CorrectionEntry, BatchResult, CaptureResult } from \"../types\";\n\nexport interface QueuedEntry {\n entry: CorrectionEntry;\n resolve: (result: CaptureResult) => void;\n reject: (error: Error) => void;\n}\n\nexport interface BatchQueueOptions {\n size: number;\n intervalMs: number;\n onFlush: (entries: CorrectionEntry[]) => Promise<BatchResult>;\n}\n\nexport class BatchQueue {\n private queue: QueuedEntry[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private readonly options: BatchQueueOptions;\n private _isShutdown = false;\n\n constructor(options: BatchQueueOptions) {\n this.options = options;\n this.startTimer();\n }\n\n get pending(): number {\n return this.queue.length;\n }\n\n get isShutdown(): boolean {\n return this._isShutdown;\n }\n\n enqueue(entry: CorrectionEntry): Promise<CaptureResult> {\n if (this._isShutdown) {\n return Promise.reject(new Error(\"BatchQueue has been shut down\"));\n }\n\n return new Promise<CaptureResult>((resolve, reject) => {\n this.queue.push({ entry, resolve, reject });\n\n if (this.queue.length >= this.options.size) {\n void this.flush();\n }\n });\n }\n\n async flush(): Promise<BatchResult> {\n if (this.queue.length === 0) {\n return { results: [], accepted: 0, rejected: 0, failed: 0 };\n }\n\n const batch = this.queue.splice(0);\n const entries = batch.map((q) => q.entry);\n\n try {\n const result = await this.options.onFlush(entries);\n\n for (let i = 0; i < batch.length; i++) {\n const captureResult = result.results[i];\n if (captureResult) {\n batch[i].resolve(captureResult);\n } else {\n batch[i].resolve({\n id: \"unknown\",\n status: \"failed\",\n reason: \"No result returned\",\n });\n }\n }\n\n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n for (const item of batch) {\n item.reject(error);\n }\n return {\n results: [],\n accepted: 0,\n rejected: 0,\n failed: batch.length,\n };\n }\n }\n\n async shutdown(): Promise<void> {\n this._isShutdown = true;\n this.stopTimer();\n if (this.queue.length > 0) {\n await this.flush();\n }\n }\n\n private startTimer(): void {\n if (this.options.intervalMs > 0) {\n this.timer = setInterval(() => {\n if (this.queue.length > 0) {\n void this.flush();\n }\n }, this.options.intervalMs);\n }\n }\n\n private stopTimer(): void {\n if (this.timer !== null) {\n clearInterval(this.timer);\n this.timer = null;\n }\n }\n}\n","import type { CorrectionEntry } from \"../types\";\n\nconst PII_PATTERNS: Array<{ pattern: RegExp; replacement: string }> = [\n // SSN must come before phone to avoid false positives\n {\n pattern: /\\b\\d{3}-\\d{2}-\\d{4}\\b/g,\n replacement: \"[REDACTED_SSN]\",\n },\n {\n pattern: /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b/g,\n replacement: \"[REDACTED_EMAIL]\",\n },\n {\n pattern: /\\b\\d{3}[-.]?\\d{3}[-.]?\\d{4}\\b/g,\n replacement: \"[REDACTED_PHONE]\",\n },\n {\n pattern: /\\b(?:4\\d{3}|5[1-5]\\d{2}|3[47]\\d{2}|6(?:011|5\\d{2}))\\d{8,12}\\b/g,\n replacement: \"[REDACTED_CC]\",\n },\n];\n\nexport function scrubText(text: string): string {\n let result = text;\n for (const { pattern, replacement } of PII_PATTERNS) {\n // Reset lastIndex for global regexes\n pattern.lastIndex = 0;\n result = result.replace(pattern, replacement);\n }\n return result;\n}\n\nexport function scrubEntry(entry: CorrectionEntry): CorrectionEntry {\n return {\n ...entry,\n userPrompt: scrubText(entry.userPrompt),\n aiResponse: scrubText(entry.aiResponse),\n userCorrection: scrubText(entry.userCorrection),\n ...(entry.aiCorrectedResponse\n ? { aiCorrectedResponse: scrubText(entry.aiCorrectedResponse) }\n : {}),\n ...(entry.aiInitialPrompt\n ? { aiInitialPrompt: scrubText(entry.aiInitialPrompt) }\n : {}),\n };\n}\n","import type { BatchResult } from \"./types\";\n\nexport class Logger {\n constructor(private readonly debug: boolean = false) {}\n\n info(message: string, ...args: unknown[]): void {\n if (this.debug) {\n console.log(`[easydata] ${message}`, ...args);\n }\n }\n\n warn(message: string, ...args: unknown[]): void {\n console.warn(`[easydata] ${message}`, ...args);\n }\n\n error(message: string, ...args: unknown[]): void {\n console.error(`[easydata] ${message}`, ...args);\n }\n\n logBatchResult(result: BatchResult): void {\n const msg = `${result.accepted} entries accepted ${result.rejected} entries rejected ${result.failed} entries failed`;\n if (result.failed > 0) {\n this.warn(msg);\n } else {\n this.info(msg);\n }\n }\n}\n","import type {\n EasydataConfig,\n CorrectionEntry,\n CaptureResult,\n BatchResult,\n} from \"./types\";\nimport { EasydataValidationError } from \"./errors\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_BATCH_SIZE,\n DEFAULT_BATCH_INTERVAL_MS,\n DEFAULT_TIMEOUT_MS,\n DEFAULT_MAX_RETRIES,\n} from \"./constants\";\nimport { httpPost } from \"./transport/http\";\nimport { BatchQueue } from \"./transport/batch\";\nimport { scrubEntry } from \"./pii/scrubber\";\nimport { Logger } from \"./logger\";\n\nexport class Easydata {\n private readonly config: Required<\n Pick<EasydataConfig, \"apiKey\" | \"baseUrl\" | \"scrubPii\" | \"timeoutMs\" | \"maxRetries\" | \"debug\">\n >;\n private readonly batchQueue: BatchQueue;\n private readonly logger: Logger;\n\n constructor(config: EasydataConfig) {\n if (!config.apiKey) {\n throw new EasydataValidationError(\"apiKey is required\");\n }\n\n this.config = {\n apiKey: config.apiKey,\n baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,\n scrubPii: config.scrubPii ?? true,\n timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n debug: config.debug ?? false,\n };\n\n this.logger = new Logger(this.config.debug);\n\n this.batchQueue = new BatchQueue({\n size: config.batch?.size ?? DEFAULT_BATCH_SIZE,\n intervalMs: config.batch?.intervalMs ?? DEFAULT_BATCH_INTERVAL_MS,\n onFlush: (entries) => this.sendBatch(entries),\n });\n\n this.logger.info(\"Client initialized\");\n }\n\n async captureCorrection(entry: CorrectionEntry): Promise<CaptureResult> {\n this.validateEntry(entry);\n\n const processed = this.config.scrubPii ? scrubEntry(entry) : entry;\n return this.batchQueue.enqueue(processed);\n }\n\n async captureCorrections(entries: CorrectionEntry[]): Promise<CaptureResult[]> {\n return Promise.all(entries.map((e) => this.captureCorrection(e)));\n }\n\n async flush(): Promise<BatchResult> {\n return this.batchQueue.flush();\n }\n\n async shutdown(): Promise<void> {\n this.logger.info(\"Shutting down client\");\n await this.batchQueue.shutdown();\n }\n\n static createBrowserClient(config: EasydataConfig): Easydata {\n return new Easydata(config);\n }\n\n private validateEntry(entry: CorrectionEntry): void {\n if (!entry.userPrompt) {\n throw new EasydataValidationError(\"userPrompt is required\");\n }\n if (!entry.aiResponse) {\n throw new EasydataValidationError(\"aiResponse is required\");\n }\n if (!entry.userCorrection) {\n throw new EasydataValidationError(\"userCorrection is required\");\n }\n }\n\n private toApiEntry(entry: CorrectionEntry) {\n return {\n user_prompt: entry.userPrompt,\n ai_response: entry.aiResponse,\n user_correction: entry.userCorrection,\n ...(entry.aiCorrectedResponse && { ai_corrected_response: entry.aiCorrectedResponse }),\n ...(entry.aiInitialPrompt && { system_prompt: entry.aiInitialPrompt }),\n ...(entry.provider && { provider: entry.provider }),\n ...(entry.model && { model: entry.model }),\n ...(entry.domain && { domain: entry.domain }),\n ...(entry.metadata && { metadata: entry.metadata }),\n };\n }\n\n private async sendBatch(entries: CorrectionEntry[]): Promise<BatchResult> {\n this.logger.info(`Sending batch of ${entries.length} entries`);\n\n const apiEntries = entries.map((e) => this.toApiEntry(e));\n\n const result = await httpPost<BatchResult>(\n \"/v1/corrections\",\n { entries: apiEntries },\n {\n baseUrl: this.config.baseUrl,\n apiKey: this.config.apiKey,\n timeoutMs: this.config.timeoutMs,\n maxRetries: this.config.maxRetries,\n }\n );\n\n this.logger.logBatchResult(result);\n return result;\n }\n}\n"],"mappings":"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","names":["index_exports","__export","DEFAULT_BASE_URL","DEFAULT_BATCH_INTERVAL_MS","DEFAULT_BATCH_SIZE","DEFAULT_MAX_RETRIES","DEFAULT_TIMEOUT_MS","Easydata","EasydataError","EasydataNetworkError","EasydataValidationError","SDK_VERSION","scrubEntry","scrubText","__toCommonJS","EasydataError","message","code","EasydataValidationError","EasydataNetworkError","statusCode","DEFAULT_BASE_URL","DEFAULT_BATCH_SIZE","DEFAULT_BATCH_INTERVAL_MS","DEFAULT_TIMEOUT_MS","DEFAULT_MAX_RETRIES","SDK_VERSION","isRetryable","status","delay","ms","resolve","httpPost","path","body","options","url","lastError","attempt","controller","timer","response","text","EasydataNetworkError","err","BatchQueue","options","entry","resolve","reject","batch","entries","q","result","i","captureResult","err","error","item","PII_PATTERNS","scrubText","text","result","pattern","replacement","scrubEntry","entry","Logger","debug","message","args","result","msg","Easydata","_Easydata","config","EasydataValidationError","DEFAULT_BASE_URL","Logger","BatchQueue","entries","entry","processed","scrubEntry","e","apiEntries","result","httpPost"]}
@@ -0,0 +1,41 @@
1
+ import { E as EasydataConfig, C as CorrectionEntry, a as CaptureResult, B as BatchResult } from './types-BCRHQ6gc.cjs';
2
+ export { b as BatchConfig, D as Domain, c as EphemeralToken } from './types-BCRHQ6gc.cjs';
3
+
4
+ declare class Easydata {
5
+ private readonly config;
6
+ private readonly batchQueue;
7
+ private readonly logger;
8
+ constructor(config: EasydataConfig);
9
+ captureCorrection(entry: CorrectionEntry): Promise<CaptureResult>;
10
+ captureCorrections(entries: CorrectionEntry[]): Promise<CaptureResult[]>;
11
+ flush(): Promise<BatchResult>;
12
+ shutdown(): Promise<void>;
13
+ static createBrowserClient(config: EasydataConfig): Easydata;
14
+ private validateEntry;
15
+ private toApiEntry;
16
+ private sendBatch;
17
+ }
18
+
19
+ declare class EasydataError extends Error {
20
+ readonly code?: string | undefined;
21
+ constructor(message: string, code?: string | undefined);
22
+ }
23
+ declare class EasydataValidationError extends EasydataError {
24
+ constructor(message: string);
25
+ }
26
+ declare class EasydataNetworkError extends EasydataError {
27
+ readonly statusCode?: number;
28
+ constructor(message: string, statusCode?: number);
29
+ }
30
+
31
+ declare function scrubText(text: string): string;
32
+ declare function scrubEntry(entry: CorrectionEntry): CorrectionEntry;
33
+
34
+ declare const DEFAULT_BASE_URL = "https://api.easydata.dev";
35
+ declare const DEFAULT_BATCH_SIZE = 10;
36
+ declare const DEFAULT_BATCH_INTERVAL_MS = 5000;
37
+ declare const DEFAULT_TIMEOUT_MS = 30000;
38
+ declare const DEFAULT_MAX_RETRIES = 3;
39
+ declare const SDK_VERSION = "0.1.0";
40
+
41
+ export { BatchResult, CaptureResult, CorrectionEntry, DEFAULT_BASE_URL, DEFAULT_BATCH_INTERVAL_MS, DEFAULT_BATCH_SIZE, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT_MS, Easydata, EasydataConfig, EasydataError, EasydataNetworkError, EasydataValidationError, SDK_VERSION, scrubEntry, scrubText };
@@ -0,0 +1,41 @@
1
+ import { E as EasydataConfig, C as CorrectionEntry, a as CaptureResult, B as BatchResult } from './types-BCRHQ6gc.js';
2
+ export { b as BatchConfig, D as Domain, c as EphemeralToken } from './types-BCRHQ6gc.js';
3
+
4
+ declare class Easydata {
5
+ private readonly config;
6
+ private readonly batchQueue;
7
+ private readonly logger;
8
+ constructor(config: EasydataConfig);
9
+ captureCorrection(entry: CorrectionEntry): Promise<CaptureResult>;
10
+ captureCorrections(entries: CorrectionEntry[]): Promise<CaptureResult[]>;
11
+ flush(): Promise<BatchResult>;
12
+ shutdown(): Promise<void>;
13
+ static createBrowserClient(config: EasydataConfig): Easydata;
14
+ private validateEntry;
15
+ private toApiEntry;
16
+ private sendBatch;
17
+ }
18
+
19
+ declare class EasydataError extends Error {
20
+ readonly code?: string | undefined;
21
+ constructor(message: string, code?: string | undefined);
22
+ }
23
+ declare class EasydataValidationError extends EasydataError {
24
+ constructor(message: string);
25
+ }
26
+ declare class EasydataNetworkError extends EasydataError {
27
+ readonly statusCode?: number;
28
+ constructor(message: string, statusCode?: number);
29
+ }
30
+
31
+ declare function scrubText(text: string): string;
32
+ declare function scrubEntry(entry: CorrectionEntry): CorrectionEntry;
33
+
34
+ declare const DEFAULT_BASE_URL = "https://api.easydata.dev";
35
+ declare const DEFAULT_BATCH_SIZE = 10;
36
+ declare const DEFAULT_BATCH_INTERVAL_MS = 5000;
37
+ declare const DEFAULT_TIMEOUT_MS = 30000;
38
+ declare const DEFAULT_MAX_RETRIES = 3;
39
+ declare const SDK_VERSION = "0.1.0";
40
+
41
+ export { BatchResult, CaptureResult, CorrectionEntry, DEFAULT_BASE_URL, DEFAULT_BATCH_INTERVAL_MS, DEFAULT_BATCH_SIZE, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT_MS, Easydata, EasydataConfig, EasydataError, EasydataNetworkError, EasydataValidationError, SDK_VERSION, scrubEntry, scrubText };
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ var p=class extends Error{constructor(t,o){super(t);this.code=o;this.name="EasydataError"}},u=class extends p{constructor(e){super(e,"VALIDATION_ERROR"),this.name="EasydataValidationError"}},n=class extends p{statusCode;constructor(e,t){super(e,"NETWORK_ERROR"),this.name="EasydataNetworkError",this.statusCode=t}};var h="https://api.easydata.dev",m=10,E=5e3,f=3e4,R=3;var A="0.1.0";function b(r){return r>=500||r===429}function x(r){return new Promise(e=>setTimeout(e,r))}async function _(r,e,t){let o=`${t.baseUrl}${r}`,i;for(let a=0;a<t.maxRetries;a++){let y=new AbortController,C=setTimeout(()=>y.abort(),t.timeoutMs);try{let s=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.apiKey}`,"X-Easydata-SDK":"js/0.1.0"},body:JSON.stringify(e),signal:y.signal});if(clearTimeout(C),s.ok)return await s.json();if(!b(s.status)){let w=await s.text().catch(()=>"Unknown error");throw new n(`HTTP ${s.status}: ${w}`,s.status)}i=new n(`HTTP ${s.status}`,s.status)}catch(s){if(clearTimeout(C),s instanceof n&&!b(s.statusCode??0))throw s;s instanceof DOMException&&s.name==="AbortError"?i=new n("Request timed out"):s instanceof n?i=s:i=s instanceof Error?s:new Error(String(s))}a<t.maxRetries-1&&await x(500*Math.pow(2,a))}throw i??new n("Request failed after retries")}var l=class{queue=[];timer=null;options;_isShutdown=!1;constructor(e){this.options=e,this.startTimer()}get pending(){return this.queue.length}get isShutdown(){return this._isShutdown}enqueue(e){return this._isShutdown?Promise.reject(new Error("BatchQueue has been shut down")):new Promise((t,o)=>{this.queue.push({entry:e,resolve:t,reject:o}),this.queue.length>=this.options.size&&this.flush()})}async flush(){if(this.queue.length===0)return{results:[],accepted:0,rejected:0,failed:0};let e=this.queue.splice(0),t=e.map(o=>o.entry);try{let o=await this.options.onFlush(t);for(let i=0;i<e.length;i++){let a=o.results[i];a?e[i].resolve(a):e[i].resolve({id:"unknown",status:"failed",reason:"No result returned"})}return o}catch(o){let i=o instanceof Error?o:new Error(String(o));for(let a of e)a.reject(i);return{results:[],accepted:0,rejected:0,failed:e.length}}}async shutdown(){this._isShutdown=!0,this.stopTimer(),this.queue.length>0&&await this.flush()}startTimer(){this.options.intervalMs>0&&(this.timer=setInterval(()=>{this.queue.length>0&&this.flush()},this.options.intervalMs))}stopTimer(){this.timer!==null&&(clearInterval(this.timer),this.timer=null)}};var P=[{pattern:/\b\d{3}-\d{2}-\d{4}\b/g,replacement:"[REDACTED_SSN]"},{pattern:/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,replacement:"[REDACTED_EMAIL]"},{pattern:/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g,replacement:"[REDACTED_PHONE]"},{pattern:/\b(?:4\d{3}|5[1-5]\d{2}|3[47]\d{2}|6(?:011|5\d{2}))\d{8,12}\b/g,replacement:"[REDACTED_CC]"}];function c(r){let e=r;for(let{pattern:t,replacement:o}of P)t.lastIndex=0,e=e.replace(t,o);return e}function g(r){return{...r,userPrompt:c(r.userPrompt),aiResponse:c(r.aiResponse),userCorrection:c(r.userCorrection),...r.aiCorrectedResponse?{aiCorrectedResponse:c(r.aiCorrectedResponse)}:{},...r.aiInitialPrompt?{aiInitialPrompt:c(r.aiInitialPrompt)}:{}}}var d=class{constructor(e=!1){this.debug=e}info(e,...t){this.debug&&console.log(`[easydata] ${e}`,...t)}warn(e,...t){console.warn(`[easydata] ${e}`,...t)}error(e,...t){console.error(`[easydata] ${e}`,...t)}logBatchResult(e){let t=`${e.accepted} entries accepted ${e.rejected} entries rejected ${e.failed} entries failed`;e.failed>0?this.warn(t):this.info(t)}};var T=class r{config;batchQueue;logger;constructor(e){if(!e.apiKey)throw new u("apiKey is required");this.config={apiKey:e.apiKey,baseUrl:e.baseUrl??h,scrubPii:e.scrubPii??!0,timeoutMs:e.timeoutMs??3e4,maxRetries:e.maxRetries??3,debug:e.debug??!1},this.logger=new d(this.config.debug),this.batchQueue=new l({size:e.batch?.size??10,intervalMs:e.batch?.intervalMs??5e3,onFlush:t=>this.sendBatch(t)}),this.logger.info("Client initialized")}async captureCorrection(e){this.validateEntry(e);let t=this.config.scrubPii?g(e):e;return this.batchQueue.enqueue(t)}async captureCorrections(e){return Promise.all(e.map(t=>this.captureCorrection(t)))}async flush(){return this.batchQueue.flush()}async shutdown(){this.logger.info("Shutting down client"),await this.batchQueue.shutdown()}static createBrowserClient(e){return new r(e)}validateEntry(e){if(!e.userPrompt)throw new u("userPrompt is required");if(!e.aiResponse)throw new u("aiResponse is required");if(!e.userCorrection)throw new u("userCorrection is required")}toApiEntry(e){return{user_prompt:e.userPrompt,ai_response:e.aiResponse,user_correction:e.userCorrection,...e.aiCorrectedResponse&&{ai_corrected_response:e.aiCorrectedResponse},...e.aiInitialPrompt&&{system_prompt:e.aiInitialPrompt},...e.provider&&{provider:e.provider},...e.model&&{model:e.model},...e.domain&&{domain:e.domain},...e.metadata&&{metadata:e.metadata}}}async sendBatch(e){this.logger.info(`Sending batch of ${e.length} entries`);let t=e.map(i=>this.toApiEntry(i)),o=await _("/v1/corrections",{entries:t},{baseUrl:this.config.baseUrl,apiKey:this.config.apiKey,timeoutMs:this.config.timeoutMs,maxRetries:this.config.maxRetries});return this.logger.logBatchResult(o),o}};export{h as DEFAULT_BASE_URL,E as DEFAULT_BATCH_INTERVAL_MS,m as DEFAULT_BATCH_SIZE,R as DEFAULT_MAX_RETRIES,f as DEFAULT_TIMEOUT_MS,T as Easydata,p as EasydataError,n as EasydataNetworkError,u as EasydataValidationError,A as SDK_VERSION,g as scrubEntry,c as scrubText};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/constants.ts","../src/transport/http.ts","../src/transport/batch.ts","../src/pii/scrubber.ts","../src/logger.ts","../src/client.ts"],"sourcesContent":["export class EasydataError extends Error {\n constructor(message: string, public readonly code?: string) {\n super(message);\n this.name = \"EasydataError\";\n }\n}\n\nexport class EasydataValidationError extends EasydataError {\n constructor(message: string) {\n super(message, \"VALIDATION_ERROR\");\n this.name = \"EasydataValidationError\";\n }\n}\n\nexport class EasydataNetworkError extends EasydataError {\n public readonly statusCode?: number;\n\n constructor(message: string, statusCode?: number) {\n super(message, \"NETWORK_ERROR\");\n this.name = \"EasydataNetworkError\";\n this.statusCode = statusCode;\n }\n}\n","export const DEFAULT_BASE_URL = \"https://api.easydata.dev\";\nexport const DEFAULT_BATCH_SIZE = 10;\nexport const DEFAULT_BATCH_INTERVAL_MS = 5000;\nexport const DEFAULT_TIMEOUT_MS = 30000;\nexport const DEFAULT_MAX_RETRIES = 3;\nexport const RETRY_BASE_DELAY_MS = 500;\nexport const SDK_VERSION = \"0.1.0\";\n","import { EasydataNetworkError } from \"../errors\";\nimport { RETRY_BASE_DELAY_MS } from \"../constants\";\n\nexport interface HttpOptions {\n baseUrl: string;\n apiKey: string;\n timeoutMs: number;\n maxRetries: number;\n}\n\nfunction isRetryable(status: number): boolean {\n return status >= 500 || status === 429;\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport async function httpPost<T>(\n path: string,\n body: unknown,\n options: HttpOptions\n): Promise<T> {\n const url = `${options.baseUrl}${path}`;\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt < options.maxRetries; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), options.timeoutMs);\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${options.apiKey}`,\n \"X-Easydata-SDK\": \"js/0.1.0\",\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n clearTimeout(timer);\n\n if (response.ok) {\n return (await response.json()) as T;\n }\n\n if (!isRetryable(response.status)) {\n const text = await response.text().catch(() => \"Unknown error\");\n throw new EasydataNetworkError(\n `HTTP ${response.status}: ${text}`,\n response.status\n );\n }\n\n lastError = new EasydataNetworkError(\n `HTTP ${response.status}`,\n response.status\n );\n } catch (err) {\n clearTimeout(timer);\n\n if (err instanceof EasydataNetworkError && !isRetryable(err.statusCode ?? 0)) {\n throw err;\n }\n\n if (err instanceof DOMException && err.name === \"AbortError\") {\n lastError = new EasydataNetworkError(\"Request timed out\");\n } else if (!(err instanceof EasydataNetworkError)) {\n lastError = err instanceof Error ? err : new Error(String(err));\n } else {\n lastError = err;\n }\n }\n\n if (attempt < options.maxRetries - 1) {\n await delay(RETRY_BASE_DELAY_MS * Math.pow(2, attempt));\n }\n }\n\n throw lastError ?? new EasydataNetworkError(\"Request failed after retries\");\n}\n","import type { CorrectionEntry, BatchResult, CaptureResult } from \"../types\";\n\nexport interface QueuedEntry {\n entry: CorrectionEntry;\n resolve: (result: CaptureResult) => void;\n reject: (error: Error) => void;\n}\n\nexport interface BatchQueueOptions {\n size: number;\n intervalMs: number;\n onFlush: (entries: CorrectionEntry[]) => Promise<BatchResult>;\n}\n\nexport class BatchQueue {\n private queue: QueuedEntry[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private readonly options: BatchQueueOptions;\n private _isShutdown = false;\n\n constructor(options: BatchQueueOptions) {\n this.options = options;\n this.startTimer();\n }\n\n get pending(): number {\n return this.queue.length;\n }\n\n get isShutdown(): boolean {\n return this._isShutdown;\n }\n\n enqueue(entry: CorrectionEntry): Promise<CaptureResult> {\n if (this._isShutdown) {\n return Promise.reject(new Error(\"BatchQueue has been shut down\"));\n }\n\n return new Promise<CaptureResult>((resolve, reject) => {\n this.queue.push({ entry, resolve, reject });\n\n if (this.queue.length >= this.options.size) {\n void this.flush();\n }\n });\n }\n\n async flush(): Promise<BatchResult> {\n if (this.queue.length === 0) {\n return { results: [], accepted: 0, rejected: 0, failed: 0 };\n }\n\n const batch = this.queue.splice(0);\n const entries = batch.map((q) => q.entry);\n\n try {\n const result = await this.options.onFlush(entries);\n\n for (let i = 0; i < batch.length; i++) {\n const captureResult = result.results[i];\n if (captureResult) {\n batch[i].resolve(captureResult);\n } else {\n batch[i].resolve({\n id: \"unknown\",\n status: \"failed\",\n reason: \"No result returned\",\n });\n }\n }\n\n return result;\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n for (const item of batch) {\n item.reject(error);\n }\n return {\n results: [],\n accepted: 0,\n rejected: 0,\n failed: batch.length,\n };\n }\n }\n\n async shutdown(): Promise<void> {\n this._isShutdown = true;\n this.stopTimer();\n if (this.queue.length > 0) {\n await this.flush();\n }\n }\n\n private startTimer(): void {\n if (this.options.intervalMs > 0) {\n this.timer = setInterval(() => {\n if (this.queue.length > 0) {\n void this.flush();\n }\n }, this.options.intervalMs);\n }\n }\n\n private stopTimer(): void {\n if (this.timer !== null) {\n clearInterval(this.timer);\n this.timer = null;\n }\n }\n}\n","import type { CorrectionEntry } from \"../types\";\n\nconst PII_PATTERNS: Array<{ pattern: RegExp; replacement: string }> = [\n // SSN must come before phone to avoid false positives\n {\n pattern: /\\b\\d{3}-\\d{2}-\\d{4}\\b/g,\n replacement: \"[REDACTED_SSN]\",\n },\n {\n pattern: /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b/g,\n replacement: \"[REDACTED_EMAIL]\",\n },\n {\n pattern: /\\b\\d{3}[-.]?\\d{3}[-.]?\\d{4}\\b/g,\n replacement: \"[REDACTED_PHONE]\",\n },\n {\n pattern: /\\b(?:4\\d{3}|5[1-5]\\d{2}|3[47]\\d{2}|6(?:011|5\\d{2}))\\d{8,12}\\b/g,\n replacement: \"[REDACTED_CC]\",\n },\n];\n\nexport function scrubText(text: string): string {\n let result = text;\n for (const { pattern, replacement } of PII_PATTERNS) {\n // Reset lastIndex for global regexes\n pattern.lastIndex = 0;\n result = result.replace(pattern, replacement);\n }\n return result;\n}\n\nexport function scrubEntry(entry: CorrectionEntry): CorrectionEntry {\n return {\n ...entry,\n userPrompt: scrubText(entry.userPrompt),\n aiResponse: scrubText(entry.aiResponse),\n userCorrection: scrubText(entry.userCorrection),\n ...(entry.aiCorrectedResponse\n ? { aiCorrectedResponse: scrubText(entry.aiCorrectedResponse) }\n : {}),\n ...(entry.aiInitialPrompt\n ? { aiInitialPrompt: scrubText(entry.aiInitialPrompt) }\n : {}),\n };\n}\n","import type { BatchResult } from \"./types\";\n\nexport class Logger {\n constructor(private readonly debug: boolean = false) {}\n\n info(message: string, ...args: unknown[]): void {\n if (this.debug) {\n console.log(`[easydata] ${message}`, ...args);\n }\n }\n\n warn(message: string, ...args: unknown[]): void {\n console.warn(`[easydata] ${message}`, ...args);\n }\n\n error(message: string, ...args: unknown[]): void {\n console.error(`[easydata] ${message}`, ...args);\n }\n\n logBatchResult(result: BatchResult): void {\n const msg = `${result.accepted} entries accepted ${result.rejected} entries rejected ${result.failed} entries failed`;\n if (result.failed > 0) {\n this.warn(msg);\n } else {\n this.info(msg);\n }\n }\n}\n","import type {\n EasydataConfig,\n CorrectionEntry,\n CaptureResult,\n BatchResult,\n} from \"./types\";\nimport { EasydataValidationError } from \"./errors\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_BATCH_SIZE,\n DEFAULT_BATCH_INTERVAL_MS,\n DEFAULT_TIMEOUT_MS,\n DEFAULT_MAX_RETRIES,\n} from \"./constants\";\nimport { httpPost } from \"./transport/http\";\nimport { BatchQueue } from \"./transport/batch\";\nimport { scrubEntry } from \"./pii/scrubber\";\nimport { Logger } from \"./logger\";\n\nexport class Easydata {\n private readonly config: Required<\n Pick<EasydataConfig, \"apiKey\" | \"baseUrl\" | \"scrubPii\" | \"timeoutMs\" | \"maxRetries\" | \"debug\">\n >;\n private readonly batchQueue: BatchQueue;\n private readonly logger: Logger;\n\n constructor(config: EasydataConfig) {\n if (!config.apiKey) {\n throw new EasydataValidationError(\"apiKey is required\");\n }\n\n this.config = {\n apiKey: config.apiKey,\n baseUrl: config.baseUrl ?? DEFAULT_BASE_URL,\n scrubPii: config.scrubPii ?? true,\n timeoutMs: config.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,\n debug: config.debug ?? false,\n };\n\n this.logger = new Logger(this.config.debug);\n\n this.batchQueue = new BatchQueue({\n size: config.batch?.size ?? DEFAULT_BATCH_SIZE,\n intervalMs: config.batch?.intervalMs ?? DEFAULT_BATCH_INTERVAL_MS,\n onFlush: (entries) => this.sendBatch(entries),\n });\n\n this.logger.info(\"Client initialized\");\n }\n\n async captureCorrection(entry: CorrectionEntry): Promise<CaptureResult> {\n this.validateEntry(entry);\n\n const processed = this.config.scrubPii ? scrubEntry(entry) : entry;\n return this.batchQueue.enqueue(processed);\n }\n\n async captureCorrections(entries: CorrectionEntry[]): Promise<CaptureResult[]> {\n return Promise.all(entries.map((e) => this.captureCorrection(e)));\n }\n\n async flush(): Promise<BatchResult> {\n return this.batchQueue.flush();\n }\n\n async shutdown(): Promise<void> {\n this.logger.info(\"Shutting down client\");\n await this.batchQueue.shutdown();\n }\n\n static createBrowserClient(config: EasydataConfig): Easydata {\n return new Easydata(config);\n }\n\n private validateEntry(entry: CorrectionEntry): void {\n if (!entry.userPrompt) {\n throw new EasydataValidationError(\"userPrompt is required\");\n }\n if (!entry.aiResponse) {\n throw new EasydataValidationError(\"aiResponse is required\");\n }\n if (!entry.userCorrection) {\n throw new EasydataValidationError(\"userCorrection is required\");\n }\n }\n\n private toApiEntry(entry: CorrectionEntry) {\n return {\n user_prompt: entry.userPrompt,\n ai_response: entry.aiResponse,\n user_correction: entry.userCorrection,\n ...(entry.aiCorrectedResponse && { ai_corrected_response: entry.aiCorrectedResponse }),\n ...(entry.aiInitialPrompt && { system_prompt: entry.aiInitialPrompt }),\n ...(entry.provider && { provider: entry.provider }),\n ...(entry.model && { model: entry.model }),\n ...(entry.domain && { domain: entry.domain }),\n ...(entry.metadata && { metadata: entry.metadata }),\n };\n }\n\n private async sendBatch(entries: CorrectionEntry[]): Promise<BatchResult> {\n this.logger.info(`Sending batch of ${entries.length} entries`);\n\n const apiEntries = entries.map((e) => this.toApiEntry(e));\n\n const result = await httpPost<BatchResult>(\n \"/v1/corrections\",\n { entries: apiEntries },\n {\n baseUrl: this.config.baseUrl,\n apiKey: this.config.apiKey,\n timeoutMs: this.config.timeoutMs,\n maxRetries: this.config.maxRetries,\n }\n );\n\n this.logger.logBatchResult(result);\n return result;\n }\n}\n"],"mappings":"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","names":["EasydataError","message","code","EasydataValidationError","EasydataNetworkError","statusCode","DEFAULT_BASE_URL","DEFAULT_BATCH_SIZE","DEFAULT_BATCH_INTERVAL_MS","DEFAULT_TIMEOUT_MS","DEFAULT_MAX_RETRIES","SDK_VERSION","isRetryable","status","delay","ms","resolve","httpPost","path","body","options","url","lastError","attempt","controller","timer","response","text","EasydataNetworkError","err","BatchQueue","options","entry","resolve","reject","batch","entries","q","result","captureResult","err","error","item","PII_PATTERNS","scrubText","text","result","pattern","replacement","scrubEntry","entry","Logger","debug","message","args","result","msg","Easydata","_Easydata","config","EasydataValidationError","DEFAULT_BASE_URL","Logger","BatchQueue","entries","entry","processed","scrubEntry","e","apiEntries","result","httpPost"]}
@@ -0,0 +1,60 @@
1
+ type Domain = "legal" | "healthcare" | "finance" | "writing" | "general" | "education" | "technology" | (string & {});
2
+ interface CorrectionEntry {
3
+ /** The user's original prompt / question */
4
+ userPrompt: string;
5
+ /** The AI's initial response */
6
+ aiResponse: string;
7
+ /** The user's correction or feedback */
8
+ userCorrection: string;
9
+ /** Optional: the AI's corrected response after user feedback */
10
+ aiCorrectedResponse?: string;
11
+ /** Optional: AI system prompt / initial greeting */
12
+ aiInitialPrompt?: string;
13
+ /** Optional: AI provider (e.g. "anthropic", "openai") */
14
+ provider?: string;
15
+ /** Optional: model identifier */
16
+ model?: string;
17
+ /** Optional: domain/industry classification */
18
+ domain?: Domain;
19
+ /** Optional: arbitrary metadata */
20
+ metadata?: Record<string, unknown>;
21
+ }
22
+ interface CaptureResult {
23
+ id: string;
24
+ status: "accepted" | "rejected" | "failed";
25
+ reason?: string;
26
+ }
27
+ interface BatchResult {
28
+ results: CaptureResult[];
29
+ accepted: number;
30
+ rejected: number;
31
+ failed: number;
32
+ }
33
+ interface BatchConfig {
34
+ /** Max entries before auto-flush (default: 10) */
35
+ size?: number;
36
+ /** Interval in ms between auto-flushes (default: 5000) */
37
+ intervalMs?: number;
38
+ }
39
+ interface EasydataConfig {
40
+ /** API key (required) */
41
+ apiKey: string;
42
+ /** Base URL for the Easydata API */
43
+ baseUrl?: string;
44
+ /** Batch configuration */
45
+ batch?: BatchConfig;
46
+ /** Enable PII scrubbing (default: true) */
47
+ scrubPii?: boolean;
48
+ /** Request timeout in ms (default: 30000) */
49
+ timeoutMs?: number;
50
+ /** Max retry attempts (default: 3) */
51
+ maxRetries?: number;
52
+ /** Enable debug logging (default: false) */
53
+ debug?: boolean;
54
+ }
55
+ interface EphemeralToken {
56
+ token: string;
57
+ expiresAt: string;
58
+ }
59
+
60
+ export type { BatchResult as B, CorrectionEntry as C, Domain as D, EasydataConfig as E, CaptureResult as a, BatchConfig as b, EphemeralToken as c };
@@ -0,0 +1,60 @@
1
+ type Domain = "legal" | "healthcare" | "finance" | "writing" | "general" | "education" | "technology" | (string & {});
2
+ interface CorrectionEntry {
3
+ /** The user's original prompt / question */
4
+ userPrompt: string;
5
+ /** The AI's initial response */
6
+ aiResponse: string;
7
+ /** The user's correction or feedback */
8
+ userCorrection: string;
9
+ /** Optional: the AI's corrected response after user feedback */
10
+ aiCorrectedResponse?: string;
11
+ /** Optional: AI system prompt / initial greeting */
12
+ aiInitialPrompt?: string;
13
+ /** Optional: AI provider (e.g. "anthropic", "openai") */
14
+ provider?: string;
15
+ /** Optional: model identifier */
16
+ model?: string;
17
+ /** Optional: domain/industry classification */
18
+ domain?: Domain;
19
+ /** Optional: arbitrary metadata */
20
+ metadata?: Record<string, unknown>;
21
+ }
22
+ interface CaptureResult {
23
+ id: string;
24
+ status: "accepted" | "rejected" | "failed";
25
+ reason?: string;
26
+ }
27
+ interface BatchResult {
28
+ results: CaptureResult[];
29
+ accepted: number;
30
+ rejected: number;
31
+ failed: number;
32
+ }
33
+ interface BatchConfig {
34
+ /** Max entries before auto-flush (default: 10) */
35
+ size?: number;
36
+ /** Interval in ms between auto-flushes (default: 5000) */
37
+ intervalMs?: number;
38
+ }
39
+ interface EasydataConfig {
40
+ /** API key (required) */
41
+ apiKey: string;
42
+ /** Base URL for the Easydata API */
43
+ baseUrl?: string;
44
+ /** Batch configuration */
45
+ batch?: BatchConfig;
46
+ /** Enable PII scrubbing (default: true) */
47
+ scrubPii?: boolean;
48
+ /** Request timeout in ms (default: 30000) */
49
+ timeoutMs?: number;
50
+ /** Max retry attempts (default: 3) */
51
+ maxRetries?: number;
52
+ /** Enable debug logging (default: false) */
53
+ debug?: boolean;
54
+ }
55
+ interface EphemeralToken {
56
+ token: string;
57
+ expiresAt: string;
58
+ }
59
+
60
+ export type { BatchResult as B, CorrectionEntry as C, Domain as D, EasydataConfig as E, CaptureResult as a, BatchConfig as b, EphemeralToken as c };
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@easy-data/sdk",
3
+ "version": "0.1.0",
4
+ "description": "Easydata SDK — capture user corrections for AI improvement",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ },
20
+ "./browser": {
21
+ "import": {
22
+ "types": "./dist/browser/index.d.ts",
23
+ "default": "./dist/browser/index.js"
24
+ },
25
+ "require": {
26
+ "types": "./dist/browser/index.d.cts",
27
+ "default": "./dist/browser/index.cjs"
28
+ }
29
+ }
30
+ },
31
+ "files": ["dist"],
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "scripts": {
36
+ "build": "tsup --minify",
37
+ "test": "vitest run",
38
+ "test:watch": "vitest",
39
+ "lint": "tsc --noEmit"
40
+ },
41
+ "devDependencies": {
42
+ "tsup": "^8.0.0",
43
+ "typescript": "^5.4.0",
44
+ "vitest": "^2.0.0"
45
+ }
46
+ }