npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

spark-property-manager

v2.0.0

Published

Spark Real Estate Management Application

Readme

Spark Property Manager

A Real Estate Property Management Web Application for streamlined bookkeeping and work order management. Allocate expenses to each property unit by uploading receipt images or bulk uploading bank statements as flat files with configurable columns.

  • Technologies: Nodejs, postgresql

Step To Setup

Postgresql

$ sudo apt-get update
$ sudo apt-get install postgresql postgresql-contrib

Create Database and Database User

$ createuser -P -s dbusername --createdb

If creating the DB doesn’t add the user, follow the steps.

$ sudo -u postgres psql
# CREATE USER username WITH PASSWORD 'password';
# ALTER USER username SUPERUSER;
# CREATE DATABASE dbname OWNER username;
# \q

Log in with the created database user and enable the pgcrypto extension for password encryption.

$ psql -U username -d dbname
# CREATE EXTENSION pgcrypto;
# \q

Install Nodejs

nodejs install guide

Install Bun

bun homepage

Download spark-property-Manager

$ git clone https://github.com/wsapiens/spark-property-manager.git

or download tarball by npm.

$ npm pack spark-property-manager

$ tar -xvf spark-property-manager-{version}.tgz

Download dependencies

$ cd spark-property-manager
spark-property-manager$ npm install

or

spark-property-manager$ bun install

Run database migration

First, setup sequelize CLI config.json.

$ vi config/config.json

See the example below.

{
  "development": {
    "username": "dbuser",
    "password": "dbpass",
    "database": "dbname",
    "host": "127.0.0.1",
    "dialect": "postgres"
  },

}

Run DB migration and generate seed data using the installed Sequelize.

$ node_modules/.bin/sequelize db:migrate
$ node_modules/.bin/sequelize db:seed:all

Or via npx (Node Package eXecute command-line utility) with sequelize-cli.

$ npx sequelize-cli db:migrate
$ npx sequelize-cli db:seed:all

Create the base company and initial login user after completing the DB migration and seeding data.

$ psql -U username -d dbname
# SELECT COUNT(*) FROM company; -- it would be zero
# INSERT INTO company(name) VALUES ('base company'); -- create base comapny
# CREATE EXTENSION pgcrypto;
# INSERT INTO login_user(company_id, email, password, is_admin, is_manager) VALUES (1, 'email', crypt('password', gen_salt('bf')), true, true); -- create a login user with email as username and password as password for the base company
# \q

If Sequelize DB migration fails, load from schema.sql to create the base company and initial login user.

spark-property-manager$ psql -U username -d Database -a -f schema.sql

Generate self-signed cert and key to run on https

$ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout apache-selfsigned.key -out apache-selfsigned.crt

Copy app.properties.TEMPLATE to app.properties and update app.properties accordingly to your environment

$ cp app.properties.TEMPLATE app.properties
$ vi app.properties
  • app.properties example
# contents of properties file
[db]
hostname = postgresql.host.com
port = 5432
name = dbname
dialect = postgres
username = dbuser
password = dbpass

[app]
hostname = localhost
port = 8080
sessionSecret = secret
https = false
serverkey = /path/to/server.key
servercert = /path/to/server.crt
url = http://localhost:8080

[log]
file = app.log
level = error

[smtp]
username = smtpUsername
password = smtpPassword
hostname = smtpHostname
port = 465
ssl = true
tls = false

If deploying in a cloud environment with a domain (named IP address), update the url property accordingly to ensure account creation emails include the correct app link. url = http://your.domain.com:8080

Encrypt database password

  • encrypt db password from command line by node.js
spark-property-manager$ node
> var crypto = require('./util/crypto');
> crypto.encrypt('mypass');
'a199/unJEhzdS5lfoF3sQe1haMc5kg=='
  • encrypt db password from command line by bun
spark-property-manager$ bun repl
Welcome to Bun v1.3.13
Type .copy [code] to copy to clipboard. .help for more info.

❯ var crypto = require('./util/crypto');
{
  generateRandomString: [Function: generateRandomString],
  encrypt: [Function: encrypt],
  decrypt: [Function: decrypt],
}
❯ crypto.encrypt('mypass');
"bPPEir+8a0z2aSQOzMr8ngYfevHLig=="
❯
  • put the encrypted password with '[encrypt]' prefix into db password field on app.properties
# contents of properties file
[db]
hostname = postgresql.host.com
port = 5432
name = dbname
dialect = postgres
username = dbuser
password = [encrypt]a199/unJEhzdS5lfoF3sQe1haMc5kg==

Static code analysis by jshint and grunt

  • install grunt
$ npm i -g grunt-cli

or

$ bun add -g grunt-cli
  • run grunt
