Categories
Javascript

How to publish an npm module

Step 0: You need some code to share.

Create a new Github repo or choose one you currently want to publish

Here is the command line argument to create a repo called “adder”

$ curl -u <your_username> https://api.github.com/user/repos -d "{\"name\": \"adder\"}"

Once you have chosen a Github repo clone it

Step 1: Create a proper package.json

The best way to do this is to run the npm init command

$ npm init

This will insure you have the required package.json file with name and version set.

Step 2: Publish

$ npm publish

If you are not logged in, you will need to run npm login

Thats it!

Step 3: Test your npm package

Double check your package information with $ npm info <package_name>

Alternatively, go to another repo and run $ npm install <package_name>

Congrats! Your code is out in the wild on the npm registry ūüôā

Troubleshooting: Package name already exists

You might run into the issue where someone else has taken the name of your npm package. Note that you can set a different name on npm than your github repo. One option is get super creative with your npm package name and change the “name” key in package.json. Another option is to namespace your package to your username like this:

"name": @theptrk/express 

and then publishing this with the public flag

$ npm publish --access=public

What if I want to publish a new version?

npm will reject your package if you do not bump the version number. Use npm version and choose either major, minor, or patch. This is the example for patch

$ npm version {major, minor, patch}

$ npm publish

Categories
Javascript

Do not use bcrypt-nodejs

“Invalid salt revision”

bcrypt-nodejs is no longer maintained and you might run into this

Use bcryptjs for a more secure actively maintained experience.

Also, check out Django, its great, but if you do, consider adding bcrypt

 

Categories
express

Express Sequelize Heroku Postgres Configuration Success

You are in flow developing on your local database and you decide to upload everything to heroku and share it with the world.

How do you configure your production database?

It’s easier than you think. Let’s assume you have already set up your site.

If you used the sequelize init command, you will have a file db/models/index.js that looks like this

Usually, your sequelize database will initialize with the usual database, username password, etc but in the special case that your config has use_env_variable, sequelize will recognize that an environment variable (usually representing a URI) can be used in place of the usual credentials.

What is your env/config variable?

Find your heroku config variables in the heroku website or by running $ heroku config. Note, config and env variables are used to reference the same settings here.

When you create a database on your heroku account, it will default a new configuration setting called “DATABASE_URL”

You can access this with process.env.DATABASE_URL in any of your node.js code (on production). Your local machine will have different environment variables set.

Step 1: Set use_env_variable

But set it to what? Set it what heroku designates as your database url, DATABASE_URL!

Thats it!

You may need to migrate your database if you aren’t using sync

Step 2: Migrate your database

Simply run the migrate command in the heroku environment with heroku run. This avoids any configuration errors of running from your local environment

$ heroku run ./node_modules/.bin/sequelize db:migrate --debug

Final config

Step 3: Check your database

Run the heroku psql command and run the “list tables” command.

$ heroku psql

$<app_name>::DATABASE=> \dt

Possible Errors

Error: no pg_hba.conf entry for host…, SSL OFF

Add the ssl setting into dialectOptions of your config.json

Error: The server does not support SSL connections

This may be an outdated error. But previously, users who tried to migrate on their local computer would run into this error.

$ NODE_ENV=production DATABASEURL=$(heroku config:get DATABASE_URL) ./node_modules/.bin/sequelize db:migrate

This will not work correctly unless you set up your local computer to support ssl in the migration. You could get a certificate and configure your sequelize config to use that BUT theres an easier way.

ERROR: SequelizeConnectionRefusedError: connect ECONNREFUSED 127.0.0.1:5432

It’s quite possible you forgot to push your code to heroku. Make sure you git push heroku master!!!

Categories
postgresql

Node Sequelize Postgres Tutorial

Why use Sequelize?

Sometimes you want your team to use an ORM. Often you need to run migrations. Sequelize provides ORM features and a much needed migrations library that allows us to create producible and version controlled database schemas.

Setup your project

Step 1: Create an npm project in your desired directory

$ npm init

Step 2: Install the packages

$ npm install --save sequelize sequelize-cli pg pg-hstore

Step 3: Create a new database

You need to have postgres installed on your machine for this. If you do not have postgres you can use brew to install it: $ brew install postgres

Now create a new database called here called “user-demo-db”

$ createdb user-demo-db

Step 4: Initialize your sequelize directories

$ node_modules/.bin/sequelize init

Now what? Using Sequelize

You have two options to create database tables: We can either create our database tables with the psql shell using raw queries or we can use sequelize to manage our database.

