Decorator regex
This package exports a regular expression for matching decorators. Decorators are functions called on classes, class accessors, class fields, class methods, and/or class method parameters.
The regular expression exported from this package can be used to match multi and single-line decorators in JavaScript and TypeScript source code.
Note:
- Decorators in comments (
/** */
,/* */
,//
) are ignored - Regular expression is ECMAScript-compatible. It has not been tested with other flavors (PCRE, PCRE2, etc)
This package is ESM only.
yarn add @flex-development/decorator-regex
From Git:
yarn add @flex-development/decorator-regex@flex-development/decorator-regex
See Git - Protocols | Yarn for details on requesting a specific branch, commit, or tag.
Suppose we have the following module:
import { DECORATOR_REGEX } from '@flex-development/decorator-regex'
import { omit } from '@flex-development/tutils'
import { dedent } from 'ts-dedent'
const code: string = dedent`
/**
* [Data access object][1] for the {@linkcode DatabaseTable.USERS} table.
*
* [1]: https://en.wikipedia.org/wiki/Data_access_object
*
* @extends {Entity<IUserRaw,CreateUserDTO,IUser>}
* @implements {IUser}
*/
@Table<User>({
defaultScope: {
attributes: ['created_at', 'email', 'id', 'provider'],
order: [['id', OrderDirection.ASC]],
raw: false
},
deletedAt: false,
hooks: {
/**
* Normalizes data before a user is persisted to the database.
*
* This includes:
*
* - Trimming and lowercasing string fields
*
* @param {User} instance - Current user instance
* @return {void} Nothing when complete
*/
beforeSave(instance: User): void {
trimmedLowercasedFields(instance.dataValues)
}
},
omitNull: false,
paranoid: false,
tableName: DatabaseTable.USERS,
timestamps: true
})
class User
extends Entity<IUserRaw, CreateUserDTO, IUser> implements IUser {
@ApiProperty({ description: 'When user was created', type: Number })
@Column({
allowNull: false,
defaultValue: User.CURRENT_TIMESTAMP,
type: DataType.BIGINT,
validate: { isUnixTimestamp: User.isUnixTimestamp }
})
declare created_at: IUser['created_at']
@ApiProperty({
description: 'Email address',
maxLength: 254,
minLength: 3,
type: String
})
@Column({
allowNull: false,
type: DataType.STRING(254),
unique: true,
validate: { isEmail: true, len: [3, 254] }
})
declare email: IUser['email']
@ApiProperty({ description: 'Unique identifier', type: Number })
@Column({
allowNull: false,
autoIncrementIdentity: true,
defaultValue: Sequelize.fn('nextval', DatabaseSequence.USERS),
primaryKey: true,
type: 'NUMERIC',
unique: true,
validate: { notNull: true }
})
declare id: IUser['id']
@ApiProperty({
description: 'Authentication provider',
enum: OAuthProvider,
enumName: 'OAuthProvider',
nullable: true
})
@Column({
allowNull: true,
defaultValue: null,
type: DataType.ENUM(...User.AUTH_PROVIDERS)
})
declare provider: IUser['provider']
@HasMany(() => Token)
declare tokens: Token[]
}
`
const print = (matches: IterableIterator<RegExpMatchArray>): void => {
console.debug([...matches].map(match => omit(match, ['input'])))
}
print(code.matchAll(DECORATOR_REGEX))
...running that yields:
[
{
'0': '@Table<User>({\n' +
' defaultScope: {\n' +
" attributes: ['created_at', 'email', 'id', 'provider'],\n" +
" order: [['id', OrderDirection.ASC]],\n" +
' raw: false\n' +
' },\n' +
' deletedAt: false,\n' +
' hooks: {\n' +
' /**\n' +
' * Normalizes data before a user is persisted to the database.\n' +
' *\n' +
' * This includes:\n' +
' *\n' +
' * - Trimming and lowercasing string fields\n' +
' *\n' +
' * @param {User} instance - Current user instance\n' +
' * @return {void} Nothing when complete\n' +
' */\n' +
' beforeSave(instance: User): void {\n' +
' trimmedLowercasedFields(instance.dataValues)\n' +
' }\n' +
' },\n' +
' omitNull: false,\n' +
' paranoid: false,\n' +
' tableName: DatabaseTable.USERS,\n' +
' timestamps: true\n' +
' })',
'1': 'Table',
'2': '({\n' +
' defaultScope: {\n' +
" attributes: ['created_at', 'email', 'id', 'provider'],\n" +
" order: [['id', OrderDirection.ASC]],\n" +
' raw: false\n' +
' },\n' +
' deletedAt: false,\n' +
' hooks: {\n' +
' /**\n' +
' * Normalizes data before a user is persisted to the database.\n' +
' *\n' +
' * This includes:\n' +
' *\n' +
' * - Trimming and lowercasing string fields\n' +
' *\n' +
' * @param {User} instance - Current user instance\n' +
' * @return {void} Nothing when complete\n' +
' */\n' +
' beforeSave(instance: User): void {\n' +
' trimmedLowercasedFields(instance.dataValues)\n' +
' }\n' +
' },\n' +
' omitNull: false,\n' +
' paranoid: false,\n' +
' tableName: DatabaseTable.USERS,\n' +
' timestamps: true\n' +
' })',
index: 227,
groups: [Object: null prototype] {
identifier: 'Table',
parameters: '({\n' +
' defaultScope: {\n' +
" attributes: ['created_at', 'email', 'id', 'provider'],\n" +
" order: [['id', OrderDirection.ASC]],\n" +
' raw: false\n' +
' },\n' +
' deletedAt: false,\n' +
' hooks: {\n' +
' /**\n' +
' * Normalizes data before a user is persisted to the database.\n' +
' *\n' +
' * This includes:\n' +
' *\n' +
' * - Trimming and lowercasing string fields\n' +
' *\n' +
' * @param {User} instance - Current user instance\n' +
' * @return {void} Nothing when complete\n' +
' */\n' +
' beforeSave(instance: User): void {\n' +
' trimmedLowercasedFields(instance.dataValues)\n' +
' }\n' +
' },\n' +
' omitNull: false,\n' +
' paranoid: false,\n' +
' tableName: DatabaseTable.USERS,\n' +
' timestamps: true\n' +
' })'
}
},
{
'0': "@ApiProperty({ description: 'When user was created', type: Number })",
'1': 'ApiProperty',
'2': "({ description: 'When user was created', type: Number })",
index: 994,
groups: [Object: null prototype] {
identifier: 'ApiProperty',
parameters: "({ description: 'When user was created', type: Number })"
}
},
{
'0': '@Column({\n' +
' allowNull: false,\n' +
' defaultValue: User.CURRENT_TIMESTAMP,\n' +
' type: DataType.BIGINT,\n' +
' validate: { isUnixTimestamp: User.isUnixTimestamp }\n' +
' })',
'1': 'Column',
'2': '({\n' +
' allowNull: false,\n' +
' defaultValue: User.CURRENT_TIMESTAMP,\n' +
' type: DataType.BIGINT,\n' +
' validate: { isUnixTimestamp: User.isUnixTimestamp }\n' +
' })',
index: 1068,
groups: [Object: null prototype] {
identifier: 'Column',
parameters: '({\n' +
' allowNull: false,\n' +
' defaultValue: User.CURRENT_TIMESTAMP,\n' +
' type: DataType.BIGINT,\n' +
' validate: { isUnixTimestamp: User.isUnixTimestamp }\n' +
' })'
}
},
{
'0': '@ApiProperty({\n' +
" description: 'Email address',\n" +
' maxLength: 254,\n' +
' minLength: 3,\n' +
' type: String\n' +
' })',
'1': 'ApiProperty',
'2': '({\n' +
" description: 'Email address',\n" +
' maxLength: 254,\n' +
' minLength: 3,\n' +
' type: String\n' +
' })',
index: 1296,
groups: [Object: null prototype] {
identifier: 'ApiProperty',
parameters: '({\n' +
" description: 'Email address',\n" +
' maxLength: 254,\n' +
' minLength: 3,\n' +
' type: String\n' +
' })'
}
},
{
'0': '@Column({\n' +
' allowNull: false,\n' +
' type: DataType.STRING(254),\n' +
' unique: true,\n' +
' validate: { isEmail: true, len: [3, 254] }\n' +
' })',
'1': 'Column',
'2': '({\n' +
' allowNull: false,\n' +
' type: DataType.STRING(254),\n' +
' unique: true,\n' +
' validate: { isEmail: true, len: [3, 254] }\n' +
' })',
index: 1425,
groups: [Object: null prototype] {
identifier: 'Column',
parameters: '({\n' +
' allowNull: false,\n' +
' type: DataType.STRING(254),\n' +
' unique: true,\n' +
' validate: { isEmail: true, len: [3, 254] }\n' +
' })'
}
},
{
'0': "@ApiProperty({ description: 'Unique identifier', type: Number })",
'1': 'ApiProperty',
'2': "({ description: 'Unique identifier', type: Number })",
index: 1615,
groups: [Object: null prototype] {
identifier: 'ApiProperty',
parameters: "({ description: 'Unique identifier', type: Number })"
}
},
{
'0': '@Column({\n' +
' allowNull: false,\n' +
' autoIncrementIdentity: true,\n' +
" defaultValue: Sequelize.fn('nextval', DatabaseSequence.USERS),\n" +
' primaryKey: true,\n' +
" type: 'NUMERIC',\n" +
' unique: true,\n' +
' validate: { notNull: true }\n' +
' })',
'1': 'Column',
'2': '({\n' +
' allowNull: false,\n' +
' autoIncrementIdentity: true,\n' +
" defaultValue: Sequelize.fn('nextval', DatabaseSequence.USERS),\n" +
' primaryKey: true,\n' +
" type: 'NUMERIC',\n" +
' unique: true,\n' +
' validate: { notNull: true }\n' +
' })',
index: 1685,
groups: [Object: null prototype] {
identifier: 'Column',
parameters: '({\n' +
' allowNull: false,\n' +
' autoIncrementIdentity: true,\n' +
" defaultValue: Sequelize.fn('nextval', DatabaseSequence.USERS),\n" +
' primaryKey: true,\n' +
" type: 'NUMERIC',\n" +
' unique: true,\n' +
' validate: { notNull: true }\n' +
' })'
}
},
{
'0': '@ApiProperty({\n' +
" description: 'Authentication provider',\n" +
' enum: OAuthProvider,\n' +
" enumName: 'OAuthProvider',\n" +
' nullable: true\n' +
' })',
'1': 'ApiProperty',
'2': '({\n' +
" description: 'Authentication provider',\n" +
' enum: OAuthProvider,\n' +
" enumName: 'OAuthProvider',\n" +
' nullable: true\n' +
' })',
index: 1974,
groups: [Object: null prototype] {
identifier: 'ApiProperty',
parameters: '({\n' +
" description: 'Authentication provider',\n" +
' enum: OAuthProvider,\n' +
" enumName: 'OAuthProvider',\n" +
' nullable: true\n' +
' })'
}
},
{
'0': '@Column({\n' +
' allowNull: true,\n' +
' defaultValue: null,\n' +
' type: DataType.ENUM(...User.AUTH_PROVIDERS)\n' +
' })',
'1': 'Column',
'2': '({\n' +
' allowNull: true,\n' +
' defaultValue: null,\n' +
' type: DataType.ENUM(...User.AUTH_PROVIDERS)\n' +
' })',
index: 2133,
groups: [Object: null prototype] {
identifier: 'Column',
parameters: '({\n' +
' allowNull: true,\n' +
' defaultValue: null,\n' +
' type: DataType.ENUM(...User.AUTH_PROVIDERS)\n' +
' })'
}
},
{
'0': '@HasMany(() => Token)',
'1': 'HasMany',
'2': '(() => Token)',
index: 2300,
groups: [Object: null prototype] {
identifier: 'HasMany',
parameters: '(() => Token)'
}
}
]
This package exports the identifier DECORATOR_REGEX
.
There is no default export.
Regular expression matching multi and single-line decorators.
Ignores matches in comments.
Required flags:
s
: dot allu
: unicode
Source:
src/decorator-regex.ts
This package is fully typed with TypeScript.
decorator-regex
—export
statement regeximport-regex
—import
statement regex
See CONTRIBUTING.md
.