diff --git a/src/functions-templates/javascript/apollo-graphql-rest/.netlify-function-template.mjs b/src/functions-templates/javascript/apollo-graphql-rest/.netlify-function-template.mjs deleted file mode 100644 index 0bea217584a..00000000000 --- a/src/functions-templates/javascript/apollo-graphql-rest/.netlify-function-template.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - name: 'apollo-graphql-rest', - description: 'GraphQL function to wrap REST API using apollo-server-lambda and apollo-datasource-rest!', - functionType: 'serverless', -} diff --git a/src/functions-templates/javascript/apollo-graphql-rest/package.json b/src/functions-templates/javascript/apollo-graphql-rest/package.json deleted file mode 100644 index fd55b9d95a4..00000000000 --- a/src/functions-templates/javascript/apollo-graphql-rest/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "apollo-graphql-rest", - "version": "1.0.0", - "description": "netlify functions:create - GraphQL function to wrap REST API using apollo-server-lambda and apollo-datasource-rest!", - "main": "apollo-graphql-rest.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "js", - "apollo" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "apollo-server-lambda": "^2.18.2", - "apollo-datasource-rest": "^0.15.0", - "graphql": "^14.1.1" - } -} diff --git a/src/functions-templates/javascript/apollo-graphql-rest/random-user.js b/src/functions-templates/javascript/apollo-graphql-rest/random-user.js deleted file mode 100644 index 2c9588740c2..00000000000 --- a/src/functions-templates/javascript/apollo-graphql-rest/random-user.js +++ /dev/null @@ -1,23 +0,0 @@ -const { RESTDataSource } = require('apollo-datasource-rest') - -class RandomUser extends RESTDataSource { - constructor() { - super() - this.baseURL = 'https://randomuser.me/api' - } - - async getUser(gender = DEFAULT_GENDER) { - const user = await this.get(`/?gender=${gender}`) - return user.results[0] - } - - async getUsers(people = DEFAULT_PEOPLE_COUNT, gender = DEFAULT_GENDER) { - const user = await this.get(`/?results=${people}&gender=${gender}`) - return user.results - } -} - -const DEFAULT_PEOPLE_COUNT = 10 -const DEFAULT_GENDER = 'all' - -module.exports = RandomUser diff --git a/src/functions-templates/javascript/apollo-graphql-rest/{{name}}.js b/src/functions-templates/javascript/apollo-graphql-rest/{{name}}.js deleted file mode 100644 index fcf88089a49..00000000000 --- a/src/functions-templates/javascript/apollo-graphql-rest/{{name}}.js +++ /dev/null @@ -1,68 +0,0 @@ -const { ApolloServer, gql } = require('apollo-server-lambda') - -const RandomUser = require('./random-user.js') -// example from: https://medium.com/yld-engineering-blog/easier-graphql-wrappers-for-your-rest-apis-1410b0b5446d - -const typeDefs = gql` - """ - Example Description for Name Type - - It's multiline and you can use **markdown**! [more docs](https://www.apollographql.com/docs/apollo-server/essentials/schema#documentation)! - """ - type Name { - "Description for first" - title: String - "Description for title" - first: String - "Description for last" - last: String - } - type Location { - street: String - city: String - state: String - postcode: String - } - type Picture { - large: String - medium: String - thumbnail: String - } - type User { - gender: String - name: Name - location: Location - email: String - phone: String - cell: String - picture: Picture - nat: String - } - type Query { - """ - Example Description for getUser - - It's multiline and you can use **markdown**! - """ - getUser(gender: String): User - getUsers(people: Int, gender: String): [User] - } -` -const resolvers = { - Query: { - getUser: async (_, { gender }, { dataSources }) => dataSources.RandomUser.getUser(gender), - getUsers: async (_, { gender, people }, { dataSources }) => dataSources.RandomUser.getUsers(people, gender), - }, -} - -const server = new ApolloServer({ - typeDefs, - resolvers, - dataSources: () => ({ - RandomUser: new RandomUser(), - }), -}) - -const handler = server.createHandler() - -module.exports = { handler } diff --git a/src/functions-templates/javascript/apollo-graphql/.netlify-function-template.mjs b/src/functions-templates/javascript/apollo-graphql/.netlify-function-template.mjs deleted file mode 100644 index cba340baa21..00000000000 --- a/src/functions-templates/javascript/apollo-graphql/.netlify-function-template.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - name: 'apollo-graphql', - description: 'GraphQL function using Apollo-Server-Lambda!', - functionType: 'serverless', -} diff --git a/src/functions-templates/javascript/apollo-graphql/package.json b/src/functions-templates/javascript/apollo-graphql/package.json deleted file mode 100644 index 60557bf2741..00000000000 --- a/src/functions-templates/javascript/apollo-graphql/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "apollo-graphql", - "version": "1.0.0", - "description": "netlify functions:create - set up for apollo graphql", - "main": "apollo-graphql.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "js", - "apollo" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "apollo-server-lambda": "^2.18.2", - "graphql": "^14.1.1" - } -} diff --git a/src/functions-templates/javascript/apollo-graphql/{{name}}.js b/src/functions-templates/javascript/apollo-graphql/{{name}}.js deleted file mode 100644 index 9e4c018aa1d..00000000000 --- a/src/functions-templates/javascript/apollo-graphql/{{name}}.js +++ /dev/null @@ -1,42 +0,0 @@ -const { ApolloServer, gql } = require('apollo-server-lambda') - -const typeDefs = gql` - type Query { - hello: String - allAuthors: [Author!] - author(id: Int!): Author - authorByName(name: String!): Author - } - type Author { - id: ID! - name: String! - married: Boolean! - } -` - -const authors = [ - { id: 1, name: 'Terry Pratchett', married: false }, - { id: 2, name: 'Stephen King', married: true }, - { id: 3, name: 'JK Rowling', married: false }, -] - -const resolvers = { - Query: { - hello: () => 'Hello, world!', - allAuthors: () => authors, - author: () => {}, - authorByName: (root, args) => { - console.log('hihhihi', args.name) - return authors.find((author) => author.name === args.name) || 'NOTFOUND' - }, - }, -} - -const server = new ApolloServer({ - typeDefs, - resolvers, -}) - -const handler = server.createHandler() - -module.exports = { handler } diff --git a/src/functions-templates/javascript/auth-fetch/.netlify-function-template.mjs b/src/functions-templates/javascript/auth-fetch/.netlify-function-template.mjs deleted file mode 100644 index 73dd99a94ff..00000000000 --- a/src/functions-templates/javascript/auth-fetch/.netlify-function-template.mjs +++ /dev/null @@ -1,11 +0,0 @@ -export default { - name: 'auth-fetch', - description: 'Use `node-fetch` library and Netlify Identity to access APIs', - functionType: 'serverless', - onComplete() { - console.log(`auth-fetch function created from template!`) - console.log( - 'REMINDER: Make sure to call this function with the Netlify Identity JWT. See https://netlify-gotrue-in-react.netlify.com/ for demo', - ) - }, -} diff --git a/src/functions-templates/javascript/auth-fetch/package-lock.json b/src/functions-templates/javascript/auth-fetch/package-lock.json deleted file mode 100644 index 82f3dd7ef63..00000000000 --- a/src/functions-templates/javascript/auth-fetch/package-lock.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "name": "auth-fetch", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "auth-fetch", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.3.0" - } - }, - "node_modules/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - } - }, - "dependencies": { - "node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - } - } -} diff --git a/src/functions-templates/javascript/auth-fetch/package.json b/src/functions-templates/javascript/auth-fetch/package.json deleted file mode 100644 index ba2df044c92..00000000000 --- a/src/functions-templates/javascript/auth-fetch/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "auth-fetch", - "version": "1.0.0", - "description": "netlify functions:create - default template for auth fetch function", - "main": "auth-fetch.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "js", - "identity", - "authentication" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.3.0" - } -} diff --git a/src/functions-templates/javascript/auth-fetch/{{name}}.js b/src/functions-templates/javascript/auth-fetch/{{name}}.js deleted file mode 100644 index ad1a85741ff..00000000000 --- a/src/functions-templates/javascript/auth-fetch/{{name}}.js +++ /dev/null @@ -1,39 +0,0 @@ -// for a full working demo of Netlify Identity + Functions, see https://netlify-gotrue-in-react.netlify.com/ - -const fetch = require('node-fetch') - -const handler = async function (event, context) { - if (!context.clientContext && !context.clientContext.identity) { - return { - statusCode: 500, - // Could be a custom message or object i.e. JSON.stringify(err) - body: JSON.stringify({ - msg: 'No identity instance detected. Did you enable it?', - }), - } - } - const { identity, user } = context.clientContext - try { - const response = await fetch('https://api.chucknorris.io/jokes/random') - if (!response.ok) { - // NOT res.status >= 200 && res.status < 300 - return { statusCode: response.status, body: response.statusText } - } - const data = await response.json() - - return { - statusCode: 200, - body: JSON.stringify({ identity, user, msg: data.value }), - } - } catch (error) { - // output to netlify function log - console.log(error) - return { - statusCode: 500, - // Could be a custom message or object i.e. JSON.stringify(err) - body: JSON.stringify({ msg: error.message }), - } - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/create-user/.netlify-function-template.mjs b/src/functions-templates/javascript/create-user/.netlify-function-template.mjs deleted file mode 100644 index b1cf386705a..00000000000 --- a/src/functions-templates/javascript/create-user/.netlify-function-template.mjs +++ /dev/null @@ -1,11 +0,0 @@ -export default { - name: 'create-user', - description: 'Programmatically create a Netlify Identity user by invoking a function', - functionType: 'serverless', - onComplete() { - console.log(`create-user function created from template!`) - console.log( - 'REMINDER: Make sure to call this function with a Netlify Identity JWT. See https://netlify-gotrue-in-react.netlify.com/ for demo', - ) - }, -} diff --git a/src/functions-templates/javascript/create-user/package.json b/src/functions-templates/javascript/create-user/package.json deleted file mode 100644 index 7b445b22ec2..00000000000 --- a/src/functions-templates/javascript/create-user/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "create-user", - "version": "1.0.0", - "description": "netlify functions:create - Programmatically create a Netlify Identity user by invoking a function", - "main": "create-user.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "js", - "identity", - "authentication" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.6.1" - } -} diff --git a/src/functions-templates/javascript/create-user/{{name}}.js b/src/functions-templates/javascript/create-user/{{name}}.js deleted file mode 100644 index 81fae17b69b..00000000000 --- a/src/functions-templates/javascript/create-user/{{name}}.js +++ /dev/null @@ -1,36 +0,0 @@ -const fetch = require('node-fetch') - -const handler = async (event, context) => { - if (event.httpMethod !== 'POST') return { statusCode: 400, body: 'Must POST to this function' } - - // send account information along with the POST - const { email, full_name: fullName, password } = JSON.parse(event.body) - if (!email) return { statusCode: 400, body: 'email missing' } - if (!password) return { statusCode: 400, body: 'password missing' } - if (!fullName) return { statusCode: 400, body: 'full_name missing' } - - // identity.token is a short lived admin token which - // is provided to all Netlify Functions to interact - // with the Identity API - const { identity } = context.clientContext - - await fetch(`${identity.url}/admin/users`, { - method: 'POST', - headers: { Authorization: `Bearer ${identity.token}` }, - body: JSON.stringify({ - email, - password, - confirm: true, - user_metadata: { - full_name: fullName, - }, - }), - }) - - return { - statusCode: 200, - body: 'success!', - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/fauna-crud/.netlify-function-template.mjs b/src/functions-templates/javascript/fauna-crud/.netlify-function-template.mjs deleted file mode 100644 index 137e79c997e..00000000000 --- a/src/functions-templates/javascript/fauna-crud/.netlify-function-template.mjs +++ /dev/null @@ -1,17 +0,0 @@ -import execa from 'execa' - -export default { - name: 'fauna-crud', - description: 'CRUD function using Fauna DB', - functionType: 'serverless', - addons: [ - { - addonName: 'fauna', - addonDidInstall(fnPath) { - execa.sync(fnPath + '/create-schema.js', undefined, { - stdio: 'inherit', - }) - }, - }, - ], -} diff --git a/src/functions-templates/javascript/fauna-crud/create-schema.js b/src/functions-templates/javascript/fauna-crud/create-schema.js deleted file mode 100755 index 4a75aba9e20..00000000000 --- a/src/functions-templates/javascript/fauna-crud/create-schema.js +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env node -const process = require('process') - -/* bootstrap database in your FaunaDB account - use with `netlify dev:exec ` */ -const { Client, query } = require('faunadb') - -const createFaunaDB = async function () { - if (!process.env.FAUNADB_SERVER_SECRET) { - console.log('No FAUNADB_SERVER_SECRET in environment, skipping DB setup') - } - console.log('Create the database!') - const client = new Client({ - secret: process.env.FAUNADB_SERVER_SECRET, - }) - - /* Based on your requirements, change the schema here */ - try { - await client.query(query.CreateCollection({ name: 'items' })) - - console.log('Created items class') - return await client.query( - query.CreateIndex({ - name: 'all_items', - source: query.Collection('items'), - active: true, - }), - ) - } catch (error) { - if (error.requestResult.statusCode === 400 && error.message === 'instance not unique') { - console.log('DB already exists') - } - throw error - } -} - -createFaunaDB() diff --git a/src/functions-templates/javascript/fauna-crud/create.js b/src/functions-templates/javascript/fauna-crud/create.js deleted file mode 100644 index 00098d3741e..00000000000 --- a/src/functions-templates/javascript/fauna-crud/create.js +++ /dev/null @@ -1,37 +0,0 @@ -const process = require('process') - -const { Client, query } = require('faunadb') - -/* configure faunaDB Client with our secret */ -const client = new Client({ - secret: process.env.FAUNADB_SERVER_SECRET, -}) - -/* export our lambda function as named "handler" export */ -const handler = async (event) => { - /* parse the string body into a useable JS object */ - const data = JSON.parse(event.body) - console.log('Function `create` invoked', data) - const item = { - data, - } - /* construct the fauna query */ - try { - const response = await client.query(query.Create(query.Collection('items'), item)) - console.log('success', response) - /* Success! return the response with statusCode 200 */ - return { - statusCode: 200, - body: JSON.stringify(response), - } - } catch (error) { - console.log('error', error) - /* Error! return the error with statusCode 400 */ - return { - statusCode: 400, - body: JSON.stringify(error), - } - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/fauna-crud/delete.js b/src/functions-templates/javascript/fauna-crud/delete.js deleted file mode 100644 index eaa9240b013..00000000000 --- a/src/functions-templates/javascript/fauna-crud/delete.js +++ /dev/null @@ -1,29 +0,0 @@ -/* Import faunaDB sdk */ -const process = require('process') - -const { Client, query } = require('faunadb') - -const client = new Client({ - secret: process.env.FAUNADB_SERVER_SECRET, -}) - -const handler = async (event) => { - const { id } = event - console.log(`Function 'delete' invoked. delete id: ${id}`) - try { - const response = await client.query(query.Delete(query.Ref(query.Collection('items'), id))) - console.log('success', response) - return { - statusCode: 200, - body: JSON.stringify(response), - } - } catch (error) { - console.log('error', error) - return { - statusCode: 400, - body: JSON.stringify(error), - } - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/fauna-crud/package.json b/src/functions-templates/javascript/fauna-crud/package.json deleted file mode 100644 index 4871f402913..00000000000 --- a/src/functions-templates/javascript/fauna-crud/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "fauna-crud", - "version": "1.0.0", - "description": "netlify functions:create - CRUD functionality with Fauna DB", - "main": "fauna-crud.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "js", - "faunadb" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "faunadb": "^4.0.3" - } -} diff --git a/src/functions-templates/javascript/fauna-crud/read-all.js b/src/functions-templates/javascript/fauna-crud/read-all.js deleted file mode 100644 index f7287e64a3b..00000000000 --- a/src/functions-templates/javascript/fauna-crud/read-all.js +++ /dev/null @@ -1,33 +0,0 @@ -/* Import faunaDB sdk */ -const process = require('process') - -const { Client, query } = require('faunadb') - -const client = new Client({ - secret: process.env.FAUNADB_SERVER_SECRET, -}) - -const handler = async () => { - console.log('Function `read-all` invoked') - - try { - const response = await client.query(query.Paginate(query.Match(query.Index('all_items')))) - const itemRefs = response.data - // create new query out of item refs. http://bit.ly/2LG3MLg - const getAllItemsDataQuery = itemRefs.map((ref) => query.Get(ref)) - // then query the refs - const ret = await client.query(getAllItemsDataQuery) - return { - statusCode: 200, - body: JSON.stringify(ret), - } - } catch (error) { - console.log('error', error) - return { - statusCode: 400, - body: JSON.stringify(error), - } - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/fauna-crud/read.js b/src/functions-templates/javascript/fauna-crud/read.js deleted file mode 100644 index b22afec32e6..00000000000 --- a/src/functions-templates/javascript/fauna-crud/read.js +++ /dev/null @@ -1,30 +0,0 @@ -/* Import faunaDB sdk */ -const process = require('process') - -const { Client, query } = require('faunadb') - -const client = new Client({ - secret: process.env.FAUNADB_SERVER_SECRET, -}) - -const handler = async (event) => { - const { id } = event - console.log(`Function 'read' invoked. Read id: ${id}`) - - try { - const response = await client.query(query.Get(query.Ref(query.Collection('items'), id))) - console.log('success', response) - return { - statusCode: 200, - body: JSON.stringify(response), - } - } catch (error) { - console.log('error', error) - return { - statusCode: 400, - body: JSON.stringify(error), - } - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/fauna-crud/update.js b/src/functions-templates/javascript/fauna-crud/update.js deleted file mode 100644 index 7bbf05ef323..00000000000 --- a/src/functions-templates/javascript/fauna-crud/update.js +++ /dev/null @@ -1,30 +0,0 @@ -/* Import faunaDB sdk */ -const process = require('process') - -const { Client, query } = require('faunadb') - -const client = new Client({ - secret: process.env.FAUNADB_SERVER_SECRET, -}) - -const handler = async (event) => { - const data = JSON.parse(event.body) - const { id } = event - console.log(`Function 'update' invoked. update id: ${id}`) - try { - const response = await client.query(query.Update(query.Ref(query.Collection('items'), id), { data })) - console.log('success', response) - return { - statusCode: 200, - body: JSON.stringify(response), - } - } catch (error) { - console.log('error', error) - return { - statusCode: 400, - body: JSON.stringify(error), - } - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/fauna-crud/{{name}}.js b/src/functions-templates/javascript/fauna-crud/{{name}}.js deleted file mode 100644 index c394bbcfb2c..00000000000 --- a/src/functions-templates/javascript/fauna-crud/{{name}}.js +++ /dev/null @@ -1,62 +0,0 @@ -const createRoute = require('./create.js') -const deleteRoute = require('./delete.js') -const readAllRoute = require('./read-all.js') -const readRoute = require('./read.js') -const updateRoute = require('./update.js') - -const handler = async (event, context) => { - const path = event.path.replace(/\.netlify\/functions\/[^/]+/, '') - const segments = path.split('/').filter(Boolean) - - switch (event.httpMethod) { - case 'GET': - // e.g. GET /.netlify/functions/fauna-crud - if (segments.length === 0) { - return readAllRoute.handler(event, context) - } - // e.g. GET /.netlify/functions/fauna-crud/123456 - if (segments.length === 1) { - const [id] = segments - event.id = id - return readRoute.handler(event, context) - } - return { - statusCode: 500, - body: 'too many segments in GET request, must be either /.netlify/functions/fauna-crud or /.netlify/functions/fauna-crud/123456', - } - - case 'POST': - // e.g. POST /.netlify/functions/fauna-crud with a body of key value pair objects, NOT strings - return createRoute.handler(event, context) - case 'PUT': - // e.g. PUT /.netlify/functions/fauna-crud/123456 with a body of key value pair objects, NOT strings - if (segments.length === 1) { - const [id] = segments - event.id = id - return updateRoute.handler(event, context) - } - return { - statusCode: 500, - body: 'invalid segments in POST request, must be /.netlify/functions/fauna-crud/123456', - } - - case 'DELETE': - // e.g. DELETE /.netlify/functions/fauna-crud/123456 - if (segments.length === 1) { - const [id] = segments - event.id = id - return deleteRoute.handler(event, context) - } - return { - statusCode: 500, - body: 'invalid segments in DELETE request, must be /.netlify/functions/fauna-crud/123456', - } - default: - return { - statusCode: 500, - body: 'unrecognized HTTP Method, must be one of GET/POST/PUT/DELETE', - } - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/fauna-graphql/.netlify-function-template.mjs b/src/functions-templates/javascript/fauna-graphql/.netlify-function-template.mjs deleted file mode 100644 index b850f9e6771..00000000000 --- a/src/functions-templates/javascript/fauna-graphql/.netlify-function-template.mjs +++ /dev/null @@ -1,17 +0,0 @@ -import execa from 'execa' - -export default { - name: 'fauna-graphql', - description: 'GraphQL Backend using Fauna DB', - functionType: 'serverless', - addons: [ - { - addonName: 'fauna', - addonDidInstall(fnPath) { - execa.sync(fnPath + '/sync-schema.js', undefined, { - stdio: 'inherit', - }) - }, - }, - ], -} diff --git a/src/functions-templates/javascript/fauna-graphql/package.json b/src/functions-templates/javascript/fauna-graphql/package.json deleted file mode 100644 index 2c88367cf96..00000000000 --- a/src/functions-templates/javascript/fauna-graphql/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "fauna-graphql", - "version": "1.0.0", - "description": "netlify functions:create - set up for fauna db + apollo graphql", - "main": "fauna-graphql.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "js", - "apollo", - "fauna" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "apollo-link-http": "^1.5.17", - "apollo-link-context": "^1.0.20", - "apollo-server-lambda": "^2.18.2", - "graphql": "^14.1.1", - "graphql-tools": "^4.0.8", - "node-fetch": "^2.6.1" - } -} diff --git a/src/functions-templates/javascript/fauna-graphql/schema.graphql b/src/functions-templates/javascript/fauna-graphql/schema.graphql deleted file mode 100644 index c90dad504cc..00000000000 --- a/src/functions-templates/javascript/fauna-graphql/schema.graphql +++ /dev/null @@ -1,8 +0,0 @@ -type Todo { - title: String! - completed: Boolean! -} -type Query { - allTodos: [Todo!] - todosByCompletedFlag(completed: Boolean!): [Todo!] -} diff --git a/src/functions-templates/javascript/fauna-graphql/sync-schema.js b/src/functions-templates/javascript/fauna-graphql/sync-schema.js deleted file mode 100644 index c31c60e1624..00000000000 --- a/src/functions-templates/javascript/fauna-graphql/sync-schema.js +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env node -const { Buffer } = require('buffer') -const fs = require('fs') -const path = require('path') -const process = require('process') - -const fetch = require('node-fetch') - -/* sync GraphQL schema to your FaunaDB account - use with `netlify dev:exec ` */ -const createFaunaGraphQL = async function () { - if (!process.env.FAUNADB_SERVER_SECRET) { - console.log('No FAUNADB_SERVER_SECRET in environment, skipping DB setup') - } - console.log('Upload GraphQL Schema!') - - // name of your schema file - const dataString = fs.readFileSync(path.join(__dirname, 'schema.graphql')).toString() - - // encoded authorization header similar to https://www.npmjs.com/package/request#http-authentication - const token = Buffer.from(`${process.env.FAUNADB_SERVER_SECRET}:`).toString('base64') - - const options = { - method: 'POST', - body: dataString, - headers: { Authorization: `Basic ${token}` }, - } - - try { - const res = await fetch('https://graphql.fauna.com/import', options) - const body = await res.text() - console.log('Netlify Functions:Create - `fauna-graphql/sync-schema.js` success!') - console.log(body) - } catch (error) { - console.error('something wrong happened:', { err: error }) - } -} - -createFaunaGraphQL() diff --git a/src/functions-templates/javascript/fauna-graphql/{{name}}.js b/src/functions-templates/javascript/fauna-graphql/{{name}}.js deleted file mode 100644 index 20acae3d420..00000000000 --- a/src/functions-templates/javascript/fauna-graphql/{{name}}.js +++ /dev/null @@ -1,46 +0,0 @@ -const { Buffer } = require('buffer') -const process = require('process') - -const { createHttpLink } = require('apollo-link-http') -const { ApolloServer } = require('apollo-server-lambda') -const { introspectSchema, makeRemoteExecutableSchema } = require('graphql-tools') -const fetch = require('node-fetch') - -const handler = async function (event, context) { - /** required for Fauna GraphQL auth */ - if (!process.env.FAUNADB_SERVER_SECRET) { - const msg = ` - FAUNADB_SERVER_SECRET missing. - Did you forget to install the fauna addon or forgot to run inside Netlify Dev? - ` - console.error(msg) - return { - statusCode: 500, - body: JSON.stringify({ msg }), - } - } - const b64encodedSecret = Buffer.from(`${process.env.FAUNADB_SERVER_SECRET}:`).toString('base64') - const headers = { Authorization: `Basic ${b64encodedSecret}` } - - /** standard creation of apollo-server executable schema */ - const link = createHttpLink({ - // modify as you see fit - uri: 'https://graphql.fauna.com/graphql', - fetch, - headers, - }) - const schema = await introspectSchema(link) - const executableSchema = makeRemoteExecutableSchema({ - schema, - link, - }) - const server = new ApolloServer({ - schema: executableSchema, - }) - return new Promise((resolve, reject) => { - const cb = (err, args) => (err ? reject(err) : resolve(args)) - server.createHandler()(event, context, cb) - }) -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/google-analytics/.netlify-function-template.mjs b/src/functions-templates/javascript/google-analytics/.netlify-function-template.mjs deleted file mode 100644 index 4aee18f5957..00000000000 --- a/src/functions-templates/javascript/google-analytics/.netlify-function-template.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - name: 'google-analytics', - description: 'Google Analytics: proxy for GA on your domain to avoid adblock', - functionType: 'serverless', -} diff --git a/src/functions-templates/javascript/google-analytics/package-lock.json b/src/functions-templates/javascript/google-analytics/package-lock.json deleted file mode 100644 index 9357ab83b48..00000000000 --- a/src/functions-templates/javascript/google-analytics/package-lock.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "name": "google-analytics", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "google-analytics", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.6.1", - "uuid": "^9.0.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - } - }, - "node_modules/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - } - }, - "dependencies": { - "node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - } - } -} diff --git a/src/functions-templates/javascript/google-analytics/package.json b/src/functions-templates/javascript/google-analytics/package.json deleted file mode 100644 index 830cf8a324b..00000000000 --- a/src/functions-templates/javascript/google-analytics/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "google-analytics", - "version": "1.0.0", - "description": "netlify functions:create - Google Analytics: proxy for GA on your domain to avoid adblock", - "main": "google-analytics.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "engines": { - "node": ">=16.16.0" - }, - "keywords": [ - "netlify", - "serverless", - "apis", - "email", - "js" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.6.1", - "uuid": "^9.0.0" - } -} diff --git a/src/functions-templates/javascript/google-analytics/{{name}}.js b/src/functions-templates/javascript/google-analytics/{{name}}.js deleted file mode 100644 index edee749abc7..00000000000 --- a/src/functions-templates/javascript/google-analytics/{{name}}.js +++ /dev/null @@ -1,114 +0,0 @@ -// with thanks to https://github.com/codeniko/simple-tracker/blob/master/examples/server-examples/aws-lambda/google-analytics.js - -const fetch = require('node-fetch') -const { v4: uuidv4 } = require('uuid') - -const GA_ENDPOINT = `https://www.google-analytics.com/collect` - -const whitelistDomain = function (domain, addWww = true) { - const prefixes = ['https://', 'http://'] - if (addWww) { - prefixes.push('https://www.', 'http://www.') - } - prefixes.forEach((prefix) => { - originWhitelist.push(prefix + domain) - }) -} - -// Domains to whitelist. Replace with your own! -// keep this empty and append domains to whitelist using whiteListDomain() -const originWhitelist = [] -whitelistDomain('test.com') -whitelistDomain('nfeld.com') - -const proxyToGoogleAnalytics = async function (event) { - // get GA params whether GET or POST request - const params = event.httpMethod.toUpperCase() === 'GET' ? event.queryStringParameters : JSON.parse(event.body) - const headers = event.headers || {} - - // attach other GA params, required for IP address since client doesn't have access to it. UA and CID can be sent from client - // ip override. Look into headers for clients IP address, as opposed to IP address of host running lambda function - params.uip = headers['x-forwarded-for'] || headers['x-bb-ip'] || '' - // user agent override - params.ua = params.ua || headers['user-agent'] || '' - // REQUIRED: use given cid, or generate a new one as last resort. Generating should be avoided because one user can show up in GA multiple times. If user refresh page `n` times, you'll get `n` pageviews logged into GA from "different" users. Client should generate a uuid and store in cookies, local storage, or generate a fingerprint. Check simple-tracker client example - params.cid = params.cid || uuidv4() - - console.info('proxying params:', params) - const qs = new URLSearchParams(params).toString() - - try { - const { ok, status, statusText } = await fetch(GA_ENDPOINT, { - method: 'POST', - headers: { 'Content-Type': 'image/gif' }, - body: qs, - }) - if (!ok) { - throw new Error(`HTTP error ${status}`) - } - console.info('googleanalytics status code', status, statusText) - } catch (error) { - console.info('googleanalytics error!', error) - } -} - -const handler = async function (event) { - const origin = event.headers.origin || event.headers.Origin || '' - const httpMethod = event.httpMethod.toUpperCase() - - console.log(`Received ${httpMethod} request from, origin: ${origin}`) - - const isOriginWhitelisted = originWhitelist.includes(origin) - console.info('is whitelisted?', isOriginWhitelisted) - - const headers = { - // 'Access-Control-Allow-Origin': '*', // allow all domains to POST. Use for localhost development only - 'Access-Control-Allow-Origin': isOriginWhitelisted ? origin : originWhitelist[0], - 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS', - 'Access-Control-Allow-Headers': 'Content-Type,Accept', - } - - // CORS (required if you use a different subdomain to host this function, or a different domain entirely) - if (httpMethod === 'OPTIONS') { - return { statusCode: 200, headers, body: '' } - } - - // allow GET or POST, but only for whitelisted domains - if ((httpMethod === 'GET' || httpMethod === 'POST') && isOriginWhitelisted) { - await proxyToGoogleAnalytics(event) - return { statusCode: 200, headers, body: '' } - } - - return { statusCode: 404, headers, body: 'Not found' } -} - -module.exports = { handler } - -// -// Docs on GA endpoint and example params -// -// https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide -// -// v: 1 -// _v: j67 -// a: 751874410 -// t: pageview -// _s: 1 -// dl: https://nfeld.com/contact.html -// dr: https://google.com -// ul: en-us -// de: UTF-8 -// dt: Nikolay Feldman - Software Engineer -// sd: 24-bit -// sr: 1440x900 -// vp: 945x777 -// je: 0 -// _u: blabla~ -// jid: -// gjid: -// cid: 1837873423.1522911810 -// tid: UA-116530991-1 -// _gid: 1828045325.1524815793 -// gtm: u4d -// z: 1379041260 -// diff --git a/src/functions-templates/javascript/graphql-gateway/.netlify-function-template.mjs b/src/functions-templates/javascript/graphql-gateway/.netlify-function-template.mjs deleted file mode 100644 index 051e41a79b7..00000000000 --- a/src/functions-templates/javascript/graphql-gateway/.netlify-function-template.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - name: 'graphql-gateway', - description: 'Apollo Server Lambda Gateway stitching schemas from other GraphQL Functions!', - functionType: 'serverless', -} diff --git a/src/functions-templates/javascript/graphql-gateway/example-sibling-function-graphql-1.js b/src/functions-templates/javascript/graphql-gateway/example-sibling-function-graphql-1.js deleted file mode 100644 index 6225f9ca2fd..00000000000 --- a/src/functions-templates/javascript/graphql-gateway/example-sibling-function-graphql-1.js +++ /dev/null @@ -1,42 +0,0 @@ -// not meant to be run inside the graqhql-gateway function -// but just shows a copy-pastable example sibling function -// that would work with graphql-gateway -const { ApolloServer, gql } = require('apollo-server-lambda') - -const typeDefs = gql` - type Query { - hello: String - allAuthors: [Author!] - author(id: Int!): Author - authorByName(name: String!): Author - } - type Author { - id: ID! - name: String! - age: Int! - } -` - -const authors = [ - { id: 1, name: 'Terry Pratchett', age: 67 }, - { id: 2, name: 'Stephen King', age: 71 }, - { id: 3, name: 'JK Rowling', age: 53 }, -] - -const resolvers = { - Query: { - hello: () => 'Hello, world!', - allAuthors: () => authors, - author: () => {}, - authorByName: (root, args) => authors.find((author) => author.name === args.name) || 'NOTFOUND', - }, -} - -const server = new ApolloServer({ - typeDefs, - resolvers, -}) - -const handler = server.createHandler() - -module.exports = { handler } diff --git a/src/functions-templates/javascript/graphql-gateway/example-sibling-function-graphql-2.js b/src/functions-templates/javascript/graphql-gateway/example-sibling-function-graphql-2.js deleted file mode 100644 index 7fac975eff3..00000000000 --- a/src/functions-templates/javascript/graphql-gateway/example-sibling-function-graphql-2.js +++ /dev/null @@ -1,80 +0,0 @@ -// not meant to be run inside the graqhql-gateway function -// but just shows a copy-pastable example sibling function -// that would work with graphql-gateway -const { ApolloServer, gql } = require('apollo-server-lambda') - -const typeDefs = gql` - type Query { - hello: String - allBooks: [Book] - book(id: Int!): Book - } - type Book { - id: ID! - year: Int! - title: String! - authorName: String! - } -` - -const books = [ - { - id: 1, - title: "The Philosopher's Stone", - year: 1997, - authorName: 'JK Rowling', - }, - { - id: 2, - title: 'Pet Sematary', - year: 1983, - authorName: 'Stephen King', - }, - { - id: 3, - title: 'Going Postal', - year: 2004, - authorName: 'Terry Pratchett', - }, - { - id: 4, - title: 'Small Gods', - year: 1992, - authorName: 'Terry Pratchett', - }, - { - id: 5, - title: 'Night Watch', - year: 2002, - authorName: 'Terry Pratchett', - }, - { - id: 6, - title: 'The Shining', - year: 1977, - authorName: 'Stephen King', - }, - { - id: 7, - title: 'The Deathly Hallows', - year: 2007, - authorName: 'JK Rowling', - }, -] - -const resolvers = { - Query: { - hello: () => 'Hello, world!', - allBooks: () => books, - book: (root, args) => books.find((book) => book.id === args.id), - }, -} - -const server = new ApolloServer({ - typeDefs, - resolvers, -}) - -const handler = server.createHandler() - -module.exports = { handler } diff --git a/src/functions-templates/javascript/graphql-gateway/package.json b/src/functions-templates/javascript/graphql-gateway/package.json deleted file mode 100644 index b103d3eac10..00000000000 --- a/src/functions-templates/javascript/graphql-gateway/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "graphql-gateway", - "version": "1.0.0", - "description": "netlify functions:create - Apollo Server Lambda Gateway stitching schemas from other GraphQL Functions!", - "main": "graphql-gateway.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "js", - "apollo" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "apollo-link-http": "^1.5.17", - "apollo-server-lambda": "^2.18.2", - "graphql": "^14.2.1", - "graphql-tools": "^4.0.8", - "node-fetch": "^2.6.1" - } -} diff --git a/src/functions-templates/javascript/graphql-gateway/{{name}}.js b/src/functions-templates/javascript/graphql-gateway/{{name}}.js deleted file mode 100644 index 61ba8bd65b8..00000000000 --- a/src/functions-templates/javascript/graphql-gateway/{{name}}.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * This code assumes you have other graphql Netlify functions - * and shows you how to stitch them together in a "gateway". - * - * Of course, feel free to modify this gateway to suit your needs. - */ -const process = require('process') - -const { createHttpLink } = require('apollo-link-http') -const { ApolloServer } = require('apollo-server-lambda') -const { introspectSchema, makeRemoteExecutableSchema, mergeSchemas } = require('graphql-tools') -const fetch = require('node-fetch') - -const handler = async function (event, context) { - // other Netlify functions which are graphql lambdas - const schema1 = await getSchema('graphql-1') - const schema2 = await getSchema('graphql-2') - const schemas = [schema1, schema2] - - /** - * resolving -between- schemas - * https://www.apollographql.com/docs/graphql-tools/schema-stitching#adding-resolvers - */ - const linkTypeDefs = ` - extend type Book { - author: Author - } - ` - schemas.push(linkTypeDefs) - const resolvers = { - Book: { - author: { - fragment: `... on Book { authorName }`, - resolve(book, args, resolveContext, info) { - return info.mergeInfo.delegateToSchema({ - schema: schema1, - operation: 'query', - // reuse what's implemented in schema1 - fieldName: 'authorByName', - args: { - name: book.authorName, - }, - context: resolveContext, - info, - }) - }, - }, - }, - } - - // more docs https://www.apollographql.com/docs/graphql-tools/schema-stitching#api - const schema = mergeSchemas({ - schemas, - resolvers, - }) - const server = new ApolloServer({ schema }) - return new Promise((resolve, reject) => { - const cb = (err, args) => (err ? reject(err) : resolve(args)) - server.createHandler()(event, context, cb) - }) -} - -const getSchema = async function (endpoint) { - // you can't use relative URLs within Netlify Functions so need a base URL - // process.env.URL is one of many build env variables: - // https://docs.netlify.com/configure-builds/environment-variables/ - // Netlify Dev only supports URL and DEPLOY URL for now - const uri = `${process.env.URL}/.netlify/functions/${endpoint}` - const link = createHttpLink({ uri, fetch }) - const schema = await introspectSchema(link) - const executableSchema = makeRemoteExecutableSchema({ schema, link }) - return executableSchema -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/hasura-event-triggered/.netlify-function-template.mjs b/src/functions-templates/javascript/hasura-event-triggered/.netlify-function-template.mjs deleted file mode 100644 index 660d48c43fc..00000000000 --- a/src/functions-templates/javascript/hasura-event-triggered/.netlify-function-template.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - name: 'hasura-event-triggered', - description: 'Hasura Cleaning: process a Hasura event and fire off a GraphQL mutation with processed text data', - functionType: 'serverless', -} diff --git a/src/functions-templates/javascript/hasura-event-triggered/package.json b/src/functions-templates/javascript/hasura-event-triggered/package.json deleted file mode 100644 index 6ad447a77fe..00000000000 --- a/src/functions-templates/javascript/hasura-event-triggered/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "hasura-event-triggered", - "version": "1.0.0", - "description": "netlify functions:create - Serverless function to process a Hasura event and fire off a GraphQL mutation with cleaned text data", - "main": "hasura-event-triggered.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "js", - "hasura" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "axios": "^1.0.0", - "bad-words": "^3.0.3" - } -} diff --git a/src/functions-templates/javascript/hasura-event-triggered/{{name}}.js b/src/functions-templates/javascript/hasura-event-triggered/{{name}}.js deleted file mode 100644 index a1d346e01e7..00000000000 --- a/src/functions-templates/javascript/hasura-event-triggered/{{name}}.js +++ /dev/null @@ -1,40 +0,0 @@ -// with thanks to https://github.com/vnovick/netlify-function-example/blob/master/functions/bad-words.js -const axios = require('axios') -const Filter = require('bad-words') - -const filter = new Filter() -const hgeEndpoint = 'https://live-coding-netlify.herokuapp.com' - -const query = ` -mutation verifiedp($id: uuid!, $title: String!, $content: String!) { - update_posts(_set: { verified: true, content: $content, title: $title }, - where:{ id: { _eq: $id } }) { - returning { - id - } - } -} -` - -const handler = async (event) => { - let request - try { - request = JSON.parse(event.body) - } catch { - return { statusCode: 400, body: 'c annot parse hasura event' } - } - - const variables = { - id: request.event.data.new.id, - title: filter.clean(request.event.data.new.title), - content: filter.clean(request.event.data.new.content), - } - try { - await axios.post(`${hgeEndpoint}/v1alpha1/graphql`, { query, variables }) - return { statusCode: 200, body: 'success' } - } catch (error) { - return { statusCode: 500, body: error.toString() } - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/node-fetch/.netlify-function-template.mjs b/src/functions-templates/javascript/node-fetch/.netlify-function-template.mjs deleted file mode 100644 index f0b3dbb0433..00000000000 --- a/src/functions-templates/javascript/node-fetch/.netlify-function-template.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - name: 'node-fetch', - description: 'Fetch function: uses node-fetch to hit an external API without CORS issues', - functionType: 'serverless', -} diff --git a/src/functions-templates/javascript/node-fetch/package.json b/src/functions-templates/javascript/node-fetch/package.json deleted file mode 100644 index daa6de51214..00000000000 --- a/src/functions-templates/javascript/node-fetch/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "node-fetch", - "version": "1.0.0", - "description": "netlify functions:create - default template for node fetch function", - "main": "node-fetch.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "js" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.6.1" - } -} diff --git a/src/functions-templates/javascript/node-fetch/{{name}}.js b/src/functions-templates/javascript/node-fetch/{{name}}.js deleted file mode 100644 index bfc5316fdd8..00000000000 --- a/src/functions-templates/javascript/node-fetch/{{name}}.js +++ /dev/null @@ -1,29 +0,0 @@ -const fetch = require('node-fetch') - -const handler = async function () { - try { - const response = await fetch('https://icanhazdadjoke.com', { - headers: { Accept: 'application/json' }, - }) - if (!response.ok) { - // NOT res.status >= 200 && res.status < 300 - return { statusCode: response.status, body: response.statusText } - } - const data = await response.json() - - return { - statusCode: 200, - body: JSON.stringify({ msg: data.joke }), - } - } catch (error) { - // output to netlify function log - console.log(error) - return { - statusCode: 500, - // Could be a custom message or object i.e. JSON.stringify(err) - body: JSON.stringify({ msg: error.message }), - } - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/oauth-passport/.netlify-function-template.mjs b/src/functions-templates/javascript/oauth-passport/.netlify-function-template.mjs deleted file mode 100644 index 74578382307..00000000000 --- a/src/functions-templates/javascript/oauth-passport/.netlify-function-template.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - name: 'oauth-passport', - description: 'oauth-passport: template for Oauth workflow using Passport + Express.js', - functionType: 'serverless', -} diff --git a/src/functions-templates/javascript/oauth-passport/package.json b/src/functions-templates/javascript/oauth-passport/package.json deleted file mode 100644 index c9af77e4a75..00000000000 --- a/src/functions-templates/javascript/oauth-passport/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "oauth-passport", - "version": "1.0.0", - "description": "netlify functions:create - template for Oauth workflow using Passport + Express.js", - "main": "oauth-passport.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "js" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "cookie-parser": "^1.4.5", - "express": "^4.17.1", - "jsonwebtoken": "^9.0.0", - "passport": "^0.6.0", - "passport-github2": "^0.1.12", - "passport-jwt": "^4.0.0", - "serverless-http": "^2.0.2" - } -} diff --git a/src/functions-templates/javascript/oauth-passport/utils/auth.js b/src/functions-templates/javascript/oauth-passport/utils/auth.js deleted file mode 100644 index 32fa6166f8a..00000000000 --- a/src/functions-templates/javascript/oauth-passport/utils/auth.js +++ /dev/null @@ -1,65 +0,0 @@ -const { sign } = require('jsonwebtoken') -const passport = require('passport') -const { Strategy: GitHubStrategy } = require('passport-github2') -const passportJwt = require('passport-jwt') - -const { BASE_URL, ENDPOINT, GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, SECRET } = require('./config.js') - -const authJwt = function (email) { - return sign({ user: { email } }, SECRET) -} - -const applyPassportStrategies = function () { - passport.use(getGitHubStrategy()) - passport.use(getJwtStrategy()) -} - -const getGitHubStrategy = function () { - return new GitHubStrategy( - { - clientID: GITHUB_CLIENT_ID, - clientSecret: GITHUB_CLIENT_SECRET, - callbackURL: `${BASE_URL}${ENDPOINT}/auth/github/callback`, - scope: ['user:email'], - }, - async (accessToken, refreshToken, profile, done) => { - try { - const email = profile.emails[0].value - // Here you'd typically create a new or load an existing user and - // store the bare necessary informations about the user in the JWT. - const jwt = authJwt(email) - - return done(null, { email, jwt }) - } catch (error) { - return done(error) - } - }, - ) -} - -const getJwtStrategy = function () { - return new passportJwt.Strategy( - { - jwtFromRequest(req) { - if (!req.cookies) throw new Error('Missing cookie-parser middleware') - return req.cookies.jwt - }, - secretOrKey: SECRET, - }, - async ({ user: { email } }, done) => { - try { - // Here you'd typically load an existing user - // and use the data to create the JWT. - const jwt = authJwt(email) - - return done(null, { email, jwt }) - } catch (error) { - return done(error) - } - }, - ) -} - -module.exports = { - applyPassportStrategies, -} diff --git a/src/functions-templates/javascript/oauth-passport/utils/config.js b/src/functions-templates/javascript/oauth-passport/utils/config.js deleted file mode 100644 index 573b1d73fbb..00000000000 --- a/src/functions-templates/javascript/oauth-passport/utils/config.js +++ /dev/null @@ -1,24 +0,0 @@ -// lambda/utils/config.js -// Circumvent problem with Netlify CLI. -// https://github.com/netlify/netlify-dev-plugin/issues/147 -const process = require('process') - -const BASE_URL = process.env.NODE_ENV === 'development' ? 'http://localhost:8888' : process.env.BASE_URL - -const COOKIE_SECURE = process.env.NODE_ENV !== 'development' - -const ENDPOINT = process.env.NODE_ENV === 'development' ? '/.netlify/functions' : '/api' - -const { GITHUB_CLIENT_ID } = process.env -const { GITHUB_CLIENT_SECRET } = process.env - -const SECRET = process.env.SECRET || 'SUPERSECRET' - -module.exports = { - BASE_URL, - COOKIE_SECURE, - ENDPOINT, - GITHUB_CLIENT_ID, - GITHUB_CLIENT_SECRET, - SECRET, -} diff --git a/src/functions-templates/javascript/oauth-passport/{{name}}.js b/src/functions-templates/javascript/oauth-passport/{{name}}.js deleted file mode 100644 index 853492bb133..00000000000 --- a/src/functions-templates/javascript/oauth-passport/{{name}}.js +++ /dev/null @@ -1,37 +0,0 @@ -// details: https://markus.oberlehner.net/blog/implementing-an-authentication-flow-with-passport-and-netlify-functions/ - -const cookieParser = require('cookie-parser') -const express = require('express') -const passport = require('passport') -const serverless = require('serverless-http') - -const { applyPassportStrategies } = require('./utils/auth.js') -const { COOKIE_SECURE, ENDPOINT } = require('./utils/config.js') - -applyPassportStrategies() - -const app = express() - -app.use(express.urlencoded({ extended: true })) -app.use(express.json()) -app.use(cookieParser()) -app.use(passport.initialize()) - -const handleCallback = (req, res) => { - res.cookie('jwt', req.user.jwt, { httpOnly: true, COOKIE_SECURE }).redirect('/') -} - -app.get(`${ENDPOINT}/auth/github`, passport.authenticate('github', { session: false })) -app.get( - `${ENDPOINT}/auth/github/callback`, - passport.authenticate('github', { failureRedirect: '/', session: false }), - handleCallback, -) - -app.get(`${ENDPOINT}/auth/status`, passport.authenticate('jwt', { session: false }), (req, res) => - res.json({ email: req.user.email }), -) - -const handler = serverless(app) - -module.exports = { handler } diff --git a/src/functions-templates/javascript/protected-function/.netlify-function-template.mjs b/src/functions-templates/javascript/protected-function/.netlify-function-template.mjs deleted file mode 100644 index 46592dd217d..00000000000 --- a/src/functions-templates/javascript/protected-function/.netlify-function-template.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - name: 'protected-function', - description: 'Function protected Netlify Identity authentication', - functionType: 'serverless', -} diff --git a/src/functions-templates/javascript/protected-function/{{name}}.js b/src/functions-templates/javascript/protected-function/{{name}}.js deleted file mode 100644 index 2c36ffeba31..00000000000 --- a/src/functions-templates/javascript/protected-function/{{name}}.js +++ /dev/null @@ -1,25 +0,0 @@ -const handler = async (event, context) => { - console.log('protected function!') - // Reading the context.clientContext will give us the current user - const claims = context.clientContext && context.clientContext.user - console.log('user claims', claims) - - if (!claims) { - console.log('No claims! Begone!') - return { - statusCode: 401, - body: JSON.stringify({ - data: 'NOT ALLOWED', - }), - } - } - - return { - statusCode: 200, - body: JSON.stringify({ - data: 'auth true', - }), - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/send-email/.netlify-function-template.mjs b/src/functions-templates/javascript/send-email/.netlify-function-template.mjs deleted file mode 100644 index 474e94b9934..00000000000 --- a/src/functions-templates/javascript/send-email/.netlify-function-template.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - name: 'send-email', - description: "Send Email: Send email with no SMTP server via 'sendmail' pkg", - functionType: 'serverless', -} diff --git a/src/functions-templates/javascript/send-email/package.json b/src/functions-templates/javascript/send-email/package.json deleted file mode 100644 index 303acdd2462..00000000000 --- a/src/functions-templates/javascript/send-email/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "send-email", - "version": "1.0.0", - "description": "netlify functions:create - Send email with no SMTP server via 'sendmail' pkg", - "main": "send-email.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "apis", - "email", - "js" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "sendmail": "1.6.1" - } -} diff --git a/src/functions-templates/javascript/send-email/validations.js b/src/functions-templates/javascript/send-email/validations.js deleted file mode 100644 index e515be87184..00000000000 --- a/src/functions-templates/javascript/send-email/validations.js +++ /dev/null @@ -1,38 +0,0 @@ -const validateEmail = (ctx, str) => { - if (typeof str !== 'string' && !(str instanceof String)) { - throw new TypeError(`${ctx} must be a string`) - } - - validateLength(ctx, str, EMAIL_MIN_LENGTH, EMAIL_MAX_LENGTH) - - if (!/^[\w.-]+@[\w.-]+\.\w+$/.test(str)) { - throw new TypeError(`${ctx} is not an email address`) - } -} - -const EMAIL_MIN_LENGTH = 5 -const EMAIL_MAX_LENGTH = 30 - -const validateLength = (ctx, str, min, max) => { - if (max === undefined) { - max = min - min = 0 - } - - if (typeof str !== 'string' && !(str instanceof String)) { - throw new TypeError(`${ctx} must be a string`) - } - - if (str.length < min) { - throw new TypeError(`${ctx} must be at least ${min} chars long`) - } - - if (str.length > max) { - throw new TypeError(`${ctx} must contain ${max} chars at most`) - } -} - -module.exports = { - validateEmail, - validateLength, -} diff --git a/src/functions-templates/javascript/send-email/{{name}}.js b/src/functions-templates/javascript/send-email/{{name}}.js deleted file mode 100644 index 85796309483..00000000000 --- a/src/functions-templates/javascript/send-email/{{name}}.js +++ /dev/null @@ -1,68 +0,0 @@ -// with thanks to https://github.com/Urigo/graphql-modules/blob/8cb2fd7d9938a856f83e4eee2081384533771904/website/lambda/contact.js -const process = require('process') -const { promisify } = require('util') - -const sendMailLib = require('sendmail') - -const { validateEmail, validateLength } = require('./validations.js') - -const sendMail = promisify(sendMailLib()) - -const NAME_MIN_LENGTH = 3 -const NAME_MAX_LENGTH = 50 -const DETAILS_MIN_LENGTH = 10 -const DETAILS_MAX_LENGTH = 1e3 - -const handler = async (event) => { - if (!process.env.CONTACT_EMAIL) { - return { - statusCode: 500, - body: 'process.env.CONTACT_EMAIL must be defined', - } - } - - const body = JSON.parse(event.body) - - try { - validateLength('body.name', body.name, NAME_MIN_LENGTH, NAME_MAX_LENGTH) - } catch (error) { - return { - statusCode: 403, - body: error.message, - } - } - - try { - validateEmail('body.email', body.email) - } catch (error) { - return { - statusCode: 403, - body: error.message, - } - } - - try { - validateLength('body.details', body.details, DETAILS_MIN_LENGTH, DETAILS_MAX_LENGTH) - } catch (error) { - return { - statusCode: 403, - body: error.message, - } - } - - const descriptor = { - from: `"${body.email}" `, - to: process.env.CONTACT_EMAIL, - subject: `${body.name} sent you a message from gql-modules.com`, - text: body.details, - } - - try { - await sendMail(descriptor) - return { statusCode: 200, body: '' } - } catch (error) { - return { statusCode: 500, body: error.message } - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/serverless-ssr/.netlify-function-template.mjs b/src/functions-templates/javascript/serverless-ssr/.netlify-function-template.mjs deleted file mode 100644 index 2e5dc345c00..00000000000 --- a/src/functions-templates/javascript/serverless-ssr/.netlify-function-template.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - name: 'serverless-ssr', - description: 'Dynamic serverside rendering via functions', - functionType: 'serverless', -} diff --git a/src/functions-templates/javascript/serverless-ssr/app/index.js b/src/functions-templates/javascript/serverless-ssr/app/index.js deleted file mode 100644 index 37ff0d68afe..00000000000 --- a/src/functions-templates/javascript/serverless-ssr/app/index.js +++ /dev/null @@ -1,116 +0,0 @@ -/* Express App */ -const process = require('process') - -const compression = require('compression') -const cors = require('cors') -const express = require('express') -const morgan = require('morgan') - -/* My express App */ -module.exports = function expressApp(functionName) { - const app = express() - const router = express.Router() - - // gzip responses - router.use(compression()) - - // Set router base path for local dev - const routerBasePath = process.env.NODE_ENV === 'dev' ? `/${functionName}` : `/.netlify/functions/${functionName}/` - - /* define routes */ - router.get('/', function onRequest(req, res) { - const html = ` - - - - - -

Express via '${functionName}' ⊂◉‿◉つ

- -

I'm using Express running via a Netlify Function.

- -

Choose a route:

- -
- View /users route -
- -
- View /hello route -
- -
-
- -
- - Go back to demo homepage - -
- -
-
- -
- - See the source code on GitHub - -
- - - ` - res.send(html) - }) - - router.get('/users', function onRequest(req, res) { - res.json({ - users: [ - { - name: 'steve', - }, - { - name: 'joe', - }, - ], - }) - }) - - router.get('/hello/', function onRequest(req, res) { - res.send('hello world') - }) - - // Attach logger - app.use(morgan(customLogger)) - - // Setup routes - app.use(routerBasePath, router) - - // Apply express middlewares - router.use(cors()) - router.use(express.json()) - router.use(express.urlencoded({ extended: true })) - - return app -} - -const customLogger = function (tokens, req, res) { - const log = [ - tokens.method(req, res), - tokens.url(req, res), - tokens.status(req, res), - tokens.res(req, res, 'content-length'), - '-', - tokens['response-time'](req, res), - 'ms', - ].join(' ') - - if (process.env.NODE_ENV !== 'dev') { - // Log only in AWS context to get back function logs - console.log(log) - } - return log -} diff --git a/src/functions-templates/javascript/serverless-ssr/package.json b/src/functions-templates/javascript/serverless-ssr/package.json deleted file mode 100644 index 91734b408fa..00000000000 --- a/src/functions-templates/javascript/serverless-ssr/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "serverless-ssr", - "version": "1.0.0", - "description": "netlify functions:create - default template for a serverless SSR function", - "main": "serverless-ssr.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "js" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "compression": "^1.7.4", - "cors": "^2.8.5", - "express": "^4.17.1", - "morgan": "^1.10.0", - "node-fetch": "^2.6.1", - "serverless-http": "^2.0.0" - } -} diff --git a/src/functions-templates/javascript/serverless-ssr/serverless-http.js b/src/functions-templates/javascript/serverless-ssr/serverless-http.js deleted file mode 100644 index 573b0585f71..00000000000 --- a/src/functions-templates/javascript/serverless-ssr/serverless-http.js +++ /dev/null @@ -1,15 +0,0 @@ -// for a full working demo check https://express-via-functions.netlify.com/.netlify/functions/serverless-http -const serverless = require('serverless-http') - -const expressApp = require('./app.js') - -// We need to define our function name for express routes to set the correct base path -const functionName = 'serverless-http' - -// Initialize express app -const app = expressApp(functionName) - -// Export lambda handler -const handler = serverless(app) - -module.exports = { handler } diff --git a/src/functions-templates/javascript/serverless-ssr/{{name}}.js b/src/functions-templates/javascript/serverless-ssr/{{name}}.js deleted file mode 100644 index 573b0585f71..00000000000 --- a/src/functions-templates/javascript/serverless-ssr/{{name}}.js +++ /dev/null @@ -1,15 +0,0 @@ -// for a full working demo check https://express-via-functions.netlify.com/.netlify/functions/serverless-http -const serverless = require('serverless-http') - -const expressApp = require('./app.js') - -// We need to define our function name for express routes to set the correct base path -const functionName = 'serverless-http' - -// Initialize express app -const app = expressApp(functionName) - -// Export lambda handler -const handler = serverless(app) - -module.exports = { handler } diff --git a/src/functions-templates/javascript/set-cookie/.netlify-function-template.mjs b/src/functions-templates/javascript/set-cookie/.netlify-function-template.mjs deleted file mode 100644 index 3326dc0fadf..00000000000 --- a/src/functions-templates/javascript/set-cookie/.netlify-function-template.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - name: 'set-cookie', - description: 'Set a cookie alongside your function', - functionType: 'serverless', -} diff --git a/src/functions-templates/javascript/set-cookie/package.json b/src/functions-templates/javascript/set-cookie/package.json deleted file mode 100644 index 8a4f4e1c2a3..00000000000 --- a/src/functions-templates/javascript/set-cookie/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "set-cookie", - "version": "1.0.0", - "description": "netlify functions:create - set a cookie with your Netlify Function", - "main": "set-cookie", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "js" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "cookie": "^0.5.0" - } -} diff --git a/src/functions-templates/javascript/set-cookie/{{name}}.js b/src/functions-templates/javascript/set-cookie/{{name}}.js deleted file mode 100644 index c283828e1cd..00000000000 --- a/src/functions-templates/javascript/set-cookie/{{name}}.js +++ /dev/null @@ -1,44 +0,0 @@ -const cookie = require('cookie') - -// 14 days -const COOKIE_MAX_AGE = 12_096e5 - -const handler = async () => { - const myCookie = cookie.serialize('my_cookie', 'lolHi', { - secure: true, - httpOnly: true, - path: '/', - maxAge: COOKIE_MAX_AGE, - }) - - const redirectUrl = 'https://google.com' - // Do redirects via html - const html = ` - - - - - - - - - ` - - return { - statusCode: 200, - headers: { - 'Set-Cookie': myCookie, - 'Cache-Control': 'no-cache', - 'Content-Type': 'text/html', - }, - body: html, - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/slack-rate-limit/.netlify-function-template.mjs b/src/functions-templates/javascript/slack-rate-limit/.netlify-function-template.mjs deleted file mode 100644 index 4a15cc58866..00000000000 --- a/src/functions-templates/javascript/slack-rate-limit/.netlify-function-template.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - name: 'slack-rate-limit', - description: 'Slack Rate-limit: post to Slack, at most once an hour, using Netlify Identity metadata', - functionType: 'serverless', -} diff --git a/src/functions-templates/javascript/slack-rate-limit/package.json b/src/functions-templates/javascript/slack-rate-limit/package.json deleted file mode 100644 index 7010a19417b..00000000000 --- a/src/functions-templates/javascript/slack-rate-limit/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "slack-rate-limit", - "version": "1.0.0", - "description": "netlify functions:create - post to Slack, at most once an hour, using Netlify Identity metadata", - "main": "node-fetch.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "slack", - "js" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.6.1" - } -} diff --git a/src/functions-templates/javascript/slack-rate-limit/{{name}}.js b/src/functions-templates/javascript/slack-rate-limit/{{name}}.js deleted file mode 100644 index c46157311a5..00000000000 --- a/src/functions-templates/javascript/slack-rate-limit/{{name}}.js +++ /dev/null @@ -1,115 +0,0 @@ -// code walkthrough: https://www.netlify.com/blog/2018/03/29/jamstack-architecture-on-netlify-how-identity-and-functions-work-together/#updating-user-data-with-the-identity-api -// demo repo: https://github.com/biilmann/testing-slack-tutorial/tree/v3-one-message-an-hour -// note: requires SLACK_WEBHOOK_URL environment variable -const process = require('process') - -const slackURL = process.env.SLACK_WEBHOOK_URL -const fetch = require('node-fetch') - -const parseJsonResponse = async (response) => { - const json = await response.json() - if (!response.ok) { - const error = `JSON: ${JSON.stringify(json)}. Status: ${response.status}` - throw new Error(error) - } - return json -} - -class IdentityAPI { - constructor(apiURL, token) { - this.apiURL = apiURL - this.token = token - } - - headers(headers = {}) { - return { - 'Content-Type': 'application/json', - Authorization: `Bearer ${this.token}`, - ...headers, - } - } - - async request(path, options = {}) { - const headers = this.headers(options.headers || {}) - const response = await fetch(this.apiURL + path, { ...options, headers }) - const contentType = response.headers.get('Content-Type') - if (contentType && /json/.test(contentType)) { - return parseJsonResponse(response) - } - - if (!response.ok) { - const data = await response.text() - const error = `Data: ${data}. Status: ${response.status}` - throw new Error(error) - } - return await response.text() - } -} - -// -// Fetch a user from GoTrue via id -// -const fetchUser = function (identity, id) { - const api = new IdentityAPI(identity.url, identity.token) - return api.request(`/admin/users/${id}`) -} - -// -// Update the app_metadata of a user -// -const updateUser = function (identity, user, appMetadata) { - const api = new IdentityAPI(identity.url, identity.token) - - return api.request(`/admin/users/${user.id}`, { - method: 'PUT', - body: JSON.stringify({ app_metadata: { ...user.app_metadata, ...appMetadata } }), - }) -} - -// One hour -const MESSAGE_RATE_LIMIT = 36e5 - -module.exports = async function handler(event, context) { - if (event.httpMethod !== 'POST') { - return { - statusCode: 410, - body: 'Unsupported Request Method', - } - } - - const claims = context.clientContext && context.clientContext.user - if (!claims) { - return { - statusCode: 401, - body: 'You must be signed in to call this function', - } - } - - const user = await fetchUser(context.clientContext.identity, claims.sub) - const lastMessage = new Date(user.app_metadata.last_message_at || 0).getTime() - const cutOff = Date.now() - MESSAGE_RATE_LIMIT - if (lastMessage > cutOff) { - return { - statusCode: 401, - body: 'Only one message an hour allowed', - } - } - - try { - const payload = JSON.parse(event.body) - - await fetch(slackURL, { - method: 'POST', - body: JSON.stringify({ - text: payload.text, - attachments: [{ text: `From ${user.email}` }], - }), - }) - await updateUser(context.clientContext.identity, user, { - last_message_at: Date.now(), - }) - return { statusCode: 204 } - } catch (error) { - return { statusCode: 500, body: `Internal Server Error: ${error}` } - } -} diff --git a/src/functions-templates/javascript/stripe-charge/.netlify-function-template.mjs b/src/functions-templates/javascript/stripe-charge/.netlify-function-template.mjs deleted file mode 100644 index 93bce4238a4..00000000000 --- a/src/functions-templates/javascript/stripe-charge/.netlify-function-template.mjs +++ /dev/null @@ -1,28 +0,0 @@ -import chalk from 'chalk' - -export default { - name: 'stripe-charge', - description: 'Stripe Charge: Charge a user with Stripe', - functionType: 'serverless', - async onComplete() { - console.log(`${chalk.yellow('stripe-charge')} function created from template!`) - if (!process.env.STRIPE_SECRET_KEY) { - console.log( - `note this function requires ${chalk.yellow( - 'STRIPE_SECRET_KEY', - )} build environment variable set in your Netlify Site.`, - ) - let siteData = { name: 'YOURSITENAMEHERE' } - try { - siteData = await this.netlify.api.getSite({ - siteId: this.netlify.site.id, - }) - } catch (e) { - // silent error, not important - } - console.log( - `Set it at: https://app.netlify.com/sites/${siteData.name}/settings/deploys#environment-variables (must have CD setup)`, - ) - } - }, -} diff --git a/src/functions-templates/javascript/stripe-charge/package-lock.json b/src/functions-templates/javascript/stripe-charge/package-lock.json deleted file mode 100644 index e516ee97ed5..00000000000 --- a/src/functions-templates/javascript/stripe-charge/package-lock.json +++ /dev/null @@ -1,196 +0,0 @@ -{ - "name": "stripe-charge", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "stripe-charge", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "stripe": "^10.0.0" - } - }, - "node_modules/@types/node": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.2.tgz", - "integrity": "sha512-JepeIUPFDARgIs0zD/SKPgFsJEAF0X5/qO80llx59gOxFTboS9Amv3S+QfB7lqBId5sFXJ99BN0J6zFRvL9dDA==" - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/stripe": { - "version": "10.17.0", - "resolved": "https://registry.npmjs.org/stripe/-/stripe-10.17.0.tgz", - "integrity": "sha512-JHV2KoL+nMQRXu3m9ervCZZvi4DDCJfzHUE6CmtJxR9TmizyYfrVuhGvnsZLLnheby9Qrnf4Hq6iOEcejGwnGQ==", - "dependencies": { - "@types/node": ">=8.1.0", - "qs": "^6.11.0" - }, - "engines": { - "node": "^8.1 || >=10.*" - } - } - }, - "dependencies": { - "@types/node": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.2.tgz", - "integrity": "sha512-JepeIUPFDARgIs0zD/SKPgFsJEAF0X5/qO80llx59gOxFTboS9Amv3S+QfB7lqBId5sFXJ99BN0J6zFRvL9dDA==" - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - }, - "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "requires": { - "side-channel": "^1.0.4" - } - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "stripe": { - "version": "10.17.0", - "resolved": "https://registry.npmjs.org/stripe/-/stripe-10.17.0.tgz", - "integrity": "sha512-JHV2KoL+nMQRXu3m9ervCZZvi4DDCJfzHUE6CmtJxR9TmizyYfrVuhGvnsZLLnheby9Qrnf4Hq6iOEcejGwnGQ==", - "requires": { - "@types/node": ">=8.1.0", - "qs": "^6.11.0" - } - } - } -} diff --git a/src/functions-templates/javascript/stripe-charge/package.json b/src/functions-templates/javascript/stripe-charge/package.json deleted file mode 100644 index 1f8fce643f6..00000000000 --- a/src/functions-templates/javascript/stripe-charge/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "stripe-charge", - "version": "1.0.0", - "description": "netlify functions:create - Charge a user with Stripe", - "main": "stripe-charge.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "apis", - "stripe", - "js" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "stripe": "^10.0.0" - } -} diff --git a/src/functions-templates/javascript/stripe-charge/{{name}}.js b/src/functions-templates/javascript/stripe-charge/{{name}}.js deleted file mode 100644 index 09d7eab33f9..00000000000 --- a/src/functions-templates/javascript/stripe-charge/{{name}}.js +++ /dev/null @@ -1,56 +0,0 @@ -// with thanks https://github.com/alexmacarthur/netlify-lambda-function-example/blob/68a0cdc05e201d68fe80b0926b0af7ff88f15802/lambda-src/purchase.js -const process = require('process') - -const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY) - -const statusCode = 200 -const headers = { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': 'Content-Type', -} - -const handler = async function (event) { - // -- We only care to do anything if this is our POST request. - if (event.httpMethod !== 'POST' || !event.body) { - return { - statusCode, - headers, - body: '', - } - } - - // -- Parse the body contents into an object. - const data = JSON.parse(event.body) - - // -- Make sure we have all required data. Otherwise, escape. - if (!data.token || !data.amount || !data.idempotency_key) { - console.error('Required information is missing.') - - return { - statusCode, - headers, - body: JSON.stringify({ status: 'missing-information' }), - } - } - - try { - const charge = await stripe.charges.create( - { - currency: 'usd', - amount: data.amount, - source: data.token.id, - receipt_email: data.token.email, - description: `charge for a widget`, - }, - { - idempotency_key: data.idempotency_key, - }, - ) - const status = charge === null || charge.status !== 'succeeded' ? 'failed' : charge.status - return { statusCode, headers, body: JSON.stringify({ status }) } - } catch (error) { - return { statusCode: 500, error: error.message } - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/stripe-subscription/.netlify-function-template.mjs b/src/functions-templates/javascript/stripe-subscription/.netlify-function-template.mjs deleted file mode 100644 index 213791a2dd7..00000000000 --- a/src/functions-templates/javascript/stripe-subscription/.netlify-function-template.mjs +++ /dev/null @@ -1,28 +0,0 @@ -import chalk from 'chalk' - -export default { - name: 'stripe-subscription', - description: 'Stripe subscription: Create a subscription with Stripe', - functionType: 'serverless', - async onComplete() { - console.log(`${chalk.yellow('stripe-subscription')} function created from template!`) - if (!process.env.STRIPE_SECRET_KEY) { - console.log( - `note this function requires ${chalk.yellow( - 'STRIPE_SECRET_KEY', - )} build environment variable set in your Netlify Site.`, - ) - let siteData = { name: 'YOURSITENAMEHERE' } - try { - siteData = await this.netlify.api.getSite({ - siteId: this.netlify.site.id, - }) - } catch (e) { - // silent error, not important - } - console.log( - `Set it at: https://app.netlify.com/sites/${siteData.name}/settings/deploys#environment-variables (must have CD setup)`, - ) - } - }, -} diff --git a/src/functions-templates/javascript/stripe-subscription/package-lock.json b/src/functions-templates/javascript/stripe-subscription/package-lock.json deleted file mode 100644 index ac894405ab6..00000000000 --- a/src/functions-templates/javascript/stripe-subscription/package-lock.json +++ /dev/null @@ -1,196 +0,0 @@ -{ - "name": "stripe-subscription", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "stripe-subscription", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "stripe": "^10.0.0" - } - }, - "node_modules/@types/node": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.2.tgz", - "integrity": "sha512-JepeIUPFDARgIs0zD/SKPgFsJEAF0X5/qO80llx59gOxFTboS9Amv3S+QfB7lqBId5sFXJ99BN0J6zFRvL9dDA==" - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/stripe": { - "version": "10.17.0", - "resolved": "https://registry.npmjs.org/stripe/-/stripe-10.17.0.tgz", - "integrity": "sha512-JHV2KoL+nMQRXu3m9ervCZZvi4DDCJfzHUE6CmtJxR9TmizyYfrVuhGvnsZLLnheby9Qrnf4Hq6iOEcejGwnGQ==", - "dependencies": { - "@types/node": ">=8.1.0", - "qs": "^6.11.0" - }, - "engines": { - "node": "^8.1 || >=10.*" - } - } - }, - "dependencies": { - "@types/node": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.2.tgz", - "integrity": "sha512-JepeIUPFDARgIs0zD/SKPgFsJEAF0X5/qO80llx59gOxFTboS9Amv3S+QfB7lqBId5sFXJ99BN0J6zFRvL9dDA==" - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - }, - "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "requires": { - "side-channel": "^1.0.4" - } - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "stripe": { - "version": "10.17.0", - "resolved": "https://registry.npmjs.org/stripe/-/stripe-10.17.0.tgz", - "integrity": "sha512-JHV2KoL+nMQRXu3m9ervCZZvi4DDCJfzHUE6CmtJxR9TmizyYfrVuhGvnsZLLnheby9Qrnf4Hq6iOEcejGwnGQ==", - "requires": { - "@types/node": ">=8.1.0", - "qs": "^6.11.0" - } - } - } -} diff --git a/src/functions-templates/javascript/stripe-subscription/package.json b/src/functions-templates/javascript/stripe-subscription/package.json deleted file mode 100644 index a1623633f12..00000000000 --- a/src/functions-templates/javascript/stripe-subscription/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "stripe-subscription", - "version": "1.0.0", - "description": "netlify functions:create - Create a subscription with Stripe", - "main": "stripe-subscription.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "apis", - "stripe", - "js" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "stripe": "^10.0.0" - } -} diff --git a/src/functions-templates/javascript/stripe-subscription/{{name}}.js b/src/functions-templates/javascript/stripe-subscription/{{name}}.js deleted file mode 100644 index 6fb46e2a9f2..00000000000 --- a/src/functions-templates/javascript/stripe-subscription/{{name}}.js +++ /dev/null @@ -1,52 +0,0 @@ -// with thanks https://github.com/LukeMwila/stripe-subscriptions-backend/blob/master/stripe-api/index.ts -const process = require('process') - -const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY) - -const respond = (fulfillmentText) => ({ - statusCode: 200, - body: JSON.stringify(fulfillmentText), - headers: { - 'Access-Control-Allow-Credentials': true, - 'Access-Control-Allow-Origin': '*', - 'Content-Type': 'application/json', - }, -}) - -const handler = async function (event) { - let incoming - try { - incoming = JSON.parse(event.body) - } catch (error) { - console.error(`error with parsing function parameters:`, error) - return { - statusCode: 400, - body: JSON.stringify(error), - } - } - try { - const { email, productPlan, stripeToken } = incoming - const data = await createCustomerAndSubscribeToPlan(stripeToken, email, productPlan) - return respond(data) - } catch (error) { - return respond(error) - } -} - -const createCustomerAndSubscribeToPlan = async function (stripeToken, email, productPlan) { - // create a customer - const customer = await stripe.customers.create({ - email, - source: stripeToken, - }) - // retrieve created customer id to add customer to subscription plan - const customerId = customer.id - // create a subscription for the newly created customer - const subscription = await stripe.subscriptions.create({ - customer: customerId, - items: [{ plan: productPlan }], - }) - return subscription -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/token-hider/.netlify-function-template.mjs b/src/functions-templates/javascript/token-hider/.netlify-function-template.mjs deleted file mode 100644 index 984cc9e413f..00000000000 --- a/src/functions-templates/javascript/token-hider/.netlify-function-template.mjs +++ /dev/null @@ -1,29 +0,0 @@ -import chalk from 'chalk' - -export default { - name: 'token-hider', - description: 'Token Hider: access APIs without exposing your API keys', - functionType: 'serverless', - async onComplete() { - console.log(`${chalk.yellow('token-hider')} function created from template!`) - if (!process.env.API_URL || !process.env.API_TOKEN) { - console.log( - `note this function requires ${chalk.yellow('API_URL')} and ${chalk.yellow( - 'API_TOKEN', - )} build environment variables set in your Netlify Site.`, - ) - - let siteData = { name: 'YOURSITENAMEHERE' } - try { - siteData = await this.netlify.api.getSite({ - siteId: this.netlify.site.id, - }) - } catch (e) { - // silent error, not important - } - console.log( - `Set them at: https://app.netlify.com/sites/${siteData.name}/settings/deploys#environment-variables (must have CD setup)`, - ) - } - }, -} diff --git a/src/functions-templates/javascript/token-hider/package-lock.json b/src/functions-templates/javascript/token-hider/package-lock.json deleted file mode 100644 index 4a414a91d75..00000000000 --- a/src/functions-templates/javascript/token-hider/package-lock.json +++ /dev/null @@ -1,317 +0,0 @@ -{ - "name": "token-hider", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "token-hider", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "axios": "^1.0.0", - "qs": "^6.7.0" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/axios": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.6.tgz", - "integrity": "sha512-PEcdkk7JcdPiMDkvM4K6ZBRYq9keuVJsToxm2zQIM70Qqo2WHTdJZMXcG9X+RmRp2VPNUQC8W1RAGbgt6b1yMg==", - "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", - "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - } - }, - "dependencies": { - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "axios": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.6.tgz", - "integrity": "sha512-PEcdkk7JcdPiMDkvM4K6ZBRYq9keuVJsToxm2zQIM70Qqo2WHTdJZMXcG9X+RmRp2VPNUQC8W1RAGbgt6b1yMg==", - "requires": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "follow-redirects": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", - "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==" - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", - "requires": { - "side-channel": "^1.0.4" - } - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - } - } -} diff --git a/src/functions-templates/javascript/token-hider/package.json b/src/functions-templates/javascript/token-hider/package.json deleted file mode 100644 index 40003db9a88..00000000000 --- a/src/functions-templates/javascript/token-hider/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "token-hider", - "version": "1.0.0", - "description": "netlify functions:create - how to hide API tokens from your users", - "main": "token-hider.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "apis", - "js" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "axios": "^1.0.0", - "qs": "^6.7.0" - } -} diff --git a/src/functions-templates/javascript/token-hider/{{name}}.js b/src/functions-templates/javascript/token-hider/{{name}}.js deleted file mode 100644 index d72f5361f66..00000000000 --- a/src/functions-templates/javascript/token-hider/{{name}}.js +++ /dev/null @@ -1,37 +0,0 @@ -const process = require('process') - -const axios = require('axios') -const qs = require('qs') - -const handler = async function (event) { - // apply our function to the queryStringParameters and assign it to a variable - const API_PARAMS = qs.stringify(event.queryStringParameters) - console.log('API_PARAMS', API_PARAMS) - // Get env var values defined in our Netlify site UI - - // TODO: customize your URL and API keys set in the Netlify Dashboard - // this is secret too, your frontend won't see this - const { API_SECRET = 'shiba' } = process.env - const URL = `https://dog.ceo/api/breed/${API_SECRET}/images` - - console.log('Constructed URL is ...', URL) - - try { - const { data } = await axios.get(URL) - // refer to axios docs for other methods if you need them - // for example if you want to POST data: - // axios.post('/user', { firstName: 'Fred' }) - return { - statusCode: 200, - body: JSON.stringify(data), - } - } catch (error) { - const { data, headers, status, statusText } = error.response - return { - statusCode: error.response.status, - body: JSON.stringify({ status, statusText, headers, data }), - } - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/url-shortener/.netlify-function-template.mjs b/src/functions-templates/javascript/url-shortener/.netlify-function-template.mjs deleted file mode 100644 index f8029d9e0e0..00000000000 --- a/src/functions-templates/javascript/url-shortener/.netlify-function-template.mjs +++ /dev/null @@ -1,29 +0,0 @@ -import chalk from 'chalk' - -export default { - name: 'url-shortener', - description: 'URL Shortener: simple URL shortener with Netlify Forms!', - functionType: 'serverless', - async onComplete() { - console.log(`${chalk.yellow('url-shortener')} function created from template!`) - if (!process.env.ROUTES_FORM_ID || !process.env.API_AUTH) { - console.log( - `note this function requires ${chalk.yellow('ROUTES_FORM_ID')} and ${chalk.yellow( - 'API_AUTH', - )} build environment variables set in your Netlify Site.`, - ) - - let siteData = { name: 'YOURSITENAMEHERE' } - try { - siteData = await this.netlify.api.getSite({ - siteId: this.netlify.site.id, - }) - } catch (e) { - // silent error, not important - } - console.log( - `Set them at: https://app.netlify.com/sites/${siteData.name}/settings/deploys#environment-variables (must have CD setup)`, - ) - } - }, -} diff --git a/src/functions-templates/javascript/url-shortener/generate-route.js b/src/functions-templates/javascript/url-shortener/generate-route.js deleted file mode 100644 index 0706dd6af4b..00000000000 --- a/src/functions-templates/javascript/url-shortener/generate-route.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict' -const process = require('process') - -const fetch = require('fetch') -const FormData = require('form-data') -const Hashids = require('hashids/cjs') - -const NUMBER_TO_CODE = 100 - -module.exports = async function handler(event) { - // Set the root URL according to the Netlify site we are within - const rootURL = `${process.env.URL}/` - - // get the details of what we are creating - let destination = event.queryStringParameters.to - - // generate a unique short code (stupidly for now) - const hash = new Hashids() - const number = Math.round(Date.now() / NUMBER_TO_CODE) - const code = hash.encode(number) - - // ensure that a protocol was provided - if (!destination.includes('://')) { - destination = `http://${destination}` - } - - // prepare a payload to post - const form = new FormData() - form.append('form-name', 'routes') - form.append('destination', destination) - form.append('code', code) - form.append('expires', '') - - // post the new route to the Routes form - try { - await fetch(rootURL, { method: 'POST', body: form }) - const url = `${rootURL}${code}` - console.log(`Route registered. Site deploying to include it. ${url}`) - // tell the user what their shortcode will be - return { - statusCode: 200, - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ url }), - } - } catch (error) { - return { statusCode: 500, body: `Post to Routes stash failed: ${error.message}` } - } - - // ENHANCEMENT: check for uniqueness of shortcode - // ENHANCEMENT: let the user provide their own shortcode - // ENHANCEMENT: dont' duplicate existing routes, return the current one - // ENHANCEMENT: allow the user to specify how long the redirect should exist for -} diff --git a/src/functions-templates/javascript/url-shortener/get-route.js b/src/functions-templates/javascript/url-shortener/get-route.js deleted file mode 100644 index 8515545a8e6..00000000000 --- a/src/functions-templates/javascript/url-shortener/get-route.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict' -const process = require('process') - -const fetch = require('fetch') - -module.exports = async function handler(event) { - // which URL code are we trying to retrieve? - const { code } = event.queryStringParameters - - try { - const response = await fetch( - `https://api.netlify.com/api/v1/forms/${process.env.ROUTES_FORM_ID}/submissions/?access_token=${process.env.API_AUTH}`, - ) - const body = await response.text() - - if (response.statusCode !== 200) { - return { statusCode: 500, body } - } - - const { - data: { destination }, - } = body.find(({ data }) => data.code === code) - console.log(`We searched for ${code} and we found ${destination}`) - return { - statusCode: 200, - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ code, url: destination }), - } - } catch (error) { - return { statusCode: 500, body: error.message } - } -} diff --git a/src/functions-templates/javascript/url-shortener/package-lock.json b/src/functions-templates/javascript/url-shortener/package-lock.json deleted file mode 100644 index 0f819553ab8..00000000000 --- a/src/functions-templates/javascript/url-shortener/package-lock.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "name": "url-shortener", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "url-shortener", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "form-data": "^4.0.0", - "hashids": "^2.0.0" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/hashids": { - "version": "2.2.11", - "resolved": "https://registry.npmjs.org/hashids/-/hashids-2.2.11.tgz", - "integrity": "sha512-e1rAPT5Wa9vf/Dq1eq8LFw5VH2dtKxRf6k9bCw0GLwKL/SRnUphIcqwJWUZ1ki18cdj03nCrpdlJOcyHILQk8Q==" - }, - "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "dependencies": { - "mime-db": "1.51.0" - }, - "engines": { - "node": ">= 0.6" - } - } - }, - "dependencies": { - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "hashids": { - "version": "2.2.11", - "resolved": "https://registry.npmjs.org/hashids/-/hashids-2.2.11.tgz", - "integrity": "sha512-e1rAPT5Wa9vf/Dq1eq8LFw5VH2dtKxRf6k9bCw0GLwKL/SRnUphIcqwJWUZ1ki18cdj03nCrpdlJOcyHILQk8Q==" - }, - "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" - }, - "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "requires": { - "mime-db": "1.51.0" - } - } - } -} diff --git a/src/functions-templates/javascript/url-shortener/package.json b/src/functions-templates/javascript/url-shortener/package.json deleted file mode 100644 index 5ee0c3649ee..00000000000 --- a/src/functions-templates/javascript/url-shortener/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "url-shortener", - "version": "1.0.0", - "description": "", - "main": "url-shortener.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "apis", - "url", - "js" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "form-data": "^4.0.0", - "hashids": "^2.0.0" - } -} diff --git a/src/functions-templates/javascript/url-shortener/{{name}}.js b/src/functions-templates/javascript/url-shortener/{{name}}.js deleted file mode 100644 index 7c0a7a9988c..00000000000 --- a/src/functions-templates/javascript/url-shortener/{{name}}.js +++ /dev/null @@ -1,30 +0,0 @@ -const generateRoute = require('./generate-route.js') -const getRoute = require('./get-route.js') - -const handler = async (event) => { - const path = event.path.replace(/\.netlify\/functions\/[^/]+/, '') - const segments = path.split('/').filter(Boolean) - console.log('segments', segments) - - switch (event.httpMethod) { - case 'GET': - // e.g. GET /.netlify/functions/url-shortener - return getRoute(event) - case 'POST': - // e.g. POST /.netlify/functions/url-shortener - return generateRoute(event) - case 'PUT': - // your code here - return - case 'DELETE': - // your code here - return - default: - return { - statusCode: 500, - error: `unrecognized HTTP Method ${event.httpMethod}, must be one of GET/POST/PUT/DELETE`, - } - } -} - -module.exports = { handler } diff --git a/src/functions-templates/javascript/using-middleware/.netlify-function-template.mjs b/src/functions-templates/javascript/using-middleware/.netlify-function-template.mjs deleted file mode 100644 index 4875ce06018..00000000000 --- a/src/functions-templates/javascript/using-middleware/.netlify-function-template.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - name: 'using-middleware', - description: 'Using Middleware with middy', - functionType: 'serverless', -} diff --git a/src/functions-templates/javascript/using-middleware/package.json b/src/functions-templates/javascript/using-middleware/package.json deleted file mode 100644 index f46a6d39563..00000000000 --- a/src/functions-templates/javascript/using-middleware/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "using-middleware", - "version": "1.0.0", - "description": "netlify functions:create - using middleware with your netlify function", - "main": "using-middleware.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "netlify", - "serverless", - "js" - ], - "author": "Netlify", - "license": "MIT", - "dependencies": { - "middy": "^0.36.0" - } -} diff --git a/src/functions-templates/javascript/using-middleware/{{name}}.js b/src/functions-templates/javascript/using-middleware/{{name}}.js deleted file mode 100644 index bf159440293..00000000000 --- a/src/functions-templates/javascript/using-middleware/{{name}}.js +++ /dev/null @@ -1,60 +0,0 @@ -const middy = require('middy') -const { httpErrorHandler, httpHeaderNormalizer, jsonBodyParser, validator } = require('middy/middlewares') - -/* Normal lambda code */ -const businessLogic = async (event) => { - // event.body has already been turned into an object by `jsonBodyParser` middleware - const { name } = event.body - return { - statusCode: 200, - body: JSON.stringify({ - result: 'success', - message: `Hi ${name} ⊂◉‿◉つ`, - }), - } -} - -/* Export inputSchema & outputSchema for automatic documentation */ -const schema = { - input: { - type: 'object', - properties: { - body: { - type: 'object', - required: ['name'], - properties: { - name: { type: 'string' }, - }, - }, - }, - required: ['body'], - }, - output: { - type: 'object', - properties: { - body: { - type: 'string', - required: ['result', 'message'], - properties: { - result: { type: 'string' }, - message: { type: 'string' }, - }, - }, - }, - required: ['body'], - }, -} - -const handler = middy(businessLogic) - .use(httpHeaderNormalizer()) - // parses the request body when it's a JSON and converts it to an object - .use(jsonBodyParser()) - // validates the input - .use(validator({ inputSchema: schema.input })) - // handles common http errors and returns proper responses - .use(httpErrorHandler()) - -module.exports = { - schema, - handler, -} diff --git a/tests/integration/commands/functions-create/functions-create.test.ts b/tests/integration/commands/functions-create/functions-create.test.ts index 5bf3d8f5c47..b878f3be53d 100644 --- a/tests/integration/commands/functions-create/functions-create.test.ts +++ b/tests/integration/commands/functions-create/functions-create.test.ts @@ -143,101 +143,6 @@ describe.concurrent('functions:create command', () => { }) }) - test('should install function template dependencies on a site-level `package.json` if one is found', async () => { - await withSiteBuilder('site-with-no-functions-dir-with-package-json', async (builder) => { - builder.withPackageJson({ - packageJson: { - dependencies: { - '@netlify/functions': '^0.1.0', - }, - }, - }) - - await builder.buildAsync() - - const createFunctionQuestions = [ - { - question: "Select the type of function you'd like to create", - answer: answerWithValue(DOWN), - }, - { - question: 'Enter the path, relative to your site', - answer: answerWithValue('test/functions'), - }, - { - question: 'Select the language of your function', - answer: CONFIRM, - }, - { - question: 'Pick a template', - answer: answerWithValue(`set-cookie`), - }, - { - question: 'Name your function', - answer: CONFIRM, - }, - ] - - await withMockApi(routes, async ({ apiUrl }) => { - const childProcess = execa(cliPath, ['functions:create'], getCLIOptions({ apiUrl, builder })) - - handleQuestions(childProcess, createFunctionQuestions) - - await childProcess - - const { dependencies } = JSON.parse(await readFile(`${builder.directory}/package.json`, 'utf-8')) - - expect(await fileExistsAsync(`${builder.directory}/test/functions/set-cookie/set-cookie.js`)).toBe(true) - expect(await fileExistsAsync(`${builder.directory}/test/functions/set-cookie/package.json`)).toBe(false) - expect(await fileExistsAsync(`${builder.directory}/test/functions/set-cookie/package-lock.json`)).toBe(false) - expect(typeof dependencies.cookie).toBe('string') - - expect(dependencies['@netlify/functions']).toBe('^0.1.0') - }) - }) - }) - - test('should install function template dependencies in the function sub-directory if no site-level `package.json` is found', async () => { - await withSiteBuilder('site-with-no-functions-dir-without-package-json', async (builder) => { - await builder.buildAsync() - - const createFunctionQuestions = [ - { - question: "Select the type of function you'd like to create", - answer: answerWithValue(DOWN), - }, - { - question: 'Enter the path, relative to your site', - answer: answerWithValue('test/functions'), - }, - { - question: 'Select the language of your function', - answer: CONFIRM, - }, - { - question: 'Pick a template', - answer: answerWithValue(`set-cookie`), - }, - { - question: 'Name your function', - answer: CONFIRM, - }, - ] - - await withMockApi(routes, async ({ apiUrl }) => { - const childProcess = execa(cliPath, ['functions:create'], getCLIOptions({ apiUrl, builder })) - - handleQuestions(childProcess, createFunctionQuestions) - - await childProcess - - expect(await fileExistsAsync(`${builder.directory}/test/functions/set-cookie/set-cookie.js`)).toBe(true) - expect(await fileExistsAsync(`${builder.directory}/test/functions/set-cookie/package.json`)).toBe(true) - expect(await fileExistsAsync(`${builder.directory}/test/functions/set-cookie/package-lock.json`)).toBe(true) - }) - }) - }) - test('should not create a new function directory when one is found', async () => { await withSiteBuilder('site-with-functions-dir', async (builder) => { builder.withNetlifyToml({ config: { build: { functions: 'functions' } } })