reslib 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/README.md +298 -0
  2. package/build/auth/index.d.ts +2034 -0
  3. package/build/auth/index.js +5 -0
  4. package/build/auth/types.d.ts +465 -0
  5. package/build/auth/types.js +1 -0
  6. package/build/countries/countries.d.ts +1454 -0
  7. package/build/countries/countries.js +1 -0
  8. package/build/countries/index.d.ts +159 -0
  9. package/build/countries/index.js +5 -0
  10. package/build/countries/types.d.ts +65 -0
  11. package/build/countries/types.js +1 -0
  12. package/build/currency/currencies.d.ts +8 -0
  13. package/build/currency/currencies.js +1 -0
  14. package/build/currency/index.d.ts +51 -0
  15. package/build/currency/index.js +5 -0
  16. package/build/currency/session.d.ts +23 -0
  17. package/build/currency/session.js +5 -0
  18. package/build/currency/types.d.ts +1039 -0
  19. package/build/currency/types.js +1 -0
  20. package/build/currency/utils.d.ts +25 -0
  21. package/build/currency/utils.js +1 -0
  22. package/build/i18n/index.d.ts +640 -0
  23. package/build/i18n/index.js +5 -0
  24. package/build/inputFormatter/index.d.ts +396 -0
  25. package/build/inputFormatter/index.js +5 -0
  26. package/build/inputFormatter/types.d.ts +544 -0
  27. package/build/inputFormatter/types.js +1 -0
  28. package/build/logger/index.d.ts +235 -0
  29. package/build/logger/index.js +5 -0
  30. package/build/observable/index.d.ts +329 -0
  31. package/build/observable/index.js +1 -0
  32. package/build/platform/index.d.ts +32 -0
  33. package/build/platform/index.js +1 -0
  34. package/build/resources/ResourcePaginationHelper.d.ts +537 -0
  35. package/build/resources/ResourcePaginationHelper.js +2 -0
  36. package/build/resources/decorators/create.decorator.d.ts +20 -0
  37. package/build/resources/decorators/create.decorator.js +1 -0
  38. package/build/resources/decorators/index.d.ts +41 -0
  39. package/build/resources/decorators/index.js +1 -0
  40. package/build/resources/fields/index.d.ts +33 -0
  41. package/build/resources/fields/index.js +1 -0
  42. package/build/resources/filters.d.ts +62 -0
  43. package/build/resources/filters.js +1 -0
  44. package/build/resources/index.d.ts +854 -0
  45. package/build/resources/index.js +6 -0
  46. package/build/resources/types/filters.d.ts +508 -0
  47. package/build/resources/types/filters.js +1 -0
  48. package/build/resources/types/index.d.ts +4138 -0
  49. package/build/resources/types/index.js +1 -0
  50. package/build/session/index.d.ts +1474 -0
  51. package/build/session/index.js +1 -0
  52. package/build/translations/auth.en.d.ts +3 -0
  53. package/build/translations/auth.en.js +1 -0
  54. package/build/translations/countries.en.d.ts +6 -0
  55. package/build/translations/countries.en.js +1 -0
  56. package/build/translations/currencies.en.d.ts +5 -0
  57. package/build/translations/currencies.en.js +1 -0
  58. package/build/translations/date.en.d.ts +19 -0
  59. package/build/translations/date.en.js +1 -0
  60. package/build/translations/index.d.ts +1583 -0
  61. package/build/translations/index.js +5 -0
  62. package/build/translations/resources.en.d.ts +6 -0
  63. package/build/translations/resources.en.js +1 -0
  64. package/build/translations/validator.en.d.ts +104 -0
  65. package/build/translations/validator.en.js +5 -0
  66. package/build/types/date.d.ts +44 -0
  67. package/build/types/date.js +1 -0
  68. package/build/types/dictionary.d.ts +29 -0
  69. package/build/types/dictionary.js +1 -0
  70. package/build/types/i18n.d.ts +121 -0
  71. package/build/types/i18n.js +1 -0
  72. package/build/types/index.d.ts +145 -0
  73. package/build/types/index.js +1 -0
  74. package/build/utils/areEquals.d.ts +19 -0
  75. package/build/utils/areEquals.js +1 -0
  76. package/build/utils/date/dateHelper.d.ts +371 -0
  77. package/build/utils/date/dateHelper.js +5 -0
  78. package/build/utils/date/index.d.ts +212 -0
  79. package/build/utils/date/index.js +5 -0
  80. package/build/utils/date/isDateObj.d.ts +14 -0
  81. package/build/utils/date/isDateObj.js +1 -0
  82. package/build/utils/debounce.d.ts +52 -0
  83. package/build/utils/debounce.js +1 -0
  84. package/build/utils/defaultArray.d.ts +18 -0
  85. package/build/utils/defaultArray.js +1 -0
  86. package/build/utils/defaultBool.d.ts +14 -0
  87. package/build/utils/defaultBool.js +1 -0
  88. package/build/utils/defaultStr.d.ts +17 -0
  89. package/build/utils/defaultStr.js +1 -0
  90. package/build/utils/defaultVal.d.ts +18 -0
  91. package/build/utils/defaultVal.js +1 -0
  92. package/build/utils/dom/index.d.ts +65 -0
  93. package/build/utils/dom/index.js +1 -0
  94. package/build/utils/dom/isDOMElement.d.ts +11 -0
  95. package/build/utils/dom/isDOMElement.js +1 -0
  96. package/build/utils/file/index.d.ts +26 -0
  97. package/build/utils/file/index.js +1 -0
  98. package/build/utils/global.d.ts +53 -0
  99. package/build/utils/global.js +1 -0
  100. package/build/utils/image.d.ts +56 -0
  101. package/build/utils/image.js +1 -0
  102. package/build/utils/index.d.ts +39 -0
  103. package/build/utils/index.js +6 -0
  104. package/build/utils/interpolate.d.ts +105 -0
  105. package/build/utils/interpolate.js +1 -0
  106. package/build/utils/isEmail.d.ts +57 -0
  107. package/build/utils/isEmail.js +1 -0
  108. package/build/utils/isEmpty.d.ts +18 -0
  109. package/build/utils/isEmpty.js +1 -0
  110. package/build/utils/isNonNullString.d.ts +17 -0
  111. package/build/utils/isNonNullString.js +1 -0
  112. package/build/utils/isNullable.d.ts +7 -0
  113. package/build/utils/isNullable.js +1 -0
  114. package/build/utils/isNumber.d.ts +36 -0
  115. package/build/utils/isNumber.js +1 -0
  116. package/build/utils/isPrimitive.d.ts +16 -0
  117. package/build/utils/isPrimitive.js +1 -0
  118. package/build/utils/isPromise.d.ts +14 -0
  119. package/build/utils/isPromise.js +1 -0
  120. package/build/utils/isRegex.d.ts +15 -0
  121. package/build/utils/isRegex.js +1 -0
  122. package/build/utils/isTime.d.ts +18 -0
  123. package/build/utils/isTime.js +1 -0
  124. package/build/utils/json.d.ts +224 -0
  125. package/build/utils/json.js +1 -0
  126. package/build/utils/numbers.d.ts +148 -0
  127. package/build/utils/numbers.js +5 -0
  128. package/build/utils/object.d.ts +567 -0
  129. package/build/utils/object.js +1 -0
  130. package/build/utils/sort.d.ts +67 -0
  131. package/build/utils/sort.js +1 -0
  132. package/build/utils/string.d.ts +165 -0
  133. package/build/utils/string.js +1 -0
  134. package/build/utils/stringify.d.ts +23 -0
  135. package/build/utils/stringify.js +1 -0
  136. package/build/utils/uniqid.d.ts +18 -0
  137. package/build/utils/uniqid.js +1 -0
  138. package/build/utils/uri/index.d.ts +333 -0
  139. package/build/utils/uri/index.js +2 -0
  140. package/build/validator/index.d.ts +4 -0
  141. package/build/validator/index.js +6 -0
  142. package/build/validator/rules/array.d.ts +848 -0
  143. package/build/validator/rules/array.js +5 -0
  144. package/build/validator/rules/boolean.d.ts +87 -0
  145. package/build/validator/rules/boolean.js +5 -0
  146. package/build/validator/rules/date.d.ts +551 -0
  147. package/build/validator/rules/date.js +5 -0
  148. package/build/validator/rules/default.d.ts +367 -0
  149. package/build/validator/rules/default.js +5 -0
  150. package/build/validator/rules/enum.d.ts +155 -0
  151. package/build/validator/rules/enum.js +5 -0
  152. package/build/validator/rules/file.d.ts +356 -0
  153. package/build/validator/rules/file.js +5 -0
  154. package/build/validator/rules/format.d.ts +2825 -0
  155. package/build/validator/rules/format.js +6 -0
  156. package/build/validator/rules/index.d.ts +16 -0
  157. package/build/validator/rules/index.js +6 -0
  158. package/build/validator/rules/multiRules.d.ts +475 -0
  159. package/build/validator/rules/multiRules.js +5 -0
  160. package/build/validator/rules/numeric.d.ts +1135 -0
  161. package/build/validator/rules/numeric.js +5 -0
  162. package/build/validator/rules/string.d.ts +504 -0
  163. package/build/validator/rules/string.js +5 -0
  164. package/build/validator/rules/target.d.ts +137 -0
  165. package/build/validator/rules/target.js +5 -0
  166. package/build/validator/rules/utils.d.ts +1 -0
  167. package/build/validator/rules/utils.js +1 -0
  168. package/build/validator/rulesMarkers.d.ts +11 -0
  169. package/build/validator/rulesMarkers.js +1 -0
  170. package/build/validator/types.d.ts +2906 -0
  171. package/build/validator/types.js +1 -0
  172. package/build/validator/validator.d.ts +3692 -0
  173. package/build/validator/validator.js +5 -0
  174. package/lib/cjs/auth.js +1 -0
  175. package/lib/cjs/countries.js +1 -0
  176. package/lib/cjs/currency.js +1 -0
  177. package/lib/cjs/i18n.js +1 -0
  178. package/lib/cjs/inputFormatter.js +1 -0
  179. package/lib/cjs/logger.js +1 -0
  180. package/lib/cjs/observable.js +1 -0
  181. package/lib/cjs/platform.js +1 -0
  182. package/lib/cjs/resources.js +1 -0
  183. package/lib/cjs/session.js +1 -0
  184. package/lib/cjs/types.js +1 -0
  185. package/lib/cjs/utils.js +1 -0
  186. package/lib/cjs/validator.js +1 -0
  187. package/lib/esm/auth.mjs +1 -0
  188. package/lib/esm/countries.mjs +1 -0
  189. package/lib/esm/currency.mjs +1 -0
  190. package/lib/esm/i18n.mjs +1 -0
  191. package/lib/esm/inputFormatter.mjs +1 -0
  192. package/lib/esm/logger.mjs +1 -0
  193. package/lib/esm/observable.mjs +1 -0
  194. package/lib/esm/platform.mjs +1 -0
  195. package/lib/esm/resources.mjs +1 -0
  196. package/lib/esm/session.mjs +1 -0
  197. package/lib/esm/types.mjs +1 -0
  198. package/lib/esm/utils.mjs +1 -0
  199. package/lib/esm/validator.mjs +1 -0
  200. package/package.json +244 -0
