@villedemontreal/http-request 7.4.4
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/LICENSE +21 -0
- package/README.md +216 -0
- package/dist/src/config/configs.d.ts +38 -0
- package/dist/src/config/configs.js +63 -0
- package/dist/src/config/configs.js.map +1 -0
- package/dist/src/config/constants.d.ts +40 -0
- package/dist/src/config/constants.js +40 -0
- package/dist/src/config/constants.js.map +1 -0
- package/dist/src/config/init.d.ts +22 -0
- package/dist/src/config/init.js +50 -0
- package/dist/src/config/init.js.map +1 -0
- package/dist/src/httpUtils.d.ts +131 -0
- package/dist/src/httpUtils.js +363 -0
- package/dist/src/httpUtils.js.map +1 -0
- package/dist/src/httpUtils.test.d.ts +1 -0
- package/dist/src/httpUtils.test.js +628 -0
- package/dist/src/httpUtils.test.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +24 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/utils/logger.d.ts +11 -0
- package/dist/src/utils/logger.js +54 -0
- package/dist/src/utils/logger.js.map +1 -0
- package/dist/src/utils/testingConfigurations.d.ts +9 -0
- package/dist/src/utils/testingConfigurations.js +18 -0
- package/dist/src/utils/testingConfigurations.js.map +1 -0
- package/package.json +67 -0
- package/src/config/configs.ts +74 -0
- package/src/config/constants.ts +54 -0
- package/src/config/init.ts +55 -0
- package/src/httpUtils.test.ts +764 -0
- package/src/httpUtils.ts +405 -0
- package/src/index.ts +8 -0
- package/src/utils/logger.ts +53 -0
- package/src/utils/testingConfigurations.ts +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Ville de Montréal and other contributors
|
|
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,216 @@
|
|
|
1
|
+
# @villedemontreal/http-request
|
|
2
|
+
|
|
3
|
+
Utilitaires pour requêtes HTTP. Fourni principalement une fonction permettant de faire
|
|
4
|
+
des requêtes HTTP de manière à ce que les bons Correlation Ids soient envoyés.
|
|
5
|
+
|
|
6
|
+
## Configuration
|
|
7
|
+
|
|
8
|
+
Avant d'utiliser la fonction `httpUtils.send()`, il faut avoir correctement configuré la librairie.
|
|
9
|
+
|
|
10
|
+
La librarie a présentement besoin de deux configurations :
|
|
11
|
+
|
|
12
|
+
- Un "`Logger Creator`", qui est une fonction passée par le code appelant et servant à créer des Loggers
|
|
13
|
+
configurés correctement.
|
|
14
|
+
- Un "`Correlation Id provider`". Ceci est requis car la librairie doit avoir accès
|
|
15
|
+
aux bons Correlation Ids à ajouter aux requêtes effectuées.
|
|
16
|
+
|
|
17
|
+
Voici un exemple de code configurant la librairie, ici dans un projet démarré à l'aide du gabarit
|
|
18
|
+
[generator-mtl-node-api].
|
|
19
|
+
|
|
20
|
+
Dans le fichier "`src/init.ts`" du projet de l'API :
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { init as initHttpUtils } from '@villedemontreal/http-request';
|
|
24
|
+
import { createLogger } from './utils/logger';
|
|
25
|
+
import { correlationIdService } from '@villedemontreal/correlation-id';
|
|
26
|
+
import { configs } from '../config/configs';
|
|
27
|
+
|
|
28
|
+
//...
|
|
29
|
+
|
|
30
|
+
export async function initComponents() {
|
|
31
|
+
initHttpUtils(
|
|
32
|
+
createLogger,
|
|
33
|
+
() => {
|
|
34
|
+
return correlationIdService.getId();
|
|
35
|
+
},
|
|
36
|
+
config.routing.caseSensitive // required since 7.0.0
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
//...
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Notez que si vous configurez la librairie depuis _une autre librairie_, vous aurez probablement à passer
|
|
44
|
+
le "`Logger Creator`", le "`Correlation Id provider`" et le "`caseSensitive`" que vous aurez _vous-même_ reçus
|
|
45
|
+
comme configurations! Le but étant que toutes les librairies utilisées dans un projet d'API, ainsi que leurs
|
|
46
|
+
propres librairies transitives, puissent logger de la même manière, aient accès aux bons Correlation Ids et
|
|
47
|
+
parsent les URLs de la même manière.
|
|
48
|
+
|
|
49
|
+
Finalement, notez qu'une fonction "`isInited()`" est exportée et permet au code appelant de valider que la librairie a été
|
|
50
|
+
configurée correctement.
|
|
51
|
+
|
|
52
|
+
## Utilisation
|
|
53
|
+
|
|
54
|
+
### Effectuer une requête HTTP
|
|
55
|
+
|
|
56
|
+
Il s'agit de créer un objet "SuperAgentRequest" en utilisant [SuperAgent](http://visionmedia.github.io/superagent/), et de passer
|
|
57
|
+
cet objet à la fonction "`send(...)`" fournie ici. Il ne faut _pas_ awaiter l'objet "SuperAgentRequest" lui-même, mais plutôt
|
|
58
|
+
l'appel à la fonction "`send(...)`"! Par exemple :
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
import * as superagent from 'superagent';
|
|
62
|
+
|
|
63
|
+
//...
|
|
64
|
+
|
|
65
|
+
// Création de l'object requête
|
|
66
|
+
// (pas de "await" ici!)
|
|
67
|
+
let request = superagent
|
|
68
|
+
.get('https://some.url')
|
|
69
|
+
.set('someCustomHeader', '123')
|
|
70
|
+
.accept('application/json');
|
|
71
|
+
|
|
72
|
+
// Utilisation de httpUtils pour lancer la requête.
|
|
73
|
+
// Le bon Correlation Id sera automatiquement ajouté.
|
|
74
|
+
// Ne pas oublier le "await"!
|
|
75
|
+
try {
|
|
76
|
+
let response = await httpUtils.send(request);
|
|
77
|
+
|
|
78
|
+
// Gestion des erreurs 4XX-5XX...
|
|
79
|
+
if (!response.ok) {
|
|
80
|
+
let status = response.status;
|
|
81
|
+
//...
|
|
82
|
+
}
|
|
83
|
+
//...
|
|
84
|
+
} catch (err) {
|
|
85
|
+
// Ici une erreur réseau s'est produite ou le serveur
|
|
86
|
+
// demandé n'a pas été trouvé...
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### Gestion des erreurs
|
|
91
|
+
|
|
92
|
+
**Note importante** : la méthode `httpUtils.send(...)` gère les erreurs différement de la manière dont elles le sont
|
|
93
|
+
par défaut par SuperAgent! En effet, SuperAgent va _thrower_ une erreur lorsqu'une réponse avec status 4XX-5XX est retournée.
|
|
94
|
+
La méthode `httpUtils.send(...)`, au contraire, va _retourner ces réponses de manière régulière_ et c'est au code appelant
|
|
95
|
+
de valider le status HTTP (ou d'utiliser _`if (response.ok)`_). Le but est d'être en mesure de différencier entre une "erreur"
|
|
96
|
+
4XX-5XX et une _vraie_ erreur, par exemple lorsque la requête ne peut être effectuée car il y a un problème de réseau, ou lorsque
|
|
97
|
+
le host visé n'est pas trouvé.
|
|
98
|
+
|
|
99
|
+
Bref, il faut savoir qu'en utilisant `httpUtils.send(...)`, une erreur comme un "`Not Found`" (`404`) ne throwera **pas** d'erreur,
|
|
100
|
+
et c'est à vous à valider le status retourné...
|
|
101
|
+
|
|
102
|
+
### Autres utilitaires
|
|
103
|
+
|
|
104
|
+
#### getQueryParamAll
|
|
105
|
+
|
|
106
|
+
Retourne tous les paramètres de la _querystring_ d'un object `express.Request` spécifié.
|
|
107
|
+
|
|
108
|
+
Cette fonction tient compte de la configuration `urlCaseSensitive` ayant été utilisée lors
|
|
109
|
+
de l'initialisation de la librairie.
|
|
110
|
+
|
|
111
|
+
#### getQueryParamOne
|
|
112
|
+
|
|
113
|
+
Retourne un paramètre de la _querystring_ d'un object `express.Request` spécifié. Si
|
|
114
|
+
plusieures valeurs pour ce paramètre sont trouvées, la function retourne _la dernière trouvée_.
|
|
115
|
+
|
|
116
|
+
Cette fonction tient compte de la configuration `urlCaseSensitive` ayant été utilisée lors
|
|
117
|
+
de l'initialisation de la librairie.
|
|
118
|
+
|
|
119
|
+
#### getQueryParamOneAsDate
|
|
120
|
+
|
|
121
|
+
Retourne un paramètre de la _querystring_ d'un object `express.Request` spécifié, en tant
|
|
122
|
+
que `Date`. Si plusieures valeurs pour ce paramètre sont trouvées, la function retourne _la dernière trouvée_.
|
|
123
|
+
|
|
124
|
+
Si le paramètre est trouvé mais sa valeur ne peut être convertie en `Date` valide (en utilisant `new Date(xxx)`),
|
|
125
|
+
par défaut une `Error` est lancée. Mais si un `errorHandler` est passé en option, ce handler
|
|
126
|
+
sera appellé à la place. Dans une API basée sur `@villemontreal/generator-mtl-node-api`, ceci
|
|
127
|
+
vous permet de lancer une erreur custom, en utilisant par exemple `throw createInvalidParameterError(xxx)`.
|
|
128
|
+
|
|
129
|
+
Il est recommandé de toujours utiliser le format `ISO 8601` pour les dates.
|
|
130
|
+
|
|
131
|
+
Cette fonction tient compte de la configuration `urlCaseSensitive` ayant été utilisée lors
|
|
132
|
+
de l'initialisation de la librairie.
|
|
133
|
+
|
|
134
|
+
#### getQueryParamOneAsNumber
|
|
135
|
+
|
|
136
|
+
Retourne un paramètre de la _querystring_ d'un object `express.Request` spécifié, en tant
|
|
137
|
+
que `Number`. Si plusieures valeurs pour ce paramètre sont trouvées, la function retourne _la dernière trouvée_.
|
|
138
|
+
|
|
139
|
+
Si le paramètre est trouvé mais sa valeur ne peut être convertie en `Number` valide (en utilisant `Number(xxx)`),
|
|
140
|
+
par défaut une `Error` est lancée. Mais si un `errorHandler` est passé en option, ce handler
|
|
141
|
+
sera appellé à la place. Dans une API basée sur `@villemontreal/generator-mtl-node-api`, ceci
|
|
142
|
+
vous permet de lancer une erreur custom, en utilisant par exemple `throw createInvalidParameterError(xxx)`.
|
|
143
|
+
|
|
144
|
+
Cette fonction tient compte de la configuration `urlCaseSensitive` ayant été utilisée lors
|
|
145
|
+
de l'initialisation de la librairie.
|
|
146
|
+
|
|
147
|
+
#### getOrderBys
|
|
148
|
+
|
|
149
|
+
Retourne les `IOrderBy` spécifiés dans la querystring d'une requête de recherche.
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
#### urlJoin
|
|
153
|
+
|
|
154
|
+
Util to join part of url:
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import { httpUtils } from '@villedemontreal/http-request';
|
|
158
|
+
|
|
159
|
+
// To join multiple part of uri:
|
|
160
|
+
let url: string = httpUtils.urlJoin('http://api.montreal.ca/accounts/', '/inum', '@5441521452', 'tickets');
|
|
161
|
+
console.log(url); // http://api.montreal.ca/accounts/inum/@5441521452/tickets
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
#### buildUriObject
|
|
165
|
+
|
|
166
|
+
Util to parse an url and get the different parts:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { httpUtils } from '@villedemontreal/http-request';
|
|
170
|
+
|
|
171
|
+
let url: string = httpUtils.buildUriObject('http://api.montreal.ca/accounts/inum/@5441521452/tickets');
|
|
172
|
+
console.log(url); // {"uri": "http://api.montreal.ca/accounts/inum/@5441521452/tickets", "baseUri":"http://api.montreal.ca", "path":"/accounts/inum/@5441521452/tickets"}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
# Builder le projet
|
|
176
|
+
|
|
177
|
+
**Note**: Sur Linux/Mac assurz-vous que le fichier `run` est exécutable. Autrement, lancez `chmod +x ./run`.
|
|
178
|
+
|
|
179
|
+
Pour lancer le build :
|
|
180
|
+
|
|
181
|
+
- > `run compile` ou `./run compile` (sur Linux/Mac)
|
|
182
|
+
|
|
183
|
+
Pour lancer les tests :
|
|
184
|
+
|
|
185
|
+
- > `run test` ou `./run test` (sur Linux/Mac)
|
|
186
|
+
|
|
187
|
+
# Mode Watch
|
|
188
|
+
|
|
189
|
+
Lors du développement, il est possible de lancer `run watch` (ou `./run watch` sur Linux/mac) dans un terminal
|
|
190
|
+
externe pour démarrer la compilation incrémentale. Il est alors possible de lancer certaines _launch configuration_
|
|
191
|
+
comme `Debug current tests file - fast` dans VsCode et ainsi déboguer le fichier de tests présentement ouvert sans
|
|
192
|
+
avoir à (re)compiler au préalable (la compilation incrémentale s'en sera chargé).
|
|
193
|
+
|
|
194
|
+
Notez que, par défaut, des _notifications desktop_ sont activées pour indiquer visuellement si la compilation
|
|
195
|
+
incrémentale est un succès ou si une erreur a été trouvée. Vous pouvez désactiver ces notifications en utilisant
|
|
196
|
+
`run watch --dn` (`d`isable `n`otifications).
|
|
197
|
+
|
|
198
|
+
# Déboguer le projet
|
|
199
|
+
|
|
200
|
+
Trois "_launch configurations_" sont founies pour déboguer le projet dans VSCode :
|
|
201
|
+
|
|
202
|
+
- "`Debug all tests`", la launch configuration par défaut. Lance les tests en mode debug. Vous pouvez mettre
|
|
203
|
+
des breakpoints et ils seront respectés.
|
|
204
|
+
|
|
205
|
+
- "`Debug a test file`". Lance _un_ fichier de tests en mode debug. Vous pouvez mettre
|
|
206
|
+
des breakpoints et ils seront respectés. Pour changer le fichier de tests à être exécuté, vous devez modifier la ligne appropriée dans le fichier "`.vscode/launch.json`".
|
|
207
|
+
|
|
208
|
+
- "`Debug current tests file`". Lance le fichier de tests _présentement ouvert_ dans VSCode en mode debug. Effectue la compîlation au préalable.
|
|
209
|
+
|
|
210
|
+
- "`Debug current tests file - fast`". Lance le fichier de tests _présentement ouvert_ dans VSCode en mode debug. Aucune compilation
|
|
211
|
+
n'est effectuée au préalable. Cette launch configuration doit être utilisée lorsque la compilation incrémentale roule (voir la section "`Mode Watch`" plus haut)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
# Aide / Contributions
|
|
215
|
+
|
|
216
|
+
Notez que les contributions sous forme de pull requests sont bienvenues.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ILogger } from '@villedemontreal/logger';
|
|
2
|
+
/**
|
|
3
|
+
* Http Client Config
|
|
4
|
+
*/
|
|
5
|
+
export declare class Configs {
|
|
6
|
+
private _correlationIdProvider;
|
|
7
|
+
private _loggerCreator;
|
|
8
|
+
private _urlCaseSensitive;
|
|
9
|
+
/**
|
|
10
|
+
* Sets the Logger creator.
|
|
11
|
+
*/
|
|
12
|
+
setLoggerCreator(loggerCreator: (name: string) => ILogger): void;
|
|
13
|
+
/**
|
|
14
|
+
* The Logger creator
|
|
15
|
+
*/
|
|
16
|
+
get loggerCreator(): (name: string) => ILogger;
|
|
17
|
+
/**
|
|
18
|
+
* Sets the Correlation Id provider.
|
|
19
|
+
*/
|
|
20
|
+
setCorrelationIdProvider(correlationIdProvider: () => string): void;
|
|
21
|
+
/**
|
|
22
|
+
* The Correlation Id provider
|
|
23
|
+
*/
|
|
24
|
+
get correlationIdProvider(): () => string;
|
|
25
|
+
/**
|
|
26
|
+
* The current Correlation Id.
|
|
27
|
+
*/
|
|
28
|
+
get correlationId(): string;
|
|
29
|
+
/**
|
|
30
|
+
* Sets the case sensitivity to use for the URLs.
|
|
31
|
+
*/
|
|
32
|
+
setUrlCaseSensitive(urlCaseSensitive: boolean): void;
|
|
33
|
+
/**
|
|
34
|
+
* Routing info
|
|
35
|
+
*/
|
|
36
|
+
get isUrlCaseSensitive(): boolean;
|
|
37
|
+
}
|
|
38
|
+
export declare let configs: Configs;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.configs = exports.Configs = void 0;
|
|
4
|
+
const _ = require("lodash");
|
|
5
|
+
/**
|
|
6
|
+
* Http Client Config
|
|
7
|
+
*/
|
|
8
|
+
class Configs {
|
|
9
|
+
/**
|
|
10
|
+
* Sets the Logger creator.
|
|
11
|
+
*/
|
|
12
|
+
setLoggerCreator(loggerCreator) {
|
|
13
|
+
this._loggerCreator = loggerCreator;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The Logger creator
|
|
17
|
+
*/
|
|
18
|
+
get loggerCreator() {
|
|
19
|
+
if (!this._loggerCreator) {
|
|
20
|
+
throw new Error(`The Logger Creator HAS to be set as a configuration! Please call the init(...) function first.`);
|
|
21
|
+
}
|
|
22
|
+
return this._loggerCreator;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Sets the Correlation Id provider.
|
|
26
|
+
*/
|
|
27
|
+
setCorrelationIdProvider(correlationIdProvider) {
|
|
28
|
+
this._correlationIdProvider = correlationIdProvider;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The Correlation Id provider
|
|
32
|
+
*/
|
|
33
|
+
get correlationIdProvider() {
|
|
34
|
+
if (!this._correlationIdProvider) {
|
|
35
|
+
throw new Error(`The Correlation Id provider HAS to be set as a configuration! Please call the init(...) function first.`);
|
|
36
|
+
}
|
|
37
|
+
return this._correlationIdProvider;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The current Correlation Id.
|
|
41
|
+
*/
|
|
42
|
+
get correlationId() {
|
|
43
|
+
return this.correlationIdProvider();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Sets the case sensitivity to use for the URLs.
|
|
47
|
+
*/
|
|
48
|
+
setUrlCaseSensitive(urlCaseSensitive) {
|
|
49
|
+
this._urlCaseSensitive = urlCaseSensitive;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Routing info
|
|
53
|
+
*/
|
|
54
|
+
get isUrlCaseSensitive() {
|
|
55
|
+
if (_.isNil(this._urlCaseSensitive)) {
|
|
56
|
+
throw new Error(`The Case Sensitivity to use for the URLs HAS to be set as a configuration! Please call the init(...) function first.`);
|
|
57
|
+
}
|
|
58
|
+
return this._urlCaseSensitive;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.Configs = Configs;
|
|
62
|
+
exports.configs = new Configs();
|
|
63
|
+
//# sourceMappingURL=configs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configs.js","sourceRoot":"","sources":["../../../src/config/configs.ts"],"names":[],"mappings":";;;AACA,4BAA4B;AAE5B;;GAEG;AACH,MAAa,OAAO;IAKlB;;OAEG;IACI,gBAAgB,CAAC,aAAwC;QAC9D,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC;IACtC,CAAC;IAED;;OAEG;IACH,IAAI,aAAa;QACf,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;YACxB,MAAM,IAAI,KAAK,CAAC,gGAAgG,CAAC,CAAC;SACnH;QACD,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED;;OAEG;IACI,wBAAwB,CAAC,qBAAmC;QACjE,IAAI,CAAC,sBAAsB,GAAG,qBAAqB,CAAC;IACtD,CAAC;IAED;;OAEG;IACH,IAAI,qBAAqB;QACvB,IAAI,CAAC,IAAI,CAAC,sBAAsB,EAAE;YAChC,MAAM,IAAI,KAAK,CACb,yGAAyG,CAC1G,CAAC;SACH;QACD,OAAO,IAAI,CAAC,sBAAsB,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,qBAAqB,EAAE,CAAC;IACtC,CAAC;IAED;;OAEG;IACI,mBAAmB,CAAC,gBAAyB;QAClD,IAAI,CAAC,iBAAiB,GAAG,gBAAgB,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,IAAI,kBAAkB;QACpB,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE;YACnC,MAAM,IAAI,KAAK,CACb,sHAAsH,CACvH,CAAC;SACH;QACD,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAChC,CAAC;CACF;AAlED,0BAkEC;AACU,QAAA,OAAO,GAAY,IAAI,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Library constants
|
|
3
|
+
*/
|
|
4
|
+
export declare class Constants {
|
|
5
|
+
/**
|
|
6
|
+
* The library root. When this library is used
|
|
7
|
+
* as a dependency in a project, the "libRoot"
|
|
8
|
+
* will be the path to the dependency folder,
|
|
9
|
+
* inside the "node_modules".
|
|
10
|
+
*/
|
|
11
|
+
libRoot: string;
|
|
12
|
+
/**
|
|
13
|
+
* The app root. When this library is used
|
|
14
|
+
* as a dependency in a project, the "appRoot"
|
|
15
|
+
* will be the path to the root project!
|
|
16
|
+
*/
|
|
17
|
+
appRoot: string;
|
|
18
|
+
constructor();
|
|
19
|
+
/**
|
|
20
|
+
* Requests constants
|
|
21
|
+
*/
|
|
22
|
+
get request(): {
|
|
23
|
+
/**
|
|
24
|
+
* Default timeout constants
|
|
25
|
+
*/
|
|
26
|
+
timeoutsDefault: {
|
|
27
|
+
/**
|
|
28
|
+
* The default number of milliseconds to wait
|
|
29
|
+
* for the server to start sending data.
|
|
30
|
+
*/
|
|
31
|
+
response: number;
|
|
32
|
+
/**
|
|
33
|
+
* The default number of milliseconds to wait
|
|
34
|
+
* for the data to finish loading.
|
|
35
|
+
*/
|
|
36
|
+
deadline: number;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export declare let constants: Constants;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.constants = exports.Constants = void 0;
|
|
4
|
+
const app_root_path_1 = require("app-root-path");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
/**
|
|
7
|
+
* Library constants
|
|
8
|
+
*/
|
|
9
|
+
class Constants {
|
|
10
|
+
constructor() {
|
|
11
|
+
// From the "dist/src/config" folder
|
|
12
|
+
this.libRoot = path.normalize(__dirname + '/../../..');
|
|
13
|
+
this.appRoot = app_root_path_1.path;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Requests constants
|
|
17
|
+
*/
|
|
18
|
+
get request() {
|
|
19
|
+
return {
|
|
20
|
+
/**
|
|
21
|
+
* Default timeout constants
|
|
22
|
+
*/
|
|
23
|
+
timeoutsDefault: {
|
|
24
|
+
/**
|
|
25
|
+
* The default number of milliseconds to wait
|
|
26
|
+
* for the server to start sending data.
|
|
27
|
+
*/
|
|
28
|
+
response: 30000,
|
|
29
|
+
/**
|
|
30
|
+
* The default number of milliseconds to wait
|
|
31
|
+
* for the data to finish loading.
|
|
32
|
+
*/
|
|
33
|
+
deadline: 60000
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.Constants = Constants;
|
|
39
|
+
exports.constants = new Constants();
|
|
40
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/config/constants.ts"],"names":[],"mappings":";;;AAAA,iDAAgD;AAChD,6BAA6B;AAE7B;;GAEG;AACH,MAAa,SAAS;IAgBpB;QACE,oCAAoC;QACpC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,GAAG,WAAW,CAAC,CAAC;QACvD,IAAI,CAAC,OAAO,GAAG,oBAAO,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,IAAI,OAAO;QACT,OAAO;YACL;;eAEG;YACH,eAAe,EAAE;gBACf;;;mBAGG;gBACH,QAAQ,EAAE,KAAK;gBAEf;;;mBAGG;gBACH,QAAQ,EAAE,KAAK;aAChB;SACF,CAAC;IACJ,CAAC;CACF;AA7CD,8BA6CC;AAEU,QAAA,SAAS,GAAc,IAAI,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ILogger } from '@villedemontreal/logger';
|
|
2
|
+
/**
|
|
3
|
+
* Inits the library.
|
|
4
|
+
*/
|
|
5
|
+
export declare function init(loggerCreator: (name: string) => ILogger, correlationIdProvider: () => string,
|
|
6
|
+
/**
|
|
7
|
+
* The case sensitivity to use for the URLs.
|
|
8
|
+
*
|
|
9
|
+
* In an API based on "@villemontreal/generator-mtl-node-api",
|
|
10
|
+
* you need to pass `configs.routing.caseSensitive` here!
|
|
11
|
+
*/
|
|
12
|
+
urlCaseSensitive: boolean): void;
|
|
13
|
+
/**
|
|
14
|
+
* Is the library properly initialized?
|
|
15
|
+
*
|
|
16
|
+
* This function MUST be named "isInited()"!
|
|
17
|
+
* Code using this library may loop over all its "@villemontreal"
|
|
18
|
+
* dependencies and, if one of those exports a "isInited" fonction,
|
|
19
|
+
* it will enforce that the lib has been properly initialized before
|
|
20
|
+
* starting...
|
|
21
|
+
*/
|
|
22
|
+
export declare function isInited(): boolean;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isInited = exports.init = void 0;
|
|
4
|
+
const _ = require("lodash");
|
|
5
|
+
const configs_1 = require("./configs");
|
|
6
|
+
let libIsInited = false;
|
|
7
|
+
/**
|
|
8
|
+
* Inits the library.
|
|
9
|
+
*/
|
|
10
|
+
function init(loggerCreator, correlationIdProvider,
|
|
11
|
+
/**
|
|
12
|
+
* The case sensitivity to use for the URLs.
|
|
13
|
+
*
|
|
14
|
+
* In an API based on "@villemontreal/generator-mtl-node-api",
|
|
15
|
+
* you need to pass `configs.routing.caseSensitive` here!
|
|
16
|
+
*/
|
|
17
|
+
urlCaseSensitive) {
|
|
18
|
+
if (!loggerCreator) {
|
|
19
|
+
throw new Error(`The Logger Creator is required.`);
|
|
20
|
+
}
|
|
21
|
+
if (!correlationIdProvider) {
|
|
22
|
+
throw new Error(`The Correlation Id provider is required.`);
|
|
23
|
+
}
|
|
24
|
+
if (_.isNil(urlCaseSensitive)) {
|
|
25
|
+
throw new Error(`The Case Sensitivity to use for the URLs is required.`);
|
|
26
|
+
}
|
|
27
|
+
configs_1.configs.setLoggerCreator(loggerCreator);
|
|
28
|
+
configs_1.configs.setCorrelationIdProvider(correlationIdProvider);
|
|
29
|
+
configs_1.configs.setUrlCaseSensitive(urlCaseSensitive);
|
|
30
|
+
// ==========================================
|
|
31
|
+
// Set as being "properly initialized".
|
|
32
|
+
// At the very end of the "init()" function!
|
|
33
|
+
// ==========================================
|
|
34
|
+
libIsInited = true;
|
|
35
|
+
}
|
|
36
|
+
exports.init = init;
|
|
37
|
+
/**
|
|
38
|
+
* Is the library properly initialized?
|
|
39
|
+
*
|
|
40
|
+
* This function MUST be named "isInited()"!
|
|
41
|
+
* Code using this library may loop over all its "@villemontreal"
|
|
42
|
+
* dependencies and, if one of those exports a "isInited" fonction,
|
|
43
|
+
* it will enforce that the lib has been properly initialized before
|
|
44
|
+
* starting...
|
|
45
|
+
*/
|
|
46
|
+
function isInited() {
|
|
47
|
+
return libIsInited;
|
|
48
|
+
}
|
|
49
|
+
exports.isInited = isInited;
|
|
50
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/config/init.ts"],"names":[],"mappings":";;;AACA,4BAA4B;AAC5B,uCAAoC;AAEpC,IAAI,WAAW,GAAY,KAAK,CAAC;AAEjC;;GAEG;AACH,SAAgB,IAAI,CAClB,aAAwC,EACxC,qBAAmC;AACnC;;;;;GAKG;AACH,gBAAyB;IAEzB,IAAI,CAAC,aAAa,EAAE;QAClB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;KACpD;IAED,IAAI,CAAC,qBAAqB,EAAE;QAC1B,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;KAC7D;IAED,IAAI,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE;QAC7B,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;KAC1E;IAED,iBAAO,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;IACxC,iBAAO,CAAC,wBAAwB,CAAC,qBAAqB,CAAC,CAAC;IACxD,iBAAO,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;IAE9C,6CAA6C;IAC7C,uCAAuC;IACvC,4CAA4C;IAC5C,6CAA6C;IAC7C,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC;AAhCD,oBAgCC;AAED;;;;;;;;GAQG;AACH,SAAgB,QAAQ;IACtB,OAAO,WAAW,CAAC;AACrB,CAAC;AAFD,4BAEC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { IOrderBy } from '@villedemontreal/general-utils';
|
|
2
|
+
import { Request } from 'express';
|
|
3
|
+
import * as superagent from 'superagent';
|
|
4
|
+
/**
|
|
5
|
+
* HTTP utilities
|
|
6
|
+
*/
|
|
7
|
+
export declare class HttpUtils {
|
|
8
|
+
private readonly REQ_PARAMS_LOWERCASED;
|
|
9
|
+
/**
|
|
10
|
+
* Remove first and last slash of the string unless the string is the part after protocol (http://)
|
|
11
|
+
*/
|
|
12
|
+
removeSlashes(text: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Join few parts of an url to a final string
|
|
15
|
+
*/
|
|
16
|
+
urlJoin(...args: string[]): string;
|
|
17
|
+
/**
|
|
18
|
+
* Sends a HTTP request built with Superagent.
|
|
19
|
+
*
|
|
20
|
+
* Will add the proper Correlation Id and will write
|
|
21
|
+
* useful logs.
|
|
22
|
+
*
|
|
23
|
+
* IMPORTANT : this method does NOT throw an Error on a
|
|
24
|
+
* 4XX-5XX status response! It will return it the same way
|
|
25
|
+
* it returns a 200 response and it is up to the calling code
|
|
26
|
+
* to validate the actual response's status. For example
|
|
27
|
+
* by using :
|
|
28
|
+
*
|
|
29
|
+
* if(response.ok) {...}
|
|
30
|
+
*
|
|
31
|
+
* and/or by checking the status :
|
|
32
|
+
*
|
|
33
|
+
* if(response.status === 404) {...}
|
|
34
|
+
*
|
|
35
|
+
* An error will be thrown only when a network problem occures or
|
|
36
|
+
* if the target server can't be reached.
|
|
37
|
+
*
|
|
38
|
+
* This is different from SuperAgent's default behavior that DOES
|
|
39
|
+
* throw an error on 4XX-5XX status responses.
|
|
40
|
+
*
|
|
41
|
+
*/
|
|
42
|
+
send(request: superagent.SuperAgentRequest): Promise<superagent.Response>;
|
|
43
|
+
/**
|
|
44
|
+
* Gets all the values of a querystring parameter.
|
|
45
|
+
* Manages the fact that we may use insensitive routing.
|
|
46
|
+
*
|
|
47
|
+
* A querystring parameter may indeed contains multiple values. For
|
|
48
|
+
* example : "path?name=aaa&name=bbb" will result in an
|
|
49
|
+
* *array* when getting the "name" parameter : ['aaa', 'bbb'].
|
|
50
|
+
*
|
|
51
|
+
* @returns all the values of the parameters as an array (even if
|
|
52
|
+
* only one value is found) or an empty array if none are found.
|
|
53
|
+
*/
|
|
54
|
+
getQueryParamAll(req: Request, key: string): string[];
|
|
55
|
+
/**
|
|
56
|
+
* Get the last value of a querystring parameter.
|
|
57
|
+
* Manages the fact that we may use insensitive routing.
|
|
58
|
+
*
|
|
59
|
+
* A querystring parameter may indeed contains multiple values. For
|
|
60
|
+
* example : "path?name=aaa&name=bbb" will result in an
|
|
61
|
+
* *array* when getting the "name" parameter : ['aaa', 'bbb'].
|
|
62
|
+
*
|
|
63
|
+
* In many situation, we only want to deal withy a single value.
|
|
64
|
+
* This function return the last value of a query param.
|
|
65
|
+
*
|
|
66
|
+
* @returns the last parameter with that key or `undefined` if
|
|
67
|
+
* not found.
|
|
68
|
+
*/
|
|
69
|
+
getQueryParamOne(req: Request, key: string): string;
|
|
70
|
+
/**
|
|
71
|
+
* Get the last value of a querystring parameter *as a Date*.
|
|
72
|
+
* The parameter must be parsable using `new Date(xxx)`.
|
|
73
|
+
* It is recommended to always use ISO-8601 to represent dates
|
|
74
|
+
* (ex: "2020-04-21T17:13:33.107Z").
|
|
75
|
+
*
|
|
76
|
+
* If the parameter is found but can't be parsed to a Date,
|
|
77
|
+
* by default an `Error` is thrown. But if `errorHandler`
|
|
78
|
+
* is specified, it is called instead. This allows you
|
|
79
|
+
* to catch the error and throw a custom error, for
|
|
80
|
+
* example by using `throw createInvalidParameterError(xxx)`
|
|
81
|
+
* in an API.
|
|
82
|
+
*
|
|
83
|
+
* Manages the fact that we may use insensitive routing.
|
|
84
|
+
*
|
|
85
|
+
* @returns the last parameter with that key as a Date
|
|
86
|
+
* or `undefined` if not found.
|
|
87
|
+
* @throws An Error if the parameter is found but can't be parsed
|
|
88
|
+
* to a Date and no `errorHandler` is specified.
|
|
89
|
+
*/
|
|
90
|
+
getQueryParamOneAsDate: (req: Request, key: string, errorHandler?: (errMsg: string, value?: string) => any) => Date;
|
|
91
|
+
/**
|
|
92
|
+
* Get the last value of a querystring parameter *as a Number*.
|
|
93
|
+
* The parameter must be parsable using `Number(xxx)`.
|
|
94
|
+
*
|
|
95
|
+
* If the parameter is found but can't be parsed to a Number,
|
|
96
|
+
* by default an `Error` is thrown. But if `errorHandler`
|
|
97
|
+
* is specified, it is called instead. This allows you
|
|
98
|
+
* to catch the error and throw a custom error, for
|
|
99
|
+
* example by using `throw createInvalidParameterError(xxx)`
|
|
100
|
+
* in an API.
|
|
101
|
+
*
|
|
102
|
+
* Manages the fact that we may use insensitive routing.
|
|
103
|
+
*
|
|
104
|
+
* @returns the last parameter with that key as a Number
|
|
105
|
+
* or `undefined` if not found.
|
|
106
|
+
* @throws An Error if the parameter is found but can't be parsed
|
|
107
|
+
* to a Number and no `errorHandler` is specified.
|
|
108
|
+
*/
|
|
109
|
+
getQueryParamOneAsNumber: (req: Request, key: string, errorHandler?: (errMsg: string, value?: string) => any) => number;
|
|
110
|
+
/**
|
|
111
|
+
* Get the last value of a querystring parameter *as a boolean*.
|
|
112
|
+
* The value must be "true" or "false" (case insensitive) to
|
|
113
|
+
* be considered as a valid boolean. For example, the value '1'
|
|
114
|
+
* is invalid.
|
|
115
|
+
*
|
|
116
|
+
* @returns the last parameter with that key as a boolean
|
|
117
|
+
* or `undefined` if not found.
|
|
118
|
+
* @throws An Error if the parameter is found but can't be parsed
|
|
119
|
+
* to a valid boolean and no `errorHandler` is specified.
|
|
120
|
+
*/
|
|
121
|
+
getQueryParamOneAsBoolean: (req: Request, key: string, errorHandler?: (errMsg: string, value?: string) => any) => boolean;
|
|
122
|
+
private getOriginalQueryParamAsArray;
|
|
123
|
+
/**
|
|
124
|
+
* Gets the "IOrderBy[]" from the querystring parameters
|
|
125
|
+
* of a search request.
|
|
126
|
+
*
|
|
127
|
+
* @see https://confluence.montreal.ca/pages/viewpage.action?spaceKey=AES&title=REST+API#RESTAPI-Tridelarequ%C3%AAte
|
|
128
|
+
*/
|
|
129
|
+
getOrderBys: (req: Request) => IOrderBy[];
|
|
130
|
+
}
|
|
131
|
+
export declare let httpUtils: HttpUtils;
|