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

ejsc-ma-api

v1.0.9

Published

Native Hardware Bridge API for 365 Mini App environment. Facilitates real-time, asynchronous communication with system-level APIs including Media, UI, and Location services.

Readme

@ejsc/ma-api 🔌

npm version License: MIT

The Universal Bridge API for 365 Mini App Native Communication.

ejsc-ma-api là lớp cầu nối (Bridge) chính thức giữa môi trường Web của Mini App và các tính năng Native của Super App host. Thư viện bọc lại window.ejsc với đầy đủ TypeScript types và cung cấp các helper async/await giúp lập trình viên thao tác với phần cứng (Camera, GPS, Biometrics...) một cách an toàn và tinh giản.


Cài đặt

npm install ejsc-ma-apis

Cách dùng

Sync — callback-based

Proxy trực tiếp tới window.ejsc. Dùng khi cần tương thích với native bridge pattern.

import { apisSync } from 'ejsc-ma-apis';

apisSync.getSystemInfo({
  success: (res) => console.log(res.platform),
  fail: (err) => console.error(err),
});

Async — Promise-based

Tất cả method đều trả về Promise. Khuyến nghị dùng với async/await.

import { apisAsync } from 'ejsc-ma-apis';

const info = await apisAsync.getSystemInfo();
console.log(info.platform); // 'ios' | 'android' | ...

Import async-only entry

import apisAsync from 'ejsc-ma-apis/async';

Default export

import apis from 'ejsc-ma-apis';
// apis === apisSync

Package Exports

| Entry | Mô tả | |-------|-------| | ejsc-ma-apis | Main — export apis, apisSync, apisAsync, tất cả types | | ejsc-ma-apis/async | Async-only — default export là apisAsync |


API Reference

Tất cả method đều có 2 dạng:

  • Sync: nhận options kèm success, fail, complete callbacks
  • Async: nhận options thuần, trả về Promise

System

getSystemInfo(options?)

Lấy thông tin hệ thống và thiết bị.

const res = await apisAsync.getSystemInfo();
// hoặc chỉ lấy một số field
const res = await apisAsync.getSystemInfo({ keys: ['platform', 'locale'] });

| Options | Type | Mô tả | |---------|------|-------| | keys | Array<keyof IEjscGetSystemInfoData> | Các field cần lấy. Bỏ trống = lấy tất cả |

| Response | Type | Mô tả | |----------|------|-------| | app | string | Tên super app | | brand | string | Nhãn hiệu thiết bị | | currentBattery | number | Mức pin (0–1) | | model | string | Model thiết bị | | platform | 'ios' \| 'android' \| 'macos' \| 'windows' \| 'web' \| 'native' | Nền tảng | | system | 'Android' \| 'iOS' \| 'iPhone OS' \| 'iPadOS' | Hệ điều hành | | version | string | Phiên bản OS | | hostVersion | string | Phiên bản host app | | runtimeVersion | string | Phiên bản runtime | | freeStorage | number | Dung lượng trống (bytes) | | screenWidth / screenHeight | number | Kích thước màn hình (px) | | windowWidth / windowHeight | number | Kích thước cửa sổ (px) | | titleBarHeight / statusBarHeight | number | Chiều cao bar (px) | | locale | 'vi' \| 'en' | Ngôn ngữ | | deviceId | string | UUID thiết bị |


exitMiniApp(options)

Thoát mini app, quay về host app.

await apisAsync.exitMiniApp();

confirmBeforeExit(options)

Bật/tắt xác nhận trước khi thoát.

await apisAsync.confirmBeforeExit({ enable: true, message: 'Bạn có chắc muốn thoát?' });

| Options | Type | Mô tả | |---------|------|-------| | enable | boolean | Bắt buộc. Bật hay tắt xác nhận | | message | string | Nội dung popup xác nhận |


Navigation Bar

setNavigationBar(options?)

Tùy chỉnh thanh điều hướng.

await apisAsync.setNavigationBar({
  title: 'Trang chủ',
  titleBarColor: '#ffffff',
  theme: 'dark',
});

| Options | Type | Mô tả | |---------|------|-------| | title | string | Tiêu đề | | image | string | URL ảnh thay tiêu đề | | titleBarColor | string | Màu nền thanh | | borderBottomColor | string | Màu viền dưới | | reset | boolean | Reset về mặc định | | theme | 'dark' \| 'light' | Giao diện |


Storage

setStorage(options)

