{"_id":"@beninfintech/frappe","_rev":"3-755f80adbe31b9ea40b6abf28f49bf9a","name":"@beninfintech/frappe","dist-tags":{"latest":"2.0.2"},"versions":{"1.12.1":{"name":"@beninfintech/frappe","version":"1.12.1","keywords":["Frappe"],"author":{"name":"Wilfried K. AGO","email":"wilfried.ago@bftgroup.co"},"license":"MIT","_id":"@beninfintech/frappe@1.12.1","maintainers":[{"name":"wilfriedago","email":"kirinago66@gmail.com"}],"homepage":"https://github.com/beninfintech/frappe-js-sdk#readme","bugs":{"url":"https://github.com/beninfintech/frappe-js-sdk/issues"},"dist":{"shasum":"0eda58389d764fc02491183c260a90d0865ec10a","tarball":"https://registry.npmjs.org/@beninfintech/frappe/-/frappe-1.12.1.tgz","fileCount":7,"integrity":"sha512-ASj8n1HfCInJMIX+3Xea5ac4f2d4lu/ED8RWWerT/TUE+45Vb0z8KUJ/ytOjqCna3nssTDRlS8widmvDcRNBnQ==","signatures":[{"sig":"MEUCIF4MM5nW9WQresQowuGcFjV2svJcu3YB3crRIsc3XbBiAiEA9ORQhAJSnJO6sgHsrVSSHku3Yo3Kli7aZJuFaPQbgmU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":77300},"type":"module","_from":"file:beninfintech-frappe-1.12.1.tgz","types":"./dist/index.d.mts","exports":{".":"./dist/index.mjs","./vite":"./dist/vite/index.mjs","./package.json":"./package.json"},"scripts":{"dev":"tsdown --watch","lint":"eslint","test":"vitest","build":"tsdown","start":"tsx src/index.ts","publint":"publint","release":"changelogen --output CHANGELOG.md --release --push","lint:fix":"eslint --fix","changelog":"changelogen --output CHANGELOG.md","typecheck":"tsc"},"_npmUser":{"name":"wilfriedago","email":"kirinago66@gmail.com"},"_resolved":"/private/var/folders/t9/_bg75gpd30s_yrb0gdpvylzh0000gn/T/58de381a90b568afaf27122e754abaee/beninfintech-frappe-1.12.1.tgz","_integrity":"sha512-ASj8n1HfCInJMIX+3Xea5ac4f2d4lu/ED8RWWerT/TUE+45Vb0z8KUJ/ytOjqCna3nssTDRlS8widmvDcRNBnQ==","repository":{"url":"git+https://github.com/beninfintech/frappe-js-sdk.git","type":"git"},"_npmVersion":"10.9.4","description":"TypeScript/JavaScript client for Frappe Framework REST API","directories":{},"lint-staged":{"*":"eslint --fix"},"sideEffects":false,"_nodeVersion":"22.22.1","dependencies":{"axios":"^1.15.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","jiti":"^2.6.1","vite":"^8.0.8","bumpp":"^11.0.1","eslint":"^10.2.0","tsdown":"^0.21.8","tsnapi":"^0.1.2","vitest":"^4.1.4","publint":"^0.3.18","@antfu/ni":"^30.0.0","typescript":"^6.0.2","@types/node":"^25.6.0","changelogen":"^0.6.2","lint-staged":"^16.4.0","@antfu/utils":"^9.3.0","simple-git-hooks":"^2.13.1","@antfu/eslint-config":"^8.2.0","eslint-plugin-format":"^2.0.1"},"peerDependencies":{"vite":">=5.0.0"},"simple-git-hooks":{"pre-commit":"pnpm i --frozen-lockfile --ignore-scripts --offline && pnpm run build && npx lint-staged"},"peerDependenciesMeta":{"vite":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/frappe_1.12.1_1776171558210_0.1160564441353158","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@beninfintech/frappe","version":"2.0.0","keywords":["Frappe"],"author":{"name":"Wilfried K. AGO","email":"wilfried.ago@bftgroup.co"},"license":"MIT","_id":"@beninfintech/frappe@2.0.0","maintainers":[{"name":"wilfriedago","email":"kirinago66@gmail.com"}],"homepage":"https://github.com/beninfintech/frappe-js-sdk#readme","bugs":{"url":"https://github.com/beninfintech/frappe-js-sdk/issues"},"dist":{"shasum":"f65f6f92c4d30d1b0150ee962d0c347248dbd51d","tarball":"https://registry.npmjs.org/@beninfintech/frappe/-/frappe-2.0.0.tgz","fileCount":7,"integrity":"sha512-gwuvfeotQ/ODno6kM1YZhU4j+w/iT02A5n3d8UoPh8p1SiQdZqKUO8v3ZEsOaci6ghySFy+HjDoEg+uesGinGg==","signatures":[{"sig":"MEYCIQCn30Dtvldg4i7iNDIhakcvsIPLUAdhwbtLEFFVFxetGAIhAOlnV1OH2W3JmKBYNbZgIea2nK74oxs3+EBoIyzLHQLl","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":77327},"type":"module","_from":"file:beninfintech-frappe-2.0.0.tgz","types":"./dist/index.d.mts","exports":{".":"./dist/index.mjs","./vite":"./dist/vite/index.mjs","./package.json":"./package.json"},"scripts":{"dev":"tsdown --watch","lint":"eslint","test":"vitest","build":"tsdown","start":"tsx src/index.ts","publint":"publint","release":"changelogen --output CHANGELOG.md --release --push","lint:fix":"eslint --fix","changelog":"changelogen --output CHANGELOG.md","typecheck":"tsc"},"_npmUser":{"name":"wilfriedago","email":"kirinago66@gmail.com"},"_resolved":"/private/var/folders/t9/_bg75gpd30s_yrb0gdpvylzh0000gn/T/0a7c78e013740f3ea7f03e3ec8ccb9cd/beninfintech-frappe-2.0.0.tgz","_integrity":"sha512-gwuvfeotQ/ODno6kM1YZhU4j+w/iT02A5n3d8UoPh8p1SiQdZqKUO8v3ZEsOaci6ghySFy+HjDoEg+uesGinGg==","repository":{"url":"git+https://github.com/beninfintech/frappe-js-sdk.git","type":"git"},"_npmVersion":"10.9.4","description":"TypeScript/JavaScript client for Frappe Framework REST API","directories":{},"lint-staged":{"*":"eslint --fix"},"sideEffects":false,"_nodeVersion":"22.22.1","dependencies":{"axios":"^1.15.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","jiti":"^2.6.1","vite":"^8.0.8","bumpp":"^11.0.1","eslint":"^10.2.0","tsdown":"^0.21.8","tsnapi":"^0.1.2","vitest":"^4.1.4","publint":"^0.3.18","@antfu/ni":"^30.0.0","typescript":"^6.0.2","@types/node":"^25.6.0","changelogen":"^0.6.2","lint-staged":"^16.4.0","@antfu/utils":"^9.3.0","simple-git-hooks":"^2.13.1","@antfu/eslint-config":"^8.2.0","eslint-plugin-format":"^2.0.1"},"peerDependencies":{"vite":">=5.0.0"},"simple-git-hooks":{"pre-commit":"pnpm i --frozen-lockfile --ignore-scripts --offline && pnpm run build && npx lint-staged"},"peerDependenciesMeta":{"vite":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/frappe_2.0.0_1776171836936_0.8838489767679307","host":"s3://npm-registry-packages-npm-production"}},"2.0.2":{"name":"@beninfintech/frappe","type":"module","version":"2.0.2","description":"TypeScript/JavaScript client for Frappe Framework REST API","author":{"name":"Wilfried K. AGO","email":"wilfried.ago@bftgroup.co"},"license":"MIT","homepage":"https://github.com/beninfintech/frappe-js-sdk#readme","repository":{"type":"git","url":"git+https://github.com/beninfintech/frappe-js-sdk.git"},"bugs":{"url":"https://github.com/beninfintech/frappe-js-sdk/issues"},"keywords":["Frappe"],"sideEffects":false,"exports":{".":"./dist/index.mjs","./vite":"./dist/vite/index.mjs","./package.json":"./package.json"},"types":"./dist/index.d.mts","peerDependencies":{"vite":">=5.0.0"},"peerDependenciesMeta":{"vite":{"optional":true}},"dependencies":{"axios":"^1.15.0"},"devDependencies":{"@antfu/eslint-config":"^8.2.0","@antfu/ni":"^30.0.0","@antfu/utils":"^9.3.0","@types/node":"^25.6.0","bumpp":"^11.0.1","changelogen":"^0.6.2","eslint":"^10.2.0","eslint-plugin-format":"^2.0.1","jiti":"^2.6.1","lint-staged":"^16.4.0","publint":"^0.3.18","simple-git-hooks":"^2.13.1","tsdown":"^0.21.8","tsnapi":"^0.1.2","tsx":"^4.21.0","typescript":"^6.0.2","vite":"^8.0.8","vitest":"^4.1.4"},"simple-git-hooks":{"pre-commit":"pnpm i --frozen-lockfile --ignore-scripts --offline && pnpm run build && npx lint-staged"},"lint-staged":{"*":"eslint --fix"},"scripts":{"dev":"tsdown --watch","build":"tsdown","test":"vitest","typecheck":"tsc","changelog":"changelogen --output CHANGELOG.md","publint":"publint","release":"changelogen --output CHANGELOG.md --release --push","start":"tsx src/index.ts","bumpp":"bumpp","lint":"eslint","lint:fix":"eslint --fix"},"_id":"@beninfintech/frappe@2.0.2","_integrity":"sha512-GLDFfWJp81F36wzkGNeMQUAjMqmgW5zveeqk+eiKeyTtSLiRLQRQbBHLXkxx6opn6PRkYh6daJlbuSuOXARngw==","_resolved":"/private/var/folders/t9/_bg75gpd30s_yrb0gdpvylzh0000gn/T/fc16e5aed6a84f831d9b1e69a2f7b058/beninfintech-frappe-2.0.2.tgz","_from":"file:beninfintech-frappe-2.0.2.tgz","_nodeVersion":"22.22.1","_npmVersion":"10.9.4","dist":{"integrity":"sha512-GLDFfWJp81F36wzkGNeMQUAjMqmgW5zveeqk+eiKeyTtSLiRLQRQbBHLXkxx6opn6PRkYh6daJlbuSuOXARngw==","shasum":"57dd02c0c2c7944e6ec364458b7c1d61ee52f5c3","tarball":"https://registry.npmjs.org/@beninfintech/frappe/-/frappe-2.0.2.tgz","fileCount":7,"unpackedSize":77693,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDYVy7sLR5/e9CxOq1V8aDjuViH9F5OjydvBPXC/T2zTAiEAjwD4E0Xf5Et2NXRi1mhki7j2fzjbvAAhpaa7vwewp2E="}]},"_npmUser":{"name":"wilfriedago","email":"kirinago66@gmail.com"},"directories":{},"maintainers":[{"name":"wilfriedago","email":"kirinago66@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/frappe_2.0.2_1776174257818_0.5696621020742214"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-14T12:59:18.153Z","modified":"2026-04-14T13:44:18.053Z","1.12.1":"2026-04-14T12:59:18.348Z","2.0.0":"2026-04-14T13:03:57.099Z","2.0.2":"2026-04-14T13:44:17.954Z"},"bugs":{"url":"https://github.com/beninfintech/frappe-js-sdk/issues"},"author":{"name":"Wilfried K. AGO","email":"wilfried.ago@bftgroup.co"},"license":"MIT","homepage":"https://github.com/beninfintech/frappe-js-sdk#readme","keywords":["Frappe"],"repository":{"type":"git","url":"git+https://github.com/beninfintech/frappe-js-sdk.git"},"description":"TypeScript/JavaScript client for Frappe Framework REST API","maintainers":[{"name":"wilfriedago","email":"kirinago66@gmail.com"}],"readme":"# @beninfintech/frappe\n\nTypeScript/JavaScript library for a [Frappe Framework](https://frappeframework.com) backend.\n\n<br />\n<p align=\"center\">\n  <a href=\"https://github.com/beninfintech/frappe-js-sdk\"><img src=\"https://img.shields.io/maintenance/yes/2026?style=flat-square\" alt=\"Maintenance status\" /></a>\n  <a href=\"https://github.com/beninfintech/frappe-js-sdk\"><img src=\"https://img.shields.io/github/license/beninfintech/frappe-js-sdk?style=flat-square\" alt=\"License\" /></a>\n  <a href=\"https://www.npmjs.com/package/@beninfintech/frappe\"><img src=\"https://img.shields.io/npm/v/@beninfintech/frappe?style=flat-square\" alt=\"npm version\" /></a>\n  <a href=\"https://www.npmjs.com/package/@beninfintech/frappe\"><img src=\"https://img.shields.io/npm/dw/@beninfintech/frappe?style=flat-square\" alt=\"npm downloads\" /></a>\n</p>\n\n## Features\n\n- REST API client (auth, database CRUD, file upload, RPC calls)\n- Vite plugin suite for Frappe app development (proxy, build config, Jinja boot data, DocType type generation)\n- Full TypeScript support\n- Token-based and cookie-based authentication\n\nThe library uses [Axios](https://axios-http.com) under the hood to make API calls to your Frappe backend.\n\n## Installation\n\n```bash\npnpm add @beninfintech/frappe\n```\n\n## REST API Client\n\n### Initializing the library\n\n```ts\nimport { FrappeApp } from '@beninfintech/frappe'\n\nconst frappe = new FrappeApp('https://test.frappe.cloud')\n```\n\nWith token-based authentication (OAuth bearer tokens or API key/secret pairs):\n\n```ts\nimport { FrappeApp } from '@beninfintech/frappe'\n\nconst frappe = new FrappeApp('https://test.frappe.cloud', {\n  useToken: true,\n  token: () => localStorage.getItem('token') ?? '',\n  type: 'Bearer'\n})\n```\n\n### Authentication\n\n```ts\nconst auth = frappe.auth()\n\n// Login\nauth\n  .loginWithUsernamePassword({ username: 'admin', password: 'my-password' })\n  .then((response) => console.log('Logged in'))\n  .catch((error) => console.error(error))\n\n// Get currently logged in user\nauth\n  .getLoggedInUser()\n  .then((user) => console.log(`User ${user} is logged in.`))\n  .catch((error) => console.error(error))\n\n// Logout\nauth\n  .logout()\n  .then(() => console.log('Logged out.'))\n  .catch((error) => console.error(error))\n\n// Forget password\nauth\n  .forgetPassword('example@example.com')\n  .then(() => console.log('Password Reset Email Sent!'))\n  .catch(() => console.error('Account not found.'))\n```\n\n### Database\n\n```ts\nconst db = frappe.db()\n```\n\n#### Fetch a document\n\n```ts\ndb.getDoc('ToDo', 'TODO-001')\n  .then((doc) => console.log(doc))\n  .catch((error) => console.error(error))\n```\n\n#### Fetch a list of documents\n\n```ts\ndb.getDocList('ToDo', {\n  fields: ['name', 'creation'],\n  filters: [['creation', '>', '2021-10-09']],\n  orFilters: [],\n  limit_start: 5,\n  limit: 10,\n  orderBy: {\n    field: 'creation',\n    order: 'desc'\n  },\n  groupBy: 'name',\n  asDict: false\n})\n  .then((docs) => console.log(docs))\n  .catch((error) => console.error(error))\n```\n\n#### Create, update, delete\n\n```ts\n// Create\ndb.createDoc('ToDo', { description: 'New task' })\n\n// Update\ndb.updateDoc('ToDo', 'TODO-001', { description: 'Updated task' })\n\n// Delete\ndb.deleteDoc('ToDo', 'TODO-001')\n\n// Rename\ndb.renameDoc('ToDo', 'Old Name', 'New Name')\n```\n\n#### Other operations\n\n```ts\n// Get document count with filters\ndb.getCount('ToDo', [['status', '=', 'Open']])\n\n// Get / set field values\ndb.getValue('ToDo', 'description', [['name', '=', 'TODO-001']])\ndb.setValue('ToDo', 'TODO-001', 'status', 'Closed')\n\n// Single doctype value\ndb.getSingleValue('Website Settings', 'home_page')\n\n// Submit / cancel workflow\ndb.submit(doc)\ndb.cancel('Sales Invoice', 'INV-001')\n```\n\n### API Calls\n\n```ts\nconst call = frappe.call()\n\n// GET\ncall.get('frappe.desk.search_link', { doctype: 'Currency', txt: 'IN' })\n\n// POST\ncall.post('frappe.client.set_value', { doctype: 'User', name: 'Administrator', fieldname: 'interest', value: 'Frappe' })\n\n// PUT\ncall.put('frappe.client.set_value', { doctype: 'User', name: 'Administrator', fieldname: 'interest', value: 'Frappe' })\n\n// DELETE\ncall.delete('frappe.client.delete', { doctype: 'Tag', name: 'Random Tag' })\n```\n\n### File Uploads\n\n```ts\nconst file = frappe.file()\n\nfile.uploadFile(\n  myFile,\n  {\n    isPrivate: true,\n    folder: 'Home',\n    doctype: 'User',\n    docname: 'Administrator',\n    fieldname: 'image'\n  },\n  (completedBytes, totalBytes) => console.log(Math.round((completedBytes / totalBytes) * 100), '% completed')\n)\n```\n\n### TypeScript Support\n\nAll methods accept generic type parameters:\n\n```ts\ninterface MyDoc {\n  description: string\n  status: 'Open' | 'Closed'\n}\n\nconst doc = await db.getDoc<MyDoc>('ToDo', 'TODO-001')\n// doc is FrappeDoc<MyDoc> with full autocomplete\n```\n\n## Vite Plugin\n\nThe package includes a Vite plugin suite at `@beninfintech/frappe/vite` for Frappe app frontend development.\n\n### Quick start\n\nUse the unified `frappe()` plugin which composes all sub-plugins:\n\n```ts\nimport { frappe } from '@beninfintech/frappe/vite'\n\nexport default defineConfig({\n  plugins: [\n    ...frappe({\n      frontendRoute: '/app'\n    })\n  ]\n})\n```\n\n### Options\n\n```ts\nfrappe({\n  // Frontend route path. Passed to the build plugin and defined as __FRONTEND_ROUTE__ global.\n  frontendRoute: '/app',\n\n  // Dev proxy plugin. Default: true.\n  // Pass false to disable, or an options object to configure.\n  proxy: true,\n\n  // Jinja boot data injection. Default: true.\n  // Injects Frappe boot data via Jinja templates in production builds.\n  jinja: true,\n\n  // Build config plugin. Default: true.\n  // Auto-detects output directory, base URL, and copies index.html for Frappe routing.\n  build: true,\n\n  // DocType TypeScript type generation. Default: disabled.\n  // Pass options to enable.\n  types: {\n    input: { myapp: ['loan_management', 'savings_management'] }\n  }\n})\n```\n\n### Using plugins individually\n\nEach plugin is also exported separately for fine-grained control:\n\n```ts\nimport { buildConfig, frappeProxy, frappeTypes, jinjaBootData } from '@beninfintech/frappe/vite'\n\nexport default defineConfig({\n  plugins: [\n    frappeProxy({ port: 8080 }),\n    jinjaBootData(),\n    buildConfig({ frontendRoute: '/app', sourcemap: false }),\n    frappeTypes({ input: { myapp: ['*'] } })\n  ]\n})\n```\n\n### Proxy plugin\n\nProxies Frappe backend routes (`/api`, `/app`, `/assets`, etc.) to your local Frappe dev server.\n\n```ts\nfrappeProxy({\n  // Vite dev server port. Auto-calculated from Frappe's webserver_port if omitted.\n  port: 8080,\n  // Regex pattern for routes to proxy. Default covers all standard Frappe routes.\n  source: '^/(desk|app|login|api|assets|files|private)'\n})\n```\n\nThe plugin reads `common_site_config.json` from the bench to determine the backend port, or uses the `FRAPPE_WEB_SERVER_PORT` environment variable.\n\n### Build config plugin\n\nConfigures Vite's build output for Frappe app deployment.\n\n```ts\nbuildConfig({\n  // Output directory. Auto-detected from Frappe app structure if omitted.\n  outDir: '../myapp/public/frontend',\n  // Path to copy index.html to for Frappe's www/ routing.\n  indexHtmlPath: '../myapp/www/app.html',\n  // Or derive it from the frontend route:\n  frontendRoute: '/app',\n  // Base URL for assets. Auto-detected from outDir if omitted.\n  baseUrl: '/assets/myapp/frontend/',\n  // Sourcemaps. Default: true.\n  sourcemap: true,\n  // Empty output directory before build. Default: true.\n  emptyOutDir: true\n})\n```\n\n### Jinja boot data plugin\n\nInjects Frappe boot data into the HTML during production builds via Jinja templates:\n\n```ts\njinjaBootData()\n```\n\nThis transforms the built `index.html` to include:\n\n```html\n<script>\n  {% for key in boot %}\n  window[\"{{ key }}\"] = {{ boot[key] | tojson }};\n  {% endfor %}\n</script>\n```\n\n### DocType type generation plugin\n\nScans Frappe DocType JSON schemas from the bench and generates TypeScript declaration files.\n\n```ts\nfrappeTypes({\n  // Map of Frappe app name to list of module names.\n  // Use '*' to include all modules from an app.\n  input: {\n    myapp: ['loan_management', 'savings_management'],\n    frappe: ['*']\n  },\n  // Output directory. Default: 'src/types/doctypes'.\n  output: 'src/types/doctypes',\n  // Override bench path. Auto-detected by default.\n  benchPath: '/path/to/bench'\n})\n```\n\nThis generates:\n\n```\nsrc/types/doctypes/\n  _base.d.ts           # DocType, ChildDocType base interfaces\n  loan-management.d.ts  # One file per module\n  index.d.ts           # Re-exports everything\n```\n\nThen in your app code:\n\n```ts\nimport { type LoanApplication } from '~/types/doctypes'\n```\n\n### Utility functions\n\nThe following Frappe bench utility functions are also exported from `@beninfintech/frappe/vite`:\n\n```ts\nimport {\n  findAppName,\n  findAppsFolder,\n  findBenchPath,\n  getCommonSiteConfig,\n  getConfig,\n  getInstalledAppSites\n} from '@beninfintech/frappe/vite'\n```\n\n## License\n\nSee [LICENSE](./LICENSE).\n","readmeFilename":"README.md"}