@iyulab/enterprise 0.10.2 → 0.11.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.1
4
+
5
+ ### Fixed
6
+
7
+ - **`createAuthClient`'s README section documented only 4 of `AuthClientConfig`'s
8
+ 7 fields** — `baseUrl`, `credentials`, and `extractLoginError` had no mention
9
+ anywhere (only `permissionStore` was covered, in prose). Added a config table
10
+ matching the one already used for `createODataService`.
11
+
12
+ ## 0.11.0
13
+
14
+ ### Added
15
+
16
+ - **`ODataService.odataPatchQuiet`/`odataDeleteQuiet`** — quiet counterparts to
17
+ `odataPatch`/`odataDelete`, mirroring the existing `odataPost`/`odataPostQuiet`
18
+ split. For an action that fires more than one mutation in response to a single
19
+ user click (e.g. editing a row and syncing a denormalized parent field), the
20
+ toasting variants would show a toast per mutation; the quiet variants do the
21
+ request and error handling without one, so the caller can toast once for the
22
+ whole action. Previously PATCH/DELETE had no quiet path, forcing a raw
23
+ `fetch()` that lost 401 handling and `ApiError` extraction.
24
+
3
25
  ## 0.10.2
4
26
 
5
27
  ### Changed
package/README.md CHANGED
@@ -147,8 +147,16 @@ const user = await auth.fetchMe() // null → 미인증(로그인 화면)
147
147
  if (hasPermission('orders.write')) { /* 저장 버튼 노출 */ }
