Dac0d3r
Dac0d3r

Reputation: 1844

Convert string to uuid in vanilla JavaScript without external dependencies

I'm in a situation where I need to run some javascript in a place where I cannot use external packages.

Ideally the function should take a string as parameter and return a string in the format of a uuid (not random), based on the string parameter of course.

I've been searching all over the internet but except a few npm packages I could not find a simple and short function for doing so, since most of the functions are just random uuidv4 functions.

Since I need this to run some js in an external application, it is important that no external dependencies are used, and also the shorter the better.

Use case:

I have an entity without an id (uuid) field. It does have 2 other ids however. Before I persist it I want to generate an id in the format of a uuid based on a concatenated string of ${fooId}-${barId} so I will be able to get the resource by this id from the API.

If I did not have the limitation of not being able to use external dependencies / npm packages and scripts, I would have used the uuid package and the uuidv5. Sadly I do not have this possibility, so I thought it would be possible to to this in a single vanilla js function.

If I was not clear before I need to figure out what to put here

const stringToUuid = (str) => {
  // return string formatted as a uuid, based on the str parameter
}

Upvotes: 1

Views: 21811

Answers (1)

vicpermir
vicpermir

Reputation: 3702

If the combination of fooId and barId is unique you could iterate over them and fill some UUID mask.

const stringToUuid = (str) => {
  str = str.replace('-', '');
  return 'xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, function(c, p) {
    return str[p % str.length];
  });
}

var input  = "813538-359512";
var output = stringToUuid(input);

console.log('Input: ' + input);
console.log('Output: ' + output);

The output should be a valid UUID string.

Caveats about fooId and barId:

  • Both must contain only hexadecimal characters (I'm guessing they are numbers?)
  • The length of both combined must be below 32 characters, otherwise the combination is longer than the characters replaced in the UUID mask and you could run into duplicates

It's a really simplistic way to solve your problem to be honest, I'm not sure of the implications or how robust it is.

If you want to combine two UUID to generate a third one you could operate on each character in pairs. In this case, it seems the most used operation is a bitwise XOR so that's what I'll do in this example:

const stringToUuid = (uuid1, uuid2) => {
  return 'xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx'.replace(/[x]/g, function(c, p) {
    var c1 = uuid1.charAt(p);
    var c2 = uuid2.charAt(p);
    return (parseInt(c1, 16) ^ parseInt(c2, 16)).toString(16).charAt(0);
  });
}

// Both must be valid UUID
var uuid1 = 'e7d24026-3081-4789-a6bd-34d8b69365ac';
var uuid2 = '6556c838-df63-461a-a415-852aa464f344';
var output = stringToUuid(uuid1, uuid2);

console.log('Uuid1: ' + uuid1);
console.log('Uuid2: ' + uuid2);
console.log('Output: ' + output);

The result should still be a valid UUID, but I guess you lose on uniqueness.

Upvotes: 5

Related Questions