await apisAsync.setStorage({ key: 'token', data: 'abc123' });

| Options | Type | Mô tả | |---------|------|-------| | key | string | Bắt buộc | | data | string \| Record<string, any> | Bắt buộc |


getStorage(options)

const { data } = await apisAsync.getStorage({ key: 'token' });

removeStorage(options)

await apisAsync.removeStorage({ key: 'token' });

clearStorage()

Xóa toàn bộ storage.

await apisAsync.clearStorage();

getStorageInfo()

const { keys, currentSize, limitSize } = await apisAsync.getStorageInfo();

| Response | Type | Mô tả | |----------|------|-------| | keys | string[] | Danh sách key đang lưu | | currentSize | number | Dung lượng đang dùng (bytes) | | limitSize | number | Dung lượng tối đa (bytes) |


Clipboard

getClipboard()

const { text } = await apisAsync.getClipboard();

setClipboard(options)

await apisAsync.setClipboard({ text: 'nội dung cần copy' });

UI Dialogs

alert(options?)

await apisAsync.alert({ title: 'Thông báo', content: 'Thao tác thành công', buttonText: 'OK' });

confirm(options?)

const { confirm } = await apisAsync.confirm({
  title: 'Xác nhận',
  content: 'Bạn có chắc không?',
  confirmButtonText: 'Có',
  cancelButtonText: 'Không',
});

| Response | Type | Mô tả | |----------|------|-------| | confirm | boolean | true nếu bấm xác nhận |


prompt(options?)

const { ok, inputValue } = await apisAsync.prompt({
  title: 'Nhập tên',
  placeholder: 'Họ và tên...',
  okButtonText: 'Xác nhận',
  cancelButtonText: 'Hủy',
});

| Response | Type | Mô tả | |----------|------|-------| | ok | boolean | true nếu bấm OK | | inputValue | string | Giá trị người dùng nhập |


showToast(options?)

await apisAsync.showToast({ type: 'success', content: 'Lưu thành công', duration: 2000 });

| Options | Type | Mô tả | |---------|------|-------| | type | 'success' \| 'fail' \| 'info' | Loại toast | | content | string | Nội dung | | buttonText | string | Text nút | | duration | number | Thời gian hiển thị (ms) |


showLoading(options?) / hideLoading()

await apisAsync.showLoading({ content: 'Đang tải...' });
// ... xử lý xong
await apisAsync.hideLoading();

showActionSheet(options)

const { index } = await apisAsync.showActionSheet({
  title: 'Chọn hành động',
  items: ['Chỉnh sửa', 'Xóa'],
  cancelButton: 'Hủy',
  destructiveBtnIndex: 1,
});

| Response | Type | Mô tả | |----------|------|-------| | index | number | Vị trí item được chọn (0-indexed) |


Media

chooseImage(options?)

const { filePaths, tempFiles } = await apisAsync.chooseImage({
  count: 3,
  sourceType: ['album', 'camera'],
  includeBase64: false,
});

| Options | Type | Mô tả | |---------|------|-------| | count | number | Số ảnh tối đa. Mặc định: 1 | | sourceType | Array<'camera' \| 'album'> | Nguồn ảnh | | includeBase64 | boolean | Kèm data base64 |

| Response | Type | Mô tả | |----------|------|-------| | filePaths | string[] | Đường dẫn các ảnh | | tempFiles | IEjscChooseImageTempFile[] | Chi tiết từng ảnh (path, size, width, height, data?) |


previewImage(options)

await apisAsync.previewImage({
  urls: ['https://...', 'https://...'],
  current: 0,
  enablesavephoto: true,
});

saveImage(options)

await apisAsync.saveImage({ url: 'https://...' });

getImageInfo(options)

const { width, height, orientation, type } = await apisAsync.getImageInfo({ src: 'https://...' });

| Response | Type | |----------|------| | width / height | number | | orientation | 'up' \| 'down' \| 'left' \| 'right' \| 'up-mirrored' \| 'down-mirrored' \| 'left-mirrored' \| 'right-mirrored' | | path | string | | type | string |


compressImage(options)

const { filePaths } = await apisAsync.compressImage({
  filePaths: ['/tmp/img.jpg'],
  options: { quality: 80, maxWidth: 1024 },
});

Network

request(options)

HTTP request — dùng thay cho fetch trong môi trường mini app (chỉ hỗ trợ HTTPS).

const res = await apisAsync.request({
  url: 'https://api.example.com/data',
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  data: { key: 'value' },
  timeout: 10000,
  dataType: 'JSON',
});