$ grunt
Running "jshint:files" (jshint) task
>> 46 files lint free.

Done.

Static code analysis by ESLint

The .eslintrc.js file defines ESLint configurations and rules.

$ npm run lint

> [email protected] lint
> eslint --ext .js app.js bin config email log migrations models routes util seeders

To recreate the configuration rather than editing the existing one.

$ npm init @eslint/config

Run unit test by mocha

  • install mocha globally
$ npm i -g mocha

or

$ bun add -g mocha
  • run mocha
❯ mocha


  util
    getImportAmount()
      ✔ get negative amount for positive return amount
      ✔ get negative amount for negative return amount
      ✔ get postive amount for positive sale amount
      ✔ get positive amount for negative sale amount
    getImportDescription()
      ✔ get description with return mark
      ✔ get description without return mark
    getRandomRGB()
      ✔ get RGB number list

  crypto
    encrypt()
      ✔ test encrypt
    decrypt()
      ✔ test decrypt


  9 passing (10ms)
  • install mocha locally
$ npm i mocha
$ node_modules/.bin/mocha

util
  getImportAmount()
    ✓ get negative amount for positive return amount
    ✓ get negative amount for negative return amount
    ✓ get postive amount for positive sale amount
    ✓ get positive amount for negative sale amount
  getImportDescription()
    ✓ get description with return mark
    ✓ get description without return mark
  getRandomRGB()
    ✓ get RGB number list

crypto
  encrypt()
    ✓ test encrypt
  decrypt()
    ✓ test decrypt


9 passing (23ms)

Run Application

  • run application by npm

Update package.json script section to use Node

  "scripts": {
    "test": "mocha",
    "lint": "eslint --ext .js .",
    "start": "node ./bin/server.js",
    "debug": "node --inspect ./bin/server.js"
  },

npm start command will run the application

$ npm start

or update package.json script section to use bun

  "scripts": {
    "test": "mocha",
    "lint": "eslint --ext .js .",
    "start": "bun ./bin/server.js",
    "debug": "bun --inspect ./bin/server.js"
  },

bun start command will run the application

$ bun start

Run Application by using Process Manager PM2

PM2 offers production-grade process management. pm2 install guide

  • install pm2
$ npm install pm2 -g
  • run application by pm2
$ pm2 start ./bin/server.js --name "spark-property-manager" -i 8 -l pm2.log
[PM2] Starting /Users/spark/workspace3/spark-property-manager/bin/server.js in cluster_mode (8 instances)
[PM2] Done.
┌────────────────────────┬────┬─────────┬───────┬────────┬─────────┬────────┬──────┬───────────┬───────┬──────────┐
│ App name               │ id │ mode    │ pid   │ status │ restart │ uptime │ cpu  │ mem       │ user  │ watching │
├────────────────────────┼────┼─────────┼───────┼────────┼─────────┼────────┼──────┼───────────┼───────┼──────────┤
│ spark-property-manager │ 0  │ cluster │ 35491 │ online │ 0       │ 2s     │ 0%   │ 83.1 MB   │ spark │ disabled │
│ spark-property-manager │ 1  │ cluster │ 35494 │ online │ 0       │ 2s     │ 1%   │ 83.5 MB   │ spark │ disabled │
│ spark-property-manager │ 2  │ cluster │ 35511 │ online │ 0       │ 2s     │ 3%   │ 83.6 MB   │ spark │ disabled │
│ spark-property-manager │ 3  │ cluster │ 35528 │ online │ 0       │ 1s     │ 13%  │ 83.5 MB   │ spark │ disabled │
│ spark-property-manager │ 4  │ cluster │ 35547 │ online │ 0       │ 1s     │ 55%  │ 82.1 MB   │ spark │ disabled │
│ spark-property-manager │ 5  │ cluster │ 35564 │ online │ 0       │ 1s     │ 104% │ 75.2 MB   │ spark │ disabled │
│ spark-property-manager │ 6  │ cluster │ 35581 │ online │ 0       │ 0s     │ 95%  │ 54.8 MB   │ spark │ disabled │
│ spark-property-manager │ 7  │ cluster │ 35602 │ online │ 0       │ 0s     │ 77%  │ 35.8 MB   │ spark │ disabled │
└────────────────────────┴────┴─────────┴───────┴────────┴─────────┴────────┴──────┴───────────┴───────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app
  • stop application by pm2
