├── test ├── fixtures │ └── test.txt ├── types │ ├── types_test.js.map │ ├── .eslintrc │ ├── tsconfig.json │ ├── types_test.js │ └── types_test.ts ├── build │ ├── node │ │ ├── js_esm │ │ │ ├── namedImport.js │ │ │ ├── import.js │ │ │ └── package.json │ │ ├── ts_es6 │ │ │ ├── namedImport.ts │ │ │ ├── namedImport.js │ │ │ ├── namedImport.js.map │ │ │ ├── import.js │ │ │ ├── import.ts │ │ │ ├── import.js.map │ │ │ ├── package.json │ │ │ └── tsconfig.json │ │ ├── ts_cjs │ │ │ ├── require.js │ │ │ ├── require.ts │ │ │ ├── require.js.map │ │ │ ├── package.json │ │ │ └── tsconfig.json │ │ └── js_cjs │ │ │ ├── require.js │ │ │ └── package.json │ ├── browser │ │ ├── umd.html │ │ ├── umd.min.html │ │ └── es.html │ ├── node.js │ └── browser.js ├── .eslintrc ├── unit │ ├── response.js │ ├── error.js │ ├── utils.js │ ├── dropbox.js │ └── auth.js └── integration │ ├── team.js │ └── user.js ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature_request.md │ ├── question_help.md │ └── bug_report.md ├── pull_request_template.md ├── dependabot.yml └── workflows │ ├── npm_upload.yml │ ├── documentation.yml │ ├── coverage.yml │ ├── ci.yml │ └── spec_update.yml ├── generator ├── typescript │ ├── dropbox_types.d.tstemplate │ └── index.d.tstemplate └── generate_routes.py ├── examples ├── javascript │ ├── .eslintrc │ ├── node │ │ ├── package.json │ │ ├── basic.js │ │ ├── team.js │ │ ├── team-as-user.js │ │ ├── download.js │ │ └── upload.js │ ├── PKCE-backend │ │ ├── package.json │ │ └── code_flow_example.js │ ├── simple-backend │ │ ├── package.json │ │ └── code_flow_example.js │ ├── server.js │ ├── utils.js │ ├── index.html │ ├── styles.css │ ├── team │ │ └── index.html │ ├── team-as-user │ │ └── index.html │ ├── basic │ │ └── index.html │ ├── download │ │ └── index.html │ ├── auth │ │ └── index.html │ ├── pkce-browser │ │ └── index.html │ └── upload │ │ └── index.html ├── typescript │ ├── .eslintrc │ ├── basic │ │ ├── basic.ts │ │ ├── basic.js.map │ │ └── index.js │ ├── tsconfig.json │ ├── team │ │ ├── team.js.map │ │ ├── team.ts │ │ └── index.js │ ├── team-as-user │ │ ├── team-as-user.js.map │ │ ├── team-as-user.ts │ │ └── index.js │ ├── package.json │ ├── upload │ │ ├── upload.js.map │ │ ├── upload.ts │ │ └── index.js │ └── download │ │ ├── download.js.map │ │ ├── download.ts │ │ └── index.js └── README.md ├── .nycrc.json ├── index.js ├── .gitmodules ├── codecov.yml ├── .eslintignore ├── CODE_OF_CONDUCT.md ├── .jsdoc.json ├── .eslintrc ├── types └── .eslintrc ├── scripts ├── update_version.sh └── release_note_generator.sh ├── src ├── constants.js ├── error.js ├── response.js ├── utils.js ├── dropbox.js └── auth.js ├── .babelrc ├── LICENSE ├── rollup.config.js ├── .gitignore ├── CONTRIBUTING.md ├── README.md ├── package.json └── UPGRADING.md /test/fixtures/test.txt: -------------------------------------------------------------------------------- 1 | Hello world! 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false -------------------------------------------------------------------------------- /generator/typescript/dropbox_types.d.tstemplate: -------------------------------------------------------------------------------- 1 | // Auto-generated by Stone, do not modify. 2 | 3 | /*TYPES*/ 4 | -------------------------------------------------------------------------------- /examples/javascript/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-console": 0, 4 | "import/no-extraneous-dependencies": 0 5 | } 6 | } -------------------------------------------------------------------------------- /test/types/types_test.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"types_test.js","sourceRoot":"","sources":["types_test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"} -------------------------------------------------------------------------------- /.nycrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "all": true, 3 | "include": [ 4 | "src/*.js", 5 | "lib/*.js" 6 | ], 7 | "require": ["@babel/register"] 8 | } -------------------------------------------------------------------------------- /test/build/node/js_esm/namedImport.js: -------------------------------------------------------------------------------- 1 | import { Dropbox, DropboxAuth } from 'dropbox'; 2 | 3 | var dbx = new dropbox.Dropbox(); 4 | var dbxAuth = new dropbox.DropboxAuth(); -------------------------------------------------------------------------------- /examples/javascript/node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-node-examples", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "dropbox": "file:../../../" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/build/node/ts_es6/namedImport.ts: -------------------------------------------------------------------------------- 1 | import { Dropbox, DropboxAuth } from 'dropbox'; 2 | 3 | var dbx: Dropbox = new Dropbox(); 4 | var dbxAuth: DropboxAuth = new DropboxAuth(); -------------------------------------------------------------------------------- /examples/javascript/PKCE-backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PKCE-backend", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "dropbox": "file:../../../" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/javascript/simple-backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "simple-backend", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "dropbox": "file:../../../" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/build/node/ts_cjs/require.js: -------------------------------------------------------------------------------- 1 | const dropbox = require('dropbox'); 2 | var dbx = new dropbox.Dropbox(); 3 | var dbxAuth = new dropbox.DropboxAuth(); 4 | //# sourceMappingURL=require.js.map -------------------------------------------------------------------------------- /test/build/node/ts_cjs/require.ts: -------------------------------------------------------------------------------- 1 | const dropbox = require('dropbox'); 2 | 3 | var dbx: dropbox.Dropbox = new dropbox.Dropbox(); 4 | var dbxAuth: dropbox.DropboxAuth = new dropbox.DropboxAuth(); -------------------------------------------------------------------------------- /test/build/node/ts_es6/namedImport.js: -------------------------------------------------------------------------------- 1 | import { Dropbox, DropboxAuth } from 'dropbox'; 2 | var dbx = new Dropbox(); 3 | var dbxAuth = new DropboxAuth(); 4 | //# sourceMappingURL=namedImport.js.map -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "rules": { 6 | "no-restricted-syntax": 0, 7 | "no-console": 0, 8 | "no-unused-vars": 0 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | export { default as Dropbox } from './src/dropbox.js'; 2 | export { default as DropboxAuth } from './src/auth.js'; 3 | export { DropboxResponse } from './src/response.js'; 4 | export { DropboxResponseError } from './src/error.js'; 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "dropbox-api-spec"] 2 | path = generator/dropbox-api-spec 3 | url = https://github.com/dropbox/dropbox-api-spec.git 4 | [submodule "stone"] 5 | path = generator/stone 6 | url = https://github.com/dropbox/stone.git 7 | -------------------------------------------------------------------------------- /test/build/node/js_esm/import.js: -------------------------------------------------------------------------------- 1 | import dropbox from 'dropbox'; 2 | 3 | var dbx = new dropbox.Dropbox(); 4 | var dbxAuth = new dropbox.DropboxAuth(); 5 | 6 | var { Dropbox, DropboxAuth } = dropbox; 7 | 8 | var dbx2 = new Dropbox(); 9 | var dbxAuth2 = new DropboxAuth(); -------------------------------------------------------------------------------- /test/build/node/js_cjs/require.js: -------------------------------------------------------------------------------- 1 | var dropbox = require('dropbox'); 2 | 3 | var dbx = new dropbox.Dropbox(); 4 | var dbxAuth = new dropbox.DropboxAuth(); 5 | 6 | var { Dropbox, DropboxAuth } = dropbox; 7 | 8 | var dbx2 = new Dropbox(); 9 | var dbxAuth2 = new DropboxAuth(); -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | default: 5 | target: auto 6 | threshold: 0% 7 | base: auto 8 | if_not_found: error 9 | if_ci_failed: error 10 | informational: false 11 | only_pulls: true -------------------------------------------------------------------------------- /test/build/node/ts_es6/namedImport.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"namedImport.js","sourceRoot":"","sources":["namedImport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE/C,IAAI,GAAG,GAAY,IAAI,OAAO,EAAE,CAAC;AACjC,IAAI,OAAO,GAAgB,IAAI,WAAW,EAAE,CAAC"} -------------------------------------------------------------------------------- /test/build/node/ts_cjs/require.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"require.js","sourceRoot":"","sources":["require.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAEnC,IAAI,GAAG,GAAoB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;AACjD,IAAI,OAAO,GAAwB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC"} -------------------------------------------------------------------------------- /test/build/node/ts_es6/import.js: -------------------------------------------------------------------------------- 1 | import dropbox from 'dropbox'; 2 | const dbx = new dropbox.Dropbox(); 3 | const dbxAuth = new dropbox.DropboxAuth(); 4 | const { Dropbox, DropboxAuth } = dropbox; 5 | var dbx2 = new Dropbox(); 6 | var dbxAuth2 = new DropboxAuth(); 7 | //# sourceMappingURL=import.js.map -------------------------------------------------------------------------------- /test/build/node/js_cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cjs_build_test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "scripts": { 6 | "test:require": "node require.js" 7 | }, 8 | "devDependencies": { 9 | "dropbox": "file:../../../../" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | lib/types.js 2 | lib/routes.js 3 | types/dropbox_types.d.ts 4 | types/index.d.ts 5 | test/types/types_test.js 6 | test/types/types_test.js.map 7 | test/build/node/** 8 | docs/** 9 | dist/ 10 | es/ 11 | cjs/ 12 | examples/typescript/**/*.js 13 | examples/typescript/**/*.js.map 14 | **/node_modules/** 15 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Dropbox Code Of Conduct 2 | 3 | *Dropbox believes that an inclusive development environment fosters greater technical achievement. To encourage a diverse group of contributors we've adopted this code of conduct.* 4 | 5 | Please read the Official Dropbox [Code of Conduct](https://opensource.dropbox.com/coc/) before contributing. -------------------------------------------------------------------------------- /test/build/node/ts_es6/import.ts: -------------------------------------------------------------------------------- 1 | import dropbox from 'dropbox'; 2 | 3 | const dbx: dropbox.Dropbox = new dropbox.Dropbox(); 4 | const dbxAuth: dropbox.DropboxAuth = new dropbox.DropboxAuth(); 5 | 6 | const { Dropbox, DropboxAuth } = dropbox; 7 | 8 | var dbx2: dropbox.Dropbox = new Dropbox(); 9 | var dbxAuth2: dropbox.DropboxAuth = new DropboxAuth(); -------------------------------------------------------------------------------- /.jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "source": { 3 | "include": ["./src", "./lib"] 4 | }, 5 | "opts": { 6 | "template": "./node_modules/ink-docstrap/template", 7 | "destination": "docs", 8 | "readme": "./README.md", 9 | "recurse": true 10 | }, 11 | "templates": { 12 | "systemName": "Dropbox Node SDK", 13 | "theme": "cosmo" 14 | } 15 | } -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["airbnb-base"], 3 | "env": { 4 | "node": true 5 | }, 6 | "rules": { 7 | "func-names": 0, 8 | "no-param-reassign": 0, 9 | "import/prefer-default-export": 0, 10 | "import/extensions": 0, 11 | "no-undef": 0 12 | }, 13 | "parserOptions": { 14 | "ecmaVersion": 2017, 15 | "impliedStrict": false 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/build/node/js_esm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cjs_build_test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "type": "module", 6 | "scripts": { 7 | "test:import": "node import.js", 8 | "test:namedImport": "node namedImport.js" 9 | }, 10 | "devDependencies": { 11 | "dropbox": "file:../../../../" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /types/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["airbnb-base"], 3 | "env": { 4 | "browser": false, 5 | "node": true 6 | }, 7 | "rules": { 8 | "func-names": 0, 9 | "no-param-reassign": 0, 10 | "import/prefer-default-export": 0 11 | }, 12 | "plugins": ["@typescript-eslint"], 13 | "parser": "@typescript-eslint/parser", 14 | "parserOptions": { "ecmaVersion": 6 } 15 | } -------------------------------------------------------------------------------- /scripts/update_version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -z $1 ]; then 4 | echo "error: $0 needs a version number as argument."; 5 | exit 1 6 | else 7 | set -ex 8 | NEW_VERSION=$1 9 | 10 | git checkout main 11 | git reset --hard HEAD 12 | 13 | git tag "v${NEW_VERSION}" -m "${NEW_VERSION} release" 14 | 15 | git push origin 16 | git push origin --tags 17 | fi -------------------------------------------------------------------------------- /test/build/node/ts_es6/import.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"import.js","sourceRoot":"","sources":["import.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,MAAM,GAAG,GAAoB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;AACnD,MAAM,OAAO,GAAwB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;AAE/D,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;AAEzC,IAAI,IAAI,GAAoB,IAAI,OAAO,EAAE,CAAC;AAC1C,IAAI,QAAQ,GAAwB,IAAI,WAAW,EAAE,CAAC"} -------------------------------------------------------------------------------- /test/build/node/ts_cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cjs_build_test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "type": "module", 6 | "scripts": { 7 | "build": "tsc -p tsconfig.json", 8 | "test:require": "node require.js" 9 | }, 10 | "devDependencies": { 11 | "dropbox": "file:../../../../", 12 | "typescript": "^4.0.3" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/build/node/ts_es6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cjs_build_test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "type": "module", 6 | "scripts": { 7 | "build": "tsc -p tsconfig.json", 8 | "test:import": "node import.js", 9 | "test:namedImport": "node namedImport.js" 10 | }, 11 | "devDependencies": { 12 | "dropbox": "file:../../../../", 13 | "typescript": "^4.0.3" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/types/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["airbnb-base"], 3 | "env": { 4 | "browser": false, 5 | "node": true 6 | }, 7 | "rules": { 8 | "func-names": 0, 9 | "no-param-reassign": 0, 10 | "import/prefer-default-export": 0, 11 | "no-unused-expressions": 0, 12 | "no-unused-vars": 0 13 | }, 14 | "plugins": ["@typescript-eslint"], 15 | "parser": "@typescript-eslint/parser", 16 | "parserOptions": { "ecmaVersion": 6 } 17 | } -------------------------------------------------------------------------------- /examples/typescript/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["airbnb-base"], 3 | "env": { 4 | "browser": false, 5 | "node": true 6 | }, 7 | "rules": { 8 | "func-names": 0, 9 | "no-param-reassign": 0, 10 | "import/prefer-default-export": 0, 11 | "no-console": 0, 12 | "import/no-extraneous-dependencies": 0 13 | }, 14 | "plugins": ["@typescript-eslint"], 15 | "parser": "@typescript-eslint/parser", 16 | "parserOptions": { "ecmaVersion": 6 } 17 | } -------------------------------------------------------------------------------- /scripts/release_note_generator.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | last_version=$(git tag --sort v:refname | tail -n 2 | head -n 1) 4 | echo "Getting commit history since $last_version" 5 | num_commits=$(git rev-list --count $last_version..HEAD) 6 | echo "Found $num_commits commits since last revision" 7 | git_log=$(git log -n $num_commits --pretty="format:* %s %n") 8 | linked_log=$(echo "Release Notes: \n\n$git_log" | sed -e 's/#\([0-9]*\)/[#\1](https:\/\/github.com\/dropbox\/dropbox-sdk-js\/pull\/\1)/g') 9 | echo "\n\n$linked_log" -------------------------------------------------------------------------------- /src/constants.js: -------------------------------------------------------------------------------- 1 | export const RPC = 'rpc'; 2 | export const UPLOAD = 'upload'; 3 | export const DOWNLOAD = 'download'; 4 | 5 | export const APP_AUTH = 'app'; 6 | export const USER_AUTH = 'user'; 7 | export const TEAM_AUTH = 'team'; 8 | export const NO_AUTH = 'noauth'; 9 | export const COOKIE = 'cookie'; 10 | 11 | export const DEFAULT_API_DOMAIN = 'dropboxapi.com'; 12 | export const DEFAULT_DOMAIN = 'dropbox.com'; 13 | 14 | export const TEST_DOMAIN_MAPPINGS = { 15 | api: 'api', 16 | notify: 'bolt', 17 | content: 'api-content', 18 | }; 19 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"], 3 | "env": { 4 | "coverage": { 5 | "plugins": ["istanbul"] 6 | }, 7 | "commonjs": { 8 | "presets": [[ 9 | "@babel/preset-env", { 10 | "modules": "cjs" 11 | } 12 | ]], 13 | "plugins": [ 14 | ["transform-es2015-modules-commonjs", { "noInterop": true }] 15 | ] 16 | }, 17 | "es": { 18 | "presets": [[ 19 | "@babel/preset-env", { 20 | "modules": false 21 | } 22 | ]] 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/typescript/basic/basic.ts: -------------------------------------------------------------------------------- 1 | import { Dropbox } from 'dropbox'; 2 | 3 | const prompt = require('prompt'); 4 | 5 | prompt.start(); 6 | 7 | prompt.get({ 8 | properties: { 9 | accessToken: { 10 | description: 'Please enter an API V2 access token', 11 | }, 12 | }, 13 | }, (error: any, result: any) => { 14 | const dbx = new Dropbox({ accessToken: result.accessToken }); 15 | dbx.filesListFolder({ path: '' }) 16 | .then((response: any) => { 17 | console.log(response); 18 | }) 19 | .catch((err: any) => { 20 | console.log(err); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /examples/typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2015", 5 | "lib": ["dom", "es2015", "es2016", "es2017"], 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "declaration": false, 9 | "noFallthroughCasesInSwitch": true, 10 | "noImplicitAny": true, 11 | "noImplicitReturns": true, 12 | "noImplicitThis": true, 13 | "noImplicitUseStrict": true, 14 | "noUnusedLocals": true, 15 | "outDir": "dist" 16 | }, 17 | "include": ["**/*.ts", "node/**/*.ts"], 18 | "exclude": ["node_modules"] 19 | } 20 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | ## **Checklist** 6 | 7 | 8 | **General Contributing** 9 | - [ ] Have you read the Code of Conduct and signed the [CLA](https://opensource.dropbox.com/cla/)? 10 | 11 | **Is This a Code Change?** 12 | - [ ] Non-code related change (markdown/git settings etc) 13 | - [ ] SDK Code Change 14 | - [ ] Example/Test Code Change 15 | 16 | **Validation** 17 | - [ ] Does `npm test` pass? 18 | - [ ] Does `npm run build` pass? 19 | - [ ] Does `npm run lint` pass? -------------------------------------------------------------------------------- /examples/javascript/node/basic.js: -------------------------------------------------------------------------------- 1 | const prompt = require('prompt'); 2 | const { Dropbox } = require('dropbox'); // eslint-disable-line import/no-unresolved 3 | 4 | prompt.start(); 5 | 6 | prompt.get({ 7 | properties: { 8 | accessToken: { 9 | description: 'Please enter an API V2 access token', 10 | }, 11 | }, 12 | }, (error, result) => { 13 | const dbx = new Dropbox({ accessToken: result.accessToken }); 14 | dbx.filesListFolder({ path: '/Screenshots' }) 15 | .then((response) => { 16 | console.log(response); 17 | }) 18 | .catch((err) => { 19 | console.log(err); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /examples/javascript/node/team.js: -------------------------------------------------------------------------------- 1 | const prompt = require('prompt'); 2 | const { Dropbox } = require('dropbox'); // eslint-disable-line import/no-unresolved 3 | 4 | prompt.start(); 5 | 6 | prompt.get({ 7 | properties: { 8 | accessToken: { 9 | description: 'Please enter an API V2 team access token', 10 | }, 11 | }, 12 | }, (error, result) => { 13 | const dbx = new Dropbox({ accessToken: result.accessToken }); 14 | dbx.teamDevicesListTeamDevices({}) 15 | .then((response) => { 16 | console.log('Devices', response); 17 | }) 18 | .catch((err) => { 19 | console.log(err); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /examples/typescript/basic/basic.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["basic.ts"],"names":[],"mappings":";AAAA,qCAAkC;AAElC,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEjC,MAAM,CAAC,KAAK,EAAE,CAAC;AAEf,MAAM,CAAC,GAAG,CAAC;IACT,UAAU,EAAE;QACV,WAAW,EAAE;YACX,WAAW,EAAE,qCAAqC;SACnD;KACF;CACF,EAAE,CAAC,KAAU,EAAE,MAAW,EAAE,EAAE;IAC7B,MAAM,GAAG,GAAG,IAAI,iBAAO,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7D,GAAG,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;SAC9B,IAAI,CAAC,CAAC,QAAa,EAAE,EAAE;QACtB,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxB,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,GAAQ,EAAE,EAAE;QAClB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} -------------------------------------------------------------------------------- /examples/typescript/team/team.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["team.ts"],"names":[],"mappings":";AAAA,qCAA+C,CAAC,qCAAqC;AAErF,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEjC,MAAM,CAAC,KAAK,EAAE,CAAC;AAEf,MAAM,CAAC,GAAG,CAAC;IACT,UAAU,EAAE;QACV,WAAW,EAAE;YACX,WAAW,EAAE,0CAA0C;SACxD;KACF;CACF,EAAE,CAAC,KAAU,EAAE,MAAW,EAAE,EAAE;IAC7B,MAAM,GAAG,GAAG,IAAI,iBAAO,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7D,GAAG,CAAC,0BAA0B,CAAC,EAAE,CAAC;SAC/B,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;QACjB,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,GAAqC,EAAE,EAAE;QAC/C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} -------------------------------------------------------------------------------- /examples/typescript/team/team.ts: -------------------------------------------------------------------------------- 1 | import { Dropbox, Error, team } from 'dropbox'; // eslint-disable-line no-unused-vars 2 | 3 | const prompt = require('prompt'); 4 | 5 | prompt.start(); 6 | 7 | prompt.get({ 8 | properties: { 9 | accessToken: { 10 | description: 'Please enter an API V2 team access token', 11 | }, 12 | }, 13 | }, (error: any, result: any) => { 14 | const dbx = new Dropbox({ accessToken: result.accessToken }); 15 | dbx.teamDevicesListTeamDevices({}) 16 | .then((response) => { 17 | console.log('Devices', response); 18 | }) 19 | .catch((err: Error) => { 20 | console.log(err); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /test/build/node/ts_cjs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2015", 5 | "lib": ["dom", "es2015", "es2016", "es2017"], 6 | "moduleResolution": "node", 7 | "esModuleInterop": true, 8 | "sourceMap": true, 9 | "declaration": false, 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitReturns": true, 13 | "noImplicitThis": true, 14 | "noImplicitUseStrict": true, 15 | "noUnusedLocals": false 16 | }, 17 | "include": [ 18 | "import.ts", 19 | "require.ts" 20 | ], 21 | "exclude": [ 22 | "node_modules" 23 | ] 24 | } -------------------------------------------------------------------------------- /test/build/node/ts_es6/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ES6", 4 | "target": "es2015", 5 | "lib": ["dom", "es2015", "es2016", "es2017"], 6 | "moduleResolution": "node", 7 | "esModuleInterop": true, 8 | "sourceMap": true, 9 | "declaration": false, 10 | "noFallthroughCasesInSwitch": true, 11 | "noImplicitAny": true, 12 | "noImplicitReturns": true, 13 | "noImplicitThis": true, 14 | "noImplicitUseStrict": true, 15 | "noUnusedLocals": false 16 | }, 17 | "include": [ 18 | "import.ts", 19 | "namedImport.ts" 20 | ], 21 | "exclude": [ 22 | "node_modules" 23 | ] 24 | } -------------------------------------------------------------------------------- /examples/typescript/basic/index.js: -------------------------------------------------------------------------------- 1 | Object.defineProperty(exports, "__esModule", { value: true }); 2 | const dropbox_1 = require("dropbox"); 3 | const prompt = require('prompt'); 4 | prompt.start(); 5 | prompt.get({ 6 | properties: { 7 | accessToken: { 8 | description: 'Please enter an API V2 access token', 9 | }, 10 | }, 11 | }, (error, result) => { 12 | const dbx = new dropbox_1.Dropbox({ accessToken: result.accessToken }); 13 | dbx.filesListFolder({ path: '' }) 14 | .then((response) => { 15 | console.log(response); 16 | }) 17 | .catch((err) => { 18 | console.log(err); 19 | }); 20 | }); 21 | //# sourceMappingURL=basic.js.map -------------------------------------------------------------------------------- /src/error.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The response class of HTTP errors from API calls using the Dropbox SDK. 3 | * @class DropboxResponseError 4 | * @classdesc The response class of HTTP errors from API calls using the Dropbox SDK. 5 | * @arg {number} status - HTTP Status code of the call 6 | * @arg {Object} headers - Headers returned from the call 7 | * @arg {Object} error - Serialized Error of the call 8 | */ 9 | export class DropboxResponseError extends Error { 10 | constructor(status, headers, error) { 11 | super(`Response failed with a ${status} code`); 12 | this.name = 'DropboxResponseError'; 13 | this.status = status; 14 | this.headers = headers; 15 | this.error = error; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/typescript/team/index.js: -------------------------------------------------------------------------------- 1 | Object.defineProperty(exports, "__esModule", { value: true }); 2 | const dropbox_1 = require("dropbox"); // eslint-disable-line no-unused-vars 3 | const prompt = require('prompt'); 4 | prompt.start(); 5 | prompt.get({ 6 | properties: { 7 | accessToken: { 8 | description: 'Please enter an API V2 team access token', 9 | }, 10 | }, 11 | }, (error, result) => { 12 | const dbx = new dropbox_1.Dropbox({ accessToken: result.accessToken }); 13 | dbx.teamDevicesListTeamDevices({}) 14 | .then((response) => { 15 | console.log('Devices', response); 16 | }) 17 | .catch((err) => { 18 | console.log(err); 19 | }); 20 | }); 21 | //# sourceMappingURL=team.js.map -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F680 Feature Request" 3 | about: Suggest an idea for this SDK 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Why is this feature valuable to you? Does it solve a problem you're having?** 11 | A clear and concise description of why this feature is valuable. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. (if applicable) 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /examples/javascript/node/team-as-user.js: -------------------------------------------------------------------------------- 1 | const prompt = require('prompt'); 2 | const { Dropbox } = require('dropbox'); // eslint-disable-line import/no-unresolved 3 | 4 | prompt.start(); 5 | 6 | prompt.get({ 7 | properties: { 8 | accessToken: { 9 | description: 'Please enter an API V2 team access token', 10 | }, 11 | userId: { 12 | description: 'Please enter the id of the user you would like to act as', 13 | }, 14 | }, 15 | }, (error, result) => { 16 | const dbx = new Dropbox({ accessToken: result.accessToken, selectUser: result.userId }); 17 | dbx.filesListFolder({ path: '' }) 18 | .then((response) => { 19 | console.log(response); 20 | }) 21 | .catch((err) => { 22 | console.log(err); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /examples/typescript/team-as-user/team-as-user.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["team-as-user.ts"],"names":[],"mappings":";AAAA,qCAAgD,CAAC,qCAAqC;AAEtF,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEjC,MAAM,CAAC,KAAK,EAAE,CAAC;AAEf,MAAM,CAAC,GAAG,CAAC;IACT,UAAU,EAAE;QACV,WAAW,EAAE;YACX,WAAW,EAAE,0CAA0C;SACxD;QACD,MAAM,EAAE;YACN,WAAW,EAAE,0DAA0D;SACxE;KACF;CACF,EAAE,CAAC,KAAU,EAAE,MAAW,EAAE,EAAE;IAC7B,MAAM,GAAG,GAAG,IAAI,iBAAO,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACxF,GAAG,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;SAC9B,IAAI,CAAC,CAAC,QAAa,EAAE,EAAE;QACtB,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxB,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,GAAiC,EAAE,EAAE;QAC3C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | # Updates to main package 9 | - package-ecosystem: "npm" 10 | directory: "/" 11 | schedule: 12 | interval: "monthly" 13 | # Updates to TS examples 14 | - package-ecosystem: "npm" 15 | directory: "examples/typescript" 16 | schedule: 17 | interval: "monthly" 18 | 19 | - package-ecosystem: "github-actions" 20 | directory: "/" 21 | schedule: 22 | interval: "monthly" 23 | -------------------------------------------------------------------------------- /examples/typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dropbox-ts-examples", 3 | "version": "1.0.0", 4 | "description": "Dropbox TypeScript SDK Examples", 5 | "scripts": { 6 | "build": "tsc -p tsconfig.json" 7 | }, 8 | "contributors": [ 9 | "Brad Rogers ", 10 | "Andrew Lawson ", 11 | "John Vilk " 12 | ], 13 | "license": "MIT", 14 | "engines": { 15 | "node": ">=0.10" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/dropbox/dropbox-sdk-js.git" 20 | }, 21 | "dependencies": { 22 | "dropbox": "file:../../" 23 | }, 24 | "devDependencies": { 25 | "@types/express": "^4.17.11", 26 | "@types/node": "^14.14.25", 27 | "typescript": "^4.1.4" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question_help.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F4AC Questions / Help" 3 | about: Get help with issues you are experiencing 4 | title: '' 5 | labels: help-wanted, question 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Before you start** 11 | Have you checked StackOverflow, previous issues, and Dropbox Developer Forums for help? 12 | 13 | **What is your question?** 14 | A clear and concise description of the question. 15 | 16 | **Screenshots** 17 | If applicable, add screenshots to help explain your question. 18 | 19 | **Versions** 20 | * What version of the SDK are you using? 21 | * What version of the language are you using? 22 | * Are you using Javascript or Typescript? 23 | * What platform are you using? (if applicable) 24 | 25 | **Additional context** 26 | Add any other context about the question here. -------------------------------------------------------------------------------- /examples/typescript/team-as-user/team-as-user.ts: -------------------------------------------------------------------------------- 1 | import { Dropbox, Error, files } from 'dropbox'; // eslint-disable-line no-unused-vars 2 | 3 | const prompt = require('prompt'); 4 | 5 | prompt.start(); 6 | 7 | prompt.get({ 8 | properties: { 9 | accessToken: { 10 | description: 'Please enter an API V2 team access token', 11 | }, 12 | userId: { 13 | description: 'Please enter the id of the user you would like to act as', 14 | }, 15 | }, 16 | }, (error: any, result: any) => { 17 | const dbx = new Dropbox({ accessToken: result.accessToken, selectUser: result.userId }); 18 | dbx.filesListFolder({ path: '' }) 19 | .then((response: any) => { 20 | console.log(response); 21 | }) 22 | .catch((err: Error) => { 23 | console.log(err); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /.github/workflows/npm_upload.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages 3 | 4 | name: Publish to NPM 5 | 6 | on: 7 | workflow_dispatch: 8 | release: 9 | types: [created] 10 | 11 | jobs: 12 | npm: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v2.3.4 16 | - uses: actions/setup-node@v2.1.5 17 | with: 18 | node-version: 14 19 | - name: Build Package 20 | run: | 21 | npm install 22 | npm run build 23 | - name: NPM Publish 24 | uses: JS-DevTools/npm-publish@v1.4.3 25 | with: 26 | token: ${{ secrets.NPM_TOKEN }} 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41B Bug report" 3 | about: Create a report to help us improve the SDK 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of the bug. 12 | 13 | **To Reproduce** 14 | The steps to reproduce the behavior 15 | 16 | **Expected Behavior** 17 | A clear description of what you expected to happen. 18 | 19 | **Actual Behavior** 20 | A clear description of what actually happened 21 | 22 | **Screenshots** 23 | If applicable, add screenshots to help explain your problem. 24 | 25 | **Versions** 26 | * What version of the SDK are you using? 27 | * What version of the language are you using? 28 | * Are you using Javascript or Typescript? 29 | * What platform are you using? (if applicable) 30 | 31 | **Additional context** 32 | Add any other context about the problem here. -------------------------------------------------------------------------------- /.github/workflows/documentation.yml: -------------------------------------------------------------------------------- 1 | name: Update Documentation 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | npm: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2.3.4 13 | - uses: actions/setup-node@v2.1.5 14 | with: 15 | registry-url: https://npm.pkg.github.com/ 16 | node-version: 14 17 | - name: Build Package 18 | run: | 19 | npm install 20 | npm run build 21 | - name: Build Documentation 22 | run: npm run generate-docs 23 | - name: Push Documentation 24 | uses: JamesIves/github-pages-deploy-action@releases/v3 25 | with: 26 | ACCESS_TOKEN: ${{ secrets.GH_PAGES_PUBLISH_TOKEN }} 27 | BRANCH: gh-pages # The branch the action should deploy to. 28 | FOLDER: docs # The folder the action should deploy. -------------------------------------------------------------------------------- /examples/typescript/team-as-user/index.js: -------------------------------------------------------------------------------- 1 | Object.defineProperty(exports, "__esModule", { value: true }); 2 | const dropbox_1 = require("dropbox"); // eslint-disable-line no-unused-vars 3 | const prompt = require('prompt'); 4 | prompt.start(); 5 | prompt.get({ 6 | properties: { 7 | accessToken: { 8 | description: 'Please enter an API V2 team access token', 9 | }, 10 | userId: { 11 | description: 'Please enter the id of the user you would like to act as', 12 | }, 13 | }, 14 | }, (error, result) => { 15 | const dbx = new dropbox_1.Dropbox({ accessToken: result.accessToken, selectUser: result.userId }); 16 | dbx.filesListFolder({ path: '' }) 17 | .then((response) => { 18 | console.log(response); 19 | }) 20 | .catch((err) => { 21 | console.log(err); 22 | }); 23 | }); 24 | //# sourceMappingURL=team-as-user.js.map -------------------------------------------------------------------------------- /examples/javascript/node/download.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const prompt = require('prompt'); 3 | const { Dropbox } = require('dropbox'); // eslint-disable-line import/no-unresolved 4 | 5 | prompt.start(); 6 | 7 | prompt.get({ 8 | properties: { 9 | accessToken: { 10 | description: 'Please enter an API V2 access token', 11 | }, 12 | sharedLink: { 13 | description: 'Please enter a shared link to a file', 14 | }, 15 | }, 16 | }, (error, result) => { 17 | const dbx = new Dropbox({ accessToken: result.accessToken }); 18 | dbx.sharingGetSharedLinkFile({ url: result.sharedLink }) 19 | .then((data) => { 20 | fs.writeFile(data.result.name, data.result.fileBinary, 'binary', (err) => { 21 | if (err) { throw err; } 22 | console.log(`File: ${data.result.name} saved.`); 23 | }); 24 | }) 25 | .catch((err) => { 26 | throw err; 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /examples/typescript/upload/upload.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["upload.ts"],"names":[],"mappings":";AAAA,qCAAgD,CAAC,qCAAqC;AACtF,yBAA0B;AAC1B,6BAA8B;AAE9B,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEjC,MAAM,CAAC,KAAK,EAAE,CAAC;AAEf,MAAM,CAAC,GAAG,CAAC;IACT,UAAU,EAAE;QACV,WAAW,EAAE;YACX,WAAW,EAAE,qCAAqC;SACnD;KACF;CACF,EAAE,CAAC,KAAU,EAAE,MAAW,EAAE,EAAE;IAC7B,MAAM,GAAG,GAAG,IAAI,iBAAO,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAE7D,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;QACvE,IAAI,GAAG,EAAE;YACP,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;SAC7B;QAED,oDAAoD;QACpD,GAAG,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;aAC7C,IAAI,CAAC,CAAC,QAAa,EAAE,EAAE;YACtB,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACxB,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,SAAmC,EAAE,EAAE;YAC7C,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} -------------------------------------------------------------------------------- /examples/javascript/node/upload.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const prompt = require('prompt'); 4 | const { Dropbox } = require('dropbox'); // eslint-disable-line import/no-unresolved 5 | 6 | prompt.start(); 7 | 8 | prompt.get({ 9 | properties: { 10 | accessToken: { 11 | description: 'Please enter an API V2 access token', 12 | }, 13 | }, 14 | }, (error, result) => { 15 | const dbx = new Dropbox({ accessToken: result.accessToken }); 16 | 17 | fs.readFile(path.join(__dirname, '/basic.js'), (err, contents) => { 18 | if (err) { 19 | console.log('Error: ', err); 20 | } 21 | 22 | // This uploads basic.js to the root of your dropbox 23 | dbx.filesUpload({ path: '/basic.js', contents }) 24 | .then((response) => { 25 | console.log(response); 26 | }) 27 | .catch((uploadErr) => { 28 | console.log(uploadErr); 29 | }); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /examples/javascript/server.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const express = require('express'); 4 | const rewrite = require('express-urlrewrite'); 5 | const rollup = require('rollup-endpoint'); 6 | 7 | const app = express(); 8 | const port = process.env.PORT || 8080; 9 | 10 | app.get( 11 | '/__build__/Dropbox-sdk.min.js', 12 | rollup.serve({ 13 | entry: path.resolve(__dirname, '../../dist/Dropbox-sdk.js'), 14 | }), 15 | ); 16 | 17 | fs.readdirSync(__dirname).forEach((file) => { 18 | if (fs.statSync(path.join(__dirname, file)).isDirectory()) { 19 | console.log(`Adding Route: /${file}/* from file /${file}/index.html`); 20 | app.use(rewrite(`/${file}/*`, `/${file}/index.html`)); 21 | } 22 | }); 23 | 24 | app.use(express.static(__dirname)); 25 | app.use('/__dist__', express.static(path.resolve(__dirname, '../../dist'))); 26 | 27 | app.listen(port, () => { 28 | console.log(`Express server listening on port ${port}`); 29 | }); 30 | -------------------------------------------------------------------------------- /examples/typescript/download/download.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["download.ts"],"names":[],"mappings":";AAAA,qCAAkD,CAAC,qCAAqC;AACxF,yBAA0B;AAE1B,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEjC,MAAM,CAAC,KAAK,EAAE,CAAC;AAEf,MAAM,CAAC,GAAG,CAAC;IACT,UAAU,EAAE;QACV,WAAW,EAAE;YACX,WAAW,EAAE,qCAAqC;SACnD;QACD,UAAU,EAAE;YACV,WAAW,EAAE,sCAAsC;SACpD;KACF;CACF,EAAE,CAAC,KAAU,EAAE,MAAW,EAAE,EAAE;IAC7B,MAAM,GAAG,GAAG,IAAI,iBAAO,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7D,GAAG,CAAC,wBAAwB,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;SACrD,IAAI,CAAC,CAAC,IAAS,EAAE,EAAE;QAClB,4DAA4D;QAC5D,+DAA+D;QAC/D,6BAA6B;QAC7B,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAS,IAAK,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE;YAC/E,IAAI,GAAG,EAAE;gBAAE,MAAM,GAAG,CAAC;aAAE;YACvB,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,IAAI,SAAS,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,GAA0C,EAAE,EAAE;QACpD,MAAM,GAAG,CAAC;IACZ,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"} -------------------------------------------------------------------------------- /examples/typescript/upload/upload.ts: -------------------------------------------------------------------------------- 1 | import { Dropbox, Error, files } from 'dropbox'; // eslint-disable-line no-unused-vars 2 | import fs = require('fs'); 3 | import path = require('path'); 4 | 5 | const prompt = require('prompt'); 6 | 7 | prompt.start(); 8 | 9 | prompt.get({ 10 | properties: { 11 | accessToken: { 12 | description: 'Please enter an API V2 access token', 13 | }, 14 | }, 15 | }, (error: any, result: any) => { 16 | const dbx = new Dropbox({ accessToken: result.accessToken }); 17 | 18 | fs.readFile(path.join(__dirname, '/basic.js'), 'utf8', (err, contents) => { 19 | if (err) { 20 | console.log('Error: ', err); 21 | } 22 | 23 | // This uploads basic.js to the root of your dropbox 24 | dbx.filesUpload({ path: '/basic.js', contents }) 25 | .then((response: any) => { 26 | console.log(response); 27 | }) 28 | .catch((uploadErr: Error) => { 29 | console.log(uploadErr); 30 | }); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /examples/typescript/upload/index.js: -------------------------------------------------------------------------------- 1 | Object.defineProperty(exports, "__esModule", { value: true }); 2 | const dropbox_1 = require("dropbox"); // eslint-disable-line no-unused-vars 3 | const fs = require("fs"); 4 | const path = require("path"); 5 | const prompt = require('prompt'); 6 | prompt.start(); 7 | prompt.get({ 8 | properties: { 9 | accessToken: { 10 | description: 'Please enter an API V2 access token', 11 | }, 12 | }, 13 | }, (error, result) => { 14 | const dbx = new dropbox_1.Dropbox({ accessToken: result.accessToken }); 15 | fs.readFile(path.join(__dirname, '/basic.js'), 'utf8', (err, contents) => { 16 | if (err) { 17 | console.log('Error: ', err); 18 | } 19 | // This uploads basic.js to the root of your dropbox 20 | dbx.filesUpload({ path: '/basic.js', contents }) 21 | .then((response) => { 22 | console.log(response); 23 | }) 24 | .catch((uploadErr) => { 25 | console.log(uploadErr); 26 | }); 27 | }); 28 | }); 29 | //# sourceMappingURL=upload.js.map -------------------------------------------------------------------------------- /test/build/browser/umd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
    11 |
  • 12 |

    No Execution

    13 | 14 | 22 |
  • 23 |
