{"id":18264025,"url":"https://github.com/linusbolls/splid-js","last_synced_at":"2025-04-04T20:31:31.411Z","repository":{"id":190178957,"uuid":"682157353","full_name":"LinusBolls/splid-js","owner":"LinusBolls","description":"A feature-complete NPM package for the  Splid (https://splid.app) API","archived":false,"fork":false,"pushed_at":"2025-04-01T19:02:28.000Z","size":565,"stargazers_count":10,"open_issues_count":1,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-04-01T20:22:23.965Z","etag":null,"topics":["api","api-client","splid","splid-js","splidjs"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LinusBolls.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-23T15:04:46.000Z","updated_at":"2025-04-01T19:02:31.000Z","dependencies_parsed_at":"2023-12-08T18:29:29.509Z","dependency_job_id":"480478f1-70da-4ed2-a9ba-1cd1b7e9b9d5","html_url":"https://github.com/LinusBolls/splid-js","commit_stats":null,"previous_names":["linusbolls/splid-js"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LinusBolls%2Fsplid-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LinusBolls%2Fsplid-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LinusBolls%2Fsplid-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LinusBolls%2Fsplid-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LinusBolls","download_url":"https://codeload.github.com/LinusBolls/splid-js/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246709926,"owners_count":20821297,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","api-client","splid","splid-js","splidjs"],"created_at":"2024-11-05T11:13:31.310Z","updated_at":"2025-04-04T20:31:31.404Z","avatar_url":"https://github.com/LinusBolls.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"docs/banner.svg\" width=\"100%\" /\u003e\n\n# splid.js\n\na feature-complete typescript client for the Splid (https://splid.app) API.\nSplid is a free mobile app for keeping track of expenses among friend groups.\nthis package is not officially associated with Splid.\n\nlast updated Nov 7 2024\n\n## Install\n\ninstall the package:\n\n```bash\nnpm install splid-js\n```\n\n## Examples\n\n```typescript\n// basic usage\nimport { SplidClient } from 'splid-js';\n\nasync function main() {\n  const splid = new SplidClient();\n\n  const inviteCode = 'PWJ E2B P7A';\n\n  const groupRes = await splid.group.getByInviteCode(inviteCode);\n\n  const groupId = groupRes.result.objectId;\n\n  const groupInfo = await splid.groupInfo.getOneByGroup(groupId);\n  const members = await splid.person.getAllByGroup(groupId);\n  const expensesAndPayments = await splid.entry.getAllByGroup(groupId);\n\n  const balance = SplidClient.getBalance(\n    members,\n    expensesAndPayments,\n    groupInfo\n  );\n  const suggestedPayments = SplidClient.getSuggestedPayments(balance);\n\n  console.log(balance, suggestedPayments);\n}\nmain();\n```\n\n```typescript\n// parsing the returned data\nimport { SplidClient } from 'splid-js';\n\nconst formatCurrency = (amount: number, currency: string) =\u003e {\n  return amount.toLocaleString(undefined, {\n    style: 'currency',\n    currency,\n    minimumFractionDigits: 2,\n    maximumFractionDigits: 2,\n  });\n};\n\nconst getEntryDescription = (\n  entry: SplidJs.Entry,\n  members: SplidJs.Person[]\n) =\u003e {\n  const primaryPayer = members.find((i) =\u003e i.GlobalId === entry.primaryPayer)!;\n\n  for (const item of entry.items) {\n    const totalAmount = item.AM;\n    // a map of a userId to their share (how much they profit from the expense). the shares are floats between 0 and 1 and their sum is exactly 1.\n    const userIdToShareMap = item.P.P;\n\n    const profiteers = Object.entries(userIdToShareMap).map(\n      ([userId, share]) =\u003e {\n        const user = members.find((i) =\u003e i.GlobalId === userId)!;\n\n        const shareText = formatCurrency(\n          totalAmount * share,\n          entry.currencyCode\n        );\n        return user.name + ' (' + shareText + ')';\n      }\n    );\n    const profiteersText = profiteers.join(', ');\n\n    const totalText = formatCurrency(totalAmount, entry.currencyCode);\n\n    if (entry.isPayment) {\n      const description =\n        primaryPayer.name + ' sent ' + totalText + ' to ' + profiteersText;\n\n      return description;\n    } else {\n      const description =\n        primaryPayer.name + ' payed ' + totalText + ' for ' + profiteersText;\n\n      return description;\n    }\n  }\n};\n\nasync function main() {\n  const splid = new SplidClient();\n\n  const inviteCode = 'PWJ E2B P7A';\n\n  const groupRes = await splid.group.getByInviteCode(inviteCode);\n\n  const groupId = groupRes.result.objectId;\n\n  const members = await splid.person.getAllByGroup(groupId);\n  const expensesAndPayments = await splid.entry.getAllByGroup(groupId);\n\n  for (const entry of expensesAndPayments) {\n    console.log(getEntryDescription(entry, members));\n  }\n}\nmain();\n```\n\n```typescript\n// updating group properties\nconst groupInfo = await splid.groupInfo.getOneByGroup(groupId);\n\ngroupInfo.name = 'Modified Group 🔥';\n\ngroupInfo.customCategories.push('Pharmaceuticals 💊');\n\n// setting the currency exchange rates to the most recent values\ngroupInfo.currencyRates = await splid.getCurrencyRates();\n\ngroupInfo.defaultCurrencyCode = 'EUR';\n\nawait splid.groupInfo.set(groupInfo);\n```\n\n```typescript\n// updating group wallpaper (NodeJs)\nimport fs from 'fs';\n\nconst file = await fs.promises.readFile('image.png');\n\nconst uploadRes = await splid.file.upload(file);\n\ngroupInfo.wallpaperID = uploadRes.dataID;\n```\n\n```typescript\n// updating person properties\nconst members = await splid.person.getAllByGroup(groupId);\n\nconst linus = members.find((i) =\u003e i.name === 'Linus');\n\nlinus.name = 'Alex';\nlinus.initials = 'A';\n\nawait splid.person.set(linus);\n```\n\n```typescript\n// updating entry properties\nconst entries = await splid.entry.getAllByGroup(groupId);\n\nconst pizzaEntries = entries.filter((i) =\u003e\n  i.title.toLowerCase().includes('pizza')\n);\n\nfor (const entry of pizzaEntries) {\n  // setting the category of an entry\n  entry.category = {\n    type: 'custom',\n    originalName: 'Italian Food 🍕',\n  };\n  // setting the date of an entry\n  if (!entry.date) {\n    entry.date = {\n      __type: 'Date',\n      iso: new Date().toISOString(),\n    };\n  } else {\n    entry.date.iso = new Date().toISOString();\n  }\n}\nawait splid.entry.set(pizzaEntries);\n```\n\n```typescript\n// converting all foreign currency entries to the default currency of the group\n\nconst foreignCurrencyEntries = expensesAndPayments.filter(\n  (i) =\u003e !i.isPayment \u0026\u0026 i.currencyCode !== groupInfo.defaultCurrencyCode\n);\n\nfor (const entry of foreignCurrencyEntries) {\n  const factor =\n    groupInfo.currencyRates[entry.currencyCode] /\n    groupInfo.currencyRates[groupInfo.defaultCurrencyCode];\n\n  entry.currencyCode = groupInfo.defaultCurrencyCode;\n\n  for (const item of entry.items) {\n    item.AM = item.AM * factor;\n  }\n  for (const [payerId, amount] of Object.entries(entry.secondaryPayers ?? {})) {\n    entry.secondaryPayers[payerId] = amount * factor;\n  }\n}\nawait splid.entry.set(foreignCurrencyEntries);\n```\n\n```typescript\n// deleting entries\nconst entries = await splid.entry.getAllByGroup(groupId);\n\nconst entry = entries[0];\n\nentry.isDeleted = true;\n\nawait splid.entry.set(entry);\n```\n\n```typescript\n// creating a group\nawait splid.group.create('🎉 Ramber Zamber', ['Linus', 'Laurin', 'Oskar']);\n```\n\n```typescript\n// creating a basic expense\nawait splid.entry.expense.create(\n  {\n    groupId,\n    payers: [linus.GlobalId],\n    title: 'döner',\n  },\n  {\n    amount: 10,\n    // equivalent to equivalent to { [laurin.GlobalId]: 0.5, [oskar.GlobalId]: 0.5 }\n    profiteers: [laurin.GlobalId, oskar.GlobalId],\n  }\n);\n```\n\n```typescript\n// creating an expense with multiple items\nawait splid.entry.expense.create(\n  {\n    groupId,\n    payers: [linus.GlobalId],\n    title: 'shopping spree 😌',\n  },\n  [\n    {\n      title: 'gucci belt',\n      amount: 10,\n      profiteers: [laurin.GlobalId],\n    },\n    {\n      title: 'drippy hat',\n      amount: 15,\n      profiteers: [oskar.GlobalId],\n    },\n  ]\n);\n```\n\n```typescript\n// creating an expense with multiple payers (both pay half)\nawait splid.entry.expense.create(\n  {\n    groupId,\n    // equivalent to { [linus.GlobalId]: 5, [oskar.GlobalId]: 5 }\n    payers: [linus.GlobalId, oskar.GlobalId],\n    title: 'döner',\n  },\n  {\n    amount: 10,\n    profiteers: [linus.GlobalId, oskar.GlobalId],\n  }\n);\n```\n\n```typescript\n// creating an expense with unevenly split payers (oskar pays 3€)\nawait splid.entry.expense.create(\n  {\n    groupId,\n    // equivalent to { [linus.GlobalId]: 7, [oskar.GlobalId]: 3 }\n    payers: [linus.GlobalId, { id: oskar.GlobalId, amount: 3 }],\n    title: 'shopping',\n  },\n  {\n    amount: 10,\n    profiteers: [laurin.GlobalId],\n  }\n);\n```\n\n```typescript\n// creating an expense with unevenly split profiteers (oskar owes 2.25€)\nawait splid.entry.expense.create(\n  {\n    groupId,\n    payers: [linus.GlobalId],\n    title: 'shopping',\n  },\n  {\n    amount: 10,\n    // equivalent to { [linus.GlobalId]: 3 / 4, [oskar.GlobalId]: 1 / 4 }\n    profiteers: [linus.GlobalId, { id: oskar.GlobalId, share: 1 / 4 }],\n  }\n);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinusbolls%2Fsplid-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flinusbolls%2Fsplid-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinusbolls%2Fsplid-js/lists"}