Package Exports
- ph-municipalities
- ph-municipalities/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (ph-municipalities) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
ph-municipalities
The ph-municipalities NPM package has NPM scripts that allow interactive querying of Philippines municipalities included in one or more provinces or from a whole region, with an option of writing them to JSON files from the command line.
It uses /app/data/day1.xlsx (downloaded and stored as of this 20220808) from PAGASA's 10-day weather forecast Excel files as the default data source.
It also asks users to key in the file download URL of a remote PAGASA 10-Day weather forecast Excel file should they want to use another Excel file for a new and updated data source.
INFO: When installing the package using
npm i ph-municipalities, the default data source is inside/data/day1.xlsx. All source codes and files are also inside the ph-municipalities root directory.
Extracted municipalities are written in JSON files following the format:
{
"metadata": {
"source": "https://pubfiles.pagasa.dost.gov.ph/pagasaweb/files/climate/tendayweatheroutlook/day1.xlsx",
"title": "List of PH Municipalities By Province and Region",
"description": "This dataset generated with reference to the excel file contents from the source URL on 20220808.",
"date_created": "Mon Aug 08 2022"
},
"data": {
"Albay": ["Bacacay", "Camalig", ... ],
"Camarines Norte": ["Basud", "Capalonga", ... ],
"Camarines Sur": ["Baao", "Balatan", ... ],
...
}
}Pre-compiled windows binaries are available for download in the latest Releases download page.
Requirements
The following dependencies are used for this project. Feel free to use other dependency versions as needed.
- Windows 10 OS
- nvm for Windows v1.1.9
- NodeJS, installed using nvm
- node v16.14.2
- npm v8.5.0
- Excel file
- ph-municipalities uses Excel files in the
/app/datadirectory as data source. - At minimum, the excel file should have a column that contains municipality and province names following the pattern
"municipalityName (provinceName)" - Checkout the excel file format on the
/app/data/day1.xlsxsample file for more information
- ph-municipalities uses Excel files in the
- (Optional) Download URL for a remote excel file.
- See the
EXCEL_FILE_URLvariable on the Installation section.
- See the
Contents
- ph-municipalities
- Requirements
- Contents
- Installation
- Installation Using Docker
- Available Scripts
- Class Usage
- Building Standalone Windows Executables
- Compiling into Single, Minified Files
- Troubleshooting
Installation
Clone this repository.
git clone https://github.com/ciatph/municipalities-by-province.gitInstall dependencies.
cd app npm install
Create a
.envfile from the.env.examplefile inside the/appdirectory. Use the default values for the following environment variables.INFO: If installed as an NPM package with
npm i ph-municipalities, create the.envfile inside the NPM project's root directory.Variable Name Description EXCEL_FILE_URL (Optional) Remote excel file's download URL.
If provided, the excel file will be downloaded and saved on the specifiedpathToFilelocal filesystem location during theExcelFileclass initialization.
Read on Usage for more information.SHEETJS_COLUMN Column name read by sheetjs in an excel file.
This column contains the municipality and province names following the string pattern"municipalityName (provinceName)"
Default value is__EMPTYSORT_ALPHABETICAL Arranges the municipality names in alphabetical order.
Default value is1. Set to0to use the ordering as read from the Excel file.SPECIAL_CHARACTERS Key-value pairs of special characters or garbled text and their normalized text conversions, delimited by the ":"character.
Multiple key-value pairs are delimited by the","character.
If a special character key's value is a an empty string, write it as i.e.,:"some-garbled-text:"
Installation Using Docker
We can use Docker to run dockerized Node app for local development mode. The following methods require Docker and Docker compose correctly installed and set up on your development machine.
Docker Dependencies
The following dependencies are used to build and run the image. Please feel feel free to use other OS and versions as needed.
- Ubuntu 22.04.1
- Docker version 23.0.1, build a5eeb1
- Docker Compose v2.16.0
- Microsoft Windows 10 Pro
- version 22H2 Build 19045.4651
- Docker Desktop
- Docker Compose version v2.27.1-desktop.1
- Docker Engine version 26.1.4, build 5650f9b
Docker for Localhost Development
Set up the environment variables for the
/appdirectory. Visit the Installation section, step #3 for more information.Stop and delete all docker instances for a fresh start.
NOTE: Running this script will delete all docker images, containers, volumes, and networks. Run this script if you feel like everything is piling but do not proceed if you have important work on other running Docker containers.
sudo chmod u+x scripts/docker-cleanup.sh ./scripts/docker-cleanup.sh # Answer all proceeding prompts
Build and run the app using Docker.
- Build
docker compose -f docker-compose.dev.yml build - Run
docker compose -f docker-compose.dev.yml up - Stop
docker compose -f docker-compose.dev.yml down
- Build
Edit and execute scripts within the running docker container from step #3.
- For running NPM scripts (see the Available Scripts section for more information):
docker exec -it ph-municipalities <NPM_SCRIPT> - For new scripts (example only):
docker exec -it ph-municipalities node ./src/new.js
- For running NPM scripts (see the Available Scripts section for more information):
Available Scripts
Note: These NPM scripts run relative within the
/appdirectory, when working on a git-cloned repository of the app. To run using only NodeJS, navigate first to the/appdirectory and execute a target script, for example:
cd app
npm run list:regionnpm start / npm run list:region
- Asks users to enter the download URL of a remote excel file or use the default local excel file
- Loads and parses the local excel file in
/app/data/day1.xlsxby default. - Loads and parses the downloaded excel file in
/app/data/datasource.xlsxif download URL in the class constructor is provided.
- Loads and parses the local excel file in
- Displays a list of available PH region names.
- Lists all provinces and municipalities of a specified region via commandline input.
- Asks for an option to write results to a JSON file.
- Run the script as follows if installed using
npm i ph-municipalities:node .\node_modules\ph-municipalities\src\scripts\by_region.js
npm run list:province
- Asks users to enter the download URL of a remote excel file or use the default local excel file
- Loads and parses the local excel file in
/app/data/day1.xlsxby default. - Loads and parses the downloaded excel file in
/app/data/datasource.xlsxif download URL in the class constructor is provided.
- Loads and parses the local excel file in
- Lists all municipalities under specified province(s) via commandline input.
- Asks for an option to write results to a JSON file.
- Run the script as follows if installed using
npm i ph-municipalities:node .\node_modules\ph-municipalities\src\scripts\by_province.js
npm run example
- Downloads and parses a remote excel file.
- Demonstrates sample usage with
await
build:win:region
- Package the Node.js project's
npm startscript into a stand-alone windowsnode16-win-x64executable. - The windows executable file will be stored in
/dist/ph-regions-win.exe. Click the executable file to run.
build:win:province
- Package the Node.js project's
npm list:provincescript into a stand-alone windowsnode16-win-x64executable. - The windows executable file will be stored in
/dist/ph-provinces-win.exe. Click the executable file to run.
build:win:all
- Package the Node.js project's
npm startandnpm list:provincescript into a stand-alone windowsnode16-win-x64executables in one go. - Each window executable file will be stored in the
/distdirectory.
npm run minify:region
- Compiles the Node.js project's
npm list:regionscript and dependencies into a single script using ncc. - The compiled/minified file will be stored in
/dist/region. Run the command to use the compiled script:
node dist/region
npm run minify:province
- Compiles the Node.js project's
npm list:provincescript and dependencies into a single script using ncc. - The compiled/minified file will be stored in
/dist/province. Run the command to use the compiled script:
node dist/province
npm run minify:all
- Run the
npm list:regionandnpm list:provincescripts in one go. - Each compiled/minified files will be stored in the
/distdirectory.
npm run lint
Lint JavaScript source codes.
npm run lint:fix
Fix JavaScript lint errors.
Class Usage
Below are example usages of the ExcelFile class, run from the /app/src/examples directory. Check out the /app/src/examples/sample_usage.js file for more examples.
Load and Parse a Local Excel File
This is a simple usage example of the ExcelFile class.
Simple Usage
const path = require('path')
const ExcelFile = require('../classes/excel')
// Use the the following if installed via npm
// const { ExcelFile } = require('ph-municipalities')
// Reads an existing excel file on /app/data/day1.xlsx
file = new ExcelFile({
pathToFile: path.join(__dirname, '..', '..', 'data', 'day1.xlsx'),
// fastload: false
})
// Call init() if fastload=false
// file.init()
// listMunicipalities() lists all municipalities
// for each province
const provinces = ['Albay','Masbate','Sorsogon']
const municipalitiesFromProvince = file.listMunicipalities({ provinces })
// writeMunicipalities() writes municipalities data to a JSON file
// and returns the JSON object
const json = file.writeMunicipalities({
provinces,
fileName: path.join(__dirname, 'municipalities.json'),
prettify: true
})
// shapeJsonData() returns the output of writeMunicipalities()
// without writing to a JSON file
const json2 = file.shapeJsonData(provinces)
// JSON data of the parsed excel file will is accessible on
// file.datalist
console.log(file.datalist)
// Set the contents of file.datalist
file.datalist = [
{ municipality: 'Tayum', province: 'Abra' },
{ municipality: 'Bucay', province: 'Abra' }]Reading regions, provinces and municipalities
const path = require('path')
const ExcelFile = require('../classes/excel')
// Use the the following if installed via npm
// const { ExcelFile } = require('ph-municipalities')
// Reads an existing excel file on /app/data/day1.xlsx
const file = new ExcelFile({
pathToFile: path.join(__dirname, '..', '..', 'data', 'day1.xlsx'),
fastload: true
})
// listRegions() lists all regions from the regions settings file
const regions = file.listRegions()
console.log('---regions', regions)
// List region data from query
const regionQuery = file.listRegions('region_name')
console.log(`---region full name`, regionQuery)
// listProvinces() lists all provinces of a region
// for each given province
const provinces = file.listProvinces('Region IX')
console.log(`---provinces of ${regions[0]}`, provinces)
const municipalitiesFromProvince = file.listMunicipalities({ provinces })
console.log(`---municipalities`, municipalitiesFromProvince)Download and Parse a Remote Excel File
Adding a url field in the constructor parameter prepares the class to download a remote Excel file for the data source.
INFO: Run the
.init()method after initializing a class with aurlparameter to start the async file download.
require('dotenv').config()
const path = require('path')
const ExcelFile = require('../classes/excel')
// Use the the following if installed via npm
// const { ExcelFile } = require('ph-municipalities')
const main = async () => {
// Excel file will be downloaded to /app/src/examples/excelfile.xlsx
const file = new ExcelFile({
pathToFile: path.join(__dirname, 'excelfile.xlsx'),
url: process.env.EXCEL_FILE_URL
})
try {
// Download file
await file.init()
console.log(file.datalist)
} catch (err) {
console.log(err.message)
}
}
main()Alternate Usage - Events
Initialize an ExcelFile class instance.
require('dotenv').config()
const path = require('path')
const ExcelFile = require('../classes/excel')
// Use the the following if installed via npm
// const { ExcelFile } = require('ph-municipalities')
const main = () => {
try {
// Initialize an ExcelFile class instance.
const PHExcel = new ExcelFile({
pathToFile: path.join(__dirname, 'excelfile.xlsx'),
url: process.env.EXCEL_FILE_URL
})
// Download file
PHExcel.init()
// Listen to the instance's EVENTS.LOADED event.
PHExcel.events.on(PHExcel.EVENTS.LOADED, () => {
console.log('--Excel data loaded!', PHExcel.datalist)
})
} catch (err) {
console.log(`[ERROR]: ${err.message}`)
}
}
main()Using a Custom Configuration File
The ph-municipalities ExcelFile and ExcelFactory classes use a default configuration file to define their regions and provinces in the /app/config/regions.json file. The regions and provinces data in this file syncs with the PAGASA Seasonal and 10-Day Weather Forecast Excel files provinces and municipalities naming convention, encoded by hand as of August 24, 2024.
Follow the codes to define a custom regions config file, following the format of the /app/config/regions.json file to customize region definitions.
Note: The custom config file's province/municipality names should match those in the 10-day Excel file.
config.json
{
"metadata": {
"sources": [
"http://localhost:3000"
],
"title": "List of Random Provinces by Regions",
"description": "Sample regions config file",
"date_created": "20240824"
},
"data": [
{
"name": "Mondstat",
"abbrev": "MON",
"region_num": "1",
"region_name": "The City of Freedom",
"provinces": ["Brightcrown Mountains","Galesong Hill","Starfell Valley","Windwail Highland","Dragonspine"]
},
{
"name": "Inazuma",
"abbrev": "INZ",
"region_num": "3",
"region_name": "The Realm of Eternity",
"provinces": ["Narukami","Kannazuka","Yashiori","Watatsumi","Seirai","Tsurumi","Enkanomiya"]
},
...
]
}Custom config usage
require('dotenv').config()
const path = require('path')
const ExcelFile = require('../classes/excel')
// Use the the following if installed via npm
// const { ExcelFile } = require('ph-municipalities')
const config = require('./config.json')
// Load the local Excel file
const file = new ExcelFile({
pathToFile: path.join(__dirname, '..', '..', 'data', 'day1.xlsx'),
fastload: true,
// Use a custom settings file to define region info
settings: config
})
// Load provinces from the custom config file
const provinces = file
.settings
.data
.find(item => item.abbrev === 'INZ')?.provinces ?? []
// List the municipalities of defined provinces in the config file
// Note: Province/municipality names should match with those in the 10-day Excel file
const municipalities = file.listMunicipalities({ provinces })
console.log('---provinces', provinces)
console.log('\nProvince/municipality names should match with those in the 10-day Excel file')
console.log('---municipalities', municipalities)Building Standalone Windows Executables
The main npm scripts can be packaged into standalone windows executables. Pre-compiled windows binaries are available for download in the latest Releases download page.
- Run any of the following scripts to build the programs.
npm run build:win:region npm run build:win:province # npm run build:win:all
- Click the resulting executable files in the
/distdirectory to execute.
Compiling into Single, Minified Files
The main npm scripts can be compiled into standalone JavaScript files together with all its dependencies.
- Run any of the following scripts to compile the source codes.
npm run minify:region npm run minify:province # npm run minify:all
- Run the compiled source codes in the
/distdirectory to execute.node dist/region node dist/province
Troubleshooting
This section describes several common errors and related fixes.
EACCESS: permission denied
Information
- This error usually happens when writing to files inside Docker-mounted volumes on an Ubuntu host during run time.
- A full sample error log is:
EACCESS: permission denied, open '/opt/app/region1.json'
Fix
- Find the host UID of the ph-municipalities Docker user. Its name is
"app,"defined in the Dockerfile.
docker run --rm -it ciatph/ph-municipalities:dev sh -c "id -u app" - Change the ownership of the
./appdirectory using the ph-municipalities user host UID from step #1.
sudo chown -R <APP_UID>:<APP_UID> ./app - Re-run the NPM script.
@ciatph
20220807