@simplysm/core-common 13.0.81 → 13.0.83

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/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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/core-common",
3
- "version": "13.0.81",
3
+ "version": "13.0.83",
4
4
  "description": "Simplysm package - Core module (common)",
5
5
  "author": "simplysm",
6
6
  "license": "Apache-2.0",