@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/dist/index.d.ts CHANGED
@@ -31,11 +31,61 @@ export interface TPSComponents {
31
31
  }
32
32
  /**
33
33
  * Interface for Calendar Driver plugins.
34
- * Implementations must provide conversion logic to/from Gregorian.
34
+ * Implementations provide conversion logic to/from Gregorian and support for
35
+ * external calendar libraries.
36
+ *
37
+ * @example Using a driver to parse a Hijri date string
38
+ * ```ts
39
+ * const driver = TPS.getDriver('hij');
40
+ * if (driver?.parseDate) {
41
+ * const components = driver.parseDate('1447-07-21');
42
+ * const gregDate = driver.toGregorian(components);
43
+ * const tpsString = TPS.fromDate(gregDate, 'hij');
44
+ * }
45
+ * ```
46
+ *
47
+ * @example Wrapping an external library (moment-hijri)
48
+ * ```ts
49
+ * import moment from 'moment-hijri';
50
+ *
51
+ * class HijriDriver implements CalendarDriver {
52
+ * readonly code = 'hij';
53
+ *
54
+ * parseDate(input: string, format?: string): Partial<TPSComponents> {
55
+ * const m = moment(input, format || 'iYYYY-iMM-iDD');
56
+ * return {
57
+ * calendar: 'hij',
58
+ * year: m.iYear(),
59
+ * month: m.iMonth() + 1,
60
+ * day: m.iDate()
61
+ * };
62
+ * }
63
+ *
64
+ * fromGregorian(date: Date): Partial<TPSComponents> {
65
+ * const m = moment(date);
66
+ * return {
67
+ * calendar: 'hij',
68
+ * year: m.iYear(),
69
+ * month: m.iMonth() + 1,
70
+ * day: m.iDate(),
71
+ * hour: m.hour(),
72
+ * minute: m.minute(),
73
+ * second: m.second()
74
+ * };
75
+ * }
76
+ *
77
+ * // ... other methods
78
+ * }
79
+ * ```
35
80
  */
36
81
  export interface CalendarDriver {
37
82
  /** The calendar code this driver handles (e.g., 'hij', 'jul'). */
38
83
  readonly code: CalendarCode;
84
+ /**
85
+ * Human-readable name for this calendar (optional).
86
+ * @example "Hijri (Islamic)"
87
+ */
88
+ readonly name?: string;
39
89
  /**
40
90
  * Converts a Gregorian Date to this calendar's components.
41
91
  * @param date - The Gregorian Date object.
@@ -51,9 +101,87 @@ export interface CalendarDriver {
51
101
  /**
52
102
  * Generates a TPS time string for this calendar from a Date.
53
103
  * @param date - The Gregorian Date object.
54
- * @returns A TPS time string (e.g., "T:hij.m2.c5.y47...").
104
+ * @returns A TPS time string (e.g., "T:hij.y1447.M07.d21...").
55
105
  */
56
106
  fromDate(date: Date): string;
107
+ /**
108
+ * Parse a calendar-specific date string into TPS components.
109
+ * This allows drivers to handle native date formats from external libraries.
110
+ *
111
+ * @param input - Date string in calendar-native format (e.g., '1447-07-21' for Hijri)
112
+ * @param format - Optional format string (driver-specific, e.g., 'iYYYY-iMM-iDD')
113
+ * @returns Partial TPS components
114
+ *
115
+ * @example
116
+ * ```ts
117
+ * // Hijri driver
118
+ * driver.parseDate('1447-07-21'); // → { year: 1447, month: 7, day: 21, calendar: 'hij' }
119
+ *
120
+ * // With time
121
+ * driver.parseDate('1447-07-21 14:30:00'); // → { year: 1447, month: 7, day: 21, hour: 14, ... }
122
+ * ```
123
+ */
124
+ parseDate?(input: string, format?: string): Partial<TPSComponents>;
125
+ /**
126
+ * Format TPS components to a calendar-specific date string.
127
+ * Inverse of parseDate().
128
+ *
129
+ * @param components - TPS components to format
130
+ * @param format - Optional format string (driver-specific)
131
+ * @returns Formatted date string in calendar-native format
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * driver.format({ year: 1447, month: 7, day: 21 }); // → '1447-07-21'
136
+ * driver.format({ year: 1447, month: 7, day: 21 }, 'short'); // → '21/7/1447'
137
+ * ```
138
+ */
139
+ format?(components: Partial<TPSComponents>, format?: string): string;
140
+ /**
141
+ * Validate a calendar-specific date string or components.
142
+ *
143
+ * @param input - Date string or components to validate
144
+ * @returns true if valid for this calendar
145
+ *
146
+ * @example
147
+ * ```ts
148
+ * driver.validate('1447-13-01'); // → false (month 13 invalid)
149
+ * driver.validate({ year: 1447, month: 7, day: 31 }); // → false (Rajab has 30 days)
150
+ * ```
151
+ */
152
+ validate?(input: string | Partial<TPSComponents>): boolean;
153
+ /**
154
+ * Get calendar metadata (month names, day names, etc.).
155
+ * Useful for UI rendering.
156
+ *
157
+ * @example
158
+ * ```ts
159
+ * driver.getMetadata().monthNames
160
+ * // → ['Muharram', 'Safar', 'Rabi I', ...]
161
+ * ```
162
+ */
163
+ getMetadata?(): CalendarMetadata;
164
+ }
165
+ /**
166
+ * Metadata about a calendar system.
167
+ */
168
+ export interface CalendarMetadata {
169
+ /** Human-readable calendar name */
170
+ name: string;
171
+ /** Month names in order (1-12 or 1-13) */
172
+ monthNames?: string[];
173
+ /** Short month names */
174
+ monthNamesShort?: string[];
175
+ /** Day of week names (Sunday=0 or locale-specific) */
176
+ dayNames?: string[];
177
+ /** Short day names */
178
+ dayNamesShort?: string[];
179
+ /** Whether this calendar is lunar-based */
180
+ isLunar?: boolean;
181
+ /** Number of months per year */
182
+ monthsPerYear?: number;
183
+ /** Epoch year (for reference) */
184
+ epochYear?: number;
57
185
  }
