Skip to content

Commit

Permalink
docs: add usage examples (#166)
Browse files Browse the repository at this point in the history
  • Loading branch information
fityannugroho authored May 9, 2024
1 parent 81c6934 commit 10b29e1
Show file tree
Hide file tree
Showing 29 changed files with 1,369 additions and 0 deletions.
5 changes: 5 additions & 0 deletions examples/mysql/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=
DB_PASSWORD=
DB_NAME=idn_area
1 change: 1 addition & 0 deletions examples/mysql/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.env
24 changes: 24 additions & 0 deletions examples/mysql/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# idn-area-data with MySQL example

This example shows how to use the `idn-area-data` package with MySQL using [`mysql2`](https://www.npmjs.com/package/mysql2) driver.

Database migration and seeding are provided (see [`db/migration.ts`](./db/migration.ts) and [`db/seeder.ts`](./db/seeder.ts)).

In the project directory, you can run:

- Database migration:

```bash
npm run db:migrate
```

- Database seeding:

```bash
npm run db:seed
```

- Start the application:
```bash
npm start
```
56 changes: 56 additions & 0 deletions examples/mysql/db/migration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { pool } from '../utils/db.js';

// Create tables
await pool.query(`
CREATE TABLE IF NOT EXISTS provinces (
code VARCHAR(2),
name VARCHAR(255) NOT NULL,
PRIMARY KEY (code)
);
`);

await pool.query(`
CREATE TABLE IF NOT EXISTS regencies (
code VARCHAR(5),
province_code VARCHAR(2) NOT NULL,
name VARCHAR(255) NOT NULL,
PRIMARY KEY (code),
FOREIGN KEY (province_code) REFERENCES provinces(code)
);
`);

await pool.query(`
CREATE TABLE IF NOT EXISTS districts (
code VARCHAR(8),
regency_code VARCHAR(5) NOT NULL,
name VARCHAR(255) NOT NULL,
PRIMARY KEY (code),
FOREIGN KEY (regency_code) REFERENCES regencies(code)
);
`);

await pool.query(`
CREATE TABLE IF NOT EXISTS villages (
code VARCHAR(13),
district_code VARCHAR(8) NOT NULL,
name VARCHAR(255) NOT NULL,
PRIMARY KEY (code),
FOREIGN KEY (district_code) REFERENCES districts(code)
);
`);

await pool.query(`
CREATE TABLE IF NOT EXISTS islands (
code VARCHAR(11),
regency_code VARCHAR(5),
name VARCHAR(255) NOT NULL,
coordinate VARCHAR(255) NOT NULL,
is_outermost_small BOOLEAN NOT NULL,
is_populated BOOLEAN NOT NULL,
PRIMARY KEY (code),
FOREIGN KEY (regency_code) REFERENCES regencies(code)
);
`);

console.log('Migration successful');
pool.end();
53 changes: 53 additions & 0 deletions examples/mysql/db/seeder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {
getProvinces,
getRegencies,
getDistricts,
getVillages,
getIslands,
} from 'idn-area-data';
import { pool } from '../utils/db.js';

await pool.query('INSERT INTO provinces (code, name) VALUES ?', [
(await getProvinces()).map((province) => [province.code, province.name]),
]);

await pool.query('INSERT INTO regencies (code, province_code, name) VALUES ?', [
(await getRegencies({ transform: true })).map((regency) => [
regency.code,
regency.provinceCode,
regency.name,
]),
]);

await pool.query('INSERT INTO districts (code, regency_code, name) VALUES ?', [
(await getDistricts({ transform: true })).map((district) => [
district.code,
district.regencyCode,
district.name,
]),
]);

await pool.query('INSERT INTO villages (code, district_code, name) VALUES ?', [
(await getVillages({ transform: true })).map((village) => [
village.code,
village.districtCode,
village.name,
]),
]);

await pool.query(
'INSERT INTO islands (code, regency_code, name, coordinate, is_outermost_small, is_populated) VALUES ?',
[
(await getIslands({ transform: true })).map((island) => [
island.code,
island.regencyCode,
island.name,
island.coordinate,
island.isOutermostSmall,
island.isPopulated,
]),
],
);

console.log('Seeding successful');
pool.end();
26 changes: 26 additions & 0 deletions examples/mysql/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { pool } from './utils/db.js';

// After migration and seeding, you can query the database. For example:
// Get all provinces with count of regencies, districts, villages, and islands
const timeStart = performance.now();
const [result] = await pool.query(`
SELECT
provinces.code AS province_code,
provinces.name AS province_name,
COUNT(DISTINCT regencies.code) AS regency_count,
COUNT(DISTINCT districts.code) AS district_count,
COUNT(DISTINCT villages.code) AS village_count,
COUNT(DISTINCT islands.code) AS island_count
FROM provinces
LEFT JOIN regencies ON regencies.province_code = provinces.code
LEFT JOIN districts ON districts.regency_code = regencies.code
LEFT JOIN villages ON villages.district_code = districts.code
LEFT JOIN islands ON islands.regency_code = regencies.code
GROUP BY provinces.code
`);
const timeEnd = performance.now();

console.log(`Query executed in ${timeEnd - timeStart}ms`);
console.table(result);

pool.end();
22 changes: 22 additions & 0 deletions examples/mysql/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "idn-area-data-usage-example",
"version": "1.0.0",
"description": "Example of using idn-area-data with MySQL",
"main": "index.js",
"type": "module",
"scripts": {
"db:migrate": "tsx db/migration.ts",
"db:seed": "tsx db/seeder.ts",
"start": "tsx index.ts"
},
"devDependencies": {
"idn-area-data": "^3.1.1",
"tsx": "^4.9.3",
"typescript": "^5.4.5"
},
"dependencies": {
"dotenv": "^16.4.5",
"mysql2": "^3.9.7",
"zod": "^3.23.7"
}
}
13 changes: 13 additions & 0 deletions examples/mysql/utils/db.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import mysql from 'mysql2/promise';
import env from './env.js';

/**
* MySQL database pool
*/
export const pool = mysql.createPool({
host: env.DB_HOST,
port: env.DB_PORT,
user: env.DB_USERNAME,
password: env.DB_PASSWORD,
database: env.DB_NAME,
});
14 changes: 14 additions & 0 deletions examples/mysql/utils/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import 'dotenv/config';
import { z } from 'zod';

const envSchema = z
.object({
DB_HOST: z.string(),
DB_PORT: z.coerce.number(),
DB_USERNAME: z.string(),
DB_PASSWORD: z.string(),
DB_NAME: z.string(),
})
.required();

export default envSchema.parse(process.env);
5 changes: 5 additions & 0 deletions examples/postgres/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=
DB_PASSWORD=
DB_NAME=idn_area
1 change: 1 addition & 0 deletions examples/postgres/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.env
24 changes: 24 additions & 0 deletions examples/postgres/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# idn-area-data with PostgreSQL example

This example shows how to use the `idn-area-data` package with PostgreSQL using [`postgres`](https://www.npmjs.com/package/postgres) driver.

Database migration and seeding are provided (see [`db/migration.ts`](./db/migration.ts) and [`db/seeder.ts`](./db/seeder.ts)).

In the project directory, you can run:

- Database migration:

```bash
npm run db:migrate
```

- Database seeding:

```bash
npm run db:seed
```

- Start the application:
```bash
npm start
```
55 changes: 55 additions & 0 deletions examples/postgres/db/migration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { sql } from '../utils/db.js';

await sql`
CREATE TABLE IF NOT EXISTS provinces (
code VARCHAR(2),
name VARCHAR(255) NOT NULL,
PRIMARY KEY (code)
)
`;

await sql`
CREATE TABLE IF NOT EXISTS regencies (
code VARCHAR(5),
province_code VARCHAR(2) NOT NULL,
name VARCHAR(255) NOT NULL,
PRIMARY KEY (code),
FOREIGN KEY (province_code) REFERENCES provinces(code)
)
`;

await sql`
CREATE TABLE IF NOT EXISTS districts (
code VARCHAR(8),
regency_code VARCHAR(5) NOT NULL,
name VARCHAR(255) NOT NULL,
PRIMARY KEY (code),
FOREIGN KEY (regency_code) REFERENCES regencies(code)
)
`;

await sql`
CREATE TABLE IF NOT EXISTS villages (
code VARCHAR(13),
district_code VARCHAR(8) NOT NULL,
name VARCHAR(255) NOT NULL,
PRIMARY KEY (code),
FOREIGN KEY (district_code) REFERENCES districts(code)
)
`;

await sql`
CREATE TABLE IF NOT EXISTS islands (
code VARCHAR(11),
regency_code VARCHAR(5) DEFAULT NULL,
name VARCHAR(255) NOT NULL,
coordinate VARCHAR(255) NOT NULL,
is_outermost_small BOOLEAN NOT NULL,
is_populated BOOLEAN NOT NULL,
PRIMARY KEY (code),
FOREIGN KEY (regency_code) REFERENCES regencies(code)
)
`;

sql.end();
console.log('Migration completed');
38 changes: 38 additions & 0 deletions examples/postgres/db/seeder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {
getDistricts,
getIslands,
getProvinces,
getRegencies,
getVillages,
} from 'idn-area-data';
import { sql } from '../utils/db.js';

// Insert provinces
await sql`INSERT INTO provinces ${sql(await getProvinces())};`;

// Insert regencies
await sql`INSERT INTO regencies ${sql(await getRegencies({ transform: true }))};`;

// Insert districts
await sql`INSERT INTO districts ${sql(await getDistricts({ transform: true }))};`;

const BATCH_SIZE = 1000;

// Insert villages in batch
const villages = await getVillages({ transform: true });

for (let i = 0; i < villages.length; i += BATCH_SIZE) {
const batch = villages.slice(i, i + BATCH_SIZE);
await sql`INSERT INTO villages ${sql(batch)};`;
}

// Insert islands in batch
const islands = await getIslands({ transform: true });

for (let i = 0; i < islands.length; i += BATCH_SIZE) {
const batch = islands.slice(i, i + BATCH_SIZE);
await sql`INSERT INTO islands ${sql(batch)};`;
}

sql.end();
console.log('Seed completed');
26 changes: 26 additions & 0 deletions examples/postgres/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { sql } from './utils/db.js';

// After migration and seeding, you can query the database. For example:
// Get all provinces with count of regencies, districts, villages, and islands
const timeStart = performance.now();
const result = await sql`
SELECT
provinces.code AS province_code,
provinces.name AS province_name,
COUNT(DISTINCT regencies.code) AS regency_count,
COUNT(DISTINCT districts.code) AS district_count,
COUNT(DISTINCT villages.code) AS village_count,
COUNT(DISTINCT islands.code) AS island_count
FROM provinces
LEFT JOIN regencies ON regencies.province_code = provinces.code
LEFT JOIN districts ON districts.regency_code = regencies.code
LEFT JOIN villages ON villages.district_code = districts.code
LEFT JOIN islands ON islands.regency_code = regencies.code
GROUP BY provinces.code
`;
const timeEnd = performance.now();

console.log(`Query executed in ${timeEnd - timeStart}ms`);
console.table(result);

sql.end();
Loading

0 comments on commit 10b29e1

Please sign in to comment.