@simplysm/core-common 13.0.100 → 14.0.4
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 +86 -92
- package/dist/common.types.d.ts +14 -14
- package/dist/common.types.js +2 -1
- package/dist/common.types.js.map +1 -6
- package/dist/env.d.ts +8 -1
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +13 -9
- package/dist/env.js.map +1 -6
- package/dist/errors/argument-error.d.ts +10 -10
- package/dist/errors/argument-error.d.ts.map +1 -1
- package/dist/errors/argument-error.js +31 -14
- package/dist/errors/argument-error.js.map +1 -6
- package/dist/errors/not-implemented-error.d.ts +8 -8
- package/dist/errors/not-implemented-error.js +30 -12
- package/dist/errors/not-implemented-error.js.map +1 -6
- package/dist/errors/sd-error.d.ts +10 -10
- package/dist/errors/sd-error.d.ts.map +1 -1
- package/dist/errors/sd-error.js +45 -24
- package/dist/errors/sd-error.js.map +1 -6
- package/dist/errors/timeout-error.d.ts +10 -10
- package/dist/errors/timeout-error.js +34 -15
- package/dist/errors/timeout-error.js.map +1 -6
- package/dist/extensions/arr-ext.d.ts +2 -2
- package/dist/extensions/arr-ext.helpers.d.ts +10 -10
- package/dist/extensions/arr-ext.helpers.js +112 -89
- package/dist/extensions/arr-ext.helpers.js.map +1 -6
- package/dist/extensions/arr-ext.js +458 -422
- package/dist/extensions/arr-ext.js.map +1 -6
- package/dist/extensions/arr-ext.types.d.ts +57 -57
- package/dist/extensions/arr-ext.types.d.ts.map +1 -1
- package/dist/extensions/arr-ext.types.js +6 -1
- package/dist/extensions/arr-ext.types.js.map +1 -6
- package/dist/extensions/map-ext.d.ts +16 -16
- package/dist/extensions/map-ext.js +27 -22
- package/dist/extensions/map-ext.js.map +1 -6
- package/dist/extensions/set-ext.d.ts +11 -11
- package/dist/extensions/set-ext.js +32 -25
- package/dist/extensions/set-ext.js.map +1 -6
- package/dist/features/debounce-queue.d.ts +17 -17
- package/dist/features/debounce-queue.js +98 -70
- package/dist/features/debounce-queue.js.map +1 -6
- package/dist/features/event-emitter.d.ts +20 -20
- package/dist/features/event-emitter.js +101 -78
- package/dist/features/event-emitter.js.map +1 -6
- package/dist/features/serial-queue.d.ts +11 -11
- package/dist/features/serial-queue.js +78 -57
- package/dist/features/serial-queue.js.map +1 -6
- package/dist/globals.d.ts +4 -4
- package/dist/globals.js +9 -1
- package/dist/globals.js.map +1 -6
- package/dist/index.js +28 -27
- package/dist/index.js.map +1 -6
- package/dist/types/date-only.d.ts +64 -64
- package/dist/types/date-only.d.ts.map +1 -1
- package/dist/types/date-only.js +263 -252
- package/dist/types/date-only.js.map +1 -6
- package/dist/types/date-time.d.ts +36 -36
- package/dist/types/date-time.d.ts.map +1 -1
- package/dist/types/date-time.js +196 -288
- package/dist/types/date-time.js.map +1 -6
- package/dist/types/lazy-gc-map.d.ts +26 -26
- package/dist/types/lazy-gc-map.d.ts.map +1 -1
- package/dist/types/lazy-gc-map.js +202 -159
- package/dist/types/lazy-gc-map.js.map +1 -6
- package/dist/types/time.d.ts +23 -23
- package/dist/types/time.d.ts.map +1 -1
- package/dist/types/time.js +169 -158
- package/dist/types/time.js.map +1 -6
- package/dist/types/uuid.d.ts +11 -11
- package/dist/types/uuid.d.ts.map +1 -1
- package/dist/types/uuid.js +95 -70
- package/dist/types/uuid.js.map +1 -6
- package/dist/utils/bytes.d.ts +17 -17
- package/dist/utils/bytes.js +137 -81
- package/dist/utils/bytes.js.map +1 -6
- package/dist/utils/date-format.d.ts +40 -40
- package/dist/utils/date-format.js +187 -101
- package/dist/utils/date-format.js.map +1 -6
- package/dist/utils/error.d.ts +4 -4
- package/dist/utils/error.js +11 -6
- package/dist/utils/error.js.map +1 -6
- package/dist/utils/json.d.ts +19 -19
- package/dist/utils/json.js +187 -135
- package/dist/utils/json.js.map +1 -6
- package/dist/utils/num.d.ts +20 -20
- package/dist/utils/num.js +76 -34
- package/dist/utils/num.js.map +1 -6
- package/dist/utils/obj.d.ts +111 -111
- package/dist/utils/obj.d.ts.map +1 -1
- package/dist/utils/obj.js +706 -496
- package/dist/utils/obj.js.map +1 -6
- package/dist/utils/path.d.ts +10 -10
- package/dist/utils/path.js +35 -18
- package/dist/utils/path.js.map +1 -6
- package/dist/utils/primitive.d.ts +5 -5
- package/dist/utils/primitive.js +34 -14
- package/dist/utils/primitive.js.map +1 -6
- package/dist/utils/str.d.ts +38 -38
- package/dist/utils/str.js +217 -113
- package/dist/utils/str.js.map +1 -6
- package/dist/utils/template-strings.d.ts +26 -26
- package/dist/utils/template-strings.js +113 -40
- package/dist/utils/template-strings.js.map +1 -6
- package/dist/utils/transferable.d.ts +18 -18
- package/dist/utils/transferable.js +218 -151
- package/dist/utils/transferable.js.map +1 -6
- package/dist/utils/wait.d.ts +9 -9
- package/dist/utils/wait.js +30 -15
- package/dist/utils/wait.js.map +1 -6
- package/dist/utils/xml.d.ts +13 -13
- package/dist/utils/xml.js +84 -46
- package/dist/utils/xml.js.map +1 -6
- package/dist/utils/zip.d.ts +22 -22
- package/dist/utils/zip.js +172 -148
- package/dist/utils/zip.js.map +1 -6
- package/docs/array-extensions.md +430 -0
- package/docs/env.md +52 -0
- package/docs/errors.md +41 -56
- package/docs/features.md +82 -97
- package/docs/type-utilities.md +91 -0
- package/docs/types.md +221 -201
- package/docs/utils.md +319 -435
- package/package.json +7 -5
- package/src/common.types.ts +14 -14
- package/src/env.ts +12 -3
- package/src/errors/argument-error.ts +15 -15
- package/src/errors/not-implemented-error.ts +9 -9
- package/src/errors/sd-error.ts +12 -12
- package/src/errors/timeout-error.ts +12 -12
- package/src/extensions/arr-ext.helpers.ts +16 -16
- package/src/extensions/arr-ext.ts +35 -35
- package/src/extensions/arr-ext.types.ts +57 -57
- package/src/extensions/map-ext.ts +16 -16
- package/src/extensions/set-ext.ts +11 -11
- package/src/features/debounce-queue.ts +23 -23
- package/src/features/event-emitter.ts +25 -25
- package/src/features/serial-queue.ts +13 -13
- package/src/globals.ts +4 -4
- package/src/index.ts +5 -5
- package/src/types/date-only.ts +84 -83
- package/src/types/date-time.ts +43 -42
- package/src/types/lazy-gc-map.ts +44 -44
- package/src/types/time.ts +29 -29
- package/src/types/uuid.ts +15 -15
- package/src/utils/bytes.ts +35 -35
- package/src/utils/date-format.ts +59 -59
- package/src/utils/error.ts +4 -4
- package/src/utils/json.ts +41 -41
- package/src/utils/num.ts +20 -20
- package/src/utils/obj.ts +138 -138
- package/src/utils/path.ts +10 -10
- package/src/utils/primitive.ts +6 -6
- package/src/utils/str.ts +48 -48
- package/src/utils/template-strings.ts +29 -29
- package/src/utils/transferable.ts +38 -38
- package/src/utils/wait.ts +10 -10
- package/src/utils/xml.ts +19 -19
- package/src/utils/zip.ts +25 -25
- package/docs/extensions.md +0 -387
- package/tests/errors/errors.spec.ts +0 -80
- package/tests/extensions/array-extension.spec.ts +0 -654
- package/tests/extensions/map-extension.spec.ts +0 -117
- package/tests/extensions/set-extension.spec.ts +0 -67
- package/tests/types/date-only.spec.ts +0 -533
- package/tests/types/date-time.spec.ts +0 -246
- package/tests/types/lazy-gc-map.spec.ts +0 -606
- package/tests/types/time.spec.ts +0 -428
- package/tests/types/uuid.spec.ts +0 -74
- package/tests/utils/bytes-utils.spec.ts +0 -197
- package/tests/utils/date-format.spec.ts +0 -350
- package/tests/utils/debounce-queue.spec.ts +0 -226
- package/tests/utils/json.spec.ts +0 -400
- package/tests/utils/number.spec.ts +0 -136
- package/tests/utils/object.spec.ts +0 -810
- package/tests/utils/path.spec.ts +0 -70
- package/tests/utils/primitive.spec.ts +0 -43
- package/tests/utils/sd-event-emitter.spec.ts +0 -189
- package/tests/utils/serial-queue.spec.ts +0 -305
- package/tests/utils/string.spec.ts +0 -265
- package/tests/utils/template-strings.spec.ts +0 -48
- package/tests/utils/transferable.spec.ts +0 -639
- package/tests/utils/wait.spec.ts +0 -123
- package/tests/utils/xml.spec.ts +0 -146
- package/tests/utils/zip.spec.ts +0 -221
package/docs/features.md
CHANGED
|
@@ -1,143 +1,128 @@
|
|
|
1
1
|
# Features
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Async queue and event emitter utilities. All support `using` syntax via `Symbol.dispose`.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## `EventEmitter`
|
|
5
|
+
## `DebounceQueue`
|
|
10
6
|
|
|
11
|
-
|
|
7
|
+
Async debounce queue. When called multiple times in rapid succession, only the last enqueued function executes after the delay. Extends `EventEmitter<{ error: SdError }>`.
|
|
12
8
|
|
|
13
9
|
```typescript
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
> {
|
|
17
|
-
/**
|
|
18
|
-
* Register an event listener
|
|
19
|
-
* @note Duplicate registration of the same listener to the same event is ignored
|
|
20
|
-
*/
|
|
21
|
-
on<TEventName extends keyof TEvents & string>(
|
|
22
|
-
type: TEventName,
|
|
23
|
-
listener: (data: TEvents[TEventName]) => void,
|
|
24
|
-
): void;
|
|
25
|
-
|
|
26
|
-
/** Remove an event listener */
|
|
27
|
-
off<TEventName extends keyof TEvents & string>(
|
|
28
|
-
type: TEventName,
|
|
29
|
-
listener: (data: TEvents[TEventName]) => void,
|
|
30
|
-
): void;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Emit an event
|
|
34
|
-
* @param args Event data (omitted if void type)
|
|
35
|
-
*/
|
|
36
|
-
emit<TEventName extends keyof TEvents & string>(
|
|
37
|
-
type: TEventName,
|
|
38
|
-
...args: TEvents[TEventName] extends void ? [] : [data: TEvents[TEventName]]
|
|
39
|
-
): void;
|
|
40
|
-
|
|
41
|
-
/** Return the number of listeners for a specific event */
|
|
42
|
-
listenerCount<TEventName extends keyof TEvents & string>(type: TEventName): number;
|
|
10
|
+
class DebounceQueue extends EventEmitter<{ error: SdError }> {
|
|
11
|
+
constructor(delay?: number);
|
|
43
12
|
|
|
44
|
-
|
|
13
|
+
run(fn: () => void | Promise<void>): void;
|
|
45
14
|
dispose(): void;
|
|
46
|
-
|
|
47
15
|
[Symbol.dispose](): void;
|
|
48
16
|
}
|
|
49
17
|
```
|
|
50
18
|
|
|
51
|
-
|
|
19
|
+
### Constructor
|
|
52
20
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
error: Error;
|
|
57
|
-
done: void;
|
|
58
|
-
}
|
|
21
|
+
| Parameter | Type | Default | Description |
|
|
22
|
+
|-----------|------|---------|-------------|
|
|
23
|
+
| `delay` | `number \| undefined` | `undefined` (next event loop) | Debounce delay in milliseconds |
|
|
59
24
|
|
|
60
|
-
|
|
25
|
+
### Methods
|
|
61
26
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
```
|
|
27
|
+
| Method | Description |
|
|
28
|
+
|--------|-------------|
|
|
29
|
+
| `run(fn)` | Enqueue a function. Replaces any previously pending function. After the delay, executes the last enqueued function |
|
|
30
|
+
| `dispose()` | Cancels pending timer and clears state |
|
|
67
31
|
|
|
68
|
-
|
|
32
|
+
### Behavior
|
|
69
33
|
|
|
70
|
-
|
|
34
|
+
- If a new `run()` call arrives while a previous function is executing, the new function runs immediately after the current one completes (no debounce delay).
|
|
35
|
+
- Errors are emitted as `"error"` events if listeners exist; otherwise logged via consola.
|
|
71
36
|
|
|
72
|
-
|
|
37
|
+
```typescript
|
|
38
|
+
const queue = new DebounceQueue(300);
|
|
39
|
+
queue.on("error", (err) => console.error(err));
|
|
73
40
|
|
|
74
|
-
|
|
41
|
+
queue.run(() => console.log("1")); // cancelled
|
|
42
|
+
queue.run(() => console.log("2")); // cancelled
|
|
43
|
+
queue.run(() => console.log("3")); // executes after 300ms
|
|
44
|
+
```
|
|
75
45
|
|
|
76
|
-
|
|
77
|
-
export class DebounceQueue extends EventEmitter<{ error: SdError }> {
|
|
78
|
-
/**
|
|
79
|
-
* @param _delay Debounce delay time (milliseconds). If omitted, executes immediately (next event loop)
|
|
80
|
-
*/
|
|
81
|
-
constructor(delay?: number);
|
|
46
|
+
## `SerialQueue`
|
|
82
47
|
|
|
83
|
-
|
|
84
|
-
dispose(): void;
|
|
48
|
+
Async serial queue. Functions are executed one at a time in the order they are enqueued. Errors in one function do not prevent subsequent functions from running. Extends `EventEmitter<{ error: SdError }>`.
|
|
85
49
|
|
|
86
|
-
|
|
50
|
+
```typescript
|
|
51
|
+
class SerialQueue extends EventEmitter<{ error: SdError }> {
|
|
52
|
+
constructor(gap?: number);
|
|
87
53
|
|
|
88
|
-
/**
|
|
89
|
-
* Add a function to the queue
|
|
90
|
-
* If there was a previously added function, it will be replaced
|
|
91
|
-
*/
|
|
92
54
|
run(fn: () => void | Promise<void>): void;
|
|
55
|
+
dispose(): void;
|
|
56
|
+
[Symbol.dispose](): void;
|
|
93
57
|
}
|
|
94
58
|
```
|
|
95
59
|
|
|
96
|
-
|
|
60
|
+
### Constructor
|
|
97
61
|
|
|
98
|
-
|
|
62
|
+
| Parameter | Type | Default | Description |
|
|
63
|
+
|-----------|------|---------|-------------|
|
|
64
|
+
| `gap` | `number` | `0` | Delay between each task execution (ms) |
|
|
99
65
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
66
|
+
### Methods
|
|
67
|
+
|
|
68
|
+
| Method | Description |
|
|
69
|
+
|--------|-------------|
|
|
70
|
+
| `run(fn)` | Add a function to the queue. Starts processing if not already running |
|
|
71
|
+
| `dispose()` | Clears the pending queue. The currently running task still completes |
|
|
105
72
|
|
|
73
|
+
```typescript
|
|
74
|
+
const queue = new SerialQueue();
|
|
106
75
|
queue.on("error", (err) => console.error(err));
|
|
107
|
-
```
|
|
108
76
|
|
|
109
|
-
|
|
77
|
+
queue.run(async () => { await fetch("/api/1"); }); // runs first
|
|
78
|
+
queue.run(async () => { await fetch("/api/2"); }); // runs after 1 completes
|
|
79
|
+
queue.run(async () => { await fetch("/api/3"); }); // runs after 2 completes
|
|
80
|
+
```
|
|
110
81
|
|
|
111
|
-
## `
|
|
82
|
+
## `EventEmitter<TEvents>`
|
|
112
83
|
|
|
113
|
-
|
|
84
|
+
Type-safe event emitter built on the `EventTarget` API. Works in both browser and Node.js.
|
|
114
85
|
|
|
115
86
|
```typescript
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
87
|
+
class EventEmitter<TEvents extends { [K in keyof TEvents]: unknown } = Record<string, unknown>> {
|
|
88
|
+
on<K extends keyof TEvents & string>(type: K, listener: (data: TEvents[K]) => void): void;
|
|
89
|
+
off<K extends keyof TEvents & string>(type: K, listener: (data: TEvents[K]) => void): void;
|
|
90
|
+
emit<K extends keyof TEvents & string>(
|
|
91
|
+
type: K,
|
|
92
|
+
...args: TEvents[K] extends void ? [] : [data: TEvents[K]]
|
|
93
|
+
): void;
|
|
94
|
+
listenerCount<K extends keyof TEvents & string>(type: K): number;
|
|
123
95
|
dispose(): void;
|
|
124
|
-
|
|
125
96
|
[Symbol.dispose](): void;
|
|
126
|
-
|
|
127
|
-
/** Add a function to the queue and execute it */
|
|
128
|
-
run(fn: () => void | Promise<void>): void;
|
|
129
97
|
}
|
|
130
98
|
```
|
|
131
99
|
|
|
132
|
-
|
|
100
|
+
### Methods
|
|
101
|
+
|
|
102
|
+
| Method | Description |
|
|
103
|
+
|--------|-------------|
|
|
104
|
+
| `on(type, listener)` | Register a listener. Duplicate registration for the same event+listener is ignored |
|
|
105
|
+
| `off(type, listener)` | Remove a listener |
|
|
106
|
+
| `emit(type, data?)` | Dispatch an event. For `void` event types, data argument is omitted |
|
|
107
|
+
| `listenerCount(type)` | Returns the number of registered listeners for an event type |
|
|
108
|
+
| `dispose()` | Removes all listeners from all event types |
|
|
133
109
|
|
|
134
|
-
|
|
110
|
+
### Type Parameter
|
|
111
|
+
|
|
112
|
+
`TEvents` is a map where keys are event names and values are event data types. Use `void` for events with no data.
|
|
135
113
|
|
|
136
114
|
```typescript
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
115
|
+
interface MyEvents {
|
|
116
|
+
data: string;
|
|
117
|
+
error: Error;
|
|
118
|
+
done: void;
|
|
119
|
+
}
|
|
141
120
|
|
|
142
|
-
|
|
121
|
+
class MyService extends EventEmitter<MyEvents> {}
|
|
122
|
+
|
|
123
|
+
const svc = new MyService();
|
|
124
|
+
svc.on("data", (data) => {}); // data: string
|
|
125
|
+
svc.on("done", () => {}); // no argument
|
|
126
|
+
svc.emit("data", "hello");
|
|
127
|
+
svc.emit("done"); // no argument needed
|
|
143
128
|
```
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Type Utilities
|
|
2
|
+
|
|
3
|
+
TypeScript type aliases and interfaces exported from `common.types.ts`.
|
|
4
|
+
|
|
5
|
+
## `Bytes`
|
|
6
|
+
|
|
7
|
+
Type alias for `Uint8Array`. Used throughout the framework instead of `Buffer`.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
type Bytes = Uint8Array;
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## `PrimitiveTypeMap`
|
|
14
|
+
|
|
15
|
+
Maps primitive type string keys to their corresponding TypeScript types. Shared with `orm-common`.
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
type PrimitiveTypeMap = {
|
|
19
|
+
string: string;
|
|
20
|
+
number: number;
|
|
21
|
+
boolean: boolean;
|
|
22
|
+
DateTime: DateTime;
|
|
23
|
+
DateOnly: DateOnly;
|
|
24
|
+
Time: Time;
|
|
25
|
+
Uuid: Uuid;
|
|
26
|
+
Bytes: Bytes;
|
|
27
|
+
};
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## `PrimitiveTypeStr`
|
|
31
|
+
|
|
32
|
+
Union of all keys in `PrimitiveTypeMap`.
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
type PrimitiveTypeStr = keyof PrimitiveTypeMap;
|
|
36
|
+
// "string" | "number" | "boolean" | "DateTime" | "DateOnly" | "Time" | "Uuid" | "Bytes"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## `PrimitiveType`
|
|
40
|
+
|
|
41
|
+
Union of all primitive type values (including `undefined`).
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
type PrimitiveType = PrimitiveTypeMap[PrimitiveTypeStr] | undefined;
|
|
45
|
+
// string | number | boolean | DateTime | DateOnly | Time | Uuid | Uint8Array | undefined
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## `DeepPartial<TObject>`
|
|
49
|
+
|
|
50
|
+
Recursively makes all properties optional. Primitive types (`PrimitiveType`) are preserved as-is; only object/array types are recursively made partial.
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
type DeepPartial<TObject> = Partial<{
|
|
54
|
+
[K in keyof TObject]: TObject[K] extends PrimitiveType
|
|
55
|
+
? TObject[K]
|
|
56
|
+
: DeepPartial<TObject[K]>;
|
|
57
|
+
}>;
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
interface User {
|
|
62
|
+
name: string;
|
|
63
|
+
profile: {
|
|
64
|
+
age: number;
|
|
65
|
+
address: { city: string };
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const partial: DeepPartial<User> = {
|
|
70
|
+
profile: { address: {} },
|
|
71
|
+
};
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## `Type<TInstance>`
|
|
75
|
+
|
|
76
|
+
Constructor type interface. Represents a class constructor that creates instances of `TInstance`. Used for dependency injection, factory patterns, and `instanceof` checks.
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
interface Type<TInstance> extends Function {
|
|
80
|
+
new (...args: unknown[]): TInstance;
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
function create<T>(ctor: Type<T>): T {
|
|
86
|
+
return new ctor();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
class MyClass { name = "test"; }
|
|
90
|
+
const instance = create(MyClass); // MyClass instance
|
|
91
|
+
```
|