home scroll deno

deno learning blog January 2023

Jan 1, 2023

Failed attempt to install LAMP server, because of mySQL problems
deno_learning_failed_attempts.html

Jan 2, 2023

Install LAMP server

Create new Linode.
Login via ssh

sudo apt update
sudo apt upgrade
sudo reboot
Add new admin user.
adduser sammy
sudo usermod -aG sudo sammy

Install mySQL server

instructions at
https://www.digitalocean.com/community/tutorials/how-to-install-mysql-on-ubuntu-22-04

sudo apt install mysql-server
Make sure mySQL server is running:
sudo systemctl status mysql.service
Prevent error that would occur when running secure install:
sudo mysql
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
This command will show whether the previous command was successful:
SELECT user,plugin,host FROM mysql.user;
Output:
mysql> SELECT user,plugin,host FROM mysql.user;
+------------------+-----------------------+-----------+
| user | plugin | host |
+------------------+-----------------------+-----------+
| debian-sys-maint | caching_sha2_password | localhost |
| mysql.infoschema | caching_sha2_password | localhost |
| mysql.session | caching_sha2_password | localhost |
| mysql.sys | caching_sha2_password | localhost |
| phpmyadmin | caching_sha2_password | localhost |
| root | mysql_native_password | localhost |
| sammy | caching_sha2_password | localhost |
+------------------+-----------------------+-----------+
7 rows in set (0.00 sec)
exit
Now we can run the secure installation script:
sudo mysql_secure_installation

will ask for password, is now 'password'

Output:
Securing the MySQL server deployment.

Enter password for user root:
The 'validate_password' component is installed on the server.
The subsequent steps will run with the existing configuration
of the component.
Using existing password for root.

Estimated strength of the password: 50
Change the password for root ? ((Press y|Y for Yes, any other key for No) : n

... skipping.
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.

Remove anonymous users? (Press y|Y for Yes, any other key for No) : n

... skipping.


Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : n

... skipping.
By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.


Remove test database and access to it? (Press y|Y for Yes, any other key for No) : n

... skipping.
Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
Success.

All done!

Add another user
mysql -u root -p
CREATE USER 'sammy'@'localhost' IDENTIFIED BY 'password';
GRANT CREATE, ALTER, DROP, INSERT, UPDATE, INDEX, DELETE, SELECT, REFERENCES, RELOAD on *.* TO 'sammy'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
exit

Test new user
mysql -u sammy -p
list databases:
SHOW DATABASES;
Output:
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.01 sec)
Create new database
CREATE DATABASE db_name;
SHOW DATABASES;
Output:
SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| db_name |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
The newly created database is listed.
Change the password
mysql -u sammy -p
ALTER USER 'sammy'@'localhost' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;

Install Apache web server

Instructions at
https://www.digitalocean.com/community/tutorials/how-to-install-the-apache-web-server-on-ubuntu-22-04

sudo apt install apache2
Open browser at
http://45.79.28.148/
Apache2 Default Page message comes up - it works.
I am not changing the ufw firewall for now because my deno servers will use port 8000.

Install PHP

Instructions at
https://www.digitalocean.com/community/tutorials/how-to-install-linux-apache-mysql-php-lamp-stack-on-ubuntu-22-04

sudo apt install php libapache2-mod-php php-mysql
Test the installation:
php -v

Install phpmyadmin

Instructions at
https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-phpmyadmin-on-ubuntu-22-04

sudo apt install phpmyadmin php-mbstring php-zip php-gd php-json php-curl
Make sure to select Apache!
Test phpmyadmin
http://45.79.28.148/phpmyadmin

Run deno app on linode server

http://45.79.28.148:8000

deno and mySQL

deno module:
https://deno.land/x/mysql@v2.10.2

Example 1:

https://codeforgeek.com/deno-and-mysql-connection-tutorial/
Setup:
  1. User sammy has no password
  2. sammy creates a database named "sammydb"
  3. sammy creates a table named table1
  4. deno code is run on the same server as the mysql database
