
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@thrinz/pgapi
Advanced tools
pgAPI is a "Database as a service" application that automatically creates the REST API endpoint for the given URL. The endpoint is designed to call a Postgres Database Function which is configured at the time of API endpoint creation. This application automates the URL routing while the developers must have to just focus on the database method creation. No Coding is required.
$ docker run --name postgres -p 5430:5432 -e POSTGRES_DATABASE=pgapi -e POSTGRES_USER=pgapi -e POSTGRES_PASSWORD=pgapi -e POSTGRES_ROOT_PASSWORD=postgres -d postgres
$ docker run --name pgapi --link postgres:postgres -p 5001:3000 -e PG_USER=pgapi -e PG_HOST=postgres -e PG_PASSWORD=pgapi -e PG_DATABASE=pgapi -e PG_PORT=5432 pgapi
Open the link in the Browser. http://localhost:5001/admin
username: admin
password: admin
$ git clone https://github.com/thrinz/pgapi-starter-template
$ cd pgapi-starter-template
$ vi config.env from the terminal (linux or Mac) or open the config.env in a text editor. Modify the config.env file with the postgres database Information
DB_HOST=Postgres Hostname
DB_USER=Postgres username
DB_PASSWORD=Postgres Database Password
DB_NAME=Postgres Database Name
DB_PORT=Port Number
$ npm install
$ node index.js
The console must display log of the server to be running on port 5001
Open the link in the Browser. http://localhost:5001/admin
username: admin
password: admin
Open the link in the Browser. http://localhost:5001/admin
username: admin
password: admin
You must already have a “default-connection” Connection entry. This connection can be used for the next steps. However, if you decide to use a different database connection, then follow the below instructions
This step is not performed in this application. You would need a database client like pgAdmin to start developing the database function
Note : the database function must have only one input parameter with datatype JSON and the return type must be a JSON datatype . See sample database function.
Sample Database Function
CREATE OR REPLACE FUNCTION create_task ( p_data json)
RETURNS json AS
$BODY$
DECLARE
l_out json;
l_message_text text;
l_exception_detail text;
l_exception_hint text;
--
l_id uuid;
l_name text;
l_description text;
l_start_date timestamp;
l_due_date timestamp;
l_priority integer;
BEGIN
l_id := md5(random()::text || clock_timestamp()::text)::uuid;
l_name := (p_data->>'name')::text;
l_description := (p_data->>'description')::text;
l_start_date := NOW();
l_due_date := (p_data->>'due_date')::timestamp;
l_priority := (p_data->>'priority')::integer;
INSERT INTO tasks
(
id,
name,
description,
start_date,
due_date,
priority,
created,
updated
)
VALUES
(
l_id,
l_name,
l_description,
l_start_date,
l_due_date,
l_priority,
NOW(),
NOW()
);
l_out := '{"status" : "S" , "message" : "OK" , "id" : "' || l_id || '"}';
RETURN l_out;
EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS l_message_text = MESSAGE_TEXT,
l_exception_detail = PG_EXCEPTION_DETAIL,
l_exception_hint = PG_EXCEPTION_HINT;
l_out := '{ "status" : "E" , "message" : "' || REPLACE(l_message_text, '"', E'\\"') || '" }';
return l_out;
END
$BODY$
LANGUAGE plpgsql;
For POST Routes:
curl --header "Content-Type: application/json" --request POST --data 'JSON Data' http://localhost:5001/**route url created in Step 4**
Example:
curl --header "Content-Type: application/json" --request POST --data '{"name":"Task1" ,"description":"Task Description 1", "priority": 1, "start_date":"2018-12-08 02:41:17","due_date":"2018-12-12 01:31:10"}' http://localhost:5001/api/task/create
For GET Routes:
curl http://localhost:5001/**route url created in Step 4**
Example
Let us create a Tasks Demo Application
Table Creation Script
CREATE TABLE IF NOT EXISTS tasks (
id uuid NOT NULL,
name text NOT NULL,
description text NOT NULL,
start_date timestamp with time zone NOT NULL,
due_date timestamp with time zone NOT NULL,
priority integer NOT NULL,
created timestamp with time zone NOT NULL,
updated timestamp with time zone NOT NULL
);
Create_Task
CREATE OR REPLACE FUNCTION create_task ( p_data json)
RETURNS json AS
$BODY$
DECLARE
l_out json;
l_message_text text;
l_exception_detail text;
l_exception_hint text;
l_id uuid;
l_name text;
l_description text;
l_start_date timestamp;
l_due_date timestamp;
l_priority integer;
BEGIN
l_id := md5(random()::text || clock_timestamp()::text)::uuid;
l_name := (p_data->>'name')::text;
l_description := (p_data->>'description')::text;
l_start_date := NOW();
l_due_date := (p_data->>'due_date')::timestamp;
l_priority := (p_data->>'priority')::integer;
INSERT INTO tasks
(
id,
name,
description,
start_date,
due_date,
priority,
created,
updated
)
VALUES
(
l_id,
l_name,
l_description,
l_start_date,
l_due_date,
l_priority,
NOW(),
NOW()
);
l_out := '{"status" : "S" , "message" : "OK" , "id" : "' || l_id || '"}';
RETURN l_out;
EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS l_message_text = MESSAGE_TEXT,
l_exception_detail = PG_EXCEPTION_DETAIL,
l_exception_hint = PG_EXCEPTION_HINT;
l_out := '{ "status" : "E" , "message" : "' || REPLACE(l_message_text, '"', E'\\"') || '" }';
return l_out;
END
$BODY$
LANGUAGE plpgsql;
Create_Bulk_Tasks
CREATE OR REPLACE FUNCTION create_bulk_tasks ( p_data json)
RETURNS json AS
$BODY$
DECLARE
l_out json;
l_message_text text;
l_exception_detail text;
l_exception_hint text;
--
l_id uuid;
l_name text;
l_description text;
l_start_date timestamp;
l_due_date timestamp;
l_priority integer;
l_task_record json;
l_tasks_c CURSOR FOR SELECT json_array_elements(p_data->'tasks');
BEGIN
OPEN l_tasks_c;
LOOP
FETCH l_tasks_c INTO l_task_record;
EXIT WHEN NOT FOUND;
l_id := md5(random()::text || clock_timestamp()::text)::uuid;
l_name := (l_task_record->>'name')::text;
l_description := (l_task_record->>'description')::text;
l_start_date := NOW();
l_due_date := (l_task_record->>'due_date')::timestamp;
l_priority := (l_task_record->>'priority')::integer;
INSERT INTO tasks
(
id,
name,
description,
start_date,
due_date,
priority,
created,
updated
)
VALUES
(
l_id,
l_name,
l_description,
l_start_date,
l_due_date,
l_priority,
NOW(),
NOW()
);
END LOOP;
CLOSE l_tasks_c;
l_out := '{"status" : "S" , "message" : "OK" }';
RETURN l_out;
EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS l_message_text = MESSAGE_TEXT,
l_exception_detail = PG_EXCEPTION_DETAIL,
l_exception_hint = PG_EXCEPTION_HINT;
l_out := '{ "status" : "E" , "message" : "' || REPLACE(l_message_text, '"', E'\\"') || '" }';
return l_out;
END
$BODY$
LANGUAGE plpgsql;
Delete_Task
CREATE OR REPLACE FUNCTION delete_task ( p_data json)
RETURNS json AS
$BODY$
DECLARE
l_out json;
l_message_text text;
l_exception_detail text;
l_exception_hint text;
--
l_id uuid;
l_cnt int;
BEGIN
l_id := (p_data->>'id')::uuid;
DELETE FROM tasks
WHERE id = l_id;
GET DIAGNOSTICS l_cnt = row_count;
l_out := '{"status" : "S" , "message" : "OK" , "rows_affected" : "' || l_cnt || '"}';
RETURN l_out;
EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS l_message_text = MESSAGE_TEXT,
l_exception_detail = PG_EXCEPTION_DETAIL,
l_exception_hint = PG_EXCEPTION_HINT;
l_out := '{ "status" : "E" , "message" : "' || REPLACE(l_message_text, '"', E'\\"') || '" }';
return l_out;
END
$BODY$
LANGUAGE plpgsql;
Select_Task
CREATE OR REPLACE FUNCTION select_task ( p_data json)
RETURNS json AS
$BODY$
DECLARE
l_out json;
l_message_text text;
l_exception_detail text;
l_exception_hint text;
--
l_data text;
l_id uuid;
l_params json;
BEGIN
l_params := (p_data->>'urlparams')::json;
IF l_params IS NOT NULL THEN
l_id := (l_params->>'id')::uuid;
END IF;
IF l_id IS NULL THEN
SELECT array_to_json(array_agg(row_to_json(t.*))) INTO l_data
FROM (SELECT * FROM tasks) t;
ELSE
SELECT array_to_json(array_agg(row_to_json(t.*))) INTO l_data
FROM (SELECT * FROM tasks WHERE id = l_id) t;
END IF;
l_out := '{"status" : "S" , "message" : "OK" , "data" : ' || l_data || '}';
RETURN l_out;
EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS l_message_text = MESSAGE_TEXT,
l_exception_detail = PG_EXCEPTION_DETAIL,
l_exception_hint = PG_EXCEPTION_HINT;
l_out := '{ "status" : "E" , "message" : "' || REPLACE(l_message_text, '"', E'\\"') || '" }';
return l_out;
END
$BODY$
LANGUAGE plpgsql;
Update_Task
CREATE OR REPLACE FUNCTION update_task ( p_data json)
RETURNS json AS
$BODY$
DECLARE
l_out json;
l_message_text text;
l_exception_detail text;
l_exception_hint text;
--
l_id uuid;
l_name text;
l_description text;
l_due_date timestamp;
l_priority integer;
l_cnt int;
BEGIN
l_id := (p_data->>'id')::uuid;
l_name := (p_data->>'name')::text;
l_description := (p_data->>'description')::text;
l_due_date := (p_data->>'due_date')::timestamp;
l_priority := (p_data->>'priority')::integer;
UPDATE tasks
SET name = COALESCE(l_name,name)
, description = COALESCE(l_description, description)
, due_date = COALESCE(l_due_date, due_date)
, priority = COALESCE(l_priority, priority)
, updated = NOW()
WHERE id = l_id;
GET DIAGNOSTICS l_cnt = row_count;
l_out := '{"status" : "S" , "message" : "OK" , "rows_affected" : "' || l_cnt || '"}';
RETURN l_out;
EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS l_message_text = MESSAGE_TEXT,
l_exception_detail = PG_EXCEPTION_DETAIL,
l_exception_hint = PG_EXCEPTION_HINT;
l_out := '{ "status" : "E" , "message" : "' || REPLACE(l_message_text, '"', E'\\"') || '" }';
return l_out;
END
$BODY$
LANGUAGE plpgsql;
After setting up all the functions , the UI must look something like the below image. The green icon next to the Connection Name indicates that the connection is valid and the green icon next to the Function Name indicates that the database function is defined in the postgres database specified.
After setting up all the routes , the UI must look something like the below image.
curl --header "Content-Type: application/json" \ --request POST \ --data '{"name":"Task1" , "description":"Task Description 1", "priority": 1, "start_date":"2018-12-08 02:41:17", "due_date":"2018-12-12 01:31:10"}' \ http://localhost:5001/api/task/create
{"status":"S","message":"OK","result":[{"result":{"status":"S","message":"OK","id":"8003c392-d89a-e577-be11-5f42808cf28b"}}]}
curl --header "Content-Type: application/json" \ --request POST \ --data '{"id":"8003c392-d89a-e577-be11-5f42808cf28b","name":"Task2"}' \ http://localhost:5001/api/task/update
{"status":"S","message":"OK","result":[{"result":{"status":"S","message":"OK","rows_affected":"1"}}]}
curl --header "Content-Type: application/json" \ --request POST \ --data '{"id":"8003c392-d89a-e577-be11-5f42808cf28b"}' \ http://localhost:5001/api/task/delete
{"status":"S","message":"OK","result":[{"result":{"status":"S","message":"OK","rows_affected":"1"}}]}
curl --header "Content-Type: application/json" \ --request POST \ --data '{"tasks": [{"name":"Task4" , "description":"Task Description 4", "priority": 2, "start_date":"2018-12-08 02:41:17", "due_date":"2018-12-12 01:31:10"}, {"name":"Task5" , "description":"Task Description 5", "priority": 2, "start_date":"2018-12-08 02:41:17", "due_date":"2018-12-12 01:31:10"}]}' \ http://localhost:5001/api/tasks/bulk/create
{"status":"S","message":"OK","result":[{"result":{"status":"S","message":"OK"}}]}
curl http://localhost:5001/api/tasks
{"status":"S","message":"OK","result":[{"result":{"status":"S","message":"OK","data":[{"id":"d716a072-be43-2301-1d9e-80998bb0c95e","name":"Task4","description":"Task Description 4","start_date":"2018-12-22T23:56:29.495069+05:30","due_date":"2018-12-12T01:31:10+05:30","priority":2,"created":"2018-12-22T23:56:29.495069+05:30","updated":"2018-12-22T23:56:29.495069+05:30"},{"id":"4ee0bec0-f5df-e75e-9180-25dc216bd021","name":"Task5","description":"Task Description 5","start_date":"2018-12-22T23:56:29.495069+05:30","due_date":"2018-12-12T01:31:10+05:30","priority":2,"created":"2018-12-22T23:56:29.495069+05:30","updated":"2018-12-22T23:56:29.495069+05:30"}]}}]}
curl http://localhost:5001/api/task/d716a072-be43-2301-1d9e-80998bb0c95e
{"status":"S","message":"OK","result":[{"result":{"status":"S","message":"OK","data ":[{"id":"d716a072-be43-2301-1d9e- 80998bb0c95e","name":"Task4","description":"Task Description 4","start_date":"2018-12-22T23:56:29.495069+05:30","due_date":"2018-12- 12T01:31:10+05:30","priority":2,"created":"2018-12- 22T23:56:29.495069+05:30","updated":"2018-12-22T23:56:29.495069+05:30"}]}}]}
This project is licensed under the GPLv3 License - see the LICENSE file for details
FAQs
pgAPI - Database as a service
The npm package @thrinz/pgapi receives a total of 4 weekly downloads. As such, @thrinz/pgapi popularity was classified as not popular.
We found that @thrinz/pgapi demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.