curso node llamar a un service web api

primero vamos a instalar yargs
y setear que reciba (esta vez sin un comando de por medio) el argumento
de la direccion de la que se quiere saber su clima


const argv=require('yargs').options(
{
   direccion:{
alias:'d',
demand:true,
desc: 'direccion a traer el clima'
}
}).
argv;

console.log(argv.direccion);


entonces si llamamos

node app -d "buenos aires argentina"

obtendremos

buenos aires argentina


vamos a instalar ahora un paquete para poder hacer llamadas a apis externas,
en este caso usaremos Axios (tambien puede ser request)

npm install axios --save

recordar que ponemos el --save para que se registre el paquete en el package.json como un dependencia, de lo contrario, se bajara la libreria sin registrarse la dependencia.

si se quiere instalar una version en especifico simplemente la escribimos antecediendole una arroba:

npm installa axios@0.18.0 --save

ahora ya podemos utilizarlo para llamar al webservice de google de geocoding

const axios=require('axios');

const urlEncoded = encodeURIComponent(argv.direccion);//para que convierta espacios

const apiKey = "AIzaSyBlRKjSjinm50447yd_qWAjvzojhWND7Ip-w";

axios.get(`https://maps.googleapis.com/maps/api/geocode/json?address=${urlEncoded}&key=${apiKey}`)
  .then(function (response) {
    console.log(JSON.stringify(response.data));
  })
  .catch(function (error) {
    console.log(error);
  });


usamos response.data
para que por consola nos muestre solo los datos de la data de geocoding
y JSON.stringify(response.data)
para que nos muestre los datos de los objetos / arrays que trae Data sino no los podremos ver.

por consola los datos apareceran uno al lado del otro si queremos que se vean en distintas lineas
y con margenes usamos

JSON.stringify(response.data,undefined,2));

la respuesta sera algo asi

 {                                                   
 "results": [                                       
   {                                                 
     "address_components": [                         
       {                                             
         "long_name": "Buenos Aires",               
         "short_name": "CABA",                       
         "types": [                                 
           "locality",                               
           "political"                               
         ]                                           
       },                                           
       {                                             
         "long_name": "Buenos Aires",               
         "short_name": "CABA",                       
         "types": [                                 
           "administrative_area_level_1",           
           "political"                               
         ]                                           
       },                                           
       {                                             
         "long_name": "Argentina",                   
         "short_name": "AR",                         
         "types": [                                 
           "country",                               
           "political"                               
         ]                                           
       }                                             
     ],                                             
     "formatted_address": "Buenos Aires, Argentina", 
     "geometry": {                                   
       "bounds": {                                   
         "northeast": {                             
           "lat": -34.5265464,                       
           "lng": -58.33514470000001                 
         },                                         
         "southwest": {                             
           "lat": -34.7051011,                       
           "lng": -58.5314522                       
         }                                           
       },                                           
       "location": {                                 
         "lat": -34.6036844,                         
         "lng": -58.3815591                         
       },                                           
       "location_type": "APPROXIMATE",               
       "viewport": {                                 
         "northeast": {                             
           "lat": -34.5265464,                       
           "lng": -58.33514470000001                 
         },                                         
         "southwest": {                             
           "lat": -34.7051011,                       
           "lng": -58.5314522                       
         }                                           
       }                                             
     },                                             
     "place_id": "ChIJvQz5TjvKvJURh47oiC6Bs6A",     
     "types": [                                     
       "locality",                                   
       "political"                                   
     ]                                               
   }                                                 
 ],                                                 
 "status": "OK"                                     
 }                                                 

entonces..si quisieramos imprimir solo la direccion formateada, la latitud y la longitud hariamos esto:

let results = response.data.results[0];
    let formatted_address = results.formatted_address;

    let lat = results.geometry.location.lat;
    let lng = results.geometry.location.lng;

    console.log(`Direccion: ${formatted_address}`);
 
console.log(`Longitud: ${lng}`);
 
console.log(`Latitud: ${lat}`);



///////////////////////// refactorizando el codigo//////////////////////////////////

vamos a crear una funcion getLugar para que nos devuelva un objeto con las propiedades
direccion,latitud y longitud. Y lo escribiremos en un archivo aparte (lugar/lugar.app) dentro de un carpeta llamada lugar.