When to use “sync” and when to use “migrations”

Using sequelize, there are two options for creating tables: 1. Using sync or 2. Using migrations.

In most tutorials you will see code using sync() or even sync({force: true}). This is completely fine in a test database since this option will completely overwrite your database based on your model files. Note: this means you can destroy data with this option.

Why use migrations?

With migrations, we are incrementally changing the database tables and will retain a record of all these changes in our “migration” files. This record is a valuable record of our changes and will allow us to avoid destroying our data.

Step 5 : Create your first model by generating your first migration files

Here we are creating a new model by generating both the initial model file AND the migration file for a sample model User with some attributes firstName;lastName;email

* Note: we are using the singular “User” and not the plural “Users”. This will be an ORM convention that you will need to get used to.

$ node_modules/.bin/sequelize model:generate --name User --attributes firstName:string,lastName:string,email:string

Look inside your new model file: 

It should export a new “model” using sequelize.define("User", ...)¬†with the attributes that you specified in the command line arguments.

* Note that the default id field is INTEGER and not something cool like UUID, its your code now, you can change this.

Look inside your new migration file:

It should use the  queryInterface function  createTable('User', ...) with attributes that you specified in the command line arguments plus three fields that sequelize will add to every table id, createdAt and updatedAt

* One thing that is key to note is that by default you table name is pluralized

Step 6: Run the migration

Before you run this migration, you may change the migration/model file to edit your attributes.

$ node_modules/.bin/sequelize db:migrate

Sequelize will create a SequelizeMeta table in your database to keep track of which migrations have been run. That also means you can create many other models before running this command and it will run all not-yet-run migrations

Check your migration

After you run your migration you can check your table status with psql shell or pgadmin

$ psql user-demo-db

psql> \d "Users"¬†<- note the “s”; note the double quotes¬†

Get used to this pattern, you will use this a lot.

(Optional) Create an instance of your model – User

Note that we use the singular User instead of the Users from the actual table

node> var models = require('./db/models')

node> models.create.User({

  firstName: "John", lastName: "Doe", email: "jd@gmail.com"})

Step 7: How to create a 1:Many (1:M) relationship

Lets create a model called Task that can only have one User. 1(User):Many(Tasks).

Create your migration files and migrate your database to add the new table

$ node_modules/.bin/sequelize model:generate --name task --attributes body:string,done:boolean

$ node_modules/.bin/sequelize db:migrate

Now we will need to associate the Task to the User in some way.

According to the docs we need to run Task.belongsTo(User)

However if we add this to the db/models/Task.js file in the associate function, our file now fails to load correctly when accessing db/models within the node shell. We can open up our node shell and do this manually.

node> const models = require('./db/models')

node> models.Task.belongsTo(models.User)

What happened?

BelongsTo associations are associations where the foreign key for the one-to-one relation exists on the source model.

– docs

We ran the code¬†<source>.belongsTo(<target>)¬†with having the appropriate “foreign key” on our source model (Our Task model is missing the column UserId). Instead of undoing our migration, this is a perfect time to learn how to do a database migration.

Step 8: Fix our 1:M relationship

This time we only need the migration file, and not the model generated file.

$ node_modules/.bin/sequelize migration:generate --name add_userid_to_task

Adding a foreign key field to a model – Task

We want to create a new column UserId on our Task model/table that represents a foreign key relationship. The docs explain that all we need is a references key with the correct values

Your migration file will look something like this: code

return queryInterface.addColumn(
  SOURCE_TABLE_NAME,  // "Tasks"
  TARGET_FIELD_NAME, // "UserId"
  {
    type: Sequelize.INTEGER,
    reference: {
      model: TARGET_TABLE_NAME, // "Users"
      key: "id"
    }
    onDelete: 'cascade
  }
)

Important Notes:

  • we have to match the type of the target field (“integer” in our case above, “UUID” if you wanted to create an advanced User model)
  • Your source “table” name is likely the plural version of your “model” name. You can get the model name with node> require('../models')[model_name].getTableName()
  • Your target field name should be “title-case” based on sequelize convention, so if you’re targeting id¬†on User, your target field name is UserId

Step 9: Remember to migrate your database!

$ node_modules/.bin/sequelize db:migrate

 

More: 

Code: Sample

Docs: Sequelize Docs

Blog Post: How to configure sequelize with heroku

Blog Post: How to define Sequelize associations using migrations

Categories
Coding Javascript

How does sequelize pluralize?

If you use .sync with sequlize and have a model name like User, your database ends up with a table called Users. More clearly, when you use the sequelize-cli model generator the generated file will show this pluralized table. Here is the code: (link)