| Options | Type | Mô tả | |---------|------|-------| | url | string | Bắt buộc | | method | string | Mặc định: 'GET' | | headers | Record<string, string> | | | data | any | Request body | | timeout | number | ms. Mặc định: 30000 | | dataType | string | 'JSON', 'text', 'base64', 'arraybuffer' | | includeHeader | boolean | Kèm headers trong response | | stepup | boolean | |


downloadFile(options)

const { filePath } = await apisAsync.downloadFile({
  url: 'https://example.com/file.pdf',
  headers: { Authorization: 'Bearer ...' },
});

uploadFile(options)

const res = await apisAsync.uploadFile({
  url: 'https://api.example.com/upload',
  fileName: 'file',
  filePath: '/tmp/img.jpg',
  fileType: 'image',
  formData: { userId: '123' },
});

| Options | Type | Mô tả | |---------|------|-------| | url | string | Bắt buộc | | fileName | string | Bắt buộc. Key trong form data | | fileType | 'image' \| 'video' \| 'audio' | Bắt buộc | | filePath | string | Đường dẫn file đơn | | filePaths | string[] | Upload nhiều file | | formData | Record<string, any> | Các field form khác | | method | string | Mặc định: 'POST' | | headers | Record<string, string> | |


Auth & User

getAuthCode(options?)

const { authCode, authSuccessScopes } = await apisAsync.getAuthCode({
  scopes: ['profile', 'phone'],
});

| Response | Type | Mô tả | |----------|------|-------| | authCode | string | Mã xác thực | | authSuccessScopes | Array<'profile' \| 'phone' \| 'email'> | Scope được cấp | | authErrorScopes | Record<string, string> | Scope bị lỗi |


getUserInfo()

const { avatar, name, gender } = await apisAsync.getUserInfo();

getSetting()

const { authSetting } = await apisAsync.getSetting();
// authSetting: Record<string, boolean>

openSetting()

Mở trang cài đặt quyền của mini app.

const { authSetting } = await apisAsync.openSetting();

openAppSetting()

Mở cài đặt ứng dụng của thiết bị cho host app.

await apisAsync.openAppSetting();

Navigation

openDeeplink(options)

const success = await apisAsync.openDeeplink({ url: 'myapp://screen/home' });

openPublicDeepLink(options)

const success = await apisAsync.openPublicDeepLink({
  url: 'https://example.com/path',
  inAppBrowser: true,
});

openNativeAppStore(options)

await apisAsync.openNativeAppStore({
  appleStoreId: '123456789',
  googlePlayId: 'com.example.app',
});

shareApp(options?)

await apisAsync.shareApp({
  title: 'Chia sẻ app',
  desc: 'Mô tả ngắn',
  path: '/pages/home',
});

Device

makePhoneCall(options)

await apisAsync.makePhoneCall({ number: '0901234567' });

choosePhoneContact()

Mở danh bạ để chọn liên hệ.

const { full_name, phone_number } = await apisAsync.choosePhoneContact();

getLocation(options?)

const { latitude, longitude, accuracy } = await apisAsync.getLocation({
  type: 1, // 0 = WiFi (thấp), 1 = GPS (cao)
  cacheTimeout: 30,
});

scan(options?)

Quét QR / barcode.

const result = await apisAsync.scan({ hideAlbum: false });
// result: string — nội dung mã quét được

addCalendarEvent(options)

await apisAsync.addCalendarEvent({
  title: 'Họp nhóm',
  startDate: '2026-04-01T09:00:00.000Z',
  endDate: '2026-04-01T10:00:00.000Z',
  location: 'Phòng họp A',
  allDay: false,
  notes: 'Mang theo laptop',
});

reportAnalytics(name, options?)

await apisAsync.reportAnalytics('button_click', { screen: 'home', buttonId: 'cta' });

Payment

initPayment(options)

const transactionId = await apisAsync.initPayment({
  paymentApiKey: 'your-api-key',
  orderInfo: {
    amount: 100000,
    currency: 'VND',
    description: 'Thanh toán đơn hàng',
    orderId: 'ORD-001',
    referenceId: 'REF-001',
    secureHash: 'hash...',
    orderInfo: {
      customerName: 'Nguyễn Văn A',
      customerPhone: '0901234567',
      items: [{ itemName: 'Sản phẩm A', quantity: 1, unitPrice: 100000 }],
    },
  },
});

