เริ่มต้นอย่างรวดเร็ว
HTTP client ที่ปลอดภัยตามประเภทที่ใช้ RxJS สำหรับ TypeScript + (เลือก) Next.js/RSocket adapter.
คุณสมบัติหลัก
- ฉีดประเภท Paths แบบ OpenAPI-style ที่ได้จาก Swagger/OpenAPI / AsyncAPI สคีม่า / สัญญาที่กำหนดเอง เพื่อให้มั่นใจในความเสถียรของประเภทการร้องขอ (route)
- API ทุกตัวจะส่งคืน RxJS Observable
- core เป็นอิสระจากเฟรมเวิร์ก (ไม่ขึ้นอยู่กับ Next.js)
- ฟังก์ชันเฉพาะสำหรับ Next.js แยกออกเป็น @byeolnaerim/typed-rx-http/next เอนทรีพอยต์ → ต้องการ Next.js เฉพาะเมื่อ import /next.
- ฟังก์ชันเฉพาะสำหรับ RSocket แยกออกเป็น @byeolnaerim/typed-rx-http/rsocket เอนทรีพอยต์ → ต้องการแพ็คเกจ RSocket เฉพาะเมื่อ import /rsocket.
ติดตั้ง
npm
เอนทรีพอยต์
Core (ไม่ขึ้นกับ framework)
Next.js adapter (เลือก)
ในโครงการที่ไม่ใช้ Next.js อย่านำเข้า /next.
RSocket adapter (เลือก)
ติดตั้ง peer package เฉพาะในโครงการที่ใช้ RSocket.
ในโครงการที่ไม่ใช้ RSocket อย่านำเข้า /rsocket.
วิธีการใช้ Core
1) เตรียมประเภท Paths (ปกติคือ OpenAPI paths)
Paths ของ createHttpClient<Paths>() แสดงถึงประเภท "สเปคคำขอ (route)" ในเอกสารจะเรียกว่า paths ตามธรรมเนียม แต่ไม่จำเป็นต้องเป็น OpenAPI/Swagger หรือชื่อว่า paths.
อย่างไรก็ตาม core ใช้ข้อจำกัด OpenApiPathsLike ภายใน ดังนั้น Paths จะต้องมีลักษณะคล้ายกับ OpenAPI paths ตามด้านล่าง.
- คีย์ระดับสูงสุด: สตริงเส้นทาง URL (เช่น "/users/{id}")
- คีย์ระดับล่าง: วิธีการ HTTP (get/post/put/delete/patch …)
- ภายในแต่ละวิธีจะมีฟิลด์ parameters.query/path/header/cookie, requestBody, responses (หรือ never)
core จะอ้างอิงฟิลด์ด้านบนเพื่อสร้างประเภท ServiceArguments.
- url: keyof Paths
- method: keyof Paths[url]
- queryString: parameters.query
- pathVariable: parameters.path
- body: requestBody
ตัวอย่าง: ผลลัพธ์ของ openapi-typescript มักมีรูปแบบดังต่อไปนี้ (บางส่วนย่อ)
2) สร้าง HeaderStore
HeaderStore เป็น in-memory store ที่ง่ายสำหรับการจัดการ header พื้นฐานใน CSR
3) สร้าง HTTP client
- headerStore เป็นตัวเลือก แต่แนะนำให้ใส่หากต้องการใช้ header/การรับรองเซสชันพื้นฐานใน CSR
- headersProvider ใช้เมื่อจำเป็นต้องคำนวณ header สำหรับแต่ละคำขอ เช่น SSR/มัลติเทนแนนท์
4) เรียก API (ประเภทปลอดภัย)
ประเภทคำขอ (url/method/pathVariable/queryString/body) จะถูกกำหนดจากประเภทที่ผู้ใช้ฉีดเข้าไปใน createHttpClient<Paths>() (ตามธรรมเนียมคือ OpenAPI paths) ประเภทการตอบกลับจะถูกเลือกโดยผู้เรียกใน callApi<R>() โดยใช้ R ที่เป็นเจนเนอริก (คอร์จะไม่อนุมานจาก responses โดยอัตโนมัติ)
การห่อหุ้มการตอบกลับ (ResponseWrapper) — ตัวเลือก
ไลบรารีนี้ไม่บังคับให้มีการห่อหุ้มการตอบกลับ สามารถเลือกประเภทการตอบกลับแบบเจนเนอริกตาม API ได้
การตอบกลับที่ห่อหุ้ม
การตอบกลับที่ไม่มีการห่อหุ้ม
การสตรีม (NDJSON)
เมื่อเซิร์ฟเวอร์ส่ง NDJSON (JSON หนึ่งตัวต่อหนึ่งบรรทัด) ให้ใช้ callApiStream หากไม่มี Accept header จะตั้งค่าเป็น application/x-ndjson โดยค่าเริ่มต้น
CSR แคช (แคชของไคลเอนต์)
ฟังก์ชันที่ให้โดย createCsrCache<CacheName>():
callApiCsrCache(callApiFn, serviceArgs, cacheOptions)- removeCsrCache(cacheName) — รองรับชื่อแคชประเภท + สตริงทั้งหมด
ปลั๊กอินการรับรองเซสชัน (ตัวเลือก)
createSessionAuth แยกตรรกะการรับรองเซสชันออกจากคอร์และสามารถเพิ่มหรือลบได้ตามต้องการ
การทำงาน:
- เก็บ Authorization ไว้ใน headerStore
- ซิงโครไนซ์โทเค็นด้วย ensureToken$() (/api/auth/token)
- เมื่อเกิด 401 ให้ลองรีเฟรช 1 ครั้ง (/api/auth/token/refresh) แล้วลองคำขอเดิมอีกครั้ง
- เมื่อรีเฟรชล้มเหลวให้ logout (/api/auth/logout) และส่งต่อข้อผิดพลาด
- การเปลี่ยนแปลงสถานะการเข้าสู่ระบบจะถูกจัดการจากภายนอกด้วย callback onLoginChange
หากต้องการเพียงซิงโครไนซ์โทเค็นโดยไม่ต้องรีเฟรช/ลองใหม่:
การจัดการข้อผิดพลาด
หากไม่ใช่ 2xx จะโยน HttpResponseError (รวมถึง status, response, args, data)
ความเข้ากันได้กับเลกาซี: หากร่างข้อผิดพลาดมีรูปแบบ { resultType: ... } จะโยนวัตถุที่ตรงนั้นโดยตรง
Next.js อะแดปเตอร์ (/next)
redirectToUnauthorizedOnServer401
redirectToUnauthorizedOnServer401 เป็นการดำเนินการพื้นฐาน (ฟังก์ชันสะดวก) ที่ทำการ redirect เมื่อเกิด 401 ในสภาพแวดล้อม SSR ของ Next.js (App Router)
กฎการทำงาน (คงที่):
- เป้าหมายการ redirect: /unauthorized
- queryString: redirect_uri=<หน้าปัจจุบัน> + logout=true
- หน้าปัจจุบันจะอ่านจาก header x-page-url (ถ้าไม่มีจะใช้ /)
หมายความว่าให้ใช้กฎเส้นทาง/query ข้างต้นตามที่ตรงกับโปรเจกต์เท่านั้น หากเส้นทางแตกต่างหรือกฎ query แตกต่าง ให้สร้าง onServer401 โดยตรงและฉีดเข้าไปตามที่ต้องการ.
callApiSsrCache
นี่คือผู้ช่วยแคช SSR ที่ใช้ next/cache(unstable_cache) ของ Next.
- GET + cacheTime > 0 → force-cache + revalidate
- อื่น ๆ → no-store
- ฉีด Cookie / Authorization ตามคำขอด้วย headersProvider
- เมื่อเกิด 401 หากมี onServer401 จะถูกเรียกใช้งาน (ปกติคือ redirect())
ตัวอย่างการรวม Next.js: โค้ดทั้งหมดของโปรเจกต์ rxjsHttpService/commonService
ไฟล์ rxjsHttpService.ts ด้านล่างนี้คือ HTTP adapter สาธารณะของโปรเจกต์ที่อ้างถึง commonServiceFile ในตัวอย่าง generator ต่อไปนี้ ไม่ใช่ไฟล์ที่สร้างโดยไลบรารี แต่โปรเจกต์จัดการโดยตรง และส่งออก core client + session auth + CSR cache + SSR cache helper ในที่เดียว นี่คือโค้ดทั้งหมด.
rxjsHttpService.ts
tsเอกสารอ้างอิง API (core)
createHttpClient<Paths>(options)
ส่งคืน:
callApi<R>(args): Observable<R>callApiStream<RChunk>(args): Observable<RChunk>uploadFile({ file, url, ifNoneMatch?, headers? }): Observable<Response>createSSEObservable<R>(args): Observable<R>
ตัวเลือก:
baseUrl: stringheaderStore?: HeaderStoreheadersProvider?: () => Record<string, string> | Promise<Record<string, string>>- dropAuthWhenCacheControl?: boolean (ค่าเริ่มต้น: true)
onServer401?: () => void | Promise<void>
createHeaderStore(initial?)
get(), set(), merge(), remove(), clear()
createCsrCache<CacheName>()
callApiCsrCache(callApiFn, serviceArgs, cacheForService)- removeCsrCache(cacheName) (ประเภท + สตริง)
createSessionAuth(options)
withSessionAuth(), withEnsureToken()ensureToken$(), refreshToken$(), logout$()
ข้อกำหนดในการทำงาน
- ใช้ fetch / Response API (rxjs/fetch)
- การสตรีม (NDJSON) ต้องการ ReadableStream + TextDecoder
- SSE ต้องการ EventSource
ส่วนใหญ่จะมีให้ในเบราว์เซอร์ล่าสุดและ runtime ของ Next.js อาจต้องใช้ polyfill ใน runtime ของ Node ที่กำหนดเอง.
Auto Node Script: การสร้างโค้ด OpenAPI/Swagger (ตัวเลือก)
แพ็คเกจนี้ให้สคริปต์ Node ที่สร้างโค้ดประเภท/บริการจาก OpenAPI/Swagger JSON แยกต่างหากจาก HTTP client runtime สคริปต์นี้เป็นฟังก์ชันเสริม.
ผู้ใช้ทั่วไปของ @byeolnaerim/typed-rx-http, /next, /rsocket ไม่จำเป็นต้องเรียกใช้สคริปต์นี้ และไม่จำเป็นต้องติดตั้ง openapi-typescript.
การแยกการพึ่งพา
การสร้างประเภท OpenAPI ต้องการ openapi-typescript CLI แต่แพ็คเกจนี้ไม่ใส่ openapi-typescript ไว้ใน dependencies ทั่วไป.
ไลบรารี @byeolnaerim/typed-rx-http ใช้ TypeScript 6.0.3 ใน devDependencies.typescript เอง. typed-rx-http, /next, /rsocket entry points และการสร้างไลบรารีจะรักษามาตรฐาน TypeScript 6.0.3 นี้.
อย่างไรก็ตาม openapi-typescript อาจต้องการเวอร์ชัน TypeScript 5.x เฉพาะ ดังนั้น OpenAPI auto node script จะทำงานในสภาพแวดล้อมชั่วคราวที่แยกต่างหากโดยใช้ openapi-typescript และ [email protected] สภาพแวดล้อมชั่วคราวนี้จะไม่เปลี่ยนแปลง devDependencies.typescript 6.0.3 ของไลบรารี และจะไม่ใช้เวอร์ชัน typescript หรือ openapi-typescript ที่ติดตั้งในโปรเจกต์ของผู้ใช้.
ค่าเริ่มต้นคือการสร้างและเรียกใช้คำสั่งด้านล่างในช่วงเวลาที่เรียกใช้ auto script.
ดังนั้นวิธีการใช้งานจึงไม่เปลี่ยนแปลง ผู้ใช้สามารถเรียกใช้ auto node script ได้ตามปกติ และจะใช้สภาพแวดล้อม TypeScript 5.9.3 ที่แยกต่างหากในขั้นตอนการสร้างประเภท OpenAPI ผู้ใช้ที่ไม่ใช้ auto script จะไม่ถูกผูกพันกับ openapi-typescript หรือ TypeScript 5.9.3.
หากจำเป็น สามารถกำหนดคำสั่งโดยตรงด้วย openApiTypescriptCommand ได้
หรือสามารถเปลี่ยนแค่เวอร์ชันของแพ็กเกจที่กำหนดคำสั่งพื้นฐานได้
ไฟล์ที่สร้างขึ้น
การตั้งค่าเริ่มต้นจะสร้างไฟล์ด้านล่างนี้
apiUnionArrays.ts จะสร้าง enum ของ OpenAPI schema รวมถึง query, path, header, cookie parameter enum เป็นอาร์เรย์คงที่ด้วย อาร์เรย์ query parameter ของ items.enum ก็จะถูกจัดการด้วยเช่นกัน
การตรวจสอบ EventStream
HTTP 1 ครั้ง
สร้างจากไฟล์ท้องถิ่น
ตัวอย่างการรวมโปรเจกต์ที่มีอยู่: WebFlux + Swagger สร้างอัตโนมัติ
ตั้งแต่ที่นี่เป็นต้นไปเป็นตัวอย่างการรวมโปรเจกต์ที่ใช้ Swagger ด้านหลังและบริการสร้างอัตโนมัติร่วมกัน ฟังก์ชันการใช้งานหลักด้านบนและฟังก์ชันเลือกสามารถใช้ได้ด้วย typed-rx-http เอง และกระบวนการด้านล่างจะใช้ในโปรเจกต์ที่ใช้การสร้างบริการอัตโนมัติจาก Swagger
1. เขียน REST endpoint ที่ Backend
เขียนโค้ด Backend ตามปกติ ในตัวอย่างนี้จะรับชื่อเป็น path variable และข้อความเป็น query parameter Monoและตอบกลับ
TypedRxHttpExampleRouter.java
java2. สร้างบริการ Front จาก Swagger
รับจาก Backend แต่ผมไม่ต้องการให้ typed-rx-http ถูกใช้เฉพาะใน WebFlux เท่านั้น แม้ว่า backend จะไม่สร้าง Swagger โดยตรง แต่หากมี TypeScript ที่ตรงตาม OpenAPI สเปค ก็สามารถลดการเขียน URL สตริงและ request type ด้วยมือได้ RSocket client ก็ถูกสร้างขึ้นตามเหตุผลเดียวกันโดยอิงจากเอกสาร AsyncAPIเพื่อสร้างไฟล์ประเภทและบริการ การทำงานนี้สามารถเรียกใช้ได้ครั้งเดียวเมื่อรันเซิร์ฟเวอร์พัฒนา หรือเชื่อมต่อกับสคริปต์ watch
generateSwagger.cjs
js3. ส่งคำขอด้วยฟังก์ชันที่สร้างขึ้น
สามารถเปลี่ยนแปลงได้ด้านล่าง โค้ด Frontและ โค้ด Backendสามารถเปลี่ยนแปลงได้ ผลลัพธ์เมื่อกดจะเปิดหน้าจอการทำงานทางด้านขวา เปลี่ยนค่าแล้วกดปุ่มคำขอ