{"id":18695342,"url":"https://github.com/smartthingscommunity/smartapp-sdk-nodejs","last_synced_at":"2025-04-05T02:12:41.818Z","repository":{"id":34068454,"uuid":"166849709","full_name":"SmartThingsCommunity/smartapp-sdk-nodejs","owner":"SmartThingsCommunity","description":"Javascript/NodeJS SDK to create SmartThings SmartApps","archived":false,"fork":false,"pushed_at":"2024-04-25T20:22:49.000Z","size":2973,"stargazers_count":138,"open_issues_count":9,"forks_count":81,"subscribers_count":88,"default_branch":"main","last_synced_at":"2024-04-25T21:31:58.318Z","etag":null,"topics":["aws-lambda","javascript","nodejs","nodejs-sdk","sdk","sdk-js","smartapp","smartthings"],"latest_commit_sha":null,"homepage":"https://smartthings.developer.samsung.com/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SmartThingsCommunity.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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-01-21T17:00:59.000Z","updated_at":"2024-06-18T18:17:20.513Z","dependencies_parsed_at":"2023-02-17T09:30:48.584Z","dependency_job_id":"faee6e9e-e1e5-4376-8cc3-7433edc8f20f","html_url":"https://github.com/SmartThingsCommunity/smartapp-sdk-nodejs","commit_stats":{"total_commits":212,"total_committers":16,"mean_commits":13.25,"dds":0.7169811320754718,"last_synced_commit":"1480453c793e2bad836a9532b96cb70c788f07c7"},"previous_names":[],"tags_count":77,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SmartThingsCommunity%2Fsmartapp-sdk-nodejs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SmartThingsCommunity%2Fsmartapp-sdk-nodejs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SmartThingsCommunity%2Fsmartapp-sdk-nodejs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SmartThingsCommunity%2Fsmartapp-sdk-nodejs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SmartThingsCommunity","download_url":"https://codeload.github.com/SmartThingsCommunity/smartapp-sdk-nodejs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247276189,"owners_count":20912288,"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":["aws-lambda","javascript","nodejs","nodejs-sdk","sdk","sdk-js","smartapp","smartthings"],"created_at":"2024-11-07T11:14:40.745Z","updated_at":"2025-04-05T02:12:41.797Z","avatar_url":"https://github.com/SmartThingsCommunity.png","language":"JavaScript","readme":"# SmartThings SmartApp Node.js SDK\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://www.npmjs.com/package/@smartthings/smartapp\"\u003e\u003cimg src=\"https://badgen.net/npm/v/@smartthings/smartapp\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://www.npmjs.com/package/@smartthings/smartapp\"\u003e\u003cimg src=\"https://badgen.net/npm/license/@smartthings/smartapp\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://codecov.io/gh/SmartThingsCommunity/smartapp-sdk-nodejs\"\u003e\u003cimg src=\"https://codecov.io/gh/SmartThingsCommunity/smartapp-sdk-nodejs/branch/main/graph/badge.svg\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://status.badgen.net/\"\u003e\u003cimg src=\"https://badgen.net/xo/status/@smartthings/smartapp\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://lgtm.com/projects/g/SmartThingsCommunity/smartapp-sdk-nodejs/context:javascript\"\u003e\u003cimg alt=\"Language grade: JavaScript\" src=\"https://img.shields.io/lgtm/grade/javascript/g/SmartThingsCommunity/smartapp-sdk-nodejs.svg?logo=lgtm\u0026logoWidth=18\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://lgtm.com/projects/g/SmartThingsCommunity/smartapp-sdk-nodejs/alerts/\"\u003e\u003cimg alt=\"Total alerts\" src=\"https://img.shields.io/lgtm/alerts/g/SmartThingsCommunity/smartapp-sdk-nodejs.svg?logo=lgtm\u0026logoWidth=18\"/\u003e\u003c/a\u003e\n\u003ca href=\"https://snyk.io/test/github/SmartThingsCommunity/smartapp-sdk-nodejs?targetFile=package.json\"\u003e\u003cimg src=\"https://snyk.io/test/github/SmartThingsCommunity/smartapp-sdk-nodejs/badge.svg?targetFile=package.json\" alt=\"Known Vulnerabilities\" data-canonical-src=\"https://snyk.io/test/github/SmartThingsCommunity/smartapp-sdk-nodejs?targetFile=package.json\" style=\"max-width:100%;\"\u003e\u003c/a\u003e\n\u003ca href=\"https://smartthingsdev.slack.com/messages/CG595N08N\"\u003e\u003cimg src=\"https://badgen.net/badge//smartthingsdev?icon=slack\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## Reference Documentation\n\nFor a detailed look at the API, check out the [reference documentation](docs/index.md).\n\n## Getting Started\n\n\u003e**Version 2.0 Release**\n\u003e\n\u003eThis major release is not fully backwards compatible with version 1.X, though for most SmartApps the changes required should be relatively minor. The major non-backwards compatible changes include:\n\u003e* Methods that return lists now return arrays instead of objects with the properties `items` and `_links`.\n\u003e* Axios is now used rather than request-promise-native for making HTTP calls, resulting in changes to the error\nobjects thrown when exceptions occur.\n\u003e\n\u003eSee the [Version 2.0.0 release notes](docs/V2_RELEASE_NOTES.md) for more information.\n\nThis SDK includes a set of Node.js libraries for building Webhook and AWS Lambda SmartApps, and interacting with the public SmartThings API.\n\nHighlights include:\n\n- ✅ Javascript API hides details of REST calls and authentication.\n- ✅ Event handler framework dispatches lifecycle events to named event handlers.\n- ✅ Configuration page API simplifies page definition.\n- ✅ Integrated [i18n](https://www.npmjs.com/package/i18n) framework provides configuration page localization.\n- ✅ [Winston](https://www.npmjs.com/package/winston) framework manges log messages.\n- ✅ Context Store plugins – easily scale access token management (and more) to support many users.\n  - ✅ [AWS DynamoDB](https://github.com/SmartThingsCommunity/dynamodb-context-store-nodejs) plugin ([usage](#amazon-aws-dynamodb))\n  - ✅ [Firebase Cloud Firestore](https://github.com/SmartThingsCommunity/firestore-context-store-nodejs) plugin ([usage](#firebase-cloud-firestore))\n\n### What is a SmartApp?\n\nSmartApps are custom applications that execute outside of the SmartThings Platform. All of the SmartApp execution will happen on the server or Lambda that you control. The complexity of execution and the number of expected users will need to be examined to understand the hardware or execution requirements your app needs to handle. Your application will respond to lifecycle events sent from SmartThings to perform actions on behalf of your users and will execute any scheduled tasks that you have created in the SmartApp. Creating a SmartApp allows you to control and get status notifications from SmartThings devices using the SmartThings API.\n\n#### Hosting Your SmartApp\n\nThere are two distinct options for hosting your SmartApp: AWS Lambda and Webhook.\n\n- **AWS Lambda** SmartApps are hosted in the Amazon Web Services cloud and are invoked by ARN instead of a public-DNS address.\n\n- **Webhook** SmartApps are any publicly-accessible web server that will receive a POST request payload.\n\nTo learn more about SmartApps, including choosing the best hosting solution for your SmartApp, visit the [SmartApp developer documentation](https://developer.smartthings.com/docs/connected-services/smartapp-basics).\n\n## Installation\n\n```bash\nnpm i @smartthings/smartapp --save\n```\n\n## Importing\n\n`Node.js`:\n\n```javascript\nconst SmartApp = require('@smartthings/smartapp')\n```\n\nOr `ES2015`+:\n\n```javascript\nimport SmartApp from '@smartthings/smartapp'\n```\n\n## Examples\n\nThe example SmartApp below is the equivalent of a simple Rule (if contact sensor opens/closes, turn lights on/off) which is easily achieved via our Rules API. It is given here as a brief showcase of the SDK, and is not meant to be a good candidate for a SmartApp.\n\n\u003eBefore hosting your own Automation, be sure to check out [Rules](https://developer.smartthings.com/docs/automations/rules). When all services and Device features involved in a Rule are local, Rules execute locally on a Hub, allowing you to benefit from greater speed, stability, and security than cloud-reliant solutions.\n\n### Running as a Web Service\n\nTo run your SmartApp with an HTTP server, such as Express.js:\n\n```javascript\nconst SmartApp = require('@smartthings/smartapp');\nconst express = require('express');\nconst server = express();\nconst PORT = 8080;\n\n\n/* Define the SmartApp */\nconst smartapp = new SmartApp()\n    .enableEventLogging(2) // logs all lifecycle event requests and responses as pretty-printed JSON. Omit in production\n    .page('mainPage', (context, page, configData) =\u003e {\n        page.section('sensors', section =\u003e {\n            section\n                .deviceSetting('contactSensor')\n                .capabilities(['contactSensor'])\n        });\n        page.section('lights', section =\u003e {\n            section\n                .deviceSetting('lights')\n                .capabilities(['switch'])\n                .permissions('rx')\n                .multiple(true);\n        });\n    })\n    // Called for both INSTALLED and UPDATED lifecycle events if there is no separate installed() handler\n    .updated(async (context, updateData) =\u003e {\n        await context.api.subscriptions.delete() // clear any existing configuration\n        await context.api.subscriptions.subscribeToDevices(context.config.contactSensor, 'contactSensor', 'contact', 'myDeviceEventHandler');\n    })\n    .subscribedEventHandler('myDeviceEventHandler', async (context, event) =\u003e {\n        const value = event.value === 'open' ? 'on' : 'off';\n        await context.api.devices.sendCommands(context.config.lights, 'switch', value);\n    });\n\nserver.use(express.json());\n\n/* Handle POST requests */\nserver.post('/', function (req, res, next) {\n    smartapp.handleHttpCallback(req, res);\n});\n\n/* Start listening at your defined PORT */\nserver.listen(PORT, () =\u003e console.log(`Server is up and running on port ${PORT}`));\n```\n\n### Running as an AWS Lambda Function\n\nTo run your SmartApp as a Lambda function instead of an HTTP server, ensure that your main entry file exports `smartapp.handleLambdaCallback(...)`.\n\nNote that this snippet is heavily truncated for brevity:\n\n```javascript\nconst SmartApp = require('@smartthings/smartapp');\n\nconst smartapp = new SmartApp()\n    .enableEventLogging() // logs all lifecycle event requests and responses. Omit in production\n    .page( ... )\n    .updated(() =\u003e { ... })\n    .subscribedEventHandler( ... );\n\nexports.handler = (event, context, callback) =\u003e {\n    smartapp.handleLambdaCallback(event, context, callback);\n};\n```\n\n### Additional Examples\n\nYou can find additional examples in Glitch:\n\n- [Simple SmartThings Automation App using Contact Sensors](https://glitch.com/edit/#!/south-mayonnaise?path=README.md:1:0)\n- [Simple SmartThings Automation App using Motion Detectors](https://glitch.com/edit/#!/polite-math?path=README.md:1:0)\n- [Simple Switch Cloud-to-Cloud (C2C) App](https://glitch.com/edit/#!/aquamarine-crop?path=README.md:1:0)\n\nMore detailed examples to use as a starting point can be found in our [smartthings-smartapp-example](https://github.com/topics/smartthings-smartapp-example) Github Topic.\n\n## Localization\n\nConfiguration page strings are specified in a separate `locales/en.json` file, which can be automatically created the first time you run the app. Here's a completed English localization file for the previous simple SmartApp example:\n\n```json\n{\n  \"pages.mainPage.name\": \"Let There Be Light\",\n  \"pages.mainPage.sections.sensors.name\": \"When this door or window opens or closes\",\n  \"pages.mainPage.settings.contactSensor.name\": \"Select open/close sensor\",\n  \"pages.mainPage.sections.lights.name\": \"Turn on and off these lights and switches\",\n  \"pages.mainPage.settings.lights.name\": \"Select lights and switches\",\n  \"Tap to set\": \"Tap to set\"\n}\n```\n\n## Unhandled Promise Rejection Handling\n\nBy default, instantiation of the SmartApp object registers an `unhandledReject` handler that logs unhandled promise rejections. You can disable this behavior by passing an option to the SmartApp instantiation (e.g. `new SmartApp({logUnhandledRejections: false})`).\n\nIf desired, you can replace the handler by calling `unhandledRejectionHandler(promise =\u003e {...})` on the SmartApp object.\n\n## Making API Calls Outside of an `EVENT` Handler\n\nBy default, the SmartApp SDK will facilitate API calls on behalf of a user within the `EVENT` lifecycle. These user tokens are ephemeral and last *5 minutes*. These access tokens are not able to be refreshed and should _not_ be stored.\n\nIf you are making out-of-band API calls on behalf of a user's installed app, you will need to use the 24-hour access token that is supplied after the `INSTALL` and `UPDATE` lifecycles. This token includes a `refresh_token`, and will automatically be refreshed by the SDK when necessary.\n\n\u003eNote that **there is no in-memory context store**; you must use a context store plugin. If you'd like to add a custom context store plugin, please consider  [contributing](CONTRIBUTING.md).\n\nTo get started with our context store example below, we will add a compatible `ContextStore` plugin that will persist these tokens (among other things) to a database.\n\n### Amazon AWS DynamoDB\n\n\u003eAvailable as a node package on [NPM](https://www.npmjs.com/package/@smartthings/dynamodb-context-store) or [fork on GitHub](https://github.com/SmartThingsCommunity/dynamodb-context-store-nodejs/fork).\n\nIf you are hosting your SmartApp as an AWS Lambda, this DynamoDB context store makes perfect sense. This assumes you've already configured the [`aws-sdk`](https://www.npmjs.com/package/aws-sdk) package to interact with your Lambda, so extending your context store to DynamoDB is a drop-in solution.\n\nIf you are self-hosted and still want to use DynamoDB, you can do that, too:\n\n1. Import the package to your project: `npm i --save @smartthings/dynamodb-context-store`\n    - *Note:* when adding this package, you also have `aws-sdk` available at the global scope, so you can configure the AWS SDK: `AWS.config.loadFromPath(creds)`\n1. Get an [AWS Access Key and Secret](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/getting-your-credentials.html)\n1. Set your credentials for your app, [any of the following ways are fine](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-node.html).\n1. Register your Context Store plugin as described on [the project repository's readme.](https://github.com/SmartThingsCommunity/dynamodb-context-store-nodejs#usage)\n\nFor complete directions on usage, please see this project's GitHub repository. ([SmartThingsCommunity/dynamodb-context-store-nodejs](https://github.com/SmartThingsCommunity/dynamodb-context-store-nodejs))\n\n### Firebase Cloud Firestore\n\n\u003eAvailable as a node package on [NPM](https://www.npmjs.com/package/@smartthings/firestore-context-store) or [fork on GitHub](https://github.com/SmartThingsCommunity/firestore-context-store-nodejs/fork).\n\nUsage is generally the same as DynamoDB:\n\n1. Generate a Firebase service account. You will receive a JSON file with the credentials.\n1. Load your Google Services JSON\n1. Create the context store\n\nSee the full usage guide on the [project's GitHub repository](https://github.com/SmartThingsCommunity/firestore-context-store-nodejs#usage).\n\n---\n## More about SmartThings\n\nCheck out our complete developer documentation [here](https://developer.smartthings.com/docs/getting-started/welcome).\n\nTo create and manage your services and devices on SmartThings, create an account in the\n[developer workspace](https://smartthings.developer.samsung.com/workspace/).\n\nThe [SmartThings Community](https://community.smartthings.com/) is a good place share and\nask questions.\n\nThere is also a [SmartThings reddit community](https://www.reddit.com/r/SmartThings/) where you\ncan read and share information.\n\n## License and Copyright\n\nLicensed under the [Apache License, Version 2.0](LICENSE)\n\nCopyright 2023 Samsung Electronics Co., LTD.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartthingscommunity%2Fsmartapp-sdk-nodejs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmartthingscommunity%2Fsmartapp-sdk-nodejs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmartthingscommunity%2Fsmartapp-sdk-nodejs/lists"}