24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /test/build/browser/umd.min.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
    11 |
  • 12 |

    No Execution

    13 | 14 | 22 |
  • 23 |
24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Dropbox JavaScript SDK Examples 2 | 3 | To run the examples in your development environment: 4 | 5 | 1. Clone this repo 6 | 2. Run `npm install` and `npm run build` 7 | 3. Start the development server with `node server.js`. 8 | 4. Point your browser to 9 | 10 | # Dropbox TypeScript SDK Examples 11 | 12 | To run the examples in your development environment: 13 | 14 | 1. Clone this repo 15 | 2. Run `npm install` and `npm run build` 16 | 3. Run the example you want (basic, download, team, team-as-user, or upload) 17 | e.g. `node basic` 18 | 19 | ## Code flow example 20 | 21 | 1. Clone this repo 22 | 2. Run `npm install` and `npm run build` in the root of the repository 23 | 3. Create an app in the [App console](https://www.dropbox.com/developers/apps). 24 | 4. Set a redirect URI "http://localhost:3000/auth" on the app's page on the [App console](https://www.dropbox.com/developers/apps). 25 | 5. Set app key and secret in `examples/javascript/simple-backend/code_flow_example.js` on lines 17 and 18. 26 | 6. Run `node examples/javascript/simple-backend/code_flow_example.js` 27 | 7. Point your browser to 28 | -------------------------------------------------------------------------------- /test/build/browser/es.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
    10 |
  • 11 |

    No Execution

    12 | 13 | 22 |
  • 23 |
