@shopify/koa-shopify-webhooks
Advanced tools
Comparing version 5.0.6 to 5.1.0
@@ -5,2 +5,3 @@ 'use strict'; | ||
var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js'); | ||
var crypto = require('crypto'); | ||
@@ -21,37 +22,57 @@ var safeCompare = require('safe-compare'); | ||
function receiveWebhook({ | ||
secret, | ||
path, | ||
onReceived = noop | ||
}) { | ||
async function receiveWebhookMiddleware(ctx, next) { | ||
const hmac = ctx.get(types.WebhookHeader.Hmac); | ||
const topic = ctx.get(types.WebhookHeader.Topic); | ||
const domain = ctx.get(types.WebhookHeader.Domain); | ||
const { | ||
rawBody | ||
} = ctx.request; | ||
const generatedHash = crypto.createHmac('sha256', secret).update(rawBody, 'utf8').digest('base64'); | ||
const graphqlTopic = topic.toUpperCase().replace(/\//g, '_'); | ||
if (safeCompare__default["default"](generatedHash, hmac)) { | ||
ctx.res.statusCode = network.StatusCode.Accepted; | ||
ctx.state.webhook = { | ||
topic: graphqlTopic, | ||
domain, | ||
payload: JSON.parse(rawBody) | ||
}; | ||
await onReceived(ctx); | ||
await next(); | ||
} else { | ||
ctx.res.statusCode = network.StatusCode.Unauthorized; | ||
} | ||
function receiveWebhook(_ref) { | ||
var secret = _ref.secret, | ||
path = _ref.path, | ||
_ref$onReceived = _ref.onReceived, | ||
onReceived = _ref$onReceived === void 0 ? noop : _ref$onReceived; | ||
function receiveWebhookMiddleware(_x, _x2) { | ||
return _receiveWebhookMiddleware.apply(this, arguments); | ||
} | ||
const middleware = compose__default["default"]([bodyParser__default["default"](), receiveWebhookMiddleware]); | ||
function _receiveWebhookMiddleware() { | ||
_receiveWebhookMiddleware = _rollupPluginBabelHelpers.asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(ctx, next) { | ||
var hmac, topic, domain, rawBody, generatedHash, graphqlTopic; | ||
return regeneratorRuntime.wrap(function _callee$(_context) { | ||
while (1) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
hmac = ctx.get(types.WebhookHeader.Hmac); | ||
topic = ctx.get(types.WebhookHeader.Topic); | ||
domain = ctx.get(types.WebhookHeader.Domain); | ||
rawBody = ctx.request.rawBody; | ||
generatedHash = crypto.createHmac('sha256', secret).update(rawBody, 'utf8').digest('base64'); | ||
graphqlTopic = topic.toUpperCase().replace(/\//g, '_'); | ||
if (!safeCompare__default["default"](generatedHash, hmac)) { | ||
_context.next = 15; | ||
break; | ||
} | ||
ctx.res.statusCode = network.StatusCode.Accepted; | ||
ctx.state.webhook = { | ||
topic: graphqlTopic, | ||
domain: domain, | ||
payload: JSON.parse(rawBody) | ||
}; | ||
_context.next = 11; | ||
return onReceived(ctx); | ||
case 11: | ||
_context.next = 13; | ||
return next(); | ||
case 13: | ||
_context.next = 16; | ||
break; | ||
case 15: | ||
ctx.res.statusCode = network.StatusCode.Unauthorized; | ||
case 16: | ||
case "end": | ||
return _context.stop(); | ||
} | ||
} | ||
}, _callee); | ||
})); | ||
return _receiveWebhookMiddleware.apply(this, arguments); | ||
} | ||
var middleware = compose__default["default"]([bodyParser__default["default"](), receiveWebhookMiddleware]); | ||
return path ? mount__default["default"](path, middleware) : middleware; | ||
} | ||
function noop() {} | ||
exports.receiveWebhook = receiveWebhook; |
@@ -5,2 +5,3 @@ 'use strict'; | ||
var _rollupPluginBabelHelpers = require('./_virtual/_rollupPluginBabelHelpers.js'); | ||
var network = require('@shopify/network'); | ||
@@ -10,3 +11,2 @@ var types = require('./types.js'); | ||
exports.DeliveryMethod = void 0; | ||
(function (DeliveryMethod) { | ||
@@ -16,27 +16,39 @@ DeliveryMethod["Http"] = "http"; | ||
})(exports.DeliveryMethod || (exports.DeliveryMethod = {})); | ||
async function registerWebhook({ | ||
address, | ||
topic, | ||
accessToken, | ||
shop, | ||
apiVersion, | ||
includeFields, | ||
deliveryMethod = exports.DeliveryMethod.Http | ||
}) { | ||
const response = await fetch(`https://${shop}/admin/api/${apiVersion}/graphql.json`, { | ||
method: network.Method.Post, | ||
body: buildQuery(topic, address, deliveryMethod, includeFields), | ||
headers: { | ||
[types.WebhookHeader.AccessToken]: accessToken, | ||
[network.Header.ContentType]: 'application/graphql' | ||
} | ||
}); | ||
const result = await response.json(); | ||
return { | ||
success: isSuccess(result, deliveryMethod), | ||
result | ||
}; | ||
function registerWebhook(_x) { | ||
return _registerWebhook.apply(this, arguments); | ||
} | ||
function _registerWebhook() { | ||
_registerWebhook = _rollupPluginBabelHelpers.asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(_ref) { | ||
var _headers; | ||
var address, topic, accessToken, shop, apiVersion, includeFields, _ref$deliveryMethod, deliveryMethod, response, result; | ||
return regeneratorRuntime.wrap(function _callee$(_context) { | ||
while (1) { | ||
switch (_context.prev = _context.next) { | ||
case 0: | ||
address = _ref.address, topic = _ref.topic, accessToken = _ref.accessToken, shop = _ref.shop, apiVersion = _ref.apiVersion, includeFields = _ref.includeFields, _ref$deliveryMethod = _ref.deliveryMethod, deliveryMethod = _ref$deliveryMethod === void 0 ? exports.DeliveryMethod.Http : _ref$deliveryMethod; | ||
_context.next = 3; | ||
return fetch("https://".concat(shop, "/admin/api/").concat(apiVersion, "/graphql.json"), { | ||
method: network.Method.Post, | ||
body: buildQuery(topic, address, deliveryMethod, includeFields), | ||
headers: (_headers = {}, _rollupPluginBabelHelpers.defineProperty(_headers, types.WebhookHeader.AccessToken, accessToken), _rollupPluginBabelHelpers.defineProperty(_headers, network.Header.ContentType, 'application/graphql'), _headers) | ||
}); | ||
case 3: | ||
response = _context.sent; | ||
_context.next = 6; | ||
return response.json(); | ||
case 6: | ||
result = _context.sent; | ||
return _context.abrupt("return", { | ||
success: isSuccess(result, deliveryMethod), | ||
result: result | ||
}); | ||
case 8: | ||
case "end": | ||
return _context.stop(); | ||
} | ||
} | ||
}, _callee); | ||
})); | ||
return _registerWebhook.apply(this, arguments); | ||
} | ||
function isSuccess(result, deliveryMethod) { | ||
@@ -46,3 +58,2 @@ switch (deliveryMethod) { | ||
return Boolean(result.data && result.data.webhookSubscriptionCreate && result.data.webhookSubscriptionCreate.webhookSubscription); | ||
case exports.DeliveryMethod.EventBridge: | ||
@@ -52,14 +63,19 @@ return Boolean(result.data && result.data.eventBridgeWebhookSubscriptionCreate && result.data.eventBridgeWebhookSubscriptionCreate.webhookSubscription); | ||
} | ||
function buildArgs(args) { | ||
const formattedArgs = Object.entries(args).filter(([_key, value]) => typeof value !== 'undefined').map(([key, value]) => { | ||
return `${key}: ${JSON.stringify(value)}`; | ||
var formattedArgs = Object.entries(args).filter(function (_ref2) { | ||
var _ref3 = _rollupPluginBabelHelpers.slicedToArray(_ref2, 2); | ||
_ref3[0]; | ||
var value = _ref3[1]; | ||
return typeof value !== 'undefined'; | ||
}).map(function (_ref4) { | ||
var _ref5 = _rollupPluginBabelHelpers.slicedToArray(_ref4, 2), | ||
key = _ref5[0], | ||
value = _ref5[1]; | ||
return "".concat(key, ": ").concat(JSON.stringify(value)); | ||
}); | ||
return `{${formattedArgs.join(', ')}}`; | ||
return "{".concat(formattedArgs.join(', '), "}"); | ||
} | ||
function buildQuery(topic, address, deliveryMethod, includeFields) { | ||
let mutationName; | ||
let webhookSubscriptionArgs; | ||
var mutationName; | ||
var webhookSubscriptionArgs; | ||
switch (deliveryMethod) { | ||
@@ -70,6 +86,5 @@ case exports.DeliveryMethod.Http: | ||
callbackUrl: address, | ||
includeFields | ||
includeFields: includeFields | ||
}); | ||
break; | ||
case exports.DeliveryMethod.EventBridge: | ||
@@ -79,22 +94,9 @@ mutationName = 'eventBridgeWebhookSubscriptionCreate'; | ||
arn: address, | ||
includeFields | ||
includeFields: includeFields | ||
}); | ||
break; | ||
} | ||
return ` | ||
mutation webhookSubscriptionCreate { | ||
${mutationName}(topic: ${topic}, webhookSubscription: ${webhookSubscriptionArgs}) { | ||
userErrors { | ||
field | ||
message | ||
} | ||
webhookSubscription { | ||
id | ||
} | ||
} | ||
} | ||
`; | ||
return "\n mutation webhookSubscriptionCreate {\n ".concat(mutationName, "(topic: ").concat(topic, ", webhookSubscription: ").concat(webhookSubscriptionArgs, ") {\n userErrors {\n field\n message\n }\n webhookSubscription {\n id\n }\n }\n }\n "); | ||
} | ||
exports.registerWebhook = registerWebhook; |
@@ -6,3 +6,2 @@ 'use strict'; | ||
exports.WebhookHeader = void 0; | ||
(function (WebhookHeader) { | ||
@@ -9,0 +8,0 @@ WebhookHeader["AccessToken"] = "X-Shopify-Access-Token"; |
{ | ||
"name": "@shopify/koa-shopify-webhooks", | ||
"version": "5.0.6", | ||
"version": "5.1.0", | ||
"license": "MIT", | ||
@@ -24,6 +24,6 @@ "description": "Receive webhooks from Shopify with ease", | ||
"engines": { | ||
"node": "^14.17.0 || >=16.0.0" | ||
"node": ">=18.12.0" | ||
}, | ||
"dependencies": { | ||
"@shopify/network": "^3.2.1", | ||
"@shopify/network": "^3.3.0", | ||
"@types/koa": "^2.0.0", | ||
@@ -36,3 +36,3 @@ "koa-bodyparser": ">=4.0.0 <5.0.0", | ||
"devDependencies": { | ||
"@shopify/jest-dom-mocks": "^4.1.2", | ||
"@shopify/jest-dom-mocks": "^5.1.0", | ||
"@types/koa-bodyparser": "*", | ||
@@ -39,0 +39,0 @@ "@types/koa-compose": "*" |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
37880
27
591
Updated@shopify/network@^3.3.0