@tnid/core 0.0.5 → 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 +47 -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/index.d.ts +1 -1
- package/esm/index.d.ts.map +1 -1
- 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/index.d.ts +1 -1
- package/script/index.d.ts.map +1 -1
- 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,20 +100,21 @@ 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
|
|
95
108
|
TnidVariant, // "v0" | "v1" | "v2" | "v3"
|
|
96
109
|
UuidLike, // UUID string operations (type + namespace)
|
|
110
|
+
ValidateName, // Compile-time name validation (for library authors)
|
|
97
111
|
} from "@tnid/core";
|
|
98
112
|
```
|
|
99
113
|
|
|
100
114
|
### `Tnid(name)`
|
|
101
115
|
|
|
102
|
-
Creates a `NamedTnid` for a specific name. The name is validated at
|
|
103
|
-
|
|
116
|
+
Creates a `NamedTnid` for a specific name. The name is validated at **compile
|
|
117
|
+
time**.
|
|
104
118
|
|
|
105
119
|
```typescript
|
|
106
120
|
const UserId = Tnid("user");
|
|
@@ -137,27 +151,27 @@ Tnid(""); // empty not allowed
|
|
|
137
151
|
const UserId = Tnid("user");
|
|
138
152
|
type UserId = TnidType<typeof UserId>;
|
|
139
153
|
|
|
140
|
-
UserId.new_v0();
|
|
141
|
-
UserId.new_v1();
|
|
142
|
-
UserId.v0_from_parts(1234567890n, 0n);
|
|
143
|
-
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
|
|
144
158
|
```
|
|
145
159
|
|
|
146
160
|
#### Parsing
|
|
147
161
|
|
|
148
162
|
```typescript
|
|
149
|
-
UserId.parse("user.Br2flcNDfF6LYICnT");
|
|
150
|
-
UserId.parseUuidString("d6157329-4640-8e30-...");
|
|
163
|
+
UserId.parse("user.Br2flcNDfF6LYICnT"); // parse TNID string
|
|
164
|
+
UserId.parseUuidString("d6157329-4640-8e30-..."); // parse UUID hex string
|
|
151
165
|
```
|
|
152
166
|
|
|
153
167
|
#### Inspection and Conversion
|
|
154
168
|
|
|
155
169
|
```typescript
|
|
156
|
-
UserId.name;
|
|
157
|
-
UserId.variant(id);
|
|
158
|
-
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
|
|
159
173
|
UserId.toUuidString(id, "upper"); // "D6157329-4640-8E30-..." - uppercase UUID
|
|
160
|
-
UserId.nameHex();
|
|
174
|
+
UserId.nameHex(); // "d6157" - name as 5-char hex
|
|
161
175
|
```
|
|
162
176
|
|
|
163
177
|
### `TnidType<T>`
|
|
@@ -187,23 +201,27 @@ function logAnyId(id: DynamicTnid) {
|
|
|
187
201
|
}
|
|
188
202
|
|
|
189
203
|
// Generation with runtime names
|
|
190
|
-
DynamicTnid.
|
|
191
|
-
DynamicTnid.
|
|
204
|
+
DynamicTnid.newV0("user"); // time-ordered (alias: newTimeOrdered)
|
|
205
|
+
DynamicTnid.newV1("user"); // high-entropy (alias: newHighEntropy)
|
|
192
206
|
|
|
193
207
|
// Generation with explicit values (useful for testing/migrations)
|
|
194
|
-
DynamicTnid.
|
|
195
|
-
DynamicTnid.
|
|
196
|
-
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
|
|
197
215
|
|
|
198
|
-
//
|
|
199
|
-
DynamicTnid.
|
|
200
|
-
DynamicTnid.
|
|
216
|
+
// Or use explicit parse methods
|
|
217
|
+
DynamicTnid.parseTnidString("post.EUBcUw4T9x3KNOll-");
|
|
218
|
+
DynamicTnid.parseUuidString("d6157329-4640-...");
|
|
201
219
|
|
|
202
220
|
// Inspection
|
|
203
|
-
DynamicTnid.getName(id);
|
|
204
|
-
DynamicTnid.getNameHex(id);
|
|
205
|
-
DynamicTnid.getVariant(id);
|
|
206
|
-
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
|
|
207
225
|
```
|
|
208
226
|
|
|
209
227
|
### `UuidLike`
|
|
@@ -211,10 +229,10 @@ DynamicTnid.toUuidString(id); // UUID hex string
|
|
|
211
229
|
For working with UUID hex strings that may or may not be valid TNIDs.
|
|
212
230
|
|
|
213
231
|
```typescript
|
|
214
|
-
UuidLike.fromTnid(id);
|
|
215
|
-
UuidLike.parse(s);
|
|
216
|
-
UuidLike.toTnid(uuid);
|
|
217
|
-
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
|
|
218
236
|
```
|
|
219
237
|
|
|
220
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/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { TnidValue, TnidVariant, Case, NamedTnid, TnidType, } from "./types.js";
|
|
1
|
+
export type { TnidValue, TnidVariant, Case, NamedTnid, TnidType, ValidateName, } from "./types.js";
|
|
2
2
|
export { DynamicTnid } from "./dynamic.js";
|
|
3
3
|
export { UuidLike } from "./uuidlike.js";
|
|
4
4
|
export { Tnid } from "./factory.js";
|
package/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,YAAY,EACV,SAAS,EACT,WAAW,EACX,IAAI,EACJ,SAAS,EACT,QAAQ,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,YAAY,EACV,SAAS,EACT,WAAW,EACX,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC"}
|
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/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { TnidValue, TnidVariant, Case, NamedTnid, TnidType, } from "./types.js";
|
|
1
|
+
export type { TnidValue, TnidVariant, Case, NamedTnid, TnidType, ValidateName, } from "./types.js";
|
|
2
2
|
export { DynamicTnid } from "./dynamic.js";
|
|
3
3
|
export { UuidLike } from "./uuidlike.js";
|
|
4
4
|
export { Tnid } from "./factory.js";
|
package/script/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,YAAY,EACV,SAAS,EACT,WAAW,EACX,IAAI,EACJ,SAAS,EACT,QAAQ,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,YAAY,EACV,SAAS,EACT,WAAW,EACX,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC"}
|
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"}
|