-
Notifications
You must be signed in to change notification settings - Fork 3
Changes pre-ET #48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes pre-ET #48
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -763,7 +763,22 @@ const isConfigFlagEnabled = flag => { | |
| return config[flag] || false; | ||
| }; | ||
|
|
||
|
|
||
| const getAuthType = accountId => { | ||
| let authType = 'unknown'; | ||
|
|
||
| if (accountId) { | ||
| const accountConfig = getAccountConfig(accountId); | ||
| if (accountConfig && accountConfig.authType) { | ||
| authType = accountConfig.authType; | ||
| } | ||
| } | ||
|
|
||
| return authType; | ||
| }; | ||
|
|
||
| module.exports = { | ||
| getAuthType, | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moving this to config to be useable elsewhere |
||
| getAndLoadConfigIfNeeded, | ||
| getEnv, | ||
| getConfig, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,7 +23,7 @@ const { | |
| isUngatedForPreview, | ||
| } = require('./preview/previewUtils'); | ||
| const { markRemoteFsDirty } = require('./preview/routes/meta'); | ||
| const { startShadowDevServer } = require('./preview/shadowDevServer'); | ||
| const { startSprocketMenuServer } = require('./preview/sprocketMenuServer'); | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| const { | ||
| createHttpsRedirectingServer, | ||
| } = require('./preview/httpsRedirectingServer'); | ||
|
|
@@ -108,7 +108,7 @@ const buildDeleteFileFromPreviewBufferCallback = (sessionInfo, type) => { | |
| }; | ||
|
|
||
| const buildUploadFileToPreviewBufferCallback = (sessionInfo, notifyMessage) => { | ||
| const { portalId, src, dest, notify } = sessionInfo; | ||
| const { accountId, src, dest, notify } = sessionInfo; | ||
|
|
||
| return async filePath => { | ||
| if (!isAllowedExtension(filePath)) { | ||
|
|
@@ -120,15 +120,17 @@ const buildUploadFileToPreviewBufferCallback = (sessionInfo, notifyMessage) => { | |
| return; | ||
| } | ||
| const destPath = getDesignManagerPath(src, dest, filePath); | ||
| const uploadPromise = uploadFile(portalId, filePath, destPath); | ||
| const uploadPromise = uploadFile(accountId, filePath, destPath); | ||
| triggerNotify(notify, notifyMessage, filePath, uploadPromise); | ||
| }; | ||
| }; | ||
|
|
||
| const initialPreviewBufferUpload = async (sessionInfo, filePaths) => { | ||
| const { portalId, src, dest } = sessionInfo; | ||
| const initialPreviewBufferUpload = async (sessionInfo, filePaths, uploadOptions) => { | ||
| const { accountId, src, dest } = sessionInfo; | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated the initial upload to be less spammy and only draw attention if there's actually a problem - instead display a progress bar & print out any errors at the end Screen.Recording.2024-02-07.at.3.17.21.PM.mov
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I generally like this pattern better, because it is cleaner in the terminal -- but I'm not sure if there is discussion to be had about this pattern being globalized as the standard 'upload' pattern for the CLI cc @brandenrodgers - we have the cli guidelines being formed right now and I saw on the doc that the component library was slotted to include progress indicators - We are somewhat straying from what is the current pattern for uploading here for the moment, do you have any concerns about that for the interim? I'm assuming that once the guidelines are established, we can circle back and match the decided upon pattern. |
||
| const { onFinishCallback, ...rest } = uploadOptions; | ||
|
|
||
| return uploadFolder(portalId, src, dest, fileMapperArgs, {}, filePaths); | ||
| const results = await uploadFolder(accountId, src, dest, fileMapperArgs, rest, filePaths); | ||
| onFinishCallback(results); | ||
| }; | ||
|
|
||
| const startPreviewWatcher = async sessionInfo => { | ||
|
|
@@ -158,11 +160,14 @@ const startPreviewWatcher = async sessionInfo => { | |
| ); | ||
|
|
||
| watcher.on('ready', () => { | ||
| console.log('Local file watching service has started!'); | ||
| watcherIsReady = true; | ||
| }); | ||
| watcher.on('add', addFileCallback); | ||
| watcher.on('change', changeFileCallback); | ||
| watcher.on('error', error => | ||
| logger.error(`An error occurred while watching files: ${error}`) | ||
| ); | ||
|
|
||
| watcher.on('unlink', deleteFileCallback); | ||
| watcher.on('unlinkDir', deleteFolderCallback); | ||
|
|
||
|
|
@@ -180,7 +185,6 @@ const startPreviewWatcher = async sessionInfo => { | |
|
|
||
| const createLocalHttpServer = async sessionInfo => { | ||
| const expressServer = express(); | ||
| //expressServer.use(bodyParser.json()); | ||
| expressServer.use('/', await createPreviewServerRoutes(sessionInfo)); | ||
|
|
||
| return expressServer; | ||
|
|
@@ -190,19 +194,20 @@ const preview = async ( | |
| accountId, | ||
| src, | ||
| dest, | ||
| { notify, filePaths, skipUpload, noSsl, port } | ||
| { notify, filePaths, skipUpload, noSsl, port, uploadOptions } | ||
| ) => { | ||
| const accountConfig = getAccountConfig(accountId); | ||
| const domains = await getPortalDomains(accountId); | ||
| const sessionToken = '96cd331a-189d-41f2-8a4c-a12485402eff'; | ||
| const sessionToken = uuidv4(); | ||
| const PORT = port || 3000; | ||
| const protocol = noSsl ? 'http' : 'https'; | ||
|
|
||
| const sessionInfo = { | ||
| src, | ||
| dest: `@preview/${sessionToken}/${dest}`, | ||
| fakeDest: dest, | ||
| portalName: accountConfig.name, | ||
| portalId: accountId, | ||
| accountId, | ||
| env: accountConfig.env, | ||
| personalAccessKey: accountConfig.personalAccessKey, | ||
| // we find hublet later in the content metadata fetch | ||
|
|
@@ -215,7 +220,7 @@ const preview = async ( | |
| }; | ||
| const ungated = await isUngatedForPreview(sessionInfo); | ||
| if (!ungated) { | ||
| console.log( | ||
| logger.log( | ||
| `Portal ${accountId} is missing a required gate for this feature.` | ||
| ); | ||
| process.exit(); | ||
|
|
@@ -225,7 +230,7 @@ const preview = async ( | |
| } | ||
|
|
||
| if (!skipUpload) { | ||
| await initialPreviewBufferUpload(sessionInfo, filePaths); | ||
| await initialPreviewBufferUpload(sessionInfo, filePaths, uploadOptions); | ||
| } | ||
| const expressServer = await createLocalHttpServer(sessionInfo); | ||
| const previewWatcher = await startPreviewWatcher(sessionInfo); | ||
|
|
@@ -241,9 +246,9 @@ const preview = async ( | |
| const httpServer = http.createServer(expressServer); | ||
| httpServer.listen(PORT); | ||
| } | ||
| startShadowDevServer(sessionInfo); | ||
| console.log( | ||
| `HubSpot preview local dev server hosting at ${protocol}://hslocal.net:${PORT}, portalId=${accountId}` | ||
| startSprocketMenuServer(sessionInfo); | ||
| logger.log( | ||
| `Local dev server started at ${protocol}://hslocal.net:${PORT} for portal ${accountId}` | ||
| ); | ||
| }; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| const http = require('http'); | ||
| const https = require('https'); | ||
| const net = require('net'); | ||
| const os = require('os') | ||
| const { unlinkSync } = require('fs'); | ||
| const { silenceConsoleWhile } = require('./previewUtils'); | ||
|
|
||
|
|
@@ -14,11 +15,11 @@ const createCert = async (domainsToProxy) => { | |
| const hosts = ['localhost', 'hslocal.net', ...additionalMkcertHosts]; | ||
| const { createCertificate } = await import('mkcert-cli'); | ||
| const { key, cert } = await silenceConsoleWhile(createCertificate, { | ||
| keyFilePath: `${__dirname}/key.pem`, | ||
| certFilePath: `${__dirname}/cert.pem` | ||
| keyFilePath: `${os.tmpdir()}/hstmp/hsLocalSshKey.pem`, | ||
| certFilePath: `${os.tmpdir()}/hstmp/hsLocalSshCert.pem` | ||
| }, hosts); | ||
| unlinkSync(`${__dirname}/key.pem`); | ||
| unlinkSync(`${__dirname}/cert.pem`); | ||
| unlinkSync(`${os.tmpdir()}/hstmp/hsLocalSshKey.pem`); | ||
| unlinkSync(`${os.tmpdir()}/hstmp/hsLocalSshCert.pem`); | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Put these in the os temp dir feels a little cleaner pattern for the millisecond they exist before they get deleted. Should be cross platform but I'll make sure |
||
| return { key, cert }; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,34 +2,29 @@ const { fetchDomains } = require('../../api/domains'); | |
| const { getAccountId, isTrackingAllowed, getAccountConfig } = require('../config'); | ||
| const { platform, release } = require('os'); | ||
| const { trackUsage } = require('../../api/fileMapper'); | ||
| const unAuth = require('../../api/localDevAuth/unauthenticated'); | ||
|
|
||
| const { enabledFeaturesForPersonalAccessKey } = require('../../personalAccessKey'); | ||
| const { stringify } = require('querystring'); | ||
|
TanyaScales marked this conversation as resolved.
|
||
| const { logger } = require('./../../logger'); | ||
| const { getAuthType } = require('./../../lib/config'); | ||
| const VALID_PROXY_DOMAIN_SUFFIXES = ['localhost', 'hslocal.net']; | ||
|
|
||
| const HS_PREVIEW_GATE = "cms:localHublPreviews"; | ||
|
|
||
| const getPortalDomains = async (portalId) => { | ||
| const getPortalDomains = async (accountId) => { | ||
| try { | ||
| const result = await fetchDomains(portalId); | ||
| const result = await fetchDomains(accountId); | ||
| return result; | ||
| } catch (error) { | ||
| console.log("There was a problem fetching domains for your portal. You may be missing a scope necessary for this feature.") | ||
| return []; | ||
| } | ||
| } | ||
|
|
||
| const getPreviewUrl = (sessionInfo, queryParams) => { | ||
| const { portalId, env, hublet } = sessionInfo; | ||
| const { accountId, env, hublet } = sessionInfo; | ||
|
|
||
| return `http://${portalId}.hubspotpreview${ | ||
| return `http://${accountId}.hubspotpreview${ | ||
| env === 'qa' ? 'qa' : '' | ||
| }-${hublet}.com/_hcms/preview/template/multi?${stringifyQuery(queryParams)}`; | ||
| } | ||
|
|
||
| const stringifyQuery = (query) => { | ||
| return Object.keys(query) | ||
| .sort() | ||
| .map(key => `${key}=${query[key]}`) | ||
| .join('&'); | ||
| }-${hublet}.com/_hcms/preview/template/multi?${stringify(queryParams)}`; | ||
| } | ||
|
|
||
| const insertAtEndOfBody = (html, script) => { | ||
|
|
@@ -44,6 +39,7 @@ const addRefreshScript = (html) => { | |
| const refreshScript = ` | ||
| <script> | ||
| (() => { | ||
| const MAX_WAIT = 16000; | ||
| const NORMAL_WAIT_MS = 1000; | ||
| const BACKOFF_RATIO = 2; | ||
| let nextWait = NORMAL_WAIT_MS; | ||
|
|
@@ -62,7 +58,9 @@ const addRefreshScript = (html) => { | |
| nextWait = NORMAL_WAIT_MS; | ||
| }) | ||
| .catch(err => { | ||
| nextWait *= BACKOFF_RATIO; | ||
| if (nextWait * BACKOFF_RATIO <= MAX_WAIT) { | ||
| nextWait *= BACKOFF_RATIO; | ||
| } | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Figured I'd cap this while I'm in here and close an open issue |
||
| console.log('Disconnected from local server... (retrying in ' + nextWait / 1000 + 's)'); | ||
| }); | ||
| }, NORMAL_WAIT_MS); | ||
|
|
@@ -78,10 +76,8 @@ const getSubDomainFromValidLocalDomain = hostname => { | |
| return hostname.slice(0, -1 * validProxyDomainSuffix.length - 1); | ||
| } | ||
| } | ||
| return undefined; | ||
| }; | ||
|
|
||
| // From(ish) https://git.hubteam.com/HubSpot/cloudflare-workers/blob/master/worker-lib/src/Constants.ts | ||
| const internalRoutes = { | ||
| HCMS: '/_hcms/', | ||
| HS_FS: '/hs-fs/', | ||
|
|
@@ -93,7 +89,7 @@ const isInternalCMSRoute = (req) => | |
|
|
||
| const silenceConsoleWhile = async (act, ...args) => { | ||
| const tmpConsole = console; | ||
| console = { log: () => {} } | ||
| console = { log: () => {} } // ! | ||
| const result = await act(...args); | ||
| console = tmpConsole; | ||
| return result; | ||
|
|
@@ -135,38 +131,30 @@ const trackPreviewEvent = async (action) => { | |
| accountId | ||
| ).catch( | ||
| (err) => { | ||
| console.error(`trackUsage failed: ${JSON.stringify(err, null, 2)}`); | ||
| logger.debug(`trackUsage failed: ${JSON.stringify(err, null, 2)}`); | ||
| } | ||
| ); | ||
| } | ||
|
|
||
| const getAuthType = (accountId) => { | ||
| let authType = 'unknown'; | ||
|
|
||
| if (accountId) { | ||
| const accountConfig = getAccountConfig(accountId); | ||
| authType = | ||
| accountConfig && accountConfig.authType | ||
| ? accountConfig.authType | ||
| : 'apikey'; | ||
| } | ||
|
|
||
| return authType; | ||
| }; | ||
|
|
||
| const isUngatedForPreview = async (sessionInfo) => { | ||
| const { portalId, env, personalAccessKey } = sessionInfo; | ||
| const { accountId } = sessionInfo; | ||
|
|
||
| const { enabledFeatures = {} } = await unAuth.fetchAccessToken( | ||
| personalAccessKey, | ||
| env, | ||
| portalId | ||
| ); | ||
| const enabledFeatures = await enabledFeaturesForPersonalAccessKey(accountId); | ||
|
|
||
| return (Object.keys(enabledFeatures).includes(HS_PREVIEW_GATE) | ||
| && enabledFeatures[HS_PREVIEW_GATE] === true) | ||
| } | ||
|
|
||
| const buildHTMLResponse = (content) => { | ||
| return ` | ||
| <!DOCTYPE html> | ||
| <head> | ||
| </head> | ||
| <body> | ||
| ${content} | ||
| </body> | ||
| `; | ||
| } | ||
|
|
||
| module.exports = { | ||
| isInternalCMSRoute, | ||
|
|
@@ -180,4 +168,5 @@ module.exports = { | |
| hidePreviewInDest, | ||
| trackPreviewEvent, | ||
| isUngatedForPreview, | ||
| buildHTMLResponse, | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we just throw here we can remove the catch and rethrow