@tmlmobilidade/utils 20251031.1051.3 → 20251202.1817.5

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 (112) hide show
  1. package/README.md +239 -9
  2. package/dist/{src/http.js → http.js} +1 -1
  3. package/dist/index.d.ts +8 -17
  4. package/dist/index.js +8 -17
  5. package/dist/objects/fill-template.d.ts +7 -0
  6. package/dist/objects/fill-template.js +52 -0
  7. package/dist/{src/objects → objects}/index.d.ts +1 -0
  8. package/dist/{src/objects → objects}/index.js +1 -0
  9. package/dist/permissions.d.ts +46 -0
  10. package/dist/permissions.js +86 -0
  11. package/dist/{src/validate-query-params.js → validate-query-params.js} +1 -1
  12. package/package.json +21 -35
  13. package/dist/src/css/get-variable-value.d.ts +0 -1
  14. package/dist/src/css/get-variable-value.js +0 -8
  15. package/dist/src/css/index.d.ts +0 -1
  16. package/dist/src/css/index.js +0 -1
  17. package/dist/src/dates/dates.d.ts +0 -175
  18. package/dist/src/dates/dates.js +0 -385
  19. package/dist/src/dates/format.d.ts +0 -27
  20. package/dist/src/dates/format.js +0 -99
  21. package/dist/src/dates/index.d.ts +0 -4
  22. package/dist/src/dates/index.js +0 -4
  23. package/dist/src/dates/types.d.ts +0 -4
  24. package/dist/src/dates/types.js +0 -338
  25. package/dist/src/dates/utils.d.ts +0 -17
  26. package/dist/src/dates/utils.js +0 -53
  27. package/dist/src/files/files.d.ts +0 -64
  28. package/dist/src/files/files.js +0 -152
  29. package/dist/src/files/utils.d.ts +0 -20
  30. package/dist/src/files/utils.js +0 -47
  31. package/dist/src/geo/chunk-line.d.ts +0 -10
  32. package/dist/src/geo/chunk-line.js +0 -75
  33. package/dist/src/geo/constants.d.ts +0 -8
  34. package/dist/src/geo/constants.js +0 -8
  35. package/dist/src/geo/conversions.d.ts +0 -36
  36. package/dist/src/geo/conversions.js +0 -79
  37. package/dist/src/geo/coordinates.d.ts +0 -37
  38. package/dist/src/geo/coordinates.js +0 -64
  39. package/dist/src/geo/cut-line-at-length.d.ts +0 -10
  40. package/dist/src/geo/cut-line-at-length.js +0 -68
  41. package/dist/src/geo/geojson-collections.d.ts +0 -11
  42. package/dist/src/geo/geojson-collections.js +0 -29
  43. package/dist/src/geo/get-geofence-on-point.d.ts +0 -17
  44. package/dist/src/geo/get-geofence-on-point.js +0 -46
  45. package/dist/src/geo/index.d.ts +0 -9
  46. package/dist/src/geo/index.js +0 -9
  47. package/dist/src/geo/is-point-in-polygon.d.ts +0 -9
  48. package/dist/src/geo/is-point-in-polygon.js +0 -37
  49. package/dist/src/geo/measurements.d.ts +0 -42
  50. package/dist/src/geo/measurements.js +0 -71
  51. package/dist/src/logs/index.d.ts +0 -1
  52. package/dist/src/logs/index.js +0 -1
  53. package/dist/src/logs/logs.d.ts +0 -82
  54. package/dist/src/logs/logs.js +0 -145
  55. package/dist/src/math/coefficient-of-variation.d.ts +0 -6
  56. package/dist/src/math/coefficient-of-variation.js +0 -14
  57. package/dist/src/math/entropy.d.ts +0 -6
  58. package/dist/src/math/entropy.js +0 -20
  59. package/dist/src/math/index.d.ts +0 -3
  60. package/dist/src/math/index.js +0 -3
  61. package/dist/src/math/round-number-bias.d.ts +0 -6
  62. package/dist/src/math/round-number-bias.js +0 -11
  63. package/dist/src/navigation/index.d.ts +0 -1
  64. package/dist/src/navigation/index.js +0 -1
  65. package/dist/src/navigation/keep-url-params.d.ts +0 -8
  66. package/dist/src/navigation/keep-url-params.js +0 -13
  67. package/dist/src/nuqs/index.d.ts +0 -1
  68. package/dist/src/nuqs/index.js +0 -2
  69. package/dist/src/nuqs/parse-as-array-of-strings.d.ts +0 -1
  70. package/dist/src/nuqs/parse-as-array-of-strings.js +0 -43
  71. package/dist/src/permissions.d.ts +0 -46
  72. package/dist/src/permissions.js +0 -77
  73. package/dist/src/random/generate-random-number.d.ts +0 -8
  74. package/dist/src/random/generate-random-number.js +0 -14
  75. package/dist/src/random/generate-random-string.d.ts +0 -12
  76. package/dist/src/random/generate-random-string.js +0 -32
  77. package/dist/src/random/generate-random-token.d.ts +0 -8
  78. package/dist/src/random/generate-random-token.js +0 -12
  79. package/dist/src/random/index.d.ts +0 -3
  80. package/dist/src/random/index.js +0 -3
  81. package/dist/src/strings/index.d.ts +0 -2
  82. package/dist/src/strings/index.js +0 -2
  83. package/dist/src/strings/normalize-string.d.ts +0 -8
  84. package/dist/src/strings/normalize-string.js +0 -18
  85. package/dist/src/strings/validation.d.ts +0 -2
  86. package/dist/src/strings/validation.js +0 -7
  87. /package/dist/{src/batching → batching}/index.d.ts +0 -0
  88. /package/dist/{src/batching → batching}/index.js +0 -0
  89. /package/dist/{src/batching → batching}/perform-in-chunks.d.ts +0 -0
  90. /package/dist/{src/batching → batching}/perform-in-chunks.js +0 -0
  91. /package/dist/{src/caching → caching}/cache.d.ts +0 -0
  92. /package/dist/{src/caching → caching}/cache.js +0 -0
  93. /package/dist/{src/caching → caching}/index.d.ts +0 -0
  94. /package/dist/{src/caching → caching}/index.js +0 -0
  95. /package/dist/{src/generic → generic}/get-value-at-path.d.ts +0 -0
  96. /package/dist/{src/generic → generic}/get-value-at-path.js +0 -0
  97. /package/dist/{src/generic → generic}/index.d.ts +0 -0
  98. /package/dist/{src/generic → generic}/index.js +0 -0
  99. /package/dist/{src/generic → generic}/set-value-at-path.d.ts +0 -0
  100. /package/dist/{src/generic → generic}/set-value-at-path.js +0 -0
  101. /package/dist/{src/http.d.ts → http.d.ts} +0 -0
  102. /package/dist/{src/objects → objects}/compare-objects.d.ts +0 -0
  103. /package/dist/{src/objects → objects}/compare-objects.js +0 -0
  104. /package/dist/{src/objects → objects}/convert-object.d.ts +0 -0
  105. /package/dist/{src/objects → objects}/convert-object.js +0 -0
  106. /package/dist/{src/objects → objects}/flatten-object.d.ts +0 -0
  107. /package/dist/{src/objects → objects}/flatten-object.js +0 -0
  108. /package/dist/{src/objects → objects}/merge-objects.d.ts +0 -0
  109. /package/dist/{src/objects → objects}/merge-objects.js +0 -0
  110. /package/dist/{src/singleton-proxy.d.ts → singleton-proxy.d.ts} +0 -0
  111. /package/dist/{src/singleton-proxy.js → singleton-proxy.js} +0 -0
  112. /package/dist/{src/validate-query-params.d.ts → validate-query-params.d.ts} +0 -0
