-
Notifications
You must be signed in to change notification settings - Fork 8
feat(generateId): encode a UUID as base58 for the generateId method #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 2 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
8fadbaa
feat(generateId): encode a UUID as base58 for the generateId method
cmwhited f1ea769
feat(generateId): update ci/cd
cmwhited 4e73a87
feat(generateId): remove encoded padding
cmwhited e16b054
feat(generateId): bump uuid version
cmwhited cab0399
feat(generateId): externalize deps
cmwhited File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# Graph Framework Utils | ||
|
||
Provides common utilities for the Graph Framework. | ||
|
||
_All utilities must be runnable on: Browser, NodeJS server, ReactNative._ | ||
|
||
## API | ||
|
||
- `generateId()` - generates a base58 encoded ID from a generated v4 UUID. | ||
|
||
```ts | ||
import { generateId } from "graph-framework-utils"; | ||
|
||
const id = generateId(); | ||
console.log(id); // Gw9uTVTnJdhtczyuzBkL3X | ||
``` | ||
|
||
### Base58 utils | ||
|
||
- `encodeBase58` - encodes a given string (like the hyphen-stripped UUID) to base 58 | ||
|
||
```ts | ||
import { v4 } from "uuid"; | ||
import { encodeBase58 } from "graph-framework-utils/base58"; | ||
|
||
const uuid = v4(); // 92539817-7989-4083-ab80-e9c2b2b66669 | ||
const stripped = uuid.replaceAll(/-/g, ""); // 9253981779894083ab80e9c2b2b66669 | ||
const encoded = encodeBase58(dashesRemoved); | ||
console.log(encoded); // K51CbDqxW35osbjPo5ZF77 | ||
``` | ||
|
||
- `decodeBase58ToUUID` - decodes the given base58 encoded UUID back to its original UUID value | ||
|
||
```ts | ||
import { v4 } from "uuid"; | ||
import { decodeBase58ToUUID, encodeBase58 } from "graph-framework-utils/base58"; | ||
|
||
const uuid = v4(); // 92539817-7989-4083-ab80-e9c2b2b66669 | ||
const stripped = uuid.replaceAll(/-/g, ""); // 9253981779894083ab80e9c2b2b66669 | ||
const encoded = encodeBase58(dashesRemoved); // K51CbDqxW35osbjPo5ZF77 | ||
const decoded = decodeBase58ToUUID(encoded); | ||
|
||
expect(encoded).toHaveLength(22); | ||
expect(decoded).toEqual(uuid); | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { describe, expect, it } from "vitest"; | ||
import { v4 } from "uuid"; | ||
|
||
import { decodeBase58ToUUID, encodeBase58 } from "./base58.js"; | ||
|
||
describe("base58", () => { | ||
it("should be able to encoded a UUID to base58 and then decode it back to its original UUID", () => { | ||
const expected = v4(); | ||
const given = expected.replaceAll(/-/g, ""); | ||
|
||
const encoded = encodeBase58(given); | ||
expect(encoded).toHaveLength(22); | ||
|
||
const decoded = decodeBase58ToUUID(encoded); | ||
expect(decoded).toHaveLength(expected.length); | ||
expect(decoded).toEqual(expected); | ||
}); | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
const BASE58_ALLOWED_CHARS = | ||
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; | ||
|
||
export type Base58 = string; | ||
|
||
/** | ||
* Base58 encodes the given string value. | ||
* | ||
* @example | ||
* ```ts | ||
* import { v4 as uuidv4 } from "uuid"; | ||
* | ||
* const uuid = uuidv4(); // 92539817-7989-4083-ab80-e9c2b2b66669 | ||
* const dashesRemoved = uuid.replaceAll(/-/g, ""); // 9253981779894083ab80e9c2b2b66669 | ||
* const encoded = encodeBase58(dashesRemoved) | ||
* console.log(encoded) // K51CbDqxW35osbjPo5ZF77 | ||
* ``` | ||
* | ||
* @param val string to encode as base58 | ||
* @returns the base58 encoded string | ||
*/ | ||
export function encodeBase58(val: string): Base58 { | ||
const hex = BigInt(`0x${val}`); | ||
let remainder = hex; | ||
const result: string[] = []; // Use an array to store encoded characters | ||
|
||
while (remainder > 0n) { | ||
const mod = remainder % 58n; | ||
result.push(BASE58_ALLOWED_CHARS[Number(mod)]!); | ||
remainder = remainder / 58n; | ||
} | ||
|
||
// Reverse and join the array to get the final Base58 encoded string | ||
return result.reverse().join(""); | ||
} | ||
|
||
export type UUID = string; | ||
|
||
/** | ||
* Expand the base58 encoded UUID back to its original UUID format | ||
* | ||
* @example | ||
* ```ts | ||
* const uuid = 92539817-7989-4083-ab80-e9c2b2b66669; | ||
* const encoded = encodeBase58(dashesRemoved); // K51CbDqxW35osbjPo5ZF77 | ||
* const decoded = decodeBase58ToUUID(encoded); // 92539817-7989-4083-ab80-e9c2b2b66669 | ||
* | ||
* expect(decoded).toEqual(uuid); | ||
* ``` | ||
* | ||
* @param encoded base58 encoded UUID | ||
* @returns the expanded UUID from the base58 encoded value | ||
*/ | ||
export function decodeBase58ToUUID(encoded: string): UUID { | ||
let decoded = 0n; | ||
|
||
for (let char of encoded) { | ||
const index = BASE58_ALLOWED_CHARS.indexOf(char); | ||
if (index === -1) { | ||
throw new Error("Invalid Base58 character"); | ||
} | ||
decoded = decoded * 58n + BigInt(index); | ||
} | ||
|
||
// Convert the bigint to a hex string, padded to 32 characters | ||
let hexStr = decoded.toString(16); | ||
hexStr = hexStr.padStart(32, "0"); // Ensure it is 32 characters | ||
|
||
return [ | ||
hexStr.slice(0, 8), | ||
hexStr.slice(8, 12), | ||
hexStr.slice(12, 16), | ||
hexStr.slice(16, 20), | ||
hexStr.slice(20), | ||
].join("-"); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,9 @@ | ||
import { expect, it } from "vitest"; | ||
import { generateId } from "./generateId.js"; | ||
|
||
it("should generate an id", () => { | ||
expect(generateId()).toBeTypeOf("string"); | ||
}); | ||
import { generateId } from "./generateId.js"; | ||
|
||
it.skip("should have a length of 22 characters", () => { | ||
expect(generateId()).toHaveLength(22); | ||
it("should generate a base58 encoded uuid of 22 char length", () => { | ||
const id = generateId(); | ||
expect(id).toBeTypeOf("string"); | ||
expect(id).toHaveLength(22); | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,25 @@ | ||
import { v4 as uuidv4 } from "uuid"; | ||
|
||
export const generateId = () => { | ||
return uuidv4(); | ||
}; | ||
import { encodeBase58 } from "./base58.js"; | ||
|
||
/** | ||
* Generate a v4 UUID. | ||
* Remove the dashes to make it a 32bit value. | ||
* Base58 encode it and return. | ||
* | ||
* @example | ||
* ``` | ||
* import { generateId } from 'graph-framework-utils' | ||
* | ||
* const id = generateId() | ||
* console.log(id) // Gw9uTVTnJdhtczyuzBkL3X | ||
* ``` | ||
* | ||
* @returns base58 encoded v4 UUID | ||
*/ | ||
export function generateId() { | ||
const uuid = uuidv4(); | ||
const stripped = uuid.replaceAll(/-/g, ""); | ||
const encoded = encodeBase58(stripped); | ||
return encoded.padStart(22, "1"); | ||
|
||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from "./base58.js"; | ||
export * from "./generateId.js"; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"compilerOptions": { | ||
"strict": true, | ||
"exactOptionalPropertyTypes": true, | ||
"noUncheckedIndexedAccess": true, | ||
"esModuleInterop": true, | ||
"sourceMap": true, | ||
"declarationMap": true, | ||
"declaration": true, | ||
"strictNullChecks": true, | ||
"incremental": true, | ||
"composite": true, | ||
"allowJs": true, | ||
"skipLibCheck": true, | ||
"strictFunctionTypes": true, | ||
"forceConsistentCasingInFileNames": true, | ||
"noFallthroughCasesInSwitch": true, | ||
"noErrorTruncation": true, | ||
"isolatedModules": true, | ||
"target": "ESNext", | ||
"module": "NodeNext", | ||
"moduleResolution": "NodeNext", | ||
"outDir": "./dist", | ||
"rootDir": "./src", | ||
"jsx": "react-jsx" | ||
}, | ||
"include": ["./src"], | ||
"exclude": ["node_modules", "src/**/*.test.ts", "src/**/*.spec.ts", "dist"] | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,10 @@ | ||
{ | ||
"extends": "./tsconfig.build.json", | ||
"compilerOptions": { | ||
"strict": true, | ||
"exactOptionalPropertyTypes": true, | ||
"noUncheckedIndexedAccess": true, | ||
"esModuleInterop": true, | ||
"sourceMap": true, | ||
"declarationMap": true, | ||
"declaration": true, | ||
"strictNullChecks": true, | ||
"incremental": true, | ||
"composite": true, | ||
"allowJs": true, | ||
"skipLibCheck": true, | ||
"forceConsistentCasingInFileNames": true, | ||
"noFallthroughCasesInSwitch": true, | ||
"noErrorTruncation": true, | ||
"isolatedModules": true, | ||
"target": "ESNext", | ||
"module": "NodeNext", | ||
"moduleResolution": "NodeNext", | ||
"outDir": "./dist", | ||
"rootDir": "./src", | ||
"jsx": "react-jsx" | ||
"baseUrl": ".", | ||
"rootDir": ".", | ||
"noEmit": true | ||
}, | ||
"include": ["./src"] | ||
"include": ["**/*"], | ||
"exclude": ["**/node_modules", "**/dist"] | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { defineConfig } from "vite"; | ||
import dts from "vite-plugin-dts"; | ||
|
||
// https://vitejs.dev/config/ | ||
export default defineConfig({ | ||
plugins: [ | ||
dts({ tsconfigPath: "./tsconfig.build.json", insertTypesEntry: true }), | ||
], | ||
build: { | ||
lib: { | ||
entry: { | ||
index: "./src/index.ts", | ||
base58: "./src/base58.ts", | ||
}, | ||
formats: ["es", "cjs"], | ||
fileName(format, entryName) { | ||
return `${entryName}${format === "es" ? ".mjs" : ".cjs"}`; | ||
}, | ||
}, | ||
}, | ||
}); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only if we think moving to this build pattern is a good call; otherwise, will revert
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no objection
usually I keep them in parallel so it's easier to see what fails and also to parallelize things, but currently everything fast enough to do this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah had same thought. Parallelizing has the advantage of being able to rerun specific jobs, etc. But felt like we were constantly reinstalling deps, etc. and this let me run build beforehand.