Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions .changeset/sunny-tools-tell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ssecd/jkn': patch
---

Improve path handling
2 changes: 1 addition & 1 deletion src/antrean-fktp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export class AntreanFKTP extends BaseApi<'pcare'> {
}[];
}>({
name: this.name + 'Referensi Dokter',
path: `/ref/dokter/kodepoli/${encodeURIComponent(params.kodePoli)}/tanggal/${params.tanggal}`,
path: ['/ref/dokter/kodepoli/:kodePoli/tanggal/:tanggal', params],
method: 'GET'
});
}
Expand Down
11 changes: 7 additions & 4 deletions src/antrean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export class Antrean extends BaseApi<'antrean'> {
}[]
>({
name: 'Referensi Jadwal Dokter',
path: `/jadwaldokter/kodepoli/${encodeURIComponent(params.poli)}/tanggal/${params.tanggal}`,
path: ['/jadwaldokter/kodepoli/:poli/tanggal/:tanggal', params],
method: 'GET'
});
}
Expand Down Expand Up @@ -103,7 +103,7 @@ export class Antrean extends BaseApi<'antrean'> {
daftarfp: number;
}>({
name: 'Referensi Pasien Fingerprint',
path: `/ref/pasien/fp/identitas/${encodeURIComponent(params.jenis)}/noidentitas/${params.nomor}`,
path: ['/ref/pasien/fp/identitas/:jenis/noidentitas/:nomor', params],
method: 'GET'
});
}
Expand Down Expand Up @@ -453,7 +453,7 @@ export class Antrean extends BaseApi<'antrean'> {
async perKodeBooking(kodeBooking: string) {
return this.send<AntreanDetail[]>({
name: 'Antrean Per-KodeBooking',
path: `/antrean/pendaftaran/kodebooking/${encodeURIComponent(kodeBooking)}`,
path: ['/antrean/pendaftaran/kodebooking/:kodeBooking', { kodeBooking }],
method: 'GET'
});
}
Expand Down Expand Up @@ -487,7 +487,10 @@ export class Antrean extends BaseApi<'antrean'> {
}) {
return this.send<AntreanDetail[]>({
name: 'Antrean Belum Dilayani Per-(Poli, Dokter, Hari, dan Jam Praktik)',
path: `/antrean/pendaftaran/kodepoli/${encodeURIComponent(params.poli)}/kodedokter/${encodeURIComponent(params.dokter)}/hari/${params.hari}/jampraktek/${params.jam}`,
path: [
'/antrean/pendaftaran/kodepoli/:poli/kodedokter/:dokter/hari/:hari/jampraktek/:jam',
params
],
method: 'GET'
});
}
Expand Down
51 changes: 34 additions & 17 deletions src/aplicares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,14 @@ export class Aplicares extends BaseApi<'aplicares'> {
* tempat tidur untuk pasien laki-laki, perempuan, dan laki–laki atau
* perempuan.
*/
async update(data: AplicaresBedData) {
const { ppkCode } = await this.requiredConfig('ppkCode');
async update(data: AplicaresBedData, kodePpk?: string) {
if (!kodePpk) {
const config = await this.requiredConfig('ppkCode');
kodePpk = config.ppkCode;
}
return this.send({
name: 'Update Ketersediaan Tempat Tidur',
path: `/rest/bed/update/${encodeURIComponent(ppkCode)}`,
path: ['/rest/bed/update/:kodePpk', { kodePpk }],
method: 'POST',
skipContentTypeHack: true,
headers: { 'Content-Type': 'application/json' },
Expand All @@ -51,11 +54,14 @@ export class Aplicares extends BaseApi<'aplicares'> {
* tempat tidur untuk pasien laki-laki, perempuan, dan laki–laki atau
* perempuan.
*/
async create(data: AplicaresBedData) {
const { ppkCode } = await this.requiredConfig('ppkCode');
async create(data: AplicaresBedData, kodePpk?: string) {
if (!kodePpk) {
const config = await this.requiredConfig('ppkCode');
kodePpk = config.ppkCode;
}
return this.send<undefined>({
name: 'Ruangan Baru',
path: `/rest/bed/create/${encodeURIComponent(ppkCode)}`,
path: ['/rest/bed/create/:kodePpk', { kodePpk }],
method: 'POST',
skipContentTypeHack: true,
headers: { 'Content-Type': 'application/json' },
Expand All @@ -76,8 +82,13 @@ export class Aplicares extends BaseApi<'aplicares'> {

/** paging limit */
limit: number;

kodePpk?: string;
}) {
const { ppkCode } = await this.requiredConfig('ppkCode');
if (!params.kodePpk) {
const config = await this.requiredConfig('ppkCode');
params.kodePpk = config.ppkCode;
}
return this.send<
{
list: (AplicaresBedData & {
Expand All @@ -89,7 +100,7 @@ export class Aplicares extends BaseApi<'aplicares'> {
{ totalitems: number }
>({
name: 'Ketersediaan Kamar Faskes',
path: `/rest/bed/read/${encodeURIComponent(ppkCode)}/${params.start}/${params.limit}`,
path: ['/rest/bed/read/:kodePpk/:start/:limit', params],
method: 'GET',
skipDecrypt: true
});
Expand All @@ -98,17 +109,23 @@ export class Aplicares extends BaseApi<'aplicares'> {
/**
* Hapus Ruangan
*/
async delete(data: {
/** kode kelas ruang rawat sesuai dengan mapping BPJS Kesehatan */
kodekelas: string;

/** kode ruangan faskes */
koderuang: string;
}) {
const { ppkCode } = await this.requiredConfig('ppkCode');
async delete(
data: {
/** kode kelas ruang rawat sesuai dengan mapping BPJS Kesehatan */
kodekelas: string;

/** kode ruangan faskes */
koderuang: string;
},
kodePpk?: string
) {
if (!kodePpk) {
const config = await this.requiredConfig('ppkCode');
kodePpk = config.ppkCode;
}
return this.send<undefined>({
name: 'Hapus Ruangan',
path: `/rest/bed/delete/${encodeURIComponent(ppkCode)}`,
path: ['/rest/bed/delete/:kodePpk', { kodePpk }],
method: 'POST',
skipContentTypeHack: true,
headers: { 'Content-Type': 'application/json' },
Expand Down
4 changes: 2 additions & 2 deletions src/apotek/pelayanan-obat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class PelayananObat extends ApotekBaseApi {
};
}>({
name: this.name + 'List/Daftar',
path: `/pelayanan/obat/daftar/${encodeURIComponent(params.nomorSep)}`,
path: ['/pelayanan/obat/daftar/:nomorSep', params],
method: 'GET'
});
}
Expand Down Expand Up @@ -88,7 +88,7 @@ export class PelayananObat extends ApotekBaseApi {
};
}>({
name: this.name + 'Riwayat',
path: `/riwayatobat/${params.awal}/${params.akhir}/${encodeURIComponent(params.nomorKartu)}`,
path: ['/riwayatobat/:awal/:akhir/:nomorKartu', params],
method: 'GET'
});
}
Expand Down
11 changes: 5 additions & 6 deletions src/apotek/referensi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class Referensi extends ApotekBaseApi {
}[];
}>({
name: this.name + 'Poli',
path: `/referensi/poli/${encodeURIComponent(params.keyword)}`,
path: ['/referensi/poli/:keyword', params],
method: 'GET'
});
}
Expand All @@ -66,7 +66,7 @@ export class Referensi extends ApotekBaseApi {
}[];
}>({
name: this.name + 'Fasilitas Kesehatan',
path: `/referensi/ppk/${params.jenis}/${encodeURIComponent(params.nama)}`,
path: ['/referensi/ppk/:jenis/:nama', params],
method: 'GET'
});
}
Expand Down Expand Up @@ -94,7 +94,7 @@ export class Referensi extends ApotekBaseApi {
checkstock: 'True' | 'False';
}>({
name: this.name + 'Setting',
path: `/referensi/settingppk/read/${encodeURIComponent(params.kodeApotek)}`,
path: ['/referensi/settingppk/read/:kodeApotek', params],
method: 'GET'
});
}
Expand All @@ -118,7 +118,7 @@ export class Referensi extends ApotekBaseApi {
/**
* Pencarian data obat
*/
async obat(param: {
async obat(params: {
/** kode jenis obat */
jenis: string;

Expand All @@ -128,7 +128,6 @@ export class Referensi extends ApotekBaseApi {
/** filter nama obat */
filter?: string;
}) {
const filter = encodeURIComponent(param.filter ?? '');
return this.send<{
list: {
kode: string;
Expand All @@ -137,7 +136,7 @@ export class Referensi extends ApotekBaseApi {
}[];
}>({
name: this.name + 'Cari Obat',
path: `/referensi/obat/${encodeURIComponent(param.jenis)}/${param.tanggal}/${filter}`,
path: ['/referensi/obat/:jenis/:tanggal/:filter?', params],
method: 'GET'
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/apotek/sep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class SEP extends ApotekBaseApi {
namadokter: string | null;
}>({
name: this.name + 'Cari No. Kunjungan/SEP',
path: `/sep/${encodeURIComponent(params.nomorSep)}`,
path: ['/sep/:nomorSep', params],
method: 'GET'
});
}
Expand Down
36 changes: 30 additions & 6 deletions src/fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export interface Config {
export interface SendOption {
/** name of request, it helpful for log or collect stats */
name?: string;
path: `/${string}`;
path: `/${string}` | [`/${string}`, Record<string, string | number | undefined | null>];
method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
data?: unknown;
skipDecrypt?: boolean;
Expand Down Expand Up @@ -319,14 +319,14 @@ export class Fetcher {
option: SendOption
): Promise<SendResponse<R | undefined, M | undefined>[T]> {
await this.applyConfig();
if (!option.path.startsWith('/')) throw new Error(`Path must be starts with "/"`);

const path = normalizePath(option.path);
const baseUrl = this.config.baseUrls[type];
if (!baseUrl) throw new Error(`Invalid base URL for type "${type}"`);

let result = '';
try {
const baseUrl = this.config.baseUrls[type];
if (!baseUrl) throw new Error(`base url of type "${type}" is invalid`);

const url = new URL(baseUrl[this.config.mode] + option.path);
const url = new URL(baseUrl[this.config.mode] + path);
const init: RequestInit = { method: option.method ?? 'GET' };
const headers = { ...this.getDefaultHeaders(type), ...(option.headers ?? {}) };

Expand Down Expand Up @@ -414,3 +414,27 @@ function parseHtml(html?: string) {
.replace(/\r?\n+/g, ' - ') // newlines to dash
.replace(/\s+/g, ' '); // normalize whitespace
}

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

if (!pathname.startsWith('/')) throw new Error(`Path must start with "/"`);
if (!params) return pathname;

return pathname.replace(/\/:([A-Za-z0-9_]+)(\?)?/g, (_, key: string, optional?: string) => {
const value = params[key];

if (value == null) {
if (optional) return ''; // remove entire `/:param?`
throw new Error(`Missing params: ${key}`);
}

const component = String(value);
try {
return '/' + encodeURIComponent(decodeURIComponent(component));
} catch {
return '/' + encodeURIComponent(component);
}
});
}
5 changes: 4 additions & 1 deletion src/vclaim/monitoring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ export class Monitoring extends VClaimBaseApi {
}[];
}>({
name: this.name + 'Data Histori Pelayanan Peserta',
path: `/monitoring/HistoriPelayanan/NoKartu/${encodeURIComponent(params.nomorKartu)}/tglMulai/${params.awal}/tglAkhir/${params.akhir}`,
path: [
'/monitoring/HistoriPelayanan/NoKartu/:nomorKartu/tglMulai/:awal/tglAkhir/:akhir',
params
],
method: 'GET'
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/vclaim/peserta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class Peserta extends VClaimBaseApi {
}) {
return this.send<{ peserta: DataPeserta }>({
name: this.name + 'No. Kartu BPJS',
path: `/Peserta/nokartu/${encodeURIComponent(params.nomor)}/tglSEP/${params.tanggal}`,
path: ['/Peserta/nokartu/:nomor/tglSEP/:tanggal', params],
method: 'GET'
});
}
Expand All @@ -30,7 +30,7 @@ export class Peserta extends VClaimBaseApi {
}) {
return this.send<{ peserta: DataPeserta }>({
name: this.name + 'NIK',
path: `/Peserta/nik/${encodeURIComponent(params.nomor)}/tglSEP/${params.tanggal}`,
path: ['/Peserta/nik/:nomor/tglSEP/:tanggal', params],
method: 'GET'
});
}
Expand Down
6 changes: 3 additions & 3 deletions src/vclaim/prb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ export class PRB extends VClaimBaseApi {
};
}>({
name: this.name + 'Cari by Nomor SRB',
path: `/prb/${encodeURIComponent(params.nomorSrb)}/nosep/${encodeURIComponent(params.nomorSep)}`,
path: ['/prb/:nomorSrb/nosep/:nomorSep', params],
method: 'GET'
});
}
Expand Down Expand Up @@ -229,7 +229,7 @@ export class PRB extends VClaimBaseApi {
};
}>({
name: this.name + 'Cari by Tanggal SRB',
path: `/prb/tglMulai/${params.awal}/tglAkhir/${params.akhir}`,
path: ['/prb/tglMulai/:awal/tglAkhir/:akhir', params],
method: 'GET'
});
}
Expand All @@ -251,7 +251,7 @@ export class PRB extends VClaimBaseApi {
}[];
}>({
name: this.name + 'Rekap Potensi PRB',
path: `/prbpotensi/tahun/${params.tahun}/bulan/${params.bulan}`,
path: [`/prbpotensi/tahun/:tahun/bulan/:bulan`, params],
method: 'GET'
});
}
Expand Down
Loading