From 009eef357b3843b688df43791801c943dc267105 Mon Sep 17 00:00:00 2001 From: Florian Mertens Date: Thu, 20 May 2021 19:38:34 +0100 Subject: [PATCH] Changed whitespace to respect with original authors preferences, removed some unneeded items. --- README.md | 2 +- bin/qb-deploy.js | 152 ++++++++++---------- demo/index.html | 8 +- lib/api.js | 364 +++++++++++++++++++++++------------------------ 4 files changed, 262 insertions(+), 264 deletions(-) diff --git a/README.md b/README.md index 6ea0d73..643959e 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ For now this is only a wrapper around `git clone`. After you pull down a repo yo * Instead of exposing your password for the `quickbase-cli.config.js` file you can rely on an environment variable called `QUICKBASE_CLI_PASSWORD`. If you have that variable defined and leave the `password` empty when prompted the `qb deploy` command will use it instead. Always practice safe passwords. -* The same can also be done with username (using `QUICKBASE_CLI_USERNAME`), user token (using `QUICKBASE_CLI_USERTOKEN`, sort of an Admin token) and/or app token (using `QUICKBASE_CLI_APPTOKEN`). +* The same can also be done with username (using `QUICKBASE_CLI_USERNAME`), user token (using `QUICKBASE_CLI_USERTOKEN`) and/or app token (using `QUICKBASE_CLI_APPTOKEN`). * ~~Moves are being made to add cool shit like a build process, global defaults, awesome starter templates, and pulling down existing code files from QuickBase. They're not out yet, so for now you're on your own.~~ diff --git a/bin/qb-deploy.js b/bin/qb-deploy.js index 396a8d1..4a643dc 100644 --- a/bin/qb-deploy.js +++ b/bin/qb-deploy.js @@ -16,12 +16,12 @@ const readFile = util.promisify(fs.readFile); const stat = util.promisify(fs.stat); program - .option('-w, --watch', 'deploy files on change') - .option( - '-x --replace', - 'replace css and js file paths inside html file with their QuickBase url' - ) - .parse(process.argv); + .option('-w, --watch', 'deploy files on change') + .option( + '-x --replace', + 'replace css and js file paths inside html file with their QuickBase url' + ) + .parse(process.argv); const sourceArg = program.args[0] || '.'; const configPath = require('../lib/find-config')(sourceArg); @@ -31,98 +31,98 @@ const api = new ApiClient(config); qbDeploy(sourceArg); if (program.watch) { - console.log(`Watching for file changes in ${sourceArg}`); - - watch(sourceArg, {}).on('change', fileName => { - console.log(`\nChange detected in ${fileName}`); - program.replace - ? qbDeploy(sourceArg) - : qbDeploy(fileName); - }); + console.log(`Watching for file changes in ${sourceArg}`); + + watch(sourceArg, {}).on('change', fileName => { + console.log(`\nChange detected in ${fileName}`); + program.replace + ? qbDeploy(sourceArg) + : qbDeploy(fileName); + }); } async function qbDeploy(source) { - console.log('Uploading files to QuickBase...'); - - const stats = await fs.statSync(source); - const isFile = stats.isFile(); - - //We authenticate here, before we make a series of asynchronous api calls for each file - api.authenticateIfNeeded().then((authType) => { - - if (isFile) { - return uploadToQuickbase(source) - .then(res => - console.log(`Successfully uploaded to QuickBase:\n=> ${source}`) - ) - .catch(err => console.error(err)); - } - - if (!isFile) { - getFiles(source).then(files => { - const uploadPromises = program.replace - ? files.map(file => replaceUrlsAndUpload(file, files)) - : files.map(file => uploadToQuickbase(file)); - - return Promise.all(uploadPromises) - .then(res => - console.log( - `Successfully uploaded to QuickBase:\n=> ${files.join('\n=> ')}` - ) - ) - .catch(err => console.error(err)); - }); - } - - }).catch((errorDesc) => console.error(errorDesc)); + console.log('Uploading files to QuickBase...'); + + const stats = await fs.statSync(source); + const isFile = stats.isFile(); + + //We authenticate here, before we make a series of asynchronous api calls for each file + api.authenticateIfNeeded().then((authType) => { + + if (isFile) { + return uploadToQuickbase(source) + .then(res => + console.log(`Successfully uploaded to QuickBase:\n=> ${source}`) + ) + .catch(err => console.error(err)); + } + + if (!isFile) { + getFiles(source).then(files => { + const uploadPromises = program.replace + ? files.map(file => replaceUrlsAndUpload(file, files)) + : files.map(file => uploadToQuickbase(file)); + + return Promise.all(uploadPromises) + .then(res => + console.log( + `Successfully uploaded to QuickBase:\n=> ${files.join('\n=> ')}` + ) + ) + .catch(err => console.error(err)); + }); + } + + }).catch((errorDesc) => console.error(errorDesc)); } function uploadToQuickbase(file, fileContents) { - let fileName = path.basename(file); - let codePageName; + let fileName = path.basename(file); + let codePageName; - if (!fileContents) { - fileContents = fs.readFileSync(file, 'utf-8'); - } + if (!fileContents) { + fileContents = fs.readFileSync(file, 'utf-8'); + } - if (config.appName) { - codePageName = `${config.appName}-${fileName}`; - } else { - codePageName = fileName; - } + if (config.appName) { + codePageName = `${config.appName}-${fileName}`; + } else { + codePageName = fileName; + } - return api.uploadPage(codePageName, fileContents); + return api.uploadPage(codePageName, fileContents); } async function replaceUrlsAndUpload(file, allFiles) { - let fileContents = await readFile(file, 'utf-8'); + let fileContents = await readFile(file, 'utf-8'); - allFiles.forEach(assetFile => { - if (file !== assetFile) { - const fileName = path.basename(assetFile); - const regex = new RegExp(`("|')[^"]*${fileName}("|')`, 'g'); + allFiles.forEach(assetFile => { + if (file !== assetFile) { + const fileName = path.basename(assetFile); + const regex = new RegExp(`("|')[^"]*${fileName}("|')`, 'g'); - fileContents = fileContents.replace( - regex, - generateCustomPageUrl(path.basename(assetFile)) - ); - } - }); + fileContents = fileContents.replace( + regex, + generateCustomPageUrl(path.basename(assetFile)) + ); + } + }); - return uploadToQuickbase(file, fileContents); + return uploadToQuickbase(file, fileContents); } function generateCustomPageUrl(fileName) { - const suffix = config.appName - ? `${config.appName}-${fileName}` - : `${fileName}`; + const suffix = config.appName + ? `${config.appName}-${fileName}` + : `${fileName}`; - return `"https://${config.realm}.quickbase.com/db/${ - config.dbid - }?a=dbpage&pagename=${suffix}"`; + return `"https://${config.realm}.quickbase.com/db/${ + config.dbid + }?a=dbpage&pagename=${suffix}"`; } diff --git a/demo/index.html b/demo/index.html index e81c8ab..f77347f 100644 --- a/demo/index.html +++ b/demo/index.html @@ -7,11 +7,9 @@

Hello, world

-

This is a page, that should be deployed using quickbase-cli to quickbase, with styling and scripts properly referenced..!

-

If this paragraph is bold, CSS files are properly referenced!

-

If this paragraph is bold, JS files are properly referenced!

-

Florian M.

- +

This is a page, that should be deployed using quickbase-cli to quickbase, with styling and scripts properly referenced.

+

If this paragraph is bold, CSS files are properly referenced.

+

If this paragraph is bold, JS files are properly referenced.

diff --git a/lib/api.js b/lib/api.js index 1ba3489..d6734ef 100644 --- a/lib/api.js +++ b/lib/api.js @@ -3,203 +3,203 @@ const URL = require('url'); class ApiClient { - - constructor(config) { - this.config = config; - this.config.password = this.config.password || process.env.QUICKBASE_CLI_PASSWORD; - this.config.username = this.config.username || process.env.QUICKBASE_CLI_USERNAME; - this.config.appToken = this.config.appToken || process.env.QUICKBASE_CLI_APPTOKEN; - this.config.userToken = this.config.userToken || process.env.QUICKBASE_CLI_USERTOKEN; - this.ticket = null - this.ticketTime = null - } - - - uploadPage(pageName, pageText) { - const xmlData = ` + + constructor(config) { + this.config = config; + this.config.password = this.config.password || process.env.QUICKBASE_CLI_PASSWORD; + this.config.username = this.config.username || process.env.QUICKBASE_CLI_USERNAME; + this.config.appToken = this.config.appToken || process.env.QUICKBASE_CLI_APPTOKEN; + this.config.userToken = this.config.userToken || process.env.QUICKBASE_CLI_USERTOKEN; + this.ticket = null + this.ticketTime = null + } + + + uploadPage(pageName, pageText) { + const xmlData = ` ${this._handleXMLChars(pageText)} 1 ${pageName} `; - return new Promise((resolve, reject) => { - this.authenticateIfNeeded().then((authType) => { - - this.sendQbRequest('API_AddReplaceDBPage', xmlData).then((response) => { - resolve(response) - }).catch((errorDesc, err) => { - reject(errorDesc, err) - }); - }).catch((errorDesc) => console.error(errorDesc)); - }); - } - - - // Private-ish - _handleXMLChars(string) { - if (!string) { - return; - } - - return string.replace(/[<>&'"]/g, char => { - switch (char) { - case '<': - return '<'; - case '>': - return '>'; - case '&': - return '&'; - case "'": - return '''; - case '"': - return '"'; - } - }); - } - - - isTicketValid() { - if (this.ticket && this.ticketTime) { - if (this.ticketTime + (3595 * parseInt(this.config.ticketExpiryHours)) > parseInt(Math.floor(Date.now() / 1000))) { - return true; - } - } - return false; - } - - - authenticateIfNeeded() { - - return new Promise((resolve, reject) => { - - //Decide here which type of authentication should be done - if (this.config.userToken) { - //Suggest to use usertoken now - resolve("userToken") - } else if (this.ticket && this.isTicketValid()) { - //Suggest to use ticket now, still valid - resolve("ticket") - } else if (this.config.username && this.config.password) { - //regenerate ticket first, then Suggest to use ticket - - const dbid = 'main'; - const action = "API_Authenticate"; - - const url = URL.parse( - `https://${this.config.realm}.quickbase.com/db/${dbid}?a=${action}` - ); - - const options = { - hostname: url.hostname, - path: url.pathname + url.search, - method: 'POST', - headers: { - 'Content-Type': 'application/xml', - 'QUICKBASE-ACTION': action - } - }; - - const authData = ` + return new Promise((resolve, reject) => { + this.authenticateIfNeeded().then((authType) => { + + this.sendQbRequest('API_AddReplaceDBPage', xmlData).then((response) => { + resolve(response) + }).catch((errorDesc, err) => { + reject(errorDesc, err) + }); + }).catch((errorDesc) => console.error(errorDesc)); + }); + } + + + // Private-ish + _handleXMLChars(string) { + if (!string) { + return; + } + + return string.replace(/[<>&'"]/g, char => { + switch (char) { + case '<': + return '<'; + case '>': + return '>'; + case '&': + return '&'; + case "'": + return '''; + case '"': + return '"'; + } + }); + } + + + isTicketValid() { + if (this.ticket && this.ticketTime) { + if (this.ticketTime + (3595 * parseInt(this.config.ticketExpiryHours)) > parseInt(Math.floor(Date.now() / 1000))) { + return true; + } + } + return false; + } + + + authenticateIfNeeded() { + + return new Promise((resolve, reject) => { + + //Decide here which type of authentication should be done + if (this.config.userToken) { + //Suggest to use usertoken now + resolve("userToken") + } else if (this.ticket && this.isTicketValid()) { + //Suggest to use ticket now, still valid + resolve("ticket") + } else if (this.config.username && this.config.password) { + //regenerate ticket first, then Suggest to use ticket + + const dbid = 'main'; + const action = "API_Authenticate"; + + const url = URL.parse( + `https://${this.config.realm}.quickbase.com/db/${dbid}?a=${action}` + ); + + const options = { + hostname: url.hostname, + path: url.pathname + url.search, + method: 'POST', + headers: { + 'Content-Type': 'application/xml', + 'QUICKBASE-ACTION': action + } + }; + + const authData = ` ${this.config.username} ${this.config.password} ${this.config.ticketExpiryHours} `; - const req = https.request(options, res => { - let response = ''; - res.setEncoding('utf8'); - res.on('data', chunk => (response += chunk)); - res.on('end', () => { - const errCode = +response.match(/(.*)<\/errcode>/)[1]; - const ticket = response.match(/(.*)<\/ticket>/)[1]; - const errtext = response.match(/(.*)<\/errtext>/)[1]; - - if (errCode != 0) { - reject(errtext); - } else { - this.ticket = ticket - this.ticketTime = parseInt(Math.floor(Date.now() / 1000)) - - //Suggest to use ticket now, just validated - resolve("ticket"); - } - }); - }); - - req.on('error', err => reject('Could not send Authentication request', err)); - req.write(authData); - req.end(); - - } else { - //Error: not enough auth credentials - reject("There are not enough authentication credentials in the config or environment. Please setup a valid username and password.") - } - }); - }; - - - sendQbRequest(action, data, mainAPICall) { - - return new Promise((resolve, reject) => { - - const dbid = mainAPICall ? 'main' : this.config.dbid; - const url = URL.parse( - `https://${this.config.realm}.quickbase.com/db/${dbid}?a=${action}` - ); - - var authData = null; - if (this.config.userToken) { - authData = `${this.config.userToken}`; - } else if (this.ticket) { - authData = `${this.ticket}`; - if (this.config.appToken) { - authData += `${this.config.appToken}`; - } - } else { - //Shouldn't happen - reject("No user token and ticket; Could not authenticate. Check if there is a valid username/password?"); - } - - if(authData) { - const postData = ` + const req = https.request(options, res => { + let response = ''; + res.setEncoding('utf8'); + res.on('data', chunk => (response += chunk)); + res.on('end', () => { + const errCode = +response.match(/(.*)<\/errcode>/)[1]; + const ticket = response.match(/(.*)<\/ticket>/)[1]; + const errtext = response.match(/(.*)<\/errtext>/)[1]; + + if (errCode != 0) { + reject(errtext); + } else { + this.ticket = ticket + this.ticketTime = parseInt(Math.floor(Date.now() / 1000)) + + //Suggest to use ticket now, just validated + resolve("ticket"); + } + }); + }); + + req.on('error', err => reject('Could not send Authentication request', err)); + req.write(authData); + req.end(); + + } else { + //Error: not enough auth credentials + reject("There are not enough authentication credentials in the config or environment. Please setup a valid username and password.") + } + }); + }; + + + sendQbRequest(action, data, mainAPICall) { + + return new Promise((resolve, reject) => { + + const dbid = mainAPICall ? 'main' : this.config.dbid; + const url = URL.parse( + `https://${this.config.realm}.quickbase.com/db/${dbid}?a=${action}` + ); + + var authData = null; + if (this.config.userToken) { + authData = `${this.config.userToken}`; + } else if (this.ticket) { + authData = `${this.ticket}`; + if (this.config.appToken) { + authData += `${this.config.appToken}`; + } + } else { + //Shouldn't happen + reject("No user token and ticket; Could not authenticate. Check if there is a valid username/password?"); + } + + if(authData) { + const postData = ` ${authData} ${data} `; - const options = { - hostname: url.hostname, - path: url.pathname + url.search, - method: 'POST', - headers: { - 'Content-Type': 'application/xml', - 'QUICKBASE-ACTION': action - } - }; - - const req = https.request(options, res => { - let response = ''; - res.setEncoding('utf8'); - res.on('data', chunk => (response += chunk)); - res.on('end', () => { - const errCode = +response.match(/(.*)<\/errcode>/)[1]; - - if (errCode != 0) { - reject(response); - } else { - resolve(response); - } - - resolve(response); - }); - }); - - req.on('error', err => reject('ERROR:', err)); - req.write(postData); - req.end(); - } - }); - } + const options = { + hostname: url.hostname, + path: url.pathname + url.search, + method: 'POST', + headers: { + 'Content-Type': 'application/xml', + 'QUICKBASE-ACTION': action + } + }; + + const req = https.request(options, res => { + let response = ''; + res.setEncoding('utf8'); + res.on('data', chunk => (response += chunk)); + res.on('end', () => { + const errCode = +response.match(/(.*)<\/errcode>/)[1]; + + if (errCode != 0) { + reject(response); + } else { + resolve(response); + } + + resolve(response); + }); + }); + + req.on('error', err => reject('ERROR:', err)); + req.write(postData); + req.end(); + } + }); + } }