@fincuratech/stedi-sdk-js 1.7.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -27
- package/dist/endpoints/eligibility.js.map +1 -1
- package/dist/endpoints/enrollment.js.map +1 -1
- package/dist/endpoints/payers.js.map +1 -1
- package/dist/endpoints/provider.js.map +1 -1
- package/dist/endpoints/transactions.js.map +1 -1
- package/dist/index.js +5 -20
- package/dist/index.js.map +1 -1
- package/dist/lib/client.js +1 -1
- package/dist/lib/client.js.map +1 -1
- package/dist/mock-defaults.js +114 -0
- package/dist/mock-defaults.js.map +1 -0
- package/dist/sdk.js +21 -0
- package/dist/sdk.js.map +1 -0
- package/dist/store.js +94 -0
- package/dist/store.js.map +1 -0
- package/dist/test-mode.js +85 -0
- package/dist/test-mode.js.map +1 -0
- package/dist/types/endpoints/eligibility.d.ts +2 -2
- package/dist/types/endpoints/eligibility.d.ts.map +1 -1
- package/dist/types/endpoints/enrollment.d.ts +2 -2
- package/dist/types/endpoints/enrollment.d.ts.map +1 -1
- package/dist/types/endpoints/payers.d.ts +2 -2
- package/dist/types/endpoints/payers.d.ts.map +1 -1
- package/dist/types/endpoints/provider.d.ts +2 -2
- package/dist/types/endpoints/provider.d.ts.map +1 -1
- package/dist/types/endpoints/transactions.d.ts +2 -2
- package/dist/types/endpoints/transactions.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -32
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/client.d.ts +2 -2
- package/dist/types/lib/client.d.ts.map +1 -1
- package/dist/types/mock-defaults.d.ts +7 -0
- package/dist/types/mock-defaults.d.ts.map +1 -0
- package/dist/types/sdk.d.ts +32 -0
- package/dist/types/sdk.d.ts.map +1 -0
- package/dist/types/store.d.ts +14 -0
- package/dist/types/store.d.ts.map +1 -0
- package/dist/types/test-mode.d.ts +3 -0
- package/dist/types/test-mode.d.ts.map +1 -0
- package/package.json +3 -3
- package/dist/in-memory.js +0 -296
- package/dist/in-memory.js.map +0 -1
- package/dist/types/in-memory.d.ts +0 -17
- package/dist/types/in-memory.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ TypeScript SDK for [Stedi's EDI Platform and Healthcare APIs](https://www.stedi.
|
|
|
19
19
|
|
|
20
20
|
- [Installation](#installation)
|
|
21
21
|
- [Quick Start](#quick-start)
|
|
22
|
-
- [
|
|
22
|
+
- [Modes: live vs test](#modes-live-vs-test)
|
|
23
23
|
- [API Reference](#api-reference)
|
|
24
24
|
- [Eligibility](#eligibility)
|
|
25
25
|
- [Payers](#payers)
|
|
@@ -64,7 +64,7 @@ pnpm add @fincuratech/stedi-sdk-js
|
|
|
64
64
|
import { createStediClient } from '@fincuratech/stedi-sdk-js';
|
|
65
65
|
|
|
66
66
|
// Initialize the client with your Stedi API key
|
|
67
|
-
const stedi = createStediClient('your-stedi-api-key');
|
|
67
|
+
const stedi = createStediClient('your-stedi-api-key', 'live');
|
|
68
68
|
|
|
69
69
|
// Check insurance eligibility
|
|
70
70
|
const eligibilityResult = await stedi.eligibility.check({
|
|
@@ -86,25 +86,35 @@ const eligibilityResult = await stedi.eligibility.check({
|
|
|
86
86
|
console.log(eligibilityResult.benefitsInformation);
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
##
|
|
89
|
+
## Modes: live vs test
|
|
90
90
|
|
|
91
|
-
`
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
`createStediClient(apiKey, mode)` takes a mandatory `mode` argument: `'live'` or
|
|
92
|
+
`'test'`. This mirrors [Stedi's test mode](https://www.stedi.com/docs/healthcare/test-mode)
|
|
93
|
+
and complements the enrollment endpoints Stedi test mode does not yet support.
|
|
94
|
+
|
|
95
|
+
| Mode | Behavior |
|
|
96
|
+
|------|----------|
|
|
97
|
+
| `'live'` | Every request goes to Stedi. Use in production. |
|
|
98
|
+
| `'test'` | `provider.create` and `enrollment.create` are stored in memory (transaction enrollment is [not supported in Stedi test mode](https://www.stedi.com/docs/healthcare/test-mode)). Reads call Stedi and merge in-memory records. `eligibility`, `payers`, `transactions`, and `downloadFile` pass through to Stedi unchanged. |
|
|
99
|
+
|
|
100
|
+
In `'test'` mode the API key is never inspected. If Stedi rejects the key with a
|
|
101
|
+
`401`/`403` (a fake, empty, or wrong key), the client silently switches to fully
|
|
102
|
+
mocked data for all reads: built-in seed payers, a minimal eligibility response,
|
|
103
|
+
empty transactions, a placeholder EDI file, and provider/enrollment reads served
|
|
104
|
+
from the in-memory store. This lets the same code run with a real test key (real
|
|
105
|
+
reads merged with in-memory writes) or with no usable key at all (fully offline).
|
|
106
|
+
Non-auth errors (e.g. `500`, network failures) are not swallowed and still throw.
|
|
96
107
|
|
|
97
108
|
```typescript
|
|
98
|
-
import {
|
|
99
|
-
createInMemoryStediClient,
|
|
100
|
-
createInMemoryStediStore,
|
|
101
|
-
} from '@fincuratech/stedi-sdk-js';
|
|
109
|
+
import { createStediClient } from '@fincuratech/stedi-sdk-js';
|
|
102
110
|
|
|
103
|
-
//
|
|
104
|
-
const
|
|
105
|
-
const stedi = createInMemoryStediClient({ store });
|
|
111
|
+
// Production: all requests hit Stedi
|
|
112
|
+
const live = createStediClient(process.env.STEDI_API_KEY, 'live');
|
|
106
113
|
|
|
107
|
-
|
|
114
|
+
// Test/dev: enrollment writes are faked; reads merge real + in-memory data
|
|
115
|
+
const test = createStediClient(process.env.STEDI_API_KEY, 'test');
|
|
116
|
+
|
|
117
|
+
const provider = await test.provider.create({
|
|
108
118
|
name: 'Main Street Medical Clinic',
|
|
109
119
|
npi: '1234567890',
|
|
110
120
|
taxId: '123456789',
|
|
@@ -112,14 +122,15 @@ const provider = await stedi.provider.create({
|
|
|
112
122
|
contacts: [],
|
|
113
123
|
});
|
|
114
124
|
|
|
115
|
-
|
|
125
|
+
// Resolves from the in-memory store without calling Stedi
|
|
126
|
+
await test.provider.get(provider.id);
|
|
127
|
+
|
|
128
|
+
// Lists real Stedi providers plus in-memory ones
|
|
129
|
+
await test.provider.list();
|
|
116
130
|
```
|
|
117
131
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
generic, environment-agnostic defaults. **Deciding when to use the real client vs.
|
|
121
|
-
the in-memory one, and providing realistic business fixtures, remains entirely the
|
|
122
|
-
consumer's responsibility** — the SDK has no notion of your environment or payers.
|
|
132
|
+
When Stedi adds native test support for enrollment, the SDK can stop intercepting
|
|
133
|
+
those writes and they will flow through to Stedi with no API shape change.
|
|
123
134
|
|
|
124
135
|
## API Reference
|
|
125
136
|
|
|
@@ -633,7 +644,7 @@ import type {
|
|
|
633
644
|
```typescript
|
|
634
645
|
import { createStediClient, type StediEligibilityInput } from '@fincuratech/stedi-sdk-js';
|
|
635
646
|
|
|
636
|
-
const stedi = createStediClient(process.env.STEDI_API_KEY
|
|
647
|
+
const stedi = createStediClient(process.env.STEDI_API_KEY, 'live');
|
|
637
648
|
|
|
638
649
|
// TypeScript will validate your input
|
|
639
650
|
const input: StediEligibilityInput = {
|
|
@@ -667,7 +678,7 @@ By default, the SDK uses a no-op logger that doesn't output anything:
|
|
|
667
678
|
```typescript
|
|
668
679
|
import { createStediClient } from '@fincuratech/stedi-sdk-js';
|
|
669
680
|
|
|
670
|
-
const stedi = createStediClient('your-api-key');
|
|
681
|
+
const stedi = createStediClient('your-api-key', 'live');
|
|
671
682
|
// No logging output - silent by default
|
|
672
683
|
```
|
|
673
684
|
|
|
@@ -681,7 +692,7 @@ import { createStediClient, setLogger, createConsoleLogger } from '@fincuratech/
|
|
|
681
692
|
// Enable console logging at 'debug' level
|
|
682
693
|
setLogger(createConsoleLogger('debug'));
|
|
683
694
|
|
|
684
|
-
const stedi = createStediClient('your-api-key');
|
|
695
|
+
const stedi = createStediClient('your-api-key', 'live');
|
|
685
696
|
|
|
686
697
|
// Now you'll see debug logs in the console:
|
|
687
698
|
// [stedi-sdk] DEBUG: Stedi API request { method: 'POST', path: '/eligibility', ... }
|
|
@@ -728,7 +739,7 @@ const stediLogger: Logger = {
|
|
|
728
739
|
// Set the custom logger
|
|
729
740
|
setLogger(stediLogger);
|
|
730
741
|
|
|
731
|
-
const stedi = createStediClient('your-api-key');
|
|
742
|
+
const stedi = createStediClient('your-api-key', 'live');
|
|
732
743
|
// All SDK logs now go through Winston
|
|
733
744
|
```
|
|
734
745
|
|
|
@@ -754,7 +765,7 @@ const stediLogger: Logger = {
|
|
|
754
765
|
|
|
755
766
|
setLogger(stediLogger);
|
|
756
767
|
|
|
757
|
-
const stedi = createStediClient('your-api-key');
|
|
768
|
+
const stedi = createStediClient('your-api-key', 'live');
|
|
758
769
|
```
|
|
759
770
|
|
|
760
771
|
### Logger Interface
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eligibility.js","sourceRoot":"","sources":["../../src/endpoints/eligibility.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"eligibility.js","sourceRoot":"","sources":["../../src/endpoints/eligibility.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAuB,EAAE,OAAe,EAAE,EAAE;IACtE,OAAO;QASL,KAAK,EAAE,KAAK,EACV,KAA4B,EACO,EAAE;YACrC,MAAM,IAAI,GAAG;gBACX,GAAG,KAAK;gBACR,SAAS,EAAE;oBACT,gBAAgB,EAAE;wBAChB,IAAI;wBACJ,IAAI;wBACJ,IAAI;wBACJ,IAAI;wBACJ,IAAI;wBACJ,IAAI;wBACJ,IAAI;wBACJ,IAAI;wBACJ,IAAI;wBACJ,IAAI;qBACL;iBACF;aACF,CAAC;YAEF,OAAO,MAAM,MAAM,CAAC,OAAO,CACzB,OAAO,EACP,MAAM,EACN,uCAAuC,EACvC;gBACE,IAAI;aACL,CACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { type StediHttpClient } from '../lib/client.js';\nimport {\n type StediEligibilityInput,\n type StediEligibilityResponse,\n} from '../lib/types.js';\n\nexport const eligibility = (client: StediHttpClient, baseUrl: string) => {\n return {\n /**\n * Sends a real-time eligibility check to payers.\n *\n * @see https://www.stedi.com/docs/api-reference/healthcare/post-healthcare-eligibility\n *\n * @param input - The eligibility check parameters including subscriber, provider, and trading partner information.\n * @returns A promise that resolves to the eligibility response with benefits information.\n */\n check: async (\n input: StediEligibilityInput,\n ): Promise<StediEligibilityResponse> => {\n const data = {\n ...input,\n encounter: {\n serviceTypeCodes: [\n '27',\n '28',\n '30',\n '35',\n '36',\n '37',\n '38',\n '39',\n '40',\n '41',\n ],\n },\n };\n\n return await client.request(\n baseUrl,\n 'POST',\n '/change/medicalnetwork/eligibility/v3',\n {\n data,\n },\n );\n },\n };\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enrollment.js","sourceRoot":"","sources":["../../src/endpoints/enrollment.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"enrollment.js","sourceRoot":"","sources":["../../src/endpoints/enrollment.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAAuB,EAAE,OAAe,EAAE,EAAE;IACrE,OAAO;QASL,MAAM,EAAE,KAAK,EACX,KAA2B,EACO,EAAE;YACpC,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE;gBAC3D,IAAI,EAAE,KAAK;aACZ,CAAC,CAAC;QACL,CAAC;QAUD,GAAG,EAAE,KAAK,EAAE,YAAoB,EAAoC,EAAE;YACpE,OAAO,MAAM,MAAM,CAAC,OAAO,CACzB,OAAO,EACP,KAAK,EACL,gBAAgB,YAAY,EAAE,CAC/B,CAAC;QACJ,CAAC;QAUD,IAAI,EAAE,KAAK,EACT,SAAqC,EAAE,EACA,EAAE;YACzC,OAAO,MAAM,MAAM,CAAC,OAAO,CACzB,OAAO,EACP,KAAK,EACL,cAAc,EACd;gBACE,MAAM;aACP,CACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { type StediHttpClient } from '../lib/client.js';\nimport {\n type StediEnrollmentInput,\n type StediEnrollmentResponse,\n type StediListEnrollmentsParams,\n type StediListEnrollmentsResponse,\n} from '../lib/types.js';\n\nexport const enrollment = (client: StediHttpClient, baseUrl: string) => {\n return {\n /**\n * Create a Stedi enrollment for a provider\n *\n * @see https://www.stedi.com/docs/api-reference/healthcare/post-enrollment-create-enrollment\n *\n * @param input - The enrollment information.\n * @returns A promise that resolves to the enrollment response.\n */\n create: async (\n input: StediEnrollmentInput,\n ): Promise<StediEnrollmentResponse> => {\n return await client.request(baseUrl, 'POST', '/enrollments', {\n data: input,\n });\n },\n\n /**\n * Get a single enrollment by ID.\n *\n * @see https://www.stedi.com/docs/api-reference/healthcare/get-enrollment\n *\n * @param enrollmentId - The ID of the enrollment to retrieve.\n * @returns A promise that resolves to the enrollment.\n */\n get: async (enrollmentId: string): Promise<StediEnrollmentResponse> => {\n return await client.request<StediEnrollmentResponse>(\n baseUrl,\n 'GET',\n `/enrollments/${enrollmentId}`,\n );\n },\n\n /**\n * List transaction enrollment records with optional filtering and pagination.\n *\n * @see https://www.stedi.com/docs/healthcare/api-reference/get-enrollment-list-enrollments\n *\n * @param params - Optional filtering and pagination parameters.\n * @returns A promise that resolves to the list of enrollments.\n */\n list: async (\n params: StediListEnrollmentsParams = {},\n ): Promise<StediListEnrollmentsResponse> => {\n return await client.request<StediListEnrollmentsResponse>(\n baseUrl,\n 'GET',\n '/enrollments',\n {\n params,\n },\n );\n },\n };\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payers.js","sourceRoot":"","sources":["../../src/endpoints/payers.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"payers.js","sourceRoot":"","sources":["../../src/endpoints/payers.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,MAAuB,EAAE,OAAe,EAAE,EAAE;IACjE,OAAO;QAQL,GAAG,EAAE,KAAK,IAA0C,EAAE;YACpD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CACnC,OAAO,EACP,KAAK,EACL,SAAS,CACV,CAAC;YAEF,OAAO,QAAQ,CAAC,KAAK,CAAC;QACxB,CAAC;QAUD,MAAM,EAAE,KAAK,EACX,eAA2D,EACrB,EAAE;YACxC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CACnC,OAAO,EACP,KAAK,EACL,gBAAgB,EAChB;gBACE,MAAM,EAAE,eAAe;aACxB,CACF,CAAC;YAEF,OAAO,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClD,CAAC;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { type StediHttpClient } from '../lib/client.js';\nimport {\n type StediPayerResponse,\n type StediPayerSearchResponse,\n} from '../lib/types.js';\n\nexport const payers = (client: StediHttpClient, baseUrl: string) => {\n return {\n /**\n * Get all payers.\n *\n * @see https://www.stedi.com/docs/api-reference/healthcare/get-payers\n *\n * @returns A promise that resolves to all Stedi's supported payers.\n */\n get: async (): Promise<StediPayerResponse['items']> => {\n const response = await client.request<StediPayerResponse>(\n baseUrl,\n 'GET',\n '/payers',\n );\n\n return response.items;\n },\n\n /**\n * Search for payers.\n *\n * @see https://www.stedi.com/docs/api-reference/healthcare/get-search-payers\n *\n * @param queryParameters - The query parameters to search for.\n * @returns A promise that resolves to the filtered payers.\n */\n search: async (\n queryParameters: Record<string, string[] | number | string>,\n ): Promise<StediPayerResponse['items']> => {\n const response = await client.request<StediPayerSearchResponse>(\n baseUrl,\n 'GET',\n '/payers/search',\n {\n params: queryParameters,\n },\n );\n\n return response.items.map((item) => item.payer);\n },\n };\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/endpoints/provider.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/endpoints/provider.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,MAAuB,EAAE,OAAe,EAAE,EAAE;IACnE,OAAO;QASL,MAAM,EAAE,KAAK,EACX,KAAyB,EACO,EAAE;YAClC,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE;gBACzD,IAAI,EAAE,KAAK;aACZ,CAAC,CAAC;QACL,CAAC;QAUD,GAAG,EAAE,KAAK,EAAE,UAAkB,EAAkC,EAAE;YAChE,OAAO,MAAM,MAAM,CAAC,OAAO,CACzB,OAAO,EACP,KAAK,EACL,cAAc,UAAU,EAAE,EAC1B,EAAE,CACH,CAAC;QACJ,CAAC;QAUD,IAAI,EAAE,KAAK,EACT,SAAmC,EAAE,EACD,EAAE;YACtC,OAAO,MAAM,MAAM,CAAC,OAAO,CACzB,OAAO,EACP,KAAK,EACL,YAAY,EACZ;gBACE,MAAM;aACP,CACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { type StediHttpClient } from '../lib/client.js';\nimport {\n type StediListProvidersParams,\n type StediProviderInput,\n type StediProviderListResponse,\n type StediProviderResponse,\n} from '../lib/types.js';\n\nexport const provider = (client: StediHttpClient, baseUrl: string) => {\n return {\n /**\n * Create a Stedi provider\n *\n * @see https://www.stedi.com/docs/api-reference/healthcare/post-enrollment-create-provider\n *\n * @param input - The provider information.\n * @returns A promise that resolves to the provider response.\n */\n create: async (\n input: StediProviderInput,\n ): Promise<StediProviderResponse> => {\n return await client.request(baseUrl, 'POST', '/providers', {\n data: input,\n });\n },\n\n /**\n * Get a Stedi provider by ID\n *\n * @see https://www.stedi.com/docs/api-reference/healthcare/get-enrollment-provider\n *\n * @param providerId - The ID of the provider to retrieve.\n * @returns A promise that resolves to the provider response.\n */\n get: async (providerId: string): Promise<StediProviderResponse> => {\n return await client.request(\n baseUrl,\n 'GET',\n `/providers/${providerId}`,\n {},\n );\n },\n\n /**\n * List Stedi providers with optional filtering and pagination.\n *\n * @see https://www.stedi.com/docs/api-reference/healthcare/get-enrollment-providers\n *\n * @param params - Optional filtering and pagination parameters.\n * @returns A promise that resolves to the list of providers.\n */\n list: async (\n params: StediListProvidersParams = {},\n ): Promise<StediProviderListResponse> => {\n return await client.request<StediProviderListResponse>(\n baseUrl,\n 'GET',\n '/providers',\n {\n params,\n },\n );\n },\n };\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transactions.js","sourceRoot":"","sources":["../../src/endpoints/transactions.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"transactions.js","sourceRoot":"","sources":["../../src/endpoints/transactions.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAuB,EAAE,OAAe,EAAE,EAAE;IACvE,OAAO;QASL,GAAG,EAAE,KAAK,EACR,aAAqB,EACiB,EAAE;YACxC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CACnC,OAAO,EACP,KAAK,EACL,iBAAiB,aAAa,EAAE,CACjC,CAAC;YAEF,OAAO,QAAQ,CAAC;QAClB,CAAC;QASD,IAAI,EAAE,KAAK,EACT,SAGI,EAAE,EACiC,EAAE;YACzC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CACnC,OAAO,EACP,KAAK,EACL,eAAe,EACf;gBACE,MAAM;aACP,CACF,CAAC;YAEF,OAAO,QAAQ,CAAC;QAClB,CAAC;QASD,MAAM,EAAE,KAAK,EACX,SAEI,EAAE,EACiC,EAAE;YACzC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CACnC,OAAO,EACP,KAAK,EACL,eAAe,EACf;gBACE,MAAM;aACP,CACF,CAAC;YAEF,OAAO,QAAQ,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { type StediHttpClient } from '../lib/client.js';\nimport {\n type StediTransactionGetResponse,\n type StediTransactionListResponse,\n} from '../lib/types.js';\n\nexport const transactions = (client: StediHttpClient, baseUrl: string) => {\n return {\n /**\n * Get a transaction.\n *\n * @see https://www.stedi.com/docs/api-reference/edi-platform/core/get-transactions\n *\n * @param transactionId - The ID of the transaction to get.\n * @returns A promise that resolves to the transaction.\n */\n get: async (\n transactionId: string,\n ): Promise<StediTransactionGetResponse> => {\n const response = await client.request<StediTransactionGetResponse>(\n baseUrl,\n 'GET',\n `/transactions/${transactionId}`,\n );\n\n return response;\n },\n\n /**\n * Fecth a list of transactions.\n *\n * @see https://www.stedi.com/docs/api-reference/edi-platform/core/get-list-transactions\n *\n * @returns A promise that resolves to the transactions.\n */\n list: async (\n params: {\n pageSize?: number;\n pageToken?: string;\n } = {},\n ): Promise<StediTransactionListResponse> => {\n const response = await client.request<StediTransactionListResponse>(\n baseUrl,\n 'GET',\n '/transactions',\n {\n params,\n },\n );\n\n return response;\n },\n\n /**\n * Search for specific transactions.\n *\n * @see https://www.stedi.com/docs/api-reference/edi-platform/core/get-list-transactions\n *\n * @returns A promise that resolves to the transactions.\n */\n search: async (\n params: {\n businessIdentifier?: string;\n } = {},\n ): Promise<StediTransactionListResponse> => {\n const response = await client.request<StediTransactionListResponse>(\n baseUrl,\n 'GET',\n '/transactions',\n {\n params,\n },\n );\n\n return response;\n },\n };\n};\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,26 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { payers } from './endpoints/payers.js';
|
|
4
|
-
import { provider } from './endpoints/provider.js';
|
|
5
|
-
import { transactions } from './endpoints/transactions.js';
|
|
6
|
-
import { stediClient } from './lib/client.js';
|
|
7
|
-
export { clearInMemoryStediStore, createInMemoryStediClient, createInMemoryStediStore, } from './in-memory.js';
|
|
1
|
+
import { buildStediClient } from './sdk.js';
|
|
2
|
+
import { withTestMode } from './test-mode.js';
|
|
8
3
|
export { StediApiError } from './lib/errors.js';
|
|
9
4
|
export { createConsoleLogger, createNoOpLogger, setLogger, } from './lib/logger.js';
|
|
10
5
|
export * from './lib/types.js';
|
|
11
|
-
export const createStediClient = (apiKey) => {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
const enrollmentsBaseUrl = 'https://enrollments.us.stedi.com/2024-09-01';
|
|
15
|
-
const client = stediClient(apiKey);
|
|
16
|
-
return {
|
|
17
|
-
downloadFile: client.downloadFile,
|
|
18
|
-
eligibility: eligibility(client, healthcareBaseUrl),
|
|
19
|
-
enrollment: enrollment(client, enrollmentsBaseUrl),
|
|
20
|
-
payers: payers(client, healthcareBaseUrl),
|
|
21
|
-
provider: provider(client, enrollmentsBaseUrl),
|
|
22
|
-
transactions: transactions(client, coreBaseUrl),
|
|
23
|
-
};
|
|
6
|
+
export const createStediClient = (apiKey, mode) => {
|
|
7
|
+
const client = buildStediClient(apiKey);
|
|
8
|
+
return mode === 'test' ? withTestMode(client) : client;
|
|
24
9
|
};
|
|
25
10
|
export default createStediClient;
|
|
26
11
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAoB,MAAM,UAAU,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,aAAa,EAAuB,MAAM,iBAAiB,CAAC;AACrE,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAEhB,SAAS,GACV,MAAM,iBAAiB,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAe/B,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,MAAc,EACd,IAAe,EACF,EAAE;IACf,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAExC,OAAO,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AACzD,CAAC,CAAC;AAEF,eAAe,iBAAiB,CAAC","sourcesContent":["import { buildStediClient, type StediClient } from './sdk.js';\nimport { withTestMode } from './test-mode.js';\n\nexport { StediApiError, type StediErrorBody } from './lib/errors.js';\nexport {\n createConsoleLogger,\n createNoOpLogger,\n type Logger,\n setLogger,\n} from './lib/logger.js';\nexport * from './lib/types.js';\nexport { type StediClient } from './sdk.js';\n\nexport type StediMode = 'live' | 'test';\n\n/**\n * Create a Stedi API client.\n *\n * @param apiKey - Stedi API key.\n * @param mode - `'live'` sends every request to Stedi. `'test'` fakes\n * `provider.create` and `enrollment.create` in memory (unsupported in Stedi\n * test mode) and merges those records into real Stedi reads. If Stedi rejects\n * the API key, `'test'` silently serves fully mocked data instead.\n * @returns A {@link StediClient}.\n */\nexport const createStediClient = (\n apiKey: string,\n mode: StediMode,\n): StediClient => {\n const client = buildStediClient(apiKey);\n\n return mode === 'test' ? withTestMode(client) : client;\n};\n\nexport default createStediClient;\n"]}
|
package/dist/lib/client.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import axios, { AxiosError } from 'axios';
|
|
2
2
|
import { StediApiError } from './errors.js';
|
|
3
3
|
import { getLogger } from './logger.js';
|
|
4
|
-
export const
|
|
4
|
+
export const stediHttpClient = (apiKey) => {
|
|
5
5
|
const defaultHeaders = {
|
|
6
6
|
headers: {
|
|
7
7
|
Authorization: apiKey,
|
package/dist/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAwC,MAAM,OAAO,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAOxC,MAAM,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"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","sourcesContent":["import axios, { AxiosError, type AxiosRequestConfig, type Method } from 'axios';\n\nimport { StediApiError } from './errors.js';\nimport { getLogger } from './logger.js';\n\n/**\n * Create an HTTP client for the Stedi API.\n *\n * @returns The Stedi HTTP client.\n */\nexport const stediHttpClient = (apiKey: string) => {\n const defaultHeaders = {\n headers: {\n Authorization: apiKey,\n 'Content-Type': 'application/json',\n },\n };\n\n /**\n * Download a file from the Stedi API.\n *\n * @param url - The URL to download the file from.\n * @returns The file content.\n */\n const downloadFile = async (url: string): Promise<string> => {\n // Validate that the URL is from stedi.com or its subdomains\n const stediUrlRegex = /^https:\\/\\/(?:[\\dA-Za-z-]+\\.)*stedi\\.com\\/.*/u;\n if (!stediUrlRegex.test(url)) {\n throw new Error(\n 'Invalid URL: The URL must be from the Stedi API (stedi.com or its subdomains)',\n );\n }\n\n try {\n const response = await axios.get(url, {\n ...defaultHeaders,\n responseType: 'arraybuffer',\n });\n // Convert buffer to string if it's a buffer\n if (Buffer.isBuffer(response.data)) {\n return response.data.toString('utf8');\n }\n\n return response.data;\n } catch (error) {\n if (error instanceof AxiosError) {\n delete error.config;\n delete error.request;\n delete error.response?.request;\n\n throw new StediApiError(\n `Request to Stedi API failed: ${\n error.response?.data.message ||\n error.response?.data.detail ||\n error.message\n }`,\n error.response?.status ?? 0,\n error.response?.data,\n error,\n );\n } else {\n throw error;\n }\n }\n };\n\n /**\n * Execute a request to the Stedi API.\n *\n * @param baseUrl - The base URL to use.\n * @param method - The HTTP method to use.\n * @param path - The path to request.\n * @param [config] - custom configuration for the request.\n * @returns The result of the request.\n */\n const request = async <T>(\n baseUrl: string,\n method: Method,\n path: string,\n config?: AxiosRequestConfig,\n ): Promise<T> => {\n const log = getLogger();\n\n try {\n log.debug('Stedi API request', { config, method, path });\n\n const response = await axios.request<T>({\n ...config,\n headers: {\n ...defaultHeaders.headers,\n ...config?.headers,\n },\n method,\n // Serialize arrays without brackets\n paramsSerializer: {\n indexes: null,\n },\n url: `${baseUrl}/${path.replace(/^\\//u, '')}`,\n });\n\n log.debug('Stedi API response', {\n data: response.data,\n status: response.status,\n });\n\n return response.data;\n } catch (error) {\n if (error instanceof AxiosError) {\n delete error.config;\n delete error.request;\n delete error.response?.request;\n\n throw new StediApiError(\n `Request to Stedi API failed: ${\n error.response?.data.message ||\n error.response?.data.detail ||\n error.message\n }`,\n error.response?.status ?? 0,\n error.response?.data,\n error,\n );\n } else {\n throw error;\n }\n }\n };\n\n return {\n downloadFile,\n request,\n };\n};\n\nexport type StediHttpClient = ReturnType<typeof stediHttpClient>;\n"]}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
export const PLACEHOLDER_EDI = 'ISA*00* *00* *ZZ*INMEMORY *ZZ*INMEMORY *250101*0000*^*00501*000000001*0*T*:~' +
|
|
2
|
+
'GS*HB*INMEMORY*INMEMORY*20250101*0000*1*X*005010X279A1~' +
|
|
3
|
+
'ST*271*0001~SE*1*0001~GE*1*1~IEA*1*000000001~';
|
|
4
|
+
export const DEFAULT_SEED_PAYERS = [
|
|
5
|
+
{
|
|
6
|
+
aliases: ['vanguard', 'benefits', 'corp'],
|
|
7
|
+
coverageTypes: ['dental', 'medical'],
|
|
8
|
+
displayName: 'Vanguard Benefits Corp',
|
|
9
|
+
names: ['Vanguard Benefits', 'VANGUARD CARE'],
|
|
10
|
+
primaryPayerId: 'demo_63088',
|
|
11
|
+
stediId: '_GUAR',
|
|
12
|
+
transactionSupport: {
|
|
13
|
+
claimPayment: 'SUPPORTED',
|
|
14
|
+
claimStatus: 'SUPPORTED',
|
|
15
|
+
claimSubmission: 'SUPPORTED',
|
|
16
|
+
coordinationOfBenefits: 'SUPPORTED',
|
|
17
|
+
eligibilityCheck: 'SUPPORTED',
|
|
18
|
+
institutionalClaimSubmission: 'SUPPORTED',
|
|
19
|
+
professionalClaimSubmission: 'SUPPORTED',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
aliases: ['group', 'benefits', 'nimbus'],
|
|
24
|
+
coverageTypes: ['dental', 'medical'],
|
|
25
|
+
displayName: 'Nimbus Benefits Group',
|
|
26
|
+
names: ['Nimbus', 'NIMBUS BENEFITS'],
|
|
27
|
+
primaryPayerId: 'demo_62308',
|
|
28
|
+
stediId: '_CIGN',
|
|
29
|
+
transactionSupport: {
|
|
30
|
+
claimPayment: 'SUPPORTED',
|
|
31
|
+
claimStatus: 'SUPPORTED',
|
|
32
|
+
claimSubmission: 'SUPPORTED',
|
|
33
|
+
coordinationOfBenefits: 'SUPPORTED',
|
|
34
|
+
eligibilityCheck: 'SUPPORTED',
|
|
35
|
+
institutionalClaimSubmission: 'SUPPORTED',
|
|
36
|
+
professionalClaimSubmission: 'SUPPORTED',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
aliases: ['healthcoverage', 'meridian'],
|
|
41
|
+
coverageTypes: ['dental', 'medical'],
|
|
42
|
+
displayName: 'Meridian HealthCoverage',
|
|
43
|
+
names: ['Meridian Health', 'MHC Dental'],
|
|
44
|
+
primaryPayerId: 'demo_87726',
|
|
45
|
+
stediId: '_UHCD',
|
|
46
|
+
transactionSupport: {
|
|
47
|
+
claimPayment: 'SUPPORTED',
|
|
48
|
+
claimStatus: 'SUPPORTED',
|
|
49
|
+
claimSubmission: 'SUPPORTED',
|
|
50
|
+
coordinationOfBenefits: 'SUPPORTED',
|
|
51
|
+
eligibilityCheck: 'SUPPORTED',
|
|
52
|
+
institutionalClaimSubmission: 'SUPPORTED',
|
|
53
|
+
professionalClaimSubmission: 'SUPPORTED',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
export const buildMockEligibilityResponse = (input) => ({
|
|
58
|
+
benefitsInformation: [],
|
|
59
|
+
controlNumber: input.controlNumber,
|
|
60
|
+
eligibilitySearchId: `in-memory-eligibility-${input.controlNumber}`,
|
|
61
|
+
errors: [],
|
|
62
|
+
meta: {
|
|
63
|
+
applicationMode: 'inmemory',
|
|
64
|
+
outboundTraceId: `in-memory-${input.controlNumber}`,
|
|
65
|
+
senderId: 'in-memory',
|
|
66
|
+
submitterId: 'in-memory',
|
|
67
|
+
traceId: `in-memory-${input.controlNumber}`,
|
|
68
|
+
},
|
|
69
|
+
payer: {},
|
|
70
|
+
planDateInformation: {},
|
|
71
|
+
planInformation: {},
|
|
72
|
+
provider: {
|
|
73
|
+
entityIdentifier: '',
|
|
74
|
+
entityType: '',
|
|
75
|
+
npi: input.provider.npi,
|
|
76
|
+
providerName: input.provider.organizationName,
|
|
77
|
+
},
|
|
78
|
+
reassociationKey: `in-memory-${input.controlNumber}`,
|
|
79
|
+
subscriber: {},
|
|
80
|
+
tradingPartnerServiceId: input.tradingPartnerServiceId,
|
|
81
|
+
});
|
|
82
|
+
export const buildMockTransactionPage = () => ({
|
|
83
|
+
items: [],
|
|
84
|
+
});
|
|
85
|
+
export const searchMockPayers = (queryParameters) => {
|
|
86
|
+
const query = typeof queryParameters.query === 'string'
|
|
87
|
+
? queryParameters.query.toLowerCase()
|
|
88
|
+
: undefined;
|
|
89
|
+
const eligibilityCheck = typeof queryParameters.eligibilityCheck === 'string'
|
|
90
|
+
? queryParameters.eligibilityCheck
|
|
91
|
+
: undefined;
|
|
92
|
+
return DEFAULT_SEED_PAYERS.filter((payer) => {
|
|
93
|
+
if (query !== undefined) {
|
|
94
|
+
const haystack = [
|
|
95
|
+
payer.displayName,
|
|
96
|
+
payer.primaryPayerId,
|
|
97
|
+
payer.stediId,
|
|
98
|
+
...payer.names,
|
|
99
|
+
...payer.aliases,
|
|
100
|
+
]
|
|
101
|
+
.join(' ')
|
|
102
|
+
.toLowerCase();
|
|
103
|
+
if (!haystack.includes(query)) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (eligibilityCheck !== undefined &&
|
|
108
|
+
payer.transactionSupport.eligibilityCheck !== eligibilityCheck) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
return true;
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=mock-defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-defaults.js","sourceRoot":"","sources":["../src/mock-defaults.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type StediEligibilityInput,\n type StediEligibilityResponse,\n type StediPayerItem,\n type StediTransactionListResponse,\n} from './lib/types.js';\n\n/**\n * Placeholder EDI payload returned by the mock `downloadFile`.\n */\nexport const PLACEHOLDER_EDI =\n 'ISA*00* *00* *ZZ*INMEMORY *ZZ*INMEMORY *250101*0000*^*00501*000000001*0*T*:~' +\n 'GS*HB*INMEMORY*INMEMORY*20250101*0000*1*X*005010X279A1~' +\n 'ST*271*0001~SE*1*0001~GE*1*1~IEA*1*000000001~';\n\n/**\n * Generic, plausible payers served when Stedi is unreachable in test mode.\n */\nexport const DEFAULT_SEED_PAYERS: StediPayerItem[] = [\n {\n aliases: ['vanguard', 'benefits', 'corp'],\n coverageTypes: ['dental', 'medical'],\n displayName: 'Vanguard Benefits Corp',\n names: ['Vanguard Benefits', 'VANGUARD CARE'],\n primaryPayerId: 'demo_63088',\n stediId: '_GUAR',\n transactionSupport: {\n claimPayment: 'SUPPORTED',\n claimStatus: 'SUPPORTED',\n claimSubmission: 'SUPPORTED',\n coordinationOfBenefits: 'SUPPORTED',\n eligibilityCheck: 'SUPPORTED',\n institutionalClaimSubmission: 'SUPPORTED',\n professionalClaimSubmission: 'SUPPORTED',\n },\n },\n {\n aliases: ['group', 'benefits', 'nimbus'],\n coverageTypes: ['dental', 'medical'],\n displayName: 'Nimbus Benefits Group',\n names: ['Nimbus', 'NIMBUS BENEFITS'],\n primaryPayerId: 'demo_62308',\n stediId: '_CIGN',\n transactionSupport: {\n claimPayment: 'SUPPORTED',\n claimStatus: 'SUPPORTED',\n claimSubmission: 'SUPPORTED',\n coordinationOfBenefits: 'SUPPORTED',\n eligibilityCheck: 'SUPPORTED',\n institutionalClaimSubmission: 'SUPPORTED',\n professionalClaimSubmission: 'SUPPORTED',\n },\n },\n {\n aliases: ['healthcoverage', 'meridian'],\n coverageTypes: ['dental', 'medical'],\n displayName: 'Meridian HealthCoverage',\n names: ['Meridian Health', 'MHC Dental'],\n primaryPayerId: 'demo_87726',\n stediId: '_UHCD',\n transactionSupport: {\n claimPayment: 'SUPPORTED',\n claimStatus: 'SUPPORTED',\n claimSubmission: 'SUPPORTED',\n coordinationOfBenefits: 'SUPPORTED',\n eligibilityCheck: 'SUPPORTED',\n institutionalClaimSubmission: 'SUPPORTED',\n professionalClaimSubmission: 'SUPPORTED',\n },\n },\n];\n\n/**\n * Build a deterministic, schema-valid minimal eligibility response.\n *\n * @param input - The eligibility check parameters.\n * @returns A minimal {@link StediEligibilityResponse}.\n */\nexport const buildMockEligibilityResponse = (\n input: StediEligibilityInput,\n): StediEligibilityResponse => ({\n benefitsInformation: [],\n controlNumber: input.controlNumber,\n eligibilitySearchId: `in-memory-eligibility-${input.controlNumber}`,\n errors: [],\n meta: {\n applicationMode: 'inmemory',\n outboundTraceId: `in-memory-${input.controlNumber}`,\n senderId: 'in-memory',\n submitterId: 'in-memory',\n traceId: `in-memory-${input.controlNumber}`,\n },\n payer: {},\n planDateInformation: {},\n planInformation: {},\n provider: {\n entityIdentifier: '',\n entityType: '',\n npi: input.provider.npi,\n providerName: input.provider.organizationName,\n },\n reassociationKey: `in-memory-${input.controlNumber}`,\n subscriber: {},\n tradingPartnerServiceId: input.tradingPartnerServiceId,\n});\n\n/**\n * Empty transaction page served when Stedi is unreachable in test mode.\n *\n * @returns An empty {@link StediTransactionListResponse}.\n */\nexport const buildMockTransactionPage = (): StediTransactionListResponse => ({\n items: [],\n});\n\n/**\n * Match the in-memory payer search semantics against the seed payers.\n *\n * @param queryParameters - Search parameters.\n * @returns Matching seed payers.\n */\nexport const searchMockPayers = (\n queryParameters: Record<string, string[] | number | string>,\n): StediPayerItem[] => {\n const query =\n typeof queryParameters.query === 'string'\n ? queryParameters.query.toLowerCase()\n : undefined;\n const eligibilityCheck =\n typeof queryParameters.eligibilityCheck === 'string'\n ? queryParameters.eligibilityCheck\n : undefined;\n\n return DEFAULT_SEED_PAYERS.filter((payer) => {\n if (query !== undefined) {\n const haystack = [\n payer.displayName,\n payer.primaryPayerId,\n payer.stediId,\n ...payer.names,\n ...payer.aliases,\n ]\n .join(' ')\n .toLowerCase();\n\n if (!haystack.includes(query)) {\n return false;\n }\n }\n\n if (\n eligibilityCheck !== undefined &&\n payer.transactionSupport.eligibilityCheck !== eligibilityCheck\n ) {\n return false;\n }\n\n return true;\n });\n};\n"]}
|
package/dist/sdk.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { eligibility } from './endpoints/eligibility.js';
|
|
2
|
+
import { enrollment } from './endpoints/enrollment.js';
|
|
3
|
+
import { payers } from './endpoints/payers.js';
|
|
4
|
+
import { provider } from './endpoints/provider.js';
|
|
5
|
+
import { transactions } from './endpoints/transactions.js';
|
|
6
|
+
import { stediHttpClient } from './lib/client.js';
|
|
7
|
+
export const buildStediClient = (apiKey) => {
|
|
8
|
+
const coreBaseUrl = 'https://core.us.stedi.com/2023-08-01';
|
|
9
|
+
const healthcareBaseUrl = 'https://healthcare.us.stedi.com/2024-04-01';
|
|
10
|
+
const enrollmentsBaseUrl = 'https://enrollments.us.stedi.com/2024-09-01';
|
|
11
|
+
const httpClient = stediHttpClient(apiKey);
|
|
12
|
+
return {
|
|
13
|
+
downloadFile: httpClient.downloadFile,
|
|
14
|
+
eligibility: eligibility(httpClient, healthcareBaseUrl),
|
|
15
|
+
enrollment: enrollment(httpClient, enrollmentsBaseUrl),
|
|
16
|
+
payers: payers(httpClient, healthcareBaseUrl),
|
|
17
|
+
provider: provider(httpClient, enrollmentsBaseUrl),
|
|
18
|
+
transactions: transactions(httpClient, coreBaseUrl),
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=sdk.js.map
|
package/dist/sdk.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AASlD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAc,EAAE,EAAE;IACjD,MAAM,WAAW,GAAG,sCAAsC,CAAC;IAC3D,MAAM,iBAAiB,GAAG,4CAA4C,CAAC;IACvE,MAAM,kBAAkB,GAAG,6CAA6C,CAAC;IAEzE,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAC3C,OAAO;QACL,YAAY,EAAE,UAAU,CAAC,YAAY;QACrC,WAAW,EAAE,WAAW,CAAC,UAAU,EAAE,iBAAiB,CAAC;QACvD,UAAU,EAAE,UAAU,CAAC,UAAU,EAAE,kBAAkB,CAAC;QACtD,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,iBAAiB,CAAC;QAC7C,QAAQ,EAAE,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;QAClD,YAAY,EAAE,YAAY,CAAC,UAAU,EAAE,WAAW,CAAC;KACpD,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { eligibility } from './endpoints/eligibility.js';\nimport { enrollment } from './endpoints/enrollment.js';\nimport { payers } from './endpoints/payers.js';\nimport { provider } from './endpoints/provider.js';\nimport { transactions } from './endpoints/transactions.js';\nimport { stediHttpClient } from './lib/client.js';\n\n/**\n * Assemble a Stedi client from an API key, wiring every endpoint to the\n * underlying HTTP transport.\n *\n * @param apiKey - Stedi API key.\n * @returns A {@link StediClient}.\n */\nexport const buildStediClient = (apiKey: string) => {\n const coreBaseUrl = 'https://core.us.stedi.com/2023-08-01';\n const healthcareBaseUrl = 'https://healthcare.us.stedi.com/2024-04-01';\n const enrollmentsBaseUrl = 'https://enrollments.us.stedi.com/2024-09-01';\n\n const httpClient = stediHttpClient(apiKey);\n return {\n downloadFile: httpClient.downloadFile,\n eligibility: eligibility(httpClient, healthcareBaseUrl),\n enrollment: enrollment(httpClient, enrollmentsBaseUrl),\n payers: payers(httpClient, healthcareBaseUrl),\n provider: provider(httpClient, enrollmentsBaseUrl),\n transactions: transactions(httpClient, coreBaseUrl),\n };\n};\n\nexport type StediClient = ReturnType<typeof buildStediClient>;\n"]}
|
package/dist/store.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
export const createStore = () => ({
|
|
2
|
+
enrollments: new Map(),
|
|
3
|
+
providers: new Map(),
|
|
4
|
+
});
|
|
5
|
+
export const buildProviderRecord = (input, store) => {
|
|
6
|
+
const id = `in-memory-provider-${input.npi}`;
|
|
7
|
+
const existing = store.providers.get(id);
|
|
8
|
+
if (existing) {
|
|
9
|
+
return existing;
|
|
10
|
+
}
|
|
11
|
+
const timestamp = new Date().toISOString();
|
|
12
|
+
const created = {
|
|
13
|
+
contacts: input.contacts,
|
|
14
|
+
createdAt: timestamp,
|
|
15
|
+
id,
|
|
16
|
+
name: input.name,
|
|
17
|
+
npi: input.npi,
|
|
18
|
+
taxId: input.taxId,
|
|
19
|
+
taxIdType: input.taxIdType,
|
|
20
|
+
updatedAt: timestamp,
|
|
21
|
+
};
|
|
22
|
+
store.providers.set(id, created);
|
|
23
|
+
return created;
|
|
24
|
+
};
|
|
25
|
+
export const buildEnrollmentRecord = (input, store) => {
|
|
26
|
+
const id = `in-memory-enrollment-${input.provider.id}-${input.payer.idOrAlias}`;
|
|
27
|
+
const linkedProvider = store.providers.get(input.provider.id);
|
|
28
|
+
const existing = store.enrollments.get(id);
|
|
29
|
+
const timestamp = new Date().toISOString();
|
|
30
|
+
const created = {
|
|
31
|
+
createdAt: existing?.createdAt ?? timestamp,
|
|
32
|
+
id,
|
|
33
|
+
payer: {
|
|
34
|
+
stediPayerId: input.payer.idOrAlias,
|
|
35
|
+
submittedPayerIdOrAlias: input.payer.idOrAlias,
|
|
36
|
+
},
|
|
37
|
+
primaryContact: input.primaryContact,
|
|
38
|
+
provider: {
|
|
39
|
+
id: input.provider.id,
|
|
40
|
+
name: linkedProvider?.name,
|
|
41
|
+
npi: linkedProvider?.npi,
|
|
42
|
+
taxId: linkedProvider?.taxId,
|
|
43
|
+
taxIdType: linkedProvider?.taxIdType,
|
|
44
|
+
},
|
|
45
|
+
source: input.source,
|
|
46
|
+
status: input.status,
|
|
47
|
+
transactions: input.transactions,
|
|
48
|
+
updatedAt: timestamp,
|
|
49
|
+
userEmail: input.userEmail,
|
|
50
|
+
};
|
|
51
|
+
store.enrollments.set(id, created);
|
|
52
|
+
return created;
|
|
53
|
+
};
|
|
54
|
+
export const filterStoredEnrollments = (store, params = {}) => {
|
|
55
|
+
const { payerIds, providerTaxIds, status } = params;
|
|
56
|
+
return [...store.enrollments.values()].filter((enrollment) => {
|
|
57
|
+
if (providerTaxIds &&
|
|
58
|
+
(enrollment.provider.taxId === undefined ||
|
|
59
|
+
!providerTaxIds.includes(enrollment.provider.taxId))) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
if (payerIds && !payerIds.includes(enrollment.payer.stediPayerId)) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if (status && !status.includes(enrollment.status)) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
export const filterStoredProviders = (store, params = {}) => {
|
|
72
|
+
const { providerNpis, providerTaxIds } = params;
|
|
73
|
+
return [...store.providers.values()]
|
|
74
|
+
.filter((provider) => !providerNpis || providerNpis.includes(provider.npi))
|
|
75
|
+
.filter((provider) => !providerTaxIds || providerTaxIds.includes(provider.taxId))
|
|
76
|
+
.map((provider) => ({
|
|
77
|
+
id: provider.id,
|
|
78
|
+
name: provider.name,
|
|
79
|
+
npi: provider.npi,
|
|
80
|
+
taxId: provider.taxId,
|
|
81
|
+
taxIdType: provider.taxIdType,
|
|
82
|
+
}));
|
|
83
|
+
};
|
|
84
|
+
export const mergeListItems = (realItems, storedItems) => {
|
|
85
|
+
const byId = new Map();
|
|
86
|
+
for (const item of realItems) {
|
|
87
|
+
byId.set(item.id, item);
|
|
88
|
+
}
|
|
89
|
+
for (const item of storedItems) {
|
|
90
|
+
byId.set(item.id, item);
|
|
91
|
+
}
|
|
92
|
+
return [...byId.values()];
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type StediEnrollmentInput,\n type StediEnrollmentResponse,\n type StediListEnrollmentsParams,\n type StediListProvidersParams,\n type StediProviderInput,\n type StediProviderListItem,\n type StediProviderResponse,\n} from './lib/types.js';\n\n/**\n * In-memory storage for provider/enrollment writes in test mode.\n *\n * @property enrollments - Created enrollments, keyed by their deterministic id.\n * @property providers - Created providers, keyed by their deterministic id.\n */\nexport type InMemoryStediStore = {\n enrollments: Map<string, StediEnrollmentResponse>;\n providers: Map<string, StediProviderResponse>;\n};\n\n/**\n * Create an empty in-memory store.\n *\n * @returns A fresh {@link InMemoryStediStore}.\n */\nexport const createStore = (): InMemoryStediStore => ({\n enrollments: new Map(),\n providers: new Map(),\n});\n\n/**\n * Build or return an existing provider record in the store.\n *\n * @param input - Provider creation input.\n * @param store - The in-memory store.\n * @returns The created or existing provider response.\n */\nexport const buildProviderRecord = (\n input: StediProviderInput,\n store: InMemoryStediStore,\n): StediProviderResponse => {\n const id = `in-memory-provider-${input.npi}`;\n const existing = store.providers.get(id);\n\n if (existing) {\n return existing;\n }\n\n const timestamp = new Date().toISOString();\n const created: StediProviderResponse = {\n contacts: input.contacts,\n createdAt: timestamp,\n id,\n name: input.name,\n npi: input.npi,\n taxId: input.taxId,\n taxIdType: input.taxIdType,\n updatedAt: timestamp,\n };\n\n store.providers.set(id, created);\n\n return created;\n};\n\n/**\n * Build or update an enrollment record in the store.\n *\n * @param input - Enrollment creation input.\n * @param store - The in-memory store.\n * @returns The created enrollment response.\n */\nexport const buildEnrollmentRecord = (\n input: StediEnrollmentInput,\n store: InMemoryStediStore,\n): StediEnrollmentResponse => {\n const id = `in-memory-enrollment-${input.provider.id}-${input.payer.idOrAlias}`;\n const linkedProvider = store.providers.get(input.provider.id);\n const existing = store.enrollments.get(id);\n const timestamp = new Date().toISOString();\n\n const created: StediEnrollmentResponse = {\n createdAt: existing?.createdAt ?? timestamp,\n id,\n payer: {\n stediPayerId: input.payer.idOrAlias,\n submittedPayerIdOrAlias: input.payer.idOrAlias,\n },\n primaryContact: input.primaryContact,\n provider: {\n id: input.provider.id,\n name: linkedProvider?.name,\n npi: linkedProvider?.npi,\n taxId: linkedProvider?.taxId,\n taxIdType: linkedProvider?.taxIdType,\n },\n source: input.source,\n status: input.status,\n transactions: input.transactions,\n updatedAt: timestamp,\n userEmail: input.userEmail,\n };\n\n store.enrollments.set(id, created);\n\n return created;\n};\n\n/**\n * Filter enrollments from the store using list query parameters.\n *\n * @param store - The in-memory store.\n * @param params - Optional list filters.\n * @returns Matching enrollments.\n */\nexport const filterStoredEnrollments = (\n store: InMemoryStediStore,\n params: StediListEnrollmentsParams = {},\n): StediEnrollmentResponse[] => {\n const { payerIds, providerTaxIds, status } = params;\n\n return [...store.enrollments.values()].filter((enrollment) => {\n if (\n providerTaxIds &&\n (enrollment.provider.taxId === undefined ||\n !providerTaxIds.includes(enrollment.provider.taxId))\n ) {\n return false;\n }\n\n if (payerIds && !payerIds.includes(enrollment.payer.stediPayerId)) {\n return false;\n }\n\n if (status && !status.includes(enrollment.status)) {\n return false;\n }\n\n return true;\n });\n};\n\n/**\n * Filter providers from the store and map to list items.\n *\n * @param store - The in-memory store.\n * @param params - Optional list filters.\n * @returns Matching provider list items.\n */\nexport const filterStoredProviders = (\n store: InMemoryStediStore,\n params: StediListProvidersParams = {},\n): StediProviderListItem[] => {\n const { providerNpis, providerTaxIds } = params;\n\n return [...store.providers.values()]\n .filter((provider) => !providerNpis || providerNpis.includes(provider.npi))\n .filter(\n (provider) => !providerTaxIds || providerTaxIds.includes(provider.taxId),\n )\n .map((provider) => ({\n id: provider.id,\n name: provider.name,\n npi: provider.npi,\n taxId: provider.taxId,\n taxIdType: provider.taxIdType,\n }));\n};\n\n/**\n * Merge real and stored list items, with stored items winning on id conflict.\n *\n * @param realItems - Items returned from Stedi.\n * @param storedItems - Items from the in-memory store.\n * @returns De-duplicated merged items.\n */\nexport const mergeListItems = <T extends { id: string }>(\n realItems: T[],\n storedItems: T[],\n): T[] => {\n const byId = new Map<string, T>();\n\n for (const item of realItems) {\n byId.set(item.id, item);\n }\n\n for (const item of storedItems) {\n byId.set(item.id, item);\n }\n\n return [...byId.values()];\n};\n"]}
|