lugar.js:


const axios=require('axios');



const getLugar = async (direccion) => {

   let addressEncoded = encodeURI(direccion);
   let apiKey = "AIzaSyBlRKjSjinm507yd_qWAjvzojhWND7Ip-w";

   let resp = await axios.get(`https://maps.googleapis.com/maps/api/geocode/json?address=${addressEncoded}&key=${apiKey}`);

   if(resp.data.status === "ZERO_RESULTS"){
      throw new Error("No se encontraron resultados");
   }
 
   let results = resp.data.results[0];
   return {
     direccion: results.formatted_address,
     longitud:results.geometry.location.lng,
     latitud:results.geometry.location.lat
   }
 
}
   
module.exports = {
  getLugar
}


y en app.js

const argv=require('yargs').options(
{
   direccion:{
alias:'d',
demand:true,
desc: 'direccion a traer el clima'
}
}).
argv;

const { getLugar } = require('./lugar/lugar.js');

getLugar(argv.direccion)
.then(resp=>{
  console.log(resp)
}).catch(e=>console.log(e));




curso node crear release del proyecto

vamos a crear un tag desde la carpeta en la consola

git tag -a v1.0 -m "Primera version"

listamos los tags

git tag

veremos que hay uno solo

v1.0

y luego pusheamos

git push --tags

luego vamos a nuestra pagina de github y hacemos click en la cabecera que dice "release"
vamos a la pestaña de Tags y ahi clickeamos en "crear release"

le ponemos un titulo, una descripcion y click en el boton de publicar.

nos quedaria algo asi

un Release es un Tag con una descripcion.

entonces desde aqui se puede hacer click para descargar facilmente todo el codigo fuente de la aplicacion

wordress creando un plugin para wordpress

la razon principal para escribir un plugin es separar tu codigo del codigo core de wordpress.
Si algo sale mal el resto del sitio seguira , funcionando.

Una alternativa para modificar las funciones de wordpress es editar el archivo
wp-includes/functions.php o functions.php que es parte de un theme. Sin embargo esto no es recomendable debido a las constantes actualizaciones de wordpress que borraran las modificaciones que le hagas a su archivo functions.php

Los plugind interactuan con el core de wordpress atraves de hooks,
existen 2 tipos de hooks:
1-action hooks , para agregar y/o eliminar funciones
2-filter hooks, para modificar datos producidos por funciones

para crear y activar un plugin nuestro, creamos el archivo php dentro de la carpeta wp-content/plugins
luego en el admin de wordpress, vamos al menu de PLugins, lo ubicamos y activamos.

Ejemplo de action hook, para agregar un bloque de texto al final del footer y lo saca si es domingo (Sunday)

<?php
/*
Plugin Name: Add Text To Footer
Description: Example Plugin Action Hook
*/

// Hook the 'wp_footer' action hook, add the function named 'mfp_Add_Text' to it
add_action("wp_footer", "mfp_Add_Text");

// Hook the 'wp_head' action, run the function named 'mfp_Remove_Text()'
add_action("wp_head", "mfp_Remove_Text");

// Define 'mfp_Add_Text'
function mfp_Add_Text()
{
  echo "<p style='color: black;'>".date("l")."Despues de que el Footer es cargado, mi texto es agrega.do! </p>";
}

// Define the function named 'mfp_Remove_Text()' to remove our previous function from the 'wp_footer' action
function mfp_Remove_Text()
{
  if (date("l") === "Sunday") {
    // Target the 'wp_footer' action, remove the 'mfp_Add_Text' function from it
    remove_action("wp_footer", "mfp_Add_Text");
  }
}


Ejemplo de filter Hook, que reemplaza los espacios en blanco del contenido de un post por asteriscos

<?php
/*
Plugin Name: Replace text space in content post
Description: Example PLugin Filter hook
*/
// Hook the 'the_content' filter hook (content of any post), run the function named 'mfp_Fix_Text_Spacing'
add_filter("the_content", "mfp_Fix_Text_Spacing");

// Automatically correct double spaces from any post
function mfp_Fix_Text_Spacing($the_Post)
{
 $the_New_Post = str_replace(" ", "*", $the_Post);

 return $the_New_Post;
}

wordpress programando en wordpress

worpress tiene 3 componentes principales:

el core, themes y plugins

