Year #3, Week #12 đ» đž
New stuff we learned this week: đ€
Tidbits about pm2
- start up a daemon with the
start
subcommand:pm2 start <some-executable>
- pm2 doesnât like accepting a command like
npm run foo
, so you can work around this by making a simple shell script (ending with.sh
) that is executable thanks to a hashbang. - naming a pm2 process is helpful, by adding
--name 'foobar'
. This allows you to refer to it by name, and delete it by name, likepm2 delete foobar
. pm2 list
lists your pm2 processespm2 show <name>
give you more infopm2 logs <name>
lets you see logging produced- beware of uptime for detecting crashes.
Jest hates import.meta.env
- to work around the fact that Jest canât handle
import.meta.env
, make a file responsible for handling env, and have it export functions that we can mock for jest:
// env.ts
export function getApiUrl(): string {
if (import.meta.env.MODE === `production`) {
return `http://live-api.com`;
} else {
return `http://localhost:7070`;
}
}
Then, in any jest file that calls into a module that loads that file, youâll need to provide a mock:
// __tests__/some.spec.ts
jest.mock(`../../env`, () => ({ getApiUrl: () => `/` }));
Homework Plan
- 1 day Monkey Assignment #19 đ
- 1 day review all flashcards in your app.
- 1 day touch typing practice
- 1 day watch CS50
CS50 Lecture #3 segment,
from
37:21
to1:01:56
- 1 day Flashcards API pm2 assignment
- 1 day Flashcards WebApp Redux-Heavy assignment
- 3 days Execute Program homework
Monkey #19
- Address all feedback from prior MRâs, and merge.
- Create a new branch.
- Double-check that you did the first two steps.
- Slowly and carefully read the first 3 sections of chapter 3:
3.1 - Giving Meaning to Symbols
,3.2 - Strategies of Evaluation
, and3.3 - A Tree-Walking Interpreter
. Try to re-read and slowly think, scratching your beard until you understand as much as possible of what heâs saying. - Next, start at section 3.4 â Representing Objects. Work through that section.
- Then, go on, and start section 3.5 â Evaluating Expressions. Work up through the sub-section labeled Completing the REPL, stopping at the end of that section, where it says Boolean Literals. This would be page 114 of the PDF, or page 145 of the printed book.
- Commit your work.
- As always, make sure to try to do as much as you can without the videos, but always also watch the videos and update your code to (mostly) match.
- Video link
- Submit a MR, Review your diffs and fixup!!, then slack the MR url
Flashcards API pm2 Assignment
- Make sure youâve addressed any feedback from your last API MR, and merge.
- get back on master, pull from origin master and create a new branch.
- use the knowledge you gained in class, and the hints from âNew Stuffâ above to
make an npm âserveâ script setup that daemonizes your API application with
pm2
. Hints/requirements:- make sure you give your pm2 process a
name
- youâll need to make a bash script for
pm2
to execute, I recommend calling it./serve.sh
. It should invokets-node
correctly, setting theNODE_ENV
env var toproduction
. It will need a hashbang. - your
"serve"
script should also terminate the process if it exists. You can use the commandpm2 delete <name>
to do this. Itâs OK if deleting the process errors if it doesnât exist. If you donât want to see the error output, you can redirect stdout and stderr to dev/null with&> /dev/null
.
- make sure you give your pm2 process a
- once you have it working, test it out. You should be able to access a url like
http://api-tabitha.howtocomputer.link/cards
and see the json output. If itâs not working, usepm2 list
andpm2 logs
to investigate. Youâll need to make sure that your server is listening on the right port, your production api port (see~/.user_env
). - experiment a little with starting, stopping, and viewing logs for you process
by using some of the
pm2
sub-commands listed in the ânew stuffâ, and that we went over in class. - when youâve got everything working, commit your work, and push up a MR. Slack
the MR url, and also, slack the production url of your
/cards
route so I can test it in my browser.
Flashcards WebApp Redux-Heavy Assignment
- Make sure youâve completed the API pm2 assignment first, before doing this assignment.
- Make sure youâve addressed any feedback and merged your MR from the last flashcards webapp assignment.
- get back on master, pull from origin master and create a new branch.
- take a few minutes and carefully read the typescript quickstart tutorial from the redux-toolkit docs site.
- next, youâll be following along with a video I made of me converting my
flashcards webapp from
@htc-class/reduxlite
toreact-redux
. But your app will look somewhat different, you wonât be able to 100% copy what Iâm doing. Youâll need to understand what Iâm doing, and apply it to your files and file structure. So work slowly, pausing the video each time I do something significant and implementing it on your app. Video link is here. - once youâve got your app working again with real redux, commit your work.
- next watch and copy this short video where I show how to add logging to your redux app (which reduxlite did for you).
- commit your work again.
- next, make sure you included the
Thunk
type shown in my video, which is this:
type Thunk = (dispatch: Dispatch, getState: () => State): unknown
- use your knowledge of Thunks to make it so your flashcards app fetches its
cards from your API. To do this you will need to:
- create and export a thunk-creator function from your
rootSlice.ts
file. It should be a function that takes no arguments, and returns a thunk, that is, a function that returns a function. I would recommend calling itloadCards
. - in the thunk returned by your thunk-creator, youâll fetch the cards from
your API, using
fetch()
. You can refer to your old flashcards app to jog your mind how to do that. Start by hardcoding the url to your dev flashcards api. (Note: youâll need to have it running for this to work). - the thunk function you return should be
async
so you canawait
on the fetch and json-decoding. - once you have an array of cards from your API, youâll need to dispatch an
action that sends the cards back into your system. This means youâll need
another action-creator defined within your call to
createSlice
. It will be a little more powerful though, it will take a payload. Look at thecounterSlice.ts
example code here, specifically theincrementByAmount
action creator, for an example of how to do an action that takes a payload. - now, delete the hard-coded cards you currently have in your state, if you havenât done that yet.
- then, use your new
loadCards()
thunk creator in the component where you need to fetch your cards, which should be in some container component in your app. Hint: youâll need to useuseEffect()
and pass the right depedency argument so that it runs only once. Hint #2:loadCards()
is a thunk-creator, that is to say, an action-creator, so it needs to be invoked and the result passed todispatch
for it to do anything. - I would recommending adding a guard to your container component for when you
have 0 cards (that is, before the load request finishes), and bail early
with a loading message instead of rendering the presentational component.
But the early return should be after the
useEffect()
call. - If you have trouble, check the console for errors, be sure to log out what your API returns, and verify that it matches what you want on the client (object keys and types, etc.).
- create and export a thunk-creator function from your
- once youâve got that basically working, I want you to remove the hard-coded
API url. Instead, create a file called
src/env.ts
and have it export a function calledgetApiUrl()
which tests the current environment usingimport.meta.env
. See the âNew Stuffâ above for an example. It should return your dev URL unless theMODE
isproduction
in which case it should return your production url, which is something likehttp://api-kiah.howtocomputer.link
. - once youâve got all that working, commit your work again.
- next, get your tests passing again. youâll have to fix a handful of things:
- import your reducer from the new spot
- the real redux reducers return a new state, so youâll have to capture
that into a variable and assert on the new state, instead of asserting that
the state was mutated as formerly, like
const nextState = reducer(state, action);
- youâll have to mock the
env.ts
file, as described in the âNew Stuffâ above to get Jest to not have a cow aboutimport.meta.env
- when your tests are all green commit your work again.
- finally, deploy your site to netlify, using what you learned last week, with
the below hints: requirements:
- Youâll need to use an environment variable to make sure that you end up with the right API url getting used.
- you must create a
netlify.toml
file to specify where the dir is for publishing. - Create two new npm scripts:
deploy:staging
anddeploy:production
that takes care of first running a âbuildâ command of some sort to produce newly built files, and then invokingnetlify
with the right arguments (for a draft url vs production). - since you already got your API daemonized with pm2, your production deploy should talk to your pm2 API url, and it should work â meaning, you should be able to view your site on netlify and have it be pulling real card data from your production api.
- make another commit covering your deployment scripts and netlify.toml files.
- push up a MR, review your diffs, clean up anything you see, then slack me the MR url, and your new shiny netlify production url which is talking to your production API.