@@ -61,7 +61,391 @@ yarn add @flex-development/decorator-regex@flex-development/decorator-regex
6161
6262## Use
6363
64- ** TODO** : usage example.
64+ Suppose we have the following module:
65+
66+ ``` typescript
67+ import { DECORATOR_REGEX } from ' @flex-development/decorator-regex'
68+ import { omit } from ' radash'
69+ import { dedent } from ' ts-dedent'
70+
71+ const code: string = dedent `
72+ /**
73+ * [Data access object][1] for the {@linkcode DatabaseTable.USERS} table.
74+ *
75+ * [1]: https://en.wikipedia.org/wiki/Data_access_object
76+ *
77+ * @extends {Entity<IUserRaw,CreateUserDTO,IUser>}
78+ * @implements {IUser}
79+ */
80+ @Table<User>({
81+ defaultScope: {
82+ attributes: ['created_at', 'email', 'id', 'provider'],
83+ order: [['id', OrderDirection.ASC]],
84+ raw: false
85+ },
86+ deletedAt: false,
87+ hooks: {
88+ /**
89+ * Normalizes data before a user is persisted to the database.
90+ *
91+ * This includes:
92+ *
93+ * - Trimming and lowercasing string fields
94+ *
95+ * @param {User} instance - Current user instance
96+ * @return {void} Nothing when complete
97+ */
98+ beforeSave(instance: User): void {
99+ trimmedLowercasedFields(instance.dataValues)
100+ }
101+ },
102+ omitNull: false,
103+ paranoid: false,
104+ tableName: DatabaseTable.USERS,
105+ timestamps: true
106+ })
107+ class User
108+ extends Entity<IUserRaw, CreateUserDTO, IUser> implements IUser {
109+ @ApiProperty({ description: 'When user was created', type: Number })
110+ @Column({
111+ allowNull: false,
112+ defaultValue: User.CURRENT_TIMESTAMP,
113+ type: DataType.BIGINT,
114+ validate: { isUnixTimestamp: User.isUnixTimestamp }
115+ })
116+ declare created_at: IUser['created_at']
117+
118+ @ApiProperty({
119+ description: 'Email address',
120+ maxLength: 254,
121+ minLength: 3,
122+ type: String
123+ })
124+ @Column({
125+ allowNull: false,
126+ type: DataType.STRING(254),
127+ unique: true,
128+ validate: { isEmail: true, len: [3, 254] }
129+ })
130+ declare email: IUser['email']
131+
132+ @ApiProperty({ description: 'Unique identifier', type: Number })
133+ @Column({
134+ allowNull: false,
135+ autoIncrementIdentity: true,
136+ defaultValue: Sequelize.fn('nextval', DatabaseSequence.USERS),
137+ primaryKey: true,
138+ type: 'NUMERIC',
139+ unique: true,
140+ validate: { notNull: true }
141+ })
142+ declare id: IUser['id']
143+
144+ @ApiProperty({
145+ description: 'Authentication provider',
146+ enum: OAuthProvider,
147+ enumName: 'OAuthProvider',
148+ nullable: true
149+ })
150+ @Column({
151+ allowNull: true,
152+ defaultValue: null,
153+ type: DataType.ENUM(...User.AUTH_PROVIDERS)
154+ })
155+ declare provider: IUser['provider']
156+
157+ @HasMany(() => Token)
158+ declare tokens: Token[]
159+ }
160+ `
161+
162+ const print = (matches : IterableIterator <RegExpMatchArray >): void => {
163+ console .debug ([... matches ].map (match => omit (match , [' input' ])))
164+ }
165+
166+ print (code .matchAll (DECORATOR_REGEX ))
167+ ```
168+
169+ ...running that yields:
170+
171+ ``` sh
172+ [
173+ {
174+ ' 0' : ' @Table<User>({\n' +
175+ ' defaultScope: {\n' +
176+ " attributes: ['created_at', 'email', 'id', 'provider'],\n" +
177+ " order: [['id', OrderDirection.ASC]],\n" +
178+ ' raw: false\n' +
179+ ' },\n' +
180+ ' deletedAt: false,\n' +
181+ ' hooks: {\n' +
182+ ' /**\n' +
183+ ' * Normalizes data before a user is persisted to the database.\n' +
184+ ' *\n' +
185+ ' * This includes:\n' +
186+ ' *\n' +
187+ ' * - Trimming and lowercasing string fields\n' +
188+ ' *\n' +
189+ ' * @param {User} instance - Current user instance\n' +
190+ ' * @return {void} Nothing when complete\n' +
191+ ' */\n' +
192+ ' beforeSave(instance: User): void {\n' +
193+ ' trimmedLowercasedFields(instance.dataValues)\n' +
194+ ' }\n' +
195+ ' },\n' +
196+ ' omitNull: false,\n' +
197+ ' paranoid: false,\n' +
198+ ' tableName: DatabaseTable.USERS,\n' +
199+ ' timestamps: true\n' +
200+ ' })' ,
201+ ' 1' : ' Table' ,
202+ ' 2' : ' ({\n' +
203+ ' defaultScope: {\n' +
204+ " attributes: ['created_at', 'email', 'id', 'provider'],\n" +
205+ " order: [['id', OrderDirection.ASC]],\n" +
206+ ' raw: false\n' +
207+ ' },\n' +
208+ ' deletedAt: false,\n' +
209+ ' hooks: {\n' +
210+ ' /**\n' +
211+ ' * Normalizes data before a user is persisted to the database.\n' +
212+ ' *\n' +
213+ ' * This includes:\n' +
214+ ' *\n' +
215+ ' * - Trimming and lowercasing string fields\n' +
216+ ' *\n' +
217+ ' * @param {User} instance - Current user instance\n' +
218+ ' * @return {void} Nothing when complete\n' +
219+ ' */\n' +
220+ ' beforeSave(instance: User): void {\n' +
221+ ' trimmedLowercasedFields(instance.dataValues)\n' +
222+ ' }\n' +
223+ ' },\n' +
224+ ' omitNull: false,\n' +
225+ ' paranoid: false,\n' +
226+ ' tableName: DatabaseTable.USERS,\n' +
227+ ' timestamps: true\n' +
228+ ' })' ,
229+ index: 227,
230+ groups: [Object: null prototype] {
231+ identifier: ' Table' ,
232+ parameters: ' ({\n' +
233+ ' defaultScope: {\n' +
234+ " attributes: ['created_at', 'email', 'id', 'provider'],\n" +
235+ " order: [['id', OrderDirection.ASC]],\n" +
236+ ' raw: false\n' +
237+ ' },\n' +
238+ ' deletedAt: false,\n' +
239+ ' hooks: {\n' +
240+ ' /**\n' +
241+ ' * Normalizes data before a user is persisted to the database.\n' +
242+ ' *\n' +
243+ ' * This includes:\n' +
244+ ' *\n' +
245+ ' * - Trimming and lowercasing string fields\n' +
246+ ' *\n' +
247+ ' * @param {User} instance - Current user instance\n' +
248+ ' * @return {void} Nothing when complete\n' +
249+ ' */\n' +
250+ ' beforeSave(instance: User): void {\n' +
251+ ' trimmedLowercasedFields(instance.dataValues)\n' +
252+ ' }\n' +
253+ ' },\n' +
254+ ' omitNull: false,\n' +
255+ ' paranoid: false,\n' +
256+ ' tableName: DatabaseTable.USERS,\n' +
257+ ' timestamps: true\n' +
258+ ' })'
259+ }
260+ },
261+ {
262+ ' 0' : " @ApiProperty({ description: 'When user was created', type: Number })" ,
263+ ' 1' : ' ApiProperty' ,
264+ ' 2' : " ({ description: 'When user was created', type: Number })" ,
265+ index: 994,
266+ groups: [Object: null prototype] {
267+ identifier: ' ApiProperty' ,
268+ parameters: " ({ description: 'When user was created', type: Number })"
269+ }
270+ },
271+ {
272+ ' 0' : ' @Column({\n' +
273+ ' allowNull: false,\n' +
274+ ' defaultValue: User.CURRENT_TIMESTAMP,\n' +
275+ ' type: DataType.BIGINT,\n' +
276+ ' validate: { isUnixTimestamp: User.isUnixTimestamp }\n' +
277+ ' })' ,
278+ ' 1' : ' Column' ,
279+ ' 2' : ' ({\n' +
280+ ' allowNull: false,\n' +
281+ ' defaultValue: User.CURRENT_TIMESTAMP,\n' +
282+ ' type: DataType.BIGINT,\n' +
283+ ' validate: { isUnixTimestamp: User.isUnixTimestamp }\n' +
284+ ' })' ,
285+ index: 1068,
286+ groups: [Object: null prototype] {
287+ identifier: ' Column' ,
288+ parameters: ' ({\n' +
289+ ' allowNull: false,\n' +
290+ ' defaultValue: User.CURRENT_TIMESTAMP,\n' +
291+ ' type: DataType.BIGINT,\n' +
292+ ' validate: { isUnixTimestamp: User.isUnixTimestamp }\n' +
293+ ' })'
294+ }
295+ },
296+ {
297+ ' 0' : ' @ApiProperty({\n' +
298+ " description: 'Email address',\n" +
299+ ' maxLength: 254,\n' +
300+ ' minLength: 3,\n' +
301+ ' type: String\n' +
302+ ' })' ,
303+ ' 1' : ' ApiProperty' ,
304+ ' 2' : ' ({\n' +
305+ " description: 'Email address',\n" +
306+ ' maxLength: 254,\n' +
307+ ' minLength: 3,\n' +
308+ ' type: String\n' +
309+ ' })' ,
310+ index: 1296,
311+ groups: [Object: null prototype] {
312+ identifier: ' ApiProperty' ,
313+ parameters: ' ({\n' +
314+ " description: 'Email address',\n" +
315+ ' maxLength: 254,\n' +
316+ ' minLength: 3,\n' +
317+ ' type: String\n' +
318+ ' })'
319+ }
320+ },
321+ {
322+ ' 0' : ' @Column({\n' +
323+ ' allowNull: false,\n' +
324+ ' type: DataType.STRING(254),\n' +
325+ ' unique: true,\n' +
326+ ' validate: { isEmail: true, len: [3, 254] }\n' +
327+ ' })' ,
328+ ' 1' : ' Column' ,
329+ ' 2' : ' ({\n' +
330+ ' allowNull: false,\n' +
331+ ' type: DataType.STRING(254),\n' +
332+ ' unique: true,\n' +
333+ ' validate: { isEmail: true, len: [3, 254] }\n' +
334+ ' })' ,
335+ index: 1425,
336+ groups: [Object: null prototype] {
337+ identifier: ' Column' ,
338+ parameters: ' ({\n' +
339+ ' allowNull: false,\n' +
340+ ' type: DataType.STRING(254),\n' +
341+ ' unique: true,\n' +
342+ ' validate: { isEmail: true, len: [3, 254] }\n' +
343+ ' })'
344+ }
345+ },
346+ {
347+ ' 0' : " @ApiProperty({ description: 'Unique identifier', type: Number })" ,
348+ ' 1' : ' ApiProperty' ,
349+ ' 2' : " ({ description: 'Unique identifier', type: Number })" ,
350+ index: 1615,
351+ groups: [Object: null prototype] {
352+ identifier: ' ApiProperty' ,
353+ parameters: " ({ description: 'Unique identifier', type: Number })"
354+ }
355+ },
356+ {
357+ ' 0' : ' @Column({\n' +
358+ ' allowNull: false,\n' +
359+ ' autoIncrementIdentity: true,\n' +
360+ " defaultValue: Sequelize.fn('nextval', DatabaseSequence.USERS),\n" +
361+ ' primaryKey: true,\n' +
362+ " type: 'NUMERIC',\n" +
363+ ' unique: true,\n' +
364+ ' validate: { notNull: true }\n' +
365+ ' })' ,
366+ ' 1' : ' Column' ,
367+ ' 2' : ' ({\n' +
368+ ' allowNull: false,\n' +
369+ ' autoIncrementIdentity: true,\n' +
370+ " defaultValue: Sequelize.fn('nextval', DatabaseSequence.USERS),\n" +
371+ ' primaryKey: true,\n' +
372+ " type: 'NUMERIC',\n" +
373+ ' unique: true,\n' +
374+ ' validate: { notNull: true }\n' +
375+ ' })' ,
376+ index: 1685,
377+ groups: [Object: null prototype] {
378+ identifier: ' Column' ,
379+ parameters: ' ({\n' +
380+ ' allowNull: false,\n' +
381+ ' autoIncrementIdentity: true,\n' +
382+ " defaultValue: Sequelize.fn('nextval', DatabaseSequence.USERS),\n" +
383+ ' primaryKey: true,\n' +
384+ " type: 'NUMERIC',\n" +
385+ ' unique: true,\n' +
386+ ' validate: { notNull: true }\n' +
387+ ' })'
388+ }
389+ },
390+ {
391+ ' 0' : ' @ApiProperty({\n' +
392+ " description: 'Authentication provider',\n" +
393+ ' enum: OAuthProvider,\n' +
394+ " enumName: 'OAuthProvider',\n" +
395+ ' nullable: true\n' +
396+ ' })' ,
397+ ' 1' : ' ApiProperty' ,
398+ ' 2' : ' ({\n' +
399+ " description: 'Authentication provider',\n" +
400+ ' enum: OAuthProvider,\n' +
401+ " enumName: 'OAuthProvider',\n" +
402+ ' nullable: true\n' +
403+ ' })' ,
404+ index: 1974,
405+ groups: [Object: null prototype] {
406+ identifier: ' ApiProperty' ,
407+ parameters: ' ({\n' +
408+ " description: 'Authentication provider',\n" +
409+ ' enum: OAuthProvider,\n' +
410+ " enumName: 'OAuthProvider',\n" +
411+ ' nullable: true\n' +
412+ ' })'
413+ }
414+ },
415+ {
416+ ' 0' : ' @Column({\n' +
417+ ' allowNull: true,\n' +
418+ ' defaultValue: null,\n' +
419+ ' type: DataType.ENUM(...User.AUTH_PROVIDERS)\n' +
420+ ' })' ,
421+ ' 1' : ' Column' ,
422+ ' 2' : ' ({\n' +
423+ ' allowNull: true,\n' +
424+ ' defaultValue: null,\n' +
425+ ' type: DataType.ENUM(...User.AUTH_PROVIDERS)\n' +
426+ ' })' ,
427+ index: 2133,
428+ groups: [Object: null prototype] {
429+ identifier: ' Column' ,
430+ parameters: ' ({\n' +
431+ ' allowNull: true,\n' +
432+ ' defaultValue: null,\n' +
433+ ' type: DataType.ENUM(...User.AUTH_PROVIDERS)\n' +
434+ ' })'
435+ }
436+ },
437+ {
438+ ' 0' : ' @HasMany(() => Token)' ,
439+ ' 1' : ' HasMany' ,
440+ ' 2' : ' (() => Token)' ,
441+ index: 2300,
442+ groups: [Object: null prototype] {
443+ identifier: ' HasMany' ,
444+ parameters: ' (() => Token)'
445+ }
446+ }
447+ ]
448+ ```
65449
66450## API
67451
0 commit comments