24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /examples/typescript/download/download.ts: -------------------------------------------------------------------------------- 1 | import { Dropbox, Error, sharing } from 'dropbox'; // eslint-disable-line no-unused-vars 2 | import fs = require('fs'); 3 | 4 | const prompt = require('prompt'); 5 | 6 | prompt.start(); 7 | 8 | prompt.get({ 9 | properties: { 10 | accessToken: { 11 | description: 'Please enter an API V2 access token', 12 | }, 13 | sharedLink: { 14 | description: 'Please enter a shared link to a file', 15 | }, 16 | }, 17 | }, (error: any, result: any) => { 18 | const dbx = new Dropbox({ accessToken: result.accessToken }); 19 | dbx.sharingGetSharedLinkFile({ url: result.sharedLink }) 20 | .then((data: any) => { 21 | // Note: The fileBinary field is not part of the Dropbox SDK 22 | // specification, so it is not included in the TypeScript type. 23 | // It is injected by the SDK. 24 | fs.writeFile(data.result.name, ( data).result.fileBinary, { encoding: 'binary' }, (err) => { 25 | if (err) { throw err; } 26 | console.log(`File: ${data.result.name} saved.`); 27 | }); 28 | }) 29 | .catch((err: Error) => { 30 | throw err; 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Dropbox Inc., http://www.dropbox.com/ 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | import { terser } from 'rollup-plugin-terser'; 3 | 4 | /** 5 | * We use rollup for the UMD build. 6 | * Rollup is only needed for this because UMD is the 7 | * only build configuration that requires us to bundle 8 | * all assets into a single file. 9 | * 10 | * We also only publish a minified bundle for UMD. 11 | * We use a flag of BUNDLE_TYPE set by cross-env to control 12 | * whether or not we minify the bundle. We use terser to 13 | * do the actual minification and it is only added when the 14 | * BUNDLE_TYPE = minified (BUNDLE_TYPE=normal for basic UMD) 15 | */ 16 | 17 | const config = { 18 | output: { 19 | format: 'umd', 20 | sourcemap: (process.env.BUNDLE_TYPE !== 'minified'), 21 | globals: { 22 | crypto: 'crypto', 23 | }, 24 | }, 25 | external: ['es6-promise/auto', 'crypto'], 26 | plugins: [ 27 | babel(), 28 | ], 29 | }; 30 | 31 | if (process.env.BUNDLE_TYPE === 'minified') { 32 | config.plugins.push( 33 | terser({ 34 | compress: { 35 | pure_getters: true, 36 | unsafe: true, 37 | unsafe_comps: true, 38 | warnings: false, 39 | }, 40 | }), 41 | ); 42 | } 43 | 44 | export default config; 45 | -------------------------------------------------------------------------------- /examples/javascript/utils.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | window.utils = { 3 | parseQueryString(str) { 4 | const ret = Object.create(null); 5 | 6 | if (typeof str !== 'string') { 7 | return ret; 8 | } 9 | 10 | str = str.trim().replace(/^(\?|#|&)/, ''); 11 | 12 | if (!str) { 13 | return ret; 14 | } 15 | 16 | str.split('&').forEach((param) => { 17 | const parts = param.replace(/\+/g, ' ').split('='); 18 | // Firefox (pre 40) decodes `%3D` to `=` 19 | // https://github.com/sindresorhus/query-string/pull/37 20 | let key = parts.shift(); 21 | let val = parts.length > 0 ? parts.join('=') : undefined; 22 | 23 | key = decodeURIComponent(key); 24 | 25 | // missing `=` should be `null`: 26 | // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters 27 | val = val === undefined ? null : decodeURIComponent(val); 28 | 29 | if (ret[key] === undefined) { 30 | ret[key] = val; 31 | } else if (Array.isArray(ret[key])) { 32 | ret[key].push(val); 33 | } else { 34 | ret[key] = [ret[key], val]; 35 | } 36 | }); 37 | 38 | return ret; 39 | }, 40 | }; 41 | }(window)); 42 | -------------------------------------------------------------------------------- /examples/typescript/download/index.js: -------------------------------------------------------------------------------- 1 | Object.defineProperty(exports, "__esModule", { value: true }); 2 | const dropbox_1 = require("dropbox"); // eslint-disable-line no-unused-vars 3 | const fs = require("fs"); 4 | const prompt = require('prompt'); 5 | prompt.start(); 6 | prompt.get({ 7 | properties: { 8 | accessToken: { 9 | description: 'Please enter an API V2 access token', 10 | }, 11 | sharedLink: { 12 | description: 'Please enter a shared link to a file', 13 | }, 14 | }, 15 | }, (error, result) => { 16 | const dbx = new dropbox_1.Dropbox({ accessToken: result.accessToken }); 17 | dbx.sharingGetSharedLinkFile({ url: result.sharedLink }) 18 | .then((data) => { 19 | // Note: The fileBinary field is not part of the Dropbox SDK 20 | // specification, so it is not included in the TypeScript type. 21 | // It is injected by the SDK. 22 | fs.writeFile(data.result.name, data.result.fileBinary, { encoding: 'binary' }, (err) => { 23 | if (err) { 24 | throw err; 25 | } 26 | console.log(`File: ${data.result.name} saved.`); 27 | }); 28 | }) 29 | .catch((err) => { 30 | throw err; 31 | }); 32 | }); 33 | //# sourceMappingURL=download.js.map -------------------------------------------------------------------------------- /test/types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": ["./types_test.ts"], 3 | "compilerOptions": { 4 | /* Basic Options */ 5 | "incremental": false /* Enable incremental compilation */, 6 | "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, 7 | "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, 8 | "lib": ["esnext"], 9 | 10 | /* Strict Type-Checking Options */ 11 | "strict": true /* Enable all strict type-checking options. */, 12 | "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */, 13 | "strictNullChecks": true /* Enable strict null checks. */, 14 | "strictFunctionTypes": true /* Enable strict checking of function types. */, 15 | "strictBindCallApply": true /* Enable strict 'bind', 'call', and 'apply' methods on functions. */, 16 | "strictPropertyInitialization": true /* Enable strict checking of property initialization in classes. */, 17 | "noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */, 18 | "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */ 19 | }, 20 | "exclude": [ 21 | "node_modules" 22 | ] 23 | } -------------------------------------------------------------------------------- /examples/javascript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Dropbox JavaScript SDK Examples 6 | 7 | 8 | 9 | 10 | 11 | 26 | 27 |
28 | 37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /examples/javascript/PKCE-backend/code_flow_example.js: -------------------------------------------------------------------------------- 1 | // Standalone example to demonstrate codeflow. 2 | // Start the server, hit localhost:3000 on the browser, and click through. 3 | // On the server logs, you should have the auth code, as well as the token 4 | // from exchanging it. This exchange is invisible to the app user 5 | 6 | const fetch = require('node-fetch'); 7 | const app = require('express')(); 8 | 9 | const hostname = 'localhost'; 10 | const port = 3000; 11 | 12 | const config = { 13 | fetch, 14 | clientId: '42zjexze6mfpf7x', 15 | }; 16 | 17 | const { Dropbox } = require('dropbox'); // eslint-disable-line import/no-unresolved 18 | 19 | const dbx = new Dropbox(config); 20 | 21 | const redirectUri = `http://${hostname}:${port}/auth`; 22 | 23 | app.get('/', (req, res) => { 24 | dbx.auth.getAuthenticationUrl(redirectUri, null, 'code', 'offline', null, 'none', true) 25 | .then((authUrl) => { 26 | res.writeHead(302, { Location: authUrl }); 27 | res.end(); 28 | }); 29 | }); 30 | 31 | app.get('/auth', (req, res) => { // eslint-disable-line no-unused-vars 32 | const { code } = req.query; 33 | console.log(`code:${code}`); 34 | 35 | dbx.auth.getAccessTokenFromCode(redirectUri, code) 36 | .then((token) => { 37 | console.log(`Token Result:${JSON.stringify(token)}`); 38 | dbx.auth.setRefreshToken(token.result.refresh_token); 39 | dbx.usersGetCurrentAccount() 40 | .then((response) => { 41 | console.log('response', response); 42 | }) 43 | .catch((error) => { 44 | console.error(error); 45 | }); 46 | }) 47 | .catch((error) => { 48 | console.error(error); 49 | }); 50 | res.end(); 51 | }); 52 | 53 | app.listen(port); 54 | -------------------------------------------------------------------------------- /src/response.js: -------------------------------------------------------------------------------- 1 | import { isWindowOrWorker } from './utils.js'; 2 | import { DropboxResponseError } from './error.js'; 3 | 4 | export class DropboxResponse { 5 | constructor(status, headers, result) { 6 | this.status = status; 7 | this.headers = headers; 8 | this.result = result; 9 | } 10 | } 11 | 12 | function throwAsError(res) { 13 | return res.text() 14 | .then((data) => { 15 | let errorObject; 16 | try { 17 | errorObject = JSON.parse(data); 18 | } catch (error) { 19 | errorObject = data; 20 | } 21 | 22 | throw new DropboxResponseError(res.status, res.headers, errorObject); 23 | }); 24 | } 25 | 26 | export function parseResponse(res) { 27 | if (!res.ok) { 28 | return throwAsError(res); 29 | } 30 | return res.text() 31 | .then((data) => { 32 | let responseObject; 33 | try { 34 | responseObject = JSON.parse(data); 35 | } catch (error) { 36 | responseObject = data; 37 | } 38 | 39 | return new DropboxResponse(res.status, res.headers, responseObject); 40 | }); 41 | } 42 | 43 | export function parseDownloadResponse(res) { 44 | if (!res.ok) { 45 | return throwAsError(res); 46 | } 47 | return new Promise((resolve) => { 48 | if (isWindowOrWorker()) { 49 | res.blob().then((data) => resolve(data)); 50 | } else { 51 | res.buffer().then((data) => resolve(data)); 52 | } 53 | }).then((data) => { 54 | const result = JSON.parse(res.headers.get('dropbox-api-result')); 55 | 56 | if (isWindowOrWorker()) { 57 | result.fileBlob = data; 58 | } else { 59 | result.fileBinary = data; 60 | } 61 | 62 | return new DropboxResponse(res.status, res.headers, result); 63 | }); 64 | } 65 | -------------------------------------------------------------------------------- /examples/javascript/simple-backend/code_flow_example.js: -------------------------------------------------------------------------------- 1 | // Standalone example to demonstrate codeflow. 2 | // Start the server, hit localhost:3000 on the browser, and click through. 3 | // On the server logs, you should have the auth code, as well as the token 4 | // from exchanging it. This exchange is invisible to the app user 5 | 6 | const fetch = require('node-fetch'); 7 | const app = require('express')(); 8 | 9 | const hostname = 'localhost'; 10 | const port = 3000; 11 | 12 | const config = { 13 | fetch, 14 | clientId: 'APP_KEY_HERE', 15 | clientSecret: 'APP_SECRET_HERE', 16 | }; 17 | 18 | const { Dropbox } = require('dropbox'); // eslint-disable-line import/no-unresolved 19 | 20 | const dbx = new Dropbox(config); 21 | 22 | const redirectUri = `http://${hostname}:${port}/auth`; 23 | app.get('/', (req, res) => { 24 | dbx.auth.getAuthenticationUrl(redirectUri, null, 'code', 'offline', null, 'none', false) 25 | .then((authUrl) => { 26 | res.writeHead(302, { Location: authUrl }); 27 | res.end(); 28 | }); 29 | }); 30 | 31 | app.get('/auth', (req, res) => { // eslint-disable-line no-unused-vars 32 | const { code } = req.query; 33 | console.log(`code:${code}`); 34 | 35 | dbx.auth.getAccessTokenFromCode(redirectUri, code) 36 | .then((token) => { 37 | console.log(`Token Result:${JSON.stringify(token)}`); 38 | dbx.auth.setRefreshToken(token.result.refresh_token); 39 | dbx.usersGetCurrentAccount() 40 | .then((response) => { 41 | console.log('response', response); 42 | }) 43 | .catch((error) => { 44 | console.error(error); 45 | }); 46 | }) 47 | .catch((error) => { 48 | console.error(error); 49 | }); 50 | res.end(); 51 | }); 52 | 53 | app.listen(port); 54 | -------------------------------------------------------------------------------- /examples/javascript/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 4 | line-height: 1.5; 5 | } 6 | .container { 7 | display: block; 8 | width: 90%; 9 | max-width: 800px; 10 | margin-left: auto; 11 | margin-right: auto; 12 | } 13 | .container.main { 14 | padding-top: 30px; 15 | } 16 | code, .code { 17 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; 18 | color: #666; 19 | } 20 | .info { 21 | font-size: 13px; 22 | font-style: italic; 23 | color: #666; 24 | margin-top: 40px; 25 | } 26 | a { 27 | color: #007ee5; 28 | } 29 | input { 30 | border: 2px solid #007ee5; 31 | border-radius: 3px; 32 | padding: 8px; 33 | font-size: 16px; 34 | } 35 | .button, button { 36 | border-radius: 3px; 37 | background-color: #007ee5; 38 | border: none; 39 | color: #fff; 40 | font-size: 16px; 41 | padding: 10px 15px; 42 | text-decoration: none; 43 | } 44 | 45 | .page-header { 46 | background-color: #007ee5; 47 | padding: 10px 0 0 0; 48 | } 49 | .page-header .container { 50 | display: flex; 51 | flex-direction: column; 52 | justify-content: space-between; 53 | height: 150px; 54 | } 55 | .page-header a { 56 | color: #fff; 57 | text-decoration: none; 58 | } 59 | .page-header nav { 60 | display: flex; 61 | justify-content: space-between; 62 | align-items: center; 63 | } 64 | .page-header h1 { 65 | display: flex; 66 | align-items: center; 67 | color: #fff; 68 | font-size: 17px; 69 | font-weight: 200; 70 | } 71 | .page-header .logo { 72 | width: 100px; 73 | margin-right: 10px; 74 | } 75 | .page-header .view-source { 76 | font-weight: 200; 77 | font-size: 12px; 78 | } 79 | .page-header h2 { 80 | color: #fff; 81 | font-size: 18px; 82 | font-weight: normal; 83 | } 84 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE config folders 2 | .idea/ 3 | 4 | #Output Directories 5 | es/ 6 | cjs/ 7 | umd/ 8 | 9 | # Logs 10 | logs 11 | *.log 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | lerna-debug.log* 16 | 17 | 18 | docs/ 19 | 20 | # Diagnostic reports (https://nodejs.org/api/report.html) 21 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 22 | 23 | # Runtime data 24 | pids 25 | *.pid 26 | *.seed 27 | *.pid.lock 28 | 29 | # Directory for instrumented libs generated by jscoverage/JSCover 30 | lib-cov 31 | 32 | # Coverage directory used by tools like istanbul 33 | coverage 34 | *.lcov 35 | 36 | # nyc test coverage 37 | .nyc_output 38 | 39 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 40 | .grunt 41 | 42 | # Bower dependency directory (https://bower.io/) 43 | bower_components 44 | 45 | # node-waf configuration 46 | .lock-wscript 47 | 48 | # Compiled binary addons (https://nodejs.org/api/addons.html) 49 | build/Release 50 | 51 | # Dependency directories 52 | node_modules/ 53 | jspm_packages/ 54 | 55 | # TypeScript v1 declaration files 56 | typings/ 57 | 58 | # TypeScript cache 59 | *.tsbuildinfo 60 | 61 | # Optional npm cache directory 62 | .npm 63 | 64 | # Optional eslint cache 65 | .eslintcache 66 | 67 | # Microbundle cache 68 | .rpt2_cache/ 69 | .rts2_cache_cjs/ 70 | .rts2_cache_es/ 71 | .rts2_cache_umd/ 72 | 73 | # Optional REPL history 74 | .node_repl_history 75 | 76 | # Output of 'npm pack' 77 | *.tgz 78 | 79 | # Yarn Integrity file 80 | .yarn-integrity 81 | 82 | # dotenv environment variables file 83 | .env 84 | .env.test 85 | 86 | # parcel-bundler cache (https://parceljs.org/) 87 | .cache 88 | 89 | # Next.js build output 90 | .next 91 | 92 | # Nuxt.js build / generate output 93 | .nuxt 94 | dist 95 | 96 | # Gatsby files 97 | .cache/ 98 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 99 | # https://nextjs.org/blog/next-9-1#public-directory-support 100 | # public 101 | 102 | # vuepress build output 103 | .vuepress/dist 104 | 105 | # Serverless directories 106 | .serverless/ 107 | 108 | # FuseBox cache 109 | .fusebox/ 110 | 111 | # DynamoDB Local files 112 | .dynamodb/ 113 | 114 | # TernJS port file 115 | .tern-port 116 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: CodeCov 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | schedule: 8 | - cron: 0 0 * * * 9 | 10 | jobs: 11 | Unit: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2.3.4 15 | - name: Setup Node.js environment 16 | uses: actions/setup-node@v2.1.5 17 | with: 18 | node-version: '14' 19 | - name: Install SDK 20 | run: | 21 | npm install 22 | - name: Generate Unit Test Coverage 23 | run: | 24 | npm run coverage:unit 25 | - name: Publish Coverage 26 | uses: codecov/codecov-action@v1.5.0 27 | with: 28 | flags: unit 29 | fail_ci_if_error: true 30 | Integration: 31 | runs-on: ubuntu-latest 32 | steps: 33 | - uses: actions/checkout@v2.3.4 34 | - name: Setup Node.js environment 35 | uses: actions/setup-node@v2.1.5 36 | with: 37 | node-version: '14' 38 | - name: Install SDK 39 | run: | 40 | npm install 41 | - name: Generate Integration Test Coverage 42 | env: 43 | LEGACY_USER_DROPBOX_TOKEN: ${{ secrets.LEGACY_USER_DROPBOX_TOKEN }} 44 | LEGACY_USER_CLIENT_ID: ${{ secrets.LEGACY_USER_CLIENT_ID }} 45 | LEGACY_USER_CLIENT_SECRET: ${{ secrets.LEGACY_USER_CLIENT_SECRET }} 46 | LEGACY_USER_REFRESH_TOKEN: ${{ secrets.LEGACY_USER_REFRESH_TOKEN }} 47 | SCOPED_USER_DROPBOX_TOKEN: ${{ secrets.SCOPED_USER_DROPBOX_TOKEN }} 48 | SCOPED_USER_CLIENT_ID: ${{ secrets.SCOPED_USER_CLIENT_ID }} 49 | SCOPED_USER_CLIENT_SECRET: ${{ secrets.SCOPED_USER_CLIENT_SECRET }} 50 | SCOPED_USER_REFRESH_TOKEN: ${{ secrets.SCOPED_USER_REFRESH_TOKEN }} 51 | SCOPED_TEAM_DROPBOX_TOKEN: ${{ secrets.SCOPED_TEAM_DROPBOX_TOKEN }} 52 | SCOPED_TEAM_CLIENT_ID: ${{ secrets.SCOPED_TEAM_CLIENT_ID }} 53 | SCOPED_TEAM_CLIENT_SECRET: ${{ secrets.SCOPED_TEAM_CLIENT_SECRET }} 54 | SCOPED_TEAM_REFRESH_TOKEN: ${{ secrets.SCOPED_TEAM_REFRESH_TOKEN }} 55 | DROPBOX_SHARED_LINK: ${{ secrets.DROPBOX_SHARED_LINK }} 56 | run: | 57 | npm run coverage:integration 58 | - name: Publish Coverage 59 | uses: codecov/codecov-action@v1.5.0 60 | with: 61 | flags: integration 62 | fail_ci_if_error: true 63 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | import { DEFAULT_API_DOMAIN, DEFAULT_DOMAIN, TEST_DOMAIN_MAPPINGS } from './constants'; 2 | 3 | function getSafeUnicode(c) { 4 | const unicode = `000${c.charCodeAt(0).toString(16)}`.slice(-4); 5 | return `\\u${unicode}`; 6 | } 7 | 8 | export const baseApiUrl = (subdomain, domain = DEFAULT_API_DOMAIN, domainDelimiter = '.') => { 9 | if (!domainDelimiter) { 10 | return `https://${domain}/2/`; 11 | } 12 | if (domain !== DEFAULT_API_DOMAIN && TEST_DOMAIN_MAPPINGS[subdomain] !== undefined) { 13 | subdomain = TEST_DOMAIN_MAPPINGS[subdomain]; 14 | domainDelimiter = '-'; 15 | } 16 | return `https://${subdomain}${domainDelimiter}${domain}/2/`; 17 | }; 18 | export const OAuth2AuthorizationUrl = (domain = DEFAULT_DOMAIN) => { 19 | if (domain !== DEFAULT_DOMAIN) { 20 | domain = `meta-${domain}`; 21 | } 22 | return `https://${domain}/oauth2/authorize`; 23 | }; 24 | export const OAuth2TokenUrl = (domain = DEFAULT_API_DOMAIN, domainDelimiter = '.') => { 25 | let subdomain = 'api'; 26 | if (domain !== DEFAULT_API_DOMAIN) { 27 | subdomain = TEST_DOMAIN_MAPPINGS[subdomain]; 28 | domainDelimiter = '-'; 29 | } 30 | return `https://${subdomain}${domainDelimiter}${domain}/oauth2/token`; 31 | }; 32 | 33 | // source https://www.dropboxforum.com/t5/API-support/HTTP-header-quot-Dropbox-API-Arg-quot-could-not-decode-input-as/m-p/173823/highlight/true#M6786 34 | export function httpHeaderSafeJson(args) { 35 | return JSON.stringify(args).replace(/[\u007f-\uffff]/g, getSafeUnicode); 36 | } 37 | 38 | export function getTokenExpiresAtDate(expiresIn) { 39 | return new Date(Date.now() + (expiresIn * 1000)); 40 | } 41 | 42 | /* global WorkerGlobalScope */ 43 | export function isWindowOrWorker() { 44 | return ( 45 | ( 46 | typeof WorkerGlobalScope !== 'undefined' 47 | && self instanceof WorkerGlobalScope // eslint-disable-line no-restricted-globals 48 | ) 49 | || ( 50 | typeof module === 'undefined' 51 | || typeof window !== 'undefined' 52 | ) 53 | ); 54 | } 55 | 56 | export function isBrowserEnv() { 57 | return typeof window !== 'undefined'; 58 | } 59 | 60 | export function isWorkerEnv() { 61 | return typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope; // eslint-disable-line no-restricted-globals 62 | } 63 | 64 | export function createBrowserSafeString(toBeConverted) { 65 | const convertedString = toBeConverted.toString('base64') 66 | .replace(/\+/g, '-') 67 | .replace(/\//g, '_') 68 | .replace(/=/g, ''); 69 | return convertedString; 70 | } 71 | -------------------------------------------------------------------------------- /test/unit/response.js: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import chaiAsPromised from 'chai-as-promised'; 3 | import { Response } from 'node-fetch'; 4 | import { httpHeaderSafeJson } from '../../src/utils'; 5 | import { 6 | DropboxResponse, 7 | parseResponse, 8 | parseDownloadResponse, 9 | } from '../../src/response.js'; 10 | import { DropboxResponseError } from '../../src/error.js'; 11 | 12 | chai.use(chaiAsPromised); 13 | describe('DropboxResponse', () => { 14 | describe('Status', () => { 15 | it('can be set in the constructor', () => { 16 | const response = new DropboxResponse(200, {}, {}); 17 | chai.assert.equal(response.status, 200); 18 | }); 19 | }); 20 | 21 | describe('Headers', () => { 22 | it('can be set in the constructor', () => { 23 | const response = new DropboxResponse(200, {}, {}); 24 | chai.assert.deepEqual(response.headers, {}); 25 | }); 26 | }); 27 | 28 | describe('Result', () => { 29 | it('can be set in the constructor', () => { 30 | const response = new DropboxResponse(200, {}, {}); 31 | chai.assert.deepEqual(response.result, {}); 32 | }); 33 | }); 34 | 35 | describe('parseResponse', () => { 36 | it('correctly parses the response', () => { 37 | const init = { 38 | status: 200, 39 | }; 40 | const response = new Response(undefined, init); 41 | return chai.assert.isFulfilled(parseResponse(response)); 42 | }); 43 | 44 | it('throws an error when not a 200 status code', () => { 45 | const statusArray = [300, 400, 500]; 46 | for (const status of statusArray) { 47 | const init = { 48 | status, 49 | }; 50 | const response = new Response(undefined, init); 51 | chai.assert.isRejected(parseResponse(response), DropboxResponseError); 52 | } 53 | }); 54 | }); 55 | 56 | describe('parseDownloadResponse', () => { 57 | it('correctly parses the response', () => { 58 | const init = { 59 | status: 200, 60 | headers: { 61 | 'dropbox-api-result': httpHeaderSafeJson({ fileBinary: 'test' }), 62 | }, 63 | }; 64 | const response = new Response(undefined, init); 65 | return chai.assert.isFulfilled(parseDownloadResponse(response)); 66 | }); 67 | 68 | it('throws an error when not a 200 status code', () => { 69 | const statusArray = [300, 400, 500]; 70 | for (const status of statusArray) { 71 | const init = { 72 | status, 73 | }; 74 | const response = new Response(undefined, init); 75 | chai.assert.isRejected(parseDownloadResponse(response), DropboxResponseError); 76 | } 77 | }); 78 | }); 79 | }); 80 | -------------------------------------------------------------------------------- /test/types/types_test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /** 3 | * This file does not exist to be executed, just compiled, 4 | * so that we can ensure that the definition files 5 | * only reference names that exist, 6 | * and to perform a basic sanity check that types are exported as intended. 7 | */ 8 | Object.defineProperty(exports, "__esModule", { value: true }); 9 | var Dropbox = require("../../types/index"); // eslint-disable-line 10 | // Check DropboxAuth Constructor and Methods 11 | // Test default constructor 12 | var dropboxAuth = new Dropbox.DropboxAuth(); 13 | // Test config constructor 14 | dropboxAuth = new Dropbox.DropboxAuth({ 15 | accessToken: 'myToken', 16 | accessTokenExpiresAt: new Date(Date.now()), 17 | refreshToken: 'myToken', 18 | clientId: 'myClientId', 19 | clientSecret: 'myClientSecret', 20 | }); 21 | // Test getters/setters 22 | dropboxAuth.setAccessToken('myToken'); 23 | dropboxAuth.getAccessToken(); 24 | dropboxAuth.setAccessTokenExpiresAt(new Date(Date.now())); 25 | dropboxAuth.getAccessTokenExpiresAt(); 26 | dropboxAuth.setRefreshToken('myToken'); 27 | dropboxAuth.getRefreshToken(); 28 | dropboxAuth.setClientId('myClientId'); 29 | dropboxAuth.getClientId(); 30 | dropboxAuth.setClientSecret('myClientSecret'); 31 | // Test other methods 32 | dropboxAuth.getAuthenticationUrl('myRedirect'); 33 | dropboxAuth.getAuthenticationUrl('myRedirect', 'myState'); 34 | dropboxAuth.getAuthenticationUrl('myRedirect', 'myState', 'code'); 35 | dropboxAuth.getAuthenticationUrl('myRedirect', 'mystate', 'code', 'offline', ['scope', 'scope'], 'none', false); 36 | dropboxAuth.getAccessTokenFromCode('myRedirect', 'myCode'); 37 | dropboxAuth.checkAndRefreshAccessToken(); 38 | dropboxAuth.refreshAccessToken(); 39 | dropboxAuth.refreshAccessToken(['files.metadata.read', 'files.metadata.write']); 40 | // Check Dropbox Constructor or Methods 41 | // Test config constructor 42 | var dropbox = new Dropbox.Dropbox({ 43 | auth: dropboxAuth, 44 | selectUser: '', 45 | selectAdmin: '', 46 | pathRoot: '', 47 | }); 48 | var dropbox2 = new Dropbox.Dropbox({ 49 | accessToken: 'myToken', 50 | accessTokenExpiresAt: new Date(Date.now()), 51 | refreshToken: 'myToken', 52 | clientId: 'myClientId', 53 | clientSecret: 'myClientSecret', 54 | selectUser: '', 55 | selectAdmin: '', 56 | pathRoot: '', 57 | }); 58 | dropbox.usersGetCurrentAccount() 59 | .then(function (response) { 60 | var status = response.status; 61 | var result = response.result; 62 | var headers = response.headers; 63 | }) 64 | .catch(function (error) { 65 | var status = error.status; 66 | var headers = error.headers; 67 | var errorObject = error.error; 68 | }); 69 | dropbox2.usersGetCurrentAccount(); 70 | -------------------------------------------------------------------------------- /examples/javascript/team/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dropbox JavaScript SDK 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 28 | 29 | 30 |
31 |

