@simplysm/core-common 13.0.82 → 13.0.84
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 +35 -0
- package/dist/utils/num.d.ts +1 -1
- package/docs/byte-utilities.md +55 -0
- package/docs/date-format-utilities.md +96 -0
- package/docs/environment.md +35 -0
- package/docs/error-utilities.md +35 -0
- package/docs/errors.md +79 -0
- package/docs/extensions.md +201 -0
- package/docs/features.md +88 -0
- package/docs/json-utilities.md +57 -0
- package/docs/number-utilities.md +76 -0
- package/docs/object-utilities.md +165 -0
- package/docs/path-utilities.md +54 -0
- package/docs/primitive-utilities.md +40 -0
- package/docs/string-utilities.md +79 -0
- package/docs/template-strings.md +105 -0
- package/docs/transfer-utilities.md +53 -0
- package/docs/types.md +242 -0
- package/docs/wait-utilities.md +50 -0
- package/docs/xml-utilities.md +48 -0
- package/docs/zip-archive.md +61 -0
- package/package.json +1 -1
- package/src/utils/num.ts +1 -1
- package/src/utils/transferable.ts +1 -1
package/docs/types.md
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# Types
|
|
2
|
+
|
|
3
|
+
Immutable date/time classes, UUID, auto-expiring map, and shared type aliases.
|
|
4
|
+
|
|
5
|
+
## DateTime
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
class DateTime {
|
|
9
|
+
constructor();
|
|
10
|
+
constructor(year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number);
|
|
11
|
+
constructor(tick: number);
|
|
12
|
+
constructor(date: Date);
|
|
13
|
+
|
|
14
|
+
static parse(str: string): DateTime;
|
|
15
|
+
|
|
16
|
+
readonly date: Date;
|
|
17
|
+
|
|
18
|
+
get year(): number;
|
|
19
|
+
get month(): number;
|
|
20
|
+
get day(): number;
|
|
21
|
+
get hour(): number;
|
|
22
|
+
get minute(): number;
|
|
23
|
+
get second(): number;
|
|
24
|
+
get millisecond(): number;
|
|
25
|
+
get tick(): number;
|
|
26
|
+
get dayOfWeek(): number;
|
|
27
|
+
get timezoneOffsetMinutes(): number;
|
|
28
|
+
get isValid(): boolean;
|
|
29
|
+
|
|
30
|
+
setYear(year: number): DateTime;
|
|
31
|
+
setMonth(month: number): DateTime;
|
|
32
|
+
setDay(day: number): DateTime;
|
|
33
|
+
setHour(hour: number): DateTime;
|
|
34
|
+
setMinute(minute: number): DateTime;
|
|
35
|
+
setSecond(second: number): DateTime;
|
|
36
|
+
setMillisecond(millisecond: number): DateTime;
|
|
37
|
+
|
|
38
|
+
addYears(years: number): DateTime;
|
|
39
|
+
addMonths(months: number): DateTime;
|
|
40
|
+
addDays(days: number): DateTime;
|
|
41
|
+
addHours(hours: number): DateTime;
|
|
42
|
+
addMinutes(minutes: number): DateTime;
|
|
43
|
+
addSeconds(seconds: number): DateTime;
|
|
44
|
+
addMilliseconds(milliseconds: number): DateTime;
|
|
45
|
+
|
|
46
|
+
toFormatString(formatStr: string): string;
|
|
47
|
+
toString(): string; // "yyyy-MM-ddTHH:mm:ss.fffzzz"
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Immutable DateTime class wrapping JavaScript `Date`. Supports millisecond precision with local timezone. All setter and add methods return a new instance.
|
|
52
|
+
|
|
53
|
+
**Parsing formats:** `yyyy-MM-dd HH:mm:ss`, `yyyy-MM-dd HH:mm:ss.fff`, `yyyyMMddHHmmss`, `yyyy-MM-dd AM/PM HH:mm:ss`, ISO 8601.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## DateOnly
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
class DateOnly {
|
|
61
|
+
constructor();
|
|
62
|
+
constructor(year: number, month: number, day: number);
|
|
63
|
+
constructor(tick: number);
|
|
64
|
+
constructor(date: Date);
|
|
65
|
+
|
|
66
|
+
static parse(str: string): DateOnly;
|
|
67
|
+
static getDateByYearWeekSeq(
|
|
68
|
+
arg: { year: number; month?: number; weekSeq: number },
|
|
69
|
+
weekStartDay?: number,
|
|
70
|
+
minDaysInFirstWeek?: number,
|
|
71
|
+
): DateOnly;
|
|
72
|
+
|
|
73
|
+
readonly date: Date;
|
|
74
|
+
|
|
75
|
+
get year(): number;
|
|
76
|
+
get month(): number;
|
|
77
|
+
get day(): number;
|
|
78
|
+
get tick(): number;
|
|
79
|
+
get dayOfWeek(): number;
|
|
80
|
+
get isValid(): boolean;
|
|
81
|
+
|
|
82
|
+
setYear(year: number): DateOnly;
|
|
83
|
+
setMonth(month: number): DateOnly;
|
|
84
|
+
setDay(day: number): DateOnly;
|
|
85
|
+
|
|
86
|
+
addYears(years: number): DateOnly;
|
|
87
|
+
addMonths(months: number): DateOnly;
|
|
88
|
+
addDays(days: number): DateOnly;
|
|
89
|
+
|
|
90
|
+
getBaseYearMonthSeqForWeekSeq(weekStartDay?: number, minDaysInFirstWeek?: number): { year: number; monthSeq: number };
|
|
91
|
+
getWeekSeqStartDate(weekStartDay?: number, minDaysInFirstWeek?: number): DateOnly;
|
|
92
|
+
getWeekSeqOfYear(weekStartDay?: number, minDaysInFirstWeek?: number): { year: number; weekSeq: number };
|
|
93
|
+
getWeekSeqOfMonth(weekStartDay?: number, minDaysInFirstWeek?: number): { year: number; monthSeq: number; weekSeq: number };
|
|
94
|
+
|
|
95
|
+
toFormatString(formatStr: string): string;
|
|
96
|
+
toString(): string; // "yyyy-MM-dd"
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Immutable date-only class (no time). Includes ISO 8601 week calculation utilities.
|
|
101
|
+
|
|
102
|
+
**Parsing formats:** `yyyy-MM-dd`, `yyyyMMdd`, ISO 8601.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Time
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
class Time {
|
|
110
|
+
constructor();
|
|
111
|
+
constructor(hour: number, minute: number, second?: number, millisecond?: number);
|
|
112
|
+
constructor(tick: number);
|
|
113
|
+
constructor(date: Date);
|
|
114
|
+
|
|
115
|
+
static parse(str: string): Time;
|
|
116
|
+
|
|
117
|
+
get hour(): number;
|
|
118
|
+
get minute(): number;
|
|
119
|
+
get second(): number;
|
|
120
|
+
get millisecond(): number;
|
|
121
|
+
get tick(): number;
|
|
122
|
+
get isValid(): boolean;
|
|
123
|
+
|
|
124
|
+
setHour(hour: number): Time;
|
|
125
|
+
setMinute(minute: number): Time;
|
|
126
|
+
setSecond(second: number): Time;
|
|
127
|
+
setMillisecond(millisecond: number): Time;
|
|
128
|
+
|
|
129
|
+
addHours(hours: number): Time;
|
|
130
|
+
addMinutes(minutes: number): Time;
|
|
131
|
+
addSeconds(seconds: number): Time;
|
|
132
|
+
addMilliseconds(milliseconds: number): Time;
|
|
133
|
+
|
|
134
|
+
toFormatString(formatStr: string): string;
|
|
135
|
+
toString(): string; // "HH:mm:ss.fff"
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Immutable time-only class. Values exceeding 24 hours or negative values are automatically normalized with wraparound.
|
|
140
|
+
|
|
141
|
+
**Parsing formats:** `HH:mm:ss`, `HH:mm:ss.fff`, `AM/PM HH:mm:ss`, ISO 8601 (time part extracted).
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Uuid
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
class Uuid {
|
|
149
|
+
static generate(): Uuid;
|
|
150
|
+
static fromBytes(bytes: Bytes): Uuid;
|
|
151
|
+
|
|
152
|
+
constructor(uuid: string);
|
|
153
|
+
|
|
154
|
+
toString(): string;
|
|
155
|
+
toBytes(): Bytes;
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
UUID v4 class using `crypto.getRandomValues`. Validates format on construction.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## LazyGcMap
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
class LazyGcMap<TKey, TValue> {
|
|
167
|
+
constructor(options: {
|
|
168
|
+
gcInterval?: number;
|
|
169
|
+
expireTime: number;
|
|
170
|
+
onExpire?: (key: TKey, value: TValue) => void | Promise<void>;
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
get size(): number;
|
|
174
|
+
|
|
175
|
+
has(key: TKey): boolean;
|
|
176
|
+
get(key: TKey): TValue | undefined;
|
|
177
|
+
set(key: TKey, value: TValue): void;
|
|
178
|
+
delete(key: TKey): boolean;
|
|
179
|
+
clear(): void;
|
|
180
|
+
getOrCreate(key: TKey, factory: () => TValue): TValue;
|
|
181
|
+
|
|
182
|
+
values(): IterableIterator<TValue>;
|
|
183
|
+
keys(): IterableIterator<TKey>;
|
|
184
|
+
entries(): IterableIterator<[TKey, TValue]>;
|
|
185
|
+
|
|
186
|
+
dispose(): void;
|
|
187
|
+
[Symbol.dispose](): void;
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
A Map with LRU-style automatic expiration. Access time is updated on `get` and `getOrCreate`. Entries not accessed within `expireTime` are automatically removed. Must call `dispose()` or use `using` statement to stop the GC timer.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Type Aliases
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
type Bytes = Uint8Array;
|
|
199
|
+
|
|
200
|
+
type PrimitiveTypeStr = "string" | "number" | "boolean" | "DateTime" | "DateOnly" | "Time" | "Uuid" | "Bytes";
|
|
201
|
+
|
|
202
|
+
type PrimitiveType = string | number | boolean | DateTime | DateOnly | Time | Uuid | Bytes | undefined;
|
|
203
|
+
|
|
204
|
+
type DeepPartial<T> = Partial<{ [K in keyof T]: T[K] extends PrimitiveType ? T[K] : DeepPartial<T[K]> }>;
|
|
205
|
+
|
|
206
|
+
interface Type<T> extends Function {
|
|
207
|
+
new (...args: unknown[]): T;
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Usage Examples
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
import { DateTime, DateOnly, Time, Uuid, LazyGcMap } from "@simplysm/core-common";
|
|
217
|
+
|
|
218
|
+
// DateTime
|
|
219
|
+
const now = new DateTime();
|
|
220
|
+
const specific = new DateTime(2025, 3, 15, 10, 30, 0);
|
|
221
|
+
const parsed = DateTime.parse("2025-03-15 10:30:00");
|
|
222
|
+
const tomorrow = now.addDays(1);
|
|
223
|
+
const formatted = now.toFormatString("yyyy-MM-dd HH:mm");
|
|
224
|
+
|
|
225
|
+
// DateOnly
|
|
226
|
+
const today = new DateOnly();
|
|
227
|
+
const week = today.getWeekSeqOfYear(); // { year, weekSeq }
|
|
228
|
+
|
|
229
|
+
// Time
|
|
230
|
+
const time = new Time(14, 30, 0);
|
|
231
|
+
const wrapped = time.addHours(12); // wraps around 24h
|
|
232
|
+
|
|
233
|
+
// Uuid
|
|
234
|
+
const id = Uuid.generate();
|
|
235
|
+
const bytes = id.toBytes();
|
|
236
|
+
const restored = Uuid.fromBytes(bytes);
|
|
237
|
+
|
|
238
|
+
// LazyGcMap
|
|
239
|
+
using cache = new LazyGcMap<string, object>({ expireTime: 60_000 });
|
|
240
|
+
cache.set("key", { data: 1 });
|
|
241
|
+
const val = cache.getOrCreate("key2", () => ({ data: 2 }));
|
|
242
|
+
```
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Wait Utilities
|
|
2
|
+
|
|
3
|
+
Imported as the `wait` namespace. Async timing utilities.
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
import { wait } from "@simplysm/core-common";
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## time
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
function time(millisecond: number): Promise<void>;
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Waits for the specified number of milliseconds.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## until
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
function until(
|
|
23
|
+
forwarder: () => boolean | Promise<boolean>,
|
|
24
|
+
milliseconds?: number,
|
|
25
|
+
maxCount?: number,
|
|
26
|
+
): Promise<void>;
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Polls a condition at the given interval (default: 100ms) until it returns `true`. Returns immediately if the condition is `true` on the first call. Throws `TimeoutError` if `maxCount` attempts are exhausted.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Usage Examples
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { wait } from "@simplysm/core-common";
|
|
37
|
+
|
|
38
|
+
// Simple delay
|
|
39
|
+
await wait.time(1000); // wait 1 second
|
|
40
|
+
|
|
41
|
+
// Poll until condition is met
|
|
42
|
+
await wait.until(() => isReady, 100, 50);
|
|
43
|
+
// Checks every 100ms, up to 50 times (5 seconds total)
|
|
44
|
+
|
|
45
|
+
// With async condition
|
|
46
|
+
await wait.until(async () => {
|
|
47
|
+
const status = await checkStatus();
|
|
48
|
+
return status === "complete";
|
|
49
|
+
}, 500);
|
|
50
|
+
```
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# XML Utilities
|
|
2
|
+
|
|
3
|
+
Imported as the `xml` namespace. XML parsing and serialization via `fast-xml-parser`.
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
import { xml } from "@simplysm/core-common";
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## parse
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
function parse(str: string, options?: { stripTagPrefix?: boolean }): unknown;
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Parses an XML string into an object. Attributes are grouped under `$`, text content under `_`, and child elements are converted to arrays (except the root). Set `stripTagPrefix` to remove namespace prefixes from tag names.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## stringify
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
function stringify(obj: unknown, options?: XmlBuilderOptions): string;
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Serializes an object to XML string. Accepts optional `fast-xml-parser` builder options.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Usage Examples
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { xml } from "@simplysm/core-common";
|
|
33
|
+
|
|
34
|
+
const obj = xml.parse('<root id="1"><item>hello</item><item>world</item></root>');
|
|
35
|
+
// { root: { $: { id: "1" }, item: [{ _: "hello" }, { _: "world" }] } }
|
|
36
|
+
|
|
37
|
+
const xmlStr = xml.stringify({
|
|
38
|
+
root: {
|
|
39
|
+
$: { id: "1" },
|
|
40
|
+
item: [{ _: "hello" }, { _: "world" }],
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
// '<root id="1"><item>hello</item><item>world</item></root>'
|
|
44
|
+
|
|
45
|
+
// Strip namespace prefixes
|
|
46
|
+
xml.parse('<ns:root><ns:item>test</ns:item></ns:root>', { stripTagPrefix: true });
|
|
47
|
+
// { root: { item: [{ _: "test" }] } }
|
|
48
|
+
```
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# ZIP Archive
|
|
2
|
+
|
|
3
|
+
The `ZipArchive` class for reading, writing, and compressing ZIP files. Uses `@zip.js/zip.js` internally.
|
|
4
|
+
|
|
5
|
+
Directly exported (not namespaced).
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { ZipArchive } from "@simplysm/core-common";
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## ZipArchive
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
class ZipArchive {
|
|
15
|
+
constructor(data?: Blob | Bytes);
|
|
16
|
+
|
|
17
|
+
get(fileName: string): Promise<Bytes | undefined>;
|
|
18
|
+
exists(fileName: string): Promise<boolean>;
|
|
19
|
+
write(fileName: string, bytes: Bytes): void;
|
|
20
|
+
extractAll(progressCallback?: (progress: ZipArchiveProgress) => void): Promise<Map<string, Bytes | undefined>>;
|
|
21
|
+
compress(): Promise<Bytes>;
|
|
22
|
+
close(): Promise<void>;
|
|
23
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface ZipArchiveProgress {
|
|
27
|
+
fileName: string;
|
|
28
|
+
totalSize: number;
|
|
29
|
+
extractedSize: number;
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
- **Read mode:** Pass existing ZIP data (`Blob` or `Uint8Array`) to the constructor. Use `get()` for individual files or `extractAll()` for everything.
|
|
34
|
+
- **Write mode:** Omit the constructor argument. Use `write()` to add files, then `compress()` to generate the ZIP.
|
|
35
|
+
- Supports `await using` syntax for automatic cleanup.
|
|
36
|
+
- Internally caches decompressed files to prevent duplicate extraction.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Usage Examples
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { ZipArchive } from "@simplysm/core-common";
|
|
44
|
+
|
|
45
|
+
// Read a ZIP file
|
|
46
|
+
await using archive = new ZipArchive(zipBytes);
|
|
47
|
+
const content = await archive.get("file.txt");
|
|
48
|
+
const exists = await archive.exists("data.json");
|
|
49
|
+
|
|
50
|
+
// Extract all with progress
|
|
51
|
+
const files = await archive.extractAll((progress) => {
|
|
52
|
+
const pct = (progress.extractedSize / progress.totalSize * 100).toFixed(1);
|
|
53
|
+
console.log(`${progress.fileName}: ${pct}%`);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Create a new ZIP file
|
|
57
|
+
await using newArchive = new ZipArchive();
|
|
58
|
+
newArchive.write("hello.txt", new TextEncoder().encode("Hello World"));
|
|
59
|
+
newArchive.write("data.json", new TextEncoder().encode('{"key":"value"}'));
|
|
60
|
+
const zipOutput = await newArchive.compress();
|
|
61
|
+
```
|
package/package.json
CHANGED
package/src/utils/num.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* @note Strings with decimal points return only the integer part (e.g., '12.34' → 12).
|
|
12
12
|
* Use {@link parseRoundedInt} if rounding is needed.
|
|
13
13
|
* @note Hyphens (-) in the middle of the string are preserved, which may result in unintended negative numbers.
|
|
14
|
-
* Example: `"
|
|
14
|
+
* Example: `"A-123B"` → `-123`
|
|
15
15
|
*/
|
|
16
16
|
export function parseInt(text: unknown): number | undefined {
|
|
17
17
|
if (typeof text === "number") return Math.trunc(text);
|
|
@@ -63,7 +63,7 @@ function encodeImpl(
|
|
|
63
63
|
): unknown {
|
|
64
64
|
if (obj == null) return obj;
|
|
65
65
|
|
|
66
|
-
//
|
|
66
|
+
// Object type processing: circular reference detection + cache
|
|
67
67
|
if (typeof obj === "object") {
|
|
68
68
|
// Circular reference detection (object in current recursion stack)
|
|
69
69
|
if (ancestors.has(obj)) {
|