From 5f23b7f7ff4d835ac4fa320531fee0f67ca46506 Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Thu, 1 Dec 2016 10:48:49 -0800 Subject: [PATCH] Removed stupid _schema shit --- app/common/__tests__/database.test.js | 2 +- app/common/database.js | 10 +- app/common/import.js | 1 - app/common/querystring.js | 2 +- app/main.development.js | 532 +++++++++++++++++++++++++- app/main/index.js | 531 ------------------------- app/models/__tests__/request.test.js | 58 ++- app/models/index.js | 1 - app/models/request.js | 14 +- app/ui/components/base/Editor.js | 5 +- package.json | 4 +- 11 files changed, 591 insertions(+), 569 deletions(-) delete mode 100644 app/main/index.js diff --git a/app/common/__tests__/database.test.js b/app/common/__tests__/database.test.js index ae2762b642..18425bd6a5 100644 --- a/app/common/__tests__/database.test.js +++ b/app/common/__tests__/database.test.js @@ -99,7 +99,7 @@ describe('requestCreate()', () => { }; const r = await models.request.create(patch); - expect(Object.keys(r).length).toBe(14); + expect(Object.keys(r).length).toBe(13); expect(r._id).toMatch(/^req_[a-zA-Z0-9]{32}$/); expect(r.created).toBeGreaterThanOrEqual(now); diff --git a/app/common/database.js b/app/common/database.js index 5540284a21..6c4568b021 100644 --- a/app/common/database.js +++ b/app/common/database.js @@ -275,13 +275,15 @@ export function docCreate (type, patch = {}) { { type: type, modified: Date.now(), - - // This is here so that we can regenerate _id if it's - // set to null - _id: patch._id || generateId(idPrefix), } ); + // NOTE: This CAN'T be inside initModel() because initModel checks + // for _id existence to do migrations and stuff + if (!doc._id) { + doc._id = generateId(idPrefix); + } + return insert(doc); } diff --git a/app/common/import.js b/app/common/import.js index b187d85922..cbbcded3cf 100644 --- a/app/common/import.js +++ b/app/common/import.js @@ -133,7 +133,6 @@ export async function exportJSON (parentDoc = null) { // Delete the things we don't want to export delete d.type; - delete d._schema; return d; }); diff --git a/app/common/querystring.js b/app/common/querystring.js index 5c5a817681..dc8cbaf4c6 100644 --- a/app/common/querystring.js +++ b/app/common/querystring.js @@ -60,7 +60,7 @@ export function buildFromParams (parameters, strict = true) { * @param strict allow empty names and values */ export function deconstructToParams (qs, strict = true) { - if (qs === '') { + if (!qs) { return []; } diff --git a/app/main.development.js b/app/main.development.js index ce89878208..85fe3160cc 100644 --- a/app/main.development.js +++ b/app/main.development.js @@ -1 +1,531 @@ -import './main'; +import reboot from 'electron-squirrel-startup'; +if (reboot) { + process.exit(0); +} + +import raven from 'raven'; +import request from 'request'; +import path from 'path'; +import electron from 'electron'; +import * as packageJSON from './package.json'; +import LocalStorage from './common/LocalStorage'; +import installExtension, {REACT_DEVELOPER_TOOLS} from 'electron-devtools-installer'; + +// Some useful helpers +const IS_DEV = process.env.INSOMNIA_ENV === 'development'; +const IS_MAC = process.platform === 'darwin'; +const IS_WINDOWS = process.platform === 'win32'; +const IS_LINUX = !IS_MAC && !IS_WINDOWS; + +const ravenClient = new raven.Client('https://786e43ae199c4757a9ea4a48a9abd17d@sentry.io/109702', { + environment: process.env.INSOMNIA_ENV || 'production', + release: packageJSON.version, + logger: 'electron.main' +}); + +if (!IS_DEV) { + ravenClient.patchGlobal(); +} + +const {app, dialog, shell, ipcMain, autoUpdater, Menu, BrowserWindow, webContents} = electron; +const {version: appVersion, productName: appName} = packageJSON; + +const UPDATE_URLS = { + // Add `r` param to help cache bust + darwin: `https://updates.insomnia.rest/builds/check/mac?v=${appVersion}`, + linux: `https://updates.insomnia.rest/builds/check/linux?v=${appVersion}`, + win32: `https://downloads.insomnia.rest/win` +}; + +const DOWNLOAD_URL = 'http://download.insomnia.rest'; + +const localStoragePath = path.join(app.getPath('userData'), 'localStorage'); +const localStorage = new LocalStorage(localStoragePath); + +let mainWindow = null; +let hasPromptedForUpdates = false; + +// Enable this for CSS grid layout :) +app.commandLine.appendSwitch('enable-experimental-web-platform-features'); + +process.on('uncaughtException', e => { + if (IS_DEV) { + console.error(e); + } else { + ravenClient.captureError(e, {}); + } +}); + +autoUpdater.on('error', e => { + if (IS_DEV) { + console.error(e); + } else { + // Don't report autoUpdater error. They are way too noisy + } +}); + +autoUpdater.on('update-not-available', () => { + console.log('-- Update Not Available --') +}); + +autoUpdater.on('update-available', () => { + console.log('-- Update Available --'); +}); + +autoUpdater.on('update-downloaded', (e, releaseNotes, releaseName, releaseDate, updateUrl) => { + console.log(`-- Update Downloaded ${releaseName} --`); + showUpdateNotification(); +}); + +function checkForUpdates () { + if (hasPromptedForUpdates) { + // We've already prompted for updates. Don't bug the user anymore + return; + } + + if (IS_DEV) { + console.log('-- Skipping update check in Development --'); + return; + } + + if (IS_LINUX) { + try { + request.get(UPDATE_URLS.linux, null, (err, response) => { + if (err) { + ravenClient.captureError(err); + return; + } + + if (response.statusCode === 200) { + showDownloadModal(response.body); + } else { + // No update available (should be STATUS=204) + } + }); + } catch (e) { + ravenClient.captureException(e); + } + } else { + try { + autoUpdater.setFeedURL(UPDATE_URLS[process.platform]); + autoUpdater.checkForUpdates(); + } catch (e) { + // This will fail in development + } + } +} + +function showUnresponsiveModal () { + dialog.showMessageBox({ + type: 'info', + buttons: ['Cancel', 'Reload'], + defaultId: 1, + cancelId: 0, + title: 'Unresponsive', + message: 'Insomnia has become unresponsive. Do you want to reload?' + }, id => { + if (id === 1) { + mainWindow.destroy(); + createWindow(); + } + }); +} + +function showUpdateNotification () { + if (hasPromptedForUpdates) { + return; + } + + const window = BrowserWindow.getFocusedWindow(); + if (!window || !window.webContents) { + return; + } + + window.webContents.send('update-available'); + hasPromptedForUpdates = true; +} + +function trackEvent (...args) { + const window = BrowserWindow.getFocusedWindow(); + if (!window || !window.webContents) { + return; + } + + window.webContents.send('analytics-track-event', args); +} + +function showDownloadModal (version) { + hasPromptedForUpdates = true; + + dialog.showMessageBox({ + type: 'info', + buttons: ['Download', 'Later'], + defaultId: 0, + cancelId: 1, + title: 'Insomnia Update Available', + message: `Exciting news!\n\nVersion ${version} of Insomnia is now available.\n\n\n~Gregory` + }, id => { + if (id === 0) { + console.log('-- Installing Update --'); + shell.openExternal(DOWNLOAD_URL); + } else { + console.log('-- Cancel Update --'); + } + }); +} + +ipcMain.on('check-for-updates', () => { + console.log('-- Checking for Updates --'); + checkForUpdates(); +}); + +function saveBounds () { + if (!mainWindow) { + return; + } + + const fullscreen = mainWindow.isFullScreen(); + + // Only save the size if we're not in fullscreen + if (!fullscreen) { + localStorage.setItem('bounds', mainWindow.getBounds()); + localStorage.setItem('fullscreen', false); + } else { + localStorage.setItem('fullscreen', true); + } +} + +function getBounds () { + let bounds = {}; + let fullscreen = false; + try { + bounds = localStorage.getItem('bounds', {}); + fullscreen = localStorage.getItem('fullscreen', false); + } catch (e) { + // This should never happen, but if it does...! + console.error('Failed to parse window bounds', e); + } + + return {bounds, fullscreen}; +} + +function saveZoomFactor (zoomFactor) { + localStorage.setItem('zoomFactor', zoomFactor); +} + +function getZoomFactor () { + let zoomFactor = 1; + try { + zoomFactor = localStorage.getItem('zoomFactor', 1); + } catch (e) { + // This should never happen, but if it does...! + console.error('Failed to parse zoomFactor', e); + } + + return zoomFactor; +} + +// Quit when all windows are closed (except on Mac). +app.on('window-all-closed', () => { + if (!IS_MAC) { + app.quit(); + } +}); + +// Mac-only, when the user clicks the doc icon +app.on('activate', (e, hasVisibleWindows) => { + // Create a new window when clicking the doc icon if there isn't one open + if (!hasVisibleWindows) { + try { + createWindow() + } catch (e) { + // This might happen if 'ready' hasn't fired yet. So we're just going + // to silence these errors. + console.log('-- App not ready to "activate" yet --'); + } + } +}); + +// When the app is first launched +app.on('ready', () => { + createWindow(); + checkForUpdates(); +}); + +function createWindow () { + const zoomFactor = getZoomFactor(); + const {bounds, fullscreen} = getBounds(); + const {x, y, width, height} = bounds; + + // Make sure we don't place the window outside of the visible space + let maxX = 0; + let maxY = 0; + for (const d of electron.screen.getAllDisplays()) { + // Set the maximum placement location to 50 pixels short of the end + maxX = Math.max(maxX, d.bounds.x + d.bounds.width - 50); + maxY = Math.max(maxY, d.bounds.y + d.bounds.height - 50); + } + const finalX = Math.min(maxX, x); + const finalY = Math.min(maxX, y); + + mainWindow = new BrowserWindow({ + // Make sure we don't initialize the window outside the bounds + x: finalX, + y: finalY, + fullscreen: fullscreen, + fullscreenable: true, + title: appName, + width: width || 1200, + height: height || 600, + minHeight: 500, + minWidth: 500, + acceptFirstMouse: true, + webPreferences: { + zoomFactor: zoomFactor + } + }); + + let _resizeTimeout = null; + mainWindow.on('resize', e => { + saveBounds(); + + clearTimeout(_resizeTimeout); + _resizeTimeout = setTimeout(() => { + trackEvent('Window', 'Resize'); + }, 1000); + }); + mainWindow.on('move', e => { + saveBounds(); + trackEvent('Window', 'Move'); + }); + mainWindow.on('unresponsive', e => { + showUnresponsiveModal(); + trackEvent('Window', 'Unresponsive'); + }); + + // and load the app.html of the app. + // TODO: Use path.join for this + mainWindow.loadURL(`file://${__dirname}/renderer.html`); + + // Emitted when the window is closed. + mainWindow.on('closed', () => { + // Dereference the window object, usually you would store windows + // in an array if your app supports multi windows, this is the time + // when you should delete the corresponding element. + mainWindow = null; + trackEvent('Window', 'Close'); + }); + + require('electron-context-menu')({}); + + var template = [ + { + label: "Application", + submenu: [ + { + label: `About ${appName}`, + role: 'about', + visible: IS_MAC + }, + { + type: "separator", + visible: IS_MAC + }, + { + label: "Preferences", + accelerator: "CmdOrCtrl+,", + click: function (menuItem, window, e) { + if (!window || !window.webContents) { + return + } + + window.webContents.send('toggle-preferences'); + trackEvent('App Menu', 'Preferences'); + } + }, + { + label: "Changelog", + click: function (menuItem, window, e) { + if (!window || !window.webContents) { + return + } + + window.webContents.send('toggle-changelog'); + trackEvent('App Menu', 'Changelog'); + } + }, + { + type: "separator", + visible: IS_MAC + }, + { + role: "hide", + visible: IS_MAC + }, + { + role: "hideothers", + visible: IS_MAC + }, + {type: "separator"}, + { + label: "Quit", + accelerator: "Command+Q", + click: function () { + app.quit(); + } + } + ] + }, + { + label: "Edit", + submenu: [{ + label: "Undo", + accelerator: "CmdOrCtrl+Z", + selector: "undo:" + }, { + label: "Redo", + accelerator: "Shift+CmdOrCtrl+Z", + selector: "redo:" + }, { + type: "separator" + }, { + label: "Cut", + accelerator: "CmdOrCtrl+X", + selector: "cut:" + }, { + label: "Copy", + accelerator: "CmdOrCtrl+C", + selector: "copy:" + }, { + label: "Paste", + accelerator: "CmdOrCtrl+V", + selector: "paste:" + }, { + label: "Select All", + accelerator: "CmdOrCtrl+A", + selector: "selectAll:" + }] + }, + { + label: "View", + submenu: [ + { + role: 'togglefullscreen' + }, + { + label: "Actual Size", + accelerator: "CmdOrCtrl+0", + click: () => { + const window = BrowserWindow.getFocusedWindow(); + if (!window || !window.webContents) { + return; + } + + const zoomFactor = 1; + window.webContents.setZoomFactor(zoomFactor); + saveZoomFactor(zoomFactor); + trackEvent('App Menu', 'Zoom Reset'); + } + }, + { + label: "Zoom In", + accelerator: IS_MAC ? "CmdOrCtrl+Plus" : "CmdOrCtrl+=", + click: () => { + const window = BrowserWindow.getFocusedWindow(); + if (!window || !window.webContents) { + return; + } + + const zoomFactor = Math.min(1.8, getZoomFactor() + 0.05); + window.webContents.setZoomFactor(zoomFactor); + + saveZoomFactor(zoomFactor); + trackEvent('App Menu', 'Zoom In'); + } + }, + { + label: "Zoom Out", + accelerator: "CmdOrCtrl+-", + click: () => { + const window = BrowserWindow.getFocusedWindow(); + if (!window || !window.webContents) { + return; + } + + const zoomFactor = Math.max(0.5, getZoomFactor() - 0.05); + window.webContents.setZoomFactor(zoomFactor); + saveZoomFactor(zoomFactor); + trackEvent('App Menu', 'Zoom Out'); + } + }, + { + label: "Toggle Sidebar", + accelerator: "CmdOrCtrl+\\", + click: () => { + const window = BrowserWindow.getFocusedWindow(); + if (!window || !window.webContents) { + return; + } + + window.webContents.send('toggle-sidebar'); + trackEvent('App Menu', 'Toggle Sidebar'); + } + } + ] + }, { + label: "Window", + role: "window", + submenu: [ + {role: 'minimize'}, + ...(IS_MAC ? [{role: 'close'}] : []) + ] + }, { + label: "Help", + role: "help", + id: "help", + submenu: [ + { + label: "Contact Support", + click: () => { + trackEvent('App Menu', 'Contact'); + shell.openExternal('mailto:support@insomnia.rest'); + } + }, + { + label: "Insomnia Help", + accelerator: "CmdOrCtrl+?", + click: (e) => { + trackEvent('App Menu', 'Help'); + shell.openExternal('http://docs.insomnia.rest'); + } + } + ] + } + ]; + + if (IS_DEV) { + installExtension(REACT_DEVELOPER_TOOLS) + .then((name) => console.log(`Added Extension: ${name}`)) + .catch((err) => console.log('An error occurred: ', err)); + + template.push({ + label: 'Developer', + position: 'before=help', + submenu: [{ + label: 'Reload', + accelerator: 'Command+R', + click: function () { + mainWindow.reload(); + } + }, { + label: 'Toggle DevTools', + accelerator: 'Alt+Command+I', + click: function () { + mainWindow.toggleDevTools(); + } + }] + }); + } + + Menu.setApplicationMenu(Menu.buildFromTemplate(template)); +} diff --git a/app/main/index.js b/app/main/index.js deleted file mode 100644 index 9331e57aaa..0000000000 --- a/app/main/index.js +++ /dev/null @@ -1,531 +0,0 @@ -import reboot from 'electron-squirrel-startup'; -if (reboot) { - process.exit(0); -} - -import raven from 'raven'; -import request from 'request'; -import path from 'path'; -import electron from 'electron'; -import * as packageJSON from '../package.json'; -import LocalStorage from '../common/LocalStorage'; -import installExtension, {REACT_DEVELOPER_TOOLS} from 'electron-devtools-installer'; - -// Some useful helpers -const IS_DEV = process.env.INSOMNIA_ENV === 'development'; -const IS_MAC = process.platform === 'darwin'; -const IS_WINDOWS = process.platform === 'win32'; -const IS_LINUX = !IS_MAC && !IS_WINDOWS; - -const ravenClient = new raven.Client('https://786e43ae199c4757a9ea4a48a9abd17d@sentry.io/109702', { - environment: process.env.INSOMNIA_ENV || 'production', - release: packageJSON.version, - logger: 'electron.main' -}); - -if (!IS_DEV) { - ravenClient.patchGlobal(); -} - -const {app, dialog, shell, ipcMain, autoUpdater, Menu, BrowserWindow, webContents} = electron; -const {version: appVersion, productName: appName} = packageJSON; - -const UPDATE_URLS = { - // Add `r` param to help cache bust - darwin: `https://updates.insomnia.rest/builds/check/mac?v=${appVersion}`, - linux: `https://updates.insomnia.rest/builds/check/linux?v=${appVersion}`, - win32: `https://downloads.insomnia.rest/win` -}; - -const DOWNLOAD_URL = 'http://download.insomnia.rest'; - -const localStoragePath = path.join(app.getPath('userData'), 'localStorage'); -const localStorage = new LocalStorage(localStoragePath); - -let mainWindow = null; -let hasPromptedForUpdates = false; - -// Enable this for CSS grid layout :) -app.commandLine.appendSwitch('enable-experimental-web-platform-features'); - -process.on('uncaughtException', e => { - if (IS_DEV) { - console.error(e); - } else { - ravenClient.captureError(e, {}); - } -}); - -autoUpdater.on('error', e => { - if (IS_DEV) { - console.error(e); - } else { - // Don't report autoUpdater error. They are way too noisy - } -}); - -autoUpdater.on('update-not-available', () => { - console.log('-- Update Not Available --') -}); - -autoUpdater.on('update-available', () => { - console.log('-- Update Available --'); -}); - -autoUpdater.on('update-downloaded', (e, releaseNotes, releaseName, releaseDate, updateUrl) => { - console.log(`-- Update Downloaded ${releaseName} --`); - showUpdateNotification(); -}); - -function checkForUpdates () { - if (hasPromptedForUpdates) { - // We've already prompted for updates. Don't bug the user anymore - return; - } - - if (IS_DEV) { - console.log('-- Skipping update check in Development --'); - return; - } - - if (IS_LINUX) { - try { - request.get(UPDATE_URLS.linux, null, (err, response) => { - if (err) { - ravenClient.captureError(err); - return; - } - - if (response.statusCode === 200) { - showDownloadModal(response.body); - } else { - // No update available (should be STATUS=204) - } - }); - } catch (e) { - ravenClient.captureException(e); - } - } else { - try { - autoUpdater.setFeedURL(UPDATE_URLS[process.platform]); - autoUpdater.checkForUpdates(); - } catch (e) { - // This will fail in development - } - } -} - -function showUnresponsiveModal () { - dialog.showMessageBox({ - type: 'info', - buttons: ['Cancel', 'Reload'], - defaultId: 1, - cancelId: 0, - title: 'Unresponsive', - message: 'Insomnia has become unresponsive. Do you want to reload?' - }, id => { - if (id === 1) { - mainWindow.destroy(); - createWindow(); - } - }); -} - -function showUpdateNotification () { - if (hasPromptedForUpdates) { - return; - } - - const window = BrowserWindow.getFocusedWindow(); - if (!window || !window.webContents) { - return; - } - - window.webContents.send('update-available'); - hasPromptedForUpdates = true; -} - -function trackEvent (...args) { - const window = BrowserWindow.getFocusedWindow(); - if (!window || !window.webContents) { - return; - } - - window.webContents.send('analytics-track-event', args); -} - -function showDownloadModal (version) { - hasPromptedForUpdates = true; - - dialog.showMessageBox({ - type: 'info', - buttons: ['Download', 'Later'], - defaultId: 0, - cancelId: 1, - title: 'Insomnia Update Available', - message: `Exciting news!\n\nVersion ${version} of Insomnia is now available.\n\n\n~Gregory` - }, id => { - if (id === 0) { - console.log('-- Installing Update --'); - shell.openExternal(DOWNLOAD_URL); - } else { - console.log('-- Cancel Update --'); - } - }); -} - -ipcMain.on('check-for-updates', () => { - console.log('-- Checking for Updates --'); - checkForUpdates(); -}); - -function saveBounds () { - if (!mainWindow) { - return; - } - - const fullscreen = mainWindow.isFullScreen(); - - // Only save the size if we're not in fullscreen - if (!fullscreen) { - localStorage.setItem('bounds', mainWindow.getBounds()); - localStorage.setItem('fullscreen', false); - } else { - localStorage.setItem('fullscreen', true); - } -} - -function getBounds () { - let bounds = {}; - let fullscreen = false; - try { - bounds = localStorage.getItem('bounds', {}); - fullscreen = localStorage.getItem('fullscreen', false); - } catch (e) { - // This should never happen, but if it does...! - console.error('Failed to parse window bounds', e); - } - - return {bounds, fullscreen}; -} - -function saveZoomFactor (zoomFactor) { - localStorage.setItem('zoomFactor', zoomFactor); -} - -function getZoomFactor () { - let zoomFactor = 1; - try { - zoomFactor = localStorage.getItem('zoomFactor', 1); - } catch (e) { - // This should never happen, but if it does...! - console.error('Failed to parse zoomFactor', e); - } - - return zoomFactor; -} - -// Quit when all windows are closed (except on Mac). -app.on('window-all-closed', () => { - if (!IS_MAC) { - app.quit(); - } -}); - -// Mac-only, when the user clicks the doc icon -app.on('activate', (e, hasVisibleWindows) => { - // Create a new window when clicking the doc icon if there isn't one open - if (!hasVisibleWindows) { - try { - createWindow() - } catch (e) { - // This might happen if 'ready' hasn't fired yet. So we're just going - // to silence these errors. - console.log('-- App not ready to "activate" yet --'); - } - } -}); - -// When the app is first launched -app.on('ready', () => { - createWindow(); - checkForUpdates(); -}); - -function createWindow () { - const zoomFactor = getZoomFactor(); - const {bounds, fullscreen} = getBounds(); - const {x, y, width, height} = bounds; - - // Make sure we don't place the window outside of the visible space - let maxX = 0; - let maxY = 0; - for (const d of electron.screen.getAllDisplays()) { - // Set the maximum placement location to 50 pixels short of the end - maxX = Math.max(maxX, d.bounds.x + d.bounds.width - 50); - maxY = Math.max(maxY, d.bounds.y + d.bounds.height - 50); - } - const finalX = Math.min(maxX, x); - const finalY = Math.min(maxX, y); - - mainWindow = new BrowserWindow({ - // Make sure we don't initialize the window outside the bounds - x: finalX, - y: finalY, - fullscreen: fullscreen, - fullscreenable: true, - title: appName, - width: width || 1200, - height: height || 600, - minHeight: 500, - minWidth: 500, - acceptFirstMouse: true, - webPreferences: { - zoomFactor: zoomFactor - } - }); - - let _resizeTimeout = null; - mainWindow.on('resize', e => { - saveBounds(); - - clearTimeout(_resizeTimeout); - _resizeTimeout = setTimeout(() => { - trackEvent('Window', 'Resize'); - }, 1000); - }); - mainWindow.on('move', e => { - saveBounds(); - trackEvent('Window', 'Move'); - }); - mainWindow.on('unresponsive', e => { - showUnresponsiveModal(); - trackEvent('Window', 'Unresponsive'); - }); - - // and load the app.html of the app. - // TODO: Use path.join for this - mainWindow.loadURL(`file://${__dirname}/../renderer.html`); - - // Emitted when the window is closed. - mainWindow.on('closed', () => { - // Dereference the window object, usually you would store windows - // in an array if your app supports multi windows, this is the time - // when you should delete the corresponding element. - mainWindow = null; - trackEvent('Window', 'Close'); - }); - - require('electron-context-menu')({}); - - var template = [ - { - label: "Application", - submenu: [ - { - label: `About ${appName}`, - role: 'about', - visible: IS_MAC - }, - { - type: "separator", - visible: IS_MAC - }, - { - label: "Preferences", - accelerator: "CmdOrCtrl+,", - click: function (menuItem, window, e) { - if (!window || !window.webContents) { - return - } - - window.webContents.send('toggle-preferences'); - trackEvent('App Menu', 'Preferences'); - } - }, - { - label: "Changelog", - click: function (menuItem, window, e) { - if (!window || !window.webContents) { - return - } - - window.webContents.send('toggle-changelog'); - trackEvent('App Menu', 'Changelog'); - } - }, - { - type: "separator", - visible: IS_MAC - }, - { - role: "hide", - visible: IS_MAC - }, - { - role: "hideothers", - visible: IS_MAC - }, - {type: "separator"}, - { - label: "Quit", - accelerator: "Command+Q", - click: function () { - app.quit(); - } - } - ] - }, - { - label: "Edit", - submenu: [{ - label: "Undo", - accelerator: "CmdOrCtrl+Z", - selector: "undo:" - }, { - label: "Redo", - accelerator: "Shift+CmdOrCtrl+Z", - selector: "redo:" - }, { - type: "separator" - }, { - label: "Cut", - accelerator: "CmdOrCtrl+X", - selector: "cut:" - }, { - label: "Copy", - accelerator: "CmdOrCtrl+C", - selector: "copy:" - }, { - label: "Paste", - accelerator: "CmdOrCtrl+V", - selector: "paste:" - }, { - label: "Select All", - accelerator: "CmdOrCtrl+A", - selector: "selectAll:" - }] - }, - { - label: "View", - submenu: [ - { - role: 'togglefullscreen' - }, - { - label: "Actual Size", - accelerator: "CmdOrCtrl+0", - click: () => { - const window = BrowserWindow.getFocusedWindow(); - if (!window || !window.webContents) { - return; - } - - const zoomFactor = 1; - window.webContents.setZoomFactor(zoomFactor); - saveZoomFactor(zoomFactor); - trackEvent('App Menu', 'Zoom Reset'); - } - }, - { - label: "Zoom In", - accelerator: IS_MAC ? "CmdOrCtrl+Plus" : "CmdOrCtrl+=", - click: () => { - const window = BrowserWindow.getFocusedWindow(); - if (!window || !window.webContents) { - return; - } - - const zoomFactor = Math.min(1.8, getZoomFactor() + 0.05); - window.webContents.setZoomFactor(zoomFactor); - - saveZoomFactor(zoomFactor); - trackEvent('App Menu', 'Zoom In'); - } - }, - { - label: "Zoom Out", - accelerator: "CmdOrCtrl+-", - click: () => { - const window = BrowserWindow.getFocusedWindow(); - if (!window || !window.webContents) { - return; - } - - const zoomFactor = Math.max(0.5, getZoomFactor() - 0.05); - window.webContents.setZoomFactor(zoomFactor); - saveZoomFactor(zoomFactor); - trackEvent('App Menu', 'Zoom Out'); - } - }, - { - label: "Toggle Sidebar", - accelerator: "CmdOrCtrl+\\", - click: () => { - const window = BrowserWindow.getFocusedWindow(); - if (!window || !window.webContents) { - return; - } - - window.webContents.send('toggle-sidebar'); - trackEvent('App Menu', 'Toggle Sidebar'); - } - } - ] - }, { - label: "Window", - role: "window", - submenu: [ - {role: 'minimize'}, - ...(IS_MAC ? [{role: 'close'}] : []) - ] - }, { - label: "Help", - role: "help", - id: "help", - submenu: [ - { - label: "Contact Support", - click: () => { - trackEvent('App Menu', 'Contact'); - shell.openExternal('mailto:support@insomnia.rest'); - } - }, - { - label: "Insomnia Help", - accelerator: "CmdOrCtrl+?", - click: (e) => { - trackEvent('App Menu', 'Help'); - shell.openExternal('http://docs.insomnia.rest'); - } - } - ] - } - ]; - - if (IS_DEV) { - installExtension(REACT_DEVELOPER_TOOLS) - .then((name) => console.log(`Added Extension: ${name}`)) - .catch((err) => console.log('An error occurred: ', err)); - - template.push({ - label: 'Developer', - position: 'before=help', - submenu: [{ - label: 'Reload', - accelerator: 'Command+R', - click: function () { - mainWindow.reload(); - } - }, { - label: 'Toggle DevTools', - accelerator: 'Alt+Command+I', - click: function () { - mainWindow.toggleDevTools(); - } - }] - }); - } - - Menu.setApplicationMenu(Menu.buildFromTemplate(template)); -} diff --git a/app/models/__tests__/request.test.js b/app/models/__tests__/request.test.js index 95cf21ab6b..a6b6266f1c 100644 --- a/app/models/__tests__/request.test.js +++ b/app/models/__tests__/request.test.js @@ -1,6 +1,8 @@ import * as db from '../../common/database'; import * as requestModel from '../../models/request'; import {types as allModelTypes} from '../../models'; +import {initModel} from '../index'; +import * as models from '../index'; describe('init()', () => { beforeEach(() => { @@ -10,7 +12,6 @@ describe('init()', () => { it('contains all required fields', async () => { Date.now = jest.genMockFunction().mockReturnValue(1478795580200); expect(requestModel.init()).toEqual({ - _schema: 1, authentication: {}, body: {}, headers: [], @@ -34,7 +35,6 @@ describe('create()', async () => { const request = await requestModel.create({name: 'Test Request', parentId: 'fld_124'}); const expected = { _id: 'req_dd2ccc1a2745477a881a9e8ef9d42403', - _schema: 1, created: 1478795580200, modified: 1478795580200, parentId: 'fld_124', @@ -127,7 +127,6 @@ describe('migrate()', () => { }; const expected = { - _schema: 1, headers: [], body: {mimeType: "", text: 'hello world!'} }; @@ -142,7 +141,6 @@ describe('migrate()', () => { }; const expected = { - _schema: 1, headers: [{name: 'content-type', value: 'application/x-www-form-urlencoded'}], body: { mimeType: 'application/x-www-form-urlencoded', @@ -163,7 +161,6 @@ describe('migrate()', () => { }; const expected = { - _schema: 1, headers: [{name: 'content-type', value: 'application/x-www-form-urlencoded; charset=utf-8'}], body: { mimeType: 'application/x-www-form-urlencoded', @@ -184,7 +181,6 @@ describe('migrate()', () => { }; const expected = { - _schema: 1, headers: [{name: 'content-type', value: 'application/x-www-form-urlencoded'}], body: { mimeType: 'application/x-www-form-urlencoded', @@ -211,7 +207,6 @@ describe('migrate()', () => { }; const expected = { - _schema: 1, headers: [{name: 'content-type', value: contentType}], body: {mimeType: contentToMimeMap[contentType], text: ''} }; @@ -222,29 +217,60 @@ describe('migrate()', () => { it('skips migrate for schema 1', () => { const original = { - _schema: 1, body: {mimeType: 'text/plain', text: 'foo'} }; expect(requestModel.migrate(original)).toBe(original); }); - it('migrates with no schema and schema < 1', () => { - const withoutSchema = {body: 'foo bar!'}; - const withSchema = {_schema: 0, body: 'foo bar!'}; - const withWeirdSchema = {_schema: -4, body: 'foo bar!'}; + it('migrates with weird data', () => { + const newBody = {body: {mimeType: '', text: 'foo bar!'}}; + const stringBody = {body: 'foo bar!'}; + const nullBody = {body: null}; + const noBody = {}; const expected = { - _schema: 1, body: { mimeType: "", text: 'foo bar!' } }; - expect(requestModel.migrate(withSchema)).toEqual(expected); - expect(requestModel.migrate(withoutSchema)).toEqual(expected); - expect(requestModel.migrate(withWeirdSchema)).toEqual(expected); + const expected2 = { + body: {} + }; + + expect(requestModel.migrate(newBody)).toEqual(expected); + expect(requestModel.migrate(stringBody)).toEqual(expected); + expect(requestModel.migrate(nullBody)).toEqual(expected2); + expect(requestModel.migrate(noBody)).toEqual(expected2); + }); + + it('migrates from initModel()', () => { + const original = { + _id: 'req_123', + headers: [], + body: 'hello world!' + }; + + const expected = { + _id: 'req_123', + type: 'Request', + url: '', + created: 1478795580200, + modified: 1478795580200, + metaSortKey: -1478795580200, + name: 'New Request', + method: 'GET', + headers: [], + authentication: {}, + parameters: [], + parentId: null, + body: {mimeType: '', text: 'hello world!'} + }; + + const migrated = initModel(models.request.type, original); + expect(migrated).toEqual(expected); }); }); diff --git a/app/models/index.js b/app/models/index.js index 4b4f1caef0..b637870fb4 100644 --- a/app/models/index.js +++ b/app/models/index.js @@ -70,7 +70,6 @@ export function initModel (type, ...sources) { const objectDefaults = Object.assign({ type: type, _id: null, - _schema: 0, parentId: null, modified: Date.now(), created: Date.now(), diff --git a/app/models/request.js b/app/models/request.js index 356b0322cf..ffa54c3975 100644 --- a/app/models/request.js +++ b/app/models/request.js @@ -9,7 +9,6 @@ export const prefix = 'req'; export function init () { return { - _schema: 1, url: '', name: 'New Request', method: METHOD_GET, @@ -57,13 +56,7 @@ export function newBodyForm (parameters) { } export function migrate (doc) { - const schema = doc._schema || 0; - - if (schema <= 0) { - doc = migrateTo1(doc); - doc._schema = 1; - } - + doc = migrateTo1(doc); return doc; } @@ -143,6 +136,9 @@ export function all () { // ~~~~~~~~~~ // function migrateTo1 (request) { + if (request.body && typeof request.body === 'object') { + return request; + } // Second, convert all existing urlencoded bodies to new format const contentType = getContentTypeFromHeaders(request.headers) || ''; @@ -152,6 +148,8 @@ function migrateTo1 (request) { // Convert old-style form-encoded request bodies to new style const params = deconstructToParams(request.body, false); request.body = newBodyFormUrlEncoded(params); + } else if (!request.body && !contentType) { + request.body = {}; } else { request.body = newBodyRaw(request.body, contentType); } diff --git a/app/ui/components/base/Editor.js b/app/ui/components/base/Editor.js index 8f45b8d8ff..647b7ef562 100644 --- a/app/ui/components/base/Editor.js +++ b/app/ui/components/base/Editor.js @@ -250,8 +250,7 @@ class Editor extends Component { return; } - var newValue = doc.getValue(); - this.props.onChange(newValue); + this.props.onChange(doc.getValue()); } /** @@ -265,7 +264,7 @@ class Editor extends Component { if (this.props.autoPrettify && this._canPrettify()) { this._prettify(code); } else { - this.codeMirror.setValue(code); + this.codeMirror.setValue(code || ''); } } diff --git a/package.json b/package.json index 752fbe77b0..085b2fc2cb 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "private": true, "version": "1.0.0", "description": "Insomnia App", - "main": "electron.js", + "main": "main.js", "licence": "GNU AGPLv3", "homepage": "http://insomnia.rest", "repository": { @@ -77,7 +77,7 @@ }, "win": { "iconUrl": "https://insomnia.rest/images/icon.png", - "__remoteReleases": "https://s3.amazonaws.com/downloads.insomnia.rest/win", + "remoteReleases": "https://s3.amazonaws.com/downloads.insomnia.rest/win", "target": "squirrel", "msi": false },