core: contiene todo el codigo que lo hace funcionar como un CMS
This includes desde the admin backend hasta functions like scheduling posts, password strength checking, lae creation of users and asi. is responsible for the backend of a website and how it operates.

themesare responsible for the front-end and how website’s look and feel. You might want to install and activate pre-built themes or break out of the box completely and go your own way with custom designs.

plugins: proveen funcionalidad extra a wordpress. To make this happen, a plugin may modify the backend and/or the front-end of a website. A plugin that adds a Tweet button for Twitter is a good example. It would probably create a new settings page in the backend admin menu where you could set up some default options for a user’s tweet and it would also add itself to the front-end of a website, most likely displaying under a post.

areas de desarrollo:


themes,plugins, rest apis, core

Plugins

plugins are la esencia de WordPress, transforming it into everything from a forum to a social network, eCommerce platforms and much more with the push of a button. Plugins give you total control over all aspects of the WordPress system, allowing you to modify anything you want. 
The REST API is relatively new and allows you to create true applications based on WordPress. This includes iPhone and Android apps and all sorts of crazy things like TV apps even, if you know some other programming languages.
You can connect to any website and ask it for your latest five posts. But you can do a lot more than that: you can delete users, create users, edit categories and more (which you need to authenticate yourself, of course). This means you can use WordPress as a repository of information and build the front-end and/or the backend using a different system altogether.




laravel 5.6 crear api rest con autenticacion usando passport


Crear una nueva aplicacion laravel


composer create-project --prefer-dist laravel/laravel blog


Dentro de la carpeta del proyecto creado instalar Passport

composer require laravel/passport

Editar el archivo config/app.php

y en la seccion donde se registren providers agregar una nueva entrada para Passport
'providers' =>[
Laravel\Passport\PassportServiceProvider::class,
],


Crear la base de datos que usara la aplicacion y setear los datos de conexion en el archivo .env

Ejecutar la migracion
php artisan migrate

Instalar Passport para que genere los tokens de seguridad
php artisan passport:install

Editar app/User.php
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
  use HasApiTokens, Notifiable;


Editar app/Providers/AuthServiceProvider.php
use Laravel\Passport\Passport;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        'App\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();
        

Passport::routes(); 

//
    }
}

Editar config/auth.php en la seccion de guards cambiar la entrada para api/driver a passport

'guards' => [ 
        'web' => [ 
            'driver' => 'session', 
            'provider' => 'users', 
        ], 
        'api' => [ 
            'driver' => 'passport', 
            'provider' => 'users', 
        ], 
    ],

Crear la api route editando el archivo routes/api.php

Route::post('login', 'API\UserController@login');
Route::post('register', 'API\UserController@register');
Route::group(
 ['middleware' => 'auth:api'], 
 function(){
  Route::get('details', 'API\UserController@details');
 });


crear la carpeta API en app/Http/Controllers

en esa carpeta crear el controlador UserController.php

<?php

namespace App\Http\Controllers\API;

use Illuminate\Http\Request; 
use App\Http\Controllers\Controller; 
use App\User; 
use Illuminate\Support\Facades\Auth; 
use Validator;
class UserController extends Controller 
{
 public $successStatus = 200;
/** 
     * login api 
     * 
     * @return \Illuminate\Http\Response 
     */ 
public function login(){ 
 if(Auth::attempt(['email' => request('email'), 'password' => request('password')])){ 
  $user = Auth::user(); 
  $success['token'] =  $user->createToken('MyApp')-> accessToken; 
  return response()->json(['success' => $success], $this-> successStatus); 
 } 
 else{ 
  return response()->json(['error'=>'Unauthorised'], 401); 
 } 
}
/** 
     * Register api 
     * 
     * @return \Illuminate\Http\Response 
     */ 
public function register(Request $request) 
{ 
 $validator = Validator::make($request->all(), [ 
  'name' => 'required', 
  'email' => 'required|email', 
  'password' => 'required', 
  'c_password' => 'required|same:password', 
 ]);
 if ($validator->fails()) { 
  return response()->json(['error'=>$validator->errors()], 401);            
 }
 $input = $request->all(); 
 $input['password'] = bcrypt($input['password']); 
 $user = User::create($input); 
 $success['token'] =  $user->createToken('MyApp')-> accessToken; 
 $success['name'] =  $user->name;
 return response()->json(['success'=>$success], $this-> successStatus); 
}
/** 
     * details api 
     * 
     * @return \Illuminate\Http\Response 
     */ 
public function details() 
{ 
 $user = Auth::user(); 
 return response()->json(['success' => $user], $this-> successStatus); 
} 
}

