@tnid/core 0.0.6 → 0.0.7
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 +46 -29
- package/esm/dynamic.d.ts +13 -11
- package/esm/dynamic.d.ts.map +1 -1
- package/esm/dynamic.js +26 -13
- package/esm/factory.d.ts.map +1 -1
- package/esm/factory.js +15 -3
- package/esm/types.d.ts +16 -7
- package/esm/types.d.ts.map +1 -1
- package/package.json +4 -3
- package/script/dynamic.d.ts +13 -11
- package/script/dynamic.d.ts.map +1 -1
- package/script/dynamic.js +26 -13
- package/script/factory.d.ts.map +1 -1
- package/script/factory.js +12 -0
- package/script/types.d.ts +16 -7
- package/script/types.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -52,6 +52,19 @@ const parsed: UserId = UserId.parse("user.Br2flcNDfF6LYICnT");
|
|
|
52
52
|
// Convert to/from UUID format
|
|
53
53
|
const uuid: string = UserId.toUuidString(id); // "d6157329-4640-8e30-..."
|
|
54
54
|
const fromUuid: UserId = UserId.parseUuidString(uuid);
|
|
55
|
+
|
|
56
|
+
// Works great with Zod
|
|
57
|
+
import { z } from "zod";
|
|
58
|
+
const UserSchema = z.object({
|
|
59
|
+
id: z.string().transform(UserId.parse),
|
|
60
|
+
name: z.string(),
|
|
61
|
+
});
|
|
62
|
+
interface User extends z.infer<typeof UserSchema> {} // { id: UserId; name: string }
|
|
63
|
+
|
|
64
|
+
const user: User = UserSchema.parse({
|
|
65
|
+
id: "user.Br2flcNDfF6LYICnT",
|
|
66
|
+
name: "Alice",
|
|
67
|
+
});
|
|
55
68
|
```
|
|
56
69
|
|
|
57
70
|
## Features
|
|
@@ -87,8 +100,8 @@ id === otherUserId; // true/false
|
|
|
87
100
|
import {
|
|
88
101
|
Case, // "lower" | "upper"
|
|
89
102
|
DynamicTnid, // Runtime TNID operations (type + namespace)
|
|
90
|
-
Tnid, // NamedTnid creator function
|
|
91
103
|
NamedTnid, // NamedTnid interface
|
|
104
|
+
Tnid, // NamedTnid creator function
|
|
92
105
|
TnidType, // Type helper to extract ID type
|
|
93
106
|
// Types only:
|
|
94
107
|
TnidValue, // Branded string type
|
|
@@ -100,8 +113,8 @@ import {
|
|
|
100
113
|
|
|
101
114
|
### `Tnid(name)`
|
|
102
115
|
|
|
103
|
-
Creates a `NamedTnid` for a specific name. The name is validated at
|
|
104
|
-
|
|
116
|
+
Creates a `NamedTnid` for a specific name. The name is validated at **compile
|
|
117
|
+
time**.
|
|
105
118
|
|
|
106
119
|
```typescript
|
|
107
120
|
const UserId = Tnid("user");
|
|
@@ -138,27 +151,27 @@ Tnid(""); // empty not allowed
|
|
|
138
151
|
const UserId = Tnid("user");
|
|
139
152
|
type UserId = TnidType<typeof UserId>;
|
|
140
153
|
|
|
141
|
-
UserId.new_v0();
|
|
142
|
-
UserId.new_v1();
|
|
143
|
-
UserId.v0_from_parts(1234567890n, 0n);
|
|
144
|
-
UserId.v1_from_parts(0n);
|
|
154
|
+
UserId.new_v0(); // time-ordered ID
|
|
155
|
+
UserId.new_v1(); // high-entropy random ID
|
|
156
|
+
UserId.v0_from_parts(1234567890n, 0n); // V0 with explicit timestamp/random
|
|
157
|
+
UserId.v1_from_parts(0n); // V1 with explicit random bits
|
|
145
158
|
```
|
|
146
159
|
|
|
147
160
|
#### Parsing
|
|
148
161
|
|
|
149
162
|
```typescript
|
|
150
|
-
UserId.parse("user.Br2flcNDfF6LYICnT");
|
|
151
|
-
UserId.parseUuidString("d6157329-4640-8e30-...");
|
|
163
|
+
UserId.parse("user.Br2flcNDfF6LYICnT"); // parse TNID string
|
|
164
|
+
UserId.parseUuidString("d6157329-4640-8e30-..."); // parse UUID hex string
|
|
152
165
|
```
|
|
153
166
|
|
|
154
167
|
#### Inspection and Conversion
|
|
155
168
|
|
|
156
169
|
```typescript
|
|
157
|
-
UserId.name;
|
|
158
|
-
UserId.variant(id);
|
|
159
|
-
UserId.toUuidString(id);
|
|
170
|
+
UserId.name; // "user" - the TNID name
|
|
171
|
+
UserId.variant(id); // "v0" or "v1" - get the variant
|
|
172
|
+
UserId.toUuidString(id); // "d6157329-4640-8e30-..." - convert to UUID
|
|
160
173
|
UserId.toUuidString(id, "upper"); // "D6157329-4640-8E30-..." - uppercase UUID
|
|
161
|
-
UserId.nameHex();
|
|
174
|
+
UserId.nameHex(); // "d6157" - name as 5-char hex
|
|
162
175
|
```
|
|
163
176
|
|
|
164
177
|
### `TnidType<T>`
|
|
@@ -188,23 +201,27 @@ function logAnyId(id: DynamicTnid) {
|
|
|
188
201
|
}
|
|
189
202
|
|
|
190
203
|
// Generation with runtime names
|
|
191
|
-
DynamicTnid.
|
|
192
|
-
DynamicTnid.
|
|
204
|
+
DynamicTnid.newV0("user"); // time-ordered (alias: newTimeOrdered)
|
|
205
|
+
DynamicTnid.newV1("user"); // high-entropy (alias: newHighEntropy)
|
|
193
206
|
|
|
194
207
|
// Generation with explicit values (useful for testing/migrations)
|
|
195
|
-
DynamicTnid.
|
|
196
|
-
DynamicTnid.
|
|
197
|
-
DynamicTnid.
|
|
208
|
+
DynamicTnid.newV0WithTime("user", new Date("2024-01-15"));
|
|
209
|
+
DynamicTnid.newV0WithParts("user", 1705312800000n, 123n);
|
|
210
|
+
DynamicTnid.newV1WithRandom("user", 0x123456789abcdef0123456789n);
|
|
211
|
+
|
|
212
|
+
// Parsing (auto-detects format)
|
|
213
|
+
DynamicTnid.parse("post.EUBcUw4T9x3KNOll-"); // TNID string
|
|
214
|
+
DynamicTnid.parse("d6157329-4640-..."); // UUID string
|
|
198
215
|
|
|
199
|
-
//
|
|
200
|
-
DynamicTnid.
|
|
201
|
-
DynamicTnid.
|
|
216
|
+
// Or use explicit parse methods
|
|
217
|
+
DynamicTnid.parseTnidString("post.EUBcUw4T9x3KNOll-");
|
|
218
|
+
DynamicTnid.parseUuidString("d6157329-4640-...");
|
|
202
219
|
|
|
203
220
|
// Inspection
|
|
204
|
-
DynamicTnid.getName(id);
|
|
205
|
-
DynamicTnid.getNameHex(id);
|
|
206
|
-
DynamicTnid.getVariant(id);
|
|
207
|
-
DynamicTnid.toUuidString(id);
|
|
221
|
+
DynamicTnid.getName(id); // "user"
|
|
222
|
+
DynamicTnid.getNameHex(id); // "d6157"
|
|
223
|
+
DynamicTnid.getVariant(id); // "v0" or "v1"
|
|
224
|
+
DynamicTnid.toUuidString(id); // UUID hex string
|
|
208
225
|
```
|
|
209
226
|
|
|
210
227
|
### `UuidLike`
|
|
@@ -212,10 +229,10 @@ DynamicTnid.toUuidString(id); // UUID hex string
|
|
|
212
229
|
For working with UUID hex strings that may or may not be valid TNIDs.
|
|
213
230
|
|
|
214
231
|
```typescript
|
|
215
|
-
UuidLike.fromTnid(id);
|
|
216
|
-
UuidLike.parse(s);
|
|
217
|
-
UuidLike.toTnid(uuid);
|
|
218
|
-
UuidLike.toUpperCase(uuid);
|
|
232
|
+
UuidLike.fromTnid(id); // convert TNID to UUID string
|
|
233
|
+
UuidLike.parse(s); // parse any UUID (validates format only)
|
|
234
|
+
UuidLike.toTnid(uuid); // convert UUID to TNID (throws if invalid)
|
|
235
|
+
UuidLike.toUpperCase(uuid); // convert to uppercase
|
|
219
236
|
```
|
|
220
237
|
|
|
221
238
|
## Variants
|
package/esm/dynamic.d.ts
CHANGED
|
@@ -6,23 +6,25 @@ declare function toUuidStringImpl(id: DynamicTnid, upperCase?: boolean): string;
|
|
|
6
6
|
/** Interface for DynamicTnid static methods. */
|
|
7
7
|
export interface DynamicTnidNamespace {
|
|
8
8
|
/** Generate a new time-sortable TNID (variant 0) with runtime name validation. */
|
|
9
|
-
|
|
10
|
-
/** Alias for
|
|
11
|
-
|
|
9
|
+
newV0(name: string): DynamicTnid;
|
|
10
|
+
/** Alias for newV0. */
|
|
11
|
+
newTimeOrdered(name: string): DynamicTnid;
|
|
12
12
|
/** Generate a new time-sortable TNID with a specific timestamp. */
|
|
13
|
-
|
|
13
|
+
newV0WithTime(name: string, time: Date): DynamicTnid;
|
|
14
14
|
/** Generate a new time-sortable TNID with explicit timestamp and random components. */
|
|
15
|
-
|
|
15
|
+
newV0WithParts(name: string, epochMillis: bigint, random: bigint): DynamicTnid;
|
|
16
16
|
/** Generate a new high-entropy TNID (variant 1) with runtime name validation. */
|
|
17
|
-
|
|
18
|
-
/** Alias for
|
|
19
|
-
|
|
17
|
+
newV1(name: string): DynamicTnid;
|
|
18
|
+
/** Alias for newV1. */
|
|
19
|
+
newHighEntropy(name: string): DynamicTnid;
|
|
20
20
|
/** Generate a new high-entropy TNID with explicit random bits. */
|
|
21
|
-
|
|
22
|
-
/** Parse
|
|
21
|
+
newV1WithRandom(name: string, randomBits: bigint): DynamicTnid;
|
|
22
|
+
/** Parse a TNID from either TNID string format or UUID hex format (auto-detected). */
|
|
23
23
|
parse(s: string): DynamicTnid;
|
|
24
|
+
/** Parse a TNID string (e.g., "user.Br2flcNDfF6LYICnT"). */
|
|
25
|
+
parseTnidString(s: string): DynamicTnid;
|
|
24
26
|
/** Parse a UUID hex string into a DynamicTnid (validates TNID structure). */
|
|
25
|
-
|
|
27
|
+
parseUuidString(uuid: string): DynamicTnid;
|
|
26
28
|
/** Get the name from a TNID. */
|
|
27
29
|
getName(id: DynamicTnid): string;
|
|
28
30
|
/** Get the name encoded as a 5-character hex string. */
|
package/esm/dynamic.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic.d.ts","sourceRoot":"","sources":["../src/dynamic.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE/D,gEAAgE;AAChE,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAgB5C,iBAAS,kBAAkB,CAAC,EAAE,EAAE,WAAW,GAAG,WAAW,CASxD;AAiBD,iBAAS,gBAAgB,CAAC,EAAE,EAAE,WAAW,EAAE,SAAS,GAAE,OAAe,GAAG,MAAM,CAmB7E;AAmDD,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,kFAAkF;IAClF,
|
|
1
|
+
{"version":3,"file":"dynamic.d.ts","sourceRoot":"","sources":["../src/dynamic.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE/D,gEAAgE;AAChE,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAgB5C,iBAAS,kBAAkB,CAAC,EAAE,EAAE,WAAW,GAAG,WAAW,CASxD;AAiBD,iBAAS,gBAAgB,CAAC,EAAE,EAAE,WAAW,EAAE,SAAS,GAAE,OAAe,GAAG,MAAM,CAmB7E;AAmDD,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,kFAAkF;IAClF,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IACjC,uBAAuB;IACvB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC1C,mEAAmE;IACnE,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,WAAW,CAAC;IACrD,uFAAuF;IACvF,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC;IAC/E,iFAAiF;IACjF,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IACjC,uBAAuB;IACvB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC1C,kEAAkE;IAClE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW,CAAC;IAC/D,sFAAsF;IACtF,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC9B,4DAA4D;IAC5D,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IACxC,6EAA6E;IAC7E,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3C,gCAAgC;IAChC,OAAO,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAAC;IACjC,wDAAwD;IACxD,UAAU,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAAC;IACpC,iCAAiC;IACjC,UAAU,CAAC,EAAE,EAAE,WAAW,GAAG,WAAW,CAAC;IACzC,yCAAyC;IACzC,YAAY,CAAC,EAAE,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;CAC1D;AAED,mEAAmE;AACnE,eAAO,MAAM,WAAW,EAAE,oBA4HzB,CAAC;AAGF,OAAO,EACL,kBAAkB,EAClB,gBAAgB,GACjB,CAAC"}
|
package/esm/dynamic.js
CHANGED
|
@@ -83,7 +83,7 @@ function parseDynamicUuidStringImpl(uuid) {
|
|
|
83
83
|
/** Static methods for working with any TNID regardless of name. */
|
|
84
84
|
export const DynamicTnid = {
|
|
85
85
|
/** Generate a new time-sortable TNID (variant 0) with runtime name validation. */
|
|
86
|
-
|
|
86
|
+
newV0(name) {
|
|
87
87
|
if (!isValidNameRuntime(name)) {
|
|
88
88
|
throw new Error(`Invalid TNID name: "${name}". Must be 1-4 characters of: 0-4, a-z`);
|
|
89
89
|
}
|
|
@@ -92,12 +92,12 @@ export const DynamicTnid = {
|
|
|
92
92
|
const dataEncoded = encodeData(bytes);
|
|
93
93
|
return `${name}.${dataEncoded}`;
|
|
94
94
|
},
|
|
95
|
-
/** Alias for
|
|
96
|
-
|
|
97
|
-
return DynamicTnid.
|
|
95
|
+
/** Alias for newV0. */
|
|
96
|
+
newTimeOrdered(name) {
|
|
97
|
+
return DynamicTnid.newV0(name);
|
|
98
98
|
},
|
|
99
99
|
/** Generate a new time-sortable TNID with a specific timestamp. */
|
|
100
|
-
|
|
100
|
+
newV0WithTime(name, time) {
|
|
101
101
|
if (!isValidNameRuntime(name)) {
|
|
102
102
|
throw new Error(`Invalid TNID name: "${name}". Must be 1-4 characters of: 0-4, a-z`);
|
|
103
103
|
}
|
|
@@ -108,7 +108,7 @@ export const DynamicTnid = {
|
|
|
108
108
|
return `${name}.${dataEncoded}`;
|
|
109
109
|
},
|
|
110
110
|
/** Generate a new time-sortable TNID with explicit timestamp and random components. */
|
|
111
|
-
|
|
111
|
+
newV0WithParts(name, epochMillis, random) {
|
|
112
112
|
if (!isValidNameRuntime(name)) {
|
|
113
113
|
throw new Error(`Invalid TNID name: "${name}". Must be 1-4 characters of: 0-4, a-z`);
|
|
114
114
|
}
|
|
@@ -118,7 +118,7 @@ export const DynamicTnid = {
|
|
|
118
118
|
return `${name}.${dataEncoded}`;
|
|
119
119
|
},
|
|
120
120
|
/** Generate a new high-entropy TNID (variant 1) with runtime name validation. */
|
|
121
|
-
|
|
121
|
+
newV1(name) {
|
|
122
122
|
if (!isValidNameRuntime(name)) {
|
|
123
123
|
throw new Error(`Invalid TNID name: "${name}". Must be 1-4 characters of: 0-4, a-z`);
|
|
124
124
|
}
|
|
@@ -127,12 +127,12 @@ export const DynamicTnid = {
|
|
|
127
127
|
const dataEncoded = encodeData(bytes);
|
|
128
128
|
return `${name}.${dataEncoded}`;
|
|
129
129
|
},
|
|
130
|
-
/** Alias for
|
|
131
|
-
|
|
132
|
-
return DynamicTnid.
|
|
130
|
+
/** Alias for newV1. */
|
|
131
|
+
newHighEntropy(name) {
|
|
132
|
+
return DynamicTnid.newV1(name);
|
|
133
133
|
},
|
|
134
134
|
/** Generate a new high-entropy TNID with explicit random bits. */
|
|
135
|
-
|
|
135
|
+
newV1WithRandom(name, randomBits) {
|
|
136
136
|
if (!isValidNameRuntime(name)) {
|
|
137
137
|
throw new Error(`Invalid TNID name: "${name}". Must be 1-4 characters of: 0-4, a-z`);
|
|
138
138
|
}
|
|
@@ -141,12 +141,25 @@ export const DynamicTnid = {
|
|
|
141
141
|
const dataEncoded = encodeData(bytes);
|
|
142
142
|
return `${name}.${dataEncoded}`;
|
|
143
143
|
},
|
|
144
|
-
/** Parse
|
|
144
|
+
/** Parse a TNID from either TNID string format or UUID hex format (auto-detected). */
|
|
145
145
|
parse(s) {
|
|
146
|
+
// Detect format by length: TNID strings are 19-22 chars with '.', UUIDs are 36 chars
|
|
147
|
+
if (s.length >= 19 && s.length <= 22 && s.includes(".")) {
|
|
148
|
+
return parseDynamicTnidImpl(s);
|
|
149
|
+
}
|
|
150
|
+
else if (s.length === 36) {
|
|
151
|
+
return parseDynamicUuidStringImpl(s);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
throw new Error(`Invalid TNID: expected TNID string (19-22 chars) or UUID (36 chars), got ${s.length} chars`);
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
/** Parse a TNID string (e.g., "user.Br2flcNDfF6LYICnT"). */
|
|
158
|
+
parseTnidString(s) {
|
|
146
159
|
return parseDynamicTnidImpl(s);
|
|
147
160
|
},
|
|
148
161
|
/** Parse a UUID hex string into a DynamicTnid (validates TNID structure). */
|
|
149
|
-
|
|
162
|
+
parseUuidString(uuid) {
|
|
150
163
|
return parseDynamicUuidStringImpl(uuid);
|
|
151
164
|
},
|
|
152
165
|
/** Get the name from a TNID. */
|
package/esm/factory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,SAAS,EAGT,YAAY,EACb,MAAM,YAAY,CAAC;AAapB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,EAC5C,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,GACvB,SAAS,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,SAAS,EAGT,YAAY,EACb,MAAM,YAAY,CAAC;AAapB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,EAC5C,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,GACvB,SAAS,CAAC,IAAI,CAAC,CAmHjB"}
|
package/esm/factory.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// =============================================================================
|
|
2
2
|
// Tnid Function
|
|
3
3
|
// =============================================================================
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { decodeName, encodeName, isValidNameRuntime } from "./name_encoding.js";
|
|
5
|
+
import { dataBitsToBytes, decodeData, encodeData } from "./data_encoding.js";
|
|
6
6
|
import { generateV0, generateV1 } from "./bits.js";
|
|
7
|
-
import { parseUuidStringToValue, validateUuidBits,
|
|
7
|
+
import { extractNameBitsFromValue, parseUuidStringToValue, validateUuidBits, valueToTnidString, } from "./uuid.js";
|
|
8
8
|
import { getTnidVariantImpl, toUuidStringImpl } from "./dynamic.js";
|
|
9
9
|
/**
|
|
10
10
|
* Create a NamedTnid for the given name.
|
|
@@ -59,6 +59,18 @@ export function Tnid(name) {
|
|
|
59
59
|
return `${name}.${dataEncoded}`;
|
|
60
60
|
},
|
|
61
61
|
parse(s) {
|
|
62
|
+
// Detect format by length: TNID strings are 19-22 chars with '.', UUIDs are 36 chars
|
|
63
|
+
if (s.length >= 19 && s.length <= 22 && s.includes(".")) {
|
|
64
|
+
return tnid.parseTnidString(s);
|
|
65
|
+
}
|
|
66
|
+
else if (s.length === 36) {
|
|
67
|
+
return tnid.parseUuidString(s);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
throw new Error(`Invalid TNID: expected TNID string (19-22 chars) or UUID (36 chars), got ${s.length} chars`);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
parseTnidString(s) {
|
|
62
74
|
const dotIndex = s.indexOf(".");
|
|
63
75
|
if (dotIndex === -1) {
|
|
64
76
|
throw new Error(`Invalid TNID string: missing '.' separator`);
|
package/esm/types.d.ts
CHANGED
|
@@ -23,14 +23,18 @@ export type ValidateName<S extends string> = ValidateNameChars<S> extends true ?
|
|
|
23
23
|
* const id: UserId = UserId.new_v0(); // time-sortable
|
|
24
24
|
* const id2: UserId = UserId.new_v1(); // high-entropy random
|
|
25
25
|
*
|
|
26
|
-
* // Parse from strings
|
|
27
|
-
* const parsed = UserId.parse("user.abc..."); //
|
|
28
|
-
* const fromUuid = UserId.
|
|
26
|
+
* // Parse from strings (auto-detects format)
|
|
27
|
+
* const parsed = UserId.parse("user.abc..."); // TNID string format
|
|
28
|
+
* const fromUuid = UserId.parse("d6157329-4640-8e30-..."); // UUID format
|
|
29
|
+
*
|
|
30
|
+
* // Or use explicit parse methods
|
|
31
|
+
* UserId.parseTnidString("user.abc..."); // TNID string only
|
|
32
|
+
* UserId.parseUuidString("d6157329-..."); // UUID string only
|
|
29
33
|
*
|
|
30
34
|
* // DynamicTnid - runtime name validation
|
|
31
|
-
* DynamicTnid.
|
|
32
|
-
* DynamicTnid.
|
|
33
|
-
* DynamicTnid.parse("post.xyz..."); // parse any TNID
|
|
35
|
+
* DynamicTnid.newV0("item"); // create with runtime name
|
|
36
|
+
* DynamicTnid.newV1("item"); // create with runtime name
|
|
37
|
+
* DynamicTnid.parse("post.xyz..."); // parse any TNID (auto-detects)
|
|
34
38
|
* DynamicTnid.getName(id); // "user"
|
|
35
39
|
* DynamicTnid.getVariant(id); // "v0" | "v1" | "v2" | "v3"
|
|
36
40
|
*
|
|
@@ -70,10 +74,15 @@ export interface NamedTnid<Name extends string> {
|
|
|
70
74
|
/** Construct a V1 TNID from specific parts (for deterministic testing) */
|
|
71
75
|
v1_from_parts(randomBits: bigint): TnidValue<Name>;
|
|
72
76
|
/**
|
|
73
|
-
* Parse
|
|
77
|
+
* Parse a TNID from either TNID string format or UUID hex format (auto-detected).
|
|
74
78
|
* @throws Error if the string is invalid or the name doesn't match
|
|
75
79
|
*/
|
|
76
80
|
parse(s: string): TnidValue<Name>;
|
|
81
|
+
/**
|
|
82
|
+
* Parse and validate a TNID string (e.g., "user.Br2flcNDfF6LYICnT").
|
|
83
|
+
* @throws Error if the string is invalid or the name doesn't match
|
|
84
|
+
*/
|
|
85
|
+
parseTnidString(s: string): TnidValue<Name>;
|
|
77
86
|
/**
|
|
78
87
|
* Parse a UUID hex string into a TNID.
|
|
79
88
|
* Validates that it's a valid UUIDv8 TNID and the name matches.
|
package/esm/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAQA,iEAAiE;AACjE,MAAM,MAAM,QAAQ,GAChB,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,CAAC;AAER,mFAAmF;AACnF,KAAK,iBAAiB,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,GAC1D,CAAC,SAAS,GAAG,MAAM,KAAK,GAAG,MAAM,IAAI,EAAE,GACrC,KAAK,SAAS,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAChD,KAAK,GACP,KAAK,CAAC;AAEV,0DAA0D;AAC1D,KAAK,YAAY,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,SAAS,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,GAC1E,GAAG,CAAC,QAAQ,CAAC,GACb,CAAC,SAAS,GAAG,MAAM,CAAC,GAAG,MAAM,IAAI,EAAE,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,OAAO,CAAC,CAAC,GAC3E,KAAK,CAAC;AAEV,KAAK,WAAW,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEjC;;;GAGG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,IAAI,iBAAiB,CAAC,CAAC,CAAC,SAAS,IAAI,GAC1E,YAAY,CAAC,CAAC,CAAC,SAAS,WAAW,GAAG,CAAC,GACvC,KAAK,GACL,KAAK,CAAC;AAMV
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tnid/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "Type-safe, named, unique identifiers (TNIDs) - UUID-compatible IDs with embedded type names",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"uuid",
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
],
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
|
-
"url": "git+https://github.com/
|
|
15
|
+
"url": "git+https://github.com/mkeedlinger/tnid-typescript.git"
|
|
16
16
|
},
|
|
17
17
|
"license": "MIT",
|
|
18
18
|
"bugs": {
|
|
19
|
-
"url": "https://github.com/
|
|
19
|
+
"url": "https://github.com/mkeedlinger/tnid-typescript/issues"
|
|
20
20
|
},
|
|
21
21
|
"main": "./script/index.js",
|
|
22
22
|
"module": "./esm/index.js",
|
|
@@ -38,5 +38,6 @@
|
|
|
38
38
|
"node": ">=20"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {},
|
|
41
|
+
"peerDependencies": {},
|
|
41
42
|
"_generatedBy": "dnt@dev"
|
|
42
43
|
}
|
package/script/dynamic.d.ts
CHANGED
|
@@ -6,23 +6,25 @@ declare function toUuidStringImpl(id: DynamicTnid, upperCase?: boolean): string;
|
|
|
6
6
|
/** Interface for DynamicTnid static methods. */
|
|
7
7
|
export interface DynamicTnidNamespace {
|
|
8
8
|
/** Generate a new time-sortable TNID (variant 0) with runtime name validation. */
|
|
9
|
-
|
|
10
|
-
/** Alias for
|
|
11
|
-
|
|
9
|
+
newV0(name: string): DynamicTnid;
|
|
10
|
+
/** Alias for newV0. */
|
|
11
|
+
newTimeOrdered(name: string): DynamicTnid;
|
|
12
12
|
/** Generate a new time-sortable TNID with a specific timestamp. */
|
|
13
|
-
|
|
13
|
+
newV0WithTime(name: string, time: Date): DynamicTnid;
|
|
14
14
|
/** Generate a new time-sortable TNID with explicit timestamp and random components. */
|
|
15
|
-
|
|
15
|
+
newV0WithParts(name: string, epochMillis: bigint, random: bigint): DynamicTnid;
|
|
16
16
|
/** Generate a new high-entropy TNID (variant 1) with runtime name validation. */
|
|
17
|
-
|
|
18
|
-
/** Alias for
|
|
19
|
-
|
|
17
|
+
newV1(name: string): DynamicTnid;
|
|
18
|
+
/** Alias for newV1. */
|
|
19
|
+
newHighEntropy(name: string): DynamicTnid;
|
|
20
20
|
/** Generate a new high-entropy TNID with explicit random bits. */
|
|
21
|
-
|
|
22
|
-
/** Parse
|
|
21
|
+
newV1WithRandom(name: string, randomBits: bigint): DynamicTnid;
|
|
22
|
+
/** Parse a TNID from either TNID string format or UUID hex format (auto-detected). */
|
|
23
23
|
parse(s: string): DynamicTnid;
|
|
24
|
+
/** Parse a TNID string (e.g., "user.Br2flcNDfF6LYICnT"). */
|
|
25
|
+
parseTnidString(s: string): DynamicTnid;
|
|
24
26
|
/** Parse a UUID hex string into a DynamicTnid (validates TNID structure). */
|
|
25
|
-
|
|
27
|
+
parseUuidString(uuid: string): DynamicTnid;
|
|
26
28
|
/** Get the name from a TNID. */
|
|
27
29
|
getName(id: DynamicTnid): string;
|
|
28
30
|
/** Get the name encoded as a 5-character hex string. */
|
package/script/dynamic.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic.d.ts","sourceRoot":"","sources":["../src/dynamic.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE/D,gEAAgE;AAChE,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAgB5C,iBAAS,kBAAkB,CAAC,EAAE,EAAE,WAAW,GAAG,WAAW,CASxD;AAiBD,iBAAS,gBAAgB,CAAC,EAAE,EAAE,WAAW,EAAE,SAAS,GAAE,OAAe,GAAG,MAAM,CAmB7E;AAmDD,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,kFAAkF;IAClF,
|
|
1
|
+
{"version":3,"file":"dynamic.d.ts","sourceRoot":"","sources":["../src/dynamic.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE/D,gEAAgE;AAChE,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAgB5C,iBAAS,kBAAkB,CAAC,EAAE,EAAE,WAAW,GAAG,WAAW,CASxD;AAiBD,iBAAS,gBAAgB,CAAC,EAAE,EAAE,WAAW,EAAE,SAAS,GAAE,OAAe,GAAG,MAAM,CAmB7E;AAmDD,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,kFAAkF;IAClF,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IACjC,uBAAuB;IACvB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC1C,mEAAmE;IACnE,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,WAAW,CAAC;IACrD,uFAAuF;IACvF,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAAC;IAC/E,iFAAiF;IACjF,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IACjC,uBAAuB;IACvB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC1C,kEAAkE;IAClE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW,CAAC;IAC/D,sFAAsF;IACtF,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC9B,4DAA4D;IAC5D,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IACxC,6EAA6E;IAC7E,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3C,gCAAgC;IAChC,OAAO,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAAC;IACjC,wDAAwD;IACxD,UAAU,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAAC;IACpC,iCAAiC;IACjC,UAAU,CAAC,EAAE,EAAE,WAAW,GAAG,WAAW,CAAC;IACzC,yCAAyC;IACzC,YAAY,CAAC,EAAE,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;CAC1D;AAED,mEAAmE;AACnE,eAAO,MAAM,WAAW,EAAE,oBA4HzB,CAAC;AAGF,OAAO,EACL,kBAAkB,EAClB,gBAAgB,GACjB,CAAC"}
|
package/script/dynamic.js
CHANGED
|
@@ -88,7 +88,7 @@ function parseDynamicUuidStringImpl(uuid) {
|
|
|
88
88
|
/** Static methods for working with any TNID regardless of name. */
|
|
89
89
|
exports.DynamicTnid = {
|
|
90
90
|
/** Generate a new time-sortable TNID (variant 0) with runtime name validation. */
|
|
91
|
-
|
|
91
|
+
newV0(name) {
|
|
92
92
|
if (!(0, name_encoding_js_1.isValidNameRuntime)(name)) {
|
|
93
93
|
throw new Error(`Invalid TNID name: "${name}". Must be 1-4 characters of: 0-4, a-z`);
|
|
94
94
|
}
|
|
@@ -97,12 +97,12 @@ exports.DynamicTnid = {
|
|
|
97
97
|
const dataEncoded = (0, data_encoding_js_1.encodeData)(bytes);
|
|
98
98
|
return `${name}.${dataEncoded}`;
|
|
99
99
|
},
|
|
100
|
-
/** Alias for
|
|
101
|
-
|
|
102
|
-
return exports.DynamicTnid.
|
|
100
|
+
/** Alias for newV0. */
|
|
101
|
+
newTimeOrdered(name) {
|
|
102
|
+
return exports.DynamicTnid.newV0(name);
|
|
103
103
|
},
|
|
104
104
|
/** Generate a new time-sortable TNID with a specific timestamp. */
|
|
105
|
-
|
|
105
|
+
newV0WithTime(name, time) {
|
|
106
106
|
if (!(0, name_encoding_js_1.isValidNameRuntime)(name)) {
|
|
107
107
|
throw new Error(`Invalid TNID name: "${name}". Must be 1-4 characters of: 0-4, a-z`);
|
|
108
108
|
}
|
|
@@ -113,7 +113,7 @@ exports.DynamicTnid = {
|
|
|
113
113
|
return `${name}.${dataEncoded}`;
|
|
114
114
|
},
|
|
115
115
|
/** Generate a new time-sortable TNID with explicit timestamp and random components. */
|
|
116
|
-
|
|
116
|
+
newV0WithParts(name, epochMillis, random) {
|
|
117
117
|
if (!(0, name_encoding_js_1.isValidNameRuntime)(name)) {
|
|
118
118
|
throw new Error(`Invalid TNID name: "${name}". Must be 1-4 characters of: 0-4, a-z`);
|
|
119
119
|
}
|
|
@@ -123,7 +123,7 @@ exports.DynamicTnid = {
|
|
|
123
123
|
return `${name}.${dataEncoded}`;
|
|
124
124
|
},
|
|
125
125
|
/** Generate a new high-entropy TNID (variant 1) with runtime name validation. */
|
|
126
|
-
|
|
126
|
+
newV1(name) {
|
|
127
127
|
if (!(0, name_encoding_js_1.isValidNameRuntime)(name)) {
|
|
128
128
|
throw new Error(`Invalid TNID name: "${name}". Must be 1-4 characters of: 0-4, a-z`);
|
|
129
129
|
}
|
|
@@ -132,12 +132,12 @@ exports.DynamicTnid = {
|
|
|
132
132
|
const dataEncoded = (0, data_encoding_js_1.encodeData)(bytes);
|
|
133
133
|
return `${name}.${dataEncoded}`;
|
|
134
134
|
},
|
|
135
|
-
/** Alias for
|
|
136
|
-
|
|
137
|
-
return exports.DynamicTnid.
|
|
135
|
+
/** Alias for newV1. */
|
|
136
|
+
newHighEntropy(name) {
|
|
137
|
+
return exports.DynamicTnid.newV1(name);
|
|
138
138
|
},
|
|
139
139
|
/** Generate a new high-entropy TNID with explicit random bits. */
|
|
140
|
-
|
|
140
|
+
newV1WithRandom(name, randomBits) {
|
|
141
141
|
if (!(0, name_encoding_js_1.isValidNameRuntime)(name)) {
|
|
142
142
|
throw new Error(`Invalid TNID name: "${name}". Must be 1-4 characters of: 0-4, a-z`);
|
|
143
143
|
}
|
|
@@ -146,12 +146,25 @@ exports.DynamicTnid = {
|
|
|
146
146
|
const dataEncoded = (0, data_encoding_js_1.encodeData)(bytes);
|
|
147
147
|
return `${name}.${dataEncoded}`;
|
|
148
148
|
},
|
|
149
|
-
/** Parse
|
|
149
|
+
/** Parse a TNID from either TNID string format or UUID hex format (auto-detected). */
|
|
150
150
|
parse(s) {
|
|
151
|
+
// Detect format by length: TNID strings are 19-22 chars with '.', UUIDs are 36 chars
|
|
152
|
+
if (s.length >= 19 && s.length <= 22 && s.includes(".")) {
|
|
153
|
+
return parseDynamicTnidImpl(s);
|
|
154
|
+
}
|
|
155
|
+
else if (s.length === 36) {
|
|
156
|
+
return parseDynamicUuidStringImpl(s);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
throw new Error(`Invalid TNID: expected TNID string (19-22 chars) or UUID (36 chars), got ${s.length} chars`);
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
/** Parse a TNID string (e.g., "user.Br2flcNDfF6LYICnT"). */
|
|
163
|
+
parseTnidString(s) {
|
|
151
164
|
return parseDynamicTnidImpl(s);
|
|
152
165
|
},
|
|
153
166
|
/** Parse a UUID hex string into a DynamicTnid (validates TNID structure). */
|
|
154
|
-
|
|
167
|
+
parseUuidString(uuid) {
|
|
155
168
|
return parseDynamicUuidStringImpl(uuid);
|
|
156
169
|
},
|
|
157
170
|
/** Get the name from a TNID. */
|
package/script/factory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,SAAS,EAGT,YAAY,EACb,MAAM,YAAY,CAAC;AAapB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,EAC5C,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,GACvB,SAAS,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,SAAS,EAGT,YAAY,EACb,MAAM,YAAY,CAAC;AAapB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,IAAI,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,EAC5C,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,GACvB,SAAS,CAAC,IAAI,CAAC,CAmHjB"}
|
package/script/factory.js
CHANGED
|
@@ -62,6 +62,18 @@ function Tnid(name) {
|
|
|
62
62
|
return `${name}.${dataEncoded}`;
|
|
63
63
|
},
|
|
64
64
|
parse(s) {
|
|
65
|
+
// Detect format by length: TNID strings are 19-22 chars with '.', UUIDs are 36 chars
|
|
66
|
+
if (s.length >= 19 && s.length <= 22 && s.includes(".")) {
|
|
67
|
+
return tnid.parseTnidString(s);
|
|
68
|
+
}
|
|
69
|
+
else if (s.length === 36) {
|
|
70
|
+
return tnid.parseUuidString(s);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
throw new Error(`Invalid TNID: expected TNID string (19-22 chars) or UUID (36 chars), got ${s.length} chars`);
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
parseTnidString(s) {
|
|
65
77
|
const dotIndex = s.indexOf(".");
|
|
66
78
|
if (dotIndex === -1) {
|
|
67
79
|
throw new Error(`Invalid TNID string: missing '.' separator`);
|
package/script/types.d.ts
CHANGED
|
@@ -23,14 +23,18 @@ export type ValidateName<S extends string> = ValidateNameChars<S> extends true ?
|
|
|
23
23
|
* const id: UserId = UserId.new_v0(); // time-sortable
|
|
24
24
|
* const id2: UserId = UserId.new_v1(); // high-entropy random
|
|
25
25
|
*
|
|
26
|
-
* // Parse from strings
|
|
27
|
-
* const parsed = UserId.parse("user.abc..."); //
|
|
28
|
-
* const fromUuid = UserId.
|
|
26
|
+
* // Parse from strings (auto-detects format)
|
|
27
|
+
* const parsed = UserId.parse("user.abc..."); // TNID string format
|
|
28
|
+
* const fromUuid = UserId.parse("d6157329-4640-8e30-..."); // UUID format
|
|
29
|
+
*
|
|
30
|
+
* // Or use explicit parse methods
|
|
31
|
+
* UserId.parseTnidString("user.abc..."); // TNID string only
|
|
32
|
+
* UserId.parseUuidString("d6157329-..."); // UUID string only
|
|
29
33
|
*
|
|
30
34
|
* // DynamicTnid - runtime name validation
|
|
31
|
-
* DynamicTnid.
|
|
32
|
-
* DynamicTnid.
|
|
33
|
-
* DynamicTnid.parse("post.xyz..."); // parse any TNID
|
|
35
|
+
* DynamicTnid.newV0("item"); // create with runtime name
|
|
36
|
+
* DynamicTnid.newV1("item"); // create with runtime name
|
|
37
|
+
* DynamicTnid.parse("post.xyz..."); // parse any TNID (auto-detects)
|
|
34
38
|
* DynamicTnid.getName(id); // "user"
|
|
35
39
|
* DynamicTnid.getVariant(id); // "v0" | "v1" | "v2" | "v3"
|
|
36
40
|
*
|
|
@@ -70,10 +74,15 @@ export interface NamedTnid<Name extends string> {
|
|
|
70
74
|
/** Construct a V1 TNID from specific parts (for deterministic testing) */
|
|
71
75
|
v1_from_parts(randomBits: bigint): TnidValue<Name>;
|
|
72
76
|
/**
|
|
73
|
-
* Parse
|
|
77
|
+
* Parse a TNID from either TNID string format or UUID hex format (auto-detected).
|
|
74
78
|
* @throws Error if the string is invalid or the name doesn't match
|
|
75
79
|
*/
|
|
76
80
|
parse(s: string): TnidValue<Name>;
|
|
81
|
+
/**
|
|
82
|
+
* Parse and validate a TNID string (e.g., "user.Br2flcNDfF6LYICnT").
|
|
83
|
+
* @throws Error if the string is invalid or the name doesn't match
|
|
84
|
+
*/
|
|
85
|
+
parseTnidString(s: string): TnidValue<Name>;
|
|
77
86
|
/**
|
|
78
87
|
* Parse a UUID hex string into a TNID.
|
|
79
88
|
* Validates that it's a valid UUIDv8 TNID and the name matches.
|
package/script/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAQA,iEAAiE;AACjE,MAAM,MAAM,QAAQ,GAChB,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,CAAC;AAER,mFAAmF;AACnF,KAAK,iBAAiB,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,GAC1D,CAAC,SAAS,GAAG,MAAM,KAAK,GAAG,MAAM,IAAI,EAAE,GACrC,KAAK,SAAS,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAChD,KAAK,GACP,KAAK,CAAC;AAEV,0DAA0D;AAC1D,KAAK,YAAY,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,SAAS,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,GAC1E,GAAG,CAAC,QAAQ,CAAC,GACb,CAAC,SAAS,GAAG,MAAM,CAAC,GAAG,MAAM,IAAI,EAAE,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,OAAO,CAAC,CAAC,GAC3E,KAAK,CAAC;AAEV,KAAK,WAAW,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEjC;;;GAGG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,IAAI,iBAAiB,CAAC,CAAC,CAAC,SAAS,IAAI,GAC1E,YAAY,CAAC,CAAC,CAAC,SAAS,WAAW,GAAG,CAAC,GACvC,KAAK,GACL,KAAK,CAAC;AAMV
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAQA,iEAAiE;AACjE,MAAM,MAAM,QAAQ,GAChB,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,CAAC;AAER,mFAAmF;AACnF,KAAK,iBAAiB,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,GAC1D,CAAC,SAAS,GAAG,MAAM,KAAK,GAAG,MAAM,IAAI,EAAE,GACrC,KAAK,SAAS,QAAQ,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAChD,KAAK,GACP,KAAK,CAAC;AAEV,0DAA0D;AAC1D,KAAK,YAAY,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,SAAS,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,GAC1E,GAAG,CAAC,QAAQ,CAAC,GACb,CAAC,SAAS,GAAG,MAAM,CAAC,GAAG,MAAM,IAAI,EAAE,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,OAAO,CAAC,CAAC,GAC3E,KAAK,CAAC;AAEV,KAAK,WAAW,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEjC;;;GAGG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,IAAI,iBAAiB,CAAC,CAAC,CAAC,SAAS,IAAI,GAC1E,YAAY,CAAC,CAAC,CAAC,SAAS,WAAW,GAAG,CAAC,GACvC,KAAK,GACL,KAAK,CAAC;AAMV;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,MAAM,SAAS,CAAC,IAAI,SAAS,MAAM,IAAI,MAAM,GAAG;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC;AAErE,+DAA+D;AAC/D,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEpD,2CAA2C;AAC3C,MAAM,MAAM,IAAI,GAAG,OAAO,GAAG,OAAO,CAAC;AAMrC,MAAM,WAAW,SAAS,CAAC,IAAI,SAAS,MAAM;IAC5C,oBAAoB;IACpB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IAEpB,oDAAoD;IACpD,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC;IAE1B,6CAA6C;IAC7C,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC;IAE1B,0EAA0E;IAC1E,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAExE,0EAA0E;IAC1E,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAEnD;;;OAGG;IACH,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAElC;;;OAGG;IACH,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE5C;;;;OAIG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE/C,wDAAwD;IACxD,OAAO,IAAI,MAAM,CAAC;IAElB,iCAAiC;IACjC,OAAO,CAAC,EAAE,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC;IAE1C,gDAAgD;IAChD,YAAY,CAAC,EAAE,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;CAC9D;AAED,qDAAqD;AACrD,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC"}
|