create-redis-key
v1.0.1
Published
A Redis key creation utility.
Downloads
123
Maintainers
Readme
Create Redis Key
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.
| | | | | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
Examples
Check How to Use section to see explanations of usage options on examples.
Sections
Installation
Install create-redis-key with npm
npm install create-redis-key
Type definitions? Included!
How It Works
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 Map
usingcreateRedisKeysMap()
to use it in conjunction withcreateRedisKey()
to create Redis keys. - Create an object which has keys shaped as a
Redis Key Template
and use it in conjunction withcreateRedisKey()
to create Redis keys. - Just use
createRedisKey()
function by writing yourRedis Key Template
as parameter to create a Redis key.
There are detailed explanations for each of them down below.
Usage
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 Template
you provided tocreateRedisKey()
function.
All params on a
Redis Key Template
are 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;
Option 1 (Recommended)
Create a Redis Keys Config
object.
You should write
as const
at 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',
}
);
Option 2
Instead of creating a Redis Keys Templates Map
using createRedisKeysMap()
with a config, you can write it yourself.
You should write
as const
at the end of the object for things to properly work.
When you write
Redis Key Templates
manually, 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',
}
);
Option 3
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',
}
);
Documentation
Documentation - Terms
Redis Key Template
A string to be used as a template to create a Redis key.
Format: a-key-part:%ParamName1%:another-key-part:%ParamName2%
Redis Key Param
A part of Redis Key Template
which represents a variable part of the key.
Format: %ParamName%
Redis Key Part
A part of Redis Key Template
which is either a Redis Key Param
or a string
Formats: %ParamName%
| random-text
Redis Keys Config Template Array
An array of Redis Key Part
const exampleTemplateArray = ['key1', createRedisKeyParam('Param1')];
Redis Keys Config Scope
Main building block of the a Redis Keys Config
.
- It has to have a key named
SCOPE_FIRST_PART
which is aRedis Keys Config Template Array
- Other keys can be either a
Redis Keys Config Template Array
or 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')],
},
};
Redis Keys Config
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;
Redis Keys Template Map
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.
Documentation - Functions
createRedisKeyParam
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
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.
redisKeysConfig
should 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 RedisKeysConfig
does not work. Only way is to writeas const
at 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
createRedisKey(
redisKeyTemplateString: string,
params: Record<string, string>
): string
Creates 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
FAQ
When I give a config object to createRedisKeysMap()
it's output type is never
. Why?
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.
Running Tests
To run tests, run the following command:
npm run test
Local Development
This 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.
Contributing
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.