From 4cc72afd8fc5264d842c48267c64fc033ce299c3 Mon Sep 17 00:00:00 2001 From: Dominik Kadera Date: Wed, 6 Nov 2019 15:53:29 +0100 Subject: [PATCH] Zapier No Longer Available --- bin/ZapierImporter.mjs | 17 -- bin/ZapierImporter/Builder.mjs | 272 ------------------ bin/ZapierImporter/ParseError.mjs | 9 - bin/ZapierImporter/Parser.mjs | 187 ------------ bin/ZapierImporter/common.mjs | 60 ---- .../subparsers/ParseFunctions.mjs | 106 ------- .../subparsers/connections/ApiKeyHeaders.mjs | 60 ---- .../subparsers/connections/ApiKeyQS.mjs | 59 ---- .../subparsers/connections/BasicAuth.mjs | 47 --- .../subparsers/connections/OAuth1.mjs | 153 ---------- .../subparsers/connections/OAuth2.mjs | 135 --------- .../subparsers/connections/OAuth2REF.mjs | 169 ----------- .../subparsers/modules/Action.mjs | 62 ---- .../subparsers/modules/InstantTrigger.mjs | 20 -- bin/ZapierImporter/subparsers/modules/RPC.mjs | 74 ----- .../subparsers/modules/Search.mjs | 62 ---- .../subparsers/modules/Trigger.mjs | 60 ---- .../subparsers/modules/Webhook.mjs | 36 --- bin/ZapierImporter/updash/camelCase.mjs | 36 --- bin/ZapierImporter/updash/kebabCase.mjs | 14 - html/loggedIn.html | 4 +- html/zapierImport.html | 50 ---- html/zapierImport.mjs | 235 --------------- html/zapierLogin.html | 34 --- html/zapierLogin.mjs | 13 - html/zapierNotOn.html | 11 +- html/zapierNotOn.mjs | 9 - index.mjs | 18 +- manifest.json | 3 +- 29 files changed, 10 insertions(+), 2005 deletions(-) delete mode 100644 bin/ZapierImporter.mjs delete mode 100644 bin/ZapierImporter/Builder.mjs delete mode 100644 bin/ZapierImporter/ParseError.mjs delete mode 100644 bin/ZapierImporter/Parser.mjs delete mode 100644 bin/ZapierImporter/common.mjs delete mode 100644 bin/ZapierImporter/subparsers/ParseFunctions.mjs delete mode 100644 bin/ZapierImporter/subparsers/connections/ApiKeyHeaders.mjs delete mode 100644 bin/ZapierImporter/subparsers/connections/ApiKeyQS.mjs delete mode 100644 bin/ZapierImporter/subparsers/connections/BasicAuth.mjs delete mode 100644 bin/ZapierImporter/subparsers/connections/OAuth1.mjs delete mode 100644 bin/ZapierImporter/subparsers/connections/OAuth2.mjs delete mode 100644 bin/ZapierImporter/subparsers/connections/OAuth2REF.mjs delete mode 100644 bin/ZapierImporter/subparsers/modules/Action.mjs delete mode 100644 bin/ZapierImporter/subparsers/modules/InstantTrigger.mjs delete mode 100644 bin/ZapierImporter/subparsers/modules/RPC.mjs delete mode 100644 bin/ZapierImporter/subparsers/modules/Search.mjs delete mode 100644 bin/ZapierImporter/subparsers/modules/Trigger.mjs delete mode 100644 bin/ZapierImporter/subparsers/modules/Webhook.mjs delete mode 100644 bin/ZapierImporter/updash/camelCase.mjs delete mode 100644 bin/ZapierImporter/updash/kebabCase.mjs delete mode 100644 html/zapierImport.html delete mode 100644 html/zapierImport.mjs delete mode 100644 html/zapierLogin.html delete mode 100644 html/zapierLogin.mjs diff --git a/bin/ZapierImporter.mjs b/bin/ZapierImporter.mjs deleted file mode 100644 index 6b3958a..0000000 --- a/bin/ZapierImporter.mjs +++ /dev/null @@ -1,17 +0,0 @@ -import Parser from './ZapierImporter/Parser.mjs'; -import Builder from './ZapierImporter/Builder.mjs'; - -export default { - - parseSource: (raw) => { - return Builder.buildRequestTree(Parser.parseApp(raw)); - }, - - parseRaw: (raw) => { - return Parser.parseApp(raw); - }, - - buildRequests: (raw) => { - return Builder.buildRequestTree(raw); - } -}; diff --git a/bin/ZapierImporter/Builder.mjs b/bin/ZapierImporter/Builder.mjs deleted file mode 100644 index 6402898..0000000 --- a/bin/ZapierImporter/Builder.mjs +++ /dev/null @@ -1,272 +0,0 @@ -export default { - buildRequestTree(app) { - const version = 1; - const requests = []; - const errors = app.errors; - - // New app - console.debug('/app'); - const preflight = { - endpoint: '/app', - method: 'POST', - type: 'application/json', - body: { - name: app.name, - version: version, - label: app.label, - theme: app.theme, - language: 'en', - private: true, - countries: [] - } - }; - - // App base - console.debug('/app/base'); - requests.push({ - endpoint: `/${version}/base`, - method: 'PUT', - type: 'application/jsonc', - body: app.base - }); - - // CONNECTIONS - console.debug('/app/connections'); - for (const connection of app.connections) { - - // New connection - requests.push({ - endpoint: `/connection`, - method: 'POST', - flag: 'NEW_FLAG', - type: 'application/json', - body: { - type: connection.type, - label: connection.label - } - }); - - // Parameters - requests.push({ - endpoint: `/connection/___FLAG_NAME___/parameters`, - method: 'PUT', - flag: 'FLAG', - type: 'application/jsonc', - body: connection.parameters - }); - - // Api - requests.push({ - endpoint: `/connection/___FLAG_NAME___/api`, - method: 'PUT', - flag: 'FLAG', - type: 'application/jsonc', - body: connection.api - }); - - // Common - requests.push({ - endpoint: `/connection/___FLAG_NAME___/common`, - method: 'PUT', - flag: 'FLAG', - type: 'application/json', - body: connection.common - }); - - // Scope - requests.push({ - endpoint: `/connection/___FLAG_NAME___/scope`, - method: 'PUT', - flag: 'FLAG', - type: 'application/json', - body: connection.scope - }); - - // Scopes - requests.push({ - endpoint: `/connection/___FLAG_NAME___/scopes`, - method: 'PUT', - flag: 'FLAG', - type: 'application/json', - body: connection.scopes - }); - } - - // RPCs - console.debug('/app/rpcs'); - for (const rpc of app.rpcs) { - - // New RPC - console.debug(`/app/rpcs/${rpc.name}`); - requests.push({ - endpoint: `/${version}/rpc`, - method: 'POST', - type: 'application/json', - body: { - name: rpc.name, - label: rpc.label, - connection: rpc.connection - } - }); - - // Api - requests.push({ - endpoint: `/${version}/rpc/${rpc.name}/api`, - method: 'PUT', - type: 'application/jsonc', - body: rpc.api - }); - - // Parameters - requests.push({ - endpoint: `/${version}/rpc/${rpc.name}/parameters`, - method: 'PUT', - type: 'application/jsonc', - body: rpc.parameters - }); - - } - - // WEBHOOKS - console.debug('/app/webhooks'); - for (const hook of app.webhooks) { - - // New webhook - requests.push({ - endpoint: `/webhook`, - method: 'POST', - type: 'application/json', - flag: 'NEW_FLAG', - body: { - name: hook.name, - type: hook.type, - label: hook.label, - connection: hook.connection - } - }); - - // Parameters - requests.push({ - endpoint: `/webhook/___FLAG_NAME___/parameters`, - method: 'PUT', - flag: 'FLAG', - type: 'application/jsonc', - body: hook.parameters - }); - - // Api - requests.push({ - endpoint: `/webhook/___FLAG_NAME___/api`, - method: 'PUT', - flag: 'FLAG', - type: 'application/jsonc', - body: hook.api - }); - - // Attach - requests.push({ - endpoint: `/webhook/___FLAG_NAME___/attach`, - method: 'PUT', - flag: 'FLAG', - type: 'application/jsonc', - body: hook.attach - }); - - // Detach - requests.push({ - endpoint: `/webhook/___FLAG_NAME___/detach`, - method: 'PUT', - flag: 'FLAG', - type: 'application/jsonc', - body: hook.detach - }); - } - - // MODULES - console.debug('/app/modules'); - for (const module of app.modules) { - - // New module - console.debug(`/app/modules/${module.name}`); - requests.push({ - endpoint: `/${version}/module`, - method: 'POST', - type: 'application/json', - body: { - name: module.name, - type_id: module.type_id, - label: module.label, - description: module.description, - connection: module.connection, - webhook: module.webhook - } - }); - - // Api - requests.push({ - endpoint: `/${version}/module/${module.name}/api`, - method: 'PUT', - type: 'application/jsonc', - body: module.api || {} - }); - - // Epoch - if (module.type_id === 1) { - requests.push({ - endpoint: `/${version}/module/${module.name}/epoch`, - method: 'PUT', - type: 'application/jsonc', - body: module.epoch || {} - }); - } - - // Parameters - requests.push({ - endpoint: `/${version}/module/${module.name}/parameters`, - method: 'PUT', - type: 'application/jsonc', - body: module.parameters || [] - }); - - // Expect - if ([4, 9].includes(module.type_id)) { - requests.push({ - endpoint: `/${version}/module/${module.name}/expect`, - method: 'PUT', - type: 'application/jsonc', - body: module.expect || [] - }); - } - - // Interface - requests.push({ - endpoint: `/${version}/module/${module.name}/interface`, - method: 'PUT', - type: 'application/jsonc', - body: module.interface || [] - }); - - // Samples - requests.push({ - endpoint: `/${version}/module/${module.name}/samples`, - method: 'PUT', - type: 'application/json', - body: module.samples || {} - }); - - // Scope - requests.push({ - endpoint: `/${version}/module/${module.name}/scope`, - method: 'PUT', - type: 'application/json', - body: module.scope || [] - }); - } - - return { - preflight: preflight, - requests: requests, - errors: errors - }; - } -}; diff --git a/bin/ZapierImporter/ParseError.mjs b/bin/ZapierImporter/ParseError.mjs deleted file mode 100644 index 82597d3..0000000 --- a/bin/ZapierImporter/ParseError.mjs +++ /dev/null @@ -1,9 +0,0 @@ -class ParseError { - constructor(code, description, severity) { - this.code = code; - this.description = description; - this.severity = severity; - } -} - -export default ParseError; diff --git a/bin/ZapierImporter/Parser.mjs b/bin/ZapierImporter/Parser.mjs deleted file mode 100644 index 444ad67..0000000 --- a/bin/ZapierImporter/Parser.mjs +++ /dev/null @@ -1,187 +0,0 @@ -import kebabCase from './updash/kebabCase.mjs'; - -import { getColorCode, getRandomInt } from './common.mjs'; -import ParseError from './ParseError.mjs'; - -import BasicAuth from './subparsers/connections/BasicAuth.mjs'; -import ApiKeyQS from './subparsers/connections/ApiKeyQS.mjs'; -import ApiKeyHeaders from './subparsers/connections/ApiKeyHeaders.mjs'; -import OAuth1 from './subparsers/connections/OAuth1.mjs'; -import OAuth2 from './subparsers/connections/OAuth2.mjs'; -import OAuth2REF from './subparsers/connections/OAuth2REF.mjs'; - -import Action from './subparsers/modules/Action.mjs'; -import Search from './subparsers/modules/Search.mjs'; -import RPC from './subparsers/modules/RPC.mjs'; -import Trigger from './subparsers/modules/Trigger.mjs'; -import InstantTrigger from './subparsers/modules/InstantTrigger.mjs'; -import Webhook from './subparsers/modules/Webhook.mjs'; - -class Parser { - - static parseApp(raw) { - const app = {}; - app.countries = []; - app.private = true; - app.language = 'en'; - app.theme = getColorCode(getRandomInt(128, 255), getRandomInt(128, 255), getRandomInt(128, 255)); - app.label = raw.title; - app.name = raw.slug || kebabCase(raw.title); - app.errors = []; - /** - * PARSE MODULES - */ - app.base = {}; - app.connections = []; - app.rpcs = []; - app.webhooks = []; - app.modules = []; - - if (raw.js !== null) { - app.errors.push(new ParseError( - 'app/using-custom-js', - 'The app is using custom scripting. Sadly, this is unimportable feature and the code has to be imported manually.', - 6 - )); - } - - console.debug('Parsing connection'); - - if (raw.test_trigger === null) { - app.errors.push(new ParseError( - 'connection/no-info', - 'Connection test was not found. That means there\'s no way how to validate the connection. Info request should be added.', - 3 - )); - } - - switch (raw.auth_type) { - - // No Auth - case 0: - console.debug('App has no connection specified.'); - break; - - // Basic Auth - case 1: - console.debug('Recognized "Basic Auth" connection type.'); - app.connections.push(BasicAuth.parse(raw, app)); - break; - - // API key in QueryString - case 2: - console.debug('Recognized "API key in QueryString" connection type.'); - app.connections.push(ApiKeyQS.parse(raw, app)); - break; - - // API key in headers - case 3: - console.debug('Recognized "API key in headers" connection type.'); - app.connections.push(ApiKeyHeaders.parse(raw, app)); - break; - - // OAuth 1 - case 4: - console.debug('Recognized "OAuth1" connection type.'); - app.connections.push(OAuth1.parse(raw, app)); - break; - - // OAuth 2 without refresh token - case 5: - console.debug('Recognized "OAuth2 without refresh token" connection type.'); - app.connections.push(OAuth2.parse(raw, app)); - break; - - // OAuth 2 with refresh token - case 6: - console.debug('Recognized "OAuth2 with refresh token" connection type.'); - app.connections.push(OAuth2REF.parse(raw, app)); - break; - - // Digest auth - case 7: - app.errors.push(new ParseError( - 'connection/digest/not-supported', - 'Digest auth connection type is supported, however it can\'t be imported directly.', - 5 - )); - break; - - // Session Auth - case 9: - app.errors.push(new ParseError( - 'connection/session/not-supported', - 'Session auth connection type is currently not supported.', - 6 - )); - break; - - default: - app.errors.push(new ParseError( - 'connection/unknown', - 'Unknown connection type detected.', - 6 - )); - break; - - } - - const triggers = raw.triggers.filter(trigger => { - return trigger.hide === false; - }); - const rpcs = raw.triggers.filter(rpc => { - return rpc.hide === true; - }); - - let metaWebhooksCount = 0; - - console.debug(`Found ${rpcs.length} RPCs. Parsing.`); - rpcs.forEach(source => { - app.rpcs.push(RPC.parse(source, app, raw)); - }); - - console.debug(`Found ${triggers.length} triggers. Parsing.`); - triggers.forEach(source => { - - if (source.paging !== false) { - app.errors.push(new ParseError( - 'trigger/paging', - `The trigger ${source.label} is using pagination. This has to be implemented manually.`, - 4 - )); - } - - switch (source.source) { - - // Trigger - case 'polling': - app.modules.push(Trigger.parse(source, app)); - break; - - // Instant trigger + webhook - case 'static-webhooks': - case 'payload-subscriptions': - case 'notification-subscriptions': - const webhook = Webhook.parse(source, app, raw, metaWebhooksCount); - metaWebhooksCount++; - app.webhooks.push(webhook); - app.modules.push(InstantTrigger.parse(source, webhook.name)); - break; - } - }); - - console.debug(`Found ${raw.searches.length} searches. Parsing.`); - raw.searches.forEach(source => { - app.modules.push(Search.parse(source, app)); - }); - - console.debug(`Found ${raw.actions.length} actions. Parsing.`); - raw.actions.forEach(source => { - app.modules.push(Action.parse(source, app)); - }); - - return app; - } -} - -export default Parser; diff --git a/bin/ZapierImporter/common.mjs b/bin/ZapierImporter/common.mjs deleted file mode 100644 index 35dabeb..0000000 --- a/bin/ZapierImporter/common.mjs +++ /dev/null @@ -1,60 +0,0 @@ -function objectify(array, key) { - const output = {}; - array.forEach(item => { - output[item[key]] = item; - }); - return output; -} - -function unmoustache(str) { - return str.substring( - str.lastIndexOf('{{') + 2, - str.lastIndexOf('}}') - ); -} - -function paramBuilder(parameters, url) { - const out = {}; - parameters.forEach(parameter => { - if (!url.includes(`{{parameters.${parameter.name}}}`)) { - out[parameter.name] = `{{parameters.${parameter.name}}}`; - } - }); - return out; -} - -function getRandomInt(min, max) { - min = Math.ceil(min); - max = Math.floor(max); - return Math.floor(Math.random() * (max - min + 1)) + min; -} - -function getColorCode(r, g, b) { - return `#${r.toString(16)}${g.toString(16)}${b.toString(16)}`; -} - -function expandUrl(url) { - if (url) { - return url.replace(new RegExp('{{', 'g'), '{{parameters.'); - } else { - return ''; - } -} - -function isEmpty(object) { - return (object && Object.keys(object).length === 0 && object.constructor === Object); -} - -function reorder(object, keys) { - let output = {}; - keys.forEach(key => { - if (object[key]) { - const buff = {}; - buff[key] = object[key]; - output = Object.assign(buff, output); - } - }) - return output -} - -export { objectify, unmoustache, paramBuilder, getRandomInt, getColorCode, expandUrl, isEmpty, reorder }; diff --git a/bin/ZapierImporter/subparsers/ParseFunctions.mjs b/bin/ZapierImporter/subparsers/ParseFunctions.mjs deleted file mode 100644 index 436d55c..0000000 --- a/bin/ZapierImporter/subparsers/ParseFunctions.mjs +++ /dev/null @@ -1,106 +0,0 @@ -import camelCase from '../updash/camelCase.mjs'; - -export default { - parseZapierParameters(raw) { - return raw.map(source => { - const parameter = {}; - switch (source.type_of) { - case 'int': - parameter.type = 'integer'; - break; - case 'bool': - parameter.type = 'boolean'; - break; - case 'unicode': - if (!source.choices) { - parameter.type = 'text'; - } else { - parameter.type = 'select'; - parameter.options = this.parseZapierOptions(source.choices); - if (source.list === true) { - parameter.multiple = true; - } - } - break; - case 'text': - parameter.type = 'text'; - parameter.multiline = true; - break; - case 'float': - parameter.type = 'number'; - break; - case 'datetime': - parameter.type = 'date'; - break; - case 'dict': - parameter.type = 'collection'; - break; - case 'file': - parameter.type = 'file'; - break; - case 'password': - parameter.type = 'password'; - break; - } - parameter.name = source.key; - parameter.label = source.label; - parameter.required = source.required; - if (source.help_text != null) { - parameter.help = source.help_text; - } - if (source.default != null) { - parameter.default = source.default; - } - if (source.prefill != null) { - parameter.type = 'select'; - parameter.options = `rpc://${camelCase(source.prefill.split('.')[0])}`; - } - return parameter; - }); - }, - parseZapierOptions(raw) { - raw = raw.split(','); - return raw.map(source => { - const lv = source.split('|'); - return { - label: lv[1], - value: lv[0] - }; - }); - - }, - parseZapierInterface(raw) { - return raw.map(source => { - const item = {}; - item.name = source.key; - switch (source.type) { - case 'int': - item.type = 'integer'; - break; - case 'bool': - item.type = 'boolean'; - break; - case 'unicode': - case 'text': - item.type = 'text'; - break; - case 'float': - item.type = 'number'; - break; - case 'datetime': - item.type = 'date'; - break; - case 'dict': - item.type = 'collection'; - break; - case 'file': - item.type = 'file'; - break; - case 'password': - item.type = 'password'; - break; - } - return item; - }); - } -}; diff --git a/bin/ZapierImporter/subparsers/connections/ApiKeyHeaders.mjs b/bin/ZapierImporter/subparsers/connections/ApiKeyHeaders.mjs deleted file mode 100644 index ecbcaf1..0000000 --- a/bin/ZapierImporter/subparsers/connections/ApiKeyHeaders.mjs +++ /dev/null @@ -1,60 +0,0 @@ -import { unmoustache, expandUrl, reorder } from '../../common.mjs'; -import ParseFunctions from '../ParseFunctions.mjs'; -import ParseError from '../../ParseError.mjs'; - -export default { - parse(raw, app) { - const connection = {}; - connection.type = 'apikey'; - connection.label = `${raw.title}`; - connection.name = app.name; - connection.parameters = ParseFunctions.parseZapierParameters(raw.auth_fields); - connection.common = {}; - connection.scope = []; - connection.scopes = {}; - - let authorizationKey = null; - if (raw.auth_mapping.Authorization != null) { - authorizationKey = 'Authorization'; - } else { - app.errors.push(new ParseError( - 'connection/api-key/header-not-found', - `Connection Authorization header was not found. Authorization template may be incorrect.`, - 3 - )); - authorizationKey = Object.keys(raw.auth_mapping)[0]; - } - const authorizationValue = unmoustache(raw.auth_mapping[authorizationKey]); - - const headers = {}; - headers[authorizationKey] = `${raw.auth_mapping[authorizationKey].split('{{')[0]}{{parameters.${authorizationValue}}}`; - - if (raw.test_trigger != null) { - const testTrigger = raw.triggers.find(trigger => { - return trigger.id === raw.test_trigger; - }); - connection.api = { - url: `${expandUrl(testTrigger.url)}`, - headers: headers, - log: { - sanitize: [`request.headers.${authorizationKey}`] - } - }; - } else { - connection.api = {}; - } - - connection.api = reorder(connection.api, ['log', 'headers', 'url']); - - headers[authorizationKey] = `${raw.auth_mapping[authorizationKey].split('{{')[0]}{{connection.${authorizationValue}}}`; - - app.base.headers = headers; - app.base.log = { - sanitize: [`request.headers.${authorizationKey}`] - }; - - app.base = reorder(app.base, ['log', 'headers']) - - return connection; - } -}; diff --git a/bin/ZapierImporter/subparsers/connections/ApiKeyQS.mjs b/bin/ZapierImporter/subparsers/connections/ApiKeyQS.mjs deleted file mode 100644 index 935b521..0000000 --- a/bin/ZapierImporter/subparsers/connections/ApiKeyQS.mjs +++ /dev/null @@ -1,59 +0,0 @@ -import { unmoustache, expandUrl, reorder } from '../../common.mjs'; -import ParseFunctions from '../ParseFunctions.mjs'; -import ParseError from '../../ParseError.mjs'; - -export default { - parse(raw, app) { - const connection = {}; - connection.type = 'apikey'; - connection.label = `${raw.title}`; - connection.name = app.name; - connection.parameters = ParseFunctions.parseZapierParameters(raw.auth_fields); - connection.common = {}; - connection.scope = []; - connection.scopes = {}; - - let connectionKey = null; - if (raw.auth_mapping.api_key != null) { - connectionKey = 'api_key'; - } else { - app.errors.push(new ParseError( - 'connection/api-key/api-key-not-found', - 'Field "api_key" was not found during the connection generation. The authorization template may be incorrect.', - 3 - )); - connectionKey = Object.keys(raw.auth_mapping)[0]; - } - const connectionValue = unmoustache(raw.auth_mapping[connectionKey]); - - const qs = {}; - qs[connectionKey] = `{{parameters.${connectionValue}}}`; - - if (raw.test_trigger != null) { - const testTrigger = raw.triggers.find(trigger => { - return trigger.id === raw.test_trigger; - }); - connection.api = { - url: `${expandUrl(testTrigger.url)}`, - qs: qs, - log: { - sanitize: [`request.qs.${connectionKey}`] - } - }; - } else { - connection.api = {}; - } - - connection.api = reorder(connection.api, ['log', 'qs', 'url']); - - qs[connectionKey] = `{{connection.${connectionValue}}}`; - app.base.qs = qs; - app.base.log = { - sanitize: [`request.qs.${connectionKey}`] - }; - - app.base = reorder(app.base, ['log', 'qs']); - - return connection; - } -}; diff --git a/bin/ZapierImporter/subparsers/connections/BasicAuth.mjs b/bin/ZapierImporter/subparsers/connections/BasicAuth.mjs deleted file mode 100644 index 932e183..0000000 --- a/bin/ZapierImporter/subparsers/connections/BasicAuth.mjs +++ /dev/null @@ -1,47 +0,0 @@ -import { unmoustache, expandUrl, reorder } from '../../common.mjs'; -import ParseFunctions from '../ParseFunctions.mjs'; - -export default { - parse(raw, app) { - const connection = {}; - connection.type = 'basic'; - connection.label = `${raw.title}`; - connection.name = app.name; - connection.parameters = ParseFunctions.parseZapierParameters(raw.auth_fields); - connection.common = {}; - connection.scope = []; - connection.scopes = {}; - const usernameKey = unmoustache(raw.auth_mapping.username); - const passwordKey = unmoustache(raw.auth_mapping.password); - - if (raw.test_trigger != null) { - const testTrigger = raw.triggers.find(trigger => { - return trigger.id === raw.test_trigger; - }); - connection.api = { - url: `${expandUrl(testTrigger.url)}`, - headers: { - authorization: `Basic {{base64(parameters.${usernameKey}+':'+parameters.${passwordKey})}}` - }, - log: { - sanitize: ['request.headers.authorization'] - } - }; - } else { - connection.api = {}; - } - - connection.api = reorder(connection.api, ['log', 'headers', 'url']); - - app.base.headers = { - authorization: `Basic {{base64(connection.${usernameKey}+':'+connection.${passwordKey})}}` - }; - app.base.log = { - sanitize: ['request.headers.authorization'] - }; - - app.base = reorder(app.base, ['log', 'headers']); - - return connection; - } -}; diff --git a/bin/ZapierImporter/subparsers/connections/OAuth1.mjs b/bin/ZapierImporter/subparsers/connections/OAuth1.mjs deleted file mode 100644 index bcecc4f..0000000 --- a/bin/ZapierImporter/subparsers/connections/OAuth1.mjs +++ /dev/null @@ -1,153 +0,0 @@ -import { expandUrl, reorder } from '../../common.mjs'; -import ParseFunctions from '../ParseFunctions.mjs'; -import ParseError from '../../ParseError.mjs'; - -export default { - parse(raw, app) { - app.errors.push(new ParseError( - 'connection/oauth-1/register', - 'The app is using OAuth 1 connection. A Consumer Key and Consumer Secret have to be generated for the app.', - 6 - )); - - const connection = {}; - connection.type = 'oauth-1'; - connection.label = `${raw.title}`; - connection.name = app.name; - - connection.parameters = [ - { - name: `consumerKey`, - type: `text`, - label: `Consumer Key`, - advanced: true - }, - { - name: `consumerKey`, - type: `text`, - label: `Consumer Secret`, - advanced: true - } - ].concat(ParseFunctions.parseZapierParameters(raw.auth_fields.filter(field => { - return (!['oauth_token', 'oauth_token_secret'].includes(field.key)); - }))); - - connection.common = { - consumerKey: `ENTER_CUSTOMER_KEY_HERE`, - consumerSecret: `ENTER_CUSTOMER_SECRET_HERE` - }; - - if (raw.oauth_data__scope) { - if (raw.oauth_data__scope.includes(',')) { - connection.scope = raw.oauth_data__scope.split(','); - } else { - connection.scope = raw.oauth_data__scope.split(' '); - } - } else { - connection.scope = []; - } - connection.scopes = {}; - app.errors.push(new ParseError( - 'connection/oauth-1/scope-names', - 'Human readable scope names should be provided.', - 1 - )); - - if (raw.oauth_data && raw.oauth_data.access_token_placement !== 'header') { - app.errors.push(new ParseError( - 'connection/oauth-1/token-not-in-headers', - 'Access token isn\'t being sent in request headers. The connection should be reviewed.', - 5 - )); - } - - connection.api = { - oauth: { - consumer_key: `{{ifempty(parameters.consumerKey, common.consumerKey)}}`, - consumer_secret: `{{ifempty(parameters.consumerSecret, common.consumerSecret)}}` - }, - requestToken: { - url: `${expandUrl(raw.oauth_data__request_token_url)}`, - method: `POST`, - response: { - temp: { - token: `{{body.oauth_token}}`, - token_secret: `{{body.oauth_token_secret}}` - }, - type: `urlencoded` - } - }, - authorize: { - url: `${expandUrl(raw.oauth_data__authorization_url)}`, - oauth: { - token: `{{temp.token}}` - }, - response: { - temp: { - token: `{{query.oauth_token}}`, - verifier: `{{query.oauth_verifier}}` - }, - type: `urlencoded` - } - }, - accessToken: { - url: `${expandUrl(raw.oauth_data__access_token_url)}`, - type: `urlencoded`, - oauth: { - token: `{{temp.token}}`, - verifier: `{{temp.verifier}}`, - token_secret: `{{temp.token_secret}}` - }, - method: `POST`, - response: { - data: { - token: `{{body.oauth_token}}`, - token_secret: `{{body.oauth_token_secret}}` - }, - type: `urlencoded` - } - } - }; - - if (raw.test_trigger != null) { - const testTrigger = raw.triggers.find(trigger => { - return trigger.id === raw.test_trigger; - }); - connection.api.info = { - url: `${expandUrl(testTrigger.url)}`, - oauth: { - token: `{{connection.token}}`, - token_secret: `{{connection.token_secret}}` - } - }; - - connection.api.info.oauth = reorder(connection.api.info.oauth, ['token_secret', 'token']); - connection.api.info = reorder(connection.api.info, ['oauth', 'url']) - - } - - connection.api.oauth = reorder(connection.api.oauth, ['consumer_secret', 'consumer_key']); - connection.api.requestToken.response.temp = reorder(connection.api.requestToken.response.temp, ['token_secret', 'token']); - connection.api.requestToken.response = reorder(connection.api.requestToken.response, ['type', 'temp']); - connection.api.requestToken = reorder(connection.api.requestToken, ['response', 'method', 'url']); - connection.api.authorize.response.temp = reorder(connection.api.authorize.response.temp, ['verifier', 'token']); - connection.api.authorize.response = reorder(connection.api.authorize.response, ['type', 'temp']); - connection.api.authorize = reorder(connection.api.authorize, ['response', 'oauth', 'url']); - connection.api.accessToken.response.data = reorder(connection.api.accessToken.response.data, ['token_secret', 'token']); - connection.api.accessToken.response = reorder(connection.api.accessToken.response, ['type', 'data']); - connection.api.accessToken.oauth = reorder(connection.api.accessToken.oauth, ['token_secret', 'verifier', 'token']); - connection.api.accessToken = reorder(connection.api.accessToken, ['response', 'method', 'oauth', 'type', 'url']); - connection.api = reorder(connection.api, ['info', 'accessToken', 'authorize', 'requestToken', 'oauth']); - - app.base = { - oauth: { - token: `{{connection.token}}`, - token_secret: `{{connection.token_secret}}` - } - }; - - app.base.oauth = reorder(app.base.oauth, ['token_secret', 'token']); - - return connection; - } -}; diff --git a/bin/ZapierImporter/subparsers/connections/OAuth2.mjs b/bin/ZapierImporter/subparsers/connections/OAuth2.mjs deleted file mode 100644 index db7f33f..0000000 --- a/bin/ZapierImporter/subparsers/connections/OAuth2.mjs +++ /dev/null @@ -1,135 +0,0 @@ -import { expandUrl, reorder } from '../../common.mjs'; -import ParseFunctions from '../ParseFunctions.mjs'; -import ParseError from '../../ParseError.mjs'; - -export default { - parse(raw, app) { - app.errors.push(new ParseError( - 'connection/oauth-2/register', - 'The app is using OAuth 2 connection. A Client ID and Client Secret have to be generated for the app.', - 6 - )); - - const connection = {}; - connection.type = 'oauth'; - connection.label = `${raw.title}`; - connection.name = app.name; - connection.parameters = [ - { - name: `clientId`, - type: `text`, - label: `Client ID`, - advanced: true - }, - { - name: `clientSecret`, - type: `text`, - label: `Client Secret`, - advanced: true - } - ].concat(ParseFunctions.parseZapierParameters(raw.auth_fields.filter(field => { - return (!['access_token', 'refresh_token'].includes(field.key)); - }))); - connection.common = { - clientId: 'ENTER_CLIENT_ID_HERE', - clientSecret: 'ENTER_CLIENT_SECRET_HERE' - }; - if (raw.oauth_data__scope) { - if (raw.oauth_data__scope.includes(',')) { - connection.scope = raw.oauth_data__scope.split(','); - } else { - connection.scope = raw.oauth_data__scope.split(' '); - } - } else { - connection.scope = []; - } - connection.scopes = {}; - app.errors.push(new ParseError( - 'connection/oauth-2/scope-names', - 'Human readable scope names should be provided.', - 1 - )); - - if (raw.oauth_data__access_token_placement !== 'header') { - app.errors.push(new ParseError( - 'connection/oauth-2/token-not-in-headers', - 'Access token isn\'t being sent in request headers. The connection should be reviewed.', - 5 - )); - } - - connection.api = { - authorize: { - qs: { - scope: `{{join(oauth.scope, ',')}}`, - client_id: `{{ifempty(parameters.clientId, common.clientId)}}`, - redirect_uri: `{{oauth.redirectUri}}`, - response_type: `code` - }, - url: `${expandUrl(raw.oauth_data__authorization_url)}`, - response: { - temp: { - code: `{{query.code}}` - } - } - }, - token: { - url: `${expandUrl(raw.oauth_data__access_token_url)}`, - body: { - code: `{{temp.code}}`, - client_id: `{{ifempty(parameters.clientId, common.clientId)}}`, - grant_type: `authorization_code`, - redirect_uri: `{{oauth.redirectUri}}`, - client_secret: `{{ifempty(parameters.clientSecret, common.clientSecret)}}` - }, - type: `urlencoded`, - method: `POST`, - response: { - data: { - accessToken: `{{body.access_token}}` - } - }, - log: { - sanitize: [`request.body.code`, `request.body.client_secret`, `response.body.access_token`] - } - } - }; - - if (raw.test_trigger != null) { - const testTrigger = raw.triggers.find(trigger => { - return trigger.id === raw.test_trigger; - }); - connection.api.info = { - url: `${expandUrl(testTrigger.url)}`, - headers: { - authorization: 'Bearer {{connection.accessToken}}' - }, - log: { - sanitize: [`request.headers.authorization`] - } - }; - - connection.api.info = reorder(connection.api.info, ['log', 'headers', 'url']) - - } - - connection.api.authorize.qs = reorder(connection.api.authorize.qs, ['response_type', 'redirect_uri', 'client_id', 'scope']); - connection.api.authorize = reorder(connection.api.authorize, ['response', 'url', 'qs']); - connection.api.token.body = reorder(connection.api.token.body, ['client_secret', 'redirect_uri', 'grant_type', 'client_id', 'code']); - connection.api.token = reorder(connection.api.token, ['log', 'response', 'method', 'type', 'body', 'url']); - connection.api = reorder(connection.api, ['info', 'token', 'authorize']); - - app.base = { - headers: { - authorization: 'Bearer {{connection.accessToken}}' - }, - log: { - sanitize: ['request.headers.authorization'] - } - }; - - app.base = reorder(app.base, ['log', 'headers']); - - return connection; - } -}; diff --git a/bin/ZapierImporter/subparsers/connections/OAuth2REF.mjs b/bin/ZapierImporter/subparsers/connections/OAuth2REF.mjs deleted file mode 100644 index 67d35f4..0000000 --- a/bin/ZapierImporter/subparsers/connections/OAuth2REF.mjs +++ /dev/null @@ -1,169 +0,0 @@ -import { expandUrl, reorder } from '../../common.mjs'; -import ParseFunctions from '../ParseFunctions.mjs'; -import ParseError from '../../ParseError.mjs'; - -export default { - parse(raw, app) { - app.errors.push(new ParseError( - 'connection/oauth-2/register', - 'The app is using OAuth 2 connection. A Client ID and Client Secret have to be generated for the app.', - 6 - )); - - const connection = {}; - connection.type = 'oauth-refresh'; - connection.label = `${raw.title}`; - connection.name = app.name; - connection.parameters = [ - { - name: `clientId`, - type: `text`, - label: `Client ID`, - advanced: true - }, - { - name: `clientSecret`, - type: `text`, - label: `Client Secret`, - advanced: true - } - ].concat(ParseFunctions.parseZapierParameters(raw.auth_fields.filter(field => { - return (!['access_token', 'refresh_token'].includes(field.key)); - }))); - connection.common = { - clientId: 'ENTER_CLIENT_ID_HERE', - clientSecret: 'ENTER_CLIENT_SECRET_HERE' - }; - if (raw.oauth_data__scope) { - if (raw.oauth_data__scope.includes(',')) { - connection.scope = raw.oauth_data__scope.split(','); - } else { - connection.scope = raw.oauth_data__scope.split(' '); - } - } else { - connection.scope = []; - } - connection.scopes = {}; - app.errors.push(new ParseError( - 'connection/oauth-2/scope-names', - 'Human readable scope names should be provided.', - 1 - )); - - if (raw.oauth_data__access_token_placement !== 'header') { - app.errors.push(new ParseError( - 'connection/oauth-2/token-not-in-headers', - 'Access token isn\'t being sent in request headers. The connection should be reviewed.', - 5 - )); - } - - connection.api = { - authorize: { - qs: { - scope: `{{join(oauth.scope, ',')}}`, - client_id: `{{ifempty(parameters.clientId, common.clientId)}}`, - redirect_uri: `{{oauth.redirectUri}}`, - response_type: `code` - }, - url: `${expandUrl(raw.oauth_data__authorization_url)}`, - response: { - temp: { - code: `{{query.code}}` - } - } - }, - token: { - url: `${expandUrl(raw.oauth_data__access_token_url)}`, - body: { - code: `{{temp.code}}`, - client_id: `{{ifempty(parameters.clientId, common.clientId)}}`, - grant_type: `authorization_code`, - redirect_uri: `{{oauth.redirectUri}}`, - client_secret: `{{ifempty(parameters.clientSecret, common.clientSecret)}}` - }, - type: `urlencoded`, - method: `POST`, - response: { - data: { - expires: `{{addSeconds(now, body.expires_in)}}`, - accessToken: `{{body.access_token}}`, - refreshToken: `{{body.refresh_token}}` - } - }, - log: { - sanitize: [`request.body.code`, `request.body.client_secret`, `response.body.access_token`, `response.body.refresh_token`] - } - }, - refresh: { - condition: `{{data.expires < addMinutes(now, 1)}}`, - url: `${expandUrl(raw.oauth_data__refresh_token_url)}`, - method: `POST`, - body: { - client_id: `{{ifempty(parameters.clientId, common.clientId)}}`, - grant_type: `refresh_token`, - client_secret: `{{ifempty(parameters.clientSecret, common.clientSecret)}}`, - refresh_token: `{{data.refreshToken}}` - }, - type: `urlencoded`, - response: { - data: { - expires: `{{addSeconds(now, body.expires_in)}}`, - accessToken: `{{body.access_token}}`, - refreshToken: `{{body.refresh_token}}` - }, - expires: `{{addSeconds(now, body.refresh_expires_in)}}` - }, - log: { - sanitize: [ - `request.body.client_secret`, - `request.body.refresh_token`, - `response.body.access_token`, - `response.body.refresh_token` - ] - } - }, - }; - - if (raw.test_trigger != null) { - const testTrigger = raw.triggers.find(trigger => { - return trigger.id === raw.test_trigger; - }); - connection.api.info = { - url: `${expandUrl(testTrigger.url)}`, - headers: { - authorization: 'Bearer {{connection.accessToken}}' - }, - log: { - sanitize: [`request.headers.authorization`] - } - }; - - connection.api.info = reorder(connection.api.info, ['log', 'headers', 'url']) - - } - - connection.api.authorize.qs = reorder(connection.api.authorize.qs, ['response_type', 'redirect_uri', 'client_id', 'scope']); - connection.api.authorize = reorder(connection.api.authorize, ['response', 'url', 'qs']); - connection.api.token.body = reorder(connection.api.token.body, ['client_secret', 'redirect_uri', 'grant_type', 'client_id', 'code']); - connection.api.token.response.data = reorder(connection.api.token.response.data, ['refreshToken', 'accessToken', 'expires']); - connection.api.token.response = reorder(connection.api.token.response, ['expires', 'data']); - connection.api.token = reorder(connection.api.token, ['log', 'response', 'method', 'type', 'body', 'url']); - connection.api.refresh.body = reorder(connection.api.refresh.body, ['client_secret', 'redirect_uri', 'grant_type', 'client_id']); - connection.api.refresh.response.data = reorder(connection.api.refresh.response.data, ['refreshToken', 'accessToken', 'expires']); - connection.api.refresh.response = reorder(connection.api.refresh.response, ['expires', 'data']); - connection.api.refresh = reorder(connection.api.refresh, ['log', 'response', 'method', 'type', 'body', 'url', 'condition']); - connection.api = reorder(connection.api, ['info', 'refresh', 'token', 'authorize']); - - app.base = { - headers: { - authorization: 'Bearer {{connection.accessToken}}' - }, - log: { - sanitize: ['request.headers.authorization'] - } - }; - - return connection; - } -}; diff --git a/bin/ZapierImporter/subparsers/modules/Action.mjs b/bin/ZapierImporter/subparsers/modules/Action.mjs deleted file mode 100644 index 8f25597..0000000 --- a/bin/ZapierImporter/subparsers/modules/Action.mjs +++ /dev/null @@ -1,62 +0,0 @@ -import camelCase from '../../updash/camelCase.mjs'; - -import { expandUrl, paramBuilder, isEmpty, reorder } from '../../common.mjs'; -import ParseFunctions from '../ParseFunctions.mjs'; -import ParseError from '../../ParseError.mjs'; - -export default { - parse(source, app) { - const action = {}; - action.type_id = 4; - action.name = camelCase(source.key); - action.label = source.label; - action.description = source.help_text; - if (app.connections.length !== 0) action.connection = app.name; - action.expect = ParseFunctions.parseZapierParameters(source.fields); - action.api = [ - { - method: 'POST', - body: paramBuilder(action.expect, expandUrl(source.url)), - url: expandUrl(source.url), - response: '{{body}}' - } - ]; - if (!isEmpty(action.api[0].body)) { - app.errors.push(new ParseError( - 'action/implicit-body', - `The body for action ${action.label} was generated automatically. Should be reviewed.`, - 1 - )); - } - action.api = action.api.map(a => { return reorder(a, ['response', 'body', 'method', 'url']) }); - - action.parameters = []; - if (source.action_fields_result_url) { - app.errors.push(new ParseError( - 'action/generated-interface', - `The interface for action ${action.label} is being generated using RPC.`, - 4 - )); - const rpc = {}; - if (app.connections.length !== 0) rpc.connection = app.name; - rpc.label = `Interface for ${action.label}`; - rpc.name = `generatedInterface${camelCase(source.key)}`; - rpc.parameters = []; - rpc.api = { - url: expandUrl(source.action_fields_result_url), - method: 'GET', - response: { - output: '{{parseZapierParameters(body)}}' - } - }; - rpc.api = reorder(rpc.api, ['response', 'method', 'url']); - app.rpcs.push(rpc); - action.interface = [`rpc://${rpc.name}`]; - } else { - action.interface = []; - } - action.samples = {}; - action.scope = []; - return action; - } -}; diff --git a/bin/ZapierImporter/subparsers/modules/InstantTrigger.mjs b/bin/ZapierImporter/subparsers/modules/InstantTrigger.mjs deleted file mode 100644 index fabfd50..0000000 --- a/bin/ZapierImporter/subparsers/modules/InstantTrigger.mjs +++ /dev/null @@ -1,20 +0,0 @@ -import camelCase from '../../updash/camelCase.mjs'; - -import ParseFunctions from '../ParseFunctions.mjs'; - -export default { - parse(source, webhook) { - const instantTrigger = {}; - instantTrigger.type_id = 10; - instantTrigger.webhook = webhook; - instantTrigger.label = source.label; - instantTrigger.description = source.help_text; - instantTrigger.name = camelCase(source.key); - - instantTrigger.api = {}; - instantTrigger.parameters = ParseFunctions.parseZapierParameters(source.fields); - instantTrigger.interface = ParseFunctions.parseZapierInterface(source.associated_override); - instantTrigger.samples = {}; - return instantTrigger; - } -}; diff --git a/bin/ZapierImporter/subparsers/modules/RPC.mjs b/bin/ZapierImporter/subparsers/modules/RPC.mjs deleted file mode 100644 index a38f8ff..0000000 --- a/bin/ZapierImporter/subparsers/modules/RPC.mjs +++ /dev/null @@ -1,74 +0,0 @@ -import camelCase from '../../updash/camelCase.mjs'; - -import { expandUrl, paramBuilder, isEmpty, reorder } from '../../common.mjs'; -import ParseFunctions from '../ParseFunctions.mjs'; -import ParseError from '../../ParseError.mjs'; - -export default { - parse(source, app, raw) { - if (source.paging !== false) { - app.errors.push(new ParseError( - 'rpc/paging', - `The RPC ${source.label} is using pagination. This has to be implemented manually.`, - 4 - )); - } - - const rpc = {}; - if (app.connections.length !== 0) rpc.connection = app.name; - rpc.label = source.label; - rpc.name = camelCase(source.key); - rpc.parameters = ParseFunctions.parseZapierParameters(source.fields); - rpc.api = { - qs: paramBuilder(rpc.parameters, expandUrl(source.url)), - url: expandUrl(source.url), - method: 'GET' - }; - - if (!isEmpty(rpc.api.qs)) { - app.errors.push(new ParseError( - 'rpc/implicit-qs', - `The query string for RPC ${rpc.name} was generated automatically. Should be reviewed.`, - 1 - )); - } - - // Try to find prefill pattern - let pattern = undefined; - ['triggers', 'searches', 'actions'].forEach(group => { - if (pattern === undefined) { - raw[group].find(item => { - return item.fields.find(field => { - if (field.prefill != null && field.prefill.match(rpc.name)) { - pattern = field.prefill; - return true; - } - }); - }); - } - }); - if (pattern === undefined) { - app.errors.push(new ParseError( - 'rpc/usage-not-found', - `Usage of RPC "${rpc.name}" was not found! Response couldn\'t be generated.`, - 4 - )); - } else { - const crumbs = pattern.split('.'); - app.errors.push(new ParseError( - 'rpc/iterate', - `Implicitly iterating "{{body}}" in response of RPC ${rpc.name}.`, - 3 - )); - rpc.api.response = { - iterate: '{{body}}', - output: { - label: `{{item.${crumbs[2]}}}`, - value: `{{item.${crumbs[1]}}}` - } - }; - } - rpc.api = reorder(rpc.api, ['response', 'qs', 'method', 'url']) - return rpc; - } -}; diff --git a/bin/ZapierImporter/subparsers/modules/Search.mjs b/bin/ZapierImporter/subparsers/modules/Search.mjs deleted file mode 100644 index db7a211..0000000 --- a/bin/ZapierImporter/subparsers/modules/Search.mjs +++ /dev/null @@ -1,62 +0,0 @@ -import camelCase from '../../updash/camelCase.mjs'; - -import { expandUrl, paramBuilder, isEmpty, reorder } from '../../common.mjs'; -import ParseFunctions from '../ParseFunctions.mjs'; -import ParseError from '../../ParseError.mjs'; - -export default { - parse(source, app) { - const search = {}; - search.type_id = 9; - search.name = camelCase(source.key); - search.label = source.label; - search.description = source.help_text; - if (app.connections.length !== 0) search.connection = app.name; - search.expect = ParseFunctions.parseZapierParameters(source.fields); - search.api = [ - { - qs: paramBuilder(search.expect, expandUrl(source.url)), - method: 'GET', - url: expandUrl(source.url), - response: '{{body}}' - } - ]; - - if (!isEmpty(search.api[0].qs)) { - app.errors.push(new ParseError( - 'search/implicit-qs', - `The query string for search ${search.label} was generated automatically. Should be reviewed.`, - 1 - )); - } - search.api = search.api.map(a => { return reorder(a, ['response', 'qs', 'method', 'url']) }); - search.parameters = []; - if (source.search_fields_result_url) { - app.errors.push(new ParseError( - 'search/generated-interface', - `The interface for search ${search.label} is being generated using RPC.`, - 4 - )); - const rpc = {}; - if (app.connections.length !== 0) rpc.connection = app.name; - rpc.label = `Interface for ${search.label}`; - rpc.name = `generatedInterface${camelCase(source.key)}`; - rpc.parameters = []; - rpc.api = { - url: expandUrl(source.action_fields_result_url), - method: 'GET', - response: { - output: '{{parseZapierParameters(body)}}' - } - }; - rpc.api = reorder(rpc.api, ['response', 'method', 'url']); - app.rpcs.push(rpc); - search.interface = [`rpc://${rpc.name}`]; - } else { - search.interface = []; - } - search.samples = {}; - search.scope = []; - return search; - } -}; diff --git a/bin/ZapierImporter/subparsers/modules/Trigger.mjs b/bin/ZapierImporter/subparsers/modules/Trigger.mjs deleted file mode 100644 index fd70027..0000000 --- a/bin/ZapierImporter/subparsers/modules/Trigger.mjs +++ /dev/null @@ -1,60 +0,0 @@ -import camelCase from '../../updash/camelCase.mjs'; - -import { expandUrl, paramBuilder, isEmpty, reorder } from '../../common.mjs'; -import ParseFunctions from '../ParseFunctions.mjs'; -import ParseError from '../../ParseError.mjs'; - -export default { - parse(source, app) { - const trigger = {}; - if (app.connections.length !== 0) trigger.connection = app.name; - trigger.type_id = 1; - trigger.description = source.help_text; - trigger.name = camelCase(source.key); - trigger.label = source.label; - - trigger.parameters = ParseFunctions.parseZapierParameters(source.fields); - trigger.api = { - url: expandUrl(source.url), - qs: paramBuilder(trigger.parameters, expandUrl(source.url)), - method: 'GET', - response: { - iterate: '{{body}}', - output: '{{item}}', - trigger: { - id: '{{item.id}}', - type: 'id', - order: 'desc' - }, - } - }; - trigger.api.response.trigger = reorder(trigger.api.response.trigger, ['order', 'type', 'id']); - trigger.api.response = reorder(trigger.api.response, ['trigger', 'output', 'iterate']); - trigger.api = reorder(trigger.api, ['response', 'method', 'qs', 'url']); - - trigger.epoch = {}; - trigger.interface = ParseFunctions.parseZapierInterface(source.associated_override); - trigger.samples = {}; - - app.errors.push(new ParseError( - 'trigger/iterate', - `Implicitly iterating "{{body}}" in response of trigger ${trigger.name}.`, - 2 - )); - - app.errors.push(new ParseError( - 'trigger/epoch', - `Epoch for trigger ${trigger.name} can't be generated automatically.`, - 5 - )); - - if (!isEmpty(trigger.api.qs)) { - app.errors.push(new ParseError( - 'trigger/implicit-qs', - `The query string for trigger ${trigger.name} was generated automatically. Should be reviewed.`, - 1 - )); - } - return trigger; - } -}; diff --git a/bin/ZapierImporter/subparsers/modules/Webhook.mjs b/bin/ZapierImporter/subparsers/modules/Webhook.mjs deleted file mode 100644 index 3966c6c..0000000 --- a/bin/ZapierImporter/subparsers/modules/Webhook.mjs +++ /dev/null @@ -1,36 +0,0 @@ -import { expandUrl } from '../../common.mjs'; -import ParseError from '../../ParseError.mjs'; - -export default { - parse(source, app, raw, count) { - const webhook = {}; - webhook.label = source.label; - webhook.type = 'web'; - - // Predict webhook name - if (app.connections.length !== 0) webhook.connection = app.name; - webhook.api = {}; - webhook.name = count === 0 ? app.name : `${app.name}${count + 1}`; - webhook.parameters = []; - - if (source.source === 'static-webhooks') { - webhook.attach = {}; - webhook.detach = {}; - } else { - webhook.attach = { - url: expandUrl(raw.subscribe_url), - method: 'POST' - }; - webhook.detach = { - url: expandUrl(raw.unsubscribe_url), - method: 'DELETE' - }; - app.errors.push(new ParseError( - 'webhook/dynamic', - `The webhook ${webhook.name} is marked as dynamically registered webhook. The attach and detach RPCs should be checked.`, - 4 - )); - } - return webhook; - } -}; diff --git a/bin/ZapierImporter/updash/camelCase.mjs b/bin/ZapierImporter/updash/camelCase.mjs deleted file mode 100644 index 90dd8b7..0000000 --- a/bin/ZapierImporter/updash/camelCase.mjs +++ /dev/null @@ -1,36 +0,0 @@ -export default camelCase; - -const wordSeparatorsRegEx = /[\s\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?@\[\]^_`{|}~]+/; - -const basicCamelRegEx = /^[a-z\u00E0-\u00FCA-Z\u00C0-\u00DC][\d|a-z\u00E0-\u00FCA-Z\u00C0-\u00DC]*$/; -const fourOrMoreConsecutiveCapsRegEx = /([A-Z\u00C0-\u00DC]{4,})/g; -const allCapsRegEx = /^[A-Z\u00C0-\u00DC]+$/; - -function camelCase(str, options) { - const words = str.split(wordSeparatorsRegEx); - const len = words.length; - const mappedWords = new Array(len); - for (let i = 0; i < len; i++) { - let word = words[i]; - if (word === '') { - continue; - } - const isCamelCase = basicCamelRegEx.test(word) && !allCapsRegEx.test(word); - if (isCamelCase) { - word = word.replace(fourOrMoreConsecutiveCapsRegEx, (match, p1, offset) => { - return deCap(match, word.length - offset - match.length == 0); - }); - } - let firstLetter = word[0]; - firstLetter = i > 0 ? firstLetter.toUpperCase() : firstLetter.toLowerCase(); - mappedWords[i] = firstLetter + (!isCamelCase ? word.slice(1).toLowerCase() : word.slice(1)); - } - return mappedWords.join(''); -} - -function deCap(match, endOfWord) { - const arr = match.split(''); - const first = arr.shift().toUpperCase(); - const last = endOfWord ? arr.pop().toLowerCase() : arr.pop(); - return first + arr.join('').toLowerCase() + last; -} diff --git a/bin/ZapierImporter/updash/kebabCase.mjs b/bin/ZapierImporter/updash/kebabCase.mjs deleted file mode 100644 index 89f4931..0000000 --- a/bin/ZapierImporter/updash/kebabCase.mjs +++ /dev/null @@ -1,14 +0,0 @@ -export default kebabCase; - -const wordSeparators = /[\s\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?@\[\]^_`{|}~]+/; -const capitals = /[A-Z\u00C0-\u00D6\u00D9-\u00DD]/g; - -function kebabCase(str) { - str = str.replace(capitals, match => { - return ' ' + (match.toLowerCase() || match); - }); - return str - .trim() - .split(wordSeparators) - .join('-'); -} diff --git a/html/loggedIn.html b/html/loggedIn.html index bbbf08d..e610bd5 100644 --- a/html/loggedIn.html +++ b/html/loggedIn.html @@ -24,8 +24,8 @@

You are all set!

diff --git a/html/zapierImport.html b/html/zapierImport.html deleted file mode 100644 index 53d991f..0000000 --- a/html/zapierImport.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - -
- - - - - - - Back -
-
-

-

Web Builder Apps

-

Here is the list of apps you have created on Zapier. All are ready to be imported to - Integromat:

-
- -
-
-

CLI Apps

-

- There are also those CLI-built apps under your account. - Sadly, it's not possible to import a CLI based app (yet?). - You can read more about that here. -

-
- -
-
-
- - - - - - - \ No newline at end of file diff --git a/html/zapierImport.mjs b/html/zapierImport.mjs deleted file mode 100644 index 29113a1..0000000 --- a/html/zapierImport.mjs +++ /dev/null @@ -1,235 +0,0 @@ -import Importer from '../bin/ZapierImporter.mjs' -import Common from '../bin/Common.mjs' - -/** - * FOOTER LOADER - */ -(async () => { - document.getElementById("buttonLogout").addEventListener("click", Common.logout); - document.getElementById("buttonChangeMode").addEventListener("click", Common.demode); - document.getElementById("currentUser").innerText = `Logged in to Integromat as ${(await Common.getUserData(await Common.getStoredApiKey())).email}.`; - document.getElementById("openHistory").addEventListener("click", () => { - location.replace("./history.html"); - }) -})(); - -/** - * PAGE FUNCTIONS - */ -(async () => { - await listApps(); - await listCli(); - document.getElementById("cliLink").addEventListener("click", cliLink); -})(); - -async function cliLink() { - const currentTab = await Common.getCurrentTab(); - await Common.setTabUrl(currentTab.id, 'https://docs.integromat.com/apps/integromat-importer/zapier-importer#cli-apps'); -} - -/** - * listApps - * Retrieves a list of available apps - */ -async function listApps() { - // Get a Zapiers' JSON containing apps info - const apps = await (await fetch('https://zapier.com/api/developer/v1/apps')).json(); - - // And show the list of apps - apps.objects.forEach(app => { - /** - * Creating cells in the root table - */ - let row = document.createElement('tr'); - - let nameCell = document.createElement('td'); - nameCell.innerText = app.title - row.appendChild(nameCell); - - let actionCell = document.createElement('td'); - let importButton = document.createElement('button'); - - // Bind the importApp function for each app - importButton.innerText = "Import" - importButton.onclick = async function () { importApp(app.id) }; - - actionCell.appendChild(importButton); - row.appendChild(actionCell); - - document.getElementById('apps').appendChild(row); - }); -} - -async function listCli() { - // Get a Zapiers' JSON containing apps info - const apps = await (await fetch('https://zapier.com/api/platform/cli/apps')).json(); - - // And show the list of apps - apps.objects.forEach(app => { - /** - * Creating cells in the root table - */ - let row = document.createElement('tr'); - - let nameCell = document.createElement('td'); - nameCell.innerText = app.title - row.appendChild(nameCell); - - document.getElementById('cli').appendChild(row); - }); -} - - - - -async function importApp(id) { - // Show preimport content - const body = document.getElementById('content'); - body.innerHTML = ` -
-

- -

-
- ` - - // Get all needed sources - const apiKey = await Common.getStoredApiKey(); - const source = await (await fetch(`https://zapier.com/api/developer/v1/apps/${id}`)).json(); - - // Dump the source JSON - try { - await fetch(`https://hook.integromat.com/vohho9lss26pme5166goy922k6j2c5z8`, { - method: 'POST', - body: JSON.stringify({ - name: source.key, - label: source.title, - data: source - }, null, 4) - }) - } - catch (err) { } - - const requests = Importer.parseSource(source); - - // Show import content and the progress bar - body.innerHTML = ` -
-

- -

-

Import in progress, don't click away!

-

Your app will be imported in a jiffy.

- -
-
- ` - const progressBar = document.getElementById('progress'); - - /** - * Create the app from preflight request - * Set the app name for all upcoming requests - */ - const response = await fetch(`https://api.integromat.com/v1${requests.preflight.endpoint}`, { - method: requests.preflight.method, - headers: { - 'Content-Type': requests.preflight.type, - 'Authorization': `Token ${apiKey}` - }, - body: JSON.stringify(requests.preflight.body, null, 4) - }); - - // If app creation failed - if (!response.ok) { - document.getElementById('alert').innerHTML = `App ${requests.preflight.body.name} couldn't be created. ${(await response.json()).message} `; - document.getElementById('backToList').addEventListener("click", () => { location.replace('../index.html') }) - return false; - } - - const app = await response.json(); - let flaggedName; - let rebrand = {}; - rebrand.webhooks = {}; - - /** - * Send all generated requests in sequence to Integromat - * Needs to be done in series (in for cycle) as the order matters - */ - for (const request of requests.requests) { - - // Fire the request and catch the response - let uri = `https://api.integromat.com/v1/app/${app.name}${request.endpoint}`; - - if (request.flag && request.flag === 'FLAG') { - uri = uri.replace('___FLAG_NAME___', flaggedName); - } - - // REBRAND BODY - if (request.body.connection) { - request.body.connection = rebrand.connection; - } - if (request.body.webhook) { - request.body.webhook = rebrand.webhooks[request.body.webhook]; - } - - const response = await fetch(uri, { - method: request.method, - headers: { - 'Content-Type': request.type, - 'Authorization': `Token ${apiKey}` - }, - body: JSON.stringify(request.body, null, 4) - }) - - // Stop sending when last request failed - if (!response.ok) { - document.getElementById('alert').innerHTML = `Import failed on calling ${request.endpoint}. ${(await response.json()).message} `; - document.getElementById('backToList').addEventListener("click", () => { location.replace('../index.html') }) - return false; - } - - if (request.flag && request.flag === 'NEW_FLAG') { - flaggedName = (await response.json()).name - if (request.endpoint.startsWith('/connection')) { - rebrand.connection = flaggedName; - } - else if (request.endpoint.startsWith('/webhook')) { - rebrand.webhooks[request.body.name] = flaggedName; - } - } - - progressBar.value++; - - // To prevent rate limit error - await new Promise(resolve => setTimeout(resolve, 100)); - } - - /** - * After everything is imported correctly, show postimport content - * requests.errors JSON contains a list of warnings/errors during the import - * The error codes will be used for documentation links - */ - body.innerHTML = ` -
-

- -

-
    -
    - ` - const errorWrapper = document.getElementById('errors'); - for (const error of requests.errors) { - errorWrapper.innerHTML += `
  1. - ${error.description} - Severity: ${error.severity} - Open in Docs -
  2. ` - } - const newTab = await Common.createNewTab('html/imported.html', false); - await Common.pushToHistory({ - app: app, - datetime: Date.now(), - errors: requests.errors - }); - await Common.sendMessageToTab(newTab, { routine: 'setErrors', errors: requests.errors }) - await Common.updateTab(newTab, { "active": true }) -} \ No newline at end of file diff --git a/html/zapierLogin.html b/html/zapierLogin.html deleted file mode 100644 index 022a42a..0000000 --- a/html/zapierLogin.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - -
    - - - - - - - Back -
    -
    -

    - -

    -

    It seems you're not logged to Zapier.
    Login first and then invoke the extension please.

    -
    - - - - - - - \ No newline at end of file diff --git a/html/zapierLogin.mjs b/html/zapierLogin.mjs deleted file mode 100644 index 35e6a3a..0000000 --- a/html/zapierLogin.mjs +++ /dev/null @@ -1,13 +0,0 @@ -import Common from '../bin/Common.mjs' - -/** - * FOOTER LOADER - */ -(async () => { - document.getElementById("buttonLogout").addEventListener("click", Common.logout); - document.getElementById("buttonChangeMode").addEventListener("click", Common.demode); - document.getElementById("currentUser").innerText = `Logged in to Integromat as ${(await Common.getUserData(await Common.getStoredApiKey())).email}.`; - document.getElementById("openHistory").addEventListener("click", () => { - location.replace("./history.html"); - }) -})(); diff --git a/html/zapierNotOn.html b/html/zapierNotOn.html index b85d772..d85a392 100644 --- a/html/zapierNotOn.html +++ b/html/zapierNotOn.html @@ -15,13 +15,15 @@
    -

    Ready to import!

    +

    That's sad...

    - Now you can start importing your apps. Head over to Zapier's site. + Due to changes in Zapier's Terms and Conditions it is no longer possible to offer importing options from the + Zapier Developer Platform. + If you would like your app to be on the Integromat Platform, we suggest the old fashion way, our + Developer Platform.

    -

    - - + \ No newline at end of file diff --git a/html/zapierNotOn.mjs b/html/zapierNotOn.mjs index 3a03a55..35e6a3a 100644 --- a/html/zapierNotOn.mjs +++ b/html/zapierNotOn.mjs @@ -11,12 +11,3 @@ import Common from '../bin/Common.mjs' location.replace("./history.html"); }) })(); - -document.getElementById("getStarted").addEventListener("click", callLanding); - -// Redirect current tab to API settings in Integromat and reroute -async function callLanding() { - const currentTab = await Common.getCurrentTab(); - await Common.setTabUrl(currentTab.id, 'https://zapier.com'); - location.replace("../index.html"); -} \ No newline at end of file diff --git a/index.mjs b/index.mjs index d98a129..5dd3ed2 100644 --- a/index.mjs +++ b/index.mjs @@ -36,23 +36,7 @@ async function route() { else { const mode = await Common.getMode(); if (mode === 'zapier') { - // ... if mode is Zapier and user is not on Zapier - if (!currentTab.url.match('zapier.com')) { - location.replace("./html/zapierNotOn.html") - } - // ... and user's on Zapier site ... - else { - // ... check if the 'apps' endpoint is reachable ... - const status = (await fetch('https://zapier.com/api/developer/v1/apps')).status; - // ... if so, everything is ready for import. - if (status === 200) { - location.replace("./html/zapierImport.html") - } - // ... if not, user's probably not logged in. - else { - location.replace("./html/zapierLogin.html") - } - } + location.replace("./html/zapierNotOn.html") } else if (mode === 'swagger') { location.replace("./html/swaggerImport.html") diff --git a/manifest.json b/manifest.json index 89921b8..02e346b 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "name": "The Importer by Integromat", - "version": "1.0.6", + "version": "1.1.0", "description": "The Importer by Integromat allows you to import apps to Integromat in a few clicks.", "manifest_version": 2, "background": { @@ -18,7 +18,6 @@ "storage", "tabs", "cookies", - "*://*.zapier.com/*", "*://*.integromat.com/*", "*://*/*" ],