Ya podemos probar la api rest:

la de creacion/registro de usuarios

POST http://localhost/authblog/public/api/register

Y en el body ( fom-data ) envio

name
email
password
c_password

el de login

POST http://localhost/authblog/public/api/login

Y en el body ( fom-data ) envio

email
password

que nos devolvera algo similar:

{
    "success": {
        "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImZjODRmMzhhZjg3MmNlZTM0ZDgyZGRlZjNkNDI3OWU0OGE3MjIzYmY5ZjY1ZDVkN2ZlOWNhN2ExNWQ5NGZhNWFiMDg0ZTM1ZmE3N2U4NjgzIn0.eyJhdWQiOiIxIiwianRpIjoiZmM4NGYzOGFmODcyY2VlMzRkODJkZGVmM2Q0Mjc5ZTQ4YTcyMjNiZjlmNjVkNWQ3ZmU5Y2E3YTE1ZDk0ZmE1YWIwODRlMzVmYTc3ZTg2ODMiLCJpYXQiOjE1MzQ2NDcwMDIsIm5iZiI6MTUzNDY0NzAwMiwiZXhwIjoxNTY2MTgzMDAyLCJzdWIiOiIxIiwic2NvcGVzIjpbXX0.FWOKWiOsWLv5oWrIWPKCsMRFd9k2DXMePgr6bWZRVwQqTj-8V5c5ZNfsntDehNnZ0mP0IWBgA9NtjFBeC-VUwsN4uowi3nd8LMINtkMhPa61mPXkem83hxA0t4ZO46dWWggq64kXCkwZz0CRkv99F4RRVd3G6_upKbMZy0U-t-G0GNC8uXs6OQsIGDoTGTAxdUSs7fbS4uC4TinYAirxibBpbXGRTE0Hxr4-ji5vKU0myHPPk9xg-6x4kHin6JVXvIU5QHkWJxYDXOaou0OF2znW8huG7L-s4G4zUmHbID6vc8ycIkdpGP2lFRaomyVtwtnQMze6YLCYEQtf28JfBaMyuejsPzj788Dv0ijK7BJmfc0zOgsuOqb3xkzgczAtmlJarwbJlEVHCH99tAP1iC75lNHw1lgo1_EcU9aRvRrmmGaEb4GIQdFqf7O5Hf5trmiFpszEVOGkGxQVe1acs_HIpv9ivUAkh5aPDczI2ZrH7WAXnyIcaO92OqX4ZbdTtpyk-J-ExXiNCjjfyg7bOsh3sXwZKO76hlpp1oPiAwbj1hrTND8Gz5_0nE37pqG0cu65m81VnwGezs3nOCnBkHsvQ6FiIdK_ViBOS9rnUaypwMCEjnJLimdNjI-jFZBJ1dUkws2GHlianISxegFq6pmBiBMtX0dZTJeEUu3je_M"
    }
}

el que trae los detalles de un usuario

GET http://localhost/authblog/public/api/details

en este caso debemos enviar en el header
Accept -> application/json
Authorization -> Bearer {{el token que se obtiene en el login}} 

que nos devolvera algo asi:

{
    "success": {
        "id": 1,
        "name": "ibazan",
        "email": "israelbazan76@gmail.com",
        "created_at": "2018-08-18 22:42:41",
        "updated_at": "2018-08-18 22:42:41"
    }
}





curso node leer y guardar en un archivo

estructura de proyecto:

db/data.json
por-hacer/por-hacer.php
app.js

/*********** por-hacer.php **********/

const fs = require('fs');

let listadoPorHacer=[];

const cargarDB = () =>{
try {
//
listadoPorHacer=require("../db/data.json");
} catch(e) {
// al inicio cuando el archivo esta vacio nos da una exception, entonces la variable
// la ponemos como una arreglo vacio
listadoPorHacer=[];
}


}