| IEjscOrderInfo | Type | Mô tả | |-----------------|------|-------| | amount | number | Số tiền | | currency | string | Đơn vị tiền tệ | | description | string | Mô tả | | orderId | string | Mã đơn hàng | | referenceId | string | Mã tham chiếu | | secureHash | string | Hash bảo mật | | orderInfo | IEjscCustomerOrderInfo | Thông tin khách hàng | | paymentMethodCode | string | Mã phương thức thanh toán | | providerId | string | ID nhà cung cấp | | platformCode | string | Mã nền tảng | | returnURL | string | URL callback | | providerData | string | Dữ liệu nhà cung cấp |


showPaymentMethod(options)

const method = await apisAsync.showPaymentMethod({
  paymentApiKey: 'your-api-key',
  amount: 100000,
});

| Response (IEjscPaymentMethod) | Type | |-------------------------------|------| | code | string | | type | string | | name | string | | providerId | string | | providerName | string | | paymentMethodId | string | | iconUrl | string | | category | string | | platformPaymentMethodId | string |


getDefaultPaymentMethod(options)

const method = await apisAsync.getDefaultPaymentMethod({ paymentApiKey: 'your-api-key' });
// method: IEjscPaymentMethod

Beacon

startBeaconDiscovery(options?)

await apisAsync.startBeaconDiscovery({ UUID: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' });

stopBeaconDiscovery()

await apisAsync.stopBeaconDiscovery();

getBeaconDiscoveryStatus()

const status = await apisAsync.getBeaconDiscoveryStatus();
// status: 'initializing' | 'started' | 'stopped'

onBeaconDiscovery(callback) / offBeaconDiscovery(callback)

Event-based — không có dạng async.

const handler = (data: IEjscBeaconInfo) => {
  console.log(data.type, data.data);
};

apisSync.onBeaconDiscovery(handler);
// ...
apisSync.offBeaconDiscovery(handler);

| IEjscBeaconInfo | Type | |-----------------|------| | type | 'iBeacon' \| 'Eddystone' \| string | | data | any |


BioMetrics

Tất cả method nằm trong namespace bioMetrics.

bioMetrics.isSupported()

const { isSupported, mode, error } = await apisAsync.bioMetrics.isSupported();

bioMetrics.localAuth(options)

Xác thực sinh trắc học.

const success = await apisAsync.bioMetrics.localAuth({ content: 'Xác nhận danh tính' });
// success: boolean

bioMetrics.keyExists()

const exists = await apisAsync.bioMetrics.keyExists();
// exists: boolean

bioMetrics.createKey()

const { publicKey } = await apisAsync.bioMetrics.createKey();

bioMetrics.createSignature(options)

const { signature } = await apisAsync.bioMetrics.createSignature({
  challenge: 'random-challenge-string',
  content: 'Xác nhận giao dịch',
});

bioMetrics.deleteKey()

const success = await apisAsync.bioMetrics.deleteKey();
// success: boolean

Cloud

Types dùng cho upload file lên cloud storage. Không được wire vào apisSync/apisAsync — dùng trực tiếp với bridge tùy platform.

import type { IEjscCloudUploadFile, IEjscCloudUploadFileAsync } from 'ejsc-ma-apis';

| Type | Mô tả | |------|-------| | IEjscCloudUploadFileOptions | { fileType, fileName, filePath } | | IEjscCloudUploadFileData | any | | IEjscCloudUploadFile | Sync function type | | IEjscCloudUploadFileAsync | Async function type |


Types

Tất cả types được export từ main entry:

import type {
  IEjsc,
  IEjscGetSystemInfoData,
  IEjscRequestAsync,
  IEjscPaymentMethod,
  IEjscBeaconInfo,
  IEjscOptionsWithCallback,
  IEjscPlatform,
  IEjscSystem,
  IEjscLocale,
} from 'ejsc-ma-apis';

Common types

| Type | Mô tả | |------|-------| | IEjscOptionsWithCallback<Options, Success> | Base type cho tất cả callback options | | IEjscPlatform | 'ios' \| 'android' \| 'macos' \| 'windows' \| 'web' \| 'native' | | IEjscSystem | 'Android' \| 'iOS' \| 'iPhone OS' \| 'iPadOS' | | IEjscLocale | 'en' \| 'vi' | | IEjsc | Interface đầy đủ của window.ejsc |


� 2026 EJSC Technology. All rights reserved.


© 2026 EJSC Technology. All rights reserved.