@@ -0,0 +1,537 @@
1
+ import { Dictionary } from '../types';
2
+ import { NestedPaths, ResourcePaginationMeta, ResourceQueryOptions, ResourceQueryOrderBy } from './types';
3
+ export declare class ResourcePaginationHelper {
4
+ /**
5
+ * Normalizes pagination parameters into a consistent format, calculating missing values and ensuring valid pagination state.
6
+ *
7
+ * This method takes pagination options and normalizes them by calculating the missing pagination parameters
8
+ * (`page`, `skip`, `limit`) based on the provided values. It handles the relationship between page-based
9
+ * and offset-based pagination, ensuring that all three parameters are consistent and valid.
10
+ *
11
+ * **Normalization Logic:**
12
+ * - If `limit` is not a valid number, returns an empty object (no pagination)
13
+ * - If `skip` is provided, calculates the corresponding `page` number
14
+ * - If `page` is provided, calculates the corresponding `skip` offset
15
+ * - If neither `skip` nor `page` are provided, defaults to page 1 with skip 0
16
+ * - Ensures all returned values are valid numbers
17
+ *
18
+ * **Parameter Relationships:**
19
+ * - `page`: 1-based page number (first page = 1)
20
+ * - `skip`: 0-based offset (number of records to skip)
21
+ * - `limit`: Maximum records per page
22
+ * - Formula: `skip = (page - 1) * limit`
23
+ *
24
+ * @template DataType - The resource data type (used for type consistency with ResourceQueryOptions)
25
+ * @param {ResourceQueryOptions<DataType>} [options] - Pagination options containing page, skip, and/or limit
26
+ * @param {number} [options.page] - The page number (1-based)
27
+ * @param {number} [options.skip] - The number of records to skip (0-based offset)
28
+ * @param {number} [options.limit] - The maximum number of records per page
29
+ * @returns {{page?: number, skip?: number, limit?: number}} Normalized pagination parameters:
30
+ * - `page`: Calculated or provided page number
31
+ * - `skip`: Calculated or provided skip offset
32
+ * - `limit`: The limit value (unchanged if valid, omitted if invalid)
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * // Page-based pagination - calculates skip automatically
37
+ * const result = ResourcePaginationHelper.normalizePagination({
38
+ * page: 3,
39
+ * limit: 10
40
+ * });
41
+ * // Result: { page: 3, skip: 20, limit: 10 }
42
+ * // (skip = (3-1) * 10 = 20)
43
+ * ```
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * // Offset-based pagination - calculates page automatically
48
+ * const result = ResourcePaginationHelper.normalizePagination({
49
+ * skip: 50,
50
+ * limit: 25
51
+ * });
52
+ * // Result: { page: 3, skip: 50, limit: 25 }
53
+ * // (page = floor(50/25) + 1 = 3)
54
+ * ```
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * // Default pagination - no parameters provided
59
+ * const result = ResourcePaginationHelper.normalizePagination({
60
+ * limit: 20
61
+ * });
62
+ * // Result: { page: 1, skip: 0, limit: 20 }
63
+ * ```
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * // Invalid limit - returns empty object (no pagination)
68
+ * const result = ResourcePaginationHelper.normalizePagination({
69
+ * page: 2,
70
+ * limit: "invalid"
71
+ * });
72
+ * // Result: {}
73
+ * ```
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * // Zero or negative values - defaults to first page
78
+ * const result = ResourcePaginationHelper.normalizePagination({
79
+ * page: 0,
80
+ * limit: 15
81
+ * });
82
+ * // Result: { page: 1, skip: 0, limit: 15 }
83
+ * ```
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * // Large skip values
88
+ * const result = ResourcePaginationHelper.normalizePagination({
89
+ * skip: 1000,
90
+ * limit: 50
91
+ * });
92
+ * // Result: { page: 21, skip: 1000, limit: 50 }
93
+ * // (page = floor(1000/50) + 1 = 21)
94
+ * ```
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * // Fractional skip values (floor operation)
99
+ * const result = ResourcePaginationHelper.normalizePagination({
100
+ * skip: 37,
101
+ * limit: 10
102
+ * });
103
+ * // Result: { page: 4, skip: 37, limit: 10 }
104
+ * // (page = floor(37/10) + 1 = 4)
105
+ * ```
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * // Mixed parameters - skip takes precedence over page
110
+ * const result = ResourcePaginationHelper.normalizePagination({
111
+ * page: 2,
112
+ * skip: 30,
113
+ * limit: 15
114
+ * });
115
+ * // Result: { page: 3, skip: 30, limit: 15 }
116
+ * // (skip provided, so page is recalculated from skip)
117
+ * ```
118
+ *
119
+ * @example
120
+ * ```typescript
121
+ * // Database cursor scenario
122
+ * const result = ResourcePaginationHelper.normalizePagination({
123
+ * skip: 500,
124
+ * limit: 100
125
+ * });
126
+ * // Result: { page: 6, skip: 500, limit: 100 }
127
+ * // Useful for database queries with OFFSET
128
+ * ```
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * // API pagination with user input
133
+ * const userOptions = { page: 5, limit: 20 };
134
+ * const result = ResourcePaginationHelper.normalizePagination(userOptions);
135
+ * // Result: { page: 5, skip: 80, limit: 20 }
136
+ * // Ready for database query: LIMIT 20 OFFSET 80
137
+ * ```
138
+ *
139
+ * @remarks
140
+ * - Page numbers are 1-based (first page = 1, not 0)
141
+ * - Skip values are 0-based (skip 0 = first record)
142
+ * - Invalid limit values disable pagination entirely
143
+ * - When both page and skip are provided, skip takes precedence for page calculation
144
+ * - Negative or zero page values default to page 1
145
+ * - Fractional skip values are floored when calculating page numbers
146
+ */
147
+ static normalizePagination<DataType = unknown>(options?: ResourceQueryOptions<DataType>): {
148
+ page?: undefined;
149
+ skip?: undefined;
150
+ limit?: undefined;
151
+ } | {
152
+ page: number;
153
+ skip: number;
154
+ limit: number;
155
+ };
156
+ /**
157
+ * Normalizes orderBy parameters into a structured object format.
158
+ *
159
+ * This method takes various input formats for sorting criteria and converts them into a consistent
160
+ * object where keys are valid nested property paths and values are sort directions ("asc" or "desc").
161
+ * It handles single strings, arrays of strings, and undefined inputs gracefully.
162
+ *
163
+ * @template T - The resource type to validate paths against
164
+ * @param orderBy - The orderBy specification in various formats:
165
+ * - `string`: Single field like "name" (ascending) or "-name" (descending)
166
+ * - `string[]`: Multiple fields like ["name", "-age", "createdAt"]
167
+ * - `undefined`: No sorting specified
168
+ * @returns A partial record mapping valid nested paths to sort directions
169
+ *
170
+ * @example
171
+ * ```typescript
172
+ * interface User {
173
+ * id: number;
174
+ * name: string;
175
+ * profile: { age: number; address: { city: string } };
176
+ * }
177
+ *
178
+ * // Single ascending field
179
+ * normalizeOrderBy<User>("name")
180
+ * // Returns: { "name": "asc" }
181
+ *
182
+ * // Single descending field
183
+ * normalizeOrderBy<User>("-profile.age")
184
+ * // Returns: { "profile.age": "desc" }
185
+ *
186
+ * // Multiple fields
187
+ * normalizeOrderBy<User>(["name", "-profile.age", "profile.address.city"])
188
+ * // Returns: { "name": "asc", "profile.age": "desc", "profile.address.city": "asc" }
189
+ *
190
+ * // Invalid input (filtered out)
191
+ * normalizeOrderBy<User>([null, "", "name", undefined])
192
+ * // Returns: { "name": "asc" }
193
+ * ```
194
+ *
195
+ * @remarks
196
+ * - Fields starting with "-" are treated as descending order
197
+ * - Invalid or empty strings are silently filtered out
198
+ * - Duplicate fields will log a warning and use the last occurrence
199
+ * - The method performs type assertion to `NestedPaths<T>` - ensure input paths are valid at call site
200
+ */
201
+ static normalizeOrderBy<T = unknown>(orderBy?: ResourceQueryOrderBy<T>): Partial<Record<NestedPaths<T>, SortOrder>>;
202
+ /***
203
+ * Determines if result can be paginated based on the provided query options.
204
+ * It checks if the query options have a `limit` property of type number.
205
+ * @template DataType The type of resource data.
206
+ * @param {ResourceQueryOptions} queryOptions - The query options.
207
+ * @returns {boolean} Whether the result can be paginated.
208
+ *
209
+ * @example
210
+ * canPaginateResult({ limit: undefined }); //false
211
+ * canPaginateResult({ limit: 10, skip: 20 }); // true
212
+ * canPaginateResult({ page: 3, limit: 10 }); // true
213
+ * canPaginateResult({ page: 3, skip: 20 }); // true
214
+ */
215
+ static canPaginateResult<DataType = unknown>(queryOptions: ResourceQueryOptions<DataType>): boolean;
216
+ static getPaginationMetaData<DataType = unknown>(count: number, queryOptions?: ResourceQueryOptions<DataType>): ResourcePaginationMeta;
217
+ /**
218
+ * Paginates an array of data based on the provided query options and total count.
219
+ *
220
+ * This method applies pagination logic to slice the data array according to the specified
221
+ * page size and current page, while also generating comprehensive pagination metadata.
222
+ * It's designed to work seamlessly with database query results and API responses.
223
+ *
224
+ * **Pagination Logic:**
225
+ * - Calculates the correct slice of data based on `page` and `limit` parameters
226
+ * - Generates metadata including total pages, current page, navigation flags, etc.
227
+ * - Handles edge cases like invalid page numbers or missing pagination parameters
228
+ *
229
+ * **Data Slicing:**
230
+ * - Uses zero-based indexing for array slicing
231
+ * - Ensures start/end indices are within array bounds
232
+ * - Returns empty array if pagination parameters are invalid
233
+ *
234
+ * @template DataType - The type of individual data items in the array
235
+ * @param {DataType[]} data - The complete array of data to be paginated
236
+ * @param {number} count - The total number of records available (may be different from data.length for database queries)
237
+ * @param {ResourceQueryOptions<DataType>} [options] - Pagination and query options
238
+ * @returns {{
239
+ * data: DataType[],
240
+ * total: number,
241
+ * meta: ResourcePaginationMeta
242
+ * }} An object containing:
243
+ * - `data`: The paginated slice of the original data array
244
+ * - `total`: The total count of records (unchanged from input)
245
+ * - `meta`: Comprehensive pagination metadata
246
+ *
247
+ * @example
248
+ * ```typescript
249
+ * // Basic pagination - page 1 with 10 items per page
250
+ * const users = [{id: 1}, {id: 2}, ..., {id: 25}]; // 25 total users
251
+ * const result = ResourcePaginationHelper.paginate(users, 25, {
252
+ * page: 1,
253
+ * limit: 10
254
+ * });
255
+ * // Result:
256
+ * // {
257
+ * // data: [{id: 1}, {id: 2}, ..., {id: 10}], // First 10 users
258
+ * // total: 25,
259
+ * // meta: {
260
+ * // total: 25,
261
+ * // currentPage: 1,
262
+ * // pageSize: 10,
263
+ * // totalPages: 3,
264
+ * // hasNextPage: true,
265
+ * // hasPreviousPage: false,
266
+ * // nextPage: 2,
267
+ * // previousPage: undefined,
268
+ * // lastPage: 3
269
+ * // }
270
+ * // }
271
+ * ```
272
+ *
273
+ * @example
274
+ * ```typescript
275
+ * // Middle page pagination
276
+ * const result = ResourcePaginationHelper.paginate(users, 25, {
277
+ * page: 2,
278
+ * limit: 10
279
+ * });
280
+ * // Result: data contains items 11-20, meta shows navigation to pages 1 and 3
281
+ * ```
282
+ *
283
+ * @example
284
+ * ```typescript
285
+ * // Last page with fewer items
286
+ * const result = ResourcePaginationHelper.paginate(users, 25, {
287
+ * page: 3,
288
+ * limit: 10
289
+ * });
290
+ * // Result: data contains items 21-25 (5 items), meta shows no next page
291
+ * ```
292
+ *
293
+ * @example
294
+ * ```typescript
295
+ * // Using skip instead of page
296
+ * const result = ResourcePaginationHelper.paginate(users, 25, {
297
+ * skip: 15,
298
+ * limit: 5
299
+ * });
300
+ * // Result: data contains items 16-20, meta shows currentPage: 4
301
+ * ```
302
+ *
303
+ * @example
304
+ * ```typescript
305
+ * // No pagination options - returns all data
306
+ * const result = ResourcePaginationHelper.paginate(users, 25);
307
+ * // Result: data contains all 25 users, meta is minimal (only total)
308
+ * ```
309
+ *
310
+ * @example
311
+ * ```typescript
312
+ * // Invalid page number - clamps to valid range
313
+ * const result = ResourcePaginationHelper.paginate(users, 25, {
314
+ * page: 999,
315
+ * limit: 10
316
+ * });
317
+ * // Result: data is empty array, meta shows page: 999 but no valid data slice
318
+ * ```
319
+ *
320
+ * @example
321
+ * ```typescript
322
+ * // Database scenario - data array smaller than total count
323
+ * const dbResult = [{id: 101}, {id: 102}, {id: 103}]; // Only 3 records from DB
324
+ * const result = ResourcePaginationHelper.paginate(dbResult, 150, {
325
+ * page: 34,
326
+ * limit: 3
327
+ * });
328
+ * // Result: data contains the 3 DB records, total: 150, meta shows page 34 of ~50
329
+ * ```
330
+ *
331
+ * @example
332
+ * ```typescript
333
+ * // Empty data array
334
+ * const result = ResourcePaginationHelper.paginate([], 0, {
335
+ * page: 1,
336
+ * limit: 10
337
+ * });
338
+ * // Result: data is empty array, total: 0, meta shows single empty page
339
+ * ```
340
+ *
341
+ * @example
342
+ * ```typescript
343
+ * // Large dataset pagination
344
+ * const largeDataset = Array.from({length: 10000}, (_, i) => ({id: i + 1}));
345
+ * const result = ResourcePaginationHelper.paginate(largeDataset, 10000, {
346
+ * page: 500,
347
+ * limit: 20
348
+ * });
349
+ * // Result: data contains items 9981-10000, meta shows page 500 of 500
350
+ * ```
351
+ */
352
+ static paginate<DataType = unknown>(data: DataType[], count: number, options?: ResourceQueryOptions<DataType>): {
353
+ data: DataType[];
354
+ total: number;
355
+ meta: ResourcePaginationMeta;
356
+ };
357
+ /**
358
+ * Parses query options from HTTP request data, extracting and normalizing parameters from multiple sources.
359
+ *
360
+ * This method consolidates query parameters from URL query strings, request headers, route parameters,
361
+ * and custom filters into a standardized `ResourceQueryOptions` object. It's designed for REST API
362
+ * endpoints that need to handle complex query parameters for filtering, sorting, pagination, and more.
363
+ *
364
+ * **Parameter Sources (in precedence order):**
365
+ * 1. URL query parameters (`req.url`)
366
+ * 2. Route parameters (`req.params`)
367
+ * 3. X-Filters header (`req.headers['x-filters']`)
368
+ * 4. Custom filters (`req.filters`)
369
+ *
370
+ * **Supported Parameters:**
371
+ * - **Pagination**: `limit`, `skip`, `page`
372
+ * - **Sorting**: `orderBy` (string, array, or object)
373
+ * - **Filtering**: `where` (object, array, or string conditions)
374
+ * - **Relations**: `include`, `relations` (related data to load)
375
+ * - **Caching**: `cache`, `cacheTTL`
376
+ * - **Soft Deletes**: `includeDeleted`
377
+ * - **Distinct**: `distinct` (unique results)
378
+ *
379
+ * @template T - The resource data type for type-safe query options
380
+ * @param {Object} req - The request object containing query data from multiple sources
381
+ * @param {string} req.url - The request URL containing query parameters
382
+ * @param {Dictionary} req.headers - Request headers (may include 'x-filters')
383
+ * @param {Dictionary} [req.params] - Route parameters from URL path
384
+ * @param {Dictionary} [req.filters] - Custom filter object
385
+ * @returns {ResourceQueryOptions<T> & {queryParams: Dictionary}} Normalized query options with:
386
+ * - All standard `ResourceQueryOptions<T>` properties
387
+ * - `queryParams`: Raw parsed query parameters for reference
388
+ *
389
+ * @example
390
+ * ```typescript
391
+ * // Basic pagination from URL query
392
+ * const req = {
393
+ * url: '/api/users?limit=10&page=2',
394
+ * headers: {}
395
+ * };
396
+ * const options = ResourcePaginationHelper.parseQueryOptions(req);
397
+ * // Result: { limit: 10, page: 2, skip: 10, queryParams: { limit: '10', page: '2' } }
398
+ * ```
399
+ *
400
+ * @example
401
+ * ```typescript
402
+ * // Complex query with multiple sources
403
+ * const req = {
404
+ * url: '/api/users?limit=20&orderBy=name',
405
+ * headers: {
406
+ * 'x-filters': {
407
+ * where: { active: true },
408
+ * include: ['profile', 'roles']
409
+ * }
410
+ * },
411
+ * params: { userId: '123' },
412
+ * filters: { cache: true }
413
+ * };
414
+ * const options = ResourcePaginationHelper.parseQueryOptions(req);
415
+ * // Result includes all merged parameters with proper precedence
416
+ * ```
417
+ *
418
+ * @example
419
+ * ```typescript
420
+ * // Sorting with multiple fields
421
+ * const req = {
422
+ * url: '/api/users?orderBy[]=name&orderBy[]=-createdAt',
423
+ * headers: {}
424
+ * };
425
+ * const options = ResourcePaginationHelper.parseQueryOptions(req);
426
+ * // Result: { orderBy: { name: 'asc', createdAt: 'desc' }, ... }
427
+ * ```
428
+ *
429
+ * @example
430
+ * ```typescript
431
+ * // Filtering with complex where conditions
432
+ * const req = {
433
+ * url: '/api/users',
434
+ * headers: {
435
+ * 'x-filters': {
436
+ * where: {
437
+ * age: { $gte: 18 },
438
+ * status: 'active',
439
+ * $or: [{ role: 'admin' }, { role: 'moderator' }]
440
+ * }
441
+ * }
442
+ * }
443
+ * };
444
+ * const options = ResourcePaginationHelper.parseQueryOptions(req);
445
+ * // Result includes complex where conditions for database queries
446
+ * ```
447
+ *
448
+ * @example
449
+ * ```typescript
450
+ * // Including related data
451
+ * const req = {
452
+ * url: '/api/posts?include[]=author&include[]=comments',
453
+ * headers: {
454
+ * 'x-filters': {
455
+ * relations: ['tags', 'categories']
456
+ * }
457
+ * }
458
+ * };
459
+ * const options = ResourcePaginationHelper.parseQueryOptions(req);
460
+ * // Result: { include: ['author', 'comments'], relations: ['tags', 'categories'], ... }
461
+ * ```
462
+ *
463
+ * @example
464
+ * ```typescript
465
+ * // Caching configuration
466
+ * const req = {
467
+ * url: '/api/users?cache=1&cacheTTL=300',
468
+ * headers: {}
469
+ * };
470
+ * const options = ResourcePaginationHelper.parseQueryOptions(req);
471
+ * // Result: { cache: true, cacheTTL: 300, ... }
472
+ * ```
473
+ *
474
+ * @example
475
+ * ```typescript
476
+ * // Distinct results and soft deletes
477
+ * const req = {
478
+ * url: '/api/users?distinct=1&includeDeleted=true',
479
+ * headers: {}
480
+ * };
481
+ * const options = ResourcePaginationHelper.parseQueryOptions(req);
482
+ * // Result: { distinct: true, includeDeleted: true, ... }
483
+ * ```
484
+ *
485
+ * @example
486
+ * ```typescript
487
+ * // Express.js style request object
488
+ * const expressReq = {
489
+ * url: '/api/users?limit=5&page=1&orderBy=name',
490
+ * headers: {
491
+ * 'x-filters': JSON.stringify({ where: { active: true } })
492
+ * },
493
+ * params: { tenantId: 'abc123' },
494
+ * query: { search: 'john' } // Additional query params
495
+ * };
496
+ * const options = ResourcePaginationHelper.parseQueryOptions(expressReq);
497
+ * // Handles all Express.js request formats automatically
498
+ * ```
499
+ *
500
+ * @example
501
+ * ```typescript
502
+ * // Minimal request - only URL parameters
503
+ * const req = {
504
+ * url: '/api/users',
505
+ * headers: {}
506
+ * };
507
+ * const options = ResourcePaginationHelper.parseQueryOptions(req);
508
+ * // Result: { queryParams: {} } - minimal options, no pagination/sorting
509
+ * ```
510
+ *
511
+ * @example
512
+ * ```typescript
513
+ * // Mixed data types and type coercion
514
+ * const req = {
515
+ * url: '/api/users?limit=10&page=2&cache=true&includeDeleted=0',
516
+ * headers: {
517
+ * 'x-filters': {
518
+ * distinct: '1', // String '1' becomes boolean true
519
+ * cacheTTL: '600' // String '600' becomes number 600
520
+ * }
521
+ * }
522
+ * };
523
+ * const options = ResourcePaginationHelper.parseQueryOptions(req);
524
+ * // Result: proper type coercion for all parameters
525
+ * ```
526
+ */
527
+ static parseQueryOptions<T = unknown>(req: {
528
+ url: string;
529
+ headers: Dictionary;
530
+ params?: Dictionary;
531
+ filters?: Dictionary;
532
+ }): ResourceQueryOptions<T> & {
533
+ queryParams: Dictionary;
534
+ };
535
+ }
536
+ type SortOrder = 'asc' | 'desc';
537
+ export {};
@@ -0,0 +1,2 @@
1
+ 'use strict';var _=require('qs');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var ___default=/*#__PURE__*/_interopDefault(_);var Q=Object.defineProperty,W=Object.defineProperties;var K=Object.getOwnPropertyDescriptors;var M=Object.getOwnPropertySymbols;var v=Object.prototype.hasOwnProperty,F=Object.prototype.propertyIsEnumerable;var U=(t,e,n)=>e in t?Q(t,e,{enumerable:true,configurable:true,writable:true,value:n}):t[e]=n,A=(t,e)=>{for(var n in e||(e={}))v.call(e,n)&&U(t,n,e[n]);if(M)for(var n of M(e))F.call(e,n)&&U(t,n,e[n]);return t},k=(t,e)=>W(t,K(e));function w(...t){if(t.length===1)return Array.isArray(t[0])?t[0]:[];let e=null;for(var n in t){let r=t[n];if(Array.isArray(r)){if(r.length)return r;e||(e=r);}}return e||[]}function u(t){return !!(t&&typeof t=="string")}function O(t){return typeof t=="number"&&!isNaN(t)&&isFinite(t)}function R(t){return !t||typeof t!="object"?false:t instanceof Date?true:typeof t.getTime!="function"?false:!(Object.prototype.toString.call(t)!=="[object Date]"||isNaN(t.getTime()))}function N(t){return typeof window!="object"||!window||typeof document=="undefined"||typeof HTMLElement=="undefined"||!HTMLElement?false:t===document?true:"HTMLElement"in window?!!t&&t instanceof HTMLElement:!!t&&typeof t=="object"&&t.nodeType===1&&!!t.nodeName}function D(t){return t==null||typeof t=="string"||typeof t=="number"||typeof t=="boolean"}function j(t){if(t instanceof RegExp)return true;if(!t||typeof t!="object"||!Object.prototype.toString.call(t).includes("RegExp"))return false;try{return new RegExp(t),!0}catch(e){return false}}function y(t){if(t===null||typeof t!="object"||N(t)||R(t)||j(t)||D(t))return false;let e=Object.getPrototypeOf(t);if(e===null)return true;let n=e.constructor;if(typeof n!="function")return false;if(n===Object)return true;let r=n.prototype;return typeof r!="object"?false:r===Object.prototype?true:typeof e.hasOwnProperty=="function"&&Object.prototype.hasOwnProperty.call(e,"isPrototypeOf")&&typeof e.isPrototypeOf=="function"}function C(t){if(Array.isArray(t)){let r=[];for(var e=0;e<t.length;e++)r[e]=C(t[e]);return r}else if(y(t)&&t){let r={};for(var n in t)t.hasOwnProperty(n)&&(r[n]=C(t[n]));return r}else return t}Object.getSize=function(t,e=false){if(!t||typeof t!="object")return 0;if(Array.isArray(t))return t.length;typeof e!="boolean"&&(e=false);let n=0;for(let r in t)if(Object.prototype.hasOwnProperty.call(t,r)&&(n++,e===true))return n;return n};function x(t,...e){let n=Array.isArray(t),r=y(t);(t==null||!n&&!r)&&(t={});for(let i=0;i<e.length;i++){let s=e[i];if(s==null)continue;let o=y(s),c=Array.isArray(s);if(!(!o&&!c)){if(n){c&&L(t,s);continue}else if(c)continue;for(let a in s){let f=s[a];if(f==null)continue;if(f===s){t[a]=t;continue}let p=t[a],m=Array.isArray(p),h=Array.isArray(f);if(m){h?L(t[a],f):t[a]=f;continue}else if(!y(p)){t[a]=f;continue}if(h||!y(f)){t[a]=f;continue}t[a]=x({},p,f);}}}return t}var L=(t,e)=>{let n=e.length,r=0;for(let i=0;i<t.length;i++){let s=t[i],o=e[i];if(i<n){let c=Array.isArray(s),a=Array.isArray(o),f=y(s),p=y(o);c&&a||f&&p?(t[r]=x(c?[]:{},s,o),r++):o!=null?(t[r]=o,r++):s!=null&&(t[r]=s,r++);}}for(let i=t.length;i<n;i++)e[i]!==void 0&&e[i]!==null&&t.push(e[i]);return t};function Z(t,e){return P(t,"",{},e)}function P(t,e="",n={},r){if(n=y(n)?n:{},D(t)||R(t)||j(t)||Array.isArray(t)&&(r!=null&&r.skipArrays))return e&&(n[e]=t),n;if(typeof t=="function"||typeof t=="object"&&!y(t)&&!H(t))return n;if(t instanceof Map||t instanceof WeakMap)return Array.from(t.entries()).forEach(([i,s])=>{let o=e?`${e}[${String(i)}]`:String(i);P(s,o,n,r);}),n;if(Array.isArray(t)||t instanceof Set||t instanceof WeakSet)return (Array.isArray(t)?t:Array.from(t)).forEach((s,o)=>{let c=e?`${e}[${o}]`:String(o);P(s,c,n,r);}),n;if(y(t))for(let i in t){if(!Object.prototype.hasOwnProperty.call(t,i))continue;let s=t[i],o=e?e.endsWith("]")?`${e}.${i}`:`${e}.${i}`:i;P(s,o,n,r);}return n}function H(t){return Array.isArray(t)||t instanceof Set||t instanceof Map||t instanceof WeakMap||t instanceof WeakSet}function V(t){return Object.entries(t)}Object.typedEntries=V;Object.flatten=Z;Object.clone=C;var S=function(t,e=""){if(!t||typeof t!="string")return "";if(!e||typeof e!="string")return t.trim();let n=t.length;for(;t.startsWith(e)&&n>=0;)t=t.slice(e.length),--n;return t.toString()},$=function(t,e=""){if(!t||typeof t!="string")return "";if(!e||typeof e!="string")return t.trim();let n=t.length;for(;t.endsWith(e)&&n>=0;)t=t.slice(0,-e.length),--n;return t.toString()},I=(t,e=true)=>typeof t!="string"?false:e!==false?/^\d*\.?\d+$/.test(t):/^\d+$/.test(t);String.prototype.ltrim=function(t){return S(this.toString(),t)};String.prototype.rtrim=function(t){return $(this.toString(),t)};String.prototype.isNumber=function(t=true){return I(this.toString(),t)};String.prototype.replaceAll=function(t,e){return !u(t)||!u(e)?this.toString():this.toString().split(t).join(e)};var G=t=>u(t)?(t=t.trim(),t.replace(/(.)([A-Z][a-z]+)/,"$1_$2").replace(/([a-z0-9])([A-Z])/,"$1_$2").toUpperCase()):"";String.prototype.toSnakeCase=function(){return G(this.toString())};var J=t=>u(t)?(t=t.trim(),t.charAt(0)+t.replace(/(_\w)/g,e=>e[1].toUpperCase()).substring(1)):"";String.prototype.toCamelCase=function(){return J(this.toString())};var X=function(t){return !t||typeof t!="string"?"":(t=t.trim(),t.charAt(0).toUpperCase()+t.slice(1))};String.prototype.upperFirst=function(){return X(this.toString())};var Y=function(t){return !t||typeof t!="string"?"":(t=t.trim(),t.charAt(0).toLowerCase()+t.slice(1))};String.prototype.lowerFirst=function(){return Y(this.toString())};var q=(t,e=true)=>{if(typeof t!="string")return "";let n=tt(t);return t=typeof n.search=="string"?n.search:"",e&&t?"?"+S(t,"?"):(t=$(S(t.trim(),"?"),"?"),t)},E=function(t,e={}){return typeof t!="string"?{}:___default.default.parse(q(t,false),A({allowSparse:true,decoder:n=>decodeURIComponent(n.replace(/\+/g," "))},Object.assign({},e)))};var tt=t=>{if(typeof t!="string")return {};if(typeof URL!="undefined"&&URL&&et(t))try{return new URL(t)}catch(r){}t=nt(t)?decodeURIComponent(t):t;var e=t.match(/^(([^:\\/?#]+:)?(?:\/\/((?:([^\\/?#:]*):([^\\/?#:]*)@)?([^\\/?#:]*)(?::([^\\/?#:]*))?)))?([^?#]*)(\?[^#]*)?(#.*)?$/);let n=e?{hash:e[10]||"",host:e[3]||"",hostname:e[6]||"",href:e[0]||"",origin:e[1]||"",pathname:e[8]||(e[1]?"/":""),port:e[7]||"",protocol:e[2]||"",search:e[9]||"",username:e[4]||"",password:e[5]||""}:{};return n.protocol&&n.protocol.length==2&&(n.protocol="file:///"+n.protocol.toUpperCase(),n.origin=n.protocol+"//"+n.host),n.protocol&&(n.href=n.origin+n.pathname+n.search+n.hash),n};function et(t,e={}){let{requireHost:n=true,allowedProtocols:r}=Object.assign({},e);if(!u(t)||!u(t.trim()))return false;let i=t;if(typeof URL!="undefined"&&URL)try{let s=new URL(i);if(!s.protocol||s.protocol===":")return !1;let o=s.protocol.slice(0,-1);if(r&&r.length>0&&!r.includes(o))return !1;if(n)if(["http","https","ftp","ftps","ws","wss"].includes(o)){if(!u(s.hostname)||!s.hostname.trim()||!u(s.host)||!s.host.trim())return !1;let a=`${o}://`;if(!i.startsWith(a)||i.slice(a.length).startsWith("/"))return !1;let p=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/,m=s.hostname.match(p);if(m&&!m.slice(1,5).map(Number).every(l=>l>=0&&l<=255))return !1}else return !1;return !0}catch(s){return false}if(n){let s=i.indexOf("://");if(s===-1)return false;let o=i.slice(0,s);if(!o||r&&r.length>0&&!r.includes(o))return false;let c=i.slice(s+3);if(c==="")return false;let a=c.indexOf("@"),f=a>=0?c.slice(a+1):c;if(f===""||f.startsWith("/"))return false;let p=f.indexOf("/"),m=f.indexOf("?"),h=f.indexOf("#"),T=Math.min(p>=0?p:f.length,m>=0?m:f.length,h>=0?h:f.length),l=f.slice(0,T);if(!l)return false;let d=l;if(l.startsWith("[")){let g=l.indexOf("]");if(g===-1)return false;d=l.slice(0,g+1);let b=l.slice(g+1);if(b&&!b.startsWith(":"))return false}else {let g=l.indexOf(":");g>=0&&(d=l.slice(0,g));}if(!d)return false;if(d==="localhost")return true;if(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(d))return !d.split(".").map(Number).some(b=>b>255||b<0);if(/^\[.*\]$/.test(d)){let g=d.slice(1,-1);return !(!g||g.includes(":::"))}return !!(/^[a-zA-Z\d-]*(\.[a-zA-Z\d-]+)*$/.test(d)&&d!=="")}else {let s="[a-zA-Z][a-zA-Z\\d+\\-.]*";return r&&r.length>0&&(s=`(?:${r.join("|")})`),new RegExp(`^(${s}):.+$`).test(i)}}var nt=t=>{if(!u(t)||!t.includes("%"))return false;let e=/%[0-9A-Fa-f]{2}/g;if(!t.match(e))return false;try{let r=decodeURIComponent(t);if(r!==t)return !0;try{if(decodeURIComponent(r)!==r)return !0}catch(i){return !0}}catch(r){return false}return false};var B=class t{static normalizePagination(e){let{page:n,skip:r,limit:i}=Object.assign({},e);return O(i)?(O(r)&&r>0?n=Math.floor(r/i)+1:O(n)&&n>0?r=(n-1)*i:(n=1,r=0),{page:n,skip:r,limit:i}):{}}static normalizeOrderBy(e){let n=Array.isArray(e)?e:u(e)?[e]:[],r={};return n.forEach(i=>{if(!u(i)||String(i).trim()==="")return;let s=String(i).startsWith("-"),o=s?"desc":"asc",c=s?String(i).slice(1):i,a=c;r[a]!==void 0&&console.warn(`Duplicate orderBy field: ${c}. Using last occurrence.`),r[a]=o;}),r}static canPaginateResult(e){return y(e)?O(e.limit):false}static getPaginationMetaData(e,n){let{limit:r,page:i,skip:s}=t.normalizePagination(n);e=O(e)?e:0;let o={total:e};return typeof r=="number"&&r>0&&typeof i=="number"&&i>=0&&(o.currentPage=i,o.pageSize=r,o.totalPages=Math.ceil(e/r),o.hasNextPage=o.currentPage<o.totalPages,o.hasPreviousPage=o.currentPage>1,o.nextPage=o.hasNextPage?o.currentPage+1:void 0,o.previousPage=o.hasPreviousPage?o.currentPage-1:void 0,o.lastPage=o.totalPages),o}static paginate(e,n,r){let i=t.getPaginationMetaData(n,r),{currentPage:s,pageSize:o,totalPages:c}=i;if(Array.isArray(e)&&O(s)&&O(o)&&O(c)){let a=Math.max(0,s-1)*o,f=a+o;e=e.slice(a,f);}return {data:e,total:n,meta:i}}static parseQueryOptions(e){var b;let n=x({},e==null?void 0:e.params,E(e==null?void 0:e.url)),r=x({},n,(b=e==null?void 0:e.headers)==null?void 0:b["x-filters"],e==null?void 0:e.filters),i=z(r.limit),s=z(r.skip),o=z(r.page),c=t.normalizePagination({limit:i,skip:s,page:o}),a=r.distinct;typeof a=="number"&&(a=!!a),(typeof a=="boolean"||Array.isArray(a)&&a.length)&&(c.distinct=a);let f=r.orderBy,p=t.normalizeOrderBy(f);p&&Object.getSize(p,true)>0&&(c.orderBy=p);let m=w(r.include);m.length&&(c.include=m);let h=r.cache;h!==void 0&&(c.cache=!!h);let T=r.cacheTTL;T!==void 0&&(c.cacheTTL=T);let l=rt(r.where);y(l)&&Object.getSize(l,true)&&(c.where=l);let d=r.includeDeleted;typeof d=="boolean"&&(c.includeDeleted=d);let g=w(r.relations);return g.length&&(c.relations=g),k(A({},c),{queryParams:n})}},rt=(...t)=>{for(let e of t)if(Array.isArray(e)&&e.length||u(e)||y(e)&&Object.getSize(e,true))return e},z=t=>{if(I(t))return Number(t);if(typeof t=="number")return t};
2
+ exports.ResourcePaginationHelper=B;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Creates a decorator that can be applied to class properties or methods.
3
+ *
4
+ * This function takes a key of type KeyType (defaulting to any) and returns a function that takes a value of type ValueType (defaulting to any).
5
+ * The returned function is a decorator that can be applied to class properties or methods.
6
+ *
7
+ * @template KeyType - The type of the key used to store metadata.
8
+ * @template ValueType - The type of the value associated with the key.
9
+ * @param {KeyType} key - The key under which the metadata will be stored.
10
+ * @returns {(value: ValueType) => (target: Object, propertyKey: string) => void} A function that takes a value and returns the decorator function.
11
+ * @example
12
+ * ```typescript
13
+ * const myDecorator = createDecorator('myKey')('myValue');
14
+ * class MyClass {
15
+ * @myDecorator
16
+ * myProperty: string;
17
+ * }
18
+ * ```
19
+ */
20
+ export declare function createDecorator<ValueType = unknown, KeyType = unknown>(key: KeyType): (value: ValueType) => (target: object, propertyKey: string | symbol) => void;
@@ -0,0 +1 @@
1
+ 'use strict';function o(e){return t=>(n,r)=>{Reflect.defineMetadata(e,t,n,r);}}exports.createDecorator=o;
@@ -0,0 +1,41 @@
1
+ import 'reflect-metadata';
2
+ import { ClassConstructor } from '../../types';
3
+ /**
4
+ * Creates a property decorator that stores metadata without making the property readonly
5
+ @template MetadataType - The type of the metadata
6
+ @template PropertyKeyType - The type of the property key
7
+ * @param metadataKey - The key to store the metadata under
8
+ @param metadata - The metadata to store, or a function that returns the metadata
9
+ * @returns PropertyDecorator
10
+ */
11
+ export declare function buildPropertyDecorator<MetadataType = unknown, PropertyKeyType extends MetadataPropertyKey = MetadataPropertyKey>(metadataKey: any,
12
+ /**
13
+ Retrieves the metadata for a property
14
+ @param {Object} target - The class constructor
15
+ @param {PropertyKeyType} propertyKey - The property key
16
+ @param {MetadataType} existingMetaData - The existing metadata for the property
17
+ @param {Record<PropertyKeyType, MetadataType>} allExistingMetadata - All existing metadata for the class
18
+ @returns {MetadataType} The metadata for the property
19
+
20
+ */
21
+ metadata: ((existingMetaData: MetadataType, allExistingMetadata: Record<PropertyKeyType, MetadataType>, target: object, propertyKey: MetadataPropertyKey) => MetadataType) | MetadataType): PropertyDecorator;
22
+ /**
23
+ * Retrieves all properties of a class that have been decorated with a specific metadata key.
24
+ @template MetaDataType - The type of the metadata
25
+ @template PropertyKeyType - The type of the property key
26
+ * @param target The class to retrieve decorated properties from.
27
+ * @param metadataKey The metadata key.
28
+ * @returns Record of property names and their metadata
29
+ */
30
+ export declare function getDecoratedProperties<MetaDataType = any, PropertyKeyType extends MetadataPropertyKey = MetadataPropertyKey>(target: ClassConstructor, metadataKey: any): Record<PropertyKeyType, MetaDataType>;
31
+ /**
32
+ * Retrieves metadata for a specific property.
33
+ * @template MetaDataType - The type of the metadata
34
+ * @param target - target The class or object containing the property.
35
+ * @param metadataKey - The key to retrieve metadata for
36
+ *@param propertyKey - The name of the propertyfor which metadata is being retrieved.
37
+ * @returns {MetaDataType} The metadata value for the property.
38
+ */
39
+ export declare function getDecoratedProperty<MetaDataType = unknown>(target: ClassConstructor, metadataKey: MetadataPropertyKey, propertyKey: MetadataPropertyKey): MetaDataType;
40
+ type MetadataPropertyKey = string | symbol | number;
41
+ export {};
@@ -0,0 +1 @@
1
+ 'use strict';require('reflect-metadata');function d(t,e){return (a,o)=>{let y=a==null?void 0:a.constructor,r=Object.assign({},Reflect.getMetadata(t,y)),n=r[o],p=typeof e=="function"?e(n,r,a,o):e;r[o]=p,Reflect.defineMetadata(t,r,y),Reflect.defineMetadata(t,e,a,o);}}function s(t,e){return Object.assign({},Object.assign({},Reflect.getMetadata(e,t)),Object.assign({},Reflect.getMetadata(e,t.prototype)))}function M(t,e,a){return s(t,e)[a]}exports.buildPropertyDecorator=d;exports.getDecoratedProperties=s;exports.getDecoratedProperty=M;
@@ -0,0 +1,33 @@
1
+ import { ClassConstructor } from '../../types';
2
+ import 'reflect-metadata';
3
+ import { Field, FieldType } from '../types';
4
+ export declare const fieldsMetaData: unique symbol;
5
+ export declare function FieldMeta<T extends FieldType = FieldType>(options: Field<T>): PropertyDecorator;
6
+ /**
7
+ * Retrieves the fields metadata from a class target.
8
+ *
9
+ * This function uses reflection to access the metadata associated with the given target class.
10
+ * It returns an object where the keys are property names, and the values are objects containing the type, name, and any additional options defined in the field metadata.
11
+ *
12
+ * @param {any} target - The target class or instance from which to retrieve the metadata.
13
+ * @returns {Record<string, ({ name: string } & Field)>} An object mapping property names to their corresponding metadata, which includes the type and other options.
14
+ * @example
15
+ * ```typescript
16
+ * class MyClass {
17
+ * @FieldMeta({ type: 'string' }) myField: string;
18
+ * }
19
+ * const fields = getFieldsFromTarget(MyClass);
20
+ * console.log(fields); // Output: { myField: { name: 'myField', type: 'string' } }
21
+ * ```
22
+ */
23
+ export declare function getFieldsFromTarget(target: ClassConstructor): Record<string, {
24
+ name: string;
25
+ } & Field>;
26
+ /***
27
+ * Retrieves the fields metadata from a class instance.
28
+ * @param {T} instance - The instance of the class from which to retrieve the metadata.
29
+ * @returns {Record<string, ({ name: string } & Field)>} An object mapping property names to their corresponding metadata, which includes the type and other options.
30
+ */
31
+ export declare function getFields<T extends ClassConstructor>(instance: InstanceType<T>): Record<string, {
32
+ name: string;
33
+ } & Field>;
@@ -0,0 +1 @@
1
+ 'use strict';require('reflect-metadata');var l=Object.defineProperty;var r=Object.getOwnPropertySymbols;var f=Object.prototype.hasOwnProperty,g=Object.prototype.propertyIsEnumerable;var d=(t,e,s)=>e in t?l(t,e,{enumerable:true,configurable:true,writable:true,value:s}):t[e]=s,c=(t,e)=>{for(var s in e||(e={}))f.call(e,s)&&d(t,s,e[s]);if(r)for(var s of r(e))g.call(e,s)&&d(t,s,e[s]);return t};var n=Symbol("fieldsResourcesMetadata");function p(t){return function(e,s){var o;let a=Object.assign({},Reflect.getMetadata(n,e)||{}),i=String((o=Reflect.getMetadata("design:type",e,s))==null?void 0:o.name).toLowerCase();t.type===void 0&&(t.type=["string","number","boolean","date"].includes(i)?i:"text"),a[s]=c({name:s},Object.assign({},t)),Reflect.defineMetadata(n,a,e);}}function F(t){let e=Reflect.getMetadata(n,t.prototype);return Object.assign({},e)}function y(t){let e=Reflect.getMetadata(n,Object.getPrototypeOf(t).constructor);return Object.assign({},e)}exports.FieldMeta=p;exports.fieldsMetaData=n;exports.getFields=y;exports.getFieldsFromTarget=F;