{"id":14978469,"url":"https://github.com/codebytere/node-mac-contacts","last_synced_at":"2025-08-21T09:32:47.878Z","repository":{"id":35059370,"uuid":"201668612","full_name":"codebytere/node-mac-contacts","owner":"codebytere","description":"Create, read, update, and delete contacts from users' contacts databases on macOS.","archived":false,"fork":false,"pushed_at":"2024-02-22T02:14:28.000Z","size":307,"stargazers_count":69,"open_issues_count":11,"forks_count":15,"subscribers_count":7,"default_branch":"main","last_synced_at":"2024-04-14T07:25:54.769Z","etag":null,"topics":["contacts","electronjs","macos","node-addon","nodejs"],"latest_commit_sha":null,"homepage":"","language":"Objective-C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codebytere.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2019-08-10T18:31:10.000Z","updated_at":"2024-06-19T01:24:38.653Z","dependencies_parsed_at":"2024-06-19T01:24:26.016Z","dependency_job_id":"0c305ebe-70c7-46a1-8aa8-33545f56dcca","html_url":"https://github.com/codebytere/node-mac-contacts","commit_stats":{"total_commits":86,"total_committers":5,"mean_commits":17.2,"dds":"0.16279069767441856","last_synced_commit":"16ce1885cbd3a5b2515e63f86cd9866b7162131d"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codebytere%2Fnode-mac-contacts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codebytere%2Fnode-mac-contacts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codebytere%2Fnode-mac-contacts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codebytere%2Fnode-mac-contacts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codebytere","download_url":"https://codeload.github.com/codebytere/node-mac-contacts/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":229915635,"owners_count":18144014,"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":["contacts","electronjs","macos","node-addon","nodejs"],"created_at":"2024-09-24T13:57:44.961Z","updated_at":"2024-12-19T22:07:31.763Z","avatar_url":"https://github.com/codebytere.png","language":"Objective-C++","readme":"[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://lbesson.mit-license.org/)\n [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) [![Actions Status](https://github.com/codebytere/node-mac-contacts/workflows/Test/badge.svg)](https://github.com/codebytere/node-mac-contacts/actions)\n\n# node-mac-contacts\n\n## Description\n\n```js\n$ npm i node-mac-contacts\n```\n\nThis Native Node Module allows you to create, read, update, and delete contact from users' contacts databases on macOS.\n\nAll methods invoking the [CNContactStore](https://developer.apple.com/documentation/contacts/cncontactstore) will require authorization, which you can request from users with the `requestAccess` method. You can verify authorization status with `contacts.getAuthStatus()` as outlined below.\n\nIn your app, you should put the reason you're requesting to manipulate user's contacts database in your `Info.plist` like so:\n\n```\n\u003ckey\u003eNSContactsUsageDescription\u003c/key\u003e\n\u003cstring\u003eYour reason for wanting to access the Contact store\u003c/string\u003e\n```\n\nIf you're using macOS 12.3 or newer, you'll need to ensure you have Python installed on your system, as macOS does not bundle it anymore.\n\n**Note:** The `note` field requires the [`com.apple.developer.contacts.notes`](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_contacts_notes) entitlement. Before you submit an app with this entitlement to the App Store, you'll need to get permission to use the entitlement. Request permission using [this form](https://developer.apple.com/contact/request/contact-note-field).\n\n## API\n\n### `contacts.requestAccess()`\n\nReturns `Promise\u003cString\u003e` - Can be one of 'Denied', 'Authorized'.\n\nRequests access to the [CNContactStore](https://developer.apple.com/documentation/contacts/cncontactstore) via a dialog presented to the user.\n\nIf the user has previously denied the request, this method will open the Contacts pane within the Privacy section of System Preferences.\n\n*Note that access permission request prompts will not appear when `requestAccess()` is invoked in embedded terminals such as those found in Visual Studio Code. Run your code from an external terminal such as Terminal.app instead.*\n\n### `contacts.getAuthStatus()`\n\nReturns `String` - Can be one of 'Not Determined', 'Denied', 'Authorized', or 'Restricted'.\n\nChecks the authorization status of the application to access the central Contacts store on macOS.\n\nReturn Value Descriptions: \n* 'Not Determined' - The user has not yet made a choice regarding whether the application may access contact data.\n* 'Not Authorized' - The application is not authorized to access contact data. The user cannot change this application’s status, possibly due to active restrictions such as parental controls being in place.\n* 'Denied' - The user explicitly denied access to contact data for the application.\n* 'Authorized' - The application is authorized to access contact data.\n\nExample Usage:\n\n```js\nconst authStatus = contacts.getAuthStatus()\n\nconsole.log(`Authorization access to contacts is: ${authStatus}`)\n/* prints one of:\n'Not Determined'\n'Denied',\n'Authorized'\n'Restricted'\n*/\n```\n\n### `contacts.getAllContacts([extraProperties])`\n\n* `extraProperties` string[] (optional) - an array of extra contact properties to fetch that can be any of: `jobTitle`, `departmentName`, `organizationName`, `middleName`, `note`, `contactImage`, `contactThumbnailImage`, `instantMessageAddresses`, `socialProfiles`, or `urlAddresses`.\n\nReturns `Array\u003cObject\u003e` - Returns an array of contact objects.\n\nThe returned objects will take the following format:\n\n* `identifier` String - The contact's unique identifier.\n* `firstName` String - The contact's first name, or an empty string ('') if one is not set.\n* `lastName` String - The contact's last name, or an empty string ('') if one is not set.\n* `nickname` String - The contact's nickname, or an empty string ('') if one is not set.\n* `birthday` String - The contact's birthday in YYYY-MM-DD format, or an empty string ('') if one is not set.\n* `phoneNumbers` String[] - An array of phone numbers as strings in [E.164 format](https://en.wikipedia.org/wiki/E.164).\n* `emailAddresses` String[] - An array of email addresses as strings.\n* `postalAddresses` String[] - An array of postal as strings.\n* `jobTitle` String (optional) - The contact's job title.\n* `departmentName` String (optional) - The name of the department associated with the contact.\n* `organizationName` String (optional) - The name of the organization associated with the contact.\n* `middleName` String (optional) - The contact's middle name.\n* `note` String (optional) - The note associated with the contact.\n* `contactImage` Buffer (optional) - a Buffer representation of the contact's profile picture.\n* `contactThumbnailImage` Buffer (optional) - a Buffer representation of The thumbnail version of the contact’s profile picture.\n* `socialProfiles` Object[] (optional) - An array of labeled social profiles for a contact.\n* `instantMessageAddresses` Object[] (optional) - An array of labeled IM addresses for the contact.\n* `urlAddresses` String[] (optional) - An array of url addresses as strings.\n\nThis method will return an empty array (`[]`) if access to Contacts has not been granted.\n\nExample Usage:\n\n```js\nconst allContacts = contacts.getAllContacts()\n\nconsole.log(allContacts[0])\n/* Prints:\n[\n  { \n    firstName: 'Jonathan',\n    lastName: 'Appleseed',\n    nickname: 'Johnny',\n    birthday: '1970-01-01',\n    phoneNumbers: [ +11234566789' ],\n    emailAddresses: [ 'johnny@appleseed.com' ],\n    postalAddresses: [ '123 Pine Tree Way\\nBlack Oak, Arkansas 72414\\nUnited States' ]\n  }\n]\n*/\n```\n\n### `contacts.getContactsByName(name[, extraProperties])`\n\n* `name` String (required) - The first, middle, last, or full name of a contact.\n* `extraProperties` String[] (optional) - an array of extra contact properties to fetch that can be any of: `jobTitle`, `departmentName`, `organizationName`, `middleName`, `note`, `contactImage`, `contactThumbnailImage`, `instantMessageAddresses`, `socialProfiles`, or `urlAddresses`.\n\nReturns `Array\u003cObject\u003e` - Returns an array of contact objects where either the first or last name of the contact matches `name`.\n\nIf a contact's full name is 'Shelley Vohr', I could pass 'Shelley', 'Vohr', or 'Shelley Vohr' as `name`.\n\nThe returned object will take the following format:\n\n* `identifier` String - The contact's unique identifier.\n* `firstName` String - The contact's first name, or an empty string ('') if one is not set.\n* `lastName` String - The contact's last name, or an empty string ('') if one is not set.\n* `nickname` String - The contact's nickname, or an empty string ('') if one is not set.\n* `birthday` String - The contact's birthday in YYYY-MM-DD format, or an empty string ('') if one is not set.\n* `phoneNumbers` String[] - An array of phone numbers as strings in [E.164 format](https://en.wikipedia.org/wiki/E.164).\n* `emailAddresses` String[] - An array of email addresses as strings.\n* `postalAddresses` String[] - An array of postal as strings.\n* `jobTitle` String (optional) - The contact's job title.\n* `departmentName` String (optional) - The name of the department associated with the contact.\n* `organizationName` String (optional) - The name of the organization associated with the contact.\n* `middleName` String (optional) - The contact's middle name.\n* `note` String (optional) - The note associated with the contact.\n* `contactImage` Buffer (optional) - a Buffer representation of the contact's profile picture.\n* `contactThumbnailImage` Buffer (optional) - a Buffer representation of The thumbnail version of the contact’s profile picture.\n* `socialProfiles` Object[] (optional) - An array of labeled social profiles for a contact.\n* `instantMessageAddresses` Object[] (optional) - An array of labeled IM addresses for the contact.\n* `urlAddresses` String[] (optional) - An array of url addresses as strings.\n\nThis method will return an empty array (`[]`) if access to Contacts has not been granted.\n\nExample Usage:\n\n```js\nconst contacts = contacts.getContactsByName('Appleseed')\n\nconsole.log(contacts)\n/* Prints:\n[\n  { \n    firstName: 'Jonathan',\n    lastName: 'Appleseed',\n    nickname: 'Johnny',\n    birthday: '1970-01-01',\n    phoneNumbers: [ +11234566789' ],\n    emailAddresses: [ 'johnny@appleseed.com' ],\n    postalAddresses: [ '123 Pine Tree Way\\nBlack Oak, Arkansas 72414\\nUnited States' ]\n  }\n]\n*/\n```\n\n### `contacts.addNewContact(contact)`\n\n* `contact` Object\n  * `firstName` String (required) - The first name of the contact.\n  * `lastName` String (optional) - The last name of the contact.\n  * `nickname` String (optional) - The nickname for the contact.\n  * `jobTitle` String (optional) - The contact's job title.\n  * `departmentName` String (optional) - The name of the department associated with the contact.\n  * `organizationName` String (optional) - The name of the organization associated with the contact.\n  * `middleName` String (optional) - The contact's middle name.\n  * `birthday` String (optional) - The birthday for the contact in `YYYY-MM-DD` format.\n  * `phoneNumbers` Array\\\u003cString\\\u003e (optional) - The phone numbers for the contact, as strings in [E.164 format](https://en.wikipedia.org/wiki/E.164): `+14155552671` or `+442071838750`.\n  * `emailAddresses` Array\\\u003cString\\\u003e (optional) - The email addresses for the contact, as strings.\n  * `urlAddresses` Array\\\u003cString\\\u003e (optional) - The url addresses for the contact, as strings.\n\nReturns `Boolean` - whether the contact information was created successfully.\n\nCreates and save a new contact to the user's contacts database.\n\nThis method will return `false` if access to Contacts has not been granted.\n\nExample Usage:\n\n```js\nconst success = contacts.addNewContact({\n  firstName: 'William',\n  lastName: 'Grapeseed',\n  nickname: 'Billy',\n  birthday: '1990-09-09',\n  phoneNumbers: ['+1234567890'],\n  emailAddresses: ['billy@grapeseed.com'],\n})\n\nconsole.log(`New contact was ${success ? 'saved' : 'not saved'}.`)\n```\n\n### `contacts.deleteContact({ identifier, name })`\n\n* `identifier` String (optional) - The contact's unique identifier.\n* `name` String (optional) - The first, middle, last, or full name of a contact.\n\nReturns `Boolean` - whether the contact was deleted successfully.\n\nDeletes a contact from the user's contacts database.\n\nIf a contact's full name is 'Shelley Vohr', I could pass 'Shelley', 'Vohr', or 'Shelley Vohr' as `name`.\nHowever, you should take care to specify `name` to such a degree that you can be confident the first contact to be returned from a predicate search is the contact you intend to delete.\n\nThis method will return `false` if access to Contacts has not been granted.\n\nExample Usage:\n\n```js\nconst name = 'Jonathan Appleseed'\nconst deleted = contacts.deleteContact(name)\n\nconsole.log(`Contact ${name} was ${deleted ? 'deleted' : 'not deleted'}.`)\n```\n\n### `contacts.updateContact(contact)`\n\n* `contact` Object\n  * `firstName` String (required) - The first name of the contact.\n  * `lastName` String (optional) - The last name of the contact.\n  * `nickname` String (optional) - The nickname for the contact.\n  * `jobTitle` String (optional) - The contact's job title.\n  * `departmentName` String (optional) - The name of the department associated with the contact.\n  * `organizationName` String (optional) - The name of the organization associated with the contact.\n  * `middleName` String (optional) - The contact's middle name.\n  * `birthday` String (optional) - The birthday for the contact in `YYYY-MM-DD` format.\n  * `phoneNumbers` Array\\\u003cString\\\u003e (optional) - The phone numbers for the contact, as strings in [E.164 format](https://en.wikipedia.org/wiki/E.164): `+14155552671` or `+442071838750`.\n  * `emailAddresses` Array\\\u003cString\\\u003e (optional) - The email addresses for the contact, as strings.\n  * `urlAddresses` Array\\\u003cString\\\u003e (optional) - The url addresses for the contact, as strings.\n\nReturns `Boolean` - whether the contact was updated successfully.\n\nUpdates a contact to the user's contacts database.\n\nYou should take care to specify parameters to the `contact` object to such a degree that you can be confident the first contact to be returned from a predicate search is the contact you intend to update.\n\nThis method will return `false` if access to Contacts has not been granted.\n\nExample Usage:\n\n```js\n// Change contact's nickname from Billy -\u003e Will\nconst updated = contacts.updateContact({\n  firstName: 'William',\n  lastName: 'Grapeseed',\n  nickname: 'Will',\n})\n\nconsole.log(`Contact was ${updated ? 'updated' : 'not updated'}.`)\n```\n\n### `contacts.listener`\n\nThis module exposes an `EventEmitter`, which can be used to listen to potential changes to the `CNContactStore`. When a contact is changed either with methods contained in this module, or manually by a user, the `contact-changed` event will be emitted with one parameter `external`. This signifies whether or not the change to contact data originated outside the current app.\n\nOwing to the underlying architecture of this module, the listener must be manually managed; before use you must initialize it with `listener.setup()` and when you are finished listening for events you must remove it with `listener.remove()`. To check if a listener is currently active, use `listener.isListening()`.\n\nExample Usage:\n\n```js\nconst { listener, addNewContact } = require('node-mac-contacts')\n\nlistener.setup()\n\naddNewContact({\n  firstName: 'William',\n  lastName: 'Grapeseed',\n  nickname: 'Billy',\n  birthday: '1990-09-09',\n  phoneNumbers: ['+1234567890'],\n  emailAddresses: ['billy@grapeseed.com'],\n})\n\nlistener.once('contact-changed', (external) =\u003e {\n  console.log(`A contact was changed ${external ? 'outside of' : 'within'} this app!`)\n  listener.remove()\n})\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodebytere%2Fnode-mac-contacts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodebytere%2Fnode-mac-contacts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodebytere%2Fnode-mac-contacts/lists"}