@cra-risk-management/sdk 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.
package/CHANGELOG.md ADDED
@@ -0,0 +1,33 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2025-12-30
9
+
10
+ ### Added
11
+ - Initial release of CRA Risk Management SDK for JavaScript
12
+ - Client class with authentication support (username/password and token-based)
13
+ - HTTP methods: GET, POST, PATCH, DELETE
14
+ - Resource clients for:
15
+ - Municipalities
16
+ - Critical Points (with nested attributes: Event Zones, Event Types, Observations)
17
+ - Users
18
+ - Automatic token management and re-authentication
19
+ - Request retry logic with exponential backoff
20
+ - Configurable timeout and retry settings
21
+ - Comprehensive test suite with Jest
22
+ - Full API documentation in README
23
+
24
+ ### Features
25
+ - Token-based authentication with automatic expiration handling
26
+ - Username/password authentication
27
+ - Request timeout handling with AbortController
28
+ - Automatic retry on transient failures (5xx errors)
29
+ - Automatic re-authentication on 401 errors
30
+ - Support for query parameters in GET requests
31
+ - Structured error handling with status codes
32
+
33
+ [1.0.0]: https://github.com/CRA-Risk-Management/sdk-js/releases/tag/v1.0.0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 CRA Risk Management
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,413 @@
1
+ # CRA Risk Management SDK for JavaScript
2
+
3
+ A comprehensive JavaScript SDK for interacting with the CRA Risk Management API. This SDK provides a simple and intuitive interface for managing municipalities, critical points, users, and related resources.
4
+
5
+ ## Installation
6
+
7
+ Install the package via npm:
8
+
9
+ ```bash
10
+ npm install @cra-risk-management/sdk-js
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ### CommonJS
16
+
17
+ ```javascript
18
+ const Client = require('@cra-risk-management/sdk-js');
19
+
20
+ // Initialize the client
21
+ const client = new Client({
22
+ baseURL: 'https://your-api-url.com',
23
+ username: 'your-username',
24
+ password: 'your-password'
25
+ });
26
+
27
+ // Authenticate (happens automatically when needed)
28
+ await client.login('username', 'password');
29
+
30
+ // Use resource clients
31
+ const municipalities = await client.municipalities.list();
32
+ console.log(municipalities);
33
+ ```
34
+
35
+ ### ES Modules
36
+
37
+ ```javascript
38
+ import Client from '@cra-risk-management/sdk-js';
39
+
40
+ // Initialize the client
41
+ const client = new Client({
42
+ baseURL: 'https://your-api-url.com',
43
+ username: 'your-username',
44
+ password: 'your-password'
45
+ });
46
+
47
+ // Authenticate (happens automatically when needed)
48
+ await client.login('username', 'password');
49
+
50
+ // Use resource clients
51
+ const municipalities = await client.municipalities.list();
52
+ console.log(municipalities);
53
+ ```
54
+
55
+ ## Authentication
56
+
57
+ The SDK supports two authentication methods:
58
+
59
+ ### 1. Username and Password
60
+
61
+ ```javascript
62
+ const client = new Client({
63
+ baseURL: 'https://your-api-url.com',
64
+ username: 'your-username',
65
+ password: 'your-password'
66
+ });
67
+
68
+ // Login explicitly
69
+ await client.login('username', 'password');
70
+
71
+ // Or set credentials and let the SDK authenticate automatically
72
+ client.setCredentials('username', 'password');
73
+ ```
74
+
75
+ ### 2. Token-based Authentication
76
+
77
+ ```javascript
78
+ const client = new Client({
79
+ baseURL: 'https://your-api-url.com'
80
+ });
81
+
82
+ // Set token directly (if you already have one)
83
+ client.setToken('your-access-token', 3600); // token and expiry in seconds
84
+ ```
85
+
86
+ The SDK automatically handles token expiration and re-authentication when using username/password credentials.
87
+
88
+ ## Configuration Options
89
+
90
+ When creating a new client instance, you can provide the following options:
91
+
92
+ ```javascript
93
+ const client = new Client({
94
+ baseURL: 'https://your-api-url.com', // Required: Base URL of the API
95
+ username: 'user', // Optional: Username for authentication
96
+ password: 'pass', // Optional: Password for authentication
97
+ authEndpoint: '/users/token', // Optional: Custom auth endpoint (default: /users/token)
98
+ timeout: 30000, // Optional: Request timeout in ms (default: 30000)
99
+ maxRetries: 1 // Optional: Max retry attempts (default: 1)
100
+ });
101
+ ```
102
+
103
+ ## API Reference
104
+
105
+ ### Client Methods
106
+
107
+ #### Authentication Methods
108
+
109
+ - **`login(username, password)`** - Authenticate with username and password
110
+ ```javascript
111
+ const token = await client.login('username', 'password');
112
+ ```
113
+
114
+ - **`logout()`** - Clear credentials and token
115
+ ```javascript
116
+ client.logout();
117
+ ```
118
+
119
+ - **`setCredentials(username, password)`** - Set credentials without authenticating
120
+ ```javascript
121
+ client.setCredentials('username', 'password');
122
+ ```
123
+
124
+ - **`setToken(token, expiresIn)`** - Set token directly
125
+ ```javascript
126
+ client.setToken('your-token', 3600);
127
+ ```
128
+
129
+ - **`isAuthenticated()`** - Check if client has a valid token
130
+ ```javascript
131
+ if (client.isAuthenticated()) {
132
+ // Client is authenticated
133
+ }
134
+ ```
135
+
136
+ #### HTTP Methods
137
+
138
+ - **`get(endpoint, params)`** - Make a GET request
139
+ ```javascript
140
+ const data = await client.get('/municipalities/items', { limit: 10 });
141
+ ```
142
+
143
+ - **`post(endpoint, data)`** - Make a POST request
144
+ ```javascript
145
+ const result = await client.post('/municipalities', { name: 'New Municipality' });
146
+ ```
147
+
148
+ - **`patch(endpoint, data)`** - Make a PATCH request
149
+ ```javascript
150
+ const updated = await client.patch('/municipalities/items/1', { name: 'Updated Name' });
151
+ ```
152
+
153
+ - **`delete(endpoint)`** - Make a DELETE request
154
+ ```javascript
155
+ await client.delete('/municipalities/items/1');
156
+ ```
157
+
158
+ - **`confirm(endpoint, id)`** - Confirm a resource
159
+ ```javascript
160
+ await client.confirm('/critical_points', 123);
161
+ ```
162
+
163
+ ### Resource Clients
164
+
165
+ #### Municipalities
166
+
167
+ Access via `client.municipalities`:
168
+
169
+ - **`list(params)`** - List all municipalities
170
+ ```javascript
171
+ const municipalities = await client.municipalities.list({ limit: 10 });
172
+ ```
173
+
174
+ - **`get(id, params)`** - Get a municipality by ID
175
+ ```javascript
176
+ const municipality = await client.municipalities.get(1);
177
+ ```
178
+
179
+ - **`create(data)`** - Create a new municipality
180
+ ```javascript
181
+ const newMunicipality = await client.municipalities.create({
182
+ name: 'New Municipality',
183
+ code: 'NM001'
184
+ });
185
+ ```
186
+
187
+ - **`update(id, data)`** - Update a municipality
188
+ ```javascript
189
+ const updated = await client.municipalities.update(1, { name: 'Updated Name' });
190
+ ```
191
+
192
+ - **`delete(id)`** - Delete a municipality
193
+ ```javascript
194
+ await client.municipalities.delete(1);
195
+ ```
196
+
197
+ #### Critical Points
198
+
199
+ Access via `client.criticalPoints`:
200
+
201
+ - **`list(params)`** - List all critical points
202
+ ```javascript
203
+ const points = await client.criticalPoints.list({
204
+ event_type_id: 1,
205
+ municipality_id: 5,
206
+ confirmed: true
207
+ });
208
+ ```
209
+
210
+ - **`get(id, params)`** - Get a critical point by ID
211
+ ```javascript
212
+ const point = await client.criticalPoints.get(123);
213
+ ```
214
+
215
+ - **`create(data)`** - Create a new critical point
216
+ ```javascript
217
+ const newPoint = await client.criticalPoints.create({
218
+ name: 'Critical Point 1',
219
+ latitude: 40.7128,
220
+ longitude: -74.0060
221
+ });
222
+ ```
223
+
224
+ - **`update(id, data)`** - Update a critical point
225
+ ```javascript
226
+ const updated = await client.criticalPoints.update(123, { confirmed: true });
227
+ ```
228
+
229
+ - **`delete(id)`** - Delete a critical point
230
+ ```javascript
231
+ await client.criticalPoints.delete(123);
232
+ ```
233
+
234
+ ##### Critical Point Attributes
235
+
236
+ Access nested attribute resources via `client.criticalPoints.attributes`:
237
+
238
+ **Event Zones** - `client.criticalPoints.attributes.eventZones`
239
+ - `list(params)` - List event zones
240
+ - `get(id, params)` - Get event zone by ID
241
+ - `create(data)` - Create event zone
242
+ - `update(id, data)` - Update event zone
243
+ - `delete(id)` - Delete event zone
244
+
245
+ **Event Types** - `client.criticalPoints.attributes.eventTypes`
246
+ - `list(params)` - List event types
247
+ - `get(id, params)` - Get event type by ID
248
+ - `create(data)` - Create event type
249
+ - `update(id, data)` - Update event type
250
+ - `delete(id)` - Delete event type
251
+
252
+ **Observations** - `client.criticalPoints.attributes.observations`
253
+ - `list(params)` - List observations
254
+ - `get(id, params)` - Get observation by ID
255
+ - `create(data)` - Create observation
256
+ - `update(id, data)` - Update observation
257
+ - `delete(id)` - Delete observation
258
+
259
+ #### Users
260
+
261
+ Access via `client.users`:
262
+
263
+ - **`list(params)`** - List all users
264
+ ```javascript
265
+ const users = await client.users.list();
266
+ ```
267
+
268
+ - **`get(id, params)`** - Get a user by ID
269
+ ```javascript
270
+ const user = await client.users.get(1);
271
+ ```
272
+
273
+ - **`create(data)`** - Create a new user
274
+ ```javascript
275
+ const newUser = await client.users.create({
276
+ username: 'newuser',
277
+ email: 'newuser@example.com'
278
+ });
279
+ ```
280
+
281
+ - **`update(id, data)`** - Update a user
282
+ ```javascript
283
+ const updated = await client.users.update(1, { email: 'newemail@example.com' });
284
+ ```
285
+
286
+ - **`delete(id)`** - Delete a user
287
+ ```javascript
288
+ await client.users.delete(1);
289
+ ```
290
+
291
+ ## Examples
292
+
293
+ ### Complete Usage Example
294
+
295
+ ```javascript
296
+ const Client = require('@cra-risk-management/sdk-js');
297
+
298
+ async function main() {
299
+ // Initialize client
300
+ const client = new Client({
301
+ baseURL: 'https://api.example.com',
302
+ username: 'your-username',
303
+ password: 'your-password',
304
+ timeout: 30000
305
+ });
306
+
307
+ try {
308
+ // Authenticate
309
+ await client.login('username', 'password');
310
+ console.log('Authenticated successfully');
311
+
312
+ // List municipalities
313
+ const municipalities = await client.municipalities.list({ limit: 5 });
314
+ console.log('Municipalities:', municipalities);
315
+
316
+ // Create a critical point
317
+ const newPoint = await client.criticalPoints.create({
318
+ name: 'Flood Risk Area',
319
+ latitude: 40.7128,
320
+ longitude: -74.0060,
321
+ event_type_id: 1,
322
+ municipality_id: 5
323
+ });
324
+ console.log('Created critical point:', newPoint);
325
+
326
+ // Update the critical point
327
+ const updated = await client.criticalPoints.update(newPoint.id, {
328
+ confirmed: true
329
+ });
330
+ console.log('Updated critical point:', updated);
331
+
332
+ // List event zones
333
+ const eventZones = await client.criticalPoints.attributes.eventZones.list();
334
+ console.log('Event zones:', eventZones);
335
+
336
+ } catch (error) {
337
+ console.error('Error:', error.message);
338
+ } finally {
339
+ // Logout when done
340
+ client.logout();
341
+ }
342
+ }
343
+
344
+ main();
345
+ ```
346
+
347
+ ### Error Handling
348
+
349
+ ```javascript
350
+ try {
351
+ const municipalities = await client.municipalities.list();
352
+ } catch (error) {
353
+ if (error.status === 404) {
354
+ console.error('Resource not found');
355
+ } else if (error.status === 401) {
356
+ console.error('Authentication failed');
357
+ } else if (error.status >= 500) {
358
+ console.error('Server error');
359
+ } else {
360
+ console.error('Error:', error.message);
361
+ }
362
+ }
363
+ ```
364
+
365
+ ### Using Query Parameters
366
+
367
+ ```javascript
368
+ // List with filtering
369
+ const filteredPoints = await client.criticalPoints.list({
370
+ event_type_id: 1,
371
+ municipality_id: 5,
372
+ confirmed: true,
373
+ from_datetime: '2025-01-01',
374
+ to_datetime: '2025-12-31'
375
+ });
376
+
377
+ // List with pagination
378
+ const paginatedMunicipalities = await client.municipalities.list({
379
+ limit: 20,
380
+ offset: 40
381
+ });
382
+ ```
383
+
384
+ ## Requirements
385
+
386
+ - Node.js >= 14.0.0
387
+ - npm or yarn package manager
388
+
389
+ ## License
390
+
391
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
392
+
393
+ ## Contributing
394
+
395
+ Contributions are welcome! Please feel free to submit a Pull Request.
396
+
397
+ ### Development Setup
398
+
399
+ 1. Clone the repository
400
+ 2. Install dependencies: `npm install`
401
+ 3. Run tests: `npm test`
402
+ 4. Run tests in watch mode: `npm run test:watch`
403
+ 5. Generate coverage report: `npm run test:coverage`
404
+
405
+ ## Support
406
+
407
+ For issues, questions, or contributions, please visit:
408
+ - GitHub Issues: https://github.com/CRA-Risk-Management/sdk-js/issues
409
+ - GitHub Repository: https://github.com/CRA-Risk-Management/sdk-js
410
+
411
+ ---
412
+
413
+ Made with ❤️ by CRA Risk Management
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@cra-risk-management/sdk",
3
+ "version": "1.0.0",
4
+ "description": "Software Development Kit for JS apps - CRA Risk Management API Client",
5
+ "main": "src/client.js",
6
+ "keywords": [
7
+ "sdk",
8
+ "api",
9
+ "client",
10
+ "cra",
11
+ "risk-management"
12
+ ],
13
+ "author": "CRA Risk Management",
14
+ "license": "MIT",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/CRA-Risk-Management/sdk-js.git"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/CRA-Risk-Management/sdk-js/issues"
21
+ },
22
+ "homepage": "https://github.com/CRA-Risk-Management/sdk-js#readme",
23
+ "files": [
24
+ "src/",
25
+ "LICENSE",
26
+ "README.md",
27
+ "CHANGELOG.md"
28
+ ],
29
+ "engines": {
30
+ "node": ">=14.0.0"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "devDependencies": {
36
+ "node-fetch": "^2.7.0"
37
+ }
38
+ }
package/src/client.js ADDED
@@ -0,0 +1,281 @@
1
+ const UsersClient = require("../src/resources/users");
2
+ const MunicipalitiesClient = require("../src/resources/municipalities");
3
+ const CriticalPointsClient = require("../src/resources/criticalPoints");
4
+
5
+ class Client {
6
+ /**
7
+ * @param {Object} options
8
+ * @param {string} options.baseURL
9
+ * @param {number} [options.timeout]
10
+ * @param {string} [options.username]
11
+ * @param {string} [options.password]
12
+ * @param {string} [options.authEndpoint]
13
+ * @param {number} [options.maxRetries]
14
+ */
15
+
16
+ constructor(options = {}) {
17
+ this.baseURL = options.baseURL;
18
+ this.authEndpoint = options.authEndpoint || "/users/token"
19
+ this.timeout = options.timeout || 30000;
20
+ this.maxRetries = options.maxRetries || 1;
21
+
22
+ this.username = options.username || null;
23
+ this.password = options.password || null;
24
+
25
+ this.token = null;
26
+ this.tokenExpiry = null;
27
+
28
+ this.defaultHeaders = {
29
+ "Content-Type": "application/json",
30
+ };
31
+
32
+ this.municipalities = new MunicipalitiesClient(this);
33
+ this.criticalPoints = new CriticalPointsClient(this);
34
+ this.users = new UsersClient(this);
35
+ }
36
+
37
+ /**
38
+ * Authenticate
39
+ * @returns {Promise<string>} Access Token
40
+ */
41
+ async authenticate() {
42
+ if (!this.username || !this.password) {
43
+ throw new Error("Username and password are required");
44
+ }
45
+
46
+ try {
47
+ const response = await fetch(`${this.baseURL}${this.authEndpoint}`, {
48
+ method: "POST",
49
+ headers: {
50
+ "Content-Type": "application/x-www-form-urlencoded",
51
+ },
52
+ body: new URLSearchParams({
53
+ username: this.username,
54
+ password: this.password,
55
+ }),
56
+ });
57
+
58
+ if (!response.ok) {
59
+ const error = await response.json().catch(() => ({}));
60
+ throw new Error(error.message || "Authentication failed");
61
+ }
62
+
63
+ const data = await response.json();
64
+ this.token = data.access_token || data.token;
65
+ if (!this.token) {
66
+ throw new Error("No token received from authentication endpoint");
67
+ }
68
+
69
+ const expiresIn = data.expires_in || 3600;
70
+ this.tokenExpiry = Date.now() + (expiresIn * 1000);
71
+
72
+ return this.token;
73
+ } catch (error) {
74
+ throw new Error(`Authentication error ${error.message}`);
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Check if token is valid.
80
+ * @returns {boolean}
81
+ */
82
+ isAuthenticated() {
83
+ if (!this.token) return false;
84
+ if (!this.tokenExpiry) return true;
85
+ return Date.now() < this.tokenExpiry;
86
+ }
87
+
88
+ /**
89
+ * Ensures client is authenticated.
90
+ * @private
91
+ */
92
+ async ensureAuthenticated() {
93
+ if (!this.isAuthenticated()) {
94
+ await this.authenticate();
95
+ }
96
+ }
97
+
98
+ /**
99
+ * HTTP request
100
+ * @private
101
+ */
102
+ async _request(endpoint, options = {}, retryCount = 0) {
103
+ let url = `${this.baseURL}${endpoint}`
104
+ const config = {
105
+ method: options.method || "GET",
106
+ headers: {
107
+ ...this.defaultHeaders,
108
+ ...options.headers,
109
+ }
110
+ }
111
+
112
+ if (options.body) {
113
+ config.body = options.body;
114
+ }
115
+
116
+ const requiresAuth = ['POST', 'PATCH', 'DELETE'].includes(options.method);
117
+ if (requiresAuth) {
118
+ await this.ensureAuthenticated();
119
+ config.headers["Authorization"] = `Bearer ${this.token}`;
120
+ }
121
+
122
+ if (options.params) {
123
+ const queryString = new URLSearchParams(options.params).toString();
124
+ url = queryString ? `${url}?${queryString}` : url;
125
+ }
126
+
127
+ const controller = new AbortController();
128
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
129
+ config.signal = controller.signal;
130
+
131
+ try {
132
+ const response = await fetch(url, config);
133
+ clearTimeout(timeoutId);
134
+
135
+ if (!response.ok) {
136
+ const error = await response.json().catch(() => ({}));
137
+ if (response.status === 401 && requiresAuth && retryCount < this.maxRetries) {
138
+ this.token = null;
139
+ await this.ensureAuthenticated();
140
+ config.headers["Authorization"] = `Bearer ${this.token}`;
141
+
142
+ return this._request(endpoint, options, retryCount + 1);
143
+ }
144
+
145
+ throw this._createError(response.status, error.message || response.statusText, error);
146
+ }
147
+
148
+ return await response.json();
149
+ } catch (error) {
150
+ if (error.name === "AbortError") {
151
+ throw new Error("Request timeout");
152
+ }
153
+ if (retryCount < this.maxRetries && this._isRetryableError(error)) {
154
+ await this._delay(Math.pow(2, retryCount) * 1000);
155
+ return this._request(endpoint, options, retryCount + 1);
156
+ }
157
+
158
+ throw error;
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Create structured error
164
+ * @private
165
+ */
166
+ _createError(status, message, data) {
167
+ const error = new Error(message);
168
+ error.status = status;
169
+ error.data = data;
170
+ return error;
171
+ }
172
+
173
+ /**
174
+ * Check if error is retryable
175
+ * @private
176
+ */
177
+ _isRetryableError(error) {
178
+ return (
179
+ error.name === "AbortError" ||
180
+ error.message.includes("fetch") ||
181
+ (error.status >= 500 && error.status < 600)
182
+ );
183
+ }
184
+
185
+ /**
186
+ * Delay helper for retry backoff
187
+ * @private
188
+ */
189
+ _delay(ms) {
190
+ return new Promise(resolve => setTimeout(resolve, ms));
191
+ }
192
+
193
+ /**
194
+ * Login with username and password
195
+ * @param {string} username
196
+ * @param {string} password
197
+ * @returns {Promise<string>} Access token
198
+ */
199
+ async login(username, password) {
200
+ this.username = username;
201
+ this.password = password;
202
+ return await this.authenticate();
203
+ }
204
+
205
+ /**
206
+ * Logout (clear credentials and token)
207
+ */
208
+ logout() {
209
+ this.username = null;
210
+ this.password = null;
211
+ this.token = null;
212
+ this.tokenExpiry = null;
213
+ }
214
+
215
+ /**
216
+ * Set credentials without authenticating
217
+ * @param {string} username
218
+ * @param {string} password
219
+ */
220
+ setCredentials(username, password) {
221
+ this.username = username;
222
+ this.password = password;
223
+ }
224
+
225
+ /**
226
+ * Set token directly (if you already have one)
227
+ * @param {string} token
228
+ * @param {number} [expiresIn] - Expiry in seconds
229
+ */
230
+ setToken(token, expiresIn = 3600) {
231
+ this.token = token;
232
+ this.tokenExpiry = Date.now() + (expiresIn * 1000);
233
+ }
234
+
235
+ /**
236
+ * GET request
237
+ * @param {string} endpoint
238
+ * @param {Object} [params]
239
+ */
240
+ async get(endpoint, params = {}) {
241
+ return this._request(endpoint, {method: "GET", params});
242
+ }
243
+
244
+ /**
245
+ * POST request
246
+ * @param {string} endpoint
247
+ * @param {Object} [params]
248
+ */
249
+ async post(endpoint, data) {
250
+ return this._request(`${endpoint}/`, {method: "POST", body: JSON.stringify(data)})
251
+ }
252
+
253
+ /**
254
+ * PATCH request
255
+ * @param {string} endpoint
256
+ * @param {Object} data
257
+ */
258
+ async patch(endpoint, data) {
259
+ return this._request(endpoint, {method: "PATCH", body: JSON.stringify(data)})
260
+ }
261
+
262
+ /**
263
+ * DELETE request
264
+ * @param {string} endpoint
265
+ */
266
+ async delete(endpoint) {
267
+ return this._request(endpoint, {method: "DELETE"});
268
+ }
269
+
270
+ /**
271
+ * Special request to confirm data
272
+ * @param {string} endpoint
273
+ * @param {number} id
274
+ */
275
+ async confirm(endpoint, id) {
276
+ let url = `${endpoint}/items/${id}/confirm`;
277
+ return this._request(url, {method: "PATCH"});
278
+ }
279
+ }
280
+
281
+ module.exports = Client;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @typedef {Object} CriticalPointCreate
3
+ * @property {string} description
4
+ * @property {number} municipality_id
5
+ * @property {number} event_type_id
6
+ * @property {number} event_zone_id
7
+ * @property {number} [user_id]
8
+ * @property {string} [image_id]
9
+ * @property {Date} [datetime]
10
+ * @property {number} [confirmed=0]
11
+ * @property {string} geometry
12
+ */
13
+
14
+ /**
15
+ * @typedef {Object} CriticalPoint
16
+ * @property {number} id
17
+ * @property {string} description
18
+ * @property {number} municipality_id
19
+ * @property {number} event_type_id
20
+ * @property {number} event_zone_id
21
+ * @property {number} user_id
22
+ * @property {string} image_id
23
+ * @property {Date} datetime
24
+ * @property {number} confirmed
25
+ * @property {string} geometry
26
+ */
27
+
28
+ /**
29
+ * @typedef {Object} CriticalPointUpdate
30
+ * @property {string} [description]
31
+ * @property {number} [municipality_id]
32
+ * @property {number} [event_type_id]
33
+ * @property {number} [event_zone_id]
34
+ * @property {number} [user_id]
35
+ * @property {string} [image_id]
36
+ * @property {Date} [datetime]
37
+ * @property {number} [confirmed]
38
+ * @property {string} [geometry]
39
+ */
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @typedef {Object} EventTypeCreate
3
+ * @property {string} event_type
4
+ * @property {string} icon
5
+ * @property {string} color
6
+ */
7
+
8
+ /**
9
+ * @typedef {Object} EventType
10
+ * @property {number} id
11
+ * @property {string} event_type
12
+ * @property {string} icon
13
+ * @property {string} color
14
+ */
15
+
16
+ /**
17
+ * @typedef {Object} EventTypeUpdate
18
+ * @property {string} [event_type]
19
+ * @property {string} [icon]
20
+ * @property {string} [color]
21
+ */
22
+
23
+ module.exports = {}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @typedef {Object} EventZoneCreate
3
+ * @property {string} event_zone
4
+ * @property {string} icon
5
+ * @property {string} color
6
+ */
7
+
8
+ /**
9
+ * @typedef {Object} EventZone
10
+ * @property {number} id
11
+ * @property {string} event_zone
12
+ * @property {string} icon
13
+ * @property {string} color
14
+ */
15
+
16
+ /**
17
+ * @typedef {Object} EventZoneUpdate
18
+ * @property {string} [event_zone]
19
+ * @property {string} [icon]
20
+ * @property {string} [color]
21
+ */
22
+
23
+ module.exports = {}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @typedef {Object} MunicipalityCreate
3
+ * @property {string} name
4
+ * @property {string} geometry
5
+ */
6
+
7
+ /**
8
+ * @typedef {Object} Municipality
9
+ * @property {number} id
10
+ * @property {string} name
11
+ * @property {string} geometry
12
+ */
13
+
14
+ /**
15
+ * @typedef {Object} MunicipalityUpdate
16
+ * @property {string} [name]
17
+ * @property {string} [geometry]
18
+ */
19
+
20
+ module.exports = {}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @typedef {Object} ObservationCreate
3
+ * @property {string} information
4
+ * @property {string} critical_point_id
5
+ * @property {string} [image_id]
6
+ * @property {Date} [datetime]
7
+ * @property {number} [confirmed=0]
8
+ */
9
+
10
+ /**
11
+ * @typedef {Object} Observation
12
+ * @property {number} id
13
+ * @property {string} information
14
+ * @property {string} critical_point_id
15
+ * @property {string} image_id
16
+ * @property {Date} datetime
17
+ * @property {number} confirmed
18
+ */
19
+
20
+ /**
21
+ * @typedef {Object} ObservationUpdate
22
+ * @property {string} [information]
23
+ * @property {string} [critical_point_id]
24
+ * @property {string} [image_id]
25
+ * @property {Date} [datetime]
26
+ * @property {number} [confirmed]
27
+ */
28
+
29
+ module.exports = {}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @typedef UserCreate
3
+ * @param {string} username
4
+ * @param {string} password
5
+ * @param {string} type
6
+ */
7
+
8
+ /**
9
+ * @typedef User
10
+ * @param {number} id
11
+ * @param {string} username
12
+ * @param {string} password
13
+ * @param {string} type
14
+ */
15
+
16
+ /**
17
+ * @typedef UserUpdate
18
+ * @param {string} [username]
19
+ * @param {string} [password]
20
+ * @param {string} [type]
21
+ */
22
+
23
+ module.exports = {}
@@ -0,0 +1,236 @@
1
+ class CriticalPoints {
2
+ constructor(client) {
3
+ this.client = client;
4
+ this.endpoint = "/critical_points";
5
+ this.attributes = new CriticalPointAttributes(client);
6
+ }
7
+
8
+ /**
9
+ * List all critical points.
10
+ * @param {Object} [params]
11
+ * @param {number} [params.event_type_id]
12
+ * @param {number} [params.event_zone_id]
13
+ * @param {number} [params.municipality_id]
14
+ * @param {number} [params.user_id]
15
+ * @param {boolean} [params.confirmed]
16
+ * @param {Date} [params.from_datetime]
17
+ * @param {Date} [params.to_datetime]
18
+ * @returns {Promise<import("../models/criticalPoints").CriticalPoint[]>}
19
+ */
20
+ async list(params = {}) {
21
+ return this.client.get(`${this.endpoint}/items`, params);
22
+ }
23
+
24
+ /**
25
+ * Get one critical point by its ID.
26
+ * @param {number} id
27
+ * @param {Object} params
28
+ * @returns {Promise<import("../models/criticalPoints").CriticalPoint>}
29
+ */
30
+ async get(id, params = {}) {
31
+ return this.client.get(`${this.endpoint}/items/${id}`, params);
32
+ }
33
+
34
+ /**
35
+ * Create a critical point instance.
36
+ * @param {import("../models/criticalPoints").CriticalPointCreate} data
37
+ * @returns {Promise<import("../models/criticalPoints").CriticalPoint>}
38
+ */
39
+ async create(data) {
40
+ return this.client.post(this.endpoint, data);
41
+ }
42
+
43
+ /**
44
+ * Patch critical point.
45
+ * @param {number} id
46
+ * @param {import("../models/criticalPoints").CriticalPointUpdate} data
47
+ * @returns {Promise<import("../models/criticalPoints").CriticalPoint>}
48
+ */
49
+ async update(id, data) {
50
+ return this.client.patch(`${this.endpoint}/items/${id}`, data);
51
+ }
52
+
53
+ /**
54
+ * Delete a critical point.
55
+ * @param {number} id
56
+ * @returns {Promise<void>}
57
+ */
58
+ async delete(id) {
59
+ return this.client.delete(`${this.endpoint}/items/${id}`);
60
+ }
61
+ }
62
+
63
+ class CriticalPointAttributes {
64
+ constructor(client) {
65
+ this.client = client;
66
+ this.endpoint = "/critical_points/attributes";
67
+ this.eventZones = new EventZoneAttribute(client, this.endpoint);
68
+ this.eventTypes = new EventTypeAttribute(client, this.endpoint);
69
+ this.observations = new ObservationAttribute(client, this.endpoint);
70
+ }
71
+ }
72
+
73
+ class EventZoneAttribute {
74
+ constructor(client, parentEndpoint) {
75
+ this.client = client;
76
+ this.endpoint = `${parentEndpoint}/event_zones`;
77
+ }
78
+
79
+ /**
80
+ * Get all event zones.
81
+ * @param {Object} [params]
82
+ * @returns {promise<import("../models/eventZones").EventZone[]>}
83
+ */
84
+ async list(params = {}) {
85
+ return this.client.get(`${this.endpoint}/items`, params);
86
+ }
87
+
88
+ /**
89
+ * Get one event zone by its ID.
90
+ * @param {number} id
91
+ * @param {object} [params]
92
+ * @returns {Promise<import("../models/eventZones").EventZone>}
93
+ */
94
+ async get(id, params = {}) {
95
+ return this.client.get(`${this.endpoint}/items/${id}`, params);
96
+ }
97
+
98
+ /**
99
+ * Create an event zone instance.
100
+ * @param {import("../models/eventZones").EventZoneCreate} data
101
+ * @returns {Promise<import("../models/eventZones").EventZone>}
102
+ */
103
+ async create(data) {
104
+ return this.client.post(this.endpoint, data);
105
+ }
106
+
107
+ /**
108
+ * Update event zone.
109
+ * @param {number} id
110
+ * @param {import("../models/eventZones").EventZoneUpdate} data
111
+ * @returns {Promise<import("../models/eventZones").EventZone>}
112
+ */
113
+ async update(id, data) {
114
+ return this.client.patch(`${this.endpoint}/items/${id}`, data);
115
+ }
116
+
117
+ /**
118
+ * Delete event zone by ID.
119
+ * @param {number} id
120
+ * @returns {Promise<void>}
121
+ */
122
+ async delete(id) {
123
+ return this.client.delete(`${this.endpoint}/items/${id}`);
124
+ }
125
+ }
126
+
127
+ class EventTypeAttribute {
128
+ constructor(client, parentEndpoint) {
129
+ this.client = client;
130
+ this.endpoint = `${parentEndpoint}/event_types`;
131
+ }
132
+
133
+ /**
134
+ * List all event types.
135
+ * @param {Object} [params]
136
+ * @returns {Promise<import("../models/eventTypes").EventType[]>}
137
+ */
138
+ async list(params = {}) {
139
+ return this.client.get(`${this.endpoint}/items`, params);
140
+ }
141
+
142
+ /**
143
+ * Get one event type by its ID.
144
+ * @param {number} id
145
+ * @param {Object} [params]
146
+ * @returns {Promise<import("../models/eventTypes").EventType>}
147
+ */
148
+ async get(id, params = {}) {
149
+ return this.client.get(`${this.endpoint}/items/${id}`, params);
150
+ }
151
+
152
+ /**
153
+ * Create event type instance.
154
+ * @param {import("../models/eventTypes").EventTypeCreate} data
155
+ * @returns {Promise<import("../models/eventTypes").EventType>}
156
+ */
157
+ async create(data) {
158
+ return this.client.post(this.endpoint, data);
159
+ }
160
+
161
+ /**
162
+ * Update event type.
163
+ * @param {number} id
164
+ * @param {import("../models/eventTypes").EventTypeUpdate} data
165
+ * @returns {Promise<import("../models/eventTypes").EventType>}
166
+ */
167
+ async update(id, data) {
168
+ return this.client.patch(`${this.endpoint}/items/${id}`, data);
169
+ }
170
+
171
+ /**
172
+ * Delete event type instance.
173
+ * @param {number} id
174
+ * @returns {Promise<void>}
175
+ */
176
+ async delete(id) {
177
+ return this.client.delete(`${this.endpoint}/items/${id}`);
178
+ }
179
+ }
180
+
181
+ class ObservationAttribute {
182
+ constructor(client, parentEndpoint) {
183
+ this.client = client;
184
+ this.endpoint = `${parentEndpoint}/observations`;
185
+ }
186
+
187
+ /**
188
+ * List observations.
189
+ * @param {Object} [params]
190
+ * @param {number} [params.critical_point_id]
191
+ * @returns {Promise<import("../models/observations").Observation[]>}
192
+ */
193
+ async list(params = {}) {
194
+ return this.client.get(`${this.endpoint}/items`, params);
195
+ }
196
+
197
+ /**
198
+ * Get one observation by ID.
199
+ * @param {number} id
200
+ * @param {Object} [params]
201
+ * @returns {Promise<import("../models/observations").Observation>}
202
+ */
203
+ async get(id, params = {}) {
204
+ return this.client.get(`${this.endpoint}/items/${id}`, params);
205
+ }
206
+
207
+ /**
208
+ * Create observation instance.
209
+ * @param {import("../models/observations").ObservationCreate} data
210
+ * @returns {Promise<import("../models/observations").Observation>}
211
+ */
212
+ async create(data) {
213
+ return this.client.post(this.endpoint, data);
214
+ }
215
+
216
+ /**
217
+ * Update observation instance.
218
+ * @param {number} id
219
+ * @param {import("../models/observations").ObservationUpdate} data
220
+ * @returns {Promise<import("../models/observations").Observation>}
221
+ */
222
+ async update(id, data) {
223
+ return this.client.patch(`${this.endpoint}/items/${id}`, data);
224
+ }
225
+
226
+ /**
227
+ * Delete observation.
228
+ * @param {number} id
229
+ * @returns {Promise<void>}
230
+ */
231
+ async delete(id) {
232
+ return this.client.delete(`${this.endpoint}/items/${id}`);
233
+ }
234
+ }
235
+
236
+ module.exports = CriticalPoints;
@@ -0,0 +1,58 @@
1
+ class Municipalities {
2
+ /**
3
+ * @param {import("../client")} client
4
+ */
5
+ constructor(client) {
6
+ this.client = client;
7
+ this.endpoint = "/cartography/municipalities";
8
+ }
9
+
10
+ /**
11
+ * List all municipalities.
12
+ * @param {Object} [params]
13
+ * @returns {Promise<import("../models/municipalities").Municipality[]>}
14
+ */
15
+ async list(params = {}) {
16
+ return this.client.get(`${this.endpoint}/items`, params);
17
+ }
18
+
19
+ /**
20
+ * Get a municipality instance by id.
21
+ * @param {number} id
22
+ * @param {Object} [params]
23
+ * @returns {Promise<import("../models/municipalities").Municipality>}
24
+ */
25
+ async get(id, params = {}) {
26
+ return this.client.get(`${this.endpoint}/items/${id}`, params)
27
+ }
28
+
29
+ /**
30
+ * Create a municipality instance.
31
+ * @param {import("../models/municipalities").MunicipalityCreate} data
32
+ * @returns {Promise<import("../models/municipalities").Municipality>}
33
+ */
34
+ async create(data) {
35
+ return this.client.post(this.endpoint, data)
36
+ }
37
+
38
+ /**
39
+ * Update a municipality instance.
40
+ * @param {number} id
41
+ * @param {import("../models/municipalities").MunicipalityUpdate} data
42
+ * @returns {Promise<import("../models/municipalities").Municipality>}
43
+ */
44
+ async update(id, data) {
45
+ return this.client.patch(`${this.endpoint}/items/${id}`, data)
46
+ }
47
+
48
+ /**
49
+ * Delete municipality instance.
50
+ * @param {number} id
51
+ * @returns {Promise<void>}
52
+ */
53
+ async delete(id) {
54
+ return this.client.delete(`${this.endpoint}/items/${id}`)
55
+ }
56
+ }
57
+
58
+ module.exports = Municipalities;
@@ -0,0 +1,58 @@
1
+ class Users {
2
+ /**
3
+ * @param {import("../client")} client
4
+ */
5
+ constructor(client) {
6
+ this.client = client;
7
+ this.endpoint = "/users";
8
+ }
9
+
10
+ /**
11
+ * Get all Users.
12
+ * @param {Object} params
13
+ * @returns {Promise<import("../models/users").User[]>}
14
+ */
15
+ async list(params = {}) {
16
+ return this.client.get(`${this.endpoint}/items`, params);
17
+ }
18
+
19
+ /**
20
+ * Get one User by ID.
21
+ * @param {number} id
22
+ * @param {Object} params
23
+ * @returns {Promise<import("../models/users").User>}
24
+ */
25
+ async get(id, params = {}) {
26
+ return this.client.get(`${this.endpoint}/items/${id}`, params);
27
+ }
28
+
29
+ /**
30
+ * Create an User instance
31
+ * @param {import("../models/users").UserCreate} data
32
+ * @returns {Promise<import("../models/users").User>}
33
+ */
34
+ async create(data) {
35
+ return this.client.post(this.endpoint, data);
36
+ }
37
+
38
+ /**
39
+ * Update User instance.
40
+ * @param {number} id
41
+ * @param {import("../models/users").UserUpdate} data
42
+ * @returns {Promise<import("../models/users").User}
43
+ */
44
+ async update(id, data) {
45
+ return this.client.patch(`${this.endpoint}/items/${id}`, data);
46
+ }
47
+
48
+ /**
49
+ * Delete user instance.
50
+ * @param {number} id
51
+ * @returns {Promise<void>}
52
+ */
53
+ async delete(id) {
54
+ return this.client.delete(`${this.endpoint}/items/${id}`);
55
+ }
56
+ }
57
+
58
+ module.exports = Users;