algolia, sendgrid and slack sparks

This commit is contained in:
Shams mosowi
2020-09-29 16:26:56 +10:00
parent 3f1a0d781f
commit 120f0b7854
27 changed files with 9226 additions and 52 deletions

4
.gitignore vendored
View File

@@ -3,7 +3,7 @@
# dependencies
/node_modules
www/node_modules
www/.firebaserc
Firetable/node_modules
cloud_functions/functions/node_modules
@@ -22,7 +22,6 @@ cloud_functions/functions/lib
cloud_functions/functions/src/functionConfig.ts
cloud_functions/functions/firebase-credentials.json
cloud_functions/.firebaserc
# misc
.DS_Store
@@ -35,6 +34,7 @@ yarn-debug.log*
yarn-error.log*
firebase-debug.log*
*.firebaserc
# Accidental package installs to root directories

View File

@@ -18,6 +18,7 @@
"dependencies": {
"@google-cloud/cloudbuild": "^1.5.0",
"@google-cloud/firestore": "^3.7.5",
"@google-cloud/pubsub": "^2.5.0",
"@google-cloud/storage": "^5.1.2",
"@sendgrid/mail": "^7.2.6",
"@slack/web-api": "^5.11.0",

View File

@@ -71,6 +71,8 @@ if (serviceAccount) {
case "FT_subTableStats":
configData = `export const collectionPath ="${configString}"\nexport default []`;
break;
case "FT_spark":
configData = configString;
default:
configData = `export default ${configString}\n export const collectionPath=''`;
break;

View File

@@ -10,14 +10,20 @@ export const callable = callableFns;
// these functions are designed to be built and deployed based on the configuration passed through the callable
export { FT_derivatives } from "./derivatives";
export { FT_aggregates } from "./aggregates";
export { FT_algolia } from "./algolia";
export { FT_subTableStats } from "./subTableStats";
export { actionScript } from "./actionScript";
export { FT_spark } from "./sparks";
export { webhook } from "./webhooks";
export { FT_sync } from "./collectionSync";
export { FT_snapshotSync } from "./snapshotSync";
//export { FT_history } from "./history";
export { FT_subTableStats } from "./subTableStats";
export { FT_compressedThumbnail } from "./compressedThumbnail";
export { actionScript } from "./actionScript";
export { webhook } from "./webhooks";
export { slackBotMessageOnCreate } from "./slackOnTrigger/trigger";
// depercated will be using sparks integrations instead.
export { FT_algolia } from "./algolia";
export { FT_email } from "./emailOnTrigger";
export { FT_slack } from "./slackOnTrigger";
export { slackBotMessageOnCreate } from "./slackOnTrigger/trigger";

View File

@@ -1,36 +1,78 @@
const sampleConfig = [
{
type: "slack",
triggers: ["create"],
shouldSend: (row, db) => true,
requiredFields: [],
target: (row, db) => ({ emails: ["shams@antler.co"], channels: [] }),
message: (row, db) => ({
text: "I am a test ${user.firstName} message",
attachments: [
{
text: "And heres an attachment!",
},
],
}),
},
{
type: "sendGrid",
triggers: ["create"],
requiredFields: [],
shouldSend: (row, db) => true,
to: (row, db) => "",
cc: (row, db) => undefined,
bcc: (row, db) => undefined,
attachments: (row, db) => undefined,
templateId: "d-",
personalizations: ["firstName", { email: "user.email" }],
},
{
type: "algolia",
triggers: ["create", "update", "delete"],
index: "users",
requiredFields: ["email"],
fieldsToSync: ["firstName", "lastName", "email", { email: "user.email" }],
},
];
import * as functions from "firebase-functions";
import { hasRequiredFields } from "../utils";
const { PubSub } = require("@google-cloud/pubsub");
const pubSubClient = new PubSub();
import { db } from "../config";
import config, { collectionPath } from "../functionConfig";
// generated using generateConfig.ts
const functionConfig: any = config;
const sparkTrigger = async (
change: functions.Change<functions.firestore.DocumentSnapshot>,
context: functions.EventContext
) => {
const beforeData = change.before?.data();
const afterData = change.after?.data();
const ref = change.after ? change.after.ref : change.before.ref;
const triggerType =
Boolean(beforeData) && Boolean(afterData)
? "update"
: Boolean(afterData)
? "create"
: "delete";
try {
const sparkPromises = functionConfig.map(async (sparkConfig) => {
const {
topic,
triggers,
shouldRun,
requiredFields,
sparkBody,
} = sparkConfig;
const sparkContext = {
row: afterData,
ref,
db,
change,
triggerType,
sparkConfig,
};
if (!triggers.includes(triggerType)) return false; //check if trigger type is included in the spark
if (
triggerType !== "delete" &&
requiredFields &&
requiredFields.length !== 0 &&
!hasRequiredFields(requiredFields, afterData)
)
return false; // check if it hase required fields for the spark to run
const dontRun = shouldRun ? !(await shouldRun(sparkContext)) : false; //
if (dontRun) return false;
const sparkData = await Object.keys(sparkBody).reduce(
async (acc, key) => ({
[key]: await sparkBody[key](sparkContext),
...(await acc),
}),
{}
);
console.log(JSON.stringify(sparkData));
const messageBuffer = Buffer.from(JSON.stringify(sparkData), "utf8");
const messageId = await pubSubClient.topic(topic).publish(messageBuffer);
console.log(`Message ${messageId} published.`);
return true;
});
await Promise.all(sparkPromises);
return true;
} catch (err) {
console.error(err);
return Promise.reject(err);
}
};
export const FT_spark = {
[collectionPath.replace(/-/g, "_")]: functions.firestore
.document(`${collectionPath}/{docId}`)
.onWrite(sparkTrigger),
};

View File

@@ -151,6 +151,11 @@
resolved "https://registry.yarnpkg.com/@google-cloud/precise-date/-/precise-date-1.0.3.tgz#39c600ed52213f4158692a72c90d13b2162a93d2"
integrity sha512-wWnDGh9y3cJHLuVEY8t6un78vizzMWsS7oIWKeFtPj+Ndy+dXvHW0HTx29ZUhen+tswSlQYlwFubvuRP5kKdzQ==
"@google-cloud/precise-date@^2.0.0":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@google-cloud/precise-date/-/precise-date-2.0.3.tgz#14f6f28ce35dabf3882e7aeab1c9d51bd473faed"
integrity sha512-+SDJ3ZvGkF7hzo6BGa8ZqeK3F6Z4+S+KviC9oOK+XCs3tfMyJCh/4j93XIWINgMMDIh9BgEvlw4306VxlXIlYA==
"@google-cloud/projectify@^1.0.0":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-1.0.4.tgz#28daabebba6579ed998edcadf1a8f3be17f3b5f0"
@@ -192,6 +197,27 @@
p-defer "^3.0.0"
protobufjs "^6.8.1"
"@google-cloud/pubsub@^2.5.0":
version "2.5.0"
resolved "https://registry.yarnpkg.com/@google-cloud/pubsub/-/pubsub-2.5.0.tgz#6c696d9b448f2e1689be9a37ef0362ed173731fd"
integrity sha512-7bbbQqa+LSTopVjt20EZ8maO6rEpbO7v8EvDImHMsbRS30HJ5+kClbaQTRvhNzhc1qy221A1GbHPHMCQ/U5E3Q==
dependencies:
"@google-cloud/paginator" "^3.0.0"
"@google-cloud/precise-date" "^2.0.0"
"@google-cloud/projectify" "^2.0.0"
"@google-cloud/promisify" "^2.0.0"
"@opentelemetry/api" "^0.10.0"
"@opentelemetry/tracing" "^0.10.0"
"@types/duplexify" "^3.6.0"
"@types/long" "^4.0.0"
arrify "^2.0.0"
extend "^3.0.2"
google-auth-library "^6.0.0"
google-gax "^2.7.0"
is-stream-ended "^0.1.4"
lodash.snakecase "^4.1.1"
p-defer "^3.0.0"
"@google-cloud/storage@^4.1.2":
version "4.7.0"
resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-4.7.0.tgz#a7466086a83911c7979cc238d00a127ffb645615"
@@ -260,6 +286,16 @@
dependencies:
semver "^6.2.0"
"@grpc/grpc-js@~1.1.1":
version "1.1.7"
resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.1.7.tgz#d3d71c6da95397e2d63895ccc4a05e7572f7b7e6"
integrity sha512-EuxMstI0u778dp0nk6Fe3gHXYPeV6FYsWOe0/QFwxv1NQ6bc5Wl/0Yxa4xl9uBlKElL6AIxuASmSfu7KEJhqiw==
dependencies:
"@grpc/proto-loader" "^0.6.0-pre14"
"@types/node" "^12.12.47"
google-auth-library "^6.0.0"
semver "^6.2.0"
"@grpc/proto-loader@^0.5.1":
version "0.5.5"
resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.5.5.tgz#6725e7a1827bdf8e92e29fbf4e9ef0203c0906a9"
@@ -268,6 +304,17 @@
lodash.camelcase "^4.3.0"
protobufjs "^6.8.6"
"@grpc/proto-loader@^0.6.0-pre14":
version "0.6.0-pre9"
resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.6.0-pre9.tgz#0c6fe42f6c5ef9ce1b3cef7be64d5b09d6fe4d6d"
integrity sha512-oM+LjpEjNzW5pNJjt4/hq1HYayNeQT+eGrOPABJnYHv7TyNPDNzkQ76rDYZF86X5swJOa4EujEMzQ9iiTdPgww==
dependencies:
"@types/long" "^4.0.1"
lodash.camelcase "^4.3.0"
long "^4.0.0"
protobufjs "^6.9.0"
yargs "^15.3.1"
"@nodelib/fs.scandir@2.1.3":
version "2.1.3"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b"
@@ -289,6 +336,46 @@
"@nodelib/fs.scandir" "2.1.3"
fastq "^1.6.0"
"@opentelemetry/api@^0.10.0", "@opentelemetry/api@^0.10.2":
version "0.10.2"
resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-0.10.2.tgz#9647b881f3e1654089ff7ea59d587b2d35060654"
integrity sha512-GtpMGd6vkzDMYcpu2t9LlhEgMy/SzBwRnz48EejlRArYqZzqSzAsKmegUK7zHgl+EOIaK9mKHhnRaQu3qw20cA==
dependencies:
"@opentelemetry/context-base" "^0.10.2"
"@opentelemetry/context-base@^0.10.2":
version "0.10.2"
resolved "https://registry.yarnpkg.com/@opentelemetry/context-base/-/context-base-0.10.2.tgz#55bea904b2b91aa8a8675df9eaba5961bddb1def"
integrity sha512-hZNKjKOYsckoOEgBziGMnBcX0M7EtstnCmwz5jZUOUYwlZ+/xxX6z3jPu1XVO2Jivk0eLfuP9GP+vFD49CMetw==
"@opentelemetry/core@^0.10.2":
version "0.10.2"
resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-0.10.2.tgz#86b9e94bbcaf8e07bb86e8205aa1d53af854e7de"
integrity sha512-DhkiTp5eje2zTGd+HAIKWpGE6IR6lq7tUpYt4nnkhOi6Hq9WQAANVDCWEZEbYOw57LkdXbE50FZ/kMvHDm450Q==
dependencies:
"@opentelemetry/api" "^0.10.2"
"@opentelemetry/context-base" "^0.10.2"
semver "^7.1.3"
"@opentelemetry/resources@^0.10.2":
version "0.10.2"
resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-0.10.2.tgz#6e291d525450359c615aac013fd977047f2c26d7"
integrity sha512-5JGC2TPSAIHth615IURt+sSsTljY43zTfJD0JE9PHC6ipZPiQ0dpQDZOrLn8NAMfOHY1jeWwpIuLASjqbXUfuw==
dependencies:
"@opentelemetry/api" "^0.10.2"
"@opentelemetry/core" "^0.10.2"
gcp-metadata "^3.5.0"
"@opentelemetry/tracing@^0.10.0":
version "0.10.2"
resolved "https://registry.yarnpkg.com/@opentelemetry/tracing/-/tracing-0.10.2.tgz#384779a6e1be988200cc316a97030d95bd8f2129"
integrity sha512-mNAhARn4dEdOjTa9OdysjI4fRHMbvr4YSbPuH7jhkyPzgoa+DnvnbY3GGpEay6kpuYJsrW8Ef9OIKAV/GndhbQ==
dependencies:
"@opentelemetry/api" "^0.10.2"
"@opentelemetry/context-base" "^0.10.2"
"@opentelemetry/core" "^0.10.2"
"@opentelemetry/resources" "^0.10.2"
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
@@ -543,6 +630,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.3.tgz#cc4f979548ca4d8e7b90bc0180052ab99ee64224"
integrity sha512-pC/hkcREG6YfDfui1FBmj8e20jFU5Exjw4NYDm8kEdrW+mOh0T1Zve8DWKnS7ZIZvgncrctcNCXF4Q2I+loyww==
"@types/node@^12.12.47":
version "12.12.62"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.62.tgz#733923d73669188d35950253dd18a21570085d2b"
integrity sha512-qAfo81CsD7yQIM9mVyh6B/U47li5g7cfpVQEDMfQeF8pSZVwzbhwU3crc0qG4DmpsebpJPR49AKOExQyJ05Cpg==
"@types/node@^13.7.0":
version "13.13.16"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.16.tgz#66f2177047b61131eaac18c47eb25d6f1317070a"
@@ -710,7 +802,7 @@ ansi-styles@^3.2.1:
dependencies:
color-convert "^1.9.0"
ansi-styles@^4.1.0:
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359"
integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==
@@ -1204,7 +1296,7 @@ camelcase@^4.0.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
camelcase@^5.3.1:
camelcase@^5.0.0, camelcase@^5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
@@ -1378,6 +1470,15 @@ cli-width@^2.0.0:
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
cliui@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
dependencies:
string-width "^4.2.0"
strip-ansi "^6.0.0"
wrap-ansi "^6.2.0"
clone-response@1.0.2, clone-response@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
@@ -1782,7 +1883,7 @@ debug@^3.1.1:
dependencies:
ms "^2.1.1"
decamelize@^1.1.2:
decamelize@^1.1.2, decamelize@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
@@ -2050,7 +2151,7 @@ duplexify@^3.5.0, duplexify@^3.6.0:
readable-stream "^2.0.0"
stream-shift "^1.0.0"
duplexify@^4.1.1:
duplexify@^4.0.0, duplexify@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.1.tgz#7027dc374f157b122a8ae08c2d3ea4d2d953aa61"
integrity sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==
@@ -2839,7 +2940,7 @@ gaxios@^3.0.0:
is-stream "^2.0.0"
node-fetch "^2.3.0"
gcp-metadata@^3.4.0:
gcp-metadata@^3.4.0, gcp-metadata@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-3.5.0.tgz#6d28343f65a6bbf8449886a0c0e4a71c77577055"
integrity sha512-ZQf+DLZ5aKcRpLzYUyBS3yo3N0JSa82lNDO8rj3nMSlovLcz2riKFBsYgDzeXcv75oo5eqB2lx+B14UvPoCRnA==
@@ -2880,6 +2981,11 @@ gcs-resumable-upload@^3.1.0:
pumpify "^2.0.0"
stream-events "^1.0.4"
get-caller-file@^2.0.1:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
get-proxy@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93"
@@ -3051,6 +3157,22 @@ google-gax@^1.14.2, google-gax@^1.15.3:
semver "^6.0.0"
walkdir "^0.4.0"
google-gax@^2.7.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-2.9.0.tgz#84edef8715d82c0f91a6e5485b8f2803d2690f00"
integrity sha512-MFMwA7Fb8PEwjnYwfGXjZMidCNyMl3gSnvS/+kS8TQioJZQDpzK+W3dmwyNyig/U13+kbABqDnbkkAXJ5NiUkw==
dependencies:
"@grpc/grpc-js" "~1.1.1"
"@grpc/proto-loader" "^0.5.1"
"@types/long" "^4.0.0"
abort-controller "^3.0.0"
duplexify "^4.0.0"
google-auth-library "^6.0.0"
is-stream-ended "^0.1.4"
node-fetch "^2.6.1"
protobufjs "^6.9.0"
retry-request "^4.0.0"
google-gax@~1.12.0:
version "1.12.0"
resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-1.12.0.tgz#f926f7e6abda245db38ecbebbbf58daaf3a8f687"
@@ -4634,6 +4756,11 @@ node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.6.0:
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
node-fetch@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
node-forge@^0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
@@ -5224,7 +5351,7 @@ proto-list@~1.2.1:
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
protobufjs@^6.8.1, protobufjs@^6.8.6, protobufjs@^6.8.8, protobufjs@^6.8.9:
protobufjs@^6.8.1, protobufjs@^6.8.6, protobufjs@^6.8.8, protobufjs@^6.8.9, protobufjs@^6.9.0:
version "6.10.1"
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.1.tgz#e6a484dd8f04b29629e9053344e3970cccf13cd2"
integrity sha512-pb8kTchL+1Ceg4lFd5XUpK8PdWacbvV5SK2ULH2ebrYtl4GjJmS24m6CKME67jzV53tbJxHlnNOSqQHbTsR9JQ==
@@ -5504,6 +5631,16 @@ request@^2.87.0, request@^2.88.2:
tunnel-agent "^0.6.0"
uuid "^3.3.2"
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
require-main-filename@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
@@ -5660,7 +5797,7 @@ semver@^6.0.0, semver@^6.2.0, semver@^6.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
semver@^7.3.2:
semver@^7.1.3, semver@^7.3.2:
version "7.3.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
@@ -5694,7 +5831,7 @@ serve-static@1.14.1:
parseurl "~1.3.3"
send "0.17.1"
set-blocking@~2.0.0:
set-blocking@^2.0.0, set-blocking@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
@@ -5960,7 +6097,7 @@ string-width@^3.0.0:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0"
string-width@^4.0.0, string-width@^4.1.0:
string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5"
integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==
@@ -6688,6 +6825,11 @@ which-collection@^1.0.1:
is-weakmap "^2.0.1"
is-weakset "^2.0.1"
which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
which-pm-runs@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb"
@@ -6763,6 +6905,15 @@ winston@^3.0.0:
triple-beam "^1.3.0"
winston-transport "^4.4.0"
wrap-ansi@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
@@ -6817,6 +6968,11 @@ xtend@^4.0.0, xtend@~4.0.0:
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
y18n@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
@@ -6837,6 +6993,31 @@ yaml@^1.7.2:
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e"
integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==
yargs-parser@^18.1.2:
version "18.1.3"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
dependencies:
camelcase "^5.0.0"
decamelize "^1.2.0"
yargs@^15.3.1:
version "15.4.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
dependencies:
cliui "^6.0.0"
decamelize "^1.2.0"
find-up "^4.1.0"
get-caller-file "^2.0.1"
require-directory "^2.1.1"
require-main-filename "^2.0.0"
set-blocking "^2.0.0"
string-width "^4.2.0"
which-module "^2.0.0"
y18n "^4.0.0"
yargs-parser "^18.1.2"
yauzl@^2.4.2:
version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"

66
sparks/algolia/.gitignore vendored Normal file
View File

@@ -0,0 +1,66 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
firebase-debug.log*
firebase-debug.*.log*
# Firebase cache
.firebase/
# Firebase config
# Uncomment this if you'd like others to create their own Firebase project.
# For a team working on the same Firebase project(s), it is recommended to leave
# it commented so all members can deploy to the same project(s) in .firebaserc.
# .firebaserc
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env

View File

@@ -0,0 +1,8 @@
{
"functions": {
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint",
"npm --prefix \"$RESOURCE_DIR\" run build"
]
}
}

9
sparks/algolia/functions/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
# Compiled JavaScript files
**/*.js
**/*.js.map
# TypeScript v1 declaration files
typings/
# Node.js dependency directory
node_modules/

View File

@@ -0,0 +1,30 @@
{
"name": "functions",
"scripts": {
"lint": "eslint 'src/**/*'",
"build": "tsc",
"serve": "npm run build && firebase emulators:start --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions:spark_algolia",
"logs": "firebase functions:log"
},
"engines": {
"node": "10"
},
"main": "lib/index.js",
"dependencies": {
"algoliasearch": "^4.5.1",
"firebase-admin": "^9.2.0",
"firebase-functions": "^3.6.1"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^3.9.1",
"@typescript-eslint/parser": "^3.8.0",
"eslint": "^7.6.0",
"eslint-plugin-import": "^2.22.0",
"firebase-functions-test": "^0.2.0",
"typescript": "^3.8.0"
},
"private": true
}

View File

@@ -0,0 +1,34 @@
import algoliasearch from "algoliasearch";
import { pubsub, config } from "firebase-functions";
export const env = config();
const APP_ID = env.algolia ? env.algolia.app : "NEEDS_CONFIG";
const ADMIN_KEY = env.algolia ? env.algolia.key : "NEEDS_CONFIG";
const client = algoliasearch(APP_ID, ADMIN_KEY);
const SPARK_TOPIC = "spark_algolia";
export const spark_algolia = pubsub
.topic(SPARK_TOPIC)
.onPublish(async (message, context) => {
const messageBody = message.data
? Buffer.from(message.data, "base64").toString("utf-8")
: "{}";
const data = JSON.parse(messageBody);
const { triggerType, record, objectID, index } = data;
const _index = client.initIndex(index); // initialize algolia index
console.log({ triggerType, record, objectID, index });
switch (triggerType) {
case "delete":
await _index.deleteObject(objectID);
break;
case "update":
case "create":
await _index.saveObject({ ...record, objectID });
break;
default:
break;
}
return true;
});

View File

@@ -0,0 +1,13 @@
{
"compilerOptions": {
"module": "commonjs",
"noImplicitReturns": true,
"noUnusedLocals": true,
"outDir": "lib",
"sourceMap": true,
"strict": true,
"target": "es2017"
},
"compileOnSave": true,
"include": ["src"]
}

File diff suppressed because it is too large Load Diff

66
sparks/sendgrid/.gitignore vendored Normal file
View File

@@ -0,0 +1,66 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
firebase-debug.log*
firebase-debug.*.log*
# Firebase cache
.firebase/
# Firebase config
# Uncomment this if you'd like others to create their own Firebase project.
# For a team working on the same Firebase project(s), it is recommended to leave
# it commented so all members can deploy to the same project(s) in .firebaserc.
# .firebaserc
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env

View File

@@ -0,0 +1,8 @@
{
"functions": {
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint",
"npm --prefix \"$RESOURCE_DIR\" run build"
]
}
}

