Saturday, 8 July 2023

Guide to install Apache2, Php 8.1, MySql 5.6, Mssql driver

1. Install Apache2


Let’s begin by updating the local package index to reflect the latest upstream changes:
sudo apt update
Then, install the apache2 package:
sudo apt install apache2
Check with the systemd init system to make sure the service is running by typing:
sudo systemctl status apache2
When you have your server’s IP address, enter it into your browser’s address bar:
http://your_server_ip/
 


* Errors can happen:

-  Server not open port (manual with ufw)

-  Server not open port (on control pannel)  

2. Setup Virtual Hosts for project


Create the Directory Structure
sudo mkdir -p /var/www/example.com/public
Grant Permissions
Now we have the directory structure for our files, but they are owned by our root user. If we want our regular user to be able to modify files in our web directories, we can change the ownership by doing this:
sudo chown -R $USER:$USER /var/www/example.com/public
We should also modify our permissions to ensure that read access is permitted to the general web directory and all of the files and folders it contains so that pages can be served correctly:
sudo chmod -R 755 /var/www
Create file index.html
nano /var/www/example.com/public/index.html
<html>
<head>
<title>Welcome to example.com!</title>
</head>
<body>
<h1>Success! The example.com virtual host is working!</h1>
</body>
</html>
Create New Virtual Host Files
Start by copying the file for the first domain:
sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/example.com.conf
Open the new file in your editor with root privileges:
sudo nano /etc/apache2/sites-available/example.com.conf
When complete, our virtual host file should look like this:
/etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>
ServerAdmin admin@example.com
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Enable the New Virtual Host Files
sudo a2ensite example.com.conf
Next, disable the default site defined in 000-default.conf:
sudo a2dissite 000-default.conf
sudo a2ensite ec-cube-dev.cdb-lab1.com.conf
enter ip into your browser’s address bar:
http://your_server_ip/
 

3. Install php 8.1

Run the following commands to update your list of available packages, then then install PHP 8.1:
sudo apt update
sudo apt install --no-install-recommends php8.1
Check your PHP version information with the following command:
php -v
Install package needed for php 8.1
sudo apt install php8.1-{ctype,pdo,tokenizer,cli,gd,curl,mysql,ldap,zip,fileinfo,fpm,xml,mbstring,exif,pspell,imagick,bcmath}
install the Apache module for PHP 8.1 for apache2 using php8.1
sudo apt install libapache2-mod-php8.1
Install sqlsrv driver for php 8.1 to connect mssql
sudo apt install php8.1-dev
sudo update-alternatives --set php /usr/bin/php8.1
sudo update-alternatives --set php-config /usr/bin/php-config8.1
sudo update-alternatives --set phpize /usr/bin/phpize8.1
sudo pecl install -f sqlsrv
sudo pecl install -f pdo_sqlsrv
sudo phpenmod -v 8.1 sqlsrv pdo_sqlsrv
sudo service apache2 restart
 

4. Install Mysql Server 5.6

Server: <IP server>

User: root

Password: <password> 

 
Download version 5.6.46 from MySQL site
wget https://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
Add mysql user group
sudo groupadd mysql
Add mysql (not the current user) to mysql user group
sudo useradd -g mysql mysql
Extract it
sudo tar -xvf mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
Move it to /usr/local
sudo mv mysql-5.6.46-linux-glibc2.12-x86_64 /usr/local/
Create mysql folder in /usr/local by moving the untarred folder
cd /usr/local
sudo mv mysql-5.6.46-linux-glibc2.12-x86_64 mysql
set MySql directory owner and user group
cd mysql
sudo chown -R mysql:mysql *
Install the required lib package
sudo apt-get install libaio1 libncurses5
Execute mysql installation script
sudo scripts/mysql_install_db --user=mysql
Set mysql directory owner from outside the mysql directory
sudo chown -R root .
Set data directory owner from inside mysql directory
sudo chown -R mysql data
Copy the mysql configuration file
sudo cp support-files/my-default.cnf /etc/my.cnf
Start mysql
sudo bin/mysqld_safe --user=mysql & sudo cp support-files/mysql.server /etc/init.d/mysql.server
Set root user password
sudo bin/mysqladmin -u root password '[your new password]'
Add mysql path to the system
sudo ln -s /usr/local/mysql/bin/mysql /usr/local/bin/mysql
Start mysql server
sudo /etc/init.d/mysql.server start
Stop mysql server
sudo /etc/init.d/mysql.server stop
Check status of mysql
sudo /etc/init.d/mysql.server status
Now login using below command, start mysql server if it's not running already
mysql -u root -p

Create new User, DB for Mysql 

// handle with root user 
mysql -u root -p
mysql root {$password}
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY {$password};
// add new user, db
CREATE USER '{$user_name}'@'localhost' IDENTIFIED BY {$password};  
ALTER USER '{$user_name}'@'localhost' IDENTIFIED BY {$new_password};
CREATE DATABASE IF NOT EXISTS '{$db_name}';
GRANT ALL ON {$db_name}.* TO '{$user_name}'@'localhost';
FLUSH PRIVILEGES  