Configuration:
hostname: "127.0.0.1",
username: "sammy",
db: "sammydb",
poolSize: 3, // connection limit
password: "",
const users = await client.query(`select * from table1`);
Output:
~/github/learn/deno/deno_mysql/deno_mysql_01$ deno run --allow-net deno_mysql_01_local.ts
INFO connecting 127.0.0.1:3306
INFO connected to 127.0.0.1:3306
[ { col1: 1, col2: 3, col3: 8, col4: 6 }, { col1: 1, col2: 3, col3: 8, col4: 6 } ]
If I run the code from another location and change the hostname
hostname: "45.79.28.148",
I get
deno run --allow-net deno_mysql_01.ts
INFO connecting 45.79.28.148:3306
error: Uncaught (in promise) ConnectionRefused: Connection refused (os error 111)

More Examples:

https://www.freecodecamp.org/news/how-to-use-mysql-in-deno-oak/

https://github.com/adeelibr/deno-playground/blob/master/guidelines/setting-up-mysql-mac-os-catalina.md

Jan 3, 2023

deno and databases

Database comparison:
https://www.digitalocean.com/community/tutorials/sqlite-vs-mysql-vs-postgresql-a-comparison-of-relational-database-management-systems
supported databases
mySQL
https://deno.land/x/mysql@v2.11.0
PostgreSQL
https://deno.land/x/postgres@v0.17.0
SQLite
https://deno.land/x/sqlite@v3.7.0
Comments
The blog at https://github.com/adeelibr/deno-playground/blob/master/guidelines/setting-up-mysql-mac-os-catalina.md
from Jun 4, 2020 says:
"current MySQL lib of Deno doesn't connect to a username with a password."
However, it seems to work now in January 2023.

Note: When I create a new user and try to run the program with a password, it does not work.
However, it works after I log the new user into mySQL in the terminal.
I have verified this behavior on two different computers.


Examples
https://blog.logrocket.com/how-to-create-rest-api-deno-postgres/#database-repository-deno-postgres

Jan 4, 2023

deno + fresh + mySQL

Task: write a note writing, saving, and viewing app.
Create the empty new deno with Fresh project:
deno run -A -r https://fresh.deno.dev my-project

Jan 5, 2023

The web site for Fresh has links to examples. https://fresh.deno.dev/showcase
PPaste has a text area and a button.

Jan 7, 2023

Understanding the showcase example Tasks

https://fresh.deno.dev/showcase
The file routes/index.tsx contains a function Home() which returns the HTML code for the client.
Inside the returned data is an element named
<Todo />
which is declared by the statement
import Todo from "../islands/Todo.tsx";
The Todo element contains a function named Todo().
This function starts with
const [tasks, setTasks] = useState<ITask[]>([]);
which uses the Preact functionality for dealing with states.*
The return value is an array containing two variables:
The first variable is a state, and the second is a function that can be called to update the state using hooks.
The first parameter is the initial value, in this case an empty array.
The array will contain members of the Task type.
The return of the function contains
  • a form
  • an element of the type Tasks which is declared in the import.
The form contains
  • the onSubmit function
  • a textbox for entering a new task
  • a button to trigger the submit for the form
The Tasks element returns a div tag
within which a function is called that returns an element of type Task.
The Task element returns a div tag
which contains
  • a paragraph with the text of the todo which is retrieved from the desc parameter of the props passed
  • a button to remove the task
tasks: ITask[]; removeTask:
* More information on hooks:
https://preactjs.com/tutorial/04-state/
https://www.w3schools.com/react/react_usestate.asp

Jan 9, 2023

What are the parameters and functions that can be called on a UI element?
For example, right-clicking on the word input and choosing opens the file jsx.d.ts
where input is part of an interface named
"interface IntrinsicElements"
input: HTMLAttributes<HTMLInputElement> & { defaultValue?: string };
and right-clicking on textarea takes us to
textarea: HTMLAttributes<HTMLTextAreaElement>;
More information at
https://reactjs.org/docs/forms.html

Jan 11, 2023

