Comparing version 0.5.0 to 0.6.0
@@ -1,1 +0,81 @@ | ||
export { TypeID, typeid } from './typeid.js'; | ||
declare class TypeID<const T extends string> { | ||
private prefix; | ||
private suffix; | ||
constructor(prefix: T, suffix?: string); | ||
getType(): T; | ||
getSuffix(): string; | ||
asType<const U extends string>(prefix: U): TypeID<U>; | ||
toUUIDBytes(): Uint8Array; | ||
toUUID(): string; | ||
toString(): `${T}_${string}` | string; | ||
static fromString<const T extends string>(str: string): TypeID<T>; | ||
static fromUUIDBytes<const T extends string>(prefix: T, bytes: Uint8Array): TypeID<T>; | ||
static fromUUID<const T extends string>(prefix: T, uuid: string): TypeID<T>; | ||
} | ||
declare function typeid<T extends string>(): TypeID<"">; | ||
declare function typeid<T extends string>(prefix: T): TypeID<T>; | ||
declare function typeid<T extends string>(prefix: T, suffix: string): TypeID<T>; | ||
type TypeId<T> = string & { | ||
__type: T; | ||
}; | ||
declare function typeidUnboxed<T extends string>(prefix?: T, suffix?: string): TypeId<T>; | ||
/** | ||
* Constructs a TypeId from a string representation, optionally validating against a provided prefix. | ||
* This function splits the input `typeId` string by an underscore `_` to separate the prefix and suffix. | ||
* If the `typeId` contains no underscore, it is assumed to be a suffix with an empty prefix. | ||
* If a `prefix` is provided, it must match the prefix part of the `typeId`, or an error is thrown. | ||
* | ||
* @param {string} typeId - The string representation of the TypeId to be parsed. | ||
* @param {T} [prefix] - An optional prefix to validate against the prefix in the `typeId`. | ||
* @returns {TypeId<T>} A new TypeId instance constructed from the parsed `typeId`. | ||
* @throws {Error} If the `typeId` format is invalid, the prefix is empty when there's a separator, | ||
* or there's a prefix mismatch when a `prefix` is provided. | ||
* @template T - A string literal type that extends string. | ||
*/ | ||
declare function fromString<T extends string>(typeId: string, prefix?: T): TypeId<T>; | ||
/** | ||
* Parses a TypeId string into its prefix and suffix components. | ||
* | ||
* @param {TypeId<T>} typeId - The TypeId string to parse. | ||
* @returns {{ prefix: T; suffix: string }} An object containing the prefix and suffix of the TypeId. | ||
* @throws {Error} If the TypeId format is invalid (not exactly two parts separated by an underscore). | ||
* | ||
* @example | ||
* // For a valid TypeId 'example_00041061050r3gg28a1c60t3gf' | ||
* const { prefix, suffix } = parseTypeId('example_00041061050r3gg28a1c60t3gf'); | ||
* console.log(prefix); // 'example' | ||
* console.log(suffix); // '00041061050r3gg28a1c60t3gf' | ||
* | ||
* @example | ||
* // Throws an error for invalid TypeId format | ||
* try { | ||
* parseTypeId('invalidTypeId'); | ||
* } catch (error) { | ||
* console.error(error.message); // 'Invalid TypeId format: invalidTypeId' | ||
* } | ||
*/ | ||
declare function parseTypeId<T extends string>(typeId: TypeId<T>): { | ||
prefix: T; | ||
suffix: string; | ||
}; | ||
/** | ||
* Retrieves the prefix from a TypeId. | ||
* | ||
* @param {TypeId<T>} typeId - The TypeId from which to extract the prefix. | ||
* @returns {T} The prefix of the TypeId. | ||
*/ | ||
declare function getType<T extends string>(typeId: TypeId<T>): T; | ||
/** | ||
* Retrieves the suffix from a TypeId. | ||
* | ||
* @param {TypeId<T>} typeId - The TypeId from which to extract the suffix. | ||
* @returns {string} The suffix of the TypeId. | ||
*/ | ||
declare function getSuffix<T extends string>(typeId: TypeId<T>): string; | ||
declare function toUUIDBytes<T extends string>(typeId: TypeId<T>): Uint8Array; | ||
declare function toUUID<T extends string>(typeId: TypeId<T>): string; | ||
declare function fromUUIDBytes(prefix: string, bytes: Uint8Array): TypeId<typeof prefix>; | ||
declare function fromUUID<T extends string>(uuid: string, prefix?: T): TypeId<T>; | ||
export { TypeID, TypeId, fromString, fromUUID, fromUUIDBytes, getSuffix, getType, parseTypeId, toUUID, toUUIDBytes, typeid, typeidUnboxed }; |
@@ -25,3 +25,12 @@ "use strict"; | ||
TypeID: () => TypeID, | ||
typeid: () => typeid | ||
fromString: () => fromString, | ||
fromUUID: () => fromUUID, | ||
fromUUIDBytes: () => fromUUIDBytes, | ||
getSuffix: () => getSuffix, | ||
getType: () => getType, | ||
parseTypeId: () => parseTypeId, | ||
toUUID: () => toUUID, | ||
toUUIDBytes: () => toUUIDBytes, | ||
typeid: () => typeid, | ||
typeidUnboxed: () => typeidUnboxed | ||
}); | ||
@@ -633,3 +642,5 @@ module.exports = __toCommonJS(src_exports); | ||
if (src.length !== 16) { | ||
throw new Error("Invalid length"); | ||
throw new Error( | ||
`Invalid length. Expected 16 bytes, got ${src.length}. Input: ${src}` | ||
); | ||
} | ||
@@ -666,3 +677,5 @@ dst[0] = alphabet[(src[0] & 224) >> 5]; | ||
if (s.length !== 26) { | ||
throw new Error("Invalid length"); | ||
throw new Error( | ||
`Invalid length. Expected 26 bytes, got ${s.length}. Input: ${s}` | ||
); | ||
} | ||
@@ -694,3 +707,3 @@ const encoder = new TextEncoder(); | ||
// src/typeid.ts | ||
// src/prefix.ts | ||
function isValidPrefix(str) { | ||
@@ -711,2 +724,87 @@ if (str.length > 63) { | ||
} | ||
// src/unboxed/typeid.ts | ||
function typeidUnboxed(prefix = "", suffix = "") { | ||
if (!isValidPrefix(prefix)) { | ||
throw new Error("Invalid prefix. Must be at most 63 ascii letters [a-z]"); | ||
} | ||
let finalSuffix; | ||
if (suffix) { | ||
finalSuffix = suffix; | ||
} else { | ||
const uuid = uuidv7obj(); | ||
finalSuffix = encode(uuid.bytes); | ||
} | ||
if (finalSuffix.length !== 26) { | ||
throw new Error( | ||
`Invalid length. Suffix should have 26 characters, got ${finalSuffix.length}` | ||
); | ||
} | ||
if (finalSuffix[0] > "7") { | ||
throw new Error( | ||
"Invalid suffix. First character must be in the range [0-7]" | ||
); | ||
} | ||
decode(finalSuffix); | ||
if (prefix === "") { | ||
return finalSuffix; | ||
} else { | ||
return `${prefix}_${finalSuffix}`; | ||
} | ||
} | ||
function fromString(typeId, prefix) { | ||
const parts = typeId.split("_"); | ||
if (parts.length === 1) { | ||
return typeidUnboxed("", parts[0]); | ||
} else if (parts.length === 2) { | ||
if (parts[0] === "") { | ||
throw new Error( | ||
`Invalid TypeId. Prefix cannot be empty when there's a separator: ${typeId}` | ||
); | ||
} | ||
if (prefix && parts[0] !== prefix) { | ||
throw new Error( | ||
`Invalid TypeId. Prefix mismatch. Expected ${prefix}, got ${parts[0]}` | ||
); | ||
} | ||
return typeidUnboxed(parts[0], parts[1]); | ||
} else { | ||
throw new Error(`Invalid TypeId format: ${typeId}`); | ||
} | ||
} | ||
function parseTypeId(typeId) { | ||
return { prefix: getType(typeId), suffix: getSuffix(typeId) }; | ||
} | ||
function getType(typeId) { | ||
const underscoreIndex = typeId.indexOf("_"); | ||
if (underscoreIndex === -1) { | ||
return ""; | ||
} | ||
return typeId.substring(0, underscoreIndex); | ||
} | ||
function getSuffix(typeId) { | ||
const underscoreIndex = typeId.indexOf("_"); | ||
if (underscoreIndex === -1) { | ||
return typeId; | ||
} | ||
return typeId.substring(underscoreIndex + 1); | ||
} | ||
function toUUIDBytes(typeId) { | ||
return decode(getSuffix(typeId)); | ||
} | ||
function toUUID(typeId) { | ||
const uuidBytes = toUUIDBytes(typeId); | ||
const uuid = UUID.ofInner(uuidBytes); | ||
return uuid.toString(); | ||
} | ||
function fromUUIDBytes(prefix, bytes) { | ||
const suffix = encode(bytes); | ||
return prefix ? `${prefix}_${suffix}` : suffix; | ||
} | ||
function fromUUID(uuid, prefix) { | ||
const suffix = encode(parseUUID(uuid)); | ||
return prefix ? `${prefix}_${suffix}` : suffix; | ||
} | ||
// src/typeid.ts | ||
var TypeID = class { | ||
@@ -716,19 +814,5 @@ constructor(prefix, suffix = "") { | ||
this.suffix = suffix; | ||
if (!isValidPrefix(prefix)) { | ||
throw new Error("Invalid prefix. Must be at most 63 ascii letters [a-z]"); | ||
} | ||
this.prefix = prefix; | ||
if (suffix) { | ||
this.suffix = suffix; | ||
} else { | ||
const uuid = uuidv7obj(); | ||
this.suffix = encode(uuid.bytes); | ||
} | ||
if (this.suffix.length !== 26) { | ||
throw new Error(`Invalid length. Suffix should have 26 characters, got ${suffix.length}`); | ||
} | ||
if (this.suffix[0] > "7") { | ||
throw new Error("Invalid suffix. First character must be in the range [0-7]"); | ||
} | ||
const unused = decode(this.suffix); | ||
const typeIdRaw = typeidUnboxed(prefix, suffix); | ||
this.prefix = getType(typeIdRaw); | ||
this.suffix = getSuffix(typeIdRaw); | ||
} | ||
@@ -744,3 +828,5 @@ getType() { | ||
if (self.prefix !== prefix) { | ||
throw new Error(`Cannot convert TypeID of type ${self.prefix} to type ${prefix}`); | ||
throw new Error( | ||
`Cannot convert TypeID of type ${self.prefix} to type ${prefix}` | ||
); | ||
} | ||
@@ -763,13 +849,4 @@ return self; | ||
static fromString(str) { | ||
const parts = str.split("_"); | ||
if (parts.length === 1) { | ||
return new TypeID("", parts[0]); | ||
} | ||
if (parts.length === 2) { | ||
if (parts[0] === "") { | ||
throw new Error(`Invalid TypeID. Prefix cannot be empty when there's a separator: ${str}`); | ||
} | ||
return new TypeID(parts[0], parts[1]); | ||
} | ||
throw new Error(`Invalid TypeID string: ${str}`); | ||
const typeIdRaw = fromString(str); | ||
return new TypeID(getType(typeIdRaw), getSuffix(typeIdRaw)); | ||
} | ||
@@ -791,3 +868,12 @@ static fromUUIDBytes(prefix, bytes) { | ||
TypeID, | ||
typeid | ||
fromString, | ||
fromUUID, | ||
fromUUIDBytes, | ||
getSuffix, | ||
getType, | ||
parseTypeId, | ||
toUUID, | ||
toUUIDBytes, | ||
typeid, | ||
typeidUnboxed | ||
}); | ||
@@ -794,0 +880,0 @@ /*! Bundled license information: |
{ | ||
"name": "typeid-js", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"description": "Official implementation of the TypeID specification in TypeScript. TypeIDs are type-safe, K-sortable, and globally unique identifiers inspired by Stripe IDs", | ||
@@ -11,10 +11,10 @@ "keywords": [ | ||
], | ||
"homepage": "https://github.com/jetpack-io/typeid-js", | ||
"bugs": "https://github.com/jetpack-io/typeid-js/issues", | ||
"homepage": "https://github.com/jetify-com/typeid-js", | ||
"bugs": "https://github.com/jetify-com/typeid-js/issues", | ||
"license": "Apache-2.0", | ||
"author": { | ||
"name": "jetpack.io", | ||
"email": "opensource@jetpack.io" | ||
"name": "jetify", | ||
"email": "opensource@jetify.com" | ||
}, | ||
"repository": "github:jetpack-io/typeid-js", | ||
"repository": "github:jetify-com/typeid-js", | ||
"sideEffects": false, | ||
@@ -35,7 +35,7 @@ "main": "./dist/index.js", | ||
"scripts": { | ||
"build": "tsup src --format esm,cjs --dts", | ||
"build": "tsup --format esm,cjs --dts", | ||
"clean": "rm -rf node_modules && rm -rf dist", | ||
"dev": "tsup src --format esm,cjs --watch --dts", | ||
"dev": "tsup --format esm,cjs --watch --dts", | ||
"fmt": "pnpm lint --fix", | ||
"lint": "eslint --cache --cache-location ./node_modules/.cache/eslint .", | ||
"lint": "prettier --write .", | ||
"test": "jest" | ||
@@ -42,0 +42,0 @@ }, |
# Official TypeID-JS Package | ||
### JavaScript implementation of [TypeIDs](https://github.com/jetpack-io/typeid) using TypeScript. | ||
### JavaScript implementation of [TypeIDs](https://github.com/jetify-com/typeid) using TypeScript. | ||
TypeIDs are a modern, **type-safe**, globally unique identifier based on the upcoming | ||
UUIDv7 standard. They provide a ton of nice properties that make them a great choice | ||
as the primary identifiers for your data in a database, APIs, and distributed systems. | ||
Read more about TypeIDs in their [spec](https://github.com/jetpack-io/typeid). | ||
Read more about TypeIDs in their [spec](https://github.com/jetify-com/typeid). | ||
This is the official JavaScript / TypeScript implementation of TypeID by the | ||
[jetpack.io](https://jetpack.io) team. It provides an npm package that can be used by | ||
[jetify](https://www.jetify.com) team. It provides an npm package that can be used by | ||
any JavaScript or TypeScript project. | ||
#### **_ If you wish to use a string-based representation of typeid (instead of class-based), please follow the instructions [here](src/unboxed/README.md). _** | ||
# Installation | ||
Using npm: | ||
```bash | ||
@@ -21,2 +25,3 @@ npm install typeid-js | ||
Using yarn: | ||
```bash | ||
@@ -27,2 +32,3 @@ yarn add typeid-js | ||
Using pnpm: | ||
```bash | ||
@@ -33,2 +39,3 @@ pnpm add typeid-js | ||
# Usage | ||
To create a random TypeID of a given type, use the `typeid()` function: | ||
@@ -38,3 +45,3 @@ | ||
import { typeid } from 'typeid-js'; | ||
const tid = typeid("prefix"); | ||
const tid = typeid('prefix'); | ||
``` | ||
@@ -55,7 +62,8 @@ | ||
For example, you can create a function that only accepts TypeIDs of type `user`: | ||
```typescript | ||
import { typeid, TypeID } from 'typeid-js'; | ||
function doSomethingWithUserID(id: TypeID<"user">) { | ||
// ... | ||
function doSomethingWithUserID(id: TypeID<'user'>) { | ||
// ... | ||
} | ||
@@ -68,2 +76,3 @@ ``` | ||
For example, to parse an existing typeid from a string: | ||
```typescript | ||
@@ -74,6 +83,9 @@ import { TypeID } from 'typeid-js'; | ||
// of TypeID<string> | ||
const tid = TypeID.fromString("prefix_00041061050r3gg28a1c60t3gf").asType("prefix"); | ||
const tid = TypeID.fromString('prefix_00041061050r3gg28a1c60t3gf').asType( | ||
'prefix' | ||
); | ||
``` | ||
To encode an existing UUID as a TypeID: | ||
```typescript | ||
@@ -83,13 +95,14 @@ import { TypeID } from 'typeid-js'; | ||
// In this case TypeID<"prefix"> is inferred from the first argument | ||
const tid = TypeID.fromUUID("prefix", "00000000-0000-0000-0000-000000000000"); | ||
const tid = TypeID.fromUUID('prefix', '00000000-0000-0000-0000-000000000000'); | ||
``` | ||
The full list of methods includes: | ||
+ `getType()`: Returns the type of the type prefix | ||
+ `getSuffix()`: Returns uuid suffix in its base32 representation | ||
+ `toString()`: Encodes the object as a string, using the canonical format | ||
+ `toUUID()`: Decodes the TypeID into a UUID string in hex format. The type prefix is ignored | ||
+ `toUUIDBytes()`: Decodes the TypeID into a UUID byte array. The type prefix is ignored | ||
+ `fromString(str)`: Parses a TypeID from a string | ||
+ `fromUUID(prefix, uuid)`: Creates a TypeID from a prefix and a UUID in hex format | ||
+ `fromUUIDBytes(prefix, bytes)`: Creates a TypeID from a prefix and a UUID in byte array format | ||
- `getType()`: Returns the type of the type prefix | ||
- `getSuffix()`: Returns uuid suffix in its base32 representation | ||
- `toString()`: Encodes the object as a string, using the canonical format | ||
- `toUUID()`: Decodes the TypeID into a UUID string in hex format. The type prefix is ignored | ||
- `toUUIDBytes()`: Decodes the TypeID into a UUID byte array. The type prefix is ignored | ||
- `fromString(str)`: Parses a TypeID from a string | ||
- `fromUUID(prefix, uuid)`: Creates a TypeID from a prefix and a UUID in hex format | ||
- `fromUUIDBytes(prefix, bytes)`: Creates a TypeID from a prefix and a UUID in byte array format |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
101
157983
8
1792