58
186
  export declare class TPS {
59
187
  private static readonly drivers;
@@ -101,6 +229,242 @@ export declare class TPS {
101
229
  * @returns JS Date object or `null` if invalid.
102
230
  */
103
231
  static toDate(tpsString: string): Date | null;
232
+ /**
233
+ * Parse a calendar-specific date string into TPS components.
234
+ * Requires the driver to implement the optional `parseDate` method.
235
+ *
236
+ * @param calendar - The calendar code (e.g., 'hij')
237
+ * @param dateString - Date string in calendar-native format (e.g., '1447-07-21')
238
+ * @param format - Optional format string (driver-specific)
239
+ * @returns TPS components or null if parsing fails
240
+ *
241
+ * @example
242
+ * ```ts
243
+ * const components = TPS.parseCalendarDate('hij', '1447-07-21');
244
+ * // { calendar: 'hij', year: 1447, month: 7, day: 21 }
245
+ *
246
+ * const uri = TPS.toURI({ ...components, latitude: 31.95, longitude: 35.91 });
247
+ * // "tps://31.95,35.91@T:hij.y1447.M07.d21"
248
+ * ```
249
+ */
250
+ static parseCalendarDate(calendar: CalendarCode, dateString: string, format?: string): Partial<TPSComponents> | null;
251
+ /**
252
+ * Convert a calendar-specific date string directly to a TPS URI.
253
+ * This is a convenience method that combines parseDate + toURI.
254
+ *
255
+ * @param calendar - The calendar code (e.g., 'hij')
256
+ * @param dateString - Date string in calendar-native format
257
+ * @param location - Optional location (lat/lon/alt or privacy flag)
258
+ * @returns Full TPS URI string
259
+ *
260
+ * @example
261
+ * ```ts
262
+ * // With coordinates
263
+ * TPS.fromCalendarDate('hij', '1447-07-21', { latitude: 31.95, longitude: 35.91 });
264
+ * // "tps://31.95,35.91@T:hij.y1447.M07.d21"
265
+ *
266
+ * // With privacy flag
267
+ * TPS.fromCalendarDate('hij', '1447-07-21', { isHiddenLocation: true });
268
+ * // "tps://hidden@T:hij.y1447.M07.d21"
269
+ *
270
+ * // Without location
271
+ * TPS.fromCalendarDate('hij', '1447-07-21');
272
+ * // "tps://unknown@T:hij.y1447.M07.d21"
273
+ * ```
274
+ */
275
+ static fromCalendarDate(calendar: CalendarCode, dateString: string, location?: {
276
+ latitude?: number;
277
+ longitude?: number;
278
+ altitude?: number;
279
+ isUnknownLocation?: boolean;
280
+ isHiddenLocation?: boolean;
281
+ isRedactedLocation?: boolean;
282
+ }): string;
283
+ /**
284
+ * Format TPS components to a calendar-specific date string.
285
+ * Requires the driver to implement the optional `format` method.
286
+ *
287
+ * @param calendar - The calendar code
288
+ * @param components - TPS components to format
289
+ * @param format - Optional format string (driver-specific)
290
+ * @returns Formatted date string in calendar-native format
291
+ *
292
+ * @example
293
+ * ```ts
294
+ * const tps = TPS.parse('tps://unknown@T:hij.y1447.M07.d21');
295
+ * const formatted = TPS.formatCalendarDate('hij', tps);
296
+ * // "1447-07-21"
297
+ * ```
298
+ */
299
+ static formatCalendarDate(calendar: CalendarCode, components: Partial<TPSComponents>, format?: string): string;
104
300
  private static _mapGroupsToComponents;
105
301
  private static pad;
106
302
  }
303
+ /**
304
+ * Decoded result from TPSUID7RB binary format.
305
+ */
306
+ export type TPSUID7RBDecodeResult = {
307
+ /** Version identifier */
308
+ version: 'tpsuid7rb';
309
+ /** Epoch milliseconds (UTC) */
310
+ epochMs: number;
311
+ /** Whether the TPS payload was compressed */
312
+ compressed: boolean;
313
+ /** 32-bit nonce for collision prevention */
314
+ nonce: number;
315
+ /** The original TPS string (exact reconstruction) */
316
+ tps: string;
317
+ };
318
+ /**
319
+ * Encoding options for TPSUID7RB.
320
+ */
321
+ export type TPSUID7RBEncodeOptions = {
322
+ /** Enable zlib compression of TPS payload */
323
+ compress?: boolean;
324
+ /** Override epoch milliseconds (default: parsed from TPS) */
325
+ epochMs?: number;
326
+ };
327
+ /**
328
+ * TPS-UID v1 — Temporal Positioning System Identifier (Binary Reversible)
329
+ *
330
+ * A time-first, reversible identifier that binds an event to a TPS coordinate.
331
+ * Unlike UUIDs, TPS-UID identifies events in spacetime and allows exact
332
+ * reconstruction of the original TPS string.
333
+ *
334
+ * Binary Schema (all integers big-endian):
335
+ * ```
336
+ * MAGIC 4 bytes "TPU7"
337
+ * VER 1 byte 0x01
338
+ * FLAGS 1 byte bit0 = compression flag
339
+ * TIME 6 bytes epoch_ms (48-bit unsigned)
340
+ * NONCE 4 bytes 32-bit random
341
+ * LEN varint length of TPS payload
342
+ * TPS bytes UTF-8 TPS string (raw or zlib-compressed)
343
+ * ```
344
+ *
345
+ * @example
346
+ * ```ts
347
+ * const tps = 'tps://31.95,35.91@T:greg.m3.c1.y26.M01.d09';
348
+ *
349
+ * // Encode to binary
350
+ * const bytes = TPSUID7RB.encodeBinary(tps);
351
+ *
352
+ * // Encode to base64url string
353
+ * const id = TPSUID7RB.encodeBinaryB64(tps);
354
+ * // → "tpsuid7rb_AFRQV..."
355
+ *
356
+ * // Decode back to original TPS
357
+ * const decoded = TPSUID7RB.decodeBinaryB64(id);
358
+ * console.log(decoded.tps); // exact original TPS
359
+ * ```
360
+ */
361
+ export declare class TPSUID7RB {
362
+ /** Magic bytes: "TPU7" */
363
+ private static readonly MAGIC;
364
+ /** Version 1 */
365
+ private static readonly VER;
366
+ /** String prefix for base64url encoded form */
367
+ private static readonly PREFIX;
368
+ /** Regex for validating base64url encoded form */
369
+ static readonly REGEX: RegExp;
370
+ /**
371
+ * Encode TPS string to binary bytes (Uint8Array).
372
+ * This is the canonical form for hashing, signing, and storage.
373
+ *
374
+ * @param tps - The TPS string to encode
375
+ * @param opts - Encoding options (compress, epochMs override)
376
+ * @returns Binary TPS-UID as Uint8Array
377
+ */
378
+ static encodeBinary(tps: string, opts?: TPSUID7RBEncodeOptions): Uint8Array;
379
+ /**
380
+ * Decode binary bytes back to original TPS string.
381
+ *
382
+ * @param bytes - Binary TPS-UID
383
+ * @returns Decoded result with original TPS string
384
+ */
385
+ static decodeBinary(bytes: Uint8Array): TPSUID7RBDecodeResult;
386
+ /**
387
+ * Encode TPS to base64url string with prefix.
388
+ * This is the transport/storage form.
389
+ *
390
+ * @param tps - The TPS string to encode
391
+ * @param opts - Encoding options
392
+ * @returns Base64url encoded TPS-UID with prefix
393
+ */
394
+ static encodeBinaryB64(tps: string, opts?: TPSUID7RBEncodeOptions): string;
395
+ /**
396
+ * Decode base64url string back to original TPS string.
397
+ *
398
+ * @param id - Base64url encoded TPS-UID with prefix
399
+ * @returns Decoded result with original TPS string
400
+ */
401
+ static decodeBinaryB64(id: string): TPSUID7RBDecodeResult;
402
+ /**
403
+ * Validate base64url encoded TPS-UID format.
404
+ * Note: This validates shape only; binary decode is authoritative.
405
+ *
406
+ * @param id - String to validate
407
+ * @returns true if format is valid
408
+ */
409
+ static validateBinaryB64(id: string): boolean;
410
+ /**
411
+ * Generate a TPS-UID from the current time and optional location.
412
+ *
413
+ * @param opts - Generation options
414
+ * @returns Base64url encoded TPS-UID
415
+ */
416
+ static generate(opts?: {
417
+ latitude?: number;
418
+ longitude?: number;
419
+ altitude?: number;
420
+ compress?: boolean;
421
+ }): string;
422
+ /**
423
+ * Generate a TPS string from a Date and optional location.
424
+ */
425
+ private static generateTPSString;
426
+ /**
427
+ * Parse epoch milliseconds from a TPS string.
428
+ * Supports both URI format (tps://...) and time-only format (T:greg...)
429
+ */
430
+ static epochMsFromTPSString(tps: string): number;
431
+ /** Write 48-bit unsigned integer (big-endian) */
432
+ private static writeU48;
433
+ /** Read 48-bit unsigned integer (big-endian) */
434
+ private static readU48;
435
+ /** Encode unsigned integer as LEB128 varint */
436
+ private static uvarintEncode;
437
+ /** Decode LEB128 varint */
438
+ private static uvarintDecode;
439
+ /** Encode bytes to base64url (no padding) */
440
+ private static base64UrlEncode;
441
+ /** Decode base64url to bytes */
442
+ private static base64UrlDecode;
443
+ /** Compress using zlib deflate raw */
444
+ private static deflateRaw;
445
+ /** Decompress using zlib inflate raw */
446
+ private static inflateRaw;
447
+ /**
448
+ * Seal (sign) a TPS string to create a cryptographically verifiable TPS-UID.
449
+ * This appends an Ed25519 signature to the binary form.
450
+ *
451
+ * @param tps - The TPS string to seal
452
+ * @param privateKey - Ed25519 private key (hex or buffer)
453
+ * @param opts - Encoding options
454
+ * @returns Sealed binary TPS-UID
455
+ */
456
+ static seal(tps: string, privateKey: string | Buffer | Uint8Array, opts?: TPSUID7RBEncodeOptions): Uint8Array;
457
+ /**
458
+ * Verify a sealed TPS-UID and decode it.
459
+ * Throws if signature is invalid or not sealed.
460
+ *
461
+ * @param sealedBytes - The binary sealed TPS-UID
462
+ * @param publicKey - Ed25519 public key (hex or buffer) to verify against
463
+ * @returns Decoded result
464
+ */
465
+ static verifyAndDecode(sealedBytes: Uint8Array, publicKey: string | Buffer | Uint8Array): TPSUID7RBDecodeResult;
466
+ private static signEd25519;
467
+ private static verifyEd25519;
468
+ /** Generate cryptographically secure random bytes */
469
+ private static randomBytes;
470
+ }