[{"data":1,"prerenderedAt":6156},["ShallowReactive",2],{"tag-posts-aws":3},[4],{"id":5,"title":6,"author":7,"body":8,"category":6113,"categorySlug":6114,"date":6115,"description":14,"excerpt":6116,"extension":6141,"location":6142,"meta":6143,"navigation":205,"path":6144,"published":205,"seo":6145,"slug":6146,"stem":6147,"tags":6148,"timeToRead":1067,"__hash__":6155},"posts\u002Fposts\u002FProgrammation\u002F2021-09-27_achat_velo.md","Du souhait d'achat d'un vélo ...","Ulrich Vandenhekke",{"type":9,"value":10,"toc":6097},"minimark",[11,15,23,38,41,49,52,55,60,63,74,77,84,87,95,98,111,116,125,135,144,247,250,597,600,603,610,613,641,644,647,667,673,684,687,691,698,701,708,715,718,729,732,837,840,844,847,895,898,1216,1219,1223,1226,1229,1238,1240,1903,1906,1912,2414,2417,2424,2428,2436,2444,2870,2873,2889,2892,2896,2899,2902,2905,2908,2911,2914,2917,2921,2924,2927,2930,2933,2936,3320,3323,3746,3749,3752,3771,4647,4650,4657,4661,4664,4675,4983,4986,4989,5522,5525,5529,5532,5535,5542,5599,5606,5613,5957,5960,6017,6021,6024,6027,6034,6038,6041,6044,6047,6050,6053,6056,6093],[12,13,14],"p",{},"Que penseriez-vous si je vous racontais un peu mes vacances ? Attendez ... attendez ... ne partez pas ... l'histoire est intéressante,\net surtout nous allons parler informatique.",[12,16,17,18,22],{},"Début Août j'ai décidé de m'acheter un nouveau vélo (un VTC à assistance électrique). Le choix du vélo importe peu, mais du fait d'une pénurie\nde matière première et d'une forte demande en vélo depuis le début de la crise ",[19,20,21],"del",{},"de mes"," sanitaire, tous les vélos sont en rupture de stock.",[12,24,25,26],{},"J'ai fait le choix personnel de me rendre dans une enseigne connue dont le nom est aussi une discipline de l'athlétisme pour acheter ce VTC.",[27,28,29],"sup",{},[30,31,37],"a",{"href":32,"ariaDescribedBy":33,"dataFootnoteRef":35,"id":36},"#user-content-fn-1",[34],"footnote-label","","user-content-fnref-1","1",[12,39,40],{},"Et là c'est le drame.",[12,42,43,44,48],{},"Si vous regardez les différents vélos de la marque (et en fonction de la taille du cadre qui vous correspond) vous tombez sur le message: ",[45,46,47],"em",{},"En\nrupture de stock",". (Bon. À aujourd'hui, nous avons un peu plus de stock sur le site)",[12,50,51],{},"Arf. Moi qui quand j'ai décidé quelque chose, je deviens impatient ...",[12,53,54],{},"Alors il est vrai que j'aurais pu aller voir sur un autre site, aller dans une autre boutique pour choisir un autre modèle, mais ce n'est pas\nce que j'ai fait.",[56,57,59],"h2",{"id":58},"lattente","L'attente",[12,61,62],{},"J'ai donc commencé par attendre, en allant régulièrement sur le site ou en rafraîchissant l'onglet d'un navigateur. C'est long, la page est\nrelativement lourde pour un site WEB: plus de 2.2M de fichier à transférer pour un total de 175 requêtes et ce malgrès la présence d'un adblock.",[12,64,65,66,69,70,73],{},"De plus je dois sélectionner manuellement la taille dans une select box pour voir : ",[45,67,68],{},"Rupture de stock sur cette taille",". Là je clique sur\nle bouton ",[45,71,72],{},"Vérifier le stock en magasin",", ... je rentre mon code postal, ... et je regarde sur l'ensemble des magasins de ma région...",[12,75,76],{},"Bref, je prépare mes valises, et je pars me mettre au vert. Je fais un peu de marche avec les enfants (C'est les vacances quoi). Et je ne\npeux donc pas m'amuser à rafraîchir en continu (même si je le fais depuis mon téléphone portable).",[12,78,79,80,83],{},"Bien sûr j'ai cliqué sur le bouton ",[45,81,82],{},"M'avertir lorsque le produit est à nouveau disponible"," mais je me demande si ce bouton fonctionne, je n'ai\nà aujourd'hui toujours pas recu de mail 😄.",[12,85,86],{},"Je décide donc de passer à l'étape suivante.",[56,88,90,91,94],{"id":89},"la-1er-version","La 1",[27,92,93],{},"er"," version",[12,96,97],{},"Je me pose donc et me demande comment je peux mettre mes compétences à contribution pour m'aider moi-même à m'acheter pour moi mon propre vélo. Je décide donc de mon propre chef de me développer une application sur mon compte AWS que je viens de me créer. Ce programme devra\nme permettre de faire plusieurs choses:",[99,100,101,105,108],"ol",{},[102,103,104],"li",{},"En un coup d'oeil visualiser le stock pour le vélo sur Internet et dans les différents magasins",[102,106,107],{},"M'avertir si le stock change",[102,109,110],{},"Et le plus important, ne pas me prendre la tête et développer l'application dans le moins de temps possible",[12,112,90,113,115],{},[27,114,93],{}," version que je développe a pour but de visualiser le stock.",[12,117,118],{},[119,120],"img",{"alt":121,"className":122,"src":124},"Selecteur JS",[123],"img-center","\u002FProgrammation\u002Fachat_velo\u002Ffirst_version.png",[12,126,127,128,134],{},"Le but de l'application est de récupérer l'état des stocks du site Internet. Si je peux le faire avec un navigateur internet sur le site,\nalors un programme peut le faire aussi. Je prends les outils dont j'ai l'habitude pour faire le travail: Node.JS et le framework\n",[30,129,133],{"href":130,"rel":131},"https:\u002F\u002Fnestjs.com\u002F",[132],"nofollow","Nest.JS"," - framework que j'apprécie pour sa simplicité d'utilisation.",[12,136,137,138,143],{},"Pour parser la page, j'utilise ",[30,139,142],{"href":140,"rel":141},"https:\u002F\u002Fgithub.com\u002Fjsdom\u002Fjsdom",[132],"JSDom",":",[145,146,150],"pre",{"className":147,"code":148,"language":149,"meta":35,"style":35},"language-ts shiki shiki-themes one-dark-pro","const dom = await JSDOM.fromURL(VTC_540E_URL, options);\n\nconsole.log(dom.window.document.querySelector(\"#product-size-selection\"));\n","ts",[151,152,153,200,207],"code",{"__ignoreMap":35},[154,155,158,162,166,170,173,176,180,184,187,190,193,197],"span",{"class":156,"line":157},"line",1,[154,159,161],{"class":160},"seHd6","const",[154,163,165],{"class":164},"sU0A5"," dom",[154,167,169],{"class":168},"sjrmR"," =",[154,171,172],{"class":160}," await",[154,174,175],{"class":164}," JSDOM",[154,177,179],{"class":178},"sn6KH",".",[154,181,183],{"class":182},"sVbv2","fromURL",[154,185,186],{"class":178},"(",[154,188,189],{"class":164},"VTC_540E_URL",[154,191,192],{"class":178},", ",[154,194,196],{"class":195},"sVyAn","options",[154,198,199],{"class":178},");\n",[154,201,203],{"class":156,"line":202},2,[154,204,206],{"emptyLinePlaceholder":205},true,"\n",[154,208,210,213,215,218,220,223,225,228,230,233,235,238,240,244],{"class":156,"line":209},3,[154,211,212],{"class":164},"console",[154,214,179],{"class":178},[154,216,217],{"class":182},"log",[154,219,186],{"class":178},[154,221,222],{"class":164},"dom",[154,224,179],{"class":178},[154,226,227],{"class":164},"window",[154,229,179],{"class":178},[154,231,232],{"class":164},"document",[154,234,179],{"class":178},[154,236,237],{"class":182},"querySelector",[154,239,186],{"class":178},[154,241,243],{"class":242},"subq3","\"#product-size-selection\"",[154,245,246],{"class":178},"));\n",[12,248,249],{},"Première erreur quand je lance le programme:",[145,251,255],{"className":252,"code":253,"language":254,"meta":35,"style":35},"language-sh shiki shiki-themes one-dark-pro","(node:15246) UnhandledPromiseRejectionWarning: Error: Parse Error: Header overflow\n    at TLSSocket.socketOnData (_http_client.js:476:22)\n    at TLSSocket.emit (events.js:311:20)\n    at addChunk (_stream_readable.js:294:12)\n    at readableAddChunk (_stream_readable.js:275:11)\n    at TLSSocket.Readable.push (_stream_readable.js:209:10)\n    at TLSWrap.onStreamRead (internal\u002Fstream_base_commons.js:186:23)\n(node:15246) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https:\u002F\u002Fnodejs.org\u002Fapi\u002Fcli.html#cli_unhandled_rejections_mode). (rejection id: 1)\n(node:15246) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.\n","sh",[151,256,257,284,295,305,316,327,338,349,525],{"__ignoreMap":35},[154,258,259,261,264,267,270,273,276,278,281],{"class":156,"line":157},[154,260,186],{"class":178},[154,262,263],{"class":182},"node:15246",[154,265,266],{"class":178},") ",[154,268,269],{"class":182},"UnhandledPromiseRejectionWarning:",[154,271,272],{"class":242}," Error:",[154,274,275],{"class":242}," Parse",[154,277,272],{"class":242},[154,279,280],{"class":242}," Header",[154,282,283],{"class":242}," overflow\n",[154,285,286,289,292],{"class":156,"line":202},[154,287,288],{"class":182},"    at",[154,290,291],{"class":242}," TLSSocket.socketOnData",[154,293,294],{"class":178}," (_http_client.js:476:22)\n",[154,296,297,299,302],{"class":156,"line":209},[154,298,288],{"class":182},[154,300,301],{"class":242}," TLSSocket.emit",[154,303,304],{"class":178}," (events.js:311:20)\n",[154,306,308,310,313],{"class":156,"line":307},4,[154,309,288],{"class":182},[154,311,312],{"class":242}," addChunk",[154,314,315],{"class":178}," (_stream_readable.js:294:12)\n",[154,317,319,321,324],{"class":156,"line":318},5,[154,320,288],{"class":182},[154,322,323],{"class":242}," readableAddChunk",[154,325,326],{"class":178}," (_stream_readable.js:275:11)\n",[154,328,330,332,335],{"class":156,"line":329},6,[154,331,288],{"class":182},[154,333,334],{"class":242}," TLSSocket.Readable.push",[154,336,337],{"class":178}," (_stream_readable.js:209:10)\n",[154,339,341,343,346],{"class":156,"line":340},7,[154,342,288],{"class":182},[154,344,345],{"class":242}," TLSWrap.onStreamRead",[154,347,348],{"class":178}," (internal\u002Fstream_base_commons.js:186:23)\n",[154,350,352,354,356,358,360,363,366,369,372,375,378,381,384,387,390,393,396,399,402,405,408,411,414,417,419,422,424,426,429,432,435,438,441,444,447,449,452,455,458,461,464,467,470,472,475,478,480,483,486,489,492,495,498,501,504,507,510,512,515,518,522],{"class":156,"line":351},8,[154,353,186],{"class":178},[154,355,263],{"class":182},[154,357,266],{"class":178},[154,359,269],{"class":182},[154,361,362],{"class":242}," Unhandled",[154,364,365],{"class":242}," promise",[154,367,368],{"class":242}," rejection.",[154,370,371],{"class":242}," This",[154,373,374],{"class":242}," error",[154,376,377],{"class":242}," originated",[154,379,380],{"class":242}," either",[154,382,383],{"class":242}," by",[154,385,386],{"class":242}," throwing",[154,388,389],{"class":242}," inside",[154,391,392],{"class":242}," of",[154,394,395],{"class":242}," an",[154,397,398],{"class":242}," async",[154,400,401],{"class":242}," function",[154,403,404],{"class":242}," without",[154,406,407],{"class":242}," a",[154,409,410],{"class":242}," catch",[154,412,413],{"class":242}," block,",[154,415,416],{"class":242}," or",[154,418,383],{"class":242},[154,420,421],{"class":242}," rejecting",[154,423,407],{"class":242},[154,425,365],{"class":242},[154,427,428],{"class":242}," which",[154,430,431],{"class":242}," was",[154,433,434],{"class":242}," not",[154,436,437],{"class":242}," handled",[154,439,440],{"class":242}," with",[154,442,443],{"class":242}," .catch",[154,445,446],{"class":178},"()",[154,448,179],{"class":242},[154,450,451],{"class":242}," To",[154,453,454],{"class":242}," terminate",[154,456,457],{"class":242}," the",[154,459,460],{"class":242}," node",[154,462,463],{"class":242}," process",[154,465,466],{"class":242}," on",[154,468,469],{"class":242}," unhandled",[154,471,365],{"class":242},[154,473,474],{"class":242}," rejection,",[154,476,477],{"class":242}," use",[154,479,457],{"class":242},[154,481,482],{"class":242}," CLI",[154,484,485],{"class":242}," flag",[154,487,488],{"class":242}," `",[154,490,491],{"class":195},"--unhandled-rejections",[154,493,494],{"class":168},"=",[154,496,497],{"class":242},"strict`",[154,499,500],{"class":178}," (",[154,502,503],{"class":182},"see",[154,505,506],{"class":242}," https:\u002F\u002Fnodejs.org\u002Fapi\u002Fcli.html#cli_unhandled_rejections_mode",[154,508,509],{"class":178},")",[154,511,179],{"class":168},[154,513,514],{"class":178}," (rejection ",[154,516,517],{"class":242},"id:",[154,519,521],{"class":520},"sVC51"," 1",[154,523,524],{"class":178},")\n",[154,526,528,530,532,535,538,540,542,545,548,551,554,556,559,561,563,566,568,570,572,575,577,579,582,584,586,588,591,594],{"class":156,"line":527},9,[154,529,186],{"class":178},[154,531,263],{"class":182},[154,533,534],{"class":178},") [DEP0018] ",[154,536,537],{"class":182},"DeprecationWarning:",[154,539,362],{"class":242},[154,541,365],{"class":242},[154,543,544],{"class":242}," rejections",[154,546,547],{"class":242}," are",[154,549,550],{"class":242}," deprecated.",[154,552,553],{"class":242}," In",[154,555,457],{"class":242},[154,557,558],{"class":242}," future,",[154,560,365],{"class":242},[154,562,544],{"class":242},[154,564,565],{"class":242}," that",[154,567,547],{"class":242},[154,569,434],{"class":242},[154,571,437],{"class":242},[154,573,574],{"class":242}," will",[154,576,454],{"class":242},[154,578,457],{"class":242},[154,580,581],{"class":242}," Node.js",[154,583,463],{"class":242},[154,585,440],{"class":242},[154,587,407],{"class":242},[154,589,590],{"class":242}," non-zero",[154,592,593],{"class":242}," exit",[154,595,596],{"class":242}," code.\n",[12,598,599],{},"Pas de chance, les headers http de la grande enseigne contiennent tellement de blabla que nodejs limite et bloque. C'est l'effet CSP (Content-Security-Policy). Les CSP sont\nutilisés pour bloquer les requêtes faites par le navigateur sur une page si elle ne sont pas autorisées.",[12,601,602],{},"Par exemple, si un utisateur arrive à profiter d'une faille et arrive dans un avis client à mettre une iframe, une image, ... vers un site dont il possède le contrôle. La CSP\nva dire au navigateur que ce site n'est pas autorisé. Et le hack de l'utilisateur ne fonctionnera pas totalement.",[12,604,605,606,609],{},"Mais quand un site commence à avoir beaucoup de ",[45,607,608],{},"\"partenaire\""," (google, vimeo, cloudfront, facebook, gstatic.com, et tous les trucs bloqués par\nadblock ...), la liste prend de la place.",[12,611,612],{},"Je relance node avec l'option adéquate:",[145,614,616],{"className":252,"code":615,"language":254,"meta":35,"style":35},"node --max-http-header-size=80000 app.js\n\nHTMLSelectElement {}\n",[151,617,618,629,633],{"__ignoreMap":35},[154,619,620,623,626],{"class":156,"line":157},[154,621,622],{"class":182},"node",[154,624,625],{"class":520}," --max-http-header-size=80000",[154,627,628],{"class":242}," app.js\n",[154,630,631],{"class":156,"line":202},[154,632,206],{"emptyLinePlaceholder":205},[154,634,635,638],{"class":156,"line":209},[154,636,637],{"class":182},"HTMLSelectElement",[154,639,640],{"class":242}," {}\n",[12,642,643],{},"Cela commence bien.",[12,645,646],{},"Maintenant nous allons devoir ouvrir le sélecteur de taille, choisir la taille L (qui me correspond) et cliquer dessus. Je pourrai alors récupérer l'info de stock.",[12,648,649,650,655,663,664,179],{},"Malheureusement beaucoup de choses sur le site sont en JavaScript, ",[30,651,654],{"href":652,"rel":653},"https:\u002F\u002Fgithub.com\u002Fjsdom\u002Fjsdom\u002Fissues\u002F2162",[132],"JSDom ne permet pas d'executer le JS de la page",[27,656,657],{},[30,658,662],{"href":659,"ariaDescribedBy":660,"dataFootnoteRef":35,"id":661},"#user-content-fn-2",[34],"user-content-fnref-2","2"," et donc je suis bloqué. Déjà, pour un truc que je voulais faire rapidement, mauvais choix de solution ;). Je commence à me dire que je vais devoir sortir la grosse\nartillerie : ",[45,665,666],{},"Puppeteer",[12,668,669],{},[119,670],{"alt":121,"className":671,"src":672},[123],"\u002FProgrammation\u002Fachat_velo\u002Fselecteur_js.png",[12,674,675,679,680,683],{},[30,676,666],{"href":677,"rel":678},"https:\u002F\u002Fgithub.com\u002Fpuppeteer\u002Fpuppeteer",[132]," est une librairie javascript qui permet de contrôler le navigateur chrome en mode headless (sans fenêtre). Cela me\npermettrait donc de parser la page en ",[19,681,682],{},"simulant"," avec un navigateur chrome.",[12,685,686],{},"Mais attendez, s'il y a beaucoup de javascript, il y a peut-être des requêtes XHR ?",[56,688,690],{"id":689},"xhr","XHR",[12,692,693,694,697],{},"XHR, c'est pour ",[151,695,696],{},"XMLHttpRequest",", ce sont des requêtes executées par le Javascript pour récupérer quelques informations.",[12,699,700],{},"Avec Chrome, on peut récupérer la liste des requêtes qui sont effectuées lors de l'affichage de la page mais également lors des différentes interactions.",[12,702,703],{},[119,704],{"alt":705,"className":706,"src":707},"Vue network de Chrome",[123],"\u002FProgrammation\u002Fachat_velo\u002Fchrome_network.png",[12,709,710,711,714],{},"On active alors le filtre ",[45,712,713],{},"Fetch\u002FXHR"," qu nous permet de voir les requêtes qui ne sont pas du CSS, ni du HTML, ni du JS, mais uniquement des requêtes qui sont lancées\npar le code Javascript.",[12,716,717],{},"Bien sûr il faut éliminer les requêtes vers d'autres sites (comme abtasty, ...). On peut alors retrouver la requête qui permet de retourner le stock du site Internet:",[145,719,723],{"className":720,"code":721,"language":722,"meta":35,"style":35},"language-http shiki shiki-themes one-dark-pro","GET \u002Ffr\u002Fajax\u002Fnfs\u002Fstocks\u002Fonline?skuIds=4216661,4216663,4216662,4216664\n","http",[151,724,725],{"__ignoreMap":35},[154,726,727],{"class":156,"line":157},[154,728,721],{},[12,730,731],{},"Et avec la réponse:",[145,733,737],{"className":734,"code":735,"language":736,"meta":35,"style":35},"language-json shiki shiki-themes one-dark-pro","{\n  \"4216661\": {\n    \"stockOnline\": 0\n  },\n  \"4216662\": {\n    \"stockOnline\": 0\n  },\n  \"4216663\": {\n    \"stockOnline\": 0\n  },\n  \"4216664\": {\n    \"stockOnline\": 18\n  }\n}\n","json",[151,738,739,744,752,763,768,775,783,787,794,802,807,815,825,831],{"__ignoreMap":35},[154,740,741],{"class":156,"line":157},[154,742,743],{"class":178},"{\n",[154,745,746,749],{"class":156,"line":202},[154,747,748],{"class":195},"  \"4216661\"",[154,750,751],{"class":178},": {\n",[154,753,754,757,760],{"class":156,"line":209},[154,755,756],{"class":195},"    \"stockOnline\"",[154,758,759],{"class":178},": ",[154,761,762],{"class":520},"0\n",[154,764,765],{"class":156,"line":307},[154,766,767],{"class":178},"  },\n",[154,769,770,773],{"class":156,"line":318},[154,771,772],{"class":195},"  \"4216662\"",[154,774,751],{"class":178},[154,776,777,779,781],{"class":156,"line":329},[154,778,756],{"class":195},[154,780,759],{"class":178},[154,782,762],{"class":520},[154,784,785],{"class":156,"line":340},[154,786,767],{"class":178},[154,788,789,792],{"class":156,"line":351},[154,790,791],{"class":195},"  \"4216663\"",[154,793,751],{"class":178},[154,795,796,798,800],{"class":156,"line":527},[154,797,756],{"class":195},[154,799,759],{"class":178},[154,801,762],{"class":520},[154,803,805],{"class":156,"line":804},10,[154,806,767],{"class":178},[154,808,810,813],{"class":156,"line":809},11,[154,811,812],{"class":195},"  \"4216664\"",[154,814,751],{"class":178},[154,816,818,820,822],{"class":156,"line":817},12,[154,819,756],{"class":195},[154,821,759],{"class":178},[154,823,824],{"class":520},"18\n",[154,826,828],{"class":156,"line":827},13,[154,829,830],{"class":178},"  }\n",[154,832,834],{"class":156,"line":833},14,[154,835,836],{"class":178},"}\n",[12,838,839],{},"La requête nous retourne les différents stocks pour les différentes tailles de cadre (S, M, L, XL). C'est la taille L qui m'intéresse, mais comment savoir quel\ncode produit correspond à quelle taille ?",[56,841,843],{"id":842},"code-source-de-la-page","Code source de la page",[12,845,846],{},"On peut afficher le code source de la page (clic droit sur la page HTML : Afficher la source). Dans le source HTML on retrouve le bout de code suivant :",[145,848,852],{"className":849,"code":850,"language":851,"meta":35,"style":35},"language-html shiki shiki-themes one-dark-pro","\u003Cscript id=\"__dkt\" type=\"application\u002Fjson\">\n  ...\n\u003C\u002Fscript>\n","html",[151,853,854,881,886],{"__ignoreMap":35},[154,855,856,859,862,865,867,870,873,875,878],{"class":156,"line":157},[154,857,858],{"class":178},"\u003C",[154,860,861],{"class":195},"script",[154,863,864],{"class":520}," id",[154,866,494],{"class":178},[154,868,869],{"class":242},"\"__dkt\"",[154,871,872],{"class":520}," type",[154,874,494],{"class":178},[154,876,877],{"class":242},"\"application\u002Fjson\"",[154,879,880],{"class":178},">\n",[154,882,883],{"class":156,"line":202},[154,884,885],{"class":178},"  ...\n",[154,887,888,891,893],{"class":156,"line":209},[154,889,890],{"class":178},"\u003C\u002F",[154,892,861],{"class":195},[154,894,880],{"class":178},[12,896,897],{},"Le JSON contient le contexte qui sera utilisé par le code Javascript pour la génération de la page et le côté interactif. C'est l'équivalent d'un appel XHR intégré au démarrage\nde la page. On peut y retrouver ce que l'on cherche :",[145,899,901],{"className":734,"code":900,"language":736,"meta":35,"style":35},"{\n  \"skus\": [\n    {\n      \"skuId\": \"4216661\",\n      \"size\": \"S\",\n      \"grossWeight\": \"20.9\",\n      \"price\": 2199,\n      \"isNotAvailable\": true,\n      \"availableInStores\": []\n    },\n    {\n      \"skuId\": \"4216663\",\n      \"size\": \"M\",\n      \"grossWeight\": \"21.0\",\n      \"price\": 2199,\n      \"isNotAvailable\": true,\n      \"availableInStores\": []\n    },\n    {\n      \"skuId\": \"4216662\",\n      \"size\": \"L\",\n      \"grossWeight\": \"21.1\",\n      \"price\": 2199,\n      \"isNotAvailable\": true,\n      \"availableInStores\": []\n    },\n    {\n      \"skuId\": \"4216664\",\n      \"size\": \"XL\",\n      \"grossWeight\": \"21.2\",\n      \"price\": 2199,\n      \"availableInStores\": []\n    }\n  ]\n}\n",[151,902,903,907,915,920,933,945,957,969,981,989,994,998,1009,1020,1031,1042,1053,1060,1065,1070,1082,1094,1106,1117,1128,1135,1140,1145,1157,1169,1181,1192,1199,1205,1211],{"__ignoreMap":35},[154,904,905],{"class":156,"line":157},[154,906,743],{"class":178},[154,908,909,912],{"class":156,"line":202},[154,910,911],{"class":195},"  \"skus\"",[154,913,914],{"class":178},": [\n",[154,916,917],{"class":156,"line":209},[154,918,919],{"class":178},"    {\n",[154,921,922,925,927,930],{"class":156,"line":307},[154,923,924],{"class":195},"      \"skuId\"",[154,926,759],{"class":178},[154,928,929],{"class":242},"\"4216661\"",[154,931,932],{"class":178},",\n",[154,934,935,938,940,943],{"class":156,"line":318},[154,936,937],{"class":195},"      \"size\"",[154,939,759],{"class":178},[154,941,942],{"class":242},"\"S\"",[154,944,932],{"class":178},[154,946,947,950,952,955],{"class":156,"line":329},[154,948,949],{"class":195},"      \"grossWeight\"",[154,951,759],{"class":178},[154,953,954],{"class":242},"\"20.9\"",[154,956,932],{"class":178},[154,958,959,962,964,967],{"class":156,"line":340},[154,960,961],{"class":195},"      \"price\"",[154,963,759],{"class":178},[154,965,966],{"class":520},"2199",[154,968,932],{"class":178},[154,970,971,974,976,979],{"class":156,"line":351},[154,972,973],{"class":195},"      \"isNotAvailable\"",[154,975,759],{"class":178},[154,977,978],{"class":520},"true",[154,980,932],{"class":178},[154,982,983,986],{"class":156,"line":527},[154,984,985],{"class":195},"      \"availableInStores\"",[154,987,988],{"class":178},": []\n",[154,990,991],{"class":156,"line":804},[154,992,993],{"class":178},"    },\n",[154,995,996],{"class":156,"line":809},[154,997,919],{"class":178},[154,999,1000,1002,1004,1007],{"class":156,"line":817},[154,1001,924],{"class":195},[154,1003,759],{"class":178},[154,1005,1006],{"class":242},"\"4216663\"",[154,1008,932],{"class":178},[154,1010,1011,1013,1015,1018],{"class":156,"line":827},[154,1012,937],{"class":195},[154,1014,759],{"class":178},[154,1016,1017],{"class":242},"\"M\"",[154,1019,932],{"class":178},[154,1021,1022,1024,1026,1029],{"class":156,"line":833},[154,1023,949],{"class":195},[154,1025,759],{"class":178},[154,1027,1028],{"class":242},"\"21.0\"",[154,1030,932],{"class":178},[154,1032,1034,1036,1038,1040],{"class":156,"line":1033},15,[154,1035,961],{"class":195},[154,1037,759],{"class":178},[154,1039,966],{"class":520},[154,1041,932],{"class":178},[154,1043,1045,1047,1049,1051],{"class":156,"line":1044},16,[154,1046,973],{"class":195},[154,1048,759],{"class":178},[154,1050,978],{"class":520},[154,1052,932],{"class":178},[154,1054,1056,1058],{"class":156,"line":1055},17,[154,1057,985],{"class":195},[154,1059,988],{"class":178},[154,1061,1063],{"class":156,"line":1062},18,[154,1064,993],{"class":178},[154,1066,1068],{"class":156,"line":1067},19,[154,1069,919],{"class":178},[154,1071,1073,1075,1077,1080],{"class":156,"line":1072},20,[154,1074,924],{"class":195},[154,1076,759],{"class":178},[154,1078,1079],{"class":242},"\"4216662\"",[154,1081,932],{"class":178},[154,1083,1085,1087,1089,1092],{"class":156,"line":1084},21,[154,1086,937],{"class":195},[154,1088,759],{"class":178},[154,1090,1091],{"class":242},"\"L\"",[154,1093,932],{"class":178},[154,1095,1097,1099,1101,1104],{"class":156,"line":1096},22,[154,1098,949],{"class":195},[154,1100,759],{"class":178},[154,1102,1103],{"class":242},"\"21.1\"",[154,1105,932],{"class":178},[154,1107,1109,1111,1113,1115],{"class":156,"line":1108},23,[154,1110,961],{"class":195},[154,1112,759],{"class":178},[154,1114,966],{"class":520},[154,1116,932],{"class":178},[154,1118,1120,1122,1124,1126],{"class":156,"line":1119},24,[154,1121,973],{"class":195},[154,1123,759],{"class":178},[154,1125,978],{"class":520},[154,1127,932],{"class":178},[154,1129,1131,1133],{"class":156,"line":1130},25,[154,1132,985],{"class":195},[154,1134,988],{"class":178},[154,1136,1138],{"class":156,"line":1137},26,[154,1139,993],{"class":178},[154,1141,1143],{"class":156,"line":1142},27,[154,1144,919],{"class":178},[154,1146,1148,1150,1152,1155],{"class":156,"line":1147},28,[154,1149,924],{"class":195},[154,1151,759],{"class":178},[154,1153,1154],{"class":242},"\"4216664\"",[154,1156,932],{"class":178},[154,1158,1160,1162,1164,1167],{"class":156,"line":1159},29,[154,1161,937],{"class":195},[154,1163,759],{"class":178},[154,1165,1166],{"class":242},"\"XL\"",[154,1168,932],{"class":178},[154,1170,1172,1174,1176,1179],{"class":156,"line":1171},30,[154,1173,949],{"class":195},[154,1175,759],{"class":178},[154,1177,1178],{"class":242},"\"21.2\"",[154,1180,932],{"class":178},[154,1182,1184,1186,1188,1190],{"class":156,"line":1183},31,[154,1185,961],{"class":195},[154,1187,759],{"class":178},[154,1189,966],{"class":520},[154,1191,932],{"class":178},[154,1193,1195,1197],{"class":156,"line":1194},32,[154,1196,985],{"class":195},[154,1198,988],{"class":178},[154,1200,1202],{"class":156,"line":1201},33,[154,1203,1204],{"class":178},"    }\n",[154,1206,1208],{"class":156,"line":1207},34,[154,1209,1210],{"class":178},"  ]\n",[154,1212,1214],{"class":156,"line":1213},35,[154,1215,836],{"class":178},[12,1217,1218],{},"La taille qui m'intéresse est donc le SKU 4216662.",[56,1220,1222],{"id":1221},"stock-des-magasins","Stock des magasins",[12,1224,1225],{},"Vient ensuite la partie sur le stock des magasins. Je clique sur le bouton permettant de vérifier le stock des magasins, rentre mon code postal, et je me\nretrouve avec la liste des magasins.",[12,1227,1228],{},"Je regarde les requêtes et trouve celle qui m'intéresse avec l'ensemble des magasins du nord de la france:",[145,1230,1232],{"className":720,"code":1231,"language":722,"meta":35,"style":35},"GET \u002Ffr\u002Fajax\u002Frest\u002Fmodel\u002Fcom\u002Fdecathlon\u002Fcube\u002Fcommerce\u002Finventory\u002FInventoryActor\u002FgetStoreAvailability?storeIds=0070000200002%2C0070093300933%2C0070043700437%2C0070051800518%2C0070011800118%2C0070219902199%2C0070050400504%2C0070253902539%2C0070001500015%2C0070064800648&skuId=4216662&modelId=8614842&displayStoreDetails=false\n",[151,1233,1234],{"__ignoreMap":35},[154,1235,1236],{"class":156,"line":157},[154,1237,1231],{},[12,1239,731],{},[145,1241,1243],{"className":734,"code":1242,"language":736,"meta":35,"style":35},"{\n  \"responseTO\": {\n    \"data\": [\n      {\n        \"aboveThreshold\": false,\n        \"address\": null,\n        \"availabilityInfo\": \"noStock\",\n        \"clickNcollect1h\": false,\n        \"favoriteStore\": false,\n        \"latitude\": 0,\n        \"longitude\": 0,\n        \"optionId\": null,\n        \"originId\": null,\n        \"phoneNumber\": null,\n        \"priceId\": null,\n        \"quantity\": 0,\n        \"securedStockLevel\": 0,\n        \"skuId\": \"4216662\",\n        \"storeId\": \"0070000200002\",\n        \"storeName\": \"Neuville en Ferrain - Roncq\",\n        \"storeSchedule\": null,\n        \"storeUrl\": null\n      },\n      {\n        \"aboveThreshold\": false,\n        \"address\": null,\n        \"availabilityInfo\": \"noStock\",\n        \"clickNcollect1h\": false,\n        \"favoriteStore\": false,\n        \"latitude\": 0,\n        \"longitude\": 0,\n        \"optionId\": null,\n        \"originId\": null,\n        \"phoneNumber\": null,\n        \"priceId\": null,\n        \"quantity\": 0,\n        \"securedStockLevel\": 1,\n        \"skuId\": \"4216662\",\n        \"storeId\": \"0070051800518\",\n        \"storeName\": \"Marcq-en-Baroeul DOMYOS\",\n        \"storeSchedule\": null,\n        \"storeUrl\": null\n      },\n      {\n        \"aboveThreshold\": false,\n        \"address\": null,\n        \"availabilityInfo\": \"noStock\",\n        \"clickNcollect1h\": false,\n        \"favoriteStore\": false,\n        \"latitude\": 0,\n        \"longitude\": 0,\n        \"optionId\": null,\n        \"originId\": null,\n        \"phoneNumber\": null,\n        \"priceId\": null,\n        \"quantity\": 0,\n        \"securedStockLevel\": 1,\n        \"skuId\": \"4216662\",\n        \"storeId\": \"0070219902199\",\n        \"storeName\": \"Villeneuve d'Ascq - DX\",\n        \"storeSchedule\": null,\n        \"storeUrl\": null\n      },\n      ...\n    ],\n  }\n}\n",[151,1244,1245,1249,1256,1263,1268,1280,1292,1304,1315,1326,1338,1349,1360,1371,1382,1393,1404,1415,1426,1438,1450,1461,1471,1476,1480,1490,1500,1510,1520,1530,1540,1550,1560,1570,1580,1590,1601,1612,1623,1635,1647,1658,1667,1672,1677,1688,1699,1710,1721,1732,1743,1754,1765,1776,1787,1798,1809,1820,1831,1843,1855,1866,1875,1880,1887,1893,1898],{"__ignoreMap":35},[154,1246,1247],{"class":156,"line":157},[154,1248,743],{"class":178},[154,1250,1251,1254],{"class":156,"line":202},[154,1252,1253],{"class":195},"  \"responseTO\"",[154,1255,751],{"class":178},[154,1257,1258,1261],{"class":156,"line":209},[154,1259,1260],{"class":195},"    \"data\"",[154,1262,914],{"class":178},[154,1264,1265],{"class":156,"line":307},[154,1266,1267],{"class":178},"      {\n",[154,1269,1270,1273,1275,1278],{"class":156,"line":318},[154,1271,1272],{"class":195},"        \"aboveThreshold\"",[154,1274,759],{"class":178},[154,1276,1277],{"class":520},"false",[154,1279,932],{"class":178},[154,1281,1282,1285,1287,1290],{"class":156,"line":329},[154,1283,1284],{"class":195},"        \"address\"",[154,1286,759],{"class":178},[154,1288,1289],{"class":520},"null",[154,1291,932],{"class":178},[154,1293,1294,1297,1299,1302],{"class":156,"line":340},[154,1295,1296],{"class":195},"        \"availabilityInfo\"",[154,1298,759],{"class":178},[154,1300,1301],{"class":242},"\"noStock\"",[154,1303,932],{"class":178},[154,1305,1306,1309,1311,1313],{"class":156,"line":351},[154,1307,1308],{"class":195},"        \"clickNcollect1h\"",[154,1310,759],{"class":178},[154,1312,1277],{"class":520},[154,1314,932],{"class":178},[154,1316,1317,1320,1322,1324],{"class":156,"line":527},[154,1318,1319],{"class":195},"        \"favoriteStore\"",[154,1321,759],{"class":178},[154,1323,1277],{"class":520},[154,1325,932],{"class":178},[154,1327,1328,1331,1333,1336],{"class":156,"line":804},[154,1329,1330],{"class":195},"        \"latitude\"",[154,1332,759],{"class":178},[154,1334,1335],{"class":520},"0",[154,1337,932],{"class":178},[154,1339,1340,1343,1345,1347],{"class":156,"line":809},[154,1341,1342],{"class":195},"        \"longitude\"",[154,1344,759],{"class":178},[154,1346,1335],{"class":520},[154,1348,932],{"class":178},[154,1350,1351,1354,1356,1358],{"class":156,"line":817},[154,1352,1353],{"class":195},"        \"optionId\"",[154,1355,759],{"class":178},[154,1357,1289],{"class":520},[154,1359,932],{"class":178},[154,1361,1362,1365,1367,1369],{"class":156,"line":827},[154,1363,1364],{"class":195},"        \"originId\"",[154,1366,759],{"class":178},[154,1368,1289],{"class":520},[154,1370,932],{"class":178},[154,1372,1373,1376,1378,1380],{"class":156,"line":833},[154,1374,1375],{"class":195},"        \"phoneNumber\"",[154,1377,759],{"class":178},[154,1379,1289],{"class":520},[154,1381,932],{"class":178},[154,1383,1384,1387,1389,1391],{"class":156,"line":1033},[154,1385,1386],{"class":195},"        \"priceId\"",[154,1388,759],{"class":178},[154,1390,1289],{"class":520},[154,1392,932],{"class":178},[154,1394,1395,1398,1400,1402],{"class":156,"line":1044},[154,1396,1397],{"class":195},"        \"quantity\"",[154,1399,759],{"class":178},[154,1401,1335],{"class":520},[154,1403,932],{"class":178},[154,1405,1406,1409,1411,1413],{"class":156,"line":1055},[154,1407,1408],{"class":195},"        \"securedStockLevel\"",[154,1410,759],{"class":178},[154,1412,1335],{"class":520},[154,1414,932],{"class":178},[154,1416,1417,1420,1422,1424],{"class":156,"line":1062},[154,1418,1419],{"class":195},"        \"skuId\"",[154,1421,759],{"class":178},[154,1423,1079],{"class":242},[154,1425,932],{"class":178},[154,1427,1428,1431,1433,1436],{"class":156,"line":1067},[154,1429,1430],{"class":195},"        \"storeId\"",[154,1432,759],{"class":178},[154,1434,1435],{"class":242},"\"0070000200002\"",[154,1437,932],{"class":178},[154,1439,1440,1443,1445,1448],{"class":156,"line":1072},[154,1441,1442],{"class":195},"        \"storeName\"",[154,1444,759],{"class":178},[154,1446,1447],{"class":242},"\"Neuville en Ferrain - Roncq\"",[154,1449,932],{"class":178},[154,1451,1452,1455,1457,1459],{"class":156,"line":1084},[154,1453,1454],{"class":195},"        \"storeSchedule\"",[154,1456,759],{"class":178},[154,1458,1289],{"class":520},[154,1460,932],{"class":178},[154,1462,1463,1466,1468],{"class":156,"line":1096},[154,1464,1465],{"class":195},"        \"storeUrl\"",[154,1467,759],{"class":178},[154,1469,1470],{"class":520},"null\n",[154,1472,1473],{"class":156,"line":1108},[154,1474,1475],{"class":178},"      },\n",[154,1477,1478],{"class":156,"line":1119},[154,1479,1267],{"class":178},[154,1481,1482,1484,1486,1488],{"class":156,"line":1130},[154,1483,1272],{"class":195},[154,1485,759],{"class":178},[154,1487,1277],{"class":520},[154,1489,932],{"class":178},[154,1491,1492,1494,1496,1498],{"class":156,"line":1137},[154,1493,1284],{"class":195},[154,1495,759],{"class":178},[154,1497,1289],{"class":520},[154,1499,932],{"class":178},[154,1501,1502,1504,1506,1508],{"class":156,"line":1142},[154,1503,1296],{"class":195},[154,1505,759],{"class":178},[154,1507,1301],{"class":242},[154,1509,932],{"class":178},[154,1511,1512,1514,1516,1518],{"class":156,"line":1147},[154,1513,1308],{"class":195},[154,1515,759],{"class":178},[154,1517,1277],{"class":520},[154,1519,932],{"class":178},[154,1521,1522,1524,1526,1528],{"class":156,"line":1159},[154,1523,1319],{"class":195},[154,1525,759],{"class":178},[154,1527,1277],{"class":520},[154,1529,932],{"class":178},[154,1531,1532,1534,1536,1538],{"class":156,"line":1171},[154,1533,1330],{"class":195},[154,1535,759],{"class":178},[154,1537,1335],{"class":520},[154,1539,932],{"class":178},[154,1541,1542,1544,1546,1548],{"class":156,"line":1183},[154,1543,1342],{"class":195},[154,1545,759],{"class":178},[154,1547,1335],{"class":520},[154,1549,932],{"class":178},[154,1551,1552,1554,1556,1558],{"class":156,"line":1194},[154,1553,1353],{"class":195},[154,1555,759],{"class":178},[154,1557,1289],{"class":520},[154,1559,932],{"class":178},[154,1561,1562,1564,1566,1568],{"class":156,"line":1201},[154,1563,1364],{"class":195},[154,1565,759],{"class":178},[154,1567,1289],{"class":520},[154,1569,932],{"class":178},[154,1571,1572,1574,1576,1578],{"class":156,"line":1207},[154,1573,1375],{"class":195},[154,1575,759],{"class":178},[154,1577,1289],{"class":520},[154,1579,932],{"class":178},[154,1581,1582,1584,1586,1588],{"class":156,"line":1213},[154,1583,1386],{"class":195},[154,1585,759],{"class":178},[154,1587,1289],{"class":520},[154,1589,932],{"class":178},[154,1591,1593,1595,1597,1599],{"class":156,"line":1592},36,[154,1594,1397],{"class":195},[154,1596,759],{"class":178},[154,1598,1335],{"class":520},[154,1600,932],{"class":178},[154,1602,1604,1606,1608,1610],{"class":156,"line":1603},37,[154,1605,1408],{"class":195},[154,1607,759],{"class":178},[154,1609,37],{"class":520},[154,1611,932],{"class":178},[154,1613,1615,1617,1619,1621],{"class":156,"line":1614},38,[154,1616,1419],{"class":195},[154,1618,759],{"class":178},[154,1620,1079],{"class":242},[154,1622,932],{"class":178},[154,1624,1626,1628,1630,1633],{"class":156,"line":1625},39,[154,1627,1430],{"class":195},[154,1629,759],{"class":178},[154,1631,1632],{"class":242},"\"0070051800518\"",[154,1634,932],{"class":178},[154,1636,1638,1640,1642,1645],{"class":156,"line":1637},40,[154,1639,1442],{"class":195},[154,1641,759],{"class":178},[154,1643,1644],{"class":242},"\"Marcq-en-Baroeul DOMYOS\"",[154,1646,932],{"class":178},[154,1648,1650,1652,1654,1656],{"class":156,"line":1649},41,[154,1651,1454],{"class":195},[154,1653,759],{"class":178},[154,1655,1289],{"class":520},[154,1657,932],{"class":178},[154,1659,1661,1663,1665],{"class":156,"line":1660},42,[154,1662,1465],{"class":195},[154,1664,759],{"class":178},[154,1666,1470],{"class":520},[154,1668,1670],{"class":156,"line":1669},43,[154,1671,1475],{"class":178},[154,1673,1675],{"class":156,"line":1674},44,[154,1676,1267],{"class":178},[154,1678,1680,1682,1684,1686],{"class":156,"line":1679},45,[154,1681,1272],{"class":195},[154,1683,759],{"class":178},[154,1685,1277],{"class":520},[154,1687,932],{"class":178},[154,1689,1691,1693,1695,1697],{"class":156,"line":1690},46,[154,1692,1284],{"class":195},[154,1694,759],{"class":178},[154,1696,1289],{"class":520},[154,1698,932],{"class":178},[154,1700,1702,1704,1706,1708],{"class":156,"line":1701},47,[154,1703,1296],{"class":195},[154,1705,759],{"class":178},[154,1707,1301],{"class":242},[154,1709,932],{"class":178},[154,1711,1713,1715,1717,1719],{"class":156,"line":1712},48,[154,1714,1308],{"class":195},[154,1716,759],{"class":178},[154,1718,1277],{"class":520},[154,1720,932],{"class":178},[154,1722,1724,1726,1728,1730],{"class":156,"line":1723},49,[154,1725,1319],{"class":195},[154,1727,759],{"class":178},[154,1729,1277],{"class":520},[154,1731,932],{"class":178},[154,1733,1735,1737,1739,1741],{"class":156,"line":1734},50,[154,1736,1330],{"class":195},[154,1738,759],{"class":178},[154,1740,1335],{"class":520},[154,1742,932],{"class":178},[154,1744,1746,1748,1750,1752],{"class":156,"line":1745},51,[154,1747,1342],{"class":195},[154,1749,759],{"class":178},[154,1751,1335],{"class":520},[154,1753,932],{"class":178},[154,1755,1757,1759,1761,1763],{"class":156,"line":1756},52,[154,1758,1353],{"class":195},[154,1760,759],{"class":178},[154,1762,1289],{"class":520},[154,1764,932],{"class":178},[154,1766,1768,1770,1772,1774],{"class":156,"line":1767},53,[154,1769,1364],{"class":195},[154,1771,759],{"class":178},[154,1773,1289],{"class":520},[154,1775,932],{"class":178},[154,1777,1779,1781,1783,1785],{"class":156,"line":1778},54,[154,1780,1375],{"class":195},[154,1782,759],{"class":178},[154,1784,1289],{"class":520},[154,1786,932],{"class":178},[154,1788,1790,1792,1794,1796],{"class":156,"line":1789},55,[154,1791,1386],{"class":195},[154,1793,759],{"class":178},[154,1795,1289],{"class":520},[154,1797,932],{"class":178},[154,1799,1801,1803,1805,1807],{"class":156,"line":1800},56,[154,1802,1397],{"class":195},[154,1804,759],{"class":178},[154,1806,1335],{"class":520},[154,1808,932],{"class":178},[154,1810,1812,1814,1816,1818],{"class":156,"line":1811},57,[154,1813,1408],{"class":195},[154,1815,759],{"class":178},[154,1817,37],{"class":520},[154,1819,932],{"class":178},[154,1821,1823,1825,1827,1829],{"class":156,"line":1822},58,[154,1824,1419],{"class":195},[154,1826,759],{"class":178},[154,1828,1079],{"class":242},[154,1830,932],{"class":178},[154,1832,1834,1836,1838,1841],{"class":156,"line":1833},59,[154,1835,1430],{"class":195},[154,1837,759],{"class":178},[154,1839,1840],{"class":242},"\"0070219902199\"",[154,1842,932],{"class":178},[154,1844,1846,1848,1850,1853],{"class":156,"line":1845},60,[154,1847,1442],{"class":195},[154,1849,759],{"class":178},[154,1851,1852],{"class":242},"\"Villeneuve d'Ascq - DX\"",[154,1854,932],{"class":178},[154,1856,1858,1860,1862,1864],{"class":156,"line":1857},61,[154,1859,1454],{"class":195},[154,1861,759],{"class":178},[154,1863,1289],{"class":520},[154,1865,932],{"class":178},[154,1867,1869,1871,1873],{"class":156,"line":1868},62,[154,1870,1465],{"class":195},[154,1872,759],{"class":178},[154,1874,1470],{"class":520},[154,1876,1878],{"class":156,"line":1877},63,[154,1879,1475],{"class":178},[154,1881,1883],{"class":156,"line":1882},64,[154,1884,1886],{"class":1885},"sLaUg","      ...\n",[154,1888,1890],{"class":156,"line":1889},65,[154,1891,1892],{"class":178},"    ],\n",[154,1894,1896],{"class":156,"line":1895},66,[154,1897,830],{"class":178},[154,1899,1901],{"class":156,"line":1900},67,[154,1902,836],{"class":178},[12,1904,1905],{},"Parfait, j'ai l'ensemble des requêtes et le résultat permettant de recupérer les informations dont j'ai besoin. Il ne me reste plus qu'à coder. Je crée donc\nun premier service dont le but est pour un code donné de récupérer le stock internet et les stocks en magasin.",[12,1907,1908,1909,1911],{},"Il est probable que j'aurais pu mieux écrire mon code (et d'ailleurs mieux utiliser RxJS), mais je vous rappelle, ceci est un 1",[27,1910,93],{}," jet. Le but étant de déployer\ncela le plus rapidement possible.",[145,1913,1915],{"className":147,"code":1914,"language":149,"meta":35,"style":35},"@Injectable()\nexport class AppService {\n  constructor(private httpService: HttpService) {}\n\n  async getVtcElectectricL(code: string): Promise\u003CStockInformation[]> {\n    const availability = [];\n    const sku = await firstValueFrom(\n      this.httpService.get\u003CStocksOnline>(STOCKS_ONLINE([code])),\n    );\n    const onlineStocks = sku.data[code]?.stockOnline;\n\n    availability.push({\n      type: 'Internet',\n      stocks: onlineStocks,\n    });\n\n    const stores = await firstValueFrom(\n      this.httpService.get\u003CStocksStores>(STOCKS_STORE(code)),\n    );\n\n    availability.push(\n      ...stores.data.responseTO.data\n        .map((store) => ({\n          type: store.storeName,\n          stocks: store.quantity,\n        }))\n        .sort((a, b) => b.stocks - a.stocks),\n    );\n\n    return availability.map((store) => ({\n      ...store,\n      availability: store.stocks > 0 ? 'available' : 'not_available',\n    }));\n  }\n}\n",[151,1916,1917,1928,1942,1964,1968,1999,2012,2029,2063,2068,2098,2102,2115,2127,2139,2144,2148,2163,2192,2196,2200,2210,2232,2254,2270,2286,2291,2331,2335,2339,2360,2368,2401,2406,2410],{"__ignoreMap":35},[154,1918,1919,1922,1925],{"class":156,"line":157},[154,1920,1921],{"class":178},"@",[154,1923,1924],{"class":182},"Injectable",[154,1926,1927],{"class":178},"()\n",[154,1929,1930,1933,1936,1939],{"class":156,"line":202},[154,1931,1932],{"class":160},"export",[154,1934,1935],{"class":160}," class",[154,1937,1938],{"class":164}," AppService",[154,1940,1941],{"class":178}," {\n",[154,1943,1944,1947,1949,1952,1956,1958,1961],{"class":156,"line":209},[154,1945,1946],{"class":160},"  constructor",[154,1948,186],{"class":178},[154,1950,1951],{"class":160},"private",[154,1953,1955],{"class":1954},"s_ZVi"," httpService",[154,1957,759],{"class":178},[154,1959,1960],{"class":164},"HttpService",[154,1962,1963],{"class":178},") {}\n",[154,1965,1966],{"class":156,"line":307},[154,1967,206],{"emptyLinePlaceholder":205},[154,1969,1970,1973,1976,1978,1980,1982,1985,1988,1991,1993,1996],{"class":156,"line":318},[154,1971,1972],{"class":160},"  async",[154,1974,1975],{"class":182}," getVtcElectectricL",[154,1977,186],{"class":178},[154,1979,151],{"class":1954},[154,1981,759],{"class":178},[154,1983,1984],{"class":164},"string",[154,1986,1987],{"class":178},"): ",[154,1989,1990],{"class":164},"Promise",[154,1992,858],{"class":178},[154,1994,1995],{"class":164},"StockInformation",[154,1997,1998],{"class":178},"[]> {\n",[154,2000,2001,2004,2007,2009],{"class":156,"line":329},[154,2002,2003],{"class":160},"    const",[154,2005,2006],{"class":164}," availability",[154,2008,169],{"class":168},[154,2010,2011],{"class":178}," [];\n",[154,2013,2014,2016,2019,2021,2023,2026],{"class":156,"line":340},[154,2015,2003],{"class":160},[154,2017,2018],{"class":164}," sku",[154,2020,169],{"class":168},[154,2022,172],{"class":160},[154,2024,2025],{"class":182}," firstValueFrom",[154,2027,2028],{"class":178},"(\n",[154,2030,2031,2034,2036,2039,2041,2044,2046,2049,2052,2055,2058,2060],{"class":156,"line":351},[154,2032,2033],{"class":164},"      this",[154,2035,179],{"class":178},[154,2037,2038],{"class":164},"httpService",[154,2040,179],{"class":178},[154,2042,2043],{"class":182},"get",[154,2045,858],{"class":178},[154,2047,2048],{"class":164},"StocksOnline",[154,2050,2051],{"class":178},">(",[154,2053,2054],{"class":182},"STOCKS_ONLINE",[154,2056,2057],{"class":178},"([",[154,2059,151],{"class":195},[154,2061,2062],{"class":178},"])),\n",[154,2064,2065],{"class":156,"line":527},[154,2066,2067],{"class":178},"    );\n",[154,2069,2070,2072,2075,2077,2079,2081,2084,2087,2089,2092,2095],{"class":156,"line":804},[154,2071,2003],{"class":160},[154,2073,2074],{"class":164}," onlineStocks",[154,2076,169],{"class":168},[154,2078,2018],{"class":164},[154,2080,179],{"class":178},[154,2082,2083],{"class":195},"data",[154,2085,2086],{"class":178},"[",[154,2088,151],{"class":195},[154,2090,2091],{"class":178},"]?.",[154,2093,2094],{"class":195},"stockOnline",[154,2096,2097],{"class":178},";\n",[154,2099,2100],{"class":156,"line":809},[154,2101,206],{"emptyLinePlaceholder":205},[154,2103,2104,2107,2109,2112],{"class":156,"line":817},[154,2105,2106],{"class":164},"    availability",[154,2108,179],{"class":178},[154,2110,2111],{"class":182},"push",[154,2113,2114],{"class":178},"({\n",[154,2116,2117,2120,2122,2125],{"class":156,"line":827},[154,2118,2119],{"class":195},"      type",[154,2121,759],{"class":178},[154,2123,2124],{"class":242},"'Internet'",[154,2126,932],{"class":178},[154,2128,2129,2132,2134,2137],{"class":156,"line":833},[154,2130,2131],{"class":195},"      stocks",[154,2133,759],{"class":178},[154,2135,2136],{"class":195},"onlineStocks",[154,2138,932],{"class":178},[154,2140,2141],{"class":156,"line":1033},[154,2142,2143],{"class":178},"    });\n",[154,2145,2146],{"class":156,"line":1044},[154,2147,206],{"emptyLinePlaceholder":205},[154,2149,2150,2152,2155,2157,2159,2161],{"class":156,"line":1055},[154,2151,2003],{"class":160},[154,2153,2154],{"class":164}," stores",[154,2156,169],{"class":168},[154,2158,172],{"class":160},[154,2160,2025],{"class":182},[154,2162,2028],{"class":178},[154,2164,2165,2167,2169,2171,2173,2175,2177,2180,2182,2185,2187,2189],{"class":156,"line":1062},[154,2166,2033],{"class":164},[154,2168,179],{"class":178},[154,2170,2038],{"class":164},[154,2172,179],{"class":178},[154,2174,2043],{"class":182},[154,2176,858],{"class":178},[154,2178,2179],{"class":164},"StocksStores",[154,2181,2051],{"class":178},[154,2183,2184],{"class":182},"STOCKS_STORE",[154,2186,186],{"class":178},[154,2188,151],{"class":195},[154,2190,2191],{"class":178},")),\n",[154,2193,2194],{"class":156,"line":1067},[154,2195,2067],{"class":178},[154,2197,2198],{"class":156,"line":1072},[154,2199,206],{"emptyLinePlaceholder":205},[154,2201,2202,2204,2206,2208],{"class":156,"line":1084},[154,2203,2106],{"class":164},[154,2205,179],{"class":178},[154,2207,2111],{"class":182},[154,2209,2028],{"class":178},[154,2211,2212,2215,2218,2220,2222,2224,2227,2229],{"class":156,"line":1096},[154,2213,2214],{"class":178},"      ...",[154,2216,2217],{"class":164},"stores",[154,2219,179],{"class":178},[154,2221,2083],{"class":164},[154,2223,179],{"class":178},[154,2225,2226],{"class":164},"responseTO",[154,2228,179],{"class":178},[154,2230,2231],{"class":195},"data\n",[154,2233,2234,2237,2240,2243,2246,2248,2251],{"class":156,"line":1108},[154,2235,2236],{"class":178},"        .",[154,2238,2239],{"class":182},"map",[154,2241,2242],{"class":178},"((",[154,2244,2245],{"class":1954},"store",[154,2247,266],{"class":178},[154,2249,2250],{"class":160},"=>",[154,2252,2253],{"class":178}," ({\n",[154,2255,2256,2259,2261,2263,2265,2268],{"class":156,"line":1119},[154,2257,2258],{"class":195},"          type",[154,2260,759],{"class":178},[154,2262,2245],{"class":164},[154,2264,179],{"class":178},[154,2266,2267],{"class":195},"storeName",[154,2269,932],{"class":178},[154,2271,2272,2275,2277,2279,2281,2284],{"class":156,"line":1130},[154,2273,2274],{"class":195},"          stocks",[154,2276,759],{"class":178},[154,2278,2245],{"class":164},[154,2280,179],{"class":178},[154,2282,2283],{"class":195},"quantity",[154,2285,932],{"class":178},[154,2287,2288],{"class":156,"line":1137},[154,2289,2290],{"class":178},"        }))\n",[154,2292,2293,2295,2298,2300,2302,2304,2307,2309,2311,2314,2316,2319,2322,2324,2326,2328],{"class":156,"line":1142},[154,2294,2236],{"class":178},[154,2296,2297],{"class":182},"sort",[154,2299,2242],{"class":178},[154,2301,30],{"class":1954},[154,2303,192],{"class":178},[154,2305,2306],{"class":1954},"b",[154,2308,266],{"class":178},[154,2310,2250],{"class":160},[154,2312,2313],{"class":164}," b",[154,2315,179],{"class":178},[154,2317,2318],{"class":195},"stocks",[154,2320,2321],{"class":168}," -",[154,2323,407],{"class":164},[154,2325,179],{"class":178},[154,2327,2318],{"class":195},[154,2329,2330],{"class":178},"),\n",[154,2332,2333],{"class":156,"line":1147},[154,2334,2067],{"class":178},[154,2336,2337],{"class":156,"line":1159},[154,2338,206],{"emptyLinePlaceholder":205},[154,2340,2341,2344,2346,2348,2350,2352,2354,2356,2358],{"class":156,"line":1171},[154,2342,2343],{"class":160},"    return",[154,2345,2006],{"class":164},[154,2347,179],{"class":178},[154,2349,2239],{"class":182},[154,2351,2242],{"class":178},[154,2353,2245],{"class":1954},[154,2355,266],{"class":178},[154,2357,2250],{"class":160},[154,2359,2253],{"class":178},[154,2361,2362,2364,2366],{"class":156,"line":1183},[154,2363,2214],{"class":178},[154,2365,2245],{"class":195},[154,2367,932],{"class":178},[154,2369,2370,2373,2375,2377,2379,2381,2384,2387,2390,2393,2396,2399],{"class":156,"line":1194},[154,2371,2372],{"class":195},"      availability",[154,2374,759],{"class":178},[154,2376,2245],{"class":164},[154,2378,179],{"class":178},[154,2380,2318],{"class":195},[154,2382,2383],{"class":168}," >",[154,2385,2386],{"class":520}," 0",[154,2388,2389],{"class":160}," ?",[154,2391,2392],{"class":242}," 'available'",[154,2394,2395],{"class":160}," :",[154,2397,2398],{"class":242}," 'not_available'",[154,2400,932],{"class":178},[154,2402,2403],{"class":156,"line":1201},[154,2404,2405],{"class":178},"    }));\n",[154,2407,2408],{"class":156,"line":1207},[154,2409,830],{"class":178},[154,2411,2412],{"class":156,"line":1213},[154,2413,836],{"class":178},[12,2415,2416],{},"Une petite page en Mustashe pour afficher en HTML le contenu de la page et c'est parti !",[12,2418,2419],{},[119,2420],{"alt":2421,"className":2422,"src":2423},"La page WEB",[123],"\u002FProgrammation\u002Fachat_velo\u002Fpage_web.png",[56,2425,2427],{"id":2426},"le-déploiement","Le déploiement",[12,2429,2430,2431,179],{},"Afin d'améliorer mes compétences professionnelles je décide de déployer cette application sur AWS, et afin que cette application me coûte le moins cher possible, je\nvais déployer cette application dans une Lambda à l'aide du framework ",[30,2432,2435],{"href":2433,"rel":2434},"https:\u002F\u002Fwww.serverless.com\u002F",[132],"Serverless",[12,2437,2438,2439,179],{},"Viens alors l'adaptation du l'application Nest.JS pour utiliser le framework Serverless. Je laisse la documentation de Nest.JS expliquer comment faire:\n",[30,2440,2443],{"href":2441,"rel":2442},"https:\u002F\u002Fdocs.nestjs.com\u002Ffaq\u002Fserverless",[132],"Nest.JS - Serverless",[145,2445,2449],{"className":2446,"code":2447,"language":2448,"meta":35,"style":35},"language-yaml shiki shiki-themes one-dark-pro","service: triathlon\nframeworkVersion: \"2\"\n\nplugins:\n  - serverless-plugin-log-retention\n  - serverless-offline\n  - serverless-domain-manager\n\ncustom:\n  region: eu-central-1\n  logRetentionInDays: 7\n  serverless-offline:\n    noPrependStageInUrl: true\n    allowCache: false\n  customDomain:\n    domainName: \"decat-${self:provider.stage}.aws.shadoware.org\"\n    basePath: \"\"\n    certificateName: \"aws.shadoware.org\"\n    createRoute53Record: true\n    endpointType: \"regional\"\n    securityPolicy: tls_1_2\n    apiType: rest\n    autoDomain: false\n\nprovider:\n  name: aws\n  region: ${self:custom.region}\n  runtime: nodejs12.x\n  lambdaHashingVersion: \"20201221\"\n  stage: ${opt:stage, 'dev'}\n  environment:\n    NODE_OPTIONS: \"--max-http-header-size=80000\"\n\npackage:\n  patterns:\n    - \"!.\u002F**\"\n    - dist\u002F**\n    - views\u002F**\n\nfunctions:\n  api:\n    handler: dist\u002Fmain.handler\n    environment:\n      region: ${self:custom.region}\n    events:\n      - http:\n          path: \u002F\n          method: ANY\n      - http:\n          path: \u002F{proxy+}\n          method: ANY\n","yaml",[151,2450,2451,2461,2471,2475,2483,2491,2498,2505,2509,2516,2526,2536,2543,2553,2563,2570,2580,2590,2600,2609,2619,2629,2639,2648,2652,2659,2669,2678,2688,2698,2708,2715,2725,2729,2736,2743,2751,2758,2765,2769,2776,2783,2793,2800,2809,2816,2825,2835,2845,2853,2862],{"__ignoreMap":35},[154,2452,2453,2456,2458],{"class":156,"line":157},[154,2454,2455],{"class":195},"service",[154,2457,759],{"class":178},[154,2459,2460],{"class":242},"triathlon\n",[154,2462,2463,2466,2468],{"class":156,"line":202},[154,2464,2465],{"class":195},"frameworkVersion",[154,2467,759],{"class":178},[154,2469,2470],{"class":242},"\"2\"\n",[154,2472,2473],{"class":156,"line":209},[154,2474,206],{"emptyLinePlaceholder":205},[154,2476,2477,2480],{"class":156,"line":307},[154,2478,2479],{"class":195},"plugins",[154,2481,2482],{"class":178},":\n",[154,2484,2485,2488],{"class":156,"line":318},[154,2486,2487],{"class":178},"  - ",[154,2489,2490],{"class":242},"serverless-plugin-log-retention\n",[154,2492,2493,2495],{"class":156,"line":329},[154,2494,2487],{"class":178},[154,2496,2497],{"class":242},"serverless-offline\n",[154,2499,2500,2502],{"class":156,"line":340},[154,2501,2487],{"class":178},[154,2503,2504],{"class":242},"serverless-domain-manager\n",[154,2506,2507],{"class":156,"line":351},[154,2508,206],{"emptyLinePlaceholder":205},[154,2510,2511,2514],{"class":156,"line":527},[154,2512,2513],{"class":195},"custom",[154,2515,2482],{"class":178},[154,2517,2518,2521,2523],{"class":156,"line":804},[154,2519,2520],{"class":195},"  region",[154,2522,759],{"class":178},[154,2524,2525],{"class":242},"eu-central-1\n",[154,2527,2528,2531,2533],{"class":156,"line":809},[154,2529,2530],{"class":195},"  logRetentionInDays",[154,2532,759],{"class":178},[154,2534,2535],{"class":520},"7\n",[154,2537,2538,2541],{"class":156,"line":817},[154,2539,2540],{"class":195},"  serverless-offline",[154,2542,2482],{"class":178},[154,2544,2545,2548,2550],{"class":156,"line":827},[154,2546,2547],{"class":195},"    noPrependStageInUrl",[154,2549,759],{"class":178},[154,2551,2552],{"class":520},"true\n",[154,2554,2555,2558,2560],{"class":156,"line":833},[154,2556,2557],{"class":195},"    allowCache",[154,2559,759],{"class":178},[154,2561,2562],{"class":520},"false\n",[154,2564,2565,2568],{"class":156,"line":1033},[154,2566,2567],{"class":195},"  customDomain",[154,2569,2482],{"class":178},[154,2571,2572,2575,2577],{"class":156,"line":1044},[154,2573,2574],{"class":195},"    domainName",[154,2576,759],{"class":178},[154,2578,2579],{"class":242},"\"decat-${self:provider.stage}.aws.shadoware.org\"\n",[154,2581,2582,2585,2587],{"class":156,"line":1055},[154,2583,2584],{"class":195},"    basePath",[154,2586,759],{"class":178},[154,2588,2589],{"class":242},"\"\"\n",[154,2591,2592,2595,2597],{"class":156,"line":1062},[154,2593,2594],{"class":195},"    certificateName",[154,2596,759],{"class":178},[154,2598,2599],{"class":242},"\"aws.shadoware.org\"\n",[154,2601,2602,2605,2607],{"class":156,"line":1067},[154,2603,2604],{"class":195},"    createRoute53Record",[154,2606,759],{"class":178},[154,2608,2552],{"class":520},[154,2610,2611,2614,2616],{"class":156,"line":1072},[154,2612,2613],{"class":195},"    endpointType",[154,2615,759],{"class":178},[154,2617,2618],{"class":242},"\"regional\"\n",[154,2620,2621,2624,2626],{"class":156,"line":1084},[154,2622,2623],{"class":195},"    securityPolicy",[154,2625,759],{"class":178},[154,2627,2628],{"class":242},"tls_1_2\n",[154,2630,2631,2634,2636],{"class":156,"line":1096},[154,2632,2633],{"class":195},"    apiType",[154,2635,759],{"class":178},[154,2637,2638],{"class":242},"rest\n",[154,2640,2641,2644,2646],{"class":156,"line":1108},[154,2642,2643],{"class":195},"    autoDomain",[154,2645,759],{"class":178},[154,2647,2562],{"class":520},[154,2649,2650],{"class":156,"line":1119},[154,2651,206],{"emptyLinePlaceholder":205},[154,2653,2654,2657],{"class":156,"line":1130},[154,2655,2656],{"class":195},"provider",[154,2658,2482],{"class":178},[154,2660,2661,2664,2666],{"class":156,"line":1137},[154,2662,2663],{"class":195},"  name",[154,2665,759],{"class":178},[154,2667,2668],{"class":242},"aws\n",[154,2670,2671,2673,2675],{"class":156,"line":1142},[154,2672,2520],{"class":195},[154,2674,759],{"class":178},[154,2676,2677],{"class":242},"${self:custom.region}\n",[154,2679,2680,2683,2685],{"class":156,"line":1147},[154,2681,2682],{"class":195},"  runtime",[154,2684,759],{"class":178},[154,2686,2687],{"class":242},"nodejs12.x\n",[154,2689,2690,2693,2695],{"class":156,"line":1159},[154,2691,2692],{"class":195},"  lambdaHashingVersion",[154,2694,759],{"class":178},[154,2696,2697],{"class":242},"\"20201221\"\n",[154,2699,2700,2703,2705],{"class":156,"line":1171},[154,2701,2702],{"class":195},"  stage",[154,2704,759],{"class":178},[154,2706,2707],{"class":242},"${opt:stage, 'dev'}\n",[154,2709,2710,2713],{"class":156,"line":1183},[154,2711,2712],{"class":195},"  environment",[154,2714,2482],{"class":178},[154,2716,2717,2720,2722],{"class":156,"line":1194},[154,2718,2719],{"class":195},"    NODE_OPTIONS",[154,2721,759],{"class":178},[154,2723,2724],{"class":242},"\"--max-http-header-size=80000\"\n",[154,2726,2727],{"class":156,"line":1201},[154,2728,206],{"emptyLinePlaceholder":205},[154,2730,2731,2734],{"class":156,"line":1207},[154,2732,2733],{"class":195},"package",[154,2735,2482],{"class":178},[154,2737,2738,2741],{"class":156,"line":1213},[154,2739,2740],{"class":195},"  patterns",[154,2742,2482],{"class":178},[154,2744,2745,2748],{"class":156,"line":1592},[154,2746,2747],{"class":178},"    - ",[154,2749,2750],{"class":242},"\"!.\u002F**\"\n",[154,2752,2753,2755],{"class":156,"line":1603},[154,2754,2747],{"class":178},[154,2756,2757],{"class":242},"dist\u002F**\n",[154,2759,2760,2762],{"class":156,"line":1614},[154,2761,2747],{"class":178},[154,2763,2764],{"class":242},"views\u002F**\n",[154,2766,2767],{"class":156,"line":1625},[154,2768,206],{"emptyLinePlaceholder":205},[154,2770,2771,2774],{"class":156,"line":1637},[154,2772,2773],{"class":195},"functions",[154,2775,2482],{"class":178},[154,2777,2778,2781],{"class":156,"line":1649},[154,2779,2780],{"class":195},"  api",[154,2782,2482],{"class":178},[154,2784,2785,2788,2790],{"class":156,"line":1660},[154,2786,2787],{"class":195},"    handler",[154,2789,759],{"class":178},[154,2791,2792],{"class":242},"dist\u002Fmain.handler\n",[154,2794,2795,2798],{"class":156,"line":1669},[154,2796,2797],{"class":195},"    environment",[154,2799,2482],{"class":178},[154,2801,2802,2805,2807],{"class":156,"line":1674},[154,2803,2804],{"class":195},"      region",[154,2806,759],{"class":178},[154,2808,2677],{"class":242},[154,2810,2811,2814],{"class":156,"line":1679},[154,2812,2813],{"class":195},"    events",[154,2815,2482],{"class":178},[154,2817,2818,2821,2823],{"class":156,"line":1690},[154,2819,2820],{"class":178},"      - ",[154,2822,722],{"class":195},[154,2824,2482],{"class":178},[154,2826,2827,2830,2832],{"class":156,"line":1701},[154,2828,2829],{"class":195},"          path",[154,2831,759],{"class":178},[154,2833,2834],{"class":242},"\u002F\n",[154,2836,2837,2840,2842],{"class":156,"line":1712},[154,2838,2839],{"class":195},"          method",[154,2841,759],{"class":178},[154,2843,2844],{"class":242},"ANY\n",[154,2846,2847,2849,2851],{"class":156,"line":1723},[154,2848,2820],{"class":178},[154,2850,722],{"class":195},[154,2852,2482],{"class":178},[154,2854,2855,2857,2859],{"class":156,"line":1734},[154,2856,2829],{"class":195},[154,2858,759],{"class":178},[154,2860,2861],{"class":242},"\u002F{proxy+}\n",[154,2863,2864,2866,2868],{"class":156,"line":1745},[154,2865,2839],{"class":195},[154,2867,759],{"class":178},[154,2869,2844],{"class":242},[12,2871,2872],{},"Il ne reste plus qu'à lancer le déploiement:",[145,2874,2876],{"className":252,"code":2875,"language":254,"meta":35,"style":35},"npx serverless deploy\n",[151,2877,2878],{"__ignoreMap":35},[154,2879,2880,2883,2886],{"class":156,"line":157},[154,2881,2882],{"class":182},"npx",[154,2884,2885],{"class":242}," serverless",[154,2887,2888],{"class":242}," deploy\n",[12,2890,2891],{},"Nous avons alors notre belle page de déployée.",[56,2893,2895],{"id":2894},"la-suite-de-laventure","La suite de l'aventure",[12,2897,2898],{},"Me voilà avec un petit programme qui me permet de facilement visualiser les stocks du vélo que je souhaite. J'en profite également pour ajouter le même\nproduit en taille XL (où il y a du stock) et un VTT.",[12,2900,2901],{},"Le problème c'est que je dois continuer à rafraîchir la page, même si c'est plus rapide.",[12,2903,2904],{},"Pour l'anecdocte, après une matinée de glandouille (c'est les vacances), je décide de rafraîchir la page vers midi. Je vois \"Stock: 1\". Heureux, je me précipite pour\nacheter le seul exemplaire. Mais lors de la commande je tombe sur le fameux message: \"Internal Server Error\" dans un bandeau rouge en haut de l'écran.",[12,2906,2907],{},"J'appelle le service client qui m'informe que cela provient du fait qu'il n'y a déjà plus de stock mais que le stock du site n'est mis à jours que tout les 24h.\nJe m'en doutais mais le message d'erreur laisse à désirer un peu.",[12,2909,2910],{},"Malgrès l'apparition soudaine d'un stock, je n'ai recu aucun mail pour me prévenir (relatif à la fonctionnalité \"M'avertir lorsque le produit est à nouveau disponible\"). Il\nme faut un moyen d'être averti dans les premiers dès qu'il y a du stock.",[12,2912,2913],{},"La situation s'est reproduite sans que je sois averti par mail.",[12,2915,2916],{},"Bref, il me faut une solution !",[56,2918,2920],{"id":2919},"la-notification","La notification",[12,2922,2923],{},"Je profite donc des services AWS pour développer une nouvelle fonctionnalité. Cette dernière est simple: je vais faire une requête à mon\nservice toutes les 30 minutes, pour vérifier le stock, et si ce dernier bouge, j'envoie un SMS.",[12,2925,2926],{},"Le coût actuel d'envoi d'un SMS vers la France sur AWS est de 0.06933$. Donc si je recois 1 SMS par heure en journée, je vais aller vers 1$ par jour.\nC'est à prévoir pour mon budget. Maintenant je veux recevoir le minimum de SMS. Je n'ai pas envie de recevoir de SMS quand le stock ne change pas. Il faut donc\nque je puisse comparer le stock entre l'état précédent et l'etat actuel.",[12,2928,2929],{},"Quand on utilise les lambda (fonction) d'AWS, il n'y a pas de serveur de démarré. Donc je ne peux pas stocker les valeurs précédentes temporairement en\nmémoire pour contrôler les changements (ce qui ne serait pas une bonne pratique, mais un truc rapide à faire pour un dev maison).",[12,2931,2932],{},"Je stocke donc le dernier accès au site dans une base de données de type Document de chez AWS: DynamoDB.",[12,2934,2935],{},"Le service d'envoi de SMS est simple (et prend un numéro de téléphone et un message):",[145,2937,2939],{"className":147,"code":2938,"language":149,"meta":35,"style":35},"  \u002F**\n   * Sends a SMS message to the specificed phone number.\n   * Returns the message ID from SNS\n   * @param   {String} phoneNumber\n   * @param   {String} message\n   * @returns {Promise|String}\n   *\u002F\n  async sendMessage(phoneNumber, message) {\n    await this.SNS.setSMSAttributes({\n      attributes: { DefaultSMSType: 'Promotional' },\n    }).promise();\n\n    const smsData = {\n      Message: message,\n      PhoneNumber: phoneNumber,\n      MessageAttributes: {\n        'AWS.SNS.SMS.SenderID': {\n          DataType: 'String',\n          StringValue: 'DecatStock',\n        },\n      },\n    };\n\n    this.logger.log(\n      `Send message to ${phoneNumber} (${message.length}):\\n${message}`,\n    );\n    const response = await this.SNS.publish(smsData).promise();\n\n    this.logger.log(`Response of SMS is ${JSON.stringify(response)}`);\n    return response.MessageId;\n  }\n",[151,2940,2941,2947,2952,2957,2973,2984,2994,2999,3019,3039,3058,3069,3073,3084,3095,3106,3113,3120,3132,3144,3149,3153,3158,3162,3178,3221,3225,3259,3263,3303,3316],{"__ignoreMap":35},[154,2942,2943],{"class":156,"line":157},[154,2944,2946],{"class":2945},"sV9Aq","  \u002F**\n",[154,2948,2949],{"class":156,"line":202},[154,2950,2951],{"class":2945},"   * Sends a SMS message to the specificed phone number.\n",[154,2953,2954],{"class":156,"line":209},[154,2955,2956],{"class":2945},"   * Returns the message ID from SNS\n",[154,2958,2959,2962,2966,2970],{"class":156,"line":307},[154,2960,2961],{"class":2945},"   * ",[154,2963,2965],{"class":2964},"shdRp","@param",[154,2967,2969],{"class":2968},"sKU4T","   {String}",[154,2971,2972],{"class":1954}," phoneNumber\n",[154,2974,2975,2977,2979,2981],{"class":156,"line":318},[154,2976,2961],{"class":2945},[154,2978,2965],{"class":2964},[154,2980,2969],{"class":2968},[154,2982,2983],{"class":1954}," message\n",[154,2985,2986,2988,2991],{"class":156,"line":329},[154,2987,2961],{"class":2945},[154,2989,2990],{"class":2964},"@returns",[154,2992,2993],{"class":2968}," {Promise|String}\n",[154,2995,2996],{"class":156,"line":340},[154,2997,2998],{"class":2945},"   *\u002F\n",[154,3000,3001,3003,3006,3008,3011,3013,3016],{"class":156,"line":351},[154,3002,1972],{"class":195},[154,3004,3005],{"class":182}," sendMessage",[154,3007,186],{"class":178},[154,3009,3010],{"class":195},"phoneNumber",[154,3012,192],{"class":178},[154,3014,3015],{"class":195},"message",[154,3017,3018],{"class":178},") {\n",[154,3020,3021,3024,3027,3029,3032,3034,3037],{"class":156,"line":527},[154,3022,3023],{"class":160},"    await",[154,3025,3026],{"class":164}," this",[154,3028,179],{"class":178},[154,3030,3031],{"class":164},"SNS",[154,3033,179],{"class":178},[154,3035,3036],{"class":182},"setSMSAttributes",[154,3038,2114],{"class":178},[154,3040,3041,3044,3047,3050,3052,3055],{"class":156,"line":804},[154,3042,3043],{"class":195},"      attributes",[154,3045,3046],{"class":178},": { ",[154,3048,3049],{"class":195},"DefaultSMSType",[154,3051,759],{"class":178},[154,3053,3054],{"class":242},"'Promotional'",[154,3056,3057],{"class":178}," },\n",[154,3059,3060,3063,3066],{"class":156,"line":809},[154,3061,3062],{"class":178},"    }).",[154,3064,3065],{"class":182},"promise",[154,3067,3068],{"class":178},"();\n",[154,3070,3071],{"class":156,"line":817},[154,3072,206],{"emptyLinePlaceholder":205},[154,3074,3075,3077,3080,3082],{"class":156,"line":827},[154,3076,2003],{"class":160},[154,3078,3079],{"class":164}," smsData",[154,3081,169],{"class":168},[154,3083,1941],{"class":178},[154,3085,3086,3089,3091,3093],{"class":156,"line":833},[154,3087,3088],{"class":195},"      Message",[154,3090,759],{"class":178},[154,3092,3015],{"class":195},[154,3094,932],{"class":178},[154,3096,3097,3100,3102,3104],{"class":156,"line":1033},[154,3098,3099],{"class":195},"      PhoneNumber",[154,3101,759],{"class":178},[154,3103,3010],{"class":195},[154,3105,932],{"class":178},[154,3107,3108,3111],{"class":156,"line":1044},[154,3109,3110],{"class":195},"      MessageAttributes",[154,3112,751],{"class":178},[154,3114,3115,3118],{"class":156,"line":1055},[154,3116,3117],{"class":242},"        'AWS.SNS.SMS.SenderID'",[154,3119,751],{"class":178},[154,3121,3122,3125,3127,3130],{"class":156,"line":1062},[154,3123,3124],{"class":195},"          DataType",[154,3126,759],{"class":178},[154,3128,3129],{"class":242},"'String'",[154,3131,932],{"class":178},[154,3133,3134,3137,3139,3142],{"class":156,"line":1067},[154,3135,3136],{"class":195},"          StringValue",[154,3138,759],{"class":178},[154,3140,3141],{"class":242},"'DecatStock'",[154,3143,932],{"class":178},[154,3145,3146],{"class":156,"line":1072},[154,3147,3148],{"class":178},"        },\n",[154,3150,3151],{"class":156,"line":1084},[154,3152,1475],{"class":178},[154,3154,3155],{"class":156,"line":1096},[154,3156,3157],{"class":178},"    };\n",[154,3159,3160],{"class":156,"line":1108},[154,3161,206],{"emptyLinePlaceholder":205},[154,3163,3164,3167,3169,3172,3174,3176],{"class":156,"line":1119},[154,3165,3166],{"class":164},"    this",[154,3168,179],{"class":178},[154,3170,3171],{"class":164},"logger",[154,3173,179],{"class":178},[154,3175,217],{"class":182},[154,3177,2028],{"class":178},[154,3179,3180,3183,3186,3188,3191,3193,3195,3197,3199,3202,3204,3207,3210,3212,3214,3216,3219],{"class":156,"line":1130},[154,3181,3182],{"class":242},"      `Send message to ",[154,3184,3185],{"class":160},"${",[154,3187,3010],{"class":195},[154,3189,3190],{"class":160},"}",[154,3192,500],{"class":242},[154,3194,3185],{"class":160},[154,3196,3015],{"class":164},[154,3198,179],{"class":178},[154,3200,3201],{"class":195},"length",[154,3203,3190],{"class":160},[154,3205,3206],{"class":242},"):",[154,3208,3209],{"class":168},"\\n",[154,3211,3185],{"class":160},[154,3213,3015],{"class":195},[154,3215,3190],{"class":160},[154,3217,3218],{"class":242},"`",[154,3220,932],{"class":178},[154,3222,3223],{"class":156,"line":1137},[154,3224,2067],{"class":178},[154,3226,3227,3229,3232,3234,3236,3238,3240,3242,3244,3247,3249,3252,3255,3257],{"class":156,"line":1142},[154,3228,2003],{"class":160},[154,3230,3231],{"class":164}," response",[154,3233,169],{"class":168},[154,3235,172],{"class":160},[154,3237,3026],{"class":164},[154,3239,179],{"class":178},[154,3241,3031],{"class":164},[154,3243,179],{"class":178},[154,3245,3246],{"class":182},"publish",[154,3248,186],{"class":178},[154,3250,3251],{"class":195},"smsData",[154,3253,3254],{"class":178},").",[154,3256,3065],{"class":182},[154,3258,3068],{"class":178},[154,3260,3261],{"class":156,"line":1147},[154,3262,206],{"emptyLinePlaceholder":205},[154,3264,3265,3267,3269,3271,3273,3275,3277,3280,3282,3285,3287,3290,3292,3295,3297,3299,3301],{"class":156,"line":1159},[154,3266,3166],{"class":164},[154,3268,179],{"class":178},[154,3270,3171],{"class":164},[154,3272,179],{"class":178},[154,3274,217],{"class":182},[154,3276,186],{"class":178},[154,3278,3279],{"class":242},"`Response of SMS is ",[154,3281,3185],{"class":160},[154,3283,3284],{"class":164},"JSON",[154,3286,179],{"class":178},[154,3288,3289],{"class":182},"stringify",[154,3291,186],{"class":178},[154,3293,3294],{"class":195},"response",[154,3296,509],{"class":178},[154,3298,3190],{"class":160},[154,3300,3218],{"class":242},[154,3302,199],{"class":178},[154,3304,3305,3307,3309,3311,3314],{"class":156,"line":1171},[154,3306,2343],{"class":160},[154,3308,3231],{"class":164},[154,3310,179],{"class":178},[154,3312,3313],{"class":195},"MessageId",[154,3315,2097],{"class":178},[154,3317,3318],{"class":156,"line":1183},[154,3319,830],{"class":178},[12,3321,3322],{},"Le service permettant de lire et d'écrire dans la base DynamoDB est lui aussi très simple et ne possède que deux méthodes:",[145,3324,3326],{"className":147,"code":3325,"language":149,"meta":35,"style":35},"class {\n  async findOneById(sku: string): Promise\u003CDecathlonStatus> {\n    try {\n      const result = await dynamoDB\n        .get({\n          TableName: process.env.DECATHLON_TABLE_NAME,\n          Key: { id: sku },\n        })\n        .promise();\n      return result.Item as DecathlonStatus;\n    } catch (error) {\n      this.logger.warn(`Can't read the table ${sku}: ${error.message}`);\n      return null;\n    }\n  }\n\n  async update(\n    sku: string,\n    items: StockInformations\n  ): Promise\u003CDecathlonStatus> {\n    const status = new DecathlonStatus();\n    status.id = sku;\n    status.informations = items;\n\n    try {\n      await dynamoDB\n        .put({\n          TableName: process.env.DECATHLON_TABLE_NAME,\n          Item: status,\n        })\n        .promise();\n      return status;\n    } catch (error) {\n      throw new InternalServerErrorException(error);\n    }\n  }\n}\n",[151,3327,3328,3335,3363,3370,3385,3393,3415,3431,3436,3444,3464,3479,3519,3528,3532,3536,3540,3549,3560,3570,3583,3599,3614,3630,3634,3640,3647,3656,3674,3686,3690,3698,3706,3718,3734,3738,3742],{"__ignoreMap":35},[154,3329,3330,3333],{"class":156,"line":157},[154,3331,3332],{"class":160},"class",[154,3334,1941],{"class":178},[154,3336,3337,3339,3342,3344,3347,3349,3351,3353,3355,3357,3360],{"class":156,"line":202},[154,3338,1972],{"class":160},[154,3340,3341],{"class":182}," findOneById",[154,3343,186],{"class":178},[154,3345,3346],{"class":1954},"sku",[154,3348,759],{"class":178},[154,3350,1984],{"class":164},[154,3352,1987],{"class":178},[154,3354,1990],{"class":164},[154,3356,858],{"class":178},[154,3358,3359],{"class":164},"DecathlonStatus",[154,3361,3362],{"class":178},"> {\n",[154,3364,3365,3368],{"class":156,"line":209},[154,3366,3367],{"class":160},"    try",[154,3369,1941],{"class":178},[154,3371,3372,3375,3378,3380,3382],{"class":156,"line":307},[154,3373,3374],{"class":160},"      const",[154,3376,3377],{"class":164}," result",[154,3379,169],{"class":168},[154,3381,172],{"class":160},[154,3383,3384],{"class":195}," dynamoDB\n",[154,3386,3387,3389,3391],{"class":156,"line":318},[154,3388,2236],{"class":178},[154,3390,2043],{"class":182},[154,3392,2114],{"class":178},[154,3394,3395,3398,3400,3403,3405,3408,3410,3413],{"class":156,"line":329},[154,3396,3397],{"class":195},"          TableName",[154,3399,759],{"class":178},[154,3401,3402],{"class":164},"process",[154,3404,179],{"class":178},[154,3406,3407],{"class":164},"env",[154,3409,179],{"class":178},[154,3411,3412],{"class":195},"DECATHLON_TABLE_NAME",[154,3414,932],{"class":178},[154,3416,3417,3420,3422,3425,3427,3429],{"class":156,"line":340},[154,3418,3419],{"class":195},"          Key",[154,3421,3046],{"class":178},[154,3423,3424],{"class":195},"id",[154,3426,759],{"class":178},[154,3428,3346],{"class":195},[154,3430,3057],{"class":178},[154,3432,3433],{"class":156,"line":351},[154,3434,3435],{"class":178},"        })\n",[154,3437,3438,3440,3442],{"class":156,"line":527},[154,3439,2236],{"class":178},[154,3441,3065],{"class":182},[154,3443,3068],{"class":178},[154,3445,3446,3449,3451,3453,3456,3459,3462],{"class":156,"line":804},[154,3447,3448],{"class":160},"      return",[154,3450,3377],{"class":164},[154,3452,179],{"class":178},[154,3454,3455],{"class":195},"Item",[154,3457,3458],{"class":160}," as",[154,3460,3461],{"class":164}," DecathlonStatus",[154,3463,2097],{"class":178},[154,3465,3466,3469,3472,3474,3477],{"class":156,"line":809},[154,3467,3468],{"class":178},"    } ",[154,3470,3471],{"class":160},"catch",[154,3473,500],{"class":178},[154,3475,3476],{"class":195},"error",[154,3478,3018],{"class":178},[154,3480,3481,3483,3485,3487,3489,3492,3494,3497,3499,3501,3503,3505,3507,3509,3511,3513,3515,3517],{"class":156,"line":817},[154,3482,2033],{"class":164},[154,3484,179],{"class":178},[154,3486,3171],{"class":164},[154,3488,179],{"class":178},[154,3490,3491],{"class":182},"warn",[154,3493,186],{"class":178},[154,3495,3496],{"class":242},"`Can't read the table ",[154,3498,3185],{"class":160},[154,3500,3346],{"class":195},[154,3502,3190],{"class":160},[154,3504,759],{"class":242},[154,3506,3185],{"class":160},[154,3508,3476],{"class":164},[154,3510,179],{"class":178},[154,3512,3015],{"class":195},[154,3514,3190],{"class":160},[154,3516,3218],{"class":242},[154,3518,199],{"class":178},[154,3520,3521,3523,3526],{"class":156,"line":827},[154,3522,3448],{"class":160},[154,3524,3525],{"class":520}," null",[154,3527,2097],{"class":178},[154,3529,3530],{"class":156,"line":833},[154,3531,1204],{"class":178},[154,3533,3534],{"class":156,"line":1033},[154,3535,830],{"class":178},[154,3537,3538],{"class":156,"line":1044},[154,3539,206],{"emptyLinePlaceholder":205},[154,3541,3542,3544,3547],{"class":156,"line":1055},[154,3543,1972],{"class":160},[154,3545,3546],{"class":182}," update",[154,3548,2028],{"class":178},[154,3550,3551,3554,3556,3558],{"class":156,"line":1062},[154,3552,3553],{"class":1954},"    sku",[154,3555,759],{"class":178},[154,3557,1984],{"class":164},[154,3559,932],{"class":178},[154,3561,3562,3565,3567],{"class":156,"line":1067},[154,3563,3564],{"class":1954},"    items",[154,3566,759],{"class":178},[154,3568,3569],{"class":164},"StockInformations\n",[154,3571,3572,3575,3577,3579,3581],{"class":156,"line":1072},[154,3573,3574],{"class":178},"  ): ",[154,3576,1990],{"class":164},[154,3578,858],{"class":178},[154,3580,3359],{"class":164},[154,3582,3362],{"class":178},[154,3584,3585,3587,3590,3592,3595,3597],{"class":156,"line":1084},[154,3586,2003],{"class":160},[154,3588,3589],{"class":164}," status",[154,3591,169],{"class":168},[154,3593,3594],{"class":160}," new",[154,3596,3461],{"class":182},[154,3598,3068],{"class":178},[154,3600,3601,3604,3606,3608,3610,3612],{"class":156,"line":1096},[154,3602,3603],{"class":164},"    status",[154,3605,179],{"class":178},[154,3607,3424],{"class":195},[154,3609,169],{"class":168},[154,3611,2018],{"class":195},[154,3613,2097],{"class":178},[154,3615,3616,3618,3620,3623,3625,3628],{"class":156,"line":1108},[154,3617,3603],{"class":164},[154,3619,179],{"class":178},[154,3621,3622],{"class":195},"informations",[154,3624,169],{"class":168},[154,3626,3627],{"class":195}," items",[154,3629,2097],{"class":178},[154,3631,3632],{"class":156,"line":1119},[154,3633,206],{"emptyLinePlaceholder":205},[154,3635,3636,3638],{"class":156,"line":1130},[154,3637,3367],{"class":160},[154,3639,1941],{"class":178},[154,3641,3642,3645],{"class":156,"line":1137},[154,3643,3644],{"class":160},"      await",[154,3646,3384],{"class":195},[154,3648,3649,3651,3654],{"class":156,"line":1142},[154,3650,2236],{"class":178},[154,3652,3653],{"class":182},"put",[154,3655,2114],{"class":178},[154,3657,3658,3660,3662,3664,3666,3668,3670,3672],{"class":156,"line":1147},[154,3659,3397],{"class":195},[154,3661,759],{"class":178},[154,3663,3402],{"class":164},[154,3665,179],{"class":178},[154,3667,3407],{"class":164},[154,3669,179],{"class":178},[154,3671,3412],{"class":195},[154,3673,932],{"class":178},[154,3675,3676,3679,3681,3684],{"class":156,"line":1159},[154,3677,3678],{"class":195},"          Item",[154,3680,759],{"class":178},[154,3682,3683],{"class":195},"status",[154,3685,932],{"class":178},[154,3687,3688],{"class":156,"line":1171},[154,3689,3435],{"class":178},[154,3691,3692,3694,3696],{"class":156,"line":1183},[154,3693,2236],{"class":178},[154,3695,3065],{"class":182},[154,3697,3068],{"class":178},[154,3699,3700,3702,3704],{"class":156,"line":1194},[154,3701,3448],{"class":160},[154,3703,3589],{"class":195},[154,3705,2097],{"class":178},[154,3707,3708,3710,3712,3714,3716],{"class":156,"line":1201},[154,3709,3468],{"class":178},[154,3711,3471],{"class":160},[154,3713,500],{"class":178},[154,3715,3476],{"class":195},[154,3717,3018],{"class":178},[154,3719,3720,3723,3725,3728,3730,3732],{"class":156,"line":1207},[154,3721,3722],{"class":160},"      throw",[154,3724,3594],{"class":160},[154,3726,3727],{"class":182}," InternalServerErrorException",[154,3729,186],{"class":178},[154,3731,3476],{"class":195},[154,3733,199],{"class":178},[154,3735,3736],{"class":156,"line":1213},[154,3737,1204],{"class":178},[154,3739,3740],{"class":156,"line":1592},[154,3741,830],{"class":178},[154,3743,3744],{"class":156,"line":1603},[154,3745,836],{"class":178},[12,3747,3748],{},"Le but est bien de lire le status et d'écrire le status pour un produit.",[12,3750,3751],{},"Le service qui sera appellé de façon régulière est relativement simple. Il va:",[99,3753,3754,3761,3768],{},[102,3755,3756,3757,3760],{},"appeler le service d'API ",[151,3758,3759],{},"REST"," pour vérifier le stock en live,",[102,3762,3763,3764,3767],{},"appeler la service ",[151,3765,3766],{},"DynamoDB"," pour récupérer le dernier stock en base de données,",[102,3769,3770],{},"et faire la différences entre les deux, et s'il y en a une: envoyer un SMS.",[145,3772,3774],{"className":147,"code":3773,"language":149,"meta":35,"style":35},"export class AvailibilityCheckerService {\n  private logger = new Logger(AvailibilityCheckerService.name);\n\n  constructor(\n    private service: AppService,\n    private decathlonService: DecathlonsService,\n    private smsService: SMSService,\n  ) {}\n\n  async checkAvailibility() {\n    const message = (\n      await Promise.all(\n        PRODUCTS.map(\n          async (product) =>\n            await this.checkAvailabilityOfSku(product.code, product.name),\n        ),\n      )\n    )\n      .filter((message) => !!message)\n      .join('\\n\\n');\n\n    if (message.length) {\n      await this.smsService.sendMessage(process.env.PHONE_NUMBER, message);\n    }\n  }\n\n  async checkAvailabilityOfSku(code: string, name: string) {\n    const stocks = await this.service.getVtcElectectricL(code);\n    const oldStocks = await this.decathlonService.findOneById(code);\n    const diffStocks = this.diffStocks(oldStocks?.informations, stocks);\n    this.logger.debug(`The are ${diffStocks.length} stocks that change`);\n\n    let message;\n    if (diffStocks.length) {\n      message = diffStocks\n        .map((value) => `  ${value.type} - ${value.stocks}`)\n        .join('\\n');\n    }\n\n    await this.decathlonService.update(code, stocks);\n    return message && `${name}:\\n${message}`;\n  }\n\n  diffStocks(oldInfos: StockInformations, newInfos: StockInformations) {\n    oldInfos || (oldInfos = []);\n    newInfos || (newInfos = []);\n\n    const oldMap = oldInfos.reduce((acc, i) => {\n      acc[i.type] = i;\n      return acc;\n    }, {} as Record\u003Cstring, StockInformation>);\n\n    return newInfos.filter((info) => {\n      const oldStocks = oldMap[info.type]?.stocks || 0;\n      return oldStocks !== (info?.stocks || 0);\n    });\n  }\n}\n",[151,3775,3776,3787,3814,3818,3824,3839,3853,3867,3872,3876,3886,3898,3912,3923,3938,3968,3973,3978,3983,4006,4025,4029,4044,4079,4083,4087,4091,4116,4144,4173,4205,4238,4242,4251,4265,4275,4321,4337,4341,4345,4370,4401,4405,4409,4435,4452,4467,4471,4504,4527,4536,4558,4562,4584,4612,4635,4639,4643],{"__ignoreMap":35},[154,3777,3778,3780,3782,3785],{"class":156,"line":157},[154,3779,1932],{"class":160},[154,3781,1935],{"class":160},[154,3783,3784],{"class":164}," AvailibilityCheckerService",[154,3786,1941],{"class":178},[154,3788,3789,3792,3795,3797,3799,3802,3804,3807,3809,3812],{"class":156,"line":202},[154,3790,3791],{"class":160},"  private",[154,3793,3794],{"class":195}," logger",[154,3796,169],{"class":168},[154,3798,3594],{"class":160},[154,3800,3801],{"class":182}," Logger",[154,3803,186],{"class":178},[154,3805,3806],{"class":164},"AvailibilityCheckerService",[154,3808,179],{"class":178},[154,3810,3811],{"class":195},"name",[154,3813,199],{"class":178},[154,3815,3816],{"class":156,"line":209},[154,3817,206],{"emptyLinePlaceholder":205},[154,3819,3820,3822],{"class":156,"line":307},[154,3821,1946],{"class":160},[154,3823,2028],{"class":178},[154,3825,3826,3829,3832,3834,3837],{"class":156,"line":318},[154,3827,3828],{"class":160},"    private",[154,3830,3831],{"class":1954}," service",[154,3833,759],{"class":178},[154,3835,3836],{"class":164},"AppService",[154,3838,932],{"class":178},[154,3840,3841,3843,3846,3848,3851],{"class":156,"line":329},[154,3842,3828],{"class":160},[154,3844,3845],{"class":1954}," decathlonService",[154,3847,759],{"class":178},[154,3849,3850],{"class":164},"DecathlonsService",[154,3852,932],{"class":178},[154,3854,3855,3857,3860,3862,3865],{"class":156,"line":340},[154,3856,3828],{"class":160},[154,3858,3859],{"class":1954}," smsService",[154,3861,759],{"class":178},[154,3863,3864],{"class":164},"SMSService",[154,3866,932],{"class":178},[154,3868,3869],{"class":156,"line":351},[154,3870,3871],{"class":178},"  ) {}\n",[154,3873,3874],{"class":156,"line":527},[154,3875,206],{"emptyLinePlaceholder":205},[154,3877,3878,3880,3883],{"class":156,"line":804},[154,3879,1972],{"class":160},[154,3881,3882],{"class":182}," checkAvailibility",[154,3884,3885],{"class":178},"() {\n",[154,3887,3888,3890,3893,3895],{"class":156,"line":809},[154,3889,2003],{"class":160},[154,3891,3892],{"class":182}," message",[154,3894,169],{"class":168},[154,3896,3897],{"class":178}," (\n",[154,3899,3900,3902,3905,3907,3910],{"class":156,"line":817},[154,3901,3644],{"class":160},[154,3903,3904],{"class":164}," Promise",[154,3906,179],{"class":178},[154,3908,3909],{"class":182},"all",[154,3911,2028],{"class":178},[154,3913,3914,3917,3919,3921],{"class":156,"line":827},[154,3915,3916],{"class":164},"        PRODUCTS",[154,3918,179],{"class":178},[154,3920,2239],{"class":182},[154,3922,2028],{"class":178},[154,3924,3925,3928,3930,3933,3935],{"class":156,"line":833},[154,3926,3927],{"class":160},"          async",[154,3929,500],{"class":178},[154,3931,3932],{"class":1954},"product",[154,3934,266],{"class":178},[154,3936,3937],{"class":160},"=>\n",[154,3939,3940,3943,3945,3947,3950,3952,3954,3956,3958,3960,3962,3964,3966],{"class":156,"line":1033},[154,3941,3942],{"class":160},"            await",[154,3944,3026],{"class":164},[154,3946,179],{"class":178},[154,3948,3949],{"class":182},"checkAvailabilityOfSku",[154,3951,186],{"class":178},[154,3953,3932],{"class":164},[154,3955,179],{"class":178},[154,3957,151],{"class":195},[154,3959,192],{"class":178},[154,3961,3932],{"class":164},[154,3963,179],{"class":178},[154,3965,3811],{"class":195},[154,3967,2330],{"class":178},[154,3969,3970],{"class":156,"line":1044},[154,3971,3972],{"class":178},"        ),\n",[154,3974,3975],{"class":156,"line":1055},[154,3976,3977],{"class":178},"      )\n",[154,3979,3980],{"class":156,"line":1062},[154,3981,3982],{"class":178},"    )\n",[154,3984,3985,3988,3991,3993,3995,3997,3999,4002,4004],{"class":156,"line":1067},[154,3986,3987],{"class":178},"      .",[154,3989,3990],{"class":182},"filter",[154,3992,2242],{"class":178},[154,3994,3015],{"class":1954},[154,3996,266],{"class":178},[154,3998,2250],{"class":160},[154,4000,4001],{"class":168}," !!",[154,4003,3015],{"class":195},[154,4005,524],{"class":178},[154,4007,4008,4010,4013,4015,4018,4021,4023],{"class":156,"line":1072},[154,4009,3987],{"class":178},[154,4011,4012],{"class":182},"join",[154,4014,186],{"class":178},[154,4016,4017],{"class":242},"'",[154,4019,4020],{"class":168},"\\n\\n",[154,4022,4017],{"class":242},[154,4024,199],{"class":178},[154,4026,4027],{"class":156,"line":1084},[154,4028,206],{"emptyLinePlaceholder":205},[154,4030,4031,4034,4036,4038,4040,4042],{"class":156,"line":1096},[154,4032,4033],{"class":160},"    if",[154,4035,500],{"class":178},[154,4037,3015],{"class":164},[154,4039,179],{"class":178},[154,4041,3201],{"class":195},[154,4043,3018],{"class":178},[154,4045,4046,4048,4050,4052,4055,4057,4060,4062,4064,4066,4068,4070,4073,4075,4077],{"class":156,"line":1108},[154,4047,3644],{"class":160},[154,4049,3026],{"class":164},[154,4051,179],{"class":178},[154,4053,4054],{"class":164},"smsService",[154,4056,179],{"class":178},[154,4058,4059],{"class":182},"sendMessage",[154,4061,186],{"class":178},[154,4063,3402],{"class":164},[154,4065,179],{"class":178},[154,4067,3407],{"class":164},[154,4069,179],{"class":178},[154,4071,4072],{"class":195},"PHONE_NUMBER",[154,4074,192],{"class":178},[154,4076,3015],{"class":195},[154,4078,199],{"class":178},[154,4080,4081],{"class":156,"line":1119},[154,4082,1204],{"class":178},[154,4084,4085],{"class":156,"line":1130},[154,4086,830],{"class":178},[154,4088,4089],{"class":156,"line":1137},[154,4090,206],{"emptyLinePlaceholder":205},[154,4092,4093,4095,4098,4100,4102,4104,4106,4108,4110,4112,4114],{"class":156,"line":1142},[154,4094,1972],{"class":160},[154,4096,4097],{"class":182}," checkAvailabilityOfSku",[154,4099,186],{"class":178},[154,4101,151],{"class":1954},[154,4103,759],{"class":178},[154,4105,1984],{"class":164},[154,4107,192],{"class":178},[154,4109,3811],{"class":1954},[154,4111,759],{"class":178},[154,4113,1984],{"class":164},[154,4115,3018],{"class":178},[154,4117,4118,4120,4123,4125,4127,4129,4131,4133,4135,4138,4140,4142],{"class":156,"line":1147},[154,4119,2003],{"class":160},[154,4121,4122],{"class":164}," stocks",[154,4124,169],{"class":168},[154,4126,172],{"class":160},[154,4128,3026],{"class":164},[154,4130,179],{"class":178},[154,4132,2455],{"class":164},[154,4134,179],{"class":178},[154,4136,4137],{"class":182},"getVtcElectectricL",[154,4139,186],{"class":178},[154,4141,151],{"class":195},[154,4143,199],{"class":178},[154,4145,4146,4148,4151,4153,4155,4157,4159,4162,4164,4167,4169,4171],{"class":156,"line":1159},[154,4147,2003],{"class":160},[154,4149,4150],{"class":164}," oldStocks",[154,4152,169],{"class":168},[154,4154,172],{"class":160},[154,4156,3026],{"class":164},[154,4158,179],{"class":178},[154,4160,4161],{"class":164},"decathlonService",[154,4163,179],{"class":178},[154,4165,4166],{"class":182},"findOneById",[154,4168,186],{"class":178},[154,4170,151],{"class":195},[154,4172,199],{"class":178},[154,4174,4175,4177,4180,4182,4184,4186,4189,4191,4194,4197,4199,4201,4203],{"class":156,"line":1171},[154,4176,2003],{"class":160},[154,4178,4179],{"class":164}," diffStocks",[154,4181,169],{"class":168},[154,4183,3026],{"class":164},[154,4185,179],{"class":178},[154,4187,4188],{"class":182},"diffStocks",[154,4190,186],{"class":178},[154,4192,4193],{"class":164},"oldStocks",[154,4195,4196],{"class":178},"?.",[154,4198,3622],{"class":195},[154,4200,192],{"class":178},[154,4202,2318],{"class":195},[154,4204,199],{"class":178},[154,4206,4207,4209,4211,4213,4215,4218,4220,4223,4225,4227,4229,4231,4233,4236],{"class":156,"line":1183},[154,4208,3166],{"class":164},[154,4210,179],{"class":178},[154,4212,3171],{"class":164},[154,4214,179],{"class":178},[154,4216,4217],{"class":182},"debug",[154,4219,186],{"class":178},[154,4221,4222],{"class":242},"`The are ",[154,4224,3185],{"class":160},[154,4226,4188],{"class":164},[154,4228,179],{"class":178},[154,4230,3201],{"class":195},[154,4232,3190],{"class":160},[154,4234,4235],{"class":242}," stocks that change`",[154,4237,199],{"class":178},[154,4239,4240],{"class":156,"line":1194},[154,4241,206],{"emptyLinePlaceholder":205},[154,4243,4244,4247,4249],{"class":156,"line":1201},[154,4245,4246],{"class":160},"    let",[154,4248,3892],{"class":195},[154,4250,2097],{"class":178},[154,4252,4253,4255,4257,4259,4261,4263],{"class":156,"line":1207},[154,4254,4033],{"class":160},[154,4256,500],{"class":178},[154,4258,4188],{"class":164},[154,4260,179],{"class":178},[154,4262,3201],{"class":195},[154,4264,3018],{"class":178},[154,4266,4267,4270,4272],{"class":156,"line":1213},[154,4268,4269],{"class":195},"      message",[154,4271,169],{"class":168},[154,4273,4274],{"class":195}," diffStocks\n",[154,4276,4277,4279,4281,4283,4286,4288,4290,4293,4295,4297,4299,4302,4304,4307,4309,4311,4313,4315,4317,4319],{"class":156,"line":1592},[154,4278,2236],{"class":178},[154,4280,2239],{"class":182},[154,4282,2242],{"class":178},[154,4284,4285],{"class":1954},"value",[154,4287,266],{"class":178},[154,4289,2250],{"class":160},[154,4291,4292],{"class":242}," `  ",[154,4294,3185],{"class":160},[154,4296,4285],{"class":164},[154,4298,179],{"class":178},[154,4300,4301],{"class":195},"type",[154,4303,3190],{"class":160},[154,4305,4306],{"class":242}," - ",[154,4308,3185],{"class":160},[154,4310,4285],{"class":164},[154,4312,179],{"class":178},[154,4314,2318],{"class":195},[154,4316,3190],{"class":160},[154,4318,3218],{"class":242},[154,4320,524],{"class":178},[154,4322,4323,4325,4327,4329,4331,4333,4335],{"class":156,"line":1603},[154,4324,2236],{"class":178},[154,4326,4012],{"class":182},[154,4328,186],{"class":178},[154,4330,4017],{"class":242},[154,4332,3209],{"class":168},[154,4334,4017],{"class":242},[154,4336,199],{"class":178},[154,4338,4339],{"class":156,"line":1614},[154,4340,1204],{"class":178},[154,4342,4343],{"class":156,"line":1625},[154,4344,206],{"emptyLinePlaceholder":205},[154,4346,4347,4349,4351,4353,4355,4357,4360,4362,4364,4366,4368],{"class":156,"line":1637},[154,4348,3023],{"class":160},[154,4350,3026],{"class":164},[154,4352,179],{"class":178},[154,4354,4161],{"class":164},[154,4356,179],{"class":178},[154,4358,4359],{"class":182},"update",[154,4361,186],{"class":178},[154,4363,151],{"class":195},[154,4365,192],{"class":178},[154,4367,2318],{"class":195},[154,4369,199],{"class":178},[154,4371,4372,4374,4376,4379,4381,4383,4385,4387,4389,4391,4393,4395,4397,4399],{"class":156,"line":1649},[154,4373,2343],{"class":160},[154,4375,3892],{"class":195},[154,4377,4378],{"class":168}," &&",[154,4380,488],{"class":242},[154,4382,3185],{"class":160},[154,4384,3811],{"class":195},[154,4386,3190],{"class":160},[154,4388,143],{"class":242},[154,4390,3209],{"class":168},[154,4392,3185],{"class":160},[154,4394,3015],{"class":195},[154,4396,3190],{"class":160},[154,4398,3218],{"class":242},[154,4400,2097],{"class":178},[154,4402,4403],{"class":156,"line":1660},[154,4404,830],{"class":178},[154,4406,4407],{"class":156,"line":1669},[154,4408,206],{"emptyLinePlaceholder":205},[154,4410,4411,4414,4416,4419,4421,4424,4426,4429,4431,4433],{"class":156,"line":1674},[154,4412,4413],{"class":182},"  diffStocks",[154,4415,186],{"class":178},[154,4417,4418],{"class":1954},"oldInfos",[154,4420,759],{"class":178},[154,4422,4423],{"class":164},"StockInformations",[154,4425,192],{"class":178},[154,4427,4428],{"class":1954},"newInfos",[154,4430,759],{"class":178},[154,4432,4423],{"class":164},[154,4434,3018],{"class":178},[154,4436,4437,4440,4443,4445,4447,4449],{"class":156,"line":1679},[154,4438,4439],{"class":195},"    oldInfos",[154,4441,4442],{"class":168}," ||",[154,4444,500],{"class":178},[154,4446,4418],{"class":195},[154,4448,169],{"class":168},[154,4450,4451],{"class":178}," []);\n",[154,4453,4454,4457,4459,4461,4463,4465],{"class":156,"line":1690},[154,4455,4456],{"class":195},"    newInfos",[154,4458,4442],{"class":168},[154,4460,500],{"class":178},[154,4462,4428],{"class":195},[154,4464,169],{"class":168},[154,4466,4451],{"class":178},[154,4468,4469],{"class":156,"line":1701},[154,4470,206],{"emptyLinePlaceholder":205},[154,4472,4473,4475,4478,4480,4483,4485,4488,4490,4493,4495,4498,4500,4502],{"class":156,"line":1712},[154,4474,2003],{"class":160},[154,4476,4477],{"class":164}," oldMap",[154,4479,169],{"class":168},[154,4481,4482],{"class":164}," oldInfos",[154,4484,179],{"class":178},[154,4486,4487],{"class":182},"reduce",[154,4489,2242],{"class":178},[154,4491,4492],{"class":1954},"acc",[154,4494,192],{"class":178},[154,4496,4497],{"class":1954},"i",[154,4499,266],{"class":178},[154,4501,2250],{"class":160},[154,4503,1941],{"class":178},[154,4505,4506,4509,4511,4513,4515,4517,4520,4522,4525],{"class":156,"line":1723},[154,4507,4508],{"class":195},"      acc",[154,4510,2086],{"class":178},[154,4512,4497],{"class":164},[154,4514,179],{"class":178},[154,4516,4301],{"class":195},[154,4518,4519],{"class":178},"] ",[154,4521,494],{"class":168},[154,4523,4524],{"class":195}," i",[154,4526,2097],{"class":178},[154,4528,4529,4531,4534],{"class":156,"line":1734},[154,4530,3448],{"class":160},[154,4532,4533],{"class":195}," acc",[154,4535,2097],{"class":178},[154,4537,4538,4541,4544,4547,4549,4551,4553,4555],{"class":156,"line":1745},[154,4539,4540],{"class":178},"    }, {} ",[154,4542,4543],{"class":160},"as",[154,4545,4546],{"class":164}," Record",[154,4548,858],{"class":178},[154,4550,1984],{"class":164},[154,4552,192],{"class":178},[154,4554,1995],{"class":164},[154,4556,4557],{"class":178},">);\n",[154,4559,4560],{"class":156,"line":1756},[154,4561,206],{"emptyLinePlaceholder":205},[154,4563,4564,4566,4569,4571,4573,4575,4578,4580,4582],{"class":156,"line":1767},[154,4565,2343],{"class":160},[154,4567,4568],{"class":164}," newInfos",[154,4570,179],{"class":178},[154,4572,3990],{"class":182},[154,4574,2242],{"class":178},[154,4576,4577],{"class":1954},"info",[154,4579,266],{"class":178},[154,4581,2250],{"class":160},[154,4583,1941],{"class":178},[154,4585,4586,4588,4590,4592,4594,4596,4598,4600,4602,4604,4606,4608,4610],{"class":156,"line":1778},[154,4587,3374],{"class":160},[154,4589,4150],{"class":164},[154,4591,169],{"class":168},[154,4593,4477],{"class":195},[154,4595,2086],{"class":178},[154,4597,4577],{"class":164},[154,4599,179],{"class":178},[154,4601,4301],{"class":195},[154,4603,2091],{"class":178},[154,4605,2318],{"class":195},[154,4607,4442],{"class":168},[154,4609,2386],{"class":520},[154,4611,2097],{"class":178},[154,4613,4614,4616,4618,4621,4623,4625,4627,4629,4631,4633],{"class":156,"line":1789},[154,4615,3448],{"class":160},[154,4617,4150],{"class":195},[154,4619,4620],{"class":168}," !==",[154,4622,500],{"class":178},[154,4624,4577],{"class":164},[154,4626,4196],{"class":178},[154,4628,2318],{"class":195},[154,4630,4442],{"class":168},[154,4632,2386],{"class":520},[154,4634,199],{"class":178},[154,4636,4637],{"class":156,"line":1800},[154,4638,2143],{"class":178},[154,4640,4641],{"class":156,"line":1811},[154,4642,830],{"class":178},[154,4644,4645],{"class":156,"line":1822},[154,4646,836],{"class":178},[12,4648,4649],{},"Cela me permet de recevoir un SMS de la forme :",[12,4651,4652],{},[119,4653],{"alt":4654,"className":4655,"src":4656},"Les SMS",[123],"\u002FProgrammation\u002Fachat_velo\u002FSMS.png",[56,4658,4660],{"id":4659},"déploiement-de-la-notification","Déploiement de la notification",[12,4662,4663],{},"Pour déployer la notification, il me faut deux endpoints (un pour la partie web, et l'autre pour la notification).",[12,4665,4666,4667,4670,4671,4674],{},"Je garde donc dans le dossier ",[151,4668,4669],{},"src"," le fichier ",[151,4672,4673],{},"main.ts"," pour la partie web et je créé un point d'entrée spécial pour la lambda de notification:",[145,4676,4678],{"className":147,"code":4677,"language":149,"meta":35,"style":35},"\nimport { HttpStatus } from '@nestjs\u002Fcommon';\nimport { NestFactory } from '@nestjs\u002Fcore';\nimport { Handler } from 'aws-lambda';\n\nimport { CheckAvailabilityModule } from '.\u002Fcheck-availability.module';\nimport { AvailibilityCheckerService } from '.\u002Favailability\u002Favailibility-checker.service';\n\nlet service: AvailibilityCheckerService;\n\nasync function bootstrap(): Promise\u003CAvailibilityCheckerService> {\n  const appContext = await NestFactory.createApplicationContext(\n    CheckAvailabilityModule,\n  );\n  return appContext.get(AvailibilityCheckerService);\n}\n\nexport const handler: Handler = async () => {\n  service = service ?? (await bootstrap());\n\n  await service.checkAvailibility();\n\n  return {\n    statusCode: HttpStatus.OK,\n  };\n};\n",[151,4679,4680,4684,4706,4724,4742,4746,4764,4781,4785,4798,4802,4823,4845,4852,4857,4874,4878,4882,4907,4929,4933,4947,4951,4957,4973,4978],{"__ignoreMap":35},[154,4681,4682],{"class":156,"line":157},[154,4683,206],{"emptyLinePlaceholder":205},[154,4685,4686,4689,4692,4695,4698,4701,4704],{"class":156,"line":202},[154,4687,4688],{"class":160},"import",[154,4690,4691],{"class":178}," { ",[154,4693,4694],{"class":195},"HttpStatus",[154,4696,4697],{"class":178}," } ",[154,4699,4700],{"class":160},"from",[154,4702,4703],{"class":242}," '@nestjs\u002Fcommon'",[154,4705,2097],{"class":178},[154,4707,4708,4710,4712,4715,4717,4719,4722],{"class":156,"line":209},[154,4709,4688],{"class":160},[154,4711,4691],{"class":178},[154,4713,4714],{"class":195},"NestFactory",[154,4716,4697],{"class":178},[154,4718,4700],{"class":160},[154,4720,4721],{"class":242}," '@nestjs\u002Fcore'",[154,4723,2097],{"class":178},[154,4725,4726,4728,4730,4733,4735,4737,4740],{"class":156,"line":307},[154,4727,4688],{"class":160},[154,4729,4691],{"class":178},[154,4731,4732],{"class":195},"Handler",[154,4734,4697],{"class":178},[154,4736,4700],{"class":160},[154,4738,4739],{"class":242}," 'aws-lambda'",[154,4741,2097],{"class":178},[154,4743,4744],{"class":156,"line":318},[154,4745,206],{"emptyLinePlaceholder":205},[154,4747,4748,4750,4752,4755,4757,4759,4762],{"class":156,"line":329},[154,4749,4688],{"class":160},[154,4751,4691],{"class":178},[154,4753,4754],{"class":195},"CheckAvailabilityModule",[154,4756,4697],{"class":178},[154,4758,4700],{"class":160},[154,4760,4761],{"class":242}," '.\u002Fcheck-availability.module'",[154,4763,2097],{"class":178},[154,4765,4766,4768,4770,4772,4774,4776,4779],{"class":156,"line":340},[154,4767,4688],{"class":160},[154,4769,4691],{"class":178},[154,4771,3806],{"class":195},[154,4773,4697],{"class":178},[154,4775,4700],{"class":160},[154,4777,4778],{"class":242}," '.\u002Favailability\u002Favailibility-checker.service'",[154,4780,2097],{"class":178},[154,4782,4783],{"class":156,"line":351},[154,4784,206],{"emptyLinePlaceholder":205},[154,4786,4787,4790,4792,4794,4796],{"class":156,"line":527},[154,4788,4789],{"class":160},"let",[154,4791,3831],{"class":195},[154,4793,759],{"class":178},[154,4795,3806],{"class":164},[154,4797,2097],{"class":178},[154,4799,4800],{"class":156,"line":804},[154,4801,206],{"emptyLinePlaceholder":205},[154,4803,4804,4807,4809,4812,4815,4817,4819,4821],{"class":156,"line":809},[154,4805,4806],{"class":160},"async",[154,4808,401],{"class":160},[154,4810,4811],{"class":182}," bootstrap",[154,4813,4814],{"class":178},"(): ",[154,4816,1990],{"class":164},[154,4818,858],{"class":178},[154,4820,3806],{"class":164},[154,4822,3362],{"class":178},[154,4824,4825,4828,4831,4833,4835,4838,4840,4843],{"class":156,"line":817},[154,4826,4827],{"class":160},"  const",[154,4829,4830],{"class":164}," appContext",[154,4832,169],{"class":168},[154,4834,172],{"class":160},[154,4836,4837],{"class":164}," NestFactory",[154,4839,179],{"class":178},[154,4841,4842],{"class":182},"createApplicationContext",[154,4844,2028],{"class":178},[154,4846,4847,4850],{"class":156,"line":827},[154,4848,4849],{"class":195},"    CheckAvailabilityModule",[154,4851,932],{"class":178},[154,4853,4854],{"class":156,"line":833},[154,4855,4856],{"class":178},"  );\n",[154,4858,4859,4862,4864,4866,4868,4870,4872],{"class":156,"line":1033},[154,4860,4861],{"class":160},"  return",[154,4863,4830],{"class":164},[154,4865,179],{"class":178},[154,4867,2043],{"class":182},[154,4869,186],{"class":178},[154,4871,3806],{"class":195},[154,4873,199],{"class":178},[154,4875,4876],{"class":156,"line":1044},[154,4877,836],{"class":178},[154,4879,4880],{"class":156,"line":1055},[154,4881,206],{"emptyLinePlaceholder":205},[154,4883,4884,4886,4889,4892,4894,4896,4898,4900,4903,4905],{"class":156,"line":1062},[154,4885,1932],{"class":160},[154,4887,4888],{"class":160}," const",[154,4890,4891],{"class":182}," handler",[154,4893,759],{"class":178},[154,4895,4732],{"class":164},[154,4897,169],{"class":168},[154,4899,398],{"class":160},[154,4901,4902],{"class":178}," () ",[154,4904,2250],{"class":160},[154,4906,1941],{"class":178},[154,4908,4909,4912,4914,4916,4919,4921,4924,4926],{"class":156,"line":1067},[154,4910,4911],{"class":195},"  service",[154,4913,169],{"class":168},[154,4915,3831],{"class":195},[154,4917,4918],{"class":168}," ??",[154,4920,500],{"class":178},[154,4922,4923],{"class":160},"await",[154,4925,4811],{"class":182},[154,4927,4928],{"class":178},"());\n",[154,4930,4931],{"class":156,"line":1072},[154,4932,206],{"emptyLinePlaceholder":205},[154,4934,4935,4938,4940,4942,4945],{"class":156,"line":1084},[154,4936,4937],{"class":160},"  await",[154,4939,3831],{"class":164},[154,4941,179],{"class":178},[154,4943,4944],{"class":182},"checkAvailibility",[154,4946,3068],{"class":178},[154,4948,4949],{"class":156,"line":1096},[154,4950,206],{"emptyLinePlaceholder":205},[154,4952,4953,4955],{"class":156,"line":1108},[154,4954,4861],{"class":160},[154,4956,1941],{"class":178},[154,4958,4959,4962,4964,4966,4968,4971],{"class":156,"line":1119},[154,4960,4961],{"class":195},"    statusCode",[154,4963,759],{"class":178},[154,4965,4694],{"class":164},[154,4967,179],{"class":178},[154,4969,4970],{"class":195},"OK",[154,4972,932],{"class":178},[154,4974,4975],{"class":156,"line":1130},[154,4976,4977],{"class":178},"  };\n",[154,4979,4980],{"class":156,"line":1137},[154,4981,4982],{"class":178},"};\n",[12,4984,4985],{},"Contrairement à la partie WEB ce service ne démarre pas de serveur Web (ni la partie express).",[12,4987,4988],{},"Le paramétrage de la lambda se fait donc avec le fichier serverless.yml dont voici les principales modifications:",[145,4990,4992],{"className":2446,"code":4991,"language":2448,"meta":35,"style":35},"service: decathlon\nframeworkVersion: \"2\"\n\nplugins:\n  - serverless-dynamodb-local\n  - serverless-plugin-log-retention\n  - serverless-offline\n  - serverless-domain-manager\n\ncustom:\n  region: eu-central-1\n  logRetentionInDays: 7\n  serverless-offline:\n    noPrependStageInUrl: true\n    allowCache: false\n  decathlonTable:\n    name: ${self:provider.stage}-decathlon\n    arn: !GetAtt decathlonTable.Arn\n  dynamodb:\n    stages:\n      - ${self:provider.stage}\n    start:\n      migrate: true\n  endpoints:\n    dynamodbURL: \"http:\u002F\u002Flocalhost:8000\"\n  customDomain: ...\n\nprovider:\n  name: aws\n  region: ${self:custom.region}\n  runtime: nodejs12.x\n  lambdaHashingVersion: \"20201221\"\n  stage: ${opt:stage, 'dev'}\n  environment:\n    DYNAMODB_ENDPOINT: ${self:custom.endpoints.dynamodbURL}\n    DECATHLON_TABLE_NAME: ${self:custom.decathlonTable.name}\n    NODE_OPTIONS: \"--max-http-header-size=80000\"\n  iamRoleStatements: ${file(delivery\u002Froles.yml)}\n\npackage:\n  individually: true\n  patterns:\n    - \"!.\u002F**\"\n\nfunctions:\n  api:\n    handler: dist\u002Fmain.handler\n    environment:\n      region: ${self:custom.region}\n    events:\n      - http:\n          path: \u002F\n          method: ANY\n      - http:\n          path: \u002F{proxy+}\n          method: ANY\n    package:\n      patterns:\n        - dist\u002Fmain.js\n        - views\u002F**\n\n  check-availability:\n    handler: dist\u002Fcheck-availability.handler\n    events:\n      - schedule: rate(30 minutes)\n    package:\n      patterns:\n        - dist\u002Fcheck-availability.js\n\nresources:\n  Resources:\n    decathlonTable: ${file(delivery\u002FdecathlonTable.yml):decathlonTable}\n",[151,4993,4994,5003,5011,5015,5021,5028,5034,5040,5046,5050,5056,5064,5072,5078,5086,5094,5101,5111,5124,5131,5138,5145,5152,5161,5168,5178,5187,5191,5197,5205,5213,5221,5229,5237,5243,5253,5263,5271,5281,5285,5291,5300,5306,5312,5316,5322,5328,5336,5342,5350,5356,5364,5372,5380,5388,5396,5404,5411,5418,5426,5432,5436,5443,5452,5458,5470,5476,5482,5490,5495,5503,5511],{"__ignoreMap":35},[154,4995,4996,4998,5000],{"class":156,"line":157},[154,4997,2455],{"class":195},[154,4999,759],{"class":178},[154,5001,5002],{"class":242},"decathlon\n",[154,5004,5005,5007,5009],{"class":156,"line":202},[154,5006,2465],{"class":195},[154,5008,759],{"class":178},[154,5010,2470],{"class":242},[154,5012,5013],{"class":156,"line":209},[154,5014,206],{"emptyLinePlaceholder":205},[154,5016,5017,5019],{"class":156,"line":307},[154,5018,2479],{"class":195},[154,5020,2482],{"class":178},[154,5022,5023,5025],{"class":156,"line":318},[154,5024,2487],{"class":178},[154,5026,5027],{"class":242},"serverless-dynamodb-local\n",[154,5029,5030,5032],{"class":156,"line":329},[154,5031,2487],{"class":178},[154,5033,2490],{"class":242},[154,5035,5036,5038],{"class":156,"line":340},[154,5037,2487],{"class":178},[154,5039,2497],{"class":242},[154,5041,5042,5044],{"class":156,"line":351},[154,5043,2487],{"class":178},[154,5045,2504],{"class":242},[154,5047,5048],{"class":156,"line":527},[154,5049,206],{"emptyLinePlaceholder":205},[154,5051,5052,5054],{"class":156,"line":804},[154,5053,2513],{"class":195},[154,5055,2482],{"class":178},[154,5057,5058,5060,5062],{"class":156,"line":809},[154,5059,2520],{"class":195},[154,5061,759],{"class":178},[154,5063,2525],{"class":242},[154,5065,5066,5068,5070],{"class":156,"line":817},[154,5067,2530],{"class":195},[154,5069,759],{"class":178},[154,5071,2535],{"class":520},[154,5073,5074,5076],{"class":156,"line":827},[154,5075,2540],{"class":195},[154,5077,2482],{"class":178},[154,5079,5080,5082,5084],{"class":156,"line":833},[154,5081,2547],{"class":195},[154,5083,759],{"class":178},[154,5085,2552],{"class":520},[154,5087,5088,5090,5092],{"class":156,"line":1033},[154,5089,2557],{"class":195},[154,5091,759],{"class":178},[154,5093,2562],{"class":520},[154,5095,5096,5099],{"class":156,"line":1044},[154,5097,5098],{"class":195},"  decathlonTable",[154,5100,2482],{"class":178},[154,5102,5103,5106,5108],{"class":156,"line":1055},[154,5104,5105],{"class":195},"    name",[154,5107,759],{"class":178},[154,5109,5110],{"class":242},"${self:provider.stage}-decathlon\n",[154,5112,5113,5116,5118,5121],{"class":156,"line":1062},[154,5114,5115],{"class":195},"    arn",[154,5117,759],{"class":178},[154,5119,5120],{"class":160},"!GetAtt",[154,5122,5123],{"class":242}," decathlonTable.Arn\n",[154,5125,5126,5129],{"class":156,"line":1067},[154,5127,5128],{"class":195},"  dynamodb",[154,5130,2482],{"class":178},[154,5132,5133,5136],{"class":156,"line":1072},[154,5134,5135],{"class":195},"    stages",[154,5137,2482],{"class":178},[154,5139,5140,5142],{"class":156,"line":1084},[154,5141,2820],{"class":178},[154,5143,5144],{"class":242},"${self:provider.stage}\n",[154,5146,5147,5150],{"class":156,"line":1096},[154,5148,5149],{"class":195},"    start",[154,5151,2482],{"class":178},[154,5153,5154,5157,5159],{"class":156,"line":1108},[154,5155,5156],{"class":195},"      migrate",[154,5158,759],{"class":178},[154,5160,2552],{"class":520},[154,5162,5163,5166],{"class":156,"line":1119},[154,5164,5165],{"class":195},"  endpoints",[154,5167,2482],{"class":178},[154,5169,5170,5173,5175],{"class":156,"line":1130},[154,5171,5172],{"class":195},"    dynamodbURL",[154,5174,759],{"class":178},[154,5176,5177],{"class":242},"\"http:\u002F\u002Flocalhost:8000\"\n",[154,5179,5180,5182,5184],{"class":156,"line":1137},[154,5181,2567],{"class":195},[154,5183,759],{"class":178},[154,5185,5186],{"class":520},"...\n",[154,5188,5189],{"class":156,"line":1142},[154,5190,206],{"emptyLinePlaceholder":205},[154,5192,5193,5195],{"class":156,"line":1147},[154,5194,2656],{"class":195},[154,5196,2482],{"class":178},[154,5198,5199,5201,5203],{"class":156,"line":1159},[154,5200,2663],{"class":195},[154,5202,759],{"class":178},[154,5204,2668],{"class":242},[154,5206,5207,5209,5211],{"class":156,"line":1171},[154,5208,2520],{"class":195},[154,5210,759],{"class":178},[154,5212,2677],{"class":242},[154,5214,5215,5217,5219],{"class":156,"line":1183},[154,5216,2682],{"class":195},[154,5218,759],{"class":178},[154,5220,2687],{"class":242},[154,5222,5223,5225,5227],{"class":156,"line":1194},[154,5224,2692],{"class":195},[154,5226,759],{"class":178},[154,5228,2697],{"class":242},[154,5230,5231,5233,5235],{"class":156,"line":1201},[154,5232,2702],{"class":195},[154,5234,759],{"class":178},[154,5236,2707],{"class":242},[154,5238,5239,5241],{"class":156,"line":1207},[154,5240,2712],{"class":195},[154,5242,2482],{"class":178},[154,5244,5245,5248,5250],{"class":156,"line":1213},[154,5246,5247],{"class":195},"    DYNAMODB_ENDPOINT",[154,5249,759],{"class":178},[154,5251,5252],{"class":242},"${self:custom.endpoints.dynamodbURL}\n",[154,5254,5255,5258,5260],{"class":156,"line":1592},[154,5256,5257],{"class":195},"    DECATHLON_TABLE_NAME",[154,5259,759],{"class":178},[154,5261,5262],{"class":242},"${self:custom.decathlonTable.name}\n",[154,5264,5265,5267,5269],{"class":156,"line":1603},[154,5266,2719],{"class":195},[154,5268,759],{"class":178},[154,5270,2724],{"class":242},[154,5272,5273,5276,5278],{"class":156,"line":1614},[154,5274,5275],{"class":195},"  iamRoleStatements",[154,5277,759],{"class":178},[154,5279,5280],{"class":242},"${file(delivery\u002Froles.yml)}\n",[154,5282,5283],{"class":156,"line":1625},[154,5284,206],{"emptyLinePlaceholder":205},[154,5286,5287,5289],{"class":156,"line":1637},[154,5288,2733],{"class":195},[154,5290,2482],{"class":178},[154,5292,5293,5296,5298],{"class":156,"line":1649},[154,5294,5295],{"class":195},"  individually",[154,5297,759],{"class":178},[154,5299,2552],{"class":520},[154,5301,5302,5304],{"class":156,"line":1660},[154,5303,2740],{"class":195},[154,5305,2482],{"class":178},[154,5307,5308,5310],{"class":156,"line":1669},[154,5309,2747],{"class":178},[154,5311,2750],{"class":242},[154,5313,5314],{"class":156,"line":1674},[154,5315,206],{"emptyLinePlaceholder":205},[154,5317,5318,5320],{"class":156,"line":1679},[154,5319,2773],{"class":195},[154,5321,2482],{"class":178},[154,5323,5324,5326],{"class":156,"line":1690},[154,5325,2780],{"class":195},[154,5327,2482],{"class":178},[154,5329,5330,5332,5334],{"class":156,"line":1701},[154,5331,2787],{"class":195},[154,5333,759],{"class":178},[154,5335,2792],{"class":242},[154,5337,5338,5340],{"class":156,"line":1712},[154,5339,2797],{"class":195},[154,5341,2482],{"class":178},[154,5343,5344,5346,5348],{"class":156,"line":1723},[154,5345,2804],{"class":195},[154,5347,759],{"class":178},[154,5349,2677],{"class":242},[154,5351,5352,5354],{"class":156,"line":1734},[154,5353,2813],{"class":195},[154,5355,2482],{"class":178},[154,5357,5358,5360,5362],{"class":156,"line":1745},[154,5359,2820],{"class":178},[154,5361,722],{"class":195},[154,5363,2482],{"class":178},[154,5365,5366,5368,5370],{"class":156,"line":1756},[154,5367,2829],{"class":195},[154,5369,759],{"class":178},[154,5371,2834],{"class":242},[154,5373,5374,5376,5378],{"class":156,"line":1767},[154,5375,2839],{"class":195},[154,5377,759],{"class":178},[154,5379,2844],{"class":242},[154,5381,5382,5384,5386],{"class":156,"line":1778},[154,5383,2820],{"class":178},[154,5385,722],{"class":195},[154,5387,2482],{"class":178},[154,5389,5390,5392,5394],{"class":156,"line":1789},[154,5391,2829],{"class":195},[154,5393,759],{"class":178},[154,5395,2861],{"class":242},[154,5397,5398,5400,5402],{"class":156,"line":1800},[154,5399,2839],{"class":195},[154,5401,759],{"class":178},[154,5403,2844],{"class":242},[154,5405,5406,5409],{"class":156,"line":1811},[154,5407,5408],{"class":195},"    package",[154,5410,2482],{"class":178},[154,5412,5413,5416],{"class":156,"line":1822},[154,5414,5415],{"class":195},"      patterns",[154,5417,2482],{"class":178},[154,5419,5420,5423],{"class":156,"line":1833},[154,5421,5422],{"class":178},"        - ",[154,5424,5425],{"class":242},"dist\u002Fmain.js\n",[154,5427,5428,5430],{"class":156,"line":1845},[154,5429,5422],{"class":178},[154,5431,2764],{"class":242},[154,5433,5434],{"class":156,"line":1857},[154,5435,206],{"emptyLinePlaceholder":205},[154,5437,5438,5441],{"class":156,"line":1868},[154,5439,5440],{"class":195},"  check-availability",[154,5442,2482],{"class":178},[154,5444,5445,5447,5449],{"class":156,"line":1877},[154,5446,2787],{"class":195},[154,5448,759],{"class":178},[154,5450,5451],{"class":242},"dist\u002Fcheck-availability.handler\n",[154,5453,5454,5456],{"class":156,"line":1882},[154,5455,2813],{"class":195},[154,5457,2482],{"class":178},[154,5459,5460,5462,5465,5467],{"class":156,"line":1889},[154,5461,2820],{"class":178},[154,5463,5464],{"class":195},"schedule",[154,5466,759],{"class":178},[154,5468,5469],{"class":242},"rate(30 minutes)\n",[154,5471,5472,5474],{"class":156,"line":1895},[154,5473,5408],{"class":195},[154,5475,2482],{"class":178},[154,5477,5478,5480],{"class":156,"line":1900},[154,5479,5415],{"class":195},[154,5481,2482],{"class":178},[154,5483,5485,5487],{"class":156,"line":5484},68,[154,5486,5422],{"class":178},[154,5488,5489],{"class":242},"dist\u002Fcheck-availability.js\n",[154,5491,5493],{"class":156,"line":5492},69,[154,5494,206],{"emptyLinePlaceholder":205},[154,5496,5498,5501],{"class":156,"line":5497},70,[154,5499,5500],{"class":195},"resources",[154,5502,2482],{"class":178},[154,5504,5506,5509],{"class":156,"line":5505},71,[154,5507,5508],{"class":195},"  Resources",[154,5510,2482],{"class":178},[154,5512,5514,5517,5519],{"class":156,"line":5513},72,[154,5515,5516],{"class":195},"    decathlonTable",[154,5518,759],{"class":178},[154,5520,5521],{"class":242},"${file(delivery\u002FdecathlonTable.yml):decathlonTable}\n",[12,5523,5524],{},"Il ne reste plus qu'à déployer et profiter de l'envoi de SMS.",[56,5526,5528],{"id":5527},"optimisation","Optimisation",[12,5530,5531],{},"Sur AWS, le coût d'une lambda est lié au nombre d'exécutions mais aussi au temps d'exécution. Il est important que le temps d'exécution soit le plus\nrapide possible.",[12,5533,5534],{},"Ici dans notre cas le temps le temps de traitement sera lié au temps de réponse de la requête HTTP extérieur à notre site. Afin de parfaire notre petite\napplication de bonne pratique, nous allons utiliser webpack (côté serveur) afin d'optimiser le temps de démarrage de notre application.",[12,5536,5537,5538,5541],{},"Grâce au framework Nest.JS, cela est très facile à faire, dans le fichier ",[151,5539,5540],{},"nest-cli.json",", nous allons demander à Nest.JS de générer un bundle webpack:",[145,5543,5545],{"className":734,"code":5544,"language":736,"meta":35,"style":35},"{\n  \"collection\": \"@nestjs\u002Fschematics\",\n  \"sourceRoot\": \"src\",\n  \"compilerOptions\": {\n    \"webpack\": true\n  }\n}\n",[151,5546,5547,5551,5563,5575,5582,5591,5595],{"__ignoreMap":35},[154,5548,5549],{"class":156,"line":157},[154,5550,743],{"class":178},[154,5552,5553,5556,5558,5561],{"class":156,"line":202},[154,5554,5555],{"class":195},"  \"collection\"",[154,5557,759],{"class":178},[154,5559,5560],{"class":242},"\"@nestjs\u002Fschematics\"",[154,5562,932],{"class":178},[154,5564,5565,5568,5570,5573],{"class":156,"line":209},[154,5566,5567],{"class":195},"  \"sourceRoot\"",[154,5569,759],{"class":178},[154,5571,5572],{"class":242},"\"src\"",[154,5574,932],{"class":178},[154,5576,5577,5580],{"class":156,"line":307},[154,5578,5579],{"class":195},"  \"compilerOptions\"",[154,5581,751],{"class":178},[154,5583,5584,5587,5589],{"class":156,"line":318},[154,5585,5586],{"class":195},"    \"webpack\"",[154,5588,759],{"class":178},[154,5590,2552],{"class":520},[154,5592,5593],{"class":156,"line":329},[154,5594,830],{"class":178},[154,5596,5597],{"class":156,"line":340},[154,5598,836],{"class":178},[12,5600,5601,5602,3254],{},"Par défaut, webpack ne crée un bundle qu'avec le source de notre application (et donc sans les modules node). Ce qui nous intéresse c'est de faire un bundle\ncomprenant notre application ainsi que les modules node (on peut voir un bench sur la ",[30,5603,5605],{"href":2441,"rel":5604},[132],"FAQ Nest.JS",[12,5607,5608,5609,5612],{},"Pour cela nous allons créer un fichier ",[151,5610,5611],{},"webpack.config.js"," qui sera pris automatiquement (inspiré de la documentation mais modifié pour posséder plusieurs points\nd'entrées, on exclut aussi le framework AWS qui est déjà inclus dans AWS):",[145,5614,5616],{"className":147,"code":5615,"language":149,"meta":35,"style":35},"module.exports = (options, webpack) => {\n  const lazyImports = [\n    \"@nestjs\u002Fmicroservices\u002Fmicroservices-module\",\n    \"@nestjs\u002Fwebsockets\u002Fsocket-module\",\n  ];\n\n  return {\n    ...options,\n    entry: {\n      main: options.entry,\n      \"check-availability\": options.entry.replace(\"main\", \"check-availability\"),\n    },\n    externals: [\"aws-sdk\"],\n    output: {\n      filename: \"[name].js\",\n      libraryTarget: \"commonjs2\",\n    },\n    plugins: [\n      ...options.plugins,\n      new webpack.IgnorePlugin({\n        checkResource(resource) {\n          if (lazyImports.includes(resource)) {\n            try {\n              require.resolve(resource);\n            } catch (err) {\n              return true;\n            }\n          }\n          return false;\n        },\n      }),\n    ],\n  };\n};\n",[151,5617,5618,5645,5657,5664,5671,5676,5680,5686,5695,5702,5718,5748,5752,5766,5773,5785,5797,5801,5808,5820,5835,5847,5869,5876,5892,5906,5916,5921,5926,5936,5940,5945,5949,5953],{"__ignoreMap":35},[154,5619,5620,5623,5625,5628,5630,5632,5634,5636,5639,5641,5643],{"class":156,"line":157},[154,5621,5622],{"class":164},"module",[154,5624,179],{"class":178},[154,5626,5627],{"class":164},"exports",[154,5629,169],{"class":168},[154,5631,500],{"class":178},[154,5633,196],{"class":1954},[154,5635,192],{"class":178},[154,5637,5638],{"class":1954},"webpack",[154,5640,266],{"class":178},[154,5642,2250],{"class":160},[154,5644,1941],{"class":178},[154,5646,5647,5649,5652,5654],{"class":156,"line":202},[154,5648,4827],{"class":160},[154,5650,5651],{"class":164}," lazyImports",[154,5653,169],{"class":168},[154,5655,5656],{"class":178}," [\n",[154,5658,5659,5662],{"class":156,"line":209},[154,5660,5661],{"class":242},"    \"@nestjs\u002Fmicroservices\u002Fmicroservices-module\"",[154,5663,932],{"class":178},[154,5665,5666,5669],{"class":156,"line":307},[154,5667,5668],{"class":242},"    \"@nestjs\u002Fwebsockets\u002Fsocket-module\"",[154,5670,932],{"class":178},[154,5672,5673],{"class":156,"line":318},[154,5674,5675],{"class":178},"  ];\n",[154,5677,5678],{"class":156,"line":329},[154,5679,206],{"emptyLinePlaceholder":205},[154,5681,5682,5684],{"class":156,"line":340},[154,5683,4861],{"class":160},[154,5685,1941],{"class":178},[154,5687,5688,5691,5693],{"class":156,"line":351},[154,5689,5690],{"class":178},"    ...",[154,5692,196],{"class":195},[154,5694,932],{"class":178},[154,5696,5697,5700],{"class":156,"line":527},[154,5698,5699],{"class":195},"    entry",[154,5701,751],{"class":178},[154,5703,5704,5707,5709,5711,5713,5716],{"class":156,"line":804},[154,5705,5706],{"class":195},"      main",[154,5708,759],{"class":178},[154,5710,196],{"class":164},[154,5712,179],{"class":178},[154,5714,5715],{"class":195},"entry",[154,5717,932],{"class":178},[154,5719,5720,5723,5725,5727,5729,5731,5733,5736,5738,5741,5743,5746],{"class":156,"line":809},[154,5721,5722],{"class":242},"      \"check-availability\"",[154,5724,759],{"class":178},[154,5726,196],{"class":164},[154,5728,179],{"class":178},[154,5730,5715],{"class":164},[154,5732,179],{"class":178},[154,5734,5735],{"class":182},"replace",[154,5737,186],{"class":178},[154,5739,5740],{"class":242},"\"main\"",[154,5742,192],{"class":178},[154,5744,5745],{"class":242},"\"check-availability\"",[154,5747,2330],{"class":178},[154,5749,5750],{"class":156,"line":817},[154,5751,993],{"class":178},[154,5753,5754,5757,5760,5763],{"class":156,"line":827},[154,5755,5756],{"class":195},"    externals",[154,5758,5759],{"class":178},": [",[154,5761,5762],{"class":242},"\"aws-sdk\"",[154,5764,5765],{"class":178},"],\n",[154,5767,5768,5771],{"class":156,"line":833},[154,5769,5770],{"class":195},"    output",[154,5772,751],{"class":178},[154,5774,5775,5778,5780,5783],{"class":156,"line":1033},[154,5776,5777],{"class":195},"      filename",[154,5779,759],{"class":178},[154,5781,5782],{"class":242},"\"[name].js\"",[154,5784,932],{"class":178},[154,5786,5787,5790,5792,5795],{"class":156,"line":1044},[154,5788,5789],{"class":195},"      libraryTarget",[154,5791,759],{"class":178},[154,5793,5794],{"class":242},"\"commonjs2\"",[154,5796,932],{"class":178},[154,5798,5799],{"class":156,"line":1055},[154,5800,993],{"class":178},[154,5802,5803,5806],{"class":156,"line":1062},[154,5804,5805],{"class":195},"    plugins",[154,5807,914],{"class":178},[154,5809,5810,5812,5814,5816,5818],{"class":156,"line":1067},[154,5811,2214],{"class":178},[154,5813,196],{"class":164},[154,5815,179],{"class":178},[154,5817,2479],{"class":195},[154,5819,932],{"class":178},[154,5821,5822,5825,5828,5830,5833],{"class":156,"line":1072},[154,5823,5824],{"class":160},"      new",[154,5826,5827],{"class":164}," webpack",[154,5829,179],{"class":178},[154,5831,5832],{"class":182},"IgnorePlugin",[154,5834,2114],{"class":178},[154,5836,5837,5840,5842,5845],{"class":156,"line":1084},[154,5838,5839],{"class":182},"        checkResource",[154,5841,186],{"class":178},[154,5843,5844],{"class":1954},"resource",[154,5846,3018],{"class":178},[154,5848,5849,5852,5854,5857,5859,5862,5864,5866],{"class":156,"line":1096},[154,5850,5851],{"class":160},"          if",[154,5853,500],{"class":178},[154,5855,5856],{"class":164},"lazyImports",[154,5858,179],{"class":178},[154,5860,5861],{"class":182},"includes",[154,5863,186],{"class":178},[154,5865,5844],{"class":195},[154,5867,5868],{"class":178},")) {\n",[154,5870,5871,5874],{"class":156,"line":1108},[154,5872,5873],{"class":160},"            try",[154,5875,1941],{"class":178},[154,5877,5878,5881,5883,5886,5888,5890],{"class":156,"line":1119},[154,5879,5880],{"class":164},"              require",[154,5882,179],{"class":178},[154,5884,5885],{"class":182},"resolve",[154,5887,186],{"class":178},[154,5889,5844],{"class":195},[154,5891,199],{"class":178},[154,5893,5894,5897,5899,5901,5904],{"class":156,"line":1130},[154,5895,5896],{"class":178},"            } ",[154,5898,3471],{"class":160},[154,5900,500],{"class":178},[154,5902,5903],{"class":195},"err",[154,5905,3018],{"class":178},[154,5907,5908,5911,5914],{"class":156,"line":1137},[154,5909,5910],{"class":160},"              return",[154,5912,5913],{"class":520}," true",[154,5915,2097],{"class":178},[154,5917,5918],{"class":156,"line":1142},[154,5919,5920],{"class":178},"            }\n",[154,5922,5923],{"class":156,"line":1147},[154,5924,5925],{"class":178},"          }\n",[154,5927,5928,5931,5934],{"class":156,"line":1159},[154,5929,5930],{"class":160},"          return",[154,5932,5933],{"class":520}," false",[154,5935,2097],{"class":178},[154,5937,5938],{"class":156,"line":1171},[154,5939,3148],{"class":178},[154,5941,5942],{"class":156,"line":1183},[154,5943,5944],{"class":178},"      }),\n",[154,5946,5947],{"class":156,"line":1194},[154,5948,1892],{"class":178},[154,5950,5951],{"class":156,"line":1201},[154,5952,4977],{"class":178},[154,5954,5955],{"class":156,"line":1207},[154,5956,4982],{"class":178},[12,5958,5959],{},"A l'heure actuelle (mais principalement à cause du temps d'exécution de la requête), la requête prend environ 1s:",[145,5961,5964],{"className":5962,"code":5963,"language":217,"meta":35,"style":35},"language-log shiki shiki-themes one-dark-pro","REPORT RequestId: eaa2b5a3-a754-4b1f-adcc-22ca3c6045aa Duration: 984.41 ms Billed Duration: 985 ms Memory Size: 1024 MB Max Memory Used: 109 MB Init Duration: 540.30 ms\n",[151,5965,5966],{"__ignoreMap":35},[154,5967,5968,5971,5974,5977,5980,5982,5985,5988,5991,5994,5997,6000,6003,6006,6009,6011,6014],{"class":156,"line":157},[154,5969,5970],{"class":178},"REPORT RequestId: ",[154,5972,5973],{"class":520},"eaa2b5a3-a754-4b1f-adcc-22ca3c6045aa",[154,5975,5976],{"class":178}," Duration: ",[154,5978,5979],{"class":520},"984",[154,5981,179],{"class":178},[154,5983,5984],{"class":520},"41",[154,5986,5987],{"class":178}," ms Billed Duration: ",[154,5989,5990],{"class":520},"985",[154,5992,5993],{"class":178}," ms Memory Size: ",[154,5995,5996],{"class":520},"1024",[154,5998,5999],{"class":178}," MB Max Memory Used: ",[154,6001,6002],{"class":520},"109",[154,6004,6005],{"class":178}," MB Init Duration: ",[154,6007,6008],{"class":520},"540",[154,6010,179],{"class":178},[154,6012,6013],{"class":520},"30",[154,6015,6016],{"class":178}," ms\n",[56,6018,6020],{"id":6019},"le-coût-du-projet","Le coût du projet",[12,6022,6023],{},"Grâce au Free-Tiers d'AWS, ce qui me coûte réellement de l'argent dans ce projet est SNS (qui sert à l'envoi de SMS). L'autre coût est relatif à Route 53 car j'ai déployé le site\ndans un sous-domaine.",[12,6025,6026],{},"Au 29 Août 2021, je vais avoir dépensé 7,34$ pour me faire plaisir (j'aurais pu le déployer sur mes propres serveurs dédiés) et pour pouvoir m'acheter un vélo sans\nattendre que le site m'envoie un mail ou qu'il y ait suffisamment de stock pendant suffisamment longtemps pour que je puisse voir le vélo, ou l'acheter en magasin.",[12,6028,6029],{},[119,6030],{"alt":6031,"className":6032,"src":6033},"Coût du projet",[123],"\u002FProgrammation\u002Fachat_velo\u002Fcout.png",[56,6035,6037],{"id":6036},"bilan","Bilan",[12,6039,6040],{},"On est fin septembre, j'ai reçu mon vélo et j'ai pu rouler plusieurs semaines avec (Je l'ai recu début septembre).",[12,6042,6043],{},"Cela a commencé par une notification à 11h59 indiquant que 4 exemplaires avaient été ajoutés au site. J'ai pu le commander dans la foulée. A 14h, tous les exemplaires avaient été vendus.\nJe devais partir manger quand j'ai reçu la notification.",[12,6045,6046],{},"Si je n'avais pas développé ce petit programme, je n'aurais jamais su que des vélos étaient en stock, car je n'ai jamais reçu le fameux mail. De plus en travaillant\n(car je suis revenu de vacances depuis) je ne peux pas rafraîchir la page en continu (1 fois le matin, 1 fois le soir).",[12,6048,6049],{},"Bref, est-ce que le mail que doit nous envoyer le site est de la poudre aux yeux ? Se sert-il d'une file d'attente (et dans ce cas je m'excuse auprès de celui que\nj'ai doublé) ? Ou n'est-il envoyé que quand il y a plus de 10 exemplaires qui arrivent sur le site ?",[12,6051,6052],{},"Depuis j'ai désactivé le programme. Avant j'avais pu voir le stock bouger rapidement sur les VTT en XL et sur le VTC en XL et en S. Ce que je peux dire c'est qu'une\ntrentaine de vélo ajoutés sur le VTT le soir à 21h partent comme des petits pains. Il n'en restait plus le lendemin à 12h...",[12,6054,6055],{},"Au delà de l'achat du vélo, j'ai été content de pouvoir mettre un site en production rapidement et quasi-gratuitement (si on ne compte pas les SMS). Je me demande ce\nque m'aurais coûté le même site au delà de la période des 1 an (après la fin du free-tiers).",[6057,6058,6061,6066],"section",{"className":6059,"dataFootnotes":35},[6060],"footnotes",[56,6062,6065],{"className":6063,"id":34},[6064],"sr-only","Footnotes",[99,6067,6068,6079],{},[102,6069,6071,6072],{"id":6070},"user-content-fn-1","Certains me conseillent des petits magasins de vélo, d'autres des VTCAE à plus de 5 000 €. Bref, nous ne sommes pas là pour parler de mon choix d'enseigne. Mais si vous voulez tout savoir, c'est une question pratique. Il est à coté de chez moi. ",[30,6073,6078],{"href":6074,"ariaLabel":6075,"className":6076,"dataFootnoteBackref":35},"#user-content-fnref-1","Back to reference 1",[6077],"data-footnote-backref","↩",[102,6080,6082,6088],{"id":6081},"user-content-fn-2",[6083,6084,6085],"blockquote",{},[12,6086,6087],{},"Hello friend jsdom only handles static html, to make the click event you will need a headless browser for scraping the web. There are several one of them is the Puppeter that uses the chorme in the background.",[30,6089,6078],{"href":6090,"ariaLabel":6091,"className":6092,"dataFootnoteBackref":35},"#user-content-fnref-2","Back to reference 2",[6077],[6094,6095,6096],"style",{},"html pre.shiki code .seHd6, html code.shiki .seHd6{--shiki-default:#C678DD}html pre.shiki code .sU0A5, html code.shiki .sU0A5{--shiki-default:#E5C07B}html pre.shiki code .sjrmR, html code.shiki .sjrmR{--shiki-default:#56B6C2}html pre.shiki code .sn6KH, html code.shiki .sn6KH{--shiki-default:#ABB2BF}html pre.shiki code .sVbv2, html code.shiki .sVbv2{--shiki-default:#61AFEF}html pre.shiki code .sVyAn, html code.shiki .sVyAn{--shiki-default:#E06C75}html pre.shiki code .subq3, html code.shiki .subq3{--shiki-default:#98C379}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sVC51, html code.shiki .sVC51{--shiki-default:#D19A66}html pre.shiki code .sLaUg, html code.shiki .sLaUg{--shiki-default:#FFFFFF}html pre.shiki code .s_ZVi, html code.shiki .s_ZVi{--shiki-default:#E06C75;--shiki-default-font-style:italic}html pre.shiki code .sV9Aq, html code.shiki .sV9Aq{--shiki-default:#7F848E;--shiki-default-font-style:italic}html pre.shiki code .shdRp, html code.shiki .shdRp{--shiki-default:#C678DD;--shiki-default-font-style:italic}html pre.shiki code .sKU4T, html code.shiki .sKU4T{--shiki-default:#E5C07B;--shiki-default-font-style:italic}",{"title":35,"searchDepth":202,"depth":202,"links":6098},[6099,6100,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112],{"id":58,"depth":202,"text":59},{"id":89,"depth":202,"text":6101},"La 1er version",{"id":689,"depth":202,"text":690},{"id":842,"depth":202,"text":843},{"id":1221,"depth":202,"text":1222},{"id":2426,"depth":202,"text":2427},{"id":2894,"depth":202,"text":2895},{"id":2919,"depth":202,"text":2920},{"id":4659,"depth":202,"text":4660},{"id":5527,"depth":202,"text":5528},{"id":6019,"depth":202,"text":6020},{"id":6036,"depth":202,"text":6037},{"id":34,"depth":202,"text":6065},"Programmation","programmation","2021-09-27",{"type":9,"value":6117},[6118,6120,6124,6131,6133,6137,6139],[12,6119,14],{},[12,6121,17,6122,22],{},[19,6123,21],{},[12,6125,25,6126],{},[27,6127,6128],{},[30,6129,37],{"href":32,"ariaDescribedBy":6130,"dataFootnoteRef":35,"id":36},[34],[12,6132,40],{},[12,6134,43,6135,48],{},[45,6136,47],{},[12,6138,51],{},[12,6140,54],{},"md","Lille, France",{"planet":205},"\u002Fpost\u002Fachat_velo",{"title":6,"description":14},"achat_velo","posts\u002FProgrammation\u002F2021-09-27_achat_velo",[6149,6150,6151,6152,6153,6154],"javascript","nodejs","aws","web","velo","sms","p5JgMwprkltEBjhdZdpkmC59vL1CqDYiHhoE51Qhs0U",1777849586235]