148
148
  ```
149
149
 
150
+ 주입 항목(위 예시가 쓴 것 외 나머지):
151
+
152
+ | config | 용도 |
153
+ |--------|------|
154
+ | `baseUrl` | 상대 URL 앞에 붙일 오리진 (기본 `''` = same-origin) |
155
+ | `credentials` | fetch `credentials` 모드 (기본 `'same-origin'` — 쿠키 세션) |
156
+ | `extractLoginError` | 로그인 실패(non-401) 응답 바디에서 서버 메시지 추출 오버라이드 (기본: `body.Message ?? body.message`) |
157
+ | `permissionStore` | 권한 자동 갱신 대상 store (기본 `defaultPermissionStore`) — 격리가 필요하면 `createPermissionStore()`로 별도 store를 만들어 주입 |
158
+
150
159
  - `fetchMe()` 는 401/네트워크 오류 시 `null` — 이 신호가 로그인 게이트를 구동한다(라이브러리가 리다이렉트하지 않음).
151
- - 격리가 필요하면 `createPermissionStore()` 로 별도 store 를 만들어 `permissionStore` 로 주입한다.
152
160
  - 도메인 판정(`isPortalUser` 등)·권한 코드 상수는 라이브러리가 아니라 앱 adapter 에 둔다.
153
161
 
154
162
  ### 도메인 헬퍼
@@ -67,8 +67,13 @@ export interface ODataService {
67
67
  odataPostQuiet<T>(entity: string, body: Partial<T>): Promise<T>;
68
68
  /** OData POST(생성) — 성공 시 `saved` 토스트. */
69
69
  odataPost<T>(entity: string, body: Partial<T>): Promise<T>;
70
+ /** OData PATCH(수정) — 토스트 없이 결과만(자식 컬렉션 편집 후 부모의 파생 필드를
71
+ * 함께 동기화하는 등, 한 사용자 액션이 여러 mutation을 낼 때 토스트 폭주 방지). */
72
+ odataPatchQuiet<T>(entity: string, id: string, body: Partial<T>): Promise<void>;
70
73
  /** OData PATCH(수정) — 성공 시 `updated` 토스트. */
71
74
  odataPatch<T>(entity: string, id: string, body: Partial<T>): Promise<void>;
75
+ /** OData DELETE — 토스트 없이(`odataPatchQuiet`와 같은 이유). */
76
+ odataDeleteQuiet(entity: string, id: string): Promise<void>;
72
77
  /** OData DELETE — 성공 시 `deleted` 토스트. */
73
78
  odataDelete(entity: string, id: string): Promise<void>;
74
79
  /** custom REST GET — 204 등 빈 바디를 안전 파싱. */
package/dist/icons.d.ts CHANGED
@@ -1 +1 @@
1
- export {};
1
+ export {}
package/dist/index.js CHANGED
@@ -743,31 +743,29 @@ function createODataService(config) {
743
743
  throw e;
744
744
  }
745
745
  }
746
+ async function odataPatchQuiet(entity, id, body) {
747
+ await throwIfError(await client.patch(`${odataUrl(entity)}(${id})`, normalizeBody(body)));
748
+ }
746
749
  async function odataPatch(entity, id, body) {
747
- const res = await client.patch(`${odataUrl(entity)}(${id})`, normalizeBody(body));
748
- if (!res.ok) {
749
- if (res.status === 401) {
750
- config.onUnauthorized?.(401);
751
- throw new ApiError(messages.sessionExpired, 401);
752
- }
753
- const msg = await extractErrorMsg(res);
754
- notifyError?.(msg);
755
- throw new ApiError(msg, res.status);
750
+ try {
751
+ await odataPatchQuiet(entity, id, body);
752
+ notifySuccess?.(messages.updated);
753
+ } catch (e) {
754
+ if (!(e instanceof ApiError && e.status === 401)) notifyError?.(e instanceof Error ? e.message : messages.requestFailed);
755
+ throw e;
756
756
  }
757
- notifySuccess?.(messages.updated);
757
+ }
758
+ async function odataDeleteQuiet(entity, id) {
759
+ await throwIfError(await client.delete(`${odataUrl(entity)}(${id})`));
758
760
  }
759
761
  async function odataDelete(entity, id) {
760
- const res = await client.delete(`${odataUrl(entity)}(${id})`);
761
- if (!res.ok) {
762
- if (res.status === 401) {
763
- config.onUnauthorized?.(401);
764
- throw new ApiError(messages.sessionExpired, 401);
765
- }
766
- const msg = await extractErrorMsg(res);
767
- notifyError?.(msg);
768
- throw new ApiError(msg, res.status);
762
+ try {
763
+ await odataDeleteQuiet(entity, id);
764
+ notifySuccess?.(messages.deleted);
765
+ } catch (e) {
766
+ if (!(e instanceof ApiError && e.status === 401)) notifyError?.(e instanceof Error ? e.message : messages.requestFailed);
767
+ throw e;
769
768
  }
770
- notifySuccess?.(messages.deleted);
771
769
  }
772
770
  async function apiGet(path) {
773
771
  const [p, ...q] = path.split("?");
@@ -809,7 +807,9 @@ function createODataService(config) {
809
807
  odataCount,
810
808
  odataPostQuiet,
811
809
  odataPost,
810
+ odataPatchQuiet,
812
811
  odataPatch,
812
+ odataDeleteQuiet,
813
813
  odataDelete,
814
814
  apiGet,
815
815
  apiPost,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iyulab/enterprise",
3
- "version": "0.10.2",
3
+ "version": "0.11.1",
4
4
  "description": "Enterprise utilities and components for iyulab framework",
5
5
  "keywords": [
6
6
  "enterprise",
@@ -45,6 +45,7 @@
45
45
  "./styles/preset.css": "./dist/styles/preset.css"
46
46
  },
47
47
  "scripts": {
48
+ "preversion": "node -e \"if(require('fs').existsSync('../../scripts/preversion-check.mjs'))require('child_process').execFileSync('node',['../../scripts/preversion-check.mjs'],{stdio:'inherit'})\"",
48
49
  "build": "npm run typecheck && vite build && node scripts/copy-styles.mjs",
49
50
  "test": "vitest run",
50
51
  "typecheck": "tsc --noEmit"