@ptx-showcase/utils 0.3.0 → 0.4.0
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/README.md +48 -14
- package/dist/build-query-params/index.cjs +1 -1
- package/dist/build-query-params/index.js +1 -1
- package/dist/chunks/handle-api-error-CMd_LxPS.es +38 -0
- package/dist/chunks/handle-api-error-D714W9rp.cjs +1 -0
- package/dist/cookies/index.cjs +1 -1
- package/dist/download-file/index.cjs +1 -1
- package/dist/download-file/index.js +2 -1
- package/dist/handle-api-error/constants/handle-api-error.constant.d.ts +2 -0
- package/dist/handle-api-error/index.cjs +1 -0
- package/dist/handle-api-error/index.d.ts +3 -0
- package/dist/handle-api-error/index.js +2 -0
- package/dist/handle-api-error/libs/handle-api-error.lib.d.ts +5 -0
- package/dist/handle-api-error/libs/init-handle-api-error.lib.d.ts +3 -0
- package/dist/handle-api-error/types/handle-api-error.type.d.ts +14 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -2
- package/dist/types/index.d.ts +7 -0
- package/package.json +21 -9
- package/dist/chunks/cookies-BayERMbH.cjs +0 -1
package/README.md
CHANGED
|
@@ -58,13 +58,13 @@ import { buildSortParam } from '@ptx-showcase/utils'
|
|
|
58
58
|
// from subpath
|
|
59
59
|
import { buildSortParam } from '@ptx-showcase/utils/build-sort-param'
|
|
60
60
|
|
|
61
|
-
buildSortParam('name')
|
|
62
|
-
buildSortParam('name', 'name')
|
|
63
|
-
buildSortParam('name', '-name')
|
|
61
|
+
buildSortParam('name') // → 'name'
|
|
62
|
+
buildSortParam('name', 'name') // → '-name'
|
|
63
|
+
buildSortParam('name', '-name') // → ''
|
|
64
64
|
|
|
65
65
|
// combining with existing sort
|
|
66
|
-
buildSortParam('age', 'name')
|
|
67
|
-
buildSortParam('age', 'age,name')
|
|
66
|
+
buildSortParam('age', 'name') // → 'age,name'
|
|
67
|
+
buildSortParam('age', 'age,name') // → '-age,name'
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
---
|
|
@@ -96,7 +96,7 @@ deleteCookie('token')
|
|
|
96
96
|
Default options:
|
|
97
97
|
|
|
98
98
|
| Option | Value |
|
|
99
|
-
|
|
99
|
+
| ---------- | ---------- |
|
|
100
100
|
| `expires` | 1 hour |
|
|
101
101
|
| `secure` | `true` |
|
|
102
102
|
| `sameSite` | `'Strict'` |
|
|
@@ -126,16 +126,50 @@ await downloadBlob(blob, { hash: 12345 })
|
|
|
126
126
|
|
|
127
127
|
---
|
|
128
128
|
|
|
129
|
+
### handleApiError
|
|
130
|
+
|
|
131
|
+
Parses backend error responses (including `ky`'s `HTTPError`) and reports human-readable messages through whatever notification system your project uses (`vue-sonner`, `react-hot-toast`, `console.error`, etc).
|
|
132
|
+
|
|
133
|
+
The utility is UI-agnostic: call `initHandleApiError` once at app startup with a `notify` function, then call `handleApiError` from anywhere without touching the notification library again. Without initialization, messages fall back to `console.error`.
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
// from root
|
|
137
|
+
import { handleApiError, initHandleApiError } from '@ptx-showcase/utils'
|
|
138
|
+
|
|
139
|
+
// from subpath
|
|
140
|
+
import { handleApiError, initHandleApiError } from '@ptx-showcase/utils/handle-api-error'
|
|
141
|
+
|
|
142
|
+
// Vue project (e.g. main.ts), using vue-sonner
|
|
143
|
+
import { toast } from 'vue-sonner'
|
|
144
|
+
|
|
145
|
+
initHandleApiError({ notify: (message) => toast.error(message) })
|
|
146
|
+
|
|
147
|
+
// React project (e.g. app entry), using react-hot-toast
|
|
148
|
+
import toast from 'react-hot-toast'
|
|
149
|
+
|
|
150
|
+
initHandleApiError({ notify: (message) => toast.error(message) })
|
|
151
|
+
|
|
152
|
+
// anywhere in either project
|
|
153
|
+
try {
|
|
154
|
+
await api.get('users')
|
|
155
|
+
} catch (error) {
|
|
156
|
+
handleApiError(error)
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
129
162
|
## Available modules
|
|
130
163
|
|
|
131
|
-
| Subpath
|
|
132
|
-
|
|
133
|
-
| `@ptx-showcase/utils`
|
|
134
|
-
| `@ptx-showcase/utils/build-query-params`
|
|
135
|
-
| `@ptx-showcase/utils/build-sort-param`
|
|
136
|
-
| `@ptx-showcase/utils/cookies`
|
|
137
|
-
| `@ptx-showcase/utils/download-file`
|
|
138
|
-
| `@ptx-showcase/utils/
|
|
164
|
+
| Subpath | Exports |
|
|
165
|
+
| ---------------------------------------- | ---------------------------------------------------------------- |
|
|
166
|
+
| `@ptx-showcase/utils` | all utilities |
|
|
167
|
+
| `@ptx-showcase/utils/build-query-params` | `buildQueryParams` |
|
|
168
|
+
| `@ptx-showcase/utils/build-sort-param` | `buildSortParam` |
|
|
169
|
+
| `@ptx-showcase/utils/cookies` | `setCookie`, `getCookie`, `deleteCookie`, `defaultCookieOptions` |
|
|
170
|
+
| `@ptx-showcase/utils/download-file` | `downloadBlob` |
|
|
171
|
+
| `@ptx-showcase/utils/handle-api-error` | `handleApiError`, `initHandleApiError` |
|
|
172
|
+
| `@ptx-showcase/utils/types` | `TableColumnConfig`, `PaginatedList` |
|
|
139
173
|
|
|
140
174
|
---
|
|
141
175
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=e=>{let t=new URLSearchParams;Object.entries(e).forEach(([e,n])=>{n
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=e=>{let t=new URLSearchParams;Object.entries(e).forEach(([e,n])=>{n!=null&&n!==``&&(Array.isArray(n)&&n.length===0||t.append(e,String(n)))});let n=t.toString();return n?`?${n}`:``};exports.buildQueryParams=e;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
var e = (e) => {
|
|
3
3
|
let t = new URLSearchParams();
|
|
4
4
|
Object.entries(e).forEach(([e, n]) => {
|
|
5
|
-
n
|
|
5
|
+
n != null && n !== "" && (Array.isArray(n) && n.length === 0 || t.append(e, String(n)));
|
|
6
6
|
});
|
|
7
7
|
let n = t.toString();
|
|
8
8
|
return n ? `?${n}` : "";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { isHTTPError as e } from "ky";
|
|
2
|
+
//#region src/handle-api-error/constants/handle-api-error.constant.ts
|
|
3
|
+
var t = "Something went wrong", n = /* @__PURE__ */ new Set([
|
|
4
|
+
"message",
|
|
5
|
+
"detail",
|
|
6
|
+
"error",
|
|
7
|
+
"msg"
|
|
8
|
+
]), r = (e) => typeof e == "object" && !!e && !Array.isArray(e), i = (e) => typeof e == "string" && e.trim() ? e : null, a = (e, t) => typeof e == "string" ? e.trim() ? [t ? `${t}: ${e}` : e] : [] : Array.isArray(e) ? e.flatMap((e) => a(e, t)) : r(e) ? Object.entries(e).flatMap(([e, t]) => a(t, e === "non_field_errors" ? void 0 : e)) : [], o = (e) => {
|
|
9
|
+
if (!e) return [];
|
|
10
|
+
if (typeof e == "string") return [e];
|
|
11
|
+
if (Array.isArray(e)) return e.filter((e) => typeof e == "string" && !!e.trim());
|
|
12
|
+
let t = i(e.detail) ?? i(e.message) ?? i(e.error) ?? i(e.msg);
|
|
13
|
+
return [...Object.entries(e).flatMap(([e, t]) => n.has(e) ? [] : e === "non_field_errors" || e === "errors" ? a(t) : a(t, e)), ...t ? [t] : []];
|
|
14
|
+
}, s = (e) => {
|
|
15
|
+
console.error(e);
|
|
16
|
+
}, c = (e) => {
|
|
17
|
+
s = e;
|
|
18
|
+
}, l = () => s, u = (e) => {
|
|
19
|
+
c(e.notify);
|
|
20
|
+
}, d = (n) => {
|
|
21
|
+
let r = l();
|
|
22
|
+
if (e(n)) {
|
|
23
|
+
let e = n.data, i = [...new Set(o(e))];
|
|
24
|
+
if (i.length > 0) {
|
|
25
|
+
i.forEach((e) => r(e));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
r(t);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (n instanceof Error) {
|
|
32
|
+
r(n.message || "Something went wrong");
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
r(t);
|
|
36
|
+
};
|
|
37
|
+
//#endregion
|
|
38
|
+
export { u as n, d as t };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let e=require("ky");var t=`Something went wrong`,n=new Set([`message`,`detail`,`error`,`msg`]),r=e=>typeof e==`object`&&!!e&&!Array.isArray(e),i=e=>typeof e==`string`&&e.trim()?e:null,a=(e,t)=>typeof e==`string`?e.trim()?[t?`${t}: ${e}`:e]:[]:Array.isArray(e)?e.flatMap(e=>a(e,t)):r(e)?Object.entries(e).flatMap(([e,t])=>a(t,e===`non_field_errors`?void 0:e)):[],o=e=>{if(!e)return[];if(typeof e==`string`)return[e];if(Array.isArray(e))return e.filter(e=>typeof e==`string`&&!!e.trim());let t=i(e.detail)??i(e.message)??i(e.error)??i(e.msg);return[...Object.entries(e).flatMap(([e,t])=>n.has(e)?[]:e===`non_field_errors`||e===`errors`?a(t):a(t,e)),...t?[t]:[]]},s=e=>{console.error(e)},c=e=>{s=e},l=()=>s,u=e=>{c(e.notify)},d=n=>{let r=l();if((0,e.isHTTPError)(n)){let e=n.data,i=[...new Set(o(e))];if(i.length>0){i.forEach(e=>r(e));return}r(t);return}if(n instanceof Error){r(n.message||`Something went wrong`);return}r(t)};Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return d}});
|
package/dist/cookies/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));let c=require("js-cookie");c=s(c,1);var l={expires:1/24,secure:!0,sameSite:`Strict`},u=(e,t,n)=>{c.default.set(e,t,{...l,...n})},d=e=>c.default.get(e),f=(e,t)=>{c.default.remove(e,t)};exports.defaultCookieOptions=l,exports.deleteCookie=f,exports.getCookie=d,exports.setCookie=u;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("file-saver");var t=async e=>{let t=new TextEncoder().encode(String(e)),n=await crypto.subtle.digest(`SHA-1`,t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,`0`)).join(``)},n=async(n,r)=>{if(!(n instanceof Blob))throw Error(`downloadBlob: expected Blob, got ${typeof n}`);
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("file-saver");var t=async e=>{let t=new TextEncoder().encode(String(e)),n=await crypto.subtle.digest(`SHA-1`,t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,`0`)).join(``)},n=async(n,r)=>{if(!(n instanceof Blob))throw Error(`downloadBlob: expected Blob, got ${typeof n}`);let i=`filename`in r?r.filename:await t(r.hash);(0,e.saveAs)(n,i)};exports.downloadBlob=n;
|
|
@@ -5,7 +5,8 @@ var t = async (e) => {
|
|
|
5
5
|
return Array.from(new Uint8Array(n)).map((e) => e.toString(16).padStart(2, "0")).join("");
|
|
6
6
|
}, n = async (n, r) => {
|
|
7
7
|
if (!(n instanceof Blob)) throw Error(`downloadBlob: expected Blob, got ${typeof n}`);
|
|
8
|
-
|
|
8
|
+
let i = "filename" in r ? r.filename : await t(r.hash);
|
|
9
|
+
e(n, i);
|
|
9
10
|
};
|
|
10
11
|
//#endregion
|
|
11
12
|
export { n as downloadBlob };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../chunks/handle-api-error-D714W9rp.cjs");exports.handleApiError=e.t,exports.initHandleApiError=e.n;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ApiErrorData, ApiErrorPrimitive } from '../types/handle-api-error.type';
|
|
2
|
+
export declare const isPlainObject: (value: unknown) => value is Record<string, unknown>;
|
|
3
|
+
export declare const toMessage: (value: unknown) => string | null;
|
|
4
|
+
export declare const extractMessages: (value: unknown, parentKey?: string) => string[];
|
|
5
|
+
export declare const getHttpErrorMessages: (errorData: ApiErrorData | ApiErrorPrimitive | undefined) => string[];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type NotifyFn = (message: string) => void;
|
|
2
|
+
export interface HandleApiErrorConfig {
|
|
3
|
+
notify: NotifyFn;
|
|
4
|
+
}
|
|
5
|
+
export type ApiErrorPrimitive = string | string[];
|
|
6
|
+
export interface ApiErrorData {
|
|
7
|
+
detail?: string;
|
|
8
|
+
message?: string;
|
|
9
|
+
error?: string;
|
|
10
|
+
msg?: string;
|
|
11
|
+
non_field_errors?: string[];
|
|
12
|
+
errors?: unknown;
|
|
13
|
+
[key: string]: unknown;
|
|
14
|
+
}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./build-query-params/index.cjs"),t=require("./clean-object/index.cjs"),n=require("./cookies/index.cjs"),r=require("./build-sort-param/index.cjs"),i=require("./download-file/index.cjs"),a=require("./chunks/handle-api-error-D714W9rp.cjs"),o=require("./normalize-input/index.cjs");exports.buildQueryParams=e.buildQueryParams,exports.buildSortParam=r.buildSortParam,exports.cleanObject=t.cleanObject,exports.defaultCookieOptions=n.defaultCookieOptions,exports.deleteCookie=n.deleteCookie,exports.downloadBlob=i.downloadBlob,exports.getCookie=n.getCookie,exports.handleApiError=a.t,exports.initHandleApiError=a.n,exports.normalizeDecimalInput=o.normalizeDecimalInput,exports.normalizePhoneNumberInput=o.normalizePhoneNumberInput,exports.setCookie=n.setCookie;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -3,5 +3,6 @@ import { cleanObject as t } from "./clean-object/index.js";
|
|
|
3
3
|
import { defaultCookieOptions as n, deleteCookie as r, getCookie as i, setCookie as a } from "./cookies/index.js";
|
|
4
4
|
import { buildSortParam as o } from "./build-sort-param/index.js";
|
|
5
5
|
import { downloadBlob as s } from "./download-file/index.js";
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import { n as c, t as l } from "./chunks/handle-api-error-CMd_LxPS.es";
|
|
7
|
+
import { normalizeDecimalInput as u, normalizePhoneNumberInput as d } from "./normalize-input/index.js";
|
|
8
|
+
export { e as buildQueryParams, o as buildSortParam, t as cleanObject, n as defaultCookieOptions, r as deleteCookie, s as downloadBlob, i as getCookie, l as handleApiError, c as initHandleApiError, u as normalizeDecimalInput, d as normalizePhoneNumberInput, a as setCookie };
|
package/dist/types/index.d.ts
CHANGED
|
@@ -4,3 +4,10 @@ export interface TableColumnConfig<T, ExtraKeys extends string = never> {
|
|
|
4
4
|
key: keyof T | ExtraKeys;
|
|
5
5
|
sortable?: boolean;
|
|
6
6
|
}
|
|
7
|
+
export interface PaginatedList<T> {
|
|
8
|
+
items: T[];
|
|
9
|
+
page: number;
|
|
10
|
+
per_page: number;
|
|
11
|
+
total_items: number;
|
|
12
|
+
total_pages: number;
|
|
13
|
+
}
|
package/package.json
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"name": "@ptx-showcase/utils",
|
|
3
3
|
"author": "ptx-showcase",
|
|
4
4
|
"description": "Shared utilities for PTX Showcase projects",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.4.0",
|
|
6
6
|
"private": false,
|
|
7
7
|
"type": "module",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
|
-
"url": "https://github.com/gibPerviy/ptx-showcase-utils"
|
|
11
|
+
"url": "git+https://github.com/gibPerviy/ptx-showcase-utils.git"
|
|
12
12
|
},
|
|
13
13
|
"homepage": "https://github.com/gibPerviy/ptx-showcase-utils#readme",
|
|
14
14
|
"bugs": {
|
|
@@ -56,6 +56,11 @@
|
|
|
56
56
|
"require": "./dist/download-file/index.cjs",
|
|
57
57
|
"types": "./dist/download-file/index.d.ts"
|
|
58
58
|
},
|
|
59
|
+
"./handle-api-error": {
|
|
60
|
+
"import": "./dist/handle-api-error/index.js",
|
|
61
|
+
"require": "./dist/handle-api-error/index.cjs",
|
|
62
|
+
"types": "./dist/handle-api-error/index.d.ts"
|
|
63
|
+
},
|
|
59
64
|
"./normalize-input": {
|
|
60
65
|
"import": "./dist/normalize-input/index.js",
|
|
61
66
|
"require": "./dist/normalize-input/index.cjs",
|
|
@@ -71,24 +76,31 @@
|
|
|
71
76
|
"dev": "vite",
|
|
72
77
|
"test": "vitest",
|
|
73
78
|
"build": "vite build",
|
|
79
|
+
"lint": "oxlint",
|
|
80
|
+
"lint:fix": "oxlint --fix",
|
|
81
|
+
"fmt": "oxfmt",
|
|
82
|
+
"fmt:check": "oxfmt --check",
|
|
83
|
+
"pre:commit": "oxfmt && oxlint && vite build",
|
|
74
84
|
"release": "bumpp"
|
|
75
85
|
},
|
|
76
86
|
"publishConfig": {
|
|
77
87
|
"access": "public"
|
|
78
88
|
},
|
|
79
89
|
"devDependencies": {
|
|
80
|
-
"@types/node": "^
|
|
81
|
-
"bumpp": "^
|
|
82
|
-
"
|
|
90
|
+
"@types/node": "^26.1.2",
|
|
91
|
+
"bumpp": "^12.2.0",
|
|
92
|
+
"oxfmt": "^0.62.0",
|
|
93
|
+
"oxlint": "^1.77.0",
|
|
83
94
|
"typescript": "~6.0.3",
|
|
84
|
-
"vite": "^8.
|
|
85
|
-
"vite-plugin-dts": "^5.0.
|
|
86
|
-
"vitest": "^4.1.
|
|
95
|
+
"vite": "^8.2.1",
|
|
96
|
+
"vite-plugin-dts": "^5.0.3",
|
|
97
|
+
"vitest": "^4.1.10"
|
|
87
98
|
},
|
|
88
99
|
"dependencies": {
|
|
89
100
|
"@types/file-saver": "^2.0.7",
|
|
90
101
|
"@types/js-cookie": "^3.0.6",
|
|
91
102
|
"file-saver": "^2.0.5",
|
|
92
|
-
"js-cookie": "^3.0.8"
|
|
103
|
+
"js-cookie": "^3.0.8",
|
|
104
|
+
"ky": "^2.0.2"
|
|
93
105
|
}
|
|
94
106
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require("js-cookie");c=s(c,1);var l={expires:1/24,secure:!0,sameSite:`Strict`},u=(e,t,n)=>{c.default.set(e,t,{...l,...n})},d=e=>c.default.get(e),f=(e,t)=>{c.default.remove(e,t)};Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return l}});
|