What is Utils? 

* Note Sequelize has a directory called Utils AND a file at lib/utils.js.

What’s in¬†lib/util.js?

 

We find the function! This is how sequelize defines utils.pluralize link

Util.pluralize IS inflection.pluralize

This is how its tested 

What is inflection?

Inflection is a port of Ruby on Rails Active Support Inflection classes into JavaScript built by DreamersLab in Taipei. (link)

So how does sequelize/inflection pluralize?

Inflection seems to have rules based on:

Eventually, inflection takes these rules, uses RegExp and applies them to your string. Theres a bunch of rules and at the end theres this

The common rule that is the exhausted else or case default rule that targets the end of the string with $. No rules for that singular term? Add an s

Categories
postgresql

Postgres timestamp with timezone – “timestamptz”

Postgres can store your “timestamp with timezone” or “timestamp without timezone”.
If you don’t specify either, it will default to “timestamp without timezone”

Which one should you use? TLDR: “timestamps with time zones”

Whats the problem living life without timezones?

Say you have two users in two different timezones – one in California and one in France. Imagine you may need to know which one acted “first”, maybe in an auction or draft scenario where the whoever acts first wins.

Without specifying timezone, your database will save the plain timestamp of each user, say “midnight” and “midnight”. How will you know which one acted first?

You could save the original timezone from the user and perform the necessary algebra when needed.

Solution – Use “timestamp with time zone” otherwise known as “timestamptz”¬†

For¬†timestamp with time zone, the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time,¬†GMT). An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone. If no time zone is stated in the input string, then it is assumed to be in the time zone indicated by the system’s¬†TimeZone parameter, and is converted to UTC using the offset for the¬†timezone¬†zone.

Postgres docs

This bears repeating: 

“For¬†timestamp with time zone, the internally stored value is always in UTC.”

A proper name for this might be timestamp saved as UTC by default. By saving everything in the “same” timezone, we know the absolute time of the timestamps.

This brings up the main UX concern: What do users see?

Your users want to read data from the database using their preferred timezone.

(If they added a blog post at 3:00pm PST, they want to see the timestamp as 3:00pm not 6:00PM EST )

Dates are saved as UTC so you will eventually need to convert the time

Converting on the server:

Best practice is to save the users’ preferred timezone as a name (e.g. America/Los_Angeles). This way your query or ORM can convert the date according to user preference.

Remember, timezones offsets are affected by political actions. A timezones actual hour offset can change depending on whether the timezone recognizes daylight savings time (Phoenix does not) or just simply when the political “owners” of the timezone decide to CHANGE the offset. Read The Long, Painful History of Time¬†for more info.

Converting on the browser:

Many browsers have default timezones that can be used by passing in your date to new Date. You can also, simply use moment.js to parse the dates on the client to show the correctly formatted date string for your purpose.

Do not convert at all! Use “Time from now”:

Ever notice how websites have time indicators like “just now”, “30 minutes ago” and “22 hours ago”? These avoid dealing with timezones altogether. Way easier! moment.js¬†has this API that will simply accept your date and convert it to time from now style.

moment([2007, 0, 29]).fromNow(); // 4 years ago

What about user input?

User input should always be converted to UTC (with timestampz this will be handled and stored in UTC by default). Many functions already return UTC by default such as  new Date() in Browser JavaScript and node.

Resources:

PostgreSQL Data Types: Date, Timestamp, and Time Zones

Detecting the time zone from the browser: 

Categories
CAShapeLayer Core Animation iOS

Using CAShapeLayer to draw a circle

UIViews are like Ogres, which are like onions – they have layers.

Source: Documentation

More accurately, UIView has a single layer property that can have infinite sublayers.

UIView’s have layers

Lets draw a circle.

First create a UIView and a CAShapeLayer:

let myView = UIView()

let myLayer = CAShapeLayer()

Layers have a path

UIBezierPath makes drawing shapes extremely smooth, lets say in the shape of a circle:

let circlePath = UIBezierPath(
  arcCenter: CGPoint(x: 100.0, y: 100.0),
  radius: 100,
  startAngle: 0 * CGFloat.pi / 180,
  endAngle: 360 * CGFloat.pi / 180,
  clockwise: true)

Great! Now we can add CAShapeLayer as a CGPath and spruce up our fill and stroke colors

myLayer.path = circlePath.cgPath
myLayer.strokeColor = UIColor.blue.cgColor
myLayer.fillColor = UIColor.yellow.cgColor

