@venizia/ignis-docs 0.0.5 → 0.0.6-1
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/package.json +1 -1
- package/wiki/best-practices/architectural-patterns.md +0 -2
- package/wiki/best-practices/architecture-decisions.md +0 -8
- package/wiki/best-practices/code-style-standards/control-flow.md +1 -1
- package/wiki/best-practices/code-style-standards/index.md +0 -1
- package/wiki/best-practices/code-style-standards/tooling.md +0 -3
- package/wiki/best-practices/contribution-workflow.md +12 -12
- package/wiki/best-practices/index.md +4 -14
- package/wiki/best-practices/performance-optimization.md +3 -3
- package/wiki/best-practices/security-guidelines.md +2 -2
- package/wiki/best-practices/troubleshooting-tips.md +1 -1
- package/wiki/guides/core-concepts/application/bootstrapping.md +6 -7
- package/wiki/guides/core-concepts/components-guide.md +1 -1
- package/wiki/guides/core-concepts/components.md +2 -2
- package/wiki/guides/core-concepts/dependency-injection.md +4 -5
- package/wiki/guides/core-concepts/persistent/datasources.md +4 -5
- package/wiki/guides/core-concepts/services.md +1 -1
- package/wiki/guides/get-started/5-minute-quickstart.md +4 -5
- package/wiki/guides/get-started/philosophy.md +12 -24
- package/wiki/guides/index.md +2 -9
- package/wiki/guides/reference/mcp-docs-server.md +13 -13
- package/wiki/guides/tutorials/building-a-crud-api.md +10 -10
- package/wiki/guides/tutorials/complete-installation.md +11 -12
- package/wiki/guides/tutorials/ecommerce-api.md +3 -3
- package/wiki/guides/tutorials/realtime-chat.md +6 -6
- package/wiki/guides/tutorials/testing.md +4 -5
- package/wiki/index.md +8 -14
- package/wiki/references/base/bootstrapping.md +0 -3
- package/wiki/references/base/components.md +2 -2
- package/wiki/references/base/controllers.md +0 -1
- package/wiki/references/base/datasources.md +1 -1
- package/wiki/references/base/dependency-injection.md +2 -2
- package/wiki/references/base/filter-system/default-filter.md +2 -3
- package/wiki/references/base/filter-system/index.md +1 -1
- package/wiki/references/base/filter-system/quick-reference.md +0 -14
- package/wiki/references/base/middlewares.md +0 -8
- package/wiki/references/base/providers.md +0 -9
- package/wiki/references/base/repositories/advanced.md +1 -1
- package/wiki/references/base/repositories/mixins.md +2 -3
- package/wiki/references/base/services.md +0 -1
- package/wiki/references/components/authentication/api.md +444 -0
- package/wiki/references/components/authentication/errors.md +177 -0
- package/wiki/references/components/authentication/index.md +571 -0
- package/wiki/references/components/authentication/usage.md +781 -0
- package/wiki/references/components/health-check.md +292 -103
- package/wiki/references/components/index.md +14 -12
- package/wiki/references/components/mail/api.md +505 -0
- package/wiki/references/components/mail/errors.md +176 -0
- package/wiki/references/components/mail/index.md +535 -0
- package/wiki/references/components/mail/usage.md +404 -0
- package/wiki/references/components/request-tracker.md +229 -25
- package/wiki/references/components/socket-io/api.md +1051 -0
- package/wiki/references/components/socket-io/errors.md +119 -0
- package/wiki/references/components/socket-io/index.md +410 -0
- package/wiki/references/components/socket-io/usage.md +322 -0
- package/wiki/references/components/static-asset/api.md +261 -0
- package/wiki/references/components/static-asset/errors.md +89 -0
- package/wiki/references/components/static-asset/index.md +617 -0
- package/wiki/references/components/static-asset/usage.md +364 -0
- package/wiki/references/components/swagger.md +390 -110
- package/wiki/references/components/template/api-page.md +125 -0
- package/wiki/references/components/template/errors-page.md +100 -0
- package/wiki/references/components/template/index.md +104 -0
- package/wiki/references/components/template/setup-page.md +134 -0
- package/wiki/references/components/template/single-page.md +132 -0
- package/wiki/references/components/template/usage-page.md +127 -0
- package/wiki/references/components/websocket/api.md +508 -0
- package/wiki/references/components/websocket/errors.md +123 -0
- package/wiki/references/components/websocket/index.md +453 -0
- package/wiki/references/components/websocket/usage.md +475 -0
- package/wiki/references/helpers/cron/index.md +224 -0
- package/wiki/references/helpers/crypto/index.md +537 -0
- package/wiki/references/helpers/env/index.md +214 -0
- package/wiki/references/helpers/error/index.md +232 -0
- package/wiki/references/helpers/index.md +16 -15
- package/wiki/references/helpers/inversion/index.md +608 -0
- package/wiki/references/helpers/logger/index.md +600 -0
- package/wiki/references/helpers/network/api.md +986 -0
- package/wiki/references/helpers/network/index.md +620 -0
- package/wiki/references/helpers/queue/index.md +589 -0
- package/wiki/references/helpers/redis/index.md +495 -0
- package/wiki/references/helpers/socket-io/api.md +497 -0
- package/wiki/references/helpers/socket-io/index.md +513 -0
- package/wiki/references/helpers/storage/api.md +705 -0
- package/wiki/references/helpers/storage/index.md +583 -0
- package/wiki/references/helpers/template/index.md +66 -0
- package/wiki/references/helpers/template/single-page.md +126 -0
- package/wiki/references/helpers/testing/index.md +510 -0
- package/wiki/references/helpers/types/index.md +512 -0
- package/wiki/references/helpers/uid/index.md +272 -0
- package/wiki/references/helpers/websocket/api.md +736 -0
- package/wiki/references/helpers/websocket/index.md +574 -0
- package/wiki/references/helpers/worker-thread/index.md +470 -0
- package/wiki/references/index.md +2 -9
- package/wiki/references/quick-reference.md +3 -18
- package/wiki/references/utilities/jsx.md +1 -8
- package/wiki/references/utilities/statuses.md +0 -7
- package/wiki/references/components/authentication.md +0 -476
- package/wiki/references/components/mail.md +0 -687
- package/wiki/references/components/socket-io.md +0 -562
- package/wiki/references/components/static-asset.md +0 -1277
- package/wiki/references/helpers/cron.md +0 -108
- package/wiki/references/helpers/crypto.md +0 -132
- package/wiki/references/helpers/env.md +0 -83
- package/wiki/references/helpers/error.md +0 -97
- package/wiki/references/helpers/inversion.md +0 -176
- package/wiki/references/helpers/logger.md +0 -296
- package/wiki/references/helpers/network.md +0 -396
- package/wiki/references/helpers/queue.md +0 -150
- package/wiki/references/helpers/redis.md +0 -142
- package/wiki/references/helpers/socket-io.md +0 -932
- package/wiki/references/helpers/storage.md +0 -665
- package/wiki/references/helpers/testing.md +0 -133
- package/wiki/references/helpers/types.md +0 -167
- package/wiki/references/helpers/uid.md +0 -167
- package/wiki/references/helpers/worker-thread.md +0 -178
- package/wiki/references/src-details/boot.md +0 -379
- package/wiki/references/src-details/core.md +0 -263
- package/wiki/references/src-details/dev-configs.md +0 -298
- package/wiki/references/src-details/docs.md +0 -71
- package/wiki/references/src-details/helpers.md +0 -211
- package/wiki/references/src-details/index.md +0 -86
- package/wiki/references/src-details/inversion.md +0 -340
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# UID
|
|
2
|
+
|
|
3
|
+
Snowflake ID generator with Base62 encoding for unique, time-sortable distributed identifiers.
|
|
4
|
+
|
|
5
|
+
## Quick Reference
|
|
6
|
+
|
|
7
|
+
| Item | Value |
|
|
8
|
+
|------|-------|
|
|
9
|
+
| **Package** | `@venizia/ignis-helpers` |
|
|
10
|
+
| **Class** | `SnowflakeUidHelper` |
|
|
11
|
+
| **Extends** | `BaseHelper` |
|
|
12
|
+
| **Runtimes** | Both |
|
|
13
|
+
|
|
14
|
+
#### Import Paths
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { SnowflakeUidHelper, SnowflakeConfig } from '@venizia/ignis-helpers';
|
|
18
|
+
|
|
19
|
+
// Types
|
|
20
|
+
import type { IIdGeneratorOptions, ISnowflakeParsedId } from '@venizia/ignis-helpers';
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
#### Snowflake ID Structure (70 bits)
|
|
24
|
+
|
|
25
|
+
| Component | Bits | Range | Purpose |
|
|
26
|
+
|-----------|------|-------|---------|
|
|
27
|
+
| Timestamp | 48 | ~8,919 years | Time since epoch |
|
|
28
|
+
| Worker ID | 10 | 0--1023 | Unique worker identifier |
|
|
29
|
+
| Sequence | 12 | 0--4095 | IDs per millisecond |
|
|
30
|
+
|
|
31
|
+
#### Key Specifications
|
|
32
|
+
|
|
33
|
+
| Spec | Value |
|
|
34
|
+
|------|-------|
|
|
35
|
+
| Base62 Output | 10--12 characters |
|
|
36
|
+
| Throughput | 4,096,000 IDs/second/worker |
|
|
37
|
+
| Max Workers | 1024 |
|
|
38
|
+
| Lifespan | Until ~10,944 AD |
|
|
39
|
+
| Default Epoch | 2025-01-01 00:00:00 UTC |
|
|
40
|
+
|
|
41
|
+
## Creating an Instance
|
|
42
|
+
|
|
43
|
+
`SnowflakeUidHelper` extends `BaseHelper`, providing scoped logging via `LoggerFactory`.
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { SnowflakeUidHelper } from '@venizia/ignis-helpers';
|
|
47
|
+
|
|
48
|
+
// Use defaults (workerId: 199, epoch: 2025-01-01 00:00:00 UTC)
|
|
49
|
+
const generator = new SnowflakeUidHelper();
|
|
50
|
+
|
|
51
|
+
// Or with custom values
|
|
52
|
+
const customGenerator = new SnowflakeUidHelper({
|
|
53
|
+
workerId: 123,
|
|
54
|
+
epoch: BigInt(1735689600000),
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
#### `IIdGeneratorOptions`
|
|
59
|
+
|
|
60
|
+
| Option | Type | Default | Description |
|
|
61
|
+
|--------|------|---------|-------------|
|
|
62
|
+
| `workerId` | `number` | `199` | Worker ID (0--1023). Must be unique per instance in distributed deployments |
|
|
63
|
+
| `epoch` | `bigint` | `BigInt(1735689600000)` | Custom epoch timestamp in milliseconds since Unix epoch. Must be positive and in the past |
|
|
64
|
+
|
|
65
|
+
> [!TIP]
|
|
66
|
+
> Use unique worker IDs in distributed systems to prevent ID collisions, and keep the epoch consistent across all instances to ensure proper ID ordering.
|
|
67
|
+
|
|
68
|
+
#### `SnowflakeConfig` Constants
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import { SnowflakeConfig } from '@venizia/ignis-helpers';
|
|
72
|
+
|
|
73
|
+
SnowflakeConfig.DEFAULT_EPOCH // BigInt(1735689600000) - 2025-01-01 00:00:00 UTC
|
|
74
|
+
SnowflakeConfig.MAX_WORKER_ID // 1023n
|
|
75
|
+
SnowflakeConfig.MAX_SEQUENCE // 4095n
|
|
76
|
+
SnowflakeConfig.TIMESTAMP_SHIFT // 22n
|
|
77
|
+
SnowflakeConfig.WORKER_ID_SHIFT // 12n
|
|
78
|
+
|
|
79
|
+
// Bit widths
|
|
80
|
+
SnowflakeConfig.TIMESTAMP_BITS // 48n
|
|
81
|
+
SnowflakeConfig.WORKER_ID_BITS // 10n
|
|
82
|
+
SnowflakeConfig.SEQUENCE_BITS // 12n
|
|
83
|
+
|
|
84
|
+
// Safety thresholds
|
|
85
|
+
SnowflakeConfig.MAX_CLOCK_BACKWARD_MS // 100n (busy-wait tolerance)
|
|
86
|
+
SnowflakeConfig.MAX_TIMESTAMP_MS // (1n << 48n) - 1n (~8,919 years)
|
|
87
|
+
SnowflakeConfig.WARNING_THRESHOLD_MS // ~8,909 years (warns 10 years before expiry)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Usage
|
|
91
|
+
|
|
92
|
+
### Generating IDs
|
|
93
|
+
|
|
94
|
+
Generate unique Snowflake IDs as either compact Base62 strings or raw bigints.
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// Generate Base62 encoded ID (recommended for most use cases)
|
|
98
|
+
const id = generator.nextId();
|
|
99
|
+
// => e.g., "9du1sJXO88"
|
|
100
|
+
|
|
101
|
+
// Generate raw Snowflake ID as bigint
|
|
102
|
+
const snowflakeId = generator.nextSnowflake();
|
|
103
|
+
// => e.g., 130546360012247045n
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
> [!TIP]
|
|
107
|
+
> Use `nextId()` for most cases -- it returns a compact Base62 string (10--12 chars) that works well as database primary keys and URL-safe identifiers. Use `nextSnowflake()` only when you need the raw bigint for arithmetic or bit-level operations.
|
|
108
|
+
|
|
109
|
+
#### Clock Drift Handling
|
|
110
|
+
|
|
111
|
+
When `nextSnowflake()` detects the system clock has moved backward:
|
|
112
|
+
- Drifts up to 100ms are handled automatically by busy-waiting until the clock catches up.
|
|
113
|
+
- Drifts exceeding 100ms throw an error to protect ID uniqueness.
|
|
114
|
+
- A warning is logged whenever any backward clock movement is detected.
|
|
115
|
+
|
|
116
|
+
#### Sequence Exhaustion
|
|
117
|
+
|
|
118
|
+
If more than 4096 IDs are requested in a single millisecond from the same worker, the generator busy-waits until the next millisecond before continuing. This is transparent to the caller.
|
|
119
|
+
|
|
120
|
+
### Base62 Encoding and Decoding
|
|
121
|
+
|
|
122
|
+
Encode any bigint to a compact, URL-safe Base62 string using the alphabet `0-9A-Za-z`, or decode back to the original bigint.
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
// Encode
|
|
126
|
+
const encoded = generator.encodeBase62(130546360012247045n);
|
|
127
|
+
// => "9du1sJXO88"
|
|
128
|
+
|
|
129
|
+
// Decode
|
|
130
|
+
const decoded = generator.decodeBase62('9du1sJXO88');
|
|
131
|
+
// => 130546360012247045n
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
> [!WARNING]
|
|
135
|
+
> `decodeBase62()` throws if the input contains characters outside the Base62 alphabet (`0-9`, `A-Z`, `a-z`). Watch for URL-encoded strings or accidental whitespace.
|
|
136
|
+
|
|
137
|
+
### Parsing IDs
|
|
138
|
+
|
|
139
|
+
Extract the embedded timestamp, worker ID, and sequence from a generated ID.
|
|
140
|
+
|
|
141
|
+
#### Parse a Base62 ID
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const parsed = generator.parseId('9du1sJXO88');
|
|
145
|
+
// => {
|
|
146
|
+
// raw: 130546360012247045n,
|
|
147
|
+
// timestamp: Date,
|
|
148
|
+
// workerId: 199,
|
|
149
|
+
// sequence: 0
|
|
150
|
+
// }
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### `ISnowflakeParsedId`
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
interface ISnowflakeParsedId {
|
|
157
|
+
raw: bigint;
|
|
158
|
+
timestamp: Date;
|
|
159
|
+
workerId: number;
|
|
160
|
+
sequence: number;
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
#### Extract Individual Components
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
const snowflakeId = generator.nextSnowflake();
|
|
168
|
+
|
|
169
|
+
// Extract timestamp
|
|
170
|
+
const timestamp = generator.extractTimestamp(snowflakeId);
|
|
171
|
+
// => Date object
|
|
172
|
+
|
|
173
|
+
// Extract worker ID
|
|
174
|
+
const workerId = generator.extractWorkerId(snowflakeId);
|
|
175
|
+
// => 199
|
|
176
|
+
|
|
177
|
+
// Extract sequence
|
|
178
|
+
const sequence = generator.extractSequence(snowflakeId);
|
|
179
|
+
// => 0-4095
|
|
180
|
+
|
|
181
|
+
// Get current instance's worker ID
|
|
182
|
+
const currentWorkerId = generator.getWorkerId();
|
|
183
|
+
// => 199
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## API Summary
|
|
187
|
+
|
|
188
|
+
| Method | Signature | Description |
|
|
189
|
+
|--------|-----------|-------------|
|
|
190
|
+
| `nextId` | `nextId(): string` | Generate a Base62-encoded Snowflake ID (10--12 chars) |
|
|
191
|
+
| `nextSnowflake` | `nextSnowflake(): bigint` | Generate a raw 70-bit Snowflake ID |
|
|
192
|
+
| `encodeBase62` | `encodeBase62(num: bigint): string` | Encode a bigint to Base62 string |
|
|
193
|
+
| `decodeBase62` | `decodeBase62(str: string): bigint` | Decode a Base62 string to bigint |
|
|
194
|
+
| `parseId` | `parseId(base62Id: string): ISnowflakeParsedId` | Parse a Base62 ID into its components |
|
|
195
|
+
| `extractTimestamp` | `extractTimestamp(id: bigint): Date` | Extract the timestamp from a raw Snowflake ID |
|
|
196
|
+
| `extractWorkerId` | `extractWorkerId(id: bigint): number` | Extract the worker ID from a raw Snowflake ID |
|
|
197
|
+
| `extractSequence` | `extractSequence(id: bigint): number` | Extract the sequence number from a raw Snowflake ID |
|
|
198
|
+
| `getWorkerId` | `getWorkerId(): number` | Get the current instance's worker ID |
|
|
199
|
+
|
|
200
|
+
## Troubleshooting
|
|
201
|
+
|
|
202
|
+
### "Worker ID must be between 0 and 1023"
|
|
203
|
+
|
|
204
|
+
**Cause:** The `workerId` option passed to the constructor is negative or exceeds 1023 (10-bit maximum).
|
|
205
|
+
|
|
206
|
+
**Fix:** Ensure the worker ID is within the valid range (0--1023):
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
// Wrong
|
|
210
|
+
new SnowflakeUidHelper({ workerId: 2000 });
|
|
211
|
+
|
|
212
|
+
// Correct
|
|
213
|
+
new SnowflakeUidHelper({ workerId: 1 });
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### "Epoch must be a positive number"
|
|
217
|
+
|
|
218
|
+
**Cause:** The `epoch` option is zero or negative.
|
|
219
|
+
|
|
220
|
+
**Fix:** Provide a valid epoch as a positive bigint representing milliseconds since Unix epoch:
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
// Wrong
|
|
224
|
+
new SnowflakeUidHelper({ epoch: BigInt(0) });
|
|
225
|
+
|
|
226
|
+
// Correct
|
|
227
|
+
new SnowflakeUidHelper({ epoch: BigInt(1735689600000) });
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### "Epoch cannot be in the future"
|
|
231
|
+
|
|
232
|
+
**Cause:** The `epoch` option is set to a timestamp later than the current time. A future epoch would produce negative timestamp offsets in generated IDs.
|
|
233
|
+
|
|
234
|
+
**Fix:** Use a past date as the epoch. The default (`2025-01-01 00:00:00 UTC`) is recommended unless you have a specific reason to change it.
|
|
235
|
+
|
|
236
|
+
### "Clock moved backward by Xms. Refusing to generate ID."
|
|
237
|
+
|
|
238
|
+
**Cause:** The system clock moved backward by more than 100ms, typically caused by NTP time synchronization. Small drifts (up to 100ms) are handled by busy-waiting, but larger jumps are rejected to protect ID uniqueness.
|
|
239
|
+
|
|
240
|
+
**Fix:** Ensure your system clock is stable. If running in containers, verify the host clock is not being adjusted aggressively. There is no code-level workaround -- the error protects against duplicate IDs.
|
|
241
|
+
|
|
242
|
+
### "Invalid Base62 character: X"
|
|
243
|
+
|
|
244
|
+
**Cause:** `decodeBase62()` encountered a character outside the Base62 alphabet (`0-9`, `A-Z`, `a-z`).
|
|
245
|
+
|
|
246
|
+
**Fix:** Ensure the input string only contains valid Base62 characters:
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
// Wrong
|
|
250
|
+
generator.decodeBase62('9du1sJ+O88'); // '+' is not Base62
|
|
251
|
+
generator.decodeBase62(' 9du1sJXO88'); // leading space
|
|
252
|
+
|
|
253
|
+
// Correct
|
|
254
|
+
generator.decodeBase62('9du1sJXO88');
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## See Also
|
|
258
|
+
|
|
259
|
+
- **Related Concepts:**
|
|
260
|
+
- [Models](/guides/core-concepts/persistent/models) - Using UIDs as primary keys
|
|
261
|
+
- [Services](/guides/core-concepts/services) - Generating unique IDs in services
|
|
262
|
+
|
|
263
|
+
- **Other Helpers:**
|
|
264
|
+
- [Helpers Index](../index) - All available helpers
|
|
265
|
+
- [Crypto Helper](../crypto/) - For cryptographic random values
|
|
266
|
+
|
|
267
|
+
- **External Resources:**
|
|
268
|
+
- [Snowflake ID](https://en.wikipedia.org/wiki/Snowflake_ID) - Snowflake algorithm explained
|
|
269
|
+
- [Base62 Encoding](https://en.wikipedia.org/wiki/Base62) - Base62 encoding overview
|
|
270
|
+
|
|
271
|
+
- **Best Practices:**
|
|
272
|
+
- [Data Modeling](/best-practices/data-modeling) - ID generation strategies
|