$ pm2 stop spark-property-manager
[PM2] Applying action stopProcessId on app [spark-property-manager](ids: 0,1,2,3,4,5,6,7)
[PM2] [spark-property-manager](0) ✓
[PM2] [spark-property-manager](1) ✓
[PM2] [spark-property-manager](2) ✓
[PM2] [spark-property-manager](3) ✓
[PM2] [spark-property-manager](4) ✓
[PM2] [spark-property-manager](5) ✓
[PM2] [spark-property-manager](6) ✓
[PM2] [spark-property-manager](7) ✓
┌────────────────────────┬────┬─────────┬─────┬─────────┬─────────┬────────┬─────┬────────┬───────┬──────────┐
│ App name               │ id │ mode    │ pid │ status  │ restart │ uptime │ cpu │ mem    │ user  │ watching │
├────────────────────────┼────┼─────────┼─────┼─────────┼─────────┼────────┼─────┼────────┼───────┼──────────┤
│ spark-property-manager │ 0  │ cluster │ 0   │ stopped │ 0       │ 0      │ 0%  │ 0 B    │ spark │ disabled │
│ spark-property-manager │ 1  │ cluster │ 0   │ stopped │ 0       │ 0      │ 0%  │ 0 B    │ spark │ disabled │
│ spark-property-manager │ 2  │ cluster │ 0   │ stopped │ 0       │ 0      │ 0%  │ 0 B    │ spark │ disabled │
│ spark-property-manager │ 3  │ cluster │ 0   │ stopped │ 0       │ 0      │ 0%  │ 0 B    │ spark │ disabled │
│ spark-property-manager │ 4  │ cluster │ 0   │ stopped │ 0       │ 0      │ 0%  │ 0 B    │ spark │ disabled │
│ spark-property-manager │ 5  │ cluster │ 0   │ stopped │ 0       │ 0      │ 0%  │ 0 B    │ spark │ disabled │
│ spark-property-manager │ 6  │ cluster │ 0   │ stopped │ 0       │ 0      │ 0%  │ 0 B    │ spark │ disabled │
│ spark-property-manager │ 7  │ cluster │ 0   │ stopped │ 0       │ 0      │ 0%  │ 0 B    │ spark │ disabled │
└────────────────────────┴────┴─────────┴─────┴─────────┴─────────┴────────┴─────┴────────┴───────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app
  • remove application from pm2
$ pm2 delete spark-property-manager
[PM2] Applying action deleteProcessId on app [spark-property-manager](ids: 0,1,2,3,4,5,6,7)
[PM2] [spark-property-manager](0) ✓
[PM2] [spark-property-manager](1) ✓
[PM2] [spark-property-manager](2) ✓
[PM2] [spark-property-manager](3) ✓
[PM2] [spark-property-manager](4) ✓
[PM2] [spark-property-manager](5) ✓
[PM2] [spark-property-manager](6) ✓
[PM2] [spark-property-manager](7) ✓
┌──────────┬────┬──────┬─────┬────────┬─────────┬────────┬─────┬─────┬──────┬──────────┐
│ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │
└──────────┴────┴──────┴─────┴────────┴─────────┴────────┴─────┴─────┴──────┴──────────┘
Use `pm2 show <id|name>` to get more details about an app

Run Application by using Process Manager BM2

BM2 is a process manager built entirely on Bun native APIs. The modern PM2 replacement — zero Node.js dependencies, pure Bun performance.

  • install bm2
$ bun add -g bm2
bun add v1.3.13 (bf2e2cec)

installed [email protected] with binaries:
 - bm2

12 packages installed [516.00ms]

warn: To run "bm2", add the global bin folder to $PATH:
  • run application by bm2
$ bm2 start ./bin/server.js --name "spark-property-manager" -i 4 --cwd $(pwd)
Starting daemon..
Waiting for daemon..

BM2 — Bun Process Manager
─────────────────────────────────────────────

┌────┬──────────────────────────┬───────────┬─────────┬─────────┬───────┬──────────┬───┬──────────┬──────┬─────┐
│ id │ name                     │ namespace │ version │ mode    │   pid │   uptime │ ↺ │ status   │  cpu │ mem │
├────┼──────────────────────────┼───────────┼─────────┼─────────┼───────┼──────────┼───┼──────────┼──────┼─────┤
│  0 │ spark-property-manager-0 │ default   │ -       │ cluster │ 96142 │ 0h 0m 0s │ 0 │ ● online │ 0.0% │  0b │
├────┼──────────────────────────┼───────────┼─────────┼─────────┼───────┼──────────┼───┼──────────┼──────┼─────┤
│  1 │ spark-property-manager-1 │ default   │ -       │ cluster │ 96143 │ 0h 0m 0s │ 0 │ ● online │ 0.0% │  0b │
├────┼──────────────────────────┼───────────┼─────────┼─────────┼───────┼──────────┼───┼──────────┼──────┼─────┤
│  2 │ spark-property-manager-2 │ default   │ -       │ cluster │ 96144 │ 0h 0m 0s │ 0 │ ● online │ 0.0% │  0b │
├────┼──────────────────────────┼───────────┼─────────┼─────────┼───────┼──────────┼───┼──────────┼──────┼─────┤
│  3 │ spark-property-manager-3 │ default   │ -       │ cluster │ 96145 │ 0h 0m 0s │ 0 │ ● online │ 0.0% │  0b │
└────┴──────────────────────────┴───────────┴─────────┴─────────┴───────┴──────────┴───┴──────────┴──────┴─────┘
  • stop application by bm2
