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

@bumiresourcesminerals/approval-easy-connect

v2.3.1

Published

Library for integration to approval system

Readme

@bumiresourcesminerals/approval-easy-connect

Library untuk integrasi ke Approval System internal BRM.

Package ini biasanya dipakai untuk:

  • validasi token Microsoft Graph
  • ambil session user dari Approval System
  • cek permission menu admin
  • create approval transaction dari aplikasi lain
  • ambil detail/status approval
  • ambil master item form (Form Builder)
  • generate record ID yang sinkron dengan Approval System

Install

npm install @bumiresourcesminerals/approval-easy-connect

Environment Variable

MSGRAPH_ENDPOINT=https://graph.microsoft.com/v1.0/me/
APPROVAL_SYSTEM_ENDPOINT=https://approval-system-host

Quick Start

Contoh seperti pola di FARMS-SAP:

const express = require("express");
const ApprovalSystemAPI = require("@bumiresourcesminerals/approval-easy-connect");

const app = express();

app.use(express.json());
app.use(ApprovalSystemAPI.authenticateToken);

app.get("/api/example", async (req, res) => {
  const api = new ApprovalSystemAPI(req.token);

  return res.json({
    employee_id: req.userInfo.employee_id,
    fullname: req.userInfo.fullname,
    business_entity: req.userInfo.business_entity,
    permissions: req.userInfo.access_permission,
  });
});

Setelah authenticateToken berhasil, object berikut tersedia:

  • req.token
  • req.email
  • req.userInfo

req.userInfo berasal dari endpoint /api/signin Approval System.

Permission Middleware

Contoh route admin:

const ApprovalSystemAPI = require("@bumiresourcesminerals/approval-easy-connect");

const api = new ApprovalSystemAPI();
const menu = "CR";

app.get(
  "/api/capex/admin",
  api.adminCheckPermission(menu, "READ"),
  controller.History
);

Rule permission saat ini:

  • READ menerima user dengan permission READ atau WRITE
  • WRITE hanya menerima user dengan permission WRITE

Jadi kalau endpoint hanya baca data, pakai:

api.adminCheckPermission(menu, "READ")

Kalau endpoint mutasi data, pakai:

api.adminCheckPermission(menu, "WRITE")

Contoh Penggunaan Seperti SAP

Contoh create record + create approval seperti di FARMS-SAP:

const ApprovalSystemAPI = require("@bumiresourcesminerals/approval-easy-connect");

async function createProduct(req, Product, session) {
  const api = new ApprovalSystemAPI(req.token);
  const userInfo = req.userInfo;

  const recordId = await api.GetRecordId({
    model: Product,
    type_record: "FRM",
    business_code: userInfo.business_entity,
    department: "ICT",
    document_name: "SAPPRD",
    column_name: "record_id",
    session,
    maxAttempts: 20,
  });

  await api.createApproval({
    form_code: "SAPPRD",
    form_submit_id: recordId,
    custom_approval: [],
    approval_context: {
      request_type: "NEW",
      category: "MATERIAL",
      amount: 150000000,
      plant: "BRM",
    },
    notification: {
      description: "SAP Product Upload",
    },
  });

  return recordId;
}

Contoh ambil detail/status approval:

const api = new ApprovalSystemAPI(req.token);

const detail = await api.getApprovalDetail(recordId);
const status = await api.getApprovalStatus(recordId);

API Reference

new ApprovalSystemAPI(token)

Membuat instance API client.

Parameter:

  • token: string Token bearer Microsoft Graph yang juga dikirim ke Approval System lewat header x-access-token.

ApprovalSystemAPI.authenticateToken(req, res, next)

Middleware auth.

Perilaku:

  • baca header x-access-token
  • call MSGRAPH_ENDPOINT
  • call /api/signin ke Approval System
  • simpan hasil ke req.userInfo

api.adminCheckPermission(menu, typePermission)

