From 5e48a470dd87cc97fc0756ab7d152499d67096bd Mon Sep 17 00:00:00 2001 From: Mustofa Date: Sat, 26 Aug 2023 06:44:04 +0700 Subject: [PATCH] feat: i-Care implementation (#41) * init * update doc * define individual icare user key * add note about icare user key * explicitly set content-type * fix i care response type * clarify test * fix type * clarify icare user key doc * add changeset --- .changeset/fifty-lemons-vanish.md | 5 +++++ .env.example | 3 ++- README.md | 16 ++++++++++++--- src/fetcher.ts | 31 ++++++++++++++++++++++------ src/icare.ts | 34 +++++++++++++++++++++++++++++++ src/index.ts | 5 +++++ test/icare.test.ts | 26 +++++++++++++++++++++++ words.txt | 1 + 8 files changed, 111 insertions(+), 10 deletions(-) create mode 100644 .changeset/fifty-lemons-vanish.md create mode 100644 src/icare.ts create mode 100644 test/icare.test.ts diff --git a/.changeset/fifty-lemons-vanish.md b/.changeset/fifty-lemons-vanish.md new file mode 100644 index 0000000..799e7e6 --- /dev/null +++ b/.changeset/fifty-lemons-vanish.md @@ -0,0 +1,5 @@ +--- +'@ssecd/jkn': minor +--- + +implement i-care service diff --git a/.env.example b/.env.example index 02148c5..43fa3ed 100644 --- a/.env.example +++ b/.env.example @@ -3,4 +3,5 @@ JKN_CONS_SECRET= JKN_VCLAIM_USER_KEY= JKN_ANTREAN_USER_KEY= JKN_APOTEK_USER_KEY= -JKN_PCARE_USER_KEY= \ No newline at end of file +JKN_PCARE_USER_KEY= +JKN_ICARE_USER_KEY= diff --git a/README.md b/README.md index f907f7a..d7aacd2 100644 --- a/README.md +++ b/README.md @@ -167,6 +167,16 @@ interface Config { */ pcareUserKey: string; + /** + * User key i-Care dari BPJS + * + * Umumnya user key i-Care ini nilai sama dengan user key VClaim + * untuk FKRTL dan PCare untuk FKTP + * + * @default process.env.JKN_ICARE_USER_KEY + */ + icareUserKey: string; + /** * Berupa mode "development" dan "production". Secara default akan * membaca nilai environment variable NODE_ENV atau "development" @@ -196,10 +206,11 @@ interface Config { - ✅ Antrean - ✅ Apotek _(experimental)_ - 🧩 PCare _([partial](https://github.com/ssecd/jkn/pull/26))_ +- ✅ i-Care ## Kontribusi -Kontribusi sangat dipersilakan dan dapat dilakukan dengan berbagai cara seperti melaporkan masalah, membuat permintaan atau menambahkan fitur melalui PR, atau sekedar memperbaiki kesalahan ketikan. +Kontribusi sangat dipersilakan dan dapat dilakukan dengan berbagai cara seperti melaporkan masalah, membuat permintaan atau menambahkan fitur melalui PR, atau sekedar memperbaiki kesalahan ketikan. ## Lisensi @@ -209,5 +220,4 @@ Kontribusi sangat dipersilakan dan dapat dilakukan dengan berbagai cara seperti - [Consent](https://github.com/ssecd/jkn/issues/6) - [Pemecahan Masalah](https://github.com/ssecd/jkn/issues?q=is%3Aissue) -- [Laporkan Bug](https://github.com/ssecd/jkn/issues) - +- [Laporkan Bug](https://github.com/ssecd/jkn/issues/new) diff --git a/src/fetcher.ts b/src/fetcher.ts index a8985d3..acb1a22 100644 --- a/src/fetcher.ts +++ b/src/fetcher.ts @@ -5,7 +5,7 @@ type MaybePromise = T | Promise; export type Mode = 'development' | 'production'; -export type Type = 'vclaim' | 'antrean' | 'apotek' | 'pcare'; +export type Type = 'vclaim' | 'antrean' | 'apotek' | 'pcare' | 'icare'; export interface Config { /** @@ -50,6 +50,16 @@ export interface Config { */ pcareUserKey: string; + /** + * User key i-Care dari BPJS + * + * Umumnya user key i-Care ini nilai sama dengan user key VClaim + * untuk FKRTL dan PCare untuk FKTP + * + * @default process.env.JKN_ICARE_USER_KEY + */ + icareUserKey: string; + /** * Berupa mode "development" dan "production". Secara default akan * membaca nilai environment variable NODE_ENV atau "development" @@ -98,10 +108,10 @@ export interface LowerResponse { }; } -export interface CamelResponse { +export interface CamelResponse { response: T; metaData: { - code: string; + code: C; message: string; }; } @@ -111,6 +121,7 @@ export type SendResponse = { vclaim: CamelResponse; apotek: CamelResponse; pcare: CamelResponse; + icare: CamelResponse; }; const api_base_urls: Record> = { @@ -129,6 +140,10 @@ const api_base_urls: Record> = { pcare: { development: 'https://apijkn-dev.bpjs-kesehatan.go.id/pcare-rest-dev', production: 'https://apijkn.bpjs-kesehatan.go.id/pcare-rest' + }, + icare: { + development: 'https://apijkn-dev.bpjs-kesehatan.go.id/ihs_dev', + production: 'https://apijkn.bpjs-kesehatan.go.id/ihs' } }; @@ -143,6 +158,7 @@ export class Fetcher { antreanUserKey: process.env.JKN_ANTREAN_USER_KEY ?? '', apotekUserKey: process.env.JKN_APOTEK_USER_KEY ?? '', pcareUserKey: process.env.JKN_PCARE_USER_KEY ?? '', + icareUserKey: process.env.JKN_ICARE_USER_KEY ?? '', throw: false }; @@ -176,7 +192,8 @@ export class Fetcher { vclaim: this.config.vclaimUserKey, antrean: this.config.antreanUserKey, apotek: this.config.apotekUserKey, - pcare: this.config.pcareUserKey + pcare: this.config.pcareUserKey, + icare: this.config.icareUserKey }; } @@ -264,13 +281,15 @@ export class Fetcher { : 'An error occurred while requesting information from the JKN API'; if (error instanceof Error) message += `. ` + error.message; message += '. ' + response; - const code = '500'; console.error(error); + + // TODO: find better way to infer generic response type + const code = type === 'icare' ? 500 : '500'; return { metadata: { code: +code, message }, metaData: { code, message }, response: undefined - }; + } as unknown as SendResponse[T]; } } diff --git a/src/icare.ts b/src/icare.ts new file mode 100644 index 0000000..205c1fb --- /dev/null +++ b/src/icare.ts @@ -0,0 +1,34 @@ +import { BaseApi } from './base.js'; + +export class ICare extends BaseApi<'icare'> { + protected type = 'icare' as const; + + async fkrtl(data: { + /** Nomor kartu peserta */ + param: string; + + /** Kode dokter */ + kodedokter: number; + }) { + return this.send<{ url: string }>({ + path: `/api/rs/validate`, + method: 'POST', + skipContentTypeHack: true, + headers: { 'Content-Type': 'Application/json' }, + data + }); + } + + async fktp(data: { + /** Nomor kartu peserta */ + param: string; + }) { + return this.send<{ url: string }>({ + path: `/api/pcare/validate`, + method: 'POST', + skipContentTypeHack: true, + headers: { 'Content-Type': 'Application/json' }, + data + }); + } +} diff --git a/src/index.ts b/src/index.ts index 5971fed..5a80ec4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ import { Antrean } from './antrean.js'; import { Apotek } from './apotek/index.js'; import { CachedApi } from './base.js'; import { Fetcher } from './fetcher.js'; +import { ICare } from './icare.js'; import { PCare } from './pcare/index.js'; import { VClaim } from './vclaim/index.js'; @@ -32,6 +33,10 @@ export default class JKN extends Fetcher { get pcare(): PCare { return this.cache.get('pcare', PCare); } + + get icare(): ICare { + return this.cache.get('icare', ICare); + } } export type AntreanResponse = JKNResponseType; diff --git a/test/icare.test.ts b/test/icare.test.ts new file mode 100644 index 0000000..c65347c --- /dev/null +++ b/test/icare.test.ts @@ -0,0 +1,26 @@ +import { describe, expect, it } from 'vitest'; +import jkn from './jkn'; + +describe( + 'ICare', + () => { + it.concurrent('fkrtl()', async () => { + const result = await jkn.icare.fkrtl({ + param: '0002084717968', + kodedokter: 292667 + }); + expect(result.metaData.code).toBe(200); + expect(result.response?.url).not.toBeFalsy(); + expect(result.response?.url).contains('?token='); + }); + + it.concurrent('fktp()', async () => { + const result = await jkn.icare.fktp({ + param: '0002084717968' + }); + expect(result.metaData.code).toBe(200); + expect(result.response?.url).not.toBeFalsy(); + }); + }, + { timeout: 25_000 } +); diff --git a/words.txt b/words.txt index f04b2f6..6fe3cdf 100644 --- a/words.txt +++ b/words.txt @@ -41,6 +41,7 @@ hapusresep HEMODIALISA HFIS Histori +icare ICCU IDUSERSJP Inacbg