Thank you


Saturday, 17 June 2023

Learning CakePhp3

013: add using job

012: add using email

011: add using HelloShell 

010: add using relation, baseService

009: add check auth in view 

007: add using element in view

006: add using beforeRender 

005: add DemoMiddleware

004: add register, login, logout for user 

003: add CRUD for users

002: add CRUD for products 

001: add migrate products

first commit 

Adonis web using Inertia

- Install Adonisjs Web

yarn create adonis-ts-app hello-world
 
❯ Select the project structure · web
❯ Enter the project name · hello-world
❯ Setup eslint? (y/N) · false
❯ Configure webpack encore for compiling frontend assets? (y/N) · true

- Install inertia 

yarn add  @eidellev/inertia-adonisjs
node ace configure @eidellev/inertia-adonisjs
❯ Enter the `.edge` view file you would like to use as your root template · app
❯ Would you like to use SSR? (y/N) · false
❯ Which client-side adapter would you like to set up? · @inertiajs/react
[ wait ]  Installing dependencies: @inertiajs/react, react, react-dom, @types/react, @types/react-dom ..

-  Register Inertia middleware

// start/kernel.ts
Server.middleware.register([
() => import('@ioc:Adonis/Core/BodyParser'),
() => import('@ioc:EidelLev/Inertia/Middleware'),
]); 

- Configure Webpack-Encore for React in Typescript: By default Webpack Encore (AdonisJS asset bundler) is configured for JS, we want to use TS in our app, let's configure support for TS.

yarn add ts-loader @babel/preset-react --save-dev 
=> have file  resources\views\app.edge.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="/favicon.ico">
@entryPointStyles('app')
@entryPointScripts('app')
<title>csr-adonis-inertia-react</title>
</head>
<body>
@inertia
</body>
</html>

- Modify the entrypoint, edit webpack.config.js changing the following:

// webpack.config.js
Encore.addEntry('app', './resources/js/app.js')
into:
Encore.addEntry('app', './resources/js/app.tsx')
Encore.enableTypeScriptLoader()
Encore.enableReactPreset()

// Rename ./resources/js/app.js to ./resources/js/app.tsx.
resources/js/app.tsx.

// Create a file ./resources/js/tsconfig.json, with contents:
{
"include": ["**/*"],
"compilerOptions": {
"lib": ["DOM"],
"jsx": "react",
"esModuleInterop": true
}
}

// tsconfig.json at the root of your project add the following to the "compilerOptions" section
"lib": ["DOM"],
"jsx": "react",

- Configure the app entrypoint file resources/js/app.tsx to contain

import { InertiaApp } from '@inertiajs/inertia-react'
import React from 'react'
import ReactDOM from 'react-dom'
import '../css/app.css'

// initial page object with props from server
const root = document.getElementById('app')
const page = JSON.parse(root?.dataset.page as string)

// dynamically load specified page component from "resources/js/Pages/." dir
async function resolver(pageName) {
const module = await import(`./Pages/${pageName}`)
return module.default
}

function App() {
return <InertiaApp initialPage={page} resolveComponent={resolver} initialComponent={''} />
}

ReactDOM.render(<App />, root)

- Create a test component

import React from 'react'

const Test = ({exampleProp}) => <div>Hello world, from {exampleProp}!)</div>

export default Test

- Create a test route

// start/routes.ts
import Route from '@ioc:Adonis/Core/Route'

Route.get('/test', async ({ inertia }) => {
return inertia.render('Test', { exampleProp: 'inertia' })
})

* show result

node ace serve --watch

* Errors

- TS2688: Cannot find type definition file for 'pino-std-serializers'.

yarn add @types/pino-std-serializers

- TS2307: Cannot find module '@inertiajs/inertia-react'

yarn add @inertiajs/inertia-react

-  Error: Can't resolve '@inertiajs/inertia'

yarn add @inertiajs/inertia

- Warning: React-dom.development.js:86: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17

// update resources/js/app.tsx
import { InertiaApp } from '@inertiajs/inertia-react';
import React from 'react';
import { createRoot } from 'react-dom/client';
import '../css/app.css';

// initial page object with props from server
const root = document.getElementById('app');
const page = JSON.parse(root?.dataset.page as string);

// dynamically load specified page component from "resources/js/Pages/." dir
async function resolver(pageName) {
const module = await import(`./Pages/${pageName}`);
return module.default;
}

function App() {
return <InertiaApp initialPage={page} resolveComponent={resolver} initialComponent={''} />;
}

createRoot(root).render(<App />);

Source git: https://github.com/phong2018/learning-adonisjs-web-inertia

Reference: guide

Thank you.  

Monday, 5 June 2023

Adonis using Reactjs for Frontend