This example shows how to use the Dropbox class and the Dropbox.teamDevicesListTeamDevices() method [docs].

32 | 33 |
34 | 35 | 36 |
37 | 38 | 39 |
    40 | 41 |

    This endpoint requires a Dropbox Business API app key, see here for more details.

    42 |
    43 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /test/types/types_test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file does not exist to be executed, just compiled, 3 | * so that we can ensure that the definition files 4 | * only reference names that exist, 5 | * and to perform a basic sanity check that types are exported as intended. 6 | */ 7 | 8 | import { Headers } from 'node-fetch'; 9 | import * as Dropbox from '../../types/index'; // eslint-disable-line 10 | 11 | // Check DropboxAuth Constructor and Methods 12 | // Test default constructor 13 | let dropboxAuth = new Dropbox.DropboxAuth(); 14 | 15 | // Test config constructor 16 | dropboxAuth = new Dropbox.DropboxAuth({ 17 | accessToken: 'myToken', 18 | accessTokenExpiresAt: new Date(Date.now()), 19 | refreshToken: 'myToken', 20 | clientId: 'myClientId', 21 | clientSecret: 'myClientSecret', 22 | }); 23 | 24 | // Test getters/setters 25 | dropboxAuth.setAccessToken('myToken'); 26 | dropboxAuth.getAccessToken(); 27 | dropboxAuth.setAccessTokenExpiresAt(new Date(Date.now())); 28 | dropboxAuth.getAccessTokenExpiresAt(); 29 | dropboxAuth.setRefreshToken('myToken'); 30 | dropboxAuth.getRefreshToken(); 31 | dropboxAuth.setClientId('myClientId'); 32 | dropboxAuth.getClientId(); 33 | dropboxAuth.setClientSecret('myClientSecret'); 34 | 35 | // Test other methods 36 | dropboxAuth.getAuthenticationUrl('myRedirect'); 37 | dropboxAuth.getAuthenticationUrl('myRedirect', 'myState'); 38 | dropboxAuth.getAuthenticationUrl('myRedirect', 'myState', 'code'); 39 | dropboxAuth.getAuthenticationUrl('myRedirect', 'mystate', 'code', 'offline', ['scope', 'scope'], 'none', false); 40 | dropboxAuth.getAccessTokenFromCode('myRedirect', 'myCode'); 41 | dropboxAuth.checkAndRefreshAccessToken(); 42 | dropboxAuth.refreshAccessToken(); 43 | dropboxAuth.refreshAccessToken(['files.metadata.read', 'files.metadata.write']); 44 | 45 | // Check Dropbox Constructor or Methods 46 | // Test config constructor 47 | const dropbox = new Dropbox.Dropbox({ 48 | auth: dropboxAuth, 49 | selectUser: '', 50 | selectAdmin: '', 51 | pathRoot: '', 52 | }); 53 | 54 | const dropbox2 = new Dropbox.Dropbox({ 55 | accessToken: 'myToken', 56 | accessTokenExpiresAt: new Date(Date.now()), 57 | refreshToken: 'myToken', 58 | clientId: 'myClientId', 59 | clientSecret: 'myClientSecret', 60 | selectUser: '', 61 | selectAdmin: '', 62 | pathRoot: '', 63 | }); 64 | 65 | dropbox.usersGetCurrentAccount() 66 | .then((response: Dropbox.DropboxResponse) => { 67 | const { status } = response; 68 | const { result } = response; 69 | const { headers } = response; 70 | }) 71 | .catch((error: Dropbox.DropboxResponseError) => { 72 | const { status } = error; 73 | const { headers } = error; 74 | const errorObject: Dropbox.users.GetAccountError = error.error; 75 | }); 76 | dropbox2.usersGetCurrentAccount(); 77 | -------------------------------------------------------------------------------- /test/unit/error.js: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | 3 | import { DropboxResponseError } from '../../src/error.js'; 4 | 5 | describe('DropboxResponseError', () => { 6 | describe('Error throwing', () => { 7 | it('can be caught with a try/catch', () => { 8 | try { 9 | throw new DropboxResponseError(400, {}, {}); 10 | } catch (error) { 11 | chai.assert.isTrue(error instanceof DropboxResponseError); 12 | chai.assert.equal(error.status, 400); 13 | chai.assert.deepEqual(error.headers, {}); 14 | chai.assert.deepEqual(error.error, {}); 15 | } 16 | }); 17 | 18 | it('can be caught in a promise reject', () => { 19 | new Promise((resolve, reject) => { 20 | reject(new DropboxResponseError(400, {}, {})); 21 | }).catch((error) => { 22 | chai.assert.isTrue(error instanceof DropboxResponseError); 23 | chai.assert.equal(error.status, 400); 24 | chai.assert.deepEqual(error.headers, {}); 25 | chai.assert.deepEqual(error.error, {}); 26 | }); 27 | }); 28 | 29 | it('can be caught if thrown in promise', () => { 30 | new Promise(() => { 31 | throw new DropboxResponseError(400, {}, {}); 32 | }).catch((error) => { 33 | chai.assert.isTrue(error instanceof DropboxResponseError); 34 | chai.assert.equal(error.status, 400); 35 | chai.assert.deepEqual(error.headers, {}); 36 | chai.assert.deepEqual(error.error, {}); 37 | }); 38 | }); 39 | }); 40 | 41 | describe('Message', () => { 42 | it('correctly formats message with response code', () => { 43 | const error = new DropboxResponseError(400, {}, {}); 44 | chai.assert.equal(error.message, 'Response failed with a 400 code'); 45 | }); 46 | }); 47 | 48 | describe('Name', () => { 49 | it('correctly sets name', () => { 50 | const error = new DropboxResponseError(400, {}, {}); 51 | chai.assert.equal(error.name, 'DropboxResponseError'); 52 | }); 53 | }); 54 | 55 | describe('Stack Trace', () => { 56 | it('is set in super', () => { 57 | const error = new DropboxResponseError(400, {}, {}); 58 | chai.assert.exists(error.stack); 59 | }); 60 | }); 61 | 62 | describe('Status', () => { 63 | it('can be set in the constructor', () => { 64 | const error = new DropboxResponseError(400, {}, {}); 65 | chai.assert.equal(error.status, 400); 66 | }); 67 | }); 68 | 69 | describe('Headers', () => { 70 | it('can be set in the constructor', () => { 71 | const error = new DropboxResponseError(400, {}, {}); 72 | chai.assert.deepEqual(error.headers, {}); 73 | }); 74 | }); 75 | 76 | describe('Error', () => { 77 | it('can be set in the constructor', () => { 78 | const error = new DropboxResponseError(400, {}, {}); 79 | chai.assert.deepEqual(error.error, {}); 80 | }); 81 | }); 82 | }); 83 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | pull_request: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | CI: 8 | continue-on-error: true 9 | runs-on: ${{ matrix.os }} 10 | strategy: 11 | matrix: 12 | os: [ubuntu-latest, macos-latest] 13 | node: [10, 11, 12, 13, 14] 14 | steps: 15 | - uses: actions/checkout@v2.3.4 16 | - name: Setup Node.js environment 17 | uses: actions/setup-node@v2.1.5 18 | with: 19 | node-version: ${{ matrix.node }} 20 | - name: Install SDK 21 | run: | 22 | npm install 23 | - name: Run Build 24 | run: | 25 | npm run build 26 | - name: Run Examples Builds 27 | run: | 28 | cd examples/typescript/ 29 | npm install 30 | npm run build 31 | cd ../.. 32 | - name: Run Linter 33 | run: | 34 | npm run lint 35 | - name: Run Unit Tests 36 | run: | 37 | npm run test:unit 38 | - name: Run TypeScipt Tests 39 | run: | 40 | npm run test:typescript 41 | - name: Run Build Tests 42 | if: matrix.node >= 12 # "type" = "module" was introduced in node v12 so lower versions will fail ESM tests 43 | run: | 44 | npm run clean 45 | npm run build 46 | npm run test:build 47 | Integration: 48 | runs-on: ${{ matrix.os }} 49 | strategy: 50 | matrix: 51 | os: [ubuntu-latest, macos-latest] 52 | node: [14] # Can only be ran on 14 because it relies on fs/promises 53 | steps: 54 | - uses: actions/checkout@v2.3.4 55 | - name: Setup Node.js environment 56 | uses: actions/setup-node@v2.1.5 57 | with: 58 | node-version: ${{ matrix.node }} 59 | - name: Install SDK 60 | run: | 61 | npm install 62 | - name: Run Integration Tests 63 | env: 64 | LEGACY_USER_DROPBOX_TOKEN: ${{ secrets.LEGACY_USER_DROPBOX_TOKEN }} 65 | LEGACY_USER_CLIENT_ID: ${{ secrets.LEGACY_USER_CLIENT_ID }} 66 | LEGACY_USER_CLIENT_SECRET: ${{ secrets.LEGACY_USER_CLIENT_SECRET }} 67 | LEGACY_USER_REFRESH_TOKEN: ${{ secrets.LEGACY_USER_REFRESH_TOKEN }} 68 | SCOPED_USER_DROPBOX_TOKEN: ${{ secrets.SCOPED_USER_DROPBOX_TOKEN }} 69 | SCOPED_USER_CLIENT_ID: ${{ secrets.SCOPED_USER_CLIENT_ID }} 70 | SCOPED_USER_CLIENT_SECRET: ${{ secrets.SCOPED_USER_CLIENT_SECRET }} 71 | SCOPED_USER_REFRESH_TOKEN: ${{ secrets.SCOPED_USER_REFRESH_TOKEN }} 72 | SCOPED_TEAM_DROPBOX_TOKEN: ${{ secrets.SCOPED_TEAM_DROPBOX_TOKEN }} 73 | SCOPED_TEAM_CLIENT_ID: ${{ secrets.SCOPED_TEAM_CLIENT_ID }} 74 | SCOPED_TEAM_CLIENT_SECRET: ${{ secrets.SCOPED_TEAM_CLIENT_SECRET }} 75 | SCOPED_TEAM_REFRESH_TOKEN: ${{ secrets.SCOPED_TEAM_REFRESH_TOKEN }} 76 | DROPBOX_SHARED_LINK: ${{ secrets.DROPBOX_SHARED_LINK }} 77 | run: | 78 | npm run test:integration 79 | -------------------------------------------------------------------------------- /.github/workflows/spec_update.yml: -------------------------------------------------------------------------------- 1 | name: Spec Update 2 | on: 3 | workflow_dispatch: 4 | repository_dispatch: 5 | types: [spec_update] 6 | 7 | jobs: 8 | Update: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2.3.4 12 | - name: Setup Python environment 13 | uses: actions/setup-python@v2.2.2 14 | with: 15 | python-version: 3.7 16 | - name: Setup Node.JS environment 17 | uses: actions/setup-node@v2.1.5 18 | with: 19 | node-version: 14 20 | - name: Get current time 21 | uses: 1466587594/get-current-time@v2 22 | id: current-time 23 | with: 24 | format: YYYY_MM_DD 25 | utcOffset: "-08:00" 26 | - name: Update SDK Version 27 | run: npm version --commit-hooks false --git-tag-version false minor 28 | - name: Install SDK 29 | run: | 30 | npm install 31 | - name: Update Modules 32 | run: | 33 | git submodule init 34 | git submodule update --remote --recursive 35 | - name: Generate Branch Name 36 | id: git-branch 37 | run: | 38 | echo "::set-output name=branch::spec_update_${{ steps.current-time.outputs.formattedTime }}" 39 | - name: Generate Num Diffs 40 | id: git-diff-num 41 | run: | 42 | cd generator/ 43 | diffs=$(git diff --submodule dropbox-api-spec | grep ">" | wc -l) 44 | echo "Number of Spec diffs: $diffs" 45 | echo "::set-output name=num-diff::$diffs" 46 | cd .. 47 | - name: Generate Diff 48 | id: git-diff 49 | run: | 50 | cd generator/dropbox-api-spec 51 | gitdiff=$(git log -n ${{ steps.git-diff-num.outputs.num-diff }} --pretty="format:%n %H %n%n %b") 52 | commit="Automated Spec Update $gitdiff" 53 | commit="${commit//'%'/'%25'}" 54 | commit="${commit//$'\n'/'%0A'}" 55 | commit="${commit//$'\r'/'%0D'}" 56 | echo "Commit Message: $commit" 57 | echo "::set-output name=commit::$commit" 58 | cd ../.. 59 | - name: Generate New Routes 60 | run: | 61 | cd generator/stone 62 | python setup.py install 63 | cd .. 64 | python generate_routes.py 65 | cd .. 66 | - name: Create Pull Request 67 | uses: peter-evans/create-pull-request@v3.9.1 68 | if: steps.git-diff-num.outputs.num-diff != 0 69 | with: 70 | token: ${{ secrets.SPEC_UPDATE_TOKEN }} 71 | commit-message: | 72 | ${{ steps.git-diff.outputs.commit}} 73 | branch: ${{ steps.git-branch.outputs.branch }} 74 | delete-branch: true 75 | title: 'Automated Spec Update' 76 | body: | 77 | ${{ steps.git-diff.outputs.commit}} 78 | base: 'main' 79 | team-reviewers: | 80 | owners 81 | maintainers 82 | draft: false -------------------------------------------------------------------------------- /examples/javascript/team-as-user/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dropbox JavaScript SDK 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 28 | 29 | 30 |
    31 |

    This example shows how to use the Dropbox class and the selectUser [docs] parameter, to retreive a Dropbox class that is acting as a specific user on the team.

    32 | 33 |
    34 | 35 | 36 | 37 |
    38 | 39 | 40 |
      41 | 42 |

      This endpoint requires a Dropbox Business API app key, see here for more details.

      43 |
      44 | 45 | 46 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /examples/javascript/basic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dropbox JavaScript SDK 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 28 | 29 | 30 |
      31 |

      This example fetches the contents of your root Dropbox directory. It uses the Dropbox.filesListFolder() method [docs].

      32 | 33 |
      34 | 35 | 36 |
      37 | 38 | 39 |
        40 | 41 |

        To obtain an access token for quick testing, you can go to API Explorer click the "Get Token" button on the top right, copy the token it creates and then paste it here.

        42 |
        43 | 44 | 45 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /examples/javascript/download/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dropbox JavaScript SDK 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 28 | 29 | 30 |
        31 |

        This example shows how to use the Dropbox.sharingGetSharedLinkFile() [docs] method to download the file for the given shared link.

        32 | 33 |
        34 | 35 | 36 | 37 |
        38 | 39 | 40 |
        41 | 42 |

        To obtain an access token for quick testing, you can go to API Explorer click the "Get Token" button on the top right, copy the token it creates and then paste it here.

        43 |
        44 | 45 | 46 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /test/unit/utils.js: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import { 3 | baseApiUrl, 4 | getTokenExpiresAtDate, 5 | isWindowOrWorker, 6 | OAuth2AuthorizationUrl, 7 | OAuth2TokenUrl, 8 | isWorkerEnv, 9 | } from '../../src/utils.js'; 10 | 11 | describe('Dropbox utils', () => { 12 | describe('baseApiUrl', () => { 13 | it('correctly sets base url when domainDelimiter is empty', () => { 14 | const host = 'api'; 15 | const domain = 'mydomain.com'; 16 | const testUrl = baseApiUrl(host, domain, ''); 17 | chai.assert.equal(testUrl, 'https://mydomain.com/2/'); 18 | }); 19 | 20 | it('correctly sets base url when provided a subdomain', () => { 21 | const host = 'test'; 22 | const testUrl = baseApiUrl(host); 23 | chai.assert.equal(testUrl, 'https://test.dropboxapi.com/2/'); 24 | }); 25 | 26 | it('correctly sets base url when provided a subdomain and domain', () => { 27 | const host = 'test'; 28 | const domain = 'mydomain.com'; 29 | const testUrl = baseApiUrl(host, domain); 30 | chai.assert.equal(testUrl, 'https://test.mydomain.com/2/'); 31 | }); 32 | }); 33 | 34 | it('correctly sets base url when provided a normal subdomain and domain', () => { 35 | const host = 'api'; 36 | const domain = 'mydomain.com'; 37 | const testUrl = baseApiUrl(host, domain); 38 | chai.assert.equal(testUrl, 'https://api-mydomain.com/2/'); 39 | }); 40 | }); 41 | 42 | describe('OAuth2AuthorizationUrl', () => { 43 | it('correctly returns the authorization url when not provided an override', () => { 44 | const testUrl = OAuth2AuthorizationUrl(); 45 | chai.assert.equal(testUrl, 'https://dropbox.com/oauth2/authorize'); 46 | }); 47 | 48 | it('correctly returns the authorization url when provided an override', () => { 49 | const domain = 'mydomain.com'; 50 | const testUrl = OAuth2AuthorizationUrl(domain); 51 | chai.assert.equal(testUrl, 'https://meta-mydomain.com/oauth2/authorize'); 52 | }); 53 | }); 54 | 55 | describe('OAuth2TokenUrl', () => { 56 | it('correctly returns the authorization url when not provided an override', () => { 57 | const testUrl = OAuth2TokenUrl(); 58 | chai.assert.equal(testUrl, 'https://api.dropboxapi.com/oauth2/token'); 59 | }); 60 | 61 | it('correctly returns the authorization url when provided an override', () => { 62 | const domain = 'mydomain.com'; 63 | const testUrl = OAuth2TokenUrl(domain); 64 | chai.assert.equal(testUrl, 'https://api-mydomain.com/oauth2/token'); 65 | }); 66 | }); 67 | 68 | describe('getTokenExpiresAtDate', () => { 69 | it('correctly sets when the token will expire', () => { 70 | const expirationTime = 600; 71 | const currentDate = new Date(Date.now()); 72 | const expiresDate = getTokenExpiresAtDate(expirationTime); 73 | // adding a buffer of 100ms to expiration time 74 | chai.assert.isTrue((expiresDate - currentDate) / 1000 <= (expirationTime + 100)); 75 | }); 76 | }); 77 | 78 | describe('isWindowOrWorker', () => { 79 | it('returns false when not window or of type WorkerGlobalScope', () => { 80 | const testEnv = isWindowOrWorker(); 81 | chai.assert.isFalse(testEnv); 82 | }); 83 | }); 84 | 85 | describe('isWorkerEnv', () => { 86 | it('returns false when not running in a service worker env', () => { 87 | chai.assert.isFalse(isWorkerEnv()); 88 | }); 89 | }); 90 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the Dropbox SDK for Javascript 2 | We value and rely on the feedback from our community. This comes in the form of bug reports, feature requests, and general guidance. We welcome your issues and pull requests and try our hardest to be timely in both response and resolution. Please read through this document before submitting issues or pull requests to ensure we have the necessary information to help you resolve your issue. 3 | 4 | ## Filing Bug Reports 5 | You can file a bug report on the [GitHub Issues][issues] page. 6 | 7 | 1. Search through existing issues to ensure that your issue has not been reported. If it is a common issue, there is likely already an issue. 8 | 9 | 2. Please ensure you are using the latest version of the SDK. While this may be a valid issue, we only will fix bugs affecting the latest version and your bug may have been fixed in a newer version. 10 | 11 | 3. Provide as much information as you can regarding the language version, SDK version, and any other relevant information about your environment so we can help resolve the issue as quickly as possible. 12 | 13 | ## Submitting Pull Requests 14 | 15 | We are more than happy to recieve pull requests helping us improve the state of our SDK. You can open a new pull request on the [GitHub Pull Requests][pr] page. 16 | 17 | 1. Please ensure that you have read the [License][license], [Code of Conduct][coc] and have signed the [Contributing License Agreement (CLA)][cla]. 18 | 19 | 2. Please add tests confirming the new functionality works. Pull requests will not be merged without passing continuous integration tests unless the pull requests aims to fix existing issues with these tests. 20 | 21 | 3. If the pull request is modifying typescript definitions, please remember to change the template found under `generator/typescript` and run the generation instead of manually changing types. If there is an issue with the generation, please file an issue. 22 | 23 | ## Updating Generated Code 24 | 25 | Generated code can be updated by running the following commands: 26 | 27 | ``` 28 | $ git submodule init 29 | $ git submodule update --remote --recursive 30 | $ cd generator/stone 31 | $ python setup.py install 32 | $ cd .. 33 | $ python generate_routes.py 34 | ``` 35 | 36 | This will generate typescript definitions and route code. 37 | 38 | ## Testing the Code 39 | 40 | Tests live under the `test/` folder and are then broken down into the type of test it is. To run both the unit tests and the typescript tests, you can use: 41 | 42 | ``` 43 | $ npm test 44 | ``` 45 | 46 | If you would like to run the integration tests locally, you can run: 47 | 48 | ``` 49 | export DROPBOX_TOKEN={fill in user token} 50 | export DROPBOX_TEAM_TOKEN={fill in team token} 51 | export DROPBOX_USER_ID={fill in assume user id} 52 | export DROPBOX_SHARED_LINK={fill in shared link} 53 | $ npm run test:integration 54 | ``` 55 | 56 | Note: If you do not have all of these tokens available, we run integration tests as a part of pull request validation and you are able to rely on those if you are unable to obtain yourself. 57 | 58 | [issues]: https://github.com/dropbox/dropbox-sdk-js/issues 59 | [pr]: https://github.com/dropbox/dropbox-sdk-js/pulls 60 | [coc]: https://github.com/dropbox/dropbox-sdk-js/blob/main/CODE_OF_CONDUCT.md 61 | [license]: https://github.com/dropbox/dropbox-sdk-js/blob/main/LICENSE 62 | [cla]: https://opensource.dropbox.com/cla/ -------------------------------------------------------------------------------- /test/build/node.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | 3 | const { exec } = require('child_process'); 4 | 5 | describe('Node Definitions', () => { 6 | describe('JS CJS Imports', () => { 7 | const dirPath = path.resolve(__dirname, 'node/js_cjs'); 8 | 9 | beforeEach((done) => { 10 | exec(`cd ${dirPath} && npm install`, (error, stdout, stderr) => { 11 | if (error) { 12 | console.log(stdout); 13 | done(error); 14 | } else { 15 | done(); 16 | } 17 | }); 18 | }); 19 | 20 | it('Require', (done) => { 21 | exec(`cd ${dirPath} && npm run test:require`, (error, stdout, stderr) => { 22 | if (error) { 23 | console.log(stdout); 24 | done(error); 25 | } else { 26 | done(); 27 | } 28 | }); 29 | }); 30 | }); 31 | 32 | describe('JS ESM Imports', () => { 33 | const dirPath = path.resolve(__dirname, 'node/js_esm'); 34 | 35 | beforeEach((done) => { 36 | exec(`cd ${dirPath} && npm install`, (error, stdout, stderr) => { 37 | if (error) { 38 | console.log(stdout); 39 | done(error); 40 | } else { 41 | done(); 42 | } 43 | }); 44 | }); 45 | 46 | it('Import', (done) => { 47 | exec(`cd ${dirPath} && npm run test:import`, (error, stdout, stderr) => { 48 | if (error) { 49 | console.log(stdout); 50 | done(error); 51 | } else { 52 | done(); 53 | } 54 | }); 55 | }); 56 | 57 | // Named imports do not currently work. 58 | // it("Named Import", (done) => { 59 | // exec(`cd ${dirPath} && npm run test:namedImport`, (error, stdout, stderr) => { 60 | // if (error) { 61 | // console.log(stdout); 62 | // done(error); 63 | // } else { 64 | // done(); 65 | // } 66 | // }); 67 | // }); 68 | }); 69 | 70 | describe('TS ES6 Imports', () => { 71 | const dirPath = path.resolve(__dirname, 'node/ts_es6'); 72 | 73 | beforeEach((done) => { 74 | exec(`cd ${dirPath} && npm install && npm run build`, (error, stdout, stderr) => { 75 | if (error) { 76 | console.log(stdout); 77 | done(error); 78 | } else { 79 | done(); 80 | } 81 | }); 82 | }); 83 | 84 | it('Import', (done) => { 85 | exec(`cd ${dirPath} && npm run test:import`, (error, stdout, stderr) => { 86 | if (error) { 87 | console.log(stdout); 88 | done(error); 89 | } else { 90 | done(); 91 | } 92 | }); 93 | }); 94 | 95 | // Named imports do not currently work 96 | // it("Named Import", (done) => { 97 | // exec(`cd ${dirPath} && npm run test:namedImport`, (error, stdout, stderr) => { 98 | // if (error) { 99 | // console.log(stdout); 100 | // done(error); 101 | // } else { 102 | // done(); 103 | // } 104 | // }); 105 | // }); 106 | }); 107 | 108 | describe('TS CJS Imports', () => { 109 | const dirPath = path.resolve(__dirname, 'node/ts_cjs'); 110 | 111 | beforeEach((done) => { 112 | exec(`cd ${dirPath} && npm install && npm run build`, (error, stdout, stderr) => { 113 | if (error) { 114 | console.log(stdout); 115 | done(error); 116 | } else { 117 | done(); 118 | } 119 | }); 120 | }); 121 | 122 | // Current Namespace definitions fail compilation 123 | // it("Require", (done) => { 124 | // exec(`cd ${dirPath} && npm run test:require`, (error, stdout, stderr) => { 125 | // if (error) { 126 | // console.log(stdout); 127 | // done(error); 128 | // } else { 129 | // done(); 130 | // } 131 | // }); 132 | // }); 133 | }); 134 | }); 135 | -------------------------------------------------------------------------------- /examples/javascript/auth/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dropbox JavaScript SDK 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 29 | 30 |
        31 | 36 | 37 | 41 |
        42 | 43 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /test/integration/team.js: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import fs from 'fs/promises'; 3 | import path from 'path'; 4 | import { Dropbox, DropboxAuth } from '../../index.js'; 5 | import { DropboxResponse } from '../../src/response.js'; 6 | 7 | const appInfo = { 8 | SCOPED: { 9 | accessToken: process.env.SCOPED_TEAM_DROPBOX_TOKEN, 10 | clientId: process.env.SCOPED_TEAM_CLIENT_ID, 11 | clientSecret: process.env.SCOPED_TEAM_CLIENT_SECRET, 12 | refreshToken: process.env.SCOPED_TEAM_REFRESH_TOKEN, 13 | }, 14 | }; 15 | 16 | for (const appType in appInfo) { 17 | if (appType) { // for linter 18 | describe(`Team ${appType}`, () => { 19 | let dbxAuth; 20 | let dbx; 21 | beforeEach(() => { 22 | dbxAuth = new DropboxAuth(appInfo[appType]); 23 | dbx = new Dropbox({ auth: dbxAuth }); 24 | }); 25 | 26 | describe('rpc', () => { 27 | it('rpc request is successful', (done) => { 28 | dbx.teamGetInfo() 29 | .then((resp) => { 30 | chai.assert.instanceOf(resp, DropboxResponse); 31 | chai.assert.equal(resp.status, 200, resp.result); 32 | chai.assert.isObject(resp.result); 33 | 34 | done(); 35 | }) 36 | .catch(done); 37 | }); 38 | }); 39 | 40 | describe('app auth', () => { 41 | it('successfully uses app auth', (done) => { 42 | dbx.checkApp({ query: 'Echo string' }) 43 | .then((resp) => { 44 | chai.assert.instanceOf(resp, DropboxResponse); 45 | chai.assert.equal(resp.status, 200, resp.result); 46 | chai.assert.isObject(resp.result); 47 | chai.assert.equal('Echo string', resp.result.result); 48 | 49 | done(); 50 | }) 51 | .catch(done); 52 | }); 53 | }); 54 | 55 | describe('token refresh', () => { 56 | it('refreshes the token when necessary', (done) => { 57 | const currentDate = new Date(); 58 | dbxAuth.setAccessTokenExpiresAt(currentDate.setHours(currentDate.getHours() - 20)); 59 | const expirationBeforeRefresh = dbxAuth.getAccessTokenExpiresAt(); 60 | const dbxWithRefreshToken = new Dropbox({ auth: dbxAuth }); 61 | 62 | dbxWithRefreshToken.teamGetInfo() 63 | .then((resp) => { 64 | chai.assert.instanceOf(resp, DropboxResponse); 65 | chai.assert.equal(resp.status, 200, resp.result); 66 | chai.assert.isObject(resp.result); 67 | // testing to make sure that the token has been refreshed 68 | chai.assert.notEqual( 69 | dbxAuth.getAccessToken(), appInfo[appType].token, 70 | ); 71 | // comparing dates to make sure new token expiration is set 72 | chai.assert.isTrue( 73 | dbxAuth.accessTokenExpiresAt > new Date(expirationBeforeRefresh), 74 | ); 75 | 76 | done(); 77 | }) 78 | .catch(done); 79 | }); 80 | }); 81 | }); 82 | } 83 | } 84 | 85 | describe('incorrect auth', () => { 86 | it('fails if there is an empty auth object', () => { 87 | const dbxAuth = new DropboxAuth(); 88 | const dbx = new Dropbox({ auth: dbxAuth }); 89 | 90 | dbx.teamGetInfo() 91 | .catch((err) => { 92 | chai.assert.instanceOf(err, DropboxResponseError); 93 | chai.assert.isObject(err); 94 | chai.assert.equal(err.error, 'Error in call to API function "users/get_current_account": The given OAuth 2 access token is malformed.'); 95 | }); 96 | }); 97 | 98 | it('fails if token is invalid', () => { 99 | const dbxAuth = new DropboxAuth({ accessToken: 'foo' }); 100 | const dbx = new Dropbox({ auth: dbxAuth }); 101 | 102 | dbx.teamGetInfo() 103 | .catch((err) => { 104 | chai.assert.instanceOf(err, DropboxResponseError); 105 | chai.assert.isObject(err); 106 | chai.assert.equal(err.error, 'Error in call to API function "users/get_current_account": The given OAuth 2 access token is malformed.'); 107 | }); 108 | }); 109 | }); 110 | -------------------------------------------------------------------------------- /generator/generate_routes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from __future__ import absolute_import, division, print_function, unicode_literals 3 | 4 | import argparse 5 | import glob 6 | import json 7 | import os 8 | import subprocess 9 | import sys 10 | 11 | cmdline_desc = """\ 12 | Runs Stone to generate JS routes for the Dropbox client. 13 | """ 14 | 15 | _cmdline_parser = argparse.ArgumentParser(description=cmdline_desc) 16 | _cmdline_parser.add_argument( 17 | '-v', 18 | '--verbose', 19 | action='store_true', 20 | help='Print debugging statements.', 21 | ) 22 | _cmdline_parser.add_argument( 23 | 'spec', 24 | nargs='*', 25 | type=str, 26 | help='Path to API specifications. Each must have a .stone extension.', 27 | ) 28 | _cmdline_parser.add_argument( 29 | '-s', 30 | '--stone', 31 | type=str, 32 | help='Path to clone of stone repository.', 33 | ) 34 | 35 | 36 | def main(): 37 | """The entry point for the program.""" 38 | 39 | args = _cmdline_parser.parse_args() 40 | verbose = args.verbose 41 | 42 | if args.spec: 43 | specs = args.spec 44 | else: 45 | # If no specs were specified, default to the spec submodule. 46 | specs = glob.glob('dropbox-api-spec/*.stone') # Arbitrary sorting 47 | specs.sort() 48 | 49 | specs = [os.path.join(os.getcwd(), s) for s in specs] 50 | 51 | stone_path = os.path.abspath('stone') 52 | if args.stone: 53 | stone_path = args.stone 54 | 55 | dropbox_pkg_path = os.path.abspath( 56 | os.path.join(os.path.dirname(sys.argv[0]), '../lib')) 57 | if verbose: 58 | print('Dropbox package path: %s' % dropbox_pkg_path) 59 | 60 | typescript_template_path = os.path.abspath( 61 | os.path.join(os.path.dirname(sys.argv[0]), 'typescript')) 62 | if verbose: 63 | print('TypeScript template path: %s' % typescript_template_path) 64 | 65 | types_template_path = os.path.abspath( 66 | os.path.join(os.path.dirname(sys.argv[0]), '../types')) 67 | if verbose: 68 | print('Types template path: %s' % types_template_path) 69 | 70 | upload_arg = { 71 | "match": ["style", "upload"], 72 | "arg_name": "contents", 73 | "arg_type": "Object", 74 | "arg_docstring": "The file contents to be uploaded." 75 | } 76 | 77 | if verbose: 78 | print('Generating JS types') 79 | subprocess.check_output( 80 | (['python3', '-m', 'stone.cli', 'js_types', dropbox_pkg_path] + 81 | specs + ['-b', 'team'] + ['-a', 'host', '-a', 'style', '-a', 'auth'] + 82 | ['--', 'types.js', '-e', json.dumps(upload_arg)]), 83 | cwd=stone_path) 84 | 85 | if verbose: 86 | print('Generating JS client routes for user routes') 87 | o = subprocess.check_output( 88 | (['python3', '-m', 'stone.cli', 'js_client', dropbox_pkg_path] + 89 | specs + ['-a', 'host', '-a', 'style', '-a', 'auth', '-a', 'scope'] + 90 | ['--', 'routes.js', '-c', 'Dropbox', '--wrap-response-in', 'DropboxResponse', '--wrap-error-in', 'DropboxResponseError', '-a', 'scope']), 91 | cwd=stone_path) 92 | if verbose: 93 | print(o) 94 | 95 | if verbose: 96 | print('Generating TSD types') 97 | subprocess.check_output( 98 | (['python3', '-m', 'stone.cli', 'tsd_types', typescript_template_path] + 99 | specs + ['-b', 'team'] + ['-a', 'host', '-a', 'style'] + 100 | ['--', 'dropbox_types.d.tstemplate', 'dropbox_types.d.ts', '-e', json.dumps(upload_arg), '--export-namespaces']), 101 | cwd=stone_path) 102 | 103 | if verbose: 104 | print('Generating TSD client routes for user routes') 105 | subprocess.check_output( 106 | (['python3', '-m', 'stone.cli', 'tsd_client', typescript_template_path] + 107 | specs + ['-a', 'host', '-a', 'style', '-a', 'scope'] + 108 | ['--', 'index.d.tstemplate', 'index.d.ts', '--wrap-response-in', 'DropboxResponse', '--wrap-error-in', 'DropboxResponseError', '--import-namespaces', '--types-file', './dropbox_types', '-a', 'scope']), 109 | cwd=stone_path) 110 | 111 | typescript_generated_files = glob.glob('typescript/*.d.ts') 112 | typescript_generated_files.sort() 113 | typescript_generated_files = [os.path.join(os.getcwd(), f) for f in typescript_generated_files] 114 | if verbose: 115 | print('TypeScript generated files: %s' % typescript_generated_files) 116 | 117 | if verbose: 118 | print('Moving TSD routes and types to types/') 119 | for file in typescript_generated_files: 120 | subprocess.check_output( 121 | (['mv', file , types_template_path]), 122 | cwd=typescript_template_path 123 | ) 124 | 125 | if __name__ == '__main__': 126 | main() 127 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Logo][logo]][repo] 2 | 3 | [![node-current](https://img.shields.io/node/v/dropbox)](https://www.npmjs.com/package/dropbox) 4 | [![npm](https://img.shields.io/npm/v/dropbox)](https://www.npmjs.com/package/dropbox) 5 | [![codecov](https://codecov.io/gh/dropbox/dropbox-sdk-js/branch/main/graph/badge.svg)](https://codecov.io/gh/dropbox/dropbox-sdk-js) 6 | 7 | The offical Dropbox SDK for Javascript. 8 | 9 | Documentation can be found on [GitHub Pages][documentation] 10 | 11 | ## Installation 12 | 13 | Create an app via the [Developer Console][devconsole] 14 | 15 | Install via [npm](https://www.npmjs.com/) 16 | 17 | ``` 18 | $ npm install --save dropbox 19 | ``` 20 | 21 | Install from source: 22 | 23 | ``` 24 | $ git clone https://github.com/dropbox/dropbox-sdk-js.git 25 | $ cd dropbox-sdk-js 26 | $ npm install 27 | ``` 28 | 29 | If you are using the repository from the browser, you can use any CDNs that hosts the Dropbox package by including a script tag with the link to the package. However, we highly recommend you do not directly import the latest version and instead choose a specific version. When we update and release a breaking change, this could break production code which we hope to avoid. Note, we follow [semver](https://semver.org/) naming conventions which means that any major version update could contain a breaking change. 30 | 31 | After installation, follow one of our [Examples][examples] or read the [Documentation][documentation]. 32 | 33 | You can also view our [OAuth guide][oauthguide]. 34 | 35 | ## Examples 36 | 37 | We provide [Examples][examples] to help get you started with a lot of the basic functionality in the SDK. We provide most examples in both Javascript and Typescript with some having a Node equivalent. 38 | 39 | - **OAuth** 40 | - Auth - [ [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/auth) ] - A simple auth example to get an access token and list the files in the root of your Dropbox account. 41 | - Simple Backend [ [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/simple-backend) ] - A simple example of a node backend doing a multi-step auth flow for Short Lived Tokens. 42 | - PKCE Backend [ [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/PKCE-backend) ] - A simple example of a node backend doing a multi-step auth flow using PKCE and Short Lived Tokens. 43 | - PKCE Browser [ [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/pkce-browser) ] - A simple example of a frontend doing a multi-step auth flow using PKCE and Short Lived Tokens. 44 | 45 | - **Other Examples** 46 | - Basic - [ [TS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/typescript/basic), [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/basic) ] - A simple example that takes in a token and fetches files from your Dropbox account. 47 | - Download - [ [TS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/typescript/download), [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/download) ] - An example showing how to download a shared file. 48 | - Team As User - [ [TS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/typescript/team-as-user), [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/team-as-user) ] - An example showing how to act as a user. 49 | - Team - [ [TS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/typescript/team), [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/team) ] - An example showing how to use the team functionality and list team devices. 50 | - Upload [ [TS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/typescript/upload), [JS](https://github.com/dropbox/dropbox-sdk-js/tree/main/examples/javascript/upload) ] - An example showing how to upload a file to Dropbox. 51 | 52 | ## Getting Help 53 | 54 | If you find a bug, please see [CONTRIBUTING.md][contributing] for information on how to report it. 55 | 56 | If you need help that is not specific to this SDK, please reach out to [Dropbox Support][support]. 57 | 58 | ## License 59 | 60 | This SDK is distributed under the MIT license, please see [LICENSE][license] for more information. 61 | 62 | [logo]: https://cfl.dropboxstatic.com/static/images/sdk/javascript_banner.png 63 | [repo]: https://github.com/dropbox/dropbox-sdk-js 64 | [documentation]: https://dropbox.github.io/dropbox-sdk-js/ 65 | [examples]: https://github.com/dropbox/dropbox-sdk-js/tree/main/examples 66 | [license]: https://github.com/dropbox/dropbox-sdk-js/blob/main/LICENSE 67 | [contributing]: https://github.com/dropbox/dropbox-sdk-js/blob/main/CONTRIBUTING.md 68 | [devconsole]: https://dropbox.com/developers/apps 69 | [oauthguide]: https://www.dropbox.com/lp/developers/reference/oauth-guide 70 | [support]: https://www.dropbox.com/developers/contact 71 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dropbox", 3 | "version": "10.34.0", 4 | "registry": "npm", 5 | "description": "The Dropbox JavaScript SDK is a lightweight, promise based interface to the Dropbox v2 API that works in both nodejs and browser environments.", 6 | "main": "cjs/index.js", 7 | "browser": "dist/Dropbox-sdk.min.js", 8 | "typings": "types/index", 9 | "types": "types/index", 10 | "module": "es/index.js", 11 | "jsnext:main": "es/index.js", 12 | "scripts": { 13 | "build:es": "cross-env BABEL_ENV=es babel src -d es/src && cross-env BABEL_ENV=es babel lib -d es/lib && cross-env BABEL_ENV=es babel index.js -d es", 14 | "build:cjs": "cross-env BABEL_ENV=commonjs babel src -d cjs/src && cross-env BABEL_ENV=commonjs babel lib -d cjs/lib && cross-env BABEL_ENV=commonjs babel index.js -d cjs", 15 | "build:umd": "cross-env BABEL_ENV=es BUNDLE_TYPE=normal rollup -c -i index.js -o dist/Dropbox-sdk.js -n Dropbox", 16 | "build:umd:min": "cross-env BABEL_ENV=es BUNDLE_TYPE=minified rollup -c -i index.js -o dist/Dropbox-sdk.min.js -n Dropbox", 17 | "build": "npm run build:es && npm run build:cjs && npm run build:umd && npm run build:umd:min", 18 | "lint": "eslint --ext .js,.jsx,.ts .", 19 | "lint-fix": "eslint --fix --ext .js,.jsx,.ts .", 20 | "test": "npm run test:typescript && npm run test:unit", 21 | "test:typescript": "tsc --build test/types", 22 | "test:integration": "mocha --timeout 10000 --require @babel/register test/integration/**/*.js", 23 | "test:unit": "mocha --require @babel/register test/unit/**/*.js", 24 | "test:build": "mocha --timeout 100000 --require @babel/register test/build/*.js", 25 | "report": "nyc report --reporter=lcov --reporter=text", 26 | "clean": "rm -rf dist es cjs", 27 | "generate-docs": "jsdoc -c ./.jsdoc.json", 28 | "coverage:unit": "cross-env BABEL_ENV=coverage nyc --reporter=lcov npm run test:unit", 29 | "coverage:integration": "cross-env BABEL_ENV=coverage nyc --reporter=lcov npm run test:integration" 30 | }, 31 | "files": [ 32 | "*.md", 33 | "LICENSE", 34 | "index.js", 35 | "src", 36 | "lib", 37 | "types", 38 | "dist", 39 | "es", 40 | "cjs" 41 | ], 42 | "keywords": [ 43 | "dropbox", 44 | "files", 45 | "sync", 46 | "sdk", 47 | "client" 48 | ], 49 | "homepage": "https://github.com/dropbox/dropbox-sdk-js#readme", 50 | "repository": { 51 | "type": "git", 52 | "url": "git+https://github.com/dropbox/dropbox-sdk-js.git" 53 | }, 54 | "bugs": { 55 | "url": "https://github.com/dropbox/dropbox-sdk-js/issues" 56 | }, 57 | "license": "MIT", 58 | "directories": { 59 | "example": "examples", 60 | "test": "test" 61 | }, 62 | "engines": { 63 | "node": ">=0.10.3" 64 | }, 65 | "contributors": [ 66 | "Brad Rogers ", 67 | "Andrew Lawson ", 68 | "James Sidhu ", 69 | "John Vilk ", 70 | "Steve Klebanoff ", 71 | "Bohdan Tereta " 72 | ], 73 | "devDependencies": { 74 | "@babel/cli": "^7.11.6", 75 | "@babel/core": "^7.11.6", 76 | "@babel/preset-env": "^7.11.5", 77 | "@babel/register": "^7.11.5", 78 | "@testing-library/dom": "^7.24.5", 79 | "@types/node": "^14.11.2", 80 | "@types/node-fetch": "^2.5.7", 81 | "@typescript-eslint/eslint-plugin": "^4.0.0", 82 | "@typescript-eslint/parser": "^3.10.1", 83 | "babel-plugin-istanbul": "^6.0.0", 84 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2", 85 | "chai": "^4.2.0", 86 | "chai-as-promised": "^7.1.1", 87 | "cross-env": "^7.0.2", 88 | "eslint": "^7.9.0", 89 | "eslint-config-airbnb-base": "^14.2.0", 90 | "eslint-plugin-import": "^2.22.0", 91 | "express": "^4.17.1", 92 | "express-urlrewrite": "^1.3.0", 93 | "gh-pages": "^3.1.0", 94 | "ink-docstrap": "^1.3.2", 95 | "jsdoc": "^3.6.6", 96 | "jsdom": "^16.4.0", 97 | "mocha": "^8.1.3", 98 | "nyc": "^15.1.0", 99 | "prompt": "^1.0.0", 100 | "rollup": "^2.28.2", 101 | "rollup-endpoint": "^0.2.2", 102 | "rollup-plugin-babel": "^4.4.0", 103 | "rollup-plugin-terser": "^7.0.2", 104 | "sinon": "^9.0.3", 105 | "typescript": "^4.0.3" 106 | }, 107 | "peerDependencies": { 108 | "@types/node-fetch": "^2.5.7" 109 | }, 110 | "dependencies": { 111 | "node-fetch": "^2.6.1" 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /examples/javascript/pkce-browser/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Dropbox JavaScript SDK 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 31 | 32 | 33 |
        34 |

        This example shows how to use PKCE in the browser

        35 | 40 | 41 | 45 |
        46 | 47 | 48 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /examples/javascript/upload/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dropbox JavaScript SDK 5 | 6 | 7 | 8 | 9 | 10 | 26 | 27 | 28 |
        29 |

        This example shows how to use the Dropbox.filesUpload() [docs] method to upload a file.

        30 | 31 |
        32 | 33 | 34 | 35 |
        36 | 37 | 38 |

        39 | 40 |

        To obtain an access token for quick testing, you can go to API Explorer click the "Get Token" button on the top right, copy the token it creates and then paste it here.

        41 |
        42 | 43 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /test/build/browser.js: -------------------------------------------------------------------------------- 1 | import { JSDOM } from 'jsdom'; 2 | import { fireEvent } from '@testing-library/dom'; 3 | import chai from 'chai'; 4 | import fs from 'fs'; 5 | import path from 'path'; 6 | 7 | const SDK_IMPORT_HOLDER = 'sdkscript'; 8 | 9 | const setImport = (rawHTML, importPath) => rawHTML.replace(SDK_IMPORT_HOLDER, `file://${importPath}`); 10 | 11 | const executeTest = (testContainer) => { 12 | const children = testContainer.childNodes; 13 | const result = children[1]; 14 | chai.assert.equal(result.localName, 'h1', 'Test setup'); 15 | 16 | const execute = children[3]; 17 | chai.assert.equal(execute.localName, 'button', 'Test setup'); 18 | 19 | fireEvent.click(execute); 20 | return result.innerHTML; 21 | }; 22 | 23 | describe('Browser Definitions', () => { 24 | describe('ES Build', () => { 25 | let html; 26 | let dom; 27 | // let document; 28 | 29 | before((done) => { 30 | const importPath = path.resolve(__dirname, '../../es/index.js'); 31 | html = fs.readFileSync(path.resolve(__dirname, './browser/es.html'), 'utf8'); 32 | html = setImport(html, importPath); 33 | done(); 34 | }); 35 | 36 | beforeEach((done) => { 37 | // Constructing a new JSDOM with this option is the key 38 | // to getting the code in the script tag to execute. 39 | // This is indeed dangerous and should only be done with trusted content. 40 | // https://github.com/jsdom/jsdom#executing-scripts 41 | dom = new JSDOM(html, { 42 | runScripts: 'dangerously', 43 | resources: 'usable', 44 | }); 45 | dom.window.onload = () => { 46 | // document = dom.window.document; 47 | done(); 48 | }; 49 | }); 50 | 51 | // Broken until JSDOM supports