Skip to content

Commit

Permalink
Merge pull request #73 from mailchimp/feature/node-18-support
Browse files Browse the repository at this point in the history
Node 18 runtime testing and configuration.
  • Loading branch information
barticus authored Aug 14, 2023
2 parents 9b920c0 + 4f74eb2 commit 738cf1d
Show file tree
Hide file tree
Showing 5 changed files with 2,318 additions and 1,717 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## Version 0.5.4

- Switch from mailchimp-api-v3 package to @mailchimp/mailchimp_marketing (PR #66)
- Add a configurable retry to allow a higher chance of requests causing transient failures to succeed (PR #69)
- Added linter config and updated packages. (PR #70)
- Node.JS 18 runtime for functions (PR #73)

## Version 0.5.3

- Addressed [breaking change in Google Cloud Functions](https://cloud.google.com/functions/docs/release-notes#April_11_2023) where the build command would run on function deployment (PR #65).
Expand Down
36 changes: 16 additions & 20 deletions extension.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@
# limitations under the License.

name: mailchimp-firebase-sync
version: 0.5.3
version: 0.5.4
specVersion: v1beta

displayName: Manage Marketing with Mailchimp
description:
Syncs user data with a Mailchimp audience for sending personalized email marketing campaigns.
description: Syncs user data with a Mailchimp audience for sending personalized email marketing campaigns.

license: Apache-2.0

Expand Down Expand Up @@ -59,7 +58,7 @@ resources:
then automatically adds the new user to your specified MailChimp audience.
properties:
location: ${LOCATION}
runtime: nodejs16
runtime: nodejs18
eventTrigger:
eventType: providers/firebase.auth/eventTypes/user.create
resource: projects/${PROJECT_ID}
Expand All @@ -72,7 +71,7 @@ resources:
MailChimp audience.
properties:
location: ${LOCATION}
runtime: nodejs16
runtime: nodejs18
eventTrigger:
eventType: providers/firebase.auth/eventTypes/user.delete
resource: projects/${PROJECT_ID}
Expand All @@ -81,11 +80,11 @@ resources:
type: firebaseextensions.v1beta.function
description:
Member Tags provide the ability to associate "metadata" or "labels" with a Mailchimp subscriber.
The memberTagsHandler function listens for Firestore write events based on specified config path,
The memberTagsHandler function listens for Firestore write events based on specified config path,
then automatically classifies the document data as Mailchimp subscriber tags.
properties:
location: ${LOCATION}
runtime: nodejs16
runtime: nodejs18
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${param:PROJECT_ID}/databases/(default)/documents/${param:MAILCHIMP_MEMBER_TAGS_WATCH_PATH}/{documentId}
Expand All @@ -94,11 +93,11 @@ resources:
type: firebaseextensions.v1beta.function
description:
Merge fields provide the ability to create new properties that can be associated with Mailchimp subscriber.
The mergeFieldsHandler function listens for Firestore write events based on specified config path,
The mergeFieldsHandler function listens for Firestore write events based on specified config path,
then automatically populates the Mailchimp subscriber's respective merge fields.
properties:
location: ${LOCATION}
runtime: nodejs16
runtime: nodejs18
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${param:PROJECT_ID}/databases/(default)/documents/${param:MAILCHIMP_MERGE_FIELDS_WATCH_PATH}/{documentId}
Expand All @@ -107,12 +106,12 @@ resources:
type: firebaseextensions.v1beta.function
description:
Member events are Mailchimp specific activity events that can be created and associated with a predefined action.
The memberEventsHandler function Listens for Firestore write events based on specified config path,
then automatically uses the document data to create a Mailchimp event on the subscriber's profile
The memberEventsHandler function Listens for Firestore write events based on specified config path,
then automatically uses the document data to create a Mailchimp event on the subscriber's profile
which can subsequently trigger automation workflows.
properties:
location: ${LOCATION}
runtime: nodejs16
runtime: nodejs18
eventTrigger:
eventType: providers/cloud.firestore/eventTypes/document.write
resource: projects/${param:PROJECT_ID}/databases/(default)/documents/${param:MAILCHIMP_MEMBER_EVENTS_WATCH_PATH}/{documentId}
Expand Down Expand Up @@ -305,17 +304,16 @@ params:
NOTE: To disable this cloud function listener, provide an empty JSON config `{}`.
required: true
default: '{}'
default: "{}"

- param: MAILCHIMP_MERGE_FIELDS_WATCH_PATH
label: Firebase Merge Fields Watch Path
description: The Firestore collection to watch for merge field changes
type: string
example: registrations
default: _unused_
required: true
required: true

- param: MAILCHIMP_MERGE_FIELDS_CONFIG
type: string
Expand All @@ -335,7 +333,7 @@ params:
2) `statusField` - An optional configuration setting for syncing the users mailchimp status. Properties are:
- `documentPath` - (required) The path to the field in the document containing the users status, as a string. The format can be any valid [JMES Path query](https://jmespath.org/). e.g. "status", "meta.status".
- `statusFormat` - (optional) Indicates the format that the status field is. The options are:
- `"string"` - The default, this will sync the value from the status field as is, with no modification.
- `"boolean"` - This will check if the value is truthy (e.g. true, 1, "subscribed"), and if so will resolve the status to "subscribed", otherwise it will resolve to "unsubscribed".
Expand Down Expand Up @@ -418,9 +416,8 @@ params:
NOTE: To disable this cloud function listener, provide an empty JSON config `{}`.
required: true
default: '{}'
default: "{}"

- param: MAILCHIMP_MEMBER_EVENTS_WATCH_PATH
label: Firebase Member Events Watch Path
Expand Down Expand Up @@ -513,6 +510,5 @@ params:
NOTE: To disable this cloud function listener, provide an empty JSON config `{}`.
required: true
default: '{}'
default: "{}"
32 changes: 16 additions & 16 deletions functions/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const crypto = require("crypto");
const _ = require("lodash");
const functions = require("firebase-functions");
const { auth, firestore, logger } = require("firebase-functions");
const admin = require("firebase-admin");
const mailchimp = require("@mailchimp/mailchimp_marketing");
const jmespath = require("jmespath");
Expand All @@ -25,7 +25,7 @@ function processConfig(configInput) {
// (tags, merge fields, custom events) at the root.
config = Object.entries(configInput).reduce((acc, [key, value]) => {
const logError = (message) => {
functions.logger.log(message, key, value);
logger.log(message, key, value);
return acc;
};
if (configInput[key] && Object.keys(CONFIG_PARAMS).includes(key)) {
Expand Down Expand Up @@ -180,7 +180,7 @@ function errorFilterFor404(err) {
return err?.status === 404;
}

exports.addUserToList = functions.handler.auth.user.onCreate(
exports.addUserToList = auth.user().onCreate(
async (user) => {
logs.start();

Expand Down Expand Up @@ -221,7 +221,7 @@ exports.addUserToList = functions.handler.auth.user.onCreate(
},
);

exports.removeUserFromList = functions.handler.auth.user.onDelete(
exports.removeUserFromList = auth.user().onDelete(
async (user) => {
logs.start();

Expand Down Expand Up @@ -256,7 +256,7 @@ exports.removeUserFromList = functions.handler.auth.user.onDelete(
},
);

exports.memberTagsHandler = functions.handler.firestore.document
exports.memberTagsHandler = firestore.document(config.mailchimpMemberTagsWatchPath)
.onWrite(async (event) => {
// If an empty JSON configuration was provided then consider function as NO-OP
if (_.isEmpty(config.mailchimpMemberTags)) return;
Expand All @@ -271,11 +271,11 @@ exports.memberTagsHandler = functions.handler.firestore.document
return;
}
if (!tagsConfig.memberTags) {
functions.logger.log(`A property named 'memberTags' is required`);
logger.log(`A property named 'memberTags' is required`);
return;
}
if (!Array.isArray(tagsConfig.memberTags)) {
functions.logger.log("\"memberTags\" must be an array");
logger.log("\"memberTags\" must be an array");
return;
}

Expand Down Expand Up @@ -320,11 +320,11 @@ exports.memberTagsHandler = functions.handler.firestore.document
), errorFilterFor404);
}
} catch (e) {
functions.logger.log(e);
logger.log(e);
}
});

exports.mergeFieldsHandler = functions.handler.firestore.document
exports.mergeFieldsHandler = firestore.document(config.mailchimpMergeFieldWatchPath)
.onWrite(async (event) => {
// If an empty JSON configuration was provided then consider function as NO-OP
if (_.isEmpty(config.mailchimpMergeField)) return;
Expand All @@ -339,11 +339,11 @@ exports.mergeFieldsHandler = functions.handler.firestore.document
return;
}
if (!mergeFieldsConfig.mergeFields || _.isEmpty(mergeFieldsConfig.mergeFields)) {
functions.logger.log(`A property named 'mergeFields' is required`);
logger.log(`A property named 'mergeFields' is required`);
return;
}
if (!_.isObject(mergeFieldsConfig.mergeFields)) {
functions.logger.log("Merge Fields config must be an object");
logger.log("Merge Fields config must be an object");
return;
}

Expand Down Expand Up @@ -410,11 +410,11 @@ exports.mergeFieldsHandler = functions.handler.firestore.document
), errorFilterFor404);
}
} catch (e) {
functions.logger.log(e);
logger.log(e);
}
});

exports.memberEventsHandler = functions.handler.firestore.document
exports.memberEventsHandler = firestore.document(config.mailchimpMemberEventsWatchPath)
.onWrite(async (event) => {
// If an empty JSON configuration was provided then consider function as NO-OP
if (_.isEmpty(config.mailchimpMemberEvents)) return;
Expand All @@ -429,11 +429,11 @@ exports.memberEventsHandler = functions.handler.firestore.document
return;
}
if (!eventsConfig.memberEvents) {
functions.logger.log(`A property named 'memberEvents' is required`);
logger.log(`A property named 'memberEvents' is required`);
return;
}
if (!Array.isArray(eventsConfig.memberEvents)) {
functions.logger.log(`'memberEvents' property must be an array`);
logger.log(`'memberEvents' property must be an array`);
return;
}

Expand Down Expand Up @@ -482,7 +482,7 @@ exports.memberEventsHandler = functions.handler.firestore.document
await Promise.all(requests);
}
} catch (e) {
functions.logger.log(e);
logger.log(e);
}
});

Expand Down
Loading

0 comments on commit 738cf1d

Please sign in to comment.