Middleware permission untuk route admin.

Parameter:

  • menu: string Kode menu approval, contoh: CR, TA, SAPPRD
  • typePermission: string Nilai yang didukung: READ atau WRITE

api.createApproval(data)

POST ke /api/approval.

Parameter:

  • data: object

Payload minimum yang umum dipakai:

  • form_code: string
  • form_submit_id: string
  • custom_approval: string[]
  • approval_context?: object
  • notification: object
  • route_by_employee_id?: stringoptional, routing matrix override (lihat di bawah)

Field lain boleh ikut dikirim sesuai kontrak Approval System yang dipakai aplikasi Anda.

Requestor approval default-nya diambil dari user hasil autentikasi token/session, bukan dari body createApproval. Jadi caller cukup kirim konteks bisnis di approval_context.

Routing override (route_by_employee_id)

Ada beberapa flow di mana orang yang memegang token (= JWT user) bukan subjek hierarki yang seharusnya dipakai untuk routing approval. Contoh:

  • HR admin / dispatcher submit Travel Authority untuk employee lain
  • Admin SR submit Service Request untuk requester lain
  • Buyer submit Bidding untuk akun procurement

Untuk kasus seperti ini, kirim route_by_employee_id di payload. Approval System akan resolve requestorDetail (matrix lookup hierarki) dari employee tersebut, sementara audit & notification metadata tetap dari JWT user.

await api.createApproval({
  form_code: "TA",
  form_submit_id: recordId,
  // Submitted oleh JWT user (= dispatcher Mas Tegar), tapi approval matrix
  // harus follow hierarki traveller (Pak Andi, NIK 20864).
  route_by_employee_id: "20864",
  custom_approval: [],
  approval_context: { cost_code: "CPM", flight_type: "Domestic" },
  notification: { description: "TA atas nama Pak Andi" },
});

Yang terjadi di Approval System Create endpoint:

| Aspek | Sumber | |---|---| | Matrix routing (resolveApprovalRoute, getFormSetting) | route_by_employee_id | | tapproval_hdr.created_by / updated_by | JWT user | | tapproval_dtl.created_by per row | JWT user | | Notification "Submitted by" | JWT user |

Kalau route_by_employee_id tidak dikirim (atau null), routing fallback ke JWT user — perilaku lama untuk caller yang tidak butuh override.

created_by di body (NOT ACTIVE)

Beberapa caller legacy mengirim created_by di body sebagai "routing hint". Field tersebut diabaikan oleh Approval System Create endpoint — tapproval_hdr.created_by selalu di-set dari JWT user. Kalau Anda ingin override routing, gunakan route_by_employee_id (lihat di atas).

approval_context diteruskan apa adanya ke Approval System dan bisa dipakai untuk rule approver dinamis di konfigurasi form approval. Contoh rule di Approval System:

{
  "requestor_approver_rules": [
    {
      "requestors": ["10157", "30123"],
      "approver": ["NIK_TRAVEL_ADMIN"]
    }
  ],
  "conditional_approver_rules": [
    {
      "conditions": [
        {
          "source": "payload",
          "field": "amount",
          "operator": "gte",
          "value": 100000000
        },
        {
          "source": "payload",
          "field": "category",
          "operator": "eq",
          "value": "MATERIAL"
        }
      ],
      "approver": ["NIK_FINANCE_HEAD"]
    }
  ]
}

Dengan payload ini, Approval System akan membaca:

  • requestor session employee_id untuk requestor_approver_rules
  • approval_context.amount
  • approval_context.category

dan menyisipkan approver dari requestor rule serta payload rule yang match.

api.broadcastwa(data)

POST ke /api/broadcastwa.

Parameter:

  • data: object

Umumnya berisi payload broadcast WhatsApp personal.

api.broadcastwaGroup(data)

POST ke /api/broadcastwa/group.

Parameter:

  • data: object

