@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.
- package/README.md +239 -9
- package/dist/{src/http.js → http.js} +1 -1
- package/dist/index.d.ts +8 -17
- package/dist/index.js +8 -17
- package/dist/objects/fill-template.d.ts +7 -0
- package/dist/objects/fill-template.js +52 -0
- package/dist/{src/objects → objects}/index.d.ts +1 -0
- package/dist/{src/objects → objects}/index.js +1 -0
- package/dist/permissions.d.ts +46 -0
- package/dist/permissions.js +86 -0
- package/dist/{src/validate-query-params.js → validate-query-params.js} +1 -1
- package/package.json +21 -35
- package/dist/src/css/get-variable-value.d.ts +0 -1
- package/dist/src/css/get-variable-value.js +0 -8
- package/dist/src/css/index.d.ts +0 -1
- package/dist/src/css/index.js +0 -1
- package/dist/src/dates/dates.d.ts +0 -175
- package/dist/src/dates/dates.js +0 -385
- package/dist/src/dates/format.d.ts +0 -27
- package/dist/src/dates/format.js +0 -99
- package/dist/src/dates/index.d.ts +0 -4
- package/dist/src/dates/index.js +0 -4
- package/dist/src/dates/types.d.ts +0 -4
- package/dist/src/dates/types.js +0 -338
- package/dist/src/dates/utils.d.ts +0 -17
- package/dist/src/dates/utils.js +0 -53
- package/dist/src/files/files.d.ts +0 -64
- package/dist/src/files/files.js +0 -152
- package/dist/src/files/utils.d.ts +0 -20
- package/dist/src/files/utils.js +0 -47
- package/dist/src/geo/chunk-line.d.ts +0 -10
- package/dist/src/geo/chunk-line.js +0 -75
- package/dist/src/geo/constants.d.ts +0 -8
- package/dist/src/geo/constants.js +0 -8
- package/dist/src/geo/conversions.d.ts +0 -36
- package/dist/src/geo/conversions.js +0 -79
- package/dist/src/geo/coordinates.d.ts +0 -37
- package/dist/src/geo/coordinates.js +0 -64
- package/dist/src/geo/cut-line-at-length.d.ts +0 -10
- package/dist/src/geo/cut-line-at-length.js +0 -68
- package/dist/src/geo/geojson-collections.d.ts +0 -11
- package/dist/src/geo/geojson-collections.js +0 -29
- package/dist/src/geo/get-geofence-on-point.d.ts +0 -17
- package/dist/src/geo/get-geofence-on-point.js +0 -46
- package/dist/src/geo/index.d.ts +0 -9
- package/dist/src/geo/index.js +0 -9
- package/dist/src/geo/is-point-in-polygon.d.ts +0 -9
- package/dist/src/geo/is-point-in-polygon.js +0 -37
- package/dist/src/geo/measurements.d.ts +0 -42
- package/dist/src/geo/measurements.js +0 -71
- package/dist/src/logs/index.d.ts +0 -1
- package/dist/src/logs/index.js +0 -1
- package/dist/src/logs/logs.d.ts +0 -82
- package/dist/src/logs/logs.js +0 -145
- package/dist/src/math/coefficient-of-variation.d.ts +0 -6
- package/dist/src/math/coefficient-of-variation.js +0 -14
- package/dist/src/math/entropy.d.ts +0 -6
- package/dist/src/math/entropy.js +0 -20
- package/dist/src/math/index.d.ts +0 -3
- package/dist/src/math/index.js +0 -3
- package/dist/src/math/round-number-bias.d.ts +0 -6
- package/dist/src/math/round-number-bias.js +0 -11
- package/dist/src/navigation/index.d.ts +0 -1
- package/dist/src/navigation/index.js +0 -1
- package/dist/src/navigation/keep-url-params.d.ts +0 -8
- package/dist/src/navigation/keep-url-params.js +0 -13
- package/dist/src/nuqs/index.d.ts +0 -1
- package/dist/src/nuqs/index.js +0 -2
- package/dist/src/nuqs/parse-as-array-of-strings.d.ts +0 -1
- package/dist/src/nuqs/parse-as-array-of-strings.js +0 -43
- package/dist/src/permissions.d.ts +0 -46
- package/dist/src/permissions.js +0 -77
- package/dist/src/random/generate-random-number.d.ts +0 -8
- package/dist/src/random/generate-random-number.js +0 -14
- package/dist/src/random/generate-random-string.d.ts +0 -12
- package/dist/src/random/generate-random-string.js +0 -32
- package/dist/src/random/generate-random-token.d.ts +0 -8
- package/dist/src/random/generate-random-token.js +0 -12
- package/dist/src/random/index.d.ts +0 -3
- package/dist/src/random/index.js +0 -3
- package/dist/src/strings/index.d.ts +0 -2
- package/dist/src/strings/index.js +0 -2
- package/dist/src/strings/normalize-string.d.ts +0 -8
- package/dist/src/strings/normalize-string.js +0 -18
- package/dist/src/strings/validation.d.ts +0 -2
- package/dist/src/strings/validation.js +0 -7
- /package/dist/{src/batching → batching}/index.d.ts +0 -0
- /package/dist/{src/batching → batching}/index.js +0 -0
- /package/dist/{src/batching → batching}/perform-in-chunks.d.ts +0 -0
- /package/dist/{src/batching → batching}/perform-in-chunks.js +0 -0
- /package/dist/{src/caching → caching}/cache.d.ts +0 -0
- /package/dist/{src/caching → caching}/cache.js +0 -0
- /package/dist/{src/caching → caching}/index.d.ts +0 -0
- /package/dist/{src/caching → caching}/index.js +0 -0
- /package/dist/{src/generic → generic}/get-value-at-path.d.ts +0 -0
- /package/dist/{src/generic → generic}/get-value-at-path.js +0 -0
- /package/dist/{src/generic → generic}/index.d.ts +0 -0
- /package/dist/{src/generic → generic}/index.js +0 -0
- /package/dist/{src/generic → generic}/set-value-at-path.d.ts +0 -0
- /package/dist/{src/generic → generic}/set-value-at-path.js +0 -0
- /package/dist/{src/http.d.ts → http.d.ts} +0 -0
- /package/dist/{src/objects → objects}/compare-objects.d.ts +0 -0
- /package/dist/{src/objects → objects}/compare-objects.js +0 -0
- /package/dist/{src/objects → objects}/convert-object.d.ts +0 -0
- /package/dist/{src/objects → objects}/convert-object.js +0 -0
- /package/dist/{src/objects → objects}/flatten-object.d.ts +0 -0
- /package/dist/{src/objects → objects}/flatten-object.js +0 -0
- /package/dist/{src/objects → objects}/merge-objects.d.ts +0 -0
- /package/dist/{src/objects → objects}/merge-objects.js +0 -0
- /package/dist/{src/singleton-proxy.d.ts → singleton-proxy.d.ts} +0 -0
- /package/dist/{src/singleton-proxy.js → singleton-proxy.js} +0 -0
- /package/dist/{src/validate-query-params.d.ts → validate-query-params.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -1,13 +1,243 @@
|
|
|
1
|
-
|
|
1
|
+
# @tmlmobilidade/utils
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
6
|
-
- Centralize reusable logic
|
|
7
|
-
- Promote consistency and reduce code duplication
|
|
8
|
-
- Simplify development with well-tested, shared helpers
|
|
5
|
+
## Installation
|
|
9
6
|
|
|
10
|
-
|
|
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
|
+
|
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,8 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './
|
|
6
|
-
export * from './
|
|
7
|
-
export * from './
|
|
8
|
-
export * from './
|
|
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 './
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './
|
|
6
|
-
export * from './
|
|
7
|
-
export * from './
|
|
8
|
-
export * from './
|
|
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
|
+
}
|
|
@@ -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
|
+
}
|
package/package.json
CHANGED
|
@@ -1,64 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tmlmobilidade/utils",
|
|
3
|
-
"version": "
|
|
4
|
-
"author":
|
|
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/
|
|
9
|
+
"homepage": "https://github.com/tmlmobilidade/go#readme",
|
|
7
10
|
"bugs": {
|
|
8
|
-
"url": "https://github.com/tmlmobilidade/
|
|
11
|
+
"url": "https://github.com/tmlmobilidade/go/issues"
|
|
9
12
|
},
|
|
10
13
|
"repository": {
|
|
11
14
|
"type": "git",
|
|
12
|
-
"url": "git+https://github.com/tmlmobilidade/
|
|
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
|
-
"
|
|
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
|
-
"
|
|
28
|
-
|
|
29
|
-
"default": "./dist/index.js"
|
|
30
|
-
},
|
|
30
|
+
"main": "./dist/index.js",
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
31
32
|
"scripts": {
|
|
32
|
-
"build": "
|
|
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/
|
|
43
|
-
"@
|
|
44
|
-
"
|
|
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
|
-
"@
|
|
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
|
-
"
|
|
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;
|
package/dist/src/css/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './get-variable-value.js';
|
package/dist/src/css/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './get-variable-value.js';
|