9
sparks/sendgrid/functions/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
# Compiled JavaScript files
**/*.js
**/*.js.map
# TypeScript v1 declaration files
typings/
# Node.js dependency directory
node_modules/

View File

@@ -0,0 +1,30 @@
{
"name": "functions",
"scripts": {
"lint": "eslint 'src/**/*'",
"build": "tsc",
"serve": "npm run build && firebase emulators:start --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions:spark_sendgrid",
"logs": "firebase functions:log"
},
"engines": {
"node": "10"
},
"main": "lib/index.js",
"dependencies": {
"@sendgrid/mail": "^7.2.6",
"firebase-admin": "^9.2.0",
"firebase-functions": "^3.6.1"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^3.9.1",
"@typescript-eslint/parser": "^3.8.0",
"eslint": "^7.6.0",
"eslint-plugin-import": "^2.22.0",
"firebase-functions-test": "^0.2.0",
"typescript": "^3.8.0"
},
"private": true
}

View File

@@ -0,0 +1,17 @@
import { pubsub, config } from "firebase-functions";
const env = config();
const sgMail = require("@sendgrid/mail");
sgMail.setSubstitutionWrappers("{{", "}}");
if (env.send_grid) sgMail.setApiKey(env.send_grid.key);
const SPARK_TOPIC = "spark_sendgrid";
export const spark_sendgrid = pubsub
.topic(SPARK_TOPIC)
.onPublish(async (message, context) => {
const sparkBody = message.data
? Buffer.from(message.data, "base64").toString("utf-8")
: "{}";
const data = JSON.parse(sparkBody);
const { msg } = data;
sgMail.send(msg);
return true;
});

