From 53424c311e0e9481ad25a1e25c3d9e27131c836e Mon Sep 17 00:00:00 2001 From: Matt Kane Date: Tue, 27 Jul 2021 12:44:17 +0100 Subject: [PATCH 01/17] feat: add support for secrets 0.7.3-handle-secrets.0 --- .eslintrc.js | 21 +- package-lock.json | 394 +++++++++++++++++++++++++++++++++++++- package.json | 3 +- src/function/handler.d.ts | 4 +- src/lib/builder.d.ts | 3 +- src/lib/secrets.d.ts | 23 +++ src/lib/secrets.js | 34 ++++ src/lib/services.json | 17 ++ src/main.d.ts | 1 + src/main.js | 3 +- 10 files changed, 495 insertions(+), 8 deletions(-) create mode 100644 src/lib/secrets.d.ts create mode 100644 src/lib/secrets.js create mode 100644 src/lib/services.json diff --git a/.eslintrc.js b/.eslintrc.js index 44a088f0..53651f61 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -4,7 +4,15 @@ const { overrides } = require('@netlify/eslint-config-node') module.exports = { extends: '@netlify/eslint-config-node', - rules: {}, + // TODO: remove after https://github.com/netlify/eslint-config-node/pull/230 is merged and released + rules: { + 'node/no-unsupported-features/es-syntax': [ + 'error', + { + ignores: ['modules'], + }, + ], + }, overrides: [ ...overrides, { @@ -14,5 +22,16 @@ module.exports = { 'promise/prefer-await-to-callbacks': 'off', }, }, + // TODO: remove after https://github.com/netlify/eslint-config-node/pull/230 is merged and released + { + files: ['*.ts'], + extends: ['plugin:@typescript-eslint/recommended', 'plugin:import/typescript'], + }, ], + settings: { + // TODO: remove after https://github.com/netlify/eslint-config-node/pull/230 is merged and released + 'import/parsers': { + '@typescript-eslint/parser': ['.ts', '.tsx'], + }, + }, } diff --git a/package-lock.json b/package-lock.json index 5d81b450..f58bdfd2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@netlify/functions", - "version": "0.7.2", + "version": "0.7.3-handle-secrets.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@netlify/functions", - "version": "0.7.2", + "version": "0.7.3-handle-secrets.0", "license": "MIT", "dependencies": { "is-promise": "^4.0.0" @@ -15,6 +15,7 @@ "@commitlint/cli": "^13.0.0", "@commitlint/config-conventional": "^13.0.0", "@netlify/eslint-config-node": "^3.1.9", + "@typescript-eslint/eslint-plugin": "^4.28.5", "ava": "^2.4.0", "husky": "^4.3.8", "nyc": "^15.0.0" @@ -1182,6 +1183,12 @@ "@types/node": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", + "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", + "dev": true + }, "node_modules/@types/mdast": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.7.tgz", @@ -1227,6 +1234,210 @@ "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", "dev": true }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.5.tgz", + "integrity": "sha512-m31cPEnbuCqXtEZQJOXAHsHvtoDi9OVaeL5wZnO2KZTnkvELk+u6J6jHg+NzvWQxk+87Zjbc4lJS4NHmgImz6Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "4.28.5", + "@typescript-eslint/scope-manager": "4.28.5", + "debug": "^4.3.1", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^4.0.0", + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.5.tgz", + "integrity": "sha512-bGPLCOJAa+j49hsynTaAtQIWg6uZd8VLiPcyDe4QPULsvQwLHGLSGKKcBN8/lBxIX14F74UEMK2zNDI8r0okwA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.7", + "@typescript-eslint/scope-manager": "4.28.5", + "@typescript-eslint/types": "4.28.5", + "@typescript-eslint/typescript-estree": "4.28.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.5.tgz", + "integrity": "sha512-NPCOGhTnkXGMqTznqgVbA5LqVsnw+i3+XA1UKLnAb+MG1Y1rP4ZSK9GX0kJBmAZTMIktf+dTwXToT6kFwyimbw==", + "dev": true, + "peer": true, + "dependencies": { + "@typescript-eslint/scope-manager": "4.28.5", + "@typescript-eslint/types": "4.28.5", + "@typescript-eslint/typescript-estree": "4.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.5.tgz", + "integrity": "sha512-PHLq6n9nTMrLYcVcIZ7v0VY1X7dK309NM8ya9oL/yG8syFINIMHxyr2GzGoBYUdv3NUfCOqtuqps0ZmcgnZTfQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.28.5", + "@typescript-eslint/visitor-keys": "4.28.5" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.5.tgz", + "integrity": "sha512-MruOu4ZaDOLOhw4f/6iudyks/obuvvZUAHBDSW80Trnc5+ovmViLT2ZMDXhUV66ozcl6z0LJfKs1Usldgi/WCA==", + "dev": true, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.5.tgz", + "integrity": "sha512-FzJUKsBX8poCCdve7iV7ShirP8V+ys2t1fvamVeD1rWpiAnIm550a+BX/fmTHrjEpQJ7ZAn+Z7ZZwJjytk9rZw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.28.5", + "@typescript-eslint/visitor-keys": "4.28.5", + "debug": "^4.3.1", + "globby": "^11.0.3", + "is-glob": "^4.0.1", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.5.tgz", + "integrity": "sha512-dva/7Rr+EkxNWdJWau26xU/0slnFlkh88v3TsyTgRS/IIYFi5iIfpCFM4ikw0vQTFUR9FYSSyqgK4w64gsgxhg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.28.5", + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -9834,6 +10045,27 @@ "node": ">=4" } }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -9867,6 +10099,20 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typescript": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "dev": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/uid2": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", @@ -11289,6 +11535,12 @@ "@types/node": "*" } }, + "@types/json-schema": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", + "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==", + "dev": true + }, "@types/mdast": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.7.tgz", @@ -11334,6 +11586,122 @@ "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", "dev": true }, + "@typescript-eslint/eslint-plugin": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.5.tgz", + "integrity": "sha512-m31cPEnbuCqXtEZQJOXAHsHvtoDi9OVaeL5wZnO2KZTnkvELk+u6J6jHg+NzvWQxk+87Zjbc4lJS4NHmgImz6Q==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.28.5", + "@typescript-eslint/scope-manager": "4.28.5", + "debug": "^4.3.1", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.5.tgz", + "integrity": "sha512-bGPLCOJAa+j49hsynTaAtQIWg6uZd8VLiPcyDe4QPULsvQwLHGLSGKKcBN8/lBxIX14F74UEMK2zNDI8r0okwA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.7", + "@typescript-eslint/scope-manager": "4.28.5", + "@typescript-eslint/types": "4.28.5", + "@typescript-eslint/typescript-estree": "4.28.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "dependencies": { + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.5.tgz", + "integrity": "sha512-NPCOGhTnkXGMqTznqgVbA5LqVsnw+i3+XA1UKLnAb+MG1Y1rP4ZSK9GX0kJBmAZTMIktf+dTwXToT6kFwyimbw==", + "dev": true, + "peer": true, + "requires": { + "@typescript-eslint/scope-manager": "4.28.5", + "@typescript-eslint/types": "4.28.5", + "@typescript-eslint/typescript-estree": "4.28.5", + "debug": "^4.3.1" + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.5.tgz", + "integrity": "sha512-PHLq6n9nTMrLYcVcIZ7v0VY1X7dK309NM8ya9oL/yG8syFINIMHxyr2GzGoBYUdv3NUfCOqtuqps0ZmcgnZTfQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.28.5", + "@typescript-eslint/visitor-keys": "4.28.5" + } + }, + "@typescript-eslint/types": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.5.tgz", + "integrity": "sha512-MruOu4ZaDOLOhw4f/6iudyks/obuvvZUAHBDSW80Trnc5+ovmViLT2ZMDXhUV66ozcl6z0LJfKs1Usldgi/WCA==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.5.tgz", + "integrity": "sha512-FzJUKsBX8poCCdve7iV7ShirP8V+ys2t1fvamVeD1rWpiAnIm550a+BX/fmTHrjEpQJ7ZAn+Z7ZZwJjytk9rZw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.28.5", + "@typescript-eslint/visitor-keys": "4.28.5", + "debug": "^4.3.1", + "globby": "^11.0.3", + "is-glob": "^4.0.1", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "dependencies": { + "globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.5.tgz", + "integrity": "sha512-dva/7Rr+EkxNWdJWau26xU/0slnFlkh88v3TsyTgRS/IIYFi5iIfpCFM4ikw0vQTFUR9FYSSyqgK4w64gsgxhg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.28.5", + "eslint-visitor-keys": "^2.0.0" + } + }, "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -17838,6 +18206,21 @@ } } }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -17862,6 +18245,13 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "dev": true, + "peer": true + }, "uid2": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", diff --git a/package.json b/package.json index 31ba0caf..1c7a8043 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@netlify/functions", "main": "./src/main.js", "types": "./src/main.d.ts", - "version": "0.7.2", + "version": "0.7.3-handle-secrets.0", "description": "JavaScript utilities for Netlify Functions", "files": [ "src/**/*.js", @@ -58,6 +58,7 @@ "@commitlint/cli": "^13.0.0", "@commitlint/config-conventional": "^13.0.0", "@netlify/eslint-config-node": "^3.1.9", + "@typescript-eslint/eslint-plugin": "^4.28.5", "ava": "^2.4.0", "husky": "^4.3.8", "nyc": "^15.0.0" diff --git a/src/function/handler.d.ts b/src/function/handler.d.ts index 01485ffd..d5c6300d 100644 --- a/src/function/handler.d.ts +++ b/src/function/handler.d.ts @@ -6,6 +6,6 @@ export interface HandlerCallback { (error: any, response: Response): void } -export interface Handler { - (event: Event, context: Context, callback: HandlerCallback): void | Response | Promise +export interface Handler { + (event: Event, context: C, callback: HandlerCallback): void | Response | Promise } diff --git a/src/lib/builder.d.ts b/src/lib/builder.d.ts index 7493156c..f52bf505 100644 --- a/src/lib/builder.d.ts +++ b/src/lib/builder.d.ts @@ -1,7 +1,8 @@ +import { Context } from '../function/context' import { Handler } from '../function/handler' export interface Builder { - (handler: Handler): Handler + (handler: Handler): Handler } export declare const builder: Builder diff --git a/src/lib/secrets.d.ts b/src/lib/secrets.d.ts new file mode 100644 index 00000000..2c202276 --- /dev/null +++ b/src/lib/secrets.d.ts @@ -0,0 +1,23 @@ +import { Context } from '../function/context' +import { Handler } from '../function/handler' +import * as services from './services.json' + +export type Services = typeof services + +export type ServiceKey = keyof Services + +export type ServiceTokens = Services[T]['tokens'] + +export type NetlifySecrets = { + [K in ServiceKey]?: ServiceTokens +} + +export interface ContextWithSecrets extends Context { + secrets: NetlifySecrets +} + +export type HandlerWithSecrets = Handler + +export declare const getSecrets: () => NetlifySecrets + +export declare const withSecrets: (handler: HandlerWithSecrets) => Handler diff --git a/src/lib/secrets.js b/src/lib/secrets.js new file mode 100644 index 00000000..51397a35 --- /dev/null +++ b/src/lib/secrets.js @@ -0,0 +1,34 @@ +const process = require('process') + +// eslint-disable-next-line node/no-unpublished-require +const services = require('./services.json') + +const getSecrets = () => + Object.entries(services).reduce((secrets, [serviceName, service]) => { + const serviceSecrets = [] + // This is so if there are no secrets we don't add an empty object + Object.entries(service.tokens).forEach(([tokenName, token]) => { + if (token in process.env) { + serviceSecrets.push([tokenName, process.env[token]]) + } + }) + if (serviceSecrets.length !== 0) { + // No Object.fromEntries in node < 12 + return { + ...secrets, + [serviceName]: serviceSecrets.reduce((acc, [tokenName, token]) => ({ ...acc, [tokenName]: token }), {}), + } + } + return secrets + }, {}) + +// eslint-disable-next-line promise/prefer-await-to-callbacks +const withSecrets = (handler) => (event, context, callback) => { + const secrets = getSecrets() + return handler(event, { ...context, secrets }, callback) +} + +module.exports = { + getSecrets, + withSecrets, +} diff --git a/src/lib/services.json b/src/lib/services.json new file mode 100644 index 00000000..18e164e1 --- /dev/null +++ b/src/lib/services.json @@ -0,0 +1,17 @@ +{ + "github": { + "tokens": { + "token": "ONEGRAPH_GITHUB_TOKEN" + } + }, + "spotify": { + "tokens": { + "token": "ONEGRAPH_SPOTIFY_TOKEN" + } + }, + "salesforce": { + "tokens": { + "token": "ONEGRAPH_SALESFORCE_TOKEN" + } + } +} diff --git a/src/main.d.ts b/src/main.d.ts index 8d0a8a5a..9a1df06d 100644 --- a/src/main.d.ts +++ b/src/main.d.ts @@ -1,2 +1,3 @@ export * from './lib/builder' export * from './function' +export * from './lib/secrets' diff --git a/src/main.js b/src/main.js index 9c21cbe0..c576e3bf 100644 --- a/src/main.js +++ b/src/main.js @@ -1,3 +1,4 @@ const { builder } = require('./lib/builder') +const { withSecrets, getSecrets } = require('./lib/secrets') -module.exports = { builder } +module.exports = { builder, withSecrets, getSecrets } From 2392bb064ffe8cbc4aa1a6adec501c12c2689cd8 Mon Sep 17 00:00:00 2001 From: Matt Kane Date: Tue, 27 Jul 2021 14:46:55 +0100 Subject: [PATCH 02/17] fix: include json --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 1c7a8043..365cdebf 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "files": [ "src/**/*.js", "src/**/*.ts", + "src/**/*.json", "!src/**/*.test.js" ], "scripts": { From 249318916d97a7625b2a389b09d2bff98419dd39 Mon Sep 17 00:00:00 2001 From: Matt Kane Date: Tue, 27 Jul 2021 14:49:58 +0100 Subject: [PATCH 03/17] 0.7.3-handle-secrets.1 --- package-lock.json | 4 ++-- package.json | 2 +- src/lib/secrets.js | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index f58bdfd2..e25d1af2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@netlify/functions", - "version": "0.7.3-handle-secrets.0", + "version": "0.7.3-handle-secrets.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@netlify/functions", - "version": "0.7.3-handle-secrets.0", + "version": "0.7.3-handle-secrets.1", "license": "MIT", "dependencies": { "is-promise": "^4.0.0" diff --git a/package.json b/package.json index 365cdebf..95557658 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@netlify/functions", "main": "./src/main.js", "types": "./src/main.d.ts", - "version": "0.7.3-handle-secrets.0", + "version": "0.7.3-handle-secrets.1", "description": "JavaScript utilities for Netlify Functions", "files": [ "src/**/*.js", diff --git a/src/lib/secrets.js b/src/lib/secrets.js index 51397a35..71886b11 100644 --- a/src/lib/secrets.js +++ b/src/lib/secrets.js @@ -1,6 +1,5 @@ const process = require('process') -// eslint-disable-next-line node/no-unpublished-require const services = require('./services.json') const getSecrets = () => From f8221571af5af4164adbde91d9941b4a416ed731 Mon Sep 17 00:00:00 2001 From: Sean Grove Date: Tue, 27 Jul 2021 12:09:12 -0700 Subject: [PATCH 04/17] Make secrets lookup just-in-time and dynamic --- src/lib/consts.js | 2 + src/lib/secrets.js | 145 +++++++++++++++++++++++++++++++++++------- src/lib/services.json | 18 +----- 3 files changed, 128 insertions(+), 37 deletions(-) diff --git a/src/lib/consts.js b/src/lib/consts.js index ae2176cb..25b96981 100644 --- a/src/lib/consts.js +++ b/src/lib/consts.js @@ -2,10 +2,12 @@ const BUILDER_FUNCTIONS_FLAG = true const HTTP_STATUS_METHOD_NOT_ALLOWED = 405 const HTTP_STATUS_OK = 200 const METADATA_VERSION = 1 +const ONEGRAPH_AUTHLIFY_APP_ID = '4d3de9a5-722f-4d27-9c96-2ac43c93c004' module.exports = { BUILDER_FUNCTIONS_FLAG, HTTP_STATUS_METHOD_NOT_ALLOWED, HTTP_STATUS_OK, METADATA_VERSION, + ONEGRAPH_AUTHLIFY_APP_ID } diff --git a/src/lib/secrets.js b/src/lib/secrets.js index 71886b11..64987206 100644 --- a/src/lib/secrets.js +++ b/src/lib/secrets.js @@ -1,33 +1,134 @@ -const process = require('process') +const https = require("https"); +const process = require("process"); +const { ONEGRAPH_AUTHLIFY_APP_ID } = require("./consts"); -const services = require('./services.json') +function camelize(text) { + text = text.replace(/[-_\s.]+(.)?/g, (_, c) => (c ? c.toUpperCase() : "")); + return text.substr(0, 1).toLowerCase() + text.substr(1); +} + +// The services will be camelized versions of the OneGraph service enums +// unless overridden by the serviceNormalizeOverrides object +const serviceNormalizeOverrides = { + // Keys are the OneGraph service enums, values are the desired `secret.` names + GITHUB: "gitHub", +}; + +function oneGraphRequest(secretToken, body) { + return new Promise((resolve, reject) => { + const options = { + host: "serve.onegraph.com", + path: "/graphql?app_id=" + ONEGRAPH_AUTHLIFY_APP_ID, + port: 443, + method: "POST", + headers: { + Authorization: "Bearer " + secretToken, + "Content-Type": "application/json", + Accept: "application/json", + "Content-Length": body ? Buffer.byteLength(body) : 0, + }, + }; -const getSecrets = () => - Object.entries(services).reduce((secrets, [serviceName, service]) => { - const serviceSecrets = [] - // This is so if there are no secrets we don't add an empty object - Object.entries(service.tokens).forEach(([tokenName, token]) => { - if (token in process.env) { - serviceSecrets.push([tokenName, process.env[token]]) + const req = https.request(options, (res) => { + if (res.statusCode !== 200) { + return reject(new Error(res.statusCode)); } - }) - if (serviceSecrets.length !== 0) { - // No Object.fromEntries in node < 12 - return { - ...secrets, - [serviceName]: serviceSecrets.reduce((acc, [tokenName, token]) => ({ ...acc, [tokenName]: token }), {}), + + var body = []; + + res.on("data", function (chunk) { + body.push(chunk); + }); + + res.on("end", function () { + const data = Buffer.concat(body).toString(); + try { + body = JSON.parse(data); + } catch (e) { + reject(e); + } + resolve(body); + }); + }); + + req.on("error", (e) => { + reject(e.message); + }); + + req.write(body); + + req.end(); + }); +} + +let secrets = {}; + +// Note: We may want to have configurable "sets" of secrets, +// e.g. "dev" and "prod" +const getSecrets = async () => { + const secretToken = process.env.ONEGRAPH_AUTHLIFY_TOKEN; + + if (!secretToken) { + return {}; + } + + // Cache in memory for the life of the serverless process + if (secrets[secretToken]) { + return secrets[secretToken]; + } + + const doc = `query FindLoggedInServicesQuery { + me { + serviceMetadata { + loggedInServices { + friendlyServiceName + service + isLoggedIn + bearerToken + } } } - return secrets - }, {}) + }`; + + const body = JSON.stringify({ query: doc }); + + const result = await oneGraphRequest( + secretToken, + new TextEncoder().encode(body) + ); + + const services = + result.data && + result.data.me && + result.data.me.serviceMetadata && + result.data.me.serviceMetadata.loggedInServices; + + if (services) { + const newSecrets = services.reduce((acc, service) => { + const normalized = + serviceNormalizeOverrides[service.service] || + camelize(service.friendlyServiceName); + acc[normalized] = service; + return acc; + }, {}); + + secrets[secretToken] = newSecrets; + return newSecrets; + } else { + return {}; + } +}; // eslint-disable-next-line promise/prefer-await-to-callbacks -const withSecrets = (handler) => (event, context, callback) => { - const secrets = getSecrets() - return handler(event, { ...context, secrets }, callback) -} +const withSecrets = (handler) => async (event, context, callback) => { + const secrets = await getSecrets(); + + return handler(event, { ...context, secrets }, callback); +}; module.exports = { + // Fine-grained control during the preview, less necessary with a more proactive OneGraph solution getSecrets, + // The common usage of this module withSecrets, -} +}; diff --git a/src/lib/services.json b/src/lib/services.json index 18e164e1..e859f19b 100644 --- a/src/lib/services.json +++ b/src/lib/services.json @@ -1,17 +1,5 @@ { - "github": { - "tokens": { - "token": "ONEGRAPH_GITHUB_TOKEN" - } - }, - "spotify": { - "tokens": { - "token": "ONEGRAPH_SPOTIFY_TOKEN" - } - }, - "salesforce": { - "tokens": { - "token": "ONEGRAPH_SALESFORCE_TOKEN" - } - } + "gitHub": null, + "spotify": null, + "salesforce": null } From d0dd0bfc91033207acf026169be4c57285cfb5ad Mon Sep 17 00:00:00 2001 From: Sean Grove Date: Tue, 27 Jul 2021 12:43:41 -0700 Subject: [PATCH 05/17] fix: fix ci issues Fix eslint and prettier --- src/lib/consts.js | 2 +- src/lib/secrets.js | 148 +++++++++++++++++++++++---------------------- 2 files changed, 77 insertions(+), 73 deletions(-) diff --git a/src/lib/consts.js b/src/lib/consts.js index 25b96981..f71ab0b4 100644 --- a/src/lib/consts.js +++ b/src/lib/consts.js @@ -9,5 +9,5 @@ module.exports = { HTTP_STATUS_METHOD_NOT_ALLOWED, HTTP_STATUS_OK, METADATA_VERSION, - ONEGRAPH_AUTHLIFY_APP_ID + ONEGRAPH_AUTHLIFY_APP_ID, } diff --git a/src/lib/secrets.js b/src/lib/secrets.js index 64987206..f585f3a3 100644 --- a/src/lib/secrets.js +++ b/src/lib/secrets.js @@ -1,80 +1,102 @@ -const https = require("https"); -const process = require("process"); -const { ONEGRAPH_AUTHLIFY_APP_ID } = require("./consts"); +const Buffer = require('buffer') +const https = require('https') +const process = require('process') -function camelize(text) { - text = text.replace(/[-_\s.]+(.)?/g, (_, c) => (c ? c.toUpperCase() : "")); - return text.substr(0, 1).toLowerCase() + text.substr(1); +const { ONEGRAPH_AUTHLIFY_APP_ID } = require('./consts') + +const camelize = function (text) { + const safe = text.replace(/[-_\s.]+(.)?/g, (_, sub) => (sub ? sub.toUpperCase() : '')) + return safe.slice(0, 1).toLowerCase() + safe.slice(1) } // The services will be camelized versions of the OneGraph service enums // unless overridden by the serviceNormalizeOverrides object const serviceNormalizeOverrides = { // Keys are the OneGraph service enums, values are the desired `secret.` names - GITHUB: "gitHub", -}; + GITHUB: 'gitHub', +} -function oneGraphRequest(secretToken, body) { +const oneGraphRequest = function (secretToken, requestBody) { return new Promise((resolve, reject) => { + const port = 443 + const options = { - host: "serve.onegraph.com", - path: "/graphql?app_id=" + ONEGRAPH_AUTHLIFY_APP_ID, - port: 443, - method: "POST", + host: 'serve.onegraph.com', + path: `/graphql?app_id=${ONEGRAPH_AUTHLIFY_APP_ID}`, + port, + method: 'POST', headers: { - Authorization: "Bearer " + secretToken, - "Content-Type": "application/json", - Accept: "application/json", - "Content-Length": body ? Buffer.byteLength(body) : 0, + Authorization: `Bearer ${secretToken}`, + 'Content-Type': 'application/json', + Accept: 'application/json', + 'Content-Length': requestBody ? Buffer.byteLength(requestBody) : 0, }, - }; + } const req = https.request(options, (res) => { if (res.statusCode !== 200) { - return reject(new Error(res.statusCode)); + return reject(new Error(res.statusCode)) } - var body = []; + let body = [] - res.on("data", function (chunk) { - body.push(chunk); - }); + res.on('data', (chunk) => { + body.push(chunk) + }) - res.on("end", function () { - const data = Buffer.concat(body).toString(); + res.on('end', () => { + const data = Buffer.concat(body).toString() try { - body = JSON.parse(data); - } catch (e) { - reject(e); + body = JSON.parse(data) + } catch (error) { + reject(error) } - resolve(body); - }); - }); + resolve(body) + }) + }) + + req.on('error', (error) => { + reject(error.message) + }) + + req.write(requestBody) + + req.end() + }) +} + +const formatSecrets = (result) => { + const services = + result.data && result.data.me && result.data.me.serviceMetadata && result.data.me.serviceMetadata.loggedInServices - req.on("error", (e) => { - reject(e.message); - }); + if (services) { + const newSecrets = services.reduce((acc, service) => { + const normalized = serviceNormalizeOverrides[service.service] || camelize(service.friendlyServiceName) + // eslint-disable-next-line no-param-reassign + acc[normalized] = service + return acc + }, {}) - req.write(body); + return newSecrets + } - req.end(); - }); + return {} } -let secrets = {}; +const secretsCache = {} // Note: We may want to have configurable "sets" of secrets, // e.g. "dev" and "prod" const getSecrets = async () => { - const secretToken = process.env.ONEGRAPH_AUTHLIFY_TOKEN; + const secretToken = process.env.ONEGRAPH_AUTHLIFY_TOKEN if (!secretToken) { - return {}; + return {} } // Cache in memory for the life of the serverless process - if (secrets[secretToken]) { - return secrets[secretToken]; + if (secretsCache[secretToken]) { + return secretsCache[secretToken] } const doc = `query FindLoggedInServicesQuery { @@ -88,47 +110,29 @@ const getSecrets = async () => { } } } - }`; + }` - const body = JSON.stringify({ query: doc }); + const body = JSON.stringify({ query: doc }) - const result = await oneGraphRequest( - secretToken, - new TextEncoder().encode(body) - ); + // eslint-disable-next-line node/no-unsupported-features/node-builtins + const result = await oneGraphRequest(secretToken, new TextEncoder().encode(body)) - const services = - result.data && - result.data.me && - result.data.me.serviceMetadata && - result.data.me.serviceMetadata.loggedInServices; + const newSecrets = formatSecrets(result) + secretsCache[secretToken] = newSecrets - if (services) { - const newSecrets = services.reduce((acc, service) => { - const normalized = - serviceNormalizeOverrides[service.service] || - camelize(service.friendlyServiceName); - acc[normalized] = service; - return acc; - }, {}); - - secrets[secretToken] = newSecrets; - return newSecrets; - } else { - return {}; - } -}; + return newSecrets +} // eslint-disable-next-line promise/prefer-await-to-callbacks const withSecrets = (handler) => async (event, context, callback) => { - const secrets = await getSecrets(); + const secrets = await getSecrets() - return handler(event, { ...context, secrets }, callback); -}; + return handler(event, { ...context, secrets }, callback) +} module.exports = { // Fine-grained control during the preview, less necessary with a more proactive OneGraph solution getSecrets, // The common usage of this module withSecrets, -}; +} From 393a711d0dd35bd4577c2db1f56c735e01b85187 Mon Sep 17 00:00:00 2001 From: Sean Grove Date: Sun, 1 Aug 2021 19:33:45 -0700 Subject: [PATCH 06/17] feat: update TypeScript definitions and auth metadata Expands on the GraphQL query for the service auths --- package-lock.json | 6 ++++-- package.json | 4 ++-- src/lib/secrets.d.ts | 23 +++++++++++++++++++++-- src/lib/secrets.js | 26 +++++++++++++++++--------- src/lib/services.json | 3 ++- 5 files changed, 46 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index e25d1af2..93be6b3d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@netlify/functions", + "name": "@sgrove/netlify-functions", "version": "0.7.3-handle-secrets.1", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "@netlify/functions", + "name": "@sgrove/netlify-functions", "version": "0.7.3-handle-secrets.1", "license": "MIT", "dependencies": { @@ -2409,6 +2409,7 @@ "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", + "fsevents": "~2.3.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -6636,6 +6637,7 @@ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, "dependencies": { + "graceful-fs": "^4.1.6", "universalify": "^2.0.0" }, "optionalDependencies": { diff --git a/package.json b/package.json index 95557658..2206e842 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "@netlify/functions", + "name": "@sgrove/netlify-functions", "main": "./src/main.js", "types": "./src/main.d.ts", - "version": "0.7.3-handle-secrets.1", + "version": "0.7.3-handle-secrets.3", "description": "JavaScript utilities for Netlify Functions", "files": [ "src/**/*.js", diff --git a/src/lib/secrets.d.ts b/src/lib/secrets.d.ts index 2c202276..2bacf278 100644 --- a/src/lib/secrets.d.ts +++ b/src/lib/secrets.d.ts @@ -2,14 +2,33 @@ import { Context } from '../function/context' import { Handler } from '../function/handler' import * as services from './services.json' +export type Service = { + friendlyServiceName: string + service: string + isLoggedIn: boolean + bearerToken: string | null + grantedScopes: Array<{ + scope: string + scopeInfo: { + category: string | null + scope: string + display: string + isDefault: boolean + isRequired: boolean + description: string | null + title: string | null + } + }> | null +} + export type Services = typeof services export type ServiceKey = keyof Services -export type ServiceTokens = Services[T]['tokens'] +export type ServiceTokens = Service export type NetlifySecrets = { - [K in ServiceKey]?: ServiceTokens + [K in ServiceKey]?: Service } export interface ContextWithSecrets extends Context { diff --git a/src/lib/secrets.js b/src/lib/secrets.js index f585f3a3..8c5f3524 100644 --- a/src/lib/secrets.js +++ b/src/lib/secrets.js @@ -1,4 +1,4 @@ -const Buffer = require('buffer') +const { Buffer } = require('buffer') const https = require('https') const process = require('process') @@ -83,8 +83,6 @@ const formatSecrets = (result) => { return {} } -const secretsCache = {} - // Note: We may want to have configurable "sets" of secrets, // e.g. "dev" and "prod" const getSecrets = async () => { @@ -94,11 +92,10 @@ const getSecrets = async () => { return {} } - // Cache in memory for the life of the serverless process - if (secretsCache[secretToken]) { - return secretsCache[secretToken] - } - + // We select for more than we typeically need here + // in order to allow for some metaprogramming for + // consumers downstream. Also, the data is typically + // static and shouldn't add any measurable overhead. const doc = `query FindLoggedInServicesQuery { me { serviceMetadata { @@ -107,6 +104,18 @@ const getSecrets = async () => { service isLoggedIn bearerToken + grantedScopes { + scope + scopeInfo { + category + scope + display + isDefault + isRequired + description + title + } + } } } } @@ -118,7 +127,6 @@ const getSecrets = async () => { const result = await oneGraphRequest(secretToken, new TextEncoder().encode(body)) const newSecrets = formatSecrets(result) - secretsCache[secretToken] = newSecrets return newSecrets } diff --git a/src/lib/services.json b/src/lib/services.json index e859f19b..2eed9bf5 100644 --- a/src/lib/services.json +++ b/src/lib/services.json @@ -1,5 +1,6 @@ { "gitHub": null, "spotify": null, - "salesforce": null + "salesforce": null, + "stripe": null } From 83fc4882790cd3b1be9994a88c2000954d22accd Mon Sep 17 00:00:00 2001 From: Sean Grove Date: Thu, 11 Nov 2021 09:40:47 -0800 Subject: [PATCH 07/17] feat: updates the env var to look for --- package-lock.json | 4 ++-- package.json | 2 +- src/lib/consts.js | 2 -- src/lib/secrets.js | 4 ++-- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 93be6b3d..49bab249 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@sgrove/netlify-functions", - "version": "0.7.3-handle-secrets.1", + "version": "0.7.3-handle-secrets.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@sgrove/netlify-functions", - "version": "0.7.3-handle-secrets.1", + "version": "0.7.3-handle-secrets.5", "license": "MIT", "dependencies": { "is-promise": "^4.0.0" diff --git a/package.json b/package.json index 2206e842..2584f688 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@sgrove/netlify-functions", "main": "./src/main.js", "types": "./src/main.d.ts", - "version": "0.7.3-handle-secrets.3", + "version": "0.7.3-handle-secrets.8", "description": "JavaScript utilities for Netlify Functions", "files": [ "src/**/*.js", diff --git a/src/lib/consts.js b/src/lib/consts.js index f71ab0b4..ae2176cb 100644 --- a/src/lib/consts.js +++ b/src/lib/consts.js @@ -2,12 +2,10 @@ const BUILDER_FUNCTIONS_FLAG = true const HTTP_STATUS_METHOD_NOT_ALLOWED = 405 const HTTP_STATUS_OK = 200 const METADATA_VERSION = 1 -const ONEGRAPH_AUTHLIFY_APP_ID = '4d3de9a5-722f-4d27-9c96-2ac43c93c004' module.exports = { BUILDER_FUNCTIONS_FLAG, HTTP_STATUS_METHOD_NOT_ALLOWED, HTTP_STATUS_OK, METADATA_VERSION, - ONEGRAPH_AUTHLIFY_APP_ID, } diff --git a/src/lib/secrets.js b/src/lib/secrets.js index 8c5f3524..767abb14 100644 --- a/src/lib/secrets.js +++ b/src/lib/secrets.js @@ -2,7 +2,7 @@ const { Buffer } = require('buffer') const https = require('https') const process = require('process') -const { ONEGRAPH_AUTHLIFY_APP_ID } = require('./consts') +const siteId = process.env.SITE_ID const camelize = function (text) { const safe = text.replace(/[-_\s.]+(.)?/g, (_, sub) => (sub ? sub.toUpperCase() : '')) @@ -22,7 +22,7 @@ const oneGraphRequest = function (secretToken, requestBody) { const options = { host: 'serve.onegraph.com', - path: `/graphql?app_id=${ONEGRAPH_AUTHLIFY_APP_ID}`, + path: `/graphql?app_id=${siteId}`, port, method: 'POST', headers: { From 241a2be07529d073530f27623872b84221b22ae0 Mon Sep 17 00:00:00 2001 From: Sean Grove Date: Tue, 16 Nov 2021 08:19:40 -0800 Subject: [PATCH 08/17] chore: fix lint --- src/function/index.ts | 10 ++++------ src/lib/secrets.d.ts | 8 +++++++- src/lib/services.json | 6 ------ 3 files changed, 11 insertions(+), 13 deletions(-) delete mode 100644 src/lib/services.json diff --git a/src/function/index.ts b/src/function/index.ts index d69ebc9f..aa1cbd39 100644 --- a/src/function/index.ts +++ b/src/function/index.ts @@ -1,6 +1,4 @@ -import type { Context } from './context' -import type { Event } from './event' -import type { Handler, HandlerCallback } from './handler' -import { Response } from './response' - -export type { Context as HandlerContext, Event as HandlerEvent, Handler, HandlerCallback, Response as HandlerResponse } +export { Context as HandlerContext } from './context' +export { Event as HandlerEvent } from './event' +export { Handler, HandlerCallback } from './handler' +export { Response as HandlerResponse } from './response' diff --git a/src/lib/secrets.d.ts b/src/lib/secrets.d.ts index 2bacf278..58c15afe 100644 --- a/src/lib/secrets.d.ts +++ b/src/lib/secrets.d.ts @@ -1,6 +1,12 @@ import { Context } from '../function/context' import { Handler } from '../function/handler' -import * as services from './services.json' + +const services = { + gitHub: null, + spotify: null, + salesforce: null, + stripe: null, +} export type Service = { friendlyServiceName: string diff --git a/src/lib/services.json b/src/lib/services.json deleted file mode 100644 index 2eed9bf5..00000000 --- a/src/lib/services.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "gitHub": null, - "spotify": null, - "salesforce": null, - "stripe": null -} From e86e5ffe66f543bc3afffedaf47b1715777b4c99 Mon Sep 17 00:00:00 2001 From: Sean Grove Date: Tue, 16 Nov 2021 08:31:27 -0800 Subject: [PATCH 09/17] feat: check for authlify token in the event as well, if it's available --- src/lib/secrets.d.ts | 3 ++- src/lib/secrets.js | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lib/secrets.d.ts b/src/lib/secrets.d.ts index 58c15afe..db540da0 100644 --- a/src/lib/secrets.d.ts +++ b/src/lib/secrets.d.ts @@ -1,3 +1,4 @@ +import { HandlerEvent } from '../function' import { Context } from '../function/context' import { Handler } from '../function/handler' @@ -43,6 +44,6 @@ export interface ContextWithSecrets extends Context { export type HandlerWithSecrets = Handler -export declare const getSecrets: () => NetlifySecrets +export declare const getSecrets: (event: ?HandlerEvent) => NetlifySecrets export declare const withSecrets: (handler: HandlerWithSecrets) => Handler diff --git a/src/lib/secrets.js b/src/lib/secrets.js index 767abb14..cbc91644 100644 --- a/src/lib/secrets.js +++ b/src/lib/secrets.js @@ -85,8 +85,11 @@ const formatSecrets = (result) => { // Note: We may want to have configurable "sets" of secrets, // e.g. "dev" and "prod" -const getSecrets = async () => { - const secretToken = process.env.ONEGRAPH_AUTHLIFY_TOKEN +const getSecrets = async (event) => { + // Allow us to get the token from event if present, else fallback to checking the env + // eslint-disable-next-line no-underscore-dangle + const eventToken = event && event._oneGraph && event._oneGraph.authlifyToken + const secretToken = eventToken || process.env.ONEGRAPH_AUTHLIFY_TOKEN if (!secretToken) { return {} @@ -133,7 +136,7 @@ const getSecrets = async () => { // eslint-disable-next-line promise/prefer-await-to-callbacks const withSecrets = (handler) => async (event, context, callback) => { - const secrets = await getSecrets() + const secrets = await getSecrets(event) return handler(event, { ...context, secrets }, callback) } From 644bd02f47cf09d615d3b3e2813d63abbd139481 Mon Sep 17 00:00:00 2001 From: Sean Grove Date: Tue, 16 Nov 2021 08:43:32 -0800 Subject: [PATCH 10/17] chore: fix typescript errors --- src/lib/builder.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib/builder.ts b/src/lib/builder.ts index d3af8e3c..5e83e2bd 100644 --- a/src/lib/builder.ts +++ b/src/lib/builder.ts @@ -1,5 +1,6 @@ import isPromise from 'is-promise' +import { HandlerCallback, HandlerContext, HandlerEvent } from '../function' import { Handler } from '../function/handler' import { Response } from '../function/response' @@ -17,9 +18,9 @@ const augmentResponse = (response: Response) => { } const wrapHandler = - (handler: Handler): Handler => + (handler: Handler): Handler => // eslint-disable-next-line promise/prefer-await-to-callbacks - (event, context, callback) => { + (event: HandlerEvent, context: HandlerContext, callback: HandlerCallback) => { if (event.httpMethod !== 'GET' && event.httpMethod !== 'HEAD') { return Promise.resolve({ body: 'Method Not Allowed', From 476eb97cf06aeb5b4397e7e64c0ad8ed25ebb7c3 Mon Sep 17 00:00:00 2001 From: Sean Grove Date: Tue, 16 Nov 2021 09:56:21 -0800 Subject: [PATCH 11/17] chore: split file apart to avoid too-long rule, convert secrets to ts, etc --- .eslintrc.js | 21 +--- src/function/handler.ts | 2 +- src/lib/secrets.d.ts | 49 ---------- src/lib/secrets.ts | 26 +++++ src/lib/{secrets.js => secrets_helper.ts} | 114 +++++++++++++++------- 5 files changed, 105 insertions(+), 107 deletions(-) delete mode 100644 src/lib/secrets.d.ts create mode 100644 src/lib/secrets.ts rename src/lib/{secrets.js => secrets_helper.ts} (54%) diff --git a/.eslintrc.js b/.eslintrc.js index 53651f61..44a088f0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -4,15 +4,7 @@ const { overrides } = require('@netlify/eslint-config-node') module.exports = { extends: '@netlify/eslint-config-node', - // TODO: remove after https://github.com/netlify/eslint-config-node/pull/230 is merged and released - rules: { - 'node/no-unsupported-features/es-syntax': [ - 'error', - { - ignores: ['modules'], - }, - ], - }, + rules: {}, overrides: [ ...overrides, { @@ -22,16 +14,5 @@ module.exports = { 'promise/prefer-await-to-callbacks': 'off', }, }, - // TODO: remove after https://github.com/netlify/eslint-config-node/pull/230 is merged and released - { - files: ['*.ts'], - extends: ['plugin:@typescript-eslint/recommended', 'plugin:import/typescript'], - }, ], - settings: { - // TODO: remove after https://github.com/netlify/eslint-config-node/pull/230 is merged and released - 'import/parsers': { - '@typescript-eslint/parser': ['.ts', '.tsx'], - }, - }, } diff --git a/src/function/handler.ts b/src/function/handler.ts index 130500f4..15d6cc45 100644 --- a/src/function/handler.ts +++ b/src/function/handler.ts @@ -7,6 +7,6 @@ export interface HandlerCallback { (error: any, response: Response): void } -export interface Handler { +export interface Handler { (event: Event, context: C, callback: HandlerCallback): void | Response | Promise } diff --git a/src/lib/secrets.d.ts b/src/lib/secrets.d.ts deleted file mode 100644 index db540da0..00000000 --- a/src/lib/secrets.d.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { HandlerEvent } from '../function' -import { Context } from '../function/context' -import { Handler } from '../function/handler' - -const services = { - gitHub: null, - spotify: null, - salesforce: null, - stripe: null, -} - -export type Service = { - friendlyServiceName: string - service: string - isLoggedIn: boolean - bearerToken: string | null - grantedScopes: Array<{ - scope: string - scopeInfo: { - category: string | null - scope: string - display: string - isDefault: boolean - isRequired: boolean - description: string | null - title: string | null - } - }> | null -} - -export type Services = typeof services - -export type ServiceKey = keyof Services - -export type ServiceTokens = Service - -export type NetlifySecrets = { - [K in ServiceKey]?: Service -} - -export interface ContextWithSecrets extends Context { - secrets: NetlifySecrets -} - -export type HandlerWithSecrets = Handler - -export declare const getSecrets: (event: ?HandlerEvent) => NetlifySecrets - -export declare const withSecrets: (handler: HandlerWithSecrets) => Handler diff --git a/src/lib/secrets.ts b/src/lib/secrets.ts new file mode 100644 index 00000000..9257029d --- /dev/null +++ b/src/lib/secrets.ts @@ -0,0 +1,26 @@ +import { Handler, HandlerCallback, HandlerContext } from '../function' +import { Context } from '../function/context' + +import { getSecrets, HandlerEventWithOneGraph, NetlifySecrets } from './secrets_helper' + +export interface ContextWithSecrets extends Context { + secrets: NetlifySecrets +} + +export type HandlerWithSecrets = Handler + +const withSecrets: unknown = + (handler: HandlerWithSecrets) => + // eslint-disable-next-line promise/prefer-await-to-callbacks + async (event: HandlerEventWithOneGraph, context: HandlerContext, callback: HandlerCallback) => { + const secrets = await getSecrets(event) + + return handler(event, { ...context, secrets }, callback) + } + +module.exports = { + // Fine-grained control during the preview, less necessary with a more proactive OneGraph solution + getSecrets, + // The common usage of this module + withSecrets, +} diff --git a/src/lib/secrets.js b/src/lib/secrets_helper.ts similarity index 54% rename from src/lib/secrets.js rename to src/lib/secrets_helper.ts index cbc91644..0fa93034 100644 --- a/src/lib/secrets.js +++ b/src/lib/secrets_helper.ts @@ -1,22 +1,75 @@ -const { Buffer } = require('buffer') -const https = require('https') -const process = require('process') +import { Buffer } from 'buffer' +import { request } from 'https' +import { env } from 'process' -const siteId = process.env.SITE_ID +import { HandlerEvent } from '../function' -const camelize = function (text) { +const services = { + gitHub: null, + spotify: null, + salesforce: null, + stripe: null, +} + +export type Service = { + friendlyServiceName: string + service: string + isLoggedIn: boolean + bearerToken: string | null + grantedScopes: Array<{ + scope: string + scopeInfo: { + category: string | null + scope: string + display: string + isDefault: boolean + isRequired: boolean + description: string | null + title: string | null + } + }> | null +} + +export type Services = typeof services + +export type ServiceKey = keyof Services + +export type ServiceTokens = Service + +export type NetlifySecrets = { + [K in ServiceKey]?: Service +} & { [key: string]: Service } + +type OneGraphSecretsResponse = { + data?: { + me?: { + serviceMetadata?: { + loggedInServices: [Service] + } + } + } +} + +const siteId = env.SITE_ID + +const camelize = function (text: string) { const safe = text.replace(/[-_\s.]+(.)?/g, (_, sub) => (sub ? sub.toUpperCase() : '')) return safe.slice(0, 1).toLowerCase() + safe.slice(1) } +type ServiceNormalizeOverrides = { + GITHUB: string + [key: string]: string +} + // The services will be camelized versions of the OneGraph service enums // unless overridden by the serviceNormalizeOverrides object -const serviceNormalizeOverrides = { +const serviceNormalizeOverrides: ServiceNormalizeOverrides = { // Keys are the OneGraph service enums, values are the desired `secret.` names GITHUB: 'gitHub', } -const oneGraphRequest = function (secretToken, requestBody) { +const oneGraphRequest = function (secretToken: string, requestBody: Uint8Array): Promise { return new Promise((resolve, reject) => { const port = 443 @@ -33,12 +86,12 @@ const oneGraphRequest = function (secretToken, requestBody) { }, } - const req = https.request(options, (res) => { + const req = request(options, (res) => { if (res.statusCode !== 200) { - return reject(new Error(res.statusCode)) + return reject(new Error(String(res.statusCode))) } - let body = [] + const body: Array = [] res.on('data', (chunk) => { body.push(chunk) @@ -47,11 +100,11 @@ const oneGraphRequest = function (secretToken, requestBody) { res.on('end', () => { const data = Buffer.concat(body).toString() try { - body = JSON.parse(data) + const result: OneGraphSecretsResponse = JSON.parse(data) + resolve(result) } catch (error) { reject(error) } - resolve(body) }) }) @@ -65,16 +118,13 @@ const oneGraphRequest = function (secretToken, requestBody) { }) } -const formatSecrets = (result) => { - const services = - result.data && result.data.me && result.data.me.serviceMetadata && result.data.me.serviceMetadata.loggedInServices +const formatSecrets = (result: OneGraphSecretsResponse | undefined) => { + const responseServices = result?.data?.me?.serviceMetadata?.loggedInServices - if (services) { - const newSecrets = services.reduce((acc, service) => { + if (responseServices) { + const newSecrets = responseServices.reduce((acc: NetlifySecrets, service) => { const normalized = serviceNormalizeOverrides[service.service] || camelize(service.friendlyServiceName) - // eslint-disable-next-line no-param-reassign - acc[normalized] = service - return acc + return { ...acc, [normalized]: service } }, {}) return newSecrets @@ -83,13 +133,17 @@ const formatSecrets = (result) => { return {} } +type OneGraphPayload = { authlifyToken: string | undefined } + +export type HandlerEventWithOneGraph = HandlerEvent & { _oneGraph: OneGraphPayload } + // Note: We may want to have configurable "sets" of secrets, // e.g. "dev" and "prod" -const getSecrets = async (event) => { +export const getSecrets = async (event: HandlerEventWithOneGraph | undefined): Promise => { // Allow us to get the token from event if present, else fallback to checking the env // eslint-disable-next-line no-underscore-dangle - const eventToken = event && event._oneGraph && event._oneGraph.authlifyToken - const secretToken = eventToken || process.env.ONEGRAPH_AUTHLIFY_TOKEN + const eventToken = event?._oneGraph?.authlifyToken + const secretToken = eventToken || env.ONEGRAPH_AUTHLIFY_TOKEN if (!secretToken) { return {} @@ -133,17 +187,3 @@ const getSecrets = async (event) => { return newSecrets } - -// eslint-disable-next-line promise/prefer-await-to-callbacks -const withSecrets = (handler) => async (event, context, callback) => { - const secrets = await getSecrets(event) - - return handler(event, { ...context, secrets }, callback) -} - -module.exports = { - // Fine-grained control during the preview, less necessary with a more proactive OneGraph solution - getSecrets, - // The common usage of this module - withSecrets, -} From 1f0ea1d96793c521e22be12ef264c3ddb980d128 Mon Sep 17 00:00:00 2001 From: Sean Grove Date: Tue, 16 Nov 2021 17:37:47 -0800 Subject: [PATCH 12/17] chore: refactor and expose types --- package.json | 4 ++-- src/function/index.ts | 2 ++ src/lib/secrets.ts | 26 +++++++++++++------------- src/lib/secrets_helper.ts | 8 +++++--- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index cfba810f..6b744da5 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "@netlify/functions", + "name": "@sgrove/netlify-functions", "main": "./dist/main.js", "types": "./dist/main.d.ts", - "version": "0.8.0", + "version": "0.8.0-5", "description": "JavaScript utilities for Netlify Functions", "files": [ "dist/**/*.js", diff --git a/src/function/index.ts b/src/function/index.ts index aa1cbd39..4e06026e 100644 --- a/src/function/index.ts +++ b/src/function/index.ts @@ -2,3 +2,5 @@ export { Context as HandlerContext } from './context' export { Event as HandlerEvent } from './event' export { Handler, HandlerCallback } from './handler' export { Response as HandlerResponse } from './response' +export { getSecrets, withSecrets } from '../lib/secrets' +export { NetlifySecrets } from '../lib/secrets_helper' diff --git a/src/lib/secrets.ts b/src/lib/secrets.ts index 9257029d..a79947a9 100644 --- a/src/lib/secrets.ts +++ b/src/lib/secrets.ts @@ -1,7 +1,10 @@ -import { Handler, HandlerCallback, HandlerContext } from '../function' -import { Context } from '../function/context' +import { HandlerEvent } from '../function' +import { Context as HandlerContext, Context } from '../function/context' +import { Handler, HandlerCallback } from '../function/handler' import { getSecrets, HandlerEventWithOneGraph, NetlifySecrets } from './secrets_helper' +// Fine-grained control during the preview, less necessary with a more proactive OneGraph solution +export { getSecrets } from './secrets_helper' export interface ContextWithSecrets extends Context { secrets: NetlifySecrets @@ -9,18 +12,15 @@ export interface ContextWithSecrets extends Context { export type HandlerWithSecrets = Handler -const withSecrets: unknown = - (handler: HandlerWithSecrets) => +// The common usage of this module +export const withSecrets = + (handler: Handler) => // eslint-disable-next-line promise/prefer-await-to-callbacks - async (event: HandlerEventWithOneGraph, context: HandlerContext, callback: HandlerCallback) => { - const secrets = await getSecrets(event) + async (event: HandlerEventWithOneGraph | HandlerEvent, context: HandlerContext, callback: HandlerCallback) => { + // eslint-disable-next-line no-underscore-dangle + const secrets = await ((event as HandlerEventWithOneGraph)._oneGraph + ? getSecrets(event as HandlerEventWithOneGraph) + : getSecrets()) return handler(event, { ...context, secrets }, callback) } - -module.exports = { - // Fine-grained control during the preview, less necessary with a more proactive OneGraph solution - getSecrets, - // The common usage of this module - withSecrets, -} diff --git a/src/lib/secrets_helper.ts b/src/lib/secrets_helper.ts index 0fa93034..0b28a128 100644 --- a/src/lib/secrets_helper.ts +++ b/src/lib/secrets_helper.ts @@ -2,7 +2,7 @@ import { Buffer } from 'buffer' import { request } from 'https' import { env } from 'process' -import { HandlerEvent } from '../function' +import { Event as HandlerEvent } from '../function/event' const services = { gitHub: null, @@ -139,10 +139,12 @@ export type HandlerEventWithOneGraph = HandlerEvent & { _oneGraph: OneGraphPaylo // Note: We may want to have configurable "sets" of secrets, // e.g. "dev" and "prod" -export const getSecrets = async (event: HandlerEventWithOneGraph | undefined): Promise => { +export const getSecrets = async ( + event?: HandlerEventWithOneGraph | HandlerEvent | undefined, +): Promise => { // Allow us to get the token from event if present, else fallback to checking the env // eslint-disable-next-line no-underscore-dangle - const eventToken = event?._oneGraph?.authlifyToken + const eventToken = (event as HandlerEventWithOneGraph)?._oneGraph?.authlifyToken const secretToken = eventToken || env.ONEGRAPH_AUTHLIFY_TOKEN if (!secretToken) { From ddb3a81bfc7710d48bb635373367a6e67bb94052 Mon Sep 17 00:00:00 2001 From: Sean Grove Date: Tue, 16 Nov 2021 21:56:56 -0800 Subject: [PATCH 13/17] chore: fix package name and version --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6b744da5..cfba810f 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "@sgrove/netlify-functions", + "name": "@netlify/functions", "main": "./dist/main.js", "types": "./dist/main.d.ts", - "version": "0.8.0-5", + "version": "0.8.0", "description": "JavaScript utilities for Netlify Functions", "files": [ "dist/**/*.js", From 58d164083e852577868135ac21900fd1f0a9d085 Mon Sep 17 00:00:00 2001 From: Sean Grove Date: Tue, 16 Nov 2021 22:03:55 -0800 Subject: [PATCH 14/17] chore: fix circular deps --- src/lib/secrets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/secrets.ts b/src/lib/secrets.ts index a79947a9..ac62cf8f 100644 --- a/src/lib/secrets.ts +++ b/src/lib/secrets.ts @@ -1,4 +1,4 @@ -import { HandlerEvent } from '../function' +import { Event as HandlerEvent } from '../function/event' import { Context as HandlerContext, Context } from '../function/context' import { Handler, HandlerCallback } from '../function/handler' From a49e9e5640bc1bf863f5098a5aa3a66816b5fddf Mon Sep 17 00:00:00 2001 From: Sean Grove Date: Tue, 16 Nov 2021 22:05:03 -0800 Subject: [PATCH 15/17] chore: fix import order --- src/lib/secrets.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/secrets.ts b/src/lib/secrets.ts index ac62cf8f..a50ee06a 100644 --- a/src/lib/secrets.ts +++ b/src/lib/secrets.ts @@ -1,5 +1,5 @@ -import { Event as HandlerEvent } from '../function/event' import { Context as HandlerContext, Context } from '../function/context' +import { Event as HandlerEvent } from '../function/event' import { Handler, HandlerCallback } from '../function/handler' import { getSecrets, HandlerEventWithOneGraph, NetlifySecrets } from './secrets_helper' From c2d762d4e481816e311fde520c8539d5c239dc2d Mon Sep 17 00:00:00 2001 From: Sean Grove Date: Wed, 17 Nov 2021 03:27:45 -0800 Subject: [PATCH 16/17] chore: reject with error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Eduardo Bouças --- src/lib/secrets_helper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/secrets_helper.ts b/src/lib/secrets_helper.ts index 0b28a128..042eaab9 100644 --- a/src/lib/secrets_helper.ts +++ b/src/lib/secrets_helper.ts @@ -109,7 +109,7 @@ const oneGraphRequest = function (secretToken: string, requestBody: Uint8Array): }) req.on('error', (error) => { - reject(error.message) + reject(error) }) req.write(requestBody) From 34973fd4b3006520a259cac85642d18e45b0f9eb Mon Sep 17 00:00:00 2001 From: Sean Grove Date: Wed, 17 Nov 2021 03:35:23 -0800 Subject: [PATCH 17/17] chore: refactor to keep TypeScript happy but simplify a bit --- src/lib/secrets.ts | 5 +---- src/lib/secrets_helper.ts | 16 ++++++++-------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/lib/secrets.ts b/src/lib/secrets.ts index a50ee06a..19227a95 100644 --- a/src/lib/secrets.ts +++ b/src/lib/secrets.ts @@ -17,10 +17,7 @@ export const withSecrets = (handler: Handler) => // eslint-disable-next-line promise/prefer-await-to-callbacks async (event: HandlerEventWithOneGraph | HandlerEvent, context: HandlerContext, callback: HandlerCallback) => { - // eslint-disable-next-line no-underscore-dangle - const secrets = await ((event as HandlerEventWithOneGraph)._oneGraph - ? getSecrets(event as HandlerEventWithOneGraph) - : getSecrets()) + const secrets = await getSecrets(event as HandlerEventWithOneGraph) return handler(event, { ...context, secrets }, callback) } diff --git a/src/lib/secrets_helper.ts b/src/lib/secrets_helper.ts index 0b28a128..484021b4 100644 --- a/src/lib/secrets_helper.ts +++ b/src/lib/secrets_helper.ts @@ -121,16 +121,16 @@ const oneGraphRequest = function (secretToken: string, requestBody: Uint8Array): const formatSecrets = (result: OneGraphSecretsResponse | undefined) => { const responseServices = result?.data?.me?.serviceMetadata?.loggedInServices - if (responseServices) { - const newSecrets = responseServices.reduce((acc: NetlifySecrets, service) => { - const normalized = serviceNormalizeOverrides[service.service] || camelize(service.friendlyServiceName) - return { ...acc, [normalized]: service } - }, {}) - - return newSecrets + if (!responseServices) { + return {} } - return {} + const newSecrets = responseServices.reduce((acc: NetlifySecrets, service) => { + const normalized = serviceNormalizeOverrides[service.service] || camelize(service.friendlyServiceName) + return { ...acc, [normalized]: service } + }, {}) + + return newSecrets } type OneGraphPayload = { authlifyToken: string | undefined }