Umumnya berisi payload broadcast WhatsApp group.

api.saveRequestLog(data)

POST ke /api/requestlog.

Parameter:

  • data: object

Field yang biasa dipakai:

  • time_request: Date|string
  • ip: string
  • os: string
  • browser: string
  • method: string
  • url: string
  • nik: string
  • email: string
  • appName: string
  • page: string

api.getBaseUrl(data)

GET ke /api/baseurl.

Parameter:

  • data: object

Query parameter diteruskan apa adanya ke Approval System.

api.rollbackCreateApproval(data)

POST ke /api/approval/rollback.

Parameter:

  • data: object

Field minimum:

  • record_id: string

api.getApprovalDetail(recordId)

GET ke /api/approval/:recordId.

Parameter:

  • recordId: string

api.getApprovalStatus(recordId)

GET ke /api/approval-status/:recordId.

Parameter:

  • recordId: string

api.getUserByEmployeeId(employeeId)

GET ke /api/user/employeeid/:employeeId.

Parameter:

  • employeeId: string

api.getUserByIdRow(id)

GET ke /api/user/idrow/:id.

Parameter:

  • id: string

api.getUserByEmail(email)

GET ke /api/user/email/:email.

Parameter:

  • email: string

api.getUserByBranch(branchids)

GET ke /api/user/branchid/:branchids.

Parameter:

  • branchids: string

api.getUserByJobPosition(id)

GET ke /api/user/jobposition/:id.

Parameter:

  • id: string

api.signIn()

POST ke /api/signin.

Tidak butuh parameter tambahan selain token pada constructor.

api.getOrganization(branchId = null)

GET ke /api/organizations atau /api/organizations/:branchId.

Parameter:

  • branchId?: string|null

api.getFormItems(params)

GET ke /api/form-item. Ambil master item form (m_form_item) yang dikelola di Form Builder (FARMS-Admin). Parameter dikirim sebagai query string.

Parameter:

  • params?: object
    • form_code?: string — filter per form (mis. WP, VWP)
    • branch?: string — filter per branch (mis. CPM)
    • active?: stringtrue | false | all

Return: envelope { code, status, data: [...] }. Tiap item antara lain: column_name, label, input_type, options[], columns[], checkbox (Section/Group), type (Condition), order, mandatory, form_name.

Contoh (service tinggal panggil, lalu loop untuk render form-nya sendiri):

const api = new ApprovalSystemAPI(req.token);
const result = await api.getFormItems({ form_code: "WP", branch: "CPM", active: "true" });
const items = result.data; // group by `checkbox` (Section) → sort `order` → render per `input_type`

api.setRequestorDetail(employee_id, object)

Helper untuk inject hasil getUserByEmployeeId() ke object target.

Parameter:

  • employee_id: string
  • object: object

Output:

  • menambahkan object.requestor_id

api.setApprovalProcess(recordId, object)

Helper untuk inject hasil getApprovalDetail() ke object target.

Parameter:

  • recordId: string
  • object: object

Output:

  • menambahkan object.approval_process_id

api.GetRecordId(data)

Generate record ID baru dan cross-check ke Approval System agar tidak bentrok.

Parameter:

  • data.model: mongoose model
  • data.type_record: string
  • data.business_code: string
  • data.department: string
  • data.document_name: string
  • data.column_name: string
  • data.session: mongoose session
  • data.maxAttempts?: number

Format record ID yang dihasilkan:

{business_code}-{department}-{type_record}-{document_name}{YYMM}{NNNN}

Contoh:

BRM-ICT-FRM-SAPPRD26040001

Notes

  • Package ini mengirim token ke Approval System menggunakan header x-access-token.
  • Permission yang dibaca adalah req.userInfo.access_permission.
  • Untuk endpoint read-only, gunakan READ. User WRITE tetap akan lolos.
  • Untuk endpoint mutasi, gunakan WRITE.