View File

@@ -0,0 +1,13 @@
{
"compilerOptions": {
"module": "commonjs",
"noImplicitReturns": true,
"noUnusedLocals": true,
"outDir": "lib",
"sourceMap": true,
"strict": true,
"target": "es2017"
},
"compileOnSave": true,
"include": ["src"]
}

File diff suppressed because it is too large Load Diff

66
sparks/slack/.gitignore vendored Normal file
View File

@@ -0,0 +1,66 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
firebase-debug.log*
firebase-debug.*.log*
# Firebase cache
.firebase/
# Firebase config
# Uncomment this if you'd like others to create their own Firebase project.
# For a team working on the same Firebase project(s), it is recommended to leave
# it commented so all members can deploy to the same project(s) in .firebaserc.
# .firebaserc
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env

View File

@@ -0,0 +1,8 @@
{
"functions": {
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint",
"npm --prefix \"$RESOURCE_DIR\" run build"
]
}
}

9
sparks/slack/functions/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
# Compiled JavaScript files
**/*.js
**/*.js.map
# TypeScript v1 declaration files
typings/
# Node.js dependency directory
node_modules/

View File

@@ -0,0 +1,30 @@
{
"name": "functions",
"scripts": {
"lint": "eslint 'src/**/*'",
"build": "tsc",
"serve": "npm run build && firebase emulators:start --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions:spark_slack",
"logs": "firebase functions:log"
},
"engines": {
"node": "10"
},
"main": "lib/index.js",
"dependencies": {
"@slack/web-api": "^5.12.0",
"firebase-admin": "^9.2.0",
"firebase-functions": "^3.6.1"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^3.9.1",
"@typescript-eslint/parser": "^3.8.0",
"eslint": "^7.6.0",
"eslint-plugin-import": "^2.22.0",
"firebase-functions-test": "^0.2.0",
"typescript": "^3.8.0"
},
"private": true
}

