@nextera.one/tps-standard 0.4.2 → 0.5.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 +268 -49
- package/dist/index.d.ts +366 -2
- package/dist/index.js +724 -1
- package/dist/src/index.js +693 -0
- package/dist/test/src/index.js +960 -0
- package/dist/test/test/persian-calendar.test.js +488 -0
- package/dist/test/test/tps-uid.test.js +295 -0
- package/dist/test/tps-uid.test.js +240 -0
- package/package.json +3 -2
- package/src/index.ts +1031 -2
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ TPS defines a deterministic way to represent **when** something happened, **wher
|
|
|
7
7
|
## 📦 Installation
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm
|
|
10
|
+
npm i @nextera.one/tps-standard
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
## 🚀 Quick Start
|
|
@@ -15,27 +15,27 @@ npm install tps-standard
|
|
|
15
15
|
### Basic Example
|
|
16
16
|
|
|
17
17
|
```ts
|
|
18
|
-
import { TPS } from
|
|
18
|
+
import { TPS } from "tps-standard";
|
|
19
19
|
|
|
20
20
|
// Create a TPS time string from current date
|
|
21
|
-
const nowTime = TPS.fromDate(new Date(),
|
|
21
|
+
const nowTime = TPS.fromDate(new Date(), "greg");
|
|
22
22
|
console.log(nowTime);
|
|
23
23
|
// Output: "T:greg.m3.c1.y26.M01.d07.h13.n20.s45"
|
|
24
24
|
|
|
25
25
|
// Parse a full TPS URI with location and extensions
|
|
26
|
-
const uri =
|
|
26
|
+
const uri = "tps://31.95,35.91,800@T:greg.m3.c1.y26.M01.d07.h13.n20;f4;r7";
|
|
27
27
|
const parsed = TPS.parse(uri);
|
|
28
28
|
console.log(parsed);
|
|
29
29
|
// { latitude: 31.95, longitude: 35.91, altitude: 800, calendar: 'greg', year: 26, ... }
|
|
30
30
|
|
|
31
31
|
// Convert back to URI
|
|
32
32
|
const components = {
|
|
33
|
-
calendar:
|
|
33
|
+
calendar: "greg",
|
|
34
34
|
year: 26,
|
|
35
35
|
month: 1,
|
|
36
36
|
day: 7,
|
|
37
37
|
latitude: 31.95,
|
|
38
|
-
longitude: 35.91
|
|
38
|
+
longitude: 35.91,
|
|
39
39
|
};
|
|
40
40
|
const uriString = TPS.toURI(components);
|
|
41
41
|
console.log(uriString);
|
|
@@ -52,34 +52,35 @@ TPS represents time as a coordinate using this hierarchy:
|
|
|
52
52
|
T:greg.m3.c1.y26.M01.d07.h13.n20.s45
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
| Component | Meaning
|
|
56
|
-
|
|
57
|
-
| `greg`
|
|
58
|
-
| `m3`
|
|
59
|
-
| `c1`
|
|
60
|
-
| `y26`
|
|
61
|
-
| `M01`
|
|
62
|
-
| `d07`
|
|
63
|
-
| `h13`
|
|
64
|
-
| `n20`
|
|
65
|
-
| `s45`
|
|
55
|
+
| Component | Meaning |
|
|
56
|
+
| --------- | ------------------------- |
|
|
57
|
+
| `greg` | Calendar code (gregorian) |
|
|
58
|
+
| `m3` | Millennium 3 (2000-2999) |
|
|
59
|
+
| `c1` | Century 1 (2000-2099) |
|
|
60
|
+
| `y26` | Year 26 (2026) |
|
|
61
|
+
| `M01` | Month 01 (January) |
|
|
62
|
+
| `d07` | Day 07 |
|
|
63
|
+
| `h13` | Hour 13 (1:00 PM) |
|
|
64
|
+
| `n20` | Minute 20 |
|
|
65
|
+
| `s45` | Second 45 |
|
|
66
66
|
|
|
67
67
|
Partial coordinates represent **time volumes** (entire year, century, etc.).
|
|
68
68
|
|
|
69
69
|
### TPS URI Format
|
|
70
70
|
|
|
71
71
|
**Canonical form:**
|
|
72
|
+
|
|
72
73
|
```
|
|
73
74
|
tps://[SPACE]@[TIME][;EXTENSIONS]
|
|
74
75
|
```
|
|
75
76
|
|
|
76
77
|
#### Components
|
|
77
78
|
|
|
78
|
-
| Component
|
|
79
|
-
|
|
80
|
-
| `SPACE`
|
|
81
|
-
| `TIME`
|
|
82
|
-
| `EXTENSIONS` | Optional context (key-value pairs separated by dots)
|
|
79
|
+
| Component | Description |
|
|
80
|
+
| ------------ | --------------------------------------------------------- |
|
|
81
|
+
| `SPACE` | `lat,lon[,alt]m` (WGS84) or `unknown`/`hidden`/`redacted` |
|
|
82
|
+
| `TIME` | TPS Time format (`T:calendar.hierarchy`) |
|
|
83
|
+
| `EXTENSIONS` | Optional context (key-value pairs separated by dots) |
|
|
83
84
|
|
|
84
85
|
#### Location Privacy
|
|
85
86
|
|
|
@@ -92,57 +93,156 @@ tps://[SPACE]@[TIME][;EXTENSIONS]
|
|
|
92
93
|
|
|
93
94
|
- `greg` — Gregorian calendar (default)
|
|
94
95
|
- `unix` — Unix epoch seconds
|
|
95
|
-
- `hij` — Hijri (Islamic) —
|
|
96
|
-
- `jul` — Julian —
|
|
97
|
-
- `holo` — Holocene —
|
|
96
|
+
- `hij` — Hijri (Islamic) — _requires driver_
|
|
97
|
+
- `jul` — Julian — _requires driver_
|
|
98
|
+
- `holo` — Holocene — _requires driver_
|
|
98
99
|
|
|
99
100
|
## 🔌 Plugin Architecture
|
|
100
101
|
|
|
101
|
-
TPS supports custom calendar drivers for non-Gregorian systems.
|
|
102
|
+
TPS supports custom calendar drivers for non-Gregorian systems. Drivers can wrap external date libraries (like `moment-hijri`, `@js-joda/extra`, etc.).
|
|
102
103
|
|
|
103
104
|
### CalendarDriver Interface
|
|
104
105
|
|
|
105
106
|
```ts
|
|
106
107
|
export interface CalendarDriver {
|
|
107
108
|
readonly code: CalendarCode;
|
|
109
|
+
readonly name?: string; // Optional human-readable name
|
|
110
|
+
|
|
111
|
+
// Required methods
|
|
108
112
|
fromGregorian(date: Date): Partial<TPSComponents>;
|
|
109
113
|
toGregorian(components: Partial<TPSComponents>): Date;
|
|
110
114
|
fromDate(date: Date): string;
|
|
115
|
+
|
|
116
|
+
// Optional enhanced methods
|
|
117
|
+
parseDate?(input: string, format?: string): Partial<TPSComponents>;
|
|
118
|
+
format?(components: Partial<TPSComponents>, format?: string): string;
|
|
119
|
+
validate?(input: string | Partial<TPSComponents>): boolean;
|
|
120
|
+
getMetadata?(): CalendarMetadata;
|
|
111
121
|
}
|
|
112
122
|
```
|
|
113
123
|
|
|
114
124
|
### Register a Custom Driver
|
|
115
125
|
|
|
116
126
|
```ts
|
|
117
|
-
import { TPS, CalendarDriver, TPSComponents } from
|
|
127
|
+
import { TPS, CalendarDriver, TPSComponents } from "@nextera.one/tps-standard";
|
|
118
128
|
|
|
119
129
|
class HijriDriver implements CalendarDriver {
|
|
120
|
-
readonly code =
|
|
130
|
+
readonly code = "hij";
|
|
131
|
+
readonly name = "Hijri (Islamic)";
|
|
132
|
+
|
|
133
|
+
// Parse a Hijri date string like '1447-07-21'
|
|
134
|
+
parseDate(input: string): Partial<TPSComponents> {
|
|
135
|
+
const [year, month, day] = input.split("-").map(Number);
|
|
136
|
+
return { calendar: "hij", year, month, day };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Format components to Hijri date string
|
|
140
|
+
format(comp: Partial<TPSComponents>): string {
|
|
141
|
+
return `${comp.year}-${String(comp.month).padStart(2, "0")}-${String(
|
|
142
|
+
comp.day
|
|
143
|
+
).padStart(2, "0")}`;
|
|
144
|
+
}
|
|
121
145
|
|
|
122
146
|
fromGregorian(date: Date): Partial<TPSComponents> {
|
|
123
|
-
//
|
|
124
|
-
//
|
|
125
|
-
|
|
147
|
+
// Use external library for accurate conversion
|
|
148
|
+
// Example with moment-hijri:
|
|
149
|
+
// const m = moment(date);
|
|
150
|
+
// return { year: m.iYear(), month: m.iMonth() + 1, day: m.iDate() };
|
|
151
|
+
return { year: 1447, month: 7, day: 21 };
|
|
126
152
|
}
|
|
127
153
|
|
|
128
154
|
toGregorian(components: Partial<TPSComponents>): Date {
|
|
129
|
-
//
|
|
130
|
-
// ... conversion logic ...
|
|
155
|
+
// Reverse conversion using external library
|
|
131
156
|
return new Date();
|
|
132
157
|
}
|
|
133
158
|
|
|
134
159
|
fromDate(date: Date): string {
|
|
135
160
|
const comp = this.fromGregorian(date);
|
|
136
|
-
|
|
161
|
+
const pad = (n?: number) => String(n || 0).padStart(2, "0");
|
|
162
|
+
return `T:hij.y${comp.year}.M${pad(comp.month)}.d${pad(comp.day)}`;
|
|
137
163
|
}
|
|
138
164
|
}
|
|
139
165
|
|
|
140
166
|
// Register the driver
|
|
141
167
|
TPS.registerDriver(new HijriDriver());
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Using Calendar Drivers
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
// Parse a Hijri date string directly
|
|
174
|
+
const components = TPS.parseCalendarDate("hij", "1447-07-21");
|
|
175
|
+
// { calendar: 'hij', year: 1447, month: 7, day: 21 }
|
|
176
|
+
|
|
177
|
+
// Convert to TPS URI with location
|
|
178
|
+
const uri = TPS.fromCalendarDate("hij", "1447-07-21", {
|
|
179
|
+
latitude: 31.95,
|
|
180
|
+
longitude: 35.91,
|
|
181
|
+
});
|
|
182
|
+
// "tps://31.95,35.91@T:hij.y1447.M07.d21"
|
|
183
|
+
|
|
184
|
+
// Format TPS components back to calendar-native string
|
|
185
|
+
const parsed = TPS.parse("tps://unknown@T:hij.y1447.M07.d21");
|
|
186
|
+
const formatted = TPS.formatCalendarDate("hij", parsed);
|
|
187
|
+
// "1447-07-21"
|
|
188
|
+
|
|
189
|
+
// Using the driver directly
|
|
190
|
+
const driver = TPS.getDriver("hij");
|
|
191
|
+
if (driver?.parseDate) {
|
|
192
|
+
const comp = driver.parseDate("1447-07-21");
|
|
193
|
+
const gregDate = driver.toGregorian(comp);
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Wrapping External Libraries
|
|
198
|
+
|
|
199
|
+
Example with `moment-hijri`:
|
|
142
200
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
201
|
+
```ts
|
|
202
|
+
import moment from "moment-hijri";
|
|
203
|
+
|
|
204
|
+
class MomentHijriDriver implements CalendarDriver {
|
|
205
|
+
readonly code = "hij";
|
|
206
|
+
|
|
207
|
+
parseDate(input: string, format = "iYYYY-iMM-iDD"): Partial<TPSComponents> {
|
|
208
|
+
const m = moment(input, format);
|
|
209
|
+
return {
|
|
210
|
+
calendar: "hij",
|
|
211
|
+
year: m.iYear(),
|
|
212
|
+
month: m.iMonth() + 1,
|
|
213
|
+
day: m.iDate(),
|
|
214
|
+
hour: m.hour(),
|
|
215
|
+
minute: m.minute(),
|
|
216
|
+
second: m.second(),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
fromGregorian(date: Date): Partial<TPSComponents> {
|
|
221
|
+
const m = moment(date);
|
|
222
|
+
return {
|
|
223
|
+
calendar: "hij",
|
|
224
|
+
year: m.iYear(),
|
|
225
|
+
month: m.iMonth() + 1,
|
|
226
|
+
day: m.iDate(),
|
|
227
|
+
hour: m.hour(),
|
|
228
|
+
minute: m.minute(),
|
|
229
|
+
second: m.second(),
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
toGregorian(comp: Partial<TPSComponents>): Date {
|
|
234
|
+
const m = moment(`${comp.year}-${comp.month}-${comp.day}`, "iYYYY-iM-iD");
|
|
235
|
+
return m.toDate();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
fromDate(date: Date): string {
|
|
239
|
+
const c = this.fromGregorian(date);
|
|
240
|
+
const p = (n?: number) => String(n || 0).padStart(2, "0");
|
|
241
|
+
return `T:hij.y${c.year}.M${p(c.month)}.d${p(c.day)}.h${p(c.hour)}.n${p(
|
|
242
|
+
c.minute
|
|
243
|
+
)}.s${p(c.second)}`;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
146
246
|
```
|
|
147
247
|
|
|
148
248
|
## 📚 API Reference
|
|
@@ -152,8 +252,8 @@ console.log(hijriTime);
|
|
|
152
252
|
Validates whether a string is properly formatted TPS.
|
|
153
253
|
|
|
154
254
|
```ts
|
|
155
|
-
TPS.validate(
|
|
156
|
-
TPS.validate(
|
|
255
|
+
TPS.validate("tps://31.95,35.91@T:greg.m3.c1.y26"); // true
|
|
256
|
+
TPS.validate("invalid"); // false
|
|
157
257
|
```
|
|
158
258
|
|
|
159
259
|
### `TPS.parse(input: string): TPSComponents | null`
|
|
@@ -161,7 +261,9 @@ TPS.validate('invalid'); // false
|
|
|
161
261
|
Parses a TPS string into components. Returns `null` if invalid.
|
|
162
262
|
|
|
163
263
|
```ts
|
|
164
|
-
const parsed = TPS.parse(
|
|
264
|
+
const parsed = TPS.parse(
|
|
265
|
+
"tps://31.95,35.91,800@T:greg.m3.c1.y26.M01.d07.h13.n20;f4;r7"
|
|
266
|
+
);
|
|
165
267
|
// {
|
|
166
268
|
// latitude: 31.95,
|
|
167
269
|
// longitude: 35.91,
|
|
@@ -184,14 +286,14 @@ Converts a components object into a canonical TPS URI string.
|
|
|
184
286
|
|
|
185
287
|
```ts
|
|
186
288
|
const components = {
|
|
187
|
-
calendar:
|
|
289
|
+
calendar: "greg",
|
|
188
290
|
year: 26,
|
|
189
291
|
month: 1,
|
|
190
292
|
day: 7,
|
|
191
293
|
latitude: 31.95,
|
|
192
294
|
longitude: 35.91,
|
|
193
295
|
altitude: 800,
|
|
194
|
-
extensions: { f: "4", r: "7" }
|
|
296
|
+
extensions: { f: "4", r: "7" },
|
|
195
297
|
};
|
|
196
298
|
const uri = TPS.toURI(components);
|
|
197
299
|
// "tps://31.95,35.91,800m@T:greg.y26.M01.d07;f4.r7"
|
|
@@ -202,10 +304,10 @@ const uri = TPS.toURI(components);
|
|
|
202
304
|
Generates a TPS time string from a JavaScript Date. Supports registered drivers.
|
|
203
305
|
|
|
204
306
|
```ts
|
|
205
|
-
const timeString = TPS.fromDate(new Date(),
|
|
307
|
+
const timeString = TPS.fromDate(new Date(), "greg");
|
|
206
308
|
// "T:greg.m3.c1.y26.M01.d07.h13.n20.s45"
|
|
207
309
|
|
|
208
|
-
const unixTime = TPS.fromDate(new Date(),
|
|
310
|
+
const unixTime = TPS.fromDate(new Date(), "unix");
|
|
209
311
|
// "T:unix.s1704729645.123"
|
|
210
312
|
```
|
|
211
313
|
|
|
@@ -214,7 +316,7 @@ const unixTime = TPS.fromDate(new Date(), 'unix');
|
|
|
214
316
|
Converts a TPS string back to a JavaScript Date object.
|
|
215
317
|
|
|
216
318
|
```ts
|
|
217
|
-
const date = TPS.toDate(
|
|
319
|
+
const date = TPS.toDate("T:greg.m3.c1.y26.M01.d07.h13.n20.s45");
|
|
218
320
|
console.log(date); // Date object for 2026-01-07 13:20:45 UTC
|
|
219
321
|
```
|
|
220
322
|
|
|
@@ -223,8 +325,8 @@ console.log(date); // Date object for 2026-01-07 13:20:45 UTC
|
|
|
223
325
|
Converts a TPS string from one calendar to another using registered drivers.
|
|
224
326
|
|
|
225
327
|
```ts
|
|
226
|
-
const gregTime =
|
|
227
|
-
const hijriTime = TPS.to(
|
|
328
|
+
const gregTime = "T:greg.m3.c1.y26.M01.d07";
|
|
329
|
+
const hijriTime = TPS.to("hij", gregTime);
|
|
228
330
|
// Requires registered Hijri driver
|
|
229
331
|
```
|
|
230
332
|
|
|
@@ -242,7 +344,7 @@ TPS.registerDriver(hijriDriver);
|
|
|
242
344
|
Retrieves a registered calendar driver.
|
|
243
345
|
|
|
244
346
|
```ts
|
|
245
|
-
const driver = TPS.getDriver(
|
|
347
|
+
const driver = TPS.getDriver("hij");
|
|
246
348
|
if (driver) {
|
|
247
349
|
const components = driver.fromGregorian(new Date());
|
|
248
350
|
}
|
|
@@ -284,7 +386,124 @@ interface TPSComponents {
|
|
|
284
386
|
### `CalendarCode`
|
|
285
387
|
|
|
286
388
|
```ts
|
|
287
|
-
type CalendarCode =
|
|
389
|
+
type CalendarCode = "greg" | "hij" | "jul" | "holo" | "unix";
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
## 🆔 TPS-UID — Temporal Positioning Identifier
|
|
393
|
+
|
|
394
|
+
TPS-UID is a **time-first, reversible identifier** format that binds an event to a TPS coordinate. Unlike UUIDs which identify records, TPS-UID identifies **events in spacetime** and allows exact reconstruction of the original TPS string.
|
|
395
|
+
|
|
396
|
+
### Why TPS-UID?
|
|
397
|
+
|
|
398
|
+
| Feature | UUID v4/v7 | TPS-UID |
|
|
399
|
+
| ----------------- | ---------------- | --------------- |
|
|
400
|
+
| **Purpose** | Identify objects | Identify events |
|
|
401
|
+
| **Time** | Optional/weak | Mandatory |
|
|
402
|
+
| **Reversible** | ❌ No | ✅ Yes |
|
|
403
|
+
| **Time-sortable** | v7 only | ✅ Always |
|
|
404
|
+
| **Audit-grade** | ❌ No | ✅ Yes |
|
|
405
|
+
|
|
406
|
+
### Binary Schema
|
|
407
|
+
|
|
408
|
+
```
|
|
409
|
+
MAGIC 4 bytes "TPU7"
|
|
410
|
+
VER 1 byte 0x01
|
|
411
|
+
FLAGS 1 byte bit0 = compression
|
|
412
|
+
TIME 6 bytes 48-bit epoch ms
|
|
413
|
+
NONCE 4 bytes collision guard
|
|
414
|
+
LEN varint payload length
|
|
415
|
+
TPS bytes UTF-8 TPS string
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Quick Start
|
|
419
|
+
|
|
420
|
+
```ts
|
|
421
|
+
import { TPSUID7RB } from "@nextera.one/tps-standard";
|
|
422
|
+
|
|
423
|
+
// Create TPS-UID from a TPS string
|
|
424
|
+
const tps = "tps://31.95,35.91@T:greg.m3.c1.y26.M01.d09.h14.n30.s25";
|
|
425
|
+
const id = TPSUID7RB.encodeBinaryB64(tps);
|
|
426
|
+
// → "tpsuid7rb_VFBVNwEAAZujKmvo..."
|
|
427
|
+
|
|
428
|
+
// Decode back to original TPS (exact reconstruction)
|
|
429
|
+
const decoded = TPSUID7RB.decodeBinaryB64(id);
|
|
430
|
+
console.log(decoded.tps); // exact original TPS
|
|
431
|
+
console.log(decoded.epochMs); // 1767969025000
|
|
432
|
+
|
|
433
|
+
// Generate from current time
|
|
434
|
+
const generated = TPSUID7RB.generate({
|
|
435
|
+
latitude: 32.0,
|
|
436
|
+
longitude: 35.0,
|
|
437
|
+
});
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### API Reference
|
|
441
|
+
|
|
442
|
+
#### `TPSUID7RB.encodeBinary(tps, opts?): Uint8Array`
|
|
443
|
+
|
|
444
|
+
Encode TPS string to binary bytes (canonical form).
|
|
445
|
+
|
|
446
|
+
```ts
|
|
447
|
+
const bytes = TPSUID7RB.encodeBinary(tps, { compress: true });
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
#### `TPSUID7RB.decodeBinary(bytes): TPSUID7RBDecodeResult`
|
|
451
|
+
|
|
452
|
+
Decode binary bytes back to original TPS.
|
|
453
|
+
|
|
454
|
+
```ts
|
|
455
|
+
const decoded = TPSUID7RB.decodeBinary(bytes);
|
|
456
|
+
// { version: 'tpsuid7rb', epochMs, compressed, nonce, tps }
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
#### `TPSUID7RB.encodeBinaryB64(tps, opts?): string`
|
|
460
|
+
|
|
461
|
+
Encode to base64url string with prefix (transport form).
|
|
462
|
+
|
|
463
|
+
```ts
|
|
464
|
+
const id = TPSUID7RB.encodeBinaryB64(tps, { compress: true });
|
|
465
|
+
// "tpsuid7rb_..."
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
#### `TPSUID7RB.decodeBinaryB64(id): TPSUID7RBDecodeResult`
|
|
469
|
+
|
|
470
|
+
Decode base64url string back to original TPS.
|
|
471
|
+
|
|
472
|
+
```ts
|
|
473
|
+
const decoded = TPSUID7RB.decodeBinaryB64(id);
|
|
474
|
+
console.log(decoded.tps); // exact original
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
#### `TPSUID7RB.validateBinaryB64(id): boolean`
|
|
478
|
+
|
|
479
|
+
Validate base64url encoded TPS-UID format.
|
|
480
|
+
|
|
481
|
+
```ts
|
|
482
|
+
TPSUID7RB.validateBinaryB64("tpsuid7rb_VFB..."); // true
|
|
483
|
+
TPSUID7RB.validateBinaryB64("invalid"); // false
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
#### `TPSUID7RB.generate(opts?): string`
|
|
487
|
+
|
|
488
|
+
Generate TPS-UID from current time.
|
|
489
|
+
|
|
490
|
+
```ts
|
|
491
|
+
const id = TPSUID7RB.generate({
|
|
492
|
+
latitude: 32.0,
|
|
493
|
+
longitude: 35.0,
|
|
494
|
+
compress: true,
|
|
495
|
+
});
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### Database Schema (Recommended)
|
|
499
|
+
|
|
500
|
+
```sql
|
|
501
|
+
CREATE TABLE events (
|
|
502
|
+
epoch_ms BIGINT NOT NULL,
|
|
503
|
+
tps_uid VARBINARY(96) NOT NULL,
|
|
504
|
+
tps TEXT NOT NULL,
|
|
505
|
+
PRIMARY KEY (epoch_ms, tps_uid)
|
|
506
|
+
);
|
|
288
507
|
```
|
|
289
508
|
|
|
290
509
|
## 🎯 Use Cases
|