Running the app on a local computer works.
Running the same app on a Linode server leades to an error when trying to add a note:
hello World
However, when calling the function on the command line, it works:
hello World
Possible explanation: the Linode server does not run in secure context,
(no https:// but http://)
https://github.com/google/timesketch/issues/2410
https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID

Jan 14, 2023

Replaced the function crypto.randomUUID() with a function that uses Math.random().
Now it runs on a non-secure server that uses http://

Jan 15, 2023

Try to run the mySQL example - fails with error message:

INFO connecting 127.0.0.1:3306 INFO close connection
error: Uncaught (in promise) Error: Access denied for user 'atmelino'@'localhost' (using password: YES)
throw new Error(error.message);
Now, when I open a terminal and log into mySQL with this user
mysql -u atmelino -p
and run the program again, it works - multiple times.

Reboot the computer.
Is mySQL running?
sudo systemctl status mysql.service
yes:
mysql.service - MySQL Community Server
Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2023-01-15 20:37:16 CST; 1min 57s ago
Process: 899 ExecStartPre=/usr/share/mysql/mysql-systemd-start pre (code=exited, status=0/SUCCESS)
Main PID: 989 (mysqld)
Status: "Server is operational"
Tasks: 39 (limit: 9058)
Memory: 425.7M
CPU: 1.333s
CGroup: /system.slice/mysql.service
└─989 /usr/sbin/mysqld
login to mySQL as different user - still get Access denied error
login to mySQL as the same user as the deno program - deno program works!

Jan 16, 2023

Adding the code for connecting the mySQL database to the deno Frash code
leads to an error in the browser:
wasm.js:214 Uncaught RangeError: WebAssembly.
Compile is disallowed on the main thread, if the buffer size is larger than 4KB.
Use WebAssembly.compile, or compile on a worker thread.
at wasm.js:214:20
Possible solutions
https://github.com/dyedgreen/deno-sqlite/issues/105

Jan 18, 2023

PostgreSQL

https://deno.land/x/postgres@v0.17.0
https://deno-postgres.com/#/

Install Postgre on Ubuntu 22.04

Installs the latest version:
https://www.digitalocean.com/community/tutorials/how-to-install-postgresql-on-ubuntu-22-04-quickstart
sudo apt install postgresql postgresql-contrib
Check status:
systemctl status postgresql


This installs an older version but Also explains how to allow access from connections other than localhost:
Configure remote Connection
https://computingforgeeks.com/how-to-install-postgresql-13-on-ubuntu/

Using Postgres

The installation automatically creates a user named postgres.
Login as default user postgres

sudo -i -u postgres
On command line, to change the password of the default user:
psql -c "alter user postgres with password 'StrongAdminP@ssw0rd'"
On command line, access the Postgres prompt:
psql
The terminal will now show the name of the user who entered the Postgre prompt:
postgres=#
Exit the Postgre prompt:
\q
Create a new database:
On the postgres user's command prompt:
createdb sammy
Show databases:
\l
To list the tables in a database, first connect to the database:
\c sammy
Then
\dt
get specific information about a table named todos:
\d+ todos
to show the contents of a table named todos:
SELECT * FROM todos;
Note: The query has to be upper-case and have the semi-colon at the end.

Create a new user:
sudo -u postgres createuser --interactive
For Example:
Enter name of role to add: sammy
Shall the new role be a superuser? (y/n) y
To be able to use Postgre with this new user, need to make admin
sudo adduser sammy

Install pgadmin4 (phpadmin - like interface)

with nginx:
https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-pgadmin-4-in-server-mode-on-ubuntu-22-04
with Apache:
https://computingforgeeks.com/how-to-install-pgadmin-4-on-ubuntu/

Connect to the admin tool:
http://127.0.0.1/pgadmin4

Postgre example 1

Example on deno land page:
https://deno.land/x/postgres@v0.17.0
In first example:
changed user to postgre
added password
using pgadmin4:
created user sammy with database sammy as described in computingforgeeks page.
added columns id, name (lowercase) as described in
https://www.pgadmin.org/docs/pgadmin4/development/column_dialog.html
inserted rows as described in
https://stackoverflow.com/questions/22755230/how-to-insert-a-row-in-postgresql-pgadmin/47230112
run example - works

Jan 19, 2023

Postgre example 2

https://deno.com/deploy/docs/tutorial-postgres
The place for connection pooling is not under database, it is under settings -> database
The password in the connection string needs to be added without the [] characters.
I can connect to the database from the command line

psql -h db.lwbjwhxdyxafkxjdldmn.supabase.co -p 5432 -d postgres -U postgres
and it will show the todos table that was created with the playground program.

Jan 20, 2023

Postgre example 2 - ctd.

Running the example locally requires either using the environment variable system
https://stackoverflow.com/questions/61873926/where-does-deno-env-got-its-data-from
change code to
import { config } from "https://deno.land/x/dotenv/mod.ts";
const databaseUrl = config().DATABASE_URL;
and setting the environment variable DATABASE_URL to the according value
or simply set the string
const databaseUrl = "postgres://postgres:deno1pass2word3@db.lwbjwhxdyxafkxjdldmn.supabase.co:6543/postgres";
With the server running locally, we can now use the API using cURL:
curl -X GET http://localhost:8000/todos
curl -X POST -d '"Buy cereal"' http://localhost:8000/todos
Run deno app on remote server
ssh into remote server
run the deno app
On local terminal:
curl -X GET http://45.79.28.148:8000/todos
curl -X POST -d '"Buy light bulbs"' http://45.79.28.148:8000/todos
works:
  • run curl command in a local terminal
  • deno app runs on a remote server
  • database runs on supabase
Use local Postgre database
  • replace pool.connect() with client.connect()
  • replace connection.queryObject with client.queryArray
We can now
  • run curl command in a local terminal
  • deno app runs on local computer
  • database runs on local compter

Jan 21, 2023

Postgre database and deno app on remote server
Install Postgre as described above.
copy the local deno app to remote server and run it
works:
  • run curl command in a local terminal
  • deno app runs on remote computer
  • database runs on remote computer

Jan 22, 2023

Deno Postgres with Deno Fresh

Both the postgre deno app and the deno Fresh todo app use port 8000.
Solution: change the deno Fresh todo app to use port 7000.
in main.ts:

await start(manifest, { port: 7000, plugins: [twindPlugin(twindConfig)] });
Both deno apps can now run in parallel.

HTTP request in deno
https://examples.deno.land/http-requests

Jan 23, 2023

running the two deno apps parallel leads to a problem with CORS:
browser gives error message
Access to fetch at 'http://localhost:8000/todos' from origin 'http://localhost:7000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
https://stackoverflow.com/questions/62301531/deno-oak-disable-cors

create an oak server

https://www.robinwieruch.de/deno-oak-rest-api/
Write the server in oak and disable CORS.
Running the deno Fresh app on port 7000 and the database connection server on port 8000 - works!

Jan 24, 2023

Deployed on remote server, get error:
NoteKeeper.tsx:49 GET http://localhost:8000/todos net::ERR_BLOCKED_BY_CLIENT
"This usually happens if you have ad blocker on. "
https://groups.google.com/g/gwdbeta/c/ti-Q8_Hzu7A
Turned ad blocker off, now get error
NoteKeeper.tsx:49 GET http://localhost:8000/todos net::ERR_CONNECTION_REFUSED
Solution:
Chrome does not like localhost as host
so change in Notekeeper.tsx to
const req = new Request("http://45.79.28.148:8000/todos", {
Links to potential solution:
https://www.ionos.com/digitalguide/hosting/technical-matters/err-connection-refused/
https://www.digitalocean.com/community/questions/get-http-localhost-5000-user-net-err_connection_refused-when-running-application
https://github.com/facebook/create-react-app/issues/2844 https://phoenixnap.com/kb/localhost-refused-to-connect https://phoenixnap.com/kb/127-0-0-1-localhost

Jan 25, 2023

web based systemd manager: cockpit
https://cockpit-project.org/running
Get public IP address in code:
https://morioh.com/p/2c69e96e8be1
Disadvantage: requires Internet connection to retrieve IP address from
https://api.ipify.org

Jan 30, 2023

Creating a custom component in Fresh

The name of the component must start with an uppercase letter, otherwise you will get error
Property does not exist on type 'JSX.IntrinsicElements
https://stackoverflow.com/questions/37414304/typescript-complains-property-does-not-exist-on-type-jsx-intrinsicelements-whe

Follow Me

discord