$ bm2 stop spark-property-manager

BM2 — Bun Process Manager
─────────────────────────────────────────────

┌────┬──────────────────────────┬───────────┬─────────┬─────────┬─────┬────────┬────┬───────────┬──────┬─────┐
│ id │ name                     │ namespace │ version │ mode    │ pid │ uptime │  ↺ │ status    │  cpu │ mem │
├────┼──────────────────────────┼───────────┼─────────┼─────────┼─────┼────────┼────┼───────────┼──────┼─────┤
│  0 │ spark-property-manager-0 │ default   │ -       │ cluster │   - │      - │ 16 │ ● errored │ 0.0% │  0b │
├────┼──────────────────────────┼───────────┼─────────┼─────────┼─────┼────────┼────┼───────────┼──────┼─────┤
│  1 │ spark-property-manager-1 │ default   │ -       │ cluster │   - │      - │ 16 │ ● errored │ 0.0% │  0b │
├────┼──────────────────────────┼───────────┼─────────┼─────────┼─────┼────────┼────┼───────────┼──────┼─────┤
│  2 │ spark-property-manager-2 │ default   │ -       │ cluster │   - │      - │ 16 │ ● errored │ 0.0% │  0b │
├────┼──────────────────────────┼───────────┼─────────┼─────────┼─────┼────────┼────┼───────────┼──────┼─────┤
│  3 │ spark-property-manager-3 │ default   │ -       │ cluster │   - │      - │ 16 │ ● errored │ 0.0% │  0b │
└────┴──────────────────────────┴───────────┴─────────┴─────────┴─────┴────────┴────┴───────────┴──────┴─────┘
  • remove application from bm2
$ bm2 delete spark-property-manager
✓ Deleted

BM2 — Bun Process Manager
─────────────────────────────────────────────

┌────┬──────────────────────────┬───────────┬─────────┬─────────┬─────┬────────┬────┬───────────┬──────┬─────┐
│ id │ name                     │ namespace │ version │ mode    │ pid │ uptime │  ↺ │ status    │  cpu │ mem │
├────┼──────────────────────────┼───────────┼─────────┼─────────┼─────┼────────┼────┼───────────┼──────┼─────┤
│  0 │ spark-property-manager-0 │ default   │ -       │ cluster │   - │      - │ 16 │ ● errored │ 0.0% │  0b │
├────┼──────────────────────────┼───────────┼─────────┼─────────┼─────┼────────┼────┼───────────┼──────┼─────┤
│  1 │ spark-property-manager-1 │ default   │ -       │ cluster │   - │      - │ 16 │ ● errored │ 0.0% │  0b │
├────┼──────────────────────────┼───────────┼─────────┼─────────┼─────┼────────┼────┼───────────┼──────┼─────┤
│  2 │ spark-property-manager-2 │ default   │ -       │ cluster │   - │      - │ 16 │ ● errored │ 0.0% │  0b │
├────┼──────────────────────────┼───────────┼─────────┼─────────┼─────┼────────┼────┼───────────┼──────┼─────┤
│  3 │ spark-property-manager-3 │ default   │ -       │ cluster │   - │      - │ 16 │ ● errored │ 0.0% │  0b │
└────┴──────────────────────────┴───────────┴─────────┴─────────┴─────┴────────┴────┴───────────┴──────┴─────┘

$ bm2 list

BM2 — Bun Process Manager
─────────────────────────────────────────────

No processes running

Open by Browser

http://localhost:8080

Create Account by Valid Email address and it will send temporary password to your email

alt text

Login by temporary password sent to your email

alt text

Change password

alt text

How to record expense

  • Add a property from the Property Manager view; the building unit will be automatically added as the default unit.

  • Add or modify a unit for the added property from the Unit Manager view.

  • Add an expense by selecting the unit/property and expense type; you can also upload a receipt photo. On mobile, users will be prompted to either take a picture or choose a photo from the device.

  • For importing bank or credit card statements, use a flat file (.csv) format. As each bank and credit card company has a different format, define the column numbers for each data type first. Once the import column configuration is set in the Import Manager view, upload the .csv file to populate expenses.