Thursday, 4 January 2018

NodeJS - BC

Auth0


Go to: https://publisher-film.beacon.britishcouncil.digital
Log in with credentials:
dawid.nawrot@britishcouncil.pl
dmj2=DGZVXAChRzh6sk*hkuXd8KHR=ecEZrT)7tVaijLEvHxbtu4pp=zGLwrFQYW

Enable 2 factor auth if needed.

After logging in go to console and get access_token by typing:
localStorage.access_token

in console. It should return access token.

Go to playground and add code to add a page and in http headers add authorization header like so:

{
"Authorization" :"Bearer access_token"
}

it should return an ID of a page.

You can also go to https://jwt.io/
and paste your access_token to get an idea what you can do in scope section and how long this access_token is valid.

Adding a page with test:seed and publishing with graphql playground

Once panda is running go to console and type:
lando yarn test:seed

This is going to create a full page for you bypassing authorization. A structure of a page can be viewed at panda/src/resolvers/__tests__/helpers/data.js (fullSamplePage constance).

Once the page is added, you can log in to mongo db and get pageId value. Copy pageId and go to playground to publish it.



Postgraphile:


Video

Starting the app. First you need to have yarn installed and node > 8.6. I use nvm, so to install another version of node i use:

nvm install 8.9

Check node version with:
nvm version node

With this we can go to /zoo/hedgehog and type yarn which will install project which will display:

dns-MacBook-Pro-2:hedgehog dn$ yarn start
yarn run v1.10.1
warning ../package.json: No license field
$ env NODE_ENV=production node src/index.js
> 🐻 is alive and kicking at:
>> http://localhost:5000/graphql (Apollo)
>> http://localhost:5000/db (PostGraphile)

Several things needs to be done to make this work now. The problem is that postgresql does not have any schema imported and no data. If you try to run yarn seed it will end up with error. So, we need to:

1. Log in to lando service where PostgresDB exists
lando ssh pg

2. Import schema to db
psql -f src/postgres/schema.sql -U hh hh

In result we should get:
CREATE TYPE
CREATE TYPE
CREATE TABLE
CREATE TABLE

3. Log in to db to verify if schema exists.
psql -d hh -U hh

Similar to show databases in MySQL is:
\dt

Which should result with List of relations
Schema | Name | Type | Owner
--------+----------+-------+-------
public | author | table | hh
public | metadata | table | hh
(2 rows)

To exit from db:
\q