const crear=(descripcion)=>{

    cargarDB();

let porHacer = {
descripcion:descripcion,
completado:false
}

listadoPorHacer.push(porHacer);

guardarDB();

return porHacer;
}

const guardarDB=()=>{
let data=JSON.stringify(listadoPorHacer);
fs.writeFile('db/data.json', data, (err) => {
      if (err) throw new Error('No se pudo grabar',err);
     // console.log('The file has been saved!');
    });
}

const actualizar=(descripcion,completado=true)=>{

    cargarDB();

let index = listadoPorHacer.findIndex(tarea=>tarea.descripcion===descripcion);

if(index>=0){
listadoPorHacer[index].completado=completado;
    guardarDB();
        return true;
}


return false;
}

module.exports = {
crear, getListado, actualizar
}


/**************************   app.js ******************************/
const { crear, getListado, actualizar } = require('./por-hacer/por-hacer.js');


let comando =argv._[0];

switch (comando) {
case 'listar': let listado = getListado(); for(let elemento of listado){ console.log(elemento.descripcion +' estado: '+elemento.completado); } break; case 'crear': crear(argv.descripcion); break;
case 'actualizar':
console.log("actualizar");
break;
default:
console.log("comando no reconocido");
break;
}


vamos a agregarle la tarea de borrar entonces en app.js

case 'borrar':
    if(borrar(argv.descripcion,argv)){
    console.log('Borrado OK')
    }else{
    console.log("Fallo en el borrado");
}
break;

y en por-hacer.js

const borrar=(descripcion)=>{

    cargarDB();

let index = listadoPorHacer.findIndex(tarea=>tarea.descripcion===descripcion);

if(index>=0){
listadoPorHacer.splice(index,1);//elimina en la posicion index 1 elemento
    guardarDB();
        return true;
}


return false;
}
//recordar exportarla
module.exports = {
crear, getListado, actualizar, borrar
}

y en app.js
agregarla a la lista de funciones que necesito

const { crear, getListado, actualizar,borrar } = require('./por-hacer/por-hacer.js');

en yargs.js agregar la definicion de la tarea

.command('borrar','borra una tarea',{
    descripcion:descripcion
})


para ejecutar

node app.js borrar "nombre de tarea a borrar"

curso node guardar proyecto en github

en la consola y desde la carpeta del proyecto

escribimos

git init

luego creamos en la raiz creamos un archivo .gitignore

y listamos los archivos o carpetas que no queremos backupear
por ejemplo

*.txt
node_modules/

luego
git add .
git commit -m "commit inicial"

luego vamos a nuestra cuenta de github y creamos un New repository en donde se almacenaran los backups de nuestro proyecto, por ejemplo uno llamado "multiplicar-node"

volvemos a la consola y
seteamos la direccion que tomaremos como "origin"
git remote add origin https://github.com/israelbazan76/multiplicar-node.git

y luego enviamos los archivos a la rama master
git push -u origin master

podemos tambien escribir un archivo de readme describiendo el archivo.

esto lo hacemos creando un archivo en la raiz llamado README.md

(la extension md significa que es un archivo markdown..archivo de markado ligero 
con una sintaxis sencilla)

lo subimos
git add .
git commit -m "nuevo readme.md"
git push

listo, ahora cuando entremos a nuestro repositorio, veremos el archivo readme
interpretado.

https://github.com/israelbazan76/multiplicar-node




curso node yargs simplificar configuracion de comandos

la parte inicial del codigo la podemos separar en otro archivo y en el caso del ejemplo en el que estuvimos trabajando de crear y listar las tablas de multiplicar en el que los argumentos son los mismos estos se pueden tambien simplificar.

entonces podemos crear una carpeta config y dentro el archivo yargs.js

ahi adentro pondriamos

const opciones={
base:{
demand: true,
alias: 'b'
},
limite:{
alias:'l',
default:10
}
};

const argv=require('yargs')
.command('listar','imprime por consola la tabla de multiplicar',opciones)
.command('crear','crea un archivo con la tabla de multiplicar',opciones)
.help().argv;

module.exports = {
argv
}

y luego en el archivo de la aplicacion principal app.js

const argv=require('./config/yargs').argv;//asi solo tomamos argv para asignarlo a nuestra variable




linux ubuntu mint actualizar chrome

 desde una terminal: $ sudo apt update $ sudo apt install google-chrome-stable