Last step! Add this layer to your UIView

myView.layer.addSublayer(myLayer)

Layers have attributes

strokeColor,fillColor, opacity, lineWidth and more!

Bonus: Layers can animate attributes

// create the animation
let opacityAnimation = CABasicAnimation(
  keyPath: #keyPath(CALayer.opacity))
opacityAnimation.fromValue = 0
opacityAnimation.toValue = 1
opacityAnimation.duration = 5.0

// set the final value; add the animation
myLayer.opacity = 1
myLayer.add(opacityAnimation, forKey: #keyPath(CALayer.opacity))

Categories
iOS

iOS Application Lifecycle – UIKit basics

iOS applications are all about cycles

This is because the iOS applications are¬†richly interactive¬†when it comes to user input¬†and much of your programming with UIKit will be delegate oriented. Knowing the many different “cycles” of the device and application will be illuminating for your development.

States of the UIKit App Cycle

* These are the execution states of a UIKit app from the Apple docs. But why so many arrows? Below is the simplified flow charts

User Action: Your app has not been launched

Your application starts off Current State: Not Running

User Action: Your app is launched

Delegate method called: application(_:didFinishLaunchingWithOptions:)

New state: Inactive – your application is briefly here as it prepares a successful launch

New state: Active¬†– your application is now the “foreground app”.

Many apps will place a majority of the app setup logic in this function including setting up a programmatic view controller setup (bypassing the default storyboard)

Delegate method called: applicationDidBecomeActive

User Action: User goes to home screen or opens another app

 

Current state: Active

Delegate method called: applicationWillResignActive

New state: Inactive – your application is briefly here

New state: Background Рyour app is available in the app picker screen on home button double tap

Delegate method called: applicationDidEnterBackground*

* If your app does not support background execution “applicationWillTerminate” is called

** If your iOS device is low on memory, it may suspend and even terminate your app back to the state “Not Running”

User Action: User reopens a background app

Current state: Background

Delegate method called: applicationWillEnterForeground

New state: Active

Delegate method called: applicationDidBecomeActive

 

TLDR: Your basic UIKit flow moves from Active <-> Background

These are only the basic lifecycle events for your UIKit app, there are MANY different scenarios that can change the state of your app – the device can span a low battery warning and show the power saving alert, a phone call may occur, users can click and hold notifications, the device can run out of batteries.

Categories
iOS project setup

iOS without storyboard

Why?

Programmatically/Code or NIB based layouts are a much better fit for projects that use version control (see merge conflicts) and make it much easier to reuse views. If you are deciding not to use storyboards, you will need to manually set your application window to your desired UIWindow

Prerequisites:

РDelete Main Interface from Deployment Info Settings

РDelete the Main.storyboard file

How to: set up a iOS project without storyboard

Step 1: Create a UIWindow with the frame using the bounds of the UIScreen

UIWindow(frame: UIScreen.main.bounds)

Step 2: Assign this to the AppDelegate window property

window = ...

Step 3: Make the window “key” and “visible”¬†

window?.makeKeyAndVisible

Step 4: Set the window `rootViewController` to the VC of your choice

window?.rootViewController = ...

Code: link

Categories
autolayout iOS

Forgetting to set translatesAutoresizingMaskIntoConstraints to false

UIKit on iOS is great! There are tons of tools and often this can supercharge your productivity for getting a prototype out into the world.

Additionally, working with AutoLayout programmatically can be great if you avoid these rookie mistakes.

Rookie Mistake 1:

It hurts when you spend hours dealing with the rookie mistake of forgetting to set translatesAutoresizingMaskIntoConstraints to false on the view when setting constraints.

view.translatesAutoresizingMaskIntoConstraints = false

Rookie Mistake 2: 

Remember that you also have to also set your NSLayoutConstraint to true

Example:

yourView.centerXAnchor.constraint(equalTo:
  view.centerXAnchor).isActive = true

Solution:

This function allows you to program with wild abandon! If you use this function to set your constraints you never need to remember those pesky settings.

func setLayoutConstraints(
    view: UIView,
    constraints: [NSLayoutConstraint]) {
        view.translatesAutoresizingMaskIntoConstraints = false
        constraints.forEach({constraint in
            constraint.isActive = true
        })
}

Code found here, and more

*Update: Apple created a convenience method on NSLayoutConstraint called .activate that will set the isActive property to true. The new code would look like this:

func setLayoutConstraints(
    view: UIView,
    constraints: [NSLayoutConstraint]) {
        view.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate(constraints)
}