Skip to content

TypeScript/JavaScript library for Frappe REST API

License

Notifications You must be signed in to change notification settings

git-avc/frappe-js-sdk

 
 

Repository files navigation

frappe-js-sdk

TypeScript/JavaScript library for a Frappe Framework backend.


Features

The library currently supports the following features:

  • 🔐 Authentication - login with username and password
  • 🗄 Database - Get document, get list of documents, get count, create, update and delete documents
  • 📄 File upload
  • 🤙🏻 API calls

We plan to add the following features in the future:

  • 🗝 Authentication with OAuth clients
  • Support for common functions like get_last_doc, exists in the database.

The library uses Axios under the hood to make API calls to your Frappe backend.

Maintainers

Maintainer GitHub Social
Nikhil Kothari nikkothari22 @nik_kothari22
Janhvi Patil janhvipatil @janhvipatil_

Installation

npm install frappe-js-sdk

or

yarn add frappe-js-sdk

Initialising the library

To get started, initialise the library:

import { FrappeApp } from "frappe-js-sdk";
//Add your Frappe backend's URL
const frappe = new FrappeApp("https://test.frappe.cloud")

Authentication

Initialise the auth library

const auth = frappe.auth()

Login a user:

This makes an API call to the /api/method/login endpoint.

auth.loginWithUsernamePassword({ username: "admin", password: "my-password" })
    .then(response => console.log("Logged in"))
    .catch(error => console.error(error))

Get currently logged in user:

This makes an API call to the /api/method/frappe.auth.get_logged_user endpoint.

auth.getLoggedInUser()
    .then(user => console.log(`User ${user} is logged in.`))
    .catch(error => console.error(error))

Logout:

This makes an API call to the /api/method/logout endpoint.

auth.logout()
    .then(() => console.log("Logged out."))
    .catch(error => console.error(error))

Database

Initialise the database library

const db = frappe.db()

Fetch document using document name

db.getDoc("DocType", "My DocType Name")
    .then(doc => console.log(doc))
    .catch(error => console.error(error))

Fetch list of documents

db.getDocList("DocType")
    .then(docs => console.log(docs))
    .catch(error => console.error(error))

Optionally, a second argument can be provided to filter, sort, limit and paginate results.

db.getDocList("DocType", {
        /** Fields to be fetched */
        fields: ["name", "creation"],
        /** Filters to be applied - SQL AND operation */
        filters: [["creation", ">", "2021-10-09"]],
        /** Filters to be applied - SQL OR operation */
        orFilters: [],
        /** Fetch from nth document in filtered and sorted list. Used for pagination  */
        limit_start: 5,
        /** Number of documents to be fetched. Default is 20  */
        limit: 10,
        /** Sort results by field and order  */
        orderBy: {
            field: "creation",
            order: 'desc'
        },
        /** Fetch documents as a dictionary */
        asDict: false
    })
    .then(docs => console.log(docs))
    .catch(error => console.error(error))

Type declarations are available for the second argument in the source code.

Fetch number of documents with filters

const filters = [["creation", ">", "2021-10-09"]];
const useCache = true /** Default is false - Optional **/
const debug = false /** Default is false - Optional **/

db.getCount("DocType", filters, cache, debug)
    .then(count => console.log(count))
    .catch(error => console.error(error))

Create a document

To create a new document, pass the name of the DocType and the fields to createDoc.

db.createDoc("My Custom DocType", {
        "name": "Test",
        "test_field": "This is a test field"
    })
    .then(doc => console.log(doc))
    .catch(error => console.error(error))

Update a document

To update an existing document, pass the name of the DocType, name of the document and the fields to be updated to updateDoc.

db.updateDoc("My Custom DocType", "Test", {
        "test_field": "This is an updated test field."
    })
    .then(doc => console.log(doc))
    .catch(error => console.error(error))

Delete a document

To create a new document, pass the name of the DocType and the name of the document to be deleted to deleteDoc.

db.deleteDoc("My Custom DocType", "Test")
    .then(response => console.log(response.message)) // Message will be "ok"
    .catch(error => console.error(error))

Usage with Typescript

The library supports Typescript out of the box. For example, to enforce type on the updateDoc method:

interface TestDoc {
    test_field: string
}
db.updateDoc<TestDoc>("My Custom DocType", "Test", {
        "test_field": "This is an updated test field."
    })

The library also has an inbuilt type FrappeDoc which adds the following fields to your type declarations when you use it with the database methods:

export type FrappeDoc<T> = T & {
  /** User who created the document */
  owner: string;
  /** Date and time when the document was created - ISO format */
  creation: string;
  /** Date and time when the document was last modified - ISO format */
  modified: string;
  /** User who last modified the document */
  modified_by: string;
  idx: number;
  /** 0 - Saved, 1 - Submitted, 2 - Cancelled */
  docstatus: 0 | 1 | 2;
  parent?: any;
  parentfield?: any;
  parenttype?: any;
  /** The primary key of the DocType table */
  name: string;
};

All document responses are returned as an intersection of FrappeDoc and the specified type.

API Calls

Initialise the call library

const call = frappe.call()

Make sure all endpoints are whitelisted (@frappe.whitelist()) in your backend

GET request

Make a GET request to your endpoint with parameters.

const searchParams = {
    doctype: "Currency",
    txt: "IN"
}
call.get('frappe.desk.search_link', searchParams)
    .then(result => console.log(result))
    .catch(error => console.error(error))

POST request

Make a POST request to your endpoint with parameters.

const updatedFields = {
    "doctype": "User",
    "name": "Administrator",
    "fieldname": "interest",
    "value": "Frappe Framework, ERPNext"
}
call.post('frappe.client.set_value', updatedFields)
    .then(result => console.log(result))
    .catch(error => console.error(error))

PUT request

Make a PUT request to your endpoint with parameters.

const updatedFields = {
    "doctype": "User",
    "name": "Administrator",
    "fieldname": "interest",
    "value": "Frappe Framework, ERPNext"
}
call.put('frappe.client.set_value', updatedFields)
    .then(result => console.log(result))
    .catch(error => console.error(error))

DELETE request

Make a DELETE request to your endpoint with parameters.

const documentToBeDeleted = {
    "doctype": "Tag",
    "name": "Random Tag",
}
call.put('frappe.client.delete', documentToBeDeleted)
    .then(result => console.log(result))
    .catch(error => console.error(error))

File Uploads

Initialise the file library

const file = frappe.file()

Upload a file with on progress callback

const myFile; //Your File object

const fileArgs = {
  /** If the file access is private then set to TRUE (optional) */
  "isPrivate": true,
  /** Folder the file exists in (optional) */
  "folder": "Home",
  /** File URL (optional) */
  "file_url": "",
  /** Doctype associated with the file (optional) */
  "doctype": "User",
  /** Docname associated with the file (mandatory if doctype is present) */
  "docname": "Administrator"
}

file.uploadFile(
            myFile, 
            fileArgs, 
            /** Progress Indicator callback function **/
            (completedBytes, totalBytes) => console.log(Math.round((c / t) * 100), " completed")
        )
        .then(() => console.log("File Upload complete"))
        .catch(e => console.error(e))

License

See LICENSE.

About

TypeScript/JavaScript library for Frappe REST API

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 100.0%