Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e2315a1
feat: add type pcare for diagnosa
hermandev Feb 14, 2026
25ece75
Merge branch 'ssecd:main' into main
hermandev Mar 24, 2026
29a268b
fix: add config for user and pass pcare
Mar 24, 2026
4cfc392
fix: update pcare instance
Mar 24, 2026
d89a565
feat: add pcare diagnosa
Mar 24, 2026
d9378d0
feat(test): add file test for pcare diagnosa
Mar 24, 2026
ad4f036
feat: add pcare get data dokter
Mar 24, 2026
30ab86b
feat(test): add testing for pcare get data dokter
Mar 24, 2026
aa60d8b
fix(docs): add comment docs
Mar 24, 2026
8a26305
feat: add pcare get data kesadaran
Mar 24, 2026
e46b5c3
feat(test): add test for pcare get data kesadaran
Mar 24, 2026
6143ae9
feat: add pcare get data poli FKTP
Mar 24, 2026
6db328e
feat(test): add test pcare get data poli FKTP
Mar 24, 2026
dc5dd2a
feat: move all pacare refensi to file referensi
Mar 24, 2026
539a20f
feat: add pcare referensi for get data alergi
Mar 24, 2026
376d42f
feat: add pcare for referensi data prognosa
Mar 24, 2026
740639e
feat: add pcare for get data peserta
Mar 24, 2026
cef0fbd
feat: add pcare for referensi status pulang
Mar 24, 2026
0cd6076
feat: add pcare referrensi for get data provider
Mar 24, 2026
dcfc8f6
feat: add pcare for data kunjungan
Mar 24, 2026
1278ea0
feat: add pcare referensi for data spesialis
Mar 24, 2026
65cf466
feat: add pcare referensi for data sub spesialis
Mar 24, 2026
f69a246
fix: move spesialis from referensi file
Mar 24, 2026
2236ea3
feat: add pcare spesialis for get data sarana
Mar 24, 2026
1b1a7ec
feat: add pcare spesialis for get data ref khusus
Mar 24, 2026
55fde4d
feat: add pcare spesialis for get data faskes rujukan sub spesialis
Mar 24, 2026
0846116
feat: add pcare kunjungan for insert, update and delete kunjungan
Mar 25, 2026
9012e36
fix: update file .env.example
Mar 26, 2026
75af071
fix(docs): update file README.md
Mar 26, 2026
ebae80e
fix: update and test partial request PCare api
Mar 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ JKN_VCLAIM_USER_KEY=
JKN_ANTREAN_USER_KEY=
JKN_APOTEK_USER_KEY=
JKN_PCARE_USER_KEY=
JKN_PCARE_USER_PASS=
JKN_ICARE_USER_KEY=
JKN_REKAM_MEDIS_USER_KEY=
JKN_APLICARES_USER_KEY=
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,13 @@ interface Config {
* @default process.env.JKN_PCARE_USER_KEY
*/
pcareUserKey: string;

/**
* Username dan Password PCare dari BPJS
*
* @default process.env.JKN_PCARE_USER_PASS
*/
pcareUserPass: string;

/**
* User key i-Care dari BPJS
Expand Down
22 changes: 18 additions & 4 deletions src/fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ export interface Config {
*/
pcareUserKey: string;

/**
* User dan Password PCare dari BPJS
* contoh: username:password
*
* @default process.env.JKN_PCARE_USER_PASS
*/
pcareUserPass: string;

/**
* User key i-Care dari BPJS
*
Expand Down Expand Up @@ -229,6 +237,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 ?? '',
pcareUserPass: process.env.JKN_PCARE_USER_PASS ?? '',
icareUserKey: process.env.JKN_ICARE_USER_KEY,
rekamMedisUserKey: process.env.JKN_REKAM_MEDIS_USER_KEY,
throw: false,
Expand Down Expand Up @@ -287,15 +296,17 @@ export class Fetcher {
const userKey = this.userKeyMap[type];
if (!userKey) throw new Error(`failed to get user key of type "${type}"`);

const { consId, consSecret } = this.config;
const { consId, consSecret, pcareUserPass } = this.config;
const timestamp = Math.round(Date.now() / 1000);
const message = `${consId}&${timestamp}`;
const signature = createHmac('SHA256', consSecret).update(message).digest('base64');
const pcareAuth = `Basic ${Buffer.from(`${pcareUserPass}:095`).toString('base64')}`;
return {
'X-cons-id': consId,
'X-timestamp': String(timestamp),
'X-signature': encodeURI(signature),
user_key: userKey
user_key: userKey,
'X-Authorization': pcareAuth
};
}

Expand Down Expand Up @@ -328,7 +339,10 @@ export class Fetcher {
try {
const url = new URL(baseUrl[this.config.mode] + path);
const init: RequestInit = { method: option.method ?? 'GET' };
const headers = { ...this.getDefaultHeaders(type), ...(option.headers ?? {}) };
const headers = {
...this.getDefaultHeaders(type),
...(option.headers ?? {})
};

init.headers = headers;
if (option.data) {
Expand Down Expand Up @@ -417,7 +431,7 @@ function parseHtml(html?: string) {

/** @internal */
export function normalizePath(path: SendOption['path']) {
const [pathname, params] = typeof path == 'string' ? [path] : path;
const [pathname, params] = typeof path === 'string' ? [path] : path;

if (!pathname.startsWith('/')) throw new Error(`Path must start with "/"`);
if (!params) return pathname;
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default class JKN extends Fetcher {
}

get pcare(): PCare {
return this.cache.get('pcare', PCare);
return PCare.getInstance(this.cache);
}

get antreanFktp(): AntreanFKTP {
Expand Down
40 changes: 39 additions & 1 deletion src/pcare/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,50 @@
import { CachedApi } from '../base.js';
import { SendOption } from '../fetcher.js';
import { PCareBaseApi } from './base.js';
import { Kunjungan } from './kunjungan.js';
import { Peserta } from './peserta.js';
import { Referensi } from './referensi.js';
import { Spesialis } from './spesialis.js';

type RequestOption = SendOption;

export class PCare {
private static instance: PCare | undefined;

private constructor(private readonly cache: CachedApi) {}

static getInstance(cache: CachedApi): PCare {
if (!this.instance) {
this.instance = new PCare(cache);
}
return this.instance;
}

get referensi() {
return this.cache.get('pcare_referensi', Referensi);
}

get peserta() {
return this.cache.get('pcare_peserta', Peserta);
}

get kunjungan() {
return this.cache.get('pcare_kunjungan', Kunjungan);
}

get spesialis() {
return this.cache.get('pcare_spesialis', Spesialis);
}

get api() {
return this.cache.get('pcare_partial', PartialRequest);
}
}

/**
* Implement base api directly since this is for partial support
*/
export class PCare extends PCareBaseApi {
class PartialRequest extends PCareBaseApi {
async request<T>(option: RequestOption) {
return this.send<T>(option);
}
Expand Down
Loading