View File

@@ -0,0 +1,85 @@
import { pubsub, config } from "firebase-functions";
export const env = config();
import { WebClient } from "@slack/web-api";
const SPARK_TOPIC = "spark_slack";
async function asyncForEach(array: any[], callback: Function) {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
}
const web = new WebClient(env.slackbot ? env.slackbot.token : "NEEDS_CONFIG");
const messageByChannel = async ({
text,
channel,
blocks,
}: {
channel: string;
text: string;
blocks: any[];
}) =>
await web.chat.postMessage({
text,
channel,
blocks,
});
const messageByEmail = async ({
email,
text,
blocks,
}: {
email: string;
text: string;
blocks: any[];
}) => {
try {
const user = await web.users.lookupByEmail({ email });
if (user.ok) {
const channel = (user as any).user.id as string;
return await messageByChannel({
text,
blocks,
channel,
});
} else {
return await false;
}
} catch (error) {
console.log(`${error} maybe${email} is not on slack`);
console.log(`${error}`);
return await false;
}
};
export const spark_slack = pubsub
.topic(SPARK_TOPIC)
.onPublish(async (message, context) => {
const messageBody = message.data
? Buffer.from(message.data, "base64").toString("utf-8")
: "{}";
const data = JSON.parse(messageBody);
const { channels, emails, text, blocks } = data;
if (channels) {
await asyncForEach(channels, async (channel: string) => {
await messageByChannel({
text,
blocks: blocks ?? [],
channel,
});
});
}
if (emails) {
await asyncForEach(emails, async (email: string) => {
await messageByEmail({
text: text,
blocks: blocks ?? [],
email,
});
});
}
return true;
});

View File

@@ -0,0 +1,13 @@
{
"compilerOptions": {
"module": "commonjs",
"noImplicitReturns": true,
"noUnusedLocals": true,
"outDir": "lib",
"sourceMap": true,
"strict": true,
"target": "es2017"
},
"compileOnSave": true,
"include": ["src"]
}

File diff suppressed because it is too large Load Diff