package/README.md CHANGED
@@ -1,13 +1,243 @@
1
- ## @tmlmobilidade/utils
1
+ # @tmlmobilidade/utils
2
2
 
3
- This package provides a collection of common utility functions used across projects within the organization.
3
+ A collection of utility functions and helpers for the TML Mobilidade Go monorepo, providing common functionality for batching operations, caching, HTTP requests, object manipulation, permissions, and more.
4
4
 
5
- ### Purpose
6
- - Centralize reusable logic
7
- - Promote consistency and reduce code duplication
8
- - Simplify development with well-tested, shared helpers
5
+ ## Installation
9
6
 
10
- ### Installation
11
- ```
7
+ ```bash
12
8
  npm install @tmlmobilidade/utils
13
- ```
9
+ ```
10
+
11
+ ## Features
12
+
13
+ ### Batching
14
+
15
+ Utilities for processing large datasets in chunks to avoid memory issues and improve performance.
16
+
17
+ - **`performInChunks`** - Processes large arrays in configurable chunks with async operations
18
+
19
+ ### Caching
20
+
21
+ In-memory cache implementation with TTL (time-to-live) support.
22
+
23
+ - **`Cache`** - A simple key-value cache with automatic expiration
24
+
25
+ ### Generic Utilities
26
+
27
+ Path-based object manipulation utilities with full TypeScript support.
28
+
29
+ - **`getValueAtPath`** - Retrieves a value from an object using a dot-notation path
30
+ - **`setValueAtPath`** - Sets a value at a dot-notation path, creating intermediate objects/arrays as needed
31
+ - **`DotPath`** - TypeScript type for generating all possible paths in an object
32
+ - **`PathValue`** - TypeScript type for retrieving the value type at a specific path
33
+
34
+ ### HTTP Utilities
35
+
36
+ Comprehensive HTTP client utilities with retry logic, error handling, and SWR integration.
37
+
38
+ - **`fetchData`** - Fetches data with automatic retry, exponential backoff, and error handling
39
+ - **`multipartFetch`** - Sends multipart form data requests
40
+ - **`uploadFile`** - Uploads files using multipart form data
41
+ - **`swrFetcher`** - SWR-compatible fetcher with authentication
42
+ - **`standardSwrFetcher`** - SWR-compatible fetcher without authentication
43
+ - **`HttpResponse`** - Response wrapper with data, error, and status code
44
+ - **`WithPagination`** - Type helper for paginated responses
45
+
46
+ ### Object Manipulation
47
+
48
+ Utilities for comparing, converting, flattening, and merging objects.
49
+
50
+ - **`compareObjects`** - Deep comparison of objects, returning differences
51
+ - **`convertObject`** - Converts objects to match a Zod schema shape
52
+ - **`flattenObject`** - Flattens nested objects using dot notation
53
+ - **`mergeObjects`** - Deep merges objects and arrays with deduplication
54
+
55
+ ### Permissions
56
+
57
+ Permission checking utilities for role-based access control.
58
+
59
+ - **`getPermission`** - Retrieves a permission from a list by scope and action
60
+ - **`hasPermission`** - Checks if a permission exists in a list
61
+ - **`hasPermissionResource`** - Checks if a value exists in a permission's resource
62
+ - **`hasAPIResourcePermission`** - Fastify-specific permission check for API resources
63
+
64
+ ### Singleton Proxy
65
+
66
+ Utility for creating proxies around async singleton classes.
67
+
68
+ - **`AsyncSingletonProxy`** - Creates a proxy that delays method access until singleton instance is initialized
69
+
70
+ ### Query Validation
71
+
72
+ Utilities for validating and parsing query parameters.
73
+
74
+ - **`validateQueryParams`** - Validates query parameters against a Zod schema
75
+
76
+ ## Usage Examples
77
+
78
+ ### Batching
79
+
80
+ ```typescript
81
+ import { performInChunks } from '@tmlmobilidade/utils';
82
+
83
+ const largeDataset = Array.from({ length: 10000 }, (_, i) => ({ id: i }));
84
+
85
+ await performInChunks(largeDataset, async (chunk) => {
86
+ await processChunk(chunk);
87
+ }, 1000); // Process 1000 items at a time
88
+ ```
89
+
90
+ ### Caching
91
+
92
+ ```typescript
93
+ import { Cache } from '@tmlmobilidade/utils';
94
+
95
+ const cache = new Cache<string, User>(60000); // 60 second TTL
96
+
97
+ cache.set('user:123', user);
98
+ const user = cache.get('user:123');
99
+ cache.delete('user:123');
100
+ ```
101
+
102
+ ### Path Operations
103
+
104
+ ```typescript
105
+ import { getValueAtPath, setValueAtPath } from '@tmlmobilidade/utils';
106
+
107
+ const obj = { user: { profile: { name: 'John' } } };
108
+
109
+ // Get nested value
110
+ const name = getValueAtPath(obj, 'user.profile.name'); // 'John'
111
+
112
+ // Set nested value (creates intermediate objects if needed)
113
+ setValueAtPath(obj, 'user.profile.email', 'john@example.com');
114
+ ```
115
+
116
+ ### HTTP Requests
117
+
118
+ ```typescript
119
+ import { fetchData, uploadFile, swrFetcher } from '@tmlmobilidade/utils';
120
+
121
+ // GET request with retry
122
+ const response = await fetchData<User>('/api/users/123');
123
+ if (response.isOk()) {
124
+ console.log(response.data);
125
+ }
126
+
127
+ // POST request
128
+ const createResponse = await fetchData<User>(
129
+ '/api/users',
130
+ 'POST',
131
+ { name: 'John', email: 'john@example.com' }
132
+ );
133
+
134
+ // File upload
135
+ const uploadResponse = await uploadFile<{ url: string }>('/api/upload', file);
136
+
137
+ // SWR integration
138
+ const data = await swrFetcher<User[]>('/api/users');
139
+ ```
140
+
141
+ ### Object Manipulation
142
+
143
+ ```typescript
144
+ import { compareObjects, flattenObject, mergeObjects, convertObject } from '@tmlmobilidade/utils';
145
+ import { z } from 'zod';
146
+
147
+ // Compare objects
148
+ const prev = { name: 'Alice', age: 30 };
149
+ const curr = { name: 'Alice', age: 31 };
150
+ const diff = compareObjects(prev, curr);
151
+ // { age: { curr_value: 31, prev_value: 30 } }
152
+
153
+ // Flatten object
154
+ const nested = { a: { b: 1, c: { d: 2 } } };
155
+ const flat = flattenObject(nested);
156
+ // { 'a': { b: 1, c: { d: 2 } }, 'a.b': 1, 'a.c': { d: 2 }, 'a.c.d': 2 }
157
+
158
+ // Merge objects
159
+ const merged = mergeObjects({ a: 1, b: 2 }, { b: 3, c: 4 });
160
+ // { a: 1, b: 3, c: 4 }
161
+
162
+ // Convert to schema
163
+ const schema = z.object({ name: z.string(), age: z.number() });
164
+ const converted = convertObject({ name: 'John', age: 30, extra: 'ignored' }, schema);
165
+ // { name: 'John', age: 30 }
166
+ ```
167
+
168
+ ### Permissions
169
+
170
+ ```typescript
171
+ import { hasPermission, hasPermissionResource } from '@tmlmobilidade/utils';
172
+
173
+ const permissions = [
174
+ { scope: 'users', action: 'read', resource: { userId: ['123', '456'] } },
175
+ { scope: 'users', action: 'write', resource: { userId: ['*'] } }
176
+ ];
177
+
178
+ // Check if permission exists
179
+ if (hasPermission(permissions, 'users', 'read')) {
180
+ // User has read permission
181
+ }
182
+
183
+ // Check resource-specific permission
184
+ if (hasPermissionResource({
185
+ permissions,
186
+ scope: 'users',
187
+ action: 'read',
188
+ resource_key: 'userId',
189
+ value: '123'
190
+ })) {
191
+ // User has permission for resource '123'
192
+ }
193
+ ```
194
+
195
+ ### Query Validation
196
+
197
+ ```typescript
198
+ import { validateQueryParams } from '@tmlmobilidade/utils';
199
+ import { z } from 'zod';
200
+
201
+ const schema = z.object({
202
+ page: z.coerce.number().min(1),
203
+ limit: z.coerce.number().min(1).max(100)
204
+ });
205
+
206
+ // In a Fastify route handler
207
+ const params = validateQueryParams(req.query, schema);
208
+ // Throws HttpException if validation fails
209
+ ```
210
+
211
+ ### Singleton Proxy
212
+
213
+ ```typescript
214
+ import { AsyncSingletonProxy } from '@tmlmobilidade/utils';
215
+
216
+ class Database {
217
+ private static instance: Database | null = null;
218
+
219
+ static async getInstance(): Promise<Database> {
220
+ if (!this.instance) {
221
+ this.instance = await this.initialize();
222
+ }
223
+ return this.instance;
224
+ }
225
+
226
+ async query(sql: string) {
227
+ // ...
228
+ }
229
+ }
230
+
231
+ // Create proxy that handles async initialization
232
+ const db = AsyncSingletonProxy(Database);
233
+ await db.query('SELECT * FROM users'); // Automatically waits for initialization
234
+ ```
235
+
236
+ ## License
237
+
238
+ AGPL-3.0-or-later
239
+
240
+ ## Repository
241
+
242
+ [GitHub](https://github.com/tmlmobilidade/go)
243
+
@@ -1,4 +1,4 @@
1
- import { HttpException } from '@tmlmobilidade/lib';
1
+ import { HttpException } from '@tmlmobilidade/consts';
2
2
  export class HttpResponse {
3
3
  data;
4
4
  error;
package/dist/index.d.ts CHANGED
@@ -1,17 +1,8 @@
1
- export * from './src/batching/index.js';
2
- export * from './src/caching/index.js';
3
- export * from './src/css/index.js';
4
- export * from './src/dates/index.js';
5
- export * from './src/files/files.js';
6
- export * from './src/generic/index.js';
7
- export * from './src/geo/index.js';
8
- export * from './src/http.js';
9
- export * from './src/logs/index.js';
10
- export * from './src/math/index.js';
11
- export * from './src/navigation/index.js';
12
- export * from './src/objects/index.js';
13
- export * from './src/permissions.js';
14
- export * from './src/random/index.js';
15
- export * from './src/singleton-proxy.js';
16
- export * from './src/strings/index.js';
17
- export * from './src/validate-query-params.js';
1
+ export * from './batching/index.js';
2
+ export * from './caching/index.js';
3
+ export * from './generic/index.js';
4
+ export * from './http.js';
5
+ export * from './objects/index.js';
6
+ export * from './permissions.js';
7
+ export * from './singleton-proxy.js';
8
+ export * from './validate-query-params.js';
package/dist/index.js CHANGED
@@ -1,17 +1,8 @@
1
- export * from './src/batching/index.js';
2
- export * from './src/caching/index.js';
3
- export * from './src/css/index.js';
4
- export * from './src/dates/index.js';
5
- export * from './src/files/files.js';
6
- export * from './src/generic/index.js';
7
- export * from './src/geo/index.js';
8
- export * from './src/http.js';
9
- export * from './src/logs/index.js';
10
- export * from './src/math/index.js';
11
- export * from './src/navigation/index.js';
12
- export * from './src/objects/index.js';
13
- export * from './src/permissions.js';
14
- export * from './src/random/index.js';
15
- export * from './src/singleton-proxy.js';
16
- export * from './src/strings/index.js';
17
- export * from './src/validate-query-params.js';
1
+ export * from './batching/index.js';
2
+ export * from './caching/index.js';
3
+ export * from './generic/index.js';
4
+ export * from './http.js';
5
+ export * from './objects/index.js';
6
+ export * from './permissions.js';
7
+ export * from './singleton-proxy.js';
8
+ export * from './validate-query-params.js';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Populates a template object with data from another object.
3
+ * @param template The template object to be populated.
4
+ * @param data The data object to populate the template with.
5
+ * @returns The populated template object.
6
+ */
7
+ export default function fillTemplate<T>(template: T, data: any): T;
@@ -0,0 +1,52 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /**
3
+ * Populates a template object with data from another object.
4
+ * @param template The template object to be populated.
5
+ * @param data The data object to populate the template with.
6
+ * @returns The populated template object.
7
+ */
8
+ export default function fillTemplate(template, data) {
9
+ //
10
+ // Return the template if there is no data
11
+ if (!data)
12
+ return template;
13
+ // Create a deep copy of the template object
14
+ const populatedTemplateObject = JSON.parse(JSON.stringify(template));
15
+ // Setup a recursive function to populate the template
16
+ const recursivePopulate = (currentTemplateStep, currentDataStep) => {
17
+ //
18
+ // If the template is an object and not null
19
+ if (typeof currentTemplateStep === 'object' && currentTemplateStep !== null) {
20
+ //
21
+ // If the template is an array and the data is also an array, populate each element recursively
22
+ if (Array.isArray(currentTemplateStep) && Array.isArray(currentDataStep)) {
23
+ return currentDataStep?.map(item => recursivePopulate(currentTemplateStep, item));
24
+ }
25
+ // If the data is also an object, recursively populate its properties
26
+ if (typeof currentDataStep === 'object') {
27
+ const populatedInnerObject = {};
28
+ for (const key in currentTemplateStep) {
29
+ populatedInnerObject[key] = recursivePopulate(currentTemplateStep[key], currentDataStep[key]);
30
+ }
31
+ return populatedInnerObject;
32
+ }
33
+ // If the data is null then use the template value
34
+ if (currentDataStep === null || currentDataStep === undefined) {
35
+ return currentTemplateStep;
36
+ }
37
+ // If it is something else use the data
38
+ return currentDataStep;
39
+ //
40
+ }
41
+ // If the template is not an object (i.e. an object or array) but data is null, use the template value
42
+ if (currentDataStep === null || currentDataStep === undefined) {
43
+ return currentTemplateStep;
44
+ }
45
+ // If the template is not an object and the data is defined, then use the data
46
+ return currentDataStep;
47
+ //
48
+ };
49
+ // Initiate the recursive dance
50
+ return recursivePopulate(populatedTemplateObject, data);
51
+ //
52
+ }
@@ -1,4 +1,5 @@
1
1
  export * from './compare-objects.js';
2
2
  export * from './convert-object.js';
3
+ export * from './fill-template.js';
3
4
  export * from './flatten-object.js';
4
5
  export * from './merge-objects.js';
@@ -1,4 +1,5 @@
1
1
  export * from './compare-objects.js';
2
2
  export * from './convert-object.js';
3
+ export * from './fill-template.js';
3
4
  export * from './flatten-object.js';
4
5
  export * from './merge-objects.js';
@@ -0,0 +1,46 @@
1
+ import { type Permission } from '@tmlmobilidade/types';
2
+ /**
3
+ * Get a scope and action filtered Permission object
4
+ * from a list of User permissions.
5
+ * @param permissions The full list of permissions of the user.
6
+ * @param scope The resource scope of the permission to filter by.
7
+ * @param action The action of the permission to filter by.
8
+ * @returns The filtered Permission object.
9
+ * @deprecated Use hasPermissionResource instead.
10
+ */
11
+ export declare function getPermission(permissions: Permission[], scope: string, action: string): Permission;
12
+ /**
13
+ * Arguments for hasPermissionResource function.
14
+ * @param T The type of the resource.
15
+ */
16
+ export interface HasPermissionResourceArgs {
17
+ action: string;
18
+ permissions: Permission[];
19
+ resource_key: string;
20
+ scope: string;
21
+ value: unknown;
22
+ }
23
+ /**
24
+ * Check if a permission exists in a list of permissions, with additional check for a given resource value.
25
+ * If a `value` exists in a `resource` of a User `permissions` object that
26
+ * matches the given `action` and `scope`. For example, if you want to check if
27
+ * a user has access to a specific `agency_id`, you set `value=43` and `resource_key='agency_ids'`.
28
+ * If the provided `permissions` object contains the value `43` inside the `scope='plans'`,
29
+ * `action='create'` and `resource_key='agency_ids'` the function will return true.
30
+ * @param permissions The list of permissions (from a user or request).
31
+ * @param value The permission value to check against.
32
+ * @param resource_key The key of the resource.
33
+ * @param scope The scope of the permission.
34
+ * @param action The action of the permission.
35
+ * @returns The permission.
36
+ * @deprecated Use hasPermissionResource instead.
37
+ */
38
+ export declare function hasPermissionResource({ action, permissions, resource_key, scope, value }: HasPermissionResourceArgs): boolean;
39
+ /**
40
+ * Check if a value exists in a resource of a permission from Fastify request.
41
+ * @param request The FastifyRequest.
42
+ * @param params The parameters for checking permission.
43
+ * @returns True if the user has the requested permission, false otherwise.
44
+ * @deprecated Use hasPermissionResource instead.
45
+ */
46
+ export declare function hasAPIResourcePermission(request: any, params: HasPermissionResourceArgs): boolean;
@@ -0,0 +1,86 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /* * */
3
+ import { PermissionCatalog } from '@tmlmobilidade/types';
4
+ import { mergekit } from 'mergekit';
5
+ /**
6
+ * Get a scope and action filtered Permission object
7
+ * from a list of User permissions.
8
+ * @param permissions The full list of permissions of the user.
9
+ * @param scope The resource scope of the permission to filter by.
10
+ * @param action The action of the permission to filter by.
11
+ * @returns The filtered Permission object.
12
+ * @deprecated Use hasPermissionResource instead.
13
+ */
14
+ export function getPermission(permissions, scope, action) {
15
+ return mergekit([...(permissions ?? [])], {
16
+ appendArrays: true,
17
+ dedupArrays: true,
18
+ onlyObjectWithKeyValues: [
19
+ { key: 'scope', value: scope },
20
+ { key: 'action', value: action },
21
+ ],
22
+ });
23
+ }
24
+ /**
25
+ * Check if a permission exists in a list of permissions, with additional check for a given resource value.
26
+ * If a `value` exists in a `resource` of a User `permissions` object that
27
+ * matches the given `action` and `scope`. For example, if you want to check if
28
+ * a user has access to a specific `agency_id`, you set `value=43` and `resource_key='agency_ids'`.
29
+ * If the provided `permissions` object contains the value `43` inside the `scope='plans'`,
30
+ * `action='create'` and `resource_key='agency_ids'` the function will return true.
31
+ * @param permissions The list of permissions (from a user or request).
32
+ * @param value The permission value to check against.
33
+ * @param resource_key The key of the resource.
34
+ * @param scope The scope of the permission.
35
+ * @param action The action of the permission.
36
+ * @returns The permission.
37
+ * @deprecated Use hasPermissionResource instead.
38
+ */
39
+ export function hasPermissionResource({ action, permissions, resource_key, scope, value }) {
40
+ //
41
+ //
42
+ // Return false if no permissions
43
+ if (!permissions)
44
+ return false;
45
+ //
46
+ // Find the permission with the given action and scope
47
+ const foundPermission = permissions.find(permission => permission.action === action && permission.scope === scope);
48
+ if (!foundPermission)
49
+ return false;
50
+ //
51
+ // Check if value exists in the permission.resources[resource_key]
52
+ const resourceValues = foundPermission['resources']?.[resource_key];
53
+ if (!resourceValues)
54
+ return false;
55
+ //
56
+ // If resourceValues is an Array, check if value is in the array
57
+ // or if it contains the ALLOW_ALL_FLAG.
58
+ if (Array.isArray(resourceValues) && resourceValues.includes(PermissionCatalog.ALLOW_ALL_FLAG))
59
+ return true;
60
+ if (Array.isArray(resourceValues) && resourceValues.includes(value))
61
+ return true;
62
+ //
63
+ // If resourceValues is not an Array, check if it is equal to the requested value
64
+ if (resourceValues === value)
65
+ return true;
66
+ //
67
+ // Otherwise, return false
68
+ return false;
69
+ //
70
+ }
71
+ /**
72
+ * Check if a value exists in a resource of a permission from Fastify request.
73
+ * @param request The FastifyRequest.
74
+ * @param params The parameters for checking permission.
75
+ * @returns True if the user has the requested permission, false otherwise.
76
+ * @deprecated Use hasPermissionResource instead.
77
+ */
78
+ export function hasAPIResourcePermission(request, params) {
79
+ return hasPermissionResource({
80
+ action: params.action,
81
+ permissions: request.permissions,
82
+ resource_key: params.resource_key,
83
+ scope: params.scope,
84
+ value: params.value,
85
+ });
86
+ }
@@ -1,4 +1,4 @@
1
- import { HttpException, HttpStatus } from '@tmlmobilidade/lib';
1
+ import { HttpException, HttpStatus } from '@tmlmobilidade/consts';
2
2
  export function validateQueryParams(queryParams, schema) {
3
3
  const result = schema.safeParse(queryParams);
4
4
  if (!result.success) {
package/package.json CHANGED
@@ -1,64 +1,50 @@
1
1
  {
2
2
  "name": "@tmlmobilidade/utils",
3
- "version": "20251031.1051.3",
4
- "author": "João de Vasconcelos & Jusi Monteiro",
3
+ "version": "20251202.1817.5",
4
+ "author": {
5
+ "email": "iso@tmlmobilidade.pt",
6
+ "name": "TML-ISO"
7
+ },
5
8
  "license": "AGPL-3.0-or-later",
6
- "homepage": "https://github.com/tmlmobilidade/services#readme",
9
+ "homepage": "https://github.com/tmlmobilidade/go#readme",
7
10
  "bugs": {
8
- "url": "https://github.com/tmlmobilidade/services/issues"
11
+ "url": "https://github.com/tmlmobilidade/go/issues"
9
12
  },
10
13
  "repository": {
11
14
  "type": "git",
12
- "url": "git+https://github.com/tmlmobilidade/services.git"
15
+ "url": "git+https://github.com/tmlmobilidade/go.git"
13
16
  },
14
17
  "keywords": [
15
18
  "public transit",
16
19
  "tml",
17
20
  "transportes metropolitanos de lisboa",
18
- "services"
21
+ "go"
19
22
  ],
20
23
  "publishConfig": {
21
24
  "access": "public"
22
25
  },
23
26
  "type": "module",
24
27
  "files": [
25
- "dist/"
28
+ "dist"
26
29
  ],
27
- "exports": {
28
- "types": "./dist/index.d.ts",
29
- "default": "./dist/index.js"
30
- },
30
+ "main": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
31
32
  "scripts": {
32
- "build": "rimraf ./dist && tsc && resolve-tspaths",
33
- "lint": "eslint && tsc --noEmit",
34
- "lint:fix": "eslint --fix"
35
- },
36
- "browser": {
37
- "fs": false,
38
- "os": false,
39
- "path": false
33
+ "build": "tsc && resolve-tspaths",
34
+ "lint": "eslint ./src/ && tsc --noEmit",
35
+ "lint:fix": "eslint ./src/ --fix",
36
+ "watch": "tsc-watch --onSuccess 'resolve-tspaths'"
40
37
  },
41
38
  "dependencies": {
42
- "@tmlmobilidade/lib": "*",
43
- "@turf/turf": "7.2.0",
44
- "extract-zip": "2.0.1",
45
- "geojson": "0.5.0",
46
- "jszip": "3.10.1",
47
- "luxon": "3.7.2",
48
- "mergekit": "3.0.6",
49
- "papaparse": "5.5.3",
50
- "zod": "3.25.76"
39
+ "@tmlmobilidade/consts": "*",
40
+ "@tmlmobilidade/types": "*",
41
+ "mergekit": "3.0.6"
51
42
  },
52
43
  "devDependencies": {
53
- "@carrismetropolitana/eslint": "20250622.1204.50",
54
44
  "@tmlmobilidade/tsconfig": "*",
55
- "@tmlmobilidade/types": "*",
56
- "@types/luxon": "3.7.1",
57
- "@types/node": "24.9.1",
58
- "@types/papaparse": "5.3.16",
45
+ "@types/node": "24.10.1",
59
46
  "resolve-tspaths": "0.8.23",
60
- "rimraf": "6.0.1",
61
- "turbo": "2.5.8",
47
+ "tsc-watch": "7.2.0",
62
48
  "typescript": "5.9.3"
63
49
  }
64
50
  }
@@ -1 +0,0 @@
1
- export declare const getCssVariableValue: (variableName: string) => any;
@@ -1,8 +0,0 @@
1
- /* * */
2
- export const getCssVariableValue = (variableName) => {
3
- if (typeof globalThis.window === 'undefined')
4
- return undefined;
5
- return globalThis.window.getComputedStyle(globalThis.document.documentElement)
6
- .getPropertyValue(variableName)
7
- .trim();
8
- };
@@ -1 +0,0 @@
1
- export * from './get-variable-value.js';
@@ -1 +0,0 @@
1
- export * from './get-variable-value.js';