- configure compile React assets

yarn add adonis-mix-asset && yarn add -D laravel-mix laravel-mix-tailwind;

- setup provider, commands, webpack.mix.js for adonis

node ace invoke adonis-mix-asset;

- install package for hot loading, 

yarn add -D @babel/preset-react babel-loader @pmmmwh/react-refresh-webpack-plugin react-refresh;

- config webpack.mix.js

const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin')
const webpack = require('webpack')
const mix = require('laravel-mix')
require('laravel-mix-tailwind')
const isDevelopment = process.env.NODE_ENV !== 'production'
mix
.setPublicPath('public')
.js('resources/client/index.js', 'public/js/')
.react()
.sass('resources/assets/scss/index.scss', 'public/css/')
.tailwind()
.options({
processCssUrls: false
})
if (isDevelopment) {
mix.sourceMaps()
}
mix.webpackConfig({
mode: isDevelopment ? 'development' : 'production',
context: __dirname,
node: {
__filename: true,
__dirname: true,
},
module: {
rules: [
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
exclude: /node_modules/,
use: [
{
loader: require.resolve('babel-loader'),
options: {
presets: ['@babel/preset-react'],
plugins: [isDevelopment && require.resolve('react-refresh/babel')].filter(Boolean),
},
},
],
},
],
},
plugins: [
isDevelopment && new webpack.HotModuleReplacementPlugin(),
isDevelopment && new ReactRefreshWebpackPlugin(),
new webpack.ProvidePlugin({
React: 'react',
}),
].filter(Boolean),
})

- add .gitignore

# other settings...
mix-manifest.json
hot
public/js/*
public/css/*
public/**/*_js*

- Configure Tailwind

yarn add -D tailwindcss@npm:@tailwindcss/postcss7-compat @tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9 sass-loader@8.* sass postcss@^8.1;
mkdir -p resources/assets/scss && touch resources/assets/scss/index.scss;
npx tailwindcss init

tailwind.config.js

module.exports = {
purge: ['./resources/client/**/*.{js,jsx,ts,tsx}', './resources/views/**/*.edge'],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
}

resources/assets/scss/index.scss 

@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

- Create Client React App

yarn add react react-dom;
mkdir -p resources/client && touch resources/client/index.js resources/client/App.js;

resources/client/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);

resources/client/App.js

import React from 'react'
export default function App() {
return (
<div>
Hello World!
</div>
)
}

using index.js in resources/views/index.edge 

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/css/index.css">
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script src="/js/index.js"></script>
</body>
</html>

package.json

"start": "node build/server.js",
"server": "node ace serve --watch",
"client": "node ace mix:watch",
"build": "yarn client:build && yarn server:build",
"server:build": "node ace build --production",
"client:build": "node ace mix:build --production",
"dev": "concurrently \"yarn server\" \"yarn client\"",

=> watch client: yarn client

Reference: guide

Thank you.  

Saturday, 20 May 2023

How to use repl in Adonisjs

>> Official Guide

* use node ace repl

.ls
loadModels()
const users = await models.User.all()
console.log(users)
 

Thank you.  

Wednesday, 10 May 2023

Understand about how Nodejs work

 * Nodejs use 

+ Single-threaded with Event Loop: when a request is made, it is added to the event loop, which is a queue of pending requests. Node.js then continues executing the remaining code, rather than waiting for the request to be completed. When the request is completed, Node.js retrieves it from the event loop and returns the result to the client.

+ Event-driven, non-blocking I/O: allows it to handle multiple requests and connections concurrently without blocking the execution of other code.

 

Three ways to use asynchronous in nodejs

* There are 3 ways to use asynchronous in nodejs: callback, promises, async/await

1. Callbacks functions

- Callbacks are functions that are passed as arguments to other functions and are executed when the operation completes.

- Callbacks are commonly used to handle asynchronous operations.

const fs = require('fs');
fs.readFile('myfile.txt', function(err, data) {
if (err) {
console.error(err);
} else {
console.log(data.toString());
}
});

* function(err, data): is callback (is the second parameter of readFile() method)

2. Promises

- Promises represent a value that may not be avaiable

const fs = require('fs/promises');

fs.readFile('myfile.txt')
.then((data) => {
console.log(data.toString());
})
.catch((err) => {
console.error(err);
});

* (data) is promises (is return by method readFile())

3. Async/await syntax

- Async/await is a syntax allows to write asynchronous code that looks and behaves like synchronous code

const fs = require('fs/promises');

async function readFile() {
try {
const data = await fs.readFile('myfile.txt');
console.log(data.toString());
} catch (err) {
console.error(err);
}
}

readFile();

Thank you 


 





Publish npm package

  Để publish   pav-kit  lên NPM, bạn hãy làm theo các bước dưới đây. Tôi đã tạo thêm file  index.js  để đảm bảo gói tin hợp lệ. Bước 1: Tạo ...