A Redis key creation utility.
Create Redis Key Templates, which include parameters, using a nested config object & use your Redis Key Template strings to create Redis Keys.
This package heavily uses Template Literal Types which is available since TypeScript 4.1 so you need at least this version of Typescript for this package to properly work.
![]() |
|---|
Check How to Use section to see explanations of usage options on examples.
Install create-redis-key with npm
npm install create-redis-keyType definitions? Included!
Eventual purpose of this library is to create a Redis Key (which is basically a string) using a template which we call in this library a Redis Key Template.
There is a function called createRedisKey() which takes a Redis Key Template and an object which includes values for the params in the Redis Key Template, then replaces parameters in template with the given values.
Most basic usage is as follows:
const blogPostRK = createRedisKey('posts:%PostID%', {
PostID: '1',
});This creates a string which equals to posts:1
There are 3 ways you can use this library.
- Create a
Redis Key Templates MapusingcreateRedisKeysMap()to use it in conjunction withcreateRedisKey()to create Redis keys. - Create an object which has keys shaped as a
Redis Key Templateand use it in conjunction withcreateRedisKey()to create Redis keys. - Just use
createRedisKey()function by writing yourRedis Key Templateas parameter to create a Redis key.
There are detailed explanations for each of them down below.
There are 3 ways you can use this library. Examples for different options show how you can get the same output using different methods.
You will get parameter suggestions on your IDE based on the
Redis Key Templateyou provided tocreateRedisKey()function.
All params on a
Redis Key Templateare required. You will get type errors if you don't provide all of them.
First of all, import needed functions as follows:
import {
createRedisKeyParam,
createRedisKeysMap,
createRedisKey,
} from 'create-redis-key';or using require
var CRK = require('create-redis-key');
const { createRedisKeyParam, createRedisKeysMap, createRedisKey } = CRK;Create a Redis Keys Config object.
You should write
as constat the end of the object for things to properly work.
const redisKeysConfig = {
SCOPE_FIRST_PART: [],
appStatus: ['app-status'],
restaurants: {
SCOPE_FIRST_PART: ['RESTAURANTS'],
byCategory: ['by-category', createRedisKeyParam('CategoryID')],
byCity: [createRedisKeyParam('CityID')],
},
categories: {
SCOPE_FIRST_PART: ['categories'],
byID: [createRedisKeyParam('CategoryID')],
},
users: {
SCOPE_FIRST_PART: ['users'],
online: ['online'],
withActiveOrder: ['with-active-order'],
byID: ['by-id', createRedisKeyParam('UserID')],
},
couriers: {
SCOPE_FIRST_PART: ['couriers'],
Online: ['online'],
OnDelivery: ['on-delivery'],
byID: {
SCOPE_FIRST_PART: ['by-id', createRedisKeyParam('CourierID')],
PreviousDeliveries: ['previous-deliveries'],
},
},
orders: {
SCOPE_FIRST_PART: ['orders'],
byUser: ['of-user', createRedisKeyParam('UserID')],
byCity: {
SCOPE_FIRST_PART: ['by-city', createRedisKeyParam('CityName')],
byCourier: ['of-courier', createRedisKeyParam('CourierID')],
},
},
} as const;Then create a Redis Keys Templates Map using the config:
If you give an invalid config, return type will be
never. I explained why it works this way at FAQ section.
const RedisKeysMap = createRedisKeysMap(exampleRedisKeysConfig);It will create a Redis Keys Templates Map
{
appStatus: 'app-status',
restaurants: {
byCategory: 'RESTAURANTS:by-category:%CategoryID%',
byCity: 'RESTAURANTS:%CityID%',
},
categories: {
byID: 'categories:%CategoryID%',
},
users: {
online: 'users:online',
withActiveOrder: 'users:with-active-order',
byID: 'users:by-id:%UserID%',
},
couriers: {
Online: 'couriers:online',
OnDelivery: 'couriers:on-delivery',
byID: {
PreviousDeliveries: 'couriers:by-id:%CourierID%:previous-deliveries',
},
},
orders: {
byUser: 'orders:of-user:%UserID%',
byCity: {
byCourier: 'orders:by-city:%CityName%:of-courier:%CourierID%',
},
},
}You can then use this map to create a Redis key when needed:
This will produce couriers:by-id:1234:previous-deliveries
const previousDeliveriesOfCourierRK = createRedisKey(
RedisKeysMap.couriers.byID.PreviousDeliveries,
{
CourierID: '1234',
}
);Create another key using map:
This will produce orders:by-city:istanbul:of-courier:1234
const latestOrdersOfCourierInCityRK = createRedisKey(
RedisKeysMap.orders.byCity.byCourier,
{
CourierID: '1234',
CityName: 'istanbul',
}
);Instead of creating a Redis Keys Templates Map using createRedisKeysMap() with a config, you can write it yourself.
You should write
as constat the end of the object for things to properly work.
When you write
Redis Key Templatesmanually, be aware that it is much more error prone than usingOption 1.
const DeliveryServiceRedisKeyTemplatesMap = {
appStatus: 'app-status',
restaurantsByCategory: 'RESTAURANTS:by-category:%CategoryID%',
users: 'users:with-active-order',
previousDeliveriesOfCourier: 'couriers:by-id:%CourierID%:previous-deliveries',
latestOrdersOfCourierInCity:
'orders:by-city:%CityName%:of-courier:%CourierID%',
} as const;Then you can use it just like shown on Option 1:
This will produce orders:by-city:istanbul:of-courier:1234
const latestOrdersOfCourierInCityRK = createRedisKey(
DeliveryServiceRedisKeyTemplatesMap.latestOrdersOfCourierInCity,
{
CourierID: '1234',
CityName: 'istanbul',
}
);This is most basic usage of this package.
You can just write your Redis Key Template as a parameter:
This will produce orders:by-city:istanbul:of-courier:1234
const latestOrdersOfCourierInCityRK = createRedisKey(
'orders:by-city:%CityName%:of-courier:%CourierID%',
{
CourierID: '1234',
CityName: 'istanbul',
}
);A string to be used as a template to create a Redis key.
Format: a-key-part:%ParamName1%:another-key-part:%ParamName2%
A part of Redis Key Template which represents a variable part of the key.
Format: %ParamName%
A part of Redis Key Template which is either a Redis Key Param or a string
Formats: %ParamName% | random-text
An array of Redis Key Part
const exampleTemplateArray = ['key1', createRedisKeyParam('Param1')];Main building block of the a Redis Keys Config.
- It has to have a key named
SCOPE_FIRST_PARTwhich is aRedis Keys Config Template Array - Other keys can be either a
Redis Keys Config Template Arrayor aRedis Keys Config Scope
const exampleScope = {
SCOPE_FIRST_PART: [],
key0: ['key0'],
key1: ['key1', createRedisKeyParam('Param1')],
key2: ['key2', createRedisKeyParam('Param2')],
aNestedScope: {
SCOPE_FIRST_PART: ['a-nested-scope', createRedisKeyParam('Param3')],
scopedKey1: ['a-key-1'],
scopedKey2: ['a-key-2', createRedisKeyParam('KeyParam')],
},
};A config object to create Redis Keys Template Map
- This is actually a
Redis Keys Config Scope
const exampleRedisKeysConfig = {
SCOPE_FIRST_PART: [],
key1: ['a-random-text-1', createRedisKeyParam('Param1')],
key2: ['another-text', createRedisKeyParam('Param2')],
aNestedScope: {
SCOPE_FIRST_PART: ['a-nested-scope', createRedisKeyParam('Param3')],
scopedKey1: ['a-key-1', createRedisKeyParam('KeyParam')],
},
} as const;This is the product of createRedisKeysMap() function.
Given the following config to createRedisKeysMap() function:
const exampleRedisKeysConfig = {
SCOPE_FIRST_PART: [],
key1: ['a-random-text-1', createRedisKeyParam('Param1')],
key2: ['another-text', createRedisKeyParam('Param2')],
aNestedScope: {
SCOPE_FIRST_PART: ['a-nested-scope', createRedisKeyParam('Param3')],
scopedKey1: ['a-key-1', createRedisKeyParam('KeyParam')],
},
} as const;When you use this config to create a map:
createRedisKeysMap(exampleRedisKeysConfig);It will produce this object which is a Redis Keys Template Map:
{
key1: 'a-random-text-1:%Param1%';
key2: 'another-text:%Param2%';
aNestedScope: {
scopedKey1: 'a-nested-scope:%Param3%:a-key-1:%KeyParam%';
}
}You can then use it with createRedisKey() to create Redis keys as needed.
createRedisKeyParam(paramName: string)
Creates a Redis Key Param object.
It can be used in a Redis Keys Config Template Array when creating Redis Keys Config
const exampleRedisKeysConfig = {
SCOPE_FIRST_PART: ['micro-service', createRedisKeyParam('ServiceID')],
key1: ['a-random-text-1', createRedisKeyParam('Param1')],
key2: [
'another-text',
createRedisKeyParam('Param2'),
'another-part',
createRedisKeyParam('Param3'),
],
} as const;createRedisKeysMap(
redisKeysConfig: Record<string, any>,
optionalDelimiter: string | null
)Creates a Redis Keys Template Map using a Redis Keys Config object.
Default delimiter is colon (:)
If you don't want to use a delimiter, give an empty string ('') to optionalDelimiter parameter.
For most cases (like 95% of them), you will use a delimiter. Therefore I chose the most commonly used one (colon
:), which is also used in official Redis tutorials, as the default delimiter.
redisKeysConfigshould be given as the example below. Otherwise you won't get suggestions oncreateRedisKey()and also Typescript will give an error when you try to provide parameter values.
readonly RedisKeysConfigdoes not work. Only way is to writeas constat the end of the config object.
Given the config following config:
// a Redis Keys Config
const exampleRedisKeysConfig = {
SCOPE_FIRST_PART: [],
key1: ['a-random-text-1', createRedisKeyParam('Param1')],
key2: ['another-text', createRedisKeyParam('Param2')],
aNestedScope: {
SCOPE_FIRST_PART: ['a-nested-scope', createRedisKeyParam('Param3')],
scopedKey1: ['a-key-1', createRedisKeyParam('KeyParam')],
},
} as const;And called as follows:
const exampleRedisKeysTemplateMap = createRedisKeysMap(exampleRedisKeysConfig);It will produce this object which is a Redis Keys Template Map:
{
key1: 'a-random-text-1:%Param1%';
key2: 'another-text:%Param2%';
aNestedScope: {
scopedKey1: 'a-nested-scope:%Param3%:a-key-1:%KeyParam%';
}
}createRedisKey(
redisKeyTemplateString: string,
params: Record<string, string>
): stringCreates a Redis key using a Redis Key Template and replacing parameters on template with given parameter values.
const blogPostCommentRepliesRK = createRedisKey(
'posts:%PostID%:comments:%CommentID%:replies',
{
PostID: '1234',
CommentID: '9876',
}
);This creates a string which equals to posts:1234:comments:9876:replies
When you give an invalid config object to it, it returns never as a result type. Since I need your config as a readonly object, I can't make the parameter type RedisKeysConfig directly. So I need to accept an object, check if it is valid & make the return type never in order to make you aware that there is something wrong.
I now that it's a bad developer experience but I'm not sure if there is a way to solve this. Feel free to open an Issue to discuss this.
To run tests, run the following command:
npm run testThis an NPM package.
- When you make changes,
- Build the project.
- Create a new empty project.
- Link the local build to your test project.
- Use your development version on your test project to see if it is working.
- Write tests to verify that your new feature is working properly and also doesn't break anything.
Contributions are always welcome!
There are some basic rules though.
- Be sure you don't break any existing type definitions.
- Developer Experience of this library depends on Typescript types.
- Any change you make on type definitions might cause performance issues.
- If you create a new Typescript type, write tests for it.
- Yes, really. Typescript is complicated and it isn't enough if it seems like it's working.
- Check TSD package to see how you can test types.
- Write tests for your new feature.
- I won't accept any PR without additional tests.
- I won't accept any PR if it can't pass existing tests.
