@digitalwalletcorp/utils 0.2.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 +13 -13
- package/lib/crypto-util-DFJqfmuw.js +46 -0
- package/lib/crypto-util-DFJqfmuw.js.map +1 -0
- package/lib/crypto-util-DeZSGetI.cjs +2 -0
- package/lib/crypto-util-DeZSGetI.cjs.map +1 -0
- package/lib/crypto-util.cjs +2 -0
- package/lib/crypto-util.cjs.map +1 -0
- package/lib/crypto-util.d.cts +28 -0
- package/lib/crypto-util.d.ts +28 -0
- package/lib/crypto-util.js +7 -0
- package/lib/crypto-util.js.map +1 -0
- package/lib/date-util-CG7L8nSP.js +184 -0
- package/lib/date-util-CG7L8nSP.js.map +1 -0
- package/lib/date-util-DopNKy3u.cjs +2 -0
- package/lib/date-util-DopNKy3u.cjs.map +1 -0
- package/lib/date-util.cjs +2 -0
- package/lib/date-util.cjs.map +1 -0
- package/lib/date-util.d.cts +231 -0
- package/lib/date-util.d.ts +231 -0
- package/lib/date-util.js +23 -0
- package/lib/date-util.js.map +1 -0
- package/lib/decimal.cjs +2 -0
- package/lib/decimal.cjs.map +1 -0
- package/lib/decimal.d.cts +197 -0
- package/lib/decimal.d.ts +197 -0
- package/lib/decimal.js +227 -0
- package/lib/decimal.js.map +1 -0
- package/lib/file-util-D09BvDYY.cjs +2 -0
- package/lib/file-util-D09BvDYY.cjs.map +1 -0
- package/lib/file-util-H-c_eQcd.js +140 -0
- package/lib/file-util-H-c_eQcd.js.map +1 -0
- package/lib/file-util.cjs +2 -0
- package/lib/file-util.cjs.map +1 -0
- package/lib/file-util.d.cts +119 -0
- package/lib/file-util.d.ts +119 -0
- package/lib/file-util.js +18 -0
- package/lib/file-util.js.map +1 -0
- package/lib/html-util-Bxn5YDSK.cjs +2 -0
- package/lib/html-util-Bxn5YDSK.cjs.map +1 -0
- package/lib/html-util-CgMIuOsf.js +49 -0
- package/lib/html-util-CgMIuOsf.js.map +1 -0
- package/lib/html-util.cjs +2 -0
- package/lib/html-util.cjs.map +1 -0
- package/lib/html-util.d.cts +71 -0
- package/lib/html-util.d.ts +71 -0
- package/lib/html-util.js +8 -0
- package/lib/html-util.js.map +1 -0
- package/lib/index.cjs +1 -1
- package/lib/index.d.cts +8 -0
- package/lib/index.d.ts +8 -0
- package/lib/index.js +18 -2
- package/lib/index.js.map +1 -1
- package/lib/json-util-BvrFYh5E.cjs +3 -0
- package/lib/json-util-BvrFYh5E.cjs.map +1 -0
- package/lib/json-util-YX7xSF6R.js +136 -0
- package/lib/json-util-YX7xSF6R.js.map +1 -0
- package/lib/json-util.cjs +2 -0
- package/lib/json-util.cjs.map +1 -0
- package/lib/json-util.d.cts +58 -0
- package/lib/json-util.d.ts +58 -0
- package/lib/json-util.js +8 -0
- package/lib/json-util.js.map +1 -0
- package/lib/number-util-BA4KVFyF.js +198 -0
- package/lib/number-util-BA4KVFyF.js.map +1 -0
- package/lib/number-util-BaSf1wWH.cjs +2 -0
- package/lib/number-util-BaSf1wWH.cjs.map +1 -0
- package/lib/number-util.cjs +1 -1
- package/lib/number-util.d.cts +65 -51
- package/lib/number-util.d.ts +65 -51
- package/lib/number-util.js +19 -14
- package/lib/object-util-DhGi-PmA.js +204 -0
- package/lib/object-util-DhGi-PmA.js.map +1 -0
- package/lib/object-util-Z0Ah5J8A.cjs +2 -0
- package/lib/object-util-Z0Ah5J8A.cjs.map +1 -0
- package/lib/object-util.cjs +2 -0
- package/lib/object-util.cjs.map +1 -0
- package/lib/object-util.d.cts +157 -0
- package/lib/object-util.d.ts +157 -0
- package/lib/object-util.js +16 -0
- package/lib/object-util.js.map +1 -0
- package/lib/string-util-Cw0VgbIH.js +52 -0
- package/lib/string-util-Cw0VgbIH.js.map +1 -0
- package/lib/string-util-w2I5EYuY.cjs +2 -0
- package/lib/string-util-w2I5EYuY.cjs.map +1 -0
- package/lib/string-util.cjs +2 -0
- package/lib/string-util.cjs.map +1 -0
- package/lib/string-util.d.cts +51 -0
- package/lib/string-util.d.ts +51 -0
- package/lib/string-util.js +8 -0
- package/lib/string-util.js.map +1 -0
- package/package.json +26 -8
- package/src/crypto-util.ts +84 -0
- package/src/date-util.ts +448 -0
- package/src/decimal.ts +294 -0
- package/src/file-util.ts +281 -0
- package/src/html-util.ts +196 -0
- package/src/index.ts +8 -0
- package/src/json-util.ts +271 -0
- package/src/number-util.ts +141 -194
- package/src/object-util.ts +482 -0
- package/src/string-util.ts +115 -0
- package/lib/number-util-DHq-ux31.js +0 -253
- package/lib/number-util-DHq-ux31.js.map +0 -1
- package/lib/number-util-DiMi-j7B.cjs +0 -2
- package/lib/number-util-DiMi-j7B.cjs.map +0 -1
- package/lib/reg-exp-matcher.cjs +0 -2
- package/lib/reg-exp-matcher.cjs.map +0 -1
- package/lib/reg-exp-matcher.d.cts +0 -85
- package/lib/reg-exp-matcher.d.ts +0 -85
- package/lib/reg-exp-matcher.js +0 -94
- package/lib/reg-exp-matcher.js.map +0 -1
- package/src/reg-exp-matcher.ts +0 -154
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/** コンストラクタの型 */
|
|
2
|
+
export type Constructor<T> = new (...args: any[]) => T;
|
|
3
|
+
/**
|
|
4
|
+
* マージのオプション
|
|
5
|
+
*/
|
|
6
|
+
export interface MergeOptions {
|
|
7
|
+
/**
|
|
8
|
+
* 配列のマージ方法。既定は 'replace'
|
|
9
|
+
* ├ replace source側の配列の複製で置き換える
|
|
10
|
+
* ├ concat original側の配列にsource側の要素の複製を連結する
|
|
11
|
+
* └ indexMerge 添字ごとにマージする。source側より長い部分はoriginal側の要素が残る
|
|
12
|
+
*/
|
|
13
|
+
arrays?: 'replace' | 'concat' | 'indexMerge';
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 指定したクラスのインスタンスを生成する
|
|
17
|
+
*
|
|
18
|
+
* @param {Constructor<T>} creator クラス
|
|
19
|
+
* @param {any[]} args コンストラクタの引数
|
|
20
|
+
* @returns {T}
|
|
21
|
+
*/
|
|
22
|
+
export declare function create<T>(creator: Constructor<T>, ...args: any[]): T;
|
|
23
|
+
/**
|
|
24
|
+
* オブジェクトに階層構造で値を設定する
|
|
25
|
+
* 引数の最後の要素が値、それ以外がキーの階層である。キーが1つもない場合は何もしない
|
|
26
|
+
* 途中の階層が存在しない、またはオブジェクトでない場合は、新しいオブジェクトで置き換えて先へ進む
|
|
27
|
+
* 設定先がすでに配列の場合は、値を置き換えずに配列へ追加する。値が配列の場合はその要素を追加する
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* const obj = {};
|
|
31
|
+
* appendObjectHierarchy(obj, 'a', 'b', 'c', 100); // { a: { b: { c: 100 } } }
|
|
32
|
+
* appendObjectHierarchy(obj, 'a', 'b', 'd', [1]); // { a: { b: { c: 100, d: [1] } } }
|
|
33
|
+
* appendObjectHierarchy(obj, 'a', 'b', 'd', [2]); // { a: { b: { c: 100, d: [1, 2] } } }
|
|
34
|
+
*
|
|
35
|
+
* @param {object} obj
|
|
36
|
+
* @param {any[]} args キーの階層と、最後に設定する値
|
|
37
|
+
*/
|
|
38
|
+
export declare function appendObjectHierarchy(obj: Record<PropertyKey, any>, ...args: any[]): void;
|
|
39
|
+
/**
|
|
40
|
+
* オブジェクトの階層キーをドット(.)で繋いで指定して値を取得する
|
|
41
|
+
* 配列の要素は [n] で指定する
|
|
42
|
+
* 該当するキーがない場合、または途中の値が null / undefined の場合は undefined を返す
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* getValue({ a: { b: [1, 2, 3] } }, 'a.b[1]'); // 2
|
|
46
|
+
*
|
|
47
|
+
* @param {any} obj
|
|
48
|
+
* @param {string} key
|
|
49
|
+
* @returns {T | undefined}
|
|
50
|
+
*/
|
|
51
|
+
export declare function getValue<T = any>(obj: any, key: string): T | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* 値を深く複製する
|
|
54
|
+
* ・プリミティブと関数はそのまま返す
|
|
55
|
+
* ・Date / RegExp / Map / Set / 配列 / ArrayBuffer / 型付き配列は複製する
|
|
56
|
+
* ・プレーンオブジェクトとクラスのインスタンスは、プロトタイプを引き継いで列挙可能な自身のプロパティを複製する
|
|
57
|
+
* ・DOMのNodeは cloneNode(true) で複製する
|
|
58
|
+
* ・WeakMap / WeakSet / Promise / Error は参照のまま返す
|
|
59
|
+
* ・循環参照と、同じオブジェクトを複数箇所から参照している構造は、複製後も保たれる
|
|
60
|
+
*
|
|
61
|
+
* @param {T} value
|
|
62
|
+
* @returns {T}
|
|
63
|
+
*/
|
|
64
|
+
export declare function cloneObject<T>(value: T): T;
|
|
65
|
+
/**
|
|
66
|
+
* originalにsourceのプロパティを深くマージする(破壊)
|
|
67
|
+
* ・original側とsource側が両方プレーンオブジェクトの場合は再帰的にマージする
|
|
68
|
+
* ・source側が undefined のプロパティは「指定なし」とみなし、original側の値を残す
|
|
69
|
+
* ・それ以外はsource側の値の深い複製で置き換える。null は null を設定する
|
|
70
|
+
* ・配列は既定でsource側の複製で置き換える。options.arrays で連結・添字ごとのマージに変更できる
|
|
71
|
+
* ・source側の循環参照と、同じオブジェクトを複数箇所から参照している構造は、結果にも保たれる
|
|
72
|
+
* ・sourceが null / undefined / プレーンオブジェクト以外の場合は何もしない
|
|
73
|
+
*
|
|
74
|
+
* @param {T} original マージ先。この引数が書き換えられる
|
|
75
|
+
* @param {object | null | undefined} source マージするプロパティを持つオブジェクト
|
|
76
|
+
* @param {MergeOptions} [options]
|
|
77
|
+
* @returns {T} original
|
|
78
|
+
*/
|
|
79
|
+
export declare function merge<T extends object>(original: T, source: object | null | undefined, options?: MergeOptions): T;
|
|
80
|
+
/**
|
|
81
|
+
* originalの複製にsourceのプロパティを深くマージした新しいオブジェクトを返す(非破壊)
|
|
82
|
+
* マージの規則は merge と同じ
|
|
83
|
+
*
|
|
84
|
+
* @param {T} original マージ元。この引数は書き換えない
|
|
85
|
+
* @param {object | null | undefined} source マージするプロパティを持つオブジェクト
|
|
86
|
+
* @param {MergeOptions} [options]
|
|
87
|
+
* @returns {T} マージした新しいオブジェクト
|
|
88
|
+
*/
|
|
89
|
+
export declare function cloneMerge<T extends object>(original: T, source: object | null | undefined, options?: MergeOptions): T;
|
|
90
|
+
/**
|
|
91
|
+
* originalが自身のプロパティとして持つキーに限定して、sourceのプロパティを深くマージする(破壊)
|
|
92
|
+
* 値が undefined でもキーがあれば対象になる。入れ子のプレーンオブジェクトにも同じ限定を適用する
|
|
93
|
+
* original側が null やプリミティブで形を持たない場合は、source側の複製を設定する
|
|
94
|
+
* そのほかの規則は merge と同じ
|
|
95
|
+
*
|
|
96
|
+
* @param {T} original マージ先。この引数が書き換えられる
|
|
97
|
+
* @param {object | null | undefined} source マージするプロパティを持つオブジェクト
|
|
98
|
+
* @param {MergeOptions} [options]
|
|
99
|
+
* @returns {T} original
|
|
100
|
+
*/
|
|
101
|
+
export declare function transfer<T extends object>(original: T, source: object | null | undefined, options?: MergeOptions): T;
|
|
102
|
+
/**
|
|
103
|
+
* originalの複製に対して、originalが持つキーに限定してsourceのプロパティを深くマージした新しいオブジェクトを返す(非破壊)
|
|
104
|
+
* マージの規則は transfer と同じ
|
|
105
|
+
*
|
|
106
|
+
* @param {T} original マージ元。この引数は書き換えない
|
|
107
|
+
* @param {object | null | undefined} source マージするプロパティを持つオブジェクト
|
|
108
|
+
* @param {MergeOptions} [options]
|
|
109
|
+
* @returns {T} マージした新しいオブジェクト
|
|
110
|
+
*/
|
|
111
|
+
export declare function cloneTransfer<T extends object>(original: T, source: object | null | undefined, options?: MergeOptions): T;
|
|
112
|
+
/**
|
|
113
|
+
* 値を人が読める文字列にする。値の中身は変えない
|
|
114
|
+
* ・null / undefined は 'null' / 'undefined'
|
|
115
|
+
* ・文字列はそのまま
|
|
116
|
+
* ・number / boolean / bigint / symbol は String(value)
|
|
117
|
+
* ・関数は '[Function: name]'
|
|
118
|
+
* ・Error は 'name: message'。スタックは含めない
|
|
119
|
+
* ・ArrayBuffer / 型付き配列はUTF-8の文字列として復号する
|
|
120
|
+
* ・toJSON を持つオブジェクト(Dateなど)は toJSON() の結果を変換する
|
|
121
|
+
* ・Map は { key: value } のオブジェクト、Set は要素の配列としてJSON化する。Mapのキーもこの規則で文字列にする
|
|
122
|
+
* ・それ以外のオブジェクトと配列はインデント2のJSON。循環参照は '[Circular]' になる
|
|
123
|
+
* Error / 関数 / Map / Set / bigint の変換は、オブジェクトの中に入っている値にも適用する
|
|
124
|
+
*
|
|
125
|
+
* @param {any} value
|
|
126
|
+
* @returns {string}
|
|
127
|
+
*/
|
|
128
|
+
export declare function toString(value: any): string;
|
|
129
|
+
/**
|
|
130
|
+
* 値のハッシュ値を返す
|
|
131
|
+
* 値を toStableString で文字列にし、そのUTF-8のバイト列をFNV-1a(32bit)でハッシュ化する
|
|
132
|
+
* distinct で同じとみなされる値は同じハッシュ値になる
|
|
133
|
+
*
|
|
134
|
+
* @param {any} value
|
|
135
|
+
* @returns {number} 0 〜 4294967295 の整数
|
|
136
|
+
*/
|
|
137
|
+
export declare function hashCode(value: any): number;
|
|
138
|
+
/**
|
|
139
|
+
* 配列から重複する要素を除いた新しい配列を返す
|
|
140
|
+
* ・null / undefined の要素は除く
|
|
141
|
+
* ・オブジェクトはJSON化した文字列で比較する。プロパティの順序は区別せず、配列の順序は区別する(hashCode と同じ文字列表現)
|
|
142
|
+
* ・プリミティブは型も区別する。'1' と 1 は別の要素として残る
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* distinct([1, 3, 3, 2, 1]); // [1, 3, 2]
|
|
146
|
+
* distinct([{ id: 1, name: 'a' }, { id: 1, name: 'b' }], { distinct: a => a.id }); // [{ id: 1, name: 'a' }]
|
|
147
|
+
*
|
|
148
|
+
* @param {T[]} array
|
|
149
|
+
* @param {*} [options]
|
|
150
|
+
* ├ distinct 重複判定に使う値を返す関数。戻り値が null / undefined の要素は除く
|
|
151
|
+
* └ exclude trueを返した要素は除く
|
|
152
|
+
* @returns {T[]}
|
|
153
|
+
*/
|
|
154
|
+
export declare function distinct<T>(array: T[], options?: {
|
|
155
|
+
distinct?: (a: T) => any;
|
|
156
|
+
exclude?: (a: T) => boolean;
|
|
157
|
+
}): T[];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import "./json-util-YX7xSF6R.js";
|
|
2
|
+
import { a as r, c as t, b as c, d as n, e as o, f as i, g, h as d, m as f, t as h, i as l } from "./object-util-DhGi-PmA.js";
|
|
3
|
+
export {
|
|
4
|
+
r as appendObjectHierarchy,
|
|
5
|
+
t as cloneMerge,
|
|
6
|
+
c as cloneObject,
|
|
7
|
+
n as cloneTransfer,
|
|
8
|
+
o as create,
|
|
9
|
+
i as distinct,
|
|
10
|
+
g as getValue,
|
|
11
|
+
d as hashCode,
|
|
12
|
+
f as merge,
|
|
13
|
+
h as toString,
|
|
14
|
+
l as transfer
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=object-util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object-util.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
function f(e) {
|
|
2
|
+
return e && e.trim();
|
|
3
|
+
}
|
|
4
|
+
function g(e) {
|
|
5
|
+
return e && e.replace(/^[a-z]/, (r) => r.toUpperCase());
|
|
6
|
+
}
|
|
7
|
+
function o(e, r) {
|
|
8
|
+
if (!e || !r || !r.length)
|
|
9
|
+
return e;
|
|
10
|
+
let l = e;
|
|
11
|
+
for (let i = 0; i < r.length; i++) {
|
|
12
|
+
const n = r[i], a = String(typeof n == "symbol" ? n.description : n);
|
|
13
|
+
l = l.replace(new RegExp(`\\{${i}\\}`, "g"), a);
|
|
14
|
+
}
|
|
15
|
+
return l;
|
|
16
|
+
}
|
|
17
|
+
function y(e) {
|
|
18
|
+
const r = e.base?.replace(/\/+$/, "") ?? "", l = e.segments?.map((a, u) => {
|
|
19
|
+
let t = String(a);
|
|
20
|
+
return !e.base && u === 0 ? t = t.replace(/^\/+/g, "/") : t = t.replace(/^\/+/g, ""), t.replace(/\/+$/g, "");
|
|
21
|
+
}) ?? [], i = [r, ...l].filter(Boolean).join("/");
|
|
22
|
+
let n = "";
|
|
23
|
+
if (e.query)
|
|
24
|
+
if (typeof e.query == "string")
|
|
25
|
+
n = e.query.startsWith("?") ? e.query : `?${e.query}`;
|
|
26
|
+
else {
|
|
27
|
+
const a = new URLSearchParams();
|
|
28
|
+
for (const [t, c] of Object.entries(e.query))
|
|
29
|
+
if (Array.isArray(c))
|
|
30
|
+
for (const s of c)
|
|
31
|
+
a.append(t, String(s));
|
|
32
|
+
else c != null && a.append(t, String(c));
|
|
33
|
+
const u = a.toString();
|
|
34
|
+
u && (n = `?${u}`);
|
|
35
|
+
}
|
|
36
|
+
return `${i}${n}`;
|
|
37
|
+
}
|
|
38
|
+
const m = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
39
|
+
__proto__: null,
|
|
40
|
+
buildUrl: y,
|
|
41
|
+
capitalize: g,
|
|
42
|
+
messageFormat: o,
|
|
43
|
+
trim: f
|
|
44
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
45
|
+
export {
|
|
46
|
+
y as b,
|
|
47
|
+
g as c,
|
|
48
|
+
o as m,
|
|
49
|
+
m as s,
|
|
50
|
+
f as t
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=string-util-Cw0VgbIH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"string-util-Cw0VgbIH.js","sources":["../src/string-util.ts"],"sourcesContent":["/**\n * URLのクエリに指定できる値\n */\nexport type QueryValue = string | number | boolean | undefined;\n\n/**\n * URLのクエリをキーと値の組で表したもの\n */\nexport type QueryObject = Record<string, QueryValue | QueryValue[]>;\n\n/**\n * 文字列の前後の空白を取り除く\n * null, undefined, 空文字の場合はそのまま元の値を返す\n *\n * @param {string} str\n * @returns {string}\n */\nexport function trim(str: string): string {\n if (!str) {\n return str;\n }\n return str.trim();\n}\n\n/**\n * 文字列の先頭が英小文字の場合、先頭文字を大文字にする\n * null, undefined, 空文字の場合はそのまま元の値を返す\n *\n * @param {string} str\n * @returns {string}\n */\nexport function capitalize(str: string): string {\n if (!str) {\n return str;\n }\n return str.replace(/^[a-z]/, c => c.toUpperCase());\n}\n\n/**\n * 文字列内の {0} {1} の部分を、配列の添字に該当するパラメータで置換する\n *\n * @param {string} str 元の文字列\n * @param {(string | number | boolean | symbol)[]} [replacements] 置換パラメータ\n * @returns {string}\n */\nexport function messageFormat(str: string, replacements?: (string | number | boolean | symbol)[]): string {\n if (!str || !replacements || !replacements.length) {\n return str;\n }\n let buf = str;\n for (let i = 0; i < replacements.length; i++) {\n const replacement = replacements[i];\n const value = typeof replacement === 'symbol'\n ? String(replacement.description)\n : String(replacement);\n buf = buf.replace(new RegExp(`\\\\{${i}\\\\}`, 'g'), value);\n }\n return buf;\n}\n\n/**\n * base, segments, queryを連結してURLを生成する\n *\n * @param {*} options\n * ├ base {string} https://example.com のようなプロトコル付きURL\n * ├ segments {(string | number)[]} セグメント\n * baseが未指定で配列の先頭要素がスラッシュで始まる場合、生成されるパスはスラッシュで始まる絶対パスを示す\n * baseが未指定で配列の先頭要素がスラッシュで始まらない場合、生成されるパスはスラッシュで始まらない相対パスを示す\n * baseが指定されている場合は、先頭要素のスラッシュの有無に関わらずbaseに続くURLとして生成する。URLクラスの挙動とは異なる\n * ├ query {string | QueryObject}\n * 文字列: ?date=2022-11-02¶m=abc のようなクエリ。先頭に?がない場合は補完する。エンコードはしない\n * キーと値の組: { date: '2022-11-02', param: 'abc' }。値が配列の場合は同じキーで複数指定する\n * @returns {string}\n */\nexport function buildUrl(options: {\n base?: string;\n segments?: (string | number)[];\n query?: string | QueryObject;\n}): string {\n const base = options.base?.replace(/\\/+$/, '') ?? '';\n const segments = options.segments?.map((seg, idx) => {\n let normalizedSegment = String(seg);\n if (!options.base && idx === 0) {\n // 絶対パスか相対パスかを表すため、baseがない場合の先頭要素だけはスラッシュを1つ残す\n normalizedSegment = normalizedSegment.replace(/^\\/+/g, '/');\n } else {\n normalizedSegment = normalizedSegment.replace(/^\\/+/g, '');\n }\n return normalizedSegment.replace(/\\/+$/g, '');\n }) ?? [];\n const path = [base, ...segments].filter(Boolean).join('/');\n\n let qs = '';\n if (options.query) {\n if (typeof options.query === 'string') {\n qs = options.query.startsWith('?') ? options.query : `?${options.query}`;\n } else {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(options.query)) {\n if (Array.isArray(value)) {\n for (const v of value) {\n params.append(key, String(v));\n }\n } else if (value != null) {\n params.append(key, String(value));\n }\n }\n const strParams = params.toString();\n if (strParams) {\n qs = `?${strParams}`;\n }\n }\n }\n return `${path}${qs}`;\n}\n"],"names":["trim","str","capitalize","c","messageFormat","replacements","buf","replacement","value","buildUrl","options","base","segments","seg","idx","normalizedSegment","path","qs","params","key","v","strParams"],"mappings":"AAiBO,SAASA,EAAKC,GAAqB;AACxC,SAAKA,KAGEA,EAAI,KAAA;AACb;AASO,SAASC,EAAWD,GAAqB;AAC9C,SAAKA,KAGEA,EAAI,QAAQ,UAAU,CAAAE,MAAKA,EAAE,aAAa;AACnD;AASO,SAASC,EAAcH,GAAaI,GAA+D;AACxG,MAAI,CAACJ,KAAO,CAACI,KAAgB,CAACA,EAAa;AACzC,WAAOJ;AAET,MAAIK,IAAML;AACV,WAAS,IAAI,GAAG,IAAII,EAAa,QAAQ,KAAK;AAC5C,UAAME,IAAcF,EAAa,CAAC,GAC5BG,IACF,OADU,OAAOD,KAAgB,WAC1BA,EAAY,cACZA,CADuB;AAElC,IAAAD,IAAMA,EAAI,QAAQ,IAAI,OAAO,MAAM,CAAC,OAAO,GAAG,GAAGE,CAAK;AAAA,EACxD;AACA,SAAOF;AACT;AAgBO,SAASG,EAASC,GAId;AACT,QAAMC,IAAOD,EAAQ,MAAM,QAAQ,QAAQ,EAAE,KAAK,IAC5CE,IAAWF,EAAQ,UAAU,IAAI,CAACG,GAAKC,MAAQ;AACnD,QAAIC,IAAoB,OAAOF,CAAG;AAClC,WAAI,CAACH,EAAQ,QAAQI,MAAQ,IAE3BC,IAAoBA,EAAkB,QAAQ,SAAS,GAAG,IAE1DA,IAAoBA,EAAkB,QAAQ,SAAS,EAAE,GAEpDA,EAAkB,QAAQ,SAAS,EAAE;AAAA,EAC9C,CAAC,KAAK,CAAA,GACAC,IAAO,CAACL,GAAM,GAAGC,CAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAEzD,MAAIK,IAAK;AACT,MAAIP,EAAQ;AACV,QAAI,OAAOA,EAAQ,SAAU;AAC3B,MAAAO,IAAKP,EAAQ,MAAM,WAAW,GAAG,IAAIA,EAAQ,QAAQ,IAAIA,EAAQ,KAAK;AAAA,SACjE;AACL,YAAMQ,IAAS,IAAI,gBAAA;AACnB,iBAAW,CAACC,GAAKX,CAAK,KAAK,OAAO,QAAQE,EAAQ,KAAK;AACrD,YAAI,MAAM,QAAQF,CAAK;AACrB,qBAAWY,KAAKZ;AACd,YAAAU,EAAO,OAAOC,GAAK,OAAOC,CAAC,CAAC;AAAA,YAEhC,CAAWZ,KAAS,QAClBU,EAAO,OAAOC,GAAK,OAAOX,CAAK,CAAC;AAGpC,YAAMa,IAAYH,EAAO,SAAA;AACzB,MAAIG,MACFJ,IAAK,IAAII,CAAS;AAAA,IAEtB;AAEF,SAAO,GAAGL,CAAI,GAAGC,CAAE;AACrB;;;;;;;;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";function f(e){return e&&e.trim()}function s(e){return e&&e.replace(/^[a-z]/,r=>r.toUpperCase())}function g(e,r){if(!e||!r||!r.length)return e;let l=e;for(let i=0;i<r.length;i++){const n=r[i],a=String(typeof n=="symbol"?n.description:n);l=l.replace(new RegExp(`\\{${i}\\}`,"g"),a)}return l}function o(e){const r=e.base?.replace(/\/+$/,"")??"",l=e.segments?.map((a,u)=>{let t=String(a);return!e.base&&u===0?t=t.replace(/^\/+/g,"/"):t=t.replace(/^\/+/g,""),t.replace(/\/+$/g,"")})??[],i=[r,...l].filter(Boolean).join("/");let n="";if(e.query)if(typeof e.query=="string")n=e.query.startsWith("?")?e.query:`?${e.query}`;else{const a=new URLSearchParams;for(const[t,c]of Object.entries(e.query))if(Array.isArray(c))for(const m of c)a.append(t,String(m));else c!=null&&a.append(t,String(c));const u=a.toString();u&&(n=`?${u}`)}return`${i}${n}`}const y=Object.freeze(Object.defineProperty({__proto__:null,buildUrl:o,capitalize:s,messageFormat:g,trim:f},Symbol.toStringTag,{value:"Module"}));exports.buildUrl=o;exports.capitalize=s;exports.messageFormat=g;exports.stringUtil=y;exports.trim=f;
|
|
2
|
+
//# sourceMappingURL=string-util-w2I5EYuY.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"string-util-w2I5EYuY.cjs","sources":["../src/string-util.ts"],"sourcesContent":["/**\n * URLのクエリに指定できる値\n */\nexport type QueryValue = string | number | boolean | undefined;\n\n/**\n * URLのクエリをキーと値の組で表したもの\n */\nexport type QueryObject = Record<string, QueryValue | QueryValue[]>;\n\n/**\n * 文字列の前後の空白を取り除く\n * null, undefined, 空文字の場合はそのまま元の値を返す\n *\n * @param {string} str\n * @returns {string}\n */\nexport function trim(str: string): string {\n if (!str) {\n return str;\n }\n return str.trim();\n}\n\n/**\n * 文字列の先頭が英小文字の場合、先頭文字を大文字にする\n * null, undefined, 空文字の場合はそのまま元の値を返す\n *\n * @param {string} str\n * @returns {string}\n */\nexport function capitalize(str: string): string {\n if (!str) {\n return str;\n }\n return str.replace(/^[a-z]/, c => c.toUpperCase());\n}\n\n/**\n * 文字列内の {0} {1} の部分を、配列の添字に該当するパラメータで置換する\n *\n * @param {string} str 元の文字列\n * @param {(string | number | boolean | symbol)[]} [replacements] 置換パラメータ\n * @returns {string}\n */\nexport function messageFormat(str: string, replacements?: (string | number | boolean | symbol)[]): string {\n if (!str || !replacements || !replacements.length) {\n return str;\n }\n let buf = str;\n for (let i = 0; i < replacements.length; i++) {\n const replacement = replacements[i];\n const value = typeof replacement === 'symbol'\n ? String(replacement.description)\n : String(replacement);\n buf = buf.replace(new RegExp(`\\\\{${i}\\\\}`, 'g'), value);\n }\n return buf;\n}\n\n/**\n * base, segments, queryを連結してURLを生成する\n *\n * @param {*} options\n * ├ base {string} https://example.com のようなプロトコル付きURL\n * ├ segments {(string | number)[]} セグメント\n * baseが未指定で配列の先頭要素がスラッシュで始まる場合、生成されるパスはスラッシュで始まる絶対パスを示す\n * baseが未指定で配列の先頭要素がスラッシュで始まらない場合、生成されるパスはスラッシュで始まらない相対パスを示す\n * baseが指定されている場合は、先頭要素のスラッシュの有無に関わらずbaseに続くURLとして生成する。URLクラスの挙動とは異なる\n * ├ query {string | QueryObject}\n * 文字列: ?date=2022-11-02¶m=abc のようなクエリ。先頭に?がない場合は補完する。エンコードはしない\n * キーと値の組: { date: '2022-11-02', param: 'abc' }。値が配列の場合は同じキーで複数指定する\n * @returns {string}\n */\nexport function buildUrl(options: {\n base?: string;\n segments?: (string | number)[];\n query?: string | QueryObject;\n}): string {\n const base = options.base?.replace(/\\/+$/, '') ?? '';\n const segments = options.segments?.map((seg, idx) => {\n let normalizedSegment = String(seg);\n if (!options.base && idx === 0) {\n // 絶対パスか相対パスかを表すため、baseがない場合の先頭要素だけはスラッシュを1つ残す\n normalizedSegment = normalizedSegment.replace(/^\\/+/g, '/');\n } else {\n normalizedSegment = normalizedSegment.replace(/^\\/+/g, '');\n }\n return normalizedSegment.replace(/\\/+$/g, '');\n }) ?? [];\n const path = [base, ...segments].filter(Boolean).join('/');\n\n let qs = '';\n if (options.query) {\n if (typeof options.query === 'string') {\n qs = options.query.startsWith('?') ? options.query : `?${options.query}`;\n } else {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(options.query)) {\n if (Array.isArray(value)) {\n for (const v of value) {\n params.append(key, String(v));\n }\n } else if (value != null) {\n params.append(key, String(value));\n }\n }\n const strParams = params.toString();\n if (strParams) {\n qs = `?${strParams}`;\n }\n }\n }\n return `${path}${qs}`;\n}\n"],"names":["trim","str","capitalize","c","messageFormat","replacements","buf","replacement","value","buildUrl","options","base","segments","seg","idx","normalizedSegment","path","qs","params","key","v","strParams"],"mappings":"aAiBO,SAASA,EAAKC,EAAqB,CACxC,OAAKA,GAGEA,EAAI,KAAA,CACb,CASO,SAASC,EAAWD,EAAqB,CAC9C,OAAKA,GAGEA,EAAI,QAAQ,SAAUE,GAAKA,EAAE,aAAa,CACnD,CASO,SAASC,EAAcH,EAAaI,EAA+D,CACxG,GAAI,CAACJ,GAAO,CAACI,GAAgB,CAACA,EAAa,OACzC,OAAOJ,EAET,IAAIK,EAAML,EACV,QAAS,EAAI,EAAG,EAAII,EAAa,OAAQ,IAAK,CAC5C,MAAME,EAAcF,EAAa,CAAC,EAC5BG,EACF,OADU,OAAOD,GAAgB,SAC1BA,EAAY,YACZA,CADuB,EAElCD,EAAMA,EAAI,QAAQ,IAAI,OAAO,MAAM,CAAC,MAAO,GAAG,EAAGE,CAAK,CACxD,CACA,OAAOF,CACT,CAgBO,SAASG,EAASC,EAId,CACT,MAAMC,EAAOD,EAAQ,MAAM,QAAQ,OAAQ,EAAE,GAAK,GAC5CE,EAAWF,EAAQ,UAAU,IAAI,CAACG,EAAKC,IAAQ,CACnD,IAAIC,EAAoB,OAAOF,CAAG,EAClC,MAAI,CAACH,EAAQ,MAAQI,IAAQ,EAE3BC,EAAoBA,EAAkB,QAAQ,QAAS,GAAG,EAE1DA,EAAoBA,EAAkB,QAAQ,QAAS,EAAE,EAEpDA,EAAkB,QAAQ,QAAS,EAAE,CAC9C,CAAC,GAAK,CAAA,EACAC,EAAO,CAACL,EAAM,GAAGC,CAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,EAEzD,IAAIK,EAAK,GACT,GAAIP,EAAQ,MACV,GAAI,OAAOA,EAAQ,OAAU,SAC3BO,EAAKP,EAAQ,MAAM,WAAW,GAAG,EAAIA,EAAQ,MAAQ,IAAIA,EAAQ,KAAK,OACjE,CACL,MAAMQ,EAAS,IAAI,gBACnB,SAAW,CAACC,EAAKX,CAAK,IAAK,OAAO,QAAQE,EAAQ,KAAK,EACrD,GAAI,MAAM,QAAQF,CAAK,EACrB,UAAWY,KAAKZ,EACdU,EAAO,OAAOC,EAAK,OAAOC,CAAC,CAAC,OAErBZ,GAAS,MAClBU,EAAO,OAAOC,EAAK,OAAOX,CAAK,CAAC,EAGpC,MAAMa,EAAYH,EAAO,SAAA,EACrBG,IACFJ,EAAK,IAAII,CAAS,GAEtB,CAEF,MAAO,GAAGL,CAAI,GAAGC,CAAE,EACrB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./string-util-w2I5EYuY.cjs");exports.buildUrl=e.buildUrl;exports.capitalize=e.capitalize;exports.messageFormat=e.messageFormat;exports.trim=e.trim;
|
|
2
|
+
//# sourceMappingURL=string-util.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"string-util.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URLのクエリに指定できる値
|
|
3
|
+
*/
|
|
4
|
+
export type QueryValue = string | number | boolean | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* URLのクエリをキーと値の組で表したもの
|
|
7
|
+
*/
|
|
8
|
+
export type QueryObject = Record<string, QueryValue | QueryValue[]>;
|
|
9
|
+
/**
|
|
10
|
+
* 文字列の前後の空白を取り除く
|
|
11
|
+
* null, undefined, 空文字の場合はそのまま元の値を返す
|
|
12
|
+
*
|
|
13
|
+
* @param {string} str
|
|
14
|
+
* @returns {string}
|
|
15
|
+
*/
|
|
16
|
+
export declare function trim(str: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* 文字列の先頭が英小文字の場合、先頭文字を大文字にする
|
|
19
|
+
* null, undefined, 空文字の場合はそのまま元の値を返す
|
|
20
|
+
*
|
|
21
|
+
* @param {string} str
|
|
22
|
+
* @returns {string}
|
|
23
|
+
*/
|
|
24
|
+
export declare function capitalize(str: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* 文字列内の {0} {1} の部分を、配列の添字に該当するパラメータで置換する
|
|
27
|
+
*
|
|
28
|
+
* @param {string} str 元の文字列
|
|
29
|
+
* @param {(string | number | boolean | symbol)[]} [replacements] 置換パラメータ
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*/
|
|
32
|
+
export declare function messageFormat(str: string, replacements?: (string | number | boolean | symbol)[]): string;
|
|
33
|
+
/**
|
|
34
|
+
* base, segments, queryを連結してURLを生成する
|
|
35
|
+
*
|
|
36
|
+
* @param {*} options
|
|
37
|
+
* ├ base {string} https://example.com のようなプロトコル付きURL
|
|
38
|
+
* ├ segments {(string | number)[]} セグメント
|
|
39
|
+
* baseが未指定で配列の先頭要素がスラッシュで始まる場合、生成されるパスはスラッシュで始まる絶対パスを示す
|
|
40
|
+
* baseが未指定で配列の先頭要素がスラッシュで始まらない場合、生成されるパスはスラッシュで始まらない相対パスを示す
|
|
41
|
+
* baseが指定されている場合は、先頭要素のスラッシュの有無に関わらずbaseに続くURLとして生成する。URLクラスの挙動とは異なる
|
|
42
|
+
* ├ query {string | QueryObject}
|
|
43
|
+
* 文字列: ?date=2022-11-02¶m=abc のようなクエリ。先頭に?がない場合は補完する。エンコードはしない
|
|
44
|
+
* キーと値の組: { date: '2022-11-02', param: 'abc' }。値が配列の場合は同じキーで複数指定する
|
|
45
|
+
* @returns {string}
|
|
46
|
+
*/
|
|
47
|
+
export declare function buildUrl(options: {
|
|
48
|
+
base?: string;
|
|
49
|
+
segments?: (string | number)[];
|
|
50
|
+
query?: string | QueryObject;
|
|
51
|
+
}): string;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URLのクエリに指定できる値
|
|
3
|
+
*/
|
|
4
|
+
export type QueryValue = string | number | boolean | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* URLのクエリをキーと値の組で表したもの
|
|
7
|
+
*/
|
|
8
|
+
export type QueryObject = Record<string, QueryValue | QueryValue[]>;
|
|
9
|
+
/**
|
|
10
|
+
* 文字列の前後の空白を取り除く
|
|
11
|
+
* null, undefined, 空文字の場合はそのまま元の値を返す
|
|
12
|
+
*
|
|
13
|
+
* @param {string} str
|
|
14
|
+
* @returns {string}
|
|
15
|
+
*/
|
|
16
|
+
export declare function trim(str: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* 文字列の先頭が英小文字の場合、先頭文字を大文字にする
|
|
19
|
+
* null, undefined, 空文字の場合はそのまま元の値を返す
|
|
20
|
+
*
|
|
21
|
+
* @param {string} str
|
|
22
|
+
* @returns {string}
|
|
23
|
+
*/
|
|
24
|
+
export declare function capitalize(str: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* 文字列内の {0} {1} の部分を、配列の添字に該当するパラメータで置換する
|
|
27
|
+
*
|
|
28
|
+
* @param {string} str 元の文字列
|
|
29
|
+
* @param {(string | number | boolean | symbol)[]} [replacements] 置換パラメータ
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*/
|
|
32
|
+
export declare function messageFormat(str: string, replacements?: (string | number | boolean | symbol)[]): string;
|
|
33
|
+
/**
|
|
34
|
+
* base, segments, queryを連結してURLを生成する
|
|
35
|
+
*
|
|
36
|
+
* @param {*} options
|
|
37
|
+
* ├ base {string} https://example.com のようなプロトコル付きURL
|
|
38
|
+
* ├ segments {(string | number)[]} セグメント
|
|
39
|
+
* baseが未指定で配列の先頭要素がスラッシュで始まる場合、生成されるパスはスラッシュで始まる絶対パスを示す
|
|
40
|
+
* baseが未指定で配列の先頭要素がスラッシュで始まらない場合、生成されるパスはスラッシュで始まらない相対パスを示す
|
|
41
|
+
* baseが指定されている場合は、先頭要素のスラッシュの有無に関わらずbaseに続くURLとして生成する。URLクラスの挙動とは異なる
|
|
42
|
+
* ├ query {string | QueryObject}
|
|
43
|
+
* 文字列: ?date=2022-11-02¶m=abc のようなクエリ。先頭に?がない場合は補完する。エンコードはしない
|
|
44
|
+
* キーと値の組: { date: '2022-11-02', param: 'abc' }。値が配列の場合は同じキーで複数指定する
|
|
45
|
+
* @returns {string}
|
|
46
|
+
*/
|
|
47
|
+
export declare function buildUrl(options: {
|
|
48
|
+
base?: string;
|
|
49
|
+
segments?: (string | number)[];
|
|
50
|
+
query?: string | QueryObject;
|
|
51
|
+
}): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"string-util.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digitalwalletcorp/utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "A javascript utility.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.cjs",
|
|
@@ -30,8 +30,11 @@
|
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "vite build",
|
|
33
|
+
"yarn:dedupe": "npx yarn-deduplicate --strategy highest yarn.lock",
|
|
33
34
|
"install:dev": "rm -rf lib dest && find node_modules -mindepth 1 -delete && yarn install",
|
|
34
|
-
"
|
|
35
|
+
"tsc": "tsc --noEmit -p tsconfig.json",
|
|
36
|
+
"lint": "eslint .",
|
|
37
|
+
"lint:fix": "eslint --fix .",
|
|
35
38
|
"version:patch": "npm version patch",
|
|
36
39
|
"version:minor": "npm version minor",
|
|
37
40
|
"version:major": "npm version major",
|
|
@@ -41,12 +44,9 @@
|
|
|
41
44
|
"test:unit": "vitest run --coverage"
|
|
42
45
|
},
|
|
43
46
|
"keywords": [
|
|
44
|
-
"
|
|
45
|
-
"utils",
|
|
46
|
-
"number",
|
|
47
|
-
"decimal"
|
|
47
|
+
"utils"
|
|
48
48
|
],
|
|
49
|
-
"author": "
|
|
49
|
+
"author": "Digital Wallet Corporation",
|
|
50
50
|
"license": "MIT",
|
|
51
51
|
"repository": {
|
|
52
52
|
"type": "git",
|
|
@@ -56,20 +56,38 @@
|
|
|
56
56
|
"bugs": {
|
|
57
57
|
"url": "https://github.com/digitalwalletcorp/utils/issues"
|
|
58
58
|
},
|
|
59
|
+
"engines": {
|
|
60
|
+
"node": ">=21"
|
|
61
|
+
},
|
|
59
62
|
"files": [
|
|
60
63
|
"lib/**/*",
|
|
61
64
|
"src/**/*"
|
|
62
65
|
],
|
|
63
66
|
"dependencies": {
|
|
64
|
-
"big.js": "7.0.1"
|
|
67
|
+
"big.js": "7.0.1",
|
|
68
|
+
"crypto-js": "4.2.0",
|
|
69
|
+
"diff": "8.0.2",
|
|
70
|
+
"luxon": "3.7.2"
|
|
65
71
|
},
|
|
66
72
|
"devDependencies": {
|
|
73
|
+
"@stylistic/eslint-plugin": "5.10.0",
|
|
67
74
|
"@types/big.js": "6.2.2",
|
|
75
|
+
"@types/crypto-js": "4.2.2",
|
|
76
|
+
"@types/luxon": "3.7.1",
|
|
68
77
|
"@types/node": "24.13.6",
|
|
69
78
|
"@vitest/coverage-v8": "3.2.4",
|
|
79
|
+
"eslint": "10.11.0",
|
|
80
|
+
"globals": "17.13.0",
|
|
70
81
|
"typescript": "6.0.3",
|
|
82
|
+
"typescript-eslint": "8.71.0",
|
|
71
83
|
"vite": "7.3.6",
|
|
72
84
|
"vite-plugin-dts": "5.1.0",
|
|
73
85
|
"vitest": "3.2.4"
|
|
86
|
+
},
|
|
87
|
+
"resolutions": {
|
|
88
|
+
"eslint": "10.11.0",
|
|
89
|
+
"typescript-eslint": "8.71.0",
|
|
90
|
+
"@stylistic/eslint-plugin": "5.10.0",
|
|
91
|
+
"globals": "17.13.0"
|
|
74
92
|
}
|
|
75
93
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import CryptoJS from 'crypto-js';
|
|
2
|
+
|
|
3
|
+
const CHARSETS = {
|
|
4
|
+
ascii: `!"#$%&'()*+,-./0123456789:;<=>?@[]^_\`abcdefghijklmnopqrstuvwxyz{|}~`,
|
|
5
|
+
number: '0123456789',
|
|
6
|
+
alphabet: 'abcdefghijklmnopqrstuvwxyz',
|
|
7
|
+
alphanum: '0123456789abcdefghijklmnopqrstuvwxyz',
|
|
8
|
+
hex: '0123456789abcdef'
|
|
9
|
+
} as const;
|
|
10
|
+
|
|
11
|
+
const randomBytes = (size: number): Uint8Array => globalThis.crypto.getRandomValues(new Uint8Array(size));
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 文字列をSHA-256でハッシュ化し、大文字の16進数文字列で返す
|
|
15
|
+
*
|
|
16
|
+
* @param {string} str
|
|
17
|
+
* @returns {string}
|
|
18
|
+
*/
|
|
19
|
+
export function toSha256(str: string): string {
|
|
20
|
+
return CryptoJS.SHA256(str).toString().toUpperCase();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* ランダムな文字列を生成する
|
|
25
|
+
* 大文字と小文字は別の文字として扱う
|
|
26
|
+
* caseを指定しない場合は生成対象の文字セットに大文字と小文字の両方を含めるため、'a'と'A'の出現率は同じ確率になる
|
|
27
|
+
*
|
|
28
|
+
* @param {number} length 生成する文字列の桁数
|
|
29
|
+
* @param {*} [options]
|
|
30
|
+
* ├ charset 'ascii' | 'number' | 'alphabet' | 'alphanum' | 'hex' 未指定の場合はASCIIの記号・数字・英字(スペースとバックスラッシュを除く)
|
|
31
|
+
* ├ case 'upperCase' | 'lowerCase' 英字を大文字のみ・小文字のみにする。未指定の場合は大文字小文字混在
|
|
32
|
+
* ├ rejectStartsWithZero trueを指定した場合、0始まりの文字列を生成しない
|
|
33
|
+
* ├ includeChars 文字セットに追加する文字。大文字小文字を区別する
|
|
34
|
+
* ├ excludeChars 文字セットから除外する文字。大文字小文字は区別する
|
|
35
|
+
* @returns {string}
|
|
36
|
+
*/
|
|
37
|
+
export function generateRandomString(length: number, options?: {
|
|
38
|
+
charset?: 'ascii' | 'number' | 'alphabet' | 'alphanum' | 'hex';
|
|
39
|
+
case?: 'upperCase' | 'lowerCase';
|
|
40
|
+
rejectStartsWithZero?: boolean;
|
|
41
|
+
includeChars?: string | string[];
|
|
42
|
+
excludeChars?: string | string[];
|
|
43
|
+
}): string {
|
|
44
|
+
if (!Number.isInteger(length) || length < 0) {
|
|
45
|
+
throw new Error('crypto-util.generateRandomString: length must be a non-negative integer');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const lower = CHARSETS[options?.charset ?? 'ascii'];
|
|
49
|
+
const upper = lower.toUpperCase();
|
|
50
|
+
let pool = options?.case === 'upperCase'
|
|
51
|
+
? upper
|
|
52
|
+
: options?.case === 'lowerCase'
|
|
53
|
+
? lower
|
|
54
|
+
: lower + upper;
|
|
55
|
+
const includeChars = options?.includeChars;
|
|
56
|
+
if (includeChars) {
|
|
57
|
+
// 追加文字の指定がある場合
|
|
58
|
+
pool += Array.isArray(includeChars) ? includeChars.join('') : includeChars;
|
|
59
|
+
}
|
|
60
|
+
const excludeChars = options?.excludeChars;
|
|
61
|
+
if (excludeChars) {
|
|
62
|
+
// 除外文字の指定がある場合
|
|
63
|
+
const excluded = new Set(Array.isArray(excludeChars) ? excludeChars : Array.from(excludeChars));
|
|
64
|
+
pool = Array.from(pool).filter(a => !excluded.has(a)).join('');
|
|
65
|
+
}
|
|
66
|
+
const characters = Array.from(new Set(pool));
|
|
67
|
+
if (!characters.length) {
|
|
68
|
+
throw new Error('crypto-util.generateRandomString: no characters left after applying excludeChars');
|
|
69
|
+
}
|
|
70
|
+
// 256を文字種の数で割り切れる範囲のバイトだけを使い、文字ごとの出現率を揃える
|
|
71
|
+
const maxAcceptableValue = Math.floor(256 / characters.length) * characters.length - 1;
|
|
72
|
+
let result = '';
|
|
73
|
+
do {
|
|
74
|
+
result = '';
|
|
75
|
+
while (result.length < length) {
|
|
76
|
+
for (const byte of randomBytes(length - result.length)) {
|
|
77
|
+
if (byte <= maxAcceptableValue) {
|
|
78
|
+
result += characters[byte % characters.length];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} while (options?.rejectStartsWithZero && result.startsWith('0'));
|
|
83
|
+
return result;
|
|
84
|
+
}
|