4. Edit seed.js file to uncomment part which adds users and comment out part which adds metadata.
5. RUN yarn start
5. In another console tab run yarn seed to generate users.
6. Edit seed.js file to comment out users and uncomment metadata.
7. Run yarn seed again to generate metadata.
8. Go to ChromiQL and provide backend url to db (http://localhost:5000/db)
9. Check if schema is there.
10. Go to Apollo graphql endpoint and run example query or mutation.

Easy, right?

Apollo graphql endpoint usage:
Query and mutation:



Connecting to DB issue

Whenever you get an error about port allocated for database the issue is that you run wrong command or use wrong direcotory for command. Scenarios:

1. If you decide to run all the apps (Panda, Rhino, Puma) at the same time with lando start from /zoo direcotory you need to run commands from /zoo direcotory. For example:

lando panda test:watch
lando panda user:add --username='admin' --password='admin' --email='admin@example.com'

and so on.

2. If you have three apps at once, but you run only one at the time, eg.: lando start panda then commands should be quite different. First of all all the commands should be run from panda directory. For example:


lando yarn test:watch
lando yarn user:add --username='admin' --password='admin' --email='admin@example.com'

And that's it.

Working with panda on platform.sh

Login to ssh with platform.sh on desired branch
from /app directory we run:

yarn user:add --username='dawidnawrot' --password='dawidnawrot' --email='dawidnawrot@example.com'
yarn user:role --username='dawidnawrot' --role='admin'

voilla

Document describing project

Document

Updating libraries

If someone updates package.json file, so it has new dependencies (dev or standard) we need to get those to make project work. So, assuming we already have pulled changes with new dependencies we need to type:

lando panda add mongoid-js@1.1.3 --dev

This example shows how to add mongoid, which was added by someone else to package.json. I'm pretty sure it might be done better way, so we don't have to list dependency, there should be some update command.

Update: and there is: lando yarn upgrade (note it's upgrade, not update)


As far as the command itself:

lando - run lando
panda - use panda project
add - this is one of yarn commands, so if this was provided without lando we would type: yarn add mongoid-js@1.1.3 --dev but I assume lando is configured the way we don't have to use yarn command because it's a default one.
mongoid-js@1.1.3 - it's a package and version of it
--dev - it's the same as --save-dev in npm

Cheetsheet for yarn vs npm commands: https://github.com/areai51/yarn-cheatsheet

Running tests against panda


Assuming we're working in consolidated version of zoo:

1. We run tests from /zoo directory (not from panda)
2. In /zoo directory we can run:

lando panda test
lando panda test:watch

And so on. So all the scripts that are defined in panda/package.json are run from /zoo directory but with
lando panda
prefix.

In addition, because we use yarn, rather npm for running test commands we don't have to add
run
for non default scripts. So, if were using npm it should be something like this:

lando panda npm run test:watch

But, becasue we use yarn and it's already aliased, we run:
lando panda test:watch

As we run tests we need to have some users. Tests that run mostly defines some users (eg. a username or password or role). So, we need to generate those users or roles in order to pass tests. To add user or role we can use scripts developed by Simon. It's described down below, in next section.

And that's it.

Adding a page from scratch


1. Go to /zoo directory
2. We have to create a user if there's no users in DB:

lando panda user:add --username='admin' --password='admin' --email='admin@example.com'

It should give us a note in green: "User added".

3. We have to assign a role to this user. Available roles are: guest, contributor, editor, admin, superadmin. It's all from in db.acl_roles.find() collection.

To assign a user to specific role:

lando panda user:role --username='admin' --role='superuser'

It should give us a note in green: "Role added to admin".

4. Open up a ChromeiQL extension. Endpoint should be set up to: http://panda.lndo.site/graphql

5. Write a login mutation to login:

mutation login {
  login(username:"admin", password:"admin") {
    username
    id
  }
}

6. To check if we're logged in query DB:
query currentUser {
  currentUser {
    id,
    email,
    username
  }  
}

7. To add a page we need to use two window sections, first we provide a mutation and second we add query variables like so:

Mutation:
mutation addPage($input : PageInput) {
  addPage(input : $input)
  {
    id
  }
}

Query variables:
{
  "input": {
    "language": "pl", 
    "type": "whatever"
  }
}

By running this mutation with those variables we should end up with that kind of response:

{
  "data": {
    "addPage": {
      "id": "5b4734f38dbeba047107ee29"
    }
  }
}


Using scripts made with babel-node

Being in zoo direcotory (not panda) type:

lando panda user:add --username='admin' --password='admin' --email='admin@example.com'

General note

It's better to use chromeIQL extension rather than Playground Tool. The second one is buggy, it does not send a cookie, so there's no way to find out whether user is logged in or not.

Adding user:




Simplest query:




Current user:




Multiple queries

You can choose the one you want on play. Basically it just needs a name right after the query or mutuation:



Basic facts about node

  1. npm = bower (2013) = yarn (2017)
  2. to start new project we use npm init which generate package.json file
  3. npm init command will only generate package.json file, it's not checking anything (if the index.js file exists, or similar
  4. npm is using package.json file to keep project dependencies
  5. npm is a package manager, so you don't have to download each library, but declare it in package.json file
  6. Installing package: npm install package_name --save or npm install package_name --save-dev. This will do two things, first it'll modify package.json file. Second it'll download a package to node_modules folder.
  7. If you have node.js installed, you already have npm installed

  8. Node.js -> Webpack and require function

    Loading external files: php have its include() function. Javascript didn't have this feature until a new project CommonJS started in 2009. The output of this project is node.js which is server software and it does allow to do this. Previously all the files had to be loaded each by each in html. Today we can use something like that with nodejs. Instead of loading all of moment.min.js with an HTML script tag, you can load it directly in the JavaScript file as follows:



    This is how module loading works in node.js, which works great since node.js is a server side language with access to the computer’s file system. Node.js also knows the location of each npm module path, so instead of having to write require('./node_modules/moment/min/moment.min.js), you can simply write require('moment') — pretty sweet.

    Ok, but this won't work right now, as browser does not know what is require function. To make it work we need to have module bundler, which will make an output as one big file, for example bundle.js with all libraries in it. The bundler we need is a Webpack.

    Installing webpack:



    Running webpack:



    This is going to analyze index.js file, it'll find all the occurences of require and replace it with actuall js files and output it as a bundle.js file. It's all working fine, but with any change in index.js file we would have to run it over and over again. To automate this process we have to create webpack.config.js file in root directory of our project.



    This will allow us to regenrate everythis with simpler version:



    To make it work even easier we can run task runner that comes with npm. We can do it by modifying package.json file like so:



    Running npm run build will rebuild everything and will minimize our code for production because it uses -p option.
    Running npm run watch will rebuild everything on the fly with every change to index.js file.

    Let's go deeper and run a tool (webpack-server-dev) that will automatically refresh our site in browser with every change we make in index.js file.



    Now, we have to add another script / command to our package.json file to make it work:




Mongo CLI

  • To open mongo db cli just type: lando mongo in project directory
  • To login to main: lando mongo main -umain -pmain

  • Commands

    • db.getCollectionNames() - displays list of collections
    • db.[collectionName].find() - similar to select * from collectionName
    • db.contents.find().pretty()
    • db.users.find().pretty()
    • db.roles.find().pretty()
    • db.components.find(ObjectId("5b55bad212161c05e9fa5e2c")).pretty()
    • db.components.find({}, {}).pretty() - get IDs only

    • db.components.find({ col1: "A" }, { column, column, column }) - similar to: select col1, col2 from components where col1 = A














Lando

  • lando logs -t -f
  • lando start
  • lando stop
  • lando restart
  • lando rebuild

Useful links

Link to testing branch for PR (different then with drupal)

Quote from Vin: "when a PR is open, go to the PR, scroll down, open up "checks passed", next to platformsh, details link".